qcacmn: Add support to get usable channels for NAN

Fetch usable channels for NAN iface mode from policy manager
or reg current channel list based on filter mask and
Update res msg channel list.

Change-Id: Ifa4ad4c7c8479f4a0ecc7dbe101f6507ff1525dc
CRs-Fixed: 2949340
This commit is contained in:
sheenam monga
2021-05-19 11:18:52 +05:30
committed by Madan Koyyalamudi
parent 09bb1c3ad0
commit ef4a346a73
2 changed files with 147 additions and 42 deletions

View File

@@ -35,7 +35,10 @@
#include "reg_build_chan_list.h" #include "reg_build_chan_list.h"
#include <wlan_objmgr_pdev_obj.h> #include <wlan_objmgr_pdev_obj.h>
#include <target_if.h> #include <target_if.h>
#ifdef WLAN_FEATURE_GET_USABLE_CHAN_LIST
#include "wlan_mlme_ucfg_api.h" #include "wlan_mlme_ucfg_api.h"
#include "wlan_nan_api.h"
#endif
const struct chan_map *channel_map; const struct chan_map *channel_map;
#ifdef CONFIG_CHAN_NUM_API #ifdef CONFIG_CHAN_NUM_API
@@ -3324,6 +3327,7 @@ is_freq_present_in_resp_list(uint32_t pcl_ch,
* @pcl_ch: pcl channel * @pcl_ch: pcl channel
* @len: calculated pcl len * @len: calculated pcl len
* @iface_mode_mask: interface type * @iface_mode_mask: interface type
* @band_mask: requested band mask
* @count: no of usable channels * @count: no of usable channels
* *
* Return: void * Return: void
@@ -3332,7 +3336,8 @@ static void
reg_update_usable_chan_resp(struct wlan_objmgr_pdev *pdev, reg_update_usable_chan_resp(struct wlan_objmgr_pdev *pdev,
struct get_usable_chan_res_params *res_msg, struct get_usable_chan_res_params *res_msg,
uint32_t *pcl_ch, uint32_t len, uint32_t *pcl_ch, uint32_t len,
uint32_t iface_mode_mask, int *count) uint32_t iface_mode_mask,
uint32_t band_mask, int *count)
{ {
int i; int i;
struct ch_params ch_params = {0}; struct ch_params ch_params = {0};
@@ -3348,6 +3353,10 @@ reg_update_usable_chan_resp(struct wlan_objmgr_pdev *pdev,
res_msg[i].iface_mode_mask |= 1 << iface_mode_mask; res_msg[i].iface_mode_mask |= 1 << iface_mode_mask;
continue; continue;
} }
if (!(band_mask & 1 << wlan_reg_freq_to_band(pcl_ch[i])))
continue;
ch_params.ch_width = CH_WIDTH_MAX; ch_params.ch_width = CH_WIDTH_MAX;
reg_set_channel_params_for_freq( reg_set_channel_params_for_freq(
pdev, pdev,
@@ -3375,6 +3384,7 @@ reg_update_usable_chan_resp(struct wlan_objmgr_pdev *pdev,
* @res_msg: Response msg * @res_msg: Response msg
* @policy_mgr_con_mode: policy mgr mode * @policy_mgr_con_mode: policy mgr mode
* @iftype: interface type * @iftype: interface type
* @band_mask: requested band mask
* @count: no of usable channels * @count: no of usable channels
* *
* Return: qdf status * Return: qdf status
@@ -3384,31 +3394,54 @@ reg_update_conn_chan_list(struct wlan_objmgr_pdev *pdev,
struct get_usable_chan_res_params *res_msg, struct get_usable_chan_res_params *res_msg,
enum policy_mgr_con_mode mode, enum policy_mgr_con_mode mode,
uint32_t iftype, uint32_t iftype,
uint32_t band_mask,
uint32_t *count) uint32_t *count)
{ {
uint32_t pcl_ch[NUM_CHANNELS] = {0}; uint32_t *pcl_ch;
uint8_t weight_list[NUM_CHANNELS] = {0}; uint8_t *weight_list;
uint32_t len; uint32_t len;
uint32_t weight_len; uint32_t weight_len;
struct wlan_objmgr_psoc *psoc; struct wlan_objmgr_psoc *psoc;
QDF_STATUS status = QDF_STATUS_SUCCESS; QDF_STATUS status = QDF_STATUS_SUCCESS;
psoc = wlan_pdev_get_psoc(pdev); pcl_ch = qdf_mem_malloc(NUM_CHANNELS *
if (!psoc) { sizeof(uint32_t));
reg_err("invalid psoc");
if (!pcl_ch) {
reg_err("pcl_ch invalid");
return QDF_STATUS_E_FAILURE; return QDF_STATUS_E_FAILURE;
} }
len = QDF_ARRAY_SIZE(pcl_ch); weight_list = qdf_mem_malloc(NUM_CHANNELS *
weight_len = QDF_ARRAY_SIZE(weight_list); sizeof(uint8_t));
if (!weight_list) {
reg_err("weight_list invalid");
qdf_mem_free(pcl_ch);
return QDF_STATUS_E_FAILURE;
}
psoc = wlan_pdev_get_psoc(pdev);
if (!psoc) {
reg_err("invalid psoc");
status = QDF_STATUS_E_FAILURE;
goto err;
}
len = NUM_CHANNELS;
weight_len = NUM_CHANNELS;
status = policy_mgr_get_pcl(psoc, mode, pcl_ch, &len, status = policy_mgr_get_pcl(psoc, mode, pcl_ch, &len,
weight_list, weight_len); weight_list, weight_len);
if (QDF_IS_STATUS_ERROR(status)) { if (QDF_IS_STATUS_ERROR(status)) {
reg_err("get pcl failed for mode: %d", mode); reg_err("get pcl failed for mode: %d", mode);
return status; goto err;
} }
reg_update_usable_chan_resp(pdev, res_msg, pcl_ch, len, iftype, count); reg_update_usable_chan_resp(pdev, res_msg, pcl_ch, len,
iftype, band_mask, count);
err:
qdf_mem_free(pcl_ch);
qdf_mem_free(weight_list);
return status; return status;
} }
@@ -3434,22 +3467,30 @@ reg_get_usable_channel_con_filter(struct wlan_objmgr_pdev *pdev,
if (req_msg.iface_mode_mask & 1 << IFTYPE_AP) { if (req_msg.iface_mode_mask & 1 << IFTYPE_AP) {
status = status =
reg_update_conn_chan_list(pdev, res_msg, PM_SAP_MODE, reg_update_conn_chan_list(pdev, res_msg, PM_SAP_MODE,
IFTYPE_AP, count); IFTYPE_AP, req_msg.band_mask, count);
} }
if (req_msg.iface_mode_mask & 1 << IFTYPE_STATION) { if (req_msg.iface_mode_mask & 1 << IFTYPE_STATION) {
status = status =
reg_update_conn_chan_list(pdev, res_msg, PM_STA_MODE, reg_update_conn_chan_list(pdev, res_msg, PM_STA_MODE,
IFTYPE_STATION, count); IFTYPE_STATION, req_msg.band_mask,
count);
} }
if (req_msg.iface_mode_mask & 1 << IFTYPE_P2P_GO) { if (req_msg.iface_mode_mask & 1 << IFTYPE_P2P_GO) {
status = status =
reg_update_conn_chan_list(pdev, res_msg, PM_P2P_GO_MODE, reg_update_conn_chan_list(pdev, res_msg, PM_P2P_GO_MODE,
IFTYPE_P2P_GO, count); IFTYPE_P2P_GO, req_msg.band_mask,
count);
} }
if (req_msg.iface_mode_mask & 1 << IFTYPE_P2P_CLIENT) { if (req_msg.iface_mode_mask & 1 << IFTYPE_P2P_CLIENT) {
status = status =
reg_update_conn_chan_list(pdev, res_msg, PM_P2P_CLIENT_MODE, reg_update_conn_chan_list(pdev, res_msg, PM_P2P_CLIENT_MODE,
IFTYPE_P2P_CLIENT, count); IFTYPE_P2P_CLIENT, req_msg.band_mask,
count);
}
if (req_msg.iface_mode_mask & 1 << IFTYPE_NAN) {
status =
reg_update_conn_chan_list(pdev, res_msg, PM_NAN_DISC_MODE,
IFTYPE_NAN, req_msg.band_mask, count);
} }
return status; return status;
} }
@@ -3471,7 +3512,8 @@ reg_remove_freq(struct get_usable_chan_res_params *res_msg,
} }
/** /**
* reg_skip_invalid_chan_for_sap_p2p_go() - Remove invalid freq for SAP & P2PGO * reg_skip_invalid_chan_freq() - Remove invalid freq for SAP, P2P GO
* and NAN
* @pdev: Pointer to pdev * @pdev: Pointer to pdev
* @res_msg: Response msg * @res_msg: Response msg
* @count: no of usable channels * @count: no of usable channels
@@ -3480,17 +3522,16 @@ reg_remove_freq(struct get_usable_chan_res_params *res_msg,
* Return: qdf status * Return: qdf status
*/ */
static QDF_STATUS static QDF_STATUS
reg_skip_invalid_chan_for_sap_p2p_go(struct wlan_objmgr_pdev *pdev, reg_skip_invalid_chan_freq(struct wlan_objmgr_pdev *pdev,
struct get_usable_chan_res_params *res_msg, struct get_usable_chan_res_params *res_msg,
uint32_t *no_usable_channels, uint32_t *no_usable_channels,
uint32_t iface_mode_mask) uint32_t iface_mode_mask)
{ {
uint32_t chan_enum, iface_mode = 0; uint32_t chan_enum, iface_mode = 0;
QDF_STATUS status = QDF_STATUS_SUCCESS; QDF_STATUS status = QDF_STATUS_SUCCESS;
bool include_indoor_channel; bool include_indoor_channel;
uint8_t enable_srd_chan, srd_mask = 0; uint8_t enable_srd_chan, srd_mask = 0;
struct wlan_objmgr_psoc *psoc; struct wlan_objmgr_psoc *psoc;
psoc = wlan_pdev_get_psoc(pdev); psoc = wlan_pdev_get_psoc(pdev);
if (!psoc) { if (!psoc) {
reg_err("invalid psoc"); reg_err("invalid psoc");
@@ -3518,27 +3559,42 @@ reg_skip_invalid_chan_for_sap_p2p_go(struct wlan_objmgr_pdev *pdev,
} else if (iface_mode_mask & (1 << IFTYPE_P2P_GO)) { } else if (iface_mode_mask & (1 << IFTYPE_P2P_GO)) {
srd_mask = 2; srd_mask = 2;
iface_mode = 1 << IFTYPE_P2P_GO; iface_mode = 1 << IFTYPE_P2P_GO;
} else if (iface_mode_mask & (1 << IFTYPE_NAN)) {
iface_mode = 1 << IFTYPE_NAN;
} else { } else {
break; break;
} }
for (chan_enum = 0; chan_enum < *no_usable_channels; for (chan_enum = 0; chan_enum < *no_usable_channels;
chan_enum++) { chan_enum++) {
if (wlan_reg_is_freq_indoor( if (iface_mode_mask & (1 << IFTYPE_NAN)) {
pdev, res_msg[chan_enum].freq) && if (res_msg[chan_enum].state ==
!include_indoor_channel) { CHANNEL_STATE_DISABLE ||
res_msg[chan_enum].iface_mode_mask &= !wlan_is_nan_allowed_on_freq(pdev,
res_msg[chan_enum].freq))
res_msg[chan_enum].iface_mode_mask &=
~(iface_mode); ~(iface_mode);
if (!res_msg[chan_enum].iface_mode_mask) if (!res_msg[chan_enum].iface_mode_mask)
reg_remove_freq(res_msg, chan_enum); reg_remove_freq(res_msg, chan_enum);
} } else {
if (wlan_reg_is_freq_indoor(
pdev, res_msg[chan_enum].freq) &&
!include_indoor_channel) {
res_msg[chan_enum].iface_mode_mask &=
~(iface_mode);
if (!res_msg[chan_enum].iface_mode_mask)
reg_remove_freq(res_msg,
chan_enum);
}
if (!(enable_srd_chan & srd_mask) && if (!(enable_srd_chan & srd_mask) &&
reg_is_etsi13_srd_chan( reg_is_etsi13_srd_chan_for_freq(
pdev, res_msg[chan_enum].freq)) { pdev, res_msg[chan_enum].freq)) {
res_msg[chan_enum].iface_mode_mask &= res_msg[chan_enum].iface_mode_mask &=
~(iface_mode); ~(iface_mode);
if (!res_msg[chan_enum].iface_mode_mask) if (!res_msg[chan_enum].iface_mode_mask)
reg_remove_freq(res_msg, chan_enum); reg_remove_freq(res_msg,
chan_enum);
}
} }
} }
@@ -3568,8 +3624,8 @@ reg_get_usable_channel_no_filter(struct wlan_objmgr_pdev *pdev,
QDF_STATUS status = QDF_STATUS_SUCCESS; QDF_STATUS status = QDF_STATUS_SUCCESS;
status = status =
reg_skip_invalid_chan_for_sap_p2p_go(pdev, res_msg, reg_skip_invalid_chan_freq(pdev, res_msg,
count, req_msg.iface_mode_mask); count, req_msg.iface_mode_mask);
return status; return status;
} }
@@ -3624,13 +3680,35 @@ reg_get_usable_channel_coex_filter(struct wlan_objmgr_pdev *pdev,
index++; index++;
} }
if (req_msg.iface_mode_mask & 1 << IFTYPE_AP || if (req_msg.iface_mode_mask & 1 << IFTYPE_AP ||
req_msg.iface_mode_mask & 1 << IFTYPE_P2P_GO) req_msg.iface_mode_mask & 1 << IFTYPE_P2P_GO ||
req_msg.iface_mode_mask & 1 << IFTYPE_NAN)
status = status =
reg_skip_invalid_chan_for_sap_p2p_go(pdev, res_msg, count, reg_skip_invalid_chan_freq(pdev, res_msg, count,
req_msg.iface_mode_mask); req_msg.iface_mode_mask);
return status; return status;
} }
/**
* reg_calculate_mode_mask() - calculate valid mode mask
* @iface_mode_mask: interface mode mask
*
* Return: Valid mode mask
*/
static uint32_t
reg_calculate_mode_mask(uint32_t iface_mode_mask)
{
int mode_mask = 0;
mode_mask = (iface_mode_mask & 1 << IFTYPE_STATION) |
(iface_mode_mask & 1 << IFTYPE_AP) |
(iface_mode_mask & 1 << IFTYPE_P2P_GO) |
(iface_mode_mask & 1 << IFTYPE_P2P_CLIENT) |
(iface_mode_mask & 1 << IFTYPE_P2P_DEVICE) |
(iface_mode_mask & 1 << IFTYPE_NAN);
return mode_mask;
}
/** /**
* reg_add_usable_channel_to_resp() - Add usable channels to resp structure * reg_add_usable_channel_to_resp() - Add usable channels to resp structure
* @pdev: Pointer to pdev * @pdev: Pointer to pdev
@@ -3639,9 +3717,9 @@ reg_get_usable_channel_coex_filter(struct wlan_objmgr_pdev *pdev,
* @chan_list: reg channel list * @chan_list: reg channel list
* @count: no of usable channels * @count: no of usable channels
* *
* Return: void * Return: qdf status
*/ */
static void static QDF_STATUS
reg_add_usable_channel_to_resp(struct wlan_objmgr_pdev *pdev, reg_add_usable_channel_to_resp(struct wlan_objmgr_pdev *pdev,
struct get_usable_chan_res_params *res_msg, struct get_usable_chan_res_params *res_msg,
uint32_t iface_mode_mask, uint32_t iface_mode_mask,
@@ -3650,6 +3728,7 @@ reg_add_usable_channel_to_resp(struct wlan_objmgr_pdev *pdev,
{ {
enum channel_enum chan_enum; enum channel_enum chan_enum;
struct ch_params ch_params = {0}; struct ch_params ch_params = {0};
QDF_STATUS status = QDF_STATUS_SUCCESS;
for (chan_enum = 0; chan_enum < *count; chan_enum++) { for (chan_enum = 0; chan_enum < *count; chan_enum++) {
ch_params.ch_width = CH_WIDTH_MAX; ch_params.ch_width = CH_WIDTH_MAX;
@@ -3659,8 +3738,14 @@ reg_add_usable_channel_to_resp(struct wlan_objmgr_pdev *pdev,
chan_list[chan_enum].max_bw, &ch_params); chan_list[chan_enum].max_bw, &ch_params);
res_msg[chan_enum].freq = chan_list[chan_enum].center_freq; res_msg[chan_enum].freq = chan_list[chan_enum].center_freq;
res_msg[chan_enum].iface_mode_mask = iface_mode_mask; res_msg[chan_enum].iface_mode_mask =
reg_calculate_mode_mask(iface_mode_mask);
if (!res_msg[chan_enum].iface_mode_mask) {
reg_err("invalid iface mask");
return QDF_STATUS_E_FAILURE;
}
res_msg[chan_enum].bw = chan_list[chan_enum].max_bw; res_msg[chan_enum].bw = chan_list[chan_enum].max_bw;
res_msg[chan_enum].state = chan_list[chan_enum].state;
if (ch_params.center_freq_seg0) if (ch_params.center_freq_seg0)
res_msg[chan_enum].seg0_freq = res_msg[chan_enum].seg0_freq =
ch_params.center_freq_seg0; ch_params.center_freq_seg0;
@@ -3668,6 +3753,8 @@ reg_add_usable_channel_to_resp(struct wlan_objmgr_pdev *pdev,
res_msg[chan_enum].seg1_freq = res_msg[chan_enum].seg1_freq =
ch_params.center_freq_seg1; ch_params.center_freq_seg1;
} }
return status;
} }
QDF_STATUS QDF_STATUS
@@ -3676,19 +3763,31 @@ wlan_reg_get_usable_channel(struct wlan_objmgr_pdev *pdev,
struct get_usable_chan_res_params *res_msg, struct get_usable_chan_res_params *res_msg,
uint32_t *usable_channels) uint32_t *usable_channels)
{ {
struct regulatory_channel chan_list[NUM_CHANNELS]; struct regulatory_channel *chan_list;
QDF_STATUS status = QDF_STATUS_SUCCESS; QDF_STATUS status = QDF_STATUS_SUCCESS;
chan_list = qdf_mem_malloc(NUM_CHANNELS *
sizeof(*chan_list));
if (!chan_list) {
reg_err("chan_list invalid");
return QDF_STATUS_E_FAILURE;
}
if ((req_msg.filter_mask & 1 << FILTER_CELLULAR_COEX) || if ((req_msg.filter_mask & 1 << FILTER_CELLULAR_COEX) ||
(!(req_msg.filter_mask & 1 << FILTER_CELLULAR_COEX) && (!(req_msg.filter_mask & 1 << FILTER_CELLULAR_COEX) &&
!(req_msg.filter_mask & 1 << FILTER_WLAN_CONCURRENCY))) { !(req_msg.filter_mask & 1 << FILTER_WLAN_CONCURRENCY))) {
*usable_channels = reg_get_band_channel_list(pdev, *usable_channels = reg_get_band_channel_list(pdev,
req_msg.band_mask, req_msg.band_mask,
chan_list); chan_list);
status =
reg_add_usable_channel_to_resp(pdev, res_msg, reg_add_usable_channel_to_resp(pdev, res_msg,
req_msg.iface_mode_mask, req_msg.iface_mode_mask,
chan_list, usable_channels); chan_list, usable_channels);
if (QDF_IS_STATUS_ERROR(status)) {
qdf_mem_free(chan_list);
return status;
}
} }
if (req_msg.filter_mask & 1 << FILTER_CELLULAR_COEX) if (req_msg.filter_mask & 1 << FILTER_CELLULAR_COEX)
@@ -3706,7 +3805,9 @@ wlan_reg_get_usable_channel(struct wlan_objmgr_pdev *pdev,
status = status =
reg_get_usable_channel_no_filter(pdev, req_msg, res_msg, reg_get_usable_channel_no_filter(pdev, req_msg, res_msg,
chan_list, usable_channels); chan_list, usable_channels);
reg_debug("usable chan count is %d", *usable_channels);
qdf_mem_free(chan_list);
return status; return status;
} }
#endif #endif

View File

@@ -822,8 +822,9 @@ enum country_src {
* and therefore can't be created in the normal ways, use the * and therefore can't be created in the normal ways, use the
* %NL80211_CMD_START_P2P_DEVICE and %NL80211_CMD_STOP_P2P_DEVICE * %NL80211_CMD_START_P2P_DEVICE and %NL80211_CMD_STOP_P2P_DEVICE
* commands to create and destroy one * commands to create and destroy one
* @NL80211_IF_TYPE_OCB: Outside Context of a BSS * @IF_TYPE_OCB: Outside Context of a BSS
* This mode corresponds to the MIB variable dot11OCBActivated=true * This mode corresponds to the MIB variable dot11OCBActivated=true
* @IF_TYPE_NAN: NAN mode
* @IFTYPE_MAX: highest interface type number currently defined * @IFTYPE_MAX: highest interface type number currently defined
* @NUM_IFTYPES: number of defined interface types * @NUM_IFTYPES: number of defined interface types
* *
@@ -844,6 +845,7 @@ enum iftype {
IFTYPE_P2P_GO, IFTYPE_P2P_GO,
IFTYPE_P2P_DEVICE, IFTYPE_P2P_DEVICE,
IFTYPE_OCB, IFTYPE_OCB,
IFTYPE_NAN,
/* keep last */ /* keep last */
NUM_IFTYPES, NUM_IFTYPES,
@@ -866,6 +868,7 @@ enum usable_channels_filter {
* seg0_freq : seg0 freq * seg0_freq : seg0 freq
* seg1_freq: seg1 freq * seg1_freq: seg1 freq
* bw : bandwidth * bw : bandwidth
* state: channel state
* iface_mode_mask: interface mode mask * iface_mode_mask: interface mode mask
**/ **/
struct get_usable_chan_res_params { struct get_usable_chan_res_params {
@@ -874,6 +877,7 @@ struct get_usable_chan_res_params {
uint32_t seg1_freq; uint32_t seg1_freq;
uint32_t bw; uint32_t bw;
uint32_t iface_mode_mask; uint32_t iface_mode_mask;
enum channel_state state;
}; };
/** /**