mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-19 10:23:03 +00:00
613 lines
19 KiB
Diff
613 lines
19 KiB
Diff
--- a/drivers/net/wireless/ath/ath11k/Makefile
|
|
+++ b/drivers/net/wireless/ath/ath11k/Makefile
|
|
@@ -16,7 +16,8 @@ ath11k-y += core.o \
|
|
ce.o \
|
|
peer.o \
|
|
dbring.o \
|
|
- hw.o
|
|
+ hw.o \
|
|
+ vendor.o
|
|
|
|
ath11k-$(CPTCFG_ATH11K_DEBUGFS) += debug_htt_stats.o debugfs_sta.o
|
|
ath11k-$(CPTCFG_NL80211_TESTMODE) += testmode.o
|
|
--- a/drivers/net/wireless/ath/ath11k/core.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
|
@@ -440,6 +440,16 @@ struct ath11k_vdev_stop_status {
|
|
u32 vdev_id;
|
|
};
|
|
|
|
+struct ath11k_coex_info {
|
|
+ bool coex_support;
|
|
+ u32 pta_num;
|
|
+ u32 coex_mode;
|
|
+ u32 bt_active_time_slot;
|
|
+ u32 bt_priority_time_slot;
|
|
+ u32 coex_algo_type;
|
|
+ u32 pta_priority;
|
|
+};
|
|
+
|
|
struct ath11k {
|
|
struct ath11k_base *ab;
|
|
struct ath11k_pdev *pdev;
|
|
@@ -556,6 +566,8 @@ struct ath11k {
|
|
struct ath11k_per_peer_tx_stats cached_stats;
|
|
u32 last_ppdu_id;
|
|
u32 cached_ppdu_id;
|
|
+
|
|
+ struct ath11k_coex_info coex;
|
|
#ifdef CPTCFG_ATH11K_DEBUGFS
|
|
struct ath11k_debug debug;
|
|
#endif
|
|
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
|
@@ -5,6 +5,7 @@
|
|
|
|
#include <net/mac80211.h>
|
|
#include <linux/etherdevice.h>
|
|
+#include <linux/of.h>
|
|
#include "mac.h"
|
|
#include "core.h"
|
|
#include "debug.h"
|
|
@@ -14,6 +15,7 @@
|
|
#include "dp_rx.h"
|
|
#include "testmode.h"
|
|
#include "peer.h"
|
|
+#include "vendor.h"
|
|
|
|
#define CHAN2G(_channel, _freq, _flags) { \
|
|
.band = NL80211_BAND_2GHZ, \
|
|
@@ -5821,6 +5823,91 @@ static void ath11k_mac_op_sta_statistics
|
|
sinfo->signal = arsta->rssi_comb + ATH11K_DEFAULT_NOISE_FLOOR;
|
|
}
|
|
|
|
+#define ATH11K_WLAN_PRIO_MAX 0x63
|
|
+#define ATH11K_WLAN_PRIO_WEIGHT 0xff
|
|
+
|
|
+int ath11k_mac_coex_config(struct ath11k *ar, struct ath11k_vif *arvif,
|
|
+ int coex, u32 wlan_prio_mask, u8 wlan_weight)
|
|
+{
|
|
+ struct coex_config_arg coex_config;
|
|
+ int ret;
|
|
+
|
|
+ if (ar->state != ATH11K_STATE_ON &&
|
|
+ ar->state != ATH11K_STATE_RESTARTED)
|
|
+ return -ENETDOWN;
|
|
+
|
|
+ if (coex == -1 || !(test_bit(ATH11K_FLAG_BTCOEX, &ar->ab->dev_flags) ^ coex))
|
|
+ goto next;
|
|
+
|
|
+ coex_config.vdev_id = arvif->vdev_id;
|
|
+ if (coex == 1) {
|
|
+ coex_config.config_type = WMI_COEX_CONFIG_PTA_INTERFACE;
|
|
+ coex_config.pta_num = ar->coex.pta_num;
|
|
+ coex_config.coex_mode = ar->coex.coex_mode;
|
|
+ coex_config.bt_txrx_time = ar->coex.bt_active_time_slot;
|
|
+ coex_config.bt_priority_time = ar->coex.bt_priority_time_slot;
|
|
+ coex_config.pta_algorithm = ar->coex.coex_algo_type;
|
|
+ coex_config.pta_priority = ar->coex.pta_priority;
|
|
+ ret = ath11k_send_coex_config_cmd(ar, &coex_config);
|
|
+ if (ret) {
|
|
+ ath11k_warn(ar->ab,
|
|
+ "failed to set coex config vdev_id %d ret %d\n",
|
|
+ coex_config.vdev_id, ret);
|
|
+ goto out;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ memset(&coex_config, 0, sizeof(struct coex_config_arg));
|
|
+ coex_config.vdev_id = arvif->vdev_id;
|
|
+ coex_config.config_type = WMI_COEX_CONFIG_BTC_ENABLE;
|
|
+ coex_config.coex_enable = coex;
|
|
+ ret = ath11k_send_coex_config_cmd(ar, &coex_config);
|
|
+ if (ret) {
|
|
+ ath11k_warn(ar->ab,
|
|
+ "failed to set coex config vdev_id %d ret %d\n",
|
|
+ coex_config.vdev_id, ret);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (coex)
|
|
+ set_bit(ATH11K_FLAG_BTCOEX, &ar->ab->dev_flags);
|
|
+ else
|
|
+ clear_bit(ATH11K_FLAG_BTCOEX, &ar->ab->dev_flags);
|
|
+
|
|
+next:
|
|
+ if (!wlan_prio_mask) {
|
|
+ ret = 0;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (!(test_bit(ATH11K_FLAG_BTCOEX, &ar->ab->dev_flags))) {
|
|
+ ret = -EINVAL;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (wlan_prio_mask > ATH11K_WLAN_PRIO_MAX ||
|
|
+ wlan_weight > ATH11K_WLAN_PRIO_WEIGHT) {
|
|
+ ret = -EINVAL;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ memset(&coex_config, 0, sizeof(struct coex_config_arg));
|
|
+ coex_config.vdev_id = arvif->vdev_id;
|
|
+ coex_config.config_type = WMI_COEX_CONFIG_WLAN_PKT_PRIORITY;
|
|
+ coex_config.wlan_pkt_type = wlan_prio_mask;
|
|
+ coex_config.wlan_pkt_weight = wlan_weight;
|
|
+ ret = ath11k_send_coex_config_cmd(ar, &coex_config);
|
|
+ if (ret) {
|
|
+ ath11k_warn(ar->ab,
|
|
+ "failed to set coex config vdev_id %d ret %d\n",
|
|
+ coex_config.vdev_id, ret);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+out:
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static const struct ieee80211_ops ath11k_ops = {
|
|
.tx = ath11k_mac_op_tx,
|
|
.start = ath11k_mac_op_start,
|
|
@@ -6013,6 +6100,56 @@ static int ath11k_mac_setup_channels_rat
|
|
return 0;
|
|
}
|
|
|
|
+static void ath11k_mac_fetch_coex_info(struct ath11k *ar)
|
|
+{
|
|
+ struct ath11k_pdev_cap *cap = &ar->pdev->cap;
|
|
+ struct ath11k_base *ab = ar->ab;
|
|
+ struct device *dev = ab->dev;
|
|
+
|
|
+ ar->coex.coex_support = false;
|
|
+
|
|
+ if (!(cap->supported_bands & WMI_HOST_WLAN_2G_CAP))
|
|
+ return;
|
|
+
|
|
+ if (of_property_read_u32(dev->of_node, "qcom,pta-num",
|
|
+ &ar->coex.pta_num)) {
|
|
+ ath11k_err(ab, "No qcom,pta_num entry in dev-tree.\n");
|
|
+ }
|
|
+
|
|
+ if (of_property_read_u32(dev->of_node, "qcom,coex-mode",
|
|
+ &ar->coex.coex_mode)) {
|
|
+ ath11k_err(ab, "No qcom,coex_mode entry in dev-tree.\n");
|
|
+ }
|
|
+
|
|
+ if (of_property_read_u32(dev->of_node, "qcom,bt-active-time",
|
|
+ &ar->coex.bt_active_time_slot)) {
|
|
+ ath11k_err(ab, "No qcom,bt-active-time entry in dev-tree.\n");
|
|
+ }
|
|
+
|
|
+ if (of_property_read_u32(dev->of_node, "qcom,bt-priority-time",
|
|
+ &ar->coex.bt_priority_time_slot)) {
|
|
+ ath11k_err(ab, "No qcom,bt-priority-time entry in dev-tree.\n");
|
|
+ }
|
|
+
|
|
+ if (of_property_read_u32(dev->of_node, "qcom,coex-algo",
|
|
+ &ar->coex.coex_algo_type)) {
|
|
+ ath11k_err(ab, "No qcom,coex-algo entry in dev-tree.\n");
|
|
+ }
|
|
+
|
|
+ if (of_property_read_u32(dev->of_node, "qcom,pta-priority",
|
|
+ &ar->coex.pta_priority)) {
|
|
+ ath11k_err(ab, "No qcom,pta-priority entry in dev-tree.\n");
|
|
+ }
|
|
+
|
|
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "coex pta_num %u coex_mode %u"
|
|
+ " bt_active_time_slot %u bt_priority_time_slot %u"
|
|
+ " coex_algorithm %u pta_priority %u\n", ar->coex.pta_num,
|
|
+ ar->coex.coex_mode, ar->coex.bt_active_time_slot,
|
|
+ ar->coex.bt_priority_time_slot, ar->coex.coex_algo_type,
|
|
+ ar->coex.pta_priority);
|
|
+ ar->coex.coex_support = true;
|
|
+}
|
|
+
|
|
static const u8 ath11k_if_types_ext_capa[] = {
|
|
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
|
|
[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
|
|
@@ -6195,6 +6332,7 @@ static int __ath11k_mac_register(struct
|
|
ARRAY_SIZE(ath11k_iftypes_ext_capa);
|
|
|
|
ath11k_reg_init(ar);
|
|
+ ath11k_vendor_register(ar);
|
|
|
|
if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) {
|
|
ar->hw->netdev_features = NETIF_F_HW_CSUM;
|
|
@@ -6307,6 +6445,7 @@ int ath11k_mac_allocate(struct ath11k_ba
|
|
*/
|
|
ath11k_wmi_pdev_attach(ab, i);
|
|
|
|
+ ath11k_mac_fetch_coex_info(ar);
|
|
ar->cfg_tx_chainmask = pdev->cap.tx_chain_mask;
|
|
ar->cfg_rx_chainmask = pdev->cap.rx_chain_mask;
|
|
ar->num_tx_chains = get_num_chains(pdev->cap.tx_chain_mask);
|
|
--- a/drivers/net/wireless/ath/ath11k/mac.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/mac.h
|
|
@@ -133,8 +133,9 @@ void __ath11k_mac_scan_finish(struct ath
|
|
void ath11k_mac_scan_finish(struct ath11k *ar);
|
|
|
|
struct ath11k_vif *ath11k_mac_get_arvif(struct ath11k *ar, u32 vdev_id);
|
|
-struct ath11k_vif *ath11k_mac_get_arvif_by_vdev_id(struct ath11k_base *ab,
|
|
- u32 vdev_id);
|
|
+struct ath11k_vif *ath11k_mac_get_arvif_by_vdev_id(struct ath11k_base *ab, u32 vdev_id);
|
|
+int ath11k_mac_coex_config(struct ath11k *ar, struct ath11k_vif *arvif,
|
|
+ int coex, u32 wlan_prio_mask, u8 wlan_weight);
|
|
struct ath11k *ath11k_mac_get_ar_by_vdev_id(struct ath11k_base *ab, u32 vdev_id);
|
|
struct ath11k *ath11k_mac_get_ar_by_pdev_id(struct ath11k_base *ab, u32 pdev_id);
|
|
struct ath11k *ath11k_mac_get_ar_vdev_stop_status(struct ath11k_base *ab,
|
|
--- /dev/null
|
|
+++ b/drivers/net/wireless/ath/ath11k/vendor.c
|
|
@@ -0,0 +1,121 @@
|
|
+// SPDX-License-Identifier: ISC
|
|
+/*
|
|
+ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
|
+ */
|
|
+
|
|
+#include <net/netlink.h>
|
|
+#include <net/mac80211.h>
|
|
+#include "core.h"
|
|
+#include "vendor.h"
|
|
+#include "debug.h"
|
|
+
|
|
+static const struct nla_policy
|
|
+ath11k_vendor_btcoex_config_policy[QCA_WLAN_VENDOR_ATTR_BTCOEX_CONFIG_MAX + 1] = {
|
|
+ [QCA_WLAN_VENDOR_ATTR_BTCOEX_CONFIG_ENABLE] = { .type = NLA_U8 },
|
|
+ [QCA_WLAN_VENDOR_ATTR_BTCOEX_CONFIG_WLAN_PRIORITY] = { .type = NLA_NESTED },
|
|
+};
|
|
+
|
|
+static const struct nla_policy
|
|
+ath11k_vendor_wlan_prio_policy[QCA_WLAN_VENDOR_ATTR_WLAN_PRIO_MAX + 1] = {
|
|
+ [QCA_WLAN_VENDOR_ATTR_WLAN_PRIO_MASK] = { .type = NLA_U8 },
|
|
+ [QCA_WLAN_VENDOR_ATTR_WLAN_PRIO_WEIGHT] = { .type = NLA_U8 },
|
|
+};
|
|
+
|
|
+static int ath11k_vendor_btcoex_configure(struct wiphy *wiphy,
|
|
+ struct wireless_dev *wdev,
|
|
+ const void *data,
|
|
+ int data_len)
|
|
+{
|
|
+ struct ieee80211_vif *vif;
|
|
+ struct ath11k_vif *arvif;
|
|
+ struct ath11k *ar;
|
|
+ struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_BTCOEX_CONFIG_MAX + 1];
|
|
+ struct nlattr *tb_wlan_prio[QCA_WLAN_VENDOR_ATTR_WLAN_PRIO_MAX + 1];
|
|
+ struct nlattr *wlan_prio;
|
|
+ enum qca_wlan_priority_type wlan_prio_mask = 0;
|
|
+ int ret, coex = -1, rem_conf;
|
|
+ u8 wlan_weight = 0;
|
|
+
|
|
+ if (!wdev)
|
|
+ return -EINVAL;
|
|
+
|
|
+ vif = wdev_to_ieee80211_vif(wdev);
|
|
+ if (!vif)
|
|
+ return -EINVAL;
|
|
+
|
|
+ arvif = (struct ath11k_vif *)vif->drv_priv;
|
|
+ if (!arvif)
|
|
+ return -EINVAL;
|
|
+
|
|
+ ar = arvif->ar;
|
|
+
|
|
+ mutex_lock(&ar->conf_mutex);
|
|
+
|
|
+ ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_BTCOEX_CONFIG_MAX, data, data_len,
|
|
+ ath11k_vendor_btcoex_config_policy, NULL);
|
|
+ if (ret) {
|
|
+ ath11k_warn(ar->ab, "invalid BTCOEX config policy attribute\n");
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (!tb[QCA_WLAN_VENDOR_ATTR_BTCOEX_CONFIG_ENABLE] &&
|
|
+ !tb[QCA_WLAN_VENDOR_ATTR_BTCOEX_CONFIG_WLAN_PRIORITY]) {
|
|
+ ath11k_warn(ar->ab, "invalid BTCOEX config attributes\n");
|
|
+ ret = -EINVAL;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (tb[QCA_WLAN_VENDOR_ATTR_BTCOEX_CONFIG_ENABLE]) {
|
|
+ coex = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_BTCOEX_CONFIG_ENABLE]);
|
|
+ ret = ath11k_mac_coex_config(ar, arvif, coex, wlan_prio_mask, wlan_weight);
|
|
+ if (ret)
|
|
+ goto out;
|
|
+ }
|
|
+ if (tb[QCA_WLAN_VENDOR_ATTR_BTCOEX_CONFIG_WLAN_PRIORITY]) {
|
|
+ nla_for_each_nested(wlan_prio,
|
|
+ tb[QCA_WLAN_VENDOR_ATTR_BTCOEX_CONFIG_WLAN_PRIORITY],
|
|
+ rem_conf) {
|
|
+ ret =
|
|
+ nla_parse_nested(tb_wlan_prio, QCA_WLAN_VENDOR_ATTR_WLAN_PRIO_MAX,
|
|
+ wlan_prio, ath11k_vendor_wlan_prio_policy,
|
|
+ NULL);
|
|
+ if (ret)
|
|
+ goto out;
|
|
+ wlan_prio_mask =
|
|
+ nla_get_u8(tb_wlan_prio[QCA_WLAN_VENDOR_ATTR_WLAN_PRIO_MASK]);
|
|
+ if (tb_wlan_prio[QCA_WLAN_VENDOR_ATTR_WLAN_PRIO_WEIGHT])
|
|
+ wlan_weight =
|
|
+ nla_get_u8(tb_wlan_prio[QCA_WLAN_VENDOR_ATTR_WLAN_PRIO_WEIGHT]);
|
|
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
|
|
+ "BTCOEX enable %u WLAN Priority %u wlan weight %u\n",
|
|
+ coex, wlan_prio_mask, wlan_weight);
|
|
+
|
|
+ ret = ath11k_mac_coex_config(ar, arvif, coex, wlan_prio_mask, wlan_weight);
|
|
+ if (ret)
|
|
+ goto out;
|
|
+ }
|
|
+ }
|
|
+
|
|
+out:
|
|
+ mutex_unlock(&ar->conf_mutex);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static struct wiphy_vendor_command ath11k_vendor_commands[] = {
|
|
+ {
|
|
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
|
|
+ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_BTCOEX_CONFIG,
|
|
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
|
|
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
|
|
+ .doit = ath11k_vendor_btcoex_configure,
|
|
+ .policy = ath11k_vendor_btcoex_config_policy
|
|
+ }
|
|
+};
|
|
+
|
|
+int ath11k_vendor_register(struct ath11k *ar)
|
|
+{
|
|
+ ar->hw->wiphy->vendor_commands = ath11k_vendor_commands;
|
|
+ ar->hw->wiphy->n_vendor_commands = ARRAY_SIZE(ath11k_vendor_commands);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
--- /dev/null
|
|
+++ b/drivers/net/wireless/ath/ath11k/vendor.h
|
|
@@ -0,0 +1,83 @@
|
|
+/* SPDX-License-Identifier: ISC */
|
|
+/*
|
|
+ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
|
+ */
|
|
+
|
|
+#ifndef ATH11K_VENDOR_H
|
|
+#define ATH11K_VENDOR_H
|
|
+
|
|
+#define QCA_NL80211_VENDOR_ID 0x001374
|
|
+
|
|
+enum qca_nl80211_vendor_subcmds {
|
|
+ /* QCA_NL80211_VENDOR_SUBCMD_BTCOEX_CONFIG: This command is used to
|
|
+ * enable/disable BTCOEX and set priority for different type of WLAN
|
|
+ * traffic over BT low priority traffic. This uses attributes in
|
|
+ * enum qca-vendor_attr_btcoex_config.
|
|
+ */
|
|
+ QCA_NL80211_VENDOR_SUBCMD_BTCOEX_CONFIG = 182,
|
|
+};
|
|
+
|
|
+/*
|
|
+ * enum qca_wlan_priority_type - priority mask
|
|
+ * This enum defines priority mask that user can configure
|
|
+ * over BT traffic type which can be passed through
|
|
+ * QCA_WLAN_VENDOR_ATTR_BTCOEX_CONFIG_WLAN_PRIORITY attribute.
|
|
+ *
|
|
+ * @QCA_WLAN_PRIORITY_BE: Bit mask for WLAN Best effort traffic
|
|
+ * @QCA_WLAN_PRIORITY_BK: Bit mask for WLAN Background traffic
|
|
+ * @QCA_WLAN_PRIORITY_VI: Bit mask for WLAN Video traffic
|
|
+ * @QCA_WLAN_PRIORITY_VO: Bit mask for WLAN Voice traffic
|
|
+ * @QCA_WLAN_PRIORITY_BEACON: Bit mask for WLAN BEACON frame
|
|
+ * @QCA_WLAN_PRIORITY_MGMT: Bit mask for WLAN Management frame
|
|
+*/
|
|
+enum qca_wlan_priority_type {
|
|
+ QCA_WLAN_PRIORITY_BE = BIT(0),
|
|
+ QCA_WLAN_PRIORITY_BK = BIT(1),
|
|
+ QCA_WLAN_PRIORITY_VI = BIT(2),
|
|
+ QCA_WLAN_PRIORITY_VO = BIT(3),
|
|
+ QCA_WLAN_PRIORITY_BEACON = BIT(4),
|
|
+ QCA_WLAN_PRIORITY_MGMT = BIT(5),
|
|
+};
|
|
+
|
|
+/**
|
|
+ * enum qca_wlan_vendor_attr_wlan_prio - Used to configure
|
|
+ * WLAN priority mask and its respective weight value.
|
|
+ * @QCA_WLAN_VENDOR_ATTR_WLAN_PRIO_MASK - This is u8 attribute
|
|
+ * used to pass traffic type mask value see %qca_wlan_priority_type
|
|
+ * @QCA_WLAN_VENDOR_ATTR_WLAN_PRIO_WEIGHT - This is u8 attribute
|
|
+ * accepts value between 0 and 255 and used to configure weight for
|
|
+ * traffic type mentioned in %QCA_WLAN_VENDOR_ATTR_WLAN_PRIO_MASK.
|
|
+ */
|
|
+enum qca_wlan_vendor_attr_wlan_prio {
|
|
+ QCA_WLAN_VENDOR_ATTR_WLAN_PRIO_INVALID = 0,
|
|
+ QCA_WLAN_VENDOR_ATTR_WLAN_PRIO_MASK = 1,
|
|
+ QCA_WLAN_VENDOR_ATTR_WLAN_PRIO_WEIGHT = 2,
|
|
+
|
|
+ QCA_WLAN_VENDOR_ATTR_WLAN_PRIO_LAST,
|
|
+ QCA_WLAN_VENDOR_ATTR_WLAN_PRIO_MAX =
|
|
+ QCA_WLAN_VENDOR_ATTR_WLAN_PRIO_LAST - 1,
|
|
+};
|
|
+
|
|
+
|
|
+
|
|
+/**
|
|
+ * enum qca_wlan_vendor_attr_btcoex_config - Used by the vendor command
|
|
+ * The use can enable/disable BTCOEX and configure WLAN priority for
|
|
+ * different traffic type over BT.
|
|
+ * QCA_WLAN_VENDOR_ATTR_BTCOEX_CONFIG_ENABLE, enable/disable BTCOEX
|
|
+ * QCA_WLAN_VENDOR_ATTR_BTCOEX_CONFIG_WLAN_PRIORITY, This is a nested
|
|
+ * attribute pass the attributes in %qca_wlan_vendor_attr_wlan_prio.
|
|
+ */
|
|
+enum qca_wlan_vendor_attr_btcoex_config {
|
|
+ QCA_WLAN_VENDOR_ATTR_BTCOEX_CONFIG_INVALID = 0,
|
|
+ QCA_WLAN_VENDOR_ATTR_BTCOEX_CONFIG_ENABLE = 1,
|
|
+ QCA_WLAN_VENDOR_ATTR_BTCOEX_CONFIG_WLAN_PRIORITY = 2,
|
|
+
|
|
+ /* keep last */
|
|
+ QCA_WLAN_VENDOR_ATTR_BTCOEX_CONFIG_LAST,
|
|
+ QCA_WLAN_VENDOR_ATTR_BTCOEX_CONFIG_MAX =
|
|
+ QCA_WLAN_VENDOR_ATTR_BTCOEX_CONFIG_LAST - 1
|
|
+};
|
|
+
|
|
+int ath11k_vendor_register(struct ath11k *ar);
|
|
+#endif /* QCA_VENDOR_H */
|
|
--- a/drivers/net/wireless/ath/ath11k/wmi.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
|
|
@@ -1485,6 +1485,71 @@ int ath11k_wmi_vdev_set_param_cmd(struct
|
|
return ret;
|
|
}
|
|
|
|
+static void ath11k_wmi_copy_coex_config(struct ath11k *ar, struct wmi_coex_config_cmd *cmd,
|
|
+ struct coex_config_arg *coex_config)
|
|
+{
|
|
+ if (coex_config->config_type == WMI_COEX_CONFIG_BTC_ENABLE) {
|
|
+ cmd->coex_enable = coex_config->coex_enable;
|
|
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
|
|
+ "WMI coex config type %u vdev id %d coex_enable %u\n",
|
|
+ coex_config->config_type, coex_config->vdev_id,
|
|
+ coex_config->coex_enable);
|
|
+ }
|
|
+
|
|
+ if (coex_config->config_type == WMI_COEX_CONFIG_WLAN_PKT_PRIORITY) {
|
|
+ cmd->wlan_pkt_type = coex_config->wlan_pkt_type;
|
|
+ cmd->wlan_pkt_weight = coex_config->wlan_pkt_weight;
|
|
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
|
|
+ "WMI coex config type %u vdev id %d wlan pkt type 0x%x wlan pkt weight %u\n",
|
|
+ coex_config->config_type, coex_config->vdev_id,
|
|
+ coex_config->wlan_pkt_type, coex_config->wlan_pkt_weight);
|
|
+ }
|
|
+
|
|
+ if (coex_config->config_type == WMI_COEX_CONFIG_PTA_INTERFACE) {
|
|
+ cmd->pta_num = coex_config->pta_num;
|
|
+ cmd->coex_mode = coex_config->coex_mode;
|
|
+ cmd->bt_txrx_time = coex_config->bt_txrx_time;
|
|
+ cmd->bt_priority_time = coex_config->bt_priority_time;
|
|
+ cmd->pta_algorithm = coex_config->pta_algorithm;
|
|
+ cmd->pta_priority = coex_config->pta_priority;
|
|
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
|
|
+ "WMI coex config type %u vdev id %d pta num %u coex mode %u bt_txrx_time %u bt_priority_time %u pta alogrithm %u pta priority %u\n",
|
|
+ coex_config->config_type, coex_config->vdev_id,
|
|
+ coex_config->pta_num, coex_config->coex_mode,
|
|
+ coex_config->bt_txrx_time, coex_config->bt_priority_time,
|
|
+ coex_config->pta_algorithm, coex_config->pta_priority);
|
|
+ }
|
|
+}
|
|
+
|
|
+int ath11k_send_coex_config_cmd(struct ath11k *ar,
|
|
+ struct coex_config_arg *coex_config)
|
|
+{
|
|
+ struct ath11k_pdev_wmi *wmi = ar->wmi;
|
|
+ struct wmi_coex_config_cmd *cmd;
|
|
+ struct sk_buff *skb;
|
|
+ int ret;
|
|
+
|
|
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
|
|
+ if (!skb)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ cmd = (struct wmi_coex_config_cmd *)skb->data;
|
|
+ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_COEX_CONFIG_CMD) |
|
|
+ FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
|
|
+
|
|
+ cmd->vdev_id = coex_config->vdev_id;
|
|
+ cmd->config_type = coex_config->config_type;
|
|
+ ath11k_wmi_copy_coex_config(ar, cmd, coex_config);
|
|
+
|
|
+ ret = ath11k_wmi_cmd_send(wmi, skb, WMI_COEX_CONFIG_CMDID);
|
|
+ if (ret) {
|
|
+ ath11k_warn(ar->ab, "failed to send WMI_COEX_CONFIG_CMD cmd\n");
|
|
+ dev_kfree_skb(skb);
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
int ath11k_wmi_send_stats_request_cmd(struct ath11k *ar,
|
|
struct stats_request_params *param)
|
|
{
|
|
--- a/drivers/net/wireless/ath/ath11k/wmi.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
|
|
@@ -4697,6 +4697,79 @@ struct wmi_wmm_params_arg {
|
|
u8 no_ack;
|
|
};
|
|
|
|
+enum wmi_coex_config_type {
|
|
+ WMI_COEX_CONFIG_PAGE_P2P_TDM = 1,
|
|
+ WMI_COEX_CONFIG_PAGE_STA_TDM = 2,
|
|
+ WMI_COEX_CONFIG_PAGE_SAP_TDM = 3,
|
|
+ WMI_COEX_CONFIG_DURING_WLAN_CONN = 4,
|
|
+ WMI_COEX_CONFIG_BTC_ENABLE = 5,
|
|
+ WMI_COEX_CONFIG_COEX_DBG = 6,
|
|
+ WMI_COEX_CONFIG_PAGE_P2P_STA_TDM = 7,
|
|
+ WMI_COEX_CONFIG_INQUIRY_P2P_TDM = 8,
|
|
+ WMI_COEX_CONFIG_INQUIRY_STA_TDM = 9,
|
|
+ WMI_COEX_CONFIG_INQUIRY_SAP_TDM = 10,
|
|
+ WMI_COEX_CONFIG_INQUIRY_P2P_STA_TDM = 11,
|
|
+ WMI_COEX_CONFIG_TX_POWER = 12,
|
|
+ WMI_COEX_CONFIG_PTA_CONFIG = 13,
|
|
+ WMI_COEX_CONFIG_AP_TDM = 14,
|
|
+ WMI_COEX_CONFIG_WLAN_SCAN_PRIORITY = 15,
|
|
+ WMI_COEX_CONFIG_WLAN_PKT_PRIORITY = 16,
|
|
+ WMI_COEX_CONFIG_PTA_INTERFACE = 17,
|
|
+};
|
|
+
|
|
+struct coex_config_arg {
|
|
+ u32 vdev_id;
|
|
+ u32 config_type;
|
|
+ union {
|
|
+ struct {
|
|
+ u32 coex_enable;
|
|
+ };
|
|
+
|
|
+ struct {
|
|
+ u32 pta_num;
|
|
+ u32 coex_mode;
|
|
+ u32 bt_txrx_time;
|
|
+ u32 bt_priority_time;
|
|
+ u32 pta_algorithm;
|
|
+ u32 pta_priority;
|
|
+ };
|
|
+
|
|
+ struct {
|
|
+ u32 wlan_pkt_type;
|
|
+ u32 wlan_pkt_type_continued;
|
|
+ u32 wlan_pkt_weight;
|
|
+ u32 bt_pkt_weight;
|
|
+ };
|
|
+ };
|
|
+};
|
|
+
|
|
+struct wmi_coex_config_cmd {
|
|
+ u32 tlv_header;
|
|
+ u32 vdev_id;
|
|
+ u32 config_type;
|
|
+ union {
|
|
+ struct {
|
|
+ u32 coex_enable;
|
|
+ } __packed;
|
|
+
|
|
+ struct {
|
|
+ u32 pta_num;
|
|
+ u32 coex_mode;
|
|
+ u32 bt_txrx_time;
|
|
+ u32 bt_priority_time;
|
|
+ u32 pta_algorithm;
|
|
+ u32 pta_priority;
|
|
+ } __packed;
|
|
+
|
|
+ struct {
|
|
+ u32 wlan_pkt_type;
|
|
+ u32 wlan_pkt_type_continued;
|
|
+ u32 wlan_pkt_weight;
|
|
+ u32 bt_pkt_weight;
|
|
+ } __packed;
|
|
+ } __packed;
|
|
+} __packed;
|
|
+
|
|
struct wmi_vdev_set_wmm_params_cmd {
|
|
u32 tlv_header;
|
|
u32 vdev_id;
|
|
@@ -5110,6 +5183,8 @@ int ath11k_wmi_send_twt_enable_cmd(struc
|
|
int ath11k_wmi_send_twt_disable_cmd(struct ath11k *ar, u32 pdev_id);
|
|
int ath11k_wmi_send_obss_spr_cmd(struct ath11k *ar, u32 vdev_id,
|
|
struct ieee80211_he_obss_pd *he_obss_pd);
|
|
+int ath11k_send_coex_config_cmd(struct ath11k *ar,
|
|
+ struct coex_config_arg *coex_config);
|
|
int ath11k_wmi_send_obss_color_collision_cfg_cmd(struct ath11k *ar, u32 vdev_id,
|
|
u8 bss_color, u32 period,
|
|
bool enable);
|