diff options
Diffstat (limited to 'drivers/net/wireless/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 | 111 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/debugfs.c | 240 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/event.c | 70 | ||||
-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 | 492 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/ps.c | 30 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/ps.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/rx.c | 36 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/scan.c | 243 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/scan.h | 114 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/sdio.c | 64 | ||||
-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 | 14 |
20 files changed, 1578 insertions, 294 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..b07f8b7e5f1 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c | |||
@@ -479,11 +479,11 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
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; | 482 | PERIODIC_SCAN_REPORT_EVENT_ID | |
483 | PERIODIC_SCAN_COMPLETE_EVENT_ID; | ||
483 | 484 | ||
484 | if (wl->bss_type == BSS_TYPE_AP_BSS) | 485 | if (wl->bss_type == BSS_TYPE_AP_BSS) |
485 | wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID | | 486 | wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID; |
486 | INACTIVE_STA_EVENT_ID; | ||
487 | else | 487 | else |
488 | wl->event_mask |= DUMMY_PACKET_EVENT_ID; | 488 | wl->event_mask |= DUMMY_PACKET_EVENT_ID; |
489 | 489 | ||
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 69d24f35cd9..42935ac7266 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 e3de91528de..1ab6c86aac4 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 | */ | ||
691 | u8 max_tx_retries; | ||
692 | |||
693 | /* | ||
694 | * AP-mode - after this number of seconds a connected station is | ||
695 | * considered inactive. | ||
696 | */ | 716 | */ |
697 | u16 ap_aging_period; | 717 | u16 ap_max_tx_retries; |
698 | 718 | ||
699 | /* | 719 | /* |
700 | * Configuration for TID parameters. | 720 | * Configuration for TID parameters. |
@@ -1127,6 +1147,26 @@ struct conf_scan_settings { | |||
1127 | 1147 | ||
1128 | }; | 1148 | }; |
1129 | 1149 | ||
1150 | struct conf_sched_scan_settings { | ||
1151 | /* minimum time to wait on the channel for active scans (in TUs) */ | ||
1152 | u16 min_dwell_time_active; | ||
1153 | |||
1154 | /* maximum time to wait on the channel for active scans (in TUs) */ | ||
1155 | u16 max_dwell_time_active; | ||
1156 | |||
1157 | /* time to wait on the channel for passive scans (in TUs) */ | ||
1158 | u32 dwell_time_passive; | ||
1159 | |||
1160 | /* number of probe requests to send on each channel in active scans */ | ||
1161 | u8 num_probe_reqs; | ||
1162 | |||
1163 | /* RSSI threshold to be used for filtering */ | ||
1164 | s8 rssi_threshold; | ||
1165 | |||
1166 | /* SNR threshold to be used for filtering */ | ||
1167 | s8 snr_threshold; | ||
1168 | }; | ||
1169 | |||
1130 | /* these are number of channels on the band divided by two, rounded up */ | 1170 | /* these are number of channels on the band divided by two, rounded up */ |
1131 | #define CONF_TX_PWR_COMPENSATION_LEN_2 7 | 1171 | #define CONF_TX_PWR_COMPENSATION_LEN_2 7 |
1132 | #define CONF_TX_PWR_COMPENSATION_LEN_5 18 | 1172 | #define CONF_TX_PWR_COMPENSATION_LEN_5 18 |
@@ -1192,6 +1232,19 @@ struct conf_memory_settings { | |||
1192 | u8 tx_min; | 1232 | u8 tx_min; |
1193 | }; | 1233 | }; |
1194 | 1234 | ||
1235 | struct conf_fm_coex { | ||
1236 | u8 enable; | ||
1237 | u8 swallow_period; | ||
1238 | u8 n_divider_fref_set_1; | ||
1239 | u8 n_divider_fref_set_2; | ||
1240 | u16 m_divider_fref_set_1; | ||
1241 | u16 m_divider_fref_set_2; | ||
1242 | u32 coex_pll_stabilization_time; | ||
1243 | u16 ldo_stabilization_time; | ||
1244 | u8 fm_disturbed_band_margin; | ||
1245 | u8 swallow_clk_diff; | ||
1246 | }; | ||
1247 | |||
1195 | struct conf_drv_settings { | 1248 | struct conf_drv_settings { |
1196 | struct conf_sg_settings sg; | 1249 | struct conf_sg_settings sg; |
1197 | struct conf_rx_settings rx; | 1250 | struct conf_rx_settings rx; |
@@ -1201,10 +1254,12 @@ struct conf_drv_settings { | |||
1201 | struct conf_pm_config_settings pm_config; | 1254 | struct conf_pm_config_settings pm_config; |
1202 | struct conf_roam_trigger_settings roam_trigger; | 1255 | struct conf_roam_trigger_settings roam_trigger; |
1203 | struct conf_scan_settings scan; | 1256 | struct conf_scan_settings scan; |
1257 | struct conf_sched_scan_settings sched_scan; | ||
1204 | struct conf_rf_settings rf; | 1258 | struct conf_rf_settings rf; |
1205 | struct conf_ht_setting ht; | 1259 | struct conf_ht_setting ht; |
1206 | struct conf_memory_settings mem_wl127x; | 1260 | struct conf_memory_settings mem_wl127x; |
1207 | struct conf_memory_settings mem_wl128x; | 1261 | struct conf_memory_settings mem_wl128x; |
1262 | struct conf_fm_coex fm_coex; | ||
1208 | u8 hci_io_ds; | 1263 | u8 hci_io_ds; |
1209 | }; | 1264 | }; |
1210 | 1265 | ||
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 70ab1986788..f1f8df9b6cd 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c | |||
@@ -291,6 +291,242 @@ 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 | DRIVER_STATE_PRINT_INT(sched_scanning); | ||
381 | |||
382 | #undef DRIVER_STATE_PRINT_INT | ||
383 | #undef DRIVER_STATE_PRINT_LONG | ||
384 | #undef DRIVER_STATE_PRINT_HEX | ||
385 | #undef DRIVER_STATE_PRINT_LHEX | ||
386 | #undef DRIVER_STATE_PRINT_STR | ||
387 | #undef DRIVER_STATE_PRINT | ||
388 | |||
389 | mutex_unlock(&wl->mutex); | ||
390 | |||
391 | return simple_read_from_buffer(user_buf, count, ppos, buf, res); | ||
392 | } | ||
393 | |||
394 | static const struct file_operations driver_state_ops = { | ||
395 | .read = driver_state_read, | ||
396 | .open = wl1271_open_file_generic, | ||
397 | .llseek = default_llseek, | ||
398 | }; | ||
399 | |||
400 | static ssize_t dtim_interval_read(struct file *file, char __user *user_buf, | ||
401 | size_t count, loff_t *ppos) | ||
402 | { | ||
403 | struct wl1271 *wl = file->private_data; | ||
404 | u8 value; | ||
405 | |||
406 | if (wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_DTIM || | ||
407 | wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_N_DTIM) | ||
408 | value = wl->conf.conn.listen_interval; | ||
409 | else | ||
410 | value = 0; | ||
411 | |||
412 | return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value); | ||
413 | } | ||
414 | |||
415 | static ssize_t dtim_interval_write(struct file *file, | ||
416 | const char __user *user_buf, | ||
417 | size_t count, loff_t *ppos) | ||
418 | { | ||
419 | struct wl1271 *wl = file->private_data; | ||
420 | char buf[10]; | ||
421 | size_t len; | ||
422 | unsigned long value; | ||
423 | int ret; | ||
424 | |||
425 | len = min(count, sizeof(buf) - 1); | ||
426 | if (copy_from_user(buf, user_buf, len)) | ||
427 | return -EFAULT; | ||
428 | buf[len] = '\0'; | ||
429 | |||
430 | ret = kstrtoul(buf, 0, &value); | ||
431 | if (ret < 0) { | ||
432 | wl1271_warning("illegal value for dtim_interval"); | ||
433 | return -EINVAL; | ||
434 | } | ||
435 | |||
436 | if (value < 1 || value > 10) { | ||
437 | wl1271_warning("dtim value is not in valid range"); | ||
438 | return -ERANGE; | ||
439 | } | ||
440 | |||
441 | mutex_lock(&wl->mutex); | ||
442 | |||
443 | wl->conf.conn.listen_interval = value; | ||
444 | /* for some reason there are different event types for 1 and >1 */ | ||
445 | if (value == 1) | ||
446 | wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_DTIM; | ||
447 | else | ||
448 | wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM; | ||
449 | |||
450 | /* | ||
451 | * we don't reconfigure ACX_WAKE_UP_CONDITIONS now, so it will only | ||
452 | * take effect on the next time we enter psm. | ||
453 | */ | ||
454 | mutex_unlock(&wl->mutex); | ||
455 | return count; | ||
456 | } | ||
457 | |||
458 | static const struct file_operations dtim_interval_ops = { | ||
459 | .read = dtim_interval_read, | ||
460 | .write = dtim_interval_write, | ||
461 | .open = wl1271_open_file_generic, | ||
462 | .llseek = default_llseek, | ||
463 | }; | ||
464 | |||
465 | static ssize_t beacon_interval_read(struct file *file, char __user *user_buf, | ||
466 | size_t count, loff_t *ppos) | ||
467 | { | ||
468 | struct wl1271 *wl = file->private_data; | ||
469 | u8 value; | ||
470 | |||
471 | if (wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_BEACON || | ||
472 | wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_N_BEACONS) | ||
473 | value = wl->conf.conn.listen_interval; | ||
474 | else | ||
475 | value = 0; | ||
476 | |||
477 | return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value); | ||
478 | } | ||
479 | |||
480 | static ssize_t beacon_interval_write(struct file *file, | ||
481 | const char __user *user_buf, | ||
482 | size_t count, loff_t *ppos) | ||
483 | { | ||
484 | struct wl1271 *wl = file->private_data; | ||
485 | char buf[10]; | ||
486 | size_t len; | ||
487 | unsigned long value; | ||
488 | int ret; | ||
489 | |||
490 | len = min(count, sizeof(buf) - 1); | ||
491 | if (copy_from_user(buf, user_buf, len)) | ||
492 | return -EFAULT; | ||
493 | buf[len] = '\0'; | ||
494 | |||
495 | ret = kstrtoul(buf, 0, &value); | ||
496 | if (ret < 0) { | ||
497 | wl1271_warning("illegal value for beacon_interval"); | ||
498 | return -EINVAL; | ||
499 | } | ||
500 | |||
501 | if (value < 1 || value > 255) { | ||
502 | wl1271_warning("beacon interval value is not in valid range"); | ||
503 | return -ERANGE; | ||
504 | } | ||
505 | |||
506 | mutex_lock(&wl->mutex); | ||
507 | |||
508 | wl->conf.conn.listen_interval = value; | ||
509 | /* for some reason there are different event types for 1 and >1 */ | ||
510 | if (value == 1) | ||
511 | wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_BEACON; | ||
512 | else | ||
513 | wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_N_BEACONS; | ||
514 | |||
515 | /* | ||
516 | * we don't reconfigure ACX_WAKE_UP_CONDITIONS now, so it will only | ||
517 | * take effect on the next time we enter psm. | ||
518 | */ | ||
519 | mutex_unlock(&wl->mutex); | ||
520 | return count; | ||
521 | } | ||
522 | |||
523 | static const struct file_operations beacon_interval_ops = { | ||
524 | .read = beacon_interval_read, | ||
525 | .write = beacon_interval_write, | ||
526 | .open = wl1271_open_file_generic, | ||
527 | .llseek = default_llseek, | ||
528 | }; | ||
529 | |||
294 | static int wl1271_debugfs_add_files(struct wl1271 *wl, | 530 | static int wl1271_debugfs_add_files(struct wl1271 *wl, |
295 | struct dentry *rootdir) | 531 | struct dentry *rootdir) |
296 | { | 532 | { |
@@ -399,6 +635,10 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl, | |||
399 | DEBUGFS_ADD(excessive_retries, rootdir); | 635 | DEBUGFS_ADD(excessive_retries, rootdir); |
400 | 636 | ||
401 | DEBUGFS_ADD(gpio_power, rootdir); | 637 | DEBUGFS_ADD(gpio_power, rootdir); |
638 | DEBUGFS_ADD(start_recovery, rootdir); | ||
639 | DEBUGFS_ADD(driver_state, rootdir); | ||
640 | DEBUGFS_ADD(dtim_interval, rootdir); | ||
641 | DEBUGFS_ADD(beacon_interval, rootdir); | ||
402 | 642 | ||
403 | return 0; | 643 | return 0; |
404 | 644 | ||
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index d7be3aec6fc..c3c554cd658 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c | |||
@@ -135,6 +135,13 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
135 | 135 | ||
136 | /* enable beacon early termination */ | 136 | /* enable beacon early termination */ |
137 | ret = wl1271_acx_bet_enable(wl, true); | 137 | ret = wl1271_acx_bet_enable(wl, true); |
138 | if (ret < 0) | ||
139 | break; | ||
140 | |||
141 | if (wl->ps_compl) { | ||
142 | complete(wl->ps_compl); | ||
143 | wl->ps_compl = NULL; | ||
144 | } | ||
138 | break; | 145 | break; |
139 | default: | 146 | default: |
140 | break; | 147 | break; |
@@ -174,8 +181,6 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
174 | u32 vector; | 181 | u32 vector; |
175 | bool beacon_loss = false; | 182 | bool beacon_loss = false; |
176 | bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); | 183 | bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); |
177 | bool disconnect_sta = false; | ||
178 | unsigned long sta_bitmap = 0; | ||
179 | 184 | ||
180 | wl1271_event_mbox_dump(mbox); | 185 | wl1271_event_mbox_dump(mbox); |
181 | 186 | ||
@@ -190,6 +195,22 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
190 | wl1271_scan_stm(wl); | 195 | wl1271_scan_stm(wl); |
191 | } | 196 | } |
192 | 197 | ||
198 | if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) { | ||
199 | wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_REPORT_EVENT " | ||
200 | "(status 0x%0x)", mbox->scheduled_scan_status); | ||
201 | |||
202 | wl1271_scan_sched_scan_results(wl); | ||
203 | } | ||
204 | |||
205 | if (vector & PERIODIC_SCAN_COMPLETE_EVENT_ID) { | ||
206 | wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_COMPLETE_EVENT " | ||
207 | "(status 0x%0x)", mbox->scheduled_scan_status); | ||
208 | if (wl->sched_scanning) { | ||
209 | wl1271_scan_sched_scan_stop(wl); | ||
210 | ieee80211_sched_scan_stopped(wl->hw); | ||
211 | } | ||
212 | } | ||
213 | |||
193 | /* disable dynamic PS when requested by the firmware */ | 214 | /* disable dynamic PS when requested by the firmware */ |
194 | if (vector & SOFT_GEMINI_SENSE_EVENT_ID && | 215 | if (vector & SOFT_GEMINI_SENSE_EVENT_ID && |
195 | wl->bss_type == BSS_TYPE_STA_BSS) { | 216 | wl->bss_type == BSS_TYPE_STA_BSS) { |
@@ -237,54 +258,9 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
237 | wl1271_tx_dummy_packet(wl); | 258 | wl1271_tx_dummy_packet(wl); |
238 | } | 259 | } |
239 | 260 | ||
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) | 261 | if (wl->vif && beacon_loss) |
262 | ieee80211_connection_loss(wl->vif); | 262 | ieee80211_connection_loss(wl->vif); |
263 | 263 | ||
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; | 264 | return 0; |
289 | } | 265 | } |
290 | 266 | ||
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..610be03a198 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] = { |
@@ -241,12 +257,16 @@ static struct conf_drv_settings default_conf = { | |||
241 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | 257 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, |
242 | .listen_interval = 1, | 258 | .listen_interval = 1, |
243 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, | 259 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, |
244 | .bcn_filt_ie_count = 1, | 260 | .bcn_filt_ie_count = 2, |
245 | .bcn_filt_ie = { | 261 | .bcn_filt_ie = { |
246 | [0] = { | 262 | [0] = { |
247 | .ie = WLAN_EID_CHANNEL_SWITCH, | 263 | .ie = WLAN_EID_CHANNEL_SWITCH, |
248 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, | 264 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, |
249 | } | 265 | }, |
266 | [1] = { | ||
267 | .ie = WLAN_EID_HT_INFORMATION, | ||
268 | .rule = CONF_BCN_RULE_PASS_ON_CHANGE, | ||
269 | }, | ||
250 | }, | 270 | }, |
251 | .synch_fail_thold = 10, | 271 | .synch_fail_thold = 10, |
252 | .bss_lose_timeout = 100, | 272 | .bss_lose_timeout = 100, |
@@ -258,7 +278,7 @@ static struct conf_drv_settings default_conf = { | |||
258 | .bet_enable = CONF_BET_MODE_ENABLE, | 278 | .bet_enable = CONF_BET_MODE_ENABLE, |
259 | .bet_max_consecutive = 50, | 279 | .bet_max_consecutive = 50, |
260 | .psm_entry_retries = 5, | 280 | .psm_entry_retries = 5, |
261 | .psm_exit_retries = 255, | 281 | .psm_exit_retries = 16, |
262 | .psm_entry_nullfunc_retries = 3, | 282 | .psm_entry_nullfunc_retries = 3, |
263 | .psm_entry_hangover_period = 1, | 283 | .psm_entry_hangover_period = 1, |
264 | .keep_alive_interval = 55000, | 284 | .keep_alive_interval = 55000, |
@@ -286,6 +306,15 @@ static struct conf_drv_settings default_conf = { | |||
286 | .max_dwell_time_passive = 100000, | 306 | .max_dwell_time_passive = 100000, |
287 | .num_probe_reqs = 2, | 307 | .num_probe_reqs = 2, |
288 | }, | 308 | }, |
309 | .sched_scan = { | ||
310 | /* sched_scan requires dwell times in TU instead of TU/1000 */ | ||
311 | .min_dwell_time_active = 8, | ||
312 | .max_dwell_time_active = 30, | ||
313 | .dwell_time_passive = 100, | ||
314 | .num_probe_reqs = 2, | ||
315 | .rssi_threshold = -90, | ||
316 | .snr_threshold = 0, | ||
317 | }, | ||
289 | .rf = { | 318 | .rf = { |
290 | .tx_per_channel_power_compensation_2 = { | 319 | .tx_per_channel_power_compensation_2 = { |
291 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 320 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -305,7 +334,7 @@ static struct conf_drv_settings default_conf = { | |||
305 | .ssid_profiles = 1, | 334 | .ssid_profiles = 1, |
306 | .rx_block_num = 70, | 335 | .rx_block_num = 70, |
307 | .tx_min_block_num = 40, | 336 | .tx_min_block_num = 40, |
308 | .dynamic_memory = 0, | 337 | .dynamic_memory = 1, |
309 | .min_req_tx_blocks = 100, | 338 | .min_req_tx_blocks = 100, |
310 | .min_req_rx_blocks = 22, | 339 | .min_req_rx_blocks = 22, |
311 | .tx_min = 27, | 340 | .tx_min = 27, |
@@ -320,10 +349,23 @@ static struct conf_drv_settings default_conf = { | |||
320 | .min_req_rx_blocks = 22, | 349 | .min_req_rx_blocks = 22, |
321 | .tx_min = 27, | 350 | .tx_min = 27, |
322 | }, | 351 | }, |
352 | .fm_coex = { | ||
353 | .enable = true, | ||
354 | .swallow_period = 5, | ||
355 | .n_divider_fref_set_1 = 0xff, /* default */ | ||
356 | .n_divider_fref_set_2 = 12, | ||
357 | .m_divider_fref_set_1 = 148, | ||
358 | .m_divider_fref_set_2 = 0xffff, /* default */ | ||
359 | .coex_pll_stabilization_time = 0xffffffff, /* default */ | ||
360 | .ldo_stabilization_time = 0xffff, /* default */ | ||
361 | .fm_disturbed_band_margin = 0xff, /* default */ | ||
362 | .swallow_clk_diff = 0xff, /* default */ | ||
363 | }, | ||
323 | .hci_io_ds = HCI_IO_DS_6MA, | 364 | .hci_io_ds = HCI_IO_DS_6MA, |
324 | }; | 365 | }; |
325 | 366 | ||
326 | static void __wl1271_op_remove_interface(struct wl1271 *wl); | 367 | static void __wl1271_op_remove_interface(struct wl1271 *wl, |
368 | bool reset_tx_queues); | ||
327 | static void wl1271_free_ap_keys(struct wl1271 *wl); | 369 | static void wl1271_free_ap_keys(struct wl1271 *wl); |
328 | 370 | ||
329 | 371 | ||
@@ -508,6 +550,11 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
508 | if (ret < 0) | 550 | if (ret < 0) |
509 | goto out_free_memmap; | 551 | goto out_free_memmap; |
510 | 552 | ||
553 | /* FM WLAN coexistence */ | ||
554 | ret = wl1271_acx_fm_coex(wl); | ||
555 | if (ret < 0) | ||
556 | goto out_free_memmap; | ||
557 | |||
511 | /* Energy detection */ | 558 | /* Energy detection */ |
512 | ret = wl1271_init_energy_detection(wl); | 559 | ret = wl1271_init_energy_detection(wl); |
513 | if (ret < 0) | 560 | if (ret < 0) |
@@ -932,15 +979,30 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
932 | if (wl->state != WL1271_STATE_ON) | 979 | if (wl->state != WL1271_STATE_ON) |
933 | goto out; | 980 | goto out; |
934 | 981 | ||
935 | wl1271_info("Hardware recovery in progress."); | 982 | wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x", |
983 | wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4)); | ||
936 | 984 | ||
937 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | 985 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) |
938 | ieee80211_connection_loss(wl->vif); | 986 | ieee80211_connection_loss(wl->vif); |
939 | 987 | ||
988 | /* Prevent spurious TX during FW restart */ | ||
989 | ieee80211_stop_queues(wl->hw); | ||
990 | |||
991 | if (wl->sched_scanning) { | ||
992 | ieee80211_sched_scan_stopped(wl->hw); | ||
993 | wl->sched_scanning = false; | ||
994 | } | ||
995 | |||
940 | /* reboot the chipset */ | 996 | /* reboot the chipset */ |
941 | __wl1271_op_remove_interface(wl); | 997 | __wl1271_op_remove_interface(wl, false); |
942 | ieee80211_restart_hw(wl->hw); | 998 | ieee80211_restart_hw(wl->hw); |
943 | 999 | ||
1000 | /* | ||
1001 | * Its safe to enable TX now - the queues are stopped after a request | ||
1002 | * to restart the HW. | ||
1003 | */ | ||
1004 | ieee80211_wake_queues(wl->hw); | ||
1005 | |||
944 | out: | 1006 | out: |
945 | mutex_unlock(&wl->mutex); | 1007 | mutex_unlock(&wl->mutex); |
946 | } | 1008 | } |
@@ -1011,6 +1073,10 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
1011 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", | 1073 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", |
1012 | wl->chip.id); | 1074 | wl->chip.id); |
1013 | 1075 | ||
1076 | /* end-of-transaction flag should be set in wl127x AP mode */ | ||
1077 | if (wl->bss_type == BSS_TYPE_AP_BSS) | ||
1078 | wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION; | ||
1079 | |||
1014 | ret = wl1271_setup(wl); | 1080 | ret = wl1271_setup(wl); |
1015 | if (ret < 0) | 1081 | if (ret < 0) |
1016 | goto out; | 1082 | goto out; |
@@ -1273,7 +1339,7 @@ static struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl) | |||
1273 | skb->priority = WL1271_TID_MGMT; | 1339 | skb->priority = WL1271_TID_MGMT; |
1274 | 1340 | ||
1275 | /* Initialize all fields that might be used */ | 1341 | /* Initialize all fields that might be used */ |
1276 | skb->queue_mapping = 0; | 1342 | skb_set_queue_mapping(skb, 0); |
1277 | memset(IEEE80211_SKB_CB(skb), 0, sizeof(struct ieee80211_tx_info)); | 1343 | memset(IEEE80211_SKB_CB(skb), 0, sizeof(struct ieee80211_tx_info)); |
1278 | 1344 | ||
1279 | return skb; | 1345 | return skb; |
@@ -1284,6 +1350,150 @@ static struct notifier_block wl1271_dev_notifier = { | |||
1284 | .notifier_call = wl1271_dev_notify, | 1350 | .notifier_call = wl1271_dev_notify, |
1285 | }; | 1351 | }; |
1286 | 1352 | ||
1353 | static int wl1271_configure_suspend(struct wl1271 *wl) | ||
1354 | { | ||
1355 | int ret; | ||
1356 | |||
1357 | if (wl->bss_type != BSS_TYPE_STA_BSS) | ||
1358 | return 0; | ||
1359 | |||
1360 | mutex_lock(&wl->mutex); | ||
1361 | |||
1362 | ret = wl1271_ps_elp_wakeup(wl); | ||
1363 | if (ret < 0) | ||
1364 | goto out_unlock; | ||
1365 | |||
1366 | /* enter psm if needed*/ | ||
1367 | if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) { | ||
1368 | DECLARE_COMPLETION_ONSTACK(compl); | ||
1369 | |||
1370 | wl->ps_compl = &compl; | ||
1371 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, | ||
1372 | wl->basic_rate, true); | ||
1373 | if (ret < 0) | ||
1374 | goto out_sleep; | ||
1375 | |||
1376 | /* we must unlock here so we will be able to get events */ | ||
1377 | wl1271_ps_elp_sleep(wl); | ||
1378 | mutex_unlock(&wl->mutex); | ||
1379 | |||
1380 | ret = wait_for_completion_timeout( | ||
1381 | &compl, msecs_to_jiffies(WL1271_PS_COMPLETE_TIMEOUT)); | ||
1382 | if (ret <= 0) { | ||
1383 | wl1271_warning("couldn't enter ps mode!"); | ||
1384 | ret = -EBUSY; | ||
1385 | goto out; | ||
1386 | } | ||
1387 | |||
1388 | /* take mutex again, and wakeup */ | ||
1389 | mutex_lock(&wl->mutex); | ||
1390 | |||
1391 | ret = wl1271_ps_elp_wakeup(wl); | ||
1392 | if (ret < 0) | ||
1393 | goto out_unlock; | ||
1394 | } | ||
1395 | out_sleep: | ||
1396 | wl1271_ps_elp_sleep(wl); | ||
1397 | out_unlock: | ||
1398 | mutex_unlock(&wl->mutex); | ||
1399 | out: | ||
1400 | return ret; | ||
1401 | |||
1402 | } | ||
1403 | |||
1404 | static void wl1271_configure_resume(struct wl1271 *wl) | ||
1405 | { | ||
1406 | int ret; | ||
1407 | |||
1408 | if (wl->bss_type != BSS_TYPE_STA_BSS) | ||
1409 | return; | ||
1410 | |||
1411 | mutex_lock(&wl->mutex); | ||
1412 | ret = wl1271_ps_elp_wakeup(wl); | ||
1413 | if (ret < 0) | ||
1414 | goto out; | ||
1415 | |||
1416 | /* exit psm if it wasn't configured */ | ||
1417 | if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) | ||
1418 | wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, | ||
1419 | wl->basic_rate, true); | ||
1420 | |||
1421 | wl1271_ps_elp_sleep(wl); | ||
1422 | out: | ||
1423 | mutex_unlock(&wl->mutex); | ||
1424 | } | ||
1425 | |||
1426 | static int wl1271_op_suspend(struct ieee80211_hw *hw, | ||
1427 | struct cfg80211_wowlan *wow) | ||
1428 | { | ||
1429 | struct wl1271 *wl = hw->priv; | ||
1430 | wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); | ||
1431 | wl->wow_enabled = !!wow; | ||
1432 | if (wl->wow_enabled) { | ||
1433 | int ret; | ||
1434 | ret = wl1271_configure_suspend(wl); | ||
1435 | if (ret < 0) { | ||
1436 | wl1271_warning("couldn't prepare device to suspend"); | ||
1437 | return ret; | ||
1438 | } | ||
1439 | /* flush any remaining work */ | ||
1440 | wl1271_debug(DEBUG_MAC80211, "flushing remaining works"); | ||
1441 | flush_delayed_work(&wl->scan_complete_work); | ||
1442 | |||
1443 | /* | ||
1444 | * disable and re-enable interrupts in order to flush | ||
1445 | * the threaded_irq | ||
1446 | */ | ||
1447 | wl1271_disable_interrupts(wl); | ||
1448 | |||
1449 | /* | ||
1450 | * set suspended flag to avoid triggering a new threaded_irq | ||
1451 | * work. no need for spinlock as interrupts are disabled. | ||
1452 | */ | ||
1453 | set_bit(WL1271_FLAG_SUSPENDED, &wl->flags); | ||
1454 | |||
1455 | wl1271_enable_interrupts(wl); | ||
1456 | flush_work(&wl->tx_work); | ||
1457 | flush_delayed_work(&wl->pspoll_work); | ||
1458 | flush_delayed_work(&wl->elp_work); | ||
1459 | } | ||
1460 | return 0; | ||
1461 | } | ||
1462 | |||
1463 | static int wl1271_op_resume(struct ieee80211_hw *hw) | ||
1464 | { | ||
1465 | struct wl1271 *wl = hw->priv; | ||
1466 | wl1271_debug(DEBUG_MAC80211, "mac80211 resume wow=%d", | ||
1467 | wl->wow_enabled); | ||
1468 | |||
1469 | /* | ||
1470 | * re-enable irq_work enqueuing, and call irq_work directly if | ||
1471 | * there is a pending work. | ||
1472 | */ | ||
1473 | if (wl->wow_enabled) { | ||
1474 | struct wl1271 *wl = hw->priv; | ||
1475 | unsigned long flags; | ||
1476 | bool run_irq_work = false; | ||
1477 | |||
1478 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
1479 | clear_bit(WL1271_FLAG_SUSPENDED, &wl->flags); | ||
1480 | if (test_and_clear_bit(WL1271_FLAG_PENDING_WORK, &wl->flags)) | ||
1481 | run_irq_work = true; | ||
1482 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
1483 | |||
1484 | if (run_irq_work) { | ||
1485 | wl1271_debug(DEBUG_MAC80211, | ||
1486 | "run postponed irq_work directly"); | ||
1487 | wl1271_irq(0, wl); | ||
1488 | wl1271_enable_interrupts(wl); | ||
1489 | } | ||
1490 | |||
1491 | wl1271_configure_resume(wl); | ||
1492 | } | ||
1493 | |||
1494 | return 0; | ||
1495 | } | ||
1496 | |||
1287 | static int wl1271_op_start(struct ieee80211_hw *hw) | 1497 | static int wl1271_op_start(struct ieee80211_hw *hw) |
1288 | { | 1498 | { |
1289 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); | 1499 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); |
@@ -1440,7 +1650,8 @@ out: | |||
1440 | return ret; | 1650 | return ret; |
1441 | } | 1651 | } |
1442 | 1652 | ||
1443 | static void __wl1271_op_remove_interface(struct wl1271 *wl) | 1653 | static void __wl1271_op_remove_interface(struct wl1271 *wl, |
1654 | bool reset_tx_queues) | ||
1444 | { | 1655 | { |
1445 | int i; | 1656 | int i; |
1446 | 1657 | ||
@@ -1486,7 +1697,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) | |||
1486 | mutex_lock(&wl->mutex); | 1697 | mutex_lock(&wl->mutex); |
1487 | 1698 | ||
1488 | /* let's notify MAC80211 about the remaining pending TX frames */ | 1699 | /* let's notify MAC80211 about the remaining pending TX frames */ |
1489 | wl1271_tx_reset(wl); | 1700 | wl1271_tx_reset(wl, reset_tx_queues); |
1490 | wl1271_power_off(wl); | 1701 | wl1271_power_off(wl); |
1491 | 1702 | ||
1492 | memset(wl->bssid, 0, ETH_ALEN); | 1703 | memset(wl->bssid, 0, ETH_ALEN); |
@@ -1514,6 +1725,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) | |||
1514 | memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); | 1725 | memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); |
1515 | wl->ap_fw_ps_map = 0; | 1726 | wl->ap_fw_ps_map = 0; |
1516 | wl->ap_ps_map = 0; | 1727 | wl->ap_ps_map = 0; |
1728 | wl->sched_scanning = false; | ||
1517 | 1729 | ||
1518 | /* | 1730 | /* |
1519 | * this is performed after the cancel_work calls and the associated | 1731 | * this is performed after the cancel_work calls and the associated |
@@ -1547,7 +1759,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
1547 | */ | 1759 | */ |
1548 | if (wl->vif) { | 1760 | if (wl->vif) { |
1549 | WARN_ON(wl->vif != vif); | 1761 | WARN_ON(wl->vif != vif); |
1550 | __wl1271_op_remove_interface(wl); | 1762 | __wl1271_op_remove_interface(wl, true); |
1551 | } | 1763 | } |
1552 | 1764 | ||
1553 | mutex_unlock(&wl->mutex); | 1765 | mutex_unlock(&wl->mutex); |
@@ -1716,6 +1928,13 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle) | |||
1716 | wl->session_counter++; | 1928 | wl->session_counter++; |
1717 | if (wl->session_counter >= SESSION_COUNTER_MAX) | 1929 | if (wl->session_counter >= SESSION_COUNTER_MAX) |
1718 | wl->session_counter = 0; | 1930 | wl->session_counter = 0; |
1931 | |||
1932 | /* The current firmware only supports sched_scan in idle */ | ||
1933 | if (wl->sched_scanning) { | ||
1934 | wl1271_scan_sched_scan_stop(wl); | ||
1935 | ieee80211_sched_scan_stopped(wl->hw); | ||
1936 | } | ||
1937 | |||
1719 | ret = wl1271_dummy_join(wl); | 1938 | ret = wl1271_dummy_join(wl); |
1720 | if (ret < 0) | 1939 | if (ret < 0) |
1721 | goto out; | 1940 | goto out; |
@@ -2268,6 +2487,60 @@ out: | |||
2268 | return ret; | 2487 | return ret; |
2269 | } | 2488 | } |
2270 | 2489 | ||
2490 | static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw, | ||
2491 | struct ieee80211_vif *vif, | ||
2492 | struct cfg80211_sched_scan_request *req, | ||
2493 | struct ieee80211_sched_scan_ies *ies) | ||
2494 | { | ||
2495 | struct wl1271 *wl = hw->priv; | ||
2496 | int ret; | ||
2497 | |||
2498 | wl1271_debug(DEBUG_MAC80211, "wl1271_op_sched_scan_start"); | ||
2499 | |||
2500 | mutex_lock(&wl->mutex); | ||
2501 | |||
2502 | ret = wl1271_ps_elp_wakeup(wl); | ||
2503 | if (ret < 0) | ||
2504 | goto out; | ||
2505 | |||
2506 | ret = wl1271_scan_sched_scan_config(wl, req, ies); | ||
2507 | if (ret < 0) | ||
2508 | goto out_sleep; | ||
2509 | |||
2510 | ret = wl1271_scan_sched_scan_start(wl); | ||
2511 | if (ret < 0) | ||
2512 | goto out_sleep; | ||
2513 | |||
2514 | wl->sched_scanning = true; | ||
2515 | |||
2516 | out_sleep: | ||
2517 | wl1271_ps_elp_sleep(wl); | ||
2518 | out: | ||
2519 | mutex_unlock(&wl->mutex); | ||
2520 | return ret; | ||
2521 | } | ||
2522 | |||
2523 | static void wl1271_op_sched_scan_stop(struct ieee80211_hw *hw, | ||
2524 | struct ieee80211_vif *vif) | ||
2525 | { | ||
2526 | struct wl1271 *wl = hw->priv; | ||
2527 | int ret; | ||
2528 | |||
2529 | wl1271_debug(DEBUG_MAC80211, "wl1271_op_sched_scan_stop"); | ||
2530 | |||
2531 | mutex_lock(&wl->mutex); | ||
2532 | |||
2533 | ret = wl1271_ps_elp_wakeup(wl); | ||
2534 | if (ret < 0) | ||
2535 | goto out; | ||
2536 | |||
2537 | wl1271_scan_sched_scan_stop(wl); | ||
2538 | |||
2539 | wl1271_ps_elp_sleep(wl); | ||
2540 | out: | ||
2541 | mutex_unlock(&wl->mutex); | ||
2542 | } | ||
2543 | |||
2271 | static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value) | 2544 | static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value) |
2272 | { | 2545 | { |
2273 | struct wl1271 *wl = hw->priv; | 2546 | struct wl1271 *wl = hw->priv; |
@@ -2284,7 +2557,7 @@ static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value) | |||
2284 | if (ret < 0) | 2557 | if (ret < 0) |
2285 | goto out; | 2558 | goto out; |
2286 | 2559 | ||
2287 | ret = wl1271_acx_frag_threshold(wl, (u16)value); | 2560 | ret = wl1271_acx_frag_threshold(wl, value); |
2288 | if (ret < 0) | 2561 | if (ret < 0) |
2289 | wl1271_warning("wl1271_op_set_frag_threshold failed: %d", ret); | 2562 | wl1271_warning("wl1271_op_set_frag_threshold failed: %d", ret); |
2290 | 2563 | ||
@@ -2312,7 +2585,7 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | |||
2312 | if (ret < 0) | 2585 | if (ret < 0) |
2313 | goto out; | 2586 | goto out; |
2314 | 2587 | ||
2315 | ret = wl1271_acx_rts_threshold(wl, (u16) value); | 2588 | ret = wl1271_acx_rts_threshold(wl, value); |
2316 | if (ret < 0) | 2589 | if (ret < 0) |
2317 | wl1271_warning("wl1271_op_set_rts_threshold failed: %d", ret); | 2590 | wl1271_warning("wl1271_op_set_rts_threshold failed: %d", ret); |
2318 | 2591 | ||
@@ -2327,20 +2600,24 @@ out: | |||
2327 | static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, | 2600 | static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, |
2328 | int offset) | 2601 | int offset) |
2329 | { | 2602 | { |
2330 | u8 *ptr = skb->data + offset; | 2603 | u8 ssid_len; |
2604 | const u8 *ptr = cfg80211_find_ie(WLAN_EID_SSID, skb->data + offset, | ||
2605 | skb->len - offset); | ||
2331 | 2606 | ||
2332 | /* find the location of the ssid in the beacon */ | 2607 | if (!ptr) { |
2333 | while (ptr < skb->data + skb->len) { | 2608 | wl1271_error("No SSID in IEs!"); |
2334 | if (ptr[0] == WLAN_EID_SSID) { | 2609 | return -ENOENT; |
2335 | wl->ssid_len = ptr[1]; | ||
2336 | memcpy(wl->ssid, ptr+2, wl->ssid_len); | ||
2337 | return 0; | ||
2338 | } | ||
2339 | ptr += (ptr[1] + 2); | ||
2340 | } | 2610 | } |
2341 | 2611 | ||
2342 | wl1271_error("No SSID in IEs!\n"); | 2612 | ssid_len = ptr[1]; |
2343 | return -ENOENT; | 2613 | if (ssid_len > IEEE80211_MAX_SSID_LEN) { |
2614 | wl1271_error("SSID is too long!"); | ||
2615 | return -EINVAL; | ||
2616 | } | ||
2617 | |||
2618 | wl->ssid_len = ssid_len; | ||
2619 | memcpy(wl->ssid, ptr+2, ssid_len); | ||
2620 | return 0; | ||
2344 | } | 2621 | } |
2345 | 2622 | ||
2346 | static int wl1271_bss_erp_info_changed(struct wl1271 *wl, | 2623 | static int wl1271_bss_erp_info_changed(struct wl1271 *wl, |
@@ -2455,24 +2732,19 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, | |||
2455 | 2732 | ||
2456 | if ((changed & BSS_CHANGED_BASIC_RATES)) { | 2733 | if ((changed & BSS_CHANGED_BASIC_RATES)) { |
2457 | u32 rates = bss_conf->basic_rates; | 2734 | u32 rates = bss_conf->basic_rates; |
2458 | struct conf_tx_rate_class mgmt_rc; | ||
2459 | 2735 | ||
2460 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates); | 2736 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates); |
2461 | wl->basic_rate = wl1271_tx_min_rate_get(wl); | 2737 | wl->basic_rate = wl1271_tx_min_rate_get(wl); |
2462 | wl1271_debug(DEBUG_AP, "basic rates: 0x%x", | 2738 | |
2463 | wl->basic_rate_set); | 2739 | 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) { | 2740 | if (ret < 0) { |
2473 | wl1271_error("AP mgmt policy change failed %d", ret); | 2741 | wl1271_error("AP rate policy change failed %d", ret); |
2474 | goto out; | 2742 | goto out; |
2475 | } | 2743 | } |
2744 | |||
2745 | ret = wl1271_ap_init_templates(wl); | ||
2746 | if (ret < 0) | ||
2747 | goto out; | ||
2476 | } | 2748 | } |
2477 | 2749 | ||
2478 | ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, changed); | 2750 | ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, changed); |
@@ -2505,6 +2777,24 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, | |||
2505 | } | 2777 | } |
2506 | } | 2778 | } |
2507 | 2779 | ||
2780 | if (changed & BSS_CHANGED_IBSS) { | ||
2781 | wl1271_debug(DEBUG_ADHOC, "ibss_joined: %d", | ||
2782 | bss_conf->ibss_joined); | ||
2783 | |||
2784 | if (bss_conf->ibss_joined) { | ||
2785 | u32 rates = bss_conf->basic_rates; | ||
2786 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, | ||
2787 | rates); | ||
2788 | wl->basic_rate = wl1271_tx_min_rate_get(wl); | ||
2789 | |||
2790 | /* by default, use 11b rates */ | ||
2791 | wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES; | ||
2792 | ret = wl1271_acx_sta_rate_policies(wl); | ||
2793 | if (ret < 0) | ||
2794 | goto out; | ||
2795 | } | ||
2796 | } | ||
2797 | |||
2508 | ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed); | 2798 | ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed); |
2509 | if (ret < 0) | 2799 | if (ret < 0) |
2510 | goto out; | 2800 | goto out; |
@@ -2694,8 +2984,10 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
2694 | } | 2984 | } |
2695 | } else { | 2985 | } else { |
2696 | /* use defaults when not associated */ | 2986 | /* use defaults when not associated */ |
2987 | bool was_assoc = | ||
2988 | !!test_and_clear_bit(WL1271_FLAG_STA_ASSOCIATED, | ||
2989 | &wl->flags); | ||
2697 | clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags); | 2990 | clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags); |
2698 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | ||
2699 | wl->aid = 0; | 2991 | wl->aid = 0; |
2700 | 2992 | ||
2701 | /* free probe-request template */ | 2993 | /* free probe-request template */ |
@@ -2721,8 +3013,10 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
2721 | goto out; | 3013 | goto out; |
2722 | 3014 | ||
2723 | /* restore the bssid filter and go to dummy bssid */ | 3015 | /* restore the bssid filter and go to dummy bssid */ |
2724 | wl1271_unjoin(wl); | 3016 | if (was_assoc) { |
2725 | wl1271_dummy_join(wl); | 3017 | wl1271_unjoin(wl); |
3018 | wl1271_dummy_join(wl); | ||
3019 | } | ||
2726 | } | 3020 | } |
2727 | } | 3021 | } |
2728 | 3022 | ||
@@ -2954,12 +3248,6 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid) | |||
2954 | __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | 3248 | __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); |
2955 | } | 3249 | } |
2956 | 3250 | ||
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, | 3251 | static int wl1271_op_sta_add(struct ieee80211_hw *hw, |
2964 | struct ieee80211_vif *vif, | 3252 | struct ieee80211_vif *vif, |
2965 | struct ieee80211_sta *sta) | 3253 | struct ieee80211_sta *sta) |
@@ -3104,6 +3392,28 @@ out: | |||
3104 | return ret; | 3392 | return ret; |
3105 | } | 3393 | } |
3106 | 3394 | ||
3395 | static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) | ||
3396 | { | ||
3397 | struct wl1271 *wl = hw->priv; | ||
3398 | bool ret = false; | ||
3399 | |||
3400 | mutex_lock(&wl->mutex); | ||
3401 | |||
3402 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
3403 | goto out; | ||
3404 | |||
3405 | /* packets are considered pending if in the TX queue or the FW */ | ||
3406 | ret = (wl->tx_queue_count > 0) || (wl->tx_frames_cnt > 0); | ||
3407 | |||
3408 | /* the above is appropriate for STA mode for PS purposes */ | ||
3409 | WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); | ||
3410 | |||
3411 | out: | ||
3412 | mutex_unlock(&wl->mutex); | ||
3413 | |||
3414 | return ret; | ||
3415 | } | ||
3416 | |||
3107 | /* can't be const, mac80211 writes to this */ | 3417 | /* can't be const, mac80211 writes to this */ |
3108 | static struct ieee80211_rate wl1271_rates[] = { | 3418 | static struct ieee80211_rate wl1271_rates[] = { |
3109 | { .bitrate = 10, | 3419 | { .bitrate = 10, |
@@ -3340,12 +3650,16 @@ static const struct ieee80211_ops wl1271_ops = { | |||
3340 | .stop = wl1271_op_stop, | 3650 | .stop = wl1271_op_stop, |
3341 | .add_interface = wl1271_op_add_interface, | 3651 | .add_interface = wl1271_op_add_interface, |
3342 | .remove_interface = wl1271_op_remove_interface, | 3652 | .remove_interface = wl1271_op_remove_interface, |
3653 | .suspend = wl1271_op_suspend, | ||
3654 | .resume = wl1271_op_resume, | ||
3343 | .config = wl1271_op_config, | 3655 | .config = wl1271_op_config, |
3344 | .prepare_multicast = wl1271_op_prepare_multicast, | 3656 | .prepare_multicast = wl1271_op_prepare_multicast, |
3345 | .configure_filter = wl1271_op_configure_filter, | 3657 | .configure_filter = wl1271_op_configure_filter, |
3346 | .tx = wl1271_op_tx, | 3658 | .tx = wl1271_op_tx, |
3347 | .set_key = wl1271_op_set_key, | 3659 | .set_key = wl1271_op_set_key, |
3348 | .hw_scan = wl1271_op_hw_scan, | 3660 | .hw_scan = wl1271_op_hw_scan, |
3661 | .sched_scan_start = wl1271_op_sched_scan_start, | ||
3662 | .sched_scan_stop = wl1271_op_sched_scan_stop, | ||
3349 | .bss_info_changed = wl1271_op_bss_info_changed, | 3663 | .bss_info_changed = wl1271_op_bss_info_changed, |
3350 | .set_frag_threshold = wl1271_op_set_frag_threshold, | 3664 | .set_frag_threshold = wl1271_op_set_frag_threshold, |
3351 | .set_rts_threshold = wl1271_op_set_rts_threshold, | 3665 | .set_rts_threshold = wl1271_op_set_rts_threshold, |
@@ -3355,6 +3669,7 @@ static const struct ieee80211_ops wl1271_ops = { | |||
3355 | .sta_add = wl1271_op_sta_add, | 3669 | .sta_add = wl1271_op_sta_add, |
3356 | .sta_remove = wl1271_op_sta_remove, | 3670 | .sta_remove = wl1271_op_sta_remove, |
3357 | .ampdu_action = wl1271_op_ampdu_action, | 3671 | .ampdu_action = wl1271_op_ampdu_action, |
3672 | .tx_frames_pending = wl1271_tx_frames_pending, | ||
3358 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | 3673 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) |
3359 | }; | 3674 | }; |
3360 | 3675 | ||
@@ -3542,6 +3857,8 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
3542 | IEEE80211_HW_HAS_RATE_CONTROL | | 3857 | IEEE80211_HW_HAS_RATE_CONTROL | |
3543 | IEEE80211_HW_CONNECTION_MONITOR | | 3858 | IEEE80211_HW_CONNECTION_MONITOR | |
3544 | IEEE80211_HW_SUPPORTS_CQM_RSSI | | 3859 | IEEE80211_HW_SUPPORTS_CQM_RSSI | |
3860 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | | ||
3861 | IEEE80211_HW_SPECTRUM_MGMT | | ||
3545 | IEEE80211_HW_AP_LINK_PS; | 3862 | IEEE80211_HW_AP_LINK_PS; |
3546 | 3863 | ||
3547 | wl->hw->wiphy->cipher_suites = cipher_suites; | 3864 | wl->hw->wiphy->cipher_suites = cipher_suites; |
@@ -3663,6 +3980,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
3663 | wl->ap_fw_ps_map = 0; | 3980 | wl->ap_fw_ps_map = 0; |
3664 | wl->quirks = 0; | 3981 | wl->quirks = 0; |
3665 | wl->platform_quirks = 0; | 3982 | wl->platform_quirks = 0; |
3983 | wl->sched_scanning = false; | ||
3666 | 3984 | ||
3667 | memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); | 3985 | memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); |
3668 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 3986 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
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/ps.h b/drivers/net/wireless/wl12xx/ps.h index c41bd0a711b..25eb9bc9b62 100644 --- a/drivers/net/wireless/wl12xx/ps.h +++ b/drivers/net/wireless/wl12xx/ps.h | |||
@@ -35,4 +35,6 @@ void wl1271_elp_work(struct work_struct *work); | |||
35 | void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues); | 35 | void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues); |
36 | void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid); | 36 | void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid); |
37 | 37 | ||
38 | #define WL1271_PS_COMPLETE_TIMEOUT 500 | ||
39 | |||
38 | #endif /* __WL1271_PS_H__ */ | 40 | #endif /* __WL1271_PS_H__ */ |
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/scan.c b/drivers/net/wireless/wl12xx/scan.c index 5d0544c8f3f..f37e5a39197 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c | |||
@@ -320,3 +320,246 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | |||
320 | 320 | ||
321 | return 0; | 321 | return 0; |
322 | } | 322 | } |
323 | |||
324 | static int | ||
325 | wl1271_scan_get_sched_scan_channels(struct wl1271 *wl, | ||
326 | struct cfg80211_sched_scan_request *req, | ||
327 | struct conn_scan_ch_params *channels, | ||
328 | u32 band, bool radar, bool passive, | ||
329 | int start) | ||
330 | { | ||
331 | struct conf_sched_scan_settings *c = &wl->conf.sched_scan; | ||
332 | int i, j; | ||
333 | u32 flags; | ||
334 | |||
335 | for (i = 0, j = start; | ||
336 | i < req->n_channels && j < MAX_CHANNELS_ALL_BANDS; | ||
337 | i++) { | ||
338 | flags = req->channels[i]->flags; | ||
339 | |||
340 | if (!(flags & IEEE80211_CHAN_DISABLED) && | ||
341 | ((flags & IEEE80211_CHAN_PASSIVE_SCAN) == passive) && | ||
342 | ((flags & IEEE80211_CHAN_RADAR) == radar) && | ||
343 | (req->channels[i]->band == band)) { | ||
344 | wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ", | ||
345 | req->channels[i]->band, | ||
346 | req->channels[i]->center_freq); | ||
347 | wl1271_debug(DEBUG_SCAN, "hw_value %d, flags %X", | ||
348 | req->channels[i]->hw_value, | ||
349 | req->channels[i]->flags); | ||
350 | wl1271_debug(DEBUG_SCAN, "max_power %d", | ||
351 | req->channels[i]->max_power); | ||
352 | |||
353 | if (flags & IEEE80211_CHAN_PASSIVE_SCAN) { | ||
354 | channels[j].passive_duration = | ||
355 | cpu_to_le16(c->dwell_time_passive); | ||
356 | } else { | ||
357 | channels[j].min_duration = | ||
358 | cpu_to_le16(c->min_dwell_time_active); | ||
359 | channels[j].max_duration = | ||
360 | cpu_to_le16(c->max_dwell_time_active); | ||
361 | } | ||
362 | channels[j].tx_power_att = req->channels[j]->max_power; | ||
363 | channels[j].channel = req->channels[i]->hw_value; | ||
364 | |||
365 | j++; | ||
366 | } | ||
367 | } | ||
368 | |||
369 | return j - start; | ||
370 | } | ||
371 | |||
372 | static int | ||
373 | wl1271_scan_sched_scan_channels(struct wl1271 *wl, | ||
374 | struct cfg80211_sched_scan_request *req, | ||
375 | struct wl1271_cmd_sched_scan_config *cfg) | ||
376 | { | ||
377 | int idx = 0; | ||
378 | |||
379 | cfg->passive[0] = | ||
380 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels, | ||
381 | IEEE80211_BAND_2GHZ, | ||
382 | false, true, idx); | ||
383 | idx += cfg->passive[0]; | ||
384 | |||
385 | cfg->active[0] = | ||
386 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels, | ||
387 | IEEE80211_BAND_2GHZ, | ||
388 | false, false, idx); | ||
389 | idx += cfg->active[0]; | ||
390 | |||
391 | cfg->passive[1] = | ||
392 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels, | ||
393 | IEEE80211_BAND_5GHZ, | ||
394 | false, true, idx); | ||
395 | idx += cfg->passive[1]; | ||
396 | |||
397 | cfg->active[1] = | ||
398 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels, | ||
399 | IEEE80211_BAND_5GHZ, | ||
400 | false, false, 14); | ||
401 | idx += cfg->active[1]; | ||
402 | |||
403 | cfg->dfs = | ||
404 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels, | ||
405 | IEEE80211_BAND_5GHZ, | ||
406 | true, false, idx); | ||
407 | idx += cfg->dfs; | ||
408 | |||
409 | wl1271_debug(DEBUG_SCAN, " 2.4GHz: active %d passive %d", | ||
410 | cfg->active[0], cfg->passive[0]); | ||
411 | wl1271_debug(DEBUG_SCAN, " 5GHz: active %d passive %d", | ||
412 | cfg->active[1], cfg->passive[1]); | ||
413 | |||
414 | return idx; | ||
415 | } | ||
416 | |||
417 | int wl1271_scan_sched_scan_config(struct wl1271 *wl, | ||
418 | struct cfg80211_sched_scan_request *req, | ||
419 | struct ieee80211_sched_scan_ies *ies) | ||
420 | { | ||
421 | struct wl1271_cmd_sched_scan_config *cfg = NULL; | ||
422 | struct conf_sched_scan_settings *c = &wl->conf.sched_scan; | ||
423 | int i, total_channels, ret; | ||
424 | |||
425 | wl1271_debug(DEBUG_CMD, "cmd sched_scan scan config"); | ||
426 | |||
427 | cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); | ||
428 | if (!cfg) | ||
429 | return -ENOMEM; | ||
430 | |||
431 | cfg->rssi_threshold = c->rssi_threshold; | ||
432 | cfg->snr_threshold = c->snr_threshold; | ||
433 | cfg->n_probe_reqs = c->num_probe_reqs; | ||
434 | /* cycles set to 0 it means infinite (until manually stopped) */ | ||
435 | cfg->cycles = 0; | ||
436 | /* report APs when at least 1 is found */ | ||
437 | cfg->report_after = 1; | ||
438 | /* don't stop scanning automatically when something is found */ | ||
439 | cfg->terminate = 0; | ||
440 | cfg->tag = WL1271_SCAN_DEFAULT_TAG; | ||
441 | /* don't filter on BSS type */ | ||
442 | cfg->bss_type = SCAN_BSS_TYPE_ANY; | ||
443 | /* currently NL80211 supports only a single interval */ | ||
444 | for (i = 0; i < SCAN_MAX_CYCLE_INTERVALS; i++) | ||
445 | cfg->intervals[i] = cpu_to_le32(req->interval); | ||
446 | |||
447 | if (req->ssids[0].ssid_len && req->ssids[0].ssid) { | ||
448 | cfg->filter_type = SCAN_SSID_FILTER_SPECIFIC; | ||
449 | cfg->ssid_len = req->ssids[0].ssid_len; | ||
450 | memcpy(cfg->ssid, req->ssids[0].ssid, | ||
451 | req->ssids[0].ssid_len); | ||
452 | } else { | ||
453 | cfg->filter_type = SCAN_SSID_FILTER_ANY; | ||
454 | cfg->ssid_len = 0; | ||
455 | } | ||
456 | |||
457 | total_channels = wl1271_scan_sched_scan_channels(wl, req, cfg); | ||
458 | if (total_channels == 0) { | ||
459 | wl1271_error("scan channel list is empty"); | ||
460 | ret = -EINVAL; | ||
461 | goto out; | ||
462 | } | ||
463 | |||
464 | if (cfg->active[0]) { | ||
465 | ret = wl1271_cmd_build_probe_req(wl, req->ssids[0].ssid, | ||
466 | req->ssids[0].ssid_len, | ||
467 | ies->ie[IEEE80211_BAND_2GHZ], | ||
468 | ies->len[IEEE80211_BAND_2GHZ], | ||
469 | IEEE80211_BAND_2GHZ); | ||
470 | if (ret < 0) { | ||
471 | wl1271_error("2.4GHz PROBE request template failed"); | ||
472 | goto out; | ||
473 | } | ||
474 | } | ||
475 | |||
476 | if (cfg->active[1]) { | ||
477 | ret = wl1271_cmd_build_probe_req(wl, req->ssids[0].ssid, | ||
478 | req->ssids[0].ssid_len, | ||
479 | ies->ie[IEEE80211_BAND_5GHZ], | ||
480 | ies->len[IEEE80211_BAND_5GHZ], | ||
481 | IEEE80211_BAND_5GHZ); | ||
482 | if (ret < 0) { | ||
483 | wl1271_error("5GHz PROBE request template failed"); | ||
484 | goto out; | ||
485 | } | ||
486 | } | ||
487 | |||
488 | wl1271_dump(DEBUG_SCAN, "SCAN_CFG: ", cfg, sizeof(*cfg)); | ||
489 | |||
490 | ret = wl1271_cmd_send(wl, CMD_CONNECTION_SCAN_CFG, cfg, | ||
491 | sizeof(*cfg), 0); | ||
492 | if (ret < 0) { | ||
493 | wl1271_error("SCAN configuration failed"); | ||
494 | goto out; | ||
495 | } | ||
496 | out: | ||
497 | kfree(cfg); | ||
498 | return ret; | ||
499 | } | ||
500 | |||
501 | int wl1271_scan_sched_scan_start(struct wl1271 *wl) | ||
502 | { | ||
503 | struct wl1271_cmd_sched_scan_start *start; | ||
504 | int ret = 0; | ||
505 | |||
506 | wl1271_debug(DEBUG_CMD, "cmd periodic scan start"); | ||
507 | |||
508 | if (wl->bss_type != BSS_TYPE_STA_BSS) | ||
509 | return -EOPNOTSUPP; | ||
510 | |||
511 | if (!test_bit(WL1271_FLAG_IDLE, &wl->flags)) | ||
512 | return -EBUSY; | ||
513 | |||
514 | start = kzalloc(sizeof(*start), GFP_KERNEL); | ||
515 | if (!start) | ||
516 | return -ENOMEM; | ||
517 | |||
518 | start->tag = WL1271_SCAN_DEFAULT_TAG; | ||
519 | |||
520 | ret = wl1271_cmd_send(wl, CMD_START_PERIODIC_SCAN, start, | ||
521 | sizeof(*start), 0); | ||
522 | if (ret < 0) { | ||
523 | wl1271_error("failed to send scan start command"); | ||
524 | goto out_free; | ||
525 | } | ||
526 | |||
527 | out_free: | ||
528 | kfree(start); | ||
529 | return ret; | ||
530 | } | ||
531 | |||
532 | void wl1271_scan_sched_scan_results(struct wl1271 *wl) | ||
533 | { | ||
534 | wl1271_debug(DEBUG_SCAN, "got periodic scan results"); | ||
535 | |||
536 | ieee80211_sched_scan_results(wl->hw); | ||
537 | } | ||
538 | |||
539 | void wl1271_scan_sched_scan_stop(struct wl1271 *wl) | ||
540 | { | ||
541 | struct wl1271_cmd_sched_scan_stop *stop; | ||
542 | int ret = 0; | ||
543 | |||
544 | wl1271_debug(DEBUG_CMD, "cmd periodic scan stop"); | ||
545 | |||
546 | /* FIXME: what to do if alloc'ing to stop fails? */ | ||
547 | stop = kzalloc(sizeof(*stop), GFP_KERNEL); | ||
548 | if (!stop) { | ||
549 | wl1271_error("failed to alloc memory to send sched scan stop"); | ||
550 | return; | ||
551 | } | ||
552 | |||
553 | stop->tag = WL1271_SCAN_DEFAULT_TAG; | ||
554 | |||
555 | ret = wl1271_cmd_send(wl, CMD_STOP_PERIODIC_SCAN, stop, | ||
556 | sizeof(*stop), 0); | ||
557 | if (ret < 0) { | ||
558 | wl1271_error("failed to send sched scan stop command"); | ||
559 | goto out_free; | ||
560 | } | ||
561 | wl->sched_scanning = false; | ||
562 | |||
563 | out_free: | ||
564 | kfree(stop); | ||
565 | } | ||
diff --git a/drivers/net/wireless/wl12xx/scan.h b/drivers/net/wireless/wl12xx/scan.h index 421a750add5..c83319579ca 100644 --- a/drivers/net/wireless/wl12xx/scan.h +++ b/drivers/net/wireless/wl12xx/scan.h | |||
@@ -33,6 +33,12 @@ int wl1271_scan_build_probe_req(struct wl1271 *wl, | |||
33 | const u8 *ie, size_t ie_len, u8 band); | 33 | const u8 *ie, size_t ie_len, u8 band); |
34 | void wl1271_scan_stm(struct wl1271 *wl); | 34 | void wl1271_scan_stm(struct wl1271 *wl); |
35 | void wl1271_scan_complete_work(struct work_struct *work); | 35 | void wl1271_scan_complete_work(struct work_struct *work); |
36 | int wl1271_scan_sched_scan_config(struct wl1271 *wl, | ||
37 | struct cfg80211_sched_scan_request *req, | ||
38 | struct ieee80211_sched_scan_ies *ies); | ||
39 | int wl1271_scan_sched_scan_start(struct wl1271 *wl); | ||
40 | void wl1271_scan_sched_scan_stop(struct wl1271 *wl); | ||
41 | void wl1271_scan_sched_scan_results(struct wl1271 *wl); | ||
36 | 42 | ||
37 | #define WL1271_SCAN_MAX_CHANNELS 24 | 43 | #define WL1271_SCAN_MAX_CHANNELS 24 |
38 | #define WL1271_SCAN_DEFAULT_TAG 1 | 44 | #define WL1271_SCAN_DEFAULT_TAG 1 |
@@ -106,4 +112,112 @@ struct wl1271_cmd_trigger_scan_to { | |||
106 | __le32 timeout; | 112 | __le32 timeout; |
107 | } __packed; | 113 | } __packed; |
108 | 114 | ||
115 | #define MAX_CHANNELS_ALL_BANDS 41 | ||
116 | #define SCAN_MAX_CYCLE_INTERVALS 16 | ||
117 | #define SCAN_MAX_BANDS 3 | ||
118 | |||
119 | enum { | ||
120 | SCAN_CHANNEL_TYPE_2GHZ_PASSIVE, | ||
121 | SCAN_CHANNEL_TYPE_2GHZ_ACTIVE, | ||
122 | SCAN_CHANNEL_TYPE_5GHZ_PASSIVE, | ||
123 | SCAN_CHANNEL_TYPE_5GHZ_ACTIVE, | ||
124 | SCAN_CHANNEL_TYPE_5GHZ_DFS, | ||
125 | }; | ||
126 | |||
127 | enum { | ||
128 | SCAN_SSID_FILTER_ANY = 0, | ||
129 | SCAN_SSID_FILTER_SPECIFIC = 1, | ||
130 | SCAN_SSID_FILTER_LIST = 2, | ||
131 | SCAN_SSID_FILTER_DISABLED = 3 | ||
132 | }; | ||
133 | |||
134 | enum { | ||
135 | SCAN_BSS_TYPE_INDEPENDENT, | ||
136 | SCAN_BSS_TYPE_INFRASTRUCTURE, | ||
137 | SCAN_BSS_TYPE_ANY, | ||
138 | }; | ||
139 | |||
140 | struct conn_scan_ch_params { | ||
141 | __le16 min_duration; | ||
142 | __le16 max_duration; | ||
143 | __le16 passive_duration; | ||
144 | |||
145 | u8 channel; | ||
146 | u8 tx_power_att; | ||
147 | |||
148 | /* bit 0: DFS channel; bit 1: DFS enabled */ | ||
149 | u8 flags; | ||
150 | |||
151 | u8 padding[3]; | ||
152 | } __packed; | ||
153 | |||
154 | struct wl1271_cmd_sched_scan_config { | ||
155 | struct wl1271_cmd_header header; | ||
156 | |||
157 | __le32 intervals[SCAN_MAX_CYCLE_INTERVALS]; | ||
158 | |||
159 | s8 rssi_threshold; /* for filtering (in dBm) */ | ||
160 | s8 snr_threshold; /* for filtering (in dB) */ | ||
161 | |||
162 | u8 cycles; /* maximum number of scan cycles */ | ||
163 | u8 report_after; /* report when this number of results are received */ | ||
164 | u8 terminate; /* stop scanning after reporting */ | ||
165 | |||
166 | u8 tag; | ||
167 | u8 bss_type; /* for filtering */ | ||
168 | u8 filter_type; | ||
169 | |||
170 | u8 ssid_len; /* For SCAN_SSID_FILTER_SPECIFIC */ | ||
171 | u8 ssid[IW_ESSID_MAX_SIZE]; | ||
172 | |||
173 | u8 n_probe_reqs; /* Number of probes requests per channel */ | ||
174 | |||
175 | u8 passive[SCAN_MAX_BANDS]; | ||
176 | u8 active[SCAN_MAX_BANDS]; | ||
177 | |||
178 | u8 dfs; | ||
179 | |||
180 | u8 padding[3]; | ||
181 | |||
182 | struct conn_scan_ch_params channels[MAX_CHANNELS_ALL_BANDS]; | ||
183 | } __packed; | ||
184 | |||
185 | |||
186 | #define SCHED_SCAN_MAX_SSIDS 8 | ||
187 | |||
188 | enum { | ||
189 | SCAN_SSID_TYPE_PUBLIC = 0, | ||
190 | SCAN_SSID_TYPE_HIDDEN = 1, | ||
191 | }; | ||
192 | |||
193 | struct wl1271_ssid { | ||
194 | u8 type; | ||
195 | u8 len; | ||
196 | u8 ssid[IW_ESSID_MAX_SIZE]; | ||
197 | /* u8 padding[2]; */ | ||
198 | } __packed; | ||
199 | |||
200 | struct wl1271_cmd_sched_scan_ssid_list { | ||
201 | struct wl1271_cmd_header header; | ||
202 | |||
203 | u8 n_ssids; | ||
204 | struct wl1271_ssid ssids[SCHED_SCAN_MAX_SSIDS]; | ||
205 | u8 padding[3]; | ||
206 | } __packed; | ||
207 | |||
208 | struct wl1271_cmd_sched_scan_start { | ||
209 | struct wl1271_cmd_header header; | ||
210 | |||
211 | u8 tag; | ||
212 | u8 padding[3]; | ||
213 | } __packed; | ||
214 | |||
215 | struct wl1271_cmd_sched_scan_stop { | ||
216 | struct wl1271_cmd_header header; | ||
217 | |||
218 | u8 tag; | ||
219 | u8 padding[3]; | ||
220 | } __packed; | ||
221 | |||
222 | |||
109 | #endif /* __WL1271_SCAN_H__ */ | 223 | #endif /* __WL1271_SCAN_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index bcd4ad7ba90..92d29a860fc 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c | |||
@@ -82,6 +82,16 @@ static irqreturn_t wl1271_hardirq(int irq, void *cookie) | |||
82 | complete(wl->elp_compl); | 82 | complete(wl->elp_compl); |
83 | wl->elp_compl = NULL; | 83 | wl->elp_compl = NULL; |
84 | } | 84 | } |
85 | |||
86 | if (test_bit(WL1271_FLAG_SUSPENDED, &wl->flags)) { | ||
87 | /* don't enqueue a work right now. mark it as pending */ | ||
88 | set_bit(WL1271_FLAG_PENDING_WORK, &wl->flags); | ||
89 | wl1271_debug(DEBUG_IRQ, "should not enqueue work"); | ||
90 | disable_irq_nosync(wl->irq); | ||
91 | pm_wakeup_event(wl1271_sdio_wl_to_dev(wl), 0); | ||
92 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
93 | return IRQ_HANDLED; | ||
94 | } | ||
85 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 95 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
86 | 96 | ||
87 | return IRQ_WAKE_THREAD; | 97 | return IRQ_WAKE_THREAD; |
@@ -221,6 +231,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, | |||
221 | const struct wl12xx_platform_data *wlan_data; | 231 | const struct wl12xx_platform_data *wlan_data; |
222 | struct wl1271 *wl; | 232 | struct wl1271 *wl; |
223 | unsigned long irqflags; | 233 | unsigned long irqflags; |
234 | mmc_pm_flag_t mmcflags; | ||
224 | int ret; | 235 | int ret; |
225 | 236 | ||
226 | /* We are only able to handle the wlan function */ | 237 | /* We are only able to handle the wlan function */ |
@@ -267,8 +278,18 @@ static int __devinit wl1271_probe(struct sdio_func *func, | |||
267 | goto out_free; | 278 | goto out_free; |
268 | } | 279 | } |
269 | 280 | ||
281 | enable_irq_wake(wl->irq); | ||
282 | device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 1); | ||
283 | |||
270 | disable_irq(wl->irq); | 284 | disable_irq(wl->irq); |
271 | 285 | ||
286 | /* if sdio can keep power while host is suspended, enable wow */ | ||
287 | mmcflags = sdio_get_host_pm_caps(func); | ||
288 | wl1271_debug(DEBUG_SDIO, "sdio PM caps = 0x%x", mmcflags); | ||
289 | |||
290 | if (mmcflags & MMC_PM_KEEP_POWER) | ||
291 | hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY; | ||
292 | |||
272 | ret = wl1271_init_ieee80211(wl); | 293 | ret = wl1271_init_ieee80211(wl); |
273 | if (ret) | 294 | if (ret) |
274 | goto out_irq; | 295 | goto out_irq; |
@@ -303,6 +324,8 @@ static void __devexit wl1271_remove(struct sdio_func *func) | |||
303 | pm_runtime_get_noresume(&func->dev); | 324 | pm_runtime_get_noresume(&func->dev); |
304 | 325 | ||
305 | wl1271_unregister_hw(wl); | 326 | wl1271_unregister_hw(wl); |
327 | device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 0); | ||
328 | disable_irq_wake(wl->irq); | ||
306 | free_irq(wl->irq, wl); | 329 | free_irq(wl->irq, wl); |
307 | wl1271_free_hw(wl); | 330 | wl1271_free_hw(wl); |
308 | } | 331 | } |
@@ -311,11 +334,50 @@ static int wl1271_suspend(struct device *dev) | |||
311 | { | 334 | { |
312 | /* Tell MMC/SDIO core it's OK to power down the card | 335 | /* Tell MMC/SDIO core it's OK to power down the card |
313 | * (if it isn't already), but not to remove it completely */ | 336 | * (if it isn't already), but not to remove it completely */ |
314 | return 0; | 337 | struct sdio_func *func = dev_to_sdio_func(dev); |
338 | struct wl1271 *wl = sdio_get_drvdata(func); | ||
339 | mmc_pm_flag_t sdio_flags; | ||
340 | int ret = 0; | ||
341 | |||
342 | wl1271_debug(DEBUG_MAC80211, "wl1271 suspend. wow_enabled: %d", | ||
343 | wl->wow_enabled); | ||
344 | |||
345 | /* check whether sdio should keep power */ | ||
346 | if (wl->wow_enabled) { | ||
347 | sdio_flags = sdio_get_host_pm_caps(func); | ||
348 | |||
349 | if (!(sdio_flags & MMC_PM_KEEP_POWER)) { | ||
350 | wl1271_error("can't keep power while host " | ||
351 | "is suspended"); | ||
352 | ret = -EINVAL; | ||
353 | goto out; | ||
354 | } | ||
355 | |||
356 | /* keep power while host suspended */ | ||
357 | ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); | ||
358 | if (ret) { | ||
359 | wl1271_error("error while trying to keep power"); | ||
360 | goto out; | ||
361 | } | ||
362 | |||
363 | /* release host */ | ||
364 | sdio_release_host(func); | ||
365 | } | ||
366 | out: | ||
367 | return ret; | ||
315 | } | 368 | } |
316 | 369 | ||
317 | static int wl1271_resume(struct device *dev) | 370 | static int wl1271_resume(struct device *dev) |
318 | { | 371 | { |
372 | struct sdio_func *func = dev_to_sdio_func(dev); | ||
373 | struct wl1271 *wl = sdio_get_drvdata(func); | ||
374 | |||
375 | wl1271_debug(DEBUG_MAC80211, "wl1271 resume"); | ||
376 | if (wl->wow_enabled) { | ||
377 | /* claim back host */ | ||
378 | sdio_claim_host(func); | ||
379 | } | ||
380 | |||
319 | return 0; | 381 | return 0; |
320 | } | 382 | } |
321 | 383 | ||
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..fbe8f46d123 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,17 +346,19 @@ 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, |
351 | WL1271_FLAG_IDLE, | 353 | WL1271_FLAG_IDLE, |
352 | WL1271_FLAG_IDLE_REQUESTED, | ||
353 | WL1271_FLAG_PSPOLL_FAILURE, | 354 | WL1271_FLAG_PSPOLL_FAILURE, |
354 | WL1271_FLAG_STA_STATE_SENT, | 355 | WL1271_FLAG_STA_STATE_SENT, |
355 | WL1271_FLAG_FW_TX_BUSY, | 356 | WL1271_FLAG_FW_TX_BUSY, |
356 | WL1271_FLAG_AP_STARTED, | 357 | WL1271_FLAG_AP_STARTED, |
357 | WL1271_FLAG_IF_INITIALIZED, | 358 | WL1271_FLAG_IF_INITIALIZED, |
358 | WL1271_FLAG_DUMMY_PACKET_PENDING, | 359 | WL1271_FLAG_DUMMY_PACKET_PENDING, |
360 | WL1271_FLAG_SUSPENDED, | ||
361 | WL1271_FLAG_PENDING_WORK, | ||
359 | }; | 362 | }; |
360 | 363 | ||
361 | struct wl1271_link { | 364 | struct wl1271_link { |
@@ -478,6 +481,8 @@ struct wl1271 { | |||
478 | struct wl1271_scan scan; | 481 | struct wl1271_scan scan; |
479 | struct delayed_work scan_complete_work; | 482 | struct delayed_work scan_complete_work; |
480 | 483 | ||
484 | bool sched_scanning; | ||
485 | |||
481 | /* probe-req template for the current AP */ | 486 | /* probe-req template for the current AP */ |
482 | struct sk_buff *probereq; | 487 | struct sk_buff *probereq; |
483 | 488 | ||
@@ -508,6 +513,7 @@ struct wl1271 { | |||
508 | unsigned int rx_filter; | 513 | unsigned int rx_filter; |
509 | 514 | ||
510 | struct completion *elp_compl; | 515 | struct completion *elp_compl; |
516 | struct completion *ps_compl; | ||
511 | struct delayed_work elp_work; | 517 | struct delayed_work elp_work; |
512 | struct delayed_work pspoll_work; | 518 | struct delayed_work pspoll_work; |
513 | 519 | ||
@@ -562,6 +568,12 @@ struct wl1271 { | |||
562 | int tcxo_clock; | 568 | int tcxo_clock; |
563 | 569 | ||
564 | /* | 570 | /* |
571 | * wowlan trigger was configured during suspend. | ||
572 | * (currently, only "ANY" trigger is supported) | ||
573 | */ | ||
574 | bool wow_enabled; | ||
575 | |||
576 | /* | ||
565 | * AP-mode - links indexed by HLID. The global and broadcast links | 577 | * AP-mode - links indexed by HLID. The global and broadcast links |
566 | * are always active. | 578 | * are always active. |
567 | */ | 579 | */ |