qcacld-3.0: Refine the extscan start BSSID hotlist logic

Make the following updates to the extscan start BSSID hotlist logic:
1) Exclusively use the Unified WMI data structures.
2) Use the new wmi_unified_extscan_start_hotlist_monitor_cmd() API.
3) Update the HDD<=>SME interface to enforce the contract that SME
   must not make any assumptions about the buffers provided by HDD.

Change-Id: I4d9f982177bc61a751ba0e7437fe55482dfd2723
CRs-Fixed: 2291946
This commit is contained in:
Jeff Johnson 2018-07-13 23:14:32 -07:00 • committed by nshrivas
commit 1148cb0bb2
7 changed files with 163 additions and 182 deletions

View file

@ -31,6 +31,8 @@
#include "cds_sched.h"
#include <qca_vendor.h>
#define EXTSCAN_PARAM_MAX QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
/* amount of time to wait for a synchronous request/response operation */
#define WLAN_WAIT_TIME_EXTSCAN 1000
@ -1887,6 +1889,60 @@ int wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy,
return ret;
}
/**
* hdd_parse_ap_rssi_threshold() - parse AP RSSI threshold parameters
* @attr: netlink attribute containing the AP RSSI threshold parameters
* @ap: destination buffer for the parsed parameters
*
* This function parses the BSSID, low RSSI and high RSSI values from
* the @attr netlink attribute, storing the parsed values in @ap.
*
* Return: 0 if @attr is parsed and all required attributes are
* present, otherwise a negative errno.
*/
static int hdd_parse_ap_rssi_threshold(struct nlattr *attr,
struct ap_threshold_params *ap)
{
struct nlattr *tb[EXTSCAN_PARAM_MAX + 1];
int id;
if (wlan_cfg80211_nla_parse(tb, EXTSCAN_PARAM_MAX,
nla_data(attr), nla_len(attr),
wlan_hdd_extscan_config_policy)) {
hdd_err("nla_parse failed");
return -EINVAL;
}
/* Parse and fetch MAC address */
id = QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID;
if (!tb[id]) {
hdd_err("attr mac address failed");
return -EINVAL;
}
nla_memcpy(ap->bssid.bytes, tb[id], QDF_MAC_ADDR_SIZE);
hdd_debug("BSSID: " MAC_ADDRESS_STR, MAC_ADDR_ARRAY(ap->bssid.bytes));
/* Parse and fetch low RSSI */
id = QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW;
if (!tb[id]) {
hdd_err("attr low RSSI failed");
return -EINVAL;
}
ap->low = nla_get_s32(tb[id]);
hdd_debug("RSSI low %d", ap->low);
/* Parse and fetch high RSSI */
id = QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH;
if (!tb[id]) {
hdd_err("attr high RSSI failed");
return -EINVAL;
}
ap->high = nla_get_s32(tb[id]);
hdd_debug("RSSI High %d", ap->high);
return 0;
}
/**
* __wlan_hdd_cfg80211_extscan_set_bssid_hotlist() - set bssid hot list
* @wiphy: Pointer to wireless phy
@ -1898,24 +1954,20 @@ int wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy,
*/
static int
__wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy,
struct wireless_dev
*wdev, const void *data,
int data_len)
struct wireless_dev *wdev,
const void *data,
int data_len)
{
tpSirExtScanSetBssidHotListReqParams pReqMsg = NULL;
struct extscan_bssid_hotlist_set_params *params;
struct net_device *dev = wdev->netdev;
struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
1];
struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
+ 1];
struct nlattr *apTh;
struct nlattr *tb[EXTSCAN_PARAM_MAX + 1];
struct nlattr *apth;
struct hdd_ext_scan_context *context;
uint32_t request_id;
QDF_STATUS status;
uint8_t i;
int rem, retval;
int id, rem, retval;
unsigned long rc;
hdd_enter_dev(dev);
@ -1933,131 +1985,98 @@ __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy,
hdd_err("extscan not supported");
return -ENOTSUPP;
}
if (wlan_cfg80211_nla_parse(tb,
QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
data, data_len, wlan_hdd_extscan_config_policy)) {
if (wlan_cfg80211_nla_parse(tb, EXTSCAN_PARAM_MAX,
data, data_len,
wlan_hdd_extscan_config_policy)) {
hdd_err("Invalid ATTR");
return -EINVAL;
}
pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
if (!pReqMsg) {
params = qdf_mem_malloc(sizeof(*params));
if (!params) {
hdd_err("qdf_mem_malloc failed");
return -ENOMEM;
}
/* assume the worst until proven otherwise */
retval = -EINVAL;
/* Parse and fetch request Id */
if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
id = QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID;
if (!tb[id]) {
hdd_err("attr request id failed");
goto fail;
}
pReqMsg->requestId =
nla_get_u32(tb
[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
hdd_debug("Req Id %d", pReqMsg->requestId);
params->request_id = nla_get_u32(tb[id]);
hdd_debug("Req Id %d", params->request_id);
/* Parse and fetch number of APs */
if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]) {
id = QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP;
if (!tb[id]) {
hdd_err("attr number of AP failed");
goto fail;
}
pReqMsg->numAp =
nla_get_u32(tb
[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]);
if (pReqMsg->numAp > WLAN_EXTSCAN_MAX_HOTLIST_APS) {
params->num_ap = nla_get_u32(tb[id]);
if (params->num_ap > WMI_WLAN_EXTSCAN_MAX_HOTLIST_APS) {
hdd_err("Number of AP: %u exceeds max: %u",
pReqMsg->numAp, WLAN_EXTSCAN_MAX_HOTLIST_APS);
params->num_ap, WMI_WLAN_EXTSCAN_MAX_HOTLIST_APS);
goto fail;
}
pReqMsg->sessionId = adapter->session_id;
hdd_debug("Number of AP %d Session Id %d",
pReqMsg->numAp, pReqMsg->sessionId);
params->vdev_id = adapter->session_id;
hdd_debug("Number of AP %d vdev Id %d",
params->num_ap, params->vdev_id);
/* Parse and fetch lost ap sample size */
if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE]) {
id = QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE;
if (!tb[id]) {
hdd_err("attr lost ap sample size failed");
goto fail;
}
pReqMsg->lost_ap_sample_size = nla_get_u32(
tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE]);
params->lost_ap_sample_size = nla_get_u32(tb[id]);
hdd_debug("Lost ap sample size %d",
pReqMsg->lost_ap_sample_size);
params->lost_ap_sample_size);
if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM]) {
/* Parse the AP Threshold array */
id = QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM;
if (!tb[id]) {
hdd_err("attr ap threshold failed");
goto fail;
}
i = 0;
nla_for_each_nested(apTh,
tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM],
rem) {
if (i == pReqMsg->numAp) {
nla_for_each_nested(apth, tb[id], rem) {
if (i == params->num_ap) {
hdd_warn("Ignoring excess AP");
break;
}
if (wlan_cfg80211_nla_parse(tb2,
QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
nla_data(apTh), nla_len(apTh),
wlan_hdd_extscan_config_policy)) {
hdd_err("nla_parse failed");
retval = hdd_parse_ap_rssi_threshold(apth, &params->ap[i]);
if (retval)
goto fail;
}
/* Parse and fetch MAC address */
if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]) {
hdd_err("attr mac address failed");
goto fail;
}
nla_memcpy(pReqMsg->ap[i].bssid.bytes,
tb2
[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID],
QDF_MAC_ADDR_SIZE);
hdd_debug(MAC_ADDRESS_STR,
MAC_ADDR_ARRAY(pReqMsg->ap[i].bssid.bytes));
/* Parse and fetch low RSSI */
if (!tb2
[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]) {
hdd_err("attr low RSSI failed");
goto fail;
}
pReqMsg->ap[i].low =
nla_get_s32(tb2
[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]);
hdd_debug("RSSI low %d", pReqMsg->ap[i].low);
/* Parse and fetch high RSSI */
if (!tb2
[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]) {
hdd_err("attr high RSSI failed");
goto fail;
}
pReqMsg->ap[i].high =
nla_get_s32(tb2
[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]);
hdd_debug("RSSI High %d", pReqMsg->ap[i].high);
i++;
}
if (i < pReqMsg->numAp) {
if (i < params->num_ap) {
hdd_warn("Number of AP %u less than expected %u",
i, pReqMsg->numAp);
pReqMsg->numAp = i;
i, params->num_ap);
params->num_ap = i;
}
context = &ext_scan_context;
spin_lock(&context->context_lock);
INIT_COMPLETION(context->response_event);
context->request_id = request_id = pReqMsg->requestId;
context->request_id = params->request_id;
spin_unlock(&context->context_lock);
status = sme_set_bss_hotlist(hdd_ctx->mac_handle, pReqMsg);
status = sme_set_bss_hotlist(hdd_ctx->mac_handle, params);
if (!QDF_IS_STATUS_SUCCESS(status)) {
hdd_err("sme_set_bss_hotlist failed(err=%d)", status);
retval = qdf_status_to_os_return(status);
goto fail;
}
@ -2071,18 +2090,17 @@ __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy,
retval = -ETIMEDOUT;
} else {
spin_lock(&context->context_lock);
if (context->request_id == request_id)
if (context->request_id == params->request_id)
retval = context->response_status;
else
retval = -EINVAL;
spin_unlock(&context->context_lock);
}
hdd_exit();
return retval;
fail:
qdf_mem_free(pReqMsg);
return -EINVAL;
qdf_mem_free(params);
return retval;
}
/**

View file

@ -3905,7 +3905,6 @@ struct sir_wisa_params {
#define WLAN_EXTSCAN_MAX_CHANNELS 36
#define WLAN_EXTSCAN_MAX_BUCKETS 16
#define WLAN_EXTSCAN_MAX_HOTLIST_APS 128
#define WLAN_EXTSCAN_MAX_SIGNIFICANT_CHANGE_APS 64
typedef enum {
@ -4321,23 +4320,6 @@ typedef struct {
uint8_t sessionId;
} tSirExtScanStopReqParams, *tpSirExtScanStopReqParams;
/**
* struct tSirExtScanSetBssidHotListReqParams - set hotlist request
* @requestId: request identifier
* @sessionId: session identifier
* @lost_ap_sample_size: number of samples to confirm AP loss
* @numAp: Number of hotlist APs
* @ap: hotlist APs
*/
typedef struct {
uint32_t requestId;
uint8_t sessionId;
uint32_t lost_ap_sample_size;
uint32_t numAp;
tSirAPThresholdParam ap[WLAN_EXTSCAN_MAX_HOTLIST_APS];
} tSirExtScanSetBssidHotListReqParams, *tpSirExtScanSetBssidHotListReqParams;
typedef struct {
uint32_t requestId;
uint8_t sessionId;

View file

@ -983,9 +983,20 @@ QDF_STATUS sme_ext_scan_start(tHalHandle hHal,
tSirWifiScanCmdReqParams *pStartCmd);
QDF_STATUS sme_ext_scan_stop(tHalHandle hHal,
tSirExtScanStopReqParams *pStopReq);
QDF_STATUS sme_set_bss_hotlist(tHalHandle hHal,
tSirExtScanSetBssidHotListReqParams *
pSetHotListReq);
/**
* sme_set_bss_hotlist() - SME API to set BSSID hotlist
* @mac_handle: Opaque handle to the MAC context
* @params: extscan set hotlist structure
*
* Handles the request to set the BSSID hotlist in firmware.
*
* Return: QDF_STATUS
*/
QDF_STATUS
sme_set_bss_hotlist(mac_handle_t mac_handle,
struct extscan_bssid_hotlist_set_params *params);
QDF_STATUS sme_reset_bss_hotlist(tHalHandle hHal,
tSirExtScanResetBssidHotlistReqParams *
pResetReq);

View file

@ -11178,36 +11178,37 @@ QDF_STATUS sme_ext_scan_stop(tHalHandle hHal, tSirExtScanStopReqParams
return status;
}
/*
* sme_set_bss_hotlist() -
* SME API to set BSSID hotlist
*
* hHal
* pSetHotListReq: extscan set hotlist structure
* Return QDF_STATUS
*/
QDF_STATUS sme_set_bss_hotlist(tHalHandle hHal,
tSirExtScanSetBssidHotListReqParams *
pSetHotListReq)
QDF_STATUS
sme_set_bss_hotlist(mac_handle_t mac_handle,
struct extscan_bssid_hotlist_set_params *params)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status;
tpAniSirGlobal mac = MAC_CONTEXT(mac_handle);
struct scheduler_msg message = {0};
struct extscan_bssid_hotlist_set_params *bodyptr;
status = sme_acquire_global_lock(&pMac->sme);
/* per contract must make a copy of the params when messaging */
bodyptr = qdf_mem_malloc(sizeof(*bodyptr));
if (!bodyptr) {
sme_err("buffer allocation failure");
return QDF_STATUS_E_NOMEM;
}
*bodyptr = *params;
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* Serialize the req through MC thread */
message.bodyptr = pSetHotListReq;
message.bodyptr = bodyptr;
message.type = WMA_EXTSCAN_SET_BSSID_HOTLIST_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, message.type));
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status))
status = QDF_STATUS_E_FAILURE;
qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, message.type);
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
sme_release_global_lock(&mac->sme);
}
sme_release_global_lock(&pMac->sme);
if (QDF_IS_STATUS_ERROR(status)) {
sme_err("failure: %d", status);
qdf_mem_free(bodyptr);
}
return status;
}

View file

@ -362,13 +362,17 @@ QDF_STATUS wma_start_extscan(tp_wma_handle wma,
QDF_STATUS wma_stop_extscan(tp_wma_handle wma,
tSirExtScanStopReqParams *pstopcmd);
QDF_STATUS wma_get_buf_extscan_hotlist_cmd(tp_wma_handle wma_handle,
tSirExtScanSetBssidHotListReqParams *
photlist, int *buf_len);
/**
* wma_extscan_start_hotlist_monitor() - start hotlist monitor
* @wma: wma handle
* @params: hotlist request params
*
* This function configures hotlist monitor in fw.
*
* Return: QDF status
*/
QDF_STATUS wma_extscan_start_hotlist_monitor(tp_wma_handle wma,
tSirExtScanSetBssidHotListReqParams
*photlist);
struct extscan_bssid_hotlist_set_params *params);
QDF_STATUS wma_extscan_stop_hotlist_monitor(tp_wma_handle wma,
tSirExtScanResetBssidHotlistReqParams *photlist_reset);

View file

@ -8149,8 +8149,7 @@ static QDF_STATUS wma_mc_process_msg(struct scheduler_msg *msg)
qdf_mem_free(msg->bodyptr);
break;
case WMA_EXTSCAN_SET_BSSID_HOTLIST_REQ:
wma_extscan_start_hotlist_monitor(wma_handle,
(tSirExtScanSetBssidHotListReqParams *) msg->bodyptr);
wma_extscan_start_hotlist_monitor(wma_handle, msg->bodyptr);
qdf_mem_free(msg->bodyptr);
break;
case WMA_EXTSCAN_RESET_BSSID_HOTLIST_REQ:

View file

@ -4628,56 +4628,22 @@ static inline int wma_get_hotlist_entries_per_page(wmi_unified_t wmi_handle,
return num_entries;
}
/**
* wma_get_buf_extscan_hotlist_cmd() - prepare hotlist command
* @handle: wma handle
* @photlist: hotlist command params
* @buf_len: buffer length
*
* This function fills individual elements for hotlist request and
* TLV for bssid entries
*
* Return: QDF Status.
*/
QDF_STATUS wma_get_buf_extscan_hotlist_cmd(tp_wma_handle wma_handle,
tSirExtScanSetBssidHotListReqParams *photlist,
int *buf_len)
{
return wmi_unified_get_buf_extscan_hotlist_cmd(wma_handle->wmi_handle,
(struct ext_scan_setbssid_hotlist_params *)photlist,
buf_len);
}
/**
* wma_extscan_start_hotlist_monitor() - start hotlist monitor
* @wma: wma handle
* @photlist: hotlist request params
*
* This function configures hotlist monitor in fw.
*
* Return: QDF status
*/
QDF_STATUS wma_extscan_start_hotlist_monitor(tp_wma_handle wma,
tSirExtScanSetBssidHotListReqParams *photlist)
struct extscan_bssid_hotlist_set_params *params)
{
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
int len;
if (!wma || !wma->wmi_handle) {
WMA_LOGE("%s: WMA is closed, can not issue hotlist cmd",
__func__);
return QDF_STATUS_E_INVAL;
}
/* Fill individual elements for hotlist request and
* TLV for bssid entries
*/
qdf_status = wma_get_buf_extscan_hotlist_cmd(wma, photlist, &len);
if (qdf_status != QDF_STATUS_SUCCESS) {
WMA_LOGE("%s: Failed to get buffer for hotlist scan cmd",
__func__);
return QDF_STATUS_E_FAILURE;
if (!params) {
WMA_LOGE("%s: Invalid params", __func__);
return QDF_STATUS_E_INVAL;
}
return QDF_STATUS_SUCCESS;
return wmi_unified_extscan_start_hotlist_monitor_cmd(wma->wmi_handle,
params);
}
/**