summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-11-21 08:28:08 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2024-11-21 08:28:08 -0800
commitfcc79e1714e8c2b8e216dc3149812edd37884eef (patch)
tree17a51d29db810b81412be040aaf380936b3261b4 /drivers/net/wireless/ath
parent6e95ef0258ff4ee23ae3b06bf6b00b33dbbd5ef7 (diff)
parentdd7207838d38780b51e4690ee508ab2d5057e099 (diff)
Merge tag 'net-next-6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next
Pull networking updates from Paolo Abeni: "The most significant set of changes is the per netns RTNL. The new behavior is disabled by default, regression risk should be contained. Notably the new config knob PTP_1588_CLOCK_VMCLOCK will inherit its default value from PTP_1588_CLOCK_KVM, as the first is intended to be a more reliable replacement for the latter. Core: - Started a very large, in-progress, effort to make the RTNL lock scope per network-namespace, thus reducing the lock contention significantly in the containerized use-case, comprising: - RCU-ified some relevant slices of the FIB control path - introduce basic per netns locking helpers - namespacified the IPv4 address hash table - remove rtnl_register{,_module}() in favour of rtnl_register_many() - refactor rtnl_{new,del,set}link() moving as much validation as possible out of RTNL lock - convert all phonet doit() and dumpit() handlers to RCU - convert IPv4 addresses manipulation to per-netns RTNL - convert virtual interface creation to per-netns RTNL the per-netns lock infrastructure is guarded by the CONFIG_DEBUG_NET_SMALL_RTNL knob, disabled by default ad interim. - Introduce NAPI suspension, to efficiently switching between busy polling (NAPI processing suspended) and normal processing. - Migrate the IPv4 routing input, output and control path from direct ToS usage to DSCP macros. This is a work in progress to make ECN handling consistent and reliable. - Add drop reasons support to the IPv4 rotue input path, allowing better introspection in case of packets drop. - Make FIB seqnum lockless, dropping RTNL protection for read access. - Make inet{,v6} addresses hashing less predicable. - Allow providing timestamp OPT_ID via cmsg, to correlate TX packets and timestamps Things we sprinkled into general kernel code: - Add small file operations for debugfs, to reduce the struct ops size. - Refactoring and optimization for the implementation of page_frag API, This is a preparatory work to consolidate the page_frag implementation. Netfilter: - Optimize set element transactions to reduce memory consumption - Extended netlink error reporting for attribute parser failure. - Make legacy xtables configs user selectable, giving users the option to configure iptables without enabling any other config. - Address a lot of false-positive RCU issues, pointed by recent CI improvements. BPF: - Put xsk sockets on a struct diet and add various cleanups. Overall, this helps to bump performance by 12% for some workloads. - Extend BPF selftests to increase coverage of XDP features in combination with BPF cpumap. - Optimize and homogenize bpf_csum_diff helper for all archs and also add a batch of new BPF selftests for it. - Extend netkit with an option to delegate skb->{mark,priority} scrubbing to its BPF program. - Make the bpf_get_netns_cookie() helper available also to tc(x) BPF programs. Protocols: - Introduces 4-tuple hash for connected udp sockets, speeding-up significantly connected sockets lookup. - Add a fastpath for some TCP timers that usually expires after close, the socket lock contention. - Add inbound and outbound xfrm state caches to speed up state lookups. - Avoid sending MPTCP advertisements on stale subflows, reducing risks on loosing them. - Make neighbours table flushing more scalable, maintaining per device neigh lists. Driver API: - Introduce a unified interface to configure transmission H/W shaping, and expose it to user-space via generic-netlink. - Add support for per-NAPI config via netlink. This makes napi configuration persistent across queues removal and re-creation. Requires driver updates, currently supported drivers are: nVidia/Mellanox mlx4 and mlx5, Broadcom brcm and Intel ice. - Add ethtool support for writing SFP / PHY firmware blocks. - Track RSS context allocation from ethtool core. - Implement support for mirroring to DSA CPU port, via TC mirror offload. - Consolidate FDB updates notification, to avoid duplicates on device-specific entries. - Expose DPLL clock quality level to the user-space. - Support master-slave PHY config via device tree. Tests and tooling: - forwarding: introduce deferred commands, to simplify the cleanup phase Drivers: - Updated several drivers - Amazon vNic, Google vNic, Microsoft vNic, Intel e1000e and Broadcom Tigon3 - to use netdev-genl to link the IRQs and queues to NAPI IDs, allowing busy polling and better introspection. - Ethernet high-speed NICs: - nVidia/Mellanox: - mlx5: - a large refactor to implement support for cross E-Switch scheduling - refactor H/W conter management to let it scale better - H/W GRO cleanups - Intel (100G, ice):: - add support for ethtool reset - implement support for per TX queue H/W shaping - AMD/Solarflare: - implement per device queue stats support - Broadcom (bnxt): - improve wildcard l4proto on IPv4/IPv6 ntuple rules - Marvell Octeon: - Add representor support for each Resource Virtualization Unit (RVU) device. - Hisilicon: - add support for the BMC Gigabit Ethernet - IBM (EMAC): - driver cleanup and modernization - Cisco (VIC): - raise the queues number limit to 256 - Ethernet virtual: - Google vNIC: - implement page pool support - macsec: - inherit lower device's features and TSO limits when offloading - virtio_net: - enable premapped mode by default - support for XDP socket(AF_XDP) zerocopy TX - wireguard: - set the TSO max size to be GSO_MAX_SIZE, to aggregate larger packets. - Ethernet NICs embedded and virtual: - Broadcom ASP: - enable software timestamping - Freescale: - add enetc4 PF driver - MediaTek: Airoha SoC: - implement BQL support - RealTek r8169: - enable TSO by default on r8168/r8125 - implement extended ethtool stats - Renesas AVB: - enable TX checksum offload - Synopsys (stmmac): - support header splitting for vlan tagged packets - move common code for DWMAC4 and DWXGMAC into a separate FPE module. - add dwmac driver support for T-HEAD TH1520 SoC - Synopsys (xpcs): - driver refactor and cleanup - TI: - icssg_prueth: add VLAN offload support - Xilinx emaclite: - add clock support - Ethernet switches: - Microchip: - implement support for the lan969x Ethernet switch family - add LAN9646 switch support to KSZ DSA driver - Ethernet PHYs: - Marvel: 88q2x: enable auto negotiation - Microchip: add support for LAN865X Rev B1 and LAN867X Rev C1/C2 - PTP: - Add support for the Amazon virtual clock device - Add PtP driver for s390 clocks - WiFi: - mac80211 - EHT 1024 aggregation size for transmissions - new operation to indicate that a new interface is to be added - support radio separation of multi-band devices - move wireless extension spy implementation to libiw - Broadcom: - brcmfmac: optional LPO clock support - Microchip: - add support for Atmel WILC3000 - Qualcomm (ath12k): - firmware coredump collection support - add debugfs support for a multitude of statistics - Qualcomm (ath5k): - Arcadyan ARV45XX AR2417 & Gigaset SX76[23] AR241[34]A support - Realtek: - rtw88: 8821au and 8812au USB adapters support - rtw89: add thermal protection - rtw89: fine tune BT-coexsitence to improve user experience - rtw89: firmware secure boot for WiFi 6 chip - Bluetooth - add Qualcomm WCN785x support for ids Foxconn 0xe0fc/0xe0f3 and 0x13d3:0x3623 - add Realtek RTL8852BE support for id Foxconn 0xe123 - add MediaTek MT7920 support for wireless module ids - btintel_pcie: add handshake between driver and firmware - btintel_pcie: add recovery mechanism - btnxpuart: add GPIO support to power save feature" * tag 'net-next-6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1475 commits) mm: page_frag: fix a compile error when kernel is not compiled Documentation: tipc: fix formatting issue in tipc.rst selftests: nic_performance: Add selftest for performance of NIC driver selftests: nic_link_layer: Add selftest case for speed and duplex states selftests: nic_link_layer: Add link layer selftest for NIC driver bnxt_en: Add FW trace coredump segments to the coredump bnxt_en: Add a new ethtool -W dump flag bnxt_en: Add 2 parameters to bnxt_fill_coredump_seg_hdr() bnxt_en: Add functions to copy host context memory bnxt_en: Do not free FW log context memory bnxt_en: Manage the FW trace context memory bnxt_en: Allocate backing store memory for FW trace logs bnxt_en: Add a 'force' parameter to bnxt_free_ctx_mem() bnxt_en: Refactor bnxt_free_ctx_mem() bnxt_en: Add mem_valid bit to struct bnxt_ctx_mem_type bnxt_en: Update firmware interface spec to 1.10.3.85 selftests/bpf: Add some tests with sockmap SK_PASS bpf: fix recursive lock when verdict program return SK_PASS wireguard: device: support big tcp GSO wireguard: selftests: load nf_conntrack if not present ...
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r--drivers/net/wireless/ath/ath10k/ahb.c8
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c105
-rw-r--r--drivers/net/wireless/ath/ath10k/sdio.c6
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.c6
-rw-r--r--drivers/net/wireless/ath/ath11k/ahb.c20
-rw-r--r--drivers/net/wireless/ath/ath11k/core.c2
-rw-r--r--drivers/net/wireless/ath/ath11k/hal.c1
-rw-r--r--drivers/net/wireless/ath/ath11k/mac.c5
-rw-r--r--drivers/net/wireless/ath/ath11k/qmi.c3
-rw-r--r--drivers/net/wireless/ath/ath11k/wow.c39
-rw-r--r--drivers/net/wireless/ath/ath12k/Kconfig10
-rw-r--r--drivers/net/wireless/ath/ath12k/Makefile1
-rw-r--r--drivers/net/wireless/ath/ath12k/ce.h2
-rw-r--r--drivers/net/wireless/ath/ath12k/core.c9
-rw-r--r--drivers/net/wireless/ath/ath12k/core.h110
-rw-r--r--drivers/net/wireless/ath/ath12k/coredump.c51
-rw-r--r--drivers/net/wireless/ath/ath12k/coredump.h80
-rw-r--r--drivers/net/wireless/ath/ath12k/debugfs.c4
-rw-r--r--drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c1358
-rw-r--r--drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h444
-rw-r--r--drivers/net/wireless/ath/ath12k/dp.c58
-rw-r--r--drivers/net/wireless/ath/ath12k/dp.h7
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_mon.c122
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_rx.c16
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_rx.h2
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_tx.c9
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_tx.h2
-rw-r--r--drivers/net/wireless/ath/ath12k/hal.c12
-rw-r--r--drivers/net/wireless/ath/ath12k/hal_rx.h53
-rw-r--r--drivers/net/wireless/ath/ath12k/hif.h6
-rw-r--r--drivers/net/wireless/ath/ath12k/hw.c4
-rw-r--r--drivers/net/wireless/ath/ath12k/mac.c1850
-rw-r--r--drivers/net/wireless/ath/ath12k/mac.h11
-rw-r--r--drivers/net/wireless/ath/ath12k/mhi.c5
-rw-r--r--drivers/net/wireless/ath/ath12k/mhi.h2
-rw-r--r--drivers/net/wireless/ath/ath12k/p2p.c17
-rw-r--r--drivers/net/wireless/ath/ath12k/p2p.h2
-rw-r--r--drivers/net/wireless/ath/ath12k/pci.c200
-rw-r--r--drivers/net/wireless/ath/ath12k/peer.c13
-rw-r--r--drivers/net/wireless/ath/ath12k/peer.h4
-rw-r--r--drivers/net/wireless/ath/ath12k/rx_desc.h88
-rw-r--r--drivers/net/wireless/ath/ath12k/wmi.c30
-rw-r--r--drivers/net/wireless/ath/ath12k/wmi.h8
-rw-r--r--drivers/net/wireless/ath/ath12k/wow.c87
-rw-r--r--drivers/net/wireless/ath/ath5k/ahb.c8
-rw-r--r--drivers/net/wireless/ath/ath5k/pci.c2
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.h8
-rw-r--r--drivers/net/wireless/ath/ath9k/ahb.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_aic.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/btcoex.c16
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_hst.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c52
-rw-r--r--drivers/net/wireless/ath/wcn36xx/main.c8
-rw-r--r--drivers/net/wireless/ath/wcn36xx/wcn36xx.h2
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c1
59 files changed, 3791 insertions, 1222 deletions
diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c
index f0441b3d7dcb..db9f9ebcb62d 100644
--- a/drivers/net/wireless/ath/ath10k/ahb.c
+++ b/drivers/net/wireless/ath/ath10k/ahb.c
@@ -837,12 +837,12 @@ static void ath10k_ahb_remove(struct platform_device *pdev)
}
static struct platform_driver ath10k_ahb_driver = {
- .driver = {
- .name = "ath10k_ahb",
+ .driver = {
+ .name = "ath10k_ahb",
.of_match_table = ath10k_ahb_of_match,
},
- .probe = ath10k_ahb_probe,
- .remove_new = ath10k_ahb_remove,
+ .probe = ath10k_ahb_probe,
+ .remove = ath10k_ahb_remove,
};
int ath10k_ahb_init(void)
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 646e1737d4c4..c61b95a928da 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -6369,7 +6369,7 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw,
struct ath10k *ar = hw->priv;
struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct cfg80211_scan_request *req = &hw_req->req;
- struct wmi_start_scan_arg arg;
+ struct wmi_start_scan_arg *arg = NULL;
int ret = 0;
int i;
u32 scan_timeout;
@@ -6402,56 +6402,61 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw,
if (ret)
goto exit;
- memset(&arg, 0, sizeof(arg));
- ath10k_wmi_start_scan_init(ar, &arg);
- arg.vdev_id = arvif->vdev_id;
- arg.scan_id = ATH10K_SCAN_ID;
+ arg = kzalloc(sizeof(*arg), GFP_KERNEL);
+ if (!arg) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ ath10k_wmi_start_scan_init(ar, arg);
+ arg->vdev_id = arvif->vdev_id;
+ arg->scan_id = ATH10K_SCAN_ID;
if (req->ie_len) {
- arg.ie_len = req->ie_len;
- memcpy(arg.ie, req->ie, arg.ie_len);
+ arg->ie_len = req->ie_len;
+ memcpy(arg->ie, req->ie, arg->ie_len);
}
if (req->n_ssids) {
- arg.n_ssids = req->n_ssids;
- for (i = 0; i < arg.n_ssids; i++) {
- arg.ssids[i].len = req->ssids[i].ssid_len;
- arg.ssids[i].ssid = req->ssids[i].ssid;
+ arg->n_ssids = req->n_ssids;
+ for (i = 0; i < arg->n_ssids; i++) {
+ arg->ssids[i].len = req->ssids[i].ssid_len;
+ arg->ssids[i].ssid = req->ssids[i].ssid;
}
} else {
- arg.scan_ctrl_flags |= WMI_SCAN_FLAG_PASSIVE;
+ arg->scan_ctrl_flags |= WMI_SCAN_FLAG_PASSIVE;
}
if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
- arg.scan_ctrl_flags |= WMI_SCAN_ADD_SPOOFED_MAC_IN_PROBE_REQ;
- ether_addr_copy(arg.mac_addr.addr, req->mac_addr);
- ether_addr_copy(arg.mac_mask.addr, req->mac_addr_mask);
+ arg->scan_ctrl_flags |= WMI_SCAN_ADD_SPOOFED_MAC_IN_PROBE_REQ;
+ ether_addr_copy(arg->mac_addr.addr, req->mac_addr);
+ ether_addr_copy(arg->mac_mask.addr, req->mac_addr_mask);
}
if (req->n_channels) {
- arg.n_channels = req->n_channels;
- for (i = 0; i < arg.n_channels; i++)
- arg.channels[i] = req->channels[i]->center_freq;
+ arg->n_channels = req->n_channels;
+ for (i = 0; i < arg->n_channels; i++)
+ arg->channels[i] = req->channels[i]->center_freq;
}
/* if duration is set, default dwell times will be overwritten */
if (req->duration) {
- arg.dwell_time_active = req->duration;
- arg.dwell_time_passive = req->duration;
- arg.burst_duration_ms = req->duration;
+ arg->dwell_time_active = req->duration;
+ arg->dwell_time_passive = req->duration;
+ arg->burst_duration_ms = req->duration;
- scan_timeout = min_t(u32, arg.max_rest_time *
- (arg.n_channels - 1) + (req->duration +
+ scan_timeout = min_t(u32, arg->max_rest_time *
+ (arg->n_channels - 1) + (req->duration +
ATH10K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD) *
- arg.n_channels, arg.max_scan_time);
+ arg->n_channels, arg->max_scan_time);
} else {
- scan_timeout = arg.max_scan_time;
+ scan_timeout = arg->max_scan_time;
}
/* Add a 200ms margin to account for event/command processing */
scan_timeout += 200;
- ret = ath10k_start_scan(ar, &arg);
+ ret = ath10k_start_scan(ar, arg);
if (ret) {
ath10k_warn(ar, "failed to start hw scan: %d\n", ret);
spin_lock_bh(&ar->data_lock);
@@ -6463,6 +6468,8 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw,
msecs_to_jiffies(scan_timeout));
exit:
+ kfree(arg);
+
mutex_unlock(&ar->conf_mutex);
return ret;
}
@@ -7899,7 +7906,7 @@ static int ath10k_remain_on_channel(struct ieee80211_hw *hw,
{
struct ath10k *ar = hw->priv;
struct ath10k_vif *arvif = (void *)vif->drv_priv;
- struct wmi_start_scan_arg arg;
+ struct wmi_start_scan_arg *arg = NULL;
int ret = 0;
u32 scan_time_msec;
@@ -7936,20 +7943,25 @@ static int ath10k_remain_on_channel(struct ieee80211_hw *hw,
scan_time_msec = ar->hw->wiphy->max_remain_on_channel_duration * 2;
- memset(&arg, 0, sizeof(arg));
- ath10k_wmi_start_scan_init(ar, &arg);
- arg.vdev_id = arvif->vdev_id;
- arg.scan_id = ATH10K_SCAN_ID;
- arg.n_channels = 1;
- arg.channels[0] = chan->center_freq;
- arg.dwell_time_active = scan_time_msec;
- arg.dwell_time_passive = scan_time_msec;
- arg.max_scan_time = scan_time_msec;
- arg.scan_ctrl_flags |= WMI_SCAN_FLAG_PASSIVE;
- arg.scan_ctrl_flags |= WMI_SCAN_FILTER_PROBE_REQ;
- arg.burst_duration_ms = duration;
-
- ret = ath10k_start_scan(ar, &arg);
+ arg = kzalloc(sizeof(*arg), GFP_KERNEL);
+ if (!arg) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ ath10k_wmi_start_scan_init(ar, arg);
+ arg->vdev_id = arvif->vdev_id;
+ arg->scan_id = ATH10K_SCAN_ID;
+ arg->n_channels = 1;
+ arg->channels[0] = chan->center_freq;
+ arg->dwell_time_active = scan_time_msec;
+ arg->dwell_time_passive = scan_time_msec;
+ arg->max_scan_time = scan_time_msec;
+ arg->scan_ctrl_flags |= WMI_SCAN_FLAG_PASSIVE;
+ arg->scan_ctrl_flags |= WMI_SCAN_FILTER_PROBE_REQ;
+ arg->burst_duration_ms = duration;
+
+ ret = ath10k_start_scan(ar, arg);
if (ret) {
ath10k_warn(ar, "failed to start roc scan: %d\n", ret);
spin_lock_bh(&ar->data_lock);
@@ -7975,6 +7987,8 @@ static int ath10k_remain_on_channel(struct ieee80211_hw *hw,
ret = 0;
exit:
+ kfree(arg);
+
mutex_unlock(&ar->conf_mutex);
return ret;
}
@@ -8507,9 +8521,10 @@ exit:
static void ath10k_sta_rc_update(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ieee80211_link_sta *link_sta,
u32 changed)
{
+ struct ieee80211_sta *sta = link_sta->sta;
struct ath10k *ar = hw->priv;
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
struct ath10k_vif *arvif = (void *)vif->drv_priv;
@@ -9121,7 +9136,7 @@ static const struct ath10k_index_vht_data_rate_type supported_vht_mcs_rate_nss1[
{6, {2633, 2925}, {1215, 1350}, {585, 650} },
{7, {2925, 3250}, {1350, 1500}, {650, 722} },
{8, {3510, 3900}, {1620, 1800}, {780, 867} },
- {9, {3900, 4333}, {1800, 2000}, {780, 867} }
+ {9, {3900, 4333}, {1800, 2000}, {865, 960} }
};
/*MCS parameters with Nss = 2 */
@@ -9136,7 +9151,7 @@ static const struct ath10k_index_vht_data_rate_type supported_vht_mcs_rate_nss2[
{6, {5265, 5850}, {2430, 2700}, {1170, 1300} },
{7, {5850, 6500}, {2700, 3000}, {1300, 1444} },
{8, {7020, 7800}, {3240, 3600}, {1560, 1733} },
- {9, {7800, 8667}, {3600, 4000}, {1560, 1733} }
+ {9, {7800, 8667}, {3600, 4000}, {1730, 1920} }
};
static void ath10k_mac_get_rate_flags_ht(struct ath10k *ar, u32 rate, u8 nss, u8 mcs,
@@ -9450,7 +9465,7 @@ static const struct ieee80211_ops ath10k_ops = {
.reconfig_complete = ath10k_reconfig_complete,
.get_survey = ath10k_get_survey,
.set_bitrate_mask = ath10k_mac_op_set_bitrate_mask,
- .sta_rc_update = ath10k_sta_rc_update,
+ .link_sta_rc_update = ath10k_sta_rc_update,
.offset_tsf = ath10k_offset_tsf,
.ampdu_action = ath10k_ampdu_action,
.get_et_sset_count = ath10k_debug_get_et_sset_count,
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
index 08a6f36a6be9..6805357ee29e 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -3,7 +3,7 @@
* Copyright (c) 2004-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012,2017 Qualcomm Atheros, Inc.
* Copyright (c) 2016-2017 Erik Stromdahl <erik.stromdahl@gmail.com>
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/module.h>
@@ -2648,9 +2648,9 @@ static void ath10k_sdio_remove(struct sdio_func *func)
netif_napi_del(&ar->napi);
- ath10k_core_destroy(ar);
-
destroy_workqueue(ar_sdio->workqueue);
+
+ ath10k_core_destroy(ar);
}
static const struct sdio_device_id ath10k_sdio_devices[] = {
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index 0fe47d51013c..d436a874cd5a 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -1885,11 +1885,11 @@ static void ath10k_snoc_shutdown(struct platform_device *pdev)
}
static struct platform_driver ath10k_snoc_driver = {
- .probe = ath10k_snoc_probe,
- .remove_new = ath10k_snoc_remove,
+ .probe = ath10k_snoc_probe,
+ .remove = ath10k_snoc_remove,
.shutdown = ath10k_snoc_shutdown,
.driver = {
- .name = "ath10k_snoc",
+ .name = "ath10k_snoc",
.of_match_table = ath10k_snoc_dt_match,
},
};
diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c
index 97b12f51ef28..f2fc04596d48 100644
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -1000,18 +1000,18 @@ static int ath11k_ahb_fw_resources_init(struct ath11k_base *ab)
if (!ab->hw_params.fixed_fw_mem)
return 0;
- ret = ath11k_ahb_setup_msa_resources(ab);
- if (ret) {
- ath11k_err(ab, "failed to setup msa resources\n");
- return ret;
- }
-
node = of_get_child_by_name(host_dev->of_node, "wifi-firmware");
if (!node) {
ab_ahb->fw.use_tz = true;
return 0;
}
+ ret = ath11k_ahb_setup_msa_resources(ab);
+ if (ret) {
+ ath11k_err(ab, "failed to setup msa resources\n");
+ return ret;
+ }
+
info.fwnode = &node->fwnode;
info.parent = host_dev;
info.name = node->name;
@@ -1313,12 +1313,12 @@ free_resources:
}
static struct platform_driver ath11k_ahb_driver = {
- .driver = {
- .name = "ath11k",
+ .driver = {
+ .name = "ath11k",
.of_match_table = ath11k_ahb_of_match,
},
- .probe = ath11k_ahb_probe,
- .remove_new = ath11k_ahb_remove,
+ .probe = ath11k_ahb_probe,
+ .remove = ath11k_ahb_remove,
.shutdown = ath11k_ahb_shutdown,
};
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index ccf4ad35fdc3..be67382c00f6 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -616,7 +616,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
.supports_rssi_stats = true,
- .fw_wmi_diag_event = false,
+ .fw_wmi_diag_event = true,
.current_cc_support = true,
.dbr_debug_support = false,
.global_reset = false,
diff --git a/drivers/net/wireless/ath/ath11k/hal.c b/drivers/net/wireless/ath/ath11k/hal.c
index f02599bd1c36..61f4b6dd5380 100644
--- a/drivers/net/wireless/ath/ath11k/hal.c
+++ b/drivers/net/wireless/ath/ath11k/hal.c
@@ -1351,6 +1351,7 @@ void ath11k_hal_srng_deinit(struct ath11k_base *ab)
ath11k_hal_free_cont_rdp(ab);
ath11k_hal_free_cont_wrp(ab);
kfree(hal->srng_config);
+ hal->srng_config = NULL;
}
EXPORT_SYMBOL(ath11k_hal_srng_deinit);
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index f8068d2e848c..e6acbff06749 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -5079,9 +5079,10 @@ static void ath11k_mac_op_sta_set_4addr(struct ieee80211_hw *hw,
static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ieee80211_link_sta *link_sta,
u32 changed)
{
+ struct ieee80211_sta *sta = link_sta->sta;
struct ath11k *ar = hw->priv;
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
@@ -9708,7 +9709,7 @@ static const struct ieee80211_ops ath11k_ops = {
.sta_state = ath11k_mac_op_sta_state,
.sta_set_4addr = ath11k_mac_op_sta_set_4addr,
.sta_set_txpwr = ath11k_mac_op_sta_set_txpwr,
- .sta_rc_update = ath11k_mac_op_sta_rc_update,
+ .link_sta_rc_update = ath11k_mac_op_sta_rc_update,
.conf_tx = ath11k_mac_op_conf_tx,
.set_antenna = ath11k_mac_op_set_antenna,
.get_antenna = ath11k_mac_op_get_antenna,
diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c
index f477afd325de..7a22483b35cd 100644
--- a/drivers/net/wireless/ath/ath11k/qmi.c
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
@@ -2180,6 +2180,9 @@ static int ath11k_qmi_request_device_info(struct ath11k_base *ab)
ab->mem = bar_addr_va;
ab->mem_len = resp.bar_size;
+ if (!ab->hw_params.ce_remap)
+ ab->mem_ce = ab->mem;
+
return 0;
out:
return ret;
diff --git a/drivers/net/wireless/ath/ath11k/wow.c b/drivers/net/wireless/ath/ath11k/wow.c
index 99d8ba45a75b..827085a926b2 100644
--- a/drivers/net/wireless/ath/ath11k/wow.c
+++ b/drivers/net/wireless/ath/ath11k/wow.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/delay.h>
@@ -155,6 +155,7 @@ static void ath11k_wow_convert_8023_to_80211(struct cfg80211_pkt_pattern *new,
u8 hdr_8023_bit_mask[ETH_HLEN] = {};
u8 hdr_80211_pattern[WOW_HDR_LEN] = {};
u8 hdr_80211_bit_mask[WOW_HDR_LEN] = {};
+ u8 bytemask[WOW_MAX_PATTERN_SIZE] = {};
int total_len = old->pkt_offset + old->pattern_len;
int hdr_80211_end_offset;
@@ -172,11 +173,17 @@ static void ath11k_wow_convert_8023_to_80211(struct cfg80211_pkt_pattern *new,
struct rfc1042_hdr *new_rfc_mask =
(struct rfc1042_hdr *)(hdr_80211_bit_mask + hdr_len);
int rfc_len = sizeof(*new_rfc_pattern);
+ int i;
+
+ /* convert bitmask to bytemask */
+ for (i = 0; i < old->pattern_len; i++)
+ if (old->mask[i / 8] & BIT(i % 8))
+ bytemask[i] = 0xff;
memcpy(hdr_8023_pattern + old->pkt_offset,
old->pattern, ETH_HLEN - old->pkt_offset);
memcpy(hdr_8023_bit_mask + old->pkt_offset,
- old->mask, ETH_HLEN - old->pkt_offset);
+ bytemask, ETH_HLEN - old->pkt_offset);
/* Copy destination address */
memcpy(new_hdr_pattern->addr1, old_hdr_pattern->h_dest, ETH_ALEN);
@@ -232,7 +239,7 @@ static void ath11k_wow_convert_8023_to_80211(struct cfg80211_pkt_pattern *new,
(void *)old->pattern + ETH_HLEN - old->pkt_offset,
total_len - ETH_HLEN);
memcpy((u8 *)new->mask + new->pattern_len,
- (void *)old->mask + ETH_HLEN - old->pkt_offset,
+ bytemask + ETH_HLEN - old->pkt_offset,
total_len - ETH_HLEN);
new->pattern_len += total_len - ETH_HLEN;
@@ -393,35 +400,31 @@ static int ath11k_vif_wow_set_wakeups(struct ath11k_vif *arvif,
}
for (i = 0; i < wowlan->n_patterns; i++) {
- u8 bitmask[WOW_MAX_PATTERN_SIZE] = {};
u8 ath_pattern[WOW_MAX_PATTERN_SIZE] = {};
u8 ath_bitmask[WOW_MAX_PATTERN_SIZE] = {};
struct cfg80211_pkt_pattern new_pattern = {};
- struct cfg80211_pkt_pattern old_pattern = patterns[i];
- int j;
new_pattern.pattern = ath_pattern;
new_pattern.mask = ath_bitmask;
if (patterns[i].pattern_len > WOW_MAX_PATTERN_SIZE)
continue;
- /* convert bytemask to bitmask */
- for (j = 0; j < patterns[i].pattern_len; j++)
- if (patterns[i].mask[j / 8] & BIT(j % 8))
- bitmask[j] = 0xff;
- old_pattern.mask = bitmask;
if (ar->wmi->wmi_ab->wlan_resource_config.rx_decap_mode ==
ATH11K_HW_TXRX_NATIVE_WIFI) {
if (patterns[i].pkt_offset < ETH_HLEN) {
- u8 pattern_ext[WOW_MAX_PATTERN_SIZE] = {};
-
- memcpy(pattern_ext, old_pattern.pattern,
- old_pattern.pattern_len);
- old_pattern.pattern = pattern_ext;
ath11k_wow_convert_8023_to_80211(&new_pattern,
- &old_pattern);
+ &patterns[i]);
} else {
- new_pattern = old_pattern;
+ int j;
+
+ new_pattern = patterns[i];
+ new_pattern.mask = ath_bitmask;
+
+ /* convert bitmask to bytemask */
+ for (j = 0; j < patterns[i].pattern_len; j++)
+ if (patterns[i].mask[j / 8] & BIT(j % 8))
+ ath_bitmask[j] = 0xff;
+
new_pattern.pkt_offset += WOW_HDR_LEN - ETH_HLEN;
}
}
diff --git a/drivers/net/wireless/ath/ath12k/Kconfig b/drivers/net/wireless/ath/ath12k/Kconfig
index f64e7c322216..52a1bb19e3da 100644
--- a/drivers/net/wireless/ath/ath12k/Kconfig
+++ b/drivers/net/wireless/ath/ath12k/Kconfig
@@ -42,3 +42,13 @@ config ATH12K_TRACING
If unsure, say Y to make it easier to debug problems. But if
you want optimal performance choose N.
+
+config ATH12K_COREDUMP
+ bool "ath12k coredump"
+ depends on ATH12K
+ select WANT_DEV_COREDUMP
+ help
+ Enable ath12k coredump collection
+
+ If unsure, say Y to make it easier to debug problems. But if
+ dump collection not required choose N.
diff --git a/drivers/net/wireless/ath/ath12k/Makefile b/drivers/net/wireless/ath/ath12k/Makefile
index 5a1ed20d730e..b5bb3e2599cd 100644
--- a/drivers/net/wireless/ath/ath12k/Makefile
+++ b/drivers/net/wireless/ath/ath12k/Makefile
@@ -27,6 +27,7 @@ ath12k-$(CONFIG_ATH12K_DEBUGFS) += debugfs.o debugfs_htt_stats.o
ath12k-$(CONFIG_ACPI) += acpi.o
ath12k-$(CONFIG_ATH12K_TRACING) += trace.o
ath12k-$(CONFIG_PM) += wow.o
+ath12k-$(CONFIG_ATH12K_COREDUMP) += coredump.o
# for tracing framework to find trace.h
CFLAGS_trace.o := -I$(src)
diff --git a/drivers/net/wireless/ath/ath12k/ce.h b/drivers/net/wireless/ath/ath12k/ce.h
index 857bc5f9e946..1a14b9fb86b8 100644
--- a/drivers/net/wireless/ath/ath12k/ce.h
+++ b/drivers/net/wireless/ath/ath12k/ce.h
@@ -148,7 +148,7 @@ struct ath12k_ce_pipe {
void (*send_cb)(struct ath12k_ce_pipe *pipe);
void (*recv_cb)(struct ath12k_base *ab, struct sk_buff *skb);
- struct tasklet_struct intr_tq;
+ struct work_struct intr_wq;
struct ath12k_ce_ring *src_ring;
struct ath12k_ce_ring *dest_ring;
struct ath12k_ce_ring *status_ring;
diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
index 51252e8bc1ae..c57322221e1d 100644
--- a/drivers/net/wireless/ath/ath12k/core.c
+++ b/drivers/net/wireless/ath/ath12k/core.c
@@ -1004,7 +1004,7 @@ void ath12k_core_halt(struct ath12k *ar)
{
struct ath12k_base *ab = ar->ab;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
ar->num_created_vdevs = 0;
ar->allocated_vdev_map = 0;
@@ -1078,6 +1078,7 @@ static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
if (!ah || ah->state == ATH12K_HW_STATE_OFF)
continue;
+ wiphy_lock(ah->hw->wiphy);
mutex_lock(&ah->hw_mutex);
switch (ah->state) {
@@ -1086,10 +1087,7 @@ static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
for (j = 0; j < ah->num_radio; j++) {
ar = &ah->radio[j];
-
- mutex_lock(&ar->conf_mutex);
ath12k_core_halt(ar);
- mutex_unlock(&ar->conf_mutex);
}
break;
@@ -1110,6 +1108,7 @@ static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
}
mutex_unlock(&ah->hw_mutex);
+ wiphy_unlock(ah->hw->wiphy);
}
complete(&ab->driver_recovery);
@@ -1188,6 +1187,7 @@ static void ath12k_core_reset(struct work_struct *work)
ab->is_reset = true;
atomic_set(&ab->recovery_count, 0);
+ ath12k_coredump_collect(ab);
ath12k_core_pre_reconfigure_recovery(ab);
ath12k_core_post_reconfigure_recovery(ab);
@@ -1312,6 +1312,7 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
INIT_WORK(&ab->restart_work, ath12k_core_restart);
INIT_WORK(&ab->reset_work, ath12k_core_reset);
INIT_WORK(&ab->rfkill_work, ath12k_rfkill_work);
+ INIT_WORK(&ab->dump_work, ath12k_coredump_upload);
timer_setup(&ab->rx_replenish_retry, ath12k_ce_rx_replenish_retry, 0);
init_completion(&ab->htc_suspend);
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index 7f2e9a9b4097..3bf31ee5b9fa 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -30,6 +30,7 @@
#include "acpi.h"
#include "wow.h"
#include "debugfs_htt_stats.h"
+#include "coredump.h"
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@@ -94,6 +95,14 @@ static inline enum wme_ac ath12k_tid_to_ac(u32 tid)
WME_AC_VO);
}
+static inline u64 ath12k_le32hilo_to_u64(__le32 hi, __le32 lo)
+{
+ u64 hi64 = le32_to_cpu(hi);
+ u64 lo64 = le32_to_cpu(lo);
+
+ return (hi64 << 32) | lo64;
+}
+
enum ath12k_skb_flags {
ATH12K_SKB_HW_80211_ENCAP = BIT(0),
ATH12K_SKB_CIPHER_SET = BIT(1),
@@ -220,8 +229,9 @@ struct ath12k_tx_conf {
};
struct ath12k_key_conf {
- bool changed;
enum set_key_cmd cmd;
+ struct list_head list;
+ struct ieee80211_sta *sta;
struct ieee80211_key_conf *key;
};
@@ -238,10 +248,8 @@ struct ath12k_rekey_data {
bool enable_offload;
};
-struct ath12k_vif {
+struct ath12k_link_vif {
u32 vdev_id;
- enum wmi_vdev_type vdev_type;
- enum wmi_vdev_subtype vdev_subtype;
u32 beacon_interval;
u32 dtim_period;
u16 ast_hash;
@@ -251,13 +259,38 @@ struct ath12k_vif {
u8 search_type;
struct ath12k *ar;
- struct ieee80211_vif *vif;
int bank_id;
u8 vdev_id_check_en;
struct wmi_wmm_params_all_arg wmm_params;
struct list_head list;
+
+ bool is_created;
+ bool is_started;
+ bool is_up;
+ u8 bssid[ETH_ALEN];
+ struct cfg80211_bitrate_mask bitrate_mask;
+ struct delayed_work connection_loss_work;
+ int num_legacy_stations;
+ int rtscts_prot_mode;
+ int txpower;
+ bool rsnie_present;
+ bool wpaie_present;
+ struct ieee80211_chanctx_conf chanctx;
+ u8 vdev_stats_id;
+ u32 punct_bitmap;
+ u8 link_id;
+ struct ath12k_vif *ahvif;
+ struct ath12k_rekey_data rekey_data;
+};
+
+struct ath12k_vif {
+ enum wmi_vdev_type vdev_type;
+ enum wmi_vdev_subtype vdev_subtype;
+ struct ieee80211_vif *vif;
+ struct ath12k_hw *ah;
+
union {
struct {
u32 uapsd;
@@ -275,25 +308,16 @@ struct ath12k_vif {
} ap;
} u;
- bool is_created;
- bool is_started;
- bool is_up;
u32 aid;
- u8 bssid[ETH_ALEN];
- struct cfg80211_bitrate_mask bitrate_mask;
- struct delayed_work connection_loss_work;
- int num_legacy_stations;
- int rtscts_prot_mode;
- int txpower;
- bool rsnie_present;
- bool wpaie_present;
u32 key_cipher;
u8 tx_encap_type;
- u8 vdev_stats_id;
- u32 punct_bitmap;
bool ps;
- struct ath12k_vif_cache *cache;
- struct ath12k_rekey_data rekey_data;
+
+ struct ath12k_link_vif deflink;
+ struct ath12k_link_vif __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
+ struct ath12k_vif_cache *cache[IEEE80211_MLD_MAX_NUM_LINKS];
+ /* indicates bitmap of link vif created in FW */
+ u16 links_map;
/* Must be last - ends in a flexible-array member.
*
@@ -306,7 +330,7 @@ struct ath12k_vif {
struct ath12k_vif_iter {
u32 vdev_id;
struct ath12k *ar;
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
};
#define HAL_AST_IDX_INVALID 0xFFFF
@@ -441,27 +465,36 @@ struct ath12k_wbm_tx_stats {
u64 wbm_tx_comp_stats[HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX];
};
-struct ath12k_sta {
- struct ath12k_vif *arvif;
+struct ath12k_link_sta {
+ struct ath12k_link_vif *arvif;
+ struct ath12k_sta *ahsta;
/* the following are protected by ar->data_lock */
u32 changed; /* IEEE80211_RC_* */
u32 bw;
u32 nss;
u32 smps;
- enum hal_pn_type pn_type;
- struct work_struct update_wk;
+ struct wiphy_work update_wk;
struct rate_info txrate;
struct rate_info last_txrate;
u64 rx_duration;
u64 tx_duration;
u8 rssi_comb;
+ u8 link_id;
struct ath12k_rx_peer_stats *rx_stats;
struct ath12k_wbm_tx_stats *wbm_tx_stats;
u32 bw_prev;
};
+struct ath12k_sta {
+ enum hal_pn_type pn_type;
+ struct ath12k_link_sta deflink;
+ struct ath12k_link_sta __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
+ /* indicates bitmap of link sta created in FW */
+ u16 links_map;
+};
+
#define ATH12K_MIN_5G_FREQ 4150
#define ATH12K_MIN_6G_FREQ 5925
#define ATH12K_MAX_6G_FREQ 7115
@@ -561,13 +594,9 @@ struct ath12k {
u32 chan_tx_pwr;
u32 num_stations;
u32 max_num_stations;
- bool monitor_present;
- /* To synchronize concurrent synchronous mac80211 callback operations,
- * concurrent debugfs configuration and concurrent FW statistics events.
- */
- struct mutex conf_mutex;
+
/* protects the radio specific data like debug stats, ppdu_stats_info stats,
- * vdev_stop_status info, scan data, ath12k_sta info, ath12k_vif info,
+ * vdev_stop_status info, scan data, ath12k_sta info, ath12k_link_vif info,
* channel context data, survey info, test mode data.
*/
spinlock_t data_lock;
@@ -666,6 +695,7 @@ struct ath12k_hw {
enum ath12k_hw_state state;
bool regd_updated;
bool use_6ghz_regd;
+
u8 num_radio;
/* Keep last */
@@ -782,6 +812,10 @@ struct ath12k_base {
/* HW channel counters frequency value in hertz common to all MACs */
u32 cc_freq_hz;
+ struct ath12k_dump_file_data *dump_data;
+ size_t ath12k_coredump_len;
+ struct work_struct dump_work;
+
struct ath12k_htc htc;
struct ath12k_dp dp;
@@ -1024,16 +1058,26 @@ static inline struct ath12k_skb_rxcb *ATH12K_SKB_RXCB(struct sk_buff *skb)
return (struct ath12k_skb_rxcb *)skb->cb;
}
-static inline struct ath12k_vif *ath12k_vif_to_arvif(struct ieee80211_vif *vif)
+static inline struct ath12k_vif *ath12k_vif_to_ahvif(struct ieee80211_vif *vif)
{
return (struct ath12k_vif *)vif->drv_priv;
}
-static inline struct ath12k_sta *ath12k_sta_to_arsta(struct ieee80211_sta *sta)
+static inline struct ath12k_sta *ath12k_sta_to_ahsta(struct ieee80211_sta *sta)
{
return (struct ath12k_sta *)sta->drv_priv;
}
+static inline struct ieee80211_sta *ath12k_ahsta_to_sta(struct ath12k_sta *ahsta)
+{
+ return container_of((void *)ahsta, struct ieee80211_sta, drv_priv);
+}
+
+static inline struct ieee80211_vif *ath12k_ahvif_to_vif(struct ath12k_vif *ahvif)
+{
+ return container_of((void *)ahvif, struct ieee80211_vif, drv_priv);
+}
+
static inline struct ath12k *ath12k_ab_to_ar(struct ath12k_base *ab,
int mac_id)
{
diff --git a/drivers/net/wireless/ath/ath12k/coredump.c b/drivers/net/wireless/ath/ath12k/coredump.c
new file mode 100644
index 000000000000..72d675d15e64
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/coredump.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+#include <linux/devcoredump.h>
+#include "hif.h"
+#include "coredump.h"
+#include "debug.h"
+
+enum
+ath12k_fw_crash_dump_type ath12k_coredump_get_dump_type(enum ath12k_qmi_target_mem type)
+{
+ enum ath12k_fw_crash_dump_type dump_type;
+
+ switch (type) {
+ case HOST_DDR_REGION_TYPE:
+ dump_type = FW_CRASH_DUMP_REMOTE_MEM_DATA;
+ break;
+ case M3_DUMP_REGION_TYPE:
+ dump_type = FW_CRASH_DUMP_M3_DUMP;
+ break;
+ case PAGEABLE_MEM_REGION_TYPE:
+ dump_type = FW_CRASH_DUMP_PAGEABLE_DATA;
+ break;
+ case BDF_MEM_REGION_TYPE:
+ case CALDB_MEM_REGION_TYPE:
+ dump_type = FW_CRASH_DUMP_NONE;
+ break;
+ default:
+ dump_type = FW_CRASH_DUMP_TYPE_MAX;
+ break;
+ }
+
+ return dump_type;
+}
+
+void ath12k_coredump_upload(struct work_struct *work)
+{
+ struct ath12k_base *ab = container_of(work, struct ath12k_base, dump_work);
+
+ ath12k_info(ab, "Uploading coredump\n");
+ /* dev_coredumpv() takes ownership of the buffer */
+ dev_coredumpv(ab->dev, ab->dump_data, ab->ath12k_coredump_len, GFP_KERNEL);
+ ab->dump_data = NULL;
+}
+
+void ath12k_coredump_collect(struct ath12k_base *ab)
+{
+ ath12k_hif_coredump_download(ab);
+}
diff --git a/drivers/net/wireless/ath/ath12k/coredump.h b/drivers/net/wireless/ath/ath12k/coredump.h
new file mode 100644
index 000000000000..5d6003b1c12d
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/coredump.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+#ifndef _ATH12K_COREDUMP_H_
+#define _ATH12K_COREDUMP_H_
+
+#define ATH12K_FW_CRASH_DUMP_V2 2
+
+enum ath12k_fw_crash_dump_type {
+ FW_CRASH_DUMP_PAGING_DATA,
+ FW_CRASH_DUMP_RDDM_DATA,
+ FW_CRASH_DUMP_REMOTE_MEM_DATA,
+ FW_CRASH_DUMP_PAGEABLE_DATA,
+ FW_CRASH_DUMP_M3_DUMP,
+ FW_CRASH_DUMP_NONE,
+
+ /* keep last */
+ FW_CRASH_DUMP_TYPE_MAX,
+};
+
+#define COREDUMP_TLV_HDR_SIZE 8
+
+struct ath12k_tlv_dump_data {
+ /* see ath11k_fw_crash_dump_type above */
+ __le32 type;
+
+ /* in bytes */
+ __le32 tlv_len;
+
+ /* pad to 32-bit boundaries as needed */
+ u8 tlv_data[];
+} __packed;
+
+struct ath12k_dump_file_data {
+ /* "ATH12K-FW-DUMP" */
+ char df_magic[16];
+ /* total dump len in bytes */
+ __le32 len;
+ /* file dump version */
+ __le32 version;
+ /* pci device id */
+ __le32 chip_id;
+ /* qrtr instance id */
+ __le32 qrtr_id;
+ /* pci domain id */
+ __le32 bus_id;
+ guid_t guid;
+ /* time-of-day stamp */
+ __le64 tv_sec;
+ /* time-of-day stamp, nano-seconds */
+ __le64 tv_nsec;
+ /* room for growth w/out changing binary format */
+ u8 unused[128];
+ u8 data[];
+} __packed;
+
+#ifdef CONFIG_ATH12K_COREDUMP
+enum ath12k_fw_crash_dump_type ath12k_coredump_get_dump_type
+ (enum ath12k_qmi_target_mem type);
+void ath12k_coredump_upload(struct work_struct *work);
+void ath12k_coredump_collect(struct ath12k_base *ab);
+#else
+static inline enum ath12k_fw_crash_dump_type ath12k_coredump_get_dump_type
+ (enum ath12k_qmi_target_mem type)
+{
+ return FW_CRASH_DUMP_TYPE_MAX;
+}
+
+static inline void ath12k_coredump_upload(struct work_struct *work)
+{
+}
+
+static inline void ath12k_coredump_collect(struct ath12k_base *ab)
+{
+}
+#endif
+
+#endif
diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c
index 2a977c36af00..d4b32d1a431c 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs.c
+++ b/drivers/net/wireless/ath/ath12k/debugfs.c
@@ -15,14 +15,14 @@ static ssize_t ath12k_write_simulate_radar(struct file *file,
struct ath12k *ar = file->private_data;
int ret;
- mutex_lock(&ar->conf_mutex);
+ wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
ret = ath12k_wmi_simulate_radar(ar);
if (ret)
goto exit;
ret = count;
exit:
- mutex_unlock(&ar->conf_mutex);
+ wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return ret;
}
diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c
index f1b7e74aefe4..c9980c0193d1 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c
+++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c
@@ -12,8 +12,8 @@
#include "dp_rx.h"
static u32
-print_array_to_buf(u8 *buf, u32 offset, const char *header,
- const __le32 *array, u32 array_len, const char *footer)
+print_array_to_buf_index(u8 *buf, u32 offset, const char *header, u32 stats_index,
+ const __le32 *array, u32 array_len, const char *footer)
{
int index = 0;
u8 i;
@@ -26,7 +26,7 @@ print_array_to_buf(u8 *buf, u32 offset, const char *header,
for (i = 0; i < array_len; i++) {
index += scnprintf(buf + offset + index,
(ATH12K_HTT_STATS_BUF_SIZE - offset) - index,
- " %u:%u,", i, le32_to_cpu(array[i]));
+ " %u:%u,", stats_index++, le32_to_cpu(array[i]));
}
/* To overwrite the last trailing comma */
index--;
@@ -40,6 +40,54 @@ print_array_to_buf(u8 *buf, u32 offset, const char *header,
return index;
}
+static u32
+print_array_to_buf(u8 *buf, u32 offset, const char *header,
+ const __le32 *array, u32 array_len, const char *footer)
+{
+ return print_array_to_buf_index(buf, offset, header, 0, array, array_len,
+ footer);
+}
+
+static const char *ath12k_htt_be_tx_rx_ru_size_to_str(u8 ru_size)
+{
+ switch (ru_size) {
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_26:
+ return "26";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_52:
+ return "52";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_52_26:
+ return "52+26";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_106:
+ return "106";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_106_26:
+ return "106+26";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_242:
+ return "242";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_484:
+ return "484";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_484_242:
+ return "484+242";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996:
+ return "996";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996_484:
+ return "996+484";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996_484_242:
+ return "996+484+242";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996x2:
+ return "996x2";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996x2_484:
+ return "996x2+484";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996x3:
+ return "996x3";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996x3_484:
+ return "996x3+484";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996x4:
+ return "996x4";
+ default:
+ return "unknown";
+ }
+}
+
static void
htt_print_tx_pdev_stats_cmn_tlv(const void *tag_buf, u16 tag_len,
struct debug_htt_stats_req *stats_req)
@@ -1447,6 +1495,1207 @@ ath12k_htt_print_tx_de_compl_stats_tlv(const void *tag_buf, u16 tag_len,
stats_req->buf_len = len;
}
+static void
+ath12k_htt_print_tx_selfgen_cmn_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_selfgen_cmn_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u32 mac_id_word;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ mac_id_word = __le32_to_cpu(htt_stats_buf->mac_id__word);
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_CMN_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n",
+ u32_get_bits(mac_id_word, ATH12K_HTT_STATS_MAC_ID));
+ len += scnprintf(buf + len, buf_len - len, "su_bar = %u\n",
+ le32_to_cpu(htt_stats_buf->su_bar));
+ len += scnprintf(buf + len, buf_len - len, "rts = %u\n",
+ le32_to_cpu(htt_stats_buf->rts));
+ len += scnprintf(buf + len, buf_len - len, "cts2self = %u\n",
+ le32_to_cpu(htt_stats_buf->cts2self));
+ len += scnprintf(buf + len, buf_len - len, "qos_null = %u\n",
+ le32_to_cpu(htt_stats_buf->qos_null));
+ len += scnprintf(buf + len, buf_len - len, "delayed_bar_1 = %u\n",
+ le32_to_cpu(htt_stats_buf->delayed_bar_1));
+ len += scnprintf(buf + len, buf_len - len, "delayed_bar_2 = %u\n",
+ le32_to_cpu(htt_stats_buf->delayed_bar_2));
+ len += scnprintf(buf + len, buf_len - len, "delayed_bar_3 = %u\n",
+ le32_to_cpu(htt_stats_buf->delayed_bar_3));
+ len += scnprintf(buf + len, buf_len - len, "delayed_bar_4 = %u\n",
+ le32_to_cpu(htt_stats_buf->delayed_bar_4));
+ len += scnprintf(buf + len, buf_len - len, "delayed_bar_5 = %u\n",
+ le32_to_cpu(htt_stats_buf->delayed_bar_5));
+ len += scnprintf(buf + len, buf_len - len, "delayed_bar_6 = %u\n",
+ le32_to_cpu(htt_stats_buf->delayed_bar_6));
+ len += scnprintf(buf + len, buf_len - len, "delayed_bar_7 = %u\n\n",
+ le32_to_cpu(htt_stats_buf->delayed_bar_7));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_selfgen_ac_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_selfgen_ac_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_AC_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "ac_su_ndpa_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->ac_su_ndpa));
+ len += scnprintf(buf + len, buf_len - len, "ac_su_ndp_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->ac_su_ndp));
+ len += scnprintf(buf + len, buf_len - len, "ac_mu_mimo_ndpa_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->ac_mu_mimo_ndpa));
+ len += scnprintf(buf + len, buf_len - len, "ac_mu_mimo_ndp_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->ac_mu_mimo_ndp));
+ len += print_array_to_buf_index(buf, len, "ac_mu_mimo_brpollX_tried = ", 1,
+ htt_stats_buf->ac_mu_mimo_brpoll,
+ ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS, "\n\n");
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_selfgen_ax_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_selfgen_ax_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_AX_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "ax_su_ndpa_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_su_ndpa));
+ len += scnprintf(buf + len, buf_len - len, "ax_su_ndp_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_su_ndp));
+ len += scnprintf(buf + len, buf_len - len, "ax_mu_mimo_ndpa_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_mu_mimo_ndpa));
+ len += scnprintf(buf + len, buf_len - len, "ax_mu_mimo_ndp_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_mu_mimo_ndp));
+ len += print_array_to_buf_index(buf, len, "ax_mu_mimo_brpollX_tried = ", 1,
+ htt_stats_buf->ax_mu_mimo_brpoll,
+ ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS, "\n");
+ len += scnprintf(buf + len, buf_len - len, "ax_basic_trigger = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_basic_trigger));
+ len += scnprintf(buf + len, buf_len - len, "ax_ulmumimo_total_trigger = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_ulmumimo_trigger));
+ len += scnprintf(buf + len, buf_len - len, "ax_bsr_trigger = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_bsr_trigger));
+ len += scnprintf(buf + len, buf_len - len, "ax_mu_bar_trigger = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_mu_bar_trigger));
+ len += scnprintf(buf + len, buf_len - len, "ax_mu_rts_trigger = %u\n\n",
+ le32_to_cpu(htt_stats_buf->ax_mu_rts_trigger));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_selfgen_be_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_selfgen_be_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_BE_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "be_su_ndpa_queued = %u\n",
+ le32_to_cpu(htt_stats_buf->be_su_ndpa_queued));
+ len += scnprintf(buf + len, buf_len - len, "be_su_ndpa_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->be_su_ndpa));
+ len += scnprintf(buf + len, buf_len - len, "be_su_ndp_queued = %u\n",
+ le32_to_cpu(htt_stats_buf->be_su_ndp_queued));
+ len += scnprintf(buf + len, buf_len - len, "be_su_ndp_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->be_su_ndp));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_mimo_ndpa_queued = %u\n",
+ le32_to_cpu(htt_stats_buf->be_mu_mimo_ndpa_queued));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_mimo_ndpa_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->be_mu_mimo_ndpa));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_mimo_ndp_queued = %u\n",
+ le32_to_cpu(htt_stats_buf->be_mu_mimo_ndp_queued));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_mimo_ndp_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->be_mu_mimo_ndp));
+ len += print_array_to_buf_index(buf, len, "be_mu_mimo_brpollX_queued = ", 1,
+ htt_stats_buf->be_mu_mimo_brpoll_queued,
+ ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS - 1,
+ "\n");
+ len += print_array_to_buf_index(buf, len, "be_mu_mimo_brpollX_tried = ", 1,
+ htt_stats_buf->be_mu_mimo_brpoll,
+ ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS - 1,
+ "\n");
+ len += print_array_to_buf(buf, len, "be_ul_mumimo_trigger = ",
+ htt_stats_buf->be_ul_mumimo_trigger,
+ ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS, "\n");
+ len += scnprintf(buf + len, buf_len - len, "be_basic_trigger = %u\n",
+ le32_to_cpu(htt_stats_buf->be_basic_trigger));
+ len += scnprintf(buf + len, buf_len - len, "be_ulmumimo_total_trigger = %u\n",
+ le32_to_cpu(htt_stats_buf->be_ulmumimo_trigger));
+ len += scnprintf(buf + len, buf_len - len, "be_bsr_trigger = %u\n",
+ le32_to_cpu(htt_stats_buf->be_bsr_trigger));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_bar_trigger = %u\n",
+ le32_to_cpu(htt_stats_buf->be_mu_bar_trigger));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_rts_trigger = %u\n\n",
+ le32_to_cpu(htt_stats_buf->be_mu_rts_trigger));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_selfgen_ac_err_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_selfgen_ac_err_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_AC_ERR_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "ac_su_ndp_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ac_su_ndp_err));
+ len += scnprintf(buf + len, buf_len - len, "ac_su_ndpa_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ac_su_ndpa_err));
+ len += scnprintf(buf + len, buf_len - len, "ac_mu_mimo_ndpa_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ac_mu_mimo_ndpa_err));
+ len += scnprintf(buf + len, buf_len - len, "ac_mu_mimo_ndp_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ac_mu_mimo_ndp_err));
+ len += scnprintf(buf + len, buf_len - len, "ac_mu_mimo_brp1_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ac_mu_mimo_brp1_err));
+ len += scnprintf(buf + len, buf_len - len, "ac_mu_mimo_brp2_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ac_mu_mimo_brp2_err));
+ len += scnprintf(buf + len, buf_len - len, "ac_mu_mimo_brp3_err = %u\n\n",
+ le32_to_cpu(htt_stats_buf->ac_mu_mimo_brp3_err));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_selfgen_ax_err_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_selfgen_ax_err_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_AX_ERR_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "ax_su_ndp_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_su_ndp_err));
+ len += scnprintf(buf + len, buf_len - len, "ax_su_ndpa_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_su_ndpa_err));
+ len += scnprintf(buf + len, buf_len - len, "ax_mu_mimo_ndpa_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_mu_mimo_ndpa_err));
+ len += scnprintf(buf + len, buf_len - len, "ax_mu_mimo_ndp_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_mu_mimo_ndp_err));
+ len += print_array_to_buf_index(buf, len, "ax_mu_mimo_brpX_err", 1,
+ htt_stats_buf->ax_mu_mimo_brp_err,
+ ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS - 1,
+ "\n");
+ len += scnprintf(buf + len, buf_len - len, "ax_basic_trigger_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_basic_trigger_err));
+ len += scnprintf(buf + len, buf_len - len, "ax_ulmumimo_total_trigger_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_ulmumimo_trigger_err));
+ len += scnprintf(buf + len, buf_len - len, "ax_bsr_trigger_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_bsr_trigger_err));
+ len += scnprintf(buf + len, buf_len - len, "ax_mu_bar_trigger_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_mu_bar_trigger_err));
+ len += scnprintf(buf + len, buf_len - len, "ax_mu_rts_trigger_err = %u\n\n",
+ le32_to_cpu(htt_stats_buf->ax_mu_rts_trigger_err));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_selfgen_be_err_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_selfgen_be_err_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_BE_ERR_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "be_su_ndp_err = %u\n",
+ le32_to_cpu(htt_stats_buf->be_su_ndp_err));
+ len += scnprintf(buf + len, buf_len - len, "be_su_ndp_flushed = %u\n",
+ le32_to_cpu(htt_stats_buf->be_su_ndp_flushed));
+ len += scnprintf(buf + len, buf_len - len, "be_su_ndpa_err = %u\n",
+ le32_to_cpu(htt_stats_buf->be_su_ndpa_err));
+ len += scnprintf(buf + len, buf_len - len, "be_su_ndpa_flushed = %u\n",
+ le32_to_cpu(htt_stats_buf->be_su_ndpa_flushed));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_mimo_ndpa_err = %u\n",
+ le32_to_cpu(htt_stats_buf->be_mu_mimo_ndpa_err));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_mimo_ndpa_flushed = %u\n",
+ le32_to_cpu(htt_stats_buf->be_mu_mimo_ndpa_flushed));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_mimo_ndp_err = %u\n",
+ le32_to_cpu(htt_stats_buf->be_mu_mimo_ndp_err));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_mimo_ndp_flushed = %u\n",
+ le32_to_cpu(htt_stats_buf->be_mu_mimo_ndp_flushed));
+ len += print_array_to_buf_index(buf, len, "be_mu_mimo_brpX_err", 1,
+ htt_stats_buf->be_mu_mimo_brp_err,
+ ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS - 1,
+ "\n");
+ len += print_array_to_buf_index(buf, len, "be_mu_mimo_brpollX_flushed", 1,
+ htt_stats_buf->be_mu_mimo_brpoll_flushed,
+ ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS - 1,
+ "\n");
+ len += print_array_to_buf(buf, len, "be_mu_mimo_num_cbf_rcvd_on_brp_err",
+ htt_stats_buf->be_mu_mimo_brp_err_num_cbf_rxd,
+ ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS, "\n");
+ len += print_array_to_buf(buf, len, "be_ul_mumimo_trigger_err",
+ htt_stats_buf->be_ul_mumimo_trigger_err,
+ ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS, "\n");
+ len += scnprintf(buf + len, buf_len - len, "be_basic_trigger_err = %u\n",
+ le32_to_cpu(htt_stats_buf->be_basic_trigger_err));
+ len += scnprintf(buf + len, buf_len - len, "be_ulmumimo_total_trig_err = %u\n",
+ le32_to_cpu(htt_stats_buf->be_ulmumimo_trigger_err));
+ len += scnprintf(buf + len, buf_len - len, "be_bsr_trigger_err = %u\n",
+ le32_to_cpu(htt_stats_buf->be_bsr_trigger_err));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_bar_trigger_err = %u\n",
+ le32_to_cpu(htt_stats_buf->be_mu_bar_trigger_err));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_rts_trigger_err = %u\n\n",
+ le32_to_cpu(htt_stats_buf->be_mu_rts_trigger_err));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_selfgen_ac_sched_status_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats)
+{
+ const struct ath12k_htt_tx_selfgen_ac_sched_status_stats_tlv *htt_stats_buf =
+ tag_buf;
+ u8 *buf = stats->buf;
+ u32 len = stats->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len,
+ "HTT_TX_SELFGEN_AC_SCHED_STATUS_STATS_TLV:\n");
+ len += print_array_to_buf(buf, len, "ac_su_ndpa_sch_status",
+ htt_stats_buf->ac_su_ndpa_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ac_su_ndp_sch_status",
+ htt_stats_buf->ac_su_ndp_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ac_mu_mimo_ndpa_sch_status",
+ htt_stats_buf->ac_mu_mimo_ndpa_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ac_mu_mimo_ndp_sch_status",
+ htt_stats_buf->ac_mu_mimo_ndp_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ac_mu_mimo_brp_sch_status",
+ htt_stats_buf->ac_mu_mimo_brp_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ac_su_ndp_sch_flag_err",
+ htt_stats_buf->ac_su_ndp_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "ac_mu_mimo_ndp_sch_flag_err",
+ htt_stats_buf->ac_mu_mimo_ndp_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "ac_mu_mimo_brp_sch_flag_err",
+ htt_stats_buf->ac_mu_mimo_brp_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n\n");
+
+ stats->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_selfgen_ax_sched_status_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats)
+{
+ const struct ath12k_htt_tx_selfgen_ax_sched_status_stats_tlv *htt_stats_buf =
+ tag_buf;
+ u8 *buf = stats->buf;
+ u32 len = stats->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len,
+ "HTT_TX_SELFGEN_AX_SCHED_STATUS_STATS_TLV:\n");
+ len += print_array_to_buf(buf, len, "ax_su_ndpa_sch_status",
+ htt_stats_buf->ax_su_ndpa_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ax_su_ndp_sch_status",
+ htt_stats_buf->ax_su_ndp_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ax_mu_mimo_ndpa_sch_status",
+ htt_stats_buf->ax_mu_mimo_ndpa_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ax_mu_mimo_ndp_sch_status",
+ htt_stats_buf->ax_mu_mimo_ndp_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ax_mu_brp_sch_status",
+ htt_stats_buf->ax_mu_brp_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ax_mu_bar_sch_status",
+ htt_stats_buf->ax_mu_bar_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ax_basic_trig_sch_status",
+ htt_stats_buf->ax_basic_trig_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ax_su_ndp_sch_flag_err",
+ htt_stats_buf->ax_su_ndp_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "ax_mu_mimo_ndp_sch_flag_err",
+ htt_stats_buf->ax_mu_mimo_ndp_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "ax_mu_brp_sch_flag_err",
+ htt_stats_buf->ax_mu_brp_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "ax_mu_bar_sch_flag_err",
+ htt_stats_buf->ax_mu_bar_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "ax_basic_trig_sch_flag_err",
+ htt_stats_buf->ax_basic_trig_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "ax_ulmumimo_trig_sch_status",
+ htt_stats_buf->ax_ulmumimo_trig_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ax_ulmumimo_trig_sch_flag_err",
+ htt_stats_buf->ax_ulmumimo_trig_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n\n");
+
+ stats->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_selfgen_be_sched_status_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats)
+{
+ const struct ath12k_htt_tx_selfgen_be_sched_status_stats_tlv *htt_stats_buf =
+ tag_buf;
+ u8 *buf = stats->buf;
+ u32 len = stats->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len,
+ "HTT_TX_SELFGEN_BE_SCHED_STATUS_STATS_TLV:\n");
+ len += print_array_to_buf(buf, len, "be_su_ndpa_sch_status",
+ htt_stats_buf->be_su_ndpa_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "be_su_ndp_sch_status",
+ htt_stats_buf->be_su_ndp_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "be_mu_mimo_ndpa_sch_status",
+ htt_stats_buf->be_mu_mimo_ndpa_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "be_mu_mimo_ndp_sch_status",
+ htt_stats_buf->be_mu_mimo_ndp_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "be_mu_brp_sch_status",
+ htt_stats_buf->be_mu_brp_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "be_mu_bar_sch_status",
+ htt_stats_buf->be_mu_bar_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "be_basic_trig_sch_status",
+ htt_stats_buf->be_basic_trig_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "be_su_ndp_sch_flag_err",
+ htt_stats_buf->be_su_ndp_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "be_mu_mimo_ndp_sch_flag_err",
+ htt_stats_buf->be_mu_mimo_ndp_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "be_mu_brp_sch_flag_err",
+ htt_stats_buf->be_mu_brp_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "be_mu_bar_sch_flag_err",
+ htt_stats_buf->be_mu_bar_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "be_basic_trig_sch_flag_err",
+ htt_stats_buf->be_basic_trig_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "be_basic_trig_sch_flag_err",
+ htt_stats_buf->be_basic_trig_sch_flag_err,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "be_ulmumimo_trig_sch_flag_err",
+ htt_stats_buf->be_ulmumimo_trig_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n\n");
+
+ stats->buf_len = len;
+}
+
+static void
+ath12k_htt_print_stats_string_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_stats_string_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u8 i;
+ u16 index = 0;
+ u32 datum;
+ char data[ATH12K_HTT_MAX_STRING_LEN] = {0};
+
+ tag_len = tag_len >> 2;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_STATS_STRING_TLV:\n");
+ for (i = 0; i < tag_len; i++) {
+ datum = __le32_to_cpu(htt_stats_buf->data[i]);
+ index += scnprintf(&data[index], ATH12K_HTT_MAX_STRING_LEN - index,
+ "%.*s", 4, (char *)&datum);
+ if (index >= ATH12K_HTT_MAX_STRING_LEN)
+ break;
+ }
+ len += scnprintf(buf + len, buf_len - len, "data = %s\n\n", data);
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_sring_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_sring_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u32 mac_id_word;
+ u32 avail_words;
+ u32 head_tail_ptr;
+ u32 sring_stat;
+ u32 tail_ptr;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ mac_id_word = __le32_to_cpu(htt_stats_buf->mac_id__ring_id__arena__ep);
+ avail_words = __le32_to_cpu(htt_stats_buf->num_avail_words__num_valid_words);
+ head_tail_ptr = __le32_to_cpu(htt_stats_buf->head_ptr__tail_ptr);
+ sring_stat = __le32_to_cpu(htt_stats_buf->consumer_empty__producer_full);
+ tail_ptr = __le32_to_cpu(htt_stats_buf->prefetch_count__internal_tail_ptr);
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_SRING_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n",
+ u32_get_bits(mac_id_word, ATH12K_HTT_SRING_STATS_MAC_ID));
+ len += scnprintf(buf + len, buf_len - len, "ring_id = %u\n",
+ u32_get_bits(mac_id_word, ATH12K_HTT_SRING_STATS_RING_ID));
+ len += scnprintf(buf + len, buf_len - len, "arena = %u\n",
+ u32_get_bits(mac_id_word, ATH12K_HTT_SRING_STATS_ARENA));
+ len += scnprintf(buf + len, buf_len - len, "ep = %u\n",
+ u32_get_bits(mac_id_word, ATH12K_HTT_SRING_STATS_EP));
+ len += scnprintf(buf + len, buf_len - len, "base_addr_lsb = 0x%x\n",
+ le32_to_cpu(htt_stats_buf->base_addr_lsb));
+ len += scnprintf(buf + len, buf_len - len, "base_addr_msb = 0x%x\n",
+ le32_to_cpu(htt_stats_buf->base_addr_msb));
+ len += scnprintf(buf + len, buf_len - len, "ring_size = %u\n",
+ le32_to_cpu(htt_stats_buf->ring_size));
+ len += scnprintf(buf + len, buf_len - len, "elem_size = %u\n",
+ le32_to_cpu(htt_stats_buf->elem_size));
+ len += scnprintf(buf + len, buf_len - len, "num_avail_words = %u\n",
+ u32_get_bits(avail_words,
+ ATH12K_HTT_SRING_STATS_NUM_AVAIL_WORDS));
+ len += scnprintf(buf + len, buf_len - len, "num_valid_words = %u\n",
+ u32_get_bits(avail_words,
+ ATH12K_HTT_SRING_STATS_NUM_VALID_WORDS));
+ len += scnprintf(buf + len, buf_len - len, "head_ptr = %u\n",
+ u32_get_bits(head_tail_ptr, ATH12K_HTT_SRING_STATS_HEAD_PTR));
+ len += scnprintf(buf + len, buf_len - len, "tail_ptr = %u\n",
+ u32_get_bits(head_tail_ptr, ATH12K_HTT_SRING_STATS_TAIL_PTR));
+ len += scnprintf(buf + len, buf_len - len, "consumer_empty = %u\n",
+ u32_get_bits(sring_stat,
+ ATH12K_HTT_SRING_STATS_CONSUMER_EMPTY));
+ len += scnprintf(buf + len, buf_len - len, "producer_full = %u\n",
+ u32_get_bits(head_tail_ptr,
+ ATH12K_HTT_SRING_STATS_PRODUCER_FULL));
+ len += scnprintf(buf + len, buf_len - len, "prefetch_count = %u\n",
+ u32_get_bits(tail_ptr, ATH12K_HTT_SRING_STATS_PREFETCH_COUNT));
+ len += scnprintf(buf + len, buf_len - len, "internal_tail_ptr = %u\n\n",
+ u32_get_bits(tail_ptr,
+ ATH12K_HTT_SRING_STATS_INTERNAL_TAIL_PTR));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_sfm_cmn_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_sfm_cmn_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u32 mac_id_word;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ mac_id_word = __le32_to_cpu(htt_stats_buf->mac_id__word);
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_SFM_CMN_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n",
+ u32_get_bits(mac_id_word, ATH12K_HTT_STATS_MAC_ID));
+ len += scnprintf(buf + len, buf_len - len, "buf_total = %u\n",
+ le32_to_cpu(htt_stats_buf->buf_total));
+ len += scnprintf(buf + len, buf_len - len, "mem_empty = %u\n",
+ le32_to_cpu(htt_stats_buf->mem_empty));
+ len += scnprintf(buf + len, buf_len - len, "deallocate_bufs = %u\n",
+ le32_to_cpu(htt_stats_buf->deallocate_bufs));
+ len += scnprintf(buf + len, buf_len - len, "num_records = %u\n\n",
+ le32_to_cpu(htt_stats_buf->num_records));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_sfm_client_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_sfm_client_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_SFM_CLIENT_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "client_id = %u\n",
+ le32_to_cpu(htt_stats_buf->client_id));
+ len += scnprintf(buf + len, buf_len - len, "buf_min = %u\n",
+ le32_to_cpu(htt_stats_buf->buf_min));
+ len += scnprintf(buf + len, buf_len - len, "buf_max = %u\n",
+ le32_to_cpu(htt_stats_buf->buf_max));
+ len += scnprintf(buf + len, buf_len - len, "buf_busy = %u\n",
+ le32_to_cpu(htt_stats_buf->buf_busy));
+ len += scnprintf(buf + len, buf_len - len, "buf_alloc = %u\n",
+ le32_to_cpu(htt_stats_buf->buf_alloc));
+ len += scnprintf(buf + len, buf_len - len, "buf_avail = %u\n",
+ le32_to_cpu(htt_stats_buf->buf_avail));
+ len += scnprintf(buf + len, buf_len - len, "num_users = %u\n\n",
+ le32_to_cpu(htt_stats_buf->num_users));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_sfm_client_user_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_sfm_client_user_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u16 num_elems = tag_len >> 2;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_SFM_CLIENT_USER_TLV:\n");
+ len += print_array_to_buf(buf, len, "dwords_used_by_user_n",
+ htt_stats_buf->dwords_used_by_user_n,
+ num_elems, "\n\n");
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_pdev_mu_mimo_sch_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_pdev_mu_mimo_sch_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u8 i;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len,
+ "HTT_TX_PDEV_MU_MIMO_SCH_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "mu_mimo_sch_posted = %u\n",
+ le32_to_cpu(htt_stats_buf->mu_mimo_sch_posted));
+ len += scnprintf(buf + len, buf_len - len, "mu_mimo_sch_failed = %u\n",
+ le32_to_cpu(htt_stats_buf->mu_mimo_sch_failed));
+ len += scnprintf(buf + len, buf_len - len, "mu_mimo_ppdu_posted = %u\n",
+ le32_to_cpu(htt_stats_buf->mu_mimo_ppdu_posted));
+ len += scnprintf(buf + len, buf_len - len,
+ "\nac_mu_mimo_sch_posted_per_group_index %u (SU) = %u\n", 0,
+ le32_to_cpu(htt_stats_buf->ac_mu_mimo_per_grp_sz[0]));
+ for (i = 1; i < ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS; i++) {
+ len += scnprintf(buf + len, buf_len - len,
+ "ac_mu_mimo_sch_posted_per_group_index %u ", i);
+ len += scnprintf(buf + len, buf_len - len,
+ "(TOTAL STREAMS = %u) = %u\n", i + 1,
+ le32_to_cpu(htt_stats_buf->ac_mu_mimo_per_grp_sz[i]));
+ }
+
+ for (i = 0; i < ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS; i++) {
+ len += scnprintf(buf + len, buf_len - len,
+ "ac_mu_mimo_sch_posted_per_group_index %u ",
+ i + ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS);
+ len += scnprintf(buf + len, buf_len - len,
+ "(TOTAL STREAMS = %u) = %u\n",
+ i + ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS + 1,
+ le32_to_cpu(htt_stats_buf->ac_mu_mimo_grp_sz_ext[i]));
+ }
+
+ len += scnprintf(buf + len, buf_len - len,
+ "\nax_mu_mimo_sch_posted_per_group_index %u (SU) = %u\n", 0,
+ le32_to_cpu(htt_stats_buf->ax_mu_mimo_per_grp_sz[0]));
+ for (i = 1; i < ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS; i++) {
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_mimo_sch_posted_per_group_index %u ", i);
+ len += scnprintf(buf + len, buf_len - len,
+ "(TOTAL STREAMS = %u) = %u\n", i + 1,
+ le32_to_cpu(htt_stats_buf->ax_mu_mimo_per_grp_sz[i]));
+ }
+
+ len += scnprintf(buf + len, buf_len - len,
+ "\nbe_mu_mimo_sch_posted_per_group_index %u (SU) = %u\n", 0,
+ le32_to_cpu(htt_stats_buf->be_mu_mimo_per_grp_sz[0]));
+ for (i = 1; i < ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS; i++) {
+ len += scnprintf(buf + len, buf_len - len,
+ "be_mu_mimo_sch_posted_per_group_index %u ", i);
+ len += scnprintf(buf + len, buf_len - len,
+ "(TOTAL STREAMS = %u) = %u\n", i + 1,
+ le32_to_cpu(htt_stats_buf->be_mu_mimo_per_grp_sz[i]));
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "\n11ac MU_MIMO SCH STATS:\n");
+ for (i = 0; i < ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS; i++) {
+ len += scnprintf(buf + len, buf_len - len, "ac_mu_mimo_sch_nusers_");
+ len += scnprintf(buf + len, buf_len - len, "%u = %u\n", i,
+ le32_to_cpu(htt_stats_buf->ac_mu_mimo_sch_nusers[i]));
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "\n11ax MU_MIMO SCH STATS:\n");
+ for (i = 0; i < ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS; i++) {
+ len += scnprintf(buf + len, buf_len - len, "ax_mu_mimo_sch_nusers_");
+ len += scnprintf(buf + len, buf_len - len, "%u = %u\n", i,
+ le32_to_cpu(htt_stats_buf->ax_mu_mimo_sch_nusers[i]));
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "\n11be MU_MIMO SCH STATS:\n");
+ for (i = 0; i < ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS; i++) {
+ len += scnprintf(buf + len, buf_len - len, "be_mu_mimo_sch_nusers_");
+ len += scnprintf(buf + len, buf_len - len, "%u = %u\n", i,
+ le32_to_cpu(htt_stats_buf->be_mu_mimo_sch_nusers[i]));
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "\n11ax OFDMA SCH STATS:\n");
+ for (i = 0; i < ATH12K_HTT_TX_NUM_OFDMA_USER_STATS; i++) {
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_ofdma_sch_nusers_%u = %u\n", i,
+ le32_to_cpu(htt_stats_buf->ax_ofdma_sch_nusers[i]));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_ul_ofdma_basic_sch_nusers_%u = %u\n", i,
+ le32_to_cpu(htt_stats_buf->ax_ul_ofdma_nusers[i]));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_ul_ofdma_bsr_sch_nusers_%u = %u\n", i,
+ le32_to_cpu(htt_stats_buf->ax_ul_ofdma_bsr_nusers[i]));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_ul_ofdma_bar_sch_nusers_%u = %u\n", i,
+ le32_to_cpu(htt_stats_buf->ax_ul_ofdma_bar_nusers[i]));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_ul_ofdma_brp_sch_nusers_%u = %u\n\n", i,
+ le32_to_cpu(htt_stats_buf->ax_ul_ofdma_brp_nusers[i]));
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "11ax UL MUMIMO SCH STATS:\n");
+ for (i = 0; i < ATH12K_HTT_TX_NUM_UL_MUMIMO_USER_STATS; i++) {
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_ul_mumimo_basic_sch_nusers_%u = %u\n", i,
+ le32_to_cpu(htt_stats_buf->ax_ul_mumimo_nusers[i]));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_ul_mumimo_brp_sch_nusers_%u = %u\n\n", i,
+ le32_to_cpu(htt_stats_buf->ax_ul_mumimo_brp_nusers[i]));
+ }
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_pdev_mumimo_grp_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_pdev_mumimo_grp_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ int j;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_TX_PDEV_MUMIMO_GRP_STATS:\n");
+ len += print_array_to_buf(buf, len,
+ "dl_mumimo_grp_tputs_observed (per bin = 300 mbps)",
+ htt_stats_buf->dl_mumimo_grp_tputs,
+ ATH12K_HTT_STATS_MUMIMO_TPUT_NUM_BINS, "\n");
+ len += print_array_to_buf(buf, len, "dl_mumimo_grp eligible",
+ htt_stats_buf->dl_mumimo_grp_eligible,
+ ATH12K_HTT_STATS_NUM_MAX_MUMIMO_SZ, "\n");
+ len += print_array_to_buf(buf, len, "dl_mumimo_grp_ineligible",
+ htt_stats_buf->dl_mumimo_grp_ineligible,
+ ATH12K_HTT_STATS_NUM_MAX_MUMIMO_SZ, "\n");
+ len += scnprintf(buf + len, buf_len - len, "dl_mumimo_grp_invalid:\n");
+ for (j = 0; j < ATH12K_HTT_STATS_NUM_MAX_MUMIMO_SZ; j++) {
+ len += scnprintf(buf + len, buf_len - len, "grp_id = %u", j);
+ len += print_array_to_buf(buf, len, "",
+ htt_stats_buf->dl_mumimo_grp_invalid,
+ ATH12K_HTT_STATS_MAX_INVALID_REASON_CODE,
+ "\n");
+ }
+
+ len += print_array_to_buf(buf, len, "ul_mumimo_grp_best_grp_size",
+ htt_stats_buf->ul_mumimo_grp_best_grp_size,
+ ATH12K_HTT_STATS_NUM_MAX_MUMIMO_SZ, "\n");
+ len += print_array_to_buf_index(buf, len, "ul_mumimo_grp_best_num_usrs = ", 1,
+ htt_stats_buf->ul_mumimo_grp_best_usrs,
+ ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS, "\n");
+ len += print_array_to_buf(buf, len,
+ "ul_mumimo_grp_tputs_observed (per bin = 300 mbps)",
+ htt_stats_buf->ul_mumimo_grp_tputs,
+ ATH12K_HTT_STATS_MUMIMO_TPUT_NUM_BINS, "\n\n");
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_pdev_mu_mimo_mpdu_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_pdev_mpdu_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u32 user_index;
+ u32 tx_sched_mode;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ user_index = __le32_to_cpu(htt_stats_buf->user_index);
+ tx_sched_mode = __le32_to_cpu(htt_stats_buf->tx_sched_mode);
+
+ if (tx_sched_mode == ATH12K_HTT_STATS_TX_SCHED_MODE_MU_MIMO_AC) {
+ if (!user_index)
+ len += scnprintf(buf + len, buf_len - len,
+ "HTT_TX_PDEV_MU_MIMO_AC_MPDU_STATS:\n");
+
+ if (user_index < ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS) {
+ len += scnprintf(buf + len, buf_len - len,
+ "ac_mu_mimo_mpdus_queued_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_queued_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ac_mu_mimo_mpdus_tried_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_tried_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ac_mu_mimo_mpdus_failed_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_failed_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ac_mu_mimo_mpdus_requeued_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_requeued_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ac_mu_mimo_err_no_ba_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->err_no_ba_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ac_mu_mimo_mpdu_underrun_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdu_underrun_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ac_mu_mimo_ampdu_underrun_usr_%u = %u\n\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->ampdu_underrun_usr));
+ }
+ }
+
+ if (tx_sched_mode == ATH12K_HTT_STATS_TX_SCHED_MODE_MU_MIMO_AX) {
+ if (!user_index)
+ len += scnprintf(buf + len, buf_len - len,
+ "HTT_TX_PDEV_MU_MIMO_AX_MPDU_STATS:\n");
+
+ if (user_index < ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS) {
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_mimo_mpdus_queued_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_queued_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_mimo_mpdus_tried_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_tried_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_mimo_mpdus_failed_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_failed_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_mimo_mpdus_requeued_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_requeued_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_mimo_err_no_ba_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->err_no_ba_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_mimo_mpdu_underrun_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdu_underrun_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_mimo_ampdu_underrun_usr_%u = %u\n\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->ampdu_underrun_usr));
+ }
+ }
+
+ if (tx_sched_mode == ATH12K_HTT_STATS_TX_SCHED_MODE_MU_OFDMA_AX) {
+ if (!user_index)
+ len += scnprintf(buf + len, buf_len - len,
+ "HTT_TX_PDEV_AX_MU_OFDMA_MPDU_STATS:\n");
+
+ if (user_index < ATH12K_HTT_TX_NUM_OFDMA_USER_STATS) {
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_ofdma_mpdus_queued_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_queued_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_ofdma_mpdus_tried_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_tried_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_ofdma_mpdus_failed_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_failed_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_ofdma_mpdus_requeued_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_requeued_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_ofdma_err_no_ba_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->err_no_ba_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_ofdma_mpdu_underrun_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdu_underrun_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_ofdma_ampdu_underrun_usr_%u = %u\n\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->ampdu_underrun_usr));
+ }
+ }
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_pdev_cca_stats_hist_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_pdev_cca_stats_hist_v1_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_PDEV_CCA_STATS_HIST_TLV :\n");
+ len += scnprintf(buf + len, buf_len - len, "chan_num = %u\n",
+ le32_to_cpu(htt_stats_buf->chan_num));
+ len += scnprintf(buf + len, buf_len - len, "num_records = %u\n",
+ le32_to_cpu(htt_stats_buf->num_records));
+ len += scnprintf(buf + len, buf_len - len, "valid_cca_counters_bitmap = 0x%x\n",
+ le32_to_cpu(htt_stats_buf->valid_cca_counters_bitmap));
+ len += scnprintf(buf + len, buf_len - len, "collection_interval = %u\n\n",
+ le32_to_cpu(htt_stats_buf->collection_interval));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_pdev_stats_cca_counters_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_pdev_stats_cca_counters_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len,
+ "HTT_PDEV_STATS_CCA_COUNTERS_TLV:(in usec)\n");
+ len += scnprintf(buf + len, buf_len - len, "tx_frame_usec = %u\n",
+ le32_to_cpu(htt_stats_buf->tx_frame_usec));
+ len += scnprintf(buf + len, buf_len - len, "rx_frame_usec = %u\n",
+ le32_to_cpu(htt_stats_buf->rx_frame_usec));
+ len += scnprintf(buf + len, buf_len - len, "rx_clear_usec = %u\n",
+ le32_to_cpu(htt_stats_buf->rx_clear_usec));
+ len += scnprintf(buf + len, buf_len - len, "my_rx_frame_usec = %u\n",
+ le32_to_cpu(htt_stats_buf->my_rx_frame_usec));
+ len += scnprintf(buf + len, buf_len - len, "usec_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->usec_cnt));
+ len += scnprintf(buf + len, buf_len - len, "med_rx_idle_usec = %u\n",
+ le32_to_cpu(htt_stats_buf->med_rx_idle_usec));
+ len += scnprintf(buf + len, buf_len - len, "med_tx_idle_global_usec = %u\n",
+ le32_to_cpu(htt_stats_buf->med_tx_idle_global_usec));
+ len += scnprintf(buf + len, buf_len - len, "cca_obss_usec = %u\n\n",
+ le32_to_cpu(htt_stats_buf->cca_obss_usec));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_pdev_obss_pd_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_pdev_obss_pd_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u8 i;
+ static const char *access_cat_names[ATH12K_HTT_NUM_AC_WMM] = {"best effort",
+ "background",
+ "video", "voice"};
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_PDEV_OBSS_PD_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "num_spatial_reuse_tx = %u\n",
+ le32_to_cpu(htt_stats_buf->num_sr_tx_transmissions));
+ len += scnprintf(buf + len, buf_len - len,
+ "num_spatial_reuse_opportunities = %u\n",
+ le32_to_cpu(htt_stats_buf->num_spatial_reuse_opportunities));
+ len += scnprintf(buf + len, buf_len - len, "num_non_srg_opportunities = %u\n",
+ le32_to_cpu(htt_stats_buf->num_non_srg_opportunities));
+ len += scnprintf(buf + len, buf_len - len, "num_non_srg_ppdu_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->num_non_srg_ppdu_tried));
+ len += scnprintf(buf + len, buf_len - len, "num_non_srg_ppdu_success = %u\n",
+ le32_to_cpu(htt_stats_buf->num_non_srg_ppdu_success));
+ len += scnprintf(buf + len, buf_len - len, "num_srg_opportunities = %u\n",
+ le32_to_cpu(htt_stats_buf->num_srg_opportunities));
+ len += scnprintf(buf + len, buf_len - len, "num_srg_ppdu_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->num_srg_ppdu_tried));
+ len += scnprintf(buf + len, buf_len - len, "num_srg_ppdu_success = %u\n",
+ le32_to_cpu(htt_stats_buf->num_srg_ppdu_success));
+ len += scnprintf(buf + len, buf_len - len, "num_psr_opportunities = %u\n",
+ le32_to_cpu(htt_stats_buf->num_psr_opportunities));
+ len += scnprintf(buf + len, buf_len - len, "num_psr_ppdu_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->num_psr_ppdu_tried));
+ len += scnprintf(buf + len, buf_len - len, "num_psr_ppdu_success = %u\n",
+ le32_to_cpu(htt_stats_buf->num_psr_ppdu_success));
+ len += scnprintf(buf + len, buf_len - len, "min_duration_check_flush_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->num_obss_min_dur_check_flush_cnt));
+ len += scnprintf(buf + len, buf_len - len, "sr_ppdu_abort_flush_cnt = %u\n\n",
+ le32_to_cpu(htt_stats_buf->num_sr_ppdu_abort_flush_cnt));
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_PDEV_OBSS_PD_PER_AC_STATS:\n");
+ for (i = 0; i < ATH12K_HTT_NUM_AC_WMM; i++) {
+ len += scnprintf(buf + len, buf_len - len, "Access Category %u (%s)\n",
+ i, access_cat_names[i]);
+ len += scnprintf(buf + len, buf_len - len,
+ "num_non_srg_ppdu_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->num_non_srg_tried_per_ac[i]));
+ len += scnprintf(buf + len, buf_len - len,
+ "num_non_srg_ppdu_success = %u\n",
+ le32_to_cpu(htt_stats_buf->num_non_srg_success_ac[i]));
+ len += scnprintf(buf + len, buf_len - len, "num_srg_ppdu_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->num_srg_tried_per_ac[i]));
+ len += scnprintf(buf + len, buf_len - len,
+ "num_srg_ppdu_success = %u\n\n",
+ le32_to_cpu(htt_stats_buf->num_srg_success_per_ac[i]));
+ }
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_dmac_reset_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_dmac_reset_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u64 time;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_DMAC_RESET_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "reset_count = %u\n",
+ le32_to_cpu(htt_stats_buf->reset_count));
+ time = ath12k_le32hilo_to_u64(htt_stats_buf->reset_time_hi_ms,
+ htt_stats_buf->reset_time_lo_ms);
+ len += scnprintf(buf + len, buf_len - len, "reset_time_ms = %llu\n", time);
+
+ time = ath12k_le32hilo_to_u64(htt_stats_buf->disengage_time_hi_ms,
+ htt_stats_buf->disengage_time_lo_ms);
+ len += scnprintf(buf + len, buf_len - len, "disengage_time_ms = %llu\n", time);
+
+ time = ath12k_le32hilo_to_u64(htt_stats_buf->engage_time_hi_ms,
+ htt_stats_buf->engage_time_lo_ms);
+ len += scnprintf(buf + len, buf_len - len, "engage_time_ms = %llu\n", time);
+
+ len += scnprintf(buf + len, buf_len - len, "disengage_count = %u\n",
+ le32_to_cpu(htt_stats_buf->disengage_count));
+ len += scnprintf(buf + len, buf_len - len, "engage_count = %u\n",
+ le32_to_cpu(htt_stats_buf->engage_count));
+ len += scnprintf(buf + len, buf_len - len, "drain_dest_ring_mask = 0x%x\n\n",
+ le32_to_cpu(htt_stats_buf->drain_dest_ring_mask));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_pdev_sched_algo_ofdma_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_pdev_sched_algo_ofdma_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u32 mac_id_word;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ mac_id_word = le32_to_cpu(htt_stats_buf->mac_id__word);
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_PDEV_SCHED_ALGO_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n",
+ u32_get_bits(mac_id_word, ATH12K_HTT_STATS_MAC_ID));
+ len += print_array_to_buf(buf, len, "rate_based_dlofdma_enabled_count",
+ htt_stats_buf->rate_based_dlofdma_enabled_cnt,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "rate_based_dlofdma_disabled_count",
+ htt_stats_buf->rate_based_dlofdma_disabled_cnt,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "rate_based_dlofdma_probing_count",
+ htt_stats_buf->rate_based_dlofdma_disabled_cnt,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "rate_based_dlofdma_monitoring_count",
+ htt_stats_buf->rate_based_dlofdma_monitor_cnt,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "chan_acc_lat_based_dlofdma_enabled_count",
+ htt_stats_buf->chan_acc_lat_based_dlofdma_enabled_cnt,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "chan_acc_lat_based_dlofdma_disabled_count",
+ htt_stats_buf->chan_acc_lat_based_dlofdma_disabled_cnt,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "chan_acc_lat_based_dlofdma_monitoring_count",
+ htt_stats_buf->chan_acc_lat_based_dlofdma_monitor_cnt,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "downgrade_to_dl_su_ru_alloc_fail",
+ htt_stats_buf->downgrade_to_dl_su_ru_alloc_fail,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "candidate_list_single_user_disable_ofdma",
+ htt_stats_buf->candidate_list_single_user_disable_ofdma,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "dl_cand_list_dropped_high_ul_qos_weight",
+ htt_stats_buf->dl_cand_list_dropped_high_ul_qos_weight,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "ax_dlofdma_disabled_due_to_pipelining",
+ htt_stats_buf->ax_dlofdma_disabled_due_to_pipelining,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "dlofdma_disabled_su_only_eligible",
+ htt_stats_buf->dlofdma_disabled_su_only_eligible,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "dlofdma_disabled_consec_no_mpdus_tried",
+ htt_stats_buf->dlofdma_disabled_consec_no_mpdus_tried,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "dlofdma_disabled_consec_no_mpdus_success",
+ htt_stats_buf->dlofdma_disabled_consec_no_mpdus_success,
+ ATH12K_HTT_NUM_AC_WMM, "\n\n");
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_pdev_rate_stats_be_ofdma_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_pdev_rate_stats_be_ofdma_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u32 mac_id_word;
+ u8 i;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ mac_id_word = le32_to_cpu(htt_stats_buf->mac_id__word);
+
+ len += scnprintf(buf + len, buf_len - len,
+ "HTT_TX_PDEV_RATE_STATS_BE_OFDMA_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n",
+ u32_get_bits(mac_id_word, ATH12K_HTT_STATS_MAC_ID));
+ len += scnprintf(buf + len, buf_len - len, "be_ofdma_tx_ldpc = %u\n",
+ le32_to_cpu(htt_stats_buf->be_ofdma_tx_ldpc));
+ len += print_array_to_buf(buf, len, "be_ofdma_tx_mcs",
+ htt_stats_buf->be_ofdma_tx_mcs,
+ ATH12K_HTT_TX_PDEV_NUM_BE_MCS_CNTRS, "\n");
+ len += print_array_to_buf(buf, len, "be_ofdma_eht_sig_mcs",
+ htt_stats_buf->be_ofdma_eht_sig_mcs,
+ ATH12K_HTT_TX_PDEV_NUM_EHT_SIG_MCS_CNTRS, "\n");
+ len += scnprintf(buf + len, buf_len - len, "be_ofdma_tx_ru_size = ");
+ for (i = 0; i < ATH12K_HTT_TX_RX_PDEV_NUM_BE_RU_SIZE_CNTRS; i++)
+ len += scnprintf(buf + len, buf_len - len, " %s:%u ",
+ ath12k_htt_be_tx_rx_ru_size_to_str(i),
+ le32_to_cpu(htt_stats_buf->be_ofdma_tx_ru_size[i]));
+ len += scnprintf(buf + len, buf_len - len, "\n");
+ len += print_array_to_buf_index(buf, len, "be_ofdma_tx_nss = ", 1,
+ htt_stats_buf->be_ofdma_tx_nss,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS,
+ "\n");
+ len += print_array_to_buf(buf, len, "be_ofdma_tx_bw",
+ htt_stats_buf->be_ofdma_tx_bw,
+ ATH12K_HTT_TX_PDEV_NUM_BE_BW_CNTRS, "\n");
+ for (i = 0; i < ATH12K_HTT_TX_PDEV_NUM_GI_CNTRS; i++) {
+ len += scnprintf(buf + len, buf_len - len,
+ "be_ofdma_tx_gi[%u]", i);
+ len += print_array_to_buf(buf, len, "", htt_stats_buf->gi[i],
+ ATH12K_HTT_TX_PDEV_NUM_BE_MCS_CNTRS, "\n");
+ }
+ len += scnprintf(buf + len, buf_len - len, "\n");
+
+ stats_req->buf_len = len;
+}
+
static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab,
u16 tag, u16 len, const void *tag_buf,
void *user_data)
@@ -1552,6 +2801,83 @@ static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab,
case HTT_STATS_TX_DE_COMPL_STATS_TAG:
ath12k_htt_print_tx_de_compl_stats_tlv(tag_buf, len, stats_req);
break;
+ case HTT_STATS_TX_SELFGEN_CMN_STATS_TAG:
+ ath12k_htt_print_tx_selfgen_cmn_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_TX_SELFGEN_AC_STATS_TAG:
+ ath12k_htt_print_tx_selfgen_ac_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_TX_SELFGEN_AX_STATS_TAG:
+ ath12k_htt_print_tx_selfgen_ax_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_TX_SELFGEN_BE_STATS_TAG:
+ ath12k_htt_print_tx_selfgen_be_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_TX_SELFGEN_AC_ERR_STATS_TAG:
+ ath12k_htt_print_tx_selfgen_ac_err_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_TX_SELFGEN_AX_ERR_STATS_TAG:
+ ath12k_htt_print_tx_selfgen_ax_err_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_TX_SELFGEN_BE_ERR_STATS_TAG:
+ ath12k_htt_print_tx_selfgen_be_err_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_TX_SELFGEN_AC_SCHED_STATUS_STATS_TAG:
+ ath12k_htt_print_tx_selfgen_ac_sched_status_stats_tlv(tag_buf, len,
+ stats_req);
+ break;
+ case HTT_STATS_TX_SELFGEN_AX_SCHED_STATUS_STATS_TAG:
+ ath12k_htt_print_tx_selfgen_ax_sched_status_stats_tlv(tag_buf, len,
+ stats_req);
+ break;
+ case HTT_STATS_TX_SELFGEN_BE_SCHED_STATUS_STATS_TAG:
+ ath12k_htt_print_tx_selfgen_be_sched_status_stats_tlv(tag_buf, len,
+ stats_req);
+ break;
+ case HTT_STATS_STRING_TAG:
+ ath12k_htt_print_stats_string_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_SRING_STATS_TAG:
+ ath12k_htt_print_sring_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_SFM_CMN_TAG:
+ ath12k_htt_print_sfm_cmn_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_SFM_CLIENT_TAG:
+ ath12k_htt_print_sfm_client_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_SFM_CLIENT_USER_TAG:
+ ath12k_htt_print_sfm_client_user_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_TX_PDEV_MU_MIMO_STATS_TAG:
+ ath12k_htt_print_tx_pdev_mu_mimo_sch_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_TX_PDEV_MUMIMO_GRP_STATS_TAG:
+ ath12k_htt_print_tx_pdev_mumimo_grp_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_TX_PDEV_MPDU_STATS_TAG:
+ ath12k_htt_print_tx_pdev_mu_mimo_mpdu_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_PDEV_CCA_1SEC_HIST_TAG:
+ case HTT_STATS_PDEV_CCA_100MSEC_HIST_TAG:
+ case HTT_STATS_PDEV_CCA_STAT_CUMULATIVE_TAG:
+ ath12k_htt_print_pdev_cca_stats_hist_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_PDEV_CCA_COUNTERS_TAG:
+ ath12k_htt_print_pdev_stats_cca_counters_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_PDEV_OBSS_PD_TAG:
+ ath12k_htt_print_pdev_obss_pd_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_DMAC_RESET_STATS_TAG:
+ ath12k_htt_print_dmac_reset_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_PDEV_SCHED_ALGO_OFDMA_STATS_TAG:
+ ath12k_htt_print_pdev_sched_algo_ofdma_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_TX_PDEV_RATE_STATS_BE_OFDMA_TAG:
+ ath12k_htt_print_tx_pdev_rate_stats_be_ofdma_tlv(tag_buf, len, stats_req);
+ break;
default:
break;
}
@@ -1627,9 +2953,9 @@ static ssize_t ath12k_read_htt_stats_type(struct file *file,
char buf[32];
size_t len;
- mutex_lock(&ar->conf_mutex);
+ wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
type = ar->debug.htt_stats.type;
- mutex_unlock(&ar->conf_mutex);
+ wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
len = scnprintf(buf, sizeof(buf), "%u\n", type);
@@ -1662,7 +2988,7 @@ static ssize_t ath12k_write_htt_stats_type(struct file *file,
type >= ATH12K_DBG_HTT_NUM_EXT_STATS)
return -EINVAL;
- mutex_lock(&ar->conf_mutex);
+ wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
ar->debug.htt_stats.type = type;
ar->debug.htt_stats.cfg_param[0] = cfg_param[0];
@@ -1670,7 +2996,7 @@ static ssize_t ath12k_write_htt_stats_type(struct file *file,
ar->debug.htt_stats.cfg_param[2] = cfg_param[2];
ar->debug.htt_stats.cfg_param[3] = cfg_param[3];
- mutex_unlock(&ar->conf_mutex);
+ wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return count;
}
@@ -1691,7 +3017,7 @@ static int ath12k_debugfs_htt_stats_req(struct ath12k *ar)
int ret, pdev_id;
struct htt_ext_stats_cfg_params cfg_params = { 0 };
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
init_completion(&stats_req->htt_stats_rcvd);
@@ -1741,7 +3067,7 @@ static int ath12k_open_htt_stats(struct inode *inode,
if (type == ATH12K_DBG_HTT_EXT_STATS_RESET)
return -EPERM;
- mutex_lock(&ar->conf_mutex);
+ wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
if (ah->state != ATH12K_HW_STATE_ON) {
ret = -ENETDOWN;
@@ -1776,14 +3102,14 @@ static int ath12k_open_htt_stats(struct inode *inode,
file->private_data = stats_req;
- mutex_unlock(&ar->conf_mutex);
+ wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return 0;
out:
kfree(stats_req);
ar->debug.htt_stats.stats_req = NULL;
err_unlock:
- mutex_unlock(&ar->conf_mutex);
+ wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return ret;
}
@@ -1793,10 +3119,10 @@ static int ath12k_release_htt_stats(struct inode *inode,
{
struct ath12k *ar = inode->i_private;
- mutex_lock(&ar->conf_mutex);
+ wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
kfree(file->private_data);
ar->debug.htt_stats.stats_req = NULL;
- mutex_unlock(&ar->conf_mutex);
+ wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return 0;
}
@@ -1840,7 +3166,7 @@ static ssize_t ath12k_write_htt_stats_reset(struct file *file,
type == ATH12K_DBG_HTT_EXT_STATS_RESET)
return -E2BIG;
- mutex_lock(&ar->conf_mutex);
+ wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
cfg_params.cfg0 = HTT_STAT_DEFAULT_RESET_START_OFFSET;
param_pos = (type >> 5) + 1;
@@ -1866,12 +3192,12 @@ static ssize_t ath12k_write_htt_stats_reset(struct file *file,
0ULL);
if (ret) {
ath12k_warn(ar->ab, "failed to send htt stats request: %d\n", ret);
- mutex_unlock(&ar->conf_mutex);
+ wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return ret;
}
ar->debug.htt_stats.reset = type;
- mutex_unlock(&ar->conf_mutex);
+ wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return count;
}
diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h
index d52b26b23e65..ac86cab234ec 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h
+++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h
@@ -123,12 +123,21 @@ struct ath12k_htt_extd_stats_msg {
/* htt_dbg_ext_stats_type */
enum ath12k_dbg_htt_ext_stats_type {
- ATH12K_DBG_HTT_EXT_STATS_RESET = 0,
- ATH12K_DBG_HTT_EXT_STATS_PDEV_TX = 1,
- ATH12K_DBG_HTT_EXT_STATS_PDEV_TX_SCHED = 4,
- ATH12K_DBG_HTT_EXT_STATS_PDEV_ERROR = 5,
- ATH12K_DBG_HTT_EXT_STATS_PDEV_TQM = 6,
- ATH12K_DBG_HTT_EXT_STATS_TX_DE_INFO = 8,
+ ATH12K_DBG_HTT_EXT_STATS_RESET = 0,
+ ATH12K_DBG_HTT_EXT_STATS_PDEV_TX = 1,
+ ATH12K_DBG_HTT_EXT_STATS_PDEV_TX_SCHED = 4,
+ ATH12K_DBG_HTT_EXT_STATS_PDEV_ERROR = 5,
+ ATH12K_DBG_HTT_EXT_STATS_PDEV_TQM = 6,
+ ATH12K_DBG_HTT_EXT_STATS_TX_DE_INFO = 8,
+ ATH12K_DBG_HTT_EXT_STATS_TX_SELFGEN_INFO = 12,
+ ATH12K_DBG_HTT_EXT_STATS_SRNG_INFO = 15,
+ ATH12K_DBG_HTT_EXT_STATS_SFM_INFO = 16,
+ ATH12K_DBG_HTT_EXT_STATS_PDEV_TX_MU = 17,
+ ATH12K_DBG_HTT_EXT_STATS_PDEV_CCA_STATS = 19,
+ ATH12K_DBG_HTT_EXT_STATS_PDEV_OBSS_PD_STATS = 23,
+ ATH12K_DBG_HTT_EXT_STATS_SOC_ERROR = 45,
+ ATH12K_DBG_HTT_EXT_STATS_PDEV_SCHED_ALGO = 49,
+ ATH12K_DBG_HTT_EXT_STATS_MANDATORY_MUOFDMA = 51,
/* keep this last */
ATH12K_DBG_HTT_NUM_EXT_STATS,
@@ -139,6 +148,7 @@ enum ath12k_dbg_htt_tlv_tag {
HTT_STATS_TX_PDEV_UNDERRUN_TAG = 1,
HTT_STATS_TX_PDEV_SIFS_TAG = 2,
HTT_STATS_TX_PDEV_FLUSH_TAG = 3,
+ HTT_STATS_STRING_TAG = 5,
HTT_STATS_TX_TQM_GEN_MPDU_TAG = 11,
HTT_STATS_TX_TQM_LIST_MPDU_TAG = 12,
HTT_STATS_TX_TQM_LIST_MPDU_CNT_TAG = 13,
@@ -151,22 +161,47 @@ enum ath12k_dbg_htt_tlv_tag {
HTT_STATS_TX_DE_ENQUEUE_PACKETS_TAG = 21,
HTT_STATS_TX_DE_ENQUEUE_DISCARD_TAG = 22,
HTT_STATS_TX_DE_CMN_TAG = 23,
+ HTT_STATS_TX_PDEV_MU_MIMO_STATS_TAG = 25,
+ HTT_STATS_SFM_CMN_TAG = 26,
+ HTT_STATS_SRING_STATS_TAG = 27,
HTT_STATS_TX_PDEV_SCHEDULER_TXQ_STATS_TAG = 36,
HTT_STATS_TX_SCHED_CMN_TAG = 37,
HTT_STATS_SCHED_TXQ_CMD_POSTED_TAG = 39,
+ HTT_STATS_SFM_CLIENT_USER_TAG = 41,
+ HTT_STATS_SFM_CLIENT_TAG = 42,
HTT_STATS_TX_TQM_ERROR_STATS_TAG = 43,
HTT_STATS_SCHED_TXQ_CMD_REAPED_TAG = 44,
+ HTT_STATS_TX_SELFGEN_AC_ERR_STATS_TAG = 46,
+ HTT_STATS_TX_SELFGEN_CMN_STATS_TAG = 47,
+ HTT_STATS_TX_SELFGEN_AC_STATS_TAG = 48,
+ HTT_STATS_TX_SELFGEN_AX_STATS_TAG = 49,
+ HTT_STATS_TX_SELFGEN_AX_ERR_STATS_TAG = 50,
HTT_STATS_HW_INTR_MISC_TAG = 54,
HTT_STATS_HW_PDEV_ERRS_TAG = 56,
HTT_STATS_TX_DE_COMPL_STATS_TAG = 65,
HTT_STATS_WHAL_TX_TAG = 66,
HTT_STATS_TX_PDEV_SIFS_HIST_TAG = 67,
+ HTT_STATS_PDEV_CCA_1SEC_HIST_TAG = 70,
+ HTT_STATS_PDEV_CCA_100MSEC_HIST_TAG = 71,
+ HTT_STATS_PDEV_CCA_STAT_CUMULATIVE_TAG = 72,
+ HTT_STATS_PDEV_CCA_COUNTERS_TAG = 73,
+ HTT_STATS_TX_PDEV_MPDU_STATS_TAG = 74,
HTT_STATS_SCHED_TXQ_SCHED_ORDER_SU_TAG = 86,
HTT_STATS_SCHED_TXQ_SCHED_INELIGIBILITY_TAG = 87,
+ HTT_STATS_PDEV_OBSS_PD_TAG = 88,
HTT_STATS_HW_WAR_TAG = 89,
HTT_STATS_SCHED_TXQ_SUPERCYCLE_TRIGGER_TAG = 100,
HTT_STATS_PDEV_CTRL_PATH_TX_STATS_TAG = 102,
+ HTT_STATS_TX_SELFGEN_AC_SCHED_STATUS_STATS_TAG = 111,
+ HTT_STATS_TX_SELFGEN_AX_SCHED_STATUS_STATS_TAG = 112,
HTT_STATS_MU_PPDU_DIST_TAG = 129,
+ HTT_STATS_TX_PDEV_MUMIMO_GRP_STATS_TAG = 130,
+ HTT_STATS_TX_PDEV_RATE_STATS_BE_OFDMA_TAG = 135,
+ HTT_STATS_TX_SELFGEN_BE_ERR_STATS_TAG = 137,
+ HTT_STATS_TX_SELFGEN_BE_STATS_TAG = 138,
+ HTT_STATS_TX_SELFGEN_BE_SCHED_STATUS_STATS_TAG = 139,
+ HTT_STATS_DMAC_RESET_STATS_TAG = 155,
+ HTT_STATS_PDEV_SCHED_ALGO_OFDMA_STATS_TAG = 165,
HTT_STATS_MAX_TAG,
};
@@ -690,4 +725,401 @@ struct ath12k_htt_tx_de_compl_stats_tlv {
__le32 tqm_bypass_frame;
} __packed;
+enum ath12k_htt_tx_mumimo_grp_invalid_reason_code_stats {
+ ATH12K_HTT_TX_MUMIMO_GRP_VALID,
+ ATH12K_HTT_TX_MUMIMO_GRP_INVALID_NUM_MU_USERS_EXCEEDED_MU_MAX_USERS,
+ ATH12K_HTT_TX_MUMIMO_GRP_INVALID_SCHED_ALGO_NOT_MU_COMPATIBLE_GID,
+ ATH12K_HTT_TX_MUMIMO_GRP_INVALID_NON_PRIMARY_GRP,
+ ATH12K_HTT_TX_MUMIMO_GRP_INVALID_ZERO_CANDIDATES,
+ ATH12K_HTT_TX_MUMIMO_GRP_INVALID_MORE_CANDIDATES,
+ ATH12K_HTT_TX_MUMIMO_GRP_INVALID_GROUP_SIZE_EXCEED_NSS,
+ ATH12K_HTT_TX_MUMIMO_GRP_INVALID_GROUP_INELIGIBLE,
+ ATH12K_HTT_TX_MUMIMO_GRP_INVALID,
+ ATH12K_HTT_TX_MUMIMO_GRP_INVALID_GROUP_EFF_MU_TPUT_OMBPS,
+ ATH12K_HTT_TX_MUMIMO_GRP_INVALID_MAX_REASON_CODE,
+};
+
+#define ATH12K_HTT_NUM_AC_WMM 0x4
+#define ATH12K_HTT_MAX_NUM_SBT_INTR 4
+#define ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS 4
+#define ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS 8
+#define ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS 8
+#define ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS 7
+#define ATH12K_HTT_TX_NUM_OFDMA_USER_STATS 74
+#define ATH12K_HTT_TX_NUM_UL_MUMIMO_USER_STATS 8
+#define ATH12K_HTT_STATS_NUM_MAX_MUMIMO_SZ 8
+#define ATH12K_HTT_STATS_MUMIMO_TPUT_NUM_BINS 10
+
+#define ATH12K_HTT_STATS_MAX_INVALID_REASON_CODE \
+ ATH12K_HTT_TX_MUMIMO_GRP_INVALID_MAX_REASON_CODE
+#define ATH12K_HTT_TX_NUM_MUMIMO_GRP_INVALID_WORDS \
+ (ATH12K_HTT_STATS_NUM_MAX_MUMIMO_SZ * ATH12K_HTT_STATS_MAX_INVALID_REASON_CODE)
+
+struct ath12k_htt_tx_selfgen_cmn_stats_tlv {
+ __le32 mac_id__word;
+ __le32 su_bar;
+ __le32 rts;
+ __le32 cts2self;
+ __le32 qos_null;
+ __le32 delayed_bar_1;
+ __le32 delayed_bar_2;
+ __le32 delayed_bar_3;
+ __le32 delayed_bar_4;
+ __le32 delayed_bar_5;
+ __le32 delayed_bar_6;
+ __le32 delayed_bar_7;
+} __packed;
+
+struct ath12k_htt_tx_selfgen_ac_stats_tlv {
+ __le32 ac_su_ndpa;
+ __le32 ac_su_ndp;
+ __le32 ac_mu_mimo_ndpa;
+ __le32 ac_mu_mimo_ndp;
+ __le32 ac_mu_mimo_brpoll[ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS - 1];
+} __packed;
+
+struct ath12k_htt_tx_selfgen_ax_stats_tlv {
+ __le32 ax_su_ndpa;
+ __le32 ax_su_ndp;
+ __le32 ax_mu_mimo_ndpa;
+ __le32 ax_mu_mimo_ndp;
+ __le32 ax_mu_mimo_brpoll[ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS - 1];
+ __le32 ax_basic_trigger;
+ __le32 ax_bsr_trigger;
+ __le32 ax_mu_bar_trigger;
+ __le32 ax_mu_rts_trigger;
+ __le32 ax_ulmumimo_trigger;
+} __packed;
+
+struct ath12k_htt_tx_selfgen_be_stats_tlv {
+ __le32 be_su_ndpa;
+ __le32 be_su_ndp;
+ __le32 be_mu_mimo_ndpa;
+ __le32 be_mu_mimo_ndp;
+ __le32 be_mu_mimo_brpoll[ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS - 1];
+ __le32 be_basic_trigger;
+ __le32 be_bsr_trigger;
+ __le32 be_mu_bar_trigger;
+ __le32 be_mu_rts_trigger;
+ __le32 be_ulmumimo_trigger;
+ __le32 be_su_ndpa_queued;
+ __le32 be_su_ndp_queued;
+ __le32 be_mu_mimo_ndpa_queued;
+ __le32 be_mu_mimo_ndp_queued;
+ __le32 be_mu_mimo_brpoll_queued[ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS - 1];
+ __le32 be_ul_mumimo_trigger[ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS];
+} __packed;
+
+struct ath12k_htt_tx_selfgen_ac_err_stats_tlv {
+ __le32 ac_su_ndp_err;
+ __le32 ac_su_ndpa_err;
+ __le32 ac_mu_mimo_ndpa_err;
+ __le32 ac_mu_mimo_ndp_err;
+ __le32 ac_mu_mimo_brp1_err;
+ __le32 ac_mu_mimo_brp2_err;
+ __le32 ac_mu_mimo_brp3_err;
+} __packed;
+
+struct ath12k_htt_tx_selfgen_ax_err_stats_tlv {
+ __le32 ax_su_ndp_err;
+ __le32 ax_su_ndpa_err;
+ __le32 ax_mu_mimo_ndpa_err;
+ __le32 ax_mu_mimo_ndp_err;
+ __le32 ax_mu_mimo_brp_err[ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS - 1];
+ __le32 ax_basic_trigger_err;
+ __le32 ax_bsr_trigger_err;
+ __le32 ax_mu_bar_trigger_err;
+ __le32 ax_mu_rts_trigger_err;
+ __le32 ax_ulmumimo_trigger_err;
+} __packed;
+
+struct ath12k_htt_tx_selfgen_be_err_stats_tlv {
+ __le32 be_su_ndp_err;
+ __le32 be_su_ndpa_err;
+ __le32 be_mu_mimo_ndpa_err;
+ __le32 be_mu_mimo_ndp_err;
+ __le32 be_mu_mimo_brp_err[ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS - 1];
+ __le32 be_basic_trigger_err;
+ __le32 be_bsr_trigger_err;
+ __le32 be_mu_bar_trigger_err;
+ __le32 be_mu_rts_trigger_err;
+ __le32 be_ulmumimo_trigger_err;
+ __le32 be_mu_mimo_brp_err_num_cbf_rxd[ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS];
+ __le32 be_su_ndpa_flushed;
+ __le32 be_su_ndp_flushed;
+ __le32 be_mu_mimo_ndpa_flushed;
+ __le32 be_mu_mimo_ndp_flushed;
+ __le32 be_mu_mimo_brpoll_flushed[ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS - 1];
+ __le32 be_ul_mumimo_trigger_err[ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS];
+} __packed;
+
+enum ath12k_htt_tx_selfgen_sch_tsflag_error_stats {
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_FLUSH_RCVD_ERR,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_FILT_SCHED_CMD_ERR,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_RESP_MISMATCH_ERR,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_RESP_CBF_MIMO_CTRL_MISMATCH_ERR,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_RESP_CBF_BW_MISMATCH_ERR,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_RETRY_COUNT_FAIL_ERR,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_RESP_TOO_LATE_RECEIVED_ERR,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_SIFS_STALL_NO_NEXT_CMD_ERR,
+
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS
+};
+
+struct ath12k_htt_tx_selfgen_ac_sched_status_stats_tlv {
+ __le32 ac_su_ndpa_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ac_su_ndp_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ac_su_ndp_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 ac_mu_mimo_ndpa_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ac_mu_mimo_ndp_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ac_mu_mimo_ndp_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 ac_mu_mimo_brp_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ac_mu_mimo_brp_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+} __packed;
+
+struct ath12k_htt_tx_selfgen_ax_sched_status_stats_tlv {
+ __le32 ax_su_ndpa_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ax_su_ndp_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ax_su_ndp_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 ax_mu_mimo_ndpa_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ax_mu_mimo_ndp_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ax_mu_mimo_ndp_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 ax_mu_brp_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ax_mu_brp_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 ax_mu_bar_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ax_mu_bar_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 ax_basic_trig_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ax_basic_trig_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 ax_ulmumimo_trig_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ax_ulmumimo_trig_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+} __packed;
+
+struct ath12k_htt_tx_selfgen_be_sched_status_stats_tlv {
+ __le32 be_su_ndpa_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 be_su_ndp_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 be_su_ndp_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 be_mu_mimo_ndpa_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 be_mu_mimo_ndp_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 be_mu_mimo_ndp_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 be_mu_brp_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 be_mu_brp_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 be_mu_bar_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 be_mu_bar_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 be_basic_trig_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 be_basic_trig_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 be_ulmumimo_trig_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 be_ulmumimo_trig_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+} __packed;
+
+struct ath12k_htt_stats_string_tlv {
+ DECLARE_FLEX_ARRAY(__le32, data);
+} __packed;
+
+#define ATH12K_HTT_SRING_STATS_MAC_ID GENMASK(7, 0)
+#define ATH12K_HTT_SRING_STATS_RING_ID GENMASK(15, 8)
+#define ATH12K_HTT_SRING_STATS_ARENA GENMASK(23, 16)
+#define ATH12K_HTT_SRING_STATS_EP BIT(24)
+#define ATH12K_HTT_SRING_STATS_NUM_AVAIL_WORDS GENMASK(15, 0)
+#define ATH12K_HTT_SRING_STATS_NUM_VALID_WORDS GENMASK(31, 16)
+#define ATH12K_HTT_SRING_STATS_HEAD_PTR GENMASK(15, 0)
+#define ATH12K_HTT_SRING_STATS_TAIL_PTR GENMASK(31, 16)
+#define ATH12K_HTT_SRING_STATS_CONSUMER_EMPTY GENMASK(15, 0)
+#define ATH12K_HTT_SRING_STATS_PRODUCER_FULL GENMASK(31, 16)
+#define ATH12K_HTT_SRING_STATS_PREFETCH_COUNT GENMASK(15, 0)
+#define ATH12K_HTT_SRING_STATS_INTERNAL_TAIL_PTR GENMASK(31, 16)
+
+struct ath12k_htt_sring_stats_tlv {
+ __le32 mac_id__ring_id__arena__ep;
+ __le32 base_addr_lsb;
+ __le32 base_addr_msb;
+ __le32 ring_size;
+ __le32 elem_size;
+ __le32 num_avail_words__num_valid_words;
+ __le32 head_ptr__tail_ptr;
+ __le32 consumer_empty__producer_full;
+ __le32 prefetch_count__internal_tail_ptr;
+} __packed;
+
+struct ath12k_htt_sfm_cmn_tlv {
+ __le32 mac_id__word;
+ __le32 buf_total;
+ __le32 mem_empty;
+ __le32 deallocate_bufs;
+ __le32 num_records;
+} __packed;
+
+struct ath12k_htt_sfm_client_tlv {
+ __le32 client_id;
+ __le32 buf_min;
+ __le32 buf_max;
+ __le32 buf_busy;
+ __le32 buf_alloc;
+ __le32 buf_avail;
+ __le32 num_users;
+} __packed;
+
+struct ath12k_htt_sfm_client_user_tlv {
+ DECLARE_FLEX_ARRAY(__le32, dwords_used_by_user_n);
+} __packed;
+
+struct ath12k_htt_tx_pdev_mu_mimo_sch_stats_tlv {
+ __le32 mu_mimo_sch_posted;
+ __le32 mu_mimo_sch_failed;
+ __le32 mu_mimo_ppdu_posted;
+ __le32 ac_mu_mimo_sch_nusers[ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS];
+ __le32 ax_mu_mimo_sch_nusers[ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS];
+ __le32 ax_ofdma_sch_nusers[ATH12K_HTT_TX_NUM_OFDMA_USER_STATS];
+ __le32 ax_ul_ofdma_nusers[ATH12K_HTT_TX_NUM_OFDMA_USER_STATS];
+ __le32 ax_ul_ofdma_bsr_nusers[ATH12K_HTT_TX_NUM_OFDMA_USER_STATS];
+ __le32 ax_ul_ofdma_bar_nusers[ATH12K_HTT_TX_NUM_OFDMA_USER_STATS];
+ __le32 ax_ul_ofdma_brp_nusers[ATH12K_HTT_TX_NUM_OFDMA_USER_STATS];
+ __le32 ax_ul_mumimo_nusers[ATH12K_HTT_TX_NUM_UL_MUMIMO_USER_STATS];
+ __le32 ax_ul_mumimo_brp_nusers[ATH12K_HTT_TX_NUM_UL_MUMIMO_USER_STATS];
+ __le32 ac_mu_mimo_per_grp_sz[ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS];
+ __le32 ax_mu_mimo_per_grp_sz[ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS];
+ __le32 be_mu_mimo_sch_nusers[ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS];
+ __le32 be_mu_mimo_per_grp_sz[ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS];
+ __le32 ac_mu_mimo_grp_sz_ext[ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS];
+} __packed;
+
+struct ath12k_htt_tx_pdev_mumimo_grp_stats_tlv {
+ __le32 dl_mumimo_grp_best_grp_size[ATH12K_HTT_STATS_NUM_MAX_MUMIMO_SZ];
+ __le32 dl_mumimo_grp_best_num_usrs[ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS];
+ __le32 dl_mumimo_grp_eligible[ATH12K_HTT_STATS_NUM_MAX_MUMIMO_SZ];
+ __le32 dl_mumimo_grp_ineligible[ATH12K_HTT_STATS_NUM_MAX_MUMIMO_SZ];
+ __le32 dl_mumimo_grp_invalid[ATH12K_HTT_TX_NUM_MUMIMO_GRP_INVALID_WORDS];
+ __le32 dl_mumimo_grp_tputs[ATH12K_HTT_STATS_MUMIMO_TPUT_NUM_BINS];
+ __le32 ul_mumimo_grp_best_grp_size[ATH12K_HTT_STATS_NUM_MAX_MUMIMO_SZ];
+ __le32 ul_mumimo_grp_best_usrs[ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS];
+ __le32 ul_mumimo_grp_tputs[ATH12K_HTT_STATS_MUMIMO_TPUT_NUM_BINS];
+} __packed;
+
+enum ath12k_htt_stats_tx_sched_modes {
+ ATH12K_HTT_STATS_TX_SCHED_MODE_MU_MIMO_AC = 0,
+ ATH12K_HTT_STATS_TX_SCHED_MODE_MU_MIMO_AX,
+ ATH12K_HTT_STATS_TX_SCHED_MODE_MU_OFDMA_AX,
+ ATH12K_HTT_STATS_TX_SCHED_MODE_MU_OFDMA_BE,
+ ATH12K_HTT_STATS_TX_SCHED_MODE_MU_MIMO_BE
+};
+
+struct ath12k_htt_tx_pdev_mpdu_stats_tlv {
+ __le32 mpdus_queued_usr;
+ __le32 mpdus_tried_usr;
+ __le32 mpdus_failed_usr;
+ __le32 mpdus_requeued_usr;
+ __le32 err_no_ba_usr;
+ __le32 mpdu_underrun_usr;
+ __le32 ampdu_underrun_usr;
+ __le32 user_index;
+ __le32 tx_sched_mode;
+} __packed;
+
+struct ath12k_htt_pdev_stats_cca_counters_tlv {
+ __le32 tx_frame_usec;
+ __le32 rx_frame_usec;
+ __le32 rx_clear_usec;
+ __le32 my_rx_frame_usec;
+ __le32 usec_cnt;
+ __le32 med_rx_idle_usec;
+ __le32 med_tx_idle_global_usec;
+ __le32 cca_obss_usec;
+} __packed;
+
+struct ath12k_htt_pdev_cca_stats_hist_v1_tlv {
+ __le32 chan_num;
+ __le32 num_records;
+ __le32 valid_cca_counters_bitmap;
+ __le32 collection_interval;
+} __packed;
+
+struct ath12k_htt_pdev_obss_pd_stats_tlv {
+ __le32 num_obss_tx_ppdu_success;
+ __le32 num_obss_tx_ppdu_failure;
+ __le32 num_sr_tx_transmissions;
+ __le32 num_spatial_reuse_opportunities;
+ __le32 num_non_srg_opportunities;
+ __le32 num_non_srg_ppdu_tried;
+ __le32 num_non_srg_ppdu_success;
+ __le32 num_srg_opportunities;
+ __le32 num_srg_ppdu_tried;
+ __le32 num_srg_ppdu_success;
+ __le32 num_psr_opportunities;
+ __le32 num_psr_ppdu_tried;
+ __le32 num_psr_ppdu_success;
+ __le32 num_non_srg_tried_per_ac[ATH12K_HTT_NUM_AC_WMM];
+ __le32 num_non_srg_success_ac[ATH12K_HTT_NUM_AC_WMM];
+ __le32 num_srg_tried_per_ac[ATH12K_HTT_NUM_AC_WMM];
+ __le32 num_srg_success_per_ac[ATH12K_HTT_NUM_AC_WMM];
+ __le32 num_obss_min_dur_check_flush_cnt;
+ __le32 num_sr_ppdu_abort_flush_cnt;
+} __packed;
+
+struct ath12k_htt_dmac_reset_stats_tlv {
+ __le32 reset_count;
+ __le32 reset_time_lo_ms;
+ __le32 reset_time_hi_ms;
+ __le32 disengage_time_lo_ms;
+ __le32 disengage_time_hi_ms;
+ __le32 engage_time_lo_ms;
+ __le32 engage_time_hi_ms;
+ __le32 disengage_count;
+ __le32 engage_count;
+ __le32 drain_dest_ring_mask;
+} __packed;
+
+struct ath12k_htt_pdev_sched_algo_ofdma_stats_tlv {
+ __le32 mac_id__word;
+ __le32 rate_based_dlofdma_enabled_cnt[ATH12K_HTT_NUM_AC_WMM];
+ __le32 rate_based_dlofdma_disabled_cnt[ATH12K_HTT_NUM_AC_WMM];
+ __le32 rate_based_dlofdma_probing_cnt[ATH12K_HTT_NUM_AC_WMM];
+ __le32 rate_based_dlofdma_monitor_cnt[ATH12K_HTT_NUM_AC_WMM];
+ __le32 chan_acc_lat_based_dlofdma_enabled_cnt[ATH12K_HTT_NUM_AC_WMM];
+ __le32 chan_acc_lat_based_dlofdma_disabled_cnt[ATH12K_HTT_NUM_AC_WMM];
+ __le32 chan_acc_lat_based_dlofdma_monitor_cnt[ATH12K_HTT_NUM_AC_WMM];
+ __le32 downgrade_to_dl_su_ru_alloc_fail[ATH12K_HTT_NUM_AC_WMM];
+ __le32 candidate_list_single_user_disable_ofdma[ATH12K_HTT_NUM_AC_WMM];
+ __le32 dl_cand_list_dropped_high_ul_qos_weight[ATH12K_HTT_NUM_AC_WMM];
+ __le32 ax_dlofdma_disabled_due_to_pipelining[ATH12K_HTT_NUM_AC_WMM];
+ __le32 dlofdma_disabled_su_only_eligible[ATH12K_HTT_NUM_AC_WMM];
+ __le32 dlofdma_disabled_consec_no_mpdus_tried[ATH12K_HTT_NUM_AC_WMM];
+ __le32 dlofdma_disabled_consec_no_mpdus_success[ATH12K_HTT_NUM_AC_WMM];
+} __packed;
+
+enum ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE {
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_26,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_52,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_52_26,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_106,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_106_26,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_242,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_484,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_484_242,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996_484,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996_484_242,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996x2,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996x2_484,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996x3,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996x3_484,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996x4,
+ ATH12K_HTT_TX_RX_PDEV_NUM_BE_RU_SIZE_CNTRS,
+};
+
+#define ATH12K_HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS 8
+#define ATH12K_HTT_TX_PDEV_NUM_BE_MCS_CNTRS 16
+#define ATH12K_HTT_TX_PDEV_NUM_BE_BW_CNTRS 5
+#define ATH12K_HTT_TX_PDEV_NUM_EHT_SIG_MCS_CNTRS 4
+#define ATH12K_HTT_TX_PDEV_NUM_GI_CNTRS 4
+
+struct ath12k_htt_tx_pdev_rate_stats_be_ofdma_tlv {
+ __le32 mac_id__word;
+ __le32 be_ofdma_tx_ldpc;
+ __le32 be_ofdma_tx_mcs[ATH12K_HTT_TX_PDEV_NUM_BE_MCS_CNTRS];
+ __le32 be_ofdma_tx_nss[ATH12K_HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS];
+ __le32 be_ofdma_tx_bw[ATH12K_HTT_TX_PDEV_NUM_BE_BW_CNTRS];
+ __le32 gi[ATH12K_HTT_TX_PDEV_NUM_GI_CNTRS][ATH12K_HTT_TX_PDEV_NUM_BE_MCS_CNTRS];
+ __le32 be_ofdma_tx_ru_size[ATH12K_HTT_TX_RX_PDEV_NUM_BE_RU_SIZE_CNTRS];
+ __le32 be_ofdma_eht_sig_mcs[ATH12K_HTT_TX_PDEV_NUM_EHT_SIG_MCS_CNTRS];
+} __packed;
+
#endif
diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c
index 61aa78d8bd8c..c99e9ceb1a6e 100644
--- a/drivers/net/wireless/ath/ath12k/dp.c
+++ b/drivers/net/wireless/ath/ath12k/dp.c
@@ -327,20 +327,22 @@ int ath12k_dp_srng_setup(struct ath12k_base *ab, struct dp_srng *ring,
}
static
-u32 ath12k_dp_tx_get_vdev_bank_config(struct ath12k_base *ab, struct ath12k_vif *arvif)
+u32 ath12k_dp_tx_get_vdev_bank_config(struct ath12k_base *ab,
+ struct ath12k_link_vif *arvif)
{
u32 bank_config = 0;
+ struct ath12k_vif *ahvif = arvif->ahvif;
/* Only valid for raw frames with HW crypto enabled.
* With SW crypto, mac80211 sets key per packet
*/
- if (arvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW &&
+ if (ahvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW &&
test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags))
bank_config |=
- u32_encode_bits(ath12k_dp_tx_get_encrypt_type(arvif->key_cipher),
+ u32_encode_bits(ath12k_dp_tx_get_encrypt_type(ahvif->key_cipher),
HAL_TX_BANK_CONFIG_ENCRYPT_TYPE);
- bank_config |= u32_encode_bits(arvif->tx_encap_type,
+ bank_config |= u32_encode_bits(ahvif->tx_encap_type,
HAL_TX_BANK_CONFIG_ENCAP_TYPE);
bank_config |= u32_encode_bits(0, HAL_TX_BANK_CONFIG_SRC_BUFFER_SWAP) |
u32_encode_bits(0, HAL_TX_BANK_CONFIG_LINK_META_SWAP) |
@@ -355,7 +357,7 @@ u32 ath12k_dp_tx_get_vdev_bank_config(struct ath12k_base *ab, struct ath12k_vif
HAL_TX_ADDRY_EN),
HAL_TX_BANK_CONFIG_ADDRY_EN);
- bank_config |= u32_encode_bits(ieee80211_vif_is_mesh(arvif->vif) ? 3 : 0,
+ bank_config |= u32_encode_bits(ieee80211_vif_is_mesh(ahvif->vif) ? 3 : 0,
HAL_TX_BANK_CONFIG_MESH_EN) |
u32_encode_bits(arvif->vdev_id_check_en,
HAL_TX_BANK_CONFIG_VDEV_ID_CHECK_EN);
@@ -365,7 +367,8 @@ u32 ath12k_dp_tx_get_vdev_bank_config(struct ath12k_base *ab, struct ath12k_vif
return bank_config;
}
-static int ath12k_dp_tx_get_bank_profile(struct ath12k_base *ab, struct ath12k_vif *arvif,
+static int ath12k_dp_tx_get_bank_profile(struct ath12k_base *ab,
+ struct ath12k_link_vif *arvif,
struct ath12k_dp *dp)
{
int bank_id = DP_INVALID_BANK_ID;
@@ -1099,9 +1102,9 @@ int ath12k_dp_htt_connect(struct ath12k_dp *dp)
return 0;
}
-static void ath12k_dp_update_vdev_search(struct ath12k_vif *arvif)
+static void ath12k_dp_update_vdev_search(struct ath12k_link_vif *arvif)
{
- switch (arvif->vdev_type) {
+ switch (arvif->ahvif->vdev_type) {
case WMI_VDEV_TYPE_STA:
/* TODO: Verify the search type and flags since ast hash
* is not part of peer mapv3
@@ -1120,7 +1123,7 @@ static void ath12k_dp_update_vdev_search(struct ath12k_vif *arvif)
}
}
-void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_vif *arvif)
+void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_link_vif *arvif)
{
struct ath12k_base *ab = ar->ab;
@@ -1162,7 +1165,7 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
spin_lock_bh(&dp->rx_desc_lock);
for (i = 0; i < ATH12K_NUM_RX_SPT_PAGES; i++) {
- desc_info = dp->spt_info->rxbaddr[i];
+ desc_info = dp->rxbaddr[i];
for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) {
if (!desc_info[j].in_use) {
@@ -1181,11 +1184,11 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
}
for (i = 0; i < ATH12K_NUM_RX_SPT_PAGES; i++) {
- if (!dp->spt_info->rxbaddr[i])
+ if (!dp->rxbaddr[i])
continue;
- kfree(dp->spt_info->rxbaddr[i]);
- dp->spt_info->rxbaddr[i] = NULL;
+ kfree(dp->rxbaddr[i]);
+ dp->rxbaddr[i] = NULL;
}
spin_unlock_bh(&dp->rx_desc_lock);
@@ -1202,10 +1205,16 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
if (!skb)
continue;
- skb_cb = ATH12K_SKB_CB(skb);
- ar = skb_cb->ar;
- if (atomic_dec_and_test(&ar->dp.num_tx_pending))
- wake_up(&ar->dp.tx_empty_waitq);
+ /* if we are unregistering, hw would've been destroyed and
+ * ar is no longer valid.
+ */
+ if (!(test_bit(ATH12K_FLAG_UNREGISTERING, &ab->dev_flags))) {
+ skb_cb = ATH12K_SKB_CB(skb);
+ ar = skb_cb->ar;
+
+ if (atomic_dec_and_test(&ar->dp.num_tx_pending))
+ wake_up(&ar->dp.tx_empty_waitq);
+ }
dma_unmap_single(ab->dev, ATH12K_SKB_CB(skb)->paddr,
skb->len, DMA_TO_DEVICE);
@@ -1220,11 +1229,11 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
for (i = 0; i < ATH12K_TX_SPT_PAGES_PER_POOL; i++) {
tx_spt_page = i + pool_id * ATH12K_TX_SPT_PAGES_PER_POOL;
- if (!dp->spt_info->txbaddr[tx_spt_page])
+ if (!dp->txbaddr[tx_spt_page])
continue;
- kfree(dp->spt_info->txbaddr[tx_spt_page]);
- dp->spt_info->txbaddr[tx_spt_page] = NULL;
+ kfree(dp->txbaddr[tx_spt_page]);
+ dp->txbaddr[tx_spt_page] = NULL;
}
spin_unlock_bh(&dp->tx_desc_lock[pool_id]);
@@ -1241,6 +1250,7 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
}
kfree(dp->spt_info);
+ dp->spt_info = NULL;
}
static void ath12k_dp_reoq_lut_cleanup(struct ath12k_base *ab)
@@ -1276,8 +1286,10 @@ void ath12k_dp_free(struct ath12k_base *ab)
ath12k_dp_rx_reo_cmd_list_cleanup(ab);
- for (i = 0; i < ab->hw_params->max_tx_ring; i++)
+ for (i = 0; i < ab->hw_params->max_tx_ring; i++) {
kfree(dp->tx_ring[i].tx_status);
+ dp->tx_ring[i].tx_status = NULL;
+ }
ath12k_dp_rx_free(ab);
/* Deinit any SOC level resource */
@@ -1415,7 +1427,7 @@ static int ath12k_dp_cc_desc_init(struct ath12k_base *ab)
ppt_idx = ATH12K_RX_SPT_PAGE_OFFSET + i;
cookie_ppt_idx = dp->rx_ppt_base + ppt_idx;
- dp->spt_info->rxbaddr[i] = &rx_descs[0];
+ dp->rxbaddr[i] = &rx_descs[0];
for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) {
rx_descs[j].cookie = ath12k_dp_cc_cookie_gen(cookie_ppt_idx, j);
@@ -1445,7 +1457,7 @@ static int ath12k_dp_cc_desc_init(struct ath12k_base *ab)
tx_spt_page = i + pool_id * ATH12K_TX_SPT_PAGES_PER_POOL;
ppt_idx = ATH12K_TX_SPT_PAGE_OFFSET + tx_spt_page;
- dp->spt_info->txbaddr[tx_spt_page] = &tx_descs[0];
+ dp->txbaddr[tx_spt_page] = &tx_descs[0];
for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) {
tx_descs[j].desc_id = ath12k_dp_cc_cookie_gen(ppt_idx, j);
diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h
index 2fb18b83b3ee..2e05fc19410e 100644
--- a/drivers/net/wireless/ath/ath12k/dp.h
+++ b/drivers/net/wireless/ath/ath12k/dp.h
@@ -16,6 +16,7 @@ struct ath12k_base;
struct ath12k_peer;
struct ath12k_dp;
struct ath12k_vif;
+struct ath12k_link_vif;
struct hal_tcl_status_ring;
struct ath12k_ext_irq_grp;
@@ -300,8 +301,6 @@ struct ath12k_tx_desc_info {
struct ath12k_spt_info {
dma_addr_t paddr;
u64 *vaddr;
- struct ath12k_rx_desc_info *rxbaddr[ATH12K_NUM_RX_SPT_PAGES];
- struct ath12k_tx_desc_info *txbaddr[ATH12K_NUM_TX_SPT_PAGES];
};
struct ath12k_reo_queue_ref {
@@ -352,6 +351,8 @@ struct ath12k_dp {
struct ath12k_spt_info *spt_info;
u32 num_spt_pages;
u32 rx_ppt_base;
+ struct ath12k_rx_desc_info *rxbaddr[ATH12K_NUM_RX_SPT_PAGES];
+ struct ath12k_tx_desc_info *txbaddr[ATH12K_NUM_TX_SPT_PAGES];
struct list_head rx_desc_free_list;
/* protects the free desc list */
spinlock_t rx_desc_lock;
@@ -1799,7 +1800,7 @@ int ath12k_dp_service_srng(struct ath12k_base *ab,
struct ath12k_ext_irq_grp *irq_grp,
int budget);
int ath12k_dp_htt_connect(struct ath12k_dp *dp);
-void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_vif *arvif);
+void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_link_vif *arvif);
void ath12k_dp_free(struct ath12k_base *ab);
int ath12k_dp_alloc(struct ath12k_base *ab);
void ath12k_dp_cc_config(struct ath12k_base *ab);
diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c
index 5c6749bc4039..494984133a91 100644
--- a/drivers/net/wireless/ath/ath12k/dp_mon.c
+++ b/drivers/net/wireless/ath/ath12k/dp_mon.c
@@ -26,15 +26,12 @@ ath12k_dp_mon_rx_populate_byte_count(const struct hal_rx_ppdu_end_user_stats *st
void *ppduinfo,
struct hal_rx_user_status *rx_user_status)
{
- u32 mpdu_ok_byte_count = __le32_to_cpu(stats->mpdu_ok_cnt);
- u32 mpdu_err_byte_count = __le32_to_cpu(stats->mpdu_err_cnt);
-
rx_user_status->mpdu_ok_byte_count =
- u32_get_bits(mpdu_ok_byte_count,
- HAL_RX_PPDU_END_USER_STATS_MPDU_DELIM_OK_BYTE_COUNT);
+ le32_get_bits(stats->info7,
+ HAL_RX_PPDU_END_USER_STATS_INFO7_MPDU_OK_BYTE_COUNT);
rx_user_status->mpdu_err_byte_count =
- u32_get_bits(mpdu_err_byte_count,
- HAL_RX_PPDU_END_USER_STATS_MPDU_DELIM_ERR_BYTE_COUNT);
+ le32_get_bits(stats->info8,
+ HAL_RX_PPDU_END_USER_STATS_INFO8_MPDU_ERR_BYTE_COUNT);
}
static void
@@ -593,12 +590,20 @@ ath12k_dp_mon_rx_parse_status_tlv(struct ath12k_base *ab,
struct hal_rx_ppdu_start *ppdu_start =
(struct hal_rx_ppdu_start *)tlv_data;
+ u64 ppdu_ts = ath12k_le32hilo_to_u64(ppdu_start->ppdu_start_ts_63_32,
+ ppdu_start->ppdu_start_ts_31_0);
+
info[0] = __le32_to_cpu(ppdu_start->info0);
- ppdu_info->ppdu_id =
- u32_get_bits(info[0], HAL_RX_PPDU_START_INFO0_PPDU_ID);
- ppdu_info->chan_num = __le32_to_cpu(ppdu_start->chan_num);
- ppdu_info->ppdu_ts = __le32_to_cpu(ppdu_start->ppdu_start_ts);
+ ppdu_info->ppdu_id = u32_get_bits(info[0],
+ HAL_RX_PPDU_START_INFO0_PPDU_ID);
+
+ info[1] = __le32_to_cpu(ppdu_start->info1);
+ ppdu_info->chan_num = u32_get_bits(info[1],
+ HAL_RX_PPDU_START_INFO1_CHAN_NUM);
+ ppdu_info->freq = u32_get_bits(info[1],
+ HAL_RX_PPDU_START_INFO1_CHAN_FREQ);
+ ppdu_info->ppdu_ts = ppdu_ts;
if (ppdu_info->ppdu_id != ppdu_info->last_ppdu_id) {
ppdu_info->last_ppdu_id = ppdu_info->ppdu_id;
@@ -726,33 +731,20 @@ ath12k_dp_mon_rx_parse_status_tlv(struct ath12k_base *ab,
case HAL_PHYRX_RSSI_LEGACY: {
struct hal_rx_phyrx_rssi_legacy_info *rssi =
(struct hal_rx_phyrx_rssi_legacy_info *)tlv_data;
- u32 reception_type = 0;
- u32 rssi_legacy_info = __le32_to_cpu(rssi->rsvd[0]);
info[0] = __le32_to_cpu(rssi->info0);
+ info[1] = __le32_to_cpu(rssi->info1);
/* TODO: Please note that the combined rssi will not be accurate
* in MU case. Rssi in MU needs to be retrieved from
* PHYRX_OTHER_RECEIVE_INFO TLV.
*/
ppdu_info->rssi_comb =
- u32_get_bits(info[0],
- HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RSSI_COMB);
- reception_type =
- u32_get_bits(rssi_legacy_info,
- HAL_RX_PHYRX_RSSI_LEGACY_INFO_RSVD1_RECEPTION);
-
- switch (reception_type) {
- case HAL_RECEPTION_TYPE_ULOFMDA:
- ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_MU_OFDMA;
- break;
- case HAL_RECEPTION_TYPE_ULMIMO:
- ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_MU_MIMO;
- break;
- default:
- ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_SU;
- break;
- }
+ u32_get_bits(info[1],
+ HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO1_RSSI_COMB);
+
+ ppdu_info->bw = u32_get_bits(info[0],
+ HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RX_BW);
break;
}
case HAL_RXPCU_PPDU_END_INFO: {
@@ -860,27 +852,29 @@ ath12k_dp_mon_rx_parse_status_tlv(struct ath12k_base *ab,
return HAL_RX_MON_STATUS_PPDU_NOT_DONE;
}
-static void ath12k_dp_mon_rx_msdus_set_payload(struct ath12k *ar, struct sk_buff *msdu)
+static void ath12k_dp_mon_rx_msdus_set_payload(struct ath12k *ar,
+ struct sk_buff *head_msdu,
+ struct sk_buff *tail_msdu)
{
u32 rx_pkt_offset, l2_hdr_offset;
rx_pkt_offset = ar->ab->hal.hal_desc_sz;
- l2_hdr_offset = ath12k_dp_rx_h_l3pad(ar->ab,
- (struct hal_rx_desc *)msdu->data);
- skb_pull(msdu, rx_pkt_offset + l2_hdr_offset);
+ l2_hdr_offset =
+ ath12k_dp_rx_h_l3pad(ar->ab, (struct hal_rx_desc *)tail_msdu->data);
+ skb_pull(head_msdu, rx_pkt_offset + l2_hdr_offset);
}
static struct sk_buff *
-ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
- u32 mac_id, struct sk_buff *head_msdu,
+ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar, u32 mac_id,
+ struct sk_buff *head_msdu, struct sk_buff *tail_msdu,
struct ieee80211_rx_status *rxs, bool *fcs_err)
{
struct ath12k_base *ab = ar->ab;
- struct sk_buff *msdu, *mpdu_buf, *prev_buf;
- struct hal_rx_desc *rx_desc;
+ struct sk_buff *msdu, *mpdu_buf, *prev_buf, *head_frag_list;
+ struct hal_rx_desc *rx_desc, *tail_rx_desc;
u8 *hdr_desc, *dest, decap_format;
struct ieee80211_hdr_3addr *wh;
- u32 err_bitmap;
+ u32 err_bitmap, frag_list_sum_len = 0;
mpdu_buf = NULL;
@@ -888,24 +882,30 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
goto err_merge_fail;
rx_desc = (struct hal_rx_desc *)head_msdu->data;
- err_bitmap = ath12k_dp_rx_h_mpdu_err(ab, rx_desc);
+ tail_rx_desc = (struct hal_rx_desc *)tail_msdu->data;
+ err_bitmap = ath12k_dp_rx_h_mpdu_err(ab, tail_rx_desc);
if (err_bitmap & HAL_RX_MPDU_ERR_FCS)
*fcs_err = true;
- decap_format = ath12k_dp_rx_h_decap_type(ab, rx_desc);
+ decap_format = ath12k_dp_rx_h_decap_type(ab, tail_rx_desc);
- ath12k_dp_rx_h_ppdu(ar, rx_desc, rxs);
+ ath12k_dp_rx_h_ppdu(ar, tail_rx_desc, rxs);
if (decap_format == DP_RX_DECAP_TYPE_RAW) {
- ath12k_dp_mon_rx_msdus_set_payload(ar, head_msdu);
+ ath12k_dp_mon_rx_msdus_set_payload(ar, head_msdu, tail_msdu);
prev_buf = head_msdu;
msdu = head_msdu->next;
+ head_frag_list = NULL;
while (msdu) {
- ath12k_dp_mon_rx_msdus_set_payload(ar, msdu);
+ ath12k_dp_mon_rx_msdus_set_payload(ar, msdu, tail_msdu);
+
+ if (!head_frag_list)
+ head_frag_list = msdu;
+ frag_list_sum_len += msdu->len;
prev_buf = msdu;
msdu = msdu->next;
}
@@ -913,6 +913,12 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
prev_buf->next = NULL;
skb_trim(prev_buf, prev_buf->len - HAL_RX_FCS_LEN);
+ if (head_frag_list) {
+ skb_shinfo(head_msdu)->frag_list = head_frag_list;
+ head_msdu->data_len = frag_list_sum_len;
+ head_msdu->len += head_msdu->data_len;
+ head_msdu->next = NULL;
+ }
} else if (decap_format == DP_RX_DECAP_TYPE_NATIVE_WIFI) {
u8 qos_pkt = 0;
@@ -929,7 +935,7 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
msdu = head_msdu;
while (msdu) {
- ath12k_dp_mon_rx_msdus_set_payload(ar, msdu);
+ ath12k_dp_mon_rx_msdus_set_payload(ar, msdu, tail_msdu);
if (qos_pkt) {
dest = skb_push(msdu, sizeof(__le16));
if (!dest)
@@ -1135,7 +1141,7 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k *ar, struct napi_struct
}
static int ath12k_dp_mon_rx_deliver(struct ath12k *ar, u32 mac_id,
- struct sk_buff *head_msdu,
+ struct sk_buff *head_msdu, struct sk_buff *tail_msdu,
struct hal_rx_mon_ppdu_info *ppduinfo,
struct napi_struct *napi)
{
@@ -1144,7 +1150,8 @@ static int ath12k_dp_mon_rx_deliver(struct ath12k *ar, u32 mac_id,
struct ieee80211_rx_status *rxs = &dp->rx_status;
bool fcs_err = false;
- mon_skb = ath12k_dp_mon_rx_merg_msdus(ar, mac_id, head_msdu,
+ mon_skb = ath12k_dp_mon_rx_merg_msdus(ar, mac_id,
+ head_msdu, tail_msdu,
rxs, &fcs_err);
if (!mon_skb)
goto mon_deliver_fail;
@@ -1252,7 +1259,7 @@ ath12k_dp_mon_rx_parse_mon_status(struct ath12k *ar,
if (head_msdu && tail_msdu) {
ath12k_dp_mon_rx_deliver(ar, mac_id, head_msdu,
- ppdu_info, napi);
+ tail_msdu, ppdu_info, napi);
}
kfree(mon_mpdu);
@@ -1948,15 +1955,16 @@ ath12k_dp_mon_tx_process_ppdu_info(struct ath12k *ar, int mac_id,
struct dp_mon_tx_ppdu_info *tx_ppdu_info)
{
struct dp_mon_mpdu *tmp, *mon_mpdu;
- struct sk_buff *head_msdu;
+ struct sk_buff *head_msdu, *tail_msdu;
list_for_each_entry_safe(mon_mpdu, tmp,
&tx_ppdu_info->dp_tx_mon_mpdu_list, list) {
list_del(&mon_mpdu->list);
head_msdu = mon_mpdu->head;
+ tail_msdu = mon_mpdu->tail;
if (head_msdu)
- ath12k_dp_mon_rx_deliver(ar, mac_id, head_msdu,
+ ath12k_dp_mon_rx_deliver(ar, mac_id, head_msdu, tail_msdu,
&tx_ppdu_info->rx_status, napi);
kfree(mon_mpdu);
@@ -2165,7 +2173,7 @@ ath12k_dp_mon_rx_update_peer_rate_table_stats(struct ath12k_rx_peer_stats *rx_st
}
static void ath12k_dp_mon_rx_update_peer_su_stats(struct ath12k *ar,
- struct ath12k_sta *arsta,
+ struct ath12k_link_sta *arsta,
struct hal_rx_mon_ppdu_info *ppdu_info)
{
struct ath12k_rx_peer_stats *rx_stats = arsta->rx_stats;
@@ -2321,7 +2329,8 @@ ath12k_dp_mon_rx_update_user_stats(struct ath12k *ar,
struct hal_rx_mon_ppdu_info *ppdu_info,
u32 uid)
{
- struct ath12k_sta *arsta = NULL;
+ struct ath12k_sta *ahsta;
+ struct ath12k_link_sta *arsta;
struct ath12k_rx_peer_stats *rx_stats = NULL;
struct hal_rx_user_status *user_stats = &ppdu_info->userstats[uid];
struct ath12k_peer *peer;
@@ -2338,7 +2347,8 @@ ath12k_dp_mon_rx_update_user_stats(struct ath12k *ar,
return;
}
- arsta = ath12k_sta_to_arsta(peer->sta);
+ ahsta = ath12k_sta_to_ahsta(peer->sta);
+ arsta = &ahsta->deflink;
rx_stats = arsta->rx_stats;
if (!rx_stats)
@@ -2445,7 +2455,8 @@ int ath12k_dp_mon_rx_process_stats(struct ath12k *ar, int mac_id,
struct dp_srng *mon_dst_ring;
struct hal_srng *srng;
struct dp_rxdma_mon_ring *buf_ring;
- struct ath12k_sta *arsta = NULL;
+ struct ath12k_sta *ahsta = NULL;
+ struct ath12k_link_sta *arsta;
struct ath12k_peer *peer;
u64 cookie;
int num_buffs_reaped = 0, srng_id, buf_id;
@@ -2514,7 +2525,8 @@ int ath12k_dp_mon_rx_process_stats(struct ath12k *ar, int mac_id,
}
if (ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_SU) {
- arsta = ath12k_sta_to_arsta(peer->sta);
+ ahsta = ath12k_sta_to_ahsta(peer->sta);
+ arsta = &ahsta->deflink;
ath12k_dp_mon_rx_update_peer_su_stats(ar, arsta,
ppdu_info);
} else if ((ppdu_info->fc_valid) &&
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c
index 91e3393f7b5f..9ae579e50557 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
@@ -1041,13 +1041,14 @@ int ath12k_dp_rx_ampdu_start(struct ath12k *ar,
struct ieee80211_ampdu_params *params)
{
struct ath12k_base *ab = ar->ab;
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(params->sta);
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(params->sta);
+ struct ath12k_link_sta *arsta = &ahsta->deflink;
int vdev_id = arsta->arvif->vdev_id;
int ret;
ret = ath12k_dp_rx_peer_tid_setup(ar, params->sta->addr, vdev_id,
params->tid, params->buf_size,
- params->ssn, arsta->pn_type);
+ params->ssn, arsta->ahsta->pn_type);
if (ret)
ath12k_warn(ab, "failed to setup rx tid %d\n", ret);
@@ -1059,7 +1060,8 @@ int ath12k_dp_rx_ampdu_stop(struct ath12k *ar,
{
struct ath12k_base *ab = ar->ab;
struct ath12k_peer *peer;
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(params->sta);
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(params->sta);
+ struct ath12k_link_sta *arsta = &ahsta->deflink;
int vdev_id = arsta->arvif->vdev_id;
bool active;
int ret;
@@ -1091,7 +1093,7 @@ int ath12k_dp_rx_ampdu_stop(struct ath12k *ar,
return ret;
}
-int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_vif *arvif,
+int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif,
const u8 *peer_addr,
enum set_key_cmd key_cmd,
struct ieee80211_key_conf *key)
@@ -1313,7 +1315,8 @@ ath12k_update_per_peer_tx_stats(struct ath12k *ar,
struct ath12k_base *ab = ar->ab;
struct ath12k_peer *peer;
struct ieee80211_sta *sta;
- struct ath12k_sta *arsta;
+ struct ath12k_sta *ahsta;
+ struct ath12k_link_sta *arsta;
struct htt_ppdu_stats_user_rate *user_rate;
struct ath12k_per_peer_tx_stats *peer_stats = &ar->peer_tx_stats;
struct htt_ppdu_user_stats *usr_stats = &ppdu_stats->user_stats[user];
@@ -1394,7 +1397,8 @@ ath12k_update_per_peer_tx_stats(struct ath12k *ar,
}
sta = peer->sta;
- arsta = ath12k_sta_to_arsta(sta);
+ ahsta = ath12k_sta_to_ahsta(sta);
+ arsta = &ahsta->deflink;
memset(&arsta->txrate, 0, sizeof(arsta->txrate));
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.h b/drivers/net/wireless/ath/ath12k/dp_rx.h
index eb1f92559179..bfd4f814553e 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.h
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.h
@@ -88,7 +88,7 @@ int ath12k_dp_rx_ampdu_start(struct ath12k *ar,
struct ieee80211_ampdu_params *params);
int ath12k_dp_rx_ampdu_stop(struct ath12k *ar,
struct ieee80211_ampdu_params *params);
-int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_vif *arvif,
+int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif,
const u8 *peer_addr,
enum set_key_cmd key_cmd,
struct ieee80211_key_conf *key);
diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c
index 44406e0b4a34..a8d341a6df01 100644
--- a/drivers/net/wireless/ath/ath12k/dp_tx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_tx.c
@@ -10,7 +10,7 @@
#include "hw.h"
static enum hal_tcl_encap_type
-ath12k_dp_tx_get_encap_type(struct ath12k_vif *arvif, struct sk_buff *skb)
+ath12k_dp_tx_get_encap_type(struct ath12k_link_vif *arvif, struct sk_buff *skb)
{
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ath12k_base *ab = arvif->ar->ab;
@@ -216,7 +216,7 @@ out:
return ret;
}
-int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif,
+int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
struct sk_buff *skb)
{
struct ath12k_base *ab = ar->ab;
@@ -230,6 +230,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif,
struct sk_buff *skb_ext_desc;
struct hal_srng *tcl_ring;
struct ieee80211_hdr *hdr = (void *)skb->data;
+ struct ath12k_vif *ahvif = arvif->ahvif;
struct dp_tx_ring *tx_ring;
u8 pool_id;
u8 hal_ring_id;
@@ -274,7 +275,7 @@ tcl_ring_sel:
ti.bank_id = arvif->bank_id;
ti.meta_data_flags = arvif->tcl_metadata;
- if (arvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW &&
+ if (ahvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW &&
test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags)) {
if (skb_cb->flags & ATH12K_SKB_CIPHER_SET) {
ti.encrypt_type =
@@ -376,7 +377,7 @@ map:
ti.desc_id = tx_desc->desc_id;
ti.data_len = skb->len;
skb_cb->paddr = ti.paddr;
- skb_cb->vif = arvif->vif;
+ skb_cb->vif = ahvif->vif;
skb_cb->ar = ar;
if (msdu_ext_desc) {
diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.h b/drivers/net/wireless/ath/ath12k/dp_tx.h
index 55ff8cc721e3..46dce23501f3 100644
--- a/drivers/net/wireless/ath/ath12k/dp_tx.h
+++ b/drivers/net/wireless/ath/ath12k/dp_tx.h
@@ -16,7 +16,7 @@ struct ath12k_dp_htt_wbm_tx_status {
};
int ath12k_dp_tx_htt_h2t_ver_req_msg(struct ath12k_base *ab);
-int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif,
+int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
struct sk_buff *skb);
void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id);
diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c
index ca04bfae8bdc..fd98fac16dd5 100644
--- a/drivers/net/wireless/ath/ath12k/hal.c
+++ b/drivers/net/wireless/ath/ath12k/hal.c
@@ -385,13 +385,13 @@ static u8 ath12k_hw_qcn9274_rx_desc_get_msdu_pkt_type(struct hal_rx_desc *desc)
static u8 ath12k_hw_qcn9274_rx_desc_get_msdu_nss(struct hal_rx_desc *desc)
{
return le32_get_bits(desc->u.qcn9274.msdu_end.info12,
- RX_MSDU_END_QCN9274_INFO12_MIMO_SS_BITMAP);
+ RX_MSDU_END_INFO12_MIMO_SS_BITMAP);
}
static u8 ath12k_hw_qcn9274_rx_desc_get_mpdu_tid(struct hal_rx_desc *desc)
{
return le16_get_bits(desc->u.qcn9274.msdu_end.info5,
- RX_MSDU_END_QCN9274_INFO5_TID);
+ RX_MSDU_END_INFO5_TID);
}
static u16 ath12k_hw_qcn9274_rx_desc_get_mpdu_peer_id(struct hal_rx_desc *desc)
@@ -846,13 +846,13 @@ static u8 ath12k_hw_qcn9274_compact_rx_desc_get_msdu_pkt_type(struct hal_rx_desc
static u8 ath12k_hw_qcn9274_compact_rx_desc_get_msdu_nss(struct hal_rx_desc *desc)
{
return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info12,
- RX_MSDU_END_QCN9274_INFO12_MIMO_SS_BITMAP);
+ RX_MSDU_END_INFO12_MIMO_SS_BITMAP);
}
static u8 ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_tid(struct hal_rx_desc *desc)
{
return le16_get_bits(desc->u.qcn9274_compact.msdu_end.info5,
- RX_MSDU_END_QCN9274_INFO5_TID);
+ RX_MSDU_END_INFO5_TID);
}
static u16 ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_peer_id(struct hal_rx_desc *desc)
@@ -1198,7 +1198,7 @@ static u8 ath12k_hw_wcn7850_rx_desc_get_msdu_pkt_type(struct hal_rx_desc *desc)
static u8 ath12k_hw_wcn7850_rx_desc_get_msdu_nss(struct hal_rx_desc *desc)
{
return le32_get_bits(desc->u.wcn7850.msdu_end.info12,
- RX_MSDU_END_WCN7850_INFO12_MIMO_SS_BITMAP);
+ RX_MSDU_END_INFO12_MIMO_SS_BITMAP);
}
static u8 ath12k_hw_wcn7850_rx_desc_get_mpdu_tid(struct hal_rx_desc *desc)
@@ -1216,7 +1216,7 @@ static void ath12k_hw_wcn7850_rx_desc_copy_end_tlv(struct hal_rx_desc *fdesc,
struct hal_rx_desc *ldesc)
{
memcpy(&fdesc->u.wcn7850.msdu_end, &ldesc->u.wcn7850.msdu_end,
- sizeof(struct rx_msdu_end_wcn7850));
+ sizeof(struct rx_msdu_end_qcn9274));
}
static u32 ath12k_hw_wcn7850_rx_desc_get_mpdu_start_tag(struct hal_rx_desc *desc)
diff --git a/drivers/net/wireless/ath/ath12k/hal_rx.h b/drivers/net/wireless/ath/ath12k/hal_rx.h
index 095216eabc01..2de7b0eba9f2 100644
--- a/drivers/net/wireless/ath/ath12k/hal_rx.h
+++ b/drivers/net/wireless/ath/ath12k/hal_rx.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef ATH12K_HAL_RX_H
@@ -156,6 +156,7 @@ struct hal_rx_mon_ppdu_info {
u32 preamble_type;
u32 mpdu_len;
u16 chan_num;
+ u16 freq;
u16 tcp_msdu_count;
u16 tcp_ack_msdu_count;
u16 udp_msdu_count;
@@ -232,21 +233,25 @@ struct hal_rx_mon_ppdu_info {
u8 medium_prot_type;
};
-#define HAL_RX_PPDU_START_INFO0_PPDU_ID GENMASK(15, 0)
+#define HAL_RX_PPDU_START_INFO0_PPDU_ID GENMASK(15, 0)
+#define HAL_RX_PPDU_START_INFO1_CHAN_NUM GENMASK(15, 0)
+#define HAL_RX_PPDU_START_INFO1_CHAN_FREQ GENMASK(31, 16)
struct hal_rx_ppdu_start {
__le32 info0;
- __le32 chan_num;
- __le32 ppdu_start_ts;
+ __le32 info1;
+ __le32 ppdu_start_ts_31_0;
+ __le32 ppdu_start_ts_63_32;
+ __le32 rsvd[2];
} __packed;
-#define HAL_RX_PPDU_END_USER_STATS_INFO0_MPDU_CNT_FCS_ERR GENMASK(25, 16)
+#define HAL_RX_PPDU_END_USER_STATS_INFO0_MPDU_CNT_FCS_ERR GENMASK(26, 16)
-#define HAL_RX_PPDU_END_USER_STATS_INFO1_MPDU_CNT_FCS_OK GENMASK(8, 0)
-#define HAL_RX_PPDU_END_USER_STATS_INFO1_FC_VALID BIT(9)
-#define HAL_RX_PPDU_END_USER_STATS_INFO1_QOS_CTRL_VALID BIT(10)
-#define HAL_RX_PPDU_END_USER_STATS_INFO1_HT_CTRL_VALID BIT(11)
-#define HAL_RX_PPDU_END_USER_STATS_INFO1_PKT_TYPE GENMASK(23, 20)
+#define HAL_RX_PPDU_END_USER_STATS_INFO1_MPDU_CNT_FCS_OK GENMASK(10, 0)
+#define HAL_RX_PPDU_END_USER_STATS_INFO1_FC_VALID BIT(11)
+#define HAL_RX_PPDU_END_USER_STATS_INFO1_QOS_CTRL_VALID BIT(12)
+#define HAL_RX_PPDU_END_USER_STATS_INFO1_HT_CTRL_VALID BIT(13)
+#define HAL_RX_PPDU_END_USER_STATS_INFO1_PKT_TYPE GENMASK(24, 21)
#define HAL_RX_PPDU_END_USER_STATS_INFO2_AST_INDEX GENMASK(15, 0)
#define HAL_RX_PPDU_END_USER_STATS_INFO2_FRAME_CTRL GENMASK(31, 16)
@@ -262,8 +267,8 @@ struct hal_rx_ppdu_start {
#define HAL_RX_PPDU_END_USER_STATS_INFO6_TID_BITMAP GENMASK(15, 0)
#define HAL_RX_PPDU_END_USER_STATS_INFO6_TID_EOSP_BITMAP GENMASK(31, 16)
-#define HAL_RX_PPDU_END_USER_STATS_MPDU_DELIM_OK_BYTE_COUNT GENMASK(24, 0)
-#define HAL_RX_PPDU_END_USER_STATS_MPDU_DELIM_ERR_BYTE_COUNT GENMASK(24, 0)
+#define HAL_RX_PPDU_END_USER_STATS_INFO7_MPDU_OK_BYTE_COUNT GENMASK(24, 0)
+#define HAL_RX_PPDU_END_USER_STATS_INFO8_MPDU_ERR_BYTE_COUNT GENMASK(24, 0)
struct hal_rx_ppdu_end_user_stats {
__le32 rsvd0[2];
@@ -278,9 +283,9 @@ struct hal_rx_ppdu_end_user_stats {
__le32 usr_resp_ref;
__le32 info6;
__le32 rsvd3[4];
- __le32 mpdu_ok_cnt;
+ __le32 info7;
__le32 rsvd4;
- __le32 mpdu_err_cnt;
+ __le32 info8;
__le32 rsvd5[2];
__le32 usr_resp_ref_ext;
__le32 rsvd6;
@@ -436,23 +441,27 @@ enum hal_rx_ul_reception_type {
HAL_RECEPTION_TYPE_FRAMELESS
};
-#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RSSI_COMB GENMASK(15, 8)
-#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_RSVD1_RECEPTION GENMASK(3, 0)
+#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RECEPTION GENMASK(3, 0)
+#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RX_BW GENMASK(7, 5)
+#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO1_RSSI_COMB GENMASK(15, 8)
struct hal_rx_phyrx_rssi_legacy_info {
- __le32 rsvd[35];
__le32 info0;
+ __le32 rsvd0[39];
+ __le32 info1;
+ __le32 rsvd1;
} __packed;
-#define HAL_RX_MPDU_START_INFO0_PPDU_ID GENMASK(31, 16)
-#define HAL_RX_MPDU_START_INFO1_PEERID GENMASK(31, 16)
-#define HAL_RX_MPDU_START_INFO2_MPDU_LEN GENMASK(13, 0)
+#define HAL_RX_MPDU_START_INFO0_PPDU_ID GENMASK(31, 16)
+#define HAL_RX_MPDU_START_INFO1_PEERID GENMASK(31, 16)
+#define HAL_RX_MPDU_START_INFO2_MPDU_LEN GENMASK(13, 0)
struct hal_rx_mpdu_start {
+ __le32 rsvd0[9];
__le32 info0;
__le32 info1;
- __le32 rsvd1[11];
+ __le32 rsvd1[2];
__le32 info2;
- __le32 rsvd2[9];
+ __le32 rsvd2[16];
} __packed;
#define HAL_RX_PPDU_END_DURATION GENMASK(23, 0)
diff --git a/drivers/net/wireless/ath/ath12k/hif.h b/drivers/net/wireless/ath/ath12k/hif.h
index 0e53ec269fa4..e8840fab6061 100644
--- a/drivers/net/wireless/ath/ath12k/hif.h
+++ b/drivers/net/wireless/ath/ath12k/hif.h
@@ -31,6 +31,7 @@ struct ath12k_hif_ops {
void (*ce_irq_disable)(struct ath12k_base *ab);
void (*get_ce_msi_idx)(struct ath12k_base *ab, u32 ce_id, u32 *msi_idx);
int (*panic_handler)(struct ath12k_base *ab);
+ void (*coredump_download)(struct ath12k_base *ab);
};
static inline int ath12k_hif_map_service_to_pipe(struct ath12k_base *ab, u16 service_id,
@@ -156,4 +157,9 @@ static inline int ath12k_hif_panic_handler(struct ath12k_base *ab)
return ab->hif.ops->panic_handler(ab);
}
+static inline void ath12k_hif_coredump_download(struct ath12k_base *ab)
+{
+ if (ab->hif.ops->coredump_download)
+ ab->hif.ops->coredump_download(ab);
+}
#endif /* ATH12K_HIF_H */
diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c
index ec1bda95e555..b7b583fadb5a 100644
--- a/drivers/net/wireless/ath/ath12k/hw.c
+++ b/drivers/net/wireless/ath/ath12k/hw.c
@@ -913,7 +913,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
.rfkill_cfg = 0,
.rfkill_on_level = 0,
- .rddm_size = 0,
+ .rddm_size = 0x600000,
.def_num_link = 0,
.max_mlo_peer = 256,
@@ -1069,7 +1069,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
.rfkill_cfg = 0,
.rfkill_on_level = 0,
- .rddm_size = 0,
+ .rddm_size = 0x600000,
.def_num_link = 0,
.max_mlo_peer = 256,
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 137394c36460..d493ec812055 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -250,10 +250,10 @@ static const u32 ath12k_smps_map[] = {
};
static int ath12k_start_vdev_delay(struct ath12k *ar,
- struct ath12k_vif *arvif);
+ struct ath12k_link_vif *arvif);
static void ath12k_mac_stop(struct ath12k *ar);
-static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif);
-static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ieee80211_vif *vif);
+static int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif);
+static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ath12k_link_vif *arvif);
static const char *ath12k_mac_phymode_str(enum wmi_phy_mode mode)
{
@@ -476,18 +476,25 @@ static u8 ath12k_parse_mpdudensity(u8 mpdudensity)
}
}
-static int ath12k_mac_vif_chan(struct ieee80211_vif *vif,
- struct cfg80211_chan_def *def)
+static int ath12k_mac_vif_link_chan(struct ieee80211_vif *vif, u8 link_id,
+ struct cfg80211_chan_def *def)
{
+ struct ieee80211_bss_conf *link_conf;
struct ieee80211_chanctx_conf *conf;
rcu_read_lock();
- conf = rcu_dereference(vif->bss_conf.chanctx_conf);
+ link_conf = rcu_dereference(vif->link_conf[link_id]);
+
+ if (!link_conf) {
+ rcu_read_unlock();
+ return -ENOLINK;
+ }
+
+ conf = rcu_dereference(link_conf->chanctx_conf);
if (!conf) {
rcu_read_unlock();
return -ENOENT;
}
-
*def = conf->def;
rcu_read_unlock();
@@ -539,18 +546,33 @@ static void ath12k_get_arvif_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
struct ath12k_vif_iter *arvif_iter = data;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ unsigned long links_map = ahvif->links_map;
+ struct ath12k_link_vif *arvif;
+ u8 link_id;
+
+ for_each_set_bit(link_id, &links_map, IEEE80211_MLD_MAX_NUM_LINKS) {
+ arvif = rcu_dereference(ahvif->link[link_id]);
+
+ if (WARN_ON(!arvif))
+ continue;
- if (arvif->vdev_id == arvif_iter->vdev_id &&
- arvif->ar == arvif_iter->ar)
- arvif_iter->arvif = arvif;
+ if (arvif->vdev_id == arvif_iter->vdev_id &&
+ arvif->ar == arvif_iter->ar) {
+ arvif_iter->arvif = arvif;
+ break;
+ }
+ }
}
-struct ath12k_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id)
+struct ath12k_link_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id)
{
struct ath12k_vif_iter arvif_iter = {};
u32 flags;
+ /* To use the arvif returned, caller must have held rcu read lock.
+ */
+ WARN_ON(!rcu_read_lock_any_held());
arvif_iter.vdev_id = vdev_id;
arvif_iter.ar = ar;
@@ -567,12 +589,12 @@ struct ath12k_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id)
return arvif_iter.arvif;
}
-struct ath12k_vif *ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base *ab,
- u32 vdev_id)
+struct ath12k_link_vif *ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base *ab,
+ u32 vdev_id)
{
int i;
struct ath12k_pdev *pdev;
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
for (i = 0; i < ab->num_radios; i++) {
pdev = rcu_dereference(ab->pdevs_active[i]);
@@ -658,7 +680,8 @@ static struct ath12k *ath12k_get_ar_by_ctx(struct ieee80211_hw *hw,
static struct ath12k *ath12k_get_ar_by_vif(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif = &ahvif->deflink;
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
/* If there is one pdev within ah, then we return
@@ -673,11 +696,12 @@ static struct ath12k *ath12k_get_ar_by_vif(struct ieee80211_hw *hw,
return NULL;
}
-static struct ath12k_vif *ath12k_mac_get_vif_up(struct ath12k *ar)
+static struct ath12k_link_vif *ath12k_mac_get_vif_up(struct ath12k *ar)
{
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
+
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- lockdep_assert_held(&ar->conf_mutex);
list_for_each_entry(arvif, &ar->arvifs, list) {
if (arvif->is_up)
return arvif;
@@ -705,17 +729,17 @@ static bool ath12k_mac_band_match(enum nl80211_band band1, enum WMI_HOST_WLAN_BA
return false;
}
-static u8 ath12k_mac_get_target_pdev_id_from_vif(struct ath12k_vif *arvif)
+static u8 ath12k_mac_get_target_pdev_id_from_vif(struct ath12k_link_vif *arvif)
{
struct ath12k *ar = arvif->ar;
struct ath12k_base *ab = ar->ab;
- struct ieee80211_vif *vif = arvif->vif;
+ struct ieee80211_vif *vif = arvif->ahvif->vif;
struct cfg80211_chan_def def;
enum nl80211_band band;
u8 pdev_id = ab->fw_pdev[0].pdev_id;
int i;
- if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
+ if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return pdev_id;
band = def.chan->band;
@@ -730,7 +754,7 @@ static u8 ath12k_mac_get_target_pdev_id_from_vif(struct ath12k_vif *arvif)
u8 ath12k_mac_get_target_pdev_id(struct ath12k *ar)
{
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
struct ath12k_base *ab = ar->ab;
if (!ab->hw_params->single_pdev_only)
@@ -770,11 +794,11 @@ static void ath12k_pdev_caps_update(struct ath12k *ar)
static int ath12k_mac_txpower_recalc(struct ath12k *ar)
{
struct ath12k_pdev *pdev = ar->pdev;
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
int ret, txpower = -1;
u32 param;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
if (arvif->txpower <= 0)
@@ -824,13 +848,13 @@ fail:
return ret;
}
-static int ath12k_recalc_rtscts_prot(struct ath12k_vif *arvif)
+static int ath12k_recalc_rtscts_prot(struct ath12k_link_vif *arvif)
{
struct ath12k *ar = arvif->ar;
u32 vdev_param, rts_cts;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
vdev_param = WMI_VDEV_PARAM_ENABLE_RTSCTS;
@@ -863,7 +887,7 @@ static int ath12k_recalc_rtscts_prot(struct ath12k_vif *arvif)
return ret;
}
-static int ath12k_mac_set_kickout(struct ath12k_vif *arvif)
+static int ath12k_mac_set_kickout(struct ath12k_link_vif *arvif)
{
struct ath12k *ar = arvif->ar;
u32 param;
@@ -913,11 +937,14 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar)
struct ath12k_peer *peer, *tmp;
struct ath12k_base *ab = ar->ab;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
spin_lock_bh(&ab->base_lock);
list_for_each_entry_safe(peer, tmp, &ab->peers, list) {
- ath12k_dp_rx_peer_tid_cleanup(ar, peer);
+ /* Skip Rx TID cleanup for self peer */
+ if (peer->sta)
+ ath12k_dp_rx_peer_tid_cleanup(ar, peer);
+
list_del(&peer->list);
kfree(peer);
}
@@ -929,7 +956,7 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar)
static int ath12k_mac_vdev_setup_sync(struct ath12k *ar)
{
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
return -ESHUTDOWN;
@@ -971,7 +998,7 @@ static int ath12k_mac_monitor_vdev_start(struct ath12k *ar, int vdev_id,
struct ath12k_wmi_vdev_up_params params = {};
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
channel = chandef->chan;
arg.vdev_id = vdev_id;
@@ -1034,7 +1061,7 @@ static int ath12k_mac_monitor_vdev_stop(struct ath12k *ar)
{
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
reinit_completion(&ar->vdev_setup_done);
@@ -1064,9 +1091,8 @@ static int ath12k_mac_monitor_vdev_create(struct ath12k *ar)
struct ath12k_wmi_vdev_create_arg arg = {};
int bit, ret;
u8 tmp_addr[6];
- u16 nss;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (ar->monitor_vdev_created)
return 0;
@@ -1104,19 +1130,6 @@ static int ath12k_mac_monitor_vdev_create(struct ath12k *ar)
return ret;
}
- nss = hweight32(ar->cfg_tx_chainmask) ? : 1;
- ret = ath12k_wmi_vdev_set_param_cmd(ar, ar->monitor_vdev_id,
- WMI_VDEV_PARAM_NSS, nss);
- if (ret) {
- ath12k_warn(ar->ab, "failed to set vdev %d chainmask 0x%x, nss %d :%d\n",
- ar->monitor_vdev_id, ar->cfg_tx_chainmask, nss, ret);
- return ret;
- }
-
- ret = ath12k_mac_txpower_recalc(ar);
- if (ret)
- return ret;
-
ar->allocated_vdev_map |= 1LL << ar->monitor_vdev_id;
ar->ab->free_vdev_map &= ~(1LL << ar->monitor_vdev_id);
ar->num_created_vdevs++;
@@ -1132,7 +1145,7 @@ static int ath12k_mac_monitor_vdev_delete(struct ath12k *ar)
int ret;
unsigned long time_left;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (!ar->monitor_vdev_created)
return 0;
@@ -1178,7 +1191,7 @@ static int ath12k_mac_monitor_start(struct ath12k *ar)
struct cfg80211_chan_def *chandef = NULL;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (ar->monitor_started)
return 0;
@@ -1208,7 +1221,7 @@ static int ath12k_mac_monitor_stop(struct ath12k *ar)
{
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (!ar->monitor_started)
return 0;
@@ -1226,12 +1239,13 @@ static int ath12k_mac_monitor_stop(struct ath12k *ar)
return ret;
}
-static int ath12k_mac_vdev_stop(struct ath12k_vif *arvif)
+static int ath12k_mac_vdev_stop(struct ath12k_link_vif *arvif)
{
+ struct ath12k_vif *ahvif = arvif->ahvif;
struct ath12k *ar = arvif->ar;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
reinit_completion(&ar->vdev_setup_done);
@@ -1253,7 +1267,7 @@ static int ath12k_mac_vdev_stop(struct ath12k_vif *arvif)
ar->num_started_vdevs--;
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "vdev %pM stopped, vdev_id %d\n",
- arvif->vif->addr, arvif->vdev_id);
+ ahvif->vif->addr, arvif->vdev_id);
if (test_bit(ATH12K_CAC_RUNNING, &ar->dev_flags)) {
clear_bit(ATH12K_CAC_RUNNING, &ar->dev_flags);
@@ -1272,36 +1286,33 @@ static int ath12k_mac_config(struct ath12k *ar, u32 changed)
struct ieee80211_conf *conf = &hw->conf;
int ret = 0;
- mutex_lock(&ar->conf_mutex);
+ lockdep_assert_wiphy(hw->wiphy);
if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
ar->monitor_conf_enabled = conf->flags & IEEE80211_CONF_MONITOR;
if (ar->monitor_conf_enabled) {
if (ar->monitor_vdev_created)
- goto exit;
+ return ret;
ret = ath12k_mac_monitor_vdev_create(ar);
if (ret)
- goto exit;
+ return ret;
ret = ath12k_mac_monitor_start(ar);
if (ret)
goto err_mon_del;
} else {
if (!ar->monitor_vdev_created)
- goto exit;
+ return ret;
ret = ath12k_mac_monitor_stop(ar);
if (ret)
- goto exit;
+ return ret;
ath12k_mac_monitor_vdev_delete(ar);
}
}
-exit:
- mutex_unlock(&ar->conf_mutex);
return ret;
err_mon_del:
ath12k_mac_monitor_vdev_delete(ar);
- mutex_unlock(&ar->conf_mutex);
return ret;
}
@@ -1311,6 +1322,8 @@ static int ath12k_mac_op_config(struct ieee80211_hw *hw, u32 changed)
struct ath12k *ar;
int ret;
+ lockdep_assert_wiphy(hw->wiphy);
+
ar = ath12k_ah_to_ar(ah, 0);
ret = ath12k_mac_config(ar, changed);
@@ -1321,7 +1334,7 @@ static int ath12k_mac_op_config(struct ieee80211_hw *hw, u32 changed)
return ret;
}
-static int ath12k_mac_setup_bcn_p2p_ie(struct ath12k_vif *arvif,
+static int ath12k_mac_setup_bcn_p2p_ie(struct ath12k_link_vif *arvif,
struct sk_buff *bcn)
{
struct ath12k *ar = arvif->ar;
@@ -1378,7 +1391,7 @@ static int ath12k_mac_remove_vendor_ie(struct sk_buff *skb, unsigned int oui,
return 0;
}
-static void ath12k_mac_set_arvif_ies(struct ath12k_vif *arvif, struct sk_buff *bcn,
+static void ath12k_mac_set_arvif_ies(struct ath12k_link_vif *arvif, struct sk_buff *bcn,
u8 bssid_index, bool *nontx_profile_found)
{
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)bcn->data;
@@ -1470,19 +1483,22 @@ static void ath12k_mac_set_arvif_ies(struct ath12k_vif *arvif, struct sk_buff *b
}
}
-static int ath12k_mac_setup_bcn_tmpl_ema(struct ath12k_vif *arvif)
+static int ath12k_mac_setup_bcn_tmpl_ema(struct ath12k_link_vif *arvif)
{
- struct ieee80211_bss_conf *bss_conf = &arvif->vif->bss_conf;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_bss_conf *bss_conf = &ahvif->vif->bss_conf;
struct ath12k_wmi_bcn_tmpl_ema_arg ema_args;
struct ieee80211_ema_beacons *beacons;
- struct ath12k_vif *tx_arvif;
+ struct ath12k_link_vif *tx_arvif;
bool nontx_profile_found = false;
+ struct ath12k_vif *tx_ahvif;
int ret = 0;
u8 i;
- tx_arvif = ath12k_vif_to_arvif(arvif->vif->mbssid_tx_vif);
+ tx_ahvif = ath12k_vif_to_ahvif(ahvif->vif->mbssid_tx_vif);
+ tx_arvif = &tx_ahvif->deflink;
beacons = ieee80211_beacon_get_template_ema_list(ath12k_ar_to_hw(tx_arvif->ar),
- tx_arvif->vif, 0);
+ tx_ahvif->vif, 0);
if (!beacons || !beacons->cnt) {
ath12k_warn(arvif->ar->ab,
"failed to get ema beacon templates from mac80211\n");
@@ -1520,22 +1536,25 @@ static int ath12k_mac_setup_bcn_tmpl_ema(struct ath12k_vif *arvif)
return ret;
}
-static int ath12k_mac_setup_bcn_tmpl(struct ath12k_vif *arvif)
+static int ath12k_mac_setup_bcn_tmpl(struct ath12k_link_vif *arvif)
{
- struct ath12k_vif *tx_arvif = arvif;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
+ struct ath12k_link_vif *tx_arvif = arvif;
struct ath12k *ar = arvif->ar;
struct ath12k_base *ab = ar->ab;
- struct ieee80211_vif *vif = arvif->vif;
struct ieee80211_mutable_offsets offs = {};
+ struct ath12k_vif *tx_ahvif = ahvif;
bool nontx_profile_found = false;
struct sk_buff *bcn;
int ret;
- if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
+ if (ahvif->vdev_type != WMI_VDEV_TYPE_AP)
return 0;
if (vif->mbssid_tx_vif) {
- tx_arvif = ath12k_vif_to_arvif(vif->mbssid_tx_vif);
+ tx_ahvif = ath12k_vif_to_ahvif(vif->mbssid_tx_vif);
+ tx_arvif = &tx_ahvif->deflink;
if (tx_arvif != arvif && arvif->is_up)
return 0;
@@ -1543,7 +1562,7 @@ static int ath12k_mac_setup_bcn_tmpl(struct ath12k_vif *arvif)
return ath12k_mac_setup_bcn_tmpl_ema(arvif);
}
- bcn = ieee80211_beacon_get_template(ath12k_ar_to_hw(tx_arvif->ar), tx_arvif->vif,
+ bcn = ieee80211_beacon_get_template(ath12k_ar_to_hw(tx_arvif->ar), tx_ahvif->vif,
&offs, 0);
if (!bcn) {
ath12k_warn(ab, "failed to get beacon template from mac80211\n");
@@ -1554,14 +1573,14 @@ static int ath12k_mac_setup_bcn_tmpl(struct ath12k_vif *arvif)
ath12k_mac_set_arvif_ies(arvif, bcn, 0, NULL);
} else {
ath12k_mac_set_arvif_ies(arvif, bcn,
- arvif->vif->bss_conf.bssid_index,
+ ahvif->vif->bss_conf.bssid_index,
&nontx_profile_found);
if (!nontx_profile_found)
ath12k_warn(ab,
"nontransmitted profile not found in beacon template\n");
}
- if (arvif->vif->type == NL80211_IFTYPE_AP && arvif->vif->p2p) {
+ if (ahvif->vif->type == NL80211_IFTYPE_AP && ahvif->vif->p2p) {
ret = ath12k_mac_setup_bcn_p2p_ie(arvif, bcn);
if (ret) {
ath12k_warn(ab, "failed to setup P2P GO bcn ie: %d\n",
@@ -1595,14 +1614,15 @@ free_bcn_skb:
return ret;
}
-static void ath12k_control_beaconing(struct ath12k_vif *arvif,
+static void ath12k_control_beaconing(struct ath12k_link_vif *arvif,
struct ieee80211_bss_conf *info)
{
struct ath12k_wmi_vdev_up_params params = {};
+ struct ath12k_vif *ahvif = arvif->ahvif;
struct ath12k *ar = arvif->ar;
int ret;
- lockdep_assert_held(&arvif->ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(arvif->ar)->wiphy);
if (!info->enable_beacon) {
ret = ath12k_wmi_vdev_down(ar, arvif->vdev_id);
@@ -1622,15 +1642,19 @@ static void ath12k_control_beaconing(struct ath12k_vif *arvif,
return;
}
- arvif->aid = 0;
+ ahvif->aid = 0;
ether_addr_copy(arvif->bssid, info->bssid);
params.vdev_id = arvif->vdev_id;
- params.aid = arvif->aid;
+ params.aid = ahvif->aid;
params.bssid = arvif->bssid;
- if (arvif->vif->mbssid_tx_vif) {
- params.tx_bssid = ath12k_vif_to_arvif(arvif->vif->mbssid_tx_vif)->bssid;
+ if (ahvif->vif->mbssid_tx_vif) {
+ struct ath12k_vif *tx_ahvif =
+ ath12k_vif_to_ahvif(ahvif->vif->mbssid_tx_vif);
+ struct ath12k_link_vif *tx_arvif = &tx_ahvif->deflink;
+
+ params.tx_bssid = tx_arvif->bssid;
params.nontx_profile_idx = info->bssid_index;
params.nontx_profile_cnt = 1 << info->bssid_indicator;
}
@@ -1651,7 +1675,8 @@ static void ath12k_mac_handle_beacon_iter(void *data, u8 *mac,
{
struct sk_buff *skb = data;
struct ieee80211_mgmt *mgmt = (void *)skb->data;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif = &ahvif->deflink;
if (vif->type != NL80211_IFTYPE_STATION)
return;
@@ -1674,7 +1699,8 @@ static void ath12k_mac_handle_beacon_miss_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
u32 *vdev_id = data;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif = &ahvif->deflink;
struct ath12k *ar = arvif->ar;
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
@@ -1705,9 +1731,9 @@ void ath12k_mac_handle_beacon_miss(struct ath12k *ar, u32 vdev_id)
static void ath12k_mac_vif_sta_connection_loss_work(struct work_struct *work)
{
- struct ath12k_vif *arvif = container_of(work, struct ath12k_vif,
- connection_loss_work.work);
- struct ieee80211_vif *vif = arvif->vif;
+ struct ath12k_link_vif *arvif = container_of(work, struct ath12k_link_vif,
+ connection_loss_work.work);
+ struct ieee80211_vif *vif = arvif->ahvif->vif;
if (!arvif->is_up)
return;
@@ -1716,15 +1742,16 @@ static void ath12k_mac_vif_sta_connection_loss_work(struct work_struct *work)
}
static void ath12k_peer_assoc_h_basic(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
u32 aid;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(hw->wiphy);
if (vif->type == NL80211_IFTYPE_STATION)
aid = vif->cfg.aid;
@@ -1742,21 +1769,22 @@ static void ath12k_peer_assoc_h_basic(struct ath12k *ar,
}
static void ath12k_peer_assoc_h_crypto(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct ieee80211_bss_conf *info = &vif->bss_conf;
struct cfg80211_chan_def def;
struct cfg80211_bss *bss;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
const u8 *rsnie = NULL;
const u8 *wpaie = NULL;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(hw->wiphy);
- if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
+ if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return;
bss = cfg80211_get_bss(hw->wiphy, def.chan, info->bssid, NULL, 0,
@@ -1804,11 +1832,12 @@ static void ath12k_peer_assoc_h_crypto(struct ath12k *ar,
}
static void ath12k_peer_assoc_h_rates(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct wmi_rate_set_arg *rateset = &arg->peer_legacy_rates;
struct cfg80211_chan_def def;
const struct ieee80211_supported_band *sband;
@@ -1819,9 +1848,9 @@ static void ath12k_peer_assoc_h_rates(struct ath12k *ar,
u8 rate;
int i;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(hw->wiphy);
- if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
+ if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return;
band = def.chan->band;
@@ -1867,12 +1896,13 @@ ath12k_peer_assoc_h_vht_masked(const u16 *vht_mcs_mask)
}
static void ath12k_peer_assoc_h_ht(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
struct cfg80211_chan_def def;
enum nl80211_band band;
const u8 *ht_mcs_mask;
@@ -1880,9 +1910,9 @@ static void ath12k_peer_assoc_h_ht(struct ath12k *ar,
u8 max_nss;
u32 stbc;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
+ if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return;
if (!ht_cap->ht_supported)
@@ -2028,12 +2058,13 @@ ath12k_peer_assoc_h_vht_limit(u16 tx_mcs_set,
}
static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
const struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
struct cfg80211_chan_def def;
enum nl80211_band band;
const u16 *vht_mcs_mask;
@@ -2042,7 +2073,9 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
u8 max_nss, vht_mcs;
int i;
- if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
+ if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return;
if (!vht_cap->vht_supported)
@@ -2123,10 +2156,12 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
}
static void ath12k_peer_assoc_h_he(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
int i;
u8 ampdu_factor, max_nss;
@@ -2278,16 +2313,18 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar,
}
static void ath12k_peer_assoc_h_he_6ghz(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
struct cfg80211_chan_def def;
enum nl80211_band band;
u8 ampdu_factor, mpdu_density;
- if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
+ if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return;
band = def.chan->band;
@@ -2347,9 +2384,10 @@ static int ath12k_get_smps_from_capa(const struct ieee80211_sta_ht_cap *ht_cap,
return 0;
}
-static void ath12k_peer_assoc_h_smps(struct ieee80211_sta *sta,
+static void ath12k_peer_assoc_h_smps(struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
const struct ieee80211_he_6ghz_capa *he_6ghz_capa = &sta->deflink.he_6ghz_capa;
const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
int smps;
@@ -2376,13 +2414,13 @@ static void ath12k_peer_assoc_h_smps(struct ieee80211_sta *sta,
}
static void ath12k_peer_assoc_h_qos(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
- switch (arvif->vdev_type) {
+ switch (arvif->ahvif->vdev_type) {
case WMI_VDEV_TYPE_AP:
if (sta->wme) {
/* TODO: Check WME vs QoS */
@@ -2412,15 +2450,16 @@ static void ath12k_peer_assoc_h_qos(struct ath12k *ar,
}
static int ath12k_peer_assoc_qos_ap(struct ath12k *ar,
- struct ath12k_vif *arvif,
- struct ieee80211_sta *sta)
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta)
{
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct ath12k_wmi_ap_ps_arg arg;
u32 max_sp;
u32 uapsd;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
arg.vdev_id = arvif->vdev_id;
@@ -2574,18 +2613,22 @@ static enum wmi_phy_mode ath12k_mac_get_phymode_eht(struct ath12k *ar,
}
static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
struct cfg80211_chan_def def;
enum nl80211_band band;
const u8 *ht_mcs_mask;
const u16 *vht_mcs_mask;
enum wmi_phy_mode phymode = MODE_UNKNOWN;
- if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
+
+ if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return;
band = def.chan->band;
@@ -2719,17 +2762,19 @@ static void ath12k_mac_set_eht_ppe_threshold(const u8 *ppe_thres,
}
static void ath12k_peer_assoc_h_eht(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
const struct ieee80211_sta_eht_cap *eht_cap = &sta->deflink.eht_cap;
const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
const struct ieee80211_eht_mcs_nss_supp_20mhz_only *bw_20;
const struct ieee80211_eht_mcs_nss_supp_bw *bw;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
u32 *rx_mcs, *tx_mcs;
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
if (!sta->deflink.he_cap.has_he || !eht_cap->has_eht)
return;
@@ -2802,34 +2847,34 @@ static void ath12k_peer_assoc_h_eht(struct ath12k *ar,
}
static void ath12k_peer_assoc_prepare(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg,
bool reassoc)
{
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
memset(arg, 0, sizeof(*arg));
reinit_completion(&ar->peer_assoc_done);
arg->peer_new_assoc = !reassoc;
- ath12k_peer_assoc_h_basic(ar, vif, sta, arg);
- ath12k_peer_assoc_h_crypto(ar, vif, sta, arg);
- ath12k_peer_assoc_h_rates(ar, vif, sta, arg);
- ath12k_peer_assoc_h_ht(ar, vif, sta, arg);
- ath12k_peer_assoc_h_vht(ar, vif, sta, arg);
- ath12k_peer_assoc_h_he(ar, vif, sta, arg);
- ath12k_peer_assoc_h_he_6ghz(ar, vif, sta, arg);
- ath12k_peer_assoc_h_eht(ar, vif, sta, arg);
- ath12k_peer_assoc_h_qos(ar, vif, sta, arg);
- ath12k_peer_assoc_h_phymode(ar, vif, sta, arg);
- ath12k_peer_assoc_h_smps(sta, arg);
+ ath12k_peer_assoc_h_basic(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_crypto(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_rates(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_ht(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_vht(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_he(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_he_6ghz(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_eht(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_qos(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_phymode(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_smps(arsta, arg);
/* TODO: amsdu_disable req? */
}
-static int ath12k_setup_peer_smps(struct ath12k *ar, struct ath12k_vif *arvif,
+static int ath12k_setup_peer_smps(struct ath12k *ar, struct ath12k_link_vif *arvif,
const u8 *addr,
const struct ieee80211_sta_ht_cap *ht_cap,
const struct ieee80211_he_6ghz_capa *he_6ghz_capa)
@@ -2849,21 +2894,24 @@ static int ath12k_setup_peer_smps(struct ath12k *ar, struct ath12k_vif *arvif,
}
static void ath12k_bss_assoc(struct ath12k *ar,
- struct ath12k_vif *arvif,
+ struct ath12k_link_vif *arvif,
struct ieee80211_bss_conf *bss_conf)
{
- struct ieee80211_vif *vif = arvif->vif;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
struct ath12k_wmi_vdev_up_params params = {};
struct ath12k_wmi_peer_assoc_arg peer_arg;
+ struct ath12k_link_sta *arsta;
struct ieee80211_sta *ap_sta;
+ struct ath12k_sta *ahsta;
struct ath12k_peer *peer;
bool is_auth = false;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %i assoc bssid %pM aid %d\n",
- arvif->vdev_id, arvif->bssid, arvif->aid);
+ arvif->vdev_id, arvif->bssid, ahvif->aid);
rcu_read_lock();
@@ -2875,7 +2923,15 @@ static void ath12k_bss_assoc(struct ath12k *ar,
return;
}
- ath12k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg, false);
+ ahsta = ath12k_sta_to_ahsta(ap_sta);
+ arsta = &ahsta->deflink;
+
+ if (WARN_ON(!arsta)) {
+ rcu_read_unlock();
+ return;
+ }
+
+ ath12k_peer_assoc_prepare(ar, arvif, arsta, &peer_arg, false);
rcu_read_unlock();
@@ -2903,11 +2959,11 @@ static void ath12k_bss_assoc(struct ath12k *ar,
WARN_ON(arvif->is_up);
- arvif->aid = vif->cfg.aid;
+ ahvif->aid = vif->cfg.aid;
ether_addr_copy(arvif->bssid, bss_conf->bssid);
params.vdev_id = arvif->vdev_id;
- params.aid = arvif->aid;
+ params.aid = ahvif->aid;
params.bssid = arvif->bssid;
ret = ath12k_wmi_vdev_up(ar, &params);
if (ret) {
@@ -2949,11 +3005,11 @@ static void ath12k_bss_assoc(struct ath12k *ar,
}
static void ath12k_bss_disassoc(struct ath12k *ar,
- struct ath12k_vif *arvif)
+ struct ath12k_link_vif *arvif)
{
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %i disassoc bssid %pM\n",
arvif->vdev_id, arvif->bssid);
@@ -2996,10 +3052,10 @@ static u32 ath12k_mac_get_rate_hw_value(int bitrate)
}
static void ath12k_recalculate_mgmt_rate(struct ath12k *ar,
- struct ieee80211_vif *vif,
+ struct ath12k_link_vif *arvif,
struct cfg80211_chan_def *def)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
const struct ieee80211_supported_band *sband;
u8 basic_rate_idx;
@@ -3008,7 +3064,7 @@ static void ath12k_recalculate_mgmt_rate(struct ath12k *ar,
u16 bitrate;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(hw->wiphy);
sband = hw->wiphy->bands[def->chan->band];
basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1;
@@ -3033,9 +3089,19 @@ static void ath12k_recalculate_mgmt_rate(struct ath12k *ar,
ath12k_warn(ar->ab, "failed to set beacon tx rate %d\n", ret);
}
-static int ath12k_mac_fils_discovery(struct ath12k_vif *arvif,
+static int
+ath12k_mac_op_change_vif_links(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ u16 old_links, u16 new_links,
+ struct ieee80211_bss_conf *ol[IEEE80211_MLD_MAX_NUM_LINKS])
+{
+ return 0;
+}
+
+static int ath12k_mac_fils_discovery(struct ath12k_link_vif *arvif,
struct ieee80211_bss_conf *info)
{
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
struct ath12k *ar = arvif->ar;
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
struct sk_buff *tmpl;
@@ -3046,7 +3112,7 @@ static int ath12k_mac_fils_discovery(struct ath12k_vif *arvif,
if (info->fils_discovery.max_interval) {
interval = info->fils_discovery.max_interval;
- tmpl = ieee80211_get_fils_discovery_tmpl(hw, arvif->vif);
+ tmpl = ieee80211_get_fils_discovery_tmpl(hw, vif);
if (tmpl)
ret = ath12k_wmi_fils_discovery_tmpl(ar, arvif->vdev_id,
tmpl);
@@ -3054,8 +3120,7 @@ static int ath12k_mac_fils_discovery(struct ath12k_vif *arvif,
unsol_bcast_probe_resp_enabled = 1;
interval = info->unsol_bcast_probe_resp_interval;
- tmpl = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw,
- arvif->vif);
+ tmpl = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif);
if (tmpl)
ret = ath12k_wmi_probe_resp_tmpl(ar, arvif->vdev_id,
tmpl);
@@ -3080,10 +3145,44 @@ static int ath12k_mac_fils_discovery(struct ath12k_vif *arvif,
return ret;
}
-static void ath12k_mac_vif_setup_ps(struct ath12k_vif *arvif)
+static void ath12k_mac_op_vif_cfg_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ u64 changed)
+{
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ unsigned long links = ahvif->links_map;
+ struct ath12k_link_vif *arvif;
+ struct ath12k *ar;
+ u8 link_id;
+
+ lockdep_assert_wiphy(hw->wiphy);
+
+ if (changed & BSS_CHANGED_SSID && vif->type == NL80211_IFTYPE_AP) {
+ ahvif->u.ap.ssid_len = vif->cfg.ssid_len;
+ if (vif->cfg.ssid_len)
+ memcpy(ahvif->u.ap.ssid, vif->cfg.ssid, vif->cfg.ssid_len);
+ }
+
+ if (changed & BSS_CHANGED_ASSOC) {
+ for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
+ if (!arvif || !arvif->ar)
+ continue;
+
+ ar = arvif->ar;
+
+ if (vif->cfg.assoc)
+ ath12k_bss_assoc(ar, arvif, &vif->bss_conf);
+ else
+ ath12k_bss_disassoc(ar, arvif);
+ }
+ }
+}
+
+static void ath12k_mac_vif_setup_ps(struct ath12k_link_vif *arvif)
{
struct ath12k *ar = arvif->ar;
- struct ieee80211_vif *vif = arvif->vif;
+ struct ieee80211_vif *vif = arvif->ahvif->vif;
struct ieee80211_conf *conf = &ath12k_ar_to_hw(ar)->conf;
enum wmi_sta_powersave_param param;
enum wmi_sta_ps_mode psmode;
@@ -3091,12 +3190,12 @@ static void ath12k_mac_vif_setup_ps(struct ath12k_vif *arvif)
int timeout;
bool enable_ps;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (vif->type != NL80211_IFTYPE_STATION)
return;
- enable_ps = arvif->ps;
+ enable_ps = arvif->ahvif->ps;
if (enable_ps) {
psmode = WMI_STA_PS_MODE_ENABLED;
param = WMI_STA_PS_PARAM_INACTIVITY_TIME;
@@ -3128,11 +3227,12 @@ static void ath12k_mac_vif_setup_ps(struct ath12k_vif *arvif)
}
static void ath12k_mac_bss_info_changed(struct ath12k *ar,
- struct ath12k_vif *arvif,
+ struct ath12k_link_vif *arvif,
struct ieee80211_bss_conf *info,
u64 changed)
{
- struct ieee80211_vif *vif = arvif->vif;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
struct ieee80211_vif_cfg *vif_cfg = &vif->cfg;
struct cfg80211_chan_def def;
u32 param_id, param_value;
@@ -3146,7 +3246,7 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar,
u8 rateidx;
u32 rate;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (changed & BSS_CHANGED_BEACON_INT) {
arvif->beacon_interval = info->beacon_int;
@@ -3202,10 +3302,10 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar,
if (changed & BSS_CHANGED_SSID &&
vif->type == NL80211_IFTYPE_AP) {
- arvif->u.ap.ssid_len = vif->cfg.ssid_len;
+ ahvif->u.ap.ssid_len = vif->cfg.ssid_len;
if (vif->cfg.ssid_len)
- memcpy(arvif->u.ap.ssid, vif->cfg.ssid, vif->cfg.ssid_len);
- arvif->u.ap.hidden_ssid = info->hidden_ssid;
+ memcpy(ahvif->u.ap.ssid, vif->cfg.ssid, vif->cfg.ssid_len);
+ ahvif->u.ap.hidden_ssid = info->hidden_ssid;
}
if (changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid))
@@ -3316,7 +3416,7 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar,
}
if (changed & BSS_CHANGED_MCAST_RATE &&
- !ath12k_mac_vif_chan(arvif->vif, &def)) {
+ !ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)) {
band = def.chan->band;
mcast_rate = vif->bss_conf.mcast_rate[band];
@@ -3360,8 +3460,8 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar,
}
if (changed & BSS_CHANGED_BASIC_RATES &&
- !ath12k_mac_vif_chan(arvif->vif, &def))
- ath12k_recalculate_mgmt_rate(ar, vif, &def);
+ !ath12k_mac_vif_link_chan(vif, arvif->link_id, &def))
+ ath12k_recalculate_mgmt_rate(ar, arvif, &def);
if (changed & BSS_CHANGED_TWT) {
if (info->twt_requester || info->twt_responder)
@@ -3406,53 +3506,177 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar,
if (changed & BSS_CHANGED_PS &&
ar->ab->hw_params->supports_sta_ps) {
- arvif->ps = vif_cfg->ps;
+ ahvif->ps = vif_cfg->ps;
ath12k_mac_vif_setup_ps(arvif);
}
}
-static struct ath12k_vif_cache *ath12k_arvif_get_cache(struct ath12k_vif *arvif)
+static struct ath12k_vif_cache *ath12k_ahvif_get_link_cache(struct ath12k_vif *ahvif,
+ u8 link_id)
+{
+ if (!ahvif->cache[link_id]) {
+ ahvif->cache[link_id] = kzalloc(sizeof(*ahvif->cache[0]), GFP_KERNEL);
+ if (ahvif->cache[link_id])
+ INIT_LIST_HEAD(&ahvif->cache[link_id]->key_conf.list);
+ }
+
+ return ahvif->cache[link_id];
+}
+
+static void ath12k_ahvif_put_link_key_cache(struct ath12k_vif_cache *cache)
{
- if (!arvif->cache)
- arvif->cache = kzalloc(sizeof(*arvif->cache), GFP_KERNEL);
+ struct ath12k_key_conf *key_conf, *tmp;
- return arvif->cache;
+ if (!cache || list_empty(&cache->key_conf.list))
+ return;
+ list_for_each_entry_safe(key_conf, tmp, &cache->key_conf.list, list) {
+ list_del(&key_conf->list);
+ kfree(key_conf);
+ }
}
-static void ath12k_arvif_put_cache(struct ath12k_vif *arvif)
+static void ath12k_ahvif_put_link_cache(struct ath12k_vif *ahvif, u8 link_id)
{
- kfree(arvif->cache);
- arvif->cache = NULL;
+ ath12k_ahvif_put_link_key_cache(ahvif->cache[link_id]);
+ kfree(ahvif->cache[link_id]);
+ ahvif->cache[link_id] = NULL;
}
-static void ath12k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *info,
- u64 changed)
+static void ath12k_mac_op_link_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *info,
+ u64 changed)
{
struct ath12k *ar;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_vif_cache *cache;
+ struct ath12k_link_vif *arvif;
+ u8 link_id = info->link_id;
- ar = ath12k_get_ar_by_vif(hw, vif);
+ lockdep_assert_wiphy(hw->wiphy);
+
+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
/* if the vdev is not created on a certain radio,
* cache the info to be updated later on vdev creation
*/
- if (!ar) {
- cache = ath12k_arvif_get_cache(arvif);
+ if (!arvif || !arvif->is_created) {
+ cache = ath12k_ahvif_get_link_cache(ahvif, link_id);
if (!cache)
return;
- arvif->cache->bss_conf_changed |= changed;
+
+ cache->bss_conf_changed |= changed;
+
return;
}
- mutex_lock(&ar->conf_mutex);
+ ar = arvif->ar;
ath12k_mac_bss_info_changed(ar, arvif, info, changed);
+}
+
+static struct ath12k_link_vif *ath12k_mac_assign_link_vif(struct ath12k_hw *ah,
+ struct ieee80211_vif *vif,
+ u8 link_id)
+{
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
+ int i;
+
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
+ arvif = wiphy_dereference(ah->hw->wiphy, ahvif->link[link_id]);
+ if (arvif)
+ return arvif;
+
+ if (!vif->valid_links) {
+ /* Use deflink for Non-ML VIFs and mark the link id as 0
+ */
+ link_id = 0;
+ arvif = &ahvif->deflink;
+ } else {
+ /* If this is the first link arvif being created for an ML VIF
+ * use the preallocated deflink memory
+ */
+ if (!ahvif->links_map) {
+ arvif = &ahvif->deflink;
+ } else {
+ arvif = (struct ath12k_link_vif *)
+ kzalloc(sizeof(struct ath12k_link_vif), GFP_KERNEL);
+ if (!arvif)
+ return NULL;
+ }
+ }
+
+ arvif->ahvif = ahvif;
+ arvif->link_id = link_id;
+ ahvif->links_map |= BIT(link_id);
+
+ INIT_LIST_HEAD(&arvif->list);
+ INIT_DELAYED_WORK(&arvif->connection_loss_work,
+ ath12k_mac_vif_sta_connection_loss_work);
+
+ for (i = 0; i < ARRAY_SIZE(arvif->bitrate_mask.control); i++) {
+ arvif->bitrate_mask.control[i].legacy = 0xffffffff;
+ memset(arvif->bitrate_mask.control[i].ht_mcs, 0xff,
+ sizeof(arvif->bitrate_mask.control[i].ht_mcs));
+ memset(arvif->bitrate_mask.control[i].vht_mcs, 0xff,
+ sizeof(arvif->bitrate_mask.control[i].vht_mcs));
+ }
+
+ /* Allocate Default Queue now and reassign during actual vdev create */
+ vif->cab_queue = ATH12K_HW_DEFAULT_QUEUE;
+ for (i = 0; i < ARRAY_SIZE(vif->hw_queue); i++)
+ vif->hw_queue[i] = ATH12K_HW_DEFAULT_QUEUE;
- mutex_unlock(&ar->conf_mutex);
+ vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
+
+ rcu_assign_pointer(ahvif->link[arvif->link_id], arvif);
+ ahvif->links_map |= BIT(link_id);
+ synchronize_rcu();
+ return arvif;
+}
+
+static void ath12k_mac_unassign_link_vif(struct ath12k_link_vif *arvif)
+{
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ath12k_hw *ah = ahvif->ah;
+
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
+ rcu_assign_pointer(ahvif->link[arvif->link_id], NULL);
+ synchronize_rcu();
+ ahvif->links_map &= ~BIT(arvif->link_id);
+
+ if (arvif != &ahvif->deflink)
+ kfree(arvif);
+ else
+ memset(arvif, 0, sizeof(*arvif));
+}
+
+static void ath12k_mac_remove_link_interface(struct ieee80211_hw *hw,
+ struct ath12k_link_vif *arvif)
+{
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ath12k_hw *ah = hw->priv;
+ struct ath12k *ar = arvif->ar;
+ int ret;
+
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
+ cancel_delayed_work_sync(&arvif->connection_loss_work);
+
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac remove link interface (vdev %d link id %d)",
+ arvif->vdev_id, arvif->link_id);
+
+ if (ahvif->vdev_type == WMI_VDEV_TYPE_AP) {
+ ret = ath12k_peer_delete(ar, arvif->vdev_id, arvif->bssid);
+ if (ret)
+ ath12k_warn(ar->ab, "failed to submit AP self-peer removal on vdev %d link id %d: %d",
+ arvif->vdev_id, arvif->link_id, ret);
+ }
+ ath12k_mac_vdev_delete(ar, arvif);
}
static struct ath12k*
@@ -3541,7 +3765,7 @@ static int ath12k_scan_stop(struct ath12k *ar)
};
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
/* TODO: Fill other STOP Params */
arg.pdev_id = ar->pdev->pdev_id;
@@ -3581,7 +3805,7 @@ static void ath12k_scan_abort(struct ath12k *ar)
{
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
spin_lock_bh(&ar->data_lock);
@@ -3616,9 +3840,9 @@ static void ath12k_scan_timeout_work(struct work_struct *work)
struct ath12k *ar = container_of(work, struct ath12k,
scan.timeout.work);
- mutex_lock(&ar->conf_mutex);
+ wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
ath12k_scan_abort(ar);
- mutex_unlock(&ar->conf_mutex);
+ wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
}
static int ath12k_start_scan(struct ath12k *ar,
@@ -3626,7 +3850,7 @@ static int ath12k_start_scan(struct ath12k *ar,
{
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
ret = ath12k_wmi_send_scan_start_cmd(ar, arg);
if (ret)
@@ -3655,24 +3879,50 @@ static int ath12k_start_scan(struct ath12k *ar,
return 0;
}
+static u8
+ath12k_mac_find_link_id_by_ar(struct ath12k_vif *ahvif, struct ath12k *ar)
+{
+ struct ath12k_link_vif *arvif;
+ struct ath12k_hw *ah = ahvif->ah;
+ unsigned long links = ahvif->links_map;
+ u8 link_id;
+
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
+ for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
+ arvif = wiphy_dereference(ah->hw->wiphy, ahvif->link[link_id]);
+
+ if (!arvif || !arvif->is_created)
+ continue;
+
+ if (ar == arvif->ar)
+ return link_id;
+ }
+
+ /* input ar is not assigned to any of the links, use link id
+ * 0 for scan vdev creation.
+ */
+ return 0;
+}
+
static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_scan_request *hw_req)
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
- struct ath12k *ar, *prev_ar;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k *ar;
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
struct cfg80211_scan_request *req = &hw_req->req;
struct ath12k_wmi_scan_req_arg *arg = NULL;
+ u8 link_id;
int ret;
int i;
bool create = true;
- if (ah->num_radio == 1) {
- WARN_ON(!arvif->is_created);
- ar = ath12k_ah_to_ar(ah, 0);
- goto scan;
- }
+ lockdep_assert_wiphy(hw->wiphy);
+
+ arvif = &ahvif->deflink;
/* Since the targeted scan device could depend on the frequency
* requested in the hw_req, select the corresponding radio
@@ -3681,6 +3931,13 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
if (!ar)
return -EINVAL;
+ /* check if any of the links of ML VIF is already started on
+ * radio(ar) correpsondig to given scan frequency and use it,
+ * if not use deflink(link 0) for scan purpose.
+ */
+ link_id = ath12k_mac_find_link_id_by_ar(ahvif, ar);
+ arvif = ath12k_mac_assign_link_vif(ah, vif, link_id);
+
/* If the vif is already assigned to a specific vdev of an ar,
* check whether its already started, vdev which is started
* are not allowed to switch to a new radio.
@@ -3698,31 +3955,24 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
return -EINVAL;
if (ar != arvif->ar) {
- /* backup the previously used ar ptr, since the vdev delete
- * would assign the arvif->ar to NULL after the call
- */
- prev_ar = arvif->ar;
- mutex_lock(&prev_ar->conf_mutex);
- ret = ath12k_mac_vdev_delete(prev_ar, vif);
- mutex_unlock(&prev_ar->conf_mutex);
- if (ret)
- ath12k_warn(prev_ar->ab,
- "unable to delete scan vdev %d\n", ret);
+ ath12k_mac_remove_link_interface(hw, arvif);
+ ath12k_mac_unassign_link_vif(arvif);
} else {
create = false;
}
}
if (create) {
- mutex_lock(&ar->conf_mutex);
- ret = ath12k_mac_vdev_create(ar, vif);
- mutex_unlock(&ar->conf_mutex);
+ /* Previous arvif would've been cleared in radio switch block
+ * above, assign arvif again for create.
+ */
+ arvif = ath12k_mac_assign_link_vif(ah, vif, link_id);
+
+ ret = ath12k_mac_vdev_create(ar, arvif);
if (ret) {
ath12k_warn(ar->ab, "unable to create scan vdev %d\n", ret);
return -EINVAL;
}
}
-scan:
- mutex_lock(&ar->conf_mutex);
spin_lock_bh(&ar->data_lock);
switch (ar->scan.state) {
@@ -3805,30 +4055,31 @@ exit:
kfree(arg);
}
- mutex_unlock(&ar->conf_mutex);
-
return ret;
}
static void ath12k_mac_op_cancel_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
struct ath12k *ar;
+ lockdep_assert_wiphy(hw->wiphy);
+
+ arvif = &ahvif->deflink;
+
if (!arvif->is_created)
return;
ar = arvif->ar;
- mutex_lock(&ar->conf_mutex);
ath12k_scan_abort(ar);
- mutex_unlock(&ar->conf_mutex);
cancel_delayed_work_sync(&ar->scan.timeout);
}
-static int ath12k_install_key(struct ath12k_vif *arvif,
+static int ath12k_install_key(struct ath12k_link_vif *arvif,
struct ieee80211_key_conf *key,
enum set_key_cmd cmd,
const u8 *macaddr, u32 flags)
@@ -3843,8 +4094,10 @@ static int ath12k_install_key(struct ath12k_vif *arvif,
.key_flags = flags,
.macaddr = macaddr,
};
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
- lockdep_assert_held(&arvif->ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
reinit_completion(&ar->install_key_done);
@@ -3895,13 +4148,13 @@ install:
if (!wait_for_completion_timeout(&ar->install_key_done, 1 * HZ))
return -ETIMEDOUT;
- if (ether_addr_equal(macaddr, arvif->vif->addr))
- arvif->key_cipher = key->cipher;
+ if (ether_addr_equal(macaddr, vif->addr))
+ ahvif->key_cipher = key->cipher;
return ar->install_key_status ? -EINVAL : 0;
}
-static int ath12k_clear_peer_keys(struct ath12k_vif *arvif,
+static int ath12k_clear_peer_keys(struct ath12k_link_vif *arvif,
const u8 *addr)
{
struct ath12k *ar = arvif->ar;
@@ -3912,7 +4165,7 @@ static int ath12k_clear_peer_keys(struct ath12k_vif *arvif,
int i;
u32 flags = 0;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
spin_lock_bh(&ab->base_lock);
peer = ath12k_peer_find(ab, arvif->vdev_id, addr);
@@ -3944,25 +4197,31 @@ static int ath12k_clear_peer_keys(struct ath12k_vif *arvif,
}
static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
- struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ieee80211_key_conf *key)
{
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
+ struct ieee80211_sta *sta = NULL;
struct ath12k_base *ab = ar->ab;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
struct ath12k_peer *peer;
- struct ath12k_sta *arsta;
+ struct ath12k_sta *ahsta;
const u8 *peer_addr;
- int ret = 0;
+ int ret;
u32 flags = 0;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
+ if (arsta)
+ sta = ath12k_ahsta_to_sta(arsta->ahsta);
if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags))
return 1;
if (sta)
peer_addr = sta->addr;
- else if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
+ else if (ahvif->vdev_type == WMI_VDEV_TYPE_STA)
peer_addr = vif->bss_conf.bssid;
else
peer_addr = vif->addr;
@@ -3970,7 +4229,7 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
key->hw_key_idx = key->keyidx;
/* the peer should not disappear in mid-way (unless FW goes awry) since
- * we already hold conf_mutex. we just make sure its there now.
+ * we already hold wiphy lock. we just make sure its there now.
*/
spin_lock_bh(&ab->base_lock);
peer = ath12k_peer_find(ab, arvif->vdev_id, peer_addr);
@@ -3980,14 +4239,13 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
if (cmd == SET_KEY) {
ath12k_warn(ab, "cannot install key for non-existent peer %pM\n",
peer_addr);
- ret = -EOPNOTSUPP;
- goto exit;
- } else {
- /* if the peer doesn't exist there is no key to disable
- * anymore
- */
- goto exit;
+ return -EOPNOTSUPP;
}
+
+ /* if the peer doesn't exist there is no key to disable
+ * anymore
+ */
+ return 0;
}
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
@@ -3998,13 +4256,13 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
ret = ath12k_install_key(arvif, key, cmd, peer_addr, flags);
if (ret) {
ath12k_warn(ab, "ath12k_install_key failed (%d)\n", ret);
- goto exit;
+ return ret;
}
ret = ath12k_dp_rx_peer_pn_replay_config(arvif, peer_addr, cmd, key);
if (ret) {
ath12k_warn(ab, "failed to offload PN replay detection %d\n", ret);
- goto exit;
+ return ret;
}
spin_lock_bh(&ab->base_lock);
@@ -4029,7 +4287,7 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
ath12k_warn(ab, "peer %pM disappeared!\n", peer_addr);
if (sta) {
- arsta = ath12k_sta_to_arsta(sta);
+ ahsta = ath12k_sta_to_ahsta(sta);
switch (key->cipher) {
case WLAN_CIPHER_SUITE_TKIP:
@@ -4038,61 +4296,138 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
if (cmd == SET_KEY)
- arsta->pn_type = HAL_PN_TYPE_WPA;
+ ahsta->pn_type = HAL_PN_TYPE_WPA;
else
- arsta->pn_type = HAL_PN_TYPE_NONE;
+ ahsta->pn_type = HAL_PN_TYPE_NONE;
break;
default:
- arsta->pn_type = HAL_PN_TYPE_NONE;
+ ahsta->pn_type = HAL_PN_TYPE_NONE;
break;
}
}
spin_unlock_bh(&ab->base_lock);
-exit:
- return ret;
+ return 0;
+}
+
+static int ath12k_mac_update_key_cache(struct ath12k_vif_cache *cache,
+ enum set_key_cmd cmd,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key)
+{
+ struct ath12k_key_conf *key_conf = NULL, *tmp;
+
+ if (cmd == SET_KEY) {
+ key_conf = kzalloc(sizeof(*key_conf), GFP_KERNEL);
+
+ if (!key_conf)
+ return -ENOMEM;
+
+ key_conf->cmd = cmd;
+ key_conf->sta = sta;
+ key_conf->key = key;
+ list_add_tail(&key_conf->list,
+ &cache->key_conf.list);
+ }
+ if (list_empty(&cache->key_conf.list))
+ return 0;
+ list_for_each_entry_safe(key_conf, tmp, &cache->key_conf.list, list) {
+ if (key_conf->key == key) {
+ /* DEL key for an old SET key which driver hasn't flushed yet.
+ */
+ list_del(&key_conf->list);
+ kfree(key_conf);
+ break;
+ }
+ }
+ return 0;
}
static int ath12k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
struct ieee80211_key_conf *key)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
+ struct ath12k_link_sta *arsta = NULL;
struct ath12k_vif_cache *cache;
- struct ath12k *ar;
+ struct ath12k_sta *ahsta;
+ unsigned long links;
+ u8 link_id;
int ret;
+ lockdep_assert_wiphy(hw->wiphy);
+
/* BIP needs to be done in software */
if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 ||
- key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256)
+ key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256) {
return 1;
+ }
if (key->keyidx > WMI_MAX_KEY_INDEX)
return -ENOSPC;
- ar = ath12k_get_ar_by_vif(hw, vif);
- if (!ar) {
- /* ar is expected to be valid when sta ptr is available */
- if (sta) {
- WARN_ON_ONCE(1);
- return -EINVAL;
+ if (sta) {
+ ahsta = ath12k_sta_to_ahsta(sta);
+ /* For an ML STA Pairwise key is same for all associated link Stations,
+ * hence do set key for all link STAs which are active.
+ */
+ if (sta->mlo) {
+ links = ahsta->links_map;
+ for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
+ arvif = wiphy_dereference(hw->wiphy,
+ ahvif->link[link_id]);
+ arsta = wiphy_dereference(hw->wiphy,
+ ahsta->link[link_id]);
+
+ if (WARN_ON(!arvif || !arsta))
+ /* arvif and arsta are expected to be valid when
+ * STA is present.
+ */
+ continue;
+
+ ret = ath12k_mac_set_key(arvif->ar, cmd, arvif,
+ arsta, key);
+ if (ret)
+ break;
+ }
+ } else {
+ arsta = &ahsta->deflink;
+ arvif = arsta->arvif;
+ if (WARN_ON(!arvif)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = ath12k_mac_set_key(arvif->ar, cmd, arvif, arsta, key);
+ }
+ } else {
+ if (key->link_id >= 0 && key->link_id < IEEE80211_MLD_MAX_NUM_LINKS) {
+ link_id = key->link_id;
+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
+ } else {
+ link_id = 0;
+ arvif = &ahvif->deflink;
}
- cache = ath12k_arvif_get_cache(arvif);
- if (!cache)
- return -ENOSPC;
- cache->key_conf.cmd = cmd;
- cache->key_conf.key = key;
- cache->key_conf.changed = true;
- return 0;
+ if (!arvif || !arvif->is_created) {
+ cache = ath12k_ahvif_get_link_cache(ahvif, link_id);
+ if (!cache)
+ return -ENOSPC;
+
+ ret = ath12k_mac_update_key_cache(cache, cmd, sta, key);
+
+ return ret;
+ }
+
+ ret = ath12k_mac_set_key(arvif->ar, cmd, arvif, NULL, key);
}
- mutex_lock(&ar->conf_mutex);
- ret = ath12k_mac_set_key(ar, cmd, vif, sta, key);
- mutex_unlock(&ar->conf_mutex);
+out:
+
return ret;
}
@@ -4111,17 +4446,18 @@ ath12k_mac_bitrate_mask_num_vht_rates(struct ath12k *ar,
}
static int
-ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_vif *arvif,
- struct ieee80211_sta *sta,
+ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
const struct cfg80211_bitrate_mask *mask,
enum nl80211_band band)
{
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct ath12k *ar = arvif->ar;
u8 vht_rate, nss;
u32 rate_code;
int ret, i;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
nss = 0;
@@ -4157,11 +4493,12 @@ ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_vif *arvif,
}
static int ath12k_station_assoc(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
bool reassoc)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct ath12k_wmi_peer_assoc_arg peer_arg;
int ret;
struct cfg80211_chan_def def;
@@ -4169,15 +4506,15 @@ static int ath12k_station_assoc(struct ath12k *ar,
struct cfg80211_bitrate_mask *mask;
u8 num_vht_rates;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
+ if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return -EPERM;
band = def.chan->band;
mask = &arvif->bitrate_mask;
- ath12k_peer_assoc_prepare(ar, vif, sta, &peer_arg, reassoc);
+ ath12k_peer_assoc_prepare(ar, arvif, arsta, &peer_arg, reassoc);
if (peer_arg.peer_nss < 1) {
ath12k_warn(ar->ab,
@@ -4205,7 +4542,7 @@ static int ath12k_station_assoc(struct ath12k *ar,
* Note that all other rates and NSS will be disabled for this peer.
*/
if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) {
- ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, sta, mask,
+ ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask,
band);
if (ret)
return ret;
@@ -4234,7 +4571,7 @@ static int ath12k_station_assoc(struct ath12k *ar,
}
if (sta->wme && sta->uapsd_queues) {
- ret = ath12k_peer_assoc_qos_ap(ar, arvif, sta);
+ ret = ath12k_peer_assoc_qos_ap(ar, arvif, arsta);
if (ret) {
ath12k_warn(ar->ab, "failed to set qos params for STA %pM for vdev %i: %d\n",
sta->addr, arvif->vdev_id, ret);
@@ -4246,13 +4583,13 @@ static int ath12k_station_assoc(struct ath12k *ar,
}
static int ath12k_station_disassoc(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (!sta->wme) {
arvif->num_legacy_stations--;
@@ -4270,11 +4607,10 @@ static int ath12k_station_disassoc(struct ath12k *ar,
return 0;
}
-static void ath12k_sta_rc_update_wk(struct work_struct *wk)
+static void ath12k_sta_rc_update_wk(struct wiphy *wiphy, struct wiphy_work *wk)
{
struct ath12k *ar;
- struct ath12k_vif *arvif;
- struct ath12k_sta *arsta;
+ struct ath12k_link_vif *arvif;
struct ieee80211_sta *sta;
struct cfg80211_chan_def def;
enum nl80211_band band;
@@ -4285,13 +4621,18 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
const struct cfg80211_bitrate_mask *mask;
struct ath12k_wmi_peer_assoc_arg peer_arg;
enum wmi_phy_mode peer_phymode;
+ struct ath12k_link_sta *arsta;
+ struct ieee80211_vif *vif;
- arsta = container_of(wk, struct ath12k_sta, update_wk);
- sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv);
+ lockdep_assert_wiphy(wiphy);
+
+ arsta = container_of(wk, struct ath12k_link_sta, update_wk);
+ sta = ath12k_ahsta_to_sta(arsta->ahsta);
arvif = arsta->arvif;
+ vif = ath12k_ahvif_to_vif(arvif->ahvif);
ar = arvif->ar;
- if (WARN_ON(ath12k_mac_vif_chan(arvif->vif, &def)))
+ if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return;
band = def.chan->band;
@@ -4310,14 +4651,12 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
spin_unlock_bh(&ar->data_lock);
- mutex_lock(&ar->conf_mutex);
-
nss = max_t(u32, 1, nss);
nss = min(nss, max(ath12k_mac_max_ht_nss(ht_mcs_mask),
ath12k_mac_max_vht_nss(vht_mcs_mask)));
if (changed & IEEE80211_RC_BW_CHANGED) {
- ath12k_peer_assoc_h_phymode(ar, arvif->vif, sta, &peer_arg);
+ ath12k_peer_assoc_h_phymode(ar, arvif, arsta, &peer_arg);
peer_phymode = peer_arg.peer_phymode;
if (bw > bw_prev) {
@@ -4334,7 +4673,7 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
if (err) {
ath12k_warn(ar->ab, "failed to update STA %pM to peer phymode %d: %d\n",
sta->addr, peer_phymode, err);
- goto err_rc_bw_changed;
+ return;
}
err = ath12k_wmi_set_peer_param(ar, sta->addr,
arvif->vdev_id, WMI_PEER_CHWIDTH,
@@ -4355,7 +4694,7 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
if (err) {
ath12k_warn(ar->ab, "failed to update STA %pM peer to bandwidth %d: %d\n",
sta->addr, bw, err);
- goto err_rc_bw_changed;
+ return;
}
err = ath12k_wmi_set_peer_param(ar, sta->addr,
arvif->vdev_id, WMI_PEER_PHYMODE,
@@ -4405,14 +4744,14 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
* across HT/VHT and for multiple VHT MCS support.
*/
if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) {
- ath12k_mac_set_peer_vht_fixed_rate(arvif, sta, mask,
+ ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask,
band);
} else {
/* If the peer is non-VHT or no fixed VHT rate
* is provided in the new bitrate mask we set the
* other rates using peer_assoc command.
*/
- ath12k_peer_assoc_prepare(ar, arvif->vif, sta,
+ ath12k_peer_assoc_prepare(ar, arvif, arsta,
&peer_arg, true);
err = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
@@ -4425,18 +4764,17 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
sta->addr, arvif->vdev_id);
}
}
-err_rc_bw_changed:
- mutex_unlock(&ar->conf_mutex);
}
-static int ath12k_mac_inc_num_stations(struct ath12k_vif *arvif,
- struct ieee80211_sta *sta)
+static int ath12k_mac_inc_num_stations(struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta)
{
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct ath12k *ar = arvif->ar;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- if (arvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls)
+ if (arvif->ahvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls)
return 0;
if (ar->num_stations >= ar->max_num_stations)
@@ -4447,38 +4785,38 @@ static int ath12k_mac_inc_num_stations(struct ath12k_vif *arvif,
return 0;
}
-static void ath12k_mac_dec_num_stations(struct ath12k_vif *arvif,
- struct ieee80211_sta *sta)
+static void ath12k_mac_dec_num_stations(struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta)
{
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct ath12k *ar = arvif->ar;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- if (arvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls)
+ if (arvif->ahvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls)
return;
ar->num_stations--;
}
static int ath12k_mac_station_add(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta)
{
struct ath12k_base *ab = ar->ab;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct ath12k_wmi_peer_create_arg peer_param;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- ret = ath12k_mac_inc_num_stations(arvif, sta);
+ ret = ath12k_mac_inc_num_stations(arvif, arsta);
if (ret) {
ath12k_warn(ab, "refusing to associate station: too many connected already (%d)\n",
ar->max_num_stations);
goto exit;
}
-
arsta->rx_stats = kzalloc(sizeof(*arsta->rx_stats), GFP_KERNEL);
if (!arsta->rx_stats) {
ret = -ENOMEM;
@@ -4519,7 +4857,7 @@ static int ath12k_mac_station_add(struct ath12k *ar,
if (ab->hw_params->vdev_start_delay &&
!arvif->is_started &&
- arvif->vdev_type != WMI_VDEV_TYPE_AP) {
+ arvif->ahvif->vdev_type != WMI_VDEV_TYPE_AP) {
ret = ath12k_start_vdev_delay(ar, arvif);
if (ret) {
ath12k_warn(ab, "failed to delay vdev start: %d\n", ret);
@@ -4532,7 +4870,7 @@ static int ath12k_mac_station_add(struct ath12k *ar,
free_peer:
ath12k_peer_delete(ar, arvif->vdev_id, sta->addr);
dec_num_station:
- ath12k_mac_dec_num_stations(arvif, sta);
+ ath12k_mac_dec_num_stations(arvif, arsta);
exit:
return ret;
}
@@ -4574,16 +4912,18 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
enum ieee80211_sta_state old_state,
enum ieee80211_sta_state new_state)
{
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
struct ath12k *ar;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
+ struct ath12k_link_vif *arvif;
+ struct ath12k_link_sta *arsta;
struct ath12k_peer *peer;
int ret = 0;
- /* cancel must be done outside the mutex to avoid deadlock */
- if ((old_state == IEEE80211_STA_NONE &&
- new_state == IEEE80211_STA_NOTEXIST))
- cancel_work_sync(&arsta->update_wk);
+ lockdep_assert_wiphy(hw->wiphy);
+
+ arvif = &ahvif->deflink;
+ arsta = &ahsta->deflink;
ar = ath12k_get_ar_by_vif(hw, vif);
if (!ar) {
@@ -4591,21 +4931,28 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
return -EINVAL;
}
- mutex_lock(&ar->conf_mutex);
-
if (old_state == IEEE80211_STA_NOTEXIST &&
new_state == IEEE80211_STA_NONE) {
memset(arsta, 0, sizeof(*arsta));
+ rcu_assign_pointer(ahsta->link[0], arsta);
+ /* TODO use appropriate link id once MLO support is added */
+ arsta->link_id = ATH12K_DEFAULT_LINK_ID;
+ ahsta->links_map = BIT(arsta->link_id);
+ arsta->ahsta = ahsta;
arsta->arvif = arvif;
- INIT_WORK(&arsta->update_wk, ath12k_sta_rc_update_wk);
+ wiphy_work_init(&arsta->update_wk, ath12k_sta_rc_update_wk);
+
+ synchronize_rcu();
- ret = ath12k_mac_station_add(ar, vif, sta);
+ ret = ath12k_mac_station_add(ar, arvif, arsta);
if (ret)
ath12k_warn(ar->ab, "Failed to add station: %pM for VDEV: %d\n",
sta->addr, arvif->vdev_id);
} else if ((old_state == IEEE80211_STA_NONE &&
new_state == IEEE80211_STA_NOTEXIST)) {
- if (arvif->vdev_type == WMI_VDEV_TYPE_STA) {
+ wiphy_work_cancel(hw->wiphy, &arsta->update_wk);
+
+ if (ahvif->vdev_type == WMI_VDEV_TYPE_STA) {
ath12k_bss_disassoc(ar, arvif);
ret = ath12k_mac_vdev_stop(arvif);
if (ret)
@@ -4622,7 +4969,7 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "Removed peer: %pM for VDEV: %d\n",
sta->addr, arvif->vdev_id);
- ath12k_mac_dec_num_stations(arvif, sta);
+ ath12k_mac_dec_num_stations(arvif, arsta);
spin_lock_bh(&ar->ab->base_lock);
peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
if (peer && peer->sta == sta) {
@@ -4637,12 +4984,20 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
kfree(arsta->rx_stats);
arsta->rx_stats = NULL;
+
+ if (arsta->link_id < IEEE80211_MLD_MAX_NUM_LINKS) {
+ rcu_assign_pointer(ahsta->link[arsta->link_id], NULL);
+ synchronize_rcu();
+ ahsta->links_map &= ~(BIT(arsta->link_id));
+ arsta->link_id = ATH12K_INVALID_LINK_ID;
+ arsta->ahsta = NULL;
+ }
} else if (old_state == IEEE80211_STA_AUTH &&
new_state == IEEE80211_STA_ASSOC &&
(vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_MESH_POINT ||
vif->type == NL80211_IFTYPE_ADHOC)) {
- ret = ath12k_station_assoc(ar, vif, sta, false);
+ ret = ath12k_station_assoc(ar, arvif, arsta, false);
if (ret)
ath12k_warn(ar->ab, "Failed to associate station: %pM\n",
sta->addr);
@@ -4686,14 +5041,12 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
(vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_MESH_POINT ||
vif->type == NL80211_IFTYPE_ADHOC)) {
- ret = ath12k_station_disassoc(ar, vif, sta);
+ ret = ath12k_station_disassoc(ar, arvif, arsta);
if (ret)
ath12k_warn(ar->ab, "Failed to disassociate station: %pM\n",
sta->addr);
}
- mutex_unlock(&ar->conf_mutex);
-
return ret;
}
@@ -4703,25 +5056,32 @@ static int ath12k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw,
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
int ret;
s16 txpwr;
+ lockdep_assert_wiphy(hw->wiphy);
+
+ arvif = &ahvif->deflink;
+
if (sta->deflink.txpwr.type == NL80211_TX_POWER_AUTOMATIC) {
txpwr = 0;
} else {
txpwr = sta->deflink.txpwr.power;
- if (!txpwr)
- return -EINVAL;
+ if (!txpwr) {
+ ret = -EINVAL;
+ goto out;
+ }
}
- if (txpwr > ATH12K_TX_POWER_MAX_VAL || txpwr < ATH12K_TX_POWER_MIN_VAL)
- return -EINVAL;
+ if (txpwr > ATH12K_TX_POWER_MAX_VAL || txpwr < ATH12K_TX_POWER_MIN_VAL) {
+ ret = -EINVAL;
+ goto out;
+ }
ar = ath12k_ah_to_ar(ah, 0);
- mutex_lock(&ar->conf_mutex);
-
ret = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
WMI_PEER_USE_FIXED_PWR, txpwr);
if (ret) {
@@ -4731,20 +5091,26 @@ static int ath12k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw,
}
out:
- mutex_unlock(&ar->conf_mutex);
return ret;
}
static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ieee80211_link_sta *link_sta,
u32 changed)
{
+ struct ieee80211_sta *sta = link_sta->sta;
struct ath12k *ar;
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_sta *arsta;
+ struct ath12k_link_vif *arvif;
struct ath12k_peer *peer;
u32 bw, smps;
+ /* TODO: use proper link id once link sta specific rc update support is
+ * available in mac80211.
+ */
+ u8 link_id = ATH12K_DEFAULT_LINK_ID;
ar = ath12k_get_ar_by_vif(hw, vif);
if (!ar) {
@@ -4752,11 +5118,27 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
return;
}
+ rcu_read_lock();
+ arvif = rcu_dereference(ahvif->link[link_id]);
+ if (!arvif) {
+ ath12k_warn(ar->ab, "mac sta rc update failed to fetch link vif on link id %u for peer %pM\n",
+ link_id, sta->addr);
+ rcu_read_unlock();
+ return;
+ }
+ arsta = rcu_dereference(ahsta->link[link_id]);
+ if (!arsta) {
+ rcu_read_unlock();
+ ath12k_warn(ar->ab, "mac sta rc update failed to fetch link sta on link id %u for peer %pM\n",
+ link_id, sta->addr);
+ return;
+ }
spin_lock_bh(&ar->ab->base_lock);
peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
if (!peer) {
spin_unlock_bh(&ar->ab->base_lock);
+ rcu_read_unlock();
ath12k_warn(ar->ab, "mac sta rc update failed to find peer %pM on vdev %i\n",
sta->addr, arvif->vdev_id);
return;
@@ -4808,17 +5190,20 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
spin_unlock_bh(&ar->data_lock);
- ieee80211_queue_work(hw, &arsta->update_wk);
+ wiphy_work_queue(hw->wiphy, &arsta->update_wk);
+
+ rcu_read_unlock();
}
-static int ath12k_conf_tx_uapsd(struct ath12k_vif *arvif,
+static int ath12k_conf_tx_uapsd(struct ath12k_link_vif *arvif,
u16 ac, bool enable)
{
struct ath12k *ar = arvif->ar;
+ struct ath12k_vif *ahvif = arvif->ahvif;
u32 value;
int ret;
- if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
+ if (ahvif->vdev_type != WMI_VDEV_TYPE_STA)
return 0;
switch (ac) {
@@ -4841,19 +5226,19 @@ static int ath12k_conf_tx_uapsd(struct ath12k_vif *arvif,
}
if (enable)
- arvif->u.sta.uapsd |= value;
+ ahvif->u.sta.uapsd |= value;
else
- arvif->u.sta.uapsd &= ~value;
+ ahvif->u.sta.uapsd &= ~value;
ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
WMI_STA_PS_PARAM_UAPSD,
- arvif->u.sta.uapsd);
+ ahvif->u.sta.uapsd);
if (ret) {
ath12k_warn(ar->ab, "could not set uapsd params %d\n", ret);
goto exit;
}
- if (arvif->u.sta.uapsd)
+ if (ahvif->u.sta.uapsd)
value = WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD;
else
value = WMI_STA_PS_RX_WAKE_POLICY_WAKE;
@@ -4868,8 +5253,7 @@ exit:
return ret;
}
-static int ath12k_mac_conf_tx(struct ath12k_vif *arvif,
- unsigned int link_id, u16 ac,
+static int ath12k_mac_conf_tx(struct ath12k_link_vif *arvif, u16 ac,
const struct ieee80211_tx_queue_params *params)
{
struct wmi_wmm_params_arg *p = NULL;
@@ -4877,7 +5261,7 @@ static int ath12k_mac_conf_tx(struct ath12k_vif *arvif,
struct ath12k_base *ab = ar->ab;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
switch (ac) {
case IEEE80211_AC_VO:
@@ -4926,26 +5310,30 @@ static int ath12k_mac_op_conf_tx(struct ieee80211_hw *hw,
unsigned int link_id, u16 ac,
const struct ieee80211_tx_queue_params *params)
{
- struct ath12k *ar;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
- struct ath12k_vif_cache *cache = arvif->cache;
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
+ struct ath12k_vif_cache *cache;
int ret;
- ar = ath12k_get_ar_by_vif(hw, vif);
- if (!ar) {
- /* cache the info and apply after vdev is created */
- cache = ath12k_arvif_get_cache(arvif);
+ lockdep_assert_wiphy(hw->wiphy);
+
+ if (link_id >= IEEE80211_MLD_MAX_NUM_LINKS)
+ return -EINVAL;
+
+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
+ if (!arvif || !arvif->is_created) {
+ cache = ath12k_ahvif_get_link_cache(ahvif, link_id);
if (!cache)
return -ENOSPC;
+
cache->tx_conf.changed = true;
cache->tx_conf.ac = ac;
cache->tx_conf.tx_queue_params = *params;
+
return 0;
}
- mutex_lock(&ar->conf_mutex);
- ret = ath12k_mac_conf_tx(arvif, link_id, ac, params);
- mutex_unlock(&ar->conf_mutex);
+ ret = ath12k_mac_conf_tx(arvif, ac, params);
return ret;
}
@@ -5016,10 +5404,11 @@ ath12k_create_ht_cap(struct ath12k *ar, u32 ar_ht_cap, u32 rate_cap_rx_chainmask
return ht_cap;
}
-static int ath12k_mac_set_txbf_conf(struct ath12k_vif *arvif)
+static int ath12k_mac_set_txbf_conf(struct ath12k_link_vif *arvif)
{
u32 value = 0;
struct ath12k *ar = arvif->ar;
+ struct ath12k_vif *ahvif = arvif->ahvif;
int nsts;
int sound_dim;
u32 vht_cap = ar->pdev->cap.vht_cap;
@@ -5047,7 +5436,7 @@ static int ath12k_mac_set_txbf_conf(struct ath12k_vif *arvif)
value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFER;
if ((vht_cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) &&
- arvif->vdev_type == WMI_VDEV_TYPE_AP)
+ ahvif->vdev_type == WMI_VDEV_TYPE_AP)
value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFER;
}
@@ -5055,7 +5444,7 @@ static int ath12k_mac_set_txbf_conf(struct ath12k_vif *arvif)
value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFEE;
if ((vht_cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) &&
- arvif->vdev_type == WMI_VDEV_TYPE_STA)
+ ahvif->vdev_type == WMI_VDEV_TYPE_STA)
value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFEE;
}
@@ -5612,7 +6001,7 @@ static int __ath12k_set_antenna(struct ath12k *ar, u32 tx_ant, u32 rx_ant)
struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (ath12k_check_chain_mask(ar, tx_ant, true))
return -EINVAL;
@@ -5716,7 +6105,7 @@ static int ath12k_mac_vif_txmgmt_idr_remove(int buf_id, void *skb, void *ctx)
return 0;
}
-static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_vif *arvif,
+static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_link_vif *arvif,
struct sk_buff *skb)
{
struct ath12k_base *ab = ar->ab;
@@ -5784,7 +6173,8 @@ static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work)
{
struct ath12k *ar = container_of(work, struct ath12k, wmi_mgmt_tx_work);
struct ath12k_skb_cb *skb_cb;
- struct ath12k_vif *arvif;
+ struct ath12k_vif *ahvif;
+ struct ath12k_link_vif *arvif;
struct sk_buff *skb;
int ret;
@@ -5796,8 +6186,8 @@ static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work)
continue;
}
- arvif = ath12k_vif_to_arvif(skb_cb->vif);
-
+ ahvif = ath12k_vif_to_ahvif(skb_cb->vif);
+ arvif = &ahvif->deflink;
if (ar->allocated_vdev_map & (1LL << arvif->vdev_id)) {
ret = ath12k_mac_mgmt_tx_wmi(ar, arvif, skb);
if (ret) {
@@ -5852,18 +6242,18 @@ static void ath12k_mac_add_p2p_noa_ie(struct ath12k *ar,
struct sk_buff *skb,
bool is_prb_rsp)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
if (likely(!is_prb_rsp))
return;
spin_lock_bh(&ar->data_lock);
- if (arvif->u.ap.noa_data &&
- !pskb_expand_head(skb, 0, arvif->u.ap.noa_len,
+ if (ahvif->u.ap.noa_data &&
+ !pskb_expand_head(skb, 0, ahvif->u.ap.noa_len,
GFP_ATOMIC))
- skb_put_data(skb, arvif->u.ap.noa_data,
- arvif->u.ap.noa_len);
+ skb_put_data(skb, ahvif->u.ap.noa_data,
+ ahvif->u.ap.noa_len);
spin_unlock_bh(&ar->data_lock);
}
@@ -5875,7 +6265,8 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw,
struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_vif *vif = info->control.vif;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif = &ahvif->deflink;
struct ath12k *ar = arvif->ar;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_key_conf *key = info->control.hw_key;
@@ -5939,8 +6330,7 @@ static int ath12k_mac_start(struct ath12k *ar)
int ret;
lockdep_assert_held(&ah->hw_mutex);
-
- mutex_lock(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PMF_QOS,
1, pdev->pdev_id);
@@ -6025,14 +6415,11 @@ static int ath12k_mac_start(struct ath12k *ar)
}
}
- mutex_unlock(&ar->conf_mutex);
-
rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx],
&ab->pdevs[ar->pdev_idx]);
return 0;
err:
- mutex_unlock(&ar->conf_mutex);
return ret;
}
@@ -6052,6 +6439,8 @@ static int ath12k_mac_op_start(struct ieee80211_hw *hw)
struct ath12k *ar;
int ret, i;
+ lockdep_assert_wiphy(hw->wiphy);
+
ath12k_drain_tx(ah);
guard(mutex)(&ah->hw_mutex);
@@ -6158,15 +6547,14 @@ static void ath12k_mac_stop(struct ath12k *ar)
int ret;
lockdep_assert_held(&ah->hw_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- mutex_lock(&ar->conf_mutex);
ret = ath12k_mac_config_mon_status_default(ar, false);
if (ret && (ret != -EOPNOTSUPP))
ath12k_err(ar->ab, "failed to clear rx_filter for monitor status ring: (%d)\n",
ret);
clear_bit(ATH12K_CAC_RUNNING, &ar->dev_flags);
- mutex_unlock(&ar->conf_mutex);
cancel_delayed_work_sync(&ar->scan.timeout);
cancel_work_sync(&ar->regd_update_work);
@@ -6192,6 +6580,8 @@ static void ath12k_mac_op_stop(struct ieee80211_hw *hw, bool suspend)
struct ath12k *ar;
int i;
+ lockdep_assert_wiphy(hw->wiphy);
+
ath12k_drain_tx(ah);
mutex_lock(&ah->hw_mutex);
@@ -6205,7 +6595,7 @@ static void ath12k_mac_op_stop(struct ieee80211_hw *hw, bool suspend)
}
static u8
-ath12k_mac_get_vdev_stats_id(struct ath12k_vif *arvif)
+ath12k_mac_get_vdev_stats_id(struct ath12k_link_vif *arvif)
{
struct ath12k_base *ab = arvif->ar->ab;
u8 vdev_stats_id = 0;
@@ -6227,19 +6617,22 @@ ath12k_mac_get_vdev_stats_id(struct ath12k_vif *arvif)
return vdev_stats_id;
}
-static int ath12k_mac_setup_vdev_params_mbssid(struct ath12k_vif *arvif,
+static int ath12k_mac_setup_vdev_params_mbssid(struct ath12k_link_vif *arvif,
u32 *flags, u32 *tx_vdev_id)
{
- struct ieee80211_vif *tx_vif = arvif->vif->mbssid_tx_vif;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *tx_vif = ahvif->vif->mbssid_tx_vif;
struct ath12k *ar = arvif->ar;
- struct ath12k_vif *tx_arvif;
+ struct ath12k_link_vif *tx_arvif;
+ struct ath12k_vif *tx_ahvif;
if (!tx_vif)
return 0;
- tx_arvif = ath12k_vif_to_arvif(tx_vif);
+ tx_ahvif = ath12k_vif_to_ahvif(tx_vif);
+ tx_arvif = &tx_ahvif->deflink;
- if (arvif->vif->bss_conf.nontransmitted) {
+ if (ahvif->vif->bss_conf.nontransmitted) {
if (ar->ah->hw->wiphy != ieee80211_vif_to_wdev(tx_vif)->wiphy)
return -EINVAL;
@@ -6251,22 +6644,23 @@ static int ath12k_mac_setup_vdev_params_mbssid(struct ath12k_vif *arvif,
return -EINVAL;
}
- if (arvif->vif->bss_conf.ema_ap)
+ if (ahvif->vif->bss_conf.ema_ap)
*flags |= WMI_VDEV_MBSSID_FLAGS_EMA_MODE;
return 0;
}
-static int ath12k_mac_setup_vdev_create_arg(struct ath12k_vif *arvif,
+static int ath12k_mac_setup_vdev_create_arg(struct ath12k_link_vif *arvif,
struct ath12k_wmi_vdev_create_arg *arg)
{
struct ath12k *ar = arvif->ar;
struct ath12k_pdev *pdev = ar->pdev;
+ struct ath12k_vif *ahvif = arvif->ahvif;
int ret;
arg->if_id = arvif->vdev_id;
- arg->type = arvif->vdev_type;
- arg->subtype = arvif->vdev_subtype;
+ arg->type = ahvif->vdev_type;
+ arg->subtype = ahvif->vdev_subtype;
arg->pdev_id = pdev->pdev_id;
arg->mbssid_flags = WMI_VDEV_MBSSID_FLAGS_NON_MBSSID_AP;
@@ -6333,14 +6727,15 @@ ath12k_mac_prepare_he_mode(struct ath12k_pdev *pdev, u32 viftype)
}
static int ath12k_set_he_mu_sounding_mode(struct ath12k *ar,
- struct ath12k_vif *arvif)
+ struct ath12k_link_vif *arvif)
{
u32 param_id, param_value;
struct ath12k_base *ab = ar->ab;
+ struct ath12k_vif *ahvif = arvif->ahvif;
int ret;
param_id = WMI_VDEV_PARAM_SET_HEMU_MODE;
- param_value = ath12k_mac_prepare_he_mode(ar->pdev, arvif->vif->type);
+ param_value = ath12k_mac_prepare_he_mode(ar->pdev, ahvif->vif->type);
ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
param_id, param_value);
if (ret) {
@@ -6363,9 +6758,10 @@ static int ath12k_set_he_mu_sounding_mode(struct ath12k *ar,
return ret;
}
-static void ath12k_mac_update_vif_offload(struct ath12k_vif *arvif)
+static void ath12k_mac_update_vif_offload(struct ath12k_link_vif *arvif)
{
- struct ieee80211_vif *vif = arvif->vif;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
struct ath12k *ar = arvif->ar;
struct ath12k_base *ab = ar->ab;
u32 param_id, param_value;
@@ -6378,14 +6774,14 @@ static void ath12k_mac_update_vif_offload(struct ath12k_vif *arvif)
IEEE80211_OFFLOAD_DECAP_ENABLED);
if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED)
- arvif->tx_encap_type = ATH12K_HW_TXRX_ETHERNET;
+ ahvif->tx_encap_type = ATH12K_HW_TXRX_ETHERNET;
else if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags))
- arvif->tx_encap_type = ATH12K_HW_TXRX_RAW;
+ ahvif->tx_encap_type = ATH12K_HW_TXRX_RAW;
else
- arvif->tx_encap_type = ATH12K_HW_TXRX_NATIVE_WIFI;
+ ahvif->tx_encap_type = ATH12K_HW_TXRX_NATIVE_WIFI;
ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
- param_id, arvif->tx_encap_type);
+ param_id, ahvif->tx_encap_type);
if (ret) {
ath12k_warn(ab, "failed to set vdev %d tx encap mode: %d\n",
arvif->vdev_id, ret);
@@ -6412,57 +6808,86 @@ static void ath12k_mac_update_vif_offload(struct ath12k_vif *arvif)
static void ath12k_mac_op_update_vif_offload(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
+ unsigned long links;
+ int link_id;
- ath12k_mac_update_vif_offload(arvif);
+ lockdep_assert_wiphy(hw->wiphy);
+
+ if (vif->valid_links) {
+ links = vif->valid_links;
+ for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
+ if (!(arvif && arvif->ar))
+ continue;
+
+ ath12k_mac_update_vif_offload(arvif);
+ }
+
+ return;
+ }
+
+ ath12k_mac_update_vif_offload(&ahvif->deflink);
}
-static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif)
+int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
{
struct ath12k_hw *ah = ar->ah;
struct ath12k_base *ab = ar->ab;
struct ieee80211_hw *hw = ah->hw;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
struct ath12k_wmi_vdev_create_arg vdev_arg = {0};
struct ath12k_wmi_peer_create_arg peer_param;
+ struct ieee80211_bss_conf *link_conf;
u32 param_id, param_value;
u16 nss;
int i;
int ret, vdev_id;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(hw->wiphy);
+
+ link_conf = wiphy_dereference(hw->wiphy, vif->link_conf[arvif->link_id]);
+ if (!link_conf) {
+ ath12k_warn(ar->ab, "unable to access bss link conf in vdev create for vif %pM link %u\n",
+ vif->addr, arvif->link_id);
+ return -ENOLINK;
+ }
+
+ memcpy(arvif->bssid, link_conf->addr, ETH_ALEN);
arvif->ar = ar;
vdev_id = __ffs64(ab->free_vdev_map);
arvif->vdev_id = vdev_id;
- arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
+ ahvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
switch (vif->type) {
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_STATION:
- arvif->vdev_type = WMI_VDEV_TYPE_STA;
+ ahvif->vdev_type = WMI_VDEV_TYPE_STA;
if (vif->p2p)
- arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_CLIENT;
+ ahvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_CLIENT;
break;
case NL80211_IFTYPE_MESH_POINT:
- arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH_11S;
+ ahvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH_11S;
fallthrough;
case NL80211_IFTYPE_AP:
- arvif->vdev_type = WMI_VDEV_TYPE_AP;
+ ahvif->vdev_type = WMI_VDEV_TYPE_AP;
if (vif->p2p)
- arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_GO;
+ ahvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_GO;
break;
case NL80211_IFTYPE_MONITOR:
- arvif->vdev_type = WMI_VDEV_TYPE_MONITOR;
+ ahvif->vdev_type = WMI_VDEV_TYPE_MONITOR;
ar->monitor_vdev_id = vdev_id;
break;
case NL80211_IFTYPE_P2P_DEVICE:
- arvif->vdev_type = WMI_VDEV_TYPE_STA;
- arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE;
+ ahvif->vdev_type = WMI_VDEV_TYPE_STA;
+ ahvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE;
break;
default:
WARN_ON(1);
@@ -6470,7 +6895,7 @@ static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif)
}
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev create id %d type %d subtype %d map %llx\n",
- arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype,
+ arvif->vdev_id, ahvif->vdev_type, ahvif->vdev_subtype,
ab->free_vdev_map);
vif->cab_queue = arvif->vdev_id % (ATH12K_HW_MAX_QUEUES - 1);
@@ -6484,11 +6909,11 @@ static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif)
goto err;
}
- ret = ath12k_wmi_vdev_create(ar, vif->addr, &vdev_arg);
+ ret = ath12k_wmi_vdev_create(ar, arvif->bssid, &vdev_arg);
if (ret) {
ath12k_warn(ab, "failed to create WMI vdev %d: %d\n",
arvif->vdev_id, ret);
- goto err;
+ return ret;
}
ar->num_created_vdevs++;
@@ -6513,10 +6938,10 @@ static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif)
goto err_vdev_del;
}
- switch (arvif->vdev_type) {
+ switch (ahvif->vdev_type) {
case WMI_VDEV_TYPE_AP:
peer_param.vdev_id = arvif->vdev_id;
- peer_param.peer_addr = vif->addr;
+ peer_param.peer_addr = arvif->bssid;
peer_param.peer_type = WMI_PEER_TYPE_DEFAULT;
ret = ath12k_peer_create(ar, arvif, NULL, &peer_param);
if (ret) {
@@ -6589,29 +7014,28 @@ static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif)
}
ath12k_dp_vdev_tx_attach(ar, arvif);
-
if (vif->type != NL80211_IFTYPE_MONITOR && ar->monitor_conf_enabled)
ath12k_mac_monitor_vdev_create(ar);
- arvif->ar = ar;
return ret;
err_peer_del:
- if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
+ if (ahvif->vdev_type == WMI_VDEV_TYPE_AP) {
reinit_completion(&ar->peer_delete_done);
- ret = ath12k_wmi_send_peer_delete_cmd(ar, vif->addr,
+ ret = ath12k_wmi_send_peer_delete_cmd(ar, arvif->bssid,
arvif->vdev_id);
if (ret) {
ath12k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n",
- arvif->vdev_id, vif->addr);
+ arvif->vdev_id, arvif->bssid);
goto err;
}
ret = ath12k_wait_for_peer_delete_done(ar, arvif->vdev_id,
- vif->addr);
+ arvif->bssid);
if (ret)
- goto err;
+ /* KVALO: why not goto err? */
+ return ret;
ar->num_peers--;
}
@@ -6633,21 +7057,56 @@ err:
return ret;
}
-static void ath12k_mac_vif_cache_flush(struct ath12k *ar, struct ieee80211_vif *vif)
+static void ath12k_mac_vif_flush_key_cache(struct ath12k_link_vif *arvif)
+{
+ struct ath12k_key_conf *key_conf, *tmp;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ath12k_hw *ah = ahvif->ah;
+ struct ath12k_sta *ahsta;
+ struct ath12k_link_sta *arsta;
+ struct ath12k_vif_cache *cache = ahvif->cache[arvif->link_id];
+ int ret;
+
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
+ list_for_each_entry_safe(key_conf, tmp, &cache->key_conf.list, list) {
+ arsta = NULL;
+ if (key_conf->sta) {
+ ahsta = ath12k_sta_to_ahsta(key_conf->sta);
+ arsta = wiphy_dereference(ah->hw->wiphy,
+ ahsta->link[arvif->link_id]);
+ if (!arsta)
+ goto free_cache;
+ }
+
+ ret = ath12k_mac_set_key(arvif->ar, key_conf->cmd,
+ arvif, arsta,
+ key_conf->key);
+ if (ret)
+ ath12k_warn(arvif->ar->ab, "unable to apply set key param to vdev %d ret %d\n",
+ arvif->vdev_id, ret);
+free_cache:
+ list_del(&key_conf->list);
+ kfree(key_conf);
+ }
+}
+
+static void ath12k_mac_vif_cache_flush(struct ath12k *ar, struct ath12k_link_vif *arvif)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
- struct ath12k_vif_cache *cache = arvif->cache;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
+ struct ath12k_vif_cache *cache = ahvif->cache[arvif->link_id];
struct ath12k_base *ab = ar->ab;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (!cache)
return;
if (cache->tx_conf.changed) {
- ret = ath12k_mac_conf_tx(arvif, 0, cache->tx_conf.ac,
+ ret = ath12k_mac_conf_tx(arvif, cache->tx_conf.ac,
&cache->tx_conf.tx_queue_params);
if (ret)
ath12k_warn(ab,
@@ -6660,26 +7119,25 @@ static void ath12k_mac_vif_cache_flush(struct ath12k *ar, struct ieee80211_vif
cache->bss_conf_changed);
}
- if (cache->key_conf.changed) {
- ret = ath12k_mac_set_key(ar, cache->key_conf.cmd, vif, NULL,
- cache->key_conf.key);
- if (ret)
- ath12k_warn(ab, "unable to apply set key param to vdev %d ret %d\n",
- arvif->vdev_id, ret);
- }
- ath12k_arvif_put_cache(arvif);
+ if (!list_empty(&cache->key_conf.list))
+ ath12k_mac_vif_flush_key_cache(arvif);
+
+ ath12k_ahvif_put_link_cache(ahvif, arvif->link_id);
}
static struct ath12k *ath12k_mac_assign_vif_to_vdev(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
+ struct ath12k_link_vif *arvif,
struct ieee80211_chanctx_conf *ctx)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
struct ath12k_hw *ah = hw->priv;
- struct ath12k *ar, *prev_ar;
+ struct ath12k *ar;
struct ath12k_base *ab;
+ u8 link_id = arvif->link_id;
int ret;
+ lockdep_assert_wiphy(hw->wiphy);
+
if (ah->num_radio == 1)
ar = ah->radio;
else if (ctx)
@@ -6708,27 +7166,20 @@ static struct ath12k *ath12k_mac_assign_vif_to_vdev(struct ieee80211_hw *hw,
if (WARN_ON(arvif->is_started))
return NULL;
- /* backup the previously used ar ptr since arvif->ar would
- * be set to NULL after vdev delete is done
- */
- prev_ar = arvif->ar;
- mutex_lock(&prev_ar->conf_mutex);
- ret = ath12k_mac_vdev_delete(prev_ar, vif);
-
- if (ret)
- ath12k_warn(prev_ar->ab, "unable to delete vdev %d\n",
- ret);
- mutex_unlock(&prev_ar->conf_mutex);
+ ath12k_mac_remove_link_interface(hw, arvif);
+ ath12k_mac_unassign_link_vif(arvif);
}
}
ab = ar->ab;
- mutex_lock(&ar->conf_mutex);
-
if (arvif->is_created)
goto flush;
+ /* Assign arvif again here since previous radio switch block
+ * would've unassigned and cleared it.
+ */
+ arvif = ath12k_mac_assign_link_vif(ah, vif, link_id);
if (vif->type == NL80211_IFTYPE_AP &&
ar->num_peers > (ar->max_num_peers - 1)) {
ath12k_warn(ab, "failed to create vdev due to insufficient peer entry resource in firmware\n");
@@ -6741,7 +7192,7 @@ static struct ath12k *ath12k_mac_assign_vif_to_vdev(struct ieee80211_hw *hw,
goto unlock;
}
- ret = ath12k_mac_vdev_create(ar, vif);
+ ret = ath12k_mac_vdev_create(ar, arvif);
if (ret) {
ath12k_warn(ab, "failed to create vdev %pM ret %d", vif->addr, ret);
goto unlock;
@@ -6752,21 +7203,27 @@ flush:
* add_interface(), Apply any parameters for the vdev which were received
* after add_interface, corresponding to this vif.
*/
- ath12k_mac_vif_cache_flush(ar, vif);
+ ath12k_mac_vif_cache_flush(ar, arvif);
unlock:
- mutex_unlock(&ar->conf_mutex);
return arvif->ar;
}
static int ath12k_mac_op_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
int i;
- memset(arvif, 0, sizeof(*arvif));
+ lockdep_assert_wiphy(hw->wiphy);
- arvif->vif = vif;
+ memset(ahvif, 0, sizeof(*ahvif));
+
+ ahvif->ah = ah;
+ ahvif->vif = vif;
+ arvif = &ahvif->deflink;
+ arvif->ahvif = ahvif;
INIT_LIST_HEAD(&arvif->list);
INIT_DELAYED_WORK(&arvif->connection_loss_work,
@@ -6786,13 +7243,14 @@ static int ath12k_mac_op_add_interface(struct ieee80211_hw *hw,
vif->hw_queue[i] = ATH12K_HW_DEFAULT_QUEUE;
vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
-
- /* For single radio wiphy(i.e ah->num_radio is 1), create the vdev
- * during add_interface itself, for multi radio wiphy, defer the vdev
- * creation until channel_assign to determine the radio on which the
- * vdev needs to be created
+ /* For non-ml vifs, vif->addr is the actual vdev address but for
+ * ML vif link(link BSSID) address is the vdev address and it can be a
+ * different one from vif->addr (i.e ML address).
+ * Defer vdev creation until assign_chanctx or hw_scan is initiated as driver
+ * will not know if this interface is an ML vif at this point.
*/
- ath12k_mac_assign_vif_to_vdev(hw, vif, NULL);
+ ath12k_mac_assign_vif_to_vdev(hw, arvif, NULL);
+
return 0;
}
@@ -6821,14 +7279,16 @@ static void ath12k_mac_vif_unref(struct ath12k_dp *dp, struct ieee80211_vif *vif
}
}
-static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ieee80211_vif *vif)
+static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ath12k_link_vif *arvif)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
struct ath12k_base *ab = ar->ab;
unsigned long time_left;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
reinit_completion(&ar->vdev_delete_done);
ret = ath12k_wmi_vdev_delete(ar, arvif->vdev_id);
@@ -6849,7 +7309,7 @@ static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ieee80211_vif *vif)
ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id);
ar->num_created_vdevs--;
- if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
+ if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
ar->monitor_vdev_id = -1;
ar->monitor_vdev_created = false;
} else if (ar->monitor_vdev_created && !ar->monitor_started) {
@@ -6865,7 +7325,7 @@ err_vdev_del:
spin_unlock_bh(&ar->data_lock);
ath12k_peer_cleanup(ar, arvif->vdev_id);
- ath12k_arvif_put_cache(arvif);
+ ath12k_ahvif_put_link_cache(ahvif, arvif->link_id);
idr_for_each(&ar->txmgmt_idr,
ath12k_mac_vif_txmgmt_idr_remove, vif);
@@ -6886,39 +7346,24 @@ err_vdev_del:
static void ath12k_mac_op_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
- struct ath12k_base *ab;
- struct ath12k *ar;
- int ret;
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
+ u8 link_id;
- if (!arvif->is_created) {
+ lockdep_assert_wiphy(hw->wiphy);
+
+ for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
/* if we cached some config but never received assign chanctx,
* free the allocated cache.
*/
- ath12k_arvif_put_cache(arvif);
- return;
- }
-
- ar = arvif->ar;
- ab = ar->ab;
-
- cancel_delayed_work_sync(&arvif->connection_loss_work);
-
- mutex_lock(&ar->conf_mutex);
-
- ath12k_dbg(ab, ATH12K_DBG_MAC, "mac remove interface (vdev %d)\n",
- arvif->vdev_id);
+ ath12k_ahvif_put_link_cache(ahvif, link_id);
+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
+ if (!arvif || !arvif->is_created)
+ continue;
- if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
- ret = ath12k_peer_delete(ar, arvif->vdev_id, vif->addr);
- if (ret)
- ath12k_warn(ab, "failed to submit AP self-peer removal on vdev %d: %d\n",
- arvif->vdev_id, ret);
+ ath12k_mac_remove_link_interface(hw, arvif);
+ ath12k_mac_unassign_link_vif(arvif);
}
-
- ath12k_mac_vdev_delete(ar, vif);
-
- mutex_unlock(&ar->conf_mutex);
}
/* FIXME: Has to be verified. */
@@ -6937,7 +7382,7 @@ static void ath12k_mac_configure_filter(struct ath12k *ar,
bool reset_flag;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
ar->filter_flags = total_flags;
@@ -6962,14 +7407,12 @@ static void ath12k_mac_op_configure_filter(struct ieee80211_hw *hw,
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
- ar = ath12k_ah_to_ar(ah, 0);
+ lockdep_assert_wiphy(hw->wiphy);
- mutex_lock(&ar->conf_mutex);
+ ar = ath12k_ah_to_ar(ah, 0);
*total_flags &= SUPPORTED_FILTERS;
ath12k_mac_configure_filter(ar, *total_flags);
-
- mutex_unlock(&ar->conf_mutex);
}
static int ath12k_mac_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
@@ -6979,11 +7422,11 @@ static int ath12k_mac_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *
struct ath12k *ar;
int i;
+ lockdep_assert_wiphy(hw->wiphy);
+
for_each_ar(ah, ar, i) {
- mutex_lock(&ar->conf_mutex);
antennas_rx = max_t(u32, antennas_rx, ar->cfg_rx_chainmask);
antennas_tx = max_t(u32, antennas_tx, ar->cfg_tx_chainmask);
- mutex_unlock(&ar->conf_mutex);
}
*tx_ant = antennas_tx;
@@ -6999,10 +7442,10 @@ static int ath12k_mac_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx
int ret = 0;
int i;
+ lockdep_assert_wiphy(hw->wiphy);
+
for_each_ar(ah, ar, i) {
- mutex_lock(&ar->conf_mutex);
ret = __ath12k_set_antenna(ar, tx_ant, rx_ant);
- mutex_unlock(&ar->conf_mutex);
if (ret)
break;
}
@@ -7010,13 +7453,13 @@ static int ath12k_mac_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx
return ret;
}
-static int ath12k_mac_ampdu_action(struct ath12k_vif *arvif,
+static int ath12k_mac_ampdu_action(struct ath12k_link_vif *arvif,
struct ieee80211_ampdu_params *params)
{
struct ath12k *ar = arvif->ar;
int ret = -EINVAL;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
switch (params->action) {
case IEEE80211_AMPDU_RX_START:
@@ -7046,19 +7489,20 @@ static int ath12k_mac_op_ampdu_action(struct ieee80211_hw *hw,
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
int ret = -EINVAL;
+ lockdep_assert_wiphy(hw->wiphy);
+
ar = ath12k_get_ar_by_vif(hw, vif);
if (!ar)
return -EINVAL;
ar = ath12k_ah_to_ar(ah, 0);
+ arvif = &ahvif->deflink;
- mutex_lock(&ar->conf_mutex);
ret = ath12k_mac_ampdu_action(arvif, params);
- mutex_unlock(&ar->conf_mutex);
-
if (ret)
ath12k_warn(ar->ab, "pdev idx %d unable to perform ampdu action %d ret %d\n",
ar->pdev_idx, params->action, ret);
@@ -7072,6 +7516,8 @@ static int ath12k_mac_op_add_chanctx(struct ieee80211_hw *hw,
struct ath12k *ar;
struct ath12k_base *ab;
+ lockdep_assert_wiphy(hw->wiphy);
+
ar = ath12k_get_ar_by_ctx(hw, ctx);
if (!ar)
return -EINVAL;
@@ -7082,8 +7528,6 @@ static int ath12k_mac_op_add_chanctx(struct ieee80211_hw *hw,
"mac chanctx add freq %u width %d ptr %p\n",
ctx->def.chan->center_freq, ctx->def.width, ctx);
- mutex_lock(&ar->conf_mutex);
-
spin_lock_bh(&ar->data_lock);
/* TODO: In case of multiple channel context, populate rx_channel from
* Rx PPDU desc information.
@@ -7091,8 +7535,6 @@ static int ath12k_mac_op_add_chanctx(struct ieee80211_hw *hw,
ar->rx_channel = ctx->def.chan;
spin_unlock_bh(&ar->data_lock);
- mutex_unlock(&ar->conf_mutex);
-
return 0;
}
@@ -7102,6 +7544,8 @@ static void ath12k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
struct ath12k *ar;
struct ath12k_base *ab;
+ lockdep_assert_wiphy(hw->wiphy);
+
ar = ath12k_get_ar_by_ctx(hw, ctx);
if (!ar)
return;
@@ -7112,16 +7556,12 @@ static void ath12k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
"mac chanctx remove freq %u width %d ptr %p\n",
ctx->def.chan->center_freq, ctx->def.width, ctx);
- mutex_lock(&ar->conf_mutex);
-
spin_lock_bh(&ar->data_lock);
/* TODO: In case of there is one more channel context left, populate
* rx_channel with the channel of that remaining channel context.
*/
ar->rx_channel = NULL;
spin_unlock_bh(&ar->data_lock);
-
- mutex_unlock(&ar->conf_mutex);
}
static enum wmi_phy_mode
@@ -7188,7 +7628,7 @@ ath12k_mac_check_down_grade_phy_mode(struct ath12k *ar,
}
static int
-ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
+ath12k_mac_vdev_start_restart(struct ath12k_link_vif *arvif,
struct ieee80211_chanctx_conf *ctx,
bool restart)
{
@@ -7196,10 +7636,11 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
struct ath12k_base *ab = ar->ab;
struct wmi_vdev_start_req_arg arg = {};
const struct cfg80211_chan_def *chandef = &ctx->def;
- int he_support = arvif->vif->bss_conf.he_support;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ int he_support = ahvif->vif->bss_conf.he_support;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
reinit_completion(&ar->vdev_setup_done);
@@ -7215,7 +7656,7 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
arg.mode = ath12k_mac_check_down_grade_phy_mode(ar, arg.mode,
chandef->chan->band,
- arvif->vif->type);
+ ahvif->vif->type);
arg.min_power = 0;
arg.max_power = chandef->chan->max_power * 2;
arg.max_reg_power = chandef->chan->max_reg_power * 2;
@@ -7235,10 +7676,10 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
return ret;
}
- if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
- arg.ssid = arvif->u.ap.ssid;
- arg.ssid_len = arvif->u.ap.ssid_len;
- arg.hidden_ssid = arvif->u.ap.hidden_ssid;
+ if (ahvif->vdev_type == WMI_VDEV_TYPE_AP) {
+ arg.ssid = ahvif->u.ap.ssid;
+ arg.ssid_len = ahvif->u.ap.ssid_len;
+ arg.hidden_ssid = ahvif->u.ap.hidden_ssid;
/* For now allow DFS for AP mode */
arg.chan_radar = !!(chandef->chan->flags & IEEE80211_CHAN_RADAR);
@@ -7285,7 +7726,7 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
ar->num_started_vdevs++;
ath12k_dbg(ab, ATH12K_DBG_MAC, "vdev %pM started, vdev_id %d\n",
- arvif->vif->addr, arvif->vdev_id);
+ ahvif->vif->addr, arvif->vdev_id);
/* Enable CAC Flag in the driver by checking the channel DFS cac time,
* i.e dfs_cac_ms value which will be valid only for radar channels
@@ -7294,7 +7735,7 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
* during CAC.
*/
/* TODO: Set the flag for other interface types as required */
- if (arvif->vdev_type == WMI_VDEV_TYPE_AP &&
+ if (arvif->ahvif->vdev_type == WMI_VDEV_TYPE_AP &&
chandef->chan->dfs_cac_ms &&
chandef->chan->dfs_state == NL80211_DFS_USABLE) {
set_bit(ATH12K_CAC_RUNNING, &ar->dev_flags);
@@ -7311,13 +7752,13 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
return 0;
}
-static int ath12k_mac_vdev_start(struct ath12k_vif *arvif,
+static int ath12k_mac_vdev_start(struct ath12k_link_vif *arvif,
struct ieee80211_chanctx_conf *ctx)
{
return ath12k_mac_vdev_start_restart(arvif, ctx, false);
}
-static int ath12k_mac_vdev_restart(struct ath12k_vif *arvif,
+static int ath12k_mac_vdev_restart(struct ath12k_link_vif *arvif,
struct ieee80211_chanctx_conf *ctx)
{
return ath12k_mac_vdev_start_restart(arvif, ctx, true);
@@ -7335,8 +7776,13 @@ static void
ath12k_mac_change_chanctx_cnt_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_mac_change_chanctx_arg *arg = data;
+ struct ath12k_link_vif *arvif;
+
+ lockdep_assert_wiphy(ahvif->ah->hw->wiphy);
+
+ arvif = &ahvif->deflink;
if (arvif->ar != arg->ar)
return;
@@ -7351,9 +7797,14 @@ static void
ath12k_mac_change_chanctx_fill_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_mac_change_chanctx_arg *arg = data;
struct ieee80211_chanctx_conf *ctx;
+ struct ath12k_link_vif *arvif;
+
+ lockdep_assert_wiphy(ahvif->ah->hw->wiphy);
+
+ arvif = &ahvif->deflink;
if (arvif->ar != arg->ar)
return;
@@ -7397,13 +7848,13 @@ static u32 ath12k_mac_nlwidth_to_wmiwidth(enum nl80211_chan_width width)
}
static int ath12k_mac_update_peer_puncturing_width(struct ath12k *ar,
- struct ath12k_vif *arvif,
+ struct ath12k_link_vif *arvif,
struct cfg80211_chan_def def)
{
u32 param_id, param_value;
int ret;
- if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
+ if (arvif->ahvif->vdev_type != WMI_VDEV_TYPE_STA)
return 0;
param_id = WMI_PEER_CHWIDTH_PUNCTURE_20MHZ_BITMAP;
@@ -7429,17 +7880,19 @@ ath12k_mac_update_vif_chan(struct ath12k *ar,
{
struct ath12k_wmi_vdev_up_params params = {};
struct ath12k_base *ab = ar->ab;
+ struct ath12k_link_vif *arvif;
struct ieee80211_vif *vif;
- struct ath12k_vif *arvif;
+ struct ath12k_vif *ahvif;
int ret;
int i;
bool monitor_vif = false;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
for (i = 0; i < n_vifs; i++) {
vif = vifs[i].vif;
- arvif = ath12k_vif_to_arvif(vif);
+ ahvif = ath12k_vif_to_ahvif(vif);
+ arvif = &ahvif->deflink;
if (vif->type == NL80211_IFTYPE_MONITOR)
monitor_vif = true;
@@ -7489,10 +7942,14 @@ ath12k_mac_update_vif_chan(struct ath12k *ar,
memset(&params, 0, sizeof(params));
params.vdev_id = arvif->vdev_id;
- params.aid = arvif->aid;
+ params.aid = ahvif->aid;
params.bssid = arvif->bssid;
if (vif->mbssid_tx_vif) {
- params.tx_bssid = ath12k_vif_to_arvif(vif->mbssid_tx_vif)->bssid;
+ struct ath12k_vif *ahvif =
+ ath12k_vif_to_ahvif(vif->mbssid_tx_vif);
+ struct ath12k_link_vif *arvif = &ahvif->deflink;
+
+ params.tx_bssid = arvif->bssid;
params.nontx_profile_idx = vif->bss_conf.bssid_index;
params.nontx_profile_cnt = 1 << vif->bss_conf.bssid_indicator;
}
@@ -7528,7 +7985,7 @@ ath12k_mac_update_active_vif_chan(struct ath12k *ar,
struct ath12k_mac_change_chanctx_arg arg = { .ctx = ctx, .ar = ar };
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
ieee80211_iterate_active_interfaces_atomic(hw,
IEEE80211_IFACE_ITER_NORMAL,
@@ -7558,14 +8015,14 @@ static void ath12k_mac_op_change_chanctx(struct ieee80211_hw *hw,
struct ath12k *ar;
struct ath12k_base *ab;
+ lockdep_assert_wiphy(hw->wiphy);
+
ar = ath12k_get_ar_by_ctx(hw, ctx);
if (!ar)
return;
ab = ar->ab;
- mutex_lock(&ar->conf_mutex);
-
ath12k_dbg(ab, ATH12K_DBG_MAC,
"mac chanctx change freq %u width %d ptr %p changed %x\n",
ctx->def.chan->center_freq, ctx->def.width, ctx, changed);
@@ -7574,7 +8031,7 @@ static void ath12k_mac_op_change_chanctx(struct ieee80211_hw *hw,
* switch_vif_chanctx().
*/
if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL))
- goto unlock;
+ return;
if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH ||
changed & IEEE80211_CHANCTX_CHANGE_RADAR ||
@@ -7582,16 +8039,14 @@ static void ath12k_mac_op_change_chanctx(struct ieee80211_hw *hw,
ath12k_mac_update_active_vif_chan(ar, ctx);
/* TODO: Recalc radar detection */
-
-unlock:
- mutex_unlock(&ar->conf_mutex);
}
static int ath12k_start_vdev_delay(struct ath12k *ar,
- struct ath12k_vif *arvif)
+ struct ath12k_link_vif *arvif)
{
struct ath12k_base *ab = ar->ab;
- struct ieee80211_vif *vif = arvif->vif;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
int ret;
if (WARN_ON(arvif->is_started))
@@ -7605,7 +8060,7 @@ static int ath12k_start_vdev_delay(struct ath12k *ar,
return ret;
}
- if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
+ if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
ret = ath12k_monitor_vdev_up(ar, arvif->vdev_id);
if (ret) {
ath12k_warn(ab, "failed put monitor up: %d\n", ret);
@@ -7625,24 +8080,37 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_chanctx_conf *ctx)
{
+ struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
struct ath12k_base *ab;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ u8 link_id = link_conf->link_id;
+ struct ath12k_link_vif *arvif;
int ret;
+ lockdep_assert_wiphy(hw->wiphy);
+
/* For multi radio wiphy, the vdev was not created during add_interface
* create now since we have a channel ctx now to assign to a specific ar/fw
*/
- ar = ath12k_mac_assign_vif_to_vdev(hw, vif, ctx);
- if (!ar) {
+ arvif = ath12k_mac_assign_link_vif(ah, vif, link_id);
+ if (!arvif) {
WARN_ON(1);
+ return -ENOMEM;
+ }
+
+ if (!arvif->is_started) {
+ ar = ath12k_mac_assign_vif_to_vdev(hw, arvif, ctx);
+ if (!ar)
+ return -EINVAL;
+ } else {
+ ath12k_warn(arvif->ar->ab, "failed to assign chanctx for vif %pM link id %u link vif is already started",
+ vif->addr, link_id);
return -EINVAL;
}
ab = ar->ab;
- mutex_lock(&ar->conf_mutex);
-
ath12k_dbg(ab, ATH12K_DBG_MAC,
"mac chanctx assign ptr %p vdev_id %i\n",
ctx, arvif->vdev_id);
@@ -7651,8 +8119,8 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
/* for some targets bss peer must be created before vdev_start */
if (ab->hw_params->vdev_start_delay &&
- arvif->vdev_type != WMI_VDEV_TYPE_AP &&
- arvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
+ ahvif->vdev_type != WMI_VDEV_TYPE_AP &&
+ ahvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
!ath12k_peer_exist_by_vdev_id(ab, arvif->vdev_id)) {
memcpy(&arvif->chanctx, ctx, sizeof(*ctx));
ret = 0;
@@ -7664,10 +8132,11 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
goto out;
}
- if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
+ if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
ret = ath12k_mac_monitor_start(ar);
if (ret)
goto out;
+
arvif->is_started = true;
goto out;
}
@@ -7680,7 +8149,7 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
goto out;
}
- if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR && ar->monitor_vdev_created)
+ if (ahvif->vdev_type != WMI_VDEV_TYPE_MONITOR && ar->monitor_vdev_created)
ath12k_mac_monitor_start(ar);
arvif->is_started = true;
@@ -7688,8 +8157,6 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
/* TODO: Setup ps and cts/rts protection */
out:
- mutex_unlock(&ar->conf_mutex);
-
return ret;
}
@@ -7701,9 +8168,15 @@ ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
{
struct ath12k *ar;
struct ath12k_base *ab;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
+ u8 link_id = link_conf->link_id;
int ret;
+ lockdep_assert_wiphy(hw->wiphy);
+
+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
+
/* The vif is expected to be attached to an ar's VDEV.
* We leave the vif/vdev in this function as is
* and not delete the vdev symmetric to assign_vif_chanctx()
@@ -7711,32 +8184,28 @@ ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
* remove_interface() or when there is a change in channel
* that moves the vif to a new ar
*/
- if (!arvif->is_created)
+ if (!arvif || !arvif->is_created)
return;
ar = arvif->ar;
ab = ar->ab;
- mutex_lock(&ar->conf_mutex);
-
ath12k_dbg(ab, ATH12K_DBG_MAC,
"mac chanctx unassign ptr %p vdev_id %i\n",
ctx, arvif->vdev_id);
WARN_ON(!arvif->is_started);
- if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
+ if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
ret = ath12k_mac_monitor_stop(ar);
- if (ret) {
- mutex_unlock(&ar->conf_mutex);
+ if (ret)
return;
- }
arvif->is_started = false;
}
- if (arvif->vdev_type != WMI_VDEV_TYPE_STA &&
- arvif->vdev_type != WMI_VDEV_TYPE_MONITOR) {
+ if (ahvif->vdev_type != WMI_VDEV_TYPE_STA &&
+ ahvif->vdev_type != WMI_VDEV_TYPE_MONITOR) {
ath12k_bss_disassoc(ar, arvif);
ret = ath12k_mac_vdev_stop(arvif);
if (ret)
@@ -7745,11 +8214,12 @@ ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
}
arvif->is_started = false;
- if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
+ if (ahvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
ar->num_started_vdevs == 1 && ar->monitor_vdev_created)
ath12k_mac_monitor_stop(ar);
- mutex_unlock(&ar->conf_mutex);
+ ath12k_mac_remove_link_interface(hw, arvif);
+ ath12k_mac_unassign_link_vif(arvif);
}
static int
@@ -7760,35 +8230,32 @@ ath12k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
{
struct ath12k *ar;
+ lockdep_assert_wiphy(hw->wiphy);
+
ar = ath12k_get_ar_by_ctx(hw, vifs->old_ctx);
if (!ar)
return -EINVAL;
- mutex_lock(&ar->conf_mutex);
-
/* Switching channels across radio is not allowed */
- if (ar != ath12k_get_ar_by_ctx(hw, vifs->new_ctx)) {
- mutex_unlock(&ar->conf_mutex);
+ if (ar != ath12k_get_ar_by_ctx(hw, vifs->new_ctx))
return -EINVAL;
- }
ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
"mac chanctx switch n_vifs %d mode %d\n",
n_vifs, mode);
ath12k_mac_update_vif_chan(ar, vifs, n_vifs);
- mutex_unlock(&ar->conf_mutex);
-
return 0;
}
static int
ath12k_set_vdev_param_to_all_vifs(struct ath12k *ar, int param, u32 value)
{
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
int ret = 0;
- mutex_lock(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
list_for_each_entry(arvif, &ar->arvifs, list) {
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "setting mac vdev %d param %d value %d\n",
param, arvif->vdev_id, value);
@@ -7801,7 +8268,7 @@ ath12k_set_vdev_param_to_all_vifs(struct ath12k *ar, int param, u32 value)
break;
}
}
- mutex_unlock(&ar->conf_mutex);
+
return ret;
}
@@ -7814,6 +8281,8 @@ static int ath12k_mac_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
struct ath12k *ar;
int param_id = WMI_VDEV_PARAM_RTS_THRESHOLD, ret = 0, i;
+ lockdep_assert_wiphy(hw->wiphy);
+
/* Currently we set the rts threshold value to all the vifs across
* all radios of the single wiphy.
* TODO Once support for vif specific RTS threshold in mac80211 is
@@ -7843,6 +8312,9 @@ static int ath12k_mac_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
* supported. This effectively prevents mac80211 from doing frame
* fragmentation in software.
*/
+
+ lockdep_assert_wiphy(hw->wiphy);
+
return -EOPNOTSUPP;
}
@@ -7887,6 +8359,8 @@ static void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *v
struct ath12k *ar;
int i;
+ lockdep_assert_wiphy(hw->wiphy);
+
if (drop)
return;
@@ -8020,14 +8494,14 @@ ath12k_mac_get_single_legacy_rate(struct ath12k *ar,
return 0;
}
-static int ath12k_mac_set_fixed_rate_params(struct ath12k_vif *arvif,
+static int ath12k_mac_set_fixed_rate_params(struct ath12k_link_vif *arvif,
u32 rate, u8 nss, u8 sgi, u8 ldpc)
{
struct ath12k *ar = arvif->ar;
u32 vdev_param;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac set fixed rate params vdev %i rate 0x%02x nss %u sgi %u\n",
arvif->vdev_id, rate, nss, sgi);
@@ -8099,8 +8573,9 @@ ath12k_mac_vht_mcs_range_present(struct ath12k *ar,
static void ath12k_mac_set_bitrate_mask_iter(void *data,
struct ieee80211_sta *sta)
{
- struct ath12k_vif *arvif = data;
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
+ struct ath12k_link_vif *arvif = data;
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
+ struct ath12k_link_sta *arsta = &ahsta->deflink;
struct ath12k *ar = arvif->ar;
if (arsta->arvif != arvif)
@@ -8110,14 +8585,15 @@ static void ath12k_mac_set_bitrate_mask_iter(void *data,
arsta->changed |= IEEE80211_RC_SUPP_RATES_CHANGED;
spin_unlock_bh(&ar->data_lock);
- ieee80211_queue_work(ath12k_ar_to_hw(ar), &arsta->update_wk);
+ wiphy_work_queue(ath12k_ar_to_hw(ar)->wiphy, &arsta->update_wk);
}
static void ath12k_mac_disable_peer_fixed_rate(void *data,
struct ieee80211_sta *sta)
{
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
- struct ath12k_vif *arvif = data;
+ struct ath12k_link_vif *arvif = data;
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
+ struct ath12k_link_sta *arsta = &ahsta->deflink;
struct ath12k *ar = arvif->ar;
int ret;
@@ -8139,9 +8615,10 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
const struct cfg80211_bitrate_mask *mask)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
struct cfg80211_chan_def def;
- struct ath12k *ar = arvif->ar;
+ struct ath12k *ar;
enum nl80211_band band;
const u8 *ht_mcs_mask;
const u16 *vht_mcs_mask;
@@ -8153,8 +8630,15 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
int ret;
int num_rates;
- if (ath12k_mac_vif_chan(vif, &def))
- return -EPERM;
+ lockdep_assert_wiphy(hw->wiphy);
+
+ arvif = &ahvif->deflink;
+
+ ar = arvif->ar;
+ if (ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)) {
+ ret = -EPERM;
+ goto out;
+ }
band = def.chan->band;
ht_mcs_mask = mask->control[band].ht_mcs;
@@ -8183,9 +8667,9 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
arvif->vdev_id, ret);
goto out;
}
- ieee80211_iterate_stations_atomic(hw,
- ath12k_mac_disable_peer_fixed_rate,
- arvif);
+ ieee80211_iterate_stations_mtx(hw,
+ ath12k_mac_disable_peer_fixed_rate,
+ arvif);
} else if (ath12k_mac_bitrate_mask_get_single_nss(ar, band, mask,
&single_nss)) {
rate = WMI_FIXED_RATE_NONE;
@@ -8226,34 +8710,25 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
*/
ath12k_warn(ar->ab,
"Setting more than one MCS Value in bitrate mask not supported\n");
- ret = -EINVAL;
- goto out;
+ return -EINVAL;
}
- ieee80211_iterate_stations_atomic(hw,
- ath12k_mac_disable_peer_fixed_rate,
- arvif);
-
- mutex_lock(&ar->conf_mutex);
+ ieee80211_iterate_stations_mtx(hw,
+ ath12k_mac_disable_peer_fixed_rate,
+ arvif);
arvif->bitrate_mask = *mask;
- ieee80211_iterate_stations_atomic(hw,
- ath12k_mac_set_bitrate_mask_iter,
- arvif);
-
- mutex_unlock(&ar->conf_mutex);
+ ieee80211_iterate_stations_mtx(hw,
+ ath12k_mac_set_bitrate_mask_iter,
+ arvif);
}
- mutex_lock(&ar->conf_mutex);
-
ret = ath12k_mac_set_fixed_rate_params(arvif, rate, nss, sgi, ldpc);
if (ret) {
ath12k_warn(ar->ab, "failed to set fixed rate params on vdev %i: %d\n",
arvif->vdev_id, ret);
}
- mutex_unlock(&ar->conf_mutex);
-
out:
return ret;
}
@@ -8265,9 +8740,12 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
struct ath12k_base *ab;
- struct ath12k_vif *arvif;
+ struct ath12k_vif *ahvif;
+ struct ath12k_link_vif *arvif;
int recovery_count, i;
+ lockdep_assert_wiphy(hw->wiphy);
+
if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART)
return;
@@ -8280,8 +8758,6 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
ieee80211_wake_queues(hw);
for_each_ar(ah, ar, i) {
- mutex_lock(&ar->conf_mutex);
-
ab = ar->ab;
ath12k_warn(ar->ab, "pdev %d successfully recovered\n",
@@ -8306,11 +8782,12 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
}
list_for_each_entry(arvif, &ar->arvifs, list) {
+ ahvif = arvif->ahvif;
ath12k_dbg(ab, ATH12K_DBG_BOOT,
"reconfig cipher %d up %d vdev type %d\n",
- arvif->key_cipher,
+ ahvif->key_cipher,
arvif->is_up,
- arvif->vdev_type);
+ ahvif->vdev_type);
/* After trigger disconnect, then upper layer will
* trigger connect again, then the PN number of
@@ -8318,16 +8795,14 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
* side, hence PN number mismatch will not happen.
*/
if (arvif->is_up &&
- arvif->vdev_type == WMI_VDEV_TYPE_STA &&
- arvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE) {
- ieee80211_hw_restart_disconnect(arvif->vif);
+ ahvif->vdev_type == WMI_VDEV_TYPE_STA &&
+ ahvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE) {
+ ieee80211_hw_restart_disconnect(ahvif->vif);
ath12k_dbg(ab, ATH12K_DBG_BOOT,
"restart disconnect\n");
}
}
-
- mutex_unlock(&ar->conf_mutex);
}
}
@@ -8338,7 +8813,7 @@ ath12k_mac_update_bss_chan_survey(struct ath12k *ar,
int ret;
enum wmi_bss_chan_info_req_type type = WMI_BSS_SURVEY_REQ_TYPE_READ;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (!test_bit(WMI_TLV_SERVICE_BSS_CHANNEL_INFO_64, ar->ab->wmi_ab.svc_map) ||
ar->rx_channel != channel)
@@ -8370,6 +8845,8 @@ static int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx,
struct ieee80211_supported_band *sband;
struct survey_info *ar_survey;
+ lockdep_assert_wiphy(hw->wiphy);
+
if (idx >= ATH12K_NUM_CHANS)
return -ENOENT;
@@ -8403,8 +8880,6 @@ static int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx,
ar_survey = &ar->survey[idx];
- mutex_lock(&ar->conf_mutex);
-
ath12k_mac_update_bss_chan_survey(ar, &sband->channels[idx]);
spin_lock_bh(&ar->data_lock);
@@ -8416,7 +8891,6 @@ static int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx,
if (ar->rx_channel == survey->channel)
survey->filled |= SURVEY_INFO_IN_USE;
- mutex_unlock(&ar->conf_mutex);
return 0;
}
@@ -8425,7 +8899,12 @@ static void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
struct station_info *sinfo)
{
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
+ struct ath12k_link_sta *arsta;
+
+ lockdep_assert_wiphy(hw->wiphy);
+
+ arsta = &ahsta->deflink;
sinfo->rx_duration = arsta->rx_duration;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
@@ -8462,7 +8941,7 @@ static int ath12k_mac_op_cancel_remain_on_channel(struct ieee80211_hw *hw,
ar = ath12k_ah_to_ar(ah, 0);
- mutex_lock(&ar->conf_mutex);
+ lockdep_assert_wiphy(hw->wiphy);
spin_lock_bh(&ar->data_lock);
ar->scan.roc_notify = false;
@@ -8470,8 +8949,6 @@ static int ath12k_mac_op_cancel_remain_on_channel(struct ieee80211_hw *hw,
ath12k_scan_abort(ar);
- mutex_unlock(&ar->conf_mutex);
-
cancel_delayed_work_sync(&ar->scan.timeout);
return 0;
@@ -8483,24 +8960,31 @@ static int ath12k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
int duration,
enum ieee80211_roc_type type)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k_wmi_scan_req_arg arg;
- struct ath12k *ar, *prev_ar;
+ struct ath12k_link_vif *arvif;
+ struct ath12k *ar;
u32 scan_time_msec;
bool create = true;
+ u8 link_id;
int ret;
- if (ah->num_radio == 1) {
- WARN_ON(!arvif->is_created);
- ar = ath12k_ah_to_ar(ah, 0);
- goto scan;
- }
+ lockdep_assert_wiphy(hw->wiphy);
ar = ath12k_mac_select_scan_device(hw, vif, chan->center_freq);
- if (!ar)
- return -EINVAL;
+ if (!ar) {
+ ret = -EINVAL;
+ goto exit;
+ }
+ /* check if any of the links of ML VIF is already started on
+ * radio(ar) correpsondig to given scan frequency and use it,
+ * if not use deflink(link 0) for scan purpose.
+ */
+
+ link_id = ath12k_mac_find_link_id_by_ar(ahvif, ar);
+ arvif = ath12k_mac_assign_link_vif(ah, vif, link_id);
/* If the vif is already assigned to a specific vdev of an ar,
* check whether its already started, vdev which is started
* are not allowed to switch to a new radio.
@@ -8511,44 +8995,35 @@ static int ath12k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
* always on the same band for the vif
*/
if (arvif->is_created) {
- if (WARN_ON(!arvif->ar))
- return -EINVAL;
+ if (WARN_ON(!arvif->ar)) {
+ ret = -EINVAL;
+ goto exit;
+ }
- if (ar != arvif->ar && arvif->is_started)
- return -EBUSY;
+ if (ar != arvif->ar && arvif->is_started) {
+ ret = -EBUSY;
+ goto exit;
+ }
if (ar != arvif->ar) {
- /* backup the previously used ar ptr, since the vdev delete
- * would assign the arvif->ar to NULL after the call
- */
- prev_ar = arvif->ar;
- mutex_lock(&prev_ar->conf_mutex);
- ret = ath12k_mac_vdev_delete(prev_ar, vif);
- mutex_unlock(&prev_ar->conf_mutex);
- if (ret) {
- ath12k_warn(prev_ar->ab,
- "unable to delete scan vdev for roc: %d\n",
- ret);
- return ret;
- }
+ ath12k_mac_remove_link_interface(hw, arvif);
+ ath12k_mac_unassign_link_vif(arvif);
} else {
create = false;
}
}
if (create) {
- mutex_lock(&ar->conf_mutex);
- ret = ath12k_mac_vdev_create(ar, vif);
- mutex_unlock(&ar->conf_mutex);
+ arvif = ath12k_mac_assign_link_vif(ah, vif, link_id);
+
+ ret = ath12k_mac_vdev_create(ar, arvif);
if (ret) {
ath12k_warn(ar->ab, "unable to create scan vdev for roc: %d\n",
ret);
- return -EINVAL;
+ goto exit;
}
}
-scan:
- mutex_lock(&ar->conf_mutex);
spin_lock_bh(&ar->data_lock);
switch (ar->scan.state) {
@@ -8623,9 +9098,8 @@ scan:
free_chan_list:
kfree(arg.chan_list);
-exit:
- mutex_unlock(&ar->conf_mutex);
+exit:
return ret;
}
@@ -8633,16 +9107,20 @@ static void ath12k_mac_op_set_rekey_data(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_gtk_rekey_data *data)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
- struct ath12k_rekey_data *rekey_data = &arvif->rekey_data;
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_rekey_data *rekey_data;
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar = ath12k_ah_to_ar(ah, 0);
+ struct ath12k_link_vif *arvif;
+
+ lockdep_assert_wiphy(hw->wiphy);
+
+ arvif = &ahvif->deflink;
+ rekey_data = &arvif->rekey_data;
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac set rekey data vdev %d\n",
arvif->vdev_id);
- mutex_lock(&ar->conf_mutex);
-
memcpy(rekey_data->kck, data->kck, NL80211_KCK_LEN);
memcpy(rekey_data->kek, data->kek, NL80211_KEK_LEN);
@@ -8659,8 +9137,6 @@ static void ath12k_mac_op_set_rekey_data(struct ieee80211_hw *hw,
rekey_data->kck, NL80211_KEK_LEN);
ath12k_dbg_dump(ar->ab, ATH12K_DBG_MAC, "replay ctr", NULL,
&rekey_data->replay_ctr, sizeof(rekey_data->replay_ctr));
-
- mutex_unlock(&ar->conf_mutex);
}
static const struct ieee80211_ops ath12k_ops = {
@@ -8673,7 +9149,9 @@ static const struct ieee80211_ops ath12k_ops = {
.remove_interface = ath12k_mac_op_remove_interface,
.update_vif_offload = ath12k_mac_op_update_vif_offload,
.config = ath12k_mac_op_config,
- .bss_info_changed = ath12k_mac_op_bss_info_changed,
+ .link_info_changed = ath12k_mac_op_link_info_changed,
+ .vif_cfg_changed = ath12k_mac_op_vif_cfg_changed,
+ .change_vif_links = ath12k_mac_op_change_vif_links,
.configure_filter = ath12k_mac_op_configure_filter,
.hw_scan = ath12k_mac_op_hw_scan,
.cancel_hw_scan = ath12k_mac_op_cancel_hw_scan,
@@ -8681,7 +9159,7 @@ static const struct ieee80211_ops ath12k_ops = {
.set_rekey_data = ath12k_mac_op_set_rekey_data,
.sta_state = ath12k_mac_op_sta_state,
.sta_set_txpwr = ath12k_mac_op_sta_set_txpwr,
- .sta_rc_update = ath12k_mac_op_sta_rc_update,
+ .link_sta_rc_update = ath12k_mac_op_sta_rc_update,
.conf_tx = ath12k_mac_op_conf_tx,
.set_antenna = ath12k_mac_op_set_antenna,
.get_antenna = ath12k_mac_op_get_antenna,
@@ -9320,7 +9798,7 @@ static void ath12k_mac_setup(struct ath12k *ar)
spin_lock_init(&ar->data_lock);
INIT_LIST_HEAD(&ar->arvifs);
INIT_LIST_HEAD(&ar->ppdu_stats_info);
- mutex_init(&ar->conf_mutex);
+
init_completion(&ar->vdev_setup_done);
init_completion(&ar->vdev_delete_done);
init_completion(&ar->peer_assoc_done);
@@ -9501,7 +9979,7 @@ err:
return ret;
}
-int ath12k_mac_vif_set_keepalive(struct ath12k_vif *arvif,
+int ath12k_mac_vif_set_keepalive(struct ath12k_link_vif *arvif,
enum wmi_sta_keepalive_method method,
u32 interval)
{
@@ -9509,9 +9987,9 @@ int ath12k_mac_vif_set_keepalive(struct ath12k_vif *arvif,
struct ath12k *ar = arvif->ar;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
+ if (arvif->ahvif->vdev_type != WMI_VDEV_TYPE_STA)
return 0;
if (!test_bit(WMI_TLV_SERVICE_STA_KEEP_ALIVE, ar->ab->wmi_ab.svc_map))
diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h
index 5efbb6822628..d382337ba649 100644
--- a/drivers/net/wireless/ath/ath12k/mac.h
+++ b/drivers/net/wireless/ath/ath12k/mac.h
@@ -41,6 +41,9 @@ struct ath12k_generic_iter {
#define ATH12K_TX_POWER_MAX_VAL 70
#define ATH12K_TX_POWER_MIN_VAL 0
+#define ATH12K_DEFAULT_LINK_ID 0
+#define ATH12K_INVALID_LINK_ID 255
+
enum ath12k_supported_bw {
ATH12K_BW_20 = 0,
ATH12K_BW_40 = 1,
@@ -65,9 +68,9 @@ u8 ath12k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
void __ath12k_mac_scan_finish(struct ath12k *ar);
void ath12k_mac_scan_finish(struct ath12k *ar);
-struct ath12k_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id);
-struct ath12k_vif *ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base *ab,
- u32 vdev_id);
+struct ath12k_link_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id);
+struct ath12k_link_vif *ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base *ab,
+ u32 vdev_id);
struct ath12k *ath12k_mac_get_ar_by_vdev_id(struct ath12k_base *ab, u32 vdev_id);
struct ath12k *ath12k_mac_get_ar_by_pdev_id(struct ath12k_base *ab, u32 pdev_id);
@@ -82,7 +85,7 @@ int ath12k_mac_rfkill_config(struct ath12k *ar);
int ath12k_mac_wait_tx_complete(struct ath12k *ar);
void ath12k_mac_handle_beacon(struct ath12k *ar, struct sk_buff *skb);
void ath12k_mac_handle_beacon_miss(struct ath12k *ar, u32 vdev_id);
-int ath12k_mac_vif_set_keepalive(struct ath12k_vif *arvif,
+int ath12k_mac_vif_set_keepalive(struct ath12k_link_vif *arvif,
enum wmi_sta_keepalive_method method,
u32 interval);
u8 ath12k_mac_get_target_pdev_id(struct ath12k *ar);
diff --git a/drivers/net/wireless/ath/ath12k/mhi.c b/drivers/net/wireless/ath/ath12k/mhi.c
index df96b0f91f54..2f6d14382ed7 100644
--- a/drivers/net/wireless/ath/ath12k/mhi.c
+++ b/drivers/net/wireless/ath/ath12k/mhi.c
@@ -649,3 +649,8 @@ void ath12k_mhi_resume(struct ath12k_pci *ab_pci)
{
ath12k_mhi_set_state(ab_pci, ATH12K_MHI_RESUME);
}
+
+void ath12k_mhi_coredump(struct mhi_controller *mhi_ctrl, bool in_panic)
+{
+ mhi_download_rddm_image(mhi_ctrl, in_panic);
+}
diff --git a/drivers/net/wireless/ath/ath12k/mhi.h b/drivers/net/wireless/ath/ath12k/mhi.h
index 9362ad1958c3..7358b8477536 100644
--- a/drivers/net/wireless/ath/ath12k/mhi.h
+++ b/drivers/net/wireless/ath/ath12k/mhi.h
@@ -43,5 +43,5 @@ void ath12k_mhi_clear_vector(struct ath12k_base *ab);
void ath12k_mhi_suspend(struct ath12k_pci *ar_pci);
void ath12k_mhi_resume(struct ath12k_pci *ar_pci);
-
+void ath12k_mhi_coredump(struct mhi_controller *mhi_ctrl, bool in_panic);
#endif
diff --git a/drivers/net/wireless/ath/ath12k/p2p.c b/drivers/net/wireless/ath/ath12k/p2p.c
index 3a851ee15b2f..84cccf7d91e7 100644
--- a/drivers/net/wireless/ath/ath12k/p2p.c
+++ b/drivers/net/wireless/ath/ath12k/p2p.c
@@ -69,20 +69,20 @@ static size_t ath12k_p2p_noa_ie_len_compute(const struct ath12k_wmi_p2p_noa_info
return len;
}
-static void ath12k_p2p_noa_ie_assign(struct ath12k_vif *arvif, void *ie,
+static void ath12k_p2p_noa_ie_assign(struct ath12k_link_vif *arvif, void *ie,
size_t len)
{
struct ath12k *ar = arvif->ar;
lockdep_assert_held(&ar->data_lock);
- kfree(arvif->u.ap.noa_data);
+ kfree(arvif->ahvif->u.ap.noa_data);
- arvif->u.ap.noa_data = ie;
- arvif->u.ap.noa_len = len;
+ arvif->ahvif->u.ap.noa_data = ie;
+ arvif->ahvif->u.ap.noa_len = len;
}
-static void __ath12k_p2p_noa_update(struct ath12k_vif *arvif,
+static void __ath12k_p2p_noa_update(struct ath12k_link_vif *arvif,
const struct ath12k_wmi_p2p_noa_info *noa)
{
struct ath12k *ar = arvif->ar;
@@ -105,7 +105,7 @@ static void __ath12k_p2p_noa_update(struct ath12k_vif *arvif,
ath12k_p2p_noa_ie_assign(arvif, ie, len);
}
-void ath12k_p2p_noa_update(struct ath12k_vif *arvif,
+void ath12k_p2p_noa_update(struct ath12k_link_vif *arvif,
const struct ath12k_wmi_p2p_noa_info *noa)
{
struct ath12k *ar = arvif->ar;
@@ -118,9 +118,12 @@ void ath12k_p2p_noa_update(struct ath12k_vif *arvif,
static void ath12k_p2p_noa_update_vdev_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_p2p_noa_arg *arg = data;
+ struct ath12k_link_vif *arvif;
+ WARN_ON(!rcu_read_lock_any_held());
+ arvif = &ahvif->deflink;
if (arvif->ar != arg->ar || arvif->vdev_id != arg->vdev_id)
return;
diff --git a/drivers/net/wireless/ath/ath12k/p2p.h b/drivers/net/wireless/ath/ath12k/p2p.h
index b2eec51a9900..03ee877e6d6b 100644
--- a/drivers/net/wireless/ath/ath12k/p2p.h
+++ b/drivers/net/wireless/ath/ath12k/p2p.h
@@ -16,7 +16,7 @@ struct ath12k_p2p_noa_arg {
const struct ath12k_wmi_p2p_noa_info *noa;
};
-void ath12k_p2p_noa_update(struct ath12k_vif *arvif,
+void ath12k_p2p_noa_update(struct ath12k_link_vif *arvif,
const struct ath12k_wmi_p2p_noa_info *noa);
void ath12k_p2p_noa_update_by_vdev_id(struct ath12k *ar, u32 vdev_id,
const struct ath12k_wmi_p2p_noa_info *noa);
diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c
index bd269aa1740b..cf907550e6a4 100644
--- a/drivers/net/wireless/ath/ath12k/pci.c
+++ b/drivers/net/wireless/ath/ath12k/pci.c
@@ -7,6 +7,8 @@
#include <linux/module.h>
#include <linux/msi.h>
#include <linux/pci.h>
+#include <linux/time.h>
+#include <linux/vmalloc.h>
#include "pci.h"
#include "core.h"
@@ -425,9 +427,9 @@ static void ath12k_pci_sync_ce_irqs(struct ath12k_base *ab)
}
}
-static void ath12k_pci_ce_tasklet(struct tasklet_struct *t)
+static void ath12k_pci_ce_workqueue(struct work_struct *work)
{
- struct ath12k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq);
+ struct ath12k_ce_pipe *ce_pipe = from_work(ce_pipe, work, intr_wq);
int irq_idx = ATH12K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num;
ath12k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);
@@ -449,7 +451,7 @@ static irqreturn_t ath12k_pci_ce_interrupt_handler(int irq, void *arg)
disable_irq_nosync(ab->irq_num[irq_idx]);
- tasklet_schedule(&ce_pipe->intr_tq);
+ queue_work(system_bh_wq, &ce_pipe->intr_wq);
return IRQ_HANDLED;
}
@@ -675,7 +677,7 @@ static int ath12k_pci_config_irq(struct ath12k_base *ab)
irq_idx = ATH12K_PCI_IRQ_CE0_OFFSET + i;
- tasklet_setup(&ce_pipe->intr_tq, ath12k_pci_ce_tasklet);
+ INIT_WORK(&ce_pipe->intr_wq, ath12k_pci_ce_workqueue);
ret = request_irq(irq, ath12k_pci_ce_interrupt_handler,
ab_pci->irq_flags, irq_name[irq_idx],
@@ -962,7 +964,7 @@ static void ath12k_pci_aspm_restore(struct ath12k_pci *ab_pci)
PCI_EXP_LNKCTL_ASPMC);
}
-static void ath12k_pci_kill_tasklets(struct ath12k_base *ab)
+static void ath12k_pci_cancel_workqueue(struct ath12k_base *ab)
{
int i;
@@ -972,7 +974,7 @@ static void ath12k_pci_kill_tasklets(struct ath12k_base *ab)
if (ath12k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
continue;
- tasklet_kill(&ce_pipe->intr_tq);
+ cancel_work_sync(&ce_pipe->intr_wq);
}
}
@@ -980,7 +982,7 @@ static void ath12k_pci_ce_irq_disable_sync(struct ath12k_base *ab)
{
ath12k_pci_ce_irqs_disable(ab);
ath12k_pci_sync_ce_irqs(ab);
- ath12k_pci_kill_tasklets(ab);
+ ath12k_pci_cancel_workqueue(ab);
}
int ath12k_pci_map_service_to_pipe(struct ath12k_base *ab, u16 service_id,
@@ -1259,6 +1261,186 @@ void ath12k_pci_write32(struct ath12k_base *ab, u32 offset, u32 value)
ab_pci->pci_ops->release(ab);
}
+#ifdef CONFIG_ATH12K_COREDUMP
+static int ath12k_pci_coredump_calculate_size(struct ath12k_base *ab, u32 *dump_seg_sz)
+{
+ struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
+ struct mhi_controller *mhi_ctrl = ab_pci->mhi_ctrl;
+ struct image_info *rddm_img, *fw_img;
+ struct ath12k_tlv_dump_data *dump_tlv;
+ enum ath12k_fw_crash_dump_type mem_type;
+ u32 len = 0, rddm_tlv_sz = 0, paging_tlv_sz = 0;
+ struct ath12k_dump_file_data *file_data;
+ int i;
+
+ rddm_img = mhi_ctrl->rddm_image;
+ if (!rddm_img) {
+ ath12k_err(ab, "No RDDM dump found\n");
+ return 0;
+ }
+
+ fw_img = mhi_ctrl->fbc_image;
+
+ for (i = 0; i < fw_img->entries ; i++) {
+ if (!fw_img->mhi_buf[i].buf)
+ continue;
+
+ paging_tlv_sz += fw_img->mhi_buf[i].len;
+ }
+ dump_seg_sz[FW_CRASH_DUMP_PAGING_DATA] = paging_tlv_sz;
+
+ for (i = 0; i < rddm_img->entries; i++) {
+ if (!rddm_img->mhi_buf[i].buf)
+ continue;
+
+ rddm_tlv_sz += rddm_img->mhi_buf[i].len;
+ }
+ dump_seg_sz[FW_CRASH_DUMP_RDDM_DATA] = rddm_tlv_sz;
+
+ for (i = 0; i < ab->qmi.mem_seg_count; i++) {
+ mem_type = ath12k_coredump_get_dump_type(ab->qmi.target_mem[i].type);
+
+ if (mem_type == FW_CRASH_DUMP_NONE)
+ continue;
+
+ if (mem_type == FW_CRASH_DUMP_TYPE_MAX) {
+ ath12k_dbg(ab, ATH12K_DBG_PCI,
+ "target mem region type %d not supported",
+ ab->qmi.target_mem[i].type);
+ continue;
+ }
+
+ if (!ab->qmi.target_mem[i].paddr)
+ continue;
+
+ dump_seg_sz[mem_type] += ab->qmi.target_mem[i].size;
+ }
+
+ for (i = 0; i < FW_CRASH_DUMP_TYPE_MAX; i++) {
+ if (!dump_seg_sz[i])
+ continue;
+
+ len += sizeof(*dump_tlv) + dump_seg_sz[i];
+ }
+
+ if (len)
+ len += sizeof(*file_data);
+
+ return len;
+}
+
+static void ath12k_pci_coredump_download(struct ath12k_base *ab)
+{
+ struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
+ struct mhi_controller *mhi_ctrl = ab_pci->mhi_ctrl;
+ struct image_info *rddm_img, *fw_img;
+ struct timespec64 timestamp;
+ int i, len, mem_idx;
+ enum ath12k_fw_crash_dump_type mem_type;
+ struct ath12k_dump_file_data *file_data;
+ struct ath12k_tlv_dump_data *dump_tlv;
+ size_t hdr_len = sizeof(*file_data);
+ void *buf;
+ u32 dump_seg_sz[FW_CRASH_DUMP_TYPE_MAX] = { 0 };
+
+ ath12k_mhi_coredump(mhi_ctrl, false);
+
+ len = ath12k_pci_coredump_calculate_size(ab, dump_seg_sz);
+ if (!len) {
+ ath12k_warn(ab, "No crash dump data found for devcoredump");
+ return;
+ }
+
+ rddm_img = mhi_ctrl->rddm_image;
+ fw_img = mhi_ctrl->fbc_image;
+
+ /* dev_coredumpv() requires vmalloc data */
+ buf = vzalloc(len);
+ if (!buf)
+ return;
+
+ ab->dump_data = buf;
+ ab->ath12k_coredump_len = len;
+ file_data = ab->dump_data;
+ strscpy(file_data->df_magic, "ATH12K-FW-DUMP", sizeof(file_data->df_magic));
+ file_data->len = cpu_to_le32(len);
+ file_data->version = cpu_to_le32(ATH12K_FW_CRASH_DUMP_V2);
+ file_data->chip_id = cpu_to_le32(ab_pci->dev_id);
+ file_data->qrtr_id = cpu_to_le32(ab_pci->ab->qmi.service_ins_id);
+ file_data->bus_id = cpu_to_le32(pci_domain_nr(ab_pci->pdev->bus));
+ guid_gen(&file_data->guid);
+ ktime_get_real_ts64(&timestamp);
+ file_data->tv_sec = cpu_to_le64(timestamp.tv_sec);
+ file_data->tv_nsec = cpu_to_le64(timestamp.tv_nsec);
+ buf += hdr_len;
+ dump_tlv = buf;
+ dump_tlv->type = cpu_to_le32(FW_CRASH_DUMP_PAGING_DATA);
+ dump_tlv->tlv_len = cpu_to_le32(dump_seg_sz[FW_CRASH_DUMP_PAGING_DATA]);
+ buf += COREDUMP_TLV_HDR_SIZE;
+
+ /* append all segments together as they are all part of a single contiguous
+ * block of memory
+ */
+ for (i = 0; i < fw_img->entries ; i++) {
+ if (!fw_img->mhi_buf[i].buf)
+ continue;
+
+ memcpy_fromio(buf, (void const __iomem *)fw_img->mhi_buf[i].buf,
+ fw_img->mhi_buf[i].len);
+ buf += fw_img->mhi_buf[i].len;
+ }
+
+ dump_tlv = buf;
+ dump_tlv->type = cpu_to_le32(FW_CRASH_DUMP_RDDM_DATA);
+ dump_tlv->tlv_len = cpu_to_le32(dump_seg_sz[FW_CRASH_DUMP_RDDM_DATA]);
+ buf += COREDUMP_TLV_HDR_SIZE;
+
+ /* append all segments together as they are all part of a single contiguous
+ * block of memory
+ */
+ for (i = 0; i < rddm_img->entries; i++) {
+ if (!rddm_img->mhi_buf[i].buf)
+ continue;
+
+ memcpy_fromio(buf, (void const __iomem *)rddm_img->mhi_buf[i].buf,
+ rddm_img->mhi_buf[i].len);
+ buf += rddm_img->mhi_buf[i].len;
+ }
+
+ mem_idx = FW_CRASH_DUMP_REMOTE_MEM_DATA;
+ for (; mem_idx < FW_CRASH_DUMP_TYPE_MAX; mem_idx++) {
+ if (!dump_seg_sz[mem_idx] || mem_idx == FW_CRASH_DUMP_NONE)
+ continue;
+
+ dump_tlv = buf;
+ dump_tlv->type = cpu_to_le32(mem_idx);
+ dump_tlv->tlv_len = cpu_to_le32(dump_seg_sz[mem_idx]);
+ buf += COREDUMP_TLV_HDR_SIZE;
+
+ for (i = 0; i < ab->qmi.mem_seg_count; i++) {
+ mem_type = ath12k_coredump_get_dump_type
+ (ab->qmi.target_mem[i].type);
+
+ if (mem_type != mem_idx)
+ continue;
+
+ if (!ab->qmi.target_mem[i].paddr) {
+ ath12k_dbg(ab, ATH12K_DBG_PCI,
+ "Skipping mem region type %d",
+ ab->qmi.target_mem[i].type);
+ continue;
+ }
+
+ memcpy_fromio(buf, ab->qmi.target_mem[i].v.ioaddr,
+ ab->qmi.target_mem[i].size);
+ buf += ab->qmi.target_mem[i].size;
+ }
+ }
+
+ queue_work(ab->workqueue, &ab->dump_work);
+}
+#endif
+
int ath12k_pci_power_up(struct ath12k_base *ab)
{
struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
@@ -1329,6 +1511,9 @@ static const struct ath12k_hif_ops ath12k_pci_hif_ops = {
.ce_irq_disable = ath12k_pci_hif_ce_irq_disable,
.get_ce_msi_idx = ath12k_pci_get_ce_msi_idx,
.panic_handler = ath12k_pci_panic_handler,
+#ifdef CONFIG_ATH12K_COREDUMP
+ .coredump_download = ath12k_pci_coredump_download,
+#endif
};
static
@@ -1538,6 +1723,7 @@ static void ath12k_pci_remove(struct pci_dev *pdev)
set_bit(ATH12K_FLAG_UNREGISTERING, &ab->dev_flags);
cancel_work_sync(&ab->reset_work);
+ cancel_work_sync(&ab->dump_work);
ath12k_core_deinit(ab);
qmi_fail:
diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c
index 19c0626fbff1..7a62665b8af9 100644
--- a/drivers/net/wireless/ath/ath12k/peer.c
+++ b/drivers/net/wireless/ath/ath12k/peer.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include "core.h"
@@ -186,7 +186,7 @@ void ath12k_peer_cleanup(struct ath12k *ar, u32 vdev_id)
struct ath12k_peer *peer, *tmp;
struct ath12k_base *ab = ar->ab;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
spin_lock_bh(&ab->base_lock);
list_for_each_entry_safe(peer, tmp, &ab->peers, list) {
@@ -235,7 +235,7 @@ int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr)
{
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
reinit_completion(&ar->peer_delete_done);
@@ -261,14 +261,15 @@ static int ath12k_wait_for_peer_created(struct ath12k *ar, int vdev_id, const u8
return ath12k_wait_for_peer_common(ar->ab, vdev_id, addr, true);
}
-int ath12k_peer_create(struct ath12k *ar, struct ath12k_vif *arvif,
+int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
struct ieee80211_sta *sta,
struct ath12k_wmi_peer_create_arg *arg)
{
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
struct ath12k_peer *peer;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (ar->num_peers > (ar->max_num_peers - 1)) {
ath12k_warn(ar->ab,
@@ -326,7 +327,7 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_vif *arvif,
peer->pdev_idx = ar->pdev_idx;
peer->sta = sta;
- if (arvif->vif->type == NL80211_IFTYPE_STATION) {
+ if (vif->type == NL80211_IFTYPE_STATION) {
arvif->ast_hash = peer->ast_hash;
arvif->ast_idx = peer->hw_peer_id;
}
diff --git a/drivers/net/wireless/ath/ath12k/peer.h b/drivers/net/wireless/ath/ath12k/peer.h
index 7b3500b5c8c2..b955f0cdf598 100644
--- a/drivers/net/wireless/ath/ath12k/peer.h
+++ b/drivers/net/wireless/ath/ath12k/peer.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef ATH12K_PEER_H
@@ -59,7 +59,7 @@ struct ath12k_peer *ath12k_peer_find_by_addr(struct ath12k_base *ab,
struct ath12k_peer *ath12k_peer_find_by_id(struct ath12k_base *ab, int peer_id);
void ath12k_peer_cleanup(struct ath12k *ar, u32 vdev_id);
int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr);
-int ath12k_peer_create(struct ath12k *ar, struct ath12k_vif *arvif,
+int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
struct ieee80211_sta *sta,
struct ath12k_wmi_peer_create_arg *arg);
int ath12k_wait_for_peer_delete_done(struct ath12k *ar, u32 vdev_id,
diff --git a/drivers/net/wireless/ath/ath12k/rx_desc.h b/drivers/net/wireless/ath/ath12k/rx_desc.h
index a0db6702a189..10366bbe9999 100644
--- a/drivers/net/wireless/ath/ath12k/rx_desc.h
+++ b/drivers/net/wireless/ath/ath12k/rx_desc.h
@@ -684,18 +684,17 @@ enum rx_msdu_start_reception_type {
#define RX_MSDU_END_INFO5_SA_IDX_TIMEOUT BIT(0)
#define RX_MSDU_END_INFO5_DA_IDX_TIMEOUT BIT(1)
+#define RX_MSDU_END_INFO5_TO_DS BIT(2)
+#define RX_MSDU_END_INFO5_TID GENMASK(6, 3)
#define RX_MSDU_END_INFO5_SA_IS_VALID BIT(7)
#define RX_MSDU_END_INFO5_DA_IS_VALID BIT(8)
#define RX_MSDU_END_INFO5_DA_IS_MCBC BIT(9)
#define RX_MSDU_END_INFO5_L3_HDR_PADDING GENMASK(11, 10)
#define RX_MSDU_END_INFO5_FIRST_MSDU BIT(12)
#define RX_MSDU_END_INFO5_LAST_MSDU BIT(13)
+#define RX_MSDU_END_INFO5_FROM_DS BIT(14)
#define RX_MSDU_END_INFO5_IP_CHKSUM_FAIL_COPY BIT(15)
-#define RX_MSDU_END_QCN9274_INFO5_TO_DS BIT(2)
-#define RX_MSDU_END_QCN9274_INFO5_TID GENMASK(6, 3)
-#define RX_MSDU_END_QCN9274_INFO5_FROM_DS BIT(14)
-
#define RX_MSDU_END_INFO6_MSDU_DROP BIT(0)
#define RX_MSDU_END_INFO6_REO_DEST_IND GENMASK(5, 1)
#define RX_MSDU_END_INFO6_FLOW_IDX GENMASK(25, 6)
@@ -709,14 +708,14 @@ enum rx_msdu_start_reception_type {
#define RX_MSDU_END_INFO7_FLOW_AGGR_CONTN BIT(8)
#define RX_MSDU_END_INFO7_FISA_TIMEOUT BIT(9)
-#define RX_MSDU_END_QCN9274_INFO7_TCPUDP_CSUM_FAIL_CPY BIT(10)
-#define RX_MSDU_END_QCN9274_INFO7_MSDU_LIMIT_ERROR BIT(11)
-#define RX_MSDU_END_QCN9274_INFO7_FLOW_IDX_TIMEOUT BIT(12)
-#define RX_MSDU_END_QCN9274_INFO7_FLOW_IDX_INVALID BIT(13)
-#define RX_MSDU_END_QCN9274_INFO7_CCE_MATCH BIT(14)
-#define RX_MSDU_END_QCN9274_INFO7_AMSDU_PARSER_ERR BIT(15)
+#define RX_MSDU_END_INFO7_TCPUDP_CSUM_FAIL_CPY BIT(10)
+#define RX_MSDU_END_INFO7_MSDU_LIMIT_ERROR BIT(11)
+#define RX_MSDU_END_INFO7_FLOW_IDX_TIMEOUT BIT(12)
+#define RX_MSDU_END_INFO7_FLOW_IDX_INVALID BIT(13)
+#define RX_MSDU_END_INFO7_CCE_MATCH BIT(14)
+#define RX_MSDU_END_INFO7_AMSDU_PARSER_ERR BIT(15)
-#define RX_MSDU_END_QCN9274_INFO8_KEY_ID GENMASK(7, 0)
+#define RX_MSDU_END_INFO8_KEY_ID GENMASK(7, 0)
#define RX_MSDU_END_INFO9_SERVICE_CODE GENMASK(14, 6)
#define RX_MSDU_END_INFO9_PRIORITY_VALID BIT(15)
@@ -758,8 +757,8 @@ enum rx_msdu_start_reception_type {
#define RX_MSDU_END_INFO12_RECV_BW GENMASK(20, 18)
#define RX_MSDU_END_INFO12_RECEPTION_TYPE GENMASK(23, 21)
-#define RX_MSDU_END_QCN9274_INFO12_MIMO_SS_BITMAP GENMASK(30, 24)
-#define RX_MSDU_END_QCN9274_INFO12_MIMO_DONE_COPY BIT(31)
+#define RX_MSDU_END_INFO12_MIMO_SS_BITMAP GENMASK(30, 24)
+#define RX_MSDU_END_INFO12_MIMO_DONE_COPY BIT(31)
#define RX_MSDU_END_INFO13_FIRST_MPDU BIT(0)
#define RX_MSDU_END_INFO13_MCAST_BCAST BIT(2)
@@ -791,7 +790,7 @@ enum rx_msdu_start_reception_type {
#define RX_MSDU_END_INFO13_UNDECRYPT_FRAME_ERR BIT(30)
#define RX_MSDU_END_INFO13_FCS_ERR BIT(31)
-#define RX_MSDU_END_QCN9274_INFO13_WIFI_PARSER_ERR BIT(15)
+#define RX_MSDU_END_INFO13_WIFI_PARSER_ERR BIT(15)
#define RX_MSDU_END_INFO14_DECRYPT_STATUS_CODE GENMASK(12, 10)
#define RX_MSDU_END_INFO14_RX_BITMAP_NOT_UPDED BIT(13)
@@ -889,65 +888,6 @@ struct rx_msdu_end_qcn9274_compact {
__le32 info14;
} __packed;
-/* These macro definitions are only used for WCN7850 */
-#define RX_MSDU_END_WCN7850_INFO2_KEY_ID BIT(7, 0)
-
-#define RX_MSDU_END_WCN7850_INFO5_MSDU_LIMIT_ERR BIT(2)
-#define RX_MSDU_END_WCN7850_INFO5_IDX_TIMEOUT BIT(3)
-#define RX_MSDU_END_WCN7850_INFO5_IDX_INVALID BIT(4)
-#define RX_MSDU_END_WCN7850_INFO5_WIFI_PARSE_ERR BIT(5)
-#define RX_MSDU_END_WCN7850_INFO5_AMSDU_PARSER_ERR BIT(6)
-#define RX_MSDU_END_WCN7850_INFO5_TCPUDP_CSUM_FAIL_CPY BIT(14)
-
-#define RX_MSDU_END_WCN7850_INFO12_MIMO_SS_BITMAP GENMASK(31, 24)
-
-#define RX_MSDU_END_WCN7850_INFO13_FRAGMENT_FLAG BIT(13)
-#define RX_MSDU_END_WCN7850_INFO13_CCE_MATCH BIT(15)
-
-struct rx_msdu_end_wcn7850 {
- __le16 info0;
- __le16 phy_ppdu_id;
- __le16 ip_hdr_cksum;
- __le16 info1;
- __le16 info2;
- __le16 cumulative_l3_checksum;
- __le32 rule_indication0;
- __le32 rule_indication1;
- __le16 info3;
- __le16 l3_type;
- __le32 ipv6_options_crc;
- __le32 tcp_seq_num;
- __le32 tcp_ack_num;
- __le16 info4;
- __le16 window_size;
- __le16 tcp_udp_chksum;
- __le16 info5;
- __le16 sa_idx;
- __le16 da_idx_or_sw_peer_id;
- __le32 info6;
- __le32 fse_metadata;
- __le16 cce_metadata;
- __le16 sa_sw_peer_id;
- __le16 info7;
- __le16 rsvd0;
- __le16 cumulative_l4_checksum;
- __le16 cumulative_ip_length;
- __le32 info9;
- __le32 info10;
- __le32 info11;
- __le32 toeplitz_hash_2_or_4;
- __le32 flow_id_toeplitz;
- __le32 info12;
- __le32 ppdu_start_timestamp_31_0;
- __le32 ppdu_start_timestamp_63_32;
- __le32 phy_meta_data;
- __le16 vlan_ctag_ci;
- __le16 vlan_stag_ci;
- __le32 rsvd[3];
- __le32 info13;
- __le32 info14;
-} __packed;
-
/* rx_msdu_end
*
* rxpcu_mpdu_filter_in_category
@@ -1578,7 +1518,7 @@ struct rx_pkt_hdr_tlv {
struct hal_rx_desc_wcn7850 {
__le64 msdu_end_tag;
- struct rx_msdu_end_wcn7850 msdu_end;
+ struct rx_msdu_end_qcn9274 msdu_end;
u8 rx_padding0[RX_BE_PADDING0_BYTES];
__le64 mpdu_start_tag;
struct rx_mpdu_start_qcn9274 mpdu_start;
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index 2cd3ff9b0164..dced2aa9ba1a 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -6687,7 +6687,8 @@ ath12k_wmi_process_csa_switch_count_event(struct ath12k_base *ab,
const u32 *vdev_ids)
{
int i;
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
+ struct ath12k_vif *ahvif;
/* Finish CSA once the switch count becomes NULL */
if (ev->current_switch_count)
@@ -6702,9 +6703,10 @@ ath12k_wmi_process_csa_switch_count_event(struct ath12k_base *ab,
vdev_ids[i]);
continue;
}
+ ahvif = arvif->ahvif;
- if (arvif->is_up && arvif->vif->bss_conf.csa_active)
- ieee80211_csa_finish(arvif->vif, 0);
+ if (arvif->is_up && ahvif->vif->bss_conf.csa_active)
+ ieee80211_csa_finish(ahvif->vif, 0);
}
rcu_read_unlock();
}
@@ -7098,7 +7100,7 @@ static void ath12k_wmi_gtk_offload_status_event(struct ath12k_base *ab,
struct sk_buff *skb)
{
const struct wmi_gtk_offload_status_event *ev;
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
__be64 replay_ctr_be;
u64 replay_ctr;
const void **tb;
@@ -7136,7 +7138,7 @@ static void ath12k_wmi_gtk_offload_status_event(struct ath12k_base *ab,
/* supplicant expects big-endian replay counter */
replay_ctr_be = cpu_to_be64(replay_ctr);
- ieee80211_gtk_rekey_notify(arvif->vif, arvif->bssid,
+ ieee80211_gtk_rekey_notify(arvif->ahvif->vif, arvif->bssid,
(void *)&replay_ctr_be, GFP_ATOMIC);
rcu_read_unlock();
@@ -7284,9 +7286,11 @@ static int ath12k_connect_pdev_htc_service(struct ath12k_base *ab,
u32 pdev_idx)
{
int status;
- u32 svc_id[] = { ATH12K_HTC_SVC_ID_WMI_CONTROL,
- ATH12K_HTC_SVC_ID_WMI_CONTROL_MAC1,
- ATH12K_HTC_SVC_ID_WMI_CONTROL_MAC2 };
+ static const u32 svc_id[] = {
+ ATH12K_HTC_SVC_ID_WMI_CONTROL,
+ ATH12K_HTC_SVC_ID_WMI_CONTROL_MAC1,
+ ATH12K_HTC_SVC_ID_WMI_CONTROL_MAC2
+ };
struct ath12k_htc_svc_conn_req conn_req = {};
struct ath12k_htc_svc_conn_resp conn_resp = {};
@@ -7372,13 +7376,13 @@ ath12k_wmi_send_unit_test_cmd(struct ath12k *ar,
int ath12k_wmi_simulate_radar(struct ath12k *ar)
{
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
u32 dfs_args[DFS_MAX_TEST_ARGS];
struct wmi_unit_test_cmd wmi_ut;
bool arvif_found = false;
list_for_each_entry(arvif, &ar->arvifs, list) {
- if (arvif->is_started && arvif->vdev_type == WMI_VDEV_TYPE_AP) {
+ if (arvif->is_started && arvif->ahvif->vdev_type == WMI_VDEV_TYPE_AP) {
arvif_found = true;
break;
}
@@ -7940,7 +7944,7 @@ static void ath12k_wmi_fill_arp_offload(struct ath12k *ar,
}
int ath12k_wmi_arp_ns_offload(struct ath12k *ar,
- struct ath12k_vif *arvif,
+ struct ath12k_link_vif *arvif,
struct wmi_arp_ns_offload_arg *offload,
bool enable)
{
@@ -7989,7 +7993,7 @@ int ath12k_wmi_arp_ns_offload(struct ath12k *ar,
}
int ath12k_wmi_gtk_rekey_offload(struct ath12k *ar,
- struct ath12k_vif *arvif, bool enable)
+ struct ath12k_link_vif *arvif, bool enable)
{
struct ath12k_rekey_data *rekey_data = &arvif->rekey_data;
struct wmi_gtk_rekey_offload_cmd *cmd;
@@ -8026,7 +8030,7 @@ int ath12k_wmi_gtk_rekey_offload(struct ath12k *ar,
}
int ath12k_wmi_gtk_rekey_getinfo(struct ath12k *ar,
- struct ath12k_vif *arvif)
+ struct ath12k_link_vif *arvif)
{
struct wmi_gtk_rekey_offload_cmd *cmd;
struct sk_buff *skb;
diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h
index 6a913f9b8315..6f55dbdf629d 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -24,7 +24,7 @@
struct ath12k_base;
struct ath12k;
-struct ath12k_vif;
+struct ath12k_link_vif;
/* There is no signed version of __le32, so for a temporary solution come
* up with our own version. The idea is from fs/ntfs/endian.h.
@@ -5627,13 +5627,13 @@ int ath12k_wmi_wow_config_pno(struct ath12k *ar, u32 vdev_id,
int ath12k_wmi_hw_data_filter_cmd(struct ath12k *ar,
struct wmi_hw_data_filter_arg *arg);
int ath12k_wmi_arp_ns_offload(struct ath12k *ar,
- struct ath12k_vif *arvif,
+ struct ath12k_link_vif *arvif,
struct wmi_arp_ns_offload_arg *offload,
bool enable);
int ath12k_wmi_gtk_rekey_offload(struct ath12k *ar,
- struct ath12k_vif *arvif, bool enable);
+ struct ath12k_link_vif *arvif, bool enable);
int ath12k_wmi_gtk_rekey_getinfo(struct ath12k *ar,
- struct ath12k_vif *arvif);
+ struct ath12k_link_vif *arvif);
int ath12k_wmi_sta_keepalive(struct ath12k *ar,
const struct wmi_sta_keepalive_arg *arg);
diff --git a/drivers/net/wireless/ath/ath12k/wow.c b/drivers/net/wireless/ath/ath12k/wow.c
index 9b8684abbe40..9e1c0bfd212f 100644
--- a/drivers/net/wireless/ath/ath12k/wow.c
+++ b/drivers/net/wireless/ath/ath12k/wow.c
@@ -29,11 +29,11 @@ static const struct wiphy_wowlan_support ath12k_wowlan_support = {
.max_pkt_offset = WOW_MAX_PKT_OFFSET,
};
-static inline bool ath12k_wow_is_p2p_vdev(struct ath12k_vif *arvif)
+static inline bool ath12k_wow_is_p2p_vdev(struct ath12k_vif *ahvif)
{
- return (arvif->vdev_subtype == WMI_VDEV_SUBTYPE_P2P_DEVICE ||
- arvif->vdev_subtype == WMI_VDEV_SUBTYPE_P2P_CLIENT ||
- arvif->vdev_subtype == WMI_VDEV_SUBTYPE_P2P_GO);
+ return (ahvif->vdev_subtype == WMI_VDEV_SUBTYPE_P2P_DEVICE ||
+ ahvif->vdev_subtype == WMI_VDEV_SUBTYPE_P2P_CLIENT ||
+ ahvif->vdev_subtype == WMI_VDEV_SUBTYPE_P2P_GO);
}
int ath12k_wow_enable(struct ath12k *ar)
@@ -101,7 +101,7 @@ int ath12k_wow_wakeup(struct ath12k *ar)
return 0;
}
-static int ath12k_wow_vif_cleanup(struct ath12k_vif *arvif)
+static int ath12k_wow_vif_cleanup(struct ath12k_link_vif *arvif)
{
struct ath12k *ar = arvif->ar;
int i, ret;
@@ -129,10 +129,10 @@ static int ath12k_wow_vif_cleanup(struct ath12k_vif *arvif)
static int ath12k_wow_cleanup(struct ath12k *ar)
{
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
ret = ath12k_wow_vif_cleanup(arvif);
@@ -191,7 +191,7 @@ ath12k_wow_convert_8023_to_80211(struct ath12k *ar,
memcpy(bytemask, eth_bytemask, eth_pat_len);
pat_len = eth_pat_len;
- } else if (eth_pkt_ofs + eth_pat_len < prot_ofs) {
+ } else if (size_add(eth_pkt_ofs, eth_pat_len) < prot_ofs) {
memcpy(pat, eth_pat, ETH_ALEN - eth_pkt_ofs);
memcpy(bytemask, eth_bytemask, ETH_ALEN - eth_pkt_ofs);
@@ -354,7 +354,7 @@ ath12k_wow_pno_check_and_convert(struct ath12k *ar, u32 vdev_id,
return 0;
}
-static int ath12k_wow_vif_set_wakeups(struct ath12k_vif *arvif,
+static int ath12k_wow_vif_set_wakeups(struct ath12k_link_vif *arvif,
struct cfg80211_wowlan *wowlan)
{
const struct cfg80211_pkt_pattern *patterns = wowlan->patterns;
@@ -364,7 +364,7 @@ static int ath12k_wow_vif_set_wakeups(struct ath12k_vif *arvif,
int ret, i, j;
/* Setup requested WOW features */
- switch (arvif->vdev_type) {
+ switch (arvif->ahvif->vdev_type) {
case WMI_VDEV_TYPE_IBSS:
__set_bit(WOW_BEACON_EVENT, &wow_mask);
fallthrough;
@@ -473,13 +473,13 @@ static int ath12k_wow_vif_set_wakeups(struct ath12k_vif *arvif,
static int ath12k_wow_set_wakeups(struct ath12k *ar,
struct cfg80211_wowlan *wowlan)
{
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
- if (ath12k_wow_is_p2p_vdev(arvif))
+ if (ath12k_wow_is_p2p_vdev(arvif->ahvif))
continue;
ret = ath12k_wow_vif_set_wakeups(arvif, wowlan);
if (ret) {
@@ -518,11 +518,11 @@ out:
return ret;
}
-static int ath12k_wow_vif_clean_nlo(struct ath12k_vif *arvif)
+static int ath12k_wow_vif_clean_nlo(struct ath12k_link_vif *arvif)
{
struct ath12k *ar = arvif->ar;
- switch (arvif->vdev_type) {
+ switch (arvif->ahvif->vdev_type) {
case WMI_VDEV_TYPE_STA:
return ath12k_wow_vdev_clean_nlo(ar, arvif->vdev_id);
default:
@@ -532,13 +532,13 @@ static int ath12k_wow_vif_clean_nlo(struct ath12k_vif *arvif)
static int ath12k_wow_nlo_cleanup(struct ath12k *ar)
{
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
- if (ath12k_wow_is_p2p_vdev(arvif))
+ if (ath12k_wow_is_p2p_vdev(arvif->ahvif))
continue;
ret = ath12k_wow_vif_clean_nlo(arvif);
@@ -555,13 +555,13 @@ static int ath12k_wow_nlo_cleanup(struct ath12k *ar)
static int ath12k_wow_set_hw_filter(struct ath12k *ar)
{
struct wmi_hw_data_filter_arg arg;
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
- if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
+ if (arvif->ahvif->vdev_type != WMI_VDEV_TYPE_STA)
continue;
arg.vdev_id = arvif->vdev_id;
@@ -581,13 +581,13 @@ static int ath12k_wow_set_hw_filter(struct ath12k *ar)
static int ath12k_wow_clear_hw_filter(struct ath12k *ar)
{
struct wmi_hw_data_filter_arg arg;
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
- if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
+ if (arvif->ahvif->vdev_type != WMI_VDEV_TYPE_STA)
continue;
arg.vdev_id = arvif->vdev_id;
@@ -626,10 +626,10 @@ static void ath12k_wow_generate_ns_mc_addr(struct ath12k_base *ab,
}
}
-static void ath12k_wow_prepare_ns_offload(struct ath12k_vif *arvif,
+static void ath12k_wow_prepare_ns_offload(struct ath12k_link_vif *arvif,
struct wmi_arp_ns_offload_arg *offload)
{
- struct net_device *ndev = ieee80211_vif_to_wdev(arvif->vif)->netdev;
+ struct net_device *ndev = ieee80211_vif_to_wdev(arvif->ahvif->vif)->netdev;
struct ath12k_base *ab = arvif->ar->ab;
struct inet6_ifaddr *ifa6;
struct ifacaddr6 *ifaca6;
@@ -710,10 +710,10 @@ unlock:
ath12k_wow_generate_ns_mc_addr(ab, offload);
}
-static void ath12k_wow_prepare_arp_offload(struct ath12k_vif *arvif,
+static void ath12k_wow_prepare_arp_offload(struct ath12k_link_vif *arvif,
struct wmi_arp_ns_offload_arg *offload)
{
- struct ieee80211_vif *vif = arvif->vif;
+ struct ieee80211_vif *vif = arvif->ahvif->vif;
struct ieee80211_vif_cfg vif_cfg = vif->cfg;
struct ath12k_base *ab = arvif->ar->ab;
u32 ipv4_cnt;
@@ -732,22 +732,25 @@ static void ath12k_wow_prepare_arp_offload(struct ath12k_vif *arvif,
static int ath12k_wow_arp_ns_offload(struct ath12k *ar, bool enable)
{
struct wmi_arp_ns_offload_arg *offload;
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
+ struct ath12k_vif *ahvif;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
offload = kmalloc(sizeof(*offload), GFP_KERNEL);
if (!offload)
return -ENOMEM;
list_for_each_entry(arvif, &ar->arvifs, list) {
- if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
+ ahvif = arvif->ahvif;
+
+ if (ahvif->vdev_type != WMI_VDEV_TYPE_STA)
continue;
memset(offload, 0, sizeof(*offload));
- memcpy(offload->mac_addr, arvif->vif->addr, ETH_ALEN);
+ memcpy(offload->mac_addr, ahvif->vif->addr, ETH_ALEN);
ath12k_wow_prepare_ns_offload(arvif, offload);
ath12k_wow_prepare_arp_offload(arvif, offload);
@@ -766,13 +769,13 @@ static int ath12k_wow_arp_ns_offload(struct ath12k *ar, bool enable)
static int ath12k_gtk_rekey_offload(struct ath12k *ar, bool enable)
{
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
- if (arvif->vdev_type != WMI_VDEV_TYPE_STA ||
+ if (arvif->ahvif->vdev_type != WMI_VDEV_TYPE_STA ||
!arvif->is_up ||
!arvif->rekey_data.enable_offload)
continue;
@@ -824,10 +827,10 @@ static int ath12k_wow_set_keepalive(struct ath12k *ar,
enum wmi_sta_keepalive_method method,
u32 interval)
{
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
ret = ath12k_mac_vif_set_keepalive(arvif, method, interval);
@@ -845,7 +848,7 @@ int ath12k_wow_op_suspend(struct ieee80211_hw *hw,
struct ath12k *ar = ath12k_ah_to_ar(ah, 0);
int ret;
- mutex_lock(&ar->conf_mutex);
+ lockdep_assert_wiphy(hw->wiphy);
ret = ath12k_wow_cleanup(ar);
if (ret) {
@@ -913,7 +916,6 @@ cleanup:
ath12k_wow_cleanup(ar);
exit:
- mutex_unlock(&ar->conf_mutex);
return ret ? 1 : 0;
}
@@ -922,9 +924,9 @@ void ath12k_wow_op_set_wakeup(struct ieee80211_hw *hw, bool enabled)
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar = ath12k_ah_to_ar(ah, 0);
- mutex_lock(&ar->conf_mutex);
+ lockdep_assert_wiphy(hw->wiphy);
+
device_set_wakeup_enable(ar->ab->dev, enabled);
- mutex_unlock(&ar->conf_mutex);
}
int ath12k_wow_op_resume(struct ieee80211_hw *hw)
@@ -933,7 +935,7 @@ int ath12k_wow_op_resume(struct ieee80211_hw *hw)
struct ath12k *ar = ath12k_ah_to_ar(ah, 0);
int ret;
- mutex_lock(&ar->conf_mutex);
+ lockdep_assert_wiphy(hw->wiphy);
ret = ath12k_hif_resume(ar->ab);
if (ret) {
@@ -995,7 +997,6 @@ exit:
}
}
- mutex_unlock(&ar->conf_mutex);
return ret;
}
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c
index f27308ccb2f1..cb3e891ee1bd 100644
--- a/drivers/net/wireless/ath/ath5k/ahb.c
+++ b/drivers/net/wireless/ath/ath5k/ahb.c
@@ -218,10 +218,10 @@ static void ath_ahb_remove(struct platform_device *pdev)
}
static struct platform_driver ath_ahb_driver = {
- .probe = ath_ahb_probe,
- .remove_new = ath_ahb_remove,
- .driver = {
- .name = "ar231x-wmac",
+ .probe = ath_ahb_probe,
+ .remove = ath_ahb_remove,
+ .driver = {
+ .name = "ar231x-wmac",
},
};
diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c
index b51fce5ae260..f5ca2fe0d074 100644
--- a/drivers/net/wireless/ath/ath5k/pci.c
+++ b/drivers/net/wireless/ath/ath5k/pci.c
@@ -46,6 +46,8 @@ static const struct pci_device_id ath5k_pci_id_table[] = {
{ PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */
{ PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */
{ PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */
+ { PCI_VDEVICE(ATHEROS, 0xff16) }, /* Gigaset SX76[23] AR241[34]A */
+ { PCI_VDEVICE(ATHEROS, 0xff1a) }, /* Arcadyan ARV45XX AR2417 */
{ PCI_VDEVICE(ATHEROS, 0xff1b) }, /* AR5BXB63 */
{ 0 }
};
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index b4fcfb72991c..68384159870b 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -1249,7 +1249,7 @@ struct wmi_rssi_threshold_params_cmd {
/* highest of upper */
a_sle16 thresh_above6_val;
- /* lowest of bellow */
+ /* lowest of below */
a_sle16 thresh_below1_val;
a_sle16 thresh_below2_val;
@@ -1257,7 +1257,7 @@ struct wmi_rssi_threshold_params_cmd {
a_sle16 thresh_below4_val;
a_sle16 thresh_below5_val;
- /* highest of bellow */
+ /* highest of below */
a_sle16 thresh_below6_val;
/* "alpha" */
@@ -1287,13 +1287,13 @@ struct wmi_snr_threshold_params_cmd {
/* highest of upper */
u8 thresh_above4_val;
- /* lowest of bellow */
+ /* lowest of below */
u8 thresh_below1_val;
u8 thresh_below2_val;
u8 thresh_below3_val;
- /* highest of bellow */
+ /* highest of below */
u8 thresh_below4_val;
u8 reserved[3];
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index 1a6697b6e3b4..d4805e02b927 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -158,12 +158,12 @@ static void ath_ahb_remove(struct platform_device *pdev)
}
static struct platform_driver ath_ahb_driver = {
- .probe = ath_ahb_probe,
- .remove_new = ath_ahb_remove,
- .driver = {
- .name = "ath9k",
+ .probe = ath_ahb_probe,
+ .remove = ath_ahb_remove,
+ .driver = {
+ .name = "ath9k",
},
- .id_table = ath9k_platform_id_table,
+ .id_table = ath9k_platform_id_table,
};
MODULE_DEVICE_TABLE(platform, ath9k_platform_id_table);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_aic.c b/drivers/net/wireless/ath/ath9k/ar9003_aic.c
index d0f1e8bcc846..45a7ca660f47 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_aic.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_aic.c
@@ -409,13 +409,11 @@ static bool ar9003_aic_cal_post_process(struct ath_hw *ah)
sram.valid = true;
sram.rot_dir_att_db =
- min(max(rot_dir_path_att_db,
- (int16_t)ATH_AIC_MIN_ROT_DIR_ATT_DB),
- ATH_AIC_MAX_ROT_DIR_ATT_DB);
+ clamp(rot_dir_path_att_db, (int16_t)ATH_AIC_MIN_ROT_DIR_ATT_DB,
+ ATH_AIC_MAX_ROT_DIR_ATT_DB);
sram.rot_quad_att_db =
- min(max(rot_quad_path_att_db,
- (int16_t)ATH_AIC_MIN_ROT_QUAD_ATT_DB),
- ATH_AIC_MAX_ROT_QUAD_ATT_DB);
+ clamp(rot_quad_path_att_db, (int16_t)ATH_AIC_MIN_ROT_QUAD_ATT_DB,
+ ATH_AIC_MAX_ROT_QUAD_ATT_DB);
aic->aic_sram[i] = (SM(sram.vga_dir_sign,
AR_PHY_AIC_SRAM_VGA_DIR_SIGN) |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c b/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c
index 004ca5f536be..fe1013a3a588 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c
+++ b/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c
@@ -18,7 +18,6 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
-#include <linux/ath9k_platform.h>
#include <linux/nvmem-consumer.h>
#include <linux/workqueue.h>
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c
index 9b393a8f7c3a..ad3a3fda1b9c 100644
--- a/drivers/net/wireless/ath/ath9k/btcoex.c
+++ b/drivers/net/wireless/ath/ath9k/btcoex.c
@@ -16,7 +16,6 @@
#include <linux/export.h>
#include <linux/types.h>
-#include <linux/ath9k_platform.h>
#include "hw.h"
enum ath_bt_mode {
@@ -115,23 +114,14 @@ static void ath9k_hw_btcoex_pin_init(struct ath_hw *ah, u8 wlanactive_gpio,
u8 btactive_gpio, u8 btpriority_gpio)
{
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
- struct ath9k_platform_data *pdata = ah->dev->platform_data;
if (btcoex_hw->scheme != ATH_BTCOEX_CFG_2WIRE &&
btcoex_hw->scheme != ATH_BTCOEX_CFG_3WIRE)
return;
- /* bt priority GPIO will be ignored by 2 wire scheme */
- if (pdata && (pdata->bt_active_pin || pdata->bt_priority_pin ||
- pdata->wlan_active_pin)) {
- btcoex_hw->btactive_gpio = pdata->bt_active_pin;
- btcoex_hw->wlanactive_gpio = pdata->wlan_active_pin;
- btcoex_hw->btpriority_gpio = pdata->bt_priority_pin;
- } else {
- btcoex_hw->btactive_gpio = btactive_gpio;
- btcoex_hw->wlanactive_gpio = wlanactive_gpio;
- btcoex_hw->btpriority_gpio = btpriority_gpio;
- }
+ btcoex_hw->btactive_gpio = btactive_gpio;
+ btcoex_hw->wlanactive_gpio = wlanactive_gpio;
+ btcoex_hw->btpriority_gpio = btpriority_gpio;
}
void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah)
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c
index efb7889142d4..df58dc02e104 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom.c
@@ -15,7 +15,6 @@
*/
#include "hw.h"
-#include <linux/ath9k_platform.h>
void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val)
{
@@ -119,14 +118,6 @@ static bool ath9k_hw_nvram_read_array(u16 *blob, size_t blob_size,
return true;
}
-static bool ath9k_hw_nvram_read_pdata(struct ath9k_platform_data *pdata,
- off_t offset, u16 *data)
-{
- return ath9k_hw_nvram_read_array(pdata->eeprom_data,
- ARRAY_SIZE(pdata->eeprom_data),
- offset, data);
-}
-
static bool ath9k_hw_nvram_read_firmware(const struct firmware *eeprom_blob,
off_t offset, u16 *data)
{
@@ -146,15 +137,12 @@ static bool ath9k_hw_nvram_read_nvmem(struct ath_hw *ah, off_t offset,
bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
{
struct ath_common *common = ath9k_hw_common(ah);
- struct ath9k_platform_data *pdata = ah->dev->platform_data;
bool ret;
if (ah->nvmem_blob)
ret = ath9k_hw_nvram_read_nvmem(ah, off, data);
else if (ah->eeprom_blob)
ret = ath9k_hw_nvram_read_firmware(ah->eeprom_blob, off, data);
- else if (pdata && !pdata->use_eeprom)
- ret = ath9k_hw_nvram_read_pdata(pdata, off, data);
else
ret = common->bus_ops->eeprom_read(common, off, data);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 8a03bcc2789e..57094bd45d98 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1357,8 +1357,10 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw,
static void ath9k_htc_sta_rc_update(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, u32 changed)
+ struct ieee80211_link_sta *link_sta,
+ u32 changed)
{
+ struct ieee80211_sta *sta = link_sta->sta;
struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv;
if (!(changed & IEEE80211_RC_SUPP_RATES_CHANGED))
@@ -1883,7 +1885,7 @@ struct ieee80211_ops ath9k_htc_ops = {
.sta_add = ath9k_htc_sta_add,
.sta_remove = ath9k_htc_sta_remove,
.conf_tx = ath9k_htc_conf_tx,
- .sta_rc_update = ath9k_htc_sta_rc_update,
+ .link_sta_rc_update = ath9k_htc_sta_rc_update,
.bss_info_changed = ath9k_htc_bss_info_changed,
.set_key = ath9k_htc_set_key,
.get_tsf = ath9k_htc_get_tsf,
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c
index eb631fd3336d..b5257b2b4aa5 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.c
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.c
@@ -294,6 +294,9 @@ int htc_connect_service(struct htc_target *target,
return -ETIMEDOUT;
}
+ if (target->conn_rsp_epid < 0 || target->conn_rsp_epid >= ENDPOINT_MAX)
+ return -EINVAL;
+
*conn_rsp_epid = target->conn_rsp_epid;
return 0;
err:
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index c3a6368bfc68..e2bef099adb3 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -490,7 +490,7 @@ static void ath9k_hw_init_macaddr(struct ath_hw *ah)
u16 eeval;
static const u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW };
- /* MAC address may already be loaded via ath9k_platform_data */
+ /* MAC address may already be loaded via NVMEM */
if (is_valid_ether_addr(common->macaddr))
return;
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 7fad7e75af6a..f9e77c4624d9 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -18,7 +18,6 @@
#include <linux/dma-mapping.h>
#include <linux/slab.h>
-#include <linux/ath9k_platform.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_net.h>
@@ -583,8 +582,8 @@ static int ath9k_nvmem_request_eeprom(struct ath_softc *sc)
/* nvmem cell might not be defined, or the nvmem
* subsystem isn't included. In this case, follow
- * the established "just return 0;" convention of
- * ath9k_init_platform to say:
+ * the established "just return 0;" convention
+ * to say:
* "All good. Nothing to see here. Please go on."
*/
if (err == -ENOENT || err == -EOPNOTSUPP)
@@ -620,49 +619,6 @@ static int ath9k_nvmem_request_eeprom(struct ath_softc *sc)
return 0;
}
-static int ath9k_init_platform(struct ath_softc *sc)
-{
- struct ath9k_platform_data *pdata = sc->dev->platform_data;
- struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
- int ret;
-
- if (!pdata)
- return 0;
-
- if (!pdata->use_eeprom) {
- ah->ah_flags &= ~AH_USE_EEPROM;
- ah->gpio_mask = pdata->gpio_mask;
- ah->gpio_val = pdata->gpio_val;
- ah->led_pin = pdata->led_pin;
- ah->is_clk_25mhz = pdata->is_clk_25mhz;
- ah->get_mac_revision = pdata->get_mac_revision;
- ah->external_reset = pdata->external_reset;
- ah->disable_2ghz = pdata->disable_2ghz;
- ah->disable_5ghz = pdata->disable_5ghz;
-
- if (!pdata->endian_check)
- ah->ah_flags |= AH_NO_EEP_SWAP;
- }
-
- if (pdata->eeprom_name) {
- ret = ath9k_eeprom_request(sc, pdata->eeprom_name);
- if (ret)
- return ret;
- }
-
- if (pdata->led_active_high)
- ah->config.led_active_high = true;
-
- if (pdata->tx_gain_buffalo)
- ah->config.tx_gain_buffalo = true;
-
- if (pdata->macaddr)
- ether_addr_copy(common->macaddr, pdata->macaddr);
-
- return 0;
-}
-
static int ath9k_of_init(struct ath_softc *sc)
{
struct device_node *np = sc->dev->of_node;
@@ -748,10 +704,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
*/
ath9k_init_pcoem_platform(sc);
- ret = ath9k_init_platform(sc);
- if (ret)
- return ret;
-
ret = ath9k_of_init(sc);
if (ret)
return ret;
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index 408776562a7e..8557d4826a46 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -1679,10 +1679,10 @@ static const struct of_device_id wcn36xx_of_match[] = {
MODULE_DEVICE_TABLE(of, wcn36xx_of_match);
static struct platform_driver wcn36xx_driver = {
- .probe = wcn36xx_probe,
- .remove_new = wcn36xx_remove,
- .driver = {
- .name = "wcn36xx",
+ .probe = wcn36xx_probe,
+ .remove = wcn36xx_remove,
+ .driver = {
+ .name = "wcn36xx",
.of_match_table = wcn36xx_of_match,
},
};
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
index bccc27de848d..7ee79593cd23 100644
--- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
@@ -167,7 +167,7 @@ struct wcn36xx_vif {
* @dpu_desc_index: DPU descriptor index is returned from HW after config_sta
* call and is used in TX BD.
* @bss_sta_index: STA index is returned from HW after config_bss call and is
- * used in both SMD channel and TX BD. See table bellow when it is used.
+ * used in both SMD channel and TX BD. See table below when it is used.
* @bss_dpu_desc_index: DPU descriptor index is returned from HW after
* config_bss call and is used in TX BD.
* ______________________________________________
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index e8f1d30a8d73..a1a0a9223e74 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -1493,6 +1493,7 @@ out:
}
static int wil_cfg80211_set_channel(struct wiphy *wiphy,
+ struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
struct wil6210_priv *wil = wiphy_to_wil(wiphy);