diff options
author | John W. Linville <linville@tuxdriver.com> | 2011-05-05 13:56:27 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-05-05 13:56:27 -0400 |
commit | 890641b2512f491f28e4ef7536dca1ea93dae997 (patch) | |
tree | 4dec378be564731945e033aca438e41324a3a522 | |
parent | eaef6a93bd52a2cc47b9fce201310010707afdb4 (diff) | |
parent | 25eaea30cd7b009ba2ca693708330d2f395cbc4d (diff) |
Merge branch 'for-linville' of git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx
-rw-r--r-- | drivers/net/wireless/wl12xx/acx.c | 190 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/acx.h | 103 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/boot.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/cmd.c | 18 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/conf.h | 90 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/debugfs.c | 239 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/event.c | 47 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/event.h | 12 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/init.c | 110 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/init.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 232 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/ps.c | 30 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/rx.c | 36 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/tx.c | 13 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/tx.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl12xx.h | 2 |
16 files changed, 852 insertions, 280 deletions
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index a5c9c0aff83..c6ee530e5bf 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c | |||
@@ -325,12 +325,19 @@ out: | |||
325 | return ret; | 325 | return ret; |
326 | } | 326 | } |
327 | 327 | ||
328 | int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold) | 328 | int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold) |
329 | { | 329 | { |
330 | struct acx_rts_threshold *rts; | 330 | struct acx_rts_threshold *rts; |
331 | int ret; | 331 | int ret; |
332 | 332 | ||
333 | wl1271_debug(DEBUG_ACX, "acx rts threshold"); | 333 | /* |
334 | * If the RTS threshold is not configured or out of range, use the | ||
335 | * default value. | ||
336 | */ | ||
337 | if (rts_threshold > IEEE80211_MAX_RTS_THRESHOLD) | ||
338 | rts_threshold = wl->conf.rx.rts_threshold; | ||
339 | |||
340 | wl1271_debug(DEBUG_ACX, "acx rts threshold: %d", rts_threshold); | ||
334 | 341 | ||
335 | rts = kzalloc(sizeof(*rts), GFP_KERNEL); | 342 | rts = kzalloc(sizeof(*rts), GFP_KERNEL); |
336 | if (!rts) { | 343 | if (!rts) { |
@@ -338,7 +345,7 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold) | |||
338 | goto out; | 345 | goto out; |
339 | } | 346 | } |
340 | 347 | ||
341 | rts->threshold = cpu_to_le16(rts_threshold); | 348 | rts->threshold = cpu_to_le16((u16)rts_threshold); |
342 | 349 | ||
343 | ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts)); | 350 | ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts)); |
344 | if (ret < 0) { | 351 | if (ret < 0) { |
@@ -540,13 +547,13 @@ out: | |||
540 | return ret; | 547 | return ret; |
541 | } | 548 | } |
542 | 549 | ||
543 | int wl1271_acx_sg_cfg(struct wl1271 *wl) | 550 | int wl1271_acx_sta_sg_cfg(struct wl1271 *wl) |
544 | { | 551 | { |
545 | struct acx_bt_wlan_coex_param *param; | 552 | struct acx_sta_bt_wlan_coex_param *param; |
546 | struct conf_sg_settings *c = &wl->conf.sg; | 553 | struct conf_sg_settings *c = &wl->conf.sg; |
547 | int i, ret; | 554 | int i, ret; |
548 | 555 | ||
549 | wl1271_debug(DEBUG_ACX, "acx sg cfg"); | 556 | wl1271_debug(DEBUG_ACX, "acx sg sta cfg"); |
550 | 557 | ||
551 | param = kzalloc(sizeof(*param), GFP_KERNEL); | 558 | param = kzalloc(sizeof(*param), GFP_KERNEL); |
552 | if (!param) { | 559 | if (!param) { |
@@ -555,8 +562,38 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl) | |||
555 | } | 562 | } |
556 | 563 | ||
557 | /* BT-WLAN coext parameters */ | 564 | /* BT-WLAN coext parameters */ |
558 | for (i = 0; i < CONF_SG_PARAMS_MAX; i++) | 565 | for (i = 0; i < CONF_SG_STA_PARAMS_MAX; i++) |
559 | param->params[i] = cpu_to_le32(c->params[i]); | 566 | param->params[i] = cpu_to_le32(c->sta_params[i]); |
567 | param->param_idx = CONF_SG_PARAMS_ALL; | ||
568 | |||
569 | ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); | ||
570 | if (ret < 0) { | ||
571 | wl1271_warning("failed to set sg config: %d", ret); | ||
572 | goto out; | ||
573 | } | ||
574 | |||
575 | out: | ||
576 | kfree(param); | ||
577 | return ret; | ||
578 | } | ||
579 | |||
580 | int wl1271_acx_ap_sg_cfg(struct wl1271 *wl) | ||
581 | { | ||
582 | struct acx_ap_bt_wlan_coex_param *param; | ||
583 | struct conf_sg_settings *c = &wl->conf.sg; | ||
584 | int i, ret; | ||
585 | |||
586 | wl1271_debug(DEBUG_ACX, "acx sg ap cfg"); | ||
587 | |||
588 | param = kzalloc(sizeof(*param), GFP_KERNEL); | ||
589 | if (!param) { | ||
590 | ret = -ENOMEM; | ||
591 | goto out; | ||
592 | } | ||
593 | |||
594 | /* BT-WLAN coext parameters */ | ||
595 | for (i = 0; i < CONF_SG_AP_PARAMS_MAX; i++) | ||
596 | param->params[i] = cpu_to_le32(c->ap_params[i]); | ||
560 | param->param_idx = CONF_SG_PARAMS_ALL; | 597 | param->param_idx = CONF_SG_PARAMS_ALL; |
561 | 598 | ||
562 | ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); | 599 | ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); |
@@ -804,7 +841,8 @@ int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c, | |||
804 | struct acx_ap_rate_policy *acx; | 841 | struct acx_ap_rate_policy *acx; |
805 | int ret = 0; | 842 | int ret = 0; |
806 | 843 | ||
807 | wl1271_debug(DEBUG_ACX, "acx ap rate policy"); | 844 | wl1271_debug(DEBUG_ACX, "acx ap rate policy %d rates 0x%x", |
845 | idx, c->enabled_rates); | ||
808 | 846 | ||
809 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 847 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
810 | if (!acx) { | 848 | if (!acx) { |
@@ -898,12 +936,19 @@ out: | |||
898 | return ret; | 936 | return ret; |
899 | } | 937 | } |
900 | 938 | ||
901 | int wl1271_acx_frag_threshold(struct wl1271 *wl, u16 frag_threshold) | 939 | int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold) |
902 | { | 940 | { |
903 | struct acx_frag_threshold *acx; | 941 | struct acx_frag_threshold *acx; |
904 | int ret = 0; | 942 | int ret = 0; |
905 | 943 | ||
906 | wl1271_debug(DEBUG_ACX, "acx frag threshold"); | 944 | /* |
945 | * If the fragmentation is not configured or out of range, use the | ||
946 | * default value. | ||
947 | */ | ||
948 | if (frag_threshold > IEEE80211_MAX_FRAG_THRESHOLD) | ||
949 | frag_threshold = wl->conf.tx.frag_threshold; | ||
950 | |||
951 | wl1271_debug(DEBUG_ACX, "acx frag threshold: %d", frag_threshold); | ||
907 | 952 | ||
908 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 953 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
909 | 954 | ||
@@ -912,7 +957,7 @@ int wl1271_acx_frag_threshold(struct wl1271 *wl, u16 frag_threshold) | |||
912 | goto out; | 957 | goto out; |
913 | } | 958 | } |
914 | 959 | ||
915 | acx->frag_threshold = cpu_to_le16(frag_threshold); | 960 | acx->frag_threshold = cpu_to_le16((u16)frag_threshold); |
916 | ret = wl1271_cmd_configure(wl, ACX_FRAG_CFG, acx, sizeof(*acx)); | 961 | ret = wl1271_cmd_configure(wl, ACX_FRAG_CFG, acx, sizeof(*acx)); |
917 | if (ret < 0) { | 962 | if (ret < 0) { |
918 | wl1271_warning("Setting of frag threshold failed: %d", ret); | 963 | wl1271_warning("Setting of frag threshold failed: %d", ret); |
@@ -954,6 +999,7 @@ out: | |||
954 | int wl1271_acx_ap_mem_cfg(struct wl1271 *wl) | 999 | int wl1271_acx_ap_mem_cfg(struct wl1271 *wl) |
955 | { | 1000 | { |
956 | struct wl1271_acx_ap_config_memory *mem_conf; | 1001 | struct wl1271_acx_ap_config_memory *mem_conf; |
1002 | struct conf_memory_settings *mem; | ||
957 | int ret; | 1003 | int ret; |
958 | 1004 | ||
959 | wl1271_debug(DEBUG_ACX, "wl1271 mem cfg"); | 1005 | wl1271_debug(DEBUG_ACX, "wl1271 mem cfg"); |
@@ -964,14 +1010,21 @@ int wl1271_acx_ap_mem_cfg(struct wl1271 *wl) | |||
964 | goto out; | 1010 | goto out; |
965 | } | 1011 | } |
966 | 1012 | ||
1013 | if (wl->chip.id == CHIP_ID_1283_PG20) | ||
1014 | /* | ||
1015 | * FIXME: The 128x AP FW does not yet support dynamic memory. | ||
1016 | * Use the base memory configuration for 128x for now. This | ||
1017 | * should be fine tuned in the future. | ||
1018 | */ | ||
1019 | mem = &wl->conf.mem_wl128x; | ||
1020 | else | ||
1021 | mem = &wl->conf.mem_wl127x; | ||
1022 | |||
967 | /* memory config */ | 1023 | /* memory config */ |
968 | /* FIXME: for now we always use mem_wl127x for AP, because it | 1024 | mem_conf->num_stations = mem->num_stations; |
969 | * doesn't support dynamic memory and we don't have the | 1025 | mem_conf->rx_mem_block_num = mem->rx_block_num; |
970 | * optimal values for wl128x without dynamic memory yet */ | 1026 | mem_conf->tx_min_mem_block_num = mem->tx_min_block_num; |
971 | mem_conf->num_stations = wl->conf.mem_wl127x.num_stations; | 1027 | mem_conf->num_ssid_profiles = mem->ssid_profiles; |
972 | mem_conf->rx_mem_block_num = wl->conf.mem_wl127x.rx_block_num; | ||
973 | mem_conf->tx_min_mem_block_num = wl->conf.mem_wl127x.tx_min_block_num; | ||
974 | mem_conf->num_ssid_profiles = wl->conf.mem_wl127x.ssid_profiles; | ||
975 | mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS); | 1028 | mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS); |
976 | 1029 | ||
977 | ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf, | 1030 | ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf, |
@@ -1524,46 +1577,22 @@ out: | |||
1524 | return ret; | 1577 | return ret; |
1525 | } | 1578 | } |
1526 | 1579 | ||
1527 | int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl) | 1580 | int wl1271_acx_max_tx_retry(struct wl1271 *wl) |
1528 | { | 1581 | { |
1529 | struct wl1271_acx_ap_max_tx_retry *acx = NULL; | 1582 | struct wl1271_acx_max_tx_retry *acx = NULL; |
1530 | int ret; | 1583 | int ret; |
1531 | 1584 | ||
1532 | wl1271_debug(DEBUG_ACX, "acx ap max tx retry"); | 1585 | wl1271_debug(DEBUG_ACX, "acx max tx retry"); |
1533 | 1586 | ||
1534 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 1587 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
1535 | if (!acx) | 1588 | if (!acx) |
1536 | return -ENOMEM; | 1589 | return -ENOMEM; |
1537 | 1590 | ||
1538 | acx->max_tx_retry = cpu_to_le16(wl->conf.tx.max_tx_retries); | 1591 | acx->max_tx_retry = cpu_to_le16(wl->conf.tx.ap_max_tx_retries); |
1539 | 1592 | ||
1540 | ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx)); | 1593 | ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx)); |
1541 | if (ret < 0) { | 1594 | if (ret < 0) { |
1542 | wl1271_warning("acx ap max tx retry failed: %d", ret); | 1595 | wl1271_warning("acx max tx retry failed: %d", ret); |
1543 | goto out; | ||
1544 | } | ||
1545 | |||
1546 | out: | ||
1547 | kfree(acx); | ||
1548 | return ret; | ||
1549 | } | ||
1550 | |||
1551 | int wl1271_acx_sta_max_tx_retry(struct wl1271 *wl) | ||
1552 | { | ||
1553 | struct wl1271_acx_sta_max_tx_retry *acx = NULL; | ||
1554 | int ret; | ||
1555 | |||
1556 | wl1271_debug(DEBUG_ACX, "acx sta max tx retry"); | ||
1557 | |||
1558 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1559 | if (!acx) | ||
1560 | return -ENOMEM; | ||
1561 | |||
1562 | acx->max_tx_retry = wl->conf.tx.max_tx_retries; | ||
1563 | |||
1564 | ret = wl1271_cmd_configure(wl, ACX_CONS_TX_FAILURE, acx, sizeof(*acx)); | ||
1565 | if (ret < 0) { | ||
1566 | wl1271_warning("acx sta max tx retry failed: %d", ret); | ||
1567 | goto out; | 1596 | goto out; |
1568 | } | 1597 | } |
1569 | 1598 | ||
@@ -1626,3 +1655,68 @@ out: | |||
1626 | kfree(acx); | 1655 | kfree(acx); |
1627 | return ret; | 1656 | return ret; |
1628 | } | 1657 | } |
1658 | |||
1659 | int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable) | ||
1660 | { | ||
1661 | struct acx_ap_beacon_filter *acx = NULL; | ||
1662 | int ret; | ||
1663 | |||
1664 | wl1271_debug(DEBUG_ACX, "acx set ap beacon filter: %d", enable); | ||
1665 | |||
1666 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1667 | if (!acx) | ||
1668 | return -ENOMEM; | ||
1669 | |||
1670 | acx->enable = enable ? 1 : 0; | ||
1671 | |||
1672 | ret = wl1271_cmd_configure(wl, ACX_AP_BEACON_FILTER_OPT, | ||
1673 | acx, sizeof(*acx)); | ||
1674 | if (ret < 0) { | ||
1675 | wl1271_warning("acx set ap beacon filter failed: %d", ret); | ||
1676 | goto out; | ||
1677 | } | ||
1678 | |||
1679 | out: | ||
1680 | kfree(acx); | ||
1681 | return ret; | ||
1682 | } | ||
1683 | |||
1684 | int wl1271_acx_fm_coex(struct wl1271 *wl) | ||
1685 | { | ||
1686 | struct wl1271_acx_fm_coex *acx; | ||
1687 | int ret; | ||
1688 | |||
1689 | wl1271_debug(DEBUG_ACX, "acx fm coex setting"); | ||
1690 | |||
1691 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1692 | if (!acx) { | ||
1693 | ret = -ENOMEM; | ||
1694 | goto out; | ||
1695 | } | ||
1696 | |||
1697 | acx->enable = wl->conf.fm_coex.enable; | ||
1698 | acx->swallow_period = wl->conf.fm_coex.swallow_period; | ||
1699 | acx->n_divider_fref_set_1 = wl->conf.fm_coex.n_divider_fref_set_1; | ||
1700 | acx->n_divider_fref_set_2 = wl->conf.fm_coex.n_divider_fref_set_2; | ||
1701 | acx->m_divider_fref_set_1 = | ||
1702 | cpu_to_le16(wl->conf.fm_coex.m_divider_fref_set_1); | ||
1703 | acx->m_divider_fref_set_2 = | ||
1704 | cpu_to_le16(wl->conf.fm_coex.m_divider_fref_set_2); | ||
1705 | acx->coex_pll_stabilization_time = | ||
1706 | cpu_to_le32(wl->conf.fm_coex.coex_pll_stabilization_time); | ||
1707 | acx->ldo_stabilization_time = | ||
1708 | cpu_to_le16(wl->conf.fm_coex.ldo_stabilization_time); | ||
1709 | acx->fm_disturbed_band_margin = | ||
1710 | wl->conf.fm_coex.fm_disturbed_band_margin; | ||
1711 | acx->swallow_clk_diff = wl->conf.fm_coex.swallow_clk_diff; | ||
1712 | |||
1713 | ret = wl1271_cmd_configure(wl, ACX_FM_COEX_CFG, acx, sizeof(*acx)); | ||
1714 | if (ret < 0) { | ||
1715 | wl1271_warning("acx fm coex setting failed: %d", ret); | ||
1716 | goto out; | ||
1717 | } | ||
1718 | |||
1719 | out: | ||
1720 | kfree(acx); | ||
1721 | return ret; | ||
1722 | } | ||
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 942908cd53a..9a895e3cc61 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h | |||
@@ -303,7 +303,6 @@ struct acx_beacon_filter_option { | |||
303 | struct acx_header header; | 303 | struct acx_header header; |
304 | 304 | ||
305 | u8 enable; | 305 | u8 enable; |
306 | |||
307 | /* | 306 | /* |
308 | * The number of beacons without the unicast TIM | 307 | * The number of beacons without the unicast TIM |
309 | * bit set that the firmware buffers before | 308 | * bit set that the firmware buffers before |
@@ -370,14 +369,23 @@ struct acx_bt_wlan_coex { | |||
370 | u8 pad[3]; | 369 | u8 pad[3]; |
371 | } __packed; | 370 | } __packed; |
372 | 371 | ||
373 | struct acx_bt_wlan_coex_param { | 372 | struct acx_sta_bt_wlan_coex_param { |
374 | struct acx_header header; | 373 | struct acx_header header; |
375 | 374 | ||
376 | __le32 params[CONF_SG_PARAMS_MAX]; | 375 | __le32 params[CONF_SG_STA_PARAMS_MAX]; |
377 | u8 param_idx; | 376 | u8 param_idx; |
378 | u8 padding[3]; | 377 | u8 padding[3]; |
379 | } __packed; | 378 | } __packed; |
380 | 379 | ||
380 | struct acx_ap_bt_wlan_coex_param { | ||
381 | struct acx_header header; | ||
382 | |||
383 | __le32 params[CONF_SG_AP_PARAMS_MAX]; | ||
384 | u8 param_idx; | ||
385 | u8 padding[3]; | ||
386 | } __packed; | ||
387 | |||
388 | |||
381 | struct acx_dco_itrim_params { | 389 | struct acx_dco_itrim_params { |
382 | struct acx_header header; | 390 | struct acx_header header; |
383 | 391 | ||
@@ -1145,7 +1153,7 @@ struct wl1271_acx_fw_tsf_information { | |||
1145 | u8 padding[3]; | 1153 | u8 padding[3]; |
1146 | } __packed; | 1154 | } __packed; |
1147 | 1155 | ||
1148 | struct wl1271_acx_ap_max_tx_retry { | 1156 | struct wl1271_acx_max_tx_retry { |
1149 | struct acx_header header; | 1157 | struct acx_header header; |
1150 | 1158 | ||
1151 | /* | 1159 | /* |
@@ -1156,13 +1164,6 @@ struct wl1271_acx_ap_max_tx_retry { | |||
1156 | u8 padding_1[2]; | 1164 | u8 padding_1[2]; |
1157 | } __packed; | 1165 | } __packed; |
1158 | 1166 | ||
1159 | struct wl1271_acx_sta_max_tx_retry { | ||
1160 | struct acx_header header; | ||
1161 | |||
1162 | u8 max_tx_retry; | ||
1163 | u8 padding_1[3]; | ||
1164 | } __packed; | ||
1165 | |||
1166 | struct wl1271_acx_config_ps { | 1167 | struct wl1271_acx_config_ps { |
1167 | struct acx_header header; | 1168 | struct acx_header header; |
1168 | 1169 | ||
@@ -1179,6 +1180,72 @@ struct wl1271_acx_inconnection_sta { | |||
1179 | u8 padding1[2]; | 1180 | u8 padding1[2]; |
1180 | } __packed; | 1181 | } __packed; |
1181 | 1182 | ||
1183 | struct acx_ap_beacon_filter { | ||
1184 | struct acx_header header; | ||
1185 | |||
1186 | u8 enable; | ||
1187 | u8 pad[3]; | ||
1188 | } __packed; | ||
1189 | |||
1190 | /* | ||
1191 | * ACX_FM_COEX_CFG | ||
1192 | * set the FM co-existence parameters. | ||
1193 | */ | ||
1194 | struct wl1271_acx_fm_coex { | ||
1195 | struct acx_header header; | ||
1196 | /* enable(1) / disable(0) the FM Coex feature */ | ||
1197 | u8 enable; | ||
1198 | /* | ||
1199 | * Swallow period used in COEX PLL swallowing mechanism. | ||
1200 | * 0xFF = use FW default | ||
1201 | */ | ||
1202 | u8 swallow_period; | ||
1203 | /* | ||
1204 | * The N divider used in COEX PLL swallowing mechanism for Fref of | ||
1205 | * 38.4/19.2 Mhz. 0xFF = use FW default | ||
1206 | */ | ||
1207 | u8 n_divider_fref_set_1; | ||
1208 | /* | ||
1209 | * The N divider used in COEX PLL swallowing mechanism for Fref of | ||
1210 | * 26/52 Mhz. 0xFF = use FW default | ||
1211 | */ | ||
1212 | u8 n_divider_fref_set_2; | ||
1213 | /* | ||
1214 | * The M divider used in COEX PLL swallowing mechanism for Fref of | ||
1215 | * 38.4/19.2 Mhz. 0xFFFF = use FW default | ||
1216 | */ | ||
1217 | __le16 m_divider_fref_set_1; | ||
1218 | /* | ||
1219 | * The M divider used in COEX PLL swallowing mechanism for Fref of | ||
1220 | * 26/52 Mhz. 0xFFFF = use FW default | ||
1221 | */ | ||
1222 | __le16 m_divider_fref_set_2; | ||
1223 | /* | ||
1224 | * The time duration in uSec required for COEX PLL to stabilize. | ||
1225 | * 0xFFFFFFFF = use FW default | ||
1226 | */ | ||
1227 | __le32 coex_pll_stabilization_time; | ||
1228 | /* | ||
1229 | * The time duration in uSec required for LDO to stabilize. | ||
1230 | * 0xFFFFFFFF = use FW default | ||
1231 | */ | ||
1232 | __le16 ldo_stabilization_time; | ||
1233 | /* | ||
1234 | * The disturbed frequency band margin around the disturbed frequency | ||
1235 | * center (single sided). | ||
1236 | * For example, if 2 is configured, the following channels will be | ||
1237 | * considered disturbed channel: | ||
1238 | * 80 +- 0.1 MHz, 91 +- 0.1 MHz, 98 +- 0.1 MHz, 102 +- 0.1 MH | ||
1239 | * 0xFF = use FW default | ||
1240 | */ | ||
1241 | u8 fm_disturbed_band_margin; | ||
1242 | /* | ||
1243 | * The swallow clock difference of the swallowing mechanism. | ||
1244 | * 0xFF = use FW default | ||
1245 | */ | ||
1246 | u8 swallow_clk_diff; | ||
1247 | } __packed; | ||
1248 | |||
1182 | enum { | 1249 | enum { |
1183 | ACX_WAKE_UP_CONDITIONS = 0x0002, | 1250 | ACX_WAKE_UP_CONDITIONS = 0x0002, |
1184 | ACX_MEM_CFG = 0x0003, | 1251 | ACX_MEM_CFG = 0x0003, |
@@ -1197,6 +1264,7 @@ enum { | |||
1197 | ACX_TID_CFG = 0x001A, | 1264 | ACX_TID_CFG = 0x001A, |
1198 | ACX_PS_RX_STREAMING = 0x001B, | 1265 | ACX_PS_RX_STREAMING = 0x001B, |
1199 | ACX_BEACON_FILTER_OPT = 0x001F, | 1266 | ACX_BEACON_FILTER_OPT = 0x001F, |
1267 | ACX_AP_BEACON_FILTER_OPT = 0x0020, | ||
1200 | ACX_NOISE_HIST = 0x0021, | 1268 | ACX_NOISE_HIST = 0x0021, |
1201 | ACX_HDK_VERSION = 0x0022, /* ??? */ | 1269 | ACX_HDK_VERSION = 0x0022, /* ??? */ |
1202 | ACX_PD_THRESHOLD = 0x0023, | 1270 | ACX_PD_THRESHOLD = 0x0023, |
@@ -1208,6 +1276,7 @@ enum { | |||
1208 | ACX_BCN_DTIM_OPTIONS = 0x0031, | 1276 | ACX_BCN_DTIM_OPTIONS = 0x0031, |
1209 | ACX_SG_ENABLE = 0x0032, | 1277 | ACX_SG_ENABLE = 0x0032, |
1210 | ACX_SG_CFG = 0x0033, | 1278 | ACX_SG_CFG = 0x0033, |
1279 | ACX_FM_COEX_CFG = 0x0034, | ||
1211 | ACX_BEACON_FILTER_TABLE = 0x0038, | 1280 | ACX_BEACON_FILTER_TABLE = 0x0038, |
1212 | ACX_ARP_IP_FILTER = 0x0039, | 1281 | ACX_ARP_IP_FILTER = 0x0039, |
1213 | ACX_ROAMING_STATISTICS_TBL = 0x003B, | 1282 | ACX_ROAMING_STATISTICS_TBL = 0x003B, |
@@ -1264,13 +1333,14 @@ int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time); | |||
1264 | int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, | 1333 | int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, |
1265 | void *mc_list, u32 mc_list_len); | 1334 | void *mc_list, u32 mc_list_len); |
1266 | int wl1271_acx_service_period_timeout(struct wl1271 *wl); | 1335 | int wl1271_acx_service_period_timeout(struct wl1271 *wl); |
1267 | int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold); | 1336 | int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold); |
1268 | int wl1271_acx_dco_itrim_params(struct wl1271 *wl); | 1337 | int wl1271_acx_dco_itrim_params(struct wl1271 *wl); |
1269 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); | 1338 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); |
1270 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); | 1339 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); |
1271 | int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable); | 1340 | int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable); |
1272 | int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable); | 1341 | int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable); |
1273 | int wl1271_acx_sg_cfg(struct wl1271 *wl); | 1342 | int wl1271_acx_sta_sg_cfg(struct wl1271 *wl); |
1343 | int wl1271_acx_ap_sg_cfg(struct wl1271 *wl); | ||
1274 | int wl1271_acx_cca_threshold(struct wl1271 *wl); | 1344 | int wl1271_acx_cca_threshold(struct wl1271 *wl); |
1275 | int wl1271_acx_bcn_dtim_options(struct wl1271 *wl); | 1345 | int wl1271_acx_bcn_dtim_options(struct wl1271 *wl); |
1276 | int wl1271_acx_aid(struct wl1271 *wl, u16 aid); | 1346 | int wl1271_acx_aid(struct wl1271 *wl, u16 aid); |
@@ -1287,7 +1357,7 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, | |||
1287 | int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, | 1357 | int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, |
1288 | u8 tsid, u8 ps_scheme, u8 ack_policy, | 1358 | u8 tsid, u8 ps_scheme, u8 ack_policy, |
1289 | u32 apsd_conf0, u32 apsd_conf1); | 1359 | u32 apsd_conf0, u32 apsd_conf1); |
1290 | int wl1271_acx_frag_threshold(struct wl1271 *wl, u16 frag_threshold); | 1360 | int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold); |
1291 | int wl1271_acx_tx_config_options(struct wl1271 *wl); | 1361 | int wl1271_acx_tx_config_options(struct wl1271 *wl); |
1292 | int wl1271_acx_ap_mem_cfg(struct wl1271 *wl); | 1362 | int wl1271_acx_ap_mem_cfg(struct wl1271 *wl); |
1293 | int wl1271_acx_sta_mem_cfg(struct wl1271 *wl); | 1363 | int wl1271_acx_sta_mem_cfg(struct wl1271 *wl); |
@@ -1314,9 +1384,10 @@ int wl1271_acx_set_ba_session(struct wl1271 *wl, | |||
1314 | int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn, | 1384 | int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn, |
1315 | bool enable); | 1385 | bool enable); |
1316 | int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); | 1386 | int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); |
1317 | int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl); | 1387 | int wl1271_acx_max_tx_retry(struct wl1271 *wl); |
1318 | int wl1271_acx_sta_max_tx_retry(struct wl1271 *wl); | ||
1319 | int wl1271_acx_config_ps(struct wl1271 *wl); | 1388 | int wl1271_acx_config_ps(struct wl1271 *wl); |
1320 | int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); | 1389 | int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); |
1390 | int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable); | ||
1391 | int wl1271_acx_fm_coex(struct wl1271 *wl); | ||
1321 | 1392 | ||
1322 | #endif /* __WL1271_ACX_H__ */ | 1393 | #endif /* __WL1271_ACX_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index d263ebb6f97..2b0cf85788b 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c | |||
@@ -478,12 +478,10 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
478 | DISCONNECT_EVENT_COMPLETE_ID | | 478 | DISCONNECT_EVENT_COMPLETE_ID | |
479 | RSSI_SNR_TRIGGER_0_EVENT_ID | | 479 | RSSI_SNR_TRIGGER_0_EVENT_ID | |
480 | PSPOLL_DELIVERY_FAILURE_EVENT_ID | | 480 | PSPOLL_DELIVERY_FAILURE_EVENT_ID | |
481 | SOFT_GEMINI_SENSE_EVENT_ID | | 481 | SOFT_GEMINI_SENSE_EVENT_ID; |
482 | MAX_TX_RETRY_EVENT_ID; | ||
483 | 482 | ||
484 | if (wl->bss_type == BSS_TYPE_AP_BSS) | 483 | if (wl->bss_type == BSS_TYPE_AP_BSS) |
485 | wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID | | 484 | wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID; |
486 | INACTIVE_STA_EVENT_ID; | ||
487 | else | 485 | else |
488 | wl->event_mask |= DUMMY_PACKET_EVENT_ID; | 486 | wl->event_mask |= DUMMY_PACKET_EVENT_ID; |
489 | 487 | ||
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index d48331682e7..2116a376c3f 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c | |||
@@ -76,7 +76,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
76 | if (time_after(jiffies, timeout)) { | 76 | if (time_after(jiffies, timeout)) { |
77 | wl1271_error("command complete timeout"); | 77 | wl1271_error("command complete timeout"); |
78 | ret = -ETIMEDOUT; | 78 | ret = -ETIMEDOUT; |
79 | goto out; | 79 | goto fail; |
80 | } | 80 | } |
81 | 81 | ||
82 | poll_count++; | 82 | poll_count++; |
@@ -96,14 +96,17 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
96 | status = le16_to_cpu(cmd->status); | 96 | status = le16_to_cpu(cmd->status); |
97 | if (status != CMD_STATUS_SUCCESS) { | 97 | if (status != CMD_STATUS_SUCCESS) { |
98 | wl1271_error("command execute failure %d", status); | 98 | wl1271_error("command execute failure %d", status); |
99 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | ||
100 | ret = -EIO; | 99 | ret = -EIO; |
100 | goto fail; | ||
101 | } | 101 | } |
102 | 102 | ||
103 | wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, | 103 | wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, |
104 | WL1271_ACX_INTR_CMD_COMPLETE); | 104 | WL1271_ACX_INTR_CMD_COMPLETE); |
105 | return 0; | ||
105 | 106 | ||
106 | out: | 107 | fail: |
108 | WARN_ON(1); | ||
109 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | ||
107 | return ret; | 110 | return ret; |
108 | } | 111 | } |
109 | 112 | ||
@@ -129,6 +132,9 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) | |||
129 | if (gp->tx_bip_fem_auto_detect) | 132 | if (gp->tx_bip_fem_auto_detect) |
130 | answer = true; | 133 | answer = true; |
131 | 134 | ||
135 | /* Override the REF CLK from the NVS with the one from platform data */ | ||
136 | gen_parms->general_params.ref_clock = wl->ref_clock; | ||
137 | |||
132 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); | 138 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); |
133 | if (ret < 0) { | 139 | if (ret < 0) { |
134 | wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); | 140 | wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); |
@@ -168,6 +174,10 @@ int wl128x_cmd_general_parms(struct wl1271 *wl) | |||
168 | if (gp->tx_bip_fem_auto_detect) | 174 | if (gp->tx_bip_fem_auto_detect) |
169 | answer = true; | 175 | answer = true; |
170 | 176 | ||
177 | /* Replace REF and TCXO CLKs with the ones from platform data */ | ||
178 | gen_parms->general_params.ref_clock = wl->ref_clock; | ||
179 | gen_parms->general_params.tcxo_ref_clock = wl->tcxo_clock; | ||
180 | |||
171 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); | 181 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); |
172 | if (ret < 0) { | 182 | if (ret < 0) { |
173 | wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); | 183 | wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); |
@@ -1070,7 +1080,7 @@ int wl1271_cmd_start_bss(struct wl1271 *wl) | |||
1070 | 1080 | ||
1071 | memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN); | 1081 | memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN); |
1072 | 1082 | ||
1073 | cmd->aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); | 1083 | cmd->aging_period = cpu_to_le16(WL1271_AP_DEF_INACTIV_SEC); |
1074 | cmd->bss_index = WL1271_AP_BSS_INDEX; | 1084 | cmd->bss_index = WL1271_AP_BSS_INDEX; |
1075 | cmd->global_hlid = WL1271_AP_GLOBAL_HLID; | 1085 | cmd->global_hlid = WL1271_AP_GLOBAL_HLID; |
1076 | cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID; | 1086 | cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID; |
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index d16094f2604..1f947368f9e 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h | |||
@@ -396,12 +396,43 @@ enum { | |||
396 | CONF_SG_TEMP_PARAM_3, | 396 | CONF_SG_TEMP_PARAM_3, |
397 | CONF_SG_TEMP_PARAM_4, | 397 | CONF_SG_TEMP_PARAM_4, |
398 | CONF_SG_TEMP_PARAM_5, | 398 | CONF_SG_TEMP_PARAM_5, |
399 | CONF_SG_PARAMS_MAX, | 399 | |
400 | /* | ||
401 | * AP beacon miss | ||
402 | * | ||
403 | * Range: 0 - 255 | ||
404 | */ | ||
405 | CONF_SG_AP_BEACON_MISS_TX, | ||
406 | |||
407 | /* | ||
408 | * AP RX window length | ||
409 | * | ||
410 | * Range: 0 - 50 | ||
411 | */ | ||
412 | CONF_SG_RX_WINDOW_LENGTH, | ||
413 | |||
414 | /* | ||
415 | * AP connection protection time | ||
416 | * | ||
417 | * Range: 0 - 5000 | ||
418 | */ | ||
419 | CONF_SG_AP_CONNECTION_PROTECTION_TIME, | ||
420 | |||
421 | CONF_SG_TEMP_PARAM_6, | ||
422 | CONF_SG_TEMP_PARAM_7, | ||
423 | CONF_SG_TEMP_PARAM_8, | ||
424 | CONF_SG_TEMP_PARAM_9, | ||
425 | CONF_SG_TEMP_PARAM_10, | ||
426 | |||
427 | CONF_SG_STA_PARAMS_MAX = CONF_SG_TEMP_PARAM_5 + 1, | ||
428 | CONF_SG_AP_PARAMS_MAX = CONF_SG_TEMP_PARAM_10 + 1, | ||
429 | |||
400 | CONF_SG_PARAMS_ALL = 0xff | 430 | CONF_SG_PARAMS_ALL = 0xff |
401 | }; | 431 | }; |
402 | 432 | ||
403 | struct conf_sg_settings { | 433 | struct conf_sg_settings { |
404 | u32 params[CONF_SG_PARAMS_MAX]; | 434 | u32 sta_params[CONF_SG_STA_PARAMS_MAX]; |
435 | u32 ap_params[CONF_SG_AP_PARAMS_MAX]; | ||
405 | u8 state; | 436 | u8 state; |
406 | }; | 437 | }; |
407 | 438 | ||
@@ -509,6 +540,12 @@ struct conf_rx_settings { | |||
509 | CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \ | 540 | CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \ |
510 | CONF_HW_BIT_RATE_54MBPS) | 541 | CONF_HW_BIT_RATE_54MBPS) |
511 | 542 | ||
543 | #define CONF_TX_OFDM_RATES (CONF_HW_BIT_RATE_6MBPS | \ | ||
544 | CONF_HW_BIT_RATE_12MBPS | CONF_HW_BIT_RATE_24MBPS | \ | ||
545 | CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \ | ||
546 | CONF_HW_BIT_RATE_54MBPS) | ||
547 | |||
548 | |||
512 | /* | 549 | /* |
513 | * Default rates for management traffic when operating in AP mode. This | 550 | * Default rates for management traffic when operating in AP mode. This |
514 | * should be configured according to the basic rate set of the AP | 551 | * should be configured according to the basic rate set of the AP |
@@ -516,6 +553,13 @@ struct conf_rx_settings { | |||
516 | #define CONF_TX_AP_DEFAULT_MGMT_RATES (CONF_HW_BIT_RATE_1MBPS | \ | 553 | #define CONF_TX_AP_DEFAULT_MGMT_RATES (CONF_HW_BIT_RATE_1MBPS | \ |
517 | CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS) | 554 | CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS) |
518 | 555 | ||
556 | /* | ||
557 | * Default rates for working as IBSS. use 11b rates | ||
558 | */ | ||
559 | #define CONF_TX_IBSS_DEFAULT_RATES (CONF_HW_BIT_RATE_1MBPS | \ | ||
560 | CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | \ | ||
561 | CONF_HW_BIT_RATE_11MBPS); | ||
562 | |||
519 | struct conf_tx_rate_class { | 563 | struct conf_tx_rate_class { |
520 | 564 | ||
521 | /* | 565 | /* |
@@ -667,34 +711,10 @@ struct conf_tx_settings { | |||
667 | struct conf_tx_ac_category ac_conf[CONF_TX_MAX_AC_COUNT]; | 711 | struct conf_tx_ac_category ac_conf[CONF_TX_MAX_AC_COUNT]; |
668 | 712 | ||
669 | /* | 713 | /* |
670 | * Configuration for rate classes in AP-mode. These rate classes | 714 | * AP-mode - allow this number of TX retries to a station before an |
671 | * are for the AC TX queues | ||
672 | */ | ||
673 | struct conf_tx_rate_class ap_rc_conf[CONF_TX_MAX_AC_COUNT]; | ||
674 | |||
675 | /* | ||
676 | * Management TX rate class for AP-mode. | ||
677 | */ | ||
678 | struct conf_tx_rate_class ap_mgmt_conf; | ||
679 | |||
680 | /* | ||
681 | * Broadcast TX rate class for AP-mode. | ||
682 | */ | ||
683 | struct conf_tx_rate_class ap_bcst_conf; | ||
684 | |||
685 | /* | ||
686 | * Allow this number of TX retries to a connected station/AP before an | ||
687 | * event is triggered from FW. | 715 | * event is triggered from FW. |
688 | * In AP-mode the hlids of unreachable stations are given in the | ||
689 | * "sta_tx_retry_exceeded" member in the event mailbox. | ||
690 | */ | 716 | */ |
691 | u8 max_tx_retries; | 717 | u16 ap_max_tx_retries; |
692 | |||
693 | /* | ||
694 | * AP-mode - after this number of seconds a connected station is | ||
695 | * considered inactive. | ||
696 | */ | ||
697 | u16 ap_aging_period; | ||
698 | 718 | ||
699 | /* | 719 | /* |
700 | * Configuration for TID parameters. | 720 | * Configuration for TID parameters. |
@@ -1192,6 +1212,19 @@ struct conf_memory_settings { | |||
1192 | u8 tx_min; | 1212 | u8 tx_min; |
1193 | }; | 1213 | }; |
1194 | 1214 | ||
1215 | struct conf_fm_coex { | ||
1216 | u8 enable; | ||
1217 | u8 swallow_period; | ||
1218 | u8 n_divider_fref_set_1; | ||
1219 | u8 n_divider_fref_set_2; | ||
1220 | u16 m_divider_fref_set_1; | ||
1221 | u16 m_divider_fref_set_2; | ||
1222 | u32 coex_pll_stabilization_time; | ||
1223 | u16 ldo_stabilization_time; | ||
1224 | u8 fm_disturbed_band_margin; | ||
1225 | u8 swallow_clk_diff; | ||
1226 | }; | ||
1227 | |||
1195 | struct conf_drv_settings { | 1228 | struct conf_drv_settings { |
1196 | struct conf_sg_settings sg; | 1229 | struct conf_sg_settings sg; |
1197 | struct conf_rx_settings rx; | 1230 | struct conf_rx_settings rx; |
@@ -1205,6 +1238,7 @@ struct conf_drv_settings { | |||
1205 | struct conf_ht_setting ht; | 1238 | struct conf_ht_setting ht; |
1206 | struct conf_memory_settings mem_wl127x; | 1239 | struct conf_memory_settings mem_wl127x; |
1207 | struct conf_memory_settings mem_wl128x; | 1240 | struct conf_memory_settings mem_wl128x; |
1241 | struct conf_fm_coex fm_coex; | ||
1208 | u8 hci_io_ds; | 1242 | u8 hci_io_ds; |
1209 | }; | 1243 | }; |
1210 | 1244 | ||
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 70ab1986788..b2f692babed 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c | |||
@@ -291,6 +291,241 @@ static const struct file_operations gpio_power_ops = { | |||
291 | .llseek = default_llseek, | 291 | .llseek = default_llseek, |
292 | }; | 292 | }; |
293 | 293 | ||
294 | static ssize_t start_recovery_write(struct file *file, | ||
295 | const char __user *user_buf, | ||
296 | size_t count, loff_t *ppos) | ||
297 | { | ||
298 | struct wl1271 *wl = file->private_data; | ||
299 | |||
300 | mutex_lock(&wl->mutex); | ||
301 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | ||
302 | mutex_unlock(&wl->mutex); | ||
303 | |||
304 | return count; | ||
305 | } | ||
306 | |||
307 | static const struct file_operations start_recovery_ops = { | ||
308 | .write = start_recovery_write, | ||
309 | .open = wl1271_open_file_generic, | ||
310 | .llseek = default_llseek, | ||
311 | }; | ||
312 | |||
313 | static ssize_t driver_state_read(struct file *file, char __user *user_buf, | ||
314 | size_t count, loff_t *ppos) | ||
315 | { | ||
316 | struct wl1271 *wl = file->private_data; | ||
317 | int res = 0; | ||
318 | char buf[1024]; | ||
319 | |||
320 | mutex_lock(&wl->mutex); | ||
321 | |||
322 | #define DRIVER_STATE_PRINT(x, fmt) \ | ||
323 | (res += scnprintf(buf + res, sizeof(buf) - res,\ | ||
324 | #x " = " fmt "\n", wl->x)) | ||
325 | |||
326 | #define DRIVER_STATE_PRINT_LONG(x) DRIVER_STATE_PRINT(x, "%ld") | ||
327 | #define DRIVER_STATE_PRINT_INT(x) DRIVER_STATE_PRINT(x, "%d") | ||
328 | #define DRIVER_STATE_PRINT_STR(x) DRIVER_STATE_PRINT(x, "%s") | ||
329 | #define DRIVER_STATE_PRINT_LHEX(x) DRIVER_STATE_PRINT(x, "0x%lx") | ||
330 | #define DRIVER_STATE_PRINT_HEX(x) DRIVER_STATE_PRINT(x, "0x%x") | ||
331 | |||
332 | DRIVER_STATE_PRINT_INT(tx_blocks_available); | ||
333 | DRIVER_STATE_PRINT_INT(tx_allocated_blocks); | ||
334 | DRIVER_STATE_PRINT_INT(tx_frames_cnt); | ||
335 | DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]); | ||
336 | DRIVER_STATE_PRINT_INT(tx_queue_count); | ||
337 | DRIVER_STATE_PRINT_INT(tx_packets_count); | ||
338 | DRIVER_STATE_PRINT_INT(tx_results_count); | ||
339 | DRIVER_STATE_PRINT_LHEX(flags); | ||
340 | DRIVER_STATE_PRINT_INT(tx_blocks_freed[0]); | ||
341 | DRIVER_STATE_PRINT_INT(tx_blocks_freed[1]); | ||
342 | DRIVER_STATE_PRINT_INT(tx_blocks_freed[2]); | ||
343 | DRIVER_STATE_PRINT_INT(tx_blocks_freed[3]); | ||
344 | DRIVER_STATE_PRINT_INT(tx_security_last_seq); | ||
345 | DRIVER_STATE_PRINT_INT(rx_counter); | ||
346 | DRIVER_STATE_PRINT_INT(session_counter); | ||
347 | DRIVER_STATE_PRINT_INT(state); | ||
348 | DRIVER_STATE_PRINT_INT(bss_type); | ||
349 | DRIVER_STATE_PRINT_INT(channel); | ||
350 | DRIVER_STATE_PRINT_HEX(rate_set); | ||
351 | DRIVER_STATE_PRINT_HEX(basic_rate_set); | ||
352 | DRIVER_STATE_PRINT_HEX(basic_rate); | ||
353 | DRIVER_STATE_PRINT_INT(band); | ||
354 | DRIVER_STATE_PRINT_INT(beacon_int); | ||
355 | DRIVER_STATE_PRINT_INT(psm_entry_retry); | ||
356 | DRIVER_STATE_PRINT_INT(ps_poll_failures); | ||
357 | DRIVER_STATE_PRINT_HEX(filters); | ||
358 | DRIVER_STATE_PRINT_HEX(rx_config); | ||
359 | DRIVER_STATE_PRINT_HEX(rx_filter); | ||
360 | DRIVER_STATE_PRINT_INT(power_level); | ||
361 | DRIVER_STATE_PRINT_INT(rssi_thold); | ||
362 | DRIVER_STATE_PRINT_INT(last_rssi_event); | ||
363 | DRIVER_STATE_PRINT_INT(sg_enabled); | ||
364 | DRIVER_STATE_PRINT_INT(enable_11a); | ||
365 | DRIVER_STATE_PRINT_INT(noise); | ||
366 | DRIVER_STATE_PRINT_LHEX(ap_hlid_map[0]); | ||
367 | DRIVER_STATE_PRINT_INT(last_tx_hlid); | ||
368 | DRIVER_STATE_PRINT_INT(ba_support); | ||
369 | DRIVER_STATE_PRINT_HEX(ba_rx_bitmap); | ||
370 | DRIVER_STATE_PRINT_HEX(ap_fw_ps_map); | ||
371 | DRIVER_STATE_PRINT_LHEX(ap_ps_map); | ||
372 | DRIVER_STATE_PRINT_HEX(quirks); | ||
373 | DRIVER_STATE_PRINT_HEX(irq); | ||
374 | DRIVER_STATE_PRINT_HEX(ref_clock); | ||
375 | DRIVER_STATE_PRINT_HEX(tcxo_clock); | ||
376 | DRIVER_STATE_PRINT_HEX(hw_pg_ver); | ||
377 | DRIVER_STATE_PRINT_HEX(platform_quirks); | ||
378 | DRIVER_STATE_PRINT_HEX(chip.id); | ||
379 | DRIVER_STATE_PRINT_STR(chip.fw_ver_str); | ||
380 | |||
381 | #undef DRIVER_STATE_PRINT_INT | ||
382 | #undef DRIVER_STATE_PRINT_LONG | ||
383 | #undef DRIVER_STATE_PRINT_HEX | ||
384 | #undef DRIVER_STATE_PRINT_LHEX | ||
385 | #undef DRIVER_STATE_PRINT_STR | ||
386 | #undef DRIVER_STATE_PRINT | ||
387 | |||
388 | mutex_unlock(&wl->mutex); | ||
389 | |||
390 | return simple_read_from_buffer(user_buf, count, ppos, buf, res); | ||
391 | } | ||
392 | |||
393 | static const struct file_operations driver_state_ops = { | ||
394 | .read = driver_state_read, | ||
395 | .open = wl1271_open_file_generic, | ||
396 | .llseek = default_llseek, | ||
397 | }; | ||
398 | |||
399 | static ssize_t dtim_interval_read(struct file *file, char __user *user_buf, | ||
400 | size_t count, loff_t *ppos) | ||
401 | { | ||
402 | struct wl1271 *wl = file->private_data; | ||
403 | u8 value; | ||
404 | |||
405 | if (wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_DTIM || | ||
406 | wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_N_DTIM) | ||
407 | value = wl->conf.conn.listen_interval; | ||
408 | else | ||
409 | value = 0; | ||
410 | |||
411 | return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value); | ||
412 | } | ||
413 | |||
414 | static ssize_t dtim_interval_write(struct file *file, | ||
415 | const char __user *user_buf, | ||
416 | size_t count, loff_t *ppos) | ||
417 | { | ||
418 | struct wl1271 *wl = file->private_data; | ||
419 | char buf[10]; | ||
420 | size_t len; | ||
421 | unsigned long value; | ||
422 | int ret; | ||
423 | |||
424 | len = min(count, sizeof(buf) - 1); | ||
425 | if (copy_from_user(buf, user_buf, len)) | ||
426 | return -EFAULT; | ||
427 | buf[len] = '\0'; | ||
428 | |||
429 | ret = kstrtoul(buf, 0, &value); | ||
430 | if (ret < 0) { | ||
431 | wl1271_warning("illegal value for dtim_interval"); | ||
432 | return -EINVAL; | ||
433 | } | ||
434 | |||
435 | if (value < 1 || value > 10) { | ||
436 | wl1271_warning("dtim value is not in valid range"); | ||
437 | return -ERANGE; | ||
438 | } | ||
439 | |||
440 | mutex_lock(&wl->mutex); | ||
441 | |||
442 | wl->conf.conn.listen_interval = value; | ||
443 | /* for some reason there are different event types for 1 and >1 */ | ||
444 | if (value == 1) | ||
445 | wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_DTIM; | ||
446 | else | ||
447 | wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM; | ||
448 | |||
449 | /* | ||
450 | * we don't reconfigure ACX_WAKE_UP_CONDITIONS now, so it will only | ||
451 | * take effect on the next time we enter psm. | ||
452 | */ | ||
453 | mutex_unlock(&wl->mutex); | ||
454 | return count; | ||
455 | } | ||
456 | |||
457 | static const struct file_operations dtim_interval_ops = { | ||
458 | .read = dtim_interval_read, | ||
459 | .write = dtim_interval_write, | ||
460 | .open = wl1271_open_file_generic, | ||
461 | .llseek = default_llseek, | ||
462 | }; | ||
463 | |||
464 | static ssize_t beacon_interval_read(struct file *file, char __user *user_buf, | ||
465 | size_t count, loff_t *ppos) | ||
466 | { | ||
467 | struct wl1271 *wl = file->private_data; | ||
468 | u8 value; | ||
469 | |||
470 | if (wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_BEACON || | ||
471 | wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_N_BEACONS) | ||
472 | value = wl->conf.conn.listen_interval; | ||
473 | else | ||
474 | value = 0; | ||
475 | |||
476 | return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value); | ||
477 | } | ||
478 | |||
479 | static ssize_t beacon_interval_write(struct file *file, | ||
480 | const char __user *user_buf, | ||
481 | size_t count, loff_t *ppos) | ||
482 | { | ||
483 | struct wl1271 *wl = file->private_data; | ||
484 | char buf[10]; | ||
485 | size_t len; | ||
486 | unsigned long value; | ||
487 | int ret; | ||
488 | |||
489 | len = min(count, sizeof(buf) - 1); | ||
490 | if (copy_from_user(buf, user_buf, len)) | ||
491 | return -EFAULT; | ||
492 | buf[len] = '\0'; | ||
493 | |||
494 | ret = kstrtoul(buf, 0, &value); | ||
495 | if (ret < 0) { | ||
496 | wl1271_warning("illegal value for beacon_interval"); | ||
497 | return -EINVAL; | ||
498 | } | ||
499 | |||
500 | if (value < 1 || value > 255) { | ||
501 | wl1271_warning("beacon interval value is not in valid range"); | ||
502 | return -ERANGE; | ||
503 | } | ||
504 | |||
505 | mutex_lock(&wl->mutex); | ||
506 | |||
507 | wl->conf.conn.listen_interval = value; | ||
508 | /* for some reason there are different event types for 1 and >1 */ | ||
509 | if (value == 1) | ||
510 | wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_BEACON; | ||
511 | else | ||
512 | wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_N_BEACONS; | ||
513 | |||
514 | /* | ||
515 | * we don't reconfigure ACX_WAKE_UP_CONDITIONS now, so it will only | ||
516 | * take effect on the next time we enter psm. | ||
517 | */ | ||
518 | mutex_unlock(&wl->mutex); | ||
519 | return count; | ||
520 | } | ||
521 | |||
522 | static const struct file_operations beacon_interval_ops = { | ||
523 | .read = beacon_interval_read, | ||
524 | .write = beacon_interval_write, | ||
525 | .open = wl1271_open_file_generic, | ||
526 | .llseek = default_llseek, | ||
527 | }; | ||
528 | |||
294 | static int wl1271_debugfs_add_files(struct wl1271 *wl, | 529 | static int wl1271_debugfs_add_files(struct wl1271 *wl, |
295 | struct dentry *rootdir) | 530 | struct dentry *rootdir) |
296 | { | 531 | { |
@@ -399,6 +634,10 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl, | |||
399 | DEBUGFS_ADD(excessive_retries, rootdir); | 634 | DEBUGFS_ADD(excessive_retries, rootdir); |
400 | 635 | ||
401 | DEBUGFS_ADD(gpio_power, rootdir); | 636 | DEBUGFS_ADD(gpio_power, rootdir); |
637 | DEBUGFS_ADD(start_recovery, rootdir); | ||
638 | DEBUGFS_ADD(driver_state, rootdir); | ||
639 | DEBUGFS_ADD(dtim_interval, rootdir); | ||
640 | DEBUGFS_ADD(beacon_interval, rootdir); | ||
402 | 641 | ||
403 | return 0; | 642 | return 0; |
404 | 643 | ||
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index d7be3aec6fc..ae69330e807 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c | |||
@@ -174,8 +174,6 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
174 | u32 vector; | 174 | u32 vector; |
175 | bool beacon_loss = false; | 175 | bool beacon_loss = false; |
176 | bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); | 176 | bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); |
177 | bool disconnect_sta = false; | ||
178 | unsigned long sta_bitmap = 0; | ||
179 | 177 | ||
180 | wl1271_event_mbox_dump(mbox); | 178 | wl1271_event_mbox_dump(mbox); |
181 | 179 | ||
@@ -237,54 +235,9 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
237 | wl1271_tx_dummy_packet(wl); | 235 | wl1271_tx_dummy_packet(wl); |
238 | } | 236 | } |
239 | 237 | ||
240 | /* | ||
241 | * "TX retries exceeded" has a different meaning according to mode. | ||
242 | * In AP mode the offending station is disconnected. In STA mode we | ||
243 | * report connection loss. | ||
244 | */ | ||
245 | if (vector & MAX_TX_RETRY_EVENT_ID) { | ||
246 | wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID"); | ||
247 | if (is_ap) { | ||
248 | sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded); | ||
249 | disconnect_sta = true; | ||
250 | } else { | ||
251 | beacon_loss = true; | ||
252 | } | ||
253 | } | ||
254 | |||
255 | if ((vector & INACTIVE_STA_EVENT_ID) && is_ap) { | ||
256 | wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID"); | ||
257 | sta_bitmap |= le16_to_cpu(mbox->sta_aging_status); | ||
258 | disconnect_sta = true; | ||
259 | } | ||
260 | |||
261 | if (wl->vif && beacon_loss) | 238 | if (wl->vif && beacon_loss) |
262 | ieee80211_connection_loss(wl->vif); | 239 | ieee80211_connection_loss(wl->vif); |
263 | 240 | ||
264 | if (is_ap && disconnect_sta) { | ||
265 | u32 num_packets = wl->conf.tx.max_tx_retries; | ||
266 | struct ieee80211_sta *sta; | ||
267 | const u8 *addr; | ||
268 | int h; | ||
269 | |||
270 | for (h = find_first_bit(&sta_bitmap, AP_MAX_LINKS); | ||
271 | h < AP_MAX_LINKS; | ||
272 | h = find_next_bit(&sta_bitmap, AP_MAX_LINKS, h+1)) { | ||
273 | if (!wl1271_is_active_sta(wl, h)) | ||
274 | continue; | ||
275 | |||
276 | addr = wl->links[h].addr; | ||
277 | |||
278 | rcu_read_lock(); | ||
279 | sta = ieee80211_find_sta(wl->vif, addr); | ||
280 | if (sta) { | ||
281 | wl1271_debug(DEBUG_EVENT, "remove sta %d", h); | ||
282 | ieee80211_report_low_ack(sta, num_packets); | ||
283 | } | ||
284 | rcu_read_unlock(); | ||
285 | } | ||
286 | } | ||
287 | |||
288 | return 0; | 241 | return 0; |
289 | } | 242 | } |
290 | 243 | ||
diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h index 7ae5a082124..b6cf06e565a 100644 --- a/drivers/net/wireless/wl12xx/event.h +++ b/drivers/net/wireless/wl12xx/event.h | |||
@@ -58,16 +58,13 @@ enum { | |||
58 | CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17), | 58 | CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17), |
59 | BSS_LOSE_EVENT_ID = BIT(18), | 59 | BSS_LOSE_EVENT_ID = BIT(18), |
60 | REGAINED_BSS_EVENT_ID = BIT(19), | 60 | REGAINED_BSS_EVENT_ID = BIT(19), |
61 | MAX_TX_RETRY_EVENT_ID = BIT(20), | 61 | ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20), |
62 | /* STA: dummy paket for dynamic mem blocks */ | 62 | /* STA: dummy paket for dynamic mem blocks */ |
63 | DUMMY_PACKET_EVENT_ID = BIT(21), | 63 | DUMMY_PACKET_EVENT_ID = BIT(21), |
64 | /* AP: STA remove complete */ | 64 | /* AP: STA remove complete */ |
65 | STA_REMOVE_COMPLETE_EVENT_ID = BIT(21), | 65 | STA_REMOVE_COMPLETE_EVENT_ID = BIT(21), |
66 | SOFT_GEMINI_SENSE_EVENT_ID = BIT(22), | 66 | SOFT_GEMINI_SENSE_EVENT_ID = BIT(22), |
67 | /* STA: SG prediction */ | ||
68 | SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23), | 67 | SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23), |
69 | /* AP: Inactive STA */ | ||
70 | INACTIVE_STA_EVENT_ID = BIT(23), | ||
71 | SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24), | 68 | SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24), |
72 | PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25), | 69 | PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25), |
73 | DBG_EVENT_ID = BIT(26), | 70 | DBG_EVENT_ID = BIT(26), |
@@ -122,11 +119,7 @@ struct event_mailbox { | |||
122 | 119 | ||
123 | /* AP FW only */ | 120 | /* AP FW only */ |
124 | u8 hlid_removed; | 121 | u8 hlid_removed; |
125 | |||
126 | /* a bitmap of hlids for stations that have been inactive too long */ | ||
127 | __le16 sta_aging_status; | 122 | __le16 sta_aging_status; |
128 | |||
129 | /* a bitmap of hlids for stations which didn't respond to TX */ | ||
130 | __le16 sta_tx_retry_exceeded; | 123 | __le16 sta_tx_retry_exceeded; |
131 | 124 | ||
132 | u8 reserved_5[24]; | 125 | u8 reserved_5[24]; |
@@ -137,7 +130,4 @@ void wl1271_event_mbox_config(struct wl1271 *wl); | |||
137 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox); | 130 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox); |
138 | void wl1271_pspoll_work(struct work_struct *work); | 131 | void wl1271_pspoll_work(struct work_struct *work); |
139 | 132 | ||
140 | /* Functions from main.c */ | ||
141 | bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid); | ||
142 | |||
143 | #endif | 133 | #endif |
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index ab3b1e21de2..a8f4f156c05 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c | |||
@@ -258,7 +258,7 @@ int wl1271_init_phy_config(struct wl1271 *wl) | |||
258 | if (ret < 0) | 258 | if (ret < 0) |
259 | return ret; | 259 | return ret; |
260 | 260 | ||
261 | ret = wl1271_acx_rts_threshold(wl, wl->conf.rx.rts_threshold); | 261 | ret = wl1271_acx_rts_threshold(wl, wl->hw->wiphy->rts_threshold); |
262 | if (ret < 0) | 262 | if (ret < 0) |
263 | return ret; | 263 | return ret; |
264 | 264 | ||
@@ -285,7 +285,10 @@ int wl1271_init_pta(struct wl1271 *wl) | |||
285 | { | 285 | { |
286 | int ret; | 286 | int ret; |
287 | 287 | ||
288 | ret = wl1271_acx_sg_cfg(wl); | 288 | if (wl->bss_type == BSS_TYPE_AP_BSS) |
289 | ret = wl1271_acx_ap_sg_cfg(wl); | ||
290 | else | ||
291 | ret = wl1271_acx_sta_sg_cfg(wl); | ||
289 | if (ret < 0) | 292 | if (ret < 0) |
290 | return ret; | 293 | return ret; |
291 | 294 | ||
@@ -351,8 +354,8 @@ static int wl1271_sta_hw_init(struct wl1271 *wl) | |||
351 | if (ret < 0) | 354 | if (ret < 0) |
352 | return ret; | 355 | return ret; |
353 | 356 | ||
354 | /* Bluetooth WLAN coexistence */ | 357 | /* FM WLAN coexistence */ |
355 | ret = wl1271_init_pta(wl); | 358 | ret = wl1271_acx_fm_coex(wl); |
356 | if (ret < 0) | 359 | if (ret < 0) |
357 | return ret; | 360 | return ret; |
358 | 361 | ||
@@ -375,10 +378,6 @@ static int wl1271_sta_hw_init(struct wl1271 *wl) | |||
375 | if (ret < 0) | 378 | if (ret < 0) |
376 | return ret; | 379 | return ret; |
377 | 380 | ||
378 | ret = wl1271_acx_sta_max_tx_retry(wl); | ||
379 | if (ret < 0) | ||
380 | return ret; | ||
381 | |||
382 | ret = wl1271_acx_sta_mem_cfg(wl); | 381 | ret = wl1271_acx_sta_mem_cfg(wl); |
383 | if (ret < 0) | 382 | if (ret < 0) |
384 | return ret; | 383 | return ret; |
@@ -414,7 +413,7 @@ static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl) | |||
414 | 413 | ||
415 | static int wl1271_ap_hw_init(struct wl1271 *wl) | 414 | static int wl1271_ap_hw_init(struct wl1271 *wl) |
416 | { | 415 | { |
417 | int ret, i; | 416 | int ret; |
418 | 417 | ||
419 | ret = wl1271_ap_init_templates_config(wl); | 418 | ret = wl1271_ap_init_templates_config(wl); |
420 | if (ret < 0) | 419 | if (ret < 0) |
@@ -425,27 +424,11 @@ static int wl1271_ap_hw_init(struct wl1271 *wl) | |||
425 | if (ret < 0) | 424 | if (ret < 0) |
426 | return ret; | 425 | return ret; |
427 | 426 | ||
428 | /* Configure initial TX rate classes */ | 427 | ret = wl1271_init_ap_rates(wl); |
429 | for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { | ||
430 | ret = wl1271_acx_ap_rate_policy(wl, | ||
431 | &wl->conf.tx.ap_rc_conf[i], i); | ||
432 | if (ret < 0) | ||
433 | return ret; | ||
434 | } | ||
435 | |||
436 | ret = wl1271_acx_ap_rate_policy(wl, | ||
437 | &wl->conf.tx.ap_mgmt_conf, | ||
438 | ACX_TX_AP_MODE_MGMT_RATE); | ||
439 | if (ret < 0) | 428 | if (ret < 0) |
440 | return ret; | 429 | return ret; |
441 | 430 | ||
442 | ret = wl1271_acx_ap_rate_policy(wl, | 431 | ret = wl1271_acx_max_tx_retry(wl); |
443 | &wl->conf.tx.ap_bcst_conf, | ||
444 | ACX_TX_AP_MODE_BCST_RATE); | ||
445 | if (ret < 0) | ||
446 | return ret; | ||
447 | |||
448 | ret = wl1271_acx_ap_max_tx_retry(wl); | ||
449 | if (ret < 0) | 432 | if (ret < 0) |
450 | return ret; | 433 | return ret; |
451 | 434 | ||
@@ -456,7 +439,7 @@ static int wl1271_ap_hw_init(struct wl1271 *wl) | |||
456 | return 0; | 439 | return 0; |
457 | } | 440 | } |
458 | 441 | ||
459 | static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl) | 442 | int wl1271_ap_init_templates(struct wl1271 *wl) |
460 | { | 443 | { |
461 | int ret; | 444 | int ret; |
462 | 445 | ||
@@ -472,6 +455,70 @@ static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl) | |||
472 | if (ret < 0) | 455 | if (ret < 0) |
473 | return ret; | 456 | return ret; |
474 | 457 | ||
458 | /* | ||
459 | * when operating as AP we want to receive external beacons for | ||
460 | * configuring ERP protection. | ||
461 | */ | ||
462 | ret = wl1271_acx_set_ap_beacon_filter(wl, false); | ||
463 | if (ret < 0) | ||
464 | return ret; | ||
465 | |||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl) | ||
470 | { | ||
471 | return wl1271_ap_init_templates(wl); | ||
472 | } | ||
473 | |||
474 | int wl1271_init_ap_rates(struct wl1271 *wl) | ||
475 | { | ||
476 | int i, ret; | ||
477 | struct conf_tx_rate_class rc; | ||
478 | u32 supported_rates; | ||
479 | |||
480 | wl1271_debug(DEBUG_AP, "AP basic rate set: 0x%x", wl->basic_rate_set); | ||
481 | |||
482 | if (wl->basic_rate_set == 0) | ||
483 | return -EINVAL; | ||
484 | |||
485 | rc.enabled_rates = wl->basic_rate_set; | ||
486 | rc.long_retry_limit = 10; | ||
487 | rc.short_retry_limit = 10; | ||
488 | rc.aflags = 0; | ||
489 | ret = wl1271_acx_ap_rate_policy(wl, &rc, ACX_TX_AP_MODE_MGMT_RATE); | ||
490 | if (ret < 0) | ||
491 | return ret; | ||
492 | |||
493 | /* use the min basic rate for AP broadcast/multicast */ | ||
494 | rc.enabled_rates = wl1271_tx_min_rate_get(wl); | ||
495 | rc.short_retry_limit = 10; | ||
496 | rc.long_retry_limit = 10; | ||
497 | rc.aflags = 0; | ||
498 | ret = wl1271_acx_ap_rate_policy(wl, &rc, ACX_TX_AP_MODE_BCST_RATE); | ||
499 | if (ret < 0) | ||
500 | return ret; | ||
501 | |||
502 | /* | ||
503 | * If the basic rates contain OFDM rates, use OFDM only | ||
504 | * rates for unicast TX as well. Else use all supported rates. | ||
505 | */ | ||
506 | if ((wl->basic_rate_set & CONF_TX_OFDM_RATES)) | ||
507 | supported_rates = CONF_TX_OFDM_RATES; | ||
508 | else | ||
509 | supported_rates = CONF_TX_AP_ENABLED_RATES; | ||
510 | |||
511 | /* configure unicast TX rate classes */ | ||
512 | for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { | ||
513 | rc.enabled_rates = supported_rates; | ||
514 | rc.short_retry_limit = 10; | ||
515 | rc.long_retry_limit = 10; | ||
516 | rc.aflags = 0; | ||
517 | ret = wl1271_acx_ap_rate_policy(wl, &rc, i); | ||
518 | if (ret < 0) | ||
519 | return ret; | ||
520 | } | ||
521 | |||
475 | return 0; | 522 | return 0; |
476 | } | 523 | } |
477 | 524 | ||
@@ -567,6 +614,11 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
567 | if (ret < 0) | 614 | if (ret < 0) |
568 | return ret; | 615 | return ret; |
569 | 616 | ||
617 | /* Bluetooth WLAN coexistence */ | ||
618 | ret = wl1271_init_pta(wl); | ||
619 | if (ret < 0) | ||
620 | return ret; | ||
621 | |||
570 | /* Default memory configuration */ | 622 | /* Default memory configuration */ |
571 | ret = wl1271_acx_init_mem_config(wl); | 623 | ret = wl1271_acx_init_mem_config(wl); |
572 | if (ret < 0) | 624 | if (ret < 0) |
@@ -606,7 +658,7 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
606 | goto out_free_memmap; | 658 | goto out_free_memmap; |
607 | 659 | ||
608 | /* Default fragmentation threshold */ | 660 | /* Default fragmentation threshold */ |
609 | ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold); | 661 | ret = wl1271_acx_frag_threshold(wl, wl->hw->wiphy->frag_threshold); |
610 | if (ret < 0) | 662 | if (ret < 0) |
611 | goto out_free_memmap; | 663 | goto out_free_memmap; |
612 | 664 | ||
diff --git a/drivers/net/wireless/wl12xx/init.h b/drivers/net/wireless/wl12xx/init.h index 4975270a91a..3a3c230fd29 100644 --- a/drivers/net/wireless/wl12xx/init.h +++ b/drivers/net/wireless/wl12xx/init.h | |||
@@ -33,5 +33,7 @@ int wl1271_init_pta(struct wl1271 *wl); | |||
33 | int wl1271_init_energy_detection(struct wl1271 *wl); | 33 | int wl1271_init_energy_detection(struct wl1271 *wl); |
34 | int wl1271_chip_specific_init(struct wl1271 *wl); | 34 | int wl1271_chip_specific_init(struct wl1271 *wl); |
35 | int wl1271_hw_init(struct wl1271 *wl); | 35 | int wl1271_hw_init(struct wl1271 *wl); |
36 | int wl1271_init_ap_rates(struct wl1271 *wl); | ||
37 | int wl1271_ap_init_templates(struct wl1271 *wl); | ||
36 | 38 | ||
37 | #endif | 39 | #endif |
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 0c69e959d0d..6dab6f0c91b 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -51,7 +51,7 @@ | |||
51 | 51 | ||
52 | static struct conf_drv_settings default_conf = { | 52 | static struct conf_drv_settings default_conf = { |
53 | .sg = { | 53 | .sg = { |
54 | .params = { | 54 | .sta_params = { |
55 | [CONF_SG_BT_PER_THRESHOLD] = 7500, | 55 | [CONF_SG_BT_PER_THRESHOLD] = 7500, |
56 | [CONF_SG_HV3_MAX_OVERRIDE] = 0, | 56 | [CONF_SG_HV3_MAX_OVERRIDE] = 0, |
57 | [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, | 57 | [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, |
@@ -101,6 +101,61 @@ static struct conf_drv_settings default_conf = { | |||
101 | [CONF_SG_DHCP_TIME] = 5000, | 101 | [CONF_SG_DHCP_TIME] = 5000, |
102 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, | 102 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, |
103 | }, | 103 | }, |
104 | .ap_params = { | ||
105 | [CONF_SG_BT_PER_THRESHOLD] = 7500, | ||
106 | [CONF_SG_HV3_MAX_OVERRIDE] = 0, | ||
107 | [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, | ||
108 | [CONF_SG_BT_LOAD_RATIO] = 50, | ||
109 | [CONF_SG_AUTO_PS_MODE] = 1, | ||
110 | [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, | ||
111 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, | ||
112 | [CONF_SG_ANTENNA_CONFIGURATION] = 0, | ||
113 | [CONF_SG_BEACON_MISS_PERCENT] = 60, | ||
114 | [CONF_SG_RATE_ADAPT_THRESH] = 64, | ||
115 | [CONF_SG_RATE_ADAPT_SNR] = 1, | ||
116 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR] = 10, | ||
117 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR] = 25, | ||
118 | [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR] = 25, | ||
119 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR] = 20, | ||
120 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR] = 25, | ||
121 | [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR] = 25, | ||
122 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR] = 7, | ||
123 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR] = 25, | ||
124 | [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR] = 25, | ||
125 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR] = 8, | ||
126 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR] = 25, | ||
127 | [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR] = 25, | ||
128 | [CONF_SG_RXT] = 1200, | ||
129 | [CONF_SG_TXT] = 1000, | ||
130 | [CONF_SG_ADAPTIVE_RXT_TXT] = 1, | ||
131 | [CONF_SG_PS_POLL_TIMEOUT] = 10, | ||
132 | [CONF_SG_UPSD_TIMEOUT] = 10, | ||
133 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR] = 7, | ||
134 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR] = 15, | ||
135 | [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR] = 15, | ||
136 | [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR] = 8, | ||
137 | [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR] = 20, | ||
138 | [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR] = 15, | ||
139 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR] = 20, | ||
140 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR] = 50, | ||
141 | [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR] = 10, | ||
142 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200, | ||
143 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP] = 800, | ||
144 | [CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME] = 75, | ||
145 | [CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME] = 15, | ||
146 | [CONF_SG_HV3_MAX_SERVED] = 6, | ||
147 | [CONF_SG_DHCP_TIME] = 5000, | ||
148 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, | ||
149 | [CONF_SG_TEMP_PARAM_1] = 0, | ||
150 | [CONF_SG_TEMP_PARAM_2] = 0, | ||
151 | [CONF_SG_TEMP_PARAM_3] = 0, | ||
152 | [CONF_SG_TEMP_PARAM_4] = 0, | ||
153 | [CONF_SG_TEMP_PARAM_5] = 0, | ||
154 | [CONF_SG_AP_BEACON_MISS_TX] = 3, | ||
155 | [CONF_SG_RX_WINDOW_LENGTH] = 6, | ||
156 | [CONF_SG_AP_CONNECTION_PROTECTION_TIME] = 50, | ||
157 | [CONF_SG_TEMP_PARAM_6] = 1, | ||
158 | }, | ||
104 | .state = CONF_SG_PROTECTIVE, | 159 | .state = CONF_SG_PROTECTIVE, |
105 | }, | 160 | }, |
106 | .rx = { | 161 | .rx = { |
@@ -108,7 +163,7 @@ static struct conf_drv_settings default_conf = { | |||
108 | .packet_detection_threshold = 0, | 163 | .packet_detection_threshold = 0, |
109 | .ps_poll_timeout = 15, | 164 | .ps_poll_timeout = 15, |
110 | .upsd_timeout = 15, | 165 | .upsd_timeout = 15, |
111 | .rts_threshold = 2347, | 166 | .rts_threshold = IEEE80211_MAX_RTS_THRESHOLD, |
112 | .rx_cca_threshold = 0, | 167 | .rx_cca_threshold = 0, |
113 | .irq_blk_threshold = 0xFFFF, | 168 | .irq_blk_threshold = 0xFFFF, |
114 | .irq_pkt_threshold = 0, | 169 | .irq_pkt_threshold = 0, |
@@ -154,46 +209,7 @@ static struct conf_drv_settings default_conf = { | |||
154 | .tx_op_limit = 1504, | 209 | .tx_op_limit = 1504, |
155 | }, | 210 | }, |
156 | }, | 211 | }, |
157 | .ap_rc_conf = { | 212 | .ap_max_tx_retries = 100, |
158 | [0] = { | ||
159 | .enabled_rates = CONF_TX_AP_ENABLED_RATES, | ||
160 | .short_retry_limit = 10, | ||
161 | .long_retry_limit = 10, | ||
162 | .aflags = 0, | ||
163 | }, | ||
164 | [1] = { | ||
165 | .enabled_rates = CONF_TX_AP_ENABLED_RATES, | ||
166 | .short_retry_limit = 10, | ||
167 | .long_retry_limit = 10, | ||
168 | .aflags = 0, | ||
169 | }, | ||
170 | [2] = { | ||
171 | .enabled_rates = CONF_TX_AP_ENABLED_RATES, | ||
172 | .short_retry_limit = 10, | ||
173 | .long_retry_limit = 10, | ||
174 | .aflags = 0, | ||
175 | }, | ||
176 | [3] = { | ||
177 | .enabled_rates = CONF_TX_AP_ENABLED_RATES, | ||
178 | .short_retry_limit = 10, | ||
179 | .long_retry_limit = 10, | ||
180 | .aflags = 0, | ||
181 | }, | ||
182 | }, | ||
183 | .ap_mgmt_conf = { | ||
184 | .enabled_rates = CONF_TX_AP_DEFAULT_MGMT_RATES, | ||
185 | .short_retry_limit = 10, | ||
186 | .long_retry_limit = 10, | ||
187 | .aflags = 0, | ||
188 | }, | ||
189 | .ap_bcst_conf = { | ||
190 | .enabled_rates = CONF_HW_BIT_RATE_1MBPS, | ||
191 | .short_retry_limit = 10, | ||
192 | .long_retry_limit = 10, | ||
193 | .aflags = 0, | ||
194 | }, | ||
195 | .max_tx_retries = 100, | ||
196 | .ap_aging_period = 300, | ||
197 | .tid_conf_count = 4, | 213 | .tid_conf_count = 4, |
198 | .tid_conf = { | 214 | .tid_conf = { |
199 | [CONF_TX_AC_BE] = { | 215 | [CONF_TX_AC_BE] = { |
@@ -258,7 +274,7 @@ static struct conf_drv_settings default_conf = { | |||
258 | .bet_enable = CONF_BET_MODE_ENABLE, | 274 | .bet_enable = CONF_BET_MODE_ENABLE, |
259 | .bet_max_consecutive = 50, | 275 | .bet_max_consecutive = 50, |
260 | .psm_entry_retries = 5, | 276 | .psm_entry_retries = 5, |
261 | .psm_exit_retries = 255, | 277 | .psm_exit_retries = 16, |
262 | .psm_entry_nullfunc_retries = 3, | 278 | .psm_entry_nullfunc_retries = 3, |
263 | .psm_entry_hangover_period = 1, | 279 | .psm_entry_hangover_period = 1, |
264 | .keep_alive_interval = 55000, | 280 | .keep_alive_interval = 55000, |
@@ -305,7 +321,7 @@ static struct conf_drv_settings default_conf = { | |||
305 | .ssid_profiles = 1, | 321 | .ssid_profiles = 1, |
306 | .rx_block_num = 70, | 322 | .rx_block_num = 70, |
307 | .tx_min_block_num = 40, | 323 | .tx_min_block_num = 40, |
308 | .dynamic_memory = 0, | 324 | .dynamic_memory = 1, |
309 | .min_req_tx_blocks = 100, | 325 | .min_req_tx_blocks = 100, |
310 | .min_req_rx_blocks = 22, | 326 | .min_req_rx_blocks = 22, |
311 | .tx_min = 27, | 327 | .tx_min = 27, |
@@ -320,10 +336,23 @@ static struct conf_drv_settings default_conf = { | |||
320 | .min_req_rx_blocks = 22, | 336 | .min_req_rx_blocks = 22, |
321 | .tx_min = 27, | 337 | .tx_min = 27, |
322 | }, | 338 | }, |
339 | .fm_coex = { | ||
340 | .enable = true, | ||
341 | .swallow_period = 5, | ||
342 | .n_divider_fref_set_1 = 0xff, /* default */ | ||
343 | .n_divider_fref_set_2 = 12, | ||
344 | .m_divider_fref_set_1 = 148, | ||
345 | .m_divider_fref_set_2 = 0xffff, /* default */ | ||
346 | .coex_pll_stabilization_time = 0xffffffff, /* default */ | ||
347 | .ldo_stabilization_time = 0xffff, /* default */ | ||
348 | .fm_disturbed_band_margin = 0xff, /* default */ | ||
349 | .swallow_clk_diff = 0xff, /* default */ | ||
350 | }, | ||
323 | .hci_io_ds = HCI_IO_DS_6MA, | 351 | .hci_io_ds = HCI_IO_DS_6MA, |
324 | }; | 352 | }; |
325 | 353 | ||
326 | static void __wl1271_op_remove_interface(struct wl1271 *wl); | 354 | static void __wl1271_op_remove_interface(struct wl1271 *wl, |
355 | bool reset_tx_queues); | ||
327 | static void wl1271_free_ap_keys(struct wl1271 *wl); | 356 | static void wl1271_free_ap_keys(struct wl1271 *wl); |
328 | 357 | ||
329 | 358 | ||
@@ -508,6 +537,11 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
508 | if (ret < 0) | 537 | if (ret < 0) |
509 | goto out_free_memmap; | 538 | goto out_free_memmap; |
510 | 539 | ||
540 | /* FM WLAN coexistence */ | ||
541 | ret = wl1271_acx_fm_coex(wl); | ||
542 | if (ret < 0) | ||
543 | goto out_free_memmap; | ||
544 | |||
511 | /* Energy detection */ | 545 | /* Energy detection */ |
512 | ret = wl1271_init_energy_detection(wl); | 546 | ret = wl1271_init_energy_detection(wl); |
513 | if (ret < 0) | 547 | if (ret < 0) |
@@ -932,15 +966,25 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
932 | if (wl->state != WL1271_STATE_ON) | 966 | if (wl->state != WL1271_STATE_ON) |
933 | goto out; | 967 | goto out; |
934 | 968 | ||
935 | wl1271_info("Hardware recovery in progress."); | 969 | wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x", |
970 | wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4)); | ||
936 | 971 | ||
937 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | 972 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) |
938 | ieee80211_connection_loss(wl->vif); | 973 | ieee80211_connection_loss(wl->vif); |
939 | 974 | ||
975 | /* Prevent spurious TX during FW restart */ | ||
976 | ieee80211_stop_queues(wl->hw); | ||
977 | |||
940 | /* reboot the chipset */ | 978 | /* reboot the chipset */ |
941 | __wl1271_op_remove_interface(wl); | 979 | __wl1271_op_remove_interface(wl, false); |
942 | ieee80211_restart_hw(wl->hw); | 980 | ieee80211_restart_hw(wl->hw); |
943 | 981 | ||
982 | /* | ||
983 | * Its safe to enable TX now - the queues are stopped after a request | ||
984 | * to restart the HW. | ||
985 | */ | ||
986 | ieee80211_wake_queues(wl->hw); | ||
987 | |||
944 | out: | 988 | out: |
945 | mutex_unlock(&wl->mutex); | 989 | mutex_unlock(&wl->mutex); |
946 | } | 990 | } |
@@ -1011,6 +1055,10 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
1011 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", | 1055 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", |
1012 | wl->chip.id); | 1056 | wl->chip.id); |
1013 | 1057 | ||
1058 | /* end-of-transaction flag should be set in wl127x AP mode */ | ||
1059 | if (wl->bss_type == BSS_TYPE_AP_BSS) | ||
1060 | wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION; | ||
1061 | |||
1014 | ret = wl1271_setup(wl); | 1062 | ret = wl1271_setup(wl); |
1015 | if (ret < 0) | 1063 | if (ret < 0) |
1016 | goto out; | 1064 | goto out; |
@@ -1273,7 +1321,7 @@ static struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl) | |||
1273 | skb->priority = WL1271_TID_MGMT; | 1321 | skb->priority = WL1271_TID_MGMT; |
1274 | 1322 | ||
1275 | /* Initialize all fields that might be used */ | 1323 | /* Initialize all fields that might be used */ |
1276 | skb->queue_mapping = 0; | 1324 | skb_set_queue_mapping(skb, 0); |
1277 | memset(IEEE80211_SKB_CB(skb), 0, sizeof(struct ieee80211_tx_info)); | 1325 | memset(IEEE80211_SKB_CB(skb), 0, sizeof(struct ieee80211_tx_info)); |
1278 | 1326 | ||
1279 | return skb; | 1327 | return skb; |
@@ -1440,7 +1488,8 @@ out: | |||
1440 | return ret; | 1488 | return ret; |
1441 | } | 1489 | } |
1442 | 1490 | ||
1443 | static void __wl1271_op_remove_interface(struct wl1271 *wl) | 1491 | static void __wl1271_op_remove_interface(struct wl1271 *wl, |
1492 | bool reset_tx_queues) | ||
1444 | { | 1493 | { |
1445 | int i; | 1494 | int i; |
1446 | 1495 | ||
@@ -1486,7 +1535,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) | |||
1486 | mutex_lock(&wl->mutex); | 1535 | mutex_lock(&wl->mutex); |
1487 | 1536 | ||
1488 | /* let's notify MAC80211 about the remaining pending TX frames */ | 1537 | /* let's notify MAC80211 about the remaining pending TX frames */ |
1489 | wl1271_tx_reset(wl); | 1538 | wl1271_tx_reset(wl, reset_tx_queues); |
1490 | wl1271_power_off(wl); | 1539 | wl1271_power_off(wl); |
1491 | 1540 | ||
1492 | memset(wl->bssid, 0, ETH_ALEN); | 1541 | memset(wl->bssid, 0, ETH_ALEN); |
@@ -1547,7 +1596,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
1547 | */ | 1596 | */ |
1548 | if (wl->vif) { | 1597 | if (wl->vif) { |
1549 | WARN_ON(wl->vif != vif); | 1598 | WARN_ON(wl->vif != vif); |
1550 | __wl1271_op_remove_interface(wl); | 1599 | __wl1271_op_remove_interface(wl, true); |
1551 | } | 1600 | } |
1552 | 1601 | ||
1553 | mutex_unlock(&wl->mutex); | 1602 | mutex_unlock(&wl->mutex); |
@@ -2284,7 +2333,7 @@ static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value) | |||
2284 | if (ret < 0) | 2333 | if (ret < 0) |
2285 | goto out; | 2334 | goto out; |
2286 | 2335 | ||
2287 | ret = wl1271_acx_frag_threshold(wl, (u16)value); | 2336 | ret = wl1271_acx_frag_threshold(wl, value); |
2288 | if (ret < 0) | 2337 | if (ret < 0) |
2289 | wl1271_warning("wl1271_op_set_frag_threshold failed: %d", ret); | 2338 | wl1271_warning("wl1271_op_set_frag_threshold failed: %d", ret); |
2290 | 2339 | ||
@@ -2312,7 +2361,7 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | |||
2312 | if (ret < 0) | 2361 | if (ret < 0) |
2313 | goto out; | 2362 | goto out; |
2314 | 2363 | ||
2315 | ret = wl1271_acx_rts_threshold(wl, (u16) value); | 2364 | ret = wl1271_acx_rts_threshold(wl, value); |
2316 | if (ret < 0) | 2365 | if (ret < 0) |
2317 | wl1271_warning("wl1271_op_set_rts_threshold failed: %d", ret); | 2366 | wl1271_warning("wl1271_op_set_rts_threshold failed: %d", ret); |
2318 | 2367 | ||
@@ -2455,24 +2504,19 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, | |||
2455 | 2504 | ||
2456 | if ((changed & BSS_CHANGED_BASIC_RATES)) { | 2505 | if ((changed & BSS_CHANGED_BASIC_RATES)) { |
2457 | u32 rates = bss_conf->basic_rates; | 2506 | u32 rates = bss_conf->basic_rates; |
2458 | struct conf_tx_rate_class mgmt_rc; | ||
2459 | 2507 | ||
2460 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates); | 2508 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates); |
2461 | wl->basic_rate = wl1271_tx_min_rate_get(wl); | 2509 | wl->basic_rate = wl1271_tx_min_rate_get(wl); |
2462 | wl1271_debug(DEBUG_AP, "basic rates: 0x%x", | 2510 | |
2463 | wl->basic_rate_set); | 2511 | ret = wl1271_init_ap_rates(wl); |
2464 | |||
2465 | /* update the AP management rate policy with the new rates */ | ||
2466 | mgmt_rc.enabled_rates = wl->basic_rate_set; | ||
2467 | mgmt_rc.long_retry_limit = 10; | ||
2468 | mgmt_rc.short_retry_limit = 10; | ||
2469 | mgmt_rc.aflags = 0; | ||
2470 | ret = wl1271_acx_ap_rate_policy(wl, &mgmt_rc, | ||
2471 | ACX_TX_AP_MODE_MGMT_RATE); | ||
2472 | if (ret < 0) { | 2512 | if (ret < 0) { |
2473 | wl1271_error("AP mgmt policy change failed %d", ret); | 2513 | wl1271_error("AP rate policy change failed %d", ret); |
2474 | goto out; | 2514 | goto out; |
2475 | } | 2515 | } |
2516 | |||
2517 | ret = wl1271_ap_init_templates(wl); | ||
2518 | if (ret < 0) | ||
2519 | goto out; | ||
2476 | } | 2520 | } |
2477 | 2521 | ||
2478 | ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, changed); | 2522 | ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, changed); |
@@ -2505,6 +2549,24 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, | |||
2505 | } | 2549 | } |
2506 | } | 2550 | } |
2507 | 2551 | ||
2552 | if (changed & BSS_CHANGED_IBSS) { | ||
2553 | wl1271_debug(DEBUG_ADHOC, "ibss_joined: %d", | ||
2554 | bss_conf->ibss_joined); | ||
2555 | |||
2556 | if (bss_conf->ibss_joined) { | ||
2557 | u32 rates = bss_conf->basic_rates; | ||
2558 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, | ||
2559 | rates); | ||
2560 | wl->basic_rate = wl1271_tx_min_rate_get(wl); | ||
2561 | |||
2562 | /* by default, use 11b rates */ | ||
2563 | wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES; | ||
2564 | ret = wl1271_acx_sta_rate_policies(wl); | ||
2565 | if (ret < 0) | ||
2566 | goto out; | ||
2567 | } | ||
2568 | } | ||
2569 | |||
2508 | ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed); | 2570 | ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed); |
2509 | if (ret < 0) | 2571 | if (ret < 0) |
2510 | goto out; | 2572 | goto out; |
@@ -2694,8 +2756,10 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
2694 | } | 2756 | } |
2695 | } else { | 2757 | } else { |
2696 | /* use defaults when not associated */ | 2758 | /* use defaults when not associated */ |
2759 | bool was_assoc = | ||
2760 | !!test_and_clear_bit(WL1271_FLAG_STA_ASSOCIATED, | ||
2761 | &wl->flags); | ||
2697 | clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags); | 2762 | clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags); |
2698 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | ||
2699 | wl->aid = 0; | 2763 | wl->aid = 0; |
2700 | 2764 | ||
2701 | /* free probe-request template */ | 2765 | /* free probe-request template */ |
@@ -2721,8 +2785,10 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
2721 | goto out; | 2785 | goto out; |
2722 | 2786 | ||
2723 | /* restore the bssid filter and go to dummy bssid */ | 2787 | /* restore the bssid filter and go to dummy bssid */ |
2724 | wl1271_unjoin(wl); | 2788 | if (was_assoc) { |
2725 | wl1271_dummy_join(wl); | 2789 | wl1271_unjoin(wl); |
2790 | wl1271_dummy_join(wl); | ||
2791 | } | ||
2726 | } | 2792 | } |
2727 | } | 2793 | } |
2728 | 2794 | ||
@@ -2954,12 +3020,6 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid) | |||
2954 | __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | 3020 | __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); |
2955 | } | 3021 | } |
2956 | 3022 | ||
2957 | bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid) | ||
2958 | { | ||
2959 | int id = hlid - WL1271_AP_STA_HLID_START; | ||
2960 | return test_bit(id, wl->ap_hlid_map); | ||
2961 | } | ||
2962 | |||
2963 | static int wl1271_op_sta_add(struct ieee80211_hw *hw, | 3023 | static int wl1271_op_sta_add(struct ieee80211_hw *hw, |
2964 | struct ieee80211_vif *vif, | 3024 | struct ieee80211_vif *vif, |
2965 | struct ieee80211_sta *sta) | 3025 | struct ieee80211_sta *sta) |
@@ -3104,6 +3164,28 @@ out: | |||
3104 | return ret; | 3164 | return ret; |
3105 | } | 3165 | } |
3106 | 3166 | ||
3167 | static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) | ||
3168 | { | ||
3169 | struct wl1271 *wl = hw->priv; | ||
3170 | bool ret = false; | ||
3171 | |||
3172 | mutex_lock(&wl->mutex); | ||
3173 | |||
3174 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
3175 | goto out; | ||
3176 | |||
3177 | /* packets are considered pending if in the TX queue or the FW */ | ||
3178 | ret = (wl->tx_queue_count > 0) || (wl->tx_frames_cnt > 0); | ||
3179 | |||
3180 | /* the above is appropriate for STA mode for PS purposes */ | ||
3181 | WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); | ||
3182 | |||
3183 | out: | ||
3184 | mutex_unlock(&wl->mutex); | ||
3185 | |||
3186 | return ret; | ||
3187 | } | ||
3188 | |||
3107 | /* can't be const, mac80211 writes to this */ | 3189 | /* can't be const, mac80211 writes to this */ |
3108 | static struct ieee80211_rate wl1271_rates[] = { | 3190 | static struct ieee80211_rate wl1271_rates[] = { |
3109 | { .bitrate = 10, | 3191 | { .bitrate = 10, |
@@ -3355,6 +3437,7 @@ static const struct ieee80211_ops wl1271_ops = { | |||
3355 | .sta_add = wl1271_op_sta_add, | 3437 | .sta_add = wl1271_op_sta_add, |
3356 | .sta_remove = wl1271_op_sta_remove, | 3438 | .sta_remove = wl1271_op_sta_remove, |
3357 | .ampdu_action = wl1271_op_ampdu_action, | 3439 | .ampdu_action = wl1271_op_ampdu_action, |
3440 | .tx_frames_pending = wl1271_tx_frames_pending, | ||
3358 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | 3441 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) |
3359 | }; | 3442 | }; |
3360 | 3443 | ||
@@ -3542,6 +3625,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
3542 | IEEE80211_HW_HAS_RATE_CONTROL | | 3625 | IEEE80211_HW_HAS_RATE_CONTROL | |
3543 | IEEE80211_HW_CONNECTION_MONITOR | | 3626 | IEEE80211_HW_CONNECTION_MONITOR | |
3544 | IEEE80211_HW_SUPPORTS_CQM_RSSI | | 3627 | IEEE80211_HW_SUPPORTS_CQM_RSSI | |
3628 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | | ||
3545 | IEEE80211_HW_AP_LINK_PS; | 3629 | IEEE80211_HW_AP_LINK_PS; |
3546 | 3630 | ||
3547 | wl->hw->wiphy->cipher_suites = cipher_suites; | 3631 | wl->hw->wiphy->cipher_suites = cipher_suites; |
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c index b8deada5d02..b59b67711a1 100644 --- a/drivers/net/wireless/wl12xx/ps.c +++ b/drivers/net/wireless/wl12xx/ps.c | |||
@@ -43,6 +43,10 @@ void wl1271_elp_work(struct work_struct *work) | |||
43 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 43 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
44 | goto out; | 44 | goto out; |
45 | 45 | ||
46 | /* our work might have been already cancelled */ | ||
47 | if (unlikely(!test_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags))) | ||
48 | goto out; | ||
49 | |||
46 | if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || | 50 | if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || |
47 | (!test_bit(WL1271_FLAG_PSM, &wl->flags) && | 51 | (!test_bit(WL1271_FLAG_PSM, &wl->flags) && |
48 | !test_bit(WL1271_FLAG_IDLE, &wl->flags))) | 52 | !test_bit(WL1271_FLAG_IDLE, &wl->flags))) |
@@ -61,12 +65,16 @@ out: | |||
61 | /* Routines to toggle sleep mode while in ELP */ | 65 | /* Routines to toggle sleep mode while in ELP */ |
62 | void wl1271_ps_elp_sleep(struct wl1271 *wl) | 66 | void wl1271_ps_elp_sleep(struct wl1271 *wl) |
63 | { | 67 | { |
64 | if (test_bit(WL1271_FLAG_PSM, &wl->flags) || | 68 | /* we shouldn't get consecutive sleep requests */ |
65 | test_bit(WL1271_FLAG_IDLE, &wl->flags)) { | 69 | if (WARN_ON(test_and_set_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags))) |
66 | cancel_delayed_work(&wl->elp_work); | 70 | return; |
67 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, | 71 | |
68 | msecs_to_jiffies(ELP_ENTRY_DELAY)); | 72 | if (!test_bit(WL1271_FLAG_PSM, &wl->flags) && |
69 | } | 73 | !test_bit(WL1271_FLAG_IDLE, &wl->flags)) |
74 | return; | ||
75 | |||
76 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, | ||
77 | msecs_to_jiffies(ELP_ENTRY_DELAY)); | ||
70 | } | 78 | } |
71 | 79 | ||
72 | int wl1271_ps_elp_wakeup(struct wl1271 *wl) | 80 | int wl1271_ps_elp_wakeup(struct wl1271 *wl) |
@@ -77,6 +85,16 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl) | |||
77 | u32 start_time = jiffies; | 85 | u32 start_time = jiffies; |
78 | bool pending = false; | 86 | bool pending = false; |
79 | 87 | ||
88 | /* | ||
89 | * we might try to wake up even if we didn't go to sleep | ||
90 | * before (e.g. on boot) | ||
91 | */ | ||
92 | if (!test_and_clear_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags)) | ||
93 | return 0; | ||
94 | |||
95 | /* don't cancel_sync as it might contend for a mutex and deadlock */ | ||
96 | cancel_delayed_work(&wl->elp_work); | ||
97 | |||
80 | if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags)) | 98 | if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags)) |
81 | return 0; | 99 | return 0; |
82 | 100 | ||
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index 2a581495d5c..70091035e01 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c | |||
@@ -76,12 +76,15 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
76 | status->band); | 76 | status->band); |
77 | 77 | ||
78 | if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { | 78 | if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { |
79 | status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; | 79 | u8 desc_err_code = desc->status & WL1271_RX_DESC_STATUS_MASK; |
80 | 80 | ||
81 | if (likely(!(desc->status & WL1271_RX_DESC_DECRYPT_FAIL))) | 81 | status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED | |
82 | status->flag |= RX_FLAG_DECRYPTED; | 82 | RX_FLAG_DECRYPTED; |
83 | if (unlikely(desc->status & WL1271_RX_DESC_MIC_FAIL)) | 83 | |
84 | if (unlikely(desc_err_code == WL1271_RX_DESC_MIC_FAIL)) { | ||
84 | status->flag |= RX_FLAG_MMIC_ERROR; | 85 | status->flag |= RX_FLAG_MMIC_ERROR; |
86 | wl1271_warning("Michael MIC error"); | ||
87 | } | ||
85 | } | 88 | } |
86 | } | 89 | } |
87 | 90 | ||
@@ -100,6 +103,25 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length) | |||
100 | if (unlikely(wl->state == WL1271_STATE_PLT)) | 103 | if (unlikely(wl->state == WL1271_STATE_PLT)) |
101 | return -EINVAL; | 104 | return -EINVAL; |
102 | 105 | ||
106 | /* the data read starts with the descriptor */ | ||
107 | desc = (struct wl1271_rx_descriptor *) data; | ||
108 | |||
109 | switch (desc->status & WL1271_RX_DESC_STATUS_MASK) { | ||
110 | /* discard corrupted packets */ | ||
111 | case WL1271_RX_DESC_DRIVER_RX_Q_FAIL: | ||
112 | case WL1271_RX_DESC_DECRYPT_FAIL: | ||
113 | wl1271_warning("corrupted packet in RX with status: 0x%x", | ||
114 | desc->status & WL1271_RX_DESC_STATUS_MASK); | ||
115 | return -EINVAL; | ||
116 | case WL1271_RX_DESC_SUCCESS: | ||
117 | case WL1271_RX_DESC_MIC_FAIL: | ||
118 | break; | ||
119 | default: | ||
120 | wl1271_error("invalid RX descriptor status: 0x%x", | ||
121 | desc->status & WL1271_RX_DESC_STATUS_MASK); | ||
122 | return -EINVAL; | ||
123 | } | ||
124 | |||
103 | skb = __dev_alloc_skb(length, GFP_KERNEL); | 125 | skb = __dev_alloc_skb(length, GFP_KERNEL); |
104 | if (!skb) { | 126 | if (!skb) { |
105 | wl1271_error("Couldn't allocate RX frame"); | 127 | wl1271_error("Couldn't allocate RX frame"); |
@@ -109,9 +131,6 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length) | |||
109 | buf = skb_put(skb, length); | 131 | buf = skb_put(skb, length); |
110 | memcpy(buf, data, length); | 132 | memcpy(buf, data, length); |
111 | 133 | ||
112 | /* the data read starts with the descriptor */ | ||
113 | desc = (struct wl1271_rx_descriptor *) buf; | ||
114 | |||
115 | /* now we pull the descriptor out of the buffer */ | 134 | /* now we pull the descriptor out of the buffer */ |
116 | skb_pull(skb, sizeof(*desc)); | 135 | skb_pull(skb, sizeof(*desc)); |
117 | 136 | ||
@@ -121,7 +140,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length) | |||
121 | 140 | ||
122 | wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon); | 141 | wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon); |
123 | 142 | ||
124 | wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len, | 143 | wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, |
144 | skb->len - desc->pad_len, | ||
125 | beacon ? "beacon" : ""); | 145 | beacon ? "beacon" : ""); |
126 | 146 | ||
127 | skb_trim(skb, skb->len - desc->pad_len); | 147 | skb_trim(skb, skb->len - desc->pad_len); |
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 7a3339fd341..ca3ab1c1ace 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c | |||
@@ -65,6 +65,9 @@ static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb) | |||
65 | static void wl1271_free_tx_id(struct wl1271 *wl, int id) | 65 | static void wl1271_free_tx_id(struct wl1271 *wl, int id) |
66 | { | 66 | { |
67 | if (__test_and_clear_bit(id, wl->tx_frames_map)) { | 67 | if (__test_and_clear_bit(id, wl->tx_frames_map)) { |
68 | if (unlikely(wl->tx_frames_cnt == ACX_TX_DESCRIPTORS)) | ||
69 | clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); | ||
70 | |||
68 | wl->tx_frames[id] = NULL; | 71 | wl->tx_frames[id] = NULL; |
69 | wl->tx_frames_cnt--; | 72 | wl->tx_frames_cnt--; |
70 | } | 73 | } |
@@ -630,7 +633,7 @@ void wl1271_tx_work(struct work_struct *work) | |||
630 | 633 | ||
631 | wl1271_tx_work_locked(wl); | 634 | wl1271_tx_work_locked(wl); |
632 | 635 | ||
633 | wl1271_ps_elp_wakeup(wl); | 636 | wl1271_ps_elp_sleep(wl); |
634 | out: | 637 | out: |
635 | mutex_unlock(&wl->mutex); | 638 | mutex_unlock(&wl->mutex); |
636 | } | 639 | } |
@@ -766,8 +769,8 @@ void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid) | |||
766 | wl1271_handle_tx_low_watermark(wl); | 769 | wl1271_handle_tx_low_watermark(wl); |
767 | } | 770 | } |
768 | 771 | ||
769 | /* caller must hold wl->mutex */ | 772 | /* caller must hold wl->mutex and TX must be stopped */ |
770 | void wl1271_tx_reset(struct wl1271 *wl) | 773 | void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues) |
771 | { | 774 | { |
772 | int i; | 775 | int i; |
773 | struct sk_buff *skb; | 776 | struct sk_buff *skb; |
@@ -803,8 +806,10 @@ void wl1271_tx_reset(struct wl1271 *wl) | |||
803 | /* | 806 | /* |
804 | * Make sure the driver is at a consistent state, in case this | 807 | * Make sure the driver is at a consistent state, in case this |
805 | * function is called from a context other than interface removal. | 808 | * function is called from a context other than interface removal. |
809 | * This call will always wake the TX queues. | ||
806 | */ | 810 | */ |
807 | wl1271_handle_tx_low_watermark(wl); | 811 | if (reset_tx_queues) |
812 | wl1271_handle_tx_low_watermark(wl); | ||
808 | 813 | ||
809 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) { | 814 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) { |
810 | if (wl->tx_frames[i] == NULL) | 815 | if (wl->tx_frames[i] == NULL) |
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index fc7835c4cf6..832f9258d67 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h | |||
@@ -185,7 +185,7 @@ static inline int wl1271_tx_get_queue(int queue) | |||
185 | void wl1271_tx_work(struct work_struct *work); | 185 | void wl1271_tx_work(struct work_struct *work); |
186 | void wl1271_tx_work_locked(struct wl1271 *wl); | 186 | void wl1271_tx_work_locked(struct wl1271 *wl); |
187 | void wl1271_tx_complete(struct wl1271 *wl); | 187 | void wl1271_tx_complete(struct wl1271 *wl); |
188 | void wl1271_tx_reset(struct wl1271 *wl); | 188 | void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues); |
189 | void wl1271_tx_flush(struct wl1271 *wl); | 189 | void wl1271_tx_flush(struct wl1271 *wl); |
190 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); | 190 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); |
191 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); | 191 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); |
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 7c521af58e7..b7601438eca 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h | |||
@@ -172,6 +172,7 @@ extern u32 wl12xx_debug_level; | |||
172 | #define WL1271_PS_STA_MAX_BLOCKS (2 * 9) | 172 | #define WL1271_PS_STA_MAX_BLOCKS (2 * 9) |
173 | 173 | ||
174 | #define WL1271_AP_BSS_INDEX 0 | 174 | #define WL1271_AP_BSS_INDEX 0 |
175 | #define WL1271_AP_DEF_INACTIV_SEC 300 | ||
175 | #define WL1271_AP_DEF_BEACON_EXP 20 | 176 | #define WL1271_AP_DEF_BEACON_EXP 20 |
176 | 177 | ||
177 | #define ACX_TX_DESCRIPTORS 32 | 178 | #define ACX_TX_DESCRIPTORS 32 |
@@ -345,6 +346,7 @@ enum wl12xx_flags { | |||
345 | WL1271_FLAG_TX_QUEUE_STOPPED, | 346 | WL1271_FLAG_TX_QUEUE_STOPPED, |
346 | WL1271_FLAG_TX_PENDING, | 347 | WL1271_FLAG_TX_PENDING, |
347 | WL1271_FLAG_IN_ELP, | 348 | WL1271_FLAG_IN_ELP, |
349 | WL1271_FLAG_ELP_REQUESTED, | ||
348 | WL1271_FLAG_PSM, | 350 | WL1271_FLAG_PSM, |
349 | WL1271_FLAG_PSM_REQUESTED, | 351 | WL1271_FLAG_PSM_REQUESTED, |
350 | WL1271_FLAG_IRQ_RUNNING, | 352 | WL1271_FLAG_IRQ_RUNNING, |