blob: 04ddbbdfb209932902a09a2ad406d0472e86cbef [file] [log] [blame]
From 1ebb020ab2ee139baed670d3ddc10f4c15263a2a Mon Sep 17 00:00:00 2001
From: Xinming Hu <huxm@marvell.com>
Date: Mon, 20 Jun 2016 07:30:37 -0700
Subject: [PATCH] CHROMIUM: mwifiex: vendor command support for set tx power
mode
This patch is to port SAR changes for Marvell to kernel 5.10.
This patch add vendor command support for mwifiex, currently command 0
is used to set device transmit power mode.
Signed-off-by: Xinming Hu <huxm@marvell.com>
Signed-off-by: Shengzhen Li <szli@marvell.com>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Conflicts:
drivers/net/wireless/marvell/mwifiex/cfg80211.c: nla_parse requires
extack: extended ACK pointer as one additional argument on 5.10 kernel.
BUG=b:195142916
TEST=tast run -var=<router> -var <pacp> DUT_IP wifi.SetTXPower
Signed-off-by: Abhishek Kumar <kuabhs@chromium.org>
[kuabhs: Fixed merged conflicts on kernel 5.10, fixed
style check issues. Added 5.10 kernel required parameter
i.e. policy and maxattr]
Change-Id: I2bba15dfd4d050b156f31532211124b7523b8c85
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/3171689
Reviewed-by: Brian Norris <briannorris@chromium.org>
---
.../net/wireless/marvell/mwifiex/cfg80211.c | 90 +++++++++++++++++++
drivers/net/wireless/marvell/mwifiex/main.h | 19 ++++
2 files changed, 109 insertions(+)
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index 0dd1cb470abdb8244b2f2857e8550d12c6c2469f..23da297c908b0b09886db6476bd6444c87ecf8a0 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -4326,6 +4326,94 @@ int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter)
return 0;
}
+static const struct nla_policy
+mwifiex_vendor_attr_policy[NUM_MWIFIEX_VENDOR_CMD_ATTR] = {
+ [MWIFIEX_VENDOR_CMD_ATTR_TXP_LIMIT_24] = { .type = NLA_U8 },
+ [MWIFIEX_VENDOR_CMD_ATTR_TXP_LIMIT_52] = { .type = NLA_U8 },
+};
+
+static int mwifiex_parse_vendor_data(struct nlattr **tb,
+ const void *data, int data_len)
+{
+ if (!data)
+ return -EINVAL;
+
+ return nla_parse(tb, MAX_MWIFIEX_VENDOR_CMD_ATTR, data, data_len,
+ mwifiex_vendor_attr_policy, NULL);
+}
+
+static int mwifiex_vendor_set_tx_power_limt(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
+ struct nlattr *tb[NUM_MWIFIEX_VENDOR_CMD_ATTR];
+ int ret;
+ u8 lowpwr;
+
+ ret = mwifiex_parse_vendor_data(tb, data, data_len);
+ if (ret)
+ return ret;
+
+ if (tb[MWIFIEX_VENDOR_CMD_ATTR_TXP_LIMIT_24]) {
+ lowpwr = nla_get_u8(tb[MWIFIEX_VENDOR_CMD_ATTR_TXP_LIMIT_24]) ?
+ true : false;
+ if (lowpwr != priv->adapter->lowpwr_mode_2g4 &&
+ priv->adapter->dt_node) {
+ ret = mwifiex_dnld_dt_cfgdata
+ (priv, priv->adapter->dt_node, lowpwr ?
+ "marvell,caldata_00_txpwrlimit_2g" :
+ "marvell,caldata_01_txpwrlimit_2g");
+ if (ret)
+ return -1;
+ priv->adapter->lowpwr_mode_2g4 = lowpwr;
+ }
+ }
+
+ if (tb[MWIFIEX_VENDOR_CMD_ATTR_TXP_LIMIT_52]) {
+ lowpwr = nla_get_u8(tb[MWIFIEX_VENDOR_CMD_ATTR_TXP_LIMIT_52]) ?
+ true : false;
+ if (lowpwr != priv->adapter->lowpwr_mode_5g2 &&
+ priv->adapter->dt_node) {
+ ret = mwifiex_dnld_dt_cfgdata
+ (priv, priv->adapter->dt_node, lowpwr ?
+ "marvell,caldata_00_txpwrlimit_5g" :
+ "marvell,caldata_01_txpwrlimit_5g");
+ if (ret)
+ return -1;
+ priv->adapter->lowpwr_mode_5g2 = lowpwr;
+ }
+ }
+
+ return 0;
+}
+
+static const struct wiphy_vendor_command mwifiex_vendor_commands[] = {
+ {
+ .info = {
+ .vendor_id = MWIFIEX_VENDOR_ID,
+ .subcmd = MWIFIEX_VENDOR_CMD_SET_TX_POWER_LIMIT,
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .doit = mwifiex_vendor_set_tx_power_limt,
+ .policy = mwifiex_vendor_attr_policy,
+ .maxattr = MAX_MWIFIEX_VENDOR_CMD_ATTR,
+ },
+};
+
+/* @brief register vendor commands and events
+ *
+ * @param wiphy A pointer to wiphy struct
+ *
+ * @return
+ */
+static void mwifiex_register_cfg80211_vendor_command(struct wiphy *wiphy)
+{
+ wiphy->vendor_commands = mwifiex_vendor_commands;
+ wiphy->n_vendor_commands = ARRAY_SIZE(mwifiex_vendor_commands);
+}
+
/*
* This function registers the device with CFG802.11 subsystem.
*
@@ -4363,6 +4451,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
if (ISSUPP_ADHOC_ENABLED(adapter->fw_cap_info))
wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
+ mwifiex_register_cfg80211_vendor_command(wiphy);
+
wiphy->bands[NL80211_BAND_2GHZ] = devm_kmemdup(adapter->dev,
&mwifiex_band_2ghz,
sizeof(mwifiex_band_2ghz),
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index c5164ae41b547534ec0c62ec0e6fa08f6251e645..c2bd953b248ea69edd71f1611a39888a26502cf8 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -158,6 +158,23 @@ enum {
#define MWIFIEX_MAC_LOCAL_ADMIN_BIT 41
+/* marvell vendor command and event ID */
+#define MWIFIEX_VENDOR_ID 0x005043
+
+/* vendor sub command */
+enum mwifiex_vendor_sub_command {
+ MWIFIEX_VENDOR_CMD_SET_TX_POWER_LIMIT = 0,
+ MWIFIEX_VENDOR_CMD_MAX,
+};
+
+enum mwifiex_vendor_cmd_attr {
+ MWIFIEX_VENDOR_CMD_ATTR_INVALID,
+ MWIFIEX_VENDOR_CMD_ATTR_TXP_LIMIT_24,
+ MWIFIEX_VENDOR_CMD_ATTR_TXP_LIMIT_52,
+ NUM_MWIFIEX_VENDOR_CMD_ATTR,
+ MAX_MWIFIEX_VENDOR_CMD_ATTR = NUM_MWIFIEX_VENDOR_CMD_ATTR - 1,
+};
+
/**
*enum mwifiex_debug_level - marvell wifi debug level
*/
@@ -848,6 +865,8 @@ struct mwifiex_if_ops {
};
struct mwifiex_adapter {
+ u8 lowpwr_mode_2g4;
+ u8 lowpwr_mode_5g2;
u8 iface_type;
unsigned int debug_mask;
struct mwifiex_iface_comb iface_limit;
--
2.46.0.792.g87dc391469-goog