[7872] wlbt: [Katmai O]Soft AP should not start on NO-OUTDOOR channels
authorSrishti Piplani <srishti.p@samsung.com>
Fri, 8 Jun 2018 06:39:30 +0000 (12:09 +0530)
committerTarun Karela <t.karela@samsung.com>
Fri, 22 Jun 2018 08:50:18 +0000 (09:50 +0100)
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 <srishti.p@samsung.com>
drivers/net/wireless/scsc/cfg80211_ops.c
drivers/net/wireless/scsc/dev.c
drivers/net/wireless/scsc/dev.h
drivers/net/wireless/scsc/mgt.c
drivers/net/wireless/scsc/mgt.h
drivers/net/wireless/scsc/nl80211_vendor.c

index 630a0de569b9b3d6cbd333ea4036d7ee70265c98..73597861b99c3547221355206a6e7c787cc1d040 100755 (executable)
@@ -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
index 72333e64838704c285ab069f9cff370a749e5e5d..b6578afe116b57897869e52b5d96e565ea539a4b 100755 (executable)
@@ -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[] = {
index a9c3a139e212bee2fe20d18f4fd1623156480a52..a144087ec5459f899065dca4f0c49eca8fa3530b 100755 (executable)
@@ -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)
 {
index b8d624c661d7ee6138c4b41f2ae75eace0e47384..ca6e3c7f1e49836af961be47f74540ab16db8d50 100755 (executable)
@@ -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;
                        }
index e0e493632e34b5d1a1aceabeab360edc56678884..449904550ed85a7a7081164d91a10426abfda7b1 100755 (executable)
@@ -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);
index 2106dbe2280aa482b2410b97a4939b4c1cebbbf0..6b2908b7436eed4fcc5e527a7d8813dc10a91d0a 100755 (executable)
@@ -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<space> */
 
        for (i = 0; i < SLSI_LLS_AC_MAX; i++)