summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/main.c
diff options
context:
space:
mode:
authorShahar Levi <shahar_levi@ti.com>2011-09-08 13:01:33 +0300
committerLuciano Coelho <coelho@ti.com>2011-10-07 08:32:27 +0300
commit6d158ff38d8c99dc1bee775a66451168316692f4 (patch)
tree500f64f4e4e4bacda3fc62b571e10dab52aa10e6 /drivers/net/wireless/wl12xx/main.c
parentc9e79a4714493df6508d8346195ea30fb69b7783 (diff)
wl12xx: Add support for HW channel switch
The wl12xx FW supports HW channel switch. If we don't use it, sometimes the firmware gets confused when recalibrating to the new channel, causing RX problems. This commit adds HW channel switch support by implementing the channell_switch op. Signed-off-by: Shahar Levi <shahar_levi@ti.com> [added one comment, remove the tx_flush and rephrased the commit message] Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net/wireless/wl12xx/main.c')
-rw-r--r--drivers/net/wireless/wl12xx/main.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index b1b405b576c..6b8a8a339f9 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -2222,6 +2222,11 @@ static int wl1271_unjoin(struct wl1271 *wl)
{
int ret;
+ if (test_and_clear_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags)) {
+ wl12xx_cmd_stop_channel_switch(wl);
+ ieee80211_chswitch_done(wl->vif, false);
+ }
+
/* to stop listening to a channel, we disconnect */
ret = wl12xx_cmd_role_stop_sta(wl);
if (ret < 0)
@@ -4130,6 +4135,37 @@ static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw,
return 0;
}
+static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
+ struct ieee80211_channel_switch *ch_switch)
+{
+ struct wl1271 *wl = hw->priv;
+ int ret;
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 channel switch");
+
+ mutex_lock(&wl->mutex);
+
+ if (unlikely(wl->state == WL1271_STATE_OFF)) {
+ mutex_unlock(&wl->mutex);
+ ieee80211_chswitch_done(wl->vif, false);
+ return;
+ }
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wl12xx_cmd_channel_switch(wl, ch_switch);
+
+ if (!ret)
+ set_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags);
+
+ wl1271_ps_elp_sleep(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
+}
+
static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
{
struct wl1271 *wl = hw->priv;
@@ -4406,6 +4442,7 @@ static const struct ieee80211_ops wl1271_ops = {
.ampdu_action = wl1271_op_ampdu_action,
.tx_frames_pending = wl1271_tx_frames_pending,
.set_bitrate_mask = wl12xx_set_bitrate_mask,
+ .channel_switch = wl12xx_op_channel_switch,
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
};