aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmitkumar Karwar <akarwar@marvell.com>2013-06-18 19:36:58 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-06-19 15:28:43 -0400
commitb887664d882ee4f6a67e0bf05e5f141d32fcc067 (patch)
tree743c252756bcdfc8d129a594ee52a99085d42477
parent2a7305c88d245f104c3d6bd3babafb029fd07477 (diff)
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: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: Paul Stewart <pstew@chromium.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/mwifiex/fw.h2
-rw-r--r--drivers/net/wireless/mwifiex/init.c3
-rw-r--r--drivers/net/wireless/mwifiex/main.h20
-rw-r--r--drivers/net/wireless/mwifiex/scan.c18
-rw-r--r--drivers/net/wireless/mwifiex/sta_event.c3
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c8
6 files changed, 54 insertions, 0 deletions
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index b6fbbf64cf96..1b45aa533300 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -245,6 +245,8 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
245#define HT_BW_20 0 245#define HT_BW_20 0
246#define HT_BW_40 1 246#define HT_BW_40 1
247 247
248#define DFS_CHAN_MOVE_TIME 10000
249
248#define HostCmd_CMD_GET_HW_SPEC 0x0003 250#define HostCmd_CMD_GET_HW_SPEC 0x0003
249#define HostCmd_CMD_802_11_SCAN 0x0006 251#define HostCmd_CMD_802_11_SCAN 0x0006
250#define HostCmd_CMD_802_11_GET_LOG 0x000b 252#define HostCmd_CMD_802_11_GET_LOG 0x000b
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 2fe31dcaa6ef..caaf4bd56b30 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -133,6 +133,9 @@ int mwifiex_init_priv(struct mwifiex_private *priv)
133 133
134 priv->scan_block = false; 134 priv->scan_block = false;
135 135
136 priv->csa_chan = 0;
137 priv->csa_expire_time = 0;
138
136 return mwifiex_add_bss_prio_tbl(priv); 139 return mwifiex_add_bss_prio_tbl(priv);
137} 140}
138 141
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 95a6f5269c6c..3da73d36acdf 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -513,6 +513,8 @@ struct mwifiex_private {
513 u32 mgmt_frame_mask; 513 u32 mgmt_frame_mask;
514 struct mwifiex_roc_cfg roc_cfg; 514 struct mwifiex_roc_cfg roc_cfg;
515 bool scan_aborting; 515 bool scan_aborting;
516 u8 csa_chan;
517 unsigned long csa_expire_time;
516}; 518};
517 519
518enum mwifiex_ba_status { 520enum mwifiex_ba_status {
@@ -1021,6 +1023,24 @@ static inline bool mwifiex_is_skb_mgmt_frame(struct sk_buff *skb)
1021 return (*(u32 *)skb->data == PKT_TYPE_MGMT); 1023 return (*(u32 *)skb->data == PKT_TYPE_MGMT);
1022} 1024}
1023 1025
1026/* This function retrieves channel closed for operation by Channel
1027 * Switch Announcement.
1028 */
1029static inline u8
1030mwifiex_11h_get_csa_closed_channel(struct mwifiex_private *priv)
1031{
1032 if (!priv->csa_chan)
1033 return 0;
1034
1035 /* Clear csa channel, if DFS channel move time has passed */
1036 if (jiffies > priv->csa_expire_time) {
1037 priv->csa_chan = 0;
1038 priv->csa_expire_time = 0;
1039 }
1040
1041 return priv->csa_chan;
1042}
1043
1024int mwifiex_init_shutdown_fw(struct mwifiex_private *priv, 1044int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
1025 u32 func_init_shutdown); 1045 u32 func_init_shutdown);
1026int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8); 1046int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8);
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 284d68bf6acc..c447d9bd1aa9 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -575,6 +575,9 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv,
575 return -1; 575 return -1;
576 } 576 }
577 577
578 /* Check csa channel expiry before preparing scan list */
579 mwifiex_11h_get_csa_closed_channel(priv);
580
578 chan_tlv_out->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); 581 chan_tlv_out->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
579 582
580 /* Set the temp channel struct pointer to the start of the desired 583 /* 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 while (tlv_idx < max_chan_per_scan && 607 while (tlv_idx < max_chan_per_scan &&
605 tmp_chan_list->chan_number && !done_early) { 608 tmp_chan_list->chan_number && !done_early) {
606 609
610 if (tmp_chan_list->chan_number == priv->csa_chan) {
611 tmp_chan_list++;
612 continue;
613 }
614
607 dev_dbg(priv->adapter->dev, 615 dev_dbg(priv->adapter->dev,
608 "info: Scan: Chan(%3d), Radio(%d)," 616 "info: Scan: Chan(%3d), Radio(%d),"
609 " Mode(%d, %d), Dur(%d)\n", 617 " Mode(%d, %d), Dur(%d)\n",
@@ -1594,6 +1602,9 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
1594 goto check_next_scan; 1602 goto check_next_scan;
1595 } 1603 }
1596 1604
1605 /* Check csa channel expiry before parsing scan response */
1606 mwifiex_11h_get_csa_closed_channel(priv);
1607
1597 bytes_left = le16_to_cpu(scan_rsp->bss_descript_size); 1608 bytes_left = le16_to_cpu(scan_rsp->bss_descript_size);
1598 dev_dbg(adapter->dev, "info: SCAN_RESP: bss_descript_size %d\n", 1609 dev_dbg(adapter->dev, "info: SCAN_RESP: bss_descript_size %d\n",
1599 bytes_left); 1610 bytes_left);
@@ -1746,6 +1757,13 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
1746 struct ieee80211_channel *chan; 1757 struct ieee80211_channel *chan;
1747 u8 band; 1758 u8 band;
1748 1759
1760 /* Skip entry if on csa closed channel */
1761 if (channel == priv->csa_chan) {
1762 dev_dbg(adapter->dev,
1763 "Dropping entry on csa closed channel\n");
1764 continue;
1765 }
1766
1749 band = BAND_G; 1767 band = BAND_G;
1750 if (chan_band_tlv) { 1768 if (chan_band_tlv) {
1751 chan_band = 1769 chan_band =
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index d28c92005cce..ea265ec0e522 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -429,6 +429,9 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
429 429
430 case EVENT_CHANNEL_SWITCH_ANN: 430 case EVENT_CHANNEL_SWITCH_ANN:
431 dev_dbg(adapter->dev, "event: Channel Switch Announcement\n"); 431 dev_dbg(adapter->dev, "event: Channel Switch Announcement\n");
432 priv->csa_expire_time =
433 jiffies + msecs_to_jiffies(DFS_CHAN_MOVE_TIME);
434 priv->csa_chan = priv->curr_bss_params.bss_descriptor.channel;
432 ret = mwifiex_send_cmd_async(priv, 435 ret = mwifiex_send_cmd_async(priv,
433 HostCmd_CMD_802_11_DEAUTHENTICATE, 436 HostCmd_CMD_802_11_DEAUTHENTICATE,
434 HostCmd_ACT_GEN_SET, 0, 437 HostCmd_ACT_GEN_SET, 0,
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 498add76a46d..206c3e038072 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -281,6 +281,14 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
281 if (ret) 281 if (ret)
282 goto done; 282 goto done;
283 283
284 if (mwifiex_11h_get_csa_closed_channel(priv) ==
285 (u8)bss_desc->channel) {
286 dev_err(adapter->dev,
287 "Attempt to reconnect on csa closed chan(%d)\n",
288 bss_desc->channel);
289 goto done;
290 }
291
284 dev_dbg(adapter->dev, "info: SSID found in scan list ... " 292 dev_dbg(adapter->dev, "info: SSID found in scan list ... "
285 "associating...\n"); 293 "associating...\n");
286 294