mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-18 18:01:23 +00:00
325 lines
9.2 KiB
Diff
325 lines
9.2 KiB
Diff
--- a/drivers/net/wireless/ath/ath11k/core.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
|
@@ -24,6 +24,7 @@
|
|
#include "thermal.h"
|
|
#include "dbring.h"
|
|
#include "spectral.h"
|
|
+#include "vendor.h"
|
|
|
|
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
|
|
|
|
@@ -454,6 +455,11 @@ struct ath11k_coex_info {
|
|
u32 pta_priority;
|
|
};
|
|
|
|
+enum ath11k_ap_ps_state {
|
|
+ ATH11K_AP_PS_STATE_OFF,
|
|
+ ATH11K_AP_PS_STATE_ON,
|
|
+};
|
|
+
|
|
struct ath11k {
|
|
struct ath11k_base *ab;
|
|
struct ath11k_pdev *pdev;
|
|
@@ -581,6 +587,8 @@ struct ath11k {
|
|
bool dfs_block_radar_events;
|
|
struct ath11k_thermal thermal;
|
|
struct completion fw_mode_reset;
|
|
+ int ap_ps_enabled;
|
|
+ enum ath11k_ap_ps_state ap_ps_state;
|
|
};
|
|
|
|
struct ath11k_band_cap {
|
|
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
|
@@ -2913,6 +2913,33 @@ static void ath11k_mac_dec_num_stations(
|
|
ar->num_stations--;
|
|
}
|
|
|
|
+int ath11k_mac_ap_ps_recalc(struct ath11k *ar)
|
|
+{
|
|
+ struct ath11k_vif *arvif;
|
|
+ bool has_sta_iface = false;
|
|
+ enum ath11k_ap_ps_state state = ATH11K_AP_PS_STATE_OFF;
|
|
+ int ret = 0;
|
|
+
|
|
+ list_for_each_entry(arvif, &ar->arvifs, list) {
|
|
+ if (arvif->vdev_type == WMI_VDEV_TYPE_STA) {
|
|
+ has_sta_iface = true;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!has_sta_iface && !ar->num_stations && ar->ap_ps_enabled)
|
|
+ state = ATH11K_AP_PS_STATE_ON;
|
|
+
|
|
+ if (ar->ap_ps_state == state)
|
|
+ return ret;
|
|
+
|
|
+ ret = ath11k_wmi_pdev_ap_ps_cmd_send(ar, ar->pdev->pdev_id, state);
|
|
+ if (!ret)
|
|
+ ar->ap_ps_state = state;
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static int ath11k_mac_station_add(struct ath11k *ar,
|
|
struct ieee80211_vif *vif,
|
|
struct ieee80211_sta *sta)
|
|
@@ -2952,6 +2979,12 @@ static int ath11k_mac_station_add(struct
|
|
ath11k_dbg(ab, ATH11K_DBG_MAC, "Added peer: %pM for VDEV: %d\n",
|
|
sta->addr, arvif->vdev_id);
|
|
|
|
+ ret = ath11k_mac_ap_ps_recalc(ar);
|
|
+ if (ret) {
|
|
+ ath11k_warn(ar->ab, "failed to send ap ps ret %d\n", ret);
|
|
+ goto exit;
|
|
+ }
|
|
+
|
|
if (ath11k_debug_is_extd_tx_stats_enabled(ar)) {
|
|
arsta->tx_stats = kzalloc(sizeof(*arsta->tx_stats), GFP_KERNEL);
|
|
if (!arsta->tx_stats) {
|
|
@@ -3058,6 +3091,9 @@ static int ath11k_mac_op_sta_state(struc
|
|
|
|
kfree(arsta->tx_stats);
|
|
arsta->tx_stats = NULL;
|
|
+ ret = ath11k_mac_ap_ps_recalc(ar);
|
|
+ if (ret)
|
|
+ ath11k_warn(ar->ab, "failed to send ap ps ret %d\n", ret);
|
|
|
|
kfree(arsta->rx_stats);
|
|
arsta->rx_stats = NULL;
|
|
@@ -4229,6 +4265,7 @@ static void ath11k_mac_op_stop(struct ie
|
|
|
|
clear_bit(ATH11K_CAC_RUNNING, &ar->dev_flags);
|
|
ar->state = ATH11K_STATE_OFF;
|
|
+ ar->ap_ps_state = ATH11K_AP_PS_STATE_OFF;
|
|
mutex_unlock(&ar->conf_mutex);
|
|
|
|
cancel_delayed_work_sync(&ar->scan.timeout);
|
|
@@ -4430,7 +4467,6 @@ static int ath11k_mac_op_add_interface(s
|
|
arvif->vdev_id, ret);
|
|
goto err;
|
|
}
|
|
-
|
|
ar->num_created_vdevs++;
|
|
ath11k_dbg(ab, ATH11K_DBG_MAC, "vdev %pM created, vdev_id %d\n",
|
|
vif->addr, arvif->vdev_id);
|
|
@@ -4555,6 +4591,10 @@ static int ath11k_mac_op_add_interface(s
|
|
|
|
ath11k_dp_vdev_tx_attach(ar, arvif);
|
|
|
|
+ ret = ath11k_mac_ap_ps_recalc(ar);
|
|
+ if (ret)
|
|
+ ath11k_warn(ar->ab, "failed to set ap ps ret %d\n", ret);
|
|
+
|
|
mutex_unlock(&ar->conf_mutex);
|
|
|
|
return 0;
|
|
@@ -4641,6 +4681,7 @@ static void ath11k_mac_op_remove_interfa
|
|
|
|
/* Recalc txpower for remaining vdev */
|
|
ath11k_mac_txpower_recalc(ar);
|
|
+ ath11k_mac_ap_ps_recalc(ar);
|
|
clear_bit(ATH11K_FLAG_MONITOR_ENABLED, &ar->monitor_flags);
|
|
|
|
/* TODO: recal traffic pause state based on the available vdevs */
|
|
--- a/drivers/net/wireless/ath/ath11k/mac.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/mac.h
|
|
@@ -118,6 +118,7 @@ struct ath11k_generic_iter {
|
|
|
|
extern const struct htt_rx_ring_tlv_filter ath11k_mac_mon_status_filter_default;
|
|
|
|
+int ath11k_mac_ap_ps_recalc(struct ath11k *ar);
|
|
void ath11k_mac_destroy(struct ath11k_base *ab);
|
|
void ath11k_mac_unregister(struct ath11k_base *ab);
|
|
int ath11k_mac_register(struct ath11k_base *ab);
|
|
--- a/drivers/net/wireless/ath/ath11k/vendor.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/vendor.c
|
|
@@ -6,7 +6,6 @@
|
|
#include <net/netlink.h>
|
|
#include <net/mac80211.h>
|
|
#include "core.h"
|
|
-#include "vendor.h"
|
|
#include "debug.h"
|
|
|
|
static const struct nla_policy
|
|
@@ -21,6 +20,11 @@ ath11k_vendor_wlan_prio_policy[QCA_WLAN_
|
|
[QCA_WLAN_VENDOR_ATTR_WLAN_PRIO_WEIGHT] = { .type = NLA_U8 },
|
|
};
|
|
|
|
+static const struct nla_policy
|
|
+ath11k_vendor_set_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
|
|
+ [QCA_WLAN_VENDOR_ATTR_CONFIG_GTX] = {.type = NLA_FLAG}
|
|
+};
|
|
+
|
|
static int ath11k_vendor_btcoex_configure(struct wiphy *wiphy,
|
|
struct wireless_dev *wdev,
|
|
const void *data,
|
|
@@ -101,6 +105,51 @@ out:
|
|
return ret;
|
|
}
|
|
|
|
+static int ath11k_vendor_set_wifi_config(struct wiphy *wihpy,
|
|
+ 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_CONFIG_MAX + 1];
|
|
+ int ret = 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_CONFIG_MAX, data, data_len,
|
|
+ ath11k_vendor_set_wifi_config_policy, NULL);
|
|
+ if (ret) {
|
|
+ ath11k_warn(ar->ab, "invalid set wifi config policy attribute\n");
|
|
+ goto exit;
|
|
+ }
|
|
+
|
|
+ ar->ap_ps_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GTX]);
|
|
+ ret = ath11k_mac_ap_ps_recalc(ar);
|
|
+ if (ret) {
|
|
+ ath11k_warn(ar->ab, "failed to send ap ps ret %d\n", ret);
|
|
+ goto exit;
|
|
+ }
|
|
+
|
|
+exit:
|
|
+ mutex_unlock(&ar->conf_mutex);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static struct wiphy_vendor_command ath11k_vendor_commands[] = {
|
|
{
|
|
.info.vendor_id = QCA_NL80211_VENDOR_ID,
|
|
@@ -108,8 +157,18 @@ static struct wiphy_vendor_command ath11
|
|
.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
|
|
WIPHY_VENDOR_CMD_NEED_RUNNING,
|
|
.doit = ath11k_vendor_btcoex_configure,
|
|
- .policy = ath11k_vendor_btcoex_config_policy
|
|
- }
|
|
+ .policy = ath11k_vendor_btcoex_config_policy,
|
|
+ .maxattr = QCA_WLAN_VENDOR_ATTR_BTCOEX_CONFIG_MAX
|
|
+ },
|
|
+ {
|
|
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
|
|
+ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
|
|
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
|
|
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
|
|
+ .doit = ath11k_vendor_set_wifi_config,
|
|
+ .policy = ath11k_vendor_set_wifi_config_policy,
|
|
+ .maxattr = QCA_WLAN_VENDOR_ATTR_CONFIG_MAX
|
|
+ },
|
|
};
|
|
|
|
int ath11k_vendor_register(struct ath11k *ar)
|
|
--- a/drivers/net/wireless/ath/ath11k/vendor.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/vendor.h
|
|
@@ -9,6 +9,9 @@
|
|
#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_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
|
|
@@ -58,7 +61,17 @@ enum qca_wlan_vendor_attr_wlan_prio {
|
|
QCA_WLAN_VENDOR_ATTR_WLAN_PRIO_LAST - 1,
|
|
};
|
|
|
|
+/* Attributes for data used by
|
|
+ * QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION
|
|
+ */
|
|
+enum qca_wlan_vendor_attr_config {
|
|
+ QCA_WLAN_VENDOR_ATTR_CONFIG_GTX = 57,
|
|
|
|
+ /* keep last */
|
|
+ QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST,
|
|
+ QCA_WLAN_VENDOR_ATTR_CONFIG_MAX =
|
|
+ QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST - 1,
|
|
+};
|
|
|
|
/**
|
|
* enum qca_wlan_vendor_attr_btcoex_config - Used by the vendor command
|
|
--- a/drivers/net/wireless/ath/ath11k/wmi.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
|
|
@@ -1193,6 +1193,38 @@ ath11k_wmi_rx_reord_queue_remove(struct
|
|
return ret;
|
|
}
|
|
|
|
+int ath11k_wmi_pdev_ap_ps_cmd_send(struct ath11k *ar, u8 pdev_id,
|
|
+ u32 param_value)
|
|
+{
|
|
+ struct ath11k_pdev_wmi *wmi = ar->wmi;
|
|
+ struct wmi_pdev_ap_ps_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_pdev_ap_ps_cmd *)skb->data;
|
|
+ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG,
|
|
+ WMI_TAG_PDEV_GREEN_AP_PS_ENABLE_CMD) |
|
|
+ FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
|
|
+ cmd->pdev_id = pdev_id;
|
|
+ cmd->param_value = param_value;
|
|
+
|
|
+ ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID);
|
|
+ if (ret) {
|
|
+ ath11k_warn(ar->ab, "failed to send ap ps enable/disable cmd\n");
|
|
+ dev_kfree_skb(skb);
|
|
+ }
|
|
+
|
|
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
|
|
+ "wmi pdev ap ps set pdev id %d value %d\n",
|
|
+ pdev_id, param_value);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
int ath11k_wmi_pdev_set_param(struct ath11k *ar, u32 param_id,
|
|
u32 param_value, u8 pdev_id)
|
|
{
|
|
--- a/drivers/net/wireless/ath/ath11k/wmi.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
|
|
@@ -2902,6 +2902,12 @@ struct set_fwtest_params {
|
|
u32 value;
|
|
};
|
|
|
|
+struct wmi_pdev_ap_ps_cmd {
|
|
+ u32 tlv_header;
|
|
+ u32 pdev_id;
|
|
+ u32 param_value;
|
|
+} __packed;
|
|
+
|
|
struct wmi_fwtest_set_param_cmd_param {
|
|
u32 tlv_header;
|
|
u32 param_id;
|
|
@@ -5185,6 +5191,7 @@ int ath11k_wmi_send_obss_spr_cmd(struct
|
|
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_pdev_ap_ps_cmd_send(struct ath11k *ar, u8 pdev_id, u32 value);
|
|
int ath11k_wmi_send_obss_color_collision_cfg_cmd(struct ath11k *ar, u32 vdev_id,
|
|
u8 bss_color, u32 period,
|
|
bool enable);
|