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.
Unified · Split
| @@ -245,6 +245,8 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { · 244 unmodified lines | ||
| 245 | 245 | #define HT_BW_20 0 |
| 246 | 246 | #define HT_BW_40 1 |
| 247 | 247 | |
| 248 | +#define DFS_CHAN_MOVE_TIME 10000 | |
| 249 | + | |
| 248 | 250 | #define HostCmd_CMD_GET_HW_SPEC 0x0003 |
| 249 | 251 | #define HostCmd_CMD_802_11_SCAN 0x0006 |
| 250 | 252 | #define HostCmd_CMD_802_11_GET_LOG 0x000b |
| @@ -133,6 +133,9 @@ int mwifiex_init_priv(struct mwifiex_private *priv) · 132 unmodified lines | ||
| 133 | 133 | |
| 134 | 134 | priv->scan_block = false; |
| 135 | 135 | |
| 136 | + priv->csa_chan = 0; | |
| 137 | + priv->csa_expire_time = 0; | |
| 138 | + | |
| 136 | 139 | return mwifiex_add_bss_prio_tbl(priv); |
| 137 | 140 | } |
| 138 | 141 | |
| @@ -513,6 +513,8 @@ struct mwifiex_private { · 512 unmodified lines | ||
| 513 | 513 | u32 mgmt_frame_mask; |
| 514 | 514 | struct mwifiex_roc_cfg roc_cfg; |
| 515 | 515 | bool scan_aborting; |
| 516 | + u8 csa_chan; | |
| 517 | + unsigned long csa_expire_time; | |
| 516 | 518 | }; |
| 517 | 519 | |
| 518 | 520 | enum mwifiex_ba_status { |
| @@ -1021,6 +1023,24 @@ static inline bool mwifiex_is_skb_mgmt_frame(struct sk_buff *skb) · 502 unmodified lines | ||
| 1021 | 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 | 1044 | int mwifiex_init_shutdown_fw(struct mwifiex_private *priv, |
| 1025 | 1045 | u32 func_init_shutdown); |
| 1026 | 1046 | int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8); |
| @@ -575,6 +575,9 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, · 574 unmodified lines | ||
| 575 | 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 | 581 | chan_tlv_out->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); |
| 579 | 582 | |
| 580 | 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, · 23 unmodified lines | ||
| 604 | 607 | while (tlv_idx < max_chan_per_scan && |
| 605 | 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 | 615 | dev_dbg(priv->adapter->dev, |
| 608 | 616 | "info: Scan: Chan(%3d), Radio(%d)," |
| 609 | 617 | " Mode(%d, %d), Dur(%d)\n", |
| @@ -1594,6 +1602,9 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, · 984 unmodified lines | ||
| 1594 | 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 | 1608 | bytes_left = le16_to_cpu(scan_rsp->bss_descript_size); |
| 1598 | 1609 | dev_dbg(adapter->dev, "info: SCAN_RESP: bss_descript_size %d\n", |
| 1599 | 1610 | bytes_left); |
| @@ -1746,6 +1757,13 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, · 146 unmodified lines | ||
| 1746 | 1757 | struct ieee80211_channel *chan; |
| 1747 | 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 | 1767 | band = BAND_G; |
| 1750 | 1768 | if (chan_band_tlv) { |
| 1751 | 1769 | chan_band = |
| @@ -429,6 +429,9 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) · 428 unmodified lines | ||
| 429 | 429 | |
| 430 | 430 | case EVENT_CHANNEL_SWITCH_ANN: |
| 431 | 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 | 435 | ret = mwifiex_send_cmd_async(priv, |
| 433 | 436 | HostCmd_CMD_802_11_DEAUTHENTICATE, |
| 434 | 437 | HostCmd_ACT_GEN_SET, 0, |
| @@ -281,6 +281,14 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, · 280 unmodified lines | ||
| 281 | 281 | if (ret) |
| 282 | 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 | 292 | dev_dbg(adapter->dev, "info: SSID found in scan list ... " |
| 285 | 293 | "associating...\n"); |
| 286 | 294 | |