diff options
author | Amitkumar Karwar <akarwar@marvell.com> | 2013-06-18 19:36:58 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-06-19 15:28:43 -0400 |
commit | b887664d882ee4f6a67e0bf05e5f141d32fcc067 (patch) | |
tree | 743c252756bcdfc8d129a594ee52a99085d42477 | |
parent | 2a7305c88d245f104c3d6bd3babafb029fd07477 (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.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/init.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/main.h | 20 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/scan.c | 18 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_event.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_ioctl.c | 8 |
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 | ||
518 | enum mwifiex_ba_status { | 520 | enum 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 | */ | ||
1029 | static inline u8 | ||
1030 | mwifiex_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 | |||
1024 | int mwifiex_init_shutdown_fw(struct mwifiex_private *priv, | 1044 | int mwifiex_init_shutdown_fw(struct mwifiex_private *priv, |
1025 | u32 func_init_shutdown); | 1045 | u32 func_init_shutdown); |
1026 | int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8); | 1046 | int 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 | ||