qcacld-3.0: Configure preferred freq list as dynamic chan list

Configure the preferred channel list received from vendor
roam subcmd command ROAMING_SUBCMD_CONTROL_SET as dynamic channel
list to firmware. Combine this channel list with the existing
occupied channel list and send to firmware. Flush this channel
list as part of csr_cleanup

Change-Id: Ibc45291f72844331096cb460257cab6f0b0095dc
CRs-Fixed: 2507159
This commit is contained in:
Srinivas Dasari 2019-08-07 16:21:48 +05:30 • committed by nshrivas
commit 25d77b28e7
5 changed files with 386 additions and 1 deletions

View file

@ -3730,6 +3730,16 @@ wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER
#define PARAM_ROAM_ENABLE \
QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE
#define PARAM_ROAM_CONTROL_CONFIG \
QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_CONTROL
#define PARAM_FREQ_LIST_SCHEME \
QCA_ATTR_ROAM_CONTROL_FREQ_LIST_SCHEME
#define PARAM_FREQ_LIST_SCHEME_MAX \
QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_SCHEME_MAX
#define PARAM_SCAN_FREQ_LIST \
QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST
#define PARAM_SCAN_FREQ_LIST_TYPE \
QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_TYPE
static const struct nla_policy
@ -3751,6 +3761,7 @@ wlan_hdd_set_roam_param_policy[MAX_ROAMING_PARAM + 1] = {
[PARAM_ROAM_BSSID] = {.type = NLA_UNSPEC, .len = QDF_MAC_ADDR_SIZE},
[PARAM_SET_BSSID] = {.type = NLA_UNSPEC, .len = QDF_MAC_ADDR_SIZE},
[PARAM_SET_BSSID_HINT] = {.type = NLA_FLAG},
[PARAM_ROAM_CONTROL_CONFIG] = {.type = NLA_NESTED},
};
/**
@ -4029,6 +4040,129 @@ fail:
return -EINVAL;
}
static const struct nla_policy
roam_scan_freq_list_scheme_policy[PARAM_FREQ_LIST_SCHEME_MAX + 1] = {
[PARAM_SCAN_FREQ_LIST_TYPE] = {.type = NLA_U32},
[PARAM_SCAN_FREQ_LIST] = {.type = NLA_NESTED},
};
/**
* hdd_send_roam_scan_channel_freq_list_to_sme() - Send control roam scan freqs
* @hdd_ctx: HDD context
* @vdev_id: vdev id
* @tb: Nested attribute carrying frequency list scheme
*
* Extracts the frequency list and frequency list type from the frequency
* list scheme and send the frequencies to SME.
*
* Return: QDF_STATUS
*/
static QDF_STATUS
hdd_send_roam_scan_channel_freq_list_to_sme(struct hdd_context *hdd_ctx,
uint8_t vdev_id, struct nlattr *tb)
{
QDF_STATUS status;
struct nlattr *tb2[PARAM_FREQ_LIST_SCHEME_MAX + 1], *curr_attr;
uint8_t num_chan = 0;
uint32_t freq_list[SIR_MAX_SUPPORTED_CHANNEL_LIST] = {0};
uint32_t list_type;
mac_handle_t mac_handle = hdd_ctx->mac_handle;
int rem;
if (wlan_cfg80211_nla_parse_nested(tb2, PARAM_FREQ_LIST_SCHEME_MAX,
tb,
roam_scan_freq_list_scheme_policy)) {
hdd_err("nla_parse failed");
return QDF_STATUS_E_INVAL;
}
if (!tb2[PARAM_SCAN_FREQ_LIST] || !tb2[PARAM_SCAN_FREQ_LIST_TYPE]) {
hdd_err("ROAM_CONTROL_SCAN_FREQ_LIST or type are not present");
return QDF_STATUS_E_INVAL;
}
list_type = nla_get_u32(tb2[PARAM_SCAN_FREQ_LIST_TYPE]);
if (list_type != QCA_PREFERRED_SCAN_FREQ_LIST &&
list_type != QCA_SPECIFIC_SCAN_FREQ_LIST) {
hdd_err("Invalid freq list type received: %u", list_type);
return QDF_STATUS_E_INVAL;
}
nla_for_each_nested(curr_attr, tb2[PARAM_SCAN_FREQ_LIST], rem)
num_chan++;
if (num_chan > SIR_MAX_SUPPORTED_CHANNEL_LIST) {
hdd_err("number of channels (%d) supported exceeded max (%d)",
num_chan, SIR_MAX_SUPPORTED_CHANNEL_LIST);
return QDF_STATUS_E_INVAL;
}
num_chan = 0;
nla_for_each_nested(curr_attr, tb2[PARAM_SCAN_FREQ_LIST], rem)
freq_list[num_chan++] = nla_get_u32(curr_attr);
status = sme_update_roam_scan_freq_list(mac_handle, vdev_id, freq_list,
num_chan, list_type);
if (QDF_IS_STATUS_ERROR(status))
hdd_err("Failed to update channel list information");
return status;
}
static const struct nla_policy
roam_control_policy[QCA_ATTR_ROAM_CONTROL_MAX + 1] = {
[PARAM_FREQ_LIST_SCHEME] = {.type = NLA_NESTED},
};
/**
* hdd_set_roam_with_control_config() - Set roam control configuration
* @hdd_ctx: HDD context
* @tb: List of attributes carrying roam subcmd data
* @vdev_id: vdev id
*
* Extracts the attribute PARAM_ROAM_CONTROL_CONFIG from the attributes list tb
* and sends the corresponding roam control configuration to driver/firmware.
*
* Return: 0 on success; error number on failure
*/
static int
hdd_set_roam_with_control_config(struct hdd_context *hdd_ctx,
struct nlattr **tb,
uint8_t vdev_id)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct nlattr *tb2[QCA_ATTR_ROAM_CONTROL_MAX + 1], *attr;
/* The command must carry PARAM_ROAM_CONTROL_CONFIG */
if (!tb[PARAM_ROAM_CONTROL_CONFIG]) {
hdd_err("Attribute CONTROL_CONFIG is not present");
return -EINVAL;
}
if (wlan_cfg80211_nla_parse_nested(tb2, QCA_ATTR_ROAM_CONTROL_MAX,
tb[PARAM_ROAM_CONTROL_CONFIG],
roam_control_policy)) {
hdd_err("nla_parse failed");
return -EINVAL;
}
attr = tb2[PARAM_FREQ_LIST_SCHEME];
if (attr) {
status = hdd_send_roam_scan_channel_freq_list_to_sme(hdd_ctx,
vdev_id,
attr);
if (QDF_IS_STATUS_ERROR(status))
hdd_err("failed to config roam control");
}
return qdf_status_to_os_return(status);
}
#undef PARAM_ROAM_CONTROL_CONFIG
#undef PARAM_FREQ_LIST_SCHEME_MAX
#undef PARAM_FREQ_LIST_SCHEME
#undef PARAM_SCAN_FREQ_LIST
#undef PARAM_SCAN_FREQ_LIST_TYPE
/**
* hdd_set_ext_roam_params() - parse ext roam params
* @hdd_ctx: HDD context
@ -4168,6 +4302,11 @@ static int hdd_set_ext_roam_params(struct hdd_context *hdd_ctx,
if (ret)
goto fail;
break;
case QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_SET:
ret = hdd_set_roam_with_control_config(hdd_ctx, tb, vdev_id);
if (ret)
goto fail;
break;
}
return 0;

View file

@ -63,6 +63,7 @@ typedef struct sCsrNeighborRoamCfgParams {
uint32_t hi_rssi_scan_rssi_delta;
uint32_t hi_rssi_scan_delay;
int32_t hi_rssi_scan_rssi_ub;
tCsrChannelInfo pref_chan_info;
} tCsrNeighborRoamCfgParams, *tpCsrNeighborRoamCfgParams;
#define CSR_NEIGHBOR_ROAM_INVALID_CHANNEL_INDEX 255

View file

@ -854,6 +854,24 @@ QDF_STATUS sme_change_roam_scan_channel_list(mac_handle_t mac_handle,
uint8_t sessionId,
uint8_t *pChannelList,
uint8_t numChannels);
/**
* sme_update_roam_scan_freq_list() - Update roam scan freq list
* @mac_handle: Opaque handle to the global MAC context
* @vdev_id: vdev identifier
* @freq_list: List of frequencies to be configured
* @num_channels: Number of frequencies to be configured
* @freq_list_type: Type of frequency list to be configured to
*
* Update the frequencies from freq_list to the corresponding channel list
* in neighborRoamInfo
*
* Return: QDF_STATUS
*/
QDF_STATUS
sme_update_roam_scan_freq_list(mac_handle_t mac_handle, uint8_t vdev_id,
uint32_t *freq_list, uint8_t num_chan,
uint32_t freq_list_type);
QDF_STATUS sme_set_ese_roam_scan_channel_list(mac_handle_t mac_handle,
uint8_t sessionId,
uint8_t *pChannelList,
@ -862,6 +880,16 @@ QDF_STATUS sme_get_roam_scan_channel_list(mac_handle_t mac_handle,
uint8_t *pChannelList,
uint8_t *pNumChannels,
uint8_t sessionId);
/**
* sme_dump_freq_list() - Dump the frequencies from given chan info
* @chan_info: Contains the frequency list and number of frequencies
*
* Extract number of frequencies and frequency list from chan_info and print
* to the logs.
*
* Return: None
*/
void sme_dump_freq_list(tCsrChannelInfo *chan_info);
bool sme_get_is_ese_feature_enabled(mac_handle_t mac_handle);
bool sme_get_wes_mode(mac_handle_t mac_handle);
bool sme_get_roam_scan_control(mac_handle_t mac_handle);

View file

@ -7168,6 +7168,114 @@ uint8_t sme_get_roam_rssi_diff(mac_handle_t mac_handle)
return mac->mlme_cfg->lfr.roam_rssi_diff;
}
void sme_dump_freq_list(tCsrChannelInfo *chan_info)
{
uint8_t *channel_list;
uint8_t i = 0, j = 0;
uint32_t buflen = CFG_VALID_CHANNEL_LIST_LEN * 4;
channel_list = qdf_mem_malloc(buflen);
if (!channel_list)
return;
if (chan_info->freq_list) {
for (i = 0; i < chan_info->numOfChannels; i++) {
if (j < buflen)
j += snprintf(channel_list + j, buflen - j,
"%d ", chan_info->freq_list[i]);
else
break;
}
}
sme_debug("No.of frequencies: %u, frequency list: %s", i, channel_list);
qdf_mem_free(channel_list);
}
static bool sme_validate_freq_list(mac_handle_t mac_handle,
uint32_t *freq_list,
uint8_t num_channels)
{
struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
uint8_t i = 0, j;
bool found;
struct csr_channel *ch_lst_info = &mac_ctx->scan.base_channels;
if (!freq_list || !num_channels) {
sme_err("Freq list empty %pK or num_channels is 0", freq_list);
return false;
}
while (i < num_channels) {
found = false;
for (j = 0; j < ch_lst_info->numChannels; j++) {
if (wlan_reg_chan_to_freq(mac_ctx->pdev,
ch_lst_info->channelList[j])
== freq_list[i]) {
found = true;
break;
}
}
if (!found) {
sme_debug("Invalid frequency %u", freq_list[i]);
return false;
}
i++;
}
return true;
}
/**
* sme_update_roam_scan_channel_list() - to update scan channel list
* @mac_handle: Opaque handle to the global MAC context
* @vdev_id: vdev identifier
* @chan_info: Channel information to be updated to.
* @freq_list: Frequency list to be updated from.
* @num_chan: Number of channels
*
* Updates the chan_info by flushing the current frequency list and update
* the same with freq_list.
*
* Return: QDF_STATUS
*/
static QDF_STATUS
sme_update_roam_scan_channel_list(mac_handle_t mac_handle, uint8_t vdev_id,
tCsrChannelInfo *chan_info,
uint32_t *freq_list, uint8_t num_chan)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct mac_context *mac = MAC_CONTEXT(mac_handle);
uint8_t *channel_list;
channel_list = qdf_mem_malloc(SIR_MAX_SUPPORTED_CHANNEL_LIST);
if (!channel_list)
return QDF_STATUS_E_NOMEM;
if (chan_info->numOfChannels) {
sme_debug("Current channels:");
sme_dump_freq_list(chan_info);
}
csr_flush_cfg_bg_scan_roam_channel_list(chan_info);
sme_freq_to_chan_list(mac->pdev, channel_list, freq_list, num_chan);
csr_create_bg_scan_roam_channel_list(mac, chan_info, channel_list,
num_chan);
sme_debug("New channels:");
sme_dump_freq_list(chan_info);
sme_debug("Updated roam scan channels - roam state is %d",
mac->roam.neighborRoamInfo[vdev_id].neighborRoamState);
if (mac->mlme_cfg->lfr.roam_scan_offload_enabled)
status = csr_roam_offload_scan(mac, vdev_id,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_CHANNEL_LIST_CHANGED);
qdf_mem_free(channel_list);
return status;
}
/**
* sme_change_roam_scan_channel_list() - to change scan channel list
* @mac_handle: Opaque handle to the global MAC context
@ -7247,6 +7355,49 @@ QDF_STATUS sme_change_roam_scan_channel_list(mac_handle_t mac_handle,
return status;
}
QDF_STATUS
sme_update_roam_scan_freq_list(mac_handle_t mac_handle, uint8_t vdev_id,
uint32_t *freq_list, uint8_t num_chan,
uint32_t freq_list_type)
{
struct mac_context *mac = MAC_CONTEXT(mac_handle);
QDF_STATUS status;
tpCsrNeighborRoamControlInfo neighbor_roam_info;
tCsrChannelInfo *channel_info;
if (vdev_id >= WLAN_MAX_VDEVS) {
sme_err("Invalid vdev_id: %d", vdev_id);
return QDF_STATUS_E_INVAL;
}
if (!sme_validate_freq_list(mac_handle, freq_list, num_chan)) {
sme_err("List contains invalid channel(s)");
return QDF_STATUS_E_INVAL;
}
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_ERROR(status)) {
sme_err("Failed to acquire SME lock");
return status;
}
neighbor_roam_info = &mac->roam.neighborRoamInfo[vdev_id];
if (freq_list_type == QCA_PREFERRED_SCAN_FREQ_LIST) {
sme_debug("Preferred frequency list: ");
channel_info = &neighbor_roam_info->cfgParams.pref_chan_info;
} else {
goto out;
}
status = sme_update_roam_scan_channel_list(mac_handle, vdev_id,
channel_info, freq_list,
num_chan);
out:
sme_release_global_lock(&mac->sme);
return status;
}
/**
* sme_get_roam_scan_channel_list() - To get roam scan channel list
* @mac_handle: Opaque handle to the global MAC context

View file

@ -1599,6 +1599,29 @@ void csr_flush_cfg_bg_scan_roam_channel_list(tCsrChannelInfo *channel_info)
}
}
/**
* csr_flush_roam_scan_chan_lists() - Flush the roam channel lists
* @mac: Global MAC context
* @vdev_id: vdev id
*
* Flush the roam channel lists pref_chan_info and specific_chan_info.
*
* Return: None
*/
static void
csr_flush_roam_scan_chan_lists(struct mac_context *mac, uint8_t vdev_id)
{
tCsrChannelInfo *chan_info;
chan_info =
&mac->roam.neighborRoamInfo[vdev_id].cfgParams.pref_chan_info;
csr_flush_cfg_bg_scan_roam_channel_list(chan_info);
chan_info =
&mac->roam.neighborRoamInfo[vdev_id].cfgParams.specific_chan_info;
csr_flush_cfg_bg_scan_roam_channel_list(chan_info);
}
QDF_STATUS csr_create_bg_scan_roam_channel_list(struct mac_context *mac,
tCsrChannelInfo *channel_info,
const uint8_t *chan_list,
@ -17156,6 +17179,7 @@ void csr_cleanup_session(struct mac_context *mac, uint8_t vdev_id)
csr_free_connect_bss_desc(mac, vdev_id);
sme_reset_key(MAC_HANDLE(mac), vdev_id);
csr_reset_cfg_privacy(mac);
csr_flush_roam_scan_chan_lists(mac, vdev_id);
csr_roam_free_connect_profile(&pSession->connectedProfile);
csr_roam_free_connected_info(mac, &pSession->connectedInfo);
csr_roam_free_connected_info(mac,
@ -17971,6 +17995,40 @@ csr_fetch_valid_ch_lst(struct mac_context *mac_ctx,
return status;
}
/**
* csr_add_ch_lst_from_roam_scan_list() - channel from roam scan chan list
* parameters
* @mac_ctx: Global mac ctx
* @req_buf: out param, roam offload scan request packet
* @roam_info: roam info struct
*
* Return: QDF_STATUS
*/
static QDF_STATUS
csr_add_ch_lst_from_roam_scan_list(struct mac_context *mac_ctx,
struct roam_offload_scan_req *req_buf,
tpCsrNeighborRoamControlInfo roam_info)
{
QDF_STATUS status;
tCsrChannelInfo *pref_chan_info = &roam_info->cfgParams.pref_chan_info;
if (!pref_chan_info->numOfChannels)
return QDF_STATUS_SUCCESS;
status = csr_populate_roam_chan_list(mac_ctx,
&req_buf->ConnectedNetwork,
pref_chan_info);
if (status != QDF_STATUS_SUCCESS) {
sme_err("Failed to copy channels to roam list");
return status;
}
sme_debug("Added to roam chan list:");
sme_dump_freq_list(pref_chan_info);
req_buf->ChannelCacheType = CHANNEL_LIST_DYNAMIC;
return QDF_STATUS_SUCCESS;
}
/**
* csr_create_roam_scan_offload_request() - init roam offload scan request
*
@ -18136,7 +18194,8 @@ csr_create_roam_scan_offload_request(struct mac_context *mac_ctx,
curr_ch_lst_info->numOfChannels == 0) {
/*
* Retrieve the Channel Cache either from ini or from
* the occupied channels list.
* the occupied channels list along with preferred
* channel list configured by the client.
* Give Preference to INI Channels
*/
if (specific_chan_info->numOfChannels) {
@ -18154,6 +18213,13 @@ csr_create_roam_scan_offload_request(struct mac_context *mac_ctx,
csr_fetch_ch_lst_from_occupied_lst(mac_ctx,
session_id, reason, req_buf,
roam_info);
/* Add the preferred channel list configured by
* client to the roam channel list along with
* occupied channel list.
*/
csr_add_ch_lst_from_roam_scan_list(mac_ctx,
req_buf,
roam_info);
}
}
#ifdef FEATURE_WLAN_ESE