diff options
author | Juuso Oikarinen <juuso.oikarinen@nokia.com> | 2010-04-28 02:50:01 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-04-28 16:50:26 -0400 |
commit | 82429d32ca3bae9d67faa32ffbc989be2e63094f (patch) | |
tree | dadf23d8eb19e5e89598954b92df7e69d4f7eb95 /drivers/net/wireless/wl12xx | |
parent | 141418c7ed22849449f39f8938c9cf0eae6c524f (diff) |
wl1271: Rewrite hardware keep-alive handling
The driver had a join command without keep-alive restart procedures in the
channel changing code. After associated scans, the mac80211 does re-set the
current channel, causing the join to occur. This would stop the hardware
keep alive.
To make the joins safer in this respect, this patch adds a join function that
does the hardware-keep-alive magic along the join. This is now invoked in the
above mentioned scenario, and also other scenarios.
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Teemu Paasikivi <ext-teemu.3.paasikivi@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/wl12xx')
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_main.c | 91 |
1 files changed, 46 insertions, 45 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index c160e5ad1e57..a794d5ed8c60 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -1117,14 +1117,13 @@ static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) | |||
1117 | } | 1117 | } |
1118 | } | 1118 | } |
1119 | 1119 | ||
1120 | static int wl1271_join_channel(struct wl1271 *wl, int channel) | 1120 | static int wl1271_dummy_join(struct wl1271 *wl) |
1121 | { | 1121 | { |
1122 | int ret = 0; | 1122 | int ret = 0; |
1123 | /* we need to use a dummy BSSID for now */ | 1123 | /* we need to use a dummy BSSID for now */ |
1124 | static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, | 1124 | static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, |
1125 | 0xad, 0xbe, 0xef }; | 1125 | 0xad, 0xbe, 0xef }; |
1126 | 1126 | ||
1127 | wl->channel = channel; | ||
1128 | memcpy(wl->bssid, dummy_bssid, ETH_ALEN); | 1127 | memcpy(wl->bssid, dummy_bssid, ETH_ALEN); |
1129 | 1128 | ||
1130 | /* pass through frames from all BSS */ | 1129 | /* pass through frames from all BSS */ |
@@ -1140,7 +1139,47 @@ out: | |||
1140 | return ret; | 1139 | return ret; |
1141 | } | 1140 | } |
1142 | 1141 | ||
1143 | static int wl1271_unjoin_channel(struct wl1271 *wl) | 1142 | static int wl1271_join(struct wl1271 *wl) |
1143 | { | ||
1144 | int ret; | ||
1145 | |||
1146 | ret = wl1271_cmd_join(wl, wl->set_bss_type); | ||
1147 | if (ret < 0) | ||
1148 | goto out; | ||
1149 | |||
1150 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | ||
1151 | |||
1152 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | ||
1153 | goto out; | ||
1154 | |||
1155 | /* | ||
1156 | * The join command disable the keep-alive mode, shut down its process, | ||
1157 | * and also clear the template config, so we need to reset it all after | ||
1158 | * the join. The acx_aid starts the keep-alive process, and the order | ||
1159 | * of the commands below is relevant. | ||
1160 | */ | ||
1161 | ret = wl1271_acx_keep_alive_mode(wl, true); | ||
1162 | if (ret < 0) | ||
1163 | goto out; | ||
1164 | |||
1165 | ret = wl1271_acx_aid(wl, wl->aid); | ||
1166 | if (ret < 0) | ||
1167 | goto out; | ||
1168 | |||
1169 | ret = wl1271_cmd_build_klv_null_data(wl); | ||
1170 | if (ret < 0) | ||
1171 | goto out; | ||
1172 | |||
1173 | ret = wl1271_acx_keep_alive_config(wl, CMD_TEMPL_KLV_IDX_NULL_DATA, | ||
1174 | ACX_KEEP_ALIVE_TPL_VALID); | ||
1175 | if (ret < 0) | ||
1176 | goto out; | ||
1177 | |||
1178 | out: | ||
1179 | return ret; | ||
1180 | } | ||
1181 | |||
1182 | static int wl1271_unjoin(struct wl1271 *wl) | ||
1144 | { | 1183 | { |
1145 | int ret; | 1184 | int ret; |
1146 | 1185 | ||
@@ -1230,7 +1269,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1230 | "failed %d", ret); | 1269 | "failed %d", ret); |
1231 | 1270 | ||
1232 | if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { | 1271 | if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { |
1233 | ret = wl1271_cmd_join(wl, wl->set_bss_type); | 1272 | ret = wl1271_join(wl); |
1234 | if (ret < 0) | 1273 | if (ret < 0) |
1235 | wl1271_warning("cmd join to update channel " | 1274 | wl1271_warning("cmd join to update channel " |
1236 | "failed %d", ret); | 1275 | "failed %d", ret); |
@@ -1240,9 +1279,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1240 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | 1279 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
1241 | if (conf->flags & IEEE80211_CONF_IDLE && | 1280 | if (conf->flags & IEEE80211_CONF_IDLE && |
1242 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) | 1281 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) |
1243 | wl1271_unjoin_channel(wl); | 1282 | wl1271_unjoin(wl); |
1244 | else if (!(conf->flags & IEEE80211_CONF_IDLE)) | 1283 | else if (!(conf->flags & IEEE80211_CONF_IDLE)) |
1245 | wl1271_join_channel(wl, channel); | 1284 | wl1271_dummy_join(wl); |
1246 | 1285 | ||
1247 | if (conf->flags & IEEE80211_CONF_IDLE) { | 1286 | if (conf->flags & IEEE80211_CONF_IDLE) { |
1248 | wl->rate_set = wl1271_min_rate_get(wl); | 1287 | wl->rate_set = wl1271_min_rate_get(wl); |
@@ -1612,7 +1651,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1612 | enum wl1271_cmd_ps_mode mode; | 1651 | enum wl1271_cmd_ps_mode mode; |
1613 | struct wl1271 *wl = hw->priv; | 1652 | struct wl1271 *wl = hw->priv; |
1614 | bool do_join = false; | 1653 | bool do_join = false; |
1615 | bool do_keepalive = false; | ||
1616 | int ret; | 1654 | int ret; |
1617 | 1655 | ||
1618 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); | 1656 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); |
@@ -1755,19 +1793,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1755 | ret = wl1271_cmd_build_probe_req(wl, NULL, 0, | 1793 | ret = wl1271_cmd_build_probe_req(wl, NULL, 0, |
1756 | NULL, 0, wl->band); | 1794 | NULL, 0, wl->band); |
1757 | 1795 | ||
1758 | /* Enable the keep-alive feature */ | ||
1759 | ret = wl1271_acx_keep_alive_mode(wl, true); | ||
1760 | if (ret < 0) | ||
1761 | goto out_sleep; | ||
1762 | |||
1763 | /* | ||
1764 | * This is awkward. The keep-alive configs must be done | ||
1765 | * *after* the join command, because otherwise it will | ||
1766 | * not work, but it must only be done *once* because | ||
1767 | * otherwise the firmware will start complaining. | ||
1768 | */ | ||
1769 | do_keepalive = true; | ||
1770 | |||
1771 | /* enable the connection monitoring feature */ | 1796 | /* enable the connection monitoring feature */ |
1772 | ret = wl1271_acx_conn_monit_params(wl, true); | 1797 | ret = wl1271_acx_conn_monit_params(wl, true); |
1773 | if (ret < 0) | 1798 | if (ret < 0) |
@@ -1835,35 +1860,11 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1835 | } | 1860 | } |
1836 | 1861 | ||
1837 | if (do_join) { | 1862 | if (do_join) { |
1838 | ret = wl1271_cmd_join(wl, wl->set_bss_type); | 1863 | ret = wl1271_join(wl); |
1839 | if (ret < 0) { | 1864 | if (ret < 0) { |
1840 | wl1271_warning("cmd join failed %d", ret); | 1865 | wl1271_warning("cmd join failed %d", ret); |
1841 | goto out_sleep; | 1866 | goto out_sleep; |
1842 | } | 1867 | } |
1843 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | ||
1844 | } | ||
1845 | |||
1846 | /* | ||
1847 | * The JOIN operation shuts down the firmware keep-alive as a side | ||
1848 | * effect, and the ACX_AID will start the keep-alive as a side effect. | ||
1849 | * Hence, for non-IBSS, the ACX_AID must always happen *after* the | ||
1850 | * JOIN operation, and the template config after the ACX_AID. | ||
1851 | */ | ||
1852 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { | ||
1853 | ret = wl1271_acx_aid(wl, wl->aid); | ||
1854 | if (ret < 0) | ||
1855 | goto out_sleep; | ||
1856 | } | ||
1857 | |||
1858 | if (do_keepalive) { | ||
1859 | ret = wl1271_cmd_build_klv_null_data(wl); | ||
1860 | if (ret < 0) | ||
1861 | goto out_sleep; | ||
1862 | ret = wl1271_acx_keep_alive_config( | ||
1863 | wl, CMD_TEMPL_KLV_IDX_NULL_DATA, | ||
1864 | ACX_KEEP_ALIVE_TPL_VALID); | ||
1865 | if (ret < 0) | ||
1866 | goto out_sleep; | ||
1867 | } | 1868 | } |
1868 | 1869 | ||
1869 | out_sleep: | 1870 | out_sleep: |