qcacld-3.0: Add WISA feature handling

Add support to enable WISA feature using QCA_NL80211_VENDOR_SUBCMD_WISA
and do scan blocking on WISA mode interface.

Change-Id: Ief105310fb71779b1a8c1d580408a489cad9977e
CRs-fixed: 997798
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index b4a2192..0b88ead 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -2780,7 +2780,7 @@
  *
  * @wiphy: wiphy device pointer
  * @wdev: wireless device pointer
- * @data: Vendof command data buffer
+ * @data: Vendor command data buffer
  * @data_len: Buffer length
  *
  * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
@@ -2804,6 +2804,95 @@
 	return ret;
 }
 
+static const struct nla_policy
+wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
+	[QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
+};
+
+/**
+ * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
+ * @wiphy: wiphy device pointer
+ * @wdev: wireless device pointer
+ * @data: Vendor command data buffer
+ * @data_len: Buffer length
+ *
+ * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
+ * setup WISA Mode features.
+ *
+ * Return: Success(0) or reason code for failure
+ */
+static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
+		struct wireless_dev *wdev, const void *data, int data_len)
+{
+	struct net_device *dev = wdev->netdev;
+	hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+	hdd_context_t *hdd_ctx  = wiphy_priv(wiphy);
+	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
+	struct sir_wisa_params wisa;
+	int ret_val;
+	QDF_STATUS status;
+	bool wisa_mode;
+
+	ENTER_DEV(dev);
+	ret_val = wlan_hdd_validate_context(hdd_ctx);
+	if (ret_val)
+		goto err;
+
+	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
+		hdd_err("Command not allowed in FTM mode");
+		return -EPERM;
+	}
+
+	if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
+		      wlan_hdd_wisa_cmd_policy)) {
+		hdd_err("Invalid WISA cmd attributes");
+		ret_val = -EINVAL;
+		goto err;
+	}
+	if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
+		hdd_err("Invalid WISA mode");
+		ret_val = -EINVAL;
+		goto err;
+	}
+
+	wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
+	hdd_info("WISA Mode: %d", wisa_mode);
+	wisa.mode = wisa_mode;
+	wisa.vdev_id = adapter->sessionId;
+	status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
+	if (!QDF_IS_STATUS_SUCCESS(status))
+		ret_val = -EINVAL;
+err:
+	EXIT();
+	return ret_val;
+}
+
+/**
+ * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
+ * @wiphy:          corestack handler
+ * @wdev:           wireless device
+ * @data:           data
+ * @data_len:       data length
+ *
+ * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
+ * setup WISA mode features.
+ *
+ * Return: Success(0) or reason code for failure
+ */
+static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
+						   struct wireless_dev *wdev,
+						   const void *data,
+						   int data_len)
+{
+	int ret;
+
+	cds_ssr_protect(__func__);
+	ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
+	cds_ssr_unprotect(__func__);
+
+	return ret;
+}
+
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 /**
  * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
@@ -5442,7 +5531,13 @@
 			WIPHY_VENDOR_CMD_NEED_NETDEV,
 		.doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
 	},
-
+	{
+		.info.vendor_id = QCA_NL80211_VENDOR_ID,
+		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+			WIPHY_VENDOR_CMD_NEED_NETDEV,
+		.doit = wlan_hdd_cfg80211_handle_wisa_cmd
+	},
 	{
 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h
index 0144b82..2ff4032 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.h
+++ b/core/hdd/src/wlan_hdd_cfg80211.h
@@ -259,6 +259,7 @@
  * @QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE: set tx power by percentage
  * @QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB: reduce tx power by DB
  * @QCA_NL80211_VENDOR_SUBCMD_TSF: TSF operations command
+ * @QCA_NL80211_VENDOR_SUBCMD_WISA: WISA mode configuration
  */
 
 enum qca_nl80211_vendor_subcmds {
@@ -379,7 +380,7 @@
 	/* Tx power scaling in db subcommands */
 	QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB = 115,
 	QCA_NL80211_VENDOR_SUBCMD_TSF = 119,
-
+	QCA_NL80211_VENDOR_SUBCMD_WISA = 120,
 };
 
 /**
@@ -1563,6 +1564,21 @@
 		QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_AFTER_LAST - 1,
 };
 
+/**
+ * enum qca_vendor_attr_wisa_cmd
+ * @QCA_WLAN_VENDOR_ATTR_WISA_INVALID: Invalid attr
+ * @QCA_WLAN_VENDOR_ATTR_WISA_MODE: WISA mode value attr (u32)
+ * @QCA_WLAN_VENDOR_ATTR_WISA_AFTER_LAST: After last
+ * @QCA_WLAN_VENDOR_ATTR_WISA_MAX: Max Value
+ * WISA setup vendor commands
+ */
+enum qca_vendor_attr_wisa_cmd {
+	QCA_WLAN_VENDOR_ATTR_WISA_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_WISA_MODE,
+	QCA_WLAN_VENDOR_ATTR_WISA_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_WISA_MAX =
+		QCA_WLAN_VENDOR_ATTR_WISA_AFTER_LAST - 1
+};
 
 /**
  * enum qca_wlan_vendor_attr_roam_auth - vendor event for roaming
diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h
index fb706bd..34e4ac7 100644
--- a/core/mac/inc/sir_api.h
+++ b/core/mac/inc/sir_api.h
@@ -4462,6 +4462,15 @@
 *tpSirExtScanResetBssidHotlistReqParams;
 
 /**
+ * struct sir_wisa_params - WISA Mode Parameters
+ * @mode: WISA mode
+ * @session_id: Session ID of vdev
+ */
+struct sir_wisa_params {
+	bool mode;
+	uint8_t vdev_id;
+};
+/**
  * struct sir_ssid_hotlist_param - param for SSID Hotlist
  * @ssid: SSID which is being hotlisted
  * @band: Band in which the given SSID should be scanned
diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h
index 9959dda..acedd40 100644
--- a/core/mac/src/include/sir_params.h
+++ b/core/mac/src/include/sir_params.h
@@ -607,6 +607,7 @@
 #define SIR_HAL_BPF_GET_CAPABILITIES_REQ     (SIR_HAL_ITC_MSG_TYPES_BEGIN + 341)
 #define SIR_HAL_BPF_SET_INSTRUCTIONS_REQ    (SIR_HAL_ITC_MSG_TYPES_BEGIN + 342)
 
+#define SIR_HAL_SET_WISA_PARAMS             (SIR_HAL_ITC_MSG_TYPES_BEGIN + 343)
 #define SIR_HAL_MSG_TYPES_END                (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF)
 
 /* CFG message types */
diff --git a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c
index 99ee02a..b533658 100644
--- a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c
+++ b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c
@@ -601,6 +601,7 @@
 #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
 		CASE_RETURN_STRING(WMA_SET_RSSI_MONITOR_REQ);
 		CASE_RETURN_STRING(WMA_FW_MEM_DUMP_REQ);
+		CASE_RETURN_STRING(WMA_SET_WISA_PARAMS);
 	default:
 		return (uint8_t *) "UNKNOWN";
 		break;
diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h
index 7b74226..f59be7b 100644
--- a/core/sme/inc/sme_api.h
+++ b/core/sme/inc/sme_api.h
@@ -891,7 +891,8 @@
 		void (*callback_routine)(void *cb_context,
 		struct fw_dump_rsp *rsp));
 QDF_STATUS sme_fw_mem_dump_unregister_cb(tHalHandle hHal);
-
+QDF_STATUS sme_set_wisa_params(tHalHandle hal,
+				struct sir_wisa_params *wisa_params);
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 QDF_STATUS sme_update_roam_offload_enabled(tHalHandle hHal,
 		bool nRoamOffloadEnabled);
diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c
index 03a9ee6..a0407e3 100644
--- a/core/sme/src/common/sme_api.c
+++ b/core/sme/src/common/sme_api.c
@@ -13304,6 +13304,39 @@
 	return status;
 }
 
+/**
+ * sme_send_wisa_params(): Pass WISA mode to WMA
+ * @hal: HAL context
+ * @wisa_params: pointer to WISA params struct
+ * @sessionId: SME session id
+ *
+ * Pass WISA params to WMA
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS sme_set_wisa_params(tHalHandle hal,
+				struct sir_wisa_params *wisa_params)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	tpAniSirGlobal mac = PMAC_STRUCT(hal);
+	cds_msg_t cds_message;
+	struct sir_wisa_params *cds_msg_wisa_params;
+
+	cds_msg_wisa_params = qdf_mem_malloc(sizeof(struct sir_wisa_params));
+	if (!cds_msg_wisa_params)
+		return QDF_STATUS_E_NOMEM;
+
+	*cds_msg_wisa_params = *wisa_params;
+	status = sme_acquire_global_lock(&mac->sme);
+	if (QDF_IS_STATUS_SUCCESS(status)) {
+		cds_message.bodyptr = cds_msg_wisa_params;
+		cds_message.type = WMA_SET_WISA_PARAMS;
+		status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
+		sme_release_global_lock(&mac->sme);
+	}
+	return status;
+}
+
 /* ---------------------------------------------------------------------------
     \fn sme_set_significant_change
     \brief  SME API to set significant change
diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h
index 2f47901..7cdcd9c 100644
--- a/core/wma/inc/wma_internal.h
+++ b/core/wma/inc/wma_internal.h
@@ -1101,11 +1101,9 @@
 	return QDF_STATUS_E_INVAL;
 }
 #endif
-
-
+QDF_STATUS wma_set_wisa_params(tp_wma_handle wma, struct sir_wisa_params *wisa);
 
 #ifdef WLAN_FEATURE_NAN
-
 QDF_STATUS wma_nan_req(void *wma_ptr, tpNanRequest nan_req);
 #endif
 
diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h
index 252d271..521d50b 100644
--- a/core/wma/inc/wma_types.h
+++ b/core/wma/inc/wma_types.h
@@ -399,6 +399,7 @@
 #define WMA_IPA_OFFLOAD_ENABLE_DISABLE        SIR_HAL_IPA_OFFLOAD_ENABLE_DISABLE
 
 #define WMA_GET_TEMPERATURE_REQ     SIR_HAL_GET_TEMPERATURE_REQ
+#define WMA_SET_WISA_PARAMS         SIR_HAL_SET_WISA_PARAMS
 
 #ifdef FEATURE_WLAN_EXTSCAN
 #define WMA_EXTSCAN_GET_CAPABILITIES_REQ    SIR_HAL_EXTSCAN_GET_CAPABILITIES_REQ
diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c
index b59374b..c0c98d5 100644
--- a/core/wma/src/wma_features.c
+++ b/core/wma/src/wma_features.c
@@ -459,6 +459,51 @@
 }
 #endif
 
+/**
+ * wma_set_wisa_params(): Set WISA features related params in FW
+ * @wma_handle: WMA handle
+ * @wisa: Pointer to WISA param struct
+ *
+ * Return: CDF status
+ */
+QDF_STATUS wma_set_wisa_params(tp_wma_handle wma_handle,
+				struct sir_wisa_params *wisa)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	wmi_buf_t buf;
+	wmi_vdev_wisa_cmd_fixed_param *cmd;
+	int ret, len = sizeof(*cmd);
+
+	buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
+	if (!buf) {
+		WMA_LOGP("%s: failed to allocate memory for WISA params",
+			 __func__);
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	cmd = (wmi_vdev_wisa_cmd_fixed_param *) wmi_buf_data(buf);
+	cmd->wisa_mode = wisa->mode;
+	cmd->vdev_id = wisa->vdev_id;
+
+	WMITLV_SET_HDR(&cmd->tlv_header,
+		WMITLV_TAG_STRUC_wmi_vdev_wisa_cmd_fixed_param,
+		WMITLV_GET_STRUCT_TLVLEN(
+				wmi_vdev_wisa_cmd_fixed_param));
+
+	ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
+				   WMI_VDEV_WISA_CMDID);
+	if (ret != EOK) {
+		WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
+		status = QDF_STATUS_E_FAILURE;
+		goto error;
+	}
+	return QDF_STATUS_SUCCESS;
+
+error:
+	wmi_buf_free(buf);
+	return status;
+}
+
 #ifdef FEATURE_WLAN_LPHB
 /**
  * wma_lphb_conf_hbenable() - enable command of LPHB configuration requests
diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c
index 92b63fc..603c7f5 100644
--- a/core/wma/src/wma_main.c
+++ b/core/wma/src/wma_main.c
@@ -5272,6 +5272,11 @@
 			(struct sir_ocb_get_tsf_timer *)msg->bodyptr);
 		qdf_mem_free(msg->bodyptr);
 		break;
+	case WMA_SET_WISA_PARAMS:
+		wma_set_wisa_params(wma_handle,
+			(struct sir_wisa_params *)msg->bodyptr);
+		qdf_mem_free(msg->bodyptr);
+		break;
 	case WMA_DCC_GET_STATS_CMD:
 		wma_dcc_get_stats(wma_handle,
 			(struct sir_dcc_get_stats *)msg->bodyptr);