mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-18 09:51:26 +00:00
This series is based on * 2020-07-10 ipq6018-ilq-11-0_qca_oem-034672b0676c37b1f4519e5720e18e95fe6236ef Add support for * qsdk kernel/v4.4 * qsdk ethernet subsystem * v5.7 ath11k backport + QualComm staging patches (wlan_ap_1.0) * ath11k-firmware * hostapd/iw/... Feature support * full boot, system detection * sysupgrade to nand * HE support via latest hostapd * driver support for usb, crypto, hwmon, cpufreq, ... Missing * NSS/HW flow offloading - FW blob is not redistributable Using the qsdk v4.4 is an intermediate solution while the vanilla is being tested. Vanilla kernel is almost on feature par. Work has already started to upstream the ethernet and switch drivers. Once complete the target will be fully upstream. Signed-off-by: John Crispin <john@phrozen.org>
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 "db_ring.h"
|
|
#include "spectral.h"
|
|
#include "thermal.h"
|
|
+#include "vendor.h"
|
|
|
|
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
|
|
|
|
@@ -445,6 +446,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;
|
|
@@ -569,6 +575,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
|
|
@@ -2791,6 +2791,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)
|
|
@@ -2830,6 +2857,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) {
|
|
@@ -2928,6 +2961,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;
|
|
@@ -4030,6 +4066,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);
|
|
@@ -4225,7 +4262,6 @@ static int ath11k_mac_op_add_interface(s
|
|
arvif->vdev_id, ret);
|
|
goto err;
|
|
}
|
|
-
|
|
ar->num_created_vdevs++;
|
|
ar->allocated_vdev_map |= 1LL << arvif->vdev_id;
|
|
ab->free_vdev_map &= ~(1LL << arvif->vdev_id);
|
|
@@ -4334,6 +4370,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;
|
|
@@ -4418,6 +4458,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
|
|
@@ -1174,6 +1174,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
|
|
@@ -2845,6 +2845,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;
|
|
@@ -5079,6 +5085,7 @@ int ath11k_wmi_vdev_spectral_conf(struct
|
|
struct ath11k_wmi_vdev_spectral_conf_param *param);
|
|
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);
|