aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorJuuso Oikarinen <juuso.oikarinen@nokia.com>2010-03-26 06:53:32 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-03-31 14:39:16 -0400
commitc18995540cc4d2c84d130581b8b6720b22ca16b5 (patch)
tree0acb4eb3863c70bfbffd355b36346aac552f2598 /drivers/net/wireless
parentbfb24c9e16921f0e57fcec5180ffa20929832545 (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.c55
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_acx.h31
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_conf.h9
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_init.c13
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_main.c33
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
1143int 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
1164out:
1165 kfree(acx);
1166 return ret;
1167}
1168int 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
1193out:
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
918struct wl1271_acx_keep_alive_mode {
919 struct acx_header header;
920
921 u8 enabled;
922 u8 padding[3];
923} __attribute__ ((packed));
924
925enum {
926 ACX_KEEP_ALIVE_NO_TX = 0,
927 ACX_KEEP_ALIVE_PERIOD_ONLY
928};
929
930enum {
931 ACX_KEEP_ALIVE_TPL_INVALID = 0,
932 ACX_KEEP_ALIVE_TPL_VALID
933};
934
935struct 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
918enum { 945enum {
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);
1031int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, 1058int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address,
1032 u8 version); 1059 u8 version);
1033int wl1271_acx_pm_config(struct wl1271 *wl); 1060int wl1271_acx_pm_config(struct wl1271 *wl);
1061int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable);
1062int 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
960enum { 969enum {
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
1747out_sleep: 1776out_sleep:
1748 wl1271_ps_elp_sleep(wl); 1777 wl1271_ps_elp_sleep(wl);
1749 1778