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
diff --git a/core/hdd/src/wlan_hdd_ext_scan.c b/core/hdd/src/wlan_hdd_ext_scan.c
index cb7b170..066a35d 100644
--- a/core/hdd/src/wlan_hdd_ext_scan.c
+++ b/core/hdd/src/wlan_hdd_ext_scan.c
@@ -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
@@ -1888,6 +1890,60 @@
}
/**
+ * 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
* @wdev: Pointer to wireless device
@@ -1898,24 +1954,20 @@
*/
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 @@
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, ¶ms->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 @@
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;
}
/**
diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h
index a13b17b..9a83acf 100644
--- a/core/mac/inc/sir_api.h
+++ b/core/mac/inc/sir_api.h
@@ -3905,7 +3905,6 @@
#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 @@
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;
diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h
index 041c8e5..d72b73b 100644
--- a/core/sme/inc/sme_api.h
+++ b/core/sme/inc/sme_api.h
@@ -983,9 +983,20 @@
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);
diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c
index 61efac0..7facf77 100644
--- a/core/sme/src/common/sme_api.c
+++ b/core/sme/src/common/sme_api.c
@@ -11178,36 +11178,37 @@
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;
}
diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h
index 2b5eaf4..59124c2 100644
--- a/core/wma/inc/wma_internal.h
+++ b/core/wma/inc/wma_internal.h
@@ -362,13 +362,17 @@
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);
diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c
index 21decf7..0c1b4f7 100644
--- a/core/wma/src/wma_main.c
+++ b/core/wma/src/wma_main.c
@@ -8149,8 +8149,7 @@
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:
diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c
index 99dab76..f988230 100644
--- a/core/wma/src/wma_scan_roam.c
+++ b/core/wma/src/wma_scan_roam.c
@@ -4628,56 +4628,22 @@
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);
}
/**