Commit b887664d authored by Amitkumar Karwar's avatar Amitkumar Karwar Committed by John W. Linville

mwifiex: channel switch handling for station

After receiving channel switch announcement from AP, scan and
association on that channel is blocked for DFS_CHAN_MOVE_TIME
(10 seconds). Hence station will be able to connect to the AP,
once it is moved to new channel.
Signed-off-by: default avatarAmitkumar Karwar <akarwar@marvell.com>
Signed-off-by: default avatarBing Zhao <bzhao@marvell.com>
Signed-off-by: default avatarPaul Stewart <pstew@chromium.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 2a7305c8
...@@ -245,6 +245,8 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { ...@@ -245,6 +245,8 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define HT_BW_20 0 #define HT_BW_20 0
#define HT_BW_40 1 #define HT_BW_40 1
#define DFS_CHAN_MOVE_TIME 10000
#define HostCmd_CMD_GET_HW_SPEC 0x0003 #define HostCmd_CMD_GET_HW_SPEC 0x0003
#define HostCmd_CMD_802_11_SCAN 0x0006 #define HostCmd_CMD_802_11_SCAN 0x0006
#define HostCmd_CMD_802_11_GET_LOG 0x000b #define HostCmd_CMD_802_11_GET_LOG 0x000b
......
...@@ -133,6 +133,9 @@ int mwifiex_init_priv(struct mwifiex_private *priv) ...@@ -133,6 +133,9 @@ int mwifiex_init_priv(struct mwifiex_private *priv)
priv->scan_block = false; priv->scan_block = false;
priv->csa_chan = 0;
priv->csa_expire_time = 0;
return mwifiex_add_bss_prio_tbl(priv); return mwifiex_add_bss_prio_tbl(priv);
} }
......
...@@ -513,6 +513,8 @@ struct mwifiex_private { ...@@ -513,6 +513,8 @@ struct mwifiex_private {
u32 mgmt_frame_mask; u32 mgmt_frame_mask;
struct mwifiex_roc_cfg roc_cfg; struct mwifiex_roc_cfg roc_cfg;
bool scan_aborting; bool scan_aborting;
u8 csa_chan;
unsigned long csa_expire_time;
}; };
enum mwifiex_ba_status { enum mwifiex_ba_status {
...@@ -1021,6 +1023,24 @@ static inline bool mwifiex_is_skb_mgmt_frame(struct sk_buff *skb) ...@@ -1021,6 +1023,24 @@ static inline bool mwifiex_is_skb_mgmt_frame(struct sk_buff *skb)
return (*(u32 *)skb->data == PKT_TYPE_MGMT); return (*(u32 *)skb->data == PKT_TYPE_MGMT);
} }
/* This function retrieves channel closed for operation by Channel
* Switch Announcement.
*/
static inline u8
mwifiex_11h_get_csa_closed_channel(struct mwifiex_private *priv)
{
if (!priv->csa_chan)
return 0;
/* Clear csa channel, if DFS channel move time has passed */
if (jiffies > priv->csa_expire_time) {
priv->csa_chan = 0;
priv->csa_expire_time = 0;
}
return priv->csa_chan;
}
int mwifiex_init_shutdown_fw(struct mwifiex_private *priv, int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
u32 func_init_shutdown); u32 func_init_shutdown);
int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8); int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8);
......
...@@ -575,6 +575,9 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, ...@@ -575,6 +575,9 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv,
return -1; return -1;
} }
/* Check csa channel expiry before preparing scan list */
mwifiex_11h_get_csa_closed_channel(priv);
chan_tlv_out->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); chan_tlv_out->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
/* Set the temp channel struct pointer to the start of the desired /* Set the temp channel struct pointer to the start of the desired
...@@ -604,6 +607,11 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, ...@@ -604,6 +607,11 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv,
while (tlv_idx < max_chan_per_scan && while (tlv_idx < max_chan_per_scan &&
tmp_chan_list->chan_number && !done_early) { tmp_chan_list->chan_number && !done_early) {
if (tmp_chan_list->chan_number == priv->csa_chan) {
tmp_chan_list++;
continue;
}
dev_dbg(priv->adapter->dev, dev_dbg(priv->adapter->dev,
"info: Scan: Chan(%3d), Radio(%d)," "info: Scan: Chan(%3d), Radio(%d),"
" Mode(%d, %d), Dur(%d)\n", " Mode(%d, %d), Dur(%d)\n",
...@@ -1594,6 +1602,9 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, ...@@ -1594,6 +1602,9 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
goto check_next_scan; goto check_next_scan;
} }
/* Check csa channel expiry before parsing scan response */
mwifiex_11h_get_csa_closed_channel(priv);
bytes_left = le16_to_cpu(scan_rsp->bss_descript_size); bytes_left = le16_to_cpu(scan_rsp->bss_descript_size);
dev_dbg(adapter->dev, "info: SCAN_RESP: bss_descript_size %d\n", dev_dbg(adapter->dev, "info: SCAN_RESP: bss_descript_size %d\n",
bytes_left); bytes_left);
...@@ -1746,6 +1757,13 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, ...@@ -1746,6 +1757,13 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
struct ieee80211_channel *chan; struct ieee80211_channel *chan;
u8 band; u8 band;
/* Skip entry if on csa closed channel */
if (channel == priv->csa_chan) {
dev_dbg(adapter->dev,
"Dropping entry on csa closed channel\n");
continue;
}
band = BAND_G; band = BAND_G;
if (chan_band_tlv) { if (chan_band_tlv) {
chan_band = chan_band =
......
...@@ -429,6 +429,9 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) ...@@ -429,6 +429,9 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
case EVENT_CHANNEL_SWITCH_ANN: case EVENT_CHANNEL_SWITCH_ANN:
dev_dbg(adapter->dev, "event: Channel Switch Announcement\n"); dev_dbg(adapter->dev, "event: Channel Switch Announcement\n");
priv->csa_expire_time =
jiffies + msecs_to_jiffies(DFS_CHAN_MOVE_TIME);
priv->csa_chan = priv->curr_bss_params.bss_descriptor.channel;
ret = mwifiex_send_cmd_async(priv, ret = mwifiex_send_cmd_async(priv,
HostCmd_CMD_802_11_DEAUTHENTICATE, HostCmd_CMD_802_11_DEAUTHENTICATE,
HostCmd_ACT_GEN_SET, 0, HostCmd_ACT_GEN_SET, 0,
......
...@@ -281,6 +281,14 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, ...@@ -281,6 +281,14 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
if (ret) if (ret)
goto done; goto done;
if (mwifiex_11h_get_csa_closed_channel(priv) ==
(u8)bss_desc->channel) {
dev_err(adapter->dev,
"Attempt to reconnect on csa closed chan(%d)\n",
bss_desc->channel);
goto done;
}
dev_dbg(adapter->dev, "info: SSID found in scan list ... " dev_dbg(adapter->dev, "info: SSID found in scan list ... "
"associating...\n"); "associating...\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment