diff --git a/core/hdd/src/wlan_hdd_nan_datapath.c b/core/hdd/src/wlan_hdd_nan_datapath.c index 885530731c..5c33825338 100644 --- a/core/hdd/src/wlan_hdd_nan_datapath.c +++ b/core/hdd/src/wlan_hdd_nan_datapath.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -200,15 +201,134 @@ static bool hdd_is_ndp_allowed(struct hdd_context *hdd_ctx) } #endif /* NDP_SAP_CONCURRENCY_ENABLE */ +static void hdd_swap_frequencies(uint32_t *a, uint32_t *b) +{ + *b ^= *a; + *a ^= *b; + *b ^= *a; +} + +/** + * hdd_ndi_config_ch_list() - Configure the channel list for NDI start + * @hdd_ctx: hdd context + * @ch_info: Buffer to fill supported channels, give preference to 5220 and 2437 + * to keep the legacy behavior intact + * + * Unlike traditional device modes, where the higher application + * layer initiates connect / join / start, the NAN data + * interface does not have any such formal requests. The NDI + * create request is responsible for starting the BSS as well. + * Use the 5GHz Band NAN Social channel for BSS start if target + * supports it, since a 2.4GHz channel will require a DBS HW mode change + * first on a DBS 2x2 MAC target. Use a 2.4 GHz Band NAN Social channel + * if the target is not 5GHz capable. If both of these channels are + * not available, pick the next available channel. This would be used just to + * start the NDI. Actual channel for NDP data transfer would be negotiated with + * peer later. + * + * Return: SUCCESS if some valid channels are obtained + */ +static QDF_STATUS +hdd_ndi_config_ch_list(struct hdd_context *hdd_ctx, + tCsrChannelInfo *ch_info) +{ + struct regulatory_channel *cur_chan_list; + int i = 0, swap_index = 0; + QDF_STATUS status; + + ch_info->numOfChannels = 0; + cur_chan_list = qdf_mem_malloc(sizeof(*cur_chan_list) * + (NUM_CHANNELS + 2)); + if (!cur_chan_list) + return QDF_STATUS_E_NOMEM; + + status = ucfg_reg_get_current_chan_list(hdd_ctx->pdev, cur_chan_list); + if (status != QDF_STATUS_SUCCESS) { + hdd_err_rl("Failed to get the current channel list"); + qdf_mem_free(cur_chan_list); + return QDF_STATUS_E_IO; + } + + ch_info->freq_list = qdf_mem_malloc(sizeof(uint32_t) * NUM_CHANNELS); + if (!ch_info->freq_list) { + qdf_mem_free(cur_chan_list); + return QDF_STATUS_E_NOMEM; + } + + for (i = 0; i < NUM_CHANNELS; i++) { + /** + * current channel list includes all channels. Exclude + * disabled channels + */ + if (cur_chan_list[i].chan_flags & REGULATORY_CHAN_DISABLED || + cur_chan_list[i].chan_flags & REGULATORY_CHAN_RADAR) + continue; + + /** + * do not include 6 GHz channels for now as NAN would need + * 2.4 GHz and 5 GHz channels for discovery. + * Need to consider the 6GHz channels when there is a + * case where all 2GHz and 5GHz channels are disabled and + * only 6GHz channels are enabled + */ + if (wlan_reg_is_6ghz_chan_freq(cur_chan_list[i].center_freq)) + continue; + + ch_info->freq_list[ch_info->numOfChannels++] = + cur_chan_list[i].center_freq; + } + + if (!ch_info->numOfChannels) { + status = QDF_STATUS_E_NULL_VALUE; + qdf_mem_free(ch_info->freq_list); + goto end; + } + + /** + * Keep the valid channels in list in below order, + * 149, 44, 6, rest of the channels + */ + for (i = ch_info->numOfChannels - 1; i >= 0; i--) { + if (ch_info->freq_list[i] != NAN_SOCIAL_FREQ_5GHZ_UPPER_BAND) + continue; + hdd_swap_frequencies(&ch_info->freq_list[i], + &ch_info->freq_list[swap_index]); + swap_index++; + break; + } + + for (i = ch_info->numOfChannels - 1; i >= 0; i--) { + if (ch_info->freq_list[i] != NAN_SOCIAL_FREQ_5GHZ_LOWER_BAND) + continue; + + hdd_swap_frequencies(&ch_info->freq_list[i], + &ch_info->freq_list[swap_index]); + swap_index++; + break; + } + + for (i = ch_info->numOfChannels - 1; i >= 0; i--) { + if (ch_info->freq_list[i] != NAN_SOCIAL_FREQ_2_4GHZ) + continue; + + hdd_swap_frequencies(&ch_info->freq_list[i], + &ch_info->freq_list[swap_index]); + break; + } + +end: + qdf_mem_free(cur_chan_list); + + return status; +} + /** * hdd_ndi_start_bss() - Start BSS on NAN data interface * @adapter: adapter context - * @oper_freq: freq on which the BSS to be started * * Return: 0 on success, error value on failure */ -static int hdd_ndi_start_bss(struct hdd_adapter *adapter, - qdf_freq_t oper_freq) +static int hdd_ndi_start_bss(struct hdd_adapter *adapter) { QDF_STATUS status; uint32_t roam_id; @@ -244,12 +364,11 @@ static int hdd_ndi_start_bss(struct hdd_adapter *adapter, roam_profile->csrPersona = adapter->device_mode; - if (!oper_freq) - oper_freq = NAN_SOCIAL_FREQ_2_4GHZ; - - roam_profile->ChannelInfo.numOfChannels = 1; - roam_profile->ChannelInfo.freq_list = (uint32_t *)&oper_freq; - + status = hdd_ndi_config_ch_list(hdd_ctx, &roam_profile->ChannelInfo); + if (!QDF_IS_STATUS_SUCCESS(status)) { + hdd_err("Get uapsd_mask failed"); + return -EINVAL; + } roam_profile->SSIDs.numOfSSIDs = 1; roam_profile->SSIDs.SSIDList->SSID.length = 0; @@ -273,6 +392,7 @@ static int hdd_ndi_start_bss(struct hdd_adapter *adapter, hdd_info("sme_RoamConnect issued successfully for NDI"); } + qdf_mem_free(roam_profile->ChannelInfo.freq_list); roam_profile->ChannelInfo.freq_list = NULL; roam_profile->ChannelInfo.numOfChannels = 0; @@ -620,7 +740,6 @@ int hdd_ndi_start(char *iface_name, uint16_t transaction_id) { int ret; QDF_STATUS status; - qdf_freq_t op_freq; struct hdd_adapter *adapter; struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); struct wlan_objmgr_vdev *vdev; @@ -656,24 +775,8 @@ int hdd_ndi_start(char *iface_name, uint16_t transaction_id) ucfg_nan_set_ndp_create_transaction_id(vdev, transaction_id); ucfg_nan_set_ndi_state(vdev, NAN_DATA_NDI_CREATING_STATE); hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_NAN_ID); - /* - * The NAN data interface has been created at this point. - * Unlike traditional device modes, where the higher application - * layer initiates connect / join / start, the NAN data - * interface does not have any such formal requests. The NDI - * create request is responsible for starting the BSS as well. - * Use the 5GHz Band NAN Social channel for BSS start if target - * supports it, since a 2.4GHz channel will require a DBS HW mode change - * first on a DBS 2x2 MAC target. Use a 2.4 GHz Band NAN Social channel - * if the target is not 5GHz capable. - */ - if (hdd_is_5g_supported(hdd_ctx)) - op_freq = NAN_SOCIAL_FREQ_5GHZ_LOWER_BAND; - else - op_freq = NAN_SOCIAL_FREQ_2_4GHZ; - - if (hdd_ndi_start_bss(adapter, op_freq)) { + if (hdd_ndi_start_bss(adapter)) { hdd_err("NDI start bss failed"); ret = -EFAULT; goto err_handler; diff --git a/os_if/nan/src/os_if_nan.c b/os_if/nan/src/os_if_nan.c index 22a6493a7d..0d49488439 100644 --- a/os_if/nan/src/os_if_nan.c +++ b/os_if/nan/src/os_if_nan.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -1055,6 +1056,16 @@ int os_if_nan_process_ndp_cmd(struct wlan_objmgr_psoc *psoc, switch (ndp_cmd_type) { case QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE: + /** + * NDI creation is not allowed if NAN discovery is not running. + * Allowing NDI creation when NAN discovery is not enabled may + * lead to issues if NDI has to be started in a + * 2GHz channel and if the target is not operating in DBS mode. + */ + if (!ucfg_is_nan_disc_active(psoc)) { + osif_err("NDI creation is not allowed when NAN discovery is not running"); + return -EOPNOTSUPP; + } return os_if_nan_process_ndi_create(psoc, tb); case QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE: return os_if_nan_process_ndi_delete(psoc, tb);