wlan-ap-Telecominfraproject/feeds/ipq95xx/mac80211/patches/qca/750-02-ath12k-Add-vendor-command-support-for-SAWF.patch
John Crispin 144c5d00f4 ipq95xx/mac80211: update to ATH12.3-CS
Signed-off-by: John Crispin <john@phrozen.org>
2024-02-28 18:56:21 +01:00

549 lines
17 KiB
Diff

From 40ea68f9c184368f1d6ca18283040368b4304f30 Mon Sep 17 00:00:00 2001
From: Nagarajan Maran <quic_nmaran@quicinc.com>
Date: Mon, 7 Nov 2022 18:26:49 +0530
Subject: [PATCH] ath12: Add vendor command support for SAWF
Add vendor command support for SAWF configure/reconfigure,
disable and view the service classes.
Signed-off-by: Nagarajan Maran <quic_nmaran@quicinc.com>
Signed-off-by: Karthikeyan Kathirvel <quic_kathirve@quicinc.com>
---
drivers/net/wireless/ath/ath12k/Makefile | 3 +-
drivers/net/wireless/ath/ath12k/vendor.c | 121 +++++++++++++++++++++++
drivers/net/wireless/ath/ath12k/vendor.h | 46 +++++++++
3 files changed, 169 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/wireless/ath/ath12k/vendor.c
create mode 100644 drivers/net/wireless/ath/ath12k/vendor.h
--- a/drivers/net/wireless/ath/ath12k/Makefile
+++ b/drivers/net/wireless/ath/ath12k/Makefile
@@ -21,7 +21,8 @@ ath12k-y += core.o \
mhi.o \
pci.o \
dp_mon.o \
- sawf.o
+ sawf.o \
+ vendor.o
ath12k-$(CPTCFG_ATH12K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o
ath12k-$(CPTCFG_NL80211_TESTMODE) += testmode.o
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/vendor.c
@@ -0,0 +1,275 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved
+ */
+#include <net/netlink.h>
+#include <net/mac80211.h>
+#include "core.h"
+#include "debug.h"
+#include "mac.h"
+
+static const struct nla_policy
+ath12k_vendor_sawf_config_policy[QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX + 1] = {
+ [QCN_WLAN_VENDOR_ATTR_SAWF_SERVICE_CLASSES] = {.type = NLA_NESTED},
+ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_ID] = {.type = NLA_U8},
+ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_APP_NAME] = {.type = NLA_STRING},
+ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MIN_TP] = {.type = NLA_U32},
+ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MAX_TP] = {.type = NLA_U32},
+ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_BURST_SIZE] = {.type = NLA_U32},
+ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_INTERVAL] = {.type = NLA_U32},
+ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_DELAY_BOUND] = {.type = NLA_U32},
+ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_TTL] = {.type = NLA_U32},
+ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_PRIO] = {.type = NLA_U32},
+ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_TID] = {.type = NLA_U32},
+ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS] = {.type = NLA_U32},
+};
+
+static void ath12k_set_default_values(struct ath12k_sawf_svc_params *param)
+{
+ param->min_throughput_rate = SAWF_SVC_PARAM_DEFAULT_MIN_THRUPUT;
+ param->max_throughput_rate = SAWF_SVC_PARAM_DEFAULT_MAX_THRUPUT;
+ param->burst_size = SAWF_SVC_PARAM_DEFAULT_BURST_SIZE;
+ param->service_interval = SAWF_SVC_PARAM_DEFAULT_SVC_INTERVAL;
+ param->delay_bound = SAWF_SVC_PARAM_DEFAULT_DELAY_BOUND;
+ param->msdu_ttl = SAWF_SVC_PARAM_DEFAULT_TIME_TO_LIVE;
+ param->priority = SAWF_SVC_PARAM_DEFAULT_PRIORITY;
+ param->tid = SAWF_SVC_PARAM_DEFAULT_TID;
+ param->msdu_rate_loss = SAWF_SVC_PARAM_DEFAULT_MSDU_LOSS_RATE;
+}
+
+static int ath12k_vendor_set_sawf_config(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data,
+ int data_len)
+{
+ struct nlattr *tb[QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX + 1];
+ struct ath12k_sawf_svc_params sawf_param;
+ char *app_name = NULL;
+ int ret = 0;
+
+ if (!ath12k_sawf_enable)
+ return -EOPNOTSUPP;
+
+ memset(&sawf_param, 0, sizeof(struct ath12k_sawf_svc_params));
+
+ ret = nla_parse(tb, QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX, data, data_len,
+ ath12k_vendor_sawf_config_policy, NULL);
+ if (ret) {
+ ath12k_err(NULL, "Invalid attributes with SAWF configure command\n");
+ return ret;
+ }
+
+ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_ID] &&
+ tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_APP_NAME]) {
+ sawf_param.svc_id = nla_get_u8(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_ID]);
+ app_name = nla_data(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_APP_NAME]);
+ memcpy(sawf_param.app_name, app_name, ATH12K_MAX_APP_NAME);
+ } else {
+ ath12k_err(NULL, "Mandatory attributes not available\n");
+ return -EINVAL;
+ }
+
+ ath12k_set_default_values(&sawf_param);
+
+ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MIN_TP])
+ sawf_param.min_throughput_rate = nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MIN_TP]);
+ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MAX_TP])
+ sawf_param.max_throughput_rate = nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MAX_TP]);
+ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_BURST_SIZE])
+ sawf_param.burst_size = nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_BURST_SIZE]);
+ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_INTERVAL])
+ sawf_param.service_interval = nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_INTERVAL]);
+ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_DELAY_BOUND])
+ sawf_param.delay_bound = nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_DELAY_BOUND]);
+ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_TTL])
+ sawf_param.msdu_ttl = nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_TTL]);
+ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_PRIO])
+ sawf_param.priority = nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_PRIO]);
+ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_TID])
+ sawf_param.tid = nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_TID]);
+ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS])
+ sawf_param.msdu_rate_loss = nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS]);
+
+ ret = ath12k_create_send_svc_params(&sawf_param);
+
+ return ret;
+}
+
+static int ath12k_vendor_disable_sawf_config(struct wiphy *wihpy,
+ struct wireless_dev *wdev,
+ const void *data,
+ int data_len)
+{
+ struct nlattr *tb[QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX + 1];
+ u8 svc_id = 0;
+ int ret = 0;
+
+ if (!ath12k_sawf_enable)
+ return -EOPNOTSUPP;
+
+ ret = nla_parse(tb, QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX, data, data_len,
+ ath12k_vendor_sawf_config_policy, NULL);
+ if (ret) {
+ ath12k_err(NULL, "Invalid attribute with SAWF disable command\n");
+ return ret;
+ }
+
+ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_ID]) {
+ svc_id = nla_get_u8(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_ID]);
+ } else {
+ ath12k_err(NULL, "Mandatory attribute not available\n");
+ return -EINVAL;
+ }
+
+ ret = ath12k_sawf_disable_config(svc_id);
+
+ return ret;
+}
+
+static int ath12k_vendor_view_sawf_config(struct wiphy *wihpy,
+ struct wireless_dev *wdev,
+ struct sk_buff *msg,
+ const void *data,
+ int data_len,
+ unsigned long *storage)
+{
+ struct nlattr *tb[QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX + 1];
+ struct ath12k_sawf_ctx *sawf_ctx;
+ struct ath12k_sawf_svc_params *svc_class;
+ struct nlattr *sawf_svc_classes, *sawf_svc_class;
+ int ret = 0, i, j = 0;
+ int tailroom = 0, nest_start_length = 0, nest_end_length = 0, nested_range = 0;
+ u8 svc_id = 0;
+
+ if (!ath12k_sawf_enable)
+ return -EOPNOTSUPP;
+
+ ret = nla_parse(tb, QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX, data, data_len,
+ ath12k_vendor_sawf_config_policy, NULL);
+
+ if (ret) {
+ ath12k_warn(NULL, "Invalid attribute with SAWF view command \n");
+ return ret;
+ }
+
+ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_ID]) {
+ svc_id = nla_get_u8(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_ID]);
+ if (!ath12k_svc_id_valid(svc_id)) {
+ ath12k_err(NULL, "Invalid Service ID: %u\n", svc_id);
+ return -EINVAL;
+ }
+ if (!ath12k_svc_id_configured(svc_id))
+ return -EINVAL;
+ }
+
+ /* return 0 to end the dump */
+ if (storage && (*storage == ATH12K_SAWF_SVC_CLASS_MAX))
+ return 0;
+
+ sawf_ctx = ath12k_get_sawf_context();
+
+ if (!sawf_ctx) {
+ ath12k_err(NULL, "SAWF context not available\n");
+ return -ENODATA;
+ }
+
+ sawf_svc_classes = nla_nest_start(msg,
+ QCN_WLAN_VENDOR_ATTR_SAWF_SERVICE_CLASSES);
+
+ if (!sawf_svc_classes)
+ return -ENOBUFS;
+
+ tailroom = skb_tailroom(msg);
+ spin_lock_bh(&sawf_ctx->sawf_svc_lock);
+ for (i = (svc_id) ? (svc_id - 1) : (*storage);
+ i < ATH12K_SAWF_SVC_CLASS_MAX && tailroom > nested_range;
+ i += (svc_id) ? (ATH12K_SAWF_SVC_CLASS_MAX) : (1)) {
+ if (!sawf_ctx->svc_classes[i].configured)
+ continue;
+
+ svc_class = &sawf_ctx->svc_classes[i];
+ nest_start_length = msg->len;
+ sawf_svc_class = nla_nest_start(msg, j);
+ if (nla_put_u8(msg, QCN_WLAN_VENDOR_ATTR_SAWF_SVC_ID,
+ svc_class->svc_id) ||
+ nla_put(msg, QCN_WLAN_VENDOR_ATTR_SAWF_SVC_APP_NAME,
+ sizeof(svc_class->app_name),
+ svc_class->app_name) ||
+ nla_put_u32(msg,
+ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MIN_TP,
+ svc_class->min_throughput_rate) ||
+ nla_put_u32(msg,
+ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MAX_TP,
+ svc_class->max_throughput_rate) ||
+ nla_put_u32(msg,
+ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_BURST_SIZE,
+ svc_class->burst_size) ||
+ nla_put_u32(msg,
+ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_INTERVAL,
+ svc_class->service_interval) ||
+ nla_put_u32(msg,
+ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_DELAY_BOUND,
+ svc_class->delay_bound) ||
+ nla_put_u32(msg,
+ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_TTL,
+ svc_class->msdu_ttl) ||
+ nla_put_u32(msg,
+ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_PRIO,
+ svc_class->priority) ||
+ nla_put_u32(msg, QCN_WLAN_VENDOR_ATTR_SAWF_SVC_TID,
+ svc_class->tid) ||
+ nla_put_u32(msg,
+ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS,
+ svc_class->msdu_rate_loss))
+ goto nla_put_failure;
+
+ nest_end_length = nla_nest_end(msg, sawf_svc_class);
+ nested_range = nest_end_length - nest_start_length;
+ tailroom -= nested_range;
+ j++;
+ }
+ spin_unlock_bh(&sawf_ctx->sawf_svc_lock);
+ nla_nest_end(msg, sawf_svc_classes);
+
+ *storage = (svc_id) ? (ATH12K_SAWF_SVC_CLASS_MAX) : (i);
+
+ if (!j)
+ return 0;
+
+ return msg->len;
+
+nla_put_failure:
+ spin_unlock_bh(&sawf_ctx->sawf_svc_lock);
+ return -ENOBUFS;
+}
+
+static struct wiphy_vendor_command ath12k_vendor_commands[] = {
+ {
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
+ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SVC_CREATE,
+ .doit = ath12k_vendor_set_sawf_config,
+ .policy = ath12k_vendor_sawf_config_policy,
+ .maxattr = QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX,
+ },
+ {
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
+ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SVC_DISABLE,
+ .doit = ath12k_vendor_disable_sawf_config,
+ .policy = ath12k_vendor_sawf_config_policy,
+ .maxattr = QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX,
+ },
+ {
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
+ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SVC_VIEW,
+ .dumpit = ath12k_vendor_view_sawf_config,
+ .policy = ath12k_vendor_sawf_config_policy,
+ .maxattr = QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX,
+ },
+};
+
+int ath12k_vendor_register(struct ath12k_hw *ah)
+{
+ ah->hw->wiphy->vendor_commands = ath12k_vendor_commands;
+ ah->hw->wiphy->n_vendor_commands = ARRAY_SIZE(ath12k_vendor_commands);
+ return 0;
+}
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/vendor.h
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved
+ */
+#ifndef ATH12K_VENDOR_H
+#define ATH12K_VENDOR_H
+
+#define QCA_NL80211_VENDOR_ID 0x001374
+
+enum qca_nl80211_vendor_subcmds {
+ /* Wi-Fi configuration subcommand */
+ QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION = 74,
+
+ QCA_NL80211_VENDOR_SUBCMD_SVC_CREATE = 204,
+ QCA_NL80211_VENDOR_SUBCMD_SVC_DISABLE = 205,
+ QCA_NL80211_VENDOR_SUBCMD_SVC_VIEW = 206,
+};
+
+enum qca_wlan_vendor_sawf_attr_config {
+ QCN_WLAN_VENDOR_ATTR_SAWF_SERVICE_CLASSES = 1,
+ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_ID,
+ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_APP_NAME,
+ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MIN_TP,
+ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MAX_TP,
+ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_BURST_SIZE,
+ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_INTERVAL,
+ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_DELAY_BOUND,
+ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_TTL,
+ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_PRIO,
+ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_TID,
+ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_AFTER_LAST,
+ QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX =
+ QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_AFTER_LAST - 1,
+};
+
+int ath12k_vendor_register(struct ath12k_hw *ah);
+#endif /* QCA_VENDOR_H */
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -27,6 +27,7 @@
#include "spectral.h"
#include "pktlog.h"
#include "sawf.h"
+#include "vendor.h"
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -15021,6 +15021,8 @@ static int ath12k_mac_hw_register(struct
ah->hw->wiphy->regulatory_flags = REGULATORY_WIPHY_SELF_MANAGED;
ah->hw->wiphy->reg_notifier = ath12k_reg_notifier;
+ ath12k_vendor_register(ah);
+
if (!test_bit(ATH12K_FLAG_RAW_MODE, &ag->dev_flags)) {
hw->netdev_features = NETIF_F_HW_CSUM;
ieee80211_hw_set(hw, SW_CRYPTO_CONTROL);
--- a/drivers/net/wireless/ath/ath12k/sawf.c
+++ b/drivers/net/wireless/ath/ath12k/sawf.c
@@ -242,3 +242,145 @@ bool ath12k_disable_svc_class(u8 svc_id)
return true;
}
+
+/* When fimware crash occurs/simulated with firmware recovery
+ * enabled, the service class records in the driver will be sent
+ * to the crashed chip for configuring in the firmware.
+ */
+int ath12k_sawf_reconfigure_on_crash(struct ath12k_base *ab)
+{
+ struct ath12k_sawf_svc_params svc_class = {};
+ struct ath12k *ar;
+ int i;
+
+ if (!ath12k_sawf_enable)
+ return 0;
+
+ if (!sawf_ctx)
+ return -ENODATA;
+
+ ar = ab->pdevs[0].ar;
+ if (!ar) {
+ ath12k_err(NULL, "Radio not initialized\n");
+ return -ENODATA;
+ }
+
+ for (i = 0; i < ATH12K_SAWF_SVC_CLASS_MAX; i++) {
+ if (!sawf_ctx->svc_classes[i].configured)
+ continue;
+ svc_class = sawf_ctx->svc_classes[i];
+ ath12k_wmi_svc_config_send(ar, &svc_class);
+ }
+ return 0;
+}
+
+/* TID which is an optional parameter, when not given during
+ * service class configuration, is calulated based on the
+ * other service class parameters.
+ */
+static u32 ath12k_sawf_tid_calc(struct ath12k_sawf_svc_params *cmd)
+{
+ u32 delay_bound_present, time_to_live_present, svc_interval_present, tid;
+
+ delay_bound_present =
+ cmd->delay_bound != SAWF_SVC_PARAM_DEFAULT_DELAY_BOUND;
+ time_to_live_present =
+ cmd->msdu_ttl != SAWF_SVC_PARAM_DEFAULT_TIME_TO_LIVE;
+ svc_interval_present =
+ cmd->service_interval != SAWF_SVC_PARAM_DEFAULT_SVC_INTERVAL;
+
+ tid = 0; /* default */
+ if (delay_bound_present) {
+ if (cmd->delay_bound < DELAY_BOUND_ULTRA_LOW) {
+ tid = 7;
+ } else if (cmd->delay_bound < DELAY_BOUND_LOW) {
+ tid = 6;
+ } else if (cmd->delay_bound < DELAY_BOUND_MID) {
+ tid = 4;
+ if (time_to_live_present &&
+ (cmd->msdu_ttl < TIME_TO_LIVE_MID))
+ tid = 5;
+ } else if (cmd->delay_bound < DELAY_BOUND_HIGH) {
+ tid = 4;
+ if (svc_interval_present) {
+ if (cmd->service_interval < SVC_INTERVAL_ULTRA_LOW)
+ tid = 7;
+ else if (cmd->service_interval < SVC_INTERVAL_LOW)
+ tid = 6;
+ }
+ }
+ } else if (svc_interval_present) {
+ if (cmd->service_interval < SVC_INTERVAL_ULTRA_LOW)
+ tid = 7;
+ else if (cmd->service_interval < SVC_INTERVAL_LOW)
+ tid = 6;
+ } else if (time_to_live_present) {
+ if (cmd->msdu_ttl < TIME_TO_LIVE_ULTRA_LOW)
+ tid = 7;
+ else if (cmd->msdu_ttl < TIME_TO_LIVE_LOW)
+ tid = 6;
+ }
+ return tid;
+}
+
+int ath12k_create_send_svc_params(struct ath12k_sawf_svc_params *param)
+{
+ int ret = 0;
+
+ if (!ath12k_svc_id_valid(param->svc_id)) {
+ ath12k_warn(NULL, "svc_id: %u is invalid, Service ID range: %d - %d\n",
+ param->svc_id, ATH12K_SAWF_SVC_CLASS_MIN,
+ ATH12K_SAWF_SVC_CLASS_MAX);
+ return -EINVAL;
+ }
+
+ if (ath12k_svc_id_configured(param->svc_id)) {
+ if (ath12k_get_tid(param->svc_id) != param->tid) {
+ ath12k_err(NULL, "Updating service class failed for TID ID:%u",
+ param->tid);
+ return -EINVAL;
+ }
+ }
+
+ if (param->tid == SAWF_SVC_PARAM_DEFAULT_TID)
+ param->tid = ath12k_sawf_tid_calc(param);
+
+ if (!ath12k_validate_sawf_param(param)) {
+ ath12k_err(NULL, "Service class parameters validation failed\n");
+ return -EINVAL;
+ }
+
+ ret = ath12k_send_sawf_configs_soc(param);
+ if (ret) {
+ ath12k_err(NULL, "service class configuration failed\n");
+ return ret;
+ }
+
+ param->configured = true;
+ ath12k_update_svc_class(param);
+ return ret;
+}
+
+int ath12k_sawf_disable_config(u8 svc_id)
+{
+ int ret;
+
+ if (!ath12k_svc_id_valid(svc_id)) {
+ ath12k_err(NULL, "svc_id: %u is invalid\n", svc_id);
+ return -EINVAL;
+ }
+
+ if (!ath12k_svc_id_configured(svc_id)) {
+ ath12k_err(NULL, "svc_id: %u is not configured\n", svc_id);
+ return -EINVAL;
+ }
+
+ ret = ath12k_sawf_send_disable_soc(svc_id);
+ if (ret) {
+ ath12k_err(NULL, "svc_id: %u disabling failed\n", svc_id);
+ return ret;
+ }
+
+ ath12k_disable_svc_class(svc_id);
+ return ret;
+}
--- a/drivers/net/wireless/ath/ath12k/sawf.h
+++ b/drivers/net/wireless/ath/ath12k/sawf.h
@@ -82,6 +82,16 @@ enum SAWF_SVC_PARAM_DEFAULTS {
SAWF_SVC_PARAM_DEFAULT_MSDU_LOSS_RATE = 0,
};
+#define DELAY_BOUND_ULTRA_LOW 10
+#define DELAY_BOUND_LOW 100
+#define DELAY_BOUND_MID 200
+#define DELAY_BOUND_HIGH 300
+#define SVC_INTERVAL_ULTRA_LOW 20
+#define SVC_INTERVAL_LOW 50
+#define TIME_TO_LIVE_ULTRA_LOW 20
+#define TIME_TO_LIVE_LOW 200
+#define TIME_TO_LIVE_MID 250
+
/**
* struct ath12k_sawf_svc_params - Service Class Parameters
* @svc_id: Service ID
@@ -134,5 +144,7 @@ bool ath12k_svc_id_valid(u8 svc_id);
void ath12k_update_svc_class(struct ath12k_sawf_svc_params *sawf_params);
bool ath12k_disable_svc_class(u8 svc_id);
int ath12k_get_tid(u8 svc_id);
-
+int ath12k_sawf_reconfigure_on_crash(struct ath12k_base *ab);
+int ath12k_create_send_svc_params(struct ath12k_sawf_svc_params *param);
+int ath12k_sawf_disable_config(u8 svc_id);
#endif /* ATH11K_SAWF_H */