aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx
diff options
context:
space:
mode:
authorJuuso Oikarinen <juuso.oikarinen@nokia.com>2010-04-28 02:50:01 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-04-28 16:50:26 -0400
commit82429d32ca3bae9d67faa32ffbc989be2e63094f (patch)
treedadf23d8eb19e5e89598954b92df7e69d4f7eb95 /drivers/net/wireless/wl12xx
parent141418c7ed22849449f39f8938c9cf0eae6c524f (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.c91
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
1120static int wl1271_join_channel(struct wl1271 *wl, int channel) 1120static 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
1143static int wl1271_unjoin_channel(struct wl1271 *wl) 1142static 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
1178out:
1179 return ret;
1180}
1181
1182static 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
1869out_sleep: 1870out_sleep: