diff options
author | Juuso Oikarinen <juuso.oikarinen@nokia.com> | 2010-03-26 06:53:32 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-03-31 14:39:16 -0400 |
commit | c18995540cc4d2c84d130581b8b6720b22ca16b5 (patch) | |
tree | 0acb4eb3863c70bfbffd355b36346aac552f2598 /drivers/net/wireless | |
parent | bfb24c9e16921f0e57fcec5180ffa20929832545 (diff) |
wl1271: Enable hardware keep alive messages
This patch will enable the hardware keep-alive mode, configure the required
template, configure keep-alive parameters, and re-order JOIN's and ACX_AID
in such a way that the keep-alive is activated.
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_acx.c | 55 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_acx.h | 31 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_conf.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_init.c | 13 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_main.c | 33 |
5 files changed, 138 insertions, 3 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index e7d11811a907..8f0bd5bee6f9 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c | |||
@@ -1139,3 +1139,58 @@ out: | |||
1139 | kfree(acx); | 1139 | kfree(acx); |
1140 | return ret; | 1140 | return ret; |
1141 | } | 1141 | } |
1142 | |||
1143 | int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable) | ||
1144 | { | ||
1145 | struct wl1271_acx_keep_alive_mode *acx = NULL; | ||
1146 | int ret = 0; | ||
1147 | |||
1148 | wl1271_debug(DEBUG_ACX, "acx keep alive mode: %d", enable); | ||
1149 | |||
1150 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1151 | if (!acx) { | ||
1152 | ret = -ENOMEM; | ||
1153 | goto out; | ||
1154 | } | ||
1155 | |||
1156 | acx->enabled = enable; | ||
1157 | |||
1158 | ret = wl1271_cmd_configure(wl, ACX_KEEP_ALIVE_MODE, acx, sizeof(*acx)); | ||
1159 | if (ret < 0) { | ||
1160 | wl1271_warning("acx keep alive mode failed: %d", ret); | ||
1161 | goto out; | ||
1162 | } | ||
1163 | |||
1164 | out: | ||
1165 | kfree(acx); | ||
1166 | return ret; | ||
1167 | } | ||
1168 | int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid) | ||
1169 | { | ||
1170 | struct wl1271_acx_keep_alive_config *acx = NULL; | ||
1171 | int ret = 0; | ||
1172 | |||
1173 | wl1271_debug(DEBUG_ACX, "acx keep alive config"); | ||
1174 | |||
1175 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1176 | if (!acx) { | ||
1177 | ret = -ENOMEM; | ||
1178 | goto out; | ||
1179 | } | ||
1180 | |||
1181 | acx->period = cpu_to_le32(wl->conf.conn.keep_alive_interval); | ||
1182 | acx->index = index; | ||
1183 | acx->tpl_validation = tpl_valid; | ||
1184 | acx->trigger = ACX_KEEP_ALIVE_NO_TX; | ||
1185 | |||
1186 | ret = wl1271_cmd_configure(wl, ACX_SET_KEEP_ALIVE_CONFIG, | ||
1187 | acx, sizeof(*acx)); | ||
1188 | if (ret < 0) { | ||
1189 | wl1271_warning("acx keep alive config failed: %d", ret); | ||
1190 | goto out; | ||
1191 | } | ||
1192 | |||
1193 | out: | ||
1194 | kfree(acx); | ||
1195 | return ret; | ||
1196 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index b6eb0c1b6c78..15cc56192de9 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h | |||
@@ -915,6 +915,33 @@ struct wl1271_acx_pm_config { | |||
915 | u8 padding[3]; | 915 | u8 padding[3]; |
916 | } __attribute__ ((packed)); | 916 | } __attribute__ ((packed)); |
917 | 917 | ||
918 | struct wl1271_acx_keep_alive_mode { | ||
919 | struct acx_header header; | ||
920 | |||
921 | u8 enabled; | ||
922 | u8 padding[3]; | ||
923 | } __attribute__ ((packed)); | ||
924 | |||
925 | enum { | ||
926 | ACX_KEEP_ALIVE_NO_TX = 0, | ||
927 | ACX_KEEP_ALIVE_PERIOD_ONLY | ||
928 | }; | ||
929 | |||
930 | enum { | ||
931 | ACX_KEEP_ALIVE_TPL_INVALID = 0, | ||
932 | ACX_KEEP_ALIVE_TPL_VALID | ||
933 | }; | ||
934 | |||
935 | struct wl1271_acx_keep_alive_config { | ||
936 | struct acx_header header; | ||
937 | |||
938 | __le32 period; | ||
939 | u8 index; | ||
940 | u8 tpl_validation; | ||
941 | u8 trigger; | ||
942 | u8 padding; | ||
943 | } __attribute__ ((packed)); | ||
944 | |||
918 | enum { | 945 | enum { |
919 | ACX_WAKE_UP_CONDITIONS = 0x0002, | 946 | ACX_WAKE_UP_CONDITIONS = 0x0002, |
920 | ACX_MEM_CFG = 0x0003, | 947 | ACX_MEM_CFG = 0x0003, |
@@ -964,7 +991,7 @@ enum { | |||
964 | ACX_BET_ENABLE = 0x0050, | 991 | ACX_BET_ENABLE = 0x0050, |
965 | ACX_RSSI_SNR_TRIGGER = 0x0051, | 992 | ACX_RSSI_SNR_TRIGGER = 0x0051, |
966 | ACX_RSSI_SNR_WEIGHTS = 0x0051, | 993 | ACX_RSSI_SNR_WEIGHTS = 0x0051, |
967 | ACX_KEEP_ALIVE_MODE = 0x0052, | 994 | ACX_KEEP_ALIVE_MODE = 0x0053, |
968 | ACX_SET_KEEP_ALIVE_CONFIG = 0x0054, | 995 | ACX_SET_KEEP_ALIVE_CONFIG = 0x0054, |
969 | ACX_BA_SESSION_RESPONDER_POLICY = 0x0055, | 996 | ACX_BA_SESSION_RESPONDER_POLICY = 0x0055, |
970 | ACX_BA_SESSION_INITIATOR_POLICY = 0x0056, | 997 | ACX_BA_SESSION_INITIATOR_POLICY = 0x0056, |
@@ -1031,5 +1058,7 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); | |||
1031 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, | 1058 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, |
1032 | u8 version); | 1059 | u8 version); |
1033 | int wl1271_acx_pm_config(struct wl1271 *wl); | 1060 | int wl1271_acx_pm_config(struct wl1271 *wl); |
1061 | int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable); | ||
1062 | int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid); | ||
1034 | 1063 | ||
1035 | #endif /* __WL1271_ACX_H__ */ | 1064 | #endif /* __WL1271_ACX_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index f63dd5ed998e..82b5dabb6e8d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h | |||
@@ -955,6 +955,15 @@ struct conf_conn_settings { | |||
955 | * Range 0 - 255 | 955 | * Range 0 - 255 |
956 | */ | 956 | */ |
957 | u8 psm_entry_retries; | 957 | u8 psm_entry_retries; |
958 | |||
959 | /* | ||
960 | * | ||
961 | * Specifies the interval of the connection keep-alive null-func | ||
962 | * frame in ms. | ||
963 | * | ||
964 | * Range: 1000 - 3600000 | ||
965 | */ | ||
966 | u32 keep_alive_interval; | ||
958 | }; | 967 | }; |
959 | 968 | ||
960 | enum { | 969 | enum { |
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index 0106663bc45b..8ec94ac84093 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c | |||
@@ -337,6 +337,19 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
337 | if (ret < 0) | 337 | if (ret < 0) |
338 | goto out_free_memmap; | 338 | goto out_free_memmap; |
339 | 339 | ||
340 | /* disable all keep-alive templates */ | ||
341 | for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { | ||
342 | ret = wl1271_acx_keep_alive_config(wl, i, | ||
343 | ACX_KEEP_ALIVE_TPL_INVALID); | ||
344 | if (ret < 0) | ||
345 | goto out_free_memmap; | ||
346 | } | ||
347 | |||
348 | /* disable the keep-alive feature */ | ||
349 | ret = wl1271_acx_keep_alive_mode(wl, false); | ||
350 | if (ret < 0) | ||
351 | goto out_free_memmap; | ||
352 | |||
340 | return 0; | 353 | return 0; |
341 | 354 | ||
342 | out_free_memmap: | 355 | out_free_memmap: |
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index afab52bec134..033cef01fd43 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -264,7 +264,8 @@ static struct conf_drv_settings default_conf = { | |||
264 | }, | 264 | }, |
265 | .bet_enable = CONF_BET_MODE_ENABLE, | 265 | .bet_enable = CONF_BET_MODE_ENABLE, |
266 | .bet_max_consecutive = 10, | 266 | .bet_max_consecutive = 10, |
267 | .psm_entry_retries = 3 | 267 | .psm_entry_retries = 3, |
268 | .keep_alive_interval = 55000 | ||
268 | }, | 269 | }, |
269 | .init = { | 270 | .init = { |
270 | .radioparam = { | 271 | .radioparam = { |
@@ -1203,6 +1204,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1203 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 1204 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; |
1204 | wl->sta_rate_set = 0; | 1205 | wl->sta_rate_set = 0; |
1205 | wl1271_acx_rate_policies(wl); | 1206 | wl1271_acx_rate_policies(wl); |
1207 | wl1271_acx_keep_alive_config( | ||
1208 | wl, CMD_TEMPL_KLV_IDX_NULL_DATA, | ||
1209 | ACX_KEEP_ALIVE_TPL_INVALID); | ||
1206 | } | 1210 | } |
1207 | } | 1211 | } |
1208 | 1212 | ||
@@ -1676,7 +1680,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1676 | ret = wl1271_cmd_build_probe_req(wl, NULL, 0, | 1680 | ret = wl1271_cmd_build_probe_req(wl, NULL, 0, |
1677 | NULL, 0, wl->band); | 1681 | NULL, 0, wl->band); |
1678 | 1682 | ||
1679 | ret = wl1271_acx_aid(wl, wl->aid); | 1683 | /* Enable the keep-alive feature */ |
1684 | ret = wl1271_acx_keep_alive_mode(wl, true); | ||
1680 | if (ret < 0) | 1685 | if (ret < 0) |
1681 | goto out_sleep; | 1686 | goto out_sleep; |
1682 | 1687 | ||
@@ -1700,6 +1705,10 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1700 | 1705 | ||
1701 | /* disable connection monitor features */ | 1706 | /* disable connection monitor features */ |
1702 | ret = wl1271_acx_conn_monit_params(wl, false); | 1707 | ret = wl1271_acx_conn_monit_params(wl, false); |
1708 | |||
1709 | /* Disable the keep-alive feature */ | ||
1710 | ret = wl1271_acx_keep_alive_mode(wl, false); | ||
1711 | |||
1703 | if (ret < 0) | 1712 | if (ret < 0) |
1704 | goto out_sleep; | 1713 | goto out_sleep; |
1705 | } | 1714 | } |
@@ -1744,6 +1753,26 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1744 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | 1753 | set_bit(WL1271_FLAG_JOINED, &wl->flags); |
1745 | } | 1754 | } |
1746 | 1755 | ||
1756 | /* | ||
1757 | * The JOIN operation shuts down the firmware keep-alive as a side | ||
1758 | * effect, and the ACX_AID will start the keep-alive as a side effect. | ||
1759 | * Hence, for non-IBSS, the ACX_AID must always happen *after* the | ||
1760 | * JOIN operation, and the template config after the ACX_AID. | ||
1761 | */ | ||
1762 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { | ||
1763 | ret = wl1271_acx_aid(wl, wl->aid); | ||
1764 | if (ret < 0) | ||
1765 | goto out_sleep; | ||
1766 | ret = wl1271_cmd_build_klv_null_data(wl); | ||
1767 | if (ret < 0) | ||
1768 | goto out_sleep; | ||
1769 | ret = wl1271_acx_keep_alive_config( | ||
1770 | wl, CMD_TEMPL_KLV_IDX_NULL_DATA, | ||
1771 | ACX_KEEP_ALIVE_TPL_VALID); | ||
1772 | if (ret < 0) | ||
1773 | goto out_sleep; | ||
1774 | } | ||
1775 | |||
1747 | out_sleep: | 1776 | out_sleep: |
1748 | wl1271_ps_elp_sleep(wl); | 1777 | wl1271_ps_elp_sleep(wl); |
1749 | 1778 | ||