浏览代码

qcacmn: implement interfaces for configuring BT coex chain mode

Add interfaces for get/set BT coex chain mode.

CRs-Fixed: 2565088
Change-Id: If74dcba4ad3b69caa895264eaff64ef06b3b0714
Yu Wang 5 年之前
父节点
当前提交
a0dc6b9144

+ 37 - 0
os_if/linux/coex/inc/wlan_cfg80211_coex.h

@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: declares driver functions interfacing with linux kernel
+ */
+
+#ifndef _WLAN_CFG80211_COEX_H_
+#define _WLAN_CFG80211_COEX_H_
+#include <wlan_cfg80211.h>
+#include <wlan_objmgr_cmn.h>
+
+#ifdef FEATURE_COEX
+int wlan_cfg80211_coex_set_btc_chain_mode(struct wlan_objmgr_vdev *vdev,
+					  const void *data, int data_len);
+#else
+static inline int
+wlan_cfg80211_coex_set_btc_chain_mode(struct wlan_objmgr_vdev *vdev,
+				      const void *data, int data_len)
+{
+	return -ENOTSUPP;
+}
+#endif
+#endif

+ 135 - 0
os_if/linux/coex/src/wlan_cfg80211_coex.c

@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: defines driver functions interfacing with linux kernel
+ */
+#include <wmi_unified_param.h>
+#include <wlan_osif_request_manager.h>
+#include <osif_sync.h>
+#include <wlan_objmgr_psoc_obj_i.h>
+#include <wlan_coex_main.h>
+#include <wlan_coex_ucfg_api.h>
+#include <wlan_cfg80211_coex.h>
+
+static const struct nla_policy
+btc_chain_mode_policy[QCA_VENDOR_ATTR_BTC_CHAIN_MODE_MAX + 1] = {
+	[QCA_VENDOR_ATTR_BTC_CHAIN_MODE] = {.type = NLA_U32},
+	[QCA_VENDOR_ATTR_BTC_CHAIN_MODE_RESTART] = {.type = NLA_FLAG},
+};
+
+static int
+__wlan_cfg80211_coex_set_btc_chain_mode(struct wlan_objmgr_vdev *vdev,
+					uint8_t mode, bool do_restart)
+{
+	QDF_STATUS status;
+	uint8_t cur_mode;
+	int err;
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_objmgr_vdev *vdev_tmp;
+	int vdev_id;
+	struct coex_psoc_obj *coex_obj;
+
+	if (!vdev) {
+		coex_err("Null vdev");
+		return -EINVAL;
+	}
+
+	psoc = wlan_vdev_get_psoc(vdev);
+	if (!psoc) {
+		coex_err("NULL psoc");
+		return -EINVAL;
+	}
+
+	coex_obj = wlan_psoc_get_coex_obj(psoc);
+	if (!coex_obj)
+		return -EINVAL;
+
+	status = ucfg_coex_psoc_get_btc_chain_mode(psoc, &cur_mode);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		coex_err("failed to get cur BTC chain mode, status %d", status);
+		return -EFAULT;
+	}
+
+	if (cur_mode == mode)
+		return -EALREADY;
+
+	status = ucfg_coex_psoc_set_btc_chain_mode(psoc, mode);
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		coex_err("unable to set BTC chain mode to %d", mode);
+		return -EFAULT;
+	}
+
+	wlan_objmgr_for_each_psoc_vdev(psoc, vdev_id, vdev_tmp) {
+		status = ucfg_coex_send_btc_chain_mode(vdev, mode);
+		err = qdf_status_to_os_return(status);
+		if (err) {
+			coex_err("Failed to set btc chain mode to %d for vdev %d",
+				 mode, vdev_id);
+			return err;
+		}
+		coex_debug("Set btc chain mode to %d for vdev %d",
+			   mode, vdev_id);
+
+		if (!do_restart)
+			continue;
+
+		wlan_coex_config_updated(vdev, COEX_CONFIG_BTC_CHAIN_MODE);
+	}
+
+	return 0;
+}
+
+/**
+ * wlan_hdd_cfg80211_set_btc_chain_mode() - set btc chain mode
+ * @wiphy: pointer to wireless wiphy structure.
+ * @wdev: pointer to wireless_dev structure.
+ * @data: pointer to btc chain mode command parameters.
+ * @data_len: the length in byte of btc chain mode command parameters.
+ *
+ * Return: An error code or 0 on success.
+ */
+int wlan_cfg80211_coex_set_btc_chain_mode(struct wlan_objmgr_vdev *vdev,
+					  const void *data, int data_len)
+{
+	struct nlattr *tb[QCA_VENDOR_ATTR_BTC_CHAIN_MODE_MAX + 1];
+	uint32_t mode;
+	bool restart;
+
+	if (wlan_cfg80211_nla_parse(tb, QCA_VENDOR_ATTR_BTC_CHAIN_MODE_MAX,
+				    data, data_len, btc_chain_mode_policy)) {
+		coex_err("Invalid btc chain mode ATTR");
+		return -EINVAL;
+	}
+
+	if (!tb[QCA_VENDOR_ATTR_BTC_CHAIN_MODE]) {
+		coex_err("btc chain mode - no attr mode");
+		return -EINVAL;
+	}
+
+	mode = nla_get_u32(tb[QCA_VENDOR_ATTR_BTC_CHAIN_MODE]);
+	if (mode < QCA_BTC_CHAIN_SHARED || mode > QCA_BTC_CHAIN_SEPARATED) {
+		coex_err("Invalid btc chain mode %d", mode);
+		return -EINVAL;
+	}
+
+	restart = nla_get_flag(tb[QCA_VENDOR_ATTR_BTC_CHAIN_MODE_RESTART]);
+
+	coex_debug("vdev_id %u mode %u restart %u",
+		   wlan_vdev_get_id(vdev), mode, restart);
+
+	return __wlan_cfg80211_coex_set_btc_chain_mode(vdev, mode, restart);
+}

+ 24 - 0
umac/coex/core/inc/wlan_coex_main.h

@@ -36,10 +36,12 @@
 
 /**
  * struct coex_psoc_obj - coex object definition
+ * @btc_chain_mode: BT Coex chain mode.
  * @coex_config_updated: callback functions for each config type, which will
  *  be called when config is updated.
  */
 struct coex_psoc_obj {
+	uint8_t btc_chain_mode;
 	update_coex_cb coex_config_updated[COEX_CONFIG_TYPE_MAX];
 };
 
@@ -132,5 +134,27 @@ QDF_STATUS wlan_coex_psoc_created_notification(struct wlan_objmgr_psoc *psoc,
  */
 QDF_STATUS wlan_coex_psoc_destroyed_notification(struct wlan_objmgr_psoc *psoc,
 						 void *arg_list);
+
+/**
+ * wlan_coex_psoc_set_btc_chain_mode() - private API to set BT coex chain mode
+ * for psoc
+ * @psoc: pointer to psoc object
+ * @val: BT coex chain mode
+ *
+ * Return : status of operation
+ */
+QDF_STATUS
+wlan_coex_psoc_set_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t val);
+
+/**
+ * wlan_coex_psoc_get_btc_chain_mode() - private API to get BT coex chain mode
+ * from psoc
+ * @psoc: pointer to psoc object
+ * @val: pointer to BT coex chain mode
+ *
+ * Return : status of operation
+ */
+QDF_STATUS
+wlan_coex_psoc_get_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t *val);
 #endif
 #endif

+ 39 - 0
umac/coex/core/src/wlan_coex_main.c

@@ -71,6 +71,13 @@ QDF_STATUS wlan_coex_psoc_destroyed_notification(struct wlan_objmgr_psoc *psoc,
 QDF_STATUS
 wlan_coex_psoc_init(struct wlan_objmgr_psoc *psoc)
 {
+	struct coex_psoc_obj *coex_obj;
+
+	coex_obj = wlan_psoc_get_coex_obj(psoc);
+	if (!coex_obj)
+		return QDF_STATUS_E_INVAL;
+
+	coex_obj->btc_chain_mode = WLAN_COEX_BTC_CHAIN_MODE_UNSETTLED;
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -124,3 +131,35 @@ wlan_coex_config_updated(struct wlan_objmgr_vdev *vdev, uint8_t type)
 
 	return status;
 }
+
+QDF_STATUS
+wlan_coex_psoc_set_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t val)
+{
+	struct coex_psoc_obj *coex_obj;
+
+	coex_obj = wlan_psoc_get_coex_obj(psoc);
+	if (!coex_obj)
+		return QDF_STATUS_E_INVAL;
+
+	coex_obj->btc_chain_mode = val;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+wlan_coex_psoc_get_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t *val)
+{
+	struct coex_psoc_obj *coex_obj;
+
+	if (!val) {
+		coex_err("invalid param for getting btc chain mode");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	coex_obj = wlan_psoc_get_coex_obj(psoc);
+	if (!coex_obj)
+		return QDF_STATUS_E_INVAL;
+
+	*val = coex_obj->btc_chain_mode;
+	return QDF_STATUS_SUCCESS;
+}

+ 50 - 0
umac/coex/dispatcher/inc/wlan_coex_ucfg_api.h

@@ -24,6 +24,11 @@
 #include "qdf_status.h"
 #include <wlan_objmgr_vdev_obj.h>
 #include <wlan_objmgr_psoc_obj.h>
+#include "qca_vendor.h"
+
+#define WLAN_COEX_BTC_CHAIN_MODE_SHARED QCA_BTC_CHAIN_SHARED
+#define WLAN_COEX_BTC_CHAIN_MODE_SEPARATED QCA_BTC_CHAIN_SEPARATED
+#define WLAN_COEX_BTC_CHAIN_MODE_UNSETTLED 0xFF
 
 /**
  * enum coex_config_type - coex config type definitions
@@ -58,6 +63,36 @@ QDF_STATUS
 ucfg_coex_register_cfg_updated_handler(struct wlan_objmgr_psoc *psoc,
 				       enum coex_config_type type,
 				       update_coex_cb handler);
+
+/**
+ * ucfg_coex_psoc_set_btc_chain_mode() - API to set BT coex chain mode for psoc
+ * @psoc: pointer to psoc object
+ * @val: BT coex chain mode
+ *
+ * Return : status of operation
+ */
+QDF_STATUS
+ucfg_coex_psoc_set_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t val);
+
+/**
+ * ucfg_coex_psoc_get_btc_chain_mode() - API to get BT coex chain mode from psoc
+ * @psoc: pointer to psoc object
+ * @val: pointer to BT coex chain mode
+ *
+ * Return : status of operation
+ */
+QDF_STATUS
+ucfg_coex_psoc_get_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t *val);
+
+/**
+ * ucfg_coex_send_btc_chain_mode() - API to send BT coex config to target if
+ * @vdev: pointer to vdev object
+ * @mode: BT coex chain mode
+ *
+ * Return: status of operation
+ */
+QDF_STATUS
+ucfg_coex_send_btc_chain_mode(struct wlan_objmgr_vdev *vdev, uint8_t mode);
 #else
 static inline QDF_STATUS
 ucfg_coex_register_cfg_updated_handler(struct wlan_objmgr_psoc *psoc,
@@ -66,5 +101,20 @@ ucfg_coex_register_cfg_updated_handler(struct wlan_objmgr_psoc *psoc,
 {
 	return QDF_STATUS_SUCCESS;
 }
+
+static inline QDF_STATUS
+ucfg_coex_psoc_get_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t *val)
+{
+	if (val)
+		*val = WLAN_COEX_BTC_CHAIN_MODE_UNSETTLED;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline QDF_STATUS
+ucfg_coex_send_btc_chain_mode(struct wlan_objmgr_vdev *vdev, uint8_t mode)
+{
+	return QDF_STATUS_SUCCESS;
+}
 #endif
 #endif

+ 31 - 0
umac/coex/dispatcher/src/wlan_coex_ucfg_api.c

@@ -20,6 +20,7 @@
 
 #include <wlan_coex_main.h>
 #include <wlan_coex_ucfg_api.h>
+#include "wmi_unified.h"
 
 QDF_STATUS
 ucfg_coex_register_cfg_updated_handler(struct wlan_objmgr_psoc *psoc,
@@ -41,3 +42,33 @@ ucfg_coex_register_cfg_updated_handler(struct wlan_objmgr_psoc *psoc,
 
 	return QDF_STATUS_SUCCESS;
 }
+
+QDF_STATUS
+ucfg_coex_psoc_set_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t val)
+{
+	return wlan_coex_psoc_set_btc_chain_mode(psoc, val);
+}
+
+QDF_STATUS
+ucfg_coex_psoc_get_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t *val)
+{
+	return wlan_coex_psoc_get_btc_chain_mode(psoc, val);
+}
+
+QDF_STATUS
+ucfg_coex_send_btc_chain_mode(struct wlan_objmgr_vdev *vdev, uint8_t mode)
+{
+	struct coex_config_params param = {0};
+
+	if (mode != WLAN_COEX_BTC_CHAIN_MODE_SHARED &&
+	    mode != WLAN_COEX_BTC_CHAIN_MODE_SEPARATED)
+		return QDF_STATUS_E_INVAL;
+
+	param.vdev_id = wlan_vdev_get_id(vdev);
+	param.config_type = WMI_COEX_CONFIG_BTCOEX_SEPARATE_CHAIN_MODE;
+	param.config_arg1 = mode;
+
+	coex_debug("send btc chain mode %d for vdev %d", mode, param.vdev_id);
+
+	return wlan_coex_config_send(vdev, &param);
+}