return "SLSI_NL80211_RTT_RESULT_EVENT";
case SLSI_NL80211_RTT_COMPLETE_EVENT:
return "SLSI_NL80211_RTT_COMPLETE_EVENT";
- case SLSI_NL80211_VENDOR_ACS_EVENT:
- return "SLSI_NL80211_VENDOR_ACS_EVENT";
default:
return "UNKNOWN_EVENT";
}
#endif /* CONFIG_SCSC_WLAN_ENHANCED_LOGGING */
-static int slsi_acs_validate_width_hw_mode(struct slsi_acs_request *request)
-{
- if (request->hw_mode != SLSI_ACS_MODE_IEEE80211A && request->hw_mode != SLSI_ACS_MODE_IEEE80211B &&
- request->hw_mode != SLSI_ACS_MODE_IEEE80211G)
- return -EINVAL;
- if (request->ch_width != 20 && request->ch_width != 40 && request->ch_width != 80)
- return -EINVAL;
- return 0;
-}
-
-static int slsi_acs_init(struct wiphy *wiphy,
- struct wireless_dev *wdev, const void *data, int len)
-{
- struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
- struct net_device *dev = wdev->netdev;
- struct netdev_vif *ndev_vif;
- struct slsi_acs_request *request;
- int temp;
- int type;
- const struct nlattr *attr;
- int r = 0;
- u32 *freq_list;
- int freq_list_len = 0;
-
- SLSI_INFO(sdev, "SUBCMD_ACS_INIT Received\n");
- if (slsi_is_test_mode_enabled()) {
- SLSI_ERR(sdev, "Not supported in WlanLite mode\n");
- return -EOPNOTSUPP;
- }
- if (wdev->iftype != NL80211_IFTYPE_AP) {
- SLSI_ERR(sdev, "Invalid iftype: %d\n", wdev->iftype);
- return -EINVAL;
- }
- if (!dev) {
- SLSI_ERR(sdev, "Dev not found!\n");
- return -ENODEV;
- }
- request = kcalloc(1, sizeof(*request), GFP_KERNEL);
- if (!request) {
- SLSI_ERR(sdev, "No memory for request!");
- return -ENOMEM;
- }
- ndev_vif = netdev_priv(dev);
-
- SLSI_MUTEX_LOCK(ndev_vif->scan_mutex);
- nla_for_each_attr(attr, data, len, temp) {
- type = nla_type(attr);
- switch (type) {
- case SLSI_ACS_ATTR_HW_MODE:
- {
- request->hw_mode = nla_get_u8(attr);
- SLSI_INFO(sdev, "ACS hw mode: %d\n", request->hw_mode);
- break;
- }
- case SLSI_ACS_ATTR_CHWIDTH:
- {
- request->ch_width = nla_get_u16(attr);
- SLSI_INFO(sdev, "ACS ch_width: %d\n", request->ch_width);
- break;
- }
- case SLSI_ACS_ATTR_FREQ_LIST:
- {
- freq_list = kmalloc(nla_len(attr), GFP_KERNEL);
- if (!freq_list) {
- SLSI_ERR(sdev, "No memory for frequency list!");
- kfree(request);
- SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex);
- return -ENOMEM;
- }
- memcpy(freq_list, nla_data(attr), nla_len(attr));
- freq_list_len = nla_len(attr);
- break;
- }
- default:
- SLSI_ERR(sdev, "Invalid type : %d\n", type);
- break;
- }
- }
-
- r = slsi_acs_validate_width_hw_mode(request);
- if (r == 0 && freq_list_len) {
- struct ieee80211_channel *channels[freq_list_len];
- struct slsi_acs_chan_info ch_info[MAX_CHAN_VALUE_ACS];
- int i = 0, num_channels = 0;
- int idx;
- u32 chan_flags = (IEEE80211_CHAN_INDOOR_ONLY | IEEE80211_CHAN_RADAR |
- IEEE80211_CHAN_DISABLED |
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 10, 13)
- IEEE80211_CHAN_PASSIVE_SCAN
-#else
- IEEE80211_CHAN_NO_IR
-#endif
- );
-
- memset(channels, 0, sizeof(channels));
- memset(&ch_info, 0, sizeof(ch_info));
- for (i = 0; i < freq_list_len; i++) {
- channels[num_channels] = ieee80211_get_channel(wiphy, freq_list[i]);
- if (!channels[num_channels]) {
- SLSI_INFO(sdev, "Ignore invalid freq:%d in freq list\n", freq_list[i]);
- } else if (channels[num_channels]->flags & chan_flags) {
- SLSI_INFO(sdev, "Skip invalid channel:%d for ACS\n", channels[num_channels]->hw_value);
- } else {
- idx = slsi_find_chan_idx(channels[num_channels]->hw_value, request->hw_mode);
- ch_info[idx].chan = channels[num_channels]->hw_value;
- num_channels++;
- }
- }
- for (i = 0; i < 25; i++)
- SLSI_INFO(sdev, "Channel value:%d\n", ch_info[i].chan); /*will remove after testing */
- if (request->hw_mode == SLSI_ACS_MODE_IEEE80211A)
- request->ch_list_len = 25;
- else
- request->ch_list_len = 14;
- memcpy(&request->acs_chan_info[0], &ch_info[0], sizeof(ch_info));
- ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request = request;
- ndev_vif->scan[SLSI_SCAN_HW_ID].is_blocking_scan = false;
- r = slsi_mlme_add_scan(sdev,
- dev,
- FAPI_SCANTYPE_AP_AUTO_CHANNEL_SELECTION,
- FAPI_REPORTMODE_REAL_TIME,
- 0, /* n_ssids */
- NULL, /* ssids */
- num_channels,
- channels,
- NULL,
- NULL, /* ie */
- 0, /* ie_len */
- ndev_vif->scan[SLSI_SCAN_HW_ID].is_blocking_scan);
- } else {
- SLSI_ERR(sdev, "Invalid freq_list len:%d or ch_width:%d or hw_mode:%d\n", freq_list_len,
- request->ch_width, request->hw_mode);
- r = -EINVAL;
- kfree(request);
- }
- SLSI_INFO(sdev, "SUBCMD_ACS_INIT Received 7 return value:%d\n", r); /*will remove after testing */
- kfree(freq_list);
- SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex);
- return r;
-}
-
static const struct nl80211_vendor_cmd_info slsi_vendor_events[] = {
{ OUI_GOOGLE, SLSI_NL80211_SIGNIFICANT_CHANGE_EVENT },
{ OUI_GOOGLE, SLSI_NL80211_HOTLIST_AP_FOUND_EVENT },
{ OUI_GOOGLE, SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT},
{ OUI_GOOGLE, SLSI_NL80211_NAN_DISABLED_EVENT},
{ OUI_GOOGLE, SLSI_NL80211_RTT_RESULT_EVENT},
- { OUI_GOOGLE, SLSI_NL80211_RTT_COMPLETE_EVENT},
- { OUI_SAMSUNG, SLSI_NL80211_VENDOR_ACS_EVENT}
+ { OUI_GOOGLE, SLSI_NL80211_RTT_COMPLETE_EVENT}
};
static const struct wiphy_vendor_command slsi_vendor_cmd[] = {
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
.doit = slsi_rtt_cancel_config
- },
- {
- {
- .vendor_id = OUI_SAMSUNG,
- .subcmd = SLSI_NL80211_VENDOR_SUBCMD_ACS_INIT
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = slsi_acs_init
- },
+ }
};
void slsi_nl80211_vendor_deinit(struct slsi_dev *sdev)
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
#include "porting_imx.h"
#endif
+
struct ieee80211_channel *slsi_find_scan_channel(struct slsi_dev *sdev, struct ieee80211_mgmt *mgmt, size_t mgmt_len, u16 freq)
{
int ielen = mgmt_len - (mgmt->u.beacon.variable - (u8 *)mgmt);
SLSI_MUTEX_UNLOCK(ndev_vif->scan_result_mutex);
}
-int slsi_send_acs_event(struct slsi_dev *sdev, struct slsi_acs_selected_channels acs_selected_channels)
-{
- struct sk_buff *skb = NULL;
- u8 err = 0;
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
- skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE,
- SLSI_NL80211_VENDOR_ACS_EVENT, GFP_KERNEL);
-#else
- skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE,
- SLSI_NL80211_VENDOR_ACS_EVENT, GFP_KERNEL);
-#endif
- if (!skb) {
- SLSI_ERR_NODEV("Failed to allocate skb for VENDOR ACS event\n");
- return -ENOMEM;
- }
- err |= nla_put_u8(skb, SLSI_ACS_ATTR_PRIMARY_CHANNEL, acs_selected_channels.pri_channel);
- err |= nla_put_u8(skb, SLSI_ACS_ATTR_SECONDARY_CHANNEL, acs_selected_channels.sec_channel);
- err |= nla_put_u8(skb, SLSI_ACS_ATTR_VHT_SEG0_CENTER_CHANNEL, acs_selected_channels.vht_seg0_center_ch);
- err |= nla_put_u8(skb, SLSI_ACS_ATTR_VHT_SEG1_CENTER_CHANNEL, acs_selected_channels.vht_seg1_center_ch);
- err |= nla_put_u16(skb, SLSI_ACS_ATTR_CHWIDTH, acs_selected_channels.ch_width);
- err |= nla_put_u8(skb, SLSI_ACS_ATTR_HW_MODE, acs_selected_channels.hw_mode);
- SLSI_DBG3(sdev, SLSI_MLME, "pri_channel=%d,sec_channel=%d,vht_seg0_center_ch=%d,"
- "vht_seg1_center_ch=%d, ch_width=%d, hw_mode=%d\n",
- acs_selected_channels.pri_channel, acs_selected_channels.sec_channel,
- acs_selected_channels.vht_seg0_center_ch, acs_selected_channels.vht_seg1_center_ch,
- acs_selected_channels.ch_width, acs_selected_channels.hw_mode);
- if (err) {
- SLSI_ERR_NODEV("Failed nla_put err=%d\n", err);
- slsi_kfree_skb(skb);
- return -EINVAL;
- }
- SLSI_INFO(sdev, "Event: SLSI_NL80211_VENDOR_ACS_EVENT(%d)\n", SLSI_NL80211_VENDOR_ACS_EVENT);
- cfg80211_vendor_event(skb, GFP_KERNEL);
- return 0;
-}
-
-int slsi_set_2g_auto_channel(struct slsi_dev *sdev, struct netdev_vif *ndev_vif,
- struct slsi_acs_selected_channels *acs_selected_channels,
- struct slsi_acs_chan_info *ch_info)
-{
- int i = 0, j = 0, adjacent_rssi, avg_load, total_num_ap, total_rssi;
- bool all_bss_load = true, none_bss_load = true;
- int min_avg_chan_utilization = INT_MAX, min_adjacent_rssi = INT_MAX;
- int ch_idx_min_load = 0, ch_idx_min_rssi = 0;
- int min_avg_chan_utilization_20 = INT_MAX, min_adjacent_rssi_20 = INT_MAX;
- int ch_idx_min_load_20 = 0, ch_idx_min_rssi_20 = 0;
- int ret = 0;
- int ch_list_len = ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->ch_list_len;
-
- acs_selected_channels->ch_width = ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->ch_width;
- acs_selected_channels->hw_mode = ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->hw_mode;
-
- SLSI_DBG3(sdev, SLSI_MLME, "ch_lis_len:%d\n", ch_list_len);
- for (i = 0; i < ch_list_len; i++) {
- if (!ch_info[i].chan)
- continue;
- adjacent_rssi = 0; /* Assuming ch_list is in sorted order. */
- for (j = -2; j <= 2; j++)
- if (i + j >= 0 && i + j < ch_list_len)
- adjacent_rssi += ch_info[i + j].rssi_factor;
- ch_info[i].adj_rssi_factor = adjacent_rssi;
- if (ch_info[i].num_bss_load_ap != 0) {
- ch_info[i].avg_chan_utilization = ch_info[i].total_chan_utilization /
- ch_info[i].num_bss_load_ap;
- if (ch_info[i].avg_chan_utilization < min_avg_chan_utilization_20) {
- min_avg_chan_utilization_20 = ch_info[i].avg_chan_utilization;
- ch_idx_min_load_20 = i;
- } else if (ch_info[i].avg_chan_utilization == min_avg_chan_utilization_20 &&
- ch_info[i].num_ap < ch_info[ch_idx_min_load_20].num_ap) {
- ch_idx_min_load_20 = i;
- }
- none_bss_load = false;
- } else {
- SLSI_DBG3(sdev, SLSI_MLME, "BSS load IE not found\n");
- all_bss_load = false;
- }
- if (adjacent_rssi < min_adjacent_rssi_20) {
- min_adjacent_rssi_20 = adjacent_rssi;
- ch_idx_min_rssi_20 = i;
- } else if (adjacent_rssi == min_adjacent_rssi_20 &&
- ch_info[i].num_ap < ch_info[ch_idx_min_rssi_20].num_ap) {
- ch_idx_min_rssi_20 = i;
- }
- SLSI_DBG3(sdev, SLSI_MLME, "min rssi:%d min_rssi_idx:%d\n", min_adjacent_rssi_20, ch_idx_min_rssi_20);
- SLSI_DBG3(sdev, SLSI_MLME, "num_ap:%d,chan:%d,total_util:%d,avg_util:%d,rssi_fac:%d,adj_rssi_fac:%d,"
- "bss_ap:%d\n", ch_info[i].num_ap, ch_info[i].chan, ch_info[i].total_chan_utilization,
- ch_info[i].avg_chan_utilization, ch_info[i].rssi_factor, ch_info[i].adj_rssi_factor,
- ch_info[i].num_bss_load_ap);
- }
-
- if (acs_selected_channels->ch_width == 20) {
- if (all_bss_load)
- acs_selected_channels->pri_channel = ch_info[ch_idx_min_load_20].chan;
- else
- acs_selected_channels->pri_channel = ch_info[ch_idx_min_rssi_20].chan;
- } else if (acs_selected_channels->ch_width == 40) {
- for (i = 0; i < ch_list_len; i++) {
- if (i + 4 >= ch_list_len || !ch_info[i + 4].chan || !ch_info[i].chan)
- continue;
- avg_load = ch_info[i].avg_chan_utilization + ch_info[i + 4].avg_chan_utilization;
- total_num_ap = ch_info[i].num_ap + ch_info[i + 4].num_ap;
- total_rssi = ch_info[i].adj_rssi_factor + ch_info[i + 4].adj_rssi_factor;
-
- if (avg_load < min_avg_chan_utilization) {
- min_avg_chan_utilization = avg_load;
- ch_idx_min_load = i;
- } else if (avg_load == min_avg_chan_utilization &&
- total_num_ap < ch_info[ch_idx_min_load].num_ap +
- ch_info[ch_idx_min_load + 4].num_ap) {
- ch_idx_min_load = i;
- }
- if (total_rssi < min_adjacent_rssi) {
- min_adjacent_rssi = total_rssi;
- ch_idx_min_rssi = i;
- } else if (total_rssi == min_adjacent_rssi &&
- total_num_ap < ch_info[ch_idx_min_rssi].num_ap +
- ch_info[ch_idx_min_rssi + 4].num_ap) {
- ch_idx_min_rssi = i;
- }
- }
- if (all_bss_load) {
- acs_selected_channels->pri_channel = ch_info[ch_idx_min_load].chan;
- acs_selected_channels->sec_channel = ch_info[ch_idx_min_load].chan + 4;
- } else {
- acs_selected_channels->pri_channel = ch_info[ch_idx_min_rssi].chan;
- acs_selected_channels->sec_channel = ch_info[ch_idx_min_rssi].chan + 4;
- }
- }
- return ret;
-}
-
-int slsi_is_40mhz_5gchan(u8 pri_channel, u8 sec_channel)
-{
- int slsi_40mhz_chan[12] = {38, 46, 54, 62, 102, 110, 118, 126, 134, 142, 151, 159};
- int i;
-
- for (i = 0; i < 12; i++) {
- if (pri_channel == slsi_40mhz_chan[i] - 2 && sec_channel == slsi_40mhz_chan[i] + 2)
- return 1;
- else if (pri_channel < slsi_40mhz_chan[i])
- return 0;
- }
- return 0;
-}
-
-int slsi_is_80mhz_5gchan(u8 pri_channel, u8 last_channel)
-{
- int slsi_80mhz_chan[6] = {42, 58, 106, 122, 138, 155};
- int i;
-
- for (i = 0; i < 6; i++) {
- if (pri_channel == slsi_80mhz_chan[i] - 6 && last_channel == slsi_80mhz_chan[i] + 6)
- return 1;
- else if (pri_channel < slsi_80mhz_chan[i])
- return 0;
- }
- return 0;
-}
-
-int slsi_set_5g_auto_channel(struct slsi_dev *sdev, struct netdev_vif *ndev_vif,
- struct slsi_acs_selected_channels *acs_selected_channels,
- struct slsi_acs_chan_info *ch_info)
-{
- int i = 0, avg_load, total_num_ap;
- bool all_bss_load = true, none_bss_load = true;
- int min_num_ap = INT_MAX, min_avg_chan_utilization = INT_MAX;
- int ch_idx_min_load = 0, ch_idx_min_ap = 0;
- int min_avg_chan_utilization_20 = INT_MAX, min_num_ap_20 = INT_MAX;
- int ch_idx_min_load_20 = 0, ch_idx_min_ap_20 = 0;
- int ret = 0;
- int ch_list_len = ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->ch_list_len;
-
- acs_selected_channels->ch_width = ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->ch_width;
- acs_selected_channels->hw_mode = ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->hw_mode;
-
- SLSI_DBG3(sdev, SLSI_MLME, "ch_lis_len:%d\n", ch_list_len);
- for (i = 0; i < ch_list_len; i++) {
- if (!ch_info[i].chan)
- continue;
- if (ch_info[i].num_bss_load_ap != 0) {
- ch_info[i].avg_chan_utilization = ch_info[i].total_chan_utilization /
- ch_info[i].num_bss_load_ap;
- if (ch_info[i].avg_chan_utilization < min_avg_chan_utilization_20) {
- min_avg_chan_utilization_20 = ch_info[i].avg_chan_utilization;
- ch_idx_min_load_20 = i;
- } else if (ch_info[i].avg_chan_utilization == min_avg_chan_utilization_20 &&
- ch_info[i].num_ap < ch_info[ch_idx_min_load_20].num_ap) {
- ch_idx_min_load_20 = i;
- }
- none_bss_load = false;
- } else {
- if (ch_info[i].num_ap < min_num_ap_20) {
- min_num_ap_20 = ch_info[i].num_ap;
- ch_idx_min_ap_20 = i;
- }
- SLSI_DBG3(sdev, SLSI_MLME, "BSS load IE not found\n");
- ch_info[i].avg_chan_utilization = 128;
- all_bss_load = false;
- }
- SLSI_DBG3(sdev, SLSI_MLME, "num_ap:%d chan:%d, total_chan_util:%d, avg_chan_util:%d, bss_load_ap:%d\n",
- ch_info[i].num_ap, ch_info[i].chan, ch_info[i].total_chan_utilization,
- ch_info[i].avg_chan_utilization, ch_info[i].num_bss_load_ap);
- }
-
- if (acs_selected_channels->ch_width == 20) {
- if (all_bss_load || min_avg_chan_utilization_20 < 128)
- acs_selected_channels->pri_channel = ch_info[ch_idx_min_load_20].chan;
- else if (none_bss_load || min_avg_chan_utilization_20 >= 128)
- acs_selected_channels->pri_channel = ch_info[ch_idx_min_ap_20].chan;
- } else if (acs_selected_channels->ch_width == 40) {
- for (i = 0; i < ch_list_len; i++) {
- if (!ch_info[i].chan || i + 1 >= ch_list_len || !ch_info[i + 1].chan)
- continue;
- if (slsi_is_40mhz_5gchan(ch_info[i].chan, ch_info[i + 1].chan)) {
- avg_load = ch_info[i].avg_chan_utilization + ch_info[i + 1].avg_chan_utilization;
- total_num_ap = ch_info[i].num_ap + ch_info[i + 1].num_ap;
- if (avg_load < min_avg_chan_utilization) {
- min_avg_chan_utilization = avg_load;
- ch_idx_min_load = i;
- } else if (avg_load == min_avg_chan_utilization && total_num_ap <
- ch_info[ch_idx_min_load].num_ap + ch_info[ch_idx_min_load + 1].num_ap) {
- ch_idx_min_load = i;
- }
- if (total_num_ap < min_num_ap) {
- min_num_ap = total_num_ap;
- ch_idx_min_ap = i;
- }
- } else {
- SLSI_DBG3(sdev, SLSI_MLME, "Invalid channels: %d, %d\n", ch_info[i].chan,
- ch_info[i + 1].chan); /*will remove after testing */
- }
- }
- if (all_bss_load || min_avg_chan_utilization <= 256) {
- acs_selected_channels->pri_channel = ch_info[ch_idx_min_load].chan;
- acs_selected_channels->sec_channel = ch_info[ch_idx_min_load + 1].chan;
- } else if (none_bss_load || min_avg_chan_utilization > 256) {
- acs_selected_channels->pri_channel = ch_info[ch_idx_min_ap].chan;
- acs_selected_channels->sec_channel = ch_info[ch_idx_min_ap + 1].chan;
- }
- } else if (acs_selected_channels->ch_width == 80) {
- for (i = 0; i < ch_list_len; i++) {
- if (i + 3 >= ch_list_len)
- continue;
- if (!ch_info[i].chan || !ch_info[i + 1].chan || !ch_info[i + 2].chan || !ch_info[i + 3].chan)
- continue;
- if (slsi_is_80mhz_5gchan(ch_info[i].chan, ch_info[i + 3].chan)) {
- avg_load = ch_info[i].avg_chan_utilization + ch_info[i + 1].avg_chan_utilization +
- ch_info[i + 2].avg_chan_utilization + ch_info[i + 3].avg_chan_utilization;
- total_num_ap = ch_info[i].num_ap + ch_info[i + 1].num_ap + ch_info[i + 2].num_ap +
- ch_info[i + 3].num_ap;
- if (avg_load < min_avg_chan_utilization) {
- min_avg_chan_utilization = avg_load;
- ch_idx_min_load = i;
- } else if (avg_load == min_avg_chan_utilization && total_num_ap <
- (ch_info[ch_idx_min_load].num_ap + ch_info[ch_idx_min_load + 1].num_ap +
- ch_info[ch_idx_min_load + 2].num_ap +
- ch_info[ch_idx_min_load + 3].num_ap)) {
- ch_idx_min_load = i;
- }
- if (total_num_ap < min_num_ap) {
- min_num_ap = total_num_ap;
- ch_idx_min_ap = i;
- }
- } else {
- SLSI_DBG3(sdev, SLSI_MLME, "Invalid channels: %d, %d\n", ch_info[i].chan,
- ch_info[i + 3].chan); /*will remove after testing */
- }
- }
- if (all_bss_load || min_avg_chan_utilization <= 512) {
- acs_selected_channels->pri_channel = ch_info[ch_idx_min_load].chan;
- acs_selected_channels->vht_seg0_center_ch = ch_info[ch_idx_min_load].chan + 6;
- } else if (none_bss_load || min_avg_chan_utilization > 512) {
- acs_selected_channels->pri_channel = ch_info[ch_idx_min_ap].chan;
- acs_selected_channels->vht_seg0_center_ch = ch_info[ch_idx_min_ap].chan + 6;
- }
- }
- return ret;
-}
-
-struct slsi_acs_chan_info *slsi_acs_scan_results(struct slsi_dev *sdev, struct netdev_vif *ndev_vif, u16 scan_id)
-{
- struct sk_buff *scan_res;
- struct sk_buff *unique_scan;
- struct sk_buff_head unique_scan_results;
- struct slsi_acs_chan_info *ch_info = ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->acs_chan_info;
-
- SLSI_DBG3(sdev, SLSI_MLME, "Received acs_results\n");
- skb_queue_head_init(&unique_scan_results);
- SLSI_MUTEX_LOCK(ndev_vif->scan_result_mutex);
- scan_res = slsi_dequeue_cached_scan_result(&ndev_vif->scan[SLSI_SCAN_HW_ID], NULL);
-
- while (scan_res) {
- struct ieee80211_mgmt *mgmt = fapi_get_mgmt(scan_res);
- size_t mgmt_len = fapi_get_mgmtlen(scan_res);
- struct ieee80211_channel *scan_channel;
- int idx = 0;
- const u8 *ie_data;
- const u8 *ie;
- int ie_len;
- int ch_util = 128;
- /* ieee80211_mgmt structure is similar for Probe Response and Beacons */
- size_t ies_len = mgmt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
- /* make sure this BSSID has not already been used */
- skb_queue_walk(&unique_scan_results, unique_scan) {
- struct ieee80211_mgmt *unique_mgmt = fapi_get_mgmt(unique_scan);
-
- if (compare_ether_addr(mgmt->bssid, unique_mgmt->bssid) == 0)
- goto next_scan;
- }
- slsi_skb_queue_head(&unique_scan_results, scan_res);
- scan_channel = slsi_find_scan_channel(sdev, mgmt, mgmt_len,
- fapi_get_u16(scan_res, u.mlme_scan_ind.channel_frequency) / 2);
- if (!scan_channel)
- goto next_scan;
- SLSI_DBG3(sdev, SLSI_MLME, "scan result (scan_id:%d, %pM, channel:%d, rssi:%d, ie_len = %zu)\n",
- fapi_get_u16(scan_res, u.mlme_scan_ind.scan_id),
- fapi_get_mgmt(scan_res)->bssid, scan_channel->hw_value,
- fapi_get_s16(scan_res, u.mlme_scan_ind.rssi),
- ies_len);
-
- idx = slsi_find_chan_idx(scan_channel->hw_value, ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->hw_mode);
- SLSI_DBG3(sdev, SLSI_MLME, "chan_idx:%d chan_value: %d\n", idx, ch_info[idx].chan);
- if (ch_info[idx].chan) {
- ch_info[idx].num_ap += 1;
- ie = cfg80211_find_ie(WLAN_EID_QBSS_LOAD, mgmt->u.beacon.variable, ies_len);
- if (ie) {
- ie_len = ie[1];
- ie_data = &ie[2];
- if (ie_len >= 3) {
- ch_util = ie_data[2];
- ch_info[idx].num_bss_load_ap += 1;
- ch_info[idx].total_chan_utilization += ch_util;
- }
- }
- if (idx == scan_channel->hw_value - 1) /*if 2.4GHZ channel */
- ch_info[idx].rssi_factor += 10 ^ (fapi_get_s16(scan_res,
- u.mlme_scan_ind.rssi) / 10) * ch_util;
- } else {
- goto next_scan;
- }
-next_scan:
- scan_res = slsi_dequeue_cached_scan_result(&ndev_vif->scan[scan_id], NULL);
- }
- SLSI_MUTEX_UNLOCK(ndev_vif->scan_result_mutex);
- slsi_skb_queue_purge(&unique_scan_results);
- SLSI_DBG3(sdev, SLSI_MLME, "slsi_acs_scan_results Received end point\n"); /*will remove after testing */
- return ch_info;
-}
-
-void slsi_acs_scan_complete(struct slsi_dev *sdev, struct netdev_vif *ndev_vif, u16 scan_id)
-{
- struct slsi_acs_selected_channels acs_selected_channels;
- struct slsi_acs_chan_info *ch_info;
- int r = 0;
-
- memset(&acs_selected_channels, 0, sizeof(acs_selected_channels));
- ch_info = slsi_acs_scan_results(sdev, ndev_vif, scan_id);
- if (ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->hw_mode == SLSI_ACS_MODE_IEEE80211A)
- r = slsi_set_5g_auto_channel(sdev, ndev_vif, &acs_selected_channels, ch_info);
- else if (ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->hw_mode == SLSI_ACS_MODE_IEEE80211B ||
- ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->hw_mode == SLSI_ACS_MODE_IEEE80211G)
- r = slsi_set_2g_auto_channel(sdev, ndev_vif, &acs_selected_channels, ch_info);
- else
- r = -EINVAL;
- if (!r) {
- r = slsi_send_acs_event(sdev, acs_selected_channels);
- if (r != 0)
- SLSI_ERR(sdev, "Could not send ACS vendor event up\n");
- } else {
- SLSI_ERR(sdev, "set_auto_channel failed: %d\n", r);
- }
- sdev->acs_channel_switched = true;
- kfree(ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request);
- if (ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request)
- ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request = NULL;
-}
-
void slsi_rx_scan_done_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb)
{
u16 scan_id = fapi_get_u16(skb, u.mlme_scan_done_ind.scan_id);
SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
SLSI_MUTEX_LOCK(ndev_vif->scan_mutex);
- SLSI_NET_DBG3(dev, SLSI_GSCAN, "slsi_rx_scan_done_ind Received scan_id:%#x\n", scan_id);
#ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE
if (slsi_is_gscan_id(scan_id)) {
#endif
scan_id = (scan_id & 0xFF);
- if (scan_id == SLSI_SCAN_HW_ID && (ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req ||
- ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request))
+ if (scan_id == SLSI_SCAN_HW_ID && ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req)
cancel_delayed_work(&ndev_vif->scan_timeout_work);
- if (ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request)
- slsi_acs_scan_complete(sdev, ndev_vif, scan_id);
- else
- slsi_scan_complete(sdev, dev, scan_id, false);
+
+ slsi_scan_complete(sdev, dev, scan_id, false);
SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex);
SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);