diff options
Diffstat (limited to 'drivers/net')
217 files changed, 13680 insertions, 7172 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 18ff622703be..6460505ab24c 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -2354,20 +2354,6 @@ config GELIC_WIRELESS | |||
2354 | the driver automatically distinguishes the models, you can | 2354 | the driver automatically distinguishes the models, you can |
2355 | safely enable this option even if you have a wireless-less model. | 2355 | safely enable this option even if you have a wireless-less model. |
2356 | 2356 | ||
2357 | config GELIC_WIRELESS_OLD_PSK_INTERFACE | ||
2358 | bool "PS3 Wireless private PSK interface (OBSOLETE)" | ||
2359 | depends on GELIC_WIRELESS | ||
2360 | select WEXT_PRIV | ||
2361 | help | ||
2362 | This option retains the obsolete private interface to pass | ||
2363 | the PSK from user space programs to the driver. The PSK | ||
2364 | stands for 'Pre Shared Key' and is used for WPA[2]-PSK | ||
2365 | (WPA-Personal) environment. | ||
2366 | If WPA[2]-PSK is used and you need to use old programs that | ||
2367 | support only this old interface, say Y. Otherwise N. | ||
2368 | |||
2369 | If unsure, say N. | ||
2370 | |||
2371 | config FSL_PQ_MDIO | 2357 | config FSL_PQ_MDIO |
2372 | tristate "Freescale PQ MDIO" | 2358 | tristate "Freescale PQ MDIO" |
2373 | depends on FSL_SOC | 2359 | 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/Kconfig b/drivers/net/wireless/Kconfig index 56dd6650c97a..588943660755 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
@@ -112,6 +112,7 @@ config AIRO_CS | |||
112 | depends on PCMCIA && (BROKEN || !M32R) | 112 | depends on PCMCIA && (BROKEN || !M32R) |
113 | select WIRELESS_EXT | 113 | select WIRELESS_EXT |
114 | select WEXT_SPY | 114 | select WEXT_SPY |
115 | select WEXT_PRIV | ||
115 | select CRYPTO | 116 | select CRYPTO |
116 | select CRYPTO_AES | 117 | select CRYPTO_AES |
117 | ---help--- | 118 | ---help--- |
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 39410016b4ff..6508515feed3 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c | |||
@@ -302,18 +302,6 @@ static int adm8211_get_stats(struct ieee80211_hw *dev, | |||
302 | return 0; | 302 | return 0; |
303 | } | 303 | } |
304 | 304 | ||
305 | static int adm8211_get_tx_stats(struct ieee80211_hw *dev, | ||
306 | struct ieee80211_tx_queue_stats *stats) | ||
307 | { | ||
308 | struct adm8211_priv *priv = dev->priv; | ||
309 | |||
310 | stats[0].len = priv->cur_tx - priv->dirty_tx; | ||
311 | stats[0].limit = priv->tx_ring_size - 2; | ||
312 | stats[0].count = priv->dirty_tx; | ||
313 | |||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static void adm8211_interrupt_tci(struct ieee80211_hw *dev) | 305 | static void adm8211_interrupt_tci(struct ieee80211_hw *dev) |
318 | { | 306 | { |
319 | struct adm8211_priv *priv = dev->priv; | 307 | struct adm8211_priv *priv = dev->priv; |
@@ -1400,15 +1388,15 @@ static void adm8211_configure_filter(struct ieee80211_hw *dev, | |||
1400 | } | 1388 | } |
1401 | 1389 | ||
1402 | static int adm8211_add_interface(struct ieee80211_hw *dev, | 1390 | static int adm8211_add_interface(struct ieee80211_hw *dev, |
1403 | struct ieee80211_if_init_conf *conf) | 1391 | struct ieee80211_vif *vif) |
1404 | { | 1392 | { |
1405 | struct adm8211_priv *priv = dev->priv; | 1393 | struct adm8211_priv *priv = dev->priv; |
1406 | if (priv->mode != NL80211_IFTYPE_MONITOR) | 1394 | if (priv->mode != NL80211_IFTYPE_MONITOR) |
1407 | return -EOPNOTSUPP; | 1395 | return -EOPNOTSUPP; |
1408 | 1396 | ||
1409 | switch (conf->type) { | 1397 | switch (vif->type) { |
1410 | case NL80211_IFTYPE_STATION: | 1398 | case NL80211_IFTYPE_STATION: |
1411 | priv->mode = conf->type; | 1399 | priv->mode = vif->type; |
1412 | break; | 1400 | break; |
1413 | default: | 1401 | default: |
1414 | return -EOPNOTSUPP; | 1402 | return -EOPNOTSUPP; |
@@ -1416,8 +1404,8 @@ static int adm8211_add_interface(struct ieee80211_hw *dev, | |||
1416 | 1404 | ||
1417 | ADM8211_IDLE(); | 1405 | ADM8211_IDLE(); |
1418 | 1406 | ||
1419 | ADM8211_CSR_WRITE(PAR0, le32_to_cpu(*(__le32 *)conf->mac_addr)); | 1407 | ADM8211_CSR_WRITE(PAR0, le32_to_cpu(*(__le32 *)vif->addr)); |
1420 | ADM8211_CSR_WRITE(PAR1, le16_to_cpu(*(__le16 *)(conf->mac_addr + 4))); | 1408 | ADM8211_CSR_WRITE(PAR1, le16_to_cpu(*(__le16 *)(vif->addr + 4))); |
1421 | 1409 | ||
1422 | adm8211_update_mode(dev); | 1410 | adm8211_update_mode(dev); |
1423 | 1411 | ||
@@ -1427,7 +1415,7 @@ static int adm8211_add_interface(struct ieee80211_hw *dev, | |||
1427 | } | 1415 | } |
1428 | 1416 | ||
1429 | static void adm8211_remove_interface(struct ieee80211_hw *dev, | 1417 | static void adm8211_remove_interface(struct ieee80211_hw *dev, |
1430 | struct ieee80211_if_init_conf *conf) | 1418 | struct ieee80211_vif *vif) |
1431 | { | 1419 | { |
1432 | struct adm8211_priv *priv = dev->priv; | 1420 | struct adm8211_priv *priv = dev->priv; |
1433 | priv->mode = NL80211_IFTYPE_MONITOR; | 1421 | priv->mode = NL80211_IFTYPE_MONITOR; |
@@ -1773,7 +1761,6 @@ static const struct ieee80211_ops adm8211_ops = { | |||
1773 | .prepare_multicast = adm8211_prepare_multicast, | 1761 | .prepare_multicast = adm8211_prepare_multicast, |
1774 | .configure_filter = adm8211_configure_filter, | 1762 | .configure_filter = adm8211_configure_filter, |
1775 | .get_stats = adm8211_get_stats, | 1763 | .get_stats = adm8211_get_stats, |
1776 | .get_tx_stats = adm8211_get_tx_stats, | ||
1777 | .get_tsf = adm8211_get_tsft | 1764 | .get_tsf = adm8211_get_tsft |
1778 | }; | 1765 | }; |
1779 | 1766 | ||
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 4331d675fcc6..260fb9905e97 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/freezer.h> | 51 | #include <linux/freezer.h> |
52 | 52 | ||
53 | #include <linux/ieee80211.h> | 53 | #include <linux/ieee80211.h> |
54 | #include <net/iw_handler.h> | ||
54 | 55 | ||
55 | #include "airo.h" | 56 | #include "airo.h" |
56 | 57 | ||
@@ -5254,11 +5255,7 @@ static int set_wep_key(struct airo_info *ai, u16 index, const char *key, | |||
5254 | WepKeyRid wkr; | 5255 | WepKeyRid wkr; |
5255 | int rc; | 5256 | int rc; |
5256 | 5257 | ||
5257 | if (keylen == 0) { | 5258 | 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 | 5259 | ||
5263 | memset(&wkr, 0, sizeof(wkr)); | 5260 | memset(&wkr, 0, sizeof(wkr)); |
5264 | wkr.len = cpu_to_le16(sizeof(wkr)); | 5261 | wkr.len = cpu_to_le16(sizeof(wkr)); |
@@ -6405,11 +6402,7 @@ static int airo_set_encode(struct net_device *dev, | |||
6405 | if (dwrq->length > MIN_KEY_SIZE) | 6402 | if (dwrq->length > MIN_KEY_SIZE) |
6406 | key.len = MAX_KEY_SIZE; | 6403 | key.len = MAX_KEY_SIZE; |
6407 | else | 6404 | else |
6408 | if (dwrq->length > 0) | 6405 | 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 */ | 6406 | /* Check if the key is not marked as invalid */ |
6414 | if(!(dwrq->flags & IW_ENCODE_NOKEY)) { | 6407 | if(!(dwrq->flags & IW_ENCODE_NOKEY)) { |
6415 | /* Cleanup */ | 6408 | /* Cleanup */ |
@@ -6590,12 +6583,22 @@ static int airo_set_encodeext(struct net_device *dev, | |||
6590 | default: | 6583 | default: |
6591 | return -EINVAL; | 6584 | return -EINVAL; |
6592 | } | 6585 | } |
6593 | /* Send the key to the card */ | 6586 | if (key.len == 0) { |
6594 | rc = set_wep_key(local, idx, key.key, key.len, perm, 1); | 6587 | rc = set_wep_tx_idx(local, idx, perm, 1); |
6595 | if (rc < 0) { | 6588 | if (rc < 0) { |
6596 | airo_print_err(local->dev->name, "failed to set WEP key" | 6589 | airo_print_err(local->dev->name, |
6597 | " at index %d: %d.", idx, rc); | 6590 | "failed to set WEP transmit index to %d: %d.", |
6598 | return rc; | 6591 | idx, rc); |
6592 | return rc; | ||
6593 | } | ||
6594 | } else { | ||
6595 | rc = set_wep_key(local, idx, key.key, key.len, perm, 1); | ||
6596 | if (rc < 0) { | ||
6597 | airo_print_err(local->dev->name, | ||
6598 | "failed to set WEP key at index %d: %d.", | ||
6599 | idx, rc); | ||
6600 | return rc; | ||
6601 | } | ||
6599 | } | 6602 | } |
6600 | } | 6603 | } |
6601 | 6604 | ||
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 2517364d3ebe..0fb419936dff 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c | |||
@@ -1789,7 +1789,7 @@ static void at76_mac80211_stop(struct ieee80211_hw *hw) | |||
1789 | } | 1789 | } |
1790 | 1790 | ||
1791 | static int at76_add_interface(struct ieee80211_hw *hw, | 1791 | static int at76_add_interface(struct ieee80211_hw *hw, |
1792 | struct ieee80211_if_init_conf *conf) | 1792 | struct ieee80211_vif *vif) |
1793 | { | 1793 | { |
1794 | struct at76_priv *priv = hw->priv; | 1794 | struct at76_priv *priv = hw->priv; |
1795 | int ret = 0; | 1795 | int ret = 0; |
@@ -1798,7 +1798,7 @@ static int at76_add_interface(struct ieee80211_hw *hw, | |||
1798 | 1798 | ||
1799 | mutex_lock(&priv->mtx); | 1799 | mutex_lock(&priv->mtx); |
1800 | 1800 | ||
1801 | switch (conf->type) { | 1801 | switch (vif->type) { |
1802 | case NL80211_IFTYPE_STATION: | 1802 | case NL80211_IFTYPE_STATION: |
1803 | priv->iw_mode = IW_MODE_INFRA; | 1803 | priv->iw_mode = IW_MODE_INFRA; |
1804 | break; | 1804 | break; |
@@ -1814,7 +1814,7 @@ exit: | |||
1814 | } | 1814 | } |
1815 | 1815 | ||
1816 | static void at76_remove_interface(struct ieee80211_hw *hw, | 1816 | static void at76_remove_interface(struct ieee80211_hw *hw, |
1817 | struct ieee80211_if_init_conf *conf) | 1817 | struct ieee80211_vif *vif) |
1818 | { | 1818 | { |
1819 | at76_dbg(DBG_MAC80211, "%s()", __func__); | 1819 | at76_dbg(DBG_MAC80211, "%s()", __func__); |
1820 | } | 1820 | } |
diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index 9f9459860d82..8c8ce67971e9 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h | |||
@@ -109,7 +109,6 @@ struct ar9170_rxstream_mpdu_merge { | |||
109 | bool has_plcp; | 109 | bool has_plcp; |
110 | }; | 110 | }; |
111 | 111 | ||
112 | #define AR9170_NUM_MAX_BA_RETRY 5 | ||
113 | #define AR9170_NUM_TID 16 | 112 | #define AR9170_NUM_TID 16 |
114 | #define WME_BA_BMP_SIZE 64 | 113 | #define WME_BA_BMP_SIZE 64 |
115 | #define AR9170_NUM_MAX_AGG_LEN (2 * WME_BA_BMP_SIZE) | 114 | #define AR9170_NUM_MAX_AGG_LEN (2 * WME_BA_BMP_SIZE) |
@@ -143,7 +142,12 @@ struct ar9170_sta_tid { | |||
143 | u16 tid; | 142 | u16 tid; |
144 | enum ar9170_tid_state state; | 143 | enum ar9170_tid_state state; |
145 | bool active; | 144 | bool active; |
146 | u8 retry; | 145 | }; |
146 | |||
147 | struct ar9170_tx_queue_stats { | ||
148 | unsigned int len; | ||
149 | unsigned int limit; | ||
150 | unsigned int count; | ||
147 | }; | 151 | }; |
148 | 152 | ||
149 | #define AR9170_QUEUE_TIMEOUT 64 | 153 | #define AR9170_QUEUE_TIMEOUT 64 |
@@ -154,6 +158,8 @@ struct ar9170_sta_tid { | |||
154 | 158 | ||
155 | #define AR9170_NUM_TX_STATUS 128 | 159 | #define AR9170_NUM_TX_STATUS 128 |
156 | #define AR9170_NUM_TX_AGG_MAX 30 | 160 | #define AR9170_NUM_TX_AGG_MAX 30 |
161 | #define AR9170_NUM_TX_LIMIT_HARD AR9170_TXQ_DEPTH | ||
162 | #define AR9170_NUM_TX_LIMIT_SOFT (AR9170_TXQ_DEPTH - 10) | ||
157 | 163 | ||
158 | struct ar9170 { | 164 | struct ar9170 { |
159 | struct ieee80211_hw *hw; | 165 | struct ieee80211_hw *hw; |
@@ -211,7 +217,7 @@ struct ar9170 { | |||
211 | 217 | ||
212 | /* qos queue settings */ | 218 | /* qos queue settings */ |
213 | spinlock_t tx_stats_lock; | 219 | spinlock_t tx_stats_lock; |
214 | struct ieee80211_tx_queue_stats tx_stats[5]; | 220 | struct ar9170_tx_queue_stats tx_stats[5]; |
215 | struct ieee80211_tx_queue_params edcf[5]; | 221 | struct ieee80211_tx_queue_params edcf[5]; |
216 | 222 | ||
217 | spinlock_t cmdlock; | 223 | spinlock_t cmdlock; |
@@ -248,13 +254,8 @@ struct ar9170_sta_info { | |||
248 | unsigned int ampdu_max_len; | 254 | unsigned int ampdu_max_len; |
249 | }; | 255 | }; |
250 | 256 | ||
251 | #define AR9170_TX_FLAG_WAIT_FOR_ACK BIT(0) | ||
252 | #define AR9170_TX_FLAG_NO_ACK BIT(1) | ||
253 | #define AR9170_TX_FLAG_BLOCK_ACK BIT(2) | ||
254 | |||
255 | struct ar9170_tx_info { | 257 | struct ar9170_tx_info { |
256 | unsigned long timeout; | 258 | unsigned long timeout; |
257 | unsigned int flags; | ||
258 | }; | 259 | }; |
259 | 260 | ||
260 | #define IS_STARTED(a) (((struct ar9170 *)a)->state >= AR9170_STARTED) | 261 | #define IS_STARTED(a) (((struct ar9170 *)a)->state >= AR9170_STARTED) |
diff --git a/drivers/net/wireless/ath/ar9170/hw.h b/drivers/net/wireless/ath/ar9170/hw.h index 701ddb7d8400..0a1d4c28e68a 100644 --- a/drivers/net/wireless/ath/ar9170/hw.h +++ b/drivers/net/wireless/ath/ar9170/hw.h | |||
@@ -276,6 +276,7 @@ struct ar9170_tx_control { | |||
276 | #define AR9170_TX_MAC_RATE_PROBE 0x8000 | 276 | #define AR9170_TX_MAC_RATE_PROBE 0x8000 |
277 | 277 | ||
278 | /* either-or */ | 278 | /* either-or */ |
279 | #define AR9170_TX_PHY_MOD_MASK 0x00000003 | ||
279 | #define AR9170_TX_PHY_MOD_CCK 0x00000000 | 280 | #define AR9170_TX_PHY_MOD_CCK 0x00000000 |
280 | #define AR9170_TX_PHY_MOD_OFDM 0x00000001 | 281 | #define AR9170_TX_PHY_MOD_OFDM 0x00000001 |
281 | #define AR9170_TX_PHY_MOD_HT 0x00000002 | 282 | #define AR9170_TX_PHY_MOD_HT 0x00000002 |
diff --git a/drivers/net/wireless/ath/ar9170/mac.c b/drivers/net/wireless/ath/ar9170/mac.c index ddc8c09dc79e..857e86104295 100644 --- a/drivers/net/wireless/ath/ar9170/mac.c +++ b/drivers/net/wireless/ath/ar9170/mac.c | |||
@@ -117,7 +117,7 @@ int ar9170_set_qos(struct ar9170 *ar) | |||
117 | ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_TXOP, | 117 | ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_TXOP, |
118 | ar->edcf[0].txop | ar->edcf[1].txop << 16); | 118 | ar->edcf[0].txop | ar->edcf[1].txop << 16); |
119 | ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_TXOP, | 119 | ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_TXOP, |
120 | ar->edcf[1].txop | ar->edcf[3].txop << 16); | 120 | ar->edcf[2].txop | ar->edcf[3].txop << 16); |
121 | 121 | ||
122 | ar9170_regwrite_finish(); | 122 | ar9170_regwrite_finish(); |
123 | 123 | ||
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index f9d6db8d013e..8a964f130367 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
@@ -194,12 +194,15 @@ static inline u16 ar9170_get_seq(struct sk_buff *skb) | |||
194 | return ar9170_get_seq_h((void *) txc->frame_data); | 194 | return ar9170_get_seq_h((void *) txc->frame_data); |
195 | } | 195 | } |
196 | 196 | ||
197 | static inline u16 ar9170_get_tid_h(struct ieee80211_hdr *hdr) | ||
198 | { | ||
199 | return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
200 | } | ||
201 | |||
197 | static inline u16 ar9170_get_tid(struct sk_buff *skb) | 202 | static inline u16 ar9170_get_tid(struct sk_buff *skb) |
198 | { | 203 | { |
199 | struct ar9170_tx_control *txc = (void *) skb->data; | 204 | struct ar9170_tx_control *txc = (void *) skb->data; |
200 | struct ieee80211_hdr *hdr = (void *) txc->frame_data; | 205 | return ar9170_get_tid_h((struct ieee80211_hdr *) txc->frame_data); |
201 | |||
202 | return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
203 | } | 206 | } |
204 | 207 | ||
205 | #define GET_NEXT_SEQ(seq) ((seq + 1) & 0x0fff) | 208 | #define GET_NEXT_SEQ(seq) ((seq + 1) & 0x0fff) |
@@ -213,10 +216,10 @@ static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) | |||
213 | struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; | 216 | struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; |
214 | struct ieee80211_hdr *hdr = (void *) txc->frame_data; | 217 | struct ieee80211_hdr *hdr = (void *) txc->frame_data; |
215 | 218 | ||
216 | printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] flags:%x s:%d " | 219 | printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] s:%d " |
217 | "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n", | 220 | "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n", |
218 | wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb), | 221 | wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb), |
219 | ieee80211_get_DA(hdr), arinfo->flags, ar9170_get_seq_h(hdr), | 222 | ieee80211_get_DA(hdr), ar9170_get_seq_h(hdr), |
220 | le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control), | 223 | le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control), |
221 | jiffies_to_msecs(arinfo->timeout - jiffies)); | 224 | jiffies_to_msecs(arinfo->timeout - jiffies)); |
222 | } | 225 | } |
@@ -430,7 +433,7 @@ void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) | |||
430 | spin_lock_irqsave(&ar->tx_stats_lock, flags); | 433 | spin_lock_irqsave(&ar->tx_stats_lock, flags); |
431 | ar->tx_stats[queue].len--; | 434 | ar->tx_stats[queue].len--; |
432 | 435 | ||
433 | if (skb_queue_empty(&ar->tx_pending[queue])) { | 436 | if (ar->tx_stats[queue].len < AR9170_NUM_TX_LIMIT_SOFT) { |
434 | #ifdef AR9170_QUEUE_STOP_DEBUG | 437 | #ifdef AR9170_QUEUE_STOP_DEBUG |
435 | printk(KERN_DEBUG "%s: wake queue %d\n", | 438 | printk(KERN_DEBUG "%s: wake queue %d\n", |
436 | wiphy_name(ar->hw->wiphy), queue); | 439 | wiphy_name(ar->hw->wiphy), queue); |
@@ -440,22 +443,17 @@ void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) | |||
440 | } | 443 | } |
441 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); | 444 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); |
442 | 445 | ||
443 | if (arinfo->flags & AR9170_TX_FLAG_BLOCK_ACK) { | 446 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) { |
444 | ar9170_tx_ampdu_callback(ar, skb); | ||
445 | } else if (arinfo->flags & AR9170_TX_FLAG_WAIT_FOR_ACK) { | ||
446 | arinfo->timeout = jiffies + | ||
447 | msecs_to_jiffies(AR9170_TX_TIMEOUT); | ||
448 | |||
449 | skb_queue_tail(&ar->tx_status[queue], skb); | ||
450 | } else if (arinfo->flags & AR9170_TX_FLAG_NO_ACK) { | ||
451 | ar9170_tx_status(ar, skb, AR9170_TX_STATUS_FAILED); | 447 | ar9170_tx_status(ar, skb, AR9170_TX_STATUS_FAILED); |
452 | } else { | 448 | } else { |
453 | #ifdef AR9170_QUEUE_DEBUG | 449 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { |
454 | printk(KERN_DEBUG "%s: unsupported frame flags!\n", | 450 | ar9170_tx_ampdu_callback(ar, skb); |
455 | wiphy_name(ar->hw->wiphy)); | 451 | } else { |
456 | ar9170_print_txheader(ar, skb); | 452 | arinfo->timeout = jiffies + |
457 | #endif /* AR9170_QUEUE_DEBUG */ | 453 | msecs_to_jiffies(AR9170_TX_TIMEOUT); |
458 | dev_kfree_skb_any(skb); | 454 | |
455 | skb_queue_tail(&ar->tx_status[queue], skb); | ||
456 | } | ||
459 | } | 457 | } |
460 | 458 | ||
461 | if (!ar->tx_stats[queue].len && | 459 | if (!ar->tx_stats[queue].len && |
@@ -1407,17 +1405,6 @@ static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | |||
1407 | 1405 | ||
1408 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && | 1406 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && |
1409 | (is_valid_ether_addr(ieee80211_get_DA(hdr)))) { | 1407 | (is_valid_ether_addr(ieee80211_get_DA(hdr)))) { |
1410 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | ||
1411 | if (unlikely(!info->control.sta)) | ||
1412 | goto err_out; | ||
1413 | |||
1414 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); | ||
1415 | arinfo->flags = AR9170_TX_FLAG_BLOCK_ACK; | ||
1416 | |||
1417 | goto out; | ||
1418 | } | ||
1419 | |||
1420 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); | ||
1421 | /* | 1408 | /* |
1422 | * WARNING: | 1409 | * WARNING: |
1423 | * Putting the QoS queue bits into an unexplored territory is | 1410 | * Putting the QoS queue bits into an unexplored territory is |
@@ -1431,12 +1418,17 @@ static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | |||
1431 | 1418 | ||
1432 | txc->phy_control |= | 1419 | txc->phy_control |= |
1433 | cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT); | 1420 | cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT); |
1434 | arinfo->flags = AR9170_TX_FLAG_WAIT_FOR_ACK; | 1421 | |
1435 | } else { | 1422 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { |
1436 | arinfo->flags = AR9170_TX_FLAG_NO_ACK; | 1423 | if (unlikely(!info->control.sta)) |
1424 | goto err_out; | ||
1425 | |||
1426 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); | ||
1427 | } else { | ||
1428 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); | ||
1429 | } | ||
1437 | } | 1430 | } |
1438 | 1431 | ||
1439 | out: | ||
1440 | return 0; | 1432 | return 0; |
1441 | 1433 | ||
1442 | err_out: | 1434 | err_out: |
@@ -1671,8 +1663,7 @@ static bool ar9170_tx_ampdu(struct ar9170 *ar) | |||
1671 | * tell the FW/HW that this is the last frame, | 1663 | * tell the FW/HW that this is the last frame, |
1672 | * that way it will wait for the immediate block ack. | 1664 | * that way it will wait for the immediate block ack. |
1673 | */ | 1665 | */ |
1674 | if (likely(skb_peek_tail(&agg))) | 1666 | ar9170_tx_indicate_immba(ar, skb_peek_tail(&agg)); |
1675 | ar9170_tx_indicate_immba(ar, skb_peek_tail(&agg)); | ||
1676 | 1667 | ||
1677 | #ifdef AR9170_TXAGG_DEBUG | 1668 | #ifdef AR9170_TXAGG_DEBUG |
1678 | printk(KERN_DEBUG "%s: generated A-MPDU looks like this:\n", | 1669 | printk(KERN_DEBUG "%s: generated A-MPDU looks like this:\n", |
@@ -1716,6 +1707,21 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1716 | 1707 | ||
1717 | for (i = 0; i < __AR9170_NUM_TXQ; i++) { | 1708 | for (i = 0; i < __AR9170_NUM_TXQ; i++) { |
1718 | spin_lock_irqsave(&ar->tx_stats_lock, flags); | 1709 | spin_lock_irqsave(&ar->tx_stats_lock, flags); |
1710 | frames = min(ar->tx_stats[i].limit - ar->tx_stats[i].len, | ||
1711 | skb_queue_len(&ar->tx_pending[i])); | ||
1712 | |||
1713 | if (remaining_space < frames) { | ||
1714 | #ifdef AR9170_QUEUE_DEBUG | ||
1715 | printk(KERN_DEBUG "%s: tx quota reached queue:%d, " | ||
1716 | "remaining slots:%d, needed:%d\n", | ||
1717 | wiphy_name(ar->hw->wiphy), i, remaining_space, | ||
1718 | frames); | ||
1719 | #endif /* AR9170_QUEUE_DEBUG */ | ||
1720 | frames = remaining_space; | ||
1721 | } | ||
1722 | |||
1723 | ar->tx_stats[i].len += frames; | ||
1724 | ar->tx_stats[i].count += frames; | ||
1719 | if (ar->tx_stats[i].len >= ar->tx_stats[i].limit) { | 1725 | if (ar->tx_stats[i].len >= ar->tx_stats[i].limit) { |
1720 | #ifdef AR9170_QUEUE_DEBUG | 1726 | #ifdef AR9170_QUEUE_DEBUG |
1721 | printk(KERN_DEBUG "%s: queue %d full\n", | 1727 | printk(KERN_DEBUG "%s: queue %d full\n", |
@@ -1733,25 +1739,8 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1733 | __ar9170_dump_txstats(ar); | 1739 | __ar9170_dump_txstats(ar); |
1734 | #endif /* AR9170_QUEUE_STOP_DEBUG */ | 1740 | #endif /* AR9170_QUEUE_STOP_DEBUG */ |
1735 | ieee80211_stop_queue(ar->hw, i); | 1741 | ieee80211_stop_queue(ar->hw, i); |
1736 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); | ||
1737 | continue; | ||
1738 | } | ||
1739 | |||
1740 | frames = min(ar->tx_stats[i].limit - ar->tx_stats[i].len, | ||
1741 | skb_queue_len(&ar->tx_pending[i])); | ||
1742 | |||
1743 | if (remaining_space < frames) { | ||
1744 | #ifdef AR9170_QUEUE_DEBUG | ||
1745 | printk(KERN_DEBUG "%s: tx quota reached queue:%d, " | ||
1746 | "remaining slots:%d, needed:%d\n", | ||
1747 | wiphy_name(ar->hw->wiphy), i, remaining_space, | ||
1748 | frames); | ||
1749 | #endif /* AR9170_QUEUE_DEBUG */ | ||
1750 | frames = remaining_space; | ||
1751 | } | 1742 | } |
1752 | 1743 | ||
1753 | ar->tx_stats[i].len += frames; | ||
1754 | ar->tx_stats[i].count += frames; | ||
1755 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); | 1744 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); |
1756 | 1745 | ||
1757 | if (!frames) | 1746 | if (!frames) |
@@ -1773,7 +1762,7 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1773 | arinfo->timeout = jiffies + | 1762 | arinfo->timeout = jiffies + |
1774 | msecs_to_jiffies(AR9170_TX_TIMEOUT); | 1763 | msecs_to_jiffies(AR9170_TX_TIMEOUT); |
1775 | 1764 | ||
1776 | if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) | 1765 | if (info->flags & IEEE80211_TX_CTL_AMPDU) |
1777 | atomic_inc(&ar->tx_ampdu_pending); | 1766 | atomic_inc(&ar->tx_ampdu_pending); |
1778 | 1767 | ||
1779 | #ifdef AR9170_QUEUE_DEBUG | 1768 | #ifdef AR9170_QUEUE_DEBUG |
@@ -1784,7 +1773,7 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1784 | 1773 | ||
1785 | err = ar->tx(ar, skb); | 1774 | err = ar->tx(ar, skb); |
1786 | if (unlikely(err)) { | 1775 | if (unlikely(err)) { |
1787 | if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) | 1776 | if (info->flags & IEEE80211_TX_CTL_AMPDU) |
1788 | atomic_dec(&ar->tx_ampdu_pending); | 1777 | atomic_dec(&ar->tx_ampdu_pending); |
1789 | 1778 | ||
1790 | frames_failed++; | 1779 | frames_failed++; |
@@ -1950,7 +1939,7 @@ err_free: | |||
1950 | } | 1939 | } |
1951 | 1940 | ||
1952 | static int ar9170_op_add_interface(struct ieee80211_hw *hw, | 1941 | static int ar9170_op_add_interface(struct ieee80211_hw *hw, |
1953 | struct ieee80211_if_init_conf *conf) | 1942 | struct ieee80211_vif *vif) |
1954 | { | 1943 | { |
1955 | struct ar9170 *ar = hw->priv; | 1944 | struct ar9170 *ar = hw->priv; |
1956 | struct ath_common *common = &ar->common; | 1945 | struct ath_common *common = &ar->common; |
@@ -1963,8 +1952,8 @@ static int ar9170_op_add_interface(struct ieee80211_hw *hw, | |||
1963 | goto unlock; | 1952 | goto unlock; |
1964 | } | 1953 | } |
1965 | 1954 | ||
1966 | ar->vif = conf->vif; | 1955 | ar->vif = vif; |
1967 | memcpy(common->macaddr, conf->mac_addr, ETH_ALEN); | 1956 | memcpy(common->macaddr, vif->addr, ETH_ALEN); |
1968 | 1957 | ||
1969 | if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { | 1958 | if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { |
1970 | ar->rx_software_decryption = true; | 1959 | ar->rx_software_decryption = true; |
@@ -1984,7 +1973,7 @@ unlock: | |||
1984 | } | 1973 | } |
1985 | 1974 | ||
1986 | static void ar9170_op_remove_interface(struct ieee80211_hw *hw, | 1975 | static void ar9170_op_remove_interface(struct ieee80211_hw *hw, |
1987 | struct ieee80211_if_init_conf *conf) | 1976 | struct ieee80211_vif *vif) |
1988 | { | 1977 | { |
1989 | struct ar9170 *ar = hw->priv; | 1978 | struct ar9170 *ar = hw->priv; |
1990 | 1979 | ||
@@ -2340,55 +2329,55 @@ out: | |||
2340 | return err; | 2329 | return err; |
2341 | } | 2330 | } |
2342 | 2331 | ||
2343 | static void ar9170_sta_notify(struct ieee80211_hw *hw, | 2332 | static int ar9170_sta_add(struct ieee80211_hw *hw, |
2344 | struct ieee80211_vif *vif, | 2333 | struct ieee80211_vif *vif, |
2345 | enum sta_notify_cmd cmd, | 2334 | struct ieee80211_sta *sta) |
2346 | struct ieee80211_sta *sta) | ||
2347 | { | 2335 | { |
2348 | struct ar9170 *ar = hw->priv; | 2336 | struct ar9170 *ar = hw->priv; |
2349 | struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; | 2337 | struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; |
2350 | unsigned int i; | 2338 | unsigned int i; |
2351 | 2339 | ||
2352 | switch (cmd) { | 2340 | memset(sta_info, 0, sizeof(*sta_info)); |
2353 | case STA_NOTIFY_ADD: | ||
2354 | memset(sta_info, 0, sizeof(*sta_info)); | ||
2355 | 2341 | ||
2356 | if (!sta->ht_cap.ht_supported) | 2342 | if (!sta->ht_cap.ht_supported) |
2357 | break; | 2343 | return 0; |
2358 | 2344 | ||
2359 | if (sta->ht_cap.ampdu_density > ar->global_ampdu_density) | 2345 | if (sta->ht_cap.ampdu_density > ar->global_ampdu_density) |
2360 | ar->global_ampdu_density = sta->ht_cap.ampdu_density; | 2346 | ar->global_ampdu_density = sta->ht_cap.ampdu_density; |
2361 | 2347 | ||
2362 | if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor) | 2348 | if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor) |
2363 | ar->global_ampdu_factor = sta->ht_cap.ampdu_factor; | 2349 | ar->global_ampdu_factor = sta->ht_cap.ampdu_factor; |
2364 | 2350 | ||
2365 | for (i = 0; i < AR9170_NUM_TID; i++) { | 2351 | for (i = 0; i < AR9170_NUM_TID; i++) { |
2366 | sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN; | 2352 | sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN; |
2367 | sta_info->agg[i].active = false; | 2353 | sta_info->agg[i].active = false; |
2368 | sta_info->agg[i].ssn = 0; | 2354 | sta_info->agg[i].ssn = 0; |
2369 | sta_info->agg[i].retry = 0; | 2355 | sta_info->agg[i].tid = i; |
2370 | sta_info->agg[i].tid = i; | 2356 | INIT_LIST_HEAD(&sta_info->agg[i].list); |
2371 | INIT_LIST_HEAD(&sta_info->agg[i].list); | 2357 | skb_queue_head_init(&sta_info->agg[i].queue); |
2372 | skb_queue_head_init(&sta_info->agg[i].queue); | 2358 | } |
2373 | } | ||
2374 | 2359 | ||
2375 | sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor); | 2360 | sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor); |
2376 | break; | ||
2377 | 2361 | ||
2378 | case STA_NOTIFY_REMOVE: | 2362 | return 0; |
2379 | if (!sta->ht_cap.ht_supported) | 2363 | } |
2380 | break; | ||
2381 | 2364 | ||
2382 | for (i = 0; i < AR9170_NUM_TID; i++) { | 2365 | static int ar9170_sta_remove(struct ieee80211_hw *hw, |
2383 | sta_info->agg[i].state = AR9170_TID_STATE_INVALID; | 2366 | struct ieee80211_vif *vif, |
2384 | skb_queue_purge(&sta_info->agg[i].queue); | 2367 | struct ieee80211_sta *sta) |
2385 | } | 2368 | { |
2369 | struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; | ||
2370 | unsigned int i; | ||
2386 | 2371 | ||
2387 | break; | 2372 | if (!sta->ht_cap.ht_supported) |
2373 | return 0; | ||
2388 | 2374 | ||
2389 | default: | 2375 | for (i = 0; i < AR9170_NUM_TID; i++) { |
2390 | break; | 2376 | sta_info->agg[i].state = AR9170_TID_STATE_INVALID; |
2377 | skb_queue_purge(&sta_info->agg[i].queue); | ||
2391 | } | 2378 | } |
2379 | |||
2380 | return 0; | ||
2392 | } | 2381 | } |
2393 | 2382 | ||
2394 | static int ar9170_get_stats(struct ieee80211_hw *hw, | 2383 | static int ar9170_get_stats(struct ieee80211_hw *hw, |
@@ -2408,18 +2397,6 @@ static int ar9170_get_stats(struct ieee80211_hw *hw, | |||
2408 | return 0; | 2397 | return 0; |
2409 | } | 2398 | } |
2410 | 2399 | ||
2411 | static int ar9170_get_tx_stats(struct ieee80211_hw *hw, | ||
2412 | struct ieee80211_tx_queue_stats *tx_stats) | ||
2413 | { | ||
2414 | struct ar9170 *ar = hw->priv; | ||
2415 | |||
2416 | spin_lock_bh(&ar->tx_stats_lock); | ||
2417 | memcpy(tx_stats, ar->tx_stats, sizeof(tx_stats[0]) * hw->queues); | ||
2418 | spin_unlock_bh(&ar->tx_stats_lock); | ||
2419 | |||
2420 | return 0; | ||
2421 | } | ||
2422 | |||
2423 | static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, | 2400 | static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, |
2424 | const struct ieee80211_tx_queue_params *param) | 2401 | const struct ieee80211_tx_queue_params *param) |
2425 | { | 2402 | { |
@@ -2519,9 +2496,9 @@ static const struct ieee80211_ops ar9170_ops = { | |||
2519 | .bss_info_changed = ar9170_op_bss_info_changed, | 2496 | .bss_info_changed = ar9170_op_bss_info_changed, |
2520 | .get_tsf = ar9170_op_get_tsf, | 2497 | .get_tsf = ar9170_op_get_tsf, |
2521 | .set_key = ar9170_set_key, | 2498 | .set_key = ar9170_set_key, |
2522 | .sta_notify = ar9170_sta_notify, | 2499 | .sta_add = ar9170_sta_add, |
2500 | .sta_remove = ar9170_sta_remove, | ||
2523 | .get_stats = ar9170_get_stats, | 2501 | .get_stats = ar9170_get_stats, |
2524 | .get_tx_stats = ar9170_get_tx_stats, | ||
2525 | .ampdu_action = ar9170_ampdu_action, | 2502 | .ampdu_action = ar9170_ampdu_action, |
2526 | }; | 2503 | }; |
2527 | 2504 | ||
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index e0799d924057..0f361186b78f 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c | |||
@@ -84,6 +84,8 @@ static struct usb_device_id ar9170_usb_ids[] = { | |||
84 | { USB_DEVICE(0x0cde, 0x0023) }, | 84 | { USB_DEVICE(0x0cde, 0x0023) }, |
85 | /* Z-Com UB82 ABG */ | 85 | /* Z-Com UB82 ABG */ |
86 | { USB_DEVICE(0x0cde, 0x0026) }, | 86 | { USB_DEVICE(0x0cde, 0x0026) }, |
87 | /* Sphairon Homelink 1202 */ | ||
88 | { USB_DEVICE(0x0cde, 0x0027) }, | ||
87 | /* Arcadyan WN7512 */ | 89 | /* Arcadyan WN7512 */ |
88 | { USB_DEVICE(0x083a, 0xf522) }, | 90 | { USB_DEVICE(0x083a, 0xf522) }, |
89 | /* Planex GWUS300 */ | 91 | /* Planex GWUS300 */ |
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 6a2a96761111..ac67f02e26d8 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -535,13 +535,12 @@ 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 | /* |
542 | * Transmit packet types. | 542 | * Transmit packet types. |
543 | * used on tx control descriptor | 543 | * used on tx control descriptor |
544 | * TODO: Use them inside base.c corectly | ||
545 | */ | 544 | */ |
546 | enum ath5k_pkt_type { | 545 | enum ath5k_pkt_type { |
547 | AR5K_PKT_TYPE_NORMAL = 0, | 546 | AR5K_PKT_TYPE_NORMAL = 0, |
@@ -1063,6 +1062,7 @@ struct ath5k_hw { | |||
1063 | u32 ah_cw_min; | 1062 | u32 ah_cw_min; |
1064 | u32 ah_cw_max; | 1063 | u32 ah_cw_max; |
1065 | u32 ah_limit_tx_retries; | 1064 | u32 ah_limit_tx_retries; |
1065 | u8 ah_coverage_class; | ||
1066 | 1066 | ||
1067 | /* Antenna Control */ | 1067 | /* Antenna Control */ |
1068 | u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; | 1068 | u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; |
@@ -1200,6 +1200,7 @@ extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah); | |||
1200 | 1200 | ||
1201 | /* Protocol Control Unit Functions */ | 1201 | /* Protocol Control Unit Functions */ |
1202 | extern int ath5k_hw_set_opmode(struct ath5k_hw *ah); | 1202 | extern int ath5k_hw_set_opmode(struct ath5k_hw *ah); |
1203 | extern void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); | ||
1203 | /* BSSID Functions */ | 1204 | /* BSSID Functions */ |
1204 | extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); | 1205 | extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); |
1205 | extern void ath5k_hw_set_associd(struct ath5k_hw *ah); | 1206 | extern void ath5k_hw_set_associd(struct ath5k_hw *ah); |
@@ -1231,6 +1232,10 @@ extern int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout); | |||
1231 | extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah); | 1232 | extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah); |
1232 | extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout); | 1233 | extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout); |
1233 | extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah); | 1234 | extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah); |
1235 | /* Clock rate related functions */ | ||
1236 | unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec); | ||
1237 | unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock); | ||
1238 | unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah); | ||
1234 | /* Key table (WEP) functions */ | 1239 | /* Key table (WEP) functions */ |
1235 | extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry); | 1240 | extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry); |
1236 | extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry); | 1241 | extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry); |
@@ -1310,24 +1315,6 @@ extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); | |||
1310 | * Functions used internaly | 1315 | * Functions used internaly |
1311 | */ | 1316 | */ |
1312 | 1317 | ||
1313 | /* | ||
1314 | * Translate usec to hw clock units | ||
1315 | * TODO: Half/quarter rate | ||
1316 | */ | ||
1317 | static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo) | ||
1318 | { | ||
1319 | return turbo ? (usec * 80) : (usec * 40); | ||
1320 | } | ||
1321 | |||
1322 | /* | ||
1323 | * Translate hw clock units to usec | ||
1324 | * TODO: Half/quarter rate | ||
1325 | */ | ||
1326 | static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo) | ||
1327 | { | ||
1328 | return turbo ? (clock / 80) : (clock / 40); | ||
1329 | } | ||
1330 | |||
1331 | static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah) | 1318 | static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah) |
1332 | { | 1319 | { |
1333 | return &ah->common; | 1320 | return &ah->common; |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index e63b7c40d0ee..2468c64d6c12 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -225,9 +225,9 @@ static int ath5k_reset_wake(struct ath5k_softc *sc); | |||
225 | static int ath5k_start(struct ieee80211_hw *hw); | 225 | static int ath5k_start(struct ieee80211_hw *hw); |
226 | static void ath5k_stop(struct ieee80211_hw *hw); | 226 | static void ath5k_stop(struct ieee80211_hw *hw); |
227 | static int ath5k_add_interface(struct ieee80211_hw *hw, | 227 | static int ath5k_add_interface(struct ieee80211_hw *hw, |
228 | struct ieee80211_if_init_conf *conf); | 228 | struct ieee80211_vif *vif); |
229 | static void ath5k_remove_interface(struct ieee80211_hw *hw, | 229 | static void ath5k_remove_interface(struct ieee80211_hw *hw, |
230 | struct ieee80211_if_init_conf *conf); | 230 | struct ieee80211_vif *vif); |
231 | static int ath5k_config(struct ieee80211_hw *hw, u32 changed); | 231 | static int ath5k_config(struct ieee80211_hw *hw, u32 changed); |
232 | static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, | 232 | static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, |
233 | int mc_count, struct dev_addr_list *mc_list); | 233 | int mc_count, struct dev_addr_list *mc_list); |
@@ -241,8 +241,6 @@ static int ath5k_set_key(struct ieee80211_hw *hw, | |||
241 | struct ieee80211_key_conf *key); | 241 | struct ieee80211_key_conf *key); |
242 | static int ath5k_get_stats(struct ieee80211_hw *hw, | 242 | static int ath5k_get_stats(struct ieee80211_hw *hw, |
243 | struct ieee80211_low_level_stats *stats); | 243 | struct ieee80211_low_level_stats *stats); |
244 | static int ath5k_get_tx_stats(struct ieee80211_hw *hw, | ||
245 | struct ieee80211_tx_queue_stats *stats); | ||
246 | static u64 ath5k_get_tsf(struct ieee80211_hw *hw); | 244 | static u64 ath5k_get_tsf(struct ieee80211_hw *hw); |
247 | static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); | 245 | static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); |
248 | static void ath5k_reset_tsf(struct ieee80211_hw *hw); | 246 | static void ath5k_reset_tsf(struct ieee80211_hw *hw); |
@@ -254,6 +252,8 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | |||
254 | u32 changes); | 252 | u32 changes); |
255 | static void ath5k_sw_scan_start(struct ieee80211_hw *hw); | 253 | static void ath5k_sw_scan_start(struct ieee80211_hw *hw); |
256 | static void ath5k_sw_scan_complete(struct ieee80211_hw *hw); | 254 | static void ath5k_sw_scan_complete(struct ieee80211_hw *hw); |
255 | static void ath5k_set_coverage_class(struct ieee80211_hw *hw, | ||
256 | u8 coverage_class); | ||
257 | 257 | ||
258 | static const struct ieee80211_ops ath5k_hw_ops = { | 258 | static const struct ieee80211_ops ath5k_hw_ops = { |
259 | .tx = ath5k_tx, | 259 | .tx = ath5k_tx, |
@@ -267,13 +267,13 @@ static const struct ieee80211_ops ath5k_hw_ops = { | |||
267 | .set_key = ath5k_set_key, | 267 | .set_key = ath5k_set_key, |
268 | .get_stats = ath5k_get_stats, | 268 | .get_stats = ath5k_get_stats, |
269 | .conf_tx = NULL, | 269 | .conf_tx = NULL, |
270 | .get_tx_stats = ath5k_get_tx_stats, | ||
271 | .get_tsf = ath5k_get_tsf, | 270 | .get_tsf = ath5k_get_tsf, |
272 | .set_tsf = ath5k_set_tsf, | 271 | .set_tsf = ath5k_set_tsf, |
273 | .reset_tsf = ath5k_reset_tsf, | 272 | .reset_tsf = ath5k_reset_tsf, |
274 | .bss_info_changed = ath5k_bss_info_changed, | 273 | .bss_info_changed = ath5k_bss_info_changed, |
275 | .sw_scan_start = ath5k_sw_scan_start, | 274 | .sw_scan_start = ath5k_sw_scan_start, |
276 | .sw_scan_complete = ath5k_sw_scan_complete, | 275 | .sw_scan_complete = ath5k_sw_scan_complete, |
276 | .set_coverage_class = ath5k_set_coverage_class, | ||
277 | }; | 277 | }; |
278 | 278 | ||
279 | /* | 279 | /* |
@@ -1246,6 +1246,29 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
1246 | return 0; | 1246 | return 0; |
1247 | } | 1247 | } |
1248 | 1248 | ||
1249 | static enum ath5k_pkt_type get_hw_packet_type(struct sk_buff *skb) | ||
1250 | { | ||
1251 | struct ieee80211_hdr *hdr; | ||
1252 | enum ath5k_pkt_type htype; | ||
1253 | __le16 fc; | ||
1254 | |||
1255 | hdr = (struct ieee80211_hdr *)skb->data; | ||
1256 | fc = hdr->frame_control; | ||
1257 | |||
1258 | if (ieee80211_is_beacon(fc)) | ||
1259 | htype = AR5K_PKT_TYPE_BEACON; | ||
1260 | else if (ieee80211_is_probe_resp(fc)) | ||
1261 | htype = AR5K_PKT_TYPE_PROBE_RESP; | ||
1262 | else if (ieee80211_is_atim(fc)) | ||
1263 | htype = AR5K_PKT_TYPE_ATIM; | ||
1264 | else if (ieee80211_is_pspoll(fc)) | ||
1265 | htype = AR5K_PKT_TYPE_PSPOLL; | ||
1266 | else | ||
1267 | htype = AR5K_PKT_TYPE_NORMAL; | ||
1268 | |||
1269 | return htype; | ||
1270 | } | ||
1271 | |||
1249 | static int | 1272 | static int |
1250 | ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | 1273 | ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, |
1251 | struct ath5k_txq *txq) | 1274 | struct ath5k_txq *txq) |
@@ -1300,7 +1323,8 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | |||
1300 | sc->vif, pktlen, info)); | 1323 | sc->vif, pktlen, info)); |
1301 | } | 1324 | } |
1302 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, | 1325 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, |
1303 | ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, | 1326 | ieee80211_get_hdrlen_from_skb(skb), |
1327 | get_hw_packet_type(skb), | ||
1304 | (sc->power_level * 2), | 1328 | (sc->power_level * 2), |
1305 | hw_rate, | 1329 | hw_rate, |
1306 | info->control.rates[0].count, keyidx, ah->ah_tx_ant, flags, | 1330 | info->control.rates[0].count, keyidx, ah->ah_tx_ant, flags, |
@@ -1329,7 +1353,6 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | |||
1329 | 1353 | ||
1330 | spin_lock_bh(&txq->lock); | 1354 | spin_lock_bh(&txq->lock); |
1331 | list_add_tail(&bf->list, &txq->q); | 1355 | list_add_tail(&bf->list, &txq->q); |
1332 | sc->tx_stats[txq->qnum].len++; | ||
1333 | if (txq->link == NULL) /* is this first packet? */ | 1356 | if (txq->link == NULL) /* is this first packet? */ |
1334 | ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr); | 1357 | ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr); |
1335 | else /* no, so only link it */ | 1358 | else /* no, so only link it */ |
@@ -1513,7 +1536,8 @@ ath5k_beaconq_config(struct ath5k_softc *sc) | |||
1513 | 1536 | ||
1514 | ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi); | 1537 | ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi); |
1515 | if (ret) | 1538 | if (ret) |
1516 | return ret; | 1539 | goto err; |
1540 | |||
1517 | if (sc->opmode == NL80211_IFTYPE_AP || | 1541 | if (sc->opmode == NL80211_IFTYPE_AP || |
1518 | sc->opmode == NL80211_IFTYPE_MESH_POINT) { | 1542 | sc->opmode == NL80211_IFTYPE_MESH_POINT) { |
1519 | /* | 1543 | /* |
@@ -1540,10 +1564,25 @@ ath5k_beaconq_config(struct ath5k_softc *sc) | |||
1540 | if (ret) { | 1564 | if (ret) { |
1541 | ATH5K_ERR(sc, "%s: unable to update parameters for beacon " | 1565 | ATH5K_ERR(sc, "%s: unable to update parameters for beacon " |
1542 | "hardware queue!\n", __func__); | 1566 | "hardware queue!\n", __func__); |
1543 | return ret; | 1567 | goto err; |
1544 | } | 1568 | } |
1569 | ret = ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */ | ||
1570 | if (ret) | ||
1571 | goto err; | ||
1572 | |||
1573 | /* reconfigure cabq with ready time to 80% of beacon_interval */ | ||
1574 | ret = ath5k_hw_get_tx_queueprops(ah, AR5K_TX_QUEUE_ID_CAB, &qi); | ||
1575 | if (ret) | ||
1576 | goto err; | ||
1577 | |||
1578 | qi.tqi_ready_time = (sc->bintval * 80) / 100; | ||
1579 | ret = ath5k_hw_set_tx_queueprops(ah, AR5K_TX_QUEUE_ID_CAB, &qi); | ||
1580 | if (ret) | ||
1581 | goto err; | ||
1545 | 1582 | ||
1546 | return ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */; | 1583 | ret = ath5k_hw_reset_tx_queue(ah, AR5K_TX_QUEUE_ID_CAB); |
1584 | err: | ||
1585 | return ret; | ||
1547 | } | 1586 | } |
1548 | 1587 | ||
1549 | static void | 1588 | static void |
@@ -1562,7 +1601,6 @@ ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
1562 | ath5k_txbuf_free(sc, bf); | 1601 | ath5k_txbuf_free(sc, bf); |
1563 | 1602 | ||
1564 | spin_lock_bh(&sc->txbuflock); | 1603 | spin_lock_bh(&sc->txbuflock); |
1565 | sc->tx_stats[txq->qnum].len--; | ||
1566 | list_move_tail(&bf->list, &sc->txbuf); | 1604 | list_move_tail(&bf->list, &sc->txbuf); |
1567 | sc->txbuf_len++; | 1605 | sc->txbuf_len++; |
1568 | spin_unlock_bh(&sc->txbuflock); | 1606 | spin_unlock_bh(&sc->txbuflock); |
@@ -1992,10 +2030,8 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
1992 | } | 2030 | } |
1993 | 2031 | ||
1994 | ieee80211_tx_status(sc->hw, skb); | 2032 | ieee80211_tx_status(sc->hw, skb); |
1995 | sc->tx_stats[txq->qnum].count++; | ||
1996 | 2033 | ||
1997 | spin_lock(&sc->txbuflock); | 2034 | spin_lock(&sc->txbuflock); |
1998 | sc->tx_stats[txq->qnum].len--; | ||
1999 | list_move_tail(&bf->list, &sc->txbuf); | 2035 | list_move_tail(&bf->list, &sc->txbuf); |
2000 | sc->txbuf_len++; | 2036 | sc->txbuf_len++; |
2001 | spin_unlock(&sc->txbuflock); | 2037 | spin_unlock(&sc->txbuflock); |
@@ -2773,7 +2809,7 @@ static void ath5k_stop(struct ieee80211_hw *hw) | |||
2773 | } | 2809 | } |
2774 | 2810 | ||
2775 | static int ath5k_add_interface(struct ieee80211_hw *hw, | 2811 | static int ath5k_add_interface(struct ieee80211_hw *hw, |
2776 | struct ieee80211_if_init_conf *conf) | 2812 | struct ieee80211_vif *vif) |
2777 | { | 2813 | { |
2778 | struct ath5k_softc *sc = hw->priv; | 2814 | struct ath5k_softc *sc = hw->priv; |
2779 | int ret; | 2815 | int ret; |
@@ -2784,22 +2820,22 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, | |||
2784 | goto end; | 2820 | goto end; |
2785 | } | 2821 | } |
2786 | 2822 | ||
2787 | sc->vif = conf->vif; | 2823 | sc->vif = vif; |
2788 | 2824 | ||
2789 | switch (conf->type) { | 2825 | switch (vif->type) { |
2790 | case NL80211_IFTYPE_AP: | 2826 | case NL80211_IFTYPE_AP: |
2791 | case NL80211_IFTYPE_STATION: | 2827 | case NL80211_IFTYPE_STATION: |
2792 | case NL80211_IFTYPE_ADHOC: | 2828 | case NL80211_IFTYPE_ADHOC: |
2793 | case NL80211_IFTYPE_MESH_POINT: | 2829 | case NL80211_IFTYPE_MESH_POINT: |
2794 | case NL80211_IFTYPE_MONITOR: | 2830 | case NL80211_IFTYPE_MONITOR: |
2795 | sc->opmode = conf->type; | 2831 | sc->opmode = vif->type; |
2796 | break; | 2832 | break; |
2797 | default: | 2833 | default: |
2798 | ret = -EOPNOTSUPP; | 2834 | ret = -EOPNOTSUPP; |
2799 | goto end; | 2835 | goto end; |
2800 | } | 2836 | } |
2801 | 2837 | ||
2802 | ath5k_hw_set_lladdr(sc->ah, conf->mac_addr); | 2838 | ath5k_hw_set_lladdr(sc->ah, vif->addr); |
2803 | ath5k_mode_setup(sc); | 2839 | ath5k_mode_setup(sc); |
2804 | 2840 | ||
2805 | ret = 0; | 2841 | ret = 0; |
@@ -2810,13 +2846,13 @@ end: | |||
2810 | 2846 | ||
2811 | static void | 2847 | static void |
2812 | ath5k_remove_interface(struct ieee80211_hw *hw, | 2848 | ath5k_remove_interface(struct ieee80211_hw *hw, |
2813 | struct ieee80211_if_init_conf *conf) | 2849 | struct ieee80211_vif *vif) |
2814 | { | 2850 | { |
2815 | struct ath5k_softc *sc = hw->priv; | 2851 | struct ath5k_softc *sc = hw->priv; |
2816 | u8 mac[ETH_ALEN] = {}; | 2852 | u8 mac[ETH_ALEN] = {}; |
2817 | 2853 | ||
2818 | mutex_lock(&sc->lock); | 2854 | mutex_lock(&sc->lock); |
2819 | if (sc->vif != conf->vif) | 2855 | if (sc->vif != vif) |
2820 | goto end; | 2856 | goto end; |
2821 | 2857 | ||
2822 | ath5k_hw_set_lladdr(sc->ah, mac); | 2858 | ath5k_hw_set_lladdr(sc->ah, mac); |
@@ -3097,17 +3133,6 @@ ath5k_get_stats(struct ieee80211_hw *hw, | |||
3097 | return 0; | 3133 | return 0; |
3098 | } | 3134 | } |
3099 | 3135 | ||
3100 | static int | ||
3101 | ath5k_get_tx_stats(struct ieee80211_hw *hw, | ||
3102 | struct ieee80211_tx_queue_stats *stats) | ||
3103 | { | ||
3104 | struct ath5k_softc *sc = hw->priv; | ||
3105 | |||
3106 | memcpy(stats, &sc->tx_stats, sizeof(sc->tx_stats)); | ||
3107 | |||
3108 | return 0; | ||
3109 | } | ||
3110 | |||
3111 | static u64 | 3136 | static u64 |
3112 | ath5k_get_tsf(struct ieee80211_hw *hw) | 3137 | ath5k_get_tsf(struct ieee80211_hw *hw) |
3113 | { | 3138 | { |
@@ -3262,3 +3287,22 @@ static void ath5k_sw_scan_complete(struct ieee80211_hw *hw) | |||
3262 | ath5k_hw_set_ledstate(sc->ah, sc->assoc ? | 3287 | ath5k_hw_set_ledstate(sc->ah, sc->assoc ? |
3263 | AR5K_LED_ASSOC : AR5K_LED_INIT); | 3288 | AR5K_LED_ASSOC : AR5K_LED_INIT); |
3264 | } | 3289 | } |
3290 | |||
3291 | /** | ||
3292 | * ath5k_set_coverage_class - Set IEEE 802.11 coverage class | ||
3293 | * | ||
3294 | * @hw: struct ieee80211_hw pointer | ||
3295 | * @coverage_class: IEEE 802.11 coverage class number | ||
3296 | * | ||
3297 | * Mac80211 callback. Sets slot time, ACK timeout and CTS timeout for given | ||
3298 | * coverage class. The values are persistent, they are restored after device | ||
3299 | * reset. | ||
3300 | */ | ||
3301 | static void ath5k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) | ||
3302 | { | ||
3303 | struct ath5k_softc *sc = hw->priv; | ||
3304 | |||
3305 | mutex_lock(&sc->lock); | ||
3306 | ath5k_hw_set_coverage_class(sc->ah, coverage_class); | ||
3307 | mutex_unlock(&sc->lock); | ||
3308 | } | ||
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index b72338c9bde7..9c2fbf230ce7 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h | |||
@@ -117,7 +117,6 @@ struct ath5k_softc { | |||
117 | struct pci_dev *pdev; /* for dma mapping */ | 117 | struct pci_dev *pdev; /* for dma mapping */ |
118 | void __iomem *iobase; /* address of the device */ | 118 | void __iomem *iobase; /* address of the device */ |
119 | struct mutex lock; /* dev-level lock */ | 119 | struct mutex lock; /* dev-level lock */ |
120 | struct ieee80211_tx_queue_stats tx_stats[AR5K_NUM_TX_QUEUES]; | ||
121 | struct ieee80211_low_level_stats ll_stats; | 120 | struct ieee80211_low_level_stats ll_stats; |
122 | struct ieee80211_hw *hw; /* IEEE 802.11 common */ | 121 | struct ieee80211_hw *hw; /* IEEE 802.11 common */ |
123 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; | 122 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; |
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/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 64fc1eb9b6d9..aefe84f9c04b 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c | |||
@@ -187,8 +187,8 @@ unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah) | |||
187 | { | 187 | { |
188 | ATH5K_TRACE(ah->ah_sc); | 188 | ATH5K_TRACE(ah->ah_sc); |
189 | 189 | ||
190 | return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, | 190 | return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah, |
191 | AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo); | 191 | AR5K_TIME_OUT), AR5K_TIME_OUT_ACK)); |
192 | } | 192 | } |
193 | 193 | ||
194 | /** | 194 | /** |
@@ -200,12 +200,12 @@ unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah) | |||
200 | int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) | 200 | int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) |
201 | { | 201 | { |
202 | ATH5K_TRACE(ah->ah_sc); | 202 | ATH5K_TRACE(ah->ah_sc); |
203 | if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK), | 203 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK)) |
204 | ah->ah_turbo) <= timeout) | 204 | <= timeout) |
205 | return -EINVAL; | 205 | return -EINVAL; |
206 | 206 | ||
207 | AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK, | 207 | AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK, |
208 | ath5k_hw_htoclock(timeout, ah->ah_turbo)); | 208 | ath5k_hw_htoclock(ah, timeout)); |
209 | 209 | ||
210 | return 0; | 210 | return 0; |
211 | } | 211 | } |
@@ -218,8 +218,8 @@ int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) | |||
218 | unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) | 218 | unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) |
219 | { | 219 | { |
220 | ATH5K_TRACE(ah->ah_sc); | 220 | ATH5K_TRACE(ah->ah_sc); |
221 | return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, | 221 | return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah, |
222 | AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo); | 222 | AR5K_TIME_OUT), AR5K_TIME_OUT_CTS)); |
223 | } | 223 | } |
224 | 224 | ||
225 | /** | 225 | /** |
@@ -231,17 +231,97 @@ unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) | |||
231 | int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) | 231 | int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) |
232 | { | 232 | { |
233 | ATH5K_TRACE(ah->ah_sc); | 233 | ATH5K_TRACE(ah->ah_sc); |
234 | if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS), | 234 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS)) |
235 | ah->ah_turbo) <= timeout) | 235 | <= timeout) |
236 | return -EINVAL; | 236 | return -EINVAL; |
237 | 237 | ||
238 | AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS, | 238 | AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS, |
239 | ath5k_hw_htoclock(timeout, ah->ah_turbo)); | 239 | ath5k_hw_htoclock(ah, timeout)); |
240 | 240 | ||
241 | return 0; | 241 | return 0; |
242 | } | 242 | } |
243 | 243 | ||
244 | /** | 244 | /** |
245 | * ath5k_hw_htoclock - Translate usec to hw clock units | ||
246 | * | ||
247 | * @ah: The &struct ath5k_hw | ||
248 | * @usec: value in microseconds | ||
249 | */ | ||
250 | unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) | ||
251 | { | ||
252 | return usec * ath5k_hw_get_clockrate(ah); | ||
253 | } | ||
254 | |||
255 | /** | ||
256 | * ath5k_hw_clocktoh - Translate hw clock units to usec | ||
257 | * @clock: value in hw clock units | ||
258 | */ | ||
259 | unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock) | ||
260 | { | ||
261 | return clock / ath5k_hw_get_clockrate(ah); | ||
262 | } | ||
263 | |||
264 | /** | ||
265 | * ath5k_hw_get_clockrate - Get the clock rate for current mode | ||
266 | * | ||
267 | * @ah: The &struct ath5k_hw | ||
268 | */ | ||
269 | unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah) | ||
270 | { | ||
271 | struct ieee80211_channel *channel = ah->ah_current_channel; | ||
272 | int clock; | ||
273 | |||
274 | if (channel->hw_value & CHANNEL_5GHZ) | ||
275 | clock = 40; /* 802.11a */ | ||
276 | else if (channel->hw_value & CHANNEL_CCK) | ||
277 | clock = 22; /* 802.11b */ | ||
278 | else | ||
279 | clock = 44; /* 802.11g */ | ||
280 | |||
281 | /* Clock rate in turbo modes is twice the normal rate */ | ||
282 | if (channel->hw_value & CHANNEL_TURBO) | ||
283 | clock *= 2; | ||
284 | |||
285 | return clock; | ||
286 | } | ||
287 | |||
288 | /** | ||
289 | * ath5k_hw_get_default_slottime - Get the default slot time for current mode | ||
290 | * | ||
291 | * @ah: The &struct ath5k_hw | ||
292 | */ | ||
293 | unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) | ||
294 | { | ||
295 | struct ieee80211_channel *channel = ah->ah_current_channel; | ||
296 | |||
297 | if (channel->hw_value & CHANNEL_TURBO) | ||
298 | return 6; /* both turbo modes */ | ||
299 | |||
300 | if (channel->hw_value & CHANNEL_CCK) | ||
301 | return 20; /* 802.11b */ | ||
302 | |||
303 | return 9; /* 802.11 a/g */ | ||
304 | } | ||
305 | |||
306 | /** | ||
307 | * ath5k_hw_get_default_sifs - Get the default SIFS for current mode | ||
308 | * | ||
309 | * @ah: The &struct ath5k_hw | ||
310 | */ | ||
311 | unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) | ||
312 | { | ||
313 | struct ieee80211_channel *channel = ah->ah_current_channel; | ||
314 | |||
315 | if (channel->hw_value & CHANNEL_TURBO) | ||
316 | return 8; /* both turbo modes */ | ||
317 | |||
318 | if (channel->hw_value & CHANNEL_5GHZ) | ||
319 | return 16; /* 802.11a */ | ||
320 | |||
321 | return 10; /* 802.11 b/g */ | ||
322 | } | ||
323 | |||
324 | /** | ||
245 | * ath5k_hw_set_lladdr - Set station id | 325 | * ath5k_hw_set_lladdr - Set station id |
246 | * | 326 | * |
247 | * @ah: The &struct ath5k_hw | 327 | * @ah: The &struct ath5k_hw |
@@ -1050,3 +1130,24 @@ int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) | |||
1050 | return 0; | 1130 | return 0; |
1051 | } | 1131 | } |
1052 | 1132 | ||
1133 | /** | ||
1134 | * ath5k_hw_set_coverage_class - Set IEEE 802.11 coverage class | ||
1135 | * | ||
1136 | * @ah: The &struct ath5k_hw | ||
1137 | * @coverage_class: IEEE 802.11 coverage class number | ||
1138 | * | ||
1139 | * Sets slot time, ACK timeout and CTS timeout for given coverage class. | ||
1140 | */ | ||
1141 | void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class) | ||
1142 | { | ||
1143 | /* As defined by IEEE 802.11-2007 17.3.8.6 */ | ||
1144 | int slot_time = ath5k_hw_get_default_slottime(ah) + 3 * coverage_class; | ||
1145 | int ack_timeout = ath5k_hw_get_default_sifs(ah) + slot_time; | ||
1146 | int cts_timeout = ack_timeout; | ||
1147 | |||
1148 | ath5k_hw_set_slot_time(ah, slot_time); | ||
1149 | ath5k_hw_set_ack_timeout(ah, ack_timeout); | ||
1150 | ath5k_hw_set_cts_timeout(ah, cts_timeout); | ||
1151 | |||
1152 | ah->ah_coverage_class = coverage_class; | ||
1153 | } | ||
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index eeebb9aef206..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) | |
@@ -520,12 +521,16 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
520 | */ | 521 | */ |
521 | unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) | 522 | unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) |
522 | { | 523 | { |
524 | unsigned int slot_time_clock; | ||
525 | |||
523 | ATH5K_TRACE(ah->ah_sc); | 526 | ATH5K_TRACE(ah->ah_sc); |
527 | |||
524 | if (ah->ah_version == AR5K_AR5210) | 528 | if (ah->ah_version == AR5K_AR5210) |
525 | return ath5k_hw_clocktoh(ath5k_hw_reg_read(ah, | 529 | slot_time_clock = ath5k_hw_reg_read(ah, AR5K_SLOT_TIME); |
526 | AR5K_SLOT_TIME) & 0xffff, ah->ah_turbo); | ||
527 | else | 530 | else |
528 | return ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT) & 0xffff; | 531 | slot_time_clock = ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT); |
532 | |||
533 | return ath5k_hw_clocktoh(ah, slot_time_clock & 0xffff); | ||
529 | } | 534 | } |
530 | 535 | ||
531 | /* | 536 | /* |
@@ -533,15 +538,17 @@ unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) | |||
533 | */ | 538 | */ |
534 | int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) | 539 | int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) |
535 | { | 540 | { |
541 | u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time); | ||
542 | |||
536 | ATH5K_TRACE(ah->ah_sc); | 543 | ATH5K_TRACE(ah->ah_sc); |
537 | if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX) | 544 | |
545 | if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX) | ||
538 | return -EINVAL; | 546 | return -EINVAL; |
539 | 547 | ||
540 | if (ah->ah_version == AR5K_AR5210) | 548 | if (ah->ah_version == AR5K_AR5210) |
541 | ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time, | 549 | ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME); |
542 | ah->ah_turbo), AR5K_SLOT_TIME); | ||
543 | else | 550 | else |
544 | ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT); | 551 | ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT); |
545 | 552 | ||
546 | return 0; | 553 | return 0; |
547 | } | 554 | } |
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 62954fc77869..a35a7db0fc4c 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
@@ -60,12 +60,11 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, | |||
60 | !(channel->hw_value & CHANNEL_OFDM)); | 60 | !(channel->hw_value & CHANNEL_OFDM)); |
61 | 61 | ||
62 | /* Get coefficient | 62 | /* Get coefficient |
63 | * ALGO: coef = (5 * clock * carrier_freq) / 2) | 63 | * ALGO: coef = (5 * clock / carrier_freq) / 2 |
64 | * we scale coef by shifting clock value by 24 for | 64 | * we scale coef by shifting clock value by 24 for |
65 | * better precision since we use integers */ | 65 | * better precision since we use integers */ |
66 | /* TODO: Half/quarter rate */ | 66 | /* TODO: Half/quarter rate */ |
67 | clock = ath5k_hw_htoclock(1, channel->hw_value & CHANNEL_TURBO); | 67 | clock = (channel->hw_value & CHANNEL_TURBO) ? 80 : 40; |
68 | |||
69 | coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq; | 68 | coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq; |
70 | 69 | ||
71 | /* Get exponent | 70 | /* Get exponent |
@@ -1317,6 +1316,10 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1317 | /* Restore antenna mode */ | 1316 | /* Restore antenna mode */ |
1318 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); | 1317 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); |
1319 | 1318 | ||
1319 | /* Restore slot time and ACK timeouts */ | ||
1320 | if (ah->ah_coverage_class > 0) | ||
1321 | ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class); | ||
1322 | |||
1320 | /* | 1323 | /* |
1321 | * Configure QCUs/DCUs | 1324 | * Configure QCUs/DCUs |
1322 | */ | 1325 | */ |
@@ -1371,8 +1374,9 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1371 | * Set clocks to 32KHz operation and use an | 1374 | * Set clocks to 32KHz operation and use an |
1372 | * external 32KHz crystal when sleeping if one | 1375 | * external 32KHz crystal when sleeping if one |
1373 | * exists */ | 1376 | * exists */ |
1374 | if (ah->ah_version == AR5K_AR5212) | 1377 | if (ah->ah_version == AR5K_AR5212 && |
1375 | ath5k_hw_set_sleep_clock(ah, true); | 1378 | ah->ah_op_mode != NL80211_IFTYPE_AP) |
1379 | ath5k_hw_set_sleep_clock(ah, true); | ||
1376 | 1380 | ||
1377 | /* | 1381 | /* |
1378 | * Disable beacons and reset the register | 1382 | * Disable beacons and reset the register |
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 4985b2b1b0a9..6b50d5eb9ec3 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -1,4 +1,6 @@ | |||
1 | ath9k-y += beacon.o \ | 1 | ath9k-y += beacon.o \ |
2 | gpio.o \ | ||
3 | init.o \ | ||
2 | main.o \ | 4 | main.o \ |
3 | recv.o \ | 5 | recv.o \ |
4 | xmit.o \ | 6 | xmit.o \ |
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 329e6bc137ab..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 | ||
@@ -121,16 +113,19 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
121 | sc->mem = mem; | 113 | sc->mem = mem; |
122 | sc->irq = irq; | 114 | sc->irq = irq; |
123 | 115 | ||
124 | ret = ath_init_device(AR5416_AR9100_DEVID, sc, 0x0, &ath_ahb_bus_ops); | 116 | /* Will be cleared in ath9k_start() */ |
117 | sc->sc_flags |= SC_OP_INVALID; | ||
118 | |||
119 | ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc); | ||
125 | if (ret) { | 120 | if (ret) { |
126 | dev_err(&pdev->dev, "failed to initialize device\n"); | 121 | dev_err(&pdev->dev, "request_irq failed\n"); |
127 | goto err_free_hw; | 122 | goto err_free_hw; |
128 | } | 123 | } |
129 | 124 | ||
130 | ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc); | 125 | ret = ath9k_init_device(AR5416_AR9100_DEVID, sc, 0x0, &ath_ahb_bus_ops); |
131 | if (ret) { | 126 | if (ret) { |
132 | dev_err(&pdev->dev, "request_irq failed\n"); | 127 | dev_err(&pdev->dev, "failed to initialize device\n"); |
133 | goto err_detach; | 128 | goto err_irq; |
134 | } | 129 | } |
135 | 130 | ||
136 | ah = sc->sc_ah; | 131 | ah = sc->sc_ah; |
@@ -143,8 +138,8 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
143 | 138 | ||
144 | return 0; | 139 | return 0; |
145 | 140 | ||
146 | err_detach: | 141 | err_irq: |
147 | ath_detach(sc); | 142 | free_irq(irq, sc); |
148 | err_free_hw: | 143 | err_free_hw: |
149 | ieee80211_free_hw(hw); | 144 | ieee80211_free_hw(hw); |
150 | platform_set_drvdata(pdev, NULL); | 145 | platform_set_drvdata(pdev, NULL); |
@@ -161,8 +156,12 @@ static int ath_ahb_remove(struct platform_device *pdev) | |||
161 | if (hw) { | 156 | if (hw) { |
162 | struct ath_wiphy *aphy = hw->priv; | 157 | struct ath_wiphy *aphy = hw->priv; |
163 | struct ath_softc *sc = aphy->sc; | 158 | struct ath_softc *sc = aphy->sc; |
159 | void __iomem *mem = sc->mem; | ||
164 | 160 | ||
165 | ath_cleanup(sc); | 161 | ath9k_deinit_device(sc); |
162 | free_irq(sc->irq, sc); | ||
163 | ieee80211_free_hw(sc->hw); | ||
164 | iounmap(mem); | ||
166 | platform_set_drvdata(pdev, NULL); | 165 | platform_set_drvdata(pdev, NULL); |
167 | } | 166 | } |
168 | 167 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 1597a42731ed..83c7ea4c007f 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -267,6 +267,7 @@ void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
267 | u16 tid, u16 *ssn); | 267 | u16 tid, u16 *ssn); |
268 | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); | 268 | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); |
269 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); | 269 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); |
270 | void ath9k_enable_ps(struct ath_softc *sc); | ||
270 | 271 | ||
271 | /********/ | 272 | /********/ |
272 | /* VIFs */ | 273 | /* VIFs */ |
@@ -341,6 +342,12 @@ int ath_beaconq_config(struct ath_softc *sc); | |||
341 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ | 342 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ |
342 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ | 343 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ |
343 | 344 | ||
345 | void ath_ani_calibrate(unsigned long data); | ||
346 | |||
347 | /**********/ | ||
348 | /* BTCOEX */ | ||
349 | /**********/ | ||
350 | |||
344 | /* Defines the BT AR_BT_COEX_WGHT used */ | 351 | /* Defines the BT AR_BT_COEX_WGHT used */ |
345 | enum ath_stomp_type { | 352 | enum ath_stomp_type { |
346 | ATH_BTCOEX_NO_STOMP, | 353 | ATH_BTCOEX_NO_STOMP, |
@@ -358,9 +365,14 @@ struct ath_btcoex { | |||
358 | int bt_stomp_type; /* Types of BT stomping */ | 365 | int bt_stomp_type; /* Types of BT stomping */ |
359 | u32 btcoex_no_stomp; /* in usec */ | 366 | u32 btcoex_no_stomp; /* in usec */ |
360 | u32 btcoex_period; /* in usec */ | 367 | u32 btcoex_period; /* in usec */ |
368 | u32 btscan_no_stomp; /* in usec */ | ||
361 | struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */ | 369 | struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */ |
362 | }; | 370 | }; |
363 | 371 | ||
372 | int ath_init_btcoex_timer(struct ath_softc *sc); | ||
373 | void ath9k_btcoex_timer_resume(struct ath_softc *sc); | ||
374 | void ath9k_btcoex_timer_pause(struct ath_softc *sc); | ||
375 | |||
364 | /********************/ | 376 | /********************/ |
365 | /* LED Control */ | 377 | /* LED Control */ |
366 | /********************/ | 378 | /********************/ |
@@ -385,6 +397,9 @@ struct ath_led { | |||
385 | bool registered; | 397 | bool registered; |
386 | }; | 398 | }; |
387 | 399 | ||
400 | void ath_init_leds(struct ath_softc *sc); | ||
401 | void ath_deinit_leds(struct ath_softc *sc); | ||
402 | |||
388 | /********************/ | 403 | /********************/ |
389 | /* Main driver core */ | 404 | /* Main driver core */ |
390 | /********************/ | 405 | /********************/ |
@@ -403,26 +418,29 @@ struct ath_led { | |||
403 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ | 418 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ |
404 | #define ATH_RATE_DUMMY_MARKER 0 | 419 | #define ATH_RATE_DUMMY_MARKER 0 |
405 | 420 | ||
406 | #define SC_OP_INVALID BIT(0) | 421 | #define SC_OP_INVALID BIT(0) |
407 | #define SC_OP_BEACONS BIT(1) | 422 | #define SC_OP_BEACONS BIT(1) |
408 | #define SC_OP_RXAGGR BIT(2) | 423 | #define SC_OP_RXAGGR BIT(2) |
409 | #define SC_OP_TXAGGR BIT(3) | 424 | #define SC_OP_TXAGGR BIT(3) |
410 | #define SC_OP_FULL_RESET BIT(4) | 425 | #define SC_OP_FULL_RESET BIT(4) |
411 | #define SC_OP_PREAMBLE_SHORT BIT(5) | 426 | #define SC_OP_PREAMBLE_SHORT BIT(5) |
412 | #define SC_OP_PROTECT_ENABLE BIT(6) | 427 | #define SC_OP_PROTECT_ENABLE BIT(6) |
413 | #define SC_OP_RXFLUSH BIT(7) | 428 | #define SC_OP_RXFLUSH BIT(7) |
414 | #define SC_OP_LED_ASSOCIATED BIT(8) | 429 | #define SC_OP_LED_ASSOCIATED BIT(8) |
415 | #define SC_OP_WAIT_FOR_BEACON BIT(12) | 430 | #define SC_OP_LED_ON BIT(9) |
416 | #define SC_OP_LED_ON BIT(13) | 431 | #define SC_OP_SCANNING BIT(10) |
417 | #define SC_OP_SCANNING BIT(14) | 432 | #define SC_OP_TSF_RESET BIT(11) |
418 | #define SC_OP_TSF_RESET BIT(15) | 433 | #define SC_OP_BT_PRIORITY_DETECTED BIT(12) |
419 | #define SC_OP_WAIT_FOR_CAB BIT(16) | 434 | #define SC_OP_BT_SCAN BIT(13) |
420 | #define SC_OP_WAIT_FOR_PSPOLL_DATA BIT(17) | 435 | |
421 | #define SC_OP_WAIT_FOR_TX_ACK BIT(18) | 436 | /* Powersave flags */ |
422 | #define SC_OP_BEACON_SYNC BIT(19) | 437 | #define PS_WAIT_FOR_BEACON BIT(0) |
423 | #define SC_OP_BT_PRIORITY_DETECTED BIT(21) | 438 | #define PS_WAIT_FOR_CAB BIT(1) |
424 | #define SC_OP_NULLFUNC_COMPLETED BIT(22) | 439 | #define PS_WAIT_FOR_PSPOLL_DATA BIT(2) |
425 | #define SC_OP_PS_ENABLED BIT(23) | 440 | #define PS_WAIT_FOR_TX_ACK BIT(3) |
441 | #define PS_BEACON_SYNC BIT(4) | ||
442 | #define PS_NULLFUNC_COMPLETED BIT(5) | ||
443 | #define PS_ENABLED BIT(6) | ||
426 | 444 | ||
427 | struct ath_wiphy; | 445 | struct ath_wiphy; |
428 | struct ath_rate_table; | 446 | struct ath_rate_table; |
@@ -453,16 +471,17 @@ struct ath_softc { | |||
453 | int irq; | 471 | int irq; |
454 | spinlock_t sc_resetlock; | 472 | spinlock_t sc_resetlock; |
455 | spinlock_t sc_serial_rw; | 473 | spinlock_t sc_serial_rw; |
456 | spinlock_t ani_lock; | ||
457 | spinlock_t sc_pm_lock; | 474 | spinlock_t sc_pm_lock; |
458 | struct mutex mutex; | 475 | struct mutex mutex; |
459 | 476 | ||
460 | u32 intrstatus; | 477 | u32 intrstatus; |
461 | u32 sc_flags; /* SC_OP_* */ | 478 | u32 sc_flags; /* SC_OP_* */ |
479 | u16 ps_flags; /* PS_* */ | ||
462 | u16 curtxpow; | 480 | u16 curtxpow; |
463 | u8 nbcnvifs; | 481 | u8 nbcnvifs; |
464 | u16 nvifs; | 482 | u16 nvifs; |
465 | bool ps_enabled; | 483 | bool ps_enabled; |
484 | bool ps_idle; | ||
466 | unsigned long ps_usecount; | 485 | unsigned long ps_usecount; |
467 | enum ath9k_int imask; | 486 | enum ath9k_int imask; |
468 | 487 | ||
@@ -509,6 +528,7 @@ struct ath_wiphy { | |||
509 | int chan_is_ht; | 528 | int chan_is_ht; |
510 | }; | 529 | }; |
511 | 530 | ||
531 | void ath9k_tasklet(unsigned long data); | ||
512 | int ath_reset(struct ath_softc *sc, bool retry_tx); | 532 | int ath_reset(struct ath_softc *sc, bool retry_tx); |
513 | int ath_get_hal_qnum(u16 queue, struct ath_softc *sc); | 533 | int ath_get_hal_qnum(u16 queue, struct ath_softc *sc); |
514 | int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); | 534 | int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); |
@@ -519,21 +539,16 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz) | |||
519 | common->bus_ops->read_cachesize(common, csz); | 539 | common->bus_ops->read_cachesize(common, csz); |
520 | } | 540 | } |
521 | 541 | ||
522 | static inline void ath_bus_cleanup(struct ath_common *common) | ||
523 | { | ||
524 | common->bus_ops->cleanup(common); | ||
525 | } | ||
526 | |||
527 | extern struct ieee80211_ops ath9k_ops; | 542 | extern struct ieee80211_ops ath9k_ops; |
543 | extern int modparam_nohwcrypt; | ||
528 | 544 | ||
529 | irqreturn_t ath_isr(int irq, void *dev); | 545 | irqreturn_t ath_isr(int irq, void *dev); |
530 | void ath_cleanup(struct ath_softc *sc); | 546 | int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, |
531 | int ath_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, | ||
532 | const struct ath_bus_ops *bus_ops); | 547 | const struct ath_bus_ops *bus_ops); |
533 | void ath_detach(struct ath_softc *sc); | 548 | void ath9k_deinit_device(struct ath_softc *sc); |
534 | const char *ath_mac_bb_name(u32 mac_bb_version); | 549 | const char *ath_mac_bb_name(u32 mac_bb_version); |
535 | const char *ath_rf_name(u16 rf_version); | 550 | const char *ath_rf_name(u16 rf_version); |
536 | void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); | 551 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); |
537 | void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, | 552 | void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, |
538 | struct ath9k_channel *ichan); | 553 | struct ath9k_channel *ichan); |
539 | void ath_update_chainmask(struct ath_softc *sc, int is_ht); | 554 | void ath_update_chainmask(struct ath_softc *sc, int is_ht); |
@@ -542,6 +557,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
542 | 557 | ||
543 | void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw); | 558 | void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw); |
544 | void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw); | 559 | void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw); |
560 | bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode); | ||
545 | 561 | ||
546 | #ifdef CONFIG_PCI | 562 | #ifdef CONFIG_PCI |
547 | int ath_pci_init(void); | 563 | int ath_pci_init(void); |
@@ -583,4 +599,8 @@ void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue); | |||
583 | void ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue); | 599 | void ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue); |
584 | 600 | ||
585 | int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype); | 601 | int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype); |
602 | |||
603 | void ath_start_rfkill_poll(struct ath_softc *sc); | ||
604 | extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); | ||
605 | |||
586 | #endif /* ATH9K_H */ | 606 | #endif /* ATH9K_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 1660ef17aaf5..b4a31a43a62c 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -62,7 +62,7 @@ int ath_beaconq_config(struct ath_softc *sc) | |||
62 | * Beacons are always sent out at the lowest rate, and are not retried. | 62 | * Beacons are always sent out at the lowest rate, and are not retried. |
63 | */ | 63 | */ |
64 | static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, | 64 | static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, |
65 | struct ath_buf *bf) | 65 | struct ath_buf *bf, int rateidx) |
66 | { | 66 | { |
67 | struct sk_buff *skb = bf->bf_mpdu; | 67 | struct sk_buff *skb = bf->bf_mpdu; |
68 | struct ath_hw *ah = sc->sc_ah; | 68 | struct ath_hw *ah = sc->sc_ah; |
@@ -96,9 +96,9 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, | |||
96 | ds->ds_data = bf->bf_buf_addr; | 96 | ds->ds_data = bf->bf_buf_addr; |
97 | 97 | ||
98 | sband = &sc->sbands[common->hw->conf.channel->band]; | 98 | sband = &sc->sbands[common->hw->conf.channel->band]; |
99 | rate = sband->bitrates[0].hw_value; | 99 | rate = sband->bitrates[rateidx].hw_value; |
100 | if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) | 100 | if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) |
101 | rate |= sband->bitrates[0].hw_value_short; | 101 | rate |= sband->bitrates[rateidx].hw_value_short; |
102 | 102 | ||
103 | ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN, | 103 | ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN, |
104 | ATH9K_PKT_TYPE_BEACON, | 104 | ATH9K_PKT_TYPE_BEACON, |
@@ -206,7 +206,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, | |||
206 | } | 206 | } |
207 | } | 207 | } |
208 | 208 | ||
209 | ath_beacon_setup(sc, avp, bf); | 209 | ath_beacon_setup(sc, avp, bf, info->control.rates[0].idx); |
210 | 210 | ||
211 | while (skb) { | 211 | while (skb) { |
212 | ath_tx_cabq(hw, skb); | 212 | ath_tx_cabq(hw, skb); |
@@ -237,7 +237,7 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc, | |||
237 | bf = avp->av_bcbuf; | 237 | bf = avp->av_bcbuf; |
238 | skb = bf->bf_mpdu; | 238 | skb = bf->bf_mpdu; |
239 | 239 | ||
240 | ath_beacon_setup(sc, avp, bf); | 240 | ath_beacon_setup(sc, avp, bf, 0); |
241 | 241 | ||
242 | /* NB: caller is known to have already stopped tx dma */ | 242 | /* NB: caller is known to have already stopped tx dma */ |
243 | ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr); | 243 | ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr); |
@@ -480,7 +480,8 @@ void ath_beacon_tasklet(unsigned long data) | |||
480 | sc->beacon.updateslot = COMMIT; /* commit next beacon */ | 480 | sc->beacon.updateslot = COMMIT; /* commit next beacon */ |
481 | sc->beacon.slotupdate = slot; | 481 | sc->beacon.slotupdate = slot; |
482 | } else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) { | 482 | } else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) { |
483 | ath9k_hw_setslottime(sc->sc_ah, sc->beacon.slottime); | 483 | ah->slottime = sc->beacon.slottime; |
484 | ath9k_hw_init_global_settings(ah); | ||
484 | sc->beacon.updateslot = OK; | 485 | sc->beacon.updateslot = OK; |
485 | } | 486 | } |
486 | if (bfaddr != 0) { | 487 | if (bfaddr != 0) { |
@@ -525,16 +526,13 @@ static void ath_beacon_config_ap(struct ath_softc *sc, | |||
525 | { | 526 | { |
526 | u32 nexttbtt, intval; | 527 | u32 nexttbtt, intval; |
527 | 528 | ||
528 | /* Configure the timers only when the TSF has to be reset */ | ||
529 | |||
530 | if (!(sc->sc_flags & SC_OP_TSF_RESET)) | ||
531 | return; | ||
532 | |||
533 | /* NB: the beacon interval is kept internally in TU's */ | 529 | /* NB: the beacon interval is kept internally in TU's */ |
534 | intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; | 530 | intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; |
535 | intval /= ATH_BCBUF; /* for staggered beacons */ | 531 | intval /= ATH_BCBUF; /* for staggered beacons */ |
536 | nexttbtt = intval; | 532 | nexttbtt = intval; |
537 | intval |= ATH9K_BEACON_RESET_TSF; | 533 | |
534 | if (sc->sc_flags & SC_OP_TSF_RESET) | ||
535 | intval |= ATH9K_BEACON_RESET_TSF; | ||
538 | 536 | ||
539 | /* | 537 | /* |
540 | * In AP mode we enable the beacon timers and SWBA interrupts to | 538 | * In AP mode we enable the beacon timers and SWBA interrupts to |
@@ -576,6 +574,13 @@ static void ath_beacon_config_sta(struct ath_softc *sc, | |||
576 | u64 tsf; | 574 | u64 tsf; |
577 | int num_beacons, offset, dtim_dec_count, cfp_dec_count; | 575 | int num_beacons, offset, dtim_dec_count, cfp_dec_count; |
578 | 576 | ||
577 | /* No need to configure beacon if we are not associated */ | ||
578 | if (!common->curaid) { | ||
579 | ath_print(common, ATH_DBG_BEACON, | ||
580 | "STA is not yet associated..skipping beacon config\n"); | ||
581 | return; | ||
582 | } | ||
583 | |||
579 | memset(&bs, 0, sizeof(bs)); | 584 | memset(&bs, 0, sizeof(bs)); |
580 | intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; | 585 | intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; |
581 | 586 | ||
@@ -738,7 +743,6 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) | |||
738 | enum nl80211_iftype iftype; | 743 | enum nl80211_iftype iftype; |
739 | 744 | ||
740 | /* Setup the beacon configuration parameters */ | 745 | /* Setup the beacon configuration parameters */ |
741 | |||
742 | if (vif) { | 746 | if (vif) { |
743 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | 747 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
744 | 748 | ||
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 b66f72dbf7b9..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 = { |
@@ -289,23 +298,49 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, | |||
289 | if (sc->cur_rate_table == NULL) | 298 | if (sc->cur_rate_table == NULL) |
290 | return 0; | 299 | return 0; |
291 | 300 | ||
292 | max = 80 + sc->cur_rate_table->rate_cnt * 64; | 301 | max = 80 + sc->cur_rate_table->rate_cnt * 1024; |
293 | buf = kmalloc(max + 1, GFP_KERNEL); | 302 | buf = kmalloc(max + 1, GFP_KERNEL); |
294 | if (buf == NULL) | 303 | if (buf == NULL) |
295 | return 0; | 304 | return 0; |
296 | buf[max] = 0; | 305 | buf[max] = 0; |
297 | 306 | ||
298 | len += sprintf(buf, "%5s %15s %8s %9s %3s\n\n", "Rate", "Success", | 307 | len += sprintf(buf, "%6s %6s %6s " |
299 | "Retries", "XRetries", "PER"); | 308 | "%10s %10s %10s %10s\n", |
309 | "HT", "MCS", "Rate", | ||
310 | "Success", "Retries", "XRetries", "PER"); | ||
300 | 311 | ||
301 | for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) { | 312 | for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) { |
302 | u32 ratekbps = sc->cur_rate_table->info[i].ratekbps; | 313 | u32 ratekbps = sc->cur_rate_table->info[i].ratekbps; |
303 | struct ath_rc_stats *stats = &sc->debug.stats.rcstats[i]; | 314 | struct ath_rc_stats *stats = &sc->debug.stats.rcstats[i]; |
315 | char mcs[5]; | ||
316 | char htmode[5]; | ||
317 | int used_mcs = 0, used_htmode = 0; | ||
318 | |||
319 | if (WLAN_RC_PHY_HT(sc->cur_rate_table->info[i].phy)) { | ||
320 | used_mcs = snprintf(mcs, 5, "%d", | ||
321 | sc->cur_rate_table->info[i].ratecode); | ||
322 | |||
323 | if (WLAN_RC_PHY_40(sc->cur_rate_table->info[i].phy)) | ||
324 | used_htmode = snprintf(htmode, 5, "HT40"); | ||
325 | else if (WLAN_RC_PHY_20(sc->cur_rate_table->info[i].phy)) | ||
326 | used_htmode = snprintf(htmode, 5, "HT20"); | ||
327 | else | ||
328 | used_htmode = snprintf(htmode, 5, "????"); | ||
329 | } | ||
330 | |||
331 | mcs[used_mcs] = '\0'; | ||
332 | htmode[used_htmode] = '\0'; | ||
304 | 333 | ||
305 | len += snprintf(buf + len, max - len, | 334 | len += snprintf(buf + len, max - len, |
306 | "%3u.%d: %8u %8u %8u %8u\n", ratekbps / 1000, | 335 | "%6s %6s %3u.%d: " |
307 | (ratekbps % 1000) / 100, stats->success, | 336 | "%10u %10u %10u %10u\n", |
308 | stats->retries, stats->xretries, | 337 | htmode, |
338 | mcs, | ||
339 | ratekbps / 1000, | ||
340 | (ratekbps % 1000) / 100, | ||
341 | stats->success, | ||
342 | stats->retries, | ||
343 | stats->xretries, | ||
309 | stats->per); | 344 | stats->per); |
310 | } | 345 | } |
311 | 346 | ||
@@ -554,6 +589,116 @@ static const struct file_operations fops_xmit = { | |||
554 | .owner = THIS_MODULE | 589 | .owner = THIS_MODULE |
555 | }; | 590 | }; |
556 | 591 | ||
592 | static ssize_t read_file_recv(struct file *file, char __user *user_buf, | ||
593 | size_t count, loff_t *ppos) | ||
594 | { | ||
595 | #define PHY_ERR(s, p) \ | ||
596 | len += snprintf(buf + len, size - len, "%18s : %10u\n", s, \ | ||
597 | sc->debug.stats.rxstats.phy_err_stats[p]); | ||
598 | |||
599 | struct ath_softc *sc = file->private_data; | ||
600 | char *buf; | ||
601 | unsigned int len = 0, size = 1152; | ||
602 | ssize_t retval = 0; | ||
603 | |||
604 | buf = kzalloc(size, GFP_KERNEL); | ||
605 | if (buf == NULL) | ||
606 | return 0; | ||
607 | |||
608 | len += snprintf(buf + len, size - len, | ||
609 | "%18s : %10u\n", "CRC ERR", | ||
610 | sc->debug.stats.rxstats.crc_err); | ||
611 | len += snprintf(buf + len, size - len, | ||
612 | "%18s : %10u\n", "DECRYPT CRC ERR", | ||
613 | sc->debug.stats.rxstats.decrypt_crc_err); | ||
614 | len += snprintf(buf + len, size - len, | ||
615 | "%18s : %10u\n", "PHY ERR", | ||
616 | sc->debug.stats.rxstats.phy_err); | ||
617 | len += snprintf(buf + len, size - len, | ||
618 | "%18s : %10u\n", "MIC ERR", | ||
619 | sc->debug.stats.rxstats.mic_err); | ||
620 | len += snprintf(buf + len, size - len, | ||
621 | "%18s : %10u\n", "PRE-DELIM CRC ERR", | ||
622 | sc->debug.stats.rxstats.pre_delim_crc_err); | ||
623 | len += snprintf(buf + len, size - len, | ||
624 | "%18s : %10u\n", "POST-DELIM CRC ERR", | ||
625 | sc->debug.stats.rxstats.post_delim_crc_err); | ||
626 | len += snprintf(buf + len, size - len, | ||
627 | "%18s : %10u\n", "DECRYPT BUSY ERR", | ||
628 | sc->debug.stats.rxstats.decrypt_busy_err); | ||
629 | |||
630 | PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN); | ||
631 | PHY_ERR("TIMING", ATH9K_PHYERR_TIMING); | ||
632 | PHY_ERR("PARITY", ATH9K_PHYERR_PARITY); | ||
633 | PHY_ERR("RATE", ATH9K_PHYERR_RATE); | ||
634 | PHY_ERR("LENGTH", ATH9K_PHYERR_LENGTH); | ||
635 | PHY_ERR("RADAR", ATH9K_PHYERR_RADAR); | ||
636 | PHY_ERR("SERVICE", ATH9K_PHYERR_SERVICE); | ||
637 | PHY_ERR("TOR", ATH9K_PHYERR_TOR); | ||
638 | PHY_ERR("OFDM-TIMING", ATH9K_PHYERR_OFDM_TIMING); | ||
639 | PHY_ERR("OFDM-SIGNAL-PARITY", ATH9K_PHYERR_OFDM_SIGNAL_PARITY); | ||
640 | PHY_ERR("OFDM-RATE", ATH9K_PHYERR_OFDM_RATE_ILLEGAL); | ||
641 | PHY_ERR("OFDM-LENGTH", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL); | ||
642 | PHY_ERR("OFDM-POWER-DROP", ATH9K_PHYERR_OFDM_POWER_DROP); | ||
643 | PHY_ERR("OFDM-SERVICE", ATH9K_PHYERR_OFDM_SERVICE); | ||
644 | PHY_ERR("OFDM-RESTART", ATH9K_PHYERR_OFDM_RESTART); | ||
645 | PHY_ERR("FALSE-RADAR-EXT", ATH9K_PHYERR_FALSE_RADAR_EXT); | ||
646 | PHY_ERR("CCK-TIMING", ATH9K_PHYERR_CCK_TIMING); | ||
647 | PHY_ERR("CCK-HEADER-CRC", ATH9K_PHYERR_CCK_HEADER_CRC); | ||
648 | PHY_ERR("CCK-RATE", ATH9K_PHYERR_CCK_RATE_ILLEGAL); | ||
649 | PHY_ERR("CCK-SERVICE", ATH9K_PHYERR_CCK_SERVICE); | ||
650 | PHY_ERR("CCK-RESTART", ATH9K_PHYERR_CCK_RESTART); | ||
651 | PHY_ERR("CCK-LENGTH", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL); | ||
652 | PHY_ERR("CCK-POWER-DROP", ATH9K_PHYERR_CCK_POWER_DROP); | ||
653 | PHY_ERR("HT-CRC", ATH9K_PHYERR_HT_CRC_ERROR); | ||
654 | PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); | ||
655 | PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL); | ||
656 | |||
657 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
658 | kfree(buf); | ||
659 | |||
660 | return retval; | ||
661 | |||
662 | #undef PHY_ERR | ||
663 | } | ||
664 | |||
665 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_buf *bf) | ||
666 | { | ||
667 | #define RX_STAT_INC(c) sc->debug.stats.rxstats.c++ | ||
668 | #define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++ | ||
669 | |||
670 | struct ath_desc *ds = bf->bf_desc; | ||
671 | u32 phyerr; | ||
672 | |||
673 | if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC) | ||
674 | RX_STAT_INC(crc_err); | ||
675 | if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) | ||
676 | RX_STAT_INC(decrypt_crc_err); | ||
677 | if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) | ||
678 | RX_STAT_INC(mic_err); | ||
679 | if (ds->ds_rxstat.rs_status & ATH9K_RX_DELIM_CRC_PRE) | ||
680 | RX_STAT_INC(pre_delim_crc_err); | ||
681 | if (ds->ds_rxstat.rs_status & ATH9K_RX_DELIM_CRC_POST) | ||
682 | RX_STAT_INC(post_delim_crc_err); | ||
683 | if (ds->ds_rxstat.rs_status & ATH9K_RX_DECRYPT_BUSY) | ||
684 | RX_STAT_INC(decrypt_busy_err); | ||
685 | |||
686 | if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY) { | ||
687 | RX_STAT_INC(phy_err); | ||
688 | phyerr = ds->ds_rxstat.rs_phyerr & 0x24; | ||
689 | RX_PHY_ERR_INC(phyerr); | ||
690 | } | ||
691 | |||
692 | #undef RX_STAT_INC | ||
693 | #undef RX_PHY_ERR_INC | ||
694 | } | ||
695 | |||
696 | static const struct file_operations fops_recv = { | ||
697 | .read = read_file_recv, | ||
698 | .open = ath9k_debugfs_open, | ||
699 | .owner = THIS_MODULE | ||
700 | }; | ||
701 | |||
557 | int ath9k_init_debug(struct ath_hw *ah) | 702 | int ath9k_init_debug(struct ath_hw *ah) |
558 | { | 703 | { |
559 | struct ath_common *common = ath9k_hw_common(ah); | 704 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -606,6 +751,13 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
606 | if (!sc->debug.debugfs_xmit) | 751 | if (!sc->debug.debugfs_xmit) |
607 | goto err; | 752 | goto err; |
608 | 753 | ||
754 | sc->debug.debugfs_recv = debugfs_create_file("recv", | ||
755 | S_IRUSR, | ||
756 | sc->debug.debugfs_phy, | ||
757 | sc, &fops_recv); | ||
758 | if (!sc->debug.debugfs_recv) | ||
759 | goto err; | ||
760 | |||
609 | return 0; | 761 | return 0; |
610 | err: | 762 | err: |
611 | ath9k_exit_debug(ah); | 763 | ath9k_exit_debug(ah); |
@@ -617,6 +769,7 @@ void ath9k_exit_debug(struct ath_hw *ah) | |||
617 | struct ath_common *common = ath9k_hw_common(ah); | 769 | struct ath_common *common = ath9k_hw_common(ah); |
618 | struct ath_softc *sc = (struct ath_softc *) common->priv; | 770 | struct ath_softc *sc = (struct ath_softc *) common->priv; |
619 | 771 | ||
772 | debugfs_remove(sc->debug.debugfs_recv); | ||
620 | debugfs_remove(sc->debug.debugfs_xmit); | 773 | debugfs_remove(sc->debug.debugfs_xmit); |
621 | debugfs_remove(sc->debug.debugfs_wiphy); | 774 | debugfs_remove(sc->debug.debugfs_wiphy); |
622 | debugfs_remove(sc->debug.debugfs_rcstat); | 775 | debugfs_remove(sc->debug.debugfs_rcstat); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 536663e3ee11..86780e68b31e 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -116,10 +116,35 @@ struct ath_tx_stats { | |||
116 | u32 delim_underrun; | 116 | u32 delim_underrun; |
117 | }; | 117 | }; |
118 | 118 | ||
119 | /** | ||
120 | * struct ath_rx_stats - RX Statistics | ||
121 | * @crc_err: No. of frames with incorrect CRC value | ||
122 | * @decrypt_crc_err: No. of frames whose CRC check failed after | ||
123 | decryption process completed | ||
124 | * @phy_err: No. of frames whose reception failed because the PHY | ||
125 | encountered an error | ||
126 | * @mic_err: No. of frames with incorrect TKIP MIC verification failure | ||
127 | * @pre_delim_crc_err: Pre-Frame delimiter CRC error detections | ||
128 | * @post_delim_crc_err: Post-Frame delimiter CRC error detections | ||
129 | * @decrypt_busy_err: Decryption interruptions counter | ||
130 | * @phy_err_stats: Individual PHY error statistics | ||
131 | */ | ||
132 | struct ath_rx_stats { | ||
133 | u32 crc_err; | ||
134 | u32 decrypt_crc_err; | ||
135 | u32 phy_err; | ||
136 | u32 mic_err; | ||
137 | u32 pre_delim_crc_err; | ||
138 | u32 post_delim_crc_err; | ||
139 | u32 decrypt_busy_err; | ||
140 | u32 phy_err_stats[ATH9K_PHYERR_MAX]; | ||
141 | }; | ||
142 | |||
119 | struct ath_stats { | 143 | struct ath_stats { |
120 | struct ath_interrupt_stats istats; | 144 | struct ath_interrupt_stats istats; |
121 | struct ath_rc_stats rcstats[RATE_TABLE_SIZE]; | 145 | struct ath_rc_stats rcstats[RATE_TABLE_SIZE]; |
122 | struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES]; | 146 | struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES]; |
147 | struct ath_rx_stats rxstats; | ||
123 | }; | 148 | }; |
124 | 149 | ||
125 | struct ath9k_debug { | 150 | struct ath9k_debug { |
@@ -130,6 +155,7 @@ struct ath9k_debug { | |||
130 | struct dentry *debugfs_rcstat; | 155 | struct dentry *debugfs_rcstat; |
131 | struct dentry *debugfs_wiphy; | 156 | struct dentry *debugfs_wiphy; |
132 | struct dentry *debugfs_xmit; | 157 | struct dentry *debugfs_xmit; |
158 | struct dentry *debugfs_recv; | ||
133 | struct ath_stats stats; | 159 | struct ath_stats stats; |
134 | }; | 160 | }; |
135 | 161 | ||
@@ -142,6 +168,7 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); | |||
142 | void ath_debug_stat_rc(struct ath_softc *sc, int final_rate); | 168 | void ath_debug_stat_rc(struct ath_softc *sc, int final_rate); |
143 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, | 169 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, |
144 | struct ath_buf *bf); | 170 | struct ath_buf *bf); |
171 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_buf *bf); | ||
145 | void ath_debug_stat_retries(struct ath_softc *sc, int rix, | 172 | void ath_debug_stat_retries(struct ath_softc *sc, int rix, |
146 | int xretries, int retries, u8 per); | 173 | int xretries, int retries, u8 per); |
147 | 174 | ||
@@ -181,6 +208,11 @@ static inline void ath_debug_stat_tx(struct ath_softc *sc, | |||
181 | { | 208 | { |
182 | } | 209 | } |
183 | 210 | ||
211 | static inline void ath_debug_stat_rx(struct ath_softc *sc, | ||
212 | struct ath_buf *bf) | ||
213 | { | ||
214 | } | ||
215 | |||
184 | static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix, | 216 | static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix, |
185 | int xretries, int retries, u8 per) | 217 | int xretries, int retries, u8 per) |
186 | { | 218 | { |
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c new file mode 100644 index 000000000000..deab8beb0680 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/gpio.c | |||
@@ -0,0 +1,442 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "ath9k.h" | ||
18 | |||
19 | /********************************/ | ||
20 | /* LED functions */ | ||
21 | /********************************/ | ||
22 | |||
23 | static void ath_led_blink_work(struct work_struct *work) | ||
24 | { | ||
25 | struct ath_softc *sc = container_of(work, struct ath_softc, | ||
26 | ath_led_blink_work.work); | ||
27 | |||
28 | if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED)) | ||
29 | return; | ||
30 | |||
31 | if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) || | ||
32 | (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) | ||
33 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); | ||
34 | else | ||
35 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, | ||
36 | (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0); | ||
37 | |||
38 | ieee80211_queue_delayed_work(sc->hw, | ||
39 | &sc->ath_led_blink_work, | ||
40 | (sc->sc_flags & SC_OP_LED_ON) ? | ||
41 | msecs_to_jiffies(sc->led_off_duration) : | ||
42 | msecs_to_jiffies(sc->led_on_duration)); | ||
43 | |||
44 | sc->led_on_duration = sc->led_on_cnt ? | ||
45 | max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) : | ||
46 | ATH_LED_ON_DURATION_IDLE; | ||
47 | sc->led_off_duration = sc->led_off_cnt ? | ||
48 | max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10) : | ||
49 | ATH_LED_OFF_DURATION_IDLE; | ||
50 | sc->led_on_cnt = sc->led_off_cnt = 0; | ||
51 | if (sc->sc_flags & SC_OP_LED_ON) | ||
52 | sc->sc_flags &= ~SC_OP_LED_ON; | ||
53 | else | ||
54 | sc->sc_flags |= SC_OP_LED_ON; | ||
55 | } | ||
56 | |||
57 | static void ath_led_brightness(struct led_classdev *led_cdev, | ||
58 | enum led_brightness brightness) | ||
59 | { | ||
60 | struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev); | ||
61 | struct ath_softc *sc = led->sc; | ||
62 | |||
63 | switch (brightness) { | ||
64 | case LED_OFF: | ||
65 | if (led->led_type == ATH_LED_ASSOC || | ||
66 | led->led_type == ATH_LED_RADIO) { | ||
67 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, | ||
68 | (led->led_type == ATH_LED_RADIO)); | ||
69 | sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; | ||
70 | if (led->led_type == ATH_LED_RADIO) | ||
71 | sc->sc_flags &= ~SC_OP_LED_ON; | ||
72 | } else { | ||
73 | sc->led_off_cnt++; | ||
74 | } | ||
75 | break; | ||
76 | case LED_FULL: | ||
77 | if (led->led_type == ATH_LED_ASSOC) { | ||
78 | sc->sc_flags |= SC_OP_LED_ASSOCIATED; | ||
79 | ieee80211_queue_delayed_work(sc->hw, | ||
80 | &sc->ath_led_blink_work, 0); | ||
81 | } else if (led->led_type == ATH_LED_RADIO) { | ||
82 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); | ||
83 | sc->sc_flags |= SC_OP_LED_ON; | ||
84 | } else { | ||
85 | sc->led_on_cnt++; | ||
86 | } | ||
87 | break; | ||
88 | default: | ||
89 | break; | ||
90 | } | ||
91 | } | ||
92 | |||
93 | static int ath_register_led(struct ath_softc *sc, struct ath_led *led, | ||
94 | char *trigger) | ||
95 | { | ||
96 | int ret; | ||
97 | |||
98 | led->sc = sc; | ||
99 | led->led_cdev.name = led->name; | ||
100 | led->led_cdev.default_trigger = trigger; | ||
101 | led->led_cdev.brightness_set = ath_led_brightness; | ||
102 | |||
103 | ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev); | ||
104 | if (ret) | ||
105 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, | ||
106 | "Failed to register led:%s", led->name); | ||
107 | else | ||
108 | led->registered = 1; | ||
109 | return ret; | ||
110 | } | ||
111 | |||
112 | static void ath_unregister_led(struct ath_led *led) | ||
113 | { | ||
114 | if (led->registered) { | ||
115 | led_classdev_unregister(&led->led_cdev); | ||
116 | led->registered = 0; | ||
117 | } | ||
118 | } | ||
119 | |||
120 | void ath_deinit_leds(struct ath_softc *sc) | ||
121 | { | ||
122 | ath_unregister_led(&sc->assoc_led); | ||
123 | sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; | ||
124 | ath_unregister_led(&sc->tx_led); | ||
125 | ath_unregister_led(&sc->rx_led); | ||
126 | ath_unregister_led(&sc->radio_led); | ||
127 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); | ||
128 | } | ||
129 | |||
130 | void ath_init_leds(struct ath_softc *sc) | ||
131 | { | ||
132 | char *trigger; | ||
133 | int ret; | ||
134 | |||
135 | if (AR_SREV_9287(sc->sc_ah)) | ||
136 | sc->sc_ah->led_pin = ATH_LED_PIN_9287; | ||
137 | else | ||
138 | sc->sc_ah->led_pin = ATH_LED_PIN_DEF; | ||
139 | |||
140 | /* Configure gpio 1 for output */ | ||
141 | ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, | ||
142 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
143 | /* LED off, active low */ | ||
144 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); | ||
145 | |||
146 | INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work); | ||
147 | |||
148 | trigger = ieee80211_get_radio_led_name(sc->hw); | ||
149 | snprintf(sc->radio_led.name, sizeof(sc->radio_led.name), | ||
150 | "ath9k-%s::radio", wiphy_name(sc->hw->wiphy)); | ||
151 | ret = ath_register_led(sc, &sc->radio_led, trigger); | ||
152 | sc->radio_led.led_type = ATH_LED_RADIO; | ||
153 | if (ret) | ||
154 | goto fail; | ||
155 | |||
156 | trigger = ieee80211_get_assoc_led_name(sc->hw); | ||
157 | snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name), | ||
158 | "ath9k-%s::assoc", wiphy_name(sc->hw->wiphy)); | ||
159 | ret = ath_register_led(sc, &sc->assoc_led, trigger); | ||
160 | sc->assoc_led.led_type = ATH_LED_ASSOC; | ||
161 | if (ret) | ||
162 | goto fail; | ||
163 | |||
164 | trigger = ieee80211_get_tx_led_name(sc->hw); | ||
165 | snprintf(sc->tx_led.name, sizeof(sc->tx_led.name), | ||
166 | "ath9k-%s::tx", wiphy_name(sc->hw->wiphy)); | ||
167 | ret = ath_register_led(sc, &sc->tx_led, trigger); | ||
168 | sc->tx_led.led_type = ATH_LED_TX; | ||
169 | if (ret) | ||
170 | goto fail; | ||
171 | |||
172 | trigger = ieee80211_get_rx_led_name(sc->hw); | ||
173 | snprintf(sc->rx_led.name, sizeof(sc->rx_led.name), | ||
174 | "ath9k-%s::rx", wiphy_name(sc->hw->wiphy)); | ||
175 | ret = ath_register_led(sc, &sc->rx_led, trigger); | ||
176 | sc->rx_led.led_type = ATH_LED_RX; | ||
177 | if (ret) | ||
178 | goto fail; | ||
179 | |||
180 | return; | ||
181 | |||
182 | fail: | ||
183 | cancel_delayed_work_sync(&sc->ath_led_blink_work); | ||
184 | ath_deinit_leds(sc); | ||
185 | } | ||
186 | |||
187 | /*******************/ | ||
188 | /* Rfkill */ | ||
189 | /*******************/ | ||
190 | |||
191 | static bool ath_is_rfkill_set(struct ath_softc *sc) | ||
192 | { | ||
193 | struct ath_hw *ah = sc->sc_ah; | ||
194 | |||
195 | return ath9k_hw_gpio_get(ah, ah->rfkill_gpio) == | ||
196 | ah->rfkill_polarity; | ||
197 | } | ||
198 | |||
199 | void ath9k_rfkill_poll_state(struct ieee80211_hw *hw) | ||
200 | { | ||
201 | struct ath_wiphy *aphy = hw->priv; | ||
202 | struct ath_softc *sc = aphy->sc; | ||
203 | bool blocked = !!ath_is_rfkill_set(sc); | ||
204 | |||
205 | wiphy_rfkill_set_hw_state(hw->wiphy, blocked); | ||
206 | } | ||
207 | |||
208 | void ath_start_rfkill_poll(struct ath_softc *sc) | ||
209 | { | ||
210 | struct ath_hw *ah = sc->sc_ah; | ||
211 | |||
212 | if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) | ||
213 | wiphy_rfkill_start_polling(sc->hw->wiphy); | ||
214 | } | ||
215 | |||
216 | /******************/ | ||
217 | /* BTCOEX */ | ||
218 | /******************/ | ||
219 | |||
220 | /* | ||
221 | * Detects if there is any priority bt traffic | ||
222 | */ | ||
223 | static void ath_detect_bt_priority(struct ath_softc *sc) | ||
224 | { | ||
225 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
226 | struct ath_hw *ah = sc->sc_ah; | ||
227 | |||
228 | if (ath9k_hw_gpio_get(sc->sc_ah, ah->btcoex_hw.btpriority_gpio)) | ||
229 | btcoex->bt_priority_cnt++; | ||
230 | |||
231 | if (time_after(jiffies, btcoex->bt_priority_time + | ||
232 | msecs_to_jiffies(ATH_BT_PRIORITY_TIME_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) { | ||
241 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX, | ||
242 | "BT priority traffic detected"); | ||
243 | sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED; | ||
244 | } | ||
245 | |||
246 | btcoex->bt_priority_cnt = 0; | ||
247 | btcoex->bt_priority_time = jiffies; | ||
248 | } | ||
249 | } | ||
250 | |||
251 | /* | ||
252 | * Configures appropriate weight based on stomp type. | ||
253 | */ | ||
254 | static void ath9k_btcoex_bt_stomp(struct ath_softc *sc, | ||
255 | enum ath_stomp_type stomp_type) | ||
256 | { | ||
257 | struct ath_hw *ah = sc->sc_ah; | ||
258 | |||
259 | switch (stomp_type) { | ||
260 | case ATH_BTCOEX_STOMP_ALL: | ||
261 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
262 | AR_STOMP_ALL_WLAN_WGHT); | ||
263 | break; | ||
264 | case ATH_BTCOEX_STOMP_LOW: | ||
265 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
266 | AR_STOMP_LOW_WLAN_WGHT); | ||
267 | break; | ||
268 | case ATH_BTCOEX_STOMP_NONE: | ||
269 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
270 | AR_STOMP_NONE_WLAN_WGHT); | ||
271 | break; | ||
272 | default: | ||
273 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | ||
274 | "Invalid Stomptype\n"); | ||
275 | break; | ||
276 | } | ||
277 | |||
278 | ath9k_hw_btcoex_enable(ah); | ||
279 | } | ||
280 | |||
281 | static void ath9k_gen_timer_start(struct ath_hw *ah, | ||
282 | struct ath_gen_timer *timer, | ||
283 | u32 timer_next, | ||
284 | u32 timer_period) | ||
285 | { | ||
286 | struct ath_common *common = ath9k_hw_common(ah); | ||
287 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
288 | |||
289 | ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period); | ||
290 | |||
291 | if ((sc->imask & ATH9K_INT_GENTIMER) == 0) { | ||
292 | ath9k_hw_set_interrupts(ah, 0); | ||
293 | sc->imask |= ATH9K_INT_GENTIMER; | ||
294 | ath9k_hw_set_interrupts(ah, sc->imask); | ||
295 | } | ||
296 | } | ||
297 | |||
298 | static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) | ||
299 | { | ||
300 | struct ath_common *common = ath9k_hw_common(ah); | ||
301 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
302 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; | ||
303 | |||
304 | ath9k_hw_gen_timer_stop(ah, timer); | ||
305 | |||
306 | /* if no timer is enabled, turn off interrupt mask */ | ||
307 | if (timer_table->timer_mask.val == 0) { | ||
308 | ath9k_hw_set_interrupts(ah, 0); | ||
309 | sc->imask &= ~ATH9K_INT_GENTIMER; | ||
310 | ath9k_hw_set_interrupts(ah, sc->imask); | ||
311 | } | ||
312 | } | ||
313 | |||
314 | /* | ||
315 | * This is the master bt coex timer which runs for every | ||
316 | * 45ms, bt traffic will be given priority during 55% of this | ||
317 | * period while wlan gets remaining 45% | ||
318 | */ | ||
319 | static void ath_btcoex_period_timer(unsigned long data) | ||
320 | { | ||
321 | struct ath_softc *sc = (struct ath_softc *) data; | ||
322 | struct ath_hw *ah = sc->sc_ah; | ||
323 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
324 | u32 timer_period; | ||
325 | bool is_btscan; | ||
326 | |||
327 | ath_detect_bt_priority(sc); | ||
328 | |||
329 | is_btscan = sc->sc_flags & SC_OP_BT_SCAN; | ||
330 | |||
331 | spin_lock_bh(&btcoex->btcoex_lock); | ||
332 | |||
333 | ath9k_btcoex_bt_stomp(sc, is_btscan ? ATH_BTCOEX_STOMP_ALL : | ||
334 | btcoex->bt_stomp_type); | ||
335 | |||
336 | spin_unlock_bh(&btcoex->btcoex_lock); | ||
337 | |||
338 | if (btcoex->btcoex_period != btcoex->btcoex_no_stomp) { | ||
339 | if (btcoex->hw_timer_enabled) | ||
340 | ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); | ||
341 | |||
342 | timer_period = is_btscan ? btcoex->btscan_no_stomp : | ||
343 | btcoex->btcoex_no_stomp; | ||
344 | ath9k_gen_timer_start(ah, | ||
345 | btcoex->no_stomp_timer, | ||
346 | (ath9k_hw_gettsf32(ah) + | ||
347 | timer_period), timer_period * 10); | ||
348 | btcoex->hw_timer_enabled = true; | ||
349 | } | ||
350 | |||
351 | mod_timer(&btcoex->period_timer, jiffies + | ||
352 | msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD)); | ||
353 | } | ||
354 | |||
355 | /* | ||
356 | * Generic tsf based hw timer which configures weight | ||
357 | * registers to time slice between wlan and bt traffic | ||
358 | */ | ||
359 | static void ath_btcoex_no_stomp_timer(void *arg) | ||
360 | { | ||
361 | struct ath_softc *sc = (struct ath_softc *)arg; | ||
362 | struct ath_hw *ah = sc->sc_ah; | ||
363 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
364 | bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN; | ||
365 | |||
366 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | ||
367 | "no stomp timer running \n"); | ||
368 | |||
369 | spin_lock_bh(&btcoex->btcoex_lock); | ||
370 | |||
371 | if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) | ||
372 | ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_NONE); | ||
373 | else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) | ||
374 | ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_LOW); | ||
375 | |||
376 | spin_unlock_bh(&btcoex->btcoex_lock); | ||
377 | } | ||
378 | |||
379 | int ath_init_btcoex_timer(struct ath_softc *sc) | ||
380 | { | ||
381 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
382 | |||
383 | btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000; | ||
384 | btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * | ||
385 | btcoex->btcoex_period / 100; | ||
386 | btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) * | ||
387 | btcoex->btcoex_period / 100; | ||
388 | |||
389 | setup_timer(&btcoex->period_timer, ath_btcoex_period_timer, | ||
390 | (unsigned long) sc); | ||
391 | |||
392 | spin_lock_init(&btcoex->btcoex_lock); | ||
393 | |||
394 | btcoex->no_stomp_timer = ath_gen_timer_alloc(sc->sc_ah, | ||
395 | ath_btcoex_no_stomp_timer, | ||
396 | ath_btcoex_no_stomp_timer, | ||
397 | (void *) sc, AR_FIRST_NDP_TIMER); | ||
398 | |||
399 | if (!btcoex->no_stomp_timer) | ||
400 | return -ENOMEM; | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | /* | ||
406 | * (Re)start btcoex timers | ||
407 | */ | ||
408 | void ath9k_btcoex_timer_resume(struct ath_softc *sc) | ||
409 | { | ||
410 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
411 | struct ath_hw *ah = sc->sc_ah; | ||
412 | |||
413 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | ||
414 | "Starting btcoex timers"); | ||
415 | |||
416 | /* make sure duty cycle timer is also stopped when resuming */ | ||
417 | if (btcoex->hw_timer_enabled) | ||
418 | ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); | ||
419 | |||
420 | btcoex->bt_priority_cnt = 0; | ||
421 | btcoex->bt_priority_time = jiffies; | ||
422 | sc->sc_flags &= ~(SC_OP_BT_PRIORITY_DETECTED | SC_OP_BT_SCAN); | ||
423 | |||
424 | mod_timer(&btcoex->period_timer, jiffies); | ||
425 | } | ||
426 | |||
427 | |||
428 | /* | ||
429 | * Pause btcoex timer and bt duty cycle timer | ||
430 | */ | ||
431 | void ath9k_btcoex_timer_pause(struct ath_softc *sc) | ||
432 | { | ||
433 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
434 | struct ath_hw *ah = sc->sc_ah; | ||
435 | |||
436 | del_timer_sync(&btcoex->period_timer); | ||
437 | |||
438 | if (btcoex->hw_timer_enabled) | ||
439 | ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); | ||
440 | |||
441 | btcoex->hw_timer_enabled = false; | ||
442 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index ae371448b5a0..f00f5c744f48 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -52,28 +52,6 @@ module_exit(ath9k_exit); | |||
52 | /* Helper Functions */ | 52 | /* Helper Functions */ |
53 | /********************/ | 53 | /********************/ |
54 | 54 | ||
55 | static u32 ath9k_hw_mac_usec(struct ath_hw *ah, u32 clks) | ||
56 | { | ||
57 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | ||
58 | |||
59 | if (!ah->curchan) /* should really check for CCK instead */ | ||
60 | return clks / ATH9K_CLOCK_RATE_CCK; | ||
61 | if (conf->channel->band == IEEE80211_BAND_2GHZ) | ||
62 | return clks / ATH9K_CLOCK_RATE_2GHZ_OFDM; | ||
63 | |||
64 | return clks / ATH9K_CLOCK_RATE_5GHZ_OFDM; | ||
65 | } | ||
66 | |||
67 | static u32 ath9k_hw_mac_to_usec(struct ath_hw *ah, u32 clks) | ||
68 | { | ||
69 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | ||
70 | |||
71 | if (conf_is_ht40(conf)) | ||
72 | return ath9k_hw_mac_usec(ah, clks) / 2; | ||
73 | else | ||
74 | return ath9k_hw_mac_usec(ah, clks); | ||
75 | } | ||
76 | |||
77 | static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs) | 55 | static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs) |
78 | { | 56 | { |
79 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | 57 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; |
@@ -343,30 +321,6 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) | |||
343 | return true; | 321 | return true; |
344 | } | 322 | } |
345 | 323 | ||
346 | static const char *ath9k_hw_devname(u16 devid) | ||
347 | { | ||
348 | switch (devid) { | ||
349 | case AR5416_DEVID_PCI: | ||
350 | return "Atheros 5416"; | ||
351 | case AR5416_DEVID_PCIE: | ||
352 | return "Atheros 5418"; | ||
353 | case AR9160_DEVID_PCI: | ||
354 | return "Atheros 9160"; | ||
355 | case AR5416_AR9100_DEVID: | ||
356 | return "Atheros 9100"; | ||
357 | case AR9280_DEVID_PCI: | ||
358 | case AR9280_DEVID_PCIE: | ||
359 | return "Atheros 9280"; | ||
360 | case AR9285_DEVID_PCIE: | ||
361 | return "Atheros 9285"; | ||
362 | case AR5416_DEVID_AR9287_PCI: | ||
363 | case AR5416_DEVID_AR9287_PCIE: | ||
364 | return "Atheros 9287"; | ||
365 | } | ||
366 | |||
367 | return NULL; | ||
368 | } | ||
369 | |||
370 | static void ath9k_hw_init_config(struct ath_hw *ah) | 324 | static void ath9k_hw_init_config(struct ath_hw *ah) |
371 | { | 325 | { |
372 | int i; | 326 | int i; |
@@ -380,7 +334,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah) | |||
380 | ah->config.pcie_clock_req = 0; | 334 | ah->config.pcie_clock_req = 0; |
381 | ah->config.pcie_waen = 0; | 335 | ah->config.pcie_waen = 0; |
382 | ah->config.analog_shiftreg = 1; | 336 | ah->config.analog_shiftreg = 1; |
383 | ah->config.ht_enable = 1; | ||
384 | ah->config.ofdm_trig_low = 200; | 337 | ah->config.ofdm_trig_low = 200; |
385 | ah->config.ofdm_trig_high = 500; | 338 | ah->config.ofdm_trig_high = 500; |
386 | ah->config.cck_trig_high = 200; | 339 | ah->config.cck_trig_high = 200; |
@@ -392,7 +345,12 @@ static void ath9k_hw_init_config(struct ath_hw *ah) | |||
392 | ah->config.spurchans[i][1] = AR_NO_SPUR; | 345 | ah->config.spurchans[i][1] = AR_NO_SPUR; |
393 | } | 346 | } |
394 | 347 | ||
395 | ah->config.intr_mitigation = true; | 348 | if (ah->hw_version.devid != AR2427_DEVID_PCIE) |
349 | ah->config.ht_enable = 1; | ||
350 | else | ||
351 | ah->config.ht_enable = 0; | ||
352 | |||
353 | ah->config.rx_intr_mitigation = true; | ||
396 | 354 | ||
397 | /* | 355 | /* |
398 | * We need this for PCI devices only (Cardbus, PCI, miniPCI) | 356 | * We need this for PCI devices only (Cardbus, PCI, miniPCI) |
@@ -437,8 +395,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) | |||
437 | ah->beacon_interval = 100; | 395 | ah->beacon_interval = 100; |
438 | ah->enable_32kHz_clock = DONT_USE_32KHZ; | 396 | ah->enable_32kHz_clock = DONT_USE_32KHZ; |
439 | ah->slottime = (u32) -1; | 397 | ah->slottime = (u32) -1; |
440 | ah->acktimeout = (u32) -1; | ||
441 | ah->ctstimeout = (u32) -1; | ||
442 | ah->globaltxtimeout = (u32) -1; | 398 | ah->globaltxtimeout = (u32) -1; |
443 | ah->power_mode = ATH9K_PM_UNDEFINED; | 399 | ah->power_mode = ATH9K_PM_UNDEFINED; |
444 | } | 400 | } |
@@ -590,6 +546,7 @@ static bool ath9k_hw_devid_supported(u16 devid) | |||
590 | case AR5416_DEVID_AR9287_PCI: | 546 | case AR5416_DEVID_AR9287_PCI: |
591 | case AR5416_DEVID_AR9287_PCIE: | 547 | case AR5416_DEVID_AR9287_PCIE: |
592 | case AR9271_USB: | 548 | case AR9271_USB: |
549 | case AR2427_DEVID_PCIE: | ||
593 | return true; | 550 | return true; |
594 | default: | 551 | default: |
595 | break; | 552 | break; |
@@ -1183,7 +1140,7 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, | |||
1183 | AR_IMR_RXORN | | 1140 | AR_IMR_RXORN | |
1184 | AR_IMR_BCNMISC; | 1141 | AR_IMR_BCNMISC; |
1185 | 1142 | ||
1186 | if (ah->config.intr_mitigation) | 1143 | if (ah->config.rx_intr_mitigation) |
1187 | ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; | 1144 | ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; |
1188 | else | 1145 | else |
1189 | ah->mask_reg |= AR_IMR_RXOK; | 1146 | ah->mask_reg |= AR_IMR_RXOK; |
@@ -1203,34 +1160,25 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, | |||
1203 | } | 1160 | } |
1204 | } | 1161 | } |
1205 | 1162 | ||
1206 | static bool ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us) | 1163 | static void ath9k_hw_setslottime(struct ath_hw *ah, u32 us) |
1207 | { | 1164 | { |
1208 | if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { | 1165 | u32 val = ath9k_hw_mac_to_clks(ah, us); |
1209 | ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, | 1166 | val = min(val, (u32) 0xFFFF); |
1210 | "bad ack timeout %u\n", us); | 1167 | REG_WRITE(ah, AR_D_GBL_IFS_SLOT, val); |
1211 | ah->acktimeout = (u32) -1; | ||
1212 | return false; | ||
1213 | } else { | ||
1214 | REG_RMW_FIELD(ah, AR_TIME_OUT, | ||
1215 | AR_TIME_OUT_ACK, ath9k_hw_mac_to_clks(ah, us)); | ||
1216 | ah->acktimeout = us; | ||
1217 | return true; | ||
1218 | } | ||
1219 | } | 1168 | } |
1220 | 1169 | ||
1221 | static bool ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us) | 1170 | static void ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us) |
1222 | { | 1171 | { |
1223 | if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { | 1172 | u32 val = ath9k_hw_mac_to_clks(ah, us); |
1224 | ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, | 1173 | val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_ACK)); |
1225 | "bad cts timeout %u\n", us); | 1174 | REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_ACK, val); |
1226 | ah->ctstimeout = (u32) -1; | 1175 | } |
1227 | return false; | 1176 | |
1228 | } else { | 1177 | static void ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us) |
1229 | REG_RMW_FIELD(ah, AR_TIME_OUT, | 1178 | { |
1230 | AR_TIME_OUT_CTS, ath9k_hw_mac_to_clks(ah, us)); | 1179 | u32 val = ath9k_hw_mac_to_clks(ah, us); |
1231 | ah->ctstimeout = us; | 1180 | val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_CTS)); |
1232 | return true; | 1181 | REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_CTS, val); |
1233 | } | ||
1234 | } | 1182 | } |
1235 | 1183 | ||
1236 | static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) | 1184 | static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) |
@@ -1247,31 +1195,48 @@ static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) | |||
1247 | } | 1195 | } |
1248 | } | 1196 | } |
1249 | 1197 | ||
1250 | static void ath9k_hw_init_user_settings(struct ath_hw *ah) | 1198 | void ath9k_hw_init_global_settings(struct ath_hw *ah) |
1251 | { | 1199 | { |
1200 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | ||
1201 | int acktimeout; | ||
1202 | int slottime; | ||
1203 | int sifstime; | ||
1204 | |||
1252 | ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n", | 1205 | ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n", |
1253 | ah->misc_mode); | 1206 | ah->misc_mode); |
1254 | 1207 | ||
1255 | if (ah->misc_mode != 0) | 1208 | if (ah->misc_mode != 0) |
1256 | REG_WRITE(ah, AR_PCU_MISC, | 1209 | REG_WRITE(ah, AR_PCU_MISC, |
1257 | REG_READ(ah, AR_PCU_MISC) | ah->misc_mode); | 1210 | REG_READ(ah, AR_PCU_MISC) | ah->misc_mode); |
1258 | if (ah->slottime != (u32) -1) | 1211 | |
1259 | ath9k_hw_setslottime(ah, ah->slottime); | 1212 | if (conf->channel && conf->channel->band == IEEE80211_BAND_5GHZ) |
1260 | if (ah->acktimeout != (u32) -1) | 1213 | sifstime = 16; |
1261 | ath9k_hw_set_ack_timeout(ah, ah->acktimeout); | 1214 | else |
1262 | if (ah->ctstimeout != (u32) -1) | 1215 | sifstime = 10; |
1263 | ath9k_hw_set_cts_timeout(ah, ah->ctstimeout); | 1216 | |
1217 | /* As defined by IEEE 802.11-2007 17.3.8.6 */ | ||
1218 | slottime = ah->slottime + 3 * ah->coverage_class; | ||
1219 | acktimeout = slottime + sifstime; | ||
1220 | |||
1221 | /* | ||
1222 | * Workaround for early ACK timeouts, add an offset to match the | ||
1223 | * initval's 64us ack timeout value. | ||
1224 | * This was initially only meant to work around an issue with delayed | ||
1225 | * BA frames in some implementations, but it has been found to fix ACK | ||
1226 | * timeout issues in other cases as well. | ||
1227 | */ | ||
1228 | if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ) | ||
1229 | acktimeout += 64 - sifstime - ah->slottime; | ||
1230 | |||
1231 | ath9k_hw_setslottime(ah, slottime); | ||
1232 | ath9k_hw_set_ack_timeout(ah, acktimeout); | ||
1233 | ath9k_hw_set_cts_timeout(ah, acktimeout); | ||
1264 | if (ah->globaltxtimeout != (u32) -1) | 1234 | if (ah->globaltxtimeout != (u32) -1) |
1265 | ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout); | 1235 | ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout); |
1266 | } | 1236 | } |
1237 | EXPORT_SYMBOL(ath9k_hw_init_global_settings); | ||
1267 | 1238 | ||
1268 | const char *ath9k_hw_probe(u16 vendorid, u16 devid) | 1239 | void ath9k_hw_deinit(struct ath_hw *ah) |
1269 | { | ||
1270 | return vendorid == ATHEROS_VENDOR_ID ? | ||
1271 | ath9k_hw_devname(devid) : NULL; | ||
1272 | } | ||
1273 | |||
1274 | void ath9k_hw_detach(struct ath_hw *ah) | ||
1275 | { | 1240 | { |
1276 | struct ath_common *common = ath9k_hw_common(ah); | 1241 | struct ath_common *common = ath9k_hw_common(ah); |
1277 | 1242 | ||
@@ -1289,7 +1254,7 @@ free_hw: | |||
1289 | kfree(ah); | 1254 | kfree(ah); |
1290 | ah = NULL; | 1255 | ah = NULL; |
1291 | } | 1256 | } |
1292 | EXPORT_SYMBOL(ath9k_hw_detach); | 1257 | EXPORT_SYMBOL(ath9k_hw_deinit); |
1293 | 1258 | ||
1294 | /*******/ | 1259 | /*******/ |
1295 | /* INI */ | 1260 | /* INI */ |
@@ -2090,7 +2055,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2090 | if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) | 2055 | if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) |
2091 | ath9k_enable_rfkill(ah); | 2056 | ath9k_enable_rfkill(ah); |
2092 | 2057 | ||
2093 | ath9k_hw_init_user_settings(ah); | 2058 | ath9k_hw_init_global_settings(ah); |
2094 | 2059 | ||
2095 | if (AR_SREV_9287_12_OR_LATER(ah)) { | 2060 | if (AR_SREV_9287_12_OR_LATER(ah)) { |
2096 | REG_WRITE(ah, AR_D_GBL_IFS_SIFS, | 2061 | REG_WRITE(ah, AR_D_GBL_IFS_SIFS, |
@@ -2120,7 +2085,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2120 | 2085 | ||
2121 | REG_WRITE(ah, AR_OBS, 8); | 2086 | REG_WRITE(ah, AR_OBS, 8); |
2122 | 2087 | ||
2123 | if (ah->config.intr_mitigation) { | 2088 | if (ah->config.rx_intr_mitigation) { |
2124 | REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500); | 2089 | REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500); |
2125 | REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000); | 2090 | REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000); |
2126 | } | 2091 | } |
@@ -2780,7 +2745,7 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) | |||
2780 | 2745 | ||
2781 | *masked = isr & ATH9K_INT_COMMON; | 2746 | *masked = isr & ATH9K_INT_COMMON; |
2782 | 2747 | ||
2783 | if (ah->config.intr_mitigation) { | 2748 | if (ah->config.rx_intr_mitigation) { |
2784 | if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) | 2749 | if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) |
2785 | *masked |= ATH9K_INT_RX; | 2750 | *masked |= ATH9K_INT_RX; |
2786 | } | 2751 | } |
@@ -2913,7 +2878,7 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) | |||
2913 | } | 2878 | } |
2914 | if (ints & ATH9K_INT_RX) { | 2879 | if (ints & ATH9K_INT_RX) { |
2915 | mask |= AR_IMR_RXERR; | 2880 | mask |= AR_IMR_RXERR; |
2916 | if (ah->config.intr_mitigation) | 2881 | if (ah->config.rx_intr_mitigation) |
2917 | mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; | 2882 | mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; |
2918 | else | 2883 | else |
2919 | mask |= AR_IMR_RXOK | AR_IMR_RXDESC; | 2884 | mask |= AR_IMR_RXOK | AR_IMR_RXDESC; |
@@ -3687,21 +3652,6 @@ u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp) | |||
3687 | } | 3652 | } |
3688 | EXPORT_SYMBOL(ath9k_hw_extend_tsf); | 3653 | EXPORT_SYMBOL(ath9k_hw_extend_tsf); |
3689 | 3654 | ||
3690 | bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us) | ||
3691 | { | ||
3692 | if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) { | ||
3693 | ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, | ||
3694 | "bad slot time %u\n", us); | ||
3695 | ah->slottime = (u32) -1; | ||
3696 | return false; | ||
3697 | } else { | ||
3698 | REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath9k_hw_mac_to_clks(ah, us)); | ||
3699 | ah->slottime = us; | ||
3700 | return true; | ||
3701 | } | ||
3702 | } | ||
3703 | EXPORT_SYMBOL(ath9k_hw_setslottime); | ||
3704 | |||
3705 | void ath9k_hw_set11nmac2040(struct ath_hw *ah) | 3655 | void ath9k_hw_set11nmac2040(struct ath_hw *ah) |
3706 | { | 3656 | { |
3707 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | 3657 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index e2b0c73a616f..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 | ||
@@ -212,7 +213,7 @@ struct ath9k_ops_config { | |||
212 | u32 cck_trig_low; | 213 | u32 cck_trig_low; |
213 | u32 enable_ani; | 214 | u32 enable_ani; |
214 | int serialize_regmode; | 215 | int serialize_regmode; |
215 | bool intr_mitigation; | 216 | bool rx_intr_mitigation; |
216 | #define SPUR_DISABLE 0 | 217 | #define SPUR_DISABLE 0 |
217 | #define SPUR_ENABLE_IOCTL 1 | 218 | #define SPUR_ENABLE_IOCTL 1 |
218 | #define SPUR_ENABLE_EEPROM 2 | 219 | #define SPUR_ENABLE_EEPROM 2 |
@@ -551,10 +552,9 @@ struct ath_hw { | |||
551 | u32 *bank6Temp; | 552 | u32 *bank6Temp; |
552 | 553 | ||
553 | int16_t txpower_indexoffset; | 554 | int16_t txpower_indexoffset; |
555 | int coverage_class; | ||
554 | u32 beacon_interval; | 556 | u32 beacon_interval; |
555 | u32 slottime; | 557 | u32 slottime; |
556 | u32 acktimeout; | ||
557 | u32 ctstimeout; | ||
558 | u32 globaltxtimeout; | 558 | u32 globaltxtimeout; |
559 | 559 | ||
560 | /* ANI */ | 560 | /* ANI */ |
@@ -616,7 +616,7 @@ static inline struct ath_regulatory *ath9k_hw_regulatory(struct ath_hw *ah) | |||
616 | 616 | ||
617 | /* Initialization, Detach, Reset */ | 617 | /* Initialization, Detach, Reset */ |
618 | const char *ath9k_hw_probe(u16 vendorid, u16 devid); | 618 | const char *ath9k_hw_probe(u16 vendorid, u16 devid); |
619 | void ath9k_hw_detach(struct ath_hw *ah); | 619 | void ath9k_hw_deinit(struct ath_hw *ah); |
620 | int ath9k_hw_init(struct ath_hw *ah); | 620 | int ath9k_hw_init(struct ath_hw *ah); |
621 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | 621 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, |
622 | bool bChannelChange); | 622 | bool bChannelChange); |
@@ -668,7 +668,7 @@ void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); | |||
668 | void ath9k_hw_reset_tsf(struct ath_hw *ah); | 668 | void ath9k_hw_reset_tsf(struct ath_hw *ah); |
669 | void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); | 669 | void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); |
670 | u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp); | 670 | u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp); |
671 | bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us); | 671 | void ath9k_hw_init_global_settings(struct ath_hw *ah); |
672 | void ath9k_hw_set11nmac2040(struct ath_hw *ah); | 672 | void ath9k_hw_set11nmac2040(struct ath_hw *ah); |
673 | void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); | 673 | void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); |
674 | void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | 674 | void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c new file mode 100644 index 000000000000..623c2f884987 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -0,0 +1,863 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "ath9k.h" | ||
18 | |||
19 | static char *dev_info = "ath9k"; | ||
20 | |||
21 | MODULE_AUTHOR("Atheros Communications"); | ||
22 | MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards."); | ||
23 | MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards"); | ||
24 | MODULE_LICENSE("Dual BSD/GPL"); | ||
25 | |||
26 | static unsigned int ath9k_debug = ATH_DBG_DEFAULT; | ||
27 | module_param_named(debug, ath9k_debug, uint, 0); | ||
28 | MODULE_PARM_DESC(debug, "Debugging mask"); | ||
29 | |||
30 | int modparam_nohwcrypt; | ||
31 | module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); | ||
32 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); | ||
33 | |||
34 | /* We use the hw_value as an index into our private channel structure */ | ||
35 | |||
36 | #define CHAN2G(_freq, _idx) { \ | ||
37 | .center_freq = (_freq), \ | ||
38 | .hw_value = (_idx), \ | ||
39 | .max_power = 20, \ | ||
40 | } | ||
41 | |||
42 | #define CHAN5G(_freq, _idx) { \ | ||
43 | .band = IEEE80211_BAND_5GHZ, \ | ||
44 | .center_freq = (_freq), \ | ||
45 | .hw_value = (_idx), \ | ||
46 | .max_power = 20, \ | ||
47 | } | ||
48 | |||
49 | /* Some 2 GHz radios are actually tunable on 2312-2732 | ||
50 | * on 5 MHz steps, we support the channels which we know | ||
51 | * we have calibration data for all cards though to make | ||
52 | * this static */ | ||
53 | static struct ieee80211_channel ath9k_2ghz_chantable[] = { | ||
54 | CHAN2G(2412, 0), /* Channel 1 */ | ||
55 | CHAN2G(2417, 1), /* Channel 2 */ | ||
56 | CHAN2G(2422, 2), /* Channel 3 */ | ||
57 | CHAN2G(2427, 3), /* Channel 4 */ | ||
58 | CHAN2G(2432, 4), /* Channel 5 */ | ||
59 | CHAN2G(2437, 5), /* Channel 6 */ | ||
60 | CHAN2G(2442, 6), /* Channel 7 */ | ||
61 | CHAN2G(2447, 7), /* Channel 8 */ | ||
62 | CHAN2G(2452, 8), /* Channel 9 */ | ||
63 | CHAN2G(2457, 9), /* Channel 10 */ | ||
64 | CHAN2G(2462, 10), /* Channel 11 */ | ||
65 | CHAN2G(2467, 11), /* Channel 12 */ | ||
66 | CHAN2G(2472, 12), /* Channel 13 */ | ||
67 | CHAN2G(2484, 13), /* Channel 14 */ | ||
68 | }; | ||
69 | |||
70 | /* Some 5 GHz radios are actually tunable on XXXX-YYYY | ||
71 | * on 5 MHz steps, we support the channels which we know | ||
72 | * we have calibration data for all cards though to make | ||
73 | * this static */ | ||
74 | static struct ieee80211_channel ath9k_5ghz_chantable[] = { | ||
75 | /* _We_ call this UNII 1 */ | ||
76 | CHAN5G(5180, 14), /* Channel 36 */ | ||
77 | CHAN5G(5200, 15), /* Channel 40 */ | ||
78 | CHAN5G(5220, 16), /* Channel 44 */ | ||
79 | CHAN5G(5240, 17), /* Channel 48 */ | ||
80 | /* _We_ call this UNII 2 */ | ||
81 | CHAN5G(5260, 18), /* Channel 52 */ | ||
82 | CHAN5G(5280, 19), /* Channel 56 */ | ||
83 | CHAN5G(5300, 20), /* Channel 60 */ | ||
84 | CHAN5G(5320, 21), /* Channel 64 */ | ||
85 | /* _We_ call this "Middle band" */ | ||
86 | CHAN5G(5500, 22), /* Channel 100 */ | ||
87 | CHAN5G(5520, 23), /* Channel 104 */ | ||
88 | CHAN5G(5540, 24), /* Channel 108 */ | ||
89 | CHAN5G(5560, 25), /* Channel 112 */ | ||
90 | CHAN5G(5580, 26), /* Channel 116 */ | ||
91 | CHAN5G(5600, 27), /* Channel 120 */ | ||
92 | CHAN5G(5620, 28), /* Channel 124 */ | ||
93 | CHAN5G(5640, 29), /* Channel 128 */ | ||
94 | CHAN5G(5660, 30), /* Channel 132 */ | ||
95 | CHAN5G(5680, 31), /* Channel 136 */ | ||
96 | CHAN5G(5700, 32), /* Channel 140 */ | ||
97 | /* _We_ call this UNII 3 */ | ||
98 | CHAN5G(5745, 33), /* Channel 149 */ | ||
99 | CHAN5G(5765, 34), /* Channel 153 */ | ||
100 | CHAN5G(5785, 35), /* Channel 157 */ | ||
101 | CHAN5G(5805, 36), /* Channel 161 */ | ||
102 | CHAN5G(5825, 37), /* Channel 165 */ | ||
103 | }; | ||
104 | |||
105 | /* Atheros hardware rate code addition for short premble */ | ||
106 | #define SHPCHECK(__hw_rate, __flags) \ | ||
107 | ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04 ) : 0) | ||
108 | |||
109 | #define RATE(_bitrate, _hw_rate, _flags) { \ | ||
110 | .bitrate = (_bitrate), \ | ||
111 | .flags = (_flags), \ | ||
112 | .hw_value = (_hw_rate), \ | ||
113 | .hw_value_short = (SHPCHECK(_hw_rate, _flags)) \ | ||
114 | } | ||
115 | |||
116 | static struct ieee80211_rate ath9k_legacy_rates[] = { | ||
117 | RATE(10, 0x1b, 0), | ||
118 | RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE), | ||
119 | RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE), | ||
120 | RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE), | ||
121 | RATE(60, 0x0b, 0), | ||
122 | RATE(90, 0x0f, 0), | ||
123 | RATE(120, 0x0a, 0), | ||
124 | RATE(180, 0x0e, 0), | ||
125 | RATE(240, 0x09, 0), | ||
126 | RATE(360, 0x0d, 0), | ||
127 | RATE(480, 0x08, 0), | ||
128 | RATE(540, 0x0c, 0), | ||
129 | }; | ||
130 | |||
131 | static void ath9k_deinit_softc(struct ath_softc *sc); | ||
132 | |||
133 | /* | ||
134 | * Read and write, they both share the same lock. We do this to serialize | ||
135 | * reads and writes on Atheros 802.11n PCI devices only. This is required | ||
136 | * as the FIFO on these devices can only accept sanely 2 requests. | ||
137 | */ | ||
138 | |||
139 | static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset) | ||
140 | { | ||
141 | struct ath_hw *ah = (struct ath_hw *) hw_priv; | ||
142 | struct ath_common *common = ath9k_hw_common(ah); | ||
143 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
144 | |||
145 | if (ah->config.serialize_regmode == SER_REG_MODE_ON) { | ||
146 | unsigned long flags; | ||
147 | spin_lock_irqsave(&sc->sc_serial_rw, flags); | ||
148 | iowrite32(val, sc->mem + reg_offset); | ||
149 | spin_unlock_irqrestore(&sc->sc_serial_rw, flags); | ||
150 | } else | ||
151 | iowrite32(val, sc->mem + reg_offset); | ||
152 | } | ||
153 | |||
154 | static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset) | ||
155 | { | ||
156 | struct ath_hw *ah = (struct ath_hw *) hw_priv; | ||
157 | struct ath_common *common = ath9k_hw_common(ah); | ||
158 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
159 | u32 val; | ||
160 | |||
161 | if (ah->config.serialize_regmode == SER_REG_MODE_ON) { | ||
162 | unsigned long flags; | ||
163 | spin_lock_irqsave(&sc->sc_serial_rw, flags); | ||
164 | val = ioread32(sc->mem + reg_offset); | ||
165 | spin_unlock_irqrestore(&sc->sc_serial_rw, flags); | ||
166 | } else | ||
167 | val = ioread32(sc->mem + reg_offset); | ||
168 | return val; | ||
169 | } | ||
170 | |||
171 | static const struct ath_ops ath9k_common_ops = { | ||
172 | .read = ath9k_ioread32, | ||
173 | .write = ath9k_iowrite32, | ||
174 | }; | ||
175 | |||
176 | /**************************/ | ||
177 | /* Initialization */ | ||
178 | /**************************/ | ||
179 | |||
180 | static void setup_ht_cap(struct ath_softc *sc, | ||
181 | struct ieee80211_sta_ht_cap *ht_info) | ||
182 | { | ||
183 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
184 | u8 tx_streams, rx_streams; | ||
185 | |||
186 | ht_info->ht_supported = true; | ||
187 | ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | | ||
188 | IEEE80211_HT_CAP_SM_PS | | ||
189 | IEEE80211_HT_CAP_SGI_40 | | ||
190 | IEEE80211_HT_CAP_DSSSCCK40; | ||
191 | |||
192 | ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; | ||
193 | ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; | ||
194 | |||
195 | /* set up supported mcs set */ | ||
196 | memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); | ||
197 | tx_streams = !(common->tx_chainmask & (common->tx_chainmask - 1)) ? | ||
198 | 1 : 2; | ||
199 | rx_streams = !(common->rx_chainmask & (common->rx_chainmask - 1)) ? | ||
200 | 1 : 2; | ||
201 | |||
202 | if (tx_streams != rx_streams) { | ||
203 | ath_print(common, ATH_DBG_CONFIG, | ||
204 | "TX streams %d, RX streams: %d\n", | ||
205 | tx_streams, rx_streams); | ||
206 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; | ||
207 | ht_info->mcs.tx_params |= ((tx_streams - 1) << | ||
208 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); | ||
209 | } | ||
210 | |||
211 | ht_info->mcs.rx_mask[0] = 0xff; | ||
212 | if (rx_streams >= 2) | ||
213 | ht_info->mcs.rx_mask[1] = 0xff; | ||
214 | |||
215 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; | ||
216 | } | ||
217 | |||
218 | static int ath9k_reg_notifier(struct wiphy *wiphy, | ||
219 | struct regulatory_request *request) | ||
220 | { | ||
221 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | ||
222 | struct ath_wiphy *aphy = hw->priv; | ||
223 | struct ath_softc *sc = aphy->sc; | ||
224 | struct ath_regulatory *reg = ath9k_hw_regulatory(sc->sc_ah); | ||
225 | |||
226 | return ath_reg_notifier_apply(wiphy, request, reg); | ||
227 | } | ||
228 | |||
229 | /* | ||
230 | * This function will allocate both the DMA descriptor structure, and the | ||
231 | * buffers it contains. These are used to contain the descriptors used | ||
232 | * by the system. | ||
233 | */ | ||
234 | int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | ||
235 | struct list_head *head, const char *name, | ||
236 | int nbuf, int ndesc) | ||
237 | { | ||
238 | #define DS2PHYS(_dd, _ds) \ | ||
239 | ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) | ||
240 | #define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0) | ||
241 | #define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096) | ||
242 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
243 | struct ath_desc *ds; | ||
244 | struct ath_buf *bf; | ||
245 | int i, bsize, error; | ||
246 | |||
247 | ath_print(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n", | ||
248 | name, nbuf, ndesc); | ||
249 | |||
250 | INIT_LIST_HEAD(head); | ||
251 | /* ath_desc must be a multiple of DWORDs */ | ||
252 | if ((sizeof(struct ath_desc) % 4) != 0) { | ||
253 | ath_print(common, ATH_DBG_FATAL, | ||
254 | "ath_desc not DWORD aligned\n"); | ||
255 | BUG_ON((sizeof(struct ath_desc) % 4) != 0); | ||
256 | error = -ENOMEM; | ||
257 | goto fail; | ||
258 | } | ||
259 | |||
260 | dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc; | ||
261 | |||
262 | /* | ||
263 | * Need additional DMA memory because we can't use | ||
264 | * descriptors that cross the 4K page boundary. Assume | ||
265 | * one skipped descriptor per 4K page. | ||
266 | */ | ||
267 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) { | ||
268 | u32 ndesc_skipped = | ||
269 | ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len); | ||
270 | u32 dma_len; | ||
271 | |||
272 | while (ndesc_skipped) { | ||
273 | dma_len = ndesc_skipped * sizeof(struct ath_desc); | ||
274 | dd->dd_desc_len += dma_len; | ||
275 | |||
276 | ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len); | ||
277 | }; | ||
278 | } | ||
279 | |||
280 | /* allocate descriptors */ | ||
281 | dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len, | ||
282 | &dd->dd_desc_paddr, GFP_KERNEL); | ||
283 | if (dd->dd_desc == NULL) { | ||
284 | error = -ENOMEM; | ||
285 | goto fail; | ||
286 | } | ||
287 | ds = dd->dd_desc; | ||
288 | ath_print(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", | ||
289 | name, ds, (u32) dd->dd_desc_len, | ||
290 | ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); | ||
291 | |||
292 | /* allocate buffers */ | ||
293 | bsize = sizeof(struct ath_buf) * nbuf; | ||
294 | bf = kzalloc(bsize, GFP_KERNEL); | ||
295 | if (bf == NULL) { | ||
296 | error = -ENOMEM; | ||
297 | goto fail2; | ||
298 | } | ||
299 | dd->dd_bufptr = bf; | ||
300 | |||
301 | for (i = 0; i < nbuf; i++, bf++, ds += ndesc) { | ||
302 | bf->bf_desc = ds; | ||
303 | bf->bf_daddr = DS2PHYS(dd, ds); | ||
304 | |||
305 | if (!(sc->sc_ah->caps.hw_caps & | ||
306 | ATH9K_HW_CAP_4KB_SPLITTRANS)) { | ||
307 | /* | ||
308 | * Skip descriptor addresses which can cause 4KB | ||
309 | * boundary crossing (addr + length) with a 32 dword | ||
310 | * descriptor fetch. | ||
311 | */ | ||
312 | while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { | ||
313 | BUG_ON((caddr_t) bf->bf_desc >= | ||
314 | ((caddr_t) dd->dd_desc + | ||
315 | dd->dd_desc_len)); | ||
316 | |||
317 | ds += ndesc; | ||
318 | bf->bf_desc = ds; | ||
319 | bf->bf_daddr = DS2PHYS(dd, ds); | ||
320 | } | ||
321 | } | ||
322 | list_add_tail(&bf->list, head); | ||
323 | } | ||
324 | return 0; | ||
325 | fail2: | ||
326 | dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, | ||
327 | dd->dd_desc_paddr); | ||
328 | fail: | ||
329 | memset(dd, 0, sizeof(*dd)); | ||
330 | return error; | ||
331 | #undef ATH_DESC_4KB_BOUND_CHECK | ||
332 | #undef ATH_DESC_4KB_BOUND_NUM_SKIPPED | ||
333 | #undef DS2PHYS | ||
334 | } | ||
335 | |||
336 | static void ath9k_init_crypto(struct ath_softc *sc) | ||
337 | { | ||
338 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
339 | int i = 0; | ||
340 | |||
341 | /* Get the hardware key cache size. */ | ||
342 | common->keymax = sc->sc_ah->caps.keycache_size; | ||
343 | if (common->keymax > ATH_KEYMAX) { | ||
344 | ath_print(common, ATH_DBG_ANY, | ||
345 | "Warning, using only %u entries in %u key cache\n", | ||
346 | ATH_KEYMAX, common->keymax); | ||
347 | common->keymax = ATH_KEYMAX; | ||
348 | } | ||
349 | |||
350 | /* | ||
351 | * Reset the key cache since some parts do not | ||
352 | * reset the contents on initial power up. | ||
353 | */ | ||
354 | for (i = 0; i < common->keymax; i++) | ||
355 | ath9k_hw_keyreset(sc->sc_ah, (u16) i); | ||
356 | |||
357 | if (ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_CIPHER, | ||
358 | ATH9K_CIPHER_TKIP, NULL)) { | ||
359 | /* | ||
360 | * Whether we should enable h/w TKIP MIC. | ||
361 | * XXX: if we don't support WME TKIP MIC, then we wouldn't | ||
362 | * report WMM capable, so it's always safe to turn on | ||
363 | * TKIP MIC in this case. | ||
364 | */ | ||
365 | ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC, 0, 1, NULL); | ||
366 | } | ||
367 | |||
368 | /* | ||
369 | * Check whether the separate key cache entries | ||
370 | * are required to handle both tx+rx MIC keys. | ||
371 | * With split mic keys the number of stations is limited | ||
372 | * to 27 otherwise 59. | ||
373 | */ | ||
374 | if (ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_CIPHER, | ||
375 | ATH9K_CIPHER_TKIP, NULL) | ||
376 | && ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_CIPHER, | ||
377 | ATH9K_CIPHER_MIC, NULL) | ||
378 | && ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_TKIP_SPLIT, | ||
379 | 0, NULL)) | ||
380 | common->splitmic = 1; | ||
381 | |||
382 | /* turn on mcast key search if possible */ | ||
383 | if (!ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) | ||
384 | (void)ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_MCAST_KEYSRCH, | ||
385 | 1, 1, NULL); | ||
386 | |||
387 | } | ||
388 | |||
389 | static int ath9k_init_btcoex(struct ath_softc *sc) | ||
390 | { | ||
391 | int r, qnum; | ||
392 | |||
393 | switch (sc->sc_ah->btcoex_hw.scheme) { | ||
394 | case ATH_BTCOEX_CFG_NONE: | ||
395 | break; | ||
396 | case ATH_BTCOEX_CFG_2WIRE: | ||
397 | ath9k_hw_btcoex_init_2wire(sc->sc_ah); | ||
398 | break; | ||
399 | case ATH_BTCOEX_CFG_3WIRE: | ||
400 | ath9k_hw_btcoex_init_3wire(sc->sc_ah); | ||
401 | r = ath_init_btcoex_timer(sc); | ||
402 | if (r) | ||
403 | return -1; | ||
404 | qnum = ath_tx_get_qnum(sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); | ||
405 | ath9k_hw_init_btcoex_hw(sc->sc_ah, qnum); | ||
406 | sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; | ||
407 | break; | ||
408 | default: | ||
409 | WARN_ON(1); | ||
410 | break; | ||
411 | } | ||
412 | |||
413 | return 0; | ||
414 | } | ||
415 | |||
416 | static int ath9k_init_queues(struct ath_softc *sc) | ||
417 | { | ||
418 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
419 | int i = 0; | ||
420 | |||
421 | for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++) | ||
422 | sc->tx.hwq_map[i] = -1; | ||
423 | |||
424 | sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah); | ||
425 | if (sc->beacon.beaconq == -1) { | ||
426 | ath_print(common, ATH_DBG_FATAL, | ||
427 | "Unable to setup a beacon xmit queue\n"); | ||
428 | goto err; | ||
429 | } | ||
430 | |||
431 | sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); | ||
432 | if (sc->beacon.cabq == NULL) { | ||
433 | ath_print(common, ATH_DBG_FATAL, | ||
434 | "Unable to setup CAB xmit queue\n"); | ||
435 | goto err; | ||
436 | } | ||
437 | |||
438 | sc->config.cabqReadytime = ATH_CABQ_READY_TIME; | ||
439 | ath_cabq_update(sc); | ||
440 | |||
441 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { | ||
442 | ath_print(common, ATH_DBG_FATAL, | ||
443 | "Unable to setup xmit queue for BK traffic\n"); | ||
444 | goto err; | ||
445 | } | ||
446 | |||
447 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) { | ||
448 | ath_print(common, ATH_DBG_FATAL, | ||
449 | "Unable to setup xmit queue for BE traffic\n"); | ||
450 | goto err; | ||
451 | } | ||
452 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) { | ||
453 | ath_print(common, ATH_DBG_FATAL, | ||
454 | "Unable to setup xmit queue for VI traffic\n"); | ||
455 | goto err; | ||
456 | } | ||
457 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) { | ||
458 | ath_print(common, ATH_DBG_FATAL, | ||
459 | "Unable to setup xmit queue for VO traffic\n"); | ||
460 | goto err; | ||
461 | } | ||
462 | |||
463 | return 0; | ||
464 | |||
465 | err: | ||
466 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
467 | if (ATH_TXQ_SETUP(sc, i)) | ||
468 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | ||
469 | |||
470 | return -EIO; | ||
471 | } | ||
472 | |||
473 | static void ath9k_init_channels_rates(struct ath_softc *sc) | ||
474 | { | ||
475 | if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) { | ||
476 | sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable; | ||
477 | sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; | ||
478 | sc->sbands[IEEE80211_BAND_2GHZ].n_channels = | ||
479 | ARRAY_SIZE(ath9k_2ghz_chantable); | ||
480 | sc->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates; | ||
481 | sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates = | ||
482 | ARRAY_SIZE(ath9k_legacy_rates); | ||
483 | } | ||
484 | |||
485 | if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) { | ||
486 | sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable; | ||
487 | sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; | ||
488 | sc->sbands[IEEE80211_BAND_5GHZ].n_channels = | ||
489 | ARRAY_SIZE(ath9k_5ghz_chantable); | ||
490 | sc->sbands[IEEE80211_BAND_5GHZ].bitrates = | ||
491 | ath9k_legacy_rates + 4; | ||
492 | sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates = | ||
493 | ARRAY_SIZE(ath9k_legacy_rates) - 4; | ||
494 | } | ||
495 | } | ||
496 | |||
497 | static void ath9k_init_misc(struct ath_softc *sc) | ||
498 | { | ||
499 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
500 | int i = 0; | ||
501 | |||
502 | common->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR; | ||
503 | setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc); | ||
504 | |||
505 | sc->config.txpowlimit = ATH_TXPOWER_MAX; | ||
506 | |||
507 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { | ||
508 | sc->sc_flags |= SC_OP_TXAGGR; | ||
509 | sc->sc_flags |= SC_OP_RXAGGR; | ||
510 | } | ||
511 | |||
512 | common->tx_chainmask = sc->sc_ah->caps.tx_chainmask; | ||
513 | common->rx_chainmask = sc->sc_ah->caps.rx_chainmask; | ||
514 | |||
515 | ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); | ||
516 | sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah); | ||
517 | |||
518 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | ||
519 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); | ||
520 | |||
521 | sc->beacon.slottime = ATH9K_SLOT_TIME_9; | ||
522 | |||
523 | for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { | ||
524 | sc->beacon.bslot[i] = NULL; | ||
525 | sc->beacon.bslot_aphy[i] = NULL; | ||
526 | } | ||
527 | } | ||
528 | |||
529 | static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, | ||
530 | const struct ath_bus_ops *bus_ops) | ||
531 | { | ||
532 | struct ath_hw *ah = NULL; | ||
533 | struct ath_common *common; | ||
534 | int ret = 0, i; | ||
535 | int csz = 0; | ||
536 | |||
537 | ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); | ||
538 | if (!ah) | ||
539 | return -ENOMEM; | ||
540 | |||
541 | ah->hw_version.devid = devid; | ||
542 | ah->hw_version.subsysid = subsysid; | ||
543 | sc->sc_ah = ah; | ||
544 | |||
545 | common = ath9k_hw_common(ah); | ||
546 | common->ops = &ath9k_common_ops; | ||
547 | common->bus_ops = bus_ops; | ||
548 | common->ah = ah; | ||
549 | common->hw = sc->hw; | ||
550 | common->priv = sc; | ||
551 | common->debug_mask = ath9k_debug; | ||
552 | |||
553 | spin_lock_init(&sc->wiphy_lock); | ||
554 | spin_lock_init(&sc->sc_resetlock); | ||
555 | spin_lock_init(&sc->sc_serial_rw); | ||
556 | spin_lock_init(&sc->sc_pm_lock); | ||
557 | mutex_init(&sc->mutex); | ||
558 | tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); | ||
559 | tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, | ||
560 | (unsigned long)sc); | ||
561 | |||
562 | /* | ||
563 | * Cache line size is used to size and align various | ||
564 | * structures used to communicate with the hardware. | ||
565 | */ | ||
566 | ath_read_cachesize(common, &csz); | ||
567 | common->cachelsz = csz << 2; /* convert to bytes */ | ||
568 | |||
569 | ret = ath9k_hw_init(ah); | ||
570 | if (ret) { | ||
571 | ath_print(common, ATH_DBG_FATAL, | ||
572 | "Unable to initialize hardware; " | ||
573 | "initialization status: %d\n", ret); | ||
574 | goto err_hw; | ||
575 | } | ||
576 | |||
577 | ret = ath9k_init_debug(ah); | ||
578 | if (ret) { | ||
579 | ath_print(common, ATH_DBG_FATAL, | ||
580 | "Unable to create debugfs files\n"); | ||
581 | goto err_debug; | ||
582 | } | ||
583 | |||
584 | ret = ath9k_init_queues(sc); | ||
585 | if (ret) | ||
586 | goto err_queues; | ||
587 | |||
588 | ret = ath9k_init_btcoex(sc); | ||
589 | if (ret) | ||
590 | goto err_btcoex; | ||
591 | |||
592 | ath9k_init_crypto(sc); | ||
593 | ath9k_init_channels_rates(sc); | ||
594 | ath9k_init_misc(sc); | ||
595 | |||
596 | return 0; | ||
597 | |||
598 | err_btcoex: | ||
599 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
600 | if (ATH_TXQ_SETUP(sc, i)) | ||
601 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | ||
602 | err_queues: | ||
603 | ath9k_exit_debug(ah); | ||
604 | err_debug: | ||
605 | ath9k_hw_deinit(ah); | ||
606 | err_hw: | ||
607 | tasklet_kill(&sc->intr_tq); | ||
608 | tasklet_kill(&sc->bcon_tasklet); | ||
609 | |||
610 | kfree(ah); | ||
611 | sc->sc_ah = NULL; | ||
612 | |||
613 | return ret; | ||
614 | } | ||
615 | |||
616 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | ||
617 | { | ||
618 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
619 | |||
620 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | | ||
621 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | ||
622 | IEEE80211_HW_SIGNAL_DBM | | ||
623 | IEEE80211_HW_SUPPORTS_PS | | ||
624 | IEEE80211_HW_PS_NULLFUNC_STACK | | ||
625 | IEEE80211_HW_SPECTRUM_MGMT | | ||
626 | IEEE80211_HW_REPORTS_TX_ACK_STATUS; | ||
627 | |||
628 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) | ||
629 | hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; | ||
630 | |||
631 | if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt) | ||
632 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; | ||
633 | |||
634 | hw->wiphy->interface_modes = | ||
635 | BIT(NL80211_IFTYPE_AP) | | ||
636 | BIT(NL80211_IFTYPE_STATION) | | ||
637 | BIT(NL80211_IFTYPE_ADHOC) | | ||
638 | BIT(NL80211_IFTYPE_MESH_POINT); | ||
639 | |||
640 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | ||
641 | |||
642 | hw->queues = 4; | ||
643 | hw->max_rates = 4; | ||
644 | hw->channel_change_time = 5000; | ||
645 | hw->max_listen_interval = 10; | ||
646 | hw->max_rate_tries = 10; | ||
647 | hw->sta_data_size = sizeof(struct ath_node); | ||
648 | hw->vif_data_size = sizeof(struct ath_vif); | ||
649 | |||
650 | hw->rate_control_algorithm = "ath9k_rate_control"; | ||
651 | |||
652 | if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) | ||
653 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | ||
654 | &sc->sbands[IEEE80211_BAND_2GHZ]; | ||
655 | if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) | ||
656 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | ||
657 | &sc->sbands[IEEE80211_BAND_5GHZ]; | ||
658 | |||
659 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { | ||
660 | if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) | ||
661 | setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); | ||
662 | if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) | ||
663 | setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); | ||
664 | } | ||
665 | |||
666 | SET_IEEE80211_PERM_ADDR(hw, common->macaddr); | ||
667 | } | ||
668 | |||
669 | int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, | ||
670 | const struct ath_bus_ops *bus_ops) | ||
671 | { | ||
672 | struct ieee80211_hw *hw = sc->hw; | ||
673 | struct ath_common *common; | ||
674 | struct ath_hw *ah; | ||
675 | int error = 0; | ||
676 | struct ath_regulatory *reg; | ||
677 | |||
678 | /* Bring up device */ | ||
679 | error = ath9k_init_softc(devid, sc, subsysid, bus_ops); | ||
680 | if (error != 0) | ||
681 | goto error_init; | ||
682 | |||
683 | ah = sc->sc_ah; | ||
684 | common = ath9k_hw_common(ah); | ||
685 | ath9k_set_hw_capab(sc, hw); | ||
686 | |||
687 | /* Initialize regulatory */ | ||
688 | error = ath_regd_init(&common->regulatory, sc->hw->wiphy, | ||
689 | ath9k_reg_notifier); | ||
690 | if (error) | ||
691 | goto error_regd; | ||
692 | |||
693 | reg = &common->regulatory; | ||
694 | |||
695 | /* Setup TX DMA */ | ||
696 | error = ath_tx_init(sc, ATH_TXBUF); | ||
697 | if (error != 0) | ||
698 | goto error_tx; | ||
699 | |||
700 | /* Setup RX DMA */ | ||
701 | error = ath_rx_init(sc, ATH_RXBUF); | ||
702 | if (error != 0) | ||
703 | goto error_rx; | ||
704 | |||
705 | /* Register with mac80211 */ | ||
706 | error = ieee80211_register_hw(hw); | ||
707 | if (error) | ||
708 | goto error_register; | ||
709 | |||
710 | /* Handle world regulatory */ | ||
711 | if (!ath_is_world_regd(reg)) { | ||
712 | error = regulatory_hint(hw->wiphy, reg->alpha2); | ||
713 | if (error) | ||
714 | goto error_world; | ||
715 | } | ||
716 | |||
717 | INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); | ||
718 | INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); | ||
719 | sc->wiphy_scheduler_int = msecs_to_jiffies(500); | ||
720 | |||
721 | ath_init_leds(sc); | ||
722 | ath_start_rfkill_poll(sc); | ||
723 | |||
724 | return 0; | ||
725 | |||
726 | error_world: | ||
727 | ieee80211_unregister_hw(hw); | ||
728 | error_register: | ||
729 | ath_rx_cleanup(sc); | ||
730 | error_rx: | ||
731 | ath_tx_cleanup(sc); | ||
732 | error_tx: | ||
733 | /* Nothing */ | ||
734 | error_regd: | ||
735 | ath9k_deinit_softc(sc); | ||
736 | error_init: | ||
737 | return error; | ||
738 | } | ||
739 | |||
740 | /*****************************/ | ||
741 | /* De-Initialization */ | ||
742 | /*****************************/ | ||
743 | |||
744 | static void ath9k_deinit_softc(struct ath_softc *sc) | ||
745 | { | ||
746 | int i = 0; | ||
747 | |||
748 | if ((sc->btcoex.no_stomp_timer) && | ||
749 | sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) | ||
750 | ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer); | ||
751 | |||
752 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
753 | if (ATH_TXQ_SETUP(sc, i)) | ||
754 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | ||
755 | |||
756 | ath9k_exit_debug(sc->sc_ah); | ||
757 | ath9k_hw_deinit(sc->sc_ah); | ||
758 | |||
759 | tasklet_kill(&sc->intr_tq); | ||
760 | tasklet_kill(&sc->bcon_tasklet); | ||
761 | } | ||
762 | |||
763 | void ath9k_deinit_device(struct ath_softc *sc) | ||
764 | { | ||
765 | struct ieee80211_hw *hw = sc->hw; | ||
766 | int i = 0; | ||
767 | |||
768 | ath9k_ps_wakeup(sc); | ||
769 | |||
770 | wiphy_rfkill_stop_polling(sc->hw->wiphy); | ||
771 | ath_deinit_leds(sc); | ||
772 | |||
773 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
774 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
775 | if (aphy == NULL) | ||
776 | continue; | ||
777 | sc->sec_wiphy[i] = NULL; | ||
778 | ieee80211_unregister_hw(aphy->hw); | ||
779 | ieee80211_free_hw(aphy->hw); | ||
780 | } | ||
781 | kfree(sc->sec_wiphy); | ||
782 | |||
783 | ieee80211_unregister_hw(hw); | ||
784 | ath_rx_cleanup(sc); | ||
785 | ath_tx_cleanup(sc); | ||
786 | ath9k_deinit_softc(sc); | ||
787 | } | ||
788 | |||
789 | void ath_descdma_cleanup(struct ath_softc *sc, | ||
790 | struct ath_descdma *dd, | ||
791 | struct list_head *head) | ||
792 | { | ||
793 | dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, | ||
794 | dd->dd_desc_paddr); | ||
795 | |||
796 | INIT_LIST_HEAD(head); | ||
797 | kfree(dd->dd_bufptr); | ||
798 | memset(dd, 0, sizeof(*dd)); | ||
799 | } | ||
800 | |||
801 | /************************/ | ||
802 | /* Module Hooks */ | ||
803 | /************************/ | ||
804 | |||
805 | static int __init ath9k_init(void) | ||
806 | { | ||
807 | int error; | ||
808 | |||
809 | /* Register rate control algorithm */ | ||
810 | error = ath_rate_control_register(); | ||
811 | if (error != 0) { | ||
812 | printk(KERN_ERR | ||
813 | "ath9k: Unable to register rate control " | ||
814 | "algorithm: %d\n", | ||
815 | error); | ||
816 | goto err_out; | ||
817 | } | ||
818 | |||
819 | error = ath9k_debug_create_root(); | ||
820 | if (error) { | ||
821 | printk(KERN_ERR | ||
822 | "ath9k: Unable to create debugfs root: %d\n", | ||
823 | error); | ||
824 | goto err_rate_unregister; | ||
825 | } | ||
826 | |||
827 | error = ath_pci_init(); | ||
828 | if (error < 0) { | ||
829 | printk(KERN_ERR | ||
830 | "ath9k: No PCI devices found, driver not installed.\n"); | ||
831 | error = -ENODEV; | ||
832 | goto err_remove_root; | ||
833 | } | ||
834 | |||
835 | error = ath_ahb_init(); | ||
836 | if (error < 0) { | ||
837 | error = -ENODEV; | ||
838 | goto err_pci_exit; | ||
839 | } | ||
840 | |||
841 | return 0; | ||
842 | |||
843 | err_pci_exit: | ||
844 | ath_pci_exit(); | ||
845 | |||
846 | err_remove_root: | ||
847 | ath9k_debug_remove_root(); | ||
848 | err_rate_unregister: | ||
849 | ath_rate_control_unregister(); | ||
850 | err_out: | ||
851 | return error; | ||
852 | } | ||
853 | module_init(ath9k_init); | ||
854 | |||
855 | static void __exit ath9k_exit(void) | ||
856 | { | ||
857 | ath_ahb_exit(); | ||
858 | ath_pci_exit(); | ||
859 | ath9k_debug_remove_root(); | ||
860 | ath_rate_control_unregister(); | ||
861 | printk(KERN_INFO "%s: Driver unloaded\n", dev_info); | ||
862 | } | ||
863 | module_exit(ath9k_exit); | ||
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index e185479e295e..29851e6376a9 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -167,6 +167,40 @@ struct ath_rx_status { | |||
167 | #define ATH9K_RXKEYIX_INVALID ((u8)-1) | 167 | #define ATH9K_RXKEYIX_INVALID ((u8)-1) |
168 | #define ATH9K_TXKEYIX_INVALID ((u32)-1) | 168 | #define ATH9K_TXKEYIX_INVALID ((u32)-1) |
169 | 169 | ||
170 | enum ath9k_phyerr { | ||
171 | ATH9K_PHYERR_UNDERRUN = 0, /* Transmit underrun */ | ||
172 | ATH9K_PHYERR_TIMING = 1, /* Timing error */ | ||
173 | ATH9K_PHYERR_PARITY = 2, /* Illegal parity */ | ||
174 | ATH9K_PHYERR_RATE = 3, /* Illegal rate */ | ||
175 | ATH9K_PHYERR_LENGTH = 4, /* Illegal length */ | ||
176 | ATH9K_PHYERR_RADAR = 5, /* Radar detect */ | ||
177 | ATH9K_PHYERR_SERVICE = 6, /* Illegal service */ | ||
178 | ATH9K_PHYERR_TOR = 7, /* Transmit override receive */ | ||
179 | |||
180 | ATH9K_PHYERR_OFDM_TIMING = 17, | ||
181 | ATH9K_PHYERR_OFDM_SIGNAL_PARITY = 18, | ||
182 | ATH9K_PHYERR_OFDM_RATE_ILLEGAL = 19, | ||
183 | ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL = 20, | ||
184 | ATH9K_PHYERR_OFDM_POWER_DROP = 21, | ||
185 | ATH9K_PHYERR_OFDM_SERVICE = 22, | ||
186 | ATH9K_PHYERR_OFDM_RESTART = 23, | ||
187 | ATH9K_PHYERR_FALSE_RADAR_EXT = 24, | ||
188 | |||
189 | ATH9K_PHYERR_CCK_TIMING = 25, | ||
190 | ATH9K_PHYERR_CCK_HEADER_CRC = 26, | ||
191 | ATH9K_PHYERR_CCK_RATE_ILLEGAL = 27, | ||
192 | ATH9K_PHYERR_CCK_SERVICE = 30, | ||
193 | ATH9K_PHYERR_CCK_RESTART = 31, | ||
194 | ATH9K_PHYERR_CCK_LENGTH_ILLEGAL = 32, | ||
195 | ATH9K_PHYERR_CCK_POWER_DROP = 33, | ||
196 | |||
197 | ATH9K_PHYERR_HT_CRC_ERROR = 34, | ||
198 | ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 35, | ||
199 | ATH9K_PHYERR_HT_RATE_ILLEGAL = 36, | ||
200 | |||
201 | ATH9K_PHYERR_MAX = 37, | ||
202 | }; | ||
203 | |||
170 | struct ath_desc { | 204 | struct ath_desc { |
171 | u32 ds_link; | 205 | u32 ds_link; |
172 | u32 ds_data; | 206 | u32 ds_data; |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 643bea35686f..67ca4e5a6017 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -18,118 +18,6 @@ | |||
18 | #include "ath9k.h" | 18 | #include "ath9k.h" |
19 | #include "btcoex.h" | 19 | #include "btcoex.h" |
20 | 20 | ||
21 | static char *dev_info = "ath9k"; | ||
22 | |||
23 | MODULE_AUTHOR("Atheros Communications"); | ||
24 | MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards."); | ||
25 | MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards"); | ||
26 | MODULE_LICENSE("Dual BSD/GPL"); | ||
27 | |||
28 | static int modparam_nohwcrypt; | ||
29 | module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); | ||
30 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); | ||
31 | |||
32 | static unsigned int ath9k_debug = ATH_DBG_DEFAULT; | ||
33 | module_param_named(debug, ath9k_debug, uint, 0); | ||
34 | MODULE_PARM_DESC(debug, "Debugging mask"); | ||
35 | |||
36 | /* We use the hw_value as an index into our private channel structure */ | ||
37 | |||
38 | #define CHAN2G(_freq, _idx) { \ | ||
39 | .center_freq = (_freq), \ | ||
40 | .hw_value = (_idx), \ | ||
41 | .max_power = 20, \ | ||
42 | } | ||
43 | |||
44 | #define CHAN5G(_freq, _idx) { \ | ||
45 | .band = IEEE80211_BAND_5GHZ, \ | ||
46 | .center_freq = (_freq), \ | ||
47 | .hw_value = (_idx), \ | ||
48 | .max_power = 20, \ | ||
49 | } | ||
50 | |||
51 | /* Some 2 GHz radios are actually tunable on 2312-2732 | ||
52 | * on 5 MHz steps, we support the channels which we know | ||
53 | * we have calibration data for all cards though to make | ||
54 | * this static */ | ||
55 | static struct ieee80211_channel ath9k_2ghz_chantable[] = { | ||
56 | CHAN2G(2412, 0), /* Channel 1 */ | ||
57 | CHAN2G(2417, 1), /* Channel 2 */ | ||
58 | CHAN2G(2422, 2), /* Channel 3 */ | ||
59 | CHAN2G(2427, 3), /* Channel 4 */ | ||
60 | CHAN2G(2432, 4), /* Channel 5 */ | ||
61 | CHAN2G(2437, 5), /* Channel 6 */ | ||
62 | CHAN2G(2442, 6), /* Channel 7 */ | ||
63 | CHAN2G(2447, 7), /* Channel 8 */ | ||
64 | CHAN2G(2452, 8), /* Channel 9 */ | ||
65 | CHAN2G(2457, 9), /* Channel 10 */ | ||
66 | CHAN2G(2462, 10), /* Channel 11 */ | ||
67 | CHAN2G(2467, 11), /* Channel 12 */ | ||
68 | CHAN2G(2472, 12), /* Channel 13 */ | ||
69 | CHAN2G(2484, 13), /* Channel 14 */ | ||
70 | }; | ||
71 | |||
72 | /* Some 5 GHz radios are actually tunable on XXXX-YYYY | ||
73 | * on 5 MHz steps, we support the channels which we know | ||
74 | * we have calibration data for all cards though to make | ||
75 | * this static */ | ||
76 | static struct ieee80211_channel ath9k_5ghz_chantable[] = { | ||
77 | /* _We_ call this UNII 1 */ | ||
78 | CHAN5G(5180, 14), /* Channel 36 */ | ||
79 | CHAN5G(5200, 15), /* Channel 40 */ | ||
80 | CHAN5G(5220, 16), /* Channel 44 */ | ||
81 | CHAN5G(5240, 17), /* Channel 48 */ | ||
82 | /* _We_ call this UNII 2 */ | ||
83 | CHAN5G(5260, 18), /* Channel 52 */ | ||
84 | CHAN5G(5280, 19), /* Channel 56 */ | ||
85 | CHAN5G(5300, 20), /* Channel 60 */ | ||
86 | CHAN5G(5320, 21), /* Channel 64 */ | ||
87 | /* _We_ call this "Middle band" */ | ||
88 | CHAN5G(5500, 22), /* Channel 100 */ | ||
89 | CHAN5G(5520, 23), /* Channel 104 */ | ||
90 | CHAN5G(5540, 24), /* Channel 108 */ | ||
91 | CHAN5G(5560, 25), /* Channel 112 */ | ||
92 | CHAN5G(5580, 26), /* Channel 116 */ | ||
93 | CHAN5G(5600, 27), /* Channel 120 */ | ||
94 | CHAN5G(5620, 28), /* Channel 124 */ | ||
95 | CHAN5G(5640, 29), /* Channel 128 */ | ||
96 | CHAN5G(5660, 30), /* Channel 132 */ | ||
97 | CHAN5G(5680, 31), /* Channel 136 */ | ||
98 | CHAN5G(5700, 32), /* Channel 140 */ | ||
99 | /* _We_ call this UNII 3 */ | ||
100 | CHAN5G(5745, 33), /* Channel 149 */ | ||
101 | CHAN5G(5765, 34), /* Channel 153 */ | ||
102 | CHAN5G(5785, 35), /* Channel 157 */ | ||
103 | CHAN5G(5805, 36), /* Channel 161 */ | ||
104 | CHAN5G(5825, 37), /* Channel 165 */ | ||
105 | }; | ||
106 | |||
107 | /* Atheros hardware rate code addition for short premble */ | ||
108 | #define SHPCHECK(__hw_rate, __flags) \ | ||
109 | ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04 ) : 0) | ||
110 | |||
111 | #define RATE(_bitrate, _hw_rate, _flags) { \ | ||
112 | .bitrate = (_bitrate), \ | ||
113 | .flags = (_flags), \ | ||
114 | .hw_value = (_hw_rate), \ | ||
115 | .hw_value_short = (SHPCHECK(_hw_rate, _flags)) \ | ||
116 | } | ||
117 | |||
118 | static struct ieee80211_rate ath9k_legacy_rates[] = { | ||
119 | RATE(10, 0x1b, 0), | ||
120 | RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE), | ||
121 | RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE), | ||
122 | RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE), | ||
123 | RATE(60, 0x0b, 0), | ||
124 | RATE(90, 0x0f, 0), | ||
125 | RATE(120, 0x0a, 0), | ||
126 | RATE(180, 0x0e, 0), | ||
127 | RATE(240, 0x09, 0), | ||
128 | RATE(360, 0x0d, 0), | ||
129 | RATE(480, 0x08, 0), | ||
130 | RATE(540, 0x0c, 0), | ||
131 | }; | ||
132 | |||
133 | static void ath_cache_conf_rate(struct ath_softc *sc, | 21 | static void ath_cache_conf_rate(struct ath_softc *sc, |
134 | struct ieee80211_conf *conf) | 22 | struct ieee80211_conf *conf) |
135 | { | 23 | { |
@@ -221,7 +109,7 @@ static struct ath9k_channel *ath_get_curchannel(struct ath_softc *sc, | |||
221 | return channel; | 109 | return channel; |
222 | } | 110 | } |
223 | 111 | ||
224 | static bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode) | 112 | bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode) |
225 | { | 113 | { |
226 | unsigned long flags; | 114 | unsigned long flags; |
227 | bool ret; | 115 | bool ret; |
@@ -255,11 +143,13 @@ void ath9k_ps_restore(struct ath_softc *sc) | |||
255 | if (--sc->ps_usecount != 0) | 143 | if (--sc->ps_usecount != 0) |
256 | goto unlock; | 144 | goto unlock; |
257 | 145 | ||
258 | if (sc->ps_enabled && | 146 | if (sc->ps_idle) |
259 | !(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | | 147 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); |
260 | SC_OP_WAIT_FOR_CAB | | 148 | else if (sc->ps_enabled && |
261 | SC_OP_WAIT_FOR_PSPOLL_DATA | | 149 | !(sc->ps_flags & (PS_WAIT_FOR_BEACON | |
262 | SC_OP_WAIT_FOR_TX_ACK))) | 150 | PS_WAIT_FOR_CAB | |
151 | PS_WAIT_FOR_PSPOLL_DATA | | ||
152 | PS_WAIT_FOR_TX_ACK))) | ||
263 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); | 153 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); |
264 | 154 | ||
265 | unlock: | 155 | unlock: |
@@ -316,7 +206,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
316 | r = ath9k_hw_reset(ah, hchan, fastcc); | 206 | r = ath9k_hw_reset(ah, hchan, fastcc); |
317 | if (r) { | 207 | if (r) { |
318 | ath_print(common, ATH_DBG_FATAL, | 208 | ath_print(common, ATH_DBG_FATAL, |
319 | "Unable to reset channel (%u Mhz) " | 209 | "Unable to reset channel (%u MHz), " |
320 | "reset status %d\n", | 210 | "reset status %d\n", |
321 | channel->center_freq, r); | 211 | channel->center_freq, r); |
322 | spin_unlock_bh(&sc->sc_resetlock); | 212 | spin_unlock_bh(&sc->sc_resetlock); |
@@ -349,7 +239,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
349 | * When the task is complete, it reschedules itself depending on the | 239 | * When the task is complete, it reschedules itself depending on the |
350 | * appropriate interval that was calculated. | 240 | * appropriate interval that was calculated. |
351 | */ | 241 | */ |
352 | static void ath_ani_calibrate(unsigned long data) | 242 | void ath_ani_calibrate(unsigned long data) |
353 | { | 243 | { |
354 | struct ath_softc *sc = (struct ath_softc *)data; | 244 | struct ath_softc *sc = (struct ath_softc *)data; |
355 | struct ath_hw *ah = sc->sc_ah; | 245 | struct ath_hw *ah = sc->sc_ah; |
@@ -363,14 +253,6 @@ static void ath_ani_calibrate(unsigned long data) | |||
363 | short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? | 253 | short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? |
364 | ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; | 254 | ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; |
365 | 255 | ||
366 | /* | ||
367 | * don't calibrate when we're scanning. | ||
368 | * we are most likely not on our home channel. | ||
369 | */ | ||
370 | spin_lock(&sc->ani_lock); | ||
371 | if (sc->sc_flags & SC_OP_SCANNING) | ||
372 | goto set_timer; | ||
373 | |||
374 | /* Only calibrate if awake */ | 256 | /* Only calibrate if awake */ |
375 | if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) | 257 | if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) |
376 | goto set_timer; | 258 | goto set_timer; |
@@ -437,7 +319,6 @@ static void ath_ani_calibrate(unsigned long data) | |||
437 | ath9k_ps_restore(sc); | 319 | ath9k_ps_restore(sc); |
438 | 320 | ||
439 | set_timer: | 321 | set_timer: |
440 | spin_unlock(&sc->ani_lock); | ||
441 | /* | 322 | /* |
442 | * Set timer interval based on previous results. | 323 | * Set timer interval based on previous results. |
443 | * The interval must be the shortest necessary to satisfy ANI, | 324 | * The interval must be the shortest necessary to satisfy ANI, |
@@ -513,7 +394,7 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) | |||
513 | ath_tx_node_cleanup(sc, an); | 394 | ath_tx_node_cleanup(sc, an); |
514 | } | 395 | } |
515 | 396 | ||
516 | static void ath9k_tasklet(unsigned long data) | 397 | void ath9k_tasklet(unsigned long data) |
517 | { | 398 | { |
518 | struct ath_softc *sc = (struct ath_softc *)data; | 399 | struct ath_softc *sc = (struct ath_softc *)data; |
519 | struct ath_hw *ah = sc->sc_ah; | 400 | struct ath_hw *ah = sc->sc_ah; |
@@ -545,7 +426,7 @@ static void ath9k_tasklet(unsigned long data) | |||
545 | */ | 426 | */ |
546 | ath_print(common, ATH_DBG_PS, | 427 | ath_print(common, ATH_DBG_PS, |
547 | "TSFOOR - Sync with next Beacon\n"); | 428 | "TSFOOR - Sync with next Beacon\n"); |
548 | sc->sc_flags |= SC_OP_WAIT_FOR_BEACON | SC_OP_BEACON_SYNC; | 429 | sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC; |
549 | } | 430 | } |
550 | 431 | ||
551 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) | 432 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) |
@@ -646,7 +527,7 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
646 | * receive frames */ | 527 | * receive frames */ |
647 | ath9k_setpower(sc, ATH9K_PM_AWAKE); | 528 | ath9k_setpower(sc, ATH9K_PM_AWAKE); |
648 | ath9k_hw_setrxabort(sc->sc_ah, 0); | 529 | ath9k_hw_setrxabort(sc->sc_ah, 0); |
649 | sc->sc_flags |= SC_OP_WAIT_FOR_BEACON; | 530 | sc->ps_flags |= PS_WAIT_FOR_BEACON; |
650 | } | 531 | } |
651 | 532 | ||
652 | chip_reset: | 533 | chip_reset: |
@@ -928,49 +809,12 @@ static void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf | |||
928 | 809 | ||
929 | clear_bit(key->hw_key_idx + 64, common->keymap); | 810 | clear_bit(key->hw_key_idx + 64, common->keymap); |
930 | if (common->splitmic) { | 811 | if (common->splitmic) { |
812 | ath9k_hw_keyreset(ah, key->hw_key_idx + 32); | ||
931 | clear_bit(key->hw_key_idx + 32, common->keymap); | 813 | clear_bit(key->hw_key_idx + 32, common->keymap); |
932 | clear_bit(key->hw_key_idx + 64 + 32, common->keymap); | 814 | clear_bit(key->hw_key_idx + 64 + 32, common->keymap); |
933 | } | 815 | } |
934 | } | 816 | } |
935 | 817 | ||
936 | static void setup_ht_cap(struct ath_softc *sc, | ||
937 | struct ieee80211_sta_ht_cap *ht_info) | ||
938 | { | ||
939 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
940 | u8 tx_streams, rx_streams; | ||
941 | |||
942 | ht_info->ht_supported = true; | ||
943 | ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | | ||
944 | IEEE80211_HT_CAP_SM_PS | | ||
945 | IEEE80211_HT_CAP_SGI_40 | | ||
946 | IEEE80211_HT_CAP_DSSSCCK40; | ||
947 | |||
948 | ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; | ||
949 | ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; | ||
950 | |||
951 | /* set up supported mcs set */ | ||
952 | memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); | ||
953 | tx_streams = !(common->tx_chainmask & (common->tx_chainmask - 1)) ? | ||
954 | 1 : 2; | ||
955 | rx_streams = !(common->rx_chainmask & (common->rx_chainmask - 1)) ? | ||
956 | 1 : 2; | ||
957 | |||
958 | if (tx_streams != rx_streams) { | ||
959 | ath_print(common, ATH_DBG_CONFIG, | ||
960 | "TX streams %d, RX streams: %d\n", | ||
961 | tx_streams, rx_streams); | ||
962 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; | ||
963 | ht_info->mcs.tx_params |= ((tx_streams - 1) << | ||
964 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); | ||
965 | } | ||
966 | |||
967 | ht_info->mcs.rx_mask[0] = 0xff; | ||
968 | if (rx_streams >= 2) | ||
969 | ht_info->mcs.rx_mask[1] = 0xff; | ||
970 | |||
971 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; | ||
972 | } | ||
973 | |||
974 | static void ath9k_bss_assoc_info(struct ath_softc *sc, | 818 | static void ath9k_bss_assoc_info(struct ath_softc *sc, |
975 | struct ieee80211_vif *vif, | 819 | struct ieee80211_vif *vif, |
976 | struct ieee80211_bss_conf *bss_conf) | 820 | struct ieee80211_bss_conf *bss_conf) |
@@ -992,7 +836,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, | |||
992 | * on the receipt of the first Beacon frame (i.e., | 836 | * on the receipt of the first Beacon frame (i.e., |
993 | * after time sync with the AP). | 837 | * after time sync with the AP). |
994 | */ | 838 | */ |
995 | sc->sc_flags |= SC_OP_BEACON_SYNC; | 839 | sc->ps_flags |= PS_BEACON_SYNC; |
996 | 840 | ||
997 | /* Configure the beacon */ | 841 | /* Configure the beacon */ |
998 | ath_beacon_config(sc, vif); | 842 | ath_beacon_config(sc, vif); |
@@ -1009,174 +853,6 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, | |||
1009 | } | 853 | } |
1010 | } | 854 | } |
1011 | 855 | ||
1012 | /********************************/ | ||
1013 | /* LED functions */ | ||
1014 | /********************************/ | ||
1015 | |||
1016 | static void ath_led_blink_work(struct work_struct *work) | ||
1017 | { | ||
1018 | struct ath_softc *sc = container_of(work, struct ath_softc, | ||
1019 | ath_led_blink_work.work); | ||
1020 | |||
1021 | if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED)) | ||
1022 | return; | ||
1023 | |||
1024 | if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) || | ||
1025 | (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) | ||
1026 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); | ||
1027 | else | ||
1028 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, | ||
1029 | (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0); | ||
1030 | |||
1031 | ieee80211_queue_delayed_work(sc->hw, | ||
1032 | &sc->ath_led_blink_work, | ||
1033 | (sc->sc_flags & SC_OP_LED_ON) ? | ||
1034 | msecs_to_jiffies(sc->led_off_duration) : | ||
1035 | msecs_to_jiffies(sc->led_on_duration)); | ||
1036 | |||
1037 | sc->led_on_duration = sc->led_on_cnt ? | ||
1038 | max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) : | ||
1039 | ATH_LED_ON_DURATION_IDLE; | ||
1040 | sc->led_off_duration = sc->led_off_cnt ? | ||
1041 | max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10) : | ||
1042 | ATH_LED_OFF_DURATION_IDLE; | ||
1043 | sc->led_on_cnt = sc->led_off_cnt = 0; | ||
1044 | if (sc->sc_flags & SC_OP_LED_ON) | ||
1045 | sc->sc_flags &= ~SC_OP_LED_ON; | ||
1046 | else | ||
1047 | sc->sc_flags |= SC_OP_LED_ON; | ||
1048 | } | ||
1049 | |||
1050 | static void ath_led_brightness(struct led_classdev *led_cdev, | ||
1051 | enum led_brightness brightness) | ||
1052 | { | ||
1053 | struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev); | ||
1054 | struct ath_softc *sc = led->sc; | ||
1055 | |||
1056 | switch (brightness) { | ||
1057 | case LED_OFF: | ||
1058 | if (led->led_type == ATH_LED_ASSOC || | ||
1059 | led->led_type == ATH_LED_RADIO) { | ||
1060 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, | ||
1061 | (led->led_type == ATH_LED_RADIO)); | ||
1062 | sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; | ||
1063 | if (led->led_type == ATH_LED_RADIO) | ||
1064 | sc->sc_flags &= ~SC_OP_LED_ON; | ||
1065 | } else { | ||
1066 | sc->led_off_cnt++; | ||
1067 | } | ||
1068 | break; | ||
1069 | case LED_FULL: | ||
1070 | if (led->led_type == ATH_LED_ASSOC) { | ||
1071 | sc->sc_flags |= SC_OP_LED_ASSOCIATED; | ||
1072 | ieee80211_queue_delayed_work(sc->hw, | ||
1073 | &sc->ath_led_blink_work, 0); | ||
1074 | } else if (led->led_type == ATH_LED_RADIO) { | ||
1075 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); | ||
1076 | sc->sc_flags |= SC_OP_LED_ON; | ||
1077 | } else { | ||
1078 | sc->led_on_cnt++; | ||
1079 | } | ||
1080 | break; | ||
1081 | default: | ||
1082 | break; | ||
1083 | } | ||
1084 | } | ||
1085 | |||
1086 | static int ath_register_led(struct ath_softc *sc, struct ath_led *led, | ||
1087 | char *trigger) | ||
1088 | { | ||
1089 | int ret; | ||
1090 | |||
1091 | led->sc = sc; | ||
1092 | led->led_cdev.name = led->name; | ||
1093 | led->led_cdev.default_trigger = trigger; | ||
1094 | led->led_cdev.brightness_set = ath_led_brightness; | ||
1095 | |||
1096 | ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev); | ||
1097 | if (ret) | ||
1098 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, | ||
1099 | "Failed to register led:%s", led->name); | ||
1100 | else | ||
1101 | led->registered = 1; | ||
1102 | return ret; | ||
1103 | } | ||
1104 | |||
1105 | static void ath_unregister_led(struct ath_led *led) | ||
1106 | { | ||
1107 | if (led->registered) { | ||
1108 | led_classdev_unregister(&led->led_cdev); | ||
1109 | led->registered = 0; | ||
1110 | } | ||
1111 | } | ||
1112 | |||
1113 | static void ath_deinit_leds(struct ath_softc *sc) | ||
1114 | { | ||
1115 | ath_unregister_led(&sc->assoc_led); | ||
1116 | sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; | ||
1117 | ath_unregister_led(&sc->tx_led); | ||
1118 | ath_unregister_led(&sc->rx_led); | ||
1119 | ath_unregister_led(&sc->radio_led); | ||
1120 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); | ||
1121 | } | ||
1122 | |||
1123 | static void ath_init_leds(struct ath_softc *sc) | ||
1124 | { | ||
1125 | char *trigger; | ||
1126 | int ret; | ||
1127 | |||
1128 | if (AR_SREV_9287(sc->sc_ah)) | ||
1129 | sc->sc_ah->led_pin = ATH_LED_PIN_9287; | ||
1130 | else | ||
1131 | sc->sc_ah->led_pin = ATH_LED_PIN_DEF; | ||
1132 | |||
1133 | /* Configure gpio 1 for output */ | ||
1134 | ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, | ||
1135 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
1136 | /* LED off, active low */ | ||
1137 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); | ||
1138 | |||
1139 | INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work); | ||
1140 | |||
1141 | trigger = ieee80211_get_radio_led_name(sc->hw); | ||
1142 | snprintf(sc->radio_led.name, sizeof(sc->radio_led.name), | ||
1143 | "ath9k-%s::radio", wiphy_name(sc->hw->wiphy)); | ||
1144 | ret = ath_register_led(sc, &sc->radio_led, trigger); | ||
1145 | sc->radio_led.led_type = ATH_LED_RADIO; | ||
1146 | if (ret) | ||
1147 | goto fail; | ||
1148 | |||
1149 | trigger = ieee80211_get_assoc_led_name(sc->hw); | ||
1150 | snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name), | ||
1151 | "ath9k-%s::assoc", wiphy_name(sc->hw->wiphy)); | ||
1152 | ret = ath_register_led(sc, &sc->assoc_led, trigger); | ||
1153 | sc->assoc_led.led_type = ATH_LED_ASSOC; | ||
1154 | if (ret) | ||
1155 | goto fail; | ||
1156 | |||
1157 | trigger = ieee80211_get_tx_led_name(sc->hw); | ||
1158 | snprintf(sc->tx_led.name, sizeof(sc->tx_led.name), | ||
1159 | "ath9k-%s::tx", wiphy_name(sc->hw->wiphy)); | ||
1160 | ret = ath_register_led(sc, &sc->tx_led, trigger); | ||
1161 | sc->tx_led.led_type = ATH_LED_TX; | ||
1162 | if (ret) | ||
1163 | goto fail; | ||
1164 | |||
1165 | trigger = ieee80211_get_rx_led_name(sc->hw); | ||
1166 | snprintf(sc->rx_led.name, sizeof(sc->rx_led.name), | ||
1167 | "ath9k-%s::rx", wiphy_name(sc->hw->wiphy)); | ||
1168 | ret = ath_register_led(sc, &sc->rx_led, trigger); | ||
1169 | sc->rx_led.led_type = ATH_LED_RX; | ||
1170 | if (ret) | ||
1171 | goto fail; | ||
1172 | |||
1173 | return; | ||
1174 | |||
1175 | fail: | ||
1176 | cancel_delayed_work_sync(&sc->ath_led_blink_work); | ||
1177 | ath_deinit_leds(sc); | ||
1178 | } | ||
1179 | |||
1180 | void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) | 856 | void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) |
1181 | { | 857 | { |
1182 | struct ath_hw *ah = sc->sc_ah; | 858 | struct ath_hw *ah = sc->sc_ah; |
@@ -1194,7 +870,7 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
1194 | r = ath9k_hw_reset(ah, ah->curchan, false); | 870 | r = ath9k_hw_reset(ah, ah->curchan, false); |
1195 | if (r) { | 871 | if (r) { |
1196 | ath_print(common, ATH_DBG_FATAL, | 872 | ath_print(common, ATH_DBG_FATAL, |
1197 | "Unable to reset channel %u (%uMhz) ", | 873 | "Unable to reset channel (%u MHz), " |
1198 | "reset status %d\n", | 874 | "reset status %d\n", |
1199 | channel->center_freq, r); | 875 | channel->center_freq, r); |
1200 | } | 876 | } |
@@ -1249,7 +925,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
1249 | r = ath9k_hw_reset(ah, ah->curchan, false); | 925 | r = ath9k_hw_reset(ah, ah->curchan, false); |
1250 | if (r) { | 926 | if (r) { |
1251 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, | 927 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, |
1252 | "Unable to reset channel %u (%uMhz) " | 928 | "Unable to reset channel (%u MHz), " |
1253 | "reset status %d\n", | 929 | "reset status %d\n", |
1254 | channel->center_freq, r); | 930 | channel->center_freq, r); |
1255 | } | 931 | } |
@@ -1261,711 +937,6 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
1261 | ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); | 937 | ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); |
1262 | } | 938 | } |
1263 | 939 | ||
1264 | /*******************/ | ||
1265 | /* Rfkill */ | ||
1266 | /*******************/ | ||
1267 | |||
1268 | static bool ath_is_rfkill_set(struct ath_softc *sc) | ||
1269 | { | ||
1270 | struct ath_hw *ah = sc->sc_ah; | ||
1271 | |||
1272 | return ath9k_hw_gpio_get(ah, ah->rfkill_gpio) == | ||
1273 | ah->rfkill_polarity; | ||
1274 | } | ||
1275 | |||
1276 | static void ath9k_rfkill_poll_state(struct ieee80211_hw *hw) | ||
1277 | { | ||
1278 | struct ath_wiphy *aphy = hw->priv; | ||
1279 | struct ath_softc *sc = aphy->sc; | ||
1280 | bool blocked = !!ath_is_rfkill_set(sc); | ||
1281 | |||
1282 | wiphy_rfkill_set_hw_state(hw->wiphy, blocked); | ||
1283 | } | ||
1284 | |||
1285 | static void ath_start_rfkill_poll(struct ath_softc *sc) | ||
1286 | { | ||
1287 | struct ath_hw *ah = sc->sc_ah; | ||
1288 | |||
1289 | if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) | ||
1290 | wiphy_rfkill_start_polling(sc->hw->wiphy); | ||
1291 | } | ||
1292 | |||
1293 | static void ath9k_uninit_hw(struct ath_softc *sc) | ||
1294 | { | ||
1295 | struct ath_hw *ah = sc->sc_ah; | ||
1296 | |||
1297 | BUG_ON(!ah); | ||
1298 | |||
1299 | ath9k_exit_debug(ah); | ||
1300 | ath9k_hw_detach(ah); | ||
1301 | sc->sc_ah = NULL; | ||
1302 | } | ||
1303 | |||
1304 | static void ath_clean_core(struct ath_softc *sc) | ||
1305 | { | ||
1306 | struct ieee80211_hw *hw = sc->hw; | ||
1307 | struct ath_hw *ah = sc->sc_ah; | ||
1308 | int i = 0; | ||
1309 | |||
1310 | ath9k_ps_wakeup(sc); | ||
1311 | |||
1312 | dev_dbg(sc->dev, "Detach ATH hw\n"); | ||
1313 | |||
1314 | ath_deinit_leds(sc); | ||
1315 | wiphy_rfkill_stop_polling(sc->hw->wiphy); | ||
1316 | |||
1317 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
1318 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
1319 | if (aphy == NULL) | ||
1320 | continue; | ||
1321 | sc->sec_wiphy[i] = NULL; | ||
1322 | ieee80211_unregister_hw(aphy->hw); | ||
1323 | ieee80211_free_hw(aphy->hw); | ||
1324 | } | ||
1325 | ieee80211_unregister_hw(hw); | ||
1326 | ath_rx_cleanup(sc); | ||
1327 | ath_tx_cleanup(sc); | ||
1328 | |||
1329 | tasklet_kill(&sc->intr_tq); | ||
1330 | tasklet_kill(&sc->bcon_tasklet); | ||
1331 | |||
1332 | if (!(sc->sc_flags & SC_OP_INVALID)) | ||
1333 | ath9k_setpower(sc, ATH9K_PM_AWAKE); | ||
1334 | |||
1335 | /* cleanup tx queues */ | ||
1336 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
1337 | if (ATH_TXQ_SETUP(sc, i)) | ||
1338 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | ||
1339 | |||
1340 | if ((sc->btcoex.no_stomp_timer) && | ||
1341 | ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) | ||
1342 | ath_gen_timer_free(ah, sc->btcoex.no_stomp_timer); | ||
1343 | } | ||
1344 | |||
1345 | void ath_detach(struct ath_softc *sc) | ||
1346 | { | ||
1347 | ath_clean_core(sc); | ||
1348 | ath9k_uninit_hw(sc); | ||
1349 | } | ||
1350 | |||
1351 | void ath_cleanup(struct ath_softc *sc) | ||
1352 | { | ||
1353 | struct ath_hw *ah = sc->sc_ah; | ||
1354 | struct ath_common *common = ath9k_hw_common(ah); | ||
1355 | |||
1356 | ath_clean_core(sc); | ||
1357 | free_irq(sc->irq, sc); | ||
1358 | ath_bus_cleanup(common); | ||
1359 | kfree(sc->sec_wiphy); | ||
1360 | ieee80211_free_hw(sc->hw); | ||
1361 | |||
1362 | ath9k_uninit_hw(sc); | ||
1363 | } | ||
1364 | |||
1365 | static int ath9k_reg_notifier(struct wiphy *wiphy, | ||
1366 | struct regulatory_request *request) | ||
1367 | { | ||
1368 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | ||
1369 | struct ath_wiphy *aphy = hw->priv; | ||
1370 | struct ath_softc *sc = aphy->sc; | ||
1371 | struct ath_regulatory *reg = ath9k_hw_regulatory(sc->sc_ah); | ||
1372 | |||
1373 | return ath_reg_notifier_apply(wiphy, request, reg); | ||
1374 | } | ||
1375 | |||
1376 | /* | ||
1377 | * Detects if there is any priority bt traffic | ||
1378 | */ | ||
1379 | static void ath_detect_bt_priority(struct ath_softc *sc) | ||
1380 | { | ||
1381 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
1382 | struct ath_hw *ah = sc->sc_ah; | ||
1383 | |||
1384 | if (ath9k_hw_gpio_get(sc->sc_ah, ah->btcoex_hw.btpriority_gpio)) | ||
1385 | btcoex->bt_priority_cnt++; | ||
1386 | |||
1387 | if (time_after(jiffies, btcoex->bt_priority_time + | ||
1388 | msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { | ||
1389 | if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { | ||
1390 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX, | ||
1391 | "BT priority traffic detected"); | ||
1392 | sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED; | ||
1393 | } else { | ||
1394 | sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; | ||
1395 | } | ||
1396 | |||
1397 | btcoex->bt_priority_cnt = 0; | ||
1398 | btcoex->bt_priority_time = jiffies; | ||
1399 | } | ||
1400 | } | ||
1401 | |||
1402 | /* | ||
1403 | * Configures appropriate weight based on stomp type. | ||
1404 | */ | ||
1405 | static void ath9k_btcoex_bt_stomp(struct ath_softc *sc, | ||
1406 | enum ath_stomp_type stomp_type) | ||
1407 | { | ||
1408 | struct ath_hw *ah = sc->sc_ah; | ||
1409 | |||
1410 | switch (stomp_type) { | ||
1411 | case ATH_BTCOEX_STOMP_ALL: | ||
1412 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
1413 | AR_STOMP_ALL_WLAN_WGHT); | ||
1414 | break; | ||
1415 | case ATH_BTCOEX_STOMP_LOW: | ||
1416 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
1417 | AR_STOMP_LOW_WLAN_WGHT); | ||
1418 | break; | ||
1419 | case ATH_BTCOEX_STOMP_NONE: | ||
1420 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
1421 | AR_STOMP_NONE_WLAN_WGHT); | ||
1422 | break; | ||
1423 | default: | ||
1424 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | ||
1425 | "Invalid Stomptype\n"); | ||
1426 | break; | ||
1427 | } | ||
1428 | |||
1429 | ath9k_hw_btcoex_enable(ah); | ||
1430 | } | ||
1431 | |||
1432 | static void ath9k_gen_timer_start(struct ath_hw *ah, | ||
1433 | struct ath_gen_timer *timer, | ||
1434 | u32 timer_next, | ||
1435 | u32 timer_period) | ||
1436 | { | ||
1437 | struct ath_common *common = ath9k_hw_common(ah); | ||
1438 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
1439 | |||
1440 | ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period); | ||
1441 | |||
1442 | if ((sc->imask & ATH9K_INT_GENTIMER) == 0) { | ||
1443 | ath9k_hw_set_interrupts(ah, 0); | ||
1444 | sc->imask |= ATH9K_INT_GENTIMER; | ||
1445 | ath9k_hw_set_interrupts(ah, sc->imask); | ||
1446 | } | ||
1447 | } | ||
1448 | |||
1449 | static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) | ||
1450 | { | ||
1451 | struct ath_common *common = ath9k_hw_common(ah); | ||
1452 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
1453 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; | ||
1454 | |||
1455 | ath9k_hw_gen_timer_stop(ah, timer); | ||
1456 | |||
1457 | /* if no timer is enabled, turn off interrupt mask */ | ||
1458 | if (timer_table->timer_mask.val == 0) { | ||
1459 | ath9k_hw_set_interrupts(ah, 0); | ||
1460 | sc->imask &= ~ATH9K_INT_GENTIMER; | ||
1461 | ath9k_hw_set_interrupts(ah, sc->imask); | ||
1462 | } | ||
1463 | } | ||
1464 | |||
1465 | /* | ||
1466 | * This is the master bt coex timer which runs for every | ||
1467 | * 45ms, bt traffic will be given priority during 55% of this | ||
1468 | * period while wlan gets remaining 45% | ||
1469 | */ | ||
1470 | static void ath_btcoex_period_timer(unsigned long data) | ||
1471 | { | ||
1472 | struct ath_softc *sc = (struct ath_softc *) data; | ||
1473 | struct ath_hw *ah = sc->sc_ah; | ||
1474 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
1475 | |||
1476 | ath_detect_bt_priority(sc); | ||
1477 | |||
1478 | spin_lock_bh(&btcoex->btcoex_lock); | ||
1479 | |||
1480 | ath9k_btcoex_bt_stomp(sc, btcoex->bt_stomp_type); | ||
1481 | |||
1482 | spin_unlock_bh(&btcoex->btcoex_lock); | ||
1483 | |||
1484 | if (btcoex->btcoex_period != btcoex->btcoex_no_stomp) { | ||
1485 | if (btcoex->hw_timer_enabled) | ||
1486 | ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); | ||
1487 | |||
1488 | ath9k_gen_timer_start(ah, | ||
1489 | btcoex->no_stomp_timer, | ||
1490 | (ath9k_hw_gettsf32(ah) + | ||
1491 | btcoex->btcoex_no_stomp), | ||
1492 | btcoex->btcoex_no_stomp * 10); | ||
1493 | btcoex->hw_timer_enabled = true; | ||
1494 | } | ||
1495 | |||
1496 | mod_timer(&btcoex->period_timer, jiffies + | ||
1497 | msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD)); | ||
1498 | } | ||
1499 | |||
1500 | /* | ||
1501 | * Generic tsf based hw timer which configures weight | ||
1502 | * registers to time slice between wlan and bt traffic | ||
1503 | */ | ||
1504 | static void ath_btcoex_no_stomp_timer(void *arg) | ||
1505 | { | ||
1506 | struct ath_softc *sc = (struct ath_softc *)arg; | ||
1507 | struct ath_hw *ah = sc->sc_ah; | ||
1508 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
1509 | |||
1510 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | ||
1511 | "no stomp timer running \n"); | ||
1512 | |||
1513 | spin_lock_bh(&btcoex->btcoex_lock); | ||
1514 | |||
1515 | if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW) | ||
1516 | ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_NONE); | ||
1517 | else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) | ||
1518 | ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_LOW); | ||
1519 | |||
1520 | spin_unlock_bh(&btcoex->btcoex_lock); | ||
1521 | } | ||
1522 | |||
1523 | static int ath_init_btcoex_timer(struct ath_softc *sc) | ||
1524 | { | ||
1525 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
1526 | |||
1527 | btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000; | ||
1528 | btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * | ||
1529 | btcoex->btcoex_period / 100; | ||
1530 | |||
1531 | setup_timer(&btcoex->period_timer, ath_btcoex_period_timer, | ||
1532 | (unsigned long) sc); | ||
1533 | |||
1534 | spin_lock_init(&btcoex->btcoex_lock); | ||
1535 | |||
1536 | btcoex->no_stomp_timer = ath_gen_timer_alloc(sc->sc_ah, | ||
1537 | ath_btcoex_no_stomp_timer, | ||
1538 | ath_btcoex_no_stomp_timer, | ||
1539 | (void *) sc, AR_FIRST_NDP_TIMER); | ||
1540 | |||
1541 | if (!btcoex->no_stomp_timer) | ||
1542 | return -ENOMEM; | ||
1543 | |||
1544 | return 0; | ||
1545 | } | ||
1546 | |||
1547 | /* | ||
1548 | * Read and write, they both share the same lock. We do this to serialize | ||
1549 | * reads and writes on Atheros 802.11n PCI devices only. This is required | ||
1550 | * as the FIFO on these devices can only accept sanely 2 requests. After | ||
1551 | * that the device goes bananas. Serializing the reads/writes prevents this | ||
1552 | * from happening. | ||
1553 | */ | ||
1554 | |||
1555 | static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset) | ||
1556 | { | ||
1557 | struct ath_hw *ah = (struct ath_hw *) hw_priv; | ||
1558 | struct ath_common *common = ath9k_hw_common(ah); | ||
1559 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
1560 | |||
1561 | if (ah->config.serialize_regmode == SER_REG_MODE_ON) { | ||
1562 | unsigned long flags; | ||
1563 | spin_lock_irqsave(&sc->sc_serial_rw, flags); | ||
1564 | iowrite32(val, sc->mem + reg_offset); | ||
1565 | spin_unlock_irqrestore(&sc->sc_serial_rw, flags); | ||
1566 | } else | ||
1567 | iowrite32(val, sc->mem + reg_offset); | ||
1568 | } | ||
1569 | |||
1570 | static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset) | ||
1571 | { | ||
1572 | struct ath_hw *ah = (struct ath_hw *) hw_priv; | ||
1573 | struct ath_common *common = ath9k_hw_common(ah); | ||
1574 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
1575 | u32 val; | ||
1576 | |||
1577 | if (ah->config.serialize_regmode == SER_REG_MODE_ON) { | ||
1578 | unsigned long flags; | ||
1579 | spin_lock_irqsave(&sc->sc_serial_rw, flags); | ||
1580 | val = ioread32(sc->mem + reg_offset); | ||
1581 | spin_unlock_irqrestore(&sc->sc_serial_rw, flags); | ||
1582 | } else | ||
1583 | val = ioread32(sc->mem + reg_offset); | ||
1584 | return val; | ||
1585 | } | ||
1586 | |||
1587 | static const struct ath_ops ath9k_common_ops = { | ||
1588 | .read = ath9k_ioread32, | ||
1589 | .write = ath9k_iowrite32, | ||
1590 | }; | ||
1591 | |||
1592 | /* | ||
1593 | * Initialize and fill ath_softc, ath_sofct is the | ||
1594 | * "Software Carrier" struct. Historically it has existed | ||
1595 | * to allow the separation between hardware specific | ||
1596 | * variables (now in ath_hw) and driver specific variables. | ||
1597 | */ | ||
1598 | static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, | ||
1599 | const struct ath_bus_ops *bus_ops) | ||
1600 | { | ||
1601 | struct ath_hw *ah = NULL; | ||
1602 | struct ath_common *common; | ||
1603 | int r = 0, i; | ||
1604 | int csz = 0; | ||
1605 | int qnum; | ||
1606 | |||
1607 | /* XXX: hardware will not be ready until ath_open() being called */ | ||
1608 | sc->sc_flags |= SC_OP_INVALID; | ||
1609 | |||
1610 | spin_lock_init(&sc->wiphy_lock); | ||
1611 | spin_lock_init(&sc->sc_resetlock); | ||
1612 | spin_lock_init(&sc->sc_serial_rw); | ||
1613 | spin_lock_init(&sc->ani_lock); | ||
1614 | spin_lock_init(&sc->sc_pm_lock); | ||
1615 | mutex_init(&sc->mutex); | ||
1616 | tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); | ||
1617 | tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, | ||
1618 | (unsigned long)sc); | ||
1619 | |||
1620 | ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); | ||
1621 | if (!ah) | ||
1622 | return -ENOMEM; | ||
1623 | |||
1624 | ah->hw_version.devid = devid; | ||
1625 | ah->hw_version.subsysid = subsysid; | ||
1626 | sc->sc_ah = ah; | ||
1627 | |||
1628 | common = ath9k_hw_common(ah); | ||
1629 | common->ops = &ath9k_common_ops; | ||
1630 | common->bus_ops = bus_ops; | ||
1631 | common->ah = ah; | ||
1632 | common->hw = sc->hw; | ||
1633 | common->priv = sc; | ||
1634 | common->debug_mask = ath9k_debug; | ||
1635 | |||
1636 | /* | ||
1637 | * Cache line size is used to size and align various | ||
1638 | * structures used to communicate with the hardware. | ||
1639 | */ | ||
1640 | ath_read_cachesize(common, &csz); | ||
1641 | /* XXX assert csz is non-zero */ | ||
1642 | common->cachelsz = csz << 2; /* convert to bytes */ | ||
1643 | |||
1644 | r = ath9k_hw_init(ah); | ||
1645 | if (r) { | ||
1646 | ath_print(common, ATH_DBG_FATAL, | ||
1647 | "Unable to initialize hardware; " | ||
1648 | "initialization status: %d\n", r); | ||
1649 | goto bad_free_hw; | ||
1650 | } | ||
1651 | |||
1652 | if (ath9k_init_debug(ah) < 0) { | ||
1653 | ath_print(common, ATH_DBG_FATAL, | ||
1654 | "Unable to create debugfs files\n"); | ||
1655 | goto bad_free_hw; | ||
1656 | } | ||
1657 | |||
1658 | /* Get the hardware key cache size. */ | ||
1659 | common->keymax = ah->caps.keycache_size; | ||
1660 | if (common->keymax > ATH_KEYMAX) { | ||
1661 | ath_print(common, ATH_DBG_ANY, | ||
1662 | "Warning, using only %u entries in %u key cache\n", | ||
1663 | ATH_KEYMAX, common->keymax); | ||
1664 | common->keymax = ATH_KEYMAX; | ||
1665 | } | ||
1666 | |||
1667 | /* | ||
1668 | * Reset the key cache since some parts do not | ||
1669 | * reset the contents on initial power up. | ||
1670 | */ | ||
1671 | for (i = 0; i < common->keymax; i++) | ||
1672 | ath9k_hw_keyreset(ah, (u16) i); | ||
1673 | |||
1674 | /* default to MONITOR mode */ | ||
1675 | sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR; | ||
1676 | |||
1677 | /* | ||
1678 | * Allocate hardware transmit queues: one queue for | ||
1679 | * beacon frames and one data queue for each QoS | ||
1680 | * priority. Note that the hal handles reseting | ||
1681 | * these queues at the needed time. | ||
1682 | */ | ||
1683 | sc->beacon.beaconq = ath9k_hw_beaconq_setup(ah); | ||
1684 | if (sc->beacon.beaconq == -1) { | ||
1685 | ath_print(common, ATH_DBG_FATAL, | ||
1686 | "Unable to setup a beacon xmit queue\n"); | ||
1687 | r = -EIO; | ||
1688 | goto bad2; | ||
1689 | } | ||
1690 | sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); | ||
1691 | if (sc->beacon.cabq == NULL) { | ||
1692 | ath_print(common, ATH_DBG_FATAL, | ||
1693 | "Unable to setup CAB xmit queue\n"); | ||
1694 | r = -EIO; | ||
1695 | goto bad2; | ||
1696 | } | ||
1697 | |||
1698 | sc->config.cabqReadytime = ATH_CABQ_READY_TIME; | ||
1699 | ath_cabq_update(sc); | ||
1700 | |||
1701 | for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++) | ||
1702 | sc->tx.hwq_map[i] = -1; | ||
1703 | |||
1704 | /* Setup data queues */ | ||
1705 | /* NB: ensure BK queue is the lowest priority h/w queue */ | ||
1706 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { | ||
1707 | ath_print(common, ATH_DBG_FATAL, | ||
1708 | "Unable to setup xmit queue for BK traffic\n"); | ||
1709 | r = -EIO; | ||
1710 | goto bad2; | ||
1711 | } | ||
1712 | |||
1713 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) { | ||
1714 | ath_print(common, ATH_DBG_FATAL, | ||
1715 | "Unable to setup xmit queue for BE traffic\n"); | ||
1716 | r = -EIO; | ||
1717 | goto bad2; | ||
1718 | } | ||
1719 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) { | ||
1720 | ath_print(common, ATH_DBG_FATAL, | ||
1721 | "Unable to setup xmit queue for VI traffic\n"); | ||
1722 | r = -EIO; | ||
1723 | goto bad2; | ||
1724 | } | ||
1725 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) { | ||
1726 | ath_print(common, ATH_DBG_FATAL, | ||
1727 | "Unable to setup xmit queue for VO traffic\n"); | ||
1728 | r = -EIO; | ||
1729 | goto bad2; | ||
1730 | } | ||
1731 | |||
1732 | /* Initializes the noise floor to a reasonable default value. | ||
1733 | * Later on this will be updated during ANI processing. */ | ||
1734 | |||
1735 | common->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR; | ||
1736 | setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc); | ||
1737 | |||
1738 | if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, | ||
1739 | ATH9K_CIPHER_TKIP, NULL)) { | ||
1740 | /* | ||
1741 | * Whether we should enable h/w TKIP MIC. | ||
1742 | * XXX: if we don't support WME TKIP MIC, then we wouldn't | ||
1743 | * report WMM capable, so it's always safe to turn on | ||
1744 | * TKIP MIC in this case. | ||
1745 | */ | ||
1746 | ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC, | ||
1747 | 0, 1, NULL); | ||
1748 | } | ||
1749 | |||
1750 | /* | ||
1751 | * Check whether the separate key cache entries | ||
1752 | * are required to handle both tx+rx MIC keys. | ||
1753 | * With split mic keys the number of stations is limited | ||
1754 | * to 27 otherwise 59. | ||
1755 | */ | ||
1756 | if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, | ||
1757 | ATH9K_CIPHER_TKIP, NULL) | ||
1758 | && ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, | ||
1759 | ATH9K_CIPHER_MIC, NULL) | ||
1760 | && ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT, | ||
1761 | 0, NULL)) | ||
1762 | common->splitmic = 1; | ||
1763 | |||
1764 | /* turn on mcast key search if possible */ | ||
1765 | if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) | ||
1766 | (void)ath9k_hw_setcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 1, | ||
1767 | 1, NULL); | ||
1768 | |||
1769 | sc->config.txpowlimit = ATH_TXPOWER_MAX; | ||
1770 | |||
1771 | /* 11n Capabilities */ | ||
1772 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) { | ||
1773 | sc->sc_flags |= SC_OP_TXAGGR; | ||
1774 | sc->sc_flags |= SC_OP_RXAGGR; | ||
1775 | } | ||
1776 | |||
1777 | common->tx_chainmask = ah->caps.tx_chainmask; | ||
1778 | common->rx_chainmask = ah->caps.rx_chainmask; | ||
1779 | |||
1780 | ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); | ||
1781 | sc->rx.defant = ath9k_hw_getdefantenna(ah); | ||
1782 | |||
1783 | if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | ||
1784 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); | ||
1785 | |||
1786 | sc->beacon.slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */ | ||
1787 | |||
1788 | /* initialize beacon slots */ | ||
1789 | for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { | ||
1790 | sc->beacon.bslot[i] = NULL; | ||
1791 | sc->beacon.bslot_aphy[i] = NULL; | ||
1792 | } | ||
1793 | |||
1794 | /* setup channels and rates */ | ||
1795 | |||
1796 | if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) { | ||
1797 | sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable; | ||
1798 | sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; | ||
1799 | sc->sbands[IEEE80211_BAND_2GHZ].n_channels = | ||
1800 | ARRAY_SIZE(ath9k_2ghz_chantable); | ||
1801 | sc->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates; | ||
1802 | sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates = | ||
1803 | ARRAY_SIZE(ath9k_legacy_rates); | ||
1804 | } | ||
1805 | |||
1806 | if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) { | ||
1807 | sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable; | ||
1808 | sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; | ||
1809 | sc->sbands[IEEE80211_BAND_5GHZ].n_channels = | ||
1810 | ARRAY_SIZE(ath9k_5ghz_chantable); | ||
1811 | sc->sbands[IEEE80211_BAND_5GHZ].bitrates = | ||
1812 | ath9k_legacy_rates + 4; | ||
1813 | sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates = | ||
1814 | ARRAY_SIZE(ath9k_legacy_rates) - 4; | ||
1815 | } | ||
1816 | |||
1817 | switch (ah->btcoex_hw.scheme) { | ||
1818 | case ATH_BTCOEX_CFG_NONE: | ||
1819 | break; | ||
1820 | case ATH_BTCOEX_CFG_2WIRE: | ||
1821 | ath9k_hw_btcoex_init_2wire(ah); | ||
1822 | break; | ||
1823 | case ATH_BTCOEX_CFG_3WIRE: | ||
1824 | ath9k_hw_btcoex_init_3wire(ah); | ||
1825 | r = ath_init_btcoex_timer(sc); | ||
1826 | if (r) | ||
1827 | goto bad2; | ||
1828 | qnum = ath_tx_get_qnum(sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); | ||
1829 | ath9k_hw_init_btcoex_hw(ah, qnum); | ||
1830 | sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; | ||
1831 | break; | ||
1832 | default: | ||
1833 | WARN_ON(1); | ||
1834 | break; | ||
1835 | } | ||
1836 | |||
1837 | return 0; | ||
1838 | bad2: | ||
1839 | /* cleanup tx queues */ | ||
1840 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
1841 | if (ATH_TXQ_SETUP(sc, i)) | ||
1842 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | ||
1843 | |||
1844 | bad_free_hw: | ||
1845 | ath9k_uninit_hw(sc); | ||
1846 | return r; | ||
1847 | } | ||
1848 | |||
1849 | void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | ||
1850 | { | ||
1851 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | | ||
1852 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | ||
1853 | IEEE80211_HW_SIGNAL_DBM | | ||
1854 | IEEE80211_HW_AMPDU_AGGREGATION | | ||
1855 | IEEE80211_HW_SUPPORTS_PS | | ||
1856 | IEEE80211_HW_PS_NULLFUNC_STACK | | ||
1857 | IEEE80211_HW_SPECTRUM_MGMT; | ||
1858 | |||
1859 | if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt) | ||
1860 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; | ||
1861 | |||
1862 | hw->wiphy->interface_modes = | ||
1863 | BIT(NL80211_IFTYPE_AP) | | ||
1864 | BIT(NL80211_IFTYPE_STATION) | | ||
1865 | BIT(NL80211_IFTYPE_ADHOC) | | ||
1866 | BIT(NL80211_IFTYPE_MESH_POINT); | ||
1867 | |||
1868 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | ||
1869 | |||
1870 | hw->queues = 4; | ||
1871 | hw->max_rates = 4; | ||
1872 | hw->channel_change_time = 5000; | ||
1873 | hw->max_listen_interval = 10; | ||
1874 | /* Hardware supports 10 but we use 4 */ | ||
1875 | hw->max_rate_tries = 4; | ||
1876 | hw->sta_data_size = sizeof(struct ath_node); | ||
1877 | hw->vif_data_size = sizeof(struct ath_vif); | ||
1878 | |||
1879 | hw->rate_control_algorithm = "ath9k_rate_control"; | ||
1880 | |||
1881 | if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) | ||
1882 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | ||
1883 | &sc->sbands[IEEE80211_BAND_2GHZ]; | ||
1884 | if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) | ||
1885 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | ||
1886 | &sc->sbands[IEEE80211_BAND_5GHZ]; | ||
1887 | } | ||
1888 | |||
1889 | /* Device driver core initialization */ | ||
1890 | int ath_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, | ||
1891 | const struct ath_bus_ops *bus_ops) | ||
1892 | { | ||
1893 | struct ieee80211_hw *hw = sc->hw; | ||
1894 | struct ath_common *common; | ||
1895 | struct ath_hw *ah; | ||
1896 | int error = 0, i; | ||
1897 | struct ath_regulatory *reg; | ||
1898 | |||
1899 | dev_dbg(sc->dev, "Attach ATH hw\n"); | ||
1900 | |||
1901 | error = ath_init_softc(devid, sc, subsysid, bus_ops); | ||
1902 | if (error != 0) | ||
1903 | return error; | ||
1904 | |||
1905 | ah = sc->sc_ah; | ||
1906 | common = ath9k_hw_common(ah); | ||
1907 | |||
1908 | /* get mac address from hardware and set in mac80211 */ | ||
1909 | |||
1910 | SET_IEEE80211_PERM_ADDR(hw, common->macaddr); | ||
1911 | |||
1912 | ath_set_hw_capab(sc, hw); | ||
1913 | |||
1914 | error = ath_regd_init(&common->regulatory, sc->hw->wiphy, | ||
1915 | ath9k_reg_notifier); | ||
1916 | if (error) | ||
1917 | return error; | ||
1918 | |||
1919 | reg = &common->regulatory; | ||
1920 | |||
1921 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) { | ||
1922 | if (test_bit(ATH9K_MODE_11G, ah->caps.wireless_modes)) | ||
1923 | setup_ht_cap(sc, | ||
1924 | &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); | ||
1925 | if (test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) | ||
1926 | setup_ht_cap(sc, | ||
1927 | &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); | ||
1928 | } | ||
1929 | |||
1930 | /* initialize tx/rx engine */ | ||
1931 | error = ath_tx_init(sc, ATH_TXBUF); | ||
1932 | if (error != 0) | ||
1933 | goto error_attach; | ||
1934 | |||
1935 | error = ath_rx_init(sc, ATH_RXBUF); | ||
1936 | if (error != 0) | ||
1937 | goto error_attach; | ||
1938 | |||
1939 | INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); | ||
1940 | INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); | ||
1941 | sc->wiphy_scheduler_int = msecs_to_jiffies(500); | ||
1942 | |||
1943 | error = ieee80211_register_hw(hw); | ||
1944 | |||
1945 | if (!ath_is_world_regd(reg)) { | ||
1946 | error = regulatory_hint(hw->wiphy, reg->alpha2); | ||
1947 | if (error) | ||
1948 | goto error_attach; | ||
1949 | } | ||
1950 | |||
1951 | /* Initialize LED control */ | ||
1952 | ath_init_leds(sc); | ||
1953 | |||
1954 | ath_start_rfkill_poll(sc); | ||
1955 | |||
1956 | return 0; | ||
1957 | |||
1958 | error_attach: | ||
1959 | /* cleanup tx queues */ | ||
1960 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
1961 | if (ATH_TXQ_SETUP(sc, i)) | ||
1962 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | ||
1963 | |||
1964 | ath9k_uninit_hw(sc); | ||
1965 | |||
1966 | return error; | ||
1967 | } | ||
1968 | |||
1969 | int ath_reset(struct ath_softc *sc, bool retry_tx) | 940 | int ath_reset(struct ath_softc *sc, bool retry_tx) |
1970 | { | 941 | { |
1971 | struct ath_hw *ah = sc->sc_ah; | 942 | struct ath_hw *ah = sc->sc_ah; |
@@ -1976,6 +947,8 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
1976 | /* Stop ANI */ | 947 | /* Stop ANI */ |
1977 | del_timer_sync(&common->ani.timer); | 948 | del_timer_sync(&common->ani.timer); |
1978 | 949 | ||
950 | ieee80211_stop_queues(hw); | ||
951 | |||
1979 | ath9k_hw_set_interrupts(ah, 0); | 952 | ath9k_hw_set_interrupts(ah, 0); |
1980 | ath_drain_all_txq(sc, retry_tx); | 953 | ath_drain_all_txq(sc, retry_tx); |
1981 | ath_stoprecv(sc); | 954 | ath_stoprecv(sc); |
@@ -2017,131 +990,14 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
2017 | } | 990 | } |
2018 | } | 991 | } |
2019 | 992 | ||
993 | ieee80211_wake_queues(hw); | ||
994 | |||
2020 | /* Start ANI */ | 995 | /* Start ANI */ |
2021 | ath_start_ani(common); | 996 | ath_start_ani(common); |
2022 | 997 | ||
2023 | return r; | 998 | return r; |
2024 | } | 999 | } |
2025 | 1000 | ||
2026 | /* | ||
2027 | * This function will allocate both the DMA descriptor structure, and the | ||
2028 | * buffers it contains. These are used to contain the descriptors used | ||
2029 | * by the system. | ||
2030 | */ | ||
2031 | int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | ||
2032 | struct list_head *head, const char *name, | ||
2033 | int nbuf, int ndesc) | ||
2034 | { | ||
2035 | #define DS2PHYS(_dd, _ds) \ | ||
2036 | ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) | ||
2037 | #define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0) | ||
2038 | #define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096) | ||
2039 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
2040 | struct ath_desc *ds; | ||
2041 | struct ath_buf *bf; | ||
2042 | int i, bsize, error; | ||
2043 | |||
2044 | ath_print(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n", | ||
2045 | name, nbuf, ndesc); | ||
2046 | |||
2047 | INIT_LIST_HEAD(head); | ||
2048 | /* ath_desc must be a multiple of DWORDs */ | ||
2049 | if ((sizeof(struct ath_desc) % 4) != 0) { | ||
2050 | ath_print(common, ATH_DBG_FATAL, | ||
2051 | "ath_desc not DWORD aligned\n"); | ||
2052 | BUG_ON((sizeof(struct ath_desc) % 4) != 0); | ||
2053 | error = -ENOMEM; | ||
2054 | goto fail; | ||
2055 | } | ||
2056 | |||
2057 | dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc; | ||
2058 | |||
2059 | /* | ||
2060 | * Need additional DMA memory because we can't use | ||
2061 | * descriptors that cross the 4K page boundary. Assume | ||
2062 | * one skipped descriptor per 4K page. | ||
2063 | */ | ||
2064 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) { | ||
2065 | u32 ndesc_skipped = | ||
2066 | ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len); | ||
2067 | u32 dma_len; | ||
2068 | |||
2069 | while (ndesc_skipped) { | ||
2070 | dma_len = ndesc_skipped * sizeof(struct ath_desc); | ||
2071 | dd->dd_desc_len += dma_len; | ||
2072 | |||
2073 | ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len); | ||
2074 | }; | ||
2075 | } | ||
2076 | |||
2077 | /* allocate descriptors */ | ||
2078 | dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len, | ||
2079 | &dd->dd_desc_paddr, GFP_KERNEL); | ||
2080 | if (dd->dd_desc == NULL) { | ||
2081 | error = -ENOMEM; | ||
2082 | goto fail; | ||
2083 | } | ||
2084 | ds = dd->dd_desc; | ||
2085 | ath_print(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", | ||
2086 | name, ds, (u32) dd->dd_desc_len, | ||
2087 | ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); | ||
2088 | |||
2089 | /* allocate buffers */ | ||
2090 | bsize = sizeof(struct ath_buf) * nbuf; | ||
2091 | bf = kzalloc(bsize, GFP_KERNEL); | ||
2092 | if (bf == NULL) { | ||
2093 | error = -ENOMEM; | ||
2094 | goto fail2; | ||
2095 | } | ||
2096 | dd->dd_bufptr = bf; | ||
2097 | |||
2098 | for (i = 0; i < nbuf; i++, bf++, ds += ndesc) { | ||
2099 | bf->bf_desc = ds; | ||
2100 | bf->bf_daddr = DS2PHYS(dd, ds); | ||
2101 | |||
2102 | if (!(sc->sc_ah->caps.hw_caps & | ||
2103 | ATH9K_HW_CAP_4KB_SPLITTRANS)) { | ||
2104 | /* | ||
2105 | * Skip descriptor addresses which can cause 4KB | ||
2106 | * boundary crossing (addr + length) with a 32 dword | ||
2107 | * descriptor fetch. | ||
2108 | */ | ||
2109 | while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { | ||
2110 | BUG_ON((caddr_t) bf->bf_desc >= | ||
2111 | ((caddr_t) dd->dd_desc + | ||
2112 | dd->dd_desc_len)); | ||
2113 | |||
2114 | ds += ndesc; | ||
2115 | bf->bf_desc = ds; | ||
2116 | bf->bf_daddr = DS2PHYS(dd, ds); | ||
2117 | } | ||
2118 | } | ||
2119 | list_add_tail(&bf->list, head); | ||
2120 | } | ||
2121 | return 0; | ||
2122 | fail2: | ||
2123 | dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, | ||
2124 | dd->dd_desc_paddr); | ||
2125 | fail: | ||
2126 | memset(dd, 0, sizeof(*dd)); | ||
2127 | return error; | ||
2128 | #undef ATH_DESC_4KB_BOUND_CHECK | ||
2129 | #undef ATH_DESC_4KB_BOUND_NUM_SKIPPED | ||
2130 | #undef DS2PHYS | ||
2131 | } | ||
2132 | |||
2133 | void ath_descdma_cleanup(struct ath_softc *sc, | ||
2134 | struct ath_descdma *dd, | ||
2135 | struct list_head *head) | ||
2136 | { | ||
2137 | dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, | ||
2138 | dd->dd_desc_paddr); | ||
2139 | |||
2140 | INIT_LIST_HEAD(head); | ||
2141 | kfree(dd->dd_bufptr); | ||
2142 | memset(dd, 0, sizeof(*dd)); | ||
2143 | } | ||
2144 | |||
2145 | int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) | 1001 | int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) |
2146 | { | 1002 | { |
2147 | int qnum; | 1003 | int qnum; |
@@ -2220,28 +1076,6 @@ void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
2220 | /* mac80211 callbacks */ | 1076 | /* mac80211 callbacks */ |
2221 | /**********************/ | 1077 | /**********************/ |
2222 | 1078 | ||
2223 | /* | ||
2224 | * (Re)start btcoex timers | ||
2225 | */ | ||
2226 | static void ath9k_btcoex_timer_resume(struct ath_softc *sc) | ||
2227 | { | ||
2228 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
2229 | struct ath_hw *ah = sc->sc_ah; | ||
2230 | |||
2231 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | ||
2232 | "Starting btcoex timers"); | ||
2233 | |||
2234 | /* make sure duty cycle timer is also stopped when resuming */ | ||
2235 | if (btcoex->hw_timer_enabled) | ||
2236 | ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); | ||
2237 | |||
2238 | btcoex->bt_priority_cnt = 0; | ||
2239 | btcoex->bt_priority_time = jiffies; | ||
2240 | sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; | ||
2241 | |||
2242 | mod_timer(&btcoex->period_timer, jiffies); | ||
2243 | } | ||
2244 | |||
2245 | static int ath9k_start(struct ieee80211_hw *hw) | 1079 | static int ath9k_start(struct ieee80211_hw *hw) |
2246 | { | 1080 | { |
2247 | struct ath_wiphy *aphy = hw->priv; | 1081 | struct ath_wiphy *aphy = hw->priv; |
@@ -2411,11 +1245,11 @@ static int ath9k_tx(struct ieee80211_hw *hw, | |||
2411 | if (ieee80211_is_pspoll(hdr->frame_control)) { | 1245 | if (ieee80211_is_pspoll(hdr->frame_control)) { |
2412 | ath_print(common, ATH_DBG_PS, | 1246 | ath_print(common, ATH_DBG_PS, |
2413 | "Sending PS-Poll to pick a buffered frame\n"); | 1247 | "Sending PS-Poll to pick a buffered frame\n"); |
2414 | sc->sc_flags |= SC_OP_WAIT_FOR_PSPOLL_DATA; | 1248 | sc->ps_flags |= PS_WAIT_FOR_PSPOLL_DATA; |
2415 | } else { | 1249 | } else { |
2416 | ath_print(common, ATH_DBG_PS, | 1250 | ath_print(common, ATH_DBG_PS, |
2417 | "Wake up to complete TX\n"); | 1251 | "Wake up to complete TX\n"); |
2418 | sc->sc_flags |= SC_OP_WAIT_FOR_TX_ACK; | 1252 | sc->ps_flags |= PS_WAIT_FOR_TX_ACK; |
2419 | } | 1253 | } |
2420 | /* | 1254 | /* |
2421 | * The actual restore operation will happen only after | 1255 | * The actual restore operation will happen only after |
@@ -2468,22 +1302,6 @@ exit: | |||
2468 | return 0; | 1302 | return 0; |
2469 | } | 1303 | } |
2470 | 1304 | ||
2471 | /* | ||
2472 | * Pause btcoex timer and bt duty cycle timer | ||
2473 | */ | ||
2474 | static void ath9k_btcoex_timer_pause(struct ath_softc *sc) | ||
2475 | { | ||
2476 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
2477 | struct ath_hw *ah = sc->sc_ah; | ||
2478 | |||
2479 | del_timer_sync(&btcoex->period_timer); | ||
2480 | |||
2481 | if (btcoex->hw_timer_enabled) | ||
2482 | ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); | ||
2483 | |||
2484 | btcoex->hw_timer_enabled = false; | ||
2485 | } | ||
2486 | |||
2487 | static void ath9k_stop(struct ieee80211_hw *hw) | 1305 | static void ath9k_stop(struct ieee80211_hw *hw) |
2488 | { | 1306 | { |
2489 | struct ath_wiphy *aphy = hw->priv; | 1307 | struct ath_wiphy *aphy = hw->priv; |
@@ -2550,12 +1368,12 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
2550 | } | 1368 | } |
2551 | 1369 | ||
2552 | static int ath9k_add_interface(struct ieee80211_hw *hw, | 1370 | static int ath9k_add_interface(struct ieee80211_hw *hw, |
2553 | struct ieee80211_if_init_conf *conf) | 1371 | struct ieee80211_vif *vif) |
2554 | { | 1372 | { |
2555 | struct ath_wiphy *aphy = hw->priv; | 1373 | struct ath_wiphy *aphy = hw->priv; |
2556 | struct ath_softc *sc = aphy->sc; | 1374 | struct ath_softc *sc = aphy->sc; |
2557 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1375 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
2558 | struct ath_vif *avp = (void *)conf->vif->drv_priv; | 1376 | struct ath_vif *avp = (void *)vif->drv_priv; |
2559 | enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; | 1377 | enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; |
2560 | int ret = 0; | 1378 | int ret = 0; |
2561 | 1379 | ||
@@ -2567,7 +1385,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
2567 | goto out; | 1385 | goto out; |
2568 | } | 1386 | } |
2569 | 1387 | ||
2570 | switch (conf->type) { | 1388 | switch (vif->type) { |
2571 | case NL80211_IFTYPE_STATION: | 1389 | case NL80211_IFTYPE_STATION: |
2572 | ic_opmode = NL80211_IFTYPE_STATION; | 1390 | ic_opmode = NL80211_IFTYPE_STATION; |
2573 | break; | 1391 | break; |
@@ -2578,11 +1396,11 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
2578 | ret = -ENOBUFS; | 1396 | ret = -ENOBUFS; |
2579 | goto out; | 1397 | goto out; |
2580 | } | 1398 | } |
2581 | ic_opmode = conf->type; | 1399 | ic_opmode = vif->type; |
2582 | break; | 1400 | break; |
2583 | default: | 1401 | default: |
2584 | ath_print(common, ATH_DBG_FATAL, | 1402 | ath_print(common, ATH_DBG_FATAL, |
2585 | "Interface type %d not yet supported\n", conf->type); | 1403 | "Interface type %d not yet supported\n", vif->type); |
2586 | ret = -EOPNOTSUPP; | 1404 | ret = -EOPNOTSUPP; |
2587 | goto out; | 1405 | goto out; |
2588 | } | 1406 | } |
@@ -2614,18 +1432,18 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
2614 | * Enable MIB interrupts when there are hardware phy counters. | 1432 | * Enable MIB interrupts when there are hardware phy counters. |
2615 | * Note we only do this (at the moment) for station mode. | 1433 | * Note we only do this (at the moment) for station mode. |
2616 | */ | 1434 | */ |
2617 | if ((conf->type == NL80211_IFTYPE_STATION) || | 1435 | if ((vif->type == NL80211_IFTYPE_STATION) || |
2618 | (conf->type == NL80211_IFTYPE_ADHOC) || | 1436 | (vif->type == NL80211_IFTYPE_ADHOC) || |
2619 | (conf->type == NL80211_IFTYPE_MESH_POINT)) { | 1437 | (vif->type == NL80211_IFTYPE_MESH_POINT)) { |
2620 | sc->imask |= ATH9K_INT_MIB; | 1438 | sc->imask |= ATH9K_INT_MIB; |
2621 | sc->imask |= ATH9K_INT_TSFOOR; | 1439 | sc->imask |= ATH9K_INT_TSFOOR; |
2622 | } | 1440 | } |
2623 | 1441 | ||
2624 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); | 1442 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); |
2625 | 1443 | ||
2626 | if (conf->type == NL80211_IFTYPE_AP || | 1444 | if (vif->type == NL80211_IFTYPE_AP || |
2627 | conf->type == NL80211_IFTYPE_ADHOC || | 1445 | vif->type == NL80211_IFTYPE_ADHOC || |
2628 | conf->type == NL80211_IFTYPE_MONITOR) | 1446 | vif->type == NL80211_IFTYPE_MONITOR) |
2629 | ath_start_ani(common); | 1447 | ath_start_ani(common); |
2630 | 1448 | ||
2631 | out: | 1449 | out: |
@@ -2634,12 +1452,12 @@ out: | |||
2634 | } | 1452 | } |
2635 | 1453 | ||
2636 | static void ath9k_remove_interface(struct ieee80211_hw *hw, | 1454 | static void ath9k_remove_interface(struct ieee80211_hw *hw, |
2637 | struct ieee80211_if_init_conf *conf) | 1455 | struct ieee80211_vif *vif) |
2638 | { | 1456 | { |
2639 | struct ath_wiphy *aphy = hw->priv; | 1457 | struct ath_wiphy *aphy = hw->priv; |
2640 | struct ath_softc *sc = aphy->sc; | 1458 | struct ath_softc *sc = aphy->sc; |
2641 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1459 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
2642 | struct ath_vif *avp = (void *)conf->vif->drv_priv; | 1460 | struct ath_vif *avp = (void *)vif->drv_priv; |
2643 | int i; | 1461 | int i; |
2644 | 1462 | ||
2645 | ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); | 1463 | ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); |
@@ -2662,7 +1480,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
2662 | sc->sc_flags &= ~SC_OP_BEACONS; | 1480 | sc->sc_flags &= ~SC_OP_BEACONS; |
2663 | 1481 | ||
2664 | for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { | 1482 | for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { |
2665 | if (sc->beacon.bslot[i] == conf->vif) { | 1483 | if (sc->beacon.bslot[i] == vif) { |
2666 | printk(KERN_DEBUG "%s: vif had allocated beacon " | 1484 | printk(KERN_DEBUG "%s: vif had allocated beacon " |
2667 | "slot\n", __func__); | 1485 | "slot\n", __func__); |
2668 | sc->beacon.bslot[i] = NULL; | 1486 | sc->beacon.bslot[i] = NULL; |
@@ -2675,6 +1493,19 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
2675 | mutex_unlock(&sc->mutex); | 1493 | mutex_unlock(&sc->mutex); |
2676 | } | 1494 | } |
2677 | 1495 | ||
1496 | void ath9k_enable_ps(struct ath_softc *sc) | ||
1497 | { | ||
1498 | sc->ps_enabled = true; | ||
1499 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { | ||
1500 | if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) { | ||
1501 | sc->imask |= ATH9K_INT_TIM_TIMER; | ||
1502 | ath9k_hw_set_interrupts(sc->sc_ah, | ||
1503 | sc->imask); | ||
1504 | } | ||
1505 | } | ||
1506 | ath9k_hw_setrxabort(sc->sc_ah, 1); | ||
1507 | } | ||
1508 | |||
2678 | static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | 1509 | static int ath9k_config(struct ieee80211_hw *hw, u32 changed) |
2679 | { | 1510 | { |
2680 | struct ath_wiphy *aphy = hw->priv; | 1511 | struct ath_wiphy *aphy = hw->priv; |
@@ -2713,6 +1544,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
2713 | spin_unlock_bh(&sc->wiphy_lock); | 1544 | spin_unlock_bh(&sc->wiphy_lock); |
2714 | 1545 | ||
2715 | if (enable_radio) { | 1546 | if (enable_radio) { |
1547 | sc->ps_idle = false; | ||
2716 | ath_radio_enable(sc, hw); | 1548 | ath_radio_enable(sc, hw); |
2717 | ath_print(common, ATH_DBG_CONFIG, | 1549 | ath_print(common, ATH_DBG_CONFIG, |
2718 | "not-idle: enabling radio\n"); | 1550 | "not-idle: enabling radio\n"); |
@@ -2727,36 +1559,27 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
2727 | */ | 1559 | */ |
2728 | if (changed & IEEE80211_CONF_CHANGE_PS) { | 1560 | if (changed & IEEE80211_CONF_CHANGE_PS) { |
2729 | if (conf->flags & IEEE80211_CONF_PS) { | 1561 | if (conf->flags & IEEE80211_CONF_PS) { |
2730 | sc->sc_flags |= SC_OP_PS_ENABLED; | 1562 | sc->ps_flags |= PS_ENABLED; |
2731 | if (!(ah->caps.hw_caps & | ||
2732 | ATH9K_HW_CAP_AUTOSLEEP)) { | ||
2733 | if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) { | ||
2734 | sc->imask |= ATH9K_INT_TIM_TIMER; | ||
2735 | ath9k_hw_set_interrupts(sc->sc_ah, | ||
2736 | sc->imask); | ||
2737 | } | ||
2738 | } | ||
2739 | /* | 1563 | /* |
2740 | * At this point we know hardware has received an ACK | 1564 | * At this point we know hardware has received an ACK |
2741 | * of a previously sent null data frame. | 1565 | * of a previously sent null data frame. |
2742 | */ | 1566 | */ |
2743 | if ((sc->sc_flags & SC_OP_NULLFUNC_COMPLETED)) { | 1567 | if ((sc->ps_flags & PS_NULLFUNC_COMPLETED)) { |
2744 | sc->sc_flags &= ~SC_OP_NULLFUNC_COMPLETED; | 1568 | sc->ps_flags &= ~PS_NULLFUNC_COMPLETED; |
2745 | sc->ps_enabled = true; | 1569 | ath9k_enable_ps(sc); |
2746 | ath9k_hw_setrxabort(sc->sc_ah, 1); | ||
2747 | } | 1570 | } |
2748 | } else { | 1571 | } else { |
2749 | sc->ps_enabled = false; | 1572 | sc->ps_enabled = false; |
2750 | sc->sc_flags &= ~(SC_OP_PS_ENABLED | | 1573 | sc->ps_flags &= ~(PS_ENABLED | |
2751 | SC_OP_NULLFUNC_COMPLETED); | 1574 | PS_NULLFUNC_COMPLETED); |
2752 | ath9k_setpower(sc, ATH9K_PM_AWAKE); | 1575 | ath9k_setpower(sc, ATH9K_PM_AWAKE); |
2753 | if (!(ah->caps.hw_caps & | 1576 | if (!(ah->caps.hw_caps & |
2754 | ATH9K_HW_CAP_AUTOSLEEP)) { | 1577 | ATH9K_HW_CAP_AUTOSLEEP)) { |
2755 | ath9k_hw_setrxabort(sc->sc_ah, 0); | 1578 | ath9k_hw_setrxabort(sc->sc_ah, 0); |
2756 | sc->sc_flags &= ~(SC_OP_WAIT_FOR_BEACON | | 1579 | sc->ps_flags &= ~(PS_WAIT_FOR_BEACON | |
2757 | SC_OP_WAIT_FOR_CAB | | 1580 | PS_WAIT_FOR_CAB | |
2758 | SC_OP_WAIT_FOR_PSPOLL_DATA | | 1581 | PS_WAIT_FOR_PSPOLL_DATA | |
2759 | SC_OP_WAIT_FOR_TX_ACK); | 1582 | PS_WAIT_FOR_TX_ACK); |
2760 | if (sc->imask & ATH9K_INT_TIM_TIMER) { | 1583 | if (sc->imask & ATH9K_INT_TIM_TIMER) { |
2761 | sc->imask &= ~ATH9K_INT_TIM_TIMER; | 1584 | sc->imask &= ~ATH9K_INT_TIM_TIMER; |
2762 | ath9k_hw_set_interrupts(sc->sc_ah, | 1585 | ath9k_hw_set_interrupts(sc->sc_ah, |
@@ -2766,6 +1589,14 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
2766 | } | 1589 | } |
2767 | } | 1590 | } |
2768 | 1591 | ||
1592 | if (changed & IEEE80211_CONF_CHANGE_MONITOR) { | ||
1593 | if (conf->flags & IEEE80211_CONF_MONITOR) { | ||
1594 | ath_print(common, ATH_DBG_CONFIG, | ||
1595 | "HW opmode set to Monitor mode\n"); | ||
1596 | sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR; | ||
1597 | } | ||
1598 | } | ||
1599 | |||
2769 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | 1600 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { |
2770 | struct ieee80211_channel *curchan = hw->conf.channel; | 1601 | struct ieee80211_channel *curchan = hw->conf.channel; |
2771 | int pos = curchan->hw_value; | 1602 | int pos = curchan->hw_value; |
@@ -2801,8 +1632,10 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
2801 | } | 1632 | } |
2802 | 1633 | ||
2803 | skip_chan_change: | 1634 | skip_chan_change: |
2804 | if (changed & IEEE80211_CONF_CHANGE_POWER) | 1635 | if (changed & IEEE80211_CONF_CHANGE_POWER) { |
2805 | sc->config.txpowlimit = 2 * conf->power_level; | 1636 | sc->config.txpowlimit = 2 * conf->power_level; |
1637 | ath_update_txpow(sc); | ||
1638 | } | ||
2806 | 1639 | ||
2807 | spin_lock_bh(&sc->wiphy_lock); | 1640 | spin_lock_bh(&sc->wiphy_lock); |
2808 | disable_radio = ath9k_all_wiphys_idle(sc); | 1641 | disable_radio = ath9k_all_wiphys_idle(sc); |
@@ -2810,6 +1643,7 @@ skip_chan_change: | |||
2810 | 1643 | ||
2811 | if (disable_radio) { | 1644 | if (disable_radio) { |
2812 | ath_print(common, ATH_DBG_CONFIG, "idle: disabling radio\n"); | 1645 | ath_print(common, ATH_DBG_CONFIG, "idle: disabling radio\n"); |
1646 | sc->ps_idle = true; | ||
2813 | ath_radio_disable(sc, hw); | 1647 | ath_radio_disable(sc, hw); |
2814 | } | 1648 | } |
2815 | 1649 | ||
@@ -2850,24 +1684,28 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw, | |||
2850 | "Set HW RX filter: 0x%x\n", rfilt); | 1684 | "Set HW RX filter: 0x%x\n", rfilt); |
2851 | } | 1685 | } |
2852 | 1686 | ||
2853 | static void ath9k_sta_notify(struct ieee80211_hw *hw, | 1687 | static int ath9k_sta_add(struct ieee80211_hw *hw, |
2854 | struct ieee80211_vif *vif, | 1688 | struct ieee80211_vif *vif, |
2855 | enum sta_notify_cmd cmd, | 1689 | struct ieee80211_sta *sta) |
2856 | struct ieee80211_sta *sta) | ||
2857 | { | 1690 | { |
2858 | struct ath_wiphy *aphy = hw->priv; | 1691 | struct ath_wiphy *aphy = hw->priv; |
2859 | struct ath_softc *sc = aphy->sc; | 1692 | struct ath_softc *sc = aphy->sc; |
2860 | 1693 | ||
2861 | switch (cmd) { | 1694 | ath_node_attach(sc, sta); |
2862 | case STA_NOTIFY_ADD: | 1695 | |
2863 | ath_node_attach(sc, sta); | 1696 | return 0; |
2864 | break; | 1697 | } |
2865 | case STA_NOTIFY_REMOVE: | 1698 | |
2866 | ath_node_detach(sc, sta); | 1699 | static int ath9k_sta_remove(struct ieee80211_hw *hw, |
2867 | break; | 1700 | struct ieee80211_vif *vif, |
2868 | default: | 1701 | struct ieee80211_sta *sta) |
2869 | break; | 1702 | { |
2870 | } | 1703 | struct ath_wiphy *aphy = hw->priv; |
1704 | struct ath_softc *sc = aphy->sc; | ||
1705 | |||
1706 | ath_node_detach(sc, sta); | ||
1707 | |||
1708 | return 0; | ||
2871 | } | 1709 | } |
2872 | 1710 | ||
2873 | static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, | 1711 | static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, |
@@ -2966,6 +1804,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
2966 | struct ath_hw *ah = sc->sc_ah; | 1804 | struct ath_hw *ah = sc->sc_ah; |
2967 | struct ath_common *common = ath9k_hw_common(ah); | 1805 | struct ath_common *common = ath9k_hw_common(ah); |
2968 | struct ath_vif *avp = (void *)vif->drv_priv; | 1806 | struct ath_vif *avp = (void *)vif->drv_priv; |
1807 | int slottime; | ||
2969 | int error; | 1808 | int error; |
2970 | 1809 | ||
2971 | mutex_lock(&sc->mutex); | 1810 | mutex_lock(&sc->mutex); |
@@ -3001,6 +1840,25 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
3001 | ath_beacon_config(sc, vif); | 1840 | ath_beacon_config(sc, vif); |
3002 | } | 1841 | } |
3003 | 1842 | ||
1843 | if (changed & BSS_CHANGED_ERP_SLOT) { | ||
1844 | if (bss_conf->use_short_slot) | ||
1845 | slottime = 9; | ||
1846 | else | ||
1847 | slottime = 20; | ||
1848 | if (vif->type == NL80211_IFTYPE_AP) { | ||
1849 | /* | ||
1850 | * Defer update, so that connected stations can adjust | ||
1851 | * their settings at the same time. | ||
1852 | * See beacon.c for more details | ||
1853 | */ | ||
1854 | sc->beacon.slottime = slottime; | ||
1855 | sc->beacon.updateslot = UPDATE; | ||
1856 | } else { | ||
1857 | ah->slottime = slottime; | ||
1858 | ath9k_hw_init_global_settings(ah); | ||
1859 | } | ||
1860 | } | ||
1861 | |||
3004 | /* Disable transmission of beacons */ | 1862 | /* Disable transmission of beacons */ |
3005 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon) | 1863 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon) |
3006 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); | 1864 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); |
@@ -3133,6 +1991,7 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) | |||
3133 | { | 1991 | { |
3134 | struct ath_wiphy *aphy = hw->priv; | 1992 | struct ath_wiphy *aphy = hw->priv; |
3135 | struct ath_softc *sc = aphy->sc; | 1993 | struct ath_softc *sc = aphy->sc; |
1994 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
3136 | 1995 | ||
3137 | mutex_lock(&sc->mutex); | 1996 | mutex_lock(&sc->mutex); |
3138 | if (ath9k_wiphy_scanning(sc)) { | 1997 | if (ath9k_wiphy_scanning(sc)) { |
@@ -3148,10 +2007,9 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) | |||
3148 | 2007 | ||
3149 | aphy->state = ATH_WIPHY_SCAN; | 2008 | aphy->state = ATH_WIPHY_SCAN; |
3150 | ath9k_wiphy_pause_all_forced(sc, aphy); | 2009 | ath9k_wiphy_pause_all_forced(sc, aphy); |
3151 | |||
3152 | spin_lock_bh(&sc->ani_lock); | ||
3153 | sc->sc_flags |= SC_OP_SCANNING; | 2010 | sc->sc_flags |= SC_OP_SCANNING; |
3154 | spin_unlock_bh(&sc->ani_lock); | 2011 | del_timer_sync(&common->ani.timer); |
2012 | cancel_delayed_work_sync(&sc->tx_complete_work); | ||
3155 | mutex_unlock(&sc->mutex); | 2013 | mutex_unlock(&sc->mutex); |
3156 | } | 2014 | } |
3157 | 2015 | ||
@@ -3159,17 +2017,30 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) | |||
3159 | { | 2017 | { |
3160 | struct ath_wiphy *aphy = hw->priv; | 2018 | struct ath_wiphy *aphy = hw->priv; |
3161 | struct ath_softc *sc = aphy->sc; | 2019 | struct ath_softc *sc = aphy->sc; |
2020 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
3162 | 2021 | ||
3163 | mutex_lock(&sc->mutex); | 2022 | mutex_lock(&sc->mutex); |
3164 | spin_lock_bh(&sc->ani_lock); | ||
3165 | aphy->state = ATH_WIPHY_ACTIVE; | 2023 | aphy->state = ATH_WIPHY_ACTIVE; |
3166 | sc->sc_flags &= ~SC_OP_SCANNING; | 2024 | sc->sc_flags &= ~SC_OP_SCANNING; |
3167 | sc->sc_flags |= SC_OP_FULL_RESET; | 2025 | sc->sc_flags |= SC_OP_FULL_RESET; |
3168 | spin_unlock_bh(&sc->ani_lock); | 2026 | ath_start_ani(common); |
2027 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); | ||
3169 | ath_beacon_config(sc, NULL); | 2028 | ath_beacon_config(sc, NULL); |
3170 | mutex_unlock(&sc->mutex); | 2029 | mutex_unlock(&sc->mutex); |
3171 | } | 2030 | } |
3172 | 2031 | ||
2032 | static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) | ||
2033 | { | ||
2034 | struct ath_wiphy *aphy = hw->priv; | ||
2035 | struct ath_softc *sc = aphy->sc; | ||
2036 | struct ath_hw *ah = sc->sc_ah; | ||
2037 | |||
2038 | mutex_lock(&sc->mutex); | ||
2039 | ah->coverage_class = coverage_class; | ||
2040 | ath9k_hw_init_global_settings(ah); | ||
2041 | mutex_unlock(&sc->mutex); | ||
2042 | } | ||
2043 | |||
3173 | struct ieee80211_ops ath9k_ops = { | 2044 | struct ieee80211_ops ath9k_ops = { |
3174 | .tx = ath9k_tx, | 2045 | .tx = ath9k_tx, |
3175 | .start = ath9k_start, | 2046 | .start = ath9k_start, |
@@ -3178,7 +2049,8 @@ struct ieee80211_ops ath9k_ops = { | |||
3178 | .remove_interface = ath9k_remove_interface, | 2049 | .remove_interface = ath9k_remove_interface, |
3179 | .config = ath9k_config, | 2050 | .config = ath9k_config, |
3180 | .configure_filter = ath9k_configure_filter, | 2051 | .configure_filter = ath9k_configure_filter, |
3181 | .sta_notify = ath9k_sta_notify, | 2052 | .sta_add = ath9k_sta_add, |
2053 | .sta_remove = ath9k_sta_remove, | ||
3182 | .conf_tx = ath9k_conf_tx, | 2054 | .conf_tx = ath9k_conf_tx, |
3183 | .bss_info_changed = ath9k_bss_info_changed, | 2055 | .bss_info_changed = ath9k_bss_info_changed, |
3184 | .set_key = ath9k_set_key, | 2056 | .set_key = ath9k_set_key, |
@@ -3189,64 +2061,5 @@ struct ieee80211_ops ath9k_ops = { | |||
3189 | .sw_scan_start = ath9k_sw_scan_start, | 2061 | .sw_scan_start = ath9k_sw_scan_start, |
3190 | .sw_scan_complete = ath9k_sw_scan_complete, | 2062 | .sw_scan_complete = ath9k_sw_scan_complete, |
3191 | .rfkill_poll = ath9k_rfkill_poll_state, | 2063 | .rfkill_poll = ath9k_rfkill_poll_state, |
2064 | .set_coverage_class = ath9k_set_coverage_class, | ||
3192 | }; | 2065 | }; |
3193 | |||
3194 | static int __init ath9k_init(void) | ||
3195 | { | ||
3196 | int error; | ||
3197 | |||
3198 | /* Register rate control algorithm */ | ||
3199 | error = ath_rate_control_register(); | ||
3200 | if (error != 0) { | ||
3201 | printk(KERN_ERR | ||
3202 | "ath9k: Unable to register rate control " | ||
3203 | "algorithm: %d\n", | ||
3204 | error); | ||
3205 | goto err_out; | ||
3206 | } | ||
3207 | |||
3208 | error = ath9k_debug_create_root(); | ||
3209 | if (error) { | ||
3210 | printk(KERN_ERR | ||
3211 | "ath9k: Unable to create debugfs root: %d\n", | ||
3212 | error); | ||
3213 | goto err_rate_unregister; | ||
3214 | } | ||
3215 | |||
3216 | error = ath_pci_init(); | ||
3217 | if (error < 0) { | ||
3218 | printk(KERN_ERR | ||
3219 | "ath9k: No PCI devices found, driver not installed.\n"); | ||
3220 | error = -ENODEV; | ||
3221 | goto err_remove_root; | ||
3222 | } | ||
3223 | |||
3224 | error = ath_ahb_init(); | ||
3225 | if (error < 0) { | ||
3226 | error = -ENODEV; | ||
3227 | goto err_pci_exit; | ||
3228 | } | ||
3229 | |||
3230 | return 0; | ||
3231 | |||
3232 | err_pci_exit: | ||
3233 | ath_pci_exit(); | ||
3234 | |||
3235 | err_remove_root: | ||
3236 | ath9k_debug_remove_root(); | ||
3237 | err_rate_unregister: | ||
3238 | ath_rate_control_unregister(); | ||
3239 | err_out: | ||
3240 | return error; | ||
3241 | } | ||
3242 | module_init(ath9k_init); | ||
3243 | |||
3244 | static void __exit ath9k_exit(void) | ||
3245 | { | ||
3246 | ath_ahb_exit(); | ||
3247 | ath_pci_exit(); | ||
3248 | ath9k_debug_remove_root(); | ||
3249 | ath_rate_control_unregister(); | ||
3250 | printk(KERN_INFO "%s: Driver unloaded\n", dev_info); | ||
3251 | } | ||
3252 | module_exit(ath9k_exit); | ||
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index f7af5ea54753..f318b3b1abe9 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -25,6 +25,7 @@ static struct pci_device_id ath_pci_id_table[] __devinitdata = { | |||
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 | }; |
@@ -113,25 +103,22 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
113 | u16 subsysid; | 103 | u16 subsysid; |
114 | u32 val; | 104 | u32 val; |
115 | int ret = 0; | 105 | int ret = 0; |
116 | struct ath_hw *ah; | ||
117 | char hw_name[64]; | 106 | char hw_name[64]; |
118 | 107 | ||
119 | if (pci_enable_device(pdev)) | 108 | if (pci_enable_device(pdev)) |
120 | return -EIO; | 109 | return -EIO; |
121 | 110 | ||
122 | ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | 111 | ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); |
123 | |||
124 | if (ret) { | 112 | if (ret) { |
125 | printk(KERN_ERR "ath9k: 32-bit DMA not available\n"); | 113 | printk(KERN_ERR "ath9k: 32-bit DMA not available\n"); |
126 | goto bad; | 114 | goto err_dma; |
127 | } | 115 | } |
128 | 116 | ||
129 | ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); | 117 | ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); |
130 | |||
131 | if (ret) { | 118 | if (ret) { |
132 | printk(KERN_ERR "ath9k: 32-bit DMA consistent " | 119 | printk(KERN_ERR "ath9k: 32-bit DMA consistent " |
133 | "DMA enable failed\n"); | 120 | "DMA enable failed\n"); |
134 | goto bad; | 121 | goto err_dma; |
135 | } | 122 | } |
136 | 123 | ||
137 | /* | 124 | /* |
@@ -171,22 +158,22 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
171 | if (ret) { | 158 | if (ret) { |
172 | dev_err(&pdev->dev, "PCI memory region reserve error\n"); | 159 | dev_err(&pdev->dev, "PCI memory region reserve error\n"); |
173 | ret = -ENODEV; | 160 | ret = -ENODEV; |
174 | goto bad; | 161 | goto err_region; |
175 | } | 162 | } |
176 | 163 | ||
177 | mem = pci_iomap(pdev, 0, 0); | 164 | mem = pci_iomap(pdev, 0, 0); |
178 | if (!mem) { | 165 | if (!mem) { |
179 | printk(KERN_ERR "PCI memory map error\n") ; | 166 | printk(KERN_ERR "PCI memory map error\n") ; |
180 | ret = -EIO; | 167 | ret = -EIO; |
181 | goto bad1; | 168 | goto err_iomap; |
182 | } | 169 | } |
183 | 170 | ||
184 | hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) + | 171 | hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) + |
185 | sizeof(struct ath_softc), &ath9k_ops); | 172 | sizeof(struct ath_softc), &ath9k_ops); |
186 | if (!hw) { | 173 | if (!hw) { |
187 | dev_err(&pdev->dev, "no memory for ieee80211_hw\n"); | 174 | dev_err(&pdev->dev, "No memory for ieee80211_hw\n"); |
188 | ret = -ENOMEM; | 175 | ret = -ENOMEM; |
189 | goto bad2; | 176 | goto err_alloc_hw; |
190 | } | 177 | } |
191 | 178 | ||
192 | SET_IEEE80211_DEV(hw, &pdev->dev); | 179 | SET_IEEE80211_DEV(hw, &pdev->dev); |
@@ -201,25 +188,25 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
201 | sc->dev = &pdev->dev; | 188 | sc->dev = &pdev->dev; |
202 | sc->mem = mem; | 189 | sc->mem = mem; |
203 | 190 | ||
204 | pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsysid); | 191 | /* Will be cleared in ath9k_start() */ |
205 | ret = ath_init_device(id->device, sc, subsysid, &ath_pci_bus_ops); | 192 | sc->sc_flags |= SC_OP_INVALID; |
206 | if (ret) { | ||
207 | dev_err(&pdev->dev, "failed to initialize device\n"); | ||
208 | goto bad3; | ||
209 | } | ||
210 | |||
211 | /* setup interrupt service routine */ | ||
212 | 193 | ||
213 | ret = request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath9k", sc); | 194 | ret = request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath9k", sc); |
214 | if (ret) { | 195 | if (ret) { |
215 | dev_err(&pdev->dev, "request_irq failed\n"); | 196 | dev_err(&pdev->dev, "request_irq failed\n"); |
216 | goto bad4; | 197 | goto err_irq; |
217 | } | 198 | } |
218 | 199 | ||
219 | sc->irq = pdev->irq; | 200 | sc->irq = pdev->irq; |
220 | 201 | ||
221 | ah = sc->sc_ah; | 202 | pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsysid); |
222 | ath9k_hw_name(ah, hw_name, sizeof(hw_name)); | 203 | ret = ath9k_init_device(id->device, sc, subsysid, &ath_pci_bus_ops); |
204 | if (ret) { | ||
205 | dev_err(&pdev->dev, "Failed to initialize device\n"); | ||
206 | goto err_init; | ||
207 | } | ||
208 | |||
209 | ath9k_hw_name(sc->sc_ah, hw_name, sizeof(hw_name)); | ||
223 | printk(KERN_INFO | 210 | printk(KERN_INFO |
224 | "%s: %s mem=0x%lx, irq=%d\n", | 211 | "%s: %s mem=0x%lx, irq=%d\n", |
225 | wiphy_name(hw->wiphy), | 212 | wiphy_name(hw->wiphy), |
@@ -227,15 +214,18 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
227 | (unsigned long)mem, pdev->irq); | 214 | (unsigned long)mem, pdev->irq); |
228 | 215 | ||
229 | return 0; | 216 | return 0; |
230 | bad4: | 217 | |
231 | ath_detach(sc); | 218 | err_init: |
232 | bad3: | 219 | free_irq(sc->irq, sc); |
220 | err_irq: | ||
233 | ieee80211_free_hw(hw); | 221 | ieee80211_free_hw(hw); |
234 | bad2: | 222 | err_alloc_hw: |
235 | pci_iounmap(pdev, mem); | 223 | pci_iounmap(pdev, mem); |
236 | bad1: | 224 | err_iomap: |
237 | pci_release_region(pdev, 0); | 225 | pci_release_region(pdev, 0); |
238 | bad: | 226 | err_region: |
227 | /* Nothing */ | ||
228 | err_dma: | ||
239 | pci_disable_device(pdev); | 229 | pci_disable_device(pdev); |
240 | return ret; | 230 | return ret; |
241 | } | 231 | } |
@@ -245,8 +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; |
238 | void __iomem *mem = sc->mem; | ||
239 | |||
240 | ath9k_deinit_device(sc); | ||
241 | free_irq(sc->irq, sc); | ||
242 | ieee80211_free_hw(sc->hw); | ||
248 | 243 | ||
249 | ath_cleanup(sc); | 244 | pci_iounmap(pdev, mem); |
245 | pci_disable_device(pdev); | ||
246 | pci_release_region(pdev, 0); | ||
250 | } | 247 | } |
251 | 248 | ||
252 | #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 c915954d4d5b..2880507f9d3f 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -668,7 +668,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
668 | struct ieee80211_tx_rate *rates = tx_info->control.rates; | 668 | struct ieee80211_tx_rate *rates = tx_info->control.rates; |
669 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 669 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
670 | __le16 fc = hdr->frame_control; | 670 | __le16 fc = hdr->frame_control; |
671 | u8 try_per_rate, i = 0, rix, nrix; | 671 | u8 try_per_rate, i = 0, rix; |
672 | int is_probe = 0; | 672 | int is_probe = 0; |
673 | 673 | ||
674 | if (rate_control_send_low(sta, priv_sta, txrc)) | 674 | if (rate_control_send_low(sta, priv_sta, txrc)) |
@@ -678,48 +678,47 @@ 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); |
691 | nrix = rix; | ||
692 | 691 | ||
693 | if (is_probe) { | 692 | if (is_probe) { |
694 | /* set one try for probe rates. For the | 693 | /* set one try for probe rates. For the |
695 | * probes don't enable rts */ | 694 | * probes don't enable rts */ |
696 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, | 695 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, |
697 | 1, nrix, 0); | 696 | 1, rix, 0); |
698 | 697 | ||
699 | /* Get the next tried/allowed rate. No RTS for the next series | 698 | /* Get the next tried/allowed rate. No RTS for the next series |
700 | * after the probe rate | 699 | * after the probe rate |
701 | */ | 700 | */ |
702 | ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix); | 701 | ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix); |
703 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, | 702 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, |
704 | try_per_rate, nrix, 0); | 703 | try_per_rate, rix, 0); |
705 | 704 | ||
706 | tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; | 705 | tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; |
707 | } else { | 706 | } else { |
708 | /* Set the choosen rate. No RTS for first series entry. */ | 707 | /* Set the choosen rate. No RTS for first series entry. */ |
709 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, | 708 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, |
710 | try_per_rate, nrix, 0); | 709 | try_per_rate, rix, 0); |
711 | } | 710 | } |
712 | 711 | ||
713 | /* Fill in the other rates for multirate retry */ | 712 | /* Fill in the other rates for multirate retry */ |
714 | for ( ; i < 4; i++) { | 713 | for ( ; i < 4; i++) { |
715 | /* Use twice the number of tries for the last MRR segment. */ | 714 | /* Use twice the number of tries for the last MRR segment. */ |
716 | if (i + 1 == 4) | 715 | if (i + 1 == 4) |
717 | try_per_rate = 4; | 716 | try_per_rate = 8; |
718 | 717 | ||
719 | ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix); | 718 | ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix); |
720 | /* All other rates in the series have RTS enabled */ | 719 | /* All other rates in the series have RTS enabled */ |
721 | ath_rc_rate_set_series(rate_table, &rates[i], txrc, | 720 | ath_rc_rate_set_series(rate_table, &rates[i], txrc, |
722 | try_per_rate, nrix, 1); | 721 | try_per_rate, rix, 1); |
723 | } | 722 | } |
724 | 723 | ||
725 | /* | 724 | /* |
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index 9eb96f506998..4f6d6fd442f4 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h | |||
@@ -57,6 +57,10 @@ enum { | |||
57 | || (_phy == WLAN_RC_PHY_HT_40_DS) \ | 57 | || (_phy == WLAN_RC_PHY_HT_40_DS) \ |
58 | || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ | 58 | || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ |
59 | || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) | 59 | || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) |
60 | #define WLAN_RC_PHY_20(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS) \ | ||
61 | || (_phy == WLAN_RC_PHY_HT_20_DS) \ | ||
62 | || (_phy == WLAN_RC_PHY_HT_20_SS_HGI) \ | ||
63 | || (_phy == WLAN_RC_PHY_HT_20_DS_HGI)) | ||
60 | #define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) \ | 64 | #define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) \ |
61 | || (_phy == WLAN_RC_PHY_HT_40_DS) \ | 65 | || (_phy == WLAN_RC_PHY_HT_40_DS) \ |
62 | || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ | 66 | || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 477365e5ae69..1ca42e5148c8 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -364,10 +364,10 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) | |||
364 | if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0) | 364 | if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0) |
365 | return; /* not from our current AP */ | 365 | return; /* not from our current AP */ |
366 | 366 | ||
367 | sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON; | 367 | sc->ps_flags &= ~PS_WAIT_FOR_BEACON; |
368 | 368 | ||
369 | if (sc->sc_flags & SC_OP_BEACON_SYNC) { | 369 | if (sc->ps_flags & PS_BEACON_SYNC) { |
370 | sc->sc_flags &= ~SC_OP_BEACON_SYNC; | 370 | sc->ps_flags &= ~PS_BEACON_SYNC; |
371 | ath_print(common, ATH_DBG_PS, | 371 | ath_print(common, ATH_DBG_PS, |
372 | "Reconfigure Beacon timers based on " | 372 | "Reconfigure Beacon timers based on " |
373 | "timestamp from the AP\n"); | 373 | "timestamp from the AP\n"); |
@@ -384,17 +384,17 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) | |||
384 | */ | 384 | */ |
385 | ath_print(common, ATH_DBG_PS, "Received DTIM beacon indicating " | 385 | ath_print(common, ATH_DBG_PS, "Received DTIM beacon indicating " |
386 | "buffered broadcast/multicast frame(s)\n"); | 386 | "buffered broadcast/multicast frame(s)\n"); |
387 | sc->sc_flags |= SC_OP_WAIT_FOR_CAB | SC_OP_WAIT_FOR_BEACON; | 387 | sc->ps_flags |= PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON; |
388 | return; | 388 | return; |
389 | } | 389 | } |
390 | 390 | ||
391 | if (sc->sc_flags & SC_OP_WAIT_FOR_CAB) { | 391 | if (sc->ps_flags & PS_WAIT_FOR_CAB) { |
392 | /* | 392 | /* |
393 | * This can happen if a broadcast frame is dropped or the AP | 393 | * This can happen if a broadcast frame is dropped or the AP |
394 | * fails to send a frame indicating that all CAB frames have | 394 | * fails to send a frame indicating that all CAB frames have |
395 | * been delivered. | 395 | * been delivered. |
396 | */ | 396 | */ |
397 | sc->sc_flags &= ~SC_OP_WAIT_FOR_CAB; | 397 | sc->ps_flags &= ~PS_WAIT_FOR_CAB; |
398 | ath_print(common, ATH_DBG_PS, | 398 | ath_print(common, ATH_DBG_PS, |
399 | "PS wait for CAB frames timed out\n"); | 399 | "PS wait for CAB frames timed out\n"); |
400 | } | 400 | } |
@@ -408,10 +408,10 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) | |||
408 | hdr = (struct ieee80211_hdr *)skb->data; | 408 | hdr = (struct ieee80211_hdr *)skb->data; |
409 | 409 | ||
410 | /* Process Beacon and CAB receive in PS state */ | 410 | /* Process Beacon and CAB receive in PS state */ |
411 | if ((sc->sc_flags & SC_OP_WAIT_FOR_BEACON) && | 411 | if ((sc->ps_flags & PS_WAIT_FOR_BEACON) && |
412 | ieee80211_is_beacon(hdr->frame_control)) | 412 | ieee80211_is_beacon(hdr->frame_control)) |
413 | ath_rx_ps_beacon(sc, skb); | 413 | ath_rx_ps_beacon(sc, skb); |
414 | else if ((sc->sc_flags & SC_OP_WAIT_FOR_CAB) && | 414 | else if ((sc->ps_flags & PS_WAIT_FOR_CAB) && |
415 | (ieee80211_is_data(hdr->frame_control) || | 415 | (ieee80211_is_data(hdr->frame_control) || |
416 | ieee80211_is_action(hdr->frame_control)) && | 416 | ieee80211_is_action(hdr->frame_control)) && |
417 | is_multicast_ether_addr(hdr->addr1) && | 417 | is_multicast_ether_addr(hdr->addr1) && |
@@ -420,20 +420,20 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) | |||
420 | * No more broadcast/multicast frames to be received at this | 420 | * No more broadcast/multicast frames to be received at this |
421 | * point. | 421 | * point. |
422 | */ | 422 | */ |
423 | sc->sc_flags &= ~SC_OP_WAIT_FOR_CAB; | 423 | sc->ps_flags &= ~PS_WAIT_FOR_CAB; |
424 | ath_print(common, ATH_DBG_PS, | 424 | ath_print(common, ATH_DBG_PS, |
425 | "All PS CAB frames received, back to sleep\n"); | 425 | "All PS CAB frames received, back to sleep\n"); |
426 | } else if ((sc->sc_flags & SC_OP_WAIT_FOR_PSPOLL_DATA) && | 426 | } else if ((sc->ps_flags & PS_WAIT_FOR_PSPOLL_DATA) && |
427 | !is_multicast_ether_addr(hdr->addr1) && | 427 | !is_multicast_ether_addr(hdr->addr1) && |
428 | !ieee80211_has_morefrags(hdr->frame_control)) { | 428 | !ieee80211_has_morefrags(hdr->frame_control)) { |
429 | sc->sc_flags &= ~SC_OP_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->sc_flags & (SC_OP_WAIT_FOR_BEACON | | 433 | sc->ps_flags & (PS_WAIT_FOR_BEACON | |
434 | SC_OP_WAIT_FOR_CAB | | 434 | PS_WAIT_FOR_CAB | |
435 | SC_OP_WAIT_FOR_PSPOLL_DATA | | 435 | PS_WAIT_FOR_PSPOLL_DATA | |
436 | SC_OP_WAIT_FOR_TX_ACK)); | 436 | PS_WAIT_FOR_TX_ACK)); |
437 | } | 437 | } |
438 | } | 438 | } |
439 | 439 | ||
@@ -571,6 +571,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
571 | hw = ath_get_virt_hw(sc, hdr); | 571 | hw = ath_get_virt_hw(sc, hdr); |
572 | rx_stats = &ds->ds_rxstat; | 572 | rx_stats = &ds->ds_rxstat; |
573 | 573 | ||
574 | ath_debug_stat_rx(sc, bf); | ||
575 | |||
574 | /* | 576 | /* |
575 | * If we're asked to flush receive queue, directly | 577 | * If we're asked to flush receive queue, directly |
576 | * chain it back at the queue without processing it. | 578 | * chain it back at the queue without processing it. |
@@ -631,9 +633,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
631 | sc->rx.rxotherant = 0; | 633 | sc->rx.rxotherant = 0; |
632 | } | 634 | } |
633 | 635 | ||
634 | if (unlikely(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | | 636 | if (unlikely(sc->ps_flags & (PS_WAIT_FOR_BEACON | |
635 | SC_OP_WAIT_FOR_CAB | | 637 | PS_WAIT_FOR_CAB | |
636 | SC_OP_WAIT_FOR_PSPOLL_DATA))) | 638 | PS_WAIT_FOR_PSPOLL_DATA))) |
637 | ath_rx_ps(sc, skb); | 639 | ath_rx_ps(sc, skb); |
638 | 640 | ||
639 | ath_rx_send_to_mac80211(hw, sc, skb, rxs); | 641 | ath_rx_send_to_mac80211(hw, sc, skb, rxs); |
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/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c index cd26caaf44e7..a43fbf84dab9 100644 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ b/drivers/net/wireless/ath/ath9k/virtual.c | |||
@@ -152,7 +152,7 @@ int ath9k_wiphy_add(struct ath_softc *sc) | |||
152 | 152 | ||
153 | SET_IEEE80211_PERM_ADDR(hw, addr); | 153 | SET_IEEE80211_PERM_ADDR(hw, addr); |
154 | 154 | ||
155 | ath_set_hw_capab(sc, hw); | 155 | ath9k_set_hw_capab(sc, hw); |
156 | 156 | ||
157 | error = ieee80211_register_hw(hw); | 157 | error = ieee80211_register_hw(hw); |
158 | 158 | ||
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 29bf33692f71..47294f90bbe5 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, |
@@ -1648,7 +1643,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, | |||
1648 | /* tag if this is a nullfunc frame to enable PS when AP acks it */ | 1643 | /* tag if this is a nullfunc frame to enable PS when AP acks it */ |
1649 | if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc)) { | 1644 | if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc)) { |
1650 | bf->bf_isnullfunc = true; | 1645 | bf->bf_isnullfunc = true; |
1651 | sc->sc_flags &= ~SC_OP_NULLFUNC_COMPLETED; | 1646 | sc->ps_flags &= ~PS_NULLFUNC_COMPLETED; |
1652 | } else | 1647 | } else |
1653 | bf->bf_isnullfunc = false; | 1648 | bf->bf_isnullfunc = false; |
1654 | 1649 | ||
@@ -1858,15 +1853,15 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1858 | skb_pull(skb, padsize); | 1853 | skb_pull(skb, padsize); |
1859 | } | 1854 | } |
1860 | 1855 | ||
1861 | if (sc->sc_flags & SC_OP_WAIT_FOR_TX_ACK) { | 1856 | if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) { |
1862 | sc->sc_flags &= ~SC_OP_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->sc_flags & (SC_OP_WAIT_FOR_BEACON | | 1861 | sc->ps_flags & (PS_WAIT_FOR_BEACON | |
1867 | SC_OP_WAIT_FOR_CAB | | 1862 | PS_WAIT_FOR_CAB | |
1868 | SC_OP_WAIT_FOR_PSPOLL_DATA | | 1863 | PS_WAIT_FOR_PSPOLL_DATA | |
1869 | SC_OP_WAIT_FOR_TX_ACK)); | 1864 | PS_WAIT_FOR_TX_ACK)); |
1870 | } | 1865 | } |
1871 | 1866 | ||
1872 | if (unlikely(tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_INTERNAL)) | 1867 | if (unlikely(tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_INTERNAL)) |
@@ -2053,11 +2048,10 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2053 | */ | 2048 | */ |
2054 | if (bf->bf_isnullfunc && | 2049 | if (bf->bf_isnullfunc && |
2055 | (ds->ds_txstat.ts_status & ATH9K_TX_ACKED)) { | 2050 | (ds->ds_txstat.ts_status & ATH9K_TX_ACKED)) { |
2056 | if ((sc->sc_flags & SC_OP_PS_ENABLED)) { | 2051 | if ((sc->ps_flags & PS_ENABLED)) |
2057 | sc->ps_enabled = true; | 2052 | ath9k_enable_ps(sc); |
2058 | ath9k_hw_setrxabort(sc->sc_ah, 1); | 2053 | else |
2059 | } else | 2054 | sc->ps_flags |= PS_NULLFUNC_COMPLETED; |
2060 | sc->sc_flags |= SC_OP_NULLFUNC_COMPLETED; | ||
2061 | } | 2055 | } |
2062 | 2056 | ||
2063 | /* | 2057 | /* |
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/ath/regd.c b/drivers/net/wireless/ath/regd.c index 039ac490465c..04abd1f556b7 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c | |||
@@ -110,8 +110,9 @@ static const struct ieee80211_regdomain ath_world_regdom_67_68_6A = { | |||
110 | 110 | ||
111 | static inline bool is_wwr_sku(u16 regd) | 111 | static inline bool is_wwr_sku(u16 regd) |
112 | { | 112 | { |
113 | return ((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) || | 113 | return ((regd & COUNTRY_ERD_FLAG) != COUNTRY_ERD_FLAG) && |
114 | (regd == WORLD); | 114 | (((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) || |
115 | (regd == WORLD)); | ||
115 | } | 116 | } |
116 | 117 | ||
117 | static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg) | 118 | static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg) |
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 64c12e1bced3..073be566d05e 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig | |||
@@ -3,6 +3,7 @@ config B43 | |||
3 | depends on SSB_POSSIBLE && MAC80211 && HAS_DMA | 3 | depends on SSB_POSSIBLE && MAC80211 && HAS_DMA |
4 | select SSB | 4 | select SSB |
5 | select FW_LOADER | 5 | select FW_LOADER |
6 | select SSB_BLOCKIO | ||
6 | ---help--- | 7 | ---help--- |
7 | b43 is a driver for the Broadcom 43xx series wireless devices. | 8 | b43 is a driver for the Broadcom 43xx series wireless devices. |
8 | 9 | ||
@@ -78,14 +79,6 @@ config B43_SDIO | |||
78 | 79 | ||
79 | If unsure, say N. | 80 | If unsure, say N. |
80 | 81 | ||
81 | # Data transfers to the device via PIO | ||
82 | # This is only needed on PCMCIA and SDIO devices. All others can do DMA properly. | ||
83 | config B43_PIO | ||
84 | bool | ||
85 | depends on B43 && (B43_SDIO || B43_PCMCIA || B43_FORCE_PIO) | ||
86 | select SSB_BLOCKIO | ||
87 | default y | ||
88 | |||
89 | config B43_NPHY | 82 | config B43_NPHY |
90 | bool "Pre IEEE 802.11n support (BROKEN)" | 83 | bool "Pre IEEE 802.11n support (BROKEN)" |
91 | depends on B43 && EXPERIMENTAL && BROKEN | 84 | depends on B43 && EXPERIMENTAL && BROKEN |
@@ -137,12 +130,4 @@ config B43_DEBUG | |||
137 | for production use. | 130 | for production use. |
138 | Only say Y, if you are debugging a problem in the b43 driver sourcecode. | 131 | Only say Y, if you are debugging a problem in the b43 driver sourcecode. |
139 | 132 | ||
140 | config B43_FORCE_PIO | ||
141 | bool "Force usage of PIO instead of DMA" | ||
142 | depends on B43 && B43_DEBUG | ||
143 | ---help--- | ||
144 | This will disable DMA and always enable PIO instead. | ||
145 | 133 | ||
146 | Say N! | ||
147 | This is only for debugging the PIO engine code. You do | ||
148 | _NOT_ want to enable this. | ||
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index 84772a2542dc..5e83b6f0a3a0 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile | |||
@@ -12,7 +12,7 @@ b43-y += xmit.o | |||
12 | b43-y += lo.o | 12 | b43-y += lo.o |
13 | b43-y += wa.o | 13 | b43-y += wa.o |
14 | b43-y += dma.o | 14 | b43-y += dma.o |
15 | b43-$(CONFIG_B43_PIO) += pio.o | 15 | b43-y += pio.o |
16 | b43-y += rfkill.o | 16 | b43-y += rfkill.o |
17 | b43-$(CONFIG_B43_LEDS) += leds.o | 17 | b43-$(CONFIG_B43_LEDS) += leds.o |
18 | b43-$(CONFIG_B43_PCMCIA) += pcmcia.o | 18 | b43-$(CONFIG_B43_PCMCIA) += pcmcia.o |
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index c484cc253892..6a6ab0f630e5 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -254,6 +254,14 @@ enum { | |||
254 | #define B43_SHM_SH_MAXBFRAMES 0x0080 /* Maximum number of frames in a burst */ | 254 | #define B43_SHM_SH_MAXBFRAMES 0x0080 /* Maximum number of frames in a burst */ |
255 | #define B43_SHM_SH_SPUWKUP 0x0094 /* pre-wakeup for synth PU in us */ | 255 | #define B43_SHM_SH_SPUWKUP 0x0094 /* pre-wakeup for synth PU in us */ |
256 | #define B43_SHM_SH_PRETBTT 0x0096 /* pre-TBTT in us */ | 256 | #define B43_SHM_SH_PRETBTT 0x0096 /* pre-TBTT in us */ |
257 | /* SHM_SHARED tx iq workarounds */ | ||
258 | #define B43_SHM_SH_NPHY_TXIQW0 0x0700 | ||
259 | #define B43_SHM_SH_NPHY_TXIQW1 0x0702 | ||
260 | #define B43_SHM_SH_NPHY_TXIQW2 0x0704 | ||
261 | #define B43_SHM_SH_NPHY_TXIQW3 0x0706 | ||
262 | /* SHM_SHARED tx pwr ctrl */ | ||
263 | #define B43_SHM_SH_NPHY_TXPWR_INDX0 0x0708 | ||
264 | #define B43_SHM_SH_NPHY_TXPWR_INDX1 0x070E | ||
257 | 265 | ||
258 | /* SHM_SCRATCH offsets */ | 266 | /* SHM_SCRATCH offsets */ |
259 | #define B43_SHM_SC_MINCONT 0x0003 /* Minimum contention window */ | 267 | #define B43_SHM_SC_MINCONT 0x0003 /* Minimum contention window */ |
@@ -822,11 +830,9 @@ struct b43_wl { | |||
822 | /* The device LEDs. */ | 830 | /* The device LEDs. */ |
823 | struct b43_leds leds; | 831 | struct b43_leds leds; |
824 | 832 | ||
825 | #ifdef CONFIG_B43_PIO | ||
826 | /* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */ | 833 | /* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */ |
827 | u8 pio_scratchspace[110] __attribute__((__aligned__(8))); | 834 | u8 pio_scratchspace[110] __attribute__((__aligned__(8))); |
828 | u8 pio_tailspace[4] __attribute__((__aligned__(8))); | 835 | u8 pio_tailspace[4] __attribute__((__aligned__(8))); |
829 | #endif /* CONFIG_B43_PIO */ | ||
830 | }; | 836 | }; |
831 | 837 | ||
832 | static inline struct b43_wl *hw_to_b43_wl(struct ieee80211_hw *hw) | 838 | static inline struct b43_wl *hw_to_b43_wl(struct ieee80211_hw *hw) |
@@ -877,20 +883,9 @@ static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value) | |||
877 | 883 | ||
878 | static inline bool b43_using_pio_transfers(struct b43_wldev *dev) | 884 | static inline bool b43_using_pio_transfers(struct b43_wldev *dev) |
879 | { | 885 | { |
880 | #ifdef CONFIG_B43_PIO | ||
881 | return dev->__using_pio_transfers; | 886 | return dev->__using_pio_transfers; |
882 | #else | ||
883 | return 0; | ||
884 | #endif | ||
885 | } | 887 | } |
886 | 888 | ||
887 | #ifdef CONFIG_B43_FORCE_PIO | ||
888 | # define B43_FORCE_PIO 1 | ||
889 | #else | ||
890 | # define B43_FORCE_PIO 0 | ||
891 | #endif | ||
892 | |||
893 | |||
894 | /* Message printing */ | 889 | /* Message printing */ |
895 | void b43info(struct b43_wl *wl, const char *fmt, ...) | 890 | void b43info(struct b43_wl *wl, const char *fmt, ...) |
896 | __attribute__ ((format(printf, 2, 3))); | 891 | __attribute__ ((format(printf, 2, 3))); |
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 88d1fd02d40a..be7abf8916ad 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c | |||
@@ -1369,7 +1369,6 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb) | |||
1369 | b43err(dev->wl, "DMA tx mapping failure\n"); | 1369 | b43err(dev->wl, "DMA tx mapping failure\n"); |
1370 | goto out; | 1370 | goto out; |
1371 | } | 1371 | } |
1372 | ring->nr_tx_packets++; | ||
1373 | if ((free_slots(ring) < TX_SLOTS_PER_FRAME) || | 1372 | if ((free_slots(ring) < TX_SLOTS_PER_FRAME) || |
1374 | should_inject_overflow(ring)) { | 1373 | should_inject_overflow(ring)) { |
1375 | /* This TX ring is full. */ | 1374 | /* This TX ring is full. */ |
@@ -1500,22 +1499,6 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | |||
1500 | } | 1499 | } |
1501 | } | 1500 | } |
1502 | 1501 | ||
1503 | void b43_dma_get_tx_stats(struct b43_wldev *dev, | ||
1504 | struct ieee80211_tx_queue_stats *stats) | ||
1505 | { | ||
1506 | const int nr_queues = dev->wl->hw->queues; | ||
1507 | struct b43_dmaring *ring; | ||
1508 | int i; | ||
1509 | |||
1510 | for (i = 0; i < nr_queues; i++) { | ||
1511 | ring = select_ring_by_priority(dev, i); | ||
1512 | |||
1513 | stats[i].len = ring->used_slots / TX_SLOTS_PER_FRAME; | ||
1514 | stats[i].limit = ring->nr_slots / TX_SLOTS_PER_FRAME; | ||
1515 | stats[i].count = ring->nr_tx_packets; | ||
1516 | } | ||
1517 | } | ||
1518 | |||
1519 | static void dma_rx(struct b43_dmaring *ring, int *slot) | 1502 | static void dma_rx(struct b43_dmaring *ring, int *slot) |
1520 | { | 1503 | { |
1521 | const struct b43_dma_ops *ops = ring->ops; | 1504 | const struct b43_dma_ops *ops = ring->ops; |
@@ -1653,7 +1636,6 @@ void b43_dma_tx_resume(struct b43_wldev *dev) | |||
1653 | b43_power_saving_ctl_bits(dev, 0); | 1636 | b43_power_saving_ctl_bits(dev, 0); |
1654 | } | 1637 | } |
1655 | 1638 | ||
1656 | #ifdef CONFIG_B43_PIO | ||
1657 | static void direct_fifo_rx(struct b43_wldev *dev, enum b43_dmatype type, | 1639 | static void direct_fifo_rx(struct b43_wldev *dev, enum b43_dmatype type, |
1658 | u16 mmio_base, bool enable) | 1640 | u16 mmio_base, bool enable) |
1659 | { | 1641 | { |
@@ -1687,4 +1669,3 @@ void b43_dma_direct_fifo_rx(struct b43_wldev *dev, | |||
1687 | mmio_base = b43_dmacontroller_base(type, engine_index); | 1669 | mmio_base = b43_dmacontroller_base(type, engine_index); |
1688 | direct_fifo_rx(dev, type, mmio_base, enable); | 1670 | direct_fifo_rx(dev, type, mmio_base, enable); |
1689 | } | 1671 | } |
1690 | #endif /* CONFIG_B43_PIO */ | ||
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index f7ab37c4cdbc..dc91944d6022 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h | |||
@@ -228,8 +228,6 @@ struct b43_dmaring { | |||
228 | int used_slots; | 228 | int used_slots; |
229 | /* Currently used slot in the ring. */ | 229 | /* Currently used slot in the ring. */ |
230 | int current_slot; | 230 | int current_slot; |
231 | /* Total number of packets sent. Statistics only. */ | ||
232 | unsigned int nr_tx_packets; | ||
233 | /* Frameoffset in octets. */ | 231 | /* Frameoffset in octets. */ |
234 | u32 frameoffset; | 232 | u32 frameoffset; |
235 | /* Descriptor buffer size. */ | 233 | /* Descriptor buffer size. */ |
@@ -278,9 +276,6 @@ void b43_dma_free(struct b43_wldev *dev); | |||
278 | void b43_dma_tx_suspend(struct b43_wldev *dev); | 276 | void b43_dma_tx_suspend(struct b43_wldev *dev); |
279 | void b43_dma_tx_resume(struct b43_wldev *dev); | 277 | void b43_dma_tx_resume(struct b43_wldev *dev); |
280 | 278 | ||
281 | void b43_dma_get_tx_stats(struct b43_wldev *dev, | ||
282 | struct ieee80211_tx_queue_stats *stats); | ||
283 | |||
284 | int b43_dma_tx(struct b43_wldev *dev, | 279 | int b43_dma_tx(struct b43_wldev *dev, |
285 | struct sk_buff *skb); | 280 | struct sk_buff *skb); |
286 | void b43_dma_handle_txstatus(struct b43_wldev *dev, | 281 | void b43_dma_handle_txstatus(struct b43_wldev *dev, |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index fcbf0e27d9f3..8f7a8c0ec27d 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -67,7 +67,12 @@ MODULE_AUTHOR("Gábor Stefanik"); | |||
67 | MODULE_LICENSE("GPL"); | 67 | MODULE_LICENSE("GPL"); |
68 | 68 | ||
69 | MODULE_FIRMWARE(B43_SUPPORTED_FIRMWARE_ID); | 69 | MODULE_FIRMWARE(B43_SUPPORTED_FIRMWARE_ID); |
70 | 70 | MODULE_FIRMWARE("b43/ucode11.fw"); | |
71 | MODULE_FIRMWARE("b43/ucode13.fw"); | ||
72 | MODULE_FIRMWARE("b43/ucode14.fw"); | ||
73 | MODULE_FIRMWARE("b43/ucode15.fw"); | ||
74 | MODULE_FIRMWARE("b43/ucode5.fw"); | ||
75 | MODULE_FIRMWARE("b43/ucode9.fw"); | ||
71 | 76 | ||
72 | static int modparam_bad_frames_preempt; | 77 | static int modparam_bad_frames_preempt; |
73 | module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444); | 78 | module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444); |
@@ -102,6 +107,9 @@ int b43_modparam_verbose = B43_VERBOSITY_DEFAULT; | |||
102 | module_param_named(verbose, b43_modparam_verbose, int, 0644); | 107 | module_param_named(verbose, b43_modparam_verbose, int, 0644); |
103 | MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug"); | 108 | MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug"); |
104 | 109 | ||
110 | static int modparam_pio; | ||
111 | module_param_named(pio, modparam_pio, int, 0444); | ||
112 | MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode"); | ||
105 | 113 | ||
106 | static const struct ssb_device_id b43_ssb_tbl[] = { | 114 | static const struct ssb_device_id b43_ssb_tbl[] = { |
107 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5), | 115 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5), |
@@ -110,6 +118,7 @@ static const struct ssb_device_id b43_ssb_tbl[] = { | |||
110 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 9), | 118 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 9), |
111 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 10), | 119 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 10), |
112 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 11), | 120 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 11), |
121 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 12), | ||
113 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 13), | 122 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 13), |
114 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 15), | 123 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 15), |
115 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 16), | 124 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 16), |
@@ -842,8 +851,10 @@ static void rx_tkip_phase1_write(struct b43_wldev *dev, u8 index, u32 iv32, | |||
842 | } | 851 | } |
843 | 852 | ||
844 | static void b43_op_update_tkip_key(struct ieee80211_hw *hw, | 853 | static void b43_op_update_tkip_key(struct ieee80211_hw *hw, |
845 | struct ieee80211_key_conf *keyconf, const u8 *addr, | 854 | struct ieee80211_vif *vif, |
846 | u32 iv32, u16 *phase1key) | 855 | struct ieee80211_key_conf *keyconf, |
856 | struct ieee80211_sta *sta, | ||
857 | u32 iv32, u16 *phase1key) | ||
847 | { | 858 | { |
848 | struct b43_wl *wl = hw_to_b43_wl(hw); | 859 | struct b43_wl *wl = hw_to_b43_wl(hw); |
849 | struct b43_wldev *dev; | 860 | struct b43_wldev *dev; |
@@ -852,19 +863,19 @@ static void b43_op_update_tkip_key(struct ieee80211_hw *hw, | |||
852 | if (B43_WARN_ON(!modparam_hwtkip)) | 863 | if (B43_WARN_ON(!modparam_hwtkip)) |
853 | return; | 864 | return; |
854 | 865 | ||
855 | mutex_lock(&wl->mutex); | 866 | /* This is only called from the RX path through mac80211, where |
856 | 867 | * our mutex is already locked. */ | |
868 | B43_WARN_ON(!mutex_is_locked(&wl->mutex)); | ||
857 | dev = wl->current_dev; | 869 | dev = wl->current_dev; |
858 | if (!dev || b43_status(dev) < B43_STAT_INITIALIZED) | 870 | B43_WARN_ON(!dev || b43_status(dev) < B43_STAT_INITIALIZED); |
859 | goto out_unlock; | ||
860 | 871 | ||
861 | keymac_write(dev, index, NULL); /* First zero out mac to avoid race */ | 872 | keymac_write(dev, index, NULL); /* First zero out mac to avoid race */ |
862 | 873 | ||
863 | rx_tkip_phase1_write(dev, index, iv32, phase1key); | 874 | rx_tkip_phase1_write(dev, index, iv32, phase1key); |
864 | keymac_write(dev, index, addr); | 875 | /* only pairwise TKIP keys are supported right now */ |
865 | 876 | if (WARN_ON(!sta)) | |
866 | out_unlock: | 877 | return; |
867 | mutex_unlock(&wl->mutex); | 878 | keymac_write(dev, index, sta->addr); |
868 | } | 879 | } |
869 | 880 | ||
870 | static void do_key_write(struct b43_wldev *dev, | 881 | static void do_key_write(struct b43_wldev *dev, |
@@ -1793,8 +1804,8 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev) | |||
1793 | dma_reason[4], dma_reason[5]); | 1804 | dma_reason[4], dma_reason[5]); |
1794 | b43err(dev->wl, "This device does not support DMA " | 1805 | b43err(dev->wl, "This device does not support DMA " |
1795 | "on your system. Please use PIO instead.\n"); | 1806 | "on your system. Please use PIO instead.\n"); |
1796 | b43err(dev->wl, "CONFIG_B43_FORCE_PIO must be set in " | 1807 | b43err(dev->wl, "Unload the b43 module and reload " |
1797 | "your kernel configuration.\n"); | 1808 | "with 'pio=1'\n"); |
1798 | return; | 1809 | return; |
1799 | } | 1810 | } |
1800 | if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) { | 1811 | if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) { |
@@ -3345,27 +3356,6 @@ out_unlock: | |||
3345 | return err; | 3356 | return err; |
3346 | } | 3357 | } |
3347 | 3358 | ||
3348 | static int b43_op_get_tx_stats(struct ieee80211_hw *hw, | ||
3349 | struct ieee80211_tx_queue_stats *stats) | ||
3350 | { | ||
3351 | struct b43_wl *wl = hw_to_b43_wl(hw); | ||
3352 | struct b43_wldev *dev; | ||
3353 | int err = -ENODEV; | ||
3354 | |||
3355 | mutex_lock(&wl->mutex); | ||
3356 | dev = wl->current_dev; | ||
3357 | if (dev && b43_status(dev) >= B43_STAT_STARTED) { | ||
3358 | if (b43_using_pio_transfers(dev)) | ||
3359 | b43_pio_get_tx_stats(dev, stats); | ||
3360 | else | ||
3361 | b43_dma_get_tx_stats(dev, stats); | ||
3362 | err = 0; | ||
3363 | } | ||
3364 | mutex_unlock(&wl->mutex); | ||
3365 | |||
3366 | return err; | ||
3367 | } | ||
3368 | |||
3369 | static int b43_op_get_stats(struct ieee80211_hw *hw, | 3359 | static int b43_op_get_stats(struct ieee80211_hw *hw, |
3370 | struct ieee80211_low_level_stats *stats) | 3360 | struct ieee80211_low_level_stats *stats) |
3371 | { | 3361 | { |
@@ -3569,6 +3559,12 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed) | |||
3569 | dev = wl->current_dev; | 3559 | dev = wl->current_dev; |
3570 | phy = &dev->phy; | 3560 | phy = &dev->phy; |
3571 | 3561 | ||
3562 | if (conf_is_ht(conf)) | ||
3563 | phy->is_40mhz = | ||
3564 | (conf_is_ht40_minus(conf) || conf_is_ht40_plus(conf)); | ||
3565 | else | ||
3566 | phy->is_40mhz = false; | ||
3567 | |||
3572 | b43_mac_suspend(dev); | 3568 | b43_mac_suspend(dev); |
3573 | 3569 | ||
3574 | if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) | 3570 | if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) |
@@ -3970,6 +3966,7 @@ static int b43_wireless_core_start(struct b43_wldev *dev) | |||
3970 | } | 3966 | } |
3971 | 3967 | ||
3972 | /* We are ready to run. */ | 3968 | /* We are ready to run. */ |
3969 | ieee80211_wake_queues(dev->wl->hw); | ||
3973 | b43_set_status(dev, B43_STAT_STARTED); | 3970 | b43_set_status(dev, B43_STAT_STARTED); |
3974 | 3971 | ||
3975 | /* Start data flow (TX/RX). */ | 3972 | /* Start data flow (TX/RX). */ |
@@ -4360,7 +4357,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | |||
4360 | 4357 | ||
4361 | if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || | 4358 | if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || |
4362 | (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) || | 4359 | (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) || |
4363 | B43_FORCE_PIO) { | 4360 | modparam_pio) { |
4364 | dev->__using_pio_transfers = 1; | 4361 | dev->__using_pio_transfers = 1; |
4365 | err = b43_pio_init(dev); | 4362 | err = b43_pio_init(dev); |
4366 | } else { | 4363 | } else { |
@@ -4379,8 +4376,6 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | |||
4379 | 4376 | ||
4380 | ieee80211_wake_queues(dev->wl->hw); | 4377 | ieee80211_wake_queues(dev->wl->hw); |
4381 | 4378 | ||
4382 | ieee80211_wake_queues(dev->wl->hw); | ||
4383 | |||
4384 | b43_set_status(dev, B43_STAT_INITIALIZED); | 4379 | b43_set_status(dev, B43_STAT_INITIALIZED); |
4385 | 4380 | ||
4386 | out: | 4381 | out: |
@@ -4395,7 +4390,7 @@ err_busdown: | |||
4395 | } | 4390 | } |
4396 | 4391 | ||
4397 | static int b43_op_add_interface(struct ieee80211_hw *hw, | 4392 | static int b43_op_add_interface(struct ieee80211_hw *hw, |
4398 | struct ieee80211_if_init_conf *conf) | 4393 | struct ieee80211_vif *vif) |
4399 | { | 4394 | { |
4400 | struct b43_wl *wl = hw_to_b43_wl(hw); | 4395 | struct b43_wl *wl = hw_to_b43_wl(hw); |
4401 | struct b43_wldev *dev; | 4396 | struct b43_wldev *dev; |
@@ -4403,24 +4398,24 @@ static int b43_op_add_interface(struct ieee80211_hw *hw, | |||
4403 | 4398 | ||
4404 | /* TODO: allow WDS/AP devices to coexist */ | 4399 | /* TODO: allow WDS/AP devices to coexist */ |
4405 | 4400 | ||
4406 | if (conf->type != NL80211_IFTYPE_AP && | 4401 | if (vif->type != NL80211_IFTYPE_AP && |
4407 | conf->type != NL80211_IFTYPE_MESH_POINT && | 4402 | vif->type != NL80211_IFTYPE_MESH_POINT && |
4408 | conf->type != NL80211_IFTYPE_STATION && | 4403 | vif->type != NL80211_IFTYPE_STATION && |
4409 | conf->type != NL80211_IFTYPE_WDS && | 4404 | vif->type != NL80211_IFTYPE_WDS && |
4410 | conf->type != NL80211_IFTYPE_ADHOC) | 4405 | vif->type != NL80211_IFTYPE_ADHOC) |
4411 | return -EOPNOTSUPP; | 4406 | return -EOPNOTSUPP; |
4412 | 4407 | ||
4413 | mutex_lock(&wl->mutex); | 4408 | mutex_lock(&wl->mutex); |
4414 | if (wl->operating) | 4409 | if (wl->operating) |
4415 | goto out_mutex_unlock; | 4410 | goto out_mutex_unlock; |
4416 | 4411 | ||
4417 | b43dbg(wl, "Adding Interface type %d\n", conf->type); | 4412 | b43dbg(wl, "Adding Interface type %d\n", vif->type); |
4418 | 4413 | ||
4419 | dev = wl->current_dev; | 4414 | dev = wl->current_dev; |
4420 | wl->operating = 1; | 4415 | wl->operating = 1; |
4421 | wl->vif = conf->vif; | 4416 | wl->vif = vif; |
4422 | wl->if_type = conf->type; | 4417 | wl->if_type = vif->type; |
4423 | memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); | 4418 | memcpy(wl->mac_addr, vif->addr, ETH_ALEN); |
4424 | 4419 | ||
4425 | b43_adjust_opmode(dev); | 4420 | b43_adjust_opmode(dev); |
4426 | b43_set_pretbtt(dev); | 4421 | b43_set_pretbtt(dev); |
@@ -4435,17 +4430,17 @@ static int b43_op_add_interface(struct ieee80211_hw *hw, | |||
4435 | } | 4430 | } |
4436 | 4431 | ||
4437 | static void b43_op_remove_interface(struct ieee80211_hw *hw, | 4432 | static void b43_op_remove_interface(struct ieee80211_hw *hw, |
4438 | struct ieee80211_if_init_conf *conf) | 4433 | struct ieee80211_vif *vif) |
4439 | { | 4434 | { |
4440 | struct b43_wl *wl = hw_to_b43_wl(hw); | 4435 | struct b43_wl *wl = hw_to_b43_wl(hw); |
4441 | struct b43_wldev *dev = wl->current_dev; | 4436 | struct b43_wldev *dev = wl->current_dev; |
4442 | 4437 | ||
4443 | b43dbg(wl, "Removing Interface type %d\n", conf->type); | 4438 | b43dbg(wl, "Removing Interface type %d\n", vif->type); |
4444 | 4439 | ||
4445 | mutex_lock(&wl->mutex); | 4440 | mutex_lock(&wl->mutex); |
4446 | 4441 | ||
4447 | B43_WARN_ON(!wl->operating); | 4442 | B43_WARN_ON(!wl->operating); |
4448 | B43_WARN_ON(wl->vif != conf->vif); | 4443 | B43_WARN_ON(wl->vif != vif); |
4449 | wl->vif = NULL; | 4444 | wl->vif = NULL; |
4450 | 4445 | ||
4451 | wl->operating = 0; | 4446 | wl->operating = 0; |
@@ -4586,7 +4581,6 @@ static const struct ieee80211_ops b43_hw_ops = { | |||
4586 | .set_key = b43_op_set_key, | 4581 | .set_key = b43_op_set_key, |
4587 | .update_tkip_key = b43_op_update_tkip_key, | 4582 | .update_tkip_key = b43_op_update_tkip_key, |
4588 | .get_stats = b43_op_get_stats, | 4583 | .get_stats = b43_op_get_stats, |
4589 | .get_tx_stats = b43_op_get_tx_stats, | ||
4590 | .get_tsf = b43_op_get_tsf, | 4584 | .get_tsf = b43_op_get_tsf, |
4591 | .set_tsf = b43_op_set_tsf, | 4585 | .set_tsf = b43_op_set_tsf, |
4592 | .start = b43_op_start, | 4586 | .start = b43_op_start, |
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 3e046ec1ff86..185219e0a552 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c | |||
@@ -80,6 +80,7 @@ static void b43_lpphy_op_free(struct b43_wldev *dev) | |||
80 | dev->phy.lp = NULL; | 80 | dev->phy.lp = NULL; |
81 | } | 81 | } |
82 | 82 | ||
83 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/LP/ReadBandSrom */ | ||
83 | static void lpphy_read_band_sprom(struct b43_wldev *dev) | 84 | static void lpphy_read_band_sprom(struct b43_wldev *dev) |
84 | { | 85 | { |
85 | struct b43_phy_lp *lpphy = dev->phy.lp; | 86 | struct b43_phy_lp *lpphy = dev->phy.lp; |
@@ -101,6 +102,12 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev) | |||
101 | maxpwr = bus->sprom.maxpwr_bg; | 102 | maxpwr = bus->sprom.maxpwr_bg; |
102 | lpphy->max_tx_pwr_med_band = maxpwr; | 103 | lpphy->max_tx_pwr_med_band = maxpwr; |
103 | cckpo = bus->sprom.cck2gpo; | 104 | cckpo = bus->sprom.cck2gpo; |
105 | /* | ||
106 | * We don't read SPROM's opo as specs say. On rev8 SPROMs | ||
107 | * opo == ofdm2gpo and we don't know any SSB with LP-PHY | ||
108 | * and SPROM rev below 8. | ||
109 | */ | ||
110 | B43_WARN_ON(bus->sprom.revision < 8); | ||
104 | ofdmpo = bus->sprom.ofdm2gpo; | 111 | ofdmpo = bus->sprom.ofdm2gpo; |
105 | if (cckpo) { | 112 | if (cckpo) { |
106 | for (i = 0; i < 4; i++) { | 113 | for (i = 0; i < 4; i++) { |
@@ -1703,19 +1710,6 @@ static const struct lpphy_rx_iq_comp lpphy_rev2plus_iq_comp = { | |||
1703 | .c0 = 0, | 1710 | .c0 = 0, |
1704 | }; | 1711 | }; |
1705 | 1712 | ||
1706 | static u8 lpphy_nbits(s32 val) | ||
1707 | { | ||
1708 | u32 tmp = abs(val); | ||
1709 | u8 nbits = 0; | ||
1710 | |||
1711 | while (tmp != 0) { | ||
1712 | nbits++; | ||
1713 | tmp >>= 1; | ||
1714 | } | ||
1715 | |||
1716 | return nbits; | ||
1717 | } | ||
1718 | |||
1719 | static int lpphy_calc_rx_iq_comp(struct b43_wldev *dev, u16 samples) | 1713 | static int lpphy_calc_rx_iq_comp(struct b43_wldev *dev, u16 samples) |
1720 | { | 1714 | { |
1721 | struct lpphy_iq_est iq_est; | 1715 | struct lpphy_iq_est iq_est; |
@@ -1742,8 +1736,8 @@ static int lpphy_calc_rx_iq_comp(struct b43_wldev *dev, u16 samples) | |||
1742 | goto out; | 1736 | goto out; |
1743 | } | 1737 | } |
1744 | 1738 | ||
1745 | prod_msb = lpphy_nbits(prod); | 1739 | prod_msb = fls(abs(prod)); |
1746 | q_msb = lpphy_nbits(qpwr); | 1740 | q_msb = fls(abs(qpwr)); |
1747 | tmp1 = prod_msb - 20; | 1741 | tmp1 = prod_msb - 20; |
1748 | 1742 | ||
1749 | if (tmp1 >= 0) { | 1743 | if (tmp1 >= 0) { |
@@ -1773,47 +1767,6 @@ out: | |||
1773 | return ret; | 1767 | return ret; |
1774 | } | 1768 | } |
1775 | 1769 | ||
1776 | /* Complex number using 2 32-bit signed integers */ | ||
1777 | typedef struct {s32 i, q;} lpphy_c32; | ||
1778 | |||
1779 | static lpphy_c32 lpphy_cordic(int theta) | ||
1780 | { | ||
1781 | u32 arctg[] = { 2949120, 1740967, 919879, 466945, 234379, 117304, | ||
1782 | 58666, 29335, 14668, 7334, 3667, 1833, 917, 458, | ||
1783 | 229, 115, 57, 29, }; | ||
1784 | int i, tmp, signx = 1, angle = 0; | ||
1785 | lpphy_c32 ret = { .i = 39797, .q = 0, }; | ||
1786 | |||
1787 | theta = clamp_t(int, theta, -180, 180); | ||
1788 | |||
1789 | if (theta > 90) { | ||
1790 | theta -= 180; | ||
1791 | signx = -1; | ||
1792 | } else if (theta < -90) { | ||
1793 | theta += 180; | ||
1794 | signx = -1; | ||
1795 | } | ||
1796 | |||
1797 | for (i = 0; i <= 17; i++) { | ||
1798 | if (theta > angle) { | ||
1799 | tmp = ret.i - (ret.q >> i); | ||
1800 | ret.q += ret.i >> i; | ||
1801 | ret.i = tmp; | ||
1802 | angle += arctg[i]; | ||
1803 | } else { | ||
1804 | tmp = ret.i + (ret.q >> i); | ||
1805 | ret.q -= ret.i >> i; | ||
1806 | ret.i = tmp; | ||
1807 | angle -= arctg[i]; | ||
1808 | } | ||
1809 | } | ||
1810 | |||
1811 | ret.i *= signx; | ||
1812 | ret.q *= signx; | ||
1813 | |||
1814 | return ret; | ||
1815 | } | ||
1816 | |||
1817 | 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, |
1818 | u16 wait) | 1771 | u16 wait) |
1819 | { | 1772 | { |
@@ -1831,8 +1784,9 @@ static void lpphy_start_tx_tone(struct b43_wldev *dev, s32 freq, u16 max) | |||
1831 | { | 1784 | { |
1832 | struct b43_phy_lp *lpphy = dev->phy.lp; | 1785 | struct b43_phy_lp *lpphy = dev->phy.lp; |
1833 | u16 buf[64]; | 1786 | u16 buf[64]; |
1834 | int i, samples = 0, angle = 0, rotation = (9 * freq) / 500; | 1787 | int i, samples = 0, angle = 0; |
1835 | lpphy_c32 sample; | 1788 | int rotation = (((36 * freq) / 20) << 16) / 100; |
1789 | struct b43_c32 sample; | ||
1836 | 1790 | ||
1837 | lpphy->tx_tone_freq = freq; | 1791 | lpphy->tx_tone_freq = freq; |
1838 | 1792 | ||
@@ -1848,10 +1802,10 @@ static void lpphy_start_tx_tone(struct b43_wldev *dev, s32 freq, u16 max) | |||
1848 | } | 1802 | } |
1849 | 1803 | ||
1850 | for (i = 0; i < samples; i++) { | 1804 | for (i = 0; i < samples; i++) { |
1851 | sample = lpphy_cordic(angle); | 1805 | sample = b43_cordic(angle); |
1852 | angle += rotation; | 1806 | angle += rotation; |
1853 | buf[i] = ((sample.i * max) & 0xFF) << 8; | 1807 | buf[i] = CORDIC_CONVERT((sample.i * max) & 0xFF) << 8; |
1854 | buf[i] |= (sample.q * max) & 0xFF; | 1808 | buf[i] |= CORDIC_CONVERT((sample.q * max) & 0xFF); |
1855 | } | 1809 | } |
1856 | 1810 | ||
1857 | 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 992318a78077..795bb1e3345d 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c | |||
@@ -28,7 +28,50 @@ | |||
28 | #include "b43.h" | 28 | #include "b43.h" |
29 | #include "phy_n.h" | 29 | #include "phy_n.h" |
30 | #include "tables_nphy.h" | 30 | #include "tables_nphy.h" |
31 | #include "main.h" | ||
31 | 32 | ||
33 | struct nphy_txgains { | ||
34 | u16 txgm[2]; | ||
35 | u16 pga[2]; | ||
36 | u16 pad[2]; | ||
37 | u16 ipa[2]; | ||
38 | }; | ||
39 | |||
40 | struct nphy_iqcal_params { | ||
41 | u16 txgm; | ||
42 | u16 pga; | ||
43 | u16 pad; | ||
44 | u16 ipa; | ||
45 | u16 cal_gain; | ||
46 | u16 ncorr[5]; | ||
47 | }; | ||
48 | |||
49 | struct nphy_iq_est { | ||
50 | s32 iq0_prod; | ||
51 | u32 i0_pwr; | ||
52 | u32 q0_pwr; | ||
53 | s32 iq1_prod; | ||
54 | u32 i1_pwr; | ||
55 | u32 q1_pwr; | ||
56 | }; | ||
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 | static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field, | ||
72 | u16 value, u8 core, bool off); | ||
73 | static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, | ||
74 | u16 value, u8 core); | ||
32 | 75 | ||
33 | void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) | 76 | void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) |
34 | {//TODO | 77 | {//TODO |
@@ -197,173 +240,1020 @@ void b43_nphy_radio_turn_off(struct b43_wldev *dev) | |||
197 | ~B43_NPHY_RFCTL_CMD_EN); | 240 | ~B43_NPHY_RFCTL_CMD_EN); |
198 | } | 241 | } |
199 | 242 | ||
200 | #define ntab_upload(dev, offset, data) do { \ | 243 | /* |
201 | unsigned int i; \ | 244 | * Upload the N-PHY tables. |
202 | for (i = 0; i < (offset##_SIZE); i++) \ | 245 | * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables |
203 | b43_ntab_write(dev, (offset) + i, (data)[i]); \ | 246 | */ |
204 | } while (0) | ||
205 | |||
206 | /* Upload the N-PHY tables. */ | ||
207 | static void b43_nphy_tables_init(struct b43_wldev *dev) | 247 | static void b43_nphy_tables_init(struct b43_wldev *dev) |
208 | { | 248 | { |
209 | /* Static tables */ | 249 | if (dev->phy.rev < 3) |
210 | ntab_upload(dev, B43_NTAB_FRAMESTRUCT, b43_ntab_framestruct); | 250 | b43_nphy_rev0_1_2_tables_init(dev); |
211 | ntab_upload(dev, B43_NTAB_FRAMELT, b43_ntab_framelookup); | 251 | else |
212 | ntab_upload(dev, B43_NTAB_TMAP, b43_ntab_tmap); | 252 | b43_nphy_rev3plus_tables_init(dev); |
213 | ntab_upload(dev, B43_NTAB_TDTRN, b43_ntab_tdtrn); | 253 | } |
214 | ntab_upload(dev, B43_NTAB_INTLEVEL, b43_ntab_intlevel); | 254 | |
215 | ntab_upload(dev, B43_NTAB_PILOT, b43_ntab_pilot); | 255 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */ |
216 | ntab_upload(dev, B43_NTAB_PILOTLT, b43_ntab_pilotlt); | 256 | static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable) |
217 | ntab_upload(dev, B43_NTAB_TDI20A0, b43_ntab_tdi20a0); | 257 | { |
218 | ntab_upload(dev, B43_NTAB_TDI20A1, b43_ntab_tdi20a1); | 258 | struct b43_phy_n *nphy = dev->phy.n; |
219 | ntab_upload(dev, B43_NTAB_TDI40A0, b43_ntab_tdi40a0); | 259 | enum ieee80211_band band; |
220 | ntab_upload(dev, B43_NTAB_TDI40A1, b43_ntab_tdi40a1); | 260 | u16 tmp; |
221 | ntab_upload(dev, B43_NTAB_BDI, b43_ntab_bdi); | 261 | |
222 | ntab_upload(dev, B43_NTAB_CHANEST, b43_ntab_channelest); | 262 | if (!enable) { |
223 | ntab_upload(dev, B43_NTAB_MCS, b43_ntab_mcs); | 263 | nphy->rfctrl_intc1_save = b43_phy_read(dev, |
224 | 264 | B43_NPHY_RFCTL_INTC1); | |
225 | /* Volatile tables */ | 265 | nphy->rfctrl_intc2_save = b43_phy_read(dev, |
226 | ntab_upload(dev, B43_NTAB_NOISEVAR10, b43_ntab_noisevar10); | 266 | B43_NPHY_RFCTL_INTC2); |
227 | ntab_upload(dev, B43_NTAB_NOISEVAR11, b43_ntab_noisevar11); | 267 | band = b43_current_band(dev->wl); |
228 | ntab_upload(dev, B43_NTAB_C0_ESTPLT, b43_ntab_estimatepowerlt0); | 268 | if (dev->phy.rev >= 3) { |
229 | ntab_upload(dev, B43_NTAB_C1_ESTPLT, b43_ntab_estimatepowerlt1); | 269 | if (band == IEEE80211_BAND_5GHZ) |
230 | ntab_upload(dev, B43_NTAB_C0_ADJPLT, b43_ntab_adjustpower0); | 270 | tmp = 0x600; |
231 | ntab_upload(dev, B43_NTAB_C1_ADJPLT, b43_ntab_adjustpower1); | 271 | else |
232 | ntab_upload(dev, B43_NTAB_C0_GAINCTL, b43_ntab_gainctl0); | 272 | tmp = 0x480; |
233 | ntab_upload(dev, B43_NTAB_C1_GAINCTL, b43_ntab_gainctl1); | 273 | } else { |
234 | ntab_upload(dev, B43_NTAB_C0_IQLT, b43_ntab_iqlt0); | 274 | if (band == IEEE80211_BAND_5GHZ) |
235 | ntab_upload(dev, B43_NTAB_C1_IQLT, b43_ntab_iqlt1); | 275 | tmp = 0x180; |
236 | ntab_upload(dev, B43_NTAB_C0_LOFEEDTH, b43_ntab_loftlt0); | 276 | else |
237 | ntab_upload(dev, B43_NTAB_C1_LOFEEDTH, b43_ntab_loftlt1); | 277 | tmp = 0x120; |
278 | } | ||
279 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp); | ||
280 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp); | ||
281 | } else { | ||
282 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, | ||
283 | nphy->rfctrl_intc1_save); | ||
284 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, | ||
285 | nphy->rfctrl_intc2_save); | ||
286 | } | ||
238 | } | 287 | } |
239 | 288 | ||
240 | static void b43_nphy_workarounds(struct b43_wldev *dev) | 289 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw */ |
290 | static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev) | ||
291 | { | ||
292 | struct b43_phy_n *nphy = dev->phy.n; | ||
293 | u16 tmp; | ||
294 | enum ieee80211_band band = b43_current_band(dev->wl); | ||
295 | bool ipa = (nphy->ipa2g_on && band == IEEE80211_BAND_2GHZ) || | ||
296 | (nphy->ipa5g_on && band == IEEE80211_BAND_5GHZ); | ||
297 | |||
298 | if (dev->phy.rev >= 3) { | ||
299 | if (ipa) { | ||
300 | tmp = 4; | ||
301 | b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2, | ||
302 | (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp); | ||
303 | } | ||
304 | |||
305 | tmp = 1; | ||
306 | b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S2, | ||
307 | (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp); | ||
308 | } | ||
309 | } | ||
310 | |||
311 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */ | ||
312 | static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force) | ||
313 | { | ||
314 | u32 tmslow; | ||
315 | |||
316 | if (dev->phy.type != B43_PHYTYPE_N) | ||
317 | return; | ||
318 | |||
319 | tmslow = ssb_read32(dev->dev, SSB_TMSLOW); | ||
320 | if (force) | ||
321 | tmslow |= SSB_TMSLOW_FGC; | ||
322 | else | ||
323 | tmslow &= ~SSB_TMSLOW_FGC; | ||
324 | ssb_write32(dev->dev, SSB_TMSLOW, tmslow); | ||
325 | } | ||
326 | |||
327 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */ | ||
328 | static void b43_nphy_reset_cca(struct b43_wldev *dev) | ||
329 | { | ||
330 | u16 bbcfg; | ||
331 | |||
332 | b43_nphy_bmac_clock_fgc(dev, 1); | ||
333 | bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG); | ||
334 | b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA); | ||
335 | udelay(1); | ||
336 | b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA); | ||
337 | b43_nphy_bmac_clock_fgc(dev, 0); | ||
338 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); | ||
339 | } | ||
340 | |||
341 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */ | ||
342 | static void b43_nphy_update_mimo_config(struct b43_wldev *dev, s32 preamble) | ||
343 | { | ||
344 | u16 mimocfg = b43_phy_read(dev, B43_NPHY_MIMOCFG); | ||
345 | |||
346 | mimocfg |= B43_NPHY_MIMOCFG_AUTO; | ||
347 | if (preamble == 1) | ||
348 | mimocfg |= B43_NPHY_MIMOCFG_GFMIX; | ||
349 | else | ||
350 | mimocfg &= ~B43_NPHY_MIMOCFG_GFMIX; | ||
351 | |||
352 | b43_phy_write(dev, B43_NPHY_MIMOCFG, mimocfg); | ||
353 | } | ||
354 | |||
355 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */ | ||
356 | static void b43_nphy_update_txrx_chain(struct b43_wldev *dev) | ||
357 | { | ||
358 | struct b43_phy_n *nphy = dev->phy.n; | ||
359 | |||
360 | bool override = false; | ||
361 | u16 chain = 0x33; | ||
362 | |||
363 | if (nphy->txrx_chain == 0) { | ||
364 | chain = 0x11; | ||
365 | override = true; | ||
366 | } else if (nphy->txrx_chain == 1) { | ||
367 | chain = 0x22; | ||
368 | override = true; | ||
369 | } | ||
370 | |||
371 | b43_phy_maskset(dev, B43_NPHY_RFSEQCA, | ||
372 | ~(B43_NPHY_RFSEQCA_TXEN | B43_NPHY_RFSEQCA_RXEN), | ||
373 | chain); | ||
374 | |||
375 | if (override) | ||
376 | b43_phy_set(dev, B43_NPHY_RFSEQMODE, | ||
377 | B43_NPHY_RFSEQMODE_CAOVER); | ||
378 | else | ||
379 | b43_phy_mask(dev, B43_NPHY_RFSEQMODE, | ||
380 | ~B43_NPHY_RFSEQMODE_CAOVER); | ||
381 | } | ||
382 | |||
383 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */ | ||
384 | static void b43_nphy_rx_iq_est(struct b43_wldev *dev, struct nphy_iq_est *est, | ||
385 | u16 samps, u8 time, bool wait) | ||
386 | { | ||
387 | int i; | ||
388 | u16 tmp; | ||
389 | |||
390 | b43_phy_write(dev, B43_NPHY_IQEST_SAMCNT, samps); | ||
391 | b43_phy_maskset(dev, B43_NPHY_IQEST_WT, ~B43_NPHY_IQEST_WT_VAL, time); | ||
392 | if (wait) | ||
393 | b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_MODE); | ||
394 | else | ||
395 | b43_phy_mask(dev, B43_NPHY_IQEST_CMD, ~B43_NPHY_IQEST_CMD_MODE); | ||
396 | |||
397 | b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_START); | ||
398 | |||
399 | for (i = 1000; i; i--) { | ||
400 | tmp = b43_phy_read(dev, B43_NPHY_IQEST_CMD); | ||
401 | if (!(tmp & B43_NPHY_IQEST_CMD_START)) { | ||
402 | est->i0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI0) << 16) | | ||
403 | b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO0); | ||
404 | est->q0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI0) << 16) | | ||
405 | b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO0); | ||
406 | est->iq0_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI0) << 16) | | ||
407 | b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO0); | ||
408 | |||
409 | est->i1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI1) << 16) | | ||
410 | b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO1); | ||
411 | est->q1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI1) << 16) | | ||
412 | b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO1); | ||
413 | est->iq1_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI1) << 16) | | ||
414 | b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO1); | ||
415 | return; | ||
416 | } | ||
417 | udelay(10); | ||
418 | } | ||
419 | memset(est, 0, sizeof(*est)); | ||
420 | } | ||
421 | |||
422 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */ | ||
423 | static void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write, | ||
424 | struct b43_phy_n_iq_comp *pcomp) | ||
425 | { | ||
426 | if (write) { | ||
427 | b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPA0, pcomp->a0); | ||
428 | b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPB0, pcomp->b0); | ||
429 | b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPA1, pcomp->a1); | ||
430 | b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPB1, pcomp->b1); | ||
431 | } else { | ||
432 | pcomp->a0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPA0); | ||
433 | pcomp->b0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPB0); | ||
434 | pcomp->a1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPA1); | ||
435 | pcomp->b1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPB1); | ||
436 | } | ||
437 | } | ||
438 | |||
439 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */ | ||
440 | static void b43_nphy_rx_cal_phy_cleanup(struct b43_wldev *dev, u8 core) | ||
441 | { | ||
442 | u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs; | ||
443 | |||
444 | b43_phy_write(dev, B43_NPHY_RFSEQCA, regs[0]); | ||
445 | if (core == 0) { | ||
446 | b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[1]); | ||
447 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]); | ||
448 | } else { | ||
449 | b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]); | ||
450 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]); | ||
451 | } | ||
452 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[3]); | ||
453 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[4]); | ||
454 | b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, regs[5]); | ||
455 | b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, regs[6]); | ||
456 | b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, regs[7]); | ||
457 | b43_phy_write(dev, B43_NPHY_RFCTL_OVER, regs[8]); | ||
458 | b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]); | ||
459 | b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]); | ||
460 | } | ||
461 | |||
462 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhySetup */ | ||
463 | static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core) | ||
464 | { | ||
465 | u8 rxval, txval; | ||
466 | u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs; | ||
467 | |||
468 | regs[0] = b43_phy_read(dev, B43_NPHY_RFSEQCA); | ||
469 | if (core == 0) { | ||
470 | regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); | ||
471 | regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1); | ||
472 | } else { | ||
473 | regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); | ||
474 | regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); | ||
475 | } | ||
476 | regs[3] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); | ||
477 | regs[4] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); | ||
478 | regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1); | ||
479 | regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2); | ||
480 | regs[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S1); | ||
481 | regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER); | ||
482 | regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0); | ||
483 | regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1); | ||
484 | |||
485 | b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001); | ||
486 | b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001); | ||
487 | |||
488 | b43_phy_maskset(dev, B43_NPHY_RFSEQCA, (u16)~B43_NPHY_RFSEQCA_RXDIS, | ||
489 | ((1 - core) << B43_NPHY_RFSEQCA_RXDIS_SHIFT)); | ||
490 | b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN, | ||
491 | ((1 - core) << B43_NPHY_RFSEQCA_TXEN_SHIFT)); | ||
492 | b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN, | ||
493 | (core << B43_NPHY_RFSEQCA_RXEN_SHIFT)); | ||
494 | b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXDIS, | ||
495 | (core << B43_NPHY_RFSEQCA_TXDIS_SHIFT)); | ||
496 | |||
497 | if (core == 0) { | ||
498 | b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x0007); | ||
499 | b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0007); | ||
500 | } else { | ||
501 | b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x0007); | ||
502 | b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0007); | ||
503 | } | ||
504 | |||
505 | b43_nphy_rf_control_intc_override(dev, 2, 0, 3); | ||
506 | b43_nphy_rf_control_override(dev, 8, 0, 3, false); | ||
507 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); | ||
508 | |||
509 | if (core == 0) { | ||
510 | rxval = 1; | ||
511 | txval = 8; | ||
512 | } else { | ||
513 | rxval = 4; | ||
514 | txval = 2; | ||
515 | } | ||
516 | b43_nphy_rf_control_intc_override(dev, 1, rxval, (core + 1)); | ||
517 | b43_nphy_rf_control_intc_override(dev, 1, txval, (2 - core)); | ||
518 | } | ||
519 | |||
520 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */ | ||
521 | static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask) | ||
522 | { | ||
523 | int i; | ||
524 | s32 iq; | ||
525 | u32 ii; | ||
526 | u32 qq; | ||
527 | int iq_nbits, qq_nbits; | ||
528 | int arsh, brsh; | ||
529 | u16 tmp, a, b; | ||
530 | |||
531 | struct nphy_iq_est est; | ||
532 | struct b43_phy_n_iq_comp old; | ||
533 | struct b43_phy_n_iq_comp new = { }; | ||
534 | bool error = false; | ||
535 | |||
536 | if (mask == 0) | ||
537 | return; | ||
538 | |||
539 | b43_nphy_rx_iq_coeffs(dev, false, &old); | ||
540 | b43_nphy_rx_iq_coeffs(dev, true, &new); | ||
541 | b43_nphy_rx_iq_est(dev, &est, 0x4000, 32, false); | ||
542 | new = old; | ||
543 | |||
544 | for (i = 0; i < 2; i++) { | ||
545 | if (i == 0 && (mask & 1)) { | ||
546 | iq = est.iq0_prod; | ||
547 | ii = est.i0_pwr; | ||
548 | qq = est.q0_pwr; | ||
549 | } else if (i == 1 && (mask & 2)) { | ||
550 | iq = est.iq1_prod; | ||
551 | ii = est.i1_pwr; | ||
552 | qq = est.q1_pwr; | ||
553 | } else { | ||
554 | B43_WARN_ON(1); | ||
555 | continue; | ||
556 | } | ||
557 | |||
558 | if (ii + qq < 2) { | ||
559 | error = true; | ||
560 | break; | ||
561 | } | ||
562 | |||
563 | iq_nbits = fls(abs(iq)); | ||
564 | qq_nbits = fls(qq); | ||
565 | |||
566 | arsh = iq_nbits - 20; | ||
567 | if (arsh >= 0) { | ||
568 | a = -((iq << (30 - iq_nbits)) + (ii >> (1 + arsh))); | ||
569 | tmp = ii >> arsh; | ||
570 | } else { | ||
571 | a = -((iq << (30 - iq_nbits)) + (ii << (-1 - arsh))); | ||
572 | tmp = ii << -arsh; | ||
573 | } | ||
574 | if (tmp == 0) { | ||
575 | error = true; | ||
576 | break; | ||
577 | } | ||
578 | a /= tmp; | ||
579 | |||
580 | brsh = qq_nbits - 11; | ||
581 | if (brsh >= 0) { | ||
582 | b = (qq << (31 - qq_nbits)); | ||
583 | tmp = ii >> brsh; | ||
584 | } else { | ||
585 | b = (qq << (31 - qq_nbits)); | ||
586 | tmp = ii << -brsh; | ||
587 | } | ||
588 | if (tmp == 0) { | ||
589 | error = true; | ||
590 | break; | ||
591 | } | ||
592 | b = int_sqrt(b / tmp - a * a) - (1 << 10); | ||
593 | |||
594 | if (i == 0 && (mask & 0x1)) { | ||
595 | if (dev->phy.rev >= 3) { | ||
596 | new.a0 = a & 0x3FF; | ||
597 | new.b0 = b & 0x3FF; | ||
598 | } else { | ||
599 | new.a0 = b & 0x3FF; | ||
600 | new.b0 = a & 0x3FF; | ||
601 | } | ||
602 | } else if (i == 1 && (mask & 0x2)) { | ||
603 | if (dev->phy.rev >= 3) { | ||
604 | new.a1 = a & 0x3FF; | ||
605 | new.b1 = b & 0x3FF; | ||
606 | } else { | ||
607 | new.a1 = b & 0x3FF; | ||
608 | new.b1 = a & 0x3FF; | ||
609 | } | ||
610 | } | ||
611 | } | ||
612 | |||
613 | if (error) | ||
614 | new = old; | ||
615 | |||
616 | b43_nphy_rx_iq_coeffs(dev, true, &new); | ||
617 | } | ||
618 | |||
619 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */ | ||
620 | static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev) | ||
621 | { | ||
622 | u16 array[4]; | ||
623 | int i; | ||
624 | |||
625 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C50); | ||
626 | for (i = 0; i < 4; i++) | ||
627 | array[i] = b43_phy_read(dev, B43_NPHY_TABLE_DATALO); | ||
628 | |||
629 | b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW0, array[0]); | ||
630 | b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW1, array[1]); | ||
631 | b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW2, array[2]); | ||
632 | b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW3, array[3]); | ||
633 | } | ||
634 | |||
635 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */ | ||
636 | static void b43_nphy_write_clip_detection(struct b43_wldev *dev, u16 *clip_st) | ||
637 | { | ||
638 | b43_phy_write(dev, B43_NPHY_C1_CLIP1THRES, clip_st[0]); | ||
639 | b43_phy_write(dev, B43_NPHY_C2_CLIP1THRES, clip_st[1]); | ||
640 | } | ||
641 | |||
642 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */ | ||
643 | static void b43_nphy_read_clip_detection(struct b43_wldev *dev, u16 *clip_st) | ||
644 | { | ||
645 | clip_st[0] = b43_phy_read(dev, B43_NPHY_C1_CLIP1THRES); | ||
646 | clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES); | ||
647 | } | ||
648 | |||
649 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */ | ||
650 | static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val) | ||
651 | { | ||
652 | u16 tmp; | ||
653 | |||
654 | if (dev->dev->id.revision == 16) | ||
655 | b43_mac_suspend(dev); | ||
656 | |||
657 | tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL); | ||
658 | tmp &= (B43_NPHY_CLASSCTL_CCKEN | B43_NPHY_CLASSCTL_OFDMEN | | ||
659 | B43_NPHY_CLASSCTL_WAITEDEN); | ||
660 | tmp &= ~mask; | ||
661 | tmp |= (val & mask); | ||
662 | b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp); | ||
663 | |||
664 | if (dev->dev->id.revision == 16) | ||
665 | b43_mac_enable(dev); | ||
666 | |||
667 | return tmp; | ||
668 | } | ||
669 | |||
670 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/carriersearch */ | ||
671 | static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable) | ||
241 | { | 672 | { |
242 | struct b43_phy *phy = &dev->phy; | 673 | struct b43_phy *phy = &dev->phy; |
243 | unsigned int i; | 674 | struct b43_phy_n *nphy = phy->n; |
244 | 675 | ||
245 | b43_phy_set(dev, B43_NPHY_IQFLIP, | 676 | if (enable) { |
246 | B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2); | 677 | u16 clip[] = { 0xFFFF, 0xFFFF }; |
247 | if (1 /* FIXME band is 2.4GHz */) { | 678 | if (nphy->deaf_count++ == 0) { |
248 | b43_phy_set(dev, B43_NPHY_CLASSCTL, | 679 | nphy->classifier_state = b43_nphy_classifier(dev, 0, 0); |
249 | B43_NPHY_CLASSCTL_CCKEN); | 680 | b43_nphy_classifier(dev, 0x7, 0); |
250 | } else { | 681 | b43_nphy_read_clip_detection(dev, nphy->clip_state); |
251 | b43_phy_mask(dev, B43_NPHY_CLASSCTL, | 682 | b43_nphy_write_clip_detection(dev, clip); |
252 | ~B43_NPHY_CLASSCTL_CCKEN); | 683 | } |
253 | } | 684 | b43_nphy_reset_cca(dev); |
254 | b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8); | 685 | } else { |
255 | b43_phy_write(dev, B43_NPHY_TXFRAMEDELAY, 8); | 686 | if (--nphy->deaf_count == 0) { |
256 | 687 | b43_nphy_classifier(dev, 0x7, nphy->classifier_state); | |
257 | /* Fixup some tables */ | 688 | b43_nphy_write_clip_detection(dev, nphy->clip_state); |
258 | b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0xA); | 689 | } |
259 | b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0xA); | 690 | } |
260 | b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA); | 691 | } |
261 | b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA); | 692 | |
262 | b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0); | 693 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */ |
263 | b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0); | 694 | static void b43_nphy_stop_playback(struct b43_wldev *dev) |
264 | b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB); | 695 | { |
265 | b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB); | 696 | struct b43_phy_n *nphy = dev->phy.n; |
266 | b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x800); | 697 | u16 tmp; |
267 | b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x800); | 698 | |
268 | 699 | if (nphy->hang_avoid) | |
269 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); | 700 | b43_nphy_stay_in_carrier_search(dev, 1); |
270 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); | 701 | |
271 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); | 702 | tmp = b43_phy_read(dev, B43_NPHY_SAMP_STAT); |
272 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); | 703 | if (tmp & 0x1) |
273 | 704 | b43_phy_set(dev, B43_NPHY_SAMP_CMD, B43_NPHY_SAMP_CMD_STOP); | |
274 | //TODO set RF sequence | 705 | else if (tmp & 0x2) |
275 | 706 | b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, (u16)~0x8000); | |
276 | /* Set narrowband clip threshold */ | 707 | |
277 | b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 66); | 708 | b43_phy_mask(dev, B43_NPHY_SAMP_CMD, ~0x0004); |
278 | b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 66); | 709 | |
279 | 710 | if (nphy->bb_mult_save & 0x80000000) { | |
280 | /* Set wideband clip 2 threshold */ | 711 | tmp = nphy->bb_mult_save & 0xFFFF; |
281 | b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES, | 712 | b43_ntab_write(dev, B43_NTAB16(15, 87), tmp); |
282 | ~B43_NPHY_C1_CLIPWBTHRES_CLIP2, | 713 | nphy->bb_mult_save = 0; |
283 | 21 << B43_NPHY_C1_CLIPWBTHRES_CLIP2_SHIFT); | 714 | } |
284 | b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES, | 715 | |
285 | ~B43_NPHY_C2_CLIPWBTHRES_CLIP2, | 716 | if (nphy->hang_avoid) |
286 | 21 << B43_NPHY_C2_CLIPWBTHRES_CLIP2_SHIFT); | 717 | b43_nphy_stay_in_carrier_search(dev, 0); |
287 | 718 | } | |
288 | /* Set Clip 2 detect */ | 719 | |
289 | b43_phy_set(dev, B43_NPHY_C1_CGAINI, | 720 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SpurWar */ |
290 | B43_NPHY_C1_CGAINI_CL2DETECT); | 721 | static void b43_nphy_spur_workaround(struct b43_wldev *dev) |
291 | b43_phy_set(dev, B43_NPHY_C2_CGAINI, | 722 | { |
292 | B43_NPHY_C2_CGAINI_CL2DETECT); | 723 | struct b43_phy_n *nphy = dev->phy.n; |
293 | 724 | ||
294 | if (0 /*FIXME*/) { | 725 | unsigned int channel; |
295 | /* Set dwell lengths */ | 726 | int tone[2] = { 57, 58 }; |
296 | b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 43); | 727 | u32 noise[2] = { 0x3FF, 0x3FF }; |
297 | b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 43); | 728 | |
298 | b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 9); | 729 | B43_WARN_ON(dev->phy.rev < 3); |
299 | b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 9); | 730 | |
300 | 731 | if (nphy->hang_avoid) | |
301 | /* Set gain backoff */ | 732 | b43_nphy_stay_in_carrier_search(dev, 1); |
302 | b43_phy_maskset(dev, B43_NPHY_C1_CGAINI, | 733 | |
303 | ~B43_NPHY_C1_CGAINI_GAINBKOFF, | 734 | /* FIXME: channel = radio_chanspec */ |
304 | 1 << B43_NPHY_C1_CGAINI_GAINBKOFF_SHIFT); | 735 | |
305 | b43_phy_maskset(dev, B43_NPHY_C2_CGAINI, | 736 | if (nphy->gband_spurwar_en) { |
306 | ~B43_NPHY_C2_CGAINI_GAINBKOFF, | 737 | /* TODO: N PHY Adjust Analog Pfbw (7) */ |
307 | 1 << B43_NPHY_C2_CGAINI_GAINBKOFF_SHIFT); | 738 | if (channel == 11 && dev->phy.is_40mhz) |
739 | ; /* TODO: N PHY Adjust Min Noise Var(2, tone, noise)*/ | ||
740 | else | ||
741 | ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/ | ||
742 | /* TODO: N PHY Adjust CRS Min Power (0x1E) */ | ||
743 | } | ||
744 | |||
745 | if (nphy->aband_spurwar_en) { | ||
746 | if (channel == 54) { | ||
747 | tone[0] = 0x20; | ||
748 | noise[0] = 0x25F; | ||
749 | } else if (channel == 38 || channel == 102 || channel == 118) { | ||
750 | if (0 /* FIXME */) { | ||
751 | tone[0] = 0x20; | ||
752 | noise[0] = 0x21F; | ||
753 | } else { | ||
754 | tone[0] = 0; | ||
755 | noise[0] = 0; | ||
756 | } | ||
757 | } else if (channel == 134) { | ||
758 | tone[0] = 0x20; | ||
759 | noise[0] = 0x21F; | ||
760 | } else if (channel == 151) { | ||
761 | tone[0] = 0x10; | ||
762 | noise[0] = 0x23F; | ||
763 | } else if (channel == 153 || channel == 161) { | ||
764 | tone[0] = 0x30; | ||
765 | noise[0] = 0x23F; | ||
766 | } else { | ||
767 | tone[0] = 0; | ||
768 | noise[0] = 0; | ||
769 | } | ||
770 | |||
771 | if (!tone[0] && !noise[0]) | ||
772 | ; /* TODO: N PHY Adjust Min Noise Var(1, tone, noise)*/ | ||
773 | else | ||
774 | ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/ | ||
775 | } | ||
776 | |||
777 | if (nphy->hang_avoid) | ||
778 | b43_nphy_stay_in_carrier_search(dev, 0); | ||
779 | } | ||
780 | |||
781 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */ | ||
782 | static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev) | ||
783 | { | ||
784 | struct b43_phy_n *nphy = dev->phy.n; | ||
785 | u8 i, j; | ||
786 | u8 code; | ||
787 | |||
788 | /* TODO: for PHY >= 3 | ||
789 | s8 *lna1_gain, *lna2_gain; | ||
790 | u8 *gain_db, *gain_bits; | ||
791 | u16 *rfseq_init; | ||
792 | u8 lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 }; | ||
793 | u8 lpf_bits[6] = { 0, 1, 2, 3, 3, 3 }; | ||
794 | */ | ||
795 | |||
796 | u8 rfseq_events[3] = { 6, 8, 7 }; | ||
797 | u8 rfseq_delays[3] = { 10, 30, 1 }; | ||
798 | |||
799 | if (dev->phy.rev >= 3) { | ||
800 | /* TODO */ | ||
801 | } else { | ||
802 | /* Set Clip 2 detect */ | ||
803 | b43_phy_set(dev, B43_NPHY_C1_CGAINI, | ||
804 | B43_NPHY_C1_CGAINI_CL2DETECT); | ||
805 | b43_phy_set(dev, B43_NPHY_C2_CGAINI, | ||
806 | B43_NPHY_C2_CGAINI_CL2DETECT); | ||
807 | |||
808 | /* Set narrowband clip threshold */ | ||
809 | b43_phy_set(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84); | ||
810 | b43_phy_set(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84); | ||
811 | |||
812 | if (!dev->phy.is_40mhz) { | ||
813 | /* Set dwell lengths */ | ||
814 | b43_phy_set(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B); | ||
815 | b43_phy_set(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B); | ||
816 | b43_phy_set(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 0x0009); | ||
817 | b43_phy_set(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 0x0009); | ||
818 | } | ||
819 | |||
820 | /* Set wideband clip 2 threshold */ | ||
821 | b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES, | ||
822 | ~B43_NPHY_C1_CLIPWBTHRES_CLIP2, | ||
823 | 21); | ||
824 | b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES, | ||
825 | ~B43_NPHY_C2_CLIPWBTHRES_CLIP2, | ||
826 | 21); | ||
827 | |||
828 | if (!dev->phy.is_40mhz) { | ||
829 | b43_phy_maskset(dev, B43_NPHY_C1_CGAINI, | ||
830 | ~B43_NPHY_C1_CGAINI_GAINBKOFF, 0x1); | ||
831 | b43_phy_maskset(dev, B43_NPHY_C2_CGAINI, | ||
832 | ~B43_NPHY_C2_CGAINI_GAINBKOFF, 0x1); | ||
833 | b43_phy_maskset(dev, B43_NPHY_C1_CCK_CGAINI, | ||
834 | ~B43_NPHY_C1_CCK_CGAINI_GAINBKOFF, 0x1); | ||
835 | b43_phy_maskset(dev, B43_NPHY_C2_CCK_CGAINI, | ||
836 | ~B43_NPHY_C2_CCK_CGAINI_GAINBKOFF, 0x1); | ||
837 | } | ||
838 | |||
839 | b43_phy_set(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C); | ||
840 | |||
841 | if (nphy->gain_boost) { | ||
842 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ && | ||
843 | dev->phy.is_40mhz) | ||
844 | code = 4; | ||
845 | else | ||
846 | code = 5; | ||
847 | } else { | ||
848 | code = dev->phy.is_40mhz ? 6 : 7; | ||
849 | } | ||
308 | 850 | ||
309 | /* Set HPVGA2 index */ | 851 | /* Set HPVGA2 index */ |
310 | b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN, | 852 | b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN, |
311 | ~B43_NPHY_C1_INITGAIN_HPVGA2, | 853 | ~B43_NPHY_C1_INITGAIN_HPVGA2, |
312 | 6 << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT); | 854 | code << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT); |
313 | b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN, | 855 | b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN, |
314 | ~B43_NPHY_C2_INITGAIN_HPVGA2, | 856 | ~B43_NPHY_C2_INITGAIN_HPVGA2, |
315 | 6 << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT); | 857 | code << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT); |
858 | |||
859 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06); | ||
860 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, | ||
861 | (code << 8 | 0x7C)); | ||
862 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, | ||
863 | (code << 8 | 0x7C)); | ||
864 | |||
865 | /* TODO: b43_nphy_adjust_lna_gain_table(dev); */ | ||
866 | |||
867 | if (nphy->elna_gain_config) { | ||
868 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0808); | ||
869 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0); | ||
870 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); | ||
871 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); | ||
872 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); | ||
873 | |||
874 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0C08); | ||
875 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0); | ||
876 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); | ||
877 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); | ||
878 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); | ||
879 | |||
880 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06); | ||
881 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, | ||
882 | (code << 8 | 0x74)); | ||
883 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, | ||
884 | (code << 8 | 0x74)); | ||
885 | } | ||
316 | 886 | ||
317 | //FIXME verify that the specs really mean to use autoinc here. | 887 | if (dev->phy.rev == 2) { |
318 | for (i = 0; i < 3; i++) | 888 | for (i = 0; i < 4; i++) { |
319 | b43_ntab_write(dev, B43_NTAB16(7, 0x106) + i, 0x673); | 889 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, |
890 | (0x0400 * i) + 0x0020); | ||
891 | for (j = 0; j < 21; j++) | ||
892 | b43_phy_write(dev, | ||
893 | B43_NPHY_TABLE_DATALO, 3 * j); | ||
894 | } | ||
895 | |||
896 | b43_nphy_set_rf_sequence(dev, 5, | ||
897 | rfseq_events, rfseq_delays, 3); | ||
898 | b43_phy_maskset(dev, B43_NPHY_OVER_DGAIN1, | ||
899 | (u16)~B43_NPHY_OVER_DGAIN_CCKDGECV, | ||
900 | 0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT); | ||
901 | |||
902 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | ||
903 | b43_phy_maskset(dev, B43_PHY_N(0xC5D), | ||
904 | 0xFF80, 4); | ||
905 | } | ||
320 | } | 906 | } |
907 | } | ||
321 | 908 | ||
322 | /* Set minimum gain value */ | 909 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */ |
323 | b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN, | 910 | static void b43_nphy_workarounds(struct b43_wldev *dev) |
324 | ~B43_NPHY_C1_MINGAIN, | 911 | { |
325 | 23 << B43_NPHY_C1_MINGAIN_SHIFT); | 912 | struct ssb_bus *bus = dev->dev->bus; |
326 | b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN, | 913 | struct b43_phy *phy = &dev->phy; |
327 | ~B43_NPHY_C2_MINGAIN, | 914 | struct b43_phy_n *nphy = phy->n; |
328 | 23 << B43_NPHY_C2_MINGAIN_SHIFT); | ||
329 | 915 | ||
330 | if (phy->rev < 2) { | 916 | u8 events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 }; |
331 | b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL, | 917 | u8 delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 }; |
332 | ~B43_NPHY_SCRAM_SIGCTL_SCM); | 918 | |
919 | u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 }; | ||
920 | u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 }; | ||
921 | |||
922 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | ||
923 | b43_nphy_classifier(dev, 1, 0); | ||
924 | else | ||
925 | b43_nphy_classifier(dev, 1, 1); | ||
926 | |||
927 | if (nphy->hang_avoid) | ||
928 | b43_nphy_stay_in_carrier_search(dev, 1); | ||
929 | |||
930 | b43_phy_set(dev, B43_NPHY_IQFLIP, | ||
931 | B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2); | ||
932 | |||
933 | if (dev->phy.rev >= 3) { | ||
934 | /* TODO */ | ||
935 | } else { | ||
936 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ && | ||
937 | nphy->band5g_pwrgain) { | ||
938 | b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8); | ||
939 | b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8); | ||
940 | } else { | ||
941 | b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8); | ||
942 | b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8); | ||
943 | } | ||
944 | |||
945 | /* TODO: convert to b43_ntab_write? */ | ||
946 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2000); | ||
947 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x000A); | ||
948 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2010); | ||
949 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x000A); | ||
950 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2002); | ||
951 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0xCDAA); | ||
952 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2012); | ||
953 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0xCDAA); | ||
954 | |||
955 | if (dev->phy.rev < 2) { | ||
956 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2008); | ||
957 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0000); | ||
958 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2018); | ||
959 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0000); | ||
960 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2007); | ||
961 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x7AAB); | ||
962 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2017); | ||
963 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x7AAB); | ||
964 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2006); | ||
965 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0800); | ||
966 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2016); | ||
967 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0800); | ||
968 | } | ||
969 | |||
970 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); | ||
971 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); | ||
972 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); | ||
973 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); | ||
974 | |||
975 | if (bus->sprom.boardflags2_lo & 0x100 && | ||
976 | bus->boardinfo.type == 0x8B) { | ||
977 | delays1[0] = 0x1; | ||
978 | delays1[5] = 0x14; | ||
979 | } | ||
980 | b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7); | ||
981 | b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7); | ||
982 | |||
983 | b43_nphy_gain_crtl_workarounds(dev); | ||
984 | |||
985 | if (dev->phy.rev < 2) { | ||
986 | if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2) | ||
987 | ; /*TODO: b43_mhf(dev, 2, 0x0010, 0x0010, 3);*/ | ||
988 | } else if (dev->phy.rev == 2) { | ||
989 | b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0); | ||
990 | b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0); | ||
991 | } | ||
992 | |||
993 | if (dev->phy.rev < 2) | ||
994 | b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL, | ||
995 | ~B43_NPHY_SCRAM_SIGCTL_SCM); | ||
996 | |||
997 | /* Set phase track alpha and beta */ | ||
998 | b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125); | ||
999 | b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3); | ||
1000 | b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105); | ||
1001 | b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E); | ||
1002 | b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD); | ||
1003 | b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20); | ||
1004 | |||
1005 | b43_phy_mask(dev, B43_NPHY_PIL_DW1, | ||
1006 | (u16)~B43_NPHY_PIL_DW_64QAM); | ||
1007 | b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5); | ||
1008 | b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4); | ||
1009 | b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00); | ||
1010 | |||
1011 | if (dev->phy.rev == 2) | ||
1012 | b43_phy_set(dev, B43_NPHY_FINERX2_CGC, | ||
1013 | B43_NPHY_FINERX2_CGC_DECGC); | ||
333 | } | 1014 | } |
334 | 1015 | ||
335 | /* Set phase track alpha and beta */ | 1016 | if (nphy->hang_avoid) |
336 | b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125); | 1017 | b43_nphy_stay_in_carrier_search(dev, 0); |
337 | b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3); | ||
338 | b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105); | ||
339 | b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E); | ||
340 | b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD); | ||
341 | b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20); | ||
342 | } | 1018 | } |
343 | 1019 | ||
344 | static void b43_nphy_reset_cca(struct b43_wldev *dev) | 1020 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/LoadSampleTable */ |
1021 | static int b43_nphy_load_samples(struct b43_wldev *dev, | ||
1022 | struct b43_c32 *samples, u16 len) { | ||
1023 | struct b43_phy_n *nphy = dev->phy.n; | ||
1024 | u16 i; | ||
1025 | u32 *data; | ||
1026 | |||
1027 | data = kzalloc(len * sizeof(u32), GFP_KERNEL); | ||
1028 | if (!data) { | ||
1029 | b43err(dev->wl, "allocation for samples loading failed\n"); | ||
1030 | return -ENOMEM; | ||
1031 | } | ||
1032 | if (nphy->hang_avoid) | ||
1033 | b43_nphy_stay_in_carrier_search(dev, 1); | ||
1034 | |||
1035 | for (i = 0; i < len; i++) { | ||
1036 | data[i] = (samples[i].i & 0x3FF << 10); | ||
1037 | data[i] |= samples[i].q & 0x3FF; | ||
1038 | } | ||
1039 | b43_ntab_write_bulk(dev, B43_NTAB32(17, 0), len, data); | ||
1040 | |||
1041 | kfree(data); | ||
1042 | if (nphy->hang_avoid) | ||
1043 | b43_nphy_stay_in_carrier_search(dev, 0); | ||
1044 | return 0; | ||
1045 | } | ||
1046 | |||
1047 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */ | ||
1048 | static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max, | ||
1049 | bool test) | ||
345 | { | 1050 | { |
346 | u16 bbcfg; | 1051 | int i; |
1052 | u16 bw, len, rot, angle; | ||
1053 | struct b43_c32 *samples; | ||
347 | 1054 | ||
348 | ssb_write32(dev->dev, SSB_TMSLOW, | 1055 | |
349 | ssb_read32(dev->dev, SSB_TMSLOW) | SSB_TMSLOW_FGC); | 1056 | bw = (dev->phy.is_40mhz) ? 40 : 20; |
350 | bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG); | 1057 | len = bw << 3; |
351 | b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTCCA); | 1058 | |
352 | b43_phy_write(dev, B43_NPHY_BBCFG, | 1059 | if (test) { |
353 | bbcfg & ~B43_NPHY_BBCFG_RSTCCA); | 1060 | if (b43_phy_read(dev, B43_NPHY_BBCFG) & B43_NPHY_BBCFG_RSTRX) |
354 | ssb_write32(dev->dev, SSB_TMSLOW, | 1061 | bw = 82; |
355 | ssb_read32(dev->dev, SSB_TMSLOW) & ~SSB_TMSLOW_FGC); | 1062 | else |
1063 | bw = 80; | ||
1064 | |||
1065 | if (dev->phy.is_40mhz) | ||
1066 | bw <<= 1; | ||
1067 | |||
1068 | len = bw << 1; | ||
1069 | } | ||
1070 | |||
1071 | samples = kzalloc(len * sizeof(struct b43_c32), GFP_KERNEL); | ||
1072 | if (!samples) { | ||
1073 | b43err(dev->wl, "allocation for samples generation failed\n"); | ||
1074 | return 0; | ||
1075 | } | ||
1076 | rot = (((freq * 36) / bw) << 16) / 100; | ||
1077 | angle = 0; | ||
1078 | |||
1079 | for (i = 0; i < len; i++) { | ||
1080 | samples[i] = b43_cordic(angle); | ||
1081 | angle += rot; | ||
1082 | samples[i].q = CORDIC_CONVERT(samples[i].q * max); | ||
1083 | samples[i].i = CORDIC_CONVERT(samples[i].i * max); | ||
1084 | } | ||
1085 | |||
1086 | i = b43_nphy_load_samples(dev, samples, len); | ||
1087 | kfree(samples); | ||
1088 | return (i < 0) ? 0 : len; | ||
356 | } | 1089 | } |
357 | 1090 | ||
358 | enum b43_nphy_rf_sequence { | 1091 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */ |
359 | B43_RFSEQ_RX2TX, | 1092 | static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops, |
360 | B43_RFSEQ_TX2RX, | 1093 | u16 wait, bool iqmode, bool dac_test) |
361 | B43_RFSEQ_RESET2RX, | 1094 | { |
362 | B43_RFSEQ_UPDATE_GAINH, | 1095 | struct b43_phy_n *nphy = dev->phy.n; |
363 | B43_RFSEQ_UPDATE_GAINL, | 1096 | int i; |
364 | B43_RFSEQ_UPDATE_GAINU, | 1097 | u16 seq_mode; |
365 | }; | 1098 | u32 tmp; |
1099 | |||
1100 | if (nphy->hang_avoid) | ||
1101 | b43_nphy_stay_in_carrier_search(dev, true); | ||
1102 | |||
1103 | if ((nphy->bb_mult_save & 0x80000000) == 0) { | ||
1104 | tmp = b43_ntab_read(dev, B43_NTAB16(15, 87)); | ||
1105 | nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000; | ||
1106 | } | ||
1107 | |||
1108 | if (!dev->phy.is_40mhz) | ||
1109 | tmp = 0x6464; | ||
1110 | else | ||
1111 | tmp = 0x4747; | ||
1112 | b43_ntab_write(dev, B43_NTAB16(15, 87), tmp); | ||
1113 | |||
1114 | if (nphy->hang_avoid) | ||
1115 | b43_nphy_stay_in_carrier_search(dev, false); | ||
1116 | |||
1117 | b43_phy_write(dev, B43_NPHY_SAMP_DEPCNT, (samps - 1)); | ||
1118 | |||
1119 | if (loops != 0xFFFF) | ||
1120 | b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, (loops - 1)); | ||
1121 | else | ||
1122 | b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, loops); | ||
1123 | |||
1124 | b43_phy_write(dev, B43_NPHY_SAMP_WAITCNT, wait); | ||
1125 | |||
1126 | seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE); | ||
1127 | |||
1128 | b43_phy_set(dev, B43_NPHY_RFSEQMODE, B43_NPHY_RFSEQMODE_CAOVER); | ||
1129 | if (iqmode) { | ||
1130 | b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF); | ||
1131 | b43_phy_set(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8000); | ||
1132 | } else { | ||
1133 | if (dac_test) | ||
1134 | b43_phy_write(dev, B43_NPHY_SAMP_CMD, 5); | ||
1135 | else | ||
1136 | b43_phy_write(dev, B43_NPHY_SAMP_CMD, 1); | ||
1137 | } | ||
1138 | for (i = 0; i < 100; i++) { | ||
1139 | if (b43_phy_read(dev, B43_NPHY_RFSEQST) & 1) { | ||
1140 | i = 0; | ||
1141 | break; | ||
1142 | } | ||
1143 | udelay(10); | ||
1144 | } | ||
1145 | if (i) | ||
1146 | b43err(dev->wl, "run samples timeout\n"); | ||
1147 | |||
1148 | b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode); | ||
1149 | } | ||
1150 | |||
1151 | /* | ||
1152 | * Transmits a known value for LO calibration | ||
1153 | * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone | ||
1154 | */ | ||
1155 | static int b43_nphy_tx_tone(struct b43_wldev *dev, u32 freq, u16 max_val, | ||
1156 | bool iqmode, bool dac_test) | ||
1157 | { | ||
1158 | u16 samp = b43_nphy_gen_load_samples(dev, freq, max_val, dac_test); | ||
1159 | if (samp == 0) | ||
1160 | return -1; | ||
1161 | b43_nphy_run_samples(dev, samp, 0xFFFF, 0, iqmode, dac_test); | ||
1162 | return 0; | ||
1163 | } | ||
1164 | |||
1165 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */ | ||
1166 | static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev) | ||
1167 | { | ||
1168 | struct b43_phy_n *nphy = dev->phy.n; | ||
1169 | int i, j; | ||
1170 | u32 tmp; | ||
1171 | u32 cur_real, cur_imag, real_part, imag_part; | ||
1172 | |||
1173 | u16 buffer[7]; | ||
1174 | |||
1175 | if (nphy->hang_avoid) | ||
1176 | b43_nphy_stay_in_carrier_search(dev, true); | ||
1177 | |||
1178 | b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer); | ||
1179 | |||
1180 | for (i = 0; i < 2; i++) { | ||
1181 | tmp = ((buffer[i * 2] & 0x3FF) << 10) | | ||
1182 | (buffer[i * 2 + 1] & 0x3FF); | ||
1183 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, | ||
1184 | (((i + 26) << 10) | 320)); | ||
1185 | for (j = 0; j < 128; j++) { | ||
1186 | b43_phy_write(dev, B43_NPHY_TABLE_DATAHI, | ||
1187 | ((tmp >> 16) & 0xFFFF)); | ||
1188 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, | ||
1189 | (tmp & 0xFFFF)); | ||
1190 | } | ||
1191 | } | ||
1192 | |||
1193 | for (i = 0; i < 2; i++) { | ||
1194 | tmp = buffer[5 + i]; | ||
1195 | real_part = (tmp >> 8) & 0xFF; | ||
1196 | imag_part = (tmp & 0xFF); | ||
1197 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, | ||
1198 | (((i + 26) << 10) | 448)); | ||
1199 | |||
1200 | if (dev->phy.rev >= 3) { | ||
1201 | cur_real = real_part; | ||
1202 | cur_imag = imag_part; | ||
1203 | tmp = ((cur_real & 0xFF) << 8) | (cur_imag & 0xFF); | ||
1204 | } | ||
1205 | |||
1206 | for (j = 0; j < 128; j++) { | ||
1207 | if (dev->phy.rev < 3) { | ||
1208 | cur_real = (real_part * loscale[j] + 128) >> 8; | ||
1209 | cur_imag = (imag_part * loscale[j] + 128) >> 8; | ||
1210 | tmp = ((cur_real & 0xFF) << 8) | | ||
1211 | (cur_imag & 0xFF); | ||
1212 | } | ||
1213 | b43_phy_write(dev, B43_NPHY_TABLE_DATAHI, | ||
1214 | ((tmp >> 16) & 0xFFFF)); | ||
1215 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, | ||
1216 | (tmp & 0xFFFF)); | ||
1217 | } | ||
1218 | } | ||
1219 | |||
1220 | if (dev->phy.rev >= 3) { | ||
1221 | b43_shm_write16(dev, B43_SHM_SHARED, | ||
1222 | B43_SHM_SH_NPHY_TXPWR_INDX0, 0xFFFF); | ||
1223 | b43_shm_write16(dev, B43_SHM_SHARED, | ||
1224 | B43_SHM_SH_NPHY_TXPWR_INDX1, 0xFFFF); | ||
1225 | } | ||
1226 | |||
1227 | if (nphy->hang_avoid) | ||
1228 | b43_nphy_stay_in_carrier_search(dev, false); | ||
1229 | } | ||
1230 | |||
1231 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRfSeq */ | ||
1232 | static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd, | ||
1233 | u8 *events, u8 *delays, u8 length) | ||
1234 | { | ||
1235 | struct b43_phy_n *nphy = dev->phy.n; | ||
1236 | u8 i; | ||
1237 | u8 end = (dev->phy.rev >= 3) ? 0x1F : 0x0F; | ||
1238 | u16 offset1 = cmd << 4; | ||
1239 | u16 offset2 = offset1 + 0x80; | ||
366 | 1240 | ||
1241 | if (nphy->hang_avoid) | ||
1242 | b43_nphy_stay_in_carrier_search(dev, true); | ||
1243 | |||
1244 | b43_ntab_write_bulk(dev, B43_NTAB8(7, offset1), length, events); | ||
1245 | b43_ntab_write_bulk(dev, B43_NTAB8(7, offset2), length, delays); | ||
1246 | |||
1247 | for (i = length; i < 16; i++) { | ||
1248 | b43_ntab_write(dev, B43_NTAB8(7, offset1 + i), end); | ||
1249 | b43_ntab_write(dev, B43_NTAB8(7, offset2 + i), 1); | ||
1250 | } | ||
1251 | |||
1252 | if (nphy->hang_avoid) | ||
1253 | b43_nphy_stay_in_carrier_search(dev, false); | ||
1254 | } | ||
1255 | |||
1256 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */ | ||
367 | static void b43_nphy_force_rf_sequence(struct b43_wldev *dev, | 1257 | static void b43_nphy_force_rf_sequence(struct b43_wldev *dev, |
368 | enum b43_nphy_rf_sequence seq) | 1258 | enum b43_nphy_rf_sequence seq) |
369 | { | 1259 | { |
@@ -376,6 +1266,7 @@ static void b43_nphy_force_rf_sequence(struct b43_wldev *dev, | |||
376 | [B43_RFSEQ_UPDATE_GAINU] = B43_NPHY_RFSEQTR_UPGU, | 1266 | [B43_RFSEQ_UPDATE_GAINU] = B43_NPHY_RFSEQTR_UPGU, |
377 | }; | 1267 | }; |
378 | int i; | 1268 | int i; |
1269 | u16 seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE); | ||
379 | 1270 | ||
380 | B43_WARN_ON(seq >= ARRAY_SIZE(trigger)); | 1271 | B43_WARN_ON(seq >= ARRAY_SIZE(trigger)); |
381 | 1272 | ||
@@ -389,8 +1280,181 @@ static void b43_nphy_force_rf_sequence(struct b43_wldev *dev, | |||
389 | } | 1280 | } |
390 | b43err(dev->wl, "RF sequence status timeout\n"); | 1281 | b43err(dev->wl, "RF sequence status timeout\n"); |
391 | ok: | 1282 | ok: |
392 | b43_phy_mask(dev, B43_NPHY_RFSEQMODE, | 1283 | b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode); |
393 | ~(B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER)); | 1284 | } |
1285 | |||
1286 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */ | ||
1287 | static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field, | ||
1288 | u16 value, u8 core, bool off) | ||
1289 | { | ||
1290 | int i; | ||
1291 | u8 index = fls(field); | ||
1292 | u8 addr, en_addr, val_addr; | ||
1293 | /* we expect only one bit set */ | ||
1294 | B43_WARN_ON(field & (~(1 << (index - 1)))); | ||
1295 | |||
1296 | if (dev->phy.rev >= 3) { | ||
1297 | const struct nphy_rf_control_override_rev3 *rf_ctrl; | ||
1298 | for (i = 0; i < 2; i++) { | ||
1299 | if (index == 0 || index == 16) { | ||
1300 | b43err(dev->wl, | ||
1301 | "Unsupported RF Ctrl Override call\n"); | ||
1302 | return; | ||
1303 | } | ||
1304 | |||
1305 | rf_ctrl = &tbl_rf_control_override_rev3[index - 1]; | ||
1306 | en_addr = B43_PHY_N((i == 0) ? | ||
1307 | rf_ctrl->en_addr0 : rf_ctrl->en_addr1); | ||
1308 | val_addr = B43_PHY_N((i == 0) ? | ||
1309 | rf_ctrl->val_addr0 : rf_ctrl->val_addr1); | ||
1310 | |||
1311 | if (off) { | ||
1312 | b43_phy_mask(dev, en_addr, ~(field)); | ||
1313 | b43_phy_mask(dev, val_addr, | ||
1314 | ~(rf_ctrl->val_mask)); | ||
1315 | } else { | ||
1316 | if (core == 0 || ((1 << core) & i) != 0) { | ||
1317 | b43_phy_set(dev, en_addr, field); | ||
1318 | b43_phy_maskset(dev, val_addr, | ||
1319 | ~(rf_ctrl->val_mask), | ||
1320 | (value << rf_ctrl->val_shift)); | ||
1321 | } | ||
1322 | } | ||
1323 | } | ||
1324 | } else { | ||
1325 | const struct nphy_rf_control_override_rev2 *rf_ctrl; | ||
1326 | if (off) { | ||
1327 | b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~(field)); | ||
1328 | value = 0; | ||
1329 | } else { | ||
1330 | b43_phy_set(dev, B43_NPHY_RFCTL_OVER, field); | ||
1331 | } | ||
1332 | |||
1333 | for (i = 0; i < 2; i++) { | ||
1334 | if (index <= 1 || index == 16) { | ||
1335 | b43err(dev->wl, | ||
1336 | "Unsupported RF Ctrl Override call\n"); | ||
1337 | return; | ||
1338 | } | ||
1339 | |||
1340 | if (index == 2 || index == 10 || | ||
1341 | (index >= 13 && index <= 15)) { | ||
1342 | core = 1; | ||
1343 | } | ||
1344 | |||
1345 | rf_ctrl = &tbl_rf_control_override_rev2[index - 2]; | ||
1346 | addr = B43_PHY_N((i == 0) ? | ||
1347 | rf_ctrl->addr0 : rf_ctrl->addr1); | ||
1348 | |||
1349 | if ((core & (1 << i)) != 0) | ||
1350 | b43_phy_maskset(dev, addr, ~(rf_ctrl->bmask), | ||
1351 | (value << rf_ctrl->shift)); | ||
1352 | |||
1353 | b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1); | ||
1354 | b43_phy_set(dev, B43_NPHY_RFCTL_CMD, | ||
1355 | B43_NPHY_RFCTL_CMD_START); | ||
1356 | udelay(1); | ||
1357 | b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, 0xFFFE); | ||
1358 | } | ||
1359 | } | ||
1360 | } | ||
1361 | |||
1362 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlIntcOverride */ | ||
1363 | static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, | ||
1364 | u16 value, u8 core) | ||
1365 | { | ||
1366 | u8 i, j; | ||
1367 | u16 reg, tmp, val; | ||
1368 | |||
1369 | B43_WARN_ON(dev->phy.rev < 3); | ||
1370 | B43_WARN_ON(field > 4); | ||
1371 | |||
1372 | for (i = 0; i < 2; i++) { | ||
1373 | if ((core == 1 && i == 1) || (core == 2 && !i)) | ||
1374 | continue; | ||
1375 | |||
1376 | reg = (i == 0) ? | ||
1377 | B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2; | ||
1378 | b43_phy_mask(dev, reg, 0xFBFF); | ||
1379 | |||
1380 | switch (field) { | ||
1381 | case 0: | ||
1382 | b43_phy_write(dev, reg, 0); | ||
1383 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); | ||
1384 | break; | ||
1385 | case 1: | ||
1386 | if (!i) { | ||
1387 | b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC1, | ||
1388 | 0xFC3F, (value << 6)); | ||
1389 | b43_phy_maskset(dev, B43_NPHY_TXF_40CO_B1S1, | ||
1390 | 0xFFFE, 1); | ||
1391 | b43_phy_set(dev, B43_NPHY_RFCTL_CMD, | ||
1392 | B43_NPHY_RFCTL_CMD_START); | ||
1393 | for (j = 0; j < 100; j++) { | ||
1394 | if (b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_START) { | ||
1395 | j = 0; | ||
1396 | break; | ||
1397 | } | ||
1398 | udelay(10); | ||
1399 | } | ||
1400 | if (j) | ||
1401 | b43err(dev->wl, | ||
1402 | "intc override timeout\n"); | ||
1403 | b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S1, | ||
1404 | 0xFFFE); | ||
1405 | } else { | ||
1406 | b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC2, | ||
1407 | 0xFC3F, (value << 6)); | ||
1408 | b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, | ||
1409 | 0xFFFE, 1); | ||
1410 | b43_phy_set(dev, B43_NPHY_RFCTL_CMD, | ||
1411 | B43_NPHY_RFCTL_CMD_RXTX); | ||
1412 | for (j = 0; j < 100; j++) { | ||
1413 | if (b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_RXTX) { | ||
1414 | j = 0; | ||
1415 | break; | ||
1416 | } | ||
1417 | udelay(10); | ||
1418 | } | ||
1419 | if (j) | ||
1420 | b43err(dev->wl, | ||
1421 | "intc override timeout\n"); | ||
1422 | b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, | ||
1423 | 0xFFFE); | ||
1424 | } | ||
1425 | break; | ||
1426 | case 2: | ||
1427 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { | ||
1428 | tmp = 0x0020; | ||
1429 | val = value << 5; | ||
1430 | } else { | ||
1431 | tmp = 0x0010; | ||
1432 | val = value << 4; | ||
1433 | } | ||
1434 | b43_phy_maskset(dev, reg, ~tmp, val); | ||
1435 | break; | ||
1436 | case 3: | ||
1437 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { | ||
1438 | tmp = 0x0001; | ||
1439 | val = value; | ||
1440 | } else { | ||
1441 | tmp = 0x0004; | ||
1442 | val = value << 2; | ||
1443 | } | ||
1444 | b43_phy_maskset(dev, reg, ~tmp, val); | ||
1445 | break; | ||
1446 | case 4: | ||
1447 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { | ||
1448 | tmp = 0x0002; | ||
1449 | val = value << 1; | ||
1450 | } else { | ||
1451 | tmp = 0x0008; | ||
1452 | val = value << 3; | ||
1453 | } | ||
1454 | b43_phy_maskset(dev, reg, ~tmp, val); | ||
1455 | break; | ||
1456 | } | ||
1457 | } | ||
394 | } | 1458 | } |
395 | 1459 | ||
396 | static void b43_nphy_bphy_init(struct b43_wldev *dev) | 1460 | static void b43_nphy_bphy_init(struct b43_wldev *dev) |
@@ -411,81 +1475,1680 @@ static void b43_nphy_bphy_init(struct b43_wldev *dev) | |||
411 | b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668); | 1475 | b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668); |
412 | } | 1476 | } |
413 | 1477 | ||
414 | /* RSSI Calibration */ | 1478 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */ |
415 | static void b43_nphy_rssi_cal(struct b43_wldev *dev, u8 type) | 1479 | static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale, |
1480 | s8 offset, u8 core, u8 rail, u8 type) | ||
416 | { | 1481 | { |
417 | //TODO | 1482 | u16 tmp; |
1483 | bool core1or5 = (core == 1) || (core == 5); | ||
1484 | bool core2or5 = (core == 2) || (core == 5); | ||
1485 | |||
1486 | offset = clamp_val(offset, -32, 31); | ||
1487 | tmp = ((scale & 0x3F) << 8) | (offset & 0x3F); | ||
1488 | |||
1489 | if (core1or5 && (rail == 0) && (type == 2)) | ||
1490 | b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp); | ||
1491 | if (core1or5 && (rail == 1) && (type == 2)) | ||
1492 | b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp); | ||
1493 | if (core2or5 && (rail == 0) && (type == 2)) | ||
1494 | b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp); | ||
1495 | if (core2or5 && (rail == 1) && (type == 2)) | ||
1496 | b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp); | ||
1497 | if (core1or5 && (rail == 0) && (type == 0)) | ||
1498 | b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp); | ||
1499 | if (core1or5 && (rail == 1) && (type == 0)) | ||
1500 | b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp); | ||
1501 | if (core2or5 && (rail == 0) && (type == 0)) | ||
1502 | b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp); | ||
1503 | if (core2or5 && (rail == 1) && (type == 0)) | ||
1504 | b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp); | ||
1505 | if (core1or5 && (rail == 0) && (type == 1)) | ||
1506 | b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp); | ||
1507 | if (core1or5 && (rail == 1) && (type == 1)) | ||
1508 | b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp); | ||
1509 | if (core2or5 && (rail == 0) && (type == 1)) | ||
1510 | b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp); | ||
1511 | if (core2or5 && (rail == 1) && (type == 1)) | ||
1512 | b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp); | ||
1513 | if (core1or5 && (rail == 0) && (type == 6)) | ||
1514 | b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp); | ||
1515 | if (core1or5 && (rail == 1) && (type == 6)) | ||
1516 | b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp); | ||
1517 | if (core2or5 && (rail == 0) && (type == 6)) | ||
1518 | b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp); | ||
1519 | if (core2or5 && (rail == 1) && (type == 6)) | ||
1520 | b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp); | ||
1521 | if (core1or5 && (rail == 0) && (type == 3)) | ||
1522 | b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp); | ||
1523 | if (core1or5 && (rail == 1) && (type == 3)) | ||
1524 | b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp); | ||
1525 | if (core2or5 && (rail == 0) && (type == 3)) | ||
1526 | b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp); | ||
1527 | if (core2or5 && (rail == 1) && (type == 3)) | ||
1528 | b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp); | ||
1529 | if (core1or5 && (type == 4)) | ||
1530 | b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp); | ||
1531 | if (core2or5 && (type == 4)) | ||
1532 | b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp); | ||
1533 | if (core1or5 && (type == 5)) | ||
1534 | b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp); | ||
1535 | if (core2or5 && (type == 5)) | ||
1536 | b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp); | ||
1537 | } | ||
1538 | |||
1539 | static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type) | ||
1540 | { | ||
1541 | u16 val; | ||
1542 | |||
1543 | if (type < 3) | ||
1544 | val = 0; | ||
1545 | else if (type == 6) | ||
1546 | val = 1; | ||
1547 | else if (type == 3) | ||
1548 | val = 2; | ||
1549 | else | ||
1550 | val = 3; | ||
1551 | |||
1552 | val = (val << 12) | (val << 14); | ||
1553 | b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val); | ||
1554 | b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val); | ||
1555 | |||
1556 | if (type < 3) { | ||
1557 | b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF, | ||
1558 | (type + 1) << 4); | ||
1559 | b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF, | ||
1560 | (type + 1) << 4); | ||
1561 | } | ||
1562 | |||
1563 | /* TODO use some definitions */ | ||
1564 | if (code == 0) { | ||
1565 | b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF, 0); | ||
1566 | if (type < 3) { | ||
1567 | b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFEC7, 0); | ||
1568 | b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xEFDC, 0); | ||
1569 | b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFFFE, 0); | ||
1570 | udelay(20); | ||
1571 | b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xFFFE, 0); | ||
1572 | } | ||
1573 | } else { | ||
1574 | b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF, | ||
1575 | 0x3000); | ||
1576 | if (type < 3) { | ||
1577 | b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, | ||
1578 | 0xFEC7, 0x0180); | ||
1579 | b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, | ||
1580 | 0xEFDC, (code << 1 | 0x1021)); | ||
1581 | b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFFFE, 0x1); | ||
1582 | udelay(20); | ||
1583 | b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xFFFE, 0); | ||
1584 | } | ||
1585 | } | ||
1586 | } | ||
1587 | |||
1588 | static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type) | ||
1589 | { | ||
1590 | struct b43_phy_n *nphy = dev->phy.n; | ||
1591 | u8 i; | ||
1592 | u16 reg, val; | ||
1593 | |||
1594 | if (code == 0) { | ||
1595 | b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, 0xFDFF); | ||
1596 | b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, 0xFDFF); | ||
1597 | b43_phy_mask(dev, B43_NPHY_AFECTL_C1, 0xFCFF); | ||
1598 | b43_phy_mask(dev, B43_NPHY_AFECTL_C2, 0xFCFF); | ||
1599 | b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S0, 0xFFDF); | ||
1600 | b43_phy_mask(dev, B43_NPHY_TXF_40CO_B32S1, 0xFFDF); | ||
1601 | b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0xFFC3); | ||
1602 | b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0xFFC3); | ||
1603 | } else { | ||
1604 | for (i = 0; i < 2; i++) { | ||
1605 | if ((code == 1 && i == 1) || (code == 2 && !i)) | ||
1606 | continue; | ||
1607 | |||
1608 | reg = (i == 0) ? | ||
1609 | B43_NPHY_AFECTL_OVER1 : B43_NPHY_AFECTL_OVER; | ||
1610 | b43_phy_maskset(dev, reg, 0xFDFF, 0x0200); | ||
1611 | |||
1612 | if (type < 3) { | ||
1613 | reg = (i == 0) ? | ||
1614 | B43_NPHY_AFECTL_C1 : | ||
1615 | B43_NPHY_AFECTL_C2; | ||
1616 | b43_phy_maskset(dev, reg, 0xFCFF, 0); | ||
1617 | |||
1618 | reg = (i == 0) ? | ||
1619 | B43_NPHY_RFCTL_LUT_TRSW_UP1 : | ||
1620 | B43_NPHY_RFCTL_LUT_TRSW_UP2; | ||
1621 | b43_phy_maskset(dev, reg, 0xFFC3, 0); | ||
1622 | |||
1623 | if (type == 0) | ||
1624 | val = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? 4 : 8; | ||
1625 | else if (type == 1) | ||
1626 | val = 16; | ||
1627 | else | ||
1628 | val = 32; | ||
1629 | b43_phy_set(dev, reg, val); | ||
1630 | |||
1631 | reg = (i == 0) ? | ||
1632 | B43_NPHY_TXF_40CO_B1S0 : | ||
1633 | B43_NPHY_TXF_40CO_B32S1; | ||
1634 | b43_phy_set(dev, reg, 0x0020); | ||
1635 | } else { | ||
1636 | if (type == 6) | ||
1637 | val = 0x0100; | ||
1638 | else if (type == 3) | ||
1639 | val = 0x0200; | ||
1640 | else | ||
1641 | val = 0x0300; | ||
1642 | |||
1643 | reg = (i == 0) ? | ||
1644 | B43_NPHY_AFECTL_C1 : | ||
1645 | B43_NPHY_AFECTL_C2; | ||
1646 | |||
1647 | b43_phy_maskset(dev, reg, 0xFCFF, val); | ||
1648 | b43_phy_maskset(dev, reg, 0xF3FF, val << 2); | ||
1649 | |||
1650 | if (type != 3 && type != 6) { | ||
1651 | enum ieee80211_band band = | ||
1652 | b43_current_band(dev->wl); | ||
1653 | |||
1654 | if ((nphy->ipa2g_on && | ||
1655 | band == IEEE80211_BAND_2GHZ) || | ||
1656 | (nphy->ipa5g_on && | ||
1657 | band == IEEE80211_BAND_5GHZ)) | ||
1658 | val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE; | ||
1659 | else | ||
1660 | val = 0x11; | ||
1661 | reg = (i == 0) ? 0x2000 : 0x3000; | ||
1662 | reg |= B2055_PADDRV; | ||
1663 | b43_radio_write16(dev, reg, val); | ||
1664 | |||
1665 | reg = (i == 0) ? | ||
1666 | B43_NPHY_AFECTL_OVER1 : | ||
1667 | B43_NPHY_AFECTL_OVER; | ||
1668 | b43_phy_set(dev, reg, 0x0200); | ||
1669 | } | ||
1670 | } | ||
1671 | } | ||
1672 | } | ||
1673 | } | ||
1674 | |||
1675 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */ | ||
1676 | static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type) | ||
1677 | { | ||
1678 | if (dev->phy.rev >= 3) | ||
1679 | b43_nphy_rev3_rssi_select(dev, code, type); | ||
1680 | else | ||
1681 | b43_nphy_rev2_rssi_select(dev, code, type); | ||
1682 | } | ||
1683 | |||
1684 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */ | ||
1685 | static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf) | ||
1686 | { | ||
1687 | int i; | ||
1688 | for (i = 0; i < 2; i++) { | ||
1689 | if (type == 2) { | ||
1690 | if (i == 0) { | ||
1691 | b43_radio_maskset(dev, B2055_C1_B0NB_RSSIVCM, | ||
1692 | 0xFC, buf[0]); | ||
1693 | b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5, | ||
1694 | 0xFC, buf[1]); | ||
1695 | } else { | ||
1696 | b43_radio_maskset(dev, B2055_C2_B0NB_RSSIVCM, | ||
1697 | 0xFC, buf[2 * i]); | ||
1698 | b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5, | ||
1699 | 0xFC, buf[2 * i + 1]); | ||
1700 | } | ||
1701 | } else { | ||
1702 | if (i == 0) | ||
1703 | b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5, | ||
1704 | 0xF3, buf[0] << 2); | ||
1705 | else | ||
1706 | b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5, | ||
1707 | 0xF3, buf[2 * i + 1] << 2); | ||
1708 | } | ||
1709 | } | ||
1710 | } | ||
1711 | |||
1712 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */ | ||
1713 | static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, | ||
1714 | u8 nsamp) | ||
1715 | { | ||
1716 | int i; | ||
1717 | int out; | ||
1718 | u16 save_regs_phy[9]; | ||
1719 | u16 s[2]; | ||
1720 | |||
1721 | if (dev->phy.rev >= 3) { | ||
1722 | save_regs_phy[0] = b43_phy_read(dev, | ||
1723 | B43_NPHY_RFCTL_LUT_TRSW_UP1); | ||
1724 | save_regs_phy[1] = b43_phy_read(dev, | ||
1725 | B43_NPHY_RFCTL_LUT_TRSW_UP2); | ||
1726 | save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); | ||
1727 | save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); | ||
1728 | save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1); | ||
1729 | save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); | ||
1730 | save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0); | ||
1731 | save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1); | ||
1732 | } | ||
1733 | |||
1734 | b43_nphy_rssi_select(dev, 5, type); | ||
1735 | |||
1736 | if (dev->phy.rev < 2) { | ||
1737 | save_regs_phy[8] = b43_phy_read(dev, B43_NPHY_GPIO_SEL); | ||
1738 | b43_phy_write(dev, B43_NPHY_GPIO_SEL, 5); | ||
1739 | } | ||
1740 | |||
1741 | for (i = 0; i < 4; i++) | ||
1742 | buf[i] = 0; | ||
1743 | |||
1744 | for (i = 0; i < nsamp; i++) { | ||
1745 | if (dev->phy.rev < 2) { | ||
1746 | s[0] = b43_phy_read(dev, B43_NPHY_GPIO_LOOUT); | ||
1747 | s[1] = b43_phy_read(dev, B43_NPHY_GPIO_HIOUT); | ||
1748 | } else { | ||
1749 | s[0] = b43_phy_read(dev, B43_NPHY_RSSI1); | ||
1750 | s[1] = b43_phy_read(dev, B43_NPHY_RSSI2); | ||
1751 | } | ||
1752 | |||
1753 | buf[0] += ((s8)((s[0] & 0x3F) << 2)) >> 2; | ||
1754 | buf[1] += ((s8)(((s[0] >> 8) & 0x3F) << 2)) >> 2; | ||
1755 | buf[2] += ((s8)((s[1] & 0x3F) << 2)) >> 2; | ||
1756 | buf[3] += ((s8)(((s[1] >> 8) & 0x3F) << 2)) >> 2; | ||
1757 | } | ||
1758 | out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 | | ||
1759 | (buf[2] & 0xFF) << 8 | (buf[3] & 0xFF); | ||
1760 | |||
1761 | if (dev->phy.rev < 2) | ||
1762 | b43_phy_write(dev, B43_NPHY_GPIO_SEL, save_regs_phy[8]); | ||
1763 | |||
1764 | if (dev->phy.rev >= 3) { | ||
1765 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, | ||
1766 | save_regs_phy[0]); | ||
1767 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, | ||
1768 | save_regs_phy[1]); | ||
1769 | b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[2]); | ||
1770 | b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[3]); | ||
1771 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, save_regs_phy[4]); | ||
1772 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]); | ||
1773 | b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]); | ||
1774 | b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]); | ||
1775 | } | ||
1776 | |||
1777 | return out; | ||
1778 | } | ||
1779 | |||
1780 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */ | ||
1781 | static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) | ||
1782 | { | ||
1783 | int i, j; | ||
1784 | u8 state[4]; | ||
1785 | u8 code, val; | ||
1786 | u16 class, override; | ||
1787 | u8 regs_save_radio[2]; | ||
1788 | u16 regs_save_phy[2]; | ||
1789 | s8 offset[4]; | ||
1790 | |||
1791 | u16 clip_state[2]; | ||
1792 | u16 clip_off[2] = { 0xFFFF, 0xFFFF }; | ||
1793 | s32 results_min[4] = { }; | ||
1794 | u8 vcm_final[4] = { }; | ||
1795 | s32 results[4][4] = { }; | ||
1796 | s32 miniq[4][2] = { }; | ||
1797 | |||
1798 | if (type == 2) { | ||
1799 | code = 0; | ||
1800 | val = 6; | ||
1801 | } else if (type < 2) { | ||
1802 | code = 25; | ||
1803 | val = 4; | ||
1804 | } else { | ||
1805 | B43_WARN_ON(1); | ||
1806 | return; | ||
1807 | } | ||
1808 | |||
1809 | class = b43_nphy_classifier(dev, 0, 0); | ||
1810 | b43_nphy_classifier(dev, 7, 4); | ||
1811 | b43_nphy_read_clip_detection(dev, clip_state); | ||
1812 | b43_nphy_write_clip_detection(dev, clip_off); | ||
1813 | |||
1814 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) | ||
1815 | override = 0x140; | ||
1816 | else | ||
1817 | override = 0x110; | ||
1818 | |||
1819 | regs_save_phy[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); | ||
1820 | regs_save_radio[0] = b43_radio_read16(dev, B2055_C1_PD_RXTX); | ||
1821 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, override); | ||
1822 | b43_radio_write16(dev, B2055_C1_PD_RXTX, val); | ||
1823 | |||
1824 | regs_save_phy[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); | ||
1825 | regs_save_radio[1] = b43_radio_read16(dev, B2055_C2_PD_RXTX); | ||
1826 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, override); | ||
1827 | b43_radio_write16(dev, B2055_C2_PD_RXTX, val); | ||
1828 | |||
1829 | state[0] = b43_radio_read16(dev, B2055_C1_PD_RSSIMISC) & 0x07; | ||
1830 | state[1] = b43_radio_read16(dev, B2055_C2_PD_RSSIMISC) & 0x07; | ||
1831 | b43_radio_mask(dev, B2055_C1_PD_RSSIMISC, 0xF8); | ||
1832 | b43_radio_mask(dev, B2055_C2_PD_RSSIMISC, 0xF8); | ||
1833 | state[2] = b43_radio_read16(dev, B2055_C1_SP_RSSI) & 0x07; | ||
1834 | state[3] = b43_radio_read16(dev, B2055_C2_SP_RSSI) & 0x07; | ||
1835 | |||
1836 | b43_nphy_rssi_select(dev, 5, type); | ||
1837 | b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 0, type); | ||
1838 | b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 1, type); | ||
1839 | |||
1840 | for (i = 0; i < 4; i++) { | ||
1841 | u8 tmp[4]; | ||
1842 | for (j = 0; j < 4; j++) | ||
1843 | tmp[j] = i; | ||
1844 | if (type != 1) | ||
1845 | b43_nphy_set_rssi_2055_vcm(dev, type, tmp); | ||
1846 | b43_nphy_poll_rssi(dev, type, results[i], 8); | ||
1847 | if (type < 2) | ||
1848 | for (j = 0; j < 2; j++) | ||
1849 | miniq[i][j] = min(results[i][2 * j], | ||
1850 | results[i][2 * j + 1]); | ||
1851 | } | ||
1852 | |||
1853 | for (i = 0; i < 4; i++) { | ||
1854 | s32 mind = 40; | ||
1855 | u8 minvcm = 0; | ||
1856 | s32 minpoll = 249; | ||
1857 | s32 curr; | ||
1858 | for (j = 0; j < 4; j++) { | ||
1859 | if (type == 2) | ||
1860 | curr = abs(results[j][i]); | ||
1861 | else | ||
1862 | curr = abs(miniq[j][i / 2] - code * 8); | ||
1863 | |||
1864 | if (curr < mind) { | ||
1865 | mind = curr; | ||
1866 | minvcm = j; | ||
1867 | } | ||
1868 | |||
1869 | if (results[j][i] < minpoll) | ||
1870 | minpoll = results[j][i]; | ||
1871 | } | ||
1872 | results_min[i] = minpoll; | ||
1873 | vcm_final[i] = minvcm; | ||
1874 | } | ||
1875 | |||
1876 | if (type != 1) | ||
1877 | b43_nphy_set_rssi_2055_vcm(dev, type, vcm_final); | ||
1878 | |||
1879 | for (i = 0; i < 4; i++) { | ||
1880 | offset[i] = (code * 8) - results[vcm_final[i]][i]; | ||
1881 | |||
1882 | if (offset[i] < 0) | ||
1883 | offset[i] = -((abs(offset[i]) + 4) / 8); | ||
1884 | else | ||
1885 | offset[i] = (offset[i] + 4) / 8; | ||
1886 | |||
1887 | if (results_min[i] == 248) | ||
1888 | offset[i] = code - 32; | ||
1889 | |||
1890 | if (i % 2 == 0) | ||
1891 | b43_nphy_scale_offset_rssi(dev, 0, offset[i], 1, 0, | ||
1892 | type); | ||
1893 | else | ||
1894 | b43_nphy_scale_offset_rssi(dev, 0, offset[i], 2, 1, | ||
1895 | type); | ||
1896 | } | ||
1897 | |||
1898 | b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[0]); | ||
1899 | b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[1]); | ||
1900 | |||
1901 | switch (state[2]) { | ||
1902 | case 1: | ||
1903 | b43_nphy_rssi_select(dev, 1, 2); | ||
1904 | break; | ||
1905 | case 4: | ||
1906 | b43_nphy_rssi_select(dev, 1, 0); | ||
1907 | break; | ||
1908 | case 2: | ||
1909 | b43_nphy_rssi_select(dev, 1, 1); | ||
1910 | break; | ||
1911 | default: | ||
1912 | b43_nphy_rssi_select(dev, 1, 1); | ||
1913 | break; | ||
1914 | } | ||
1915 | |||
1916 | switch (state[3]) { | ||
1917 | case 1: | ||
1918 | b43_nphy_rssi_select(dev, 2, 2); | ||
1919 | break; | ||
1920 | case 4: | ||
1921 | b43_nphy_rssi_select(dev, 2, 0); | ||
1922 | break; | ||
1923 | default: | ||
1924 | b43_nphy_rssi_select(dev, 2, 1); | ||
1925 | break; | ||
1926 | } | ||
1927 | |||
1928 | b43_nphy_rssi_select(dev, 0, type); | ||
1929 | |||
1930 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs_save_phy[0]); | ||
1931 | b43_radio_write16(dev, B2055_C1_PD_RXTX, regs_save_radio[0]); | ||
1932 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs_save_phy[1]); | ||
1933 | b43_radio_write16(dev, B2055_C2_PD_RXTX, regs_save_radio[1]); | ||
1934 | |||
1935 | b43_nphy_classifier(dev, 7, class); | ||
1936 | b43_nphy_write_clip_detection(dev, clip_state); | ||
1937 | } | ||
1938 | |||
1939 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */ | ||
1940 | static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) | ||
1941 | { | ||
1942 | /* TODO */ | ||
1943 | } | ||
1944 | |||
1945 | /* | ||
1946 | * RSSI Calibration | ||
1947 | * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal | ||
1948 | */ | ||
1949 | static void b43_nphy_rssi_cal(struct b43_wldev *dev) | ||
1950 | { | ||
1951 | if (dev->phy.rev >= 3) { | ||
1952 | b43_nphy_rev3_rssi_cal(dev); | ||
1953 | } else { | ||
1954 | b43_nphy_rev2_rssi_cal(dev, 2); | ||
1955 | b43_nphy_rev2_rssi_cal(dev, 0); | ||
1956 | b43_nphy_rev2_rssi_cal(dev, 1); | ||
1957 | } | ||
418 | } | 1958 | } |
419 | 1959 | ||
1960 | /* | ||
1961 | * Restore RSSI Calibration | ||
1962 | * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal | ||
1963 | */ | ||
1964 | static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev) | ||
1965 | { | ||
1966 | struct b43_phy_n *nphy = dev->phy.n; | ||
1967 | |||
1968 | u16 *rssical_radio_regs = NULL; | ||
1969 | u16 *rssical_phy_regs = NULL; | ||
1970 | |||
1971 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||
1972 | if (!nphy->rssical_chanspec_2G) | ||
1973 | return; | ||
1974 | rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; | ||
1975 | rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G; | ||
1976 | } else { | ||
1977 | if (!nphy->rssical_chanspec_5G) | ||
1978 | return; | ||
1979 | rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G; | ||
1980 | rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; | ||
1981 | } | ||
1982 | |||
1983 | /* TODO use some definitions */ | ||
1984 | b43_radio_maskset(dev, 0x602B, 0xE3, rssical_radio_regs[0]); | ||
1985 | b43_radio_maskset(dev, 0x702B, 0xE3, rssical_radio_regs[1]); | ||
1986 | |||
1987 | b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, rssical_phy_regs[0]); | ||
1988 | b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, rssical_phy_regs[1]); | ||
1989 | b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, rssical_phy_regs[2]); | ||
1990 | b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, rssical_phy_regs[3]); | ||
1991 | |||
1992 | b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, rssical_phy_regs[4]); | ||
1993 | b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, rssical_phy_regs[5]); | ||
1994 | b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, rssical_phy_regs[6]); | ||
1995 | b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, rssical_phy_regs[7]); | ||
1996 | |||
1997 | b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, rssical_phy_regs[8]); | ||
1998 | b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, rssical_phy_regs[9]); | ||
1999 | b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, rssical_phy_regs[10]); | ||
2000 | b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]); | ||
2001 | } | ||
2002 | |||
2003 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetIpaGainTbl */ | ||
2004 | static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev) | ||
2005 | { | ||
2006 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||
2007 | if (dev->phy.rev >= 6) { | ||
2008 | /* TODO If the chip is 47162 | ||
2009 | return txpwrctrl_tx_gain_ipa_rev5 */ | ||
2010 | return txpwrctrl_tx_gain_ipa_rev6; | ||
2011 | } else if (dev->phy.rev >= 5) { | ||
2012 | return txpwrctrl_tx_gain_ipa_rev5; | ||
2013 | } else { | ||
2014 | return txpwrctrl_tx_gain_ipa; | ||
2015 | } | ||
2016 | } else { | ||
2017 | return txpwrctrl_tx_gain_ipa_5g; | ||
2018 | } | ||
2019 | } | ||
2020 | |||
2021 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */ | ||
2022 | static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev) | ||
2023 | { | ||
2024 | struct b43_phy_n *nphy = dev->phy.n; | ||
2025 | u16 *save = nphy->tx_rx_cal_radio_saveregs; | ||
2026 | u16 tmp; | ||
2027 | u8 offset, i; | ||
2028 | |||
2029 | if (dev->phy.rev >= 3) { | ||
2030 | for (i = 0; i < 2; i++) { | ||
2031 | tmp = (i == 0) ? 0x2000 : 0x3000; | ||
2032 | offset = i * 11; | ||
2033 | |||
2034 | save[offset + 0] = b43_radio_read16(dev, B2055_CAL_RVARCTL); | ||
2035 | save[offset + 1] = b43_radio_read16(dev, B2055_CAL_LPOCTL); | ||
2036 | save[offset + 2] = b43_radio_read16(dev, B2055_CAL_TS); | ||
2037 | save[offset + 3] = b43_radio_read16(dev, B2055_CAL_RCCALRTS); | ||
2038 | save[offset + 4] = b43_radio_read16(dev, B2055_CAL_RCALRTS); | ||
2039 | save[offset + 5] = b43_radio_read16(dev, B2055_PADDRV); | ||
2040 | save[offset + 6] = b43_radio_read16(dev, B2055_XOCTL1); | ||
2041 | save[offset + 7] = b43_radio_read16(dev, B2055_XOCTL2); | ||
2042 | save[offset + 8] = b43_radio_read16(dev, B2055_XOREGUL); | ||
2043 | save[offset + 9] = b43_radio_read16(dev, B2055_XOMISC); | ||
2044 | save[offset + 10] = b43_radio_read16(dev, B2055_PLL_LFC1); | ||
2045 | |||
2046 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { | ||
2047 | b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x0A); | ||
2048 | b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40); | ||
2049 | b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55); | ||
2050 | b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0); | ||
2051 | b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0); | ||
2052 | if (nphy->ipa5g_on) { | ||
2053 | b43_radio_write16(dev, tmp | B2055_PADDRV, 4); | ||
2054 | b43_radio_write16(dev, tmp | B2055_XOCTL1, 1); | ||
2055 | } else { | ||
2056 | b43_radio_write16(dev, tmp | B2055_PADDRV, 0); | ||
2057 | b43_radio_write16(dev, tmp | B2055_XOCTL1, 0x2F); | ||
2058 | } | ||
2059 | b43_radio_write16(dev, tmp | B2055_XOCTL2, 0); | ||
2060 | } else { | ||
2061 | b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x06); | ||
2062 | b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40); | ||
2063 | b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55); | ||
2064 | b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0); | ||
2065 | b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0); | ||
2066 | b43_radio_write16(dev, tmp | B2055_XOCTL1, 0); | ||
2067 | if (nphy->ipa2g_on) { | ||
2068 | b43_radio_write16(dev, tmp | B2055_PADDRV, 6); | ||
2069 | b43_radio_write16(dev, tmp | B2055_XOCTL2, | ||
2070 | (dev->phy.rev < 5) ? 0x11 : 0x01); | ||
2071 | } else { | ||
2072 | b43_radio_write16(dev, tmp | B2055_PADDRV, 0); | ||
2073 | b43_radio_write16(dev, tmp | B2055_XOCTL2, 0); | ||
2074 | } | ||
2075 | } | ||
2076 | b43_radio_write16(dev, tmp | B2055_XOREGUL, 0); | ||
2077 | b43_radio_write16(dev, tmp | B2055_XOMISC, 0); | ||
2078 | b43_radio_write16(dev, tmp | B2055_PLL_LFC1, 0); | ||
2079 | } | ||
2080 | } else { | ||
2081 | save[0] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL1); | ||
2082 | b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL1, 0x29); | ||
2083 | |||
2084 | save[1] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL2); | ||
2085 | b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL2, 0x54); | ||
2086 | |||
2087 | save[2] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL1); | ||
2088 | b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL1, 0x29); | ||
2089 | |||
2090 | save[3] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL2); | ||
2091 | b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL2, 0x54); | ||
2092 | |||
2093 | save[3] = b43_radio_read16(dev, B2055_C1_PWRDET_RXTX); | ||
2094 | save[4] = b43_radio_read16(dev, B2055_C2_PWRDET_RXTX); | ||
2095 | |||
2096 | if (!(b43_phy_read(dev, B43_NPHY_BANDCTL) & | ||
2097 | B43_NPHY_BANDCTL_5GHZ)) { | ||
2098 | b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x04); | ||
2099 | b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x04); | ||
2100 | } else { | ||
2101 | b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x20); | ||
2102 | b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x20); | ||
2103 | } | ||
2104 | |||
2105 | if (dev->phy.rev < 2) { | ||
2106 | b43_radio_set(dev, B2055_C1_TX_BB_MXGM, 0x20); | ||
2107 | b43_radio_set(dev, B2055_C2_TX_BB_MXGM, 0x20); | ||
2108 | } else { | ||
2109 | b43_radio_mask(dev, B2055_C1_TX_BB_MXGM, ~0x20); | ||
2110 | b43_radio_mask(dev, B2055_C2_TX_BB_MXGM, ~0x20); | ||
2111 | } | ||
2112 | } | ||
2113 | } | ||
2114 | |||
2115 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */ | ||
2116 | static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core, | ||
2117 | struct nphy_txgains target, | ||
2118 | struct nphy_iqcal_params *params) | ||
2119 | { | ||
2120 | int i, j, indx; | ||
2121 | u16 gain; | ||
2122 | |||
2123 | if (dev->phy.rev >= 3) { | ||
2124 | params->txgm = target.txgm[core]; | ||
2125 | params->pga = target.pga[core]; | ||
2126 | params->pad = target.pad[core]; | ||
2127 | params->ipa = target.ipa[core]; | ||
2128 | params->cal_gain = (params->txgm << 12) | (params->pga << 8) | | ||
2129 | (params->pad << 4) | (params->ipa); | ||
2130 | for (j = 0; j < 5; j++) | ||
2131 | params->ncorr[j] = 0x79; | ||
2132 | } else { | ||
2133 | gain = (target.pad[core]) | (target.pga[core] << 4) | | ||
2134 | (target.txgm[core] << 8); | ||
2135 | |||
2136 | indx = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? | ||
2137 | 1 : 0; | ||
2138 | for (i = 0; i < 9; i++) | ||
2139 | if (tbl_iqcal_gainparams[indx][i][0] == gain) | ||
2140 | break; | ||
2141 | i = min(i, 8); | ||
2142 | |||
2143 | params->txgm = tbl_iqcal_gainparams[indx][i][1]; | ||
2144 | params->pga = tbl_iqcal_gainparams[indx][i][2]; | ||
2145 | params->pad = tbl_iqcal_gainparams[indx][i][3]; | ||
2146 | params->cal_gain = (params->txgm << 7) | (params->pga << 4) | | ||
2147 | (params->pad << 2); | ||
2148 | for (j = 0; j < 4; j++) | ||
2149 | params->ncorr[j] = tbl_iqcal_gainparams[indx][i][4 + j]; | ||
2150 | } | ||
2151 | } | ||
2152 | |||
2153 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */ | ||
2154 | static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core) | ||
2155 | { | ||
2156 | struct b43_phy_n *nphy = dev->phy.n; | ||
2157 | int i; | ||
2158 | u16 scale, entry; | ||
2159 | |||
2160 | u16 tmp = nphy->txcal_bbmult; | ||
2161 | if (core == 0) | ||
2162 | tmp >>= 8; | ||
2163 | tmp &= 0xff; | ||
2164 | |||
2165 | for (i = 0; i < 18; i++) { | ||
2166 | scale = (ladder_lo[i].percent * tmp) / 100; | ||
2167 | entry = ((scale & 0xFF) << 8) | ladder_lo[i].g_env; | ||
2168 | b43_ntab_write(dev, B43_NTAB16(15, i), entry); | ||
2169 | |||
2170 | scale = (ladder_iq[i].percent * tmp) / 100; | ||
2171 | entry = ((scale & 0xFF) << 8) | ladder_iq[i].g_env; | ||
2172 | b43_ntab_write(dev, B43_NTAB16(15, i + 32), entry); | ||
2173 | } | ||
2174 | } | ||
2175 | |||
2176 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */ | ||
2177 | static void b43_nphy_ext_pa_set_tx_dig_filters(struct b43_wldev *dev) | ||
2178 | { | ||
2179 | int i; | ||
2180 | for (i = 0; i < 15; i++) | ||
2181 | b43_phy_write(dev, B43_PHY_N(0x2C5 + i), | ||
2182 | tbl_tx_filter_coef_rev4[2][i]); | ||
2183 | } | ||
2184 | |||
2185 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */ | ||
2186 | static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev) | ||
2187 | { | ||
2188 | int i, j; | ||
2189 | /* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */ | ||
2190 | u16 offset[] = { 0x186, 0x195, 0x2C5 }; | ||
2191 | |||
2192 | for (i = 0; i < 3; i++) | ||
2193 | for (j = 0; j < 15; j++) | ||
2194 | b43_phy_write(dev, B43_PHY_N(offset[i] + j), | ||
2195 | tbl_tx_filter_coef_rev4[i][j]); | ||
2196 | |||
2197 | if (dev->phy.is_40mhz) { | ||
2198 | for (j = 0; j < 15; j++) | ||
2199 | b43_phy_write(dev, B43_PHY_N(offset[0] + j), | ||
2200 | tbl_tx_filter_coef_rev4[3][j]); | ||
2201 | } else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { | ||
2202 | for (j = 0; j < 15; j++) | ||
2203 | b43_phy_write(dev, B43_PHY_N(offset[0] + j), | ||
2204 | tbl_tx_filter_coef_rev4[5][j]); | ||
2205 | } | ||
2206 | |||
2207 | if (dev->phy.channel == 14) | ||
2208 | for (j = 0; j < 15; j++) | ||
2209 | b43_phy_write(dev, B43_PHY_N(offset[0] + j), | ||
2210 | tbl_tx_filter_coef_rev4[6][j]); | ||
2211 | } | ||
2212 | |||
2213 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */ | ||
2214 | static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev) | ||
2215 | { | ||
2216 | struct b43_phy_n *nphy = dev->phy.n; | ||
2217 | |||
2218 | u16 curr_gain[2]; | ||
2219 | struct nphy_txgains target; | ||
2220 | const u32 *table = NULL; | ||
2221 | |||
2222 | if (nphy->txpwrctrl == 0) { | ||
2223 | int i; | ||
2224 | |||
2225 | if (nphy->hang_avoid) | ||
2226 | b43_nphy_stay_in_carrier_search(dev, true); | ||
2227 | b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, curr_gain); | ||
2228 | if (nphy->hang_avoid) | ||
2229 | b43_nphy_stay_in_carrier_search(dev, false); | ||
2230 | |||
2231 | for (i = 0; i < 2; ++i) { | ||
2232 | if (dev->phy.rev >= 3) { | ||
2233 | target.ipa[i] = curr_gain[i] & 0x000F; | ||
2234 | target.pad[i] = (curr_gain[i] & 0x00F0) >> 4; | ||
2235 | target.pga[i] = (curr_gain[i] & 0x0F00) >> 8; | ||
2236 | target.txgm[i] = (curr_gain[i] & 0x7000) >> 12; | ||
2237 | } else { | ||
2238 | target.ipa[i] = curr_gain[i] & 0x0003; | ||
2239 | target.pad[i] = (curr_gain[i] & 0x000C) >> 2; | ||
2240 | target.pga[i] = (curr_gain[i] & 0x0070) >> 4; | ||
2241 | target.txgm[i] = (curr_gain[i] & 0x0380) >> 7; | ||
2242 | } | ||
2243 | } | ||
2244 | } else { | ||
2245 | int i; | ||
2246 | u16 index[2]; | ||
2247 | index[0] = (b43_phy_read(dev, B43_NPHY_C1_TXPCTL_STAT) & | ||
2248 | B43_NPHY_TXPCTL_STAT_BIDX) >> | ||
2249 | B43_NPHY_TXPCTL_STAT_BIDX_SHIFT; | ||
2250 | index[1] = (b43_phy_read(dev, B43_NPHY_C2_TXPCTL_STAT) & | ||
2251 | B43_NPHY_TXPCTL_STAT_BIDX) >> | ||
2252 | B43_NPHY_TXPCTL_STAT_BIDX_SHIFT; | ||
2253 | |||
2254 | for (i = 0; i < 2; ++i) { | ||
2255 | if (dev->phy.rev >= 3) { | ||
2256 | enum ieee80211_band band = | ||
2257 | b43_current_band(dev->wl); | ||
2258 | |||
2259 | if ((nphy->ipa2g_on && | ||
2260 | band == IEEE80211_BAND_2GHZ) || | ||
2261 | (nphy->ipa5g_on && | ||
2262 | band == IEEE80211_BAND_5GHZ)) { | ||
2263 | table = b43_nphy_get_ipa_gain_table(dev); | ||
2264 | } else { | ||
2265 | if (band == IEEE80211_BAND_5GHZ) { | ||
2266 | if (dev->phy.rev == 3) | ||
2267 | table = b43_ntab_tx_gain_rev3_5ghz; | ||
2268 | else if (dev->phy.rev == 4) | ||
2269 | table = b43_ntab_tx_gain_rev4_5ghz; | ||
2270 | else | ||
2271 | table = b43_ntab_tx_gain_rev5plus_5ghz; | ||
2272 | } else { | ||
2273 | table = b43_ntab_tx_gain_rev3plus_2ghz; | ||
2274 | } | ||
2275 | } | ||
2276 | |||
2277 | target.ipa[i] = (table[index[i]] >> 16) & 0xF; | ||
2278 | target.pad[i] = (table[index[i]] >> 20) & 0xF; | ||
2279 | target.pga[i] = (table[index[i]] >> 24) & 0xF; | ||
2280 | target.txgm[i] = (table[index[i]] >> 28) & 0xF; | ||
2281 | } else { | ||
2282 | table = b43_ntab_tx_gain_rev0_1_2; | ||
2283 | |||
2284 | target.ipa[i] = (table[index[i]] >> 16) & 0x3; | ||
2285 | target.pad[i] = (table[index[i]] >> 18) & 0x3; | ||
2286 | target.pga[i] = (table[index[i]] >> 20) & 0x7; | ||
2287 | target.txgm[i] = (table[index[i]] >> 23) & 0x7; | ||
2288 | } | ||
2289 | } | ||
2290 | } | ||
2291 | |||
2292 | return target; | ||
2293 | } | ||
2294 | |||
2295 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhyCleanup */ | ||
2296 | static void b43_nphy_tx_cal_phy_cleanup(struct b43_wldev *dev) | ||
2297 | { | ||
2298 | u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs; | ||
2299 | |||
2300 | if (dev->phy.rev >= 3) { | ||
2301 | b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[0]); | ||
2302 | b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]); | ||
2303 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]); | ||
2304 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[3]); | ||
2305 | b43_phy_write(dev, B43_NPHY_BBCFG, regs[4]); | ||
2306 | b43_ntab_write(dev, B43_NTAB16(8, 3), regs[5]); | ||
2307 | b43_ntab_write(dev, B43_NTAB16(8, 19), regs[6]); | ||
2308 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[7]); | ||
2309 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[8]); | ||
2310 | b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]); | ||
2311 | b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]); | ||
2312 | b43_nphy_reset_cca(dev); | ||
2313 | } else { | ||
2314 | b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, regs[0]); | ||
2315 | b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, regs[1]); | ||
2316 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]); | ||
2317 | b43_ntab_write(dev, B43_NTAB16(8, 2), regs[3]); | ||
2318 | b43_ntab_write(dev, B43_NTAB16(8, 18), regs[4]); | ||
2319 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[5]); | ||
2320 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[6]); | ||
2321 | } | ||
2322 | } | ||
2323 | |||
2324 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */ | ||
2325 | static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev) | ||
2326 | { | ||
2327 | u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs; | ||
2328 | u16 tmp; | ||
2329 | |||
2330 | regs[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); | ||
2331 | regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); | ||
2332 | if (dev->phy.rev >= 3) { | ||
2333 | b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0xF0FF, 0x0A00); | ||
2334 | b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0xF0FF, 0x0A00); | ||
2335 | |||
2336 | tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1); | ||
2337 | regs[2] = tmp; | ||
2338 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, tmp | 0x0600); | ||
2339 | |||
2340 | tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); | ||
2341 | regs[3] = tmp; | ||
2342 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x0600); | ||
2343 | |||
2344 | regs[4] = b43_phy_read(dev, B43_NPHY_BBCFG); | ||
2345 | b43_phy_mask(dev, B43_NPHY_BBCFG, (u16)~B43_NPHY_BBCFG_RSTRX); | ||
2346 | |||
2347 | tmp = b43_ntab_read(dev, B43_NTAB16(8, 3)); | ||
2348 | regs[5] = tmp; | ||
2349 | b43_ntab_write(dev, B43_NTAB16(8, 3), 0); | ||
2350 | |||
2351 | tmp = b43_ntab_read(dev, B43_NTAB16(8, 19)); | ||
2352 | regs[6] = tmp; | ||
2353 | b43_ntab_write(dev, B43_NTAB16(8, 19), 0); | ||
2354 | regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); | ||
2355 | regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); | ||
2356 | |||
2357 | b43_nphy_rf_control_intc_override(dev, 2, 1, 3); | ||
2358 | b43_nphy_rf_control_intc_override(dev, 1, 2, 1); | ||
2359 | b43_nphy_rf_control_intc_override(dev, 1, 8, 2); | ||
2360 | |||
2361 | regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0); | ||
2362 | regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1); | ||
2363 | b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001); | ||
2364 | b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001); | ||
2365 | } else { | ||
2366 | b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, 0xA000); | ||
2367 | b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, 0xA000); | ||
2368 | tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); | ||
2369 | regs[2] = tmp; | ||
2370 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x3000); | ||
2371 | tmp = b43_ntab_read(dev, B43_NTAB16(8, 2)); | ||
2372 | regs[3] = tmp; | ||
2373 | tmp |= 0x2000; | ||
2374 | b43_ntab_write(dev, B43_NTAB16(8, 2), tmp); | ||
2375 | tmp = b43_ntab_read(dev, B43_NTAB16(8, 18)); | ||
2376 | regs[4] = tmp; | ||
2377 | tmp |= 0x2000; | ||
2378 | b43_ntab_write(dev, B43_NTAB16(8, 18), tmp); | ||
2379 | regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); | ||
2380 | regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); | ||
2381 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) | ||
2382 | tmp = 0x0180; | ||
2383 | else | ||
2384 | tmp = 0x0120; | ||
2385 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp); | ||
2386 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp); | ||
2387 | } | ||
2388 | } | ||
2389 | |||
2390 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */ | ||
2391 | static void b43_nphy_save_cal(struct b43_wldev *dev) | ||
2392 | { | ||
2393 | struct b43_phy_n *nphy = dev->phy.n; | ||
2394 | |||
2395 | struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; | ||
2396 | u16 *txcal_radio_regs = NULL; | ||
2397 | u8 *iqcal_chanspec; | ||
2398 | u16 *table = NULL; | ||
2399 | |||
2400 | if (nphy->hang_avoid) | ||
2401 | b43_nphy_stay_in_carrier_search(dev, 1); | ||
2402 | |||
2403 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||
2404 | rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G; | ||
2405 | txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G; | ||
2406 | iqcal_chanspec = &nphy->iqcal_chanspec_2G; | ||
2407 | table = nphy->cal_cache.txcal_coeffs_2G; | ||
2408 | } else { | ||
2409 | rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G; | ||
2410 | txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G; | ||
2411 | iqcal_chanspec = &nphy->iqcal_chanspec_5G; | ||
2412 | table = nphy->cal_cache.txcal_coeffs_5G; | ||
2413 | } | ||
2414 | |||
2415 | b43_nphy_rx_iq_coeffs(dev, false, rxcal_coeffs); | ||
2416 | /* TODO use some definitions */ | ||
2417 | if (dev->phy.rev >= 3) { | ||
2418 | txcal_radio_regs[0] = b43_radio_read(dev, 0x2021); | ||
2419 | txcal_radio_regs[1] = b43_radio_read(dev, 0x2022); | ||
2420 | txcal_radio_regs[2] = b43_radio_read(dev, 0x3021); | ||
2421 | txcal_radio_regs[3] = b43_radio_read(dev, 0x3022); | ||
2422 | txcal_radio_regs[4] = b43_radio_read(dev, 0x2023); | ||
2423 | txcal_radio_regs[5] = b43_radio_read(dev, 0x2024); | ||
2424 | txcal_radio_regs[6] = b43_radio_read(dev, 0x3023); | ||
2425 | txcal_radio_regs[7] = b43_radio_read(dev, 0x3024); | ||
2426 | } else { | ||
2427 | txcal_radio_regs[0] = b43_radio_read(dev, 0x8B); | ||
2428 | txcal_radio_regs[1] = b43_radio_read(dev, 0xBA); | ||
2429 | txcal_radio_regs[2] = b43_radio_read(dev, 0x8D); | ||
2430 | txcal_radio_regs[3] = b43_radio_read(dev, 0xBC); | ||
2431 | } | ||
2432 | *iqcal_chanspec = nphy->radio_chanspec; | ||
2433 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 8, table); | ||
2434 | |||
2435 | if (nphy->hang_avoid) | ||
2436 | b43_nphy_stay_in_carrier_search(dev, 0); | ||
2437 | } | ||
2438 | |||
2439 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */ | ||
2440 | static void b43_nphy_restore_cal(struct b43_wldev *dev) | ||
2441 | { | ||
2442 | struct b43_phy_n *nphy = dev->phy.n; | ||
2443 | |||
2444 | u16 coef[4]; | ||
2445 | u16 *loft = NULL; | ||
2446 | u16 *table = NULL; | ||
2447 | |||
2448 | int i; | ||
2449 | u16 *txcal_radio_regs = NULL; | ||
2450 | struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; | ||
2451 | |||
2452 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||
2453 | if (nphy->iqcal_chanspec_2G == 0) | ||
2454 | return; | ||
2455 | table = nphy->cal_cache.txcal_coeffs_2G; | ||
2456 | loft = &nphy->cal_cache.txcal_coeffs_2G[5]; | ||
2457 | } else { | ||
2458 | if (nphy->iqcal_chanspec_5G == 0) | ||
2459 | return; | ||
2460 | table = nphy->cal_cache.txcal_coeffs_5G; | ||
2461 | loft = &nphy->cal_cache.txcal_coeffs_5G[5]; | ||
2462 | } | ||
2463 | |||
2464 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4, table); | ||
2465 | |||
2466 | for (i = 0; i < 4; i++) { | ||
2467 | if (dev->phy.rev >= 3) | ||
2468 | table[i] = coef[i]; | ||
2469 | else | ||
2470 | coef[i] = 0; | ||
2471 | } | ||
2472 | |||
2473 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, coef); | ||
2474 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, loft); | ||
2475 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2, loft); | ||
2476 | |||
2477 | if (dev->phy.rev < 2) | ||
2478 | b43_nphy_tx_iq_workaround(dev); | ||
2479 | |||
2480 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||
2481 | txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G; | ||
2482 | rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G; | ||
2483 | } else { | ||
2484 | txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G; | ||
2485 | rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G; | ||
2486 | } | ||
2487 | |||
2488 | /* TODO use some definitions */ | ||
2489 | if (dev->phy.rev >= 3) { | ||
2490 | b43_radio_write(dev, 0x2021, txcal_radio_regs[0]); | ||
2491 | b43_radio_write(dev, 0x2022, txcal_radio_regs[1]); | ||
2492 | b43_radio_write(dev, 0x3021, txcal_radio_regs[2]); | ||
2493 | b43_radio_write(dev, 0x3022, txcal_radio_regs[3]); | ||
2494 | b43_radio_write(dev, 0x2023, txcal_radio_regs[4]); | ||
2495 | b43_radio_write(dev, 0x2024, txcal_radio_regs[5]); | ||
2496 | b43_radio_write(dev, 0x3023, txcal_radio_regs[6]); | ||
2497 | b43_radio_write(dev, 0x3024, txcal_radio_regs[7]); | ||
2498 | } else { | ||
2499 | b43_radio_write(dev, 0x8B, txcal_radio_regs[0]); | ||
2500 | b43_radio_write(dev, 0xBA, txcal_radio_regs[1]); | ||
2501 | b43_radio_write(dev, 0x8D, txcal_radio_regs[2]); | ||
2502 | b43_radio_write(dev, 0xBC, txcal_radio_regs[3]); | ||
2503 | } | ||
2504 | b43_nphy_rx_iq_coeffs(dev, true, rxcal_coeffs); | ||
2505 | } | ||
2506 | |||
2507 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalTxIqlo */ | ||
2508 | static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, | ||
2509 | struct nphy_txgains target, | ||
2510 | bool full, bool mphase) | ||
2511 | { | ||
2512 | struct b43_phy_n *nphy = dev->phy.n; | ||
2513 | int i; | ||
2514 | int error = 0; | ||
2515 | int freq; | ||
2516 | bool avoid = false; | ||
2517 | u8 length; | ||
2518 | u16 tmp, core, type, count, max, numb, last, cmd; | ||
2519 | const u16 *table; | ||
2520 | bool phy6or5x; | ||
2521 | |||
2522 | u16 buffer[11]; | ||
2523 | u16 diq_start = 0; | ||
2524 | u16 save[2]; | ||
2525 | u16 gain[2]; | ||
2526 | struct nphy_iqcal_params params[2]; | ||
2527 | bool updated[2] = { }; | ||
2528 | |||
2529 | b43_nphy_stay_in_carrier_search(dev, true); | ||
2530 | |||
2531 | if (dev->phy.rev >= 4) { | ||
2532 | avoid = nphy->hang_avoid; | ||
2533 | nphy->hang_avoid = 0; | ||
2534 | } | ||
2535 | |||
2536 | b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, save); | ||
2537 | |||
2538 | for (i = 0; i < 2; i++) { | ||
2539 | b43_nphy_iq_cal_gain_params(dev, i, target, ¶ms[i]); | ||
2540 | gain[i] = params[i].cal_gain; | ||
2541 | } | ||
2542 | |||
2543 | b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain); | ||
2544 | |||
2545 | b43_nphy_tx_cal_radio_setup(dev); | ||
2546 | b43_nphy_tx_cal_phy_setup(dev); | ||
2547 | |||
2548 | phy6or5x = dev->phy.rev >= 6 || | ||
2549 | (dev->phy.rev == 5 && nphy->ipa2g_on && | ||
2550 | b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ); | ||
2551 | if (phy6or5x) { | ||
2552 | if (dev->phy.is_40mhz) { | ||
2553 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18, | ||
2554 | tbl_tx_iqlo_cal_loft_ladder_40); | ||
2555 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18, | ||
2556 | tbl_tx_iqlo_cal_iqimb_ladder_40); | ||
2557 | } else { | ||
2558 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18, | ||
2559 | tbl_tx_iqlo_cal_loft_ladder_20); | ||
2560 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18, | ||
2561 | tbl_tx_iqlo_cal_iqimb_ladder_20); | ||
2562 | } | ||
2563 | } | ||
2564 | |||
2565 | b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9); | ||
2566 | |||
2567 | if (!dev->phy.is_40mhz) | ||
2568 | freq = 2500; | ||
2569 | else | ||
2570 | freq = 5000; | ||
2571 | |||
2572 | if (nphy->mphase_cal_phase_id > 2) | ||
2573 | b43_nphy_run_samples(dev, (dev->phy.is_40mhz ? 40 : 20) * 8, | ||
2574 | 0xFFFF, 0, true, false); | ||
2575 | else | ||
2576 | error = b43_nphy_tx_tone(dev, freq, 250, true, false); | ||
2577 | |||
2578 | if (error == 0) { | ||
2579 | if (nphy->mphase_cal_phase_id > 2) { | ||
2580 | table = nphy->mphase_txcal_bestcoeffs; | ||
2581 | length = 11; | ||
2582 | if (dev->phy.rev < 3) | ||
2583 | length -= 2; | ||
2584 | } else { | ||
2585 | if (!full && nphy->txiqlocal_coeffsvalid) { | ||
2586 | table = nphy->txiqlocal_bestc; | ||
2587 | length = 11; | ||
2588 | if (dev->phy.rev < 3) | ||
2589 | length -= 2; | ||
2590 | } else { | ||
2591 | full = true; | ||
2592 | if (dev->phy.rev >= 3) { | ||
2593 | table = tbl_tx_iqlo_cal_startcoefs_nphyrev3; | ||
2594 | length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3; | ||
2595 | } else { | ||
2596 | table = tbl_tx_iqlo_cal_startcoefs; | ||
2597 | length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS; | ||
2598 | } | ||
2599 | } | ||
2600 | } | ||
2601 | |||
2602 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length, table); | ||
2603 | |||
2604 | if (full) { | ||
2605 | if (dev->phy.rev >= 3) | ||
2606 | max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3; | ||
2607 | else | ||
2608 | max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL; | ||
2609 | } else { | ||
2610 | if (dev->phy.rev >= 3) | ||
2611 | max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3; | ||
2612 | else | ||
2613 | max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL; | ||
2614 | } | ||
2615 | |||
2616 | if (mphase) { | ||
2617 | count = nphy->mphase_txcal_cmdidx; | ||
2618 | numb = min(max, | ||
2619 | (u16)(count + nphy->mphase_txcal_numcmds)); | ||
2620 | } else { | ||
2621 | count = 0; | ||
2622 | numb = max; | ||
2623 | } | ||
2624 | |||
2625 | for (; count < numb; count++) { | ||
2626 | if (full) { | ||
2627 | if (dev->phy.rev >= 3) | ||
2628 | cmd = tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[count]; | ||
2629 | else | ||
2630 | cmd = tbl_tx_iqlo_cal_cmds_fullcal[count]; | ||
2631 | } else { | ||
2632 | if (dev->phy.rev >= 3) | ||
2633 | cmd = tbl_tx_iqlo_cal_cmds_recal_nphyrev3[count]; | ||
2634 | else | ||
2635 | cmd = tbl_tx_iqlo_cal_cmds_recal[count]; | ||
2636 | } | ||
2637 | |||
2638 | core = (cmd & 0x3000) >> 12; | ||
2639 | type = (cmd & 0x0F00) >> 8; | ||
2640 | |||
2641 | if (phy6or5x && updated[core] == 0) { | ||
2642 | b43_nphy_update_tx_cal_ladder(dev, core); | ||
2643 | updated[core] = 1; | ||
2644 | } | ||
2645 | |||
2646 | tmp = (params[core].ncorr[type] << 8) | 0x66; | ||
2647 | b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDNNUM, tmp); | ||
2648 | |||
2649 | if (type == 1 || type == 3 || type == 4) { | ||
2650 | buffer[0] = b43_ntab_read(dev, | ||
2651 | B43_NTAB16(15, 69 + core)); | ||
2652 | diq_start = buffer[0]; | ||
2653 | buffer[0] = 0; | ||
2654 | b43_ntab_write(dev, B43_NTAB16(15, 69 + core), | ||
2655 | 0); | ||
2656 | } | ||
2657 | |||
2658 | b43_phy_write(dev, B43_NPHY_IQLOCAL_CMD, cmd); | ||
2659 | for (i = 0; i < 2000; i++) { | ||
2660 | tmp = b43_phy_read(dev, B43_NPHY_IQLOCAL_CMD); | ||
2661 | if (tmp & 0xC000) | ||
2662 | break; | ||
2663 | udelay(10); | ||
2664 | } | ||
2665 | |||
2666 | b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length, | ||
2667 | buffer); | ||
2668 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length, | ||
2669 | buffer); | ||
2670 | |||
2671 | if (type == 1 || type == 3 || type == 4) | ||
2672 | buffer[0] = diq_start; | ||
2673 | } | ||
2674 | |||
2675 | if (mphase) | ||
2676 | nphy->mphase_txcal_cmdidx = (numb >= max) ? 0 : numb; | ||
2677 | |||
2678 | last = (dev->phy.rev < 3) ? 6 : 7; | ||
2679 | |||
2680 | if (!mphase || nphy->mphase_cal_phase_id == last) { | ||
2681 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 96), 4, buffer); | ||
2682 | b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 4, buffer); | ||
2683 | if (dev->phy.rev < 3) { | ||
2684 | buffer[0] = 0; | ||
2685 | buffer[1] = 0; | ||
2686 | buffer[2] = 0; | ||
2687 | buffer[3] = 0; | ||
2688 | } | ||
2689 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, | ||
2690 | buffer); | ||
2691 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 101), 2, | ||
2692 | buffer); | ||
2693 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, | ||
2694 | buffer); | ||
2695 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2, | ||
2696 | buffer); | ||
2697 | length = 11; | ||
2698 | if (dev->phy.rev < 3) | ||
2699 | length -= 2; | ||
2700 | b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length, | ||
2701 | nphy->txiqlocal_bestc); | ||
2702 | nphy->txiqlocal_coeffsvalid = true; | ||
2703 | /* TODO: Set nphy->txiqlocal_chanspec to | ||
2704 | the current channel */ | ||
2705 | } else { | ||
2706 | length = 11; | ||
2707 | if (dev->phy.rev < 3) | ||
2708 | length -= 2; | ||
2709 | b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length, | ||
2710 | nphy->mphase_txcal_bestcoeffs); | ||
2711 | } | ||
2712 | |||
2713 | b43_nphy_stop_playback(dev); | ||
2714 | b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0); | ||
2715 | } | ||
2716 | |||
2717 | b43_nphy_tx_cal_phy_cleanup(dev); | ||
2718 | b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, save); | ||
2719 | |||
2720 | if (dev->phy.rev < 2 && (!mphase || nphy->mphase_cal_phase_id == last)) | ||
2721 | b43_nphy_tx_iq_workaround(dev); | ||
2722 | |||
2723 | if (dev->phy.rev >= 4) | ||
2724 | nphy->hang_avoid = avoid; | ||
2725 | |||
2726 | b43_nphy_stay_in_carrier_search(dev, false); | ||
2727 | |||
2728 | return error; | ||
2729 | } | ||
2730 | |||
2731 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ReapplyTxCalCoeffs */ | ||
2732 | static void b43_nphy_reapply_tx_cal_coeffs(struct b43_wldev *dev) | ||
2733 | { | ||
2734 | struct b43_phy_n *nphy = dev->phy.n; | ||
2735 | u8 i; | ||
2736 | u16 buffer[7]; | ||
2737 | bool equal = true; | ||
2738 | |||
2739 | if (!nphy->txiqlocal_coeffsvalid || 1 /* FIXME */) | ||
2740 | return; | ||
2741 | |||
2742 | b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer); | ||
2743 | for (i = 0; i < 4; i++) { | ||
2744 | if (buffer[i] != nphy->txiqlocal_bestc[i]) { | ||
2745 | equal = false; | ||
2746 | break; | ||
2747 | } | ||
2748 | } | ||
2749 | |||
2750 | if (!equal) { | ||
2751 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4, | ||
2752 | nphy->txiqlocal_bestc); | ||
2753 | for (i = 0; i < 4; i++) | ||
2754 | buffer[i] = 0; | ||
2755 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, | ||
2756 | buffer); | ||
2757 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, | ||
2758 | &nphy->txiqlocal_bestc[5]); | ||
2759 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2, | ||
2760 | &nphy->txiqlocal_bestc[5]); | ||
2761 | } | ||
2762 | } | ||
2763 | |||
2764 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */ | ||
2765 | static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, | ||
2766 | struct nphy_txgains target, u8 type, bool debug) | ||
2767 | { | ||
2768 | struct b43_phy_n *nphy = dev->phy.n; | ||
2769 | int i, j, index; | ||
2770 | u8 rfctl[2]; | ||
2771 | u8 afectl_core; | ||
2772 | u16 tmp[6]; | ||
2773 | u16 cur_hpf1, cur_hpf2, cur_lna; | ||
2774 | u32 real, imag; | ||
2775 | enum ieee80211_band band; | ||
2776 | |||
2777 | u8 use; | ||
2778 | u16 cur_hpf; | ||
2779 | u16 lna[3] = { 3, 3, 1 }; | ||
2780 | u16 hpf1[3] = { 7, 2, 0 }; | ||
2781 | u16 hpf2[3] = { 2, 0, 0 }; | ||
2782 | u32 power[3] = { }; | ||
2783 | u16 gain_save[2]; | ||
2784 | u16 cal_gain[2]; | ||
2785 | struct nphy_iqcal_params cal_params[2]; | ||
2786 | struct nphy_iq_est est; | ||
2787 | int ret = 0; | ||
2788 | bool playtone = true; | ||
2789 | int desired = 13; | ||
2790 | |||
2791 | b43_nphy_stay_in_carrier_search(dev, 1); | ||
2792 | |||
2793 | if (dev->phy.rev < 2) | ||
2794 | b43_nphy_reapply_tx_cal_coeffs(dev); | ||
2795 | b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save); | ||
2796 | for (i = 0; i < 2; i++) { | ||
2797 | b43_nphy_iq_cal_gain_params(dev, i, target, &cal_params[i]); | ||
2798 | cal_gain[i] = cal_params[i].cal_gain; | ||
2799 | } | ||
2800 | b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, cal_gain); | ||
2801 | |||
2802 | for (i = 0; i < 2; i++) { | ||
2803 | if (i == 0) { | ||
2804 | rfctl[0] = B43_NPHY_RFCTL_INTC1; | ||
2805 | rfctl[1] = B43_NPHY_RFCTL_INTC2; | ||
2806 | afectl_core = B43_NPHY_AFECTL_C1; | ||
2807 | } else { | ||
2808 | rfctl[0] = B43_NPHY_RFCTL_INTC2; | ||
2809 | rfctl[1] = B43_NPHY_RFCTL_INTC1; | ||
2810 | afectl_core = B43_NPHY_AFECTL_C2; | ||
2811 | } | ||
2812 | |||
2813 | tmp[1] = b43_phy_read(dev, B43_NPHY_RFSEQCA); | ||
2814 | tmp[2] = b43_phy_read(dev, afectl_core); | ||
2815 | tmp[3] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); | ||
2816 | tmp[4] = b43_phy_read(dev, rfctl[0]); | ||
2817 | tmp[5] = b43_phy_read(dev, rfctl[1]); | ||
2818 | |||
2819 | b43_phy_maskset(dev, B43_NPHY_RFSEQCA, | ||
2820 | (u16)~B43_NPHY_RFSEQCA_RXDIS, | ||
2821 | ((1 - i) << B43_NPHY_RFSEQCA_RXDIS_SHIFT)); | ||
2822 | b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN, | ||
2823 | (1 - i)); | ||
2824 | b43_phy_set(dev, afectl_core, 0x0006); | ||
2825 | b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0006); | ||
2826 | |||
2827 | band = b43_current_band(dev->wl); | ||
2828 | |||
2829 | if (nphy->rxcalparams & 0xFF000000) { | ||
2830 | if (band == IEEE80211_BAND_5GHZ) | ||
2831 | b43_phy_write(dev, rfctl[0], 0x140); | ||
2832 | else | ||
2833 | b43_phy_write(dev, rfctl[0], 0x110); | ||
2834 | } else { | ||
2835 | if (band == IEEE80211_BAND_5GHZ) | ||
2836 | b43_phy_write(dev, rfctl[0], 0x180); | ||
2837 | else | ||
2838 | b43_phy_write(dev, rfctl[0], 0x120); | ||
2839 | } | ||
2840 | |||
2841 | if (band == IEEE80211_BAND_5GHZ) | ||
2842 | b43_phy_write(dev, rfctl[1], 0x148); | ||
2843 | else | ||
2844 | b43_phy_write(dev, rfctl[1], 0x114); | ||
2845 | |||
2846 | if (nphy->rxcalparams & 0x10000) { | ||
2847 | b43_radio_maskset(dev, B2055_C1_GENSPARE2, 0xFC, | ||
2848 | (i + 1)); | ||
2849 | b43_radio_maskset(dev, B2055_C2_GENSPARE2, 0xFC, | ||
2850 | (2 - i)); | ||
2851 | } | ||
2852 | |||
2853 | for (j = 0; i < 4; j++) { | ||
2854 | if (j < 3) { | ||
2855 | cur_lna = lna[j]; | ||
2856 | cur_hpf1 = hpf1[j]; | ||
2857 | cur_hpf2 = hpf2[j]; | ||
2858 | } else { | ||
2859 | if (power[1] > 10000) { | ||
2860 | use = 1; | ||
2861 | cur_hpf = cur_hpf1; | ||
2862 | index = 2; | ||
2863 | } else { | ||
2864 | if (power[0] > 10000) { | ||
2865 | use = 1; | ||
2866 | cur_hpf = cur_hpf1; | ||
2867 | index = 1; | ||
2868 | } else { | ||
2869 | index = 0; | ||
2870 | use = 2; | ||
2871 | cur_hpf = cur_hpf2; | ||
2872 | } | ||
2873 | } | ||
2874 | cur_lna = lna[index]; | ||
2875 | cur_hpf1 = hpf1[index]; | ||
2876 | cur_hpf2 = hpf2[index]; | ||
2877 | cur_hpf += desired - hweight32(power[index]); | ||
2878 | cur_hpf = clamp_val(cur_hpf, 0, 10); | ||
2879 | if (use == 1) | ||
2880 | cur_hpf1 = cur_hpf; | ||
2881 | else | ||
2882 | cur_hpf2 = cur_hpf; | ||
2883 | } | ||
2884 | |||
2885 | tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) | | ||
2886 | (cur_lna << 2)); | ||
2887 | b43_nphy_rf_control_override(dev, 0x400, tmp[0], 3, | ||
2888 | false); | ||
2889 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); | ||
2890 | b43_nphy_stop_playback(dev); | ||
2891 | |||
2892 | if (playtone) { | ||
2893 | ret = b43_nphy_tx_tone(dev, 4000, | ||
2894 | (nphy->rxcalparams & 0xFFFF), | ||
2895 | false, false); | ||
2896 | playtone = false; | ||
2897 | } else { | ||
2898 | b43_nphy_run_samples(dev, 160, 0xFFFF, 0, | ||
2899 | false, false); | ||
2900 | } | ||
2901 | |||
2902 | if (ret == 0) { | ||
2903 | if (j < 3) { | ||
2904 | b43_nphy_rx_iq_est(dev, &est, 1024, 32, | ||
2905 | false); | ||
2906 | if (i == 0) { | ||
2907 | real = est.i0_pwr; | ||
2908 | imag = est.q0_pwr; | ||
2909 | } else { | ||
2910 | real = est.i1_pwr; | ||
2911 | imag = est.q1_pwr; | ||
2912 | } | ||
2913 | power[i] = ((real + imag) / 1024) + 1; | ||
2914 | } else { | ||
2915 | b43_nphy_calc_rx_iq_comp(dev, 1 << i); | ||
2916 | } | ||
2917 | b43_nphy_stop_playback(dev); | ||
2918 | } | ||
2919 | |||
2920 | if (ret != 0) | ||
2921 | break; | ||
2922 | } | ||
2923 | |||
2924 | b43_radio_mask(dev, B2055_C1_GENSPARE2, 0xFC); | ||
2925 | b43_radio_mask(dev, B2055_C2_GENSPARE2, 0xFC); | ||
2926 | b43_phy_write(dev, rfctl[1], tmp[5]); | ||
2927 | b43_phy_write(dev, rfctl[0], tmp[4]); | ||
2928 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp[3]); | ||
2929 | b43_phy_write(dev, afectl_core, tmp[2]); | ||
2930 | b43_phy_write(dev, B43_NPHY_RFSEQCA, tmp[1]); | ||
2931 | |||
2932 | if (ret != 0) | ||
2933 | break; | ||
2934 | } | ||
2935 | |||
2936 | b43_nphy_rf_control_override(dev, 0x400, 0, 3, true); | ||
2937 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); | ||
2938 | b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save); | ||
2939 | |||
2940 | b43_nphy_stay_in_carrier_search(dev, 0); | ||
2941 | |||
2942 | return ret; | ||
2943 | } | ||
2944 | |||
2945 | static int b43_nphy_rev3_cal_rx_iq(struct b43_wldev *dev, | ||
2946 | struct nphy_txgains target, u8 type, bool debug) | ||
2947 | { | ||
2948 | return -1; | ||
2949 | } | ||
2950 | |||
2951 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIq */ | ||
2952 | static int b43_nphy_cal_rx_iq(struct b43_wldev *dev, | ||
2953 | struct nphy_txgains target, u8 type, bool debug) | ||
2954 | { | ||
2955 | if (dev->phy.rev >= 3) | ||
2956 | return b43_nphy_rev3_cal_rx_iq(dev, target, type, debug); | ||
2957 | else | ||
2958 | return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug); | ||
2959 | } | ||
2960 | |||
2961 | /* | ||
2962 | * Init N-PHY | ||
2963 | * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N | ||
2964 | */ | ||
420 | int b43_phy_initn(struct b43_wldev *dev) | 2965 | int b43_phy_initn(struct b43_wldev *dev) |
421 | { | 2966 | { |
2967 | struct ssb_bus *bus = dev->dev->bus; | ||
422 | struct b43_phy *phy = &dev->phy; | 2968 | struct b43_phy *phy = &dev->phy; |
2969 | struct b43_phy_n *nphy = phy->n; | ||
2970 | u8 tx_pwr_state; | ||
2971 | struct nphy_txgains target; | ||
423 | u16 tmp; | 2972 | u16 tmp; |
2973 | enum ieee80211_band tmp2; | ||
2974 | bool do_rssi_cal; | ||
424 | 2975 | ||
425 | //TODO: Spectral management | 2976 | u16 clip[2]; |
2977 | bool do_cal = false; | ||
2978 | |||
2979 | if ((dev->phy.rev >= 3) && | ||
2980 | (bus->sprom.boardflags_lo & B43_BFL_EXTLNA) && | ||
2981 | (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) { | ||
2982 | chipco_set32(&dev->dev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40); | ||
2983 | } | ||
2984 | nphy->deaf_count = 0; | ||
426 | b43_nphy_tables_init(dev); | 2985 | b43_nphy_tables_init(dev); |
2986 | nphy->crsminpwr_adjusted = false; | ||
2987 | nphy->noisevars_adjusted = false; | ||
427 | 2988 | ||
428 | /* Clear all overrides */ | 2989 | /* Clear all overrides */ |
429 | b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0); | 2990 | if (dev->phy.rev >= 3) { |
2991 | b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, 0); | ||
2992 | b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0); | ||
2993 | b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, 0); | ||
2994 | b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, 0); | ||
2995 | } else { | ||
2996 | b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0); | ||
2997 | } | ||
430 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0); | 2998 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0); |
431 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0); | 2999 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0); |
432 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0); | 3000 | if (dev->phy.rev < 6) { |
433 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0); | 3001 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0); |
3002 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0); | ||
3003 | } | ||
434 | b43_phy_mask(dev, B43_NPHY_RFSEQMODE, | 3004 | b43_phy_mask(dev, B43_NPHY_RFSEQMODE, |
435 | ~(B43_NPHY_RFSEQMODE_CAOVER | | 3005 | ~(B43_NPHY_RFSEQMODE_CAOVER | |
436 | B43_NPHY_RFSEQMODE_TROVER)); | 3006 | B43_NPHY_RFSEQMODE_TROVER)); |
3007 | if (dev->phy.rev >= 3) | ||
3008 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, 0); | ||
437 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0); | 3009 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0); |
438 | 3010 | ||
439 | tmp = (phy->rev < 2) ? 64 : 59; | 3011 | if (dev->phy.rev <= 2) { |
440 | b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, | 3012 | tmp = (dev->phy.rev == 2) ? 0x3B : 0x40; |
441 | ~B43_NPHY_BPHY_CTL3_SCALE, | 3013 | b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, |
442 | tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT); | 3014 | ~B43_NPHY_BPHY_CTL3_SCALE, |
443 | 3015 | tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT); | |
3016 | } | ||
444 | b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20); | 3017 | b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20); |
445 | b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20); | 3018 | b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20); |
446 | 3019 | ||
447 | b43_phy_write(dev, B43_NPHY_TXREALFD, 184); | 3020 | if (bus->sprom.boardflags2_lo & 0x100 || |
448 | b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 200); | 3021 | (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE && |
449 | b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 80); | 3022 | bus->boardinfo.type == 0x8B)) |
450 | b43_phy_write(dev, B43_NPHY_C2_BCLIPBKOFF, 511); | 3023 | b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0); |
3024 | else | ||
3025 | b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8); | ||
3026 | b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 0xC8); | ||
3027 | b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50); | ||
3028 | b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30); | ||
451 | 3029 | ||
452 | //TODO MIMO-Config | 3030 | b43_nphy_update_mimo_config(dev, nphy->preamble_override); |
453 | //TODO Update TX/RX chain | 3031 | b43_nphy_update_txrx_chain(dev); |
454 | 3032 | ||
455 | if (phy->rev < 2) { | 3033 | if (phy->rev < 2) { |
456 | b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8); | 3034 | b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8); |
457 | b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4); | 3035 | b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4); |
458 | } | 3036 | } |
3037 | |||
3038 | tmp2 = b43_current_band(dev->wl); | ||
3039 | if ((nphy->ipa2g_on && tmp2 == IEEE80211_BAND_2GHZ) || | ||
3040 | (nphy->ipa5g_on && tmp2 == IEEE80211_BAND_5GHZ)) { | ||
3041 | b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1); | ||
3042 | b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ0, 0x007F, | ||
3043 | nphy->papd_epsilon_offset[0] << 7); | ||
3044 | b43_phy_set(dev, B43_NPHY_PAPD_EN1, 0x1); | ||
3045 | b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ1, 0x007F, | ||
3046 | nphy->papd_epsilon_offset[1] << 7); | ||
3047 | b43_nphy_int_pa_set_tx_dig_filters(dev); | ||
3048 | } else if (phy->rev >= 5) { | ||
3049 | b43_nphy_ext_pa_set_tx_dig_filters(dev); | ||
3050 | } | ||
3051 | |||
459 | b43_nphy_workarounds(dev); | 3052 | b43_nphy_workarounds(dev); |
460 | b43_nphy_reset_cca(dev); | ||
461 | 3053 | ||
462 | ssb_write32(dev->dev, SSB_TMSLOW, | 3054 | /* Reset CCA, in init code it differs a little from standard way */ |
463 | ssb_read32(dev->dev, SSB_TMSLOW) | B43_TMSLOW_MACPHYCLKEN); | 3055 | b43_nphy_bmac_clock_fgc(dev, 1); |
3056 | tmp = b43_phy_read(dev, B43_NPHY_BBCFG); | ||
3057 | b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA); | ||
3058 | b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA); | ||
3059 | b43_nphy_bmac_clock_fgc(dev, 0); | ||
3060 | |||
3061 | /* TODO N PHY MAC PHY Clock Set with argument 1 */ | ||
3062 | |||
3063 | b43_nphy_pa_override(dev, false); | ||
464 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); | 3064 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); |
465 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); | 3065 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); |
3066 | b43_nphy_pa_override(dev, true); | ||
3067 | |||
3068 | b43_nphy_classifier(dev, 0, 0); | ||
3069 | b43_nphy_read_clip_detection(dev, clip); | ||
3070 | tx_pwr_state = nphy->txpwrctrl; | ||
3071 | /* TODO N PHY TX power control with argument 0 | ||
3072 | (turning off power control) */ | ||
3073 | /* TODO Fix the TX Power Settings */ | ||
3074 | /* TODO N PHY TX Power Control Idle TSSI */ | ||
3075 | /* TODO N PHY TX Power Control Setup */ | ||
3076 | |||
3077 | if (phy->rev >= 3) { | ||
3078 | /* TODO */ | ||
3079 | } else { | ||
3080 | b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, | ||
3081 | b43_ntab_tx_gain_rev0_1_2); | ||
3082 | b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, | ||
3083 | b43_ntab_tx_gain_rev0_1_2); | ||
3084 | } | ||
3085 | |||
3086 | if (nphy->phyrxchain != 3) | ||
3087 | ;/* TODO N PHY RX Core Set State with phyrxchain as argument */ | ||
3088 | if (nphy->mphase_cal_phase_id > 0) | ||
3089 | ;/* TODO PHY Periodic Calibration Multi-Phase Restart */ | ||
3090 | |||
3091 | do_rssi_cal = false; | ||
3092 | if (phy->rev >= 3) { | ||
3093 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | ||
3094 | do_rssi_cal = (nphy->rssical_chanspec_2G == 0); | ||
3095 | else | ||
3096 | do_rssi_cal = (nphy->rssical_chanspec_5G == 0); | ||
3097 | |||
3098 | if (do_rssi_cal) | ||
3099 | b43_nphy_rssi_cal(dev); | ||
3100 | else | ||
3101 | b43_nphy_restore_rssi_cal(dev); | ||
3102 | } else { | ||
3103 | b43_nphy_rssi_cal(dev); | ||
3104 | } | ||
3105 | |||
3106 | if (!((nphy->measure_hold & 0x6) != 0)) { | ||
3107 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | ||
3108 | do_cal = (nphy->iqcal_chanspec_2G == 0); | ||
3109 | else | ||
3110 | do_cal = (nphy->iqcal_chanspec_5G == 0); | ||
3111 | |||
3112 | if (nphy->mute) | ||
3113 | do_cal = false; | ||
3114 | |||
3115 | if (do_cal) { | ||
3116 | target = b43_nphy_get_tx_gains(dev); | ||
3117 | |||
3118 | if (nphy->antsel_type == 2) | ||
3119 | ;/*TODO NPHY Superswitch Init with argument 1*/ | ||
3120 | if (nphy->perical != 2) { | ||
3121 | b43_nphy_rssi_cal(dev); | ||
3122 | if (phy->rev >= 3) { | ||
3123 | nphy->cal_orig_pwr_idx[0] = | ||
3124 | nphy->txpwrindex[0].index_internal; | ||
3125 | nphy->cal_orig_pwr_idx[1] = | ||
3126 | nphy->txpwrindex[1].index_internal; | ||
3127 | /* TODO N PHY Pre Calibrate TX Gain */ | ||
3128 | target = b43_nphy_get_tx_gains(dev); | ||
3129 | } | ||
3130 | } | ||
3131 | } | ||
3132 | } | ||
3133 | |||
3134 | if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false)) { | ||
3135 | if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0) | ||
3136 | b43_nphy_save_cal(dev); | ||
3137 | else if (nphy->mphase_cal_phase_id == 0) | ||
3138 | ;/* N PHY Periodic Calibration with argument 3 */ | ||
3139 | } else { | ||
3140 | b43_nphy_restore_cal(dev); | ||
3141 | } | ||
466 | 3142 | ||
467 | b43_phy_read(dev, B43_NPHY_CLASSCTL); /* dummy read */ | 3143 | b43_nphy_tx_pwr_ctrl_coef_setup(dev); |
468 | //TODO read core1/2 clip1 thres regs | 3144 | /* TODO N PHY TX Power Control Enable with argument tx_pwr_state */ |
469 | 3145 | b43_phy_write(dev, B43_NPHY_TXMACIF_HOLDOFF, 0x0015); | |
470 | if (1 /* FIXME Band is 2.4GHz */) | 3146 | b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320); |
471 | b43_nphy_bphy_init(dev); | 3147 | if (phy->rev >= 3 && phy->rev <= 6) |
472 | //TODO disable TX power control | 3148 | b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x0014); |
473 | //TODO Fix the TX power settings | 3149 | b43_nphy_tx_lp_fbw(dev); |
474 | //TODO Init periodic calibration with reason 3 | 3150 | if (phy->rev >= 3) |
475 | b43_nphy_rssi_cal(dev, 2); | 3151 | b43_nphy_spur_workaround(dev); |
476 | b43_nphy_rssi_cal(dev, 0); | ||
477 | b43_nphy_rssi_cal(dev, 1); | ||
478 | //TODO get TX gain | ||
479 | //TODO init superswitch | ||
480 | //TODO calibrate LO | ||
481 | //TODO idle TSSI TX pctl | ||
482 | //TODO TX power control power setup | ||
483 | //TODO table writes | ||
484 | //TODO TX power control coefficients | ||
485 | //TODO enable TX power control | ||
486 | //TODO control antenna selection | ||
487 | //TODO init radar detection | ||
488 | //TODO reset channel if changed | ||
489 | 3152 | ||
490 | b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n"); | 3153 | b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n"); |
491 | return 0; | 3154 | return 0; |
diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index 1749aef4147d..403aad3f894f 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h | |||
@@ -231,6 +231,7 @@ | |||
231 | #define B43_NPHY_C2_TXIQ_COMP_OFF B43_PHY_N(0x088) /* Core 2 TX I/Q comp offset */ | 231 | #define B43_NPHY_C2_TXIQ_COMP_OFF B43_PHY_N(0x088) /* Core 2 TX I/Q comp offset */ |
232 | #define B43_NPHY_C1_TXCTL B43_PHY_N(0x08B) /* Core 1 TX control */ | 232 | #define B43_NPHY_C1_TXCTL B43_PHY_N(0x08B) /* Core 1 TX control */ |
233 | #define B43_NPHY_C2_TXCTL B43_PHY_N(0x08C) /* Core 2 TX control */ | 233 | #define B43_NPHY_C2_TXCTL B43_PHY_N(0x08C) /* Core 2 TX control */ |
234 | #define B43_NPHY_AFECTL_OVER1 B43_PHY_N(0x08F) /* AFE control override 1 */ | ||
234 | #define B43_NPHY_SCRAM_SIGCTL B43_PHY_N(0x090) /* Scram signal control */ | 235 | #define B43_NPHY_SCRAM_SIGCTL B43_PHY_N(0x090) /* Scram signal control */ |
235 | #define B43_NPHY_SCRAM_SIGCTL_INITST 0x007F /* Initial state value */ | 236 | #define B43_NPHY_SCRAM_SIGCTL_INITST 0x007F /* Initial state value */ |
236 | #define B43_NPHY_SCRAM_SIGCTL_INITST_SHIFT 0 | 237 | #define B43_NPHY_SCRAM_SIGCTL_INITST_SHIFT 0 |
@@ -705,6 +706,10 @@ | |||
705 | #define B43_NPHY_TXPCTL_INIT B43_PHY_N(0x222) /* TX power controll init */ | 706 | #define B43_NPHY_TXPCTL_INIT B43_PHY_N(0x222) /* TX power controll init */ |
706 | #define B43_NPHY_TXPCTL_INIT_PIDXI1 0x00FF /* Power index init 1 */ | 707 | #define B43_NPHY_TXPCTL_INIT_PIDXI1 0x00FF /* Power index init 1 */ |
707 | #define B43_NPHY_TXPCTL_INIT_PIDXI1_SHIFT 0 | 708 | #define B43_NPHY_TXPCTL_INIT_PIDXI1_SHIFT 0 |
709 | #define B43_NPHY_PAPD_EN0 B43_PHY_N(0x297) /* PAPD Enable0 TBD */ | ||
710 | #define B43_NPHY_EPS_TABLE_ADJ0 B43_PHY_N(0x298) /* EPS Table Adj0 TBD */ | ||
711 | #define B43_NPHY_PAPD_EN1 B43_PHY_N(0x29B) /* PAPD Enable1 TBD */ | ||
712 | #define B43_NPHY_EPS_TABLE_ADJ1 B43_PHY_N(0x29C) /* EPS Table Adj1 TBD */ | ||
708 | 713 | ||
709 | 714 | ||
710 | 715 | ||
@@ -919,8 +924,99 @@ | |||
919 | 924 | ||
920 | struct b43_wldev; | 925 | struct b43_wldev; |
921 | 926 | ||
927 | struct b43_phy_n_iq_comp { | ||
928 | s16 a0; | ||
929 | s16 b0; | ||
930 | s16 a1; | ||
931 | s16 b1; | ||
932 | }; | ||
933 | |||
934 | struct b43_phy_n_rssical_cache { | ||
935 | u16 rssical_radio_regs_2G[2]; | ||
936 | u16 rssical_phy_regs_2G[12]; | ||
937 | |||
938 | u16 rssical_radio_regs_5G[2]; | ||
939 | u16 rssical_phy_regs_5G[12]; | ||
940 | }; | ||
941 | |||
942 | struct b43_phy_n_cal_cache { | ||
943 | u16 txcal_radio_regs_2G[8]; | ||
944 | u16 txcal_coeffs_2G[8]; | ||
945 | struct b43_phy_n_iq_comp rxcal_coeffs_2G; | ||
946 | |||
947 | u16 txcal_radio_regs_5G[8]; | ||
948 | u16 txcal_coeffs_5G[8]; | ||
949 | struct b43_phy_n_iq_comp rxcal_coeffs_5G; | ||
950 | }; | ||
951 | |||
952 | struct b43_phy_n_txpwrindex { | ||
953 | s8 index; | ||
954 | s8 index_internal; | ||
955 | s8 index_internal_save; | ||
956 | u16 AfectrlOverride; | ||
957 | u16 AfeCtrlDacGain; | ||
958 | u16 rad_gain; | ||
959 | u8 bbmult; | ||
960 | u16 iqcomp_a; | ||
961 | u16 iqcomp_b; | ||
962 | u16 locomp; | ||
963 | }; | ||
964 | |||
922 | struct b43_phy_n { | 965 | struct b43_phy_n { |
923 | //TODO lots of missing stuff | 966 | u8 antsel_type; |
967 | u8 cal_orig_pwr_idx[2]; | ||
968 | u8 measure_hold; | ||
969 | u8 phyrxchain; | ||
970 | u8 perical; | ||
971 | u32 deaf_count; | ||
972 | u32 rxcalparams; | ||
973 | bool hang_avoid; | ||
974 | bool mute; | ||
975 | u16 papd_epsilon_offset[2]; | ||
976 | s32 preamble_override; | ||
977 | u32 bb_mult_save; | ||
978 | u16 radio_chanspec; | ||
979 | |||
980 | bool gain_boost; | ||
981 | bool elna_gain_config; | ||
982 | bool band5g_pwrgain; | ||
983 | |||
984 | u8 mphase_cal_phase_id; | ||
985 | u16 mphase_txcal_cmdidx; | ||
986 | u16 mphase_txcal_numcmds; | ||
987 | u16 mphase_txcal_bestcoeffs[11]; | ||
988 | |||
989 | u8 txpwrctrl; | ||
990 | u16 txcal_bbmult; | ||
991 | u16 txiqlocal_bestc[11]; | ||
992 | bool txiqlocal_coeffsvalid; | ||
993 | struct b43_phy_n_txpwrindex txpwrindex[2]; | ||
994 | |||
995 | u8 txrx_chain; | ||
996 | u16 tx_rx_cal_phy_saveregs[11]; | ||
997 | u16 tx_rx_cal_radio_saveregs[22]; | ||
998 | |||
999 | u16 rfctrl_intc1_save; | ||
1000 | u16 rfctrl_intc2_save; | ||
1001 | |||
1002 | u16 classifier_state; | ||
1003 | u16 clip_state[2]; | ||
1004 | |||
1005 | bool aband_spurwar_en; | ||
1006 | bool gband_spurwar_en; | ||
1007 | |||
1008 | bool ipa2g_on; | ||
1009 | u8 iqcal_chanspec_2G; | ||
1010 | u8 rssical_chanspec_2G; | ||
1011 | |||
1012 | bool ipa5g_on; | ||
1013 | u8 iqcal_chanspec_5G; | ||
1014 | u8 rssical_chanspec_5G; | ||
1015 | |||
1016 | struct b43_phy_n_rssical_cache rssical_cache; | ||
1017 | struct b43_phy_n_cal_cache cal_cache; | ||
1018 | bool crsminpwr_adjusted; | ||
1019 | bool noisevars_adjusted; | ||
924 | }; | 1020 | }; |
925 | 1021 | ||
926 | 1022 | ||
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index c01b8e02412f..a6062c3e89a5 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c | |||
@@ -559,7 +559,6 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb) | |||
559 | b43err(dev->wl, "PIO transmission failure\n"); | 559 | b43err(dev->wl, "PIO transmission failure\n"); |
560 | goto out; | 560 | goto out; |
561 | } | 561 | } |
562 | q->nr_tx_packets++; | ||
563 | 562 | ||
564 | B43_WARN_ON(q->buffer_used > q->buffer_size); | 563 | B43_WARN_ON(q->buffer_used > q->buffer_size); |
565 | if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) || | 564 | if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) || |
@@ -605,22 +604,6 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev, | |||
605 | } | 604 | } |
606 | } | 605 | } |
607 | 606 | ||
608 | void b43_pio_get_tx_stats(struct b43_wldev *dev, | ||
609 | struct ieee80211_tx_queue_stats *stats) | ||
610 | { | ||
611 | const int nr_queues = dev->wl->hw->queues; | ||
612 | struct b43_pio_txqueue *q; | ||
613 | int i; | ||
614 | |||
615 | for (i = 0; i < nr_queues; i++) { | ||
616 | q = select_queue_by_priority(dev, i); | ||
617 | |||
618 | stats[i].len = B43_PIO_MAX_NR_TXPACKETS - q->free_packet_slots; | ||
619 | stats[i].limit = B43_PIO_MAX_NR_TXPACKETS; | ||
620 | stats[i].count = q->nr_tx_packets; | ||
621 | } | ||
622 | } | ||
623 | |||
624 | /* Returns whether we should fetch another frame. */ | 607 | /* Returns whether we should fetch another frame. */ |
625 | static bool pio_rx_frame(struct b43_pio_rxqueue *q) | 608 | static bool pio_rx_frame(struct b43_pio_rxqueue *q) |
626 | { | 609 | { |
diff --git a/drivers/net/wireless/b43/pio.h b/drivers/net/wireless/b43/pio.h index 7dd649c9ddad..1e516147424f 100644 --- a/drivers/net/wireless/b43/pio.h +++ b/drivers/net/wireless/b43/pio.h | |||
@@ -55,8 +55,6 @@ | |||
55 | #define B43_PIO_MAX_NR_TXPACKETS 32 | 55 | #define B43_PIO_MAX_NR_TXPACKETS 32 |
56 | 56 | ||
57 | 57 | ||
58 | #ifdef CONFIG_B43_PIO | ||
59 | |||
60 | struct b43_pio_txpacket { | 58 | struct b43_pio_txpacket { |
61 | /* Pointer to the TX queue we belong to. */ | 59 | /* Pointer to the TX queue we belong to. */ |
62 | struct b43_pio_txqueue *queue; | 60 | struct b43_pio_txqueue *queue; |
@@ -92,9 +90,6 @@ struct b43_pio_txqueue { | |||
92 | struct b43_pio_txpacket packets[B43_PIO_MAX_NR_TXPACKETS]; | 90 | struct b43_pio_txpacket packets[B43_PIO_MAX_NR_TXPACKETS]; |
93 | struct list_head packets_list; | 91 | struct list_head packets_list; |
94 | 92 | ||
95 | /* Total number of transmitted packets. */ | ||
96 | unsigned int nr_tx_packets; | ||
97 | |||
98 | /* Shortcut to the 802.11 core revision. This is to | 93 | /* Shortcut to the 802.11 core revision. This is to |
99 | * avoid horrible pointer dereferencing in the fastpaths. */ | 94 | * avoid horrible pointer dereferencing in the fastpaths. */ |
100 | u8 rev; | 95 | u8 rev; |
@@ -162,49 +157,9 @@ void b43_pio_free(struct b43_wldev *dev); | |||
162 | int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb); | 157 | int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb); |
163 | void b43_pio_handle_txstatus(struct b43_wldev *dev, | 158 | void b43_pio_handle_txstatus(struct b43_wldev *dev, |
164 | const struct b43_txstatus *status); | 159 | const struct b43_txstatus *status); |
165 | void b43_pio_get_tx_stats(struct b43_wldev *dev, | ||
166 | struct ieee80211_tx_queue_stats *stats); | ||
167 | void b43_pio_rx(struct b43_pio_rxqueue *q); | 160 | void b43_pio_rx(struct b43_pio_rxqueue *q); |
168 | 161 | ||
169 | void b43_pio_tx_suspend(struct b43_wldev *dev); | 162 | void b43_pio_tx_suspend(struct b43_wldev *dev); |
170 | void b43_pio_tx_resume(struct b43_wldev *dev); | 163 | void b43_pio_tx_resume(struct b43_wldev *dev); |
171 | 164 | ||
172 | |||
173 | #else /* CONFIG_B43_PIO */ | ||
174 | |||
175 | |||
176 | static inline int b43_pio_init(struct b43_wldev *dev) | ||
177 | { | ||
178 | return 0; | ||
179 | } | ||
180 | static inline void b43_pio_free(struct b43_wldev *dev) | ||
181 | { | ||
182 | } | ||
183 | static inline void b43_pio_stop(struct b43_wldev *dev) | ||
184 | { | ||
185 | } | ||
186 | static inline int b43_pio_tx(struct b43_wldev *dev, | ||
187 | struct sk_buff *skb) | ||
188 | { | ||
189 | return 0; | ||
190 | } | ||
191 | static inline void b43_pio_handle_txstatus(struct b43_wldev *dev, | ||
192 | const struct b43_txstatus *status) | ||
193 | { | ||
194 | } | ||
195 | static inline void b43_pio_get_tx_stats(struct b43_wldev *dev, | ||
196 | struct ieee80211_tx_queue_stats *stats) | ||
197 | { | ||
198 | } | ||
199 | static inline void b43_pio_rx(struct b43_pio_rxqueue *q) | ||
200 | { | ||
201 | } | ||
202 | static inline void b43_pio_tx_suspend(struct b43_wldev *dev) | ||
203 | { | ||
204 | } | ||
205 | static inline void b43_pio_tx_resume(struct b43_wldev *dev) | ||
206 | { | ||
207 | } | ||
208 | |||
209 | #endif /* CONFIG_B43_PIO */ | ||
210 | #endif /* B43_PIO_H_ */ | 165 | #endif /* B43_PIO_H_ */ |
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index 4e2336315545..a00d509150f7 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c | |||
@@ -1336,7 +1336,7 @@ b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel) | |||
1336 | } | 1336 | } |
1337 | 1337 | ||
1338 | 1338 | ||
1339 | const u8 b43_ntab_adjustpower0[] = { | 1339 | static const u8 b43_ntab_adjustpower0[] = { |
1340 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, | 1340 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, |
1341 | 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, | 1341 | 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, |
1342 | 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, | 1342 | 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, |
@@ -1355,7 +1355,7 @@ const u8 b43_ntab_adjustpower0[] = { | |||
1355 | 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, | 1355 | 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, |
1356 | }; | 1356 | }; |
1357 | 1357 | ||
1358 | const u8 b43_ntab_adjustpower1[] = { | 1358 | static const u8 b43_ntab_adjustpower1[] = { |
1359 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, | 1359 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, |
1360 | 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, | 1360 | 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, |
1361 | 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, | 1361 | 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, |
@@ -1374,11 +1374,11 @@ const u8 b43_ntab_adjustpower1[] = { | |||
1374 | 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, | 1374 | 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, |
1375 | }; | 1375 | }; |
1376 | 1376 | ||
1377 | const u16 b43_ntab_bdi[] = { | 1377 | static const u16 b43_ntab_bdi[] = { |
1378 | 0x0070, 0x0126, 0x012C, 0x0246, 0x048D, 0x04D2, | 1378 | 0x0070, 0x0126, 0x012C, 0x0246, 0x048D, 0x04D2, |
1379 | }; | 1379 | }; |
1380 | 1380 | ||
1381 | const u32 b43_ntab_channelest[] = { | 1381 | static const u32 b43_ntab_channelest[] = { |
1382 | 0x44444444, 0x44444444, 0x44444444, 0x44444444, | 1382 | 0x44444444, 0x44444444, 0x44444444, 0x44444444, |
1383 | 0x44444444, 0x44444444, 0x44444444, 0x44444444, | 1383 | 0x44444444, 0x44444444, 0x44444444, 0x44444444, |
1384 | 0x10101010, 0x10101010, 0x10101010, 0x10101010, | 1384 | 0x10101010, 0x10101010, 0x10101010, 0x10101010, |
@@ -1405,7 +1405,7 @@ const u32 b43_ntab_channelest[] = { | |||
1405 | 0x10101010, 0x10101010, 0x10101010, 0x10101010, | 1405 | 0x10101010, 0x10101010, 0x10101010, 0x10101010, |
1406 | }; | 1406 | }; |
1407 | 1407 | ||
1408 | const u8 b43_ntab_estimatepowerlt0[] = { | 1408 | static const u8 b43_ntab_estimatepowerlt0[] = { |
1409 | 0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, | 1409 | 0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, |
1410 | 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, | 1410 | 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, |
1411 | 0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, | 1411 | 0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, |
@@ -1416,7 +1416,7 @@ const u8 b43_ntab_estimatepowerlt0[] = { | |||
1416 | 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, | 1416 | 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, |
1417 | }; | 1417 | }; |
1418 | 1418 | ||
1419 | const u8 b43_ntab_estimatepowerlt1[] = { | 1419 | static const u8 b43_ntab_estimatepowerlt1[] = { |
1420 | 0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, | 1420 | 0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, |
1421 | 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, | 1421 | 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, |
1422 | 0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, | 1422 | 0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, |
@@ -1427,14 +1427,14 @@ const u8 b43_ntab_estimatepowerlt1[] = { | |||
1427 | 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, | 1427 | 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, |
1428 | }; | 1428 | }; |
1429 | 1429 | ||
1430 | const u8 b43_ntab_framelookup[] = { | 1430 | static const u8 b43_ntab_framelookup[] = { |
1431 | 0x02, 0x04, 0x14, 0x14, 0x03, 0x05, 0x16, 0x16, | 1431 | 0x02, 0x04, 0x14, 0x14, 0x03, 0x05, 0x16, 0x16, |
1432 | 0x0A, 0x0C, 0x1C, 0x1C, 0x0B, 0x0D, 0x1E, 0x1E, | 1432 | 0x0A, 0x0C, 0x1C, 0x1C, 0x0B, 0x0D, 0x1E, 0x1E, |
1433 | 0x06, 0x08, 0x18, 0x18, 0x07, 0x09, 0x1A, 0x1A, | 1433 | 0x06, 0x08, 0x18, 0x18, 0x07, 0x09, 0x1A, 0x1A, |
1434 | 0x0E, 0x10, 0x20, 0x28, 0x0F, 0x11, 0x22, 0x2A, | 1434 | 0x0E, 0x10, 0x20, 0x28, 0x0F, 0x11, 0x22, 0x2A, |
1435 | }; | 1435 | }; |
1436 | 1436 | ||
1437 | const u32 b43_ntab_framestruct[] = { | 1437 | static const u32 b43_ntab_framestruct[] = { |
1438 | 0x08004A04, 0x00100000, 0x01000A05, 0x00100020, | 1438 | 0x08004A04, 0x00100000, 0x01000A05, 0x00100020, |
1439 | 0x09804506, 0x00100030, 0x09804507, 0x00100030, | 1439 | 0x09804506, 0x00100030, 0x09804507, 0x00100030, |
1440 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, | 1440 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
@@ -1645,7 +1645,7 @@ const u32 b43_ntab_framestruct[] = { | |||
1645 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, | 1645 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
1646 | }; | 1646 | }; |
1647 | 1647 | ||
1648 | const u32 b43_ntab_gainctl0[] = { | 1648 | static const u32 b43_ntab_gainctl0[] = { |
1649 | 0x007F003F, 0x007E013F, 0x007D023E, 0x007C033E, | 1649 | 0x007F003F, 0x007E013F, 0x007D023E, 0x007C033E, |
1650 | 0x007B043D, 0x007A053D, 0x0079063C, 0x0078073C, | 1650 | 0x007B043D, 0x007A053D, 0x0079063C, 0x0078073C, |
1651 | 0x0077083B, 0x0076093B, 0x00750A3A, 0x00740B3A, | 1651 | 0x0077083B, 0x0076093B, 0x00750A3A, 0x00740B3A, |
@@ -1680,7 +1680,7 @@ const u32 b43_ntab_gainctl0[] = { | |||
1680 | 0x00030C01, 0x00020D01, 0x00010E00, 0x00000F00, | 1680 | 0x00030C01, 0x00020D01, 0x00010E00, 0x00000F00, |
1681 | }; | 1681 | }; |
1682 | 1682 | ||
1683 | const u32 b43_ntab_gainctl1[] = { | 1683 | static const u32 b43_ntab_gainctl1[] = { |
1684 | 0x007F003F, 0x007E013F, 0x007D023E, 0x007C033E, | 1684 | 0x007F003F, 0x007E013F, 0x007D023E, 0x007C033E, |
1685 | 0x007B043D, 0x007A053D, 0x0079063C, 0x0078073C, | 1685 | 0x007B043D, 0x007A053D, 0x0079063C, 0x0078073C, |
1686 | 0x0077083B, 0x0076093B, 0x00750A3A, 0x00740B3A, | 1686 | 0x0077083B, 0x0076093B, 0x00750A3A, 0x00740B3A, |
@@ -1715,12 +1715,12 @@ const u32 b43_ntab_gainctl1[] = { | |||
1715 | 0x00030C01, 0x00020D01, 0x00010E00, 0x00000F00, | 1715 | 0x00030C01, 0x00020D01, 0x00010E00, 0x00000F00, |
1716 | }; | 1716 | }; |
1717 | 1717 | ||
1718 | const u32 b43_ntab_intlevel[] = { | 1718 | static const u32 b43_ntab_intlevel[] = { |
1719 | 0x00802070, 0x0671188D, 0x0A60192C, 0x0A300E46, | 1719 | 0x00802070, 0x0671188D, 0x0A60192C, 0x0A300E46, |
1720 | 0x00C1188D, 0x080024D2, 0x00000070, | 1720 | 0x00C1188D, 0x080024D2, 0x00000070, |
1721 | }; | 1721 | }; |
1722 | 1722 | ||
1723 | const u32 b43_ntab_iqlt0[] = { | 1723 | static const u32 b43_ntab_iqlt0[] = { |
1724 | 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, | 1724 | 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, |
1725 | 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, | 1725 | 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, |
1726 | 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, | 1726 | 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, |
@@ -1755,7 +1755,7 @@ const u32 b43_ntab_iqlt0[] = { | |||
1755 | 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, | 1755 | 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, |
1756 | }; | 1756 | }; |
1757 | 1757 | ||
1758 | const u32 b43_ntab_iqlt1[] = { | 1758 | static const u32 b43_ntab_iqlt1[] = { |
1759 | 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, | 1759 | 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, |
1760 | 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, | 1760 | 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, |
1761 | 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, | 1761 | 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, |
@@ -1790,7 +1790,7 @@ const u32 b43_ntab_iqlt1[] = { | |||
1790 | 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, | 1790 | 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, |
1791 | }; | 1791 | }; |
1792 | 1792 | ||
1793 | const u16 b43_ntab_loftlt0[] = { | 1793 | static const u16 b43_ntab_loftlt0[] = { |
1794 | 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, | 1794 | 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, |
1795 | 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, | 1795 | 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, |
1796 | 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, | 1796 | 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, |
@@ -1815,7 +1815,7 @@ const u16 b43_ntab_loftlt0[] = { | |||
1815 | 0x0002, 0x0103, | 1815 | 0x0002, 0x0103, |
1816 | }; | 1816 | }; |
1817 | 1817 | ||
1818 | const u16 b43_ntab_loftlt1[] = { | 1818 | static const u16 b43_ntab_loftlt1[] = { |
1819 | 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, | 1819 | 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, |
1820 | 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, | 1820 | 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, |
1821 | 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, | 1821 | 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, |
@@ -1840,7 +1840,7 @@ const u16 b43_ntab_loftlt1[] = { | |||
1840 | 0x0002, 0x0103, | 1840 | 0x0002, 0x0103, |
1841 | }; | 1841 | }; |
1842 | 1842 | ||
1843 | const u8 b43_ntab_mcs[] = { | 1843 | static const u8 b43_ntab_mcs[] = { |
1844 | 0x00, 0x08, 0x0A, 0x10, 0x12, 0x19, 0x1A, 0x1C, | 1844 | 0x00, 0x08, 0x0A, 0x10, 0x12, 0x19, 0x1A, 0x1C, |
1845 | 0x40, 0x48, 0x4A, 0x50, 0x52, 0x59, 0x5A, 0x5C, | 1845 | 0x40, 0x48, 0x4A, 0x50, 0x52, 0x59, 0x5A, 0x5C, |
1846 | 0x80, 0x88, 0x8A, 0x90, 0x92, 0x99, 0x9A, 0x9C, | 1846 | 0x80, 0x88, 0x8A, 0x90, 0x92, 0x99, 0x9A, 0x9C, |
@@ -1859,7 +1859,7 @@ const u8 b43_ntab_mcs[] = { | |||
1859 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 1859 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
1860 | }; | 1860 | }; |
1861 | 1861 | ||
1862 | const u32 b43_ntab_noisevar10[] = { | 1862 | static const u32 b43_ntab_noisevar10[] = { |
1863 | 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, | 1863 | 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, |
1864 | 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, | 1864 | 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, |
1865 | 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, | 1865 | 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, |
@@ -1926,7 +1926,7 @@ const u32 b43_ntab_noisevar10[] = { | |||
1926 | 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, | 1926 | 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, |
1927 | }; | 1927 | }; |
1928 | 1928 | ||
1929 | const u32 b43_ntab_noisevar11[] = { | 1929 | static const u32 b43_ntab_noisevar11[] = { |
1930 | 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, | 1930 | 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, |
1931 | 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, | 1931 | 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, |
1932 | 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, | 1932 | 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, |
@@ -1993,7 +1993,7 @@ const u32 b43_ntab_noisevar11[] = { | |||
1993 | 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, | 1993 | 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, |
1994 | }; | 1994 | }; |
1995 | 1995 | ||
1996 | const u16 b43_ntab_pilot[] = { | 1996 | static const u16 b43_ntab_pilot[] = { |
1997 | 0xFF08, 0xFF08, 0xFF08, 0xFF08, 0xFF08, 0xFF08, | 1997 | 0xFF08, 0xFF08, 0xFF08, 0xFF08, 0xFF08, 0xFF08, |
1998 | 0xFF08, 0xFF08, 0x80D5, 0x80D5, 0x80D5, 0x80D5, | 1998 | 0xFF08, 0xFF08, 0x80D5, 0x80D5, 0x80D5, 0x80D5, |
1999 | 0x80D5, 0x80D5, 0x80D5, 0x80D5, 0xFF0A, 0xFF82, | 1999 | 0x80D5, 0x80D5, 0x80D5, 0x80D5, 0xFF0A, 0xFF82, |
@@ -2011,12 +2011,12 @@ const u16 b43_ntab_pilot[] = { | |||
2011 | 0xF0A0, 0xF028, 0xFFFF, 0xFFFF, | 2011 | 0xF0A0, 0xF028, 0xFFFF, 0xFFFF, |
2012 | }; | 2012 | }; |
2013 | 2013 | ||
2014 | const u32 b43_ntab_pilotlt[] = { | 2014 | static const u32 b43_ntab_pilotlt[] = { |
2015 | 0x76540123, 0x62407351, 0x76543201, 0x76540213, | 2015 | 0x76540123, 0x62407351, 0x76543201, 0x76540213, |
2016 | 0x76540123, 0x76430521, | 2016 | 0x76540123, 0x76430521, |
2017 | }; | 2017 | }; |
2018 | 2018 | ||
2019 | const u32 b43_ntab_tdi20a0[] = { | 2019 | static const u32 b43_ntab_tdi20a0[] = { |
2020 | 0x00091226, 0x000A1429, 0x000B56AD, 0x000C58B0, | 2020 | 0x00091226, 0x000A1429, 0x000B56AD, 0x000C58B0, |
2021 | 0x000D5AB3, 0x000E9CB6, 0x000F9EBA, 0x0000C13D, | 2021 | 0x000D5AB3, 0x000E9CB6, 0x000F9EBA, 0x0000C13D, |
2022 | 0x00020301, 0x00030504, 0x00040708, 0x0005090B, | 2022 | 0x00020301, 0x00030504, 0x00040708, 0x0005090B, |
@@ -2033,7 +2033,7 @@ const u32 b43_ntab_tdi20a0[] = { | |||
2033 | 0x00000000, 0x00000000, 0x00000000, | 2033 | 0x00000000, 0x00000000, 0x00000000, |
2034 | }; | 2034 | }; |
2035 | 2035 | ||
2036 | const u32 b43_ntab_tdi20a1[] = { | 2036 | static const u32 b43_ntab_tdi20a1[] = { |
2037 | 0x00014B26, 0x00028D29, 0x000393AD, 0x00049630, | 2037 | 0x00014B26, 0x00028D29, 0x000393AD, 0x00049630, |
2038 | 0x0005D833, 0x0006DA36, 0x00099C3A, 0x000A9E3D, | 2038 | 0x0005D833, 0x0006DA36, 0x00099C3A, 0x000A9E3D, |
2039 | 0x000BC081, 0x000CC284, 0x000DC488, 0x000F068B, | 2039 | 0x000BC081, 0x000CC284, 0x000DC488, 0x000F068B, |
@@ -2050,7 +2050,7 @@ const u32 b43_ntab_tdi20a1[] = { | |||
2050 | 0x00000000, 0x00000000, 0x00000000, | 2050 | 0x00000000, 0x00000000, 0x00000000, |
2051 | }; | 2051 | }; |
2052 | 2052 | ||
2053 | const u32 b43_ntab_tdi40a0[] = { | 2053 | static const u32 b43_ntab_tdi40a0[] = { |
2054 | 0x0011A346, 0x00136CCF, 0x0014F5D9, 0x001641E2, | 2054 | 0x0011A346, 0x00136CCF, 0x0014F5D9, 0x001641E2, |
2055 | 0x0017CB6B, 0x00195475, 0x001B2383, 0x001CAD0C, | 2055 | 0x0017CB6B, 0x00195475, 0x001B2383, 0x001CAD0C, |
2056 | 0x001E7616, 0x0000821F, 0x00020BA8, 0x0003D4B2, | 2056 | 0x001E7616, 0x0000821F, 0x00020BA8, 0x0003D4B2, |
@@ -2081,7 +2081,7 @@ const u32 b43_ntab_tdi40a0[] = { | |||
2081 | 0x00000000, 0x00000000, | 2081 | 0x00000000, 0x00000000, |
2082 | }; | 2082 | }; |
2083 | 2083 | ||
2084 | const u32 b43_ntab_tdi40a1[] = { | 2084 | static const u32 b43_ntab_tdi40a1[] = { |
2085 | 0x001EDB36, 0x000129CA, 0x0002B353, 0x00047CDD, | 2085 | 0x001EDB36, 0x000129CA, 0x0002B353, 0x00047CDD, |
2086 | 0x0005C8E6, 0x000791EF, 0x00091BF9, 0x000AAA07, | 2086 | 0x0005C8E6, 0x000791EF, 0x00091BF9, 0x000AAA07, |
2087 | 0x000C3391, 0x000DFD1A, 0x00120923, 0x0013D22D, | 2087 | 0x000C3391, 0x000DFD1A, 0x00120923, 0x0013D22D, |
@@ -2112,7 +2112,7 @@ const u32 b43_ntab_tdi40a1[] = { | |||
2112 | 0x00000000, 0x00000000, | 2112 | 0x00000000, 0x00000000, |
2113 | }; | 2113 | }; |
2114 | 2114 | ||
2115 | const u32 b43_ntab_tdtrn[] = { | 2115 | static const u32 b43_ntab_tdtrn[] = { |
2116 | 0x061C061C, 0x0050EE68, 0xF592FE36, 0xFE5212F6, | 2116 | 0x061C061C, 0x0050EE68, 0xF592FE36, 0xFE5212F6, |
2117 | 0x00000C38, 0xFE5212F6, 0xF592FE36, 0x0050EE68, | 2117 | 0x00000C38, 0xFE5212F6, 0xF592FE36, 0x0050EE68, |
2118 | 0x061C061C, 0xEE680050, 0xFE36F592, 0x12F6FE52, | 2118 | 0x061C061C, 0xEE680050, 0xFE36F592, 0x12F6FE52, |
@@ -2291,7 +2291,7 @@ const u32 b43_ntab_tdtrn[] = { | |||
2291 | 0xFA58FC00, 0x0B64FC7E, 0x0800F7B6, 0x00F006BE, | 2291 | 0xFA58FC00, 0x0B64FC7E, 0x0800F7B6, 0x00F006BE, |
2292 | }; | 2292 | }; |
2293 | 2293 | ||
2294 | const u32 b43_ntab_tmap[] = { | 2294 | static const u32 b43_ntab_tmap[] = { |
2295 | 0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888, | 2295 | 0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888, |
2296 | 0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8, | 2296 | 0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8, |
2297 | 0xF1111110, 0x11111111, 0x11F11111, 0x00000111, | 2297 | 0xF1111110, 0x11111111, 0x11F11111, 0x00000111, |
@@ -2406,6 +2406,544 @@ const u32 b43_ntab_tmap[] = { | |||
2406 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, | 2406 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
2407 | }; | 2407 | }; |
2408 | 2408 | ||
2409 | const u32 b43_ntab_tx_gain_rev0_1_2[] = { | ||
2410 | 0x03cc2b44, 0x03cc2b42, 0x03cc2a44, 0x03cc2a42, | ||
2411 | 0x03cc2944, 0x03c82b44, 0x03c82b42, 0x03c82a44, | ||
2412 | 0x03c82a42, 0x03c82944, 0x03c82942, 0x03c82844, | ||
2413 | 0x03c82842, 0x03c42b44, 0x03c42b42, 0x03c42a44, | ||
2414 | 0x03c42a42, 0x03c42944, 0x03c42942, 0x03c42844, | ||
2415 | 0x03c42842, 0x03c42744, 0x03c42742, 0x03c42644, | ||
2416 | 0x03c42642, 0x03c42544, 0x03c42542, 0x03c42444, | ||
2417 | 0x03c42442, 0x03c02b44, 0x03c02b42, 0x03c02a44, | ||
2418 | 0x03c02a42, 0x03c02944, 0x03c02942, 0x03c02844, | ||
2419 | 0x03c02842, 0x03c02744, 0x03c02742, 0x03b02b44, | ||
2420 | 0x03b02b42, 0x03b02a44, 0x03b02a42, 0x03b02944, | ||
2421 | 0x03b02942, 0x03b02844, 0x03b02842, 0x03b02744, | ||
2422 | 0x03b02742, 0x03b02644, 0x03b02642, 0x03b02544, | ||
2423 | 0x03b02542, 0x03a02b44, 0x03a02b42, 0x03a02a44, | ||
2424 | 0x03a02a42, 0x03a02944, 0x03a02942, 0x03a02844, | ||
2425 | 0x03a02842, 0x03a02744, 0x03a02742, 0x03902b44, | ||
2426 | 0x03902b42, 0x03902a44, 0x03902a42, 0x03902944, | ||
2427 | 0x03902942, 0x03902844, 0x03902842, 0x03902744, | ||
2428 | 0x03902742, 0x03902644, 0x03902642, 0x03902544, | ||
2429 | 0x03902542, 0x03802b44, 0x03802b42, 0x03802a44, | ||
2430 | 0x03802a42, 0x03802944, 0x03802942, 0x03802844, | ||
2431 | 0x03802842, 0x03802744, 0x03802742, 0x03802644, | ||
2432 | 0x03802642, 0x03802544, 0x03802542, 0x03802444, | ||
2433 | 0x03802442, 0x03802344, 0x03802342, 0x03802244, | ||
2434 | 0x03802242, 0x03802144, 0x03802142, 0x03802044, | ||
2435 | 0x03802042, 0x03801f44, 0x03801f42, 0x03801e44, | ||
2436 | 0x03801e42, 0x03801d44, 0x03801d42, 0x03801c44, | ||
2437 | 0x03801c42, 0x03801b44, 0x03801b42, 0x03801a44, | ||
2438 | 0x03801a42, 0x03801944, 0x03801942, 0x03801844, | ||
2439 | 0x03801842, 0x03801744, 0x03801742, 0x03801644, | ||
2440 | 0x03801642, 0x03801544, 0x03801542, 0x03801444, | ||
2441 | 0x03801442, 0x03801344, 0x03801342, 0x00002b00, | ||
2442 | }; | ||
2443 | |||
2444 | const u32 b43_ntab_tx_gain_rev3plus_2ghz[] = { | ||
2445 | 0x1f410044, 0x1f410042, 0x1f410040, 0x1f41003e, | ||
2446 | 0x1f41003c, 0x1f41003b, 0x1f410039, 0x1f410037, | ||
2447 | 0x1e410044, 0x1e410042, 0x1e410040, 0x1e41003e, | ||
2448 | 0x1e41003c, 0x1e41003b, 0x1e410039, 0x1e410037, | ||
2449 | 0x1d410044, 0x1d410042, 0x1d410040, 0x1d41003e, | ||
2450 | 0x1d41003c, 0x1d41003b, 0x1d410039, 0x1d410037, | ||
2451 | 0x1c410044, 0x1c410042, 0x1c410040, 0x1c41003e, | ||
2452 | 0x1c41003c, 0x1c41003b, 0x1c410039, 0x1c410037, | ||
2453 | 0x1b410044, 0x1b410042, 0x1b410040, 0x1b41003e, | ||
2454 | 0x1b41003c, 0x1b41003b, 0x1b410039, 0x1b410037, | ||
2455 | 0x1a410044, 0x1a410042, 0x1a410040, 0x1a41003e, | ||
2456 | 0x1a41003c, 0x1a41003b, 0x1a410039, 0x1a410037, | ||
2457 | 0x19410044, 0x19410042, 0x19410040, 0x1941003e, | ||
2458 | 0x1941003c, 0x1941003b, 0x19410039, 0x19410037, | ||
2459 | 0x18410044, 0x18410042, 0x18410040, 0x1841003e, | ||
2460 | 0x1841003c, 0x1841003b, 0x18410039, 0x18410037, | ||
2461 | 0x17410044, 0x17410042, 0x17410040, 0x1741003e, | ||
2462 | 0x1741003c, 0x1741003b, 0x17410039, 0x17410037, | ||
2463 | 0x16410044, 0x16410042, 0x16410040, 0x1641003e, | ||
2464 | 0x1641003c, 0x1641003b, 0x16410039, 0x16410037, | ||
2465 | 0x15410044, 0x15410042, 0x15410040, 0x1541003e, | ||
2466 | 0x1541003c, 0x1541003b, 0x15410039, 0x15410037, | ||
2467 | 0x14410044, 0x14410042, 0x14410040, 0x1441003e, | ||
2468 | 0x1441003c, 0x1441003b, 0x14410039, 0x14410037, | ||
2469 | 0x13410044, 0x13410042, 0x13410040, 0x1341003e, | ||
2470 | 0x1341003c, 0x1341003b, 0x13410039, 0x13410037, | ||
2471 | 0x12410044, 0x12410042, 0x12410040, 0x1241003e, | ||
2472 | 0x1241003c, 0x1241003b, 0x12410039, 0x12410037, | ||
2473 | 0x11410044, 0x11410042, 0x11410040, 0x1141003e, | ||
2474 | 0x1141003c, 0x1141003b, 0x11410039, 0x11410037, | ||
2475 | 0x10410044, 0x10410042, 0x10410040, 0x1041003e, | ||
2476 | 0x1041003c, 0x1041003b, 0x10410039, 0x10410037, | ||
2477 | }; | ||
2478 | |||
2479 | const u32 b43_ntab_tx_gain_rev3_5ghz[] = { | ||
2480 | 0xcff70044, 0xcff70042, 0xcff70040, 0xcff7003e, | ||
2481 | 0xcff7003c, 0xcff7003b, 0xcff70039, 0xcff70037, | ||
2482 | 0xcef70044, 0xcef70042, 0xcef70040, 0xcef7003e, | ||
2483 | 0xcef7003c, 0xcef7003b, 0xcef70039, 0xcef70037, | ||
2484 | 0xcdf70044, 0xcdf70042, 0xcdf70040, 0xcdf7003e, | ||
2485 | 0xcdf7003c, 0xcdf7003b, 0xcdf70039, 0xcdf70037, | ||
2486 | 0xccf70044, 0xccf70042, 0xccf70040, 0xccf7003e, | ||
2487 | 0xccf7003c, 0xccf7003b, 0xccf70039, 0xccf70037, | ||
2488 | 0xcbf70044, 0xcbf70042, 0xcbf70040, 0xcbf7003e, | ||
2489 | 0xcbf7003c, 0xcbf7003b, 0xcbf70039, 0xcbf70037, | ||
2490 | 0xcaf70044, 0xcaf70042, 0xcaf70040, 0xcaf7003e, | ||
2491 | 0xcaf7003c, 0xcaf7003b, 0xcaf70039, 0xcaf70037, | ||
2492 | 0xc9f70044, 0xc9f70042, 0xc9f70040, 0xc9f7003e, | ||
2493 | 0xc9f7003c, 0xc9f7003b, 0xc9f70039, 0xc9f70037, | ||
2494 | 0xc8f70044, 0xc8f70042, 0xc8f70040, 0xc8f7003e, | ||
2495 | 0xc8f7003c, 0xc8f7003b, 0xc8f70039, 0xc8f70037, | ||
2496 | 0xc7f70044, 0xc7f70042, 0xc7f70040, 0xc7f7003e, | ||
2497 | 0xc7f7003c, 0xc7f7003b, 0xc7f70039, 0xc7f70037, | ||
2498 | 0xc6f70044, 0xc6f70042, 0xc6f70040, 0xc6f7003e, | ||
2499 | 0xc6f7003c, 0xc6f7003b, 0xc6f70039, 0xc6f70037, | ||
2500 | 0xc5f70044, 0xc5f70042, 0xc5f70040, 0xc5f7003e, | ||
2501 | 0xc5f7003c, 0xc5f7003b, 0xc5f70039, 0xc5f70037, | ||
2502 | 0xc4f70044, 0xc4f70042, 0xc4f70040, 0xc4f7003e, | ||
2503 | 0xc4f7003c, 0xc4f7003b, 0xc4f70039, 0xc4f70037, | ||
2504 | 0xc3f70044, 0xc3f70042, 0xc3f70040, 0xc3f7003e, | ||
2505 | 0xc3f7003c, 0xc3f7003b, 0xc3f70039, 0xc3f70037, | ||
2506 | 0xc2f70044, 0xc2f70042, 0xc2f70040, 0xc2f7003e, | ||
2507 | 0xc2f7003c, 0xc2f7003b, 0xc2f70039, 0xc2f70037, | ||
2508 | 0xc1f70044, 0xc1f70042, 0xc1f70040, 0xc1f7003e, | ||
2509 | 0xc1f7003c, 0xc1f7003b, 0xc1f70039, 0xc1f70037, | ||
2510 | 0xc0f70044, 0xc0f70042, 0xc0f70040, 0xc0f7003e, | ||
2511 | 0xc0f7003c, 0xc0f7003b, 0xc0f70039, 0xc0f70037, | ||
2512 | }; | ||
2513 | |||
2514 | const u32 b43_ntab_tx_gain_rev4_5ghz[] = { | ||
2515 | 0x2ff20044, 0x2ff20042, 0x2ff20040, 0x2ff2003e, | ||
2516 | 0x2ff2003c, 0x2ff2003b, 0x2ff20039, 0x2ff20037, | ||
2517 | 0x2ef20044, 0x2ef20042, 0x2ef20040, 0x2ef2003e, | ||
2518 | 0x2ef2003c, 0x2ef2003b, 0x2ef20039, 0x2ef20037, | ||
2519 | 0x2df20044, 0x2df20042, 0x2df20040, 0x2df2003e, | ||
2520 | 0x2df2003c, 0x2df2003b, 0x2df20039, 0x2df20037, | ||
2521 | 0x2cf20044, 0x2cf20042, 0x2cf20040, 0x2cf2003e, | ||
2522 | 0x2cf2003c, 0x2cf2003b, 0x2cf20039, 0x2cf20037, | ||
2523 | 0x2bf20044, 0x2bf20042, 0x2bf20040, 0x2bf2003e, | ||
2524 | 0x2bf2003c, 0x2bf2003b, 0x2bf20039, 0x2bf20037, | ||
2525 | 0x2af20044, 0x2af20042, 0x2af20040, 0x2af2003e, | ||
2526 | 0x2af2003c, 0x2af2003b, 0x2af20039, 0x2af20037, | ||
2527 | 0x29f20044, 0x29f20042, 0x29f20040, 0x29f2003e, | ||
2528 | 0x29f2003c, 0x29f2003b, 0x29f20039, 0x29f20037, | ||
2529 | 0x28f20044, 0x28f20042, 0x28f20040, 0x28f2003e, | ||
2530 | 0x28f2003c, 0x28f2003b, 0x28f20039, 0x28f20037, | ||
2531 | 0x27f20044, 0x27f20042, 0x27f20040, 0x27f2003e, | ||
2532 | 0x27f2003c, 0x27f2003b, 0x27f20039, 0x27f20037, | ||
2533 | 0x26f20044, 0x26f20042, 0x26f20040, 0x26f2003e, | ||
2534 | 0x26f2003c, 0x26f2003b, 0x26f20039, 0x26f20037, | ||
2535 | 0x25f20044, 0x25f20042, 0x25f20040, 0x25f2003e, | ||
2536 | 0x25f2003c, 0x25f2003b, 0x25f20039, 0x25f20037, | ||
2537 | 0x24f20044, 0x24f20042, 0x24f20040, 0x24f2003e, | ||
2538 | 0x24f2003c, 0x24f2003b, 0x24f20039, 0x24f20038, | ||
2539 | 0x23f20041, 0x23f20040, 0x23f2003f, 0x23f2003e, | ||
2540 | 0x23f2003c, 0x23f2003b, 0x23f20039, 0x23f20037, | ||
2541 | 0x22f20044, 0x22f20042, 0x22f20040, 0x22f2003e, | ||
2542 | 0x22f2003c, 0x22f2003b, 0x22f20039, 0x22f20037, | ||
2543 | 0x21f20044, 0x21f20042, 0x21f20040, 0x21f2003e, | ||
2544 | 0x21f2003c, 0x21f2003b, 0x21f20039, 0x21f20037, | ||
2545 | 0x20d20043, 0x20d20041, 0x20d2003e, 0x20d2003c, | ||
2546 | 0x20d2003a, 0x20d20038, 0x20d20036, 0x20d20034, | ||
2547 | }; | ||
2548 | |||
2549 | const u32 b43_ntab_tx_gain_rev5plus_5ghz[] = { | ||
2550 | 0x0f62004a, 0x0f620048, 0x0f620046, 0x0f620044, | ||
2551 | 0x0f620042, 0x0f620040, 0x0f62003e, 0x0f62003c, | ||
2552 | 0x0e620044, 0x0e620042, 0x0e620040, 0x0e62003e, | ||
2553 | 0x0e62003c, 0x0e62003d, 0x0e62003b, 0x0e62003a, | ||
2554 | 0x0d620043, 0x0d620041, 0x0d620040, 0x0d62003e, | ||
2555 | 0x0d62003d, 0x0d62003c, 0x0d62003b, 0x0d62003a, | ||
2556 | 0x0c620041, 0x0c620040, 0x0c62003f, 0x0c62003e, | ||
2557 | 0x0c62003c, 0x0c62003b, 0x0c620039, 0x0c620037, | ||
2558 | 0x0b620046, 0x0b620044, 0x0b620042, 0x0b620040, | ||
2559 | 0x0b62003e, 0x0b62003c, 0x0b62003b, 0x0b62003a, | ||
2560 | 0x0a620041, 0x0a620040, 0x0a62003e, 0x0a62003c, | ||
2561 | 0x0a62003b, 0x0a62003a, 0x0a620039, 0x0a620038, | ||
2562 | 0x0962003e, 0x0962003d, 0x0962003c, 0x0962003b, | ||
2563 | 0x09620039, 0x09620037, 0x09620035, 0x09620033, | ||
2564 | 0x08620044, 0x08620042, 0x08620040, 0x0862003e, | ||
2565 | 0x0862003c, 0x0862003b, 0x0862003a, 0x08620039, | ||
2566 | 0x07620043, 0x07620042, 0x07620040, 0x0762003f, | ||
2567 | 0x0762003d, 0x0762003b, 0x0762003a, 0x07620039, | ||
2568 | 0x0662003e, 0x0662003d, 0x0662003c, 0x0662003b, | ||
2569 | 0x06620039, 0x06620037, 0x06620035, 0x06620033, | ||
2570 | 0x05620046, 0x05620044, 0x05620042, 0x05620040, | ||
2571 | 0x0562003e, 0x0562003c, 0x0562003b, 0x05620039, | ||
2572 | 0x04620044, 0x04620042, 0x04620040, 0x0462003e, | ||
2573 | 0x0462003c, 0x0462003b, 0x04620039, 0x04620038, | ||
2574 | 0x0362003c, 0x0362003b, 0x0362003a, 0x03620039, | ||
2575 | 0x03620038, 0x03620037, 0x03620035, 0x03620033, | ||
2576 | 0x0262004c, 0x0262004a, 0x02620048, 0x02620047, | ||
2577 | 0x02620046, 0x02620044, 0x02620043, 0x02620042, | ||
2578 | 0x0162004a, 0x01620048, 0x01620046, 0x01620044, | ||
2579 | 0x01620043, 0x01620042, 0x01620041, 0x01620040, | ||
2580 | 0x00620042, 0x00620040, 0x0062003e, 0x0062003c, | ||
2581 | 0x0062003b, 0x00620039, 0x00620037, 0x00620035, | ||
2582 | }; | ||
2583 | |||
2584 | const u32 txpwrctrl_tx_gain_ipa[] = { | ||
2585 | 0x5ff7002d, 0x5ff7002b, 0x5ff7002a, 0x5ff70029, | ||
2586 | 0x5ff70028, 0x5ff70027, 0x5ff70026, 0x5ff70025, | ||
2587 | 0x5ef7002d, 0x5ef7002b, 0x5ef7002a, 0x5ef70029, | ||
2588 | 0x5ef70028, 0x5ef70027, 0x5ef70026, 0x5ef70025, | ||
2589 | 0x5df7002d, 0x5df7002b, 0x5df7002a, 0x5df70029, | ||
2590 | 0x5df70028, 0x5df70027, 0x5df70026, 0x5df70025, | ||
2591 | 0x5cf7002d, 0x5cf7002b, 0x5cf7002a, 0x5cf70029, | ||
2592 | 0x5cf70028, 0x5cf70027, 0x5cf70026, 0x5cf70025, | ||
2593 | 0x5bf7002d, 0x5bf7002b, 0x5bf7002a, 0x5bf70029, | ||
2594 | 0x5bf70028, 0x5bf70027, 0x5bf70026, 0x5bf70025, | ||
2595 | 0x5af7002d, 0x5af7002b, 0x5af7002a, 0x5af70029, | ||
2596 | 0x5af70028, 0x5af70027, 0x5af70026, 0x5af70025, | ||
2597 | 0x59f7002d, 0x59f7002b, 0x59f7002a, 0x59f70029, | ||
2598 | 0x59f70028, 0x59f70027, 0x59f70026, 0x59f70025, | ||
2599 | 0x58f7002d, 0x58f7002b, 0x58f7002a, 0x58f70029, | ||
2600 | 0x58f70028, 0x58f70027, 0x58f70026, 0x58f70025, | ||
2601 | 0x57f7002d, 0x57f7002b, 0x57f7002a, 0x57f70029, | ||
2602 | 0x57f70028, 0x57f70027, 0x57f70026, 0x57f70025, | ||
2603 | 0x56f7002d, 0x56f7002b, 0x56f7002a, 0x56f70029, | ||
2604 | 0x56f70028, 0x56f70027, 0x56f70026, 0x56f70025, | ||
2605 | 0x55f7002d, 0x55f7002b, 0x55f7002a, 0x55f70029, | ||
2606 | 0x55f70028, 0x55f70027, 0x55f70026, 0x55f70025, | ||
2607 | 0x54f7002d, 0x54f7002b, 0x54f7002a, 0x54f70029, | ||
2608 | 0x54f70028, 0x54f70027, 0x54f70026, 0x54f70025, | ||
2609 | 0x53f7002d, 0x53f7002b, 0x53f7002a, 0x53f70029, | ||
2610 | 0x53f70028, 0x53f70027, 0x53f70026, 0x53f70025, | ||
2611 | 0x52f7002d, 0x52f7002b, 0x52f7002a, 0x52f70029, | ||
2612 | 0x52f70028, 0x52f70027, 0x52f70026, 0x52f70025, | ||
2613 | 0x51f7002d, 0x51f7002b, 0x51f7002a, 0x51f70029, | ||
2614 | 0x51f70028, 0x51f70027, 0x51f70026, 0x51f70025, | ||
2615 | 0x50f7002d, 0x50f7002b, 0x50f7002a, 0x50f70029, | ||
2616 | 0x50f70028, 0x50f70027, 0x50f70026, 0x50f70025, | ||
2617 | }; | ||
2618 | |||
2619 | const u32 txpwrctrl_tx_gain_ipa_rev5[] = { | ||
2620 | 0x1ff7002d, 0x1ff7002b, 0x1ff7002a, 0x1ff70029, | ||
2621 | 0x1ff70028, 0x1ff70027, 0x1ff70026, 0x1ff70025, | ||
2622 | 0x1ef7002d, 0x1ef7002b, 0x1ef7002a, 0x1ef70029, | ||
2623 | 0x1ef70028, 0x1ef70027, 0x1ef70026, 0x1ef70025, | ||
2624 | 0x1df7002d, 0x1df7002b, 0x1df7002a, 0x1df70029, | ||
2625 | 0x1df70028, 0x1df70027, 0x1df70026, 0x1df70025, | ||
2626 | 0x1cf7002d, 0x1cf7002b, 0x1cf7002a, 0x1cf70029, | ||
2627 | 0x1cf70028, 0x1cf70027, 0x1cf70026, 0x1cf70025, | ||
2628 | 0x1bf7002d, 0x1bf7002b, 0x1bf7002a, 0x1bf70029, | ||
2629 | 0x1bf70028, 0x1bf70027, 0x1bf70026, 0x1bf70025, | ||
2630 | 0x1af7002d, 0x1af7002b, 0x1af7002a, 0x1af70029, | ||
2631 | 0x1af70028, 0x1af70027, 0x1af70026, 0x1af70025, | ||
2632 | 0x19f7002d, 0x19f7002b, 0x19f7002a, 0x19f70029, | ||
2633 | 0x19f70028, 0x19f70027, 0x19f70026, 0x19f70025, | ||
2634 | 0x18f7002d, 0x18f7002b, 0x18f7002a, 0x18f70029, | ||
2635 | 0x18f70028, 0x18f70027, 0x18f70026, 0x18f70025, | ||
2636 | 0x17f7002d, 0x17f7002b, 0x17f7002a, 0x17f70029, | ||
2637 | 0x17f70028, 0x17f70027, 0x17f70026, 0x17f70025, | ||
2638 | 0x16f7002d, 0x16f7002b, 0x16f7002a, 0x16f70029, | ||
2639 | 0x16f70028, 0x16f70027, 0x16f70026, 0x16f70025, | ||
2640 | 0x15f7002d, 0x15f7002b, 0x15f7002a, 0x15f70029, | ||
2641 | 0x15f70028, 0x15f70027, 0x15f70026, 0x15f70025, | ||
2642 | 0x14f7002d, 0x14f7002b, 0x14f7002a, 0x14f70029, | ||
2643 | 0x14f70028, 0x14f70027, 0x14f70026, 0x14f70025, | ||
2644 | 0x13f7002d, 0x13f7002b, 0x13f7002a, 0x13f70029, | ||
2645 | 0x13f70028, 0x13f70027, 0x13f70026, 0x13f70025, | ||
2646 | 0x12f7002d, 0x12f7002b, 0x12f7002a, 0x12f70029, | ||
2647 | 0x12f70028, 0x12f70027, 0x12f70026, 0x12f70025, | ||
2648 | 0x11f7002d, 0x11f7002b, 0x11f7002a, 0x11f70029, | ||
2649 | 0x11f70028, 0x11f70027, 0x11f70026, 0x11f70025, | ||
2650 | 0x10f7002d, 0x10f7002b, 0x10f7002a, 0x10f70029, | ||
2651 | 0x10f70028, 0x10f70027, 0x10f70026, 0x10f70025, | ||
2652 | }; | ||
2653 | |||
2654 | const u32 txpwrctrl_tx_gain_ipa_rev6[] = { | ||
2655 | 0x0ff7002d, 0x0ff7002b, 0x0ff7002a, 0x0ff70029, | ||
2656 | 0x0ff70028, 0x0ff70027, 0x0ff70026, 0x0ff70025, | ||
2657 | 0x0ef7002d, 0x0ef7002b, 0x0ef7002a, 0x0ef70029, | ||
2658 | 0x0ef70028, 0x0ef70027, 0x0ef70026, 0x0ef70025, | ||
2659 | 0x0df7002d, 0x0df7002b, 0x0df7002a, 0x0df70029, | ||
2660 | 0x0df70028, 0x0df70027, 0x0df70026, 0x0df70025, | ||
2661 | 0x0cf7002d, 0x0cf7002b, 0x0cf7002a, 0x0cf70029, | ||
2662 | 0x0cf70028, 0x0cf70027, 0x0cf70026, 0x0cf70025, | ||
2663 | 0x0bf7002d, 0x0bf7002b, 0x0bf7002a, 0x0bf70029, | ||
2664 | 0x0bf70028, 0x0bf70027, 0x0bf70026, 0x0bf70025, | ||
2665 | 0x0af7002d, 0x0af7002b, 0x0af7002a, 0x0af70029, | ||
2666 | 0x0af70028, 0x0af70027, 0x0af70026, 0x0af70025, | ||
2667 | 0x09f7002d, 0x09f7002b, 0x09f7002a, 0x09f70029, | ||
2668 | 0x09f70028, 0x09f70027, 0x09f70026, 0x09f70025, | ||
2669 | 0x08f7002d, 0x08f7002b, 0x08f7002a, 0x08f70029, | ||
2670 | 0x08f70028, 0x08f70027, 0x08f70026, 0x08f70025, | ||
2671 | 0x07f7002d, 0x07f7002b, 0x07f7002a, 0x07f70029, | ||
2672 | 0x07f70028, 0x07f70027, 0x07f70026, 0x07f70025, | ||
2673 | 0x06f7002d, 0x06f7002b, 0x06f7002a, 0x06f70029, | ||
2674 | 0x06f70028, 0x06f70027, 0x06f70026, 0x06f70025, | ||
2675 | 0x05f7002d, 0x05f7002b, 0x05f7002a, 0x05f70029, | ||
2676 | 0x05f70028, 0x05f70027, 0x05f70026, 0x05f70025, | ||
2677 | 0x04f7002d, 0x04f7002b, 0x04f7002a, 0x04f70029, | ||
2678 | 0x04f70028, 0x04f70027, 0x04f70026, 0x04f70025, | ||
2679 | 0x03f7002d, 0x03f7002b, 0x03f7002a, 0x03f70029, | ||
2680 | 0x03f70028, 0x03f70027, 0x03f70026, 0x03f70025, | ||
2681 | 0x02f7002d, 0x02f7002b, 0x02f7002a, 0x02f70029, | ||
2682 | 0x02f70028, 0x02f70027, 0x02f70026, 0x02f70025, | ||
2683 | 0x01f7002d, 0x01f7002b, 0x01f7002a, 0x01f70029, | ||
2684 | 0x01f70028, 0x01f70027, 0x01f70026, 0x01f70025, | ||
2685 | 0x00f7002d, 0x00f7002b, 0x00f7002a, 0x00f70029, | ||
2686 | 0x00f70028, 0x00f70027, 0x00f70026, 0x00f70025, | ||
2687 | }; | ||
2688 | |||
2689 | const u32 txpwrctrl_tx_gain_ipa_5g[] = { | ||
2690 | 0x7ff70035, 0x7ff70033, 0x7ff70032, 0x7ff70031, | ||
2691 | 0x7ff7002f, 0x7ff7002e, 0x7ff7002d, 0x7ff7002b, | ||
2692 | 0x7ff7002a, 0x7ff70029, 0x7ff70028, 0x7ff70027, | ||
2693 | 0x7ff70026, 0x7ff70024, 0x7ff70023, 0x7ff70022, | ||
2694 | 0x7ef70028, 0x7ef70027, 0x7ef70026, 0x7ef70025, | ||
2695 | 0x7ef70024, 0x7ef70023, 0x7df70028, 0x7df70027, | ||
2696 | 0x7df70026, 0x7df70025, 0x7df70024, 0x7df70023, | ||
2697 | 0x7df70022, 0x7cf70029, 0x7cf70028, 0x7cf70027, | ||
2698 | 0x7cf70026, 0x7cf70025, 0x7cf70023, 0x7cf70022, | ||
2699 | 0x7bf70029, 0x7bf70028, 0x7bf70026, 0x7bf70025, | ||
2700 | 0x7bf70024, 0x7bf70023, 0x7bf70022, 0x7bf70021, | ||
2701 | 0x7af70029, 0x7af70028, 0x7af70027, 0x7af70026, | ||
2702 | 0x7af70025, 0x7af70024, 0x7af70023, 0x7af70022, | ||
2703 | 0x79f70029, 0x79f70028, 0x79f70027, 0x79f70026, | ||
2704 | 0x79f70025, 0x79f70024, 0x79f70023, 0x79f70022, | ||
2705 | 0x78f70029, 0x78f70028, 0x78f70027, 0x78f70026, | ||
2706 | 0x78f70025, 0x78f70024, 0x78f70023, 0x78f70022, | ||
2707 | 0x77f70029, 0x77f70028, 0x77f70027, 0x77f70026, | ||
2708 | 0x77f70025, 0x77f70024, 0x77f70023, 0x77f70022, | ||
2709 | 0x76f70029, 0x76f70028, 0x76f70027, 0x76f70026, | ||
2710 | 0x76f70024, 0x76f70023, 0x76f70022, 0x76f70021, | ||
2711 | 0x75f70029, 0x75f70028, 0x75f70027, 0x75f70026, | ||
2712 | 0x75f70025, 0x75f70024, 0x75f70023, 0x74f70029, | ||
2713 | 0x74f70028, 0x74f70026, 0x74f70025, 0x74f70024, | ||
2714 | 0x74f70023, 0x74f70022, 0x73f70029, 0x73f70027, | ||
2715 | 0x73f70026, 0x73f70025, 0x73f70024, 0x73f70023, | ||
2716 | 0x73f70022, 0x72f70028, 0x72f70027, 0x72f70026, | ||
2717 | 0x72f70025, 0x72f70024, 0x72f70023, 0x72f70022, | ||
2718 | 0x71f70028, 0x71f70027, 0x71f70026, 0x71f70025, | ||
2719 | 0x71f70024, 0x71f70023, 0x70f70028, 0x70f70027, | ||
2720 | 0x70f70026, 0x70f70024, 0x70f70023, 0x70f70022, | ||
2721 | 0x70f70021, 0x70f70020, 0x70f70020, 0x70f7001f, | ||
2722 | }; | ||
2723 | |||
2724 | const u16 tbl_iqcal_gainparams[2][9][8] = { | ||
2725 | { | ||
2726 | { 0x000, 0, 0, 2, 0x69, 0x69, 0x69, 0x69 }, | ||
2727 | { 0x700, 7, 0, 0, 0x69, 0x69, 0x69, 0x69 }, | ||
2728 | { 0x710, 7, 1, 0, 0x68, 0x68, 0x68, 0x68 }, | ||
2729 | { 0x720, 7, 2, 0, 0x67, 0x67, 0x67, 0x67 }, | ||
2730 | { 0x730, 7, 3, 0, 0x66, 0x66, 0x66, 0x66 }, | ||
2731 | { 0x740, 7, 4, 0, 0x65, 0x65, 0x65, 0x65 }, | ||
2732 | { 0x741, 7, 4, 1, 0x65, 0x65, 0x65, 0x65 }, | ||
2733 | { 0x742, 7, 4, 2, 0x65, 0x65, 0x65, 0x65 }, | ||
2734 | { 0x743, 7, 4, 3, 0x65, 0x65, 0x65, 0x65 } | ||
2735 | }, | ||
2736 | { | ||
2737 | { 0x000, 7, 0, 0, 0x79, 0x79, 0x79, 0x79 }, | ||
2738 | { 0x700, 7, 0, 0, 0x79, 0x79, 0x79, 0x79 }, | ||
2739 | { 0x710, 7, 1, 0, 0x79, 0x79, 0x79, 0x79 }, | ||
2740 | { 0x720, 7, 2, 0, 0x78, 0x78, 0x78, 0x78 }, | ||
2741 | { 0x730, 7, 3, 0, 0x78, 0x78, 0x78, 0x78 }, | ||
2742 | { 0x740, 7, 4, 0, 0x78, 0x78, 0x78, 0x78 }, | ||
2743 | { 0x741, 7, 4, 1, 0x78, 0x78, 0x78, 0x78 }, | ||
2744 | { 0x742, 7, 4, 2, 0x78, 0x78, 0x78, 0x78 }, | ||
2745 | { 0x743, 7, 4, 3, 0x78, 0x78, 0x78, 0x78 } | ||
2746 | } | ||
2747 | }; | ||
2748 | |||
2749 | const struct nphy_txiqcal_ladder ladder_lo[] = { | ||
2750 | { 3, 0 }, | ||
2751 | { 4, 0 }, | ||
2752 | { 6, 0 }, | ||
2753 | { 9, 0 }, | ||
2754 | { 13, 0 }, | ||
2755 | { 18, 0 }, | ||
2756 | { 25, 0 }, | ||
2757 | { 25, 1 }, | ||
2758 | { 25, 2 }, | ||
2759 | { 25, 3 }, | ||
2760 | { 25, 4 }, | ||
2761 | { 25, 5 }, | ||
2762 | { 25, 6 }, | ||
2763 | { 25, 7 }, | ||
2764 | { 35, 7 }, | ||
2765 | { 50, 7 }, | ||
2766 | { 71, 7 }, | ||
2767 | { 100, 7 } | ||
2768 | }; | ||
2769 | |||
2770 | const struct nphy_txiqcal_ladder ladder_iq[] = { | ||
2771 | { 3, 0 }, | ||
2772 | { 4, 0 }, | ||
2773 | { 6, 0 }, | ||
2774 | { 9, 0 }, | ||
2775 | { 13, 0 }, | ||
2776 | { 18, 0 }, | ||
2777 | { 25, 0 }, | ||
2778 | { 35, 0 }, | ||
2779 | { 50, 0 }, | ||
2780 | { 71, 0 }, | ||
2781 | { 100, 0 }, | ||
2782 | { 100, 1 }, | ||
2783 | { 100, 2 }, | ||
2784 | { 100, 3 }, | ||
2785 | { 100, 4 }, | ||
2786 | { 100, 5 }, | ||
2787 | { 100, 6 }, | ||
2788 | { 100, 7 } | ||
2789 | }; | ||
2790 | |||
2791 | const u16 loscale[] = { | ||
2792 | 256, 256, 271, 271, | ||
2793 | 287, 256, 256, 271, | ||
2794 | 271, 287, 287, 304, | ||
2795 | 304, 256, 256, 271, | ||
2796 | 271, 287, 287, 304, | ||
2797 | 304, 322, 322, 341, | ||
2798 | 341, 362, 362, 383, | ||
2799 | 383, 256, 256, 271, | ||
2800 | 271, 287, 287, 304, | ||
2801 | 304, 322, 322, 256, | ||
2802 | 256, 271, 271, 287, | ||
2803 | 287, 304, 304, 322, | ||
2804 | 322, 341, 341, 362, | ||
2805 | 362, 256, 256, 271, | ||
2806 | 271, 287, 287, 304, | ||
2807 | 304, 322, 322, 256, | ||
2808 | 256, 271, 271, 287, | ||
2809 | 287, 304, 304, 322, | ||
2810 | 322, 341, 341, 362, | ||
2811 | 362, 256, 256, 271, | ||
2812 | 271, 287, 287, 304, | ||
2813 | 304, 322, 322, 341, | ||
2814 | 341, 362, 362, 383, | ||
2815 | 383, 406, 406, 430, | ||
2816 | 430, 455, 455, 482, | ||
2817 | 482, 511, 511, 541, | ||
2818 | 541, 573, 573, 607, | ||
2819 | 607, 643, 643, 681, | ||
2820 | 681, 722, 722, 764, | ||
2821 | 764, 810, 810, 858, | ||
2822 | 858, 908, 908, 962, | ||
2823 | 962, 1019, 1019, 256 | ||
2824 | }; | ||
2825 | |||
2826 | const u16 tbl_tx_iqlo_cal_loft_ladder_40[] = { | ||
2827 | 0x0200, 0x0300, 0x0400, 0x0700, | ||
2828 | 0x0900, 0x0c00, 0x1200, 0x1201, | ||
2829 | 0x1202, 0x1203, 0x1204, 0x1205, | ||
2830 | 0x1206, 0x1207, 0x1907, 0x2307, | ||
2831 | 0x3207, 0x4707 | ||
2832 | }; | ||
2833 | |||
2834 | const u16 tbl_tx_iqlo_cal_loft_ladder_20[] = { | ||
2835 | 0x0300, 0x0500, 0x0700, 0x0900, | ||
2836 | 0x0d00, 0x1100, 0x1900, 0x1901, | ||
2837 | 0x1902, 0x1903, 0x1904, 0x1905, | ||
2838 | 0x1906, 0x1907, 0x2407, 0x3207, | ||
2839 | 0x4607, 0x6407 | ||
2840 | }; | ||
2841 | |||
2842 | const u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = { | ||
2843 | 0x0100, 0x0200, 0x0400, 0x0700, | ||
2844 | 0x0900, 0x0c00, 0x1200, 0x1900, | ||
2845 | 0x2300, 0x3200, 0x4700, 0x4701, | ||
2846 | 0x4702, 0x4703, 0x4704, 0x4705, | ||
2847 | 0x4706, 0x4707 | ||
2848 | }; | ||
2849 | |||
2850 | const u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = { | ||
2851 | 0x0200, 0x0300, 0x0600, 0x0900, | ||
2852 | 0x0d00, 0x1100, 0x1900, 0x2400, | ||
2853 | 0x3200, 0x4600, 0x6400, 0x6401, | ||
2854 | 0x6402, 0x6403, 0x6404, 0x6405, | ||
2855 | 0x6406, 0x6407 | ||
2856 | }; | ||
2857 | |||
2858 | const u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3] = { }; | ||
2859 | |||
2860 | const u16 tbl_tx_iqlo_cal_startcoefs[B43_NTAB_TX_IQLO_CAL_STARTCOEFS] = { }; | ||
2861 | |||
2862 | const u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = { | ||
2863 | 0x8423, 0x8323, 0x8073, 0x8256, | ||
2864 | 0x8045, 0x8223, 0x9423, 0x9323, | ||
2865 | 0x9073, 0x9256, 0x9045, 0x9223 | ||
2866 | }; | ||
2867 | |||
2868 | const u16 tbl_tx_iqlo_cal_cmds_recal[] = { | ||
2869 | 0x8101, 0x8253, 0x8053, 0x8234, | ||
2870 | 0x8034, 0x9101, 0x9253, 0x9053, | ||
2871 | 0x9234, 0x9034 | ||
2872 | }; | ||
2873 | |||
2874 | const u16 tbl_tx_iqlo_cal_cmds_fullcal[] = { | ||
2875 | 0x8123, 0x8264, 0x8086, 0x8245, | ||
2876 | 0x8056, 0x9123, 0x9264, 0x9086, | ||
2877 | 0x9245, 0x9056 | ||
2878 | }; | ||
2879 | |||
2880 | const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = { | ||
2881 | 0x8434, 0x8334, 0x8084, 0x8267, | ||
2882 | 0x8056, 0x8234, 0x9434, 0x9334, | ||
2883 | 0x9084, 0x9267, 0x9056, 0x9234 | ||
2884 | }; | ||
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 | |||
2409 | static inline void assert_ntab_array_sizes(void) | 2947 | static inline void assert_ntab_array_sizes(void) |
2410 | { | 2948 | { |
2411 | #undef check | 2949 | #undef check |
@@ -2442,6 +2980,72 @@ static inline void assert_ntab_array_sizes(void) | |||
2442 | #undef check | 2980 | #undef check |
2443 | } | 2981 | } |
2444 | 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 | |||
2445 | 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) |
2446 | { | 3050 | { |
2447 | u32 type; | 3051 | u32 type; |
@@ -2474,3 +3078,91 @@ void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value) | |||
2474 | /* Some compiletime assertions... */ | 3078 | /* Some compiletime assertions... */ |
2475 | assert_ntab_array_sizes(); | 3079 | assert_ntab_array_sizes(); |
2476 | } | 3080 | } |
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 | |||
3122 | #define ntab_upload(dev, offset, data) do { \ | ||
3123 | unsigned int i; \ | ||
3124 | for (i = 0; i < (offset##_SIZE); i++) \ | ||
3125 | b43_ntab_write(dev, (offset) + i, (data)[i]); \ | ||
3126 | } while (0) | ||
3127 | |||
3128 | void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev) | ||
3129 | { | ||
3130 | /* Static tables */ | ||
3131 | ntab_upload(dev, B43_NTAB_FRAMESTRUCT, b43_ntab_framestruct); | ||
3132 | ntab_upload(dev, B43_NTAB_FRAMELT, b43_ntab_framelookup); | ||
3133 | ntab_upload(dev, B43_NTAB_TMAP, b43_ntab_tmap); | ||
3134 | ntab_upload(dev, B43_NTAB_TDTRN, b43_ntab_tdtrn); | ||
3135 | ntab_upload(dev, B43_NTAB_INTLEVEL, b43_ntab_intlevel); | ||
3136 | ntab_upload(dev, B43_NTAB_PILOT, b43_ntab_pilot); | ||
3137 | ntab_upload(dev, B43_NTAB_PILOTLT, b43_ntab_pilotlt); | ||
3138 | ntab_upload(dev, B43_NTAB_TDI20A0, b43_ntab_tdi20a0); | ||
3139 | ntab_upload(dev, B43_NTAB_TDI20A1, b43_ntab_tdi20a1); | ||
3140 | ntab_upload(dev, B43_NTAB_TDI40A0, b43_ntab_tdi40a0); | ||
3141 | ntab_upload(dev, B43_NTAB_TDI40A1, b43_ntab_tdi40a1); | ||
3142 | ntab_upload(dev, B43_NTAB_BDI, b43_ntab_bdi); | ||
3143 | ntab_upload(dev, B43_NTAB_CHANEST, b43_ntab_channelest); | ||
3144 | ntab_upload(dev, B43_NTAB_MCS, b43_ntab_mcs); | ||
3145 | |||
3146 | /* Volatile tables */ | ||
3147 | ntab_upload(dev, B43_NTAB_NOISEVAR10, b43_ntab_noisevar10); | ||
3148 | ntab_upload(dev, B43_NTAB_NOISEVAR11, b43_ntab_noisevar11); | ||
3149 | ntab_upload(dev, B43_NTAB_C0_ESTPLT, b43_ntab_estimatepowerlt0); | ||
3150 | ntab_upload(dev, B43_NTAB_C1_ESTPLT, b43_ntab_estimatepowerlt1); | ||
3151 | ntab_upload(dev, B43_NTAB_C0_ADJPLT, b43_ntab_adjustpower0); | ||
3152 | ntab_upload(dev, B43_NTAB_C1_ADJPLT, b43_ntab_adjustpower1); | ||
3153 | ntab_upload(dev, B43_NTAB_C0_GAINCTL, b43_ntab_gainctl0); | ||
3154 | ntab_upload(dev, B43_NTAB_C1_GAINCTL, b43_ntab_gainctl1); | ||
3155 | ntab_upload(dev, B43_NTAB_C0_IQLT, b43_ntab_iqlt0); | ||
3156 | ntab_upload(dev, B43_NTAB_C1_IQLT, b43_ntab_iqlt1); | ||
3157 | ntab_upload(dev, B43_NTAB_C0_LOFEEDTH, b43_ntab_loftlt0); | ||
3158 | ntab_upload(dev, B43_NTAB_C1_LOFEEDTH, b43_ntab_loftlt1); | ||
3159 | } | ||
3160 | |||
3161 | void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev) | ||
3162 | { | ||
3163 | /* Static tables */ | ||
3164 | /* TODO */ | ||
3165 | |||
3166 | /* Volatile tables */ | ||
3167 | /* TODO */ | ||
3168 | } | ||
diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h index 4d498b053ec7..9c1c6ecd3672 100644 --- a/drivers/net/wireless/b43/tables_nphy.h +++ b/drivers/net/wireless/b43/tables_nphy.h | |||
@@ -46,6 +46,27 @@ struct b43_nphy_channeltab_entry { | |||
46 | 46 | ||
47 | struct b43_wldev; | 47 | struct b43_wldev; |
48 | 48 | ||
49 | struct nphy_txiqcal_ladder { | ||
50 | u8 percent; | ||
51 | u8 g_env; | ||
52 | }; | ||
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 | |||
49 | /* Upload the default register value table. | 70 | /* Upload the default register value table. |
50 | * 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 |
51 | * 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 |
@@ -126,34 +147,57 @@ b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel); | |||
126 | #define B43_NTAB_C1_LOFEEDTH B43_NTAB16(0x1B, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 1 */ | 147 | #define B43_NTAB_C1_LOFEEDTH B43_NTAB16(0x1B, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 1 */ |
127 | #define B43_NTAB_C1_LOFEEDTH_SIZE 128 | 148 | #define B43_NTAB_C1_LOFEEDTH_SIZE 128 |
128 | 149 | ||
150 | #define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_40_SIZE 18 | ||
151 | #define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_20_SIZE 18 | ||
152 | #define B43_NTAB_TX_IQLO_CAL_IQIMB_LADDER_40_SIZE 18 | ||
153 | #define B43_NTAB_TX_IQLO_CAL_IQIMB_LADDER_20_SIZE 18 | ||
154 | #define B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3 11 | ||
155 | #define B43_NTAB_TX_IQLO_CAL_STARTCOEFS 9 | ||
156 | #define B43_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3 12 | ||
157 | #define B43_NTAB_TX_IQLO_CAL_CMDS_RECAL 10 | ||
158 | #define B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL 10 | ||
159 | #define B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3 12 | ||
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); | ||
129 | 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); |
130 | 165 | void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset, | |
131 | extern const u8 b43_ntab_adjustpower0[]; | 166 | unsigned int nr_elements, const void *_data); |
132 | extern const u8 b43_ntab_adjustpower1[]; | 167 | |
133 | extern const u16 b43_ntab_bdi[]; | 168 | void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev); |
134 | extern const u32 b43_ntab_channelest[]; | 169 | void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev); |
135 | extern const u8 b43_ntab_estimatepowerlt0[]; | 170 | |
136 | extern const u8 b43_ntab_estimatepowerlt1[]; | 171 | extern const u32 b43_ntab_tx_gain_rev0_1_2[]; |
137 | extern const u8 b43_ntab_framelookup[]; | 172 | extern const u32 b43_ntab_tx_gain_rev3plus_2ghz[]; |
138 | extern const u32 b43_ntab_framestruct[]; | 173 | extern const u32 b43_ntab_tx_gain_rev3_5ghz[]; |
139 | extern const u32 b43_ntab_gainctl0[]; | 174 | extern const u32 b43_ntab_tx_gain_rev4_5ghz[]; |
140 | extern const u32 b43_ntab_gainctl1[]; | 175 | extern const u32 b43_ntab_tx_gain_rev5plus_5ghz[]; |
141 | extern const u32 b43_ntab_intlevel[]; | 176 | |
142 | extern const u32 b43_ntab_iqlt0[]; | 177 | extern const u32 txpwrctrl_tx_gain_ipa[]; |
143 | extern const u32 b43_ntab_iqlt1[]; | 178 | extern const u32 txpwrctrl_tx_gain_ipa_rev5[]; |
144 | extern const u16 b43_ntab_loftlt0[]; | 179 | extern const u32 txpwrctrl_tx_gain_ipa_rev6[]; |
145 | extern const u16 b43_ntab_loftlt1[]; | 180 | extern const u32 txpwrctrl_tx_gain_ipa_5g[]; |
146 | extern const u8 b43_ntab_mcs[]; | 181 | extern const u16 tbl_iqcal_gainparams[2][9][8]; |
147 | extern const u32 b43_ntab_noisevar10[]; | 182 | extern const struct nphy_txiqcal_ladder ladder_lo[]; |
148 | extern const u32 b43_ntab_noisevar11[]; | 183 | extern const struct nphy_txiqcal_ladder ladder_iq[]; |
149 | extern const u16 b43_ntab_pilot[]; | 184 | extern const u16 loscale[]; |
150 | extern const u32 b43_ntab_pilotlt[]; | 185 | |
151 | extern const u32 b43_ntab_tdi20a0[]; | 186 | extern const u16 tbl_tx_iqlo_cal_loft_ladder_40[]; |
152 | extern const u32 b43_ntab_tdi20a1[]; | 187 | extern const u16 tbl_tx_iqlo_cal_loft_ladder_20[]; |
153 | extern const u32 b43_ntab_tdi40a0[]; | 188 | extern const u16 tbl_tx_iqlo_cal_iqimb_ladder_40[]; |
154 | extern const u32 b43_ntab_tdi40a1[]; | 189 | extern const u16 tbl_tx_iqlo_cal_iqimb_ladder_20[]; |
155 | extern const u32 b43_ntab_tdtrn[]; | 190 | extern const u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[]; |
156 | extern const u32 b43_ntab_tmap[]; | 191 | extern const u16 tbl_tx_iqlo_cal_startcoefs[]; |
157 | 192 | extern const u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[]; | |
193 | extern const u16 tbl_tx_iqlo_cal_cmds_recal[]; | ||
194 | extern const u16 tbl_tx_iqlo_cal_cmds_fullcal[]; | ||
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[]; | ||
158 | 202 | ||
159 | #endif /* B43_TABLES_NPHY_H_ */ | 203 | #endif /* B43_TABLES_NPHY_H_ */ |
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index 0a86bdf53154..8b9387c6ff36 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c | |||
@@ -1411,7 +1411,6 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev, | |||
1411 | b43legacyerr(dev->wl, "DMA tx mapping failure\n"); | 1411 | b43legacyerr(dev->wl, "DMA tx mapping failure\n"); |
1412 | goto out_unlock; | 1412 | goto out_unlock; |
1413 | } | 1413 | } |
1414 | ring->nr_tx_packets++; | ||
1415 | if ((free_slots(ring) < SLOTS_PER_PACKET) || | 1414 | if ((free_slots(ring) < SLOTS_PER_PACKET) || |
1416 | should_inject_overflow(ring)) { | 1415 | should_inject_overflow(ring)) { |
1417 | /* This TX ring is full. */ | 1416 | /* This TX ring is full. */ |
@@ -1527,25 +1526,6 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev, | |||
1527 | spin_unlock(&ring->lock); | 1526 | spin_unlock(&ring->lock); |
1528 | } | 1527 | } |
1529 | 1528 | ||
1530 | void b43legacy_dma_get_tx_stats(struct b43legacy_wldev *dev, | ||
1531 | struct ieee80211_tx_queue_stats *stats) | ||
1532 | { | ||
1533 | const int nr_queues = dev->wl->hw->queues; | ||
1534 | struct b43legacy_dmaring *ring; | ||
1535 | unsigned long flags; | ||
1536 | int i; | ||
1537 | |||
1538 | for (i = 0; i < nr_queues; i++) { | ||
1539 | ring = priority_to_txring(dev, i); | ||
1540 | |||
1541 | spin_lock_irqsave(&ring->lock, flags); | ||
1542 | stats[i].len = ring->used_slots / SLOTS_PER_PACKET; | ||
1543 | stats[i].limit = ring->nr_slots / SLOTS_PER_PACKET; | ||
1544 | stats[i].count = ring->nr_tx_packets; | ||
1545 | spin_unlock_irqrestore(&ring->lock, flags); | ||
1546 | } | ||
1547 | } | ||
1548 | |||
1549 | static void dma_rx(struct b43legacy_dmaring *ring, | 1529 | static void dma_rx(struct b43legacy_dmaring *ring, |
1550 | int *slot) | 1530 | int *slot) |
1551 | { | 1531 | { |
diff --git a/drivers/net/wireless/b43legacy/dma.h b/drivers/net/wireless/b43legacy/dma.h index 2f186003c31e..f9681041c2d8 100644 --- a/drivers/net/wireless/b43legacy/dma.h +++ b/drivers/net/wireless/b43legacy/dma.h | |||
@@ -243,8 +243,6 @@ struct b43legacy_dmaring { | |||
243 | int used_slots; | 243 | int used_slots; |
244 | /* Currently used slot in the ring. */ | 244 | /* Currently used slot in the ring. */ |
245 | int current_slot; | 245 | int current_slot; |
246 | /* Total number of packets sent. Statistics only. */ | ||
247 | unsigned int nr_tx_packets; | ||
248 | /* Frameoffset in octets. */ | 246 | /* Frameoffset in octets. */ |
249 | u32 frameoffset; | 247 | u32 frameoffset; |
250 | /* Descriptor buffer size. */ | 248 | /* Descriptor buffer size. */ |
@@ -292,9 +290,6 @@ void b43legacy_dma_free(struct b43legacy_wldev *dev); | |||
292 | void b43legacy_dma_tx_suspend(struct b43legacy_wldev *dev); | 290 | void b43legacy_dma_tx_suspend(struct b43legacy_wldev *dev); |
293 | void b43legacy_dma_tx_resume(struct b43legacy_wldev *dev); | 291 | void b43legacy_dma_tx_resume(struct b43legacy_wldev *dev); |
294 | 292 | ||
295 | void b43legacy_dma_get_tx_stats(struct b43legacy_wldev *dev, | ||
296 | struct ieee80211_tx_queue_stats *stats); | ||
297 | |||
298 | int b43legacy_dma_tx(struct b43legacy_wldev *dev, | 293 | int b43legacy_dma_tx(struct b43legacy_wldev *dev, |
299 | struct sk_buff *skb); | 294 | struct sk_buff *skb); |
300 | void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev, | 295 | void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev, |
@@ -315,11 +310,6 @@ void b43legacy_dma_free(struct b43legacy_wldev *dev) | |||
315 | { | 310 | { |
316 | } | 311 | } |
317 | static inline | 312 | static inline |
318 | void b43legacy_dma_get_tx_stats(struct b43legacy_wldev *dev, | ||
319 | struct ieee80211_tx_queue_stats *stats) | ||
320 | { | ||
321 | } | ||
322 | static inline | ||
323 | int b43legacy_dma_tx(struct b43legacy_wldev *dev, | 313 | int b43legacy_dma_tx(struct b43legacy_wldev *dev, |
324 | struct sk_buff *skb) | 314 | struct sk_buff *skb) |
325 | { | 315 | { |
diff --git a/drivers/net/wireless/b43legacy/leds.h b/drivers/net/wireless/b43legacy/leds.h index 82167a90088f..9ff6750dc57f 100644 --- a/drivers/net/wireless/b43legacy/leds.h +++ b/drivers/net/wireless/b43legacy/leds.h | |||
@@ -45,7 +45,7 @@ enum b43legacy_led_behaviour { | |||
45 | void b43legacy_leds_init(struct b43legacy_wldev *dev); | 45 | void b43legacy_leds_init(struct b43legacy_wldev *dev); |
46 | void b43legacy_leds_exit(struct b43legacy_wldev *dev); | 46 | void b43legacy_leds_exit(struct b43legacy_wldev *dev); |
47 | 47 | ||
48 | #else /* CONFIG_B43EGACY_LEDS */ | 48 | #else /* CONFIG_B43LEGACY_LEDS */ |
49 | /* LED support disabled */ | 49 | /* LED support disabled */ |
50 | 50 | ||
51 | struct b43legacy_led { | 51 | struct b43legacy_led { |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index ab6a18c2e9d9..08523a45e23b 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -61,6 +61,8 @@ MODULE_AUTHOR("Michael Buesch"); | |||
61 | MODULE_LICENSE("GPL"); | 61 | MODULE_LICENSE("GPL"); |
62 | 62 | ||
63 | MODULE_FIRMWARE(B43legacy_SUPPORTED_FIRMWARE_ID); | 63 | MODULE_FIRMWARE(B43legacy_SUPPORTED_FIRMWARE_ID); |
64 | MODULE_FIRMWARE("b43legacy/ucode2.fw"); | ||
65 | MODULE_FIRMWARE("b43legacy/ucode4.fw"); | ||
64 | 66 | ||
65 | #if defined(CONFIG_B43LEGACY_DMA) && defined(CONFIG_B43LEGACY_PIO) | 67 | #if defined(CONFIG_B43LEGACY_DMA) && defined(CONFIG_B43LEGACY_PIO) |
66 | static int modparam_pio; | 68 | static int modparam_pio; |
@@ -2444,29 +2446,6 @@ static int b43legacy_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
2444 | return 0; | 2446 | return 0; |
2445 | } | 2447 | } |
2446 | 2448 | ||
2447 | static int b43legacy_op_get_tx_stats(struct ieee80211_hw *hw, | ||
2448 | struct ieee80211_tx_queue_stats *stats) | ||
2449 | { | ||
2450 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); | ||
2451 | struct b43legacy_wldev *dev = wl->current_dev; | ||
2452 | unsigned long flags; | ||
2453 | int err = -ENODEV; | ||
2454 | |||
2455 | if (!dev) | ||
2456 | goto out; | ||
2457 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
2458 | if (likely(b43legacy_status(dev) >= B43legacy_STAT_STARTED)) { | ||
2459 | if (b43legacy_using_pio(dev)) | ||
2460 | b43legacy_pio_get_tx_stats(dev, stats); | ||
2461 | else | ||
2462 | b43legacy_dma_get_tx_stats(dev, stats); | ||
2463 | err = 0; | ||
2464 | } | ||
2465 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
2466 | out: | ||
2467 | return err; | ||
2468 | } | ||
2469 | |||
2470 | static int b43legacy_op_get_stats(struct ieee80211_hw *hw, | 2449 | static int b43legacy_op_get_stats(struct ieee80211_hw *hw, |
2471 | struct ieee80211_low_level_stats *stats) | 2450 | struct ieee80211_low_level_stats *stats) |
2472 | { | 2451 | { |
@@ -2921,6 +2900,7 @@ static int b43legacy_wireless_core_start(struct b43legacy_wldev *dev) | |||
2921 | goto out; | 2900 | goto out; |
2922 | } | 2901 | } |
2923 | /* We are ready to run. */ | 2902 | /* We are ready to run. */ |
2903 | ieee80211_wake_queues(dev->wl->hw); | ||
2924 | b43legacy_set_status(dev, B43legacy_STAT_STARTED); | 2904 | b43legacy_set_status(dev, B43legacy_STAT_STARTED); |
2925 | 2905 | ||
2926 | /* Start data flow (TX/RX) */ | 2906 | /* Start data flow (TX/RX) */ |
@@ -3341,6 +3321,7 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev) | |||
3341 | b43legacy_security_init(dev); | 3321 | b43legacy_security_init(dev); |
3342 | b43legacy_rng_init(wl); | 3322 | b43legacy_rng_init(wl); |
3343 | 3323 | ||
3324 | ieee80211_wake_queues(dev->wl->hw); | ||
3344 | b43legacy_set_status(dev, B43legacy_STAT_INITIALIZED); | 3325 | b43legacy_set_status(dev, B43legacy_STAT_INITIALIZED); |
3345 | 3326 | ||
3346 | b43legacy_leds_init(dev); | 3327 | b43legacy_leds_init(dev); |
@@ -3361,7 +3342,7 @@ err_kfree_lo_control: | |||
3361 | } | 3342 | } |
3362 | 3343 | ||
3363 | static int b43legacy_op_add_interface(struct ieee80211_hw *hw, | 3344 | static int b43legacy_op_add_interface(struct ieee80211_hw *hw, |
3364 | struct ieee80211_if_init_conf *conf) | 3345 | struct ieee80211_vif *vif) |
3365 | { | 3346 | { |
3366 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); | 3347 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); |
3367 | struct b43legacy_wldev *dev; | 3348 | struct b43legacy_wldev *dev; |
@@ -3370,23 +3351,23 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw, | |||
3370 | 3351 | ||
3371 | /* TODO: allow WDS/AP devices to coexist */ | 3352 | /* TODO: allow WDS/AP devices to coexist */ |
3372 | 3353 | ||
3373 | if (conf->type != NL80211_IFTYPE_AP && | 3354 | if (vif->type != NL80211_IFTYPE_AP && |
3374 | conf->type != NL80211_IFTYPE_STATION && | 3355 | vif->type != NL80211_IFTYPE_STATION && |
3375 | conf->type != NL80211_IFTYPE_WDS && | 3356 | vif->type != NL80211_IFTYPE_WDS && |
3376 | conf->type != NL80211_IFTYPE_ADHOC) | 3357 | vif->type != NL80211_IFTYPE_ADHOC) |
3377 | return -EOPNOTSUPP; | 3358 | return -EOPNOTSUPP; |
3378 | 3359 | ||
3379 | mutex_lock(&wl->mutex); | 3360 | mutex_lock(&wl->mutex); |
3380 | if (wl->operating) | 3361 | if (wl->operating) |
3381 | goto out_mutex_unlock; | 3362 | goto out_mutex_unlock; |
3382 | 3363 | ||
3383 | b43legacydbg(wl, "Adding Interface type %d\n", conf->type); | 3364 | b43legacydbg(wl, "Adding Interface type %d\n", vif->type); |
3384 | 3365 | ||
3385 | dev = wl->current_dev; | 3366 | dev = wl->current_dev; |
3386 | wl->operating = 1; | 3367 | wl->operating = 1; |
3387 | wl->vif = conf->vif; | 3368 | wl->vif = vif; |
3388 | wl->if_type = conf->type; | 3369 | wl->if_type = vif->type; |
3389 | memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); | 3370 | memcpy(wl->mac_addr, vif->addr, ETH_ALEN); |
3390 | 3371 | ||
3391 | spin_lock_irqsave(&wl->irq_lock, flags); | 3372 | spin_lock_irqsave(&wl->irq_lock, flags); |
3392 | b43legacy_adjust_opmode(dev); | 3373 | b43legacy_adjust_opmode(dev); |
@@ -3403,18 +3384,18 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw, | |||
3403 | } | 3384 | } |
3404 | 3385 | ||
3405 | static void b43legacy_op_remove_interface(struct ieee80211_hw *hw, | 3386 | static void b43legacy_op_remove_interface(struct ieee80211_hw *hw, |
3406 | struct ieee80211_if_init_conf *conf) | 3387 | struct ieee80211_vif *vif) |
3407 | { | 3388 | { |
3408 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); | 3389 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); |
3409 | struct b43legacy_wldev *dev = wl->current_dev; | 3390 | struct b43legacy_wldev *dev = wl->current_dev; |
3410 | unsigned long flags; | 3391 | unsigned long flags; |
3411 | 3392 | ||
3412 | b43legacydbg(wl, "Removing Interface type %d\n", conf->type); | 3393 | b43legacydbg(wl, "Removing Interface type %d\n", vif->type); |
3413 | 3394 | ||
3414 | mutex_lock(&wl->mutex); | 3395 | mutex_lock(&wl->mutex); |
3415 | 3396 | ||
3416 | B43legacy_WARN_ON(!wl->operating); | 3397 | B43legacy_WARN_ON(!wl->operating); |
3417 | B43legacy_WARN_ON(wl->vif != conf->vif); | 3398 | B43legacy_WARN_ON(wl->vif != vif); |
3418 | wl->vif = NULL; | 3399 | wl->vif = NULL; |
3419 | 3400 | ||
3420 | wl->operating = 0; | 3401 | wl->operating = 0; |
@@ -3509,7 +3490,6 @@ static const struct ieee80211_ops b43legacy_hw_ops = { | |||
3509 | .bss_info_changed = b43legacy_op_bss_info_changed, | 3490 | .bss_info_changed = b43legacy_op_bss_info_changed, |
3510 | .configure_filter = b43legacy_op_configure_filter, | 3491 | .configure_filter = b43legacy_op_configure_filter, |
3511 | .get_stats = b43legacy_op_get_stats, | 3492 | .get_stats = b43legacy_op_get_stats, |
3512 | .get_tx_stats = b43legacy_op_get_tx_stats, | ||
3513 | .start = b43legacy_op_start, | 3493 | .start = b43legacy_op_start, |
3514 | .stop = b43legacy_op_stop, | 3494 | .stop = b43legacy_op_stop, |
3515 | .set_tim = b43legacy_op_beacon_set_tim, | 3495 | .set_tim = b43legacy_op_beacon_set_tim, |
@@ -3960,7 +3940,7 @@ static struct ssb_driver b43legacy_ssb_driver = { | |||
3960 | 3940 | ||
3961 | static void b43legacy_print_driverinfo(void) | 3941 | static void b43legacy_print_driverinfo(void) |
3962 | { | 3942 | { |
3963 | const char *feat_pci = "", *feat_leds = "", *feat_rfkill = "", | 3943 | const char *feat_pci = "", *feat_leds = "", |
3964 | *feat_pio = "", *feat_dma = ""; | 3944 | *feat_pio = "", *feat_dma = ""; |
3965 | 3945 | ||
3966 | #ifdef CONFIG_B43LEGACY_PCI_AUTOSELECT | 3946 | #ifdef CONFIG_B43LEGACY_PCI_AUTOSELECT |
@@ -3969,9 +3949,6 @@ static void b43legacy_print_driverinfo(void) | |||
3969 | #ifdef CONFIG_B43LEGACY_LEDS | 3949 | #ifdef CONFIG_B43LEGACY_LEDS |
3970 | feat_leds = "L"; | 3950 | feat_leds = "L"; |
3971 | #endif | 3951 | #endif |
3972 | #ifdef CONFIG_B43LEGACY_RFKILL | ||
3973 | feat_rfkill = "R"; | ||
3974 | #endif | ||
3975 | #ifdef CONFIG_B43LEGACY_PIO | 3952 | #ifdef CONFIG_B43LEGACY_PIO |
3976 | feat_pio = "I"; | 3953 | feat_pio = "I"; |
3977 | #endif | 3954 | #endif |
@@ -3979,9 +3956,9 @@ static void b43legacy_print_driverinfo(void) | |||
3979 | feat_dma = "D"; | 3956 | feat_dma = "D"; |
3980 | #endif | 3957 | #endif |
3981 | printk(KERN_INFO "Broadcom 43xx-legacy driver loaded " | 3958 | printk(KERN_INFO "Broadcom 43xx-legacy driver loaded " |
3982 | "[ Features: %s%s%s%s%s, Firmware-ID: " | 3959 | "[ Features: %s%s%s%s, Firmware-ID: " |
3983 | B43legacy_SUPPORTED_FIRMWARE_ID " ]\n", | 3960 | B43legacy_SUPPORTED_FIRMWARE_ID " ]\n", |
3984 | feat_pci, feat_leds, feat_rfkill, feat_pio, feat_dma); | 3961 | feat_pci, feat_leds, feat_pio, feat_dma); |
3985 | } | 3962 | } |
3986 | 3963 | ||
3987 | static int __init b43legacy_init(void) | 3964 | static int __init b43legacy_init(void) |
diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c index 51866c9a2769..017c0e9c37ef 100644 --- a/drivers/net/wireless/b43legacy/pio.c +++ b/drivers/net/wireless/b43legacy/pio.c | |||
@@ -477,7 +477,6 @@ int b43legacy_pio_tx(struct b43legacy_wldev *dev, | |||
477 | 477 | ||
478 | list_move_tail(&packet->list, &queue->txqueue); | 478 | list_move_tail(&packet->list, &queue->txqueue); |
479 | queue->nr_txfree--; | 479 | queue->nr_txfree--; |
480 | queue->nr_tx_packets++; | ||
481 | B43legacy_WARN_ON(queue->nr_txfree >= B43legacy_PIO_MAXTXPACKETS); | 480 | B43legacy_WARN_ON(queue->nr_txfree >= B43legacy_PIO_MAXTXPACKETS); |
482 | 481 | ||
483 | tasklet_schedule(&queue->txtask); | 482 | tasklet_schedule(&queue->txtask); |
@@ -546,18 +545,6 @@ void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev, | |||
546 | tasklet_schedule(&queue->txtask); | 545 | tasklet_schedule(&queue->txtask); |
547 | } | 546 | } |
548 | 547 | ||
549 | void b43legacy_pio_get_tx_stats(struct b43legacy_wldev *dev, | ||
550 | struct ieee80211_tx_queue_stats *stats) | ||
551 | { | ||
552 | struct b43legacy_pio *pio = &dev->pio; | ||
553 | struct b43legacy_pioqueue *queue; | ||
554 | |||
555 | queue = pio->queue1; | ||
556 | stats[0].len = B43legacy_PIO_MAXTXPACKETS - queue->nr_txfree; | ||
557 | stats[0].limit = B43legacy_PIO_MAXTXPACKETS; | ||
558 | stats[0].count = queue->nr_tx_packets; | ||
559 | } | ||
560 | |||
561 | static void pio_rx_error(struct b43legacy_pioqueue *queue, | 548 | static void pio_rx_error(struct b43legacy_pioqueue *queue, |
562 | int clear_buffers, | 549 | int clear_buffers, |
563 | const char *error) | 550 | const char *error) |
diff --git a/drivers/net/wireless/b43legacy/pio.h b/drivers/net/wireless/b43legacy/pio.h index 464fec05a06d..8e6773ea6e75 100644 --- a/drivers/net/wireless/b43legacy/pio.h +++ b/drivers/net/wireless/b43legacy/pio.h | |||
@@ -74,10 +74,6 @@ struct b43legacy_pioqueue { | |||
74 | * posted to the device. We are waiting for the txstatus. | 74 | * posted to the device. We are waiting for the txstatus. |
75 | */ | 75 | */ |
76 | struct list_head txrunning; | 76 | struct list_head txrunning; |
77 | /* Total number or packets sent. | ||
78 | * (This counter can obviously wrap). | ||
79 | */ | ||
80 | unsigned int nr_tx_packets; | ||
81 | struct tasklet_struct txtask; | 77 | struct tasklet_struct txtask; |
82 | struct b43legacy_pio_txpacket | 78 | struct b43legacy_pio_txpacket |
83 | tx_packets_cache[B43legacy_PIO_MAXTXPACKETS]; | 79 | tx_packets_cache[B43legacy_PIO_MAXTXPACKETS]; |
@@ -106,8 +102,6 @@ int b43legacy_pio_tx(struct b43legacy_wldev *dev, | |||
106 | struct sk_buff *skb); | 102 | struct sk_buff *skb); |
107 | void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev, | 103 | void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev, |
108 | const struct b43legacy_txstatus *status); | 104 | const struct b43legacy_txstatus *status); |
109 | void b43legacy_pio_get_tx_stats(struct b43legacy_wldev *dev, | ||
110 | struct ieee80211_tx_queue_stats *stats); | ||
111 | void b43legacy_pio_rx(struct b43legacy_pioqueue *queue); | 105 | void b43legacy_pio_rx(struct b43legacy_pioqueue *queue); |
112 | 106 | ||
113 | /* Suspend TX queue in hardware. */ | 107 | /* Suspend TX queue in hardware. */ |
@@ -140,11 +134,6 @@ void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev, | |||
140 | { | 134 | { |
141 | } | 135 | } |
142 | static inline | 136 | static inline |
143 | void b43legacy_pio_get_tx_stats(struct b43legacy_wldev *dev, | ||
144 | struct ieee80211_tx_queue_stats *stats) | ||
145 | { | ||
146 | } | ||
147 | static inline | ||
148 | void b43legacy_pio_rx(struct b43legacy_pioqueue *queue) | 137 | void b43legacy_pio_rx(struct b43legacy_pioqueue *queue) |
149 | { | 138 | { |
150 | } | 139 | } |
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index c9640a3e02c9..d19748d90aaf 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c | |||
@@ -794,13 +794,6 @@ static struct pcmcia_device_id hostap_cs_ids[] = { | |||
794 | PCMCIA_MFC_DEVICE_PROD_ID12(0, "SanDisk", "ConnectPlus", | 794 | PCMCIA_MFC_DEVICE_PROD_ID12(0, "SanDisk", "ConnectPlus", |
795 | 0x7a954bd9, 0x74be00c6), | 795 | 0x7a954bd9, 0x74be00c6), |
796 | PCMCIA_DEVICE_PROD_ID123( | 796 | PCMCIA_DEVICE_PROD_ID123( |
797 | "Intersil", "PRISM 2_5 PCMCIA ADAPTER", "ISL37300P", | ||
798 | 0x4b801a17, 0x6345a0bf, 0xc9049a39), | ||
799 | /* D-Link DWL-650 Rev. P1; manfid 0x000b, 0x7110 */ | ||
800 | PCMCIA_DEVICE_PROD_ID123( | ||
801 | "D-Link", "DWL-650 Wireless PC Card RevP", "ISL37101P-10", | ||
802 | 0x1a424a1c, 0x6ea57632, 0xdd97a26b), | ||
803 | PCMCIA_DEVICE_PROD_ID123( | ||
804 | "Addtron", "AWP-100 Wireless PCMCIA", "Version 01.02", | 797 | "Addtron", "AWP-100 Wireless PCMCIA", "Version 01.02", |
805 | 0xe6ec52ce, 0x08649af2, 0x4b74baa0), | 798 | 0xe6ec52ce, 0x08649af2, 0x4b74baa0), |
806 | PCMCIA_DEVICE_PROD_ID123( | 799 | PCMCIA_DEVICE_PROD_ID123( |
@@ -834,14 +827,12 @@ static struct pcmcia_device_id hostap_cs_ids[] = { | |||
834 | "Ver. 1.00", | 827 | "Ver. 1.00", |
835 | 0x5cd01705, 0x4271660f, 0x9d08ee12), | 828 | 0x5cd01705, 0x4271660f, 0x9d08ee12), |
836 | PCMCIA_DEVICE_PROD_ID123( | 829 | PCMCIA_DEVICE_PROD_ID123( |
837 | "corega", "WL PCCL-11", "ISL37300P", | ||
838 | 0xa21501a, 0x59868926, 0xc9049a39), | ||
839 | PCMCIA_DEVICE_PROD_ID123( | ||
840 | "The Linksys Group, Inc.", "Wireless Network CF Card", "ISL37300P", | ||
841 | 0xa5f472c2, 0x9c05598d, 0xc9049a39), | ||
842 | PCMCIA_DEVICE_PROD_ID123( | ||
843 | "Wireless LAN" , "11Mbps PC Card", "Version 01.02", | 830 | "Wireless LAN" , "11Mbps PC Card", "Version 01.02", |
844 | 0x4b8870ff, 0x70e946d1, 0x4b74baa0), | 831 | 0x4b8870ff, 0x70e946d1, 0x4b74baa0), |
832 | PCMCIA_DEVICE_PROD_ID3("HFA3863", 0x355cb092), | ||
833 | PCMCIA_DEVICE_PROD_ID3("ISL37100P", 0x630d52b2), | ||
834 | PCMCIA_DEVICE_PROD_ID3("ISL37101P-10", 0xdd97a26b), | ||
835 | PCMCIA_DEVICE_PROD_ID3("ISL37300P", 0xc9049a39), | ||
845 | PCMCIA_DEVICE_NULL | 836 | PCMCIA_DEVICE_NULL |
846 | }; | 837 | }; |
847 | MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids); | 838 | MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids); |
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index ff9b5c882184..d70732819423 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c | |||
@@ -2618,6 +2618,15 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id) | |||
2618 | int events = 0; | 2618 | int events = 0; |
2619 | u16 ev; | 2619 | u16 ev; |
2620 | 2620 | ||
2621 | /* Detect early interrupt before driver is fully configued */ | ||
2622 | if (!dev->base_addr) { | ||
2623 | if (net_ratelimit()) { | ||
2624 | printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n", | ||
2625 | dev->name); | ||
2626 | } | ||
2627 | return IRQ_HANDLED; | ||
2628 | } | ||
2629 | |||
2621 | iface = netdev_priv(dev); | 2630 | iface = netdev_priv(dev); |
2622 | local = iface->local; | 2631 | local = iface->local; |
2623 | 2632 | ||
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 8414178bcff4..3bf2e6e9b2d9 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, |
@@ -105,6 +175,8 @@ static struct iwl_lib_ops iwl1000_lib = { | |||
105 | .load_ucode = iwl5000_load_ucode, | 175 | .load_ucode = iwl5000_load_ucode, |
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, |
178 | .dump_csr = iwl_dump_csr, | ||
179 | .dump_fh = iwl_dump_fh, | ||
108 | .init_alive_start = iwl5000_init_alive_start, | 180 | .init_alive_start = iwl5000_init_alive_start, |
109 | .alive_notify = iwl5000_alive_notify, | 181 | .alive_notify = iwl5000_alive_notify, |
110 | .send_tx_power = iwl5000_send_tx_power, | 182 | .send_tx_power = iwl5000_send_tx_power, |
@@ -138,9 +210,10 @@ static struct iwl_lib_ops iwl1000_lib = { | |||
138 | .temperature = iwl5000_temperature, | 210 | .temperature = iwl5000_temperature, |
139 | .set_ct_kill = iwl1000_set_ct_threshold, | 211 | .set_ct_kill = iwl1000_set_ct_threshold, |
140 | }, | 212 | }, |
213 | .add_bcast_station = iwl_add_bcast_station, | ||
141 | }; | 214 | }; |
142 | 215 | ||
143 | static struct iwl_ops iwl1000_ops = { | 216 | static const struct iwl_ops iwl1000_ops = { |
144 | .ucode = &iwl5000_ucode, | 217 | .ucode = &iwl5000_ucode, |
145 | .lib = &iwl1000_lib, | 218 | .lib = &iwl1000_lib, |
146 | .hcmd = &iwl5000_hcmd, | 219 | .hcmd = &iwl5000_hcmd, |
@@ -173,7 +246,8 @@ struct iwl_cfg iwl1000_bgn_cfg = { | |||
173 | .use_rts_for_ht = true, /* use rts/cts protection */ | 246 | .use_rts_for_ht = true, /* use rts/cts protection */ |
174 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 247 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
175 | .support_ct_kill_exit = true, | 248 | .support_ct_kill_exit = true, |
176 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | 249 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, |
250 | .chain_noise_scale = 1000, | ||
177 | }; | 251 | }; |
178 | 252 | ||
179 | struct iwl_cfg iwl1000_bg_cfg = { | 253 | struct iwl_cfg iwl1000_bg_cfg = { |
@@ -200,6 +274,8 @@ struct iwl_cfg iwl1000_bg_cfg = { | |||
200 | .led_compensation = 51, | 274 | .led_compensation = 51, |
201 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 275 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
202 | .support_ct_kill_exit = true, | 276 | .support_ct_kill_exit = true, |
277 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, | ||
278 | .chain_noise_scale = 1000, | ||
203 | }; | 279 | }; |
204 | 280 | ||
205 | MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); | 281 | 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 234891d8cc10..521584b99fd1 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 |
@@ -45,8 +45,8 @@ | |||
45 | #include "iwl-sta.h" | 45 | #include "iwl-sta.h" |
46 | #include "iwl-3945.h" | 46 | #include "iwl-3945.h" |
47 | #include "iwl-eeprom.h" | 47 | #include "iwl-eeprom.h" |
48 | #include "iwl-helpers.h" | ||
49 | #include "iwl-core.h" | 48 | #include "iwl-core.h" |
49 | #include "iwl-helpers.h" | ||
50 | #include "iwl-led.h" | 50 | #include "iwl-led.h" |
51 | #include "iwl-3945-led.h" | 51 | #include "iwl-3945-led.h" |
52 | 52 | ||
@@ -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 */ |
@@ -2474,11 +2470,9 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) | |||
2474 | memset((void *)&priv->hw_params, 0, | 2470 | memset((void *)&priv->hw_params, 0, |
2475 | sizeof(struct iwl_hw_params)); | 2471 | sizeof(struct iwl_hw_params)); |
2476 | 2472 | ||
2477 | priv->shared_virt = | 2473 | priv->shared_virt = dma_alloc_coherent(&priv->pci_dev->dev, |
2478 | pci_alloc_consistent(priv->pci_dev, | 2474 | sizeof(struct iwl3945_shared), |
2479 | sizeof(struct iwl3945_shared), | 2475 | &priv->shared_phys, GFP_KERNEL); |
2480 | &priv->shared_phys); | ||
2481 | |||
2482 | if (!priv->shared_virt) { | 2476 | if (!priv->shared_virt) { |
2483 | IWL_ERR(priv, "failed to allocate pci memory\n"); | 2477 | IWL_ERR(priv, "failed to allocate pci memory\n"); |
2484 | mutex_unlock(&priv->mutex); | 2478 | mutex_unlock(&priv->mutex); |
@@ -2796,6 +2790,7 @@ static struct iwl_lib_ops iwl3945_lib = { | |||
2796 | .post_associate = iwl3945_post_associate, | 2790 | .post_associate = iwl3945_post_associate, |
2797 | .isr = iwl_isr_legacy, | 2791 | .isr = iwl_isr_legacy, |
2798 | .config_ap = iwl3945_config_ap, | 2792 | .config_ap = iwl3945_config_ap, |
2793 | .add_bcast_station = iwl3945_add_bcast_station, | ||
2799 | }; | 2794 | }; |
2800 | 2795 | ||
2801 | static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { | 2796 | static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { |
@@ -2804,7 +2799,7 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { | |||
2804 | .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag, | 2799 | .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag, |
2805 | }; | 2800 | }; |
2806 | 2801 | ||
2807 | static struct iwl_ops iwl3945_ops = { | 2802 | static const struct iwl_ops iwl3945_ops = { |
2808 | .ucode = &iwl3945_ucode, | 2803 | .ucode = &iwl3945_ucode, |
2809 | .lib = &iwl3945_lib, | 2804 | .lib = &iwl3945_lib, |
2810 | .hcmd = &iwl3945_hcmd, | 2805 | .hcmd = &iwl3945_hcmd, |
@@ -2830,6 +2825,7 @@ static struct iwl_cfg iwl3945_bg_cfg = { | |||
2830 | .ht_greenfield_support = false, | 2825 | .ht_greenfield_support = false, |
2831 | .led_compensation = 64, | 2826 | .led_compensation = 64, |
2832 | .broken_powersave = true, | 2827 | .broken_powersave = true, |
2828 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
2833 | }; | 2829 | }; |
2834 | 2830 | ||
2835 | static struct iwl_cfg iwl3945_abg_cfg = { | 2831 | static struct iwl_cfg iwl3945_abg_cfg = { |
@@ -2847,6 +2843,7 @@ static struct iwl_cfg iwl3945_abg_cfg = { | |||
2847 | .ht_greenfield_support = false, | 2843 | .ht_greenfield_support = false, |
2848 | .led_compensation = 64, | 2844 | .led_compensation = 64, |
2849 | .broken_powersave = true, | 2845 | .broken_powersave = true, |
2846 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
2850 | }; | 2847 | }; |
2851 | 2848 | ||
2852 | struct pci_device_id iwl3945_hw_card_ids[] = { | 2849 | struct pci_device_id iwl3945_hw_card_ids[] = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 531fa125f5a6..ae94babe595b 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 |
@@ -171,24 +171,6 @@ struct iwl3945_frame { | |||
171 | 171 | ||
172 | #define SCAN_INTERVAL 100 | 172 | #define SCAN_INTERVAL 100 |
173 | 173 | ||
174 | #define STATUS_HCMD_ACTIVE 0 /* host command in progress */ | ||
175 | #define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */ | ||
176 | #define STATUS_INT_ENABLED 2 | ||
177 | #define STATUS_RF_KILL_HW 3 | ||
178 | #define STATUS_INIT 5 | ||
179 | #define STATUS_ALIVE 6 | ||
180 | #define STATUS_READY 7 | ||
181 | #define STATUS_TEMPERATURE 8 | ||
182 | #define STATUS_GEO_CONFIGURED 9 | ||
183 | #define STATUS_EXIT_PENDING 10 | ||
184 | #define STATUS_STATISTICS 12 | ||
185 | #define STATUS_SCANNING 13 | ||
186 | #define STATUS_SCAN_ABORTING 14 | ||
187 | #define STATUS_SCAN_HW 15 | ||
188 | #define STATUS_POWER_PMI 16 | ||
189 | #define STATUS_FW_ERROR 17 | ||
190 | #define STATUS_CONF_PENDING 18 | ||
191 | |||
192 | #define MAX_TID_COUNT 9 | 174 | #define MAX_TID_COUNT 9 |
193 | 175 | ||
194 | #define IWL_INVALID_RATE 0xFF | 176 | #define IWL_INVALID_RATE 0xFF |
@@ -226,7 +208,8 @@ extern void iwl3945_rx_replenish(void *data); | |||
226 | extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | 208 | extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); |
227 | extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, | 209 | extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, |
228 | struct ieee80211_hdr *hdr,int left); | 210 | struct ieee80211_hdr *hdr,int left); |
229 | extern void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log); | 211 | extern int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, |
212 | char **buf, bool display); | ||
230 | extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv); | 213 | extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv); |
231 | 214 | ||
232 | /* | 215 | /* |
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 31462813bac0..1bd2cd836026 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 |
@@ -581,6 +581,13 @@ static int iwl4965_alive_notify(struct iwl_priv *priv) | |||
581 | 581 | ||
582 | iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); | 582 | iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); |
583 | 583 | ||
584 | /* make sure all queue are not stopped */ | ||
585 | memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); | ||
586 | for (i = 0; i < 4; i++) | ||
587 | atomic_set(&priv->queue_stop_count[i], 0); | ||
588 | |||
589 | /* reset to 0 to enable all the queue first */ | ||
590 | priv->txq_ctx_active_msk = 0; | ||
584 | /* Map each Tx/cmd queue to its corresponding fifo */ | 591 | /* Map each Tx/cmd queue to its corresponding fifo */ |
585 | for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { | 592 | for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { |
586 | int ac = default_queue_to_tx_fifo[i]; | 593 | int ac = default_queue_to_tx_fifo[i]; |
@@ -2206,9 +2213,10 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
2206 | .temperature = iwl4965_temperature_calib, | 2213 | .temperature = iwl4965_temperature_calib, |
2207 | .set_ct_kill = iwl4965_set_ct_threshold, | 2214 | .set_ct_kill = iwl4965_set_ct_threshold, |
2208 | }, | 2215 | }, |
2216 | .add_bcast_station = iwl_add_bcast_station, | ||
2209 | }; | 2217 | }; |
2210 | 2218 | ||
2211 | static struct iwl_ops iwl4965_ops = { | 2219 | static const struct iwl_ops iwl4965_ops = { |
2212 | .ucode = &iwl4965_ucode, | 2220 | .ucode = &iwl4965_ucode, |
2213 | .lib = &iwl4965_lib, | 2221 | .lib = &iwl4965_lib, |
2214 | .hcmd = &iwl4965_hcmd, | 2222 | .hcmd = &iwl4965_hcmd, |
@@ -2239,7 +2247,7 @@ struct iwl_cfg iwl4965_agn_cfg = { | |||
2239 | .broken_powersave = true, | 2247 | .broken_powersave = true, |
2240 | .led_compensation = 61, | 2248 | .led_compensation = 61, |
2241 | .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, | 2249 | .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, |
2242 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | 2250 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
2243 | }; | 2251 | }; |
2244 | 2252 | ||
2245 | /* Module firmware */ | 2253 | /* 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 cffaae772d51..e476acb53aa7 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 |
@@ -179,14 +179,24 @@ static void iwl5000_gain_computation(struct iwl_priv *priv, | |||
179 | data->delta_gain_code[i] = 0; | 179 | data->delta_gain_code[i] = 0; |
180 | continue; | 180 | continue; |
181 | } | 181 | } |
182 | delta_g = (1000 * ((s32)average_noise[default_chain] - | 182 | |
183 | delta_g = (priv->cfg->chain_noise_scale * | ||
184 | ((s32)average_noise[default_chain] - | ||
183 | (s32)average_noise[i])) / 1500; | 185 | (s32)average_noise[i])) / 1500; |
186 | |||
184 | /* bound gain by 2 bits value max, 3rd bit is sign */ | 187 | /* bound gain by 2 bits value max, 3rd bit is sign */ |
185 | data->delta_gain_code[i] = | 188 | data->delta_gain_code[i] = |
186 | min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); | 189 | min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); |
187 | 190 | ||
188 | if (delta_g < 0) | 191 | if (delta_g < 0) |
189 | /* set negative sign */ | 192 | /* |
193 | * set negative sign ... | ||
194 | * note to Intel developers: This is uCode API format, | ||
195 | * not the format of any internal device registers. | ||
196 | * Do not change this format for e.g. 6050 or similar | ||
197 | * devices. Change format only if more resolution | ||
198 | * (i.e. more than 2 bits magnitude) is needed. | ||
199 | */ | ||
190 | data->delta_gain_code[i] |= (1 << 2); | 200 | data->delta_gain_code[i] |= (1 << 2); |
191 | } | 201 | } |
192 | 202 | ||
@@ -263,8 +273,8 @@ static struct iwl_sensitivity_ranges iwl5000_sensitivity = { | |||
263 | 273 | ||
264 | .auto_corr_max_ofdm = 120, | 274 | .auto_corr_max_ofdm = 120, |
265 | .auto_corr_max_ofdm_mrc = 210, | 275 | .auto_corr_max_ofdm_mrc = 210, |
266 | .auto_corr_max_ofdm_x1 = 155, | 276 | .auto_corr_max_ofdm_x1 = 120, |
267 | .auto_corr_max_ofdm_mrc_x1 = 290, | 277 | .auto_corr_max_ofdm_mrc_x1 = 240, |
268 | 278 | ||
269 | .auto_corr_min_cck = 125, | 279 | .auto_corr_min_cck = 125, |
270 | .auto_corr_max_cck = 200, | 280 | .auto_corr_max_cck = 200, |
@@ -412,12 +422,14 @@ static void iwl5000_rx_calib_complete(struct iwl_priv *priv, | |||
412 | /* | 422 | /* |
413 | * ucode | 423 | * ucode |
414 | */ | 424 | */ |
415 | static int iwl5000_load_section(struct iwl_priv *priv, | 425 | static int iwl5000_load_section(struct iwl_priv *priv, const char *name, |
416 | struct fw_desc *image, | 426 | struct fw_desc *image, u32 dst_addr) |
417 | u32 dst_addr) | ||
418 | { | 427 | { |
419 | dma_addr_t phy_addr = image->p_addr; | 428 | dma_addr_t phy_addr = image->p_addr; |
420 | u32 byte_cnt = image->len; | 429 | u32 byte_cnt = image->len; |
430 | int ret; | ||
431 | |||
432 | priv->ucode_write_complete = 0; | ||
421 | 433 | ||
422 | iwl_write_direct32(priv, | 434 | iwl_write_direct32(priv, |
423 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | 435 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), |
@@ -447,57 +459,36 @@ static int iwl5000_load_section(struct iwl_priv *priv, | |||
447 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | | 459 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | |
448 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); | 460 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); |
449 | 461 | ||
450 | return 0; | 462 | 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, | 463 | ret = wait_event_interruptible_timeout(priv->wait_command_queue, |
466 | priv->ucode_write_complete, 5 * HZ); | 464 | priv->ucode_write_complete, 5 * HZ); |
467 | if (ret == -ERESTARTSYS) { | 465 | if (ret == -ERESTARTSYS) { |
468 | IWL_ERR(priv, "Could not load the INST uCode section due " | 466 | IWL_ERR(priv, "Could not load the %s uCode section due " |
469 | "to interrupt\n"); | 467 | "to interrupt\n", name); |
470 | return ret; | 468 | return ret; |
471 | } | 469 | } |
472 | if (!ret) { | 470 | if (!ret) { |
473 | IWL_ERR(priv, "Could not load the INST uCode section\n"); | 471 | IWL_ERR(priv, "Could not load the %s uCode section\n", |
472 | name); | ||
474 | return -ETIMEDOUT; | 473 | return -ETIMEDOUT; |
475 | } | 474 | } |
476 | 475 | ||
477 | priv->ucode_write_complete = 0; | 476 | return 0; |
478 | 477 | } | |
479 | ret = iwl5000_load_section( | ||
480 | priv, data_image, IWL50_RTC_DATA_LOWER_BOUND); | ||
481 | if (ret) | ||
482 | return ret; | ||
483 | 478 | ||
484 | IWL_DEBUG_INFO(priv, "DATA uCode section being loaded...\n"); | 479 | static int iwl5000_load_given_ucode(struct iwl_priv *priv, |
480 | struct fw_desc *inst_image, | ||
481 | struct fw_desc *data_image) | ||
482 | { | ||
483 | int ret = 0; | ||
485 | 484 | ||
486 | ret = wait_event_interruptible_timeout(priv->wait_command_queue, | 485 | ret = iwl5000_load_section(priv, "INST", inst_image, |
487 | priv->ucode_write_complete, 5 * HZ); | 486 | IWL50_RTC_INST_LOWER_BOUND); |
488 | if (ret == -ERESTARTSYS) { | 487 | if (ret) |
489 | IWL_ERR(priv, "Could not load the INST uCode section due " | ||
490 | "to interrupt\n"); | ||
491 | return ret; | 488 | 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 | 489 | ||
498 | priv->ucode_write_complete = 0; | 490 | return iwl5000_load_section(priv, "DATA", data_image, |
499 | 491 | IWL50_RTC_DATA_LOWER_BOUND); | |
500 | return ret; | ||
501 | } | 492 | } |
502 | 493 | ||
503 | int iwl5000_load_ucode(struct iwl_priv *priv) | 494 | int iwl5000_load_ucode(struct iwl_priv *priv) |
@@ -657,6 +648,13 @@ int iwl5000_alive_notify(struct iwl_priv *priv) | |||
657 | 648 | ||
658 | iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); | 649 | iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); |
659 | 650 | ||
651 | /* make sure all queue are not stopped */ | ||
652 | memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); | ||
653 | for (i = 0; i < 4; i++) | ||
654 | atomic_set(&priv->queue_stop_count[i], 0); | ||
655 | |||
656 | /* reset to 0 to enable all the queue first */ | ||
657 | priv->txq_ctx_active_msk = 0; | ||
660 | /* map qos queues to fifos one-to-one */ | 658 | /* map qos queues to fifos one-to-one */ |
661 | for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) { | 659 | for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) { |
662 | int ac = iwl5000_default_queue_to_tx_fifo[i]; | 660 | int ac = iwl5000_default_queue_to_tx_fifo[i]; |
@@ -781,7 +779,7 @@ void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | |||
781 | 779 | ||
782 | scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; | 780 | scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; |
783 | 781 | ||
784 | if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP) | 782 | if (write_ptr < TFD_QUEUE_SIZE_BC_DUP) |
785 | scd_bc_tbl[txq_id]. | 783 | scd_bc_tbl[txq_id]. |
786 | tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; | 784 | tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; |
787 | } | 785 | } |
@@ -800,12 +798,12 @@ void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, | |||
800 | if (txq_id != IWL_CMD_QUEUE_NUM) | 798 | if (txq_id != IWL_CMD_QUEUE_NUM) |
801 | sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; | 799 | sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; |
802 | 800 | ||
803 | bc_ent = cpu_to_le16(1 | (sta_id << 12)); | 801 | bc_ent = cpu_to_le16(1 | (sta_id << 12)); |
804 | scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; | 802 | scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; |
805 | 803 | ||
806 | if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP) | 804 | if (read_ptr < TFD_QUEUE_SIZE_BC_DUP) |
807 | scd_bc_tbl[txq_id]. | 805 | scd_bc_tbl[txq_id]. |
808 | tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; | 806 | tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; |
809 | } | 807 | } |
810 | 808 | ||
811 | static int iwl5000_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, | 809 | static int iwl5000_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, |
@@ -1464,6 +1462,8 @@ struct iwl_lib_ops iwl5000_lib = { | |||
1464 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | 1462 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, |
1465 | .dump_nic_event_log = iwl_dump_nic_event_log, | 1463 | .dump_nic_event_log = iwl_dump_nic_event_log, |
1466 | .dump_nic_error_log = iwl_dump_nic_error_log, | 1464 | .dump_nic_error_log = iwl_dump_nic_error_log, |
1465 | .dump_csr = iwl_dump_csr, | ||
1466 | .dump_fh = iwl_dump_fh, | ||
1467 | .load_ucode = iwl5000_load_ucode, | 1467 | .load_ucode = iwl5000_load_ucode, |
1468 | .init_alive_start = iwl5000_init_alive_start, | 1468 | .init_alive_start = iwl5000_init_alive_start, |
1469 | .alive_notify = iwl5000_alive_notify, | 1469 | .alive_notify = iwl5000_alive_notify, |
@@ -1499,6 +1499,7 @@ struct iwl_lib_ops iwl5000_lib = { | |||
1499 | .temperature = iwl5000_temperature, | 1499 | .temperature = iwl5000_temperature, |
1500 | .set_ct_kill = iwl5000_set_ct_threshold, | 1500 | .set_ct_kill = iwl5000_set_ct_threshold, |
1501 | }, | 1501 | }, |
1502 | .add_bcast_station = iwl_add_bcast_station, | ||
1502 | }; | 1503 | }; |
1503 | 1504 | ||
1504 | static struct iwl_lib_ops iwl5150_lib = { | 1505 | static struct iwl_lib_ops iwl5150_lib = { |
@@ -1516,6 +1517,7 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
1516 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | 1517 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, |
1517 | .dump_nic_event_log = iwl_dump_nic_event_log, | 1518 | .dump_nic_event_log = iwl_dump_nic_event_log, |
1518 | .dump_nic_error_log = iwl_dump_nic_error_log, | 1519 | .dump_nic_error_log = iwl_dump_nic_error_log, |
1520 | .dump_csr = iwl_dump_csr, | ||
1519 | .load_ucode = iwl5000_load_ucode, | 1521 | .load_ucode = iwl5000_load_ucode, |
1520 | .init_alive_start = iwl5000_init_alive_start, | 1522 | .init_alive_start = iwl5000_init_alive_start, |
1521 | .alive_notify = iwl5000_alive_notify, | 1523 | .alive_notify = iwl5000_alive_notify, |
@@ -1551,9 +1553,10 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
1551 | .temperature = iwl5150_temperature, | 1553 | .temperature = iwl5150_temperature, |
1552 | .set_ct_kill = iwl5150_set_ct_threshold, | 1554 | .set_ct_kill = iwl5150_set_ct_threshold, |
1553 | }, | 1555 | }, |
1556 | .add_bcast_station = iwl_add_bcast_station, | ||
1554 | }; | 1557 | }; |
1555 | 1558 | ||
1556 | static struct iwl_ops iwl5000_ops = { | 1559 | static const struct iwl_ops iwl5000_ops = { |
1557 | .ucode = &iwl5000_ucode, | 1560 | .ucode = &iwl5000_ucode, |
1558 | .lib = &iwl5000_lib, | 1561 | .lib = &iwl5000_lib, |
1559 | .hcmd = &iwl5000_hcmd, | 1562 | .hcmd = &iwl5000_hcmd, |
@@ -1561,7 +1564,7 @@ static struct iwl_ops iwl5000_ops = { | |||
1561 | .led = &iwlagn_led_ops, | 1564 | .led = &iwlagn_led_ops, |
1562 | }; | 1565 | }; |
1563 | 1566 | ||
1564 | static struct iwl_ops iwl5150_ops = { | 1567 | static const struct iwl_ops iwl5150_ops = { |
1565 | .ucode = &iwl5000_ucode, | 1568 | .ucode = &iwl5000_ucode, |
1566 | .lib = &iwl5150_lib, | 1569 | .lib = &iwl5150_lib, |
1567 | .hcmd = &iwl5000_hcmd, | 1570 | .hcmd = &iwl5000_hcmd, |
@@ -1598,7 +1601,8 @@ struct iwl_cfg iwl5300_agn_cfg = { | |||
1598 | .led_compensation = 51, | 1601 | .led_compensation = 51, |
1599 | .use_rts_for_ht = true, /* use rts/cts protection */ | 1602 | .use_rts_for_ht = true, /* use rts/cts protection */ |
1600 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 1603 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1601 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | 1604 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1605 | .chain_noise_scale = 1000, | ||
1602 | }; | 1606 | }; |
1603 | 1607 | ||
1604 | struct iwl_cfg iwl5100_bgn_cfg = { | 1608 | struct iwl_cfg iwl5100_bgn_cfg = { |
@@ -1623,6 +1627,8 @@ struct iwl_cfg iwl5100_bgn_cfg = { | |||
1623 | .led_compensation = 51, | 1627 | .led_compensation = 51, |
1624 | .use_rts_for_ht = true, /* use rts/cts protection */ | 1628 | .use_rts_for_ht = true, /* use rts/cts protection */ |
1625 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 1629 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1630 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | ||
1631 | .chain_noise_scale = 1000, | ||
1626 | }; | 1632 | }; |
1627 | 1633 | ||
1628 | struct iwl_cfg iwl5100_abg_cfg = { | 1634 | struct iwl_cfg iwl5100_abg_cfg = { |
@@ -1645,6 +1651,8 @@ struct iwl_cfg iwl5100_abg_cfg = { | |||
1645 | .use_bsm = false, | 1651 | .use_bsm = false, |
1646 | .led_compensation = 51, | 1652 | .led_compensation = 51, |
1647 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 1653 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1654 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | ||
1655 | .chain_noise_scale = 1000, | ||
1648 | }; | 1656 | }; |
1649 | 1657 | ||
1650 | struct iwl_cfg iwl5100_agn_cfg = { | 1658 | struct iwl_cfg iwl5100_agn_cfg = { |
@@ -1669,7 +1677,8 @@ struct iwl_cfg iwl5100_agn_cfg = { | |||
1669 | .led_compensation = 51, | 1677 | .led_compensation = 51, |
1670 | .use_rts_for_ht = true, /* use rts/cts protection */ | 1678 | .use_rts_for_ht = true, /* use rts/cts protection */ |
1671 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 1679 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1672 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | 1680 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1681 | .chain_noise_scale = 1000, | ||
1673 | }; | 1682 | }; |
1674 | 1683 | ||
1675 | struct iwl_cfg iwl5350_agn_cfg = { | 1684 | struct iwl_cfg iwl5350_agn_cfg = { |
@@ -1694,7 +1703,8 @@ struct iwl_cfg iwl5350_agn_cfg = { | |||
1694 | .led_compensation = 51, | 1703 | .led_compensation = 51, |
1695 | .use_rts_for_ht = true, /* use rts/cts protection */ | 1704 | .use_rts_for_ht = true, /* use rts/cts protection */ |
1696 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 1705 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1697 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | 1706 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1707 | .chain_noise_scale = 1000, | ||
1698 | }; | 1708 | }; |
1699 | 1709 | ||
1700 | struct iwl_cfg iwl5150_agn_cfg = { | 1710 | struct iwl_cfg iwl5150_agn_cfg = { |
@@ -1719,7 +1729,8 @@ struct iwl_cfg iwl5150_agn_cfg = { | |||
1719 | .led_compensation = 51, | 1729 | .led_compensation = 51, |
1720 | .use_rts_for_ht = true, /* use rts/cts protection */ | 1730 | .use_rts_for_ht = true, /* use rts/cts protection */ |
1721 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 1731 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1722 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | 1732 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1733 | .chain_noise_scale = 1000, | ||
1723 | }; | 1734 | }; |
1724 | 1735 | ||
1725 | struct iwl_cfg iwl5150_abg_cfg = { | 1736 | struct iwl_cfg iwl5150_abg_cfg = { |
@@ -1742,6 +1753,8 @@ struct iwl_cfg iwl5150_abg_cfg = { | |||
1742 | .use_bsm = false, | 1753 | .use_bsm = false, |
1743 | .led_compensation = 51, | 1754 | .led_compensation = 51, |
1744 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 1755 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1756 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | ||
1757 | .chain_noise_scale = 1000, | ||
1745 | }; | 1758 | }; |
1746 | 1759 | ||
1747 | MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); | 1760 | 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 74e571049273..c4844adff92a 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 |
@@ -70,6 +70,14 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv) | |||
70 | priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; | 70 | priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; |
71 | } | 71 | } |
72 | 72 | ||
73 | /* Indicate calibration version to uCode. */ | ||
74 | static void iwl6050_set_calib_version(struct iwl_priv *priv) | ||
75 | { | ||
76 | if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6) | ||
77 | iwl_set_bit(priv, CSR_GP_DRIVER_REG, | ||
78 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | ||
79 | } | ||
80 | |||
73 | /* NIC configuration for 6000 series */ | 81 | /* NIC configuration for 6000 series */ |
74 | static void iwl6000_nic_config(struct iwl_priv *priv) | 82 | static void iwl6000_nic_config(struct iwl_priv *priv) |
75 | { | 83 | { |
@@ -96,6 +104,8 @@ static void iwl6000_nic_config(struct iwl_priv *priv) | |||
96 | CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); | 104 | CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); |
97 | } | 105 | } |
98 | /* else do nothing, uCode configured */ | 106 | /* else do nothing, uCode configured */ |
107 | if (priv->cfg->ops->lib->temp_ops.set_calib_version) | ||
108 | priv->cfg->ops->lib->temp_ops.set_calib_version(priv); | ||
99 | } | 109 | } |
100 | 110 | ||
101 | static struct iwl_sensitivity_ranges iwl6000_sensitivity = { | 111 | static struct iwl_sensitivity_ranges iwl6000_sensitivity = { |
@@ -108,7 +118,7 @@ static struct iwl_sensitivity_ranges iwl6000_sensitivity = { | |||
108 | 118 | ||
109 | .auto_corr_max_ofdm = 145, | 119 | .auto_corr_max_ofdm = 145, |
110 | .auto_corr_max_ofdm_mrc = 232, | 120 | .auto_corr_max_ofdm_mrc = 232, |
111 | .auto_corr_max_ofdm_x1 = 145, | 121 | .auto_corr_max_ofdm_x1 = 110, |
112 | .auto_corr_max_ofdm_mrc_x1 = 232, | 122 | .auto_corr_max_ofdm_mrc_x1 = 232, |
113 | 123 | ||
114 | .auto_corr_min_cck = 125, | 124 | .auto_corr_min_cck = 125, |
@@ -158,11 +168,25 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) | |||
158 | /* Set initial sensitivity parameters */ | 168 | /* Set initial sensitivity parameters */ |
159 | /* Set initial calibration set */ | 169 | /* Set initial calibration set */ |
160 | priv->hw_params.sens = &iwl6000_sensitivity; | 170 | priv->hw_params.sens = &iwl6000_sensitivity; |
161 | priv->hw_params.calib_init_cfg = | 171 | switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { |
172 | case CSR_HW_REV_TYPE_6x50: | ||
173 | priv->hw_params.calib_init_cfg = | ||
174 | BIT(IWL_CALIB_XTAL) | | ||
175 | BIT(IWL_CALIB_DC) | | ||
176 | BIT(IWL_CALIB_LO) | | ||
177 | BIT(IWL_CALIB_TX_IQ) | | ||
178 | BIT(IWL_CALIB_BASE_BAND); | ||
179 | |||
180 | break; | ||
181 | default: | ||
182 | priv->hw_params.calib_init_cfg = | ||
162 | BIT(IWL_CALIB_XTAL) | | 183 | BIT(IWL_CALIB_XTAL) | |
163 | BIT(IWL_CALIB_LO) | | 184 | BIT(IWL_CALIB_LO) | |
164 | BIT(IWL_CALIB_TX_IQ) | | 185 | BIT(IWL_CALIB_TX_IQ) | |
165 | BIT(IWL_CALIB_BASE_BAND); | 186 | BIT(IWL_CALIB_BASE_BAND); |
187 | break; | ||
188 | } | ||
189 | |||
166 | return 0; | 190 | return 0; |
167 | } | 191 | } |
168 | 192 | ||
@@ -215,6 +239,8 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
215 | .load_ucode = iwl5000_load_ucode, | 239 | .load_ucode = iwl5000_load_ucode, |
216 | .dump_nic_event_log = iwl_dump_nic_event_log, | 240 | .dump_nic_event_log = iwl_dump_nic_event_log, |
217 | .dump_nic_error_log = iwl_dump_nic_error_log, | 241 | .dump_nic_error_log = iwl_dump_nic_error_log, |
242 | .dump_csr = iwl_dump_csr, | ||
243 | .dump_fh = iwl_dump_fh, | ||
218 | .init_alive_start = iwl5000_init_alive_start, | 244 | .init_alive_start = iwl5000_init_alive_start, |
219 | .alive_notify = iwl5000_alive_notify, | 245 | .alive_notify = iwl5000_alive_notify, |
220 | .send_tx_power = iwl5000_send_tx_power, | 246 | .send_tx_power = iwl5000_send_tx_power, |
@@ -250,9 +276,10 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
250 | .temperature = iwl5000_temperature, | 276 | .temperature = iwl5000_temperature, |
251 | .set_ct_kill = iwl6000_set_ct_threshold, | 277 | .set_ct_kill = iwl6000_set_ct_threshold, |
252 | }, | 278 | }, |
279 | .add_bcast_station = iwl_add_bcast_station, | ||
253 | }; | 280 | }; |
254 | 281 | ||
255 | static struct iwl_ops iwl6000_ops = { | 282 | static const struct iwl_ops iwl6000_ops = { |
256 | .ucode = &iwl5000_ucode, | 283 | .ucode = &iwl5000_ucode, |
257 | .lib = &iwl6000_lib, | 284 | .lib = &iwl6000_lib, |
258 | .hcmd = &iwl5000_hcmd, | 285 | .hcmd = &iwl5000_hcmd, |
@@ -260,18 +287,68 @@ static struct iwl_ops iwl6000_ops = { | |||
260 | .led = &iwlagn_led_ops, | 287 | .led = &iwlagn_led_ops, |
261 | }; | 288 | }; |
262 | 289 | ||
263 | static struct iwl_hcmd_utils_ops iwl6050_hcmd_utils = { | 290 | static struct iwl_lib_ops iwl6050_lib = { |
264 | .get_hcmd_size = iwl5000_get_hcmd_size, | 291 | .set_hw_params = iwl6000_hw_set_hw_params, |
265 | .build_addsta_hcmd = iwl5000_build_addsta_hcmd, | 292 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, |
266 | .rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag, | 293 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, |
267 | .calc_rssi = iwl5000_calc_rssi, | 294 | .txq_set_sched = iwl5000_txq_set_sched, |
295 | .txq_agg_enable = iwl5000_txq_agg_enable, | ||
296 | .txq_agg_disable = iwl5000_txq_agg_disable, | ||
297 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | ||
298 | .txq_free_tfd = iwl_hw_txq_free_tfd, | ||
299 | .txq_init = iwl_hw_tx_queue_init, | ||
300 | .rx_handler_setup = iwl5000_rx_handler_setup, | ||
301 | .setup_deferred_work = iwl5000_setup_deferred_work, | ||
302 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | ||
303 | .load_ucode = iwl5000_load_ucode, | ||
304 | .dump_nic_event_log = iwl_dump_nic_event_log, | ||
305 | .dump_nic_error_log = iwl_dump_nic_error_log, | ||
306 | .dump_csr = iwl_dump_csr, | ||
307 | .dump_fh = iwl_dump_fh, | ||
308 | .init_alive_start = iwl5000_init_alive_start, | ||
309 | .alive_notify = iwl5000_alive_notify, | ||
310 | .send_tx_power = iwl5000_send_tx_power, | ||
311 | .update_chain_flags = iwl_update_chain_flags, | ||
312 | .set_channel_switch = iwl6000_hw_channel_switch, | ||
313 | .apm_ops = { | ||
314 | .init = iwl_apm_init, | ||
315 | .stop = iwl_apm_stop, | ||
316 | .config = iwl6000_nic_config, | ||
317 | .set_pwr_src = iwl_set_pwr_src, | ||
318 | }, | ||
319 | .eeprom_ops = { | ||
320 | .regulatory_bands = { | ||
321 | EEPROM_5000_REG_BAND_1_CHANNELS, | ||
322 | EEPROM_5000_REG_BAND_2_CHANNELS, | ||
323 | EEPROM_5000_REG_BAND_3_CHANNELS, | ||
324 | EEPROM_5000_REG_BAND_4_CHANNELS, | ||
325 | EEPROM_5000_REG_BAND_5_CHANNELS, | ||
326 | EEPROM_5000_REG_BAND_24_HT40_CHANNELS, | ||
327 | EEPROM_5000_REG_BAND_52_HT40_CHANNELS | ||
328 | }, | ||
329 | .verify_signature = iwlcore_eeprom_verify_signature, | ||
330 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | ||
331 | .release_semaphore = iwlcore_eeprom_release_semaphore, | ||
332 | .calib_version = iwl5000_eeprom_calib_version, | ||
333 | .query_addr = iwl5000_eeprom_query_addr, | ||
334 | .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, | ||
335 | }, | ||
336 | .post_associate = iwl_post_associate, | ||
337 | .isr = iwl_isr_ict, | ||
338 | .config_ap = iwl_config_ap, | ||
339 | .temp_ops = { | ||
340 | .temperature = iwl5000_temperature, | ||
341 | .set_ct_kill = iwl6000_set_ct_threshold, | ||
342 | .set_calib_version = iwl6050_set_calib_version, | ||
343 | }, | ||
344 | .add_bcast_station = iwl_add_bcast_station, | ||
268 | }; | 345 | }; |
269 | 346 | ||
270 | static struct iwl_ops iwl6050_ops = { | 347 | static const struct iwl_ops iwl6050_ops = { |
271 | .ucode = &iwl5000_ucode, | 348 | .ucode = &iwl5000_ucode, |
272 | .lib = &iwl6000_lib, | 349 | .lib = &iwl6050_lib, |
273 | .hcmd = &iwl5000_hcmd, | 350 | .hcmd = &iwl5000_hcmd, |
274 | .utils = &iwl6050_hcmd_utils, | 351 | .utils = &iwl5000_hcmd_utils, |
275 | .led = &iwlagn_led_ops, | 352 | .led = &iwlagn_led_ops, |
276 | }; | 353 | }; |
277 | 354 | ||
@@ -306,7 +383,8 @@ struct iwl_cfg iwl6000i_2agn_cfg = { | |||
306 | .supports_idle = true, | 383 | .supports_idle = true, |
307 | .adv_thermal_throttle = true, | 384 | .adv_thermal_throttle = true, |
308 | .support_ct_kill_exit = true, | 385 | .support_ct_kill_exit = true, |
309 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | 386 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
387 | .chain_noise_scale = 1000, | ||
310 | }; | 388 | }; |
311 | 389 | ||
312 | struct iwl_cfg iwl6000i_2abg_cfg = { | 390 | struct iwl_cfg iwl6000i_2abg_cfg = { |
@@ -336,6 +414,8 @@ struct iwl_cfg iwl6000i_2abg_cfg = { | |||
336 | .supports_idle = true, | 414 | .supports_idle = true, |
337 | .adv_thermal_throttle = true, | 415 | .adv_thermal_throttle = true, |
338 | .support_ct_kill_exit = true, | 416 | .support_ct_kill_exit = true, |
417 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
418 | .chain_noise_scale = 1000, | ||
339 | }; | 419 | }; |
340 | 420 | ||
341 | struct iwl_cfg iwl6000i_2bg_cfg = { | 421 | struct iwl_cfg iwl6000i_2bg_cfg = { |
@@ -365,6 +445,8 @@ struct iwl_cfg iwl6000i_2bg_cfg = { | |||
365 | .supports_idle = true, | 445 | .supports_idle = true, |
366 | .adv_thermal_throttle = true, | 446 | .adv_thermal_throttle = true, |
367 | .support_ct_kill_exit = true, | 447 | .support_ct_kill_exit = true, |
448 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
449 | .chain_noise_scale = 1000, | ||
368 | }; | 450 | }; |
369 | 451 | ||
370 | struct iwl_cfg iwl6050_2agn_cfg = { | 452 | struct iwl_cfg iwl6050_2agn_cfg = { |
@@ -395,7 +477,8 @@ struct iwl_cfg iwl6050_2agn_cfg = { | |||
395 | .supports_idle = true, | 477 | .supports_idle = true, |
396 | .adv_thermal_throttle = true, | 478 | .adv_thermal_throttle = true, |
397 | .support_ct_kill_exit = true, | 479 | .support_ct_kill_exit = true, |
398 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DYNAMIC, | 480 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
481 | .chain_noise_scale = 1500, | ||
399 | }; | 482 | }; |
400 | 483 | ||
401 | struct iwl_cfg iwl6050_2abg_cfg = { | 484 | struct iwl_cfg iwl6050_2abg_cfg = { |
@@ -425,6 +508,8 @@ struct iwl_cfg iwl6050_2abg_cfg = { | |||
425 | .supports_idle = true, | 508 | .supports_idle = true, |
426 | .adv_thermal_throttle = true, | 509 | .adv_thermal_throttle = true, |
427 | .support_ct_kill_exit = true, | 510 | .support_ct_kill_exit = true, |
511 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
512 | .chain_noise_scale = 1500, | ||
428 | }; | 513 | }; |
429 | 514 | ||
430 | struct iwl_cfg iwl6000_3agn_cfg = { | 515 | struct iwl_cfg iwl6000_3agn_cfg = { |
@@ -455,7 +540,8 @@ struct iwl_cfg iwl6000_3agn_cfg = { | |||
455 | .supports_idle = true, | 540 | .supports_idle = true, |
456 | .adv_thermal_throttle = true, | 541 | .adv_thermal_throttle = true, |
457 | .support_ct_kill_exit = true, | 542 | .support_ct_kill_exit = true, |
458 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | 543 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
544 | .chain_noise_scale = 1000, | ||
459 | }; | 545 | }; |
460 | 546 | ||
461 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); | 547 | 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..8bf7c20b9d39 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 |
@@ -298,10 +298,23 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, | |||
298 | struct iwl_lq_sta *lq_data, u8 tid, | 298 | struct iwl_lq_sta *lq_data, u8 tid, |
299 | struct ieee80211_sta *sta) | 299 | struct ieee80211_sta *sta) |
300 | { | 300 | { |
301 | int ret; | ||
302 | |||
301 | if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { | 303 | if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { |
302 | IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", | 304 | IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", |
303 | sta->addr, tid); | 305 | sta->addr, tid); |
304 | ieee80211_start_tx_ba_session(sta, tid); | 306 | ret = ieee80211_start_tx_ba_session(sta, tid); |
307 | if (ret == -EAGAIN) { | ||
308 | /* | ||
309 | * driver and mac80211 is out of sync | ||
310 | * this might be cause by reloading firmware | ||
311 | * stop the tx ba session here | ||
312 | */ | ||
313 | IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n", | ||
314 | tid); | ||
315 | ret = ieee80211_stop_tx_ba_session(sta, tid, | ||
316 | WLAN_BACK_INITIATOR); | ||
317 | } | ||
305 | } | 318 | } |
306 | } | 319 | } |
307 | 320 | ||
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 1c9866daf815..c5b724eaf306 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 */ |
@@ -657,6 +652,131 @@ static void iwl_bg_statistics_periodic(unsigned long data) | |||
657 | iwl_send_statistics_request(priv, CMD_ASYNC, false); | 652 | iwl_send_statistics_request(priv, CMD_ASYNC, false); |
658 | } | 653 | } |
659 | 654 | ||
655 | |||
656 | static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, | ||
657 | u32 start_idx, u32 num_events, | ||
658 | u32 mode) | ||
659 | { | ||
660 | u32 i; | ||
661 | u32 ptr; /* SRAM byte address of log data */ | ||
662 | u32 ev, time, data; /* event log data */ | ||
663 | unsigned long reg_flags; | ||
664 | |||
665 | if (mode == 0) | ||
666 | ptr = base + (4 * sizeof(u32)) + (start_idx * 2 * sizeof(u32)); | ||
667 | else | ||
668 | ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32)); | ||
669 | |||
670 | /* Make sure device is powered up for SRAM reads */ | ||
671 | spin_lock_irqsave(&priv->reg_lock, reg_flags); | ||
672 | if (iwl_grab_nic_access(priv)) { | ||
673 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | ||
674 | return; | ||
675 | } | ||
676 | |||
677 | /* Set starting address; reads will auto-increment */ | ||
678 | _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr); | ||
679 | rmb(); | ||
680 | |||
681 | /* | ||
682 | * "time" is actually "data" for mode 0 (no timestamp). | ||
683 | * place event id # at far right for easier visual parsing. | ||
684 | */ | ||
685 | for (i = 0; i < num_events; i++) { | ||
686 | ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | ||
687 | time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | ||
688 | if (mode == 0) { | ||
689 | trace_iwlwifi_dev_ucode_cont_event(priv, | ||
690 | 0, time, ev); | ||
691 | } else { | ||
692 | data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | ||
693 | trace_iwlwifi_dev_ucode_cont_event(priv, | ||
694 | time, data, ev); | ||
695 | } | ||
696 | } | ||
697 | /* Allow device to power down */ | ||
698 | iwl_release_nic_access(priv); | ||
699 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | ||
700 | } | ||
701 | |||
702 | static void iwl_continuous_event_trace(struct iwl_priv *priv) | ||
703 | { | ||
704 | u32 capacity; /* event log capacity in # entries */ | ||
705 | u32 base; /* SRAM byte address of event log header */ | ||
706 | u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ | ||
707 | u32 num_wraps; /* # times uCode wrapped to top of log */ | ||
708 | u32 next_entry; /* index of next entry to be written by uCode */ | ||
709 | |||
710 | if (priv->ucode_type == UCODE_INIT) | ||
711 | base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); | ||
712 | else | ||
713 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | ||
714 | if (priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { | ||
715 | capacity = iwl_read_targ_mem(priv, base); | ||
716 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); | ||
717 | mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); | ||
718 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); | ||
719 | } else | ||
720 | return; | ||
721 | |||
722 | if (num_wraps == priv->event_log.num_wraps) { | ||
723 | iwl_print_cont_event_trace(priv, | ||
724 | base, priv->event_log.next_entry, | ||
725 | next_entry - priv->event_log.next_entry, | ||
726 | mode); | ||
727 | priv->event_log.non_wraps_count++; | ||
728 | } else { | ||
729 | if ((num_wraps - priv->event_log.num_wraps) > 1) | ||
730 | priv->event_log.wraps_more_count++; | ||
731 | else | ||
732 | priv->event_log.wraps_once_count++; | ||
733 | trace_iwlwifi_dev_ucode_wrap_event(priv, | ||
734 | num_wraps - priv->event_log.num_wraps, | ||
735 | next_entry, priv->event_log.next_entry); | ||
736 | if (next_entry < priv->event_log.next_entry) { | ||
737 | iwl_print_cont_event_trace(priv, base, | ||
738 | priv->event_log.next_entry, | ||
739 | capacity - priv->event_log.next_entry, | ||
740 | mode); | ||
741 | |||
742 | iwl_print_cont_event_trace(priv, base, 0, | ||
743 | next_entry, mode); | ||
744 | } else { | ||
745 | iwl_print_cont_event_trace(priv, base, | ||
746 | next_entry, capacity - next_entry, | ||
747 | mode); | ||
748 | |||
749 | iwl_print_cont_event_trace(priv, base, 0, | ||
750 | next_entry, mode); | ||
751 | } | ||
752 | } | ||
753 | priv->event_log.num_wraps = num_wraps; | ||
754 | priv->event_log.next_entry = next_entry; | ||
755 | } | ||
756 | |||
757 | /** | ||
758 | * iwl_bg_ucode_trace - Timer callback to log ucode event | ||
759 | * | ||
760 | * The timer is continually set to execute every | ||
761 | * UCODE_TRACE_PERIOD milliseconds after the last timer expired | ||
762 | * this function is to perform continuous uCode event logging operation | ||
763 | * if enabled | ||
764 | */ | ||
765 | static void iwl_bg_ucode_trace(unsigned long data) | ||
766 | { | ||
767 | struct iwl_priv *priv = (struct iwl_priv *)data; | ||
768 | |||
769 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
770 | return; | ||
771 | |||
772 | if (priv->event_log.ucode_trace) { | ||
773 | iwl_continuous_event_trace(priv); | ||
774 | /* Reschedule the timer to occur in UCODE_TRACE_PERIOD */ | ||
775 | mod_timer(&priv->ucode_trace, | ||
776 | jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD)); | ||
777 | } | ||
778 | } | ||
779 | |||
660 | static void iwl_rx_beacon_notif(struct iwl_priv *priv, | 780 | static void iwl_rx_beacon_notif(struct iwl_priv *priv, |
661 | struct iwl_rx_mem_buffer *rxb) | 781 | struct iwl_rx_mem_buffer *rxb) |
662 | { | 782 | { |
@@ -689,12 +809,14 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, | |||
689 | u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); | 809 | u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); |
690 | unsigned long status = priv->status; | 810 | unsigned long status = priv->status; |
691 | 811 | ||
692 | IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s\n", | 812 | IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n", |
693 | (flags & HW_CARD_DISABLED) ? "Kill" : "On", | 813 | (flags & HW_CARD_DISABLED) ? "Kill" : "On", |
694 | (flags & SW_CARD_DISABLED) ? "Kill" : "On"); | 814 | (flags & SW_CARD_DISABLED) ? "Kill" : "On", |
815 | (flags & CT_CARD_DISABLED) ? | ||
816 | "Reached" : "Not reached"); | ||
695 | 817 | ||
696 | if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | | 818 | if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | |
697 | RF_CARD_DISABLED)) { | 819 | CT_CARD_DISABLED)) { |
698 | 820 | ||
699 | iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, | 821 | iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, |
700 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); | 822 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); |
@@ -708,10 +830,10 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, | |||
708 | iwl_write_direct32(priv, HBUS_TARG_MBX_C, | 830 | iwl_write_direct32(priv, HBUS_TARG_MBX_C, |
709 | HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); | 831 | HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); |
710 | } | 832 | } |
711 | if (flags & RF_CARD_DISABLED) | 833 | if (flags & CT_CARD_DISABLED) |
712 | iwl_tt_enter_ct_kill(priv); | 834 | iwl_tt_enter_ct_kill(priv); |
713 | } | 835 | } |
714 | if (!(flags & RF_CARD_DISABLED)) | 836 | if (!(flags & CT_CARD_DISABLED)) |
715 | iwl_tt_exit_ct_kill(priv); | 837 | iwl_tt_exit_ct_kill(priv); |
716 | 838 | ||
717 | if (flags & HW_CARD_DISABLED) | 839 | if (flags & HW_CARD_DISABLED) |
@@ -761,6 +883,8 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv) | |||
761 | priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive; | 883 | priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive; |
762 | priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error; | 884 | priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error; |
763 | 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; | ||
764 | priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; | 888 | priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; |
765 | priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] = | 889 | priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] = |
766 | iwl_rx_pm_debug_statistics_notif; | 890 | iwl_rx_pm_debug_statistics_notif; |
@@ -774,7 +898,6 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv) | |||
774 | priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_reply_statistics; | 898 | priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_reply_statistics; |
775 | priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics; | 899 | priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics; |
776 | 900 | ||
777 | iwl_setup_spectrum_handlers(priv); | ||
778 | iwl_setup_rx_scan_handlers(priv); | 901 | iwl_setup_rx_scan_handlers(priv); |
779 | 902 | ||
780 | /* status change handler */ | 903 | /* status change handler */ |
@@ -1634,7 +1757,7 @@ static const char *desc_lookup_text[] = { | |||
1634 | "DEBUG_1", | 1757 | "DEBUG_1", |
1635 | "DEBUG_2", | 1758 | "DEBUG_2", |
1636 | "DEBUG_3", | 1759 | "DEBUG_3", |
1637 | "UNKNOWN" | 1760 | "ADVANCED SYSASSERT" |
1638 | }; | 1761 | }; |
1639 | 1762 | ||
1640 | static const char *desc_lookup(int i) | 1763 | static const char *desc_lookup(int i) |
@@ -1705,8 +1828,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
1705 | * iwl_print_event_log - Dump error event log to syslog | 1828 | * iwl_print_event_log - Dump error event log to syslog |
1706 | * | 1829 | * |
1707 | */ | 1830 | */ |
1708 | static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | 1831 | static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, |
1709 | u32 num_events, u32 mode) | 1832 | u32 num_events, u32 mode, |
1833 | int pos, char **buf, size_t bufsz) | ||
1710 | { | 1834 | { |
1711 | u32 i; | 1835 | u32 i; |
1712 | u32 base; /* SRAM byte address of event log header */ | 1836 | u32 base; /* SRAM byte address of event log header */ |
@@ -1716,7 +1840,7 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1716 | unsigned long reg_flags; | 1840 | unsigned long reg_flags; |
1717 | 1841 | ||
1718 | if (num_events == 0) | 1842 | if (num_events == 0) |
1719 | return; | 1843 | return pos; |
1720 | if (priv->ucode_type == UCODE_INIT) | 1844 | if (priv->ucode_type == UCODE_INIT) |
1721 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); | 1845 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); |
1722 | else | 1846 | else |
@@ -1744,27 +1868,44 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1744 | time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | 1868 | time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
1745 | if (mode == 0) { | 1869 | if (mode == 0) { |
1746 | /* data, ev */ | 1870 | /* data, ev */ |
1747 | trace_iwlwifi_dev_ucode_event(priv, 0, time, ev); | 1871 | if (bufsz) { |
1748 | IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev); | 1872 | pos += scnprintf(*buf + pos, bufsz - pos, |
1873 | "EVT_LOG:0x%08x:%04u\n", | ||
1874 | time, ev); | ||
1875 | } else { | ||
1876 | trace_iwlwifi_dev_ucode_event(priv, 0, | ||
1877 | time, ev); | ||
1878 | IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", | ||
1879 | time, ev); | ||
1880 | } | ||
1749 | } else { | 1881 | } else { |
1750 | data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | 1882 | data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
1751 | IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", | 1883 | if (bufsz) { |
1884 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
1885 | "EVT_LOGT:%010u:0x%08x:%04u\n", | ||
1886 | time, data, ev); | ||
1887 | } else { | ||
1888 | IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", | ||
1752 | time, data, ev); | 1889 | time, data, ev); |
1753 | trace_iwlwifi_dev_ucode_event(priv, time, data, ev); | 1890 | trace_iwlwifi_dev_ucode_event(priv, time, |
1891 | data, ev); | ||
1892 | } | ||
1754 | } | 1893 | } |
1755 | } | 1894 | } |
1756 | 1895 | ||
1757 | /* Allow device to power down */ | 1896 | /* Allow device to power down */ |
1758 | iwl_release_nic_access(priv); | 1897 | iwl_release_nic_access(priv); |
1759 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | 1898 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); |
1899 | return pos; | ||
1760 | } | 1900 | } |
1761 | 1901 | ||
1762 | /** | 1902 | /** |
1763 | * iwl_print_last_event_logs - Dump the newest # of event log to syslog | 1903 | * iwl_print_last_event_logs - Dump the newest # of event log to syslog |
1764 | */ | 1904 | */ |
1765 | static void iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | 1905 | static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, |
1766 | u32 num_wraps, u32 next_entry, | 1906 | u32 num_wraps, u32 next_entry, |
1767 | u32 size, u32 mode) | 1907 | u32 size, u32 mode, |
1908 | int pos, char **buf, size_t bufsz) | ||
1768 | { | 1909 | { |
1769 | /* | 1910 | /* |
1770 | * display the newest DEFAULT_LOG_ENTRIES entries | 1911 | * display the newest DEFAULT_LOG_ENTRIES entries |
@@ -1772,21 +1913,26 @@ static void iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | |||
1772 | */ | 1913 | */ |
1773 | if (num_wraps) { | 1914 | if (num_wraps) { |
1774 | if (next_entry < size) { | 1915 | if (next_entry < size) { |
1775 | iwl_print_event_log(priv, | 1916 | pos = iwl_print_event_log(priv, |
1776 | capacity - (size - next_entry), | 1917 | capacity - (size - next_entry), |
1777 | size - next_entry, mode); | 1918 | size - next_entry, mode, |
1778 | iwl_print_event_log(priv, 0, | 1919 | pos, buf, bufsz); |
1779 | next_entry, mode); | 1920 | pos = iwl_print_event_log(priv, 0, |
1921 | next_entry, mode, | ||
1922 | pos, buf, bufsz); | ||
1780 | } else | 1923 | } else |
1781 | iwl_print_event_log(priv, next_entry - size, | 1924 | pos = iwl_print_event_log(priv, next_entry - size, |
1782 | size, mode); | 1925 | size, mode, pos, buf, bufsz); |
1783 | } else { | 1926 | } else { |
1784 | if (next_entry < size) | 1927 | if (next_entry < size) { |
1785 | iwl_print_event_log(priv, 0, next_entry, mode); | 1928 | pos = iwl_print_event_log(priv, 0, next_entry, |
1786 | else | 1929 | mode, pos, buf, bufsz); |
1787 | iwl_print_event_log(priv, next_entry - size, | 1930 | } else { |
1788 | size, mode); | 1931 | pos = iwl_print_event_log(priv, next_entry - size, |
1932 | size, mode, pos, buf, bufsz); | ||
1933 | } | ||
1789 | } | 1934 | } |
1935 | return pos; | ||
1790 | } | 1936 | } |
1791 | 1937 | ||
1792 | /* For sanity check only. Actual size is determined by uCode, typ. 512 */ | 1938 | /* For sanity check only. Actual size is determined by uCode, typ. 512 */ |
@@ -1794,7 +1940,8 @@ static void iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | |||
1794 | 1940 | ||
1795 | #define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) | 1941 | #define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) |
1796 | 1942 | ||
1797 | void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | 1943 | int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, |
1944 | char **buf, bool display) | ||
1798 | { | 1945 | { |
1799 | u32 base; /* SRAM byte address of event log header */ | 1946 | u32 base; /* SRAM byte address of event log header */ |
1800 | u32 capacity; /* event log capacity in # entries */ | 1947 | u32 capacity; /* event log capacity in # entries */ |
@@ -1802,6 +1949,8 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | |||
1802 | u32 num_wraps; /* # times uCode wrapped to top of log */ | 1949 | u32 num_wraps; /* # times uCode wrapped to top of log */ |
1803 | u32 next_entry; /* index of next entry to be written by uCode */ | 1950 | u32 next_entry; /* index of next entry to be written by uCode */ |
1804 | u32 size; /* # entries that we'll print */ | 1951 | u32 size; /* # entries that we'll print */ |
1952 | int pos = 0; | ||
1953 | size_t bufsz = 0; | ||
1805 | 1954 | ||
1806 | if (priv->ucode_type == UCODE_INIT) | 1955 | if (priv->ucode_type == UCODE_INIT) |
1807 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); | 1956 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); |
@@ -1812,7 +1961,7 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | |||
1812 | IWL_ERR(priv, | 1961 | IWL_ERR(priv, |
1813 | "Invalid event log pointer 0x%08X for %s uCode\n", | 1962 | "Invalid event log pointer 0x%08X for %s uCode\n", |
1814 | base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT"); | 1963 | base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT"); |
1815 | return; | 1964 | return -EINVAL; |
1816 | } | 1965 | } |
1817 | 1966 | ||
1818 | /* event log header */ | 1967 | /* event log header */ |
@@ -1838,7 +1987,7 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | |||
1838 | /* bail out if nothing in log */ | 1987 | /* bail out if nothing in log */ |
1839 | if (size == 0) { | 1988 | if (size == 0) { |
1840 | IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); | 1989 | IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); |
1841 | return; | 1990 | return pos; |
1842 | } | 1991 | } |
1843 | 1992 | ||
1844 | #ifdef CONFIG_IWLWIFI_DEBUG | 1993 | #ifdef CONFIG_IWLWIFI_DEBUG |
@@ -1853,6 +2002,15 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | |||
1853 | size); | 2002 | size); |
1854 | 2003 | ||
1855 | #ifdef CONFIG_IWLWIFI_DEBUG | 2004 | #ifdef CONFIG_IWLWIFI_DEBUG |
2005 | if (display) { | ||
2006 | if (full_log) | ||
2007 | bufsz = capacity * 48; | ||
2008 | else | ||
2009 | bufsz = size * 48; | ||
2010 | *buf = kmalloc(bufsz, GFP_KERNEL); | ||
2011 | if (!*buf) | ||
2012 | return -ENOMEM; | ||
2013 | } | ||
1856 | 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) { |
1857 | /* | 2015 | /* |
1858 | * if uCode has wrapped back to top of log, | 2016 | * if uCode has wrapped back to top of log, |
@@ -1860,17 +2018,22 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | |||
1860 | * i.e the next one that uCode would fill. | 2018 | * i.e the next one that uCode would fill. |
1861 | */ | 2019 | */ |
1862 | if (num_wraps) | 2020 | if (num_wraps) |
1863 | iwl_print_event_log(priv, next_entry, | 2021 | pos = iwl_print_event_log(priv, next_entry, |
1864 | capacity - next_entry, mode); | 2022 | capacity - next_entry, mode, |
2023 | pos, buf, bufsz); | ||
1865 | /* (then/else) start at top of log */ | 2024 | /* (then/else) start at top of log */ |
1866 | iwl_print_event_log(priv, 0, next_entry, mode); | 2025 | pos = iwl_print_event_log(priv, 0, |
2026 | next_entry, mode, pos, buf, bufsz); | ||
1867 | } else | 2027 | } else |
1868 | iwl_print_last_event_logs(priv, capacity, num_wraps, | 2028 | pos = iwl_print_last_event_logs(priv, capacity, num_wraps, |
1869 | next_entry, size, mode); | 2029 | next_entry, size, mode, |
2030 | pos, buf, bufsz); | ||
1870 | #else | 2031 | #else |
1871 | iwl_print_last_event_logs(priv, capacity, num_wraps, | 2032 | pos = iwl_print_last_event_logs(priv, capacity, num_wraps, |
1872 | next_entry, size, mode); | 2033 | next_entry, size, mode, |
2034 | pos, buf, bufsz); | ||
1873 | #endif | 2035 | #endif |
2036 | return pos; | ||
1874 | } | 2037 | } |
1875 | 2038 | ||
1876 | /** | 2039 | /** |
@@ -2276,18 +2439,6 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) | |||
2276 | return; | 2439 | return; |
2277 | } | 2440 | } |
2278 | 2441 | ||
2279 | static void iwl_bg_up(struct work_struct *data) | ||
2280 | { | ||
2281 | struct iwl_priv *priv = container_of(data, struct iwl_priv, up); | ||
2282 | |||
2283 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
2284 | return; | ||
2285 | |||
2286 | mutex_lock(&priv->mutex); | ||
2287 | __iwl_up(priv); | ||
2288 | mutex_unlock(&priv->mutex); | ||
2289 | } | ||
2290 | |||
2291 | static void iwl_bg_restart(struct work_struct *data) | 2442 | static void iwl_bg_restart(struct work_struct *data) |
2292 | { | 2443 | { |
2293 | struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); | 2444 | struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); |
@@ -2304,7 +2455,13 @@ static void iwl_bg_restart(struct work_struct *data) | |||
2304 | ieee80211_restart_hw(priv->hw); | 2455 | ieee80211_restart_hw(priv->hw); |
2305 | } else { | 2456 | } else { |
2306 | iwl_down(priv); | 2457 | iwl_down(priv); |
2307 | 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); | ||
2308 | } | 2465 | } |
2309 | } | 2466 | } |
2310 | 2467 | ||
@@ -2440,7 +2597,7 @@ void iwl_post_associate(struct iwl_priv *priv) | |||
2440 | * 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 |
2441 | * other mac80211 functions grouped here. | 2598 | * other mac80211 functions grouped here. |
2442 | */ | 2599 | */ |
2443 | static int iwl_setup_mac(struct iwl_priv *priv) | 2600 | static int iwl_mac_setup_register(struct iwl_priv *priv) |
2444 | { | 2601 | { |
2445 | int ret; | 2602 | int ret; |
2446 | struct ieee80211_hw *hw = priv->hw; | 2603 | struct ieee80211_hw *hw = priv->hw; |
@@ -2456,6 +2613,10 @@ static int iwl_setup_mac(struct iwl_priv *priv) | |||
2456 | hw->flags |= IEEE80211_HW_SUPPORTS_PS | | 2613 | hw->flags |= IEEE80211_HW_SUPPORTS_PS | |
2457 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; | 2614 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; |
2458 | 2615 | ||
2616 | if (priv->cfg->sku & IWL_SKU_N) | ||
2617 | hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | ||
2618 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; | ||
2619 | |||
2459 | hw->sta_data_size = sizeof(struct iwl_station_priv); | 2620 | hw->sta_data_size = sizeof(struct iwl_station_priv); |
2460 | hw->wiphy->interface_modes = | 2621 | hw->wiphy->interface_modes = |
2461 | BIT(NL80211_IFTYPE_STATION) | | 2622 | BIT(NL80211_IFTYPE_STATION) | |
@@ -2470,7 +2631,7 @@ static int iwl_setup_mac(struct iwl_priv *priv) | |||
2470 | */ | 2631 | */ |
2471 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 2632 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
2472 | 2633 | ||
2473 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; | 2634 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX + 1; |
2474 | /* we create the 802.11 header and a zero-length SSID element */ | 2635 | /* we create the 802.11 header and a zero-length SSID element */ |
2475 | hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; | 2636 | hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; |
2476 | 2637 | ||
@@ -2668,14 +2829,18 @@ void iwl_config_ap(struct iwl_priv *priv) | |||
2668 | } | 2829 | } |
2669 | 2830 | ||
2670 | static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, | 2831 | static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, |
2671 | struct ieee80211_key_conf *keyconf, const u8 *addr, | 2832 | struct ieee80211_vif *vif, |
2672 | u32 iv32, u16 *phase1key) | 2833 | struct ieee80211_key_conf *keyconf, |
2834 | struct ieee80211_sta *sta, | ||
2835 | u32 iv32, u16 *phase1key) | ||
2673 | { | 2836 | { |
2674 | 2837 | ||
2675 | struct iwl_priv *priv = hw->priv; | 2838 | struct iwl_priv *priv = hw->priv; |
2676 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 2839 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
2677 | 2840 | ||
2678 | 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); | ||
2679 | 2844 | ||
2680 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 2845 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
2681 | } | 2846 | } |
@@ -2776,14 +2941,28 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
2776 | return ret; | 2941 | return ret; |
2777 | case IEEE80211_AMPDU_TX_START: | 2942 | case IEEE80211_AMPDU_TX_START: |
2778 | IWL_DEBUG_HT(priv, "start Tx\n"); | 2943 | IWL_DEBUG_HT(priv, "start Tx\n"); |
2779 | return iwl_tx_agg_start(priv, sta->addr, tid, ssn); | 2944 | ret = iwl_tx_agg_start(priv, sta->addr, tid, ssn); |
2945 | if (ret == 0) { | ||
2946 | priv->agg_tids_count++; | ||
2947 | IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", | ||
2948 | priv->agg_tids_count); | ||
2949 | } | ||
2950 | return ret; | ||
2780 | case IEEE80211_AMPDU_TX_STOP: | 2951 | case IEEE80211_AMPDU_TX_STOP: |
2781 | IWL_DEBUG_HT(priv, "stop Tx\n"); | 2952 | IWL_DEBUG_HT(priv, "stop Tx\n"); |
2782 | ret = iwl_tx_agg_stop(priv, sta->addr, tid); | 2953 | ret = iwl_tx_agg_stop(priv, sta->addr, tid); |
2954 | if ((ret == 0) && (priv->agg_tids_count > 0)) { | ||
2955 | priv->agg_tids_count--; | ||
2956 | IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", | ||
2957 | priv->agg_tids_count); | ||
2958 | } | ||
2783 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 2959 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
2784 | return 0; | 2960 | return 0; |
2785 | else | 2961 | else |
2786 | return ret; | 2962 | return ret; |
2963 | case IEEE80211_AMPDU_TX_OPERATIONAL: | ||
2964 | /* do nothing */ | ||
2965 | return -EOPNOTSUPP; | ||
2787 | default: | 2966 | default: |
2788 | IWL_DEBUG_HT(priv, "unknown\n"); | 2967 | IWL_DEBUG_HT(priv, "unknown\n"); |
2789 | return -EINVAL; | 2968 | return -EINVAL; |
@@ -2833,6 +3012,8 @@ static void iwl_mac_sta_notify(struct ieee80211_hw *hw, | |||
2833 | break; | 3012 | break; |
2834 | case STA_NOTIFY_AWAKE: | 3013 | case STA_NOTIFY_AWAKE: |
2835 | WARN_ON(!sta_priv->client); | 3014 | WARN_ON(!sta_priv->client); |
3015 | if (!sta_priv->asleep) | ||
3016 | break; | ||
2836 | sta_priv->asleep = false; | 3017 | sta_priv->asleep = false; |
2837 | sta_id = iwl_find_station(priv, sta->addr); | 3018 | sta_id = iwl_find_station(priv, sta->addr); |
2838 | if (sta_id != IWL_INVALID_STATION) | 3019 | if (sta_id != IWL_INVALID_STATION) |
@@ -3109,7 +3290,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) | |||
3109 | 3290 | ||
3110 | init_waitqueue_head(&priv->wait_command_queue); | 3291 | init_waitqueue_head(&priv->wait_command_queue); |
3111 | 3292 | ||
3112 | INIT_WORK(&priv->up, iwl_bg_up); | ||
3113 | INIT_WORK(&priv->restart, iwl_bg_restart); | 3293 | INIT_WORK(&priv->restart, iwl_bg_restart); |
3114 | INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish); | 3294 | INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish); |
3115 | INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); | 3295 | INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); |
@@ -3126,6 +3306,10 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) | |||
3126 | priv->statistics_periodic.data = (unsigned long)priv; | 3306 | priv->statistics_periodic.data = (unsigned long)priv; |
3127 | priv->statistics_periodic.function = iwl_bg_statistics_periodic; | 3307 | priv->statistics_periodic.function = iwl_bg_statistics_periodic; |
3128 | 3308 | ||
3309 | init_timer(&priv->ucode_trace); | ||
3310 | priv->ucode_trace.data = (unsigned long)priv; | ||
3311 | priv->ucode_trace.function = iwl_bg_ucode_trace; | ||
3312 | |||
3129 | if (!priv->cfg->use_isr_legacy) | 3313 | if (!priv->cfg->use_isr_legacy) |
3130 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) | 3314 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) |
3131 | iwl_irq_tasklet, (unsigned long)priv); | 3315 | iwl_irq_tasklet, (unsigned long)priv); |
@@ -3144,6 +3328,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) | |||
3144 | cancel_delayed_work(&priv->alive_start); | 3328 | cancel_delayed_work(&priv->alive_start); |
3145 | cancel_work_sync(&priv->beacon_update); | 3329 | cancel_work_sync(&priv->beacon_update); |
3146 | del_timer_sync(&priv->statistics_periodic); | 3330 | del_timer_sync(&priv->statistics_periodic); |
3331 | del_timer_sync(&priv->ucode_trace); | ||
3147 | } | 3332 | } |
3148 | 3333 | ||
3149 | static void iwl_init_hw_rates(struct iwl_priv *priv, | 3334 | static void iwl_init_hw_rates(struct iwl_priv *priv, |
@@ -3179,6 +3364,7 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
3179 | INIT_LIST_HEAD(&priv->free_frames); | 3364 | INIT_LIST_HEAD(&priv->free_frames); |
3180 | 3365 | ||
3181 | mutex_init(&priv->mutex); | 3366 | mutex_init(&priv->mutex); |
3367 | mutex_init(&priv->sync_cmd_mutex); | ||
3182 | 3368 | ||
3183 | /* Clear the driver's (not device's) station table */ | 3369 | /* Clear the driver's (not device's) station table */ |
3184 | iwl_clear_stations_table(priv); | 3370 | iwl_clear_stations_table(priv); |
@@ -3188,6 +3374,15 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
3188 | priv->band = IEEE80211_BAND_2GHZ; | 3374 | priv->band = IEEE80211_BAND_2GHZ; |
3189 | 3375 | ||
3190 | priv->iw_mode = NL80211_IFTYPE_STATION; | 3376 | priv->iw_mode = NL80211_IFTYPE_STATION; |
3377 | priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; | ||
3378 | priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; | ||
3379 | priv->agg_tids_count = 0; | ||
3380 | |||
3381 | /* initialize force reset */ | ||
3382 | priv->force_reset[IWL_RF_RESET].reset_duration = | ||
3383 | IWL_DELAY_NEXT_FORCE_RF_RESET; | ||
3384 | priv->force_reset[IWL_FW_RESET].reset_duration = | ||
3385 | IWL_DELAY_NEXT_FORCE_FW_RELOAD; | ||
3191 | 3386 | ||
3192 | /* Choose which receivers/antennas to use */ | 3387 | /* Choose which receivers/antennas to use */ |
3193 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 3388 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
@@ -3264,7 +3459,6 @@ static struct ieee80211_ops iwl_hw_ops = { | |||
3264 | .set_key = iwl_mac_set_key, | 3459 | .set_key = iwl_mac_set_key, |
3265 | .update_tkip_key = iwl_mac_update_tkip_key, | 3460 | .update_tkip_key = iwl_mac_update_tkip_key, |
3266 | .get_stats = iwl_mac_get_stats, | 3461 | .get_stats = iwl_mac_get_stats, |
3267 | .get_tx_stats = iwl_mac_get_tx_stats, | ||
3268 | .conf_tx = iwl_mac_conf_tx, | 3462 | .conf_tx = iwl_mac_conf_tx, |
3269 | .reset_tsf = iwl_mac_reset_tsf, | 3463 | .reset_tsf = iwl_mac_reset_tsf, |
3270 | .bss_info_changed = iwl_bss_info_changed, | 3464 | .bss_info_changed = iwl_bss_info_changed, |
@@ -3365,6 +3559,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3365 | */ | 3559 | */ |
3366 | spin_lock_init(&priv->reg_lock); | 3560 | spin_lock_init(&priv->reg_lock); |
3367 | spin_lock_init(&priv->lock); | 3561 | spin_lock_init(&priv->lock); |
3562 | |||
3563 | /* | ||
3564 | * stop and reset the on-board processor just in case it is in a | ||
3565 | * strange state ... like being left stranded by a primary kernel | ||
3566 | * and this is now the kdump kernel trying to start up | ||
3567 | */ | ||
3568 | iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); | ||
3569 | |||
3368 | iwl_hw_detect(priv); | 3570 | iwl_hw_detect(priv); |
3369 | IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n", | 3571 | IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n", |
3370 | priv->cfg->name, priv->hw_rev); | 3572 | priv->cfg->name, priv->hw_rev); |
@@ -3439,9 +3641,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3439 | iwl_setup_deferred_work(priv); | 3641 | iwl_setup_deferred_work(priv); |
3440 | iwl_setup_rx_handlers(priv); | 3642 | iwl_setup_rx_handlers(priv); |
3441 | 3643 | ||
3442 | /********************************** | 3644 | /********************************************* |
3443 | * 8. Setup and register mac80211 | 3645 | * 8. Enable interrupts and read RFKILL state |
3444 | **********************************/ | 3646 | *********************************************/ |
3445 | 3647 | ||
3446 | /* enable interrupts if needed: hw bug w/a */ | 3648 | /* enable interrupts if needed: hw bug w/a */ |
3447 | pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd); | 3649 | pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd); |
@@ -3452,14 +3654,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3452 | 3654 | ||
3453 | iwl_enable_interrupts(priv); | 3655 | iwl_enable_interrupts(priv); |
3454 | 3656 | ||
3455 | err = iwl_setup_mac(priv); | ||
3456 | if (err) | ||
3457 | goto out_remove_sysfs; | ||
3458 | |||
3459 | err = iwl_dbgfs_register(priv, DRV_NAME); | ||
3460 | if (err) | ||
3461 | IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); | ||
3462 | |||
3463 | /* If platform's RF_KILL switch is NOT set to KILL */ | 3657 | /* If platform's RF_KILL switch is NOT set to KILL */ |
3464 | if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) | 3658 | if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) |
3465 | clear_bit(STATUS_RF_KILL_HW, &priv->status); | 3659 | clear_bit(STATUS_RF_KILL_HW, &priv->status); |
@@ -3471,6 +3665,18 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3471 | 3665 | ||
3472 | iwl_power_initialize(priv); | 3666 | iwl_power_initialize(priv); |
3473 | iwl_tt_initialize(priv); | 3667 | iwl_tt_initialize(priv); |
3668 | |||
3669 | /************************************************** | ||
3670 | * 9. Setup and register with mac80211 and debugfs | ||
3671 | **************************************************/ | ||
3672 | err = iwl_mac_setup_register(priv); | ||
3673 | if (err) | ||
3674 | goto out_remove_sysfs; | ||
3675 | |||
3676 | err = iwl_dbgfs_register(priv, DRV_NAME); | ||
3677 | if (err) | ||
3678 | IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); | ||
3679 | |||
3474 | return 0; | 3680 | return 0; |
3475 | 3681 | ||
3476 | out_remove_sysfs: | 3682 | out_remove_sysfs: |
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index 95a57b36a7ea..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 |
@@ -414,7 +414,6 @@ static int iwl_sens_auto_corr_ofdm(struct iwl_priv *priv, | |||
414 | /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */ | 414 | /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */ |
415 | static int iwl_sensitivity_write(struct iwl_priv *priv) | 415 | static int iwl_sensitivity_write(struct iwl_priv *priv) |
416 | { | 416 | { |
417 | int ret = 0; | ||
418 | struct iwl_sensitivity_cmd cmd ; | 417 | struct iwl_sensitivity_cmd cmd ; |
419 | struct iwl_sensitivity_data *data = NULL; | 418 | struct iwl_sensitivity_data *data = NULL; |
420 | struct iwl_host_cmd cmd_out = { | 419 | struct iwl_host_cmd cmd_out = { |
@@ -477,11 +476,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv) | |||
477 | memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]), | 476 | memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]), |
478 | sizeof(u16)*HD_TABLE_SIZE); | 477 | sizeof(u16)*HD_TABLE_SIZE); |
479 | 478 | ||
480 | ret = iwl_send_cmd(priv, &cmd_out); | 479 | return iwl_send_cmd(priv, &cmd_out); |
481 | if (ret) | ||
482 | IWL_ERR(priv, "SENSITIVITY_CMD failed\n"); | ||
483 | |||
484 | return ret; | ||
485 | } | 480 | } |
486 | 481 | ||
487 | void iwl_init_sensitivity(struct iwl_priv *priv) | 482 | void iwl_init_sensitivity(struct iwl_priv *priv) |
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 e91507531923..ab3c77b92cc8 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 |
@@ -120,7 +120,6 @@ enum { | |||
120 | CALIBRATION_COMPLETE_NOTIFICATION = 0x67, | 120 | CALIBRATION_COMPLETE_NOTIFICATION = 0x67, |
121 | 121 | ||
122 | /* 802.11h related */ | 122 | /* 802.11h related */ |
123 | RADAR_NOTIFICATION = 0x70, /* not used */ | ||
124 | REPLY_QUIET_CMD = 0x71, /* not used */ | 123 | REPLY_QUIET_CMD = 0x71, /* not used */ |
125 | REPLY_CHANNEL_SWITCH = 0x72, | 124 | REPLY_CHANNEL_SWITCH = 0x72, |
126 | CHANNEL_SWITCH_NOTIFICATION = 0x73, | 125 | CHANNEL_SWITCH_NOTIFICATION = 0x73, |
@@ -2248,10 +2247,22 @@ struct iwl_link_quality_cmd { | |||
2248 | __le32 reserved2; | 2247 | __le32 reserved2; |
2249 | } __attribute__ ((packed)); | 2248 | } __attribute__ ((packed)); |
2250 | 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 | |||
2251 | #define BT_COEX_DISABLE (0x0) | 2264 | #define BT_COEX_DISABLE (0x0) |
2252 | #define BT_COEX_MODE_2W (0x1) | 2265 | #define BT_COEX_ENABLE (BT_ENABLE_CHANNEL_ANNOUNCE | BT_ENABLE_PRIORITY) |
2253 | #define BT_COEX_MODE_3W (0x2) | ||
2254 | #define BT_COEX_MODE_4W (0x3) | ||
2255 | 2266 | ||
2256 | #define BT_LEAD_TIME_MIN (0x0) | 2267 | #define BT_LEAD_TIME_MIN (0x0) |
2257 | #define BT_LEAD_TIME_DEF (0x1E) | 2268 | #define BT_LEAD_TIME_DEF (0x1E) |
@@ -2510,7 +2521,7 @@ struct iwl_card_state_notif { | |||
2510 | 2521 | ||
2511 | #define HW_CARD_DISABLED 0x01 | 2522 | #define HW_CARD_DISABLED 0x01 |
2512 | #define SW_CARD_DISABLED 0x02 | 2523 | #define SW_CARD_DISABLED 0x02 |
2513 | #define RF_CARD_DISABLED 0x04 | 2524 | #define CT_CARD_DISABLED 0x04 |
2514 | #define RXON_CARD_DISABLED 0x10 | 2525 | #define RXON_CARD_DISABLED 0x10 |
2515 | 2526 | ||
2516 | struct iwl_ct_kill_config { | 2527 | struct iwl_ct_kill_config { |
@@ -2984,7 +2995,7 @@ struct statistics_rx_ht_phy { | |||
2984 | __le32 agg_crc32_good; | 2995 | __le32 agg_crc32_good; |
2985 | __le32 agg_mpdu_cnt; | 2996 | __le32 agg_mpdu_cnt; |
2986 | __le32 agg_cnt; | 2997 | __le32 agg_cnt; |
2987 | __le32 reserved2; | 2998 | __le32 unsupport_mcs; |
2988 | } __attribute__ ((packed)); | 2999 | } __attribute__ ((packed)); |
2989 | 3000 | ||
2990 | #define INTERFERENCE_DATA_AVAILABLE cpu_to_le32(1) | 3001 | #define INTERFERENCE_DATA_AVAILABLE cpu_to_le32(1) |
@@ -3087,8 +3098,8 @@ struct statistics_div { | |||
3087 | } __attribute__ ((packed)); | 3098 | } __attribute__ ((packed)); |
3088 | 3099 | ||
3089 | struct statistics_general { | 3100 | struct statistics_general { |
3090 | __le32 temperature; | 3101 | __le32 temperature; /* radio temperature */ |
3091 | __le32 temperature_m; | 3102 | __le32 temperature_m; /* for 5000 and up, this is radio voltage */ |
3092 | struct statistics_dbg dbg; | 3103 | struct statistics_dbg dbg; |
3093 | __le32 sleep_time; | 3104 | __le32 sleep_time; |
3094 | __le32 slots_out; | 3105 | __le32 slots_out; |
@@ -3096,7 +3107,12 @@ struct statistics_general { | |||
3096 | __le32 ttl_timestamp; | 3107 | __le32 ttl_timestamp; |
3097 | struct statistics_div div; | 3108 | struct statistics_div div; |
3098 | __le32 rx_enable_counter; | 3109 | __le32 rx_enable_counter; |
3099 | __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; | ||
3100 | __le32 reserved2; | 3116 | __le32 reserved2; |
3101 | __le32 reserved3; | 3117 | __le32 reserved3; |
3102 | } __attribute__ ((packed)); | 3118 | } __attribute__ ((packed)); |
@@ -3161,13 +3177,30 @@ struct iwl_notif_statistics { | |||
3161 | 3177 | ||
3162 | /* | 3178 | /* |
3163 | * 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 | * | ||
3164 | */ | 3196 | */ |
3165 | /* if ucode missed CONSECUTIVE_MISSED_BCONS_TH beacons in a row, | 3197 | |
3166 | * then this notification will be sent. */ | 3198 | #define IWL_MISSED_BEACON_THRESHOLD_MIN (1) |
3167 | #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 | ||
3168 | 3201 | ||
3169 | struct iwl_missed_beacon_notif { | 3202 | struct iwl_missed_beacon_notif { |
3170 | __le32 consequtive_missed_beacons; | 3203 | __le32 consecutive_missed_beacons; |
3171 | __le32 total_missed_becons; | 3204 | __le32 total_missed_becons; |
3172 | __le32 num_expected_beacons; | 3205 | __le32 num_expected_beacons; |
3173 | __le32 num_recvd_beacons; | 3206 | __le32 num_recvd_beacons; |
@@ -3437,11 +3470,7 @@ enum { | |||
3437 | IWL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7, | 3470 | IWL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7, |
3438 | IWL_PHY_CALIBRATE_DC_CMD = 8, | 3471 | IWL_PHY_CALIBRATE_DC_CMD = 8, |
3439 | IWL_PHY_CALIBRATE_LO_CMD = 9, | 3472 | IWL_PHY_CALIBRATE_LO_CMD = 9, |
3440 | IWL_PHY_CALIBRATE_RX_BB_CMD = 10, | ||
3441 | IWL_PHY_CALIBRATE_TX_IQ_CMD = 11, | 3473 | IWL_PHY_CALIBRATE_TX_IQ_CMD = 11, |
3442 | IWL_PHY_CALIBRATE_RX_IQ_CMD = 12, | ||
3443 | IWL_PHY_CALIBRATION_NOISE_CMD = 13, | ||
3444 | IWL_PHY_CALIBRATE_AGC_TABLE_CMD = 14, | ||
3445 | IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15, | 3474 | IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15, |
3446 | IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16, | 3475 | IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16, |
3447 | IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17, | 3476 | IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index f36f804804fc..112149e9b31e 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 | ||
@@ -450,8 +470,6 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, | |||
450 | if (priv->cfg->ht_greenfield_support) | 470 | if (priv->cfg->ht_greenfield_support) |
451 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; | 471 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; |
452 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; | 472 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; |
453 | ht_info->cap |= (IEEE80211_HT_CAP_SM_PS & | ||
454 | (priv->cfg->sm_ps_mode << 2)); | ||
455 | max_bit_rate = MAX_BIT_RATE_20_MHZ; | 473 | max_bit_rate = MAX_BIT_RATE_20_MHZ; |
456 | if (priv->hw_params.ht40_channel & BIT(band)) { | 474 | if (priv->hw_params.ht40_channel & BIT(band)) { |
457 | ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 475 | ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
@@ -636,7 +654,7 @@ EXPORT_SYMBOL(iwlcore_rts_tx_cmd_flag); | |||
636 | 654 | ||
637 | static bool is_single_rx_stream(struct iwl_priv *priv) | 655 | static bool is_single_rx_stream(struct iwl_priv *priv) |
638 | { | 656 | { |
639 | return !priv->current_ht_config.is_ht || | 657 | return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC || |
640 | priv->current_ht_config.single_chain_sufficient; | 658 | priv->current_ht_config.single_chain_sufficient; |
641 | } | 659 | } |
642 | 660 | ||
@@ -1003,28 +1021,18 @@ static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) | |||
1003 | */ | 1021 | */ |
1004 | static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) | 1022 | static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) |
1005 | { | 1023 | { |
1006 | int idle_cnt = active_cnt; | 1024 | /* # Rx chains when idling, depending on SMPS mode */ |
1007 | bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); | 1025 | switch (priv->current_ht_config.smps) { |
1008 | 1026 | case IEEE80211_SMPS_STATIC: | |
1009 | /* # Rx chains when idling and maybe trying to save power */ | 1027 | case IEEE80211_SMPS_DYNAMIC: |
1010 | switch (priv->cfg->sm_ps_mode) { | 1028 | return IWL_NUM_IDLE_CHAINS_SINGLE; |
1011 | case WLAN_HT_CAP_SM_PS_STATIC: | 1029 | case IEEE80211_SMPS_OFF: |
1012 | idle_cnt = (is_cam) ? active_cnt : IWL_NUM_IDLE_CHAINS_SINGLE; | 1030 | return active_cnt; |
1013 | break; | ||
1014 | case WLAN_HT_CAP_SM_PS_DYNAMIC: | ||
1015 | idle_cnt = (is_cam) ? IWL_NUM_IDLE_CHAINS_DUAL : | ||
1016 | IWL_NUM_IDLE_CHAINS_SINGLE; | ||
1017 | break; | ||
1018 | case WLAN_HT_CAP_SM_PS_DISABLED: | ||
1019 | break; | ||
1020 | case WLAN_HT_CAP_SM_PS_INVALID: | ||
1021 | default: | 1031 | default: |
1022 | IWL_ERR(priv, "invalid sm_ps mode %u\n", | 1032 | WARN(1, "invalid SMPS mode %d", |
1023 | priv->cfg->sm_ps_mode); | 1033 | priv->current_ht_config.smps); |
1024 | WARN_ON(1); | 1034 | return active_cnt; |
1025 | break; | ||
1026 | } | 1035 | } |
1027 | return idle_cnt; | ||
1028 | } | 1036 | } |
1029 | 1037 | ||
1030 | /* up to 4 chains */ | 1038 | /* up to 4 chains */ |
@@ -1363,7 +1371,11 @@ void iwl_irq_handle_error(struct iwl_priv *priv) | |||
1363 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | 1371 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); |
1364 | 1372 | ||
1365 | priv->cfg->ops->lib->dump_nic_error_log(priv); | 1373 | priv->cfg->ops->lib->dump_nic_error_log(priv); |
1366 | priv->cfg->ops->lib->dump_nic_event_log(priv, false); | 1374 | if (priv->cfg->ops->lib->dump_csr) |
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); | ||
1378 | priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false); | ||
1367 | #ifdef CONFIG_IWLWIFI_DEBUG | 1379 | #ifdef CONFIG_IWLWIFI_DEBUG |
1368 | if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) | 1380 | if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) |
1369 | iwl_print_rx_config_cmd(priv); | 1381 | iwl_print_rx_config_cmd(priv); |
@@ -1658,9 +1670,9 @@ EXPORT_SYMBOL(iwl_set_tx_power); | |||
1658 | void iwl_free_isr_ict(struct iwl_priv *priv) | 1670 | void iwl_free_isr_ict(struct iwl_priv *priv) |
1659 | { | 1671 | { |
1660 | if (priv->ict_tbl_vir) { | 1672 | if (priv->ict_tbl_vir) { |
1661 | pci_free_consistent(priv->pci_dev, (sizeof(u32) * ICT_COUNT) + | 1673 | dma_free_coherent(&priv->pci_dev->dev, |
1662 | PAGE_SIZE, priv->ict_tbl_vir, | 1674 | (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, |
1663 | priv->ict_tbl_dma); | 1675 | priv->ict_tbl_vir, priv->ict_tbl_dma); |
1664 | priv->ict_tbl_vir = NULL; | 1676 | priv->ict_tbl_vir = NULL; |
1665 | } | 1677 | } |
1666 | } | 1678 | } |
@@ -1676,9 +1688,9 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv) | |||
1676 | if (priv->cfg->use_isr_legacy) | 1688 | if (priv->cfg->use_isr_legacy) |
1677 | return 0; | 1689 | return 0; |
1678 | /* allocate shrared data table */ | 1690 | /* allocate shrared data table */ |
1679 | priv->ict_tbl_vir = pci_alloc_consistent(priv->pci_dev, (sizeof(u32) * | 1691 | priv->ict_tbl_vir = dma_alloc_coherent(&priv->pci_dev->dev, |
1680 | ICT_COUNT) + PAGE_SIZE, | 1692 | (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, |
1681 | &priv->ict_tbl_dma); | 1693 | &priv->ict_tbl_dma, GFP_KERNEL); |
1682 | if (!priv->ict_tbl_vir) | 1694 | if (!priv->ict_tbl_vir) |
1683 | return -ENOMEM; | 1695 | return -ENOMEM; |
1684 | 1696 | ||
@@ -1813,6 +1825,16 @@ irqreturn_t iwl_isr_ict(int irq, void *data) | |||
1813 | if (val == 0xffffffff) | 1825 | if (val == 0xffffffff) |
1814 | val = 0; | 1826 | val = 0; |
1815 | 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 | |||
1816 | inta = (0xff & val) | ((0xff00 & val) << 16); | 1838 | inta = (0xff & val) | ((0xff00 & val) << 16); |
1817 | 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", |
1818 | inta, inta_mask, val); | 1840 | inta, inta_mask, val); |
@@ -1975,13 +1997,20 @@ EXPORT_SYMBOL(iwl_isr_legacy); | |||
1975 | int iwl_send_bt_config(struct iwl_priv *priv) | 1997 | int iwl_send_bt_config(struct iwl_priv *priv) |
1976 | { | 1998 | { |
1977 | struct iwl_bt_cmd bt_cmd = { | 1999 | struct iwl_bt_cmd bt_cmd = { |
1978 | .flags = BT_COEX_MODE_4W, | ||
1979 | .lead_time = BT_LEAD_TIME_DEF, | 2000 | .lead_time = BT_LEAD_TIME_DEF, |
1980 | .max_kill = BT_MAX_KILL_DEF, | 2001 | .max_kill = BT_MAX_KILL_DEF, |
1981 | .kill_ack_mask = 0, | 2002 | .kill_ack_mask = 0, |
1982 | .kill_cts_mask = 0, | 2003 | .kill_cts_mask = 0, |
1983 | }; | 2004 | }; |
1984 | 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 | |||
1985 | return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, | 2014 | return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, |
1986 | sizeof(struct iwl_bt_cmd), &bt_cmd); | 2015 | sizeof(struct iwl_bt_cmd), &bt_cmd); |
1987 | } | 2016 | } |
@@ -2599,44 +2628,43 @@ int iwl_set_mode(struct iwl_priv *priv, int mode) | |||
2599 | EXPORT_SYMBOL(iwl_set_mode); | 2628 | EXPORT_SYMBOL(iwl_set_mode); |
2600 | 2629 | ||
2601 | int iwl_mac_add_interface(struct ieee80211_hw *hw, | 2630 | int iwl_mac_add_interface(struct ieee80211_hw *hw, |
2602 | struct ieee80211_if_init_conf *conf) | 2631 | struct ieee80211_vif *vif) |
2603 | { | 2632 | { |
2604 | struct iwl_priv *priv = hw->priv; | 2633 | struct iwl_priv *priv = hw->priv; |
2605 | unsigned long flags; | 2634 | int err = 0; |
2606 | 2635 | ||
2607 | IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type); | 2636 | IWL_DEBUG_MAC80211(priv, "enter: type %d\n", vif->type); |
2637 | |||
2638 | mutex_lock(&priv->mutex); | ||
2608 | 2639 | ||
2609 | if (priv->vif) { | 2640 | if (priv->vif) { |
2610 | IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); | 2641 | IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); |
2611 | return -EOPNOTSUPP; | 2642 | err = -EOPNOTSUPP; |
2643 | goto out; | ||
2612 | } | 2644 | } |
2613 | 2645 | ||
2614 | spin_lock_irqsave(&priv->lock, flags); | 2646 | priv->vif = vif; |
2615 | priv->vif = conf->vif; | 2647 | priv->iw_mode = vif->type; |
2616 | priv->iw_mode = conf->type; | ||
2617 | |||
2618 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2619 | |||
2620 | mutex_lock(&priv->mutex); | ||
2621 | 2648 | ||
2622 | if (conf->mac_addr) { | 2649 | if (vif->addr) { |
2623 | IWL_DEBUG_MAC80211(priv, "Set %pM\n", conf->mac_addr); | 2650 | IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr); |
2624 | memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); | 2651 | memcpy(priv->mac_addr, vif->addr, ETH_ALEN); |
2625 | } | 2652 | } |
2626 | 2653 | ||
2627 | if (iwl_set_mode(priv, conf->type) == -EAGAIN) | 2654 | if (iwl_set_mode(priv, vif->type) == -EAGAIN) |
2628 | /* we are not ready, will run again when ready */ | 2655 | /* we are not ready, will run again when ready */ |
2629 | set_bit(STATUS_MODE_PENDING, &priv->status); | 2656 | set_bit(STATUS_MODE_PENDING, &priv->status); |
2630 | 2657 | ||
2658 | out: | ||
2631 | mutex_unlock(&priv->mutex); | 2659 | mutex_unlock(&priv->mutex); |
2632 | 2660 | ||
2633 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 2661 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
2634 | return 0; | 2662 | return err; |
2635 | } | 2663 | } |
2636 | EXPORT_SYMBOL(iwl_mac_add_interface); | 2664 | EXPORT_SYMBOL(iwl_mac_add_interface); |
2637 | 2665 | ||
2638 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, | 2666 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, |
2639 | struct ieee80211_if_init_conf *conf) | 2667 | struct ieee80211_vif *vif) |
2640 | { | 2668 | { |
2641 | struct iwl_priv *priv = hw->priv; | 2669 | struct iwl_priv *priv = hw->priv; |
2642 | 2670 | ||
@@ -2649,7 +2677,7 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, | |||
2649 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2677 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
2650 | iwlcore_commit_rxon(priv); | 2678 | iwlcore_commit_rxon(priv); |
2651 | } | 2679 | } |
2652 | if (priv->vif == conf->vif) { | 2680 | if (priv->vif == vif) { |
2653 | priv->vif = NULL; | 2681 | priv->vif = NULL; |
2654 | memset(priv->bssid, 0, ETH_ALEN); | 2682 | memset(priv->bssid, 0, ETH_ALEN); |
2655 | } | 2683 | } |
@@ -2689,6 +2717,21 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2689 | IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); | 2717 | IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); |
2690 | } | 2718 | } |
2691 | 2719 | ||
2720 | if (changed & (IEEE80211_CONF_CHANGE_SMPS | | ||
2721 | IEEE80211_CONF_CHANGE_CHANNEL)) { | ||
2722 | /* mac80211 uses static for non-HT which is what we want */ | ||
2723 | priv->current_ht_config.smps = conf->smps_mode; | ||
2724 | |||
2725 | /* | ||
2726 | * Recalculate chain counts. | ||
2727 | * | ||
2728 | * If monitor mode is enabled then mac80211 will | ||
2729 | * set up the SM PS mode to OFF if an HT channel is | ||
2730 | * configured. | ||
2731 | */ | ||
2732 | if (priv->cfg->ops->hcmd->set_rxon_chain) | ||
2733 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | ||
2734 | } | ||
2692 | 2735 | ||
2693 | /* during scanning mac80211 will delay channel setting until | 2736 | /* during scanning mac80211 will delay channel setting until |
2694 | * scan finish with changed = 0 | 2737 | * scan finish with changed = 0 |
@@ -2786,10 +2829,6 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2786 | iwl_set_tx_power(priv, conf->power_level, false); | 2829 | iwl_set_tx_power(priv, conf->power_level, false); |
2787 | } | 2830 | } |
2788 | 2831 | ||
2789 | /* call to ensure that 4965 rx_chain is set properly in monitor mode */ | ||
2790 | if (priv->cfg->ops->hcmd->set_rxon_chain) | ||
2791 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | ||
2792 | |||
2793 | if (!iwl_is_ready(priv)) { | 2832 | if (!iwl_is_ready(priv)) { |
2794 | IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); | 2833 | IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); |
2795 | goto out; | 2834 | goto out; |
@@ -2812,42 +2851,6 @@ out: | |||
2812 | } | 2851 | } |
2813 | EXPORT_SYMBOL(iwl_mac_config); | 2852 | EXPORT_SYMBOL(iwl_mac_config); |
2814 | 2853 | ||
2815 | int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, | ||
2816 | struct ieee80211_tx_queue_stats *stats) | ||
2817 | { | ||
2818 | struct iwl_priv *priv = hw->priv; | ||
2819 | int i, avail; | ||
2820 | struct iwl_tx_queue *txq; | ||
2821 | struct iwl_queue *q; | ||
2822 | unsigned long flags; | ||
2823 | |||
2824 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
2825 | |||
2826 | if (!iwl_is_ready_rf(priv)) { | ||
2827 | IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); | ||
2828 | return -EIO; | ||
2829 | } | ||
2830 | |||
2831 | spin_lock_irqsave(&priv->lock, flags); | ||
2832 | |||
2833 | for (i = 0; i < AC_NUM; i++) { | ||
2834 | txq = &priv->txq[i]; | ||
2835 | q = &txq->q; | ||
2836 | avail = iwl_queue_space(q); | ||
2837 | |||
2838 | stats[i].len = q->n_window - avail; | ||
2839 | stats[i].limit = q->n_window - q->high_mark; | ||
2840 | stats[i].count = q->n_window; | ||
2841 | |||
2842 | } | ||
2843 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2844 | |||
2845 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
2846 | |||
2847 | return 0; | ||
2848 | } | ||
2849 | EXPORT_SYMBOL(iwl_mac_get_tx_stats); | ||
2850 | |||
2851 | void iwl_mac_reset_tsf(struct ieee80211_hw *hw) | 2854 | void iwl_mac_reset_tsf(struct ieee80211_hw *hw) |
2852 | { | 2855 | { |
2853 | struct iwl_priv *priv = hw->priv; | 2856 | struct iwl_priv *priv = hw->priv; |
@@ -3197,6 +3200,207 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len) | |||
3197 | EXPORT_SYMBOL(iwl_update_stats); | 3200 | EXPORT_SYMBOL(iwl_update_stats); |
3198 | #endif | 3201 | #endif |
3199 | 3202 | ||
3203 | const static char *get_csr_string(int cmd) | ||
3204 | { | ||
3205 | switch (cmd) { | ||
3206 | IWL_CMD(CSR_HW_IF_CONFIG_REG); | ||
3207 | IWL_CMD(CSR_INT_COALESCING); | ||
3208 | IWL_CMD(CSR_INT); | ||
3209 | IWL_CMD(CSR_INT_MASK); | ||
3210 | IWL_CMD(CSR_FH_INT_STATUS); | ||
3211 | IWL_CMD(CSR_GPIO_IN); | ||
3212 | IWL_CMD(CSR_RESET); | ||
3213 | IWL_CMD(CSR_GP_CNTRL); | ||
3214 | IWL_CMD(CSR_HW_REV); | ||
3215 | IWL_CMD(CSR_EEPROM_REG); | ||
3216 | IWL_CMD(CSR_EEPROM_GP); | ||
3217 | IWL_CMD(CSR_OTP_GP_REG); | ||
3218 | IWL_CMD(CSR_GIO_REG); | ||
3219 | IWL_CMD(CSR_GP_UCODE_REG); | ||
3220 | IWL_CMD(CSR_GP_DRIVER_REG); | ||
3221 | IWL_CMD(CSR_UCODE_DRV_GP1); | ||
3222 | IWL_CMD(CSR_UCODE_DRV_GP2); | ||
3223 | IWL_CMD(CSR_LED_REG); | ||
3224 | IWL_CMD(CSR_DRAM_INT_TBL_REG); | ||
3225 | IWL_CMD(CSR_GIO_CHICKEN_BITS); | ||
3226 | IWL_CMD(CSR_ANA_PLL_CFG); | ||
3227 | IWL_CMD(CSR_HW_REV_WA_REG); | ||
3228 | IWL_CMD(CSR_DBG_HPET_MEM_REG); | ||
3229 | default: | ||
3230 | return "UNKNOWN"; | ||
3231 | |||
3232 | } | ||
3233 | } | ||
3234 | |||
3235 | void iwl_dump_csr(struct iwl_priv *priv) | ||
3236 | { | ||
3237 | int i; | ||
3238 | u32 csr_tbl[] = { | ||
3239 | CSR_HW_IF_CONFIG_REG, | ||
3240 | CSR_INT_COALESCING, | ||
3241 | CSR_INT, | ||
3242 | CSR_INT_MASK, | ||
3243 | CSR_FH_INT_STATUS, | ||
3244 | CSR_GPIO_IN, | ||
3245 | CSR_RESET, | ||
3246 | CSR_GP_CNTRL, | ||
3247 | CSR_HW_REV, | ||
3248 | CSR_EEPROM_REG, | ||
3249 | CSR_EEPROM_GP, | ||
3250 | CSR_OTP_GP_REG, | ||
3251 | CSR_GIO_REG, | ||
3252 | CSR_GP_UCODE_REG, | ||
3253 | CSR_GP_DRIVER_REG, | ||
3254 | CSR_UCODE_DRV_GP1, | ||
3255 | CSR_UCODE_DRV_GP2, | ||
3256 | CSR_LED_REG, | ||
3257 | CSR_DRAM_INT_TBL_REG, | ||
3258 | CSR_GIO_CHICKEN_BITS, | ||
3259 | CSR_ANA_PLL_CFG, | ||
3260 | CSR_HW_REV_WA_REG, | ||
3261 | CSR_DBG_HPET_MEM_REG | ||
3262 | }; | ||
3263 | IWL_ERR(priv, "CSR values:\n"); | ||
3264 | IWL_ERR(priv, "(2nd byte of CSR_INT_COALESCING is " | ||
3265 | "CSR_INT_PERIODIC_REG)\n"); | ||
3266 | for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) { | ||
3267 | IWL_ERR(priv, " %25s: 0X%08x\n", | ||
3268 | get_csr_string(csr_tbl[i]), | ||
3269 | iwl_read32(priv, csr_tbl[i])); | ||
3270 | } | ||
3271 | } | ||
3272 | EXPORT_SYMBOL(iwl_dump_csr); | ||
3273 | |||
3274 | const static char *get_fh_string(int cmd) | ||
3275 | { | ||
3276 | switch (cmd) { | ||
3277 | IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); | ||
3278 | IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG); | ||
3279 | IWL_CMD(FH_RSCSR_CHNL0_WPTR); | ||
3280 | IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG); | ||
3281 | IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG); | ||
3282 | IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG); | ||
3283 | IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV); | ||
3284 | IWL_CMD(FH_TSSR_TX_STATUS_REG); | ||
3285 | IWL_CMD(FH_TSSR_TX_ERROR_REG); | ||
3286 | default: | ||
3287 | return "UNKNOWN"; | ||
3288 | |||
3289 | } | ||
3290 | } | ||
3291 | |||
3292 | int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display) | ||
3293 | { | ||
3294 | int i; | ||
3295 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
3296 | int pos = 0; | ||
3297 | size_t bufsz = 0; | ||
3298 | #endif | ||
3299 | u32 fh_tbl[] = { | ||
3300 | FH_RSCSR_CHNL0_STTS_WPTR_REG, | ||
3301 | FH_RSCSR_CHNL0_RBDCB_BASE_REG, | ||
3302 | FH_RSCSR_CHNL0_WPTR, | ||
3303 | FH_MEM_RCSR_CHNL0_CONFIG_REG, | ||
3304 | FH_MEM_RSSR_SHARED_CTRL_REG, | ||
3305 | FH_MEM_RSSR_RX_STATUS_REG, | ||
3306 | FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV, | ||
3307 | FH_TSSR_TX_STATUS_REG, | ||
3308 | FH_TSSR_TX_ERROR_REG | ||
3309 | }; | ||
3310 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
3311 | if (display) { | ||
3312 | bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; | ||
3313 | *buf = kmalloc(bufsz, GFP_KERNEL); | ||
3314 | if (!*buf) | ||
3315 | return -ENOMEM; | ||
3316 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
3317 | "FH register values:\n"); | ||
3318 | for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { | ||
3319 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
3320 | " %34s: 0X%08x\n", | ||
3321 | get_fh_string(fh_tbl[i]), | ||
3322 | iwl_read_direct32(priv, fh_tbl[i])); | ||
3323 | } | ||
3324 | return pos; | ||
3325 | } | ||
3326 | #endif | ||
3327 | IWL_ERR(priv, "FH register values:\n"); | ||
3328 | for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { | ||
3329 | IWL_ERR(priv, " %34s: 0X%08x\n", | ||
3330 | get_fh_string(fh_tbl[i]), | ||
3331 | iwl_read_direct32(priv, fh_tbl[i])); | ||
3332 | } | ||
3333 | return 0; | ||
3334 | } | ||
3335 | EXPORT_SYMBOL(iwl_dump_fh); | ||
3336 | |||
3337 | static void iwl_force_rf_reset(struct iwl_priv *priv) | ||
3338 | { | ||
3339 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
3340 | return; | ||
3341 | |||
3342 | if (!iwl_is_associated(priv)) { | ||
3343 | IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n"); | ||
3344 | return; | ||
3345 | } | ||
3346 | /* | ||
3347 | * There is no easy and better way to force reset the radio, | ||
3348 | * the only known method is switching channel which will force to | ||
3349 | * reset and tune the radio. | ||
3350 | * Use internal short scan (single channel) operation to should | ||
3351 | * achieve this objective. | ||
3352 | * Driver should reset the radio when number of consecutive missed | ||
3353 | * beacon, or any other uCode error condition detected. | ||
3354 | */ | ||
3355 | IWL_DEBUG_INFO(priv, "perform radio reset.\n"); | ||
3356 | iwl_internal_short_hw_scan(priv); | ||
3357 | return; | ||
3358 | } | ||
3359 | |||
3360 | |||
3361 | int iwl_force_reset(struct iwl_priv *priv, int mode) | ||
3362 | { | ||
3363 | struct iwl_force_reset *force_reset; | ||
3364 | |||
3365 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
3366 | return -EINVAL; | ||
3367 | |||
3368 | if (mode >= IWL_MAX_FORCE_RESET) { | ||
3369 | IWL_DEBUG_INFO(priv, "invalid reset request.\n"); | ||
3370 | return -EINVAL; | ||
3371 | } | ||
3372 | force_reset = &priv->force_reset[mode]; | ||
3373 | force_reset->reset_request_count++; | ||
3374 | if (force_reset->last_force_reset_jiffies && | ||
3375 | time_after(force_reset->last_force_reset_jiffies + | ||
3376 | force_reset->reset_duration, jiffies)) { | ||
3377 | IWL_DEBUG_INFO(priv, "force reset rejected\n"); | ||
3378 | force_reset->reset_reject_count++; | ||
3379 | return -EAGAIN; | ||
3380 | } | ||
3381 | force_reset->reset_success_count++; | ||
3382 | force_reset->last_force_reset_jiffies = jiffies; | ||
3383 | IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode); | ||
3384 | switch (mode) { | ||
3385 | case IWL_RF_RESET: | ||
3386 | iwl_force_rf_reset(priv); | ||
3387 | break; | ||
3388 | case IWL_FW_RESET: | ||
3389 | IWL_ERR(priv, "On demand firmware reload\n"); | ||
3390 | /* Set the FW error flag -- cleared on iwl_down */ | ||
3391 | set_bit(STATUS_FW_ERROR, &priv->status); | ||
3392 | wake_up_interruptible(&priv->wait_command_queue); | ||
3393 | /* | ||
3394 | * Keep the restart process from trying to send host | ||
3395 | * commands by clearing the INIT status bit | ||
3396 | */ | ||
3397 | clear_bit(STATUS_READY, &priv->status); | ||
3398 | queue_work(priv->workqueue, &priv->restart); | ||
3399 | break; | ||
3400 | } | ||
3401 | return 0; | ||
3402 | } | ||
3403 | |||
3200 | #ifdef CONFIG_PM | 3404 | #ifdef CONFIG_PM |
3201 | 3405 | ||
3202 | int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) | 3406 | 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 fe37d6a6bf97..4ef7739f9e8e 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 |
@@ -63,8 +63,6 @@ | |||
63 | #ifndef __iwl_core_h__ | 63 | #ifndef __iwl_core_h__ |
64 | #define __iwl_core_h__ | 64 | #define __iwl_core_h__ |
65 | 65 | ||
66 | #include <linux/utsrelease.h> | ||
67 | |||
68 | /************************ | 66 | /************************ |
69 | * forward declarations * | 67 | * forward declarations * |
70 | ************************/ | 68 | ************************/ |
@@ -72,8 +70,8 @@ struct iwl_host_cmd; | |||
72 | struct iwl_cmd; | 70 | struct iwl_cmd; |
73 | 71 | ||
74 | 72 | ||
75 | #define IWLWIFI_VERSION UTS_RELEASE "-k" | 73 | #define IWLWIFI_VERSION "in-tree:" |
76 | #define DRV_COPYRIGHT "Copyright(c) 2003-2009 Intel Corporation" | 74 | #define DRV_COPYRIGHT "Copyright(c) 2003-2010 Intel Corporation" |
77 | #define DRV_AUTHOR "<ilw@linux.intel.com>" | 75 | #define DRV_AUTHOR "<ilw@linux.intel.com>" |
78 | 76 | ||
79 | #define IWL_PCI_DEVICE(dev, subdev, cfg) \ | 77 | #define IWL_PCI_DEVICE(dev, subdev, cfg) \ |
@@ -119,6 +117,7 @@ struct iwl_apm_ops { | |||
119 | struct iwl_temp_ops { | 117 | struct iwl_temp_ops { |
120 | void (*temperature)(struct iwl_priv *priv); | 118 | void (*temperature)(struct iwl_priv *priv); |
121 | void (*set_ct_kill)(struct iwl_priv *priv); | 119 | void (*set_ct_kill)(struct iwl_priv *priv); |
120 | void (*set_calib_version)(struct iwl_priv *priv); | ||
122 | }; | 121 | }; |
123 | 122 | ||
124 | struct iwl_ucode_ops { | 123 | struct iwl_ucode_ops { |
@@ -169,8 +168,11 @@ struct iwl_lib_ops { | |||
169 | int (*is_valid_rtc_data_addr)(u32 addr); | 168 | int (*is_valid_rtc_data_addr)(u32 addr); |
170 | /* 1st ucode load */ | 169 | /* 1st ucode load */ |
171 | int (*load_ucode)(struct iwl_priv *priv); | 170 | int (*load_ucode)(struct iwl_priv *priv); |
172 | void (*dump_nic_event_log)(struct iwl_priv *priv, bool full_log); | 171 | int (*dump_nic_event_log)(struct iwl_priv *priv, |
172 | bool full_log, char **buf, bool display); | ||
173 | void (*dump_nic_error_log)(struct iwl_priv *priv); | 173 | void (*dump_nic_error_log)(struct iwl_priv *priv); |
174 | void (*dump_csr)(struct iwl_priv *priv); | ||
175 | int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display); | ||
174 | int (*set_channel_switch)(struct iwl_priv *priv, u16 channel); | 176 | int (*set_channel_switch)(struct iwl_priv *priv, u16 channel); |
175 | /* power management */ | 177 | /* power management */ |
176 | struct iwl_apm_ops apm_ops; | 178 | struct iwl_apm_ops apm_ops; |
@@ -187,6 +189,8 @@ struct iwl_lib_ops { | |||
187 | 189 | ||
188 | /* temperature */ | 190 | /* temperature */ |
189 | struct iwl_temp_ops temp_ops; | 191 | struct iwl_temp_ops temp_ops; |
192 | /* station management */ | ||
193 | void (*add_bcast_station)(struct iwl_priv *priv); | ||
190 | }; | 194 | }; |
191 | 195 | ||
192 | struct iwl_led_ops { | 196 | struct iwl_led_ops { |
@@ -230,8 +234,9 @@ struct iwl_mod_params { | |||
230 | * @chain_noise_num_beacons: number of beacons used to compute chain noise | 234 | * @chain_noise_num_beacons: number of beacons used to compute chain noise |
231 | * @adv_thermal_throttle: support advance thermal throttle | 235 | * @adv_thermal_throttle: support advance thermal throttle |
232 | * @support_ct_kill_exit: support ct kill exit condition | 236 | * @support_ct_kill_exit: support ct kill exit condition |
233 | * @sm_ps_mode: spatial multiplexing power save mode | ||
234 | * @support_wimax_coexist: support wimax/wifi co-exist | 237 | * @support_wimax_coexist: support wimax/wifi co-exist |
238 | * @plcp_delta_threshold: plcp error rate threshold used to trigger | ||
239 | * radio tuning when there is a high receiving plcp error rate | ||
235 | * | 240 | * |
236 | * We enable the driver to be backward compatible wrt API version. The | 241 | * We enable the driver to be backward compatible wrt API version. The |
237 | * driver specifies which APIs it supports (with @ucode_api_max being the | 242 | * driver specifies which APIs it supports (with @ucode_api_max being the |
@@ -287,8 +292,9 @@ struct iwl_cfg { | |||
287 | const bool supports_idle; | 292 | const bool supports_idle; |
288 | bool adv_thermal_throttle; | 293 | bool adv_thermal_throttle; |
289 | bool support_ct_kill_exit; | 294 | bool support_ct_kill_exit; |
290 | u8 sm_ps_mode; | ||
291 | const bool support_wimax_coexist; | 295 | const bool support_wimax_coexist; |
296 | u8 plcp_delta_threshold; | ||
297 | s32 chain_noise_scale; | ||
292 | }; | 298 | }; |
293 | 299 | ||
294 | /*************************** | 300 | /*************************** |
@@ -332,13 +338,11 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); | |||
332 | int iwl_commit_rxon(struct iwl_priv *priv); | 338 | int iwl_commit_rxon(struct iwl_priv *priv); |
333 | int iwl_set_mode(struct iwl_priv *priv, int mode); | 339 | int iwl_set_mode(struct iwl_priv *priv, int mode); |
334 | int iwl_mac_add_interface(struct ieee80211_hw *hw, | 340 | int iwl_mac_add_interface(struct ieee80211_hw *hw, |
335 | struct ieee80211_if_init_conf *conf); | 341 | struct ieee80211_vif *vif); |
336 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, | 342 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, |
337 | struct ieee80211_if_init_conf *conf); | 343 | struct ieee80211_vif *vif); |
338 | int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); | 344 | int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); |
339 | void iwl_config_ap(struct iwl_priv *priv); | 345 | void iwl_config_ap(struct iwl_priv *priv); |
340 | int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, | ||
341 | struct ieee80211_tx_queue_stats *stats); | ||
342 | void iwl_mac_reset_tsf(struct ieee80211_hw *hw); | 346 | void iwl_mac_reset_tsf(struct ieee80211_hw *hw); |
343 | int iwl_alloc_txq_mem(struct iwl_priv *priv); | 347 | int iwl_alloc_txq_mem(struct iwl_priv *priv); |
344 | void iwl_free_txq_mem(struct iwl_priv *priv); | 348 | void iwl_free_txq_mem(struct iwl_priv *priv); |
@@ -411,13 +415,13 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | |||
411 | void iwl_cmd_queue_free(struct iwl_priv *priv); | 415 | void iwl_cmd_queue_free(struct iwl_priv *priv); |
412 | int iwl_rx_queue_alloc(struct iwl_priv *priv); | 416 | int iwl_rx_queue_alloc(struct iwl_priv *priv); |
413 | void iwl_rx_handle(struct iwl_priv *priv); | 417 | void iwl_rx_handle(struct iwl_priv *priv); |
414 | int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, | 418 | void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, |
415 | struct iwl_rx_queue *q); | 419 | struct iwl_rx_queue *q); |
416 | void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | 420 | void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); |
417 | void iwl_rx_replenish(struct iwl_priv *priv); | 421 | void iwl_rx_replenish(struct iwl_priv *priv); |
418 | void iwl_rx_replenish_now(struct iwl_priv *priv); | 422 | void iwl_rx_replenish_now(struct iwl_priv *priv); |
419 | int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | 423 | int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); |
420 | int iwl_rx_queue_restock(struct iwl_priv *priv); | 424 | void iwl_rx_queue_restock(struct iwl_priv *priv); |
421 | int iwl_rx_queue_space(const struct iwl_rx_queue *q); | 425 | int iwl_rx_queue_space(const struct iwl_rx_queue *q); |
422 | void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority); | 426 | void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority); |
423 | void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | 427 | void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); |
@@ -425,6 +429,8 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); | |||
425 | /* Handlers */ | 429 | /* Handlers */ |
426 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | 430 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, |
427 | 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); | ||
428 | void iwl_rx_statistics(struct iwl_priv *priv, | 434 | void iwl_rx_statistics(struct iwl_priv *priv, |
429 | struct iwl_rx_mem_buffer *rxb); | 435 | struct iwl_rx_mem_buffer *rxb); |
430 | void iwl_reply_statistics(struct iwl_priv *priv, | 436 | void iwl_reply_statistics(struct iwl_priv *priv, |
@@ -445,9 +451,9 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); | |||
445 | void iwl_hw_txq_ctx_free(struct iwl_priv *priv); | 451 | void iwl_hw_txq_ctx_free(struct iwl_priv *priv); |
446 | int iwl_hw_tx_queue_init(struct iwl_priv *priv, | 452 | int iwl_hw_tx_queue_init(struct iwl_priv *priv, |
447 | struct iwl_tx_queue *txq); | 453 | struct iwl_tx_queue *txq); |
448 | int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); | ||
449 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, | 454 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, |
450 | int sta_id, int tid, int freed); | 455 | int sta_id, int tid, int freed); |
456 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); | ||
451 | int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | 457 | int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, |
452 | int slots_num, u32 txq_id); | 458 | int slots_num, u32 txq_id); |
453 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); | 459 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); |
@@ -497,6 +503,8 @@ void iwl_init_scan_params(struct iwl_priv *priv); | |||
497 | int iwl_scan_cancel(struct iwl_priv *priv); | 503 | int iwl_scan_cancel(struct iwl_priv *priv); |
498 | int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); | 504 | int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); |
499 | int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req); | 505 | int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req); |
506 | int iwl_internal_short_hw_scan(struct iwl_priv *priv); | ||
507 | int iwl_force_reset(struct iwl_priv *priv, int mode); | ||
500 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, | 508 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, |
501 | const u8 *ie, int ie_len, int left); | 509 | const u8 *ie, int ie_len, int left); |
502 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); | 510 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); |
@@ -527,14 +535,6 @@ int iwl_send_calib_results(struct iwl_priv *priv); | |||
527 | int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len); | 535 | int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len); |
528 | void iwl_calib_free_results(struct iwl_priv *priv); | 536 | void iwl_calib_free_results(struct iwl_priv *priv); |
529 | 537 | ||
530 | /******************************************************************************* | ||
531 | * Spectrum Measureemtns in iwl-spectrum.c | ||
532 | ******************************************************************************/ | ||
533 | #ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT | ||
534 | void iwl_setup_spectrum_handlers(struct iwl_priv *priv); | ||
535 | #else | ||
536 | static inline void iwl_setup_spectrum_handlers(struct iwl_priv *priv) {} | ||
537 | #endif | ||
538 | /***************************************************** | 538 | /***************************************************** |
539 | * S e n d i n g H o s t C o m m a n d s * | 539 | * S e n d i n g H o s t C o m m a n d s * |
540 | *****************************************************/ | 540 | *****************************************************/ |
@@ -583,7 +583,10 @@ int iwl_pci_resume(struct pci_dev *pdev); | |||
583 | * Error Handling Debugging | 583 | * Error Handling Debugging |
584 | ******************************************************/ | 584 | ******************************************************/ |
585 | void iwl_dump_nic_error_log(struct iwl_priv *priv); | 585 | void iwl_dump_nic_error_log(struct iwl_priv *priv); |
586 | void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log); | 586 | int iwl_dump_nic_event_log(struct iwl_priv *priv, |
587 | bool full_log, char **buf, bool display); | ||
588 | void iwl_dump_csr(struct iwl_priv *priv); | ||
589 | int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display); | ||
587 | #ifdef CONFIG_IWLWIFI_DEBUG | 590 | #ifdef CONFIG_IWLWIFI_DEBUG |
588 | void iwl_print_rx_config_cmd(struct iwl_priv *priv); | 591 | void iwl_print_rx_config_cmd(struct iwl_priv *priv); |
589 | #else | 592 | #else |
@@ -603,7 +606,7 @@ void iwlcore_free_geos(struct iwl_priv *priv); | |||
603 | /*************** DRIVER STATUS FUNCTIONS *****/ | 606 | /*************** DRIVER STATUS FUNCTIONS *****/ |
604 | 607 | ||
605 | #define STATUS_HCMD_ACTIVE 0 /* host command in progress */ | 608 | #define STATUS_HCMD_ACTIVE 0 /* host command in progress */ |
606 | #define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */ | 609 | /* 1 is unused (used to be STATUS_HCMD_SYNC_ACTIVE) */ |
607 | #define STATUS_INT_ENABLED 2 | 610 | #define STATUS_INT_ENABLED 2 |
608 | #define STATUS_RF_KILL_HW 3 | 611 | #define STATUS_RF_KILL_HW 3 |
609 | #define STATUS_CT_KILL 4 | 612 | #define STATUS_CT_KILL 4 |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 1ec8cb4d5eae..808b7146bead 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 |
@@ -369,7 +369,7 @@ | |||
369 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_3x3_HYB (0x00000000) | 369 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_3x3_HYB (0x00000000) |
370 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB (0x00000001) | 370 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB (0x00000001) |
371 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA (0x00000002) | 371 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA (0x00000002) |
372 | 372 | #define CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6 (0x00000004) | |
373 | 373 | ||
374 | /* GIO Chicken Bits (PCI Express bus link power management) */ | 374 | /* GIO Chicken Bits (PCI Express bus link power management) */ |
375 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) | 375 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index d61293ab67c9..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,57 +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 | } dbgfs_debug_files; | ||
113 | u32 sram_offset; | ||
114 | u32 sram_len; | ||
115 | }; | ||
116 | |||
117 | int iwl_dbgfs_register(struct iwl_priv *priv, const char *name); | ||
118 | void iwl_dbgfs_unregister(struct iwl_priv *priv); | ||
119 | #endif | ||
120 | |||
121 | #else | 70 | #else |
122 | #define IWL_DEBUG(__priv, level, fmt, args...) | 71 | #define IWL_DEBUG(__priv, level, fmt, args...) |
123 | #define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) | 72 | #define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) |
@@ -126,9 +75,10 @@ static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level, | |||
126 | {} | 75 | {} |
127 | #endif /* CONFIG_IWLWIFI_DEBUG */ | 76 | #endif /* CONFIG_IWLWIFI_DEBUG */ |
128 | 77 | ||
129 | 78 | #ifdef CONFIG_IWLWIFI_DEBUGFS | |
130 | 79 | int iwl_dbgfs_register(struct iwl_priv *priv, const char *name); | |
131 | #ifndef CONFIG_IWLWIFI_DEBUGFS | 80 | void iwl_dbgfs_unregister(struct iwl_priv *priv); |
81 | #else | ||
132 | 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) |
133 | { | 83 | { |
134 | return 0; | 84 | return 0; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 21e0f6699daf..7bf44f146799 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, \ |
@@ -125,7 +110,7 @@ static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, | |||
125 | char __user *user_buf, | 110 | char __user *user_buf, |
126 | size_t count, loff_t *ppos) { | 111 | size_t count, loff_t *ppos) { |
127 | 112 | ||
128 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 113 | struct iwl_priv *priv = file->private_data; |
129 | char *buf; | 114 | char *buf; |
130 | int pos = 0; | 115 | int pos = 0; |
131 | 116 | ||
@@ -184,7 +169,7 @@ static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file, | |||
184 | char __user *user_buf, | 169 | char __user *user_buf, |
185 | size_t count, loff_t *ppos) { | 170 | size_t count, loff_t *ppos) { |
186 | 171 | ||
187 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 172 | struct iwl_priv *priv = file->private_data; |
188 | char *buf; | 173 | char *buf; |
189 | int pos = 0; | 174 | int pos = 0; |
190 | int cnt; | 175 | int cnt; |
@@ -232,28 +217,28 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, | |||
232 | ssize_t ret; | 217 | ssize_t ret; |
233 | int i; | 218 | int i; |
234 | int pos = 0; | 219 | int pos = 0; |
235 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 220 | struct iwl_priv *priv = file->private_data; |
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; |
@@ -306,7 +291,7 @@ static ssize_t iwl_dbgfs_sram_write(struct file *file, | |||
306 | static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, | 291 | static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, |
307 | size_t count, loff_t *ppos) | 292 | size_t count, loff_t *ppos) |
308 | { | 293 | { |
309 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 294 | struct iwl_priv *priv = file->private_data; |
310 | struct iwl_station_entry *station; | 295 | struct iwl_station_entry *station; |
311 | int max_sta = priv->hw_params.max_stations; | 296 | int max_sta = priv->hw_params.max_stations; |
312 | char *buf; | 297 | char *buf; |
@@ -376,7 +361,7 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, | |||
376 | loff_t *ppos) | 361 | loff_t *ppos) |
377 | { | 362 | { |
378 | ssize_t ret; | 363 | ssize_t ret; |
379 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 364 | struct iwl_priv *priv = file->private_data; |
380 | int pos = 0, ofs = 0, buf_size = 0; | 365 | int pos = 0, ofs = 0, buf_size = 0; |
381 | const u8 *ptr; | 366 | const u8 *ptr; |
382 | char *buf; | 367 | char *buf; |
@@ -420,6 +405,24 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, | |||
420 | return ret; | 405 | return ret; |
421 | } | 406 | } |
422 | 407 | ||
408 | static ssize_t iwl_dbgfs_log_event_read(struct file *file, | ||
409 | char __user *user_buf, | ||
410 | size_t count, loff_t *ppos) | ||
411 | { | ||
412 | struct iwl_priv *priv = file->private_data; | ||
413 | char *buf; | ||
414 | int pos = 0; | ||
415 | ssize_t ret = -ENOMEM; | ||
416 | |||
417 | ret = pos = priv->cfg->ops->lib->dump_nic_event_log( | ||
418 | priv, true, &buf, true); | ||
419 | if (buf) { | ||
420 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
421 | kfree(buf); | ||
422 | } | ||
423 | return ret; | ||
424 | } | ||
425 | |||
423 | static ssize_t iwl_dbgfs_log_event_write(struct file *file, | 426 | static ssize_t iwl_dbgfs_log_event_write(struct file *file, |
424 | const char __user *user_buf, | 427 | const char __user *user_buf, |
425 | size_t count, loff_t *ppos) | 428 | size_t count, loff_t *ppos) |
@@ -436,7 +439,8 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file, | |||
436 | if (sscanf(buf, "%d", &event_log_flag) != 1) | 439 | if (sscanf(buf, "%d", &event_log_flag) != 1) |
437 | return -EFAULT; | 440 | return -EFAULT; |
438 | if (event_log_flag == 1) | 441 | if (event_log_flag == 1) |
439 | priv->cfg->ops->lib->dump_nic_event_log(priv, true); | 442 | priv->cfg->ops->lib->dump_nic_event_log(priv, true, |
443 | NULL, false); | ||
440 | 444 | ||
441 | return count; | 445 | return count; |
442 | } | 446 | } |
@@ -446,7 +450,7 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file, | |||
446 | static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, | 450 | static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, |
447 | size_t count, loff_t *ppos) | 451 | size_t count, loff_t *ppos) |
448 | { | 452 | { |
449 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 453 | struct iwl_priv *priv = file->private_data; |
450 | struct ieee80211_channel *channels = NULL; | 454 | struct ieee80211_channel *channels = NULL; |
451 | const struct ieee80211_supported_band *supp_band = NULL; | 455 | const struct ieee80211_supported_band *supp_band = NULL; |
452 | int pos = 0, i, bufsz = PAGE_SIZE; | 456 | int pos = 0, i, bufsz = PAGE_SIZE; |
@@ -519,15 +523,13 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, | |||
519 | char __user *user_buf, | 523 | char __user *user_buf, |
520 | size_t count, loff_t *ppos) { | 524 | size_t count, loff_t *ppos) { |
521 | 525 | ||
522 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 526 | struct iwl_priv *priv = file->private_data; |
523 | char buf[512]; | 527 | char buf[512]; |
524 | int pos = 0; | 528 | int pos = 0; |
525 | const size_t bufsz = sizeof(buf); | 529 | const size_t bufsz = sizeof(buf); |
526 | 530 | ||
527 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n", | 531 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n", |
528 | test_bit(STATUS_HCMD_ACTIVE, &priv->status)); | 532 | test_bit(STATUS_HCMD_ACTIVE, &priv->status)); |
529 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_SYNC_ACTIVE: %d\n", | ||
530 | test_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)); | ||
531 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n", | 533 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n", |
532 | test_bit(STATUS_INT_ENABLED, &priv->status)); | 534 | test_bit(STATUS_INT_ENABLED, &priv->status)); |
533 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", | 535 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", |
@@ -567,7 +569,7 @@ static ssize_t iwl_dbgfs_interrupt_read(struct file *file, | |||
567 | char __user *user_buf, | 569 | char __user *user_buf, |
568 | size_t count, loff_t *ppos) { | 570 | size_t count, loff_t *ppos) { |
569 | 571 | ||
570 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 572 | struct iwl_priv *priv = file->private_data; |
571 | int pos = 0; | 573 | int pos = 0; |
572 | int cnt = 0; | 574 | int cnt = 0; |
573 | char *buf; | 575 | char *buf; |
@@ -654,7 +656,7 @@ static ssize_t iwl_dbgfs_interrupt_write(struct file *file, | |||
654 | static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, | 656 | static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, |
655 | size_t count, loff_t *ppos) | 657 | size_t count, loff_t *ppos) |
656 | { | 658 | { |
657 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 659 | struct iwl_priv *priv = file->private_data; |
658 | int pos = 0, i; | 660 | int pos = 0, i; |
659 | char buf[256]; | 661 | char buf[256]; |
660 | const size_t bufsz = sizeof(buf); | 662 | const size_t bufsz = sizeof(buf); |
@@ -677,7 +679,7 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, | |||
677 | static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, | 679 | static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, |
678 | size_t count, loff_t *ppos) | 680 | size_t count, loff_t *ppos) |
679 | { | 681 | { |
680 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 682 | struct iwl_priv *priv = file->private_data; |
681 | int pos = 0; | 683 | int pos = 0; |
682 | char buf[256]; | 684 | char buf[256]; |
683 | const size_t bufsz = sizeof(buf); | 685 | const size_t bufsz = sizeof(buf); |
@@ -703,7 +705,7 @@ static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, | |||
703 | char __user *user_buf, | 705 | char __user *user_buf, |
704 | size_t count, loff_t *ppos) | 706 | size_t count, loff_t *ppos) |
705 | { | 707 | { |
706 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 708 | struct iwl_priv *priv = file->private_data; |
707 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | 709 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; |
708 | struct iwl_tt_restriction *restriction; | 710 | struct iwl_tt_restriction *restriction; |
709 | char buf[100]; | 711 | char buf[100]; |
@@ -763,7 +765,7 @@ static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file, | |||
763 | char __user *user_buf, | 765 | char __user *user_buf, |
764 | size_t count, loff_t *ppos) | 766 | size_t count, loff_t *ppos) |
765 | { | 767 | { |
766 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 768 | struct iwl_priv *priv = file->private_data; |
767 | char buf[100]; | 769 | char buf[100]; |
768 | int pos = 0; | 770 | int pos = 0; |
769 | const size_t bufsz = sizeof(buf); | 771 | const size_t bufsz = sizeof(buf); |
@@ -811,7 +813,9 @@ static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, | |||
811 | 813 | ||
812 | priv->power_data.debug_sleep_level_override = value; | 814 | priv->power_data.debug_sleep_level_override = value; |
813 | 815 | ||
816 | mutex_lock(&priv->mutex); | ||
814 | iwl_power_update_mode(priv, true); | 817 | iwl_power_update_mode(priv, true); |
818 | mutex_unlock(&priv->mutex); | ||
815 | 819 | ||
816 | return count; | 820 | return count; |
817 | } | 821 | } |
@@ -820,7 +824,7 @@ static ssize_t iwl_dbgfs_sleep_level_override_read(struct file *file, | |||
820 | char __user *user_buf, | 824 | char __user *user_buf, |
821 | size_t count, loff_t *ppos) | 825 | size_t count, loff_t *ppos) |
822 | { | 826 | { |
823 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 827 | struct iwl_priv *priv = file->private_data; |
824 | char buf[10]; | 828 | char buf[10]; |
825 | int pos, value; | 829 | int pos, value; |
826 | const size_t bufsz = sizeof(buf); | 830 | const size_t bufsz = sizeof(buf); |
@@ -838,7 +842,7 @@ static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file, | |||
838 | char __user *user_buf, | 842 | char __user *user_buf, |
839 | size_t count, loff_t *ppos) | 843 | size_t count, loff_t *ppos) |
840 | { | 844 | { |
841 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 845 | struct iwl_priv *priv = file->private_data; |
842 | char buf[200]; | 846 | char buf[200]; |
843 | int pos = 0, i; | 847 | int pos = 0, i; |
844 | const size_t bufsz = sizeof(buf); | 848 | const size_t bufsz = sizeof(buf); |
@@ -859,7 +863,7 @@ static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file, | |||
859 | } | 863 | } |
860 | 864 | ||
861 | DEBUGFS_READ_WRITE_FILE_OPS(sram); | 865 | DEBUGFS_READ_WRITE_FILE_OPS(sram); |
862 | DEBUGFS_WRITE_FILE_OPS(log_event); | 866 | DEBUGFS_READ_WRITE_FILE_OPS(log_event); |
863 | DEBUGFS_READ_FILE_OPS(nvm); | 867 | DEBUGFS_READ_FILE_OPS(nvm); |
864 | DEBUGFS_READ_FILE_OPS(stations); | 868 | DEBUGFS_READ_FILE_OPS(stations); |
865 | DEBUGFS_READ_FILE_OPS(channels); | 869 | DEBUGFS_READ_FILE_OPS(channels); |
@@ -976,7 +980,7 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, | |||
976 | char __user *user_buf, | 980 | char __user *user_buf, |
977 | size_t count, loff_t *ppos) { | 981 | size_t count, loff_t *ppos) { |
978 | 982 | ||
979 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 983 | struct iwl_priv *priv = file->private_data; |
980 | struct iwl_tx_queue *txq; | 984 | struct iwl_tx_queue *txq; |
981 | struct iwl_queue *q; | 985 | struct iwl_queue *q; |
982 | char *buf; | 986 | char *buf; |
@@ -1022,7 +1026,7 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, | |||
1022 | char __user *user_buf, | 1026 | char __user *user_buf, |
1023 | size_t count, loff_t *ppos) { | 1027 | size_t count, loff_t *ppos) { |
1024 | 1028 | ||
1025 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 1029 | struct iwl_priv *priv = file->private_data; |
1026 | struct iwl_rx_queue *rxq = &priv->rxq; | 1030 | struct iwl_rx_queue *rxq = &priv->rxq; |
1027 | char buf[256]; | 1031 | char buf[256]; |
1028 | int pos = 0; | 1032 | int pos = 0; |
@@ -1063,36 +1067,33 @@ static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, | |||
1063 | return p; | 1067 | return p; |
1064 | } | 1068 | } |
1065 | 1069 | ||
1070 | static const char ucode_stats_header[] = | ||
1071 | "%-32s current acumulative delta max\n"; | ||
1072 | static const char ucode_stats_short_format[] = | ||
1073 | " %-30s %10u\n"; | ||
1074 | static const char ucode_stats_format[] = | ||
1075 | " %-30s %10u %10u %10u %10u\n"; | ||
1066 | 1076 | ||
1067 | static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, | 1077 | static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, |
1068 | char __user *user_buf, | 1078 | char __user *user_buf, |
1069 | size_t count, loff_t *ppos) | 1079 | size_t count, loff_t *ppos) |
1070 | { | 1080 | { |
1071 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 1081 | struct iwl_priv *priv = file->private_data; |
1072 | int pos = 0; | 1082 | int pos = 0; |
1073 | char *buf; | 1083 | char *buf; |
1074 | int bufsz = sizeof(struct statistics_rx_phy) * 20 + | 1084 | int bufsz = sizeof(struct statistics_rx_phy) * 40 + |
1075 | sizeof(struct statistics_rx_non_phy) * 20 + | 1085 | sizeof(struct statistics_rx_non_phy) * 40 + |
1076 | sizeof(struct statistics_rx_ht_phy) * 20 + 400; | 1086 | sizeof(struct statistics_rx_ht_phy) * 40 + 400; |
1077 | ssize_t ret; | 1087 | ssize_t ret; |
1078 | struct statistics_rx_phy *ofdm, *accum_ofdm; | 1088 | struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm; |
1079 | struct statistics_rx_phy *cck, *accum_cck; | 1089 | struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck; |
1080 | struct statistics_rx_non_phy *general, *accum_general; | 1090 | struct statistics_rx_non_phy *general, *accum_general; |
1081 | struct statistics_rx_ht_phy *ht, *accum_ht; | 1091 | struct statistics_rx_non_phy *delta_general, *max_general; |
1092 | struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht; | ||
1082 | 1093 | ||
1083 | if (!iwl_is_alive(priv)) | 1094 | if (!iwl_is_alive(priv)) |
1084 | return -EAGAIN; | 1095 | return -EAGAIN; |
1085 | 1096 | ||
1086 | /* make request to uCode to retrieve statistics information */ | ||
1087 | mutex_lock(&priv->mutex); | ||
1088 | ret = iwl_send_statistics_request(priv, CMD_SYNC, false); | ||
1089 | mutex_unlock(&priv->mutex); | ||
1090 | |||
1091 | if (ret) { | ||
1092 | IWL_ERR(priv, | ||
1093 | "Error sending statistics request: %zd\n", ret); | ||
1094 | return -EAGAIN; | ||
1095 | } | ||
1096 | buf = kzalloc(bufsz, GFP_KERNEL); | 1097 | buf = kzalloc(bufsz, GFP_KERNEL); |
1097 | if (!buf) { | 1098 | if (!buf) { |
1098 | IWL_ERR(priv, "Can not allocate Buffer\n"); | 1099 | IWL_ERR(priv, "Can not allocate Buffer\n"); |
@@ -1111,264 +1112,401 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, | |||
1111 | accum_cck = &priv->accum_statistics.rx.cck; | 1112 | accum_cck = &priv->accum_statistics.rx.cck; |
1112 | accum_general = &priv->accum_statistics.rx.general; | 1113 | accum_general = &priv->accum_statistics.rx.general; |
1113 | accum_ht = &priv->accum_statistics.rx.ofdm_ht; | 1114 | accum_ht = &priv->accum_statistics.rx.ofdm_ht; |
1115 | delta_ofdm = &priv->delta_statistics.rx.ofdm; | ||
1116 | delta_cck = &priv->delta_statistics.rx.cck; | ||
1117 | delta_general = &priv->delta_statistics.rx.general; | ||
1118 | delta_ht = &priv->delta_statistics.rx.ofdm_ht; | ||
1119 | max_ofdm = &priv->max_delta.rx.ofdm; | ||
1120 | max_cck = &priv->max_delta.rx.cck; | ||
1121 | max_general = &priv->max_delta.rx.general; | ||
1122 | max_ht = &priv->max_delta.rx.ofdm_ht; | ||
1123 | |||
1114 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | 1124 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); |
1115 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM:\n"); | 1125 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, |
1116 | pos += scnprintf(buf + pos, bufsz - pos, | 1126 | "Statistics_Rx - OFDM:"); |
1117 | "\t\t\tcurrent\t\t\taccumulative\n"); | 1127 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1118 | pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt:\t\t%u\t\t\t%u\n", | 1128 | "ina_cnt:", le32_to_cpu(ofdm->ina_cnt), |
1119 | le32_to_cpu(ofdm->ina_cnt), accum_ofdm->ina_cnt); | 1129 | accum_ofdm->ina_cnt, |
1120 | pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt:\t\t%u\t\t\t%u\n", | 1130 | delta_ofdm->ina_cnt, max_ofdm->ina_cnt); |
1121 | le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt); | 1131 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1122 | pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n", | 1132 | "fina_cnt:", |
1123 | le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err); | 1133 | le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt, |
1124 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n", | 1134 | delta_ofdm->fina_cnt, max_ofdm->fina_cnt); |
1125 | le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err); | 1135 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1126 | pos += scnprintf(buf + pos, bufsz - pos, | 1136 | "plcp_err:", |
1127 | "overrun_err:\t\t%u\t\t\t%u\n", | 1137 | le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err, |
1138 | delta_ofdm->plcp_err, max_ofdm->plcp_err); | ||
1139 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1140 | "crc32_err:", | ||
1141 | le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err, | ||
1142 | delta_ofdm->crc32_err, max_ofdm->crc32_err); | ||
1143 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1144 | "overrun_err:", | ||
1128 | le32_to_cpu(ofdm->overrun_err), | 1145 | le32_to_cpu(ofdm->overrun_err), |
1129 | accum_ofdm->overrun_err); | 1146 | accum_ofdm->overrun_err, |
1130 | pos += scnprintf(buf + pos, bufsz - pos, | 1147 | delta_ofdm->overrun_err, max_ofdm->overrun_err); |
1131 | "early_overrun_err:\t%u\t\t\t%u\n", | 1148 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1149 | "early_overrun_err:", | ||
1132 | le32_to_cpu(ofdm->early_overrun_err), | 1150 | le32_to_cpu(ofdm->early_overrun_err), |
1133 | accum_ofdm->early_overrun_err); | 1151 | accum_ofdm->early_overrun_err, |
1134 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n", | 1152 | delta_ofdm->early_overrun_err, |
1153 | max_ofdm->early_overrun_err); | ||
1154 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1155 | "crc32_good:", | ||
1135 | le32_to_cpu(ofdm->crc32_good), | 1156 | le32_to_cpu(ofdm->crc32_good), |
1136 | accum_ofdm->crc32_good); | 1157 | accum_ofdm->crc32_good, |
1137 | pos += scnprintf(buf + pos, bufsz - pos, | 1158 | delta_ofdm->crc32_good, max_ofdm->crc32_good); |
1138 | "false_alarm_cnt:\t%u\t\t\t%u\n", | 1159 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1160 | "false_alarm_cnt:", | ||
1139 | le32_to_cpu(ofdm->false_alarm_cnt), | 1161 | le32_to_cpu(ofdm->false_alarm_cnt), |
1140 | accum_ofdm->false_alarm_cnt); | 1162 | accum_ofdm->false_alarm_cnt, |
1141 | pos += scnprintf(buf + pos, bufsz - pos, | 1163 | delta_ofdm->false_alarm_cnt, |
1142 | "fina_sync_err_cnt:\t%u\t\t\t%u\n", | 1164 | max_ofdm->false_alarm_cnt); |
1165 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1166 | "fina_sync_err_cnt:", | ||
1143 | le32_to_cpu(ofdm->fina_sync_err_cnt), | 1167 | le32_to_cpu(ofdm->fina_sync_err_cnt), |
1144 | accum_ofdm->fina_sync_err_cnt); | 1168 | accum_ofdm->fina_sync_err_cnt, |
1145 | pos += scnprintf(buf + pos, bufsz - pos, | 1169 | delta_ofdm->fina_sync_err_cnt, |
1146 | "sfd_timeout:\t\t%u\t\t\t%u\n", | 1170 | max_ofdm->fina_sync_err_cnt); |
1171 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1172 | "sfd_timeout:", | ||
1147 | le32_to_cpu(ofdm->sfd_timeout), | 1173 | le32_to_cpu(ofdm->sfd_timeout), |
1148 | accum_ofdm->sfd_timeout); | 1174 | accum_ofdm->sfd_timeout, |
1149 | pos += scnprintf(buf + pos, bufsz - pos, | 1175 | delta_ofdm->sfd_timeout, |
1150 | "fina_timeout:\t\t%u\t\t\t%u\n", | 1176 | max_ofdm->sfd_timeout); |
1177 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1178 | "fina_timeout:", | ||
1151 | le32_to_cpu(ofdm->fina_timeout), | 1179 | le32_to_cpu(ofdm->fina_timeout), |
1152 | accum_ofdm->fina_timeout); | 1180 | accum_ofdm->fina_timeout, |
1153 | pos += scnprintf(buf + pos, bufsz - pos, | 1181 | delta_ofdm->fina_timeout, |
1154 | "unresponded_rts:\t%u\t\t\t%u\n", | 1182 | max_ofdm->fina_timeout); |
1183 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1184 | "unresponded_rts:", | ||
1155 | le32_to_cpu(ofdm->unresponded_rts), | 1185 | le32_to_cpu(ofdm->unresponded_rts), |
1156 | accum_ofdm->unresponded_rts); | 1186 | accum_ofdm->unresponded_rts, |
1157 | pos += scnprintf(buf + pos, bufsz - pos, | 1187 | delta_ofdm->unresponded_rts, |
1158 | "rxe_frame_lmt_ovrun:\t%u\t\t\t%u\n", | 1188 | max_ofdm->unresponded_rts); |
1189 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1190 | "rxe_frame_lmt_ovrun:", | ||
1159 | le32_to_cpu(ofdm->rxe_frame_limit_overrun), | 1191 | le32_to_cpu(ofdm->rxe_frame_limit_overrun), |
1160 | accum_ofdm->rxe_frame_limit_overrun); | 1192 | accum_ofdm->rxe_frame_limit_overrun, |
1161 | pos += scnprintf(buf + pos, bufsz - pos, | 1193 | delta_ofdm->rxe_frame_limit_overrun, |
1162 | "sent_ack_cnt:\t\t%u\t\t\t%u\n", | 1194 | max_ofdm->rxe_frame_limit_overrun); |
1195 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1196 | "sent_ack_cnt:", | ||
1163 | le32_to_cpu(ofdm->sent_ack_cnt), | 1197 | le32_to_cpu(ofdm->sent_ack_cnt), |
1164 | accum_ofdm->sent_ack_cnt); | 1198 | accum_ofdm->sent_ack_cnt, |
1165 | pos += scnprintf(buf + pos, bufsz - pos, | 1199 | delta_ofdm->sent_ack_cnt, |
1166 | "sent_cts_cnt:\t\t%u\t\t\t%u\n", | 1200 | max_ofdm->sent_ack_cnt); |
1201 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1202 | "sent_cts_cnt:", | ||
1167 | le32_to_cpu(ofdm->sent_cts_cnt), | 1203 | le32_to_cpu(ofdm->sent_cts_cnt), |
1168 | accum_ofdm->sent_cts_cnt); | 1204 | accum_ofdm->sent_cts_cnt, |
1169 | pos += scnprintf(buf + pos, bufsz - pos, | 1205 | delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt); |
1170 | "sent_ba_rsp_cnt:\t%u\t\t\t%u\n", | 1206 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1207 | "sent_ba_rsp_cnt:", | ||
1171 | le32_to_cpu(ofdm->sent_ba_rsp_cnt), | 1208 | le32_to_cpu(ofdm->sent_ba_rsp_cnt), |
1172 | accum_ofdm->sent_ba_rsp_cnt); | 1209 | accum_ofdm->sent_ba_rsp_cnt, |
1173 | pos += scnprintf(buf + pos, bufsz - pos, | 1210 | delta_ofdm->sent_ba_rsp_cnt, |
1174 | "dsp_self_kill:\t\t%u\t\t\t%u\n", | 1211 | max_ofdm->sent_ba_rsp_cnt); |
1212 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1213 | "dsp_self_kill:", | ||
1175 | le32_to_cpu(ofdm->dsp_self_kill), | 1214 | le32_to_cpu(ofdm->dsp_self_kill), |
1176 | accum_ofdm->dsp_self_kill); | 1215 | accum_ofdm->dsp_self_kill, |
1177 | pos += scnprintf(buf + pos, bufsz - pos, | 1216 | delta_ofdm->dsp_self_kill, |
1178 | "mh_format_err:\t\t%u\t\t\t%u\n", | 1217 | max_ofdm->dsp_self_kill); |
1218 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1219 | "mh_format_err:", | ||
1179 | le32_to_cpu(ofdm->mh_format_err), | 1220 | le32_to_cpu(ofdm->mh_format_err), |
1180 | accum_ofdm->mh_format_err); | 1221 | accum_ofdm->mh_format_err, |
1181 | pos += scnprintf(buf + pos, bufsz - pos, | 1222 | delta_ofdm->mh_format_err, |
1182 | "re_acq_main_rssi_sum:\t%u\t\t\t%u\n", | 1223 | max_ofdm->mh_format_err); |
1224 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1225 | "re_acq_main_rssi_sum:", | ||
1183 | le32_to_cpu(ofdm->re_acq_main_rssi_sum), | 1226 | le32_to_cpu(ofdm->re_acq_main_rssi_sum), |
1184 | accum_ofdm->re_acq_main_rssi_sum); | 1227 | accum_ofdm->re_acq_main_rssi_sum, |
1185 | 1228 | delta_ofdm->re_acq_main_rssi_sum, | |
1186 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - CCK:\n"); | 1229 | max_ofdm->re_acq_main_rssi_sum); |
1187 | pos += scnprintf(buf + pos, bufsz - pos, | 1230 | |
1188 | "\t\t\tcurrent\t\t\taccumulative\n"); | 1231 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, |
1189 | pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt:\t\t%u\t\t\t%u\n", | 1232 | "Statistics_Rx - CCK:"); |
1190 | le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt); | 1233 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1191 | pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt:\t\t%u\t\t\t%u\n", | 1234 | "ina_cnt:", |
1192 | le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt); | 1235 | le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt, |
1193 | pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n", | 1236 | delta_cck->ina_cnt, max_cck->ina_cnt); |
1194 | le32_to_cpu(cck->plcp_err), accum_cck->plcp_err); | 1237 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1195 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n", | 1238 | "fina_cnt:", |
1196 | le32_to_cpu(cck->crc32_err), accum_cck->crc32_err); | 1239 | le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt, |
1197 | pos += scnprintf(buf + pos, bufsz - pos, | 1240 | delta_cck->fina_cnt, max_cck->fina_cnt); |
1198 | "overrun_err:\t\t%u\t\t\t%u\n", | 1241 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1242 | "plcp_err:", | ||
1243 | le32_to_cpu(cck->plcp_err), accum_cck->plcp_err, | ||
1244 | delta_cck->plcp_err, max_cck->plcp_err); | ||
1245 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1246 | "crc32_err:", | ||
1247 | le32_to_cpu(cck->crc32_err), accum_cck->crc32_err, | ||
1248 | delta_cck->crc32_err, max_cck->crc32_err); | ||
1249 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1250 | "overrun_err:", | ||
1199 | le32_to_cpu(cck->overrun_err), | 1251 | le32_to_cpu(cck->overrun_err), |
1200 | accum_cck->overrun_err); | 1252 | accum_cck->overrun_err, |
1201 | pos += scnprintf(buf + pos, bufsz - pos, | 1253 | delta_cck->overrun_err, max_cck->overrun_err); |
1202 | "early_overrun_err:\t%u\t\t\t%u\n", | 1254 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1255 | "early_overrun_err:", | ||
1203 | le32_to_cpu(cck->early_overrun_err), | 1256 | le32_to_cpu(cck->early_overrun_err), |
1204 | accum_cck->early_overrun_err); | 1257 | accum_cck->early_overrun_err, |
1205 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n", | 1258 | delta_cck->early_overrun_err, |
1206 | le32_to_cpu(cck->crc32_good), accum_cck->crc32_good); | 1259 | max_cck->early_overrun_err); |
1207 | pos += scnprintf(buf + pos, bufsz - pos, | 1260 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1208 | "false_alarm_cnt:\t%u\t\t\t%u\n", | 1261 | "crc32_good:", |
1262 | le32_to_cpu(cck->crc32_good), accum_cck->crc32_good, | ||
1263 | delta_cck->crc32_good, | ||
1264 | max_cck->crc32_good); | ||
1265 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1266 | "false_alarm_cnt:", | ||
1209 | le32_to_cpu(cck->false_alarm_cnt), | 1267 | le32_to_cpu(cck->false_alarm_cnt), |
1210 | accum_cck->false_alarm_cnt); | 1268 | accum_cck->false_alarm_cnt, |
1211 | pos += scnprintf(buf + pos, bufsz - pos, | 1269 | delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt); |
1212 | "fina_sync_err_cnt:\t%u\t\t\t%u\n", | 1270 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1271 | "fina_sync_err_cnt:", | ||
1213 | le32_to_cpu(cck->fina_sync_err_cnt), | 1272 | le32_to_cpu(cck->fina_sync_err_cnt), |
1214 | accum_cck->fina_sync_err_cnt); | 1273 | accum_cck->fina_sync_err_cnt, |
1215 | pos += scnprintf(buf + pos, bufsz - pos, | 1274 | delta_cck->fina_sync_err_cnt, |
1216 | "sfd_timeout:\t\t%u\t\t\t%u\n", | 1275 | max_cck->fina_sync_err_cnt); |
1276 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1277 | "sfd_timeout:", | ||
1217 | le32_to_cpu(cck->sfd_timeout), | 1278 | le32_to_cpu(cck->sfd_timeout), |
1218 | accum_cck->sfd_timeout); | 1279 | accum_cck->sfd_timeout, |
1219 | pos += scnprintf(buf + pos, bufsz - pos, | 1280 | delta_cck->sfd_timeout, max_cck->sfd_timeout); |
1220 | "fina_timeout:\t\t%u\t\t\t%u\n", | 1281 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1282 | "fina_timeout:", | ||
1221 | le32_to_cpu(cck->fina_timeout), | 1283 | le32_to_cpu(cck->fina_timeout), |
1222 | accum_cck->fina_timeout); | 1284 | accum_cck->fina_timeout, |
1223 | pos += scnprintf(buf + pos, bufsz - pos, | 1285 | delta_cck->fina_timeout, max_cck->fina_timeout); |
1224 | "unresponded_rts:\t%u\t\t\t%u\n", | 1286 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1287 | "unresponded_rts:", | ||
1225 | le32_to_cpu(cck->unresponded_rts), | 1288 | le32_to_cpu(cck->unresponded_rts), |
1226 | accum_cck->unresponded_rts); | 1289 | accum_cck->unresponded_rts, |
1227 | pos += scnprintf(buf + pos, bufsz - pos, | 1290 | delta_cck->unresponded_rts, |
1228 | "rxe_frame_lmt_ovrun:\t%u\t\t\t%u\n", | 1291 | max_cck->unresponded_rts); |
1292 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1293 | "rxe_frame_lmt_ovrun:", | ||
1229 | le32_to_cpu(cck->rxe_frame_limit_overrun), | 1294 | le32_to_cpu(cck->rxe_frame_limit_overrun), |
1230 | accum_cck->rxe_frame_limit_overrun); | 1295 | accum_cck->rxe_frame_limit_overrun, |
1231 | pos += scnprintf(buf + pos, bufsz - pos, | 1296 | delta_cck->rxe_frame_limit_overrun, |
1232 | "sent_ack_cnt:\t\t%u\t\t\t%u\n", | 1297 | max_cck->rxe_frame_limit_overrun); |
1298 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1299 | "sent_ack_cnt:", | ||
1233 | le32_to_cpu(cck->sent_ack_cnt), | 1300 | le32_to_cpu(cck->sent_ack_cnt), |
1234 | accum_cck->sent_ack_cnt); | 1301 | accum_cck->sent_ack_cnt, |
1235 | pos += scnprintf(buf + pos, bufsz - pos, | 1302 | delta_cck->sent_ack_cnt, |
1236 | "sent_cts_cnt:\t\t%u\t\t\t%u\n", | 1303 | max_cck->sent_ack_cnt); |
1304 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1305 | "sent_cts_cnt:", | ||
1237 | le32_to_cpu(cck->sent_cts_cnt), | 1306 | le32_to_cpu(cck->sent_cts_cnt), |
1238 | accum_cck->sent_cts_cnt); | 1307 | accum_cck->sent_cts_cnt, |
1239 | pos += scnprintf(buf + pos, bufsz - pos, | 1308 | delta_cck->sent_cts_cnt, |
1240 | "sent_ba_rsp_cnt:\t%u\t\t\t%u\n", | 1309 | max_cck->sent_cts_cnt); |
1310 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1311 | "sent_ba_rsp_cnt:", | ||
1241 | le32_to_cpu(cck->sent_ba_rsp_cnt), | 1312 | le32_to_cpu(cck->sent_ba_rsp_cnt), |
1242 | accum_cck->sent_ba_rsp_cnt); | 1313 | accum_cck->sent_ba_rsp_cnt, |
1243 | pos += scnprintf(buf + pos, bufsz - pos, | 1314 | delta_cck->sent_ba_rsp_cnt, |
1244 | "dsp_self_kill:\t\t%u\t\t\t%u\n", | 1315 | max_cck->sent_ba_rsp_cnt); |
1316 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1317 | "dsp_self_kill:", | ||
1245 | le32_to_cpu(cck->dsp_self_kill), | 1318 | le32_to_cpu(cck->dsp_self_kill), |
1246 | accum_cck->dsp_self_kill); | 1319 | accum_cck->dsp_self_kill, |
1247 | pos += scnprintf(buf + pos, bufsz - pos, | 1320 | delta_cck->dsp_self_kill, |
1248 | "mh_format_err:\t\t%u\t\t\t%u\n", | 1321 | max_cck->dsp_self_kill); |
1322 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1323 | "mh_format_err:", | ||
1249 | le32_to_cpu(cck->mh_format_err), | 1324 | le32_to_cpu(cck->mh_format_err), |
1250 | accum_cck->mh_format_err); | 1325 | accum_cck->mh_format_err, |
1251 | pos += scnprintf(buf + pos, bufsz - pos, | 1326 | delta_cck->mh_format_err, max_cck->mh_format_err); |
1252 | "re_acq_main_rssi_sum:\t%u\t\t\t%u\n", | 1327 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1328 | "re_acq_main_rssi_sum:", | ||
1253 | le32_to_cpu(cck->re_acq_main_rssi_sum), | 1329 | le32_to_cpu(cck->re_acq_main_rssi_sum), |
1254 | accum_cck->re_acq_main_rssi_sum); | 1330 | accum_cck->re_acq_main_rssi_sum, |
1255 | 1331 | delta_cck->re_acq_main_rssi_sum, | |
1256 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - GENERAL:\n"); | 1332 | max_cck->re_acq_main_rssi_sum); |
1257 | pos += scnprintf(buf + pos, bufsz - pos, | 1333 | |
1258 | "\t\t\tcurrent\t\t\taccumulative\n"); | 1334 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, |
1259 | pos += scnprintf(buf + pos, bufsz - pos, "bogus_cts:\t\t%u\t\t\t%u\n", | 1335 | "Statistics_Rx - GENERAL:"); |
1336 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1337 | "bogus_cts:", | ||
1260 | le32_to_cpu(general->bogus_cts), | 1338 | le32_to_cpu(general->bogus_cts), |
1261 | accum_general->bogus_cts); | 1339 | accum_general->bogus_cts, |
1262 | pos += scnprintf(buf + pos, bufsz - pos, "bogus_ack:\t\t%u\t\t\t%u\n", | 1340 | delta_general->bogus_cts, max_general->bogus_cts); |
1341 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1342 | "bogus_ack:", | ||
1263 | le32_to_cpu(general->bogus_ack), | 1343 | le32_to_cpu(general->bogus_ack), |
1264 | accum_general->bogus_ack); | 1344 | accum_general->bogus_ack, |
1265 | pos += scnprintf(buf + pos, bufsz - pos, | 1345 | delta_general->bogus_ack, max_general->bogus_ack); |
1266 | "non_bssid_frames:\t%u\t\t\t%u\n", | 1346 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1347 | "non_bssid_frames:", | ||
1267 | le32_to_cpu(general->non_bssid_frames), | 1348 | le32_to_cpu(general->non_bssid_frames), |
1268 | accum_general->non_bssid_frames); | 1349 | accum_general->non_bssid_frames, |
1269 | pos += scnprintf(buf + pos, bufsz - pos, | 1350 | delta_general->non_bssid_frames, |
1270 | "filtered_frames:\t%u\t\t\t%u\n", | 1351 | max_general->non_bssid_frames); |
1352 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1353 | "filtered_frames:", | ||
1271 | le32_to_cpu(general->filtered_frames), | 1354 | le32_to_cpu(general->filtered_frames), |
1272 | accum_general->filtered_frames); | 1355 | accum_general->filtered_frames, |
1273 | pos += scnprintf(buf + pos, bufsz - pos, | 1356 | delta_general->filtered_frames, |
1274 | "non_channel_beacons:\t%u\t\t\t%u\n", | 1357 | max_general->filtered_frames); |
1358 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1359 | "non_channel_beacons:", | ||
1275 | le32_to_cpu(general->non_channel_beacons), | 1360 | le32_to_cpu(general->non_channel_beacons), |
1276 | accum_general->non_channel_beacons); | 1361 | accum_general->non_channel_beacons, |
1277 | pos += scnprintf(buf + pos, bufsz - pos, | 1362 | delta_general->non_channel_beacons, |
1278 | "channel_beacons:\t%u\t\t\t%u\n", | 1363 | max_general->non_channel_beacons); |
1364 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1365 | "channel_beacons:", | ||
1279 | le32_to_cpu(general->channel_beacons), | 1366 | le32_to_cpu(general->channel_beacons), |
1280 | accum_general->channel_beacons); | 1367 | accum_general->channel_beacons, |
1281 | pos += scnprintf(buf + pos, bufsz - pos, | 1368 | delta_general->channel_beacons, |
1282 | "num_missed_bcon:\t%u\t\t\t%u\n", | 1369 | max_general->channel_beacons); |
1370 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1371 | "num_missed_bcon:", | ||
1283 | le32_to_cpu(general->num_missed_bcon), | 1372 | le32_to_cpu(general->num_missed_bcon), |
1284 | accum_general->num_missed_bcon); | 1373 | accum_general->num_missed_bcon, |
1285 | pos += scnprintf(buf + pos, bufsz - pos, | 1374 | delta_general->num_missed_bcon, |
1286 | "adc_rx_saturation_time:\t%u\t\t\t%u\n", | 1375 | max_general->num_missed_bcon); |
1376 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1377 | "adc_rx_saturation_time:", | ||
1287 | le32_to_cpu(general->adc_rx_saturation_time), | 1378 | le32_to_cpu(general->adc_rx_saturation_time), |
1288 | accum_general->adc_rx_saturation_time); | 1379 | accum_general->adc_rx_saturation_time, |
1289 | pos += scnprintf(buf + pos, bufsz - pos, | 1380 | delta_general->adc_rx_saturation_time, |
1290 | "ina_detect_search_tm:\t%u\t\t\t%u\n", | 1381 | max_general->adc_rx_saturation_time); |
1382 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1383 | "ina_detect_search_tm:", | ||
1291 | le32_to_cpu(general->ina_detection_search_time), | 1384 | le32_to_cpu(general->ina_detection_search_time), |
1292 | accum_general->ina_detection_search_time); | 1385 | accum_general->ina_detection_search_time, |
1293 | pos += scnprintf(buf + pos, bufsz - pos, | 1386 | delta_general->ina_detection_search_time, |
1294 | "beacon_silence_rssi_a:\t%u\t\t\t%u\n", | 1387 | max_general->ina_detection_search_time); |
1388 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1389 | "beacon_silence_rssi_a:", | ||
1295 | le32_to_cpu(general->beacon_silence_rssi_a), | 1390 | le32_to_cpu(general->beacon_silence_rssi_a), |
1296 | accum_general->beacon_silence_rssi_a); | 1391 | accum_general->beacon_silence_rssi_a, |
1297 | pos += scnprintf(buf + pos, bufsz - pos, | 1392 | delta_general->beacon_silence_rssi_a, |
1298 | "beacon_silence_rssi_b:\t%u\t\t\t%u\n", | 1393 | max_general->beacon_silence_rssi_a); |
1394 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1395 | "beacon_silence_rssi_b:", | ||
1299 | le32_to_cpu(general->beacon_silence_rssi_b), | 1396 | le32_to_cpu(general->beacon_silence_rssi_b), |
1300 | accum_general->beacon_silence_rssi_b); | 1397 | accum_general->beacon_silence_rssi_b, |
1301 | pos += scnprintf(buf + pos, bufsz - pos, | 1398 | delta_general->beacon_silence_rssi_b, |
1302 | "beacon_silence_rssi_c:\t%u\t\t\t%u\n", | 1399 | max_general->beacon_silence_rssi_b); |
1400 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1401 | "beacon_silence_rssi_c:", | ||
1303 | le32_to_cpu(general->beacon_silence_rssi_c), | 1402 | le32_to_cpu(general->beacon_silence_rssi_c), |
1304 | accum_general->beacon_silence_rssi_c); | 1403 | accum_general->beacon_silence_rssi_c, |
1305 | pos += scnprintf(buf + pos, bufsz - pos, | 1404 | delta_general->beacon_silence_rssi_c, |
1306 | "interference_data_flag:\t%u\t\t\t%u\n", | 1405 | max_general->beacon_silence_rssi_c); |
1406 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1407 | "interference_data_flag:", | ||
1307 | le32_to_cpu(general->interference_data_flag), | 1408 | le32_to_cpu(general->interference_data_flag), |
1308 | accum_general->interference_data_flag); | 1409 | accum_general->interference_data_flag, |
1309 | pos += scnprintf(buf + pos, bufsz - pos, | 1410 | delta_general->interference_data_flag, |
1310 | "channel_load:\t\t%u\t\t\t%u\n", | 1411 | max_general->interference_data_flag); |
1412 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1413 | "channel_load:", | ||
1311 | le32_to_cpu(general->channel_load), | 1414 | le32_to_cpu(general->channel_load), |
1312 | accum_general->channel_load); | 1415 | accum_general->channel_load, |
1313 | pos += scnprintf(buf + pos, bufsz - pos, | 1416 | delta_general->channel_load, |
1314 | "dsp_false_alarms:\t%u\t\t\t%u\n", | 1417 | max_general->channel_load); |
1418 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1419 | "dsp_false_alarms:", | ||
1315 | le32_to_cpu(general->dsp_false_alarms), | 1420 | le32_to_cpu(general->dsp_false_alarms), |
1316 | accum_general->dsp_false_alarms); | 1421 | accum_general->dsp_false_alarms, |
1317 | pos += scnprintf(buf + pos, bufsz - pos, | 1422 | delta_general->dsp_false_alarms, |
1318 | "beacon_rssi_a:\t\t%u\t\t\t%u\n", | 1423 | max_general->dsp_false_alarms); |
1424 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1425 | "beacon_rssi_a:", | ||
1319 | le32_to_cpu(general->beacon_rssi_a), | 1426 | le32_to_cpu(general->beacon_rssi_a), |
1320 | accum_general->beacon_rssi_a); | 1427 | accum_general->beacon_rssi_a, |
1321 | pos += scnprintf(buf + pos, bufsz - pos, | 1428 | delta_general->beacon_rssi_a, |
1322 | "beacon_rssi_b:\t\t%u\t\t\t%u\n", | 1429 | max_general->beacon_rssi_a); |
1430 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1431 | "beacon_rssi_b:", | ||
1323 | le32_to_cpu(general->beacon_rssi_b), | 1432 | le32_to_cpu(general->beacon_rssi_b), |
1324 | accum_general->beacon_rssi_b); | 1433 | accum_general->beacon_rssi_b, |
1325 | pos += scnprintf(buf + pos, bufsz - pos, | 1434 | delta_general->beacon_rssi_b, |
1326 | "beacon_rssi_c:\t\t%u\t\t\t%u\n", | 1435 | max_general->beacon_rssi_b); |
1436 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1437 | "beacon_rssi_c:", | ||
1327 | le32_to_cpu(general->beacon_rssi_c), | 1438 | le32_to_cpu(general->beacon_rssi_c), |
1328 | accum_general->beacon_rssi_c); | 1439 | accum_general->beacon_rssi_c, |
1329 | pos += scnprintf(buf + pos, bufsz - pos, | 1440 | delta_general->beacon_rssi_c, |
1330 | "beacon_energy_a:\t%u\t\t\t%u\n", | 1441 | max_general->beacon_rssi_c); |
1442 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1443 | "beacon_energy_a:", | ||
1331 | le32_to_cpu(general->beacon_energy_a), | 1444 | le32_to_cpu(general->beacon_energy_a), |
1332 | accum_general->beacon_energy_a); | 1445 | accum_general->beacon_energy_a, |
1333 | pos += scnprintf(buf + pos, bufsz - pos, | 1446 | delta_general->beacon_energy_a, |
1334 | "beacon_energy_b:\t%u\t\t\t%u\n", | 1447 | max_general->beacon_energy_a); |
1448 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1449 | "beacon_energy_b:", | ||
1335 | le32_to_cpu(general->beacon_energy_b), | 1450 | le32_to_cpu(general->beacon_energy_b), |
1336 | accum_general->beacon_energy_b); | 1451 | accum_general->beacon_energy_b, |
1337 | pos += scnprintf(buf + pos, bufsz - pos, | 1452 | delta_general->beacon_energy_b, |
1338 | "beacon_energy_c:\t%u\t\t\t%u\n", | 1453 | max_general->beacon_energy_b); |
1454 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1455 | "beacon_energy_c:", | ||
1339 | le32_to_cpu(general->beacon_energy_c), | 1456 | le32_to_cpu(general->beacon_energy_c), |
1340 | accum_general->beacon_energy_c); | 1457 | accum_general->beacon_energy_c, |
1458 | delta_general->beacon_energy_c, | ||
1459 | max_general->beacon_energy_c); | ||
1341 | 1460 | ||
1342 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n"); | 1461 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n"); |
1343 | pos += scnprintf(buf + pos, bufsz - pos, | 1462 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, |
1344 | "\t\t\tcurrent\t\t\taccumulative\n"); | 1463 | "Statistics_Rx - OFDM_HT:"); |
1345 | pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n", | 1464 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1346 | le32_to_cpu(ht->plcp_err), accum_ht->plcp_err); | 1465 | "plcp_err:", |
1347 | pos += scnprintf(buf + pos, bufsz - pos, | 1466 | le32_to_cpu(ht->plcp_err), accum_ht->plcp_err, |
1348 | "overrun_err:\t\t%u\t\t\t%u\n", | 1467 | delta_ht->plcp_err, max_ht->plcp_err); |
1349 | le32_to_cpu(ht->overrun_err), accum_ht->overrun_err); | 1468 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1350 | pos += scnprintf(buf + pos, bufsz - pos, | 1469 | "overrun_err:", |
1351 | "early_overrun_err:\t%u\t\t\t%u\n", | 1470 | le32_to_cpu(ht->overrun_err), accum_ht->overrun_err, |
1471 | delta_ht->overrun_err, max_ht->overrun_err); | ||
1472 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1473 | "early_overrun_err:", | ||
1352 | le32_to_cpu(ht->early_overrun_err), | 1474 | le32_to_cpu(ht->early_overrun_err), |
1353 | accum_ht->early_overrun_err); | 1475 | accum_ht->early_overrun_err, |
1354 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n", | 1476 | delta_ht->early_overrun_err, |
1355 | le32_to_cpu(ht->crc32_good), accum_ht->crc32_good); | 1477 | max_ht->early_overrun_err); |
1356 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n", | 1478 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1357 | le32_to_cpu(ht->crc32_err), accum_ht->crc32_err); | 1479 | "crc32_good:", |
1358 | pos += scnprintf(buf + pos, bufsz - pos, | 1480 | le32_to_cpu(ht->crc32_good), accum_ht->crc32_good, |
1359 | "mh_format_err:\t\t%u\t\t\t%u\n", | 1481 | delta_ht->crc32_good, max_ht->crc32_good); |
1482 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1483 | "crc32_err:", | ||
1484 | le32_to_cpu(ht->crc32_err), accum_ht->crc32_err, | ||
1485 | delta_ht->crc32_err, max_ht->crc32_err); | ||
1486 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1487 | "mh_format_err:", | ||
1360 | le32_to_cpu(ht->mh_format_err), | 1488 | le32_to_cpu(ht->mh_format_err), |
1361 | accum_ht->mh_format_err); | 1489 | accum_ht->mh_format_err, |
1362 | pos += scnprintf(buf + pos, bufsz - pos, | 1490 | delta_ht->mh_format_err, max_ht->mh_format_err); |
1363 | "agg_crc32_good:\t\t%u\t\t\t%u\n", | 1491 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1492 | "agg_crc32_good:", | ||
1364 | le32_to_cpu(ht->agg_crc32_good), | 1493 | le32_to_cpu(ht->agg_crc32_good), |
1365 | accum_ht->agg_crc32_good); | 1494 | accum_ht->agg_crc32_good, |
1366 | pos += scnprintf(buf + pos, bufsz - pos, | 1495 | delta_ht->agg_crc32_good, max_ht->agg_crc32_good); |
1367 | "agg_mpdu_cnt:\t\t%u\t\t\t%u\n", | 1496 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1497 | "agg_mpdu_cnt:", | ||
1368 | le32_to_cpu(ht->agg_mpdu_cnt), | 1498 | le32_to_cpu(ht->agg_mpdu_cnt), |
1369 | accum_ht->agg_mpdu_cnt); | 1499 | accum_ht->agg_mpdu_cnt, |
1370 | pos += scnprintf(buf + pos, bufsz - pos, "agg_cnt:\t\t%u\t\t\t%u\n", | 1500 | delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt); |
1371 | le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt); | 1501 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1502 | "agg_cnt:", | ||
1503 | le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt, | ||
1504 | delta_ht->agg_cnt, max_ht->agg_cnt); | ||
1505 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1506 | "unsupport_mcs:", | ||
1507 | le32_to_cpu(ht->unsupport_mcs), | ||
1508 | accum_ht->unsupport_mcs, | ||
1509 | delta_ht->unsupport_mcs, max_ht->unsupport_mcs); | ||
1372 | 1510 | ||
1373 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1511 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1374 | kfree(buf); | 1512 | kfree(buf); |
@@ -1379,26 +1517,16 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, | |||
1379 | char __user *user_buf, | 1517 | char __user *user_buf, |
1380 | size_t count, loff_t *ppos) | 1518 | size_t count, loff_t *ppos) |
1381 | { | 1519 | { |
1382 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 1520 | struct iwl_priv *priv = file->private_data; |
1383 | int pos = 0; | 1521 | int pos = 0; |
1384 | char *buf; | 1522 | char *buf; |
1385 | int bufsz = (sizeof(struct statistics_tx) * 24) + 250; | 1523 | int bufsz = (sizeof(struct statistics_tx) * 48) + 250; |
1386 | ssize_t ret; | 1524 | ssize_t ret; |
1387 | struct statistics_tx *tx, *accum_tx; | 1525 | struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; |
1388 | 1526 | ||
1389 | if (!iwl_is_alive(priv)) | 1527 | if (!iwl_is_alive(priv)) |
1390 | return -EAGAIN; | 1528 | return -EAGAIN; |
1391 | 1529 | ||
1392 | /* make request to uCode to retrieve statistics information */ | ||
1393 | mutex_lock(&priv->mutex); | ||
1394 | ret = iwl_send_statistics_request(priv, CMD_SYNC, false); | ||
1395 | mutex_unlock(&priv->mutex); | ||
1396 | |||
1397 | if (ret) { | ||
1398 | IWL_ERR(priv, | ||
1399 | "Error sending statistics request: %zd\n", ret); | ||
1400 | return -EAGAIN; | ||
1401 | } | ||
1402 | buf = kzalloc(bufsz, GFP_KERNEL); | 1530 | buf = kzalloc(bufsz, GFP_KERNEL); |
1403 | if (!buf) { | 1531 | if (!buf) { |
1404 | IWL_ERR(priv, "Can not allocate Buffer\n"); | 1532 | IWL_ERR(priv, "Can not allocate Buffer\n"); |
@@ -1411,106 +1539,148 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, | |||
1411 | */ | 1539 | */ |
1412 | tx = &priv->statistics.tx; | 1540 | tx = &priv->statistics.tx; |
1413 | accum_tx = &priv->accum_statistics.tx; | 1541 | accum_tx = &priv->accum_statistics.tx; |
1542 | delta_tx = &priv->delta_statistics.tx; | ||
1543 | max_tx = &priv->max_delta.tx; | ||
1414 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | 1544 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); |
1415 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Tx:\n"); | 1545 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, |
1416 | pos += scnprintf(buf + pos, bufsz - pos, | 1546 | "Statistics_Tx:"); |
1417 | "\t\t\tcurrent\t\t\taccumulative\n"); | 1547 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1418 | pos += scnprintf(buf + pos, bufsz - pos, "preamble:\t\t\t%u\t\t\t%u\n", | 1548 | "preamble:", |
1419 | le32_to_cpu(tx->preamble_cnt), | 1549 | le32_to_cpu(tx->preamble_cnt), |
1420 | accum_tx->preamble_cnt); | 1550 | accum_tx->preamble_cnt, |
1421 | pos += scnprintf(buf + pos, bufsz - pos, | 1551 | delta_tx->preamble_cnt, max_tx->preamble_cnt); |
1422 | "rx_detected_cnt:\t\t%u\t\t\t%u\n", | 1552 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1553 | "rx_detected_cnt:", | ||
1423 | le32_to_cpu(tx->rx_detected_cnt), | 1554 | le32_to_cpu(tx->rx_detected_cnt), |
1424 | accum_tx->rx_detected_cnt); | 1555 | accum_tx->rx_detected_cnt, |
1425 | pos += scnprintf(buf + pos, bufsz - pos, | 1556 | delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt); |
1426 | "bt_prio_defer_cnt:\t\t%u\t\t\t%u\n", | 1557 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1558 | "bt_prio_defer_cnt:", | ||
1427 | le32_to_cpu(tx->bt_prio_defer_cnt), | 1559 | le32_to_cpu(tx->bt_prio_defer_cnt), |
1428 | accum_tx->bt_prio_defer_cnt); | 1560 | accum_tx->bt_prio_defer_cnt, |
1429 | pos += scnprintf(buf + pos, bufsz - pos, | 1561 | delta_tx->bt_prio_defer_cnt, |
1430 | "bt_prio_kill_cnt:\t\t%u\t\t\t%u\n", | 1562 | max_tx->bt_prio_defer_cnt); |
1563 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1564 | "bt_prio_kill_cnt:", | ||
1431 | le32_to_cpu(tx->bt_prio_kill_cnt), | 1565 | le32_to_cpu(tx->bt_prio_kill_cnt), |
1432 | accum_tx->bt_prio_kill_cnt); | 1566 | accum_tx->bt_prio_kill_cnt, |
1433 | pos += scnprintf(buf + pos, bufsz - pos, | 1567 | delta_tx->bt_prio_kill_cnt, |
1434 | "few_bytes_cnt:\t\t\t%u\t\t\t%u\n", | 1568 | max_tx->bt_prio_kill_cnt); |
1569 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1570 | "few_bytes_cnt:", | ||
1435 | le32_to_cpu(tx->few_bytes_cnt), | 1571 | le32_to_cpu(tx->few_bytes_cnt), |
1436 | accum_tx->few_bytes_cnt); | 1572 | accum_tx->few_bytes_cnt, |
1437 | pos += scnprintf(buf + pos, bufsz - pos, | 1573 | delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt); |
1438 | "cts_timeout:\t\t\t%u\t\t\t%u\n", | 1574 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1439 | le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout); | 1575 | "cts_timeout:", |
1440 | pos += scnprintf(buf + pos, bufsz - pos, | 1576 | le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout, |
1441 | "ack_timeout:\t\t\t%u\t\t\t%u\n", | 1577 | delta_tx->cts_timeout, max_tx->cts_timeout); |
1578 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1579 | "ack_timeout:", | ||
1442 | le32_to_cpu(tx->ack_timeout), | 1580 | le32_to_cpu(tx->ack_timeout), |
1443 | accum_tx->ack_timeout); | 1581 | accum_tx->ack_timeout, |
1444 | pos += scnprintf(buf + pos, bufsz - pos, | 1582 | delta_tx->ack_timeout, max_tx->ack_timeout); |
1445 | "expected_ack_cnt:\t\t%u\t\t\t%u\n", | 1583 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1584 | "expected_ack_cnt:", | ||
1446 | le32_to_cpu(tx->expected_ack_cnt), | 1585 | le32_to_cpu(tx->expected_ack_cnt), |
1447 | accum_tx->expected_ack_cnt); | 1586 | accum_tx->expected_ack_cnt, |
1448 | pos += scnprintf(buf + pos, bufsz - pos, | 1587 | delta_tx->expected_ack_cnt, |
1449 | "actual_ack_cnt:\t\t\t%u\t\t\t%u\n", | 1588 | max_tx->expected_ack_cnt); |
1589 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1590 | "actual_ack_cnt:", | ||
1450 | le32_to_cpu(tx->actual_ack_cnt), | 1591 | le32_to_cpu(tx->actual_ack_cnt), |
1451 | accum_tx->actual_ack_cnt); | 1592 | accum_tx->actual_ack_cnt, |
1452 | pos += scnprintf(buf + pos, bufsz - pos, | 1593 | delta_tx->actual_ack_cnt, |
1453 | "dump_msdu_cnt:\t\t\t%u\t\t\t%u\n", | 1594 | max_tx->actual_ack_cnt); |
1595 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1596 | "dump_msdu_cnt:", | ||
1454 | le32_to_cpu(tx->dump_msdu_cnt), | 1597 | le32_to_cpu(tx->dump_msdu_cnt), |
1455 | accum_tx->dump_msdu_cnt); | 1598 | accum_tx->dump_msdu_cnt, |
1456 | pos += scnprintf(buf + pos, bufsz - pos, | 1599 | delta_tx->dump_msdu_cnt, |
1457 | "abort_nxt_frame_mismatch:" | 1600 | max_tx->dump_msdu_cnt); |
1458 | "\t%u\t\t\t%u\n", | 1601 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1602 | "abort_nxt_frame_mismatch:", | ||
1459 | le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt), | 1603 | le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt), |
1460 | accum_tx->burst_abort_next_frame_mismatch_cnt); | 1604 | accum_tx->burst_abort_next_frame_mismatch_cnt, |
1461 | pos += scnprintf(buf + pos, bufsz - pos, | 1605 | delta_tx->burst_abort_next_frame_mismatch_cnt, |
1462 | "abort_missing_nxt_frame:" | 1606 | max_tx->burst_abort_next_frame_mismatch_cnt); |
1463 | "\t%u\t\t\t%u\n", | 1607 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1608 | "abort_missing_nxt_frame:", | ||
1464 | le32_to_cpu(tx->burst_abort_missing_next_frame_cnt), | 1609 | le32_to_cpu(tx->burst_abort_missing_next_frame_cnt), |
1465 | accum_tx->burst_abort_missing_next_frame_cnt); | 1610 | accum_tx->burst_abort_missing_next_frame_cnt, |
1466 | pos += scnprintf(buf + pos, bufsz - pos, | 1611 | delta_tx->burst_abort_missing_next_frame_cnt, |
1467 | "cts_timeout_collision:\t\t%u\t\t\t%u\n", | 1612 | max_tx->burst_abort_missing_next_frame_cnt); |
1613 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1614 | "cts_timeout_collision:", | ||
1468 | le32_to_cpu(tx->cts_timeout_collision), | 1615 | le32_to_cpu(tx->cts_timeout_collision), |
1469 | accum_tx->cts_timeout_collision); | 1616 | accum_tx->cts_timeout_collision, |
1470 | pos += scnprintf(buf + pos, bufsz - pos, | 1617 | delta_tx->cts_timeout_collision, |
1471 | "ack_ba_timeout_collision:\t%u\t\t\t%u\n", | 1618 | max_tx->cts_timeout_collision); |
1619 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1620 | "ack_ba_timeout_collision:", | ||
1472 | le32_to_cpu(tx->ack_or_ba_timeout_collision), | 1621 | le32_to_cpu(tx->ack_or_ba_timeout_collision), |
1473 | accum_tx->ack_or_ba_timeout_collision); | 1622 | accum_tx->ack_or_ba_timeout_collision, |
1474 | pos += scnprintf(buf + pos, bufsz - pos, | 1623 | delta_tx->ack_or_ba_timeout_collision, |
1475 | "agg ba_timeout:\t\t\t%u\t\t\t%u\n", | 1624 | max_tx->ack_or_ba_timeout_collision); |
1625 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1626 | "agg ba_timeout:", | ||
1476 | le32_to_cpu(tx->agg.ba_timeout), | 1627 | le32_to_cpu(tx->agg.ba_timeout), |
1477 | accum_tx->agg.ba_timeout); | 1628 | accum_tx->agg.ba_timeout, |
1478 | pos += scnprintf(buf + pos, bufsz - pos, | 1629 | delta_tx->agg.ba_timeout, |
1479 | "agg ba_resched_frames:\t\t%u\t\t\t%u\n", | 1630 | max_tx->agg.ba_timeout); |
1631 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1632 | "agg ba_resched_frames:", | ||
1480 | le32_to_cpu(tx->agg.ba_reschedule_frames), | 1633 | le32_to_cpu(tx->agg.ba_reschedule_frames), |
1481 | accum_tx->agg.ba_reschedule_frames); | 1634 | accum_tx->agg.ba_reschedule_frames, |
1482 | pos += scnprintf(buf + pos, bufsz - pos, | 1635 | delta_tx->agg.ba_reschedule_frames, |
1483 | "agg scd_query_agg_frame:\t%u\t\t\t%u\n", | 1636 | max_tx->agg.ba_reschedule_frames); |
1637 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1638 | "agg scd_query_agg_frame:", | ||
1484 | le32_to_cpu(tx->agg.scd_query_agg_frame_cnt), | 1639 | le32_to_cpu(tx->agg.scd_query_agg_frame_cnt), |
1485 | accum_tx->agg.scd_query_agg_frame_cnt); | 1640 | accum_tx->agg.scd_query_agg_frame_cnt, |
1486 | pos += scnprintf(buf + pos, bufsz - pos, | 1641 | delta_tx->agg.scd_query_agg_frame_cnt, |
1487 | "agg scd_query_no_agg:\t\t%u\t\t\t%u\n", | 1642 | max_tx->agg.scd_query_agg_frame_cnt); |
1643 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1644 | "agg scd_query_no_agg:", | ||
1488 | le32_to_cpu(tx->agg.scd_query_no_agg), | 1645 | le32_to_cpu(tx->agg.scd_query_no_agg), |
1489 | accum_tx->agg.scd_query_no_agg); | 1646 | accum_tx->agg.scd_query_no_agg, |
1490 | pos += scnprintf(buf + pos, bufsz - pos, | 1647 | delta_tx->agg.scd_query_no_agg, |
1491 | "agg scd_query_agg:\t\t%u\t\t\t%u\n", | 1648 | max_tx->agg.scd_query_no_agg); |
1649 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1650 | "agg scd_query_agg:", | ||
1492 | le32_to_cpu(tx->agg.scd_query_agg), | 1651 | le32_to_cpu(tx->agg.scd_query_agg), |
1493 | accum_tx->agg.scd_query_agg); | 1652 | accum_tx->agg.scd_query_agg, |
1494 | pos += scnprintf(buf + pos, bufsz - pos, | 1653 | delta_tx->agg.scd_query_agg, |
1495 | "agg scd_query_mismatch:\t\t%u\t\t\t%u\n", | 1654 | max_tx->agg.scd_query_agg); |
1655 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1656 | "agg scd_query_mismatch:", | ||
1496 | le32_to_cpu(tx->agg.scd_query_mismatch), | 1657 | le32_to_cpu(tx->agg.scd_query_mismatch), |
1497 | accum_tx->agg.scd_query_mismatch); | 1658 | accum_tx->agg.scd_query_mismatch, |
1498 | pos += scnprintf(buf + pos, bufsz - pos, | 1659 | delta_tx->agg.scd_query_mismatch, |
1499 | "agg frame_not_ready:\t\t%u\t\t\t%u\n", | 1660 | max_tx->agg.scd_query_mismatch); |
1661 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1662 | "agg frame_not_ready:", | ||
1500 | le32_to_cpu(tx->agg.frame_not_ready), | 1663 | le32_to_cpu(tx->agg.frame_not_ready), |
1501 | accum_tx->agg.frame_not_ready); | 1664 | accum_tx->agg.frame_not_ready, |
1502 | pos += scnprintf(buf + pos, bufsz - pos, | 1665 | delta_tx->agg.frame_not_ready, |
1503 | "agg underrun:\t\t\t%u\t\t\t%u\n", | 1666 | max_tx->agg.frame_not_ready); |
1667 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1668 | "agg underrun:", | ||
1504 | le32_to_cpu(tx->agg.underrun), | 1669 | le32_to_cpu(tx->agg.underrun), |
1505 | accum_tx->agg.underrun); | 1670 | accum_tx->agg.underrun, |
1506 | pos += scnprintf(buf + pos, bufsz - pos, | 1671 | delta_tx->agg.underrun, max_tx->agg.underrun); |
1507 | "agg bt_prio_kill:\t\t%u\t\t\t%u\n", | 1672 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1673 | "agg bt_prio_kill:", | ||
1508 | le32_to_cpu(tx->agg.bt_prio_kill), | 1674 | le32_to_cpu(tx->agg.bt_prio_kill), |
1509 | accum_tx->agg.bt_prio_kill); | 1675 | accum_tx->agg.bt_prio_kill, |
1510 | pos += scnprintf(buf + pos, bufsz - pos, | 1676 | delta_tx->agg.bt_prio_kill, |
1511 | "agg rx_ba_rsp_cnt:\t\t%u\t\t\t%u\n", | 1677 | max_tx->agg.bt_prio_kill); |
1678 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1679 | "agg rx_ba_rsp_cnt:", | ||
1512 | le32_to_cpu(tx->agg.rx_ba_rsp_cnt), | 1680 | le32_to_cpu(tx->agg.rx_ba_rsp_cnt), |
1513 | accum_tx->agg.rx_ba_rsp_cnt); | 1681 | accum_tx->agg.rx_ba_rsp_cnt, |
1682 | delta_tx->agg.rx_ba_rsp_cnt, | ||
1683 | max_tx->agg.rx_ba_rsp_cnt); | ||
1514 | 1684 | ||
1515 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1685 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1516 | kfree(buf); | 1686 | kfree(buf); |
@@ -1521,28 +1691,19 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, | |||
1521 | char __user *user_buf, | 1691 | char __user *user_buf, |
1522 | size_t count, loff_t *ppos) | 1692 | size_t count, loff_t *ppos) |
1523 | { | 1693 | { |
1524 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 1694 | struct iwl_priv *priv = file->private_data; |
1525 | int pos = 0; | 1695 | int pos = 0; |
1526 | char *buf; | 1696 | char *buf; |
1527 | int bufsz = sizeof(struct statistics_general) * 4 + 250; | 1697 | int bufsz = sizeof(struct statistics_general) * 10 + 300; |
1528 | ssize_t ret; | 1698 | ssize_t ret; |
1529 | struct statistics_general *general, *accum_general; | 1699 | struct statistics_general *general, *accum_general; |
1530 | struct statistics_dbg *dbg, *accum_dbg; | 1700 | struct statistics_general *delta_general, *max_general; |
1531 | struct statistics_div *div, *accum_div; | 1701 | struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; |
1702 | struct statistics_div *div, *accum_div, *delta_div, *max_div; | ||
1532 | 1703 | ||
1533 | if (!iwl_is_alive(priv)) | 1704 | if (!iwl_is_alive(priv)) |
1534 | return -EAGAIN; | 1705 | return -EAGAIN; |
1535 | 1706 | ||
1536 | /* make request to uCode to retrieve statistics information */ | ||
1537 | mutex_lock(&priv->mutex); | ||
1538 | ret = iwl_send_statistics_request(priv, CMD_SYNC, false); | ||
1539 | mutex_unlock(&priv->mutex); | ||
1540 | |||
1541 | if (ret) { | ||
1542 | IWL_ERR(priv, | ||
1543 | "Error sending statistics request: %zd\n", ret); | ||
1544 | return -EAGAIN; | ||
1545 | } | ||
1546 | buf = kzalloc(bufsz, GFP_KERNEL); | 1707 | buf = kzalloc(bufsz, GFP_KERNEL); |
1547 | if (!buf) { | 1708 | if (!buf) { |
1548 | IWL_ERR(priv, "Can not allocate Buffer\n"); | 1709 | IWL_ERR(priv, "Can not allocate Buffer\n"); |
@@ -1557,52 +1718,78 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, | |||
1557 | dbg = &priv->statistics.general.dbg; | 1718 | dbg = &priv->statistics.general.dbg; |
1558 | div = &priv->statistics.general.div; | 1719 | div = &priv->statistics.general.div; |
1559 | accum_general = &priv->accum_statistics.general; | 1720 | accum_general = &priv->accum_statistics.general; |
1721 | delta_general = &priv->delta_statistics.general; | ||
1722 | max_general = &priv->max_delta.general; | ||
1560 | accum_dbg = &priv->accum_statistics.general.dbg; | 1723 | accum_dbg = &priv->accum_statistics.general.dbg; |
1724 | delta_dbg = &priv->delta_statistics.general.dbg; | ||
1725 | max_dbg = &priv->max_delta.general.dbg; | ||
1561 | accum_div = &priv->accum_statistics.general.div; | 1726 | accum_div = &priv->accum_statistics.general.div; |
1727 | delta_div = &priv->delta_statistics.general.div; | ||
1728 | max_div = &priv->max_delta.general.div; | ||
1562 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | 1729 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); |
1563 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_General:\n"); | 1730 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, |
1564 | pos += scnprintf(buf + pos, bufsz - pos, | 1731 | "Statistics_General:"); |
1565 | "\t\t\tcurrent\t\t\taccumulative\n"); | 1732 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_short_format, |
1566 | pos += scnprintf(buf + pos, bufsz - pos, "temperature:\t\t\t%u\n", | 1733 | "temperature:", |
1567 | le32_to_cpu(general->temperature)); | 1734 | le32_to_cpu(general->temperature)); |
1568 | pos += scnprintf(buf + pos, bufsz - pos, "temperature_m:\t\t\t%u\n", | 1735 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_short_format, |
1736 | "temperature_m:", | ||
1569 | le32_to_cpu(general->temperature_m)); | 1737 | le32_to_cpu(general->temperature_m)); |
1570 | pos += scnprintf(buf + pos, bufsz - pos, | 1738 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1571 | "burst_check:\t\t\t%u\t\t\t%u\n", | 1739 | "burst_check:", |
1572 | le32_to_cpu(dbg->burst_check), | 1740 | le32_to_cpu(dbg->burst_check), |
1573 | accum_dbg->burst_check); | 1741 | accum_dbg->burst_check, |
1574 | pos += scnprintf(buf + pos, bufsz - pos, | 1742 | delta_dbg->burst_check, max_dbg->burst_check); |
1575 | "burst_count:\t\t\t%u\t\t\t%u\n", | 1743 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1744 | "burst_count:", | ||
1576 | le32_to_cpu(dbg->burst_count), | 1745 | le32_to_cpu(dbg->burst_count), |
1577 | accum_dbg->burst_count); | 1746 | accum_dbg->burst_count, |
1578 | pos += scnprintf(buf + pos, bufsz - pos, | 1747 | delta_dbg->burst_count, max_dbg->burst_count); |
1579 | "sleep_time:\t\t\t%u\t\t\t%u\n", | 1748 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1749 | "sleep_time:", | ||
1580 | le32_to_cpu(general->sleep_time), | 1750 | le32_to_cpu(general->sleep_time), |
1581 | accum_general->sleep_time); | 1751 | accum_general->sleep_time, |
1582 | pos += scnprintf(buf + pos, bufsz - pos, | 1752 | delta_general->sleep_time, max_general->sleep_time); |
1583 | "slots_out:\t\t\t%u\t\t\t%u\n", | 1753 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1754 | "slots_out:", | ||
1584 | le32_to_cpu(general->slots_out), | 1755 | le32_to_cpu(general->slots_out), |
1585 | accum_general->slots_out); | 1756 | accum_general->slots_out, |
1586 | pos += scnprintf(buf + pos, bufsz - pos, | 1757 | delta_general->slots_out, max_general->slots_out); |
1587 | "slots_idle:\t\t\t%u\t\t\t%u\n", | 1758 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1759 | "slots_idle:", | ||
1588 | le32_to_cpu(general->slots_idle), | 1760 | le32_to_cpu(general->slots_idle), |
1589 | accum_general->slots_idle); | 1761 | accum_general->slots_idle, |
1762 | delta_general->slots_idle, max_general->slots_idle); | ||
1590 | pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n", | 1763 | pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n", |
1591 | le32_to_cpu(general->ttl_timestamp)); | 1764 | le32_to_cpu(general->ttl_timestamp)); |
1592 | pos += scnprintf(buf + pos, bufsz - pos, "tx_on_a:\t\t\t%u\t\t\t%u\n", | 1765 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1593 | le32_to_cpu(div->tx_on_a), accum_div->tx_on_a); | 1766 | "tx_on_a:", |
1594 | pos += scnprintf(buf + pos, bufsz - pos, "tx_on_b:\t\t\t%u\t\t\t%u\n", | 1767 | le32_to_cpu(div->tx_on_a), accum_div->tx_on_a, |
1595 | le32_to_cpu(div->tx_on_b), accum_div->tx_on_b); | 1768 | delta_div->tx_on_a, max_div->tx_on_a); |
1596 | pos += scnprintf(buf + pos, bufsz - pos, | 1769 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1597 | "exec_time:\t\t\t%u\t\t\t%u\n", | 1770 | "tx_on_b:", |
1598 | le32_to_cpu(div->exec_time), accum_div->exec_time); | 1771 | le32_to_cpu(div->tx_on_b), accum_div->tx_on_b, |
1599 | pos += scnprintf(buf + pos, bufsz - pos, | 1772 | delta_div->tx_on_b, max_div->tx_on_b); |
1600 | "probe_time:\t\t\t%u\t\t\t%u\n", | 1773 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1601 | le32_to_cpu(div->probe_time), accum_div->probe_time); | 1774 | "exec_time:", |
1602 | pos += scnprintf(buf + pos, bufsz - pos, | 1775 | le32_to_cpu(div->exec_time), accum_div->exec_time, |
1603 | "rx_enable_counter:\t\t%u\t\t\t%u\n", | 1776 | delta_div->exec_time, max_div->exec_time); |
1777 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1778 | "probe_time:", | ||
1779 | le32_to_cpu(div->probe_time), accum_div->probe_time, | ||
1780 | delta_div->probe_time, max_div->probe_time); | ||
1781 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1782 | "rx_enable_counter:", | ||
1604 | le32_to_cpu(general->rx_enable_counter), | 1783 | le32_to_cpu(general->rx_enable_counter), |
1605 | accum_general->rx_enable_counter); | 1784 | accum_general->rx_enable_counter, |
1785 | delta_general->rx_enable_counter, | ||
1786 | max_general->rx_enable_counter); | ||
1787 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1788 | "num_of_sos_states:", | ||
1789 | le32_to_cpu(general->num_of_sos_states), | ||
1790 | accum_general->num_of_sos_states, | ||
1791 | delta_general->num_of_sos_states, | ||
1792 | max_general->num_of_sos_states); | ||
1606 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1793 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1607 | kfree(buf); | 1794 | kfree(buf); |
1608 | return ret; | 1795 | return ret; |
@@ -1612,7 +1799,7 @@ static ssize_t iwl_dbgfs_sensitivity_read(struct file *file, | |||
1612 | char __user *user_buf, | 1799 | char __user *user_buf, |
1613 | size_t count, loff_t *ppos) { | 1800 | size_t count, loff_t *ppos) { |
1614 | 1801 | ||
1615 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 1802 | struct iwl_priv *priv = file->private_data; |
1616 | int pos = 0; | 1803 | int pos = 0; |
1617 | int cnt = 0; | 1804 | int cnt = 0; |
1618 | char *buf; | 1805 | char *buf; |
@@ -1693,7 +1880,7 @@ static ssize_t iwl_dbgfs_chain_noise_read(struct file *file, | |||
1693 | char __user *user_buf, | 1880 | char __user *user_buf, |
1694 | size_t count, loff_t *ppos) { | 1881 | size_t count, loff_t *ppos) { |
1695 | 1882 | ||
1696 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 1883 | struct iwl_priv *priv = file->private_data; |
1697 | int pos = 0; | 1884 | int pos = 0; |
1698 | int cnt = 0; | 1885 | int cnt = 0; |
1699 | char *buf; | 1886 | char *buf; |
@@ -1751,26 +1938,15 @@ static ssize_t iwl_dbgfs_tx_power_read(struct file *file, | |||
1751 | char __user *user_buf, | 1938 | char __user *user_buf, |
1752 | size_t count, loff_t *ppos) { | 1939 | size_t count, loff_t *ppos) { |
1753 | 1940 | ||
1754 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 1941 | struct iwl_priv *priv = file->private_data; |
1755 | char buf[128]; | 1942 | char buf[128]; |
1756 | int pos = 0; | 1943 | int pos = 0; |
1757 | ssize_t ret; | ||
1758 | const size_t bufsz = sizeof(buf); | 1944 | const size_t bufsz = sizeof(buf); |
1759 | struct statistics_tx *tx; | 1945 | struct statistics_tx *tx; |
1760 | 1946 | ||
1761 | if (!iwl_is_alive(priv)) | 1947 | if (!iwl_is_alive(priv)) |
1762 | pos += scnprintf(buf + pos, bufsz - pos, "N/A\n"); | 1948 | pos += scnprintf(buf + pos, bufsz - pos, "N/A\n"); |
1763 | else { | 1949 | else { |
1764 | /* make request to uCode to retrieve statistics information */ | ||
1765 | mutex_lock(&priv->mutex); | ||
1766 | ret = iwl_send_statistics_request(priv, CMD_SYNC, false); | ||
1767 | mutex_unlock(&priv->mutex); | ||
1768 | |||
1769 | if (ret) { | ||
1770 | IWL_ERR(priv, "Error sending statistics request: %zd\n", | ||
1771 | ret); | ||
1772 | return -EAGAIN; | ||
1773 | } | ||
1774 | tx = &priv->statistics.tx; | 1950 | tx = &priv->statistics.tx; |
1775 | if (tx->tx_power.ant_a || | 1951 | if (tx->tx_power.ant_a || |
1776 | tx->tx_power.ant_b || | 1952 | tx->tx_power.ant_b || |
@@ -1802,7 +1978,7 @@ static ssize_t iwl_dbgfs_power_save_status_read(struct file *file, | |||
1802 | char __user *user_buf, | 1978 | char __user *user_buf, |
1803 | size_t count, loff_t *ppos) | 1979 | size_t count, loff_t *ppos) |
1804 | { | 1980 | { |
1805 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 1981 | struct iwl_priv *priv = file->private_data; |
1806 | char buf[60]; | 1982 | char buf[60]; |
1807 | int pos = 0; | 1983 | int pos = 0; |
1808 | const size_t bufsz = sizeof(buf); | 1984 | const size_t bufsz = sizeof(buf); |
@@ -1845,6 +2021,262 @@ static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file, | |||
1845 | return count; | 2021 | return count; |
1846 | } | 2022 | } |
1847 | 2023 | ||
2024 | static ssize_t iwl_dbgfs_csr_write(struct file *file, | ||
2025 | const char __user *user_buf, | ||
2026 | size_t count, loff_t *ppos) | ||
2027 | { | ||
2028 | struct iwl_priv *priv = file->private_data; | ||
2029 | char buf[8]; | ||
2030 | int buf_size; | ||
2031 | int csr; | ||
2032 | |||
2033 | memset(buf, 0, sizeof(buf)); | ||
2034 | buf_size = min(count, sizeof(buf) - 1); | ||
2035 | if (copy_from_user(buf, user_buf, buf_size)) | ||
2036 | return -EFAULT; | ||
2037 | if (sscanf(buf, "%d", &csr) != 1) | ||
2038 | return -EFAULT; | ||
2039 | |||
2040 | if (priv->cfg->ops->lib->dump_csr) | ||
2041 | priv->cfg->ops->lib->dump_csr(priv); | ||
2042 | |||
2043 | return count; | ||
2044 | } | ||
2045 | |||
2046 | static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file, | ||
2047 | char __user *user_buf, | ||
2048 | size_t count, loff_t *ppos) { | ||
2049 | |||
2050 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | ||
2051 | int pos = 0; | ||
2052 | char buf[128]; | ||
2053 | const size_t bufsz = sizeof(buf); | ||
2054 | ssize_t ret; | ||
2055 | |||
2056 | pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n", | ||
2057 | priv->event_log.ucode_trace ? "On" : "Off"); | ||
2058 | pos += scnprintf(buf + pos, bufsz - pos, "non_wraps_count:\t\t %u\n", | ||
2059 | priv->event_log.non_wraps_count); | ||
2060 | pos += scnprintf(buf + pos, bufsz - pos, "wraps_once_count:\t\t %u\n", | ||
2061 | priv->event_log.wraps_once_count); | ||
2062 | pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n", | ||
2063 | priv->event_log.wraps_more_count); | ||
2064 | |||
2065 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
2066 | return ret; | ||
2067 | } | ||
2068 | |||
2069 | static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file, | ||
2070 | const char __user *user_buf, | ||
2071 | size_t count, loff_t *ppos) | ||
2072 | { | ||
2073 | struct iwl_priv *priv = file->private_data; | ||
2074 | char buf[8]; | ||
2075 | int buf_size; | ||
2076 | int trace; | ||
2077 | |||
2078 | memset(buf, 0, sizeof(buf)); | ||
2079 | buf_size = min(count, sizeof(buf) - 1); | ||
2080 | if (copy_from_user(buf, user_buf, buf_size)) | ||
2081 | return -EFAULT; | ||
2082 | if (sscanf(buf, "%d", &trace) != 1) | ||
2083 | return -EFAULT; | ||
2084 | |||
2085 | if (trace) { | ||
2086 | priv->event_log.ucode_trace = true; | ||
2087 | /* schedule the ucode timer to occur in UCODE_TRACE_PERIOD */ | ||
2088 | mod_timer(&priv->ucode_trace, | ||
2089 | jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD)); | ||
2090 | } else { | ||
2091 | priv->event_log.ucode_trace = false; | ||
2092 | del_timer_sync(&priv->ucode_trace); | ||
2093 | } | ||
2094 | |||
2095 | return count; | ||
2096 | } | ||
2097 | |||
2098 | static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, | ||
2099 | char __user *user_buf, | ||
2100 | size_t count, loff_t *ppos) | ||
2101 | { | ||
2102 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | ||
2103 | char *buf; | ||
2104 | int pos = 0; | ||
2105 | ssize_t ret = -EFAULT; | ||
2106 | |||
2107 | if (priv->cfg->ops->lib->dump_fh) { | ||
2108 | ret = pos = priv->cfg->ops->lib->dump_fh(priv, &buf, true); | ||
2109 | if (buf) { | ||
2110 | ret = simple_read_from_buffer(user_buf, | ||
2111 | count, ppos, buf, pos); | ||
2112 | kfree(buf); | ||
2113 | } | ||
2114 | } | ||
2115 | |||
2116 | return ret; | ||
2117 | } | ||
2118 | |||
2119 | static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file, | ||
2120 | char __user *user_buf, | ||
2121 | size_t count, loff_t *ppos) { | ||
2122 | |||
2123 | struct iwl_priv *priv = file->private_data; | ||
2124 | int pos = 0; | ||
2125 | char buf[12]; | ||
2126 | const size_t bufsz = sizeof(buf); | ||
2127 | ssize_t ret; | ||
2128 | |||
2129 | pos += scnprintf(buf + pos, bufsz - pos, "%d\n", | ||
2130 | priv->missed_beacon_threshold); | ||
2131 | |||
2132 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
2133 | return ret; | ||
2134 | } | ||
2135 | |||
2136 | static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file, | ||
2137 | const char __user *user_buf, | ||
2138 | size_t count, loff_t *ppos) | ||
2139 | { | ||
2140 | struct iwl_priv *priv = file->private_data; | ||
2141 | char buf[8]; | ||
2142 | int buf_size; | ||
2143 | int missed; | ||
2144 | |||
2145 | memset(buf, 0, sizeof(buf)); | ||
2146 | buf_size = min(count, sizeof(buf) - 1); | ||
2147 | if (copy_from_user(buf, user_buf, buf_size)) | ||
2148 | return -EFAULT; | ||
2149 | if (sscanf(buf, "%d", &missed) != 1) | ||
2150 | return -EINVAL; | ||
2151 | |||
2152 | if (missed < IWL_MISSED_BEACON_THRESHOLD_MIN || | ||
2153 | missed > IWL_MISSED_BEACON_THRESHOLD_MAX) | ||
2154 | priv->missed_beacon_threshold = | ||
2155 | IWL_MISSED_BEACON_THRESHOLD_DEF; | ||
2156 | else | ||
2157 | priv->missed_beacon_threshold = missed; | ||
2158 | |||
2159 | return count; | ||
2160 | } | ||
2161 | |||
2162 | static ssize_t iwl_dbgfs_internal_scan_write(struct file *file, | ||
2163 | const char __user *user_buf, | ||
2164 | size_t count, loff_t *ppos) | ||
2165 | { | ||
2166 | struct iwl_priv *priv = file->private_data; | ||
2167 | char buf[8]; | ||
2168 | int buf_size; | ||
2169 | int scan; | ||
2170 | |||
2171 | memset(buf, 0, sizeof(buf)); | ||
2172 | buf_size = min(count, sizeof(buf) - 1); | ||
2173 | if (copy_from_user(buf, user_buf, buf_size)) | ||
2174 | return -EFAULT; | ||
2175 | if (sscanf(buf, "%d", &scan) != 1) | ||
2176 | return -EINVAL; | ||
2177 | |||
2178 | iwl_internal_short_hw_scan(priv); | ||
2179 | |||
2180 | return count; | ||
2181 | } | ||
2182 | |||
2183 | static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file, | ||
2184 | char __user *user_buf, | ||
2185 | size_t count, loff_t *ppos) { | ||
2186 | |||
2187 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | ||
2188 | int pos = 0; | ||
2189 | char buf[12]; | ||
2190 | const size_t bufsz = sizeof(buf); | ||
2191 | ssize_t ret; | ||
2192 | |||
2193 | pos += scnprintf(buf + pos, bufsz - pos, "%u\n", | ||
2194 | priv->cfg->plcp_delta_threshold); | ||
2195 | |||
2196 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
2197 | return ret; | ||
2198 | } | ||
2199 | |||
2200 | static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file, | ||
2201 | const char __user *user_buf, | ||
2202 | size_t count, loff_t *ppos) { | ||
2203 | |||
2204 | struct iwl_priv *priv = file->private_data; | ||
2205 | char buf[8]; | ||
2206 | int buf_size; | ||
2207 | int plcp; | ||
2208 | |||
2209 | memset(buf, 0, sizeof(buf)); | ||
2210 | buf_size = min(count, sizeof(buf) - 1); | ||
2211 | if (copy_from_user(buf, user_buf, buf_size)) | ||
2212 | return -EFAULT; | ||
2213 | if (sscanf(buf, "%d", &plcp) != 1) | ||
2214 | return -EINVAL; | ||
2215 | if ((plcp <= IWL_MAX_PLCP_ERR_THRESHOLD_MIN) || | ||
2216 | (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX)) | ||
2217 | priv->cfg->plcp_delta_threshold = | ||
2218 | IWL_MAX_PLCP_ERR_THRESHOLD_DEF; | ||
2219 | else | ||
2220 | priv->cfg->plcp_delta_threshold = plcp; | ||
2221 | return count; | ||
2222 | } | ||
2223 | |||
2224 | static ssize_t iwl_dbgfs_force_reset_read(struct file *file, | ||
2225 | char __user *user_buf, | ||
2226 | size_t count, loff_t *ppos) { | ||
2227 | |||
2228 | struct iwl_priv *priv = file->private_data; | ||
2229 | int i, pos = 0; | ||
2230 | char buf[300]; | ||
2231 | const size_t bufsz = sizeof(buf); | ||
2232 | struct iwl_force_reset *force_reset; | ||
2233 | |||
2234 | for (i = 0; i < IWL_MAX_FORCE_RESET; i++) { | ||
2235 | force_reset = &priv->force_reset[i]; | ||
2236 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2237 | "Force reset method %d\n", i); | ||
2238 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2239 | "\tnumber of reset request: %d\n", | ||
2240 | force_reset->reset_request_count); | ||
2241 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2242 | "\tnumber of reset request success: %d\n", | ||
2243 | force_reset->reset_success_count); | ||
2244 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2245 | "\tnumber of reset request reject: %d\n", | ||
2246 | force_reset->reset_reject_count); | ||
2247 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2248 | "\treset duration: %lu\n", | ||
2249 | force_reset->reset_duration); | ||
2250 | } | ||
2251 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
2252 | } | ||
2253 | |||
2254 | static ssize_t iwl_dbgfs_force_reset_write(struct file *file, | ||
2255 | const char __user *user_buf, | ||
2256 | size_t count, loff_t *ppos) { | ||
2257 | |||
2258 | struct iwl_priv *priv = file->private_data; | ||
2259 | char buf[8]; | ||
2260 | int buf_size; | ||
2261 | int reset, ret; | ||
2262 | |||
2263 | memset(buf, 0, sizeof(buf)); | ||
2264 | buf_size = min(count, sizeof(buf) - 1); | ||
2265 | if (copy_from_user(buf, user_buf, buf_size)) | ||
2266 | return -EFAULT; | ||
2267 | if (sscanf(buf, "%d", &reset) != 1) | ||
2268 | return -EINVAL; | ||
2269 | switch (reset) { | ||
2270 | case IWL_RF_RESET: | ||
2271 | case IWL_FW_RESET: | ||
2272 | ret = iwl_force_reset(priv, reset); | ||
2273 | break; | ||
2274 | default: | ||
2275 | return -EINVAL; | ||
2276 | } | ||
2277 | return ret ? ret : count; | ||
2278 | } | ||
2279 | |||
1848 | DEBUGFS_READ_FILE_OPS(rx_statistics); | 2280 | DEBUGFS_READ_FILE_OPS(rx_statistics); |
1849 | DEBUGFS_READ_FILE_OPS(tx_statistics); | 2281 | DEBUGFS_READ_FILE_OPS(tx_statistics); |
1850 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); | 2282 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); |
@@ -1859,6 +2291,13 @@ DEBUGFS_READ_FILE_OPS(tx_power); | |||
1859 | DEBUGFS_READ_FILE_OPS(power_save_status); | 2291 | DEBUGFS_READ_FILE_OPS(power_save_status); |
1860 | DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); | 2292 | DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); |
1861 | DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); | 2293 | DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); |
2294 | DEBUGFS_WRITE_FILE_OPS(csr); | ||
2295 | DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); | ||
2296 | DEBUGFS_READ_FILE_OPS(fh_reg); | ||
2297 | DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); | ||
2298 | DEBUGFS_WRITE_FILE_OPS(internal_scan); | ||
2299 | DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); | ||
2300 | DEBUGFS_READ_WRITE_FILE_OPS(force_reset); | ||
1862 | 2301 | ||
1863 | /* | 2302 | /* |
1864 | * Create the debugfs files and directories | 2303 | * Create the debugfs files and directories |
@@ -1866,69 +2305,74 @@ DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); | |||
1866 | */ | 2305 | */ |
1867 | int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | 2306 | int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) |
1868 | { | 2307 | { |
1869 | struct iwl_debugfs *dbgfs; | ||
1870 | struct dentry *phyd = priv->hw->wiphy->debugfsdir; | 2308 | struct dentry *phyd = priv->hw->wiphy->debugfsdir; |
1871 | int ret = 0; | 2309 | struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug; |
1872 | 2310 | ||
1873 | dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL); | 2311 | dir_drv = debugfs_create_dir(name, phyd); |
1874 | if (!dbgfs) { | 2312 | if (!dir_drv) |
1875 | ret = -ENOMEM; | 2313 | return -ENOMEM; |
1876 | goto err; | 2314 | |
1877 | } | 2315 | priv->debugfs_dir = dir_drv; |
1878 | 2316 | ||
1879 | priv->dbgfs = dbgfs; | 2317 | dir_data = debugfs_create_dir("data", dir_drv); |
1880 | dbgfs->name = name; | 2318 | if (!dir_data) |
1881 | dbgfs->dir_drv = debugfs_create_dir(name, phyd); | 2319 | goto err; |
1882 | if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)) { | 2320 | dir_rf = debugfs_create_dir("rf", dir_drv); |
1883 | ret = -ENOENT; | 2321 | if (!dir_rf) |
2322 | goto err; | ||
2323 | dir_debug = debugfs_create_dir("debug", dir_drv); | ||
2324 | if (!dir_debug) | ||
1884 | goto err; | 2325 | goto err; |
1885 | } | ||
1886 | 2326 | ||
1887 | DEBUGFS_ADD_DIR(data, dbgfs->dir_drv); | 2327 | DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR); |
1888 | DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv); | 2328 | DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR); |
1889 | DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv); | 2329 | DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR); |
1890 | DEBUGFS_ADD_FILE(nvm, data, S_IRUSR); | 2330 | DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR); |
1891 | DEBUGFS_ADD_FILE(sram, data, S_IWUSR | S_IRUSR); | 2331 | DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR); |
1892 | DEBUGFS_ADD_FILE(log_event, data, S_IWUSR); | 2332 | DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); |
1893 | DEBUGFS_ADD_FILE(stations, data, S_IRUSR); | 2333 | DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); |
1894 | DEBUGFS_ADD_FILE(channels, data, S_IRUSR); | 2334 | DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); |
1895 | DEBUGFS_ADD_FILE(status, data, S_IRUSR); | 2335 | DEBUGFS_ADD_FILE(led, dir_data, S_IRUSR); |
1896 | DEBUGFS_ADD_FILE(interrupt, data, S_IWUSR | S_IRUSR); | 2336 | DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR); |
1897 | DEBUGFS_ADD_FILE(qos, data, S_IRUSR); | 2337 | DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); |
1898 | DEBUGFS_ADD_FILE(led, data, S_IRUSR); | 2338 | DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR); |
1899 | DEBUGFS_ADD_FILE(sleep_level_override, data, S_IWUSR | S_IRUSR); | 2339 | DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); |
1900 | DEBUGFS_ADD_FILE(current_sleep_command, data, S_IRUSR); | 2340 | DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); |
1901 | DEBUGFS_ADD_FILE(thermal_throttling, data, S_IRUSR); | 2341 | DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR); |
1902 | DEBUGFS_ADD_FILE(disable_ht40, data, S_IWUSR | S_IRUSR); | 2342 | DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR); |
1903 | DEBUGFS_ADD_FILE(rx_statistics, debug, S_IRUSR); | 2343 | DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR); |
1904 | DEBUGFS_ADD_FILE(tx_statistics, debug, S_IRUSR); | 2344 | DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR); |
1905 | DEBUGFS_ADD_FILE(traffic_log, debug, S_IWUSR | S_IRUSR); | 2345 | DEBUGFS_ADD_FILE(tx_power, dir_debug, S_IRUSR); |
1906 | DEBUGFS_ADD_FILE(rx_queue, debug, S_IRUSR); | 2346 | DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); |
1907 | DEBUGFS_ADD_FILE(tx_queue, debug, S_IRUSR); | 2347 | DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR); |
1908 | DEBUGFS_ADD_FILE(tx_power, debug, S_IRUSR); | 2348 | DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR); |
1909 | DEBUGFS_ADD_FILE(power_save_status, debug, S_IRUSR); | 2349 | DEBUGFS_ADD_FILE(csr, dir_debug, S_IWUSR); |
1910 | DEBUGFS_ADD_FILE(clear_ucode_statistics, debug, S_IWUSR); | 2350 | DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR); |
1911 | DEBUGFS_ADD_FILE(clear_traffic_statistics, debug, S_IWUSR); | 2351 | DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); |
2352 | DEBUGFS_ADD_FILE(internal_scan, dir_debug, S_IWUSR); | ||
2353 | DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); | ||
2354 | DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); | ||
1912 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { | 2355 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { |
1913 | DEBUGFS_ADD_FILE(ucode_rx_stats, debug, S_IRUSR); | 2356 | DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); |
1914 | DEBUGFS_ADD_FILE(ucode_tx_stats, debug, S_IRUSR); | 2357 | DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); |
1915 | DEBUGFS_ADD_FILE(ucode_general_stats, debug, S_IRUSR); | 2358 | DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); |
1916 | DEBUGFS_ADD_FILE(sensitivity, debug, S_IRUSR); | 2359 | DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); |
1917 | DEBUGFS_ADD_FILE(chain_noise, debug, S_IRUSR); | 2360 | DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); |
2361 | DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); | ||
1918 | } | 2362 | } |
1919 | DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); | 2363 | DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, &priv->disable_sens_cal); |
1920 | DEBUGFS_ADD_BOOL(disable_chain_noise, rf, | 2364 | DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, |
1921 | &priv->disable_chain_noise_cal); | 2365 | &priv->disable_chain_noise_cal); |
1922 | if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) || | 2366 | if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) || |
1923 | ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945)) | 2367 | ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945)) |
1924 | DEBUGFS_ADD_BOOL(disable_tx_power, rf, | 2368 | DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, |
1925 | &priv->disable_tx_power_cal); | 2369 | &priv->disable_tx_power_cal); |
1926 | return 0; | 2370 | return 0; |
1927 | 2371 | ||
1928 | err: | 2372 | err: |
1929 | IWL_ERR(priv, "Can't open the debugfs directory\n"); | 2373 | IWL_ERR(priv, "Can't create the debugfs directory\n"); |
1930 | iwl_dbgfs_unregister(priv); | 2374 | iwl_dbgfs_unregister(priv); |
1931 | return ret; | 2375 | return -ENOMEM; |
1932 | } | 2376 | } |
1933 | EXPORT_SYMBOL(iwl_dbgfs_register); | 2377 | EXPORT_SYMBOL(iwl_dbgfs_register); |
1934 | 2378 | ||
@@ -1938,56 +2382,11 @@ EXPORT_SYMBOL(iwl_dbgfs_register); | |||
1938 | */ | 2382 | */ |
1939 | void iwl_dbgfs_unregister(struct iwl_priv *priv) | 2383 | void iwl_dbgfs_unregister(struct iwl_priv *priv) |
1940 | { | 2384 | { |
1941 | if (!priv->dbgfs) | 2385 | if (!priv->debugfs_dir) |
1942 | return; | 2386 | return; |
1943 | 2387 | ||
1944 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sleep_level_override); | 2388 | debugfs_remove_recursive(priv->debugfs_dir); |
1945 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_current_sleep_command); | 2389 | priv->debugfs_dir = NULL; |
1946 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm); | ||
1947 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram); | ||
1948 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event); | ||
1949 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations); | ||
1950 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels); | ||
1951 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status); | ||
1952 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt); | ||
1953 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_qos); | ||
1954 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_led); | ||
1955 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling); | ||
1956 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40); | ||
1957 | DEBUGFS_REMOVE(priv->dbgfs->dir_data); | ||
1958 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_statistics); | ||
1959 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_statistics); | ||
1960 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_traffic_log); | ||
1961 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_queue); | ||
1962 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue); | ||
1963 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_power); | ||
1964 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_power_save_status); | ||
1965 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. | ||
1966 | file_clear_ucode_statistics); | ||
1967 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. | ||
1968 | file_clear_traffic_statistics); | ||
1969 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { | ||
1970 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. | ||
1971 | file_ucode_rx_stats); | ||
1972 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. | ||
1973 | file_ucode_tx_stats); | ||
1974 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. | ||
1975 | file_ucode_general_stats); | ||
1976 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. | ||
1977 | file_sensitivity); | ||
1978 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. | ||
1979 | file_chain_noise); | ||
1980 | } | ||
1981 | DEBUGFS_REMOVE(priv->dbgfs->dir_debug); | ||
1982 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity); | ||
1983 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise); | ||
1984 | if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) || | ||
1985 | ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945)) | ||
1986 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_tx_power); | ||
1987 | DEBUGFS_REMOVE(priv->dbgfs->dir_rf); | ||
1988 | DEBUGFS_REMOVE(priv->dbgfs->dir_drv); | ||
1989 | kfree(priv->dbgfs); | ||
1990 | priv->dbgfs = NULL; | ||
1991 | } | 2390 | } |
1992 | EXPORT_SYMBOL(iwl_dbgfs_unregister); | 2391 | EXPORT_SYMBOL(iwl_dbgfs_unregister); |
1993 | 2392 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 3822cf53e368..7914d65a5a55 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 |
@@ -512,6 +512,7 @@ struct iwl_ht_config { | |||
512 | bool is_ht; | 512 | bool is_ht; |
513 | bool is_40mhz; | 513 | bool is_40mhz; |
514 | bool single_chain_sufficient; | 514 | bool single_chain_sufficient; |
515 | enum ieee80211_smps_mode smps; /* current smps mode */ | ||
515 | /* BSS related data */ | 516 | /* BSS related data */ |
516 | u8 extension_chan_offset; | 517 | u8 extension_chan_offset; |
517 | u8 ht_protection; | 518 | u8 ht_protection; |
@@ -984,6 +985,74 @@ struct iwl_switch_rxon { | |||
984 | __le16 channel; | 985 | __le16 channel; |
985 | }; | 986 | }; |
986 | 987 | ||
988 | /* | ||
989 | * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds | ||
990 | * to perform continuous uCode event logging operation if enabled | ||
991 | */ | ||
992 | #define UCODE_TRACE_PERIOD (100) | ||
993 | |||
994 | /* | ||
995 | * iwl_event_log: current uCode event log position | ||
996 | * | ||
997 | * @ucode_trace: enable/disable ucode continuous trace timer | ||
998 | * @num_wraps: how many times the event buffer wraps | ||
999 | * @next_entry: the entry just before the next one that uCode would fill | ||
1000 | * @non_wraps_count: counter for no wrap detected when dump ucode events | ||
1001 | * @wraps_once_count: counter for wrap once detected when dump ucode events | ||
1002 | * @wraps_more_count: counter for wrap more than once detected | ||
1003 | * when dump ucode events | ||
1004 | */ | ||
1005 | struct iwl_event_log { | ||
1006 | bool ucode_trace; | ||
1007 | u32 num_wraps; | ||
1008 | u32 next_entry; | ||
1009 | int non_wraps_count; | ||
1010 | int wraps_once_count; | ||
1011 | int wraps_more_count; | ||
1012 | }; | ||
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_EXT_LONG_THRESHOLD_DEF (200) | ||
1037 | #define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255) | ||
1038 | |||
1039 | #define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3) | ||
1040 | #define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5) | ||
1041 | |||
1042 | enum iwl_reset { | ||
1043 | IWL_RF_RESET = 0, | ||
1044 | IWL_FW_RESET, | ||
1045 | IWL_MAX_FORCE_RESET, | ||
1046 | }; | ||
1047 | |||
1048 | struct iwl_force_reset { | ||
1049 | int reset_request_count; | ||
1050 | int reset_success_count; | ||
1051 | int reset_reject_count; | ||
1052 | unsigned long reset_duration; | ||
1053 | unsigned long last_force_reset_jiffies; | ||
1054 | }; | ||
1055 | |||
987 | struct iwl_priv { | 1056 | struct iwl_priv { |
988 | 1057 | ||
989 | /* ieee device used by generic ieee processing code */ | 1058 | /* ieee device used by generic ieee processing code */ |
@@ -1004,13 +1073,22 @@ struct iwl_priv { | |||
1004 | 1073 | ||
1005 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; | 1074 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; |
1006 | 1075 | ||
1007 | #if defined(CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT) || defined(CONFIG_IWL3945_SPECTRUM_MEASUREMENT) | ||
1008 | /* spectrum measurement report caching */ | 1076 | /* spectrum measurement report caching */ |
1009 | struct iwl_spectrum_notification measure_report; | 1077 | struct iwl_spectrum_notification measure_report; |
1010 | u8 measurement_status; | 1078 | u8 measurement_status; |
1011 | #endif | 1079 | |
1012 | /* ucode beacon time */ | 1080 | /* ucode beacon time */ |
1013 | u32 ucode_beacon_time; | 1081 | u32 ucode_beacon_time; |
1082 | int missed_beacon_threshold; | ||
1083 | |||
1084 | /* storing the jiffies when the plcp error rate is received */ | ||
1085 | unsigned long plcp_jiffies; | ||
1086 | |||
1087 | /* reporting the number of tids has AGG on. 0 means no AGGREGATION */ | ||
1088 | u8 agg_tids_count; | ||
1089 | |||
1090 | /* force reset */ | ||
1091 | struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; | ||
1014 | 1092 | ||
1015 | /* we allocate array of iwl4965_channel_info for NIC's valid channels. | 1093 | /* we allocate array of iwl4965_channel_info for NIC's valid channels. |
1016 | * Access via channel # using indirect index array */ | 1094 | * Access via channel # using indirect index array */ |
@@ -1029,7 +1107,6 @@ struct iwl_priv { | |||
1029 | struct iwl_calib_result calib_results[IWL_CALIB_MAX]; | 1107 | struct iwl_calib_result calib_results[IWL_CALIB_MAX]; |
1030 | 1108 | ||
1031 | /* Scan related variables */ | 1109 | /* Scan related variables */ |
1032 | unsigned long last_scan_jiffies; | ||
1033 | unsigned long next_scan_jiffies; | 1110 | unsigned long next_scan_jiffies; |
1034 | unsigned long scan_start; | 1111 | unsigned long scan_start; |
1035 | unsigned long scan_pass_start; | 1112 | unsigned long scan_pass_start; |
@@ -1037,6 +1114,7 @@ struct iwl_priv { | |||
1037 | void *scan; | 1114 | void *scan; |
1038 | int scan_bands; | 1115 | int scan_bands; |
1039 | struct cfg80211_scan_request *scan_request; | 1116 | struct cfg80211_scan_request *scan_request; |
1117 | bool is_internal_short_scan; | ||
1040 | u8 scan_tx_ant[IEEE80211_NUM_BANDS]; | 1118 | u8 scan_tx_ant[IEEE80211_NUM_BANDS]; |
1041 | u8 mgmt_tx_ant; | 1119 | u8 mgmt_tx_ant; |
1042 | 1120 | ||
@@ -1045,6 +1123,7 @@ struct iwl_priv { | |||
1045 | spinlock_t hcmd_lock; /* protect hcmd */ | 1123 | spinlock_t hcmd_lock; /* protect hcmd */ |
1046 | spinlock_t reg_lock; /* protect hw register access */ | 1124 | spinlock_t reg_lock; /* protect hw register access */ |
1047 | struct mutex mutex; | 1125 | struct mutex mutex; |
1126 | struct mutex sync_cmd_mutex; /* enable serialization of sync commands */ | ||
1048 | 1127 | ||
1049 | /* basic pci-network driver stuff */ | 1128 | /* basic pci-network driver stuff */ |
1050 | struct pci_dev *pci_dev; | 1129 | struct pci_dev *pci_dev; |
@@ -1135,6 +1214,8 @@ struct iwl_priv { | |||
1135 | struct iwl_notif_statistics statistics; | 1214 | struct iwl_notif_statistics statistics; |
1136 | #ifdef CONFIG_IWLWIFI_DEBUG | 1215 | #ifdef CONFIG_IWLWIFI_DEBUG |
1137 | struct iwl_notif_statistics accum_statistics; | 1216 | struct iwl_notif_statistics accum_statistics; |
1217 | struct iwl_notif_statistics delta_statistics; | ||
1218 | struct iwl_notif_statistics max_delta; | ||
1138 | #endif | 1219 | #endif |
1139 | 1220 | ||
1140 | /* context information */ | 1221 | /* context information */ |
@@ -1207,15 +1288,10 @@ struct iwl_priv { | |||
1207 | 1288 | ||
1208 | struct workqueue_struct *workqueue; | 1289 | struct workqueue_struct *workqueue; |
1209 | 1290 | ||
1210 | struct work_struct up; | ||
1211 | struct work_struct restart; | 1291 | struct work_struct restart; |
1212 | struct work_struct calibrated_work; | ||
1213 | struct work_struct scan_completed; | 1292 | struct work_struct scan_completed; |
1214 | struct work_struct rx_replenish; | 1293 | struct work_struct rx_replenish; |
1215 | struct work_struct abort_scan; | 1294 | struct work_struct abort_scan; |
1216 | struct work_struct update_link_led; | ||
1217 | struct work_struct auth_work; | ||
1218 | struct work_struct report_work; | ||
1219 | struct work_struct request_scan; | 1295 | struct work_struct request_scan; |
1220 | struct work_struct beacon_update; | 1296 | struct work_struct beacon_update; |
1221 | struct work_struct tt_work; | 1297 | struct work_struct tt_work; |
@@ -1251,7 +1327,8 @@ struct iwl_priv { | |||
1251 | u16 rx_traffic_idx; | 1327 | u16 rx_traffic_idx; |
1252 | u8 *tx_traffic; | 1328 | u8 *tx_traffic; |
1253 | u8 *rx_traffic; | 1329 | u8 *rx_traffic; |
1254 | struct iwl_debugfs *dbgfs; | 1330 | struct dentry *debugfs_dir; |
1331 | u32 dbgfs_sram_offset, dbgfs_sram_len; | ||
1255 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | 1332 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ |
1256 | #endif /* CONFIG_IWLWIFI_DEBUG */ | 1333 | #endif /* CONFIG_IWLWIFI_DEBUG */ |
1257 | 1334 | ||
@@ -1261,6 +1338,7 @@ struct iwl_priv { | |||
1261 | u32 disable_tx_power_cal; | 1338 | u32 disable_tx_power_cal; |
1262 | struct work_struct run_time_calib_work; | 1339 | struct work_struct run_time_calib_work; |
1263 | struct timer_list statistics_periodic; | 1340 | struct timer_list statistics_periodic; |
1341 | struct timer_list ucode_trace; | ||
1264 | bool hw_ready; | 1342 | bool hw_ready; |
1265 | /*For 3945*/ | 1343 | /*For 3945*/ |
1266 | #define IWL_DEFAULT_TX_POWER 0x0F | 1344 | #define IWL_DEFAULT_TX_POWER 0x0F |
@@ -1268,6 +1346,8 @@ struct iwl_priv { | |||
1268 | struct iwl3945_notif_statistics statistics_39; | 1346 | struct iwl3945_notif_statistics statistics_39; |
1269 | 1347 | ||
1270 | u32 sta_supp_rates; | 1348 | u32 sta_supp_rates; |
1349 | |||
1350 | struct iwl_event_log event_log; | ||
1271 | }; /*iwl_priv */ | 1351 | }; /*iwl_priv */ |
1272 | 1352 | ||
1273 | static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) | 1353 | static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.c b/drivers/net/wireless/iwlwifi/iwl-devtrace.c index 83cc4e500a96..36580d8d8b8d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.c +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.c | |||
@@ -37,4 +37,6 @@ EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite32); | |||
37 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_rx); | 37 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_rx); |
38 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event); | 38 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event); |
39 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error); | 39 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error); |
40 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_cont_event); | ||
41 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_wrap_event); | ||
40 | #endif | 42 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index d9c7363b1bbb..ff4d012ce260 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h | |||
@@ -91,6 +91,50 @@ TRACE_EVENT(iwlwifi_dev_iowrite32, | |||
91 | ); | 91 | ); |
92 | 92 | ||
93 | #undef TRACE_SYSTEM | 93 | #undef TRACE_SYSTEM |
94 | #define TRACE_SYSTEM iwlwifi_ucode | ||
95 | |||
96 | TRACE_EVENT(iwlwifi_dev_ucode_cont_event, | ||
97 | TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev), | ||
98 | TP_ARGS(priv, time, data, ev), | ||
99 | TP_STRUCT__entry( | ||
100 | PRIV_ENTRY | ||
101 | |||
102 | __field(u32, time) | ||
103 | __field(u32, data) | ||
104 | __field(u32, ev) | ||
105 | ), | ||
106 | TP_fast_assign( | ||
107 | PRIV_ASSIGN; | ||
108 | __entry->time = time; | ||
109 | __entry->data = data; | ||
110 | __entry->ev = ev; | ||
111 | ), | ||
112 | TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u", | ||
113 | __entry->priv, __entry->time, __entry->data, __entry->ev) | ||
114 | ); | ||
115 | |||
116 | TRACE_EVENT(iwlwifi_dev_ucode_wrap_event, | ||
117 | TP_PROTO(struct iwl_priv *priv, u32 wraps, u32 n_entry, u32 p_entry), | ||
118 | TP_ARGS(priv, wraps, n_entry, p_entry), | ||
119 | TP_STRUCT__entry( | ||
120 | PRIV_ENTRY | ||
121 | |||
122 | __field(u32, wraps) | ||
123 | __field(u32, n_entry) | ||
124 | __field(u32, p_entry) | ||
125 | ), | ||
126 | TP_fast_assign( | ||
127 | PRIV_ASSIGN; | ||
128 | __entry->wraps = wraps; | ||
129 | __entry->n_entry = n_entry; | ||
130 | __entry->p_entry = p_entry; | ||
131 | ), | ||
132 | TP_printk("[%p] wraps=#%02d n=0x%X p=0x%X", | ||
133 | __entry->priv, __entry->wraps, __entry->n_entry, | ||
134 | __entry->p_entry) | ||
135 | ); | ||
136 | |||
137 | #undef TRACE_SYSTEM | ||
94 | #define TRACE_SYSTEM iwlwifi | 138 | #define TRACE_SYSTEM iwlwifi |
95 | 139 | ||
96 | TRACE_EVENT(iwlwifi_dev_hcmd, | 140 | TRACE_EVENT(iwlwifi_dev_hcmd, |
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 30e9ea6d54ec..73681c4fefe7 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 |
@@ -58,7 +58,6 @@ const char *get_cmd_string(u8 cmd) | |||
58 | IWL_CMD(COEX_PRIORITY_TABLE_CMD); | 58 | IWL_CMD(COEX_PRIORITY_TABLE_CMD); |
59 | IWL_CMD(COEX_MEDIUM_NOTIFICATION); | 59 | IWL_CMD(COEX_MEDIUM_NOTIFICATION); |
60 | IWL_CMD(COEX_EVENT_CMD); | 60 | IWL_CMD(COEX_EVENT_CMD); |
61 | IWL_CMD(RADAR_NOTIFICATION); | ||
62 | IWL_CMD(REPLY_QUIET_CMD); | 61 | IWL_CMD(REPLY_QUIET_CMD); |
63 | IWL_CMD(REPLY_CHANNEL_SWITCH); | 62 | IWL_CMD(REPLY_CHANNEL_SWITCH); |
64 | IWL_CMD(CHANNEL_SWITCH_NOTIFICATION); | 63 | IWL_CMD(CHANNEL_SWITCH_NOTIFICATION); |
@@ -165,15 +164,13 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
165 | /* A synchronous command can not have a callback set. */ | 164 | /* A synchronous command can not have a callback set. */ |
166 | BUG_ON(cmd->callback); | 165 | BUG_ON(cmd->callback); |
167 | 166 | ||
168 | if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) { | 167 | IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n", |
169 | IWL_ERR(priv, | ||
170 | "Error sending %s: Already sending a host command\n", | ||
171 | get_cmd_string(cmd->id)); | 168 | get_cmd_string(cmd->id)); |
172 | ret = -EBUSY; | 169 | mutex_lock(&priv->sync_cmd_mutex); |
173 | goto out; | ||
174 | } | ||
175 | 170 | ||
176 | set_bit(STATUS_HCMD_ACTIVE, &priv->status); | 171 | set_bit(STATUS_HCMD_ACTIVE, &priv->status); |
172 | IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s \n", | ||
173 | get_cmd_string(cmd->id)); | ||
177 | 174 | ||
178 | cmd_idx = iwl_enqueue_hcmd(priv, cmd); | 175 | cmd_idx = iwl_enqueue_hcmd(priv, cmd); |
179 | if (cmd_idx < 0) { | 176 | if (cmd_idx < 0) { |
@@ -194,6 +191,8 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
194 | jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); | 191 | jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); |
195 | 192 | ||
196 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | 193 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); |
194 | IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n", | ||
195 | get_cmd_string(cmd->id)); | ||
197 | ret = -ETIMEDOUT; | 196 | ret = -ETIMEDOUT; |
198 | goto cancel; | 197 | goto cancel; |
199 | } | 198 | } |
@@ -238,7 +237,7 @@ fail: | |||
238 | cmd->reply_page = 0; | 237 | cmd->reply_page = 0; |
239 | } | 238 | } |
240 | out: | 239 | out: |
241 | clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status); | 240 | mutex_unlock(&priv->sync_cmd_mutex); |
242 | return ret; | 241 | return ret; |
243 | } | 242 | } |
244 | EXPORT_SYMBOL(iwl_send_cmd_sync); | 243 | EXPORT_SYMBOL(iwl_send_cmd_sync); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index bd0b12efb5c7..51a67fb2e185 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. |
@@ -80,8 +80,8 @@ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev, | |||
80 | struct fw_desc *desc) | 80 | struct fw_desc *desc) |
81 | { | 81 | { |
82 | if (desc->v_addr) | 82 | if (desc->v_addr) |
83 | pci_free_consistent(pci_dev, desc->len, | 83 | dma_free_coherent(&pci_dev->dev, desc->len, |
84 | desc->v_addr, desc->p_addr); | 84 | desc->v_addr, desc->p_addr); |
85 | desc->v_addr = NULL; | 85 | desc->v_addr = NULL; |
86 | desc->len = 0; | 86 | desc->len = 0; |
87 | } | 87 | } |
@@ -89,7 +89,8 @@ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev, | |||
89 | static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev, | 89 | static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev, |
90 | struct fw_desc *desc) | 90 | struct fw_desc *desc) |
91 | { | 91 | { |
92 | desc->v_addr = pci_alloc_consistent(pci_dev, desc->len, &desc->p_addr); | 92 | desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len, |
93 | &desc->p_addr, GFP_KERNEL); | ||
93 | return (desc->v_addr != NULL) ? 0 : -ENOMEM; | 94 | return (desc->v_addr != NULL) ? 0 : -ENOMEM; |
94 | } | 95 | } |
95 | 96 | ||
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 2dbce85404aa..0d09f571e185 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. |
@@ -123,12 +123,11 @@ EXPORT_SYMBOL(iwl_rx_queue_space); | |||
123 | /** | 123 | /** |
124 | * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue | 124 | * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue |
125 | */ | 125 | */ |
126 | int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) | 126 | void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) |
127 | { | 127 | { |
128 | unsigned long flags; | 128 | unsigned long flags; |
129 | u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg; | 129 | u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg; |
130 | u32 reg; | 130 | u32 reg; |
131 | int ret = 0; | ||
132 | 131 | ||
133 | spin_lock_irqsave(&q->lock, flags); | 132 | spin_lock_irqsave(&q->lock, flags); |
134 | 133 | ||
@@ -161,7 +160,6 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) | |||
161 | 160 | ||
162 | exit_unlock: | 161 | exit_unlock: |
163 | spin_unlock_irqrestore(&q->lock, flags); | 162 | spin_unlock_irqrestore(&q->lock, flags); |
164 | return ret; | ||
165 | } | 163 | } |
166 | EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr); | 164 | EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr); |
167 | /** | 165 | /** |
@@ -184,14 +182,13 @@ static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv, | |||
184 | * also updates the memory address in the firmware to reference the new | 182 | * also updates the memory address in the firmware to reference the new |
185 | * target buffer. | 183 | * target buffer. |
186 | */ | 184 | */ |
187 | int iwl_rx_queue_restock(struct iwl_priv *priv) | 185 | void iwl_rx_queue_restock(struct iwl_priv *priv) |
188 | { | 186 | { |
189 | struct iwl_rx_queue *rxq = &priv->rxq; | 187 | struct iwl_rx_queue *rxq = &priv->rxq; |
190 | struct list_head *element; | 188 | struct list_head *element; |
191 | struct iwl_rx_mem_buffer *rxb; | 189 | struct iwl_rx_mem_buffer *rxb; |
192 | unsigned long flags; | 190 | unsigned long flags; |
193 | int write; | 191 | int write; |
194 | int ret = 0; | ||
195 | 192 | ||
196 | spin_lock_irqsave(&rxq->lock, flags); | 193 | spin_lock_irqsave(&rxq->lock, flags); |
197 | write = rxq->write & ~0x7; | 194 | write = rxq->write & ~0x7; |
@@ -220,10 +217,8 @@ int iwl_rx_queue_restock(struct iwl_priv *priv) | |||
220 | spin_lock_irqsave(&rxq->lock, flags); | 217 | spin_lock_irqsave(&rxq->lock, flags); |
221 | rxq->need_update = 1; | 218 | rxq->need_update = 1; |
222 | spin_unlock_irqrestore(&rxq->lock, flags); | 219 | spin_unlock_irqrestore(&rxq->lock, flags); |
223 | ret = iwl_rx_queue_update_write_ptr(priv, rxq); | 220 | iwl_rx_queue_update_write_ptr(priv, rxq); |
224 | } | 221 | } |
225 | |||
226 | return ret; | ||
227 | } | 222 | } |
228 | EXPORT_SYMBOL(iwl_rx_queue_restock); | 223 | EXPORT_SYMBOL(iwl_rx_queue_restock); |
229 | 224 | ||
@@ -350,10 +345,10 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
350 | } | 345 | } |
351 | } | 346 | } |
352 | 347 | ||
353 | pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd, | 348 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, |
354 | rxq->dma_addr); | 349 | rxq->dma_addr); |
355 | pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status), | 350 | dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), |
356 | rxq->rb_stts, rxq->rb_stts_dma); | 351 | rxq->rb_stts, rxq->rb_stts_dma); |
357 | rxq->bd = NULL; | 352 | rxq->bd = NULL; |
358 | rxq->rb_stts = NULL; | 353 | rxq->rb_stts = NULL; |
359 | } | 354 | } |
@@ -362,7 +357,7 @@ EXPORT_SYMBOL(iwl_rx_queue_free); | |||
362 | int iwl_rx_queue_alloc(struct iwl_priv *priv) | 357 | int iwl_rx_queue_alloc(struct iwl_priv *priv) |
363 | { | 358 | { |
364 | struct iwl_rx_queue *rxq = &priv->rxq; | 359 | struct iwl_rx_queue *rxq = &priv->rxq; |
365 | struct pci_dev *dev = priv->pci_dev; | 360 | struct device *dev = &priv->pci_dev->dev; |
366 | int i; | 361 | int i; |
367 | 362 | ||
368 | spin_lock_init(&rxq->lock); | 363 | spin_lock_init(&rxq->lock); |
@@ -370,12 +365,13 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) | |||
370 | INIT_LIST_HEAD(&rxq->rx_used); | 365 | INIT_LIST_HEAD(&rxq->rx_used); |
371 | 366 | ||
372 | /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ | 367 | /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ |
373 | rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr); | 368 | rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr, |
369 | GFP_KERNEL); | ||
374 | if (!rxq->bd) | 370 | if (!rxq->bd) |
375 | goto err_bd; | 371 | goto err_bd; |
376 | 372 | ||
377 | rxq->rb_stts = pci_alloc_consistent(dev, sizeof(struct iwl_rb_status), | 373 | rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct iwl_rb_status), |
378 | &rxq->rb_stts_dma); | 374 | &rxq->rb_stts_dma, GFP_KERNEL); |
379 | if (!rxq->rb_stts) | 375 | if (!rxq->rb_stts) |
380 | goto err_rb; | 376 | goto err_rb; |
381 | 377 | ||
@@ -392,8 +388,8 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) | |||
392 | return 0; | 388 | return 0; |
393 | 389 | ||
394 | err_rb: | 390 | err_rb: |
395 | pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd, | 391 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, |
396 | rxq->dma_addr); | 392 | rxq->dma_addr); |
397 | err_bd: | 393 | err_bd: |
398 | return -ENOMEM; | 394 | return -ENOMEM; |
399 | } | 395 | } |
@@ -473,8 +469,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)| | 469 | (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| |
474 | (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); | 470 | (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); |
475 | 471 | ||
476 | /* Set interrupt coalescing timer to 64 x 32 = 2048 usecs */ | 472 | /* Set interrupt coalescing timer to default (2048 usecs) */ |
477 | iwl_write8(priv, CSR_INT_COALESCING, 0x40); | 473 | iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); |
478 | 474 | ||
479 | return 0; | 475 | return 0; |
480 | } | 476 | } |
@@ -499,9 +495,10 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | |||
499 | struct iwl_missed_beacon_notif *missed_beacon; | 495 | struct iwl_missed_beacon_notif *missed_beacon; |
500 | 496 | ||
501 | missed_beacon = &pkt->u.missed_beacon; | 497 | missed_beacon = &pkt->u.missed_beacon; |
502 | if (le32_to_cpu(missed_beacon->consequtive_missed_beacons) > 5) { | 498 | if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) > |
499 | priv->missed_beacon_threshold) { | ||
503 | IWL_DEBUG_CALIB(priv, "missed bcn cnsq %d totl %d rcd %d expctd %d\n", | 500 | IWL_DEBUG_CALIB(priv, "missed bcn cnsq %d totl %d rcd %d expctd %d\n", |
504 | le32_to_cpu(missed_beacon->consequtive_missed_beacons), | 501 | le32_to_cpu(missed_beacon->consecutive_missed_beacons), |
505 | le32_to_cpu(missed_beacon->total_missed_becons), | 502 | le32_to_cpu(missed_beacon->total_missed_becons), |
506 | le32_to_cpu(missed_beacon->num_recvd_beacons), | 503 | le32_to_cpu(missed_beacon->num_recvd_beacons), |
507 | le32_to_cpu(missed_beacon->num_expected_beacons)); | 504 | le32_to_cpu(missed_beacon->num_expected_beacons)); |
@@ -511,6 +508,24 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | |||
511 | } | 508 | } |
512 | EXPORT_SYMBOL(iwl_rx_missed_beacon_notif); | 509 | EXPORT_SYMBOL(iwl_rx_missed_beacon_notif); |
513 | 510 | ||
511 | void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | ||
512 | struct iwl_rx_mem_buffer *rxb) | ||
513 | { | ||
514 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
515 | struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif); | ||
516 | |||
517 | if (!report->state) { | ||
518 | IWL_DEBUG_11H(priv, | ||
519 | "Spectrum Measure Notification: Start\n"); | ||
520 | return; | ||
521 | } | ||
522 | |||
523 | memcpy(&priv->measure_report, report, sizeof(*report)); | ||
524 | priv->measurement_status |= MEASUREMENT_READY; | ||
525 | } | ||
526 | EXPORT_SYMBOL(iwl_rx_spectrum_measure_notif); | ||
527 | |||
528 | |||
514 | 529 | ||
515 | /* Calculate noise level, based on measurements during network silence just | 530 | /* Calculate noise level, based on measurements during network silence just |
516 | * before arriving beacon. This measurement can be done only if we know | 531 | * before arriving beacon. This measurement can be done only if we know |
@@ -564,15 +579,24 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, | |||
564 | int i; | 579 | int i; |
565 | __le32 *prev_stats; | 580 | __le32 *prev_stats; |
566 | u32 *accum_stats; | 581 | u32 *accum_stats; |
582 | u32 *delta, *max_delta; | ||
567 | 583 | ||
568 | prev_stats = (__le32 *)&priv->statistics; | 584 | prev_stats = (__le32 *)&priv->statistics; |
569 | accum_stats = (u32 *)&priv->accum_statistics; | 585 | accum_stats = (u32 *)&priv->accum_statistics; |
586 | delta = (u32 *)&priv->delta_statistics; | ||
587 | max_delta = (u32 *)&priv->max_delta; | ||
570 | 588 | ||
571 | for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics); | 589 | for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics); |
572 | i += sizeof(__le32), stats++, prev_stats++, accum_stats++) | 590 | i += sizeof(__le32), stats++, prev_stats++, delta++, |
573 | if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) | 591 | max_delta++, accum_stats++) { |
574 | *accum_stats += (le32_to_cpu(*stats) - | 592 | if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) { |
593 | *delta = (le32_to_cpu(*stats) - | ||
575 | le32_to_cpu(*prev_stats)); | 594 | le32_to_cpu(*prev_stats)); |
595 | *accum_stats += *delta; | ||
596 | if (*delta > *max_delta) | ||
597 | *max_delta = *delta; | ||
598 | } | ||
599 | } | ||
576 | 600 | ||
577 | /* reset accumulative statistics for "no-counter" type statistics */ | 601 | /* reset accumulative statistics for "no-counter" type statistics */ |
578 | priv->accum_statistics.general.temperature = | 602 | priv->accum_statistics.general.temperature = |
@@ -592,11 +616,23 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, | |||
592 | 616 | ||
593 | #define REG_RECALIB_PERIOD (60) | 617 | #define REG_RECALIB_PERIOD (60) |
594 | 618 | ||
619 | /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ | ||
620 | #define ACK_CNT_RATIO (50) | ||
621 | #define BA_TIMEOUT_CNT (5) | ||
622 | #define BA_TIMEOUT_MAX (16) | ||
623 | |||
624 | #define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n" | ||
595 | void iwl_rx_statistics(struct iwl_priv *priv, | 625 | void iwl_rx_statistics(struct iwl_priv *priv, |
596 | struct iwl_rx_mem_buffer *rxb) | 626 | struct iwl_rx_mem_buffer *rxb) |
597 | { | 627 | { |
598 | int change; | 628 | int change; |
599 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 629 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
630 | int combined_plcp_delta; | ||
631 | unsigned int plcp_msec; | ||
632 | unsigned long plcp_received_jiffies; | ||
633 | int actual_ack_cnt_delta; | ||
634 | int expected_ack_cnt_delta; | ||
635 | int ba_timeout_delta; | ||
600 | 636 | ||
601 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", | 637 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", |
602 | (int)sizeof(priv->statistics), | 638 | (int)sizeof(priv->statistics), |
@@ -611,6 +647,94 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
611 | #ifdef CONFIG_IWLWIFI_DEBUG | 647 | #ifdef CONFIG_IWLWIFI_DEBUG |
612 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); | 648 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); |
613 | #endif | 649 | #endif |
650 | actual_ack_cnt_delta = le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) - | ||
651 | le32_to_cpu(priv->statistics.tx.actual_ack_cnt); | ||
652 | expected_ack_cnt_delta = le32_to_cpu( | ||
653 | pkt->u.stats.tx.expected_ack_cnt) - | ||
654 | le32_to_cpu(priv->statistics.tx.expected_ack_cnt); | ||
655 | ba_timeout_delta = le32_to_cpu( | ||
656 | pkt->u.stats.tx.agg.ba_timeout) - | ||
657 | le32_to_cpu(priv->statistics.tx.agg.ba_timeout); | ||
658 | if ((priv->agg_tids_count > 0) && | ||
659 | (expected_ack_cnt_delta > 0) && | ||
660 | (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta) < | ||
661 | ACK_CNT_RATIO) && | ||
662 | (ba_timeout_delta > BA_TIMEOUT_CNT)) { | ||
663 | IWL_DEBUG_RADIO(priv, | ||
664 | "actual_ack_cnt delta = %d, expected_ack_cnt = %d\n", | ||
665 | actual_ack_cnt_delta, expected_ack_cnt_delta); | ||
666 | |||
667 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
668 | IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n", | ||
669 | priv->delta_statistics.tx.rx_detected_cnt); | ||
670 | IWL_DEBUG_RADIO(priv, | ||
671 | "ack_or_ba_timeout_collision delta = %d\n", | ||
672 | priv->delta_statistics.tx.ack_or_ba_timeout_collision); | ||
673 | #endif | ||
674 | IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n", | ||
675 | ba_timeout_delta); | ||
676 | if ((actual_ack_cnt_delta == 0) && | ||
677 | (ba_timeout_delta >= | ||
678 | BA_TIMEOUT_MAX)) { | ||
679 | IWL_DEBUG_RADIO(priv, | ||
680 | "call iwl_force_reset(IWL_FW_RESET)\n"); | ||
681 | iwl_force_reset(priv, IWL_FW_RESET); | ||
682 | } else { | ||
683 | IWL_DEBUG_RADIO(priv, | ||
684 | "call iwl_force_reset(IWL_RF_RESET)\n"); | ||
685 | iwl_force_reset(priv, IWL_RF_RESET); | ||
686 | } | ||
687 | } | ||
688 | /* | ||
689 | * check for plcp_err and trigger radio reset if it exceeds | ||
690 | * the plcp error threshold plcp_delta. | ||
691 | */ | ||
692 | plcp_received_jiffies = jiffies; | ||
693 | plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies - | ||
694 | (long) priv->plcp_jiffies); | ||
695 | priv->plcp_jiffies = plcp_received_jiffies; | ||
696 | /* | ||
697 | * check to make sure plcp_msec is not 0 to prevent division | ||
698 | * by zero. | ||
699 | */ | ||
700 | if (plcp_msec) { | ||
701 | combined_plcp_delta = | ||
702 | (le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err) - | ||
703 | le32_to_cpu(priv->statistics.rx.ofdm.plcp_err)) + | ||
704 | (le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err) - | ||
705 | le32_to_cpu(priv->statistics.rx.ofdm_ht.plcp_err)); | ||
706 | |||
707 | if ((combined_plcp_delta > 0) && | ||
708 | ((combined_plcp_delta * 100) / plcp_msec) > | ||
709 | priv->cfg->plcp_delta_threshold) { | ||
710 | /* | ||
711 | * if plcp_err exceed the threshold, the following | ||
712 | * data is printed in csv format: | ||
713 | * Text: plcp_err exceeded %d, | ||
714 | * Received ofdm.plcp_err, | ||
715 | * Current ofdm.plcp_err, | ||
716 | * Received ofdm_ht.plcp_err, | ||
717 | * Current ofdm_ht.plcp_err, | ||
718 | * combined_plcp_delta, | ||
719 | * plcp_msec | ||
720 | */ | ||
721 | IWL_DEBUG_RADIO(priv, PLCP_MSG, | ||
722 | priv->cfg->plcp_delta_threshold, | ||
723 | le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err), | ||
724 | le32_to_cpu(priv->statistics.rx.ofdm.plcp_err), | ||
725 | le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err), | ||
726 | le32_to_cpu( | ||
727 | priv->statistics.rx.ofdm_ht.plcp_err), | ||
728 | combined_plcp_delta, plcp_msec); | ||
729 | |||
730 | /* | ||
731 | * Reset the RF radio due to the high plcp | ||
732 | * error rate | ||
733 | */ | ||
734 | iwl_force_reset(priv, IWL_RF_RESET); | ||
735 | } | ||
736 | } | ||
737 | |||
614 | memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); | 738 | memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); |
615 | 739 | ||
616 | set_bit(STATUS_STATISTICS, &priv->status); | 740 | set_bit(STATUS_STATISTICS, &priv->status); |
@@ -638,11 +762,13 @@ void iwl_reply_statistics(struct iwl_priv *priv, | |||
638 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 762 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
639 | 763 | ||
640 | if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) { | 764 | 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 | 765 | #ifdef CONFIG_IWLWIFI_DEBUG |
644 | memset(&priv->accum_statistics, 0, | 766 | memset(&priv->accum_statistics, 0, |
645 | sizeof(struct iwl_notif_statistics)); | 767 | sizeof(struct iwl_notif_statistics)); |
768 | memset(&priv->delta_statistics, 0, | ||
769 | sizeof(struct iwl_notif_statistics)); | ||
770 | memset(&priv->max_delta, 0, | ||
771 | sizeof(struct iwl_notif_statistics)); | ||
646 | #endif | 772 | #endif |
647 | IWL_DEBUG_RX(priv, "Statistics have been cleared\n"); | 773 | IWL_DEBUG_RX(priv, "Statistics have been cleared\n"); |
648 | } | 774 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index fa1c89ba6459..dd9ff2ed645a 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,9 @@ 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 | |||
255 | IWL_DEBUG_INFO(priv, "Setting scan to off\n"); | 254 | IWL_DEBUG_INFO(priv, "Setting scan to off\n"); |
256 | 255 | ||
257 | clear_bit(STATUS_SCANNING, &priv->status); | 256 | clear_bit(STATUS_SCANNING, &priv->status); |
@@ -314,6 +313,72 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | |||
314 | } | 313 | } |
315 | EXPORT_SYMBOL(iwl_get_passive_dwell_time); | 314 | EXPORT_SYMBOL(iwl_get_passive_dwell_time); |
316 | 315 | ||
316 | static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, | ||
317 | enum ieee80211_band band, | ||
318 | struct iwl_scan_channel *scan_ch) | ||
319 | { | ||
320 | const struct ieee80211_supported_band *sband; | ||
321 | const struct iwl_channel_info *ch_info; | ||
322 | u16 passive_dwell = 0; | ||
323 | u16 active_dwell = 0; | ||
324 | int i, added = 0; | ||
325 | u16 channel = 0; | ||
326 | |||
327 | sband = iwl_get_hw_mode(priv, band); | ||
328 | if (!sband) { | ||
329 | IWL_ERR(priv, "invalid band\n"); | ||
330 | return added; | ||
331 | } | ||
332 | |||
333 | active_dwell = iwl_get_active_dwell_time(priv, band, 0); | ||
334 | passive_dwell = iwl_get_passive_dwell_time(priv, band); | ||
335 | |||
336 | if (passive_dwell <= active_dwell) | ||
337 | passive_dwell = active_dwell + 1; | ||
338 | |||
339 | /* only scan single channel, good enough to reset the RF */ | ||
340 | /* pick the first valid not in-use channel */ | ||
341 | if (band == IEEE80211_BAND_5GHZ) { | ||
342 | for (i = 14; i < priv->channel_count; i++) { | ||
343 | if (priv->channel_info[i].channel != | ||
344 | le16_to_cpu(priv->staging_rxon.channel)) { | ||
345 | channel = priv->channel_info[i].channel; | ||
346 | ch_info = iwl_get_channel_info(priv, | ||
347 | band, channel); | ||
348 | if (is_channel_valid(ch_info)) | ||
349 | break; | ||
350 | } | ||
351 | } | ||
352 | } else { | ||
353 | for (i = 0; i < 14; i++) { | ||
354 | if (priv->channel_info[i].channel != | ||
355 | le16_to_cpu(priv->staging_rxon.channel)) { | ||
356 | channel = | ||
357 | priv->channel_info[i].channel; | ||
358 | ch_info = iwl_get_channel_info(priv, | ||
359 | band, channel); | ||
360 | if (is_channel_valid(ch_info)) | ||
361 | break; | ||
362 | } | ||
363 | } | ||
364 | } | ||
365 | if (channel) { | ||
366 | scan_ch->channel = cpu_to_le16(channel); | ||
367 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; | ||
368 | scan_ch->active_dwell = cpu_to_le16(active_dwell); | ||
369 | scan_ch->passive_dwell = cpu_to_le16(passive_dwell); | ||
370 | /* Set txpower levels to defaults */ | ||
371 | scan_ch->dsp_atten = 110; | ||
372 | if (band == IEEE80211_BAND_5GHZ) | ||
373 | scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; | ||
374 | else | ||
375 | scan_ch->tx_gain = ((1 << 5) | (5 << 3)); | ||
376 | added++; | ||
377 | } else | ||
378 | IWL_ERR(priv, "no valid channel found\n"); | ||
379 | return added; | ||
380 | } | ||
381 | |||
317 | static int iwl_get_channels_for_scan(struct iwl_priv *priv, | 382 | static int iwl_get_channels_for_scan(struct iwl_priv *priv, |
318 | enum ieee80211_band band, | 383 | enum ieee80211_band band, |
319 | u8 is_active, u8 n_probes, | 384 | u8 is_active, u8 n_probes, |
@@ -404,23 +469,9 @@ EXPORT_SYMBOL(iwl_init_scan_params); | |||
404 | 469 | ||
405 | static int iwl_scan_initiate(struct iwl_priv *priv) | 470 | static int iwl_scan_initiate(struct iwl_priv *priv) |
406 | { | 471 | { |
407 | if (!iwl_is_ready_rf(priv)) { | ||
408 | IWL_DEBUG_SCAN(priv, "Aborting scan due to not ready.\n"); | ||
409 | return -EIO; | ||
410 | } | ||
411 | |||
412 | if (test_bit(STATUS_SCANNING, &priv->status)) { | ||
413 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); | ||
414 | return -EAGAIN; | ||
415 | } | ||
416 | |||
417 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
418 | IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); | ||
419 | return -EAGAIN; | ||
420 | } | ||
421 | |||
422 | IWL_DEBUG_INFO(priv, "Starting scan...\n"); | 472 | IWL_DEBUG_INFO(priv, "Starting scan...\n"); |
423 | set_bit(STATUS_SCANNING, &priv->status); | 473 | set_bit(STATUS_SCANNING, &priv->status); |
474 | priv->is_internal_short_scan = false; | ||
424 | priv->scan_start = jiffies; | 475 | priv->scan_start = jiffies; |
425 | priv->scan_pass_start = priv->scan_start; | 476 | priv->scan_pass_start = priv->scan_start; |
426 | 477 | ||
@@ -449,6 +500,18 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, | |||
449 | goto out_unlock; | 500 | goto out_unlock; |
450 | } | 501 | } |
451 | 502 | ||
503 | if (test_bit(STATUS_SCANNING, &priv->status)) { | ||
504 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); | ||
505 | ret = -EAGAIN; | ||
506 | goto out_unlock; | ||
507 | } | ||
508 | |||
509 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
510 | IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); | ||
511 | ret = -EAGAIN; | ||
512 | goto out_unlock; | ||
513 | } | ||
514 | |||
452 | /* We don't schedule scan within next_scan_jiffies period. | 515 | /* We don't schedule scan within next_scan_jiffies period. |
453 | * Avoid scanning during possible EAPOL exchange, return | 516 | * Avoid scanning during possible EAPOL exchange, return |
454 | * success immediately. | 517 | * success immediately. |
@@ -461,15 +524,6 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, | |||
461 | goto out_unlock; | 524 | goto out_unlock; |
462 | } | 525 | } |
463 | 526 | ||
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; | 527 | priv->scan_bands = 0; |
474 | for (i = 0; i < req->n_channels; i++) | 528 | for (i = 0; i < req->n_channels; i++) |
475 | priv->scan_bands |= BIT(req->channels[i]->band); | 529 | priv->scan_bands |= BIT(req->channels[i]->band); |
@@ -488,6 +542,46 @@ out_unlock: | |||
488 | } | 542 | } |
489 | EXPORT_SYMBOL(iwl_mac_hw_scan); | 543 | EXPORT_SYMBOL(iwl_mac_hw_scan); |
490 | 544 | ||
545 | /* | ||
546 | * internal short scan, this function should only been called while associated. | ||
547 | * It will reset and tune the radio to prevent possible RF related problem | ||
548 | */ | ||
549 | int iwl_internal_short_hw_scan(struct iwl_priv *priv) | ||
550 | { | ||
551 | int ret = 0; | ||
552 | |||
553 | if (!iwl_is_ready_rf(priv)) { | ||
554 | ret = -EIO; | ||
555 | IWL_DEBUG_SCAN(priv, "not ready or exit pending\n"); | ||
556 | goto out; | ||
557 | } | ||
558 | if (test_bit(STATUS_SCANNING, &priv->status)) { | ||
559 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); | ||
560 | ret = -EAGAIN; | ||
561 | goto out; | ||
562 | } | ||
563 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
564 | IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); | ||
565 | ret = -EAGAIN; | ||
566 | goto out; | ||
567 | } | ||
568 | |||
569 | priv->scan_bands = 0; | ||
570 | if (priv->band == IEEE80211_BAND_5GHZ) | ||
571 | priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ); | ||
572 | else | ||
573 | priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ); | ||
574 | |||
575 | IWL_DEBUG_SCAN(priv, "Start internal short scan...\n"); | ||
576 | set_bit(STATUS_SCANNING, &priv->status); | ||
577 | priv->is_internal_short_scan = true; | ||
578 | queue_work(priv->workqueue, &priv->request_scan); | ||
579 | |||
580 | out: | ||
581 | return ret; | ||
582 | } | ||
583 | EXPORT_SYMBOL(iwl_internal_short_hw_scan); | ||
584 | |||
491 | #define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) | 585 | #define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) |
492 | 586 | ||
493 | void iwl_bg_scan_check(struct work_struct *data) | 587 | void iwl_bg_scan_check(struct work_struct *data) |
@@ -544,14 +638,26 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, | |||
544 | if (left < 0) | 638 | if (left < 0) |
545 | return 0; | 639 | return 0; |
546 | *pos++ = WLAN_EID_SSID; | 640 | *pos++ = WLAN_EID_SSID; |
547 | *pos++ = 0; | 641 | if (!priv->is_internal_short_scan && |
548 | 642 | priv->scan_request->n_ssids) { | |
549 | len += 2; | 643 | struct cfg80211_ssid *ssid = |
644 | priv->scan_request->ssids; | ||
645 | |||
646 | /* Broadcast if ssid_len is 0 */ | ||
647 | *pos++ = ssid->ssid_len; | ||
648 | memcpy(pos, ssid->ssid, ssid->ssid_len); | ||
649 | pos += ssid->ssid_len; | ||
650 | len += 2 + ssid->ssid_len; | ||
651 | } else { | ||
652 | *pos++ = 0; | ||
653 | len += 2; | ||
654 | } | ||
550 | 655 | ||
551 | if (WARN_ON(left < ie_len)) | 656 | if (WARN_ON(left < ie_len)) |
552 | return len; | 657 | return len; |
553 | 658 | ||
554 | memcpy(pos, ies, ie_len); | 659 | if (ies) |
660 | memcpy(pos, ies, ie_len); | ||
555 | len += ie_len; | 661 | len += ie_len; |
556 | left -= ie_len; | 662 | left -= ie_len; |
557 | 663 | ||
@@ -654,7 +760,6 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
654 | unsigned long flags; | 760 | unsigned long flags; |
655 | 761 | ||
656 | IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); | 762 | IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); |
657 | |||
658 | spin_lock_irqsave(&priv->lock, flags); | 763 | spin_lock_irqsave(&priv->lock, flags); |
659 | interval = priv->beacon_int; | 764 | interval = priv->beacon_int; |
660 | spin_unlock_irqrestore(&priv->lock, flags); | 765 | spin_unlock_irqrestore(&priv->lock, flags); |
@@ -672,21 +777,29 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
672 | scan_suspend_time, interval); | 777 | scan_suspend_time, interval); |
673 | } | 778 | } |
674 | 779 | ||
675 | if (priv->scan_request->n_ssids) { | 780 | if (priv->is_internal_short_scan) { |
676 | int i, p = 0; | 781 | IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); |
782 | } else if (priv->scan_request->n_ssids) { | ||
677 | IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); | 783 | IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); |
678 | for (i = 0; i < priv->scan_request->n_ssids; i++) { | 784 | /* |
679 | /* always does wildcard anyway */ | 785 | * The first SSID to scan is stuffed into the probe request |
680 | if (!priv->scan_request->ssids[i].ssid_len) | 786 | * template and the remaining ones are handled through the |
681 | continue; | 787 | * direct_scan array. |
682 | scan->direct_scan[p].id = WLAN_EID_SSID; | 788 | */ |
683 | scan->direct_scan[p].len = | 789 | if (priv->scan_request->n_ssids > 1) { |
684 | priv->scan_request->ssids[i].ssid_len; | 790 | int i, p = 0; |
685 | memcpy(scan->direct_scan[p].ssid, | 791 | for (i = 1; i < priv->scan_request->n_ssids; i++) { |
686 | priv->scan_request->ssids[i].ssid, | 792 | if (!priv->scan_request->ssids[i].ssid_len) |
687 | priv->scan_request->ssids[i].ssid_len); | 793 | continue; |
688 | n_probes++; | 794 | scan->direct_scan[p].id = WLAN_EID_SSID; |
689 | p++; | 795 | scan->direct_scan[p].len = |
796 | priv->scan_request->ssids[i].ssid_len; | ||
797 | memcpy(scan->direct_scan[p].ssid, | ||
798 | priv->scan_request->ssids[i].ssid, | ||
799 | priv->scan_request->ssids[i].ssid_len); | ||
800 | n_probes++; | ||
801 | p++; | ||
802 | } | ||
690 | } | 803 | } |
691 | is_active = true; | 804 | is_active = true; |
692 | } else | 805 | } else |
@@ -753,24 +866,38 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
753 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; | 866 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; |
754 | rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; | 867 | rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; |
755 | scan->rx_chain = cpu_to_le16(rx_chain); | 868 | scan->rx_chain = cpu_to_le16(rx_chain); |
756 | cmd_len = iwl_fill_probe_req(priv, | 869 | if (!priv->is_internal_short_scan) { |
757 | (struct ieee80211_mgmt *)scan->data, | 870 | cmd_len = iwl_fill_probe_req(priv, |
758 | priv->scan_request->ie, | 871 | (struct ieee80211_mgmt *)scan->data, |
759 | priv->scan_request->ie_len, | 872 | priv->scan_request->ie, |
760 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | 873 | priv->scan_request->ie_len, |
874 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | ||
875 | } else { | ||
876 | cmd_len = iwl_fill_probe_req(priv, | ||
877 | (struct ieee80211_mgmt *)scan->data, | ||
878 | NULL, 0, | ||
879 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | ||
761 | 880 | ||
881 | } | ||
762 | scan->tx_cmd.len = cpu_to_le16(cmd_len); | 882 | scan->tx_cmd.len = cpu_to_le16(cmd_len); |
763 | |||
764 | if (iwl_is_monitor_mode(priv)) | 883 | if (iwl_is_monitor_mode(priv)) |
765 | scan->filter_flags = RXON_FILTER_PROMISC_MSK; | 884 | scan->filter_flags = RXON_FILTER_PROMISC_MSK; |
766 | 885 | ||
767 | scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | | 886 | scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | |
768 | RXON_FILTER_BCON_AWARE_MSK); | 887 | RXON_FILTER_BCON_AWARE_MSK); |
769 | 888 | ||
770 | scan->channel_count = | 889 | if (priv->is_internal_short_scan) { |
771 | iwl_get_channels_for_scan(priv, band, is_active, n_probes, | 890 | scan->channel_count = |
772 | (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); | 891 | iwl_get_single_channel_for_scan(priv, band, |
773 | 892 | (void *)&scan->data[le16_to_cpu( | |
893 | scan->tx_cmd.len)]); | ||
894 | } else { | ||
895 | scan->channel_count = | ||
896 | iwl_get_channels_for_scan(priv, band, | ||
897 | is_active, n_probes, | ||
898 | (void *)&scan->data[le16_to_cpu( | ||
899 | scan->tx_cmd.len)]); | ||
900 | } | ||
774 | if (scan->channel_count == 0) { | 901 | if (scan->channel_count == 0) { |
775 | IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); | 902 | IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); |
776 | goto done; | 903 | goto done; |
@@ -831,7 +958,12 @@ void iwl_bg_scan_completed(struct work_struct *work) | |||
831 | 958 | ||
832 | cancel_delayed_work(&priv->scan_check); | 959 | cancel_delayed_work(&priv->scan_check); |
833 | 960 | ||
834 | ieee80211_scan_completed(priv->hw, false); | 961 | if (!priv->is_internal_short_scan) |
962 | ieee80211_scan_completed(priv->hw, false); | ||
963 | else { | ||
964 | priv->is_internal_short_scan = false; | ||
965 | IWL_DEBUG_SCAN(priv, "internal short scan completed\n"); | ||
966 | } | ||
835 | 967 | ||
836 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 968 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
837 | return; | 969 | 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 8f4071562857..10701b8eef23 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. |
@@ -60,7 +60,8 @@ static const u16 default_tid_to_tx_fifo[] = { | |||
60 | static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv, | 60 | static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv, |
61 | struct iwl_dma_ptr *ptr, size_t size) | 61 | struct iwl_dma_ptr *ptr, size_t size) |
62 | { | 62 | { |
63 | ptr->addr = pci_alloc_consistent(priv->pci_dev, size, &ptr->dma); | 63 | ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma, |
64 | GFP_KERNEL); | ||
64 | if (!ptr->addr) | 65 | if (!ptr->addr) |
65 | return -ENOMEM; | 66 | return -ENOMEM; |
66 | ptr->size = size; | 67 | ptr->size = size; |
@@ -73,21 +74,20 @@ static inline void iwl_free_dma_ptr(struct iwl_priv *priv, | |||
73 | if (unlikely(!ptr->addr)) | 74 | if (unlikely(!ptr->addr)) |
74 | return; | 75 | return; |
75 | 76 | ||
76 | pci_free_consistent(priv->pci_dev, ptr->size, ptr->addr, ptr->dma); | 77 | dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma); |
77 | memset(ptr, 0, sizeof(*ptr)); | 78 | memset(ptr, 0, sizeof(*ptr)); |
78 | } | 79 | } |
79 | 80 | ||
80 | /** | 81 | /** |
81 | * iwl_txq_update_write_ptr - Send new write index to hardware | 82 | * iwl_txq_update_write_ptr - Send new write index to hardware |
82 | */ | 83 | */ |
83 | int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) | 84 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) |
84 | { | 85 | { |
85 | u32 reg = 0; | 86 | u32 reg = 0; |
86 | int ret = 0; | ||
87 | int txq_id = txq->q.id; | 87 | int txq_id = txq->q.id; |
88 | 88 | ||
89 | if (txq->need_update == 0) | 89 | if (txq->need_update == 0) |
90 | return ret; | 90 | return; |
91 | 91 | ||
92 | /* if we're trying to save power */ | 92 | /* if we're trying to save power */ |
93 | if (test_bit(STATUS_POWER_PMI, &priv->status)) { | 93 | if (test_bit(STATUS_POWER_PMI, &priv->status)) { |
@@ -101,7 +101,7 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
101 | txq_id, reg); | 101 | txq_id, reg); |
102 | iwl_set_bit(priv, CSR_GP_CNTRL, | 102 | iwl_set_bit(priv, CSR_GP_CNTRL, |
103 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 103 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
104 | return ret; | 104 | return; |
105 | } | 105 | } |
106 | 106 | ||
107 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, | 107 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, |
@@ -114,8 +114,6 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
114 | txq->q.write_ptr | (txq_id << 8)); | 114 | txq->q.write_ptr | (txq_id << 8)); |
115 | 115 | ||
116 | txq->need_update = 0; | 116 | txq->need_update = 0; |
117 | |||
118 | return ret; | ||
119 | } | 117 | } |
120 | EXPORT_SYMBOL(iwl_txq_update_write_ptr); | 118 | EXPORT_SYMBOL(iwl_txq_update_write_ptr); |
121 | 119 | ||
@@ -146,7 +144,7 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) | |||
146 | { | 144 | { |
147 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | 145 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; |
148 | struct iwl_queue *q = &txq->q; | 146 | struct iwl_queue *q = &txq->q; |
149 | struct pci_dev *dev = priv->pci_dev; | 147 | struct device *dev = &priv->pci_dev->dev; |
150 | int i; | 148 | int i; |
151 | 149 | ||
152 | if (q->n_bd == 0) | 150 | if (q->n_bd == 0) |
@@ -163,8 +161,8 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) | |||
163 | 161 | ||
164 | /* De-alloc circular buffer of TFDs */ | 162 | /* De-alloc circular buffer of TFDs */ |
165 | if (txq->q.n_bd) | 163 | if (txq->q.n_bd) |
166 | pci_free_consistent(dev, priv->hw_params.tfd_size * | 164 | dma_free_coherent(dev, priv->hw_params.tfd_size * |
167 | txq->q.n_bd, txq->tfds, txq->q.dma_addr); | 165 | txq->q.n_bd, txq->tfds, txq->q.dma_addr); |
168 | 166 | ||
169 | /* De-alloc array of per-TFD driver data */ | 167 | /* De-alloc array of per-TFD driver data */ |
170 | kfree(txq->txb); | 168 | kfree(txq->txb); |
@@ -193,7 +191,7 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) | |||
193 | { | 191 | { |
194 | struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; | 192 | struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; |
195 | struct iwl_queue *q = &txq->q; | 193 | struct iwl_queue *q = &txq->q; |
196 | struct pci_dev *dev = priv->pci_dev; | 194 | struct device *dev = &priv->pci_dev->dev; |
197 | int i; | 195 | int i; |
198 | 196 | ||
199 | if (q->n_bd == 0) | 197 | if (q->n_bd == 0) |
@@ -205,8 +203,8 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) | |||
205 | 203 | ||
206 | /* De-alloc circular buffer of TFDs */ | 204 | /* De-alloc circular buffer of TFDs */ |
207 | if (txq->q.n_bd) | 205 | if (txq->q.n_bd) |
208 | pci_free_consistent(dev, priv->hw_params.tfd_size * | 206 | dma_free_coherent(dev, priv->hw_params.tfd_size * txq->q.n_bd, |
209 | txq->q.n_bd, txq->tfds, txq->q.dma_addr); | 207 | txq->tfds, txq->q.dma_addr); |
210 | 208 | ||
211 | /* deallocate arrays */ | 209 | /* deallocate arrays */ |
212 | kfree(txq->cmd); | 210 | kfree(txq->cmd); |
@@ -297,7 +295,7 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, | |||
297 | static int iwl_tx_queue_alloc(struct iwl_priv *priv, | 295 | static int iwl_tx_queue_alloc(struct iwl_priv *priv, |
298 | struct iwl_tx_queue *txq, u32 id) | 296 | struct iwl_tx_queue *txq, u32 id) |
299 | { | 297 | { |
300 | struct pci_dev *dev = priv->pci_dev; | 298 | struct device *dev = &priv->pci_dev->dev; |
301 | size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX; | 299 | size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX; |
302 | 300 | ||
303 | /* Driver private data, only for Tx (not command) queues, | 301 | /* Driver private data, only for Tx (not command) queues, |
@@ -316,8 +314,8 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv, | |||
316 | 314 | ||
317 | /* Circular buffer of transmit frame descriptors (TFDs), | 315 | /* Circular buffer of transmit frame descriptors (TFDs), |
318 | * shared with device */ | 316 | * shared with device */ |
319 | txq->tfds = pci_alloc_consistent(dev, tfd_sz, &txq->q.dma_addr); | 317 | txq->tfds = dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr, |
320 | 318 | GFP_KERNEL); | |
321 | if (!txq->tfds) { | 319 | if (!txq->tfds) { |
322 | IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz); | 320 | IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz); |
323 | goto error; | 321 | goto error; |
@@ -745,7 +743,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
745 | u8 tid = 0; | 743 | u8 tid = 0; |
746 | u8 *qc = NULL; | 744 | u8 *qc = NULL; |
747 | unsigned long flags; | 745 | unsigned long flags; |
748 | int ret; | ||
749 | 746 | ||
750 | spin_lock_irqsave(&priv->lock, flags); | 747 | spin_lock_irqsave(&priv->lock, flags); |
751 | if (iwl_is_rfkill(priv)) { | 748 | if (iwl_is_rfkill(priv)) { |
@@ -820,8 +817,10 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
820 | hdr->seq_ctrl |= cpu_to_le16(seq_number); | 817 | hdr->seq_ctrl |= cpu_to_le16(seq_number); |
821 | seq_number += 0x10; | 818 | seq_number += 0x10; |
822 | /* aggregation is on for this <sta,tid> */ | 819 | /* aggregation is on for this <sta,tid> */ |
823 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | 820 | if (info->flags & IEEE80211_TX_CTL_AMPDU && |
821 | priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) { | ||
824 | txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; | 822 | txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; |
823 | } | ||
825 | } | 824 | } |
826 | 825 | ||
827 | txq = &priv->txq[txq_id]; | 826 | txq = &priv->txq[txq_id]; |
@@ -963,7 +962,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
963 | 962 | ||
964 | /* Tell device the write index *just past* this latest filled TFD */ | 963 | /* Tell device the write index *just past* this latest filled TFD */ |
965 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 964 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
966 | ret = iwl_txq_update_write_ptr(priv, txq); | 965 | iwl_txq_update_write_ptr(priv, txq); |
967 | spin_unlock_irqrestore(&priv->lock, flags); | 966 | spin_unlock_irqrestore(&priv->lock, flags); |
968 | 967 | ||
969 | /* | 968 | /* |
@@ -977,9 +976,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
977 | if (sta_priv && sta_priv->client) | 976 | if (sta_priv && sta_priv->client) |
978 | atomic_inc(&sta_priv->pending_frames); | 977 | atomic_inc(&sta_priv->pending_frames); |
979 | 978 | ||
980 | if (ret) | ||
981 | return ret; | ||
982 | |||
983 | if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { | 979 | if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { |
984 | if (wait_write_ptr) { | 980 | if (wait_write_ptr) { |
985 | spin_lock_irqsave(&priv->lock, flags); | 981 | spin_lock_irqsave(&priv->lock, flags); |
@@ -1018,7 +1014,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
1018 | struct iwl_cmd_meta *out_meta; | 1014 | struct iwl_cmd_meta *out_meta; |
1019 | dma_addr_t phys_addr; | 1015 | dma_addr_t phys_addr; |
1020 | unsigned long flags; | 1016 | unsigned long flags; |
1021 | int len, ret; | 1017 | int len; |
1022 | u32 idx; | 1018 | u32 idx; |
1023 | u16 fix_size; | 1019 | u16 fix_size; |
1024 | 1020 | ||
@@ -1115,10 +1111,10 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
1115 | 1111 | ||
1116 | /* Increment and update queue's write index */ | 1112 | /* Increment and update queue's write index */ |
1117 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 1113 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
1118 | ret = iwl_txq_update_write_ptr(priv, txq); | 1114 | iwl_txq_update_write_ptr(priv, txq); |
1119 | 1115 | ||
1120 | spin_unlock_irqrestore(&priv->hcmd_lock, flags); | 1116 | spin_unlock_irqrestore(&priv->hcmd_lock, flags); |
1121 | return ret ? ret : idx; | 1117 | return idx; |
1122 | } | 1118 | } |
1123 | 1119 | ||
1124 | static void iwl_tx_status(struct iwl_priv *priv, struct sk_buff *skb) | 1120 | static void iwl_tx_status(struct iwl_priv *priv, struct sk_buff *skb) |
@@ -1260,6 +1256,8 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
1260 | 1256 | ||
1261 | if (!(meta->flags & CMD_ASYNC)) { | 1257 | if (!(meta->flags & CMD_ASYNC)) { |
1262 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | 1258 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); |
1259 | IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n", | ||
1260 | get_cmd_string(cmd->hdr.cmd)); | ||
1263 | wake_up_interruptible(&priv->wait_command_queue); | 1261 | wake_up_interruptible(&priv->wait_command_queue); |
1264 | } | 1262 | } |
1265 | } | 1263 | } |
@@ -1346,7 +1344,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) | |||
1346 | { | 1344 | { |
1347 | int tx_fifo_id, txq_id, sta_id, ssn = -1; | 1345 | int tx_fifo_id, txq_id, sta_id, ssn = -1; |
1348 | struct iwl_tid_data *tid_data; | 1346 | struct iwl_tid_data *tid_data; |
1349 | int ret, write_ptr, read_ptr; | 1347 | int write_ptr, read_ptr; |
1350 | unsigned long flags; | 1348 | unsigned long flags; |
1351 | 1349 | ||
1352 | if (!ra) { | 1350 | if (!ra) { |
@@ -1398,13 +1396,17 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) | |||
1398 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | 1396 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; |
1399 | 1397 | ||
1400 | spin_lock_irqsave(&priv->lock, flags); | 1398 | spin_lock_irqsave(&priv->lock, flags); |
1401 | ret = priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, | 1399 | /* |
1400 | * the only reason this call can fail is queue number out of range, | ||
1401 | * which can happen if uCode is reloaded and all the station | ||
1402 | * information are lost. if it is outside the range, there is no need | ||
1403 | * to deactivate the uCode queue, just return "success" to allow | ||
1404 | * mac80211 to clean up it own data. | ||
1405 | */ | ||
1406 | priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, | ||
1402 | tx_fifo_id); | 1407 | tx_fifo_id); |
1403 | spin_unlock_irqrestore(&priv->lock, flags); | 1408 | spin_unlock_irqrestore(&priv->lock, flags); |
1404 | 1409 | ||
1405 | if (ret) | ||
1406 | return ret; | ||
1407 | |||
1408 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); | 1410 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); |
1409 | 1411 | ||
1410 | return 0; | 1412 | return 0; |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index f8e4e4b18d02..54daa38ecba3 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. |
@@ -53,9 +53,10 @@ | |||
53 | #include "iwl-commands.h" | 53 | #include "iwl-commands.h" |
54 | #include "iwl-sta.h" | 54 | #include "iwl-sta.h" |
55 | #include "iwl-3945.h" | 55 | #include "iwl-3945.h" |
56 | #include "iwl-helpers.h" | ||
57 | #include "iwl-core.h" | 56 | #include "iwl-core.h" |
57 | #include "iwl-helpers.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); |
@@ -352,10 +352,10 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv) | |||
352 | static void iwl3945_unset_hw_params(struct iwl_priv *priv) | 352 | static void iwl3945_unset_hw_params(struct iwl_priv *priv) |
353 | { | 353 | { |
354 | if (priv->shared_virt) | 354 | if (priv->shared_virt) |
355 | pci_free_consistent(priv->pci_dev, | 355 | dma_free_coherent(&priv->pci_dev->dev, |
356 | sizeof(struct iwl3945_shared), | 356 | sizeof(struct iwl3945_shared), |
357 | priv->shared_virt, | 357 | priv->shared_virt, |
358 | priv->shared_phys); | 358 | priv->shared_phys); |
359 | } | 359 | } |
360 | 360 | ||
361 | static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, | 361 | static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, |
@@ -478,7 +478,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
478 | u8 wait_write_ptr = 0; | 478 | u8 wait_write_ptr = 0; |
479 | u8 *qc = NULL; | 479 | u8 *qc = NULL; |
480 | unsigned long flags; | 480 | unsigned long flags; |
481 | int rc; | ||
482 | 481 | ||
483 | spin_lock_irqsave(&priv->lock, flags); | 482 | spin_lock_irqsave(&priv->lock, flags); |
484 | if (iwl_is_rfkill(priv)) { | 483 | if (iwl_is_rfkill(priv)) { |
@@ -663,12 +662,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
663 | 662 | ||
664 | /* Tell device the write index *just past* this latest filled TFD */ | 663 | /* Tell device the write index *just past* this latest filled TFD */ |
665 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 664 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
666 | rc = iwl_txq_update_write_ptr(priv, txq); | 665 | iwl_txq_update_write_ptr(priv, txq); |
667 | spin_unlock_irqrestore(&priv->lock, flags); | 666 | spin_unlock_irqrestore(&priv->lock, flags); |
668 | 667 | ||
669 | if (rc) | ||
670 | return rc; | ||
671 | |||
672 | if ((iwl_queue_space(q) < q->high_mark) | 668 | if ((iwl_queue_space(q) < q->high_mark) |
673 | && priv->mac80211_registered) { | 669 | && priv->mac80211_registered) { |
674 | if (wait_write_ptr) { | 670 | if (wait_write_ptr) { |
@@ -689,10 +685,6 @@ drop: | |||
689 | return -1; | 685 | return -1; |
690 | } | 686 | } |
691 | 687 | ||
692 | #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT | ||
693 | |||
694 | #include "iwl-spectrum.h" | ||
695 | |||
696 | #define BEACON_TIME_MASK_LOW 0x00FFFFFF | 688 | #define BEACON_TIME_MASK_LOW 0x00FFFFFF |
697 | #define BEACON_TIME_MASK_HIGH 0xFF000000 | 689 | #define BEACON_TIME_MASK_HIGH 0xFF000000 |
698 | #define TIME_UNIT 1024 | 690 | #define TIME_UNIT 1024 |
@@ -819,7 +811,6 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, | |||
819 | 811 | ||
820 | return rc; | 812 | return rc; |
821 | } | 813 | } |
822 | #endif | ||
823 | 814 | ||
824 | static void iwl3945_rx_reply_alive(struct iwl_priv *priv, | 815 | static void iwl3945_rx_reply_alive(struct iwl_priv *priv, |
825 | struct iwl_rx_mem_buffer *rxb) | 816 | struct iwl_rx_mem_buffer *rxb) |
@@ -962,6 +953,8 @@ static void iwl3945_setup_rx_handlers(struct iwl_priv *priv) | |||
962 | priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta; | 953 | priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta; |
963 | priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error; | 954 | priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error; |
964 | priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; | 955 | priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; |
956 | priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] = | ||
957 | iwl_rx_spectrum_measure_notif; | ||
965 | priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; | 958 | priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; |
966 | priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] = | 959 | priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] = |
967 | iwl_rx_pm_debug_statistics_notif; | 960 | iwl_rx_pm_debug_statistics_notif; |
@@ -975,7 +968,6 @@ static void iwl3945_setup_rx_handlers(struct iwl_priv *priv) | |||
975 | priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_hw_rx_statistics; | 968 | priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_hw_rx_statistics; |
976 | priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics; | 969 | priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics; |
977 | 970 | ||
978 | iwl_setup_spectrum_handlers(priv); | ||
979 | iwl_setup_rx_scan_handlers(priv); | 971 | iwl_setup_rx_scan_handlers(priv); |
980 | priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif; | 972 | priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif; |
981 | 973 | ||
@@ -1067,13 +1059,13 @@ static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl_priv *priv, | |||
1067 | * also updates the memory address in the firmware to reference the new | 1059 | * also updates the memory address in the firmware to reference the new |
1068 | * target buffer. | 1060 | * target buffer. |
1069 | */ | 1061 | */ |
1070 | static int iwl3945_rx_queue_restock(struct iwl_priv *priv) | 1062 | static void iwl3945_rx_queue_restock(struct iwl_priv *priv) |
1071 | { | 1063 | { |
1072 | struct iwl_rx_queue *rxq = &priv->rxq; | 1064 | struct iwl_rx_queue *rxq = &priv->rxq; |
1073 | struct list_head *element; | 1065 | struct list_head *element; |
1074 | struct iwl_rx_mem_buffer *rxb; | 1066 | struct iwl_rx_mem_buffer *rxb; |
1075 | unsigned long flags; | 1067 | unsigned long flags; |
1076 | int write, rc; | 1068 | int write; |
1077 | 1069 | ||
1078 | spin_lock_irqsave(&rxq->lock, flags); | 1070 | spin_lock_irqsave(&rxq->lock, flags); |
1079 | write = rxq->write & ~0x7; | 1071 | write = rxq->write & ~0x7; |
@@ -1103,12 +1095,8 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv) | |||
1103 | spin_lock_irqsave(&rxq->lock, flags); | 1095 | spin_lock_irqsave(&rxq->lock, flags); |
1104 | rxq->need_update = 1; | 1096 | rxq->need_update = 1; |
1105 | spin_unlock_irqrestore(&rxq->lock, flags); | 1097 | spin_unlock_irqrestore(&rxq->lock, flags); |
1106 | rc = iwl_rx_queue_update_write_ptr(priv, rxq); | 1098 | iwl_rx_queue_update_write_ptr(priv, rxq); |
1107 | if (rc) | ||
1108 | return rc; | ||
1109 | } | 1099 | } |
1110 | |||
1111 | return 0; | ||
1112 | } | 1100 | } |
1113 | 1101 | ||
1114 | /** | 1102 | /** |
@@ -1253,10 +1241,10 @@ static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rx | |||
1253 | } | 1241 | } |
1254 | } | 1242 | } |
1255 | 1243 | ||
1256 | pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd, | 1244 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, |
1257 | rxq->dma_addr); | 1245 | rxq->dma_addr); |
1258 | pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status), | 1246 | dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), |
1259 | rxq->rb_stts, rxq->rb_stts_dma); | 1247 | rxq->rb_stts, rxq->rb_stts_dma); |
1260 | rxq->bd = NULL; | 1248 | rxq->bd = NULL; |
1261 | rxq->rb_stts = NULL; | 1249 | rxq->rb_stts = NULL; |
1262 | } | 1250 | } |
@@ -1518,8 +1506,9 @@ void iwl3945_dump_nic_error_log(struct iwl_priv *priv) | |||
1518 | * iwl3945_print_event_log - Dump error event log to syslog | 1506 | * iwl3945_print_event_log - Dump error event log to syslog |
1519 | * | 1507 | * |
1520 | */ | 1508 | */ |
1521 | static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, | 1509 | static int iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, |
1522 | u32 num_events, u32 mode) | 1510 | u32 num_events, u32 mode, |
1511 | int pos, char **buf, size_t bufsz) | ||
1523 | { | 1512 | { |
1524 | u32 i; | 1513 | u32 i; |
1525 | u32 base; /* SRAM byte address of event log header */ | 1514 | u32 base; /* SRAM byte address of event log header */ |
@@ -1529,7 +1518,7 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1529 | unsigned long reg_flags; | 1518 | unsigned long reg_flags; |
1530 | 1519 | ||
1531 | if (num_events == 0) | 1520 | if (num_events == 0) |
1532 | return; | 1521 | return pos; |
1533 | 1522 | ||
1534 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | 1523 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); |
1535 | 1524 | ||
@@ -1555,26 +1544,43 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1555 | time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | 1544 | time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
1556 | if (mode == 0) { | 1545 | if (mode == 0) { |
1557 | /* data, ev */ | 1546 | /* data, ev */ |
1558 | IWL_ERR(priv, "0x%08x\t%04u\n", time, ev); | 1547 | if (bufsz) { |
1559 | trace_iwlwifi_dev_ucode_event(priv, 0, time, ev); | 1548 | pos += scnprintf(*buf + pos, bufsz - pos, |
1549 | "0x%08x:%04u\n", | ||
1550 | time, ev); | ||
1551 | } else { | ||
1552 | IWL_ERR(priv, "0x%08x\t%04u\n", time, ev); | ||
1553 | trace_iwlwifi_dev_ucode_event(priv, 0, | ||
1554 | time, ev); | ||
1555 | } | ||
1560 | } else { | 1556 | } else { |
1561 | data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | 1557 | data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
1562 | IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", time, data, ev); | 1558 | if (bufsz) { |
1563 | trace_iwlwifi_dev_ucode_event(priv, time, data, ev); | 1559 | pos += scnprintf(*buf + pos, bufsz - pos, |
1560 | "%010u:0x%08x:%04u\n", | ||
1561 | time, data, ev); | ||
1562 | } else { | ||
1563 | IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", | ||
1564 | time, data, ev); | ||
1565 | trace_iwlwifi_dev_ucode_event(priv, time, | ||
1566 | data, ev); | ||
1567 | } | ||
1564 | } | 1568 | } |
1565 | } | 1569 | } |
1566 | 1570 | ||
1567 | /* Allow device to power down */ | 1571 | /* Allow device to power down */ |
1568 | iwl_release_nic_access(priv); | 1572 | iwl_release_nic_access(priv); |
1569 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | 1573 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); |
1574 | return pos; | ||
1570 | } | 1575 | } |
1571 | 1576 | ||
1572 | /** | 1577 | /** |
1573 | * iwl3945_print_last_event_logs - Dump the newest # of event log to syslog | 1578 | * iwl3945_print_last_event_logs - Dump the newest # of event log to syslog |
1574 | */ | 1579 | */ |
1575 | static void iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | 1580 | static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, |
1576 | u32 num_wraps, u32 next_entry, | 1581 | u32 num_wraps, u32 next_entry, |
1577 | u32 size, u32 mode) | 1582 | u32 size, u32 mode, |
1583 | int pos, char **buf, size_t bufsz) | ||
1578 | { | 1584 | { |
1579 | /* | 1585 | /* |
1580 | * display the newest DEFAULT_LOG_ENTRIES entries | 1586 | * display the newest DEFAULT_LOG_ENTRIES entries |
@@ -1582,21 +1588,28 @@ static void iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | |||
1582 | */ | 1588 | */ |
1583 | if (num_wraps) { | 1589 | if (num_wraps) { |
1584 | if (next_entry < size) { | 1590 | if (next_entry < size) { |
1585 | iwl3945_print_event_log(priv, | 1591 | pos = iwl3945_print_event_log(priv, |
1586 | capacity - (size - next_entry), | 1592 | capacity - (size - next_entry), |
1587 | size - next_entry, mode); | 1593 | size - next_entry, mode, |
1588 | iwl3945_print_event_log(priv, 0, | 1594 | pos, buf, bufsz); |
1589 | next_entry, mode); | 1595 | pos = iwl3945_print_event_log(priv, 0, |
1596 | next_entry, mode, | ||
1597 | pos, buf, bufsz); | ||
1590 | } else | 1598 | } else |
1591 | iwl3945_print_event_log(priv, next_entry - size, | 1599 | pos = iwl3945_print_event_log(priv, next_entry - size, |
1592 | size, mode); | 1600 | size, mode, |
1601 | pos, buf, bufsz); | ||
1593 | } else { | 1602 | } else { |
1594 | if (next_entry < size) | 1603 | if (next_entry < size) |
1595 | iwl3945_print_event_log(priv, 0, next_entry, mode); | 1604 | pos = iwl3945_print_event_log(priv, 0, |
1605 | next_entry, mode, | ||
1606 | pos, buf, bufsz); | ||
1596 | else | 1607 | else |
1597 | iwl3945_print_event_log(priv, next_entry - size, | 1608 | pos = iwl3945_print_event_log(priv, next_entry - size, |
1598 | size, mode); | 1609 | size, mode, |
1610 | pos, buf, bufsz); | ||
1599 | } | 1611 | } |
1612 | return pos; | ||
1600 | } | 1613 | } |
1601 | 1614 | ||
1602 | /* For sanity check only. Actual size is determined by uCode, typ. 512 */ | 1615 | /* For sanity check only. Actual size is determined by uCode, typ. 512 */ |
@@ -1604,7 +1617,8 @@ static void iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | |||
1604 | 1617 | ||
1605 | #define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20) | 1618 | #define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20) |
1606 | 1619 | ||
1607 | void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | 1620 | int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, |
1621 | char **buf, bool display) | ||
1608 | { | 1622 | { |
1609 | u32 base; /* SRAM byte address of event log header */ | 1623 | u32 base; /* SRAM byte address of event log header */ |
1610 | u32 capacity; /* event log capacity in # entries */ | 1624 | u32 capacity; /* event log capacity in # entries */ |
@@ -1612,11 +1626,13 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | |||
1612 | u32 num_wraps; /* # times uCode wrapped to top of log */ | 1626 | u32 num_wraps; /* # times uCode wrapped to top of log */ |
1613 | u32 next_entry; /* index of next entry to be written by uCode */ | 1627 | u32 next_entry; /* index of next entry to be written by uCode */ |
1614 | u32 size; /* # entries that we'll print */ | 1628 | u32 size; /* # entries that we'll print */ |
1629 | int pos = 0; | ||
1630 | size_t bufsz = 0; | ||
1615 | 1631 | ||
1616 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | 1632 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); |
1617 | if (!iwl3945_hw_valid_rtc_data_addr(base)) { | 1633 | if (!iwl3945_hw_valid_rtc_data_addr(base)) { |
1618 | IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); | 1634 | IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); |
1619 | return; | 1635 | return -EINVAL; |
1620 | } | 1636 | } |
1621 | 1637 | ||
1622 | /* event log header */ | 1638 | /* event log header */ |
@@ -1642,7 +1658,7 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | |||
1642 | /* bail out if nothing in log */ | 1658 | /* bail out if nothing in log */ |
1643 | if (size == 0) { | 1659 | if (size == 0) { |
1644 | IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); | 1660 | IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); |
1645 | return; | 1661 | return pos; |
1646 | } | 1662 | } |
1647 | 1663 | ||
1648 | #ifdef CONFIG_IWLWIFI_DEBUG | 1664 | #ifdef CONFIG_IWLWIFI_DEBUG |
@@ -1658,25 +1674,38 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | |||
1658 | size); | 1674 | size); |
1659 | 1675 | ||
1660 | #ifdef CONFIG_IWLWIFI_DEBUG | 1676 | #ifdef CONFIG_IWLWIFI_DEBUG |
1677 | if (display) { | ||
1678 | if (full_log) | ||
1679 | bufsz = capacity * 48; | ||
1680 | else | ||
1681 | bufsz = size * 48; | ||
1682 | *buf = kmalloc(bufsz, GFP_KERNEL); | ||
1683 | if (!*buf) | ||
1684 | return -ENOMEM; | ||
1685 | } | ||
1661 | if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { | 1686 | if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { |
1662 | /* if uCode has wrapped back to top of log, | 1687 | /* if uCode has wrapped back to top of log, |
1663 | * start at the oldest entry, | 1688 | * start at the oldest entry, |
1664 | * i.e the next one that uCode would fill. | 1689 | * i.e the next one that uCode would fill. |
1665 | */ | 1690 | */ |
1666 | if (num_wraps) | 1691 | if (num_wraps) |
1667 | iwl3945_print_event_log(priv, next_entry, | 1692 | pos = iwl3945_print_event_log(priv, next_entry, |
1668 | capacity - next_entry, mode); | 1693 | capacity - next_entry, mode, |
1694 | pos, buf, bufsz); | ||
1669 | 1695 | ||
1670 | /* (then/else) start at top of log */ | 1696 | /* (then/else) start at top of log */ |
1671 | iwl3945_print_event_log(priv, 0, next_entry, mode); | 1697 | pos = iwl3945_print_event_log(priv, 0, next_entry, mode, |
1698 | pos, buf, bufsz); | ||
1672 | } else | 1699 | } else |
1673 | iwl3945_print_last_event_logs(priv, capacity, num_wraps, | 1700 | pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps, |
1674 | next_entry, size, mode); | 1701 | next_entry, size, mode, |
1702 | pos, buf, bufsz); | ||
1675 | #else | 1703 | #else |
1676 | iwl3945_print_last_event_logs(priv, capacity, num_wraps, | 1704 | pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps, |
1677 | next_entry, size, mode); | 1705 | next_entry, size, mode, |
1706 | pos, buf, bufsz); | ||
1678 | #endif | 1707 | #endif |
1679 | 1708 | return pos; | |
1680 | } | 1709 | } |
1681 | 1710 | ||
1682 | static void iwl3945_irq_tasklet(struct iwl_priv *priv) | 1711 | static void iwl3945_irq_tasklet(struct iwl_priv *priv) |
@@ -2996,18 +3025,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data) | |||
2996 | mutex_unlock(&priv->mutex); | 3025 | mutex_unlock(&priv->mutex); |
2997 | } | 3026 | } |
2998 | 3027 | ||
2999 | static void iwl3945_bg_up(struct work_struct *data) | ||
3000 | { | ||
3001 | struct iwl_priv *priv = container_of(data, struct iwl_priv, up); | ||
3002 | |||
3003 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
3004 | return; | ||
3005 | |||
3006 | mutex_lock(&priv->mutex); | ||
3007 | __iwl3945_up(priv); | ||
3008 | mutex_unlock(&priv->mutex); | ||
3009 | } | ||
3010 | |||
3011 | static void iwl3945_bg_restart(struct work_struct *data) | 3028 | static void iwl3945_bg_restart(struct work_struct *data) |
3012 | { | 3029 | { |
3013 | struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); | 3030 | struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); |
@@ -3024,7 +3041,13 @@ static void iwl3945_bg_restart(struct work_struct *data) | |||
3024 | ieee80211_restart_hw(priv->hw); | 3041 | ieee80211_restart_hw(priv->hw); |
3025 | } else { | 3042 | } else { |
3026 | iwl3945_down(priv); | 3043 | iwl3945_down(priv); |
3027 | queue_work(priv->workqueue, &priv->up); | 3044 | |
3045 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
3046 | return; | ||
3047 | |||
3048 | mutex_lock(&priv->mutex); | ||
3049 | __iwl3945_up(priv); | ||
3050 | mutex_unlock(&priv->mutex); | ||
3028 | } | 3051 | } |
3029 | } | 3052 | } |
3030 | 3053 | ||
@@ -3528,8 +3551,6 @@ static ssize_t store_filter_flags(struct device *d, | |||
3528 | static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, | 3551 | static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, |
3529 | store_filter_flags); | 3552 | store_filter_flags); |
3530 | 3553 | ||
3531 | #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT | ||
3532 | |||
3533 | static ssize_t show_measurement(struct device *d, | 3554 | static ssize_t show_measurement(struct device *d, |
3534 | struct device_attribute *attr, char *buf) | 3555 | struct device_attribute *attr, char *buf) |
3535 | { | 3556 | { |
@@ -3599,7 +3620,6 @@ static ssize_t store_measurement(struct device *d, | |||
3599 | 3620 | ||
3600 | static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR, | 3621 | static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR, |
3601 | show_measurement, store_measurement); | 3622 | show_measurement, store_measurement); |
3602 | #endif /* CONFIG_IWL3945_SPECTRUM_MEASUREMENT */ | ||
3603 | 3623 | ||
3604 | static ssize_t store_retry_rate(struct device *d, | 3624 | static ssize_t store_retry_rate(struct device *d, |
3605 | struct device_attribute *attr, | 3625 | struct device_attribute *attr, |
@@ -3748,7 +3768,6 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv) | |||
3748 | 3768 | ||
3749 | init_waitqueue_head(&priv->wait_command_queue); | 3769 | init_waitqueue_head(&priv->wait_command_queue); |
3750 | 3770 | ||
3751 | INIT_WORK(&priv->up, iwl3945_bg_up); | ||
3752 | INIT_WORK(&priv->restart, iwl3945_bg_restart); | 3771 | INIT_WORK(&priv->restart, iwl3945_bg_restart); |
3753 | INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish); | 3772 | INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish); |
3754 | INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update); | 3773 | INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update); |
@@ -3782,9 +3801,7 @@ static struct attribute *iwl3945_sysfs_entries[] = { | |||
3782 | &dev_attr_dump_errors.attr, | 3801 | &dev_attr_dump_errors.attr, |
3783 | &dev_attr_flags.attr, | 3802 | &dev_attr_flags.attr, |
3784 | &dev_attr_filter_flags.attr, | 3803 | &dev_attr_filter_flags.attr, |
3785 | #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT | ||
3786 | &dev_attr_measurement.attr, | 3804 | &dev_attr_measurement.attr, |
3787 | #endif | ||
3788 | &dev_attr_retry_rate.attr, | 3805 | &dev_attr_retry_rate.attr, |
3789 | &dev_attr_statistics.attr, | 3806 | &dev_attr_statistics.attr, |
3790 | &dev_attr_status.attr, | 3807 | &dev_attr_status.attr, |
@@ -3810,7 +3827,6 @@ static struct ieee80211_ops iwl3945_hw_ops = { | |||
3810 | .config = iwl_mac_config, | 3827 | .config = iwl_mac_config, |
3811 | .configure_filter = iwl_configure_filter, | 3828 | .configure_filter = iwl_configure_filter, |
3812 | .set_key = iwl3945_mac_set_key, | 3829 | .set_key = iwl3945_mac_set_key, |
3813 | .get_tx_stats = iwl_mac_get_tx_stats, | ||
3814 | .conf_tx = iwl_mac_conf_tx, | 3830 | .conf_tx = iwl_mac_conf_tx, |
3815 | .reset_tsf = iwl_mac_reset_tsf, | 3831 | .reset_tsf = iwl_mac_reset_tsf, |
3816 | .bss_info_changed = iwl_bss_info_changed, | 3832 | .bss_info_changed = iwl_bss_info_changed, |
@@ -3831,6 +3847,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv) | |||
3831 | INIT_LIST_HEAD(&priv->free_frames); | 3847 | INIT_LIST_HEAD(&priv->free_frames); |
3832 | 3848 | ||
3833 | mutex_init(&priv->mutex); | 3849 | mutex_init(&priv->mutex); |
3850 | mutex_init(&priv->sync_cmd_mutex); | ||
3834 | 3851 | ||
3835 | /* Clear the driver's (not device's) station table */ | 3852 | /* Clear the driver's (not device's) station table */ |
3836 | iwl_clear_stations_table(priv); | 3853 | iwl_clear_stations_table(priv); |
@@ -3840,6 +3857,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv) | |||
3840 | priv->band = IEEE80211_BAND_2GHZ; | 3857 | priv->band = IEEE80211_BAND_2GHZ; |
3841 | 3858 | ||
3842 | priv->iw_mode = NL80211_IFTYPE_STATION; | 3859 | priv->iw_mode = NL80211_IFTYPE_STATION; |
3860 | priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; | ||
3843 | 3861 | ||
3844 | iwl_reset_qos(priv); | 3862 | iwl_reset_qos(priv); |
3845 | 3863 | ||
@@ -4022,6 +4040,13 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
4022 | spin_lock_init(&priv->reg_lock); | 4040 | spin_lock_init(&priv->reg_lock); |
4023 | spin_lock_init(&priv->lock); | 4041 | spin_lock_init(&priv->lock); |
4024 | 4042 | ||
4043 | /* | ||
4044 | * stop and reset the on-board processor just in case it is in a | ||
4045 | * strange state ... like being left stranded by a primary kernel | ||
4046 | * and this is now the kdump kernel trying to start up | ||
4047 | */ | ||
4048 | iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); | ||
4049 | |||
4025 | /*********************** | 4050 | /*********************** |
4026 | * 4. Read EEPROM | 4051 | * 4. Read EEPROM |
4027 | * ********************/ | 4052 | * ********************/ |
diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 842811142bef..79ffa3b98d73 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h | |||
@@ -268,7 +268,7 @@ struct iwm_priv { | |||
268 | 268 | ||
269 | struct sk_buff_head rx_list; | 269 | struct sk_buff_head rx_list; |
270 | struct list_head rx_tickets; | 270 | struct list_head rx_tickets; |
271 | struct list_head rx_packets[IWM_RX_ID_HASH + 1]; | 271 | struct list_head rx_packets[IWM_RX_ID_HASH]; |
272 | struct workqueue_struct *rx_wq; | 272 | struct workqueue_struct *rx_wq; |
273 | struct work_struct rx_worker; | 273 | struct work_struct rx_worker; |
274 | 274 | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 64d16fe37f9a..6b53ae122680 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c | |||
@@ -868,36 +868,35 @@ static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf, | |||
868 | struct iwm_umac_notif_mgt_frame *mgt_frame = | 868 | struct iwm_umac_notif_mgt_frame *mgt_frame = |
869 | (struct iwm_umac_notif_mgt_frame *)buf; | 869 | (struct iwm_umac_notif_mgt_frame *)buf; |
870 | struct ieee80211_mgmt *mgt = (struct ieee80211_mgmt *)mgt_frame->frame; | 870 | struct ieee80211_mgmt *mgt = (struct ieee80211_mgmt *)mgt_frame->frame; |
871 | u8 *ie; | ||
872 | 871 | ||
873 | IWM_HEXDUMP(iwm, DBG, MLME, "MGT: ", mgt_frame->frame, | 872 | IWM_HEXDUMP(iwm, DBG, MLME, "MGT: ", mgt_frame->frame, |
874 | le16_to_cpu(mgt_frame->len)); | 873 | le16_to_cpu(mgt_frame->len)); |
875 | 874 | ||
876 | if (ieee80211_is_assoc_req(mgt->frame_control)) { | 875 | if (ieee80211_is_assoc_req(mgt->frame_control)) { |
877 | ie = mgt->u.assoc_req.variable;; | 876 | iwm->req_ie_len = le16_to_cpu(mgt_frame->len) |
878 | iwm->req_ie_len = | 877 | - offsetof(struct ieee80211_mgmt, |
879 | le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); | 878 | u.assoc_req.variable); |
880 | kfree(iwm->req_ie); | 879 | kfree(iwm->req_ie); |
881 | iwm->req_ie = kmemdup(mgt->u.assoc_req.variable, | 880 | iwm->req_ie = kmemdup(mgt->u.assoc_req.variable, |
882 | iwm->req_ie_len, GFP_KERNEL); | 881 | iwm->req_ie_len, GFP_KERNEL); |
883 | } else if (ieee80211_is_reassoc_req(mgt->frame_control)) { | 882 | } else if (ieee80211_is_reassoc_req(mgt->frame_control)) { |
884 | ie = mgt->u.reassoc_req.variable;; | 883 | iwm->req_ie_len = le16_to_cpu(mgt_frame->len) |
885 | iwm->req_ie_len = | 884 | - offsetof(struct ieee80211_mgmt, |
886 | le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); | 885 | u.reassoc_req.variable); |
887 | kfree(iwm->req_ie); | 886 | kfree(iwm->req_ie); |
888 | iwm->req_ie = kmemdup(mgt->u.reassoc_req.variable, | 887 | iwm->req_ie = kmemdup(mgt->u.reassoc_req.variable, |
889 | iwm->req_ie_len, GFP_KERNEL); | 888 | iwm->req_ie_len, GFP_KERNEL); |
890 | } else if (ieee80211_is_assoc_resp(mgt->frame_control)) { | 889 | } else if (ieee80211_is_assoc_resp(mgt->frame_control)) { |
891 | ie = mgt->u.assoc_resp.variable;; | 890 | iwm->resp_ie_len = le16_to_cpu(mgt_frame->len) |
892 | iwm->resp_ie_len = | 891 | - offsetof(struct ieee80211_mgmt, |
893 | le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); | 892 | u.assoc_resp.variable); |
894 | kfree(iwm->resp_ie); | 893 | kfree(iwm->resp_ie); |
895 | iwm->resp_ie = kmemdup(mgt->u.assoc_resp.variable, | 894 | iwm->resp_ie = kmemdup(mgt->u.assoc_resp.variable, |
896 | iwm->resp_ie_len, GFP_KERNEL); | 895 | iwm->resp_ie_len, GFP_KERNEL); |
897 | } else if (ieee80211_is_reassoc_resp(mgt->frame_control)) { | 896 | } else if (ieee80211_is_reassoc_resp(mgt->frame_control)) { |
898 | ie = mgt->u.reassoc_resp.variable;; | 897 | iwm->resp_ie_len = le16_to_cpu(mgt_frame->len) |
899 | iwm->resp_ie_len = | 898 | - offsetof(struct ieee80211_mgmt, |
900 | le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); | 899 | u.reassoc_resp.variable); |
901 | kfree(iwm->resp_ie); | 900 | kfree(iwm->resp_ie); |
902 | iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable, | 901 | iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable, |
903 | iwm->resp_ie_len, GFP_KERNEL); | 902 | iwm->resp_ie_len, GFP_KERNEL); |
@@ -1534,6 +1533,33 @@ static void classify8023(struct sk_buff *skb) | |||
1534 | } | 1533 | } |
1535 | } | 1534 | } |
1536 | 1535 | ||
1536 | static void iwm_rx_process_amsdu(struct iwm_priv *iwm, struct sk_buff *skb) | ||
1537 | { | ||
1538 | struct wireless_dev *wdev = iwm_to_wdev(iwm); | ||
1539 | struct net_device *ndev = iwm_to_ndev(iwm); | ||
1540 | struct sk_buff_head list; | ||
1541 | struct sk_buff *frame; | ||
1542 | |||
1543 | IWM_HEXDUMP(iwm, DBG, RX, "A-MSDU: ", skb->data, skb->len); | ||
1544 | |||
1545 | __skb_queue_head_init(&list); | ||
1546 | ieee80211_amsdu_to_8023s(skb, &list, ndev->dev_addr, wdev->iftype, 0); | ||
1547 | |||
1548 | while ((frame = __skb_dequeue(&list))) { | ||
1549 | ndev->stats.rx_packets++; | ||
1550 | ndev->stats.rx_bytes += frame->len; | ||
1551 | |||
1552 | frame->protocol = eth_type_trans(frame, ndev); | ||
1553 | frame->ip_summed = CHECKSUM_NONE; | ||
1554 | memset(frame->cb, 0, sizeof(frame->cb)); | ||
1555 | |||
1556 | if (netif_rx_ni(frame) == NET_RX_DROP) { | ||
1557 | IWM_ERR(iwm, "Packet dropped\n"); | ||
1558 | ndev->stats.rx_dropped++; | ||
1559 | } | ||
1560 | } | ||
1561 | } | ||
1562 | |||
1537 | static void iwm_rx_process_packet(struct iwm_priv *iwm, | 1563 | static void iwm_rx_process_packet(struct iwm_priv *iwm, |
1538 | struct iwm_rx_packet *packet, | 1564 | struct iwm_rx_packet *packet, |
1539 | struct iwm_rx_ticket_node *ticket_node) | 1565 | struct iwm_rx_ticket_node *ticket_node) |
@@ -1548,25 +1574,34 @@ static void iwm_rx_process_packet(struct iwm_priv *iwm, | |||
1548 | switch (le16_to_cpu(ticket_node->ticket->action)) { | 1574 | switch (le16_to_cpu(ticket_node->ticket->action)) { |
1549 | case IWM_RX_TICKET_RELEASE: | 1575 | case IWM_RX_TICKET_RELEASE: |
1550 | IWM_DBG_RX(iwm, DBG, "RELEASE packet\n"); | 1576 | IWM_DBG_RX(iwm, DBG, "RELEASE packet\n"); |
1551 | classify8023(skb); | 1577 | |
1552 | iwm_rx_adjust_packet(iwm, packet, ticket_node); | 1578 | iwm_rx_adjust_packet(iwm, packet, ticket_node); |
1579 | skb->dev = iwm_to_ndev(iwm); | ||
1580 | classify8023(skb); | ||
1581 | |||
1582 | if (le16_to_cpu(ticket_node->ticket->flags) & | ||
1583 | IWM_RX_TICKET_AMSDU_MSK) { | ||
1584 | iwm_rx_process_amsdu(iwm, skb); | ||
1585 | break; | ||
1586 | } | ||
1587 | |||
1553 | ret = ieee80211_data_to_8023(skb, ndev->dev_addr, wdev->iftype); | 1588 | ret = ieee80211_data_to_8023(skb, ndev->dev_addr, wdev->iftype); |
1554 | if (ret < 0) { | 1589 | if (ret < 0) { |
1555 | IWM_DBG_RX(iwm, DBG, "Couldn't convert 802.11 header - " | 1590 | IWM_DBG_RX(iwm, DBG, "Couldn't convert 802.11 header - " |
1556 | "%d\n", ret); | 1591 | "%d\n", ret); |
1592 | kfree_skb(packet->skb); | ||
1557 | break; | 1593 | break; |
1558 | } | 1594 | } |
1559 | 1595 | ||
1560 | IWM_HEXDUMP(iwm, DBG, RX, "802.3: ", skb->data, skb->len); | 1596 | IWM_HEXDUMP(iwm, DBG, RX, "802.3: ", skb->data, skb->len); |
1561 | 1597 | ||
1562 | skb->dev = iwm_to_ndev(iwm); | 1598 | ndev->stats.rx_packets++; |
1599 | ndev->stats.rx_bytes += skb->len; | ||
1600 | |||
1563 | skb->protocol = eth_type_trans(skb, ndev); | 1601 | skb->protocol = eth_type_trans(skb, ndev); |
1564 | skb->ip_summed = CHECKSUM_NONE; | 1602 | skb->ip_summed = CHECKSUM_NONE; |
1565 | memset(skb->cb, 0, sizeof(skb->cb)); | 1603 | memset(skb->cb, 0, sizeof(skb->cb)); |
1566 | 1604 | ||
1567 | ndev->stats.rx_packets++; | ||
1568 | ndev->stats.rx_bytes += skb->len; | ||
1569 | |||
1570 | if (netif_rx_ni(skb) == NET_RX_DROP) { | 1605 | if (netif_rx_ni(skb) == NET_RX_DROP) { |
1571 | IWM_ERR(iwm, "Packet dropped\n"); | 1606 | IWM_ERR(iwm, "Packet dropped\n"); |
1572 | ndev->stats.rx_dropped++; | 1607 | ndev->stats.rx_dropped++; |
diff --git a/drivers/net/wireless/libertas/Kconfig b/drivers/net/wireless/libertas/Kconfig index 30aa9d48d67e..0485c9957575 100644 --- a/drivers/net/wireless/libertas/Kconfig +++ b/drivers/net/wireless/libertas/Kconfig | |||
@@ -37,3 +37,9 @@ config LIBERTAS_DEBUG | |||
37 | depends on LIBERTAS | 37 | depends on LIBERTAS |
38 | ---help--- | 38 | ---help--- |
39 | Debugging support. | 39 | Debugging support. |
40 | |||
41 | config LIBERTAS_MESH | ||
42 | bool "Enable mesh support" | ||
43 | depends on LIBERTAS | ||
44 | help | ||
45 | This enables Libertas' MESH support, used by e.g. the OLPC people. | ||
diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile index b188cd97a053..45e870e33117 100644 --- a/drivers/net/wireless/libertas/Makefile +++ b/drivers/net/wireless/libertas/Makefile | |||
@@ -5,11 +5,11 @@ libertas-y += cmdresp.o | |||
5 | libertas-y += debugfs.o | 5 | libertas-y += debugfs.o |
6 | libertas-y += ethtool.o | 6 | libertas-y += ethtool.o |
7 | libertas-y += main.o | 7 | libertas-y += main.o |
8 | libertas-y += mesh.o | ||
9 | libertas-y += rx.o | 8 | libertas-y += rx.o |
10 | libertas-y += scan.o | 9 | libertas-y += scan.o |
11 | libertas-y += tx.o | 10 | libertas-y += tx.o |
12 | libertas-y += wext.o | 11 | libertas-y += wext.o |
12 | libertas-$(CONFIG_LIBERTAS_MESH) += mesh.o | ||
13 | 13 | ||
14 | usb8xxx-objs += if_usb.o | 14 | usb8xxx-objs += if_usb.o |
15 | libertas_cs-objs += if_cs.o | 15 | libertas_cs-objs += if_cs.o |
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index 751067369ba8..f03d5e4e59c3 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c | |||
@@ -390,10 +390,8 @@ int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv, | |||
390 | cmd.enablehwauto = cpu_to_le16(priv->enablehwauto); | 390 | cmd.enablehwauto = cpu_to_le16(priv->enablehwauto); |
391 | cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto); | 391 | cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto); |
392 | ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd); | 392 | ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd); |
393 | if (!ret && cmd_action == CMD_ACT_GET) { | 393 | if (!ret && cmd_action == CMD_ACT_GET) |
394 | priv->ratebitmap = le16_to_cpu(cmd.bitmap); | ||
395 | priv->enablehwauto = le16_to_cpu(cmd.enablehwauto); | 394 | priv->enablehwauto = le16_to_cpu(cmd.enablehwauto); |
396 | } | ||
397 | 395 | ||
398 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | 396 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); |
399 | return ret; | 397 | return ret; |
@@ -807,8 +805,7 @@ static int lbs_try_associate(struct lbs_private *priv, | |||
807 | } | 805 | } |
808 | 806 | ||
809 | /* Use short preamble only when both the BSS and firmware support it */ | 807 | /* Use short preamble only when both the BSS and firmware support it */ |
810 | if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && | 808 | if (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE) |
811 | (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) | ||
812 | preamble = RADIO_PREAMBLE_SHORT; | 809 | preamble = RADIO_PREAMBLE_SHORT; |
813 | 810 | ||
814 | ret = lbs_set_radio(priv, preamble, 1); | 811 | ret = lbs_set_radio(priv, preamble, 1); |
@@ -939,8 +936,7 @@ static int lbs_adhoc_join(struct lbs_private *priv, | |||
939 | } | 936 | } |
940 | 937 | ||
941 | /* Use short preamble only when both the BSS and firmware support it */ | 938 | /* Use short preamble only when both the BSS and firmware support it */ |
942 | if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && | 939 | if (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) { |
943 | (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) { | ||
944 | lbs_deb_join("AdhocJoin: Short preamble\n"); | 940 | lbs_deb_join("AdhocJoin: Short preamble\n"); |
945 | preamble = RADIO_PREAMBLE_SHORT; | 941 | preamble = RADIO_PREAMBLE_SHORT; |
946 | } | 942 | } |
@@ -1049,7 +1045,7 @@ static int lbs_adhoc_start(struct lbs_private *priv, | |||
1049 | struct assoc_request *assoc_req) | 1045 | struct assoc_request *assoc_req) |
1050 | { | 1046 | { |
1051 | struct cmd_ds_802_11_ad_hoc_start cmd; | 1047 | struct cmd_ds_802_11_ad_hoc_start cmd; |
1052 | u8 preamble = RADIO_PREAMBLE_LONG; | 1048 | u8 preamble = RADIO_PREAMBLE_SHORT; |
1053 | size_t ratesize = 0; | 1049 | size_t ratesize = 0; |
1054 | u16 tmpcap = 0; | 1050 | u16 tmpcap = 0; |
1055 | int ret = 0; | 1051 | int ret = 0; |
@@ -1057,11 +1053,6 @@ static int lbs_adhoc_start(struct lbs_private *priv, | |||
1057 | 1053 | ||
1058 | lbs_deb_enter(LBS_DEB_ASSOC); | 1054 | lbs_deb_enter(LBS_DEB_ASSOC); |
1059 | 1055 | ||
1060 | if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) { | ||
1061 | lbs_deb_join("ADHOC_START: Will use short preamble\n"); | ||
1062 | preamble = RADIO_PREAMBLE_SHORT; | ||
1063 | } | ||
1064 | |||
1065 | ret = lbs_set_radio(priv, preamble, 1); | 1056 | ret = lbs_set_radio(priv, preamble, 1); |
1066 | if (ret) | 1057 | if (ret) |
1067 | goto out; | 1058 | goto out; |
@@ -1169,11 +1160,11 @@ int lbs_adhoc_stop(struct lbs_private *priv) | |||
1169 | 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, |
1170 | struct bss_descriptor *match_bss) | 1161 | struct bss_descriptor *match_bss) |
1171 | { | 1162 | { |
1172 | if (!secinfo->wep_enabled && !secinfo->WPAenabled | 1163 | if (!secinfo->wep_enabled && |
1173 | && !secinfo->WPA2enabled | 1164 | !secinfo->WPAenabled && !secinfo->WPA2enabled && |
1174 | && match_bss->wpa_ie[0] != WLAN_EID_GENERIC | 1165 | match_bss->wpa_ie[0] != WLAN_EID_GENERIC && |
1175 | && match_bss->rsn_ie[0] != WLAN_EID_RSN | 1166 | match_bss->rsn_ie[0] != WLAN_EID_RSN && |
1176 | && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) | 1167 | !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) |
1177 | return 1; | 1168 | return 1; |
1178 | else | 1169 | else |
1179 | return 0; | 1170 | return 0; |
@@ -1182,9 +1173,9 @@ static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, | |||
1182 | 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, |
1183 | struct bss_descriptor *match_bss) | 1174 | struct bss_descriptor *match_bss) |
1184 | { | 1175 | { |
1185 | if (secinfo->wep_enabled && !secinfo->WPAenabled | 1176 | if (secinfo->wep_enabled && |
1186 | && !secinfo->WPA2enabled | 1177 | !secinfo->WPAenabled && !secinfo->WPA2enabled && |
1187 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) | 1178 | (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) |
1188 | return 1; | 1179 | return 1; |
1189 | else | 1180 | else |
1190 | return 0; | 1181 | return 0; |
@@ -1193,8 +1184,8 @@ static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo, | |||
1193 | 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, |
1194 | struct bss_descriptor *match_bss) | 1185 | struct bss_descriptor *match_bss) |
1195 | { | 1186 | { |
1196 | if (!secinfo->wep_enabled && secinfo->WPAenabled | 1187 | if (!secinfo->wep_enabled && secinfo->WPAenabled && |
1197 | && (match_bss->wpa_ie[0] == WLAN_EID_GENERIC) | 1188 | (match_bss->wpa_ie[0] == WLAN_EID_GENERIC) |
1198 | /* 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 |
1199 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ | 1190 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ |
1200 | ) | 1191 | ) |
@@ -1219,11 +1210,11 @@ static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo, | |||
1219 | 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, |
1220 | struct bss_descriptor *match_bss) | 1211 | struct bss_descriptor *match_bss) |
1221 | { | 1212 | { |
1222 | if (!secinfo->wep_enabled && !secinfo->WPAenabled | 1213 | if (!secinfo->wep_enabled && |
1223 | && !secinfo->WPA2enabled | 1214 | !secinfo->WPAenabled && !secinfo->WPA2enabled && |
1224 | && (match_bss->wpa_ie[0] != WLAN_EID_GENERIC) | 1215 | (match_bss->wpa_ie[0] != WLAN_EID_GENERIC) && |
1225 | && (match_bss->rsn_ie[0] != WLAN_EID_RSN) | 1216 | (match_bss->rsn_ie[0] != WLAN_EID_RSN) && |
1226 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) | 1217 | (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) |
1227 | return 1; | 1218 | return 1; |
1228 | else | 1219 | else |
1229 | return 0; | 1220 | return 0; |
@@ -1534,8 +1525,8 @@ static int assoc_helper_associate(struct lbs_private *priv, | |||
1534 | /* 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 */ |
1535 | 1526 | ||
1536 | if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { | 1527 | if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { |
1537 | if (compare_ether_addr(bssid_any, assoc_req->bssid) | 1528 | if (compare_ether_addr(bssid_any, assoc_req->bssid) && |
1538 | && compare_ether_addr(bssid_off, assoc_req->bssid)) { | 1529 | compare_ether_addr(bssid_off, assoc_req->bssid)) { |
1539 | ret = assoc_helper_bssid(priv, assoc_req); | 1530 | ret = assoc_helper_bssid(priv, assoc_req); |
1540 | done = 1; | 1531 | done = 1; |
1541 | } | 1532 | } |
@@ -1621,11 +1612,9 @@ static int assoc_helper_channel(struct lbs_private *priv, | |||
1621 | goto restore_mesh; | 1612 | goto restore_mesh; |
1622 | } | 1613 | } |
1623 | 1614 | ||
1624 | if ( assoc_req->secinfo.wep_enabled | 1615 | if (assoc_req->secinfo.wep_enabled && |
1625 | && (assoc_req->wep_keys[0].len | 1616 | (assoc_req->wep_keys[0].len || assoc_req->wep_keys[1].len || |
1626 | || assoc_req->wep_keys[1].len | 1617 | assoc_req->wep_keys[2].len || assoc_req->wep_keys[3].len)) { |
1627 | || assoc_req->wep_keys[2].len | ||
1628 | || assoc_req->wep_keys[3].len)) { | ||
1629 | /* Make sure WEP keys are re-sent to firmware */ | 1618 | /* Make sure WEP keys are re-sent to firmware */ |
1630 | set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); | 1619 | set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); |
1631 | } | 1620 | } |
@@ -1992,14 +1981,14 @@ void lbs_association_worker(struct work_struct *work) | |||
1992 | assoc_req->secinfo.auth_mode); | 1981 | assoc_req->secinfo.auth_mode); |
1993 | 1982 | ||
1994 | /* If 'any' SSID was specified, find an SSID to associate with */ | 1983 | /* If 'any' SSID was specified, find an SSID to associate with */ |
1995 | if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags) | 1984 | if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags) && |
1996 | && !assoc_req->ssid_len) | 1985 | !assoc_req->ssid_len) |
1997 | find_any_ssid = 1; | 1986 | find_any_ssid = 1; |
1998 | 1987 | ||
1999 | /* 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 */ |
2000 | if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { | 1989 | if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { |
2001 | if (compare_ether_addr(assoc_req->bssid, bssid_any) | 1990 | if (compare_ether_addr(assoc_req->bssid, bssid_any) && |
2002 | && compare_ether_addr(assoc_req->bssid, bssid_off)) | 1991 | compare_ether_addr(assoc_req->bssid, bssid_off)) |
2003 | find_any_ssid = 0; | 1992 | find_any_ssid = 0; |
2004 | } | 1993 | } |
2005 | 1994 | ||
@@ -2061,13 +2050,6 @@ void lbs_association_worker(struct work_struct *work) | |||
2061 | goto out; | 2050 | goto out; |
2062 | } | 2051 | } |
2063 | 2052 | ||
2064 | if ( test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags) | ||
2065 | || test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) { | ||
2066 | ret = assoc_helper_wep_keys(priv, assoc_req); | ||
2067 | if (ret) | ||
2068 | goto out; | ||
2069 | } | ||
2070 | |||
2071 | if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) { | 2053 | if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) { |
2072 | ret = assoc_helper_secinfo(priv, assoc_req); | 2054 | ret = assoc_helper_secinfo(priv, assoc_req); |
2073 | if (ret) | 2055 | if (ret) |
@@ -2080,18 +2062,31 @@ void lbs_association_worker(struct work_struct *work) | |||
2080 | goto out; | 2062 | goto out; |
2081 | } | 2063 | } |
2082 | 2064 | ||
2083 | if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags) | 2065 | /* |
2084 | || 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)) { | ||
2085 | ret = assoc_helper_wpa_keys(priv, assoc_req); | 2072 | ret = assoc_helper_wpa_keys(priv, assoc_req); |
2086 | if (ret) | 2073 | if (ret) |
2087 | goto out; | 2074 | goto out; |
2088 | } | 2075 | } |
2089 | 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 | |||
2090 | /* SSID/BSSID should be the _last_ config option set, because they | 2085 | /* SSID/BSSID should be the _last_ config option set, because they |
2091 | * trigger the association attempt. | 2086 | * trigger the association attempt. |
2092 | */ | 2087 | */ |
2093 | if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags) | 2088 | if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags) || |
2094 | || test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { | 2089 | test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { |
2095 | int success = 1; | 2090 | int success = 1; |
2096 | 2091 | ||
2097 | ret = assoc_helper_associate(priv, assoc_req); | 2092 | ret = assoc_helper_associate(priv, assoc_req); |
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index b9b371bfa30f..42051f7cad6d 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c | |||
@@ -143,19 +143,6 @@ int lbs_update_hw_spec(struct lbs_private *priv) | |||
143 | lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n", | 143 | lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n", |
144 | cmd.hwifversion, cmd.version); | 144 | cmd.hwifversion, cmd.version); |
145 | 145 | ||
146 | /* Determine mesh_fw_ver from fwrelease and fwcapinfo */ | ||
147 | /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */ | ||
148 | /* 5.110.22 have mesh command with 0xa3 command id */ | ||
149 | /* 10.0.0.p0 FW brings in mesh config command with different id */ | ||
150 | /* Check FW version MSB and initialize mesh_fw_ver */ | ||
151 | if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) | ||
152 | priv->mesh_fw_ver = MESH_FW_OLD; | ||
153 | else if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && | ||
154 | (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) | ||
155 | priv->mesh_fw_ver = MESH_FW_NEW; | ||
156 | else | ||
157 | priv->mesh_fw_ver = MESH_NONE; | ||
158 | |||
159 | /* Clamp region code to 8-bit since FW spec indicates that it should | 146 | /* Clamp region code to 8-bit since FW spec indicates that it should |
160 | * only ever be 8-bit, even though the field size is 16-bit. Some firmware | 147 | * only ever be 8-bit, even though the field size is 16-bit. Some firmware |
161 | * returns non-zero high 8 bits here. | 148 | * returns non-zero high 8 bits here. |
@@ -855,9 +842,6 @@ int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on) | |||
855 | if (priv->fwrelease < 0x09000000) { | 842 | if (priv->fwrelease < 0x09000000) { |
856 | switch (preamble) { | 843 | switch (preamble) { |
857 | case RADIO_PREAMBLE_SHORT: | 844 | case RADIO_PREAMBLE_SHORT: |
858 | if (!(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) | ||
859 | goto out; | ||
860 | /* Fall through */ | ||
861 | case RADIO_PREAMBLE_AUTO: | 845 | case RADIO_PREAMBLE_AUTO: |
862 | case RADIO_PREAMBLE_LONG: | 846 | case RADIO_PREAMBLE_LONG: |
863 | cmd.control = cpu_to_le16(preamble); | 847 | cmd.control = cpu_to_le16(preamble); |
@@ -1011,6 +995,8 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1011 | ret = 0; | 995 | ret = 0; |
1012 | break; | 996 | break; |
1013 | 997 | ||
998 | #ifdef CONFIG_LIBERTAS_MESH | ||
999 | |||
1014 | case CMD_BT_ACCESS: | 1000 | case CMD_BT_ACCESS: |
1015 | ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf); | 1001 | ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf); |
1016 | break; | 1002 | break; |
@@ -1019,6 +1005,8 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1019 | ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf); | 1005 | ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf); |
1020 | break; | 1006 | break; |
1021 | 1007 | ||
1008 | #endif | ||
1009 | |||
1022 | case CMD_802_11_BEACON_CTRL: | 1010 | case CMD_802_11_BEACON_CTRL: |
1023 | ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); | 1011 | ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); |
1024 | break; | 1012 | break; |
@@ -1317,7 +1305,7 @@ int lbs_execute_next_command(struct lbs_private *priv) | |||
1317 | if ((priv->psmode != LBS802_11POWERMODECAM) && | 1305 | if ((priv->psmode != LBS802_11POWERMODECAM) && |
1318 | (priv->psstate == PS_STATE_FULL_POWER) && | 1306 | (priv->psstate == PS_STATE_FULL_POWER) && |
1319 | ((priv->connect_status == LBS_CONNECTED) || | 1307 | ((priv->connect_status == LBS_CONNECTED) || |
1320 | (priv->mesh_connect_status == LBS_CONNECTED))) { | 1308 | lbs_mesh_connected(priv))) { |
1321 | if (priv->secinfo.WPAenabled || | 1309 | if (priv->secinfo.WPAenabled || |
1322 | priv->secinfo.WPA2enabled) { | 1310 | priv->secinfo.WPA2enabled) { |
1323 | /* check for valid WPA group keys */ | 1311 | /* check for valid WPA group keys */ |
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h index 2862748aef70..cb4138a55fdf 100644 --- a/drivers/net/wireless/libertas/cmd.h +++ b/drivers/net/wireless/libertas/cmd.h | |||
@@ -110,18 +110,6 @@ int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val); | |||
110 | int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val); | 110 | int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val); |
111 | 111 | ||
112 | 112 | ||
113 | /* Mesh related */ | ||
114 | |||
115 | int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, | ||
116 | struct cmd_ds_mesh_access *cmd); | ||
117 | |||
118 | int lbs_mesh_config_send(struct lbs_private *priv, | ||
119 | struct cmd_ds_mesh_config *cmd, | ||
120 | uint16_t action, uint16_t type); | ||
121 | |||
122 | int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan); | ||
123 | |||
124 | |||
125 | /* Commands only used in wext.c, assoc. and scan.c */ | 113 | /* Commands only used in wext.c, assoc. and scan.c */ |
126 | 114 | ||
127 | int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, | 115 | int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, |
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 21d57690c20a..e7470442f76b 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c | |||
@@ -240,11 +240,6 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) | |||
240 | /* Now we got response from FW, cancel the command timer */ | 240 | /* Now we got response from FW, cancel the command timer */ |
241 | del_timer(&priv->command_timer); | 241 | del_timer(&priv->command_timer); |
242 | priv->cmd_timed_out = 0; | 242 | priv->cmd_timed_out = 0; |
243 | if (priv->nr_retries) { | ||
244 | lbs_pr_info("Received result %x to command %x after %d retries\n", | ||
245 | result, curcmd, priv->nr_retries); | ||
246 | priv->nr_retries = 0; | ||
247 | } | ||
248 | 243 | ||
249 | /* Store the response code to cur_cmd_retcode. */ | 244 | /* Store the response code to cur_cmd_retcode. */ |
250 | priv->cur_cmd_retcode = result; | 245 | priv->cur_cmd_retcode = result; |
@@ -485,20 +480,8 @@ int lbs_process_event(struct lbs_private *priv, u32 event) | |||
485 | break; | 480 | break; |
486 | 481 | ||
487 | case MACREG_INT_CODE_MESH_AUTO_STARTED: | 482 | case MACREG_INT_CODE_MESH_AUTO_STARTED: |
488 | /* Ignore spurious autostart events if autostart is disabled */ | 483 | /* Ignore spurious autostart events */ |
489 | if (!priv->mesh_autostart_enabled) { | 484 | lbs_pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n"); |
490 | lbs_pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n"); | ||
491 | break; | ||
492 | } | ||
493 | lbs_pr_info("EVENT: MESH_AUTO_STARTED\n"); | ||
494 | priv->mesh_connect_status = LBS_CONNECTED; | ||
495 | if (priv->mesh_open) { | ||
496 | netif_carrier_on(priv->mesh_dev); | ||
497 | if (!priv->tx_pending_len) | ||
498 | netif_wake_queue(priv->mesh_dev); | ||
499 | } | ||
500 | priv->mode = IW_MODE_ADHOC; | ||
501 | schedule_work(&priv->sync_channel); | ||
502 | break; | 485 | break; |
503 | 486 | ||
504 | default: | 487 | default: |
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index 6b6ea9f7bf5b..ea3f10ef4e00 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h | |||
@@ -397,13 +397,6 @@ enum KEY_INFO_WPA { | |||
397 | KEY_INFO_WPA_ENABLED = 0x04 | 397 | KEY_INFO_WPA_ENABLED = 0x04 |
398 | }; | 398 | }; |
399 | 399 | ||
400 | /** mesh_fw_ver */ | ||
401 | enum _mesh_fw_ver { | ||
402 | MESH_NONE = 0, /* MESH is not supported */ | ||
403 | MESH_FW_OLD, /* MESH is supported in FW V5 */ | ||
404 | MESH_FW_NEW, /* MESH is supported in FW V10 and newer */ | ||
405 | }; | ||
406 | |||
407 | /* Default values for fwt commands. */ | 400 | /* Default values for fwt commands. */ |
408 | #define FWT_DEFAULT_METRIC 0 | 401 | #define FWT_DEFAULT_METRIC 0 |
409 | #define FWT_DEFAULT_DIR 1 | 402 | #define FWT_DEFAULT_DIR 1 |
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 6a8d2b291d8c..efb2519d9d74 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -39,15 +39,14 @@ struct lbs_private { | |||
39 | 39 | ||
40 | /* Mesh */ | 40 | /* Mesh */ |
41 | struct net_device *mesh_dev; /* Virtual device */ | 41 | struct net_device *mesh_dev; /* Virtual device */ |
42 | #ifdef CONFIG_LIBERTAS_MESH | ||
42 | u32 mesh_connect_status; | 43 | u32 mesh_connect_status; |
43 | struct lbs_mesh_stats mstats; | 44 | struct lbs_mesh_stats mstats; |
44 | int mesh_open; | 45 | int mesh_open; |
45 | int mesh_fw_ver; | ||
46 | int mesh_autostart_enabled; | ||
47 | uint16_t mesh_tlv; | 46 | uint16_t mesh_tlv; |
48 | u8 mesh_ssid[IEEE80211_MAX_SSID_LEN + 1]; | 47 | u8 mesh_ssid[IEEE80211_MAX_SSID_LEN + 1]; |
49 | u8 mesh_ssid_len; | 48 | u8 mesh_ssid_len; |
50 | struct work_struct sync_channel; | 49 | #endif |
51 | 50 | ||
52 | /* Monitor mode */ | 51 | /* Monitor mode */ |
53 | struct net_device *rtap_net_dev; | 52 | struct net_device *rtap_net_dev; |
@@ -110,7 +109,6 @@ struct lbs_private { | |||
110 | struct list_head cmdpendingq; /* pending command buffers */ | 109 | struct list_head cmdpendingq; /* pending command buffers */ |
111 | wait_queue_head_t cmd_pending; | 110 | wait_queue_head_t cmd_pending; |
112 | struct timer_list command_timer; | 111 | struct timer_list command_timer; |
113 | int nr_retries; | ||
114 | int cmd_timed_out; | 112 | int cmd_timed_out; |
115 | 113 | ||
116 | /* Command responses sent from the hardware to the driver */ | 114 | /* Command responses sent from the hardware to the driver */ |
@@ -176,9 +174,7 @@ struct lbs_private { | |||
176 | struct bss_descriptor *networks; | 174 | struct bss_descriptor *networks; |
177 | struct assoc_request * pending_assoc_req; | 175 | struct assoc_request * pending_assoc_req; |
178 | struct assoc_request * in_progress_assoc_req; | 176 | struct assoc_request * in_progress_assoc_req; |
179 | u16 capability; | ||
180 | uint16_t enablehwauto; | 177 | uint16_t enablehwauto; |
181 | uint16_t ratebitmap; | ||
182 | 178 | ||
183 | /* ADHOC */ | 179 | /* ADHOC */ |
184 | u16 beacon_period; | 180 | u16 beacon_period; |
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c index 63d020374c2b..3804a58d7f4e 100644 --- a/drivers/net/wireless/libertas/ethtool.c +++ b/drivers/net/wireless/libertas/ethtool.c | |||
@@ -114,9 +114,11 @@ const struct ethtool_ops lbs_ethtool_ops = { | |||
114 | .get_drvinfo = lbs_ethtool_get_drvinfo, | 114 | .get_drvinfo = lbs_ethtool_get_drvinfo, |
115 | .get_eeprom = lbs_ethtool_get_eeprom, | 115 | .get_eeprom = lbs_ethtool_get_eeprom, |
116 | .get_eeprom_len = lbs_ethtool_get_eeprom_len, | 116 | .get_eeprom_len = lbs_ethtool_get_eeprom_len, |
117 | #ifdef CONFIG_LIBERTAS_MESH | ||
117 | .get_sset_count = lbs_mesh_ethtool_get_sset_count, | 118 | .get_sset_count = lbs_mesh_ethtool_get_sset_count, |
118 | .get_ethtool_stats = lbs_mesh_ethtool_get_stats, | 119 | .get_ethtool_stats = lbs_mesh_ethtool_get_stats, |
119 | .get_strings = lbs_mesh_ethtool_get_strings, | 120 | .get_strings = lbs_mesh_ethtool_get_strings, |
121 | #endif | ||
120 | .get_wol = lbs_ethtool_get_wol, | 122 | .get_wol = lbs_ethtool_get_wol, |
121 | .set_wol = lbs_ethtool_set_wol, | 123 | .set_wol = lbs_ethtool_set_wol, |
122 | }; | 124 | }; |
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index bf4bfbae6227..3ea03f259ee7 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/kthread.h> | 23 | #include <linux/kthread.h> |
24 | #include <linux/list.h> | 24 | #include <linux/list.h> |
25 | #include <linux/netdevice.h> | 25 | #include <linux/netdevice.h> |
26 | #include <linux/semaphore.h> | ||
26 | #include <linux/spi/libertas_spi.h> | 27 | #include <linux/spi/libertas_spi.h> |
27 | #include <linux/spi/spi.h> | 28 | #include <linux/spi/spi.h> |
28 | 29 | ||
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index db38a5a719fa..f5d641efd50a 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -123,7 +123,7 @@ static ssize_t lbs_rtap_set(struct device *dev, | |||
123 | if (priv->monitormode == monitor_mode) | 123 | if (priv->monitormode == monitor_mode) |
124 | return strlen(buf); | 124 | return strlen(buf); |
125 | if (!priv->monitormode) { | 125 | if (!priv->monitormode) { |
126 | if (priv->infra_open || priv->mesh_open) | 126 | if (priv->infra_open || lbs_mesh_open(priv)) |
127 | return -EBUSY; | 127 | return -EBUSY; |
128 | if (priv->mode == IW_MODE_INFRA) | 128 | if (priv->mode == IW_MODE_INFRA) |
129 | lbs_cmd_80211_deauthenticate(priv, | 129 | lbs_cmd_80211_deauthenticate(priv, |
@@ -533,31 +533,14 @@ static int lbs_thread(void *data) | |||
533 | if (priv->cmd_timed_out && priv->cur_cmd) { | 533 | if (priv->cmd_timed_out && priv->cur_cmd) { |
534 | struct cmd_ctrl_node *cmdnode = priv->cur_cmd; | 534 | struct cmd_ctrl_node *cmdnode = priv->cur_cmd; |
535 | 535 | ||
536 | if (++priv->nr_retries > 3) { | 536 | lbs_pr_info("Timeout submitting command 0x%04x\n", |
537 | lbs_pr_info("Excessive timeouts submitting " | 537 | le16_to_cpu(cmdnode->cmdbuf->command)); |
538 | "command 0x%04x\n", | 538 | lbs_complete_command(priv, cmdnode, -ETIMEDOUT); |
539 | le16_to_cpu(cmdnode->cmdbuf->command)); | 539 | if (priv->reset_card) |
540 | lbs_complete_command(priv, cmdnode, -ETIMEDOUT); | 540 | priv->reset_card(priv); |
541 | priv->nr_retries = 0; | ||
542 | if (priv->reset_card) | ||
543 | priv->reset_card(priv); | ||
544 | } else { | ||
545 | priv->cur_cmd = NULL; | ||
546 | priv->dnld_sent = DNLD_RES_RECEIVED; | ||
547 | lbs_pr_info("requeueing command 0x%04x due " | ||
548 | "to timeout (#%d)\n", | ||
549 | le16_to_cpu(cmdnode->cmdbuf->command), | ||
550 | priv->nr_retries); | ||
551 | |||
552 | /* Stick it back at the _top_ of the pending queue | ||
553 | for immediate resubmission */ | ||
554 | list_add(&cmdnode->list, &priv->cmdpendingq); | ||
555 | } | ||
556 | } | 541 | } |
557 | priv->cmd_timed_out = 0; | 542 | priv->cmd_timed_out = 0; |
558 | 543 | ||
559 | |||
560 | |||
561 | if (!priv->fw_ready) | 544 | if (!priv->fw_ready) |
562 | continue; | 545 | continue; |
563 | 546 | ||
@@ -619,7 +602,7 @@ static int lbs_thread(void *data) | |||
619 | if (priv->connect_status == LBS_CONNECTED) | 602 | if (priv->connect_status == LBS_CONNECTED) |
620 | netif_wake_queue(priv->dev); | 603 | netif_wake_queue(priv->dev); |
621 | if (priv->mesh_dev && | 604 | if (priv->mesh_dev && |
622 | priv->mesh_connect_status == LBS_CONNECTED) | 605 | lbs_mesh_connected(priv)) |
623 | netif_wake_queue(priv->mesh_dev); | 606 | netif_wake_queue(priv->mesh_dev); |
624 | } | 607 | } |
625 | } | 608 | } |
@@ -729,7 +712,7 @@ done: | |||
729 | * This function handles the timeout of command sending. | 712 | * This function handles the timeout of command sending. |
730 | * It will re-send the same command again. | 713 | * It will re-send the same command again. |
731 | */ | 714 | */ |
732 | static void command_timer_fn(unsigned long data) | 715 | static void lbs_cmd_timeout_handler(unsigned long data) |
733 | { | 716 | { |
734 | struct lbs_private *priv = (struct lbs_private *)data; | 717 | struct lbs_private *priv = (struct lbs_private *)data; |
735 | unsigned long flags; | 718 | unsigned long flags; |
@@ -806,18 +789,6 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv) | |||
806 | return 0; | 789 | return 0; |
807 | } | 790 | } |
808 | 791 | ||
809 | static void lbs_sync_channel_worker(struct work_struct *work) | ||
810 | { | ||
811 | struct lbs_private *priv = container_of(work, struct lbs_private, | ||
812 | sync_channel); | ||
813 | |||
814 | lbs_deb_enter(LBS_DEB_MAIN); | ||
815 | if (lbs_update_channel(priv)) | ||
816 | lbs_pr_info("Channel synchronization failed."); | ||
817 | lbs_deb_leave(LBS_DEB_MAIN); | ||
818 | } | ||
819 | |||
820 | |||
821 | static int lbs_init_adapter(struct lbs_private *priv) | 792 | static int lbs_init_adapter(struct lbs_private *priv) |
822 | { | 793 | { |
823 | size_t bufsize; | 794 | size_t bufsize; |
@@ -845,14 +816,12 @@ static int lbs_init_adapter(struct lbs_private *priv) | |||
845 | memset(priv->current_addr, 0xff, ETH_ALEN); | 816 | memset(priv->current_addr, 0xff, ETH_ALEN); |
846 | 817 | ||
847 | priv->connect_status = LBS_DISCONNECTED; | 818 | priv->connect_status = LBS_DISCONNECTED; |
848 | priv->mesh_connect_status = LBS_DISCONNECTED; | ||
849 | priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; | 819 | priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; |
850 | priv->mode = IW_MODE_INFRA; | 820 | priv->mode = IW_MODE_INFRA; |
851 | priv->channel = DEFAULT_AD_HOC_CHANNEL; | 821 | priv->channel = DEFAULT_AD_HOC_CHANNEL; |
852 | priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; | 822 | priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; |
853 | priv->radio_on = 1; | 823 | priv->radio_on = 1; |
854 | priv->enablehwauto = 1; | 824 | priv->enablehwauto = 1; |
855 | priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; | ||
856 | priv->psmode = LBS802_11POWERMODECAM; | 825 | priv->psmode = LBS802_11POWERMODECAM; |
857 | priv->psstate = PS_STATE_FULL_POWER; | 826 | priv->psstate = PS_STATE_FULL_POWER; |
858 | priv->is_deep_sleep = 0; | 827 | priv->is_deep_sleep = 0; |
@@ -862,7 +831,7 @@ static int lbs_init_adapter(struct lbs_private *priv) | |||
862 | 831 | ||
863 | mutex_init(&priv->lock); | 832 | mutex_init(&priv->lock); |
864 | 833 | ||
865 | setup_timer(&priv->command_timer, command_timer_fn, | 834 | setup_timer(&priv->command_timer, lbs_cmd_timeout_handler, |
866 | (unsigned long)priv); | 835 | (unsigned long)priv); |
867 | setup_timer(&priv->auto_deepsleep_timer, auto_deepsleep_timer_fn, | 836 | setup_timer(&priv->auto_deepsleep_timer, auto_deepsleep_timer_fn, |
868 | (unsigned long)priv); | 837 | (unsigned long)priv); |
@@ -997,11 +966,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | |||
997 | INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker); | 966 | INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker); |
998 | INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); | 967 | INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); |
999 | INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); | 968 | INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); |
1000 | INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker); | ||
1001 | |||
1002 | priv->mesh_open = 0; | ||
1003 | sprintf(priv->mesh_ssid, "mesh"); | ||
1004 | priv->mesh_ssid_len = 4; | ||
1005 | 969 | ||
1006 | priv->wol_criteria = 0xffffffff; | 970 | priv->wol_criteria = 0xffffffff; |
1007 | priv->wol_gpio = 0xff; | 971 | priv->wol_gpio = 0xff; |
@@ -1075,6 +1039,17 @@ void lbs_remove_card(struct lbs_private *priv) | |||
1075 | EXPORT_SYMBOL_GPL(lbs_remove_card); | 1039 | EXPORT_SYMBOL_GPL(lbs_remove_card); |
1076 | 1040 | ||
1077 | 1041 | ||
1042 | static int lbs_rtap_supported(struct lbs_private *priv) | ||
1043 | { | ||
1044 | if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) | ||
1045 | return 1; | ||
1046 | |||
1047 | /* newer firmware use a capability mask */ | ||
1048 | return ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && | ||
1049 | (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)); | ||
1050 | } | ||
1051 | |||
1052 | |||
1078 | int lbs_start_card(struct lbs_private *priv) | 1053 | int lbs_start_card(struct lbs_private *priv) |
1079 | { | 1054 | { |
1080 | struct net_device *dev = priv->dev; | 1055 | struct net_device *dev = priv->dev; |
@@ -1094,12 +1069,14 @@ int lbs_start_card(struct lbs_private *priv) | |||
1094 | 1069 | ||
1095 | lbs_update_channel(priv); | 1070 | lbs_update_channel(priv); |
1096 | 1071 | ||
1072 | lbs_init_mesh(priv); | ||
1073 | |||
1097 | /* | 1074 | /* |
1098 | * While rtap isn't related to mesh, only mesh-enabled | 1075 | * While rtap isn't related to mesh, only mesh-enabled |
1099 | * firmware implements the rtap functionality via | 1076 | * firmware implements the rtap functionality via |
1100 | * CMD_802_11_MONITOR_MODE. | 1077 | * CMD_802_11_MONITOR_MODE. |
1101 | */ | 1078 | */ |
1102 | if (lbs_init_mesh(priv)) { | 1079 | if (lbs_rtap_supported(priv)) { |
1103 | if (device_create_file(&dev->dev, &dev_attr_lbs_rtap)) | 1080 | if (device_create_file(&dev->dev, &dev_attr_lbs_rtap)) |
1104 | lbs_pr_err("cannot register lbs_rtap attribute\n"); | 1081 | lbs_pr_err("cannot register lbs_rtap attribute\n"); |
1105 | } | 1082 | } |
@@ -1133,7 +1110,9 @@ void lbs_stop_card(struct lbs_private *priv) | |||
1133 | netif_carrier_off(dev); | 1110 | netif_carrier_off(dev); |
1134 | 1111 | ||
1135 | lbs_debugfs_remove_one(priv); | 1112 | lbs_debugfs_remove_one(priv); |
1136 | if (lbs_deinit_mesh(priv)) | 1113 | lbs_deinit_mesh(priv); |
1114 | |||
1115 | if (lbs_rtap_supported(priv)) | ||
1137 | device_remove_file(&dev->dev, &dev_attr_lbs_rtap); | 1116 | device_remove_file(&dev->dev, &dev_attr_lbs_rtap); |
1138 | 1117 | ||
1139 | /* Delete the timeout of the currently processing command */ | 1118 | /* Delete the timeout of the currently processing command */ |
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c index 2f91c9b808af..954cd00f7452 100644 --- a/drivers/net/wireless/libertas/mesh.c +++ b/drivers/net/wireless/libertas/mesh.c | |||
@@ -1,4 +1,3 @@ | |||
1 | #include <linux/moduleparam.h> | ||
2 | #include <linux/delay.h> | 1 | #include <linux/delay.h> |
3 | #include <linux/etherdevice.h> | 2 | #include <linux/etherdevice.h> |
4 | #include <linux/netdevice.h> | 3 | #include <linux/netdevice.h> |
@@ -196,7 +195,14 @@ int lbs_init_mesh(struct lbs_private *priv) | |||
196 | 195 | ||
197 | lbs_deb_enter(LBS_DEB_MESH); | 196 | lbs_deb_enter(LBS_DEB_MESH); |
198 | 197 | ||
199 | if (priv->mesh_fw_ver == MESH_FW_OLD) { | 198 | priv->mesh_connect_status = LBS_DISCONNECTED; |
199 | |||
200 | /* Determine mesh_fw_ver from fwrelease and fwcapinfo */ | ||
201 | /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */ | ||
202 | /* 5.110.22 have mesh command with 0xa3 command id */ | ||
203 | /* 10.0.0.p0 FW brings in mesh config command with different id */ | ||
204 | /* Check FW version MSB and initialize mesh_fw_ver */ | ||
205 | if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) { | ||
200 | /* Enable mesh, if supported, and work out which TLV it uses. | 206 | /* Enable mesh, if supported, and work out which TLV it uses. |
201 | 0x100 + 291 is an unofficial value used in 5.110.20.pXX | 207 | 0x100 + 291 is an unofficial value used in 5.110.20.pXX |
202 | 0x100 + 37 is the official value used in 5.110.21.pXX | 208 | 0x100 + 37 is the official value used in 5.110.21.pXX |
@@ -218,7 +224,9 @@ int lbs_init_mesh(struct lbs_private *priv) | |||
218 | priv->channel)) | 224 | priv->channel)) |
219 | priv->mesh_tlv = 0; | 225 | priv->mesh_tlv = 0; |
220 | } | 226 | } |
221 | } else if (priv->mesh_fw_ver == MESH_FW_NEW) { | 227 | } else |
228 | if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && | ||
229 | (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) { | ||
222 | /* 10.0.0.pXX new firmwares should succeed with TLV | 230 | /* 10.0.0.pXX new firmwares should succeed with TLV |
223 | * 0x100+37; Do not invoke command with old TLV. | 231 | * 0x100+37; Do not invoke command with old TLV. |
224 | */ | 232 | */ |
@@ -227,7 +235,12 @@ int lbs_init_mesh(struct lbs_private *priv) | |||
227 | priv->channel)) | 235 | priv->channel)) |
228 | priv->mesh_tlv = 0; | 236 | priv->mesh_tlv = 0; |
229 | } | 237 | } |
238 | |||
239 | |||
230 | if (priv->mesh_tlv) { | 240 | if (priv->mesh_tlv) { |
241 | sprintf(priv->mesh_ssid, "mesh"); | ||
242 | priv->mesh_ssid_len = 4; | ||
243 | |||
231 | lbs_add_mesh(priv); | 244 | lbs_add_mesh(priv); |
232 | 245 | ||
233 | if (device_create_file(&dev->dev, &dev_attr_lbs_mesh)) | 246 | if (device_create_file(&dev->dev, &dev_attr_lbs_mesh)) |
@@ -416,10 +429,10 @@ struct net_device *lbs_mesh_set_dev(struct lbs_private *priv, | |||
416 | struct net_device *dev, struct rxpd *rxpd) | 429 | struct net_device *dev, struct rxpd *rxpd) |
417 | { | 430 | { |
418 | if (priv->mesh_dev) { | 431 | if (priv->mesh_dev) { |
419 | if (priv->mesh_fw_ver == MESH_FW_OLD) { | 432 | if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) { |
420 | if (rxpd->rx_control & RxPD_MESH_FRAME) | 433 | if (rxpd->rx_control & RxPD_MESH_FRAME) |
421 | dev = priv->mesh_dev; | 434 | dev = priv->mesh_dev; |
422 | } else if (priv->mesh_fw_ver == MESH_FW_NEW) { | 435 | } else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) { |
423 | if (rxpd->u.bss.bss_num == MESH_IFACE_ID) | 436 | if (rxpd->u.bss.bss_num == MESH_IFACE_ID) |
424 | dev = priv->mesh_dev; | 437 | dev = priv->mesh_dev; |
425 | } | 438 | } |
@@ -432,9 +445,9 @@ void lbs_mesh_set_txpd(struct lbs_private *priv, | |||
432 | struct net_device *dev, struct txpd *txpd) | 445 | struct net_device *dev, struct txpd *txpd) |
433 | { | 446 | { |
434 | if (dev == priv->mesh_dev) { | 447 | if (dev == priv->mesh_dev) { |
435 | if (priv->mesh_fw_ver == MESH_FW_OLD) | 448 | if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) |
436 | txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME); | 449 | txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME); |
437 | else if (priv->mesh_fw_ver == MESH_FW_NEW) | 450 | else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) |
438 | txpd->u.bss.bss_num = MESH_IFACE_ID; | 451 | txpd->u.bss.bss_num = MESH_IFACE_ID; |
439 | } | 452 | } |
440 | } | 453 | } |
@@ -538,7 +551,7 @@ static int __lbs_mesh_config_send(struct lbs_private *priv, | |||
538 | * Command id is 0xac for v10 FW along with mesh interface | 551 | * Command id is 0xac for v10 FW along with mesh interface |
539 | * id in bits 14-13-12. | 552 | * id in bits 14-13-12. |
540 | */ | 553 | */ |
541 | if (priv->mesh_fw_ver == MESH_FW_NEW) | 554 | if (priv->mesh_tlv == TLV_TYPE_MESH_ID) |
542 | command = CMD_MESH_CONFIG | | 555 | command = CMD_MESH_CONFIG | |
543 | (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET); | 556 | (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET); |
544 | 557 | ||
diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h index fea9b5d005fc..e2573303a328 100644 --- a/drivers/net/wireless/libertas/mesh.h +++ b/drivers/net/wireless/libertas/mesh.h | |||
@@ -9,6 +9,8 @@ | |||
9 | #include <net/lib80211.h> | 9 | #include <net/lib80211.h> |
10 | 10 | ||
11 | 11 | ||
12 | #ifdef CONFIG_LIBERTAS_MESH | ||
13 | |||
12 | /* Mesh statistics */ | 14 | /* Mesh statistics */ |
13 | struct lbs_mesh_stats { | 15 | struct lbs_mesh_stats { |
14 | u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */ | 16 | u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */ |
@@ -46,11 +48,20 @@ void lbs_mesh_set_txpd(struct lbs_private *priv, | |||
46 | /* Command handling */ | 48 | /* Command handling */ |
47 | 49 | ||
48 | struct cmd_ds_command; | 50 | struct cmd_ds_command; |
51 | struct cmd_ds_mesh_access; | ||
52 | struct cmd_ds_mesh_config; | ||
49 | 53 | ||
50 | int lbs_cmd_bt_access(struct cmd_ds_command *cmd, | 54 | int lbs_cmd_bt_access(struct cmd_ds_command *cmd, |
51 | u16 cmd_action, void *pdata_buf); | 55 | u16 cmd_action, void *pdata_buf); |
52 | int lbs_cmd_fwt_access(struct cmd_ds_command *cmd, | 56 | int lbs_cmd_fwt_access(struct cmd_ds_command *cmd, |
53 | u16 cmd_action, void *pdata_buf); | 57 | u16 cmd_action, void *pdata_buf); |
58 | int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, | ||
59 | struct cmd_ds_mesh_access *cmd); | ||
60 | int lbs_mesh_config_send(struct lbs_private *priv, | ||
61 | struct cmd_ds_mesh_config *cmd, | ||
62 | uint16_t action, uint16_t type); | ||
63 | int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan); | ||
64 | |||
54 | 65 | ||
55 | 66 | ||
56 | /* Persistent configuration */ | 67 | /* Persistent configuration */ |
@@ -75,4 +86,25 @@ void lbs_mesh_ethtool_get_strings(struct net_device *dev, | |||
75 | uint32_t stringset, uint8_t *s); | 86 | uint32_t stringset, uint8_t *s); |
76 | 87 | ||
77 | 88 | ||
89 | /* Accessors */ | ||
90 | |||
91 | #define lbs_mesh_open(priv) (priv->mesh_open) | ||
92 | #define lbs_mesh_connected(priv) (priv->mesh_connect_status == LBS_CONNECTED) | ||
93 | |||
94 | #else | ||
95 | |||
96 | #define lbs_init_mesh(priv) | ||
97 | #define lbs_deinit_mesh(priv) | ||
98 | #define lbs_add_mesh(priv) | ||
99 | #define lbs_remove_mesh(priv) | ||
100 | #define lbs_mesh_set_dev(priv, dev, rxpd) (dev) | ||
101 | #define lbs_mesh_set_txpd(priv, dev, txpd) | ||
102 | #define lbs_mesh_config(priv, enable, chan) | ||
103 | #define lbs_mesh_open(priv) (0) | ||
104 | #define lbs_mesh_connected(priv) (0) | ||
105 | |||
106 | #endif | ||
107 | |||
108 | |||
109 | |||
78 | #endif | 110 | #endif |
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index b0b1c7841500..220361e69cd3 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c | |||
@@ -635,7 +635,7 @@ out: | |||
635 | if (priv->connect_status == LBS_CONNECTED && !priv->tx_pending_len) | 635 | if (priv->connect_status == LBS_CONNECTED && !priv->tx_pending_len) |
636 | netif_wake_queue(priv->dev); | 636 | netif_wake_queue(priv->dev); |
637 | 637 | ||
638 | if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED) && | 638 | if (priv->mesh_dev && lbs_mesh_connected(priv) && |
639 | !priv->tx_pending_len) | 639 | !priv->tx_pending_len) |
640 | netif_wake_queue(priv->mesh_dev); | 640 | netif_wake_queue(priv->mesh_dev); |
641 | 641 | ||
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index 315d1ce286ca..52d244ea3d97 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c | |||
@@ -198,7 +198,7 @@ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count) | |||
198 | if (priv->connect_status == LBS_CONNECTED) | 198 | if (priv->connect_status == LBS_CONNECTED) |
199 | netif_wake_queue(priv->dev); | 199 | netif_wake_queue(priv->dev); |
200 | 200 | ||
201 | if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED)) | 201 | if (priv->mesh_dev && lbs_mesh_connected(priv)) |
202 | netif_wake_queue(priv->mesh_dev); | 202 | netif_wake_queue(priv->mesh_dev); |
203 | } | 203 | } |
204 | EXPORT_SYMBOL_GPL(lbs_send_tx_feedback); | 204 | EXPORT_SYMBOL_GPL(lbs_send_tx_feedback); |
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index 4b1aab593a84..71f88a08e090 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c | |||
@@ -192,7 +192,7 @@ static void copy_active_data_rates(struct lbs_private *priv, u8 *rates) | |||
192 | lbs_deb_enter(LBS_DEB_WEXT); | 192 | lbs_deb_enter(LBS_DEB_WEXT); |
193 | 193 | ||
194 | if ((priv->connect_status != LBS_CONNECTED) && | 194 | if ((priv->connect_status != LBS_CONNECTED) && |
195 | (priv->mesh_connect_status != LBS_CONNECTED)) | 195 | !lbs_mesh_connected(priv)) |
196 | memcpy(rates, lbs_bg_rates, MAX_RATES); | 196 | memcpy(rates, lbs_bg_rates, MAX_RATES); |
197 | else | 197 | else |
198 | memcpy(rates, priv->curbssparams.rates, MAX_RATES); | 198 | memcpy(rates, priv->curbssparams.rates, MAX_RATES); |
@@ -298,6 +298,7 @@ static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info, | |||
298 | return 0; | 298 | return 0; |
299 | } | 299 | } |
300 | 300 | ||
301 | #ifdef CONFIG_LIBERTAS_MESH | ||
301 | static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, | 302 | static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, |
302 | struct iw_point *dwrq, char *extra) | 303 | struct iw_point *dwrq, char *extra) |
303 | { | 304 | { |
@@ -307,7 +308,7 @@ static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, | |||
307 | 308 | ||
308 | /* Use nickname to indicate that mesh is on */ | 309 | /* Use nickname to indicate that mesh is on */ |
309 | 310 | ||
310 | if (priv->mesh_connect_status == LBS_CONNECTED) { | 311 | if (lbs_mesh_connected(priv)) { |
311 | strncpy(extra, "Mesh", 12); | 312 | strncpy(extra, "Mesh", 12); |
312 | extra[12] = '\0'; | 313 | extra[12] = '\0'; |
313 | dwrq->length = strlen(extra); | 314 | dwrq->length = strlen(extra); |
@@ -321,6 +322,7 @@ static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, | |||
321 | lbs_deb_leave(LBS_DEB_WEXT); | 322 | lbs_deb_leave(LBS_DEB_WEXT); |
322 | return 0; | 323 | return 0; |
323 | } | 324 | } |
325 | #endif | ||
324 | 326 | ||
325 | static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info, | 327 | static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info, |
326 | struct iw_param *vwrq, char *extra) | 328 | struct iw_param *vwrq, char *extra) |
@@ -422,6 +424,7 @@ static int lbs_get_mode(struct net_device *dev, | |||
422 | return 0; | 424 | return 0; |
423 | } | 425 | } |
424 | 426 | ||
427 | #ifdef CONFIG_LIBERTAS_MESH | ||
425 | static int mesh_wlan_get_mode(struct net_device *dev, | 428 | static int mesh_wlan_get_mode(struct net_device *dev, |
426 | struct iw_request_info *info, u32 * uwrq, | 429 | struct iw_request_info *info, u32 * uwrq, |
427 | char *extra) | 430 | char *extra) |
@@ -433,6 +436,7 @@ static int mesh_wlan_get_mode(struct net_device *dev, | |||
433 | lbs_deb_leave(LBS_DEB_WEXT); | 436 | lbs_deb_leave(LBS_DEB_WEXT); |
434 | return 0; | 437 | return 0; |
435 | } | 438 | } |
439 | #endif | ||
436 | 440 | ||
437 | static int lbs_get_txpow(struct net_device *dev, | 441 | static int lbs_get_txpow(struct net_device *dev, |
438 | struct iw_request_info *info, | 442 | struct iw_request_info *info, |
@@ -863,7 +867,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) | |||
863 | 867 | ||
864 | /* If we're not associated, all quality values are meaningless */ | 868 | /* If we're not associated, all quality values are meaningless */ |
865 | if ((priv->connect_status != LBS_CONNECTED) && | 869 | if ((priv->connect_status != LBS_CONNECTED) && |
866 | (priv->mesh_connect_status != LBS_CONNECTED)) | 870 | !lbs_mesh_connected(priv)) |
867 | goto out; | 871 | goto out; |
868 | 872 | ||
869 | /* Quality by RSSI */ | 873 | /* Quality by RSSI */ |
@@ -1010,6 +1014,7 @@ out: | |||
1010 | return ret; | 1014 | return ret; |
1011 | } | 1015 | } |
1012 | 1016 | ||
1017 | #ifdef CONFIG_LIBERTAS_MESH | ||
1013 | static int lbs_mesh_set_freq(struct net_device *dev, | 1018 | static int lbs_mesh_set_freq(struct net_device *dev, |
1014 | struct iw_request_info *info, | 1019 | struct iw_request_info *info, |
1015 | struct iw_freq *fwrq, char *extra) | 1020 | struct iw_freq *fwrq, char *extra) |
@@ -1061,6 +1066,7 @@ out: | |||
1061 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | 1066 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); |
1062 | return ret; | 1067 | return ret; |
1063 | } | 1068 | } |
1069 | #endif | ||
1064 | 1070 | ||
1065 | static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, | 1071 | static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, |
1066 | struct iw_param *vwrq, char *extra) | 1072 | struct iw_param *vwrq, char *extra) |
@@ -2108,6 +2114,7 @@ out: | |||
2108 | return ret; | 2114 | return ret; |
2109 | } | 2115 | } |
2110 | 2116 | ||
2117 | #ifdef CONFIG_LIBERTAS_MESH | ||
2111 | static int lbs_mesh_get_essid(struct net_device *dev, | 2118 | static int lbs_mesh_get_essid(struct net_device *dev, |
2112 | struct iw_request_info *info, | 2119 | struct iw_request_info *info, |
2113 | struct iw_point *dwrq, char *extra) | 2120 | struct iw_point *dwrq, char *extra) |
@@ -2161,6 +2168,7 @@ static int lbs_mesh_set_essid(struct net_device *dev, | |||
2161 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | 2168 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); |
2162 | return ret; | 2169 | return ret; |
2163 | } | 2170 | } |
2171 | #endif | ||
2164 | 2172 | ||
2165 | /** | 2173 | /** |
2166 | * @brief Connect to the AP or Ad-hoc Network with specific bssid | 2174 | * @brief Connect to the AP or Ad-hoc Network with specific bssid |
@@ -2267,7 +2275,13 @@ static const iw_handler lbs_handler[] = { | |||
2267 | (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */ | 2275 | (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */ |
2268 | (iw_handler) NULL, /* SIOCSIWPMKSA */ | 2276 | (iw_handler) NULL, /* SIOCSIWPMKSA */ |
2269 | }; | 2277 | }; |
2278 | struct iw_handler_def lbs_handler_def = { | ||
2279 | .num_standard = ARRAY_SIZE(lbs_handler), | ||
2280 | .standard = (iw_handler *) lbs_handler, | ||
2281 | .get_wireless_stats = lbs_get_wireless_stats, | ||
2282 | }; | ||
2270 | 2283 | ||
2284 | #ifdef CONFIG_LIBERTAS_MESH | ||
2271 | static const iw_handler mesh_wlan_handler[] = { | 2285 | static const iw_handler mesh_wlan_handler[] = { |
2272 | (iw_handler) NULL, /* SIOCSIWCOMMIT */ | 2286 | (iw_handler) NULL, /* SIOCSIWCOMMIT */ |
2273 | (iw_handler) lbs_get_name, /* SIOCGIWNAME */ | 2287 | (iw_handler) lbs_get_name, /* SIOCGIWNAME */ |
@@ -2325,14 +2339,10 @@ static const iw_handler mesh_wlan_handler[] = { | |||
2325 | (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */ | 2339 | (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */ |
2326 | (iw_handler) NULL, /* SIOCSIWPMKSA */ | 2340 | (iw_handler) NULL, /* SIOCSIWPMKSA */ |
2327 | }; | 2341 | }; |
2328 | struct iw_handler_def lbs_handler_def = { | ||
2329 | .num_standard = ARRAY_SIZE(lbs_handler), | ||
2330 | .standard = (iw_handler *) lbs_handler, | ||
2331 | .get_wireless_stats = lbs_get_wireless_stats, | ||
2332 | }; | ||
2333 | 2342 | ||
2334 | struct iw_handler_def mesh_handler_def = { | 2343 | struct iw_handler_def mesh_handler_def = { |
2335 | .num_standard = ARRAY_SIZE(mesh_wlan_handler), | 2344 | .num_standard = ARRAY_SIZE(mesh_wlan_handler), |
2336 | .standard = (iw_handler *) mesh_wlan_handler, | 2345 | .standard = (iw_handler *) mesh_wlan_handler, |
2337 | .get_wireless_stats = lbs_get_wireless_stats, | 2346 | .get_wireless_stats = lbs_get_wireless_stats, |
2338 | }; | 2347 | }; |
2348 | #endif | ||
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 26a1abd5bb03..6ab30033c26c 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c | |||
@@ -318,14 +318,14 @@ static void lbtf_op_stop(struct ieee80211_hw *hw) | |||
318 | } | 318 | } |
319 | 319 | ||
320 | static int lbtf_op_add_interface(struct ieee80211_hw *hw, | 320 | static int lbtf_op_add_interface(struct ieee80211_hw *hw, |
321 | struct ieee80211_if_init_conf *conf) | 321 | struct ieee80211_vif *vif) |
322 | { | 322 | { |
323 | struct lbtf_private *priv = hw->priv; | 323 | struct lbtf_private *priv = hw->priv; |
324 | if (priv->vif != NULL) | 324 | if (priv->vif != NULL) |
325 | return -EOPNOTSUPP; | 325 | return -EOPNOTSUPP; |
326 | 326 | ||
327 | priv->vif = conf->vif; | 327 | priv->vif = vif; |
328 | switch (conf->type) { | 328 | switch (vif->type) { |
329 | case NL80211_IFTYPE_MESH_POINT: | 329 | case NL80211_IFTYPE_MESH_POINT: |
330 | case NL80211_IFTYPE_AP: | 330 | case NL80211_IFTYPE_AP: |
331 | lbtf_set_mode(priv, LBTF_AP_MODE); | 331 | lbtf_set_mode(priv, LBTF_AP_MODE); |
@@ -337,12 +337,12 @@ static int lbtf_op_add_interface(struct ieee80211_hw *hw, | |||
337 | priv->vif = NULL; | 337 | priv->vif = NULL; |
338 | return -EOPNOTSUPP; | 338 | return -EOPNOTSUPP; |
339 | } | 339 | } |
340 | lbtf_set_mac_address(priv, (u8 *) conf->mac_addr); | 340 | lbtf_set_mac_address(priv, (u8 *) vif->addr); |
341 | return 0; | 341 | return 0; |
342 | } | 342 | } |
343 | 343 | ||
344 | static void lbtf_op_remove_interface(struct ieee80211_hw *hw, | 344 | static void lbtf_op_remove_interface(struct ieee80211_hw *hw, |
345 | struct ieee80211_if_init_conf *conf) | 345 | struct ieee80211_vif *vif) |
346 | { | 346 | { |
347 | struct lbtf_private *priv = hw->priv; | 347 | struct lbtf_private *priv = hw->priv; |
348 | 348 | ||
@@ -555,6 +555,9 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev) | |||
555 | priv->band.n_channels = ARRAY_SIZE(lbtf_channels); | 555 | priv->band.n_channels = ARRAY_SIZE(lbtf_channels); |
556 | priv->band.channels = priv->channels; | 556 | priv->band.channels = priv->channels; |
557 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; | 557 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; |
558 | hw->wiphy->interface_modes = | ||
559 | BIT(NL80211_IFTYPE_STATION) | | ||
560 | BIT(NL80211_IFTYPE_ADHOC); | ||
558 | skb_queue_head_init(&priv->bc_ps_buf); | 561 | skb_queue_head_init(&priv->bc_ps_buf); |
559 | 562 | ||
560 | SET_IEEE80211_DEV(hw, dmdev); | 563 | SET_IEEE80211_DEV(hw, dmdev); |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 88e41176e7fd..6ea77e95277b 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -32,6 +32,10 @@ static int radios = 2; | |||
32 | module_param(radios, int, 0444); | 32 | module_param(radios, int, 0444); |
33 | MODULE_PARM_DESC(radios, "Number of simulated radios"); | 33 | MODULE_PARM_DESC(radios, "Number of simulated radios"); |
34 | 34 | ||
35 | static bool fake_hw_scan; | ||
36 | module_param(fake_hw_scan, bool, 0444); | ||
37 | MODULE_PARM_DESC(fake_hw_scan, "Install fake (no-op) hw-scan handler"); | ||
38 | |||
35 | /** | 39 | /** |
36 | * enum hwsim_regtest - the type of regulatory tests we offer | 40 | * enum hwsim_regtest - the type of regulatory tests we offer |
37 | * | 41 | * |
@@ -281,6 +285,8 @@ struct mac80211_hwsim_data { | |||
281 | struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)]; | 285 | struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)]; |
282 | struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; | 286 | struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; |
283 | 287 | ||
288 | struct mac_address addresses[2]; | ||
289 | |||
284 | struct ieee80211_channel *channel; | 290 | struct ieee80211_channel *channel; |
285 | unsigned long beacon_int; /* in jiffies unit */ | 291 | unsigned long beacon_int; /* in jiffies unit */ |
286 | unsigned int rx_filter; | 292 | unsigned int rx_filter; |
@@ -436,6 +442,38 @@ static bool hwsim_ps_rx_ok(struct mac80211_hwsim_data *data, | |||
436 | } | 442 | } |
437 | 443 | ||
438 | 444 | ||
445 | struct mac80211_hwsim_addr_match_data { | ||
446 | bool ret; | ||
447 | const u8 *addr; | ||
448 | }; | ||
449 | |||
450 | static void mac80211_hwsim_addr_iter(void *data, u8 *mac, | ||
451 | struct ieee80211_vif *vif) | ||
452 | { | ||
453 | struct mac80211_hwsim_addr_match_data *md = data; | ||
454 | if (memcmp(mac, md->addr, ETH_ALEN) == 0) | ||
455 | md->ret = true; | ||
456 | } | ||
457 | |||
458 | |||
459 | static bool mac80211_hwsim_addr_match(struct mac80211_hwsim_data *data, | ||
460 | const u8 *addr) | ||
461 | { | ||
462 | struct mac80211_hwsim_addr_match_data md; | ||
463 | |||
464 | if (memcmp(addr, data->hw->wiphy->perm_addr, ETH_ALEN) == 0) | ||
465 | return true; | ||
466 | |||
467 | md.ret = false; | ||
468 | md.addr = addr; | ||
469 | ieee80211_iterate_active_interfaces_atomic(data->hw, | ||
470 | mac80211_hwsim_addr_iter, | ||
471 | &md); | ||
472 | |||
473 | return md.ret; | ||
474 | } | ||
475 | |||
476 | |||
439 | static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, | 477 | static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, |
440 | struct sk_buff *skb) | 478 | struct sk_buff *skb) |
441 | { | 479 | { |
@@ -488,8 +526,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, | |||
488 | if (nskb == NULL) | 526 | if (nskb == NULL) |
489 | continue; | 527 | continue; |
490 | 528 | ||
491 | if (memcmp(hdr->addr1, data2->hw->wiphy->perm_addr, | 529 | if (mac80211_hwsim_addr_match(data2, hdr->addr1)) |
492 | ETH_ALEN) == 0) | ||
493 | ack = true; | 530 | ack = true; |
494 | memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); | 531 | memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); |
495 | ieee80211_rx_irqsafe(data2->hw, nskb); | 532 | ieee80211_rx_irqsafe(data2->hw, nskb); |
@@ -553,24 +590,24 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw) | |||
553 | 590 | ||
554 | 591 | ||
555 | static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw, | 592 | static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw, |
556 | struct ieee80211_if_init_conf *conf) | 593 | struct ieee80211_vif *vif) |
557 | { | 594 | { |
558 | printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n", | 595 | printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n", |
559 | wiphy_name(hw->wiphy), __func__, conf->type, | 596 | wiphy_name(hw->wiphy), __func__, vif->type, |
560 | conf->mac_addr); | 597 | vif->addr); |
561 | hwsim_set_magic(conf->vif); | 598 | hwsim_set_magic(vif); |
562 | return 0; | 599 | return 0; |
563 | } | 600 | } |
564 | 601 | ||
565 | 602 | ||
566 | static void mac80211_hwsim_remove_interface( | 603 | static void mac80211_hwsim_remove_interface( |
567 | struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) | 604 | struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
568 | { | 605 | { |
569 | printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n", | 606 | printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n", |
570 | wiphy_name(hw->wiphy), __func__, conf->type, | 607 | wiphy_name(hw->wiphy), __func__, vif->type, |
571 | conf->mac_addr); | 608 | vif->addr); |
572 | hwsim_check_magic(conf->vif); | 609 | hwsim_check_magic(vif); |
573 | hwsim_clear_magic(conf->vif); | 610 | hwsim_clear_magic(vif); |
574 | } | 611 | } |
575 | 612 | ||
576 | 613 | ||
@@ -618,12 +655,26 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) | |||
618 | { | 655 | { |
619 | struct mac80211_hwsim_data *data = hw->priv; | 656 | struct mac80211_hwsim_data *data = hw->priv; |
620 | struct ieee80211_conf *conf = &hw->conf; | 657 | struct ieee80211_conf *conf = &hw->conf; |
621 | 658 | static const char *chantypes[4] = { | |
622 | printk(KERN_DEBUG "%s:%s (freq=%d idle=%d ps=%d)\n", | 659 | [NL80211_CHAN_NO_HT] = "noht", |
660 | [NL80211_CHAN_HT20] = "ht20", | ||
661 | [NL80211_CHAN_HT40MINUS] = "ht40-", | ||
662 | [NL80211_CHAN_HT40PLUS] = "ht40+", | ||
663 | }; | ||
664 | static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = { | ||
665 | [IEEE80211_SMPS_AUTOMATIC] = "auto", | ||
666 | [IEEE80211_SMPS_OFF] = "off", | ||
667 | [IEEE80211_SMPS_STATIC] = "static", | ||
668 | [IEEE80211_SMPS_DYNAMIC] = "dynamic", | ||
669 | }; | ||
670 | |||
671 | printk(KERN_DEBUG "%s:%s (freq=%d/%s idle=%d ps=%d smps=%s)\n", | ||
623 | wiphy_name(hw->wiphy), __func__, | 672 | wiphy_name(hw->wiphy), __func__, |
624 | conf->channel->center_freq, | 673 | conf->channel->center_freq, |
674 | chantypes[conf->channel_type], | ||
625 | !!(conf->flags & IEEE80211_CONF_IDLE), | 675 | !!(conf->flags & IEEE80211_CONF_IDLE), |
626 | !!(conf->flags & IEEE80211_CONF_PS)); | 676 | !!(conf->flags & IEEE80211_CONF_PS), |
677 | smps_modes[conf->smps_mode]); | ||
627 | 678 | ||
628 | data->idle = !!(conf->flags & IEEE80211_CONF_IDLE); | 679 | data->idle = !!(conf->flags & IEEE80211_CONF_IDLE); |
629 | 680 | ||
@@ -720,23 +771,41 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, | |||
720 | } | 771 | } |
721 | } | 772 | } |
722 | 773 | ||
774 | static int mac80211_hwsim_sta_add(struct ieee80211_hw *hw, | ||
775 | struct ieee80211_vif *vif, | ||
776 | struct ieee80211_sta *sta) | ||
777 | { | ||
778 | hwsim_check_magic(vif); | ||
779 | hwsim_set_sta_magic(sta); | ||
780 | |||
781 | return 0; | ||
782 | } | ||
783 | |||
784 | static int mac80211_hwsim_sta_remove(struct ieee80211_hw *hw, | ||
785 | struct ieee80211_vif *vif, | ||
786 | struct ieee80211_sta *sta) | ||
787 | { | ||
788 | hwsim_check_magic(vif); | ||
789 | hwsim_clear_sta_magic(sta); | ||
790 | |||
791 | return 0; | ||
792 | } | ||
793 | |||
723 | static void mac80211_hwsim_sta_notify(struct ieee80211_hw *hw, | 794 | static void mac80211_hwsim_sta_notify(struct ieee80211_hw *hw, |
724 | struct ieee80211_vif *vif, | 795 | struct ieee80211_vif *vif, |
725 | enum sta_notify_cmd cmd, | 796 | enum sta_notify_cmd cmd, |
726 | struct ieee80211_sta *sta) | 797 | struct ieee80211_sta *sta) |
727 | { | 798 | { |
728 | hwsim_check_magic(vif); | 799 | hwsim_check_magic(vif); |
800 | |||
729 | switch (cmd) { | 801 | switch (cmd) { |
730 | case STA_NOTIFY_ADD: | ||
731 | hwsim_set_sta_magic(sta); | ||
732 | break; | ||
733 | case STA_NOTIFY_REMOVE: | ||
734 | hwsim_clear_sta_magic(sta); | ||
735 | break; | ||
736 | case STA_NOTIFY_SLEEP: | 802 | case STA_NOTIFY_SLEEP: |
737 | case STA_NOTIFY_AWAKE: | 803 | case STA_NOTIFY_AWAKE: |
738 | /* TODO: make good use of these flags */ | 804 | /* TODO: make good use of these flags */ |
739 | break; | 805 | break; |
806 | default: | ||
807 | WARN(1, "Invalid sta notify: %d\n", cmd); | ||
808 | break; | ||
740 | } | 809 | } |
741 | } | 810 | } |
742 | 811 | ||
@@ -827,7 +896,77 @@ static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw, | |||
827 | } | 896 | } |
828 | #endif | 897 | #endif |
829 | 898 | ||
830 | static const struct ieee80211_ops mac80211_hwsim_ops = | 899 | static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw, |
900 | struct ieee80211_vif *vif, | ||
901 | enum ieee80211_ampdu_mlme_action action, | ||
902 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | ||
903 | { | ||
904 | switch (action) { | ||
905 | case IEEE80211_AMPDU_TX_START: | ||
906 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
907 | break; | ||
908 | case IEEE80211_AMPDU_TX_STOP: | ||
909 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
910 | break; | ||
911 | case IEEE80211_AMPDU_TX_OPERATIONAL: | ||
912 | break; | ||
913 | case IEEE80211_AMPDU_RX_START: | ||
914 | case IEEE80211_AMPDU_RX_STOP: | ||
915 | break; | ||
916 | default: | ||
917 | return -EOPNOTSUPP; | ||
918 | } | ||
919 | |||
920 | return 0; | ||
921 | } | ||
922 | |||
923 | static void mac80211_hwsim_flush(struct ieee80211_hw *hw, bool drop) | ||
924 | { | ||
925 | /* | ||
926 | * In this special case, there's nothing we need to | ||
927 | * do because hwsim does transmission synchronously. | ||
928 | * In the future, when it does transmissions via | ||
929 | * userspace, we may need to do something. | ||
930 | */ | ||
931 | } | ||
932 | |||
933 | struct hw_scan_done { | ||
934 | struct delayed_work w; | ||
935 | struct ieee80211_hw *hw; | ||
936 | }; | ||
937 | |||
938 | static void hw_scan_done(struct work_struct *work) | ||
939 | { | ||
940 | struct hw_scan_done *hsd = | ||
941 | container_of(work, struct hw_scan_done, w.work); | ||
942 | |||
943 | ieee80211_scan_completed(hsd->hw, false); | ||
944 | kfree(hsd); | ||
945 | } | ||
946 | |||
947 | static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, | ||
948 | struct cfg80211_scan_request *req) | ||
949 | { | ||
950 | struct hw_scan_done *hsd = kzalloc(sizeof(*hsd), GFP_KERNEL); | ||
951 | int i; | ||
952 | |||
953 | if (!hsd) | ||
954 | return -ENOMEM; | ||
955 | |||
956 | hsd->hw = hw; | ||
957 | INIT_DELAYED_WORK(&hsd->w, hw_scan_done); | ||
958 | |||
959 | printk(KERN_DEBUG "hwsim scan request\n"); | ||
960 | for (i = 0; i < req->n_channels; i++) | ||
961 | printk(KERN_DEBUG "hwsim scan freq %d\n", | ||
962 | req->channels[i]->center_freq); | ||
963 | |||
964 | ieee80211_queue_delayed_work(hw, &hsd->w, 2 * HZ); | ||
965 | |||
966 | return 0; | ||
967 | } | ||
968 | |||
969 | static struct ieee80211_ops mac80211_hwsim_ops = | ||
831 | { | 970 | { |
832 | .tx = mac80211_hwsim_tx, | 971 | .tx = mac80211_hwsim_tx, |
833 | .start = mac80211_hwsim_start, | 972 | .start = mac80211_hwsim_start, |
@@ -837,10 +976,14 @@ static const struct ieee80211_ops mac80211_hwsim_ops = | |||
837 | .config = mac80211_hwsim_config, | 976 | .config = mac80211_hwsim_config, |
838 | .configure_filter = mac80211_hwsim_configure_filter, | 977 | .configure_filter = mac80211_hwsim_configure_filter, |
839 | .bss_info_changed = mac80211_hwsim_bss_info_changed, | 978 | .bss_info_changed = mac80211_hwsim_bss_info_changed, |
979 | .sta_add = mac80211_hwsim_sta_add, | ||
980 | .sta_remove = mac80211_hwsim_sta_remove, | ||
840 | .sta_notify = mac80211_hwsim_sta_notify, | 981 | .sta_notify = mac80211_hwsim_sta_notify, |
841 | .set_tim = mac80211_hwsim_set_tim, | 982 | .set_tim = mac80211_hwsim_set_tim, |
842 | .conf_tx = mac80211_hwsim_conf_tx, | 983 | .conf_tx = mac80211_hwsim_conf_tx, |
843 | CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) | 984 | CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) |
985 | .ampdu_action = mac80211_hwsim_ampdu_action, | ||
986 | .flush = mac80211_hwsim_flush, | ||
844 | }; | 987 | }; |
845 | 988 | ||
846 | 989 | ||
@@ -1035,6 +1178,9 @@ static int __init init_mac80211_hwsim(void) | |||
1035 | if (radios < 1 || radios > 100) | 1178 | if (radios < 1 || radios > 100) |
1036 | return -EINVAL; | 1179 | return -EINVAL; |
1037 | 1180 | ||
1181 | if (fake_hw_scan) | ||
1182 | mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan; | ||
1183 | |||
1038 | spin_lock_init(&hwsim_radio_lock); | 1184 | spin_lock_init(&hwsim_radio_lock); |
1039 | INIT_LIST_HEAD(&hwsim_radios); | 1185 | INIT_LIST_HEAD(&hwsim_radios); |
1040 | 1186 | ||
@@ -1072,7 +1218,11 @@ static int __init init_mac80211_hwsim(void) | |||
1072 | SET_IEEE80211_DEV(hw, data->dev); | 1218 | SET_IEEE80211_DEV(hw, data->dev); |
1073 | addr[3] = i >> 8; | 1219 | addr[3] = i >> 8; |
1074 | addr[4] = i; | 1220 | addr[4] = i; |
1075 | SET_IEEE80211_PERM_ADDR(hw, addr); | 1221 | memcpy(data->addresses[0].addr, addr, ETH_ALEN); |
1222 | memcpy(data->addresses[1].addr, addr, ETH_ALEN); | ||
1223 | data->addresses[1].addr[0] |= 0x40; | ||
1224 | hw->wiphy->n_addresses = 2; | ||
1225 | hw->wiphy->addresses = data->addresses; | ||
1076 | 1226 | ||
1077 | hw->channel_change_time = 1; | 1227 | hw->channel_change_time = 1; |
1078 | hw->queues = 4; | 1228 | hw->queues = 4; |
@@ -1082,7 +1232,9 @@ static int __init init_mac80211_hwsim(void) | |||
1082 | BIT(NL80211_IFTYPE_MESH_POINT); | 1232 | BIT(NL80211_IFTYPE_MESH_POINT); |
1083 | 1233 | ||
1084 | hw->flags = IEEE80211_HW_MFP_CAPABLE | | 1234 | hw->flags = IEEE80211_HW_MFP_CAPABLE | |
1085 | IEEE80211_HW_SIGNAL_DBM; | 1235 | IEEE80211_HW_SIGNAL_DBM | |
1236 | IEEE80211_HW_SUPPORTS_STATIC_SMPS | | ||
1237 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS; | ||
1086 | 1238 | ||
1087 | /* ask mac80211 to reserve space for magic */ | 1239 | /* ask mac80211 to reserve space for magic */ |
1088 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); | 1240 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 59f92105b0c2..ac65e13eb0de 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * drivers/net/wireless/mwl8k.c | 2 | * drivers/net/wireless/mwl8k.c |
3 | * Driver for Marvell TOPDOG 802.11 Wireless cards | 3 | * Driver for Marvell TOPDOG 802.11 Wireless cards |
4 | * | 4 | * |
5 | * Copyright (C) 2008-2009 Marvell Semiconductor Inc. | 5 | * Copyright (C) 2008, 2009, 2010 Marvell Semiconductor Inc. |
6 | * | 6 | * |
7 | * This file is licensed under the terms of the GNU General Public | 7 | * This file is licensed under the terms of the GNU General Public |
8 | * License version 2. This program is licensed "as is" without any | 8 | * License version 2. This program is licensed "as is" without any |
@@ -26,7 +26,7 @@ | |||
26 | 26 | ||
27 | #define MWL8K_DESC "Marvell TOPDOG(R) 802.11 Wireless Network Driver" | 27 | #define MWL8K_DESC "Marvell TOPDOG(R) 802.11 Wireless Network Driver" |
28 | #define MWL8K_NAME KBUILD_MODNAME | 28 | #define MWL8K_NAME KBUILD_MODNAME |
29 | #define MWL8K_VERSION "0.10" | 29 | #define MWL8K_VERSION "0.12" |
30 | 30 | ||
31 | /* Register definitions */ | 31 | /* Register definitions */ |
32 | #define MWL8K_HIU_GEN_PTR 0x00000c10 | 32 | #define MWL8K_HIU_GEN_PTR 0x00000c10 |
@@ -92,8 +92,7 @@ struct mwl8k_device_info { | |||
92 | char *part_name; | 92 | char *part_name; |
93 | char *helper_image; | 93 | char *helper_image; |
94 | char *fw_image; | 94 | char *fw_image; |
95 | struct rxd_ops *rxd_ops; | 95 | struct rxd_ops *ap_rxd_ops; |
96 | u16 modes; | ||
97 | }; | 96 | }; |
98 | 97 | ||
99 | struct mwl8k_rx_queue { | 98 | struct mwl8k_rx_queue { |
@@ -120,34 +119,36 @@ struct mwl8k_tx_queue { | |||
120 | /* sw appends here */ | 119 | /* sw appends here */ |
121 | int tail; | 120 | int tail; |
122 | 121 | ||
123 | struct ieee80211_tx_queue_stats stats; | 122 | unsigned int len; |
124 | struct mwl8k_tx_desc *txd; | 123 | struct mwl8k_tx_desc *txd; |
125 | dma_addr_t txd_dma; | 124 | dma_addr_t txd_dma; |
126 | struct sk_buff **skb; | 125 | struct sk_buff **skb; |
127 | }; | 126 | }; |
128 | 127 | ||
129 | /* Pointers to the firmware data and meta information about it. */ | 128 | struct mwl8k_priv { |
130 | struct mwl8k_firmware { | 129 | struct ieee80211_hw *hw; |
131 | /* Boot helper code */ | 130 | struct pci_dev *pdev; |
132 | struct firmware *helper; | ||
133 | 131 | ||
134 | /* Microcode */ | 132 | struct mwl8k_device_info *device_info; |
135 | struct firmware *ucode; | ||
136 | }; | ||
137 | 133 | ||
138 | struct mwl8k_priv { | ||
139 | void __iomem *sram; | 134 | void __iomem *sram; |
140 | void __iomem *regs; | 135 | void __iomem *regs; |
141 | struct ieee80211_hw *hw; | ||
142 | 136 | ||
143 | struct pci_dev *pdev; | 137 | /* firmware */ |
138 | struct firmware *fw_helper; | ||
139 | struct firmware *fw_ucode; | ||
144 | 140 | ||
145 | struct mwl8k_device_info *device_info; | 141 | /* hardware/firmware parameters */ |
146 | bool ap_fw; | 142 | bool ap_fw; |
147 | struct rxd_ops *rxd_ops; | 143 | struct rxd_ops *rxd_ops; |
148 | 144 | struct ieee80211_supported_band band_24; | |
149 | /* firmware files and meta data */ | 145 | struct ieee80211_channel channels_24[14]; |
150 | struct mwl8k_firmware fw; | 146 | struct ieee80211_rate rates_24[14]; |
147 | struct ieee80211_supported_band band_50; | ||
148 | struct ieee80211_channel channels_50[4]; | ||
149 | struct ieee80211_rate rates_50[9]; | ||
150 | u32 ap_macids_supported; | ||
151 | u32 sta_macids_supported; | ||
151 | 152 | ||
152 | /* firmware access */ | 153 | /* firmware access */ |
153 | struct mutex fw_mutex; | 154 | struct mutex fw_mutex; |
@@ -161,9 +162,9 @@ struct mwl8k_priv { | |||
161 | /* TX quiesce completion, protected by fw_mutex and tx_lock */ | 162 | /* TX quiesce completion, protected by fw_mutex and tx_lock */ |
162 | struct completion *tx_wait; | 163 | struct completion *tx_wait; |
163 | 164 | ||
164 | struct ieee80211_vif *vif; | 165 | /* List of interfaces. */ |
165 | 166 | u32 macids_used; | |
166 | struct ieee80211_channel *current_channel; | 167 | struct list_head vif_list; |
167 | 168 | ||
168 | /* power management status cookie from firmware */ | 169 | /* power management status cookie from firmware */ |
169 | u32 *cookie; | 170 | u32 *cookie; |
@@ -182,11 +183,6 @@ struct mwl8k_priv { | |||
182 | struct mwl8k_rx_queue rxq[MWL8K_RX_QUEUES]; | 183 | struct mwl8k_rx_queue rxq[MWL8K_RX_QUEUES]; |
183 | struct mwl8k_tx_queue txq[MWL8K_TX_QUEUES]; | 184 | struct mwl8k_tx_queue txq[MWL8K_TX_QUEUES]; |
184 | 185 | ||
185 | /* PHY parameters */ | ||
186 | struct ieee80211_supported_band band; | ||
187 | struct ieee80211_channel channels[14]; | ||
188 | struct ieee80211_rate rates[14]; | ||
189 | |||
190 | bool radio_on; | 186 | bool radio_on; |
191 | bool radio_short_preamble; | 187 | bool radio_short_preamble; |
192 | bool sniffer_enabled; | 188 | bool sniffer_enabled; |
@@ -205,32 +201,33 @@ struct mwl8k_priv { | |||
205 | */ | 201 | */ |
206 | struct work_struct finalize_join_worker; | 202 | struct work_struct finalize_join_worker; |
207 | 203 | ||
208 | /* Tasklet to reclaim TX descriptors and buffers after tx */ | 204 | /* Tasklet to perform TX reclaim. */ |
209 | struct tasklet_struct tx_reclaim_task; | 205 | struct tasklet_struct poll_tx_task; |
206 | |||
207 | /* Tasklet to perform RX. */ | ||
208 | struct tasklet_struct poll_rx_task; | ||
210 | }; | 209 | }; |
211 | 210 | ||
212 | /* Per interface specific private data */ | 211 | /* Per interface specific private data */ |
213 | struct mwl8k_vif { | 212 | struct mwl8k_vif { |
214 | /* backpointer to parent config block */ | 213 | struct list_head list; |
215 | struct mwl8k_priv *priv; | 214 | struct ieee80211_vif *vif; |
216 | |||
217 | /* BSS config of AP or IBSS from mac80211*/ | ||
218 | struct ieee80211_bss_conf bss_info; | ||
219 | |||
220 | /* BSSID of AP or IBSS */ | ||
221 | u8 bssid[ETH_ALEN]; | ||
222 | u8 mac_addr[ETH_ALEN]; | ||
223 | 215 | ||
224 | /* Index into station database.Returned by update_sta_db call */ | 216 | /* Firmware macid for this vif. */ |
225 | u8 peer_id; | 217 | int macid; |
226 | 218 | ||
227 | /* Non AMPDU sequence number assigned by driver */ | 219 | /* Non AMPDU sequence number assigned by driver. */ |
228 | u16 seqno; | 220 | u16 seqno; |
229 | }; | 221 | }; |
230 | |||
231 | #define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv)) | 222 | #define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv)) |
232 | 223 | ||
233 | static const struct ieee80211_channel mwl8k_channels[] = { | 224 | struct mwl8k_sta { |
225 | /* Index into station database. Returned by UPDATE_STADB. */ | ||
226 | u8 peer_id; | ||
227 | }; | ||
228 | #define MWL8K_STA(_sta) ((struct mwl8k_sta *)&((_sta)->drv_priv)) | ||
229 | |||
230 | static const struct ieee80211_channel mwl8k_channels_24[] = { | ||
234 | { .center_freq = 2412, .hw_value = 1, }, | 231 | { .center_freq = 2412, .hw_value = 1, }, |
235 | { .center_freq = 2417, .hw_value = 2, }, | 232 | { .center_freq = 2417, .hw_value = 2, }, |
236 | { .center_freq = 2422, .hw_value = 3, }, | 233 | { .center_freq = 2422, .hw_value = 3, }, |
@@ -242,9 +239,12 @@ static const struct ieee80211_channel mwl8k_channels[] = { | |||
242 | { .center_freq = 2452, .hw_value = 9, }, | 239 | { .center_freq = 2452, .hw_value = 9, }, |
243 | { .center_freq = 2457, .hw_value = 10, }, | 240 | { .center_freq = 2457, .hw_value = 10, }, |
244 | { .center_freq = 2462, .hw_value = 11, }, | 241 | { .center_freq = 2462, .hw_value = 11, }, |
242 | { .center_freq = 2467, .hw_value = 12, }, | ||
243 | { .center_freq = 2472, .hw_value = 13, }, | ||
244 | { .center_freq = 2484, .hw_value = 14, }, | ||
245 | }; | 245 | }; |
246 | 246 | ||
247 | static const struct ieee80211_rate mwl8k_rates[] = { | 247 | static const struct ieee80211_rate mwl8k_rates_24[] = { |
248 | { .bitrate = 10, .hw_value = 2, }, | 248 | { .bitrate = 10, .hw_value = 2, }, |
249 | { .bitrate = 20, .hw_value = 4, }, | 249 | { .bitrate = 20, .hw_value = 4, }, |
250 | { .bitrate = 55, .hw_value = 11, }, | 250 | { .bitrate = 55, .hw_value = 11, }, |
@@ -261,8 +261,23 @@ static const struct ieee80211_rate mwl8k_rates[] = { | |||
261 | { .bitrate = 720, .hw_value = 144, }, | 261 | { .bitrate = 720, .hw_value = 144, }, |
262 | }; | 262 | }; |
263 | 263 | ||
264 | static const u8 mwl8k_rateids[12] = { | 264 | static const struct ieee80211_channel mwl8k_channels_50[] = { |
265 | 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, | 265 | { .center_freq = 5180, .hw_value = 36, }, |
266 | { .center_freq = 5200, .hw_value = 40, }, | ||
267 | { .center_freq = 5220, .hw_value = 44, }, | ||
268 | { .center_freq = 5240, .hw_value = 48, }, | ||
269 | }; | ||
270 | |||
271 | static const struct ieee80211_rate mwl8k_rates_50[] = { | ||
272 | { .bitrate = 60, .hw_value = 12, }, | ||
273 | { .bitrate = 90, .hw_value = 18, }, | ||
274 | { .bitrate = 120, .hw_value = 24, }, | ||
275 | { .bitrate = 180, .hw_value = 36, }, | ||
276 | { .bitrate = 240, .hw_value = 48, }, | ||
277 | { .bitrate = 360, .hw_value = 72, }, | ||
278 | { .bitrate = 480, .hw_value = 96, }, | ||
279 | { .bitrate = 540, .hw_value = 108, }, | ||
280 | { .bitrate = 720, .hw_value = 144, }, | ||
266 | }; | 281 | }; |
267 | 282 | ||
268 | /* Set or get info from Firmware */ | 283 | /* Set or get info from Firmware */ |
@@ -278,6 +293,7 @@ static const u8 mwl8k_rateids[12] = { | |||
278 | #define MWL8K_CMD_RADIO_CONTROL 0x001c | 293 | #define MWL8K_CMD_RADIO_CONTROL 0x001c |
279 | #define MWL8K_CMD_RF_TX_POWER 0x001e | 294 | #define MWL8K_CMD_RF_TX_POWER 0x001e |
280 | #define MWL8K_CMD_RF_ANTENNA 0x0020 | 295 | #define MWL8K_CMD_RF_ANTENNA 0x0020 |
296 | #define MWL8K_CMD_SET_BEACON 0x0100 /* per-vif */ | ||
281 | #define MWL8K_CMD_SET_PRE_SCAN 0x0107 | 297 | #define MWL8K_CMD_SET_PRE_SCAN 0x0107 |
282 | #define MWL8K_CMD_SET_POST_SCAN 0x0108 | 298 | #define MWL8K_CMD_SET_POST_SCAN 0x0108 |
283 | #define MWL8K_CMD_SET_RF_CHANNEL 0x010a | 299 | #define MWL8K_CMD_SET_RF_CHANNEL 0x010a |
@@ -291,8 +307,10 @@ static const u8 mwl8k_rateids[12] = { | |||
291 | #define MWL8K_CMD_MIMO_CONFIG 0x0125 | 307 | #define MWL8K_CMD_MIMO_CONFIG 0x0125 |
292 | #define MWL8K_CMD_USE_FIXED_RATE 0x0126 | 308 | #define MWL8K_CMD_USE_FIXED_RATE 0x0126 |
293 | #define MWL8K_CMD_ENABLE_SNIFFER 0x0150 | 309 | #define MWL8K_CMD_ENABLE_SNIFFER 0x0150 |
294 | #define MWL8K_CMD_SET_MAC_ADDR 0x0202 | 310 | #define MWL8K_CMD_SET_MAC_ADDR 0x0202 /* per-vif */ |
295 | #define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203 | 311 | #define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203 |
312 | #define MWL8K_CMD_BSS_START 0x1100 /* per-vif */ | ||
313 | #define MWL8K_CMD_SET_NEW_STN 0x1111 /* per-vif */ | ||
296 | #define MWL8K_CMD_UPDATE_STADB 0x1123 | 314 | #define MWL8K_CMD_UPDATE_STADB 0x1123 |
297 | 315 | ||
298 | static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) | 316 | static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) |
@@ -310,6 +328,7 @@ static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) | |||
310 | MWL8K_CMDNAME(RADIO_CONTROL); | 328 | MWL8K_CMDNAME(RADIO_CONTROL); |
311 | MWL8K_CMDNAME(RF_TX_POWER); | 329 | MWL8K_CMDNAME(RF_TX_POWER); |
312 | MWL8K_CMDNAME(RF_ANTENNA); | 330 | MWL8K_CMDNAME(RF_ANTENNA); |
331 | MWL8K_CMDNAME(SET_BEACON); | ||
313 | MWL8K_CMDNAME(SET_PRE_SCAN); | 332 | MWL8K_CMDNAME(SET_PRE_SCAN); |
314 | MWL8K_CMDNAME(SET_POST_SCAN); | 333 | MWL8K_CMDNAME(SET_POST_SCAN); |
315 | MWL8K_CMDNAME(SET_RF_CHANNEL); | 334 | MWL8K_CMDNAME(SET_RF_CHANNEL); |
@@ -325,6 +344,8 @@ static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) | |||
325 | MWL8K_CMDNAME(ENABLE_SNIFFER); | 344 | MWL8K_CMDNAME(ENABLE_SNIFFER); |
326 | MWL8K_CMDNAME(SET_MAC_ADDR); | 345 | MWL8K_CMDNAME(SET_MAC_ADDR); |
327 | MWL8K_CMDNAME(SET_RATEADAPT_MODE); | 346 | MWL8K_CMDNAME(SET_RATEADAPT_MODE); |
347 | MWL8K_CMDNAME(BSS_START); | ||
348 | MWL8K_CMDNAME(SET_NEW_STN); | ||
328 | MWL8K_CMDNAME(UPDATE_STADB); | 349 | MWL8K_CMDNAME(UPDATE_STADB); |
329 | default: | 350 | default: |
330 | snprintf(buf, bufsize, "0x%x", cmd); | 351 | snprintf(buf, bufsize, "0x%x", cmd); |
@@ -355,8 +376,8 @@ static void mwl8k_release_fw(struct firmware **fw) | |||
355 | 376 | ||
356 | static void mwl8k_release_firmware(struct mwl8k_priv *priv) | 377 | static void mwl8k_release_firmware(struct mwl8k_priv *priv) |
357 | { | 378 | { |
358 | mwl8k_release_fw(&priv->fw.ucode); | 379 | mwl8k_release_fw(&priv->fw_ucode); |
359 | mwl8k_release_fw(&priv->fw.helper); | 380 | mwl8k_release_fw(&priv->fw_helper); |
360 | } | 381 | } |
361 | 382 | ||
362 | /* Request fw image */ | 383 | /* Request fw image */ |
@@ -377,7 +398,7 @@ static int mwl8k_request_firmware(struct mwl8k_priv *priv) | |||
377 | int rc; | 398 | int rc; |
378 | 399 | ||
379 | if (di->helper_image != NULL) { | 400 | if (di->helper_image != NULL) { |
380 | rc = mwl8k_request_fw(priv, di->helper_image, &priv->fw.helper); | 401 | rc = mwl8k_request_fw(priv, di->helper_image, &priv->fw_helper); |
381 | if (rc) { | 402 | if (rc) { |
382 | printk(KERN_ERR "%s: Error requesting helper " | 403 | printk(KERN_ERR "%s: Error requesting helper " |
383 | "firmware file %s\n", pci_name(priv->pdev), | 404 | "firmware file %s\n", pci_name(priv->pdev), |
@@ -386,24 +407,22 @@ static int mwl8k_request_firmware(struct mwl8k_priv *priv) | |||
386 | } | 407 | } |
387 | } | 408 | } |
388 | 409 | ||
389 | rc = mwl8k_request_fw(priv, di->fw_image, &priv->fw.ucode); | 410 | rc = mwl8k_request_fw(priv, di->fw_image, &priv->fw_ucode); |
390 | if (rc) { | 411 | if (rc) { |
391 | printk(KERN_ERR "%s: Error requesting firmware file %s\n", | 412 | printk(KERN_ERR "%s: Error requesting firmware file %s\n", |
392 | pci_name(priv->pdev), di->fw_image); | 413 | pci_name(priv->pdev), di->fw_image); |
393 | mwl8k_release_fw(&priv->fw.helper); | 414 | mwl8k_release_fw(&priv->fw_helper); |
394 | return rc; | 415 | return rc; |
395 | } | 416 | } |
396 | 417 | ||
397 | return 0; | 418 | return 0; |
398 | } | 419 | } |
399 | 420 | ||
400 | MODULE_FIRMWARE("mwl8k/helper_8687.fw"); | ||
401 | MODULE_FIRMWARE("mwl8k/fmimage_8687.fw"); | ||
402 | |||
403 | struct mwl8k_cmd_pkt { | 421 | struct mwl8k_cmd_pkt { |
404 | __le16 code; | 422 | __le16 code; |
405 | __le16 length; | 423 | __le16 length; |
406 | __le16 seq_num; | 424 | __u8 seq_num; |
425 | __u8 macid; | ||
407 | __le16 result; | 426 | __le16 result; |
408 | char payload[0]; | 427 | char payload[0]; |
409 | } __attribute__((packed)); | 428 | } __attribute__((packed)); |
@@ -461,6 +480,7 @@ static int mwl8k_load_fw_image(struct mwl8k_priv *priv, | |||
461 | 480 | ||
462 | cmd->code = cpu_to_le16(MWL8K_CMD_CODE_DNLD); | 481 | cmd->code = cpu_to_le16(MWL8K_CMD_CODE_DNLD); |
463 | cmd->seq_num = 0; | 482 | cmd->seq_num = 0; |
483 | cmd->macid = 0; | ||
464 | cmd->result = 0; | 484 | cmd->result = 0; |
465 | 485 | ||
466 | done = 0; | 486 | done = 0; |
@@ -551,13 +571,12 @@ static int mwl8k_feed_fw_image(struct mwl8k_priv *priv, | |||
551 | static int mwl8k_load_firmware(struct ieee80211_hw *hw) | 571 | static int mwl8k_load_firmware(struct ieee80211_hw *hw) |
552 | { | 572 | { |
553 | struct mwl8k_priv *priv = hw->priv; | 573 | struct mwl8k_priv *priv = hw->priv; |
554 | struct firmware *fw = priv->fw.ucode; | 574 | struct firmware *fw = priv->fw_ucode; |
555 | struct mwl8k_device_info *di = priv->device_info; | ||
556 | int rc; | 575 | int rc; |
557 | int loops; | 576 | int loops; |
558 | 577 | ||
559 | if (!memcmp(fw->data, "\x01\x00\x00\x00", 4)) { | 578 | if (!memcmp(fw->data, "\x01\x00\x00\x00", 4)) { |
560 | struct firmware *helper = priv->fw.helper; | 579 | struct firmware *helper = priv->fw_helper; |
561 | 580 | ||
562 | if (helper == NULL) { | 581 | if (helper == NULL) { |
563 | printk(KERN_ERR "%s: helper image needed but none " | 582 | printk(KERN_ERR "%s: helper image needed but none " |
@@ -584,10 +603,7 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw) | |||
584 | return rc; | 603 | return rc; |
585 | } | 604 | } |
586 | 605 | ||
587 | if (di->modes & BIT(NL80211_IFTYPE_AP)) | 606 | iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR); |
588 | iowrite32(MWL8K_MODE_AP, priv->regs + MWL8K_HIU_GEN_PTR); | ||
589 | else | ||
590 | iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR); | ||
591 | 607 | ||
592 | loops = 500000; | 608 | loops = 500000; |
593 | do { | 609 | do { |
@@ -610,91 +626,6 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw) | |||
610 | } | 626 | } |
611 | 627 | ||
612 | 628 | ||
613 | /* | ||
614 | * Defines shared between transmission and reception. | ||
615 | */ | ||
616 | /* HT control fields for firmware */ | ||
617 | struct ewc_ht_info { | ||
618 | __le16 control1; | ||
619 | __le16 control2; | ||
620 | __le16 control3; | ||
621 | } __attribute__((packed)); | ||
622 | |||
623 | /* Firmware Station database operations */ | ||
624 | #define MWL8K_STA_DB_ADD_ENTRY 0 | ||
625 | #define MWL8K_STA_DB_MODIFY_ENTRY 1 | ||
626 | #define MWL8K_STA_DB_DEL_ENTRY 2 | ||
627 | #define MWL8K_STA_DB_FLUSH 3 | ||
628 | |||
629 | /* Peer Entry flags - used to define the type of the peer node */ | ||
630 | #define MWL8K_PEER_TYPE_ACCESSPOINT 2 | ||
631 | |||
632 | struct peer_capability_info { | ||
633 | /* Peer type - AP vs. STA. */ | ||
634 | __u8 peer_type; | ||
635 | |||
636 | /* Basic 802.11 capabilities from assoc resp. */ | ||
637 | __le16 basic_caps; | ||
638 | |||
639 | /* Set if peer supports 802.11n high throughput (HT). */ | ||
640 | __u8 ht_support; | ||
641 | |||
642 | /* Valid if HT is supported. */ | ||
643 | __le16 ht_caps; | ||
644 | __u8 extended_ht_caps; | ||
645 | struct ewc_ht_info ewc_info; | ||
646 | |||
647 | /* Legacy rate table. Intersection of our rates and peer rates. */ | ||
648 | __u8 legacy_rates[12]; | ||
649 | |||
650 | /* HT rate table. Intersection of our rates and peer rates. */ | ||
651 | __u8 ht_rates[16]; | ||
652 | __u8 pad[16]; | ||
653 | |||
654 | /* If set, interoperability mode, no proprietary extensions. */ | ||
655 | __u8 interop; | ||
656 | __u8 pad2; | ||
657 | __u8 station_id; | ||
658 | __le16 amsdu_enabled; | ||
659 | } __attribute__((packed)); | ||
660 | |||
661 | /* Inline functions to manipulate QoS field in data descriptor. */ | ||
662 | static inline u16 mwl8k_qos_setbit_eosp(u16 qos) | ||
663 | { | ||
664 | u16 val_mask = 1 << 4; | ||
665 | |||
666 | /* End of Service Period Bit 4 */ | ||
667 | return qos | val_mask; | ||
668 | } | ||
669 | |||
670 | static inline u16 mwl8k_qos_setbit_ack(u16 qos, u8 ack_policy) | ||
671 | { | ||
672 | u16 val_mask = 0x3; | ||
673 | u8 shift = 5; | ||
674 | u16 qos_mask = ~(val_mask << shift); | ||
675 | |||
676 | /* Ack Policy Bit 5-6 */ | ||
677 | return (qos & qos_mask) | ((ack_policy & val_mask) << shift); | ||
678 | } | ||
679 | |||
680 | static inline u16 mwl8k_qos_setbit_amsdu(u16 qos) | ||
681 | { | ||
682 | u16 val_mask = 1 << 7; | ||
683 | |||
684 | /* AMSDU present Bit 7 */ | ||
685 | return qos | val_mask; | ||
686 | } | ||
687 | |||
688 | static inline u16 mwl8k_qos_setbit_qlen(u16 qos, u8 len) | ||
689 | { | ||
690 | u16 val_mask = 0xff; | ||
691 | u8 shift = 8; | ||
692 | u16 qos_mask = ~(val_mask << shift); | ||
693 | |||
694 | /* Queue Length Bits 8-15 */ | ||
695 | return (qos & qos_mask) | ((len & val_mask) << shift); | ||
696 | } | ||
697 | |||
698 | /* DMA header used by firmware and hardware. */ | 629 | /* DMA header used by firmware and hardware. */ |
699 | struct mwl8k_dma_data { | 630 | struct mwl8k_dma_data { |
700 | __le16 fwlen; | 631 | __le16 fwlen; |
@@ -761,9 +692,9 @@ static inline void mwl8k_add_dma_header(struct sk_buff *skb) | |||
761 | 692 | ||
762 | 693 | ||
763 | /* | 694 | /* |
764 | * Packet reception for 88w8366. | 695 | * Packet reception for 88w8366 AP firmware. |
765 | */ | 696 | */ |
766 | struct mwl8k_rxd_8366 { | 697 | struct mwl8k_rxd_8366_ap { |
767 | __le16 pkt_len; | 698 | __le16 pkt_len; |
768 | __u8 sq2; | 699 | __u8 sq2; |
769 | __u8 rate; | 700 | __u8 rate; |
@@ -781,23 +712,23 @@ struct mwl8k_rxd_8366 { | |||
781 | __u8 rx_ctrl; | 712 | __u8 rx_ctrl; |
782 | } __attribute__((packed)); | 713 | } __attribute__((packed)); |
783 | 714 | ||
784 | #define MWL8K_8366_RATE_INFO_MCS_FORMAT 0x80 | 715 | #define MWL8K_8366_AP_RATE_INFO_MCS_FORMAT 0x80 |
785 | #define MWL8K_8366_RATE_INFO_40MHZ 0x40 | 716 | #define MWL8K_8366_AP_RATE_INFO_40MHZ 0x40 |
786 | #define MWL8K_8366_RATE_INFO_RATEID(x) ((x) & 0x3f) | 717 | #define MWL8K_8366_AP_RATE_INFO_RATEID(x) ((x) & 0x3f) |
787 | 718 | ||
788 | #define MWL8K_8366_RX_CTRL_OWNED_BY_HOST 0x80 | 719 | #define MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST 0x80 |
789 | 720 | ||
790 | static void mwl8k_rxd_8366_init(void *_rxd, dma_addr_t next_dma_addr) | 721 | static void mwl8k_rxd_8366_ap_init(void *_rxd, dma_addr_t next_dma_addr) |
791 | { | 722 | { |
792 | struct mwl8k_rxd_8366 *rxd = _rxd; | 723 | struct mwl8k_rxd_8366_ap *rxd = _rxd; |
793 | 724 | ||
794 | rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); | 725 | rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); |
795 | rxd->rx_ctrl = MWL8K_8366_RX_CTRL_OWNED_BY_HOST; | 726 | rxd->rx_ctrl = MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST; |
796 | } | 727 | } |
797 | 728 | ||
798 | static void mwl8k_rxd_8366_refill(void *_rxd, dma_addr_t addr, int len) | 729 | static void mwl8k_rxd_8366_ap_refill(void *_rxd, dma_addr_t addr, int len) |
799 | { | 730 | { |
800 | struct mwl8k_rxd_8366 *rxd = _rxd; | 731 | struct mwl8k_rxd_8366_ap *rxd = _rxd; |
801 | 732 | ||
802 | rxd->pkt_len = cpu_to_le16(len); | 733 | rxd->pkt_len = cpu_to_le16(len); |
803 | rxd->pkt_phys_addr = cpu_to_le32(addr); | 734 | rxd->pkt_phys_addr = cpu_to_le32(addr); |
@@ -806,12 +737,12 @@ static void mwl8k_rxd_8366_refill(void *_rxd, dma_addr_t addr, int len) | |||
806 | } | 737 | } |
807 | 738 | ||
808 | static int | 739 | static int |
809 | mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status, | 740 | mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status, |
810 | __le16 *qos) | 741 | __le16 *qos) |
811 | { | 742 | { |
812 | struct mwl8k_rxd_8366 *rxd = _rxd; | 743 | struct mwl8k_rxd_8366_ap *rxd = _rxd; |
813 | 744 | ||
814 | if (!(rxd->rx_ctrl & MWL8K_8366_RX_CTRL_OWNED_BY_HOST)) | 745 | if (!(rxd->rx_ctrl & MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST)) |
815 | return -1; | 746 | return -1; |
816 | rmb(); | 747 | rmb(); |
817 | 748 | ||
@@ -820,23 +751,29 @@ mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status, | |||
820 | status->signal = -rxd->rssi; | 751 | status->signal = -rxd->rssi; |
821 | status->noise = -rxd->noise_floor; | 752 | status->noise = -rxd->noise_floor; |
822 | 753 | ||
823 | if (rxd->rate & MWL8K_8366_RATE_INFO_MCS_FORMAT) { | 754 | if (rxd->rate & MWL8K_8366_AP_RATE_INFO_MCS_FORMAT) { |
824 | status->flag |= RX_FLAG_HT; | 755 | status->flag |= RX_FLAG_HT; |
825 | if (rxd->rate & MWL8K_8366_RATE_INFO_40MHZ) | 756 | if (rxd->rate & MWL8K_8366_AP_RATE_INFO_40MHZ) |
826 | status->flag |= RX_FLAG_40MHZ; | 757 | status->flag |= RX_FLAG_40MHZ; |
827 | status->rate_idx = MWL8K_8366_RATE_INFO_RATEID(rxd->rate); | 758 | status->rate_idx = MWL8K_8366_AP_RATE_INFO_RATEID(rxd->rate); |
828 | } else { | 759 | } else { |
829 | int i; | 760 | int i; |
830 | 761 | ||
831 | for (i = 0; i < ARRAY_SIZE(mwl8k_rates); i++) { | 762 | for (i = 0; i < ARRAY_SIZE(mwl8k_rates_24); i++) { |
832 | if (mwl8k_rates[i].hw_value == rxd->rate) { | 763 | if (mwl8k_rates_24[i].hw_value == rxd->rate) { |
833 | status->rate_idx = i; | 764 | status->rate_idx = i; |
834 | break; | 765 | break; |
835 | } | 766 | } |
836 | } | 767 | } |
837 | } | 768 | } |
838 | 769 | ||
839 | status->band = IEEE80211_BAND_2GHZ; | 770 | if (rxd->channel > 14) { |
771 | status->band = IEEE80211_BAND_5GHZ; | ||
772 | if (!(status->flag & RX_FLAG_HT)) | ||
773 | status->rate_idx -= 5; | ||
774 | } else { | ||
775 | status->band = IEEE80211_BAND_2GHZ; | ||
776 | } | ||
840 | status->freq = ieee80211_channel_to_frequency(rxd->channel); | 777 | status->freq = ieee80211_channel_to_frequency(rxd->channel); |
841 | 778 | ||
842 | *qos = rxd->qos_control; | 779 | *qos = rxd->qos_control; |
@@ -844,17 +781,17 @@ mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status, | |||
844 | return le16_to_cpu(rxd->pkt_len); | 781 | return le16_to_cpu(rxd->pkt_len); |
845 | } | 782 | } |
846 | 783 | ||
847 | static struct rxd_ops rxd_8366_ops = { | 784 | static struct rxd_ops rxd_8366_ap_ops = { |
848 | .rxd_size = sizeof(struct mwl8k_rxd_8366), | 785 | .rxd_size = sizeof(struct mwl8k_rxd_8366_ap), |
849 | .rxd_init = mwl8k_rxd_8366_init, | 786 | .rxd_init = mwl8k_rxd_8366_ap_init, |
850 | .rxd_refill = mwl8k_rxd_8366_refill, | 787 | .rxd_refill = mwl8k_rxd_8366_ap_refill, |
851 | .rxd_process = mwl8k_rxd_8366_process, | 788 | .rxd_process = mwl8k_rxd_8366_ap_process, |
852 | }; | 789 | }; |
853 | 790 | ||
854 | /* | 791 | /* |
855 | * Packet reception for 88w8687. | 792 | * Packet reception for STA firmware. |
856 | */ | 793 | */ |
857 | struct mwl8k_rxd_8687 { | 794 | struct mwl8k_rxd_sta { |
858 | __le16 pkt_len; | 795 | __le16 pkt_len; |
859 | __u8 link_quality; | 796 | __u8 link_quality; |
860 | __u8 noise_level; | 797 | __u8 noise_level; |
@@ -871,26 +808,26 @@ struct mwl8k_rxd_8687 { | |||
871 | __u8 pad2[2]; | 808 | __u8 pad2[2]; |
872 | } __attribute__((packed)); | 809 | } __attribute__((packed)); |
873 | 810 | ||
874 | #define MWL8K_8687_RATE_INFO_SHORTPRE 0x8000 | 811 | #define MWL8K_STA_RATE_INFO_SHORTPRE 0x8000 |
875 | #define MWL8K_8687_RATE_INFO_ANTSELECT(x) (((x) >> 11) & 0x3) | 812 | #define MWL8K_STA_RATE_INFO_ANTSELECT(x) (((x) >> 11) & 0x3) |
876 | #define MWL8K_8687_RATE_INFO_RATEID(x) (((x) >> 3) & 0x3f) | 813 | #define MWL8K_STA_RATE_INFO_RATEID(x) (((x) >> 3) & 0x3f) |
877 | #define MWL8K_8687_RATE_INFO_40MHZ 0x0004 | 814 | #define MWL8K_STA_RATE_INFO_40MHZ 0x0004 |
878 | #define MWL8K_8687_RATE_INFO_SHORTGI 0x0002 | 815 | #define MWL8K_STA_RATE_INFO_SHORTGI 0x0002 |
879 | #define MWL8K_8687_RATE_INFO_MCS_FORMAT 0x0001 | 816 | #define MWL8K_STA_RATE_INFO_MCS_FORMAT 0x0001 |
880 | 817 | ||
881 | #define MWL8K_8687_RX_CTRL_OWNED_BY_HOST 0x02 | 818 | #define MWL8K_STA_RX_CTRL_OWNED_BY_HOST 0x02 |
882 | 819 | ||
883 | static void mwl8k_rxd_8687_init(void *_rxd, dma_addr_t next_dma_addr) | 820 | static void mwl8k_rxd_sta_init(void *_rxd, dma_addr_t next_dma_addr) |
884 | { | 821 | { |
885 | struct mwl8k_rxd_8687 *rxd = _rxd; | 822 | struct mwl8k_rxd_sta *rxd = _rxd; |
886 | 823 | ||
887 | rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); | 824 | rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); |
888 | rxd->rx_ctrl = MWL8K_8687_RX_CTRL_OWNED_BY_HOST; | 825 | rxd->rx_ctrl = MWL8K_STA_RX_CTRL_OWNED_BY_HOST; |
889 | } | 826 | } |
890 | 827 | ||
891 | static void mwl8k_rxd_8687_refill(void *_rxd, dma_addr_t addr, int len) | 828 | static void mwl8k_rxd_sta_refill(void *_rxd, dma_addr_t addr, int len) |
892 | { | 829 | { |
893 | struct mwl8k_rxd_8687 *rxd = _rxd; | 830 | struct mwl8k_rxd_sta *rxd = _rxd; |
894 | 831 | ||
895 | rxd->pkt_len = cpu_to_le16(len); | 832 | rxd->pkt_len = cpu_to_le16(len); |
896 | rxd->pkt_phys_addr = cpu_to_le32(addr); | 833 | rxd->pkt_phys_addr = cpu_to_le32(addr); |
@@ -899,13 +836,13 @@ static void mwl8k_rxd_8687_refill(void *_rxd, dma_addr_t addr, int len) | |||
899 | } | 836 | } |
900 | 837 | ||
901 | static int | 838 | static int |
902 | mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status, | 839 | mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status, |
903 | __le16 *qos) | 840 | __le16 *qos) |
904 | { | 841 | { |
905 | struct mwl8k_rxd_8687 *rxd = _rxd; | 842 | struct mwl8k_rxd_sta *rxd = _rxd; |
906 | u16 rate_info; | 843 | u16 rate_info; |
907 | 844 | ||
908 | if (!(rxd->rx_ctrl & MWL8K_8687_RX_CTRL_OWNED_BY_HOST)) | 845 | if (!(rxd->rx_ctrl & MWL8K_STA_RX_CTRL_OWNED_BY_HOST)) |
909 | return -1; | 846 | return -1; |
910 | rmb(); | 847 | rmb(); |
911 | 848 | ||
@@ -915,19 +852,25 @@ mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status, | |||
915 | 852 | ||
916 | status->signal = -rxd->rssi; | 853 | status->signal = -rxd->rssi; |
917 | status->noise = -rxd->noise_level; | 854 | status->noise = -rxd->noise_level; |
918 | status->antenna = MWL8K_8687_RATE_INFO_ANTSELECT(rate_info); | 855 | status->antenna = MWL8K_STA_RATE_INFO_ANTSELECT(rate_info); |
919 | status->rate_idx = MWL8K_8687_RATE_INFO_RATEID(rate_info); | 856 | status->rate_idx = MWL8K_STA_RATE_INFO_RATEID(rate_info); |
920 | 857 | ||
921 | if (rate_info & MWL8K_8687_RATE_INFO_SHORTPRE) | 858 | if (rate_info & MWL8K_STA_RATE_INFO_SHORTPRE) |
922 | status->flag |= RX_FLAG_SHORTPRE; | 859 | status->flag |= RX_FLAG_SHORTPRE; |
923 | if (rate_info & MWL8K_8687_RATE_INFO_40MHZ) | 860 | if (rate_info & MWL8K_STA_RATE_INFO_40MHZ) |
924 | status->flag |= RX_FLAG_40MHZ; | 861 | status->flag |= RX_FLAG_40MHZ; |
925 | if (rate_info & MWL8K_8687_RATE_INFO_SHORTGI) | 862 | if (rate_info & MWL8K_STA_RATE_INFO_SHORTGI) |
926 | status->flag |= RX_FLAG_SHORT_GI; | 863 | status->flag |= RX_FLAG_SHORT_GI; |
927 | if (rate_info & MWL8K_8687_RATE_INFO_MCS_FORMAT) | 864 | if (rate_info & MWL8K_STA_RATE_INFO_MCS_FORMAT) |
928 | status->flag |= RX_FLAG_HT; | 865 | status->flag |= RX_FLAG_HT; |
929 | 866 | ||
930 | status->band = IEEE80211_BAND_2GHZ; | 867 | if (rxd->channel > 14) { |
868 | status->band = IEEE80211_BAND_5GHZ; | ||
869 | if (!(status->flag & RX_FLAG_HT)) | ||
870 | status->rate_idx -= 5; | ||
871 | } else { | ||
872 | status->band = IEEE80211_BAND_2GHZ; | ||
873 | } | ||
931 | status->freq = ieee80211_channel_to_frequency(rxd->channel); | 874 | status->freq = ieee80211_channel_to_frequency(rxd->channel); |
932 | 875 | ||
933 | *qos = rxd->qos_control; | 876 | *qos = rxd->qos_control; |
@@ -935,11 +878,11 @@ mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status, | |||
935 | return le16_to_cpu(rxd->pkt_len); | 878 | return le16_to_cpu(rxd->pkt_len); |
936 | } | 879 | } |
937 | 880 | ||
938 | static struct rxd_ops rxd_8687_ops = { | 881 | static struct rxd_ops rxd_sta_ops = { |
939 | .rxd_size = sizeof(struct mwl8k_rxd_8687), | 882 | .rxd_size = sizeof(struct mwl8k_rxd_sta), |
940 | .rxd_init = mwl8k_rxd_8687_init, | 883 | .rxd_init = mwl8k_rxd_sta_init, |
941 | .rxd_refill = mwl8k_rxd_8687_refill, | 884 | .rxd_refill = mwl8k_rxd_sta_refill, |
942 | .rxd_process = mwl8k_rxd_8687_process, | 885 | .rxd_process = mwl8k_rxd_sta_process, |
943 | }; | 886 | }; |
944 | 887 | ||
945 | 888 | ||
@@ -1153,16 +1096,18 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit) | |||
1153 | * Packet transmission. | 1096 | * Packet transmission. |
1154 | */ | 1097 | */ |
1155 | 1098 | ||
1156 | /* Transmit packet ACK policy */ | ||
1157 | #define MWL8K_TXD_ACK_POLICY_NORMAL 0 | ||
1158 | #define MWL8K_TXD_ACK_POLICY_BLOCKACK 3 | ||
1159 | |||
1160 | #define MWL8K_TXD_STATUS_OK 0x00000001 | 1099 | #define MWL8K_TXD_STATUS_OK 0x00000001 |
1161 | #define MWL8K_TXD_STATUS_OK_RETRY 0x00000002 | 1100 | #define MWL8K_TXD_STATUS_OK_RETRY 0x00000002 |
1162 | #define MWL8K_TXD_STATUS_OK_MORE_RETRY 0x00000004 | 1101 | #define MWL8K_TXD_STATUS_OK_MORE_RETRY 0x00000004 |
1163 | #define MWL8K_TXD_STATUS_MULTICAST_TX 0x00000008 | 1102 | #define MWL8K_TXD_STATUS_MULTICAST_TX 0x00000008 |
1164 | #define MWL8K_TXD_STATUS_FW_OWNED 0x80000000 | 1103 | #define MWL8K_TXD_STATUS_FW_OWNED 0x80000000 |
1165 | 1104 | ||
1105 | #define MWL8K_QOS_QLEN_UNSPEC 0xff00 | ||
1106 | #define MWL8K_QOS_ACK_POLICY_MASK 0x0060 | ||
1107 | #define MWL8K_QOS_ACK_POLICY_NORMAL 0x0000 | ||
1108 | #define MWL8K_QOS_ACK_POLICY_BLOCKACK 0x0060 | ||
1109 | #define MWL8K_QOS_EOSP 0x0010 | ||
1110 | |||
1166 | struct mwl8k_tx_desc { | 1111 | struct mwl8k_tx_desc { |
1167 | __le32 status; | 1112 | __le32 status; |
1168 | __u8 data_rate; | 1113 | __u8 data_rate; |
@@ -1187,8 +1132,7 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index) | |||
1187 | int size; | 1132 | int size; |
1188 | int i; | 1133 | int i; |
1189 | 1134 | ||
1190 | memset(&txq->stats, 0, sizeof(struct ieee80211_tx_queue_stats)); | 1135 | txq->len = 0; |
1191 | txq->stats.limit = MWL8K_TX_DESCS; | ||
1192 | txq->head = 0; | 1136 | txq->head = 0; |
1193 | txq->tail = 0; | 1137 | txq->tail = 0; |
1194 | 1138 | ||
@@ -1264,7 +1208,7 @@ static void mwl8k_dump_tx_rings(struct ieee80211_hw *hw) | |||
1264 | printk(KERN_ERR "%s: txq[%d] len=%d head=%d tail=%d " | 1208 | printk(KERN_ERR "%s: txq[%d] len=%d head=%d tail=%d " |
1265 | "fw_owned=%d drv_owned=%d unused=%d\n", | 1209 | "fw_owned=%d drv_owned=%d unused=%d\n", |
1266 | wiphy_name(hw->wiphy), i, | 1210 | wiphy_name(hw->wiphy), i, |
1267 | txq->stats.len, txq->head, txq->tail, | 1211 | txq->len, txq->head, txq->tail, |
1268 | fw_owned, drv_owned, unused); | 1212 | fw_owned, drv_owned, unused); |
1269 | } | 1213 | } |
1270 | } | 1214 | } |
@@ -1272,7 +1216,7 @@ static void mwl8k_dump_tx_rings(struct ieee80211_hw *hw) | |||
1272 | /* | 1216 | /* |
1273 | * Must be called with priv->fw_mutex held and tx queues stopped. | 1217 | * Must be called with priv->fw_mutex held and tx queues stopped. |
1274 | */ | 1218 | */ |
1275 | #define MWL8K_TX_WAIT_TIMEOUT_MS 1000 | 1219 | #define MWL8K_TX_WAIT_TIMEOUT_MS 5000 |
1276 | 1220 | ||
1277 | static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) | 1221 | static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) |
1278 | { | 1222 | { |
@@ -1316,8 +1260,8 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) | |||
1316 | } | 1260 | } |
1317 | 1261 | ||
1318 | if (priv->pending_tx_pkts < oldcount) { | 1262 | if (priv->pending_tx_pkts < oldcount) { |
1319 | printk(KERN_NOTICE "%s: timeout waiting for tx " | 1263 | printk(KERN_NOTICE "%s: waiting for tx rings " |
1320 | "rings to drain (%d -> %d pkts), retrying\n", | 1264 | "to drain (%d -> %d pkts)\n", |
1321 | wiphy_name(hw->wiphy), oldcount, | 1265 | wiphy_name(hw->wiphy), oldcount, |
1322 | priv->pending_tx_pkts); | 1266 | priv->pending_tx_pkts); |
1323 | retry = 1; | 1267 | retry = 1; |
@@ -1342,13 +1286,15 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) | |||
1342 | MWL8K_TXD_STATUS_OK_RETRY | \ | 1286 | MWL8K_TXD_STATUS_OK_RETRY | \ |
1343 | MWL8K_TXD_STATUS_OK_MORE_RETRY)) | 1287 | MWL8K_TXD_STATUS_OK_MORE_RETRY)) |
1344 | 1288 | ||
1345 | static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) | 1289 | static int |
1290 | mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force) | ||
1346 | { | 1291 | { |
1347 | struct mwl8k_priv *priv = hw->priv; | 1292 | struct mwl8k_priv *priv = hw->priv; |
1348 | struct mwl8k_tx_queue *txq = priv->txq + index; | 1293 | struct mwl8k_tx_queue *txq = priv->txq + index; |
1349 | int wake = 0; | 1294 | int processed; |
1350 | 1295 | ||
1351 | while (txq->stats.len > 0) { | 1296 | processed = 0; |
1297 | while (txq->len > 0 && limit--) { | ||
1352 | int tx; | 1298 | int tx; |
1353 | struct mwl8k_tx_desc *tx_desc; | 1299 | struct mwl8k_tx_desc *tx_desc; |
1354 | unsigned long addr; | 1300 | unsigned long addr; |
@@ -1370,8 +1316,8 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) | |||
1370 | } | 1316 | } |
1371 | 1317 | ||
1372 | txq->head = (tx + 1) % MWL8K_TX_DESCS; | 1318 | txq->head = (tx + 1) % MWL8K_TX_DESCS; |
1373 | BUG_ON(txq->stats.len == 0); | 1319 | BUG_ON(txq->len == 0); |
1374 | txq->stats.len--; | 1320 | txq->len--; |
1375 | priv->pending_tx_pkts--; | 1321 | priv->pending_tx_pkts--; |
1376 | 1322 | ||
1377 | addr = le32_to_cpu(tx_desc->pkt_phys_addr); | 1323 | addr = le32_to_cpu(tx_desc->pkt_phys_addr); |
@@ -1395,11 +1341,13 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) | |||
1395 | 1341 | ||
1396 | ieee80211_tx_status_irqsafe(hw, skb); | 1342 | ieee80211_tx_status_irqsafe(hw, skb); |
1397 | 1343 | ||
1398 | wake = 1; | 1344 | processed++; |
1399 | } | 1345 | } |
1400 | 1346 | ||
1401 | if (wake && priv->radio_on && !mutex_is_locked(&priv->fw_mutex)) | 1347 | if (processed && priv->radio_on && !mutex_is_locked(&priv->fw_mutex)) |
1402 | ieee80211_wake_queue(hw, index); | 1348 | ieee80211_wake_queue(hw, index); |
1349 | |||
1350 | return processed; | ||
1403 | } | 1351 | } |
1404 | 1352 | ||
1405 | /* must be called only when the card's transmit is completely halted */ | 1353 | /* must be called only when the card's transmit is completely halted */ |
@@ -1408,7 +1356,7 @@ static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index) | |||
1408 | struct mwl8k_priv *priv = hw->priv; | 1356 | struct mwl8k_priv *priv = hw->priv; |
1409 | struct mwl8k_tx_queue *txq = priv->txq + index; | 1357 | struct mwl8k_tx_queue *txq = priv->txq + index; |
1410 | 1358 | ||
1411 | mwl8k_txq_reclaim(hw, index, 1); | 1359 | mwl8k_txq_reclaim(hw, index, INT_MAX, 1); |
1412 | 1360 | ||
1413 | kfree(txq->skb); | 1361 | kfree(txq->skb); |
1414 | txq->skb = NULL; | 1362 | txq->skb = NULL; |
@@ -1446,11 +1394,9 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) | |||
1446 | mwl8k_vif = MWL8K_VIF(tx_info->control.vif); | 1394 | mwl8k_vif = MWL8K_VIF(tx_info->control.vif); |
1447 | 1395 | ||
1448 | if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | 1396 | if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { |
1449 | u16 seqno = mwl8k_vif->seqno; | ||
1450 | |||
1451 | wh->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | 1397 | wh->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); |
1452 | wh->seq_ctrl |= cpu_to_le16(seqno << 4); | 1398 | wh->seq_ctrl |= cpu_to_le16(mwl8k_vif->seqno); |
1453 | mwl8k_vif->seqno = seqno++ % 4096; | 1399 | mwl8k_vif->seqno += 0x10; |
1454 | } | 1400 | } |
1455 | 1401 | ||
1456 | /* Setup firmware control bit fields for each frame type. */ | 1402 | /* Setup firmware control bit fields for each frame type. */ |
@@ -1459,24 +1405,17 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) | |||
1459 | if (ieee80211_is_mgmt(wh->frame_control) || | 1405 | if (ieee80211_is_mgmt(wh->frame_control) || |
1460 | ieee80211_is_ctl(wh->frame_control)) { | 1406 | ieee80211_is_ctl(wh->frame_control)) { |
1461 | txdatarate = 0; | 1407 | txdatarate = 0; |
1462 | qos = mwl8k_qos_setbit_eosp(qos); | 1408 | qos |= MWL8K_QOS_QLEN_UNSPEC | MWL8K_QOS_EOSP; |
1463 | /* Set Queue size to unspecified */ | ||
1464 | qos = mwl8k_qos_setbit_qlen(qos, 0xff); | ||
1465 | } else if (ieee80211_is_data(wh->frame_control)) { | 1409 | } else if (ieee80211_is_data(wh->frame_control)) { |
1466 | txdatarate = 1; | 1410 | txdatarate = 1; |
1467 | if (is_multicast_ether_addr(wh->addr1)) | 1411 | if (is_multicast_ether_addr(wh->addr1)) |
1468 | txstatus |= MWL8K_TXD_STATUS_MULTICAST_TX; | 1412 | txstatus |= MWL8K_TXD_STATUS_MULTICAST_TX; |
1469 | 1413 | ||
1470 | /* Send pkt in an aggregate if AMPDU frame. */ | 1414 | qos &= ~MWL8K_QOS_ACK_POLICY_MASK; |
1471 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) | 1415 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) |
1472 | qos = mwl8k_qos_setbit_ack(qos, | 1416 | qos |= MWL8K_QOS_ACK_POLICY_BLOCKACK; |
1473 | MWL8K_TXD_ACK_POLICY_BLOCKACK); | ||
1474 | else | 1417 | else |
1475 | qos = mwl8k_qos_setbit_ack(qos, | 1418 | qos |= MWL8K_QOS_ACK_POLICY_NORMAL; |
1476 | MWL8K_TXD_ACK_POLICY_NORMAL); | ||
1477 | |||
1478 | if (qos & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) | ||
1479 | qos = mwl8k_qos_setbit_amsdu(qos); | ||
1480 | } | 1419 | } |
1481 | 1420 | ||
1482 | dma = pci_map_single(priv->pdev, skb->data, | 1421 | dma = pci_map_single(priv->pdev, skb->data, |
@@ -1503,12 +1442,14 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) | |||
1503 | tx->pkt_phys_addr = cpu_to_le32(dma); | 1442 | tx->pkt_phys_addr = cpu_to_le32(dma); |
1504 | tx->pkt_len = cpu_to_le16(skb->len); | 1443 | tx->pkt_len = cpu_to_le16(skb->len); |
1505 | tx->rate_info = 0; | 1444 | tx->rate_info = 0; |
1506 | tx->peer_id = mwl8k_vif->peer_id; | 1445 | if (!priv->ap_fw && tx_info->control.sta != NULL) |
1446 | tx->peer_id = MWL8K_STA(tx_info->control.sta)->peer_id; | ||
1447 | else | ||
1448 | tx->peer_id = 0; | ||
1507 | wmb(); | 1449 | wmb(); |
1508 | tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus); | 1450 | tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus); |
1509 | 1451 | ||
1510 | txq->stats.count++; | 1452 | txq->len++; |
1511 | txq->stats.len++; | ||
1512 | priv->pending_tx_pkts++; | 1453 | priv->pending_tx_pkts++; |
1513 | 1454 | ||
1514 | txq->tail++; | 1455 | txq->tail++; |
@@ -1656,6 +1597,56 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) | |||
1656 | return rc; | 1597 | return rc; |
1657 | } | 1598 | } |
1658 | 1599 | ||
1600 | static int mwl8k_post_pervif_cmd(struct ieee80211_hw *hw, | ||
1601 | struct ieee80211_vif *vif, | ||
1602 | struct mwl8k_cmd_pkt *cmd) | ||
1603 | { | ||
1604 | if (vif != NULL) | ||
1605 | cmd->macid = MWL8K_VIF(vif)->macid; | ||
1606 | return mwl8k_post_cmd(hw, cmd); | ||
1607 | } | ||
1608 | |||
1609 | /* | ||
1610 | * Setup code shared between STA and AP firmware images. | ||
1611 | */ | ||
1612 | static void mwl8k_setup_2ghz_band(struct ieee80211_hw *hw) | ||
1613 | { | ||
1614 | struct mwl8k_priv *priv = hw->priv; | ||
1615 | |||
1616 | BUILD_BUG_ON(sizeof(priv->channels_24) != sizeof(mwl8k_channels_24)); | ||
1617 | memcpy(priv->channels_24, mwl8k_channels_24, sizeof(mwl8k_channels_24)); | ||
1618 | |||
1619 | BUILD_BUG_ON(sizeof(priv->rates_24) != sizeof(mwl8k_rates_24)); | ||
1620 | memcpy(priv->rates_24, mwl8k_rates_24, sizeof(mwl8k_rates_24)); | ||
1621 | |||
1622 | priv->band_24.band = IEEE80211_BAND_2GHZ; | ||
1623 | priv->band_24.channels = priv->channels_24; | ||
1624 | priv->band_24.n_channels = ARRAY_SIZE(mwl8k_channels_24); | ||
1625 | priv->band_24.bitrates = priv->rates_24; | ||
1626 | priv->band_24.n_bitrates = ARRAY_SIZE(mwl8k_rates_24); | ||
1627 | |||
1628 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band_24; | ||
1629 | } | ||
1630 | |||
1631 | static void mwl8k_setup_5ghz_band(struct ieee80211_hw *hw) | ||
1632 | { | ||
1633 | struct mwl8k_priv *priv = hw->priv; | ||
1634 | |||
1635 | BUILD_BUG_ON(sizeof(priv->channels_50) != sizeof(mwl8k_channels_50)); | ||
1636 | memcpy(priv->channels_50, mwl8k_channels_50, sizeof(mwl8k_channels_50)); | ||
1637 | |||
1638 | BUILD_BUG_ON(sizeof(priv->rates_50) != sizeof(mwl8k_rates_50)); | ||
1639 | memcpy(priv->rates_50, mwl8k_rates_50, sizeof(mwl8k_rates_50)); | ||
1640 | |||
1641 | priv->band_50.band = IEEE80211_BAND_5GHZ; | ||
1642 | priv->band_50.channels = priv->channels_50; | ||
1643 | priv->band_50.n_channels = ARRAY_SIZE(mwl8k_channels_50); | ||
1644 | priv->band_50.bitrates = priv->rates_50; | ||
1645 | priv->band_50.n_bitrates = ARRAY_SIZE(mwl8k_rates_50); | ||
1646 | |||
1647 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->band_50; | ||
1648 | } | ||
1649 | |||
1659 | /* | 1650 | /* |
1660 | * CMD_GET_HW_SPEC (STA version). | 1651 | * CMD_GET_HW_SPEC (STA version). |
1661 | */ | 1652 | */ |
@@ -1678,6 +1669,89 @@ struct mwl8k_cmd_get_hw_spec_sta { | |||
1678 | __le32 total_rxd; | 1669 | __le32 total_rxd; |
1679 | } __attribute__((packed)); | 1670 | } __attribute__((packed)); |
1680 | 1671 | ||
1672 | #define MWL8K_CAP_MAX_AMSDU 0x20000000 | ||
1673 | #define MWL8K_CAP_GREENFIELD 0x08000000 | ||
1674 | #define MWL8K_CAP_AMPDU 0x04000000 | ||
1675 | #define MWL8K_CAP_RX_STBC 0x01000000 | ||
1676 | #define MWL8K_CAP_TX_STBC 0x00800000 | ||
1677 | #define MWL8K_CAP_SHORTGI_40MHZ 0x00400000 | ||
1678 | #define MWL8K_CAP_SHORTGI_20MHZ 0x00200000 | ||
1679 | #define MWL8K_CAP_RX_ANTENNA_MASK 0x000e0000 | ||
1680 | #define MWL8K_CAP_TX_ANTENNA_MASK 0x0001c000 | ||
1681 | #define MWL8K_CAP_DELAY_BA 0x00003000 | ||
1682 | #define MWL8K_CAP_MIMO 0x00000200 | ||
1683 | #define MWL8K_CAP_40MHZ 0x00000100 | ||
1684 | #define MWL8K_CAP_BAND_MASK 0x00000007 | ||
1685 | #define MWL8K_CAP_5GHZ 0x00000004 | ||
1686 | #define MWL8K_CAP_2GHZ4 0x00000001 | ||
1687 | |||
1688 | static void | ||
1689 | mwl8k_set_ht_caps(struct ieee80211_hw *hw, | ||
1690 | struct ieee80211_supported_band *band, u32 cap) | ||
1691 | { | ||
1692 | int rx_streams; | ||
1693 | int tx_streams; | ||
1694 | |||
1695 | band->ht_cap.ht_supported = 1; | ||
1696 | |||
1697 | if (cap & MWL8K_CAP_MAX_AMSDU) | ||
1698 | band->ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU; | ||
1699 | if (cap & MWL8K_CAP_GREENFIELD) | ||
1700 | band->ht_cap.cap |= IEEE80211_HT_CAP_GRN_FLD; | ||
1701 | if (cap & MWL8K_CAP_AMPDU) { | ||
1702 | hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; | ||
1703 | band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; | ||
1704 | band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE; | ||
1705 | } | ||
1706 | if (cap & MWL8K_CAP_RX_STBC) | ||
1707 | band->ht_cap.cap |= IEEE80211_HT_CAP_RX_STBC; | ||
1708 | if (cap & MWL8K_CAP_TX_STBC) | ||
1709 | band->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC; | ||
1710 | if (cap & MWL8K_CAP_SHORTGI_40MHZ) | ||
1711 | band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; | ||
1712 | if (cap & MWL8K_CAP_SHORTGI_20MHZ) | ||
1713 | band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; | ||
1714 | if (cap & MWL8K_CAP_DELAY_BA) | ||
1715 | band->ht_cap.cap |= IEEE80211_HT_CAP_DELAY_BA; | ||
1716 | if (cap & MWL8K_CAP_40MHZ) | ||
1717 | band->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
1718 | |||
1719 | rx_streams = hweight32(cap & MWL8K_CAP_RX_ANTENNA_MASK); | ||
1720 | tx_streams = hweight32(cap & MWL8K_CAP_TX_ANTENNA_MASK); | ||
1721 | |||
1722 | band->ht_cap.mcs.rx_mask[0] = 0xff; | ||
1723 | if (rx_streams >= 2) | ||
1724 | band->ht_cap.mcs.rx_mask[1] = 0xff; | ||
1725 | if (rx_streams >= 3) | ||
1726 | band->ht_cap.mcs.rx_mask[2] = 0xff; | ||
1727 | band->ht_cap.mcs.rx_mask[4] = 0x01; | ||
1728 | band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | ||
1729 | |||
1730 | if (rx_streams != tx_streams) { | ||
1731 | band->ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; | ||
1732 | band->ht_cap.mcs.tx_params |= (tx_streams - 1) << | ||
1733 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; | ||
1734 | } | ||
1735 | } | ||
1736 | |||
1737 | static void | ||
1738 | mwl8k_set_caps(struct ieee80211_hw *hw, u32 caps) | ||
1739 | { | ||
1740 | struct mwl8k_priv *priv = hw->priv; | ||
1741 | |||
1742 | if ((caps & MWL8K_CAP_2GHZ4) || !(caps & MWL8K_CAP_BAND_MASK)) { | ||
1743 | mwl8k_setup_2ghz_band(hw); | ||
1744 | if (caps & MWL8K_CAP_MIMO) | ||
1745 | mwl8k_set_ht_caps(hw, &priv->band_24, caps); | ||
1746 | } | ||
1747 | |||
1748 | if (caps & MWL8K_CAP_5GHZ) { | ||
1749 | mwl8k_setup_5ghz_band(hw); | ||
1750 | if (caps & MWL8K_CAP_MIMO) | ||
1751 | mwl8k_set_ht_caps(hw, &priv->band_50, caps); | ||
1752 | } | ||
1753 | } | ||
1754 | |||
1681 | static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) | 1755 | static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) |
1682 | { | 1756 | { |
1683 | struct mwl8k_priv *priv = hw->priv; | 1757 | struct mwl8k_priv *priv = hw->priv; |
@@ -1708,6 +1782,9 @@ static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) | |||
1708 | priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); | 1782 | priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); |
1709 | priv->fw_rev = le32_to_cpu(cmd->fw_rev); | 1783 | priv->fw_rev = le32_to_cpu(cmd->fw_rev); |
1710 | priv->hw_rev = cmd->hw_rev; | 1784 | priv->hw_rev = cmd->hw_rev; |
1785 | mwl8k_set_caps(hw, le32_to_cpu(cmd->caps)); | ||
1786 | priv->ap_macids_supported = 0x00000000; | ||
1787 | priv->sta_macids_supported = 0x00000001; | ||
1711 | } | 1788 | } |
1712 | 1789 | ||
1713 | kfree(cmd); | 1790 | kfree(cmd); |
@@ -1761,6 +1838,9 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) | |||
1761 | priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); | 1838 | priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); |
1762 | priv->fw_rev = le32_to_cpu(cmd->fw_rev); | 1839 | priv->fw_rev = le32_to_cpu(cmd->fw_rev); |
1763 | priv->hw_rev = cmd->hw_rev; | 1840 | priv->hw_rev = cmd->hw_rev; |
1841 | mwl8k_setup_2ghz_band(hw); | ||
1842 | priv->ap_macids_supported = 0x000000ff; | ||
1843 | priv->sta_macids_supported = 0x00000000; | ||
1764 | 1844 | ||
1765 | off = le32_to_cpu(cmd->wcbbase0) & 0xffff; | 1845 | off = le32_to_cpu(cmd->wcbbase0) & 0xffff; |
1766 | iowrite32(cpu_to_le32(priv->txq[0].txd_dma), priv->sram + off); | 1846 | iowrite32(cpu_to_le32(priv->txq[0].txd_dma), priv->sram + off); |
@@ -1806,7 +1886,9 @@ struct mwl8k_cmd_set_hw_spec { | |||
1806 | __le32 total_rxd; | 1886 | __le32 total_rxd; |
1807 | } __attribute__((packed)); | 1887 | } __attribute__((packed)); |
1808 | 1888 | ||
1809 | #define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080 | 1889 | #define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080 |
1890 | #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP 0x00000020 | ||
1891 | #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON 0x00000010 | ||
1810 | 1892 | ||
1811 | static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw) | 1893 | static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw) |
1812 | { | 1894 | { |
@@ -1827,7 +1909,9 @@ static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw) | |||
1827 | cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES); | 1909 | cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES); |
1828 | for (i = 0; i < MWL8K_TX_QUEUES; i++) | 1910 | for (i = 0; i < MWL8K_TX_QUEUES; i++) |
1829 | cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].txd_dma); | 1911 | cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].txd_dma); |
1830 | cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT); | 1912 | cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT | |
1913 | MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP | | ||
1914 | MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON); | ||
1831 | cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS); | 1915 | cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS); |
1832 | cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS); | 1916 | cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS); |
1833 | 1917 | ||
@@ -1897,9 +1981,9 @@ __mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int allmulti, | |||
1897 | } | 1981 | } |
1898 | 1982 | ||
1899 | /* | 1983 | /* |
1900 | * CMD_802_11_GET_STAT. | 1984 | * CMD_GET_STAT. |
1901 | */ | 1985 | */ |
1902 | struct mwl8k_cmd_802_11_get_stat { | 1986 | struct mwl8k_cmd_get_stat { |
1903 | struct mwl8k_cmd_pkt header; | 1987 | struct mwl8k_cmd_pkt header; |
1904 | __le32 stats[64]; | 1988 | __le32 stats[64]; |
1905 | } __attribute__((packed)); | 1989 | } __attribute__((packed)); |
@@ -1909,10 +1993,10 @@ struct mwl8k_cmd_802_11_get_stat { | |||
1909 | #define MWL8K_STAT_FCS_ERROR 24 | 1993 | #define MWL8K_STAT_FCS_ERROR 24 |
1910 | #define MWL8K_STAT_RTS_SUCCESS 11 | 1994 | #define MWL8K_STAT_RTS_SUCCESS 11 |
1911 | 1995 | ||
1912 | static int mwl8k_cmd_802_11_get_stat(struct ieee80211_hw *hw, | 1996 | static int mwl8k_cmd_get_stat(struct ieee80211_hw *hw, |
1913 | struct ieee80211_low_level_stats *stats) | 1997 | struct ieee80211_low_level_stats *stats) |
1914 | { | 1998 | { |
1915 | struct mwl8k_cmd_802_11_get_stat *cmd; | 1999 | struct mwl8k_cmd_get_stat *cmd; |
1916 | int rc; | 2000 | int rc; |
1917 | 2001 | ||
1918 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2002 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
@@ -1939,9 +2023,9 @@ static int mwl8k_cmd_802_11_get_stat(struct ieee80211_hw *hw, | |||
1939 | } | 2023 | } |
1940 | 2024 | ||
1941 | /* | 2025 | /* |
1942 | * CMD_802_11_RADIO_CONTROL. | 2026 | * CMD_RADIO_CONTROL. |
1943 | */ | 2027 | */ |
1944 | struct mwl8k_cmd_802_11_radio_control { | 2028 | struct mwl8k_cmd_radio_control { |
1945 | struct mwl8k_cmd_pkt header; | 2029 | struct mwl8k_cmd_pkt header; |
1946 | __le16 action; | 2030 | __le16 action; |
1947 | __le16 control; | 2031 | __le16 control; |
@@ -1949,10 +2033,10 @@ struct mwl8k_cmd_802_11_radio_control { | |||
1949 | } __attribute__((packed)); | 2033 | } __attribute__((packed)); |
1950 | 2034 | ||
1951 | static int | 2035 | static int |
1952 | mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, bool enable, bool force) | 2036 | mwl8k_cmd_radio_control(struct ieee80211_hw *hw, bool enable, bool force) |
1953 | { | 2037 | { |
1954 | struct mwl8k_priv *priv = hw->priv; | 2038 | struct mwl8k_priv *priv = hw->priv; |
1955 | struct mwl8k_cmd_802_11_radio_control *cmd; | 2039 | struct mwl8k_cmd_radio_control *cmd; |
1956 | int rc; | 2040 | int rc; |
1957 | 2041 | ||
1958 | if (enable == priv->radio_on && !force) | 2042 | if (enable == priv->radio_on && !force) |
@@ -1977,36 +2061,32 @@ mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, bool enable, bool force) | |||
1977 | return rc; | 2061 | return rc; |
1978 | } | 2062 | } |
1979 | 2063 | ||
1980 | static int mwl8k_cmd_802_11_radio_disable(struct ieee80211_hw *hw) | 2064 | static int mwl8k_cmd_radio_disable(struct ieee80211_hw *hw) |
1981 | { | 2065 | { |
1982 | return mwl8k_cmd_802_11_radio_control(hw, 0, 0); | 2066 | return mwl8k_cmd_radio_control(hw, 0, 0); |
1983 | } | 2067 | } |
1984 | 2068 | ||
1985 | static int mwl8k_cmd_802_11_radio_enable(struct ieee80211_hw *hw) | 2069 | static int mwl8k_cmd_radio_enable(struct ieee80211_hw *hw) |
1986 | { | 2070 | { |
1987 | return mwl8k_cmd_802_11_radio_control(hw, 1, 0); | 2071 | return mwl8k_cmd_radio_control(hw, 1, 0); |
1988 | } | 2072 | } |
1989 | 2073 | ||
1990 | static int | 2074 | static int |
1991 | mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) | 2075 | mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) |
1992 | { | 2076 | { |
1993 | struct mwl8k_priv *priv; | 2077 | struct mwl8k_priv *priv = hw->priv; |
1994 | |||
1995 | if (hw == NULL || hw->priv == NULL) | ||
1996 | return -EINVAL; | ||
1997 | priv = hw->priv; | ||
1998 | 2078 | ||
1999 | priv->radio_short_preamble = short_preamble; | 2079 | priv->radio_short_preamble = short_preamble; |
2000 | 2080 | ||
2001 | return mwl8k_cmd_802_11_radio_control(hw, 1, 1); | 2081 | return mwl8k_cmd_radio_control(hw, 1, 1); |
2002 | } | 2082 | } |
2003 | 2083 | ||
2004 | /* | 2084 | /* |
2005 | * CMD_802_11_RF_TX_POWER. | 2085 | * CMD_RF_TX_POWER. |
2006 | */ | 2086 | */ |
2007 | #define MWL8K_TX_POWER_LEVEL_TOTAL 8 | 2087 | #define MWL8K_TX_POWER_LEVEL_TOTAL 8 |
2008 | 2088 | ||
2009 | struct mwl8k_cmd_802_11_rf_tx_power { | 2089 | struct mwl8k_cmd_rf_tx_power { |
2010 | struct mwl8k_cmd_pkt header; | 2090 | struct mwl8k_cmd_pkt header; |
2011 | __le16 action; | 2091 | __le16 action; |
2012 | __le16 support_level; | 2092 | __le16 support_level; |
@@ -2015,9 +2095,9 @@ struct mwl8k_cmd_802_11_rf_tx_power { | |||
2015 | __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL]; | 2095 | __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL]; |
2016 | } __attribute__((packed)); | 2096 | } __attribute__((packed)); |
2017 | 2097 | ||
2018 | static int mwl8k_cmd_802_11_rf_tx_power(struct ieee80211_hw *hw, int dBm) | 2098 | static int mwl8k_cmd_rf_tx_power(struct ieee80211_hw *hw, int dBm) |
2019 | { | 2099 | { |
2020 | struct mwl8k_cmd_802_11_rf_tx_power *cmd; | 2100 | struct mwl8k_cmd_rf_tx_power *cmd; |
2021 | int rc; | 2101 | int rc; |
2022 | 2102 | ||
2023 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2103 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
@@ -2069,6 +2149,36 @@ mwl8k_cmd_rf_antenna(struct ieee80211_hw *hw, int antenna, int mask) | |||
2069 | } | 2149 | } |
2070 | 2150 | ||
2071 | /* | 2151 | /* |
2152 | * CMD_SET_BEACON. | ||
2153 | */ | ||
2154 | struct mwl8k_cmd_set_beacon { | ||
2155 | struct mwl8k_cmd_pkt header; | ||
2156 | __le16 beacon_len; | ||
2157 | __u8 beacon[0]; | ||
2158 | }; | ||
2159 | |||
2160 | static int mwl8k_cmd_set_beacon(struct ieee80211_hw *hw, | ||
2161 | struct ieee80211_vif *vif, u8 *beacon, int len) | ||
2162 | { | ||
2163 | struct mwl8k_cmd_set_beacon *cmd; | ||
2164 | int rc; | ||
2165 | |||
2166 | cmd = kzalloc(sizeof(*cmd) + len, GFP_KERNEL); | ||
2167 | if (cmd == NULL) | ||
2168 | return -ENOMEM; | ||
2169 | |||
2170 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_BEACON); | ||
2171 | cmd->header.length = cpu_to_le16(sizeof(*cmd) + len); | ||
2172 | cmd->beacon_len = cpu_to_le16(len); | ||
2173 | memcpy(cmd->beacon, beacon, len); | ||
2174 | |||
2175 | rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header); | ||
2176 | kfree(cmd); | ||
2177 | |||
2178 | return rc; | ||
2179 | } | ||
2180 | |||
2181 | /* | ||
2072 | * CMD_SET_PRE_SCAN. | 2182 | * CMD_SET_PRE_SCAN. |
2073 | */ | 2183 | */ |
2074 | struct mwl8k_cmd_set_pre_scan { | 2184 | struct mwl8k_cmd_set_pre_scan { |
@@ -2103,7 +2213,7 @@ struct mwl8k_cmd_set_post_scan { | |||
2103 | } __attribute__((packed)); | 2213 | } __attribute__((packed)); |
2104 | 2214 | ||
2105 | static int | 2215 | static int |
2106 | mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 *mac) | 2216 | mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, const __u8 *mac) |
2107 | { | 2217 | { |
2108 | struct mwl8k_cmd_set_post_scan *cmd; | 2218 | struct mwl8k_cmd_set_post_scan *cmd; |
2109 | int rc; | 2219 | int rc; |
@@ -2134,8 +2244,9 @@ struct mwl8k_cmd_set_rf_channel { | |||
2134 | } __attribute__((packed)); | 2244 | } __attribute__((packed)); |
2135 | 2245 | ||
2136 | static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw, | 2246 | static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw, |
2137 | struct ieee80211_channel *channel) | 2247 | struct ieee80211_conf *conf) |
2138 | { | 2248 | { |
2249 | struct ieee80211_channel *channel = conf->channel; | ||
2139 | struct mwl8k_cmd_set_rf_channel *cmd; | 2250 | struct mwl8k_cmd_set_rf_channel *cmd; |
2140 | int rc; | 2251 | int rc; |
2141 | 2252 | ||
@@ -2147,10 +2258,19 @@ static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw, | |||
2147 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2258 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2148 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); | 2259 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); |
2149 | cmd->current_channel = channel->hw_value; | 2260 | cmd->current_channel = channel->hw_value; |
2261 | |||
2150 | if (channel->band == IEEE80211_BAND_2GHZ) | 2262 | if (channel->band == IEEE80211_BAND_2GHZ) |
2151 | cmd->channel_flags = cpu_to_le32(0x00000081); | 2263 | cmd->channel_flags |= cpu_to_le32(0x00000001); |
2152 | else | 2264 | else if (channel->band == IEEE80211_BAND_5GHZ) |
2153 | cmd->channel_flags = cpu_to_le32(0x00000000); | 2265 | cmd->channel_flags |= cpu_to_le32(0x00000004); |
2266 | |||
2267 | if (conf->channel_type == NL80211_CHAN_NO_HT || | ||
2268 | conf->channel_type == NL80211_CHAN_HT20) | ||
2269 | cmd->channel_flags |= cpu_to_le32(0x00000080); | ||
2270 | else if (conf->channel_type == NL80211_CHAN_HT40MINUS) | ||
2271 | cmd->channel_flags |= cpu_to_le32(0x000001900); | ||
2272 | else if (conf->channel_type == NL80211_CHAN_HT40PLUS) | ||
2273 | cmd->channel_flags |= cpu_to_le32(0x000000900); | ||
2154 | 2274 | ||
2155 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2275 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2156 | kfree(cmd); | 2276 | kfree(cmd); |
@@ -2159,85 +2279,75 @@ static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw, | |||
2159 | } | 2279 | } |
2160 | 2280 | ||
2161 | /* | 2281 | /* |
2162 | * CMD_SET_SLOT. | 2282 | * CMD_SET_AID. |
2163 | */ | 2283 | */ |
2164 | struct mwl8k_cmd_set_slot { | 2284 | #define MWL8K_FRAME_PROT_DISABLED 0x00 |
2165 | struct mwl8k_cmd_pkt header; | 2285 | #define MWL8K_FRAME_PROT_11G 0x07 |
2166 | __le16 action; | 2286 | #define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02 |
2167 | __u8 short_slot; | 2287 | #define MWL8K_FRAME_PROT_11N_HT_ALL 0x06 |
2168 | } __attribute__((packed)); | ||
2169 | |||
2170 | static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, bool short_slot_time) | ||
2171 | { | ||
2172 | struct mwl8k_cmd_set_slot *cmd; | ||
2173 | int rc; | ||
2174 | |||
2175 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2176 | if (cmd == NULL) | ||
2177 | return -ENOMEM; | ||
2178 | |||
2179 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_SLOT); | ||
2180 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2181 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); | ||
2182 | cmd->short_slot = short_slot_time; | ||
2183 | |||
2184 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2185 | kfree(cmd); | ||
2186 | 2288 | ||
2187 | return rc; | 2289 | struct mwl8k_cmd_update_set_aid { |
2188 | } | 2290 | struct mwl8k_cmd_pkt header; |
2291 | __le16 aid; | ||
2189 | 2292 | ||
2190 | /* | 2293 | /* AP's MAC address (BSSID) */ |
2191 | * CMD_MIMO_CONFIG. | 2294 | __u8 bssid[ETH_ALEN]; |
2192 | */ | 2295 | __le16 protection_mode; |
2193 | struct mwl8k_cmd_mimo_config { | 2296 | __u8 supp_rates[14]; |
2194 | struct mwl8k_cmd_pkt header; | ||
2195 | __le32 action; | ||
2196 | __u8 rx_antenna_map; | ||
2197 | __u8 tx_antenna_map; | ||
2198 | } __attribute__((packed)); | 2297 | } __attribute__((packed)); |
2199 | 2298 | ||
2200 | static int mwl8k_cmd_mimo_config(struct ieee80211_hw *hw, __u8 rx, __u8 tx) | 2299 | static void legacy_rate_mask_to_array(u8 *rates, u32 mask) |
2201 | { | 2300 | { |
2202 | struct mwl8k_cmd_mimo_config *cmd; | 2301 | int i; |
2203 | int rc; | 2302 | int j; |
2204 | |||
2205 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2206 | if (cmd == NULL) | ||
2207 | return -ENOMEM; | ||
2208 | |||
2209 | cmd->header.code = cpu_to_le16(MWL8K_CMD_MIMO_CONFIG); | ||
2210 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2211 | cmd->action = cpu_to_le32((u32)MWL8K_CMD_SET); | ||
2212 | cmd->rx_antenna_map = rx; | ||
2213 | cmd->tx_antenna_map = tx; | ||
2214 | 2303 | ||
2215 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2304 | /* |
2216 | kfree(cmd); | 2305 | * Clear nonstandard rates 4 and 13. |
2306 | */ | ||
2307 | mask &= 0x1fef; | ||
2217 | 2308 | ||
2218 | return rc; | 2309 | for (i = 0, j = 0; i < 14; i++) { |
2310 | if (mask & (1 << i)) | ||
2311 | rates[j++] = mwl8k_rates_24[i].hw_value; | ||
2312 | } | ||
2219 | } | 2313 | } |
2220 | 2314 | ||
2221 | /* | 2315 | static int |
2222 | * CMD_ENABLE_SNIFFER. | 2316 | mwl8k_cmd_set_aid(struct ieee80211_hw *hw, |
2223 | */ | 2317 | struct ieee80211_vif *vif, u32 legacy_rate_mask) |
2224 | struct mwl8k_cmd_enable_sniffer { | ||
2225 | struct mwl8k_cmd_pkt header; | ||
2226 | __le32 action; | ||
2227 | } __attribute__((packed)); | ||
2228 | |||
2229 | static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable) | ||
2230 | { | 2318 | { |
2231 | struct mwl8k_cmd_enable_sniffer *cmd; | 2319 | struct mwl8k_cmd_update_set_aid *cmd; |
2320 | u16 prot_mode; | ||
2232 | int rc; | 2321 | int rc; |
2233 | 2322 | ||
2234 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2323 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2235 | if (cmd == NULL) | 2324 | if (cmd == NULL) |
2236 | return -ENOMEM; | 2325 | return -ENOMEM; |
2237 | 2326 | ||
2238 | cmd->header.code = cpu_to_le16(MWL8K_CMD_ENABLE_SNIFFER); | 2327 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_AID); |
2239 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2328 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2240 | cmd->action = cpu_to_le32(!!enable); | 2329 | cmd->aid = cpu_to_le16(vif->bss_conf.aid); |
2330 | memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN); | ||
2331 | |||
2332 | if (vif->bss_conf.use_cts_prot) { | ||
2333 | prot_mode = MWL8K_FRAME_PROT_11G; | ||
2334 | } else { | ||
2335 | switch (vif->bss_conf.ht_operation_mode & | ||
2336 | IEEE80211_HT_OP_MODE_PROTECTION) { | ||
2337 | case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: | ||
2338 | prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY; | ||
2339 | break; | ||
2340 | case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED: | ||
2341 | prot_mode = MWL8K_FRAME_PROT_11N_HT_ALL; | ||
2342 | break; | ||
2343 | default: | ||
2344 | prot_mode = MWL8K_FRAME_PROT_DISABLED; | ||
2345 | break; | ||
2346 | } | ||
2347 | } | ||
2348 | cmd->protection_mode = cpu_to_le16(prot_mode); | ||
2349 | |||
2350 | legacy_rate_mask_to_array(cmd->supp_rates, legacy_rate_mask); | ||
2241 | 2351 | ||
2242 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2352 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2243 | kfree(cmd); | 2353 | kfree(cmd); |
@@ -2246,37 +2356,32 @@ static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable) | |||
2246 | } | 2356 | } |
2247 | 2357 | ||
2248 | /* | 2358 | /* |
2249 | * CMD_SET_MAC_ADDR. | 2359 | * CMD_SET_RATE. |
2250 | */ | 2360 | */ |
2251 | struct mwl8k_cmd_set_mac_addr { | 2361 | struct mwl8k_cmd_set_rate { |
2252 | struct mwl8k_cmd_pkt header; | 2362 | struct mwl8k_cmd_pkt header; |
2253 | union { | 2363 | __u8 legacy_rates[14]; |
2254 | struct { | 2364 | |
2255 | __le16 mac_type; | 2365 | /* Bitmap for supported MCS codes. */ |
2256 | __u8 mac_addr[ETH_ALEN]; | 2366 | __u8 mcs_set[16]; |
2257 | } mbss; | 2367 | __u8 reserved[16]; |
2258 | __u8 mac_addr[ETH_ALEN]; | ||
2259 | }; | ||
2260 | } __attribute__((packed)); | 2368 | } __attribute__((packed)); |
2261 | 2369 | ||
2262 | static int mwl8k_set_mac_addr(struct ieee80211_hw *hw, u8 *mac) | 2370 | static int |
2371 | mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
2372 | u32 legacy_rate_mask, u8 *mcs_rates) | ||
2263 | { | 2373 | { |
2264 | struct mwl8k_priv *priv = hw->priv; | 2374 | struct mwl8k_cmd_set_rate *cmd; |
2265 | struct mwl8k_cmd_set_mac_addr *cmd; | ||
2266 | int rc; | 2375 | int rc; |
2267 | 2376 | ||
2268 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2377 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2269 | if (cmd == NULL) | 2378 | if (cmd == NULL) |
2270 | return -ENOMEM; | 2379 | return -ENOMEM; |
2271 | 2380 | ||
2272 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR); | 2381 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE); |
2273 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2382 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2274 | if (priv->ap_fw) { | 2383 | legacy_rate_mask_to_array(cmd->legacy_rates, legacy_rate_mask); |
2275 | cmd->mbss.mac_type = 0; | 2384 | memcpy(cmd->mcs_set, mcs_rates, 16); |
2276 | memcpy(cmd->mbss.mac_addr, mac, ETH_ALEN); | ||
2277 | } else { | ||
2278 | memcpy(cmd->mac_addr, mac, ETH_ALEN); | ||
2279 | } | ||
2280 | 2385 | ||
2281 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2386 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2282 | kfree(cmd); | 2387 | kfree(cmd); |
@@ -2284,29 +2389,40 @@ static int mwl8k_set_mac_addr(struct ieee80211_hw *hw, u8 *mac) | |||
2284 | return rc; | 2389 | return rc; |
2285 | } | 2390 | } |
2286 | 2391 | ||
2287 | |||
2288 | /* | 2392 | /* |
2289 | * CMD_SET_RATEADAPT_MODE. | 2393 | * CMD_FINALIZE_JOIN. |
2290 | */ | 2394 | */ |
2291 | struct mwl8k_cmd_set_rate_adapt_mode { | 2395 | #define MWL8K_FJ_BEACON_MAXLEN 128 |
2396 | |||
2397 | struct mwl8k_cmd_finalize_join { | ||
2292 | struct mwl8k_cmd_pkt header; | 2398 | struct mwl8k_cmd_pkt header; |
2293 | __le16 action; | 2399 | __le32 sleep_interval; /* Number of beacon periods to sleep */ |
2294 | __le16 mode; | 2400 | __u8 beacon_data[MWL8K_FJ_BEACON_MAXLEN]; |
2295 | } __attribute__((packed)); | 2401 | } __attribute__((packed)); |
2296 | 2402 | ||
2297 | static int mwl8k_cmd_setrateadaptmode(struct ieee80211_hw *hw, __u16 mode) | 2403 | static int mwl8k_cmd_finalize_join(struct ieee80211_hw *hw, void *frame, |
2404 | int framelen, int dtim) | ||
2298 | { | 2405 | { |
2299 | struct mwl8k_cmd_set_rate_adapt_mode *cmd; | 2406 | struct mwl8k_cmd_finalize_join *cmd; |
2407 | struct ieee80211_mgmt *payload = frame; | ||
2408 | int payload_len; | ||
2300 | int rc; | 2409 | int rc; |
2301 | 2410 | ||
2302 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2411 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2303 | if (cmd == NULL) | 2412 | if (cmd == NULL) |
2304 | return -ENOMEM; | 2413 | return -ENOMEM; |
2305 | 2414 | ||
2306 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATEADAPT_MODE); | 2415 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_FINALIZE_JOIN); |
2307 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2416 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2308 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); | 2417 | cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1); |
2309 | cmd->mode = cpu_to_le16(mode); | 2418 | |
2419 | payload_len = framelen - ieee80211_hdrlen(payload->frame_control); | ||
2420 | if (payload_len < 0) | ||
2421 | payload_len = 0; | ||
2422 | else if (payload_len > MWL8K_FJ_BEACON_MAXLEN) | ||
2423 | payload_len = MWL8K_FJ_BEACON_MAXLEN; | ||
2424 | |||
2425 | memcpy(cmd->beacon_data, &payload->u.beacon, payload_len); | ||
2310 | 2426 | ||
2311 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2427 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2312 | kfree(cmd); | 2428 | kfree(cmd); |
@@ -2315,59 +2431,57 @@ static int mwl8k_cmd_setrateadaptmode(struct ieee80211_hw *hw, __u16 mode) | |||
2315 | } | 2431 | } |
2316 | 2432 | ||
2317 | /* | 2433 | /* |
2318 | * CMD_SET_WMM_MODE. | 2434 | * CMD_SET_RTS_THRESHOLD. |
2319 | */ | 2435 | */ |
2320 | struct mwl8k_cmd_set_wmm { | 2436 | struct mwl8k_cmd_set_rts_threshold { |
2321 | struct mwl8k_cmd_pkt header; | 2437 | struct mwl8k_cmd_pkt header; |
2322 | __le16 action; | 2438 | __le16 action; |
2439 | __le16 threshold; | ||
2323 | } __attribute__((packed)); | 2440 | } __attribute__((packed)); |
2324 | 2441 | ||
2325 | static int mwl8k_set_wmm(struct ieee80211_hw *hw, bool enable) | 2442 | static int |
2443 | mwl8k_cmd_set_rts_threshold(struct ieee80211_hw *hw, int rts_thresh) | ||
2326 | { | 2444 | { |
2327 | struct mwl8k_priv *priv = hw->priv; | 2445 | struct mwl8k_cmd_set_rts_threshold *cmd; |
2328 | struct mwl8k_cmd_set_wmm *cmd; | ||
2329 | int rc; | 2446 | int rc; |
2330 | 2447 | ||
2331 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2448 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2332 | if (cmd == NULL) | 2449 | if (cmd == NULL) |
2333 | return -ENOMEM; | 2450 | return -ENOMEM; |
2334 | 2451 | ||
2335 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_WMM_MODE); | 2452 | cmd->header.code = cpu_to_le16(MWL8K_CMD_RTS_THRESHOLD); |
2336 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2453 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2337 | cmd->action = cpu_to_le16(!!enable); | 2454 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); |
2455 | cmd->threshold = cpu_to_le16(rts_thresh); | ||
2338 | 2456 | ||
2339 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2457 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2340 | kfree(cmd); | 2458 | kfree(cmd); |
2341 | 2459 | ||
2342 | if (!rc) | ||
2343 | priv->wmm_enabled = enable; | ||
2344 | |||
2345 | return rc; | 2460 | return rc; |
2346 | } | 2461 | } |
2347 | 2462 | ||
2348 | /* | 2463 | /* |
2349 | * CMD_SET_RTS_THRESHOLD. | 2464 | * CMD_SET_SLOT. |
2350 | */ | 2465 | */ |
2351 | struct mwl8k_cmd_rts_threshold { | 2466 | struct mwl8k_cmd_set_slot { |
2352 | struct mwl8k_cmd_pkt header; | 2467 | struct mwl8k_cmd_pkt header; |
2353 | __le16 action; | 2468 | __le16 action; |
2354 | __le16 threshold; | 2469 | __u8 short_slot; |
2355 | } __attribute__((packed)); | 2470 | } __attribute__((packed)); |
2356 | 2471 | ||
2357 | static int mwl8k_rts_threshold(struct ieee80211_hw *hw, | 2472 | static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, bool short_slot_time) |
2358 | u16 action, u16 threshold) | ||
2359 | { | 2473 | { |
2360 | struct mwl8k_cmd_rts_threshold *cmd; | 2474 | struct mwl8k_cmd_set_slot *cmd; |
2361 | int rc; | 2475 | int rc; |
2362 | 2476 | ||
2363 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2477 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2364 | if (cmd == NULL) | 2478 | if (cmd == NULL) |
2365 | return -ENOMEM; | 2479 | return -ENOMEM; |
2366 | 2480 | ||
2367 | cmd->header.code = cpu_to_le16(MWL8K_CMD_RTS_THRESHOLD); | 2481 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_SLOT); |
2368 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2482 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2369 | cmd->action = cpu_to_le16(action); | 2483 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); |
2370 | cmd->threshold = cpu_to_le16(threshold); | 2484 | cmd->short_slot = short_slot_time; |
2371 | 2485 | ||
2372 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2486 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2373 | kfree(cmd); | 2487 | kfree(cmd); |
@@ -2426,9 +2540,9 @@ struct mwl8k_cmd_set_edca_params { | |||
2426 | MWL8K_SET_EDCA_AIFS) | 2540 | MWL8K_SET_EDCA_AIFS) |
2427 | 2541 | ||
2428 | static int | 2542 | static int |
2429 | mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, | 2543 | mwl8k_cmd_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, |
2430 | __u16 cw_min, __u16 cw_max, | 2544 | __u16 cw_min, __u16 cw_max, |
2431 | __u8 aifs, __u16 txop) | 2545 | __u8 aifs, __u16 txop) |
2432 | { | 2546 | { |
2433 | struct mwl8k_priv *priv = hw->priv; | 2547 | struct mwl8k_priv *priv = hw->priv; |
2434 | struct mwl8k_cmd_set_edca_params *cmd; | 2548 | struct mwl8k_cmd_set_edca_params *cmd; |
@@ -2438,12 +2552,6 @@ mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, | |||
2438 | if (cmd == NULL) | 2552 | if (cmd == NULL) |
2439 | return -ENOMEM; | 2553 | return -ENOMEM; |
2440 | 2554 | ||
2441 | /* | ||
2442 | * Queues 0 (BE) and 1 (BK) are swapped in hardware for | ||
2443 | * this call. | ||
2444 | */ | ||
2445 | qnum ^= !(qnum >> 1); | ||
2446 | |||
2447 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_EDCA_PARAMS); | 2555 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_EDCA_PARAMS); |
2448 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2556 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2449 | cmd->action = cpu_to_le16(MWL8K_SET_EDCA_ALL); | 2557 | cmd->action = cpu_to_le16(MWL8K_SET_EDCA_ALL); |
@@ -2467,170 +2575,259 @@ mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, | |||
2467 | } | 2575 | } |
2468 | 2576 | ||
2469 | /* | 2577 | /* |
2470 | * CMD_FINALIZE_JOIN. | 2578 | * CMD_SET_WMM_MODE. |
2471 | */ | 2579 | */ |
2472 | #define MWL8K_FJ_BEACON_MAXLEN 128 | 2580 | struct mwl8k_cmd_set_wmm_mode { |
2473 | |||
2474 | struct mwl8k_cmd_finalize_join { | ||
2475 | struct mwl8k_cmd_pkt header; | 2581 | struct mwl8k_cmd_pkt header; |
2476 | __le32 sleep_interval; /* Number of beacon periods to sleep */ | 2582 | __le16 action; |
2477 | __u8 beacon_data[MWL8K_FJ_BEACON_MAXLEN]; | ||
2478 | } __attribute__((packed)); | 2583 | } __attribute__((packed)); |
2479 | 2584 | ||
2480 | static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame, | 2585 | static int mwl8k_cmd_set_wmm_mode(struct ieee80211_hw *hw, bool enable) |
2481 | int framelen, int dtim) | ||
2482 | { | 2586 | { |
2483 | struct mwl8k_cmd_finalize_join *cmd; | 2587 | struct mwl8k_priv *priv = hw->priv; |
2484 | struct ieee80211_mgmt *payload = frame; | 2588 | struct mwl8k_cmd_set_wmm_mode *cmd; |
2485 | int payload_len; | ||
2486 | int rc; | 2589 | int rc; |
2487 | 2590 | ||
2488 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2591 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2489 | if (cmd == NULL) | 2592 | if (cmd == NULL) |
2490 | return -ENOMEM; | 2593 | return -ENOMEM; |
2491 | 2594 | ||
2492 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_FINALIZE_JOIN); | 2595 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_WMM_MODE); |
2493 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2596 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2494 | cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1); | 2597 | cmd->action = cpu_to_le16(!!enable); |
2495 | |||
2496 | payload_len = framelen - ieee80211_hdrlen(payload->frame_control); | ||
2497 | if (payload_len < 0) | ||
2498 | payload_len = 0; | ||
2499 | else if (payload_len > MWL8K_FJ_BEACON_MAXLEN) | ||
2500 | payload_len = MWL8K_FJ_BEACON_MAXLEN; | ||
2501 | |||
2502 | memcpy(cmd->beacon_data, &payload->u.beacon, payload_len); | ||
2503 | 2598 | ||
2504 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2599 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2505 | kfree(cmd); | 2600 | kfree(cmd); |
2506 | 2601 | ||
2602 | if (!rc) | ||
2603 | priv->wmm_enabled = enable; | ||
2604 | |||
2507 | return rc; | 2605 | return rc; |
2508 | } | 2606 | } |
2509 | 2607 | ||
2510 | /* | 2608 | /* |
2511 | * CMD_UPDATE_STADB. | 2609 | * CMD_MIMO_CONFIG. |
2512 | */ | 2610 | */ |
2513 | struct mwl8k_cmd_update_sta_db { | 2611 | struct mwl8k_cmd_mimo_config { |
2514 | struct mwl8k_cmd_pkt header; | 2612 | struct mwl8k_cmd_pkt header; |
2613 | __le32 action; | ||
2614 | __u8 rx_antenna_map; | ||
2615 | __u8 tx_antenna_map; | ||
2616 | } __attribute__((packed)); | ||
2515 | 2617 | ||
2516 | /* See STADB_ACTION_TYPE */ | 2618 | static int mwl8k_cmd_mimo_config(struct ieee80211_hw *hw, __u8 rx, __u8 tx) |
2517 | __le32 action; | 2619 | { |
2620 | struct mwl8k_cmd_mimo_config *cmd; | ||
2621 | int rc; | ||
2518 | 2622 | ||
2519 | /* Peer MAC address */ | 2623 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2520 | __u8 peer_addr[ETH_ALEN]; | 2624 | if (cmd == NULL) |
2625 | return -ENOMEM; | ||
2521 | 2626 | ||
2522 | __le32 reserved; | 2627 | cmd->header.code = cpu_to_le16(MWL8K_CMD_MIMO_CONFIG); |
2628 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2629 | cmd->action = cpu_to_le32((u32)MWL8K_CMD_SET); | ||
2630 | cmd->rx_antenna_map = rx; | ||
2631 | cmd->tx_antenna_map = tx; | ||
2523 | 2632 | ||
2524 | /* Peer info - valid during add/update. */ | 2633 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2525 | struct peer_capability_info peer_info; | 2634 | kfree(cmd); |
2635 | |||
2636 | return rc; | ||
2637 | } | ||
2638 | |||
2639 | /* | ||
2640 | * CMD_USE_FIXED_RATE (STA version). | ||
2641 | */ | ||
2642 | struct mwl8k_cmd_use_fixed_rate_sta { | ||
2643 | struct mwl8k_cmd_pkt header; | ||
2644 | __le32 action; | ||
2645 | __le32 allow_rate_drop; | ||
2646 | __le32 num_rates; | ||
2647 | struct { | ||
2648 | __le32 is_ht_rate; | ||
2649 | __le32 enable_retry; | ||
2650 | __le32 rate; | ||
2651 | __le32 retry_count; | ||
2652 | } rate_entry[8]; | ||
2653 | __le32 rate_type; | ||
2654 | __le32 reserved1; | ||
2655 | __le32 reserved2; | ||
2526 | } __attribute__((packed)); | 2656 | } __attribute__((packed)); |
2527 | 2657 | ||
2528 | static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw, | 2658 | #define MWL8K_USE_AUTO_RATE 0x0002 |
2529 | struct ieee80211_vif *vif, __u32 action) | 2659 | #define MWL8K_UCAST_RATE 0 |
2660 | |||
2661 | static int mwl8k_cmd_use_fixed_rate_sta(struct ieee80211_hw *hw) | ||
2530 | { | 2662 | { |
2531 | struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); | 2663 | struct mwl8k_cmd_use_fixed_rate_sta *cmd; |
2532 | struct ieee80211_bss_conf *info = &mv_vif->bss_info; | ||
2533 | struct mwl8k_cmd_update_sta_db *cmd; | ||
2534 | struct peer_capability_info *peer_info; | ||
2535 | int rc; | 2664 | int rc; |
2536 | 2665 | ||
2537 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2666 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2538 | if (cmd == NULL) | 2667 | if (cmd == NULL) |
2539 | return -ENOMEM; | 2668 | return -ENOMEM; |
2540 | 2669 | ||
2541 | cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB); | 2670 | cmd->header.code = cpu_to_le16(MWL8K_CMD_USE_FIXED_RATE); |
2542 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2671 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2672 | cmd->action = cpu_to_le32(MWL8K_USE_AUTO_RATE); | ||
2673 | cmd->rate_type = cpu_to_le32(MWL8K_UCAST_RATE); | ||
2543 | 2674 | ||
2544 | cmd->action = cpu_to_le32(action); | 2675 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2545 | peer_info = &cmd->peer_info; | 2676 | kfree(cmd); |
2546 | memcpy(cmd->peer_addr, mv_vif->bssid, ETH_ALEN); | ||
2547 | 2677 | ||
2548 | switch (action) { | 2678 | return rc; |
2549 | case MWL8K_STA_DB_ADD_ENTRY: | 2679 | } |
2550 | case MWL8K_STA_DB_MODIFY_ENTRY: | ||
2551 | /* Build peer_info block */ | ||
2552 | peer_info->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT; | ||
2553 | peer_info->basic_caps = cpu_to_le16(info->assoc_capability); | ||
2554 | memcpy(peer_info->legacy_rates, mwl8k_rateids, | ||
2555 | sizeof(mwl8k_rateids)); | ||
2556 | peer_info->interop = 1; | ||
2557 | peer_info->amsdu_enabled = 0; | ||
2558 | |||
2559 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2560 | if (rc == 0) | ||
2561 | mv_vif->peer_id = peer_info->station_id; | ||
2562 | 2680 | ||
2563 | break; | 2681 | /* |
2682 | * CMD_USE_FIXED_RATE (AP version). | ||
2683 | */ | ||
2684 | struct mwl8k_cmd_use_fixed_rate_ap { | ||
2685 | struct mwl8k_cmd_pkt header; | ||
2686 | __le32 action; | ||
2687 | __le32 allow_rate_drop; | ||
2688 | __le32 num_rates; | ||
2689 | struct mwl8k_rate_entry_ap { | ||
2690 | __le32 is_ht_rate; | ||
2691 | __le32 enable_retry; | ||
2692 | __le32 rate; | ||
2693 | __le32 retry_count; | ||
2694 | } rate_entry[4]; | ||
2695 | u8 multicast_rate; | ||
2696 | u8 multicast_rate_type; | ||
2697 | u8 management_rate; | ||
2698 | } __attribute__((packed)); | ||
2564 | 2699 | ||
2565 | case MWL8K_STA_DB_DEL_ENTRY: | 2700 | static int |
2566 | case MWL8K_STA_DB_FLUSH: | 2701 | mwl8k_cmd_use_fixed_rate_ap(struct ieee80211_hw *hw, int mcast, int mgmt) |
2567 | default: | 2702 | { |
2568 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2703 | struct mwl8k_cmd_use_fixed_rate_ap *cmd; |
2569 | if (rc == 0) | 2704 | int rc; |
2570 | mv_vif->peer_id = 0; | 2705 | |
2571 | break; | 2706 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2572 | } | 2707 | if (cmd == NULL) |
2708 | return -ENOMEM; | ||
2709 | |||
2710 | cmd->header.code = cpu_to_le16(MWL8K_CMD_USE_FIXED_RATE); | ||
2711 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2712 | cmd->action = cpu_to_le32(MWL8K_USE_AUTO_RATE); | ||
2713 | cmd->multicast_rate = mcast; | ||
2714 | cmd->management_rate = mgmt; | ||
2715 | |||
2716 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2573 | kfree(cmd); | 2717 | kfree(cmd); |
2574 | 2718 | ||
2575 | return rc; | 2719 | return rc; |
2576 | } | 2720 | } |
2577 | 2721 | ||
2578 | /* | 2722 | /* |
2579 | * CMD_SET_AID. | 2723 | * CMD_ENABLE_SNIFFER. |
2580 | */ | 2724 | */ |
2581 | #define MWL8K_FRAME_PROT_DISABLED 0x00 | 2725 | struct mwl8k_cmd_enable_sniffer { |
2582 | #define MWL8K_FRAME_PROT_11G 0x07 | 2726 | struct mwl8k_cmd_pkt header; |
2583 | #define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02 | 2727 | __le32 action; |
2584 | #define MWL8K_FRAME_PROT_11N_HT_ALL 0x06 | ||
2585 | |||
2586 | struct mwl8k_cmd_update_set_aid { | ||
2587 | struct mwl8k_cmd_pkt header; | ||
2588 | __le16 aid; | ||
2589 | |||
2590 | /* AP's MAC address (BSSID) */ | ||
2591 | __u8 bssid[ETH_ALEN]; | ||
2592 | __le16 protection_mode; | ||
2593 | __u8 supp_rates[14]; | ||
2594 | } __attribute__((packed)); | 2728 | } __attribute__((packed)); |
2595 | 2729 | ||
2596 | static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw, | 2730 | static int mwl8k_cmd_enable_sniffer(struct ieee80211_hw *hw, bool enable) |
2597 | struct ieee80211_vif *vif) | ||
2598 | { | 2731 | { |
2599 | struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); | 2732 | struct mwl8k_cmd_enable_sniffer *cmd; |
2600 | struct ieee80211_bss_conf *info = &mv_vif->bss_info; | ||
2601 | struct mwl8k_cmd_update_set_aid *cmd; | ||
2602 | u16 prot_mode; | ||
2603 | int rc; | 2733 | int rc; |
2604 | 2734 | ||
2605 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2735 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2606 | if (cmd == NULL) | 2736 | if (cmd == NULL) |
2607 | return -ENOMEM; | 2737 | return -ENOMEM; |
2608 | 2738 | ||
2609 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_AID); | 2739 | cmd->header.code = cpu_to_le16(MWL8K_CMD_ENABLE_SNIFFER); |
2610 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2740 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2611 | cmd->aid = cpu_to_le16(info->aid); | 2741 | cmd->action = cpu_to_le32(!!enable); |
2612 | 2742 | ||
2613 | memcpy(cmd->bssid, mv_vif->bssid, ETH_ALEN); | 2743 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2744 | kfree(cmd); | ||
2614 | 2745 | ||
2615 | if (info->use_cts_prot) { | 2746 | return rc; |
2616 | prot_mode = MWL8K_FRAME_PROT_11G; | 2747 | } |
2748 | |||
2749 | /* | ||
2750 | * CMD_SET_MAC_ADDR. | ||
2751 | */ | ||
2752 | struct mwl8k_cmd_set_mac_addr { | ||
2753 | struct mwl8k_cmd_pkt header; | ||
2754 | union { | ||
2755 | struct { | ||
2756 | __le16 mac_type; | ||
2757 | __u8 mac_addr[ETH_ALEN]; | ||
2758 | } mbss; | ||
2759 | __u8 mac_addr[ETH_ALEN]; | ||
2760 | }; | ||
2761 | } __attribute__((packed)); | ||
2762 | |||
2763 | #define MWL8K_MAC_TYPE_PRIMARY_CLIENT 0 | ||
2764 | #define MWL8K_MAC_TYPE_SECONDARY_CLIENT 1 | ||
2765 | #define MWL8K_MAC_TYPE_PRIMARY_AP 2 | ||
2766 | #define MWL8K_MAC_TYPE_SECONDARY_AP 3 | ||
2767 | |||
2768 | static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw, | ||
2769 | struct ieee80211_vif *vif, u8 *mac) | ||
2770 | { | ||
2771 | struct mwl8k_priv *priv = hw->priv; | ||
2772 | struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); | ||
2773 | struct mwl8k_cmd_set_mac_addr *cmd; | ||
2774 | int mac_type; | ||
2775 | int rc; | ||
2776 | |||
2777 | mac_type = MWL8K_MAC_TYPE_PRIMARY_AP; | ||
2778 | if (vif != NULL && vif->type == NL80211_IFTYPE_STATION) { | ||
2779 | if (mwl8k_vif->macid + 1 == ffs(priv->sta_macids_supported)) | ||
2780 | mac_type = MWL8K_MAC_TYPE_PRIMARY_CLIENT; | ||
2781 | else | ||
2782 | mac_type = MWL8K_MAC_TYPE_SECONDARY_CLIENT; | ||
2783 | } else if (vif != NULL && vif->type == NL80211_IFTYPE_AP) { | ||
2784 | if (mwl8k_vif->macid + 1 == ffs(priv->ap_macids_supported)) | ||
2785 | mac_type = MWL8K_MAC_TYPE_PRIMARY_AP; | ||
2786 | else | ||
2787 | mac_type = MWL8K_MAC_TYPE_SECONDARY_AP; | ||
2788 | } | ||
2789 | |||
2790 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2791 | if (cmd == NULL) | ||
2792 | return -ENOMEM; | ||
2793 | |||
2794 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR); | ||
2795 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2796 | if (priv->ap_fw) { | ||
2797 | cmd->mbss.mac_type = cpu_to_le16(mac_type); | ||
2798 | memcpy(cmd->mbss.mac_addr, mac, ETH_ALEN); | ||
2617 | } else { | 2799 | } else { |
2618 | switch (info->ht_operation_mode & | 2800 | memcpy(cmd->mac_addr, mac, ETH_ALEN); |
2619 | IEEE80211_HT_OP_MODE_PROTECTION) { | ||
2620 | case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: | ||
2621 | prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY; | ||
2622 | break; | ||
2623 | case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED: | ||
2624 | prot_mode = MWL8K_FRAME_PROT_11N_HT_ALL; | ||
2625 | break; | ||
2626 | default: | ||
2627 | prot_mode = MWL8K_FRAME_PROT_DISABLED; | ||
2628 | break; | ||
2629 | } | ||
2630 | } | 2801 | } |
2631 | cmd->protection_mode = cpu_to_le16(prot_mode); | ||
2632 | 2802 | ||
2633 | memcpy(cmd->supp_rates, mwl8k_rateids, sizeof(mwl8k_rateids)); | 2803 | rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header); |
2804 | kfree(cmd); | ||
2805 | |||
2806 | return rc; | ||
2807 | } | ||
2808 | |||
2809 | /* | ||
2810 | * CMD_SET_RATEADAPT_MODE. | ||
2811 | */ | ||
2812 | struct mwl8k_cmd_set_rate_adapt_mode { | ||
2813 | struct mwl8k_cmd_pkt header; | ||
2814 | __le16 action; | ||
2815 | __le16 mode; | ||
2816 | } __attribute__((packed)); | ||
2817 | |||
2818 | static int mwl8k_cmd_set_rateadapt_mode(struct ieee80211_hw *hw, __u16 mode) | ||
2819 | { | ||
2820 | struct mwl8k_cmd_set_rate_adapt_mode *cmd; | ||
2821 | int rc; | ||
2822 | |||
2823 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2824 | if (cmd == NULL) | ||
2825 | return -ENOMEM; | ||
2826 | |||
2827 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATEADAPT_MODE); | ||
2828 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2829 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); | ||
2830 | cmd->mode = cpu_to_le16(mode); | ||
2634 | 2831 | ||
2635 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2832 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2636 | kfree(cmd); | 2833 | kfree(cmd); |
@@ -2639,115 +2836,255 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw, | |||
2639 | } | 2836 | } |
2640 | 2837 | ||
2641 | /* | 2838 | /* |
2642 | * CMD_SET_RATE. | 2839 | * CMD_BSS_START. |
2643 | */ | 2840 | */ |
2644 | struct mwl8k_cmd_update_rateset { | 2841 | struct mwl8k_cmd_bss_start { |
2645 | struct mwl8k_cmd_pkt header; | 2842 | struct mwl8k_cmd_pkt header; |
2646 | __u8 legacy_rates[14]; | 2843 | __le32 enable; |
2647 | |||
2648 | /* Bitmap for supported MCS codes. */ | ||
2649 | __u8 mcs_set[16]; | ||
2650 | __u8 reserved[16]; | ||
2651 | } __attribute__((packed)); | 2844 | } __attribute__((packed)); |
2652 | 2845 | ||
2653 | static int mwl8k_update_rateset(struct ieee80211_hw *hw, | 2846 | static int mwl8k_cmd_bss_start(struct ieee80211_hw *hw, |
2654 | struct ieee80211_vif *vif) | 2847 | struct ieee80211_vif *vif, int enable) |
2655 | { | 2848 | { |
2656 | struct mwl8k_cmd_update_rateset *cmd; | 2849 | struct mwl8k_cmd_bss_start *cmd; |
2657 | int rc; | 2850 | int rc; |
2658 | 2851 | ||
2659 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2852 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2660 | if (cmd == NULL) | 2853 | if (cmd == NULL) |
2661 | return -ENOMEM; | 2854 | return -ENOMEM; |
2662 | 2855 | ||
2663 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE); | 2856 | cmd->header.code = cpu_to_le16(MWL8K_CMD_BSS_START); |
2664 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2857 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2665 | memcpy(cmd->legacy_rates, mwl8k_rateids, sizeof(mwl8k_rateids)); | 2858 | cmd->enable = cpu_to_le32(enable); |
2666 | 2859 | ||
2667 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2860 | rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header); |
2668 | kfree(cmd); | 2861 | kfree(cmd); |
2669 | 2862 | ||
2670 | return rc; | 2863 | return rc; |
2671 | } | 2864 | } |
2672 | 2865 | ||
2673 | /* | 2866 | /* |
2674 | * CMD_USE_FIXED_RATE. | 2867 | * CMD_SET_NEW_STN. |
2675 | */ | 2868 | */ |
2676 | #define MWL8K_RATE_TABLE_SIZE 8 | 2869 | struct mwl8k_cmd_set_new_stn { |
2677 | #define MWL8K_UCAST_RATE 0 | 2870 | struct mwl8k_cmd_pkt header; |
2678 | #define MWL8K_USE_AUTO_RATE 0x0002 | 2871 | __le16 aid; |
2872 | __u8 mac_addr[6]; | ||
2873 | __le16 stn_id; | ||
2874 | __le16 action; | ||
2875 | __le16 rsvd; | ||
2876 | __le32 legacy_rates; | ||
2877 | __u8 ht_rates[4]; | ||
2878 | __le16 cap_info; | ||
2879 | __le16 ht_capabilities_info; | ||
2880 | __u8 mac_ht_param_info; | ||
2881 | __u8 rev; | ||
2882 | __u8 control_channel; | ||
2883 | __u8 add_channel; | ||
2884 | __le16 op_mode; | ||
2885 | __le16 stbc; | ||
2886 | __u8 add_qos_info; | ||
2887 | __u8 is_qos_sta; | ||
2888 | __le32 fw_sta_ptr; | ||
2889 | } __attribute__((packed)); | ||
2890 | |||
2891 | #define MWL8K_STA_ACTION_ADD 0 | ||
2892 | #define MWL8K_STA_ACTION_REMOVE 2 | ||
2893 | |||
2894 | static int mwl8k_cmd_set_new_stn_add(struct ieee80211_hw *hw, | ||
2895 | struct ieee80211_vif *vif, | ||
2896 | struct ieee80211_sta *sta) | ||
2897 | { | ||
2898 | struct mwl8k_cmd_set_new_stn *cmd; | ||
2899 | u32 rates; | ||
2900 | int rc; | ||
2901 | |||
2902 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2903 | if (cmd == NULL) | ||
2904 | return -ENOMEM; | ||
2905 | |||
2906 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_NEW_STN); | ||
2907 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2908 | cmd->aid = cpu_to_le16(sta->aid); | ||
2909 | memcpy(cmd->mac_addr, sta->addr, ETH_ALEN); | ||
2910 | cmd->stn_id = cpu_to_le16(sta->aid); | ||
2911 | cmd->action = cpu_to_le16(MWL8K_STA_ACTION_ADD); | ||
2912 | if (hw->conf.channel->band == IEEE80211_BAND_2GHZ) | ||
2913 | rates = sta->supp_rates[IEEE80211_BAND_2GHZ]; | ||
2914 | else | ||
2915 | rates = sta->supp_rates[IEEE80211_BAND_5GHZ] << 5; | ||
2916 | cmd->legacy_rates = cpu_to_le32(rates); | ||
2917 | if (sta->ht_cap.ht_supported) { | ||
2918 | cmd->ht_rates[0] = sta->ht_cap.mcs.rx_mask[0]; | ||
2919 | cmd->ht_rates[1] = sta->ht_cap.mcs.rx_mask[1]; | ||
2920 | cmd->ht_rates[2] = sta->ht_cap.mcs.rx_mask[2]; | ||
2921 | cmd->ht_rates[3] = sta->ht_cap.mcs.rx_mask[3]; | ||
2922 | cmd->ht_capabilities_info = cpu_to_le16(sta->ht_cap.cap); | ||
2923 | cmd->mac_ht_param_info = (sta->ht_cap.ampdu_factor & 3) | | ||
2924 | ((sta->ht_cap.ampdu_density & 7) << 2); | ||
2925 | cmd->is_qos_sta = 1; | ||
2926 | } | ||
2927 | |||
2928 | rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header); | ||
2929 | kfree(cmd); | ||
2930 | |||
2931 | return rc; | ||
2932 | } | ||
2933 | |||
2934 | static int mwl8k_cmd_set_new_stn_add_self(struct ieee80211_hw *hw, | ||
2935 | struct ieee80211_vif *vif) | ||
2936 | { | ||
2937 | struct mwl8k_cmd_set_new_stn *cmd; | ||
2938 | int rc; | ||
2679 | 2939 | ||
2680 | struct mwl8k_rate_entry { | 2940 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2681 | /* Set to 1 if HT rate, 0 if legacy. */ | 2941 | if (cmd == NULL) |
2682 | __le32 is_ht_rate; | 2942 | return -ENOMEM; |
2683 | 2943 | ||
2684 | /* Set to 1 to use retry_count field. */ | 2944 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_NEW_STN); |
2685 | __le32 enable_retry; | 2945 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2946 | memcpy(cmd->mac_addr, vif->addr, ETH_ALEN); | ||
2686 | 2947 | ||
2687 | /* Specified legacy rate or MCS. */ | 2948 | rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header); |
2688 | __le32 rate; | 2949 | kfree(cmd); |
2689 | 2950 | ||
2690 | /* Number of allowed retries. */ | 2951 | return rc; |
2691 | __le32 retry_count; | 2952 | } |
2953 | |||
2954 | static int mwl8k_cmd_set_new_stn_del(struct ieee80211_hw *hw, | ||
2955 | struct ieee80211_vif *vif, u8 *addr) | ||
2956 | { | ||
2957 | struct mwl8k_cmd_set_new_stn *cmd; | ||
2958 | int rc; | ||
2959 | |||
2960 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2961 | if (cmd == NULL) | ||
2962 | return -ENOMEM; | ||
2963 | |||
2964 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_NEW_STN); | ||
2965 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2966 | memcpy(cmd->mac_addr, addr, ETH_ALEN); | ||
2967 | cmd->action = cpu_to_le16(MWL8K_STA_ACTION_REMOVE); | ||
2968 | |||
2969 | rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header); | ||
2970 | kfree(cmd); | ||
2971 | |||
2972 | return rc; | ||
2973 | } | ||
2974 | |||
2975 | /* | ||
2976 | * CMD_UPDATE_STADB. | ||
2977 | */ | ||
2978 | struct ewc_ht_info { | ||
2979 | __le16 control1; | ||
2980 | __le16 control2; | ||
2981 | __le16 control3; | ||
2692 | } __attribute__((packed)); | 2982 | } __attribute__((packed)); |
2693 | 2983 | ||
2694 | struct mwl8k_rate_table { | 2984 | struct peer_capability_info { |
2695 | /* 1 to allow specified rate and below */ | 2985 | /* Peer type - AP vs. STA. */ |
2696 | __le32 allow_rate_drop; | 2986 | __u8 peer_type; |
2697 | __le32 num_rates; | 2987 | |
2698 | struct mwl8k_rate_entry rate_entry[MWL8K_RATE_TABLE_SIZE]; | 2988 | /* Basic 802.11 capabilities from assoc resp. */ |
2989 | __le16 basic_caps; | ||
2990 | |||
2991 | /* Set if peer supports 802.11n high throughput (HT). */ | ||
2992 | __u8 ht_support; | ||
2993 | |||
2994 | /* Valid if HT is supported. */ | ||
2995 | __le16 ht_caps; | ||
2996 | __u8 extended_ht_caps; | ||
2997 | struct ewc_ht_info ewc_info; | ||
2998 | |||
2999 | /* Legacy rate table. Intersection of our rates and peer rates. */ | ||
3000 | __u8 legacy_rates[12]; | ||
3001 | |||
3002 | /* HT rate table. Intersection of our rates and peer rates. */ | ||
3003 | __u8 ht_rates[16]; | ||
3004 | __u8 pad[16]; | ||
3005 | |||
3006 | /* If set, interoperability mode, no proprietary extensions. */ | ||
3007 | __u8 interop; | ||
3008 | __u8 pad2; | ||
3009 | __u8 station_id; | ||
3010 | __le16 amsdu_enabled; | ||
2699 | } __attribute__((packed)); | 3011 | } __attribute__((packed)); |
2700 | 3012 | ||
2701 | struct mwl8k_cmd_use_fixed_rate { | 3013 | struct mwl8k_cmd_update_stadb { |
2702 | struct mwl8k_cmd_pkt header; | 3014 | struct mwl8k_cmd_pkt header; |
3015 | |||
3016 | /* See STADB_ACTION_TYPE */ | ||
2703 | __le32 action; | 3017 | __le32 action; |
2704 | struct mwl8k_rate_table rate_table; | ||
2705 | 3018 | ||
2706 | /* Unicast, Broadcast or Multicast */ | 3019 | /* Peer MAC address */ |
2707 | __le32 rate_type; | 3020 | __u8 peer_addr[ETH_ALEN]; |
2708 | __le32 reserved1; | 3021 | |
2709 | __le32 reserved2; | 3022 | __le32 reserved; |
3023 | |||
3024 | /* Peer info - valid during add/update. */ | ||
3025 | struct peer_capability_info peer_info; | ||
2710 | } __attribute__((packed)); | 3026 | } __attribute__((packed)); |
2711 | 3027 | ||
2712 | static int mwl8k_cmd_use_fixed_rate(struct ieee80211_hw *hw, | 3028 | #define MWL8K_STA_DB_MODIFY_ENTRY 1 |
2713 | u32 action, u32 rate_type, struct mwl8k_rate_table *rate_table) | 3029 | #define MWL8K_STA_DB_DEL_ENTRY 2 |
3030 | |||
3031 | /* Peer Entry flags - used to define the type of the peer node */ | ||
3032 | #define MWL8K_PEER_TYPE_ACCESSPOINT 2 | ||
3033 | |||
3034 | static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw, | ||
3035 | struct ieee80211_vif *vif, | ||
3036 | struct ieee80211_sta *sta) | ||
2714 | { | 3037 | { |
2715 | struct mwl8k_cmd_use_fixed_rate *cmd; | 3038 | struct mwl8k_cmd_update_stadb *cmd; |
2716 | int count; | 3039 | struct peer_capability_info *p; |
3040 | u32 rates; | ||
2717 | int rc; | 3041 | int rc; |
2718 | 3042 | ||
2719 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 3043 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2720 | if (cmd == NULL) | 3044 | if (cmd == NULL) |
2721 | return -ENOMEM; | 3045 | return -ENOMEM; |
2722 | 3046 | ||
2723 | cmd->header.code = cpu_to_le16(MWL8K_CMD_USE_FIXED_RATE); | 3047 | cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB); |
2724 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 3048 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
3049 | cmd->action = cpu_to_le32(MWL8K_STA_DB_MODIFY_ENTRY); | ||
3050 | memcpy(cmd->peer_addr, sta->addr, ETH_ALEN); | ||
3051 | |||
3052 | p = &cmd->peer_info; | ||
3053 | p->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT; | ||
3054 | p->basic_caps = cpu_to_le16(vif->bss_conf.assoc_capability); | ||
3055 | p->ht_support = sta->ht_cap.ht_supported; | ||
3056 | p->ht_caps = sta->ht_cap.cap; | ||
3057 | p->extended_ht_caps = (sta->ht_cap.ampdu_factor & 3) | | ||
3058 | ((sta->ht_cap.ampdu_density & 7) << 2); | ||
3059 | if (hw->conf.channel->band == IEEE80211_BAND_2GHZ) | ||
3060 | rates = sta->supp_rates[IEEE80211_BAND_2GHZ]; | ||
3061 | else | ||
3062 | rates = sta->supp_rates[IEEE80211_BAND_5GHZ] << 5; | ||
3063 | legacy_rate_mask_to_array(p->legacy_rates, rates); | ||
3064 | memcpy(p->ht_rates, sta->ht_cap.mcs.rx_mask, 16); | ||
3065 | p->interop = 1; | ||
3066 | p->amsdu_enabled = 0; | ||
2725 | 3067 | ||
2726 | cmd->action = cpu_to_le32(action); | 3068 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2727 | cmd->rate_type = cpu_to_le32(rate_type); | 3069 | kfree(cmd); |
2728 | 3070 | ||
2729 | if (rate_table != NULL) { | 3071 | return rc ? rc : p->station_id; |
2730 | /* | 3072 | } |
2731 | * Copy over each field manually so that endian | 3073 | |
2732 | * conversion can be done. | 3074 | static int mwl8k_cmd_update_stadb_del(struct ieee80211_hw *hw, |
2733 | */ | 3075 | struct ieee80211_vif *vif, u8 *addr) |
2734 | cmd->rate_table.allow_rate_drop = | 3076 | { |
2735 | cpu_to_le32(rate_table->allow_rate_drop); | 3077 | struct mwl8k_cmd_update_stadb *cmd; |
2736 | cmd->rate_table.num_rates = | 3078 | int rc; |
2737 | cpu_to_le32(rate_table->num_rates); | 3079 | |
2738 | 3080 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | |
2739 | for (count = 0; count < rate_table->num_rates; count++) { | 3081 | if (cmd == NULL) |
2740 | struct mwl8k_rate_entry *dst = | 3082 | return -ENOMEM; |
2741 | &cmd->rate_table.rate_entry[count]; | 3083 | |
2742 | struct mwl8k_rate_entry *src = | 3084 | cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB); |
2743 | &rate_table->rate_entry[count]; | 3085 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2744 | 3086 | cmd->action = cpu_to_le32(MWL8K_STA_DB_DEL_ENTRY); | |
2745 | dst->is_ht_rate = cpu_to_le32(src->is_ht_rate); | 3087 | memcpy(cmd->peer_addr, addr, ETH_ALEN); |
2746 | dst->enable_retry = cpu_to_le32(src->enable_retry); | ||
2747 | dst->rate = cpu_to_le32(src->rate); | ||
2748 | dst->retry_count = cpu_to_le32(src->retry_count); | ||
2749 | } | ||
2750 | } | ||
2751 | 3088 | ||
2752 | rc = mwl8k_post_cmd(hw, &cmd->header); | 3089 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2753 | kfree(cmd); | 3090 | kfree(cmd); |
@@ -2766,19 +3103,22 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id) | |||
2766 | u32 status; | 3103 | u32 status; |
2767 | 3104 | ||
2768 | status = ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); | 3105 | status = ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); |
2769 | iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); | ||
2770 | |||
2771 | if (!status) | 3106 | if (!status) |
2772 | return IRQ_NONE; | 3107 | return IRQ_NONE; |
2773 | 3108 | ||
2774 | if (status & MWL8K_A2H_INT_TX_DONE) | 3109 | if (status & MWL8K_A2H_INT_TX_DONE) { |
2775 | tasklet_schedule(&priv->tx_reclaim_task); | 3110 | status &= ~MWL8K_A2H_INT_TX_DONE; |
3111 | tasklet_schedule(&priv->poll_tx_task); | ||
3112 | } | ||
2776 | 3113 | ||
2777 | if (status & MWL8K_A2H_INT_RX_READY) { | 3114 | if (status & MWL8K_A2H_INT_RX_READY) { |
2778 | while (rxq_process(hw, 0, 1)) | 3115 | status &= ~MWL8K_A2H_INT_RX_READY; |
2779 | rxq_refill(hw, 0, 1); | 3116 | tasklet_schedule(&priv->poll_rx_task); |
2780 | } | 3117 | } |
2781 | 3118 | ||
3119 | if (status) | ||
3120 | iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); | ||
3121 | |||
2782 | if (status & MWL8K_A2H_INT_OPC_DONE) { | 3122 | if (status & MWL8K_A2H_INT_OPC_DONE) { |
2783 | if (priv->hostcmd_wait != NULL) | 3123 | if (priv->hostcmd_wait != NULL) |
2784 | complete(priv->hostcmd_wait); | 3124 | complete(priv->hostcmd_wait); |
@@ -2793,6 +3133,53 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id) | |||
2793 | return IRQ_HANDLED; | 3133 | return IRQ_HANDLED; |
2794 | } | 3134 | } |
2795 | 3135 | ||
3136 | static void mwl8k_tx_poll(unsigned long data) | ||
3137 | { | ||
3138 | struct ieee80211_hw *hw = (struct ieee80211_hw *)data; | ||
3139 | struct mwl8k_priv *priv = hw->priv; | ||
3140 | int limit; | ||
3141 | int i; | ||
3142 | |||
3143 | limit = 32; | ||
3144 | |||
3145 | spin_lock_bh(&priv->tx_lock); | ||
3146 | |||
3147 | for (i = 0; i < MWL8K_TX_QUEUES; i++) | ||
3148 | limit -= mwl8k_txq_reclaim(hw, i, limit, 0); | ||
3149 | |||
3150 | if (!priv->pending_tx_pkts && priv->tx_wait != NULL) { | ||
3151 | complete(priv->tx_wait); | ||
3152 | priv->tx_wait = NULL; | ||
3153 | } | ||
3154 | |||
3155 | spin_unlock_bh(&priv->tx_lock); | ||
3156 | |||
3157 | if (limit) { | ||
3158 | writel(~MWL8K_A2H_INT_TX_DONE, | ||
3159 | priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); | ||
3160 | } else { | ||
3161 | tasklet_schedule(&priv->poll_tx_task); | ||
3162 | } | ||
3163 | } | ||
3164 | |||
3165 | static void mwl8k_rx_poll(unsigned long data) | ||
3166 | { | ||
3167 | struct ieee80211_hw *hw = (struct ieee80211_hw *)data; | ||
3168 | struct mwl8k_priv *priv = hw->priv; | ||
3169 | int limit; | ||
3170 | |||
3171 | limit = 32; | ||
3172 | limit -= rxq_process(hw, 0, limit); | ||
3173 | limit -= rxq_refill(hw, 0, limit); | ||
3174 | |||
3175 | if (limit) { | ||
3176 | writel(~MWL8K_A2H_INT_RX_READY, | ||
3177 | priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); | ||
3178 | } else { | ||
3179 | tasklet_schedule(&priv->poll_rx_task); | ||
3180 | } | ||
3181 | } | ||
3182 | |||
2796 | 3183 | ||
2797 | /* | 3184 | /* |
2798 | * Core driver operations. | 3185 | * Core driver operations. |
@@ -2803,7 +3190,7 @@ static int mwl8k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2803 | int index = skb_get_queue_mapping(skb); | 3190 | int index = skb_get_queue_mapping(skb); |
2804 | int rc; | 3191 | int rc; |
2805 | 3192 | ||
2806 | if (priv->current_channel == NULL) { | 3193 | if (!priv->radio_on) { |
2807 | printk(KERN_DEBUG "%s: dropped TX frame since radio " | 3194 | printk(KERN_DEBUG "%s: dropped TX frame since radio " |
2808 | "disabled\n", wiphy_name(hw->wiphy)); | 3195 | "disabled\n", wiphy_name(hw->wiphy)); |
2809 | dev_kfree_skb(skb); | 3196 | dev_kfree_skb(skb); |
@@ -2828,19 +3215,20 @@ static int mwl8k_start(struct ieee80211_hw *hw) | |||
2828 | return -EIO; | 3215 | return -EIO; |
2829 | } | 3216 | } |
2830 | 3217 | ||
2831 | /* Enable tx reclaim tasklet */ | 3218 | /* Enable TX reclaim and RX tasklets. */ |
2832 | tasklet_enable(&priv->tx_reclaim_task); | 3219 | tasklet_enable(&priv->poll_tx_task); |
3220 | tasklet_enable(&priv->poll_rx_task); | ||
2833 | 3221 | ||
2834 | /* Enable interrupts */ | 3222 | /* Enable interrupts */ |
2835 | iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | 3223 | iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); |
2836 | 3224 | ||
2837 | rc = mwl8k_fw_lock(hw); | 3225 | rc = mwl8k_fw_lock(hw); |
2838 | if (!rc) { | 3226 | if (!rc) { |
2839 | rc = mwl8k_cmd_802_11_radio_enable(hw); | 3227 | rc = mwl8k_cmd_radio_enable(hw); |
2840 | 3228 | ||
2841 | if (!priv->ap_fw) { | 3229 | if (!priv->ap_fw) { |
2842 | if (!rc) | 3230 | if (!rc) |
2843 | rc = mwl8k_enable_sniffer(hw, 0); | 3231 | rc = mwl8k_cmd_enable_sniffer(hw, 0); |
2844 | 3232 | ||
2845 | if (!rc) | 3233 | if (!rc) |
2846 | rc = mwl8k_cmd_set_pre_scan(hw); | 3234 | rc = mwl8k_cmd_set_pre_scan(hw); |
@@ -2851,10 +3239,10 @@ static int mwl8k_start(struct ieee80211_hw *hw) | |||
2851 | } | 3239 | } |
2852 | 3240 | ||
2853 | if (!rc) | 3241 | if (!rc) |
2854 | rc = mwl8k_cmd_setrateadaptmode(hw, 0); | 3242 | rc = mwl8k_cmd_set_rateadapt_mode(hw, 0); |
2855 | 3243 | ||
2856 | if (!rc) | 3244 | if (!rc) |
2857 | rc = mwl8k_set_wmm(hw, 0); | 3245 | rc = mwl8k_cmd_set_wmm_mode(hw, 0); |
2858 | 3246 | ||
2859 | mwl8k_fw_unlock(hw); | 3247 | mwl8k_fw_unlock(hw); |
2860 | } | 3248 | } |
@@ -2862,7 +3250,8 @@ static int mwl8k_start(struct ieee80211_hw *hw) | |||
2862 | if (rc) { | 3250 | if (rc) { |
2863 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | 3251 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); |
2864 | free_irq(priv->pdev->irq, hw); | 3252 | free_irq(priv->pdev->irq, hw); |
2865 | tasklet_disable(&priv->tx_reclaim_task); | 3253 | tasklet_disable(&priv->poll_tx_task); |
3254 | tasklet_disable(&priv->poll_rx_task); | ||
2866 | } | 3255 | } |
2867 | 3256 | ||
2868 | return rc; | 3257 | return rc; |
@@ -2873,7 +3262,7 @@ static void mwl8k_stop(struct ieee80211_hw *hw) | |||
2873 | struct mwl8k_priv *priv = hw->priv; | 3262 | struct mwl8k_priv *priv = hw->priv; |
2874 | int i; | 3263 | int i; |
2875 | 3264 | ||
2876 | mwl8k_cmd_802_11_radio_disable(hw); | 3265 | mwl8k_cmd_radio_disable(hw); |
2877 | 3266 | ||
2878 | ieee80211_stop_queues(hw); | 3267 | ieee80211_stop_queues(hw); |
2879 | 3268 | ||
@@ -2886,36 +3275,27 @@ static void mwl8k_stop(struct ieee80211_hw *hw) | |||
2886 | if (priv->beacon_skb != NULL) | 3275 | if (priv->beacon_skb != NULL) |
2887 | dev_kfree_skb(priv->beacon_skb); | 3276 | dev_kfree_skb(priv->beacon_skb); |
2888 | 3277 | ||
2889 | /* Stop tx reclaim tasklet */ | 3278 | /* Stop TX reclaim and RX tasklets. */ |
2890 | tasklet_disable(&priv->tx_reclaim_task); | 3279 | tasklet_disable(&priv->poll_tx_task); |
3280 | tasklet_disable(&priv->poll_rx_task); | ||
2891 | 3281 | ||
2892 | /* Return all skbs to mac80211 */ | 3282 | /* Return all skbs to mac80211 */ |
2893 | for (i = 0; i < MWL8K_TX_QUEUES; i++) | 3283 | for (i = 0; i < MWL8K_TX_QUEUES; i++) |
2894 | mwl8k_txq_reclaim(hw, i, 1); | 3284 | mwl8k_txq_reclaim(hw, i, INT_MAX, 1); |
2895 | } | 3285 | } |
2896 | 3286 | ||
2897 | static int mwl8k_add_interface(struct ieee80211_hw *hw, | 3287 | static int mwl8k_add_interface(struct ieee80211_hw *hw, |
2898 | struct ieee80211_if_init_conf *conf) | 3288 | struct ieee80211_vif *vif) |
2899 | { | 3289 | { |
2900 | struct mwl8k_priv *priv = hw->priv; | 3290 | struct mwl8k_priv *priv = hw->priv; |
2901 | struct mwl8k_vif *mwl8k_vif; | 3291 | struct mwl8k_vif *mwl8k_vif; |
2902 | 3292 | u32 macids_supported; | |
2903 | /* | 3293 | int macid; |
2904 | * We only support one active interface at a time. | ||
2905 | */ | ||
2906 | if (priv->vif != NULL) | ||
2907 | return -EBUSY; | ||
2908 | |||
2909 | /* | ||
2910 | * We only support managed interfaces for now. | ||
2911 | */ | ||
2912 | if (conf->type != NL80211_IFTYPE_STATION) | ||
2913 | return -EINVAL; | ||
2914 | 3294 | ||
2915 | /* | 3295 | /* |
2916 | * Reject interface creation if sniffer mode is active, as | 3296 | * Reject interface creation if sniffer mode is active, as |
2917 | * STA operation is mutually exclusive with hardware sniffer | 3297 | * STA operation is mutually exclusive with hardware sniffer |
2918 | * mode. | 3298 | * mode. (Sniffer mode is only used on STA firmware.) |
2919 | */ | 3299 | */ |
2920 | if (priv->sniffer_enabled) { | 3300 | if (priv->sniffer_enabled) { |
2921 | printk(KERN_INFO "%s: unable to create STA " | 3301 | printk(KERN_INFO "%s: unable to create STA " |
@@ -2924,37 +3304,54 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, | |||
2924 | return -EINVAL; | 3304 | return -EINVAL; |
2925 | } | 3305 | } |
2926 | 3306 | ||
2927 | /* Clean out driver private area */ | ||
2928 | mwl8k_vif = MWL8K_VIF(conf->vif); | ||
2929 | memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); | ||
2930 | 3307 | ||
2931 | /* Set and save the mac address */ | 3308 | switch (vif->type) { |
2932 | mwl8k_set_mac_addr(hw, conf->mac_addr); | 3309 | case NL80211_IFTYPE_AP: |
2933 | memcpy(mwl8k_vif->mac_addr, conf->mac_addr, ETH_ALEN); | 3310 | macids_supported = priv->ap_macids_supported; |
3311 | break; | ||
3312 | case NL80211_IFTYPE_STATION: | ||
3313 | macids_supported = priv->sta_macids_supported; | ||
3314 | break; | ||
3315 | default: | ||
3316 | return -EINVAL; | ||
3317 | } | ||
2934 | 3318 | ||
2935 | /* Back pointer to parent config block */ | 3319 | macid = ffs(macids_supported & ~priv->macids_used); |
2936 | mwl8k_vif->priv = priv; | 3320 | if (!macid--) |
3321 | return -EBUSY; | ||
2937 | 3322 | ||
2938 | /* Set Initial sequence number to zero */ | 3323 | /* Setup driver private area. */ |
3324 | mwl8k_vif = MWL8K_VIF(vif); | ||
3325 | memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); | ||
3326 | mwl8k_vif->vif = vif; | ||
3327 | mwl8k_vif->macid = macid; | ||
2939 | mwl8k_vif->seqno = 0; | 3328 | mwl8k_vif->seqno = 0; |
2940 | 3329 | ||
2941 | priv->vif = conf->vif; | 3330 | /* Set the mac address. */ |
2942 | priv->current_channel = NULL; | 3331 | mwl8k_cmd_set_mac_addr(hw, vif, vif->addr); |
3332 | |||
3333 | if (priv->ap_fw) | ||
3334 | mwl8k_cmd_set_new_stn_add_self(hw, vif); | ||
3335 | |||
3336 | priv->macids_used |= 1 << mwl8k_vif->macid; | ||
3337 | list_add_tail(&mwl8k_vif->list, &priv->vif_list); | ||
2943 | 3338 | ||
2944 | return 0; | 3339 | return 0; |
2945 | } | 3340 | } |
2946 | 3341 | ||
2947 | static void mwl8k_remove_interface(struct ieee80211_hw *hw, | 3342 | static void mwl8k_remove_interface(struct ieee80211_hw *hw, |
2948 | struct ieee80211_if_init_conf *conf) | 3343 | struct ieee80211_vif *vif) |
2949 | { | 3344 | { |
2950 | struct mwl8k_priv *priv = hw->priv; | 3345 | struct mwl8k_priv *priv = hw->priv; |
3346 | struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); | ||
2951 | 3347 | ||
2952 | if (priv->vif == NULL) | 3348 | if (priv->ap_fw) |
2953 | return; | 3349 | mwl8k_cmd_set_new_stn_del(hw, vif, vif->addr); |
2954 | 3350 | ||
2955 | mwl8k_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00"); | 3351 | mwl8k_cmd_set_mac_addr(hw, vif, "\x00\x00\x00\x00\x00\x00"); |
2956 | 3352 | ||
2957 | priv->vif = NULL; | 3353 | priv->macids_used &= ~(1 << mwl8k_vif->macid); |
3354 | list_del(&mwl8k_vif->list); | ||
2958 | } | 3355 | } |
2959 | 3356 | ||
2960 | static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) | 3357 | static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) |
@@ -2964,8 +3361,7 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) | |||
2964 | int rc; | 3361 | int rc; |
2965 | 3362 | ||
2966 | if (conf->flags & IEEE80211_CONF_IDLE) { | 3363 | if (conf->flags & IEEE80211_CONF_IDLE) { |
2967 | mwl8k_cmd_802_11_radio_disable(hw); | 3364 | mwl8k_cmd_radio_disable(hw); |
2968 | priv->current_channel = NULL; | ||
2969 | return 0; | 3365 | return 0; |
2970 | } | 3366 | } |
2971 | 3367 | ||
@@ -2973,19 +3369,17 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) | |||
2973 | if (rc) | 3369 | if (rc) |
2974 | return rc; | 3370 | return rc; |
2975 | 3371 | ||
2976 | rc = mwl8k_cmd_802_11_radio_enable(hw); | 3372 | rc = mwl8k_cmd_radio_enable(hw); |
2977 | if (rc) | 3373 | if (rc) |
2978 | goto out; | 3374 | goto out; |
2979 | 3375 | ||
2980 | rc = mwl8k_cmd_set_rf_channel(hw, conf->channel); | 3376 | rc = mwl8k_cmd_set_rf_channel(hw, conf); |
2981 | if (rc) | 3377 | if (rc) |
2982 | goto out; | 3378 | goto out; |
2983 | 3379 | ||
2984 | priv->current_channel = conf->channel; | ||
2985 | |||
2986 | if (conf->power_level > 18) | 3380 | if (conf->power_level > 18) |
2987 | conf->power_level = 18; | 3381 | conf->power_level = 18; |
2988 | rc = mwl8k_cmd_802_11_rf_tx_power(hw, conf->power_level); | 3382 | rc = mwl8k_cmd_rf_tx_power(hw, conf->power_level); |
2989 | if (rc) | 3383 | if (rc) |
2990 | goto out; | 3384 | goto out; |
2991 | 3385 | ||
@@ -3003,79 +3397,160 @@ out: | |||
3003 | return rc; | 3397 | return rc; |
3004 | } | 3398 | } |
3005 | 3399 | ||
3006 | static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, | 3400 | static void |
3007 | struct ieee80211_vif *vif, | 3401 | mwl8k_bss_info_changed_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
3008 | struct ieee80211_bss_conf *info, | 3402 | struct ieee80211_bss_conf *info, u32 changed) |
3009 | u32 changed) | ||
3010 | { | 3403 | { |
3011 | struct mwl8k_priv *priv = hw->priv; | 3404 | struct mwl8k_priv *priv = hw->priv; |
3012 | struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); | 3405 | u32 ap_legacy_rates; |
3406 | u8 ap_mcs_rates[16]; | ||
3013 | int rc; | 3407 | int rc; |
3014 | 3408 | ||
3015 | if ((changed & BSS_CHANGED_ASSOC) == 0) | 3409 | if (mwl8k_fw_lock(hw)) |
3016 | return; | 3410 | return; |
3017 | 3411 | ||
3018 | priv->capture_beacon = false; | 3412 | /* |
3019 | 3413 | * No need to capture a beacon if we're no longer associated. | |
3020 | rc = mwl8k_fw_lock(hw); | 3414 | */ |
3021 | if (rc) | 3415 | if ((changed & BSS_CHANGED_ASSOC) && !vif->bss_conf.assoc) |
3022 | return; | 3416 | priv->capture_beacon = false; |
3023 | 3417 | ||
3024 | if (info->assoc) { | 3418 | /* |
3025 | memcpy(&mwl8k_vif->bss_info, info, | 3419 | * Get the AP's legacy and MCS rates. |
3026 | sizeof(struct ieee80211_bss_conf)); | 3420 | */ |
3421 | if (vif->bss_conf.assoc) { | ||
3422 | struct ieee80211_sta *ap; | ||
3027 | 3423 | ||
3028 | memcpy(mwl8k_vif->bssid, info->bssid, ETH_ALEN); | 3424 | rcu_read_lock(); |
3029 | 3425 | ||
3030 | /* Install rates */ | 3426 | ap = ieee80211_find_sta(vif, vif->bss_conf.bssid); |
3031 | rc = mwl8k_update_rateset(hw, vif); | 3427 | if (ap == NULL) { |
3032 | if (rc) | 3428 | rcu_read_unlock(); |
3033 | goto out; | 3429 | goto out; |
3430 | } | ||
3431 | |||
3432 | if (hw->conf.channel->band == IEEE80211_BAND_2GHZ) { | ||
3433 | ap_legacy_rates = ap->supp_rates[IEEE80211_BAND_2GHZ]; | ||
3434 | } else { | ||
3435 | ap_legacy_rates = | ||
3436 | ap->supp_rates[IEEE80211_BAND_5GHZ] << 5; | ||
3437 | } | ||
3438 | memcpy(ap_mcs_rates, ap->ht_cap.mcs.rx_mask, 16); | ||
3034 | 3439 | ||
3035 | /* Turn on rate adaptation */ | 3440 | rcu_read_unlock(); |
3036 | rc = mwl8k_cmd_use_fixed_rate(hw, MWL8K_USE_AUTO_RATE, | 3441 | } |
3037 | MWL8K_UCAST_RATE, NULL); | 3442 | |
3443 | if ((changed & BSS_CHANGED_ASSOC) && vif->bss_conf.assoc) { | ||
3444 | rc = mwl8k_cmd_set_rate(hw, vif, ap_legacy_rates, ap_mcs_rates); | ||
3038 | if (rc) | 3445 | if (rc) |
3039 | goto out; | 3446 | goto out; |
3040 | 3447 | ||
3041 | /* Set radio preamble */ | 3448 | rc = mwl8k_cmd_use_fixed_rate_sta(hw); |
3042 | rc = mwl8k_set_radio_preamble(hw, info->use_short_preamble); | ||
3043 | if (rc) | 3449 | if (rc) |
3044 | goto out; | 3450 | goto out; |
3451 | } | ||
3045 | 3452 | ||
3046 | /* Set slot time */ | 3453 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
3047 | rc = mwl8k_cmd_set_slot(hw, info->use_short_slot); | 3454 | rc = mwl8k_set_radio_preamble(hw, |
3455 | vif->bss_conf.use_short_preamble); | ||
3048 | if (rc) | 3456 | if (rc) |
3049 | goto out; | 3457 | goto out; |
3458 | } | ||
3050 | 3459 | ||
3051 | /* Update peer rate info */ | 3460 | if (changed & BSS_CHANGED_ERP_SLOT) { |
3052 | rc = mwl8k_cmd_update_sta_db(hw, vif, | 3461 | rc = mwl8k_cmd_set_slot(hw, vif->bss_conf.use_short_slot); |
3053 | MWL8K_STA_DB_MODIFY_ENTRY); | ||
3054 | if (rc) | 3462 | if (rc) |
3055 | goto out; | 3463 | goto out; |
3464 | } | ||
3056 | 3465 | ||
3057 | /* Set AID */ | 3466 | if (vif->bss_conf.assoc && |
3058 | rc = mwl8k_cmd_set_aid(hw, vif); | 3467 | (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_ERP_CTS_PROT | |
3468 | BSS_CHANGED_HT))) { | ||
3469 | rc = mwl8k_cmd_set_aid(hw, vif, ap_legacy_rates); | ||
3059 | if (rc) | 3470 | if (rc) |
3060 | goto out; | 3471 | goto out; |
3472 | } | ||
3061 | 3473 | ||
3474 | if (vif->bss_conf.assoc && | ||
3475 | (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BEACON_INT))) { | ||
3062 | /* | 3476 | /* |
3063 | * Finalize the join. Tell rx handler to process | 3477 | * Finalize the join. Tell rx handler to process |
3064 | * next beacon from our BSSID. | 3478 | * next beacon from our BSSID. |
3065 | */ | 3479 | */ |
3066 | memcpy(priv->capture_bssid, mwl8k_vif->bssid, ETH_ALEN); | 3480 | memcpy(priv->capture_bssid, vif->bss_conf.bssid, ETH_ALEN); |
3067 | priv->capture_beacon = true; | 3481 | priv->capture_beacon = true; |
3068 | } else { | ||
3069 | rc = mwl8k_cmd_update_sta_db(hw, vif, MWL8K_STA_DB_DEL_ENTRY); | ||
3070 | memset(&mwl8k_vif->bss_info, 0, | ||
3071 | sizeof(struct ieee80211_bss_conf)); | ||
3072 | memset(mwl8k_vif->bssid, 0, ETH_ALEN); | ||
3073 | } | 3482 | } |
3074 | 3483 | ||
3075 | out: | 3484 | out: |
3076 | mwl8k_fw_unlock(hw); | 3485 | mwl8k_fw_unlock(hw); |
3077 | } | 3486 | } |
3078 | 3487 | ||
3488 | static void | ||
3489 | mwl8k_bss_info_changed_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
3490 | struct ieee80211_bss_conf *info, u32 changed) | ||
3491 | { | ||
3492 | int rc; | ||
3493 | |||
3494 | if (mwl8k_fw_lock(hw)) | ||
3495 | return; | ||
3496 | |||
3497 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | ||
3498 | rc = mwl8k_set_radio_preamble(hw, | ||
3499 | vif->bss_conf.use_short_preamble); | ||
3500 | if (rc) | ||
3501 | goto out; | ||
3502 | } | ||
3503 | |||
3504 | if (changed & BSS_CHANGED_BASIC_RATES) { | ||
3505 | int idx; | ||
3506 | int rate; | ||
3507 | |||
3508 | /* | ||
3509 | * Use lowest supported basic rate for multicasts | ||
3510 | * and management frames (such as probe responses -- | ||
3511 | * beacons will always go out at 1 Mb/s). | ||
3512 | */ | ||
3513 | idx = ffs(vif->bss_conf.basic_rates); | ||
3514 | if (idx) | ||
3515 | idx--; | ||
3516 | |||
3517 | if (hw->conf.channel->band == IEEE80211_BAND_2GHZ) | ||
3518 | rate = mwl8k_rates_24[idx].hw_value; | ||
3519 | else | ||
3520 | rate = mwl8k_rates_50[idx].hw_value; | ||
3521 | |||
3522 | mwl8k_cmd_use_fixed_rate_ap(hw, rate, rate); | ||
3523 | } | ||
3524 | |||
3525 | if (changed & (BSS_CHANGED_BEACON_INT | BSS_CHANGED_BEACON)) { | ||
3526 | struct sk_buff *skb; | ||
3527 | |||
3528 | skb = ieee80211_beacon_get(hw, vif); | ||
3529 | if (skb != NULL) { | ||
3530 | mwl8k_cmd_set_beacon(hw, vif, skb->data, skb->len); | ||
3531 | kfree_skb(skb); | ||
3532 | } | ||
3533 | } | ||
3534 | |||
3535 | if (changed & BSS_CHANGED_BEACON_ENABLED) | ||
3536 | mwl8k_cmd_bss_start(hw, vif, info->enable_beacon); | ||
3537 | |||
3538 | out: | ||
3539 | mwl8k_fw_unlock(hw); | ||
3540 | } | ||
3541 | |||
3542 | static void | ||
3543 | mwl8k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
3544 | struct ieee80211_bss_conf *info, u32 changed) | ||
3545 | { | ||
3546 | struct mwl8k_priv *priv = hw->priv; | ||
3547 | |||
3548 | if (!priv->ap_fw) | ||
3549 | mwl8k_bss_info_changed_sta(hw, vif, info, changed); | ||
3550 | else | ||
3551 | mwl8k_bss_info_changed_ap(hw, vif, info, changed); | ||
3552 | } | ||
3553 | |||
3079 | static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw, | 3554 | static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw, |
3080 | int mc_count, struct dev_addr_list *mclist) | 3555 | int mc_count, struct dev_addr_list *mclist) |
3081 | { | 3556 | { |
@@ -3105,7 +3580,7 @@ mwl8k_configure_filter_sniffer(struct ieee80211_hw *hw, | |||
3105 | * operation, so refuse to enable sniffer mode if a STA | 3580 | * operation, so refuse to enable sniffer mode if a STA |
3106 | * interface is active. | 3581 | * interface is active. |
3107 | */ | 3582 | */ |
3108 | if (priv->vif != NULL) { | 3583 | if (!list_empty(&priv->vif_list)) { |
3109 | if (net_ratelimit()) | 3584 | if (net_ratelimit()) |
3110 | printk(KERN_INFO "%s: not enabling sniffer " | 3585 | printk(KERN_INFO "%s: not enabling sniffer " |
3111 | "mode because STA interface is active\n", | 3586 | "mode because STA interface is active\n", |
@@ -3114,7 +3589,7 @@ mwl8k_configure_filter_sniffer(struct ieee80211_hw *hw, | |||
3114 | } | 3589 | } |
3115 | 3590 | ||
3116 | if (!priv->sniffer_enabled) { | 3591 | if (!priv->sniffer_enabled) { |
3117 | if (mwl8k_enable_sniffer(hw, 1)) | 3592 | if (mwl8k_cmd_enable_sniffer(hw, 1)) |
3118 | return 0; | 3593 | return 0; |
3119 | priv->sniffer_enabled = true; | 3594 | priv->sniffer_enabled = true; |
3120 | } | 3595 | } |
@@ -3126,6 +3601,14 @@ mwl8k_configure_filter_sniffer(struct ieee80211_hw *hw, | |||
3126 | return 1; | 3601 | return 1; |
3127 | } | 3602 | } |
3128 | 3603 | ||
3604 | static struct mwl8k_vif *mwl8k_first_vif(struct mwl8k_priv *priv) | ||
3605 | { | ||
3606 | if (!list_empty(&priv->vif_list)) | ||
3607 | return list_entry(priv->vif_list.next, struct mwl8k_vif, list); | ||
3608 | |||
3609 | return NULL; | ||
3610 | } | ||
3611 | |||
3129 | static void mwl8k_configure_filter(struct ieee80211_hw *hw, | 3612 | static void mwl8k_configure_filter(struct ieee80211_hw *hw, |
3130 | unsigned int changed_flags, | 3613 | unsigned int changed_flags, |
3131 | unsigned int *total_flags, | 3614 | unsigned int *total_flags, |
@@ -3163,7 +3646,7 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, | |||
3163 | } | 3646 | } |
3164 | 3647 | ||
3165 | if (priv->sniffer_enabled) { | 3648 | if (priv->sniffer_enabled) { |
3166 | mwl8k_enable_sniffer(hw, 0); | 3649 | mwl8k_cmd_enable_sniffer(hw, 0); |
3167 | priv->sniffer_enabled = false; | 3650 | priv->sniffer_enabled = false; |
3168 | } | 3651 | } |
3169 | 3652 | ||
@@ -3174,7 +3657,8 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, | |||
3174 | */ | 3657 | */ |
3175 | mwl8k_cmd_set_pre_scan(hw); | 3658 | mwl8k_cmd_set_pre_scan(hw); |
3176 | } else { | 3659 | } else { |
3177 | u8 *bssid; | 3660 | struct mwl8k_vif *mwl8k_vif; |
3661 | const u8 *bssid; | ||
3178 | 3662 | ||
3179 | /* | 3663 | /* |
3180 | * Enable the BSS filter. | 3664 | * Enable the BSS filter. |
@@ -3184,9 +3668,11 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, | |||
3184 | * (where the OUI part needs to be nonzero for | 3668 | * (where the OUI part needs to be nonzero for |
3185 | * the BSSID to be accepted by POST_SCAN). | 3669 | * the BSSID to be accepted by POST_SCAN). |
3186 | */ | 3670 | */ |
3187 | bssid = "\x01\x00\x00\x00\x00\x00"; | 3671 | mwl8k_vif = mwl8k_first_vif(priv); |
3188 | if (priv->vif != NULL) | 3672 | if (mwl8k_vif != NULL) |
3189 | bssid = MWL8K_VIF(priv->vif)->bssid; | 3673 | bssid = mwl8k_vif->vif->bss_conf.bssid; |
3674 | else | ||
3675 | bssid = "\x01\x00\x00\x00\x00\x00"; | ||
3190 | 3676 | ||
3191 | mwl8k_cmd_set_post_scan(hw, bssid); | 3677 | mwl8k_cmd_set_post_scan(hw, bssid); |
3192 | } | 3678 | } |
@@ -3213,7 +3699,39 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, | |||
3213 | 3699 | ||
3214 | static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | 3700 | static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) |
3215 | { | 3701 | { |
3216 | return mwl8k_rts_threshold(hw, MWL8K_CMD_SET, value); | 3702 | return mwl8k_cmd_set_rts_threshold(hw, value); |
3703 | } | ||
3704 | |||
3705 | static int mwl8k_sta_remove(struct ieee80211_hw *hw, | ||
3706 | struct ieee80211_vif *vif, | ||
3707 | struct ieee80211_sta *sta) | ||
3708 | { | ||
3709 | struct mwl8k_priv *priv = hw->priv; | ||
3710 | |||
3711 | if (priv->ap_fw) | ||
3712 | return mwl8k_cmd_set_new_stn_del(hw, vif, sta->addr); | ||
3713 | else | ||
3714 | return mwl8k_cmd_update_stadb_del(hw, vif, sta->addr); | ||
3715 | } | ||
3716 | |||
3717 | static int mwl8k_sta_add(struct ieee80211_hw *hw, | ||
3718 | struct ieee80211_vif *vif, | ||
3719 | struct ieee80211_sta *sta) | ||
3720 | { | ||
3721 | struct mwl8k_priv *priv = hw->priv; | ||
3722 | int ret; | ||
3723 | |||
3724 | if (!priv->ap_fw) { | ||
3725 | ret = mwl8k_cmd_update_stadb_add(hw, vif, sta); | ||
3726 | if (ret >= 0) { | ||
3727 | MWL8K_STA(sta)->peer_id = ret; | ||
3728 | return 0; | ||
3729 | } | ||
3730 | |||
3731 | return ret; | ||
3732 | } | ||
3733 | |||
3734 | return mwl8k_cmd_set_new_stn_add(hw, vif, sta); | ||
3217 | } | 3735 | } |
3218 | 3736 | ||
3219 | static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, | 3737 | static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, |
@@ -3225,14 +3743,14 @@ static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
3225 | rc = mwl8k_fw_lock(hw); | 3743 | rc = mwl8k_fw_lock(hw); |
3226 | if (!rc) { | 3744 | if (!rc) { |
3227 | if (!priv->wmm_enabled) | 3745 | if (!priv->wmm_enabled) |
3228 | rc = mwl8k_set_wmm(hw, 1); | 3746 | rc = mwl8k_cmd_set_wmm_mode(hw, 1); |
3229 | 3747 | ||
3230 | if (!rc) | 3748 | if (!rc) |
3231 | rc = mwl8k_set_edca_params(hw, queue, | 3749 | rc = mwl8k_cmd_set_edca_params(hw, queue, |
3232 | params->cw_min, | 3750 | params->cw_min, |
3233 | params->cw_max, | 3751 | params->cw_max, |
3234 | params->aifs, | 3752 | params->aifs, |
3235 | params->txop); | 3753 | params->txop); |
3236 | 3754 | ||
3237 | mwl8k_fw_unlock(hw); | 3755 | mwl8k_fw_unlock(hw); |
3238 | } | 3756 | } |
@@ -3240,28 +3758,26 @@ static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
3240 | return rc; | 3758 | return rc; |
3241 | } | 3759 | } |
3242 | 3760 | ||
3243 | static int mwl8k_get_tx_stats(struct ieee80211_hw *hw, | 3761 | static int mwl8k_get_stats(struct ieee80211_hw *hw, |
3244 | struct ieee80211_tx_queue_stats *stats) | 3762 | struct ieee80211_low_level_stats *stats) |
3245 | { | 3763 | { |
3246 | struct mwl8k_priv *priv = hw->priv; | 3764 | return mwl8k_cmd_get_stat(hw, stats); |
3247 | struct mwl8k_tx_queue *txq; | ||
3248 | int index; | ||
3249 | |||
3250 | spin_lock_bh(&priv->tx_lock); | ||
3251 | for (index = 0; index < MWL8K_TX_QUEUES; index++) { | ||
3252 | txq = priv->txq + index; | ||
3253 | memcpy(&stats[index], &txq->stats, | ||
3254 | sizeof(struct ieee80211_tx_queue_stats)); | ||
3255 | } | ||
3256 | spin_unlock_bh(&priv->tx_lock); | ||
3257 | |||
3258 | return 0; | ||
3259 | } | 3765 | } |
3260 | 3766 | ||
3261 | static int mwl8k_get_stats(struct ieee80211_hw *hw, | 3767 | static int |
3262 | struct ieee80211_low_level_stats *stats) | 3768 | mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
3769 | enum ieee80211_ampdu_mlme_action action, | ||
3770 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | ||
3263 | { | 3771 | { |
3264 | return mwl8k_cmd_802_11_get_stat(hw, stats); | 3772 | switch (action) { |
3773 | case IEEE80211_AMPDU_RX_START: | ||
3774 | case IEEE80211_AMPDU_RX_STOP: | ||
3775 | if (!(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) | ||
3776 | return -ENOTSUPP; | ||
3777 | return 0; | ||
3778 | default: | ||
3779 | return -ENOTSUPP; | ||
3780 | } | ||
3265 | } | 3781 | } |
3266 | 3782 | ||
3267 | static const struct ieee80211_ops mwl8k_ops = { | 3783 | static const struct ieee80211_ops mwl8k_ops = { |
@@ -3275,67 +3791,72 @@ static const struct ieee80211_ops mwl8k_ops = { | |||
3275 | .prepare_multicast = mwl8k_prepare_multicast, | 3791 | .prepare_multicast = mwl8k_prepare_multicast, |
3276 | .configure_filter = mwl8k_configure_filter, | 3792 | .configure_filter = mwl8k_configure_filter, |
3277 | .set_rts_threshold = mwl8k_set_rts_threshold, | 3793 | .set_rts_threshold = mwl8k_set_rts_threshold, |
3794 | .sta_add = mwl8k_sta_add, | ||
3795 | .sta_remove = mwl8k_sta_remove, | ||
3278 | .conf_tx = mwl8k_conf_tx, | 3796 | .conf_tx = mwl8k_conf_tx, |
3279 | .get_tx_stats = mwl8k_get_tx_stats, | ||
3280 | .get_stats = mwl8k_get_stats, | 3797 | .get_stats = mwl8k_get_stats, |
3798 | .ampdu_action = mwl8k_ampdu_action, | ||
3281 | }; | 3799 | }; |
3282 | 3800 | ||
3283 | static void mwl8k_tx_reclaim_handler(unsigned long data) | ||
3284 | { | ||
3285 | int i; | ||
3286 | struct ieee80211_hw *hw = (struct ieee80211_hw *) data; | ||
3287 | struct mwl8k_priv *priv = hw->priv; | ||
3288 | |||
3289 | spin_lock_bh(&priv->tx_lock); | ||
3290 | for (i = 0; i < MWL8K_TX_QUEUES; i++) | ||
3291 | mwl8k_txq_reclaim(hw, i, 0); | ||
3292 | |||
3293 | if (priv->tx_wait != NULL && !priv->pending_tx_pkts) { | ||
3294 | complete(priv->tx_wait); | ||
3295 | priv->tx_wait = NULL; | ||
3296 | } | ||
3297 | spin_unlock_bh(&priv->tx_lock); | ||
3298 | } | ||
3299 | |||
3300 | static void mwl8k_finalize_join_worker(struct work_struct *work) | 3801 | static void mwl8k_finalize_join_worker(struct work_struct *work) |
3301 | { | 3802 | { |
3302 | struct mwl8k_priv *priv = | 3803 | struct mwl8k_priv *priv = |
3303 | container_of(work, struct mwl8k_priv, finalize_join_worker); | 3804 | container_of(work, struct mwl8k_priv, finalize_join_worker); |
3304 | struct sk_buff *skb = priv->beacon_skb; | 3805 | struct sk_buff *skb = priv->beacon_skb; |
3305 | u8 dtim = MWL8K_VIF(priv->vif)->bss_info.dtim_period; | 3806 | struct ieee80211_mgmt *mgmt = (void *)skb->data; |
3807 | int len = skb->len - offsetof(struct ieee80211_mgmt, u.beacon.variable); | ||
3808 | const u8 *tim = cfg80211_find_ie(WLAN_EID_TIM, | ||
3809 | mgmt->u.beacon.variable, len); | ||
3810 | int dtim_period = 1; | ||
3306 | 3811 | ||
3307 | mwl8k_finalize_join(priv->hw, skb->data, skb->len, dtim); | 3812 | if (tim && tim[1] >= 2) |
3308 | dev_kfree_skb(skb); | 3813 | dtim_period = tim[3]; |
3814 | |||
3815 | mwl8k_cmd_finalize_join(priv->hw, skb->data, skb->len, dtim_period); | ||
3309 | 3816 | ||
3817 | dev_kfree_skb(skb); | ||
3310 | priv->beacon_skb = NULL; | 3818 | priv->beacon_skb = NULL; |
3311 | } | 3819 | } |
3312 | 3820 | ||
3313 | enum { | 3821 | enum { |
3314 | MWL8687 = 0, | 3822 | MWL8363 = 0, |
3823 | MWL8687, | ||
3315 | MWL8366, | 3824 | MWL8366, |
3316 | }; | 3825 | }; |
3317 | 3826 | ||
3318 | static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = { | 3827 | static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = { |
3319 | { | 3828 | [MWL8363] = { |
3829 | .part_name = "88w8363", | ||
3830 | .helper_image = "mwl8k/helper_8363.fw", | ||
3831 | .fw_image = "mwl8k/fmimage_8363.fw", | ||
3832 | }, | ||
3833 | [MWL8687] = { | ||
3320 | .part_name = "88w8687", | 3834 | .part_name = "88w8687", |
3321 | .helper_image = "mwl8k/helper_8687.fw", | 3835 | .helper_image = "mwl8k/helper_8687.fw", |
3322 | .fw_image = "mwl8k/fmimage_8687.fw", | 3836 | .fw_image = "mwl8k/fmimage_8687.fw", |
3323 | .rxd_ops = &rxd_8687_ops, | ||
3324 | .modes = BIT(NL80211_IFTYPE_STATION), | ||
3325 | }, | 3837 | }, |
3326 | { | 3838 | [MWL8366] = { |
3327 | .part_name = "88w8366", | 3839 | .part_name = "88w8366", |
3328 | .helper_image = "mwl8k/helper_8366.fw", | 3840 | .helper_image = "mwl8k/helper_8366.fw", |
3329 | .fw_image = "mwl8k/fmimage_8366.fw", | 3841 | .fw_image = "mwl8k/fmimage_8366.fw", |
3330 | .rxd_ops = &rxd_8366_ops, | 3842 | .ap_rxd_ops = &rxd_8366_ap_ops, |
3331 | .modes = 0, | ||
3332 | }, | 3843 | }, |
3333 | }; | 3844 | }; |
3334 | 3845 | ||
3846 | MODULE_FIRMWARE("mwl8k/helper_8363.fw"); | ||
3847 | MODULE_FIRMWARE("mwl8k/fmimage_8363.fw"); | ||
3848 | MODULE_FIRMWARE("mwl8k/helper_8687.fw"); | ||
3849 | MODULE_FIRMWARE("mwl8k/fmimage_8687.fw"); | ||
3850 | MODULE_FIRMWARE("mwl8k/helper_8366.fw"); | ||
3851 | MODULE_FIRMWARE("mwl8k/fmimage_8366.fw"); | ||
3852 | |||
3335 | static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { | 3853 | static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { |
3854 | { PCI_VDEVICE(MARVELL, 0x2a0c), .driver_data = MWL8363, }, | ||
3855 | { PCI_VDEVICE(MARVELL, 0x2a24), .driver_data = MWL8363, }, | ||
3336 | { PCI_VDEVICE(MARVELL, 0x2a2b), .driver_data = MWL8687, }, | 3856 | { PCI_VDEVICE(MARVELL, 0x2a2b), .driver_data = MWL8687, }, |
3337 | { PCI_VDEVICE(MARVELL, 0x2a30), .driver_data = MWL8687, }, | 3857 | { PCI_VDEVICE(MARVELL, 0x2a30), .driver_data = MWL8687, }, |
3338 | { PCI_VDEVICE(MARVELL, 0x2a40), .driver_data = MWL8366, }, | 3858 | { PCI_VDEVICE(MARVELL, 0x2a40), .driver_data = MWL8366, }, |
3859 | { PCI_VDEVICE(MARVELL, 0x2a43), .driver_data = MWL8366, }, | ||
3339 | { }, | 3860 | { }, |
3340 | }; | 3861 | }; |
3341 | MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table); | 3862 | MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table); |
@@ -3354,6 +3875,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3354 | printed_version = 1; | 3875 | printed_version = 1; |
3355 | } | 3876 | } |
3356 | 3877 | ||
3878 | |||
3357 | rc = pci_enable_device(pdev); | 3879 | rc = pci_enable_device(pdev); |
3358 | if (rc) { | 3880 | if (rc) { |
3359 | printk(KERN_ERR "%s: Cannot enable new PCI device\n", | 3881 | printk(KERN_ERR "%s: Cannot enable new PCI device\n", |
@@ -3370,6 +3892,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3370 | 3892 | ||
3371 | pci_set_master(pdev); | 3893 | pci_set_master(pdev); |
3372 | 3894 | ||
3895 | |||
3373 | hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops); | 3896 | hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops); |
3374 | if (hw == NULL) { | 3897 | if (hw == NULL) { |
3375 | printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME); | 3898 | printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME); |
@@ -3377,17 +3900,14 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3377 | goto err_free_reg; | 3900 | goto err_free_reg; |
3378 | } | 3901 | } |
3379 | 3902 | ||
3903 | SET_IEEE80211_DEV(hw, &pdev->dev); | ||
3904 | pci_set_drvdata(pdev, hw); | ||
3905 | |||
3380 | priv = hw->priv; | 3906 | priv = hw->priv; |
3381 | priv->hw = hw; | 3907 | priv->hw = hw; |
3382 | priv->pdev = pdev; | 3908 | priv->pdev = pdev; |
3383 | priv->device_info = &mwl8k_info_tbl[id->driver_data]; | 3909 | priv->device_info = &mwl8k_info_tbl[id->driver_data]; |
3384 | priv->rxd_ops = priv->device_info->rxd_ops; | ||
3385 | priv->sniffer_enabled = false; | ||
3386 | priv->wmm_enabled = false; | ||
3387 | priv->pending_tx_pkts = 0; | ||
3388 | 3910 | ||
3389 | SET_IEEE80211_DEV(hw, &pdev->dev); | ||
3390 | pci_set_drvdata(pdev, hw); | ||
3391 | 3911 | ||
3392 | priv->sram = pci_iomap(pdev, 0, 0x10000); | 3912 | priv->sram = pci_iomap(pdev, 0, 0x10000); |
3393 | if (priv->sram == NULL) { | 3913 | if (priv->sram == NULL) { |
@@ -3410,16 +3930,46 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3410 | } | 3930 | } |
3411 | } | 3931 | } |
3412 | 3932 | ||
3413 | memcpy(priv->channels, mwl8k_channels, sizeof(mwl8k_channels)); | ||
3414 | priv->band.band = IEEE80211_BAND_2GHZ; | ||
3415 | priv->band.channels = priv->channels; | ||
3416 | priv->band.n_channels = ARRAY_SIZE(mwl8k_channels); | ||
3417 | priv->band.bitrates = priv->rates; | ||
3418 | priv->band.n_bitrates = ARRAY_SIZE(mwl8k_rates); | ||
3419 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; | ||
3420 | 3933 | ||
3421 | BUILD_BUG_ON(sizeof(priv->rates) != sizeof(mwl8k_rates)); | 3934 | /* Reset firmware and hardware */ |
3422 | memcpy(priv->rates, mwl8k_rates, sizeof(mwl8k_rates)); | 3935 | mwl8k_hw_reset(priv); |
3936 | |||
3937 | /* Ask userland hotplug daemon for the device firmware */ | ||
3938 | rc = mwl8k_request_firmware(priv); | ||
3939 | if (rc) { | ||
3940 | printk(KERN_ERR "%s: Firmware files not found\n", | ||
3941 | wiphy_name(hw->wiphy)); | ||
3942 | goto err_stop_firmware; | ||
3943 | } | ||
3944 | |||
3945 | /* Load firmware into hardware */ | ||
3946 | rc = mwl8k_load_firmware(hw); | ||
3947 | if (rc) { | ||
3948 | printk(KERN_ERR "%s: Cannot start firmware\n", | ||
3949 | wiphy_name(hw->wiphy)); | ||
3950 | goto err_stop_firmware; | ||
3951 | } | ||
3952 | |||
3953 | /* Reclaim memory once firmware is successfully loaded */ | ||
3954 | mwl8k_release_firmware(priv); | ||
3955 | |||
3956 | |||
3957 | if (priv->ap_fw) { | ||
3958 | priv->rxd_ops = priv->device_info->ap_rxd_ops; | ||
3959 | if (priv->rxd_ops == NULL) { | ||
3960 | printk(KERN_ERR "%s: Driver does not have AP " | ||
3961 | "firmware image support for this hardware\n", | ||
3962 | wiphy_name(hw->wiphy)); | ||
3963 | goto err_stop_firmware; | ||
3964 | } | ||
3965 | } else { | ||
3966 | priv->rxd_ops = &rxd_sta_ops; | ||
3967 | } | ||
3968 | |||
3969 | priv->sniffer_enabled = false; | ||
3970 | priv->wmm_enabled = false; | ||
3971 | priv->pending_tx_pkts = 0; | ||
3972 | |||
3423 | 3973 | ||
3424 | /* | 3974 | /* |
3425 | * Extra headroom is the size of the required DMA header | 3975 | * Extra headroom is the size of the required DMA header |
@@ -3432,12 +3982,13 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3432 | 3982 | ||
3433 | hw->queues = MWL8K_TX_QUEUES; | 3983 | hw->queues = MWL8K_TX_QUEUES; |
3434 | 3984 | ||
3435 | hw->wiphy->interface_modes = priv->device_info->modes; | ||
3436 | |||
3437 | /* Set rssi and noise values to dBm */ | 3985 | /* Set rssi and noise values to dBm */ |
3438 | hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; | 3986 | hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; |
3439 | hw->vif_data_size = sizeof(struct mwl8k_vif); | 3987 | hw->vif_data_size = sizeof(struct mwl8k_vif); |
3440 | priv->vif = NULL; | 3988 | hw->sta_data_size = sizeof(struct mwl8k_sta); |
3989 | |||
3990 | priv->macids_used = 0; | ||
3991 | INIT_LIST_HEAD(&priv->vif_list); | ||
3441 | 3992 | ||
3442 | /* Set default radio state and preamble */ | 3993 | /* Set default radio state and preamble */ |
3443 | priv->radio_on = 0; | 3994 | priv->radio_on = 0; |
@@ -3446,19 +3997,20 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3446 | /* Finalize join worker */ | 3997 | /* Finalize join worker */ |
3447 | INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); | 3998 | INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); |
3448 | 3999 | ||
3449 | /* TX reclaim tasklet */ | 4000 | /* TX reclaim and RX tasklets. */ |
3450 | tasklet_init(&priv->tx_reclaim_task, | 4001 | tasklet_init(&priv->poll_tx_task, mwl8k_tx_poll, (unsigned long)hw); |
3451 | mwl8k_tx_reclaim_handler, (unsigned long)hw); | 4002 | tasklet_disable(&priv->poll_tx_task); |
3452 | tasklet_disable(&priv->tx_reclaim_task); | 4003 | tasklet_init(&priv->poll_rx_task, mwl8k_rx_poll, (unsigned long)hw); |
4004 | tasklet_disable(&priv->poll_rx_task); | ||
3453 | 4005 | ||
3454 | /* Power management cookie */ | 4006 | /* Power management cookie */ |
3455 | priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma); | 4007 | priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma); |
3456 | if (priv->cookie == NULL) | 4008 | if (priv->cookie == NULL) |
3457 | goto err_iounmap; | 4009 | goto err_stop_firmware; |
3458 | 4010 | ||
3459 | rc = mwl8k_rxq_init(hw, 0); | 4011 | rc = mwl8k_rxq_init(hw, 0); |
3460 | if (rc) | 4012 | if (rc) |
3461 | goto err_iounmap; | 4013 | goto err_free_cookie; |
3462 | rxq_refill(hw, 0, INT_MAX); | 4014 | rxq_refill(hw, 0, INT_MAX); |
3463 | 4015 | ||
3464 | mutex_init(&priv->fw_mutex); | 4016 | mutex_init(&priv->fw_mutex); |
@@ -3478,7 +4030,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3478 | 4030 | ||
3479 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); | 4031 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); |
3480 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | 4032 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); |
3481 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL); | 4033 | iowrite32(MWL8K_A2H_INT_TX_DONE | MWL8K_A2H_INT_RX_READY, |
4034 | priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL); | ||
3482 | iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); | 4035 | iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); |
3483 | 4036 | ||
3484 | rc = request_irq(priv->pdev->irq, mwl8k_interrupt, | 4037 | rc = request_irq(priv->pdev->irq, mwl8k_interrupt, |
@@ -3489,31 +4042,9 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3489 | goto err_free_queues; | 4042 | goto err_free_queues; |
3490 | } | 4043 | } |
3491 | 4044 | ||
3492 | /* Reset firmware and hardware */ | ||
3493 | mwl8k_hw_reset(priv); | ||
3494 | |||
3495 | /* Ask userland hotplug daemon for the device firmware */ | ||
3496 | rc = mwl8k_request_firmware(priv); | ||
3497 | if (rc) { | ||
3498 | printk(KERN_ERR "%s: Firmware files not found\n", | ||
3499 | wiphy_name(hw->wiphy)); | ||
3500 | goto err_free_irq; | ||
3501 | } | ||
3502 | |||
3503 | /* Load firmware into hardware */ | ||
3504 | rc = mwl8k_load_firmware(hw); | ||
3505 | if (rc) { | ||
3506 | printk(KERN_ERR "%s: Cannot start firmware\n", | ||
3507 | wiphy_name(hw->wiphy)); | ||
3508 | goto err_stop_firmware; | ||
3509 | } | ||
3510 | |||
3511 | /* Reclaim memory once firmware is successfully loaded */ | ||
3512 | mwl8k_release_firmware(priv); | ||
3513 | |||
3514 | /* | 4045 | /* |
3515 | * Temporarily enable interrupts. Initial firmware host | 4046 | * Temporarily enable interrupts. Initial firmware host |
3516 | * commands use interrupts and avoids polling. Disable | 4047 | * commands use interrupts and avoid polling. Disable |
3517 | * interrupts when done. | 4048 | * interrupts when done. |
3518 | */ | 4049 | */ |
3519 | iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | 4050 | iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); |
@@ -3529,22 +4060,29 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3529 | if (rc) { | 4060 | if (rc) { |
3530 | printk(KERN_ERR "%s: Cannot initialise firmware\n", | 4061 | printk(KERN_ERR "%s: Cannot initialise firmware\n", |
3531 | wiphy_name(hw->wiphy)); | 4062 | wiphy_name(hw->wiphy)); |
3532 | goto err_stop_firmware; | 4063 | goto err_free_irq; |
3533 | } | 4064 | } |
3534 | 4065 | ||
4066 | hw->wiphy->interface_modes = 0; | ||
4067 | if (priv->ap_macids_supported) | ||
4068 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP); | ||
4069 | if (priv->sta_macids_supported) | ||
4070 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION); | ||
4071 | |||
4072 | |||
3535 | /* Turn radio off */ | 4073 | /* Turn radio off */ |
3536 | rc = mwl8k_cmd_802_11_radio_disable(hw); | 4074 | rc = mwl8k_cmd_radio_disable(hw); |
3537 | if (rc) { | 4075 | if (rc) { |
3538 | printk(KERN_ERR "%s: Cannot disable\n", wiphy_name(hw->wiphy)); | 4076 | printk(KERN_ERR "%s: Cannot disable\n", wiphy_name(hw->wiphy)); |
3539 | goto err_stop_firmware; | 4077 | goto err_free_irq; |
3540 | } | 4078 | } |
3541 | 4079 | ||
3542 | /* Clear MAC address */ | 4080 | /* Clear MAC address */ |
3543 | rc = mwl8k_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00"); | 4081 | rc = mwl8k_cmd_set_mac_addr(hw, NULL, "\x00\x00\x00\x00\x00\x00"); |
3544 | if (rc) { | 4082 | if (rc) { |
3545 | printk(KERN_ERR "%s: Cannot clear MAC address\n", | 4083 | printk(KERN_ERR "%s: Cannot clear MAC address\n", |
3546 | wiphy_name(hw->wiphy)); | 4084 | wiphy_name(hw->wiphy)); |
3547 | goto err_stop_firmware; | 4085 | goto err_free_irq; |
3548 | } | 4086 | } |
3549 | 4087 | ||
3550 | /* Disable interrupts */ | 4088 | /* Disable interrupts */ |
@@ -3555,7 +4093,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3555 | if (rc) { | 4093 | if (rc) { |
3556 | printk(KERN_ERR "%s: Cannot register device\n", | 4094 | printk(KERN_ERR "%s: Cannot register device\n", |
3557 | wiphy_name(hw->wiphy)); | 4095 | wiphy_name(hw->wiphy)); |
3558 | goto err_stop_firmware; | 4096 | goto err_free_queues; |
3559 | } | 4097 | } |
3560 | 4098 | ||
3561 | printk(KERN_INFO "%s: %s v%d, %pM, %s firmware %u.%u.%u.%u\n", | 4099 | printk(KERN_INFO "%s: %s v%d, %pM, %s firmware %u.%u.%u.%u\n", |
@@ -3567,10 +4105,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3567 | 4105 | ||
3568 | return 0; | 4106 | return 0; |
3569 | 4107 | ||
3570 | err_stop_firmware: | ||
3571 | mwl8k_hw_reset(priv); | ||
3572 | mwl8k_release_firmware(priv); | ||
3573 | |||
3574 | err_free_irq: | 4108 | err_free_irq: |
3575 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | 4109 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); |
3576 | free_irq(priv->pdev->irq, hw); | 4110 | free_irq(priv->pdev->irq, hw); |
@@ -3580,11 +4114,16 @@ err_free_queues: | |||
3580 | mwl8k_txq_deinit(hw, i); | 4114 | mwl8k_txq_deinit(hw, i); |
3581 | mwl8k_rxq_deinit(hw, 0); | 4115 | mwl8k_rxq_deinit(hw, 0); |
3582 | 4116 | ||
3583 | err_iounmap: | 4117 | err_free_cookie: |
3584 | if (priv->cookie != NULL) | 4118 | if (priv->cookie != NULL) |
3585 | pci_free_consistent(priv->pdev, 4, | 4119 | pci_free_consistent(priv->pdev, 4, |
3586 | priv->cookie, priv->cookie_dma); | 4120 | priv->cookie, priv->cookie_dma); |
3587 | 4121 | ||
4122 | err_stop_firmware: | ||
4123 | mwl8k_hw_reset(priv); | ||
4124 | mwl8k_release_firmware(priv); | ||
4125 | |||
4126 | err_iounmap: | ||
3588 | if (priv->regs != NULL) | 4127 | if (priv->regs != NULL) |
3589 | pci_iounmap(pdev, priv->regs); | 4128 | pci_iounmap(pdev, priv->regs); |
3590 | 4129 | ||
@@ -3622,15 +4161,16 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev) | |||
3622 | 4161 | ||
3623 | ieee80211_unregister_hw(hw); | 4162 | ieee80211_unregister_hw(hw); |
3624 | 4163 | ||
3625 | /* Remove tx reclaim tasklet */ | 4164 | /* Remove TX reclaim and RX tasklets. */ |
3626 | tasklet_kill(&priv->tx_reclaim_task); | 4165 | tasklet_kill(&priv->poll_tx_task); |
4166 | tasklet_kill(&priv->poll_rx_task); | ||
3627 | 4167 | ||
3628 | /* Stop hardware */ | 4168 | /* Stop hardware */ |
3629 | mwl8k_hw_reset(priv); | 4169 | mwl8k_hw_reset(priv); |
3630 | 4170 | ||
3631 | /* Return all skbs to mac80211 */ | 4171 | /* Return all skbs to mac80211 */ |
3632 | for (i = 0; i < MWL8K_TX_QUEUES; i++) | 4172 | for (i = 0; i < MWL8K_TX_QUEUES; i++) |
3633 | mwl8k_txq_reclaim(hw, i, 1); | 4173 | mwl8k_txq_reclaim(hw, i, INT_MAX, 1); |
3634 | 4174 | ||
3635 | for (i = 0; i < MWL8K_TX_QUEUES; i++) | 4175 | for (i = 0; i < MWL8K_TX_QUEUES; i++) |
3636 | mwl8k_txq_deinit(hw, i); | 4176 | mwl8k_txq_deinit(hw, i); |
diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c index f27bb8367c98..1d4ada188eda 100644 --- a/drivers/net/wireless/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/orinoco/orinoco_cs.c | |||
@@ -407,7 +407,6 @@ static struct pcmcia_device_id orinoco_cs_ids[] = { | |||
407 | PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3), | 407 | PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3), |
408 | PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5), | 408 | PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5), |
409 | PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2), | 409 | PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2), |
410 | PCMCIA_DEVICE_PROD_ID123("AIRVAST", "IEEE 802.11b Wireless PCMCIA Card", "HFA3863", 0xea569531, 0x4bcb9645, 0x355cb092), | ||
411 | PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f), | 410 | PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f), |
412 | PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842), | 411 | PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842), |
413 | PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e), | 412 | PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e), |
@@ -417,7 +416,6 @@ static struct pcmcia_device_id orinoco_cs_ids[] = { | |||
417 | PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18), | 416 | PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18), |
418 | PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90), | 417 | PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90), |
419 | PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b), | 418 | PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b), |
420 | PCMCIA_DEVICE_PROD_ID123("corega", "WL PCCL-11", "ISL37300P", 0x0a21501a, 0x59868926, 0xc9049a39), | ||
421 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584), | 419 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584), |
422 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9), | 420 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9), |
423 | PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae), | 421 | PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae), |
@@ -432,7 +430,6 @@ static struct pcmcia_device_id orinoco_cs_ids[] = { | |||
432 | PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18), | 430 | PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18), |
433 | PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77), | 431 | PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77), |
434 | PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf), | 432 | PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf), |
435 | PCMCIA_DEVICE_PROD_ID123("Intersil", "PRISM Freedom PCMCIA Adapter", "ISL37100P", 0x4b801a17, 0xf222ec2d, 0x630d52b2), | ||
436 | PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92), | 433 | PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92), |
437 | PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395), | 434 | PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395), |
438 | PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a), | 435 | PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a), |
@@ -445,7 +442,6 @@ static struct pcmcia_device_id orinoco_cs_ids[] = { | |||
445 | PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767), | 442 | PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767), |
446 | PCMCIA_DEVICE_PROD_ID12("OEM", "PRISM2 IEEE 802.11 PC-Card", 0xfea54c90, 0x48f2bdd6), | 443 | PCMCIA_DEVICE_PROD_ID12("OEM", "PRISM2 IEEE 802.11 PC-Card", 0xfea54c90, 0x48f2bdd6), |
447 | PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed), | 444 | PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed), |
448 | PCMCIA_DEVICE_PROD_ID123("PCMCIA", "11M WLAN Card v2.5", "ISL37300P", 0x281f1c5d, 0x6e440487, 0xc9049a39), | ||
449 | PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264), | 445 | PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264), |
450 | PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178), | 446 | PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178), |
451 | PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9), | 447 | PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9), |
@@ -454,8 +450,11 @@ static struct pcmcia_device_id orinoco_cs_ids[] = { | |||
454 | PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757), | 450 | PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757), |
455 | PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a), | 451 | PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a), |
456 | PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e), | 452 | PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e), |
457 | PCMCIA_DEVICE_PROD_ID123("The Linksys Group, Inc.", "Instant Wireless Network PC Card", "ISL37300P", 0xa5f472c2, 0x590eb502, 0xc9049a39), | ||
458 | PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee), | 453 | PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee), |
454 | PCMCIA_DEVICE_PROD_ID3("HFA3863", 0x355cb092), | ||
455 | PCMCIA_DEVICE_PROD_ID3("ISL37100P", 0x630d52b2), | ||
456 | PCMCIA_DEVICE_PROD_ID3("ISL37101P-10", 0xdd97a26b), | ||
457 | PCMCIA_DEVICE_PROD_ID3("ISL37300P", 0xc9049a39), | ||
459 | PCMCIA_DEVICE_NULL, | 458 | PCMCIA_DEVICE_NULL, |
460 | }; | 459 | }; |
461 | MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids); | 460 | MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids); |
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 18012dbfb45d..4f752a21495f 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c | |||
@@ -33,21 +33,29 @@ MODULE_DESCRIPTION("Softmac Prism54 common code"); | |||
33 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
34 | MODULE_ALIAS("prism54common"); | 34 | MODULE_ALIAS("prism54common"); |
35 | 35 | ||
36 | static int p54_sta_add_remove(struct ieee80211_hw *hw, | ||
37 | struct ieee80211_vif *vif, | ||
38 | struct ieee80211_sta *sta) | ||
39 | { | ||
40 | struct p54_common *priv = hw->priv; | ||
41 | |||
42 | /* | ||
43 | * Notify the firmware that we don't want or we don't | ||
44 | * need to buffer frames for this station anymore. | ||
45 | */ | ||
46 | |||
47 | p54_sta_unlock(priv, sta->addr); | ||
48 | |||
49 | return 0; | ||
50 | } | ||
51 | |||
36 | static void p54_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif, | 52 | static void p54_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif, |
37 | enum sta_notify_cmd notify_cmd, | 53 | enum sta_notify_cmd notify_cmd, |
38 | struct ieee80211_sta *sta) | 54 | struct ieee80211_sta *sta) |
39 | { | 55 | { |
40 | struct p54_common *priv = dev->priv; | 56 | struct p54_common *priv = dev->priv; |
41 | switch (notify_cmd) { | ||
42 | case STA_NOTIFY_ADD: | ||
43 | case STA_NOTIFY_REMOVE: | ||
44 | /* | ||
45 | * Notify the firmware that we don't want or we don't | ||
46 | * need to buffer frames for this station anymore. | ||
47 | */ | ||
48 | 57 | ||
49 | p54_sta_unlock(priv, sta->addr); | 58 | switch (notify_cmd) { |
50 | break; | ||
51 | case STA_NOTIFY_AWAKE: | 59 | case STA_NOTIFY_AWAKE: |
52 | /* update the firmware's filter table */ | 60 | /* update the firmware's filter table */ |
53 | p54_sta_unlock(priv, sta->addr); | 61 | p54_sta_unlock(priv, sta->addr); |
@@ -216,7 +224,7 @@ static void p54_stop(struct ieee80211_hw *dev) | |||
216 | } | 224 | } |
217 | 225 | ||
218 | static int p54_add_interface(struct ieee80211_hw *dev, | 226 | static int p54_add_interface(struct ieee80211_hw *dev, |
219 | struct ieee80211_if_init_conf *conf) | 227 | struct ieee80211_vif *vif) |
220 | { | 228 | { |
221 | struct p54_common *priv = dev->priv; | 229 | struct p54_common *priv = dev->priv; |
222 | 230 | ||
@@ -226,28 +234,28 @@ static int p54_add_interface(struct ieee80211_hw *dev, | |||
226 | return -EOPNOTSUPP; | 234 | return -EOPNOTSUPP; |
227 | } | 235 | } |
228 | 236 | ||
229 | priv->vif = conf->vif; | 237 | priv->vif = vif; |
230 | 238 | ||
231 | switch (conf->type) { | 239 | switch (vif->type) { |
232 | case NL80211_IFTYPE_STATION: | 240 | case NL80211_IFTYPE_STATION: |
233 | case NL80211_IFTYPE_ADHOC: | 241 | case NL80211_IFTYPE_ADHOC: |
234 | case NL80211_IFTYPE_AP: | 242 | case NL80211_IFTYPE_AP: |
235 | case NL80211_IFTYPE_MESH_POINT: | 243 | case NL80211_IFTYPE_MESH_POINT: |
236 | priv->mode = conf->type; | 244 | priv->mode = vif->type; |
237 | break; | 245 | break; |
238 | default: | 246 | default: |
239 | mutex_unlock(&priv->conf_mutex); | 247 | mutex_unlock(&priv->conf_mutex); |
240 | return -EOPNOTSUPP; | 248 | return -EOPNOTSUPP; |
241 | } | 249 | } |
242 | 250 | ||
243 | memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); | 251 | memcpy(priv->mac_addr, vif->addr, ETH_ALEN); |
244 | p54_setup_mac(priv); | 252 | p54_setup_mac(priv); |
245 | mutex_unlock(&priv->conf_mutex); | 253 | mutex_unlock(&priv->conf_mutex); |
246 | return 0; | 254 | return 0; |
247 | } | 255 | } |
248 | 256 | ||
249 | static void p54_remove_interface(struct ieee80211_hw *dev, | 257 | static void p54_remove_interface(struct ieee80211_hw *dev, |
250 | struct ieee80211_if_init_conf *conf) | 258 | struct ieee80211_vif *vif) |
251 | { | 259 | { |
252 | struct p54_common *priv = dev->priv; | 260 | struct p54_common *priv = dev->priv; |
253 | 261 | ||
@@ -358,16 +366,6 @@ static int p54_get_stats(struct ieee80211_hw *dev, | |||
358 | return 0; | 366 | return 0; |
359 | } | 367 | } |
360 | 368 | ||
361 | static int p54_get_tx_stats(struct ieee80211_hw *dev, | ||
362 | struct ieee80211_tx_queue_stats *stats) | ||
363 | { | ||
364 | struct p54_common *priv = dev->priv; | ||
365 | |||
366 | memcpy(stats, &priv->tx_stats[P54_QUEUE_DATA], | ||
367 | sizeof(stats[0]) * dev->queues); | ||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static void p54_bss_info_changed(struct ieee80211_hw *dev, | 369 | static void p54_bss_info_changed(struct ieee80211_hw *dev, |
372 | struct ieee80211_vif *vif, | 370 | struct ieee80211_vif *vif, |
373 | struct ieee80211_bss_conf *info, | 371 | struct ieee80211_bss_conf *info, |
@@ -516,13 +514,14 @@ static const struct ieee80211_ops p54_ops = { | |||
516 | .remove_interface = p54_remove_interface, | 514 | .remove_interface = p54_remove_interface, |
517 | .set_tim = p54_set_tim, | 515 | .set_tim = p54_set_tim, |
518 | .sta_notify = p54_sta_notify, | 516 | .sta_notify = p54_sta_notify, |
517 | .sta_add = p54_sta_add_remove, | ||
518 | .sta_remove = p54_sta_add_remove, | ||
519 | .set_key = p54_set_key, | 519 | .set_key = p54_set_key, |
520 | .config = p54_config, | 520 | .config = p54_config, |
521 | .bss_info_changed = p54_bss_info_changed, | 521 | .bss_info_changed = p54_bss_info_changed, |
522 | .configure_filter = p54_configure_filter, | 522 | .configure_filter = p54_configure_filter, |
523 | .conf_tx = p54_conf_tx, | 523 | .conf_tx = p54_conf_tx, |
524 | .get_stats = p54_get_stats, | 524 | .get_stats = p54_get_stats, |
525 | .get_tx_stats = p54_get_tx_stats | ||
526 | }; | 525 | }; |
527 | 526 | ||
528 | struct ieee80211_hw *p54_init_common(size_t priv_data_len) | 527 | struct ieee80211_hw *p54_init_common(size_t priv_data_len) |
diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 1afc39410e85..43a3b2ead81a 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h | |||
@@ -157,6 +157,12 @@ struct p54_led_dev { | |||
157 | 157 | ||
158 | #endif /* CONFIG_P54_LEDS */ | 158 | #endif /* CONFIG_P54_LEDS */ |
159 | 159 | ||
160 | struct p54_tx_queue_stats { | ||
161 | unsigned int len; | ||
162 | unsigned int limit; | ||
163 | unsigned int count; | ||
164 | }; | ||
165 | |||
160 | struct p54_common { | 166 | struct p54_common { |
161 | struct ieee80211_hw *hw; | 167 | struct ieee80211_hw *hw; |
162 | struct ieee80211_vif *vif; | 168 | struct ieee80211_vif *vif; |
@@ -183,7 +189,7 @@ struct p54_common { | |||
183 | /* (e)DCF / QOS state */ | 189 | /* (e)DCF / QOS state */ |
184 | bool use_short_slot; | 190 | bool use_short_slot; |
185 | spinlock_t tx_stats_lock; | 191 | spinlock_t tx_stats_lock; |
186 | struct ieee80211_tx_queue_stats tx_stats[8]; | 192 | struct p54_tx_queue_stats tx_stats[8]; |
187 | struct p54_edcf_queue_param qos_params[8]; | 193 | struct p54_edcf_queue_param qos_params[8]; |
188 | 194 | ||
189 | /* Radio data */ | 195 | /* Radio data */ |
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index a72f7c2577de..bda29c00f3ef 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/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 92af9b96bb7a..b3c4fbd80d8d 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c | |||
@@ -36,6 +36,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { | |||
36 | /* Version 1 devices (pci chip + net2280) */ | 36 | /* Version 1 devices (pci chip + net2280) */ |
37 | {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */ | 37 | {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */ |
38 | {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */ | 38 | {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */ |
39 | {USB_DEVICE(0x07aa, 0x001c)}, /* Corega CG-WLUSB2GT */ | ||
39 | {USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */ | 40 | {USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */ |
40 | {USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */ | 41 | {USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */ |
41 | {USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */ | 42 | {USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */ |
@@ -60,6 +61,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { | |||
60 | {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ | 61 | {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ |
61 | {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ | 62 | {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ |
62 | {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ | 63 | {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ |
64 | {USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */ | ||
63 | {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */ | 65 | {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */ |
64 | {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */ | 66 | {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */ |
65 | {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */ | 67 | {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */ |
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index b6dda2b27fb5..66057999a93c 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c | |||
@@ -183,10 +183,10 @@ static int p54_tx_qos_accounting_alloc(struct p54_common *priv, | |||
183 | struct sk_buff *skb, | 183 | struct sk_buff *skb, |
184 | const u16 p54_queue) | 184 | const u16 p54_queue) |
185 | { | 185 | { |
186 | struct ieee80211_tx_queue_stats *queue; | 186 | struct p54_tx_queue_stats *queue; |
187 | unsigned long flags; | 187 | unsigned long flags; |
188 | 188 | ||
189 | if (WARN_ON(p54_queue > P54_QUEUE_NUM)) | 189 | if (WARN_ON(p54_queue >= P54_QUEUE_NUM)) |
190 | return -EINVAL; | 190 | return -EINVAL; |
191 | 191 | ||
192 | queue = &priv->tx_stats[p54_queue]; | 192 | queue = &priv->tx_stats[p54_queue]; |
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 2ecbedb26e15..305c106fdc1c 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
@@ -2594,23 +2594,9 @@ end: | |||
2594 | /* | 2594 | /* |
2595 | * driver/device initialization | 2595 | * driver/device initialization |
2596 | */ | 2596 | */ |
2597 | static int bcm4320a_early_init(struct usbnet *usbdev) | 2597 | static void rndis_copy_module_params(struct usbnet *usbdev) |
2598 | { | ||
2599 | /* bcm4320a doesn't handle configuration parameters well. Try | ||
2600 | * set any and you get partially zeroed mac and broken device. | ||
2601 | */ | ||
2602 | |||
2603 | return 0; | ||
2604 | } | ||
2605 | |||
2606 | static int bcm4320b_early_init(struct usbnet *usbdev) | ||
2607 | { | 2598 | { |
2608 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 2599 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
2609 | char buf[8]; | ||
2610 | |||
2611 | /* Early initialization settings, setting these won't have effect | ||
2612 | * if called after generic_rndis_bind(). | ||
2613 | */ | ||
2614 | 2600 | ||
2615 | priv->param_country[0] = modparam_country[0]; | 2601 | priv->param_country[0] = modparam_country[0]; |
2616 | priv->param_country[1] = modparam_country[1]; | 2602 | priv->param_country[1] = modparam_country[1]; |
@@ -2652,6 +2638,32 @@ static int bcm4320b_early_init(struct usbnet *usbdev) | |||
2652 | priv->param_workaround_interval = 500; | 2638 | priv->param_workaround_interval = 500; |
2653 | else | 2639 | else |
2654 | priv->param_workaround_interval = modparam_workaround_interval; | 2640 | priv->param_workaround_interval = modparam_workaround_interval; |
2641 | } | ||
2642 | |||
2643 | static int bcm4320a_early_init(struct usbnet *usbdev) | ||
2644 | { | ||
2645 | /* copy module parameters for bcm4320a so that iwconfig reports txpower | ||
2646 | * and workaround parameter is copied to private structure correctly. | ||
2647 | */ | ||
2648 | rndis_copy_module_params(usbdev); | ||
2649 | |||
2650 | /* bcm4320a doesn't handle configuration parameters well. Try | ||
2651 | * set any and you get partially zeroed mac and broken device. | ||
2652 | */ | ||
2653 | |||
2654 | return 0; | ||
2655 | } | ||
2656 | |||
2657 | static int bcm4320b_early_init(struct usbnet *usbdev) | ||
2658 | { | ||
2659 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | ||
2660 | char buf[8]; | ||
2661 | |||
2662 | rndis_copy_module_params(usbdev); | ||
2663 | |||
2664 | /* Early initialization settings, setting these won't have effect | ||
2665 | * if called after generic_rndis_bind(). | ||
2666 | */ | ||
2655 | 2667 | ||
2656 | rndis_set_config_parameter_str(usbdev, "Country", priv->param_country); | 2668 | rndis_set_config_parameter_str(usbdev, "Country", priv->param_country); |
2657 | rndis_set_config_parameter_str(usbdev, "FrameBursting", | 2669 | rndis_set_config_parameter_str(usbdev, "FrameBursting", |
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index bf60689aaabb..5239e082cd0f 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig | |||
@@ -54,17 +54,17 @@ config RT61PCI | |||
54 | When compiled as a module, this driver will be called rt61pci. | 54 | When compiled as a module, this driver will be called rt61pci. |
55 | 55 | ||
56 | config RT2800PCI_PCI | 56 | config RT2800PCI_PCI |
57 | tristate | 57 | boolean |
58 | depends on PCI | 58 | depends on PCI |
59 | default y | 59 | default y |
60 | 60 | ||
61 | config RT2800PCI_SOC | 61 | config RT2800PCI_SOC |
62 | tristate | 62 | boolean |
63 | depends on RALINK_RT288X || RALINK_RT305X | 63 | depends on RALINK_RT288X || RALINK_RT305X |
64 | default y | 64 | default y |
65 | 65 | ||
66 | config RT2800PCI | 66 | config RT2800PCI |
67 | tristate "Ralink rt2800 (PCI/PCMCIA) support (VERY EXPERIMENTAL)" | 67 | tristate "Ralink rt28xx/rt30xx/rt35xx (PCI/PCIe/PCMCIA) support (EXPERIMENTAL)" |
68 | depends on (RT2800PCI_PCI || RT2800PCI_SOC) && EXPERIMENTAL | 68 | depends on (RT2800PCI_PCI || RT2800PCI_SOC) && EXPERIMENTAL |
69 | select RT2800_LIB | 69 | select RT2800_LIB |
70 | select RT2X00_LIB_PCI if RT2800PCI_PCI | 70 | select RT2X00_LIB_PCI if RT2800PCI_PCI |
@@ -75,7 +75,7 @@ config RT2800PCI | |||
75 | select CRC_CCITT | 75 | select CRC_CCITT |
76 | select EEPROM_93CX6 | 76 | select EEPROM_93CX6 |
77 | ---help--- | 77 | ---help--- |
78 | This adds support for rt2800 wireless chipset family. | 78 | This adds support for rt2800/rt3000/rt3500 wireless chipset family. |
79 | Supported chips: RT2760, RT2790, RT2860, RT2880, RT2890 & RT3052 | 79 | Supported chips: RT2760, RT2790, RT2860, RT2880, RT2890 & RT3052 |
80 | 80 | ||
81 | This driver is non-functional at the moment and is intended for | 81 | This driver is non-functional at the moment and is intended for |
@@ -83,6 +83,32 @@ config RT2800PCI | |||
83 | 83 | ||
84 | When compiled as a module, this driver will be called "rt2800pci.ko". | 84 | When compiled as a module, this driver will be called "rt2800pci.ko". |
85 | 85 | ||
86 | if RT2800PCI | ||
87 | |||
88 | config RT2800PCI_RT30XX | ||
89 | bool "rt2800pci - Include support for rt30xx (PCI/PCIe/PCMCIA) devices" | ||
90 | default n | ||
91 | ---help--- | ||
92 | This adds support for rt30xx wireless chipset family to the | ||
93 | rt2800pci driver. | ||
94 | Supported chips: RT3090, RT3091 & RT3092 | ||
95 | |||
96 | Support for these devices is non-functional at the moment and is | ||
97 | intended for testers and developers. | ||
98 | |||
99 | config RT2800PCI_RT35XX | ||
100 | bool "rt2800pci - Include support for rt35xx (PCI/PCIe/PCMCIA) devices" | ||
101 | default n | ||
102 | ---help--- | ||
103 | This adds support for rt35xx wireless chipset family to the | ||
104 | rt2800pci driver. | ||
105 | Supported chips: RT3060, RT3062, RT3562, RT3592 | ||
106 | |||
107 | Support for these devices is non-functional at the moment and is | ||
108 | intended for testers and developers. | ||
109 | |||
110 | endif | ||
111 | |||
86 | config RT2500USB | 112 | config RT2500USB |
87 | tristate "Ralink rt2500 (USB) support" | 113 | tristate "Ralink rt2500 (USB) support" |
88 | depends on USB | 114 | depends on USB |
@@ -126,6 +152,43 @@ config RT2800USB | |||
126 | 152 | ||
127 | When compiled as a module, this driver will be called "rt2800usb.ko". | 153 | When compiled as a module, this driver will be called "rt2800usb.ko". |
128 | 154 | ||
155 | if RT2800USB | ||
156 | |||
157 | config RT2800USB_RT30XX | ||
158 | bool "rt2800usb - Include support for rt30xx (USB) devices" | ||
159 | default n | ||
160 | ---help--- | ||
161 | This adds support for rt30xx wireless chipset family to the | ||
162 | rt2800usb driver. | ||
163 | Supported chips: RT3070, RT3071 & RT3072 | ||
164 | |||
165 | Support for these devices is non-functional at the moment and is | ||
166 | intended for testers and developers. | ||
167 | |||
168 | config RT2800USB_RT35XX | ||
169 | bool "rt2800usb - Include support for rt35xx (USB) devices" | ||
170 | default n | ||
171 | ---help--- | ||
172 | This adds support for rt35xx wireless chipset family to the | ||
173 | rt2800usb driver. | ||
174 | Supported chips: RT3572 | ||
175 | |||
176 | Support for these devices is non-functional at the moment and is | ||
177 | intended for testers and developers. | ||
178 | |||
179 | config RT2800USB_UNKNOWN | ||
180 | bool "rt2800usb - Include support for unknown (USB) devices" | ||
181 | default n | ||
182 | ---help--- | ||
183 | This adds support for rt2800 family devices that are known to | ||
184 | have a rt2800 family chipset, but for which the exact chipset | ||
185 | is unknown. | ||
186 | |||
187 | Support status for these devices is unknown, and enabling these | ||
188 | devices may or may not work. | ||
189 | |||
190 | endif | ||
191 | |||
129 | config RT2800_LIB | 192 | config RT2800_LIB |
130 | tristate | 193 | tristate |
131 | 194 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index e7f46405a418..676814d3a81b 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -451,7 +451,7 @@ static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev, | |||
451 | /* | 451 | /* |
452 | * RF2420 chipset don't need any additional actions. | 452 | * RF2420 chipset don't need any additional actions. |
453 | */ | 453 | */ |
454 | if (rt2x00_rf(&rt2x00dev->chip, RF2420)) | 454 | if (rt2x00_rf(rt2x00dev, RF2420)) |
455 | return; | 455 | return; |
456 | 456 | ||
457 | /* | 457 | /* |
@@ -1340,11 +1340,10 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1340 | */ | 1340 | */ |
1341 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); | 1341 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); |
1342 | rt2x00pci_register_read(rt2x00dev, CSR0, ®); | 1342 | rt2x00pci_register_read(rt2x00dev, CSR0, ®); |
1343 | rt2x00_set_chip_rf(rt2x00dev, value, reg); | 1343 | rt2x00_set_chip(rt2x00dev, RT2460, value, |
1344 | rt2x00_print_chip(rt2x00dev); | 1344 | rt2x00_get_field32(reg, CSR0_REVISION)); |
1345 | 1345 | ||
1346 | if (!rt2x00_rf(&rt2x00dev->chip, RF2420) && | 1346 | if (!rt2x00_rf(rt2x00dev, RF2420) && !rt2x00_rf(rt2x00dev, RF2421)) { |
1347 | !rt2x00_rf(&rt2x00dev->chip, RF2421)) { | ||
1348 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); | 1347 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); |
1349 | return -ENODEV; | 1348 | return -ENODEV; |
1350 | } | 1349 | } |
@@ -1562,7 +1561,6 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { | |||
1562 | .get_stats = rt2x00mac_get_stats, | 1561 | .get_stats = rt2x00mac_get_stats, |
1563 | .bss_info_changed = rt2x00mac_bss_info_changed, | 1562 | .bss_info_changed = rt2x00mac_bss_info_changed, |
1564 | .conf_tx = rt2400pci_conf_tx, | 1563 | .conf_tx = rt2400pci_conf_tx, |
1565 | .get_tx_stats = rt2x00mac_get_tx_stats, | ||
1566 | .get_tsf = rt2400pci_get_tsf, | 1564 | .get_tsf = rt2400pci_get_tsf, |
1567 | .tx_last_beacon = rt2400pci_tx_last_beacon, | 1565 | .tx_last_beacon = rt2400pci_tx_last_beacon, |
1568 | .rfkill_poll = rt2x00mac_rfkill_poll, | 1566 | .rfkill_poll = rt2x00mac_rfkill_poll, |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index 6c21ef66dfe0..606137738848 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h | |||
@@ -65,6 +65,7 @@ | |||
65 | * CSR0: ASIC revision number. | 65 | * CSR0: ASIC revision number. |
66 | */ | 66 | */ |
67 | #define CSR0 0x0000 | 67 | #define CSR0 0x0000 |
68 | #define CSR0_REVISION FIELD32(0x0000ffff) | ||
68 | 69 | ||
69 | /* | 70 | /* |
70 | * CSR1: System control register. | 71 | * CSR1: System control register. |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 408fcfc120f5..c71266142ae9 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -440,8 +440,7 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev, | |||
440 | /* | 440 | /* |
441 | * RT2525E and RT5222 need to flip TX I/Q | 441 | * RT2525E and RT5222 need to flip TX I/Q |
442 | */ | 442 | */ |
443 | if (rt2x00_rf(&rt2x00dev->chip, RF2525E) || | 443 | if (rt2x00_rf(rt2x00dev, RF2525E) || rt2x00_rf(rt2x00dev, RF5222)) { |
444 | rt2x00_rf(&rt2x00dev->chip, RF5222)) { | ||
445 | rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1); | 444 | rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1); |
446 | rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 1); | 445 | rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 1); |
447 | rt2x00_set_field32(®, BBPCSR1_OFDM_FLIP, 1); | 446 | rt2x00_set_field32(®, BBPCSR1_OFDM_FLIP, 1); |
@@ -449,7 +448,7 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev, | |||
449 | /* | 448 | /* |
450 | * RT2525E does not need RX I/Q Flip. | 449 | * RT2525E does not need RX I/Q Flip. |
451 | */ | 450 | */ |
452 | if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) | 451 | if (rt2x00_rf(rt2x00dev, RF2525E)) |
453 | rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0); | 452 | rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0); |
454 | } else { | 453 | } else { |
455 | rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 0); | 454 | rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 0); |
@@ -475,14 +474,14 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev, | |||
475 | * Switch on tuning bits. | 474 | * Switch on tuning bits. |
476 | * For RT2523 devices we do not need to update the R1 register. | 475 | * For RT2523 devices we do not need to update the R1 register. |
477 | */ | 476 | */ |
478 | if (!rt2x00_rf(&rt2x00dev->chip, RF2523)) | 477 | if (!rt2x00_rf(rt2x00dev, RF2523)) |
479 | rt2x00_set_field32(&rf->rf1, RF1_TUNER, 1); | 478 | rt2x00_set_field32(&rf->rf1, RF1_TUNER, 1); |
480 | rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1); | 479 | rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1); |
481 | 480 | ||
482 | /* | 481 | /* |
483 | * For RT2525 we should first set the channel to half band higher. | 482 | * For RT2525 we should first set the channel to half band higher. |
484 | */ | 483 | */ |
485 | if (rt2x00_rf(&rt2x00dev->chip, RF2525)) { | 484 | if (rt2x00_rf(rt2x00dev, RF2525)) { |
486 | static const u32 vals[] = { | 485 | static const u32 vals[] = { |
487 | 0x00080cbe, 0x00080d02, 0x00080d06, 0x00080d0a, | 486 | 0x00080cbe, 0x00080d02, 0x00080d06, 0x00080d0a, |
488 | 0x00080d0e, 0x00080d12, 0x00080d16, 0x00080d1a, | 487 | 0x00080d0e, 0x00080d12, 0x00080d16, 0x00080d1a, |
@@ -516,7 +515,7 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev, | |||
516 | * Switch off tuning bits. | 515 | * Switch off tuning bits. |
517 | * For RT2523 devices we do not need to update the R1 register. | 516 | * For RT2523 devices we do not need to update the R1 register. |
518 | */ | 517 | */ |
519 | if (!rt2x00_rf(&rt2x00dev->chip, RF2523)) { | 518 | if (!rt2x00_rf(rt2x00dev, RF2523)) { |
520 | rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0); | 519 | rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0); |
521 | rt2500pci_rf_write(rt2x00dev, 1, rf->rf1); | 520 | rt2500pci_rf_write(rt2x00dev, 1, rf->rf1); |
522 | } | 521 | } |
@@ -640,7 +639,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev, | |||
640 | * up to version C the link tuning should halt after 20 | 639 | * up to version C the link tuning should halt after 20 |
641 | * seconds while being associated. | 640 | * seconds while being associated. |
642 | */ | 641 | */ |
643 | if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D && | 642 | if (rt2x00_rev(rt2x00dev) < RT2560_VERSION_D && |
644 | rt2x00dev->intf_associated && count > 20) | 643 | rt2x00dev->intf_associated && count > 20) |
645 | return; | 644 | return; |
646 | 645 | ||
@@ -650,7 +649,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev, | |||
650 | * should go straight to dynamic CCA tuning when they | 649 | * should go straight to dynamic CCA tuning when they |
651 | * are not associated. | 650 | * are not associated. |
652 | */ | 651 | */ |
653 | if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D || | 652 | if (rt2x00_rev(rt2x00dev) < RT2560_VERSION_D || |
654 | !rt2x00dev->intf_associated) | 653 | !rt2x00dev->intf_associated) |
655 | goto dynamic_cca_tune; | 654 | goto dynamic_cca_tune; |
656 | 655 | ||
@@ -1504,15 +1503,15 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1504 | */ | 1503 | */ |
1505 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); | 1504 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); |
1506 | rt2x00pci_register_read(rt2x00dev, CSR0, ®); | 1505 | rt2x00pci_register_read(rt2x00dev, CSR0, ®); |
1507 | rt2x00_set_chip_rf(rt2x00dev, value, reg); | 1506 | rt2x00_set_chip(rt2x00dev, RT2560, value, |
1508 | rt2x00_print_chip(rt2x00dev); | 1507 | rt2x00_get_field32(reg, CSR0_REVISION)); |
1509 | 1508 | ||
1510 | if (!rt2x00_rf(&rt2x00dev->chip, RF2522) && | 1509 | if (!rt2x00_rf(rt2x00dev, RF2522) && |
1511 | !rt2x00_rf(&rt2x00dev->chip, RF2523) && | 1510 | !rt2x00_rf(rt2x00dev, RF2523) && |
1512 | !rt2x00_rf(&rt2x00dev->chip, RF2524) && | 1511 | !rt2x00_rf(rt2x00dev, RF2524) && |
1513 | !rt2x00_rf(&rt2x00dev->chip, RF2525) && | 1512 | !rt2x00_rf(rt2x00dev, RF2525) && |
1514 | !rt2x00_rf(&rt2x00dev->chip, RF2525E) && | 1513 | !rt2x00_rf(rt2x00dev, RF2525E) && |
1515 | !rt2x00_rf(&rt2x00dev->chip, RF5222)) { | 1514 | !rt2x00_rf(rt2x00dev, RF5222)) { |
1516 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); | 1515 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); |
1517 | return -ENODEV; | 1516 | return -ENODEV; |
1518 | } | 1517 | } |
@@ -1744,22 +1743,22 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
1744 | spec->supported_bands = SUPPORT_BAND_2GHZ; | 1743 | spec->supported_bands = SUPPORT_BAND_2GHZ; |
1745 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; | 1744 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; |
1746 | 1745 | ||
1747 | if (rt2x00_rf(&rt2x00dev->chip, RF2522)) { | 1746 | if (rt2x00_rf(rt2x00dev, RF2522)) { |
1748 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522); | 1747 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522); |
1749 | spec->channels = rf_vals_bg_2522; | 1748 | spec->channels = rf_vals_bg_2522; |
1750 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2523)) { | 1749 | } else if (rt2x00_rf(rt2x00dev, RF2523)) { |
1751 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523); | 1750 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523); |
1752 | spec->channels = rf_vals_bg_2523; | 1751 | spec->channels = rf_vals_bg_2523; |
1753 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2524)) { | 1752 | } else if (rt2x00_rf(rt2x00dev, RF2524)) { |
1754 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524); | 1753 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524); |
1755 | spec->channels = rf_vals_bg_2524; | 1754 | spec->channels = rf_vals_bg_2524; |
1756 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2525)) { | 1755 | } else if (rt2x00_rf(rt2x00dev, RF2525)) { |
1757 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525); | 1756 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525); |
1758 | spec->channels = rf_vals_bg_2525; | 1757 | spec->channels = rf_vals_bg_2525; |
1759 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) { | 1758 | } else if (rt2x00_rf(rt2x00dev, RF2525E)) { |
1760 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); | 1759 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); |
1761 | spec->channels = rf_vals_bg_2525e; | 1760 | spec->channels = rf_vals_bg_2525e; |
1762 | } else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) { | 1761 | } else if (rt2x00_rf(rt2x00dev, RF5222)) { |
1763 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 1762 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
1764 | spec->num_channels = ARRAY_SIZE(rf_vals_5222); | 1763 | spec->num_channels = ARRAY_SIZE(rf_vals_5222); |
1765 | spec->channels = rf_vals_5222; | 1764 | spec->channels = rf_vals_5222; |
@@ -1860,7 +1859,6 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { | |||
1860 | .get_stats = rt2x00mac_get_stats, | 1859 | .get_stats = rt2x00mac_get_stats, |
1861 | .bss_info_changed = rt2x00mac_bss_info_changed, | 1860 | .bss_info_changed = rt2x00mac_bss_info_changed, |
1862 | .conf_tx = rt2x00mac_conf_tx, | 1861 | .conf_tx = rt2x00mac_conf_tx, |
1863 | .get_tx_stats = rt2x00mac_get_tx_stats, | ||
1864 | .get_tsf = rt2500pci_get_tsf, | 1862 | .get_tsf = rt2500pci_get_tsf, |
1865 | .tx_last_beacon = rt2500pci_tx_last_beacon, | 1863 | .tx_last_beacon = rt2500pci_tx_last_beacon, |
1866 | .rfkill_poll = rt2x00mac_rfkill_poll, | 1864 | .rfkill_poll = rt2x00mac_rfkill_poll, |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h index b0075674c09b..6471f8e74b35 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.h +++ b/drivers/net/wireless/rt2x00/rt2500pci.h | |||
@@ -76,6 +76,7 @@ | |||
76 | * CSR0: ASIC revision number. | 76 | * CSR0: ASIC revision number. |
77 | */ | 77 | */ |
78 | #define CSR0 0x0000 | 78 | #define CSR0 0x0000 |
79 | #define CSR0_REVISION FIELD32(0x0000ffff) | ||
79 | 80 | ||
80 | /* | 81 | /* |
81 | * CSR1: System control register. | 82 | * CSR1: System control register. |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 83f2592c59de..ee34c137e7cd 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -565,8 +565,7 @@ static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev, | |||
565 | /* | 565 | /* |
566 | * RT2525E and RT5222 need to flip TX I/Q | 566 | * RT2525E and RT5222 need to flip TX I/Q |
567 | */ | 567 | */ |
568 | if (rt2x00_rf(&rt2x00dev->chip, RF2525E) || | 568 | if (rt2x00_rf(rt2x00dev, RF2525E) || rt2x00_rf(rt2x00dev, RF5222)) { |
569 | rt2x00_rf(&rt2x00dev->chip, RF5222)) { | ||
570 | rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1); | 569 | rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1); |
571 | rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 1); | 570 | rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 1); |
572 | rt2x00_set_field16(&csr6, PHY_CSR6_OFDM_FLIP, 1); | 571 | rt2x00_set_field16(&csr6, PHY_CSR6_OFDM_FLIP, 1); |
@@ -574,7 +573,7 @@ static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev, | |||
574 | /* | 573 | /* |
575 | * RT2525E does not need RX I/Q Flip. | 574 | * RT2525E does not need RX I/Q Flip. |
576 | */ | 575 | */ |
577 | if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) | 576 | if (rt2x00_rf(rt2x00dev, RF2525E)) |
578 | rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0); | 577 | rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0); |
579 | } else { | 578 | } else { |
580 | rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 0); | 579 | rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 0); |
@@ -598,7 +597,7 @@ static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev, | |||
598 | /* | 597 | /* |
599 | * For RT2525E we should first set the channel to half band higher. | 598 | * For RT2525E we should first set the channel to half band higher. |
600 | */ | 599 | */ |
601 | if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) { | 600 | if (rt2x00_rf(rt2x00dev, RF2525E)) { |
602 | static const u32 vals[] = { | 601 | static const u32 vals[] = { |
603 | 0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2, | 602 | 0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2, |
604 | 0x000008b2, 0x000008b6, 0x000008b6, 0x000008ba, | 603 | 0x000008b2, 0x000008b6, 0x000008b6, 0x000008ba, |
@@ -793,7 +792,7 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) | |||
793 | rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 1); | 792 | rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 1); |
794 | rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg); | 793 | rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg); |
795 | 794 | ||
796 | if (rt2x00_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) { | 795 | if (rt2x00_rev(rt2x00dev) >= RT2570_VERSION_C) { |
797 | rt2500usb_register_read(rt2x00dev, PHY_CSR2, ®); | 796 | rt2500usb_register_read(rt2x00dev, PHY_CSR2, ®); |
798 | rt2x00_set_field16(®, PHY_CSR2_LNA, 0); | 797 | rt2x00_set_field16(®, PHY_CSR2_LNA, 0); |
799 | } else { | 798 | } else { |
@@ -1409,21 +1408,18 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1409 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); | 1408 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); |
1410 | rt2500usb_register_read(rt2x00dev, MAC_CSR0, ®); | 1409 | rt2500usb_register_read(rt2x00dev, MAC_CSR0, ®); |
1411 | rt2x00_set_chip(rt2x00dev, RT2570, value, reg); | 1410 | rt2x00_set_chip(rt2x00dev, RT2570, value, reg); |
1412 | rt2x00_print_chip(rt2x00dev); | ||
1413 | |||
1414 | if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0) || | ||
1415 | rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) { | ||
1416 | 1411 | ||
1412 | if (((reg & 0xfff0) != 0) || ((reg & 0x0000000f) == 0)) { | ||
1417 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); | 1413 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); |
1418 | return -ENODEV; | 1414 | return -ENODEV; |
1419 | } | 1415 | } |
1420 | 1416 | ||
1421 | if (!rt2x00_rf(&rt2x00dev->chip, RF2522) && | 1417 | if (!rt2x00_rf(rt2x00dev, RF2522) && |
1422 | !rt2x00_rf(&rt2x00dev->chip, RF2523) && | 1418 | !rt2x00_rf(rt2x00dev, RF2523) && |
1423 | !rt2x00_rf(&rt2x00dev->chip, RF2524) && | 1419 | !rt2x00_rf(rt2x00dev, RF2524) && |
1424 | !rt2x00_rf(&rt2x00dev->chip, RF2525) && | 1420 | !rt2x00_rf(rt2x00dev, RF2525) && |
1425 | !rt2x00_rf(&rt2x00dev->chip, RF2525E) && | 1421 | !rt2x00_rf(rt2x00dev, RF2525E) && |
1426 | !rt2x00_rf(&rt2x00dev->chip, RF5222)) { | 1422 | !rt2x00_rf(rt2x00dev, RF5222)) { |
1427 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); | 1423 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); |
1428 | return -ENODEV; | 1424 | return -ENODEV; |
1429 | } | 1425 | } |
@@ -1667,22 +1663,22 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
1667 | spec->supported_bands = SUPPORT_BAND_2GHZ; | 1663 | spec->supported_bands = SUPPORT_BAND_2GHZ; |
1668 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; | 1664 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; |
1669 | 1665 | ||
1670 | if (rt2x00_rf(&rt2x00dev->chip, RF2522)) { | 1666 | if (rt2x00_rf(rt2x00dev, RF2522)) { |
1671 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522); | 1667 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522); |
1672 | spec->channels = rf_vals_bg_2522; | 1668 | spec->channels = rf_vals_bg_2522; |
1673 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2523)) { | 1669 | } else if (rt2x00_rf(rt2x00dev, RF2523)) { |
1674 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523); | 1670 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523); |
1675 | spec->channels = rf_vals_bg_2523; | 1671 | spec->channels = rf_vals_bg_2523; |
1676 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2524)) { | 1672 | } else if (rt2x00_rf(rt2x00dev, RF2524)) { |
1677 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524); | 1673 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524); |
1678 | spec->channels = rf_vals_bg_2524; | 1674 | spec->channels = rf_vals_bg_2524; |
1679 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2525)) { | 1675 | } else if (rt2x00_rf(rt2x00dev, RF2525)) { |
1680 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525); | 1676 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525); |
1681 | spec->channels = rf_vals_bg_2525; | 1677 | spec->channels = rf_vals_bg_2525; |
1682 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) { | 1678 | } else if (rt2x00_rf(rt2x00dev, RF2525E)) { |
1683 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); | 1679 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); |
1684 | spec->channels = rf_vals_bg_2525e; | 1680 | spec->channels = rf_vals_bg_2525e; |
1685 | } else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) { | 1681 | } else if (rt2x00_rf(rt2x00dev, RF5222)) { |
1686 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 1682 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
1687 | spec->num_channels = ARRAY_SIZE(rf_vals_5222); | 1683 | spec->num_channels = ARRAY_SIZE(rf_vals_5222); |
1688 | spec->channels = rf_vals_5222; | 1684 | spec->channels = rf_vals_5222; |
@@ -1763,7 +1759,6 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = { | |||
1763 | .get_stats = rt2x00mac_get_stats, | 1759 | .get_stats = rt2x00mac_get_stats, |
1764 | .bss_info_changed = rt2x00mac_bss_info_changed, | 1760 | .bss_info_changed = rt2x00mac_bss_info_changed, |
1765 | .conf_tx = rt2x00mac_conf_tx, | 1761 | .conf_tx = rt2x00mac_conf_tx, |
1766 | .get_tx_stats = rt2x00mac_get_tx_stats, | ||
1767 | .rfkill_poll = rt2x00mac_rfkill_poll, | 1762 | .rfkill_poll = rt2x00mac_rfkill_poll, |
1768 | }; | 1763 | }; |
1769 | 1764 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 1a7eae357fef..74c0433dba37 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -60,11 +60,11 @@ | |||
60 | /* | 60 | /* |
61 | * Chipset version. | 61 | * Chipset version. |
62 | */ | 62 | */ |
63 | #define RT2860C_VERSION 0x28600100 | 63 | #define RT2860C_VERSION 0x0100 |
64 | #define RT2860D_VERSION 0x28600101 | 64 | #define RT2860D_VERSION 0x0101 |
65 | #define RT2880E_VERSION 0x28720200 | 65 | #define RT2880E_VERSION 0x0200 |
66 | #define RT2883_VERSION 0x28830300 | 66 | #define RT2883_VERSION 0x0300 |
67 | #define RT3070_VERSION 0x30700200 | 67 | #define RT3070_VERSION 0x0200 |
68 | 68 | ||
69 | /* | 69 | /* |
70 | * Signal information. | 70 | * Signal information. |
@@ -408,8 +408,8 @@ | |||
408 | * ASIC_VER: 2860 or 2870 | 408 | * ASIC_VER: 2860 or 2870 |
409 | */ | 409 | */ |
410 | #define MAC_CSR0 0x1000 | 410 | #define MAC_CSR0 0x1000 |
411 | #define MAC_CSR0_ASIC_REV FIELD32(0x0000ffff) | 411 | #define MAC_CSR0_REVISION FIELD32(0x0000ffff) |
412 | #define MAC_CSR0_ASIC_VER FIELD32(0xffff0000) | 412 | #define MAC_CSR0_CHIPSET FIELD32(0xffff0000) |
413 | 413 | ||
414 | /* | 414 | /* |
415 | * MAC_SYS_CTRL: | 415 | * MAC_SYS_CTRL: |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 9deae41cb784..18d4d8e4ae6b 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -37,9 +37,12 @@ | |||
37 | #include <linux/module.h> | 37 | #include <linux/module.h> |
38 | 38 | ||
39 | #include "rt2x00.h" | 39 | #include "rt2x00.h" |
40 | #if defined(CONFIG_RT2800USB) || defined(CONFIG_RT2800USB_MODULE) | 40 | #if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE) |
41 | #include "rt2x00usb.h" | 41 | #include "rt2x00usb.h" |
42 | #endif | 42 | #endif |
43 | #if defined(CONFIG_RT2X00_LIB_PCI) || defined(CONFIG_RT2X00_LIB_PCI_MODULE) | ||
44 | #include "rt2x00pci.h" | ||
45 | #endif | ||
43 | #include "rt2800lib.h" | 46 | #include "rt2800lib.h" |
44 | #include "rt2800.h" | 47 | #include "rt2800.h" |
45 | #include "rt2800usb.h" | 48 | #include "rt2800usb.h" |
@@ -89,7 +92,7 @@ static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
89 | rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); | 92 | rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); |
90 | rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); | 93 | rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); |
91 | rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 0); | 94 | rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 0); |
92 | if (rt2x00_intf_is_pci(rt2x00dev)) | 95 | if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) |
93 | rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1); | 96 | rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1); |
94 | 97 | ||
95 | rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); | 98 | rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); |
@@ -118,7 +121,7 @@ static void rt2800_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
118 | rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); | 121 | rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); |
119 | rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); | 122 | rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); |
120 | rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 1); | 123 | rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 1); |
121 | if (rt2x00_intf_is_pci(rt2x00dev)) | 124 | if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) |
122 | rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1); | 125 | rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1); |
123 | 126 | ||
124 | rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); | 127 | rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); |
@@ -218,10 +221,9 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, | |||
218 | u32 reg; | 221 | u32 reg; |
219 | 222 | ||
220 | /* | 223 | /* |
221 | * RT2880 and RT3052 don't support MCU requests. | 224 | * SOC devices don't support MCU requests. |
222 | */ | 225 | */ |
223 | if (rt2x00_rt(&rt2x00dev->chip, RT2880) || | 226 | if (rt2x00_is_soc(rt2x00dev)) |
224 | rt2x00_rt(&rt2x00dev->chip, RT3052)) | ||
225 | return; | 227 | return; |
226 | 228 | ||
227 | mutex_lock(&rt2x00dev->csr_mutex); | 229 | mutex_lock(&rt2x00dev->csr_mutex); |
@@ -246,6 +248,25 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, | |||
246 | } | 248 | } |
247 | EXPORT_SYMBOL_GPL(rt2800_mcu_request); | 249 | EXPORT_SYMBOL_GPL(rt2800_mcu_request); |
248 | 250 | ||
251 | int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) | ||
252 | { | ||
253 | unsigned int i; | ||
254 | u32 reg; | ||
255 | |||
256 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
257 | rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); | ||
258 | if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) && | ||
259 | !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY)) | ||
260 | return 0; | ||
261 | |||
262 | msleep(1); | ||
263 | } | ||
264 | |||
265 | ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n"); | ||
266 | return -EACCES; | ||
267 | } | ||
268 | EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready); | ||
269 | |||
249 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | 270 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS |
250 | const struct rt2x00debug rt2800_rt2x00debug = { | 271 | const struct rt2x00debug rt2800_rt2x00debug = { |
251 | .owner = THIS_MODULE, | 272 | .owner = THIS_MODULE, |
@@ -348,7 +369,7 @@ static int rt2800_blink_set(struct led_classdev *led_cdev, | |||
348 | return 0; | 369 | return 0; |
349 | } | 370 | } |
350 | 371 | ||
351 | void rt2800_init_led(struct rt2x00_dev *rt2x00dev, | 372 | static void rt2800_init_led(struct rt2x00_dev *rt2x00dev, |
352 | struct rt2x00_led *led, enum led_type type) | 373 | struct rt2x00_led *led, enum led_type type) |
353 | { | 374 | { |
354 | led->rt2x00dev = rt2x00dev; | 375 | led->rt2x00dev = rt2x00dev; |
@@ -357,7 +378,6 @@ void rt2800_init_led(struct rt2x00_dev *rt2x00dev, | |||
357 | led->led_dev.blink_set = rt2800_blink_set; | 378 | led->led_dev.blink_set = rt2800_blink_set; |
358 | led->flags = LED_INITIALIZED; | 379 | led->flags = LED_INITIALIZED; |
359 | } | 380 | } |
360 | EXPORT_SYMBOL_GPL(rt2800_init_led); | ||
361 | #endif /* CONFIG_RT2X00_LIB_LEDS */ | 381 | #endif /* CONFIG_RT2X00_LIB_LEDS */ |
362 | 382 | ||
363 | /* | 383 | /* |
@@ -643,7 +663,7 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant) | |||
643 | switch ((int)ant->tx) { | 663 | switch ((int)ant->tx) { |
644 | case 1: | 664 | case 1: |
645 | rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); | 665 | rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); |
646 | if (rt2x00_intf_is_pci(rt2x00dev)) | 666 | if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) |
647 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); | 667 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); |
648 | break; | 668 | break; |
649 | case 2: | 669 | case 2: |
@@ -806,12 +826,12 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
806 | unsigned int tx_pin; | 826 | unsigned int tx_pin; |
807 | u8 bbp; | 827 | u8 bbp; |
808 | 828 | ||
809 | if ((rt2x00_rt(&rt2x00dev->chip, RT3070) || | 829 | if ((rt2x00_rt(rt2x00dev, RT3070) || |
810 | rt2x00_rt(&rt2x00dev->chip, RT3090)) && | 830 | rt2x00_rt(rt2x00dev, RT3090)) && |
811 | (rt2x00_rf(&rt2x00dev->chip, RF2020) || | 831 | (rt2x00_rf(rt2x00dev, RF2020) || |
812 | rt2x00_rf(&rt2x00dev->chip, RF3020) || | 832 | rt2x00_rf(rt2x00dev, RF3020) || |
813 | rt2x00_rf(&rt2x00dev->chip, RF3021) || | 833 | rt2x00_rf(rt2x00dev, RF3021) || |
814 | rt2x00_rf(&rt2x00dev->chip, RF3022))) | 834 | rt2x00_rf(rt2x00dev, RF3022))) |
815 | rt2800_config_channel_rt3x(rt2x00dev, conf, rf, info); | 835 | rt2800_config_channel_rt3x(rt2x00dev, conf, rf, info); |
816 | else | 836 | else |
817 | rt2800_config_channel_rt2x(rt2x00dev, conf, rf, info); | 837 | rt2800_config_channel_rt2x(rt2x00dev, conf, rf, info); |
@@ -878,7 +898,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
878 | rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); | 898 | rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); |
879 | rt2800_bbp_write(rt2x00dev, 3, bbp); | 899 | rt2800_bbp_write(rt2x00dev, 3, bbp); |
880 | 900 | ||
881 | if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { | 901 | if (rt2x00_rt(rt2x00dev, RT2860) && |
902 | (rt2x00_rev(rt2x00dev) == RT2860C_VERSION)) { | ||
882 | if (conf_is_ht40(conf)) { | 903 | if (conf_is_ht40(conf)) { |
883 | rt2800_bbp_write(rt2x00dev, 69, 0x1a); | 904 | rt2800_bbp_write(rt2x00dev, 69, 0x1a); |
884 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); | 905 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); |
@@ -1040,8 +1061,9 @@ EXPORT_SYMBOL_GPL(rt2800_link_stats); | |||
1040 | static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) | 1061 | static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) |
1041 | { | 1062 | { |
1042 | if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { | 1063 | if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { |
1043 | if (rt2x00_intf_is_usb(rt2x00dev) && | 1064 | if (rt2x00_is_usb(rt2x00dev) && |
1044 | rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) | 1065 | rt2x00_rt(rt2x00dev, RT3070) && |
1066 | (rt2x00_rev(rt2x00dev) == RT3070_VERSION)) | ||
1045 | return 0x1c + (2 * rt2x00dev->lna_gain); | 1067 | return 0x1c + (2 * rt2x00dev->lna_gain); |
1046 | else | 1068 | else |
1047 | return 0x2e + rt2x00dev->lna_gain; | 1069 | return 0x2e + rt2x00dev->lna_gain; |
@@ -1072,7 +1094,8 @@ EXPORT_SYMBOL_GPL(rt2800_reset_tuner); | |||
1072 | void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, | 1094 | void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, |
1073 | const u32 count) | 1095 | const u32 count) |
1074 | { | 1096 | { |
1075 | if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) | 1097 | if (rt2x00_rt(rt2x00dev, RT2860) && |
1098 | (rt2x00_rev(rt2x00dev) == RT2860C_VERSION)) | ||
1076 | return; | 1099 | return; |
1077 | 1100 | ||
1078 | /* | 1101 | /* |
@@ -1092,7 +1115,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1092 | u32 reg; | 1115 | u32 reg; |
1093 | unsigned int i; | 1116 | unsigned int i; |
1094 | 1117 | ||
1095 | if (rt2x00_intf_is_usb(rt2x00dev)) { | 1118 | if (rt2x00_is_usb(rt2x00dev)) { |
1096 | /* | 1119 | /* |
1097 | * Wait until BBP and RF are ready. | 1120 | * Wait until BBP and RF are ready. |
1098 | */ | 1121 | */ |
@@ -1111,7 +1134,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1111 | rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); | 1134 | rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); |
1112 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, | 1135 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, |
1113 | reg & ~0x00002000); | 1136 | reg & ~0x00002000); |
1114 | } else if (rt2x00_intf_is_pci(rt2x00dev)) | 1137 | } else if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) |
1115 | rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); | 1138 | rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); |
1116 | 1139 | ||
1117 | rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); | 1140 | rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); |
@@ -1119,9 +1142,9 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1119 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); | 1142 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); |
1120 | rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | 1143 | rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); |
1121 | 1144 | ||
1122 | if (rt2x00_intf_is_usb(rt2x00dev)) { | 1145 | if (rt2x00_is_usb(rt2x00dev)) { |
1123 | rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); | 1146 | rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); |
1124 | #if defined(CONFIG_RT2800USB) || defined(CONFIG_RT2800USB_MODULE) | 1147 | #if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE) |
1125 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, | 1148 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, |
1126 | USB_MODE_RESET, REGISTER_TIMEOUT); | 1149 | USB_MODE_RESET, REGISTER_TIMEOUT); |
1127 | #endif | 1150 | #endif |
@@ -1157,8 +1180,9 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1157 | rt2x00_set_field32(®, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0); | 1180 | rt2x00_set_field32(®, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0); |
1158 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | 1181 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); |
1159 | 1182 | ||
1160 | if (rt2x00_intf_is_usb(rt2x00dev) && | 1183 | if (rt2x00_is_usb(rt2x00dev) && |
1161 | rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) { | 1184 | rt2x00_rt(rt2x00dev, RT3070) && |
1185 | (rt2x00_rev(rt2x00dev) == RT3070_VERSION)) { | ||
1162 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); | 1186 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); |
1163 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); | 1187 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); |
1164 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); | 1188 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); |
@@ -1185,8 +1209,14 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1185 | 1209 | ||
1186 | rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®); | 1210 | rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®); |
1187 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); | 1211 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); |
1188 | if (rt2x00_rev(&rt2x00dev->chip) >= RT2880E_VERSION && | 1212 | if ((rt2x00_rt(rt2x00dev, RT2872) && |
1189 | rt2x00_rev(&rt2x00dev->chip) < RT3070_VERSION) | 1213 | (rt2x00_rev(rt2x00dev) >= RT2880E_VERSION)) || |
1214 | rt2x00_rt(rt2x00dev, RT2880) || | ||
1215 | rt2x00_rt(rt2x00dev, RT2883) || | ||
1216 | rt2x00_rt(rt2x00dev, RT2890) || | ||
1217 | rt2x00_rt(rt2x00dev, RT3052) || | ||
1218 | (rt2x00_rt(rt2x00dev, RT3070) && | ||
1219 | (rt2x00_rev(rt2x00dev) < RT3070_VERSION))) | ||
1190 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); | 1220 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); |
1191 | else | 1221 | else |
1192 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); | 1222 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); |
@@ -1276,7 +1306,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1276 | rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1); | 1306 | rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1); |
1277 | rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg); | 1307 | rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg); |
1278 | 1308 | ||
1279 | if (rt2x00_intf_is_usb(rt2x00dev)) { | 1309 | if (rt2x00_is_usb(rt2x00dev)) { |
1280 | rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); | 1310 | rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); |
1281 | 1311 | ||
1282 | rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); | 1312 | rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); |
@@ -1336,7 +1366,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1336 | rt2800_register_write(rt2x00dev, HW_BEACON_BASE6, 0); | 1366 | rt2800_register_write(rt2x00dev, HW_BEACON_BASE6, 0); |
1337 | rt2800_register_write(rt2x00dev, HW_BEACON_BASE7, 0); | 1367 | rt2800_register_write(rt2x00dev, HW_BEACON_BASE7, 0); |
1338 | 1368 | ||
1339 | if (rt2x00_intf_is_usb(rt2x00dev)) { | 1369 | if (rt2x00_is_usb(rt2x00dev)) { |
1340 | rt2800_register_read(rt2x00dev, USB_CYC_CFG, ®); | 1370 | rt2800_register_read(rt2x00dev, USB_CYC_CFG, ®); |
1341 | rt2x00_set_field32(®, USB_CYC_CFG_CLOCK_CYCLE, 30); | 1371 | rt2x00_set_field32(®, USB_CYC_CFG_CLOCK_CYCLE, 30); |
1342 | rt2800_register_write(rt2x00dev, USB_CYC_CFG, reg); | 1372 | rt2800_register_write(rt2x00dev, USB_CYC_CFG, reg); |
@@ -1465,22 +1495,25 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
1465 | rt2800_bbp_write(rt2x00dev, 103, 0x00); | 1495 | rt2800_bbp_write(rt2x00dev, 103, 0x00); |
1466 | rt2800_bbp_write(rt2x00dev, 105, 0x05); | 1496 | rt2800_bbp_write(rt2x00dev, 105, 0x05); |
1467 | 1497 | ||
1468 | if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { | 1498 | if (rt2x00_rt(rt2x00dev, RT2860) && |
1499 | (rt2x00_rev(rt2x00dev) == RT2860C_VERSION)) { | ||
1469 | rt2800_bbp_write(rt2x00dev, 69, 0x16); | 1500 | rt2800_bbp_write(rt2x00dev, 69, 0x16); |
1470 | rt2800_bbp_write(rt2x00dev, 73, 0x12); | 1501 | rt2800_bbp_write(rt2x00dev, 73, 0x12); |
1471 | } | 1502 | } |
1472 | 1503 | ||
1473 | if (rt2x00_rev(&rt2x00dev->chip) > RT2860D_VERSION) | 1504 | if (rt2x00_rt(rt2x00dev, RT2860) && |
1505 | (rt2x00_rev(rt2x00dev) > RT2860D_VERSION)) | ||
1474 | rt2800_bbp_write(rt2x00dev, 84, 0x19); | 1506 | rt2800_bbp_write(rt2x00dev, 84, 0x19); |
1475 | 1507 | ||
1476 | if (rt2x00_intf_is_usb(rt2x00dev) && | 1508 | if (rt2x00_is_usb(rt2x00dev) && |
1477 | rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) { | 1509 | rt2x00_rt(rt2x00dev, RT3070) && |
1510 | (rt2x00_rev(rt2x00dev) == RT3070_VERSION)) { | ||
1478 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); | 1511 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); |
1479 | rt2800_bbp_write(rt2x00dev, 84, 0x99); | 1512 | rt2800_bbp_write(rt2x00dev, 84, 0x99); |
1480 | rt2800_bbp_write(rt2x00dev, 105, 0x05); | 1513 | rt2800_bbp_write(rt2x00dev, 105, 0x05); |
1481 | } | 1514 | } |
1482 | 1515 | ||
1483 | if (rt2x00_rt(&rt2x00dev->chip, RT3052)) { | 1516 | if (rt2x00_rt(rt2x00dev, RT3052)) { |
1484 | rt2800_bbp_write(rt2x00dev, 31, 0x08); | 1517 | rt2800_bbp_write(rt2x00dev, 31, 0x08); |
1485 | rt2800_bbp_write(rt2x00dev, 78, 0x0e); | 1518 | rt2800_bbp_write(rt2x00dev, 78, 0x0e); |
1486 | rt2800_bbp_write(rt2x00dev, 80, 0x08); | 1519 | rt2800_bbp_write(rt2x00dev, 80, 0x08); |
@@ -1565,14 +1598,15 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
1565 | u8 rfcsr; | 1598 | u8 rfcsr; |
1566 | u8 bbp; | 1599 | u8 bbp; |
1567 | 1600 | ||
1568 | if (rt2x00_intf_is_usb(rt2x00dev) && | 1601 | if (rt2x00_is_usb(rt2x00dev) && |
1569 | rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION) | 1602 | rt2x00_rt(rt2x00dev, RT3070) && |
1603 | (rt2x00_rev(rt2x00dev) != RT3070_VERSION)) | ||
1570 | return 0; | 1604 | return 0; |
1571 | 1605 | ||
1572 | if (rt2x00_intf_is_pci(rt2x00dev)) { | 1606 | if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) { |
1573 | if (!rt2x00_rf(&rt2x00dev->chip, RF3020) && | 1607 | if (!rt2x00_rf(rt2x00dev, RF3020) && |
1574 | !rt2x00_rf(&rt2x00dev->chip, RF3021) && | 1608 | !rt2x00_rf(rt2x00dev, RF3021) && |
1575 | !rt2x00_rf(&rt2x00dev->chip, RF3022)) | 1609 | !rt2x00_rf(rt2x00dev, RF3022)) |
1576 | return 0; | 1610 | return 0; |
1577 | } | 1611 | } |
1578 | 1612 | ||
@@ -1586,7 +1620,7 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
1586 | rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); | 1620 | rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); |
1587 | rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); | 1621 | rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); |
1588 | 1622 | ||
1589 | if (rt2x00_intf_is_usb(rt2x00dev)) { | 1623 | if (rt2x00_is_usb(rt2x00dev)) { |
1590 | rt2800_rfcsr_write(rt2x00dev, 4, 0x40); | 1624 | rt2800_rfcsr_write(rt2x00dev, 4, 0x40); |
1591 | rt2800_rfcsr_write(rt2x00dev, 5, 0x03); | 1625 | rt2800_rfcsr_write(rt2x00dev, 5, 0x03); |
1592 | rt2800_rfcsr_write(rt2x00dev, 6, 0x02); | 1626 | rt2800_rfcsr_write(rt2x00dev, 6, 0x02); |
@@ -1607,7 +1641,7 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
1607 | rt2800_rfcsr_write(rt2x00dev, 25, 0x01); | 1641 | rt2800_rfcsr_write(rt2x00dev, 25, 0x01); |
1608 | rt2800_rfcsr_write(rt2x00dev, 27, 0x03); | 1642 | rt2800_rfcsr_write(rt2x00dev, 27, 0x03); |
1609 | rt2800_rfcsr_write(rt2x00dev, 29, 0x1f); | 1643 | rt2800_rfcsr_write(rt2x00dev, 29, 0x1f); |
1610 | } else if (rt2x00_intf_is_pci(rt2x00dev)) { | 1644 | } else if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) { |
1611 | rt2800_rfcsr_write(rt2x00dev, 0, 0x50); | 1645 | rt2800_rfcsr_write(rt2x00dev, 0, 0x50); |
1612 | rt2800_rfcsr_write(rt2x00dev, 1, 0x01); | 1646 | rt2800_rfcsr_write(rt2x00dev, 1, 0x01); |
1613 | rt2800_rfcsr_write(rt2x00dev, 2, 0xf7); | 1647 | rt2800_rfcsr_write(rt2x00dev, 2, 0xf7); |
@@ -1737,7 +1771,12 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1737 | rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820); | 1771 | rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820); |
1738 | rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); | 1772 | rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); |
1739 | EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); | 1773 | EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); |
1740 | } else if (rt2x00_rev(&rt2x00dev->chip) < RT2883_VERSION) { | 1774 | } else if (rt2x00_rt(rt2x00dev, RT2860) || |
1775 | rt2x00_rt(rt2x00dev, RT2870) || | ||
1776 | rt2x00_rt(rt2x00dev, RT2872) || | ||
1777 | rt2x00_rt(rt2x00dev, RT2880) || | ||
1778 | (rt2x00_rt(rt2x00dev, RT2883) && | ||
1779 | (rt2x00_rev(rt2x00dev) < RT2883_VERSION))) { | ||
1741 | /* | 1780 | /* |
1742 | * There is a max of 2 RX streams for RT28x0 series | 1781 | * There is a max of 2 RX streams for RT28x0 series |
1743 | */ | 1782 | */ |
@@ -1836,36 +1875,34 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1836 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); | 1875 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); |
1837 | rt2800_register_read(rt2x00dev, MAC_CSR0, ®); | 1876 | rt2800_register_read(rt2x00dev, MAC_CSR0, ®); |
1838 | 1877 | ||
1839 | rt2x00_set_chip_rf(rt2x00dev, value, reg); | 1878 | rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET), |
1840 | 1879 | value, rt2x00_get_field32(reg, MAC_CSR0_REVISION)); | |
1841 | if (rt2x00_intf_is_usb(rt2x00dev)) { | 1880 | |
1842 | struct rt2x00_chip *chip = &rt2x00dev->chip; | 1881 | if (!rt2x00_rt(rt2x00dev, RT2860) && |
1843 | 1882 | !rt2x00_rt(rt2x00dev, RT2870) && | |
1844 | /* | 1883 | !rt2x00_rt(rt2x00dev, RT2872) && |
1845 | * The check for rt2860 is not a typo, some rt2870 hardware | 1884 | !rt2x00_rt(rt2x00dev, RT2880) && |
1846 | * identifies itself as rt2860 in the CSR register. | 1885 | !rt2x00_rt(rt2x00dev, RT2883) && |
1847 | */ | 1886 | !rt2x00_rt(rt2x00dev, RT2890) && |
1848 | if (rt2x00_check_rev(chip, 0xfff00000, 0x28600000) || | 1887 | !rt2x00_rt(rt2x00dev, RT3052) && |
1849 | rt2x00_check_rev(chip, 0xfff00000, 0x28700000) || | 1888 | !rt2x00_rt(rt2x00dev, RT3070) && |
1850 | rt2x00_check_rev(chip, 0xfff00000, 0x28800000)) { | 1889 | !rt2x00_rt(rt2x00dev, RT3071) && |
1851 | rt2x00_set_chip_rt(rt2x00dev, RT2870); | 1890 | !rt2x00_rt(rt2x00dev, RT3090) && |
1852 | } else if (rt2x00_check_rev(chip, 0xffff0000, 0x30700000)) { | 1891 | !rt2x00_rt(rt2x00dev, RT3390) && |
1853 | rt2x00_set_chip_rt(rt2x00dev, RT3070); | 1892 | !rt2x00_rt(rt2x00dev, RT3572)) { |
1854 | } else { | 1893 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); |
1855 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); | 1894 | return -ENODEV; |
1856 | return -ENODEV; | ||
1857 | } | ||
1858 | } | 1895 | } |
1859 | rt2x00_print_chip(rt2x00dev); | 1896 | |
1860 | 1897 | if (!rt2x00_rf(rt2x00dev, RF2820) && | |
1861 | if (!rt2x00_rf(&rt2x00dev->chip, RF2820) && | 1898 | !rt2x00_rf(rt2x00dev, RF2850) && |
1862 | !rt2x00_rf(&rt2x00dev->chip, RF2850) && | 1899 | !rt2x00_rf(rt2x00dev, RF2720) && |
1863 | !rt2x00_rf(&rt2x00dev->chip, RF2720) && | 1900 | !rt2x00_rf(rt2x00dev, RF2750) && |
1864 | !rt2x00_rf(&rt2x00dev->chip, RF2750) && | 1901 | !rt2x00_rf(rt2x00dev, RF3020) && |
1865 | !rt2x00_rf(&rt2x00dev->chip, RF3020) && | 1902 | !rt2x00_rf(rt2x00dev, RF2020) && |
1866 | !rt2x00_rf(&rt2x00dev->chip, RF2020) && | 1903 | !rt2x00_rf(rt2x00dev, RF3021) && |
1867 | !rt2x00_rf(&rt2x00dev->chip, RF3021) && | 1904 | !rt2x00_rf(rt2x00dev, RF3022) && |
1868 | !rt2x00_rf(&rt2x00dev->chip, RF3022)) { | 1905 | !rt2x00_rf(rt2x00dev, RF3052)) { |
1869 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); | 1906 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); |
1870 | return -ENODEV; | 1907 | return -ENODEV; |
1871 | } | 1908 | } |
@@ -2013,7 +2050,6 @@ static const struct rf_channel rf_vals_302x[] = { | |||
2013 | 2050 | ||
2014 | int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | 2051 | int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) |
2015 | { | 2052 | { |
2016 | struct rt2x00_chip *chip = &rt2x00dev->chip; | ||
2017 | struct hw_mode_spec *spec = &rt2x00dev->spec; | 2053 | struct hw_mode_spec *spec = &rt2x00dev->spec; |
2018 | struct channel_info *info; | 2054 | struct channel_info *info; |
2019 | char *tx_power1; | 2055 | char *tx_power1; |
@@ -2024,7 +2060,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2024 | /* | 2060 | /* |
2025 | * Disable powersaving as default on PCI devices. | 2061 | * Disable powersaving as default on PCI devices. |
2026 | */ | 2062 | */ |
2027 | if (rt2x00_intf_is_pci(rt2x00dev)) | 2063 | if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) |
2028 | rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 2064 | rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
2029 | 2065 | ||
2030 | /* | 2066 | /* |
@@ -2049,19 +2085,19 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2049 | spec->supported_bands = SUPPORT_BAND_2GHZ; | 2085 | spec->supported_bands = SUPPORT_BAND_2GHZ; |
2050 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; | 2086 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; |
2051 | 2087 | ||
2052 | if (rt2x00_rf(chip, RF2820) || | 2088 | if (rt2x00_rf(rt2x00dev, RF2820) || |
2053 | rt2x00_rf(chip, RF2720) || | 2089 | rt2x00_rf(rt2x00dev, RF2720) || |
2054 | (rt2x00_intf_is_pci(rt2x00dev) && rt2x00_rf(chip, RF3052))) { | 2090 | rt2x00_rf(rt2x00dev, RF3052)) { |
2055 | spec->num_channels = 14; | 2091 | spec->num_channels = 14; |
2056 | spec->channels = rf_vals; | 2092 | spec->channels = rf_vals; |
2057 | } else if (rt2x00_rf(chip, RF2850) || rt2x00_rf(chip, RF2750)) { | 2093 | } else if (rt2x00_rf(rt2x00dev, RF2850) || rt2x00_rf(rt2x00dev, RF2750)) { |
2058 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 2094 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
2059 | spec->num_channels = ARRAY_SIZE(rf_vals); | 2095 | spec->num_channels = ARRAY_SIZE(rf_vals); |
2060 | spec->channels = rf_vals; | 2096 | spec->channels = rf_vals; |
2061 | } else if (rt2x00_rf(chip, RF3020) || | 2097 | } else if (rt2x00_rf(rt2x00dev, RF3020) || |
2062 | rt2x00_rf(chip, RF2020) || | 2098 | rt2x00_rf(rt2x00dev, RF2020) || |
2063 | rt2x00_rf(chip, RF3021) || | 2099 | rt2x00_rf(rt2x00dev, RF3021) || |
2064 | rt2x00_rf(chip, RF3022)) { | 2100 | rt2x00_rf(rt2x00dev, RF3022)) { |
2065 | spec->num_channels = ARRAY_SIZE(rf_vals_302x); | 2101 | spec->num_channels = ARRAY_SIZE(rf_vals_302x); |
2066 | spec->channels = rf_vals_302x; | 2102 | spec->channels = rf_vals_302x; |
2067 | } | 2103 | } |
@@ -2069,7 +2105,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2069 | /* | 2105 | /* |
2070 | * Initialize HT information. | 2106 | * Initialize HT information. |
2071 | */ | 2107 | */ |
2072 | if (!rt2x00_rf(chip, RF2020)) | 2108 | if (!rt2x00_rf(rt2x00dev, RF2020)) |
2073 | spec->ht.ht_supported = true; | 2109 | spec->ht.ht_supported = true; |
2074 | else | 2110 | else |
2075 | spec->ht.ht_supported = false; | 2111 | spec->ht.ht_supported = false; |
@@ -2282,7 +2318,6 @@ const struct ieee80211_ops rt2800_mac80211_ops = { | |||
2282 | .set_rts_threshold = rt2800_set_rts_threshold, | 2318 | .set_rts_threshold = rt2800_set_rts_threshold, |
2283 | .bss_info_changed = rt2x00mac_bss_info_changed, | 2319 | .bss_info_changed = rt2x00mac_bss_info_changed, |
2284 | .conf_tx = rt2800_conf_tx, | 2320 | .conf_tx = rt2800_conf_tx, |
2285 | .get_tx_stats = rt2x00mac_get_tx_stats, | ||
2286 | .get_tsf = rt2800_get_tsf, | 2321 | .get_tsf = rt2800_get_tsf, |
2287 | .rfkill_poll = rt2x00mac_rfkill_poll, | 2322 | .rfkill_poll = rt2x00mac_rfkill_poll, |
2288 | }; | 2323 | }; |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 535ce22f2ac8..ebabeae62d1b 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h | |||
@@ -114,8 +114,6 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, | |||
114 | extern const struct rt2x00debug rt2800_rt2x00debug; | 114 | extern const struct rt2x00debug rt2800_rt2x00debug; |
115 | 115 | ||
116 | int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev); | 116 | int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev); |
117 | void rt2800_init_led(struct rt2x00_dev *rt2x00dev, | ||
118 | struct rt2x00_led *led, enum led_type type); | ||
119 | int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev, | 117 | int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev, |
120 | struct rt2x00lib_crypto *crypto, | 118 | struct rt2x00lib_crypto *crypto, |
121 | struct ieee80211_key_conf *key); | 119 | struct ieee80211_key_conf *key); |
@@ -139,6 +137,7 @@ void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, | |||
139 | int rt2800_init_registers(struct rt2x00_dev *rt2x00dev); | 137 | int rt2800_init_registers(struct rt2x00_dev *rt2x00dev); |
140 | int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev); | 138 | int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev); |
141 | int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev); | 139 | int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev); |
140 | int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev); | ||
142 | 141 | ||
143 | int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev); | 142 | int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev); |
144 | void rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev); | 143 | void rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev); |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index dfc886fcb44d..0e4c41766edc 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -48,14 +48,6 @@ | |||
48 | #include "rt2800.h" | 48 | #include "rt2800.h" |
49 | #include "rt2800pci.h" | 49 | #include "rt2800pci.h" |
50 | 50 | ||
51 | #ifdef CONFIG_RT2800PCI_PCI_MODULE | ||
52 | #define CONFIG_RT2800PCI_PCI | ||
53 | #endif | ||
54 | |||
55 | #ifdef CONFIG_RT2800PCI_WISOC_MODULE | ||
56 | #define CONFIG_RT2800PCI_WISOC | ||
57 | #endif | ||
58 | |||
59 | /* | 51 | /* |
60 | * Allow hardware encryption to be disabled. | 52 | * Allow hardware encryption to be disabled. |
61 | */ | 53 | */ |
@@ -87,7 +79,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) | |||
87 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); | 79 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); |
88 | } | 80 | } |
89 | 81 | ||
90 | #ifdef CONFIG_RT2800PCI_WISOC | 82 | #ifdef CONFIG_RT2800PCI_SOC |
91 | static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | 83 | static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) |
92 | { | 84 | { |
93 | u32 *base_addr = (u32 *) KSEG1ADDR(0x1F040000); /* XXX for RT3052 */ | 85 | u32 *base_addr = (u32 *) KSEG1ADDR(0x1F040000); /* XXX for RT3052 */ |
@@ -98,7 +90,7 @@ static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | |||
98 | static inline void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | 90 | static inline void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) |
99 | { | 91 | { |
100 | } | 92 | } |
101 | #endif /* CONFIG_RT2800PCI_WISOC */ | 93 | #endif /* CONFIG_RT2800PCI_SOC */ |
102 | 94 | ||
103 | #ifdef CONFIG_RT2800PCI_PCI | 95 | #ifdef CONFIG_RT2800PCI_PCI |
104 | static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) | 96 | static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) |
@@ -461,24 +453,6 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
461 | rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); | 453 | rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); |
462 | } | 454 | } |
463 | 455 | ||
464 | static int rt2800pci_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) | ||
465 | { | ||
466 | unsigned int i; | ||
467 | u32 reg; | ||
468 | |||
469 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
470 | rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); | ||
471 | if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) && | ||
472 | !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY)) | ||
473 | return 0; | ||
474 | |||
475 | msleep(1); | ||
476 | } | ||
477 | |||
478 | ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n"); | ||
479 | return -EACCES; | ||
480 | } | ||
481 | |||
482 | static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) | 456 | static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) |
483 | { | 457 | { |
484 | u32 reg; | 458 | u32 reg; |
@@ -487,10 +461,10 @@ static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
487 | /* | 461 | /* |
488 | * Initialize all registers. | 462 | * Initialize all registers. |
489 | */ | 463 | */ |
490 | if (unlikely(rt2800pci_wait_wpdma_ready(rt2x00dev) || | 464 | if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) || |
491 | rt2800pci_init_queues(rt2x00dev) || | 465 | rt2800pci_init_queues(rt2x00dev) || |
492 | rt2800_init_registers(rt2x00dev) || | 466 | rt2800_init_registers(rt2x00dev) || |
493 | rt2800pci_wait_wpdma_ready(rt2x00dev) || | 467 | rt2800_wait_wpdma_ready(rt2x00dev) || |
494 | rt2800_init_bbp(rt2x00dev) || | 468 | rt2800_init_bbp(rt2x00dev) || |
495 | rt2800_init_rfcsr(rt2x00dev))) | 469 | rt2800_init_rfcsr(rt2x00dev))) |
496 | return -EIO; | 470 | return -EIO; |
@@ -570,7 +544,7 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev) | |||
570 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); | 544 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); |
571 | 545 | ||
572 | /* Wait for DMA, ignore error */ | 546 | /* Wait for DMA, ignore error */ |
573 | rt2800pci_wait_wpdma_ready(rt2x00dev); | 547 | rt2800_wait_wpdma_ready(rt2x00dev); |
574 | } | 548 | } |
575 | 549 | ||
576 | static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev, | 550 | static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev, |
@@ -835,7 +809,6 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, | |||
835 | struct rxdone_entry_desc *rxdesc) | 809 | struct rxdone_entry_desc *rxdesc) |
836 | { | 810 | { |
837 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 811 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
838 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
839 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 812 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; |
840 | __le32 *rxd = entry_priv->desc; | 813 | __le32 *rxd = entry_priv->desc; |
841 | __le32 *rxwi = (__le32 *)entry->skb->data; | 814 | __le32 *rxwi = (__le32 *)entry->skb->data; |
@@ -883,10 +856,8 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, | |||
883 | if (rt2x00_get_field32(rxd3, RXD_W3_MY_BSS)) | 856 | if (rt2x00_get_field32(rxd3, RXD_W3_MY_BSS)) |
884 | rxdesc->dev_flags |= RXDONE_MY_BSS; | 857 | rxdesc->dev_flags |= RXDONE_MY_BSS; |
885 | 858 | ||
886 | if (rt2x00_get_field32(rxd3, RXD_W3_L2PAD)) { | 859 | if (rt2x00_get_field32(rxd3, RXD_W3_L2PAD)) |
887 | rxdesc->dev_flags |= RXDONE_L2PAD; | 860 | rxdesc->dev_flags |= RXDONE_L2PAD; |
888 | skbdesc->flags |= SKBDESC_L2_PADDED; | ||
889 | } | ||
890 | 861 | ||
891 | if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) | 862 | if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) |
892 | rxdesc->flags |= RX_FLAG_SHORT_GI; | 863 | rxdesc->flags |= RX_FLAG_SHORT_GI; |
@@ -927,7 +898,6 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, | |||
927 | * Remove TXWI descriptor from start of buffer. | 898 | * Remove TXWI descriptor from start of buffer. |
928 | */ | 899 | */ |
929 | skb_pull(entry->skb, RXWI_DESC_SIZE); | 900 | skb_pull(entry->skb, RXWI_DESC_SIZE); |
930 | skb_trim(entry->skb, rxdesc->size); | ||
931 | } | 901 | } |
932 | 902 | ||
933 | /* | 903 | /* |
@@ -1071,18 +1041,12 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1071 | /* | 1041 | /* |
1072 | * Read EEPROM into buffer | 1042 | * Read EEPROM into buffer |
1073 | */ | 1043 | */ |
1074 | switch (rt2x00dev->chip.rt) { | 1044 | if (rt2x00_is_soc(rt2x00dev)) |
1075 | case RT2880: | ||
1076 | case RT3052: | ||
1077 | rt2800pci_read_eeprom_soc(rt2x00dev); | 1045 | rt2800pci_read_eeprom_soc(rt2x00dev); |
1078 | break; | 1046 | else if (rt2800pci_efuse_detect(rt2x00dev)) |
1079 | default: | 1047 | rt2800pci_read_eeprom_efuse(rt2x00dev); |
1080 | if (rt2800pci_efuse_detect(rt2x00dev)) | 1048 | else |
1081 | rt2800pci_read_eeprom_efuse(rt2x00dev); | 1049 | rt2800pci_read_eeprom_pci(rt2x00dev); |
1082 | else | ||
1083 | rt2800pci_read_eeprom_pci(rt2x00dev); | ||
1084 | break; | ||
1085 | } | ||
1086 | 1050 | ||
1087 | return rt2800_validate_eeprom(rt2x00dev); | 1051 | return rt2800_validate_eeprom(rt2x00dev); |
1088 | } | 1052 | } |
@@ -1133,8 +1097,7 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
1133 | /* | 1097 | /* |
1134 | * This device requires firmware. | 1098 | * This device requires firmware. |
1135 | */ | 1099 | */ |
1136 | if (!rt2x00_rt(&rt2x00dev->chip, RT2880) && | 1100 | if (!rt2x00_is_soc(rt2x00dev)) |
1137 | !rt2x00_rt(&rt2x00dev->chip, RT3052)) | ||
1138 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); | 1101 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); |
1139 | __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); | 1102 | __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); |
1140 | __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); | 1103 | __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); |
@@ -1222,7 +1185,10 @@ static const struct rt2x00_ops rt2800pci_ops = { | |||
1222 | * RT2800pci module information. | 1185 | * RT2800pci module information. |
1223 | */ | 1186 | */ |
1224 | static struct pci_device_id rt2800pci_device_table[] = { | 1187 | static struct pci_device_id rt2800pci_device_table[] = { |
1225 | { PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1188 | { PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1189 | { PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
1190 | { PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
1191 | { PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
1226 | { PCI_DEVICE(0x1432, 0x7708), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1192 | { PCI_DEVICE(0x1432, 0x7708), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1227 | { PCI_DEVICE(0x1432, 0x7727), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1193 | { PCI_DEVICE(0x1432, 0x7727), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1228 | { PCI_DEVICE(0x1432, 0x7728), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1194 | { PCI_DEVICE(0x1432, 0x7728), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
@@ -1230,18 +1196,19 @@ static struct pci_device_id rt2800pci_device_table[] = { | |||
1230 | { PCI_DEVICE(0x1432, 0x7748), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1196 | { PCI_DEVICE(0x1432, 0x7748), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1231 | { PCI_DEVICE(0x1432, 0x7758), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1197 | { PCI_DEVICE(0x1432, 0x7758), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1232 | { PCI_DEVICE(0x1432, 0x7768), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1198 | { PCI_DEVICE(0x1432, 0x7768), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1233 | { PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1199 | { PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1234 | { PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1200 | #ifdef CONFIG_RT2800PCI_RT30XX |
1235 | { PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
1236 | { PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
1237 | { PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
1238 | { PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
1239 | { PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1201 | { PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1240 | { PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1202 | { PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1241 | { PCI_DEVICE(0x1814, 0x3092), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1203 | { PCI_DEVICE(0x1814, 0x3092), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1204 | { PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
1205 | #endif | ||
1206 | #ifdef CONFIG_RT2800PCI_RT35XX | ||
1207 | { PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
1208 | { PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
1242 | { PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1209 | { PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1243 | { PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1210 | { PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1244 | { PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1211 | #endif |
1245 | { 0, } | 1212 | { 0, } |
1246 | }; | 1213 | }; |
1247 | 1214 | ||
@@ -1255,12 +1222,11 @@ MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); | |||
1255 | #endif /* CONFIG_RT2800PCI_PCI */ | 1222 | #endif /* CONFIG_RT2800PCI_PCI */ |
1256 | MODULE_LICENSE("GPL"); | 1223 | MODULE_LICENSE("GPL"); |
1257 | 1224 | ||
1258 | #ifdef CONFIG_RT2800PCI_WISOC | 1225 | #ifdef CONFIG_RT2800PCI_SOC |
1259 | #if defined(CONFIG_RALINK_RT288X) | 1226 | static int rt2800soc_probe(struct platform_device *pdev) |
1260 | __rt2x00soc_probe(RT2880, &rt2800pci_ops); | 1227 | { |
1261 | #elif defined(CONFIG_RALINK_RT305X) | 1228 | return rt2x00soc_probe(pdev, rt2800pci_ops); |
1262 | __rt2x00soc_probe(RT3052, &rt2800pci_ops); | 1229 | } |
1263 | #endif | ||
1264 | 1230 | ||
1265 | static struct platform_driver rt2800soc_driver = { | 1231 | static struct platform_driver rt2800soc_driver = { |
1266 | .driver = { | 1232 | .driver = { |
@@ -1268,12 +1234,12 @@ static struct platform_driver rt2800soc_driver = { | |||
1268 | .owner = THIS_MODULE, | 1234 | .owner = THIS_MODULE, |
1269 | .mod_name = KBUILD_MODNAME, | 1235 | .mod_name = KBUILD_MODNAME, |
1270 | }, | 1236 | }, |
1271 | .probe = __rt2x00soc_probe, | 1237 | .probe = rt2800soc_probe, |
1272 | .remove = __devexit_p(rt2x00soc_remove), | 1238 | .remove = __devexit_p(rt2x00soc_remove), |
1273 | .suspend = rt2x00soc_suspend, | 1239 | .suspend = rt2x00soc_suspend, |
1274 | .resume = rt2x00soc_resume, | 1240 | .resume = rt2x00soc_resume, |
1275 | }; | 1241 | }; |
1276 | #endif /* CONFIG_RT2800PCI_WISOC */ | 1242 | #endif /* CONFIG_RT2800PCI_SOC */ |
1277 | 1243 | ||
1278 | #ifdef CONFIG_RT2800PCI_PCI | 1244 | #ifdef CONFIG_RT2800PCI_PCI |
1279 | static struct pci_driver rt2800pci_driver = { | 1245 | static struct pci_driver rt2800pci_driver = { |
@@ -1290,7 +1256,7 @@ static int __init rt2800pci_init(void) | |||
1290 | { | 1256 | { |
1291 | int ret = 0; | 1257 | int ret = 0; |
1292 | 1258 | ||
1293 | #ifdef CONFIG_RT2800PCI_WISOC | 1259 | #ifdef CONFIG_RT2800PCI_SOC |
1294 | ret = platform_driver_register(&rt2800soc_driver); | 1260 | ret = platform_driver_register(&rt2800soc_driver); |
1295 | if (ret) | 1261 | if (ret) |
1296 | return ret; | 1262 | return ret; |
@@ -1298,7 +1264,7 @@ static int __init rt2800pci_init(void) | |||
1298 | #ifdef CONFIG_RT2800PCI_PCI | 1264 | #ifdef CONFIG_RT2800PCI_PCI |
1299 | ret = pci_register_driver(&rt2800pci_driver); | 1265 | ret = pci_register_driver(&rt2800pci_driver); |
1300 | if (ret) { | 1266 | if (ret) { |
1301 | #ifdef CONFIG_RT2800PCI_WISOC | 1267 | #ifdef CONFIG_RT2800PCI_SOC |
1302 | platform_driver_unregister(&rt2800soc_driver); | 1268 | platform_driver_unregister(&rt2800soc_driver); |
1303 | #endif | 1269 | #endif |
1304 | return ret; | 1270 | return ret; |
@@ -1313,7 +1279,7 @@ static void __exit rt2800pci_exit(void) | |||
1313 | #ifdef CONFIG_RT2800PCI_PCI | 1279 | #ifdef CONFIG_RT2800PCI_PCI |
1314 | pci_unregister_driver(&rt2800pci_driver); | 1280 | pci_unregister_driver(&rt2800pci_driver); |
1315 | #endif | 1281 | #endif |
1316 | #ifdef CONFIG_RT2800PCI_WISOC | 1282 | #ifdef CONFIG_RT2800PCI_SOC |
1317 | platform_driver_unregister(&rt2800soc_driver); | 1283 | platform_driver_unregister(&rt2800soc_driver); |
1318 | #endif | 1284 | #endif |
1319 | } | 1285 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index ab95346cf6a3..5e4ee2023fcf 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -92,7 +92,6 @@ static bool rt2800usb_check_crc(const u8 *data, const size_t len) | |||
92 | static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev, | 92 | static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev, |
93 | const u8 *data, const size_t len) | 93 | const u8 *data, const size_t len) |
94 | { | 94 | { |
95 | u16 chipset = (rt2x00_rev(&rt2x00dev->chip) >> 16) & 0xffff; | ||
96 | size_t offset = 0; | 95 | size_t offset = 0; |
97 | 96 | ||
98 | /* | 97 | /* |
@@ -111,9 +110,9 @@ static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev, | |||
111 | * Check if we need the upper 4kb firmware data or not. | 110 | * Check if we need the upper 4kb firmware data or not. |
112 | */ | 111 | */ |
113 | if ((len == 4096) && | 112 | if ((len == 4096) && |
114 | (chipset != 0x2860) && | 113 | !rt2x00_rt(rt2x00dev, RT2860) && |
115 | (chipset != 0x2872) && | 114 | !rt2x00_rt(rt2x00dev, RT2872) && |
116 | (chipset != 0x3070)) | 115 | !rt2x00_rt(rt2x00dev, RT3070)) |
117 | return FW_BAD_VERSION; | 116 | return FW_BAD_VERSION; |
118 | 117 | ||
119 | /* | 118 | /* |
@@ -138,14 +137,13 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
138 | u32 reg; | 137 | u32 reg; |
139 | u32 offset; | 138 | u32 offset; |
140 | u32 length; | 139 | u32 length; |
141 | u16 chipset = (rt2x00_rev(&rt2x00dev->chip) >> 16) & 0xffff; | ||
142 | 140 | ||
143 | /* | 141 | /* |
144 | * Check which section of the firmware we need. | 142 | * Check which section of the firmware we need. |
145 | */ | 143 | */ |
146 | if ((chipset == 0x2860) || | 144 | if (rt2x00_rt(rt2x00dev, RT2860) || |
147 | (chipset == 0x2872) || | 145 | rt2x00_rt(rt2x00dev, RT2872) || |
148 | (chipset == 0x3070)) { | 146 | rt2x00_rt(rt2x00dev, RT3070)) { |
149 | offset = 0; | 147 | offset = 0; |
150 | length = 4096; | 148 | length = 4096; |
151 | } else { | 149 | } else { |
@@ -200,9 +198,9 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
200 | */ | 198 | */ |
201 | rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); | 199 | rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); |
202 | 200 | ||
203 | if ((chipset == 0x3070) || | 201 | if (rt2x00_rt(rt2x00dev, RT3070) || |
204 | (chipset == 0x3071) || | 202 | rt2x00_rt(rt2x00dev, RT3071) || |
205 | (chipset == 0x3572)) { | 203 | rt2x00_rt(rt2x00dev, RT3572)) { |
206 | udelay(200); | 204 | udelay(200); |
207 | rt2800_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0); | 205 | rt2800_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0); |
208 | udelay(10); | 206 | udelay(10); |
@@ -248,24 +246,6 @@ static void rt2800usb_toggle_rx(struct rt2x00_dev *rt2x00dev, | |||
248 | rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | 246 | rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); |
249 | } | 247 | } |
250 | 248 | ||
251 | static int rt2800usb_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) | ||
252 | { | ||
253 | unsigned int i; | ||
254 | u32 reg; | ||
255 | |||
256 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
257 | rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); | ||
258 | if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) && | ||
259 | !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY)) | ||
260 | return 0; | ||
261 | |||
262 | msleep(1); | ||
263 | } | ||
264 | |||
265 | ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n"); | ||
266 | return -EACCES; | ||
267 | } | ||
268 | |||
269 | static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) | 249 | static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) |
270 | { | 250 | { |
271 | u32 reg; | 251 | u32 reg; |
@@ -274,7 +254,7 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
274 | /* | 254 | /* |
275 | * Initialize all registers. | 255 | * Initialize all registers. |
276 | */ | 256 | */ |
277 | if (unlikely(rt2800usb_wait_wpdma_ready(rt2x00dev) || | 257 | if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) || |
278 | rt2800_init_registers(rt2x00dev) || | 258 | rt2800_init_registers(rt2x00dev) || |
279 | rt2800_init_bbp(rt2x00dev) || | 259 | rt2800_init_bbp(rt2x00dev) || |
280 | rt2800_init_rfcsr(rt2x00dev))) | 260 | rt2800_init_rfcsr(rt2x00dev))) |
@@ -295,9 +275,7 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
295 | 275 | ||
296 | rt2800_register_read(rt2x00dev, USB_DMA_CFG, ®); | 276 | rt2800_register_read(rt2x00dev, USB_DMA_CFG, ®); |
297 | rt2x00_set_field32(®, USB_DMA_CFG_PHY_CLEAR, 0); | 277 | rt2x00_set_field32(®, USB_DMA_CFG_PHY_CLEAR, 0); |
298 | /* Don't use bulk in aggregation when working with USB 1.1 */ | 278 | rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN, 0); |
299 | rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN, | ||
300 | (rt2x00dev->rx->usb_maxpacket == 512)); | ||
301 | rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128); | 279 | rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128); |
302 | /* | 280 | /* |
303 | * Total room for RX frames in kilobytes, PBF might still exceed | 281 | * Total room for RX frames in kilobytes, PBF might still exceed |
@@ -346,7 +324,7 @@ static void rt2800usb_disable_radio(struct rt2x00_dev *rt2x00dev) | |||
346 | rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0); | 324 | rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0); |
347 | 325 | ||
348 | /* Wait for DMA, ignore error */ | 326 | /* Wait for DMA, ignore error */ |
349 | rt2800usb_wait_wpdma_ready(rt2x00dev); | 327 | rt2800_wait_wpdma_ready(rt2x00dev); |
350 | 328 | ||
351 | rt2x00usb_disable_radio(rt2x00dev); | 329 | rt2x00usb_disable_radio(rt2x00dev); |
352 | } | 330 | } |
@@ -573,41 +551,57 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, | |||
573 | { | 551 | { |
574 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 552 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
575 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | 553 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); |
576 | __le32 *rxd = (__le32 *)entry->skb->data; | 554 | __le32 *rxi = (__le32 *)entry->skb->data; |
577 | __le32 *rxwi; | 555 | __le32 *rxwi; |
578 | u32 rxd0; | 556 | __le32 *rxd; |
557 | u32 rxi0; | ||
579 | u32 rxwi0; | 558 | u32 rxwi0; |
580 | u32 rxwi1; | 559 | u32 rxwi1; |
581 | u32 rxwi2; | 560 | u32 rxwi2; |
582 | u32 rxwi3; | 561 | u32 rxwi3; |
562 | u32 rxd0; | ||
563 | int rx_pkt_len; | ||
564 | |||
565 | /* | ||
566 | * RX frame format is : | ||
567 | * | RXINFO | RXWI | header | L2 pad | payload | pad | RXD | USB pad | | ||
568 | * |<------------ rx_pkt_len -------------->| | ||
569 | */ | ||
570 | rt2x00_desc_read(rxi, 0, &rxi0); | ||
571 | rx_pkt_len = rt2x00_get_field32(rxi0, RXINFO_W0_USB_DMA_RX_PKT_LEN); | ||
572 | |||
573 | rxwi = (__le32 *)(entry->skb->data + RXINFO_DESC_SIZE); | ||
574 | |||
575 | /* | ||
576 | * FIXME : we need to check for rx_pkt_len validity | ||
577 | */ | ||
578 | rxd = (__le32 *)(entry->skb->data + RXINFO_DESC_SIZE + rx_pkt_len); | ||
583 | 579 | ||
584 | /* | 580 | /* |
585 | * Copy descriptor to the skbdesc->desc buffer, making it safe from | 581 | * Copy descriptor to the skbdesc->desc buffer, making it safe from |
586 | * moving of frame data in rt2x00usb. | 582 | * moving of frame data in rt2x00usb. |
587 | */ | 583 | */ |
588 | memcpy(skbdesc->desc, rxd, skbdesc->desc_len); | 584 | memcpy(skbdesc->desc, rxi, skbdesc->desc_len); |
589 | rxd = (__le32 *)skbdesc->desc; | ||
590 | rxwi = &rxd[RXINFO_DESC_SIZE / sizeof(__le32)]; | ||
591 | 585 | ||
592 | /* | 586 | /* |
593 | * It is now safe to read the descriptor on all architectures. | 587 | * It is now safe to read the descriptor on all architectures. |
594 | */ | 588 | */ |
595 | rt2x00_desc_read(rxd, 0, &rxd0); | ||
596 | rt2x00_desc_read(rxwi, 0, &rxwi0); | 589 | rt2x00_desc_read(rxwi, 0, &rxwi0); |
597 | rt2x00_desc_read(rxwi, 1, &rxwi1); | 590 | rt2x00_desc_read(rxwi, 1, &rxwi1); |
598 | rt2x00_desc_read(rxwi, 2, &rxwi2); | 591 | rt2x00_desc_read(rxwi, 2, &rxwi2); |
599 | rt2x00_desc_read(rxwi, 3, &rxwi3); | 592 | rt2x00_desc_read(rxwi, 3, &rxwi3); |
593 | rt2x00_desc_read(rxd, 0, &rxd0); | ||
600 | 594 | ||
601 | if (rt2x00_get_field32(rxd0, RXINFO_W0_CRC_ERROR)) | 595 | if (rt2x00_get_field32(rxd0, RXD_W0_CRC_ERROR)) |
602 | rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; | 596 | rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; |
603 | 597 | ||
604 | if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { | 598 | if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { |
605 | rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF); | 599 | rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF); |
606 | rxdesc->cipher_status = | 600 | rxdesc->cipher_status = |
607 | rt2x00_get_field32(rxd0, RXINFO_W0_CIPHER_ERROR); | 601 | rt2x00_get_field32(rxd0, RXD_W0_CIPHER_ERROR); |
608 | } | 602 | } |
609 | 603 | ||
610 | if (rt2x00_get_field32(rxd0, RXINFO_W0_DECRYPTED)) { | 604 | if (rt2x00_get_field32(rxd0, RXD_W0_DECRYPTED)) { |
611 | /* | 605 | /* |
612 | * Hardware has stripped IV/EIV data from 802.11 frame during | 606 | * Hardware has stripped IV/EIV data from 802.11 frame during |
613 | * decryption. Unfortunately the descriptor doesn't contain | 607 | * decryption. Unfortunately the descriptor doesn't contain |
@@ -622,13 +616,11 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, | |||
622 | rxdesc->flags |= RX_FLAG_MMIC_ERROR; | 616 | rxdesc->flags |= RX_FLAG_MMIC_ERROR; |
623 | } | 617 | } |
624 | 618 | ||
625 | if (rt2x00_get_field32(rxd0, RXINFO_W0_MY_BSS)) | 619 | if (rt2x00_get_field32(rxd0, RXD_W0_MY_BSS)) |
626 | rxdesc->dev_flags |= RXDONE_MY_BSS; | 620 | rxdesc->dev_flags |= RXDONE_MY_BSS; |
627 | 621 | ||
628 | if (rt2x00_get_field32(rxd0, RXINFO_W0_L2PAD)) { | 622 | if (rt2x00_get_field32(rxd0, RXD_W0_L2PAD)) |
629 | rxdesc->dev_flags |= RXDONE_L2PAD; | 623 | rxdesc->dev_flags |= RXDONE_L2PAD; |
630 | skbdesc->flags |= SKBDESC_L2_PADDED; | ||
631 | } | ||
632 | 624 | ||
633 | if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) | 625 | if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) |
634 | rxdesc->flags |= RX_FLAG_SHORT_GI; | 626 | rxdesc->flags |= RX_FLAG_SHORT_GI; |
@@ -663,7 +655,6 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, | |||
663 | * Remove RXWI descriptor from start of buffer. | 655 | * Remove RXWI descriptor from start of buffer. |
664 | */ | 656 | */ |
665 | skb_pull(entry->skb, skbdesc->desc_len); | 657 | skb_pull(entry->skb, skbdesc->desc_len); |
666 | skb_trim(entry->skb, rxdesc->size); | ||
667 | } | 658 | } |
668 | 659 | ||
669 | /* | 660 | /* |
@@ -814,51 +805,27 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
814 | /* Abocom */ | 805 | /* Abocom */ |
815 | { USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, | 806 | { USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, |
816 | { USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, | 807 | { USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, |
817 | { USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
818 | { USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
819 | { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
820 | { USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, | 808 | { USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, |
821 | /* AirTies */ | ||
822 | { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
823 | /* Amigo */ | ||
824 | { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
825 | { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
826 | /* Amit */ | 809 | /* Amit */ |
827 | { USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, | 810 | { USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, |
828 | /* Askey */ | 811 | /* Askey */ |
829 | { USB_DEVICE(0x1690, 0x0740), USB_DEVICE_DATA(&rt2800usb_ops) }, | 812 | { USB_DEVICE(0x1690, 0x0740), USB_DEVICE_DATA(&rt2800usb_ops) }, |
830 | { USB_DEVICE(0x1690, 0x0744), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
831 | { USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
832 | /* ASUS */ | 813 | /* ASUS */ |
833 | { USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) }, | 814 | { USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) }, |
834 | { USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) }, | 815 | { USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) }, |
835 | { USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) }, | 816 | { USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) }, |
836 | { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
837 | { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
838 | { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
839 | /* AzureWave */ | 817 | /* AzureWave */ |
840 | { USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) }, | 818 | { USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) }, |
841 | { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
842 | { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
843 | { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
844 | { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
845 | /* Belkin */ | 819 | /* Belkin */ |
846 | { USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) }, | 820 | { USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) }, |
847 | { USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) }, | 821 | { USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) }, |
848 | { USB_DEVICE(0x050d, 0x815c), USB_DEVICE_DATA(&rt2800usb_ops) }, | 822 | { USB_DEVICE(0x050d, 0x815c), USB_DEVICE_DATA(&rt2800usb_ops) }, |
849 | { USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
850 | /* Buffalo */ | 823 | /* Buffalo */ |
851 | { USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) }, | 824 | { USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) }, |
852 | { USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
853 | /* Cisco */ | ||
854 | { USB_DEVICE(0x167b, 0x4001), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
855 | /* Conceptronic */ | 825 | /* Conceptronic */ |
856 | { USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) }, | 826 | { USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) }, |
857 | { USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) }, | 827 | { USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) }, |
858 | { USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
859 | { USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, | 828 | { USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, |
860 | { USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
861 | { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
862 | { USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) }, | 829 | { USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) }, |
863 | { USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) }, | 830 | { USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) }, |
864 | { USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) }, | 831 | { USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) }, |
@@ -867,157 +834,257 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
867 | { USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) }, | 834 | { USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) }, |
868 | { USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, | 835 | { USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, |
869 | { USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, | 836 | { USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, |
870 | { USB_DEVICE(0x07aa, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
871 | { USB_DEVICE(0x07aa, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
872 | { USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
873 | { USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
874 | /* D-Link */ | 837 | /* D-Link */ |
875 | { USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, | 838 | { USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, |
839 | { USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
840 | /* Edimax */ | ||
841 | { USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
842 | { USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
843 | /* EnGenius */ | ||
844 | { USB_DEVICE(0X1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
845 | { USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
846 | /* Gigabyte */ | ||
847 | { USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
848 | /* Hawking */ | ||
849 | { USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
850 | { USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
851 | /* Linksys */ | ||
852 | { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
853 | { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
854 | /* Logitec */ | ||
855 | { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
856 | { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
857 | { USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
858 | /* Motorola */ | ||
859 | { USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
860 | /* MSI */ | ||
861 | { USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
862 | /* Philips */ | ||
863 | { USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
864 | /* Planex */ | ||
865 | { USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
866 | /* Ralink */ | ||
867 | { USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
868 | { USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
869 | /* Samsung */ | ||
870 | { USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
871 | /* Siemens */ | ||
872 | { USB_DEVICE(0x129b, 0x1828), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
873 | /* Sitecom */ | ||
874 | { USB_DEVICE(0x0df6, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
875 | { USB_DEVICE(0x0df6, 0x002b), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
876 | { USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
877 | { USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
878 | { USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
879 | { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
880 | /* SMC */ | ||
881 | { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
882 | { USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
883 | { USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
884 | { USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
885 | { USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
886 | { USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
887 | /* Sparklan */ | ||
888 | { USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
889 | /* Sweex */ | ||
890 | { USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
891 | /* U-Media*/ | ||
892 | { USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
893 | /* ZCOM */ | ||
894 | { USB_DEVICE(0x0cde, 0x0022), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
895 | { USB_DEVICE(0x0cde, 0x0025), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
896 | /* Zinwell */ | ||
897 | { USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
898 | { USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
899 | /* Zyxel */ | ||
900 | { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
901 | #ifdef CONFIG_RT2800USB_RT30XX | ||
902 | /* Abocom */ | ||
903 | { USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
904 | { USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
905 | { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
906 | /* AirTies */ | ||
907 | { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
908 | /* AzureWave */ | ||
909 | { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
910 | /* Conceptronic */ | ||
911 | { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
912 | /* Corega */ | ||
913 | { USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
914 | /* D-Link */ | ||
876 | { USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) }, | 915 | { USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) }, |
877 | { USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
878 | { USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) }, | 916 | { USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) }, |
879 | { USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) }, | 917 | { USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) }, |
880 | { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, | 918 | { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, |
881 | { USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
882 | { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
883 | { USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
884 | /* Edimax */ | 919 | /* Edimax */ |
885 | { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, | 920 | { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, |
886 | { USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
887 | { USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
888 | /* Encore */ | 921 | /* Encore */ |
889 | { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, | 922 | { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, |
890 | { USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
891 | { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
892 | /* EnGenius */ | 923 | /* EnGenius */ |
893 | { USB_DEVICE(0X1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
894 | { USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
895 | { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, | 924 | { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, |
896 | { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, | 925 | { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, |
897 | { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, | 926 | { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, |
927 | /* Gigabyte */ | ||
928 | { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
929 | /* I-O DATA */ | ||
930 | { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
931 | /* MSI */ | ||
932 | { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
933 | /* Pegatron */ | ||
934 | { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
935 | { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
936 | /* Planex */ | ||
937 | { USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
938 | /* Quanta */ | ||
939 | { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
940 | /* Ralink */ | ||
941 | { USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
942 | { USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
943 | { USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
944 | { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
945 | /* Sitecom */ | ||
946 | { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
947 | { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
948 | /* SMC */ | ||
949 | { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
950 | /* Zinwell */ | ||
951 | { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
952 | { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
953 | #endif | ||
954 | #ifdef CONFIG_RT2800USB_RT35XX | ||
955 | /* Askey */ | ||
956 | { USB_DEVICE(0x1690, 0x0744), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
957 | /* Cisco */ | ||
958 | { USB_DEVICE(0x167b, 0x4001), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
959 | /* EnGenius */ | ||
960 | { USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
961 | /* I-O DATA */ | ||
962 | { USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
963 | /* Ralink */ | ||
964 | { USB_DEVICE(0x148f, 0x3370), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
965 | { USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
966 | { USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
967 | /* Sitecom */ | ||
968 | { USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
969 | /* Zinwell */ | ||
970 | { USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
971 | #endif | ||
972 | #ifdef CONFIG_RT2800USB_UNKNOWN | ||
973 | /* | ||
974 | * Unclear what kind of devices these are (they aren't supported by the | ||
975 | * vendor driver). | ||
976 | */ | ||
977 | /* Allwin */ | ||
978 | { USB_DEVICE(0x8516, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
979 | { USB_DEVICE(0x8516, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
980 | { USB_DEVICE(0x8516, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
981 | { USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
982 | { USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
983 | { USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
984 | { USB_DEVICE(0x8516, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
985 | /* Amigo */ | ||
986 | { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
987 | { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
988 | /* Askey */ | ||
989 | { USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
990 | /* ASUS */ | ||
991 | { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
992 | { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
993 | { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
994 | { USB_DEVICE(0x0b05, 0x1790), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
995 | { USB_DEVICE(0x1761, 0x0b05), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
996 | /* AzureWave */ | ||
997 | { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
998 | { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
999 | { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1000 | /* Belkin */ | ||
1001 | { USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1002 | /* Buffalo */ | ||
1003 | { USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1004 | { USB_DEVICE(0x0411, 0x0148), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1005 | { USB_DEVICE(0x0411, 0x0150), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1006 | { USB_DEVICE(0x0411, 0x015d), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1007 | /* Conceptronic */ | ||
1008 | { USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1009 | { USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1010 | /* Corega */ | ||
1011 | { USB_DEVICE(0x07aa, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1012 | { USB_DEVICE(0x07aa, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1013 | { USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1014 | /* D-Link */ | ||
1015 | { USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1016 | { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1017 | { USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1018 | { USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1019 | /* Encore */ | ||
1020 | { USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1021 | { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1022 | /* EnGenius */ | ||
898 | { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1023 | { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) }, |
899 | { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1024 | { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) }, |
900 | { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1025 | { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) }, |
901 | { USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
902 | /* Gemtek */ | 1026 | /* Gemtek */ |
903 | { USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1027 | { USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, |
904 | /* Gigabyte */ | 1028 | /* Gigabyte */ |
905 | { USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
906 | { USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1029 | { USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) }, |
907 | { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
908 | /* Hawking */ | 1030 | /* Hawking */ |
909 | { USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
910 | { USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
911 | { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1031 | { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, |
912 | { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1032 | { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) }, |
913 | /* I-O DATA */ | 1033 | /* I-O DATA */ |
914 | { USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
915 | { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
916 | { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1034 | { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) }, |
917 | { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1035 | { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) }, |
918 | /* LevelOne */ | 1036 | /* LevelOne */ |
919 | { USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1037 | { USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) }, |
920 | { USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1038 | { USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) }, |
921 | /* Linksys */ | 1039 | /* Linksys */ |
922 | { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
923 | { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
924 | { USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1040 | { USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1041 | { USB_DEVICE(0x1737, 0x0078), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
925 | { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1042 | { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) }, |
926 | /* Logitec */ | ||
927 | { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
928 | { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
929 | { USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
930 | /* Motorola */ | 1043 | /* Motorola */ |
931 | { USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
932 | { USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1044 | { USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) }, |
933 | /* MSI */ | 1045 | /* MSI */ |
934 | { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
935 | { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1046 | { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1047 | { USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
936 | { USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1048 | { USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) }, |
937 | { USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1049 | { USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) }, |
938 | { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1050 | { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1051 | { USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
939 | { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1052 | { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1053 | { USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
940 | { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1054 | { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) }, |
941 | /* Ovislink */ | 1055 | /* Ovislink */ |
942 | { USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1056 | { USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, |
943 | /* Para */ | 1057 | /* Para */ |
944 | { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1058 | { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, |
945 | /* Pegatron */ | 1059 | /* Pegatron */ |
1060 | { USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
946 | { USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1061 | { USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) }, |
947 | { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1062 | { USB_DEVICE(0x1d4d, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, |
948 | { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
949 | /* Philips */ | ||
950 | { USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
951 | /* Planex */ | 1063 | /* Planex */ |
952 | { USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
953 | { USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1064 | { USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) }, |
954 | { USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
955 | /* Qcom */ | 1065 | /* Qcom */ |
956 | { USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1066 | { USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) }, |
957 | /* Quanta */ | ||
958 | { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
959 | /* Ralink */ | ||
960 | { USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
961 | { USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
962 | { USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
963 | { USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
964 | { USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
965 | { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
966 | { USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
967 | /* Samsung */ | ||
968 | { USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
969 | /* Siemens */ | ||
970 | { USB_DEVICE(0x129b, 0x1828), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
971 | /* Sitecom */ | 1067 | /* Sitecom */ |
972 | { USB_DEVICE(0x0df6, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
973 | { USB_DEVICE(0x0df6, 0x002b), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
974 | { USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
975 | { USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
976 | { USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
977 | { USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1068 | { USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) }, |
978 | { USB_DEVICE(0x0df6, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1069 | { USB_DEVICE(0x0df6, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, |
979 | { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1070 | { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) }, |
980 | { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
981 | { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
982 | { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1071 | { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, |
983 | { USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
984 | { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
985 | { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1072 | { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) }, |
986 | { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1073 | { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) }, |
987 | { USB_DEVICE(0x0df6, 0x004a), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1074 | { USB_DEVICE(0x0df6, 0x004a), USB_DEVICE_DATA(&rt2800usb_ops) }, |
988 | { USB_DEVICE(0x0df6, 0x004d), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1075 | { USB_DEVICE(0x0df6, 0x004d), USB_DEVICE_DATA(&rt2800usb_ops) }, |
989 | /* SMC */ | 1076 | /* SMC */ |
990 | { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
991 | { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
992 | { USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
993 | { USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
994 | { USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
995 | { USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1077 | { USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) }, |
996 | { USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
997 | { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1078 | { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) }, |
998 | { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1079 | { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) }, |
999 | { USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1000 | { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1080 | { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1001 | /* Sparklan */ | 1081 | { USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1002 | { USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1003 | /* Sweex */ | 1082 | /* Sweex */ |
1004 | { USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1083 | { USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1005 | { USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1006 | { USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1084 | { USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1007 | /* U-Media*/ | ||
1008 | { USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1009 | /* ZCOM */ | ||
1010 | { USB_DEVICE(0x0cde, 0x0022), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1011 | { USB_DEVICE(0x0cde, 0x0025), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1012 | /* Zinwell */ | ||
1013 | { USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1014 | { USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1015 | { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1016 | { USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1017 | { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1018 | /* Zyxel */ | 1085 | /* Zyxel */ |
1019 | { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1020 | { USB_DEVICE(0x0586, 0x341a), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1086 | { USB_DEVICE(0x0586, 0x341a), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1087 | #endif | ||
1021 | { 0, } | 1088 | { 0, } |
1022 | }; | 1089 | }; |
1023 | 1090 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h index 1e4340a182ef..d1d8ae94b4d4 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.h +++ b/drivers/net/wireless/rt2x00/rt2800usb.h | |||
@@ -79,6 +79,8 @@ | |||
79 | */ | 79 | */ |
80 | #define TXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) | 80 | #define TXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) |
81 | #define RXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) | 81 | #define RXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) |
82 | #define RXWI_DESC_SIZE ( 4 * sizeof(__le32) ) | ||
83 | #define RXD_DESC_SIZE ( 1 * sizeof(__le32) ) | ||
82 | 84 | ||
83 | /* | 85 | /* |
84 | * TX Info structure | 86 | * TX Info structure |
@@ -101,6 +103,54 @@ | |||
101 | #define TXINFO_W0_USB_DMA_TX_BURST FIELD32(0x80000000) | 103 | #define TXINFO_W0_USB_DMA_TX_BURST FIELD32(0x80000000) |
102 | 104 | ||
103 | /* | 105 | /* |
106 | * RX Info structure | ||
107 | */ | ||
108 | |||
109 | /* | ||
110 | * Word 0 | ||
111 | */ | ||
112 | |||
113 | #define RXINFO_W0_USB_DMA_RX_PKT_LEN FIELD32(0x0000ffff) | ||
114 | |||
115 | /* | ||
116 | * RX WI structure | ||
117 | */ | ||
118 | |||
119 | /* | ||
120 | * Word0 | ||
121 | */ | ||
122 | #define RXWI_W0_WIRELESS_CLI_ID FIELD32(0x000000ff) | ||
123 | #define RXWI_W0_KEY_INDEX FIELD32(0x00000300) | ||
124 | #define RXWI_W0_BSSID FIELD32(0x00001c00) | ||
125 | #define RXWI_W0_UDF FIELD32(0x0000e000) | ||
126 | #define RXWI_W0_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) | ||
127 | #define RXWI_W0_TID FIELD32(0xf0000000) | ||
128 | |||
129 | /* | ||
130 | * Word1 | ||
131 | */ | ||
132 | #define RXWI_W1_FRAG FIELD32(0x0000000f) | ||
133 | #define RXWI_W1_SEQUENCE FIELD32(0x0000fff0) | ||
134 | #define RXWI_W1_MCS FIELD32(0x007f0000) | ||
135 | #define RXWI_W1_BW FIELD32(0x00800000) | ||
136 | #define RXWI_W1_SHORT_GI FIELD32(0x01000000) | ||
137 | #define RXWI_W1_STBC FIELD32(0x06000000) | ||
138 | #define RXWI_W1_PHYMODE FIELD32(0xc0000000) | ||
139 | |||
140 | /* | ||
141 | * Word2 | ||
142 | */ | ||
143 | #define RXWI_W2_RSSI0 FIELD32(0x000000ff) | ||
144 | #define RXWI_W2_RSSI1 FIELD32(0x0000ff00) | ||
145 | #define RXWI_W2_RSSI2 FIELD32(0x00ff0000) | ||
146 | |||
147 | /* | ||
148 | * Word3 | ||
149 | */ | ||
150 | #define RXWI_W3_SNR0 FIELD32(0x000000ff) | ||
151 | #define RXWI_W3_SNR1 FIELD32(0x0000ff00) | ||
152 | |||
153 | /* | ||
104 | * RX descriptor format for RX Ring. | 154 | * RX descriptor format for RX Ring. |
105 | */ | 155 | */ |
106 | 156 | ||
@@ -115,25 +165,25 @@ | |||
115 | * AMSDU: rx with 802.3 header, not 802.11 header. | 165 | * AMSDU: rx with 802.3 header, not 802.11 header. |
116 | */ | 166 | */ |
117 | 167 | ||
118 | #define RXINFO_W0_BA FIELD32(0x00000001) | 168 | #define RXD_W0_BA FIELD32(0x00000001) |
119 | #define RXINFO_W0_DATA FIELD32(0x00000002) | 169 | #define RXD_W0_DATA FIELD32(0x00000002) |
120 | #define RXINFO_W0_NULLDATA FIELD32(0x00000004) | 170 | #define RXD_W0_NULLDATA FIELD32(0x00000004) |
121 | #define RXINFO_W0_FRAG FIELD32(0x00000008) | 171 | #define RXD_W0_FRAG FIELD32(0x00000008) |
122 | #define RXINFO_W0_UNICAST_TO_ME FIELD32(0x00000010) | 172 | #define RXD_W0_UNICAST_TO_ME FIELD32(0x00000010) |
123 | #define RXINFO_W0_MULTICAST FIELD32(0x00000020) | 173 | #define RXD_W0_MULTICAST FIELD32(0x00000020) |
124 | #define RXINFO_W0_BROADCAST FIELD32(0x00000040) | 174 | #define RXD_W0_BROADCAST FIELD32(0x00000040) |
125 | #define RXINFO_W0_MY_BSS FIELD32(0x00000080) | 175 | #define RXD_W0_MY_BSS FIELD32(0x00000080) |
126 | #define RXINFO_W0_CRC_ERROR FIELD32(0x00000100) | 176 | #define RXD_W0_CRC_ERROR FIELD32(0x00000100) |
127 | #define RXINFO_W0_CIPHER_ERROR FIELD32(0x00000600) | 177 | #define RXD_W0_CIPHER_ERROR FIELD32(0x00000600) |
128 | #define RXINFO_W0_AMSDU FIELD32(0x00000800) | 178 | #define RXD_W0_AMSDU FIELD32(0x00000800) |
129 | #define RXINFO_W0_HTC FIELD32(0x00001000) | 179 | #define RXD_W0_HTC FIELD32(0x00001000) |
130 | #define RXINFO_W0_RSSI FIELD32(0x00002000) | 180 | #define RXD_W0_RSSI FIELD32(0x00002000) |
131 | #define RXINFO_W0_L2PAD FIELD32(0x00004000) | 181 | #define RXD_W0_L2PAD FIELD32(0x00004000) |
132 | #define RXINFO_W0_AMPDU FIELD32(0x00008000) | 182 | #define RXD_W0_AMPDU FIELD32(0x00008000) |
133 | #define RXINFO_W0_DECRYPTED FIELD32(0x00010000) | 183 | #define RXD_W0_DECRYPTED FIELD32(0x00010000) |
134 | #define RXINFO_W0_PLCP_RSSI FIELD32(0x00020000) | 184 | #define RXD_W0_PLCP_RSSI FIELD32(0x00020000) |
135 | #define RXINFO_W0_CIPHER_ALG FIELD32(0x00040000) | 185 | #define RXD_W0_CIPHER_ALG FIELD32(0x00040000) |
136 | #define RXINFO_W0_LAST_AMSDU FIELD32(0x00080000) | 186 | #define RXD_W0_LAST_AMSDU FIELD32(0x00080000) |
137 | #define RXINFO_W0_PLCP_SIGNAL FIELD32(0xfff00000) | 187 | #define RXD_W0_PLCP_SIGNAL FIELD32(0xfff00000) |
138 | 188 | ||
139 | #endif /* RT2800USB_H */ | 189 | #endif /* RT2800USB_H */ |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index dcfc8c25d1a7..d9daa9c406fa 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -104,6 +104,12 @@ | |||
104 | #define GET_DURATION_RES(__size, __rate)(((__size) * 8 * 10) % (__rate)) | 104 | #define GET_DURATION_RES(__size, __rate)(((__size) * 8 * 10) % (__rate)) |
105 | 105 | ||
106 | /* | 106 | /* |
107 | * Determine the number of L2 padding bytes required between the header and | ||
108 | * the payload. | ||
109 | */ | ||
110 | #define L2PAD_SIZE(__hdrlen) (-(__hdrlen) & 3) | ||
111 | |||
112 | /* | ||
107 | * Determine the alignment requirement, | 113 | * Determine the alignment requirement, |
108 | * to make sure the 802.11 payload is padded to a 4-byte boundrary | 114 | * to make sure the 802.11 payload is padded to a 4-byte boundrary |
109 | * we must determine the address of the payload and calculate the | 115 | * we must determine the address of the payload and calculate the |
@@ -154,6 +160,7 @@ struct avg_val { | |||
154 | enum rt2x00_chip_intf { | 160 | enum rt2x00_chip_intf { |
155 | RT2X00_CHIP_INTF_PCI, | 161 | RT2X00_CHIP_INTF_PCI, |
156 | RT2X00_CHIP_INTF_USB, | 162 | RT2X00_CHIP_INTF_USB, |
163 | RT2X00_CHIP_INTF_SOC, | ||
157 | }; | 164 | }; |
158 | 165 | ||
159 | /* | 166 | /* |
@@ -163,25 +170,26 @@ enum rt2x00_chip_intf { | |||
163 | */ | 170 | */ |
164 | struct rt2x00_chip { | 171 | struct rt2x00_chip { |
165 | u16 rt; | 172 | u16 rt; |
166 | #define RT2460 0x0101 | 173 | #define RT2460 0x2460 |
167 | #define RT2560 0x0201 | 174 | #define RT2560 0x2560 |
168 | #define RT2570 0x1201 | 175 | #define RT2570 0x2570 |
169 | #define RT2561s 0x0301 /* Turbo */ | 176 | #define RT2661 0x2661 |
170 | #define RT2561 0x0302 | 177 | #define RT2573 0x2573 |
171 | #define RT2661 0x0401 | 178 | #define RT2860 0x2860 /* 2.4GHz PCI/CB */ |
172 | #define RT2571 0x1300 | 179 | #define RT2870 0x2870 |
173 | #define RT2860 0x0601 /* 2.4GHz PCI/CB */ | 180 | #define RT2872 0x2872 |
174 | #define RT2860D 0x0681 /* 2.4GHz, 5GHz PCI/CB */ | ||
175 | #define RT2890 0x0701 /* 2.4GHz PCIe */ | ||
176 | #define RT2890D 0x0781 /* 2.4GHz, 5GHz PCIe */ | ||
177 | #define RT2880 0x2880 /* WSOC */ | 181 | #define RT2880 0x2880 /* WSOC */ |
182 | #define RT2883 0x2883 /* WSOC */ | ||
183 | #define RT2890 0x2890 /* 2.4GHz PCIe */ | ||
178 | #define RT3052 0x3052 /* WSOC */ | 184 | #define RT3052 0x3052 /* WSOC */ |
185 | #define RT3070 0x3070 | ||
186 | #define RT3071 0x3071 | ||
179 | #define RT3090 0x3090 /* 2.4GHz PCIe */ | 187 | #define RT3090 0x3090 /* 2.4GHz PCIe */ |
180 | #define RT2870 0x1600 | 188 | #define RT3390 0x3390 |
181 | #define RT3070 0x1800 | 189 | #define RT3572 0x3572 |
182 | 190 | ||
183 | u16 rf; | 191 | u16 rf; |
184 | u32 rev; | 192 | u16 rev; |
185 | 193 | ||
186 | enum rt2x00_chip_intf intf; | 194 | enum rt2x00_chip_intf intf; |
187 | }; | 195 | }; |
@@ -911,51 +919,30 @@ static inline void rt2x00_eeprom_write(struct rt2x00_dev *rt2x00dev, | |||
911 | * Chipset handlers | 919 | * Chipset handlers |
912 | */ | 920 | */ |
913 | static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev, | 921 | static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev, |
914 | const u16 rt, const u16 rf, const u32 rev) | 922 | const u16 rt, const u16 rf, const u16 rev) |
915 | { | 923 | { |
916 | rt2x00dev->chip.rt = rt; | 924 | rt2x00dev->chip.rt = rt; |
917 | rt2x00dev->chip.rf = rf; | 925 | rt2x00dev->chip.rf = rf; |
918 | rt2x00dev->chip.rev = rev; | 926 | rt2x00dev->chip.rev = rev; |
919 | } | ||
920 | |||
921 | static inline void rt2x00_set_chip_rt(struct rt2x00_dev *rt2x00dev, | ||
922 | const u16 rt) | ||
923 | { | ||
924 | rt2x00dev->chip.rt = rt; | ||
925 | } | ||
926 | |||
927 | static inline void rt2x00_set_chip_rf(struct rt2x00_dev *rt2x00dev, | ||
928 | const u16 rf, const u32 rev) | ||
929 | { | ||
930 | rt2x00_set_chip(rt2x00dev, rt2x00dev->chip.rt, rf, rev); | ||
931 | } | ||
932 | 927 | ||
933 | static inline void rt2x00_print_chip(struct rt2x00_dev *rt2x00dev) | ||
934 | { | ||
935 | INFO(rt2x00dev, | 928 | INFO(rt2x00dev, |
936 | "Chipset detected - rt: %04x, rf: %04x, rev: %08x.\n", | 929 | "Chipset detected - rt: %04x, rf: %04x, rev: %04x.\n", |
937 | rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev); | 930 | rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev); |
938 | } | 931 | } |
939 | 932 | ||
940 | static inline char rt2x00_rt(const struct rt2x00_chip *chipset, const u16 chip) | 933 | static inline char rt2x00_rt(struct rt2x00_dev *rt2x00dev, const u16 rt) |
941 | { | 934 | { |
942 | return (chipset->rt == chip); | 935 | return (rt2x00dev->chip.rt == rt); |
943 | } | 936 | } |
944 | 937 | ||
945 | static inline char rt2x00_rf(const struct rt2x00_chip *chipset, const u16 chip) | 938 | static inline char rt2x00_rf(struct rt2x00_dev *rt2x00dev, const u16 rf) |
946 | { | 939 | { |
947 | return (chipset->rf == chip); | 940 | return (rt2x00dev->chip.rf == rf); |
948 | } | 941 | } |
949 | 942 | ||
950 | static inline u32 rt2x00_rev(const struct rt2x00_chip *chipset) | 943 | static inline u16 rt2x00_rev(struct rt2x00_dev *rt2x00dev) |
951 | { | 944 | { |
952 | return chipset->rev; | 945 | return rt2x00dev->chip.rev; |
953 | } | ||
954 | |||
955 | static inline bool rt2x00_check_rev(const struct rt2x00_chip *chipset, | ||
956 | const u32 mask, const u32 rev) | ||
957 | { | ||
958 | return ((chipset->rev & mask) == rev); | ||
959 | } | 946 | } |
960 | 947 | ||
961 | static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev, | 948 | static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev, |
@@ -964,20 +951,25 @@ static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev, | |||
964 | rt2x00dev->chip.intf = intf; | 951 | rt2x00dev->chip.intf = intf; |
965 | } | 952 | } |
966 | 953 | ||
967 | static inline bool rt2x00_intf(const struct rt2x00_chip *chipset, | 954 | static inline bool rt2x00_intf(struct rt2x00_dev *rt2x00dev, |
968 | enum rt2x00_chip_intf intf) | 955 | enum rt2x00_chip_intf intf) |
969 | { | 956 | { |
970 | return (chipset->intf == intf); | 957 | return (rt2x00dev->chip.intf == intf); |
958 | } | ||
959 | |||
960 | static inline bool rt2x00_is_pci(struct rt2x00_dev *rt2x00dev) | ||
961 | { | ||
962 | return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); | ||
971 | } | 963 | } |
972 | 964 | ||
973 | static inline bool rt2x00_intf_is_pci(struct rt2x00_dev *rt2x00dev) | 965 | static inline bool rt2x00_is_usb(struct rt2x00_dev *rt2x00dev) |
974 | { | 966 | { |
975 | return rt2x00_intf(&rt2x00dev->chip, RT2X00_CHIP_INTF_PCI); | 967 | return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_USB); |
976 | } | 968 | } |
977 | 969 | ||
978 | static inline bool rt2x00_intf_is_usb(struct rt2x00_dev *rt2x00dev) | 970 | static inline bool rt2x00_is_soc(struct rt2x00_dev *rt2x00dev) |
979 | { | 971 | { |
980 | return rt2x00_intf(&rt2x00dev->chip, RT2X00_CHIP_INTF_USB); | 972 | return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC); |
981 | } | 973 | } |
982 | 974 | ||
983 | /** | 975 | /** |
@@ -1019,9 +1011,9 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb); | |||
1019 | int rt2x00mac_start(struct ieee80211_hw *hw); | 1011 | int rt2x00mac_start(struct ieee80211_hw *hw); |
1020 | void rt2x00mac_stop(struct ieee80211_hw *hw); | 1012 | void rt2x00mac_stop(struct ieee80211_hw *hw); |
1021 | int rt2x00mac_add_interface(struct ieee80211_hw *hw, | 1013 | int rt2x00mac_add_interface(struct ieee80211_hw *hw, |
1022 | struct ieee80211_if_init_conf *conf); | 1014 | struct ieee80211_vif *vif); |
1023 | void rt2x00mac_remove_interface(struct ieee80211_hw *hw, | 1015 | void rt2x00mac_remove_interface(struct ieee80211_hw *hw, |
1024 | struct ieee80211_if_init_conf *conf); | 1016 | struct ieee80211_vif *vif); |
1025 | int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed); | 1017 | int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed); |
1026 | void rt2x00mac_configure_filter(struct ieee80211_hw *hw, | 1018 | void rt2x00mac_configure_filter(struct ieee80211_hw *hw, |
1027 | unsigned int changed_flags, | 1019 | unsigned int changed_flags, |
@@ -1038,8 +1030,6 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1038 | #endif /* CONFIG_RT2X00_LIB_CRYPTO */ | 1030 | #endif /* CONFIG_RT2X00_LIB_CRYPTO */ |
1039 | int rt2x00mac_get_stats(struct ieee80211_hw *hw, | 1031 | int rt2x00mac_get_stats(struct ieee80211_hw *hw, |
1040 | struct ieee80211_low_level_stats *stats); | 1032 | struct ieee80211_low_level_stats *stats); |
1041 | int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw, | ||
1042 | struct ieee80211_tx_queue_stats *stats); | ||
1043 | void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, | 1033 | void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, |
1044 | struct ieee80211_vif *vif, | 1034 | struct ieee80211_vif *vif, |
1045 | struct ieee80211_bss_conf *bss_conf, | 1035 | struct ieee80211_bss_conf *bss_conf, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index 7d323a763b54..70c04c282efc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c | |||
@@ -184,7 +184,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, | |||
184 | dump_hdr->data_length = cpu_to_le32(skb->len); | 184 | dump_hdr->data_length = cpu_to_le32(skb->len); |
185 | dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt); | 185 | dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt); |
186 | dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf); | 186 | dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf); |
187 | dump_hdr->chip_rev = cpu_to_le32(rt2x00dev->chip.rev); | 187 | dump_hdr->chip_rev = cpu_to_le16(rt2x00dev->chip.rev); |
188 | dump_hdr->type = cpu_to_le16(type); | 188 | dump_hdr->type = cpu_to_le16(type); |
189 | dump_hdr->queue_index = desc->entry->queue->qid; | 189 | dump_hdr->queue_index = desc->entry->queue->qid; |
190 | dump_hdr->entry_index = desc->entry->entry_idx; | 190 | dump_hdr->entry_index = desc->entry->entry_idx; |
@@ -573,7 +573,7 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name, | |||
573 | blob->data = data; | 573 | blob->data = data; |
574 | data += sprintf(data, "rt chip:\t%04x\n", intf->rt2x00dev->chip.rt); | 574 | data += sprintf(data, "rt chip:\t%04x\n", intf->rt2x00dev->chip.rt); |
575 | data += sprintf(data, "rf chip:\t%04x\n", intf->rt2x00dev->chip.rf); | 575 | data += sprintf(data, "rf chip:\t%04x\n", intf->rt2x00dev->chip.rf); |
576 | data += sprintf(data, "revision:\t%08x\n", intf->rt2x00dev->chip.rev); | 576 | data += sprintf(data, "revision:\t%04x\n", intf->rt2x00dev->chip.rev); |
577 | data += sprintf(data, "\n"); | 577 | data += sprintf(data, "\n"); |
578 | data += sprintf(data, "register\tbase\twords\twordsize\n"); | 578 | data += sprintf(data, "register\tbase\twords\twordsize\n"); |
579 | data += sprintf(data, "csr\t%d\t%d\t%d\n", | 579 | data += sprintf(data, "csr\t%d\t%d\t%d\n", |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 265e66dba552..b93731b79903 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -385,9 +385,6 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, | |||
385 | memset(&rxdesc, 0, sizeof(rxdesc)); | 385 | memset(&rxdesc, 0, sizeof(rxdesc)); |
386 | rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); | 386 | rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); |
387 | 387 | ||
388 | /* Trim buffer to correct size */ | ||
389 | skb_trim(entry->skb, rxdesc.size); | ||
390 | |||
391 | /* | 388 | /* |
392 | * The data behind the ieee80211 header must be | 389 | * The data behind the ieee80211 header must be |
393 | * aligned on a 4 byte boundary. | 390 | * aligned on a 4 byte boundary. |
@@ -404,11 +401,16 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, | |||
404 | (rxdesc.flags & RX_FLAG_IV_STRIPPED)) | 401 | (rxdesc.flags & RX_FLAG_IV_STRIPPED)) |
405 | rt2x00crypto_rx_insert_iv(entry->skb, header_length, | 402 | rt2x00crypto_rx_insert_iv(entry->skb, header_length, |
406 | &rxdesc); | 403 | &rxdesc); |
407 | else if (rxdesc.dev_flags & RXDONE_L2PAD) | 404 | else if (header_length && |
405 | (rxdesc.size > header_length) && | ||
406 | (rxdesc.dev_flags & RXDONE_L2PAD)) | ||
408 | rt2x00queue_remove_l2pad(entry->skb, header_length); | 407 | rt2x00queue_remove_l2pad(entry->skb, header_length); |
409 | else | 408 | else |
410 | rt2x00queue_align_payload(entry->skb, header_length); | 409 | rt2x00queue_align_payload(entry->skb, header_length); |
411 | 410 | ||
411 | /* Trim buffer to correct size */ | ||
412 | skb_trim(entry->skb, rxdesc.size); | ||
413 | |||
412 | /* | 414 | /* |
413 | * Check if the frame was received using HT. In that case, | 415 | * Check if the frame was received using HT. In that case, |
414 | * the rate is the MCS index and should be passed to mac80211 | 416 | * the rate is the MCS index and should be passed to mac80211 |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index de549c244ed8..abbd857ec759 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -187,10 +187,10 @@ void rt2x00mac_stop(struct ieee80211_hw *hw) | |||
187 | EXPORT_SYMBOL_GPL(rt2x00mac_stop); | 187 | EXPORT_SYMBOL_GPL(rt2x00mac_stop); |
188 | 188 | ||
189 | int rt2x00mac_add_interface(struct ieee80211_hw *hw, | 189 | int rt2x00mac_add_interface(struct ieee80211_hw *hw, |
190 | struct ieee80211_if_init_conf *conf) | 190 | struct ieee80211_vif *vif) |
191 | { | 191 | { |
192 | struct rt2x00_dev *rt2x00dev = hw->priv; | 192 | struct rt2x00_dev *rt2x00dev = hw->priv; |
193 | struct rt2x00_intf *intf = vif_to_intf(conf->vif); | 193 | struct rt2x00_intf *intf = vif_to_intf(vif); |
194 | struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON); | 194 | struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON); |
195 | struct queue_entry *entry = NULL; | 195 | struct queue_entry *entry = NULL; |
196 | unsigned int i; | 196 | unsigned int i; |
@@ -203,7 +203,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, | |||
203 | !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) | 203 | !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) |
204 | return -ENODEV; | 204 | return -ENODEV; |
205 | 205 | ||
206 | switch (conf->type) { | 206 | switch (vif->type) { |
207 | case NL80211_IFTYPE_AP: | 207 | case NL80211_IFTYPE_AP: |
208 | /* | 208 | /* |
209 | * We don't support mixed combinations of | 209 | * We don't support mixed combinations of |
@@ -263,7 +263,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, | |||
263 | * increase interface count and start initialization. | 263 | * increase interface count and start initialization. |
264 | */ | 264 | */ |
265 | 265 | ||
266 | if (conf->type == NL80211_IFTYPE_AP) | 266 | if (vif->type == NL80211_IFTYPE_AP) |
267 | rt2x00dev->intf_ap_count++; | 267 | rt2x00dev->intf_ap_count++; |
268 | else | 268 | else |
269 | rt2x00dev->intf_sta_count++; | 269 | rt2x00dev->intf_sta_count++; |
@@ -273,16 +273,16 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, | |||
273 | mutex_init(&intf->beacon_skb_mutex); | 273 | mutex_init(&intf->beacon_skb_mutex); |
274 | intf->beacon = entry; | 274 | intf->beacon = entry; |
275 | 275 | ||
276 | if (conf->type == NL80211_IFTYPE_AP) | 276 | if (vif->type == NL80211_IFTYPE_AP) |
277 | memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN); | 277 | memcpy(&intf->bssid, vif->addr, ETH_ALEN); |
278 | memcpy(&intf->mac, conf->mac_addr, ETH_ALEN); | 278 | memcpy(&intf->mac, vif->addr, ETH_ALEN); |
279 | 279 | ||
280 | /* | 280 | /* |
281 | * The MAC adddress must be configured after the device | 281 | * The MAC adddress must be configured after the device |
282 | * has been initialized. Otherwise the device can reset | 282 | * has been initialized. Otherwise the device can reset |
283 | * the MAC registers. | 283 | * the MAC registers. |
284 | */ | 284 | */ |
285 | rt2x00lib_config_intf(rt2x00dev, intf, conf->type, intf->mac, NULL); | 285 | rt2x00lib_config_intf(rt2x00dev, intf, vif->type, intf->mac, NULL); |
286 | 286 | ||
287 | /* | 287 | /* |
288 | * Some filters depend on the current working mode. We can force | 288 | * Some filters depend on the current working mode. We can force |
@@ -296,10 +296,10 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, | |||
296 | EXPORT_SYMBOL_GPL(rt2x00mac_add_interface); | 296 | EXPORT_SYMBOL_GPL(rt2x00mac_add_interface); |
297 | 297 | ||
298 | void rt2x00mac_remove_interface(struct ieee80211_hw *hw, | 298 | void rt2x00mac_remove_interface(struct ieee80211_hw *hw, |
299 | struct ieee80211_if_init_conf *conf) | 299 | struct ieee80211_vif *vif) |
300 | { | 300 | { |
301 | struct rt2x00_dev *rt2x00dev = hw->priv; | 301 | struct rt2x00_dev *rt2x00dev = hw->priv; |
302 | struct rt2x00_intf *intf = vif_to_intf(conf->vif); | 302 | struct rt2x00_intf *intf = vif_to_intf(vif); |
303 | 303 | ||
304 | /* | 304 | /* |
305 | * Don't allow interfaces to be remove while | 305 | * Don't allow interfaces to be remove while |
@@ -307,11 +307,11 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw, | |||
307 | * no interface is present. | 307 | * no interface is present. |
308 | */ | 308 | */ |
309 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || | 309 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || |
310 | (conf->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) || | 310 | (vif->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) || |
311 | (conf->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count)) | 311 | (vif->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count)) |
312 | return; | 312 | return; |
313 | 313 | ||
314 | if (conf->type == NL80211_IFTYPE_AP) | 314 | if (vif->type == NL80211_IFTYPE_AP) |
315 | rt2x00dev->intf_ap_count--; | 315 | rt2x00dev->intf_ap_count--; |
316 | else | 316 | else |
317 | rt2x00dev->intf_sta_count--; | 317 | rt2x00dev->intf_sta_count--; |
@@ -555,22 +555,6 @@ int rt2x00mac_get_stats(struct ieee80211_hw *hw, | |||
555 | } | 555 | } |
556 | EXPORT_SYMBOL_GPL(rt2x00mac_get_stats); | 556 | EXPORT_SYMBOL_GPL(rt2x00mac_get_stats); |
557 | 557 | ||
558 | int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw, | ||
559 | struct ieee80211_tx_queue_stats *stats) | ||
560 | { | ||
561 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
562 | unsigned int i; | ||
563 | |||
564 | for (i = 0; i < rt2x00dev->ops->tx_queues; i++) { | ||
565 | stats[i].len = rt2x00dev->tx[i].length; | ||
566 | stats[i].limit = rt2x00dev->tx[i].limit; | ||
567 | stats[i].count = rt2x00dev->tx[i].count; | ||
568 | } | ||
569 | |||
570 | return 0; | ||
571 | } | ||
572 | EXPORT_SYMBOL_GPL(rt2x00mac_get_tx_stats); | ||
573 | |||
574 | void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, | 558 | void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, |
575 | struct ieee80211_vif *vif, | 559 | struct ieee80211_vif *vif, |
576 | struct ieee80211_bss_conf *bss_conf, | 560 | struct ieee80211_bss_conf *bss_conf, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 0feb4d0e4668..047123b766fc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -41,6 +41,9 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, | |||
41 | { | 41 | { |
42 | unsigned int i; | 42 | unsigned int i; |
43 | 43 | ||
44 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) | ||
45 | return 0; | ||
46 | |||
44 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 47 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { |
45 | rt2x00pci_register_read(rt2x00dev, offset, reg); | 48 | rt2x00pci_register_read(rt2x00dev, offset, reg); |
46 | if (!rt2x00_get_field32(*reg, field)) | 49 | if (!rt2x00_get_field32(*reg, field)) |
@@ -269,7 +272,6 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) | |||
269 | struct ieee80211_hw *hw; | 272 | struct ieee80211_hw *hw; |
270 | struct rt2x00_dev *rt2x00dev; | 273 | struct rt2x00_dev *rt2x00dev; |
271 | int retval; | 274 | int retval; |
272 | u16 chip; | ||
273 | 275 | ||
274 | retval = pci_request_regions(pci_dev, pci_name(pci_dev)); | 276 | retval = pci_request_regions(pci_dev, pci_name(pci_dev)); |
275 | if (retval) { | 277 | if (retval) { |
@@ -312,12 +314,6 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) | |||
312 | 314 | ||
313 | rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); | 315 | rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); |
314 | 316 | ||
315 | /* | ||
316 | * Determine RT chipset by reading PCI header. | ||
317 | */ | ||
318 | pci_read_config_word(pci_dev, PCI_DEVICE_ID, &chip); | ||
319 | rt2x00_set_chip_rt(rt2x00dev, chip); | ||
320 | |||
321 | retval = rt2x00pci_alloc_reg(rt2x00dev); | 317 | retval = rt2x00pci_alloc_reg(rt2x00dev); |
322 | if (retval) | 318 | if (retval) |
323 | goto exit_free_device; | 319 | goto exit_free_device; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index d4f9449ab0a4..8149ff68410a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h | |||
@@ -27,6 +27,7 @@ | |||
27 | #define RT2X00PCI_H | 27 | #define RT2X00PCI_H |
28 | 28 | ||
29 | #include <linux/io.h> | 29 | #include <linux/io.h> |
30 | #include <linux/pci.h> | ||
30 | 31 | ||
31 | /* | 32 | /* |
32 | * This variable should be used with the | 33 | * This variable should be used with the |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 9915a09141ef..0b4801a14601 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -177,55 +177,45 @@ void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length) | |||
177 | 177 | ||
178 | void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) | 178 | void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) |
179 | { | 179 | { |
180 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); | 180 | unsigned int payload_length = skb->len - header_length; |
181 | unsigned int frame_length = skb->len; | ||
182 | unsigned int header_align = ALIGN_SIZE(skb, 0); | 181 | unsigned int header_align = ALIGN_SIZE(skb, 0); |
183 | unsigned int payload_align = ALIGN_SIZE(skb, header_length); | 182 | unsigned int payload_align = ALIGN_SIZE(skb, header_length); |
184 | unsigned int l2pad = 4 - (payload_align - header_align); | 183 | unsigned int l2pad = payload_length ? L2PAD_SIZE(header_length) : 0; |
185 | 184 | ||
186 | if (header_align == payload_align) { | 185 | /* |
187 | /* | 186 | * Adjust the header alignment if the payload needs to be moved more |
188 | * Both header and payload must be moved the same | 187 | * than the header. |
189 | * amount of bytes to align them properly. This means | 188 | */ |
190 | * we don't use the L2 padding but just move the entire | 189 | if (payload_align > header_align) |
191 | * frame. | 190 | header_align += 4; |
192 | */ | 191 | |
193 | rt2x00queue_align_frame(skb); | 192 | /* There is nothing to do if no alignment is needed */ |
194 | } else if (!payload_align) { | 193 | if (!header_align) |
195 | /* | 194 | return; |
196 | * Simple L2 padding, only the header needs to be moved, | 195 | |
197 | * the payload is already properly aligned. | 196 | /* Reserve the amount of space needed in front of the frame */ |
198 | */ | 197 | skb_push(skb, header_align); |
199 | skb_push(skb, header_align); | 198 | |
200 | memmove(skb->data, skb->data + header_align, frame_length); | 199 | /* |
201 | skbdesc->flags |= SKBDESC_L2_PADDED; | 200 | * Move the header. |
202 | } else { | 201 | */ |
203 | /* | 202 | memmove(skb->data, skb->data + header_align, header_length); |
204 | * | ||
205 | * Complicated L2 padding, both header and payload need | ||
206 | * to be moved. By default we only move to the start | ||
207 | * of the buffer, so our header alignment needs to be | ||
208 | * increased if there is not enough room for the header | ||
209 | * to be moved. | ||
210 | */ | ||
211 | if (payload_align > header_align) | ||
212 | header_align += 4; | ||
213 | 203 | ||
214 | skb_push(skb, header_align); | 204 | /* Move the payload, if present and if required */ |
215 | memmove(skb->data, skb->data + header_align, header_length); | 205 | if (payload_length && payload_align) |
216 | memmove(skb->data + header_length + l2pad, | 206 | memmove(skb->data + header_length + l2pad, |
217 | skb->data + header_length + l2pad + payload_align, | 207 | skb->data + header_length + l2pad + payload_align, |
218 | frame_length - header_length); | 208 | payload_length); |
219 | skbdesc->flags |= SKBDESC_L2_PADDED; | 209 | |
220 | } | 210 | /* Trim the skb to the correct size */ |
211 | skb_trim(skb, header_length + l2pad + payload_length); | ||
221 | } | 212 | } |
222 | 213 | ||
223 | void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length) | 214 | void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length) |
224 | { | 215 | { |
225 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); | 216 | unsigned int l2pad = L2PAD_SIZE(header_length); |
226 | unsigned int l2pad = 4 - (header_length & 3); | ||
227 | 217 | ||
228 | if (!l2pad || (skbdesc->flags & SKBDESC_L2_PADDED)) | 218 | if (!l2pad) |
229 | return; | 219 | return; |
230 | 220 | ||
231 | memmove(skb->data + l2pad, skb->data, header_length); | 221 | memmove(skb->data + l2pad, skb->data, header_length); |
@@ -346,7 +336,9 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | |||
346 | * Header and alignment information. | 336 | * Header and alignment information. |
347 | */ | 337 | */ |
348 | txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb); | 338 | txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb); |
349 | txdesc->l2pad = ALIGN_SIZE(entry->skb, txdesc->header_length); | 339 | if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags) && |
340 | (entry->skb->len > txdesc->header_length)) | ||
341 | txdesc->l2pad = L2PAD_SIZE(txdesc->header_length); | ||
350 | 342 | ||
351 | /* | 343 | /* |
352 | * Check whether this frame is to be acked. | 344 | * Check whether this frame is to be acked. |
@@ -387,10 +379,13 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | |||
387 | 379 | ||
388 | /* | 380 | /* |
389 | * Beacons and probe responses require the tsf timestamp | 381 | * Beacons and probe responses require the tsf timestamp |
390 | * to be inserted into the frame. | 382 | * to be inserted into the frame, except for a frame that has been injected |
383 | * through a monitor interface. This latter is needed for testing a | ||
384 | * monitor interface. | ||
391 | */ | 385 | */ |
392 | if (ieee80211_is_beacon(hdr->frame_control) || | 386 | if ((ieee80211_is_beacon(hdr->frame_control) || |
393 | ieee80211_is_probe_resp(hdr->frame_control)) | 387 | ieee80211_is_probe_resp(hdr->frame_control)) && |
388 | (!(tx_info->flags & IEEE80211_TX_CTL_INJECTED))) | ||
394 | __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags); | 389 | __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags); |
395 | 390 | ||
396 | /* | 391 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 70775e5ba1ac..c1e482bb37b3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -92,8 +92,6 @@ enum data_queue_qid { | |||
92 | * @SKBDESC_DMA_MAPPED_TX: &skb_dma field has been mapped for TX | 92 | * @SKBDESC_DMA_MAPPED_TX: &skb_dma field has been mapped for TX |
93 | * @SKBDESC_IV_STRIPPED: Frame contained a IV/EIV provided by | 93 | * @SKBDESC_IV_STRIPPED: Frame contained a IV/EIV provided by |
94 | * mac80211 but was stripped for processing by the driver. | 94 | * mac80211 but was stripped for processing by the driver. |
95 | * @SKBDESC_L2_PADDED: Payload has been padded for 4-byte alignment, | ||
96 | * the padded bytes are located between header and payload. | ||
97 | * @SKBDESC_NOT_MAC80211: Frame didn't originate from mac80211, | 95 | * @SKBDESC_NOT_MAC80211: Frame didn't originate from mac80211, |
98 | * don't try to pass it back. | 96 | * don't try to pass it back. |
99 | */ | 97 | */ |
@@ -101,8 +99,7 @@ enum skb_frame_desc_flags { | |||
101 | SKBDESC_DMA_MAPPED_RX = 1 << 0, | 99 | SKBDESC_DMA_MAPPED_RX = 1 << 0, |
102 | SKBDESC_DMA_MAPPED_TX = 1 << 1, | 100 | SKBDESC_DMA_MAPPED_TX = 1 << 1, |
103 | SKBDESC_IV_STRIPPED = 1 << 2, | 101 | SKBDESC_IV_STRIPPED = 1 << 2, |
104 | SKBDESC_L2_PADDED = 1 << 3, | 102 | SKBDESC_NOT_MAC80211 = 1 << 3, |
105 | SKBDESC_NOT_MAC80211 = 1 << 4, | ||
106 | }; | 103 | }; |
107 | 104 | ||
108 | /** | 105 | /** |
diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.c b/drivers/net/wireless/rt2x00/rt2x00soc.c index 19e684f8ffa1..4efdc96010f6 100644 --- a/drivers/net/wireless/rt2x00/rt2x00soc.c +++ b/drivers/net/wireless/rt2x00/rt2x00soc.c | |||
@@ -71,9 +71,7 @@ exit: | |||
71 | return -ENOMEM; | 71 | return -ENOMEM; |
72 | } | 72 | } |
73 | 73 | ||
74 | int rt2x00soc_probe(struct platform_device *pdev, | 74 | int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops) |
75 | const unsigned short chipset, | ||
76 | const struct rt2x00_ops *ops) | ||
77 | { | 75 | { |
78 | struct ieee80211_hw *hw; | 76 | struct ieee80211_hw *hw; |
79 | struct rt2x00_dev *rt2x00dev; | 77 | struct rt2x00_dev *rt2x00dev; |
@@ -94,12 +92,7 @@ int rt2x00soc_probe(struct platform_device *pdev, | |||
94 | rt2x00dev->irq = platform_get_irq(pdev, 0); | 92 | rt2x00dev->irq = platform_get_irq(pdev, 0); |
95 | rt2x00dev->name = pdev->dev.driver->name; | 93 | rt2x00dev->name = pdev->dev.driver->name; |
96 | 94 | ||
97 | /* | 95 | rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC); |
98 | * SoC devices mimic PCI behavior. | ||
99 | */ | ||
100 | rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); | ||
101 | |||
102 | rt2x00_set_chip_rt(rt2x00dev, chipset); | ||
103 | 96 | ||
104 | retval = rt2x00soc_alloc_reg(rt2x00dev); | 97 | retval = rt2x00soc_alloc_reg(rt2x00dev); |
105 | if (retval) | 98 | if (retval) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.h b/drivers/net/wireless/rt2x00/rt2x00soc.h index 8a3416624af5..4739edfe2f00 100644 --- a/drivers/net/wireless/rt2x00/rt2x00soc.h +++ b/drivers/net/wireless/rt2x00/rt2x00soc.h | |||
@@ -28,18 +28,10 @@ | |||
28 | 28 | ||
29 | #define KSEG1ADDR(__ptr) __ptr | 29 | #define KSEG1ADDR(__ptr) __ptr |
30 | 30 | ||
31 | #define __rt2x00soc_probe(__chipset, __ops) \ | ||
32 | static int __rt2x00soc_probe(struct platform_device *pdev) \ | ||
33 | { \ | ||
34 | return rt2x00soc_probe(pdev, (__chipset), (__ops)); \ | ||
35 | } | ||
36 | |||
37 | /* | 31 | /* |
38 | * SoC driver handlers. | 32 | * SoC driver handlers. |
39 | */ | 33 | */ |
40 | int rt2x00soc_probe(struct platform_device *pdev, | 34 | int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops); |
41 | const unsigned short chipset, | ||
42 | const struct rt2x00_ops *ops); | ||
43 | int rt2x00soc_remove(struct platform_device *pdev); | 35 | int rt2x00soc_remove(struct platform_device *pdev); |
44 | #ifdef CONFIG_PM | 36 | #ifdef CONFIG_PM |
45 | int rt2x00soc_suspend(struct platform_device *pdev, pm_message_t state); | 37 | int rt2x00soc_suspend(struct platform_device *pdev, pm_message_t state); |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 0ca589306d71..ee9c696fe1d4 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -637,8 +637,7 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev, | |||
637 | rt61pci_bbp_read(rt2x00dev, 4, &r4); | 637 | rt61pci_bbp_read(rt2x00dev, 4, &r4); |
638 | rt61pci_bbp_read(rt2x00dev, 77, &r77); | 638 | rt61pci_bbp_read(rt2x00dev, 77, &r77); |
639 | 639 | ||
640 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, | 640 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF5325)); |
641 | rt2x00_rf(&rt2x00dev->chip, RF5325)); | ||
642 | 641 | ||
643 | /* | 642 | /* |
644 | * Configure the RX antenna. | 643 | * Configure the RX antenna. |
@@ -684,8 +683,7 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev, | |||
684 | rt61pci_bbp_read(rt2x00dev, 4, &r4); | 683 | rt61pci_bbp_read(rt2x00dev, 4, &r4); |
685 | rt61pci_bbp_read(rt2x00dev, 77, &r77); | 684 | rt61pci_bbp_read(rt2x00dev, 77, &r77); |
686 | 685 | ||
687 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, | 686 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529)); |
688 | rt2x00_rf(&rt2x00dev->chip, RF2529)); | ||
689 | rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, | 687 | rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, |
690 | !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); | 688 | !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); |
691 | 689 | ||
@@ -833,12 +831,11 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev, | |||
833 | 831 | ||
834 | rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg); | 832 | rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg); |
835 | 833 | ||
836 | if (rt2x00_rf(&rt2x00dev->chip, RF5225) || | 834 | if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325)) |
837 | rt2x00_rf(&rt2x00dev->chip, RF5325)) | ||
838 | rt61pci_config_antenna_5x(rt2x00dev, ant); | 835 | rt61pci_config_antenna_5x(rt2x00dev, ant); |
839 | else if (rt2x00_rf(&rt2x00dev->chip, RF2527)) | 836 | else if (rt2x00_rf(rt2x00dev, RF2527)) |
840 | rt61pci_config_antenna_2x(rt2x00dev, ant); | 837 | rt61pci_config_antenna_2x(rt2x00dev, ant); |
841 | else if (rt2x00_rf(&rt2x00dev->chip, RF2529)) { | 838 | else if (rt2x00_rf(rt2x00dev, RF2529)) { |
842 | if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) | 839 | if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) |
843 | rt61pci_config_antenna_2x(rt2x00dev, ant); | 840 | rt61pci_config_antenna_2x(rt2x00dev, ant); |
844 | else | 841 | else |
@@ -879,8 +876,7 @@ static void rt61pci_config_channel(struct rt2x00_dev *rt2x00dev, | |||
879 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); | 876 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); |
880 | rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); | 877 | rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); |
881 | 878 | ||
882 | smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) || | 879 | smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527)); |
883 | rt2x00_rf(&rt2x00dev->chip, RF2527)); | ||
884 | 880 | ||
885 | rt61pci_bbp_read(rt2x00dev, 3, &r3); | 881 | rt61pci_bbp_read(rt2x00dev, 3, &r3); |
886 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart); | 882 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart); |
@@ -1135,16 +1131,18 @@ dynamic_cca_tune: | |||
1135 | */ | 1131 | */ |
1136 | static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev) | 1132 | static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev) |
1137 | { | 1133 | { |
1134 | u16 chip; | ||
1138 | char *fw_name; | 1135 | char *fw_name; |
1139 | 1136 | ||
1140 | switch (rt2x00dev->chip.rt) { | 1137 | pci_read_config_word(to_pci_dev(rt2x00dev->dev), PCI_DEVICE_ID, &chip); |
1141 | case RT2561: | 1138 | switch (chip) { |
1139 | case RT2561_PCI_ID: | ||
1142 | fw_name = FIRMWARE_RT2561; | 1140 | fw_name = FIRMWARE_RT2561; |
1143 | break; | 1141 | break; |
1144 | case RT2561s: | 1142 | case RT2561s_PCI_ID: |
1145 | fw_name = FIRMWARE_RT2561s; | 1143 | fw_name = FIRMWARE_RT2561s; |
1146 | break; | 1144 | break; |
1147 | case RT2661: | 1145 | case RT2661_PCI_ID: |
1148 | fw_name = FIRMWARE_RT2661; | 1146 | fw_name = FIRMWARE_RT2661; |
1149 | break; | 1147 | break; |
1150 | default: | 1148 | default: |
@@ -2299,13 +2297,13 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
2299 | */ | 2297 | */ |
2300 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); | 2298 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); |
2301 | rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); | 2299 | rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); |
2302 | rt2x00_set_chip_rf(rt2x00dev, value, reg); | 2300 | rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET), |
2303 | rt2x00_print_chip(rt2x00dev); | 2301 | value, rt2x00_get_field32(reg, MAC_CSR0_REVISION)); |
2304 | 2302 | ||
2305 | if (!rt2x00_rf(&rt2x00dev->chip, RF5225) && | 2303 | if (!rt2x00_rf(rt2x00dev, RF5225) && |
2306 | !rt2x00_rf(&rt2x00dev->chip, RF5325) && | 2304 | !rt2x00_rf(rt2x00dev, RF5325) && |
2307 | !rt2x00_rf(&rt2x00dev->chip, RF2527) && | 2305 | !rt2x00_rf(rt2x00dev, RF2527) && |
2308 | !rt2x00_rf(&rt2x00dev->chip, RF2529)) { | 2306 | !rt2x00_rf(rt2x00dev, RF2529)) { |
2309 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); | 2307 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); |
2310 | return -ENODEV; | 2308 | return -ENODEV; |
2311 | } | 2309 | } |
@@ -2360,7 +2358,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
2360 | * the antenna settings should be gathered from the NIC | 2358 | * the antenna settings should be gathered from the NIC |
2361 | * eeprom word. | 2359 | * eeprom word. |
2362 | */ | 2360 | */ |
2363 | if (rt2x00_rf(&rt2x00dev->chip, RF2529) && | 2361 | if (rt2x00_rf(rt2x00dev, RF2529) && |
2364 | !test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) { | 2362 | !test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) { |
2365 | rt2x00dev->default_ant.rx = | 2363 | rt2x00dev->default_ant.rx = |
2366 | ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED); | 2364 | ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED); |
@@ -2571,8 +2569,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2571 | spec->channels = rf_vals_seq; | 2569 | spec->channels = rf_vals_seq; |
2572 | } | 2570 | } |
2573 | 2571 | ||
2574 | if (rt2x00_rf(&rt2x00dev->chip, RF5225) || | 2572 | if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325)) { |
2575 | rt2x00_rf(&rt2x00dev->chip, RF5325)) { | ||
2576 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 2573 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
2577 | spec->num_channels = ARRAY_SIZE(rf_vals_seq); | 2574 | spec->num_channels = ARRAY_SIZE(rf_vals_seq); |
2578 | } | 2575 | } |
@@ -2735,7 +2732,6 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { | |||
2735 | .get_stats = rt2x00mac_get_stats, | 2732 | .get_stats = rt2x00mac_get_stats, |
2736 | .bss_info_changed = rt2x00mac_bss_info_changed, | 2733 | .bss_info_changed = rt2x00mac_bss_info_changed, |
2737 | .conf_tx = rt61pci_conf_tx, | 2734 | .conf_tx = rt61pci_conf_tx, |
2738 | .get_tx_stats = rt2x00mac_get_tx_stats, | ||
2739 | .get_tsf = rt61pci_get_tsf, | 2735 | .get_tsf = rt61pci_get_tsf, |
2740 | .rfkill_poll = rt2x00mac_rfkill_poll, | 2736 | .rfkill_poll = rt2x00mac_rfkill_poll, |
2741 | }; | 2737 | }; |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index 6f33f7f5668c..ab20c7758824 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h | |||
@@ -28,6 +28,13 @@ | |||
28 | #define RT61PCI_H | 28 | #define RT61PCI_H |
29 | 29 | ||
30 | /* | 30 | /* |
31 | * RT chip PCI IDs. | ||
32 | */ | ||
33 | #define RT2561s_PCI_ID 0x0301 | ||
34 | #define RT2561_PCI_ID 0x0302 | ||
35 | #define RT2661_PCI_ID 0x0401 | ||
36 | |||
37 | /* | ||
31 | * RF chip defines. | 38 | * RF chip defines. |
32 | */ | 39 | */ |
33 | #define RF5225 0x0001 | 40 | #define RF5225 0x0001 |
@@ -225,6 +232,8 @@ struct hw_pairwise_ta_entry { | |||
225 | * MAC_CSR0: ASIC revision number. | 232 | * MAC_CSR0: ASIC revision number. |
226 | */ | 233 | */ |
227 | #define MAC_CSR0 0x3000 | 234 | #define MAC_CSR0 0x3000 |
235 | #define MAC_CSR0_REVISION FIELD32(0x0000000f) | ||
236 | #define MAC_CSR0_CHIPSET FIELD32(0x000ffff0) | ||
228 | 237 | ||
229 | /* | 238 | /* |
230 | * MAC_CSR1: System control register. | 239 | * MAC_CSR1: System control register. |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ced3b6ab5e16..f39a8ed17841 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -136,8 +136,8 @@ static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, | |||
136 | * all others contain 20 bits. | 136 | * all others contain 20 bits. |
137 | */ | 137 | */ |
138 | rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, | 138 | rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, |
139 | 20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) || | 139 | 20 + (rt2x00_rf(rt2x00dev, RF5225) || |
140 | rt2x00_rf(&rt2x00dev->chip, RF2527))); | 140 | rt2x00_rf(rt2x00dev, RF2527))); |
141 | rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); | 141 | rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); |
142 | rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); | 142 | rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); |
143 | 143 | ||
@@ -741,11 +741,9 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev, | |||
741 | 741 | ||
742 | rt2x00usb_register_write(rt2x00dev, PHY_CSR0, reg); | 742 | rt2x00usb_register_write(rt2x00dev, PHY_CSR0, reg); |
743 | 743 | ||
744 | if (rt2x00_rf(&rt2x00dev->chip, RF5226) || | 744 | if (rt2x00_rf(rt2x00dev, RF5226) || rt2x00_rf(rt2x00dev, RF5225)) |
745 | rt2x00_rf(&rt2x00dev->chip, RF5225)) | ||
746 | rt73usb_config_antenna_5x(rt2x00dev, ant); | 745 | rt73usb_config_antenna_5x(rt2x00dev, ant); |
747 | else if (rt2x00_rf(&rt2x00dev->chip, RF2528) || | 746 | else if (rt2x00_rf(rt2x00dev, RF2528) || rt2x00_rf(rt2x00dev, RF2527)) |
748 | rt2x00_rf(&rt2x00dev->chip, RF2527)) | ||
749 | rt73usb_config_antenna_2x(rt2x00dev, ant); | 747 | rt73usb_config_antenna_2x(rt2x00dev, ant); |
750 | } | 748 | } |
751 | 749 | ||
@@ -779,8 +777,7 @@ static void rt73usb_config_channel(struct rt2x00_dev *rt2x00dev, | |||
779 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); | 777 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); |
780 | rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); | 778 | rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); |
781 | 779 | ||
782 | smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) || | 780 | smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527)); |
783 | rt2x00_rf(&rt2x00dev->chip, RF2527)); | ||
784 | 781 | ||
785 | rt73usb_bbp_read(rt2x00dev, 3, &r3); | 782 | rt73usb_bbp_read(rt2x00dev, 3, &r3); |
786 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart); | 783 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart); |
@@ -1210,8 +1207,7 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1210 | rt2x00usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000); | 1207 | rt2x00usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000); |
1211 | 1208 | ||
1212 | reg = 0x000023b0; | 1209 | reg = 0x000023b0; |
1213 | if (rt2x00_rf(&rt2x00dev->chip, RF5225) || | 1210 | if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527)) |
1214 | rt2x00_rf(&rt2x00dev->chip, RF2527)) | ||
1215 | rt2x00_set_field32(®, PHY_CSR1_RF_RPI, 1); | 1211 | rt2x00_set_field32(®, PHY_CSR1_RF_RPI, 1); |
1216 | rt2x00usb_register_write(rt2x00dev, PHY_CSR1, reg); | 1212 | rt2x00usb_register_write(rt2x00dev, PHY_CSR1, reg); |
1217 | 1213 | ||
@@ -1824,19 +1820,18 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1824 | */ | 1820 | */ |
1825 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); | 1821 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); |
1826 | rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); | 1822 | rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); |
1827 | rt2x00_set_chip(rt2x00dev, RT2571, value, reg); | 1823 | rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET), |
1828 | rt2x00_print_chip(rt2x00dev); | 1824 | value, rt2x00_get_field32(reg, MAC_CSR0_REVISION)); |
1829 | 1825 | ||
1830 | if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0x25730) || | 1826 | if (!rt2x00_rt(rt2x00dev, RT2573) || (rt2x00_rev(rt2x00dev) == 0)) { |
1831 | rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) { | ||
1832 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); | 1827 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); |
1833 | return -ENODEV; | 1828 | return -ENODEV; |
1834 | } | 1829 | } |
1835 | 1830 | ||
1836 | if (!rt2x00_rf(&rt2x00dev->chip, RF5226) && | 1831 | if (!rt2x00_rf(rt2x00dev, RF5226) && |
1837 | !rt2x00_rf(&rt2x00dev->chip, RF2528) && | 1832 | !rt2x00_rf(rt2x00dev, RF2528) && |
1838 | !rt2x00_rf(&rt2x00dev->chip, RF5225) && | 1833 | !rt2x00_rf(rt2x00dev, RF5225) && |
1839 | !rt2x00_rf(&rt2x00dev->chip, RF2527)) { | 1834 | !rt2x00_rf(rt2x00dev, RF2527)) { |
1840 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); | 1835 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); |
1841 | return -ENODEV; | 1836 | return -ENODEV; |
1842 | } | 1837 | } |
@@ -2081,17 +2076,17 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2081 | spec->supported_bands = SUPPORT_BAND_2GHZ; | 2076 | spec->supported_bands = SUPPORT_BAND_2GHZ; |
2082 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; | 2077 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; |
2083 | 2078 | ||
2084 | if (rt2x00_rf(&rt2x00dev->chip, RF2528)) { | 2079 | if (rt2x00_rf(rt2x00dev, RF2528)) { |
2085 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528); | 2080 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528); |
2086 | spec->channels = rf_vals_bg_2528; | 2081 | spec->channels = rf_vals_bg_2528; |
2087 | } else if (rt2x00_rf(&rt2x00dev->chip, RF5226)) { | 2082 | } else if (rt2x00_rf(rt2x00dev, RF5226)) { |
2088 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 2083 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
2089 | spec->num_channels = ARRAY_SIZE(rf_vals_5226); | 2084 | spec->num_channels = ARRAY_SIZE(rf_vals_5226); |
2090 | spec->channels = rf_vals_5226; | 2085 | spec->channels = rf_vals_5226; |
2091 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2527)) { | 2086 | } else if (rt2x00_rf(rt2x00dev, RF2527)) { |
2092 | spec->num_channels = 14; | 2087 | spec->num_channels = 14; |
2093 | spec->channels = rf_vals_5225_2527; | 2088 | spec->channels = rf_vals_5225_2527; |
2094 | } else if (rt2x00_rf(&rt2x00dev->chip, RF5225)) { | 2089 | } else if (rt2x00_rf(rt2x00dev, RF5225)) { |
2095 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 2090 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
2096 | spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527); | 2091 | spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527); |
2097 | spec->channels = rf_vals_5225_2527; | 2092 | spec->channels = rf_vals_5225_2527; |
@@ -2249,7 +2244,6 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { | |||
2249 | .get_stats = rt2x00mac_get_stats, | 2244 | .get_stats = rt2x00mac_get_stats, |
2250 | .bss_info_changed = rt2x00mac_bss_info_changed, | 2245 | .bss_info_changed = rt2x00mac_bss_info_changed, |
2251 | .conf_tx = rt73usb_conf_tx, | 2246 | .conf_tx = rt73usb_conf_tx, |
2252 | .get_tx_stats = rt2x00mac_get_tx_stats, | ||
2253 | .get_tsf = rt73usb_get_tsf, | 2247 | .get_tsf = rt73usb_get_tsf, |
2254 | .rfkill_poll = rt2x00mac_rfkill_poll, | 2248 | .rfkill_poll = rt2x00mac_rfkill_poll, |
2255 | }; | 2249 | }; |
@@ -2354,6 +2348,7 @@ static struct usb_device_id rt73usb_device_table[] = { | |||
2354 | { USB_DEVICE(0x08dd, 0x0120), USB_DEVICE_DATA(&rt73usb_ops) }, | 2348 | { USB_DEVICE(0x08dd, 0x0120), USB_DEVICE_DATA(&rt73usb_ops) }, |
2355 | /* Buffalo */ | 2349 | /* Buffalo */ |
2356 | { USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) }, | 2350 | { USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) }, |
2351 | { USB_DEVICE(0x0411, 0x00d9), USB_DEVICE_DATA(&rt73usb_ops) }, | ||
2357 | { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) }, | 2352 | { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) }, |
2358 | { USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) }, | 2353 | { USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) }, |
2359 | { USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) }, | 2354 | { USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) }, |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index e783a099a8f1..b4e3ddda06cf 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h | |||
@@ -142,6 +142,8 @@ struct hw_pairwise_ta_entry { | |||
142 | * MAC_CSR0: ASIC revision number. | 142 | * MAC_CSR0: ASIC revision number. |
143 | */ | 143 | */ |
144 | #define MAC_CSR0 0x3000 | 144 | #define MAC_CSR0 0x3000 |
145 | #define MAC_CSR0_REVISION FIELD32(0x0000000f) | ||
146 | #define MAC_CSR0_CHIPSET FIELD32(0x000ffff0) | ||
145 | 147 | ||
146 | /* | 148 | /* |
147 | * MAC_CSR1: System control register. | 149 | * MAC_CSR1: System control register. |
diff --git a/drivers/net/wireless/rtl818x/rtl8180.h b/drivers/net/wireless/rtl818x/rtl8180.h index 8721282a8185..de3844fe06d8 100644 --- a/drivers/net/wireless/rtl818x/rtl8180.h +++ b/drivers/net/wireless/rtl818x/rtl8180.h | |||
@@ -60,7 +60,6 @@ struct rtl8180_priv { | |||
60 | struct rtl818x_csr __iomem *map; | 60 | struct rtl818x_csr __iomem *map; |
61 | const struct rtl818x_rf_ops *rf; | 61 | const struct rtl818x_rf_ops *rf; |
62 | struct ieee80211_vif *vif; | 62 | struct ieee80211_vif *vif; |
63 | int mode; | ||
64 | 63 | ||
65 | /* rtl8180 driver specific */ | 64 | /* rtl8180 driver specific */ |
66 | spinlock_t lock; | 65 | spinlock_t lock; |
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 8a40a1439984..109ab1baf625 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c | |||
@@ -82,8 +82,6 @@ static const struct ieee80211_channel rtl818x_channels[] = { | |||
82 | }; | 82 | }; |
83 | 83 | ||
84 | 84 | ||
85 | |||
86 | |||
87 | void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) | 85 | void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) |
88 | { | 86 | { |
89 | struct rtl8180_priv *priv = dev->priv; | 87 | struct rtl8180_priv *priv = dev->priv; |
@@ -615,7 +613,6 @@ static int rtl8180_start(struct ieee80211_hw *dev) | |||
615 | reg |= RTL818X_CMD_TX_ENABLE; | 613 | reg |= RTL818X_CMD_TX_ENABLE; |
616 | rtl818x_iowrite8(priv, &priv->map->CMD, reg); | 614 | rtl818x_iowrite8(priv, &priv->map->CMD, reg); |
617 | 615 | ||
618 | priv->mode = NL80211_IFTYPE_MONITOR; | ||
619 | return 0; | 616 | return 0; |
620 | 617 | ||
621 | err_free_rings: | 618 | err_free_rings: |
@@ -633,8 +630,6 @@ static void rtl8180_stop(struct ieee80211_hw *dev) | |||
633 | u8 reg; | 630 | u8 reg; |
634 | int i; | 631 | int i; |
635 | 632 | ||
636 | priv->mode = NL80211_IFTYPE_UNSPECIFIED; | ||
637 | |||
638 | rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); | 633 | rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); |
639 | 634 | ||
640 | reg = rtl818x_ioread8(priv, &priv->map->CMD); | 635 | reg = rtl818x_ioread8(priv, &priv->map->CMD); |
@@ -657,38 +652,39 @@ static void rtl8180_stop(struct ieee80211_hw *dev) | |||
657 | } | 652 | } |
658 | 653 | ||
659 | static int rtl8180_add_interface(struct ieee80211_hw *dev, | 654 | static int rtl8180_add_interface(struct ieee80211_hw *dev, |
660 | struct ieee80211_if_init_conf *conf) | 655 | struct ieee80211_vif *vif) |
661 | { | 656 | { |
662 | struct rtl8180_priv *priv = dev->priv; | 657 | struct rtl8180_priv *priv = dev->priv; |
663 | 658 | ||
664 | if (priv->mode != NL80211_IFTYPE_MONITOR) | 659 | /* |
665 | return -EOPNOTSUPP; | 660 | * We only support one active interface at a time. |
661 | */ | ||
662 | if (priv->vif) | ||
663 | return -EBUSY; | ||
666 | 664 | ||
667 | switch (conf->type) { | 665 | switch (vif->type) { |
668 | case NL80211_IFTYPE_STATION: | 666 | case NL80211_IFTYPE_STATION: |
669 | priv->mode = conf->type; | ||
670 | break; | 667 | break; |
671 | default: | 668 | default: |
672 | return -EOPNOTSUPP; | 669 | return -EOPNOTSUPP; |
673 | } | 670 | } |
674 | 671 | ||
675 | priv->vif = conf->vif; | 672 | priv->vif = vif; |
676 | 673 | ||
677 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); | 674 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); |
678 | rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0], | 675 | rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0], |
679 | le32_to_cpu(*(__le32 *)conf->mac_addr)); | 676 | le32_to_cpu(*(__le32 *)vif->addr)); |
680 | rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->MAC[4], | 677 | rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->MAC[4], |
681 | le16_to_cpu(*(__le16 *)(conf->mac_addr + 4))); | 678 | le16_to_cpu(*(__le16 *)(vif->addr + 4))); |
682 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | 679 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); |
683 | 680 | ||
684 | return 0; | 681 | return 0; |
685 | } | 682 | } |
686 | 683 | ||
687 | static void rtl8180_remove_interface(struct ieee80211_hw *dev, | 684 | static void rtl8180_remove_interface(struct ieee80211_hw *dev, |
688 | struct ieee80211_if_init_conf *conf) | 685 | struct ieee80211_vif *vif) |
689 | { | 686 | { |
690 | struct rtl8180_priv *priv = dev->priv; | 687 | struct rtl8180_priv *priv = dev->priv; |
691 | priv->mode = NL80211_IFTYPE_MONITOR; | ||
692 | priv->vif = NULL; | 688 | priv->vif = NULL; |
693 | } | 689 | } |
694 | 690 | ||
@@ -765,6 +761,14 @@ static void rtl8180_configure_filter(struct ieee80211_hw *dev, | |||
765 | rtl818x_iowrite32(priv, &priv->map->RX_CONF, priv->rx_conf); | 761 | rtl818x_iowrite32(priv, &priv->map->RX_CONF, priv->rx_conf); |
766 | } | 762 | } |
767 | 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 | |||
768 | static const struct ieee80211_ops rtl8180_ops = { | 772 | static const struct ieee80211_ops rtl8180_ops = { |
769 | .tx = rtl8180_tx, | 773 | .tx = rtl8180_tx, |
770 | .start = rtl8180_start, | 774 | .start = rtl8180_start, |
@@ -775,6 +779,7 @@ static const struct ieee80211_ops rtl8180_ops = { | |||
775 | .bss_info_changed = rtl8180_bss_info_changed, | 779 | .bss_info_changed = rtl8180_bss_info_changed, |
776 | .prepare_multicast = rtl8180_prepare_multicast, | 780 | .prepare_multicast = rtl8180_prepare_multicast, |
777 | .configure_filter = rtl8180_configure_filter, | 781 | .configure_filter = rtl8180_configure_filter, |
782 | .get_tsf = rtl8180_get_tsf, | ||
778 | }; | 783 | }; |
779 | 784 | ||
780 | 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.h b/drivers/net/wireless/rtl818x/rtl8187.h index 6af0f3f71f3a..6bb32112e65c 100644 --- a/drivers/net/wireless/rtl818x/rtl8187.h +++ b/drivers/net/wireless/rtl818x/rtl8187.h | |||
@@ -92,7 +92,7 @@ struct rtl8187_priv { | |||
92 | struct rtl818x_csr *map; | 92 | struct rtl818x_csr *map; |
93 | const struct rtl818x_rf_ops *rf; | 93 | const struct rtl818x_rf_ops *rf; |
94 | struct ieee80211_vif *vif; | 94 | struct ieee80211_vif *vif; |
95 | int mode; | 95 | |
96 | /* The mutex protects the TX loopback state. | 96 | /* The mutex protects the TX loopback state. |
97 | * Any attempt to set channels concurrently locks the device. | 97 | * Any attempt to set channels concurrently locks the device. |
98 | */ | 98 | */ |
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 7ba3052b0708..0fb850e0c656 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c | |||
@@ -1019,31 +1019,30 @@ static void rtl8187_stop(struct ieee80211_hw *dev) | |||
1019 | } | 1019 | } |
1020 | 1020 | ||
1021 | static int rtl8187_add_interface(struct ieee80211_hw *dev, | 1021 | static int rtl8187_add_interface(struct ieee80211_hw *dev, |
1022 | struct ieee80211_if_init_conf *conf) | 1022 | struct ieee80211_vif *vif) |
1023 | { | 1023 | { |
1024 | struct rtl8187_priv *priv = dev->priv; | 1024 | struct rtl8187_priv *priv = dev->priv; |
1025 | int i; | 1025 | int i; |
1026 | int ret = -EOPNOTSUPP; | 1026 | int ret = -EOPNOTSUPP; |
1027 | 1027 | ||
1028 | mutex_lock(&priv->conf_mutex); | 1028 | mutex_lock(&priv->conf_mutex); |
1029 | if (priv->mode != NL80211_IFTYPE_MONITOR) | 1029 | if (priv->vif) |
1030 | goto exit; | 1030 | goto exit; |
1031 | 1031 | ||
1032 | switch (conf->type) { | 1032 | switch (vif->type) { |
1033 | case NL80211_IFTYPE_STATION: | 1033 | case NL80211_IFTYPE_STATION: |
1034 | priv->mode = conf->type; | ||
1035 | break; | 1034 | break; |
1036 | default: | 1035 | default: |
1037 | goto exit; | 1036 | goto exit; |
1038 | } | 1037 | } |
1039 | 1038 | ||
1040 | ret = 0; | 1039 | ret = 0; |
1041 | priv->vif = conf->vif; | 1040 | priv->vif = vif; |
1042 | 1041 | ||
1043 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); | 1042 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); |
1044 | for (i = 0; i < ETH_ALEN; i++) | 1043 | for (i = 0; i < ETH_ALEN; i++) |
1045 | rtl818x_iowrite8(priv, &priv->map->MAC[i], | 1044 | rtl818x_iowrite8(priv, &priv->map->MAC[i], |
1046 | ((u8 *)conf->mac_addr)[i]); | 1045 | ((u8 *)vif->addr)[i]); |
1047 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | 1046 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); |
1048 | 1047 | ||
1049 | exit: | 1048 | exit: |
@@ -1052,11 +1051,10 @@ exit: | |||
1052 | } | 1051 | } |
1053 | 1052 | ||
1054 | static void rtl8187_remove_interface(struct ieee80211_hw *dev, | 1053 | static void rtl8187_remove_interface(struct ieee80211_hw *dev, |
1055 | struct ieee80211_if_init_conf *conf) | 1054 | struct ieee80211_vif *vif) |
1056 | { | 1055 | { |
1057 | struct rtl8187_priv *priv = dev->priv; | 1056 | struct rtl8187_priv *priv = dev->priv; |
1058 | mutex_lock(&priv->conf_mutex); | 1057 | mutex_lock(&priv->conf_mutex); |
1059 | priv->mode = NL80211_IFTYPE_MONITOR; | ||
1060 | priv->vif = NULL; | 1058 | priv->vif = NULL; |
1061 | mutex_unlock(&priv->conf_mutex); | 1059 | mutex_unlock(&priv->conf_mutex); |
1062 | } | 1060 | } |
@@ -1268,6 +1266,14 @@ static int rtl8187_conf_tx(struct ieee80211_hw *dev, u16 queue, | |||
1268 | return 0; | 1266 | return 0; |
1269 | } | 1267 | } |
1270 | 1268 | ||
1269 | static u64 rtl8187_get_tsf(struct ieee80211_hw *dev) | ||
1270 | { | ||
1271 | struct rtl8187_priv *priv = dev->priv; | ||
1272 | |||
1273 | return rtl818x_ioread32(priv, &priv->map->TSFT[0]) | | ||
1274 | (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32; | ||
1275 | } | ||
1276 | |||
1271 | static const struct ieee80211_ops rtl8187_ops = { | 1277 | static const struct ieee80211_ops rtl8187_ops = { |
1272 | .tx = rtl8187_tx, | 1278 | .tx = rtl8187_tx, |
1273 | .start = rtl8187_start, | 1279 | .start = rtl8187_start, |
@@ -1279,7 +1285,8 @@ static const struct ieee80211_ops rtl8187_ops = { | |||
1279 | .prepare_multicast = rtl8187_prepare_multicast, | 1285 | .prepare_multicast = rtl8187_prepare_multicast, |
1280 | .configure_filter = rtl8187_configure_filter, | 1286 | .configure_filter = rtl8187_configure_filter, |
1281 | .conf_tx = rtl8187_conf_tx, | 1287 | .conf_tx = rtl8187_conf_tx, |
1282 | .rfkill_poll = rtl8187_rfkill_poll | 1288 | .rfkill_poll = rtl8187_rfkill_poll, |
1289 | .get_tsf = rtl8187_get_tsf, | ||
1283 | }; | 1290 | }; |
1284 | 1291 | ||
1285 | static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom) | 1292 | static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom) |
@@ -1366,7 +1373,6 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
1366 | dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; | 1373 | dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; |
1367 | 1374 | ||
1368 | 1375 | ||
1369 | priv->mode = NL80211_IFTYPE_MONITOR; | ||
1370 | dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | 1376 | dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | |
1371 | IEEE80211_HW_SIGNAL_DBM | | 1377 | IEEE80211_HW_SIGNAL_DBM | |
1372 | IEEE80211_HW_RX_INCLUDES_FCS; | 1378 | IEEE80211_HW_RX_INCLUDES_FCS; |
diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.c b/drivers/net/wireless/rtl818x/rtl8187_leds.c index ded44c045eb2..4637337d5ce6 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_leds.c +++ b/drivers/net/wireless/rtl818x/rtl8187_leds.c | |||
@@ -33,7 +33,7 @@ static void led_turn_on(struct work_struct *work) | |||
33 | struct rtl8187_led *led = &priv->led_tx; | 33 | struct rtl8187_led *led = &priv->led_tx; |
34 | 34 | ||
35 | /* Don't change the LED, when the device is down. */ | 35 | /* Don't change the LED, when the device is down. */ |
36 | if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) | 36 | if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED) |
37 | return ; | 37 | return ; |
38 | 38 | ||
39 | /* Skip if the LED is not registered. */ | 39 | /* Skip if the LED is not registered. */ |
@@ -71,7 +71,7 @@ static void led_turn_off(struct work_struct *work) | |||
71 | struct rtl8187_led *led = &priv->led_tx; | 71 | struct rtl8187_led *led = &priv->led_tx; |
72 | 72 | ||
73 | /* Don't change the LED, when the device is down. */ | 73 | /* Don't change the LED, when the device is down. */ |
74 | if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) | 74 | if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED) |
75 | return ; | 75 | return ; |
76 | 76 | ||
77 | /* Skip if the LED is not registered. */ | 77 | /* Skip if the LED is not registered. */ |
@@ -241,5 +241,5 @@ void rtl8187_leds_exit(struct ieee80211_hw *dev) | |||
241 | cancel_delayed_work_sync(&priv->led_off); | 241 | cancel_delayed_work_sync(&priv->led_off); |
242 | cancel_delayed_work_sync(&priv->led_on); | 242 | cancel_delayed_work_sync(&priv->led_on); |
243 | } | 243 | } |
244 | #endif /* def CONFIG_RTL8187_LED */ | 244 | #endif /* def CONFIG_RTL8187_LEDS */ |
245 | 245 | ||
diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.h b/drivers/net/wireless/rtl818x/rtl8187_leds.h index efe8041bdda4..d743c96d4a20 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_leds.h +++ b/drivers/net/wireless/rtl818x/rtl8187_leds.h | |||
@@ -54,6 +54,6 @@ struct rtl8187_led { | |||
54 | void rtl8187_leds_init(struct ieee80211_hw *dev, u16 code); | 54 | void rtl8187_leds_init(struct ieee80211_hw *dev, u16 code); |
55 | void rtl8187_leds_exit(struct ieee80211_hw *dev); | 55 | void rtl8187_leds_exit(struct ieee80211_hw *dev); |
56 | 56 | ||
57 | #endif /* def CONFIG_RTL8187_LED */ | 57 | #endif /* def CONFIG_RTL8187_LEDS */ |
58 | 58 | ||
59 | #endif /* RTL8187_LED_H */ | 59 | #endif /* RTL8187_LED_H */ |
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile index 62e37ad01cc0..f47ec94c16dc 100644 --- a/drivers/net/wireless/wl12xx/Makefile +++ b/drivers/net/wireless/wl12xx/Makefile | |||
@@ -10,5 +10,7 @@ obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o | |||
10 | wl1271-objs = wl1271_main.o wl1271_spi.o wl1271_cmd.o \ | 10 | wl1271-objs = wl1271_main.o wl1271_spi.o wl1271_cmd.o \ |
11 | wl1271_event.o wl1271_tx.o wl1271_rx.o \ | 11 | wl1271_event.o wl1271_tx.o wl1271_rx.o \ |
12 | wl1271_ps.o wl1271_acx.o wl1271_boot.o \ | 12 | wl1271_ps.o wl1271_acx.o wl1271_boot.o \ |
13 | wl1271_init.o wl1271_debugfs.o | 13 | wl1271_init.o wl1271_debugfs.o wl1271_io.o |
14 | |||
15 | wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o | ||
14 | obj-$(CONFIG_WL1271) += wl1271.o | 16 | obj-$(CONFIG_WL1271) += wl1271.o |
diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h index 054533f7a124..37c61c19cae5 100644 --- a/drivers/net/wireless/wl12xx/wl1251.h +++ b/drivers/net/wireless/wl12xx/wl1251.h | |||
@@ -247,6 +247,7 @@ struct wl1251_debugfs { | |||
247 | struct dentry *rxpipe_tx_xfr_host_int_trig_rx_data; | 247 | struct dentry *rxpipe_tx_xfr_host_int_trig_rx_data; |
248 | 248 | ||
249 | struct dentry *tx_queue_len; | 249 | struct dentry *tx_queue_len; |
250 | struct dentry *tx_queue_status; | ||
250 | 251 | ||
251 | struct dentry *retry_count; | 252 | struct dentry *retry_count; |
252 | struct dentry *excessive_retries; | 253 | struct dentry *excessive_retries; |
@@ -340,9 +341,6 @@ struct wl1251 { | |||
340 | /* Are we currently scanning */ | 341 | /* Are we currently scanning */ |
341 | bool scanning; | 342 | bool scanning; |
342 | 343 | ||
343 | /* Our association ID */ | ||
344 | u16 aid; | ||
345 | |||
346 | /* Default key (for WEP) */ | 344 | /* Default key (for WEP) */ |
347 | u32 default_key; | 345 | u32 default_key; |
348 | 346 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.c b/drivers/net/wireless/wl12xx/wl1251_acx.c index acfa086dbfc5..beff084040b5 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.c +++ b/drivers/net/wireless/wl12xx/wl1251_acx.c | |||
@@ -976,3 +976,72 @@ out: | |||
976 | kfree(acx); | 976 | kfree(acx); |
977 | return ret; | 977 | return ret; |
978 | } | 978 | } |
979 | |||
980 | int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max, | ||
981 | u8 aifs, u16 txop) | ||
982 | { | ||
983 | struct wl1251_acx_ac_cfg *acx; | ||
984 | int ret = 0; | ||
985 | |||
986 | wl1251_debug(DEBUG_ACX, "acx ac cfg %d cw_ming %d cw_max %d " | ||
987 | "aifs %d txop %d", ac, cw_min, cw_max, aifs, txop); | ||
988 | |||
989 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
990 | |||
991 | if (!acx) { | ||
992 | ret = -ENOMEM; | ||
993 | goto out; | ||
994 | } | ||
995 | |||
996 | acx->ac = ac; | ||
997 | acx->cw_min = cw_min; | ||
998 | acx->cw_max = cw_max; | ||
999 | acx->aifsn = aifs; | ||
1000 | acx->txop_limit = txop; | ||
1001 | |||
1002 | ret = wl1251_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx)); | ||
1003 | if (ret < 0) { | ||
1004 | wl1251_warning("acx ac cfg failed: %d", ret); | ||
1005 | goto out; | ||
1006 | } | ||
1007 | |||
1008 | out: | ||
1009 | kfree(acx); | ||
1010 | return ret; | ||
1011 | } | ||
1012 | |||
1013 | int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue, | ||
1014 | enum wl1251_acx_channel_type type, | ||
1015 | u8 tsid, enum wl1251_acx_ps_scheme ps_scheme, | ||
1016 | enum wl1251_acx_ack_policy ack_policy) | ||
1017 | { | ||
1018 | struct wl1251_acx_tid_cfg *acx; | ||
1019 | int ret = 0; | ||
1020 | |||
1021 | wl1251_debug(DEBUG_ACX, "acx tid cfg %d type %d tsid %d " | ||
1022 | "ps_scheme %d ack_policy %d", queue, type, tsid, | ||
1023 | ps_scheme, ack_policy); | ||
1024 | |||
1025 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1026 | |||
1027 | if (!acx) { | ||
1028 | ret = -ENOMEM; | ||
1029 | goto out; | ||
1030 | } | ||
1031 | |||
1032 | acx->queue = queue; | ||
1033 | acx->type = type; | ||
1034 | acx->tsid = tsid; | ||
1035 | acx->ps_scheme = ps_scheme; | ||
1036 | acx->ack_policy = ack_policy; | ||
1037 | |||
1038 | ret = wl1251_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx)); | ||
1039 | if (ret < 0) { | ||
1040 | wl1251_warning("acx tid cfg failed: %d", ret); | ||
1041 | goto out; | ||
1042 | } | ||
1043 | |||
1044 | out: | ||
1045 | kfree(acx); | ||
1046 | return ret; | ||
1047 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.h b/drivers/net/wireless/wl12xx/wl1251_acx.h index 652371432cd8..26160c45784c 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.h +++ b/drivers/net/wireless/wl12xx/wl1251_acx.h | |||
@@ -1166,6 +1166,87 @@ struct wl1251_acx_wr_tbtt_and_dtim { | |||
1166 | u8 padding; | 1166 | u8 padding; |
1167 | } __attribute__ ((packed)); | 1167 | } __attribute__ ((packed)); |
1168 | 1168 | ||
1169 | struct wl1251_acx_ac_cfg { | ||
1170 | struct acx_header header; | ||
1171 | |||
1172 | /* | ||
1173 | * Access Category - The TX queue's access category | ||
1174 | * (refer to AccessCategory_enum) | ||
1175 | */ | ||
1176 | u8 ac; | ||
1177 | |||
1178 | /* | ||
1179 | * The contention window minimum size (in slots) for | ||
1180 | * the access class. | ||
1181 | */ | ||
1182 | u8 cw_min; | ||
1183 | |||
1184 | /* | ||
1185 | * The contention window maximum size (in slots) for | ||
1186 | * the access class. | ||
1187 | */ | ||
1188 | u16 cw_max; | ||
1189 | |||
1190 | /* The AIF value (in slots) for the access class. */ | ||
1191 | u8 aifsn; | ||
1192 | |||
1193 | u8 reserved; | ||
1194 | |||
1195 | /* The TX Op Limit (in microseconds) for the access class. */ | ||
1196 | u16 txop_limit; | ||
1197 | } __attribute__ ((packed)); | ||
1198 | |||
1199 | |||
1200 | enum wl1251_acx_channel_type { | ||
1201 | CHANNEL_TYPE_DCF = 0, | ||
1202 | CHANNEL_TYPE_EDCF = 1, | ||
1203 | CHANNEL_TYPE_HCCA = 2, | ||
1204 | }; | ||
1205 | |||
1206 | enum wl1251_acx_ps_scheme { | ||
1207 | /* regular ps: simple sending of packets */ | ||
1208 | WL1251_ACX_PS_SCHEME_LEGACY = 0, | ||
1209 | |||
1210 | /* sending a packet triggers a unscheduled apsd downstream */ | ||
1211 | WL1251_ACX_PS_SCHEME_UPSD_TRIGGER = 1, | ||
1212 | |||
1213 | /* a pspoll packet will be sent before every data packet */ | ||
1214 | WL1251_ACX_PS_SCHEME_LEGACY_PSPOLL = 2, | ||
1215 | |||
1216 | /* scheduled apsd mode */ | ||
1217 | WL1251_ACX_PS_SCHEME_SAPSD = 3, | ||
1218 | }; | ||
1219 | |||
1220 | enum wl1251_acx_ack_policy { | ||
1221 | WL1251_ACX_ACK_POLICY_LEGACY = 0, | ||
1222 | WL1251_ACX_ACK_POLICY_NO_ACK = 1, | ||
1223 | WL1251_ACX_ACK_POLICY_BLOCK = 2, | ||
1224 | }; | ||
1225 | |||
1226 | struct wl1251_acx_tid_cfg { | ||
1227 | struct acx_header header; | ||
1228 | |||
1229 | /* tx queue id number (0-7) */ | ||
1230 | u8 queue; | ||
1231 | |||
1232 | /* channel access type for the queue, enum wl1251_acx_channel_type */ | ||
1233 | u8 type; | ||
1234 | |||
1235 | /* EDCA: ac index (0-3), HCCA: traffic stream id (8-15) */ | ||
1236 | u8 tsid; | ||
1237 | |||
1238 | /* ps scheme of the specified queue, enum wl1251_acx_ps_scheme */ | ||
1239 | u8 ps_scheme; | ||
1240 | |||
1241 | /* the tx queue ack policy, enum wl1251_acx_ack_policy */ | ||
1242 | u8 ack_policy; | ||
1243 | |||
1244 | u8 padding[3]; | ||
1245 | |||
1246 | /* not supported */ | ||
1247 | u32 apsdconf[2]; | ||
1248 | } __attribute__ ((packed)); | ||
1249 | |||
1169 | /************************************************************************* | 1250 | /************************************************************************* |
1170 | 1251 | ||
1171 | Host Interrupt Register (WiLink -> Host) | 1252 | Host Interrupt Register (WiLink -> Host) |
@@ -1322,5 +1403,11 @@ int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime); | |||
1322 | int wl1251_acx_rate_policies(struct wl1251 *wl); | 1403 | int wl1251_acx_rate_policies(struct wl1251 *wl); |
1323 | int wl1251_acx_mem_cfg(struct wl1251 *wl); | 1404 | int wl1251_acx_mem_cfg(struct wl1251 *wl); |
1324 | int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim); | 1405 | int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim); |
1406 | int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max, | ||
1407 | u8 aifs, u16 txop); | ||
1408 | int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue, | ||
1409 | enum wl1251_acx_channel_type type, | ||
1410 | u8 tsid, enum wl1251_acx_ps_scheme ps_scheme, | ||
1411 | enum wl1251_acx_ack_policy ack_policy); | ||
1325 | 1412 | ||
1326 | #endif /* __WL1251_ACX_H__ */ | 1413 | #endif /* __WL1251_ACX_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.c b/drivers/net/wireless/wl12xx/wl1251_cmd.c index 770f260726bd..0320b478bb3f 100644 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1251_cmd.c | |||
@@ -410,3 +410,86 @@ out: | |||
410 | kfree(cmd); | 410 | kfree(cmd); |
411 | return ret; | 411 | return ret; |
412 | } | 412 | } |
413 | |||
414 | int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len, | ||
415 | struct ieee80211_channel *channels[], | ||
416 | unsigned int n_channels, unsigned int n_probes) | ||
417 | { | ||
418 | struct wl1251_cmd_scan *cmd; | ||
419 | int i, ret = 0; | ||
420 | |||
421 | wl1251_debug(DEBUG_CMD, "cmd scan"); | ||
422 | |||
423 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
424 | if (!cmd) | ||
425 | return -ENOMEM; | ||
426 | |||
427 | cmd->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD); | ||
428 | cmd->params.rx_filter_options = cpu_to_le32(CFG_RX_PRSP_EN | | ||
429 | CFG_RX_MGMT_EN | | ||
430 | CFG_RX_BCN_EN); | ||
431 | cmd->params.scan_options = 0; | ||
432 | cmd->params.num_channels = n_channels; | ||
433 | cmd->params.num_probe_requests = n_probes; | ||
434 | cmd->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */ | ||
435 | cmd->params.tid_trigger = 0; | ||
436 | |||
437 | for (i = 0; i < n_channels; i++) { | ||
438 | cmd->channels[i].min_duration = | ||
439 | cpu_to_le32(WL1251_SCAN_MIN_DURATION); | ||
440 | cmd->channels[i].max_duration = | ||
441 | cpu_to_le32(WL1251_SCAN_MAX_DURATION); | ||
442 | memset(&cmd->channels[i].bssid_lsb, 0xff, 4); | ||
443 | memset(&cmd->channels[i].bssid_msb, 0xff, 2); | ||
444 | cmd->channels[i].early_termination = 0; | ||
445 | cmd->channels[i].tx_power_att = 0; | ||
446 | cmd->channels[i].channel = channels[i]->hw_value; | ||
447 | } | ||
448 | |||
449 | cmd->params.ssid_len = ssid_len; | ||
450 | if (ssid) | ||
451 | memcpy(cmd->params.ssid, ssid, ssid_len); | ||
452 | |||
453 | ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd)); | ||
454 | if (ret < 0) { | ||
455 | wl1251_error("cmd scan failed: %d", ret); | ||
456 | goto out; | ||
457 | } | ||
458 | |||
459 | wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd)); | ||
460 | |||
461 | if (cmd->header.status != CMD_STATUS_SUCCESS) { | ||
462 | wl1251_error("cmd scan status wasn't success: %d", | ||
463 | cmd->header.status); | ||
464 | ret = -EIO; | ||
465 | goto out; | ||
466 | } | ||
467 | |||
468 | out: | ||
469 | kfree(cmd); | ||
470 | return ret; | ||
471 | } | ||
472 | |||
473 | int wl1251_cmd_trigger_scan_to(struct wl1251 *wl, u32 timeout) | ||
474 | { | ||
475 | struct wl1251_cmd_trigger_scan_to *cmd; | ||
476 | int ret; | ||
477 | |||
478 | wl1251_debug(DEBUG_CMD, "cmd trigger scan to"); | ||
479 | |||
480 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
481 | if (!cmd) | ||
482 | return -ENOMEM; | ||
483 | |||
484 | cmd->timeout = timeout; | ||
485 | |||
486 | ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd)); | ||
487 | if (ret < 0) { | ||
488 | wl1251_error("cmd trigger scan to failed: %d", ret); | ||
489 | goto out; | ||
490 | } | ||
491 | |||
492 | out: | ||
493 | kfree(cmd); | ||
494 | return ret; | ||
495 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.h b/drivers/net/wireless/wl12xx/wl1251_cmd.h index dff798ad0ef5..4ad67cae94d2 100644 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1251_cmd.h | |||
@@ -27,6 +27,8 @@ | |||
27 | 27 | ||
28 | #include "wl1251.h" | 28 | #include "wl1251.h" |
29 | 29 | ||
30 | #include <net/cfg80211.h> | ||
31 | |||
30 | struct acx_header; | 32 | struct acx_header; |
31 | 33 | ||
32 | int wl1251_cmd_send(struct wl1251 *wl, u16 type, void *buf, size_t buf_len); | 34 | int wl1251_cmd_send(struct wl1251 *wl, u16 type, void *buf, size_t buf_len); |
@@ -43,6 +45,10 @@ int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer, | |||
43 | size_t len); | 45 | size_t len); |
44 | int wl1251_cmd_template_set(struct wl1251 *wl, u16 cmd_id, | 46 | int wl1251_cmd_template_set(struct wl1251 *wl, u16 cmd_id, |
45 | void *buf, size_t buf_len); | 47 | void *buf, size_t buf_len); |
48 | int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len, | ||
49 | struct ieee80211_channel *channels[], | ||
50 | unsigned int n_channels, unsigned int n_probes); | ||
51 | int wl1251_cmd_trigger_scan_to(struct wl1251 *wl, u32 timeout); | ||
46 | 52 | ||
47 | /* unit ms */ | 53 | /* unit ms */ |
48 | #define WL1251_COMMAND_TIMEOUT 2000 | 54 | #define WL1251_COMMAND_TIMEOUT 2000 |
@@ -163,8 +169,12 @@ struct cmd_read_write_memory { | |||
163 | #define CMDMBOX_HEADER_LEN 4 | 169 | #define CMDMBOX_HEADER_LEN 4 |
164 | #define CMDMBOX_INFO_ELEM_HEADER_LEN 4 | 170 | #define CMDMBOX_INFO_ELEM_HEADER_LEN 4 |
165 | 171 | ||
172 | #define WL1251_SCAN_MIN_DURATION 30000 | ||
173 | #define WL1251_SCAN_MAX_DURATION 60000 | ||
174 | |||
175 | #define WL1251_SCAN_NUM_PROBES 3 | ||
166 | 176 | ||
167 | struct basic_scan_parameters { | 177 | struct wl1251_scan_parameters { |
168 | u32 rx_config_options; | 178 | u32 rx_config_options; |
169 | u32 rx_filter_options; | 179 | u32 rx_filter_options; |
170 | 180 | ||
@@ -189,11 +199,11 @@ struct basic_scan_parameters { | |||
189 | 199 | ||
190 | u8 tid_trigger; | 200 | u8 tid_trigger; |
191 | u8 ssid_len; | 201 | u8 ssid_len; |
192 | u32 ssid[8]; | 202 | u8 ssid[32]; |
193 | 203 | ||
194 | } __attribute__ ((packed)); | 204 | } __attribute__ ((packed)); |
195 | 205 | ||
196 | struct basic_scan_channel_parameters { | 206 | struct wl1251_scan_ch_parameters { |
197 | u32 min_duration; /* in TU */ | 207 | u32 min_duration; /* in TU */ |
198 | u32 max_duration; /* in TU */ | 208 | u32 max_duration; /* in TU */ |
199 | u32 bssid_lsb; | 209 | u32 bssid_lsb; |
@@ -213,11 +223,11 @@ struct basic_scan_channel_parameters { | |||
213 | /* SCAN parameters */ | 223 | /* SCAN parameters */ |
214 | #define SCAN_MAX_NUM_OF_CHANNELS 16 | 224 | #define SCAN_MAX_NUM_OF_CHANNELS 16 |
215 | 225 | ||
216 | struct cmd_scan { | 226 | struct wl1251_cmd_scan { |
217 | struct wl1251_cmd_header header; | 227 | struct wl1251_cmd_header header; |
218 | 228 | ||
219 | struct basic_scan_parameters params; | 229 | struct wl1251_scan_parameters params; |
220 | struct basic_scan_channel_parameters channels[SCAN_MAX_NUM_OF_CHANNELS]; | 230 | struct wl1251_scan_ch_parameters channels[SCAN_MAX_NUM_OF_CHANNELS]; |
221 | } __attribute__ ((packed)); | 231 | } __attribute__ ((packed)); |
222 | 232 | ||
223 | enum { | 233 | enum { |
diff --git a/drivers/net/wireless/wl12xx/wl1251_debugfs.c b/drivers/net/wireless/wl12xx/wl1251_debugfs.c index a00723059f83..0ccba57fb9fb 100644 --- a/drivers/net/wireless/wl12xx/wl1251_debugfs.c +++ b/drivers/net/wireless/wl12xx/wl1251_debugfs.c | |||
@@ -237,6 +237,27 @@ static const struct file_operations tx_queue_len_ops = { | |||
237 | .open = wl1251_open_file_generic, | 237 | .open = wl1251_open_file_generic, |
238 | }; | 238 | }; |
239 | 239 | ||
240 | static ssize_t tx_queue_status_read(struct file *file, char __user *userbuf, | ||
241 | size_t count, loff_t *ppos) | ||
242 | { | ||
243 | struct wl1251 *wl = file->private_data; | ||
244 | char buf[3], status; | ||
245 | int len; | ||
246 | |||
247 | if (wl->tx_queue_stopped) | ||
248 | status = 's'; | ||
249 | else | ||
250 | status = 'r'; | ||
251 | |||
252 | len = scnprintf(buf, sizeof(buf), "%c\n", status); | ||
253 | return simple_read_from_buffer(userbuf, count, ppos, buf, len); | ||
254 | } | ||
255 | |||
256 | static const struct file_operations tx_queue_status_ops = { | ||
257 | .read = tx_queue_status_read, | ||
258 | .open = wl1251_open_file_generic, | ||
259 | }; | ||
260 | |||
240 | static void wl1251_debugfs_delete_files(struct wl1251 *wl) | 261 | static void wl1251_debugfs_delete_files(struct wl1251 *wl) |
241 | { | 262 | { |
242 | DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); | 263 | DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); |
@@ -331,6 +352,7 @@ static void wl1251_debugfs_delete_files(struct wl1251 *wl) | |||
331 | DEBUGFS_FWSTATS_DEL(rxpipe, tx_xfr_host_int_trig_rx_data); | 352 | DEBUGFS_FWSTATS_DEL(rxpipe, tx_xfr_host_int_trig_rx_data); |
332 | 353 | ||
333 | DEBUGFS_DEL(tx_queue_len); | 354 | DEBUGFS_DEL(tx_queue_len); |
355 | DEBUGFS_DEL(tx_queue_status); | ||
334 | DEBUGFS_DEL(retry_count); | 356 | DEBUGFS_DEL(retry_count); |
335 | DEBUGFS_DEL(excessive_retries); | 357 | DEBUGFS_DEL(excessive_retries); |
336 | } | 358 | } |
@@ -431,6 +453,7 @@ static int wl1251_debugfs_add_files(struct wl1251 *wl) | |||
431 | DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); | 453 | DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); |
432 | 454 | ||
433 | DEBUGFS_ADD(tx_queue_len, wl->debugfs.rootdir); | 455 | DEBUGFS_ADD(tx_queue_len, wl->debugfs.rootdir); |
456 | DEBUGFS_ADD(tx_queue_status, wl->debugfs.rootdir); | ||
434 | DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); | 457 | DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); |
435 | DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); | 458 | DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); |
436 | 459 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_init.c b/drivers/net/wireless/wl12xx/wl1251_init.c index 5cb573383eeb..5aad56ea7153 100644 --- a/drivers/net/wireless/wl12xx/wl1251_init.c +++ b/drivers/net/wireless/wl12xx/wl1251_init.c | |||
@@ -294,6 +294,11 @@ static int wl1251_hw_init_tx_queue_config(struct wl1251 *wl) | |||
294 | goto out; | 294 | goto out; |
295 | } | 295 | } |
296 | 296 | ||
297 | wl1251_acx_ac_cfg(wl, AC_BE, CWMIN_BE, CWMAX_BE, AIFS_DIFS, TXOP_BE); | ||
298 | wl1251_acx_ac_cfg(wl, AC_BK, CWMIN_BK, CWMAX_BK, AIFS_DIFS, TXOP_BK); | ||
299 | wl1251_acx_ac_cfg(wl, AC_VI, CWMIN_VI, CWMAX_VI, AIFS_DIFS, TXOP_VI); | ||
300 | wl1251_acx_ac_cfg(wl, AC_VO, CWMIN_VO, CWMAX_VO, AIFS_DIFS, TXOP_VO); | ||
301 | |||
297 | out: | 302 | out: |
298 | kfree(config); | 303 | kfree(config); |
299 | return ret; | 304 | return ret; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_init.h b/drivers/net/wireless/wl12xx/wl1251_init.h index b3b25ec885ea..269cefb3e7d4 100644 --- a/drivers/net/wireless/wl12xx/wl1251_init.h +++ b/drivers/net/wireless/wl12xx/wl1251_init.h | |||
@@ -26,6 +26,53 @@ | |||
26 | 26 | ||
27 | #include "wl1251.h" | 27 | #include "wl1251.h" |
28 | 28 | ||
29 | enum { | ||
30 | /* best effort/legacy */ | ||
31 | AC_BE = 0, | ||
32 | |||
33 | /* background */ | ||
34 | AC_BK = 1, | ||
35 | |||
36 | /* video */ | ||
37 | AC_VI = 2, | ||
38 | |||
39 | /* voice */ | ||
40 | AC_VO = 3, | ||
41 | |||
42 | /* broadcast dummy access category */ | ||
43 | AC_BCAST = 4, | ||
44 | |||
45 | NUM_ACCESS_CATEGORIES = 4 | ||
46 | }; | ||
47 | |||
48 | /* following are defult values for the IE fields*/ | ||
49 | #define CWMIN_BK 15 | ||
50 | #define CWMIN_BE 15 | ||
51 | #define CWMIN_VI 7 | ||
52 | #define CWMIN_VO 3 | ||
53 | #define CWMAX_BK 1023 | ||
54 | #define CWMAX_BE 63 | ||
55 | #define CWMAX_VI 15 | ||
56 | #define CWMAX_VO 7 | ||
57 | |||
58 | /* slot number setting to start transmission at PIFS interval */ | ||
59 | #define AIFS_PIFS 1 | ||
60 | |||
61 | /* | ||
62 | * slot number setting to start transmission at DIFS interval - normal DCF | ||
63 | * access | ||
64 | */ | ||
65 | #define AIFS_DIFS 2 | ||
66 | |||
67 | #define AIFSN_BK 7 | ||
68 | #define AIFSN_BE 3 | ||
69 | #define AIFSN_VI AIFS_PIFS | ||
70 | #define AIFSN_VO AIFS_PIFS | ||
71 | #define TXOP_BK 0 | ||
72 | #define TXOP_BE 0 | ||
73 | #define TXOP_VI 3008 | ||
74 | #define TXOP_VO 1504 | ||
75 | |||
29 | int wl1251_hw_init_hwenc_config(struct wl1251 *wl); | 76 | int wl1251_hw_init_hwenc_config(struct wl1251 *wl); |
30 | int wl1251_hw_init_templates_config(struct wl1251 *wl); | 77 | int wl1251_hw_init_templates_config(struct wl1251 *wl); |
31 | int wl1251_hw_init_rx_config(struct wl1251 *wl, u32 config, u32 filter); | 78 | int wl1251_hw_init_rx_config(struct wl1251 *wl, u32 config, u32 filter); |
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 2f50a256efa5..24ae6a360ac8 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c | |||
@@ -395,6 +395,7 @@ static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
395 | * the queue here, otherwise the queue will get too long. | 395 | * the queue here, otherwise the queue will get too long. |
396 | */ | 396 | */ |
397 | if (skb_queue_len(&wl->tx_queue) >= WL1251_TX_QUEUE_MAX_LENGTH) { | 397 | if (skb_queue_len(&wl->tx_queue) >= WL1251_TX_QUEUE_MAX_LENGTH) { |
398 | wl1251_debug(DEBUG_TX, "op_tx: tx_queue full, stop queues"); | ||
398 | ieee80211_stop_queues(wl->hw); | 399 | ieee80211_stop_queues(wl->hw); |
399 | 400 | ||
400 | /* | 401 | /* |
@@ -510,13 +511,13 @@ static void wl1251_op_stop(struct ieee80211_hw *hw) | |||
510 | } | 511 | } |
511 | 512 | ||
512 | static int wl1251_op_add_interface(struct ieee80211_hw *hw, | 513 | static int wl1251_op_add_interface(struct ieee80211_hw *hw, |
513 | struct ieee80211_if_init_conf *conf) | 514 | struct ieee80211_vif *vif) |
514 | { | 515 | { |
515 | struct wl1251 *wl = hw->priv; | 516 | struct wl1251 *wl = hw->priv; |
516 | int ret = 0; | 517 | int ret = 0; |
517 | 518 | ||
518 | wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", | 519 | wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", |
519 | conf->type, conf->mac_addr); | 520 | vif->type, vif->addr); |
520 | 521 | ||
521 | mutex_lock(&wl->mutex); | 522 | mutex_lock(&wl->mutex); |
522 | if (wl->vif) { | 523 | if (wl->vif) { |
@@ -524,9 +525,9 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw, | |||
524 | goto out; | 525 | goto out; |
525 | } | 526 | } |
526 | 527 | ||
527 | wl->vif = conf->vif; | 528 | wl->vif = vif; |
528 | 529 | ||
529 | switch (conf->type) { | 530 | switch (vif->type) { |
530 | case NL80211_IFTYPE_STATION: | 531 | case NL80211_IFTYPE_STATION: |
531 | wl->bss_type = BSS_TYPE_STA_BSS; | 532 | wl->bss_type = BSS_TYPE_STA_BSS; |
532 | break; | 533 | break; |
@@ -538,8 +539,8 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw, | |||
538 | goto out; | 539 | goto out; |
539 | } | 540 | } |
540 | 541 | ||
541 | if (memcmp(wl->mac_addr, conf->mac_addr, ETH_ALEN)) { | 542 | if (memcmp(wl->mac_addr, vif->addr, ETH_ALEN)) { |
542 | memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); | 543 | memcpy(wl->mac_addr, vif->addr, ETH_ALEN); |
543 | SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); | 544 | SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); |
544 | ret = wl1251_acx_station_id(wl); | 545 | ret = wl1251_acx_station_id(wl); |
545 | if (ret < 0) | 546 | if (ret < 0) |
@@ -552,7 +553,7 @@ out: | |||
552 | } | 553 | } |
553 | 554 | ||
554 | static void wl1251_op_remove_interface(struct ieee80211_hw *hw, | 555 | static void wl1251_op_remove_interface(struct ieee80211_hw *hw, |
555 | struct ieee80211_if_init_conf *conf) | 556 | struct ieee80211_vif *vif) |
556 | { | 557 | { |
557 | struct wl1251 *wl = hw->priv; | 558 | struct wl1251 *wl = hw->priv; |
558 | 559 | ||
@@ -562,43 +563,25 @@ static void wl1251_op_remove_interface(struct ieee80211_hw *hw, | |||
562 | mutex_unlock(&wl->mutex); | 563 | mutex_unlock(&wl->mutex); |
563 | } | 564 | } |
564 | 565 | ||
565 | static int wl1251_build_null_data(struct wl1251 *wl) | 566 | static int wl1251_build_qos_null_data(struct wl1251 *wl) |
566 | { | 567 | { |
567 | struct wl12xx_null_data_template template; | 568 | struct ieee80211_qos_hdr template; |
568 | 569 | ||
569 | if (!is_zero_ether_addr(wl->bssid)) { | 570 | memset(&template, 0, sizeof(template)); |
570 | memcpy(template.header.da, wl->bssid, ETH_ALEN); | ||
571 | memcpy(template.header.bssid, wl->bssid, ETH_ALEN); | ||
572 | } else { | ||
573 | memset(template.header.da, 0xff, ETH_ALEN); | ||
574 | memset(template.header.bssid, 0xff, ETH_ALEN); | ||
575 | } | ||
576 | |||
577 | memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); | ||
578 | template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | | ||
579 | IEEE80211_STYPE_NULLFUNC | | ||
580 | IEEE80211_FCTL_TODS); | ||
581 | |||
582 | return wl1251_cmd_template_set(wl, CMD_NULL_DATA, &template, | ||
583 | sizeof(template)); | ||
584 | |||
585 | } | ||
586 | |||
587 | static int wl1251_build_ps_poll(struct wl1251 *wl, u16 aid) | ||
588 | { | ||
589 | struct wl12xx_ps_poll_template template; | ||
590 | 571 | ||
591 | memcpy(template.bssid, wl->bssid, ETH_ALEN); | 572 | memcpy(template.addr1, wl->bssid, ETH_ALEN); |
592 | memcpy(template.ta, wl->mac_addr, ETH_ALEN); | 573 | memcpy(template.addr2, wl->mac_addr, ETH_ALEN); |
574 | memcpy(template.addr3, wl->bssid, ETH_ALEN); | ||
593 | 575 | ||
594 | /* aid in PS-Poll has its two MSBs each set to 1 */ | 576 | template.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | |
595 | template.aid = cpu_to_le16(1 << 15 | 1 << 14 | aid); | 577 | IEEE80211_STYPE_QOS_NULLFUNC | |
578 | IEEE80211_FCTL_TODS); | ||
596 | 579 | ||
597 | template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); | 580 | /* FIXME: not sure what priority to use here */ |
581 | template.qos_ctrl = cpu_to_le16(0); | ||
598 | 582 | ||
599 | return wl1251_cmd_template_set(wl, CMD_PS_POLL, &template, | 583 | return wl1251_cmd_template_set(wl, CMD_QOS_NULL_DATA, &template, |
600 | sizeof(template)); | 584 | sizeof(template)); |
601 | |||
602 | } | 585 | } |
603 | 586 | ||
604 | static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) | 587 | static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) |
@@ -634,26 +617,34 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) | |||
634 | 617 | ||
635 | wl->psm_requested = true; | 618 | wl->psm_requested = true; |
636 | 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 | |||
637 | /* | 625 | /* |
638 | * We enter PSM only if we're already associated. | 626 | * mac80211 enables PSM only if we're already associated. |
639 | * If we're not, we'll enter it when joining an SSID, | ||
640 | * through the bss_info_changed() hook. | ||
641 | */ | 627 | */ |
642 | ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); | 628 | ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); |
629 | if (ret < 0) | ||
630 | goto out_sleep; | ||
643 | } else if (!(conf->flags & IEEE80211_CONF_PS) && | 631 | } else if (!(conf->flags & IEEE80211_CONF_PS) && |
644 | wl->psm_requested) { | 632 | wl->psm_requested) { |
645 | wl1251_debug(DEBUG_PSM, "psm disabled"); | 633 | wl1251_debug(DEBUG_PSM, "psm disabled"); |
646 | 634 | ||
647 | wl->psm_requested = false; | 635 | wl->psm_requested = false; |
648 | 636 | ||
649 | if (wl->psm) | 637 | if (wl->psm) { |
650 | ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); | 638 | ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); |
639 | if (ret < 0) | ||
640 | goto out_sleep; | ||
641 | } | ||
651 | } | 642 | } |
652 | 643 | ||
653 | if (conf->power_level != wl->power_level) { | 644 | if (conf->power_level != wl->power_level) { |
654 | ret = wl1251_acx_tx_power(wl, conf->power_level); | 645 | ret = wl1251_acx_tx_power(wl, conf->power_level); |
655 | if (ret < 0) | 646 | if (ret < 0) |
656 | goto out; | 647 | goto out_sleep; |
657 | 648 | ||
658 | wl->power_level = conf->power_level; | 649 | wl->power_level = conf->power_level; |
659 | } | 650 | } |
@@ -864,199 +855,61 @@ out: | |||
864 | return ret; | 855 | return ret; |
865 | } | 856 | } |
866 | 857 | ||
867 | static int wl1251_build_basic_rates(char *rates) | 858 | static int wl1251_op_hw_scan(struct ieee80211_hw *hw, |
868 | { | 859 | struct cfg80211_scan_request *req) |
869 | u8 index = 0; | ||
870 | |||
871 | rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; | ||
872 | rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; | ||
873 | rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; | ||
874 | rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; | ||
875 | |||
876 | return index; | ||
877 | } | ||
878 | |||
879 | static int wl1251_build_extended_rates(char *rates) | ||
880 | { | 860 | { |
881 | u8 index = 0; | 861 | struct wl1251 *wl = hw->priv; |
882 | 862 | struct sk_buff *skb; | |
883 | rates[index++] = IEEE80211_OFDM_RATE_6MB; | 863 | size_t ssid_len = 0; |
884 | rates[index++] = IEEE80211_OFDM_RATE_9MB; | 864 | u8 *ssid = NULL; |
885 | rates[index++] = IEEE80211_OFDM_RATE_12MB; | 865 | int ret; |
886 | rates[index++] = IEEE80211_OFDM_RATE_18MB; | ||
887 | rates[index++] = IEEE80211_OFDM_RATE_24MB; | ||
888 | rates[index++] = IEEE80211_OFDM_RATE_36MB; | ||
889 | rates[index++] = IEEE80211_OFDM_RATE_48MB; | ||
890 | rates[index++] = IEEE80211_OFDM_RATE_54MB; | ||
891 | |||
892 | return index; | ||
893 | } | ||
894 | |||
895 | 866 | ||
896 | static int wl1251_build_probe_req(struct wl1251 *wl, u8 *ssid, size_t ssid_len) | 867 | wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan"); |
897 | { | ||
898 | struct wl12xx_probe_req_template template; | ||
899 | struct wl12xx_ie_rates *rates; | ||
900 | char *ptr; | ||
901 | u16 size; | ||
902 | |||
903 | ptr = (char *)&template; | ||
904 | size = sizeof(struct ieee80211_header); | ||
905 | |||
906 | memset(template.header.da, 0xff, ETH_ALEN); | ||
907 | memset(template.header.bssid, 0xff, ETH_ALEN); | ||
908 | memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); | ||
909 | template.header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); | ||
910 | |||
911 | /* IEs */ | ||
912 | /* SSID */ | ||
913 | template.ssid.header.id = WLAN_EID_SSID; | ||
914 | template.ssid.header.len = ssid_len; | ||
915 | if (ssid_len && ssid) | ||
916 | memcpy(template.ssid.ssid, ssid, ssid_len); | ||
917 | size += sizeof(struct wl12xx_ie_header) + ssid_len; | ||
918 | ptr += size; | ||
919 | |||
920 | /* Basic Rates */ | ||
921 | rates = (struct wl12xx_ie_rates *)ptr; | ||
922 | rates->header.id = WLAN_EID_SUPP_RATES; | ||
923 | rates->header.len = wl1251_build_basic_rates(rates->rates); | ||
924 | size += sizeof(struct wl12xx_ie_header) + rates->header.len; | ||
925 | ptr += sizeof(struct wl12xx_ie_header) + rates->header.len; | ||
926 | |||
927 | /* Extended rates */ | ||
928 | rates = (struct wl12xx_ie_rates *)ptr; | ||
929 | rates->header.id = WLAN_EID_EXT_SUPP_RATES; | ||
930 | rates->header.len = wl1251_build_extended_rates(rates->rates); | ||
931 | size += sizeof(struct wl12xx_ie_header) + rates->header.len; | ||
932 | |||
933 | wl1251_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size); | ||
934 | |||
935 | return wl1251_cmd_template_set(wl, CMD_PROBE_REQ, &template, | ||
936 | size); | ||
937 | } | ||
938 | 868 | ||
939 | static int wl1251_hw_scan(struct wl1251 *wl, u8 *ssid, size_t len, | 869 | if (req->n_ssids) { |
940 | u8 active_scan, u8 high_prio, u8 num_channels, | 870 | ssid = req->ssids[0].ssid; |
941 | u8 probe_requests) | 871 | ssid_len = req->ssids[0].ssid_len; |
942 | { | ||
943 | struct wl1251_cmd_trigger_scan_to *trigger = NULL; | ||
944 | struct cmd_scan *params = NULL; | ||
945 | int i, ret; | ||
946 | u16 scan_options = 0; | ||
947 | |||
948 | if (wl->scanning) | ||
949 | return -EINVAL; | ||
950 | |||
951 | params = kzalloc(sizeof(*params), GFP_KERNEL); | ||
952 | if (!params) | ||
953 | return -ENOMEM; | ||
954 | |||
955 | params->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD); | ||
956 | params->params.rx_filter_options = | ||
957 | cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN); | ||
958 | |||
959 | /* High priority scan */ | ||
960 | if (!active_scan) | ||
961 | scan_options |= SCAN_PASSIVE; | ||
962 | if (high_prio) | ||
963 | scan_options |= SCAN_PRIORITY_HIGH; | ||
964 | params->params.scan_options = scan_options; | ||
965 | |||
966 | params->params.num_channels = num_channels; | ||
967 | params->params.num_probe_requests = probe_requests; | ||
968 | params->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */ | ||
969 | params->params.tid_trigger = 0; | ||
970 | |||
971 | for (i = 0; i < num_channels; i++) { | ||
972 | params->channels[i].min_duration = cpu_to_le32(30000); | ||
973 | params->channels[i].max_duration = cpu_to_le32(60000); | ||
974 | memset(¶ms->channels[i].bssid_lsb, 0xff, 4); | ||
975 | memset(¶ms->channels[i].bssid_msb, 0xff, 2); | ||
976 | params->channels[i].early_termination = 0; | ||
977 | params->channels[i].tx_power_att = 0; | ||
978 | params->channels[i].channel = i + 1; | ||
979 | memset(params->channels[i].pad, 0, 3); | ||
980 | } | 872 | } |
981 | 873 | ||
982 | for (i = num_channels; i < SCAN_MAX_NUM_OF_CHANNELS; i++) | 874 | mutex_lock(&wl->mutex); |
983 | memset(¶ms->channels[i], 0, | ||
984 | sizeof(struct basic_scan_channel_parameters)); | ||
985 | |||
986 | if (len && ssid) { | ||
987 | params->params.ssid_len = len; | ||
988 | memcpy(params->params.ssid, ssid, len); | ||
989 | } else { | ||
990 | params->params.ssid_len = 0; | ||
991 | memset(params->params.ssid, 0, 32); | ||
992 | } | ||
993 | 875 | ||
994 | ret = wl1251_build_probe_req(wl, ssid, len); | 876 | if (wl->scanning) { |
995 | if (ret < 0) { | 877 | wl1251_debug(DEBUG_SCAN, "scan already in progress"); |
996 | wl1251_error("PROBE request template failed"); | 878 | ret = -EINVAL; |
997 | goto out; | 879 | goto out; |
998 | } | 880 | } |
999 | 881 | ||
1000 | trigger = kzalloc(sizeof(*trigger), GFP_KERNEL); | 882 | ret = wl1251_ps_elp_wakeup(wl); |
1001 | if (!trigger) | 883 | if (ret < 0) |
1002 | goto out; | 884 | goto out; |
1003 | 885 | ||
1004 | trigger->timeout = 0; | 886 | skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, |
1005 | 887 | req->ie, req->ie_len); | |
1006 | ret = wl1251_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger, | 888 | if (!skb) { |
1007 | sizeof(*trigger)); | 889 | ret = -ENOMEM; |
1008 | if (ret < 0) { | ||
1009 | wl1251_error("trigger scan to failed for hw scan"); | ||
1010 | goto out; | 890 | goto out; |
1011 | } | 891 | } |
1012 | 892 | ||
1013 | wl1251_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); | 893 | ret = wl1251_cmd_template_set(wl, CMD_PROBE_REQ, skb->data, |
1014 | 894 | skb->len); | |
1015 | wl->scanning = true; | 895 | dev_kfree_skb(skb); |
896 | if (ret < 0) | ||
897 | goto out_sleep; | ||
1016 | 898 | ||
1017 | ret = wl1251_cmd_send(wl, CMD_SCAN, params, sizeof(*params)); | 899 | ret = wl1251_cmd_trigger_scan_to(wl, 0); |
1018 | if (ret < 0) | 900 | if (ret < 0) |
1019 | wl1251_error("SCAN failed"); | 901 | goto out_sleep; |
1020 | 902 | ||
1021 | wl1251_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params)); | 903 | wl->scanning = true; |
1022 | 904 | ||
1023 | if (params->header.status != CMD_STATUS_SUCCESS) { | 905 | ret = wl1251_cmd_scan(wl, ssid, ssid_len, req->channels, |
1024 | wl1251_error("TEST command answer error: %d", | 906 | req->n_channels, WL1251_SCAN_NUM_PROBES); |
1025 | params->header.status); | 907 | if (ret < 0) { |
1026 | wl->scanning = false; | 908 | wl->scanning = false; |
1027 | ret = -EIO; | 909 | goto out_sleep; |
1028 | goto out; | ||
1029 | } | ||
1030 | |||
1031 | out: | ||
1032 | kfree(params); | ||
1033 | return ret; | ||
1034 | |||
1035 | } | ||
1036 | |||
1037 | static int wl1251_op_hw_scan(struct ieee80211_hw *hw, | ||
1038 | struct cfg80211_scan_request *req) | ||
1039 | { | ||
1040 | struct wl1251 *wl = hw->priv; | ||
1041 | int ret; | ||
1042 | u8 *ssid = NULL; | ||
1043 | size_t ssid_len = 0; | ||
1044 | |||
1045 | wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan"); | ||
1046 | |||
1047 | if (req->n_ssids) { | ||
1048 | ssid = req->ssids[0].ssid; | ||
1049 | ssid_len = req->ssids[0].ssid_len; | ||
1050 | } | 910 | } |
1051 | 911 | ||
1052 | mutex_lock(&wl->mutex); | 912 | out_sleep: |
1053 | |||
1054 | ret = wl1251_ps_elp_wakeup(wl); | ||
1055 | if (ret < 0) | ||
1056 | goto out; | ||
1057 | |||
1058 | ret = wl1251_hw_scan(hw->priv, ssid, ssid_len, 1, 0, 13, 3); | ||
1059 | |||
1060 | wl1251_ps_elp_sleep(wl); | 913 | wl1251_ps_elp_sleep(wl); |
1061 | 914 | ||
1062 | out: | 915 | out: |
@@ -1093,9 +946,8 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1093 | struct ieee80211_bss_conf *bss_conf, | 946 | struct ieee80211_bss_conf *bss_conf, |
1094 | u32 changed) | 947 | u32 changed) |
1095 | { | 948 | { |
1096 | enum wl1251_cmd_ps_mode mode; | ||
1097 | struct wl1251 *wl = hw->priv; | 949 | struct wl1251 *wl = hw->priv; |
1098 | struct sk_buff *beacon; | 950 | struct sk_buff *beacon, *skb; |
1099 | int ret; | 951 | int ret; |
1100 | 952 | ||
1101 | wl1251_debug(DEBUG_MAC80211, "mac80211 bss info changed"); | 953 | wl1251_debug(DEBUG_MAC80211, "mac80211 bss info changed"); |
@@ -1109,7 +961,17 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1109 | if (changed & BSS_CHANGED_BSSID) { | 961 | if (changed & BSS_CHANGED_BSSID) { |
1110 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); | 962 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); |
1111 | 963 | ||
1112 | ret = wl1251_build_null_data(wl); | 964 | skb = ieee80211_nullfunc_get(wl->hw, wl->vif); |
965 | if (!skb) | ||
966 | goto out_sleep; | ||
967 | |||
968 | ret = wl1251_cmd_template_set(wl, CMD_NULL_DATA, | ||
969 | skb->data, skb->len); | ||
970 | dev_kfree_skb(skb); | ||
971 | if (ret < 0) | ||
972 | goto out_sleep; | ||
973 | |||
974 | ret = wl1251_build_qos_null_data(wl); | ||
1113 | if (ret < 0) | 975 | if (ret < 0) |
1114 | goto out; | 976 | goto out; |
1115 | 977 | ||
@@ -1124,27 +986,21 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1124 | if (changed & BSS_CHANGED_ASSOC) { | 986 | if (changed & BSS_CHANGED_ASSOC) { |
1125 | if (bss_conf->assoc) { | 987 | if (bss_conf->assoc) { |
1126 | wl->beacon_int = bss_conf->beacon_int; | 988 | wl->beacon_int = bss_conf->beacon_int; |
1127 | wl->dtim_period = bss_conf->dtim_period; | ||
1128 | 989 | ||
1129 | ret = wl1251_acx_wr_tbtt_and_dtim(wl, wl->beacon_int, | 990 | skb = ieee80211_pspoll_get(wl->hw, wl->vif); |
1130 | wl->dtim_period); | 991 | if (!skb) |
1131 | wl->aid = bss_conf->aid; | 992 | goto out_sleep; |
1132 | 993 | ||
1133 | ret = wl1251_build_ps_poll(wl, wl->aid); | 994 | ret = wl1251_cmd_template_set(wl, CMD_PS_POLL, |
995 | skb->data, | ||
996 | skb->len); | ||
997 | dev_kfree_skb(skb); | ||
1134 | if (ret < 0) | 998 | if (ret < 0) |
1135 | goto out_sleep; | 999 | goto out_sleep; |
1136 | 1000 | ||
1137 | ret = wl1251_acx_aid(wl, wl->aid); | 1001 | ret = wl1251_acx_aid(wl, bss_conf->aid); |
1138 | if (ret < 0) | 1002 | if (ret < 0) |
1139 | goto out_sleep; | 1003 | goto out_sleep; |
1140 | |||
1141 | /* If we want to go in PSM but we're not there yet */ | ||
1142 | if (wl->psm_requested && !wl->psm) { | ||
1143 | mode = STATION_POWER_SAVE_MODE; | ||
1144 | ret = wl1251_ps_set_mode(wl, mode); | ||
1145 | if (ret < 0) | ||
1146 | goto out_sleep; | ||
1147 | } | ||
1148 | } else { | 1004 | } else { |
1149 | /* use defaults when not associated */ | 1005 | /* use defaults when not associated */ |
1150 | wl->beacon_int = WL1251_DEFAULT_BEACON_INT; | 1006 | wl->beacon_int = WL1251_DEFAULT_BEACON_INT; |
@@ -1176,7 +1032,7 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1176 | ret = wl1251_acx_cts_protect(wl, CTSPROTECT_DISABLE); | 1032 | ret = wl1251_acx_cts_protect(wl, CTSPROTECT_DISABLE); |
1177 | if (ret < 0) { | 1033 | if (ret < 0) { |
1178 | wl1251_warning("Set ctsprotect failed %d", ret); | 1034 | wl1251_warning("Set ctsprotect failed %d", ret); |
1179 | goto out; | 1035 | goto out_sleep; |
1180 | } | 1036 | } |
1181 | } | 1037 | } |
1182 | 1038 | ||
@@ -1187,7 +1043,7 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1187 | 1043 | ||
1188 | if (ret < 0) { | 1044 | if (ret < 0) { |
1189 | dev_kfree_skb(beacon); | 1045 | dev_kfree_skb(beacon); |
1190 | goto out; | 1046 | goto out_sleep; |
1191 | } | 1047 | } |
1192 | 1048 | ||
1193 | ret = wl1251_cmd_template_set(wl, CMD_PROBE_RESP, beacon->data, | 1049 | ret = wl1251_cmd_template_set(wl, CMD_PROBE_RESP, beacon->data, |
@@ -1196,13 +1052,13 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1196 | dev_kfree_skb(beacon); | 1052 | dev_kfree_skb(beacon); |
1197 | 1053 | ||
1198 | if (ret < 0) | 1054 | if (ret < 0) |
1199 | goto out; | 1055 | goto out_sleep; |
1200 | 1056 | ||
1201 | ret = wl1251_join(wl, wl->bss_type, wl->beacon_int, | 1057 | ret = wl1251_join(wl, wl->bss_type, wl->beacon_int, |
1202 | wl->channel, wl->dtim_period); | 1058 | wl->channel, wl->dtim_period); |
1203 | 1059 | ||
1204 | if (ret < 0) | 1060 | if (ret < 0) |
1205 | goto out; | 1061 | goto out_sleep; |
1206 | } | 1062 | } |
1207 | 1063 | ||
1208 | out_sleep: | 1064 | out_sleep: |
@@ -1273,6 +1129,49 @@ static struct ieee80211_channel wl1251_channels[] = { | |||
1273 | { .hw_value = 13, .center_freq = 2472}, | 1129 | { .hw_value = 13, .center_freq = 2472}, |
1274 | }; | 1130 | }; |
1275 | 1131 | ||
1132 | static int wl1251_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | ||
1133 | const struct ieee80211_tx_queue_params *params) | ||
1134 | { | ||
1135 | enum wl1251_acx_ps_scheme ps_scheme; | ||
1136 | struct wl1251 *wl = hw->priv; | ||
1137 | int ret; | ||
1138 | |||
1139 | mutex_lock(&wl->mutex); | ||
1140 | |||
1141 | wl1251_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue); | ||
1142 | |||
1143 | ret = wl1251_ps_elp_wakeup(wl); | ||
1144 | if (ret < 0) | ||
1145 | goto out; | ||
1146 | |||
1147 | /* mac80211 uses units of 32 usec */ | ||
1148 | ret = wl1251_acx_ac_cfg(wl, wl1251_tx_get_queue(queue), | ||
1149 | params->cw_min, params->cw_max, | ||
1150 | params->aifs, params->txop * 32); | ||
1151 | if (ret < 0) | ||
1152 | goto out_sleep; | ||
1153 | |||
1154 | if (params->uapsd) | ||
1155 | ps_scheme = WL1251_ACX_PS_SCHEME_UPSD_TRIGGER; | ||
1156 | else | ||
1157 | ps_scheme = WL1251_ACX_PS_SCHEME_LEGACY; | ||
1158 | |||
1159 | ret = wl1251_acx_tid_cfg(wl, wl1251_tx_get_queue(queue), | ||
1160 | CHANNEL_TYPE_EDCF, | ||
1161 | wl1251_tx_get_queue(queue), ps_scheme, | ||
1162 | WL1251_ACX_ACK_POLICY_LEGACY); | ||
1163 | if (ret < 0) | ||
1164 | goto out_sleep; | ||
1165 | |||
1166 | out_sleep: | ||
1167 | wl1251_ps_elp_sleep(wl); | ||
1168 | |||
1169 | out: | ||
1170 | mutex_unlock(&wl->mutex); | ||
1171 | |||
1172 | return ret; | ||
1173 | } | ||
1174 | |||
1276 | /* can't be const, mac80211 writes to this */ | 1175 | /* can't be const, mac80211 writes to this */ |
1277 | static struct ieee80211_supported_band wl1251_band_2ghz = { | 1176 | static struct ieee80211_supported_band wl1251_band_2ghz = { |
1278 | .channels = wl1251_channels, | 1177 | .channels = wl1251_channels, |
@@ -1293,6 +1192,7 @@ static const struct ieee80211_ops wl1251_ops = { | |||
1293 | .hw_scan = wl1251_op_hw_scan, | 1192 | .hw_scan = wl1251_op_hw_scan, |
1294 | .bss_info_changed = wl1251_op_bss_info_changed, | 1193 | .bss_info_changed = wl1251_op_bss_info_changed, |
1295 | .set_rts_threshold = wl1251_op_set_rts_threshold, | 1194 | .set_rts_threshold = wl1251_op_set_rts_threshold, |
1195 | .conf_tx = wl1251_op_conf_tx, | ||
1296 | }; | 1196 | }; |
1297 | 1197 | ||
1298 | static int wl1251_register_hw(struct wl1251 *wl) | 1198 | static int wl1251_register_hw(struct wl1251 *wl) |
@@ -1332,12 +1232,15 @@ int wl1251_init_ieee80211(struct wl1251 *wl) | |||
1332 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | | 1232 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | |
1333 | IEEE80211_HW_NOISE_DBM | | 1233 | IEEE80211_HW_NOISE_DBM | |
1334 | IEEE80211_HW_SUPPORTS_PS | | 1234 | IEEE80211_HW_SUPPORTS_PS | |
1335 | IEEE80211_HW_BEACON_FILTER; | 1235 | IEEE80211_HW_BEACON_FILTER | |
1236 | IEEE80211_HW_SUPPORTS_UAPSD; | ||
1336 | 1237 | ||
1337 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | 1238 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); |
1338 | wl->hw->wiphy->max_scan_ssids = 1; | 1239 | wl->hw->wiphy->max_scan_ssids = 1; |
1339 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz; | 1240 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz; |
1340 | 1241 | ||
1242 | wl->hw->queues = 4; | ||
1243 | |||
1341 | ret = wl1251_register_hw(wl); | 1244 | ret = wl1251_register_hw(wl); |
1342 | if (ret) | 1245 | if (ret) |
1343 | goto out; | 1246 | goto out; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.c b/drivers/net/wireless/wl12xx/wl1251_ps.c index 9931b197ff77..851dfb65e474 100644 --- a/drivers/net/wireless/wl12xx/wl1251_ps.c +++ b/drivers/net/wireless/wl12xx/wl1251_ps.c | |||
@@ -26,7 +26,8 @@ | |||
26 | #include "wl1251_cmd.h" | 26 | #include "wl1251_cmd.h" |
27 | #include "wl1251_io.h" | 27 | #include "wl1251_io.h" |
28 | 28 | ||
29 | #define WL1251_WAKEUP_TIMEOUT 2000 | 29 | /* in ms */ |
30 | #define WL1251_WAKEUP_TIMEOUT 100 | ||
30 | 31 | ||
31 | void wl1251_elp_work(struct work_struct *work) | 32 | void wl1251_elp_work(struct work_struct *work) |
32 | { | 33 | { |
@@ -67,7 +68,7 @@ void wl1251_ps_elp_sleep(struct wl1251 *wl) | |||
67 | 68 | ||
68 | int wl1251_ps_elp_wakeup(struct wl1251 *wl) | 69 | int wl1251_ps_elp_wakeup(struct wl1251 *wl) |
69 | { | 70 | { |
70 | unsigned long timeout; | 71 | unsigned long timeout, start; |
71 | u32 elp_reg; | 72 | u32 elp_reg; |
72 | 73 | ||
73 | if (!wl->elp) | 74 | if (!wl->elp) |
@@ -75,6 +76,7 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl) | |||
75 | 76 | ||
76 | wl1251_debug(DEBUG_PSM, "waking up chip from elp"); | 77 | wl1251_debug(DEBUG_PSM, "waking up chip from elp"); |
77 | 78 | ||
79 | start = jiffies; | ||
78 | timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT); | 80 | timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT); |
79 | 81 | ||
80 | wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); | 82 | wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); |
@@ -95,8 +97,7 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl) | |||
95 | } | 97 | } |
96 | 98 | ||
97 | wl1251_debug(DEBUG_PSM, "wakeup time: %u ms", | 99 | wl1251_debug(DEBUG_PSM, "wakeup time: %u ms", |
98 | jiffies_to_msecs(jiffies) - | 100 | jiffies_to_msecs(jiffies - start)); |
99 | (jiffies_to_msecs(timeout) - WL1251_WAKEUP_TIMEOUT)); | ||
100 | 101 | ||
101 | wl->elp = false; | 102 | wl->elp = false; |
102 | 103 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.c b/drivers/net/wireless/wl12xx/wl1251_rx.c index f84cc89cbffc..b56732226cc0 100644 --- a/drivers/net/wireless/wl12xx/wl1251_rx.c +++ b/drivers/net/wireless/wl12xx/wl1251_rx.c | |||
@@ -126,7 +126,7 @@ static void wl1251_rx_body(struct wl1251 *wl, | |||
126 | if (wl->rx_current_buffer) | 126 | if (wl->rx_current_buffer) |
127 | rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size; | 127 | rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size; |
128 | 128 | ||
129 | skb = dev_alloc_skb(length); | 129 | skb = __dev_alloc_skb(length, GFP_KERNEL); |
130 | if (!skb) { | 130 | if (!skb) { |
131 | wl1251_error("Couldn't allocate RX frame"); | 131 | wl1251_error("Couldn't allocate RX frame"); |
132 | return; | 132 | return; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.c b/drivers/net/wireless/wl12xx/wl1251_tx.c index f85970615849..c8223185efd2 100644 --- a/drivers/net/wireless/wl12xx/wl1251_tx.c +++ b/drivers/net/wireless/wl12xx/wl1251_tx.c | |||
@@ -167,8 +167,7 @@ static int wl1251_tx_fill_hdr(struct wl1251 *wl, struct sk_buff *skb, | |||
167 | tx_hdr->expiry_time = cpu_to_le32(1 << 16); | 167 | tx_hdr->expiry_time = cpu_to_le32(1 << 16); |
168 | tx_hdr->id = id; | 168 | tx_hdr->id = id; |
169 | 169 | ||
170 | /* FIXME: how to get the correct queue id? */ | 170 | tx_hdr->xmit_queue = wl1251_tx_get_queue(skb_get_queue_mapping(skb)); |
171 | tx_hdr->xmit_queue = 0; | ||
172 | 171 | ||
173 | wl1251_tx_control(tx_hdr, control, fc); | 172 | wl1251_tx_control(tx_hdr, control, fc); |
174 | wl1251_tx_frag_block_num(tx_hdr); | 173 | wl1251_tx_frag_block_num(tx_hdr); |
@@ -220,6 +219,7 @@ static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb, | |||
220 | /* align the buffer on a 4-byte boundary */ | 219 | /* align the buffer on a 4-byte boundary */ |
221 | skb_reserve(skb, offset); | 220 | skb_reserve(skb, offset); |
222 | memmove(skb->data, src, skb->len); | 221 | memmove(skb->data, src, skb->len); |
222 | tx_hdr = (struct tx_double_buffer_desc *) skb->data; | ||
223 | } else { | 223 | } else { |
224 | wl1251_info("No handler, fixme!"); | 224 | wl1251_info("No handler, fixme!"); |
225 | return -EINVAL; | 225 | return -EINVAL; |
@@ -237,8 +237,9 @@ static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb, | |||
237 | 237 | ||
238 | wl1251_mem_write(wl, addr, skb->data, len); | 238 | wl1251_mem_write(wl, addr, skb->data, len); |
239 | 239 | ||
240 | wl1251_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u rate 0x%x", | 240 | wl1251_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u rate 0x%x " |
241 | tx_hdr->id, skb, tx_hdr->length, tx_hdr->rate); | 241 | "queue %d", tx_hdr->id, skb, tx_hdr->length, |
242 | tx_hdr->rate, tx_hdr->xmit_queue); | ||
242 | 243 | ||
243 | return 0; | 244 | return 0; |
244 | } | 245 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.h b/drivers/net/wireless/wl12xx/wl1251_tx.h index 7c1c1665c810..55856c6bb97a 100644 --- a/drivers/net/wireless/wl12xx/wl1251_tx.h +++ b/drivers/net/wireless/wl12xx/wl1251_tx.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #define __WL1251_TX_H__ | 26 | #define __WL1251_TX_H__ |
27 | 27 | ||
28 | #include <linux/bitops.h> | 28 | #include <linux/bitops.h> |
29 | #include "wl1251_acx.h" | ||
29 | 30 | ||
30 | /* | 31 | /* |
31 | * | 32 | * |
@@ -209,6 +210,22 @@ struct tx_result { | |||
209 | u8 done_2; | 210 | u8 done_2; |
210 | } __attribute__ ((packed)); | 211 | } __attribute__ ((packed)); |
211 | 212 | ||
213 | static inline int wl1251_tx_get_queue(int queue) | ||
214 | { | ||
215 | switch (queue) { | ||
216 | case 0: | ||
217 | return QOS_AC_VO; | ||
218 | case 1: | ||
219 | return QOS_AC_VI; | ||
220 | case 2: | ||
221 | return QOS_AC_BE; | ||
222 | case 3: | ||
223 | return QOS_AC_BK; | ||
224 | default: | ||
225 | return QOS_AC_BE; | ||
226 | } | ||
227 | } | ||
228 | |||
212 | void wl1251_tx_work(struct work_struct *work); | 229 | void wl1251_tx_work(struct work_struct *work); |
213 | void wl1251_tx_complete(struct wl1251 *wl); | 230 | void wl1251_tx_complete(struct wl1251 *wl); |
214 | void wl1251_tx_flush(struct wl1251 *wl); | 231 | void wl1251_tx_flush(struct wl1251 *wl); |
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 94359b1a861f..97ea5096bc8c 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h | |||
@@ -43,7 +43,7 @@ enum { | |||
43 | DEBUG_SPI = BIT(1), | 43 | DEBUG_SPI = BIT(1), |
44 | DEBUG_BOOT = BIT(2), | 44 | DEBUG_BOOT = BIT(2), |
45 | DEBUG_MAILBOX = BIT(3), | 45 | DEBUG_MAILBOX = BIT(3), |
46 | DEBUG_NETLINK = BIT(4), | 46 | DEBUG_TESTMODE = BIT(4), |
47 | DEBUG_EVENT = BIT(5), | 47 | DEBUG_EVENT = BIT(5), |
48 | DEBUG_TX = BIT(6), | 48 | DEBUG_TX = BIT(6), |
49 | DEBUG_RX = BIT(7), | 49 | DEBUG_RX = BIT(7), |
@@ -107,11 +107,36 @@ enum { | |||
107 | CFG_RX_CTL_EN | CFG_RX_BCN_EN | \ | 107 | CFG_RX_CTL_EN | CFG_RX_BCN_EN | \ |
108 | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN) | 108 | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN) |
109 | 109 | ||
110 | #define WL1271_DEFAULT_BASIC_RATE_SET (CONF_TX_RATE_MASK_ALL) | ||
111 | |||
112 | #define WL1271_FW_NAME "wl1271-fw.bin" | 110 | #define WL1271_FW_NAME "wl1271-fw.bin" |
113 | #define WL1271_NVS_NAME "wl1271-nvs.bin" | 111 | #define WL1271_NVS_NAME "wl1271-nvs.bin" |
114 | 112 | ||
113 | /* NVS data structure */ | ||
114 | #define WL1271_NVS_SECTION_SIZE 468 | ||
115 | |||
116 | #define WL1271_NVS_GENERAL_PARAMS_SIZE 57 | ||
117 | #define WL1271_NVS_GENERAL_PARAMS_SIZE_PADDED \ | ||
118 | (WL1271_NVS_GENERAL_PARAMS_SIZE + 1) | ||
119 | #define WL1271_NVS_STAT_RADIO_PARAMS_SIZE 17 | ||
120 | #define WL1271_NVS_STAT_RADIO_PARAMS_SIZE_PADDED \ | ||
121 | (WL1271_NVS_STAT_RADIO_PARAMS_SIZE + 1) | ||
122 | #define WL1271_NVS_DYN_RADIO_PARAMS_SIZE 65 | ||
123 | #define WL1271_NVS_DYN_RADIO_PARAMS_SIZE_PADDED \ | ||
124 | (WL1271_NVS_DYN_RADIO_PARAMS_SIZE + 1) | ||
125 | #define WL1271_NVS_FEM_COUNT 2 | ||
126 | #define WL1271_NVS_INI_SPARE_SIZE 124 | ||
127 | |||
128 | struct wl1271_nvs_file { | ||
129 | /* NVS section */ | ||
130 | u8 nvs[WL1271_NVS_SECTION_SIZE]; | ||
131 | |||
132 | /* INI section */ | ||
133 | u8 general_params[WL1271_NVS_GENERAL_PARAMS_SIZE_PADDED]; | ||
134 | u8 stat_radio_params[WL1271_NVS_STAT_RADIO_PARAMS_SIZE_PADDED]; | ||
135 | u8 dyn_radio_params[WL1271_NVS_FEM_COUNT] | ||
136 | [WL1271_NVS_DYN_RADIO_PARAMS_SIZE_PADDED]; | ||
137 | u8 ini_spare[WL1271_NVS_INI_SPARE_SIZE]; | ||
138 | } __attribute__ ((packed)); | ||
139 | |||
115 | /* | 140 | /* |
116 | * Enable/disable 802.11a support for WL1273 | 141 | * Enable/disable 802.11a support for WL1273 |
117 | */ | 142 | */ |
@@ -276,6 +301,7 @@ struct wl1271_debugfs { | |||
276 | 301 | ||
277 | struct dentry *retry_count; | 302 | struct dentry *retry_count; |
278 | struct dentry *excessive_retries; | 303 | struct dentry *excessive_retries; |
304 | struct dentry *gpio_power; | ||
279 | }; | 305 | }; |
280 | 306 | ||
281 | #define NUM_TX_QUEUES 4 | 307 | #define NUM_TX_QUEUES 4 |
@@ -322,6 +348,17 @@ struct wl1271 { | |||
322 | enum wl1271_state state; | 348 | enum wl1271_state state; |
323 | struct mutex mutex; | 349 | struct mutex mutex; |
324 | 350 | ||
351 | #define WL1271_FLAG_STA_RATES_CHANGED (0) | ||
352 | #define WL1271_FLAG_STA_ASSOCIATED (1) | ||
353 | #define WL1271_FLAG_JOINED (2) | ||
354 | #define WL1271_FLAG_GPIO_POWER (3) | ||
355 | #define WL1271_FLAG_TX_QUEUE_STOPPED (4) | ||
356 | #define WL1271_FLAG_SCANNING (5) | ||
357 | #define WL1271_FLAG_IN_ELP (6) | ||
358 | #define WL1271_FLAG_PSM (7) | ||
359 | #define WL1271_FLAG_PSM_REQUESTED (8) | ||
360 | unsigned long flags; | ||
361 | |||
325 | struct wl1271_partition_set part; | 362 | struct wl1271_partition_set part; |
326 | 363 | ||
327 | struct wl1271_chip chip; | 364 | struct wl1271_chip chip; |
@@ -331,8 +368,7 @@ struct wl1271 { | |||
331 | 368 | ||
332 | u8 *fw; | 369 | u8 *fw; |
333 | size_t fw_len; | 370 | size_t fw_len; |
334 | u8 *nvs; | 371 | struct wl1271_nvs_file *nvs; |
335 | size_t nvs_len; | ||
336 | 372 | ||
337 | u8 bssid[ETH_ALEN]; | 373 | u8 bssid[ETH_ALEN]; |
338 | u8 mac_addr[ETH_ALEN]; | 374 | u8 mac_addr[ETH_ALEN]; |
@@ -359,7 +395,6 @@ struct wl1271 { | |||
359 | 395 | ||
360 | /* Frames scheduled for transmission, not handled yet */ | 396 | /* Frames scheduled for transmission, not handled yet */ |
361 | struct sk_buff_head tx_queue; | 397 | struct sk_buff_head tx_queue; |
362 | bool tx_queue_stopped; | ||
363 | 398 | ||
364 | struct work_struct tx_work; | 399 | struct work_struct tx_work; |
365 | 400 | ||
@@ -387,14 +422,15 @@ struct wl1271 { | |||
387 | u32 mbox_ptr[2]; | 422 | u32 mbox_ptr[2]; |
388 | 423 | ||
389 | /* Are we currently scanning */ | 424 | /* Are we currently scanning */ |
390 | bool scanning; | ||
391 | struct wl1271_scan scan; | 425 | struct wl1271_scan scan; |
392 | 426 | ||
393 | /* Our association ID */ | 427 | /* Our association ID */ |
394 | u16 aid; | 428 | u16 aid; |
395 | 429 | ||
396 | /* currently configured rate set */ | 430 | /* currently configured rate set */ |
431 | u32 sta_rate_set; | ||
397 | u32 basic_rate_set; | 432 | u32 basic_rate_set; |
433 | u32 rate_set; | ||
398 | 434 | ||
399 | /* The current band */ | 435 | /* The current band */ |
400 | enum ieee80211_band band; | 436 | enum ieee80211_band band; |
@@ -405,18 +441,9 @@ struct wl1271 { | |||
405 | unsigned int rx_config; | 441 | unsigned int rx_config; |
406 | unsigned int rx_filter; | 442 | unsigned int rx_filter; |
407 | 443 | ||
408 | /* is firmware in elp mode */ | ||
409 | bool elp; | ||
410 | |||
411 | struct completion *elp_compl; | 444 | struct completion *elp_compl; |
412 | struct delayed_work elp_work; | 445 | struct delayed_work elp_work; |
413 | 446 | ||
414 | /* we can be in psm, but not in elp, we have to differentiate */ | ||
415 | bool psm; | ||
416 | |||
417 | /* PSM mode requested */ | ||
418 | bool psm_requested; | ||
419 | |||
420 | /* retry counter for PSM entries */ | 447 | /* retry counter for PSM entries */ |
421 | u8 psm_entry_retry; | 448 | u8 psm_entry_retry; |
422 | 449 | ||
@@ -435,9 +462,6 @@ struct wl1271 { | |||
435 | 462 | ||
436 | struct ieee80211_vif *vif; | 463 | struct ieee80211_vif *vif; |
437 | 464 | ||
438 | /* Used for a workaround to send disconnect before rejoining */ | ||
439 | bool joined; | ||
440 | |||
441 | /* Current chipset configuration */ | 465 | /* Current chipset configuration */ |
442 | struct conf_drv_settings conf; | 466 | struct conf_drv_settings conf; |
443 | 467 | ||
@@ -455,11 +479,14 @@ int wl1271_plt_stop(struct wl1271 *wl); | |||
455 | 479 | ||
456 | #define WL1271_TX_QUEUE_MAX_LENGTH 20 | 480 | #define WL1271_TX_QUEUE_MAX_LENGTH 20 |
457 | 481 | ||
458 | /* WL1271 needs a 200ms sleep after power on */ | 482 | /* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power |
483 | on in case is has been shut down shortly before */ | ||
484 | #define WL1271_PRE_POWER_ON_SLEEP 20 /* in miliseconds */ | ||
459 | #define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */ | 485 | #define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */ |
460 | 486 | ||
461 | static inline bool wl1271_11a_enabled(void) | 487 | static inline bool wl1271_11a_enabled(void) |
462 | { | 488 | { |
489 | /* FIXME: this could be determined based on the NVS-INI file */ | ||
463 | #ifdef WL1271_80211A_ENABLED | 490 | #ifdef WL1271_80211A_ENABLED |
464 | return true; | 491 | return true; |
465 | #else | 492 | #else |
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index 5cc89bbdac7a..60f10dce4800 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c | |||
@@ -390,6 +390,35 @@ out: | |||
390 | return ret; | 390 | return ret; |
391 | } | 391 | } |
392 | 392 | ||
393 | int wl1271_acx_dco_itrim_params(struct wl1271 *wl) | ||
394 | { | ||
395 | struct acx_dco_itrim_params *dco; | ||
396 | struct conf_itrim_settings *c = &wl->conf.itrim; | ||
397 | int ret; | ||
398 | |||
399 | wl1271_debug(DEBUG_ACX, "acx dco itrim parameters"); | ||
400 | |||
401 | dco = kzalloc(sizeof(*dco), GFP_KERNEL); | ||
402 | if (!dco) { | ||
403 | ret = -ENOMEM; | ||
404 | goto out; | ||
405 | } | ||
406 | |||
407 | dco->enable = c->enable; | ||
408 | dco->timeout = cpu_to_le32(c->timeout); | ||
409 | |||
410 | ret = wl1271_cmd_configure(wl, ACX_SET_DCO_ITRIM_PARAMS, | ||
411 | dco, sizeof(*dco)); | ||
412 | if (ret < 0) { | ||
413 | wl1271_warning("failed to set dco itrim parameters: %d", ret); | ||
414 | goto out; | ||
415 | } | ||
416 | |||
417 | out: | ||
418 | kfree(dco); | ||
419 | return ret; | ||
420 | } | ||
421 | |||
393 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter) | 422 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter) |
394 | { | 423 | { |
395 | struct acx_beacon_filter_option *beacon_filter = NULL; | 424 | struct acx_beacon_filter_option *beacon_filter = NULL; |
@@ -758,10 +787,11 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats) | |||
758 | return 0; | 787 | return 0; |
759 | } | 788 | } |
760 | 789 | ||
761 | int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates) | 790 | int wl1271_acx_rate_policies(struct wl1271 *wl) |
762 | { | 791 | { |
763 | struct acx_rate_policy *acx; | 792 | struct acx_rate_policy *acx; |
764 | struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf; | 793 | struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf; |
794 | int idx = 0; | ||
765 | int ret = 0; | 795 | int ret = 0; |
766 | 796 | ||
767 | wl1271_debug(DEBUG_ACX, "acx rate policies"); | 797 | wl1271_debug(DEBUG_ACX, "acx rate policies"); |
@@ -773,12 +803,21 @@ int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates) | |||
773 | goto out; | 803 | goto out; |
774 | } | 804 | } |
775 | 805 | ||
776 | /* configure one default (one-size-fits-all) rate class */ | 806 | /* configure one basic rate class */ |
777 | acx->rate_class_cnt = cpu_to_le32(1); | 807 | idx = ACX_TX_BASIC_RATE; |
778 | acx->rate_class[0].enabled_rates = cpu_to_le32(enabled_rates); | 808 | acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate_set); |
779 | acx->rate_class[0].short_retry_limit = c->short_retry_limit; | 809 | acx->rate_class[idx].short_retry_limit = c->short_retry_limit; |
780 | acx->rate_class[0].long_retry_limit = c->long_retry_limit; | 810 | acx->rate_class[idx].long_retry_limit = c->long_retry_limit; |
781 | acx->rate_class[0].aflags = c->aflags; | 811 | acx->rate_class[idx].aflags = c->aflags; |
812 | |||
813 | /* configure one AP supported rate class */ | ||
814 | idx = ACX_TX_AP_FULL_RATE; | ||
815 | acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->rate_set); | ||
816 | acx->rate_class[idx].short_retry_limit = c->short_retry_limit; | ||
817 | acx->rate_class[idx].long_retry_limit = c->long_retry_limit; | ||
818 | acx->rate_class[idx].aflags = c->aflags; | ||
819 | |||
820 | acx->rate_class_cnt = cpu_to_le32(ACX_TX_RATE_POLICY_CNT); | ||
782 | 821 | ||
783 | ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); | 822 | ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); |
784 | if (ret < 0) { | 823 | if (ret < 0) { |
@@ -791,12 +830,14 @@ out: | |||
791 | return ret; | 830 | return ret; |
792 | } | 831 | } |
793 | 832 | ||
794 | int wl1271_acx_ac_cfg(struct wl1271 *wl) | 833 | int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, |
834 | u8 aifsn, u16 txop) | ||
795 | { | 835 | { |
796 | struct acx_ac_cfg *acx; | 836 | struct acx_ac_cfg *acx; |
797 | int i, ret = 0; | 837 | int ret = 0; |
798 | 838 | ||
799 | wl1271_debug(DEBUG_ACX, "acx access category config"); | 839 | wl1271_debug(DEBUG_ACX, "acx ac cfg %d cw_ming %d cw_max %d " |
840 | "aifs %d txop %d", ac, cw_min, cw_max, aifsn, txop); | ||
800 | 841 | ||
801 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 842 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
802 | 843 | ||
@@ -805,21 +846,16 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl) | |||
805 | goto out; | 846 | goto out; |
806 | } | 847 | } |
807 | 848 | ||
808 | for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { | 849 | acx->ac = ac; |
809 | struct conf_tx_ac_category *c = &(wl->conf.tx.ac_conf[i]); | 850 | acx->cw_min = cw_min; |
810 | acx->ac = c->ac; | 851 | acx->cw_max = cpu_to_le16(cw_max); |
811 | acx->cw_min = c->cw_min; | 852 | acx->aifsn = aifsn; |
812 | acx->cw_max = cpu_to_le16(c->cw_max); | 853 | acx->tx_op_limit = cpu_to_le16(txop); |
813 | acx->aifsn = c->aifsn; | ||
814 | acx->reserved = 0; | ||
815 | acx->tx_op_limit = cpu_to_le16(c->tx_op_limit); | ||
816 | 854 | ||
817 | ret = wl1271_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx)); | 855 | ret = wl1271_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx)); |
818 | if (ret < 0) { | 856 | if (ret < 0) { |
819 | wl1271_warning("Setting of access category " | 857 | wl1271_warning("acx ac cfg failed: %d", ret); |
820 | "config: %d", ret); | 858 | goto out; |
821 | goto out; | ||
822 | } | ||
823 | } | 859 | } |
824 | 860 | ||
825 | out: | 861 | out: |
@@ -827,10 +863,12 @@ out: | |||
827 | return ret; | 863 | return ret; |
828 | } | 864 | } |
829 | 865 | ||
830 | int wl1271_acx_tid_cfg(struct wl1271 *wl) | 866 | int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, |
867 | u8 tsid, u8 ps_scheme, u8 ack_policy, | ||
868 | u32 apsd_conf0, u32 apsd_conf1) | ||
831 | { | 869 | { |
832 | struct acx_tid_config *acx; | 870 | struct acx_tid_config *acx; |
833 | int i, ret = 0; | 871 | int ret = 0; |
834 | 872 | ||
835 | wl1271_debug(DEBUG_ACX, "acx tid config"); | 873 | wl1271_debug(DEBUG_ACX, "acx tid config"); |
836 | 874 | ||
@@ -841,21 +879,18 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl) | |||
841 | goto out; | 879 | goto out; |
842 | } | 880 | } |
843 | 881 | ||
844 | for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { | 882 | acx->queue_id = queue_id; |
845 | struct conf_tx_tid *c = &(wl->conf.tx.tid_conf[i]); | 883 | acx->channel_type = channel_type; |
846 | acx->queue_id = c->queue_id; | 884 | acx->tsid = tsid; |
847 | acx->channel_type = c->channel_type; | 885 | acx->ps_scheme = ps_scheme; |
848 | acx->tsid = c->tsid; | 886 | acx->ack_policy = ack_policy; |
849 | acx->ps_scheme = c->ps_scheme; | 887 | acx->apsd_conf[0] = cpu_to_le32(apsd_conf0); |
850 | acx->ack_policy = c->ack_policy; | 888 | acx->apsd_conf[1] = cpu_to_le32(apsd_conf1); |
851 | acx->apsd_conf[0] = cpu_to_le32(c->apsd_conf[0]); | ||
852 | acx->apsd_conf[1] = cpu_to_le32(c->apsd_conf[1]); | ||
853 | 889 | ||
854 | ret = wl1271_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx)); | 890 | ret = wl1271_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx)); |
855 | if (ret < 0) { | 891 | if (ret < 0) { |
856 | wl1271_warning("Setting of tid config failed: %d", ret); | 892 | wl1271_warning("Setting of tid config failed: %d", ret); |
857 | goto out; | 893 | goto out; |
858 | } | ||
859 | } | 894 | } |
860 | 895 | ||
861 | out: | 896 | out: |
@@ -1012,59 +1047,6 @@ out: | |||
1012 | return ret; | 1047 | return ret; |
1013 | } | 1048 | } |
1014 | 1049 | ||
1015 | int wl1271_acx_smart_reflex(struct wl1271 *wl) | ||
1016 | { | ||
1017 | struct acx_smart_reflex_state *sr_state = NULL; | ||
1018 | struct acx_smart_reflex_config_params *sr_param = NULL; | ||
1019 | int i, ret; | ||
1020 | |||
1021 | wl1271_debug(DEBUG_ACX, "acx smart reflex"); | ||
1022 | |||
1023 | sr_param = kzalloc(sizeof(*sr_param), GFP_KERNEL); | ||
1024 | if (!sr_param) { | ||
1025 | ret = -ENOMEM; | ||
1026 | goto out; | ||
1027 | } | ||
1028 | |||
1029 | for (i = 0; i < CONF_SR_ERR_TBL_COUNT; i++) { | ||
1030 | struct conf_mart_reflex_err_table *e = | ||
1031 | &(wl->conf.init.sr_err_tbl[i]); | ||
1032 | |||
1033 | sr_param->error_table[i].len = e->len; | ||
1034 | sr_param->error_table[i].upper_limit = e->upper_limit; | ||
1035 | memcpy(sr_param->error_table[i].values, e->values, e->len); | ||
1036 | } | ||
1037 | |||
1038 | ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_PARAMS, | ||
1039 | sr_param, sizeof(*sr_param)); | ||
1040 | if (ret < 0) { | ||
1041 | wl1271_warning("failed to set smart reflex params: %d", ret); | ||
1042 | goto out; | ||
1043 | } | ||
1044 | |||
1045 | sr_state = kzalloc(sizeof(*sr_state), GFP_KERNEL); | ||
1046 | if (!sr_state) { | ||
1047 | ret = -ENOMEM; | ||
1048 | goto out; | ||
1049 | } | ||
1050 | |||
1051 | /* enable smart reflex */ | ||
1052 | sr_state->enable = wl->conf.init.sr_enable; | ||
1053 | |||
1054 | ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_STATE, | ||
1055 | sr_state, sizeof(*sr_state)); | ||
1056 | if (ret < 0) { | ||
1057 | wl1271_warning("failed to set smart reflex params: %d", ret); | ||
1058 | goto out; | ||
1059 | } | ||
1060 | |||
1061 | out: | ||
1062 | kfree(sr_state); | ||
1063 | kfree(sr_param); | ||
1064 | return ret; | ||
1065 | |||
1066 | } | ||
1067 | |||
1068 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable) | 1050 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable) |
1069 | { | 1051 | { |
1070 | struct wl1271_acx_bet_enable *acx = NULL; | 1052 | struct wl1271_acx_bet_enable *acx = NULL; |
@@ -1132,3 +1114,31 @@ out: | |||
1132 | kfree(acx); | 1114 | kfree(acx); |
1133 | return ret; | 1115 | return ret; |
1134 | } | 1116 | } |
1117 | |||
1118 | int wl1271_acx_pm_config(struct wl1271 *wl) | ||
1119 | { | ||
1120 | struct wl1271_acx_pm_config *acx = NULL; | ||
1121 | struct conf_pm_config_settings *c = &wl->conf.pm_config; | ||
1122 | int ret = 0; | ||
1123 | |||
1124 | wl1271_debug(DEBUG_ACX, "acx pm config"); | ||
1125 | |||
1126 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1127 | if (!acx) { | ||
1128 | ret = -ENOMEM; | ||
1129 | goto out; | ||
1130 | } | ||
1131 | |||
1132 | acx->host_clk_settling_time = cpu_to_le32(c->host_clk_settling_time); | ||
1133 | acx->host_fast_wakeup_support = c->host_fast_wakeup_support; | ||
1134 | |||
1135 | ret = wl1271_cmd_configure(wl, ACX_PM_CONFIG, acx, sizeof(*acx)); | ||
1136 | if (ret < 0) { | ||
1137 | wl1271_warning("acx pm config failed: %d", ret); | ||
1138 | goto out; | ||
1139 | } | ||
1140 | |||
1141 | out: | ||
1142 | kfree(acx); | ||
1143 | return ret; | ||
1144 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index 2ce0a8128542..aeccc98581eb 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h | |||
@@ -2,7 +2,7 @@ | |||
2 | * This file is part of wl1271 | 2 | * This file is part of wl1271 |
3 | * | 3 | * |
4 | * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. | 4 | * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. |
5 | * Copyright (C) 2008-2009 Nokia Corporation | 5 | * Copyright (C) 2008-2010 Nokia Corporation |
6 | * | 6 | * |
7 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | 7 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> |
8 | * | 8 | * |
@@ -348,7 +348,7 @@ struct acx_beacon_filter_option { | |||
348 | * ACXBeaconFilterEntry (not 221) | 348 | * ACXBeaconFilterEntry (not 221) |
349 | * Byte Offset Size (Bytes) Definition | 349 | * Byte Offset Size (Bytes) Definition |
350 | * =========== ============ ========== | 350 | * =========== ============ ========== |
351 | * 0 1 IE identifier | 351 | * 0 1 IE identifier |
352 | * 1 1 Treatment bit mask | 352 | * 1 1 Treatment bit mask |
353 | * | 353 | * |
354 | * ACXBeaconFilterEntry (221) | 354 | * ACXBeaconFilterEntry (221) |
@@ -381,8 +381,8 @@ struct acx_beacon_filter_ie_table { | |||
381 | struct acx_header header; | 381 | struct acx_header header; |
382 | 382 | ||
383 | u8 num_ie; | 383 | u8 num_ie; |
384 | u8 table[BEACON_FILTER_TABLE_MAX_SIZE]; | ||
385 | u8 pad[3]; | 384 | u8 pad[3]; |
385 | u8 table[BEACON_FILTER_TABLE_MAX_SIZE]; | ||
386 | } __attribute__ ((packed)); | 386 | } __attribute__ ((packed)); |
387 | 387 | ||
388 | struct acx_conn_monit_params { | 388 | struct acx_conn_monit_params { |
@@ -415,23 +415,12 @@ struct acx_bt_wlan_coex { | |||
415 | u8 pad[3]; | 415 | u8 pad[3]; |
416 | } __attribute__ ((packed)); | 416 | } __attribute__ ((packed)); |
417 | 417 | ||
418 | struct acx_smart_reflex_state { | 418 | struct acx_dco_itrim_params { |
419 | struct acx_header header; | 419 | struct acx_header header; |
420 | 420 | ||
421 | u8 enable; | 421 | u8 enable; |
422 | u8 padding[3]; | 422 | u8 padding[3]; |
423 | } __attribute__ ((packed)); | 423 | __le32 timeout; |
424 | |||
425 | struct smart_reflex_err_table { | ||
426 | u8 len; | ||
427 | s8 upper_limit; | ||
428 | s8 values[14]; | ||
429 | } __attribute__ ((packed)); | ||
430 | |||
431 | struct acx_smart_reflex_config_params { | ||
432 | struct acx_header header; | ||
433 | |||
434 | struct smart_reflex_err_table error_table[3]; | ||
435 | } __attribute__ ((packed)); | 424 | } __attribute__ ((packed)); |
436 | 425 | ||
437 | #define PTA_ANTENNA_TYPE_DEF (0) | 426 | #define PTA_ANTENNA_TYPE_DEF (0) |
@@ -837,6 +826,9 @@ struct acx_rate_class { | |||
837 | u8 reserved; | 826 | u8 reserved; |
838 | }; | 827 | }; |
839 | 828 | ||
829 | #define ACX_TX_BASIC_RATE 0 | ||
830 | #define ACX_TX_AP_FULL_RATE 1 | ||
831 | #define ACX_TX_RATE_POLICY_CNT 2 | ||
840 | struct acx_rate_policy { | 832 | struct acx_rate_policy { |
841 | struct acx_header header; | 833 | struct acx_header header; |
842 | 834 | ||
@@ -877,8 +869,8 @@ struct acx_tx_config_options { | |||
877 | __le16 tx_compl_threshold; /* number of packets */ | 869 | __le16 tx_compl_threshold; /* number of packets */ |
878 | } __attribute__ ((packed)); | 870 | } __attribute__ ((packed)); |
879 | 871 | ||
880 | #define ACX_RX_MEM_BLOCKS 64 | 872 | #define ACX_RX_MEM_BLOCKS 70 |
881 | #define ACX_TX_MIN_MEM_BLOCKS 64 | 873 | #define ACX_TX_MIN_MEM_BLOCKS 40 |
882 | #define ACX_TX_DESCRIPTORS 32 | 874 | #define ACX_TX_DESCRIPTORS 32 |
883 | #define ACX_NUM_SSID_PROFILES 1 | 875 | #define ACX_NUM_SSID_PROFILES 1 |
884 | 876 | ||
@@ -969,6 +961,13 @@ struct wl1271_acx_arp_filter { | |||
969 | used. */ | 961 | used. */ |
970 | } __attribute__((packed)); | 962 | } __attribute__((packed)); |
971 | 963 | ||
964 | struct wl1271_acx_pm_config { | ||
965 | struct acx_header header; | ||
966 | |||
967 | __le32 host_clk_settling_time; | ||
968 | u8 host_fast_wakeup_support; | ||
969 | u8 padding[3]; | ||
970 | } __attribute__ ((packed)); | ||
972 | 971 | ||
973 | enum { | 972 | enum { |
974 | ACX_WAKE_UP_CONDITIONS = 0x0002, | 973 | ACX_WAKE_UP_CONDITIONS = 0x0002, |
@@ -1027,13 +1026,13 @@ enum { | |||
1027 | ACX_HT_BSS_OPERATION = 0x0058, | 1026 | ACX_HT_BSS_OPERATION = 0x0058, |
1028 | ACX_COEX_ACTIVITY = 0x0059, | 1027 | ACX_COEX_ACTIVITY = 0x0059, |
1029 | ACX_SET_SMART_REFLEX_DEBUG = 0x005A, | 1028 | ACX_SET_SMART_REFLEX_DEBUG = 0x005A, |
1030 | ACX_SET_SMART_REFLEX_STATE = 0x005B, | 1029 | ACX_SET_DCO_ITRIM_PARAMS = 0x0061, |
1031 | ACX_SET_SMART_REFLEX_PARAMS = 0x005F, | ||
1032 | DOT11_RX_MSDU_LIFE_TIME = 0x1004, | 1030 | DOT11_RX_MSDU_LIFE_TIME = 0x1004, |
1033 | DOT11_CUR_TX_PWR = 0x100D, | 1031 | DOT11_CUR_TX_PWR = 0x100D, |
1034 | DOT11_RX_DOT11_MODE = 0x1012, | 1032 | DOT11_RX_DOT11_MODE = 0x1012, |
1035 | DOT11_RTS_THRESHOLD = 0x1013, | 1033 | DOT11_RTS_THRESHOLD = 0x1013, |
1036 | DOT11_GROUP_ADDRESS_TBL = 0x1014, | 1034 | DOT11_GROUP_ADDRESS_TBL = 0x1014, |
1035 | ACX_PM_CONFIG = 0x1016, | ||
1037 | 1036 | ||
1038 | MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL, | 1037 | MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL, |
1039 | 1038 | ||
@@ -1056,6 +1055,7 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, | |||
1056 | void *mc_list, u32 mc_list_len); | 1055 | void *mc_list, u32 mc_list_len); |
1057 | int wl1271_acx_service_period_timeout(struct wl1271 *wl); | 1056 | int wl1271_acx_service_period_timeout(struct wl1271 *wl); |
1058 | int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold); | 1057 | int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold); |
1058 | int wl1271_acx_dco_itrim_params(struct wl1271 *wl); | ||
1059 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); | 1059 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); |
1060 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); | 1060 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); |
1061 | int wl1271_acx_conn_monit_params(struct wl1271 *wl); | 1061 | int wl1271_acx_conn_monit_params(struct wl1271 *wl); |
@@ -1069,9 +1069,12 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble); | |||
1069 | int wl1271_acx_cts_protect(struct wl1271 *wl, | 1069 | int wl1271_acx_cts_protect(struct wl1271 *wl, |
1070 | enum acx_ctsprotect_type ctsprotect); | 1070 | enum acx_ctsprotect_type ctsprotect); |
1071 | int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); | 1071 | int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); |
1072 | int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates); | 1072 | int wl1271_acx_rate_policies(struct wl1271 *wl); |
1073 | int wl1271_acx_ac_cfg(struct wl1271 *wl); | 1073 | int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, |
1074 | int wl1271_acx_tid_cfg(struct wl1271 *wl); | 1074 | u8 aifsn, u16 txop); |
1075 | int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, | ||
1076 | u8 tsid, u8 ps_scheme, u8 ack_policy, | ||
1077 | u32 apsd_conf0, u32 apsd_conf1); | ||
1075 | int wl1271_acx_frag_threshold(struct wl1271 *wl); | 1078 | int wl1271_acx_frag_threshold(struct wl1271 *wl); |
1076 | int wl1271_acx_tx_config_options(struct wl1271 *wl); | 1079 | int wl1271_acx_tx_config_options(struct wl1271 *wl); |
1077 | int wl1271_acx_mem_cfg(struct wl1271 *wl); | 1080 | int wl1271_acx_mem_cfg(struct wl1271 *wl); |
@@ -1081,5 +1084,6 @@ int wl1271_acx_smart_reflex(struct wl1271 *wl); | |||
1081 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); | 1084 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); |
1082 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, | 1085 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, |
1083 | u8 version); | 1086 | u8 version); |
1087 | int wl1271_acx_pm_config(struct wl1271 *wl); | ||
1084 | 1088 | ||
1085 | #endif /* __WL1271_ACX_H__ */ | 1089 | #endif /* __WL1271_ACX_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index b7c96454cca3..2be76ee42bb9 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "wl1271_reg.h" | 27 | #include "wl1271_reg.h" |
28 | #include "wl1271_boot.h" | 28 | #include "wl1271_boot.h" |
29 | #include "wl1271_spi.h" | 29 | #include "wl1271_spi.h" |
30 | #include "wl1271_io.h" | ||
30 | #include "wl1271_event.h" | 31 | #include "wl1271_event.h" |
31 | 32 | ||
32 | static struct wl1271_partition_set part_table[PART_TABLE_LEN] = { | 33 | static struct wl1271_partition_set part_table[PART_TABLE_LEN] = { |
@@ -93,19 +94,19 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) | |||
93 | u32 cpu_ctrl; | 94 | u32 cpu_ctrl; |
94 | 95 | ||
95 | /* 10.5.0 run the firmware (I) */ | 96 | /* 10.5.0 run the firmware (I) */ |
96 | cpu_ctrl = wl1271_spi_read32(wl, ACX_REG_ECPU_CONTROL); | 97 | cpu_ctrl = wl1271_read32(wl, ACX_REG_ECPU_CONTROL); |
97 | 98 | ||
98 | /* 10.5.1 run the firmware (II) */ | 99 | /* 10.5.1 run the firmware (II) */ |
99 | cpu_ctrl |= flag; | 100 | cpu_ctrl |= flag; |
100 | wl1271_spi_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl); | 101 | wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl); |
101 | } | 102 | } |
102 | 103 | ||
103 | static void wl1271_boot_fw_version(struct wl1271 *wl) | 104 | static void wl1271_boot_fw_version(struct wl1271 *wl) |
104 | { | 105 | { |
105 | struct wl1271_static_data static_data; | 106 | struct wl1271_static_data static_data; |
106 | 107 | ||
107 | wl1271_spi_read(wl, wl->cmd_box_addr, | 108 | wl1271_read(wl, wl->cmd_box_addr, &static_data, sizeof(static_data), |
108 | &static_data, sizeof(static_data), false); | 109 | false); |
109 | 110 | ||
110 | strncpy(wl->chip.fw_ver, static_data.fw_version, | 111 | strncpy(wl->chip.fw_ver, static_data.fw_version, |
111 | sizeof(wl->chip.fw_ver)); | 112 | sizeof(wl->chip.fw_ver)); |
@@ -164,7 +165,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
164 | memcpy(chunk, p, CHUNK_SIZE); | 165 | memcpy(chunk, p, CHUNK_SIZE); |
165 | wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", | 166 | wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", |
166 | p, addr); | 167 | p, addr); |
167 | wl1271_spi_write(wl, addr, chunk, CHUNK_SIZE, false); | 168 | wl1271_write(wl, addr, chunk, CHUNK_SIZE, false); |
168 | 169 | ||
169 | chunk_num++; | 170 | chunk_num++; |
170 | } | 171 | } |
@@ -175,7 +176,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
175 | memcpy(chunk, p, fw_data_len % CHUNK_SIZE); | 176 | memcpy(chunk, p, fw_data_len % CHUNK_SIZE); |
176 | wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x", | 177 | wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x", |
177 | fw_data_len % CHUNK_SIZE, p, addr); | 178 | fw_data_len % CHUNK_SIZE, p, addr); |
178 | wl1271_spi_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false); | 179 | wl1271_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false); |
179 | 180 | ||
180 | kfree(chunk); | 181 | kfree(chunk); |
181 | return 0; | 182 | return 0; |
@@ -219,23 +220,14 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
219 | size_t nvs_len, burst_len; | 220 | size_t nvs_len, burst_len; |
220 | int i; | 221 | int i; |
221 | u32 dest_addr, val; | 222 | u32 dest_addr, val; |
222 | u8 *nvs_ptr, *nvs, *nvs_aligned; | 223 | u8 *nvs_ptr, *nvs_aligned; |
223 | 224 | ||
224 | nvs = wl->nvs; | 225 | if (wl->nvs == NULL) |
225 | if (nvs == NULL) | ||
226 | return -ENODEV; | 226 | return -ENODEV; |
227 | 227 | ||
228 | nvs_ptr = nvs; | 228 | /* only the first part of the NVS needs to be uploaded */ |
229 | 229 | nvs_len = sizeof(wl->nvs->nvs); | |
230 | nvs_len = wl->nvs_len; | 230 | nvs_ptr = (u8 *)wl->nvs->nvs; |
231 | |||
232 | /* Update the device MAC address into the nvs */ | ||
233 | nvs[11] = wl->mac_addr[0]; | ||
234 | nvs[10] = wl->mac_addr[1]; | ||
235 | nvs[6] = wl->mac_addr[2]; | ||
236 | nvs[5] = wl->mac_addr[3]; | ||
237 | nvs[4] = wl->mac_addr[4]; | ||
238 | nvs[3] = wl->mac_addr[5]; | ||
239 | 231 | ||
240 | /* | 232 | /* |
241 | * Layout before the actual NVS tables: | 233 | * Layout before the actual NVS tables: |
@@ -265,7 +257,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
265 | wl1271_debug(DEBUG_BOOT, | 257 | wl1271_debug(DEBUG_BOOT, |
266 | "nvs burst write 0x%x: 0x%x", | 258 | "nvs burst write 0x%x: 0x%x", |
267 | dest_addr, val); | 259 | dest_addr, val); |
268 | wl1271_spi_write32(wl, dest_addr, val); | 260 | wl1271_write32(wl, dest_addr, val); |
269 | 261 | ||
270 | nvs_ptr += 4; | 262 | nvs_ptr += 4; |
271 | dest_addr += 4; | 263 | dest_addr += 4; |
@@ -277,7 +269,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
277 | * is 7 bytes further. | 269 | * is 7 bytes further. |
278 | */ | 270 | */ |
279 | nvs_ptr += 7; | 271 | nvs_ptr += 7; |
280 | nvs_len -= nvs_ptr - nvs; | 272 | nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs; |
281 | nvs_len = ALIGN(nvs_len, 4); | 273 | nvs_len = ALIGN(nvs_len, 4); |
282 | 274 | ||
283 | /* FIXME: The driver sets the partition here, but this is not needed, | 275 | /* FIXME: The driver sets the partition here, but this is not needed, |
@@ -286,15 +278,20 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
286 | wl1271_set_partition(wl, &part_table[PART_WORK]); | 278 | wl1271_set_partition(wl, &part_table[PART_WORK]); |
287 | 279 | ||
288 | /* Copy the NVS tables to a new block to ensure alignment */ | 280 | /* Copy the NVS tables to a new block to ensure alignment */ |
289 | nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); | 281 | /* FIXME: We jump 3 more bytes before uploading the NVS. It seems |
290 | if (!nvs_aligned) | 282 | that our NVS files have three extra zeros here. I'm not sure whether |
291 | return -ENOMEM; | 283 | the problem is in our NVS generation or we should really jumpt these |
284 | 3 bytes here */ | ||
285 | nvs_ptr += 3; | ||
286 | |||
287 | nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); if | ||
288 | (!nvs_aligned) return -ENOMEM; | ||
292 | 289 | ||
293 | /* And finally we upload the NVS tables */ | 290 | /* And finally we upload the NVS tables */ |
294 | /* FIXME: In wl1271, we upload everything at once. | 291 | /* FIXME: In wl1271, we upload everything at once. |
295 | No endianness handling needed here?! The ref driver doesn't do | 292 | No endianness handling needed here?! The ref driver doesn't do |
296 | anything about it at this point */ | 293 | anything about it at this point */ |
297 | wl1271_spi_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false); | 294 | wl1271_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false); |
298 | 295 | ||
299 | kfree(nvs_aligned); | 296 | kfree(nvs_aligned); |
300 | return 0; | 297 | return 0; |
@@ -303,9 +300,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
303 | static void wl1271_boot_enable_interrupts(struct wl1271 *wl) | 300 | static void wl1271_boot_enable_interrupts(struct wl1271 *wl) |
304 | { | 301 | { |
305 | enable_irq(wl->irq); | 302 | enable_irq(wl->irq); |
306 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, | 303 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, |
307 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); | 304 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); |
308 | wl1271_spi_write32(wl, HI_CFG, HI_CFG_DEF_VAL); | 305 | wl1271_write32(wl, HI_CFG, HI_CFG_DEF_VAL); |
309 | } | 306 | } |
310 | 307 | ||
311 | static int wl1271_boot_soft_reset(struct wl1271 *wl) | 308 | static int wl1271_boot_soft_reset(struct wl1271 *wl) |
@@ -314,13 +311,12 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl) | |||
314 | u32 boot_data; | 311 | u32 boot_data; |
315 | 312 | ||
316 | /* perform soft reset */ | 313 | /* perform soft reset */ |
317 | wl1271_spi_write32(wl, ACX_REG_SLV_SOFT_RESET, | 314 | wl1271_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); |
318 | ACX_SLV_SOFT_RESET_BIT); | ||
319 | 315 | ||
320 | /* SOFT_RESET is self clearing */ | 316 | /* SOFT_RESET is self clearing */ |
321 | timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); | 317 | timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); |
322 | while (1) { | 318 | while (1) { |
323 | boot_data = wl1271_spi_read32(wl, ACX_REG_SLV_SOFT_RESET); | 319 | boot_data = wl1271_read32(wl, ACX_REG_SLV_SOFT_RESET); |
324 | wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); | 320 | wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); |
325 | if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) | 321 | if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) |
326 | break; | 322 | break; |
@@ -336,10 +332,10 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl) | |||
336 | } | 332 | } |
337 | 333 | ||
338 | /* disable Rx/Tx */ | 334 | /* disable Rx/Tx */ |
339 | wl1271_spi_write32(wl, ENABLE, 0x0); | 335 | wl1271_write32(wl, ENABLE, 0x0); |
340 | 336 | ||
341 | /* disable auto calibration on start*/ | 337 | /* disable auto calibration on start*/ |
342 | wl1271_spi_write32(wl, SPARE_A2, 0xffff); | 338 | wl1271_write32(wl, SPARE_A2, 0xffff); |
343 | 339 | ||
344 | return 0; | 340 | return 0; |
345 | } | 341 | } |
@@ -351,7 +347,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
351 | 347 | ||
352 | wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); | 348 | wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); |
353 | 349 | ||
354 | chip_id = wl1271_spi_read32(wl, CHIP_ID_B); | 350 | chip_id = wl1271_read32(wl, CHIP_ID_B); |
355 | 351 | ||
356 | wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); | 352 | wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); |
357 | 353 | ||
@@ -364,8 +360,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
364 | loop = 0; | 360 | loop = 0; |
365 | while (loop++ < INIT_LOOP) { | 361 | while (loop++ < INIT_LOOP) { |
366 | udelay(INIT_LOOP_DELAY); | 362 | udelay(INIT_LOOP_DELAY); |
367 | interrupt = wl1271_spi_read32(wl, | 363 | interrupt = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); |
368 | ACX_REG_INTERRUPT_NO_CLEAR); | ||
369 | 364 | ||
370 | if (interrupt == 0xffffffff) { | 365 | if (interrupt == 0xffffffff) { |
371 | wl1271_error("error reading hardware complete " | 366 | wl1271_error("error reading hardware complete " |
@@ -374,8 +369,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
374 | } | 369 | } |
375 | /* check that ACX_INTR_INIT_COMPLETE is enabled */ | 370 | /* check that ACX_INTR_INIT_COMPLETE is enabled */ |
376 | else if (interrupt & WL1271_ACX_INTR_INIT_COMPLETE) { | 371 | else if (interrupt & WL1271_ACX_INTR_INIT_COMPLETE) { |
377 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_ACK, | 372 | wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, |
378 | WL1271_ACX_INTR_INIT_COMPLETE); | 373 | WL1271_ACX_INTR_INIT_COMPLETE); |
379 | break; | 374 | break; |
380 | } | 375 | } |
381 | } | 376 | } |
@@ -387,10 +382,10 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
387 | } | 382 | } |
388 | 383 | ||
389 | /* get hardware config command mail box */ | 384 | /* get hardware config command mail box */ |
390 | wl->cmd_box_addr = wl1271_spi_read32(wl, REG_COMMAND_MAILBOX_PTR); | 385 | wl->cmd_box_addr = wl1271_read32(wl, REG_COMMAND_MAILBOX_PTR); |
391 | 386 | ||
392 | /* get hardware config event mail box */ | 387 | /* get hardware config event mail box */ |
393 | wl->event_box_addr = wl1271_spi_read32(wl, REG_EVENT_MAILBOX_PTR); | 388 | wl->event_box_addr = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR); |
394 | 389 | ||
395 | /* set the working partition to its "running" mode offset */ | 390 | /* set the working partition to its "running" mode offset */ |
396 | wl1271_set_partition(wl, &part_table[PART_WORK]); | 391 | wl1271_set_partition(wl, &part_table[PART_WORK]); |
@@ -463,9 +458,9 @@ int wl1271_boot(struct wl1271 *wl) | |||
463 | wl1271_top_reg_write(wl, OCP_REG_CLK_POLARITY, val); | 458 | wl1271_top_reg_write(wl, OCP_REG_CLK_POLARITY, val); |
464 | } | 459 | } |
465 | 460 | ||
466 | wl1271_spi_write32(wl, PLL_PARAMETERS, clk); | 461 | wl1271_write32(wl, PLL_PARAMETERS, clk); |
467 | 462 | ||
468 | pause = wl1271_spi_read32(wl, PLL_PARAMETERS); | 463 | pause = wl1271_read32(wl, PLL_PARAMETERS); |
469 | 464 | ||
470 | wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); | 465 | wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); |
471 | 466 | ||
@@ -474,10 +469,10 @@ int wl1271_boot(struct wl1271 *wl) | |||
474 | * 0x3ff (magic number ). How does | 469 | * 0x3ff (magic number ). How does |
475 | * this work?! */ | 470 | * this work?! */ |
476 | pause |= WU_COUNTER_PAUSE_VAL; | 471 | pause |= WU_COUNTER_PAUSE_VAL; |
477 | wl1271_spi_write32(wl, WU_COUNTER_PAUSE, pause); | 472 | wl1271_write32(wl, WU_COUNTER_PAUSE, pause); |
478 | 473 | ||
479 | /* Continue the ELP wake up sequence */ | 474 | /* Continue the ELP wake up sequence */ |
480 | wl1271_spi_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); | 475 | wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); |
481 | udelay(500); | 476 | udelay(500); |
482 | 477 | ||
483 | wl1271_set_partition(wl, &part_table[PART_DRPW]); | 478 | wl1271_set_partition(wl, &part_table[PART_DRPW]); |
@@ -487,18 +482,18 @@ int wl1271_boot(struct wl1271 *wl) | |||
487 | before taking DRPw out of reset */ | 482 | before taking DRPw out of reset */ |
488 | 483 | ||
489 | wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START); | 484 | wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START); |
490 | clk = wl1271_spi_read32(wl, DRPW_SCRATCH_START); | 485 | clk = wl1271_read32(wl, DRPW_SCRATCH_START); |
491 | 486 | ||
492 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); | 487 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); |
493 | 488 | ||
494 | /* 2 */ | 489 | /* 2 */ |
495 | clk |= (REF_CLOCK << 1) << 4; | 490 | clk |= (REF_CLOCK << 1) << 4; |
496 | wl1271_spi_write32(wl, DRPW_SCRATCH_START, clk); | 491 | wl1271_write32(wl, DRPW_SCRATCH_START, clk); |
497 | 492 | ||
498 | wl1271_set_partition(wl, &part_table[PART_WORK]); | 493 | wl1271_set_partition(wl, &part_table[PART_WORK]); |
499 | 494 | ||
500 | /* Disable interrupts */ | 495 | /* Disable interrupts */ |
501 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | 496 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); |
502 | 497 | ||
503 | ret = wl1271_boot_soft_reset(wl); | 498 | ret = wl1271_boot_soft_reset(wl); |
504 | if (ret < 0) | 499 | if (ret < 0) |
@@ -513,23 +508,22 @@ int wl1271_boot(struct wl1271 *wl) | |||
513 | * ACX_EEPROMLESS_IND_REG */ | 508 | * ACX_EEPROMLESS_IND_REG */ |
514 | wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG"); | 509 | wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG"); |
515 | 510 | ||
516 | wl1271_spi_write32(wl, ACX_EEPROMLESS_IND_REG, | 511 | wl1271_write32(wl, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG); |
517 | ACX_EEPROMLESS_IND_REG); | ||
518 | 512 | ||
519 | tmp = wl1271_spi_read32(wl, CHIP_ID_B); | 513 | tmp = wl1271_read32(wl, CHIP_ID_B); |
520 | 514 | ||
521 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); | 515 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); |
522 | 516 | ||
523 | /* 6. read the EEPROM parameters */ | 517 | /* 6. read the EEPROM parameters */ |
524 | tmp = wl1271_spi_read32(wl, SCR_PAD2); | 518 | tmp = wl1271_read32(wl, SCR_PAD2); |
525 | 519 | ||
526 | ret = wl1271_boot_write_irq_polarity(wl); | 520 | ret = wl1271_boot_write_irq_polarity(wl); |
527 | if (ret < 0) | 521 | if (ret < 0) |
528 | goto out; | 522 | goto out; |
529 | 523 | ||
530 | /* FIXME: Need to check whether this is really what we want */ | 524 | /* FIXME: Need to check whether this is really what we want */ |
531 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, | 525 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, |
532 | WL1271_ACX_ALL_EVENTS_VECTOR); | 526 | WL1271_ACX_ALL_EVENTS_VECTOR); |
533 | 527 | ||
534 | /* WL1271: The reference driver skips steps 7 to 10 (jumps directly | 528 | /* WL1271: The reference driver skips steps 7 to 10 (jumps directly |
535 | * to upload_fw) */ | 529 | * to upload_fw) */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index c3385b3d246c..36a64e06f290 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "wl1271.h" | 30 | #include "wl1271.h" |
31 | #include "wl1271_reg.h" | 31 | #include "wl1271_reg.h" |
32 | #include "wl1271_spi.h" | 32 | #include "wl1271_spi.h" |
33 | #include "wl1271_io.h" | ||
33 | #include "wl1271_acx.h" | 34 | #include "wl1271_acx.h" |
34 | #include "wl12xx_80211.h" | 35 | #include "wl12xx_80211.h" |
35 | #include "wl1271_cmd.h" | 36 | #include "wl1271_cmd.h" |
@@ -57,13 +58,13 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
57 | 58 | ||
58 | WARN_ON(len % 4 != 0); | 59 | WARN_ON(len % 4 != 0); |
59 | 60 | ||
60 | wl1271_spi_write(wl, wl->cmd_box_addr, buf, len, false); | 61 | wl1271_write(wl, wl->cmd_box_addr, buf, len, false); |
61 | 62 | ||
62 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD); | 63 | wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD); |
63 | 64 | ||
64 | timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); | 65 | timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); |
65 | 66 | ||
66 | intr = wl1271_spi_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); | 67 | intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); |
67 | while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { | 68 | while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { |
68 | if (time_after(jiffies, timeout)) { | 69 | if (time_after(jiffies, timeout)) { |
69 | wl1271_error("command complete timeout"); | 70 | wl1271_error("command complete timeout"); |
@@ -73,13 +74,13 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
73 | 74 | ||
74 | msleep(1); | 75 | msleep(1); |
75 | 76 | ||
76 | intr = wl1271_spi_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); | 77 | intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); |
77 | } | 78 | } |
78 | 79 | ||
79 | /* read back the status code of the command */ | 80 | /* read back the status code of the command */ |
80 | if (res_len == 0) | 81 | if (res_len == 0) |
81 | res_len = sizeof(struct wl1271_cmd_header); | 82 | res_len = sizeof(struct wl1271_cmd_header); |
82 | wl1271_spi_read(wl, wl->cmd_box_addr, cmd, res_len, false); | 83 | wl1271_read(wl, wl->cmd_box_addr, cmd, res_len, false); |
83 | 84 | ||
84 | status = le16_to_cpu(cmd->status); | 85 | status = le16_to_cpu(cmd->status); |
85 | if (status != CMD_STATUS_SUCCESS) { | 86 | if (status != CMD_STATUS_SUCCESS) { |
@@ -87,8 +88,8 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
87 | ret = -EIO; | 88 | ret = -EIO; |
88 | } | 89 | } |
89 | 90 | ||
90 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_ACK, | 91 | wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, |
91 | WL1271_ACX_INTR_CMD_COMPLETE); | 92 | WL1271_ACX_INTR_CMD_COMPLETE); |
92 | 93 | ||
93 | out: | 94 | out: |
94 | return ret; | 95 | return ret; |
@@ -191,23 +192,19 @@ static int wl1271_cmd_cal(struct wl1271 *wl) | |||
191 | int wl1271_cmd_general_parms(struct wl1271 *wl) | 192 | int wl1271_cmd_general_parms(struct wl1271 *wl) |
192 | { | 193 | { |
193 | struct wl1271_general_parms_cmd *gen_parms; | 194 | struct wl1271_general_parms_cmd *gen_parms; |
194 | struct conf_general_parms *g = &wl->conf.init.genparam; | ||
195 | int ret; | 195 | int ret; |
196 | 196 | ||
197 | if (!wl->nvs) | ||
198 | return -ENODEV; | ||
199 | |||
197 | gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); | 200 | gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); |
198 | if (!gen_parms) | 201 | if (!gen_parms) |
199 | return -ENOMEM; | 202 | return -ENOMEM; |
200 | 203 | ||
201 | gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; | 204 | gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; |
202 | 205 | ||
203 | gen_parms->ref_clk = g->ref_clk; | 206 | memcpy(gen_parms->params, wl->nvs->general_params, |
204 | gen_parms->settling_time = g->settling_time; | 207 | WL1271_NVS_GENERAL_PARAMS_SIZE); |
205 | gen_parms->clk_valid_on_wakeup = g->clk_valid_on_wakeup; | ||
206 | gen_parms->dc2dcmode = g->dc2dcmode; | ||
207 | gen_parms->single_dual_band = g->single_dual_band; | ||
208 | gen_parms->tx_bip_fem_autodetect = g->tx_bip_fem_autodetect; | ||
209 | gen_parms->tx_bip_fem_manufacturer = g->tx_bip_fem_manufacturer; | ||
210 | gen_parms->settings = g->settings; | ||
211 | 208 | ||
212 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0); | 209 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0); |
213 | if (ret < 0) | 210 | if (ret < 0) |
@@ -220,8 +217,11 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) | |||
220 | int wl1271_cmd_radio_parms(struct wl1271 *wl) | 217 | int wl1271_cmd_radio_parms(struct wl1271 *wl) |
221 | { | 218 | { |
222 | struct wl1271_radio_parms_cmd *radio_parms; | 219 | struct wl1271_radio_parms_cmd *radio_parms; |
223 | struct conf_radio_parms *r = &wl->conf.init.radioparam; | 220 | struct conf_radio_parms *rparam = &wl->conf.init.radioparam; |
224 | int i, ret; | 221 | int ret; |
222 | |||
223 | if (!wl->nvs) | ||
224 | return -ENODEV; | ||
225 | 225 | ||
226 | radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); | 226 | radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); |
227 | if (!radio_parms) | 227 | if (!radio_parms) |
@@ -229,60 +229,13 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
229 | 229 | ||
230 | radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; | 230 | radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; |
231 | 231 | ||
232 | /* Static radio parameters */ | 232 | memcpy(radio_parms->stat_radio_params, wl->nvs->stat_radio_params, |
233 | radio_parms->rx_trace_loss = r->rx_trace_loss; | 233 | WL1271_NVS_STAT_RADIO_PARAMS_SIZE); |
234 | radio_parms->tx_trace_loss = r->tx_trace_loss; | 234 | memcpy(radio_parms->dyn_radio_params, |
235 | memcpy(radio_parms->rx_rssi_and_proc_compens, | 235 | wl->nvs->dyn_radio_params[rparam->fem], |
236 | r->rx_rssi_and_proc_compens, | 236 | WL1271_NVS_DYN_RADIO_PARAMS_SIZE); |
237 | CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE); | 237 | |
238 | 238 | /* FIXME: current NVS is missing 5GHz parameters */ | |
239 | memcpy(radio_parms->rx_trace_loss_5, r->rx_trace_loss_5, | ||
240 | CONF_NUMBER_OF_SUB_BANDS_5); | ||
241 | memcpy(radio_parms->tx_trace_loss_5, r->tx_trace_loss_5, | ||
242 | CONF_NUMBER_OF_SUB_BANDS_5); | ||
243 | memcpy(radio_parms->rx_rssi_and_proc_compens_5, | ||
244 | r->rx_rssi_and_proc_compens_5, | ||
245 | CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE); | ||
246 | |||
247 | /* Dynamic radio parameters */ | ||
248 | radio_parms->tx_ref_pd_voltage = cpu_to_le16(r->tx_ref_pd_voltage); | ||
249 | radio_parms->tx_ref_power = r->tx_ref_power; | ||
250 | radio_parms->tx_offset_db = r->tx_offset_db; | ||
251 | |||
252 | memcpy(radio_parms->tx_rate_limits_normal, r->tx_rate_limits_normal, | ||
253 | CONF_NUMBER_OF_RATE_GROUPS); | ||
254 | memcpy(radio_parms->tx_rate_limits_degraded, r->tx_rate_limits_degraded, | ||
255 | CONF_NUMBER_OF_RATE_GROUPS); | ||
256 | |||
257 | memcpy(radio_parms->tx_channel_limits_11b, r->tx_channel_limits_11b, | ||
258 | CONF_NUMBER_OF_CHANNELS_2_4); | ||
259 | memcpy(radio_parms->tx_channel_limits_ofdm, r->tx_channel_limits_ofdm, | ||
260 | CONF_NUMBER_OF_CHANNELS_2_4); | ||
261 | memcpy(radio_parms->tx_pdv_rate_offsets, r->tx_pdv_rate_offsets, | ||
262 | CONF_NUMBER_OF_RATE_GROUPS); | ||
263 | memcpy(radio_parms->tx_ibias, r->tx_ibias, CONF_NUMBER_OF_RATE_GROUPS); | ||
264 | |||
265 | radio_parms->rx_fem_insertion_loss = r->rx_fem_insertion_loss; | ||
266 | |||
267 | for (i = 0; i < CONF_NUMBER_OF_SUB_BANDS_5; i++) | ||
268 | radio_parms->tx_ref_pd_voltage_5[i] = | ||
269 | cpu_to_le16(r->tx_ref_pd_voltage_5[i]); | ||
270 | memcpy(radio_parms->tx_ref_power_5, r->tx_ref_power_5, | ||
271 | CONF_NUMBER_OF_SUB_BANDS_5); | ||
272 | memcpy(radio_parms->tx_offset_db_5, r->tx_offset_db_5, | ||
273 | CONF_NUMBER_OF_SUB_BANDS_5); | ||
274 | memcpy(radio_parms->tx_rate_limits_normal_5, | ||
275 | r->tx_rate_limits_normal_5, CONF_NUMBER_OF_RATE_GROUPS); | ||
276 | memcpy(radio_parms->tx_rate_limits_degraded_5, | ||
277 | r->tx_rate_limits_degraded_5, CONF_NUMBER_OF_RATE_GROUPS); | ||
278 | memcpy(radio_parms->tx_channel_limits_ofdm_5, | ||
279 | r->tx_channel_limits_ofdm_5, CONF_NUMBER_OF_CHANNELS_5); | ||
280 | memcpy(radio_parms->tx_pdv_rate_offsets_5, r->tx_pdv_rate_offsets_5, | ||
281 | CONF_NUMBER_OF_RATE_GROUPS); | ||
282 | memcpy(radio_parms->tx_ibias_5, r->tx_ibias_5, | ||
283 | CONF_NUMBER_OF_RATE_GROUPS); | ||
284 | memcpy(radio_parms->rx_fem_insertion_loss_5, | ||
285 | r->rx_fem_insertion_loss_5, CONF_NUMBER_OF_SUB_BANDS_5); | ||
286 | 239 | ||
287 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", | 240 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", |
288 | radio_parms, sizeof(*radio_parms)); | 241 | radio_parms, sizeof(*radio_parms)); |
@@ -311,19 +264,6 @@ int wl1271_cmd_join(struct wl1271 *wl) | |||
311 | do_cal = false; | 264 | do_cal = false; |
312 | } | 265 | } |
313 | 266 | ||
314 | /* FIXME: This is a workaround, because with the current stack, we | ||
315 | * cannot know when we have disassociated. So, if we have already | ||
316 | * joined, we disconnect before joining again. */ | ||
317 | if (wl->joined) { | ||
318 | ret = wl1271_cmd_disconnect(wl); | ||
319 | if (ret < 0) { | ||
320 | wl1271_error("failed to disconnect before rejoining"); | ||
321 | goto out; | ||
322 | } | ||
323 | |||
324 | wl->joined = false; | ||
325 | } | ||
326 | |||
327 | join = kzalloc(sizeof(*join), GFP_KERNEL); | 267 | join = kzalloc(sizeof(*join), GFP_KERNEL); |
328 | if (!join) { | 268 | if (!join) { |
329 | ret = -ENOMEM; | 269 | ret = -ENOMEM; |
@@ -388,8 +328,6 @@ int wl1271_cmd_join(struct wl1271 *wl) | |||
388 | goto out_free; | 328 | goto out_free; |
389 | } | 329 | } |
390 | 330 | ||
391 | wl->joined = true; | ||
392 | |||
393 | /* | 331 | /* |
394 | * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to | 332 | * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to |
395 | * simplify locking we just sleep instead, for now | 333 | * simplify locking we just sleep instead, for now |
@@ -487,7 +425,7 @@ int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len) | |||
487 | return 0; | 425 | return 0; |
488 | } | 426 | } |
489 | 427 | ||
490 | int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable) | 428 | int wl1271_cmd_data_path(struct wl1271 *wl, bool enable) |
491 | { | 429 | { |
492 | struct cmd_enabledisable_path *cmd; | 430 | struct cmd_enabledisable_path *cmd; |
493 | int ret; | 431 | int ret; |
@@ -501,7 +439,8 @@ int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable) | |||
501 | goto out; | 439 | goto out; |
502 | } | 440 | } |
503 | 441 | ||
504 | cmd->channel = channel; | 442 | /* the channel here is only used for calibration, so hardcoded to 1 */ |
443 | cmd->channel = 1; | ||
505 | 444 | ||
506 | if (enable) { | 445 | if (enable) { |
507 | cmd_rx = CMD_ENABLE_RX; | 446 | cmd_rx = CMD_ENABLE_RX; |
@@ -514,29 +453,29 @@ int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable) | |||
514 | ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd), 0); | 453 | ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd), 0); |
515 | if (ret < 0) { | 454 | if (ret < 0) { |
516 | wl1271_error("rx %s cmd for channel %d failed", | 455 | wl1271_error("rx %s cmd for channel %d failed", |
517 | enable ? "start" : "stop", channel); | 456 | enable ? "start" : "stop", cmd->channel); |
518 | goto out; | 457 | goto out; |
519 | } | 458 | } |
520 | 459 | ||
521 | wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d", | 460 | wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d", |
522 | enable ? "start" : "stop", channel); | 461 | enable ? "start" : "stop", cmd->channel); |
523 | 462 | ||
524 | ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd), 0); | 463 | ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd), 0); |
525 | if (ret < 0) { | 464 | if (ret < 0) { |
526 | wl1271_error("tx %s cmd for channel %d failed", | 465 | wl1271_error("tx %s cmd for channel %d failed", |
527 | enable ? "start" : "stop", channel); | 466 | enable ? "start" : "stop", cmd->channel); |
528 | return ret; | 467 | return ret; |
529 | } | 468 | } |
530 | 469 | ||
531 | wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", | 470 | wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", |
532 | enable ? "start" : "stop", channel); | 471 | enable ? "start" : "stop", cmd->channel); |
533 | 472 | ||
534 | out: | 473 | out: |
535 | kfree(cmd); | 474 | kfree(cmd); |
536 | return ret; | 475 | return ret; |
537 | } | 476 | } |
538 | 477 | ||
539 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode) | 478 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send) |
540 | { | 479 | { |
541 | struct wl1271_cmd_ps_params *ps_params = NULL; | 480 | struct wl1271_cmd_ps_params *ps_params = NULL; |
542 | int ret = 0; | 481 | int ret = 0; |
@@ -557,7 +496,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode) | |||
557 | } | 496 | } |
558 | 497 | ||
559 | ps_params->ps_mode = ps_mode; | 498 | ps_params->ps_mode = ps_mode; |
560 | ps_params->send_null_data = 1; | 499 | ps_params->send_null_data = send; |
561 | ps_params->retries = 5; | 500 | ps_params->retries = 5; |
562 | ps_params->hang_over_period = 128; | 501 | ps_params->hang_over_period = 128; |
563 | ps_params->null_data_rate = cpu_to_le32(1); /* 1 Mbps */ | 502 | ps_params->null_data_rate = cpu_to_le32(1); /* 1 Mbps */ |
@@ -636,7 +575,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
636 | channels = wl->hw->wiphy->bands[ieee_band]->channels; | 575 | channels = wl->hw->wiphy->bands[ieee_band]->channels; |
637 | n_ch = wl->hw->wiphy->bands[ieee_band]->n_channels; | 576 | n_ch = wl->hw->wiphy->bands[ieee_band]->n_channels; |
638 | 577 | ||
639 | if (wl->scanning) | 578 | if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) |
640 | return -EINVAL; | 579 | return -EINVAL; |
641 | 580 | ||
642 | params = kzalloc(sizeof(*params), GFP_KERNEL); | 581 | params = kzalloc(sizeof(*params), GFP_KERNEL); |
@@ -711,7 +650,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
711 | 650 | ||
712 | wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); | 651 | wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); |
713 | 652 | ||
714 | wl->scanning = true; | 653 | set_bit(WL1271_FLAG_SCANNING, &wl->flags); |
715 | if (wl1271_11a_enabled()) { | 654 | if (wl1271_11a_enabled()) { |
716 | wl->scan.state = band; | 655 | wl->scan.state = band; |
717 | if (band == WL1271_SCAN_BAND_DUAL) { | 656 | if (band == WL1271_SCAN_BAND_DUAL) { |
@@ -729,7 +668,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
729 | ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0); | 668 | ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0); |
730 | if (ret < 0) { | 669 | if (ret < 0) { |
731 | wl1271_error("SCAN failed"); | 670 | wl1271_error("SCAN failed"); |
732 | wl->scanning = false; | 671 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); |
733 | goto out; | 672 | goto out; |
734 | } | 673 | } |
735 | 674 | ||
@@ -1003,7 +942,7 @@ int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | |||
1003 | ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); | 942 | ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); |
1004 | if (ret < 0) { | 943 | if (ret < 0) { |
1005 | wl1271_warning("could not set keys"); | 944 | wl1271_warning("could not set keys"); |
1006 | goto out; | 945 | goto out; |
1007 | } | 946 | } |
1008 | 947 | ||
1009 | out: | 948 | out: |
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index b4fa4acb9229..2dc06c73532b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h | |||
@@ -37,8 +37,8 @@ int wl1271_cmd_join(struct wl1271 *wl); | |||
37 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); | 37 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); |
38 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); | 38 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); |
39 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); | 39 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); |
40 | int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable); | 40 | int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); |
41 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode); | 41 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send); |
42 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, | 42 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, |
43 | size_t len); | 43 | size_t len); |
44 | int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | 44 | int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, |
@@ -428,67 +428,24 @@ struct wl1271_general_parms_cmd { | |||
428 | 428 | ||
429 | struct wl1271_cmd_test_header test; | 429 | struct wl1271_cmd_test_header test; |
430 | 430 | ||
431 | u8 ref_clk; | 431 | u8 params[WL1271_NVS_GENERAL_PARAMS_SIZE]; |
432 | u8 settling_time; | 432 | s8 reserved[23]; |
433 | u8 clk_valid_on_wakeup; | ||
434 | u8 dc2dcmode; | ||
435 | u8 single_dual_band; | ||
436 | |||
437 | u8 tx_bip_fem_autodetect; | ||
438 | u8 tx_bip_fem_manufacturer; | ||
439 | u8 settings; | ||
440 | } __attribute__ ((packed)); | 433 | } __attribute__ ((packed)); |
441 | 434 | ||
435 | #define WL1271_STAT_RADIO_PARAMS_5_SIZE 29 | ||
436 | #define WL1271_DYN_RADIO_PARAMS_5_SIZE 104 | ||
437 | |||
442 | struct wl1271_radio_parms_cmd { | 438 | struct wl1271_radio_parms_cmd { |
443 | struct wl1271_cmd_header header; | 439 | struct wl1271_cmd_header header; |
444 | 440 | ||
445 | struct wl1271_cmd_test_header test; | 441 | struct wl1271_cmd_test_header test; |
446 | 442 | ||
447 | /* Static radio parameters */ | 443 | u8 stat_radio_params[WL1271_NVS_STAT_RADIO_PARAMS_SIZE]; |
448 | /* 2.4GHz */ | 444 | u8 stat_radio_params_5[WL1271_STAT_RADIO_PARAMS_5_SIZE]; |
449 | u8 rx_trace_loss; | ||
450 | u8 tx_trace_loss; | ||
451 | s8 rx_rssi_and_proc_compens[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE]; | ||
452 | |||
453 | /* 5GHz */ | ||
454 | u8 rx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
455 | u8 tx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
456 | s8 rx_rssi_and_proc_compens_5[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE]; | ||
457 | |||
458 | /* Dynamic radio parameters */ | ||
459 | /* 2.4GHz */ | ||
460 | __le16 tx_ref_pd_voltage; | ||
461 | s8 tx_ref_power; | ||
462 | s8 tx_offset_db; | ||
463 | |||
464 | s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS]; | ||
465 | s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS]; | ||
466 | |||
467 | s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4]; | ||
468 | s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4]; | ||
469 | s8 tx_pdv_rate_offsets[CONF_NUMBER_OF_RATE_GROUPS]; | ||
470 | |||
471 | u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS]; | ||
472 | u8 rx_fem_insertion_loss; | ||
473 | 445 | ||
474 | u8 padding2; | 446 | u8 dyn_radio_params[WL1271_NVS_DYN_RADIO_PARAMS_SIZE]; |
475 | 447 | u8 reserved; | |
476 | /* 5GHz */ | 448 | u8 dyn_radio_params_5[WL1271_DYN_RADIO_PARAMS_5_SIZE]; |
477 | __le16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
478 | s8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
479 | s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
480 | |||
481 | s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
482 | s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
483 | |||
484 | s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5]; | ||
485 | s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
486 | |||
487 | /* FIXME: this is inconsistent with the types for 2.4GHz */ | ||
488 | s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
489 | s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
490 | |||
491 | u8 padding3[2]; | ||
492 | } __attribute__ ((packed)); | 449 | } __attribute__ ((packed)); |
493 | 450 | ||
494 | struct wl1271_cmd_cal_channel_tune { | 451 | struct wl1271_cmd_cal_channel_tune { |
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index 565373ede265..6f9e75cc5640 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h | |||
@@ -258,7 +258,8 @@ struct conf_rx_settings { | |||
258 | #define CONF_TX_MAX_RATE_CLASSES 8 | 258 | #define CONF_TX_MAX_RATE_CLASSES 8 |
259 | 259 | ||
260 | #define CONF_TX_RATE_MASK_UNSPECIFIED 0 | 260 | #define CONF_TX_RATE_MASK_UNSPECIFIED 0 |
261 | #define CONF_TX_RATE_MASK_ALL 0x1eff | 261 | #define CONF_TX_RATE_MASK_BASIC (CONF_HW_BIT_RATE_1MBPS | \ |
262 | CONF_HW_BIT_RATE_2MBPS) | ||
262 | #define CONF_TX_RATE_RETRY_LIMIT 10 | 263 | #define CONF_TX_RATE_RETRY_LIMIT 10 |
263 | 264 | ||
264 | struct conf_tx_rate_class { | 265 | struct conf_tx_rate_class { |
@@ -722,31 +723,6 @@ struct conf_conn_settings { | |||
722 | u8 psm_entry_retries; | 723 | u8 psm_entry_retries; |
723 | }; | 724 | }; |
724 | 725 | ||
725 | #define CONF_SR_ERR_TBL_MAX_VALUES 14 | ||
726 | |||
727 | struct conf_mart_reflex_err_table { | ||
728 | /* | ||
729 | * Length of the error table values table. | ||
730 | * | ||
731 | * Range: 0 - CONF_SR_ERR_TBL_MAX_VALUES | ||
732 | */ | ||
733 | u8 len; | ||
734 | |||
735 | /* | ||
736 | * Smart Reflex error table upper limit. | ||
737 | * | ||
738 | * Range: s8 | ||
739 | */ | ||
740 | s8 upper_limit; | ||
741 | |||
742 | /* | ||
743 | * Smart Reflex error table values. | ||
744 | * | ||
745 | * Range: s8 | ||
746 | */ | ||
747 | s8 values[CONF_SR_ERR_TBL_MAX_VALUES]; | ||
748 | }; | ||
749 | |||
750 | enum { | 726 | enum { |
751 | CONF_REF_CLK_19_2_E, | 727 | CONF_REF_CLK_19_2_E, |
752 | CONF_REF_CLK_26_E, | 728 | CONF_REF_CLK_26_E, |
@@ -759,64 +735,6 @@ enum single_dual_band_enum { | |||
759 | CONF_DUAL_BAND | 735 | CONF_DUAL_BAND |
760 | }; | 736 | }; |
761 | 737 | ||
762 | struct conf_general_parms { | ||
763 | /* | ||
764 | * RF Reference Clock type / speed | ||
765 | * | ||
766 | * Range: CONF_REF_CLK_* | ||
767 | */ | ||
768 | u8 ref_clk; | ||
769 | |||
770 | /* | ||
771 | * Settling time of the reference clock after boot. | ||
772 | * | ||
773 | * Range: u8 | ||
774 | */ | ||
775 | u8 settling_time; | ||
776 | |||
777 | /* | ||
778 | * Flag defining whether clock is valid on wakeup. | ||
779 | * | ||
780 | * Range: 0 - not valid on wakeup, 1 - valid on wakeup | ||
781 | */ | ||
782 | u8 clk_valid_on_wakeup; | ||
783 | |||
784 | /* | ||
785 | * DC-to-DC mode. | ||
786 | * | ||
787 | * Range: Unknown | ||
788 | */ | ||
789 | u8 dc2dcmode; | ||
790 | |||
791 | /* | ||
792 | * Flag defining whether used as single or dual-band. | ||
793 | * | ||
794 | * Range: CONF_SINGLE_BAND, CONF_DUAL_BAND | ||
795 | */ | ||
796 | u8 single_dual_band; | ||
797 | |||
798 | /* | ||
799 | * TX bip fem autodetect flag. | ||
800 | * | ||
801 | * Range: Unknown | ||
802 | */ | ||
803 | u8 tx_bip_fem_autodetect; | ||
804 | |||
805 | /* | ||
806 | * TX bip gem manufacturer. | ||
807 | * | ||
808 | * Range: Unknown | ||
809 | */ | ||
810 | u8 tx_bip_fem_manufacturer; | ||
811 | |||
812 | /* | ||
813 | * Settings flags. | ||
814 | * | ||
815 | * Range: Unknown | ||
816 | */ | ||
817 | u8 settings; | ||
818 | }; | ||
819 | |||
820 | #define CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE 15 | 738 | #define CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE 15 |
821 | #define CONF_NUMBER_OF_SUB_BANDS_5 7 | 739 | #define CONF_NUMBER_OF_SUB_BANDS_5 7 |
822 | #define CONF_NUMBER_OF_RATE_GROUPS 6 | 740 | #define CONF_NUMBER_OF_RATE_GROUPS 6 |
@@ -825,87 +743,43 @@ struct conf_general_parms { | |||
825 | 743 | ||
826 | struct conf_radio_parms { | 744 | struct conf_radio_parms { |
827 | /* | 745 | /* |
828 | * Static radio parameters for 2.4GHz | 746 | * FEM parameter set to use |
829 | * | ||
830 | * Range: unknown | ||
831 | */ | ||
832 | u8 rx_trace_loss; | ||
833 | u8 tx_trace_loss; | ||
834 | s8 rx_rssi_and_proc_compens[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE]; | ||
835 | |||
836 | /* | ||
837 | * Static radio parameters for 5GHz | ||
838 | * | ||
839 | * Range: unknown | ||
840 | */ | ||
841 | u8 rx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
842 | u8 tx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
843 | s8 rx_rssi_and_proc_compens_5[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE]; | ||
844 | |||
845 | /* | ||
846 | * Dynamic radio parameters for 2.4GHz | ||
847 | * | 747 | * |
848 | * Range: unknown | 748 | * Range: 0 or 1 |
849 | */ | 749 | */ |
850 | s16 tx_ref_pd_voltage; | 750 | u8 fem; |
851 | s8 tx_ref_power; | 751 | }; |
852 | s8 tx_offset_db; | ||
853 | |||
854 | s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS]; | ||
855 | s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS]; | ||
856 | |||
857 | s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4]; | ||
858 | s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4]; | ||
859 | s8 tx_pdv_rate_offsets[CONF_NUMBER_OF_RATE_GROUPS]; | ||
860 | |||
861 | u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS]; | ||
862 | u8 rx_fem_insertion_loss; | ||
863 | 752 | ||
753 | struct conf_init_settings { | ||
864 | /* | 754 | /* |
865 | * Dynamic radio parameters for 5GHz | 755 | * Configure radio parameters. |
866 | * | ||
867 | * Range: unknown | ||
868 | */ | 756 | */ |
869 | s16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 757 | struct conf_radio_parms radioparam; |
870 | s8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
871 | s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
872 | |||
873 | s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
874 | s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
875 | |||
876 | s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5]; | ||
877 | s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
878 | 758 | ||
879 | /* FIXME: this is inconsistent with the types for 2.4GHz */ | ||
880 | s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
881 | s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
882 | }; | 759 | }; |
883 | 760 | ||
884 | #define CONF_SR_ERR_TBL_COUNT 3 | 761 | struct conf_itrim_settings { |
762 | /* enable dco itrim */ | ||
763 | u8 enable; | ||
885 | 764 | ||
886 | struct conf_init_settings { | 765 | /* moderation timeout in microsecs from the last TX */ |
887 | /* | 766 | u32 timeout; |
888 | * Configure Smart Reflex error table values. | 767 | }; |
889 | */ | ||
890 | struct conf_mart_reflex_err_table sr_err_tbl[CONF_SR_ERR_TBL_COUNT]; | ||
891 | 768 | ||
769 | struct conf_pm_config_settings { | ||
892 | /* | 770 | /* |
893 | * Smart Reflex enable flag. | 771 | * Host clock settling time |
894 | * | 772 | * |
895 | * Range: 1 - Smart Reflex enabled, 0 - Smart Reflex disabled | 773 | * Range: 0 - 30000 us |
896 | */ | ||
897 | u8 sr_enable; | ||
898 | |||
899 | /* | ||
900 | * Configure general parameters. | ||
901 | */ | 774 | */ |
902 | struct conf_general_parms genparam; | 775 | u32 host_clk_settling_time; |
903 | 776 | ||
904 | /* | 777 | /* |
905 | * Configure radio parameters. | 778 | * Host fast wakeup support |
779 | * | ||
780 | * Range: true, false | ||
906 | */ | 781 | */ |
907 | struct conf_radio_parms radioparam; | 782 | bool host_fast_wakeup_support; |
908 | |||
909 | }; | 783 | }; |
910 | 784 | ||
911 | struct conf_drv_settings { | 785 | struct conf_drv_settings { |
@@ -914,6 +788,8 @@ struct conf_drv_settings { | |||
914 | struct conf_tx_settings tx; | 788 | struct conf_tx_settings tx; |
915 | struct conf_conn_settings conn; | 789 | struct conf_conn_settings conn; |
916 | struct conf_init_settings init; | 790 | struct conf_init_settings init; |
791 | struct conf_itrim_settings itrim; | ||
792 | struct conf_pm_config_settings pm_config; | ||
917 | }; | 793 | }; |
918 | 794 | ||
919 | #endif | 795 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.c b/drivers/net/wireless/wl12xx/wl1271_debugfs.c index c1805e5f8964..8d7588ca68fd 100644 --- a/drivers/net/wireless/wl12xx/wl1271_debugfs.c +++ b/drivers/net/wireless/wl12xx/wl1271_debugfs.c | |||
@@ -237,6 +237,64 @@ static const struct file_operations tx_queue_len_ops = { | |||
237 | .open = wl1271_open_file_generic, | 237 | .open = wl1271_open_file_generic, |
238 | }; | 238 | }; |
239 | 239 | ||
240 | static ssize_t gpio_power_read(struct file *file, char __user *user_buf, | ||
241 | size_t count, loff_t *ppos) | ||
242 | { | ||
243 | struct wl1271 *wl = file->private_data; | ||
244 | bool state = test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
245 | |||
246 | int res; | ||
247 | char buf[10]; | ||
248 | |||
249 | res = scnprintf(buf, sizeof(buf), "%d\n", state); | ||
250 | |||
251 | return simple_read_from_buffer(user_buf, count, ppos, buf, res); | ||
252 | } | ||
253 | |||
254 | static ssize_t gpio_power_write(struct file *file, | ||
255 | const char __user *user_buf, | ||
256 | size_t count, loff_t *ppos) | ||
257 | { | ||
258 | struct wl1271 *wl = file->private_data; | ||
259 | char buf[10]; | ||
260 | size_t len; | ||
261 | unsigned long value; | ||
262 | int ret; | ||
263 | |||
264 | mutex_lock(&wl->mutex); | ||
265 | |||
266 | len = min(count, sizeof(buf) - 1); | ||
267 | if (copy_from_user(buf, user_buf, len)) { | ||
268 | ret = -EFAULT; | ||
269 | goto out; | ||
270 | } | ||
271 | buf[len] = '\0'; | ||
272 | |||
273 | ret = strict_strtoul(buf, 0, &value); | ||
274 | if (ret < 0) { | ||
275 | wl1271_warning("illegal value in gpio_power"); | ||
276 | goto out; | ||
277 | } | ||
278 | |||
279 | if (value) { | ||
280 | wl->set_power(true); | ||
281 | set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
282 | } else { | ||
283 | wl->set_power(false); | ||
284 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
285 | } | ||
286 | |||
287 | out: | ||
288 | mutex_unlock(&wl->mutex); | ||
289 | return count; | ||
290 | } | ||
291 | |||
292 | static const struct file_operations gpio_power_ops = { | ||
293 | .read = gpio_power_read, | ||
294 | .write = gpio_power_write, | ||
295 | .open = wl1271_open_file_generic | ||
296 | }; | ||
297 | |||
240 | static void wl1271_debugfs_delete_files(struct wl1271 *wl) | 298 | static void wl1271_debugfs_delete_files(struct wl1271 *wl) |
241 | { | 299 | { |
242 | DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); | 300 | DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); |
@@ -333,6 +391,8 @@ static void wl1271_debugfs_delete_files(struct wl1271 *wl) | |||
333 | DEBUGFS_DEL(tx_queue_len); | 391 | DEBUGFS_DEL(tx_queue_len); |
334 | DEBUGFS_DEL(retry_count); | 392 | DEBUGFS_DEL(retry_count); |
335 | DEBUGFS_DEL(excessive_retries); | 393 | DEBUGFS_DEL(excessive_retries); |
394 | |||
395 | DEBUGFS_DEL(gpio_power); | ||
336 | } | 396 | } |
337 | 397 | ||
338 | static int wl1271_debugfs_add_files(struct wl1271 *wl) | 398 | static int wl1271_debugfs_add_files(struct wl1271 *wl) |
@@ -434,6 +494,8 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl) | |||
434 | DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); | 494 | DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); |
435 | DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); | 495 | DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); |
436 | 496 | ||
497 | DEBUGFS_ADD(gpio_power, wl->debugfs.rootdir); | ||
498 | |||
437 | out: | 499 | out: |
438 | if (ret < 0) | 500 | if (ret < 0) |
439 | wl1271_debugfs_delete_files(wl); | 501 | wl1271_debugfs_delete_files(wl); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index d13fdd99c85c..7468ef10194b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "wl1271.h" | 24 | #include "wl1271.h" |
25 | #include "wl1271_reg.h" | 25 | #include "wl1271_reg.h" |
26 | #include "wl1271_spi.h" | 26 | #include "wl1271_spi.h" |
27 | #include "wl1271_io.h" | ||
27 | #include "wl1271_event.h" | 28 | #include "wl1271_event.h" |
28 | #include "wl1271_ps.h" | 29 | #include "wl1271_ps.h" |
29 | #include "wl12xx_80211.h" | 30 | #include "wl12xx_80211.h" |
@@ -35,7 +36,7 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, | |||
35 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", | 36 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", |
36 | mbox->scheduled_scan_status); | 37 | mbox->scheduled_scan_status); |
37 | 38 | ||
38 | if (wl->scanning) { | 39 | if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) { |
39 | if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { | 40 | if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { |
40 | wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, | 41 | wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, |
41 | NULL, size); | 42 | NULL, size); |
@@ -43,7 +44,7 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, | |||
43 | * to the wl1271_cmd_scan function that we are not | 44 | * to the wl1271_cmd_scan function that we are not |
44 | * scanning as it checks that. | 45 | * scanning as it checks that. |
45 | */ | 46 | */ |
46 | wl->scanning = false; | 47 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); |
47 | wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, | 48 | wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, |
48 | wl->scan.active, | 49 | wl->scan.active, |
49 | wl->scan.high_prio, | 50 | wl->scan.high_prio, |
@@ -62,7 +63,7 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, | |||
62 | mutex_unlock(&wl->mutex); | 63 | mutex_unlock(&wl->mutex); |
63 | ieee80211_scan_completed(wl->hw, false); | 64 | ieee80211_scan_completed(wl->hw, false); |
64 | mutex_lock(&wl->mutex); | 65 | mutex_lock(&wl->mutex); |
65 | wl->scanning = false; | 66 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); |
66 | } | 67 | } |
67 | } | 68 | } |
68 | return 0; | 69 | return 0; |
@@ -78,25 +79,61 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
78 | 79 | ||
79 | switch (mbox->ps_status) { | 80 | switch (mbox->ps_status) { |
80 | case EVENT_ENTER_POWER_SAVE_FAIL: | 81 | case EVENT_ENTER_POWER_SAVE_FAIL: |
81 | if (!wl->psm) { | 82 | wl1271_debug(DEBUG_PSM, "PSM entry failed"); |
83 | |||
84 | if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) { | ||
85 | /* remain in active mode */ | ||
82 | wl->psm_entry_retry = 0; | 86 | wl->psm_entry_retry = 0; |
83 | break; | 87 | break; |
84 | } | 88 | } |
85 | 89 | ||
86 | if (wl->psm_entry_retry < wl->conf.conn.psm_entry_retries) { | 90 | if (wl->psm_entry_retry < wl->conf.conn.psm_entry_retries) { |
87 | wl->psm_entry_retry++; | 91 | wl->psm_entry_retry++; |
88 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); | 92 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, |
93 | true); | ||
89 | } else { | 94 | } else { |
90 | wl1271_error("PSM entry failed, giving up.\n"); | 95 | wl1271_error("PSM entry failed, giving up.\n"); |
96 | /* FIXME: this may need to be reconsidered. for now it | ||
97 | is not possible to indicate to the mac80211 | ||
98 | afterwards that PSM entry failed. To maximize | ||
99 | functionality (receiving data and remaining | ||
100 | associated) make sure that we are in sync with the | ||
101 | AP in regard of PSM mode. */ | ||
102 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, | ||
103 | false); | ||
91 | wl->psm_entry_retry = 0; | 104 | wl->psm_entry_retry = 0; |
92 | *beacon_loss = true; | ||
93 | } | 105 | } |
94 | break; | 106 | break; |
95 | case EVENT_ENTER_POWER_SAVE_SUCCESS: | 107 | case EVENT_ENTER_POWER_SAVE_SUCCESS: |
96 | wl->psm_entry_retry = 0; | 108 | wl->psm_entry_retry = 0; |
109 | |||
110 | /* enable beacon filtering */ | ||
111 | ret = wl1271_acx_beacon_filter_opt(wl, true); | ||
112 | if (ret < 0) | ||
113 | break; | ||
114 | |||
115 | /* enable beacon early termination */ | ||
116 | ret = wl1271_acx_bet_enable(wl, true); | ||
117 | if (ret < 0) | ||
118 | break; | ||
119 | |||
120 | /* go to extremely low power mode */ | ||
121 | wl1271_ps_elp_sleep(wl); | ||
122 | if (ret < 0) | ||
123 | break; | ||
97 | break; | 124 | break; |
98 | case EVENT_EXIT_POWER_SAVE_FAIL: | 125 | case EVENT_EXIT_POWER_SAVE_FAIL: |
99 | wl1271_info("PSM exit failed"); | 126 | wl1271_debug(DEBUG_PSM, "PSM exit failed"); |
127 | |||
128 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { | ||
129 | wl->psm_entry_retry = 0; | ||
130 | break; | ||
131 | } | ||
132 | |||
133 | /* make sure the firmware goes to active mode - the frame to | ||
134 | be sent next will indicate to the AP, that we are active. */ | ||
135 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, | ||
136 | false); | ||
100 | break; | 137 | break; |
101 | case EVENT_EXIT_POWER_SAVE_SUCCESS: | 138 | case EVENT_EXIT_POWER_SAVE_SUCCESS: |
102 | default: | 139 | default: |
@@ -136,7 +173,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
136 | * filtering) is enabled. Without PSM, the stack will receive all | 173 | * filtering) is enabled. Without PSM, the stack will receive all |
137 | * beacons and can detect beacon loss by itself. | 174 | * beacons and can detect beacon loss by itself. |
138 | */ | 175 | */ |
139 | if (vector & BSS_LOSE_EVENT_ID && wl->psm) { | 176 | if (vector & BSS_LOSE_EVENT_ID && |
177 | test_bit(WL1271_FLAG_PSM, &wl->flags)) { | ||
140 | wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); | 178 | wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); |
141 | 179 | ||
142 | /* indicate to the stack, that beacons have been lost */ | 180 | /* indicate to the stack, that beacons have been lost */ |
@@ -150,7 +188,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
150 | return ret; | 188 | return ret; |
151 | } | 189 | } |
152 | 190 | ||
153 | if (beacon_loss) { | 191 | if (wl->vif && beacon_loss) { |
154 | /* Obviously, it's dangerous to release the mutex while | 192 | /* Obviously, it's dangerous to release the mutex while |
155 | we are holding many of the variables in the wl struct. | 193 | we are holding many of the variables in the wl struct. |
156 | That's why it's done last in the function, and care must | 194 | That's why it's done last in the function, and care must |
@@ -177,14 +215,14 @@ int wl1271_event_unmask(struct wl1271 *wl) | |||
177 | 215 | ||
178 | void wl1271_event_mbox_config(struct wl1271 *wl) | 216 | void wl1271_event_mbox_config(struct wl1271 *wl) |
179 | { | 217 | { |
180 | wl->mbox_ptr[0] = wl1271_spi_read32(wl, REG_EVENT_MAILBOX_PTR); | 218 | wl->mbox_ptr[0] = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR); |
181 | wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); | 219 | wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); |
182 | 220 | ||
183 | wl1271_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x", | 221 | wl1271_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x", |
184 | wl->mbox_ptr[0], wl->mbox_ptr[1]); | 222 | wl->mbox_ptr[0], wl->mbox_ptr[1]); |
185 | } | 223 | } |
186 | 224 | ||
187 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num, bool do_ack) | 225 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) |
188 | { | 226 | { |
189 | struct event_mailbox mbox; | 227 | struct event_mailbox mbox; |
190 | int ret; | 228 | int ret; |
@@ -195,8 +233,8 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num, bool do_ack) | |||
195 | return -EINVAL; | 233 | return -EINVAL; |
196 | 234 | ||
197 | /* first we read the mbox descriptor */ | 235 | /* first we read the mbox descriptor */ |
198 | wl1271_spi_read(wl, wl->mbox_ptr[mbox_num], &mbox, | 236 | wl1271_read(wl, wl->mbox_ptr[mbox_num], &mbox, |
199 | sizeof(struct event_mailbox), false); | 237 | sizeof(struct event_mailbox), false); |
200 | 238 | ||
201 | /* process the descriptor */ | 239 | /* process the descriptor */ |
202 | ret = wl1271_event_process(wl, &mbox); | 240 | ret = wl1271_event_process(wl, &mbox); |
@@ -204,9 +242,7 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num, bool do_ack) | |||
204 | return ret; | 242 | return ret; |
205 | 243 | ||
206 | /* then we let the firmware know it can go on...*/ | 244 | /* then we let the firmware know it can go on...*/ |
207 | if (do_ack) | 245 | wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK); |
208 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, | ||
209 | INTR_TRIG_EVENT_ACK); | ||
210 | 246 | ||
211 | return 0; | 247 | return 0; |
212 | } | 248 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.h b/drivers/net/wireless/wl12xx/wl1271_event.h index 4e3f55ebb1a8..278f9206aa56 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.h +++ b/drivers/net/wireless/wl12xx/wl1271_event.h | |||
@@ -112,6 +112,6 @@ struct event_mailbox { | |||
112 | 112 | ||
113 | int wl1271_event_unmask(struct wl1271 *wl); | 113 | int wl1271_event_unmask(struct wl1271 *wl); |
114 | void wl1271_event_mbox_config(struct wl1271 *wl); | 114 | void wl1271_event_mbox_config(struct wl1271 *wl); |
115 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox, bool do_ack); | 115 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox); |
116 | 116 | ||
117 | #endif | 117 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index 11249b436cf1..86c30a86a456 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c | |||
@@ -49,7 +49,7 @@ static int wl1271_init_hwenc_config(struct wl1271 *wl) | |||
49 | return 0; | 49 | return 0; |
50 | } | 50 | } |
51 | 51 | ||
52 | static int wl1271_init_templates_config(struct wl1271 *wl) | 52 | int wl1271_init_templates_config(struct wl1271 *wl) |
53 | { | 53 | { |
54 | int ret; | 54 | int ret; |
55 | 55 | ||
@@ -113,7 +113,7 @@ static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter) | |||
113 | return 0; | 113 | return 0; |
114 | } | 114 | } |
115 | 115 | ||
116 | static int wl1271_init_phy_config(struct wl1271 *wl) | 116 | int wl1271_init_phy_config(struct wl1271 *wl) |
117 | { | 117 | { |
118 | int ret; | 118 | int ret; |
119 | 119 | ||
@@ -156,7 +156,7 @@ static int wl1271_init_beacon_filter(struct wl1271 *wl) | |||
156 | return 0; | 156 | return 0; |
157 | } | 157 | } |
158 | 158 | ||
159 | static int wl1271_init_pta(struct wl1271 *wl) | 159 | int wl1271_init_pta(struct wl1271 *wl) |
160 | { | 160 | { |
161 | int ret; | 161 | int ret; |
162 | 162 | ||
@@ -171,7 +171,7 @@ static int wl1271_init_pta(struct wl1271 *wl) | |||
171 | return 0; | 171 | return 0; |
172 | } | 172 | } |
173 | 173 | ||
174 | static int wl1271_init_energy_detection(struct wl1271 *wl) | 174 | int wl1271_init_energy_detection(struct wl1271 *wl) |
175 | { | 175 | { |
176 | int ret; | 176 | int ret; |
177 | 177 | ||
@@ -195,7 +195,9 @@ static int wl1271_init_beacon_broadcast(struct wl1271 *wl) | |||
195 | 195 | ||
196 | int wl1271_hw_init(struct wl1271 *wl) | 196 | int wl1271_hw_init(struct wl1271 *wl) |
197 | { | 197 | { |
198 | int ret; | 198 | struct conf_tx_ac_category *conf_ac; |
199 | struct conf_tx_tid *conf_tid; | ||
200 | int ret, i; | ||
199 | 201 | ||
200 | ret = wl1271_cmd_general_parms(wl); | 202 | ret = wl1271_cmd_general_parms(wl); |
201 | if (ret < 0) | 203 | if (ret < 0) |
@@ -229,6 +231,10 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
229 | if (ret < 0) | 231 | if (ret < 0) |
230 | goto out_free_memmap; | 232 | goto out_free_memmap; |
231 | 233 | ||
234 | ret = wl1271_acx_dco_itrim_params(wl); | ||
235 | if (ret < 0) | ||
236 | goto out_free_memmap; | ||
237 | |||
232 | /* Initialize connection monitoring thresholds */ | 238 | /* Initialize connection monitoring thresholds */ |
233 | ret = wl1271_acx_conn_monit_params(wl); | 239 | ret = wl1271_acx_conn_monit_params(wl); |
234 | if (ret < 0) | 240 | if (ret < 0) |
@@ -270,22 +276,36 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
270 | goto out_free_memmap; | 276 | goto out_free_memmap; |
271 | 277 | ||
272 | /* Default TID configuration */ | 278 | /* Default TID configuration */ |
273 | ret = wl1271_acx_tid_cfg(wl); | 279 | for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { |
274 | if (ret < 0) | 280 | conf_tid = &wl->conf.tx.tid_conf[i]; |
275 | goto out_free_memmap; | 281 | ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id, |
282 | conf_tid->channel_type, | ||
283 | conf_tid->tsid, | ||
284 | conf_tid->ps_scheme, | ||
285 | conf_tid->ack_policy, | ||
286 | conf_tid->apsd_conf[0], | ||
287 | conf_tid->apsd_conf[1]); | ||
288 | if (ret < 0) | ||
289 | goto out_free_memmap; | ||
290 | } | ||
276 | 291 | ||
277 | /* Default AC configuration */ | 292 | /* Default AC configuration */ |
278 | ret = wl1271_acx_ac_cfg(wl); | 293 | for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { |
279 | if (ret < 0) | 294 | conf_ac = &wl->conf.tx.ac_conf[i]; |
280 | goto out_free_memmap; | 295 | ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, |
296 | conf_ac->cw_max, conf_ac->aifsn, | ||
297 | conf_ac->tx_op_limit); | ||
298 | if (ret < 0) | ||
299 | goto out_free_memmap; | ||
300 | } | ||
281 | 301 | ||
282 | /* Configure TX rate classes */ | 302 | /* Configure TX rate classes */ |
283 | ret = wl1271_acx_rate_policies(wl, CONF_TX_RATE_MASK_ALL); | 303 | ret = wl1271_acx_rate_policies(wl); |
284 | if (ret < 0) | 304 | if (ret < 0) |
285 | goto out_free_memmap; | 305 | goto out_free_memmap; |
286 | 306 | ||
287 | /* Enable data path */ | 307 | /* Enable data path */ |
288 | ret = wl1271_cmd_data_path(wl, wl->channel, 1); | 308 | ret = wl1271_cmd_data_path(wl, 1); |
289 | if (ret < 0) | 309 | if (ret < 0) |
290 | goto out_free_memmap; | 310 | goto out_free_memmap; |
291 | 311 | ||
@@ -299,8 +319,8 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
299 | if (ret < 0) | 319 | if (ret < 0) |
300 | goto out_free_memmap; | 320 | goto out_free_memmap; |
301 | 321 | ||
302 | /* Configure smart reflex */ | 322 | /* configure PM */ |
303 | ret = wl1271_acx_smart_reflex(wl); | 323 | ret = wl1271_acx_pm_config(wl); |
304 | if (ret < 0) | 324 | if (ret < 0) |
305 | goto out_free_memmap; | 325 | goto out_free_memmap; |
306 | 326 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.h b/drivers/net/wireless/wl12xx/wl1271_init.h index 930677fbe852..bc26f8c53b91 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.h +++ b/drivers/net/wireless/wl12xx/wl1271_init.h | |||
@@ -27,6 +27,10 @@ | |||
27 | #include "wl1271.h" | 27 | #include "wl1271.h" |
28 | 28 | ||
29 | int wl1271_hw_init_power_auth(struct wl1271 *wl); | 29 | int wl1271_hw_init_power_auth(struct wl1271 *wl); |
30 | int wl1271_init_templates_config(struct wl1271 *wl); | ||
31 | int wl1271_init_phy_config(struct wl1271 *wl); | ||
32 | int wl1271_init_pta(struct wl1271 *wl); | ||
33 | int wl1271_init_energy_detection(struct wl1271 *wl); | ||
30 | int wl1271_hw_init(struct wl1271 *wl); | 34 | int wl1271_hw_init(struct wl1271 *wl); |
31 | 35 | ||
32 | #endif | 36 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.c b/drivers/net/wireless/wl12xx/wl1271_io.c new file mode 100644 index 000000000000..5cd94d5666c2 --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_io.c | |||
@@ -0,0 +1,213 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 2008-2010 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/crc7.h> | ||
27 | #include <linux/spi/spi.h> | ||
28 | |||
29 | #include "wl1271.h" | ||
30 | #include "wl12xx_80211.h" | ||
31 | #include "wl1271_spi.h" | ||
32 | #include "wl1271_io.h" | ||
33 | |||
34 | static int wl1271_translate_addr(struct wl1271 *wl, int addr) | ||
35 | { | ||
36 | /* | ||
37 | * To translate, first check to which window of addresses the | ||
38 | * particular address belongs. Then subtract the starting address | ||
39 | * of that window from the address. Then, add offset of the | ||
40 | * translated region. | ||
41 | * | ||
42 | * The translated regions occur next to each other in physical device | ||
43 | * memory, so just add the sizes of the preceeding address regions to | ||
44 | * get the offset to the new region. | ||
45 | * | ||
46 | * Currently, only the two first regions are addressed, and the | ||
47 | * assumption is that all addresses will fall into either of those | ||
48 | * two. | ||
49 | */ | ||
50 | if ((addr >= wl->part.reg.start) && | ||
51 | (addr < wl->part.reg.start + wl->part.reg.size)) | ||
52 | return addr - wl->part.reg.start + wl->part.mem.size; | ||
53 | else | ||
54 | return addr - wl->part.mem.start; | ||
55 | } | ||
56 | |||
57 | /* Set the SPI partitions to access the chip addresses | ||
58 | * | ||
59 | * To simplify driver code, a fixed (virtual) memory map is defined for | ||
60 | * register and memory addresses. Because in the chipset, in different stages | ||
61 | * of operation, those addresses will move around, an address translation | ||
62 | * mechanism is required. | ||
63 | * | ||
64 | * There are four partitions (three memory and one register partition), | ||
65 | * which are mapped to two different areas of the hardware memory. | ||
66 | * | ||
67 | * Virtual address | ||
68 | * space | ||
69 | * | ||
70 | * | | | ||
71 | * ...+----+--> mem.start | ||
72 | * Physical address ... | | | ||
73 | * space ... | | [PART_0] | ||
74 | * ... | | | ||
75 | * 00000000 <--+----+... ...+----+--> mem.start + mem.size | ||
76 | * | | ... | | | ||
77 | * |MEM | ... | | | ||
78 | * | | ... | | | ||
79 | * mem.size <--+----+... | | {unused area) | ||
80 | * | | ... | | | ||
81 | * |REG | ... | | | ||
82 | * mem.size | | ... | | | ||
83 | * + <--+----+... ...+----+--> reg.start | ||
84 | * reg.size | | ... | | | ||
85 | * |MEM2| ... | | [PART_1] | ||
86 | * | | ... | | | ||
87 | * ...+----+--> reg.start + reg.size | ||
88 | * | | | ||
89 | * | ||
90 | */ | ||
91 | int wl1271_set_partition(struct wl1271 *wl, | ||
92 | struct wl1271_partition_set *p) | ||
93 | { | ||
94 | /* copy partition info */ | ||
95 | memcpy(&wl->part, p, sizeof(*p)); | ||
96 | |||
97 | wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", | ||
98 | p->mem.start, p->mem.size); | ||
99 | wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", | ||
100 | p->reg.start, p->reg.size); | ||
101 | wl1271_debug(DEBUG_SPI, "mem2_start %08X mem2_size %08X", | ||
102 | p->mem2.start, p->mem2.size); | ||
103 | wl1271_debug(DEBUG_SPI, "mem3_start %08X mem3_size %08X", | ||
104 | p->mem3.start, p->mem3.size); | ||
105 | |||
106 | /* write partition info to the chipset */ | ||
107 | wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start); | ||
108 | wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size); | ||
109 | wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start); | ||
110 | wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size); | ||
111 | wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start); | ||
112 | wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size); | ||
113 | wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | void wl1271_io_reset(struct wl1271 *wl) | ||
119 | { | ||
120 | wl1271_spi_reset(wl); | ||
121 | } | ||
122 | |||
123 | void wl1271_io_init(struct wl1271 *wl) | ||
124 | { | ||
125 | wl1271_spi_init(wl); | ||
126 | } | ||
127 | |||
128 | void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, | ||
129 | size_t len, bool fixed) | ||
130 | { | ||
131 | wl1271_spi_raw_write(wl, addr, buf, len, fixed); | ||
132 | } | ||
133 | |||
134 | void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, | ||
135 | size_t len, bool fixed) | ||
136 | { | ||
137 | wl1271_spi_raw_read(wl, addr, buf, len, fixed); | ||
138 | } | ||
139 | |||
140 | void wl1271_read(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
141 | bool fixed) | ||
142 | { | ||
143 | int physical; | ||
144 | |||
145 | physical = wl1271_translate_addr(wl, addr); | ||
146 | |||
147 | wl1271_spi_raw_read(wl, physical, buf, len, fixed); | ||
148 | } | ||
149 | |||
150 | void wl1271_write(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
151 | bool fixed) | ||
152 | { | ||
153 | int physical; | ||
154 | |||
155 | physical = wl1271_translate_addr(wl, addr); | ||
156 | |||
157 | wl1271_spi_raw_write(wl, physical, buf, len, fixed); | ||
158 | } | ||
159 | |||
160 | u32 wl1271_read32(struct wl1271 *wl, int addr) | ||
161 | { | ||
162 | return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr)); | ||
163 | } | ||
164 | |||
165 | void wl1271_write32(struct wl1271 *wl, int addr, u32 val) | ||
166 | { | ||
167 | wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val); | ||
168 | } | ||
169 | |||
170 | void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val) | ||
171 | { | ||
172 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ | ||
173 | addr = (addr >> 1) + 0x30000; | ||
174 | wl1271_write32(wl, OCP_POR_CTR, addr); | ||
175 | |||
176 | /* write value to OCP_POR_WDATA */ | ||
177 | wl1271_write32(wl, OCP_DATA_WRITE, val); | ||
178 | |||
179 | /* write 1 to OCP_CMD */ | ||
180 | wl1271_write32(wl, OCP_CMD, OCP_CMD_WRITE); | ||
181 | } | ||
182 | |||
183 | u16 wl1271_top_reg_read(struct wl1271 *wl, int addr) | ||
184 | { | ||
185 | u32 val; | ||
186 | int timeout = OCP_CMD_LOOP; | ||
187 | |||
188 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ | ||
189 | addr = (addr >> 1) + 0x30000; | ||
190 | wl1271_write32(wl, OCP_POR_CTR, addr); | ||
191 | |||
192 | /* write 2 to OCP_CMD */ | ||
193 | wl1271_write32(wl, OCP_CMD, OCP_CMD_READ); | ||
194 | |||
195 | /* poll for data ready */ | ||
196 | do { | ||
197 | val = wl1271_read32(wl, OCP_DATA_READ); | ||
198 | } while (!(val & OCP_READY_MASK) && --timeout); | ||
199 | |||
200 | if (!timeout) { | ||
201 | wl1271_warning("Top register access timed out."); | ||
202 | return 0xffff; | ||
203 | } | ||
204 | |||
205 | /* check data status and return if OK */ | ||
206 | if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK) | ||
207 | return val & 0xffff; | ||
208 | else { | ||
209 | wl1271_warning("Top register access returned error."); | ||
210 | return 0xffff; | ||
211 | } | ||
212 | } | ||
213 | |||
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h new file mode 100644 index 000000000000..fa9a0b35788f --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_io.h | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. | ||
5 | * Copyright (C) 2008-2010 Nokia Corporation | ||
6 | * | ||
7 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef __WL1271_IO_H__ | ||
26 | #define __WL1271_IO_H__ | ||
27 | |||
28 | struct wl1271; | ||
29 | |||
30 | void wl1271_io_reset(struct wl1271 *wl); | ||
31 | void wl1271_io_init(struct wl1271 *wl); | ||
32 | |||
33 | /* Raw target IO, address is not translated */ | ||
34 | void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, | ||
35 | size_t len, bool fixed); | ||
36 | void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, | ||
37 | size_t len, bool fixed); | ||
38 | |||
39 | /* Translated target IO */ | ||
40 | void wl1271_read(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
41 | bool fixed); | ||
42 | void wl1271_write(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
43 | bool fixed); | ||
44 | u32 wl1271_read32(struct wl1271 *wl, int addr); | ||
45 | void wl1271_write32(struct wl1271 *wl, int addr, u32 val); | ||
46 | |||
47 | /* Top Register IO */ | ||
48 | void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val); | ||
49 | u16 wl1271_top_reg_read(struct wl1271 *wl, int addr); | ||
50 | |||
51 | int wl1271_set_partition(struct wl1271 *wl, | ||
52 | struct wl1271_partition_set *p); | ||
53 | |||
54 | static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) | ||
55 | { | ||
56 | wl1271_raw_read(wl, addr, &wl->buffer_32, | ||
57 | sizeof(wl->buffer_32), false); | ||
58 | |||
59 | return wl->buffer_32; | ||
60 | } | ||
61 | |||
62 | static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val) | ||
63 | { | ||
64 | wl->buffer_32 = val; | ||
65 | wl1271_raw_write(wl, addr, &wl->buffer_32, | ||
66 | sizeof(wl->buffer_32), false); | ||
67 | } | ||
68 | #endif | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index b62c00ff42fe..2a864b24291d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * This file is part of wl1271 | 2 | * This file is part of wl1271 |
3 | * | 3 | * |
4 | * Copyright (C) 2008-2009 Nokia Corporation | 4 | * Copyright (C) 2008-2010 Nokia Corporation |
5 | * | 5 | * |
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | 6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> |
7 | * | 7 | * |
@@ -38,6 +38,7 @@ | |||
38 | #include "wl12xx_80211.h" | 38 | #include "wl12xx_80211.h" |
39 | #include "wl1271_reg.h" | 39 | #include "wl1271_reg.h" |
40 | #include "wl1271_spi.h" | 40 | #include "wl1271_spi.h" |
41 | #include "wl1271_io.h" | ||
41 | #include "wl1271_event.h" | 42 | #include "wl1271_event.h" |
42 | #include "wl1271_tx.h" | 43 | #include "wl1271_tx.h" |
43 | #include "wl1271_rx.h" | 44 | #include "wl1271_rx.h" |
@@ -46,6 +47,9 @@ | |||
46 | #include "wl1271_debugfs.h" | 47 | #include "wl1271_debugfs.h" |
47 | #include "wl1271_cmd.h" | 48 | #include "wl1271_cmd.h" |
48 | #include "wl1271_boot.h" | 49 | #include "wl1271_boot.h" |
50 | #include "wl1271_testmode.h" | ||
51 | |||
52 | #define WL1271_BOOT_RETRIES 3 | ||
49 | 53 | ||
50 | static struct conf_drv_settings default_conf = { | 54 | static struct conf_drv_settings default_conf = { |
51 | .sg = { | 55 | .sg = { |
@@ -67,16 +71,17 @@ static struct conf_drv_settings default_conf = { | |||
67 | .ps_poll_timeout = 15, | 71 | .ps_poll_timeout = 15, |
68 | .upsd_timeout = 15, | 72 | .upsd_timeout = 15, |
69 | .rts_threshold = 2347, | 73 | .rts_threshold = 2347, |
70 | .rx_cca_threshold = 0xFFEF, | 74 | .rx_cca_threshold = 0, |
71 | .irq_blk_threshold = 0, | 75 | .irq_blk_threshold = 0xFFFF, |
72 | .irq_pkt_threshold = USHORT_MAX, | 76 | .irq_pkt_threshold = 0, |
73 | .irq_timeout = 5, | 77 | .irq_timeout = 600, |
74 | .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY, | 78 | .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY, |
75 | }, | 79 | }, |
76 | .tx = { | 80 | .tx = { |
77 | .tx_energy_detection = 0, | 81 | .tx_energy_detection = 0, |
78 | .rc_conf = { | 82 | .rc_conf = { |
79 | .enabled_rates = CONF_TX_RATE_MASK_UNSPECIFIED, | 83 | .enabled_rates = CONF_HW_BIT_RATE_1MBPS | |
84 | CONF_HW_BIT_RATE_2MBPS, | ||
80 | .short_retry_limit = 10, | 85 | .short_retry_limit = 10, |
81 | .long_retry_limit = 10, | 86 | .long_retry_limit = 10, |
82 | .aflags = 0 | 87 | .aflags = 0 |
@@ -172,8 +177,8 @@ static struct conf_drv_settings default_conf = { | |||
172 | } | 177 | } |
173 | }, | 178 | }, |
174 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, | 179 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, |
175 | .tx_compl_timeout = 5, | 180 | .tx_compl_timeout = 700, |
176 | .tx_compl_threshold = 5 | 181 | .tx_compl_threshold = 4 |
177 | }, | 182 | }, |
178 | .conn = { | 183 | .conn = { |
179 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | 184 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, |
@@ -186,12 +191,12 @@ static struct conf_drv_settings default_conf = { | |||
186 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, | 191 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, |
187 | } | 192 | } |
188 | }, | 193 | }, |
189 | .synch_fail_thold = 5, | 194 | .synch_fail_thold = 10, |
190 | .bss_lose_timeout = 100, | 195 | .bss_lose_timeout = 100, |
191 | .beacon_rx_timeout = 10000, | 196 | .beacon_rx_timeout = 10000, |
192 | .broadcast_timeout = 20000, | 197 | .broadcast_timeout = 20000, |
193 | .rx_broadcast_in_ps = 1, | 198 | .rx_broadcast_in_ps = 1, |
194 | .ps_poll_threshold = 4, | 199 | .ps_poll_threshold = 20, |
195 | .sig_trigger_count = 2, | 200 | .sig_trigger_count = 2, |
196 | .sig_trigger = { | 201 | .sig_trigger = { |
197 | [0] = { | 202 | [0] = { |
@@ -226,97 +231,17 @@ static struct conf_drv_settings default_conf = { | |||
226 | .psm_entry_retries = 3 | 231 | .psm_entry_retries = 3 |
227 | }, | 232 | }, |
228 | .init = { | 233 | .init = { |
229 | .sr_err_tbl = { | ||
230 | [0] = { | ||
231 | .len = 7, | ||
232 | .upper_limit = 0x03, | ||
233 | .values = { | ||
234 | 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8, | ||
235 | 0x00 } | ||
236 | }, | ||
237 | [1] = { | ||
238 | .len = 7, | ||
239 | .upper_limit = 0x03, | ||
240 | .values = { | ||
241 | 0x18, 0x10, 0x05, 0xf6, 0xf0, 0xe8, | ||
242 | 0x00 } | ||
243 | }, | ||
244 | [2] = { | ||
245 | .len = 7, | ||
246 | .upper_limit = 0x03, | ||
247 | .values = { | ||
248 | 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8, | ||
249 | 0x00 } | ||
250 | } | ||
251 | }, | ||
252 | .sr_enable = 1, | ||
253 | .genparam = { | ||
254 | .ref_clk = CONF_REF_CLK_38_4_E, | ||
255 | .settling_time = 5, | ||
256 | .clk_valid_on_wakeup = 0, | ||
257 | .dc2dcmode = 0, | ||
258 | .single_dual_band = CONF_SINGLE_BAND, | ||
259 | .tx_bip_fem_autodetect = 0, | ||
260 | .tx_bip_fem_manufacturer = 1, | ||
261 | .settings = 1, | ||
262 | }, | ||
263 | .radioparam = { | 234 | .radioparam = { |
264 | .rx_trace_loss = 10, | 235 | .fem = 1, |
265 | .tx_trace_loss = 10, | ||
266 | .rx_rssi_and_proc_compens = { | ||
267 | 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8, | ||
268 | 0xfc, 0x00, 0x08, 0x10, 0xf0, 0xf8, | ||
269 | 0x00, 0x0a, 0x14 }, | ||
270 | .rx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, | ||
271 | .tx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, | ||
272 | .rx_rssi_and_proc_compens_5 = { | ||
273 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
274 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
275 | 0x00, 0x00, 0x00 }, | ||
276 | .tx_ref_pd_voltage = 0x24e, | ||
277 | .tx_ref_power = 0x78, | ||
278 | .tx_offset_db = 0x0, | ||
279 | .tx_rate_limits_normal = { | ||
280 | 0x1e, 0x1f, 0x22, 0x24, 0x28, 0x29 }, | ||
281 | .tx_rate_limits_degraded = { | ||
282 | 0x1b, 0x1c, 0x1e, 0x20, 0x24, 0x25 }, | ||
283 | .tx_channel_limits_11b = { | ||
284 | 0x22, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
285 | 0x50, 0x50, 0x50, 0x50, 0x22, 0x50, | ||
286 | 0x22, 0x50 }, | ||
287 | .tx_channel_limits_ofdm = { | ||
288 | 0x20, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
289 | 0x50, 0x50, 0x50, 0x50, 0x20, 0x50, | ||
290 | 0x20, 0x50 }, | ||
291 | .tx_pdv_rate_offsets = { | ||
292 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, | ||
293 | .tx_ibias = { | ||
294 | 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x27 }, | ||
295 | .rx_fem_insertion_loss = 0x14, | ||
296 | .tx_ref_pd_voltage_5 = { | ||
297 | 0x0190, 0x01a4, 0x01c3, 0x01d8, | ||
298 | 0x020a, 0x021c }, | ||
299 | .tx_ref_power_5 = { | ||
300 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, | ||
301 | .tx_offset_db_5 = { | ||
302 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, | ||
303 | .tx_rate_limits_normal_5 = { | ||
304 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, | ||
305 | .tx_rate_limits_degraded_5 = { | ||
306 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, | ||
307 | .tx_channel_limits_ofdm_5 = { | ||
308 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
309 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
310 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
311 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
312 | 0x50, 0x50, 0x50 }, | ||
313 | .tx_pdv_rate_offsets_5 = { | ||
314 | 0x01, 0x02, 0x02, 0x02, 0x02, 0x00 }, | ||
315 | .tx_ibias_5 = { | ||
316 | 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, | ||
317 | .rx_fem_insertion_loss_5 = { | ||
318 | 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 } | ||
319 | } | 236 | } |
237 | }, | ||
238 | .itrim = { | ||
239 | .enable = false, | ||
240 | .timeout = 50000, | ||
241 | }, | ||
242 | .pm_config = { | ||
243 | .host_clk_settling_time = 5000, | ||
244 | .host_fast_wakeup_support = false | ||
320 | } | 245 | } |
321 | }; | 246 | }; |
322 | 247 | ||
@@ -337,15 +262,14 @@ static void wl1271_conf_init(struct wl1271 *wl) | |||
337 | 262 | ||
338 | /* apply driver default configuration */ | 263 | /* apply driver default configuration */ |
339 | memcpy(&wl->conf, &default_conf, sizeof(default_conf)); | 264 | memcpy(&wl->conf, &default_conf, sizeof(default_conf)); |
340 | |||
341 | if (wl1271_11a_enabled()) | ||
342 | wl->conf.init.genparam.single_dual_band = CONF_DUAL_BAND; | ||
343 | } | 265 | } |
344 | 266 | ||
345 | 267 | ||
346 | static int wl1271_plt_init(struct wl1271 *wl) | 268 | static int wl1271_plt_init(struct wl1271 *wl) |
347 | { | 269 | { |
348 | int ret; | 270 | struct conf_tx_ac_category *conf_ac; |
271 | struct conf_tx_tid *conf_tid; | ||
272 | int ret, i; | ||
349 | 273 | ||
350 | ret = wl1271_cmd_general_parms(wl); | 274 | ret = wl1271_cmd_general_parms(wl); |
351 | if (ret < 0) | 275 | if (ret < 0) |
@@ -355,15 +279,89 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
355 | if (ret < 0) | 279 | if (ret < 0) |
356 | return ret; | 280 | return ret; |
357 | 281 | ||
358 | ret = wl1271_acx_init_mem_config(wl); | 282 | ret = wl1271_init_templates_config(wl); |
359 | if (ret < 0) | 283 | if (ret < 0) |
360 | return ret; | 284 | return ret; |
361 | 285 | ||
362 | ret = wl1271_cmd_data_path(wl, wl->channel, 1); | 286 | ret = wl1271_acx_init_mem_config(wl); |
363 | if (ret < 0) | 287 | if (ret < 0) |
364 | return ret; | 288 | return ret; |
365 | 289 | ||
290 | /* PHY layer config */ | ||
291 | ret = wl1271_init_phy_config(wl); | ||
292 | if (ret < 0) | ||
293 | goto out_free_memmap; | ||
294 | |||
295 | ret = wl1271_acx_dco_itrim_params(wl); | ||
296 | if (ret < 0) | ||
297 | goto out_free_memmap; | ||
298 | |||
299 | /* Initialize connection monitoring thresholds */ | ||
300 | ret = wl1271_acx_conn_monit_params(wl); | ||
301 | if (ret < 0) | ||
302 | goto out_free_memmap; | ||
303 | |||
304 | /* Bluetooth WLAN coexistence */ | ||
305 | ret = wl1271_init_pta(wl); | ||
306 | if (ret < 0) | ||
307 | goto out_free_memmap; | ||
308 | |||
309 | /* Energy detection */ | ||
310 | ret = wl1271_init_energy_detection(wl); | ||
311 | if (ret < 0) | ||
312 | goto out_free_memmap; | ||
313 | |||
314 | /* Default fragmentation threshold */ | ||
315 | ret = wl1271_acx_frag_threshold(wl); | ||
316 | if (ret < 0) | ||
317 | goto out_free_memmap; | ||
318 | |||
319 | /* Default TID configuration */ | ||
320 | for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { | ||
321 | conf_tid = &wl->conf.tx.tid_conf[i]; | ||
322 | ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id, | ||
323 | conf_tid->channel_type, | ||
324 | conf_tid->tsid, | ||
325 | conf_tid->ps_scheme, | ||
326 | conf_tid->ack_policy, | ||
327 | conf_tid->apsd_conf[0], | ||
328 | conf_tid->apsd_conf[1]); | ||
329 | if (ret < 0) | ||
330 | goto out_free_memmap; | ||
331 | } | ||
332 | |||
333 | /* Default AC configuration */ | ||
334 | for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { | ||
335 | conf_ac = &wl->conf.tx.ac_conf[i]; | ||
336 | ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, | ||
337 | conf_ac->cw_max, conf_ac->aifsn, | ||
338 | conf_ac->tx_op_limit); | ||
339 | if (ret < 0) | ||
340 | goto out_free_memmap; | ||
341 | } | ||
342 | |||
343 | /* Enable data path */ | ||
344 | ret = wl1271_cmd_data_path(wl, 1); | ||
345 | if (ret < 0) | ||
346 | goto out_free_memmap; | ||
347 | |||
348 | /* Configure for CAM power saving (ie. always active) */ | ||
349 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | ||
350 | if (ret < 0) | ||
351 | goto out_free_memmap; | ||
352 | |||
353 | /* configure PM */ | ||
354 | ret = wl1271_acx_pm_config(wl); | ||
355 | if (ret < 0) | ||
356 | goto out_free_memmap; | ||
357 | |||
366 | return 0; | 358 | return 0; |
359 | |||
360 | out_free_memmap: | ||
361 | kfree(wl->target_mem_map); | ||
362 | wl->target_mem_map = NULL; | ||
363 | |||
364 | return ret; | ||
367 | } | 365 | } |
368 | 366 | ||
369 | static void wl1271_disable_interrupts(struct wl1271 *wl) | 367 | static void wl1271_disable_interrupts(struct wl1271 *wl) |
@@ -374,11 +372,13 @@ static void wl1271_disable_interrupts(struct wl1271 *wl) | |||
374 | static void wl1271_power_off(struct wl1271 *wl) | 372 | static void wl1271_power_off(struct wl1271 *wl) |
375 | { | 373 | { |
376 | wl->set_power(false); | 374 | wl->set_power(false); |
375 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
377 | } | 376 | } |
378 | 377 | ||
379 | static void wl1271_power_on(struct wl1271 *wl) | 378 | static void wl1271_power_on(struct wl1271 *wl) |
380 | { | 379 | { |
381 | wl->set_power(true); | 380 | wl->set_power(true); |
381 | set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
382 | } | 382 | } |
383 | 383 | ||
384 | static void wl1271_fw_status(struct wl1271 *wl, | 384 | static void wl1271_fw_status(struct wl1271 *wl, |
@@ -387,8 +387,7 @@ static void wl1271_fw_status(struct wl1271 *wl, | |||
387 | u32 total = 0; | 387 | u32 total = 0; |
388 | int i; | 388 | int i; |
389 | 389 | ||
390 | wl1271_spi_read(wl, FW_STATUS_ADDR, status, | 390 | wl1271_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); |
391 | sizeof(*status), false); | ||
392 | 391 | ||
393 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " | 392 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " |
394 | "drv_rx_counter = %d, tx_results_counter = %d)", | 393 | "drv_rx_counter = %d, tx_results_counter = %d)", |
@@ -435,7 +434,7 @@ static void wl1271_irq_work(struct work_struct *work) | |||
435 | if (ret < 0) | 434 | if (ret < 0) |
436 | goto out; | 435 | goto out; |
437 | 436 | ||
438 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | 437 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); |
439 | 438 | ||
440 | wl1271_fw_status(wl, wl->fw_status); | 439 | wl1271_fw_status(wl, wl->fw_status); |
441 | intr = le32_to_cpu(wl->fw_status->intr); | 440 | intr = le32_to_cpu(wl->fw_status->intr); |
@@ -447,14 +446,13 @@ static void wl1271_irq_work(struct work_struct *work) | |||
447 | intr &= WL1271_INTR_MASK; | 446 | intr &= WL1271_INTR_MASK; |
448 | 447 | ||
449 | if (intr & WL1271_ACX_INTR_EVENT_A) { | 448 | if (intr & WL1271_ACX_INTR_EVENT_A) { |
450 | bool do_ack = (intr & WL1271_ACX_INTR_EVENT_B) ? false : true; | ||
451 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); | 449 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); |
452 | wl1271_event_handle(wl, 0, do_ack); | 450 | wl1271_event_handle(wl, 0); |
453 | } | 451 | } |
454 | 452 | ||
455 | if (intr & WL1271_ACX_INTR_EVENT_B) { | 453 | if (intr & WL1271_ACX_INTR_EVENT_B) { |
456 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); | 454 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); |
457 | wl1271_event_handle(wl, 1, true); | 455 | wl1271_event_handle(wl, 1); |
458 | } | 456 | } |
459 | 457 | ||
460 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) | 458 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) |
@@ -478,8 +476,8 @@ static void wl1271_irq_work(struct work_struct *work) | |||
478 | } | 476 | } |
479 | 477 | ||
480 | out_sleep: | 478 | out_sleep: |
481 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, | 479 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, |
482 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); | 480 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); |
483 | wl1271_ps_elp_sleep(wl); | 481 | wl1271_ps_elp_sleep(wl); |
484 | 482 | ||
485 | out: | 483 | out: |
@@ -546,6 +544,40 @@ out: | |||
546 | return ret; | 544 | return ret; |
547 | } | 545 | } |
548 | 546 | ||
547 | static int wl1271_update_mac_addr(struct wl1271 *wl) | ||
548 | { | ||
549 | int ret = 0; | ||
550 | u8 *nvs_ptr = (u8 *)wl->nvs->nvs; | ||
551 | |||
552 | /* get mac address from the NVS */ | ||
553 | wl->mac_addr[0] = nvs_ptr[11]; | ||
554 | wl->mac_addr[1] = nvs_ptr[10]; | ||
555 | wl->mac_addr[2] = nvs_ptr[6]; | ||
556 | wl->mac_addr[3] = nvs_ptr[5]; | ||
557 | wl->mac_addr[4] = nvs_ptr[4]; | ||
558 | wl->mac_addr[5] = nvs_ptr[3]; | ||
559 | |||
560 | /* FIXME: if it is a zero-address, we should bail out. Now, instead, | ||
561 | we randomize an address */ | ||
562 | if (is_zero_ether_addr(wl->mac_addr)) { | ||
563 | static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; | ||
564 | memcpy(wl->mac_addr, nokia_oui, 3); | ||
565 | get_random_bytes(wl->mac_addr + 3, 3); | ||
566 | |||
567 | /* update this address to the NVS */ | ||
568 | nvs_ptr[11] = wl->mac_addr[0]; | ||
569 | nvs_ptr[10] = wl->mac_addr[1]; | ||
570 | nvs_ptr[6] = wl->mac_addr[2]; | ||
571 | nvs_ptr[5] = wl->mac_addr[3]; | ||
572 | nvs_ptr[4] = wl->mac_addr[4]; | ||
573 | nvs_ptr[3] = wl->mac_addr[5]; | ||
574 | } | ||
575 | |||
576 | SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); | ||
577 | |||
578 | return ret; | ||
579 | } | ||
580 | |||
549 | static int wl1271_fetch_nvs(struct wl1271 *wl) | 581 | static int wl1271_fetch_nvs(struct wl1271 *wl) |
550 | { | 582 | { |
551 | const struct firmware *fw; | 583 | const struct firmware *fw; |
@@ -558,15 +590,14 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) | |||
558 | return ret; | 590 | return ret; |
559 | } | 591 | } |
560 | 592 | ||
561 | if (fw->size % 4) { | 593 | if (fw->size != sizeof(struct wl1271_nvs_file)) { |
562 | wl1271_error("nvs size is not multiple of 32 bits: %zu", | 594 | wl1271_error("nvs size is not as expected: %zu != %zu", |
563 | fw->size); | 595 | fw->size, sizeof(struct wl1271_nvs_file)); |
564 | ret = -EILSEQ; | 596 | ret = -EILSEQ; |
565 | goto out; | 597 | goto out; |
566 | } | 598 | } |
567 | 599 | ||
568 | wl->nvs_len = fw->size; | 600 | wl->nvs = kmalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL); |
569 | wl->nvs = kmalloc(wl->nvs_len, GFP_KERNEL); | ||
570 | 601 | ||
571 | if (!wl->nvs) { | 602 | if (!wl->nvs) { |
572 | wl1271_error("could not allocate memory for the nvs file"); | 603 | wl1271_error("could not allocate memory for the nvs file"); |
@@ -574,9 +605,9 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) | |||
574 | goto out; | 605 | goto out; |
575 | } | 606 | } |
576 | 607 | ||
577 | memcpy(wl->nvs, fw->data, wl->nvs_len); | 608 | memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file)); |
578 | 609 | ||
579 | ret = 0; | 610 | ret = wl1271_update_mac_addr(wl); |
580 | 611 | ||
581 | out: | 612 | out: |
582 | release_firmware(fw); | 613 | release_firmware(fw); |
@@ -614,10 +645,11 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
614 | struct wl1271_partition_set partition; | 645 | struct wl1271_partition_set partition; |
615 | int ret = 0; | 646 | int ret = 0; |
616 | 647 | ||
648 | msleep(WL1271_PRE_POWER_ON_SLEEP); | ||
617 | wl1271_power_on(wl); | 649 | wl1271_power_on(wl); |
618 | msleep(WL1271_POWER_ON_SLEEP); | 650 | msleep(WL1271_POWER_ON_SLEEP); |
619 | wl1271_spi_reset(wl); | 651 | wl1271_io_reset(wl); |
620 | wl1271_spi_init(wl); | 652 | wl1271_io_init(wl); |
621 | 653 | ||
622 | /* We don't need a real memory partition here, because we only want | 654 | /* We don't need a real memory partition here, because we only want |
623 | * to use the registers at this point. */ | 655 | * to use the registers at this point. */ |
@@ -632,7 +664,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
632 | /* whal_FwCtrl_BootSm() */ | 664 | /* whal_FwCtrl_BootSm() */ |
633 | 665 | ||
634 | /* 0. read chip id from CHIP_ID */ | 666 | /* 0. read chip id from CHIP_ID */ |
635 | wl->chip.id = wl1271_spi_read32(wl, CHIP_ID_B); | 667 | wl->chip.id = wl1271_read32(wl, CHIP_ID_B); |
636 | 668 | ||
637 | /* 1. check if chip id is valid */ | 669 | /* 1. check if chip id is valid */ |
638 | 670 | ||
@@ -643,7 +675,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
643 | 675 | ||
644 | ret = wl1271_setup(wl); | 676 | ret = wl1271_setup(wl); |
645 | if (ret < 0) | 677 | if (ret < 0) |
646 | goto out_power_off; | 678 | goto out; |
647 | break; | 679 | break; |
648 | case CHIP_ID_1271_PG20: | 680 | case CHIP_ID_1271_PG20: |
649 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", | 681 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", |
@@ -651,38 +683,34 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
651 | 683 | ||
652 | ret = wl1271_setup(wl); | 684 | ret = wl1271_setup(wl); |
653 | if (ret < 0) | 685 | if (ret < 0) |
654 | goto out_power_off; | 686 | goto out; |
655 | break; | 687 | break; |
656 | default: | 688 | default: |
657 | wl1271_error("unsupported chip id: 0x%x", wl->chip.id); | 689 | wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); |
658 | ret = -ENODEV; | 690 | ret = -ENODEV; |
659 | goto out_power_off; | 691 | goto out; |
660 | } | 692 | } |
661 | 693 | ||
662 | if (wl->fw == NULL) { | 694 | if (wl->fw == NULL) { |
663 | ret = wl1271_fetch_firmware(wl); | 695 | ret = wl1271_fetch_firmware(wl); |
664 | if (ret < 0) | 696 | if (ret < 0) |
665 | goto out_power_off; | 697 | goto out; |
666 | } | 698 | } |
667 | 699 | ||
668 | /* No NVS from netlink, try to get it from the filesystem */ | 700 | /* No NVS from netlink, try to get it from the filesystem */ |
669 | if (wl->nvs == NULL) { | 701 | if (wl->nvs == NULL) { |
670 | ret = wl1271_fetch_nvs(wl); | 702 | ret = wl1271_fetch_nvs(wl); |
671 | if (ret < 0) | 703 | if (ret < 0) |
672 | goto out_power_off; | 704 | goto out; |
673 | } | 705 | } |
674 | 706 | ||
675 | goto out; | ||
676 | |||
677 | out_power_off: | ||
678 | wl1271_power_off(wl); | ||
679 | |||
680 | out: | 707 | out: |
681 | return ret; | 708 | return ret; |
682 | } | 709 | } |
683 | 710 | ||
684 | int wl1271_plt_start(struct wl1271 *wl) | 711 | int wl1271_plt_start(struct wl1271 *wl) |
685 | { | 712 | { |
713 | int retries = WL1271_BOOT_RETRIES; | ||
686 | int ret; | 714 | int ret; |
687 | 715 | ||
688 | mutex_lock(&wl->mutex); | 716 | mutex_lock(&wl->mutex); |
@@ -696,35 +724,43 @@ int wl1271_plt_start(struct wl1271 *wl) | |||
696 | goto out; | 724 | goto out; |
697 | } | 725 | } |
698 | 726 | ||
699 | wl->state = WL1271_STATE_PLT; | 727 | while (retries) { |
700 | 728 | retries--; | |
701 | ret = wl1271_chip_wakeup(wl); | 729 | ret = wl1271_chip_wakeup(wl); |
702 | if (ret < 0) | 730 | if (ret < 0) |
703 | goto out; | 731 | goto power_off; |
704 | |||
705 | ret = wl1271_boot(wl); | ||
706 | if (ret < 0) | ||
707 | goto out_power_off; | ||
708 | |||
709 | wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver); | ||
710 | |||
711 | ret = wl1271_plt_init(wl); | ||
712 | if (ret < 0) | ||
713 | goto out_irq_disable; | ||
714 | 732 | ||
715 | /* Make sure power saving is disabled */ | 733 | ret = wl1271_boot(wl); |
716 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | 734 | if (ret < 0) |
717 | if (ret < 0) | 735 | goto power_off; |
718 | goto out_irq_disable; | ||
719 | 736 | ||
720 | goto out; | 737 | ret = wl1271_plt_init(wl); |
738 | if (ret < 0) | ||
739 | goto irq_disable; | ||
721 | 740 | ||
722 | out_irq_disable: | 741 | wl->state = WL1271_STATE_PLT; |
723 | wl1271_disable_interrupts(wl); | 742 | wl1271_notice("firmware booted in PLT mode (%s)", |
743 | wl->chip.fw_ver); | ||
744 | goto out; | ||
724 | 745 | ||
725 | out_power_off: | 746 | irq_disable: |
726 | wl1271_power_off(wl); | 747 | wl1271_disable_interrupts(wl); |
748 | mutex_unlock(&wl->mutex); | ||
749 | /* Unlocking the mutex in the middle of handling is | ||
750 | inherently unsafe. In this case we deem it safe to do, | ||
751 | because we need to let any possibly pending IRQ out of | ||
752 | the system (and while we are WL1271_STATE_OFF the IRQ | ||
753 | work function will not do anything.) Also, any other | ||
754 | possible concurrent operations will fail due to the | ||
755 | current state, hence the wl1271 struct should be safe. */ | ||
756 | cancel_work_sync(&wl->irq_work); | ||
757 | mutex_lock(&wl->mutex); | ||
758 | power_off: | ||
759 | wl1271_power_off(wl); | ||
760 | } | ||
727 | 761 | ||
762 | wl1271_error("firmware boot in PLT mode failed despite %d retries", | ||
763 | WL1271_BOOT_RETRIES); | ||
728 | out: | 764 | out: |
729 | mutex_unlock(&wl->mutex); | 765 | mutex_unlock(&wl->mutex); |
730 | 766 | ||
@@ -762,7 +798,20 @@ out: | |||
762 | static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 798 | static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
763 | { | 799 | { |
764 | struct wl1271 *wl = hw->priv; | 800 | struct wl1271 *wl = hw->priv; |
801 | struct ieee80211_conf *conf = &hw->conf; | ||
802 | struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); | ||
803 | struct ieee80211_sta *sta = txinfo->control.sta; | ||
804 | unsigned long flags; | ||
805 | |||
806 | /* peek into the rates configured in the STA entry */ | ||
807 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
808 | if (sta && sta->supp_rates[conf->channel->band] != wl->sta_rate_set) { | ||
809 | wl->sta_rate_set = sta->supp_rates[conf->channel->band]; | ||
810 | set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); | ||
811 | } | ||
812 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
765 | 813 | ||
814 | /* queue the packet */ | ||
766 | skb_queue_tail(&wl->tx_queue, skb); | 815 | skb_queue_tail(&wl->tx_queue, skb); |
767 | 816 | ||
768 | /* | 817 | /* |
@@ -784,7 +833,7 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
784 | * protected. Maybe fix this by removing the stupid | 833 | * protected. Maybe fix this by removing the stupid |
785 | * variable altogether and checking the real queue state? | 834 | * variable altogether and checking the real queue state? |
786 | */ | 835 | */ |
787 | wl->tx_queue_stopped = true; | 836 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); |
788 | } | 837 | } |
789 | 838 | ||
790 | return NETDEV_TX_OK; | 839 | return NETDEV_TX_OK; |
@@ -880,6 +929,7 @@ static struct notifier_block wl1271_dev_notifier = { | |||
880 | static int wl1271_op_start(struct ieee80211_hw *hw) | 929 | static int wl1271_op_start(struct ieee80211_hw *hw) |
881 | { | 930 | { |
882 | struct wl1271 *wl = hw->priv; | 931 | struct wl1271 *wl = hw->priv; |
932 | int retries = WL1271_BOOT_RETRIES; | ||
883 | int ret = 0; | 933 | int ret = 0; |
884 | 934 | ||
885 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); | 935 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); |
@@ -893,30 +943,42 @@ static int wl1271_op_start(struct ieee80211_hw *hw) | |||
893 | goto out; | 943 | goto out; |
894 | } | 944 | } |
895 | 945 | ||
896 | ret = wl1271_chip_wakeup(wl); | 946 | while (retries) { |
897 | if (ret < 0) | 947 | retries--; |
898 | goto out; | 948 | ret = wl1271_chip_wakeup(wl); |
899 | 949 | if (ret < 0) | |
900 | ret = wl1271_boot(wl); | 950 | goto power_off; |
901 | if (ret < 0) | ||
902 | goto out_power_off; | ||
903 | |||
904 | ret = wl1271_hw_init(wl); | ||
905 | if (ret < 0) | ||
906 | goto out_irq_disable; | ||
907 | |||
908 | wl->state = WL1271_STATE_ON; | ||
909 | 951 | ||
910 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver); | 952 | ret = wl1271_boot(wl); |
953 | if (ret < 0) | ||
954 | goto power_off; | ||
911 | 955 | ||
912 | goto out; | 956 | ret = wl1271_hw_init(wl); |
957 | if (ret < 0) | ||
958 | goto irq_disable; | ||
913 | 959 | ||
914 | out_irq_disable: | 960 | wl->state = WL1271_STATE_ON; |
915 | wl1271_disable_interrupts(wl); | 961 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver); |
962 | goto out; | ||
916 | 963 | ||
917 | out_power_off: | 964 | irq_disable: |
918 | wl1271_power_off(wl); | 965 | wl1271_disable_interrupts(wl); |
966 | mutex_unlock(&wl->mutex); | ||
967 | /* Unlocking the mutex in the middle of handling is | ||
968 | inherently unsafe. In this case we deem it safe to do, | ||
969 | because we need to let any possibly pending IRQ out of | ||
970 | the system (and while we are WL1271_STATE_OFF the IRQ | ||
971 | work function will not do anything.) Also, any other | ||
972 | possible concurrent operations will fail due to the | ||
973 | current state, hence the wl1271 struct should be safe. */ | ||
974 | cancel_work_sync(&wl->irq_work); | ||
975 | mutex_lock(&wl->mutex); | ||
976 | power_off: | ||
977 | wl1271_power_off(wl); | ||
978 | } | ||
919 | 979 | ||
980 | wl1271_error("firmware boot failed despite %d retries", | ||
981 | WL1271_BOOT_RETRIES); | ||
920 | out: | 982 | out: |
921 | mutex_unlock(&wl->mutex); | 983 | mutex_unlock(&wl->mutex); |
922 | 984 | ||
@@ -944,11 +1006,10 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
944 | 1006 | ||
945 | WARN_ON(wl->state != WL1271_STATE_ON); | 1007 | WARN_ON(wl->state != WL1271_STATE_ON); |
946 | 1008 | ||
947 | if (wl->scanning) { | 1009 | if (test_and_clear_bit(WL1271_FLAG_SCANNING, &wl->flags)) { |
948 | mutex_unlock(&wl->mutex); | 1010 | mutex_unlock(&wl->mutex); |
949 | ieee80211_scan_completed(wl->hw, true); | 1011 | ieee80211_scan_completed(wl->hw, true); |
950 | mutex_lock(&wl->mutex); | 1012 | mutex_lock(&wl->mutex); |
951 | wl->scanning = false; | ||
952 | } | 1013 | } |
953 | 1014 | ||
954 | wl->state = WL1271_STATE_OFF; | 1015 | wl->state = WL1271_STATE_OFF; |
@@ -973,10 +1034,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
973 | wl->band = IEEE80211_BAND_2GHZ; | 1034 | wl->band = IEEE80211_BAND_2GHZ; |
974 | 1035 | ||
975 | wl->rx_counter = 0; | 1036 | wl->rx_counter = 0; |
976 | wl->elp = false; | ||
977 | wl->psm = 0; | ||
978 | wl->psm_entry_retry = 0; | 1037 | wl->psm_entry_retry = 0; |
979 | wl->tx_queue_stopped = false; | ||
980 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 1038 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
981 | wl->tx_blocks_available = 0; | 1039 | wl->tx_blocks_available = 0; |
982 | wl->tx_results_count = 0; | 1040 | wl->tx_results_count = 0; |
@@ -986,7 +1044,9 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
986 | wl->tx_security_seq_32 = 0; | 1044 | wl->tx_security_seq_32 = 0; |
987 | wl->time_offset = 0; | 1045 | wl->time_offset = 0; |
988 | wl->session_counter = 0; | 1046 | wl->session_counter = 0; |
989 | wl->joined = false; | 1047 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; |
1048 | wl->sta_rate_set = 0; | ||
1049 | wl->flags = 0; | ||
990 | 1050 | ||
991 | for (i = 0; i < NUM_TX_QUEUES; i++) | 1051 | for (i = 0; i < NUM_TX_QUEUES; i++) |
992 | wl->tx_blocks_freed[i] = 0; | 1052 | wl->tx_blocks_freed[i] = 0; |
@@ -996,13 +1056,13 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
996 | } | 1056 | } |
997 | 1057 | ||
998 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, | 1058 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, |
999 | struct ieee80211_if_init_conf *conf) | 1059 | struct ieee80211_vif *vif) |
1000 | { | 1060 | { |
1001 | struct wl1271 *wl = hw->priv; | 1061 | struct wl1271 *wl = hw->priv; |
1002 | int ret = 0; | 1062 | int ret = 0; |
1003 | 1063 | ||
1004 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", | 1064 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", |
1005 | conf->type, conf->mac_addr); | 1065 | vif->type, vif->addr); |
1006 | 1066 | ||
1007 | mutex_lock(&wl->mutex); | 1067 | mutex_lock(&wl->mutex); |
1008 | if (wl->vif) { | 1068 | if (wl->vif) { |
@@ -1010,9 +1070,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
1010 | goto out; | 1070 | goto out; |
1011 | } | 1071 | } |
1012 | 1072 | ||
1013 | wl->vif = conf->vif; | 1073 | wl->vif = vif; |
1014 | 1074 | ||
1015 | switch (conf->type) { | 1075 | switch (vif->type) { |
1016 | case NL80211_IFTYPE_STATION: | 1076 | case NL80211_IFTYPE_STATION: |
1017 | wl->bss_type = BSS_TYPE_STA_BSS; | 1077 | wl->bss_type = BSS_TYPE_STA_BSS; |
1018 | break; | 1078 | break; |
@@ -1032,7 +1092,7 @@ out: | |||
1032 | } | 1092 | } |
1033 | 1093 | ||
1034 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | 1094 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, |
1035 | struct ieee80211_if_init_conf *conf) | 1095 | struct ieee80211_vif *vif) |
1036 | { | 1096 | { |
1037 | struct wl1271 *wl = hw->priv; | 1097 | struct wl1271 *wl = hw->priv; |
1038 | 1098 | ||
@@ -1109,6 +1169,51 @@ out: | |||
1109 | } | 1169 | } |
1110 | #endif | 1170 | #endif |
1111 | 1171 | ||
1172 | static int wl1271_join_channel(struct wl1271 *wl, int channel) | ||
1173 | { | ||
1174 | int ret = 0; | ||
1175 | /* we need to use a dummy BSSID for now */ | ||
1176 | static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, | ||
1177 | 0xad, 0xbe, 0xef }; | ||
1178 | |||
1179 | /* the dummy join is not required for ad-hoc */ | ||
1180 | if (wl->bss_type == BSS_TYPE_IBSS) | ||
1181 | goto out; | ||
1182 | |||
1183 | /* disable mac filter, so we hear everything */ | ||
1184 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; | ||
1185 | |||
1186 | wl->channel = channel; | ||
1187 | memcpy(wl->bssid, dummy_bssid, ETH_ALEN); | ||
1188 | |||
1189 | ret = wl1271_cmd_join(wl); | ||
1190 | if (ret < 0) | ||
1191 | goto out; | ||
1192 | |||
1193 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | ||
1194 | |||
1195 | out: | ||
1196 | return ret; | ||
1197 | } | ||
1198 | |||
1199 | static int wl1271_unjoin_channel(struct wl1271 *wl) | ||
1200 | { | ||
1201 | int ret; | ||
1202 | |||
1203 | /* to stop listening to a channel, we disconnect */ | ||
1204 | ret = wl1271_cmd_disconnect(wl); | ||
1205 | if (ret < 0) | ||
1206 | goto out; | ||
1207 | |||
1208 | clear_bit(WL1271_FLAG_JOINED, &wl->flags); | ||
1209 | wl->channel = 0; | ||
1210 | memset(wl->bssid, 0, ETH_ALEN); | ||
1211 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | ||
1212 | |||
1213 | out: | ||
1214 | return ret; | ||
1215 | } | ||
1216 | |||
1112 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | 1217 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) |
1113 | { | 1218 | { |
1114 | struct wl1271 *wl = hw->priv; | 1219 | struct wl1271 *wl = hw->priv; |
@@ -1117,10 +1222,11 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1117 | 1222 | ||
1118 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); | 1223 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); |
1119 | 1224 | ||
1120 | wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d", | 1225 | wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s", |
1121 | channel, | 1226 | channel, |
1122 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", | 1227 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", |
1123 | conf->power_level); | 1228 | conf->power_level, |
1229 | conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use"); | ||
1124 | 1230 | ||
1125 | mutex_lock(&wl->mutex); | 1231 | mutex_lock(&wl->mutex); |
1126 | 1232 | ||
@@ -1130,35 +1236,55 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1130 | if (ret < 0) | 1236 | if (ret < 0) |
1131 | goto out; | 1237 | goto out; |
1132 | 1238 | ||
1133 | if (channel != wl->channel) { | 1239 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
1134 | /* | 1240 | if (conf->flags & IEEE80211_CONF_IDLE && |
1135 | * We assume that the stack will configure the right channel | 1241 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) |
1136 | * before associating, so we don't need to send a join | 1242 | wl1271_unjoin_channel(wl); |
1137 | * command here. We will join the right channel when the | 1243 | else if (!(conf->flags & IEEE80211_CONF_IDLE)) |
1138 | * BSSID changes | 1244 | wl1271_join_channel(wl, channel); |
1139 | */ | 1245 | |
1140 | wl->channel = channel; | 1246 | if (conf->flags & IEEE80211_CONF_IDLE) { |
1247 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | ||
1248 | wl->sta_rate_set = 0; | ||
1249 | wl1271_acx_rate_policies(wl); | ||
1250 | } | ||
1141 | } | 1251 | } |
1142 | 1252 | ||
1143 | if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) { | 1253 | /* if the channel changes while joined, join again */ |
1144 | wl1271_info("psm enabled"); | 1254 | if (channel != wl->channel && |
1255 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) { | ||
1256 | wl->channel = channel; | ||
1257 | /* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */ | ||
1258 | ret = wl1271_cmd_join(wl); | ||
1259 | if (ret < 0) | ||
1260 | wl1271_warning("cmd join to update channel failed %d", | ||
1261 | ret); | ||
1262 | } else | ||
1263 | wl->channel = channel; | ||
1145 | 1264 | ||
1146 | wl->psm_requested = true; | 1265 | if (conf->flags & IEEE80211_CONF_PS && |
1266 | !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | ||
1267 | set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); | ||
1147 | 1268 | ||
1148 | /* | 1269 | /* |
1149 | * We enter PSM only if we're already associated. | 1270 | * We enter PSM only if we're already associated. |
1150 | * If we're not, we'll enter it when joining an SSID, | 1271 | * If we're not, we'll enter it when joining an SSID, |
1151 | * through the bss_info_changed() hook. | 1272 | * through the bss_info_changed() hook. |
1152 | */ | 1273 | */ |
1153 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); | 1274 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { |
1275 | wl1271_info("psm enabled"); | ||
1276 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, | ||
1277 | true); | ||
1278 | } | ||
1154 | } else if (!(conf->flags & IEEE80211_CONF_PS) && | 1279 | } else if (!(conf->flags & IEEE80211_CONF_PS) && |
1155 | wl->psm_requested) { | 1280 | test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { |
1156 | wl1271_info("psm disabled"); | 1281 | wl1271_info("psm disabled"); |
1157 | 1282 | ||
1158 | wl->psm_requested = false; | 1283 | clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); |
1159 | 1284 | ||
1160 | if (wl->psm) | 1285 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) |
1161 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE); | 1286 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, |
1287 | true); | ||
1162 | } | 1288 | } |
1163 | 1289 | ||
1164 | if (conf->power_level != wl->power_level) { | 1290 | if (conf->power_level != wl->power_level) { |
@@ -1350,9 +1476,24 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1350 | wl1271_error("Could not add or replace key"); | 1476 | wl1271_error("Could not add or replace key"); |
1351 | goto out_sleep; | 1477 | goto out_sleep; |
1352 | } | 1478 | } |
1479 | |||
1480 | /* the default WEP key needs to be configured at least once */ | ||
1481 | if (key_type == KEY_WEP) { | ||
1482 | ret = wl1271_cmd_set_default_wep_key(wl, | ||
1483 | wl->default_key); | ||
1484 | if (ret < 0) | ||
1485 | goto out_sleep; | ||
1486 | } | ||
1353 | break; | 1487 | break; |
1354 | 1488 | ||
1355 | case DISABLE_KEY: | 1489 | case DISABLE_KEY: |
1490 | /* The wl1271 does not allow to remove unicast keys - they | ||
1491 | will be cleared automatically on next CMD_JOIN. Ignore the | ||
1492 | request silently, as we dont want the mac80211 to emit | ||
1493 | an error message. */ | ||
1494 | if (!is_broadcast_ether_addr(addr)) | ||
1495 | break; | ||
1496 | |||
1356 | ret = wl1271_cmd_set_key(wl, KEY_REMOVE, | 1497 | ret = wl1271_cmd_set_key(wl, KEY_REMOVE, |
1357 | key_conf->keyidx, key_type, | 1498 | key_conf->keyidx, key_type, |
1358 | key_conf->keylen, key_conf->key, | 1499 | key_conf->keylen, key_conf->key, |
@@ -1440,20 +1581,21 @@ out: | |||
1440 | return ret; | 1581 | return ret; |
1441 | } | 1582 | } |
1442 | 1583 | ||
1443 | static u32 wl1271_enabled_rates_get(struct wl1271 *wl, u64 basic_rate_set) | 1584 | static void wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *beacon) |
1444 | { | 1585 | { |
1445 | struct ieee80211_supported_band *band; | 1586 | u8 *ptr = beacon->data + |
1446 | u32 enabled_rates = 0; | 1587 | offsetof(struct ieee80211_mgmt, u.beacon.variable); |
1447 | int bit; | 1588 | |
1448 | 1589 | /* find the location of the ssid in the beacon */ | |
1449 | band = wl->hw->wiphy->bands[wl->band]; | 1590 | while (ptr < beacon->data + beacon->len) { |
1450 | for (bit = 0; bit < band->n_bitrates; bit++) { | 1591 | if (ptr[0] == WLAN_EID_SSID) { |
1451 | if (basic_rate_set & 0x1) | 1592 | wl->ssid_len = ptr[1]; |
1452 | enabled_rates |= band->bitrates[bit].hw_value; | 1593 | memcpy(wl->ssid, ptr+2, wl->ssid_len); |
1453 | basic_rate_set >>= 1; | 1594 | return; |
1595 | } | ||
1596 | ptr += ptr[1]; | ||
1454 | } | 1597 | } |
1455 | 1598 | wl1271_error("ad-hoc beacon template has no SSID!\n"); | |
1456 | return enabled_rates; | ||
1457 | } | 1599 | } |
1458 | 1600 | ||
1459 | static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | 1601 | static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, |
@@ -1463,6 +1605,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1463 | { | 1605 | { |
1464 | enum wl1271_cmd_ps_mode mode; | 1606 | enum wl1271_cmd_ps_mode mode; |
1465 | struct wl1271 *wl = hw->priv; | 1607 | struct wl1271 *wl = hw->priv; |
1608 | bool do_join = false; | ||
1466 | int ret; | 1609 | int ret; |
1467 | 1610 | ||
1468 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); | 1611 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); |
@@ -1473,9 +1616,67 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1473 | if (ret < 0) | 1616 | if (ret < 0) |
1474 | goto out; | 1617 | goto out; |
1475 | 1618 | ||
1619 | if (wl->bss_type == BSS_TYPE_IBSS) { | ||
1620 | /* FIXME: This implements rudimentary ad-hoc support - | ||
1621 | proper templates are on the wish list and notification | ||
1622 | on when they change. This patch will update the templates | ||
1623 | on every call to this function. */ | ||
1624 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | ||
1625 | |||
1626 | if (beacon) { | ||
1627 | struct ieee80211_hdr *hdr; | ||
1628 | |||
1629 | wl1271_ssid_set(wl, beacon); | ||
1630 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, | ||
1631 | beacon->data, | ||
1632 | beacon->len); | ||
1633 | |||
1634 | if (ret < 0) { | ||
1635 | dev_kfree_skb(beacon); | ||
1636 | goto out_sleep; | ||
1637 | } | ||
1638 | |||
1639 | hdr = (struct ieee80211_hdr *) beacon->data; | ||
1640 | hdr->frame_control = cpu_to_le16( | ||
1641 | IEEE80211_FTYPE_MGMT | | ||
1642 | IEEE80211_STYPE_PROBE_RESP); | ||
1643 | |||
1644 | ret = wl1271_cmd_template_set(wl, | ||
1645 | CMD_TEMPL_PROBE_RESPONSE, | ||
1646 | beacon->data, | ||
1647 | beacon->len); | ||
1648 | dev_kfree_skb(beacon); | ||
1649 | if (ret < 0) | ||
1650 | goto out_sleep; | ||
1651 | |||
1652 | /* Need to update the SSID (for filtering etc) */ | ||
1653 | do_join = true; | ||
1654 | } | ||
1655 | } | ||
1656 | |||
1657 | if ((changed & BSS_CHANGED_BSSID) && | ||
1658 | /* | ||
1659 | * Now we know the correct bssid, so we send a new join command | ||
1660 | * and enable the BSSID filter | ||
1661 | */ | ||
1662 | memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { | ||
1663 | wl->rx_config |= CFG_BSSID_FILTER_EN; | ||
1664 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); | ||
1665 | ret = wl1271_cmd_build_null_data(wl); | ||
1666 | if (ret < 0) { | ||
1667 | wl1271_warning("cmd buld null data failed %d", | ||
1668 | ret); | ||
1669 | goto out_sleep; | ||
1670 | } | ||
1671 | |||
1672 | /* Need to update the BSSID (for filtering etc) */ | ||
1673 | do_join = true; | ||
1674 | } | ||
1675 | |||
1476 | if (changed & BSS_CHANGED_ASSOC) { | 1676 | if (changed & BSS_CHANGED_ASSOC) { |
1477 | if (bss_conf->assoc) { | 1677 | if (bss_conf->assoc) { |
1478 | wl->aid = bss_conf->aid; | 1678 | wl->aid = bss_conf->aid; |
1679 | set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | ||
1479 | 1680 | ||
1480 | /* | 1681 | /* |
1481 | * with wl1271, we don't need to update the | 1682 | * with wl1271, we don't need to update the |
@@ -1492,15 +1693,16 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1492 | goto out_sleep; | 1693 | goto out_sleep; |
1493 | 1694 | ||
1494 | /* If we want to go in PSM but we're not there yet */ | 1695 | /* If we want to go in PSM but we're not there yet */ |
1495 | if (wl->psm_requested && !wl->psm) { | 1696 | if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) && |
1697 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) { | ||
1496 | mode = STATION_POWER_SAVE_MODE; | 1698 | mode = STATION_POWER_SAVE_MODE; |
1497 | ret = wl1271_ps_set_mode(wl, mode); | 1699 | ret = wl1271_ps_set_mode(wl, mode, true); |
1498 | if (ret < 0) | 1700 | if (ret < 0) |
1499 | goto out_sleep; | 1701 | goto out_sleep; |
1500 | } | 1702 | } |
1501 | } else { | 1703 | } else { |
1502 | /* use defaults when not associated */ | 1704 | /* use defaults when not associated */ |
1503 | wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET; | 1705 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); |
1504 | wl->aid = 0; | 1706 | wl->aid = 0; |
1505 | } | 1707 | } |
1506 | 1708 | ||
@@ -1535,15 +1737,13 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1535 | } | 1737 | } |
1536 | } | 1738 | } |
1537 | 1739 | ||
1538 | if (changed & BSS_CHANGED_BASIC_RATES) { | 1740 | if (do_join) { |
1539 | wl->basic_rate_set = wl1271_enabled_rates_get( | 1741 | ret = wl1271_cmd_join(wl); |
1540 | wl, bss_conf->basic_rates); | ||
1541 | |||
1542 | ret = wl1271_acx_rate_policies(wl, wl->basic_rate_set); | ||
1543 | if (ret < 0) { | 1742 | if (ret < 0) { |
1544 | wl1271_warning("Set rate policies failed %d", ret); | 1743 | wl1271_warning("cmd join failed %d", ret); |
1545 | goto out_sleep; | 1744 | goto out_sleep; |
1546 | } | 1745 | } |
1746 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | ||
1547 | } | 1747 | } |
1548 | 1748 | ||
1549 | out_sleep: | 1749 | out_sleep: |
@@ -1553,6 +1753,43 @@ out: | |||
1553 | mutex_unlock(&wl->mutex); | 1753 | mutex_unlock(&wl->mutex); |
1554 | } | 1754 | } |
1555 | 1755 | ||
1756 | static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | ||
1757 | const struct ieee80211_tx_queue_params *params) | ||
1758 | { | ||
1759 | struct wl1271 *wl = hw->priv; | ||
1760 | int ret; | ||
1761 | |||
1762 | mutex_lock(&wl->mutex); | ||
1763 | |||
1764 | wl1271_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue); | ||
1765 | |||
1766 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
1767 | if (ret < 0) | ||
1768 | goto out; | ||
1769 | |||
1770 | ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), | ||
1771 | params->cw_min, params->cw_max, | ||
1772 | params->aifs, params->txop); | ||
1773 | if (ret < 0) | ||
1774 | goto out_sleep; | ||
1775 | |||
1776 | ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), | ||
1777 | CONF_CHANNEL_TYPE_EDCF, | ||
1778 | wl1271_tx_get_queue(queue), | ||
1779 | CONF_PS_SCHEME_LEGACY_PSPOLL, | ||
1780 | CONF_ACK_POLICY_LEGACY, 0, 0); | ||
1781 | if (ret < 0) | ||
1782 | goto out_sleep; | ||
1783 | |||
1784 | out_sleep: | ||
1785 | wl1271_ps_elp_sleep(wl); | ||
1786 | |||
1787 | out: | ||
1788 | mutex_unlock(&wl->mutex); | ||
1789 | |||
1790 | return ret; | ||
1791 | } | ||
1792 | |||
1556 | 1793 | ||
1557 | /* can't be const, mac80211 writes to this */ | 1794 | /* can't be const, mac80211 writes to this */ |
1558 | static struct ieee80211_rate wl1271_rates[] = { | 1795 | static struct ieee80211_rate wl1271_rates[] = { |
@@ -1599,19 +1836,19 @@ static struct ieee80211_rate wl1271_rates[] = { | |||
1599 | 1836 | ||
1600 | /* can't be const, mac80211 writes to this */ | 1837 | /* can't be const, mac80211 writes to this */ |
1601 | static struct ieee80211_channel wl1271_channels[] = { | 1838 | static struct ieee80211_channel wl1271_channels[] = { |
1602 | { .hw_value = 1, .center_freq = 2412}, | 1839 | { .hw_value = 1, .center_freq = 2412, .max_power = 25 }, |
1603 | { .hw_value = 2, .center_freq = 2417}, | 1840 | { .hw_value = 2, .center_freq = 2417, .max_power = 25 }, |
1604 | { .hw_value = 3, .center_freq = 2422}, | 1841 | { .hw_value = 3, .center_freq = 2422, .max_power = 25 }, |
1605 | { .hw_value = 4, .center_freq = 2427}, | 1842 | { .hw_value = 4, .center_freq = 2427, .max_power = 25 }, |
1606 | { .hw_value = 5, .center_freq = 2432}, | 1843 | { .hw_value = 5, .center_freq = 2432, .max_power = 25 }, |
1607 | { .hw_value = 6, .center_freq = 2437}, | 1844 | { .hw_value = 6, .center_freq = 2437, .max_power = 25 }, |
1608 | { .hw_value = 7, .center_freq = 2442}, | 1845 | { .hw_value = 7, .center_freq = 2442, .max_power = 25 }, |
1609 | { .hw_value = 8, .center_freq = 2447}, | 1846 | { .hw_value = 8, .center_freq = 2447, .max_power = 25 }, |
1610 | { .hw_value = 9, .center_freq = 2452}, | 1847 | { .hw_value = 9, .center_freq = 2452, .max_power = 25 }, |
1611 | { .hw_value = 10, .center_freq = 2457}, | 1848 | { .hw_value = 10, .center_freq = 2457, .max_power = 25 }, |
1612 | { .hw_value = 11, .center_freq = 2462}, | 1849 | { .hw_value = 11, .center_freq = 2462, .max_power = 25 }, |
1613 | { .hw_value = 12, .center_freq = 2467}, | 1850 | { .hw_value = 12, .center_freq = 2467, .max_power = 25 }, |
1614 | { .hw_value = 13, .center_freq = 2472}, | 1851 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, |
1615 | }; | 1852 | }; |
1616 | 1853 | ||
1617 | /* can't be const, mac80211 writes to this */ | 1854 | /* can't be const, mac80211 writes to this */ |
@@ -1718,6 +1955,8 @@ static const struct ieee80211_ops wl1271_ops = { | |||
1718 | .hw_scan = wl1271_op_hw_scan, | 1955 | .hw_scan = wl1271_op_hw_scan, |
1719 | .bss_info_changed = wl1271_op_bss_info_changed, | 1956 | .bss_info_changed = wl1271_op_bss_info_changed, |
1720 | .set_rts_threshold = wl1271_op_set_rts_threshold, | 1957 | .set_rts_threshold = wl1271_op_set_rts_threshold, |
1958 | .conf_tx = wl1271_op_conf_tx, | ||
1959 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | ||
1721 | }; | 1960 | }; |
1722 | 1961 | ||
1723 | static int wl1271_register_hw(struct wl1271 *wl) | 1962 | static int wl1271_register_hw(struct wl1271 *wl) |
@@ -1757,7 +1996,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
1757 | IEEE80211_HW_BEACON_FILTER | | 1996 | IEEE80211_HW_BEACON_FILTER | |
1758 | IEEE80211_HW_SUPPORTS_PS; | 1997 | IEEE80211_HW_SUPPORTS_PS; |
1759 | 1998 | ||
1760 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | 1999 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
2000 | BIT(NL80211_IFTYPE_ADHOC); | ||
1761 | wl->hw->wiphy->max_scan_ssids = 1; | 2001 | wl->hw->wiphy->max_scan_ssids = 1; |
1762 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; | 2002 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; |
1763 | 2003 | ||
@@ -1785,24 +2025,17 @@ static struct platform_device wl1271_device = { | |||
1785 | }; | 2025 | }; |
1786 | 2026 | ||
1787 | #define WL1271_DEFAULT_CHANNEL 0 | 2027 | #define WL1271_DEFAULT_CHANNEL 0 |
1788 | static int __devinit wl1271_probe(struct spi_device *spi) | 2028 | |
2029 | static struct ieee80211_hw *wl1271_alloc_hw(void) | ||
1789 | { | 2030 | { |
1790 | struct wl12xx_platform_data *pdata; | ||
1791 | struct ieee80211_hw *hw; | 2031 | struct ieee80211_hw *hw; |
1792 | struct wl1271 *wl; | 2032 | struct wl1271 *wl; |
1793 | int ret, i; | 2033 | int i; |
1794 | static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; | ||
1795 | |||
1796 | pdata = spi->dev.platform_data; | ||
1797 | if (!pdata) { | ||
1798 | wl1271_error("no platform data"); | ||
1799 | return -ENODEV; | ||
1800 | } | ||
1801 | 2034 | ||
1802 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); | 2035 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); |
1803 | if (!hw) { | 2036 | if (!hw) { |
1804 | wl1271_error("could not alloc ieee80211_hw"); | 2037 | wl1271_error("could not alloc ieee80211_hw"); |
1805 | return -ENOMEM; | 2038 | return ERR_PTR(-ENOMEM); |
1806 | } | 2039 | } |
1807 | 2040 | ||
1808 | wl = hw->priv; | 2041 | wl = hw->priv; |
@@ -1811,44 +2044,80 @@ static int __devinit wl1271_probe(struct spi_device *spi) | |||
1811 | INIT_LIST_HEAD(&wl->list); | 2044 | INIT_LIST_HEAD(&wl->list); |
1812 | 2045 | ||
1813 | wl->hw = hw; | 2046 | wl->hw = hw; |
1814 | dev_set_drvdata(&spi->dev, wl); | ||
1815 | wl->spi = spi; | ||
1816 | 2047 | ||
1817 | skb_queue_head_init(&wl->tx_queue); | 2048 | skb_queue_head_init(&wl->tx_queue); |
1818 | 2049 | ||
1819 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); | 2050 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); |
1820 | wl->channel = WL1271_DEFAULT_CHANNEL; | 2051 | wl->channel = WL1271_DEFAULT_CHANNEL; |
1821 | wl->scanning = false; | ||
1822 | wl->default_key = 0; | 2052 | wl->default_key = 0; |
1823 | wl->rx_counter = 0; | 2053 | wl->rx_counter = 0; |
1824 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 2054 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; |
1825 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; | 2055 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; |
1826 | wl->elp = false; | ||
1827 | wl->psm = 0; | ||
1828 | wl->psm_requested = false; | ||
1829 | wl->psm_entry_retry = 0; | 2056 | wl->psm_entry_retry = 0; |
1830 | wl->tx_queue_stopped = false; | ||
1831 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 2057 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
1832 | wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET; | 2058 | wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; |
2059 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | ||
2060 | wl->sta_rate_set = 0; | ||
1833 | wl->band = IEEE80211_BAND_2GHZ; | 2061 | wl->band = IEEE80211_BAND_2GHZ; |
1834 | wl->vif = NULL; | 2062 | wl->vif = NULL; |
1835 | wl->joined = false; | 2063 | wl->flags = 0; |
1836 | 2064 | ||
1837 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 2065 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
1838 | wl->tx_frames[i] = NULL; | 2066 | wl->tx_frames[i] = NULL; |
1839 | 2067 | ||
1840 | spin_lock_init(&wl->wl_lock); | 2068 | spin_lock_init(&wl->wl_lock); |
1841 | 2069 | ||
1842 | /* | ||
1843 | * In case our MAC address is not correctly set, | ||
1844 | * we use a random but Nokia MAC. | ||
1845 | */ | ||
1846 | memcpy(wl->mac_addr, nokia_oui, 3); | ||
1847 | get_random_bytes(wl->mac_addr + 3, 3); | ||
1848 | |||
1849 | wl->state = WL1271_STATE_OFF; | 2070 | wl->state = WL1271_STATE_OFF; |
1850 | mutex_init(&wl->mutex); | 2071 | mutex_init(&wl->mutex); |
1851 | 2072 | ||
2073 | /* Apply default driver configuration. */ | ||
2074 | wl1271_conf_init(wl); | ||
2075 | |||
2076 | return hw; | ||
2077 | } | ||
2078 | |||
2079 | int wl1271_free_hw(struct wl1271 *wl) | ||
2080 | { | ||
2081 | ieee80211_unregister_hw(wl->hw); | ||
2082 | |||
2083 | wl1271_debugfs_exit(wl); | ||
2084 | |||
2085 | kfree(wl->target_mem_map); | ||
2086 | vfree(wl->fw); | ||
2087 | wl->fw = NULL; | ||
2088 | kfree(wl->nvs); | ||
2089 | wl->nvs = NULL; | ||
2090 | |||
2091 | kfree(wl->fw_status); | ||
2092 | kfree(wl->tx_res_if); | ||
2093 | |||
2094 | ieee80211_free_hw(wl->hw); | ||
2095 | |||
2096 | return 0; | ||
2097 | } | ||
2098 | |||
2099 | static int __devinit wl1271_probe(struct spi_device *spi) | ||
2100 | { | ||
2101 | struct wl12xx_platform_data *pdata; | ||
2102 | struct ieee80211_hw *hw; | ||
2103 | struct wl1271 *wl; | ||
2104 | int ret; | ||
2105 | |||
2106 | pdata = spi->dev.platform_data; | ||
2107 | if (!pdata) { | ||
2108 | wl1271_error("no platform data"); | ||
2109 | return -ENODEV; | ||
2110 | } | ||
2111 | |||
2112 | hw = wl1271_alloc_hw(); | ||
2113 | if (IS_ERR(hw)) | ||
2114 | return PTR_ERR(hw); | ||
2115 | |||
2116 | wl = hw->priv; | ||
2117 | |||
2118 | dev_set_drvdata(&spi->dev, wl); | ||
2119 | wl->spi = spi; | ||
2120 | |||
1852 | /* This is the only SPI value that we need to set here, the rest | 2121 | /* This is the only SPI value that we need to set here, the rest |
1853 | * comes from the board-peripherals file */ | 2122 | * comes from the board-peripherals file */ |
1854 | spi->bits_per_word = 32; | 2123 | spi->bits_per_word = 32; |
@@ -1890,9 +2159,6 @@ static int __devinit wl1271_probe(struct spi_device *spi) | |||
1890 | } | 2159 | } |
1891 | dev_set_drvdata(&wl1271_device.dev, wl); | 2160 | dev_set_drvdata(&wl1271_device.dev, wl); |
1892 | 2161 | ||
1893 | /* Apply default driver configuration. */ | ||
1894 | wl1271_conf_init(wl); | ||
1895 | |||
1896 | ret = wl1271_init_ieee80211(wl); | 2162 | ret = wl1271_init_ieee80211(wl); |
1897 | if (ret) | 2163 | if (ret) |
1898 | goto out_platform; | 2164 | goto out_platform; |
@@ -1923,21 +2189,10 @@ static int __devexit wl1271_remove(struct spi_device *spi) | |||
1923 | { | 2189 | { |
1924 | struct wl1271 *wl = dev_get_drvdata(&spi->dev); | 2190 | struct wl1271 *wl = dev_get_drvdata(&spi->dev); |
1925 | 2191 | ||
1926 | ieee80211_unregister_hw(wl->hw); | ||
1927 | |||
1928 | wl1271_debugfs_exit(wl); | ||
1929 | platform_device_unregister(&wl1271_device); | 2192 | platform_device_unregister(&wl1271_device); |
1930 | free_irq(wl->irq, wl); | 2193 | free_irq(wl->irq, wl); |
1931 | kfree(wl->target_mem_map); | ||
1932 | vfree(wl->fw); | ||
1933 | wl->fw = NULL; | ||
1934 | kfree(wl->nvs); | ||
1935 | wl->nvs = NULL; | ||
1936 | 2194 | ||
1937 | kfree(wl->fw_status); | 2195 | wl1271_free_hw(wl); |
1938 | kfree(wl->tx_res_if); | ||
1939 | |||
1940 | ieee80211_free_hw(wl->hw); | ||
1941 | 2196 | ||
1942 | return 0; | 2197 | return 0; |
1943 | } | 2198 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c index 507cd91d7eed..e2b1ebf096e8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ b/drivers/net/wireless/wl12xx/wl1271_ps.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "wl1271_reg.h" | 24 | #include "wl1271_reg.h" |
25 | #include "wl1271_ps.h" | 25 | #include "wl1271_ps.h" |
26 | #include "wl1271_spi.h" | 26 | #include "wl1271_spi.h" |
27 | #include "wl1271_io.h" | ||
27 | 28 | ||
28 | #define WL1271_WAKEUP_TIMEOUT 500 | 29 | #define WL1271_WAKEUP_TIMEOUT 500 |
29 | 30 | ||
@@ -39,12 +40,13 @@ void wl1271_elp_work(struct work_struct *work) | |||
39 | 40 | ||
40 | mutex_lock(&wl->mutex); | 41 | mutex_lock(&wl->mutex); |
41 | 42 | ||
42 | if (wl->elp || !wl->psm) | 43 | if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || |
44 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) | ||
43 | goto out; | 45 | goto out; |
44 | 46 | ||
45 | wl1271_debug(DEBUG_PSM, "chip to elp"); | 47 | wl1271_debug(DEBUG_PSM, "chip to elp"); |
46 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); | 48 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); |
47 | wl->elp = true; | 49 | set_bit(WL1271_FLAG_IN_ELP, &wl->flags); |
48 | 50 | ||
49 | out: | 51 | out: |
50 | mutex_unlock(&wl->mutex); | 52 | mutex_unlock(&wl->mutex); |
@@ -55,7 +57,7 @@ out: | |||
55 | /* Routines to toggle sleep mode while in ELP */ | 57 | /* Routines to toggle sleep mode while in ELP */ |
56 | void wl1271_ps_elp_sleep(struct wl1271 *wl) | 58 | void wl1271_ps_elp_sleep(struct wl1271 *wl) |
57 | { | 59 | { |
58 | if (wl->psm) { | 60 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { |
59 | cancel_delayed_work(&wl->elp_work); | 61 | cancel_delayed_work(&wl->elp_work); |
60 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, | 62 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, |
61 | msecs_to_jiffies(ELP_ENTRY_DELAY)); | 63 | msecs_to_jiffies(ELP_ENTRY_DELAY)); |
@@ -70,7 +72,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake) | |||
70 | u32 start_time = jiffies; | 72 | u32 start_time = jiffies; |
71 | bool pending = false; | 73 | bool pending = false; |
72 | 74 | ||
73 | if (!wl->elp) | 75 | if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags)) |
74 | return 0; | 76 | return 0; |
75 | 77 | ||
76 | wl1271_debug(DEBUG_PSM, "waking up chip from elp"); | 78 | wl1271_debug(DEBUG_PSM, "waking up chip from elp"); |
@@ -101,7 +103,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake) | |||
101 | } | 103 | } |
102 | } | 104 | } |
103 | 105 | ||
104 | wl->elp = false; | 106 | clear_bit(WL1271_FLAG_IN_ELP, &wl->flags); |
105 | 107 | ||
106 | wl1271_debug(DEBUG_PSM, "wakeup time: %u ms", | 108 | wl1271_debug(DEBUG_PSM, "wakeup time: %u ms", |
107 | jiffies_to_msecs(jiffies - start_time)); | 109 | jiffies_to_msecs(jiffies - start_time)); |
@@ -117,7 +119,8 @@ out: | |||
117 | return 0; | 119 | return 0; |
118 | } | 120 | } |
119 | 121 | ||
120 | int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode) | 122 | int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, |
123 | bool send) | ||
121 | { | 124 | { |
122 | int ret; | 125 | int ret; |
123 | 126 | ||
@@ -125,25 +128,11 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode) | |||
125 | case STATION_POWER_SAVE_MODE: | 128 | case STATION_POWER_SAVE_MODE: |
126 | wl1271_debug(DEBUG_PSM, "entering psm"); | 129 | wl1271_debug(DEBUG_PSM, "entering psm"); |
127 | 130 | ||
128 | /* enable beacon filtering */ | 131 | ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE, send); |
129 | ret = wl1271_acx_beacon_filter_opt(wl, true); | ||
130 | if (ret < 0) | 132 | if (ret < 0) |
131 | return ret; | 133 | return ret; |
132 | 134 | ||
133 | /* enable beacon early termination */ | 135 | set_bit(WL1271_FLAG_PSM, &wl->flags); |
134 | ret = wl1271_acx_bet_enable(wl, true); | ||
135 | if (ret < 0) | ||
136 | return ret; | ||
137 | |||
138 | ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE); | ||
139 | if (ret < 0) | ||
140 | return ret; | ||
141 | |||
142 | wl1271_ps_elp_sleep(wl); | ||
143 | if (ret < 0) | ||
144 | return ret; | ||
145 | |||
146 | wl->psm = 1; | ||
147 | break; | 136 | break; |
148 | case STATION_ACTIVE_MODE: | 137 | case STATION_ACTIVE_MODE: |
149 | default: | 138 | default: |
@@ -162,11 +151,11 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode) | |||
162 | if (ret < 0) | 151 | if (ret < 0) |
163 | return ret; | 152 | return ret; |
164 | 153 | ||
165 | ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE); | 154 | ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE, send); |
166 | if (ret < 0) | 155 | if (ret < 0) |
167 | return ret; | 156 | return ret; |
168 | 157 | ||
169 | wl->psm = 0; | 158 | clear_bit(WL1271_FLAG_PSM, &wl->flags); |
170 | break; | 159 | break; |
171 | } | 160 | } |
172 | 161 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.h b/drivers/net/wireless/wl12xx/wl1271_ps.h index 779653d0ae85..940276f517a4 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.h +++ b/drivers/net/wireless/wl12xx/wl1271_ps.h | |||
@@ -27,7 +27,8 @@ | |||
27 | #include "wl1271.h" | 27 | #include "wl1271.h" |
28 | #include "wl1271_acx.h" | 28 | #include "wl1271_acx.h" |
29 | 29 | ||
30 | int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode); | 30 | int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, |
31 | bool send); | ||
31 | void wl1271_ps_elp_sleep(struct wl1271 *wl); | 32 | void wl1271_ps_elp_sleep(struct wl1271 *wl); |
32 | int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake); | 33 | int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake); |
33 | void wl1271_elp_work(struct work_struct *work); | 34 | void wl1271_elp_work(struct work_struct *work); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_reg.h b/drivers/net/wireless/wl12xx/wl1271_reg.h index 1f237389d1c7..990960771528 100644 --- a/drivers/net/wireless/wl12xx/wl1271_reg.h +++ b/drivers/net/wireless/wl12xx/wl1271_reg.h | |||
@@ -62,73 +62,10 @@ | |||
62 | #define WL1271_SLV_REG_DATA (REGISTERS_BASE + 0x0008) | 62 | #define WL1271_SLV_REG_DATA (REGISTERS_BASE + 0x0008) |
63 | #define WL1271_SLV_REG_ADATA (REGISTERS_BASE + 0x000c) | 63 | #define WL1271_SLV_REG_ADATA (REGISTERS_BASE + 0x000c) |
64 | #define WL1271_SLV_MEM_DATA (REGISTERS_BASE + 0x0018) | 64 | #define WL1271_SLV_MEM_DATA (REGISTERS_BASE + 0x0018) |
65 | /* | ||
66 | * Interrupt registers. | ||
67 | * 64 bit interrupt sources registers ws ced. | ||
68 | * sme interupts were removed and new ones were added. | ||
69 | * Order was changed. | ||
70 | */ | ||
71 | #define FIQ_MASK (REGISTERS_BASE + 0x0400) | ||
72 | #define FIQ_MASK_L (REGISTERS_BASE + 0x0400) | ||
73 | #define FIQ_MASK_H (REGISTERS_BASE + 0x0404) | ||
74 | #define FIQ_MASK_SET (REGISTERS_BASE + 0x0408) | ||
75 | #define FIQ_MASK_SET_L (REGISTERS_BASE + 0x0408) | ||
76 | #define FIQ_MASK_SET_H (REGISTERS_BASE + 0x040C) | ||
77 | #define FIQ_MASK_CLR (REGISTERS_BASE + 0x0410) | ||
78 | #define FIQ_MASK_CLR_L (REGISTERS_BASE + 0x0410) | ||
79 | #define FIQ_MASK_CLR_H (REGISTERS_BASE + 0x0414) | ||
80 | #define IRQ_MASK (REGISTERS_BASE + 0x0418) | ||
81 | #define IRQ_MASK_L (REGISTERS_BASE + 0x0418) | ||
82 | #define IRQ_MASK_H (REGISTERS_BASE + 0x041C) | ||
83 | #define IRQ_MASK_SET (REGISTERS_BASE + 0x0420) | ||
84 | #define IRQ_MASK_SET_L (REGISTERS_BASE + 0x0420) | ||
85 | #define IRQ_MASK_SET_H (REGISTERS_BASE + 0x0424) | ||
86 | #define IRQ_MASK_CLR (REGISTERS_BASE + 0x0428) | ||
87 | #define IRQ_MASK_CLR_L (REGISTERS_BASE + 0x0428) | ||
88 | #define IRQ_MASK_CLR_H (REGISTERS_BASE + 0x042C) | ||
89 | #define ECPU_MASK (REGISTERS_BASE + 0x0448) | ||
90 | #define FIQ_STS_L (REGISTERS_BASE + 0x044C) | ||
91 | #define FIQ_STS_H (REGISTERS_BASE + 0x0450) | ||
92 | #define IRQ_STS_L (REGISTERS_BASE + 0x0454) | ||
93 | #define IRQ_STS_H (REGISTERS_BASE + 0x0458) | ||
94 | #define INT_STS_ND (REGISTERS_BASE + 0x0464) | ||
95 | #define INT_STS_RAW_L (REGISTERS_BASE + 0x0464) | ||
96 | #define INT_STS_RAW_H (REGISTERS_BASE + 0x0468) | ||
97 | #define INT_STS_CLR (REGISTERS_BASE + 0x04B4) | ||
98 | #define INT_STS_CLR_L (REGISTERS_BASE + 0x04B4) | ||
99 | #define INT_STS_CLR_H (REGISTERS_BASE + 0x04B8) | ||
100 | #define INT_ACK (REGISTERS_BASE + 0x046C) | ||
101 | #define INT_ACK_L (REGISTERS_BASE + 0x046C) | ||
102 | #define INT_ACK_H (REGISTERS_BASE + 0x0470) | ||
103 | #define INT_TRIG (REGISTERS_BASE + 0x0474) | ||
104 | #define INT_TRIG_L (REGISTERS_BASE + 0x0474) | ||
105 | #define INT_TRIG_H (REGISTERS_BASE + 0x0478) | ||
106 | #define HOST_STS_L (REGISTERS_BASE + 0x045C) | ||
107 | #define HOST_STS_H (REGISTERS_BASE + 0x0460) | ||
108 | #define HOST_MASK (REGISTERS_BASE + 0x0430) | ||
109 | #define HOST_MASK_L (REGISTERS_BASE + 0x0430) | ||
110 | #define HOST_MASK_H (REGISTERS_BASE + 0x0434) | ||
111 | #define HOST_MASK_SET (REGISTERS_BASE + 0x0438) | ||
112 | #define HOST_MASK_SET_L (REGISTERS_BASE + 0x0438) | ||
113 | #define HOST_MASK_SET_H (REGISTERS_BASE + 0x043C) | ||
114 | #define HOST_MASK_CLR (REGISTERS_BASE + 0x0440) | ||
115 | #define HOST_MASK_CLR_L (REGISTERS_BASE + 0x0440) | ||
116 | #define HOST_MASK_CLR_H (REGISTERS_BASE + 0x0444) | ||
117 | 65 | ||
118 | #define ACX_REG_INTERRUPT_TRIG (REGISTERS_BASE + 0x0474) | 66 | #define ACX_REG_INTERRUPT_TRIG (REGISTERS_BASE + 0x0474) |
119 | #define ACX_REG_INTERRUPT_TRIG_H (REGISTERS_BASE + 0x0478) | 67 | #define ACX_REG_INTERRUPT_TRIG_H (REGISTERS_BASE + 0x0478) |
120 | 68 | ||
121 | /* Host Interrupts*/ | ||
122 | #define HINT_MASK (REGISTERS_BASE + 0x0494) | ||
123 | #define HINT_MASK_SET (REGISTERS_BASE + 0x0498) | ||
124 | #define HINT_MASK_CLR (REGISTERS_BASE + 0x049C) | ||
125 | #define HINT_STS_ND_MASKED (REGISTERS_BASE + 0x04A0) | ||
126 | /*1150 spec calls this HINT_STS_RAW*/ | ||
127 | #define HINT_STS_ND (REGISTERS_BASE + 0x04B0) | ||
128 | #define HINT_STS_CLR (REGISTERS_BASE + 0x04A4) | ||
129 | #define HINT_ACK (REGISTERS_BASE + 0x04A8) | ||
130 | #define HINT_TRIG (REGISTERS_BASE + 0x04AC) | ||
131 | |||
132 | /*============================================= | 69 | /*============================================= |
133 | Host Interrupt Mask Register - 32bit (RW) | 70 | Host Interrupt Mask Register - 32bit (RW) |
134 | ------------------------------------------ | 71 | ------------------------------------------ |
@@ -433,16 +370,6 @@ | |||
433 | 370 | ||
434 | 371 | ||
435 | /*=============================================== | 372 | /*=============================================== |
436 | Phy regs | ||
437 | ===============================================*/ | ||
438 | #define ACX_PHY_ADDR_REG SBB_ADDR | ||
439 | #define ACX_PHY_DATA_REG SBB_DATA | ||
440 | #define ACX_PHY_CTRL_REG SBB_CTL | ||
441 | #define ACX_PHY_REG_WR_MASK 0x00000001ul | ||
442 | #define ACX_PHY_REG_RD_MASK 0x00000002ul | ||
443 | |||
444 | |||
445 | /*=============================================== | ||
446 | EEPROM Read/Write Request 32bit RW | 373 | EEPROM Read/Write Request 32bit RW |
447 | ------------------------------------------ | 374 | ------------------------------------------ |
448 | 1 EE_READ - EEPROM Read Request 1 - Setting this bit | 375 | 1 EE_READ - EEPROM Read Request 1 - Setting this bit |
@@ -511,28 +438,6 @@ | |||
511 | #define ACX_CONT_WIND_MIN_MASK 0x0000007f | 438 | #define ACX_CONT_WIND_MIN_MASK 0x0000007f |
512 | #define ACX_CONT_WIND_MAX 0x03ff0000 | 439 | #define ACX_CONT_WIND_MAX 0x03ff0000 |
513 | 440 | ||
514 | /* | ||
515 | * Indirect slave register/memory registers | ||
516 | * ---------------------------------------- | ||
517 | */ | ||
518 | #define HW_SLAVE_REG_ADDR_REG 0x00000004 | ||
519 | #define HW_SLAVE_REG_DATA_REG 0x00000008 | ||
520 | #define HW_SLAVE_REG_CTRL_REG 0x0000000c | ||
521 | |||
522 | #define SLAVE_AUTO_INC 0x00010000 | ||
523 | #define SLAVE_NO_AUTO_INC 0x00000000 | ||
524 | #define SLAVE_HOST_LITTLE_ENDIAN 0x00000000 | ||
525 | |||
526 | #define HW_SLAVE_MEM_ADDR_REG SLV_MEM_ADDR | ||
527 | #define HW_SLAVE_MEM_DATA_REG SLV_MEM_DATA | ||
528 | #define HW_SLAVE_MEM_CTRL_REG SLV_MEM_CTL | ||
529 | #define HW_SLAVE_MEM_ENDIAN_REG SLV_END_CTL | ||
530 | |||
531 | #define HW_FUNC_EVENT_INT_EN 0x8000 | ||
532 | #define HW_FUNC_EVENT_MASK_REG 0x00000034 | ||
533 | |||
534 | #define ACX_MAC_TIMESTAMP_REG (MAC_TIMESTAMP) | ||
535 | |||
536 | /*=============================================== | 441 | /*=============================================== |
537 | HI_CFG Interface Configuration Register Values | 442 | HI_CFG Interface Configuration Register Values |
538 | ------------------------------------------ | 443 | ------------------------------------------ |
@@ -647,10 +552,6 @@ b12-b0 - Supported Rate indicator bits as defined below. | |||
647 | ******************************************************************************/ | 552 | ******************************************************************************/ |
648 | 553 | ||
649 | 554 | ||
650 | #define TNETW1251_CHIP_ID_PG1_0 0x07010101 | ||
651 | #define TNETW1251_CHIP_ID_PG1_1 0x07020101 | ||
652 | #define TNETW1251_CHIP_ID_PG1_2 0x07030101 | ||
653 | |||
654 | /************************************************************************* | 555 | /************************************************************************* |
655 | 556 | ||
656 | Interrupt Trigger Register (Host -> WiLink) | 557 | Interrupt Trigger Register (Host -> WiLink) |
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index ca645f38109b..6730f5b96e76 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/wl1271_rx.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "wl1271_reg.h" | 26 | #include "wl1271_reg.h" |
27 | #include "wl1271_rx.h" | 27 | #include "wl1271_rx.h" |
28 | #include "wl1271_spi.h" | 28 | #include "wl1271_spi.h" |
29 | #include "wl1271_io.h" | ||
29 | 30 | ||
30 | static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status, | 31 | static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status, |
31 | u32 drv_rx_counter) | 32 | u32 drv_rx_counter) |
@@ -166,7 +167,7 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) | |||
166 | } | 167 | } |
167 | 168 | ||
168 | buf = skb_put(skb, length); | 169 | buf = skb_put(skb, length); |
169 | wl1271_spi_read(wl, WL1271_SLV_MEM_DATA, buf, length, true); | 170 | wl1271_read(wl, WL1271_SLV_MEM_DATA, buf, length, true); |
170 | 171 | ||
171 | /* the data read starts with the descriptor */ | 172 | /* the data read starts with the descriptor */ |
172 | desc = (struct wl1271_rx_descriptor *) buf; | 173 | desc = (struct wl1271_rx_descriptor *) buf; |
@@ -210,15 +211,13 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) | |||
210 | wl->rx_mem_pool_addr.addr + 4; | 211 | wl->rx_mem_pool_addr.addr + 4; |
211 | 212 | ||
212 | /* Choose the block we want to read */ | 213 | /* Choose the block we want to read */ |
213 | wl1271_spi_write(wl, WL1271_SLV_REG_DATA, | 214 | wl1271_write(wl, WL1271_SLV_REG_DATA, &wl->rx_mem_pool_addr, |
214 | &wl->rx_mem_pool_addr, | 215 | sizeof(wl->rx_mem_pool_addr), false); |
215 | sizeof(wl->rx_mem_pool_addr), false); | ||
216 | 216 | ||
217 | wl1271_rx_handle_data(wl, buf_size); | 217 | wl1271_rx_handle_data(wl, buf_size); |
218 | 218 | ||
219 | wl->rx_counter++; | 219 | wl->rx_counter++; |
220 | drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; | 220 | drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; |
221 | wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); | ||
221 | } | 222 | } |
222 | |||
223 | wl1271_spi_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); | ||
224 | } | 223 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index 02978a16e732..67a82934f36e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c | |||
@@ -30,28 +30,6 @@ | |||
30 | #include "wl12xx_80211.h" | 30 | #include "wl12xx_80211.h" |
31 | #include "wl1271_spi.h" | 31 | #include "wl1271_spi.h" |
32 | 32 | ||
33 | static int wl1271_translate_addr(struct wl1271 *wl, int addr) | ||
34 | { | ||
35 | /* | ||
36 | * To translate, first check to which window of addresses the | ||
37 | * particular address belongs. Then subtract the starting address | ||
38 | * of that window from the address. Then, add offset of the | ||
39 | * translated region. | ||
40 | * | ||
41 | * The translated regions occur next to each other in physical device | ||
42 | * memory, so just add the sizes of the preceeding address regions to | ||
43 | * get the offset to the new region. | ||
44 | * | ||
45 | * Currently, only the two first regions are addressed, and the | ||
46 | * assumption is that all addresses will fall into either of those | ||
47 | * two. | ||
48 | */ | ||
49 | if ((addr >= wl->part.reg.start) && | ||
50 | (addr < wl->part.reg.start + wl->part.reg.size)) | ||
51 | return addr - wl->part.reg.start + wl->part.mem.size; | ||
52 | else | ||
53 | return addr - wl->part.mem.start; | ||
54 | } | ||
55 | 33 | ||
56 | void wl1271_spi_reset(struct wl1271 *wl) | 34 | void wl1271_spi_reset(struct wl1271 *wl) |
57 | { | 35 | { |
@@ -133,67 +111,6 @@ void wl1271_spi_init(struct wl1271 *wl) | |||
133 | wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); | 111 | wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); |
134 | } | 112 | } |
135 | 113 | ||
136 | /* Set the SPI partitions to access the chip addresses | ||
137 | * | ||
138 | * To simplify driver code, a fixed (virtual) memory map is defined for | ||
139 | * register and memory addresses. Because in the chipset, in different stages | ||
140 | * of operation, those addresses will move around, an address translation | ||
141 | * mechanism is required. | ||
142 | * | ||
143 | * There are four partitions (three memory and one register partition), | ||
144 | * which are mapped to two different areas of the hardware memory. | ||
145 | * | ||
146 | * Virtual address | ||
147 | * space | ||
148 | * | ||
149 | * | | | ||
150 | * ...+----+--> mem.start | ||
151 | * Physical address ... | | | ||
152 | * space ... | | [PART_0] | ||
153 | * ... | | | ||
154 | * 00000000 <--+----+... ...+----+--> mem.start + mem.size | ||
155 | * | | ... | | | ||
156 | * |MEM | ... | | | ||
157 | * | | ... | | | ||
158 | * mem.size <--+----+... | | {unused area) | ||
159 | * | | ... | | | ||
160 | * |REG | ... | | | ||
161 | * mem.size | | ... | | | ||
162 | * + <--+----+... ...+----+--> reg.start | ||
163 | * reg.size | | ... | | | ||
164 | * |MEM2| ... | | [PART_1] | ||
165 | * | | ... | | | ||
166 | * ...+----+--> reg.start + reg.size | ||
167 | * | | | ||
168 | * | ||
169 | */ | ||
170 | int wl1271_set_partition(struct wl1271 *wl, | ||
171 | struct wl1271_partition_set *p) | ||
172 | { | ||
173 | /* copy partition info */ | ||
174 | memcpy(&wl->part, p, sizeof(*p)); | ||
175 | |||
176 | wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", | ||
177 | p->mem.start, p->mem.size); | ||
178 | wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", | ||
179 | p->reg.start, p->reg.size); | ||
180 | wl1271_debug(DEBUG_SPI, "mem2_start %08X mem2_size %08X", | ||
181 | p->mem2.start, p->mem2.size); | ||
182 | wl1271_debug(DEBUG_SPI, "mem3_start %08X mem3_size %08X", | ||
183 | p->mem3.start, p->mem3.size); | ||
184 | |||
185 | /* write partition info to the chipset */ | ||
186 | wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start); | ||
187 | wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size); | ||
188 | wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start); | ||
189 | wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size); | ||
190 | wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start); | ||
191 | wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size); | ||
192 | wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start); | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | #define WL1271_BUSY_WORD_TIMEOUT 1000 | 114 | #define WL1271_BUSY_WORD_TIMEOUT 1000 |
198 | 115 | ||
199 | /* FIXME: Check busy words, removed due to SPI bug */ | 116 | /* FIXME: Check busy words, removed due to SPI bug */ |
@@ -338,78 +255,3 @@ void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, | |||
338 | wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); | 255 | wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); |
339 | wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); | 256 | wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); |
340 | } | 257 | } |
341 | |||
342 | void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
343 | bool fixed) | ||
344 | { | ||
345 | int physical; | ||
346 | |||
347 | physical = wl1271_translate_addr(wl, addr); | ||
348 | |||
349 | wl1271_spi_raw_read(wl, physical, buf, len, fixed); | ||
350 | } | ||
351 | |||
352 | void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
353 | bool fixed) | ||
354 | { | ||
355 | int physical; | ||
356 | |||
357 | physical = wl1271_translate_addr(wl, addr); | ||
358 | |||
359 | wl1271_spi_raw_write(wl, physical, buf, len, fixed); | ||
360 | } | ||
361 | |||
362 | u32 wl1271_spi_read32(struct wl1271 *wl, int addr) | ||
363 | { | ||
364 | return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr)); | ||
365 | } | ||
366 | |||
367 | void wl1271_spi_write32(struct wl1271 *wl, int addr, u32 val) | ||
368 | { | ||
369 | wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val); | ||
370 | } | ||
371 | |||
372 | void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val) | ||
373 | { | ||
374 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ | ||
375 | addr = (addr >> 1) + 0x30000; | ||
376 | wl1271_spi_write32(wl, OCP_POR_CTR, addr); | ||
377 | |||
378 | /* write value to OCP_POR_WDATA */ | ||
379 | wl1271_spi_write32(wl, OCP_DATA_WRITE, val); | ||
380 | |||
381 | /* write 1 to OCP_CMD */ | ||
382 | wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_WRITE); | ||
383 | } | ||
384 | |||
385 | u16 wl1271_top_reg_read(struct wl1271 *wl, int addr) | ||
386 | { | ||
387 | u32 val; | ||
388 | int timeout = OCP_CMD_LOOP; | ||
389 | |||
390 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ | ||
391 | addr = (addr >> 1) + 0x30000; | ||
392 | wl1271_spi_write32(wl, OCP_POR_CTR, addr); | ||
393 | |||
394 | /* write 2 to OCP_CMD */ | ||
395 | wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_READ); | ||
396 | |||
397 | /* poll for data ready */ | ||
398 | do { | ||
399 | val = wl1271_spi_read32(wl, OCP_DATA_READ); | ||
400 | timeout--; | ||
401 | } while (!(val & OCP_READY_MASK) && timeout); | ||
402 | |||
403 | if (!timeout) { | ||
404 | wl1271_warning("Top register access timed out."); | ||
405 | return 0xffff; | ||
406 | } | ||
407 | |||
408 | /* check data status and return if OK */ | ||
409 | if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK) | ||
410 | return val & 0xffff; | ||
411 | else { | ||
412 | wl1271_warning("Top register access returned error."); | ||
413 | return 0xffff; | ||
414 | } | ||
415 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.h b/drivers/net/wireless/wl12xx/wl1271_spi.h index cb7df1c56314..a803596dad4a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.h +++ b/drivers/net/wireless/wl12xx/wl1271_spi.h | |||
@@ -90,37 +90,7 @@ void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, | |||
90 | void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, | 90 | void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, |
91 | size_t len, bool fixed); | 91 | size_t len, bool fixed); |
92 | 92 | ||
93 | /* Translated target IO */ | ||
94 | void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
95 | bool fixed); | ||
96 | void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
97 | bool fixed); | ||
98 | u32 wl1271_spi_read32(struct wl1271 *wl, int addr); | ||
99 | void wl1271_spi_write32(struct wl1271 *wl, int addr, u32 val); | ||
100 | |||
101 | /* Top Register IO */ | ||
102 | void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val); | ||
103 | u16 wl1271_top_reg_read(struct wl1271 *wl, int addr); | ||
104 | |||
105 | /* INIT and RESET words */ | 93 | /* INIT and RESET words */ |
106 | void wl1271_spi_reset(struct wl1271 *wl); | 94 | void wl1271_spi_reset(struct wl1271 *wl); |
107 | void wl1271_spi_init(struct wl1271 *wl); | 95 | void wl1271_spi_init(struct wl1271 *wl); |
108 | int wl1271_set_partition(struct wl1271 *wl, | ||
109 | struct wl1271_partition_set *p); | ||
110 | |||
111 | static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) | ||
112 | { | ||
113 | wl1271_spi_raw_read(wl, addr, &wl->buffer_32, | ||
114 | sizeof(wl->buffer_32), false); | ||
115 | |||
116 | return wl->buffer_32; | ||
117 | } | ||
118 | |||
119 | static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val) | ||
120 | { | ||
121 | wl->buffer_32 = val; | ||
122 | wl1271_spi_raw_write(wl, addr, &wl->buffer_32, | ||
123 | sizeof(wl->buffer_32), false); | ||
124 | } | ||
125 | |||
126 | #endif /* __WL1271_SPI_H__ */ | 96 | #endif /* __WL1271_SPI_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.c b/drivers/net/wireless/wl12xx/wl1271_testmode.c new file mode 100644 index 000000000000..3919102e942e --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_testmode.c | |||
@@ -0,0 +1,283 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 2010 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | #include "wl1271_testmode.h" | ||
24 | |||
25 | #include <net/genetlink.h> | ||
26 | |||
27 | #include "wl1271.h" | ||
28 | #include "wl1271_spi.h" | ||
29 | #include "wl1271_acx.h" | ||
30 | |||
31 | #define WL1271_TM_MAX_DATA_LENGTH 1024 | ||
32 | |||
33 | enum wl1271_tm_commands { | ||
34 | WL1271_TM_CMD_UNSPEC, | ||
35 | WL1271_TM_CMD_TEST, | ||
36 | WL1271_TM_CMD_INTERROGATE, | ||
37 | WL1271_TM_CMD_CONFIGURE, | ||
38 | WL1271_TM_CMD_NVS_PUSH, | ||
39 | WL1271_TM_CMD_SET_PLT_MODE, | ||
40 | |||
41 | __WL1271_TM_CMD_AFTER_LAST | ||
42 | }; | ||
43 | #define WL1271_TM_CMD_MAX (__WL1271_TM_CMD_AFTER_LAST - 1) | ||
44 | |||
45 | enum wl1271_tm_attrs { | ||
46 | WL1271_TM_ATTR_UNSPEC, | ||
47 | WL1271_TM_ATTR_CMD_ID, | ||
48 | WL1271_TM_ATTR_ANSWER, | ||
49 | WL1271_TM_ATTR_DATA, | ||
50 | WL1271_TM_ATTR_IE_ID, | ||
51 | WL1271_TM_ATTR_PLT_MODE, | ||
52 | |||
53 | __WL1271_TM_ATTR_AFTER_LAST | ||
54 | }; | ||
55 | #define WL1271_TM_ATTR_MAX (__WL1271_TM_ATTR_AFTER_LAST - 1) | ||
56 | |||
57 | static struct nla_policy wl1271_tm_policy[WL1271_TM_ATTR_MAX + 1] = { | ||
58 | [WL1271_TM_ATTR_CMD_ID] = { .type = NLA_U32 }, | ||
59 | [WL1271_TM_ATTR_ANSWER] = { .type = NLA_U8 }, | ||
60 | [WL1271_TM_ATTR_DATA] = { .type = NLA_BINARY, | ||
61 | .len = WL1271_TM_MAX_DATA_LENGTH }, | ||
62 | [WL1271_TM_ATTR_IE_ID] = { .type = NLA_U32 }, | ||
63 | [WL1271_TM_ATTR_PLT_MODE] = { .type = NLA_U32 }, | ||
64 | }; | ||
65 | |||
66 | |||
67 | static int wl1271_tm_cmd_test(struct wl1271 *wl, struct nlattr *tb[]) | ||
68 | { | ||
69 | int buf_len, ret, len; | ||
70 | struct sk_buff *skb; | ||
71 | void *buf; | ||
72 | u8 answer = 0; | ||
73 | |||
74 | wl1271_debug(DEBUG_TESTMODE, "testmode cmd test"); | ||
75 | |||
76 | if (!tb[WL1271_TM_ATTR_DATA]) | ||
77 | return -EINVAL; | ||
78 | |||
79 | buf = nla_data(tb[WL1271_TM_ATTR_DATA]); | ||
80 | buf_len = nla_len(tb[WL1271_TM_ATTR_DATA]); | ||
81 | |||
82 | if (tb[WL1271_TM_ATTR_ANSWER]) | ||
83 | answer = nla_get_u8(tb[WL1271_TM_ATTR_ANSWER]); | ||
84 | |||
85 | if (buf_len > sizeof(struct wl1271_command)) | ||
86 | return -EMSGSIZE; | ||
87 | |||
88 | mutex_lock(&wl->mutex); | ||
89 | ret = wl1271_cmd_test(wl, buf, buf_len, answer); | ||
90 | mutex_unlock(&wl->mutex); | ||
91 | |||
92 | if (ret < 0) { | ||
93 | wl1271_warning("testmode cmd test failed: %d", ret); | ||
94 | return ret; | ||
95 | } | ||
96 | |||
97 | if (answer) { | ||
98 | len = nla_total_size(buf_len); | ||
99 | skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, len); | ||
100 | if (!skb) | ||
101 | return -ENOMEM; | ||
102 | |||
103 | NLA_PUT(skb, WL1271_TM_ATTR_DATA, buf_len, buf); | ||
104 | ret = cfg80211_testmode_reply(skb); | ||
105 | if (ret < 0) | ||
106 | return ret; | ||
107 | } | ||
108 | |||
109 | return 0; | ||
110 | |||
111 | nla_put_failure: | ||
112 | kfree_skb(skb); | ||
113 | return -EMSGSIZE; | ||
114 | } | ||
115 | |||
116 | static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[]) | ||
117 | { | ||
118 | int ret; | ||
119 | struct wl1271_command *cmd; | ||
120 | struct sk_buff *skb; | ||
121 | u8 ie_id; | ||
122 | |||
123 | wl1271_debug(DEBUG_TESTMODE, "testmode cmd interrogate"); | ||
124 | |||
125 | if (!tb[WL1271_TM_ATTR_IE_ID]) | ||
126 | return -EINVAL; | ||
127 | |||
128 | ie_id = nla_get_u8(tb[WL1271_TM_ATTR_IE_ID]); | ||
129 | |||
130 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
131 | if (!cmd) | ||
132 | return -ENOMEM; | ||
133 | |||
134 | mutex_lock(&wl->mutex); | ||
135 | ret = wl1271_cmd_interrogate(wl, ie_id, cmd, sizeof(*cmd)); | ||
136 | mutex_unlock(&wl->mutex); | ||
137 | |||
138 | if (ret < 0) { | ||
139 | wl1271_warning("testmode cmd interrogate failed: %d", ret); | ||
140 | return ret; | ||
141 | } | ||
142 | |||
143 | skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, sizeof(*cmd)); | ||
144 | if (!skb) | ||
145 | return -ENOMEM; | ||
146 | |||
147 | NLA_PUT(skb, WL1271_TM_ATTR_DATA, sizeof(*cmd), cmd); | ||
148 | |||
149 | return 0; | ||
150 | |||
151 | nla_put_failure: | ||
152 | kfree_skb(skb); | ||
153 | return -EMSGSIZE; | ||
154 | } | ||
155 | |||
156 | static int wl1271_tm_cmd_configure(struct wl1271 *wl, struct nlattr *tb[]) | ||
157 | { | ||
158 | int buf_len, ret; | ||
159 | void *buf; | ||
160 | u8 ie_id; | ||
161 | |||
162 | wl1271_debug(DEBUG_TESTMODE, "testmode cmd configure"); | ||
163 | |||
164 | if (!tb[WL1271_TM_ATTR_DATA]) | ||
165 | return -EINVAL; | ||
166 | if (!tb[WL1271_TM_ATTR_IE_ID]) | ||
167 | return -EINVAL; | ||
168 | |||
169 | ie_id = nla_get_u8(tb[WL1271_TM_ATTR_IE_ID]); | ||
170 | buf = nla_data(tb[WL1271_TM_ATTR_DATA]); | ||
171 | buf_len = nla_len(tb[WL1271_TM_ATTR_DATA]); | ||
172 | |||
173 | if (buf_len > sizeof(struct wl1271_command)) | ||
174 | return -EMSGSIZE; | ||
175 | |||
176 | mutex_lock(&wl->mutex); | ||
177 | ret = wl1271_cmd_configure(wl, ie_id, buf, buf_len); | ||
178 | mutex_unlock(&wl->mutex); | ||
179 | |||
180 | if (ret < 0) { | ||
181 | wl1271_warning("testmode cmd configure failed: %d", ret); | ||
182 | return ret; | ||
183 | } | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[]) | ||
189 | { | ||
190 | int ret = 0; | ||
191 | size_t len; | ||
192 | void *buf; | ||
193 | |||
194 | wl1271_debug(DEBUG_TESTMODE, "testmode cmd nvs push"); | ||
195 | |||
196 | if (!tb[WL1271_TM_ATTR_DATA]) | ||
197 | return -EINVAL; | ||
198 | |||
199 | buf = nla_data(tb[WL1271_TM_ATTR_DATA]); | ||
200 | len = nla_len(tb[WL1271_TM_ATTR_DATA]); | ||
201 | |||
202 | if (len != sizeof(struct wl1271_nvs_file)) { | ||
203 | wl1271_error("nvs size is not as expected: %zu != %zu", | ||
204 | len, sizeof(struct wl1271_nvs_file)); | ||
205 | return -EMSGSIZE; | ||
206 | } | ||
207 | |||
208 | mutex_lock(&wl->mutex); | ||
209 | |||
210 | kfree(wl->nvs); | ||
211 | |||
212 | wl->nvs = kmalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL); | ||
213 | if (!wl->nvs) { | ||
214 | wl1271_error("could not allocate memory for the nvs file"); | ||
215 | ret = -ENOMEM; | ||
216 | goto out; | ||
217 | } | ||
218 | |||
219 | memcpy(wl->nvs, buf, len); | ||
220 | |||
221 | wl1271_debug(DEBUG_TESTMODE, "testmode pushed nvs"); | ||
222 | |||
223 | out: | ||
224 | mutex_unlock(&wl->mutex); | ||
225 | |||
226 | return ret; | ||
227 | } | ||
228 | |||
229 | static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[]) | ||
230 | { | ||
231 | u32 val; | ||
232 | int ret; | ||
233 | |||
234 | wl1271_debug(DEBUG_TESTMODE, "testmode cmd set plt mode"); | ||
235 | |||
236 | if (!tb[WL1271_TM_ATTR_PLT_MODE]) | ||
237 | return -EINVAL; | ||
238 | |||
239 | val = nla_get_u32(tb[WL1271_TM_ATTR_PLT_MODE]); | ||
240 | |||
241 | switch (val) { | ||
242 | case 0: | ||
243 | ret = wl1271_plt_stop(wl); | ||
244 | break; | ||
245 | case 1: | ||
246 | ret = wl1271_plt_start(wl); | ||
247 | break; | ||
248 | default: | ||
249 | ret = -EINVAL; | ||
250 | break; | ||
251 | } | ||
252 | |||
253 | return ret; | ||
254 | } | ||
255 | |||
256 | int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len) | ||
257 | { | ||
258 | struct wl1271 *wl = hw->priv; | ||
259 | struct nlattr *tb[WL1271_TM_ATTR_MAX + 1]; | ||
260 | int err; | ||
261 | |||
262 | err = nla_parse(tb, WL1271_TM_ATTR_MAX, data, len, wl1271_tm_policy); | ||
263 | if (err) | ||
264 | return err; | ||
265 | |||
266 | if (!tb[WL1271_TM_ATTR_CMD_ID]) | ||
267 | return -EINVAL; | ||
268 | |||
269 | switch (nla_get_u32(tb[WL1271_TM_ATTR_CMD_ID])) { | ||
270 | case WL1271_TM_CMD_TEST: | ||
271 | return wl1271_tm_cmd_test(wl, tb); | ||
272 | case WL1271_TM_CMD_INTERROGATE: | ||
273 | return wl1271_tm_cmd_interrogate(wl, tb); | ||
274 | case WL1271_TM_CMD_CONFIGURE: | ||
275 | return wl1271_tm_cmd_configure(wl, tb); | ||
276 | case WL1271_TM_CMD_NVS_PUSH: | ||
277 | return wl1271_tm_cmd_nvs_push(wl, tb); | ||
278 | case WL1271_TM_CMD_SET_PLT_MODE: | ||
279 | return wl1271_tm_cmd_set_plt_mode(wl, tb); | ||
280 | default: | ||
281 | return -EOPNOTSUPP; | ||
282 | } | ||
283 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.h b/drivers/net/wireless/wl12xx/wl1271_testmode.h new file mode 100644 index 000000000000..c196d28f9d9d --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_testmode.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 2010 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #ifndef __WL1271_TESTMODE_H__ | ||
25 | #define __WL1271_TESTMODE_H__ | ||
26 | |||
27 | #include <net/mac80211.h> | ||
28 | |||
29 | int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len); | ||
30 | |||
31 | #endif /* __WL1271_TESTMODE_H__ */ | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index 00af065c77c2..811e739d05bf 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c | |||
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | #include "wl1271.h" | 27 | #include "wl1271.h" |
28 | #include "wl1271_spi.h" | 28 | #include "wl1271_spi.h" |
29 | #include "wl1271_io.h" | ||
29 | #include "wl1271_reg.h" | 30 | #include "wl1271_reg.h" |
30 | #include "wl1271_ps.h" | 31 | #include "wl1271_ps.h" |
31 | #include "wl1271_tx.h" | 32 | #include "wl1271_tx.h" |
@@ -87,7 +88,7 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
87 | u32 extra, struct ieee80211_tx_info *control) | 88 | u32 extra, struct ieee80211_tx_info *control) |
88 | { | 89 | { |
89 | struct wl1271_tx_hw_descr *desc; | 90 | struct wl1271_tx_hw_descr *desc; |
90 | int pad; | 91 | int pad, ac; |
91 | u16 tx_attr; | 92 | u16 tx_attr; |
92 | 93 | ||
93 | desc = (struct wl1271_tx_hw_descr *) skb->data; | 94 | desc = (struct wl1271_tx_hw_descr *) skb->data; |
@@ -107,9 +108,11 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
107 | 108 | ||
108 | /* configure the tx attributes */ | 109 | /* configure the tx attributes */ |
109 | tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; | 110 | tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; |
110 | /* FIXME: do we know the packet priority? can we identify mgmt | 111 | |
111 | packets, and use max prio for them at least? */ | 112 | /* queue */ |
112 | desc->tid = 0; | 113 | ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); |
114 | desc->tid = wl1271_tx_ac_to_tid(ac); | ||
115 | |||
113 | desc->aid = TX_HW_DEFAULT_AID; | 116 | desc->aid = TX_HW_DEFAULT_AID; |
114 | desc->reserved = 0; | 117 | desc->reserved = 0; |
115 | 118 | ||
@@ -121,6 +124,11 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
121 | pad = pad - skb->len; | 124 | pad = pad - skb->len; |
122 | tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; | 125 | tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; |
123 | 126 | ||
127 | /* if the packets are destined for AP (have a STA entry) send them | ||
128 | with AP rate policies, otherwise use default basic rates */ | ||
129 | if (control->control.sta) | ||
130 | tx_attr |= ACX_TX_AP_FULL_RATE << TX_HW_ATTR_OFST_RATE_POLICY; | ||
131 | |||
124 | desc->tx_attr = cpu_to_le16(tx_attr); | 132 | desc->tx_attr = cpu_to_le16(tx_attr); |
125 | 133 | ||
126 | wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad); | 134 | wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad); |
@@ -158,11 +166,11 @@ static int wl1271_tx_send_packet(struct wl1271 *wl, struct sk_buff *skb, | |||
158 | len = WL1271_TX_ALIGN(skb->len); | 166 | len = WL1271_TX_ALIGN(skb->len); |
159 | 167 | ||
160 | /* perform a fixed address block write with the packet */ | 168 | /* perform a fixed address block write with the packet */ |
161 | wl1271_spi_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true); | 169 | wl1271_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true); |
162 | 170 | ||
163 | /* write packet new counter into the write access register */ | 171 | /* write packet new counter into the write access register */ |
164 | wl->tx_packets_count++; | 172 | wl->tx_packets_count++; |
165 | wl1271_spi_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); | 173 | wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); |
166 | 174 | ||
167 | desc = (struct wl1271_tx_hw_descr *) skb->data; | 175 | desc = (struct wl1271_tx_hw_descr *) skb->data; |
168 | wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)", | 176 | wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)", |
@@ -196,6 +204,7 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) | |||
196 | ret = wl1271_cmd_set_default_wep_key(wl, idx); | 204 | ret = wl1271_cmd_set_default_wep_key(wl, idx); |
197 | if (ret < 0) | 205 | if (ret < 0) |
198 | return ret; | 206 | return ret; |
207 | wl->default_key = idx; | ||
199 | } | 208 | } |
200 | } | 209 | } |
201 | 210 | ||
@@ -214,18 +223,50 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) | |||
214 | return ret; | 223 | return ret; |
215 | } | 224 | } |
216 | 225 | ||
226 | static u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) | ||
227 | { | ||
228 | struct ieee80211_supported_band *band; | ||
229 | u32 enabled_rates = 0; | ||
230 | int bit; | ||
231 | |||
232 | band = wl->hw->wiphy->bands[wl->band]; | ||
233 | for (bit = 0; bit < band->n_bitrates; bit++) { | ||
234 | if (rate_set & 0x1) | ||
235 | enabled_rates |= band->bitrates[bit].hw_value; | ||
236 | rate_set >>= 1; | ||
237 | } | ||
238 | |||
239 | return enabled_rates; | ||
240 | } | ||
241 | |||
217 | void wl1271_tx_work(struct work_struct *work) | 242 | void wl1271_tx_work(struct work_struct *work) |
218 | { | 243 | { |
219 | struct wl1271 *wl = container_of(work, struct wl1271, tx_work); | 244 | struct wl1271 *wl = container_of(work, struct wl1271, tx_work); |
220 | struct sk_buff *skb; | 245 | struct sk_buff *skb; |
221 | bool woken_up = false; | 246 | bool woken_up = false; |
247 | u32 sta_rates = 0; | ||
222 | int ret; | 248 | int ret; |
223 | 249 | ||
250 | /* check if the rates supported by the AP have changed */ | ||
251 | if (unlikely(test_and_clear_bit(WL1271_FLAG_STA_RATES_CHANGED, | ||
252 | &wl->flags))) { | ||
253 | unsigned long flags; | ||
254 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
255 | sta_rates = wl->sta_rate_set; | ||
256 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
257 | } | ||
258 | |||
224 | mutex_lock(&wl->mutex); | 259 | mutex_lock(&wl->mutex); |
225 | 260 | ||
226 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 261 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
227 | goto out; | 262 | goto out; |
228 | 263 | ||
264 | /* if rates have changed, re-configure the rate policy */ | ||
265 | if (unlikely(sta_rates)) { | ||
266 | wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates); | ||
267 | wl1271_acx_rate_policies(wl); | ||
268 | } | ||
269 | |||
229 | while ((skb = skb_dequeue(&wl->tx_queue))) { | 270 | while ((skb = skb_dequeue(&wl->tx_queue))) { |
230 | if (!woken_up) { | 271 | if (!woken_up) { |
231 | ret = wl1271_ps_elp_wakeup(wl, false); | 272 | ret = wl1271_ps_elp_wakeup(wl, false); |
@@ -240,18 +281,18 @@ void wl1271_tx_work(struct work_struct *work) | |||
240 | wl1271_debug(DEBUG_TX, "tx_work: fw buffer full, " | 281 | wl1271_debug(DEBUG_TX, "tx_work: fw buffer full, " |
241 | "stop queues"); | 282 | "stop queues"); |
242 | ieee80211_stop_queues(wl->hw); | 283 | ieee80211_stop_queues(wl->hw); |
243 | wl->tx_queue_stopped = true; | 284 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); |
244 | skb_queue_head(&wl->tx_queue, skb); | 285 | skb_queue_head(&wl->tx_queue, skb); |
245 | goto out; | 286 | goto out; |
246 | } else if (ret < 0) { | 287 | } else if (ret < 0) { |
247 | dev_kfree_skb(skb); | 288 | dev_kfree_skb(skb); |
248 | goto out; | 289 | goto out; |
249 | } else if (wl->tx_queue_stopped) { | 290 | } else if (test_and_clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, |
291 | &wl->flags)) { | ||
250 | /* firmware buffer has space, restart queues */ | 292 | /* firmware buffer has space, restart queues */ |
251 | wl1271_debug(DEBUG_TX, | 293 | wl1271_debug(DEBUG_TX, |
252 | "complete_packet: waking queues"); | 294 | "complete_packet: waking queues"); |
253 | ieee80211_wake_queues(wl->hw); | 295 | ieee80211_wake_queues(wl->hw); |
254 | wl->tx_queue_stopped = false; | ||
255 | } | 296 | } |
256 | } | 297 | } |
257 | 298 | ||
@@ -335,8 +376,8 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count) | |||
335 | wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); | 376 | wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); |
336 | 377 | ||
337 | /* read the tx results from the chipset */ | 378 | /* read the tx results from the chipset */ |
338 | wl1271_spi_read(wl, le32_to_cpu(memmap->tx_result), | 379 | wl1271_read(wl, le32_to_cpu(memmap->tx_result), |
339 | wl->tx_res_if, sizeof(*wl->tx_res_if), false); | 380 | wl->tx_res_if, sizeof(*wl->tx_res_if), false); |
340 | 381 | ||
341 | /* verify that the result buffer is not getting overrun */ | 382 | /* verify that the result buffer is not getting overrun */ |
342 | if (count > TX_HW_RESULT_QUEUE_LEN) { | 383 | if (count > TX_HW_RESULT_QUEUE_LEN) { |
@@ -357,10 +398,10 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count) | |||
357 | } | 398 | } |
358 | 399 | ||
359 | /* write host counter to chipset (to ack) */ | 400 | /* write host counter to chipset (to ack) */ |
360 | wl1271_spi_write32(wl, le32_to_cpu(memmap->tx_result) + | 401 | wl1271_write32(wl, le32_to_cpu(memmap->tx_result) + |
361 | offsetof(struct wl1271_tx_hw_res_if, | 402 | offsetof(struct wl1271_tx_hw_res_if, |
362 | tx_result_host_counter), | 403 | tx_result_host_counter), |
363 | le32_to_cpu(wl->tx_res_if->tx_result_fw_counter)); | 404 | le32_to_cpu(wl->tx_res_if->tx_result_fw_counter)); |
364 | } | 405 | } |
365 | 406 | ||
366 | /* caller must hold wl->mutex */ | 407 | /* caller must hold wl->mutex */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h index 416396caf0a0..17e405a09caa 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.h +++ b/drivers/net/wireless/wl12xx/wl1271_tx.h | |||
@@ -123,6 +123,42 @@ struct wl1271_tx_hw_res_if { | |||
123 | struct wl1271_tx_hw_res_descr tx_results_queue[TX_HW_RESULT_QUEUE_LEN]; | 123 | struct wl1271_tx_hw_res_descr tx_results_queue[TX_HW_RESULT_QUEUE_LEN]; |
124 | } __attribute__ ((packed)); | 124 | } __attribute__ ((packed)); |
125 | 125 | ||
126 | static inline int wl1271_tx_get_queue(int queue) | ||
127 | { | ||
128 | /* FIXME: use best effort until WMM is enabled */ | ||
129 | return CONF_TX_AC_BE; | ||
130 | |||
131 | switch (queue) { | ||
132 | case 0: | ||
133 | return CONF_TX_AC_VO; | ||
134 | case 1: | ||
135 | return CONF_TX_AC_VI; | ||
136 | case 2: | ||
137 | return CONF_TX_AC_BE; | ||
138 | case 3: | ||
139 | return CONF_TX_AC_BK; | ||
140 | default: | ||
141 | return CONF_TX_AC_BE; | ||
142 | } | ||
143 | } | ||
144 | |||
145 | /* wl1271 tx descriptor needs the tid and we need to convert it from ac */ | ||
146 | static inline int wl1271_tx_ac_to_tid(int ac) | ||
147 | { | ||
148 | switch (ac) { | ||
149 | case 0: | ||
150 | return 0; | ||
151 | case 1: | ||
152 | return 2; | ||
153 | case 2: | ||
154 | return 4; | ||
155 | case 3: | ||
156 | return 6; | ||
157 | default: | ||
158 | return 0; | ||
159 | } | ||
160 | } | ||
161 | |||
126 | void wl1271_tx_work(struct work_struct *work); | 162 | void wl1271_tx_work(struct work_struct *work); |
127 | void wl1271_tx_complete(struct wl1271 *wl, u32 count); | 163 | void wl1271_tx_complete(struct wl1271 *wl, u32 count); |
128 | void wl1271_tx_flush(struct wl1271 *wl); | 164 | void wl1271_tx_flush(struct wl1271 *wl); |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 9d9b263733e6..d90f0a25b9cf 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -869,7 +869,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) | |||
869 | } | 869 | } |
870 | 870 | ||
871 | static int zd_op_add_interface(struct ieee80211_hw *hw, | 871 | static int zd_op_add_interface(struct ieee80211_hw *hw, |
872 | struct ieee80211_if_init_conf *conf) | 872 | struct ieee80211_vif *vif) |
873 | { | 873 | { |
874 | struct zd_mac *mac = zd_hw_mac(hw); | 874 | struct zd_mac *mac = zd_hw_mac(hw); |
875 | 875 | ||
@@ -877,22 +877,22 @@ static int zd_op_add_interface(struct ieee80211_hw *hw, | |||
877 | if (mac->type != NL80211_IFTYPE_UNSPECIFIED) | 877 | if (mac->type != NL80211_IFTYPE_UNSPECIFIED) |
878 | return -EOPNOTSUPP; | 878 | return -EOPNOTSUPP; |
879 | 879 | ||
880 | switch (conf->type) { | 880 | switch (vif->type) { |
881 | case NL80211_IFTYPE_MONITOR: | 881 | case NL80211_IFTYPE_MONITOR: |
882 | case NL80211_IFTYPE_MESH_POINT: | 882 | case NL80211_IFTYPE_MESH_POINT: |
883 | case NL80211_IFTYPE_STATION: | 883 | case NL80211_IFTYPE_STATION: |
884 | case NL80211_IFTYPE_ADHOC: | 884 | case NL80211_IFTYPE_ADHOC: |
885 | mac->type = conf->type; | 885 | mac->type = vif->type; |
886 | break; | 886 | break; |
887 | default: | 887 | default: |
888 | return -EOPNOTSUPP; | 888 | return -EOPNOTSUPP; |
889 | } | 889 | } |
890 | 890 | ||
891 | return zd_write_mac_addr(&mac->chip, conf->mac_addr); | 891 | return zd_write_mac_addr(&mac->chip, vif->addr); |
892 | } | 892 | } |
893 | 893 | ||
894 | static void zd_op_remove_interface(struct ieee80211_hw *hw, | 894 | static void zd_op_remove_interface(struct ieee80211_hw *hw, |
895 | struct ieee80211_if_init_conf *conf) | 895 | struct ieee80211_vif *vif) |
896 | { | 896 | { |
897 | struct zd_mac *mac = zd_hw_mac(hw); | 897 | struct zd_mac *mac = zd_hw_mac(hw); |
898 | mac->type = NL80211_IFTYPE_UNSPECIFIED; | 898 | mac->type = NL80211_IFTYPE_UNSPECIFIED; |
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 72d3e437e190..442fc1117326 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c | |||
@@ -1079,11 +1079,15 @@ static int eject_installer(struct usb_interface *intf) | |||
1079 | int r; | 1079 | int r; |
1080 | 1080 | ||
1081 | /* Find bulk out endpoint */ | 1081 | /* Find bulk out endpoint */ |
1082 | endpoint = &iface_desc->endpoint[1].desc; | 1082 | for (r = 1; r >= 0; r--) { |
1083 | if (usb_endpoint_dir_out(endpoint) && | 1083 | endpoint = &iface_desc->endpoint[r].desc; |
1084 | usb_endpoint_xfer_bulk(endpoint)) { | 1084 | if (usb_endpoint_dir_out(endpoint) && |
1085 | bulk_out_ep = endpoint->bEndpointAddress; | 1085 | usb_endpoint_xfer_bulk(endpoint)) { |
1086 | } else { | 1086 | bulk_out_ep = endpoint->bEndpointAddress; |
1087 | break; | ||
1088 | } | ||
1089 | } | ||
1090 | if (r == -1) { | ||
1087 | dev_err(&udev->dev, | 1091 | dev_err(&udev->dev, |
1088 | "zd1211rw: Could not find bulk out endpoint\n"); | 1092 | "zd1211rw: Could not find bulk out endpoint\n"); |
1089 | return -ENODEV; | 1093 | return -ENODEV; |