From 0db27ed872786b4da82517c2f09ffe5818976a5c Mon Sep 17 00:00:00 2001 From: Srishti Piplani Date: Fri, 8 Jun 2018 12:09:30 +0530 Subject: [PATCH] [7872] wlbt: [Katmai O]Soft AP should not start on NO-OUTDOOR channels Whenever softAP tries to start on any indoor channel, the driver will move the softAP to a valid channel and send channel switched notification. Change-Id: I4261baf3ba0fe63eb68b170b28a2492583e9e9ce SCSC-Bug-Id: SSB-40331 Signed-off-by: Srishti Piplani --- drivers/net/wireless/scsc/cfg80211_ops.c | 43 +++++++++++++--------- drivers/net/wireless/scsc/dev.c | 2 +- drivers/net/wireless/scsc/dev.h | 3 +- drivers/net/wireless/scsc/mgt.c | 39 ++++++++++++++++---- drivers/net/wireless/scsc/mgt.h | 5 ++- drivers/net/wireless/scsc/nl80211_vendor.c | 4 +- 6 files changed, 66 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/scsc/cfg80211_ops.c b/drivers/net/wireless/scsc/cfg80211_ops.c index 630a0de569b9..73597861b99c 100755 --- a/drivers/net/wireless/scsc/cfg80211_ops.c +++ b/drivers/net/wireless/scsc/cfg80211_ops.c @@ -1874,13 +1874,15 @@ int slsi_start_ap(struct wiphy *wiphy, struct net_device *dev, bool append_vht_ies = false; const u8 *ie; #ifdef CONFIG_SCSC_WLAN_WIFI_SHARING - int channel_switched_flag = 0; + int wifi_sharing_channel_switched = 0; u8 *ds_params_ie = NULL; struct ieee80211_mgmt *mgmt; u16 beacon_ie_head_len; u8 *ht_operation_ie; struct netdev_vif *ndev_sta_vif; #endif + struct ieee80211_channel *channel = NULL; + int indoor_channel = 0; SLSI_MUTEX_LOCK(sdev->start_stop_mutex); if (sdev->device_state != SLSI_DEVICE_STATE_STARTED) { @@ -1903,11 +1905,20 @@ int slsi_start_ap(struct wiphy *wiphy, struct net_device *dev, if ((ndev_sta_vif->activated) && (ndev_sta_vif->vif_type == FAPI_VIFTYPE_STATION) && (ndev_sta_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTING || ndev_sta_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTED)) { - slsi_select_wifi_sharing_ap_channel(wiphy, dev, settings, sdev, &channel_switched_flag); + slsi_select_wifi_sharing_ap_channel(wiphy, dev, settings, sdev, &wifi_sharing_channel_switched); } SLSI_MUTEX_UNLOCK(ndev_sta_vif->vif_mutex); } #endif + + channel = ieee80211_get_channel(sdev->wiphy, settings->chandef.chan->center_freq); + if ((channel->flags) & (IEEE80211_CHAN_INDOOR_ONLY)) { + settings->chandef.chan = ieee80211_get_channel(wiphy, + sdev->device_config.domain_info.no_indoor_freq); + settings->chandef.center_freq1 = sdev->device_config.domain_info.no_indoor_freq; + indoor_channel = 1; + } + r = slsi_ap_start_validate(dev, sdev, settings); if (r != 0) goto exit_with_vif_mutex; @@ -1967,7 +1978,7 @@ int slsi_start_ap(struct wiphy *wiphy, struct net_device *dev, ndev_vif->chandef->center_freq1 = ieee80211_channel_to_frequency(155, NL80211_BAND_5GHZ); #ifdef CONFIG_SCSC_WLAN_WIFI_SHARING /* In wifi sharing case, AP can start on STA channel even though it is DFS channel*/ - if (channel_switched_flag == 1) { + if (wifi_sharing_channel_switched == 1) { if ((oper_chan >= 52) && (oper_chan <= 64)) ndev_vif->chandef->center_freq1 = ieee80211_channel_to_frequency(58, NL80211_BAND_5GHZ); @@ -2004,7 +2015,7 @@ int slsi_start_ap(struct wiphy *wiphy, struct net_device *dev, } #ifdef CONFIG_SCSC_WLAN_WIFI_SHARING - if (channel_switched_flag == 1) { + if (wifi_sharing_channel_switched == 1) { for (ch = 0; ch < ARRAY_SIZE(bw_40_minus_dfs_channels); ch++) if (oper_chan == bw_40_minus_dfs_channels[ch]) { ndev_vif->chandef->center_freq1 = ndev_vif->chandef->chan->center_freq - 10; @@ -2084,19 +2095,12 @@ int slsi_start_ap(struct wiphy *wiphy, struct net_device *dev, } #endif +if ((indoor_channel == 1) #ifdef CONFIG_SCSC_WLAN_WIFI_SHARING -if (channel_switched_flag == 1) { - ds_params_ie = (u8 *)cfg80211_find_ie(WLAN_EID_DS_PARAMS, mgmt->u.beacon.variable, beacon_ie_head_len); - slsi_modify_ies(dev, WLAN_EID_DS_PARAMS, mgmt->u.beacon.variable, - beacon_ie_head_len, 2, ieee80211_frequency_to_channel(settings->chandef.chan->center_freq)); - - ht_operation_ie = (u8 *)cfg80211_find_ie(WLAN_EID_HT_OPERATION, settings->beacon.tail, - settings->beacon.tail_len); - slsi_modify_ies(dev, WLAN_EID_HT_OPERATION, (u8 *)settings->beacon.tail, - settings->beacon.tail_len, 2, - ieee80211_frequency_to_channel(settings->chandef.chan->center_freq)); -} +|| (wifi_sharing_channel_switched == 1) #endif +) + slsi_modify_ies_on_channel_switch(dev, settings, ds_params_ie, ht_operation_ie, mgmt, beacon_ie_head_len); ndev_vif->vif_type = FAPI_VIFTYPE_AP; @@ -2180,12 +2184,17 @@ if (channel_switched_flag == 1) { r = slsi_mlme_start(sdev, dev, dev->dev_addr, settings, wpa_ie_pos, wmm_ie_pos, append_vht_ies); + if ((indoor_channel == 1) +#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING + || (wifi_sharing_channel_switched == 1) +#endif + ) + cfg80211_ch_switch_notify(dev, &settings->chandef); + #ifdef CONFIG_SCSC_WLAN_WIFI_SHARING if (r == 0) SLSI_NET_DBG1(dev, SLSI_CFG80211, "Soft Ap started on frequency: %d\n", settings->chandef.chan->center_freq); - if (channel_switched_flag == 1) - cfg80211_ch_switch_notify(dev, &settings->chandef); if (SLSI_IS_INTERFACE_WIFI_SHARING_AP(ndev_vif)) ndev_vif->chan = settings->chandef.chan; #endif diff --git a/drivers/net/wireless/scsc/dev.c b/drivers/net/wireless/scsc/dev.c index 72333e648387..b6578afe116b 100755 --- a/drivers/net/wireless/scsc/dev.c +++ b/drivers/net/wireless/scsc/dev.c @@ -170,7 +170,7 @@ static int slsi_dev_inet6addr_changed(struct notifier_block *nb, unsigned long d } #endif -static void slsi_regd_init(struct slsi_dev *sdev) +void slsi_regd_init(struct slsi_dev *sdev) { struct ieee80211_regdomain *slsi_world_regdom_custom = sdev->device_config.domain_info.regdomain; struct ieee80211_reg_rule reg_rules[] = { diff --git a/drivers/net/wireless/scsc/dev.h b/drivers/net/wireless/scsc/dev.h index a9c3a139e212..a144087ec545 100755 --- a/drivers/net/wireless/scsc/dev.h +++ b/drivers/net/wireless/scsc/dev.h @@ -725,7 +725,7 @@ struct netdev_vif { }; struct slsi_802_11d_reg_domain { - u8 alpha2[3]; + int no_indoor_freq; u8 *countrylist; struct ieee80211_regdomain *regdomain; int country_len; @@ -1082,6 +1082,7 @@ bool slsi_dev_epno_supported(void); bool slsi_dev_vo_vi_block_ack(void); int slsi_dev_get_scan_result_count(void); bool slsi_dev_llslogs_supported(void); +void slsi_regd_init(struct slsi_dev *sdev); static inline u16 slsi_tx_host_tag(struct slsi_dev *sdev, enum slsi_traffic_q tq) { diff --git a/drivers/net/wireless/scsc/mgt.c b/drivers/net/wireless/scsc/mgt.c index b8d624c661d7..ca6e3c7f1e49 100755 --- a/drivers/net/wireless/scsc/mgt.c +++ b/drivers/net/wireless/scsc/mgt.c @@ -387,7 +387,7 @@ int slsi_start(struct slsi_dev *sdev) goto err_hip_started; /* unifiDefaultCountry != world_domain */ - if (!(sdev->device_config.domain_info.alpha2[0] == '0' && sdev->device_config.domain_info.alpha2[1] == '0')) + if (!(alpha2[0] == '0' && alpha2[1] == '0')) if (memcmp(sdev->device_config.domain_info.regdomain->alpha2, alpha2, 2) != 0) { memcpy(sdev->device_config.domain_info.regdomain->alpha2, alpha2, 2); @@ -507,6 +507,8 @@ static void slsi_stop_chip(struct slsi_dev *sdev) if (sdev->netdev_up_count) return; + slsi_reset_channel_flags(sdev); + slsi_regd_init(sdev); sdev->device_state = SLSI_DEVICE_STATE_STOPPING; slsi_sm_wlan_service_stop(sdev); @@ -3803,6 +3805,7 @@ static void slsi_reg_mib_to_regd(struct slsi_mib_data *mib, struct slsi_802_11d_ u16 freq; u8 byte_val; struct ieee80211_reg_rule *reg_rule; + int freq_found = 0; domain_info->regdomain->alpha2[0] = *(u8 *)(&mib->data[i]); i++; @@ -3837,7 +3840,12 @@ static void slsi_reg_mib_to_regd(struct slsi_mib_data *mib, struct slsi_802_11d_ /* Flags 1 byte */ reg_rule->flags = slsi_remap_reg_rule_flags(*(u8 *)(&mib->data[i + 6])); - + if (!freq_found) + if (((reg_rule->freq_range.start_freq_khz / 1000000) == 5) && + !(reg_rule->flags & NL80211_RRF_NO_OUTDOOR)) { + domain_info->no_indoor_freq = (reg_rule->freq_range.start_freq_khz / 1000) + 10; + freq_found = 1; + } i += 7; num_rules++; /* Num of reg rules */ @@ -3969,6 +3977,21 @@ int slsi_set_mib_rssi_boost(struct slsi_dev *sdev, struct net_device *dev, u16 p return error; } +void slsi_modify_ies_on_channel_switch(struct net_device *dev, struct cfg80211_ap_settings *settings, + u8 *ds_params_ie, u8 *ht_operation_ie, struct ieee80211_mgmt *mgmt, + u16 beacon_ie_head_len) +{ + ds_params_ie = (u8 *)cfg80211_find_ie(WLAN_EID_DS_PARAMS, mgmt->u.beacon.variable, beacon_ie_head_len); + slsi_modify_ies(dev, WLAN_EID_DS_PARAMS, mgmt->u.beacon.variable, + beacon_ie_head_len, 2, ieee80211_frequency_to_channel(settings->chandef.chan->center_freq)); + + ht_operation_ie = (u8 *)cfg80211_find_ie(WLAN_EID_HT_OPERATION, settings->beacon.tail, + settings->beacon.tail_len); + slsi_modify_ies(dev, WLAN_EID_HT_OPERATION, (u8 *)settings->beacon.tail, + settings->beacon.tail_len, 2, + ieee80211_frequency_to_channel(settings->chandef.chan->center_freq)); +} + #ifdef CONFIG_SCSC_WLAN_WIFI_SHARING void slsi_extract_valid_wifi_sharing_channels(struct slsi_dev *sdev) { @@ -4010,7 +4033,7 @@ bool slsi_if_valid_wifi_sharing_channel(struct slsi_dev *sdev, int freq) void slsi_select_wifi_sharing_ap_channel(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ap_settings *settings, - struct slsi_dev *sdev, int *channel_switched_flag) + struct slsi_dev *sdev, int *wifi_sharing_channel_switched) { struct net_device *sta_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); struct netdev_vif *ndev_sta_vif = netdev_priv(sta_dev); @@ -4023,7 +4046,7 @@ void slsi_select_wifi_sharing_ap_channel(struct wiphy *wiphy, struct net_device /*if single antenna*/ #ifdef CONFIG_SCSC_WLAN_SINGLE_ANTENNA if ((settings->chandef.chan->center_freq) != (sta_frequency)) { - *channel_switched_flag = 1; + *wifi_sharing_channel_switched = 1; settings->chandef.chan = ieee80211_get_channel(wiphy, sta_frequency); settings->chandef.center_freq1 = sta_frequency; } @@ -4037,7 +4060,7 @@ void slsi_select_wifi_sharing_ap_channel(struct wiphy *wiphy, struct net_device settings->chandef.center_freq1 = settings->chandef.chan->center_freq; } else { if ((settings->chandef.chan->center_freq) != (sta_frequency)) { - *channel_switched_flag = 1; + *wifi_sharing_channel_switched = 1; settings->chandef.chan = ieee80211_get_channel(wiphy, sta_frequency); settings->chandef.center_freq1 = sta_frequency; } @@ -4049,7 +4072,7 @@ void slsi_select_wifi_sharing_ap_channel(struct wiphy *wiphy, struct net_device /* For single antenna */ #ifdef CONFIG_SCSC_WLAN_SINGLE_ANTENNA if ((settings->chandef.chan->center_freq) != (sta_frequency)) { - *channel_switched_flag = 1; + *wifi_sharing_channel_switched = 1; settings->chandef.chan = ieee80211_get_channel(wiphy, sta_frequency); settings->chandef.center_freq1 = sta_frequency; } @@ -4061,11 +4084,11 @@ void slsi_select_wifi_sharing_ap_channel(struct wiphy *wiphy, struct net_device ieee80211_frequency_to_channel(sta_frequency))) && slsi_if_valid_wifi_sharing_channel(sdev, sta_frequency)) { if ((settings->chandef.chan->center_freq) != (sta_frequency)) { - *channel_switched_flag = 1; + *wifi_sharing_channel_switched = 1; settings->chandef.chan = ieee80211_get_channel(wiphy, sta_frequency); } } else { - *channel_switched_flag = 1; + *wifi_sharing_channel_switched = 1; settings->chandef.chan = ieee80211_get_channel(wiphy, SLSI_2G_CHANNEL_ONE); settings->chandef.center_freq1 = SLSI_2G_CHANNEL_ONE; } diff --git a/drivers/net/wireless/scsc/mgt.h b/drivers/net/wireless/scsc/mgt.h index e0e493632e34..449904550ed8 100755 --- a/drivers/net/wireless/scsc/mgt.h +++ b/drivers/net/wireless/scsc/mgt.h @@ -424,12 +424,15 @@ int slsi_clear_packet_filters(struct slsi_dev *sdev, struct net_device *dev); int slsi_ap_prepare_add_info_ies(struct netdev_vif *ndev_vif, const u8 *ies, size_t ies_len); int slsi_set_mib_roam(struct slsi_dev *dev, struct net_device *ndev, u16 psid, int value); int slsi_set_mib_rssi_boost(struct slsi_dev *sdev, struct net_device *dev, u16 psid, int index, int boost); +void slsi_modify_ies_on_channel_switch(struct net_device *dev, struct cfg80211_ap_settings *settings, + u8 *ds_params_ie, u8 *ht_operation_ie, struct ieee80211_mgmt *mgmt, + u16 beacon_ie_head_len); #ifdef CONFIG_SCSC_WLAN_WIFI_SHARING bool slsi_if_valid_wifi_sharing_channel(struct slsi_dev *sdev, int freq); void slsi_extract_valid_wifi_sharing_channels(struct slsi_dev *sdev); void slsi_select_wifi_sharing_ap_channel(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ap_settings *settings, struct slsi_dev *sdev, - int *channel_switched_flag); + int *wifi_sharing_channel_switched); int slsi_set_mib_wifi_sharing_5ghz_channel(struct slsi_dev *sdev, u16 psid, int value, int offset, int readbyte, char *arg); int slsi_get_byte_position(int bit); diff --git a/drivers/net/wireless/scsc/nl80211_vendor.c b/drivers/net/wireless/scsc/nl80211_vendor.c index 2106dbe2280a..6b2908b7436e 100755 --- a/drivers/net/wireless/scsc/nl80211_vendor.c +++ b/drivers/net/wireless/scsc/nl80211_vendor.c @@ -2582,8 +2582,8 @@ static void slsi_lls_iface_stat_fill(struct slsi_dev *sdev, iface_stat->iface = NULL; iface_stat->info.mode = SLSI_LLS_INTERFACE_UNKNOWN; - iface_stat->info.country_str[0] = sdev->device_config.domain_info.alpha2[0]; - iface_stat->info.country_str[1] = sdev->device_config.domain_info.alpha2[1]; + iface_stat->info.country_str[0] = sdev->device_config.domain_info.regdomain->alpha2[0]; + iface_stat->info.country_str[1] = sdev->device_config.domain_info.regdomain->alpha2[1]; iface_stat->info.country_str[2] = ' '; /* 3rd char of our country code is ASCII */ for (i = 0; i < SLSI_LLS_AC_MAX; i++) -- 2.20.1