summaryrefslogtreecommitdiff
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-02-11 19:31:52 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2026-02-11 19:31:52 -0800
commit37a93dd5c49b5fda807fd204edf2547c3493319c (patch)
treece1ef5a642b9ea3d7242156438eb96dc5607a752 /drivers/net/wireless
parent098b6e44cbaa2d526d06af90c862d13fb414a0ec (diff)
parent83310d613382f74070fc8b402f3f6c2af8439ead (diff)
Merge tag 'net-next-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-nextipvs/mainipvs/HEADipvs-next/mainipvs-next/HEADdavem/net-next/maindavem/net-next/HEAD
Pull networking updates from Paolo Abeni: "Core & protocols: - A significant effort all around the stack to guide the compiler to make the right choice when inlining code, to avoid unneeded calls for small helper and stack canary overhead in the fast-path. This generates better and faster code with very small or no text size increases, as in many cases the call generated more code than the actual inlined helper. - Extend AccECN implementation so that is now functionally complete, also allow the user-space enabling it on a per network namespace basis. - Add support for memory providers with large (above 4K) rx buffer. Paired with hw-gro, larger rx buffer sizes reduce the number of buffers traversing the stack, dincreasing single stream CPU usage by up to ~30%. - Do not add HBH header to Big TCP GSO packets. This simplifies the RX path, the TX path and the NIC drivers, and is possible because user-space taps can now interpret correctly such packets without the HBH hint. - Allow IPv6 routes to be configured with a gateway address that is resolved out of a different interface than the one specified, aligning IPv6 to IPv4 behavior. - Multi-queue aware sch_cake. This makes it possible to scale the rate shaper of sch_cake across multiple CPUs, while still enforcing a single global rate on the interface. - Add support for the nbcon (new buffer console) infrastructure to netconsole, enabling lock-free, priority-based console operations that are safer in crash scenarios. - Improve the TCP ipv6 output path to cache the flow information, saving cpu cycles, reducing cache line misses and stack use. - Improve netfilter packet tracker to resolve clashes for most protocols, avoiding unneeded drops on rare occasions. - Add IP6IP6 tunneling acceleration to the flowtable infrastructure. - Reduce tcp socket size by one cache line. - Notify neighbour changes atomically, avoiding inconsistencies between the notification sequence and the actual states sequence. - Add vsock namespace support, allowing complete isolation of vsocks across different network namespaces. - Improve xsk generic performances with cache-alignment-oriented optimizations. - Support netconsole automatic target recovery, allowing netconsole to reestablish targets when underlying low-level interface comes back online. Driver API: - Support for switching the working mode (automatic vs manual) of a DPLL device via netlink. - Introduce PHY ports representation to expose multiple front-facing media ports over a single MAC. - Introduce "rx-polarity" and "tx-polarity" device tree properties, to generalize polarity inversion requirements for differential signaling. - Add helper to create, prepare and enable managed clocks. Device drivers: - Add Huawei hinic3 PF etherner driver. - Add DWMAC glue driver for Motorcomm YT6801 PCIe ethernet controller. - Add ethernet driver for MaxLinear MxL862xx switches - Remove parallel-port Ethernet driver. - Convert existing driver timestamp configuration reporting to hwtstamp_get and remove legacy ioctl(). - Convert existing drivers to .get_rx_ring_count(), simplifing the RX ring count retrieval. Also remove the legacy fallback path. - Ethernet high-speed NICs: - Broadcom (bnxt, bng): - bnxt: add FW interface update to support FEC stats histogram and NVRAM defragmentation - bng: add TSO and H/W GRO support - nVidia/Mellanox (mlx5): - improve latency of channel restart operations, reducing the used H/W resources - add TSO support for UDP over GRE over VLAN - add flow counters support for hardware steering (HWS) rules - use a static memory area to store headers for H/W GRO, leading to 12% RX tput improvement - Intel (100G, ice, idpf): - ice: reorganizes layout of Tx and Rx rings for cacheline locality and utilizes __cacheline_group* macros on the new layouts - ice: introduces Synchronous Ethernet (SyncE) support - Meta (fbnic): - adds debugfs for firmware mailbox and tx/rx rings vectors - Ethernet virtual: - geneve: introduce GRO/GSO support for double UDP encapsulation - Ethernet NICs consumer, and embedded: - Synopsys (stmmac): - some code refactoring and cleanups - RealTek (r8169): - add support for RTL8127ATF (10G Fiber SFP) - add dash and LTR support - Airoha: - AN8811HB 2.5 Gbps phy support - Freescale (fec): - add XDP zero-copy support - Thunderbolt: - add get link setting support to allow bonding - Renesas: - add support for RZ/G3L GBETH SoC - Ethernet switches: - Maxlinear: - support R(G)MII slow rate configuration - add support for Intel GSW150 - Motorcomm (yt921x): - add DCB/QoS support - TI: - icssm-prueth: support bridging (STP/RSTP) via the switchdev framework - Ethernet PHYs: - Realtek: - enable SGMII and 2500Base-X in-band auto-negotiation - simplify and reunify C22/C45 drivers - Micrel: convert bindings to DT schema - CAN: - move skb headroom content into skb extensions, making CAN metadata access more robust - CAN drivers: - rcar_canfd: - add support for FD-only mode - add support for the RZ/T2H SoC - sja1000: cleanup the CAN state handling - WiFi: - implement EPPKE/802.1X over auth frames support - split up drop reasons better, removing generic RX_DROP - additional FTM capabilities: 6 GHz support, supported number of spatial streams and supported number of LTF repetitions - better mac80211 iterators to enumerate resources - initial UHR (Wi-Fi 8) support for cfg80211/mac80211 - WiFi drivers: - Qualcomm/Atheros: - ath11k: support for Channel Frequency Response measurement - ath12k: a significant driver refactor to support multi-wiphy devices and and pave the way for future device support in the same driver (rather than splitting to ath13k) - ath12k: support for the QCC2072 chipset - Intel: - iwlwifi: partial Neighbor Awareness Networking (NAN) support - iwlwifi: initial support for U-NII-9 and IEEE 802.11bn - RealTek (rtw89): - preparations for RTL8922DE support - Bluetooth: - implement setsockopt(BT_PHY) to set the connection packet type/PHY - set link_policy on incoming ACL connections - Bluetooth drivers: - btusb: add support for MediaTek7920, Realtek RTL8761BU and 8851BE - btqca: add WCN6855 firmware priority selection feature" * tag 'net-next-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1254 commits) bnge/bng_re: Add a new HSI net: macb: Fix tx/rx malfunction after phy link down and up af_unix: Fix memleak of newsk in unix_stream_connect(). net: ti: icssg-prueth: Add optional dependency on HSR net: dsa: add basic initial driver for MxL862xx switches net: mdio: add unlocked mdiodev C45 bus accessors net: dsa: add tag format for MxL862xx switches dt-bindings: net: dsa: add MaxLinear MxL862xx selftests: drivers: net: hw: Modify toeplitz.c to poll for packets octeontx2-pf: Unregister devlink on probe failure net: renesas: rswitch: fix forwarding offload statemachine ionic: Rate limit unknown xcvr type messages tcp: inet6_csk_xmit() optimization tcp: populate inet->cork.fl.u.ip6 in tcp_v6_syn_recv_sock() tcp: populate inet->cork.fl.u.ip6 in tcp_v6_connect() ipv6: inet6_csk_xmit() and inet6_csk_update_pmtu() use inet->cork.fl.u.ip6 ipv6: use inet->cork.fl.u.ip6 and np->final in ip6_datagram_dst_update() ipv6: use np->final in inet6_sk_rebuild_header() ipv6: add daddr/final storage in struct ipv6_pinfo net: stmmac: qcom-ethqos: fix qcom_ethqos_serdes_powerup() ...
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/ath/ath10k/sdio.c6
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.c53
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.h3
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c4
-rw-r--r--drivers/net/wireless/ath/ath11k/Kconfig11
-rw-r--r--drivers/net/wireless/ath/ath11k/Makefile1
-rw-r--r--drivers/net/wireless/ath/ath11k/cfr.c1023
-rw-r--r--drivers/net/wireless/ath/ath11k/cfr.h308
-rw-r--r--drivers/net/wireless/ath/ath11k/core.c108
-rw-r--r--drivers/net/wireless/ath/ath11k/core.h23
-rw-r--r--drivers/net/wireless/ath/ath11k/dbring.c50
-rw-r--r--drivers/net/wireless/ath/ath11k/dbring.h8
-rw-r--r--drivers/net/wireless/ath/ath11k/debug.h8
-rw-r--r--drivers/net/wireless/ath/ath11k/debugfs.c2
-rw-r--r--drivers/net/wireless/ath/ath11k/debugfs_sta.c142
-rw-r--r--drivers/net/wireless/ath/ath11k/dp.c12
-rw-r--r--drivers/net/wireless/ath/ath11k/dp.h1
-rw-r--r--drivers/net/wireless/ath/ath11k/dp_tx.c9
-rw-r--r--drivers/net/wireless/ath/ath11k/hal.c3
-rw-r--r--drivers/net/wireless/ath/ath11k/hw.c19
-rw-r--r--drivers/net/wireless/ath/ath11k/hw.h8
-rw-r--r--drivers/net/wireless/ath/ath11k/mac.c23
-rw-r--r--drivers/net/wireless/ath/ath11k/reg.c9
-rw-r--r--drivers/net/wireless/ath/ath11k/wmi.c147
-rw-r--r--drivers/net/wireless/ath/ath11k/wmi.h97
-rw-r--r--drivers/net/wireless/ath/ath12k/Makefile8
-rw-r--r--drivers/net/wireless/ath/ath12k/ahb.c165
-rw-r--r--drivers/net/wireless/ath/ath12k/ahb.h31
-rw-r--r--drivers/net/wireless/ath/ath12k/ce.c326
-rw-r--r--drivers/net/wireless/ath/ath12k/ce.h7
-rw-r--r--drivers/net/wireless/ath/ath12k/cmn_defs.h20
-rw-r--r--drivers/net/wireless/ath/ath12k/core.c75
-rw-r--r--drivers/net/wireless/ath/ath12k/core.h179
-rw-r--r--drivers/net/wireless/ath/ath12k/dbring.c6
-rw-r--r--drivers/net/wireless/ath/ath12k/debug.c8
-rw-r--r--drivers/net/wireless/ath/ath12k/debugfs.c8
-rw-r--r--drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c197
-rw-r--r--drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h85
-rw-r--r--drivers/net/wireless/ath/ath12k/debugfs_sta.c62
-rw-r--r--drivers/net/wireless/ath/ath12k/dp.c561
-rw-r--r--drivers/net/wireless/ath/ath12k/dp.h1742
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_cmn.h106
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_htt.c1353
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_htt.h1546
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_mon.c3517
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_mon.h58
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_peer.c690
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_peer.h182
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_rx.c3478
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_rx.h191
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_tx.c1634
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_tx.h39
-rw-r--r--drivers/net/wireless/ath/ath12k/fw.c10
-rw-r--r--drivers/net/wireless/ath/ath12k/fw.h3
-rw-r--r--drivers/net/wireless/ath/ath12k/hal.c2134
-rw-r--r--drivers/net/wireless/ath/ath12k/hal.h1523
-rw-r--r--drivers/net/wireless/ath/ath12k/htc.c3
-rw-r--r--drivers/net/wireless/ath/ath12k/hw.c1680
-rw-r--r--drivers/net/wireless/ath/ath12k/hw.h96
-rw-r--r--drivers/net/wireless/ath/ath12k/mac.c1255
-rw-r--r--drivers/net/wireless/ath/ath12k/mac.h142
-rw-r--r--drivers/net/wireless/ath/ath12k/mhi.c132
-rw-r--r--drivers/net/wireless/ath/ath12k/mhi.h5
-rw-r--r--drivers/net/wireless/ath/ath12k/pci.c255
-rw-r--r--drivers/net/wireless/ath/ath12k/pci.h49
-rw-r--r--drivers/net/wireless/ath/ath12k/peer.c453
-rw-r--r--drivers/net/wireless/ath/ath12k/peer.h112
-rw-r--r--drivers/net/wireless/ath/ath12k/qmi.c180
-rw-r--r--drivers/net/wireless/ath/ath12k/qmi.h16
-rw-r--r--drivers/net/wireless/ath/ath12k/testmode.c3
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/Makefile20
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/ahb.c75
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/ahb.h20
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/ce.c973
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/ce.h22
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/core.c68
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/core.h11
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/dp.c181
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/dp.h20
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c3385
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/dp_mon.h23
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c2246
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h60
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c978
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/dp_tx.h16
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/hal.c713
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/hal.h561
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/hal_desc.h (renamed from drivers/net/wireless/ath/ath12k/hal_desc.h)331
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c503
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.h13
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c1038
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.h45
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/hal_rx.c (renamed from drivers/net/wireless/ath/ath12k/hal_rx.c)284
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/hal_rx.h (renamed from drivers/net/wireless/ath/ath12k/hal_rx.h)424
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/hal_rx_desc.h (renamed from drivers/net/wireless/ath/ath12k/rx_desc.h)72
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/hal_tx.c (renamed from drivers/net/wireless/ath/ath12k/hal_tx.c)23
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/hal_tx.h (renamed from drivers/net/wireless/ath/ath12k/hal_tx.h)30
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c809
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.h40
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/hw.c1049
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/hw.h13
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/mhi.c138
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/mhi.h11
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/pci.c215
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/pci.h12
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/wmi.c110
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/wmi.h15
-rw-r--r--drivers/net/wireless/ath/ath12k/wmi.c334
-rw-r--r--drivers/net/wireless/ath/ath12k/wmi.h61
-rw-r--r--drivers/net/wireless/ath/ath12k/wow.c21
-rw-r--r--drivers/net/wireless/ath/ath5k/debug.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/Kconfig2
-rw-r--r--drivers/net/wireless/ath/ath9k/common-debug.h8
-rw-r--r--drivers/net/wireless/ath/ath9k/common.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.h15
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h33
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c4
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h8
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c4
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c9
-rw-r--r--drivers/net/wireless/intel/iwlegacy/3945-mac.c2
-rw-r--r--drivers/net/wireless/intel/iwlegacy/3945-rs.c7
-rw-r--r--drivers/net/wireless/intel/iwlegacy/4965-mac.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/bz.c12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/rf-fm.c12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/rf-pe.c1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/acpi.c117
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h159
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h34
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/power.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/rs.h41
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/rx.h95
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/file.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/regulatory.c206
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/regulatory.h9
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/runtime.h17
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/smem.c8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/uefi.c72
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/uefi.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-config.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/Makefile2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/d3.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/debugfs.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/iface.c21
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/iface.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/mac80211.c114
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/mld.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/mld.h3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/mlo.c59
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/mlo.h5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/nan.c299
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/nan.h28
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/notif.c13
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/notif.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/power.c37
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/regulatory.c66
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/rx.c142
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/scan.c12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/sta.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/tlc.c85
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/tx.c11
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/d3.c51
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c202
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/link.c22
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c25
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c68
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c29
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c193
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c28
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h60
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c18
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tdls.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/time-event.c39
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/time-event.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tx.c51
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/utils.c4
-rw-r--r--drivers/net/wireless/intersil/p54/main.c4
-rw-r--r--drivers/net/wireless/marvell/libertas/if_usb.c2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cfg80211.c13
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/core.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c13
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/regd.c2
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.c54
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.h2
-rw-r--r--drivers/net/wireless/realtek/rtw88/phy.c20
-rw-r--r--drivers/net/wireless/realtek/rtw88/phy.h2
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8723cs.c2
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8723ds.c2
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821cs.c2
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821cu.c2
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822b.c3
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822bs.c2
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822cs.c2
-rw-r--r--drivers/net/wireless/realtek/rtw88/sdio.c3
-rw-r--r--drivers/net/wireless/realtek/rtw88/sdio.h2
-rw-r--r--drivers/net/wireless/realtek/rtw88/usb.c3
-rw-r--r--drivers/net/wireless/realtek/rtw89/cam.c134
-rw-r--r--drivers/net/wireless/realtek/rtw89/cam.h129
-rw-r--r--drivers/net/wireless/realtek/rtw89/chan.c69
-rw-r--r--drivers/net/wireless/realtek/rtw89/chan.h2
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.c237
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.h198
-rw-r--r--drivers/net/wireless/realtek/rtw89/debug.c162
-rw-r--r--drivers/net/wireless/realtek/rtw89/debug.h1
-rw-r--r--drivers/net/wireless/realtek/rtw89/efuse.c4
-rw-r--r--drivers/net/wireless/realtek/rtw89/efuse.h6
-rw-r--r--drivers/net/wireless/realtek/rtw89/efuse_be.c26
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.c1163
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.h521
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac.c199
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac.h102
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac80211.c44
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac_be.c696
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci.c22
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci.h57
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci_be.c138
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.c428
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.h36
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy_be.c563
-rw-r--r--drivers/net/wireless/realtek/rtw89/ps.c4
-rw-r--r--drivers/net/wireless/realtek/rtw89/reg.h934
-rw-r--r--drivers/net/wireless/realtek/rtw89/regd.c21
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b.c10
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852a.c10
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852au.c4
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852b.c32
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852b_common.c2
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852bt.c8
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852bu.c2
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c.c10
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852cu.c2
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8922a.c89
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c48
-rw-r--r--drivers/net/wireless/realtek/rtw89/ser.c10
-rw-r--r--drivers/net/wireless/realtek/rtw89/txrx.h22
-rw-r--r--drivers/net/wireless/realtek/rtw89/usb.c2
-rw-r--r--drivers/net/wireless/realtek/rtw89/wow.c14
-rw-r--r--drivers/net/wireless/realtek/rtw89/wow.h1
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_main.c29
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_sdio.c5
-rw-r--r--drivers/net/wireless/ti/wl1251/acx.c11
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.h1
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c9
-rw-r--r--drivers/net/wireless/ti/wlcore/sdio.c6
-rw-r--r--drivers/net/wireless/virtual/mac80211_hwsim.c2
247 files changed, 31284 insertions, 19069 deletions
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
index c06d50db40b8..00d0556dafef 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -2487,7 +2487,11 @@ void ath10k_sdio_fw_crashed_dump(struct ath10k *ar)
if (fast_dump)
ath10k_bmi_start(ar);
+ mutex_lock(&ar->dump_mutex);
+
+ spin_lock_bh(&ar->data_lock);
ar->stats.fw_crash_counter++;
+ spin_unlock_bh(&ar->data_lock);
ath10k_sdio_disable_intrs(ar);
@@ -2505,6 +2509,8 @@ void ath10k_sdio_fw_crashed_dump(struct ath10k *ar)
ath10k_sdio_enable_intrs(ar);
+ mutex_unlock(&ar->dump_mutex);
+
ath10k_core_start_recovery(ar);
}
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index b3f6424c17d3..f72f236fb9eb 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/bits.h>
@@ -11,6 +12,7 @@
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/property.h>
+#include <linux/pwrseq/consumer.h>
#include <linux/regulator/consumer.h>
#include <linux/remoteproc/qcom_rproc.h>
#include <linux/of_reserved_mem.h>
@@ -1023,10 +1025,14 @@ static int ath10k_hw_power_on(struct ath10k *ar)
ath10k_dbg(ar, ATH10K_DBG_SNOC, "soc power on\n");
- ret = regulator_bulk_enable(ar_snoc->num_vregs, ar_snoc->vregs);
+ ret = pwrseq_power_on(ar_snoc->pwrseq);
if (ret)
return ret;
+ ret = regulator_bulk_enable(ar_snoc->num_vregs, ar_snoc->vregs);
+ if (ret)
+ goto pwrseq_off;
+
ret = clk_bulk_prepare_enable(ar_snoc->num_clks, ar_snoc->clks);
if (ret)
goto vreg_off;
@@ -1035,18 +1041,28 @@ static int ath10k_hw_power_on(struct ath10k *ar)
vreg_off:
regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs);
+pwrseq_off:
+ pwrseq_power_off(ar_snoc->pwrseq);
+
return ret;
}
static int ath10k_hw_power_off(struct ath10k *ar)
{
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
+ int ret_seq = 0;
+ int ret_vreg;
ath10k_dbg(ar, ATH10K_DBG_SNOC, "soc power off\n");
clk_bulk_disable_unprepare(ar_snoc->num_clks, ar_snoc->clks);
- return regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs);
+ ret_vreg = regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs);
+
+ if (ar_snoc->pwrseq)
+ ret_seq = pwrseq_power_off(ar_snoc->pwrseq);
+
+ return ret_vreg ? : ret_seq;
}
static void ath10k_snoc_wlan_disable(struct ath10k *ar)
@@ -1762,7 +1778,38 @@ static int ath10k_snoc_probe(struct platform_device *pdev)
goto err_release_resource;
}
- ar_snoc->num_vregs = ARRAY_SIZE(ath10k_regulators);
+ /*
+ * devm_pwrseq_get() can return -EPROBE_DEFER in two cases:
+ * - it is not supposed to be used
+ * - it is supposed to be used, but the driver hasn't probed yet.
+ *
+ * There is no simple way to distinguish between these two cases, but:
+ * - if it is not supposed to be used, then regulator_bulk_get() will
+ * return all regulators as expected, continuing the probe
+ * - if it is supposed to be used, but wasn't probed yet, we will get
+ * -EPROBE_DEFER from regulator_bulk_get() too.
+ *
+ * For backwards compatibility with DTs specifying regulators directly
+ * rather than using the PMU device, ignore the defer error from
+ * pwrseq.
+ */
+ ar_snoc->pwrseq = devm_pwrseq_get(&pdev->dev, "wlan");
+ if (IS_ERR(ar_snoc->pwrseq)) {
+ ret = PTR_ERR(ar_snoc->pwrseq);
+ ar_snoc->pwrseq = NULL;
+ if (ret != -EPROBE_DEFER)
+ goto err_free_irq;
+
+ ar_snoc->num_vregs = ARRAY_SIZE(ath10k_regulators);
+ } else {
+ /*
+ * The first regulator (vdd-0.8-cx-mx) is used to power on part
+ * of the SoC rather than the PMU on WCN399x, the rest are
+ * handled via pwrseq.
+ */
+ ar_snoc->num_vregs = 1;
+ }
+
ar_snoc->vregs = devm_kcalloc(&pdev->dev, ar_snoc->num_vregs,
sizeof(*ar_snoc->vregs), GFP_KERNEL);
if (!ar_snoc->vregs) {
diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h
index d4bce1707696..1ecae34687c2 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.h
+++ b/drivers/net/wireless/ath/ath10k/snoc.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef _SNOC_H_
@@ -53,6 +54,7 @@ enum ath10k_snoc_flags {
};
struct clk_bulk_data;
+struct pwrseq_desc;
struct regulator_bulk_data;
struct ath10k_snoc {
@@ -73,6 +75,7 @@ struct ath10k_snoc {
struct ath10k_snoc_ce_irq ce_irqs[CE_COUNT_MAX];
struct ath10k_ce ce;
struct timer_list rx_post_retry;
+ struct pwrseq_desc *pwrseq;
struct regulator_bulk_data *vregs;
size_t num_vregs;
struct clk_bulk_data *clks;
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index b4aad6604d6d..ce22141e5efd 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -5289,8 +5289,6 @@ ath10k_wmi_event_peer_sta_ps_state_chg(struct ath10k *ar, struct sk_buff *skb)
struct ath10k_sta *arsta;
u8 peer_addr[ETH_ALEN];
- lockdep_assert_held(&ar->data_lock);
-
ev = (struct wmi_peer_sta_ps_state_chg_event *)skb->data;
ether_addr_copy(peer_addr, ev->peer_macaddr.addr);
@@ -5305,7 +5303,9 @@ ath10k_wmi_event_peer_sta_ps_state_chg(struct ath10k *ar, struct sk_buff *skb)
}
arsta = (struct ath10k_sta *)sta->drv_priv;
+ spin_lock_bh(&ar->data_lock);
arsta->peer_ps_state = __le32_to_cpu(ev->peer_ps_state);
+ spin_unlock_bh(&ar->data_lock);
exit:
rcu_read_unlock();
diff --git a/drivers/net/wireless/ath/ath11k/Kconfig b/drivers/net/wireless/ath/ath11k/Kconfig
index 659ef134ef16..47dfd39caa89 100644
--- a/drivers/net/wireless/ath/ath11k/Kconfig
+++ b/drivers/net/wireless/ath/ath11k/Kconfig
@@ -58,3 +58,14 @@ config ATH11K_SPECTRAL
Enable ath11k spectral scan support
Say Y to enable access to the FFT/spectral data via debugfs.
+
+config ATH11K_CFR
+ bool "ath11k channel frequency response support"
+ depends on ATH11K_DEBUGFS
+ depends on RELAY
+ help
+ Enable ath11k channel frequency response dump support.
+ This option exposes debugfs nodes that will allow the user
+ to enable, disable, and dump data.
+
+ Say Y to enable CFR data dump collection via debugfs.
diff --git a/drivers/net/wireless/ath/ath11k/Makefile b/drivers/net/wireless/ath/ath11k/Makefile
index d9092414b362..b1435fcf3e1b 100644
--- a/drivers/net/wireless/ath/ath11k/Makefile
+++ b/drivers/net/wireless/ath/ath11k/Makefile
@@ -28,6 +28,7 @@ ath11k-$(CONFIG_THERMAL) += thermal.o
ath11k-$(CONFIG_ATH11K_SPECTRAL) += spectral.o
ath11k-$(CONFIG_PM) += wow.o
ath11k-$(CONFIG_DEV_COREDUMP) += coredump.o
+ath11k-$(CONFIG_ATH11K_CFR) += cfr.o
obj-$(CONFIG_ATH11K_AHB) += ath11k_ahb.o
ath11k_ahb-y += ahb.o
diff --git a/drivers/net/wireless/ath/ath11k/cfr.c b/drivers/net/wireless/ath/ath11k/cfr.c
new file mode 100644
index 000000000000..61bf1c0884f7
--- /dev/null
+++ b/drivers/net/wireless/ath/ath11k/cfr.c
@@ -0,0 +1,1023 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/relay.h>
+#include "core.h"
+#include "debug.h"
+
+struct ath11k_dbring *ath11k_cfr_get_dbring(struct ath11k *ar)
+{
+ if (ar->cfr_enabled)
+ return &ar->cfr.rx_ring;
+
+ return NULL;
+}
+
+static int ath11k_cfr_calculate_tones_from_dma_hdr(struct ath11k_cfr_dma_hdr *hdr)
+{
+ u8 bw = FIELD_GET(CFIR_DMA_HDR_INFO1_UPLOAD_PKT_BW, hdr->info1);
+ u8 preamble = FIELD_GET(CFIR_DMA_HDR_INFO1_PREAMBLE_TYPE, hdr->info1);
+
+ switch (preamble) {
+ case ATH11K_CFR_PREAMBLE_TYPE_LEGACY:
+ fallthrough;
+ case ATH11K_CFR_PREAMBLE_TYPE_VHT:
+ switch (bw) {
+ case 0:
+ return TONES_IN_20MHZ;
+ case 1: /* DUP40/VHT40 */
+ return TONES_IN_40MHZ;
+ case 2: /* DUP80/VHT80 */
+ return TONES_IN_80MHZ;
+ case 3: /* DUP160/VHT160 */
+ return TONES_IN_160MHZ;
+ default:
+ return TONES_INVALID;
+ }
+ case ATH11K_CFR_PREAMBLE_TYPE_HT:
+ switch (bw) {
+ case 0:
+ return TONES_IN_20MHZ;
+ case 1:
+ return TONES_IN_40MHZ;
+ default:
+ return TONES_INVALID;
+ }
+ default:
+ return TONES_INVALID;
+ }
+}
+
+void ath11k_cfr_release_lut_entry(struct ath11k_look_up_table *lut)
+{
+ memset(lut, 0, sizeof(*lut));
+}
+
+static void ath11k_cfr_rfs_write(struct ath11k *ar, const void *head,
+ u32 head_len, const void *data, u32 data_len,
+ const void *tail, int tail_data)
+{
+ struct ath11k_cfr *cfr = &ar->cfr;
+
+ if (!cfr->rfs_cfr_capture)
+ return;
+
+ relay_write(cfr->rfs_cfr_capture, head, head_len);
+ relay_write(cfr->rfs_cfr_capture, data, data_len);
+ relay_write(cfr->rfs_cfr_capture, tail, tail_data);
+ relay_flush(cfr->rfs_cfr_capture);
+}
+
+static void ath11k_cfr_free_pending_dbr_events(struct ath11k *ar)
+{
+ struct ath11k_cfr *cfr = &ar->cfr;
+ struct ath11k_look_up_table *lut;
+ int i;
+
+ if (!cfr->lut)
+ return;
+
+ for (i = 0; i < cfr->lut_num; i++) {
+ lut = &cfr->lut[i];
+ if (lut->dbr_recv && !lut->tx_recv &&
+ lut->dbr_tstamp < cfr->last_success_tstamp) {
+ ath11k_dbring_bufs_replenish(ar, &cfr->rx_ring, lut->buff,
+ WMI_DIRECT_BUF_CFR);
+ ath11k_cfr_release_lut_entry(lut);
+ cfr->flush_dbr_cnt++;
+ }
+ }
+}
+
+/**
+ * ath11k_cfr_correlate_and_relay() - Correlate and relay CFR events
+ * @ar: Pointer to ath11k structure
+ * @lut: Lookup table for correlation
+ * @event_type: Type of event received (TX or DBR)
+ *
+ * Correlates WMI_PDEV_DMA_RING_BUF_RELEASE_EVENT (DBR) and
+ * WMI_PEER_CFR_CAPTURE_EVENT (TX capture) by PPDU ID. If both events
+ * are present and the PPDU IDs match, returns CORRELATE_STATUS_RELEASE
+ * to relay thecorrelated data to userspace. Otherwise returns
+ * CORRELATE_STATUS_HOLD to wait for the other event.
+ *
+ * Also checks pending DBR events and clears them when no corresponding TX
+ * capture event is received for the PPDU.
+ *
+ * Return: CORRELATE_STATUS_RELEASE or CORRELATE_STATUS_HOLD
+ */
+
+static enum ath11k_cfr_correlate_status
+ath11k_cfr_correlate_and_relay(struct ath11k *ar,
+ struct ath11k_look_up_table *lut,
+ u8 event_type)
+{
+ enum ath11k_cfr_correlate_status status;
+ struct ath11k_cfr *cfr = &ar->cfr;
+ u64 diff;
+
+ if (event_type == ATH11K_CORRELATE_TX_EVENT) {
+ if (lut->tx_recv)
+ cfr->cfr_dma_aborts++;
+ cfr->tx_evt_cnt++;
+ lut->tx_recv = true;
+ } else if (event_type == ATH11K_CORRELATE_DBR_EVENT) {
+ cfr->dbr_evt_cnt++;
+ lut->dbr_recv = true;
+ }
+
+ if (lut->dbr_recv && lut->tx_recv) {
+ if (lut->dbr_ppdu_id == lut->tx_ppdu_id) {
+ /*
+ * 64-bit counters make wraparound highly improbable,
+ * wraparound handling is omitted.
+ */
+ cfr->last_success_tstamp = lut->dbr_tstamp;
+ if (lut->dbr_tstamp > lut->txrx_tstamp) {
+ diff = lut->dbr_tstamp - lut->txrx_tstamp;
+ ath11k_dbg(ar->ab, ATH11K_DBG_CFR,
+ "txrx event -> dbr event delay = %u ms",
+ jiffies_to_msecs(diff));
+ } else if (lut->txrx_tstamp > lut->dbr_tstamp) {
+ diff = lut->txrx_tstamp - lut->dbr_tstamp;
+ ath11k_dbg(ar->ab, ATH11K_DBG_CFR,
+ "dbr event -> txrx event delay = %u ms",
+ jiffies_to_msecs(diff));
+ }
+
+ ath11k_cfr_free_pending_dbr_events(ar);
+
+ cfr->release_cnt++;
+ status = ATH11K_CORRELATE_STATUS_RELEASE;
+ } else {
+ /*
+ * Discard TXRX event on PPDU ID mismatch because multiple PPDUs
+ * may share the same DMA address due to ucode aborts.
+ */
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_CFR,
+ "Received dbr event twice for the same lut entry");
+ lut->tx_recv = false;
+ lut->tx_ppdu_id = 0;
+ cfr->clear_txrx_event++;
+ cfr->cfr_dma_aborts++;
+ status = ATH11K_CORRELATE_STATUS_HOLD;
+ }
+ } else {
+ status = ATH11K_CORRELATE_STATUS_HOLD;
+ }
+
+ return status;
+}
+
+static int ath11k_cfr_process_data(struct ath11k *ar,
+ struct ath11k_dbring_data *param)
+{
+ u32 end_magic = ATH11K_CFR_END_MAGIC;
+ struct ath11k_csi_cfr_header *header;
+ struct ath11k_cfr_dma_hdr *dma_hdr;
+ struct ath11k_cfr *cfr = &ar->cfr;
+ struct ath11k_look_up_table *lut;
+ struct ath11k_base *ab = ar->ab;
+ u32 buf_id, tones, length;
+ u8 num_chains;
+ int status;
+ u8 *data;
+
+ data = param->data;
+ buf_id = param->buf_id;
+
+ if (param->data_sz < sizeof(*dma_hdr))
+ return -EINVAL;
+
+ dma_hdr = (struct ath11k_cfr_dma_hdr *)data;
+
+ tones = ath11k_cfr_calculate_tones_from_dma_hdr(dma_hdr);
+ if (tones == TONES_INVALID) {
+ ath11k_warn(ar->ab, "Number of tones received is invalid\n");
+ return -EINVAL;
+ }
+
+ num_chains = FIELD_GET(CFIR_DMA_HDR_INFO1_NUM_CHAINS,
+ dma_hdr->info1);
+
+ length = sizeof(*dma_hdr);
+ length += tones * (num_chains + 1);
+
+ spin_lock_bh(&cfr->lut_lock);
+
+ if (!cfr->lut) {
+ spin_unlock_bh(&cfr->lut_lock);
+ return -EINVAL;
+ }
+
+ lut = &cfr->lut[buf_id];
+
+ ath11k_dbg_dump(ab, ATH11K_DBG_CFR_DUMP, "data_from_buf_rel:", "",
+ data, length);
+
+ lut->buff = param->buff;
+ lut->data = data;
+ lut->data_len = length;
+ lut->dbr_ppdu_id = dma_hdr->phy_ppdu_id;
+ lut->dbr_tstamp = jiffies;
+
+ memcpy(&lut->hdr, dma_hdr, sizeof(*dma_hdr));
+
+ header = &lut->header;
+ header->meta_data.channel_bw = FIELD_GET(CFIR_DMA_HDR_INFO1_UPLOAD_PKT_BW,
+ dma_hdr->info1);
+ header->meta_data.length = length;
+
+ status = ath11k_cfr_correlate_and_relay(ar, lut,
+ ATH11K_CORRELATE_DBR_EVENT);
+ if (status == ATH11K_CORRELATE_STATUS_RELEASE) {
+ ath11k_dbg(ab, ATH11K_DBG_CFR,
+ "releasing CFR data to user space");
+ ath11k_cfr_rfs_write(ar, &lut->header,
+ sizeof(struct ath11k_csi_cfr_header),
+ lut->data, lut->data_len,
+ &end_magic, sizeof(u32));
+ ath11k_cfr_release_lut_entry(lut);
+ } else if (status == ATH11K_CORRELATE_STATUS_HOLD) {
+ ath11k_dbg(ab, ATH11K_DBG_CFR,
+ "tx event is not yet received holding the buf");
+ }
+
+ spin_unlock_bh(&cfr->lut_lock);
+
+ return status;
+}
+
+static void ath11k_cfr_fill_hdr_info(struct ath11k *ar,
+ struct ath11k_csi_cfr_header *header,
+ struct ath11k_cfr_peer_tx_param *params)
+{
+ struct ath11k_cfr *cfr;
+
+ cfr = &ar->cfr;
+ header->cfr_metadata_version = ATH11K_CFR_META_VERSION_4;
+ header->cfr_data_version = ATH11K_CFR_DATA_VERSION_1;
+ header->cfr_metadata_len = sizeof(struct cfr_metadata);
+ header->chip_type = ar->ab->hw_rev;
+ header->meta_data.status = FIELD_GET(WMI_CFR_PEER_CAPTURE_STATUS,
+ params->status);
+ header->meta_data.capture_bw = params->bandwidth;
+
+ /*
+ * FW reports phymode will always be HE mode.
+ * Replace it with cached phy mode during peer assoc
+ */
+ header->meta_data.phy_mode = cfr->phymode;
+
+ header->meta_data.prim20_chan = params->primary_20mhz_chan;
+ header->meta_data.center_freq1 = params->band_center_freq1;
+ header->meta_data.center_freq2 = params->band_center_freq2;
+
+ /*
+ * CFR capture is triggered by the ACK of a QoS Null frame:
+ * - 20 MHz: Legacy ACK
+ * - 40/80/160 MHz: DUP Legacy ACK
+ */
+ header->meta_data.capture_mode = params->bandwidth ?
+ ATH11K_CFR_CAPTURE_DUP_LEGACY_ACK : ATH11K_CFR_CAPTURE_LEGACY_ACK;
+ header->meta_data.capture_type = params->capture_method;
+ header->meta_data.num_rx_chain = ar->num_rx_chains;
+ header->meta_data.sts_count = params->spatial_streams;
+ header->meta_data.timestamp = params->timestamp_us;
+ ether_addr_copy(header->meta_data.peer_addr, params->peer_mac_addr);
+ memcpy(header->meta_data.chain_rssi, params->chain_rssi,
+ sizeof(params->chain_rssi));
+ memcpy(header->meta_data.chain_phase, params->chain_phase,
+ sizeof(params->chain_phase));
+ memcpy(header->meta_data.agc_gain, params->agc_gain,
+ sizeof(params->agc_gain));
+}
+
+int ath11k_process_cfr_capture_event(struct ath11k_base *ab,
+ struct ath11k_cfr_peer_tx_param *params)
+{
+ struct ath11k_look_up_table *lut = NULL;
+ u32 end_magic = ATH11K_CFR_END_MAGIC;
+ struct ath11k_csi_cfr_header *header;
+ struct ath11k_dbring_element *buff;
+ struct ath11k_cfr *cfr;
+ dma_addr_t buf_addr;
+ struct ath11k *ar;
+ u8 tx_status;
+ int status;
+ int i;
+
+ rcu_read_lock();
+ ar = ath11k_mac_get_ar_by_vdev_id(ab, params->vdev_id);
+ if (!ar) {
+ rcu_read_unlock();
+ ath11k_warn(ab, "Failed to get ar for vdev id %d\n",
+ params->vdev_id);
+ return -ENOENT;
+ }
+
+ cfr = &ar->cfr;
+ rcu_read_unlock();
+
+ if (WMI_CFR_CAPTURE_STATUS_PEER_PS & params->status) {
+ ath11k_warn(ab, "CFR capture failed as peer %pM is in powersave",
+ params->peer_mac_addr);
+ return -EINVAL;
+ }
+
+ if (!(WMI_CFR_PEER_CAPTURE_STATUS & params->status)) {
+ ath11k_warn(ab, "CFR capture failed for the peer : %pM",
+ params->peer_mac_addr);
+ cfr->tx_peer_status_cfr_fail++;
+ return -EINVAL;
+ }
+
+ tx_status = FIELD_GET(WMI_CFR_FRAME_TX_STATUS, params->status);
+ if (tx_status != WMI_FRAME_TX_STATUS_OK) {
+ ath11k_warn(ab, "WMI tx status %d for the peer %pM",
+ tx_status, params->peer_mac_addr);
+ cfr->tx_evt_status_cfr_fail++;
+ return -EINVAL;
+ }
+
+ buf_addr = (((u64)FIELD_GET(WMI_CFR_CORRELATION_INFO2_BUF_ADDR_HIGH,
+ params->correlation_info_2)) << 32) |
+ params->correlation_info_1;
+
+ spin_lock_bh(&cfr->lut_lock);
+
+ if (!cfr->lut) {
+ spin_unlock_bh(&cfr->lut_lock);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < cfr->lut_num; i++) {
+ struct ath11k_look_up_table *temp = &cfr->lut[i];
+
+ if (temp->dbr_address == buf_addr) {
+ lut = &cfr->lut[i];
+ break;
+ }
+ }
+
+ if (!lut) {
+ spin_unlock_bh(&cfr->lut_lock);
+ ath11k_warn(ab, "lut failure to process tx event\n");
+ cfr->tx_dbr_lookup_fail++;
+ return -EINVAL;
+ }
+
+ lut->tx_ppdu_id = FIELD_GET(WMI_CFR_CORRELATION_INFO2_PPDU_ID,
+ params->correlation_info_2);
+ lut->txrx_tstamp = jiffies;
+
+ header = &lut->header;
+ header->start_magic_num = ATH11K_CFR_START_MAGIC;
+ header->vendorid = VENDOR_QCA;
+ header->platform_type = PLATFORM_TYPE_ARM;
+
+ ath11k_cfr_fill_hdr_info(ar, header, params);
+
+ status = ath11k_cfr_correlate_and_relay(ar, lut,
+ ATH11K_CORRELATE_TX_EVENT);
+ if (status == ATH11K_CORRELATE_STATUS_RELEASE) {
+ ath11k_dbg(ab, ATH11K_DBG_CFR,
+ "Releasing CFR data to user space");
+ ath11k_cfr_rfs_write(ar, &lut->header,
+ sizeof(struct ath11k_csi_cfr_header),
+ lut->data, lut->data_len,
+ &end_magic, sizeof(u32));
+ buff = lut->buff;
+ ath11k_cfr_release_lut_entry(lut);
+
+ ath11k_dbring_bufs_replenish(ar, &cfr->rx_ring, buff,
+ WMI_DIRECT_BUF_CFR);
+ } else if (status == ATH11K_CORRELATE_STATUS_HOLD) {
+ ath11k_dbg(ab, ATH11K_DBG_CFR,
+ "dbr event is not yet received holding buf\n");
+ }
+
+ spin_unlock_bh(&cfr->lut_lock);
+
+ return 0;
+}
+
+/* Helper function to check whether the given peer mac address
+ * is in unassociated peer pool or not.
+ */
+bool ath11k_cfr_peer_is_in_cfr_unassoc_pool(struct ath11k *ar, const u8 *peer_mac)
+{
+ struct ath11k_cfr *cfr = &ar->cfr;
+ struct cfr_unassoc_pool_entry *entry;
+ int i;
+
+ if (!ar->cfr_enabled)
+ return false;
+
+ spin_lock_bh(&cfr->lock);
+ for (i = 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) {
+ entry = &cfr->unassoc_pool[i];
+ if (!entry->is_valid)
+ continue;
+
+ if (ether_addr_equal(peer_mac, entry->peer_mac)) {
+ spin_unlock_bh(&cfr->lock);
+ return true;
+ }
+ }
+
+ spin_unlock_bh(&cfr->lock);
+
+ return false;
+}
+
+void ath11k_cfr_update_unassoc_pool_entry(struct ath11k *ar,
+ const u8 *peer_mac)
+{
+ struct ath11k_cfr *cfr = &ar->cfr;
+ struct cfr_unassoc_pool_entry *entry;
+ int i;
+
+ spin_lock_bh(&cfr->lock);
+ for (i = 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) {
+ entry = &cfr->unassoc_pool[i];
+ if (!entry->is_valid)
+ continue;
+
+ if (ether_addr_equal(peer_mac, entry->peer_mac) &&
+ entry->period == 0) {
+ memset(entry->peer_mac, 0, ETH_ALEN);
+ entry->is_valid = false;
+ cfr->cfr_enabled_peer_cnt--;
+ break;
+ }
+ }
+
+ spin_unlock_bh(&cfr->lock);
+}
+
+void ath11k_cfr_decrement_peer_count(struct ath11k *ar,
+ struct ath11k_sta *arsta)
+{
+ struct ath11k_cfr *cfr = &ar->cfr;
+
+ spin_lock_bh(&cfr->lock);
+
+ if (arsta->cfr_capture.cfr_enable)
+ cfr->cfr_enabled_peer_cnt--;
+
+ spin_unlock_bh(&cfr->lock);
+}
+
+static enum ath11k_wmi_cfr_capture_bw
+ath11k_cfr_bw_to_fw_cfr_bw(enum ath11k_cfr_capture_bw bw)
+{
+ switch (bw) {
+ case ATH11K_CFR_CAPTURE_BW_20:
+ return WMI_PEER_CFR_CAPTURE_BW_20;
+ case ATH11K_CFR_CAPTURE_BW_40:
+ return WMI_PEER_CFR_CAPTURE_BW_40;
+ case ATH11K_CFR_CAPTURE_BW_80:
+ return WMI_PEER_CFR_CAPTURE_BW_80;
+ default:
+ return WMI_PEER_CFR_CAPTURE_BW_MAX;
+ }
+}
+
+static enum ath11k_wmi_cfr_capture_method
+ath11k_cfr_method_to_fw_cfr_method(enum ath11k_cfr_capture_method method)
+{
+ switch (method) {
+ case ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME:
+ return WMI_CFR_CAPTURE_METHOD_NULL_FRAME;
+ case ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE:
+ return WMI_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE;
+ case ATH11K_CFR_CAPTURE_METHOD_PROBE_RESP:
+ return WMI_CFR_CAPTURE_METHOD_PROBE_RESP;
+ default:
+ return WMI_CFR_CAPTURE_METHOD_MAX;
+ }
+}
+
+int ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k *ar,
+ struct ath11k_sta *arsta,
+ struct ath11k_per_peer_cfr_capture *params,
+ const u8 *peer_mac)
+{
+ struct ath11k_cfr *cfr = &ar->cfr;
+ struct wmi_peer_cfr_capture_conf_arg arg;
+ enum ath11k_wmi_cfr_capture_bw bw;
+ enum ath11k_wmi_cfr_capture_method method;
+ int ret = 0;
+
+ if (cfr->cfr_enabled_peer_cnt >= ATH11K_MAX_CFR_ENABLED_CLIENTS &&
+ !arsta->cfr_capture.cfr_enable) {
+ ath11k_err(ar->ab, "CFR enable peer threshold reached %u\n",
+ cfr->cfr_enabled_peer_cnt);
+ return -ENOSPC;
+ }
+
+ if (params->cfr_enable == arsta->cfr_capture.cfr_enable &&
+ params->cfr_period == arsta->cfr_capture.cfr_period &&
+ params->cfr_method == arsta->cfr_capture.cfr_method &&
+ params->cfr_bw == arsta->cfr_capture.cfr_bw)
+ return ret;
+
+ if (!params->cfr_enable && !arsta->cfr_capture.cfr_enable)
+ return ret;
+
+ bw = ath11k_cfr_bw_to_fw_cfr_bw(params->cfr_bw);
+ if (bw >= WMI_PEER_CFR_CAPTURE_BW_MAX) {
+ ath11k_warn(ar->ab, "FW doesn't support configured bw %d\n",
+ params->cfr_bw);
+ return -EINVAL;
+ }
+
+ method = ath11k_cfr_method_to_fw_cfr_method(params->cfr_method);
+ if (method >= WMI_CFR_CAPTURE_METHOD_MAX) {
+ ath11k_warn(ar->ab, "FW doesn't support configured method %d\n",
+ params->cfr_method);
+ return -EINVAL;
+ }
+
+ arg.request = params->cfr_enable;
+ arg.periodicity = params->cfr_period;
+ arg.bw = bw;
+ arg.method = method;
+
+ ret = ath11k_wmi_peer_set_cfr_capture_conf(ar, arsta->arvif->vdev_id,
+ peer_mac, &arg);
+ if (ret) {
+ ath11k_warn(ar->ab,
+ "failed to send cfr capture info: vdev_id %u peer %pM: %d\n",
+ arsta->arvif->vdev_id, peer_mac, ret);
+ return ret;
+ }
+
+ spin_lock_bh(&cfr->lock);
+
+ if (params->cfr_enable &&
+ params->cfr_enable != arsta->cfr_capture.cfr_enable)
+ cfr->cfr_enabled_peer_cnt++;
+ else if (!params->cfr_enable)
+ cfr->cfr_enabled_peer_cnt--;
+
+ spin_unlock_bh(&cfr->lock);
+
+ arsta->cfr_capture.cfr_enable = params->cfr_enable;
+ arsta->cfr_capture.cfr_period = params->cfr_period;
+ arsta->cfr_capture.cfr_method = params->cfr_method;
+ arsta->cfr_capture.cfr_bw = params->cfr_bw;
+
+ return ret;
+}
+
+void ath11k_cfr_update_unassoc_pool(struct ath11k *ar,
+ struct ath11k_per_peer_cfr_capture *params,
+ u8 *peer_mac)
+{
+ struct ath11k_cfr *cfr = &ar->cfr;
+ struct cfr_unassoc_pool_entry *entry;
+ int available_idx = -1;
+ int i;
+
+ guard(spinlock_bh)(&cfr->lock);
+
+ if (!params->cfr_enable) {
+ for (i = 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) {
+ entry = &cfr->unassoc_pool[i];
+ if (ether_addr_equal(peer_mac, entry->peer_mac)) {
+ memset(entry->peer_mac, 0, ETH_ALEN);
+ entry->is_valid = false;
+ cfr->cfr_enabled_peer_cnt--;
+ break;
+ }
+ }
+ return;
+ }
+
+ if (cfr->cfr_enabled_peer_cnt >= ATH11K_MAX_CFR_ENABLED_CLIENTS) {
+ ath11k_info(ar->ab, "Max cfr peer threshold reached\n");
+ return;
+ }
+
+ for (i = 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) {
+ entry = &cfr->unassoc_pool[i];
+
+ if (ether_addr_equal(peer_mac, entry->peer_mac)) {
+ ath11k_info(ar->ab,
+ "peer entry already present updating params\n");
+ entry->period = params->cfr_period;
+ available_idx = -1;
+ break;
+ }
+
+ if (available_idx < 0 && !entry->is_valid)
+ available_idx = i;
+ }
+
+ if (available_idx >= 0) {
+ entry = &cfr->unassoc_pool[available_idx];
+ ether_addr_copy(entry->peer_mac, peer_mac);
+ entry->period = params->cfr_period;
+ entry->is_valid = true;
+ cfr->cfr_enabled_peer_cnt++;
+ }
+}
+
+static ssize_t ath11k_read_file_enable_cfr(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath11k *ar = file->private_data;
+ char buf[32] = {};
+ size_t len;
+
+ mutex_lock(&ar->conf_mutex);
+ len = scnprintf(buf, sizeof(buf), "%d\n", ar->cfr_enabled);
+ mutex_unlock(&ar->conf_mutex);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t ath11k_write_file_enable_cfr(struct file *file,
+ const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct ath11k *ar = file->private_data;
+ u32 enable_cfr;
+ int ret;
+
+ if (kstrtouint_from_user(ubuf, count, 0, &enable_cfr))
+ return -EINVAL;
+
+ guard(mutex)(&ar->conf_mutex);
+
+ if (ar->state != ATH11K_STATE_ON)
+ return -ENETDOWN;
+
+ if (enable_cfr > 1)
+ return -EINVAL;
+
+ if (ar->cfr_enabled == enable_cfr)
+ return count;
+
+ ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PER_PEER_CFR_ENABLE,
+ enable_cfr, ar->pdev->pdev_id);
+ if (ret) {
+ ath11k_warn(ar->ab,
+ "Failed to enable/disable per peer cfr %d\n", ret);
+ return ret;
+ }
+
+ ar->cfr_enabled = enable_cfr;
+
+ return count;
+}
+
+static const struct file_operations fops_enable_cfr = {
+ .read = ath11k_read_file_enable_cfr,
+ .write = ath11k_write_file_enable_cfr,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static ssize_t ath11k_write_file_cfr_unassoc(struct file *file,
+ const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct ath11k *ar = file->private_data;
+ struct ath11k_cfr *cfr = &ar->cfr;
+ struct cfr_unassoc_pool_entry *entry;
+ char buf[64] = {};
+ u8 peer_mac[6];
+ u32 cfr_capture_enable;
+ u32 cfr_capture_period;
+ int available_idx = -1;
+ int ret, i;
+
+ simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
+
+ guard(mutex)(&ar->conf_mutex);
+ guard(spinlock_bh)(&cfr->lock);
+
+ if (ar->state != ATH11K_STATE_ON)
+ return -ENETDOWN;
+
+ if (!ar->cfr_enabled) {
+ ath11k_err(ar->ab, "CFR is not enabled on this pdev %d\n",
+ ar->pdev_idx);
+ return -EINVAL;
+ }
+
+ ret = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %u %u",
+ &peer_mac[0], &peer_mac[1], &peer_mac[2], &peer_mac[3],
+ &peer_mac[4], &peer_mac[5], &cfr_capture_enable,
+ &cfr_capture_period);
+
+ if (ret < 1)
+ return -EINVAL;
+
+ if (cfr_capture_enable && ret != 8)
+ return -EINVAL;
+
+ if (!cfr_capture_enable) {
+ for (i = 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) {
+ entry = &cfr->unassoc_pool[i];
+ if (ether_addr_equal(peer_mac, entry->peer_mac)) {
+ memset(entry->peer_mac, 0, ETH_ALEN);
+ entry->is_valid = false;
+ cfr->cfr_enabled_peer_cnt--;
+ }
+ }
+
+ return count;
+ }
+
+ if (cfr->cfr_enabled_peer_cnt >= ATH11K_MAX_CFR_ENABLED_CLIENTS) {
+ ath11k_info(ar->ab, "Max cfr peer threshold reached\n");
+ return count;
+ }
+
+ for (i = 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) {
+ entry = &cfr->unassoc_pool[i];
+
+ if (available_idx < 0 && !entry->is_valid)
+ available_idx = i;
+
+ if (ether_addr_equal(peer_mac, entry->peer_mac)) {
+ ath11k_info(ar->ab,
+ "peer entry already present updating params\n");
+ entry->period = cfr_capture_period;
+ return count;
+ }
+ }
+
+ if (available_idx >= 0) {
+ entry = &cfr->unassoc_pool[available_idx];
+ ether_addr_copy(entry->peer_mac, peer_mac);
+ entry->period = cfr_capture_period;
+ entry->is_valid = true;
+ cfr->cfr_enabled_peer_cnt++;
+ }
+
+ return count;
+}
+
+static ssize_t ath11k_read_file_cfr_unassoc(struct file *file,
+ char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct ath11k *ar = file->private_data;
+ struct ath11k_cfr *cfr = &ar->cfr;
+ struct cfr_unassoc_pool_entry *entry;
+ char buf[512] = {};
+ int len = 0, i;
+
+ spin_lock_bh(&cfr->lock);
+
+ for (i = 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) {
+ entry = &cfr->unassoc_pool[i];
+ if (entry->is_valid)
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "peer: %pM period: %u\n",
+ entry->peer_mac, entry->period);
+ }
+
+ spin_unlock_bh(&cfr->lock);
+
+ return simple_read_from_buffer(ubuf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_configure_cfr_unassoc = {
+ .write = ath11k_write_file_cfr_unassoc,
+ .read = ath11k_read_file_cfr_unassoc,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static void ath11k_cfr_debug_unregister(struct ath11k *ar)
+{
+ debugfs_remove(ar->cfr.enable_cfr);
+ ar->cfr.enable_cfr = NULL;
+ debugfs_remove(ar->cfr.cfr_unassoc);
+ ar->cfr.cfr_unassoc = NULL;
+
+ relay_close(ar->cfr.rfs_cfr_capture);
+ ar->cfr.rfs_cfr_capture = NULL;
+}
+
+static struct dentry *ath11k_cfr_create_buf_file_handler(const char *filename,
+ struct dentry *parent,
+ umode_t mode,
+ struct rchan_buf *buf,
+ int *is_global)
+{
+ struct dentry *buf_file;
+
+ buf_file = debugfs_create_file(filename, mode, parent, buf,
+ &relay_file_operations);
+ *is_global = 1;
+ return buf_file;
+}
+
+static int ath11k_cfr_remove_buf_file_handler(struct dentry *dentry)
+{
+ debugfs_remove(dentry);
+
+ return 0;
+}
+
+static const struct rchan_callbacks rfs_cfr_capture_cb = {
+ .create_buf_file = ath11k_cfr_create_buf_file_handler,
+ .remove_buf_file = ath11k_cfr_remove_buf_file_handler,
+};
+
+static void ath11k_cfr_debug_register(struct ath11k *ar)
+{
+ ar->cfr.rfs_cfr_capture = relay_open("cfr_capture",
+ ar->debug.debugfs_pdev,
+ ar->ab->hw_params.cfr_stream_buf_size,
+ ar->ab->hw_params.cfr_num_stream_bufs,
+ &rfs_cfr_capture_cb, NULL);
+
+ ar->cfr.enable_cfr = debugfs_create_file("enable_cfr", 0600,
+ ar->debug.debugfs_pdev, ar,
+ &fops_enable_cfr);
+
+ ar->cfr.cfr_unassoc = debugfs_create_file("cfr_unassoc", 0600,
+ ar->debug.debugfs_pdev, ar,
+ &fops_configure_cfr_unassoc);
+}
+
+void ath11k_cfr_lut_update_paddr(struct ath11k *ar, dma_addr_t paddr,
+ u32 buf_id)
+{
+ struct ath11k_cfr *cfr = &ar->cfr;
+
+ if (cfr->lut)
+ cfr->lut[buf_id].dbr_address = paddr;
+}
+
+void ath11k_cfr_update_phymode(struct ath11k *ar, enum wmi_phy_mode phymode)
+{
+ struct ath11k_cfr *cfr = &ar->cfr;
+
+ cfr->phymode = phymode;
+}
+
+static void ath11k_cfr_ring_free(struct ath11k *ar)
+{
+ struct ath11k_cfr *cfr = &ar->cfr;
+
+ ath11k_dbring_buf_cleanup(ar, &cfr->rx_ring);
+ ath11k_dbring_srng_cleanup(ar, &cfr->rx_ring);
+}
+
+static int ath11k_cfr_ring_alloc(struct ath11k *ar,
+ struct ath11k_dbring_cap *db_cap)
+{
+ struct ath11k_cfr *cfr = &ar->cfr;
+ int ret;
+
+ ret = ath11k_dbring_srng_setup(ar, &cfr->rx_ring,
+ ATH11K_CFR_NUM_RING_ENTRIES,
+ db_cap->min_elem);
+ if (ret) {
+ ath11k_warn(ar->ab, "failed to setup db ring: %d\n", ret);
+ return ret;
+ }
+
+ ath11k_dbring_set_cfg(ar, &cfr->rx_ring,
+ ATH11K_CFR_NUM_RESP_PER_EVENT,
+ ATH11K_CFR_EVENT_TIMEOUT_MS,
+ ath11k_cfr_process_data);
+
+ ret = ath11k_dbring_buf_setup(ar, &cfr->rx_ring, db_cap);
+ if (ret) {
+ ath11k_warn(ar->ab, "failed to setup db ring buffer: %d\n", ret);
+ goto srng_cleanup;
+ }
+
+ ret = ath11k_dbring_wmi_cfg_setup(ar, &cfr->rx_ring, WMI_DIRECT_BUF_CFR);
+ if (ret) {
+ ath11k_warn(ar->ab, "failed to setup db ring cfg: %d\n", ret);
+ goto buffer_cleanup;
+ }
+
+ return 0;
+
+buffer_cleanup:
+ ath11k_dbring_buf_cleanup(ar, &cfr->rx_ring);
+srng_cleanup:
+ ath11k_dbring_srng_cleanup(ar, &cfr->rx_ring);
+ return ret;
+}
+
+void ath11k_cfr_deinit(struct ath11k_base *ab)
+{
+ struct ath11k_cfr *cfr;
+ struct ath11k *ar;
+ int i;
+
+ if (!test_bit(WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT, ab->wmi_ab.svc_map) ||
+ !ab->hw_params.cfr_support)
+ return;
+
+ for (i = 0; i < ab->num_radios; i++) {
+ ar = ab->pdevs[i].ar;
+ cfr = &ar->cfr;
+
+ if (!cfr->enabled)
+ continue;
+
+ ath11k_cfr_debug_unregister(ar);
+ ath11k_cfr_ring_free(ar);
+
+ spin_lock_bh(&cfr->lut_lock);
+ kfree(cfr->lut);
+ cfr->lut = NULL;
+ cfr->enabled = false;
+ spin_unlock_bh(&cfr->lut_lock);
+ }
+}
+
+int ath11k_cfr_init(struct ath11k_base *ab)
+{
+ struct ath11k_dbring_cap db_cap;
+ struct ath11k_cfr *cfr;
+ u32 num_lut_entries;
+ struct ath11k *ar;
+ int i, ret;
+
+ if (!test_bit(WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT, ab->wmi_ab.svc_map) ||
+ !ab->hw_params.cfr_support)
+ return 0;
+
+ for (i = 0; i < ab->num_radios; i++) {
+ ar = ab->pdevs[i].ar;
+ cfr = &ar->cfr;
+
+ ret = ath11k_dbring_get_cap(ar->ab, ar->pdev_idx,
+ WMI_DIRECT_BUF_CFR, &db_cap);
+ if (ret)
+ continue;
+
+ idr_init(&cfr->rx_ring.bufs_idr);
+ spin_lock_init(&cfr->rx_ring.idr_lock);
+ spin_lock_init(&cfr->lock);
+ spin_lock_init(&cfr->lut_lock);
+
+ num_lut_entries = min_t(u32, CFR_MAX_LUT_ENTRIES, db_cap.min_elem);
+ cfr->lut = kcalloc(num_lut_entries, sizeof(*cfr->lut),
+ GFP_KERNEL);
+ if (!cfr->lut) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ ret = ath11k_cfr_ring_alloc(ar, &db_cap);
+ if (ret) {
+ ath11k_warn(ab, "failed to init cfr ring for pdev %d: %d\n",
+ i, ret);
+ spin_lock_bh(&cfr->lut_lock);
+ kfree(cfr->lut);
+ cfr->lut = NULL;
+ cfr->enabled = false;
+ spin_unlock_bh(&cfr->lut_lock);
+ goto err;
+ }
+
+ cfr->lut_num = num_lut_entries;
+ cfr->enabled = true;
+
+ ath11k_cfr_debug_register(ar);
+ }
+
+ return 0;
+
+err:
+ for (i = i - 1; i >= 0; i--) {
+ ar = ab->pdevs[i].ar;
+ cfr = &ar->cfr;
+
+ if (!cfr->enabled)
+ continue;
+
+ ath11k_cfr_debug_unregister(ar);
+ ath11k_cfr_ring_free(ar);
+
+ spin_lock_bh(&cfr->lut_lock);
+ kfree(cfr->lut);
+ cfr->lut = NULL;
+ cfr->enabled = false;
+ spin_unlock_bh(&cfr->lut_lock);
+ }
+ return ret;
+}
diff --git a/drivers/net/wireless/ath/ath11k/cfr.h b/drivers/net/wireless/ath/ath11k/cfr.h
new file mode 100644
index 000000000000..94fcb706f2ef
--- /dev/null
+++ b/drivers/net/wireless/ath/ath11k/cfr.h
@@ -0,0 +1,308 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef ATH11K_CFR_H
+#define ATH11K_CFR_H
+
+#include "dbring.h"
+#include "wmi.h"
+
+#define ATH11K_CFR_NUM_RESP_PER_EVENT 1
+#define ATH11K_CFR_EVENT_TIMEOUT_MS 1
+#define ATH11K_CFR_NUM_RING_ENTRIES 1
+
+#define ATH11K_MAX_CFR_ENABLED_CLIENTS 10
+#define CFR_MAX_LUT_ENTRIES 136
+
+#define HOST_MAX_CHAINS 8
+
+enum ath11k_cfr_correlate_event_type {
+ ATH11K_CORRELATE_DBR_EVENT,
+ ATH11K_CORRELATE_TX_EVENT,
+};
+
+struct ath11k_sta;
+struct ath11k_per_peer_cfr_capture;
+
+#define ATH11K_CFR_START_MAGIC 0xDEADBEAF
+#define ATH11K_CFR_END_MAGIC 0xBEAFDEAD
+
+#define VENDOR_QCA 0x8cfdf0
+#define PLATFORM_TYPE_ARM 2
+
+enum ath11k_cfr_meta_version {
+ ATH11K_CFR_META_VERSION_NONE,
+ ATH11K_CFR_META_VERSION_1,
+ ATH11K_CFR_META_VERSION_2,
+ ATH11K_CFR_META_VERSION_3,
+ ATH11K_CFR_META_VERSION_4,
+ ATH11K_CFR_META_VERSION_MAX = 0xFF,
+};
+
+enum ath11k_cfr_data_version {
+ ATH11K_CFR_DATA_VERSION_NONE,
+ ATH11K_CFR_DATA_VERSION_1,
+ ATH11K_CFR_DATA_VERSION_MAX = 0xFF,
+};
+
+enum ath11k_cfr_capture_ack_mode {
+ ATH11K_CFR_CAPTURE_LEGACY_ACK,
+ ATH11K_CFR_CAPTURE_DUP_LEGACY_ACK,
+ ATH11K_CFR_CAPTURE_HT_ACK,
+ ATH11K_CFR_CAPTURE_VHT_ACK,
+
+ /*Always keep this at last*/
+ ATH11K_CFR_CAPTURE_INVALID_ACK
+};
+
+enum ath11k_cfr_correlate_status {
+ ATH11K_CORRELATE_STATUS_RELEASE,
+ ATH11K_CORRELATE_STATUS_HOLD,
+ ATH11K_CORRELATE_STATUS_ERR,
+};
+
+enum ath11k_cfr_preamble_type {
+ ATH11K_CFR_PREAMBLE_TYPE_LEGACY,
+ ATH11K_CFR_PREAMBLE_TYPE_HT,
+ ATH11K_CFR_PREAMBLE_TYPE_VHT,
+};
+
+struct ath11k_cfr_peer_tx_param {
+ u32 capture_method;
+ u32 vdev_id;
+ u8 peer_mac_addr[ETH_ALEN];
+ u32 primary_20mhz_chan;
+ u32 bandwidth;
+ u32 phy_mode;
+ u32 band_center_freq1;
+ u32 band_center_freq2;
+ u32 spatial_streams;
+ u32 correlation_info_1;
+ u32 correlation_info_2;
+ u32 status;
+ u32 timestamp_us;
+ u32 counter;
+ u32 chain_rssi[WMI_MAX_CHAINS];
+ u16 chain_phase[WMI_MAX_CHAINS];
+ u32 cfo_measurement;
+ u8 agc_gain[HOST_MAX_CHAINS];
+ u32 rx_start_ts;
+};
+
+struct cfr_metadata {
+ u8 peer_addr[ETH_ALEN];
+ u8 status;
+ u8 capture_bw;
+ u8 channel_bw;
+ u8 phy_mode;
+ u16 prim20_chan;
+ u16 center_freq1;
+ u16 center_freq2;
+ u8 capture_mode;
+ u8 capture_type;
+ u8 sts_count;
+ u8 num_rx_chain;
+ u32 timestamp;
+ u32 length;
+ u32 chain_rssi[HOST_MAX_CHAINS];
+ u16 chain_phase[HOST_MAX_CHAINS];
+ u32 cfo_measurement;
+ u8 agc_gain[HOST_MAX_CHAINS];
+ u32 rx_start_ts;
+} __packed;
+
+struct ath11k_csi_cfr_header {
+ u32 start_magic_num;
+ u32 vendorid;
+ u8 cfr_metadata_version;
+ u8 cfr_data_version;
+ u8 chip_type;
+ u8 platform_type;
+ u32 cfr_metadata_len;
+ struct cfr_metadata meta_data;
+} __packed;
+
+#define TONES_IN_20MHZ 256
+#define TONES_IN_40MHZ 512
+#define TONES_IN_80MHZ 1024
+#define TONES_IN_160MHZ 2048 /* 160 MHz isn't supported yet */
+#define TONES_INVALID 0
+
+#define CFIR_DMA_HDR_INFO0_TAG GENMASK(7, 0)
+#define CFIR_DMA_HDR_INFO0_LEN GENMASK(13, 8)
+
+#define CFIR_DMA_HDR_INFO1_UPLOAD_DONE GENMASK(0, 0)
+#define CFIR_DMA_HDR_INFO1_CAPTURE_TYPE GENMASK(3, 1)
+#define CFIR_DMA_HDR_INFO1_PREAMBLE_TYPE GENMASK(5, 4)
+#define CFIR_DMA_HDR_INFO1_NSS GENMASK(8, 6)
+#define CFIR_DMA_HDR_INFO1_NUM_CHAINS GENMASK(11, 9)
+#define CFIR_DMA_HDR_INFO1_UPLOAD_PKT_BW GENMASK(14, 12)
+#define CFIR_DMA_HDR_INFO1_SW_PEER_ID_VALID GENMASK(15, 15)
+
+struct ath11k_cfr_dma_hdr {
+ u16 info0;
+ u16 info1;
+ u16 sw_peer_id;
+ u16 phy_ppdu_id;
+};
+
+struct ath11k_look_up_table {
+ bool dbr_recv;
+ bool tx_recv;
+ u8 *data;
+ u32 data_len;
+ u16 dbr_ppdu_id;
+ u16 tx_ppdu_id;
+ dma_addr_t dbr_address;
+ struct ath11k_csi_cfr_header header;
+ struct ath11k_cfr_dma_hdr hdr;
+ u64 txrx_tstamp;
+ u64 dbr_tstamp;
+ u32 header_length;
+ u32 payload_length;
+ struct ath11k_dbring_element *buff;
+};
+
+struct cfr_unassoc_pool_entry {
+ u8 peer_mac[ETH_ALEN];
+ u32 period;
+ bool is_valid;
+};
+
+struct ath11k_cfr {
+ struct ath11k_dbring rx_ring;
+ /* Protects cfr data */
+ spinlock_t lock;
+ /* Protect for lut entries */
+ spinlock_t lut_lock;
+ struct ath11k_look_up_table *lut;
+ struct dentry *enable_cfr;
+ struct dentry *cfr_unassoc;
+ struct rchan *rfs_cfr_capture;
+ u8 cfr_enabled_peer_cnt;
+ u32 lut_num;
+ u64 tx_evt_cnt;
+ u64 dbr_evt_cnt;
+ u64 release_cnt;
+ u64 tx_peer_status_cfr_fail;
+ u64 tx_evt_status_cfr_fail;
+ u64 tx_dbr_lookup_fail;
+ u64 last_success_tstamp;
+ u64 flush_dbr_cnt;
+ u64 clear_txrx_event;
+ u64 cfr_dma_aborts;
+ bool enabled;
+ enum wmi_phy_mode phymode;
+ struct cfr_unassoc_pool_entry unassoc_pool[ATH11K_MAX_CFR_ENABLED_CLIENTS];
+};
+
+enum ath11k_cfr_capture_method {
+ ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME,
+ ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE,
+ ATH11K_CFR_CAPTURE_METHOD_PROBE_RESP,
+ ATH11K_CFR_CAPTURE_METHOD_MAX,
+};
+
+enum ath11k_cfr_capture_bw {
+ ATH11K_CFR_CAPTURE_BW_20,
+ ATH11K_CFR_CAPTURE_BW_40,
+ ATH11K_CFR_CAPTURE_BW_80,
+ ATH11K_CFR_CAPTURE_BW_MAX,
+};
+
+#ifdef CONFIG_ATH11K_CFR
+int ath11k_cfr_init(struct ath11k_base *ab);
+void ath11k_cfr_deinit(struct ath11k_base *ab);
+void ath11k_cfr_lut_update_paddr(struct ath11k *ar, dma_addr_t paddr,
+ u32 buf_id);
+void ath11k_cfr_decrement_peer_count(struct ath11k *ar,
+ struct ath11k_sta *arsta);
+void ath11k_cfr_update_unassoc_pool_entry(struct ath11k *ar,
+ const u8 *peer_mac);
+bool ath11k_cfr_peer_is_in_cfr_unassoc_pool(struct ath11k *ar,
+ const u8 *peer_mac);
+void ath11k_cfr_update_unassoc_pool(struct ath11k *ar,
+ struct ath11k_per_peer_cfr_capture *params,
+ u8 *peer_mac);
+int ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k *ar,
+ struct ath11k_sta *arsta,
+ struct ath11k_per_peer_cfr_capture *params,
+ const u8 *peer_mac);
+struct ath11k_dbring *ath11k_cfr_get_dbring(struct ath11k *ar);
+void ath11k_cfr_release_lut_entry(struct ath11k_look_up_table *lut);
+int ath11k_process_cfr_capture_event(struct ath11k_base *ab,
+ struct ath11k_cfr_peer_tx_param *params);
+void ath11k_cfr_update_phymode(struct ath11k *ar, enum wmi_phy_mode phymode);
+#else
+static inline void ath11k_cfr_update_phymode(struct ath11k *ar,
+ enum wmi_phy_mode phymode)
+{
+}
+
+static inline int ath11k_cfr_init(struct ath11k_base *ab)
+{
+ return 0;
+}
+
+static inline void ath11k_cfr_deinit(struct ath11k_base *ab)
+{
+}
+
+static inline void ath11k_cfr_lut_update_paddr(struct ath11k *ar,
+ dma_addr_t paddr, u32 buf_id)
+{
+}
+
+static inline void ath11k_cfr_decrement_peer_count(struct ath11k *ar,
+ struct ath11k_sta *arsta)
+{
+}
+
+static inline void ath11k_cfr_update_unassoc_pool_entry(struct ath11k *ar,
+ const u8 *peer_mac)
+{
+}
+
+static inline bool
+ath11k_cfr_peer_is_in_cfr_unassoc_pool(struct ath11k *ar, const u8 *peer_mac)
+{
+ return false;
+}
+
+static inline void
+ath11k_cfr_update_unassoc_pool(struct ath11k *ar,
+ struct ath11k_per_peer_cfr_capture *params,
+ u8 *peer_mac)
+{
+}
+
+static inline int
+ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k *ar,
+ struct ath11k_sta *arsta,
+ struct ath11k_per_peer_cfr_capture *params,
+ const u8 *peer_mac)
+{
+ return 0;
+}
+
+static inline void ath11k_cfr_release_lut_entry(struct ath11k_look_up_table *lut)
+{
+}
+
+static inline
+struct ath11k_dbring *ath11k_cfr_get_dbring(struct ath11k *ar)
+{
+ return NULL;
+}
+
+static inline
+int ath11k_process_cfr_capture_event(struct ath11k_base *ab,
+ struct ath11k_cfr_peer_tx_param *params)
+{
+ return 0;
+}
+#endif /* CONFIG_ATH11K_CFR */
+#endif /* ATH11K_CFR_H */
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index 812686173ac8..3f6f4db5b7ee 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
@@ -100,7 +99,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = false,
.fix_l1ss = true,
.credit_flow = false,
- .max_tx_ring = DP_TCL_NUM_RING_MAX,
.hal_params = &ath11k_hw_hal_params_ipq8074,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = true,
@@ -126,6 +124,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.smp2p_wow_exit = false,
.support_dual_stations = false,
.pdev_suspend = false,
+ .cfr_support = true,
+ .cfr_num_stream_bufs = 255,
+ .cfr_stream_buf_size = 8200,
},
{
.hw_rev = ATH11K_HW_IPQ6018_HW10,
@@ -184,7 +185,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = false,
.fix_l1ss = true,
.credit_flow = false,
- .max_tx_ring = DP_TCL_NUM_RING_MAX,
.hal_params = &ath11k_hw_hal_params_ipq8074,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = true,
@@ -211,6 +211,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.support_fw_mac_sequence = false,
.support_dual_stations = false,
.pdev_suspend = false,
+ .cfr_support = false,
+ .cfr_num_stream_bufs = 0,
+ .cfr_stream_buf_size = 0,
},
{
.name = "qca6390 hw2.0",
@@ -271,7 +274,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = false,
.fix_l1ss = true,
.credit_flow = true,
- .max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
.hal_params = &ath11k_hw_hal_params_qca6390,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
@@ -301,6 +303,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.support_fw_mac_sequence = true,
.support_dual_stations = true,
.pdev_suspend = false,
+ .cfr_support = false,
+ .cfr_num_stream_bufs = 0,
+ .cfr_stream_buf_size = 0,
},
{
.name = "qcn9074 hw1.0",
@@ -358,7 +363,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = false,
.fix_l1ss = true,
.credit_flow = false,
- .max_tx_ring = DP_TCL_NUM_RING_MAX,
.hal_params = &ath11k_hw_hal_params_ipq8074,
.supports_dynamic_smps_6ghz = true,
.alloc_cacheable_memory = true,
@@ -385,6 +389,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.support_fw_mac_sequence = false,
.support_dual_stations = false,
.pdev_suspend = false,
+ .cfr_support = false,
+ .cfr_num_stream_bufs = 0,
+ .cfr_stream_buf_size = 0,
},
{
.name = "wcn6855 hw2.0",
@@ -445,7 +452,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = true,
.fix_l1ss = false,
.credit_flow = true,
- .max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
.hal_params = &ath11k_hw_hal_params_qca6390,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
@@ -475,6 +481,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.support_fw_mac_sequence = true,
.support_dual_stations = true,
.pdev_suspend = false,
+ .cfr_support = false,
+ .cfr_num_stream_bufs = 0,
+ .cfr_stream_buf_size = 0,
},
{
.name = "wcn6855 hw2.1",
@@ -533,7 +542,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = true,
.fix_l1ss = false,
.credit_flow = true,
- .max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
.hal_params = &ath11k_hw_hal_params_qca6390,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
@@ -563,6 +571,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.support_fw_mac_sequence = true,
.support_dual_stations = true,
.pdev_suspend = false,
+ .cfr_support = true,
+ .cfr_num_stream_bufs = 255,
+ .cfr_stream_buf_size = 8200,
},
{
.name = "wcn6750 hw1.0",
@@ -619,7 +630,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = true,
.fix_l1ss = false,
.credit_flow = true,
- .max_tx_ring = DP_TCL_NUM_RING_MAX,
.hal_params = &ath11k_hw_hal_params_wcn6750,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
@@ -646,6 +656,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.support_fw_mac_sequence = true,
.support_dual_stations = false,
.pdev_suspend = true,
+ .cfr_support = false,
+ .cfr_num_stream_bufs = 0,
+ .cfr_stream_buf_size = 0,
},
{
.hw_rev = ATH11K_HW_IPQ5018_HW10,
@@ -662,7 +675,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074,
.ring_mask = &ath11k_hw_ring_mask_ipq8074,
.credit_flow = false,
- .max_tx_ring = 1,
.spectral = {
.fft_sz = 2,
.fft_pad_sz = 0,
@@ -698,7 +710,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = false,
.idle_ps = false,
.supports_suspend = false,
- .hal_params = &ath11k_hw_hal_params_ipq8074,
+ .hal_params = &ath11k_hw_hal_params_ipq5018,
.single_pdev_only = false,
.coldboot_cal_mm = true,
.coldboot_cal_ftm = true,
@@ -729,6 +741,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.support_fw_mac_sequence = false,
.support_dual_stations = false,
.pdev_suspend = false,
+ .cfr_support = false,
+ .cfr_num_stream_bufs = 0,
+ .cfr_stream_buf_size = 0,
},
{
.name = "qca2066 hw2.1",
@@ -789,7 +804,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = true,
.fix_l1ss = false,
.credit_flow = true,
- .max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
.hal_params = &ath11k_hw_hal_params_qca6390,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
@@ -818,6 +832,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.smp2p_wow_exit = false,
.support_fw_mac_sequence = true,
.support_dual_stations = true,
+ .cfr_support = false,
+ .cfr_num_stream_bufs = 0,
+ .cfr_stream_buf_size = 0,
},
{
.name = "qca6698aq hw2.1",
@@ -876,7 +893,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = true,
.fix_l1ss = false,
.credit_flow = true,
- .max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
.hal_params = &ath11k_hw_hal_params_qca6390,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
@@ -906,6 +922,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.support_fw_mac_sequence = true,
.support_dual_stations = true,
.pdev_suspend = false,
+ .cfr_support = true,
+ .cfr_num_stream_bufs = 255,
+ .cfr_stream_buf_size = 8200,
},
};
@@ -994,9 +1013,64 @@ static const struct dmi_system_id ath11k_pm_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "21F9"),
},
},
+ {
+ .driver_data = (void *)ATH11K_PM_WOW,
+ .matches = { /* Z13 G1 */
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21D2"),
+ },
+ },
+ {
+ .driver_data = (void *)ATH11K_PM_WOW,
+ .matches = { /* Z13 G1 */
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21D3"),
+ },
+ },
+ {
+ .driver_data = (void *)ATH11K_PM_WOW,
+ .matches = { /* Z16 G1 */
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21D4"),
+ },
+ },
+ {
+ .driver_data = (void *)ATH11K_PM_WOW,
+ .matches = { /* Z16 G1 */
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21D5"),
+ },
+ },
{}
};
+static const struct __ath11k_core_usecase_firmware_table {
+ u32 hw_rev;
+ const char *compatible;
+ const char *firmware_name;
+} ath11k_core_usecase_firmware_table[] = {
+ { ATH11K_HW_WCN6855_HW21, "qcom,lemans-evk", "nfa765"},
+ { ATH11K_HW_WCN6855_HW21, "qcom,monaco-evk", "nfa765"},
+ { ATH11K_HW_WCN6855_HW21, "qcom,hamoa-iot-evk", "nfa765"},
+ { /* Sentinel */ }
+};
+
+const char *ath11k_core_get_usecase_firmware(struct ath11k_base *ab)
+{
+ const struct __ath11k_core_usecase_firmware_table *entry = NULL;
+
+ entry = ath11k_core_usecase_firmware_table;
+ while (entry->compatible) {
+ if (ab->hw_rev == entry->hw_rev &&
+ of_machine_is_compatible(entry->compatible))
+ return entry->firmware_name;
+ entry++;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL(ath11k_core_get_usecase_firmware);
+
void ath11k_fw_stats_pdevs_free(struct list_head *head)
{
struct ath11k_fw_stats_pdev *i, *tmp;
@@ -1987,8 +2061,16 @@ static int ath11k_core_pdev_create(struct ath11k_base *ab)
goto err_thermal_unregister;
}
+ ret = ath11k_cfr_init(ab);
+ if (ret) {
+ ath11k_err(ab, "failed to init cfr %d\n", ret);
+ goto err_spectral_unregister;
+ }
+
return 0;
+err_spectral_unregister:
+ ath11k_spectral_deinit(ab);
err_thermal_unregister:
ath11k_thermal_unregister(ab);
err_mac_unregister:
@@ -2038,6 +2120,7 @@ static void ath11k_core_pdev_suspend_target(struct ath11k_base *ab)
static void ath11k_core_pdev_destroy(struct ath11k_base *ab)
{
+ ath11k_cfr_deinit(ab);
ath11k_spectral_deinit(ab);
ath11k_thermal_unregister(ab);
ath11k_mac_unregister(ab);
@@ -2250,6 +2333,7 @@ static int ath11k_core_reconfigure_on_crash(struct ath11k_base *ab)
mutex_lock(&ab->core_lock);
ath11k_thermal_unregister(ab);
ath11k_dp_pdev_free(ab);
+ ath11k_cfr_deinit(ab);
ath11k_spectral_deinit(ab);
ath11k_ce_cleanup_pipes(ab);
ath11k_wmi_detach(ab);
diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index e8780b05ce11..a0d725923ef2 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH11K_CORE_H
@@ -35,6 +35,7 @@
#include "wow.h"
#include "fw.h"
#include "coredump.h"
+#include "cfr.h"
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@@ -531,6 +532,13 @@ struct ath11k_per_ppdu_tx_stats {
DECLARE_EWMA(avg_rssi, 10, 8)
+struct ath11k_per_peer_cfr_capture {
+ enum ath11k_cfr_capture_method cfr_method;
+ enum ath11k_cfr_capture_bw cfr_bw;
+ u32 cfr_enable;
+ u32 cfr_period;
+};
+
struct ath11k_sta {
struct ath11k_vif *arvif;
@@ -571,6 +579,10 @@ struct ath11k_sta {
bool peer_current_ps_valid;
u32 bw_prev;
+
+#ifdef CONFIG_ATH11K_CFR
+ struct ath11k_per_peer_cfr_capture cfr_capture;
+#endif
};
#define ATH11K_MIN_5G_FREQ 4150
@@ -795,6 +807,11 @@ struct ath11k {
bool ps_state_enable;
bool ps_timekeeper_enable;
s8 max_allowed_tx_power;
+
+#ifdef CONFIG_ATH11K_CFR
+ struct ath11k_cfr cfr;
+#endif
+ bool cfr_enabled;
};
struct ath11k_band_cap {
@@ -1275,6 +1292,7 @@ bool ath11k_core_coldboot_cal_support(struct ath11k_base *ab);
const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab,
const char *filename);
+const char *ath11k_core_get_usecase_firmware(struct ath11k_base *ab);
static inline const char *ath11k_scan_state_str(enum ath11k_scan_state state)
{
@@ -1329,6 +1347,9 @@ static inline void ath11k_core_create_firmware_path(struct ath11k_base *ab,
of_property_read_string(ab->dev->of_node, "firmware-name", &fw_name);
+ if (!fw_name)
+ fw_name = ath11k_core_get_usecase_firmware(ab);
+
if (fw_name && strncmp(filename, "board", 5))
snprintf(buf, buf_len, "%s/%s/%s/%s", ATH11K_FW_DIR,
ab->hw_params.fw.dir, fw_name, filename);
diff --git a/drivers/net/wireless/ath/ath11k/dbring.c b/drivers/net/wireless/ath/ath11k/dbring.c
index 520d8b8662a2..d6994ce6ebff 100644
--- a/drivers/net/wireless/ath/ath11k/dbring.c
+++ b/drivers/net/wireless/ath/ath11k/dbring.c
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
@@ -37,10 +36,10 @@ static void ath11k_dbring_fill_magic_value(struct ath11k *ar,
memset32(buffer, ATH11K_DB_MAGIC_VALUE, size);
}
-static int ath11k_dbring_bufs_replenish(struct ath11k *ar,
- struct ath11k_dbring *ring,
- struct ath11k_dbring_element *buff,
- enum wmi_direct_buffer_module id)
+int ath11k_dbring_bufs_replenish(struct ath11k *ar,
+ struct ath11k_dbring *ring,
+ struct ath11k_dbring_element *buff,
+ enum wmi_direct_buffer_module id)
{
struct ath11k_base *ab = ar->ab;
struct hal_srng *srng;
@@ -80,6 +79,9 @@ static int ath11k_dbring_bufs_replenish(struct ath11k *ar,
goto err_idr_remove;
}
+ if (id == WMI_DIRECT_BUF_CFR)
+ ath11k_cfr_lut_update_paddr(ar, paddr, buf_id);
+
buff->paddr = paddr;
cookie = FIELD_PREP(DP_RXDMA_BUF_COOKIE_PDEV_ID, ar->pdev_idx) |
@@ -155,12 +157,11 @@ int ath11k_dbring_wmi_cfg_setup(struct ath11k *ar,
enum wmi_direct_buffer_module id)
{
struct ath11k_wmi_pdev_dma_ring_cfg_req_cmd param = {};
- int ret;
+ int ret, i;
if (id >= WMI_DIRECT_BUF_MAX)
return -EINVAL;
- param.pdev_id = DP_SW2HW_MACID(ring->pdev_id);
param.module_id = id;
param.base_paddr_lo = lower_32_bits(ring->refill_srng.paddr);
param.base_paddr_hi = upper_32_bits(ring->refill_srng.paddr);
@@ -173,10 +174,23 @@ int ath11k_dbring_wmi_cfg_setup(struct ath11k *ar,
param.num_resp_per_event = ring->num_resp_per_event;
param.event_timeout_ms = ring->event_timeout_ms;
- ret = ath11k_wmi_pdev_dma_ring_cfg(ar, &param);
- if (ret) {
- ath11k_warn(ar->ab, "failed to setup db ring cfg\n");
- return ret;
+ /* For single pdev, 2GHz and 5GHz use one DBR. */
+ if (ar->ab->hw_params.single_pdev_only) {
+ for (i = 0; i < ar->ab->target_pdev_count; i++) {
+ param.pdev_id = ar->ab->target_pdev_ids[i].pdev_id;
+ ret = ath11k_wmi_pdev_dma_ring_cfg(ar, &param);
+ if (ret) {
+ ath11k_warn(ar->ab, "failed to setup db ring cfg\n");
+ return ret;
+ }
+ }
+ } else {
+ param.pdev_id = DP_SW2HW_MACID(ring->pdev_id);
+ ret = ath11k_wmi_pdev_dma_ring_cfg(ar, &param);
+ if (ret) {
+ ath11k_warn(ar->ab, "failed to setup db ring cfg\n");
+ return ret;
+ }
}
return 0;
@@ -281,10 +295,15 @@ int ath11k_dbring_buffer_release_event(struct ath11k_base *ab,
int size;
dma_addr_t paddr;
int ret = 0;
+ int status;
pdev_idx = ev->fixed.pdev_id;
module_id = ev->fixed.module_id;
+ if (ab->hw_params.single_pdev_only &&
+ pdev_idx < ab->target_pdev_count)
+ pdev_idx = 0;
+
if (pdev_idx >= ab->num_radios) {
ath11k_warn(ab, "Invalid pdev id %d\n", pdev_idx);
return -EINVAL;
@@ -310,6 +329,9 @@ int ath11k_dbring_buffer_release_event(struct ath11k_base *ab,
case WMI_DIRECT_BUF_SPECTRAL:
ring = ath11k_spectral_get_dbring(ar);
break;
+ case WMI_DIRECT_BUF_CFR:
+ ring = ath11k_cfr_get_dbring(ar);
+ break;
default:
ring = NULL;
ath11k_warn(ab, "Recv dma buffer release ev on unsupp module %d\n",
@@ -360,8 +382,12 @@ int ath11k_dbring_buffer_release_event(struct ath11k_base *ab,
handler_data.data = PTR_ALIGN(vaddr_unalign,
ring->buf_align);
handler_data.data_sz = ring->buf_sz;
+ handler_data.buff = buff;
+ handler_data.buf_id = buf_id;
- ring->handler(ar, &handler_data);
+ status = ring->handler(ar, &handler_data);
+ if (status == ATH11K_CORRELATE_STATUS_HOLD)
+ continue;
}
buff->paddr = 0;
diff --git a/drivers/net/wireless/ath/ath11k/dbring.h b/drivers/net/wireless/ath/ath11k/dbring.h
index 2f93b78a50df..e5f244dfa963 100644
--- a/drivers/net/wireless/ath/ath11k/dbring.h
+++ b/drivers/net/wireless/ath/ath11k/dbring.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH11K_DBRING_H
@@ -21,6 +21,8 @@ struct ath11k_dbring_data {
void *data;
u32 data_sz;
struct wmi_dma_buf_release_meta_data meta;
+ struct ath11k_dbring_element *buff;
+ u32 buf_id;
};
struct ath11k_dbring_buf_release_event {
@@ -61,6 +63,10 @@ int ath11k_dbring_set_cfg(struct ath11k *ar,
u32 event_timeout_ms,
int (*handler)(struct ath11k *,
struct ath11k_dbring_data *));
+int ath11k_dbring_bufs_replenish(struct ath11k *ar,
+ struct ath11k_dbring *ring,
+ struct ath11k_dbring_element *buff,
+ enum wmi_direct_buffer_module id);
int ath11k_dbring_wmi_cfg_setup(struct ath11k *ar,
struct ath11k_dbring *ring,
enum wmi_direct_buffer_module id);
diff --git a/drivers/net/wireless/ath/ath11k/debug.h b/drivers/net/wireless/ath/ath11k/debug.h
index cc8934d15697..aaa0034527a5 100644
--- a/drivers/net/wireless/ath/ath11k/debug.h
+++ b/drivers/net/wireless/ath/ath11k/debug.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef _ATH11K_DEBUG_H_
@@ -27,6 +27,8 @@ enum ath11k_debug_mask {
ATH11K_DBG_DP_TX = 0x00002000,
ATH11K_DBG_DP_RX = 0x00004000,
ATH11K_DBG_CE = 0x00008000,
+ ATH11K_DBG_CFR = 0x00010000,
+ ATH11K_DBG_CFR_DUMP = 0x00020000,
};
static inline const char *ath11k_dbg_str(enum ath11k_debug_mask mask)
@@ -64,6 +66,10 @@ static inline const char *ath11k_dbg_str(enum ath11k_debug_mask mask)
return "dp_rx";
case ATH11K_DBG_CE:
return "ce";
+ case ATH11K_DBG_CFR:
+ return "cfr";
+ case ATH11K_DBG_CFR_DUMP:
+ return "cfr_dump";
/* no default handler to allow compiler to check that the
* enum is fully handled
diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c
index 977f945b6e66..50f344803e8f 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs.c
+++ b/drivers/net/wireless/ath/ath11k/debugfs.c
@@ -707,7 +707,7 @@ static ssize_t ath11k_debugfs_dump_soc_dp_stats(struct file *file,
len += scnprintf(buf + len, size - len, "\nSOC TX STATS:\n");
len += scnprintf(buf + len, size - len, "\nTCL Ring Full Failures:\n");
- for (i = 0; i < ab->hw_params.max_tx_ring; i++)
+ for (i = 0; i < ab->hw_params.hal_params->num_tx_rings; i++)
len += scnprintf(buf + len, size - len, "ring%d: %u\n",
i, soc_stats->tx_err.desc_na[i]);
diff --git a/drivers/net/wireless/ath/ath11k/debugfs_sta.c b/drivers/net/wireless/ath/ath11k/debugfs_sta.c
index d89d0f28d890..621a8a8df4b8 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs_sta.c
+++ b/drivers/net/wireless/ath/ath11k/debugfs_sta.c
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
@@ -240,6 +239,140 @@ static const struct file_operations fops_tx_stats = {
.llseek = default_llseek,
};
+#ifdef CONFIG_ATH11K_CFR
+static ssize_t ath11k_dbg_sta_write_cfr_capture(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_sta *sta = file->private_data;
+ struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
+ struct ath11k *ar = arsta->arvif->ar;
+ struct ath11k_cfr *cfr = &ar->cfr;
+ struct wmi_peer_cfr_capture_conf_arg arg;
+ u32 cfr_capture_enable = 0, cfr_capture_bw = 0;
+ u32 cfr_capture_method = 0, cfr_capture_period = 0;
+ char buf[64] = {};
+ int ret;
+
+ simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
+
+ guard(mutex)(&ar->conf_mutex);
+
+ if (ar->state != ATH11K_STATE_ON)
+ return -ENETDOWN;
+
+ if (!ar->cfr_enabled)
+ return -EINVAL;
+
+ ret = sscanf(buf, "%u %u %u %u", &cfr_capture_enable, &cfr_capture_bw,
+ &cfr_capture_period, &cfr_capture_method);
+
+ if (ret < 1 || (cfr_capture_enable && ret != 4))
+ return -EINVAL;
+
+ if (cfr_capture_enable == arsta->cfr_capture.cfr_enable &&
+ (cfr_capture_period &&
+ cfr_capture_period == arsta->cfr_capture.cfr_period) &&
+ cfr_capture_bw == arsta->cfr_capture.cfr_bw &&
+ cfr_capture_method == arsta->cfr_capture.cfr_method)
+ return count;
+
+ if (!cfr_capture_enable &&
+ cfr_capture_enable == arsta->cfr_capture.cfr_enable)
+ return count;
+
+ if (cfr_capture_enable > WMI_PEER_CFR_CAPTURE_ENABLE ||
+ cfr_capture_bw > WMI_PEER_CFR_CAPTURE_BW_80 ||
+ cfr_capture_method > ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE ||
+ cfr_capture_period > WMI_PEER_CFR_PERIODICITY_MAX)
+ return -EINVAL;
+
+ /* Target expects cfr period in multiple of 10 */
+ if (cfr_capture_period % 10) {
+ ath11k_err(ar->ab, "periodicity should be 10x\n");
+ return -EINVAL;
+ }
+
+ if (ar->cfr.cfr_enabled_peer_cnt >= ATH11K_MAX_CFR_ENABLED_CLIENTS &&
+ !arsta->cfr_capture.cfr_enable) {
+ ath11k_err(ar->ab, "CFR enable peer threshold reached %u\n",
+ ar->cfr.cfr_enabled_peer_cnt);
+ return -EINVAL;
+ }
+
+ if (!cfr_capture_enable) {
+ cfr_capture_bw = arsta->cfr_capture.cfr_bw;
+ cfr_capture_period = arsta->cfr_capture.cfr_period;
+ cfr_capture_method = arsta->cfr_capture.cfr_method;
+ }
+
+ arg.request = cfr_capture_enable;
+ arg.periodicity = cfr_capture_period;
+ arg.bw = cfr_capture_bw;
+ arg.method = cfr_capture_method;
+
+ ret = ath11k_wmi_peer_set_cfr_capture_conf(ar, arsta->arvif->vdev_id,
+ sta->addr, &arg);
+ if (ret) {
+ ath11k_warn(ar->ab,
+ "failed to send cfr capture info: vdev_id %u peer %pM: %d\n",
+ arsta->arvif->vdev_id, sta->addr, ret);
+ return ret;
+ }
+
+ spin_lock_bh(&ar->cfr.lock);
+
+ if (cfr_capture_enable &&
+ cfr_capture_enable != arsta->cfr_capture.cfr_enable)
+ cfr->cfr_enabled_peer_cnt++;
+ else if (!cfr_capture_enable)
+ cfr->cfr_enabled_peer_cnt--;
+
+ spin_unlock_bh(&ar->cfr.lock);
+
+ arsta->cfr_capture.cfr_enable = cfr_capture_enable;
+ arsta->cfr_capture.cfr_period = cfr_capture_period;
+ arsta->cfr_capture.cfr_bw = cfr_capture_bw;
+ arsta->cfr_capture.cfr_method = cfr_capture_method;
+
+ return count;
+}
+
+static ssize_t ath11k_dbg_sta_read_cfr_capture(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_sta *sta = file->private_data;
+ struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
+ struct ath11k *ar = arsta->arvif->ar;
+ char buf[512] = {};
+ int len = 0;
+
+ mutex_lock(&ar->conf_mutex);
+
+ len += scnprintf(buf + len, sizeof(buf) - len, "cfr_enabled = %d\n",
+ arsta->cfr_capture.cfr_enable);
+ len += scnprintf(buf + len, sizeof(buf) - len, "bandwidth = %d\n",
+ arsta->cfr_capture.cfr_bw);
+ len += scnprintf(buf + len, sizeof(buf) - len, "period = %d\n",
+ arsta->cfr_capture.cfr_period);
+ len += scnprintf(buf + len, sizeof(buf) - len, "cfr_method = %d\n",
+ arsta->cfr_capture.cfr_method);
+
+ mutex_unlock(&ar->conf_mutex);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_peer_cfr_capture = {
+ .write = ath11k_dbg_sta_write_cfr_capture,
+ .read = ath11k_dbg_sta_read_cfr_capture,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+#endif /* CONFIG_ATH11K_CFR */
+
static ssize_t ath11k_dbg_sta_dump_rx_stats(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
@@ -877,6 +1010,13 @@ void ath11k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vi
debugfs_create_file("htt_peer_stats_reset", 0600, dir, sta,
&fops_htt_peer_stats_reset);
+#ifdef CONFIG_ATH11K_CFR
+ if (test_bit(WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT,
+ ar->ab->wmi_ab.svc_map))
+ debugfs_create_file("cfr_capture", 0600, dir, sta,
+ &fops_peer_cfr_capture);
+#endif/* CONFIG_ATH11K_CFR */
+
debugfs_create_file("peer_ps_state", 0400, dir, sta,
&fops_peer_ps_state);
diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c
index 56b1a657e0b0..c940de285276 100644
--- a/drivers/net/wireless/ath/ath11k/dp.c
+++ b/drivers/net/wireless/ath/ath11k/dp.c
@@ -344,7 +344,7 @@ void ath11k_dp_stop_shadow_timers(struct ath11k_base *ab)
if (!ab->hw_params.supports_shadow_regs)
return;
- for (i = 0; i < ab->hw_params.max_tx_ring; i++)
+ for (i = 0; i < ab->hw_params.hal_params->num_tx_rings; i++)
ath11k_dp_shadow_stop_timer(ab, &ab->dp.tx_ring_timer[i]);
ath11k_dp_shadow_stop_timer(ab, &ab->dp.reo_cmd_timer);
@@ -359,7 +359,7 @@ static void ath11k_dp_srng_common_cleanup(struct ath11k_base *ab)
ath11k_dp_srng_cleanup(ab, &dp->wbm_desc_rel_ring);
ath11k_dp_srng_cleanup(ab, &dp->tcl_cmd_ring);
ath11k_dp_srng_cleanup(ab, &dp->tcl_status_ring);
- for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
+ for (i = 0; i < ab->hw_params.hal_params->num_tx_rings; i++) {
ath11k_dp_srng_cleanup(ab, &dp->tx_ring[i].tcl_data_ring);
ath11k_dp_srng_cleanup(ab, &dp->tx_ring[i].tcl_comp_ring);
}
@@ -400,7 +400,7 @@ static int ath11k_dp_srng_common_setup(struct ath11k_base *ab)
goto err;
}
- for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
+ for (i = 0; i < ab->hw_params.hal_params->num_tx_rings; i++) {
tcl_num = ab->hw_params.hal_params->tcl2wbm_rbm_map[i].tcl_ring_num;
wbm_num = ab->hw_params.hal_params->tcl2wbm_rbm_map[i].wbm_ring_num;
@@ -782,7 +782,7 @@ int ath11k_dp_service_srng(struct ath11k_base *ab,
int i, j;
int tot_work_done = 0;
- for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
+ for (i = 0; i < ab->hw_params.hal_params->num_tx_rings; i++) {
if (BIT(ab->hw_params.hal_params->tcl2wbm_rbm_map[i].wbm_ring_num) &
ab->hw_params.ring_mask->tx[grp_id])
ath11k_dp_tx_completion_handler(ab, i);
@@ -1035,7 +1035,7 @@ void ath11k_dp_free(struct ath11k_base *ab)
ath11k_dp_reo_cmd_list_cleanup(ab);
- for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
+ for (i = 0; i < ab->hw_params.hal_params->num_tx_rings; i++) {
spin_lock_bh(&dp->tx_ring[i].tx_idr_lock);
idr_for_each(&dp->tx_ring[i].txbuf_idr,
ath11k_dp_tx_pending_cleanup, ab);
@@ -1086,7 +1086,7 @@ int ath11k_dp_alloc(struct ath11k_base *ab)
size = sizeof(struct hal_wbm_release_ring) * DP_TX_COMP_RING_SIZE;
- for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
+ for (i = 0; i < ab->hw_params.hal_params->num_tx_rings; i++) {
idr_init(&dp->tx_ring[i].txbuf_idr);
spin_lock_init(&dp->tx_ring[i].tx_idr_lock);
dp->tx_ring[i].tcl_data_ring_id = i;
diff --git a/drivers/net/wireless/ath/ath11k/dp.h b/drivers/net/wireless/ath/ath11k/dp.h
index 7a55afd33be8..1bd513f68a3c 100644
--- a/drivers/net/wireless/ath/ath11k/dp.h
+++ b/drivers/net/wireless/ath/ath11k/dp.h
@@ -199,7 +199,6 @@ struct ath11k_pdev_dp {
#define DP_BA_WIN_SZ_MAX 256
#define DP_TCL_NUM_RING_MAX 3
-#define DP_TCL_NUM_RING_MAX_QCA6390 1
#define DP_IDLE_SCATTER_BUFS_MAX 16
diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c
index 562aba66582f..86e1e6c27b36 100644
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
@@ -91,6 +91,7 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
struct hal_srng *tcl_ring;
struct ieee80211_hdr *hdr = (void *)skb->data;
struct dp_tx_ring *tx_ring;
+ size_t num_tx_rings = ab->hw_params.hal_params->num_tx_rings;
void *hal_tcl_desc;
u8 pool_id;
u8 hal_ring_id;
@@ -113,7 +114,7 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
tcl_ring_sel:
tcl_ring_retry = false;
- ti.ring_id = ring_selector % ab->hw_params.max_tx_ring;
+ ti.ring_id = ring_selector % num_tx_rings;
ti.rbm_id = ab->hw_params.hal_params->tcl2wbm_rbm_map[ti.ring_id].rbm_id;
ring_map |= BIT(ti.ring_id);
@@ -126,7 +127,7 @@ tcl_ring_sel:
spin_unlock_bh(&tx_ring->tx_idr_lock);
if (unlikely(ret < 0)) {
- if (ring_map == (BIT(ab->hw_params.max_tx_ring) - 1) ||
+ if (ring_map == (BIT(num_tx_rings) - 1) ||
!ab->hw_params.tcl_ring_retry) {
atomic_inc(&ab->soc_stats.tx_err.misc_fail);
return -ENOSPC;
@@ -244,8 +245,8 @@ tcl_ring_sel:
* checking this ring earlier for each pkt tx.
* Restart ring selection if some rings are not checked yet.
*/
- if (unlikely(ring_map != (BIT(ab->hw_params.max_tx_ring)) - 1) &&
- ab->hw_params.tcl_ring_retry && ab->hw_params.max_tx_ring > 1) {
+ if (unlikely(ring_map != (BIT(num_tx_rings)) - 1) &&
+ ab->hw_params.tcl_ring_retry && num_tx_rings > 1) {
tcl_ring_retry = true;
ring_selector++;
}
diff --git a/drivers/net/wireless/ath/ath11k/hal.c b/drivers/net/wireless/ath/ath11k/hal.c
index 0c797b8d0a27..e821e5a62c1c 100644
--- a/drivers/net/wireless/ath/ath11k/hal.c
+++ b/drivers/net/wireless/ath/ath11k/hal.c
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/dma-mapping.h>
@@ -184,7 +183,7 @@ static const struct hal_srng_config hw_srng_config_template[] = {
},
{ /* RXDMA DIR BUF */
.start_ring_id = HAL_SRNG_RING_ID_RXDMA_DIR_BUF,
- .max_rings = 1,
+ .max_rings = 2,
.entry_size = 8 >> 2, /* TODO: Define the struct */
.lmac_ring = true,
.ring_dir = HAL_SRNG_DIR_SRC,
diff --git a/drivers/net/wireless/ath/ath11k/hw.c b/drivers/net/wireless/ath/ath11k/hw.c
index caa6dc12a790..d19c4b372a2a 100644
--- a/drivers/net/wireless/ath/ath11k/hw.c
+++ b/drivers/net/wireless/ath/ath11k/hw.c
@@ -2707,6 +2707,14 @@ const struct ath11k_hw_regs wcn6750_regs = {
.hal_reo1_misc_ctl = 0x000005d8,
};
+static const struct ath11k_hw_tcl2wbm_rbm_map ath11k_hw_tcl2wbm_rbm_map_ipq5018[] = {
+ {
+ .tcl_ring_num = 0,
+ .wbm_ring_num = 0,
+ .rbm_id = HAL_RX_BUF_RBM_SW0_BM,
+ },
+};
+
static const struct ath11k_hw_tcl2wbm_rbm_map ath11k_hw_tcl2wbm_rbm_map_ipq8074[] = {
{
.tcl_ring_num = 0,
@@ -2822,19 +2830,28 @@ const struct ath11k_hw_regs ipq5018_regs = {
.hal_wbm1_release_ring_base_lsb = 0x0000097c,
};
+const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq5018 = {
+ .rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM,
+ .tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_ipq5018,
+ .num_tx_rings = ARRAY_SIZE(ath11k_hw_tcl2wbm_rbm_map_ipq5018),
+};
+
const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq8074 = {
.rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM,
.tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_ipq8074,
+ .num_tx_rings = ARRAY_SIZE(ath11k_hw_tcl2wbm_rbm_map_ipq8074),
};
const struct ath11k_hw_hal_params ath11k_hw_hal_params_qca6390 = {
.rx_buf_rbm = HAL_RX_BUF_RBM_SW1_BM,
- .tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_ipq8074,
+ .tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_ipq5018,
+ .num_tx_rings = ARRAY_SIZE(ath11k_hw_tcl2wbm_rbm_map_ipq5018),
};
const struct ath11k_hw_hal_params ath11k_hw_hal_params_wcn6750 = {
.rx_buf_rbm = HAL_RX_BUF_RBM_SW1_BM,
.tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_wcn6750,
+ .num_tx_rings = ARRAY_SIZE(ath11k_hw_tcl2wbm_rbm_map_wcn6750),
};
static const struct cfg80211_sar_freq_ranges ath11k_hw_sar_freq_ranges_wcn6855[] = {
diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h
index 52d9f4c13b13..4996536fbd14 100644
--- a/drivers/net/wireless/ath/ath11k/hw.h
+++ b/drivers/net/wireless/ath/ath11k/hw.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH11K_HW_H
@@ -134,6 +134,7 @@ struct ath11k_hw_tcl2wbm_rbm_map {
struct ath11k_hw_hal_params {
enum hal_rx_buf_return_buf_manager rx_buf_rbm;
const struct ath11k_hw_tcl2wbm_rbm_map *tcl2wbm_rbm_map;
+ size_t num_tx_rings;
};
struct ath11k_hw_params {
@@ -198,7 +199,6 @@ struct ath11k_hw_params {
bool supports_regdb;
bool fix_l1ss;
bool credit_flow;
- u8 max_tx_ring;
const struct ath11k_hw_hal_params *hal_params;
bool supports_dynamic_smps_6ghz;
bool alloc_cacheable_memory;
@@ -228,6 +228,9 @@ struct ath11k_hw_params {
bool support_fw_mac_sequence;
bool support_dual_stations;
bool pdev_suspend;
+ bool cfr_support;
+ u32 cfr_num_stream_bufs;
+ u32 cfr_stream_buf_size;
};
struct ath11k_hw_ops {
@@ -291,6 +294,7 @@ extern const struct ce_ie_addr ath11k_ce_ie_addr_ipq5018;
extern const struct ce_remap ath11k_ce_remap_ipq5018;
+extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq5018;
extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq8074;
extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_qca6390;
extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_wcn6750;
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 3276fe443502..4dfd08b58416 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -2911,6 +2911,8 @@ static void ath11k_peer_assoc_h_phymode(struct ath11k *ar,
arg->peer_phymode = phymode;
WARN_ON(phymode == MODE_UNKNOWN);
+
+ ath11k_cfr_update_phymode(ar, phymode);
}
static void ath11k_peer_assoc_prepare(struct ath11k *ar,
@@ -6186,6 +6188,8 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
dma_addr_t paddr;
int buf_id;
int ret;
+ bool tx_params_valid = false;
+ bool peer_in_unassoc_pool;
ATH11K_SKB_CB(skb)->ar = ar;
@@ -6224,7 +6228,18 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
ATH11K_SKB_CB(skb)->paddr = paddr;
- ret = ath11k_wmi_mgmt_send(ar, arvif->vdev_id, buf_id, skb);
+ peer_in_unassoc_pool = ath11k_cfr_peer_is_in_cfr_unassoc_pool(ar, hdr->addr1);
+
+ if (ar->cfr_enabled &&
+ ieee80211_is_probe_resp(hdr->frame_control) &&
+ peer_in_unassoc_pool)
+ tx_params_valid = true;
+
+ if (peer_in_unassoc_pool)
+ ath11k_cfr_update_unassoc_pool_entry(ar, hdr->addr1);
+
+ ret = ath11k_wmi_mgmt_send(ar, arvif->vdev_id, buf_id, skb,
+ tx_params_valid);
if (ret) {
ath11k_warn(ar->ab, "failed to send mgmt frame: %d\n", ret);
goto err_unmap_buf;
@@ -7392,7 +7407,7 @@ err_vdev_del:
idr_for_each(&ar->txmgmt_idr,
ath11k_mac_vif_txmgmt_idr_remove, vif);
- for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
+ for (i = 0; i < ab->hw_params.hal_params->num_tx_rings; i++) {
spin_lock_bh(&ab->dp.tx_ring[i].tx_idr_lock);
idr_for_each(&ab->dp.tx_ring[i].txbuf_idr,
ath11k_mac_vif_unref, vif);
@@ -9979,6 +9994,8 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
}
spin_unlock_bh(&ar->ab->base_lock);
mutex_unlock(&ar->ab->tbl_mtx_lock);
+
+ ath11k_cfr_decrement_peer_count(ar, arsta);
} else if (old_state == IEEE80211_STA_AUTH &&
new_state == IEEE80211_STA_ASSOC &&
(vif->type == NL80211_IFTYPE_AP ||
@@ -10640,7 +10657,7 @@ static int __ath11k_mac_register(struct ath11k *ar)
if (!ab->hw_params.supports_monitor)
/* There's a race between calling ieee80211_register_hw()
* and here where the monitor mode is enabled for a little
- * while. But that time is so short and in practise it make
+ * while. But that time is so short and in practice it doesn't make
* a difference in real life.
*/
ar->hw->wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MONITOR);
diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c
index d62a2014315a..49b79648752c 100644
--- a/drivers/net/wireless/ath/ath11k/reg.c
+++ b/drivers/net/wireless/ath/ath11k/reg.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/rtnetlink.h>
@@ -926,8 +926,11 @@ int ath11k_reg_handle_chan_list(struct ath11k_base *ab,
*/
if (ab->default_regd[pdev_idx] && !ab->new_regd[pdev_idx] &&
!memcmp((char *)ab->default_regd[pdev_idx]->alpha2,
- (char *)reg_info->alpha2, 2))
- goto retfail;
+ (char *)reg_info->alpha2, 2) &&
+ power_type == IEEE80211_REG_UNSET_AP) {
+ ath11k_reg_reset_info(reg_info);
+ return 0;
+ }
/* Intersect new rules with default regd if a new country setting was
* requested, i.e a default regd was already set during initialization
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index 110035dae8a6..451cc4c719ae 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -651,11 +651,12 @@ static u32 ath11k_wmi_mgmt_get_freq(struct ath11k *ar,
}
int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
- struct sk_buff *frame)
+ struct sk_buff *frame, bool tx_params_valid)
{
struct ath11k_pdev_wmi *wmi = ar->wmi;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(frame);
struct wmi_mgmt_send_cmd *cmd;
+ struct wmi_mgmt_send_params *params;
struct wmi_tlv *frame_tlv;
struct sk_buff *skb;
u32 buf_len;
@@ -665,6 +666,8 @@ int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
frame->len : WMI_MGMT_SEND_DOWNLD_LEN;
len = sizeof(*cmd) + sizeof(*frame_tlv) + roundup(buf_len, 4);
+ if (tx_params_valid)
+ len += sizeof(*params);
skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
@@ -680,7 +683,7 @@ int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
cmd->paddr_hi = upper_32_bits(ATH11K_SKB_CB(frame)->paddr);
cmd->frame_len = frame->len;
cmd->buf_len = buf_len;
- cmd->tx_params_valid = 0;
+ cmd->tx_params_valid = !!tx_params_valid;
frame_tlv = (struct wmi_tlv *)(skb->data + sizeof(*cmd));
frame_tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) |
@@ -690,6 +693,15 @@ int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
ath11k_ce_byte_swap(frame_tlv->value, buf_len);
+ if (tx_params_valid) {
+ params =
+ (struct wmi_mgmt_send_params *)(skb->data + (len - sizeof(*params)));
+ params->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_TX_SEND_PARAMS) |
+ FIELD_PREP(WMI_TLV_LEN,
+ sizeof(*params) - TLV_HDR_SIZE);
+ params->tx_params_dword1 |= WMI_TX_PARAMS_DWORD1_CFR_CAPTURE;
+ }
+
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_MGMT_TX_SEND_CMDID);
if (ret) {
ath11k_warn(ar->ab,
@@ -3941,6 +3953,47 @@ int ath11k_wmi_fils_discovery_tmpl(struct ath11k *ar, u32 vdev_id,
return 0;
}
+int ath11k_wmi_peer_set_cfr_capture_conf(struct ath11k *ar,
+ u32 vdev_id, const u8 *mac_addr,
+ struct wmi_peer_cfr_capture_conf_arg *arg)
+{
+ struct ath11k_pdev_wmi *wmi = ar->wmi;
+ struct wmi_peer_cfr_capture_cmd_fixed_param *cmd;
+ struct sk_buff *skb;
+ int ret;
+
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_peer_cfr_capture_cmd_fixed_param *)skb->data;
+ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG,
+ WMI_TAG_PEER_CFR_CAPTURE_CMD) |
+ FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
+
+ memcpy(&cmd->mac_addr, mac_addr, ETH_ALEN);
+ cmd->request = arg->request;
+ cmd->vdev_id = vdev_id;
+ cmd->periodicity = arg->periodicity;
+ cmd->bandwidth = arg->bw;
+ cmd->capture_method = arg->method;
+
+ ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_PEER_CFR_CAPTURE_CMDID);
+ if (ret) {
+ ath11k_warn(ar->ab,
+ "WMI vdev %d failed to send peer cfr capture cmd: %d\n",
+ vdev_id, ret);
+ dev_kfree_skb(skb);
+ }
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "WMI peer CFR capture cmd req %u id %u period %u bw %u mode %u\n",
+ arg->request, vdev_id, arg->periodicity,
+ arg->bw, arg->method);
+
+ return ret;
+}
+
int ath11k_wmi_probe_resp_tmpl(struct ath11k *ar, u32 vdev_id,
struct sk_buff *tmpl)
{
@@ -8752,6 +8805,93 @@ out:
kfree(tb);
}
+static void ath11k_wmi_tlv_cfr_capture_event_fixed_param(const void *ptr,
+ void *data)
+{
+ struct ath11k_cfr_peer_tx_param *tx_params = data;
+ const struct ath11k_wmi_cfr_peer_tx_event_param *params = ptr;
+
+ tx_params->capture_method = params->capture_method;
+ tx_params->vdev_id = params->vdev_id;
+ ether_addr_copy(tx_params->peer_mac_addr, params->mac_addr.addr);
+ tx_params->primary_20mhz_chan = params->chan_mhz;
+ tx_params->bandwidth = params->bandwidth;
+ tx_params->phy_mode = params->phy_mode;
+ tx_params->band_center_freq1 = params->band_center_freq1;
+ tx_params->band_center_freq2 = params->band_center_freq2;
+ tx_params->spatial_streams = params->sts_count;
+ tx_params->correlation_info_1 = params->correlation_info_1;
+ tx_params->correlation_info_2 = params->correlation_info_2;
+ tx_params->status = params->status;
+ tx_params->timestamp_us = params->timestamp_us;
+ tx_params->counter = params->counter;
+ tx_params->rx_start_ts = params->rx_start_ts;
+
+ memcpy(tx_params->chain_rssi, params->chain_rssi,
+ sizeof(tx_params->chain_rssi));
+
+ if (WMI_CFR_CFO_MEASUREMENT_VALID & params->cfo_measurement)
+ tx_params->cfo_measurement = FIELD_GET(WMI_CFR_CFO_MEASUREMENT_RAW_DATA,
+ params->cfo_measurement);
+}
+
+static void ath11k_wmi_tlv_cfr_capture_phase_fixed_param(const void *ptr,
+ void *data)
+{
+ struct ath11k_cfr_peer_tx_param *tx_params = data;
+ const struct ath11k_wmi_cfr_peer_tx_event_phase_param *params = ptr;
+ int i;
+
+ for (i = 0; i < WMI_MAX_CHAINS; i++) {
+ tx_params->chain_phase[i] = params->chain_phase[i];
+ tx_params->agc_gain[i] = params->agc_gain[i];
+ }
+}
+
+static int ath11k_wmi_tlv_cfr_capture_evt_parse(struct ath11k_base *ab,
+ u16 tag, u16 len,
+ const void *ptr, void *data)
+{
+ switch (tag) {
+ case WMI_TAG_PEER_CFR_CAPTURE_EVENT:
+ ath11k_wmi_tlv_cfr_capture_event_fixed_param(ptr, data);
+ break;
+ case WMI_TAG_CFR_CAPTURE_PHASE_PARAM:
+ ath11k_wmi_tlv_cfr_capture_phase_fixed_param(ptr, data);
+ break;
+ default:
+ ath11k_warn(ab, "Invalid tag received tag %d len %d\n",
+ tag, len);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void ath11k_wmi_parse_cfr_capture_event(struct ath11k_base *ab,
+ struct sk_buff *skb)
+{
+ struct ath11k_cfr_peer_tx_param params = {};
+ int ret;
+
+ ath11k_dbg_dump(ab, ATH11K_DBG_CFR_DUMP, "cfr_dump:", "",
+ skb->data, skb->len);
+
+ ret = ath11k_wmi_tlv_iter(ab, skb->data, skb->len,
+ ath11k_wmi_tlv_cfr_capture_evt_parse,
+ &params);
+ if (ret) {
+ ath11k_warn(ab, "failed to parse cfr capture event tlv %d\n",
+ ret);
+ return;
+ }
+
+ ret = ath11k_process_cfr_capture_event(ab, &params);
+ if (ret)
+ ath11k_dbg(ab, ATH11K_DBG_CFR,
+ "failed to process cfr capture ret = %d\n", ret);
+}
+
static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
{
struct wmi_cmd_hdr *cmd_hdr;
@@ -8882,6 +9022,9 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
case WMI_P2P_NOA_EVENTID:
ath11k_wmi_p2p_noa_event(ab, skb);
break;
+ case WMI_PEER_CFR_CAPTURE_EVENTID:
+ ath11k_wmi_parse_cfr_capture_event(ab, skb);
+ break;
default:
ath11k_dbg(ab, ATH11K_DBG_WMI, "unsupported event id 0x%x\n", id);
break;
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index 0f0de24a3840..baed501b640b 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -362,6 +362,10 @@ enum wmi_tlv_cmd_id {
WMI_PEER_REORDER_QUEUE_REMOVE_CMDID,
WMI_PEER_SET_RX_BLOCKSIZE_CMDID,
WMI_PEER_ANTDIV_INFO_REQ_CMDID,
+ WMI_PEER_RESERVED0_CMDID,
+ WMI_PEER_TID_MSDUQ_QDEPTH_THRESH_UPDATE_CMDID,
+ WMI_PEER_TID_CONFIGURATIONS_CMDID,
+ WMI_PEER_CFR_CAPTURE_CMDID,
WMI_BCN_TX_CMDID = WMI_TLV_CMD(WMI_GRP_MGMT),
WMI_PDEV_SEND_BCN_CMDID,
WMI_BCN_TMPL_CMDID,
@@ -981,6 +985,7 @@ enum wmi_tlv_pdev_param {
WMI_PDEV_PARAM_RADIO_CHAN_STATS_ENABLE,
WMI_PDEV_PARAM_RADIO_DIAGNOSIS_ENABLE,
WMI_PDEV_PARAM_MESH_MCAST_ENABLE,
+ WMI_PDEV_PARAM_PER_PEER_CFR_ENABLE = 0xa8,
WMI_PDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD = 0xbc,
WMI_PDEV_PARAM_SET_CMD_OBSS_PD_PER_AC = 0xbe,
WMI_PDEV_PARAM_ENABLE_SR_PROHIBIT = 0xc6,
@@ -1884,6 +1889,8 @@ enum wmi_tlv_tag {
WMI_TAG_NDP_EVENT,
WMI_TAG_PDEV_PEER_PKTLOG_FILTER_CMD = 0x301,
WMI_TAG_PDEV_PEER_PKTLOG_FILTER_INFO,
+ WMI_TAG_PEER_CFR_CAPTURE_EVENT = 0x317,
+ WMI_TAG_CFR_CAPTURE_PHASE_PARAM = 0x33b,
WMI_TAG_FILS_DISCOVERY_TMPL_CMD = 0x344,
WMI_TAG_PDEV_SRG_BSS_COLOR_BITMAP_CMD = 0x37b,
WMI_TAG_PDEV_SRG_PARTIAL_BSSID_BITMAP_CMD,
@@ -3832,7 +3839,8 @@ struct wmi_scan_prob_req_oui_cmd {
#define WMI_TX_PARAMS_DWORD1_BW_MASK GENMASK(14, 8)
#define WMI_TX_PARAMS_DWORD1_PREAMBLE_TYPE GENMASK(19, 15)
#define WMI_TX_PARAMS_DWORD1_FRAME_TYPE BIT(20)
-#define WMI_TX_PARAMS_DWORD1_RSVD GENMASK(31, 21)
+#define WMI_TX_PARAMS_DWORD1_CFR_CAPTURE BIT(21)
+#define WMI_TX_PARAMS_DWORD1_RSVD GENMASK(31, 22)
struct wmi_mgmt_send_params {
u32 tlv_header;
@@ -4217,6 +4225,87 @@ enum cc_setting_code {
*/
};
+enum ath11k_wmi_cfr_capture_bw {
+ WMI_PEER_CFR_CAPTURE_BW_20,
+ WMI_PEER_CFR_CAPTURE_BW_40,
+ WMI_PEER_CFR_CAPTURE_BW_80,
+ WMI_PEER_CFR_CAPTURE_BW_MAX,
+};
+
+enum ath11k_wmi_cfr_capture_method {
+ WMI_CFR_CAPTURE_METHOD_NULL_FRAME,
+ WMI_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE,
+ WMI_CFR_CAPTURE_METHOD_PROBE_RESP,
+ WMI_CFR_CAPTURE_METHOD_MAX,
+};
+
+#define WMI_CFR_FRAME_TX_STATUS GENMASK(1, 0)
+#define WMI_CFR_CAPTURE_STATUS_PEER_PS BIT(30)
+#define WMI_CFR_PEER_CAPTURE_STATUS BIT(31)
+
+#define WMI_CFR_CORRELATION_INFO2_BUF_ADDR_HIGH GENMASK(3, 0)
+#define WMI_CFR_CORRELATION_INFO2_PPDU_ID GENMASK(31, 16)
+
+#define WMI_CFR_CFO_MEASUREMENT_VALID BIT(0)
+#define WMI_CFR_CFO_MEASUREMENT_RAW_DATA GENMASK(14, 1)
+
+struct ath11k_wmi_cfr_peer_tx_event_param {
+ u32 capture_method;
+ u32 vdev_id;
+ struct wmi_mac_addr mac_addr;
+ u32 chan_mhz;
+ u32 bandwidth;
+ u32 phy_mode;
+ u32 band_center_freq1;
+ u32 band_center_freq2;
+ u32 sts_count;
+ u32 correlation_info_1;
+ u32 correlation_info_2;
+ u32 status;
+ u32 timestamp_us;
+ u32 counter;
+ u32 chain_rssi[WMI_MAX_CHAINS];
+ u32 cfo_measurement;
+ u32 rx_start_ts;
+} __packed;
+
+struct ath11k_wmi_cfr_peer_tx_event_phase_param {
+ u32 chain_phase[WMI_MAX_CHAINS];
+ u8 agc_gain[WMI_MAX_CHAINS];
+} __packed;
+
+enum ath11k_wmi_frame_tx_status {
+ WMI_FRAME_TX_STATUS_OK,
+ WMI_FRAME_TX_STATUS_XRETRY,
+ WMI_FRAME_TX_STATUS_DROP,
+ WMI_FRAME_TX_STATUS_FILTERED,
+};
+
+struct wmi_peer_cfr_capture_conf_arg {
+ enum ath11k_wmi_cfr_capture_bw bw;
+ enum ath11k_wmi_cfr_capture_method method;
+ u32 request;
+ u32 periodicity;
+};
+
+struct wmi_peer_cfr_capture_cmd_fixed_param {
+ u32 tlv_header;
+ u32 request;
+ struct wmi_mac_addr mac_addr;
+ u32 vdev_id;
+ u32 periodicity;
+ /* BW of measurement - of type enum ath11k_wmi_cfr_capture_bw */
+ u32 bandwidth;
+ /* Method used to capture CFR - of type enum ath11k_wmi_cfr_capture_method */
+ u32 capture_method;
+} __packed;
+
+#define WMI_PEER_CFR_CAPTURE_ENABLE 1
+#define WMI_PEER_CFR_CAPTURE_DISABLE 0
+
+/*periodicity in ms */
+#define WMI_PEER_CFR_PERIODICITY_MAX 600000
+
static inline enum cc_setting_code
ath11k_wmi_cc_setting_code_to_reg(enum wmi_reg_cc_setting_code status_code)
{
@@ -6346,7 +6435,7 @@ int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb,
u32 cmd_id);
struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len);
int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
- struct sk_buff *frame);
+ struct sk_buff *frame, bool tx_params_valid);
int ath11k_wmi_p2p_go_bcn_ie(struct ath11k *ar, u32 vdev_id,
const u8 *p2p_ie);
int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
@@ -6531,5 +6620,7 @@ bool ath11k_wmi_supports_6ghz_cc_ext(struct ath11k *ar);
int ath11k_wmi_send_vdev_set_tpc_power(struct ath11k *ar,
u32 vdev_id,
struct ath11k_reg_tpc_power_info *param);
-
+int ath11k_wmi_peer_set_cfr_capture_conf(struct ath11k *ar,
+ u32 vdev_id, const u8 *mac,
+ struct wmi_peer_cfr_capture_conf_arg *arg);
#endif
diff --git a/drivers/net/wireless/ath/ath12k/Makefile b/drivers/net/wireless/ath/ath12k/Makefile
index d95ee525a6cd..3ba1236956cc 100644
--- a/drivers/net/wireless/ath/ath12k/Makefile
+++ b/drivers/net/wireless/ath/ath12k/Makefile
@@ -2,8 +2,6 @@
obj-$(CONFIG_ATH12K) += ath12k.o
ath12k-y += core.o \
hal.o \
- hal_tx.o \
- hal_rx.o \
wmi.o \
mac.o \
reg.o \
@@ -12,11 +10,12 @@ ath12k-y += core.o \
dp.o \
dp_tx.o \
dp_rx.o \
+ dp_htt.o \
+ dp_peer.o \
debug.o \
ce.o \
peer.o \
dbring.o \
- hw.o \
mhi.o \
pci.o \
dp_mon.o \
@@ -24,6 +23,9 @@ ath12k-y += core.o \
p2p.o
ath12k-$(CONFIG_ATH12K_AHB) += ahb.o
+
+obj-$(CONFIG_ATH12K) += wifi7/
+
ath12k-$(CONFIG_ATH12K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o
ath12k-$(CONFIG_ACPI) += acpi.o
ath12k-$(CONFIG_ATH12K_TRACING) += trace.o
diff --git a/drivers/net/wireless/ath/ath12k/ahb.c b/drivers/net/wireless/ath/ath12k/ahb.c
index b30527c402f6..9a4d34e49104 100644
--- a/drivers/net/wireless/ath/ath12k/ahb.c
+++ b/drivers/net/wireless/ath/ath12k/ahb.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/dma-mapping.h>
@@ -16,18 +16,11 @@
#include "debug.h"
#include "hif.h"
-static const struct of_device_id ath12k_ahb_of_match[] = {
- { .compatible = "qcom,ipq5332-wifi",
- .data = (void *)ATH12K_HW_IPQ5332_HW10,
- },
- { }
-};
-
-MODULE_DEVICE_TABLE(of, ath12k_ahb_of_match);
-
#define ATH12K_IRQ_CE0_OFFSET 4
#define ATH12K_MAX_UPDS 1
#define ATH12K_UPD_IRQ_WRD_LEN 18
+
+static struct ath12k_ahb_driver *ath12k_ahb_family_drivers[ATH12K_DEVICE_FAMILY_MAX];
static const char ath12k_userpd_irq[][9] = {"spawn",
"ready",
"stop-ack"};
@@ -130,7 +123,7 @@ enum ext_irq_num {
static u32 ath12k_ahb_read32(struct ath12k_base *ab, u32 offset)
{
- if (ab->ce_remap && offset < HAL_SEQ_WCSS_CMEM_OFFSET)
+ if (ab->ce_remap && offset < ab->cmem_offset)
return ioread32(ab->mem_ce + offset);
return ioread32(ab->mem + offset);
}
@@ -138,7 +131,7 @@ static u32 ath12k_ahb_read32(struct ath12k_base *ab, u32 offset)
static void ath12k_ahb_write32(struct ath12k_base *ab, u32 offset,
u32 value)
{
- if (ab->ce_remap && offset < HAL_SEQ_WCSS_CMEM_OFFSET)
+ if (ab->ce_remap && offset < ab->cmem_offset)
iowrite32(value, ab->mem_ce + offset);
else
iowrite32(value, ab->mem + offset);
@@ -531,9 +524,10 @@ static int ath12k_ahb_ext_grp_napi_poll(struct napi_struct *napi, int budget)
struct ath12k_ext_irq_grp,
napi);
struct ath12k_base *ab = irq_grp->ab;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
int work_done;
- work_done = ath12k_dp_service_srng(ab, irq_grp, budget);
+ work_done = ath12k_dp_service_srng(dp, irq_grp, budget);
if (work_done < budget) {
napi_complete_done(napi, work_done);
ath12k_ahb_ext_grp_enable(irq_grp);
@@ -563,12 +557,10 @@ static int ath12k_ahb_config_ext_irq(struct ath12k_base *ab)
{
const struct ath12k_hw_ring_mask *ring_mask;
struct ath12k_ext_irq_grp *irq_grp;
- const struct hal_ops *hal_ops;
int i, j, irq, irq_idx, ret;
u32 num_irq;
ring_mask = ab->hw_params->ring_mask;
- hal_ops = ab->hw_params->hal_ops;
for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) {
irq_grp = &ab->ext_irq_grp[i];
num_irq = 0;
@@ -588,7 +580,7 @@ static int ath12k_ahb_config_ext_irq(struct ath12k_base *ab)
* tcl_to_wbm_rbm_map point to the same ring number.
*/
if (ring_mask->tx[i] &
- BIT(hal_ops->tcl_to_wbm_rbm_map[j].wbm_ring_num)) {
+ BIT(ab->hal.tcl_to_wbm_rbm_map[j].wbm_ring_num)) {
irq_grp->irqs[num_irq++] =
wbm2host_tx_completions_ring1 - j;
}
@@ -698,7 +690,7 @@ static int ath12k_ahb_map_service_to_pipe(struct ath12k_base *ab, u16 service_id
return 0;
}
-static const struct ath12k_hif_ops ath12k_ahb_hif_ops_ipq5332 = {
+static const struct ath12k_hif_ops ath12k_ahb_hif_ops = {
.start = ath12k_ahb_start,
.stop = ath12k_ahb_stop,
.read32 = ath12k_ahb_read32,
@@ -935,7 +927,8 @@ static int ath12k_ahb_resource_init(struct ath12k_base *ab)
goto err_mem_unmap;
}
ab->ce_remap = true;
- ab->ce_remap_base_addr = HAL_IPQ5332_CE_WFSS_REG_BASE;
+ ab->cmem_offset = ce_remap->cmem_offset;
+ ab->ce_remap_base_addr = ce_remap->base;
}
ab_ahb->xo_clk = devm_clk_get(ab->dev, "xo");
@@ -988,13 +981,34 @@ static void ath12k_ahb_resource_deinit(struct ath12k_base *ab)
ab_ahb->xo_clk = NULL;
}
+static enum ath12k_device_family
+ath12k_ahb_get_device_family(const struct platform_device *pdev)
+{
+ enum ath12k_device_family device_family_id;
+ struct ath12k_ahb_driver *driver;
+ const struct of_device_id *of_id;
+
+ for (device_family_id = ATH12K_DEVICE_FAMILY_START;
+ device_family_id < ATH12K_DEVICE_FAMILY_MAX; device_family_id++) {
+ driver = ath12k_ahb_family_drivers[device_family_id];
+ if (driver) {
+ of_id = of_match_device(driver->id_table, &pdev->dev);
+ if (of_id) {
+ /* Found the driver */
+ return device_family_id;
+ }
+ }
+ }
+
+ return ATH12K_DEVICE_FAMILY_MAX;
+}
+
static int ath12k_ahb_probe(struct platform_device *pdev)
{
- struct ath12k_base *ab;
- const struct ath12k_hif_ops *hif_ops;
+ enum ath12k_device_family device_id;
struct ath12k_ahb *ab_ahb;
- enum ath12k_hw_rev hw_rev;
- u32 addr, userpd_id;
+ struct ath12k_base *ab;
+ u32 addr;
int ret;
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
@@ -1008,25 +1022,32 @@ static int ath12k_ahb_probe(struct platform_device *pdev)
if (!ab)
return -ENOMEM;
- hw_rev = (enum ath12k_hw_rev)(kernel_ulong_t)of_device_get_match_data(&pdev->dev);
- switch (hw_rev) {
- case ATH12K_HW_IPQ5332_HW10:
- hif_ops = &ath12k_ahb_hif_ops_ipq5332;
- userpd_id = ATH12K_IPQ5332_USERPD_ID;
- break;
- default:
- ret = -EOPNOTSUPP;
+ ab_ahb = ath12k_ab_to_ahb(ab);
+ ab_ahb->ab = ab;
+ ab->hif.ops = &ath12k_ahb_hif_ops;
+ ab->pdev = pdev;
+ platform_set_drvdata(pdev, ab);
+
+ device_id = ath12k_ahb_get_device_family(pdev);
+ if (device_id >= ATH12K_DEVICE_FAMILY_MAX) {
+ ath12k_err(ab, "failed to get device family: %d\n", device_id);
+ ret = -EINVAL;
goto err_core_free;
}
- ab->hif.ops = hif_ops;
- ab->pdev = pdev;
- ab->hw_rev = hw_rev;
- ab->target_mem_mode = ATH12K_QMI_MEMORY_MODE_DEFAULT;
- platform_set_drvdata(pdev, ab);
- ab_ahb = ath12k_ab_to_ahb(ab);
- ab_ahb->ab = ab;
- ab_ahb->userpd_id = userpd_id;
+ ath12k_dbg(ab, ATH12K_DBG_AHB, "AHB device family id: %d\n", device_id);
+
+ ab_ahb->device_family_ops = &ath12k_ahb_family_drivers[device_id]->ops;
+
+ /* Call device specific probe. This is the callback that can
+ * be used to override any ops in future
+ * probe is validated for NULL during registration.
+ */
+ ret = ab_ahb->device_family_ops->probe(pdev);
+ if (ret) {
+ ath12k_err(ab, "failed to probe device: %d\n", ret);
+ goto err_core_free;
+ }
/* Set fixed_mem_region to true for platforms that support fixed memory
* reservation from DT. If memory is reserved from DT for FW, ath12k driver
@@ -1065,14 +1086,26 @@ static int ath12k_ahb_probe(struct platform_device *pdev)
goto err_rproc_deconfigure;
}
+ /* Invoke arch_init here so that arch-specific init operations
+ * can utilize already initialized ab fields, such as HAL SRNGs.
+ */
+ ret = ab_ahb->device_family_ops->arch_init(ab);
+ if (ret) {
+ ath12k_err(ab, "AHB arch_init failed %d\n", ret);
+ goto err_rproc_deconfigure;
+ }
+
ret = ath12k_core_init(ab);
if (ret) {
ath12k_err(ab, "failed to init core: %d\n", ret);
- goto err_rproc_deconfigure;
+ goto err_deinit_arch;
}
return 0;
+err_deinit_arch:
+ ab_ahb->device_family_ops->arch_deinit(ab);
+
err_rproc_deconfigure:
ath12k_ahb_deconfigure_rproc(ab);
@@ -1111,11 +1144,13 @@ static void ath12k_ahb_remove_prepare(struct ath12k_base *ab)
static void ath12k_ahb_free_resources(struct ath12k_base *ab)
{
struct platform_device *pdev = ab->pdev;
+ struct ath12k_ahb *ab_ahb = ath12k_ab_to_ahb(ab);
ath12k_hal_srng_deinit(ab);
ath12k_ce_free_pipes(ab);
ath12k_ahb_resource_deinit(ab);
ath12k_ahb_deconfigure_rproc(ab);
+ ab_ahb->device_family_ops->arch_deinit(ab);
ath12k_core_free(ab);
platform_set_drvdata(pdev, NULL);
}
@@ -1136,21 +1171,47 @@ qmi_fail:
ath12k_ahb_free_resources(ab);
}
-static struct platform_driver ath12k_ahb_driver = {
- .driver = {
- .name = "ath12k_ahb",
- .of_match_table = ath12k_ahb_of_match,
- },
- .probe = ath12k_ahb_probe,
- .remove = ath12k_ahb_remove,
-};
-
-int ath12k_ahb_init(void)
+int ath12k_ahb_register_driver(const enum ath12k_device_family device_id,
+ struct ath12k_ahb_driver *driver)
{
- return platform_driver_register(&ath12k_ahb_driver);
+ struct platform_driver *ahb_driver;
+
+ if (device_id >= ATH12K_DEVICE_FAMILY_MAX)
+ return -EINVAL;
+
+ if (!driver || !driver->ops.probe ||
+ !driver->ops.arch_init || !driver->ops.arch_deinit)
+ return -EINVAL;
+
+ if (ath12k_ahb_family_drivers[device_id]) {
+ pr_err("Driver already registered for id %d\n", device_id);
+ return -EALREADY;
+ }
+
+ ath12k_ahb_family_drivers[device_id] = driver;
+
+ ahb_driver = &ath12k_ahb_family_drivers[device_id]->driver;
+ ahb_driver->driver.name = driver->name;
+ ahb_driver->driver.of_match_table = driver->id_table;
+ ahb_driver->probe = ath12k_ahb_probe;
+ ahb_driver->remove = ath12k_ahb_remove;
+
+ return platform_driver_register(ahb_driver);
}
+EXPORT_SYMBOL(ath12k_ahb_register_driver);
-void ath12k_ahb_exit(void)
+void ath12k_ahb_unregister_driver(const enum ath12k_device_family device_id)
{
- platform_driver_unregister(&ath12k_ahb_driver);
+ struct platform_driver *ahb_driver;
+
+ if (device_id >= ATH12K_DEVICE_FAMILY_MAX)
+ return;
+
+ if (!ath12k_ahb_family_drivers[device_id])
+ return;
+
+ ahb_driver = &ath12k_ahb_family_drivers[device_id]->driver;
+ platform_driver_unregister(ahb_driver);
+ ath12k_ahb_family_drivers[device_id] = NULL;
}
+EXPORT_SYMBOL(ath12k_ahb_unregister_driver);
diff --git a/drivers/net/wireless/ath/ath12k/ahb.h b/drivers/net/wireless/ath/ath12k/ahb.h
index d56244b20a6a..8a040d03d27a 100644
--- a/drivers/net/wireless/ath/ath12k/ahb.h
+++ b/drivers/net/wireless/ath/ath12k/ahb.h
@@ -1,13 +1,14 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2025, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH12K_AHB_H
#define ATH12K_AHB_H
#include <linux/clk.h>
#include <linux/remoteproc/qcom_rproc.h>
+#include <linux/platform_device.h>
#include "core.h"
#define ATH12K_AHB_RECOVERY_TIMEOUT (3 * HZ)
@@ -43,6 +44,12 @@ enum ath12k_ahb_userpd_irq {
struct ath12k_base;
+struct ath12k_ahb_device_family_ops {
+ int (*probe)(struct platform_device *pdev);
+ int (*arch_init)(struct ath12k_base *ab);
+ void (*arch_deinit)(struct ath12k_base *ab);
+};
+
struct ath12k_ahb {
struct ath12k_base *ab;
struct rproc *tgt_rproc;
@@ -59,6 +66,15 @@ struct ath12k_ahb {
u32 spawn_bit;
u32 stop_bit;
int userpd_irq_num[ATH12K_USERPD_MAX_IRQ];
+ const struct ath12k_ahb_ops *ahb_ops;
+ const struct ath12k_ahb_device_family_ops *device_family_ops;
+};
+
+struct ath12k_ahb_driver {
+ const char *name;
+ const struct of_device_id *id_table;
+ struct ath12k_ahb_device_family_ops ops;
+ struct platform_driver driver;
};
static inline struct ath12k_ahb *ath12k_ab_to_ahb(struct ath12k_base *ab)
@@ -66,15 +82,8 @@ static inline struct ath12k_ahb *ath12k_ab_to_ahb(struct ath12k_base *ab)
return (struct ath12k_ahb *)ab->drv_priv;
}
-#ifdef CONFIG_ATH12K_AHB
-int ath12k_ahb_init(void);
-void ath12k_ahb_exit(void);
-#else
-static inline int ath12k_ahb_init(void)
-{
- return 0;
-}
+int ath12k_ahb_register_driver(const enum ath12k_device_family device_id,
+ struct ath12k_ahb_driver *driver);
+void ath12k_ahb_unregister_driver(const enum ath12k_device_family device_id);
-static inline void ath12k_ahb_exit(void) {};
-#endif
#endif
diff --git a/drivers/net/wireless/ath/ath12k/ce.c b/drivers/net/wireless/ath/ath12k/ce.c
index 4aea58446838..f13b260c5c96 100644
--- a/drivers/net/wireless/ath/ath12k/ce.c
+++ b/drivers/net/wireless/ath/ath12k/ce.c
@@ -1,314 +1,13 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022, 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include "dp_rx.h"
#include "debug.h"
#include "hif.h"
-const struct ce_attr ath12k_host_ce_config_qcn9274[] = {
- /* CE0: host->target HTC control and raw streams */
- {
- .flags = CE_ATTR_FLAGS,
- .src_nentries = 16,
- .src_sz_max = 2048,
- .dest_nentries = 0,
- },
-
- /* CE1: target->host HTT + HTC control */
- {
- .flags = CE_ATTR_FLAGS,
- .src_nentries = 0,
- .src_sz_max = 2048,
- .dest_nentries = 512,
- .recv_cb = ath12k_htc_rx_completion_handler,
- },
-
- /* CE2: target->host WMI */
- {
- .flags = CE_ATTR_FLAGS,
- .src_nentries = 0,
- .src_sz_max = 2048,
- .dest_nentries = 128,
- .recv_cb = ath12k_htc_rx_completion_handler,
- },
-
- /* CE3: host->target WMI (mac0) */
- {
- .flags = CE_ATTR_FLAGS,
- .src_nentries = 32,
- .src_sz_max = 2048,
- .dest_nentries = 0,
- },
-
- /* CE4: host->target HTT */
- {
- .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
- .src_nentries = 2048,
- .src_sz_max = 256,
- .dest_nentries = 0,
- },
-
- /* CE5: target->host pktlog */
- {
- .flags = CE_ATTR_FLAGS,
- .src_nentries = 0,
- .src_sz_max = 2048,
- .dest_nentries = 512,
- .recv_cb = ath12k_dp_htt_htc_t2h_msg_handler,
- },
-
- /* CE6: target autonomous hif_memcpy */
- {
- .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
- .src_nentries = 0,
- .src_sz_max = 0,
- .dest_nentries = 0,
- },
-
- /* CE7: host->target WMI (mac1) */
- {
- .flags = CE_ATTR_FLAGS,
- .src_nentries = 32,
- .src_sz_max = 2048,
- .dest_nentries = 0,
- },
-
- /* CE8: target autonomous hif_memcpy */
- {
- .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
- .src_nentries = 0,
- .src_sz_max = 0,
- .dest_nentries = 0,
- },
-
- /* CE9: MHI */
- {
- .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
- .src_nentries = 0,
- .src_sz_max = 0,
- .dest_nentries = 0,
- },
-
- /* CE10: MHI */
- {
- .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
- .src_nentries = 0,
- .src_sz_max = 0,
- .dest_nentries = 0,
- },
-
- /* CE11: MHI */
- {
- .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
- .src_nentries = 0,
- .src_sz_max = 0,
- .dest_nentries = 0,
- },
-
- /* CE12: CV Prefetch */
- {
- .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
- .src_nentries = 0,
- .src_sz_max = 0,
- .dest_nentries = 0,
- },
-
- /* CE13: CV Prefetch */
- {
- .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
- .src_nentries = 0,
- .src_sz_max = 0,
- .dest_nentries = 0,
- },
-
- /* CE14: target->host dbg log */
- {
- .flags = CE_ATTR_FLAGS,
- .src_nentries = 0,
- .src_sz_max = 2048,
- .dest_nentries = 512,
- .recv_cb = ath12k_htc_rx_completion_handler,
- },
-
- /* CE15: reserved for future use */
- {
- .flags = (CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
- .src_nentries = 0,
- .src_sz_max = 0,
- .dest_nentries = 0,
- },
-};
-
-const struct ce_attr ath12k_host_ce_config_wcn7850[] = {
- /* CE0: host->target HTC control and raw streams */
- {
- .flags = CE_ATTR_FLAGS,
- .src_nentries = 16,
- .src_sz_max = 2048,
- .dest_nentries = 0,
- },
-
- /* CE1: target->host HTT + HTC control */
- {
- .flags = CE_ATTR_FLAGS,
- .src_nentries = 0,
- .src_sz_max = 2048,
- .dest_nentries = 512,
- .recv_cb = ath12k_htc_rx_completion_handler,
- },
-
- /* CE2: target->host WMI */
- {
- .flags = CE_ATTR_FLAGS,
- .src_nentries = 0,
- .src_sz_max = 2048,
- .dest_nentries = 64,
- .recv_cb = ath12k_htc_rx_completion_handler,
- },
-
- /* CE3: host->target WMI (mac0) */
- {
- .flags = CE_ATTR_FLAGS,
- .src_nentries = 32,
- .src_sz_max = 2048,
- .dest_nentries = 0,
- },
-
- /* CE4: host->target HTT */
- {
- .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
- .src_nentries = 2048,
- .src_sz_max = 256,
- .dest_nentries = 0,
- },
-
- /* CE5: target->host pktlog */
- {
- .flags = CE_ATTR_FLAGS,
- .src_nentries = 0,
- .src_sz_max = 0,
- .dest_nentries = 0,
- },
-
- /* CE6: target autonomous hif_memcpy */
- {
- .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
- .src_nentries = 0,
- .src_sz_max = 0,
- .dest_nentries = 0,
- },
-
- /* CE7: host->target WMI (mac1) */
- {
- .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
- .src_nentries = 0,
- .src_sz_max = 2048,
- .dest_nentries = 0,
- },
-
- /* CE8: target autonomous hif_memcpy */
- {
- .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
- .src_nentries = 0,
- .src_sz_max = 0,
- .dest_nentries = 0,
- },
-
-};
-
-const struct ce_attr ath12k_host_ce_config_ipq5332[] = {
- /* CE0: host->target HTC control and raw streams */
- {
- .flags = CE_ATTR_FLAGS,
- .src_nentries = 16,
- .src_sz_max = 2048,
- .dest_nentries = 0,
- },
- /* CE1: target->host HTT + HTC control */
- {
- .flags = CE_ATTR_FLAGS,
- .src_nentries = 0,
- .src_sz_max = 2048,
- .dest_nentries = 512,
- .recv_cb = ath12k_htc_rx_completion_handler,
- },
- /* CE2: target->host WMI */
- {
- .flags = CE_ATTR_FLAGS,
- .src_nentries = 0,
- .src_sz_max = 2048,
- .dest_nentries = 128,
- .recv_cb = ath12k_htc_rx_completion_handler,
- },
- /* CE3: host->target WMI */
- {
- .flags = CE_ATTR_FLAGS,
- .src_nentries = 32,
- .src_sz_max = 2048,
- .dest_nentries = 0,
- },
- /* CE4: host->target HTT */
- {
- .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
- .src_nentries = 2048,
- .src_sz_max = 256,
- .dest_nentries = 0,
- },
- /* CE5: target -> host PKTLOG */
- {
- .flags = CE_ATTR_FLAGS,
- .src_nentries = 0,
- .src_sz_max = 2048,
- .dest_nentries = 512,
- .recv_cb = ath12k_dp_htt_htc_t2h_msg_handler,
- },
- /* CE6: Target autonomous HIF_memcpy */
- {
- .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
- .src_nentries = 0,
- .src_sz_max = 0,
- .dest_nentries = 0,
- },
- /* CE7: CV Prefetch */
- {
- .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
- .src_nentries = 0,
- .src_sz_max = 0,
- .dest_nentries = 0,
- },
- /* CE8: Target HIF memcpy (Generic HIF memcypy) */
- {
- .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
- .src_nentries = 0,
- .src_sz_max = 0,
- .dest_nentries = 0,
- },
- /* CE9: WMI logging/CFR/Spectral/Radar */
- {
- .flags = CE_ATTR_FLAGS,
- .src_nentries = 0,
- .src_sz_max = 2048,
- .dest_nentries = 128,
- },
- /* CE10: Unused */
- {
- .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
- .src_nentries = 0,
- .src_sz_max = 0,
- .dest_nentries = 0,
- },
- /* CE11: Unused */
- {
- .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
- .src_nentries = 0,
- .src_sz_max = 0,
- .dest_nentries = 0,
- },
-};
-
static int ath12k_ce_rx_buf_enqueue_pipe(struct ath12k_ce_pipe *pipe,
struct sk_buff *skb, dma_addr_t paddr)
{
@@ -341,7 +40,7 @@ static int ath12k_ce_rx_buf_enqueue_pipe(struct ath12k_ce_pipe *pipe,
goto exit;
}
- ath12k_hal_ce_dst_set_desc(desc, paddr);
+ ath12k_hal_ce_dst_set_desc(&ab->hal, desc, paddr);
ring->skb[write_index] = skb;
write_index = CE_RING_IDX_INCR(nentries_mask, write_index);
@@ -434,7 +133,7 @@ static int ath12k_ce_completed_recv_next(struct ath12k_ce_pipe *pipe,
goto err;
}
- *nbytes = ath12k_hal_ce_dst_status_get_length(desc);
+ *nbytes = ath12k_hal_ce_dst_status_get_length(&ab->hal, desc);
*skb = pipe->dest_ring->skb[sw_index];
pipe->dest_ring->skb[sw_index] = NULL;
@@ -666,6 +365,7 @@ ath12k_ce_alloc_ring(struct ath12k_base *ab, int nentries, int desc_sz)
static int ath12k_ce_alloc_pipe(struct ath12k_base *ab, int ce_id)
{
+ struct ath12k_hal *hal = &ab->hal;
struct ath12k_ce_pipe *pipe = &ab->ce.ce_pipe[ce_id];
const struct ce_attr *attr = &ab->hw_params->host_ce_config[ce_id];
struct ath12k_ce_ring *ring;
@@ -677,7 +377,7 @@ static int ath12k_ce_alloc_pipe(struct ath12k_base *ab, int ce_id)
if (attr->src_nentries) {
pipe->send_cb = ath12k_ce_send_done_cb;
nentries = roundup_pow_of_two(attr->src_nentries);
- desc_sz = ath12k_hal_ce_get_desc_size(HAL_CE_DESC_SRC);
+ desc_sz = ath12k_hal_ce_get_desc_size(hal, HAL_CE_DESC_SRC);
ring = ath12k_ce_alloc_ring(ab, nentries, desc_sz);
if (IS_ERR(ring))
return PTR_ERR(ring);
@@ -687,13 +387,13 @@ static int ath12k_ce_alloc_pipe(struct ath12k_base *ab, int ce_id)
if (attr->dest_nentries) {
pipe->recv_cb = attr->recv_cb;
nentries = roundup_pow_of_two(attr->dest_nentries);
- desc_sz = ath12k_hal_ce_get_desc_size(HAL_CE_DESC_DST);
+ desc_sz = ath12k_hal_ce_get_desc_size(hal, HAL_CE_DESC_DST);
ring = ath12k_ce_alloc_ring(ab, nentries, desc_sz);
if (IS_ERR(ring))
return PTR_ERR(ring);
pipe->dest_ring = ring;
- desc_sz = ath12k_hal_ce_get_desc_size(HAL_CE_DESC_DST_STATUS);
+ desc_sz = ath12k_hal_ce_get_desc_size(hal, HAL_CE_DESC_DST_STATUS);
ring = ath12k_ce_alloc_ring(ab, nentries, desc_sz);
if (IS_ERR(ring))
return PTR_ERR(ring);
@@ -786,7 +486,7 @@ int ath12k_ce_send(struct ath12k_base *ab, struct sk_buff *skb, u8 pipe_id,
if (pipe->attr_flags & CE_ATTR_BYTE_SWAP_DATA)
byte_swap_data = 1;
- ath12k_hal_ce_src_set_desc(desc, ATH12K_SKB_CB(skb)->paddr,
+ ath12k_hal_ce_src_set_desc(&ab->hal, desc, ATH12K_SKB_CB(skb)->paddr,
skb->len, transfer_id, byte_swap_data);
pipe->src_ring->skb[write_index] = skb;
@@ -972,6 +672,7 @@ int ath12k_ce_init_pipes(struct ath12k_base *ab)
void ath12k_ce_free_pipes(struct ath12k_base *ab)
{
+ struct ath12k_hal *hal = &ab->hal;
struct ath12k_ce_pipe *pipe;
int desc_sz;
int i;
@@ -980,7 +681,8 @@ void ath12k_ce_free_pipes(struct ath12k_base *ab)
pipe = &ab->ce.ce_pipe[i];
if (pipe->src_ring) {
- desc_sz = ath12k_hal_ce_get_desc_size(HAL_CE_DESC_SRC);
+ desc_sz = ath12k_hal_ce_get_desc_size(hal,
+ HAL_CE_DESC_SRC);
dma_free_coherent(ab->dev,
pipe->src_ring->nentries * desc_sz +
CE_DESC_RING_ALIGN,
@@ -991,7 +693,8 @@ void ath12k_ce_free_pipes(struct ath12k_base *ab)
}
if (pipe->dest_ring) {
- desc_sz = ath12k_hal_ce_get_desc_size(HAL_CE_DESC_DST);
+ desc_sz = ath12k_hal_ce_get_desc_size(hal,
+ HAL_CE_DESC_DST);
dma_free_coherent(ab->dev,
pipe->dest_ring->nentries * desc_sz +
CE_DESC_RING_ALIGN,
@@ -1003,7 +706,8 @@ void ath12k_ce_free_pipes(struct ath12k_base *ab)
if (pipe->status_ring) {
desc_sz =
- ath12k_hal_ce_get_desc_size(HAL_CE_DESC_DST_STATUS);
+ ath12k_hal_ce_get_desc_size(hal,
+ HAL_CE_DESC_DST_STATUS);
dma_free_coherent(ab->dev,
pipe->status_ring->nentries * desc_sz +
CE_DESC_RING_ALIGN,
diff --git a/drivers/net/wireless/ath/ath12k/ce.h b/drivers/net/wireless/ath/ath12k/ce.h
index 57f75899ee03..df4f2a4f8480 100644
--- a/drivers/net/wireless/ath/ath12k/ce.h
+++ b/drivers/net/wireless/ath/ath12k/ce.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-2022, 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH12K_CE_H
@@ -85,6 +85,7 @@ struct ce_ie_addr {
struct ce_remap {
u32 base;
u32 size;
+ u32 cmem_offset;
};
struct ce_attr {
@@ -173,10 +174,6 @@ struct ath12k_ce {
struct ath12k_hp_update_timer hp_timer[CE_COUNT_MAX];
};
-extern const struct ce_attr ath12k_host_ce_config_qcn9274[];
-extern const struct ce_attr ath12k_host_ce_config_wcn7850[];
-extern const struct ce_attr ath12k_host_ce_config_ipq5332[];
-
void ath12k_ce_cleanup_pipes(struct ath12k_base *ab);
void ath12k_ce_rx_replenish_retry(struct timer_list *t);
void ath12k_ce_per_engine_service(struct ath12k_base *ab, u16 ce_id);
diff --git a/drivers/net/wireless/ath/ath12k/cmn_defs.h b/drivers/net/wireless/ath/ath12k/cmn_defs.h
new file mode 100644
index 000000000000..20208ffea1c9
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/cmn_defs.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef ATH12K_CMN_DEFS_H
+#define ATH12K_CMN_DEFS_H
+
+#include <net/mac80211.h>
+
+#define MAX_RADIOS 2
+#define ATH12K_MAX_DEVICES 3
+#define ATH12K_GROUP_MAX_RADIO (ATH12K_MAX_DEVICES * MAX_RADIOS)
+
+#define ATH12K_SCAN_MAX_LINKS ATH12K_GROUP_MAX_RADIO
+/* Define 1 scan link for each radio for parallel scan purposes */
+#define ATH12K_NUM_MAX_LINKS (IEEE80211_MLD_MAX_NUM_LINKS + ATH12K_SCAN_MAX_LINKS)
+
+#define MAX_MU_GROUP_ID 64
+#endif
diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
index cc352eef1939..9d6c50a94e64 100644
--- a/drivers/net/wireless/ath/ath12k/core.c
+++ b/drivers/net/wireless/ath/ath12k/core.c
@@ -21,15 +21,18 @@
#include "hif.h"
#include "pci.h"
#include "wow.h"
+#include "dp_cmn.h"
+#include "peer.h"
-static int ahb_err, pci_err;
unsigned int ath12k_debug_mask;
module_param_named(debug_mask, ath12k_debug_mask, uint, 0644);
MODULE_PARM_DESC(debug_mask, "Debugging mask");
+EXPORT_SYMBOL(ath12k_debug_mask);
bool ath12k_ftm_mode;
module_param_named(ftm_mode, ath12k_ftm_mode, bool, 0444);
MODULE_PARM_DESC(ftm_mode, "Boots up in factory test mode");
+EXPORT_SYMBOL(ath12k_ftm_mode);
/* protected with ath12k_hw_group_mutex */
static struct list_head ath12k_hw_group_list = LIST_HEAD_INIT(ath12k_hw_group_list);
@@ -632,6 +635,7 @@ u32 ath12k_core_get_max_peers_per_radio(struct ath12k_base *ab)
{
return ath12k_core_get_max_station_per_radio(ab) + TARGET_NUM_VDEVS(ab);
}
+EXPORT_SYMBOL(ath12k_core_get_max_peers_per_radio);
struct reserved_mem *ath12k_core_get_reserved_mem(struct ath12k_base *ab,
int index)
@@ -700,6 +704,8 @@ void ath12k_core_to_group_ref_put(struct ath12k_base *ab)
static void ath12k_core_stop(struct ath12k_base *ab)
{
+ ath12k_link_sta_rhash_tbl_destroy(ab);
+
ath12k_core_to_group_ref_put(ab);
if (!test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags))
@@ -710,7 +716,7 @@ static void ath12k_core_stop(struct ath12k_base *ab)
ath12k_dp_rx_pdev_reo_cleanup(ab);
ath12k_hif_stop(ab);
ath12k_wmi_detach(ab);
- ath12k_dp_free(ab);
+ ath12k_dp_cmn_device_deinit(ath12k_ab_to_dp(ab));
/* De-Init of components as needed */
}
@@ -895,7 +901,7 @@ static int ath12k_core_start(struct ath12k_base *ab)
goto err_hif_stop;
}
- ret = ath12k_dp_htt_connect(&ab->dp);
+ ret = ath12k_dp_htt_connect(ath12k_ab_to_dp(ab));
if (ret) {
ath12k_err(ab, "failed to connect to HTT: %d\n", ret);
goto err_hif_stop;
@@ -920,7 +926,7 @@ static int ath12k_core_start(struct ath12k_base *ab)
goto err_hif_stop;
}
- ath12k_dp_cc_config(ab);
+ ath12k_hal_cc_config(ab);
ret = ath12k_dp_rx_pdev_reo_setup(ab);
if (ret) {
@@ -928,8 +934,6 @@ static int ath12k_core_start(struct ath12k_base *ab)
goto err_hif_stop;
}
- ath12k_dp_hal_rx_desc_init(ab);
-
ret = ath12k_wmi_cmd_init(ab);
if (ret) {
ath12k_err(ab, "failed to send wmi init cmd: %d\n", ret);
@@ -964,6 +968,12 @@ static int ath12k_core_start(struct ath12k_base *ab)
/* Indicate the core start in the appropriate group */
ath12k_core_to_group_ref_get(ab);
+ ret = ath12k_link_sta_rhash_tbl_init(ab);
+ if (ret) {
+ ath12k_warn(ab, "failed to init peer addr rhash table %d\n", ret);
+ goto err_reo_cleanup;
+ }
+
return 0;
err_reo_cleanup:
@@ -1288,7 +1298,7 @@ int ath12k_core_qmi_firmware_ready(struct ath12k_base *ab)
goto err_firmware_stop;
}
- ret = ath12k_dp_alloc(ab);
+ ret = ath12k_dp_cmn_device_init(ath12k_ab_to_dp(ab));
if (ret) {
ath12k_err(ab, "failed to init DP: %d\n", ret);
goto err_firmware_stop;
@@ -1300,7 +1310,7 @@ int ath12k_core_qmi_firmware_ready(struct ath12k_base *ab)
ret = ath12k_core_start(ab);
if (ret) {
ath12k_err(ab, "failed to start core: %d\n", ret);
- goto err_dp_free;
+ goto err_deinit;
}
mutex_unlock(&ab->core_lock);
@@ -1333,8 +1343,8 @@ err_core_stop:
mutex_unlock(&ag->mutex);
goto exit;
-err_dp_free:
- ath12k_dp_free(ab);
+err_deinit:
+ ath12k_dp_cmn_device_deinit(ath12k_ab_to_dp(ab));
mutex_unlock(&ab->core_lock);
mutex_unlock(&ag->mutex);
@@ -1350,13 +1360,14 @@ static int ath12k_core_reconfigure_on_crash(struct ath12k_base *ab)
int ret, total_vdev;
mutex_lock(&ab->core_lock);
+ ath12k_link_sta_rhash_tbl_destroy(ab);
ath12k_dp_pdev_free(ab);
ath12k_ce_cleanup_pipes(ab);
ath12k_wmi_detach(ab);
ath12k_dp_rx_pdev_reo_cleanup(ab);
mutex_unlock(&ab->core_lock);
- ath12k_dp_free(ab);
+ ath12k_dp_cmn_device_deinit(ath12k_ab_to_dp(ab));
ath12k_hal_srng_deinit(ab);
total_vdev = ab->num_radios * TARGET_NUM_VDEVS(ab);
ab->free_vdev_map = (1LL << total_vdev) - 1;
@@ -1565,6 +1576,7 @@ static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
ath12k_core_halt(ar);
}
+ ath12k_mac_dp_peer_cleanup(ah);
break;
case ATH12K_HW_STATE_OFF:
ath12k_warn(ab,
@@ -1739,17 +1751,11 @@ enum ath12k_qmi_mem_mode ath12k_core_get_memory_mode(struct ath12k_base *ab)
return ATH12K_QMI_MEMORY_MODE_DEFAULT;
}
+EXPORT_SYMBOL(ath12k_core_get_memory_mode);
int ath12k_core_pre_init(struct ath12k_base *ab)
{
const struct ath12k_mem_profile_based_param *param;
- int ret;
-
- ret = ath12k_hw_init(ab);
- if (ret) {
- ath12k_err(ab, "failed to init hw params: %d\n", ret);
- return ret;
- }
param = &ath12k_mem_profile_based_param[ab->target_mem_mode];
ab->profile_param = param;
@@ -1996,6 +2002,8 @@ exit:
ag->ab[ab->device_id] = ab;
ab->ag = ag;
+ ath12k_dp_cmn_hw_group_assign(ath12k_ab_to_dp(ab), ag);
+
ath12k_dbg(ab, ATH12K_DBG_BOOT, "wsi group-id %d num-devices %d index %d",
ag->id, ag->num_devices, wsi->index);
@@ -2023,6 +2031,8 @@ void ath12k_core_hw_group_unassign(struct ath12k_base *ab)
return;
}
+ ath12k_dp_cmn_hw_group_unassign(ath12k_ab_to_dp(ab), ag);
+
ag->ab[device_id] = NULL;
ab->ag = NULL;
ab->device_id = ATH12K_INVALID_DEVICE_ID;
@@ -2253,7 +2263,6 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
spin_lock_init(&ab->base_lock);
init_completion(&ab->reset_complete);
- INIT_LIST_HEAD(&ab->peers);
init_waitqueue_head(&ab->peer_mapping_wq);
init_waitqueue_head(&ab->wmi_ab.tx_credits_wq);
INIT_WORK(&ab->restart_work, ath12k_core_restart);
@@ -2291,31 +2300,5 @@ err_sc_free:
return NULL;
}
-static int ath12k_init(void)
-{
- ahb_err = ath12k_ahb_init();
- if (ahb_err)
- pr_warn("Failed to initialize ath12k AHB device: %d\n", ahb_err);
-
- pci_err = ath12k_pci_init();
- if (pci_err)
- pr_warn("Failed to initialize ath12k PCI device: %d\n", pci_err);
-
- /* If both failed, return one of the failures (arbitrary) */
- return ahb_err && pci_err ? ahb_err : 0;
-}
-
-static void ath12k_exit(void)
-{
- if (!pci_err)
- ath12k_pci_exit();
-
- if (!ahb_err)
- ath12k_ahb_exit();
-}
-
-module_init(ath12k_init);
-module_exit(ath12k_exit);
-
-MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11be WLAN devices");
+MODULE_DESCRIPTION("Driver support for Qualcomm Technologies WLAN devices");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index 3c1e0069be1e..990934ec92fc 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -18,6 +18,7 @@
#include <linux/panic_notifier.h>
#include <linux/average.h>
#include <linux/of.h>
+#include <linux/rhashtable.h>
#include "qmi.h"
#include "htc.h"
#include "wmi.h"
@@ -26,7 +27,6 @@
#include "ce.h"
#include "mac.h"
#include "hw.h"
-#include "hal_rx.h"
#include "reg.h"
#include "dbring.h"
#include "fw.h"
@@ -34,6 +34,8 @@
#include "wow.h"
#include "debugfs_htt_stats.h"
#include "coredump.h"
+#include "cmn_defs.h"
+#include "dp_cmn.h"
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@@ -64,8 +66,6 @@
#define ATH12K_RECONFIGURE_TIMEOUT_HZ (10 * HZ)
#define ATH12K_RECOVER_START_TIMEOUT_HZ (20 * HZ)
-#define ATH12K_MAX_DEVICES 3
-#define ATH12K_GROUP_MAX_RADIO (ATH12K_MAX_DEVICES * MAX_RADIOS)
#define ATH12K_INVALID_GROUP_ID 0xFF
#define ATH12K_INVALID_DEVICE_ID 0xFF
@@ -155,6 +155,7 @@ enum ath12k_hw_rev {
ATH12K_HW_QCN9274_HW20,
ATH12K_HW_WCN7850_HW20,
ATH12K_HW_IPQ5332_HW10,
+ ATH12K_HW_QCC2072_HW10,
};
enum ath12k_firmware_mode {
@@ -310,16 +311,9 @@ struct ath12k_link_vif {
u32 vdev_id;
u32 beacon_interval;
u32 dtim_period;
- u16 ast_hash;
- u16 ast_idx;
- u16 tcl_metadata;
- u8 hal_addr_search_flags;
- u8 search_type;
struct ath12k *ar;
- int bank_id;
- u8 vdev_id_check_en;
bool beacon_prot;
struct wmi_wmm_params_all_arg wmm_params;
@@ -360,6 +354,8 @@ struct ath12k_link_vif {
};
struct ath12k_vif {
+ struct ath12k_dp_vif dp_vif;
+
enum wmi_vdev_type vdev_type;
enum wmi_vdev_subtype vdev_subtype;
struct ieee80211_vif *vif;
@@ -383,10 +379,7 @@ struct ath12k_vif {
} u;
u32 aid;
- u32 key_cipher;
- u8 tx_encap_type;
bool ps;
- atomic_t mcbc_gsn;
struct ath12k_link_vif deflink;
struct ath12k_link_vif __rcu *link[ATH12K_NUM_MAX_LINKS];
@@ -407,51 +400,8 @@ struct ath12k_vif_iter {
struct ath12k_link_vif *arvif;
};
-#define HAL_AST_IDX_INVALID 0xFFFF
-#define HAL_RX_MAX_MCS 12
-#define HAL_RX_MAX_MCS_HT 31
-#define HAL_RX_MAX_MCS_VHT 9
-#define HAL_RX_MAX_MCS_HE 11
-#define HAL_RX_MAX_MCS_BE 15
-#define HAL_RX_MAX_NSS 8
-#define HAL_RX_MAX_NUM_LEGACY_RATES 12
-
#define ATH12K_SCAN_TIMEOUT_HZ (20 * HZ)
-struct ath12k_rx_peer_rate_stats {
- u64 ht_mcs_count[HAL_RX_MAX_MCS_HT + 1];
- u64 vht_mcs_count[HAL_RX_MAX_MCS_VHT + 1];
- u64 he_mcs_count[HAL_RX_MAX_MCS_HE + 1];
- u64 be_mcs_count[HAL_RX_MAX_MCS_BE + 1];
- u64 nss_count[HAL_RX_MAX_NSS];
- u64 bw_count[HAL_RX_BW_MAX];
- u64 gi_count[HAL_RX_GI_MAX];
- u64 legacy_count[HAL_RX_MAX_NUM_LEGACY_RATES];
- u64 rx_rate[HAL_RX_BW_MAX][HAL_RX_GI_MAX][HAL_RX_MAX_NSS][HAL_RX_MAX_MCS_HT + 1];
-};
-
-struct ath12k_rx_peer_stats {
- u64 num_msdu;
- u64 num_mpdu_fcs_ok;
- u64 num_mpdu_fcs_err;
- u64 tcp_msdu_count;
- u64 udp_msdu_count;
- u64 other_msdu_count;
- u64 ampdu_msdu_count;
- u64 non_ampdu_msdu_count;
- u64 stbc_count;
- u64 beamformed_count;
- u64 coding_count[HAL_RX_SU_MU_CODING_MAX];
- u64 tid_count[IEEE80211_NUM_TIDS + 1];
- u64 pream_cnt[HAL_RX_PREAMBLE_MAX];
- u64 reception_type[HAL_RX_RECEPTION_TYPE_MAX];
- u64 rx_duration;
- u64 dcm_count;
- u64 ru_alloc_cnt[HAL_RX_RU_ALLOC_TYPE_MAX];
- struct ath12k_rx_peer_rate_stats pkt_stats;
- struct ath12k_rx_peer_rate_stats byte_stats;
-};
-
#define ATH12K_HE_MCS_NUM 12
#define ATH12K_VHT_MCS_NUM 10
#define ATH12K_BW_NUM 5
@@ -533,12 +483,6 @@ struct ath12k_per_ppdu_tx_stats {
u32 retry_bytes;
};
-struct ath12k_wbm_tx_stats {
- u64 wbm_tx_comp_stats[HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX];
-};
-
-DECLARE_EWMA(avg_rssi, 10, 8)
-
struct ath12k_link_sta {
struct ath12k_link_vif *arvif;
struct ath12k_sta *ahsta;
@@ -553,15 +497,7 @@ struct ath12k_link_sta {
u32 smps;
struct wiphy_work update_wk;
- struct rate_info txrate;
- struct rate_info last_txrate;
- u64 rx_duration;
- u64 tx_duration;
- u8 rssi_comb;
- struct ewma_avg_rssi avg_rssi;
u8 link_id;
- struct ath12k_rx_peer_stats *rx_stats;
- struct ath12k_wbm_tx_stats *wbm_tx_stats;
u32 bw_prev;
u32 peer_nss;
s8 rssi_beacon;
@@ -572,14 +508,9 @@ struct ath12k_link_sta {
/* for firmware use only */
u8 link_idx;
- u32 tx_retry_failed;
- u32 tx_retry_count;
-};
-struct ath12k_reoq_buf {
- void *vaddr;
- dma_addr_t paddr_aligned;
- u32 size;
+ /* peer addr based rhashtable list pointer */
+ struct rhash_head rhash_addr;
};
struct ath12k_sta {
@@ -594,8 +525,6 @@ struct ath12k_sta {
u8 num_peer;
enum ieee80211_sta_state state;
-
- struct ath12k_reoq_buf reoq_bufs[IEEE80211_NUM_TIDS + 1];
};
#define ATH12K_HALF_20MHZ_BW 10
@@ -667,23 +596,6 @@ struct ath12k_debug {
bool extd_rx_stats;
};
-struct ath12k_per_peer_tx_stats {
- u32 succ_bytes;
- u32 retry_bytes;
- u32 failed_bytes;
- u32 duration;
- u16 succ_pkts;
- u16 retry_pkts;
- u16 failed_pkts;
- u16 ru_start;
- u16 ru_tones;
- u8 ba_fails;
- u8 ppdu_type;
- u32 mu_grpid;
- u32 mu_pos;
- bool is_ampdu;
-};
-
struct ath12k_pdev_rssi_offsets {
s32 temp_offset;
s8 min_nf_dbm;
@@ -809,9 +721,6 @@ struct ath12k {
struct ath12k_wow wow;
struct completion target_suspend;
bool target_suspend_ack;
- struct ath12k_per_peer_tx_stats peer_tx_stats;
- struct list_head ppdu_stats_info;
- u32 ppdu_stat_list_depth;
struct ath12k_per_peer_tx_stats cached_stats;
u32 last_ppdu_id;
@@ -866,8 +775,7 @@ struct ath12k_hw {
DECLARE_BITMAP(free_ml_peer_id_map, ATH12K_MAX_MLO_PEERS);
- /* protected by wiphy_lock() */
- struct list_head ml_peers;
+ struct ath12k_dp_hw dp_hw;
/* Keep last */
struct ath12k radio[] __aligned(sizeof(void *));
@@ -941,32 +849,6 @@ struct ath12k_board_data {
size_t len;
};
-struct ath12k_device_dp_tx_err_stats {
- /* TCL Ring Descriptor unavailable */
- u32 desc_na[DP_TCL_NUM_RING_MAX];
- /* Other failures during dp_tx due to mem allocation failure
- * idr unavailable etc.
- */
- atomic_t misc_fail;
-};
-
-struct ath12k_device_dp_stats {
- u32 err_ring_pkts;
- u32 invalid_rbm;
- u32 rxdma_error[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX];
- u32 reo_error[HAL_REO_DEST_RING_ERROR_CODE_MAX];
- u32 hal_reo_error[DP_REO_DST_RING_MAX];
- struct ath12k_device_dp_tx_err_stats tx_err;
- u32 reo_rx[DP_REO_DST_RING_MAX][ATH12K_MAX_DEVICES];
- u32 rx_wbm_rel_source[HAL_WBM_REL_SRC_MODULE_MAX][ATH12K_MAX_DEVICES];
- u32 tqm_rel_reason[MAX_TQM_RELEASE_REASON];
- u32 fw_tx_status[MAX_FW_TX_STATUS];
- u32 tx_wbm_rel_source[HAL_WBM_REL_SRC_MODULE_MAX];
- u32 tx_enqueued[DP_TCL_NUM_RING_MAX];
- u32 tx_completed[DP_TCL_NUM_RING_MAX];
- u32 reo_excep_msdu_buf_type;
-};
-
struct ath12k_reg_freq {
u32 start_freq;
u32 end_freq;
@@ -987,6 +869,11 @@ struct ath12k_hw_link {
* wiphy, protected with struct ath12k_hw_group::mutex.
*/
struct ath12k_hw_group {
+ /* Keep dp_hw_grp as the first member to allow efficient
+ * usage of cache lines for DP fields
+ */
+ struct ath12k_dp_hw_group dp_hw_grp;
+ struct ath12k_hw_link hw_links[ATH12K_GROUP_MAX_RADIO];
struct list_head list;
u8 id;
u8 num_devices;
@@ -1009,7 +896,6 @@ struct ath12k_hw_group {
bool mlo_capable;
struct device_node *wsi_node[ATH12K_MAX_DEVICES];
struct ath12k_mlo_memory mlo_mem;
- struct ath12k_hw_link hw_links[ATH12K_GROUP_MAX_RADIO];
bool hw_link_id_init_done;
};
@@ -1035,6 +921,12 @@ struct ath12k_mem_profile_based_param {
struct ath12k_dp_profile_params dp_params;
};
+enum ath12k_device_family {
+ ATH12K_DEVICE_FAMILY_START,
+ ATH12K_DEVICE_FAMILY_WIFI7 = ATH12K_DEVICE_FAMILY_START,
+ ATH12K_DEVICE_FAMILY_MAX,
+};
+
/* Master structure to hold the hw data which may be used in core module */
struct ath12k_base {
enum ath12k_hw_rev hw_rev;
@@ -1054,13 +946,14 @@ struct ath12k_base {
struct ath12k_htc htc;
- struct ath12k_dp dp;
+ struct ath12k_dp *dp;
void __iomem *mem;
unsigned long mem_len;
void __iomem *mem_ce;
u32 ce_remap_base_addr;
+ u32 cmem_offset;
bool ce_remap;
struct {
@@ -1105,7 +998,6 @@ struct ath12k_base {
struct ath12k_wmi_hal_reg_capabilities_ext_arg hal_reg_cap[MAX_RADIOS];
unsigned long long free_vdev_map;
unsigned long long free_vdev_stats_id_map;
- struct list_head peers;
wait_queue_head_t peer_mapping_wq;
u8 mac_addr[ETH_ALEN];
bool wmi_ready;
@@ -1135,7 +1027,6 @@ struct ath12k_base {
/* Current DFS Regulatory */
enum ath12k_dfs_region dfs_region;
- struct ath12k_device_dp_stats device_stats;
#ifdef CONFIG_ATH12K_DEBUGFS
struct dentry *debugfs_soc;
#endif
@@ -1191,13 +1082,13 @@ struct ath12k_base {
size_t amss_dualmac_len;
const u8 *m3_data;
size_t m3_len;
+ const u8 *aux_uc_data;
+ size_t aux_uc_len;
DECLARE_BITMAP(fw_features, ATH12K_FW_FEATURE_COUNT);
bool fw_features_valid;
} fw;
- const struct hal_rx_ops *hal_rx_ops;
-
struct completion restart_completed;
#ifdef CONFIG_ACPI
@@ -1241,6 +1132,14 @@ struct ath12k_base {
const struct ath12k_mem_profile_based_param *profile_param;
enum ath12k_qmi_mem_mode target_mem_mode;
+ /* FIXME: Define this field in a ag equivalent object available
+ * during the initial phase of probe later.
+ */
+ const struct ieee80211_ops *ath12k_ops;
+
+ struct rhashtable *rhead_sta_addr;
+ struct rhashtable_params rhash_sta_addr_param;
+
/* must be last */
u8 drv_priv[] __aligned(sizeof(void *));
};
@@ -1516,4 +1415,18 @@ static inline s32 ath12k_pdev_get_noise_floor(struct ath12k *ar)
return ar->rssi_info.noise_floor;
}
+/* The @ab->dp NULL check or assertion is intentionally omitted because
+ * @ab->dp is guaranteed to be non-NULL after a successful probe and
+ * remains valid until teardown. Invoking this before allocation or
+ * after teardown is considered invalid usage.
+ */
+static inline struct ath12k_dp *ath12k_ab_to_dp(struct ath12k_base *ab)
+{
+ return ab->dp;
+}
+
+static inline struct ath12k *ath12k_pdev_dp_to_ar(struct ath12k_pdev_dp *dp)
+{
+ return container_of(dp, struct ath12k, dp);
+}
#endif /* _CORE_H_ */
diff --git a/drivers/net/wireless/ath/ath12k/dbring.c b/drivers/net/wireless/ath/ath12k/dbring.c
index 6604dacea2ae..f71ec2a58469 100644
--- a/drivers/net/wireless/ath/ath12k/dbring.c
+++ b/drivers/net/wireless/ath/ath12k/dbring.c
@@ -1,12 +1,12 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include "core.h"
#include "debug.h"
+#include "hal.h"
static int ath12k_dbring_bufs_replenish(struct ath12k *ar,
struct ath12k_dbring *ring,
@@ -55,7 +55,7 @@ static int ath12k_dbring_bufs_replenish(struct ath12k *ar,
cookie = u32_encode_bits(ar->pdev_idx, DP_RXDMA_BUF_COOKIE_PDEV_ID) |
u32_encode_bits(buf_id, DP_RXDMA_BUF_COOKIE_BUF_ID);
- ath12k_hal_rx_buf_addr_info_set(desc, paddr, cookie, 0);
+ ath12k_hal_rx_buf_addr_info_set(&ab->hal, desc, paddr, cookie, 0);
ath12k_hal_srng_access_end(ab, srng);
@@ -298,7 +298,7 @@ int ath12k_dbring_buffer_release_event(struct ath12k_base *ab,
num_buff_reaped++;
- ath12k_hal_rx_buf_addr_info_get(&desc, &paddr, &cookie, &rbm);
+ ath12k_hal_rx_buf_addr_info_get(&ab->hal, &desc, &paddr, &cookie, &rbm);
buf_id = u32_get_bits(cookie, DP_RXDMA_BUF_COOKIE_BUF_ID);
diff --git a/drivers/net/wireless/ath/ath12k/debug.c b/drivers/net/wireless/ath/ath12k/debug.c
index 5ce100cd9a9d..34b3b2c920dc 100644
--- a/drivers/net/wireless/ath/ath12k/debug.c
+++ b/drivers/net/wireless/ath/ath12k/debug.c
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
*/
#include <linux/vmalloc.h>
@@ -21,6 +22,7 @@ void ath12k_info(struct ath12k_base *ab, const char *fmt, ...)
/* TODO: Trace the log */
va_end(args);
}
+EXPORT_SYMBOL(ath12k_info);
void ath12k_err(struct ath12k_base *ab, const char *fmt, ...)
{
@@ -35,6 +37,7 @@ void ath12k_err(struct ath12k_base *ab, const char *fmt, ...)
/* TODO: Trace the log */
va_end(args);
}
+EXPORT_SYMBOL(ath12k_err);
void __ath12k_warn(struct device *dev, const char *fmt, ...)
{
@@ -49,6 +52,7 @@ void __ath12k_warn(struct device *dev, const char *fmt, ...)
/* TODO: Trace the log */
va_end(args);
}
+EXPORT_SYMBOL(__ath12k_warn);
#ifdef CONFIG_ATH12K_DEBUG
@@ -72,6 +76,7 @@ void __ath12k_dbg(struct ath12k_base *ab, enum ath12k_debug_mask mask,
va_end(args);
}
+EXPORT_SYMBOL(__ath12k_dbg);
void ath12k_dbg_dump(struct ath12k_base *ab,
enum ath12k_debug_mask mask,
@@ -100,5 +105,6 @@ void ath12k_dbg_dump(struct ath12k_base *ab,
}
}
}
+EXPORT_SYMBOL(ath12k_dbg_dump);
#endif /* CONFIG_ATH12K_DEBUG */
diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c
index d6a86f075d73..358031fa14eb 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs.c
+++ b/drivers/net/wireless/ath/ath12k/debugfs.c
@@ -967,7 +967,7 @@ static int ath12k_open_link_stats(struct inode *inode, struct file *file)
"\nlink[%d] Tx Frame descriptor Encrypt Type = ",
link_id);
- for (i = 0; i < HAL_ENCRYPT_TYPE_MAX; i++) {
+ for (i = 0; i < DP_ENCRYPT_TYPE_MAX; i++) {
len += scnprintf(buf + len, buf_len - len,
" %d:%d", i,
linkstat.tx_encrypt_type[i]);
@@ -1020,13 +1020,15 @@ void ath12k_debugfs_op_vif_add(struct ieee80211_hw *hw,
debugfs_create_file("link_stats", 0400, vif->debugfs_dir, ahvif,
&ath12k_fops_link_stats);
}
+EXPORT_SYMBOL(ath12k_debugfs_op_vif_add);
static ssize_t ath12k_debugfs_dump_device_dp_stats(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath12k_base *ab = file->private_data;
- struct ath12k_device_dp_stats *device_stats = &ab->device_stats;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_device_dp_stats *device_stats = &dp->device_stats;
int len = 0, i, j, ret;
struct ath12k *ar;
const int size = 4096;
@@ -1155,6 +1157,7 @@ static ssize_t ath12k_debugfs_dump_device_dp_stats(struct file *file,
len += scnprintf(buf + len, size - len, "\n");
+ rcu_read_lock();
for (i = 0; i < ab->num_radios; i++) {
ar = ath12k_mac_get_ar_by_pdev_id(ab, DP_SW2HW_MACID(i));
if (ar) {
@@ -1163,6 +1166,7 @@ static ssize_t ath12k_debugfs_dump_device_dp_stats(struct file *file,
atomic_read(&ar->dp.num_tx_pending));
}
}
+ rcu_read_unlock();
len += scnprintf(buf + len, size - len, "\nREO Rx Received:\n");
diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c
index 48b010a1b756..7f6ca07fb335 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c
+++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.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-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/vmalloc.h>
@@ -29,8 +29,10 @@ print_array_to_buf_index(u8 *buf, u32 offset, const char *header, u32 stats_inde
" %u:%u,", stats_index++, le32_to_cpu(array[i]));
}
/* To overwrite the last trailing comma */
- index--;
- *(buf + offset + index) = '\0';
+ if (array_len > 0) {
+ index--;
+ *(buf + offset + index) = '\0';
+ }
if (footer) {
index += scnprintf(buf + offset + index,
@@ -5537,6 +5539,189 @@ ath12k_htt_print_pdev_rtt_tbr_cmd_res_stats_tlv(const void *tag_buf, u16 tag_len
stats_req->buf_len = len;
}
+static void
+ath12k_htt_print_rx_pdev_fw_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct htt_rx_pdev_fw_stats_tlv *htt_stats_buf = tag_buf;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u32 len = stats_req->buf_len;
+ u8 *buf = stats_req->buf;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_RX_PDEV_FW_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n",
+ le32_to_cpu(htt_stats_buf->mac_id__word) & 0xFF);
+ len += scnprintf(buf + len, buf_len - len, "ppdu_recvd = %u\n",
+ le32_to_cpu(htt_stats_buf->ppdu_recvd));
+ len += scnprintf(buf + len, buf_len - len, "mpdu_cnt_fcs_ok = %u\n",
+ le32_to_cpu(htt_stats_buf->mpdu_cnt_fcs_ok));
+ len += scnprintf(buf + len, buf_len - len, "mpdu_cnt_fcs_err = %u\n",
+ le32_to_cpu(htt_stats_buf->mpdu_cnt_fcs_err));
+ len += scnprintf(buf + len, buf_len - len, "tcp_msdu_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->tcp_msdu_cnt));
+ len += scnprintf(buf + len, buf_len - len, "tcp_ack_msdu_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->tcp_ack_msdu_cnt));
+ len += scnprintf(buf + len, buf_len - len, "udp_msdu_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->udp_msdu_cnt));
+ len += scnprintf(buf + len, buf_len - len, "other_msdu_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->other_msdu_cnt));
+ len += scnprintf(buf + len, buf_len - len, "fw_ring_mpdu_ind = %u\n",
+ le32_to_cpu(htt_stats_buf->fw_ring_mpdu_ind));
+ len += print_array_to_buf(buf, len, "fw_ring_mgmt_subtype",
+ htt_stats_buf->fw_ring_mgmt_subtype,
+ ATH12K_HTT_STATS_SUBTYPE_MAX, "\n");
+ len += print_array_to_buf(buf, len, "fw_ring_ctrl_subtype",
+ htt_stats_buf->fw_ring_ctrl_subtype,
+ ATH12K_HTT_STATS_SUBTYPE_MAX, "\n");
+ len += scnprintf(buf + len, buf_len - len, "fw_ring_mcast_data_msdu = %u\n",
+ le32_to_cpu(htt_stats_buf->fw_ring_mcast_data_msdu));
+ len += scnprintf(buf + len, buf_len - len, "fw_ring_bcast_data_msdu = %u\n",
+ le32_to_cpu(htt_stats_buf->fw_ring_bcast_data_msdu));
+ len += scnprintf(buf + len, buf_len - len, "fw_ring_ucast_data_msdu = %u\n",
+ le32_to_cpu(htt_stats_buf->fw_ring_ucast_data_msdu));
+ len += scnprintf(buf + len, buf_len - len, "fw_ring_null_data_msdu = %u\n",
+ le32_to_cpu(htt_stats_buf->fw_ring_null_data_msdu));
+ len += scnprintf(buf + len, buf_len - len, "fw_ring_mpdu_drop = %u\n",
+ le32_to_cpu(htt_stats_buf->fw_ring_mpdu_drop));
+ len += scnprintf(buf + len, buf_len - len, "ofld_local_data_ind_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->ofld_local_data_ind_cnt));
+ len += scnprintf(buf + len, buf_len - len,
+ "ofld_local_data_buf_recycle_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->ofld_local_data_buf_recycle_cnt));
+ len += scnprintf(buf + len, buf_len - len, "drx_local_data_ind_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->drx_local_data_ind_cnt));
+ len += scnprintf(buf + len, buf_len - len,
+ "drx_local_data_buf_recycle_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->drx_local_data_buf_recycle_cnt));
+ len += scnprintf(buf + len, buf_len - len, "local_nondata_ind_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->local_nondata_ind_cnt));
+ len += scnprintf(buf + len, buf_len - len, "local_nondata_buf_recycle_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->local_nondata_buf_recycle_cnt));
+ len += scnprintf(buf + len, buf_len - len, "fw_status_buf_ring_refill_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->fw_status_buf_ring_refill_cnt));
+ len += scnprintf(buf + len, buf_len - len, "fw_status_buf_ring_empty_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->fw_status_buf_ring_empty_cnt));
+ len += scnprintf(buf + len, buf_len - len, "fw_pkt_buf_ring_refill_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->fw_pkt_buf_ring_refill_cnt));
+ len += scnprintf(buf + len, buf_len - len, "fw_pkt_buf_ring_empty_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->fw_pkt_buf_ring_empty_cnt));
+ len += scnprintf(buf + len, buf_len - len, "fw_link_buf_ring_refill_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->fw_link_buf_ring_refill_cnt));
+ len += scnprintf(buf + len, buf_len - len, "fw_link_buf_ring_empty_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->fw_link_buf_ring_empty_cnt));
+ len += scnprintf(buf + len, buf_len - len, "host_pkt_buf_ring_refill_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->host_pkt_buf_ring_refill_cnt));
+ len += scnprintf(buf + len, buf_len - len, "host_pkt_buf_ring_empty_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->host_pkt_buf_ring_empty_cnt));
+ len += scnprintf(buf + len, buf_len - len, "mon_pkt_buf_ring_refill_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->mon_pkt_buf_ring_refill_cnt));
+ len += scnprintf(buf + len, buf_len - len, "mon_pkt_buf_ring_empty_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->mon_pkt_buf_ring_empty_cnt));
+ len += scnprintf(buf + len, buf_len - len,
+ "mon_status_buf_ring_refill_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->mon_status_buf_ring_refill_cnt));
+ len += scnprintf(buf + len, buf_len - len, "mon_status_buf_ring_empty_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->mon_status_buf_ring_empty_cnt));
+ len += scnprintf(buf + len, buf_len - len, "mon_desc_buf_ring_refill_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->mon_desc_buf_ring_refill_cnt));
+ len += scnprintf(buf + len, buf_len - len, "mon_desc_buf_ring_empty_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->mon_desc_buf_ring_empty_cnt));
+ len += scnprintf(buf + len, buf_len - len, "mon_dest_ring_update_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->mon_dest_ring_update_cnt));
+ len += scnprintf(buf + len, buf_len - len, "mon_dest_ring_full_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->mon_dest_ring_full_cnt));
+ len += scnprintf(buf + len, buf_len - len, "rx_suspend_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->rx_suspend_cnt));
+ len += scnprintf(buf + len, buf_len - len, "rx_suspend_fail_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->rx_suspend_fail_cnt));
+ len += scnprintf(buf + len, buf_len - len, "rx_resume_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->rx_resume_cnt));
+ len += scnprintf(buf + len, buf_len - len, "rx_resume_fail_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->rx_resume_fail_cnt));
+ len += scnprintf(buf + len, buf_len - len, "rx_ring_switch_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->rx_ring_switch_cnt));
+ len += scnprintf(buf + len, buf_len - len, "rx_ring_restore_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->rx_ring_restore_cnt));
+ len += scnprintf(buf + len, buf_len - len, "rx_flush_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->rx_flush_cnt));
+ len += scnprintf(buf + len, buf_len - len, "rx_recovery_reset_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->rx_recovery_reset_cnt));
+ len += scnprintf(buf + len, buf_len - len, "rx_lwm_prom_filter_dis = %u\n",
+ le32_to_cpu(htt_stats_buf->rx_lwm_prom_filter_dis));
+ len += scnprintf(buf + len, buf_len - len, "rx_hwm_prom_filter_en = %u\n",
+ le32_to_cpu(htt_stats_buf->rx_hwm_prom_filter_en));
+ len += scnprintf(buf + len, buf_len - len, "bytes_received_low_32 = %u\n",
+ le32_to_cpu(htt_stats_buf->bytes_received_low_32));
+ len += scnprintf(buf + len, buf_len - len, "bytes_received_high_32 = %u\n",
+ le32_to_cpu(htt_stats_buf->bytes_received_high_32));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_hwq_stats_cmn_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct htt_tx_hwq_stats_cmn_tlv *htt_stats_buf = tag_buf;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u32 len = stats_req->buf_len;
+ u8 *buf = stats_req->buf;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_TX_HWQ_STATS_CMN_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n",
+ le32_to_cpu(htt_stats_buf->mac_id__hwq_id__word) & 0xFF);
+ len += scnprintf(buf + len, buf_len - len, "hwq_id = %u\n",
+ (le32_to_cpu(htt_stats_buf->mac_id__hwq_id__word) & 0xFF00) >> 8);
+ len += scnprintf(buf + len, buf_len - len, "xretry = %u\n",
+ le32_to_cpu(htt_stats_buf->xretry));
+ len += scnprintf(buf + len, buf_len - len, "underrun_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->underrun_cnt));
+ len += scnprintf(buf + len, buf_len - len, "flush_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->flush_cnt));
+ len += scnprintf(buf + len, buf_len - len, "filt_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->filt_cnt));
+ len += scnprintf(buf + len, buf_len - len, "null_mpdu_bmap = %u\n",
+ le32_to_cpu(htt_stats_buf->null_mpdu_bmap));
+ len += scnprintf(buf + len, buf_len - len, "user_ack_failure = %u\n",
+ le32_to_cpu(htt_stats_buf->user_ack_failure));
+ len += scnprintf(buf + len, buf_len - len, "ack_tlv_proc = %u\n",
+ le32_to_cpu(htt_stats_buf->ack_tlv_proc));
+ len += scnprintf(buf + len, buf_len - len, "sched_id_proc = %u\n",
+ le32_to_cpu(htt_stats_buf->sched_id_proc));
+ len += scnprintf(buf + len, buf_len - len, "null_mpdu_tx_count = %u\n",
+ le32_to_cpu(htt_stats_buf->null_mpdu_tx_count));
+ len += scnprintf(buf + len, buf_len - len, "mpdu_bmap_not_recvd = %u\n",
+ le32_to_cpu(htt_stats_buf->mpdu_bmap_not_recvd));
+ len += scnprintf(buf + len, buf_len - len, "num_bar = %u\n",
+ le32_to_cpu(htt_stats_buf->num_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, "mpdu_tried_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->mpdu_tried_cnt));
+ len += scnprintf(buf + len, buf_len - len, "mpdu_queued_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->mpdu_queued_cnt));
+ len += scnprintf(buf + len, buf_len - len, "mpdu_ack_fail_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->mpdu_ack_fail_cnt));
+ len += scnprintf(buf + len, buf_len - len, "mpdu_filt_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->mpdu_filt_cnt));
+ len += scnprintf(buf + len, buf_len - len, "false_mpdu_ack_count = %u\n",
+ le32_to_cpu(htt_stats_buf->false_mpdu_ack_count));
+ len += scnprintf(buf + len, buf_len - len, "txq_timeout = %u\n",
+ le32_to_cpu(htt_stats_buf->txq_timeout));
+
+ 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)
@@ -5690,6 +5875,9 @@ static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab,
case HTT_STATS_SFM_CLIENT_USER_TAG:
ath12k_htt_print_sfm_client_user_tlv(tag_buf, len, stats_req);
break;
+ case HTT_STATS_RX_PDEV_FW_STATS_TAG:
+ ath12k_htt_print_rx_pdev_fw_stats_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;
@@ -5833,6 +6021,9 @@ static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab,
case HTT_STATS_PDEV_RTT_TBR_CMD_RESULT_STATS_TAG:
ath12k_htt_print_pdev_rtt_tbr_cmd_res_stats_tlv(tag_buf, len, stats_req);
break;
+ case HTT_STATS_TX_HWQ_CMN_TAG:
+ ath12k_htt_print_tx_hwq_stats_cmn_tlv(tag_buf, len, stats_req);
+ break;
default:
break;
}
diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h
index 9bd3a632b002..bfabe6500d44 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h
+++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h
@@ -1,12 +1,14 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef DEBUG_HTT_STATS_H
#define DEBUG_HTT_STATS_H
+#include "dp_htt.h"
+
#define ATH12K_HTT_STATS_BUF_SIZE (1024 * 512)
#define ATH12K_HTT_STATS_COOKIE_LSB GENMASK_ULL(31, 0)
#define ATH12K_HTT_STATS_COOKIE_MSB GENMASK_ULL(63, 32)
@@ -125,6 +127,8 @@ struct ath12k_htt_extd_stats_msg {
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_RX = 2,
+ ATH12K_DBG_HTT_EXT_STATS_PDEV_TX_HWQ = 3,
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,
@@ -171,6 +175,7 @@ enum ath12k_dbg_htt_tlv_tag {
HTT_STATS_TX_PDEV_SIFS_TAG = 2,
HTT_STATS_TX_PDEV_FLUSH_TAG = 3,
HTT_STATS_STRING_TAG = 5,
+ HTT_STATS_TX_HWQ_CMN_TAG = 6,
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,
@@ -186,6 +191,7 @@ enum ath12k_dbg_htt_tlv_tag {
HTT_STATS_TX_PDEV_MU_MIMO_STATS_TAG = 25,
HTT_STATS_SFM_CMN_TAG = 26,
HTT_STATS_SRING_STATS_TAG = 27,
+ HTT_STATS_RX_PDEV_FW_STATS_TAG = 28,
HTT_STATS_TX_PDEV_RATE_STATS_TAG = 34,
HTT_STATS_RX_PDEV_RATE_STATS_TAG = 35,
HTT_STATS_TX_PDEV_SCHEDULER_TXQ_STATS_TAG = 36,
@@ -2073,4 +2079,81 @@ struct ath12k_htt_stats_pdev_rtt_tbr_cmd_result_stats_tlv {
__le32 mu_res[ATH12K_HTT_FTYPE_MAX][ATH12K_HTT_MAX_SCH_CMD_RESULT];
} __packed;
+struct htt_rx_pdev_fw_stats_tlv {
+ __le32 mac_id__word;
+ __le32 ppdu_recvd;
+ __le32 mpdu_cnt_fcs_ok;
+ __le32 mpdu_cnt_fcs_err;
+ __le32 tcp_msdu_cnt;
+ __le32 tcp_ack_msdu_cnt;
+ __le32 udp_msdu_cnt;
+ __le32 other_msdu_cnt;
+ __le32 fw_ring_mpdu_ind;
+ __le32 fw_ring_mgmt_subtype[ATH12K_HTT_STATS_SUBTYPE_MAX];
+ __le32 fw_ring_ctrl_subtype[ATH12K_HTT_STATS_SUBTYPE_MAX];
+ __le32 fw_ring_mcast_data_msdu;
+ __le32 fw_ring_bcast_data_msdu;
+ __le32 fw_ring_ucast_data_msdu;
+ __le32 fw_ring_null_data_msdu;
+ __le32 fw_ring_mpdu_drop;
+ __le32 ofld_local_data_ind_cnt;
+ __le32 ofld_local_data_buf_recycle_cnt;
+ __le32 drx_local_data_ind_cnt;
+ __le32 drx_local_data_buf_recycle_cnt;
+ __le32 local_nondata_ind_cnt;
+ __le32 local_nondata_buf_recycle_cnt;
+ __le32 fw_status_buf_ring_refill_cnt;
+ __le32 fw_status_buf_ring_empty_cnt;
+ __le32 fw_pkt_buf_ring_refill_cnt;
+ __le32 fw_pkt_buf_ring_empty_cnt;
+ __le32 fw_link_buf_ring_refill_cnt;
+ __le32 fw_link_buf_ring_empty_cnt;
+ __le32 host_pkt_buf_ring_refill_cnt;
+ __le32 host_pkt_buf_ring_empty_cnt;
+ __le32 mon_pkt_buf_ring_refill_cnt;
+ __le32 mon_pkt_buf_ring_empty_cnt;
+ __le32 mon_status_buf_ring_refill_cnt;
+ __le32 mon_status_buf_ring_empty_cnt;
+ __le32 mon_desc_buf_ring_refill_cnt;
+ __le32 mon_desc_buf_ring_empty_cnt;
+ __le32 mon_dest_ring_update_cnt;
+ __le32 mon_dest_ring_full_cnt;
+ __le32 rx_suspend_cnt;
+ __le32 rx_suspend_fail_cnt;
+ __le32 rx_resume_cnt;
+ __le32 rx_resume_fail_cnt;
+ __le32 rx_ring_switch_cnt;
+ __le32 rx_ring_restore_cnt;
+ __le32 rx_flush_cnt;
+ __le32 rx_recovery_reset_cnt;
+ __le32 rx_lwm_prom_filter_dis;
+ __le32 rx_hwm_prom_filter_en;
+ __le32 bytes_received_low_32;
+ __le32 bytes_received_high_32;
+} __packed;
+
+struct htt_tx_hwq_stats_cmn_tlv {
+ __le32 mac_id__hwq_id__word;
+ __le32 xretry;
+ __le32 underrun_cnt;
+ __le32 flush_cnt;
+ __le32 filt_cnt;
+ __le32 null_mpdu_bmap;
+ __le32 user_ack_failure;
+ __le32 ack_tlv_proc;
+ __le32 sched_id_proc;
+ __le32 null_mpdu_tx_count;
+ __le32 mpdu_bmap_not_recvd;
+ __le32 num_bar;
+ __le32 rts;
+ __le32 cts2self;
+ __le32 qos_null;
+ __le32 mpdu_tried_cnt;
+ __le32 mpdu_queued_cnt;
+ __le32 mpdu_ack_fail_cnt;
+ __le32 mpdu_filt_cnt;
+ __le32 false_mpdu_ack_count;
+ __le32 txq_timeout;
+} __packed;
+
#endif
diff --git a/drivers/net/wireless/ath/ath12k/debugfs_sta.c b/drivers/net/wireless/ath/ath12k/debugfs_sta.c
index 5bd2bf4c9dac..585c40bd2951 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs_sta.c
+++ b/drivers/net/wireless/ath/ath12k/debugfs_sta.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
- * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/vmalloc.h>
@@ -11,6 +11,7 @@
#include "debug.h"
#include "debugfs_htt_stats.h"
#include "debugfs.h"
+#include "dp_cmn.h"
static
u32 ath12k_dbg_sta_dump_rate_stats(u8 *buf, u32 offset, const int size,
@@ -144,40 +145,40 @@ static ssize_t ath12k_dbg_sta_dump_rx_stats(struct file *file,
const int size = ATH12K_STA_RX_STATS_BUF_SIZE;
struct ath12k_hw *ah = ahsta->ahvif->ah;
struct ath12k_rx_peer_stats *rx_stats;
+ struct ath12k_dp_link_peer *link_peer;
struct ath12k_link_sta *arsta;
u8 link_id = link_sta->link_id;
int len = 0, i, ret = 0;
+ struct ath12k_dp *dp;
bool he_rates_avail;
struct ath12k *ar;
- wiphy_lock(ah->hw->wiphy);
+ guard(wiphy)(ah->hw->wiphy);
- if (!(BIT(link_id) & ahsta->links_map)) {
- wiphy_unlock(ah->hw->wiphy);
+ if (!(BIT(link_id) & ahsta->links_map))
return -ENOENT;
- }
arsta = wiphy_dereference(ah->hw->wiphy, ahsta->link[link_id]);
- if (!arsta || !arsta->arvif->ar) {
- wiphy_unlock(ah->hw->wiphy);
+ if (!arsta || !arsta->arvif->ar)
return -ENOENT;
- }
ar = arsta->arvif->ar;
u8 *buf __free(kfree) = kzalloc(size, GFP_KERNEL);
- if (!buf) {
- ret = -ENOENT;
- goto out;
- }
+ if (!buf)
+ return -ENOMEM;
- spin_lock_bh(&ar->ab->base_lock);
+ dp = ath12k_ab_to_dp(ar->ab);
- rx_stats = arsta->rx_stats;
- if (!rx_stats) {
- ret = -ENOENT;
- goto unlock;
- }
+ guard(spinlock_bh)(&dp->dp_lock);
+
+ link_peer = ath12k_dp_link_peer_find_by_addr(dp, arsta->addr);
+ if (!link_peer)
+ return -ENOENT;
+
+ rx_stats = link_peer->peer_stats.rx_stats;
+ if (!rx_stats)
+ return -ENOENT;
len += scnprintf(buf + len, size - len, "RX peer stats:\n\n");
len += scnprintf(buf + len, size - len, "Num of MSDUs: %llu\n",
@@ -237,13 +238,8 @@ static ssize_t ath12k_dbg_sta_dump_rx_stats(struct file *file,
len += ath12k_dbg_sta_dump_rate_stats(buf, len, size, he_rates_avail,
&rx_stats->byte_stats);
-unlock:
- spin_unlock_bh(&ar->ab->base_lock);
-
if (len)
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
-out:
- wiphy_unlock(ah->hw->wiphy);
return ret;
}
@@ -261,10 +257,9 @@ static ssize_t ath12k_dbg_sta_reset_rx_stats(struct file *file,
struct ieee80211_link_sta *link_sta = file->private_data;
struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(link_sta->sta);
struct ath12k_hw *ah = ahsta->ahvif->ah;
- struct ath12k_rx_peer_stats *rx_stats;
- struct ath12k_link_sta *arsta;
u8 link_id = link_sta->link_id;
- struct ath12k *ar;
+ struct ath12k_link_sta *arsta;
+ struct ath12k_dp *dp;
bool reset;
int ret;
@@ -288,19 +283,9 @@ static ssize_t ath12k_dbg_sta_reset_rx_stats(struct file *file,
goto out;
}
- ar = arsta->arvif->ar;
-
- spin_lock_bh(&ar->ab->base_lock);
-
- rx_stats = arsta->rx_stats;
- if (!rx_stats) {
- spin_unlock_bh(&ar->ab->base_lock);
- ret = -ENOENT;
- goto out;
- }
+ dp = ath12k_ab_to_dp(arsta->arvif->ar->ab);
- memset(rx_stats, 0, sizeof(*rx_stats));
- spin_unlock_bh(&ar->ab->base_lock);
+ ath12k_dp_link_peer_reset_rx_stats(dp, arsta->addr);
ret = count;
out:
@@ -335,3 +320,4 @@ void ath12k_debugfs_link_sta_op_add(struct ieee80211_hw *hw,
&fops_reset_rx_stats);
}
}
+EXPORT_SYMBOL(ath12k_debugfs_link_sta_op_add);
diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c
index 4a54b8c35311..ab54c8a84d3e 100644
--- a/drivers/net/wireless/ath/ath12k/dp.c
+++ b/drivers/net/wireless/ath/ath12k/dp.c
@@ -1,63 +1,58 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <crypto/hash.h>
#include "core.h"
#include "dp_tx.h"
-#include "hal_tx.h"
#include "hif.h"
+#include "hal.h"
#include "debug.h"
-#include "dp_rx.h"
#include "peer.h"
-#include "dp_mon.h"
+#include "dp_cmn.h"
enum ath12k_dp_desc_type {
ATH12K_DP_TX_DESC,
ATH12K_DP_RX_DESC,
};
-static void ath12k_dp_htt_htc_tx_complete(struct ath12k_base *ab,
- struct sk_buff *skb)
-{
- dev_kfree_skb_any(skb);
-}
-
void ath12k_dp_peer_cleanup(struct ath12k *ar, int vdev_id, const u8 *addr)
{
struct ath12k_base *ab = ar->ab;
- struct ath12k_peer *peer;
+ struct ath12k_dp_link_peer *peer;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
/* TODO: Any other peer specific DP cleanup */
- spin_lock_bh(&ab->base_lock);
- peer = ath12k_peer_find(ab, vdev_id, addr);
- if (!peer) {
+ spin_lock_bh(&dp->dp_lock);
+ peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, addr);
+ if (!peer || !peer->dp_peer) {
ath12k_warn(ab, "failed to lookup peer %pM on vdev %d\n",
addr, vdev_id);
- spin_unlock_bh(&ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
return;
}
if (!peer->primary_link) {
- spin_unlock_bh(&ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
return;
}
ath12k_dp_rx_peer_tid_cleanup(ar, peer);
- crypto_free_shash(peer->tfm_mmic);
- peer->dp_setup_done = false;
- spin_unlock_bh(&ab->base_lock);
+ crypto_free_shash(peer->dp_peer->tfm_mmic);
+ peer->dp_peer->dp_setup_done = false;
+ spin_unlock_bh(&dp->dp_lock);
}
int ath12k_dp_peer_setup(struct ath12k *ar, int vdev_id, const u8 *addr)
{
struct ath12k_base *ab = ar->ab;
- struct ath12k_peer *peer;
+ struct ath12k_dp_link_peer *peer;
u32 reo_dest;
int ret = 0, tid;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
/* NOTE: reo_dest ring id starts from 1 unlike mac_id which starts from 0 */
reo_dest = ar->dp.mac_id + 1;
@@ -92,19 +87,19 @@ int ath12k_dp_peer_setup(struct ath12k *ar, int vdev_id, const u8 *addr)
return 0;
peer_clean:
- spin_lock_bh(&ab->base_lock);
+ spin_lock_bh(&dp->dp_lock);
- peer = ath12k_peer_find(ab, vdev_id, addr);
+ peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, addr);
if (!peer) {
ath12k_warn(ab, "failed to find the peer to del rx tid\n");
- spin_unlock_bh(&ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
return -ENOENT;
}
for (tid--; tid >= 0; tid--)
- ath12k_dp_rx_peer_tid_delete(ar, peer, tid);
+ ath12k_dp_arch_rx_peer_tid_delete(dp, peer, tid);
- spin_unlock_bh(&ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
return ret;
}
@@ -147,7 +142,7 @@ static int ath12k_dp_srng_calculate_msi_group(struct ath12k_base *ab,
grp_mask = &ab->hw_params->ring_mask->rx_wbm_rel[0];
ring_num = 0;
} else {
- map = ab->hw_params->hal_ops->tcl_to_wbm_rbm_map;
+ map = ab->hal.tcl_to_wbm_rbm_map;
for (i = 0; i < ab->hw_params->max_tx_ring; i++) {
if (ring_num == map[i].wbm_ring_num) {
ring_num = i;
@@ -338,50 +333,6 @@ int ath12k_dp_srng_setup(struct ath12k_base *ab, struct dp_srng *ring,
return 0;
}
-static
-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 (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(ahvif->key_cipher),
- HAL_TX_BANK_CONFIG_ENCRYPT_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) |
- u32_encode_bits(0, HAL_TX_BANK_CONFIG_EPD);
-
- /* only valid if idx_lookup_override is not set in tcl_data_cmd */
- if (ahvif->vdev_type == WMI_VDEV_TYPE_STA)
- bank_config |= u32_encode_bits(1, HAL_TX_BANK_CONFIG_INDEX_LOOKUP_EN);
- else
- bank_config |= u32_encode_bits(0, HAL_TX_BANK_CONFIG_INDEX_LOOKUP_EN);
-
- bank_config |= u32_encode_bits(arvif->hal_addr_search_flags & HAL_TX_ADDRX_EN,
- HAL_TX_BANK_CONFIG_ADDRX_EN) |
- u32_encode_bits(!!(arvif->hal_addr_search_flags &
- HAL_TX_ADDRY_EN),
- HAL_TX_BANK_CONFIG_ADDRY_EN);
-
- 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);
-
- bank_config |= u32_encode_bits(0, HAL_TX_BANK_CONFIG_DSCP_TIP_MAP_ID);
-
- return bank_config;
-}
-
static int ath12k_dp_tx_get_bank_profile(struct ath12k_base *ab,
struct ath12k_link_vif *arvif,
struct ath12k_dp *dp)
@@ -392,7 +343,7 @@ static int ath12k_dp_tx_get_bank_profile(struct ath12k_base *ab,
bool configure_register = false;
/* convert vdev params into hal_tx_bank_config */
- bank_config = ath12k_dp_tx_get_vdev_bank_config(ab, arvif);
+ bank_config = ath12k_dp_arch_tx_get_vdev_bank_config(dp, arvif);
spin_lock_bh(&dp->tx_bank_lock);
/* TODO: implement using idr kernel framework*/
@@ -424,7 +375,8 @@ inc_ref_and_return:
spin_unlock_bh(&dp->tx_bank_lock);
if (configure_register)
- ath12k_hal_tx_configure_bank_register(ab, bank_config, bank_id);
+ ath12k_hal_tx_configure_bank_register(ab,
+ bank_config, bank_id);
ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "dp_htt tcl bank_id %d input 0x%x match 0x%x num_users %u",
bank_id, bank_config, dp->bank_profiles[bank_id].bank_config,
@@ -442,7 +394,7 @@ void ath12k_dp_tx_put_bank_profile(struct ath12k_dp *dp, u8 bank_id)
static void ath12k_dp_deinit_bank_profiles(struct ath12k_base *ab)
{
- struct ath12k_dp *dp = &ab->dp;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
kfree(dp->bank_profiles);
dp->bank_profiles = NULL;
@@ -450,7 +402,7 @@ static void ath12k_dp_deinit_bank_profiles(struct ath12k_base *ab)
static int ath12k_dp_init_bank_profiles(struct ath12k_base *ab)
{
- struct ath12k_dp *dp = &ab->dp;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
u32 num_tcl_banks = ab->hw_params->num_tcl_banks;
int i;
@@ -473,7 +425,7 @@ static int ath12k_dp_init_bank_profiles(struct ath12k_base *ab)
static void ath12k_dp_srng_common_cleanup(struct ath12k_base *ab)
{
- struct ath12k_dp *dp = &ab->dp;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
int i;
ath12k_dp_srng_cleanup(ab, &dp->reo_status_ring);
@@ -490,7 +442,7 @@ static void ath12k_dp_srng_common_cleanup(struct ath12k_base *ab)
static int ath12k_dp_srng_common_setup(struct ath12k_base *ab)
{
- struct ath12k_dp *dp = &ab->dp;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
const struct ath12k_hal_tcl_to_wbm_rbm_map *map;
struct hal_srng *srng;
int i, ret, tx_comp_ring_num;
@@ -506,7 +458,7 @@ static int ath12k_dp_srng_common_setup(struct ath12k_base *ab)
}
for (i = 0; i < ab->hw_params->max_tx_ring; i++) {
- map = ab->hw_params->hal_ops->tcl_to_wbm_rbm_map;
+ map = ab->hal.tcl_to_wbm_rbm_map;
tx_comp_ring_num = map[i].wbm_ring_num;
ret = ath12k_dp_srng_setup(ab, &dp->tx_ring[i].tcl_data_ring,
@@ -596,7 +548,7 @@ err:
static void ath12k_dp_scatter_idle_link_desc_cleanup(struct ath12k_base *ab)
{
- struct ath12k_dp *dp = &ab->dp;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
struct hal_wbm_idle_scatter_list *slist = dp->scatter_list;
int i;
@@ -616,7 +568,7 @@ static int ath12k_dp_scatter_idle_link_desc_setup(struct ath12k_base *ab,
u32 n_link_desc,
u32 last_bank_sz)
{
- struct ath12k_dp *dp = &ab->dp;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
struct dp_link_desc_bank *link_desc_banks = dp->link_desc_banks;
struct hal_wbm_idle_scatter_list *slist = dp->scatter_list;
u32 n_entries_per_buf;
@@ -659,7 +611,7 @@ static int ath12k_dp_scatter_idle_link_desc_setup(struct ath12k_base *ab,
paddr = link_desc_banks[i].paddr;
while (n_entries) {
cookie = DP_LINK_DESC_COOKIE_SET(n_entries, i);
- ath12k_hal_set_link_desc_addr(scatter_buf, cookie,
+ ath12k_hal_set_link_desc_addr(dp->hal, scatter_buf, cookie,
paddr, rbm);
n_entries--;
paddr += HAL_LINK_DESC_SIZE;
@@ -710,7 +662,7 @@ static int ath12k_dp_link_desc_bank_alloc(struct ath12k_base *ab,
int n_link_desc_bank,
int last_bank_sz)
{
- struct ath12k_dp *dp = &ab->dp;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
int i;
int ret = 0;
int desc_sz = DP_LINK_DESC_ALLOC_SIZE_THRESH;
@@ -758,7 +710,7 @@ void ath12k_dp_link_desc_cleanup(struct ath12k_base *ab,
static int ath12k_wbm_idle_ring_setup(struct ath12k_base *ab, u32 *n_link_desc)
{
- struct ath12k_dp *dp = &ab->dp;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
u32 n_mpdu_link_desc, n_mpdu_queue_desc;
u32 n_tx_msdu_link_desc, n_rx_msdu_link_desc;
int ret = 0;
@@ -797,6 +749,7 @@ int ath12k_dp_link_desc_setup(struct ath12k_base *ab,
u32 ring_type, struct hal_srng *srng,
u32 n_link_desc)
{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
u32 tot_mem_sz;
u32 n_link_desc_bank, last_bank_sz;
u32 entry_sz, align_bytes, n_entries;
@@ -804,7 +757,7 @@ int ath12k_dp_link_desc_setup(struct ath12k_base *ab,
u32 paddr;
int i, ret;
u32 cookie;
- enum hal_rx_buf_return_buf_manager rbm = ab->dp.idle_link_rbm;
+ enum hal_rx_buf_return_buf_manager rbm = dp->idle_link_rbm;
tot_mem_sz = n_link_desc * HAL_LINK_DESC_SIZE;
tot_mem_sz += HAL_LINK_DESC_ALIGN;
@@ -865,7 +818,8 @@ int ath12k_dp_link_desc_setup(struct ath12k_base *ab,
while (n_entries &&
(desc = ath12k_hal_srng_src_get_next_entry(ab, srng))) {
cookie = DP_LINK_DESC_COOKIE_SET(n_entries, i);
- ath12k_hal_set_link_desc_addr(desc, cookie, paddr, rbm);
+ ath12k_hal_set_link_desc_addr(dp->hal, desc, cookie, paddr,
+ rbm);
n_entries--;
paddr += HAL_LINK_DESC_SIZE;
}
@@ -883,133 +837,18 @@ fail_desc_bank_free:
return ret;
}
-int ath12k_dp_service_srng(struct ath12k_base *ab,
- struct ath12k_ext_irq_grp *irq_grp,
- int budget)
+void ath12k_dp_pdev_free(struct ath12k_base *ab)
{
- struct napi_struct *napi = &irq_grp->napi;
- int grp_id = irq_grp->grp_id;
- int work_done = 0;
- int i = 0, j;
- int tot_work_done = 0;
- enum dp_monitor_mode monitor_mode;
- u8 ring_mask;
-
- if (ab->hw_params->ring_mask->tx[grp_id]) {
- i = fls(ab->hw_params->ring_mask->tx[grp_id]) - 1;
- ath12k_dp_tx_completion_handler(ab, i);
- }
-
- if (ab->hw_params->ring_mask->rx_err[grp_id]) {
- work_done = ath12k_dp_rx_process_err(ab, napi, budget);
- budget -= work_done;
- tot_work_done += work_done;
- if (budget <= 0)
- goto done;
- }
-
- if (ab->hw_params->ring_mask->rx_wbm_rel[grp_id]) {
- work_done = ath12k_dp_rx_process_wbm_err(ab,
- napi,
- budget);
- budget -= work_done;
- tot_work_done += work_done;
-
- if (budget <= 0)
- goto done;
- }
-
- if (ab->hw_params->ring_mask->rx[grp_id]) {
- i = fls(ab->hw_params->ring_mask->rx[grp_id]) - 1;
- work_done = ath12k_dp_rx_process(ab, i, napi,
- budget);
- budget -= work_done;
- tot_work_done += work_done;
- if (budget <= 0)
- goto done;
- }
-
- if (ab->hw_params->ring_mask->rx_mon_status[grp_id]) {
- ring_mask = ab->hw_params->ring_mask->rx_mon_status[grp_id];
- for (i = 0; i < ab->num_radios; i++) {
- for (j = 0; j < ab->hw_params->num_rxdma_per_pdev; j++) {
- int id = i * ab->hw_params->num_rxdma_per_pdev + j;
-
- if (ring_mask & BIT(id)) {
- work_done =
- ath12k_dp_mon_process_ring(ab, id, napi, budget,
- 0);
- budget -= work_done;
- tot_work_done += work_done;
- if (budget <= 0)
- goto done;
- }
- }
- }
- }
-
- if (ab->hw_params->ring_mask->rx_mon_dest[grp_id]) {
- monitor_mode = ATH12K_DP_RX_MONITOR_MODE;
- ring_mask = ab->hw_params->ring_mask->rx_mon_dest[grp_id];
- for (i = 0; i < ab->num_radios; i++) {
- for (j = 0; j < ab->hw_params->num_rxdma_per_pdev; j++) {
- int id = i * ab->hw_params->num_rxdma_per_pdev + j;
-
- if (ring_mask & BIT(id)) {
- work_done =
- ath12k_dp_mon_process_ring(ab, id, napi, budget,
- monitor_mode);
- budget -= work_done;
- tot_work_done += work_done;
-
- if (budget <= 0)
- goto done;
- }
- }
- }
- }
-
- if (ab->hw_params->ring_mask->tx_mon_dest[grp_id]) {
- monitor_mode = ATH12K_DP_TX_MONITOR_MODE;
- ring_mask = ab->hw_params->ring_mask->tx_mon_dest[grp_id];
- for (i = 0; i < ab->num_radios; i++) {
- for (j = 0; j < ab->hw_params->num_rxdma_per_pdev; j++) {
- int id = i * ab->hw_params->num_rxdma_per_pdev + j;
-
- if (ring_mask & BIT(id)) {
- work_done =
- ath12k_dp_mon_process_ring(ab, id, napi, budget,
- monitor_mode);
- budget -= work_done;
- tot_work_done += work_done;
-
- if (budget <= 0)
- goto done;
- }
- }
- }
- }
-
- if (ab->hw_params->ring_mask->reo_status[grp_id])
- ath12k_dp_rx_process_reo_status(ab);
-
- if (ab->hw_params->ring_mask->host2rxdma[grp_id]) {
- struct ath12k_dp *dp = &ab->dp;
- struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring;
- LIST_HEAD(list);
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k *ar;
+ int i;
- ath12k_dp_rx_bufs_replenish(ab, rx_ring, &list, 0);
+ for (i = 0; i < ab->num_radios; i++) {
+ ar = ab->pdevs[i].ar;
+ rcu_assign_pointer(dp->dp_pdevs[ar->pdev_idx], NULL);
}
- /* TODO: Implement handler for other interrupts */
-
-done:
- return tot_work_done;
-}
-
-void ath12k_dp_pdev_free(struct ath12k_base *ab)
-{
- int i;
+ synchronize_rcu();
for (i = 0; i < ab->num_radios; i++)
ath12k_dp_rx_pdev_free(ab, i);
@@ -1025,31 +864,10 @@ void ath12k_dp_pdev_pre_alloc(struct ath12k *ar)
/* TODO: Add any RXDMA setup required per pdev */
}
-bool ath12k_dp_wmask_compaction_rx_tlv_supported(struct ath12k_base *ab)
-{
- if (test_bit(WMI_TLV_SERVICE_WMSK_COMPACTION_RX_TLVS, ab->wmi_ab.svc_map) &&
- ab->hw_params->hal_ops->rxdma_ring_wmask_rx_mpdu_start &&
- ab->hw_params->hal_ops->rxdma_ring_wmask_rx_msdu_end &&
- ab->hw_params->hal_ops->get_hal_rx_compact_ops) {
- return true;
- }
- return false;
-}
-
-void ath12k_dp_hal_rx_desc_init(struct ath12k_base *ab)
-{
- if (ath12k_dp_wmask_compaction_rx_tlv_supported(ab)) {
- /* RX TLVS compaction is supported, hence change the hal_rx_ops
- * to compact hal_rx_ops.
- */
- ab->hal_rx_ops = ab->hw_params->hal_ops->get_hal_rx_compact_ops();
- }
- ab->hal.hal_desc_sz =
- ab->hal_rx_ops->rx_desc_get_desc_size();
-}
-
int ath12k_dp_pdev_alloc(struct ath12k_base *ab)
{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_pdev_dp *dp_pdev;
struct ath12k *ar;
int ret;
int i;
@@ -1061,6 +879,14 @@ int ath12k_dp_pdev_alloc(struct ath12k_base *ab)
/* TODO: Per-pdev rx ring unlike tx ring which is mapped to different AC's */
for (i = 0; i < ab->num_radios; i++) {
ar = ab->pdevs[i].ar;
+
+ dp_pdev = &ar->dp;
+
+ dp_pdev->hw = ar->ah->hw;
+ dp_pdev->dp = dp;
+ dp_pdev->hw_link_id = ar->hw_link_id;
+ dp_pdev->dp_hw = &ar->ah->dp_hw;
+
ret = ath12k_dp_rx_pdev_alloc(ab, i);
if (ret) {
ath12k_warn(ab, "failed to allocate pdev rx for pdev_id :%d\n",
@@ -1074,6 +900,11 @@ int ath12k_dp_pdev_alloc(struct ath12k_base *ab)
}
}
+ for (i = 0; i < ab->num_radios; i++) {
+ ar = ab->pdevs[i].ar;
+ rcu_assign_pointer(dp->dp_pdevs[ar->pdev_idx], &ar->dp);
+ }
+
return 0;
err:
ath12k_dp_pdev_free(ab);
@@ -1081,40 +912,23 @@ out:
return ret;
}
-int ath12k_dp_htt_connect(struct ath12k_dp *dp)
+static void ath12k_dp_update_vdev_search(struct ath12k_link_vif *arvif)
{
- struct ath12k_htc_svc_conn_req conn_req = {};
- struct ath12k_htc_svc_conn_resp conn_resp = {};
- int status;
-
- conn_req.ep_ops.ep_tx_complete = ath12k_dp_htt_htc_tx_complete;
- conn_req.ep_ops.ep_rx_complete = ath12k_dp_htt_htc_t2h_msg_handler;
-
- /* connect to control service */
- conn_req.service_id = ATH12K_HTC_SVC_ID_HTT_DATA_MSG;
-
- status = ath12k_htc_connect_service(&dp->ab->htc, &conn_req,
- &conn_resp);
-
- if (status)
- return status;
-
- dp->eid = conn_resp.eid;
+ u8 link_id = arvif->link_id;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ath12k_dp_link_vif *dp_link_vif;
- return 0;
-}
+ dp_link_vif = ath12k_dp_vif_to_dp_link_vif(&ahvif->dp_vif, link_id);
-static void ath12k_dp_update_vdev_search(struct ath12k_link_vif *arvif)
-{
switch (arvif->ahvif->vdev_type) {
case WMI_VDEV_TYPE_STA:
- arvif->hal_addr_search_flags = HAL_TX_ADDRY_EN;
- arvif->search_type = HAL_TX_ADDR_SEARCH_INDEX;
+ dp_link_vif->hal_addr_search_flags = HAL_TX_ADDRY_EN;
+ dp_link_vif->search_type = HAL_TX_ADDR_SEARCH_DEFAULT;
break;
case WMI_VDEV_TYPE_AP:
case WMI_VDEV_TYPE_IBSS:
- arvif->hal_addr_search_flags = HAL_TX_ADDRX_EN;
- arvif->search_type = HAL_TX_ADDR_SEARCH_DEFAULT;
+ dp_link_vif->hal_addr_search_flags = HAL_TX_ADDRX_EN;
+ dp_link_vif->search_type = HAL_TX_ADDR_SEARCH_DEFAULT;
break;
case WMI_VDEV_TYPE_MONITOR:
default:
@@ -1125,22 +939,29 @@ static void ath12k_dp_update_vdev_search(struct ath12k_link_vif *arvif)
void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_link_vif *arvif)
{
struct ath12k_base *ab = ar->ab;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ u8 link_id = arvif->link_id;
+ int bank_id;
+ struct ath12k_dp_link_vif *dp_link_vif;
+
+ dp_link_vif = ath12k_dp_vif_to_dp_link_vif(&ahvif->dp_vif, link_id);
- arvif->tcl_metadata |= u32_encode_bits(1, HTT_TCL_META_DATA_TYPE) |
- u32_encode_bits(arvif->vdev_id,
- HTT_TCL_META_DATA_VDEV_ID) |
- u32_encode_bits(ar->pdev->pdev_id,
- HTT_TCL_META_DATA_PDEV_ID);
+ dp_link_vif->tcl_metadata |= u32_encode_bits(1, HTT_TCL_META_DATA_TYPE) |
+ u32_encode_bits(arvif->vdev_id,
+ HTT_TCL_META_DATA_VDEV_ID) |
+ u32_encode_bits(ar->pdev->pdev_id,
+ HTT_TCL_META_DATA_PDEV_ID);
/* set HTT extension valid bit to 0 by default */
- arvif->tcl_metadata &= ~HTT_TCL_META_DATA_VALID_HTT;
+ dp_link_vif->tcl_metadata &= ~HTT_TCL_META_DATA_VALID_HTT;
ath12k_dp_update_vdev_search(arvif);
- arvif->vdev_id_check_en = true;
- arvif->bank_id = ath12k_dp_tx_get_bank_profile(ab, arvif, &ab->dp);
+ dp_link_vif->vdev_id_check_en = true;
+ bank_id = ath12k_dp_tx_get_bank_profile(ab, arvif, ath12k_ab_to_dp(ab));
+ dp_link_vif->bank_id = bank_id;
/* TODO: error path for bank id failure */
- if (arvif->bank_id == DP_INVALID_BANK_ID) {
+ if (bank_id == DP_INVALID_BANK_ID) {
ath12k_err(ar->ab, "Failed to initialize DP TX Banks");
return;
}
@@ -1150,7 +971,7 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
{
struct ath12k_rx_desc_info *desc_info;
struct ath12k_tx_desc_info *tx_desc_info, *tmp1;
- struct ath12k_dp *dp = &ab->dp;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
struct ath12k_skb_cb *skb_cb;
struct sk_buff *skb;
struct ath12k *ar;
@@ -1273,15 +1094,13 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
static void ath12k_dp_reoq_lut_cleanup(struct ath12k_base *ab)
{
- struct ath12k_dp *dp = &ab->dp;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
if (!ab->hw_params->reoq_lut_support)
return;
if (dp->reoq_lut.vaddr_unaligned) {
- ath12k_hif_write32(ab,
- HAL_SEQ_WCSS_UMAC_REO_REG +
- HAL_REO1_QDESC_LUT_BASE0(ab), 0);
+ ath12k_hal_write_reoq_lut_addr(ab, 0);
dma_free_coherent(ab->dev, dp->reoq_lut.size,
dp->reoq_lut.vaddr_unaligned,
dp->reoq_lut.paddr_unaligned);
@@ -1289,9 +1108,7 @@ static void ath12k_dp_reoq_lut_cleanup(struct ath12k_base *ab)
}
if (dp->ml_reoq_lut.vaddr_unaligned) {
- ath12k_hif_write32(ab,
- HAL_SEQ_WCSS_UMAC_REO_REG +
- HAL_REO1_QDESC_LUT_BASE1(ab), 0);
+ ath12k_hal_write_ml_reoq_lut_addr(ab, 0);
dma_free_coherent(ab->dev, dp->ml_reoq_lut.size,
dp->ml_reoq_lut.vaddr_unaligned,
dp->ml_reoq_lut.paddr_unaligned);
@@ -1299,11 +1116,13 @@ static void ath12k_dp_reoq_lut_cleanup(struct ath12k_base *ab)
}
}
-void ath12k_dp_free(struct ath12k_base *ab)
+static void ath12k_dp_cleanup(struct ath12k_base *ab)
{
- struct ath12k_dp *dp = &ab->dp;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
int i;
+ ath12k_dp_link_peer_rhash_tbl_destroy(dp);
+
if (!dp->ab)
return;
@@ -1324,60 +1143,6 @@ void ath12k_dp_free(struct ath12k_base *ab)
ath12k_dp_rx_free(ab);
/* Deinit any SOC level resource */
- dp->ab = NULL;
-}
-
-void ath12k_dp_cc_config(struct ath12k_base *ab)
-{
- u32 cmem_base = ab->qmi.dev_mem[ATH12K_QMI_DEVMEM_CMEM_INDEX].start;
- u32 reo_base = HAL_SEQ_WCSS_UMAC_REO_REG;
- u32 wbm_base = HAL_SEQ_WCSS_UMAC_WBM_REG;
- u32 val = 0;
-
- if (ath12k_ftm_mode)
- return;
-
- ath12k_hif_write32(ab, reo_base + HAL_REO1_SW_COOKIE_CFG0(ab), cmem_base);
-
- val |= u32_encode_bits(ATH12K_CMEM_ADDR_MSB,
- HAL_REO1_SW_COOKIE_CFG_CMEM_BASE_ADDR_MSB) |
- u32_encode_bits(ATH12K_CC_PPT_MSB,
- HAL_REO1_SW_COOKIE_CFG_COOKIE_PPT_MSB) |
- u32_encode_bits(ATH12K_CC_SPT_MSB,
- HAL_REO1_SW_COOKIE_CFG_COOKIE_SPT_MSB) |
- u32_encode_bits(1, HAL_REO1_SW_COOKIE_CFG_ALIGN) |
- u32_encode_bits(1, HAL_REO1_SW_COOKIE_CFG_ENABLE) |
- u32_encode_bits(1, HAL_REO1_SW_COOKIE_CFG_GLOBAL_ENABLE);
-
- ath12k_hif_write32(ab, reo_base + HAL_REO1_SW_COOKIE_CFG1(ab), val);
-
- /* Enable HW CC for WBM */
- ath12k_hif_write32(ab, wbm_base + HAL_WBM_SW_COOKIE_CFG0, cmem_base);
-
- val = u32_encode_bits(ATH12K_CMEM_ADDR_MSB,
- HAL_WBM_SW_COOKIE_CFG_CMEM_BASE_ADDR_MSB) |
- u32_encode_bits(ATH12K_CC_PPT_MSB,
- HAL_WBM_SW_COOKIE_CFG_COOKIE_PPT_MSB) |
- u32_encode_bits(ATH12K_CC_SPT_MSB,
- HAL_WBM_SW_COOKIE_CFG_COOKIE_SPT_MSB) |
- u32_encode_bits(1, HAL_WBM_SW_COOKIE_CFG_ALIGN);
-
- ath12k_hif_write32(ab, wbm_base + HAL_WBM_SW_COOKIE_CFG1, val);
-
- /* Enable conversion complete indication */
- val = ath12k_hif_read32(ab, wbm_base + HAL_WBM_SW_COOKIE_CFG2);
- val |= u32_encode_bits(1, HAL_WBM_SW_COOKIE_CFG_RELEASE_PATH_EN) |
- u32_encode_bits(1, HAL_WBM_SW_COOKIE_CFG_ERR_PATH_EN) |
- u32_encode_bits(1, HAL_WBM_SW_COOKIE_CFG_CONV_IND_EN);
-
- ath12k_hif_write32(ab, wbm_base + HAL_WBM_SW_COOKIE_CFG2, val);
-
- /* Enable Cookie conversion for WBM2SW Rings */
- val = ath12k_hif_read32(ab, wbm_base + HAL_WBM_SW_COOKIE_CONVERT_CFG);
- val |= u32_encode_bits(1, HAL_WBM_SW_COOKIE_CONV_CFG_GLOBAL_EN) |
- ab->hw_params->hal_params->wbm2sw_cc_enable;
-
- ath12k_hif_write32(ab, wbm_base + HAL_WBM_SW_COOKIE_CONVERT_CFG, val);
}
static u32 ath12k_dp_cc_cookie_gen(u16 ppt_idx, u16 spt_idx)
@@ -1385,26 +1150,23 @@ static u32 ath12k_dp_cc_cookie_gen(u16 ppt_idx, u16 spt_idx)
return (u32)ppt_idx << ATH12K_CC_PPT_SHIFT | spt_idx;
}
-static inline void *ath12k_dp_cc_get_desc_addr_ptr(struct ath12k_base *ab,
- u16 ppt_idx, u16 spt_idx)
+static void *ath12k_dp_cc_get_desc_addr_ptr(struct ath12k_dp *dp,
+ u16 ppt_idx, u16 spt_idx)
{
- struct ath12k_dp *dp = &ab->dp;
-
return dp->spt_info[ppt_idx].vaddr + spt_idx;
}
-struct ath12k_rx_desc_info *ath12k_dp_get_rx_desc(struct ath12k_base *ab,
+struct ath12k_rx_desc_info *ath12k_dp_get_rx_desc(struct ath12k_dp *dp,
u32 cookie)
{
- struct ath12k_dp *dp = &ab->dp;
struct ath12k_rx_desc_info **desc_addr_ptr;
u16 start_ppt_idx, end_ppt_idx, ppt_idx, spt_idx;
ppt_idx = u32_get_bits(cookie, ATH12K_DP_CC_COOKIE_PPT);
spt_idx = u32_get_bits(cookie, ATH12K_DP_CC_COOKIE_SPT);
- start_ppt_idx = dp->rx_ppt_base + ATH12K_RX_SPT_PAGE_OFFSET(ab);
- end_ppt_idx = start_ppt_idx + ATH12K_NUM_RX_SPT_PAGES(ab);
+ start_ppt_idx = dp->rx_ppt_base + ATH12K_RX_SPT_PAGE_OFFSET(dp->ab);
+ end_ppt_idx = start_ppt_idx + ATH12K_NUM_RX_SPT_PAGES(dp->ab);
if (ppt_idx < start_ppt_idx ||
ppt_idx >= end_ppt_idx ||
@@ -1412,12 +1174,13 @@ struct ath12k_rx_desc_info *ath12k_dp_get_rx_desc(struct ath12k_base *ab,
return NULL;
ppt_idx = ppt_idx - dp->rx_ppt_base;
- desc_addr_ptr = ath12k_dp_cc_get_desc_addr_ptr(ab, ppt_idx, spt_idx);
+ desc_addr_ptr = ath12k_dp_cc_get_desc_addr_ptr(dp, ppt_idx, spt_idx);
return *desc_addr_ptr;
}
+EXPORT_SYMBOL(ath12k_dp_get_rx_desc);
-struct ath12k_tx_desc_info *ath12k_dp_get_tx_desc(struct ath12k_base *ab,
+struct ath12k_tx_desc_info *ath12k_dp_get_tx_desc(struct ath12k_dp *dp,
u32 cookie)
{
struct ath12k_tx_desc_info **desc_addr_ptr;
@@ -1428,21 +1191,22 @@ struct ath12k_tx_desc_info *ath12k_dp_get_tx_desc(struct ath12k_base *ab,
start_ppt_idx = ATH12K_TX_SPT_PAGE_OFFSET;
end_ppt_idx = start_ppt_idx +
- (ATH12K_TX_SPT_PAGES_PER_POOL(ab) * ATH12K_HW_MAX_QUEUES);
+ (ATH12K_TX_SPT_PAGES_PER_POOL(dp->ab) * ATH12K_HW_MAX_QUEUES);
if (ppt_idx < start_ppt_idx ||
ppt_idx >= end_ppt_idx ||
spt_idx > ATH12K_MAX_SPT_ENTRIES)
return NULL;
- desc_addr_ptr = ath12k_dp_cc_get_desc_addr_ptr(ab, ppt_idx, spt_idx);
+ desc_addr_ptr = ath12k_dp_cc_get_desc_addr_ptr(dp, ppt_idx, spt_idx);
return *desc_addr_ptr;
}
+EXPORT_SYMBOL(ath12k_dp_get_tx_desc);
static int ath12k_dp_cc_desc_init(struct ath12k_base *ab)
{
- struct ath12k_dp *dp = &ab->dp;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
struct ath12k_rx_desc_info *rx_descs, **rx_desc_addr;
struct ath12k_tx_desc_info *tx_descs, **tx_desc_addr;
u32 num_rx_spt_pages = ATH12K_NUM_RX_SPT_PAGES(ab);
@@ -1482,7 +1246,7 @@ static int ath12k_dp_cc_desc_init(struct ath12k_base *ab)
list_add_tail(&rx_descs[j].list, &dp->rx_desc_free_list);
/* Update descriptor VA in SPT */
- rx_desc_addr = ath12k_dp_cc_get_desc_addr_ptr(ab, ppt_idx, j);
+ rx_desc_addr = ath12k_dp_cc_get_desc_addr_ptr(dp, ppt_idx, j);
*rx_desc_addr = &rx_descs[j];
}
}
@@ -1521,7 +1285,7 @@ static int ath12k_dp_cc_desc_init(struct ath12k_base *ab)
/* Update descriptor VA in SPT */
tx_desc_addr =
- ath12k_dp_cc_get_desc_addr_ptr(ab, ppt_idx, j);
+ ath12k_dp_cc_get_desc_addr_ptr(dp, ppt_idx, j);
*tx_desc_addr = &tx_descs[j];
}
}
@@ -1571,7 +1335,7 @@ void ath12k_dp_partner_cc_init(struct ath12k_base *ab)
if (ag->ab[i] == ab)
continue;
- ath12k_dp_cmem_init(ab, &ag->ab[i]->dp, ATH12K_DP_RX_DESC);
+ ath12k_dp_cmem_init(ab, ath12k_ab_to_dp(ag->ab[i]), ATH12K_DP_RX_DESC);
}
}
@@ -1582,7 +1346,7 @@ static u32 ath12k_dp_get_num_spt_pages(struct ath12k_base *ab)
static int ath12k_dp_cc_init(struct ath12k_base *ab)
{
- struct ath12k_dp *dp = &ab->dp;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
int i, ret = 0;
INIT_LIST_HEAD(&dp->rx_desc_free_list);
@@ -1668,8 +1432,7 @@ static int ath12k_dp_alloc_reoq_lut(struct ath12k_base *ab,
static int ath12k_dp_reoq_lut_setup(struct ath12k_base *ab)
{
- struct ath12k_dp *dp = &ab->dp;
- u32 val;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
int ret;
if (!ab->hw_params->reoq_lut_support)
@@ -1697,50 +1460,24 @@ static int ath12k_dp_reoq_lut_setup(struct ath12k_base *ab)
* register only
*/
- ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_LUT_BASE0(ab),
- dp->reoq_lut.paddr >> 8);
-
- ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_LUT_BASE1(ab),
- dp->ml_reoq_lut.paddr >> 8);
-
- val = ath12k_hif_read32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_ADDR(ab));
-
- ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_ADDR(ab),
- val | HAL_REO_QDESC_ADDR_READ_LUT_ENABLE);
-
- ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_MAX_PEERID(ab),
- HAL_REO_QDESC_MAX_PEERID);
+ ath12k_hal_write_reoq_lut_addr(ab, dp->reoq_lut.paddr >> 8);
+ ath12k_hal_write_ml_reoq_lut_addr(ab, dp->ml_reoq_lut.paddr >> 8);
+ ath12k_hal_reoq_lut_addr_read_enable(ab);
+ ath12k_hal_reoq_lut_set_max_peerid(ab);
return 0;
}
-static enum hal_rx_buf_return_buf_manager
-ath12k_dp_get_idle_link_rbm(struct ath12k_base *ab)
+static int ath12k_dp_setup(struct ath12k_base *ab)
{
- switch (ab->device_id) {
- case 0:
- return HAL_RX_BUF_RBM_WBM_DEV0_IDLE_DESC_LIST;
- case 1:
- return HAL_RX_BUF_RBM_WBM_DEV1_IDLE_DESC_LIST;
- case 2:
- return HAL_RX_BUF_RBM_WBM_DEV2_IDLE_DESC_LIST;
- default:
- ath12k_warn(ab, "invalid %d device id, so choose default rbm\n",
- ab->device_id);
- WARN_ON(1);
- return HAL_RX_BUF_RBM_WBM_DEV0_IDLE_DESC_LIST;
- }
-}
-
-int ath12k_dp_alloc(struct ath12k_base *ab)
-{
- struct ath12k_dp *dp = &ab->dp;
+ struct ath12k_dp *dp;
struct hal_srng *srng = NULL;
size_t size = 0;
u32 n_link_desc = 0;
int ret;
int i;
+ dp = ath12k_ab_to_dp(ab);
dp->ab = ab;
INIT_LIST_HEAD(&dp->reo_cmd_list);
@@ -1749,13 +1486,25 @@ int ath12k_dp_alloc(struct ath12k_base *ab)
spin_lock_init(&dp->reo_cmd_lock);
spin_lock_init(&dp->reo_rxq_flush_lock);
+ spin_lock_init(&dp->dp_lock);
+ INIT_LIST_HEAD(&dp->peers);
+
+ mutex_init(&dp->link_peer_rhash_tbl_lock);
+
dp->reo_cmd_cache_flush_count = 0;
- dp->idle_link_rbm = ath12k_dp_get_idle_link_rbm(ab);
+ dp->idle_link_rbm =
+ ath12k_hal_get_idle_link_rbm(&ab->hal, ab->device_id);
+
+ ret = ath12k_dp_link_peer_rhash_tbl_init(dp);
+ if (ret) {
+ ath12k_warn(ab, "failed to init link_peer rhash table: %d\n", ret);
+ return ret;
+ }
ret = ath12k_wbm_idle_ring_setup(ab, &n_link_desc);
if (ret) {
ath12k_warn(ab, "failed to setup wbm_idle_ring: %d\n", ret);
- return ret;
+ goto rhash_destroy;
}
srng = &ab->hal.srng_list[dp->wbm_idle_ring.ring_id];
@@ -1764,7 +1513,7 @@ int ath12k_dp_alloc(struct ath12k_base *ab)
HAL_WBM_IDLE_LINK, srng, n_link_desc);
if (ret) {
ath12k_warn(ab, "failed to setup link desc: %d\n", ret);
- return ret;
+ goto rhash_destroy;
}
ret = ath12k_dp_cc_init(ab);
@@ -1783,7 +1532,7 @@ int ath12k_dp_alloc(struct ath12k_base *ab)
if (ret)
goto fail_dp_bank_profiles_cleanup;
- size = sizeof(struct hal_wbm_release_ring_tx) *
+ size = ab->hal.hal_wbm_release_ring_tx_size *
DP_TX_COMP_RING_SIZE(ab);
ret = ath12k_dp_reoq_lut_setup(ab);
@@ -1836,6 +1585,48 @@ fail_hw_cc_cleanup:
fail_link_desc_cleanup:
ath12k_dp_link_desc_cleanup(ab, dp->link_desc_banks,
HAL_WBM_IDLE_LINK, &dp->wbm_idle_ring);
+rhash_destroy:
+ ath12k_dp_link_peer_rhash_tbl_destroy(dp);
return ret;
}
+
+void ath12k_dp_cmn_device_deinit(struct ath12k_dp *dp)
+{
+ ath12k_dp_cleanup(dp->ab);
+}
+
+int ath12k_dp_cmn_device_init(struct ath12k_dp *dp)
+{
+ int ret;
+
+ ret = ath12k_dp_setup(dp->ab);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+void ath12k_dp_cmn_hw_group_unassign(struct ath12k_dp *dp,
+ struct ath12k_hw_group *ag)
+{
+ struct ath12k_dp_hw_group *dp_hw_grp = &ag->dp_hw_grp;
+
+ lockdep_assert_held(&ag->mutex);
+
+ dp_hw_grp->dp[dp->device_id] = NULL;
+
+ dp->ag = NULL;
+ dp->device_id = ATH12K_INVALID_DEVICE_ID;
+}
+
+void ath12k_dp_cmn_hw_group_assign(struct ath12k_dp *dp,
+ struct ath12k_hw_group *ag)
+{
+ struct ath12k_base *ab = dp->ab;
+ struct ath12k_dp_hw_group *dp_hw_grp = &ag->dp_hw_grp;
+
+ dp->ag = ag;
+ dp->device_id = ab->device_id;
+ dp_hw_grp->dp[dp->device_id] = dp;
+}
diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h
index 4ffec6ad7d8d..f8cfc7bb29dd 100644
--- a/drivers/net/wireless/ath/ath12k/dp.h
+++ b/drivers/net/wireless/ath/ath12k/dp.h
@@ -1,29 +1,35 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH12K_DP_H
#define ATH12K_DP_H
-#include "hal_desc.h"
-#include "hal_rx.h"
#include "hw.h"
+#include "dp_htt.h"
+#include "dp_cmn.h"
+#include <linux/rhashtable.h>
#define MAX_RXDMA_PER_PDEV 2
struct ath12k_base;
-struct ath12k_peer;
+struct ath12k_dp_link_peer;
struct ath12k_dp;
struct ath12k_vif;
struct ath12k_link_vif;
-struct hal_tcl_status_ring;
struct ath12k_ext_irq_grp;
+struct ath12k_dp_rx_tid;
+struct ath12k_dp_rx_tid_rxq;
#define DP_MON_PURGE_TIMEOUT_MS 100
#define DP_MON_SERVICE_BUDGET 128
+#define DP_ENCAP_TYPE_MAX 4
+#define DP_ENCRYPT_TYPE_MAX 12
+#define DP_DESC_TYPE_MAX 2
+
struct dp_srng {
u32 *vaddr_unaligned;
u32 *vaddr;
@@ -149,6 +155,18 @@ struct ath12k_pdev_dp {
u32 mac_id;
atomic_t num_tx_pending;
wait_queue_head_t tx_empty_waitq;
+
+ struct ath12k_dp *dp;
+ struct ieee80211_hw *hw;
+ u8 hw_link_id;
+ struct ath12k_dp_hw *dp_hw;
+
+ /* Protects ppdu stats */
+ spinlock_t ppdu_list_lock;
+ struct ath12k_per_peer_tx_stats peer_tx_stats;
+ struct list_head ppdu_stats_info;
+ u32 ppdu_stat_list_depth;
+
struct dp_srng rxdma_mon_dst_ring[MAX_RXDMA_PER_PDEV];
struct dp_srng tx_mon_dst_ring[MAX_RXDMA_PER_PDEV];
@@ -360,9 +378,77 @@ struct ath12k_link_stats {
u32 tx_completed;
u32 tx_bcast_mcast;
u32 tx_dropped;
- u32 tx_encap_type[HAL_TCL_ENCAP_TYPE_MAX];
- u32 tx_encrypt_type[HAL_ENCRYPT_TYPE_MAX];
- u32 tx_desc_type[HAL_TCL_DESC_TYPE_MAX];
+ u32 tx_encap_type[DP_ENCAP_TYPE_MAX];
+ u32 tx_encrypt_type[DP_ENCRYPT_TYPE_MAX];
+ u32 tx_desc_type[DP_DESC_TYPE_MAX];
+};
+
+/* DP arch ops to communicate from common module
+ * to arch specific module
+ */
+struct ath12k_dp_arch_ops {
+ int (*service_srng)(struct ath12k_dp *dp,
+ struct ath12k_ext_irq_grp *irq_grp,
+ int budget);
+ u32 (*tx_get_vdev_bank_config)(struct ath12k_base *ab,
+ struct ath12k_link_vif *arvif);
+ int (*reo_cmd_send)(struct ath12k_base *ab,
+ struct ath12k_dp_rx_tid_rxq *rx_tid,
+ enum hal_reo_cmd_type type,
+ struct ath12k_hal_reo_cmd *cmd,
+ void (*cb)(struct ath12k_dp *dp, void *ctx,
+ enum hal_reo_cmd_status status));
+ void (*setup_pn_check_reo_cmd)(struct ath12k_hal_reo_cmd *cmd,
+ struct ath12k_dp_rx_tid *rx_tid,
+ u32 cipher, enum set_key_cmd key_cmd);
+ void (*rx_peer_tid_delete)(struct ath12k_base *ab,
+ struct ath12k_dp_link_peer *peer, u8 tid);
+ int (*reo_cache_flush)(struct ath12k_base *ab,
+ struct ath12k_dp_rx_tid_rxq *rx_tid);
+ int (*rx_link_desc_return)(struct ath12k_dp *dp,
+ struct ath12k_buffer_addr *buf_addr_info,
+ enum hal_wbm_rel_bm_act action);
+ void (*rx_frags_cleanup)(struct ath12k_dp_rx_tid *rx_tid,
+ bool rel_link_desc);
+ int (*peer_rx_tid_reo_update)(struct ath12k_dp *dp,
+ struct ath12k_dp_link_peer *peer,
+ struct ath12k_dp_rx_tid *rx_tid,
+ u32 ba_win_sz, u16 ssn,
+ bool update_ssn);
+ int (*rx_assign_reoq)(struct ath12k_base *ab, struct ath12k_dp_peer *dp_peer,
+ struct ath12k_dp_rx_tid *rx_tid,
+ u16 ssn, enum hal_pn_type pn_type);
+ void (*peer_rx_tid_qref_setup)(struct ath12k_base *ab, u16 peer_id, u16 tid,
+ dma_addr_t paddr);
+ void (*peer_rx_tid_qref_reset)(struct ath12k_base *ab, u16 peer_id, u16 tid);
+ int (*rx_tid_delete_handler)(struct ath12k_base *ab,
+ struct ath12k_dp_rx_tid_rxq *rx_tid);
+};
+
+struct ath12k_device_dp_tx_err_stats {
+ /* TCL Ring Descriptor unavailable */
+ u32 desc_na[DP_TCL_NUM_RING_MAX];
+ /* Other failures during dp_tx due to mem allocation failure
+ * idr unavailable etc.
+ */
+ atomic_t misc_fail;
+};
+
+struct ath12k_device_dp_stats {
+ u32 err_ring_pkts;
+ u32 invalid_rbm;
+ u32 rxdma_error[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX];
+ u32 reo_error[HAL_REO_DEST_RING_ERROR_CODE_MAX];
+ u32 hal_reo_error[DP_REO_DST_RING_MAX];
+ struct ath12k_device_dp_tx_err_stats tx_err;
+ u32 reo_rx[DP_REO_DST_RING_MAX][ATH12K_MAX_DEVICES];
+ u32 rx_wbm_rel_source[HAL_WBM_REL_SRC_MODULE_MAX][ATH12K_MAX_DEVICES];
+ u32 tqm_rel_reason[MAX_TQM_RELEASE_REASON];
+ u32 fw_tx_status[MAX_FW_TX_STATUS];
+ u32 tx_wbm_rel_source[HAL_WBM_REL_SRC_MODULE_MAX];
+ u32 tx_enqueued[DP_TCL_NUM_RING_MAX];
+ u32 tx_completed[DP_TCL_NUM_RING_MAX];
+ u32 reo_excep_msdu_buf_type;
};
struct ath12k_dp {
@@ -427,1512 +513,137 @@ struct ath12k_dp {
struct dp_rxdma_mon_ring rx_mon_status_refill_ring[MAX_RXDMA_PER_PDEV];
struct ath12k_reo_q_addr_lut reoq_lut;
struct ath12k_reo_q_addr_lut ml_reoq_lut;
-};
-
-/* HTT definitions */
-#define HTT_TAG_TCL_METADATA_VERSION 5
-
-#define HTT_TCL_META_DATA_TYPE GENMASK(1, 0)
-#define HTT_TCL_META_DATA_VALID_HTT BIT(2)
-
-/* vdev meta data */
-#define HTT_TCL_META_DATA_VDEV_ID GENMASK(10, 3)
-#define HTT_TCL_META_DATA_PDEV_ID GENMASK(12, 11)
-#define HTT_TCL_META_DATA_HOST_INSPECTED_MISSION BIT(13)
-
-/* peer meta data */
-#define HTT_TCL_META_DATA_PEER_ID GENMASK(15, 3)
-
-/* Global sequence number */
-#define HTT_TCL_META_DATA_TYPE_GLOBAL_SEQ_NUM 3
-#define HTT_TCL_META_DATA_GLOBAL_SEQ_HOST_INSPECTED BIT(2)
-#define HTT_TCL_META_DATA_GLOBAL_SEQ_NUM GENMASK(14, 3)
-#define HTT_TX_MLO_MCAST_HOST_REINJECT_BASE_VDEV_ID 128
-
-/* HTT tx completion is overlaid in wbm_release_ring */
-#define HTT_TX_WBM_COMP_INFO0_STATUS GENMASK(16, 13)
-#define HTT_TX_WBM_COMP_INFO1_REINJECT_REASON GENMASK(3, 0)
-#define HTT_TX_WBM_COMP_INFO1_EXCEPTION_FRAME BIT(4)
-
-#define HTT_TX_WBM_COMP_INFO2_ACK_RSSI GENMASK(31, 24)
-
-struct htt_tx_wbm_completion {
- __le32 rsvd0[2];
- __le32 info0;
- __le32 info1;
- __le32 info2;
- __le32 info3;
- __le32 info4;
- __le32 rsvd1;
-
-} __packed;
-
-enum htt_h2t_msg_type {
- HTT_H2T_MSG_TYPE_VERSION_REQ = 0,
- HTT_H2T_MSG_TYPE_SRING_SETUP = 0xb,
- HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG = 0xc,
- HTT_H2T_MSG_TYPE_EXT_STATS_CFG = 0x10,
- HTT_H2T_MSG_TYPE_PPDU_STATS_CFG = 0x11,
- HTT_H2T_MSG_TYPE_VDEV_TXRX_STATS_CFG = 0x1a,
- HTT_H2T_MSG_TYPE_TX_MONITOR_CFG = 0x1b,
-};
-
-#define HTT_VER_REQ_INFO_MSG_ID GENMASK(7, 0)
-#define HTT_OPTION_TCL_METADATA_VER_V1 1
-#define HTT_OPTION_TCL_METADATA_VER_V2 2
-#define HTT_OPTION_TAG GENMASK(7, 0)
-#define HTT_OPTION_LEN GENMASK(15, 8)
-#define HTT_OPTION_VALUE GENMASK(31, 16)
-#define HTT_TCL_METADATA_VER_SZ 4
-
-struct htt_ver_req_cmd {
- __le32 ver_reg_info;
- __le32 tcl_metadata_version;
-} __packed;
-
-enum htt_srng_ring_type {
- HTT_HW_TO_SW_RING,
- HTT_SW_TO_HW_RING,
- HTT_SW_TO_SW_RING,
-};
-
-enum htt_srng_ring_id {
- HTT_RXDMA_HOST_BUF_RING,
- HTT_RXDMA_MONITOR_STATUS_RING,
- HTT_RXDMA_MONITOR_BUF_RING,
- HTT_RXDMA_MONITOR_DESC_RING,
- HTT_RXDMA_MONITOR_DEST_RING,
- HTT_HOST1_TO_FW_RXBUF_RING,
- HTT_HOST2_TO_FW_RXBUF_RING,
- HTT_RXDMA_NON_MONITOR_DEST_RING,
- HTT_RXDMA_HOST_BUF_RING2,
- HTT_TX_MON_HOST2MON_BUF_RING,
- HTT_TX_MON_MON2HOST_DEST_RING,
- HTT_RX_MON_HOST2MON_BUF_RING,
- HTT_RX_MON_MON2HOST_DEST_RING,
-};
-
-/* host -> target HTT_SRING_SETUP message
- *
- * After target is booted up, Host can send SRING setup message for
- * each host facing LMAC SRING. Target setups up HW registers based
- * on setup message and confirms back to Host if response_required is set.
- * Host should wait for confirmation message before sending new SRING
- * setup message
- *
- * The message would appear as follows:
- *
- * |31 24|23 20|19|18 16|15|14 8|7 0|
- * |--------------- +-----------------+----------------+------------------|
- * | ring_type | ring_id | pdev_id | msg_type |
- * |----------------------------------------------------------------------|
- * | ring_base_addr_lo |
- * |----------------------------------------------------------------------|
- * | ring_base_addr_hi |
- * |----------------------------------------------------------------------|
- * |ring_misc_cfg_flag|ring_entry_size| ring_size |
- * |----------------------------------------------------------------------|
- * | ring_head_offset32_remote_addr_lo |
- * |----------------------------------------------------------------------|
- * | ring_head_offset32_remote_addr_hi |
- * |----------------------------------------------------------------------|
- * | ring_tail_offset32_remote_addr_lo |
- * |----------------------------------------------------------------------|
- * | ring_tail_offset32_remote_addr_hi |
- * |----------------------------------------------------------------------|
- * | ring_msi_addr_lo |
- * |----------------------------------------------------------------------|
- * | ring_msi_addr_hi |
- * |----------------------------------------------------------------------|
- * | ring_msi_data |
- * |----------------------------------------------------------------------|
- * | intr_timer_th |IM| intr_batch_counter_th |
- * |----------------------------------------------------------------------|
- * | reserved |RR|PTCF| intr_low_threshold |
- * |----------------------------------------------------------------------|
- * Where
- * IM = sw_intr_mode
- * RR = response_required
- * PTCF = prefetch_timer_cfg
- *
- * The message is interpreted as follows:
- * dword0 - b'0:7 - msg_type: This will be set to
- * HTT_H2T_MSG_TYPE_SRING_SETUP
- * b'8:15 - pdev_id:
- * 0 (for rings at SOC/UMAC level),
- * 1/2/3 mac id (for rings at LMAC level)
- * b'16:23 - ring_id: identify which ring is to setup,
- * more details can be got from enum htt_srng_ring_id
- * b'24:31 - ring_type: identify type of host rings,
- * more details can be got from enum htt_srng_ring_type
- * dword1 - b'0:31 - ring_base_addr_lo: Lower 32bits of ring base address
- * dword2 - b'0:31 - ring_base_addr_hi: Upper 32bits of ring base address
- * dword3 - b'0:15 - ring_size: size of the ring in unit of 4-bytes words
- * b'16:23 - ring_entry_size: Size of each entry in 4-byte word units
- * b'24:31 - ring_misc_cfg_flag: Valid only for HW_TO_SW_RING and
- * SW_TO_HW_RING.
- * Refer to HTT_SRING_SETUP_RING_MISC_CFG_RING defs.
- * dword4 - b'0:31 - ring_head_off32_remote_addr_lo:
- * Lower 32 bits of memory address of the remote variable
- * storing the 4-byte word offset that identifies the head
- * element within the ring.
- * (The head offset variable has type u32.)
- * Valid for HW_TO_SW and SW_TO_SW rings.
- * dword5 - b'0:31 - ring_head_off32_remote_addr_hi:
- * Upper 32 bits of memory address of the remote variable
- * storing the 4-byte word offset that identifies the head
- * element within the ring.
- * (The head offset variable has type u32.)
- * Valid for HW_TO_SW and SW_TO_SW rings.
- * dword6 - b'0:31 - ring_tail_off32_remote_addr_lo:
- * Lower 32 bits of memory address of the remote variable
- * storing the 4-byte word offset that identifies the tail
- * element within the ring.
- * (The tail offset variable has type u32.)
- * Valid for HW_TO_SW and SW_TO_SW rings.
- * dword7 - b'0:31 - ring_tail_off32_remote_addr_hi:
- * Upper 32 bits of memory address of the remote variable
- * storing the 4-byte word offset that identifies the tail
- * element within the ring.
- * (The tail offset variable has type u32.)
- * Valid for HW_TO_SW and SW_TO_SW rings.
- * dword8 - b'0:31 - ring_msi_addr_lo: Lower 32bits of MSI cfg address
- * valid only for HW_TO_SW_RING and SW_TO_HW_RING
- * dword9 - b'0:31 - ring_msi_addr_hi: Upper 32bits of MSI cfg address
- * valid only for HW_TO_SW_RING and SW_TO_HW_RING
- * dword10 - b'0:31 - ring_msi_data: MSI data
- * Refer to HTT_SRING_SETUP_RING_MSC_CFG_xxx defs
- * valid only for HW_TO_SW_RING and SW_TO_HW_RING
- * dword11 - b'0:14 - intr_batch_counter_th:
- * batch counter threshold is in units of 4-byte words.
- * HW internally maintains and increments batch count.
- * (see SRING spec for detail description).
- * When batch count reaches threshold value, an interrupt
- * is generated by HW.
- * b'15 - sw_intr_mode:
- * This configuration shall be static.
- * Only programmed at power up.
- * 0: generate pulse style sw interrupts
- * 1: generate level style sw interrupts
- * b'16:31 - intr_timer_th:
- * The timer init value when timer is idle or is
- * initialized to start downcounting.
- * In 8us units (to cover a range of 0 to 524 ms)
- * dword12 - b'0:15 - intr_low_threshold:
- * Used only by Consumer ring to generate ring_sw_int_p.
- * Ring entries low threshold water mark, that is used
- * in combination with the interrupt timer as well as
- * the clearing of the level interrupt.
- * b'16:18 - prefetch_timer_cfg:
- * Used only by Consumer ring to set timer mode to
- * support Application prefetch handling.
- * The external tail offset/pointer will be updated
- * at following intervals:
- * 3'b000: (Prefetch feature disabled; used only for debug)
- * 3'b001: 1 usec
- * 3'b010: 4 usec
- * 3'b011: 8 usec (default)
- * 3'b100: 16 usec
- * Others: Reserved
- * b'19 - response_required:
- * Host needs HTT_T2H_MSG_TYPE_SRING_SETUP_DONE as response
- * b'20:31 - reserved: reserved for future use
- */
-
-#define HTT_SRNG_SETUP_CMD_INFO0_MSG_TYPE GENMASK(7, 0)
-#define HTT_SRNG_SETUP_CMD_INFO0_PDEV_ID GENMASK(15, 8)
-#define HTT_SRNG_SETUP_CMD_INFO0_RING_ID GENMASK(23, 16)
-#define HTT_SRNG_SETUP_CMD_INFO0_RING_TYPE GENMASK(31, 24)
-
-#define HTT_SRNG_SETUP_CMD_INFO1_RING_SIZE GENMASK(15, 0)
-#define HTT_SRNG_SETUP_CMD_INFO1_RING_ENTRY_SIZE GENMASK(23, 16)
-#define HTT_SRNG_SETUP_CMD_INFO1_RING_LOOP_CNT_DIS BIT(25)
-#define HTT_SRNG_SETUP_CMD_INFO1_RING_FLAGS_MSI_SWAP BIT(27)
-#define HTT_SRNG_SETUP_CMD_INFO1_RING_FLAGS_HOST_FW_SWAP BIT(28)
-#define HTT_SRNG_SETUP_CMD_INFO1_RING_FLAGS_TLV_SWAP BIT(29)
-
-#define HTT_SRNG_SETUP_CMD_INTR_INFO_BATCH_COUNTER_THRESH GENMASK(14, 0)
-#define HTT_SRNG_SETUP_CMD_INTR_INFO_SW_INTR_MODE BIT(15)
-#define HTT_SRNG_SETUP_CMD_INTR_INFO_INTR_TIMER_THRESH GENMASK(31, 16)
-
-#define HTT_SRNG_SETUP_CMD_INFO2_INTR_LOW_THRESH GENMASK(15, 0)
-#define HTT_SRNG_SETUP_CMD_INFO2_PRE_FETCH_TIMER_CFG GENMASK(18, 16)
-#define HTT_SRNG_SETUP_CMD_INFO2_RESPONSE_REQUIRED BIT(19)
-
-struct htt_srng_setup_cmd {
- __le32 info0;
- __le32 ring_base_addr_lo;
- __le32 ring_base_addr_hi;
- __le32 info1;
- __le32 ring_head_off32_remote_addr_lo;
- __le32 ring_head_off32_remote_addr_hi;
- __le32 ring_tail_off32_remote_addr_lo;
- __le32 ring_tail_off32_remote_addr_hi;
- __le32 ring_msi_addr_lo;
- __le32 ring_msi_addr_hi;
- __le32 msi_data;
- __le32 intr_info;
- __le32 info2;
-} __packed;
-
-/* host -> target FW PPDU_STATS config message
- *
- * @details
- * The following field definitions describe the format of the HTT host
- * to target FW for PPDU_STATS_CFG msg.
- * The message allows the host to configure the PPDU_STATS_IND messages
- * produced by the target.
- *
- * |31 24|23 16|15 8|7 0|
- * |-----------------------------------------------------------|
- * | REQ bit mask | pdev_mask | msg type |
- * |-----------------------------------------------------------|
- * Header fields:
- * - MSG_TYPE
- * Bits 7:0
- * Purpose: identifies this is a req to configure ppdu_stats_ind from target
- * Value: 0x11
- * - PDEV_MASK
- * Bits 8:15
- * Purpose: identifies which pdevs this PPDU stats configuration applies to
- * Value: This is a overloaded field, refer to usage and interpretation of
- * PDEV in interface document.
- * Bit 8 : Reserved for SOC stats
- * Bit 9 - 15 : Indicates PDEV_MASK in DBDC
- * Indicates MACID_MASK in DBS
- * - REQ_TLV_BIT_MASK
- * Bits 16:31
- * Purpose: each set bit indicates the corresponding PPDU stats TLV type
- * needs to be included in the target's PPDU_STATS_IND messages.
- * Value: refer htt_ppdu_stats_tlv_tag_t <<<???
- *
- */
-
-struct htt_ppdu_stats_cfg_cmd {
- __le32 msg;
-} __packed;
-
-#define HTT_PPDU_STATS_CFG_MSG_TYPE GENMASK(7, 0)
-#define HTT_PPDU_STATS_CFG_SOC_STATS BIT(8)
-#define HTT_PPDU_STATS_CFG_PDEV_ID GENMASK(15, 9)
-#define HTT_PPDU_STATS_CFG_TLV_TYPE_BITMASK GENMASK(31, 16)
-
-enum htt_ppdu_stats_tag_type {
- HTT_PPDU_STATS_TAG_COMMON,
- HTT_PPDU_STATS_TAG_USR_COMMON,
- HTT_PPDU_STATS_TAG_USR_RATE,
- HTT_PPDU_STATS_TAG_USR_MPDU_ENQ_BITMAP_64,
- HTT_PPDU_STATS_TAG_USR_MPDU_ENQ_BITMAP_256,
- HTT_PPDU_STATS_TAG_SCH_CMD_STATUS,
- HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON,
- HTT_PPDU_STATS_TAG_USR_COMPLTN_BA_BITMAP_64,
- HTT_PPDU_STATS_TAG_USR_COMPLTN_BA_BITMAP_256,
- HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS,
- HTT_PPDU_STATS_TAG_USR_COMPLTN_FLUSH,
- HTT_PPDU_STATS_TAG_USR_COMMON_ARRAY,
- HTT_PPDU_STATS_TAG_INFO,
- HTT_PPDU_STATS_TAG_TX_MGMTCTRL_PAYLOAD,
-
- /* New TLV's are added above to this line */
- HTT_PPDU_STATS_TAG_MAX,
-};
-
-#define HTT_PPDU_STATS_TAG_DEFAULT (BIT(HTT_PPDU_STATS_TAG_COMMON) \
- | BIT(HTT_PPDU_STATS_TAG_USR_COMMON) \
- | BIT(HTT_PPDU_STATS_TAG_USR_RATE) \
- | BIT(HTT_PPDU_STATS_TAG_SCH_CMD_STATUS) \
- | BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON) \
- | BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS) \
- | BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_FLUSH) \
- | BIT(HTT_PPDU_STATS_TAG_USR_COMMON_ARRAY))
-
-#define HTT_PPDU_STATS_TAG_PKTLOG (BIT(HTT_PPDU_STATS_TAG_USR_MPDU_ENQ_BITMAP_64) | \
- BIT(HTT_PPDU_STATS_TAG_USR_MPDU_ENQ_BITMAP_256) | \
- BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_BA_BITMAP_64) | \
- BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_BA_BITMAP_256) | \
- BIT(HTT_PPDU_STATS_TAG_INFO) | \
- BIT(HTT_PPDU_STATS_TAG_TX_MGMTCTRL_PAYLOAD) | \
- HTT_PPDU_STATS_TAG_DEFAULT)
-
-enum htt_stats_internal_ppdu_frametype {
- HTT_STATS_PPDU_FTYPE_CTRL,
- HTT_STATS_PPDU_FTYPE_DATA,
- HTT_STATS_PPDU_FTYPE_BAR,
- HTT_STATS_PPDU_FTYPE_MAX
-};
-
-/* HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG Message
- *
- * details:
- * HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG message is sent by host to
- * configure RXDMA rings.
- * The configuration is per ring based and includes both packet subtypes
- * and PPDU/MPDU TLVs.
- *
- * The message would appear as follows:
- *
- * |31 29|28|27|26|25|24|23 16|15 8|7 0|
- * |-------+--+--+--+--+--+-----------+----------------+---------------|
- * | rsvd1 |ED|DT|OV|PS|SS| ring_id | pdev_id | msg_type |
- * |-------------------------------------------------------------------|
- * | rsvd2 | ring_buffer_size |
- * |-------------------------------------------------------------------|
- * | packet_type_enable_flags_0 |
- * |-------------------------------------------------------------------|
- * | packet_type_enable_flags_1 |
- * |-------------------------------------------------------------------|
- * | packet_type_enable_flags_2 |
- * |-------------------------------------------------------------------|
- * | packet_type_enable_flags_3 |
- * |-------------------------------------------------------------------|
- * | tlv_filter_in_flags |
- * |-------------------------------------------------------------------|
- * Where:
- * PS = pkt_swap
- * SS = status_swap
- * The message is interpreted as follows:
- * dword0 - b'0:7 - msg_type: This will be set to
- * HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG
- * b'8:15 - pdev_id:
- * 0 (for rings at SOC/UMAC level),
- * 1/2/3 mac id (for rings at LMAC level)
- * b'16:23 - ring_id : Identify the ring to configure.
- * More details can be got from enum htt_srng_ring_id
- * b'24 - status_swap: 1 is to swap status TLV
- * b'25 - pkt_swap: 1 is to swap packet TLV
- * b'26 - rx_offset_valid (OV): flag to indicate rx offsets
- * configuration fields are valid
- * b'27 - drop_thresh_valid (DT): flag to indicate if the
- * rx_drop_threshold field is valid
- * b'28 - rx_mon_global_en: Enable/Disable global register
- * configuration in Rx monitor module.
- * b'29:31 - rsvd1: reserved for future use
- * dword1 - b'0:16 - ring_buffer_size: size of buffers referenced by rx ring,
- * in byte units.
- * Valid only for HW_TO_SW_RING and SW_TO_HW_RING
- * - b'16:31 - rsvd2: Reserved for future use
- * dword2 - b'0:31 - packet_type_enable_flags_0:
- * Enable MGMT packet from 0b0000 to 0b1001
- * bits from low to high: FP, MD, MO - 3 bits
- * FP: Filter_Pass
- * MD: Monitor_Direct
- * MO: Monitor_Other
- * 10 mgmt subtypes * 3 bits -> 30 bits
- * Refer to PKT_TYPE_ENABLE_FLAG0_xxx_MGMT_xxx defs
- * dword3 - b'0:31 - packet_type_enable_flags_1:
- * Enable MGMT packet from 0b1010 to 0b1111
- * bits from low to high: FP, MD, MO - 3 bits
- * Refer to PKT_TYPE_ENABLE_FLAG1_xxx_MGMT_xxx defs
- * dword4 - b'0:31 - packet_type_enable_flags_2:
- * Enable CTRL packet from 0b0000 to 0b1001
- * bits from low to high: FP, MD, MO - 3 bits
- * Refer to PKT_TYPE_ENABLE_FLAG2_xxx_CTRL_xxx defs
- * dword5 - b'0:31 - packet_type_enable_flags_3:
- * Enable CTRL packet from 0b1010 to 0b1111,
- * MCAST_DATA, UCAST_DATA, NULL_DATA
- * bits from low to high: FP, MD, MO - 3 bits
- * Refer to PKT_TYPE_ENABLE_FLAG3_xxx_CTRL_xxx defs
- * dword6 - b'0:31 - tlv_filter_in_flags:
- * Filter in Attention/MPDU/PPDU/Header/User tlvs
- * Refer to CFG_TLV_FILTER_IN_FLAG defs
- */
-
-#define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_MSG_TYPE GENMASK(7, 0)
-#define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID GENMASK(15, 8)
-#define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_RING_ID GENMASK(23, 16)
-#define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_SS BIT(24)
-#define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PS BIT(25)
-#define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_OFFSET_VALID BIT(26)
-#define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_DROP_THRES_VAL BIT(27)
-#define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_EN_RXMON BIT(28)
-
-#define HTT_RX_RING_SELECTION_CFG_CMD_INFO1_BUF_SIZE GENMASK(15, 0)
-#define HTT_RX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_MGMT GENMASK(18, 16)
-#define HTT_RX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_CTRL GENMASK(21, 19)
-#define HTT_RX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_DATA GENMASK(24, 22)
-
-#define HTT_RX_RING_SELECTION_CFG_CMD_INFO2_DROP_THRESHOLD GENMASK(9, 0)
-#define HTT_RX_RING_SELECTION_CFG_CMD_INFO2_EN_LOG_MGMT_TYPE BIT(17)
-#define HTT_RX_RING_SELECTION_CFG_CMD_INFO2_EN_CTRL_TYPE BIT(18)
-#define HTT_RX_RING_SELECTION_CFG_CMD_INFO2_EN_LOG_DATA_TYPE BIT(19)
-
-#define HTT_RX_RING_SELECTION_CFG_CMD_INFO3_EN_TLV_PKT_OFFSET BIT(0)
-#define HTT_RX_RING_SELECTION_CFG_CMD_INFO3_PKT_TLV_OFFSET GENMASK(14, 1)
-
-#define HTT_RX_RING_SELECTION_CFG_RX_PACKET_OFFSET GENMASK(15, 0)
-#define HTT_RX_RING_SELECTION_CFG_RX_HEADER_OFFSET GENMASK(31, 16)
-#define HTT_RX_RING_SELECTION_CFG_RX_MPDU_END_OFFSET GENMASK(15, 0)
-#define HTT_RX_RING_SELECTION_CFG_RX_MPDU_START_OFFSET GENMASK(31, 16)
-#define HTT_RX_RING_SELECTION_CFG_RX_MSDU_END_OFFSET GENMASK(15, 0)
-#define HTT_RX_RING_SELECTION_CFG_RX_MSDU_START_OFFSET GENMASK(31, 16)
-#define HTT_RX_RING_SELECTION_CFG_RX_ATTENTION_OFFSET GENMASK(15, 0)
-
-#define HTT_RX_RING_SELECTION_CFG_WORD_MASK_COMPACT_SET BIT(23)
-#define HTT_RX_RING_SELECTION_CFG_RX_MPDU_START_MASK GENMASK(15, 0)
-#define HTT_RX_RING_SELECTION_CFG_RX_MPDU_END_MASK GENMASK(18, 16)
-#define HTT_RX_RING_SELECTION_CFG_RX_MSDU_END_MASK GENMASK(16, 0)
-
-enum htt_rx_filter_tlv_flags {
- HTT_RX_FILTER_TLV_FLAGS_MPDU_START = BIT(0),
- HTT_RX_FILTER_TLV_FLAGS_MSDU_START = BIT(1),
- HTT_RX_FILTER_TLV_FLAGS_RX_PACKET = BIT(2),
- HTT_RX_FILTER_TLV_FLAGS_MSDU_END = BIT(3),
- HTT_RX_FILTER_TLV_FLAGS_MPDU_END = BIT(4),
- HTT_RX_FILTER_TLV_FLAGS_PACKET_HEADER = BIT(5),
- HTT_RX_FILTER_TLV_FLAGS_PER_MSDU_HEADER = BIT(6),
- HTT_RX_FILTER_TLV_FLAGS_ATTENTION = BIT(7),
- HTT_RX_FILTER_TLV_FLAGS_PPDU_START = BIT(8),
- HTT_RX_FILTER_TLV_FLAGS_PPDU_END = BIT(9),
- HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS = BIT(10),
- HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT = BIT(11),
- HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE = BIT(12),
- HTT_RX_FILTER_TLV_FLAGS_PPDU_START_USER_INFO = BIT(13),
-};
-
-enum htt_rx_mgmt_pkt_filter_tlv_flags0 {
- HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_REQ = BIT(0),
- HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_REQ = BIT(1),
- HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_REQ = BIT(2),
- HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_RESP = BIT(3),
- HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_RESP = BIT(4),
- HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_RESP = BIT(5),
- HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_REQ = BIT(6),
- HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_REQ = BIT(7),
- HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_REQ = BIT(8),
- HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_RESP = BIT(9),
- HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_RESP = BIT(10),
- HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_RESP = BIT(11),
- HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_REQ = BIT(12),
- HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_REQ = BIT(13),
- HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_REQ = BIT(14),
- HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_RESP = BIT(15),
- HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_RESP = BIT(16),
- HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_RESP = BIT(17),
- HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_TIMING_ADV = BIT(18),
- HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_TIMING_ADV = BIT(19),
- HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_TIMING_ADV = BIT(20),
- HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_RESERVED_7 = BIT(21),
- HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_RESERVED_7 = BIT(22),
- HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_RESERVED_7 = BIT(23),
- HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_BEACON = BIT(24),
- HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_BEACON = BIT(25),
- HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_BEACON = BIT(26),
- HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_ATIM = BIT(27),
- HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_ATIM = BIT(28),
- HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_ATIM = BIT(29),
-};
-
-enum htt_rx_mgmt_pkt_filter_tlv_flags1 {
- HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_DISASSOC = BIT(0),
- HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_DISASSOC = BIT(1),
- HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_DISASSOC = BIT(2),
- HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_AUTH = BIT(3),
- HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_AUTH = BIT(4),
- HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_AUTH = BIT(5),
- HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_DEAUTH = BIT(6),
- HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_DEAUTH = BIT(7),
- HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_DEAUTH = BIT(8),
- HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION = BIT(9),
- HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION = BIT(10),
- HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION = BIT(11),
- HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION_NOACK = BIT(12),
- HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION_NOACK = BIT(13),
- HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION_NOACK = BIT(14),
- HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_RESERVED_15 = BIT(15),
- HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_RESERVED_15 = BIT(16),
- HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_RESERVED_15 = BIT(17),
-};
-
-enum htt_rx_ctrl_pkt_filter_tlv_flags2 {
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_1 = BIT(0),
- HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_1 = BIT(1),
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_1 = BIT(2),
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_2 = BIT(3),
- HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_2 = BIT(4),
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_2 = BIT(5),
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_TRIGGER = BIT(6),
- HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_TRIGGER = BIT(7),
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_TRIGGER = BIT(8),
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_4 = BIT(9),
- HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_4 = BIT(10),
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_4 = BIT(11),
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_BF_REP_POLL = BIT(12),
- HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_BF_REP_POLL = BIT(13),
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_BF_REP_POLL = BIT(14),
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_VHT_NDP = BIT(15),
- HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_VHT_NDP = BIT(16),
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_VHT_NDP = BIT(17),
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_FRAME_EXT = BIT(18),
- HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_FRAME_EXT = BIT(19),
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_FRAME_EXT = BIT(20),
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_WRAPPER = BIT(21),
- HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_WRAPPER = BIT(22),
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_WRAPPER = BIT(23),
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_BAR = BIT(24),
- HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_BAR = BIT(25),
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_BAR = BIT(26),
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_BA = BIT(27),
- HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_BA = BIT(28),
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_BA = BIT(29),
-};
-
-enum htt_rx_ctrl_pkt_filter_tlv_flags3 {
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_PSPOLL = BIT(0),
- HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_PSPOLL = BIT(1),
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_PSPOLL = BIT(2),
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_RTS = BIT(3),
- HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_RTS = BIT(4),
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_RTS = BIT(5),
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_CTS = BIT(6),
- HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_CTS = BIT(7),
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_CTS = BIT(8),
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_ACK = BIT(9),
- HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_ACK = BIT(10),
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_ACK = BIT(11),
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND = BIT(12),
- HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND = BIT(13),
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND = BIT(14),
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND_ACK = BIT(15),
- HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND_ACK = BIT(16),
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND_ACK = BIT(17),
-};
-
-enum htt_rx_data_pkt_filter_tlv_flasg3 {
- HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_MCAST = BIT(18),
- HTT_RX_MD_DATA_PKT_FILTER_TLV_FLASG3_MCAST = BIT(19),
- HTT_RX_MO_DATA_PKT_FILTER_TLV_FLASG3_MCAST = BIT(20),
- HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_UCAST = BIT(21),
- HTT_RX_MD_DATA_PKT_FILTER_TLV_FLASG3_UCAST = BIT(22),
- HTT_RX_MO_DATA_PKT_FILTER_TLV_FLASG3_UCAST = BIT(23),
- HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA = BIT(24),
- HTT_RX_MD_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA = BIT(25),
- HTT_RX_MO_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA = BIT(26),
-};
-
-#define HTT_RX_FP_MGMT_FILTER_FLAGS0 \
- (HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_REQ \
- | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_RESP \
- | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_REQ \
- | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_RESP \
- | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_REQ \
- | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_RESP \
- | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_TIMING_ADV \
- | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_BEACON \
- | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_ATIM)
-
-#define HTT_RX_MD_MGMT_FILTER_FLAGS0 \
- (HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_REQ \
- | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_RESP \
- | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_REQ \
- | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_RESP \
- | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_REQ \
- | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_RESP \
- | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_TIMING_ADV \
- | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_BEACON \
- | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_ATIM)
-
-#define HTT_RX_MO_MGMT_FILTER_FLAGS0 \
- (HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_REQ \
- | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_RESP \
- | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_REQ \
- | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_RESP \
- | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_REQ \
- | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_RESP \
- | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_TIMING_ADV \
- | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_BEACON \
- | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_ATIM)
-
-#define HTT_RX_FP_MGMT_FILTER_FLAGS1 (HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_DISASSOC \
- | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_AUTH \
- | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_DEAUTH \
- | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION \
- | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION_NOACK)
-
-#define HTT_RX_MD_MGMT_FILTER_FLAGS1 (HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_DISASSOC \
- | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_AUTH \
- | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_DEAUTH \
- | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION \
- | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION_NOACK)
-
-#define HTT_RX_MO_MGMT_FILTER_FLAGS1 (HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_DISASSOC \
- | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_AUTH \
- | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_DEAUTH \
- | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION \
- | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION_NOACK)
-
-#define HTT_RX_FP_CTRL_FILTER_FLASG2 (HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_WRAPPER \
- | HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_BAR \
- | HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_BA)
-
-#define HTT_RX_MD_CTRL_FILTER_FLASG2 (HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_WRAPPER \
- | HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_BAR \
- | HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_BA)
-
-#define HTT_RX_MO_CTRL_FILTER_FLASG2 (HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_WRAPPER \
- | HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_BAR \
- | HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_BA)
-
-#define HTT_RX_FP_CTRL_FILTER_FLASG3 (HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_PSPOLL \
- | HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_RTS \
- | HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_CTS \
- | HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_ACK \
- | HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND \
- | HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND_ACK)
-
-#define HTT_RX_MD_CTRL_FILTER_FLASG3 (HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_PSPOLL \
- | HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_RTS \
- | HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_CTS \
- | HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_ACK \
- | HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND \
- | HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND_ACK)
-
-#define HTT_RX_MO_CTRL_FILTER_FLASG3 (HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_PSPOLL \
- | HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_RTS \
- | HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_CTS \
- | HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_ACK \
- | HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND \
- | HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND_ACK)
-
-#define HTT_RX_FP_DATA_FILTER_FLASG3 (HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_MCAST \
- | HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_UCAST \
- | HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA)
-
-#define HTT_RX_MD_DATA_FILTER_FLASG3 (HTT_RX_MD_DATA_PKT_FILTER_TLV_FLASG3_MCAST \
- | HTT_RX_MD_DATA_PKT_FILTER_TLV_FLASG3_UCAST \
- | HTT_RX_MD_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA)
-
-#define HTT_RX_MO_DATA_FILTER_FLASG3 (HTT_RX_MO_DATA_PKT_FILTER_TLV_FLASG3_MCAST \
- | HTT_RX_MO_DATA_PKT_FILTER_TLV_FLASG3_UCAST \
- | HTT_RX_MO_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA)
-
-#define HTT_RX_MON_FP_MGMT_FILTER_FLAGS0 \
- (HTT_RX_FP_MGMT_FILTER_FLAGS0 | \
- HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_RESERVED_7)
-
-#define HTT_RX_MON_MO_MGMT_FILTER_FLAGS0 \
- (HTT_RX_MO_MGMT_FILTER_FLAGS0 | \
- HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_RESERVED_7)
-
-#define HTT_RX_MON_FP_MGMT_FILTER_FLAGS1 \
- (HTT_RX_FP_MGMT_FILTER_FLAGS1 | \
- HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_RESERVED_15)
-
-#define HTT_RX_MON_MO_MGMT_FILTER_FLAGS1 \
- (HTT_RX_MO_MGMT_FILTER_FLAGS1 | \
- HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_RESERVED_15)
-
-#define HTT_RX_MON_FP_CTRL_FILTER_FLASG2 \
- (HTT_RX_FP_CTRL_FILTER_FLASG2 | \
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_1 | \
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_2 | \
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_TRIGGER | \
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_4 | \
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_BF_REP_POLL | \
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_VHT_NDP | \
- HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_FRAME_EXT)
-
-#define HTT_RX_MON_MO_CTRL_FILTER_FLASG2 \
- (HTT_RX_MO_CTRL_FILTER_FLASG2 | \
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_1 | \
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_2 | \
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_TRIGGER | \
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_4 | \
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_BF_REP_POLL | \
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_VHT_NDP | \
- HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_FRAME_EXT)
-
-#define HTT_RX_MON_FP_CTRL_FILTER_FLASG3 HTT_RX_FP_CTRL_FILTER_FLASG3
-
-#define HTT_RX_MON_MO_CTRL_FILTER_FLASG3 HTT_RX_MO_CTRL_FILTER_FLASG3
-
-#define HTT_RX_MON_FP_DATA_FILTER_FLASG3 HTT_RX_FP_DATA_FILTER_FLASG3
-
-#define HTT_RX_MON_MO_DATA_FILTER_FLASG3 HTT_RX_MO_DATA_FILTER_FLASG3
-
-#define HTT_RX_MON_FILTER_TLV_FLAGS \
- (HTT_RX_FILTER_TLV_FLAGS_MPDU_START | \
- HTT_RX_FILTER_TLV_FLAGS_PPDU_START | \
- HTT_RX_FILTER_TLV_FLAGS_PPDU_END | \
- HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS | \
- HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT | \
- HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE)
-
-#define HTT_RX_MON_FILTER_TLV_FLAGS_MON_STATUS_RING \
- (HTT_RX_FILTER_TLV_FLAGS_MPDU_START | \
- HTT_RX_FILTER_TLV_FLAGS_PPDU_START | \
- HTT_RX_FILTER_TLV_FLAGS_PPDU_END | \
- HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS | \
- HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT | \
- HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE)
-
-#define HTT_RX_MON_FILTER_TLV_FLAGS_MON_BUF_RING \
- (HTT_RX_FILTER_TLV_FLAGS_MPDU_START | \
- HTT_RX_FILTER_TLV_FLAGS_MSDU_START | \
- HTT_RX_FILTER_TLV_FLAGS_RX_PACKET | \
- HTT_RX_FILTER_TLV_FLAGS_MSDU_END | \
- HTT_RX_FILTER_TLV_FLAGS_MPDU_END | \
- HTT_RX_FILTER_TLV_FLAGS_PACKET_HEADER | \
- HTT_RX_FILTER_TLV_FLAGS_PER_MSDU_HEADER | \
- HTT_RX_FILTER_TLV_FLAGS_ATTENTION)
-
-#define HTT_RX_MON_FILTER_TLV_FLAGS_MON_DEST_RING \
- (HTT_RX_FILTER_TLV_FLAGS_MPDU_START | \
- HTT_RX_FILTER_TLV_FLAGS_MSDU_START | \
- HTT_RX_FILTER_TLV_FLAGS_RX_PACKET | \
- HTT_RX_FILTER_TLV_FLAGS_MSDU_END | \
- HTT_RX_FILTER_TLV_FLAGS_MPDU_END | \
- HTT_RX_FILTER_TLV_FLAGS_PACKET_HEADER | \
- HTT_RX_FILTER_TLV_FLAGS_PER_MSDU_HEADER | \
- HTT_RX_FILTER_TLV_FLAGS_PPDU_START | \
- HTT_RX_FILTER_TLV_FLAGS_PPDU_END | \
- HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS | \
- HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT | \
- HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE | \
- HTT_RX_FILTER_TLV_FLAGS_PPDU_START_USER_INFO)
-
-/* msdu start. mpdu end, attention, rx hdr tlv's are not subscribed */
-#define HTT_RX_TLV_FLAGS_RXDMA_RING \
- (HTT_RX_FILTER_TLV_FLAGS_MPDU_START | \
- HTT_RX_FILTER_TLV_FLAGS_RX_PACKET | \
- HTT_RX_FILTER_TLV_FLAGS_MSDU_END)
-
-#define HTT_TX_RING_SELECTION_CFG_CMD_INFO0_MSG_TYPE GENMASK(7, 0)
-#define HTT_TX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID GENMASK(15, 8)
-
-struct htt_rx_ring_selection_cfg_cmd {
- __le32 info0;
- __le32 info1;
- __le32 pkt_type_en_flags0;
- __le32 pkt_type_en_flags1;
- __le32 pkt_type_en_flags2;
- __le32 pkt_type_en_flags3;
- __le32 rx_filter_tlv;
- __le32 rx_packet_offset;
- __le32 rx_mpdu_offset;
- __le32 rx_msdu_offset;
- __le32 rx_attn_offset;
- __le32 info2;
- __le32 reserved[2];
- __le32 rx_mpdu_start_end_mask;
- __le32 rx_msdu_end_word_mask;
- __le32 info3;
-} __packed;
-
-#define HTT_RX_RING_TLV_DROP_THRESHOLD_VALUE 32
-#define HTT_RX_RING_DEFAULT_DMA_LENGTH 0x7
-#define HTT_RX_RING_PKT_TLV_OFFSET 0x1
-
-struct htt_rx_ring_tlv_filter {
- u32 rx_filter; /* see htt_rx_filter_tlv_flags */
- u32 pkt_filter_flags0; /* MGMT */
- u32 pkt_filter_flags1; /* MGMT */
- u32 pkt_filter_flags2; /* CTRL */
- u32 pkt_filter_flags3; /* DATA */
- bool offset_valid;
- u16 rx_packet_offset;
- u16 rx_header_offset;
- u16 rx_mpdu_end_offset;
- u16 rx_mpdu_start_offset;
- u16 rx_msdu_end_offset;
- u16 rx_msdu_start_offset;
- u16 rx_attn_offset;
- u16 rx_mpdu_start_wmask;
- u16 rx_mpdu_end_wmask;
- u32 rx_msdu_end_wmask;
- u32 conf_len_ctrl;
- u32 conf_len_mgmt;
- u32 conf_len_data;
- u16 rx_drop_threshold;
- bool enable_log_mgmt_type;
- bool enable_log_ctrl_type;
- bool enable_log_data_type;
- bool enable_rx_tlv_offset;
- u16 rx_tlv_offset;
- bool drop_threshold_valid;
- bool rxmon_disable;
-};
-
-#define HTT_STATS_FRAME_CTRL_TYPE_MGMT 0x0
-#define HTT_STATS_FRAME_CTRL_TYPE_CTRL 0x1
-#define HTT_STATS_FRAME_CTRL_TYPE_DATA 0x2
-#define HTT_STATS_FRAME_CTRL_TYPE_RESV 0x3
-
-#define HTT_TX_RING_SELECTION_CFG_CMD_INFO0_MSG_TYPE GENMASK(7, 0)
-#define HTT_TX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID GENMASK(15, 8)
-#define HTT_TX_RING_SELECTION_CFG_CMD_INFO0_RING_ID GENMASK(23, 16)
-#define HTT_TX_RING_SELECTION_CFG_CMD_INFO0_SS BIT(24)
-#define HTT_TX_RING_SELECTION_CFG_CMD_INFO0_PS BIT(25)
-
-#define HTT_TX_RING_SELECTION_CFG_CMD_INFO1_RING_BUFF_SIZE GENMASK(15, 0)
-#define HTT_TX_RING_SELECTION_CFG_CMD_INFO1_PKT_TYPE GENMASK(18, 16)
-#define HTT_TX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_MGMT GENMASK(21, 19)
-#define HTT_TX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_CTRL GENMASK(24, 22)
-#define HTT_TX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_DATA GENMASK(27, 25)
-
-#define HTT_TX_RING_SELECTION_CFG_CMD_INFO2_PKT_TYPE_EN_FLAG GENMASK(2, 0)
-
-struct htt_tx_ring_selection_cfg_cmd {
- __le32 info0;
- __le32 info1;
- __le32 info2;
- __le32 tlv_filter_mask_in0;
- __le32 tlv_filter_mask_in1;
- __le32 tlv_filter_mask_in2;
- __le32 tlv_filter_mask_in3;
- __le32 reserved[3];
-} __packed;
-
-#define HTT_TX_RING_TLV_FILTER_MGMT_DMA_LEN GENMASK(3, 0)
-#define HTT_TX_RING_TLV_FILTER_CTRL_DMA_LEN GENMASK(7, 4)
-#define HTT_TX_RING_TLV_FILTER_DATA_DMA_LEN GENMASK(11, 8)
-
-#define HTT_TX_MON_FILTER_HYBRID_MODE \
- (HTT_TX_FILTER_TLV_FLAGS0_RESPONSE_START_STATUS | \
- HTT_TX_FILTER_TLV_FLAGS0_RESPONSE_END_STATUS | \
- HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_START | \
- HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_END | \
- HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_START_PPDU | \
- HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_USER_PPDU | \
- HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_ACK_OR_BA | \
- HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_1K_BA | \
- HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_START_PROT | \
- HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_PROT | \
- HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_USER_RESPONSE | \
- HTT_TX_FILTER_TLV_FLAGS0_RECEIVED_RESPONSE_INFO | \
- HTT_TX_FILTER_TLV_FLAGS0_RECEIVED_RESPONSE_INFO_PART2)
-
-struct htt_tx_ring_tlv_filter {
- u32 tx_mon_downstream_tlv_flags;
- u32 tx_mon_upstream_tlv_flags0;
- u32 tx_mon_upstream_tlv_flags1;
- u32 tx_mon_upstream_tlv_flags2;
- bool tx_mon_mgmt_filter;
- bool tx_mon_data_filter;
- bool tx_mon_ctrl_filter;
- u16 tx_mon_pkt_dma_len;
-} __packed;
-
-enum htt_tx_mon_upstream_tlv_flags0 {
- HTT_TX_FILTER_TLV_FLAGS0_RESPONSE_START_STATUS = BIT(1),
- HTT_TX_FILTER_TLV_FLAGS0_RESPONSE_END_STATUS = BIT(2),
- HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_START = BIT(3),
- HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_END = BIT(4),
- HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_START_PPDU = BIT(5),
- HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_USER_PPDU = BIT(6),
- HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_ACK_OR_BA = BIT(7),
- HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_1K_BA = BIT(8),
- HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_START_PROT = BIT(9),
- HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_PROT = BIT(10),
- HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_USER_RESPONSE = BIT(11),
- HTT_TX_FILTER_TLV_FLAGS0_RX_FRAME_BITMAP_ACK = BIT(12),
- HTT_TX_FILTER_TLV_FLAGS0_RX_FRAME_1K_BITMAP_ACK = BIT(13),
- HTT_TX_FILTER_TLV_FLAGS0_COEX_TX_STATUS = BIT(14),
- HTT_TX_FILTER_TLV_FLAGS0_RECEIVED_RESPONSE_INFO = BIT(15),
- HTT_TX_FILTER_TLV_FLAGS0_RECEIVED_RESPONSE_INFO_PART2 = BIT(16),
-};
-
-#define HTT_TX_FILTER_TLV_FLAGS2_TXPCU_PHYTX_OTHER_TRANSMIT_INFO32 BIT(11)
-
-/* HTT message target->host */
-
-enum htt_t2h_msg_type {
- HTT_T2H_MSG_TYPE_VERSION_CONF,
- HTT_T2H_MSG_TYPE_PEER_MAP = 0x3,
- HTT_T2H_MSG_TYPE_PEER_UNMAP = 0x4,
- HTT_T2H_MSG_TYPE_RX_ADDBA = 0x5,
- HTT_T2H_MSG_TYPE_PKTLOG = 0x8,
- HTT_T2H_MSG_TYPE_SEC_IND = 0xb,
- HTT_T2H_MSG_TYPE_PEER_MAP2 = 0x1e,
- HTT_T2H_MSG_TYPE_PEER_UNMAP2 = 0x1f,
- HTT_T2H_MSG_TYPE_PPDU_STATS_IND = 0x1d,
- HTT_T2H_MSG_TYPE_EXT_STATS_CONF = 0x1c,
- HTT_T2H_MSG_TYPE_BKPRESSURE_EVENT_IND = 0x24,
- HTT_T2H_MSG_TYPE_MLO_TIMESTAMP_OFFSET_IND = 0x28,
- HTT_T2H_MSG_TYPE_PEER_MAP3 = 0x2b,
- HTT_T2H_MSG_TYPE_VDEV_TXRX_STATS_PERIODIC_IND = 0x2c,
-};
-
-#define HTT_TARGET_VERSION_MAJOR 3
-
-#define HTT_T2H_MSG_TYPE GENMASK(7, 0)
-#define HTT_T2H_VERSION_CONF_MINOR GENMASK(15, 8)
-#define HTT_T2H_VERSION_CONF_MAJOR GENMASK(23, 16)
-
-struct htt_t2h_version_conf_msg {
- __le32 version;
-} __packed;
-
-#define HTT_T2H_PEER_MAP_INFO_VDEV_ID GENMASK(15, 8)
-#define HTT_T2H_PEER_MAP_INFO_PEER_ID GENMASK(31, 16)
-#define HTT_T2H_PEER_MAP_INFO1_MAC_ADDR_H16 GENMASK(15, 0)
-#define HTT_T2H_PEER_MAP_INFO1_HW_PEER_ID GENMASK(31, 16)
-#define HTT_T2H_PEER_MAP_INFO2_AST_HASH_VAL GENMASK(15, 0)
-#define HTT_T2H_PEER_MAP3_INFO2_HW_PEER_ID GENMASK(15, 0)
-#define HTT_T2H_PEER_MAP3_INFO2_AST_HASH_VAL GENMASK(31, 16)
-#define HTT_T2H_PEER_MAP_INFO2_NEXT_HOP_M BIT(16)
-#define HTT_T2H_PEER_MAP_INFO2_NEXT_HOP_S 16
-
-struct htt_t2h_peer_map_event {
- __le32 info;
- __le32 mac_addr_l32;
- __le32 info1;
- __le32 info2;
-} __packed;
-
-#define HTT_T2H_PEER_UNMAP_INFO_VDEV_ID HTT_T2H_PEER_MAP_INFO_VDEV_ID
-#define HTT_T2H_PEER_UNMAP_INFO_PEER_ID HTT_T2H_PEER_MAP_INFO_PEER_ID
-#define HTT_T2H_PEER_UNMAP_INFO1_MAC_ADDR_H16 \
- HTT_T2H_PEER_MAP_INFO1_MAC_ADDR_H16
-#define HTT_T2H_PEER_MAP_INFO1_NEXT_HOP_M HTT_T2H_PEER_MAP_INFO2_NEXT_HOP_M
-#define HTT_T2H_PEER_MAP_INFO1_NEXT_HOP_S HTT_T2H_PEER_MAP_INFO2_NEXT_HOP_S
-
-struct htt_t2h_peer_unmap_event {
- __le32 info;
- __le32 mac_addr_l32;
- __le32 info1;
-} __packed;
-
-struct htt_resp_msg {
- union {
- struct htt_t2h_version_conf_msg version_msg;
- struct htt_t2h_peer_map_event peer_map_ev;
- struct htt_t2h_peer_unmap_event peer_unmap_ev;
- };
-} __packed;
-
-#define HTT_VDEV_GET_STATS_U64(msg_l32, msg_u32)\
- (((u64)__le32_to_cpu(msg_u32) << 32) | (__le32_to_cpu(msg_l32)))
-#define HTT_T2H_VDEV_STATS_PERIODIC_MSG_TYPE GENMASK(7, 0)
-#define HTT_T2H_VDEV_STATS_PERIODIC_PDEV_ID GENMASK(15, 8)
-#define HTT_T2H_VDEV_STATS_PERIODIC_NUM_VDEV GENMASK(23, 16)
-#define HTT_T2H_VDEV_STATS_PERIODIC_PAYLOAD_BYTES GENMASK(15, 0)
-#define HTT_VDEV_TXRX_STATS_COMMON_TLV 0
-#define HTT_VDEV_TXRX_STATS_HW_STATS_TLV 1
-
-struct htt_t2h_vdev_txrx_stats_ind {
- __le32 vdev_id;
- __le32 rx_msdu_byte_cnt_lo;
- __le32 rx_msdu_byte_cnt_hi;
- __le32 rx_msdu_cnt_lo;
- __le32 rx_msdu_cnt_hi;
- __le32 tx_msdu_byte_cnt_lo;
- __le32 tx_msdu_byte_cnt_hi;
- __le32 tx_msdu_cnt_lo;
- __le32 tx_msdu_cnt_hi;
- __le32 tx_retry_cnt_lo;
- __le32 tx_retry_cnt_hi;
- __le32 tx_retry_byte_cnt_lo;
- __le32 tx_retry_byte_cnt_hi;
- __le32 tx_drop_cnt_lo;
- __le32 tx_drop_cnt_hi;
- __le32 tx_drop_byte_cnt_lo;
- __le32 tx_drop_byte_cnt_hi;
- __le32 msdu_ttl_cnt_lo;
- __le32 msdu_ttl_cnt_hi;
- __le32 msdu_ttl_byte_cnt_lo;
- __le32 msdu_ttl_byte_cnt_hi;
-} __packed;
-
-struct htt_t2h_vdev_common_stats_tlv {
- __le32 soc_drop_count_lo;
- __le32 soc_drop_count_hi;
-} __packed;
-
-/* ppdu stats
- *
- * @details
- * The following field definitions describe the format of the HTT target
- * to host ppdu stats indication message.
- *
- *
- * |31 16|15 12|11 10|9 8|7 0 |
- * |----------------------------------------------------------------------|
- * | payload_size | rsvd |pdev_id|mac_id | msg type |
- * |----------------------------------------------------------------------|
- * | ppdu_id |
- * |----------------------------------------------------------------------|
- * | Timestamp in us |
- * |----------------------------------------------------------------------|
- * | reserved |
- * |----------------------------------------------------------------------|
- * | type-specific stats info |
- * | (see htt_ppdu_stats.h) |
- * |----------------------------------------------------------------------|
- * Header fields:
- * - MSG_TYPE
- * Bits 7:0
- * Purpose: Identifies this is a PPDU STATS indication
- * message.
- * Value: 0x1d
- * - mac_id
- * Bits 9:8
- * Purpose: mac_id of this ppdu_id
- * Value: 0-3
- * - pdev_id
- * Bits 11:10
- * Purpose: pdev_id of this ppdu_id
- * Value: 0-3
- * 0 (for rings at SOC level),
- * 1/2/3 PDEV -> 0/1/2
- * - payload_size
- * Bits 31:16
- * Purpose: total tlv size
- * Value: payload_size in bytes
- */
-
-#define HTT_T2H_PPDU_STATS_INFO_PDEV_ID GENMASK(11, 10)
-#define HTT_T2H_PPDU_STATS_INFO_PAYLOAD_SIZE GENMASK(31, 16)
-
-struct ath12k_htt_ppdu_stats_msg {
- __le32 info;
- __le32 ppdu_id;
- __le32 timestamp;
- __le32 rsvd;
- u8 data[];
-} __packed;
-
-struct htt_tlv {
- __le32 header;
- u8 value[];
-} __packed;
-
-#define HTT_TLV_TAG GENMASK(11, 0)
-#define HTT_TLV_LEN GENMASK(23, 12)
-
-enum HTT_PPDU_STATS_BW {
- HTT_PPDU_STATS_BANDWIDTH_5MHZ = 0,
- HTT_PPDU_STATS_BANDWIDTH_10MHZ = 1,
- HTT_PPDU_STATS_BANDWIDTH_20MHZ = 2,
- HTT_PPDU_STATS_BANDWIDTH_40MHZ = 3,
- HTT_PPDU_STATS_BANDWIDTH_80MHZ = 4,
- HTT_PPDU_STATS_BANDWIDTH_160MHZ = 5, /* includes 80+80 */
- HTT_PPDU_STATS_BANDWIDTH_DYN = 6,
-};
-
-#define HTT_PPDU_STATS_CMN_FLAGS_FRAME_TYPE_M GENMASK(7, 0)
-#define HTT_PPDU_STATS_CMN_FLAGS_QUEUE_TYPE_M GENMASK(15, 8)
-/* bw - HTT_PPDU_STATS_BW */
-#define HTT_PPDU_STATS_CMN_FLAGS_BW_M GENMASK(19, 16)
-
-struct htt_ppdu_stats_common {
- __le32 ppdu_id;
- __le16 sched_cmdid;
- u8 ring_id;
- u8 num_users;
- __le32 flags; /* %HTT_PPDU_STATS_COMMON_FLAGS_*/
- __le32 chain_mask;
- __le32 fes_duration_us; /* frame exchange sequence */
- __le32 ppdu_sch_eval_start_tstmp_us;
- __le32 ppdu_sch_end_tstmp_us;
- __le32 ppdu_start_tstmp_us;
- /* BIT [15 : 0] - phy mode (WLAN_PHY_MODE) with which ppdu was transmitted
- * BIT [31 : 16] - bandwidth (in MHz) with which ppdu was transmitted
+ const struct ath12k_hw_params *hw_params;
+ struct device *dev;
+ struct ath12k_hal *hal;
+
+ /* RCU on dp_pdevs[] provides a teardown synchronization mechanism,
+ * ensuring in-flight data path readers complete before reclaim. Writers
+ * update internal fields under their own synchronization, while readers of
+ * internal fields may perform lockless read if occasional inconsistency
+ * is acceptable or use additional synchronization for a coherent view.
+ *
+ * RCU is used for dp_pdevs[] at this stage to align with
+ * ab->pdevs_active[]. However, if the teardown paths ensure quiescence,
+ * both dp_pdevs[] and pdevs_active[] can be converted to plain pointers,
+ * removing RCU synchronize overhead.
+ *
+ * TODO: evaluate removal of RCU from dp_pdevs in the future
*/
- __le16 phy_mode;
- __le16 bw_mhz;
-} __packed;
+ struct ath12k_pdev_dp __rcu *dp_pdevs[MAX_RADIOS];
-enum htt_ppdu_stats_gi {
- HTT_PPDU_STATS_SGI_0_8_US,
- HTT_PPDU_STATS_SGI_0_4_US,
- HTT_PPDU_STATS_SGI_1_6_US,
- HTT_PPDU_STATS_SGI_3_2_US,
-};
+ struct ath12k_hw_group *ag;
+ u8 device_id;
-#define HTT_PPDU_STATS_USER_RATE_INFO0_USER_POS_M GENMASK(3, 0)
-#define HTT_PPDU_STATS_USER_RATE_INFO0_MU_GROUP_ID_M GENMASK(11, 4)
-
-enum HTT_PPDU_STATS_PPDU_TYPE {
- HTT_PPDU_STATS_PPDU_TYPE_SU,
- HTT_PPDU_STATS_PPDU_TYPE_MU_MIMO,
- HTT_PPDU_STATS_PPDU_TYPE_MU_OFDMA,
- HTT_PPDU_STATS_PPDU_TYPE_MU_MIMO_OFDMA,
- HTT_PPDU_STATS_PPDU_TYPE_UL_TRIG,
- HTT_PPDU_STATS_PPDU_TYPE_BURST_BCN,
- HTT_PPDU_STATS_PPDU_TYPE_UL_BSR_RESP,
- HTT_PPDU_STATS_PPDU_TYPE_UL_BSR_TRIG,
- HTT_PPDU_STATS_PPDU_TYPE_UL_RESP,
- HTT_PPDU_STATS_PPDU_TYPE_MAX
-};
+ /* Lock for protection of peers and rhead_peer_addr */
+ spinlock_t dp_lock;
-#define HTT_PPDU_STATS_USER_RATE_INFO1_RESP_TYPE_VALD_M BIT(0)
-#define HTT_PPDU_STATS_USER_RATE_INFO1_PPDU_TYPE_M GENMASK(5, 1)
-
-#define HTT_PPDU_STATS_USER_RATE_FLAGS_LTF_SIZE_M GENMASK(1, 0)
-#define HTT_PPDU_STATS_USER_RATE_FLAGS_STBC_M BIT(2)
-#define HTT_PPDU_STATS_USER_RATE_FLAGS_HE_RE_M BIT(3)
-#define HTT_PPDU_STATS_USER_RATE_FLAGS_TXBF_M GENMASK(7, 4)
-#define HTT_PPDU_STATS_USER_RATE_FLAGS_BW_M GENMASK(11, 8)
-#define HTT_PPDU_STATS_USER_RATE_FLAGS_NSS_M GENMASK(15, 12)
-#define HTT_PPDU_STATS_USER_RATE_FLAGS_MCS_M GENMASK(19, 16)
-#define HTT_PPDU_STATS_USER_RATE_FLAGS_PREAMBLE_M GENMASK(23, 20)
-#define HTT_PPDU_STATS_USER_RATE_FLAGS_GI_M GENMASK(27, 24)
-#define HTT_PPDU_STATS_USER_RATE_FLAGS_DCM_M BIT(28)
-#define HTT_PPDU_STATS_USER_RATE_FLAGS_LDPC_M BIT(29)
-
-#define HTT_USR_RATE_PPDU_TYPE(_val) \
- le32_get_bits(_val, HTT_PPDU_STATS_USER_RATE_INFO1_PPDU_TYPE_M)
-#define HTT_USR_RATE_PREAMBLE(_val) \
- le32_get_bits(_val, HTT_PPDU_STATS_USER_RATE_FLAGS_PREAMBLE_M)
-#define HTT_USR_RATE_BW(_val) \
- le32_get_bits(_val, HTT_PPDU_STATS_USER_RATE_FLAGS_BW_M)
-#define HTT_USR_RATE_NSS(_val) \
- le32_get_bits(_val, HTT_PPDU_STATS_USER_RATE_FLAGS_NSS_M)
-#define HTT_USR_RATE_MCS(_val) \
- le32_get_bits(_val, HTT_PPDU_STATS_USER_RATE_FLAGS_MCS_M)
-#define HTT_USR_RATE_GI(_val) \
- le32_get_bits(_val, HTT_PPDU_STATS_USER_RATE_FLAGS_GI_M)
-#define HTT_USR_RATE_DCM(_val) \
- le32_get_bits(_val, HTT_PPDU_STATS_USER_RATE_FLAGS_DCM_M)
-
-#define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_LTF_SIZE_M GENMASK(1, 0)
-#define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_STBC_M BIT(2)
-#define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_HE_RE_M BIT(3)
-#define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_TXBF_M GENMASK(7, 4)
-#define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_BW_M GENMASK(11, 8)
-#define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_NSS_M GENMASK(15, 12)
-#define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_MCS_M GENMASK(19, 16)
-#define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_PREAMBLE_M GENMASK(23, 20)
-#define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_GI_M GENMASK(27, 24)
-#define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_DCM_M BIT(28)
-#define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_LDPC_M BIT(29)
-
-struct htt_ppdu_stats_user_rate {
- u8 tid_num;
- u8 reserved0;
- __le16 sw_peer_id;
- __le32 info0; /* %HTT_PPDU_STATS_USER_RATE_INFO0_*/
- __le16 ru_end;
- __le16 ru_start;
- __le16 resp_ru_end;
- __le16 resp_ru_start;
- __le32 info1; /* %HTT_PPDU_STATS_USER_RATE_INFO1_ */
- __le32 rate_flags; /* %HTT_PPDU_STATS_USER_RATE_FLAGS_ */
- /* Note: resp_rate_info is only valid for if resp_type is UL */
- __le32 resp_rate_flags; /* %HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_ */
-} __packed;
+ struct ath12k_dp_arch_ops *ops;
-#define HTT_PPDU_STATS_TX_INFO_FLAGS_RATECODE_M GENMASK(7, 0)
-#define HTT_PPDU_STATS_TX_INFO_FLAGS_IS_AMPDU_M BIT(8)
-#define HTT_PPDU_STATS_TX_INFO_FLAGS_BA_ACK_FAILED_M GENMASK(10, 9)
-#define HTT_PPDU_STATS_TX_INFO_FLAGS_BW_M GENMASK(13, 11)
-#define HTT_PPDU_STATS_TX_INFO_FLAGS_SGI_M BIT(14)
-#define HTT_PPDU_STATS_TX_INFO_FLAGS_PEERID_M GENMASK(31, 16)
-
-#define HTT_TX_INFO_IS_AMSDU(_flags) \
- u32_get_bits(_flags, HTT_PPDU_STATS_TX_INFO_FLAGS_IS_AMPDU_M)
-#define HTT_TX_INFO_BA_ACK_FAILED(_flags) \
- u32_get_bits(_flags, HTT_PPDU_STATS_TX_INFO_FLAGS_BA_ACK_FAILED_M)
-#define HTT_TX_INFO_RATECODE(_flags) \
- u32_get_bits(_flags, HTT_PPDU_STATS_TX_INFO_FLAGS_RATECODE_M)
-#define HTT_TX_INFO_PEERID(_flags) \
- u32_get_bits(_flags, HTT_PPDU_STATS_TX_INFO_FLAGS_PEERID_M)
-
-enum htt_ppdu_stats_usr_compln_status {
- HTT_PPDU_STATS_USER_STATUS_OK,
- HTT_PPDU_STATS_USER_STATUS_FILTERED,
- HTT_PPDU_STATS_USER_STATUS_RESP_TIMEOUT,
- HTT_PPDU_STATS_USER_STATUS_RESP_MISMATCH,
- HTT_PPDU_STATS_USER_STATUS_ABORT,
-};
-
-#define HTT_PPDU_STATS_USR_CMPLTN_CMN_FLAGS_LONG_RETRY_M GENMASK(3, 0)
-#define HTT_PPDU_STATS_USR_CMPLTN_CMN_FLAGS_SHORT_RETRY_M GENMASK(7, 4)
-#define HTT_PPDU_STATS_USR_CMPLTN_CMN_FLAGS_IS_AMPDU_M BIT(8)
-#define HTT_PPDU_STATS_USR_CMPLTN_CMN_FLAGS_RESP_TYPE_M GENMASK(12, 9)
-
-#define HTT_USR_CMPLTN_IS_AMPDU(_val) \
- le32_get_bits(_val, HTT_PPDU_STATS_USR_CMPLTN_CMN_FLAGS_IS_AMPDU_M)
-#define HTT_USR_CMPLTN_LONG_RETRY(_val) \
- le32_get_bits(_val, HTT_PPDU_STATS_USR_CMPLTN_CMN_FLAGS_LONG_RETRY_M)
-#define HTT_USR_CMPLTN_SHORT_RETRY(_val) \
- le32_get_bits(_val, HTT_PPDU_STATS_USR_CMPLTN_CMN_FLAGS_SHORT_RETRY_M)
-
-struct htt_ppdu_stats_usr_cmpltn_cmn {
- u8 status;
- u8 tid_num;
- __le16 sw_peer_id;
- /* RSSI value of last ack packet (units = dB above noise floor) */
- __le32 ack_rssi;
- __le16 mpdu_tried;
- __le16 mpdu_success;
- __le32 flags; /* %HTT_PPDU_STATS_USR_CMPLTN_CMN_FLAGS_LONG_RETRIES*/
-} __packed;
+ /* Linked list of struct ath12k_dp_link_peer */
+ struct list_head peers;
-#define HTT_PPDU_STATS_ACK_BA_INFO_NUM_MPDU_M GENMASK(8, 0)
-#define HTT_PPDU_STATS_ACK_BA_INFO_NUM_MSDU_M GENMASK(24, 9)
-#define HTT_PPDU_STATS_ACK_BA_INFO_TID_NUM GENMASK(31, 25)
+ /* For rhash table init and deinit protection */
+ struct mutex link_peer_rhash_tbl_lock;
-#define HTT_PPDU_STATS_NON_QOS_TID 16
-
-struct htt_ppdu_stats_usr_cmpltn_ack_ba_status {
- __le32 ppdu_id;
- __le16 sw_peer_id;
- __le16 reserved0;
- __le32 info; /* %HTT_PPDU_STATS_USR_CMPLTN_CMN_INFO_ */
- __le16 current_seq;
- __le16 start_seq;
- __le32 success_bytes;
-} __packed;
-
-struct htt_ppdu_user_stats {
- u16 peer_id;
- u16 delay_ba;
- u32 tlv_flags;
- bool is_valid_peer_id;
- struct htt_ppdu_stats_user_rate rate;
- struct htt_ppdu_stats_usr_cmpltn_cmn cmpltn_cmn;
- struct htt_ppdu_stats_usr_cmpltn_ack_ba_status ack_ba;
+ /* The rhashtable containing struct ath12k_link_peer keyed by mac addr */
+ struct rhashtable *rhead_peer_addr;
+ struct rhashtable_params rhash_peer_addr_param;
+ struct ath12k_device_dp_stats device_stats;
};
-#define HTT_PPDU_STATS_MAX_USERS 8
-#define HTT_PPDU_DESC_MAX_DEPTH 16
+static inline u32 ath12k_dp_arch_tx_get_vdev_bank_config(struct ath12k_dp *dp,
+ struct ath12k_link_vif *arvif)
+{
+ return dp->ops->tx_get_vdev_bank_config(dp->ab, arvif);
+}
-struct htt_ppdu_stats {
- struct htt_ppdu_stats_common common;
- struct htt_ppdu_user_stats user_stats[HTT_PPDU_STATS_MAX_USERS];
-};
+static inline int ath12k_dp_arch_reo_cmd_send(struct ath12k_dp *dp,
+ struct ath12k_dp_rx_tid_rxq *rx_tid,
+ enum hal_reo_cmd_type type,
+ struct ath12k_hal_reo_cmd *cmd,
+ void (*cb)(struct ath12k_dp *dp, void *ctx,
+ enum hal_reo_cmd_status status))
+{
+ return dp->ops->reo_cmd_send(dp->ab, rx_tid, type, cmd, cb);
+}
-struct htt_ppdu_stats_info {
- u32 tlv_bitmap;
- u32 ppdu_id;
- u32 frame_type;
- u32 frame_ctrl;
- u32 delay_ba;
- u32 bar_num_users;
- struct htt_ppdu_stats ppdu_stats;
- struct list_head list;
-};
+static inline
+void ath12k_dp_arch_setup_pn_check_reo_cmd(struct ath12k_dp *dp,
+ struct ath12k_hal_reo_cmd *cmd,
+ struct ath12k_dp_rx_tid *rx_tid,
+ u32 cipher,
+ enum set_key_cmd key_cmd)
+{
+ dp->ops->setup_pn_check_reo_cmd(cmd, rx_tid, cipher, key_cmd);
+}
-/* @brief target -> host MLO offset indiciation message
- *
- * @details
- * The following field definitions describe the format of the HTT target
- * to host mlo offset indication message.
- *
- *
- * |31 29|28 |26|25 22|21 16|15 13|12 10 |9 8|7 0|
- * |---------------------------------------------------------------------|
- * | rsvd1 | mac_freq |chip_id |pdev_id|msgtype|
- * |---------------------------------------------------------------------|
- * | sync_timestamp_lo_us |
- * |---------------------------------------------------------------------|
- * | sync_timestamp_hi_us |
- * |---------------------------------------------------------------------|
- * | mlo_offset_lo |
- * |---------------------------------------------------------------------|
- * | mlo_offset_hi |
- * |---------------------------------------------------------------------|
- * | mlo_offset_clcks |
- * |---------------------------------------------------------------------|
- * | rsvd2 | mlo_comp_clks |mlo_comp_us |
- * |---------------------------------------------------------------------|
- * | rsvd3 |mlo_comp_timer |
- * |---------------------------------------------------------------------|
- * Header fields
- * - MSG_TYPE
- * Bits 7:0
- * Purpose: Identifies this is a MLO offset indication msg
- * - PDEV_ID
- * Bits 9:8
- * Purpose: Pdev of this MLO offset
- * - CHIP_ID
- * Bits 12:10
- * Purpose: chip_id of this MLO offset
- * - MAC_FREQ
- * Bits 28:13
- * - SYNC_TIMESTAMP_LO_US
- * Purpose: clock frequency of the mac HW block in MHz
- * Bits: 31:0
- * Purpose: lower 32 bits of the WLAN global time stamp at which
- * last sync interrupt was received
- * - SYNC_TIMESTAMP_HI_US
- * Bits: 31:0
- * Purpose: upper 32 bits of WLAN global time stamp at which
- * last sync interrupt was received
- * - MLO_OFFSET_LO
- * Bits: 31:0
- * Purpose: lower 32 bits of the MLO offset in us
- * - MLO_OFFSET_HI
- * Bits: 31:0
- * Purpose: upper 32 bits of the MLO offset in us
- * - MLO_COMP_US
- * Bits: 15:0
- * Purpose: MLO time stamp compensation applied in us
- * - MLO_COMP_CLCKS
- * Bits: 25:16
- * Purpose: MLO time stamp compensation applied in clock ticks
- * - MLO_COMP_TIMER
- * Bits: 21:0
- * Purpose: Periodic timer at which compensation is applied
- */
+static inline void ath12k_dp_arch_rx_peer_tid_delete(struct ath12k_dp *dp,
+ struct ath12k_dp_link_peer *peer,
+ u8 tid)
+{
+ dp->ops->rx_peer_tid_delete(dp->ab, peer, tid);
+}
-#define HTT_T2H_MLO_OFFSET_INFO_MSG_TYPE GENMASK(7, 0)
-#define HTT_T2H_MLO_OFFSET_INFO_PDEV_ID GENMASK(9, 8)
-
-struct ath12k_htt_mlo_offset_msg {
- __le32 info;
- __le32 sync_timestamp_lo_us;
- __le32 sync_timestamp_hi_us;
- __le32 mlo_offset_hi;
- __le32 mlo_offset_lo;
- __le32 mlo_offset_clks;
- __le32 mlo_comp_clks;
- __le32 mlo_comp_timer;
-} __packed;
+static inline int ath12k_dp_arch_reo_cache_flush(struct ath12k_dp *dp,
+ struct ath12k_dp_rx_tid_rxq *rx_tid)
+{
+ return dp->ops->reo_cache_flush(dp->ab, rx_tid);
+}
-/* @brief host -> target FW extended statistics retrieve
- *
- * @details
- * The following field definitions describe the format of the HTT host
- * to target FW extended stats retrieve message.
- * The message specifies the type of stats the host wants to retrieve.
- *
- * |31 24|23 16|15 8|7 0|
- * |-----------------------------------------------------------|
- * | reserved | stats type | pdev_mask | msg type |
- * |-----------------------------------------------------------|
- * | config param [0] |
- * |-----------------------------------------------------------|
- * | config param [1] |
- * |-----------------------------------------------------------|
- * | config param [2] |
- * |-----------------------------------------------------------|
- * | config param [3] |
- * |-----------------------------------------------------------|
- * | reserved |
- * |-----------------------------------------------------------|
- * | cookie LSBs |
- * |-----------------------------------------------------------|
- * | cookie MSBs |
- * |-----------------------------------------------------------|
- * Header fields:
- * - MSG_TYPE
- * Bits 7:0
- * Purpose: identifies this is a extended stats upload request message
- * Value: 0x10
- * - PDEV_MASK
- * Bits 8:15
- * Purpose: identifies the mask of PDEVs to retrieve stats from
- * Value: This is a overloaded field, refer to usage and interpretation of
- * PDEV in interface document.
- * Bit 8 : Reserved for SOC stats
- * Bit 9 - 15 : Indicates PDEV_MASK in DBDC
- * Indicates MACID_MASK in DBS
- * - STATS_TYPE
- * Bits 23:16
- * Purpose: identifies which FW statistics to upload
- * Value: Defined by htt_dbg_ext_stats_type (see htt_stats.h)
- * - Reserved
- * Bits 31:24
- * - CONFIG_PARAM [0]
- * Bits 31:0
- * Purpose: give an opaque configuration value to the specified stats type
- * Value: stats-type specific configuration value
- * Refer to htt_stats.h for interpretation for each stats sub_type
- * - CONFIG_PARAM [1]
- * Bits 31:0
- * Purpose: give an opaque configuration value to the specified stats type
- * Value: stats-type specific configuration value
- * Refer to htt_stats.h for interpretation for each stats sub_type
- * - CONFIG_PARAM [2]
- * Bits 31:0
- * Purpose: give an opaque configuration value to the specified stats type
- * Value: stats-type specific configuration value
- * Refer to htt_stats.h for interpretation for each stats sub_type
- * - CONFIG_PARAM [3]
- * Bits 31:0
- * Purpose: give an opaque configuration value to the specified stats type
- * Value: stats-type specific configuration value
- * Refer to htt_stats.h for interpretation for each stats sub_type
- * - Reserved [31:0] for future use.
- * - COOKIE_LSBS
- * Bits 31:0
- * Purpose: Provide a mechanism to match a target->host stats confirmation
- * message with its preceding host->target stats request message.
- * Value: LSBs of the opaque cookie specified by the host-side requestor
- * - COOKIE_MSBS
- * Bits 31:0
- * Purpose: Provide a mechanism to match a target->host stats confirmation
- * message with its preceding host->target stats request message.
- * Value: MSBs of the opaque cookie specified by the host-side requestor
- */
+static inline
+int ath12k_dp_arch_rx_link_desc_return(struct ath12k_dp *dp,
+ struct ath12k_buffer_addr *buf_addr_info,
+ enum hal_wbm_rel_bm_act action)
+{
+ return dp->ops->rx_link_desc_return(dp, buf_addr_info, action);
+}
-struct htt_ext_stats_cfg_hdr {
- u8 msg_type;
- u8 pdev_mask;
- u8 stats_type;
- u8 reserved;
-} __packed;
+static inline
+void ath12k_dp_arch_rx_frags_cleanup(struct ath12k_dp *dp,
+ struct ath12k_dp_rx_tid *rx_tid,
+ bool rel_link_desc)
+{
+ dp->ops->rx_frags_cleanup(rx_tid, rel_link_desc);
+}
-struct htt_ext_stats_cfg_cmd {
- struct htt_ext_stats_cfg_hdr hdr;
- __le32 cfg_param0;
- __le32 cfg_param1;
- __le32 cfg_param2;
- __le32 cfg_param3;
- __le32 reserved;
- __le32 cookie_lsb;
- __le32 cookie_msb;
-} __packed;
+static inline int ath12k_dp_arch_peer_rx_tid_reo_update(struct ath12k_dp *dp,
+ struct ath12k_dp_link_peer *peer,
+ struct ath12k_dp_rx_tid *rx_tid,
+ u32 ba_win_sz, u16 ssn,
+ bool update_ssn)
+{
+ return dp->ops->peer_rx_tid_reo_update(dp, peer, rx_tid,
+ ba_win_sz, ssn, update_ssn);
+}
-/* htt stats config default params */
-#define HTT_STAT_DEFAULT_RESET_START_OFFSET 0
-#define HTT_STAT_DEFAULT_CFG0_ALL_HWQS 0xffffffff
-#define HTT_STAT_DEFAULT_CFG0_ALL_TXQS 0xffffffff
-#define HTT_STAT_DEFAULT_CFG0_ALL_CMDQS 0xffff
-#define HTT_STAT_DEFAULT_CFG0_ALL_RINGS 0xffff
-#define HTT_STAT_DEFAULT_CFG0_ACTIVE_PEERS 0xff
-#define HTT_STAT_DEFAULT_CFG0_CCA_CUMULATIVE 0x00
-#define HTT_STAT_DEFAULT_CFG0_ACTIVE_VDEVS 0x00
-
-/* HTT_DBG_EXT_STATS_PEER_INFO
- * PARAMS:
- * @config_param0:
- * [Bit0] - [0] for sw_peer_id, [1] for mac_addr based request
- * [Bit15 : Bit 1] htt_peer_stats_req_mode_t
- * [Bit31 : Bit16] sw_peer_id
- * @config_param1:
- * peer_stats_req_type_mask:32 (enum htt_peer_stats_tlv_enum)
- * 0 bit htt_peer_stats_cmn_tlv
- * 1 bit htt_peer_details_tlv
- * 2 bit htt_tx_peer_rate_stats_tlv
- * 3 bit htt_rx_peer_rate_stats_tlv
- * 4 bit htt_tx_tid_stats_tlv/htt_tx_tid_stats_v1_tlv
- * 5 bit htt_rx_tid_stats_tlv
- * 6 bit htt_msdu_flow_stats_tlv
- * @config_param2: [Bit31 : Bit0] mac_addr31to0
- * @config_param3: [Bit15 : Bit0] mac_addr47to32
- * [Bit31 : Bit16] reserved
- */
-#define HTT_STAT_PEER_INFO_MAC_ADDR BIT(0)
-#define HTT_STAT_DEFAULT_PEER_REQ_TYPE 0x7f
-
-/* Used to set different configs to the specified stats type.*/
-struct htt_ext_stats_cfg_params {
- u32 cfg0;
- u32 cfg1;
- u32 cfg2;
- u32 cfg3;
-};
+static inline int ath12k_dp_arch_rx_assign_reoq(struct ath12k_dp *dp,
+ struct ath12k_dp_peer *dp_peer,
+ struct ath12k_dp_rx_tid *rx_tid,
+ u16 ssn, enum hal_pn_type pn_type)
+{
+ return dp->ops->rx_assign_reoq(dp->ab, dp_peer, rx_tid, ssn, pn_type);
+}
-enum vdev_stats_offload_timer_duration {
- ATH12K_STATS_TIMER_DUR_500MS = 1,
- ATH12K_STATS_TIMER_DUR_1SEC = 2,
- ATH12K_STATS_TIMER_DUR_2SEC = 3,
-};
+static inline void ath12k_dp_arch_peer_rx_tid_qref_setup(struct ath12k_dp *dp,
+ u16 peer_id, u16 tid,
+ dma_addr_t paddr)
+{
+ dp->ops->peer_rx_tid_qref_setup(dp->ab, peer_id, tid, paddr);
+}
-#define ATH12K_HTT_MAC_ADDR_L32_0 GENMASK(7, 0)
-#define ATH12K_HTT_MAC_ADDR_L32_1 GENMASK(15, 8)
-#define ATH12K_HTT_MAC_ADDR_L32_2 GENMASK(23, 16)
-#define ATH12K_HTT_MAC_ADDR_L32_3 GENMASK(31, 24)
-#define ATH12K_HTT_MAC_ADDR_H16_0 GENMASK(7, 0)
-#define ATH12K_HTT_MAC_ADDR_H16_1 GENMASK(15, 8)
+static inline void ath12k_dp_arch_peer_rx_tid_qref_reset(struct ath12k_dp *dp,
+ u16 peer_id, u16 tid)
+{
+ dp->ops->peer_rx_tid_qref_reset(dp->ab, peer_id, tid);
+}
-struct htt_mac_addr {
- __le32 mac_addr_l32;
- __le32 mac_addr_h16;
-} __packed;
+static inline
+int ath12k_dp_arch_rx_tid_delete_handler(struct ath12k_dp *dp,
+ struct ath12k_dp_rx_tid_rxq *rx_tid)
+{
+ return dp->ops->rx_tid_delete_handler(dp->ab, rx_tid);
+}
static inline void ath12k_dp_get_mac_addr(u32 addr_l32, u16 addr_h16, u8 *addr)
{
@@ -1940,20 +651,39 @@ static inline void ath12k_dp_get_mac_addr(u32 addr_l32, u16 addr_h16, u8 *addr)
memcpy(addr + 4, &addr_h16, ETH_ALEN - 4);
}
-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);
+static inline struct ath12k_dp *
+ath12k_dp_hw_grp_to_dp(struct ath12k_dp_hw_group *dp_hw_grp, u8 device_id)
+{
+ return dp_hw_grp->dp[device_id];
+}
+
+static inline int
+ath12k_dp_service_srng(struct ath12k_dp *dp, struct ath12k_ext_irq_grp *irq_grp,
+ int budget)
+{
+ return dp->ops->service_srng(dp, irq_grp, budget);
+}
+
+static inline struct ieee80211_hw *
+ath12k_pdev_dp_to_hw(struct ath12k_pdev_dp *pdev)
+{
+ return pdev->hw;
+}
+
+static inline struct ath12k_pdev_dp *
+ath12k_dp_to_pdev_dp(struct ath12k_dp *dp, u8 pdev_idx)
+{
+ RCU_LOCKDEP_WARN(!rcu_read_lock_held(),
+ "ath12k dp to dp pdev called without rcu lock");
+
+ return rcu_dereference(dp->dp_pdevs[pdev_idx]);
+}
+
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);
void ath12k_dp_partner_cc_init(struct ath12k_base *ab);
int ath12k_dp_pdev_alloc(struct ath12k_base *ab);
void ath12k_dp_pdev_pre_alloc(struct ath12k *ar);
void ath12k_dp_pdev_free(struct ath12k_base *ab);
-int ath12k_dp_tx_htt_srng_setup(struct ath12k_base *ab, u32 ring_id,
- int mac_id, enum hal_ring_type ring_type);
int ath12k_dp_peer_setup(struct ath12k *ar, int vdev_id, const u8 *addr);
void ath12k_dp_peer_cleanup(struct ath12k *ar, int vdev_id, const u8 *addr);
void ath12k_dp_srng_cleanup(struct ath12k_base *ab, struct dp_srng *ring);
@@ -1967,10 +697,8 @@ int ath12k_dp_link_desc_setup(struct ath12k_base *ab,
struct dp_link_desc_bank *link_desc_banks,
u32 ring_type, struct hal_srng *srng,
u32 n_link_desc);
-struct ath12k_rx_desc_info *ath12k_dp_get_rx_desc(struct ath12k_base *ab,
+struct ath12k_rx_desc_info *ath12k_dp_get_rx_desc(struct ath12k_dp *dp,
u32 cookie);
-struct ath12k_tx_desc_info *ath12k_dp_get_tx_desc(struct ath12k_base *ab,
+struct ath12k_tx_desc_info *ath12k_dp_get_tx_desc(struct ath12k_dp *dp,
u32 desc_id);
-bool ath12k_dp_wmask_compaction_rx_tlv_supported(struct ath12k_base *ab);
-void ath12k_dp_hal_rx_desc_init(struct ath12k_base *ab);
#endif
diff --git a/drivers/net/wireless/ath/ath12k/dp_cmn.h b/drivers/net/wireless/ath/ath12k/dp_cmn.h
new file mode 100644
index 000000000000..e17f044ff812
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/dp_cmn.h
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef ATH12K_DP_CMN_H
+#define ATH12K_DP_CMN_H
+
+#include "cmn_defs.h"
+
+struct ath12k_hw_group;
+
+/*
+ * ML Peer IDs start from 8192, assuming max SLO clients count 1536,
+ * then max peer id shall be 9728, therefore rounding the peer table size
+ * to the nearest next power of 2 i.e 16384.
+ */
+#define MAX_DP_PEER_LIST_SIZE 16384
+
+struct ath12k_dp_hw {
+ struct ath12k_dp_peer __rcu *dp_peers[MAX_DP_PEER_LIST_SIZE];
+
+ /* Lock for protection of dp_peer_list and peers */
+ spinlock_t peer_lock;
+ struct list_head dp_peers_list;
+};
+
+struct ath12k_dp_hw_group {
+ struct ath12k_dp *dp[ATH12K_MAX_DEVICES];
+};
+
+struct ath12k_dp_link_vif {
+ u32 vdev_id;
+ u8 search_type;
+ u8 hal_addr_search_flags;
+ u8 pdev_idx;
+ u8 lmac_id;
+ u16 ast_idx;
+ u16 ast_hash;
+ u16 tcl_metadata;
+ u8 vdev_id_check_en;
+ int bank_id;
+};
+
+struct ath12k_dp_vif {
+ u8 tx_encap_type;
+ u32 key_cipher;
+ atomic_t mcbc_gsn;
+ struct ath12k_dp_link_vif dp_link_vif[ATH12K_NUM_MAX_LINKS];
+};
+
+/* TODO: Move this to a separate dp_stats file */
+struct ath12k_per_peer_tx_stats {
+ u32 succ_bytes;
+ u32 retry_bytes;
+ u32 failed_bytes;
+ u32 duration;
+ u16 succ_pkts;
+ u16 retry_pkts;
+ u16 failed_pkts;
+ u16 ru_start;
+ u16 ru_tones;
+ u8 ba_fails;
+ u8 ppdu_type;
+ u32 mu_grpid;
+ u32 mu_pos;
+ bool is_ampdu;
+};
+
+struct ath12k_dp_peer_create_params {
+ struct ieee80211_sta *sta;
+ bool is_mlo;
+ u16 peer_id;
+ bool ucast_ra_only;
+};
+
+struct ath12k_dp_link_peer_rate_info {
+ struct rate_info txrate;
+ u64 rx_duration;
+ u64 tx_duration;
+ u8 rssi_comb;
+ s8 signal_avg;
+};
+
+static inline struct ath12k_dp_link_vif *
+ath12k_dp_vif_to_dp_link_vif(struct ath12k_dp_vif *dp_vif, u8 link_id)
+{
+ return &dp_vif->dp_link_vif[link_id];
+}
+
+void ath12k_dp_cmn_device_deinit(struct ath12k_dp *dp);
+int ath12k_dp_cmn_device_init(struct ath12k_dp *dp);
+void ath12k_dp_cmn_hw_group_unassign(struct ath12k_dp *dp,
+ struct ath12k_hw_group *ag);
+void ath12k_dp_cmn_hw_group_assign(struct ath12k_dp *dp,
+ struct ath12k_hw_group *ag);
+int ath12k_dp_link_peer_assign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_hw,
+ u8 vdev_id, struct ieee80211_sta *sta, u8 *addr,
+ u8 link_id, u32 hw_link_id);
+void ath12k_dp_link_peer_unassign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_hw,
+ u8 vdev_id, u8 *addr, u32 hw_link_id);
+void
+ath12k_dp_link_peer_get_sta_rate_info_stats(struct ath12k_dp *dp, const u8 *addr,
+ struct ath12k_dp_link_peer_rate_info *info);
+void ath12k_dp_link_peer_reset_rx_stats(struct ath12k_dp *dp, const u8 *addr);
+#endif
diff --git a/drivers/net/wireless/ath/ath12k/dp_htt.c b/drivers/net/wireless/ath/ath12k/dp_htt.c
new file mode 100644
index 000000000000..cc71c5c5de5a
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/dp_htt.c
@@ -0,0 +1,1353 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include "core.h"
+#include "peer.h"
+#include "htc.h"
+#include "dp_htt.h"
+#include "debugfs_htt_stats.h"
+#include "debugfs.h"
+
+static void ath12k_dp_htt_htc_tx_complete(struct ath12k_base *ab,
+ struct sk_buff *skb)
+{
+ dev_kfree_skb_any(skb);
+}
+
+int ath12k_dp_htt_connect(struct ath12k_dp *dp)
+{
+ struct ath12k_htc_svc_conn_req conn_req = {};
+ struct ath12k_htc_svc_conn_resp conn_resp = {};
+ int status;
+
+ conn_req.ep_ops.ep_tx_complete = ath12k_dp_htt_htc_tx_complete;
+ conn_req.ep_ops.ep_rx_complete = ath12k_dp_htt_htc_t2h_msg_handler;
+
+ /* connect to control service */
+ conn_req.service_id = ATH12K_HTC_SVC_ID_HTT_DATA_MSG;
+
+ status = ath12k_htc_connect_service(&dp->ab->htc, &conn_req,
+ &conn_resp);
+
+ if (status)
+ return status;
+
+ dp->eid = conn_resp.eid;
+
+ return 0;
+}
+
+static int ath12k_get_ppdu_user_index(struct htt_ppdu_stats *ppdu_stats,
+ u16 peer_id)
+{
+ int i;
+
+ for (i = 0; i < HTT_PPDU_STATS_MAX_USERS - 1; i++) {
+ if (ppdu_stats->user_stats[i].is_valid_peer_id) {
+ if (peer_id == ppdu_stats->user_stats[i].peer_id)
+ return i;
+ } else {
+ return i;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int ath12k_htt_tlv_ppdu_stats_parse(struct ath12k_base *ab,
+ u16 tag, u16 len, const void *ptr,
+ void *data)
+{
+ const struct htt_ppdu_stats_usr_cmpltn_ack_ba_status *ba_status;
+ const struct htt_ppdu_stats_usr_cmpltn_cmn *cmplt_cmn;
+ const struct htt_ppdu_stats_user_rate *user_rate;
+ struct htt_ppdu_stats_info *ppdu_info;
+ struct htt_ppdu_user_stats *user_stats;
+ int cur_user;
+ u16 peer_id;
+
+ ppdu_info = data;
+
+ switch (tag) {
+ case HTT_PPDU_STATS_TAG_COMMON:
+ if (len < sizeof(struct htt_ppdu_stats_common)) {
+ ath12k_warn(ab, "Invalid len %d for the tag 0x%x\n",
+ len, tag);
+ return -EINVAL;
+ }
+ memcpy(&ppdu_info->ppdu_stats.common, ptr,
+ sizeof(struct htt_ppdu_stats_common));
+ break;
+ case HTT_PPDU_STATS_TAG_USR_RATE:
+ if (len < sizeof(struct htt_ppdu_stats_user_rate)) {
+ ath12k_warn(ab, "Invalid len %d for the tag 0x%x\n",
+ len, tag);
+ return -EINVAL;
+ }
+ user_rate = ptr;
+ peer_id = le16_to_cpu(user_rate->sw_peer_id);
+ cur_user = ath12k_get_ppdu_user_index(&ppdu_info->ppdu_stats,
+ peer_id);
+ if (cur_user < 0)
+ return -EINVAL;
+ user_stats = &ppdu_info->ppdu_stats.user_stats[cur_user];
+ user_stats->peer_id = peer_id;
+ user_stats->is_valid_peer_id = true;
+ memcpy(&user_stats->rate, ptr,
+ sizeof(struct htt_ppdu_stats_user_rate));
+ user_stats->tlv_flags |= BIT(tag);
+ break;
+ case HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON:
+ if (len < sizeof(struct htt_ppdu_stats_usr_cmpltn_cmn)) {
+ ath12k_warn(ab, "Invalid len %d for the tag 0x%x\n",
+ len, tag);
+ return -EINVAL;
+ }
+
+ cmplt_cmn = ptr;
+ peer_id = le16_to_cpu(cmplt_cmn->sw_peer_id);
+ cur_user = ath12k_get_ppdu_user_index(&ppdu_info->ppdu_stats,
+ peer_id);
+ if (cur_user < 0)
+ return -EINVAL;
+ user_stats = &ppdu_info->ppdu_stats.user_stats[cur_user];
+ user_stats->peer_id = peer_id;
+ user_stats->is_valid_peer_id = true;
+ memcpy(&user_stats->cmpltn_cmn, ptr,
+ sizeof(struct htt_ppdu_stats_usr_cmpltn_cmn));
+ user_stats->tlv_flags |= BIT(tag);
+ break;
+ case HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS:
+ if (len <
+ sizeof(struct htt_ppdu_stats_usr_cmpltn_ack_ba_status)) {
+ ath12k_warn(ab, "Invalid len %d for the tag 0x%x\n",
+ len, tag);
+ return -EINVAL;
+ }
+
+ ba_status = ptr;
+ peer_id = le16_to_cpu(ba_status->sw_peer_id);
+ cur_user = ath12k_get_ppdu_user_index(&ppdu_info->ppdu_stats,
+ peer_id);
+ if (cur_user < 0)
+ return -EINVAL;
+ user_stats = &ppdu_info->ppdu_stats.user_stats[cur_user];
+ user_stats->peer_id = peer_id;
+ user_stats->is_valid_peer_id = true;
+ memcpy(&user_stats->ack_ba, ptr,
+ sizeof(struct htt_ppdu_stats_usr_cmpltn_ack_ba_status));
+ user_stats->tlv_flags |= BIT(tag);
+ break;
+ }
+ return 0;
+}
+
+int ath12k_dp_htt_tlv_iter(struct ath12k_base *ab, const void *ptr, size_t len,
+ int (*iter)(struct ath12k_base *ar, u16 tag, u16 len,
+ const void *ptr, void *data),
+ void *data)
+{
+ const struct htt_tlv *tlv;
+ const void *begin = ptr;
+ u16 tlv_tag, tlv_len;
+ int ret = -EINVAL;
+
+ while (len > 0) {
+ if (len < sizeof(*tlv)) {
+ ath12k_err(ab, "htt tlv parse failure at byte %zd (%zu bytes left, %zu expected)\n",
+ ptr - begin, len, sizeof(*tlv));
+ return -EINVAL;
+ }
+ tlv = (struct htt_tlv *)ptr;
+ tlv_tag = le32_get_bits(tlv->header, HTT_TLV_TAG);
+ tlv_len = le32_get_bits(tlv->header, HTT_TLV_LEN);
+ ptr += sizeof(*tlv);
+ len -= sizeof(*tlv);
+
+ if (tlv_len > len) {
+ ath12k_err(ab, "htt tlv parse failure of tag %u at byte %zd (%zu bytes left, %u expected)\n",
+ tlv_tag, ptr - begin, len, tlv_len);
+ return -EINVAL;
+ }
+ ret = iter(ab, tlv_tag, tlv_len, ptr, data);
+ if (ret == -ENOMEM)
+ return ret;
+
+ ptr += tlv_len;
+ len -= tlv_len;
+ }
+ return 0;
+}
+
+static void
+ath12k_update_per_peer_tx_stats(struct ath12k_pdev_dp *dp_pdev,
+ struct htt_ppdu_stats *ppdu_stats, u8 user)
+{
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
+ struct ath12k_dp_link_peer *peer;
+ struct htt_ppdu_stats_user_rate *user_rate;
+ struct ath12k_per_peer_tx_stats *peer_stats = &dp_pdev->peer_tx_stats;
+ struct htt_ppdu_user_stats *usr_stats = &ppdu_stats->user_stats[user];
+ struct htt_ppdu_stats_common *common = &ppdu_stats->common;
+ int ret;
+ u8 flags, mcs, nss, bw, sgi, dcm, ppdu_type, rate_idx = 0;
+ u32 v, succ_bytes = 0;
+ u16 tones, rate = 0, succ_pkts = 0;
+ u32 tx_duration = 0;
+ u8 tid = HTT_PPDU_STATS_NON_QOS_TID;
+ u16 tx_retry_failed = 0, tx_retry_count = 0;
+ bool is_ampdu = false, is_ofdma;
+
+ if (!(usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_RATE)))
+ return;
+
+ if (usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON)) {
+ is_ampdu =
+ HTT_USR_CMPLTN_IS_AMPDU(usr_stats->cmpltn_cmn.flags);
+ tx_retry_failed =
+ __le16_to_cpu(usr_stats->cmpltn_cmn.mpdu_tried) -
+ __le16_to_cpu(usr_stats->cmpltn_cmn.mpdu_success);
+ tx_retry_count =
+ HTT_USR_CMPLTN_LONG_RETRY(usr_stats->cmpltn_cmn.flags) +
+ HTT_USR_CMPLTN_SHORT_RETRY(usr_stats->cmpltn_cmn.flags);
+ }
+
+ if (usr_stats->tlv_flags &
+ BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS)) {
+ succ_bytes = le32_to_cpu(usr_stats->ack_ba.success_bytes);
+ succ_pkts = le32_get_bits(usr_stats->ack_ba.info,
+ HTT_PPDU_STATS_ACK_BA_INFO_NUM_MSDU_M);
+ tid = le32_get_bits(usr_stats->ack_ba.info,
+ HTT_PPDU_STATS_ACK_BA_INFO_TID_NUM);
+ }
+
+ if (common->fes_duration_us)
+ tx_duration = le32_to_cpu(common->fes_duration_us);
+
+ user_rate = &usr_stats->rate;
+ flags = HTT_USR_RATE_PREAMBLE(user_rate->rate_flags);
+ bw = HTT_USR_RATE_BW(user_rate->rate_flags) - 2;
+ nss = HTT_USR_RATE_NSS(user_rate->rate_flags) + 1;
+ mcs = HTT_USR_RATE_MCS(user_rate->rate_flags);
+ sgi = HTT_USR_RATE_GI(user_rate->rate_flags);
+ dcm = HTT_USR_RATE_DCM(user_rate->rate_flags);
+
+ ppdu_type = HTT_USR_RATE_PPDU_TYPE(user_rate->info1);
+ is_ofdma = (ppdu_type == HTT_PPDU_STATS_PPDU_TYPE_MU_OFDMA) ||
+ (ppdu_type == HTT_PPDU_STATS_PPDU_TYPE_MU_MIMO_OFDMA);
+
+ /* Note: If host configured fixed rates and in some other special
+ * cases, the broadcast/management frames are sent in different rates.
+ * Firmware rate's control to be skipped for this?
+ */
+
+ if (flags == WMI_RATE_PREAMBLE_HE && mcs > ATH12K_HE_MCS_MAX) {
+ ath12k_warn(ab, "Invalid HE mcs %d peer stats", mcs);
+ return;
+ }
+
+ if (flags == WMI_RATE_PREAMBLE_VHT && mcs > ATH12K_VHT_MCS_MAX) {
+ ath12k_warn(ab, "Invalid VHT mcs %d peer stats", mcs);
+ return;
+ }
+
+ if (flags == WMI_RATE_PREAMBLE_HT && (mcs > ATH12K_HT_MCS_MAX || nss < 1)) {
+ ath12k_warn(ab, "Invalid HT mcs %d nss %d peer stats",
+ mcs, nss);
+ return;
+ }
+
+ if (flags == WMI_RATE_PREAMBLE_CCK || flags == WMI_RATE_PREAMBLE_OFDM) {
+ ret = ath12k_mac_hw_ratecode_to_legacy_rate(mcs,
+ flags,
+ &rate_idx,
+ &rate);
+ if (ret < 0)
+ return;
+ }
+
+ rcu_read_lock();
+ peer = ath12k_dp_link_peer_find_by_peerid(dp_pdev, usr_stats->peer_id);
+
+ if (!peer || !peer->sta) {
+ rcu_read_unlock();
+ return;
+ }
+
+ spin_lock_bh(&dp->dp_lock);
+
+ memset(&peer->txrate, 0, sizeof(peer->txrate));
+
+ peer->txrate.bw = ath12k_mac_bw_to_mac80211_bw(bw);
+
+ switch (flags) {
+ case WMI_RATE_PREAMBLE_OFDM:
+ peer->txrate.legacy = rate;
+ break;
+ case WMI_RATE_PREAMBLE_CCK:
+ peer->txrate.legacy = rate;
+ break;
+ case WMI_RATE_PREAMBLE_HT:
+ peer->txrate.mcs = mcs + 8 * (nss - 1);
+ peer->txrate.flags = RATE_INFO_FLAGS_MCS;
+ if (sgi)
+ peer->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+ break;
+ case WMI_RATE_PREAMBLE_VHT:
+ peer->txrate.mcs = mcs;
+ peer->txrate.flags = RATE_INFO_FLAGS_VHT_MCS;
+ if (sgi)
+ peer->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+ break;
+ case WMI_RATE_PREAMBLE_HE:
+ peer->txrate.mcs = mcs;
+ peer->txrate.flags = RATE_INFO_FLAGS_HE_MCS;
+ peer->txrate.he_dcm = dcm;
+ peer->txrate.he_gi = ath12k_he_gi_to_nl80211_he_gi(sgi);
+ tones = le16_to_cpu(user_rate->ru_end) -
+ le16_to_cpu(user_rate->ru_start) + 1;
+ v = ath12k_he_ru_tones_to_nl80211_he_ru_alloc(tones);
+ peer->txrate.he_ru_alloc = v;
+ if (is_ofdma)
+ peer->txrate.bw = RATE_INFO_BW_HE_RU;
+ break;
+ case WMI_RATE_PREAMBLE_EHT:
+ peer->txrate.mcs = mcs;
+ peer->txrate.flags = RATE_INFO_FLAGS_EHT_MCS;
+ peer->txrate.he_dcm = dcm;
+ peer->txrate.eht_gi = ath12k_mac_eht_gi_to_nl80211_eht_gi(sgi);
+ tones = le16_to_cpu(user_rate->ru_end) -
+ le16_to_cpu(user_rate->ru_start) + 1;
+ v = ath12k_mac_eht_ru_tones_to_nl80211_eht_ru_alloc(tones);
+ peer->txrate.eht_ru_alloc = v;
+ if (is_ofdma)
+ peer->txrate.bw = RATE_INFO_BW_EHT_RU;
+ break;
+ }
+
+ peer->tx_retry_failed += tx_retry_failed;
+ peer->tx_retry_count += tx_retry_count;
+ peer->txrate.nss = nss;
+ peer->tx_duration += tx_duration;
+ memcpy(&peer->last_txrate, &peer->txrate, sizeof(struct rate_info));
+
+ spin_unlock_bh(&dp->dp_lock);
+
+ /* PPDU stats reported for mgmt packet doesn't have valid tx bytes.
+ * So skip peer stats update for mgmt packets.
+ */
+ if (tid < HTT_PPDU_STATS_NON_QOS_TID) {
+ memset(peer_stats, 0, sizeof(*peer_stats));
+ peer_stats->succ_pkts = succ_pkts;
+ peer_stats->succ_bytes = succ_bytes;
+ peer_stats->is_ampdu = is_ampdu;
+ peer_stats->duration = tx_duration;
+ peer_stats->ba_fails =
+ HTT_USR_CMPLTN_LONG_RETRY(usr_stats->cmpltn_cmn.flags) +
+ HTT_USR_CMPLTN_SHORT_RETRY(usr_stats->cmpltn_cmn.flags);
+ }
+
+ rcu_read_unlock();
+}
+
+static void ath12k_htt_update_ppdu_stats(struct ath12k_pdev_dp *dp_pdev,
+ struct htt_ppdu_stats *ppdu_stats)
+{
+ u8 user;
+
+ for (user = 0; user < HTT_PPDU_STATS_MAX_USERS - 1; user++)
+ ath12k_update_per_peer_tx_stats(dp_pdev, ppdu_stats, user);
+}
+
+static
+struct htt_ppdu_stats_info *ath12k_dp_htt_get_ppdu_desc(struct ath12k_pdev_dp *dp_pdev,
+ u32 ppdu_id)
+{
+ struct htt_ppdu_stats_info *ppdu_info;
+
+ lockdep_assert_held(&dp_pdev->ppdu_list_lock);
+ if (!list_empty(&dp_pdev->ppdu_stats_info)) {
+ list_for_each_entry(ppdu_info, &dp_pdev->ppdu_stats_info, list) {
+ if (ppdu_info->ppdu_id == ppdu_id)
+ return ppdu_info;
+ }
+
+ if (dp_pdev->ppdu_stat_list_depth > HTT_PPDU_DESC_MAX_DEPTH) {
+ ppdu_info = list_first_entry(&dp_pdev->ppdu_stats_info,
+ typeof(*ppdu_info), list);
+ list_del(&ppdu_info->list);
+ dp_pdev->ppdu_stat_list_depth--;
+ ath12k_htt_update_ppdu_stats(dp_pdev, &ppdu_info->ppdu_stats);
+ kfree(ppdu_info);
+ }
+ }
+
+ ppdu_info = kzalloc(sizeof(*ppdu_info), GFP_ATOMIC);
+ if (!ppdu_info)
+ return NULL;
+
+ list_add_tail(&ppdu_info->list, &dp_pdev->ppdu_stats_info);
+ dp_pdev->ppdu_stat_list_depth++;
+
+ return ppdu_info;
+}
+
+static void ath12k_copy_to_delay_stats(struct ath12k_dp_link_peer *peer,
+ struct htt_ppdu_user_stats *usr_stats)
+{
+ peer->ppdu_stats_delayba.sw_peer_id = le16_to_cpu(usr_stats->rate.sw_peer_id);
+ peer->ppdu_stats_delayba.info0 = le32_to_cpu(usr_stats->rate.info0);
+ peer->ppdu_stats_delayba.ru_end = le16_to_cpu(usr_stats->rate.ru_end);
+ peer->ppdu_stats_delayba.ru_start = le16_to_cpu(usr_stats->rate.ru_start);
+ peer->ppdu_stats_delayba.info1 = le32_to_cpu(usr_stats->rate.info1);
+ peer->ppdu_stats_delayba.rate_flags = le32_to_cpu(usr_stats->rate.rate_flags);
+ peer->ppdu_stats_delayba.resp_rate_flags =
+ le32_to_cpu(usr_stats->rate.resp_rate_flags);
+
+ peer->delayba_flag = true;
+}
+
+static void ath12k_copy_to_bar(struct ath12k_dp_link_peer *peer,
+ struct htt_ppdu_user_stats *usr_stats)
+{
+ usr_stats->rate.sw_peer_id = cpu_to_le16(peer->ppdu_stats_delayba.sw_peer_id);
+ usr_stats->rate.info0 = cpu_to_le32(peer->ppdu_stats_delayba.info0);
+ usr_stats->rate.ru_end = cpu_to_le16(peer->ppdu_stats_delayba.ru_end);
+ usr_stats->rate.ru_start = cpu_to_le16(peer->ppdu_stats_delayba.ru_start);
+ usr_stats->rate.info1 = cpu_to_le32(peer->ppdu_stats_delayba.info1);
+ usr_stats->rate.rate_flags = cpu_to_le32(peer->ppdu_stats_delayba.rate_flags);
+ usr_stats->rate.resp_rate_flags =
+ cpu_to_le32(peer->ppdu_stats_delayba.resp_rate_flags);
+
+ peer->delayba_flag = false;
+}
+
+static int ath12k_htt_pull_ppdu_stats(struct ath12k_base *ab,
+ struct sk_buff *skb)
+{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_htt_ppdu_stats_msg *msg;
+ struct htt_ppdu_stats_info *ppdu_info;
+ struct ath12k_dp_link_peer *peer = NULL;
+ struct htt_ppdu_user_stats *usr_stats = NULL;
+ u32 peer_id = 0;
+ struct ath12k_pdev_dp *dp_pdev;
+ int ret, i;
+ u8 pdev_id, pdev_idx;
+ u32 ppdu_id, len;
+
+ msg = (struct ath12k_htt_ppdu_stats_msg *)skb->data;
+ len = le32_get_bits(msg->info, HTT_T2H_PPDU_STATS_INFO_PAYLOAD_SIZE);
+ if (len > (skb->len - struct_size(msg, data, 0))) {
+ ath12k_warn(ab,
+ "HTT PPDU STATS event has unexpected payload size %u, should be smaller than %u\n",
+ len, skb->len);
+ return -EINVAL;
+ }
+
+ pdev_id = le32_get_bits(msg->info, HTT_T2H_PPDU_STATS_INFO_PDEV_ID);
+ ppdu_id = le32_to_cpu(msg->ppdu_id);
+
+ pdev_idx = DP_HW2SW_MACID(pdev_id);
+ if (pdev_idx >= MAX_RADIOS) {
+ ath12k_warn(ab, "HTT PPDU STATS invalid pdev id %u", pdev_id);
+ return -EINVAL;
+ }
+
+ rcu_read_lock();
+
+ dp_pdev = ath12k_dp_to_pdev_dp(dp, pdev_idx);
+ if (!dp_pdev) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ spin_lock_bh(&dp_pdev->ppdu_list_lock);
+ ppdu_info = ath12k_dp_htt_get_ppdu_desc(dp_pdev, ppdu_id);
+ if (!ppdu_info) {
+ spin_unlock_bh(&dp_pdev->ppdu_list_lock);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ ppdu_info->ppdu_id = ppdu_id;
+ ret = ath12k_dp_htt_tlv_iter(ab, msg->data, len,
+ ath12k_htt_tlv_ppdu_stats_parse,
+ (void *)ppdu_info);
+ if (ret) {
+ spin_unlock_bh(&dp_pdev->ppdu_list_lock);
+ ath12k_warn(ab, "Failed to parse tlv %d\n", ret);
+ goto exit;
+ }
+
+ if (ppdu_info->ppdu_stats.common.num_users >= HTT_PPDU_STATS_MAX_USERS) {
+ spin_unlock_bh(&dp_pdev->ppdu_list_lock);
+ ath12k_warn(ab,
+ "HTT PPDU STATS event has unexpected num_users %u, should be smaller than %u\n",
+ ppdu_info->ppdu_stats.common.num_users,
+ HTT_PPDU_STATS_MAX_USERS);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ /* back up data rate tlv for all peers */
+ if (ppdu_info->frame_type == HTT_STATS_PPDU_FTYPE_DATA &&
+ (ppdu_info->tlv_bitmap & (1 << HTT_PPDU_STATS_TAG_USR_COMMON)) &&
+ ppdu_info->delay_ba) {
+ for (i = 0; i < ppdu_info->ppdu_stats.common.num_users; i++) {
+ peer_id = ppdu_info->ppdu_stats.user_stats[i].peer_id;
+ peer = ath12k_dp_link_peer_find_by_peerid(dp_pdev, peer_id);
+ if (!peer)
+ continue;
+
+ usr_stats = &ppdu_info->ppdu_stats.user_stats[i];
+ if (usr_stats->delay_ba)
+ ath12k_copy_to_delay_stats(peer, usr_stats);
+ }
+ }
+
+ /* restore all peers' data rate tlv to mu-bar tlv */
+ if (ppdu_info->frame_type == HTT_STATS_PPDU_FTYPE_BAR &&
+ (ppdu_info->tlv_bitmap & (1 << HTT_PPDU_STATS_TAG_USR_COMMON))) {
+ for (i = 0; i < ppdu_info->bar_num_users; i++) {
+ peer_id = ppdu_info->ppdu_stats.user_stats[i].peer_id;
+ peer = ath12k_dp_link_peer_find_by_peerid(dp_pdev, peer_id);
+ if (!peer)
+ continue;
+
+ usr_stats = &ppdu_info->ppdu_stats.user_stats[i];
+ if (peer->delayba_flag)
+ ath12k_copy_to_bar(peer, usr_stats);
+ }
+ }
+
+ spin_unlock_bh(&dp_pdev->ppdu_list_lock);
+
+exit:
+ rcu_read_unlock();
+
+ return ret;
+}
+
+static void ath12k_htt_mlo_offset_event_handler(struct ath12k_base *ab,
+ struct sk_buff *skb)
+{
+ struct ath12k_htt_mlo_offset_msg *msg;
+ struct ath12k_pdev *pdev;
+ struct ath12k *ar;
+ u8 pdev_id;
+
+ msg = (struct ath12k_htt_mlo_offset_msg *)skb->data;
+ pdev_id = u32_get_bits(__le32_to_cpu(msg->info),
+ HTT_T2H_MLO_OFFSET_INFO_PDEV_ID);
+
+ rcu_read_lock();
+ ar = ath12k_mac_get_ar_by_pdev_id(ab, pdev_id);
+ if (!ar) {
+ /* It is possible that the ar is not yet active (started).
+ * The above function will only look for the active pdev
+ * and hence %NULL return is possible. Just silently
+ * discard this message
+ */
+ goto exit;
+ }
+
+ spin_lock_bh(&ar->data_lock);
+ pdev = ar->pdev;
+
+ pdev->timestamp.info = __le32_to_cpu(msg->info);
+ pdev->timestamp.sync_timestamp_lo_us = __le32_to_cpu(msg->sync_timestamp_lo_us);
+ pdev->timestamp.sync_timestamp_hi_us = __le32_to_cpu(msg->sync_timestamp_hi_us);
+ pdev->timestamp.mlo_offset_lo = __le32_to_cpu(msg->mlo_offset_lo);
+ pdev->timestamp.mlo_offset_hi = __le32_to_cpu(msg->mlo_offset_hi);
+ pdev->timestamp.mlo_offset_clks = __le32_to_cpu(msg->mlo_offset_clks);
+ pdev->timestamp.mlo_comp_clks = __le32_to_cpu(msg->mlo_comp_clks);
+ pdev->timestamp.mlo_comp_timer = __le32_to_cpu(msg->mlo_comp_timer);
+
+ spin_unlock_bh(&ar->data_lock);
+exit:
+ rcu_read_unlock();
+}
+
+void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab,
+ struct sk_buff *skb)
+{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct htt_resp_msg *resp = (struct htt_resp_msg *)skb->data;
+ enum htt_t2h_msg_type type;
+ u16 peer_id;
+ u8 vdev_id;
+ u8 mac_addr[ETH_ALEN];
+ u16 peer_mac_h16;
+ u16 ast_hash = 0;
+ u16 hw_peer_id;
+
+ type = le32_get_bits(resp->version_msg.version, HTT_T2H_MSG_TYPE);
+
+ ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "dp_htt rx msg type :0x%0x\n", type);
+
+ switch (type) {
+ case HTT_T2H_MSG_TYPE_VERSION_CONF:
+ dp->htt_tgt_ver_major = le32_get_bits(resp->version_msg.version,
+ HTT_T2H_VERSION_CONF_MAJOR);
+ dp->htt_tgt_ver_minor = le32_get_bits(resp->version_msg.version,
+ HTT_T2H_VERSION_CONF_MINOR);
+ complete(&dp->htt_tgt_version_received);
+ break;
+ /* TODO: remove unused peer map versions after testing */
+ case HTT_T2H_MSG_TYPE_PEER_MAP:
+ vdev_id = le32_get_bits(resp->peer_map_ev.info,
+ HTT_T2H_PEER_MAP_INFO_VDEV_ID);
+ peer_id = le32_get_bits(resp->peer_map_ev.info,
+ HTT_T2H_PEER_MAP_INFO_PEER_ID);
+ peer_mac_h16 = le32_get_bits(resp->peer_map_ev.info1,
+ HTT_T2H_PEER_MAP_INFO1_MAC_ADDR_H16);
+ ath12k_dp_get_mac_addr(le32_to_cpu(resp->peer_map_ev.mac_addr_l32),
+ peer_mac_h16, mac_addr);
+ ath12k_dp_link_peer_map_event(ab, vdev_id, peer_id, mac_addr, 0, 0);
+ break;
+ case HTT_T2H_MSG_TYPE_PEER_MAP2:
+ vdev_id = le32_get_bits(resp->peer_map_ev.info,
+ HTT_T2H_PEER_MAP_INFO_VDEV_ID);
+ peer_id = le32_get_bits(resp->peer_map_ev.info,
+ HTT_T2H_PEER_MAP_INFO_PEER_ID);
+ peer_mac_h16 = le32_get_bits(resp->peer_map_ev.info1,
+ HTT_T2H_PEER_MAP_INFO1_MAC_ADDR_H16);
+ ath12k_dp_get_mac_addr(le32_to_cpu(resp->peer_map_ev.mac_addr_l32),
+ peer_mac_h16, mac_addr);
+ ast_hash = le32_get_bits(resp->peer_map_ev.info2,
+ HTT_T2H_PEER_MAP_INFO2_AST_HASH_VAL);
+ hw_peer_id = le32_get_bits(resp->peer_map_ev.info1,
+ HTT_T2H_PEER_MAP_INFO1_HW_PEER_ID);
+ ath12k_dp_link_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash,
+ hw_peer_id);
+ break;
+ case HTT_T2H_MSG_TYPE_PEER_MAP3:
+ vdev_id = le32_get_bits(resp->peer_map_ev.info,
+ HTT_T2H_PEER_MAP_INFO_VDEV_ID);
+ peer_id = le32_get_bits(resp->peer_map_ev.info,
+ HTT_T2H_PEER_MAP_INFO_PEER_ID);
+ peer_mac_h16 = le32_get_bits(resp->peer_map_ev.info1,
+ HTT_T2H_PEER_MAP_INFO1_MAC_ADDR_H16);
+ ath12k_dp_get_mac_addr(le32_to_cpu(resp->peer_map_ev.mac_addr_l32),
+ peer_mac_h16, mac_addr);
+ ast_hash = le32_get_bits(resp->peer_map_ev.info2,
+ HTT_T2H_PEER_MAP3_INFO2_AST_HASH_VAL);
+ hw_peer_id = le32_get_bits(resp->peer_map_ev.info2,
+ HTT_T2H_PEER_MAP3_INFO2_HW_PEER_ID);
+ ath12k_dp_link_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash,
+ hw_peer_id);
+ break;
+ case HTT_T2H_MSG_TYPE_PEER_UNMAP:
+ case HTT_T2H_MSG_TYPE_PEER_UNMAP2:
+ peer_id = le32_get_bits(resp->peer_unmap_ev.info,
+ HTT_T2H_PEER_UNMAP_INFO_PEER_ID);
+ ath12k_dp_link_peer_unmap_event(ab, peer_id);
+ break;
+ case HTT_T2H_MSG_TYPE_PPDU_STATS_IND:
+ ath12k_htt_pull_ppdu_stats(ab, skb);
+ break;
+ case HTT_T2H_MSG_TYPE_EXT_STATS_CONF:
+ ath12k_debugfs_htt_ext_stats_handler(ab, skb);
+ break;
+ case HTT_T2H_MSG_TYPE_MLO_TIMESTAMP_OFFSET_IND:
+ ath12k_htt_mlo_offset_event_handler(ab, skb);
+ break;
+ default:
+ ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "dp_htt event %d not handled\n",
+ type);
+ break;
+ }
+
+ dev_kfree_skb_any(skb);
+}
+EXPORT_SYMBOL(ath12k_dp_htt_htc_t2h_msg_handler);
+
+static int
+ath12k_dp_tx_get_ring_id_type(struct ath12k_base *ab,
+ int mac_id, u32 ring_id,
+ enum hal_ring_type ring_type,
+ enum htt_srng_ring_type *htt_ring_type,
+ enum htt_srng_ring_id *htt_ring_id)
+{
+ int ret = 0;
+
+ switch (ring_type) {
+ case HAL_RXDMA_BUF:
+ /* for some targets, host fills rx buffer to fw and fw fills to
+ * rxbuf ring for each rxdma
+ */
+ if (!ab->hw_params->rx_mac_buf_ring) {
+ if (!(ring_id == HAL_SRNG_SW2RXDMA_BUF0 ||
+ ring_id == HAL_SRNG_SW2RXDMA_BUF1)) {
+ ret = -EINVAL;
+ }
+ *htt_ring_id = HTT_RXDMA_HOST_BUF_RING;
+ *htt_ring_type = HTT_SW_TO_HW_RING;
+ } else {
+ if (ring_id == HAL_SRNG_SW2RXDMA_BUF0) {
+ *htt_ring_id = HTT_HOST1_TO_FW_RXBUF_RING;
+ *htt_ring_type = HTT_SW_TO_SW_RING;
+ } else {
+ *htt_ring_id = HTT_RXDMA_HOST_BUF_RING;
+ *htt_ring_type = HTT_SW_TO_HW_RING;
+ }
+ }
+ break;
+ case HAL_RXDMA_DST:
+ *htt_ring_id = HTT_RXDMA_NON_MONITOR_DEST_RING;
+ *htt_ring_type = HTT_HW_TO_SW_RING;
+ break;
+ case HAL_RXDMA_MONITOR_BUF:
+ *htt_ring_id = HTT_RX_MON_HOST2MON_BUF_RING;
+ *htt_ring_type = HTT_SW_TO_HW_RING;
+ break;
+ case HAL_RXDMA_MONITOR_STATUS:
+ *htt_ring_id = HTT_RXDMA_MONITOR_STATUS_RING;
+ *htt_ring_type = HTT_SW_TO_HW_RING;
+ break;
+ case HAL_RXDMA_MONITOR_DST:
+ *htt_ring_id = HTT_RX_MON_MON2HOST_DEST_RING;
+ *htt_ring_type = HTT_HW_TO_SW_RING;
+ break;
+ case HAL_RXDMA_MONITOR_DESC:
+ *htt_ring_id = HTT_RXDMA_MONITOR_DESC_RING;
+ *htt_ring_type = HTT_SW_TO_HW_RING;
+ break;
+ default:
+ ath12k_warn(ab, "Unsupported ring type in DP :%d\n", ring_type);
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+int ath12k_dp_tx_htt_srng_setup(struct ath12k_base *ab, u32 ring_id,
+ int mac_id, enum hal_ring_type ring_type)
+{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct htt_srng_setup_cmd *cmd;
+ struct hal_srng *srng = &ab->hal.srng_list[ring_id];
+ struct hal_srng_params params;
+ struct sk_buff *skb;
+ u32 ring_entry_sz;
+ int len = sizeof(*cmd);
+ dma_addr_t hp_addr, tp_addr;
+ enum htt_srng_ring_type htt_ring_type;
+ enum htt_srng_ring_id htt_ring_id;
+ int ret;
+
+ skb = ath12k_htc_alloc_skb(ab, len);
+ if (!skb)
+ return -ENOMEM;
+
+ memset(&params, 0, sizeof(params));
+ ath12k_hal_srng_get_params(ab, srng, &params);
+
+ hp_addr = ath12k_hal_srng_get_hp_addr(ab, srng);
+ tp_addr = ath12k_hal_srng_get_tp_addr(ab, srng);
+
+ ret = ath12k_dp_tx_get_ring_id_type(ab, mac_id, ring_id,
+ ring_type, &htt_ring_type,
+ &htt_ring_id);
+ if (ret)
+ goto err_free;
+
+ skb_put(skb, len);
+ cmd = (struct htt_srng_setup_cmd *)skb->data;
+ cmd->info0 = le32_encode_bits(HTT_H2T_MSG_TYPE_SRING_SETUP,
+ HTT_SRNG_SETUP_CMD_INFO0_MSG_TYPE);
+ if (htt_ring_type == HTT_SW_TO_HW_RING ||
+ htt_ring_type == HTT_HW_TO_SW_RING)
+ cmd->info0 |= le32_encode_bits(DP_SW2HW_MACID(mac_id),
+ HTT_SRNG_SETUP_CMD_INFO0_PDEV_ID);
+ else
+ cmd->info0 |= le32_encode_bits(mac_id,
+ HTT_SRNG_SETUP_CMD_INFO0_PDEV_ID);
+ cmd->info0 |= le32_encode_bits(htt_ring_type,
+ HTT_SRNG_SETUP_CMD_INFO0_RING_TYPE);
+ cmd->info0 |= le32_encode_bits(htt_ring_id,
+ HTT_SRNG_SETUP_CMD_INFO0_RING_ID);
+
+ cmd->ring_base_addr_lo = cpu_to_le32(params.ring_base_paddr &
+ HAL_ADDR_LSB_REG_MASK);
+
+ cmd->ring_base_addr_hi = cpu_to_le32((u64)params.ring_base_paddr >>
+ HAL_ADDR_MSB_REG_SHIFT);
+
+ ret = ath12k_hal_srng_get_entrysize(ab, ring_type);
+ if (ret < 0)
+ goto err_free;
+
+ ring_entry_sz = ret;
+
+ ring_entry_sz >>= 2;
+ cmd->info1 = le32_encode_bits(ring_entry_sz,
+ HTT_SRNG_SETUP_CMD_INFO1_RING_ENTRY_SIZE);
+ cmd->info1 |= le32_encode_bits(params.num_entries * ring_entry_sz,
+ HTT_SRNG_SETUP_CMD_INFO1_RING_SIZE);
+ cmd->info1 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_MSI_SWAP),
+ HTT_SRNG_SETUP_CMD_INFO1_RING_FLAGS_MSI_SWAP);
+ cmd->info1 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP),
+ HTT_SRNG_SETUP_CMD_INFO1_RING_FLAGS_TLV_SWAP);
+ cmd->info1 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_RING_PTR_SWAP),
+ HTT_SRNG_SETUP_CMD_INFO1_RING_FLAGS_HOST_FW_SWAP);
+ if (htt_ring_type == HTT_SW_TO_HW_RING)
+ cmd->info1 |= cpu_to_le32(HTT_SRNG_SETUP_CMD_INFO1_RING_LOOP_CNT_DIS);
+
+ cmd->ring_head_off32_remote_addr_lo = cpu_to_le32(lower_32_bits(hp_addr));
+ cmd->ring_head_off32_remote_addr_hi = cpu_to_le32(upper_32_bits(hp_addr));
+
+ cmd->ring_tail_off32_remote_addr_lo = cpu_to_le32(lower_32_bits(tp_addr));
+ cmd->ring_tail_off32_remote_addr_hi = cpu_to_le32(upper_32_bits(tp_addr));
+
+ cmd->ring_msi_addr_lo = cpu_to_le32(lower_32_bits(params.msi_addr));
+ cmd->ring_msi_addr_hi = cpu_to_le32(upper_32_bits(params.msi_addr));
+ cmd->msi_data = cpu_to_le32(params.msi_data);
+
+ cmd->intr_info =
+ le32_encode_bits(params.intr_batch_cntr_thres_entries * ring_entry_sz,
+ HTT_SRNG_SETUP_CMD_INTR_INFO_BATCH_COUNTER_THRESH);
+ cmd->intr_info |=
+ le32_encode_bits(params.intr_timer_thres_us >> 3,
+ HTT_SRNG_SETUP_CMD_INTR_INFO_INTR_TIMER_THRESH);
+
+ cmd->info2 = 0;
+ if (params.flags & HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN) {
+ cmd->info2 = le32_encode_bits(params.low_threshold,
+ HTT_SRNG_SETUP_CMD_INFO2_INTR_LOW_THRESH);
+ }
+
+ ath12k_dbg(ab, ATH12K_DBG_HAL,
+ "%s msi_addr_lo:0x%x, msi_addr_hi:0x%x, msi_data:0x%x\n",
+ __func__, cmd->ring_msi_addr_lo, cmd->ring_msi_addr_hi,
+ cmd->msi_data);
+
+ ath12k_dbg(ab, ATH12K_DBG_HAL,
+ "ring_id:%d, ring_type:%d, intr_info:0x%x, flags:0x%x\n",
+ ring_id, ring_type, cmd->intr_info, cmd->info2);
+
+ ret = ath12k_htc_send(&ab->htc, dp->eid, skb);
+ if (ret)
+ goto err_free;
+
+ return 0;
+
+err_free:
+ dev_kfree_skb_any(skb);
+
+ return ret;
+}
+
+int ath12k_dp_tx_htt_h2t_ver_req_msg(struct ath12k_base *ab)
+{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct sk_buff *skb;
+ struct htt_ver_req_cmd *cmd;
+ int len = sizeof(*cmd);
+ u32 metadata_version;
+ int ret;
+
+ init_completion(&dp->htt_tgt_version_received);
+
+ skb = ath12k_htc_alloc_skb(ab, len);
+ if (!skb)
+ return -ENOMEM;
+
+ skb_put(skb, len);
+ cmd = (struct htt_ver_req_cmd *)skb->data;
+ cmd->ver_reg_info = le32_encode_bits(HTT_H2T_MSG_TYPE_VERSION_REQ,
+ HTT_OPTION_TAG);
+ metadata_version = ath12k_ftm_mode ? HTT_OPTION_TCL_METADATA_VER_V1 :
+ HTT_OPTION_TCL_METADATA_VER_V2;
+
+ cmd->tcl_metadata_version = le32_encode_bits(HTT_TAG_TCL_METADATA_VERSION,
+ HTT_OPTION_TAG) |
+ le32_encode_bits(HTT_TCL_METADATA_VER_SZ,
+ HTT_OPTION_LEN) |
+ le32_encode_bits(metadata_version,
+ HTT_OPTION_VALUE);
+
+ ret = ath12k_htc_send(&ab->htc, dp->eid, skb);
+ if (ret) {
+ dev_kfree_skb_any(skb);
+ return ret;
+ }
+
+ ret = wait_for_completion_timeout(&dp->htt_tgt_version_received,
+ HTT_TARGET_VERSION_TIMEOUT_HZ);
+ if (ret == 0) {
+ ath12k_warn(ab, "htt target version request timed out\n");
+ return -ETIMEDOUT;
+ }
+
+ if (dp->htt_tgt_ver_major != HTT_TARGET_VERSION_MAJOR) {
+ ath12k_err(ab, "unsupported htt major version %d supported version is %d\n",
+ dp->htt_tgt_ver_major, HTT_TARGET_VERSION_MAJOR);
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+int ath12k_dp_tx_htt_h2t_ppdu_stats_req(struct ath12k *ar, u32 mask)
+{
+ struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct sk_buff *skb;
+ struct htt_ppdu_stats_cfg_cmd *cmd;
+ int len = sizeof(*cmd);
+ u8 pdev_mask;
+ int ret;
+ int i;
+
+ for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {
+ skb = ath12k_htc_alloc_skb(ab, len);
+ if (!skb)
+ return -ENOMEM;
+
+ skb_put(skb, len);
+ cmd = (struct htt_ppdu_stats_cfg_cmd *)skb->data;
+ cmd->msg = le32_encode_bits(HTT_H2T_MSG_TYPE_PPDU_STATS_CFG,
+ HTT_PPDU_STATS_CFG_MSG_TYPE);
+
+ pdev_mask = 1 << (i + ar->pdev_idx);
+ cmd->msg |= le32_encode_bits(pdev_mask, HTT_PPDU_STATS_CFG_PDEV_ID);
+ cmd->msg |= le32_encode_bits(mask, HTT_PPDU_STATS_CFG_TLV_TYPE_BITMASK);
+
+ ret = ath12k_htc_send(&ab->htc, dp->eid, skb);
+ if (ret) {
+ dev_kfree_skb_any(skb);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+int ath12k_dp_tx_htt_rx_filter_setup(struct ath12k_base *ab, u32 ring_id,
+ int mac_id, enum hal_ring_type ring_type,
+ int rx_buf_size,
+ struct htt_rx_ring_tlv_filter *tlv_filter)
+{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct htt_rx_ring_selection_cfg_cmd *cmd;
+ struct hal_srng *srng = &ab->hal.srng_list[ring_id];
+ struct hal_srng_params params;
+ struct sk_buff *skb;
+ int len = sizeof(*cmd);
+ enum htt_srng_ring_type htt_ring_type;
+ enum htt_srng_ring_id htt_ring_id;
+ int ret;
+
+ skb = ath12k_htc_alloc_skb(ab, len);
+ if (!skb)
+ return -ENOMEM;
+
+ memset(&params, 0, sizeof(params));
+ ath12k_hal_srng_get_params(ab, srng, &params);
+
+ ret = ath12k_dp_tx_get_ring_id_type(ab, mac_id, ring_id,
+ ring_type, &htt_ring_type,
+ &htt_ring_id);
+ if (ret)
+ goto err_free;
+
+ skb_put(skb, len);
+ cmd = (struct htt_rx_ring_selection_cfg_cmd *)skb->data;
+ cmd->info0 = le32_encode_bits(HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG,
+ HTT_RX_RING_SELECTION_CFG_CMD_INFO0_MSG_TYPE);
+ if (htt_ring_type == HTT_SW_TO_HW_RING ||
+ htt_ring_type == HTT_HW_TO_SW_RING)
+ cmd->info0 |=
+ le32_encode_bits(DP_SW2HW_MACID(mac_id),
+ HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID);
+ else
+ cmd->info0 |=
+ le32_encode_bits(mac_id,
+ HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID);
+ cmd->info0 |= le32_encode_bits(htt_ring_id,
+ HTT_RX_RING_SELECTION_CFG_CMD_INFO0_RING_ID);
+ cmd->info0 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_MSI_SWAP),
+ HTT_RX_RING_SELECTION_CFG_CMD_INFO0_SS);
+ cmd->info0 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP),
+ HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PS);
+ cmd->info0 |= le32_encode_bits(tlv_filter->offset_valid,
+ HTT_RX_RING_SELECTION_CFG_CMD_INFO0_OFFSET_VALID);
+ cmd->info0 |=
+ le32_encode_bits(tlv_filter->drop_threshold_valid,
+ HTT_RX_RING_SELECTION_CFG_CMD_INFO0_DROP_THRES_VAL);
+ cmd->info0 |= le32_encode_bits(!tlv_filter->rxmon_disable,
+ HTT_RX_RING_SELECTION_CFG_CMD_INFO0_EN_RXMON);
+
+ cmd->info1 = le32_encode_bits(rx_buf_size,
+ HTT_RX_RING_SELECTION_CFG_CMD_INFO1_BUF_SIZE);
+ cmd->info1 |= le32_encode_bits(tlv_filter->conf_len_mgmt,
+ HTT_RX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_MGMT);
+ cmd->info1 |= le32_encode_bits(tlv_filter->conf_len_ctrl,
+ HTT_RX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_CTRL);
+ cmd->info1 |= le32_encode_bits(tlv_filter->conf_len_data,
+ HTT_RX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_DATA);
+ cmd->pkt_type_en_flags0 = cpu_to_le32(tlv_filter->pkt_filter_flags0);
+ cmd->pkt_type_en_flags1 = cpu_to_le32(tlv_filter->pkt_filter_flags1);
+ cmd->pkt_type_en_flags2 = cpu_to_le32(tlv_filter->pkt_filter_flags2);
+ cmd->pkt_type_en_flags3 = cpu_to_le32(tlv_filter->pkt_filter_flags3);
+ cmd->rx_filter_tlv = cpu_to_le32(tlv_filter->rx_filter);
+
+ cmd->info2 = le32_encode_bits(tlv_filter->rx_drop_threshold,
+ HTT_RX_RING_SELECTION_CFG_CMD_INFO2_DROP_THRESHOLD);
+ cmd->info2 |=
+ le32_encode_bits(tlv_filter->enable_log_mgmt_type,
+ HTT_RX_RING_SELECTION_CFG_CMD_INFO2_EN_LOG_MGMT_TYPE);
+ cmd->info2 |=
+ le32_encode_bits(tlv_filter->enable_log_ctrl_type,
+ HTT_RX_RING_SELECTION_CFG_CMD_INFO2_EN_CTRL_TYPE);
+ cmd->info2 |=
+ le32_encode_bits(tlv_filter->enable_log_data_type,
+ HTT_RX_RING_SELECTION_CFG_CMD_INFO2_EN_LOG_DATA_TYPE);
+
+ cmd->info3 =
+ le32_encode_bits(tlv_filter->enable_rx_tlv_offset,
+ HTT_RX_RING_SELECTION_CFG_CMD_INFO3_EN_TLV_PKT_OFFSET);
+ cmd->info3 |=
+ le32_encode_bits(tlv_filter->rx_tlv_offset,
+ HTT_RX_RING_SELECTION_CFG_CMD_INFO3_PKT_TLV_OFFSET);
+
+ if (tlv_filter->offset_valid) {
+ cmd->rx_packet_offset =
+ le32_encode_bits(tlv_filter->rx_packet_offset,
+ HTT_RX_RING_SELECTION_CFG_RX_PACKET_OFFSET);
+
+ cmd->rx_packet_offset |=
+ le32_encode_bits(tlv_filter->rx_header_offset,
+ HTT_RX_RING_SELECTION_CFG_RX_HEADER_OFFSET);
+
+ cmd->rx_mpdu_offset =
+ le32_encode_bits(tlv_filter->rx_mpdu_end_offset,
+ HTT_RX_RING_SELECTION_CFG_RX_MPDU_END_OFFSET);
+
+ cmd->rx_mpdu_offset |=
+ le32_encode_bits(tlv_filter->rx_mpdu_start_offset,
+ HTT_RX_RING_SELECTION_CFG_RX_MPDU_START_OFFSET);
+
+ cmd->rx_msdu_offset =
+ le32_encode_bits(tlv_filter->rx_msdu_end_offset,
+ HTT_RX_RING_SELECTION_CFG_RX_MSDU_END_OFFSET);
+
+ cmd->rx_msdu_offset |=
+ le32_encode_bits(tlv_filter->rx_msdu_start_offset,
+ HTT_RX_RING_SELECTION_CFG_RX_MSDU_START_OFFSET);
+
+ cmd->rx_attn_offset =
+ le32_encode_bits(tlv_filter->rx_attn_offset,
+ HTT_RX_RING_SELECTION_CFG_RX_ATTENTION_OFFSET);
+ }
+
+ if (tlv_filter->rx_mpdu_start_wmask > 0 &&
+ tlv_filter->rx_msdu_end_wmask > 0) {
+ cmd->info2 |=
+ le32_encode_bits(true,
+ HTT_RX_RING_SELECTION_CFG_WORD_MASK_COMPACT_SET);
+ cmd->rx_mpdu_start_end_mask =
+ le32_encode_bits(tlv_filter->rx_mpdu_start_wmask,
+ HTT_RX_RING_SELECTION_CFG_RX_MPDU_START_MASK);
+ /* mpdu_end is not used for any hardwares so far
+ * please assign it in future if any chip is
+ * using through hal ops
+ */
+ cmd->rx_mpdu_start_end_mask |=
+ le32_encode_bits(tlv_filter->rx_mpdu_end_wmask,
+ HTT_RX_RING_SELECTION_CFG_RX_MPDU_END_MASK);
+ cmd->rx_msdu_end_word_mask =
+ le32_encode_bits(tlv_filter->rx_msdu_end_wmask,
+ HTT_RX_RING_SELECTION_CFG_RX_MSDU_END_MASK);
+ }
+
+ ret = ath12k_htc_send(&ab->htc, dp->eid, skb);
+ if (ret)
+ goto err_free;
+
+ return 0;
+
+err_free:
+ dev_kfree_skb_any(skb);
+
+ return ret;
+}
+EXPORT_SYMBOL(ath12k_dp_tx_htt_rx_filter_setup);
+
+int
+ath12k_dp_tx_htt_h2t_ext_stats_req(struct ath12k *ar, u8 type,
+ struct htt_ext_stats_cfg_params *cfg_params,
+ u64 cookie)
+{
+ struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct sk_buff *skb;
+ struct htt_ext_stats_cfg_cmd *cmd;
+ int len = sizeof(*cmd);
+ int ret;
+ u32 pdev_id;
+
+ skb = ath12k_htc_alloc_skb(ab, len);
+ if (!skb)
+ return -ENOMEM;
+
+ skb_put(skb, len);
+
+ cmd = (struct htt_ext_stats_cfg_cmd *)skb->data;
+ memset(cmd, 0, sizeof(*cmd));
+ cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_EXT_STATS_CFG;
+
+ pdev_id = ath12k_mac_get_target_pdev_id(ar);
+ cmd->hdr.pdev_mask = 1 << pdev_id;
+
+ cmd->hdr.stats_type = type;
+ cmd->cfg_param0 = cpu_to_le32(cfg_params->cfg0);
+ cmd->cfg_param1 = cpu_to_le32(cfg_params->cfg1);
+ cmd->cfg_param2 = cpu_to_le32(cfg_params->cfg2);
+ cmd->cfg_param3 = cpu_to_le32(cfg_params->cfg3);
+ cmd->cookie_lsb = cpu_to_le32(lower_32_bits(cookie));
+ cmd->cookie_msb = cpu_to_le32(upper_32_bits(cookie));
+
+ ret = ath12k_htc_send(&ab->htc, dp->eid, skb);
+ if (ret) {
+ ath12k_warn(ab, "failed to send htt type stats request: %d",
+ ret);
+ dev_kfree_skb_any(skb);
+ return ret;
+ }
+
+ return 0;
+}
+
+int ath12k_dp_tx_htt_monitor_mode_ring_config(struct ath12k *ar, bool reset)
+{
+ struct ath12k_base *ab = ar->ab;
+ int ret;
+
+ ret = ath12k_dp_tx_htt_rx_monitor_mode_ring_config(ar, reset);
+ if (ret) {
+ ath12k_err(ab, "failed to setup rx monitor filter %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+int ath12k_dp_tx_htt_rx_monitor_mode_ring_config(struct ath12k *ar, bool reset)
+{
+ struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct htt_rx_ring_tlv_filter tlv_filter = {};
+ int ret, ring_id, i;
+
+ tlv_filter.offset_valid = false;
+
+ if (!reset) {
+ tlv_filter.rx_filter = HTT_RX_MON_FILTER_TLV_FLAGS_MON_DEST_RING;
+
+ tlv_filter.drop_threshold_valid = true;
+ tlv_filter.rx_drop_threshold = HTT_RX_RING_TLV_DROP_THRESHOLD_VALUE;
+
+ tlv_filter.enable_log_mgmt_type = true;
+ tlv_filter.enable_log_ctrl_type = true;
+ tlv_filter.enable_log_data_type = true;
+
+ tlv_filter.conf_len_ctrl = HTT_RX_RING_DEFAULT_DMA_LENGTH;
+ tlv_filter.conf_len_mgmt = HTT_RX_RING_DEFAULT_DMA_LENGTH;
+ tlv_filter.conf_len_data = HTT_RX_RING_DEFAULT_DMA_LENGTH;
+
+ tlv_filter.enable_rx_tlv_offset = true;
+ tlv_filter.rx_tlv_offset = HTT_RX_RING_PKT_TLV_OFFSET;
+
+ tlv_filter.pkt_filter_flags0 =
+ HTT_RX_MON_FP_MGMT_FILTER_FLAGS0 |
+ HTT_RX_MON_MO_MGMT_FILTER_FLAGS0;
+ tlv_filter.pkt_filter_flags1 =
+ HTT_RX_MON_FP_MGMT_FILTER_FLAGS1 |
+ HTT_RX_MON_MO_MGMT_FILTER_FLAGS1;
+ tlv_filter.pkt_filter_flags2 =
+ HTT_RX_MON_FP_CTRL_FILTER_FLASG2 |
+ HTT_RX_MON_MO_CTRL_FILTER_FLASG2;
+ tlv_filter.pkt_filter_flags3 =
+ HTT_RX_MON_FP_CTRL_FILTER_FLASG3 |
+ HTT_RX_MON_MO_CTRL_FILTER_FLASG3 |
+ HTT_RX_MON_FP_DATA_FILTER_FLASG3 |
+ HTT_RX_MON_MO_DATA_FILTER_FLASG3;
+ } else {
+ tlv_filter = ath12k_mac_mon_status_filter_default;
+
+ if (ath12k_debugfs_is_extd_rx_stats_enabled(ar))
+ tlv_filter.rx_filter = ath12k_debugfs_rx_filter(ar);
+ }
+
+ if (ab->hw_params->rxdma1_enable) {
+ for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {
+ ring_id = ar->dp.rxdma_mon_dst_ring[i].ring_id;
+ ret = ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id,
+ ar->dp.mac_id + i,
+ HAL_RXDMA_MONITOR_DST,
+ DP_RXDMA_REFILL_RING_SIZE,
+ &tlv_filter);
+ if (ret) {
+ ath12k_err(ab,
+ "failed to setup filter for monitor buf %d\n",
+ ret);
+ return ret;
+ }
+ }
+ return 0;
+ }
+
+ if (!reset) {
+ for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {
+ ring_id = dp->rx_mac_buf_ring[i].ring_id;
+ ret = ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id,
+ i,
+ HAL_RXDMA_BUF,
+ DP_RXDMA_REFILL_RING_SIZE,
+ &tlv_filter);
+ if (ret) {
+ ath12k_err(ab,
+ "failed to setup filter for mon rx buf %d\n",
+ ret);
+ return ret;
+ }
+ }
+ }
+
+ for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {
+ ring_id = dp->rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
+ if (!reset) {
+ tlv_filter.rx_filter =
+ HTT_RX_MON_FILTER_TLV_FLAGS_MON_STATUS_RING;
+ }
+
+ ret = ath12k_dp_tx_htt_rx_filter_setup(ab, ring_id,
+ i,
+ HAL_RXDMA_MONITOR_STATUS,
+ RX_MON_STATUS_BUF_SIZE,
+ &tlv_filter);
+ if (ret) {
+ ath12k_err(ab,
+ "failed to setup filter for mon status buf %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+int ath12k_dp_tx_htt_tx_filter_setup(struct ath12k_base *ab, u32 ring_id,
+ int mac_id, enum hal_ring_type ring_type,
+ int tx_buf_size,
+ struct htt_tx_ring_tlv_filter *htt_tlv_filter)
+{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct htt_tx_ring_selection_cfg_cmd *cmd;
+ struct hal_srng *srng = &ab->hal.srng_list[ring_id];
+ struct hal_srng_params params;
+ struct sk_buff *skb;
+ int len = sizeof(*cmd);
+ enum htt_srng_ring_type htt_ring_type;
+ enum htt_srng_ring_id htt_ring_id;
+ int ret;
+
+ skb = ath12k_htc_alloc_skb(ab, len);
+ if (!skb)
+ return -ENOMEM;
+
+ memset(&params, 0, sizeof(params));
+ ath12k_hal_srng_get_params(ab, srng, &params);
+
+ ret = ath12k_dp_tx_get_ring_id_type(ab, mac_id, ring_id,
+ ring_type, &htt_ring_type,
+ &htt_ring_id);
+
+ if (ret)
+ goto err_free;
+
+ skb_put(skb, len);
+ cmd = (struct htt_tx_ring_selection_cfg_cmd *)skb->data;
+ cmd->info0 = le32_encode_bits(HTT_H2T_MSG_TYPE_TX_MONITOR_CFG,
+ HTT_TX_RING_SELECTION_CFG_CMD_INFO0_MSG_TYPE);
+ if (htt_ring_type == HTT_SW_TO_HW_RING ||
+ htt_ring_type == HTT_HW_TO_SW_RING)
+ cmd->info0 |=
+ le32_encode_bits(DP_SW2HW_MACID(mac_id),
+ HTT_TX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID);
+ else
+ cmd->info0 |=
+ le32_encode_bits(mac_id,
+ HTT_TX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID);
+ cmd->info0 |= le32_encode_bits(htt_ring_id,
+ HTT_TX_RING_SELECTION_CFG_CMD_INFO0_RING_ID);
+ cmd->info0 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_MSI_SWAP),
+ HTT_TX_RING_SELECTION_CFG_CMD_INFO0_SS);
+ cmd->info0 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP),
+ HTT_TX_RING_SELECTION_CFG_CMD_INFO0_PS);
+
+ cmd->info1 |=
+ le32_encode_bits(tx_buf_size,
+ HTT_TX_RING_SELECTION_CFG_CMD_INFO1_RING_BUFF_SIZE);
+
+ if (htt_tlv_filter->tx_mon_mgmt_filter) {
+ cmd->info1 |=
+ le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_MGMT,
+ HTT_TX_RING_SELECTION_CFG_CMD_INFO1_PKT_TYPE);
+ cmd->info1 |=
+ le32_encode_bits(htt_tlv_filter->tx_mon_pkt_dma_len,
+ HTT_TX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_MGMT);
+ cmd->info2 |=
+ le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_MGMT,
+ HTT_TX_RING_SELECTION_CFG_CMD_INFO2_PKT_TYPE_EN_FLAG);
+ }
+
+ if (htt_tlv_filter->tx_mon_data_filter) {
+ cmd->info1 |=
+ le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_CTRL,
+ HTT_TX_RING_SELECTION_CFG_CMD_INFO1_PKT_TYPE);
+ cmd->info1 |=
+ le32_encode_bits(htt_tlv_filter->tx_mon_pkt_dma_len,
+ HTT_TX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_CTRL);
+ cmd->info2 |=
+ le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_CTRL,
+ HTT_TX_RING_SELECTION_CFG_CMD_INFO2_PKT_TYPE_EN_FLAG);
+ }
+
+ if (htt_tlv_filter->tx_mon_ctrl_filter) {
+ cmd->info1 |=
+ le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_DATA,
+ HTT_TX_RING_SELECTION_CFG_CMD_INFO1_PKT_TYPE);
+ cmd->info1 |=
+ le32_encode_bits(htt_tlv_filter->tx_mon_pkt_dma_len,
+ HTT_TX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_DATA);
+ cmd->info2 |=
+ le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_DATA,
+ HTT_TX_RING_SELECTION_CFG_CMD_INFO2_PKT_TYPE_EN_FLAG);
+ }
+
+ cmd->tlv_filter_mask_in0 =
+ cpu_to_le32(htt_tlv_filter->tx_mon_downstream_tlv_flags);
+ cmd->tlv_filter_mask_in1 =
+ cpu_to_le32(htt_tlv_filter->tx_mon_upstream_tlv_flags0);
+ cmd->tlv_filter_mask_in2 =
+ cpu_to_le32(htt_tlv_filter->tx_mon_upstream_tlv_flags1);
+ cmd->tlv_filter_mask_in3 =
+ cpu_to_le32(htt_tlv_filter->tx_mon_upstream_tlv_flags2);
+
+ ret = ath12k_htc_send(&ab->htc, dp->eid, skb);
+ if (ret)
+ goto err_free;
+
+ return 0;
+
+err_free:
+ dev_kfree_skb_any(skb);
+ return ret;
+}
diff --git a/drivers/net/wireless/ath/ath12k/dp_htt.h b/drivers/net/wireless/ath/ath12k/dp_htt.h
new file mode 100644
index 000000000000..6020e632f74e
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/dp_htt.h
@@ -0,0 +1,1546 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef ATH12K_DP_HTT_H
+#define ATH12K_DP_HTT_H
+
+struct ath12k_dp;
+
+/* HTT definitions */
+#define HTT_TAG_TCL_METADATA_VERSION 5
+
+#define HTT_TCL_META_DATA_TYPE GENMASK(1, 0)
+#define HTT_TCL_META_DATA_VALID_HTT BIT(2)
+
+/* vdev meta data */
+#define HTT_TCL_META_DATA_VDEV_ID GENMASK(10, 3)
+#define HTT_TCL_META_DATA_PDEV_ID GENMASK(12, 11)
+#define HTT_TCL_META_DATA_HOST_INSPECTED_MISSION BIT(13)
+
+/* peer meta data */
+#define HTT_TCL_META_DATA_PEER_ID GENMASK(15, 3)
+
+/* Global sequence number */
+#define HTT_TCL_META_DATA_TYPE_GLOBAL_SEQ_NUM 3
+#define HTT_TCL_META_DATA_GLOBAL_SEQ_HOST_INSPECTED BIT(2)
+#define HTT_TCL_META_DATA_GLOBAL_SEQ_NUM GENMASK(14, 3)
+#define HTT_TX_MLO_MCAST_HOST_REINJECT_BASE_VDEV_ID 128
+
+/* HTT tx completion is overlaid in wbm_release_ring */
+#define HTT_TX_WBM_COMP_INFO0_STATUS GENMASK(16, 13)
+#define HTT_TX_WBM_COMP_INFO1_REINJECT_REASON GENMASK(3, 0)
+#define HTT_TX_WBM_COMP_INFO1_EXCEPTION_FRAME BIT(4)
+
+#define HTT_TX_WBM_COMP_INFO2_ACK_RSSI GENMASK(31, 24)
+
+#define HTT_TARGET_VERSION_TIMEOUT_HZ (3 * HZ)
+
+struct htt_tx_wbm_completion {
+ __le32 rsvd0[2];
+ __le32 info0;
+ __le32 info1;
+ __le32 info2;
+ __le32 info3;
+ __le32 info4;
+ __le32 rsvd1;
+
+} __packed;
+
+enum htt_h2t_msg_type {
+ HTT_H2T_MSG_TYPE_VERSION_REQ = 0,
+ HTT_H2T_MSG_TYPE_SRING_SETUP = 0xb,
+ HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG = 0xc,
+ HTT_H2T_MSG_TYPE_EXT_STATS_CFG = 0x10,
+ HTT_H2T_MSG_TYPE_PPDU_STATS_CFG = 0x11,
+ HTT_H2T_MSG_TYPE_VDEV_TXRX_STATS_CFG = 0x1a,
+ HTT_H2T_MSG_TYPE_TX_MONITOR_CFG = 0x1b,
+};
+
+#define HTT_VER_REQ_INFO_MSG_ID GENMASK(7, 0)
+#define HTT_OPTION_TCL_METADATA_VER_V1 1
+#define HTT_OPTION_TCL_METADATA_VER_V2 2
+#define HTT_OPTION_TAG GENMASK(7, 0)
+#define HTT_OPTION_LEN GENMASK(15, 8)
+#define HTT_OPTION_VALUE GENMASK(31, 16)
+#define HTT_TCL_METADATA_VER_SZ 4
+
+struct htt_ver_req_cmd {
+ __le32 ver_reg_info;
+ __le32 tcl_metadata_version;
+} __packed;
+
+enum htt_srng_ring_type {
+ HTT_HW_TO_SW_RING,
+ HTT_SW_TO_HW_RING,
+ HTT_SW_TO_SW_RING,
+};
+
+enum htt_srng_ring_id {
+ HTT_RXDMA_HOST_BUF_RING,
+ HTT_RXDMA_MONITOR_STATUS_RING,
+ HTT_RXDMA_MONITOR_BUF_RING,
+ HTT_RXDMA_MONITOR_DESC_RING,
+ HTT_RXDMA_MONITOR_DEST_RING,
+ HTT_HOST1_TO_FW_RXBUF_RING,
+ HTT_HOST2_TO_FW_RXBUF_RING,
+ HTT_RXDMA_NON_MONITOR_DEST_RING,
+ HTT_RXDMA_HOST_BUF_RING2,
+ HTT_TX_MON_HOST2MON_BUF_RING,
+ HTT_TX_MON_MON2HOST_DEST_RING,
+ HTT_RX_MON_HOST2MON_BUF_RING,
+ HTT_RX_MON_MON2HOST_DEST_RING,
+};
+
+/* host -> target HTT_SRING_SETUP message
+ *
+ * After target is booted up, Host can send SRING setup message for
+ * each host facing LMAC SRING. Target setups up HW registers based
+ * on setup message and confirms back to Host if response_required is set.
+ * Host should wait for confirmation message before sending new SRING
+ * setup message
+ *
+ * The message would appear as follows:
+ *
+ * |31 24|23 20|19|18 16|15|14 8|7 0|
+ * |--------------- +-----------------+----------------+------------------|
+ * | ring_type | ring_id | pdev_id | msg_type |
+ * |----------------------------------------------------------------------|
+ * | ring_base_addr_lo |
+ * |----------------------------------------------------------------------|
+ * | ring_base_addr_hi |
+ * |----------------------------------------------------------------------|
+ * |ring_misc_cfg_flag|ring_entry_size| ring_size |
+ * |----------------------------------------------------------------------|
+ * | ring_head_offset32_remote_addr_lo |
+ * |----------------------------------------------------------------------|
+ * | ring_head_offset32_remote_addr_hi |
+ * |----------------------------------------------------------------------|
+ * | ring_tail_offset32_remote_addr_lo |
+ * |----------------------------------------------------------------------|
+ * | ring_tail_offset32_remote_addr_hi |
+ * |----------------------------------------------------------------------|
+ * | ring_msi_addr_lo |
+ * |----------------------------------------------------------------------|
+ * | ring_msi_addr_hi |
+ * |----------------------------------------------------------------------|
+ * | ring_msi_data |
+ * |----------------------------------------------------------------------|
+ * | intr_timer_th |IM| intr_batch_counter_th |
+ * |----------------------------------------------------------------------|
+ * | reserved |RR|PTCF| intr_low_threshold |
+ * |----------------------------------------------------------------------|
+ * Where
+ * IM = sw_intr_mode
+ * RR = response_required
+ * PTCF = prefetch_timer_cfg
+ *
+ * The message is interpreted as follows:
+ * dword0 - b'0:7 - msg_type: This will be set to
+ * HTT_H2T_MSG_TYPE_SRING_SETUP
+ * b'8:15 - pdev_id:
+ * 0 (for rings at SOC/UMAC level),
+ * 1/2/3 mac id (for rings at LMAC level)
+ * b'16:23 - ring_id: identify which ring is to setup,
+ * more details can be got from enum htt_srng_ring_id
+ * b'24:31 - ring_type: identify type of host rings,
+ * more details can be got from enum htt_srng_ring_type
+ * dword1 - b'0:31 - ring_base_addr_lo: Lower 32bits of ring base address
+ * dword2 - b'0:31 - ring_base_addr_hi: Upper 32bits of ring base address
+ * dword3 - b'0:15 - ring_size: size of the ring in unit of 4-bytes words
+ * b'16:23 - ring_entry_size: Size of each entry in 4-byte word units
+ * b'24:31 - ring_misc_cfg_flag: Valid only for HW_TO_SW_RING and
+ * SW_TO_HW_RING.
+ * Refer to HTT_SRING_SETUP_RING_MISC_CFG_RING defs.
+ * dword4 - b'0:31 - ring_head_off32_remote_addr_lo:
+ * Lower 32 bits of memory address of the remote variable
+ * storing the 4-byte word offset that identifies the head
+ * element within the ring.
+ * (The head offset variable has type u32.)
+ * Valid for HW_TO_SW and SW_TO_SW rings.
+ * dword5 - b'0:31 - ring_head_off32_remote_addr_hi:
+ * Upper 32 bits of memory address of the remote variable
+ * storing the 4-byte word offset that identifies the head
+ * element within the ring.
+ * (The head offset variable has type u32.)
+ * Valid for HW_TO_SW and SW_TO_SW rings.
+ * dword6 - b'0:31 - ring_tail_off32_remote_addr_lo:
+ * Lower 32 bits of memory address of the remote variable
+ * storing the 4-byte word offset that identifies the tail
+ * element within the ring.
+ * (The tail offset variable has type u32.)
+ * Valid for HW_TO_SW and SW_TO_SW rings.
+ * dword7 - b'0:31 - ring_tail_off32_remote_addr_hi:
+ * Upper 32 bits of memory address of the remote variable
+ * storing the 4-byte word offset that identifies the tail
+ * element within the ring.
+ * (The tail offset variable has type u32.)
+ * Valid for HW_TO_SW and SW_TO_SW rings.
+ * dword8 - b'0:31 - ring_msi_addr_lo: Lower 32bits of MSI cfg address
+ * valid only for HW_TO_SW_RING and SW_TO_HW_RING
+ * dword9 - b'0:31 - ring_msi_addr_hi: Upper 32bits of MSI cfg address
+ * valid only for HW_TO_SW_RING and SW_TO_HW_RING
+ * dword10 - b'0:31 - ring_msi_data: MSI data
+ * Refer to HTT_SRING_SETUP_RING_MSC_CFG_xxx defs
+ * valid only for HW_TO_SW_RING and SW_TO_HW_RING
+ * dword11 - b'0:14 - intr_batch_counter_th:
+ * batch counter threshold is in units of 4-byte words.
+ * HW internally maintains and increments batch count.
+ * (see SRING spec for detail description).
+ * When batch count reaches threshold value, an interrupt
+ * is generated by HW.
+ * b'15 - sw_intr_mode:
+ * This configuration shall be static.
+ * Only programmed at power up.
+ * 0: generate pulse style sw interrupts
+ * 1: generate level style sw interrupts
+ * b'16:31 - intr_timer_th:
+ * The timer init value when timer is idle or is
+ * initialized to start downcounting.
+ * In 8us units (to cover a range of 0 to 524 ms)
+ * dword12 - b'0:15 - intr_low_threshold:
+ * Used only by Consumer ring to generate ring_sw_int_p.
+ * Ring entries low threshold water mark, that is used
+ * in combination with the interrupt timer as well as
+ * the clearing of the level interrupt.
+ * b'16:18 - prefetch_timer_cfg:
+ * Used only by Consumer ring to set timer mode to
+ * support Application prefetch handling.
+ * The external tail offset/pointer will be updated
+ * at following intervals:
+ * 3'b000: (Prefetch feature disabled; used only for debug)
+ * 3'b001: 1 usec
+ * 3'b010: 4 usec
+ * 3'b011: 8 usec (default)
+ * 3'b100: 16 usec
+ * Others: Reserved
+ * b'19 - response_required:
+ * Host needs HTT_T2H_MSG_TYPE_SRING_SETUP_DONE as response
+ * b'20:31 - reserved: reserved for future use
+ */
+
+#define HTT_SRNG_SETUP_CMD_INFO0_MSG_TYPE GENMASK(7, 0)
+#define HTT_SRNG_SETUP_CMD_INFO0_PDEV_ID GENMASK(15, 8)
+#define HTT_SRNG_SETUP_CMD_INFO0_RING_ID GENMASK(23, 16)
+#define HTT_SRNG_SETUP_CMD_INFO0_RING_TYPE GENMASK(31, 24)
+
+#define HTT_SRNG_SETUP_CMD_INFO1_RING_SIZE GENMASK(15, 0)
+#define HTT_SRNG_SETUP_CMD_INFO1_RING_ENTRY_SIZE GENMASK(23, 16)
+#define HTT_SRNG_SETUP_CMD_INFO1_RING_LOOP_CNT_DIS BIT(25)
+#define HTT_SRNG_SETUP_CMD_INFO1_RING_FLAGS_MSI_SWAP BIT(27)
+#define HTT_SRNG_SETUP_CMD_INFO1_RING_FLAGS_HOST_FW_SWAP BIT(28)
+#define HTT_SRNG_SETUP_CMD_INFO1_RING_FLAGS_TLV_SWAP BIT(29)
+
+#define HTT_SRNG_SETUP_CMD_INTR_INFO_BATCH_COUNTER_THRESH GENMASK(14, 0)
+#define HTT_SRNG_SETUP_CMD_INTR_INFO_SW_INTR_MODE BIT(15)
+#define HTT_SRNG_SETUP_CMD_INTR_INFO_INTR_TIMER_THRESH GENMASK(31, 16)
+
+#define HTT_SRNG_SETUP_CMD_INFO2_INTR_LOW_THRESH GENMASK(15, 0)
+#define HTT_SRNG_SETUP_CMD_INFO2_PRE_FETCH_TIMER_CFG GENMASK(18, 16)
+#define HTT_SRNG_SETUP_CMD_INFO2_RESPONSE_REQUIRED BIT(19)
+
+struct htt_srng_setup_cmd {
+ __le32 info0;
+ __le32 ring_base_addr_lo;
+ __le32 ring_base_addr_hi;
+ __le32 info1;
+ __le32 ring_head_off32_remote_addr_lo;
+ __le32 ring_head_off32_remote_addr_hi;
+ __le32 ring_tail_off32_remote_addr_lo;
+ __le32 ring_tail_off32_remote_addr_hi;
+ __le32 ring_msi_addr_lo;
+ __le32 ring_msi_addr_hi;
+ __le32 msi_data;
+ __le32 intr_info;
+ __le32 info2;
+} __packed;
+
+/* host -> target FW PPDU_STATS config message
+ *
+ * @details
+ * The following field definitions describe the format of the HTT host
+ * to target FW for PPDU_STATS_CFG msg.
+ * The message allows the host to configure the PPDU_STATS_IND messages
+ * produced by the target.
+ *
+ * |31 24|23 16|15 8|7 0|
+ * |-----------------------------------------------------------|
+ * | REQ bit mask | pdev_mask | msg type |
+ * |-----------------------------------------------------------|
+ * Header fields:
+ * - MSG_TYPE
+ * Bits 7:0
+ * Purpose: identifies this is a req to configure ppdu_stats_ind from target
+ * Value: 0x11
+ * - PDEV_MASK
+ * Bits 8:15
+ * Purpose: identifies which pdevs this PPDU stats configuration applies to
+ * Value: This is a overloaded field, refer to usage and interpretation of
+ * PDEV in interface document.
+ * Bit 8 : Reserved for SOC stats
+ * Bit 9 - 15 : Indicates PDEV_MASK in DBDC
+ * Indicates MACID_MASK in DBS
+ * - REQ_TLV_BIT_MASK
+ * Bits 16:31
+ * Purpose: each set bit indicates the corresponding PPDU stats TLV type
+ * needs to be included in the target's PPDU_STATS_IND messages.
+ * Value: refer htt_ppdu_stats_tlv_tag_t <<<???
+ *
+ */
+
+struct htt_ppdu_stats_cfg_cmd {
+ __le32 msg;
+} __packed;
+
+#define HTT_PPDU_STATS_CFG_MSG_TYPE GENMASK(7, 0)
+#define HTT_PPDU_STATS_CFG_SOC_STATS BIT(8)
+#define HTT_PPDU_STATS_CFG_PDEV_ID GENMASK(15, 9)
+#define HTT_PPDU_STATS_CFG_TLV_TYPE_BITMASK GENMASK(31, 16)
+
+enum htt_ppdu_stats_tag_type {
+ HTT_PPDU_STATS_TAG_COMMON,
+ HTT_PPDU_STATS_TAG_USR_COMMON,
+ HTT_PPDU_STATS_TAG_USR_RATE,
+ HTT_PPDU_STATS_TAG_USR_MPDU_ENQ_BITMAP_64,
+ HTT_PPDU_STATS_TAG_USR_MPDU_ENQ_BITMAP_256,
+ HTT_PPDU_STATS_TAG_SCH_CMD_STATUS,
+ HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON,
+ HTT_PPDU_STATS_TAG_USR_COMPLTN_BA_BITMAP_64,
+ HTT_PPDU_STATS_TAG_USR_COMPLTN_BA_BITMAP_256,
+ HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS,
+ HTT_PPDU_STATS_TAG_USR_COMPLTN_FLUSH,
+ HTT_PPDU_STATS_TAG_USR_COMMON_ARRAY,
+ HTT_PPDU_STATS_TAG_INFO,
+ HTT_PPDU_STATS_TAG_TX_MGMTCTRL_PAYLOAD,
+
+ /* New TLV's are added above to this line */
+ HTT_PPDU_STATS_TAG_MAX,
+};
+
+#define HTT_PPDU_STATS_TAG_DEFAULT (BIT(HTT_PPDU_STATS_TAG_COMMON) \
+ | BIT(HTT_PPDU_STATS_TAG_USR_COMMON) \
+ | BIT(HTT_PPDU_STATS_TAG_USR_RATE) \
+ | BIT(HTT_PPDU_STATS_TAG_SCH_CMD_STATUS) \
+ | BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON) \
+ | BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS) \
+ | BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_FLUSH) \
+ | BIT(HTT_PPDU_STATS_TAG_USR_COMMON_ARRAY))
+
+#define HTT_PPDU_STATS_TAG_PKTLOG (BIT(HTT_PPDU_STATS_TAG_USR_MPDU_ENQ_BITMAP_64) | \
+ BIT(HTT_PPDU_STATS_TAG_USR_MPDU_ENQ_BITMAP_256) | \
+ BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_BA_BITMAP_64) | \
+ BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_BA_BITMAP_256) | \
+ BIT(HTT_PPDU_STATS_TAG_INFO) | \
+ BIT(HTT_PPDU_STATS_TAG_TX_MGMTCTRL_PAYLOAD) | \
+ HTT_PPDU_STATS_TAG_DEFAULT)
+
+enum htt_stats_internal_ppdu_frametype {
+ HTT_STATS_PPDU_FTYPE_CTRL,
+ HTT_STATS_PPDU_FTYPE_DATA,
+ HTT_STATS_PPDU_FTYPE_BAR,
+ HTT_STATS_PPDU_FTYPE_MAX
+};
+
+/* HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG Message
+ *
+ * details:
+ * HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG message is sent by host to
+ * configure RXDMA rings.
+ * The configuration is per ring based and includes both packet subtypes
+ * and PPDU/MPDU TLVs.
+ *
+ * The message would appear as follows:
+ *
+ * |31 29|28|27|26|25|24|23 16|15 8|7 0|
+ * |-------+--+--+--+--+--+-----------+----------------+---------------|
+ * | rsvd1 |ED|DT|OV|PS|SS| ring_id | pdev_id | msg_type |
+ * |-------------------------------------------------------------------|
+ * | rsvd2 | ring_buffer_size |
+ * |-------------------------------------------------------------------|
+ * | packet_type_enable_flags_0 |
+ * |-------------------------------------------------------------------|
+ * | packet_type_enable_flags_1 |
+ * |-------------------------------------------------------------------|
+ * | packet_type_enable_flags_2 |
+ * |-------------------------------------------------------------------|
+ * | packet_type_enable_flags_3 |
+ * |-------------------------------------------------------------------|
+ * | tlv_filter_in_flags |
+ * |-------------------------------------------------------------------|
+ * Where:
+ * PS = pkt_swap
+ * SS = status_swap
+ * The message is interpreted as follows:
+ * dword0 - b'0:7 - msg_type: This will be set to
+ * HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG
+ * b'8:15 - pdev_id:
+ * 0 (for rings at SOC/UMAC level),
+ * 1/2/3 mac id (for rings at LMAC level)
+ * b'16:23 - ring_id : Identify the ring to configure.
+ * More details can be got from enum htt_srng_ring_id
+ * b'24 - status_swap: 1 is to swap status TLV
+ * b'25 - pkt_swap: 1 is to swap packet TLV
+ * b'26 - rx_offset_valid (OV): flag to indicate rx offsets
+ * configuration fields are valid
+ * b'27 - drop_thresh_valid (DT): flag to indicate if the
+ * rx_drop_threshold field is valid
+ * b'28 - rx_mon_global_en: Enable/Disable global register
+ * configuration in Rx monitor module.
+ * b'29:31 - rsvd1: reserved for future use
+ * dword1 - b'0:16 - ring_buffer_size: size of buffers referenced by rx ring,
+ * in byte units.
+ * Valid only for HW_TO_SW_RING and SW_TO_HW_RING
+ * - b'16:31 - rsvd2: Reserved for future use
+ * dword2 - b'0:31 - packet_type_enable_flags_0:
+ * Enable MGMT packet from 0b0000 to 0b1001
+ * bits from low to high: FP, MD, MO - 3 bits
+ * FP: Filter_Pass
+ * MD: Monitor_Direct
+ * MO: Monitor_Other
+ * 10 mgmt subtypes * 3 bits -> 30 bits
+ * Refer to PKT_TYPE_ENABLE_FLAG0_xxx_MGMT_xxx defs
+ * dword3 - b'0:31 - packet_type_enable_flags_1:
+ * Enable MGMT packet from 0b1010 to 0b1111
+ * bits from low to high: FP, MD, MO - 3 bits
+ * Refer to PKT_TYPE_ENABLE_FLAG1_xxx_MGMT_xxx defs
+ * dword4 - b'0:31 - packet_type_enable_flags_2:
+ * Enable CTRL packet from 0b0000 to 0b1001
+ * bits from low to high: FP, MD, MO - 3 bits
+ * Refer to PKT_TYPE_ENABLE_FLAG2_xxx_CTRL_xxx defs
+ * dword5 - b'0:31 - packet_type_enable_flags_3:
+ * Enable CTRL packet from 0b1010 to 0b1111,
+ * MCAST_DATA, UCAST_DATA, NULL_DATA
+ * bits from low to high: FP, MD, MO - 3 bits
+ * Refer to PKT_TYPE_ENABLE_FLAG3_xxx_CTRL_xxx defs
+ * dword6 - b'0:31 - tlv_filter_in_flags:
+ * Filter in Attention/MPDU/PPDU/Header/User tlvs
+ * Refer to CFG_TLV_FILTER_IN_FLAG defs
+ */
+
+#define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_MSG_TYPE GENMASK(7, 0)
+#define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID GENMASK(15, 8)
+#define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_RING_ID GENMASK(23, 16)
+#define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_SS BIT(24)
+#define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PS BIT(25)
+#define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_OFFSET_VALID BIT(26)
+#define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_DROP_THRES_VAL BIT(27)
+#define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_EN_RXMON BIT(28)
+
+#define HTT_RX_RING_SELECTION_CFG_CMD_INFO1_BUF_SIZE GENMASK(15, 0)
+#define HTT_RX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_MGMT GENMASK(18, 16)
+#define HTT_RX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_CTRL GENMASK(21, 19)
+#define HTT_RX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_DATA GENMASK(24, 22)
+
+#define HTT_RX_RING_SELECTION_CFG_CMD_INFO2_DROP_THRESHOLD GENMASK(9, 0)
+#define HTT_RX_RING_SELECTION_CFG_CMD_INFO2_EN_LOG_MGMT_TYPE BIT(17)
+#define HTT_RX_RING_SELECTION_CFG_CMD_INFO2_EN_CTRL_TYPE BIT(18)
+#define HTT_RX_RING_SELECTION_CFG_CMD_INFO2_EN_LOG_DATA_TYPE BIT(19)
+
+#define HTT_RX_RING_SELECTION_CFG_CMD_INFO3_EN_TLV_PKT_OFFSET BIT(0)
+#define HTT_RX_RING_SELECTION_CFG_CMD_INFO3_PKT_TLV_OFFSET GENMASK(14, 1)
+
+#define HTT_RX_RING_SELECTION_CFG_RX_PACKET_OFFSET GENMASK(15, 0)
+#define HTT_RX_RING_SELECTION_CFG_RX_HEADER_OFFSET GENMASK(31, 16)
+#define HTT_RX_RING_SELECTION_CFG_RX_MPDU_END_OFFSET GENMASK(15, 0)
+#define HTT_RX_RING_SELECTION_CFG_RX_MPDU_START_OFFSET GENMASK(31, 16)
+#define HTT_RX_RING_SELECTION_CFG_RX_MSDU_END_OFFSET GENMASK(15, 0)
+#define HTT_RX_RING_SELECTION_CFG_RX_MSDU_START_OFFSET GENMASK(31, 16)
+#define HTT_RX_RING_SELECTION_CFG_RX_ATTENTION_OFFSET GENMASK(15, 0)
+
+#define HTT_RX_RING_SELECTION_CFG_WORD_MASK_COMPACT_SET BIT(23)
+#define HTT_RX_RING_SELECTION_CFG_RX_MPDU_START_MASK GENMASK(15, 0)
+#define HTT_RX_RING_SELECTION_CFG_RX_MPDU_END_MASK GENMASK(18, 16)
+#define HTT_RX_RING_SELECTION_CFG_RX_MSDU_END_MASK GENMASK(16, 0)
+
+enum htt_rx_filter_tlv_flags {
+ HTT_RX_FILTER_TLV_FLAGS_MPDU_START = BIT(0),
+ HTT_RX_FILTER_TLV_FLAGS_MSDU_START = BIT(1),
+ HTT_RX_FILTER_TLV_FLAGS_RX_PACKET = BIT(2),
+ HTT_RX_FILTER_TLV_FLAGS_MSDU_END = BIT(3),
+ HTT_RX_FILTER_TLV_FLAGS_MPDU_END = BIT(4),
+ HTT_RX_FILTER_TLV_FLAGS_PACKET_HEADER = BIT(5),
+ HTT_RX_FILTER_TLV_FLAGS_PER_MSDU_HEADER = BIT(6),
+ HTT_RX_FILTER_TLV_FLAGS_ATTENTION = BIT(7),
+ HTT_RX_FILTER_TLV_FLAGS_PPDU_START = BIT(8),
+ HTT_RX_FILTER_TLV_FLAGS_PPDU_END = BIT(9),
+ HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS = BIT(10),
+ HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT = BIT(11),
+ HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE = BIT(12),
+ HTT_RX_FILTER_TLV_FLAGS_PPDU_START_USER_INFO = BIT(13),
+};
+
+enum htt_rx_mgmt_pkt_filter_tlv_flags0 {
+ HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_REQ = BIT(0),
+ HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_REQ = BIT(1),
+ HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_REQ = BIT(2),
+ HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_RESP = BIT(3),
+ HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_RESP = BIT(4),
+ HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_RESP = BIT(5),
+ HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_REQ = BIT(6),
+ HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_REQ = BIT(7),
+ HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_REQ = BIT(8),
+ HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_RESP = BIT(9),
+ HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_RESP = BIT(10),
+ HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_RESP = BIT(11),
+ HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_REQ = BIT(12),
+ HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_REQ = BIT(13),
+ HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_REQ = BIT(14),
+ HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_RESP = BIT(15),
+ HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_RESP = BIT(16),
+ HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_RESP = BIT(17),
+ HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_TIMING_ADV = BIT(18),
+ HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_TIMING_ADV = BIT(19),
+ HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_TIMING_ADV = BIT(20),
+ HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_RESERVED_7 = BIT(21),
+ HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_RESERVED_7 = BIT(22),
+ HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_RESERVED_7 = BIT(23),
+ HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_BEACON = BIT(24),
+ HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_BEACON = BIT(25),
+ HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_BEACON = BIT(26),
+ HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_ATIM = BIT(27),
+ HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_ATIM = BIT(28),
+ HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_ATIM = BIT(29),
+};
+
+enum htt_rx_mgmt_pkt_filter_tlv_flags1 {
+ HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_DISASSOC = BIT(0),
+ HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_DISASSOC = BIT(1),
+ HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_DISASSOC = BIT(2),
+ HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_AUTH = BIT(3),
+ HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_AUTH = BIT(4),
+ HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_AUTH = BIT(5),
+ HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_DEAUTH = BIT(6),
+ HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_DEAUTH = BIT(7),
+ HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_DEAUTH = BIT(8),
+ HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION = BIT(9),
+ HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION = BIT(10),
+ HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION = BIT(11),
+ HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION_NOACK = BIT(12),
+ HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION_NOACK = BIT(13),
+ HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION_NOACK = BIT(14),
+ HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_RESERVED_15 = BIT(15),
+ HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_RESERVED_15 = BIT(16),
+ HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_RESERVED_15 = BIT(17),
+};
+
+enum htt_rx_ctrl_pkt_filter_tlv_flags2 {
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_1 = BIT(0),
+ HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_1 = BIT(1),
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_1 = BIT(2),
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_2 = BIT(3),
+ HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_2 = BIT(4),
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_2 = BIT(5),
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_TRIGGER = BIT(6),
+ HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_TRIGGER = BIT(7),
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_TRIGGER = BIT(8),
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_4 = BIT(9),
+ HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_4 = BIT(10),
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_4 = BIT(11),
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_BF_REP_POLL = BIT(12),
+ HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_BF_REP_POLL = BIT(13),
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_BF_REP_POLL = BIT(14),
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_VHT_NDP = BIT(15),
+ HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_VHT_NDP = BIT(16),
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_VHT_NDP = BIT(17),
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_FRAME_EXT = BIT(18),
+ HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_FRAME_EXT = BIT(19),
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_FRAME_EXT = BIT(20),
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_WRAPPER = BIT(21),
+ HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_WRAPPER = BIT(22),
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_WRAPPER = BIT(23),
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_BAR = BIT(24),
+ HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_BAR = BIT(25),
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_BAR = BIT(26),
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_BA = BIT(27),
+ HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_BA = BIT(28),
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_BA = BIT(29),
+};
+
+enum htt_rx_ctrl_pkt_filter_tlv_flags3 {
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_PSPOLL = BIT(0),
+ HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_PSPOLL = BIT(1),
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_PSPOLL = BIT(2),
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_RTS = BIT(3),
+ HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_RTS = BIT(4),
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_RTS = BIT(5),
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_CTS = BIT(6),
+ HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_CTS = BIT(7),
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_CTS = BIT(8),
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_ACK = BIT(9),
+ HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_ACK = BIT(10),
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_ACK = BIT(11),
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND = BIT(12),
+ HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND = BIT(13),
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND = BIT(14),
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND_ACK = BIT(15),
+ HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND_ACK = BIT(16),
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND_ACK = BIT(17),
+};
+
+enum htt_rx_data_pkt_filter_tlv_flasg3 {
+ HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_MCAST = BIT(18),
+ HTT_RX_MD_DATA_PKT_FILTER_TLV_FLASG3_MCAST = BIT(19),
+ HTT_RX_MO_DATA_PKT_FILTER_TLV_FLASG3_MCAST = BIT(20),
+ HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_UCAST = BIT(21),
+ HTT_RX_MD_DATA_PKT_FILTER_TLV_FLASG3_UCAST = BIT(22),
+ HTT_RX_MO_DATA_PKT_FILTER_TLV_FLASG3_UCAST = BIT(23),
+ HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA = BIT(24),
+ HTT_RX_MD_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA = BIT(25),
+ HTT_RX_MO_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA = BIT(26),
+};
+
+#define HTT_RX_FP_MGMT_FILTER_FLAGS0 \
+ (HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_REQ \
+ | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_RESP \
+ | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_REQ \
+ | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_RESP \
+ | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_REQ \
+ | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_RESP \
+ | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_TIMING_ADV \
+ | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_BEACON \
+ | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_ATIM)
+
+#define HTT_RX_MD_MGMT_FILTER_FLAGS0 \
+ (HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_REQ \
+ | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_RESP \
+ | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_REQ \
+ | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_RESP \
+ | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_REQ \
+ | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_RESP \
+ | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_TIMING_ADV \
+ | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_BEACON \
+ | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_ATIM)
+
+#define HTT_RX_MO_MGMT_FILTER_FLAGS0 \
+ (HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_REQ \
+ | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_RESP \
+ | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_REQ \
+ | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_REASSOC_RESP \
+ | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_REQ \
+ | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_RESP \
+ | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_TIMING_ADV \
+ | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_BEACON \
+ | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_ATIM)
+
+#define HTT_RX_FP_MGMT_FILTER_FLAGS1 (HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_DISASSOC \
+ | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_AUTH \
+ | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_DEAUTH \
+ | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION \
+ | HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION_NOACK)
+
+#define HTT_RX_MD_MGMT_FILTER_FLAGS1 (HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_DISASSOC \
+ | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_AUTH \
+ | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_DEAUTH \
+ | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION \
+ | HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION_NOACK)
+
+#define HTT_RX_MO_MGMT_FILTER_FLAGS1 (HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_DISASSOC \
+ | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_AUTH \
+ | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_DEAUTH \
+ | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION \
+ | HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION_NOACK)
+
+#define HTT_RX_FP_CTRL_FILTER_FLASG2 (HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_WRAPPER \
+ | HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_BAR \
+ | HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_BA)
+
+#define HTT_RX_MD_CTRL_FILTER_FLASG2 (HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_WRAPPER \
+ | HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_BAR \
+ | HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_BA)
+
+#define HTT_RX_MO_CTRL_FILTER_FLASG2 (HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_WRAPPER \
+ | HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_BAR \
+ | HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_BA)
+
+#define HTT_RX_FP_CTRL_FILTER_FLASG3 (HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_PSPOLL \
+ | HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_RTS \
+ | HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_CTS \
+ | HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_ACK \
+ | HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND \
+ | HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND_ACK)
+
+#define HTT_RX_MD_CTRL_FILTER_FLASG3 (HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_PSPOLL \
+ | HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_RTS \
+ | HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_CTS \
+ | HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_ACK \
+ | HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND \
+ | HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND_ACK)
+
+#define HTT_RX_MO_CTRL_FILTER_FLASG3 (HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_PSPOLL \
+ | HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_RTS \
+ | HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_CTS \
+ | HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_ACK \
+ | HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND \
+ | HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS3_CFEND_ACK)
+
+#define HTT_RX_FP_DATA_FILTER_FLASG3 (HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_MCAST \
+ | HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_UCAST \
+ | HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA)
+
+#define HTT_RX_MD_DATA_FILTER_FLASG3 (HTT_RX_MD_DATA_PKT_FILTER_TLV_FLASG3_MCAST \
+ | HTT_RX_MD_DATA_PKT_FILTER_TLV_FLASG3_UCAST \
+ | HTT_RX_MD_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA)
+
+#define HTT_RX_MO_DATA_FILTER_FLASG3 (HTT_RX_MO_DATA_PKT_FILTER_TLV_FLASG3_MCAST \
+ | HTT_RX_MO_DATA_PKT_FILTER_TLV_FLASG3_UCAST \
+ | HTT_RX_MO_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA)
+
+#define HTT_RX_MON_FP_MGMT_FILTER_FLAGS0 \
+ (HTT_RX_FP_MGMT_FILTER_FLAGS0 | \
+ HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_RESERVED_7)
+
+#define HTT_RX_MON_MO_MGMT_FILTER_FLAGS0 \
+ (HTT_RX_MO_MGMT_FILTER_FLAGS0 | \
+ HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_RESERVED_7)
+
+#define HTT_RX_MON_FP_MGMT_FILTER_FLAGS1 \
+ (HTT_RX_FP_MGMT_FILTER_FLAGS1 | \
+ HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_RESERVED_15)
+
+#define HTT_RX_MON_MO_MGMT_FILTER_FLAGS1 \
+ (HTT_RX_MO_MGMT_FILTER_FLAGS1 | \
+ HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_RESERVED_15)
+
+#define HTT_RX_MON_FP_CTRL_FILTER_FLASG2 \
+ (HTT_RX_FP_CTRL_FILTER_FLASG2 | \
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_1 | \
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_2 | \
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_TRIGGER | \
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_4 | \
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_BF_REP_POLL | \
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_VHT_NDP | \
+ HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_FRAME_EXT)
+
+#define HTT_RX_MON_MO_CTRL_FILTER_FLASG2 \
+ (HTT_RX_MO_CTRL_FILTER_FLASG2 | \
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_1 | \
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_2 | \
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_TRIGGER | \
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_4 | \
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_BF_REP_POLL | \
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_VHT_NDP | \
+ HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_FRAME_EXT)
+
+#define HTT_RX_MON_FP_CTRL_FILTER_FLASG3 HTT_RX_FP_CTRL_FILTER_FLASG3
+
+#define HTT_RX_MON_MO_CTRL_FILTER_FLASG3 HTT_RX_MO_CTRL_FILTER_FLASG3
+
+#define HTT_RX_MON_FP_DATA_FILTER_FLASG3 HTT_RX_FP_DATA_FILTER_FLASG3
+
+#define HTT_RX_MON_MO_DATA_FILTER_FLASG3 HTT_RX_MO_DATA_FILTER_FLASG3
+
+#define HTT_RX_MON_FILTER_TLV_FLAGS \
+ (HTT_RX_FILTER_TLV_FLAGS_MPDU_START | \
+ HTT_RX_FILTER_TLV_FLAGS_PPDU_START | \
+ HTT_RX_FILTER_TLV_FLAGS_PPDU_END | \
+ HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS | \
+ HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT | \
+ HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE)
+
+#define HTT_RX_MON_FILTER_TLV_FLAGS_MON_STATUS_RING \
+ (HTT_RX_FILTER_TLV_FLAGS_MPDU_START | \
+ HTT_RX_FILTER_TLV_FLAGS_PPDU_START | \
+ HTT_RX_FILTER_TLV_FLAGS_PPDU_END | \
+ HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS | \
+ HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT | \
+ HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE)
+
+#define HTT_RX_MON_FILTER_TLV_FLAGS_MON_BUF_RING \
+ (HTT_RX_FILTER_TLV_FLAGS_MPDU_START | \
+ HTT_RX_FILTER_TLV_FLAGS_MSDU_START | \
+ HTT_RX_FILTER_TLV_FLAGS_RX_PACKET | \
+ HTT_RX_FILTER_TLV_FLAGS_MSDU_END | \
+ HTT_RX_FILTER_TLV_FLAGS_MPDU_END | \
+ HTT_RX_FILTER_TLV_FLAGS_PACKET_HEADER | \
+ HTT_RX_FILTER_TLV_FLAGS_PER_MSDU_HEADER | \
+ HTT_RX_FILTER_TLV_FLAGS_ATTENTION)
+
+#define HTT_RX_MON_FILTER_TLV_FLAGS_MON_DEST_RING \
+ (HTT_RX_FILTER_TLV_FLAGS_MPDU_START | \
+ HTT_RX_FILTER_TLV_FLAGS_MSDU_START | \
+ HTT_RX_FILTER_TLV_FLAGS_RX_PACKET | \
+ HTT_RX_FILTER_TLV_FLAGS_MSDU_END | \
+ HTT_RX_FILTER_TLV_FLAGS_MPDU_END | \
+ HTT_RX_FILTER_TLV_FLAGS_PACKET_HEADER | \
+ HTT_RX_FILTER_TLV_FLAGS_PER_MSDU_HEADER | \
+ HTT_RX_FILTER_TLV_FLAGS_PPDU_START | \
+ HTT_RX_FILTER_TLV_FLAGS_PPDU_END | \
+ HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS | \
+ HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT | \
+ HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE | \
+ HTT_RX_FILTER_TLV_FLAGS_PPDU_START_USER_INFO)
+
+/* msdu start. mpdu end, attention, rx hdr tlv's are not subscribed */
+#define HTT_RX_TLV_FLAGS_RXDMA_RING \
+ (HTT_RX_FILTER_TLV_FLAGS_MPDU_START | \
+ HTT_RX_FILTER_TLV_FLAGS_RX_PACKET | \
+ HTT_RX_FILTER_TLV_FLAGS_MSDU_END)
+
+#define HTT_TX_RING_SELECTION_CFG_CMD_INFO0_MSG_TYPE GENMASK(7, 0)
+#define HTT_TX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID GENMASK(15, 8)
+
+struct htt_rx_ring_selection_cfg_cmd {
+ __le32 info0;
+ __le32 info1;
+ __le32 pkt_type_en_flags0;
+ __le32 pkt_type_en_flags1;
+ __le32 pkt_type_en_flags2;
+ __le32 pkt_type_en_flags3;
+ __le32 rx_filter_tlv;
+ __le32 rx_packet_offset;
+ __le32 rx_mpdu_offset;
+ __le32 rx_msdu_offset;
+ __le32 rx_attn_offset;
+ __le32 info2;
+ __le32 reserved[2];
+ __le32 rx_mpdu_start_end_mask;
+ __le32 rx_msdu_end_word_mask;
+ __le32 info3;
+} __packed;
+
+#define HTT_RX_RING_TLV_DROP_THRESHOLD_VALUE 32
+#define HTT_RX_RING_DEFAULT_DMA_LENGTH 0x7
+#define HTT_RX_RING_PKT_TLV_OFFSET 0x1
+
+struct htt_rx_ring_tlv_filter {
+ u32 rx_filter; /* see htt_rx_filter_tlv_flags */
+ u32 pkt_filter_flags0; /* MGMT */
+ u32 pkt_filter_flags1; /* MGMT */
+ u32 pkt_filter_flags2; /* CTRL */
+ u32 pkt_filter_flags3; /* DATA */
+ bool offset_valid;
+ u16 rx_packet_offset;
+ u16 rx_header_offset;
+ u16 rx_mpdu_end_offset;
+ u16 rx_mpdu_start_offset;
+ u16 rx_msdu_end_offset;
+ u16 rx_msdu_start_offset;
+ u16 rx_attn_offset;
+ u16 rx_mpdu_start_wmask;
+ u16 rx_mpdu_end_wmask;
+ u32 rx_msdu_end_wmask;
+ u32 conf_len_ctrl;
+ u32 conf_len_mgmt;
+ u32 conf_len_data;
+ u16 rx_drop_threshold;
+ bool enable_log_mgmt_type;
+ bool enable_log_ctrl_type;
+ bool enable_log_data_type;
+ bool enable_rx_tlv_offset;
+ u16 rx_tlv_offset;
+ bool drop_threshold_valid;
+ bool rxmon_disable;
+};
+
+#define HTT_STATS_FRAME_CTRL_TYPE_MGMT 0x0
+#define HTT_STATS_FRAME_CTRL_TYPE_CTRL 0x1
+#define HTT_STATS_FRAME_CTRL_TYPE_DATA 0x2
+#define HTT_STATS_FRAME_CTRL_TYPE_RESV 0x3
+
+#define HTT_TX_RING_SELECTION_CFG_CMD_INFO0_MSG_TYPE GENMASK(7, 0)
+#define HTT_TX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID GENMASK(15, 8)
+#define HTT_TX_RING_SELECTION_CFG_CMD_INFO0_RING_ID GENMASK(23, 16)
+#define HTT_TX_RING_SELECTION_CFG_CMD_INFO0_SS BIT(24)
+#define HTT_TX_RING_SELECTION_CFG_CMD_INFO0_PS BIT(25)
+
+#define HTT_TX_RING_SELECTION_CFG_CMD_INFO1_RING_BUFF_SIZE GENMASK(15, 0)
+#define HTT_TX_RING_SELECTION_CFG_CMD_INFO1_PKT_TYPE GENMASK(18, 16)
+#define HTT_TX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_MGMT GENMASK(21, 19)
+#define HTT_TX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_CTRL GENMASK(24, 22)
+#define HTT_TX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_DATA GENMASK(27, 25)
+
+#define HTT_TX_RING_SELECTION_CFG_CMD_INFO2_PKT_TYPE_EN_FLAG GENMASK(2, 0)
+
+struct htt_tx_ring_selection_cfg_cmd {
+ __le32 info0;
+ __le32 info1;
+ __le32 info2;
+ __le32 tlv_filter_mask_in0;
+ __le32 tlv_filter_mask_in1;
+ __le32 tlv_filter_mask_in2;
+ __le32 tlv_filter_mask_in3;
+ __le32 reserved[3];
+} __packed;
+
+#define HTT_TX_RING_TLV_FILTER_MGMT_DMA_LEN GENMASK(3, 0)
+#define HTT_TX_RING_TLV_FILTER_CTRL_DMA_LEN GENMASK(7, 4)
+#define HTT_TX_RING_TLV_FILTER_DATA_DMA_LEN GENMASK(11, 8)
+
+#define HTT_TX_MON_FILTER_HYBRID_MODE \
+ (HTT_TX_FILTER_TLV_FLAGS0_RESPONSE_START_STATUS | \
+ HTT_TX_FILTER_TLV_FLAGS0_RESPONSE_END_STATUS | \
+ HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_START | \
+ HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_END | \
+ HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_START_PPDU | \
+ HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_USER_PPDU | \
+ HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_ACK_OR_BA | \
+ HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_1K_BA | \
+ HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_START_PROT | \
+ HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_PROT | \
+ HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_USER_RESPONSE | \
+ HTT_TX_FILTER_TLV_FLAGS0_RECEIVED_RESPONSE_INFO | \
+ HTT_TX_FILTER_TLV_FLAGS0_RECEIVED_RESPONSE_INFO_PART2)
+
+struct htt_tx_ring_tlv_filter {
+ u32 tx_mon_downstream_tlv_flags;
+ u32 tx_mon_upstream_tlv_flags0;
+ u32 tx_mon_upstream_tlv_flags1;
+ u32 tx_mon_upstream_tlv_flags2;
+ bool tx_mon_mgmt_filter;
+ bool tx_mon_data_filter;
+ bool tx_mon_ctrl_filter;
+ u16 tx_mon_pkt_dma_len;
+} __packed;
+
+enum htt_tx_mon_upstream_tlv_flags0 {
+ HTT_TX_FILTER_TLV_FLAGS0_RESPONSE_START_STATUS = BIT(1),
+ HTT_TX_FILTER_TLV_FLAGS0_RESPONSE_END_STATUS = BIT(2),
+ HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_START = BIT(3),
+ HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_END = BIT(4),
+ HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_START_PPDU = BIT(5),
+ HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_USER_PPDU = BIT(6),
+ HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_ACK_OR_BA = BIT(7),
+ HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_1K_BA = BIT(8),
+ HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_START_PROT = BIT(9),
+ HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_PROT = BIT(10),
+ HTT_TX_FILTER_TLV_FLAGS0_TX_FES_STATUS_USER_RESPONSE = BIT(11),
+ HTT_TX_FILTER_TLV_FLAGS0_RX_FRAME_BITMAP_ACK = BIT(12),
+ HTT_TX_FILTER_TLV_FLAGS0_RX_FRAME_1K_BITMAP_ACK = BIT(13),
+ HTT_TX_FILTER_TLV_FLAGS0_COEX_TX_STATUS = BIT(14),
+ HTT_TX_FILTER_TLV_FLAGS0_RECEIVED_RESPONSE_INFO = BIT(15),
+ HTT_TX_FILTER_TLV_FLAGS0_RECEIVED_RESPONSE_INFO_PART2 = BIT(16),
+};
+
+#define HTT_TX_FILTER_TLV_FLAGS2_TXPCU_PHYTX_OTHER_TRANSMIT_INFO32 BIT(11)
+
+/* HTT message target->host */
+
+enum htt_t2h_msg_type {
+ HTT_T2H_MSG_TYPE_VERSION_CONF,
+ HTT_T2H_MSG_TYPE_PEER_MAP = 0x3,
+ HTT_T2H_MSG_TYPE_PEER_UNMAP = 0x4,
+ HTT_T2H_MSG_TYPE_RX_ADDBA = 0x5,
+ HTT_T2H_MSG_TYPE_PKTLOG = 0x8,
+ HTT_T2H_MSG_TYPE_SEC_IND = 0xb,
+ HTT_T2H_MSG_TYPE_PEER_MAP2 = 0x1e,
+ HTT_T2H_MSG_TYPE_PEER_UNMAP2 = 0x1f,
+ HTT_T2H_MSG_TYPE_PPDU_STATS_IND = 0x1d,
+ HTT_T2H_MSG_TYPE_EXT_STATS_CONF = 0x1c,
+ HTT_T2H_MSG_TYPE_BKPRESSURE_EVENT_IND = 0x24,
+ HTT_T2H_MSG_TYPE_MLO_TIMESTAMP_OFFSET_IND = 0x28,
+ HTT_T2H_MSG_TYPE_PEER_MAP3 = 0x2b,
+ HTT_T2H_MSG_TYPE_VDEV_TXRX_STATS_PERIODIC_IND = 0x2c,
+};
+
+#define HTT_TARGET_VERSION_MAJOR 3
+
+#define HTT_T2H_MSG_TYPE GENMASK(7, 0)
+#define HTT_T2H_VERSION_CONF_MINOR GENMASK(15, 8)
+#define HTT_T2H_VERSION_CONF_MAJOR GENMASK(23, 16)
+
+struct htt_t2h_version_conf_msg {
+ __le32 version;
+} __packed;
+
+#define HTT_T2H_PEER_MAP_INFO_VDEV_ID GENMASK(15, 8)
+#define HTT_T2H_PEER_MAP_INFO_PEER_ID GENMASK(31, 16)
+#define HTT_T2H_PEER_MAP_INFO1_MAC_ADDR_H16 GENMASK(15, 0)
+#define HTT_T2H_PEER_MAP_INFO1_HW_PEER_ID GENMASK(31, 16)
+#define HTT_T2H_PEER_MAP_INFO2_AST_HASH_VAL GENMASK(15, 0)
+#define HTT_T2H_PEER_MAP3_INFO2_HW_PEER_ID GENMASK(15, 0)
+#define HTT_T2H_PEER_MAP3_INFO2_AST_HASH_VAL GENMASK(31, 16)
+#define HTT_T2H_PEER_MAP_INFO2_NEXT_HOP_M BIT(16)
+#define HTT_T2H_PEER_MAP_INFO2_NEXT_HOP_S 16
+
+struct htt_t2h_peer_map_event {
+ __le32 info;
+ __le32 mac_addr_l32;
+ __le32 info1;
+ __le32 info2;
+} __packed;
+
+#define HTT_T2H_PEER_UNMAP_INFO_VDEV_ID HTT_T2H_PEER_MAP_INFO_VDEV_ID
+#define HTT_T2H_PEER_UNMAP_INFO_PEER_ID HTT_T2H_PEER_MAP_INFO_PEER_ID
+#define HTT_T2H_PEER_UNMAP_INFO1_MAC_ADDR_H16 \
+ HTT_T2H_PEER_MAP_INFO1_MAC_ADDR_H16
+#define HTT_T2H_PEER_MAP_INFO1_NEXT_HOP_M HTT_T2H_PEER_MAP_INFO2_NEXT_HOP_M
+#define HTT_T2H_PEER_MAP_INFO1_NEXT_HOP_S HTT_T2H_PEER_MAP_INFO2_NEXT_HOP_S
+
+struct htt_t2h_peer_unmap_event {
+ __le32 info;
+ __le32 mac_addr_l32;
+ __le32 info1;
+} __packed;
+
+struct htt_resp_msg {
+ union {
+ struct htt_t2h_version_conf_msg version_msg;
+ struct htt_t2h_peer_map_event peer_map_ev;
+ struct htt_t2h_peer_unmap_event peer_unmap_ev;
+ };
+} __packed;
+
+#define HTT_VDEV_GET_STATS_U64(msg_l32, msg_u32)\
+ (((u64)__le32_to_cpu(msg_u32) << 32) | (__le32_to_cpu(msg_l32)))
+#define HTT_T2H_VDEV_STATS_PERIODIC_MSG_TYPE GENMASK(7, 0)
+#define HTT_T2H_VDEV_STATS_PERIODIC_PDEV_ID GENMASK(15, 8)
+#define HTT_T2H_VDEV_STATS_PERIODIC_NUM_VDEV GENMASK(23, 16)
+#define HTT_T2H_VDEV_STATS_PERIODIC_PAYLOAD_BYTES GENMASK(15, 0)
+#define HTT_VDEV_TXRX_STATS_COMMON_TLV 0
+#define HTT_VDEV_TXRX_STATS_HW_STATS_TLV 1
+
+struct htt_t2h_vdev_txrx_stats_ind {
+ __le32 vdev_id;
+ __le32 rx_msdu_byte_cnt_lo;
+ __le32 rx_msdu_byte_cnt_hi;
+ __le32 rx_msdu_cnt_lo;
+ __le32 rx_msdu_cnt_hi;
+ __le32 tx_msdu_byte_cnt_lo;
+ __le32 tx_msdu_byte_cnt_hi;
+ __le32 tx_msdu_cnt_lo;
+ __le32 tx_msdu_cnt_hi;
+ __le32 tx_retry_cnt_lo;
+ __le32 tx_retry_cnt_hi;
+ __le32 tx_retry_byte_cnt_lo;
+ __le32 tx_retry_byte_cnt_hi;
+ __le32 tx_drop_cnt_lo;
+ __le32 tx_drop_cnt_hi;
+ __le32 tx_drop_byte_cnt_lo;
+ __le32 tx_drop_byte_cnt_hi;
+ __le32 msdu_ttl_cnt_lo;
+ __le32 msdu_ttl_cnt_hi;
+ __le32 msdu_ttl_byte_cnt_lo;
+ __le32 msdu_ttl_byte_cnt_hi;
+} __packed;
+
+struct htt_t2h_vdev_common_stats_tlv {
+ __le32 soc_drop_count_lo;
+ __le32 soc_drop_count_hi;
+} __packed;
+
+/* ppdu stats
+ *
+ * @details
+ * The following field definitions describe the format of the HTT target
+ * to host ppdu stats indication message.
+ *
+ *
+ * |31 16|15 12|11 10|9 8|7 0 |
+ * |----------------------------------------------------------------------|
+ * | payload_size | rsvd |pdev_id|mac_id | msg type |
+ * |----------------------------------------------------------------------|
+ * | ppdu_id |
+ * |----------------------------------------------------------------------|
+ * | Timestamp in us |
+ * |----------------------------------------------------------------------|
+ * | reserved |
+ * |----------------------------------------------------------------------|
+ * | type-specific stats info |
+ * | (see htt_ppdu_stats.h) |
+ * |----------------------------------------------------------------------|
+ * Header fields:
+ * - MSG_TYPE
+ * Bits 7:0
+ * Purpose: Identifies this is a PPDU STATS indication
+ * message.
+ * Value: 0x1d
+ * - mac_id
+ * Bits 9:8
+ * Purpose: mac_id of this ppdu_id
+ * Value: 0-3
+ * - pdev_id
+ * Bits 11:10
+ * Purpose: pdev_id of this ppdu_id
+ * Value: 0-3
+ * 0 (for rings at SOC level),
+ * 1/2/3 PDEV -> 0/1/2
+ * - payload_size
+ * Bits 31:16
+ * Purpose: total tlv size
+ * Value: payload_size in bytes
+ */
+
+#define HTT_T2H_PPDU_STATS_INFO_PDEV_ID GENMASK(11, 10)
+#define HTT_T2H_PPDU_STATS_INFO_PAYLOAD_SIZE GENMASK(31, 16)
+
+struct ath12k_htt_ppdu_stats_msg {
+ __le32 info;
+ __le32 ppdu_id;
+ __le32 timestamp;
+ __le32 rsvd;
+ u8 data[];
+} __packed;
+
+struct htt_tlv {
+ __le32 header;
+ u8 value[];
+} __packed;
+
+#define HTT_TLV_TAG GENMASK(11, 0)
+#define HTT_TLV_LEN GENMASK(23, 12)
+
+enum HTT_PPDU_STATS_BW {
+ HTT_PPDU_STATS_BANDWIDTH_5MHZ = 0,
+ HTT_PPDU_STATS_BANDWIDTH_10MHZ = 1,
+ HTT_PPDU_STATS_BANDWIDTH_20MHZ = 2,
+ HTT_PPDU_STATS_BANDWIDTH_40MHZ = 3,
+ HTT_PPDU_STATS_BANDWIDTH_80MHZ = 4,
+ HTT_PPDU_STATS_BANDWIDTH_160MHZ = 5, /* includes 80+80 */
+ HTT_PPDU_STATS_BANDWIDTH_DYN = 6,
+};
+
+#define HTT_PPDU_STATS_CMN_FLAGS_FRAME_TYPE_M GENMASK(7, 0)
+#define HTT_PPDU_STATS_CMN_FLAGS_QUEUE_TYPE_M GENMASK(15, 8)
+/* bw - HTT_PPDU_STATS_BW */
+#define HTT_PPDU_STATS_CMN_FLAGS_BW_M GENMASK(19, 16)
+
+struct htt_ppdu_stats_common {
+ __le32 ppdu_id;
+ __le16 sched_cmdid;
+ u8 ring_id;
+ u8 num_users;
+ __le32 flags; /* %HTT_PPDU_STATS_COMMON_FLAGS_*/
+ __le32 chain_mask;
+ __le32 fes_duration_us; /* frame exchange sequence */
+ __le32 ppdu_sch_eval_start_tstmp_us;
+ __le32 ppdu_sch_end_tstmp_us;
+ __le32 ppdu_start_tstmp_us;
+ /* BIT [15 : 0] - phy mode (WLAN_PHY_MODE) with which ppdu was transmitted
+ * BIT [31 : 16] - bandwidth (in MHz) with which ppdu was transmitted
+ */
+ __le16 phy_mode;
+ __le16 bw_mhz;
+} __packed;
+
+enum htt_ppdu_stats_gi {
+ HTT_PPDU_STATS_SGI_0_8_US,
+ HTT_PPDU_STATS_SGI_0_4_US,
+ HTT_PPDU_STATS_SGI_1_6_US,
+ HTT_PPDU_STATS_SGI_3_2_US,
+};
+
+#define HTT_PPDU_STATS_USER_RATE_INFO0_USER_POS_M GENMASK(3, 0)
+#define HTT_PPDU_STATS_USER_RATE_INFO0_MU_GROUP_ID_M GENMASK(11, 4)
+
+enum HTT_PPDU_STATS_PPDU_TYPE {
+ HTT_PPDU_STATS_PPDU_TYPE_SU,
+ HTT_PPDU_STATS_PPDU_TYPE_MU_MIMO,
+ HTT_PPDU_STATS_PPDU_TYPE_MU_OFDMA,
+ HTT_PPDU_STATS_PPDU_TYPE_MU_MIMO_OFDMA,
+ HTT_PPDU_STATS_PPDU_TYPE_UL_TRIG,
+ HTT_PPDU_STATS_PPDU_TYPE_BURST_BCN,
+ HTT_PPDU_STATS_PPDU_TYPE_UL_BSR_RESP,
+ HTT_PPDU_STATS_PPDU_TYPE_UL_BSR_TRIG,
+ HTT_PPDU_STATS_PPDU_TYPE_UL_RESP,
+ HTT_PPDU_STATS_PPDU_TYPE_MAX
+};
+
+#define HTT_PPDU_STATS_USER_RATE_INFO1_RESP_TYPE_VALD_M BIT(0)
+#define HTT_PPDU_STATS_USER_RATE_INFO1_PPDU_TYPE_M GENMASK(5, 1)
+
+#define HTT_PPDU_STATS_USER_RATE_FLAGS_LTF_SIZE_M GENMASK(1, 0)
+#define HTT_PPDU_STATS_USER_RATE_FLAGS_STBC_M BIT(2)
+#define HTT_PPDU_STATS_USER_RATE_FLAGS_HE_RE_M BIT(3)
+#define HTT_PPDU_STATS_USER_RATE_FLAGS_TXBF_M GENMASK(7, 4)
+#define HTT_PPDU_STATS_USER_RATE_FLAGS_BW_M GENMASK(11, 8)
+#define HTT_PPDU_STATS_USER_RATE_FLAGS_NSS_M GENMASK(15, 12)
+#define HTT_PPDU_STATS_USER_RATE_FLAGS_MCS_M GENMASK(19, 16)
+#define HTT_PPDU_STATS_USER_RATE_FLAGS_PREAMBLE_M GENMASK(23, 20)
+#define HTT_PPDU_STATS_USER_RATE_FLAGS_GI_M GENMASK(27, 24)
+#define HTT_PPDU_STATS_USER_RATE_FLAGS_DCM_M BIT(28)
+#define HTT_PPDU_STATS_USER_RATE_FLAGS_LDPC_M BIT(29)
+
+#define HTT_USR_RATE_PPDU_TYPE(_val) \
+ le32_get_bits(_val, HTT_PPDU_STATS_USER_RATE_INFO1_PPDU_TYPE_M)
+#define HTT_USR_RATE_PREAMBLE(_val) \
+ le32_get_bits(_val, HTT_PPDU_STATS_USER_RATE_FLAGS_PREAMBLE_M)
+#define HTT_USR_RATE_BW(_val) \
+ le32_get_bits(_val, HTT_PPDU_STATS_USER_RATE_FLAGS_BW_M)
+#define HTT_USR_RATE_NSS(_val) \
+ le32_get_bits(_val, HTT_PPDU_STATS_USER_RATE_FLAGS_NSS_M)
+#define HTT_USR_RATE_MCS(_val) \
+ le32_get_bits(_val, HTT_PPDU_STATS_USER_RATE_FLAGS_MCS_M)
+#define HTT_USR_RATE_GI(_val) \
+ le32_get_bits(_val, HTT_PPDU_STATS_USER_RATE_FLAGS_GI_M)
+#define HTT_USR_RATE_DCM(_val) \
+ le32_get_bits(_val, HTT_PPDU_STATS_USER_RATE_FLAGS_DCM_M)
+
+#define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_LTF_SIZE_M GENMASK(1, 0)
+#define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_STBC_M BIT(2)
+#define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_HE_RE_M BIT(3)
+#define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_TXBF_M GENMASK(7, 4)
+#define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_BW_M GENMASK(11, 8)
+#define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_NSS_M GENMASK(15, 12)
+#define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_MCS_M GENMASK(19, 16)
+#define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_PREAMBLE_M GENMASK(23, 20)
+#define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_GI_M GENMASK(27, 24)
+#define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_DCM_M BIT(28)
+#define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_LDPC_M BIT(29)
+
+struct htt_ppdu_stats_user_rate {
+ u8 tid_num;
+ u8 reserved0;
+ __le16 sw_peer_id;
+ __le32 info0; /* %HTT_PPDU_STATS_USER_RATE_INFO0_*/
+ __le16 ru_end;
+ __le16 ru_start;
+ __le16 resp_ru_end;
+ __le16 resp_ru_start;
+ __le32 info1; /* %HTT_PPDU_STATS_USER_RATE_INFO1_ */
+ __le32 rate_flags; /* %HTT_PPDU_STATS_USER_RATE_FLAGS_ */
+ /* Note: resp_rate_info is only valid for if resp_type is UL */
+ __le32 resp_rate_flags; /* %HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_ */
+} __packed;
+
+#define HTT_PPDU_STATS_TX_INFO_FLAGS_RATECODE_M GENMASK(7, 0)
+#define HTT_PPDU_STATS_TX_INFO_FLAGS_IS_AMPDU_M BIT(8)
+#define HTT_PPDU_STATS_TX_INFO_FLAGS_BA_ACK_FAILED_M GENMASK(10, 9)
+#define HTT_PPDU_STATS_TX_INFO_FLAGS_BW_M GENMASK(13, 11)
+#define HTT_PPDU_STATS_TX_INFO_FLAGS_SGI_M BIT(14)
+#define HTT_PPDU_STATS_TX_INFO_FLAGS_PEERID_M GENMASK(31, 16)
+
+#define HTT_TX_INFO_IS_AMSDU(_flags) \
+ u32_get_bits(_flags, HTT_PPDU_STATS_TX_INFO_FLAGS_IS_AMPDU_M)
+#define HTT_TX_INFO_BA_ACK_FAILED(_flags) \
+ u32_get_bits(_flags, HTT_PPDU_STATS_TX_INFO_FLAGS_BA_ACK_FAILED_M)
+#define HTT_TX_INFO_RATECODE(_flags) \
+ u32_get_bits(_flags, HTT_PPDU_STATS_TX_INFO_FLAGS_RATECODE_M)
+#define HTT_TX_INFO_PEERID(_flags) \
+ u32_get_bits(_flags, HTT_PPDU_STATS_TX_INFO_FLAGS_PEERID_M)
+
+enum htt_ppdu_stats_usr_compln_status {
+ HTT_PPDU_STATS_USER_STATUS_OK,
+ HTT_PPDU_STATS_USER_STATUS_FILTERED,
+ HTT_PPDU_STATS_USER_STATUS_RESP_TIMEOUT,
+ HTT_PPDU_STATS_USER_STATUS_RESP_MISMATCH,
+ HTT_PPDU_STATS_USER_STATUS_ABORT,
+};
+
+#define HTT_PPDU_STATS_USR_CMPLTN_CMN_FLAGS_LONG_RETRY_M GENMASK(3, 0)
+#define HTT_PPDU_STATS_USR_CMPLTN_CMN_FLAGS_SHORT_RETRY_M GENMASK(7, 4)
+#define HTT_PPDU_STATS_USR_CMPLTN_CMN_FLAGS_IS_AMPDU_M BIT(8)
+#define HTT_PPDU_STATS_USR_CMPLTN_CMN_FLAGS_RESP_TYPE_M GENMASK(12, 9)
+
+#define HTT_USR_CMPLTN_IS_AMPDU(_val) \
+ le32_get_bits(_val, HTT_PPDU_STATS_USR_CMPLTN_CMN_FLAGS_IS_AMPDU_M)
+#define HTT_USR_CMPLTN_LONG_RETRY(_val) \
+ le32_get_bits(_val, HTT_PPDU_STATS_USR_CMPLTN_CMN_FLAGS_LONG_RETRY_M)
+#define HTT_USR_CMPLTN_SHORT_RETRY(_val) \
+ le32_get_bits(_val, HTT_PPDU_STATS_USR_CMPLTN_CMN_FLAGS_SHORT_RETRY_M)
+
+struct htt_ppdu_stats_usr_cmpltn_cmn {
+ u8 status;
+ u8 tid_num;
+ __le16 sw_peer_id;
+ /* RSSI value of last ack packet (units = dB above noise floor) */
+ __le32 ack_rssi;
+ __le16 mpdu_tried;
+ __le16 mpdu_success;
+ __le32 flags; /* %HTT_PPDU_STATS_USR_CMPLTN_CMN_FLAGS_LONG_RETRIES*/
+} __packed;
+
+#define HTT_PPDU_STATS_ACK_BA_INFO_NUM_MPDU_M GENMASK(8, 0)
+#define HTT_PPDU_STATS_ACK_BA_INFO_NUM_MSDU_M GENMASK(24, 9)
+#define HTT_PPDU_STATS_ACK_BA_INFO_TID_NUM GENMASK(31, 25)
+
+#define HTT_PPDU_STATS_NON_QOS_TID 16
+
+struct htt_ppdu_stats_usr_cmpltn_ack_ba_status {
+ __le32 ppdu_id;
+ __le16 sw_peer_id;
+ __le16 reserved0;
+ __le32 info; /* %HTT_PPDU_STATS_USR_CMPLTN_CMN_INFO_ */
+ __le16 current_seq;
+ __le16 start_seq;
+ __le32 success_bytes;
+} __packed;
+
+struct htt_ppdu_user_stats {
+ u16 peer_id;
+ u16 delay_ba;
+ u32 tlv_flags;
+ bool is_valid_peer_id;
+ struct htt_ppdu_stats_user_rate rate;
+ struct htt_ppdu_stats_usr_cmpltn_cmn cmpltn_cmn;
+ struct htt_ppdu_stats_usr_cmpltn_ack_ba_status ack_ba;
+};
+
+#define HTT_PPDU_STATS_MAX_USERS 8
+#define HTT_PPDU_DESC_MAX_DEPTH 16
+
+struct htt_ppdu_stats {
+ struct htt_ppdu_stats_common common;
+ struct htt_ppdu_user_stats user_stats[HTT_PPDU_STATS_MAX_USERS];
+};
+
+struct htt_ppdu_stats_info {
+ u32 tlv_bitmap;
+ u32 ppdu_id;
+ u32 frame_type;
+ u32 frame_ctrl;
+ u32 delay_ba;
+ u32 bar_num_users;
+ struct htt_ppdu_stats ppdu_stats;
+ struct list_head list;
+};
+
+/* @brief target -> host MLO offset indiciation message
+ *
+ * @details
+ * The following field definitions describe the format of the HTT target
+ * to host mlo offset indication message.
+ *
+ *
+ * |31 29|28 |26|25 22|21 16|15 13|12 10 |9 8|7 0|
+ * |---------------------------------------------------------------------|
+ * | rsvd1 | mac_freq |chip_id |pdev_id|msgtype|
+ * |---------------------------------------------------------------------|
+ * | sync_timestamp_lo_us |
+ * |---------------------------------------------------------------------|
+ * | sync_timestamp_hi_us |
+ * |---------------------------------------------------------------------|
+ * | mlo_offset_lo |
+ * |---------------------------------------------------------------------|
+ * | mlo_offset_hi |
+ * |---------------------------------------------------------------------|
+ * | mlo_offset_clcks |
+ * |---------------------------------------------------------------------|
+ * | rsvd2 | mlo_comp_clks |mlo_comp_us |
+ * |---------------------------------------------------------------------|
+ * | rsvd3 |mlo_comp_timer |
+ * |---------------------------------------------------------------------|
+ * Header fields
+ * - MSG_TYPE
+ * Bits 7:0
+ * Purpose: Identifies this is a MLO offset indication msg
+ * - PDEV_ID
+ * Bits 9:8
+ * Purpose: Pdev of this MLO offset
+ * - CHIP_ID
+ * Bits 12:10
+ * Purpose: chip_id of this MLO offset
+ * - MAC_FREQ
+ * Bits 28:13
+ * - SYNC_TIMESTAMP_LO_US
+ * Purpose: clock frequency of the mac HW block in MHz
+ * Bits: 31:0
+ * Purpose: lower 32 bits of the WLAN global time stamp at which
+ * last sync interrupt was received
+ * - SYNC_TIMESTAMP_HI_US
+ * Bits: 31:0
+ * Purpose: upper 32 bits of WLAN global time stamp at which
+ * last sync interrupt was received
+ * - MLO_OFFSET_LO
+ * Bits: 31:0
+ * Purpose: lower 32 bits of the MLO offset in us
+ * - MLO_OFFSET_HI
+ * Bits: 31:0
+ * Purpose: upper 32 bits of the MLO offset in us
+ * - MLO_COMP_US
+ * Bits: 15:0
+ * Purpose: MLO time stamp compensation applied in us
+ * - MLO_COMP_CLCKS
+ * Bits: 25:16
+ * Purpose: MLO time stamp compensation applied in clock ticks
+ * - MLO_COMP_TIMER
+ * Bits: 21:0
+ * Purpose: Periodic timer at which compensation is applied
+ */
+
+#define HTT_T2H_MLO_OFFSET_INFO_MSG_TYPE GENMASK(7, 0)
+#define HTT_T2H_MLO_OFFSET_INFO_PDEV_ID GENMASK(9, 8)
+
+struct ath12k_htt_mlo_offset_msg {
+ __le32 info;
+ __le32 sync_timestamp_lo_us;
+ __le32 sync_timestamp_hi_us;
+ __le32 mlo_offset_hi;
+ __le32 mlo_offset_lo;
+ __le32 mlo_offset_clks;
+ __le32 mlo_comp_clks;
+ __le32 mlo_comp_timer;
+} __packed;
+
+/* @brief host -> target FW extended statistics retrieve
+ *
+ * @details
+ * The following field definitions describe the format of the HTT host
+ * to target FW extended stats retrieve message.
+ * The message specifies the type of stats the host wants to retrieve.
+ *
+ * |31 24|23 16|15 8|7 0|
+ * |-----------------------------------------------------------|
+ * | reserved | stats type | pdev_mask | msg type |
+ * |-----------------------------------------------------------|
+ * | config param [0] |
+ * |-----------------------------------------------------------|
+ * | config param [1] |
+ * |-----------------------------------------------------------|
+ * | config param [2] |
+ * |-----------------------------------------------------------|
+ * | config param [3] |
+ * |-----------------------------------------------------------|
+ * | reserved |
+ * |-----------------------------------------------------------|
+ * | cookie LSBs |
+ * |-----------------------------------------------------------|
+ * | cookie MSBs |
+ * |-----------------------------------------------------------|
+ * Header fields:
+ * - MSG_TYPE
+ * Bits 7:0
+ * Purpose: identifies this is a extended stats upload request message
+ * Value: 0x10
+ * - PDEV_MASK
+ * Bits 8:15
+ * Purpose: identifies the mask of PDEVs to retrieve stats from
+ * Value: This is a overloaded field, refer to usage and interpretation of
+ * PDEV in interface document.
+ * Bit 8 : Reserved for SOC stats
+ * Bit 9 - 15 : Indicates PDEV_MASK in DBDC
+ * Indicates MACID_MASK in DBS
+ * - STATS_TYPE
+ * Bits 23:16
+ * Purpose: identifies which FW statistics to upload
+ * Value: Defined by htt_dbg_ext_stats_type (see htt_stats.h)
+ * - Reserved
+ * Bits 31:24
+ * - CONFIG_PARAM [0]
+ * Bits 31:0
+ * Purpose: give an opaque configuration value to the specified stats type
+ * Value: stats-type specific configuration value
+ * Refer to htt_stats.h for interpretation for each stats sub_type
+ * - CONFIG_PARAM [1]
+ * Bits 31:0
+ * Purpose: give an opaque configuration value to the specified stats type
+ * Value: stats-type specific configuration value
+ * Refer to htt_stats.h for interpretation for each stats sub_type
+ * - CONFIG_PARAM [2]
+ * Bits 31:0
+ * Purpose: give an opaque configuration value to the specified stats type
+ * Value: stats-type specific configuration value
+ * Refer to htt_stats.h for interpretation for each stats sub_type
+ * - CONFIG_PARAM [3]
+ * Bits 31:0
+ * Purpose: give an opaque configuration value to the specified stats type
+ * Value: stats-type specific configuration value
+ * Refer to htt_stats.h for interpretation for each stats sub_type
+ * - Reserved [31:0] for future use.
+ * - COOKIE_LSBS
+ * Bits 31:0
+ * Purpose: Provide a mechanism to match a target->host stats confirmation
+ * message with its preceding host->target stats request message.
+ * Value: LSBs of the opaque cookie specified by the host-side requestor
+ * - COOKIE_MSBS
+ * Bits 31:0
+ * Purpose: Provide a mechanism to match a target->host stats confirmation
+ * message with its preceding host->target stats request message.
+ * Value: MSBs of the opaque cookie specified by the host-side requestor
+ */
+
+struct htt_ext_stats_cfg_hdr {
+ u8 msg_type;
+ u8 pdev_mask;
+ u8 stats_type;
+ u8 reserved;
+} __packed;
+
+struct htt_ext_stats_cfg_cmd {
+ struct htt_ext_stats_cfg_hdr hdr;
+ __le32 cfg_param0;
+ __le32 cfg_param1;
+ __le32 cfg_param2;
+ __le32 cfg_param3;
+ __le32 reserved;
+ __le32 cookie_lsb;
+ __le32 cookie_msb;
+} __packed;
+
+/* htt stats config default params */
+#define HTT_STAT_DEFAULT_RESET_START_OFFSET 0
+#define HTT_STAT_DEFAULT_CFG0_ALL_HWQS 0xffffffff
+#define HTT_STAT_DEFAULT_CFG0_ALL_TXQS 0xffffffff
+#define HTT_STAT_DEFAULT_CFG0_ALL_CMDQS 0xffff
+#define HTT_STAT_DEFAULT_CFG0_ALL_RINGS 0xffff
+#define HTT_STAT_DEFAULT_CFG0_ACTIVE_PEERS 0xff
+#define HTT_STAT_DEFAULT_CFG0_CCA_CUMULATIVE 0x00
+#define HTT_STAT_DEFAULT_CFG0_ACTIVE_VDEVS 0x00
+
+/* HTT_DBG_EXT_STATS_PEER_INFO
+ * PARAMS:
+ * @config_param0:
+ * [Bit0] - [0] for sw_peer_id, [1] for mac_addr based request
+ * [Bit15 : Bit 1] htt_peer_stats_req_mode_t
+ * [Bit31 : Bit16] sw_peer_id
+ * @config_param1:
+ * peer_stats_req_type_mask:32 (enum htt_peer_stats_tlv_enum)
+ * 0 bit htt_peer_stats_cmn_tlv
+ * 1 bit htt_peer_details_tlv
+ * 2 bit htt_tx_peer_rate_stats_tlv
+ * 3 bit htt_rx_peer_rate_stats_tlv
+ * 4 bit htt_tx_tid_stats_tlv/htt_tx_tid_stats_v1_tlv
+ * 5 bit htt_rx_tid_stats_tlv
+ * 6 bit htt_msdu_flow_stats_tlv
+ * @config_param2: [Bit31 : Bit0] mac_addr31to0
+ * @config_param3: [Bit15 : Bit0] mac_addr47to32
+ * [Bit31 : Bit16] reserved
+ */
+#define HTT_STAT_PEER_INFO_MAC_ADDR BIT(0)
+#define HTT_STAT_DEFAULT_PEER_REQ_TYPE 0x7f
+
+/* Used to set different configs to the specified stats type.*/
+struct htt_ext_stats_cfg_params {
+ u32 cfg0;
+ u32 cfg1;
+ u32 cfg2;
+ u32 cfg3;
+};
+
+enum vdev_stats_offload_timer_duration {
+ ATH12K_STATS_TIMER_DUR_500MS = 1,
+ ATH12K_STATS_TIMER_DUR_1SEC = 2,
+ ATH12K_STATS_TIMER_DUR_2SEC = 3,
+};
+
+#define ATH12K_HTT_MAC_ADDR_L32_0 GENMASK(7, 0)
+#define ATH12K_HTT_MAC_ADDR_L32_1 GENMASK(15, 8)
+#define ATH12K_HTT_MAC_ADDR_L32_2 GENMASK(23, 16)
+#define ATH12K_HTT_MAC_ADDR_L32_3 GENMASK(31, 24)
+#define ATH12K_HTT_MAC_ADDR_H16_0 GENMASK(7, 0)
+#define ATH12K_HTT_MAC_ADDR_H16_1 GENMASK(15, 8)
+
+struct htt_mac_addr {
+ __le32 mac_addr_l32;
+ __le32 mac_addr_h16;
+} __packed;
+
+int ath12k_dp_htt_connect(struct ath12k_dp *dp);
+int ath12k_dp_tx_htt_srng_setup(struct ath12k_base *ab, u32 ring_id,
+ int mac_id, enum hal_ring_type ring_type);
+
+void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab,
+ struct sk_buff *skb);
+int ath12k_dp_htt_tlv_iter(struct ath12k_base *ab, const void *ptr, size_t len,
+ int (*iter)(struct ath12k_base *ar, u16 tag, u16 len,
+ const void *ptr, void *data),
+ void *data);
+int ath12k_dp_tx_htt_h2t_ver_req_msg(struct ath12k_base *ab);
+int ath12k_dp_tx_htt_h2t_ppdu_stats_req(struct ath12k *ar, u32 mask);
+int
+ath12k_dp_tx_htt_h2t_ext_stats_req(struct ath12k *ar, u8 type,
+ struct htt_ext_stats_cfg_params *cfg_params,
+ u64 cookie);
+int ath12k_dp_tx_htt_rx_monitor_mode_ring_config(struct ath12k *ar, bool reset);
+
+int ath12k_dp_tx_htt_rx_filter_setup(struct ath12k_base *ab, u32 ring_id,
+ int mac_id, enum hal_ring_type ring_type,
+ int rx_buf_size,
+ struct htt_rx_ring_tlv_filter *tlv_filter);
+int ath12k_dp_tx_htt_tx_filter_setup(struct ath12k_base *ab, u32 ring_id,
+ int mac_id, enum hal_ring_type ring_type,
+ int tx_buf_size,
+ struct htt_tx_ring_tlv_filter *htt_tlv_filter);
+int ath12k_dp_tx_htt_monitor_mode_ring_config(struct ath12k *ar, bool reset);
+#endif
diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c
index 39d1967584db..737287a9aa46 100644
--- a/drivers/net/wireless/ath/ath12k/dp_mon.c
+++ b/drivers/net/wireless/ath/ath12k/dp_mon.c
@@ -6,1756 +6,11 @@
#include "dp_mon.h"
#include "debug.h"
-#include "dp_rx.h"
#include "dp_tx.h"
#include "peer.h"
-#define ATH12K_LE32_DEC_ENC(value, dec_bits, enc_bits) \
- u32_encode_bits(le32_get_bits(value, dec_bits), enc_bits)
-
-#define ATH12K_LE64_DEC_ENC(value, dec_bits, enc_bits) \
- u32_encode_bits(le64_get_bits(value, dec_bits), enc_bits)
-
-static void
-ath12k_dp_mon_rx_handle_ofdma_info(const struct hal_rx_ppdu_end_user_stats *ppdu_end_user,
- struct hal_rx_user_status *rx_user_status)
-{
- rx_user_status->ul_ofdma_user_v0_word0 =
- __le32_to_cpu(ppdu_end_user->usr_resp_ref);
- rx_user_status->ul_ofdma_user_v0_word1 =
- __le32_to_cpu(ppdu_end_user->usr_resp_ref_ext);
-}
-
-static void
-ath12k_dp_mon_rx_populate_byte_count(const struct hal_rx_ppdu_end_user_stats *stats,
- void *ppduinfo,
- struct hal_rx_user_status *rx_user_status)
-{
- rx_user_status->mpdu_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 =
- le32_get_bits(stats->info8,
- HAL_RX_PPDU_END_USER_STATS_INFO8_MPDU_ERR_BYTE_COUNT);
-}
-
-static void
-ath12k_dp_mon_rx_populate_mu_user_info(const struct hal_rx_ppdu_end_user_stats *rx_tlv,
- struct hal_rx_mon_ppdu_info *ppdu_info,
- struct hal_rx_user_status *rx_user_status)
-{
- rx_user_status->ast_index = ppdu_info->ast_index;
- rx_user_status->tid = ppdu_info->tid;
- rx_user_status->tcp_ack_msdu_count =
- ppdu_info->tcp_ack_msdu_count;
- rx_user_status->tcp_msdu_count =
- ppdu_info->tcp_msdu_count;
- rx_user_status->udp_msdu_count =
- ppdu_info->udp_msdu_count;
- rx_user_status->other_msdu_count =
- ppdu_info->other_msdu_count;
- rx_user_status->frame_control = ppdu_info->frame_control;
- rx_user_status->frame_control_info_valid =
- ppdu_info->frame_control_info_valid;
- rx_user_status->data_sequence_control_info_valid =
- ppdu_info->data_sequence_control_info_valid;
- rx_user_status->first_data_seq_ctrl =
- ppdu_info->first_data_seq_ctrl;
- rx_user_status->preamble_type = ppdu_info->preamble_type;
- rx_user_status->ht_flags = ppdu_info->ht_flags;
- rx_user_status->vht_flags = ppdu_info->vht_flags;
- rx_user_status->he_flags = ppdu_info->he_flags;
- rx_user_status->rs_flags = ppdu_info->rs_flags;
-
- rx_user_status->mpdu_cnt_fcs_ok =
- ppdu_info->num_mpdu_fcs_ok;
- rx_user_status->mpdu_cnt_fcs_err =
- ppdu_info->num_mpdu_fcs_err;
- memcpy(&rx_user_status->mpdu_fcs_ok_bitmap[0], &ppdu_info->mpdu_fcs_ok_bitmap[0],
- HAL_RX_NUM_WORDS_PER_PPDU_BITMAP *
- sizeof(ppdu_info->mpdu_fcs_ok_bitmap[0]));
-
- ath12k_dp_mon_rx_populate_byte_count(rx_tlv, ppdu_info, rx_user_status);
-}
-
-static void ath12k_dp_mon_parse_vht_sig_a(const struct hal_rx_vht_sig_a_info *vht_sig,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- u32 nsts, info0, info1;
- u8 gi_setting;
-
- info0 = __le32_to_cpu(vht_sig->info0);
- info1 = __le32_to_cpu(vht_sig->info1);
-
- ppdu_info->ldpc = u32_get_bits(info1, HAL_RX_VHT_SIG_A_INFO_INFO1_SU_MU_CODING);
- ppdu_info->mcs = u32_get_bits(info1, HAL_RX_VHT_SIG_A_INFO_INFO1_MCS);
- gi_setting = u32_get_bits(info1, HAL_RX_VHT_SIG_A_INFO_INFO1_GI_SETTING);
- switch (gi_setting) {
- case HAL_RX_VHT_SIG_A_NORMAL_GI:
- ppdu_info->gi = HAL_RX_GI_0_8_US;
- break;
- case HAL_RX_VHT_SIG_A_SHORT_GI:
- case HAL_RX_VHT_SIG_A_SHORT_GI_AMBIGUITY:
- ppdu_info->gi = HAL_RX_GI_0_4_US;
- break;
- }
-
- ppdu_info->is_stbc = u32_get_bits(info0, HAL_RX_VHT_SIG_A_INFO_INFO0_STBC);
- nsts = u32_get_bits(info0, HAL_RX_VHT_SIG_A_INFO_INFO0_NSTS);
- if (ppdu_info->is_stbc && nsts > 0)
- nsts = ((nsts + 1) >> 1) - 1;
-
- ppdu_info->nss = u32_get_bits(nsts, VHT_SIG_SU_NSS_MASK) + 1;
- ppdu_info->bw = u32_get_bits(info0, HAL_RX_VHT_SIG_A_INFO_INFO0_BW);
- ppdu_info->beamformed = u32_get_bits(info1,
- HAL_RX_VHT_SIG_A_INFO_INFO1_BEAMFORMED);
- ppdu_info->vht_flag_values5 = u32_get_bits(info0,
- HAL_RX_VHT_SIG_A_INFO_INFO0_GROUP_ID);
- ppdu_info->vht_flag_values3[0] = (((ppdu_info->mcs) << 4) |
- ppdu_info->nss);
- ppdu_info->vht_flag_values2 = ppdu_info->bw;
- ppdu_info->vht_flag_values4 =
- u32_get_bits(info1, HAL_RX_VHT_SIG_A_INFO_INFO1_SU_MU_CODING);
-}
-
-static void ath12k_dp_mon_parse_ht_sig(const struct hal_rx_ht_sig_info *ht_sig,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- u32 info0 = __le32_to_cpu(ht_sig->info0);
- u32 info1 = __le32_to_cpu(ht_sig->info1);
-
- ppdu_info->mcs = u32_get_bits(info0, HAL_RX_HT_SIG_INFO_INFO0_MCS);
- ppdu_info->bw = u32_get_bits(info0, HAL_RX_HT_SIG_INFO_INFO0_BW);
- ppdu_info->is_stbc = u32_get_bits(info1, HAL_RX_HT_SIG_INFO_INFO1_STBC);
- ppdu_info->ldpc = u32_get_bits(info1, HAL_RX_HT_SIG_INFO_INFO1_FEC_CODING);
- ppdu_info->gi = u32_get_bits(info1, HAL_RX_HT_SIG_INFO_INFO1_GI);
- ppdu_info->nss = (ppdu_info->mcs >> 3) + 1;
-}
-
-static void ath12k_dp_mon_parse_l_sig_b(const struct hal_rx_lsig_b_info *lsigb,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- u32 info0 = __le32_to_cpu(lsigb->info0);
- u8 rate;
-
- rate = u32_get_bits(info0, HAL_RX_LSIG_B_INFO_INFO0_RATE);
- switch (rate) {
- case 1:
- rate = HAL_RX_LEGACY_RATE_1_MBPS;
- break;
- case 2:
- case 5:
- rate = HAL_RX_LEGACY_RATE_2_MBPS;
- break;
- case 3:
- case 6:
- rate = HAL_RX_LEGACY_RATE_5_5_MBPS;
- break;
- case 4:
- case 7:
- rate = HAL_RX_LEGACY_RATE_11_MBPS;
- break;
- default:
- rate = HAL_RX_LEGACY_RATE_INVALID;
- }
-
- ppdu_info->rate = rate;
- ppdu_info->cck_flag = 1;
-}
-
-static void ath12k_dp_mon_parse_l_sig_a(const struct hal_rx_lsig_a_info *lsiga,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- u32 info0 = __le32_to_cpu(lsiga->info0);
- u8 rate;
-
- rate = u32_get_bits(info0, HAL_RX_LSIG_A_INFO_INFO0_RATE);
- switch (rate) {
- case 8:
- rate = HAL_RX_LEGACY_RATE_48_MBPS;
- break;
- case 9:
- rate = HAL_RX_LEGACY_RATE_24_MBPS;
- break;
- case 10:
- rate = HAL_RX_LEGACY_RATE_12_MBPS;
- break;
- case 11:
- rate = HAL_RX_LEGACY_RATE_6_MBPS;
- break;
- case 12:
- rate = HAL_RX_LEGACY_RATE_54_MBPS;
- break;
- case 13:
- rate = HAL_RX_LEGACY_RATE_36_MBPS;
- break;
- case 14:
- rate = HAL_RX_LEGACY_RATE_18_MBPS;
- break;
- case 15:
- rate = HAL_RX_LEGACY_RATE_9_MBPS;
- break;
- default:
- rate = HAL_RX_LEGACY_RATE_INVALID;
- }
-
- ppdu_info->rate = rate;
-}
-
static void
-ath12k_dp_mon_parse_he_sig_b2_ofdma(const struct hal_rx_he_sig_b2_ofdma_info *ofdma,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- u32 info0, value;
-
- info0 = __le32_to_cpu(ofdma->info0);
-
- ppdu_info->he_data1 |= HE_MCS_KNOWN | HE_DCM_KNOWN | HE_CODING_KNOWN;
-
- /* HE-data2 */
- ppdu_info->he_data2 |= HE_TXBF_KNOWN;
-
- ppdu_info->mcs = u32_get_bits(info0, HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_MCS);
- value = ppdu_info->mcs << HE_TRANSMIT_MCS_SHIFT;
- ppdu_info->he_data3 |= value;
-
- value = u32_get_bits(info0, HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_DCM);
- value = value << HE_DCM_SHIFT;
- ppdu_info->he_data3 |= value;
-
- value = u32_get_bits(info0, HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_CODING);
- ppdu_info->ldpc = value;
- value = value << HE_CODING_SHIFT;
- ppdu_info->he_data3 |= value;
-
- /* HE-data4 */
- value = u32_get_bits(info0, HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_ID);
- value = value << HE_STA_ID_SHIFT;
- ppdu_info->he_data4 |= value;
-
- ppdu_info->nss =
- u32_get_bits(info0,
- HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_NSTS) + 1;
- ppdu_info->beamformed = u32_get_bits(info0,
- HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_TXBF);
-}
-
-static void
-ath12k_dp_mon_parse_he_sig_b2_mu(const struct hal_rx_he_sig_b2_mu_info *he_sig_b2_mu,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- u32 info0, value;
-
- info0 = __le32_to_cpu(he_sig_b2_mu->info0);
-
- ppdu_info->he_data1 |= HE_MCS_KNOWN | HE_CODING_KNOWN;
-
- ppdu_info->mcs = u32_get_bits(info0, HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_MCS);
- value = ppdu_info->mcs << HE_TRANSMIT_MCS_SHIFT;
- ppdu_info->he_data3 |= value;
-
- value = u32_get_bits(info0, HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_CODING);
- ppdu_info->ldpc = value;
- value = value << HE_CODING_SHIFT;
- ppdu_info->he_data3 |= value;
-
- value = u32_get_bits(info0, HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_ID);
- value = value << HE_STA_ID_SHIFT;
- ppdu_info->he_data4 |= value;
-
- ppdu_info->nss =
- u32_get_bits(info0,
- HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_NSTS) + 1;
-}
-
-static void
-ath12k_dp_mon_parse_he_sig_b1_mu(const struct hal_rx_he_sig_b1_mu_info *he_sig_b1_mu,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- u32 info0 = __le32_to_cpu(he_sig_b1_mu->info0);
- u16 ru_tones;
-
- ru_tones = u32_get_bits(info0,
- HAL_RX_HE_SIG_B1_MU_INFO_INFO0_RU_ALLOCATION);
- ppdu_info->ru_alloc = ath12k_he_ru_tones_to_nl80211_he_ru_alloc(ru_tones);
- ppdu_info->he_RU[0] = ru_tones;
-}
-
-static void
-ath12k_dp_mon_parse_he_sig_mu(const struct hal_rx_he_sig_a_mu_dl_info *he_sig_a_mu_dl,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- u32 info0, info1, value;
- u16 he_gi = 0, he_ltf = 0;
-
- info0 = __le32_to_cpu(he_sig_a_mu_dl->info0);
- info1 = __le32_to_cpu(he_sig_a_mu_dl->info1);
-
- ppdu_info->he_mu_flags = 1;
-
- ppdu_info->he_data1 = HE_MU_FORMAT_TYPE;
- ppdu_info->he_data1 |=
- HE_BSS_COLOR_KNOWN |
- HE_DL_UL_KNOWN |
- HE_LDPC_EXTRA_SYMBOL_KNOWN |
- HE_STBC_KNOWN |
- HE_DATA_BW_RU_KNOWN |
- HE_DOPPLER_KNOWN;
-
- ppdu_info->he_data2 =
- HE_GI_KNOWN |
- HE_LTF_SYMBOLS_KNOWN |
- HE_PRE_FEC_PADDING_KNOWN |
- HE_PE_DISAMBIGUITY_KNOWN |
- HE_TXOP_KNOWN |
- HE_MIDABLE_PERIODICITY_KNOWN;
-
- /* data3 */
- ppdu_info->he_data3 = u32_get_bits(info0, HAL_RX_HE_SIG_A_MU_DL_INFO0_BSS_COLOR);
- value = u32_get_bits(info0, HAL_RX_HE_SIG_A_MU_DL_INFO0_UL_FLAG);
- value = value << HE_DL_UL_SHIFT;
- ppdu_info->he_data3 |= value;
-
- value = u32_get_bits(info1, HAL_RX_HE_SIG_A_MU_DL_INFO1_LDPC_EXTRA);
- value = value << HE_LDPC_EXTRA_SYMBOL_SHIFT;
- ppdu_info->he_data3 |= value;
-
- value = u32_get_bits(info1, HAL_RX_HE_SIG_A_MU_DL_INFO1_STBC);
- value = value << HE_STBC_SHIFT;
- ppdu_info->he_data3 |= value;
-
- /* data4 */
- ppdu_info->he_data4 = u32_get_bits(info0,
- HAL_RX_HE_SIG_A_MU_DL_INFO0_SPATIAL_REUSE);
- ppdu_info->he_data4 = value;
-
- /* data5 */
- value = u32_get_bits(info0, HAL_RX_HE_SIG_A_MU_DL_INFO0_TRANSMIT_BW);
- ppdu_info->he_data5 = value;
- ppdu_info->bw = value;
-
- value = u32_get_bits(info0, HAL_RX_HE_SIG_A_MU_DL_INFO0_CP_LTF_SIZE);
- switch (value) {
- case 0:
- he_gi = HE_GI_0_8;
- he_ltf = HE_LTF_4_X;
- break;
- case 1:
- he_gi = HE_GI_0_8;
- he_ltf = HE_LTF_2_X;
- break;
- case 2:
- he_gi = HE_GI_1_6;
- he_ltf = HE_LTF_2_X;
- break;
- case 3:
- he_gi = HE_GI_3_2;
- he_ltf = HE_LTF_4_X;
- break;
- }
-
- ppdu_info->gi = he_gi;
- value = he_gi << HE_GI_SHIFT;
- ppdu_info->he_data5 |= value;
-
- value = he_ltf << HE_LTF_SIZE_SHIFT;
- ppdu_info->he_data5 |= value;
-
- value = u32_get_bits(info1, HAL_RX_HE_SIG_A_MU_DL_INFO1_NUM_LTF_SYMB);
- value = (value << HE_LTF_SYM_SHIFT);
- ppdu_info->he_data5 |= value;
-
- value = u32_get_bits(info1, HAL_RX_HE_SIG_A_MU_DL_INFO1_PKT_EXT_FACTOR);
- value = value << HE_PRE_FEC_PAD_SHIFT;
- ppdu_info->he_data5 |= value;
-
- value = u32_get_bits(info1, HAL_RX_HE_SIG_A_MU_DL_INFO1_PKT_EXT_PE_DISAM);
- value = value << HE_PE_DISAMBIGUITY_SHIFT;
- ppdu_info->he_data5 |= value;
-
- /*data6*/
- value = u32_get_bits(info0, HAL_RX_HE_SIG_A_MU_DL_INFO0_DOPPLER_INDICATION);
- value = value << HE_DOPPLER_SHIFT;
- ppdu_info->he_data6 |= value;
-
- value = u32_get_bits(info1, HAL_RX_HE_SIG_A_MU_DL_INFO1_TXOP_DURATION);
- value = value << HE_TXOP_SHIFT;
- ppdu_info->he_data6 |= value;
-
- /* HE-MU Flags */
- /* HE-MU-flags1 */
- ppdu_info->he_flags1 =
- HE_SIG_B_MCS_KNOWN |
- HE_SIG_B_DCM_KNOWN |
- HE_SIG_B_COMPRESSION_FLAG_1_KNOWN |
- HE_SIG_B_SYM_NUM_KNOWN |
- HE_RU_0_KNOWN;
-
- value = u32_get_bits(info0, HAL_RX_HE_SIG_A_MU_DL_INFO0_MCS_OF_SIGB);
- ppdu_info->he_flags1 |= value;
- value = u32_get_bits(info0, HAL_RX_HE_SIG_A_MU_DL_INFO0_DCM_OF_SIGB);
- value = value << HE_DCM_FLAG_1_SHIFT;
- ppdu_info->he_flags1 |= value;
-
- /* HE-MU-flags2 */
- ppdu_info->he_flags2 = HE_BW_KNOWN;
-
- value = u32_get_bits(info0, HAL_RX_HE_SIG_A_MU_DL_INFO0_TRANSMIT_BW);
- ppdu_info->he_flags2 |= value;
- value = u32_get_bits(info0, HAL_RX_HE_SIG_A_MU_DL_INFO0_COMP_MODE_SIGB);
- value = value << HE_SIG_B_COMPRESSION_FLAG_2_SHIFT;
- ppdu_info->he_flags2 |= value;
- value = u32_get_bits(info0, HAL_RX_HE_SIG_A_MU_DL_INFO0_NUM_SIGB_SYMB);
- value = value - 1;
- value = value << HE_NUM_SIG_B_SYMBOLS_SHIFT;
- ppdu_info->he_flags2 |= value;
-
- ppdu_info->is_stbc = info1 &
- HAL_RX_HE_SIG_A_MU_DL_INFO1_STBC;
-}
-
-static void ath12k_dp_mon_parse_he_sig_su(const struct hal_rx_he_sig_a_su_info *he_sig_a,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- u32 info0, info1, value;
- u32 dcm;
- u8 he_dcm = 0, he_stbc = 0;
- u16 he_gi = 0, he_ltf = 0;
-
- ppdu_info->he_flags = 1;
-
- info0 = __le32_to_cpu(he_sig_a->info0);
- info1 = __le32_to_cpu(he_sig_a->info1);
-
- value = u32_get_bits(info0, HAL_RX_HE_SIG_A_SU_INFO_INFO0_FORMAT_IND);
- if (value == 0)
- ppdu_info->he_data1 = HE_TRIG_FORMAT_TYPE;
- else
- ppdu_info->he_data1 = HE_SU_FORMAT_TYPE;
-
- ppdu_info->he_data1 |=
- HE_BSS_COLOR_KNOWN |
- HE_BEAM_CHANGE_KNOWN |
- HE_DL_UL_KNOWN |
- HE_MCS_KNOWN |
- HE_DCM_KNOWN |
- HE_CODING_KNOWN |
- HE_LDPC_EXTRA_SYMBOL_KNOWN |
- HE_STBC_KNOWN |
- HE_DATA_BW_RU_KNOWN |
- HE_DOPPLER_KNOWN;
-
- ppdu_info->he_data2 |=
- HE_GI_KNOWN |
- HE_TXBF_KNOWN |
- HE_PE_DISAMBIGUITY_KNOWN |
- HE_TXOP_KNOWN |
- HE_LTF_SYMBOLS_KNOWN |
- HE_PRE_FEC_PADDING_KNOWN |
- HE_MIDABLE_PERIODICITY_KNOWN;
-
- ppdu_info->he_data3 = u32_get_bits(info0,
- HAL_RX_HE_SIG_A_SU_INFO_INFO0_BSS_COLOR);
- value = u32_get_bits(info0, HAL_RX_HE_SIG_A_SU_INFO_INFO0_BEAM_CHANGE);
- value = value << HE_BEAM_CHANGE_SHIFT;
- ppdu_info->he_data3 |= value;
- value = u32_get_bits(info0, HAL_RX_HE_SIG_A_SU_INFO_INFO0_DL_UL_FLAG);
- value = value << HE_DL_UL_SHIFT;
- ppdu_info->he_data3 |= value;
-
- value = u32_get_bits(info0, HAL_RX_HE_SIG_A_SU_INFO_INFO0_TRANSMIT_MCS);
- ppdu_info->mcs = value;
- value = value << HE_TRANSMIT_MCS_SHIFT;
- ppdu_info->he_data3 |= value;
-
- value = u32_get_bits(info0, HAL_RX_HE_SIG_A_SU_INFO_INFO0_DCM);
- he_dcm = value;
- value = value << HE_DCM_SHIFT;
- ppdu_info->he_data3 |= value;
- value = u32_get_bits(info1, HAL_RX_HE_SIG_A_SU_INFO_INFO1_CODING);
- value = value << HE_CODING_SHIFT;
- ppdu_info->he_data3 |= value;
- value = u32_get_bits(info1, HAL_RX_HE_SIG_A_SU_INFO_INFO1_LDPC_EXTRA);
- value = value << HE_LDPC_EXTRA_SYMBOL_SHIFT;
- ppdu_info->he_data3 |= value;
- value = u32_get_bits(info1, HAL_RX_HE_SIG_A_SU_INFO_INFO1_STBC);
- he_stbc = value;
- value = value << HE_STBC_SHIFT;
- ppdu_info->he_data3 |= value;
-
- /* data4 */
- ppdu_info->he_data4 = u32_get_bits(info0,
- HAL_RX_HE_SIG_A_SU_INFO_INFO0_SPATIAL_REUSE);
-
- /* data5 */
- value = u32_get_bits(info0,
- HAL_RX_HE_SIG_A_SU_INFO_INFO0_TRANSMIT_BW);
- ppdu_info->he_data5 = value;
- ppdu_info->bw = value;
- value = u32_get_bits(info0, HAL_RX_HE_SIG_A_SU_INFO_INFO0_CP_LTF_SIZE);
- switch (value) {
- case 0:
- he_gi = HE_GI_0_8;
- he_ltf = HE_LTF_1_X;
- break;
- case 1:
- he_gi = HE_GI_0_8;
- he_ltf = HE_LTF_2_X;
- break;
- case 2:
- he_gi = HE_GI_1_6;
- he_ltf = HE_LTF_2_X;
- break;
- case 3:
- if (he_dcm && he_stbc) {
- he_gi = HE_GI_0_8;
- he_ltf = HE_LTF_4_X;
- } else {
- he_gi = HE_GI_3_2;
- he_ltf = HE_LTF_4_X;
- }
- break;
- }
- ppdu_info->gi = he_gi;
- value = he_gi << HE_GI_SHIFT;
- ppdu_info->he_data5 |= value;
- value = he_ltf << HE_LTF_SIZE_SHIFT;
- ppdu_info->ltf_size = he_ltf;
- ppdu_info->he_data5 |= value;
-
- value = u32_get_bits(info0, HAL_RX_HE_SIG_A_SU_INFO_INFO0_NSTS);
- value = (value << HE_LTF_SYM_SHIFT);
- ppdu_info->he_data5 |= value;
-
- value = u32_get_bits(info1, HAL_RX_HE_SIG_A_SU_INFO_INFO1_PKT_EXT_FACTOR);
- value = value << HE_PRE_FEC_PAD_SHIFT;
- ppdu_info->he_data5 |= value;
-
- value = u32_get_bits(info1, HAL_RX_HE_SIG_A_SU_INFO_INFO1_TXBF);
- value = value << HE_TXBF_SHIFT;
- ppdu_info->he_data5 |= value;
- value = u32_get_bits(info1, HAL_RX_HE_SIG_A_SU_INFO_INFO1_PKT_EXT_PE_DISAM);
- value = value << HE_PE_DISAMBIGUITY_SHIFT;
- ppdu_info->he_data5 |= value;
-
- /* data6 */
- value = u32_get_bits(info0, HAL_RX_HE_SIG_A_SU_INFO_INFO0_NSTS);
- value++;
- ppdu_info->he_data6 = value;
- value = u32_get_bits(info1, HAL_RX_HE_SIG_A_SU_INFO_INFO1_DOPPLER_IND);
- value = value << HE_DOPPLER_SHIFT;
- ppdu_info->he_data6 |= value;
- value = u32_get_bits(info1, HAL_RX_HE_SIG_A_SU_INFO_INFO1_TXOP_DURATION);
- value = value << HE_TXOP_SHIFT;
- ppdu_info->he_data6 |= value;
-
- ppdu_info->mcs =
- u32_get_bits(info0, HAL_RX_HE_SIG_A_SU_INFO_INFO0_TRANSMIT_MCS);
- ppdu_info->bw =
- u32_get_bits(info0, HAL_RX_HE_SIG_A_SU_INFO_INFO0_TRANSMIT_BW);
- ppdu_info->ldpc = u32_get_bits(info1, HAL_RX_HE_SIG_A_SU_INFO_INFO1_CODING);
- ppdu_info->is_stbc = u32_get_bits(info1, HAL_RX_HE_SIG_A_SU_INFO_INFO1_STBC);
- ppdu_info->beamformed = u32_get_bits(info1, HAL_RX_HE_SIG_A_SU_INFO_INFO1_TXBF);
- dcm = u32_get_bits(info0, HAL_RX_HE_SIG_A_SU_INFO_INFO0_DCM);
- ppdu_info->nss = u32_get_bits(info0,
- HAL_RX_HE_SIG_A_SU_INFO_INFO0_NSTS) + 1;
- ppdu_info->dcm = dcm;
-}
-
-static void
-ath12k_dp_mon_hal_rx_parse_u_sig_cmn(const struct hal_mon_usig_cmn *cmn,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- u32 common;
-
- ppdu_info->u_sig_info.bw = le32_get_bits(cmn->info0,
- HAL_RX_USIG_CMN_INFO0_BW);
- ppdu_info->u_sig_info.ul_dl = le32_get_bits(cmn->info0,
- HAL_RX_USIG_CMN_INFO0_UL_DL);
-
- common = __le32_to_cpu(ppdu_info->u_sig_info.usig.common);
- common |= IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER_KNOWN |
- IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_KNOWN |
- IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL_KNOWN |
- IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR_KNOWN |
- IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP_KNOWN |
- ATH12K_LE32_DEC_ENC(cmn->info0,
- HAL_RX_USIG_CMN_INFO0_PHY_VERSION,
- IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER) |
- u32_encode_bits(ppdu_info->u_sig_info.bw,
- IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW) |
- u32_encode_bits(ppdu_info->u_sig_info.ul_dl,
- IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL) |
- ATH12K_LE32_DEC_ENC(cmn->info0,
- HAL_RX_USIG_CMN_INFO0_BSS_COLOR,
- IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR) |
- ATH12K_LE32_DEC_ENC(cmn->info0,
- HAL_RX_USIG_CMN_INFO0_TXOP,
- IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP);
- ppdu_info->u_sig_info.usig.common = cpu_to_le32(common);
-
- switch (ppdu_info->u_sig_info.bw) {
- default:
- fallthrough;
- case HAL_EHT_BW_20:
- ppdu_info->bw = HAL_RX_BW_20MHZ;
- break;
- case HAL_EHT_BW_40:
- ppdu_info->bw = HAL_RX_BW_40MHZ;
- break;
- case HAL_EHT_BW_80:
- ppdu_info->bw = HAL_RX_BW_80MHZ;
- break;
- case HAL_EHT_BW_160:
- ppdu_info->bw = HAL_RX_BW_160MHZ;
- break;
- case HAL_EHT_BW_320_1:
- case HAL_EHT_BW_320_2:
- ppdu_info->bw = HAL_RX_BW_320MHZ;
- break;
- }
-}
-
-static void
-ath12k_dp_mon_hal_rx_parse_u_sig_tb(const struct hal_mon_usig_tb *usig_tb,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- struct ieee80211_radiotap_eht_usig *usig = &ppdu_info->u_sig_info.usig;
- enum ieee80211_radiotap_eht_usig_tb spatial_reuse1, spatial_reuse2;
- u32 common, value, mask;
-
- spatial_reuse1 = IEEE80211_RADIOTAP_EHT_USIG2_TB_B3_B6_SPATIAL_REUSE_1;
- spatial_reuse2 = IEEE80211_RADIOTAP_EHT_USIG2_TB_B7_B10_SPATIAL_REUSE_2;
-
- common = __le32_to_cpu(usig->common);
- value = __le32_to_cpu(usig->value);
- mask = __le32_to_cpu(usig->mask);
-
- ppdu_info->u_sig_info.ppdu_type_comp_mode =
- le32_get_bits(usig_tb->info0,
- HAL_RX_USIG_TB_INFO0_PPDU_TYPE_COMP_MODE);
-
- common |= ATH12K_LE32_DEC_ENC(usig_tb->info0,
- HAL_RX_USIG_TB_INFO0_RX_INTEG_CHECK_PASS,
- IEEE80211_RADIOTAP_EHT_USIG_COMMON_BAD_USIG_CRC);
-
- value |= IEEE80211_RADIOTAP_EHT_USIG1_TB_B20_B25_DISREGARD |
- u32_encode_bits(ppdu_info->u_sig_info.ppdu_type_comp_mode,
- IEEE80211_RADIOTAP_EHT_USIG2_TB_B0_B1_PPDU_TYPE) |
- IEEE80211_RADIOTAP_EHT_USIG2_TB_B2_VALIDATE |
- ATH12K_LE32_DEC_ENC(usig_tb->info0,
- HAL_RX_USIG_TB_INFO0_SPATIAL_REUSE_1,
- spatial_reuse1) |
- ATH12K_LE32_DEC_ENC(usig_tb->info0,
- HAL_RX_USIG_TB_INFO0_SPATIAL_REUSE_2,
- spatial_reuse2) |
- IEEE80211_RADIOTAP_EHT_USIG2_TB_B11_B15_DISREGARD |
- ATH12K_LE32_DEC_ENC(usig_tb->info0,
- HAL_RX_USIG_TB_INFO0_CRC,
- IEEE80211_RADIOTAP_EHT_USIG2_TB_B16_B19_CRC) |
- ATH12K_LE32_DEC_ENC(usig_tb->info0,
- HAL_RX_USIG_TB_INFO0_TAIL,
- IEEE80211_RADIOTAP_EHT_USIG2_TB_B20_B25_TAIL);
-
- mask |= IEEE80211_RADIOTAP_EHT_USIG1_TB_B20_B25_DISREGARD |
- IEEE80211_RADIOTAP_EHT_USIG2_TB_B0_B1_PPDU_TYPE |
- IEEE80211_RADIOTAP_EHT_USIG2_TB_B2_VALIDATE |
- spatial_reuse1 | spatial_reuse2 |
- IEEE80211_RADIOTAP_EHT_USIG2_TB_B11_B15_DISREGARD |
- IEEE80211_RADIOTAP_EHT_USIG2_TB_B16_B19_CRC |
- IEEE80211_RADIOTAP_EHT_USIG2_TB_B20_B25_TAIL;
-
- usig->common = cpu_to_le32(common);
- usig->value = cpu_to_le32(value);
- usig->mask = cpu_to_le32(mask);
-}
-
-static void
-ath12k_dp_mon_hal_rx_parse_u_sig_mu(const struct hal_mon_usig_mu *usig_mu,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- struct ieee80211_radiotap_eht_usig *usig = &ppdu_info->u_sig_info.usig;
- enum ieee80211_radiotap_eht_usig_mu sig_symb, punc;
- u32 common, value, mask;
-
- sig_symb = IEEE80211_RADIOTAP_EHT_USIG2_MU_B11_B15_EHT_SIG_SYMBOLS;
- punc = IEEE80211_RADIOTAP_EHT_USIG2_MU_B3_B7_PUNCTURED_INFO;
-
- common = __le32_to_cpu(usig->common);
- value = __le32_to_cpu(usig->value);
- mask = __le32_to_cpu(usig->mask);
-
- ppdu_info->u_sig_info.ppdu_type_comp_mode =
- le32_get_bits(usig_mu->info0,
- HAL_RX_USIG_MU_INFO0_PPDU_TYPE_COMP_MODE);
- ppdu_info->u_sig_info.eht_sig_mcs =
- le32_get_bits(usig_mu->info0,
- HAL_RX_USIG_MU_INFO0_EHT_SIG_MCS);
- ppdu_info->u_sig_info.num_eht_sig_sym =
- le32_get_bits(usig_mu->info0,
- HAL_RX_USIG_MU_INFO0_NUM_EHT_SIG_SYM);
-
- common |= ATH12K_LE32_DEC_ENC(usig_mu->info0,
- HAL_RX_USIG_MU_INFO0_RX_INTEG_CHECK_PASS,
- IEEE80211_RADIOTAP_EHT_USIG_COMMON_BAD_USIG_CRC);
-
- value |= IEEE80211_RADIOTAP_EHT_USIG1_MU_B20_B24_DISREGARD |
- IEEE80211_RADIOTAP_EHT_USIG1_MU_B25_VALIDATE |
- u32_encode_bits(ppdu_info->u_sig_info.ppdu_type_comp_mode,
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B0_B1_PPDU_TYPE) |
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B2_VALIDATE |
- ATH12K_LE32_DEC_ENC(usig_mu->info0,
- HAL_RX_USIG_MU_INFO0_PUNC_CH_INFO,
- punc) |
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B8_VALIDATE |
- u32_encode_bits(ppdu_info->u_sig_info.eht_sig_mcs,
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B9_B10_SIG_MCS) |
- u32_encode_bits(ppdu_info->u_sig_info.num_eht_sig_sym,
- sig_symb) |
- ATH12K_LE32_DEC_ENC(usig_mu->info0,
- HAL_RX_USIG_MU_INFO0_CRC,
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B16_B19_CRC) |
- ATH12K_LE32_DEC_ENC(usig_mu->info0,
- HAL_RX_USIG_MU_INFO0_TAIL,
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B20_B25_TAIL);
-
- mask |= IEEE80211_RADIOTAP_EHT_USIG1_MU_B20_B24_DISREGARD |
- IEEE80211_RADIOTAP_EHT_USIG1_MU_B25_VALIDATE |
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B0_B1_PPDU_TYPE |
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B2_VALIDATE |
- punc |
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B8_VALIDATE |
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B9_B10_SIG_MCS |
- sig_symb |
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B16_B19_CRC |
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B20_B25_TAIL;
-
- usig->common = cpu_to_le32(common);
- usig->value = cpu_to_le32(value);
- usig->mask = cpu_to_le32(mask);
-}
-
-static void
-ath12k_dp_mon_hal_rx_parse_u_sig_hdr(const struct hal_mon_usig_hdr *usig,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- u8 comp_mode;
-
- ppdu_info->eht_usig = true;
-
- ath12k_dp_mon_hal_rx_parse_u_sig_cmn(&usig->cmn, ppdu_info);
-
- comp_mode = le32_get_bits(usig->non_cmn.mu.info0,
- HAL_RX_USIG_MU_INFO0_PPDU_TYPE_COMP_MODE);
-
- if (comp_mode == 0 && ppdu_info->u_sig_info.ul_dl)
- ath12k_dp_mon_hal_rx_parse_u_sig_tb(&usig->non_cmn.tb, ppdu_info);
- else
- ath12k_dp_mon_hal_rx_parse_u_sig_mu(&usig->non_cmn.mu, ppdu_info);
-}
-
-static void
-ath12k_dp_mon_hal_aggr_tlv(struct hal_rx_mon_ppdu_info *ppdu_info,
- u16 tlv_len, const void *tlv_data)
-{
- if (tlv_len <= HAL_RX_MON_MAX_AGGR_SIZE - ppdu_info->tlv_aggr.cur_len) {
- memcpy(ppdu_info->tlv_aggr.buf + ppdu_info->tlv_aggr.cur_len,
- tlv_data, tlv_len);
- ppdu_info->tlv_aggr.cur_len += tlv_len;
- }
-}
-
-static inline bool
-ath12k_dp_mon_hal_rx_is_frame_type_ndp(const struct hal_rx_u_sig_info *usig_info)
-{
- if (usig_info->ppdu_type_comp_mode == 1 &&
- usig_info->eht_sig_mcs == 0 &&
- usig_info->num_eht_sig_sym == 0)
- return true;
-
- return false;
-}
-
-static inline bool
-ath12k_dp_mon_hal_rx_is_non_ofdma(const struct hal_rx_u_sig_info *usig_info)
-{
- u32 ppdu_type_comp_mode = usig_info->ppdu_type_comp_mode;
- u32 ul_dl = usig_info->ul_dl;
-
- if ((ppdu_type_comp_mode == HAL_RX_RECEPTION_TYPE_MU_MIMO && ul_dl == 0) ||
- (ppdu_type_comp_mode == HAL_RX_RECEPTION_TYPE_MU_OFDMA && ul_dl == 0) ||
- (ppdu_type_comp_mode == HAL_RX_RECEPTION_TYPE_MU_MIMO && ul_dl == 1))
- return true;
-
- return false;
-}
-
-static inline bool
-ath12k_dp_mon_hal_rx_is_ofdma(const struct hal_rx_u_sig_info *usig_info)
-{
- if (usig_info->ppdu_type_comp_mode == 0 && usig_info->ul_dl == 0)
- return true;
-
- return false;
-}
-
-static void
-ath12k_dp_mon_hal_rx_parse_eht_sig_ndp(const struct hal_eht_sig_ndp_cmn_eb *eht_sig_ndp,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- struct hal_rx_radiotap_eht *eht = &ppdu_info->eht_info.eht;
- u32 known, data;
-
- known = __le32_to_cpu(eht->known);
- known |= IEEE80211_RADIOTAP_EHT_KNOWN_SPATIAL_REUSE |
- IEEE80211_RADIOTAP_EHT_KNOWN_EHT_LTF |
- IEEE80211_RADIOTAP_EHT_KNOWN_NSS_S |
- IEEE80211_RADIOTAP_EHT_KNOWN_BEAMFORMED_S |
- IEEE80211_RADIOTAP_EHT_KNOWN_DISREGARD_S |
- IEEE80211_RADIOTAP_EHT_KNOWN_CRC1 |
- IEEE80211_RADIOTAP_EHT_KNOWN_TAIL1;
- eht->known = cpu_to_le32(known);
-
- data = __le32_to_cpu(eht->data[0]);
- data |= ATH12K_LE32_DEC_ENC(eht_sig_ndp->info0,
- HAL_RX_EHT_SIG_NDP_CMN_INFO0_SPATIAL_REUSE,
- IEEE80211_RADIOTAP_EHT_DATA0_SPATIAL_REUSE);
- /* GI and LTF size are separately indicated in radiotap header
- * and hence will be parsed from other TLV
- */
- data |= ATH12K_LE32_DEC_ENC(eht_sig_ndp->info0,
- HAL_RX_EHT_SIG_NDP_CMN_INFO0_NUM_LTF_SYM,
- IEEE80211_RADIOTAP_EHT_DATA0_EHT_LTF);
-
- data |= ATH12K_LE32_DEC_ENC(eht_sig_ndp->info0,
- HAL_RX_EHT_SIG_NDP_CMN_INFO0_CRC,
- IEEE80211_RADIOTAP_EHT_DATA0_CRC1_O);
-
- data |= ATH12K_LE32_DEC_ENC(eht_sig_ndp->info0,
- HAL_RX_EHT_SIG_NDP_CMN_INFO0_DISREGARD,
- IEEE80211_RADIOTAP_EHT_DATA0_DISREGARD_S);
- eht->data[0] = cpu_to_le32(data);
-
- data = __le32_to_cpu(eht->data[7]);
- data |= ATH12K_LE32_DEC_ENC(eht_sig_ndp->info0,
- HAL_RX_EHT_SIG_NDP_CMN_INFO0_NSS,
- IEEE80211_RADIOTAP_EHT_DATA7_NSS_S);
-
- data |= ATH12K_LE32_DEC_ENC(eht_sig_ndp->info0,
- HAL_RX_EHT_SIG_NDP_CMN_INFO0_BEAMFORMED,
- IEEE80211_RADIOTAP_EHT_DATA7_BEAMFORMED_S);
- eht->data[7] = cpu_to_le32(data);
-}
-
-static void
-ath12k_dp_mon_hal_rx_parse_usig_overflow(const struct hal_eht_sig_usig_overflow *ovflow,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- struct hal_rx_radiotap_eht *eht = &ppdu_info->eht_info.eht;
- u32 known, data;
-
- known = __le32_to_cpu(eht->known);
- known |= IEEE80211_RADIOTAP_EHT_KNOWN_SPATIAL_REUSE |
- IEEE80211_RADIOTAP_EHT_KNOWN_EHT_LTF |
- IEEE80211_RADIOTAP_EHT_KNOWN_LDPC_EXTRA_SYM_OM |
- IEEE80211_RADIOTAP_EHT_KNOWN_PRE_PADD_FACOR_OM |
- IEEE80211_RADIOTAP_EHT_KNOWN_PE_DISAMBIGUITY_OM |
- IEEE80211_RADIOTAP_EHT_KNOWN_DISREGARD_O;
- eht->known = cpu_to_le32(known);
-
- data = __le32_to_cpu(eht->data[0]);
- data |= ATH12K_LE32_DEC_ENC(ovflow->info0,
- HAL_RX_EHT_SIG_OVERFLOW_INFO0_SPATIAL_REUSE,
- IEEE80211_RADIOTAP_EHT_DATA0_SPATIAL_REUSE);
-
- /* GI and LTF size are separately indicated in radiotap header
- * and hence will be parsed from other TLV
- */
- data |= ATH12K_LE32_DEC_ENC(ovflow->info0,
- HAL_RX_EHT_SIG_OVERFLOW_INFO0_NUM_LTF_SYM,
- IEEE80211_RADIOTAP_EHT_DATA0_EHT_LTF);
-
- data |= ATH12K_LE32_DEC_ENC(ovflow->info0,
- HAL_RX_EHT_SIG_OVERFLOW_INFO0_LDPC_EXTA_SYM,
- IEEE80211_RADIOTAP_EHT_DATA0_LDPC_EXTRA_SYM_OM);
-
- data |= ATH12K_LE32_DEC_ENC(ovflow->info0,
- HAL_RX_EHT_SIG_OVERFLOW_INFO0_PRE_FEC_PAD_FACTOR,
- IEEE80211_RADIOTAP_EHT_DATA0_PRE_PADD_FACOR_OM);
-
- data |= ATH12K_LE32_DEC_ENC(ovflow->info0,
- HAL_RX_EHT_SIG_OVERFLOW_INFO0_DISAMBIGUITY,
- IEEE80211_RADIOTAP_EHT_DATA0_PE_DISAMBIGUITY_OM);
-
- data |= ATH12K_LE32_DEC_ENC(ovflow->info0,
- HAL_RX_EHT_SIG_OVERFLOW_INFO0_DISREGARD,
- IEEE80211_RADIOTAP_EHT_DATA0_DISREGARD_O);
- eht->data[0] = cpu_to_le32(data);
-}
-
-static void
-ath12k_dp_mon_hal_rx_parse_non_ofdma_users(const struct hal_eht_sig_non_ofdma_cmn_eb *eb,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- struct hal_rx_radiotap_eht *eht = &ppdu_info->eht_info.eht;
- u32 known, data;
-
- known = __le32_to_cpu(eht->known);
- known |= IEEE80211_RADIOTAP_EHT_KNOWN_NR_NON_OFDMA_USERS_M;
- eht->known = cpu_to_le32(known);
-
- data = __le32_to_cpu(eht->data[7]);
- data |= ATH12K_LE32_DEC_ENC(eb->info0,
- HAL_RX_EHT_SIG_NON_OFDMA_INFO0_NUM_USERS,
- IEEE80211_RADIOTAP_EHT_DATA7_NUM_OF_NON_OFDMA_USERS);
- eht->data[7] = cpu_to_le32(data);
-}
-
-static void
-ath12k_dp_mon_hal_rx_parse_eht_mumimo_user(const struct hal_eht_sig_mu_mimo *user,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- struct hal_rx_eht_info *eht_info = &ppdu_info->eht_info;
- u32 user_idx;
-
- if (eht_info->num_user_info >= ARRAY_SIZE(eht_info->user_info))
- return;
-
- user_idx = eht_info->num_user_info++;
-
- eht_info->user_info[user_idx] |=
- IEEE80211_RADIOTAP_EHT_USER_INFO_STA_ID_KNOWN |
- IEEE80211_RADIOTAP_EHT_USER_INFO_MCS_KNOWN |
- IEEE80211_RADIOTAP_EHT_USER_INFO_CODING_KNOWN |
- IEEE80211_RADIOTAP_EHT_USER_INFO_SPATIAL_CONFIG_KNOWN_M |
- ATH12K_LE32_DEC_ENC(user->info0,
- HAL_RX_EHT_SIG_MUMIMO_USER_INFO0_STA_ID,
- IEEE80211_RADIOTAP_EHT_USER_INFO_STA_ID) |
- ATH12K_LE32_DEC_ENC(user->info0,
- HAL_RX_EHT_SIG_MUMIMO_USER_INFO0_CODING,
- IEEE80211_RADIOTAP_EHT_USER_INFO_CODING) |
- ATH12K_LE32_DEC_ENC(user->info0,
- HAL_RX_EHT_SIG_MUMIMO_USER_INFO0_MCS,
- IEEE80211_RADIOTAP_EHT_USER_INFO_MCS) |
- ATH12K_LE32_DEC_ENC(user->info0,
- HAL_RX_EHT_SIG_MUMIMO_USER_INFO0_SPATIAL_CODING,
- IEEE80211_RADIOTAP_EHT_USER_INFO_SPATIAL_CONFIG_M);
-
- ppdu_info->mcs = le32_get_bits(user->info0,
- HAL_RX_EHT_SIG_MUMIMO_USER_INFO0_MCS);
-}
-
-static void
-ath12k_dp_mon_hal_rx_parse_eht_non_mumimo_user(const struct hal_eht_sig_non_mu_mimo *user,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- struct hal_rx_eht_info *eht_info = &ppdu_info->eht_info;
- u32 user_idx;
-
- if (eht_info->num_user_info >= ARRAY_SIZE(eht_info->user_info))
- return;
-
- user_idx = eht_info->num_user_info++;
-
- eht_info->user_info[user_idx] |=
- IEEE80211_RADIOTAP_EHT_USER_INFO_STA_ID_KNOWN |
- IEEE80211_RADIOTAP_EHT_USER_INFO_MCS_KNOWN |
- IEEE80211_RADIOTAP_EHT_USER_INFO_CODING_KNOWN |
- IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_KNOWN_O |
- IEEE80211_RADIOTAP_EHT_USER_INFO_BEAMFORMING_KNOWN_O |
- ATH12K_LE32_DEC_ENC(user->info0,
- HAL_RX_EHT_SIG_NON_MUMIMO_USER_INFO0_STA_ID,
- IEEE80211_RADIOTAP_EHT_USER_INFO_STA_ID) |
- ATH12K_LE32_DEC_ENC(user->info0,
- HAL_RX_EHT_SIG_NON_MUMIMO_USER_INFO0_CODING,
- IEEE80211_RADIOTAP_EHT_USER_INFO_CODING) |
- ATH12K_LE32_DEC_ENC(user->info0,
- HAL_RX_EHT_SIG_NON_MUMIMO_USER_INFO0_MCS,
- IEEE80211_RADIOTAP_EHT_USER_INFO_MCS) |
- ATH12K_LE32_DEC_ENC(user->info0,
- HAL_RX_EHT_SIG_NON_MUMIMO_USER_INFO0_NSS,
- IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_O) |
- ATH12K_LE32_DEC_ENC(user->info0,
- HAL_RX_EHT_SIG_NON_MUMIMO_USER_INFO0_BEAMFORMED,
- IEEE80211_RADIOTAP_EHT_USER_INFO_BEAMFORMING_O);
-
- ppdu_info->mcs = le32_get_bits(user->info0,
- HAL_RX_EHT_SIG_NON_MUMIMO_USER_INFO0_MCS);
-
- ppdu_info->nss = le32_get_bits(user->info0,
- HAL_RX_EHT_SIG_NON_MUMIMO_USER_INFO0_NSS) + 1;
-}
-
-static inline bool
-ath12k_dp_mon_hal_rx_is_mu_mimo_user(const struct hal_rx_u_sig_info *usig_info)
-{
- if (usig_info->ppdu_type_comp_mode == HAL_RX_RECEPTION_TYPE_SU &&
- usig_info->ul_dl == 1)
- return true;
-
- return false;
-}
-
-static void
-ath12k_dp_mon_hal_rx_parse_eht_sig_non_ofdma(const void *tlv,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- const struct hal_eht_sig_non_ofdma_cmn_eb *eb = tlv;
-
- ath12k_dp_mon_hal_rx_parse_usig_overflow(tlv, ppdu_info);
- ath12k_dp_mon_hal_rx_parse_non_ofdma_users(eb, ppdu_info);
-
- if (ath12k_dp_mon_hal_rx_is_mu_mimo_user(&ppdu_info->u_sig_info))
- ath12k_dp_mon_hal_rx_parse_eht_mumimo_user(&eb->user_field.mu_mimo,
- ppdu_info);
- else
- ath12k_dp_mon_hal_rx_parse_eht_non_mumimo_user(&eb->user_field.n_mu_mimo,
- ppdu_info);
-}
-
-static void
-ath12k_dp_mon_hal_rx_parse_ru_allocation(const struct hal_eht_sig_ofdma_cmn_eb *eb,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- const struct hal_eht_sig_ofdma_cmn_eb1 *ofdma_cmn_eb1 = &eb->eb1;
- const struct hal_eht_sig_ofdma_cmn_eb2 *ofdma_cmn_eb2 = &eb->eb2;
- struct hal_rx_radiotap_eht *eht = &ppdu_info->eht_info.eht;
- enum ieee80211_radiotap_eht_data ru_123, ru_124, ru_125, ru_126;
- enum ieee80211_radiotap_eht_data ru_121, ru_122, ru_112, ru_111;
- u32 data;
-
- ru_123 = IEEE80211_RADIOTAP_EHT_DATA4_RU_ALLOC_CC_1_2_3;
- ru_124 = IEEE80211_RADIOTAP_EHT_DATA5_RU_ALLOC_CC_1_2_4;
- ru_125 = IEEE80211_RADIOTAP_EHT_DATA5_RU_ALLOC_CC_1_2_5;
- ru_126 = IEEE80211_RADIOTAP_EHT_DATA6_RU_ALLOC_CC_1_2_6;
- ru_121 = IEEE80211_RADIOTAP_EHT_DATA3_RU_ALLOC_CC_1_2_1;
- ru_122 = IEEE80211_RADIOTAP_EHT_DATA3_RU_ALLOC_CC_1_2_2;
- ru_112 = IEEE80211_RADIOTAP_EHT_DATA2_RU_ALLOC_CC_1_1_2;
- ru_111 = IEEE80211_RADIOTAP_EHT_DATA1_RU_ALLOC_CC_1_1_1;
-
- switch (ppdu_info->u_sig_info.bw) {
- case HAL_EHT_BW_320_2:
- case HAL_EHT_BW_320_1:
- data = __le32_to_cpu(eht->data[4]);
- /* CC1 2::3 */
- data |= IEEE80211_RADIOTAP_EHT_DATA4_RU_ALLOC_CC_1_2_3_KNOWN |
- ATH12K_LE64_DEC_ENC(ofdma_cmn_eb2->info0,
- HAL_RX_EHT_SIG_OFDMA_EB2_RU_ALLOC_2_3,
- ru_123);
- eht->data[4] = cpu_to_le32(data);
-
- data = __le32_to_cpu(eht->data[5]);
- /* CC1 2::4 */
- data |= IEEE80211_RADIOTAP_EHT_DATA5_RU_ALLOC_CC_1_2_4_KNOWN |
- ATH12K_LE64_DEC_ENC(ofdma_cmn_eb2->info0,
- HAL_RX_EHT_SIG_OFDMA_EB2_RU_ALLOC_2_4,
- ru_124);
-
- /* CC1 2::5 */
- data |= IEEE80211_RADIOTAP_EHT_DATA5_RU_ALLOC_CC_1_2_5_KNOWN |
- ATH12K_LE64_DEC_ENC(ofdma_cmn_eb2->info0,
- HAL_RX_EHT_SIG_OFDMA_EB2_RU_ALLOC_2_5,
- ru_125);
- eht->data[5] = cpu_to_le32(data);
-
- data = __le32_to_cpu(eht->data[6]);
- /* CC1 2::6 */
- data |= IEEE80211_RADIOTAP_EHT_DATA6_RU_ALLOC_CC_1_2_6_KNOWN |
- ATH12K_LE64_DEC_ENC(ofdma_cmn_eb2->info0,
- HAL_RX_EHT_SIG_OFDMA_EB2_RU_ALLOC_2_6,
- ru_126);
- eht->data[6] = cpu_to_le32(data);
-
- fallthrough;
- case HAL_EHT_BW_160:
- data = __le32_to_cpu(eht->data[3]);
- /* CC1 2::1 */
- data |= IEEE80211_RADIOTAP_EHT_DATA3_RU_ALLOC_CC_1_2_1_KNOWN |
- ATH12K_LE64_DEC_ENC(ofdma_cmn_eb2->info0,
- HAL_RX_EHT_SIG_OFDMA_EB2_RU_ALLOC_2_1,
- ru_121);
- /* CC1 2::2 */
- data |= IEEE80211_RADIOTAP_EHT_DATA3_RU_ALLOC_CC_1_2_2_KNOWN |
- ATH12K_LE64_DEC_ENC(ofdma_cmn_eb2->info0,
- HAL_RX_EHT_SIG_OFDMA_EB2_RU_ALLOC_2_2,
- ru_122);
- eht->data[3] = cpu_to_le32(data);
-
- fallthrough;
- case HAL_EHT_BW_80:
- data = __le32_to_cpu(eht->data[2]);
- /* CC1 1::2 */
- data |= IEEE80211_RADIOTAP_EHT_DATA2_RU_ALLOC_CC_1_1_2_KNOWN |
- ATH12K_LE64_DEC_ENC(ofdma_cmn_eb1->info0,
- HAL_RX_EHT_SIG_OFDMA_EB1_RU_ALLOC_1_2,
- ru_112);
- eht->data[2] = cpu_to_le32(data);
-
- fallthrough;
- case HAL_EHT_BW_40:
- fallthrough;
- case HAL_EHT_BW_20:
- data = __le32_to_cpu(eht->data[1]);
- /* CC1 1::1 */
- data |= IEEE80211_RADIOTAP_EHT_DATA1_RU_ALLOC_CC_1_1_1_KNOWN |
- ATH12K_LE64_DEC_ENC(ofdma_cmn_eb1->info0,
- HAL_RX_EHT_SIG_OFDMA_EB1_RU_ALLOC_1_1,
- ru_111);
- eht->data[1] = cpu_to_le32(data);
- break;
- default:
- break;
- }
-}
-
-static void
-ath12k_dp_mon_hal_rx_parse_eht_sig_ofdma(const void *tlv,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- const struct hal_eht_sig_ofdma_cmn_eb *ofdma = tlv;
-
- ath12k_dp_mon_hal_rx_parse_usig_overflow(tlv, ppdu_info);
- ath12k_dp_mon_hal_rx_parse_ru_allocation(ofdma, ppdu_info);
-
- ath12k_dp_mon_hal_rx_parse_eht_non_mumimo_user(&ofdma->user_field.n_mu_mimo,
- ppdu_info);
-}
-
-static void
-ath12k_dp_mon_parse_eht_sig_hdr(struct hal_rx_mon_ppdu_info *ppdu_info,
- const void *tlv_data)
-{
- ppdu_info->is_eht = true;
-
- if (ath12k_dp_mon_hal_rx_is_frame_type_ndp(&ppdu_info->u_sig_info))
- ath12k_dp_mon_hal_rx_parse_eht_sig_ndp(tlv_data, ppdu_info);
- else if (ath12k_dp_mon_hal_rx_is_non_ofdma(&ppdu_info->u_sig_info))
- ath12k_dp_mon_hal_rx_parse_eht_sig_non_ofdma(tlv_data, ppdu_info);
- else if (ath12k_dp_mon_hal_rx_is_ofdma(&ppdu_info->u_sig_info))
- ath12k_dp_mon_hal_rx_parse_eht_sig_ofdma(tlv_data, ppdu_info);
-}
-
-static inline enum ath12k_eht_ru_size
-hal_rx_mon_hal_ru_size_to_ath12k_ru_size(u32 hal_ru_size)
-{
- switch (hal_ru_size) {
- case HAL_EHT_RU_26:
- return ATH12K_EHT_RU_26;
- case HAL_EHT_RU_52:
- return ATH12K_EHT_RU_52;
- case HAL_EHT_RU_78:
- return ATH12K_EHT_RU_52_26;
- case HAL_EHT_RU_106:
- return ATH12K_EHT_RU_106;
- case HAL_EHT_RU_132:
- return ATH12K_EHT_RU_106_26;
- case HAL_EHT_RU_242:
- return ATH12K_EHT_RU_242;
- case HAL_EHT_RU_484:
- return ATH12K_EHT_RU_484;
- case HAL_EHT_RU_726:
- return ATH12K_EHT_RU_484_242;
- case HAL_EHT_RU_996:
- return ATH12K_EHT_RU_996;
- case HAL_EHT_RU_996x2:
- return ATH12K_EHT_RU_996x2;
- case HAL_EHT_RU_996x3:
- return ATH12K_EHT_RU_996x3;
- case HAL_EHT_RU_996x4:
- return ATH12K_EHT_RU_996x4;
- case HAL_EHT_RU_NONE:
- return ATH12K_EHT_RU_INVALID;
- case HAL_EHT_RU_996_484:
- return ATH12K_EHT_RU_996_484;
- case HAL_EHT_RU_996x2_484:
- return ATH12K_EHT_RU_996x2_484;
- case HAL_EHT_RU_996x3_484:
- return ATH12K_EHT_RU_996x3_484;
- case HAL_EHT_RU_996_484_242:
- return ATH12K_EHT_RU_996_484_242;
- default:
- return ATH12K_EHT_RU_INVALID;
- }
-}
-
-static inline u32
-hal_rx_ul_ofdma_ru_size_to_width(enum ath12k_eht_ru_size ru_size)
-{
- switch (ru_size) {
- case ATH12K_EHT_RU_26:
- return RU_26;
- case ATH12K_EHT_RU_52:
- return RU_52;
- case ATH12K_EHT_RU_52_26:
- return RU_52_26;
- case ATH12K_EHT_RU_106:
- return RU_106;
- case ATH12K_EHT_RU_106_26:
- return RU_106_26;
- case ATH12K_EHT_RU_242:
- return RU_242;
- case ATH12K_EHT_RU_484:
- return RU_484;
- case ATH12K_EHT_RU_484_242:
- return RU_484_242;
- case ATH12K_EHT_RU_996:
- return RU_996;
- case ATH12K_EHT_RU_996_484:
- return RU_996_484;
- case ATH12K_EHT_RU_996_484_242:
- return RU_996_484_242;
- case ATH12K_EHT_RU_996x2:
- return RU_2X996;
- case ATH12K_EHT_RU_996x2_484:
- return RU_2X996_484;
- case ATH12K_EHT_RU_996x3:
- return RU_3X996;
- case ATH12K_EHT_RU_996x3_484:
- return RU_3X996_484;
- case ATH12K_EHT_RU_996x4:
- return RU_4X996;
- default:
- return RU_INVALID;
- }
-}
-
-static void
-ath12k_dp_mon_hal_rx_parse_user_info(const struct hal_receive_user_info *rx_usr_info,
- u16 user_id,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- struct hal_rx_user_status *mon_rx_user_status = NULL;
- struct hal_rx_radiotap_eht *eht = &ppdu_info->eht_info.eht;
- enum ath12k_eht_ru_size rtap_ru_size = ATH12K_EHT_RU_INVALID;
- u32 ru_width, reception_type, ru_index = HAL_EHT_RU_INVALID;
- u32 ru_type_80_0, ru_start_index_80_0;
- u32 ru_type_80_1, ru_start_index_80_1;
- u32 ru_type_80_2, ru_start_index_80_2;
- u32 ru_type_80_3, ru_start_index_80_3;
- u32 ru_size = 0, num_80mhz_with_ru = 0;
- u64 ru_index_320mhz = 0;
- u32 ru_index_per80mhz;
-
- reception_type = le32_get_bits(rx_usr_info->info0,
- HAL_RX_USR_INFO0_RECEPTION_TYPE);
-
- switch (reception_type) {
- case HAL_RECEPTION_TYPE_SU:
- ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_SU;
- break;
- case HAL_RECEPTION_TYPE_DL_MU_MIMO:
- case HAL_RECEPTION_TYPE_UL_MU_MIMO:
- ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_MU_MIMO;
- break;
- case HAL_RECEPTION_TYPE_DL_MU_OFMA:
- case HAL_RECEPTION_TYPE_UL_MU_OFDMA:
- ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_MU_OFDMA;
- break;
- case HAL_RECEPTION_TYPE_DL_MU_OFDMA_MIMO:
- case HAL_RECEPTION_TYPE_UL_MU_OFDMA_MIMO:
- ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_MU_OFDMA_MIMO;
- }
-
- ppdu_info->is_stbc = le32_get_bits(rx_usr_info->info0, HAL_RX_USR_INFO0_STBC);
- ppdu_info->ldpc = le32_get_bits(rx_usr_info->info2, HAL_RX_USR_INFO2_LDPC);
- ppdu_info->dcm = le32_get_bits(rx_usr_info->info2, HAL_RX_USR_INFO2_STA_DCM);
- ppdu_info->bw = le32_get_bits(rx_usr_info->info1, HAL_RX_USR_INFO1_RX_BW);
- ppdu_info->mcs = le32_get_bits(rx_usr_info->info1, HAL_RX_USR_INFO1_MCS);
- ppdu_info->nss = le32_get_bits(rx_usr_info->info2, HAL_RX_USR_INFO2_NSS) + 1;
-
- if (user_id < HAL_MAX_UL_MU_USERS) {
- mon_rx_user_status = &ppdu_info->userstats[user_id];
- mon_rx_user_status->mcs = ppdu_info->mcs;
- mon_rx_user_status->nss = ppdu_info->nss;
- }
-
- if (!(ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_MU_MIMO ||
- ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_MU_OFDMA ||
- ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_MU_OFDMA_MIMO))
- return;
-
- /* RU allocation present only for OFDMA reception */
- ru_type_80_0 = le32_get_bits(rx_usr_info->info2, HAL_RX_USR_INFO2_RU_TYPE_80_0);
- ru_start_index_80_0 = le32_get_bits(rx_usr_info->info3,
- HAL_RX_USR_INFO3_RU_START_IDX_80_0);
- if (ru_type_80_0 != HAL_EHT_RU_NONE) {
- ru_size += ru_type_80_0;
- ru_index_per80mhz = ru_start_index_80_0;
- ru_index = ru_index_per80mhz;
- ru_index_320mhz |= HAL_RU_PER80(ru_type_80_0, 0, ru_index_per80mhz);
- num_80mhz_with_ru++;
- }
-
- ru_type_80_1 = le32_get_bits(rx_usr_info->info2, HAL_RX_USR_INFO2_RU_TYPE_80_1);
- ru_start_index_80_1 = le32_get_bits(rx_usr_info->info3,
- HAL_RX_USR_INFO3_RU_START_IDX_80_1);
- if (ru_type_80_1 != HAL_EHT_RU_NONE) {
- ru_size += ru_type_80_1;
- ru_index_per80mhz = ru_start_index_80_1;
- ru_index = ru_index_per80mhz;
- ru_index_320mhz |= HAL_RU_PER80(ru_type_80_1, 1, ru_index_per80mhz);
- num_80mhz_with_ru++;
- }
-
- ru_type_80_2 = le32_get_bits(rx_usr_info->info2, HAL_RX_USR_INFO2_RU_TYPE_80_2);
- ru_start_index_80_2 = le32_get_bits(rx_usr_info->info3,
- HAL_RX_USR_INFO3_RU_START_IDX_80_2);
- if (ru_type_80_2 != HAL_EHT_RU_NONE) {
- ru_size += ru_type_80_2;
- ru_index_per80mhz = ru_start_index_80_2;
- ru_index = ru_index_per80mhz;
- ru_index_320mhz |= HAL_RU_PER80(ru_type_80_2, 2, ru_index_per80mhz);
- num_80mhz_with_ru++;
- }
-
- ru_type_80_3 = le32_get_bits(rx_usr_info->info2, HAL_RX_USR_INFO2_RU_TYPE_80_3);
- ru_start_index_80_3 = le32_get_bits(rx_usr_info->info2,
- HAL_RX_USR_INFO3_RU_START_IDX_80_3);
- if (ru_type_80_3 != HAL_EHT_RU_NONE) {
- ru_size += ru_type_80_3;
- ru_index_per80mhz = ru_start_index_80_3;
- ru_index = ru_index_per80mhz;
- ru_index_320mhz |= HAL_RU_PER80(ru_type_80_3, 3, ru_index_per80mhz);
- num_80mhz_with_ru++;
- }
-
- if (num_80mhz_with_ru > 1) {
- /* Calculate the MRU index */
- switch (ru_index_320mhz) {
- case HAL_EHT_RU_996_484_0:
- case HAL_EHT_RU_996x2_484_0:
- case HAL_EHT_RU_996x3_484_0:
- ru_index = 0;
- break;
- case HAL_EHT_RU_996_484_1:
- case HAL_EHT_RU_996x2_484_1:
- case HAL_EHT_RU_996x3_484_1:
- ru_index = 1;
- break;
- case HAL_EHT_RU_996_484_2:
- case HAL_EHT_RU_996x2_484_2:
- case HAL_EHT_RU_996x3_484_2:
- ru_index = 2;
- break;
- case HAL_EHT_RU_996_484_3:
- case HAL_EHT_RU_996x2_484_3:
- case HAL_EHT_RU_996x3_484_3:
- ru_index = 3;
- break;
- case HAL_EHT_RU_996_484_4:
- case HAL_EHT_RU_996x2_484_4:
- case HAL_EHT_RU_996x3_484_4:
- ru_index = 4;
- break;
- case HAL_EHT_RU_996_484_5:
- case HAL_EHT_RU_996x2_484_5:
- case HAL_EHT_RU_996x3_484_5:
- ru_index = 5;
- break;
- case HAL_EHT_RU_996_484_6:
- case HAL_EHT_RU_996x2_484_6:
- case HAL_EHT_RU_996x3_484_6:
- ru_index = 6;
- break;
- case HAL_EHT_RU_996_484_7:
- case HAL_EHT_RU_996x2_484_7:
- case HAL_EHT_RU_996x3_484_7:
- ru_index = 7;
- break;
- case HAL_EHT_RU_996x2_484_8:
- ru_index = 8;
- break;
- case HAL_EHT_RU_996x2_484_9:
- ru_index = 9;
- break;
- case HAL_EHT_RU_996x2_484_10:
- ru_index = 10;
- break;
- case HAL_EHT_RU_996x2_484_11:
- ru_index = 11;
- break;
- default:
- ru_index = HAL_EHT_RU_INVALID;
- break;
- }
-
- ru_size += 4;
- }
-
- rtap_ru_size = hal_rx_mon_hal_ru_size_to_ath12k_ru_size(ru_size);
- if (rtap_ru_size != ATH12K_EHT_RU_INVALID) {
- u32 known, data;
-
- known = __le32_to_cpu(eht->known);
- known |= IEEE80211_RADIOTAP_EHT_KNOWN_RU_MRU_SIZE_OM;
- eht->known = cpu_to_le32(known);
-
- data = __le32_to_cpu(eht->data[1]);
- data |= u32_encode_bits(rtap_ru_size,
- IEEE80211_RADIOTAP_EHT_DATA1_RU_SIZE);
- eht->data[1] = cpu_to_le32(data);
- }
-
- if (ru_index != HAL_EHT_RU_INVALID) {
- u32 known, data;
-
- known = __le32_to_cpu(eht->known);
- known |= IEEE80211_RADIOTAP_EHT_KNOWN_RU_MRU_INDEX_OM;
- eht->known = cpu_to_le32(known);
-
- data = __le32_to_cpu(eht->data[1]);
- data |= u32_encode_bits(rtap_ru_size,
- IEEE80211_RADIOTAP_EHT_DATA1_RU_INDEX);
- eht->data[1] = cpu_to_le32(data);
- }
-
- if (mon_rx_user_status && ru_index != HAL_EHT_RU_INVALID &&
- rtap_ru_size != ATH12K_EHT_RU_INVALID) {
- mon_rx_user_status->ul_ofdma_ru_start_index = ru_index;
- mon_rx_user_status->ul_ofdma_ru_size = rtap_ru_size;
-
- ru_width = hal_rx_ul_ofdma_ru_size_to_width(rtap_ru_size);
-
- mon_rx_user_status->ul_ofdma_ru_width = ru_width;
- mon_rx_user_status->ofdma_info_valid = 1;
- }
-}
-
-static void ath12k_dp_mon_parse_rx_msdu_end_err(u32 info, u32 *errmap)
-{
- if (info & RX_MSDU_END_INFO13_FCS_ERR)
- *errmap |= HAL_RX_MPDU_ERR_FCS;
-
- if (info & RX_MSDU_END_INFO13_DECRYPT_ERR)
- *errmap |= HAL_RX_MPDU_ERR_DECRYPT;
-
- if (info & RX_MSDU_END_INFO13_TKIP_MIC_ERR)
- *errmap |= HAL_RX_MPDU_ERR_TKIP_MIC;
-
- if (info & RX_MSDU_END_INFO13_A_MSDU_ERROR)
- *errmap |= HAL_RX_MPDU_ERR_AMSDU_ERR;
-
- if (info & RX_MSDU_END_INFO13_OVERFLOW_ERR)
- *errmap |= HAL_RX_MPDU_ERR_OVERFLOW;
-
- if (info & RX_MSDU_END_INFO13_MSDU_LEN_ERR)
- *errmap |= HAL_RX_MPDU_ERR_MSDU_LEN;
-
- if (info & RX_MSDU_END_INFO13_MPDU_LEN_ERR)
- *errmap |= HAL_RX_MPDU_ERR_MPDU_LEN;
-}
-
-static void
-ath12k_parse_cmn_usr_info(const struct hal_phyrx_common_user_info *cmn_usr_info,
- struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- struct hal_rx_radiotap_eht *eht = &ppdu_info->eht_info.eht;
- u32 known, data, cp_setting, ltf_size;
-
- known = __le32_to_cpu(eht->known);
- known |= IEEE80211_RADIOTAP_EHT_KNOWN_GI |
- IEEE80211_RADIOTAP_EHT_KNOWN_EHT_LTF;
- eht->known = cpu_to_le32(known);
-
- cp_setting = le32_get_bits(cmn_usr_info->info0,
- HAL_RX_CMN_USR_INFO0_CP_SETTING);
- ltf_size = le32_get_bits(cmn_usr_info->info0,
- HAL_RX_CMN_USR_INFO0_LTF_SIZE);
-
- data = __le32_to_cpu(eht->data[0]);
- data |= u32_encode_bits(cp_setting, IEEE80211_RADIOTAP_EHT_DATA0_GI);
- data |= u32_encode_bits(ltf_size, IEEE80211_RADIOTAP_EHT_DATA0_LTF);
- eht->data[0] = cpu_to_le32(data);
-
- if (!ppdu_info->ltf_size)
- ppdu_info->ltf_size = ltf_size;
- if (!ppdu_info->gi)
- ppdu_info->gi = cp_setting;
-}
-
-static void
-ath12k_dp_mon_parse_status_msdu_end(struct ath12k_mon_data *pmon,
- const struct hal_rx_msdu_end *msdu_end)
-{
- ath12k_dp_mon_parse_rx_msdu_end_err(__le32_to_cpu(msdu_end->info2),
- &pmon->err_bitmap);
- pmon->decap_format = le32_get_bits(msdu_end->info1,
- RX_MSDU_END_INFO11_DECAP_FORMAT);
-}
-
-static enum hal_rx_mon_status
-ath12k_dp_mon_rx_parse_status_tlv(struct ath12k *ar,
- struct ath12k_mon_data *pmon,
- const struct hal_tlv_64_hdr *tlv)
-{
- struct hal_rx_mon_ppdu_info *ppdu_info = &pmon->mon_ppdu_info;
- const void *tlv_data = tlv->value;
- u32 info[7], userid;
- u16 tlv_tag, tlv_len;
-
- tlv_tag = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_TAG);
- tlv_len = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_LEN);
- userid = le64_get_bits(tlv->tl, HAL_TLV_64_USR_ID);
-
- if (ppdu_info->tlv_aggr.in_progress && ppdu_info->tlv_aggr.tlv_tag != tlv_tag) {
- ath12k_dp_mon_parse_eht_sig_hdr(ppdu_info, ppdu_info->tlv_aggr.buf);
-
- ppdu_info->tlv_aggr.in_progress = false;
- ppdu_info->tlv_aggr.cur_len = 0;
- }
-
- switch (tlv_tag) {
- case HAL_RX_PPDU_START: {
- const struct hal_rx_ppdu_start *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);
-
- 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;
- ppdu_info->num_users = 0;
- memset(&ppdu_info->mpdu_fcs_ok_bitmap, 0,
- HAL_RX_NUM_WORDS_PER_PPDU_BITMAP *
- sizeof(ppdu_info->mpdu_fcs_ok_bitmap[0]));
- }
- break;
- }
- case HAL_RX_PPDU_END_USER_STATS: {
- const struct hal_rx_ppdu_end_user_stats *eu_stats = tlv_data;
- u32 tid_bitmap;
-
- info[0] = __le32_to_cpu(eu_stats->info0);
- info[1] = __le32_to_cpu(eu_stats->info1);
- info[2] = __le32_to_cpu(eu_stats->info2);
- info[4] = __le32_to_cpu(eu_stats->info4);
- info[5] = __le32_to_cpu(eu_stats->info5);
- info[6] = __le32_to_cpu(eu_stats->info6);
-
- ppdu_info->ast_index =
- u32_get_bits(info[2], HAL_RX_PPDU_END_USER_STATS_INFO2_AST_INDEX);
- ppdu_info->fc_valid =
- u32_get_bits(info[1], HAL_RX_PPDU_END_USER_STATS_INFO1_FC_VALID);
- tid_bitmap = u32_get_bits(info[6],
- HAL_RX_PPDU_END_USER_STATS_INFO6_TID_BITMAP);
- ppdu_info->tid = ffs(tid_bitmap) - 1;
- ppdu_info->tcp_msdu_count =
- u32_get_bits(info[4],
- HAL_RX_PPDU_END_USER_STATS_INFO4_TCP_MSDU_CNT);
- ppdu_info->udp_msdu_count =
- u32_get_bits(info[4],
- HAL_RX_PPDU_END_USER_STATS_INFO4_UDP_MSDU_CNT);
- ppdu_info->other_msdu_count =
- u32_get_bits(info[5],
- HAL_RX_PPDU_END_USER_STATS_INFO5_OTHER_MSDU_CNT);
- ppdu_info->tcp_ack_msdu_count =
- u32_get_bits(info[5],
- HAL_RX_PPDU_END_USER_STATS_INFO5_TCP_ACK_MSDU_CNT);
- ppdu_info->preamble_type =
- u32_get_bits(info[1],
- HAL_RX_PPDU_END_USER_STATS_INFO1_PKT_TYPE);
- ppdu_info->num_mpdu_fcs_ok =
- u32_get_bits(info[1],
- HAL_RX_PPDU_END_USER_STATS_INFO1_MPDU_CNT_FCS_OK);
- ppdu_info->num_mpdu_fcs_err =
- u32_get_bits(info[0],
- HAL_RX_PPDU_END_USER_STATS_INFO0_MPDU_CNT_FCS_ERR);
- ppdu_info->peer_id =
- u32_get_bits(info[0], HAL_RX_PPDU_END_USER_STATS_INFO0_PEER_ID);
-
- switch (ppdu_info->preamble_type) {
- case HAL_RX_PREAMBLE_11N:
- ppdu_info->ht_flags = 1;
- break;
- case HAL_RX_PREAMBLE_11AC:
- ppdu_info->vht_flags = 1;
- break;
- case HAL_RX_PREAMBLE_11AX:
- ppdu_info->he_flags = 1;
- break;
- case HAL_RX_PREAMBLE_11BE:
- ppdu_info->is_eht = true;
- break;
- default:
- break;
- }
-
- if (userid < HAL_MAX_UL_MU_USERS) {
- struct hal_rx_user_status *rxuser_stats =
- &ppdu_info->userstats[userid];
-
- if (ppdu_info->num_mpdu_fcs_ok > 1 ||
- ppdu_info->num_mpdu_fcs_err > 1)
- ppdu_info->userstats[userid].ampdu_present = true;
-
- ppdu_info->num_users += 1;
-
- ath12k_dp_mon_rx_handle_ofdma_info(eu_stats, rxuser_stats);
- ath12k_dp_mon_rx_populate_mu_user_info(eu_stats, ppdu_info,
- rxuser_stats);
- }
- ppdu_info->mpdu_fcs_ok_bitmap[0] = __le32_to_cpu(eu_stats->rsvd1[0]);
- ppdu_info->mpdu_fcs_ok_bitmap[1] = __le32_to_cpu(eu_stats->rsvd1[1]);
- break;
- }
- case HAL_RX_PPDU_END_USER_STATS_EXT: {
- const struct hal_rx_ppdu_end_user_stats_ext *eu_stats = tlv_data;
-
- ppdu_info->mpdu_fcs_ok_bitmap[2] = __le32_to_cpu(eu_stats->info1);
- ppdu_info->mpdu_fcs_ok_bitmap[3] = __le32_to_cpu(eu_stats->info2);
- ppdu_info->mpdu_fcs_ok_bitmap[4] = __le32_to_cpu(eu_stats->info3);
- ppdu_info->mpdu_fcs_ok_bitmap[5] = __le32_to_cpu(eu_stats->info4);
- ppdu_info->mpdu_fcs_ok_bitmap[6] = __le32_to_cpu(eu_stats->info5);
- ppdu_info->mpdu_fcs_ok_bitmap[7] = __le32_to_cpu(eu_stats->info6);
- break;
- }
- case HAL_PHYRX_HT_SIG:
- ath12k_dp_mon_parse_ht_sig(tlv_data, ppdu_info);
- break;
-
- case HAL_PHYRX_L_SIG_B:
- ath12k_dp_mon_parse_l_sig_b(tlv_data, ppdu_info);
- break;
-
- case HAL_PHYRX_L_SIG_A:
- ath12k_dp_mon_parse_l_sig_a(tlv_data, ppdu_info);
- break;
-
- case HAL_PHYRX_VHT_SIG_A:
- ath12k_dp_mon_parse_vht_sig_a(tlv_data, ppdu_info);
- break;
-
- case HAL_PHYRX_HE_SIG_A_SU:
- ath12k_dp_mon_parse_he_sig_su(tlv_data, ppdu_info);
- break;
-
- case HAL_PHYRX_HE_SIG_A_MU_DL:
- ath12k_dp_mon_parse_he_sig_mu(tlv_data, ppdu_info);
- break;
-
- case HAL_PHYRX_HE_SIG_B1_MU:
- ath12k_dp_mon_parse_he_sig_b1_mu(tlv_data, ppdu_info);
- break;
-
- case HAL_PHYRX_HE_SIG_B2_MU:
- ath12k_dp_mon_parse_he_sig_b2_mu(tlv_data, ppdu_info);
- break;
-
- case HAL_PHYRX_HE_SIG_B2_OFDMA:
- ath12k_dp_mon_parse_he_sig_b2_ofdma(tlv_data, ppdu_info);
- break;
-
- case HAL_PHYRX_RSSI_LEGACY: {
- const struct hal_rx_phyrx_rssi_legacy_info *rssi = tlv_data;
-
- info[0] = __le32_to_cpu(rssi->info0);
- info[2] = __le32_to_cpu(rssi->info2);
-
- /* 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[2],
- HAL_RX_RSSI_LEGACY_INFO_INFO2_RSSI_COMB_PPDU);
-
- ppdu_info->bw = u32_get_bits(info[0],
- HAL_RX_RSSI_LEGACY_INFO_INFO0_RX_BW);
- break;
- }
- case HAL_PHYRX_COMMON_USER_INFO: {
- ath12k_parse_cmn_usr_info(tlv_data, ppdu_info);
- break;
- }
- case HAL_RX_PPDU_START_USER_INFO:
- ath12k_dp_mon_hal_rx_parse_user_info(tlv_data, userid, ppdu_info);
- break;
-
- case HAL_RXPCU_PPDU_END_INFO: {
- const struct hal_rx_ppdu_end_duration *ppdu_rx_duration = tlv_data;
-
- info[0] = __le32_to_cpu(ppdu_rx_duration->info0);
- ppdu_info->rx_duration =
- u32_get_bits(info[0], HAL_RX_PPDU_END_DURATION);
- ppdu_info->tsft = __le32_to_cpu(ppdu_rx_duration->rsvd0[1]);
- ppdu_info->tsft = (ppdu_info->tsft << 32) |
- __le32_to_cpu(ppdu_rx_duration->rsvd0[0]);
- break;
- }
- case HAL_RX_MPDU_START: {
- const struct hal_rx_mpdu_start *mpdu_start = tlv_data;
- u16 peer_id;
-
- info[1] = __le32_to_cpu(mpdu_start->info1);
- peer_id = u32_get_bits(info[1], HAL_RX_MPDU_START_INFO1_PEERID);
- if (peer_id)
- ppdu_info->peer_id = peer_id;
-
- ppdu_info->mpdu_len += u32_get_bits(info[1],
- HAL_RX_MPDU_START_INFO2_MPDU_LEN);
- if (userid < HAL_MAX_UL_MU_USERS) {
- info[0] = __le32_to_cpu(mpdu_start->info0);
- ppdu_info->userid = userid;
- ppdu_info->userstats[userid].ampdu_id =
- u32_get_bits(info[0], HAL_RX_MPDU_START_INFO0_PPDU_ID);
- }
-
- return HAL_RX_MON_STATUS_MPDU_START;
- }
- case HAL_RX_MSDU_START:
- /* TODO: add msdu start parsing logic */
- break;
- case HAL_MON_BUF_ADDR:
- return HAL_RX_MON_STATUS_BUF_ADDR;
- case HAL_RX_MSDU_END:
- ath12k_dp_mon_parse_status_msdu_end(pmon, tlv_data);
- return HAL_RX_MON_STATUS_MSDU_END;
- case HAL_RX_MPDU_END:
- return HAL_RX_MON_STATUS_MPDU_END;
- case HAL_PHYRX_GENERIC_U_SIG:
- ath12k_dp_mon_hal_rx_parse_u_sig_hdr(tlv_data, ppdu_info);
- break;
- case HAL_PHYRX_GENERIC_EHT_SIG:
- /* Handle the case where aggregation is in progress
- * or the current TLV is one of the TLVs which should be
- * aggregated
- */
- if (!ppdu_info->tlv_aggr.in_progress) {
- ppdu_info->tlv_aggr.in_progress = true;
- ppdu_info->tlv_aggr.tlv_tag = tlv_tag;
- ppdu_info->tlv_aggr.cur_len = 0;
- }
-
- ppdu_info->is_eht = true;
-
- ath12k_dp_mon_hal_aggr_tlv(ppdu_info, tlv_len, tlv_data);
- break;
- case HAL_DUMMY:
- return HAL_RX_MON_STATUS_BUF_DONE;
- case HAL_RX_PPDU_END_STATUS_DONE:
- case 0:
- return HAL_RX_MON_STATUS_PPDU_DONE;
- default:
- break;
- }
-
- return HAL_RX_MON_STATUS_PPDU_NOT_DONE;
-}
-
-static void
-ath12k_dp_mon_fill_rx_stats_info(struct ath12k *ar,
- struct hal_rx_mon_ppdu_info *ppdu_info,
+ath12k_dp_mon_fill_rx_stats_info(struct hal_rx_mon_ppdu_info *ppdu_info,
struct ieee80211_rx_status *rx_status)
{
u32 center_freq = ppdu_info->freq;
@@ -1781,7 +36,7 @@ ath12k_dp_mon_fill_rx_stats_info(struct ath12k *ar,
}
}
-static struct sk_buff
+struct sk_buff
*ath12k_dp_rx_alloc_mon_status_buf(struct ath12k_base *ab,
struct dp_rxdma_mon_ring *rx_ring,
int *buf_id)
@@ -1824,48 +79,9 @@ fail_free_skb:
fail_alloc_skb:
return NULL;
}
+EXPORT_SYMBOL(ath12k_dp_rx_alloc_mon_status_buf);
-static enum dp_mon_status_buf_state
-ath12k_dp_rx_mon_buf_done(struct ath12k_base *ab, struct hal_srng *srng,
- struct dp_rxdma_mon_ring *rx_ring)
-{
- struct ath12k_skb_rxcb *rxcb;
- struct hal_tlv_64_hdr *tlv;
- struct sk_buff *skb;
- void *status_desc;
- dma_addr_t paddr;
- u32 cookie;
- int buf_id;
- u8 rbm;
-
- status_desc = ath12k_hal_srng_src_next_peek(ab, srng);
- if (!status_desc)
- return DP_MON_STATUS_NO_DMA;
-
- ath12k_hal_rx_buf_addr_info_get(status_desc, &paddr, &cookie, &rbm);
-
- buf_id = u32_get_bits(cookie, DP_RXDMA_BUF_COOKIE_BUF_ID);
-
- spin_lock_bh(&rx_ring->idr_lock);
- skb = idr_find(&rx_ring->bufs_idr, buf_id);
- spin_unlock_bh(&rx_ring->idr_lock);
-
- if (!skb)
- return DP_MON_STATUS_NO_DMA;
-
- rxcb = ATH12K_SKB_RXCB(skb);
- dma_sync_single_for_cpu(ab->dev, rxcb->paddr,
- skb->len + skb_tailroom(skb),
- DMA_FROM_DEVICE);
-
- tlv = (struct hal_tlv_64_hdr *)skb->data;
- if (le64_get_bits(tlv->tl, HAL_TLV_HDR_TAG) != HAL_RX_STATUS_BUFFER_DONE)
- return DP_MON_STATUS_NO_DMA;
-
- return DP_MON_STATUS_REPLINISH;
-}
-
-static u32 ath12k_dp_mon_comp_ppduid(u32 msdu_ppdu_id, u32 *ppdu_id)
+u32 ath12k_dp_mon_comp_ppduid(u32 msdu_ppdu_id, u32 *ppdu_id)
{
u32 ret = 0;
@@ -1884,26 +100,15 @@ static u32 ath12k_dp_mon_comp_ppduid(u32 msdu_ppdu_id, u32 *ppdu_id)
}
return ret;
}
-
-static
-void ath12k_dp_mon_next_link_desc_get(struct hal_rx_msdu_link *msdu_link,
- dma_addr_t *paddr, u32 *sw_cookie, u8 *rbm,
- struct ath12k_buffer_addr **pp_buf_addr_info)
-{
- struct ath12k_buffer_addr *buf_addr_info;
-
- buf_addr_info = &msdu_link->buf_addr_info;
-
- ath12k_hal_rx_buf_addr_info_get(buf_addr_info, paddr, sw_cookie, rbm);
-
- *pp_buf_addr_info = buf_addr_info;
-}
+EXPORT_SYMBOL(ath12k_dp_mon_comp_ppduid);
static void
-ath12k_dp_mon_fill_rx_rate(struct ath12k *ar,
+ath12k_dp_mon_fill_rx_rate(struct ath12k_pdev_dp *dp_pdev,
struct hal_rx_mon_ppdu_info *ppdu_info,
struct ieee80211_rx_status *rx_status)
{
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
struct ieee80211_supported_band *sband;
enum rx_msdu_start_pkt_type pkt_type;
u8 rate_mcs, nss, sgi;
@@ -1919,6 +124,8 @@ ath12k_dp_mon_fill_rx_rate(struct ath12k *ar,
case RX_MSDU_START_PKT_TYPE_11B:
is_cck = (pkt_type == RX_MSDU_START_PKT_TYPE_11B);
if (rx_status->band < NUM_NL80211_BANDS) {
+ struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev);
+
sband = &ar->mac.sbands[rx_status->band];
rx_status->rate_idx = ath12k_mac_hw_rate_to_idx(sband, rate_mcs,
is_cck);
@@ -1927,7 +134,7 @@ ath12k_dp_mon_fill_rx_rate(struct ath12k *ar,
case RX_MSDU_START_PKT_TYPE_11N:
rx_status->encoding = RX_ENC_HT;
if (rate_mcs > ATH12K_HT_MCS_MAX) {
- ath12k_warn(ar->ab,
+ ath12k_warn(ab,
"Received with invalid mcs in HT mode %d\n",
rate_mcs);
break;
@@ -1940,7 +147,7 @@ ath12k_dp_mon_fill_rx_rate(struct ath12k *ar,
rx_status->encoding = RX_ENC_VHT;
rx_status->rate_idx = rate_mcs;
if (rate_mcs > ATH12K_VHT_MCS_MAX) {
- ath12k_warn(ar->ab,
+ ath12k_warn(ab,
"Received with invalid mcs in VHT mode %d\n",
rate_mcs);
break;
@@ -1951,7 +158,7 @@ ath12k_dp_mon_fill_rx_rate(struct ath12k *ar,
case RX_MSDU_START_PKT_TYPE_11AX:
rx_status->rate_idx = rate_mcs;
if (rate_mcs > ATH12K_HE_MCS_MAX) {
- ath12k_warn(ar->ab,
+ ath12k_warn(ab,
"Received with invalid mcs in HE mode %d\n",
rate_mcs);
break;
@@ -1962,7 +169,7 @@ ath12k_dp_mon_fill_rx_rate(struct ath12k *ar,
case RX_MSDU_START_PKT_TYPE_11BE:
rx_status->rate_idx = rate_mcs;
if (rate_mcs > ATH12K_EHT_MCS_MAX) {
- ath12k_warn(ar->ab,
+ ath12k_warn(ab,
"Received with invalid mcs in EHT mode %d\n",
rate_mcs);
break;
@@ -1971,24 +178,24 @@ ath12k_dp_mon_fill_rx_rate(struct ath12k *ar,
rx_status->he_gi = ath12k_he_gi_to_nl80211_he_gi(sgi);
break;
default:
- ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
+ ath12k_dbg(ab, ATH12K_DBG_DATA,
"monitor receives invalid preamble type %d",
pkt_type);
break;
}
}
-static void ath12k_dp_mon_rx_msdus_set_payload(struct ath12k *ar,
+static void ath12k_dp_mon_rx_msdus_set_payload(struct ath12k_base *ab,
struct sk_buff *head_msdu,
struct sk_buff *tail_msdu)
{
u32 rx_pkt_offset, l2_hdr_offset, total_offset;
- rx_pkt_offset = ar->ab->hal.hal_desc_sz;
+ rx_pkt_offset = ab->hal.hal_desc_sz;
l2_hdr_offset =
- ath12k_dp_rx_h_l3pad(ar->ab, (struct hal_rx_desc *)tail_msdu->data);
+ ath12k_dp_rx_h_l3pad(ab, (struct hal_rx_desc *)tail_msdu->data);
- if (ar->ab->hw_params->rxdma1_enable)
+ if (ab->hw_params->rxdma1_enable)
total_offset = ATH12K_MON_RX_PKT_OFFSET;
else
total_offset = rx_pkt_offset + l2_hdr_offset;
@@ -1996,13 +203,14 @@ static void ath12k_dp_mon_rx_msdus_set_payload(struct ath12k *ar,
skb_pull(head_msdu, total_offset);
}
-static struct sk_buff *
-ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
+struct sk_buff *
+ath12k_dp_mon_rx_merg_msdus(struct ath12k_pdev_dp *dp_pdev,
struct dp_mon_mpdu *mon_mpdu,
struct hal_rx_mon_ppdu_info *ppdu_info,
struct ieee80211_rx_status *rxs)
{
- struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
struct sk_buff *msdu, *mpdu_buf, *prev_buf, *head_frag_list;
struct sk_buff *head_msdu, *tail_msdu;
struct hal_rx_desc *rx_desc;
@@ -2019,11 +227,13 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
if (!head_msdu || !tail_msdu)
goto err_merge_fail;
- ath12k_dp_mon_fill_rx_stats_info(ar, ppdu_info, rxs);
+ ath12k_dp_mon_fill_rx_stats_info(ppdu_info, rxs);
if (unlikely(rxs->band == NUM_NL80211_BANDS ||
- !ath12k_ar_to_hw(ar)->wiphy->bands[rxs->band])) {
- ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
+ !ath12k_pdev_dp_to_hw(dp_pdev)->wiphy->bands[rxs->band])) {
+ struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev);
+
+ ath12k_dbg(ab, ATH12K_DBG_DATA,
"sband is NULL for status band %d channel_num %d center_freq %d pdev_id %d\n",
rxs->band, channel_num, ppdu_info->freq, ar->pdev_idx);
@@ -2041,17 +251,17 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
rxs->freq = ieee80211_channel_to_frequency(channel_num,
rxs->band);
- ath12k_dp_mon_fill_rx_rate(ar, ppdu_info, rxs);
+ ath12k_dp_mon_fill_rx_rate(dp_pdev, ppdu_info, rxs);
if (decap_format == DP_RX_DECAP_TYPE_RAW) {
- ath12k_dp_mon_rx_msdus_set_payload(ar, head_msdu, tail_msdu);
+ ath12k_dp_mon_rx_msdus_set_payload(ab, 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, head_msdu, tail_msdu);
+ ath12k_dp_mon_rx_msdus_set_payload(ab, head_msdu, tail_msdu);
if (!head_frag_list)
head_frag_list = msdu;
@@ -2075,7 +285,7 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
rx_desc = (struct hal_rx_desc *)head_msdu->data;
hdr_desc =
- ab->hal_rx_ops->rx_desc_get_msdu_payload(rx_desc);
+ ab->hal.ops->rx_desc_get_msdu_payload(rx_desc);
/* Base size */
wh = (struct ieee80211_hdr_3addr *)hdr_desc;
@@ -2086,7 +296,7 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
msdu = head_msdu;
while (msdu) {
- ath12k_dp_mon_rx_msdus_set_payload(ar, head_msdu, tail_msdu);
+ ath12k_dp_mon_rx_msdus_set_payload(ab, head_msdu, tail_msdu);
if (qos_pkt) {
dest = skb_push(msdu, sizeof(__le16));
if (!dest)
@@ -2121,6 +331,7 @@ err_merge_fail:
}
return NULL;
}
+EXPORT_SYMBOL(ath12k_dp_mon_rx_merg_msdus);
static void
ath12k_dp_mon_rx_update_radiotap_he(struct hal_rx_mon_ppdu_info *rx_status,
@@ -2170,11 +381,12 @@ ath12k_dp_mon_rx_update_radiotap_he_mu(struct hal_rx_mon_ppdu_info *rx_status,
rtap_buf[rtap_len] = rx_status->he_RU[3];
}
-static void ath12k_dp_mon_update_radiotap(struct ath12k *ar,
- struct hal_rx_mon_ppdu_info *ppduinfo,
- struct sk_buff *mon_skb,
- struct ieee80211_rx_status *rxs)
+void ath12k_dp_mon_update_radiotap(struct ath12k_pdev_dp *dp_pdev,
+ struct hal_rx_mon_ppdu_info *ppduinfo,
+ struct sk_buff *mon_skb,
+ struct ieee80211_rx_status *rxs)
{
+ struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev);
struct ieee80211_supported_band *sband;
s32 noise_floor;
u8 *ptr = NULL;
@@ -2267,6 +479,9 @@ static void ath12k_dp_mon_update_radiotap(struct ath12k *ar,
rxs->encoding = RX_ENC_HT;
rxs->rate_idx = ppduinfo->rate;
} else {
+ struct ath12k *ar;
+
+ ar = ath12k_pdev_dp_to_ar(dp_pdev);
rxs->encoding = RX_ENC_LEGACY;
sband = &ar->mac.sbands[rxs->band];
rxs->rate_idx = ath12k_mac_hw_rate_to_idx(sband, ppduinfo->rate,
@@ -2275,13 +490,17 @@ static void ath12k_dp_mon_update_radiotap(struct ath12k *ar,
rxs->mactime = ppduinfo->tsft;
}
+EXPORT_SYMBOL(ath12k_dp_mon_update_radiotap);
-static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *napi,
- struct sk_buff *msdu,
- const struct hal_rx_mon_ppdu_info *ppduinfo,
- struct ieee80211_rx_status *status,
- u8 decap)
+void ath12k_dp_mon_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev,
+ struct napi_struct *napi,
+ struct sk_buff *msdu,
+ const struct hal_rx_mon_ppdu_info *ppduinfo,
+ struct ieee80211_rx_status *status,
+ u8 decap)
{
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
static const struct ieee80211_radiotap_he known = {
.data1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN |
IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN),
@@ -2290,10 +509,13 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k *ar, struct napi_struct
struct ieee80211_rx_status *rx_status;
struct ieee80211_radiotap_he *he = NULL;
struct ieee80211_sta *pubsta = NULL;
- struct ath12k_peer *peer;
+ struct ath12k_dp_link_peer *peer;
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
+ struct hal_rx_desc_data rx_info;
bool is_mcbc = rxcb->is_mcbc;
bool is_eapol_tkip = rxcb->is_eapol;
+ struct hal_rx_desc *rx_desc = (struct hal_rx_desc *)msdu->data;
+ u8 addr[ETH_ALEN] = {};
status->link_valid = 0;
@@ -2304,23 +526,28 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k *ar, struct napi_struct
status->flag |= RX_FLAG_RADIOTAP_HE;
}
- spin_lock_bh(&ar->ab->base_lock);
- peer = ath12k_peer_find_by_id(ar->ab, ppduinfo->peer_id);
+ ath12k_dp_extract_rx_desc_data(dp->hal, &rx_info, rx_desc, rx_desc);
+
+ rcu_read_lock();
+ spin_lock_bh(&dp->dp_lock);
+ peer = ath12k_dp_rx_h_find_link_peer(dp_pdev, msdu, &rx_info);
if (peer && peer->sta) {
pubsta = peer->sta;
+ memcpy(addr, peer->addr, ETH_ALEN);
if (pubsta->valid_links) {
status->link_valid = 1;
status->link_id = peer->link_id;
}
}
- spin_unlock_bh(&ar->ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
+ rcu_read_unlock();
- ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
+ ath12k_dbg(ab, ATH12K_DBG_DATA,
"rx skb %p len %u peer %pM %u %s %s%s%s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
msdu,
msdu->len,
- peer ? peer->addr : NULL,
+ addr,
rxcb->tid,
(is_mcbc) ? "mcast" : "ucast",
(status->encoding == RX_ENC_LEGACY) ? "legacy" : "",
@@ -2340,7 +567,7 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k *ar, struct napi_struct
!!(status->flag & RX_FLAG_MMIC_ERROR),
!!(status->flag & RX_FLAG_AMSDU_MORE));
- ath12k_dbg_dump(ar->ab, ATH12K_DBG_DP_RX, NULL, "dp rx msdu: ",
+ ath12k_dbg_dump(ab, ATH12K_DBG_DP_RX, NULL, "dp rx msdu: ",
msdu->data, msdu->len);
rx_status = IEEE80211_SKB_RXCB(msdu);
*rx_status = *status;
@@ -2356,66 +583,11 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k *ar, struct napi_struct
!(is_mcbc && rx_status->flag & RX_FLAG_DECRYPTED))
rx_status->flag |= RX_FLAG_8023;
- ieee80211_rx_napi(ath12k_ar_to_hw(ar), pubsta, msdu, napi);
+ ieee80211_rx_napi(ath12k_pdev_dp_to_hw(dp_pdev), pubsta, msdu, napi);
}
+EXPORT_SYMBOL(ath12k_dp_mon_rx_deliver_msdu);
-static int ath12k_dp_mon_rx_deliver(struct ath12k *ar,
- struct dp_mon_mpdu *mon_mpdu,
- struct hal_rx_mon_ppdu_info *ppduinfo,
- struct napi_struct *napi)
-{
- struct ath12k_pdev_dp *dp = &ar->dp;
- struct sk_buff *mon_skb, *skb_next, *header;
- struct ieee80211_rx_status *rxs = &dp->rx_status;
- u8 decap = DP_RX_DECAP_TYPE_RAW;
-
- mon_skb = ath12k_dp_mon_rx_merg_msdus(ar, mon_mpdu, ppduinfo, rxs);
- if (!mon_skb)
- goto mon_deliver_fail;
-
- header = mon_skb;
- rxs->flag = 0;
-
- if (mon_mpdu->err_bitmap & HAL_RX_MPDU_ERR_FCS)
- rxs->flag = RX_FLAG_FAILED_FCS_CRC;
-
- do {
- skb_next = mon_skb->next;
- if (!skb_next)
- rxs->flag &= ~RX_FLAG_AMSDU_MORE;
- else
- rxs->flag |= RX_FLAG_AMSDU_MORE;
-
- if (mon_skb == header) {
- header = NULL;
- rxs->flag &= ~RX_FLAG_ALLOW_SAME_PN;
- } else {
- rxs->flag |= RX_FLAG_ALLOW_SAME_PN;
- }
- rxs->flag |= RX_FLAG_ONLY_MONITOR;
-
- if (!(rxs->flag & RX_FLAG_ONLY_MONITOR))
- decap = mon_mpdu->decap_format;
-
- ath12k_dp_mon_update_radiotap(ar, ppduinfo, mon_skb, rxs);
- ath12k_dp_mon_rx_deliver_msdu(ar, napi, mon_skb, ppduinfo, rxs, decap);
- mon_skb = skb_next;
- } while (mon_skb);
- rxs->flag = 0;
-
- return 0;
-
-mon_deliver_fail:
- mon_skb = mon_mpdu->head;
- while (mon_skb) {
- skb_next = mon_skb->next;
- dev_kfree_skb_any(mon_skb);
- mon_skb = skb_next;
- }
- return -EINVAL;
-}
-
-static int ath12k_dp_pkt_set_pktlen(struct sk_buff *skb, u32 len)
+int ath12k_dp_pkt_set_pktlen(struct sk_buff *skb, u32 len)
{
if (skb->len > len) {
skb_trim(skb, len);
@@ -2432,40 +604,16 @@ static int ath12k_dp_pkt_set_pktlen(struct sk_buff *skb, u32 len)
return 0;
}
+EXPORT_SYMBOL(ath12k_dp_pkt_set_pktlen);
-/* Hardware fill buffer with 128 bytes aligned. So need to reap it
- * with 128 bytes aligned.
- */
-#define RXDMA_DATA_DMA_BLOCK_SIZE 128
-
-static void
-ath12k_dp_mon_get_buf_len(struct hal_rx_msdu_desc_info *info,
- bool *is_frag, u32 *total_len,
- u32 *frag_len, u32 *msdu_cnt)
-{
- if (info->msdu_flags & RX_MSDU_DESC_INFO0_MSDU_CONTINUATION) {
- *is_frag = true;
- *frag_len = (RX_MON_STATUS_BASE_BUF_SIZE -
- sizeof(struct hal_rx_desc)) &
- ~(RXDMA_DATA_DMA_BLOCK_SIZE - 1);
- *total_len += *frag_len;
- } else {
- if (*is_frag)
- *frag_len = info->msdu_len - *total_len;
- else
- *frag_len = info->msdu_len;
-
- *msdu_cnt -= 1;
- }
-}
-
-static int
-ath12k_dp_mon_parse_status_buf(struct ath12k *ar,
+int
+ath12k_dp_mon_parse_status_buf(struct ath12k_pdev_dp *dp_pdev,
struct ath12k_mon_data *pmon,
const struct dp_mon_packet_info *packet_info)
{
- struct ath12k_base *ab = ar->ab;
- struct dp_rxdma_mon_ring *buf_ring = &ab->dp.rxdma_mon_buf_ring;
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
+ struct dp_rxdma_mon_ring *buf_ring = &dp->rxdma_mon_buf_ring;
struct sk_buff *msdu;
int buf_id;
u32 offset;
@@ -2503,121 +651,7 @@ dest_replenish:
return 0;
}
-
-static int
-ath12k_dp_mon_parse_rx_dest_tlv(struct ath12k *ar,
- struct ath12k_mon_data *pmon,
- enum hal_rx_mon_status hal_status,
- const void *tlv_data)
-{
- switch (hal_status) {
- case HAL_RX_MON_STATUS_MPDU_START:
- if (WARN_ON_ONCE(pmon->mon_mpdu))
- break;
-
- pmon->mon_mpdu = kzalloc(sizeof(*pmon->mon_mpdu), GFP_ATOMIC);
- if (!pmon->mon_mpdu)
- return -ENOMEM;
- break;
- case HAL_RX_MON_STATUS_BUF_ADDR:
- return ath12k_dp_mon_parse_status_buf(ar, pmon, tlv_data);
- case HAL_RX_MON_STATUS_MPDU_END:
- /* If no MSDU then free empty MPDU */
- if (pmon->mon_mpdu->tail) {
- pmon->mon_mpdu->tail->next = NULL;
- list_add_tail(&pmon->mon_mpdu->list, &pmon->dp_rx_mon_mpdu_list);
- } else {
- kfree(pmon->mon_mpdu);
- }
- pmon->mon_mpdu = NULL;
- break;
- case HAL_RX_MON_STATUS_MSDU_END:
- pmon->mon_mpdu->decap_format = pmon->decap_format;
- pmon->mon_mpdu->err_bitmap = pmon->err_bitmap;
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-static enum hal_rx_mon_status
-ath12k_dp_mon_parse_rx_dest(struct ath12k *ar, struct ath12k_mon_data *pmon,
- struct sk_buff *skb)
-{
- struct hal_tlv_64_hdr *tlv;
- struct ath12k_skb_rxcb *rxcb;
- enum hal_rx_mon_status hal_status;
- u16 tlv_tag, tlv_len;
- u8 *ptr = skb->data;
-
- do {
- tlv = (struct hal_tlv_64_hdr *)ptr;
- tlv_tag = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_TAG);
-
- /* The actual length of PPDU_END is the combined length of many PHY
- * TLVs that follow. Skip the TLV header and
- * rx_rxpcu_classification_overview that follows the header to get to
- * next TLV.
- */
-
- if (tlv_tag == HAL_RX_PPDU_END)
- tlv_len = sizeof(struct hal_rx_rxpcu_classification_overview);
- else
- tlv_len = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_LEN);
-
- hal_status = ath12k_dp_mon_rx_parse_status_tlv(ar, pmon, tlv);
-
- if (ar->monitor_started && ar->ab->hw_params->rxdma1_enable &&
- ath12k_dp_mon_parse_rx_dest_tlv(ar, pmon, hal_status, tlv->value))
- return HAL_RX_MON_STATUS_PPDU_DONE;
-
- ptr += sizeof(*tlv) + tlv_len;
- ptr = PTR_ALIGN(ptr, HAL_TLV_64_ALIGN);
-
- if ((ptr - skb->data) > skb->len)
- break;
-
- } while ((hal_status == HAL_RX_MON_STATUS_PPDU_NOT_DONE) ||
- (hal_status == HAL_RX_MON_STATUS_BUF_ADDR) ||
- (hal_status == HAL_RX_MON_STATUS_MPDU_START) ||
- (hal_status == HAL_RX_MON_STATUS_MPDU_END) ||
- (hal_status == HAL_RX_MON_STATUS_MSDU_END));
-
- rxcb = ATH12K_SKB_RXCB(skb);
- if (rxcb->is_end_of_ppdu)
- hal_status = HAL_RX_MON_STATUS_PPDU_DONE;
-
- return hal_status;
-}
-
-enum hal_rx_mon_status
-ath12k_dp_mon_rx_parse_mon_status(struct ath12k *ar,
- struct ath12k_mon_data *pmon,
- struct sk_buff *skb,
- struct napi_struct *napi)
-{
- struct hal_rx_mon_ppdu_info *ppdu_info = &pmon->mon_ppdu_info;
- struct dp_mon_mpdu *tmp;
- struct dp_mon_mpdu *mon_mpdu = pmon->mon_mpdu;
- enum hal_rx_mon_status hal_status;
-
- hal_status = ath12k_dp_mon_parse_rx_dest(ar, pmon, skb);
- if (hal_status != HAL_RX_MON_STATUS_PPDU_DONE)
- return hal_status;
-
- list_for_each_entry_safe(mon_mpdu, tmp, &pmon->dp_rx_mon_mpdu_list, list) {
- list_del(&mon_mpdu->list);
-
- if (mon_mpdu->head && mon_mpdu->tail)
- ath12k_dp_mon_rx_deliver(ar, mon_mpdu, ppdu_info, napi);
-
- kfree(mon_mpdu);
- }
-
- return hal_status;
-}
+EXPORT_SYMBOL(ath12k_dp_mon_parse_status_buf);
int ath12k_dp_mon_buf_replenish(struct ath12k_base *ab,
struct dp_rxdma_mon_ring *buf_ring,
@@ -2693,13 +727,14 @@ fail_alloc_skb:
spin_unlock_bh(&srng->lock);
return -ENOMEM;
}
+EXPORT_SYMBOL(ath12k_dp_mon_buf_replenish);
int ath12k_dp_mon_status_bufs_replenish(struct ath12k_base *ab,
struct dp_rxdma_mon_ring *rx_ring,
int req_entries)
{
enum hal_rx_buf_return_buf_manager mgr =
- ab->hw_params->hal_params->rx_buf_rbm;
+ ab->hal.hal_params->rx_buf_rbm;
int num_free, num_remain, buf_id;
struct ath12k_buffer_addr *desc;
struct hal_srng *srng;
@@ -2756,7 +791,7 @@ int ath12k_dp_mon_status_bufs_replenish(struct ath12k_base *ab,
num_remain--;
- ath12k_hal_rx_buf_addr_info_set(desc, paddr, cookie, mgr);
+ ath12k_hal_rx_buf_addr_info_set(&ab->hal, desc, paddr, cookie, mgr);
}
ath12k_hal_srng_access_end(ab, srng);
@@ -2782,676 +817,6 @@ fail_free_skb:
return req_entries - num_remain;
}
-static struct dp_mon_tx_ppdu_info *
-ath12k_dp_mon_tx_get_ppdu_info(struct ath12k_mon_data *pmon,
- unsigned int ppdu_id,
- enum dp_mon_tx_ppdu_info_type type)
-{
- struct dp_mon_tx_ppdu_info *tx_ppdu_info;
-
- if (type == DP_MON_TX_PROT_PPDU_INFO) {
- tx_ppdu_info = pmon->tx_prot_ppdu_info;
-
- if (tx_ppdu_info && !tx_ppdu_info->is_used)
- return tx_ppdu_info;
- kfree(tx_ppdu_info);
- } else {
- tx_ppdu_info = pmon->tx_data_ppdu_info;
-
- if (tx_ppdu_info && !tx_ppdu_info->is_used)
- return tx_ppdu_info;
- kfree(tx_ppdu_info);
- }
-
- /* allocate new tx_ppdu_info */
- tx_ppdu_info = kzalloc(sizeof(*tx_ppdu_info), GFP_ATOMIC);
- if (!tx_ppdu_info)
- return NULL;
-
- tx_ppdu_info->is_used = 0;
- tx_ppdu_info->ppdu_id = ppdu_id;
-
- if (type == DP_MON_TX_PROT_PPDU_INFO)
- pmon->tx_prot_ppdu_info = tx_ppdu_info;
- else
- pmon->tx_data_ppdu_info = tx_ppdu_info;
-
- return tx_ppdu_info;
-}
-
-static struct dp_mon_tx_ppdu_info *
-ath12k_dp_mon_hal_tx_ppdu_info(struct ath12k_mon_data *pmon,
- u16 tlv_tag)
-{
- switch (tlv_tag) {
- case HAL_TX_FES_SETUP:
- case HAL_TX_FLUSH:
- case HAL_PCU_PPDU_SETUP_INIT:
- case HAL_TX_PEER_ENTRY:
- case HAL_TX_QUEUE_EXTENSION:
- case HAL_TX_MPDU_START:
- case HAL_TX_MSDU_START:
- case HAL_TX_DATA:
- case HAL_MON_BUF_ADDR:
- case HAL_TX_MPDU_END:
- case HAL_TX_LAST_MPDU_FETCHED:
- case HAL_TX_LAST_MPDU_END:
- case HAL_COEX_TX_REQ:
- case HAL_TX_RAW_OR_NATIVE_FRAME_SETUP:
- case HAL_SCH_CRITICAL_TLV_REFERENCE:
- case HAL_TX_FES_SETUP_COMPLETE:
- case HAL_TQM_MPDU_GLOBAL_START:
- case HAL_SCHEDULER_END:
- case HAL_TX_FES_STATUS_USER_PPDU:
- break;
- case HAL_TX_FES_STATUS_PROT: {
- if (!pmon->tx_prot_ppdu_info->is_used)
- pmon->tx_prot_ppdu_info->is_used = true;
-
- return pmon->tx_prot_ppdu_info;
- }
- }
-
- if (!pmon->tx_data_ppdu_info->is_used)
- pmon->tx_data_ppdu_info->is_used = true;
-
- return pmon->tx_data_ppdu_info;
-}
-
-#define MAX_MONITOR_HEADER 512
-#define MAX_DUMMY_FRM_BODY 128
-
-struct sk_buff *ath12k_dp_mon_tx_alloc_skb(void)
-{
- struct sk_buff *skb;
-
- skb = dev_alloc_skb(MAX_MONITOR_HEADER + MAX_DUMMY_FRM_BODY);
- if (!skb)
- return NULL;
-
- skb_reserve(skb, MAX_MONITOR_HEADER);
-
- if (!IS_ALIGNED((unsigned long)skb->data, 4))
- skb_pull(skb, PTR_ALIGN(skb->data, 4) - skb->data);
-
- return skb;
-}
-
-static int
-ath12k_dp_mon_tx_gen_cts2self_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
-{
- struct sk_buff *skb;
- struct ieee80211_cts *cts;
-
- skb = ath12k_dp_mon_tx_alloc_skb();
- if (!skb)
- return -ENOMEM;
-
- cts = (struct ieee80211_cts *)skb->data;
- memset(cts, 0, MAX_DUMMY_FRM_BODY);
- cts->frame_control =
- cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS);
- cts->duration = cpu_to_le16(tx_ppdu_info->rx_status.rx_duration);
- memcpy(cts->ra, tx_ppdu_info->rx_status.addr1, sizeof(cts->ra));
-
- skb_put(skb, sizeof(*cts));
- tx_ppdu_info->tx_mon_mpdu->head = skb;
- tx_ppdu_info->tx_mon_mpdu->tail = NULL;
- list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
- &tx_ppdu_info->dp_tx_mon_mpdu_list);
-
- return 0;
-}
-
-static int
-ath12k_dp_mon_tx_gen_rts_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
-{
- struct sk_buff *skb;
- struct ieee80211_rts *rts;
-
- skb = ath12k_dp_mon_tx_alloc_skb();
- if (!skb)
- return -ENOMEM;
-
- rts = (struct ieee80211_rts *)skb->data;
- memset(rts, 0, MAX_DUMMY_FRM_BODY);
- rts->frame_control =
- cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
- rts->duration = cpu_to_le16(tx_ppdu_info->rx_status.rx_duration);
- memcpy(rts->ra, tx_ppdu_info->rx_status.addr1, sizeof(rts->ra));
- memcpy(rts->ta, tx_ppdu_info->rx_status.addr2, sizeof(rts->ta));
-
- skb_put(skb, sizeof(*rts));
- tx_ppdu_info->tx_mon_mpdu->head = skb;
- tx_ppdu_info->tx_mon_mpdu->tail = NULL;
- list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
- &tx_ppdu_info->dp_tx_mon_mpdu_list);
-
- return 0;
-}
-
-static int
-ath12k_dp_mon_tx_gen_3addr_qos_null_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
-{
- struct sk_buff *skb;
- struct ieee80211_qos_hdr *qhdr;
-
- skb = ath12k_dp_mon_tx_alloc_skb();
- if (!skb)
- return -ENOMEM;
-
- qhdr = (struct ieee80211_qos_hdr *)skb->data;
- memset(qhdr, 0, MAX_DUMMY_FRM_BODY);
- qhdr->frame_control =
- cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC);
- qhdr->duration_id = cpu_to_le16(tx_ppdu_info->rx_status.rx_duration);
- memcpy(qhdr->addr1, tx_ppdu_info->rx_status.addr1, ETH_ALEN);
- memcpy(qhdr->addr2, tx_ppdu_info->rx_status.addr2, ETH_ALEN);
- memcpy(qhdr->addr3, tx_ppdu_info->rx_status.addr3, ETH_ALEN);
-
- skb_put(skb, sizeof(*qhdr));
- tx_ppdu_info->tx_mon_mpdu->head = skb;
- tx_ppdu_info->tx_mon_mpdu->tail = NULL;
- list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
- &tx_ppdu_info->dp_tx_mon_mpdu_list);
-
- return 0;
-}
-
-static int
-ath12k_dp_mon_tx_gen_4addr_qos_null_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
-{
- struct sk_buff *skb;
- struct dp_mon_qosframe_addr4 *qhdr;
-
- skb = ath12k_dp_mon_tx_alloc_skb();
- if (!skb)
- return -ENOMEM;
-
- qhdr = (struct dp_mon_qosframe_addr4 *)skb->data;
- memset(qhdr, 0, MAX_DUMMY_FRM_BODY);
- qhdr->frame_control =
- cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC);
- qhdr->duration = cpu_to_le16(tx_ppdu_info->rx_status.rx_duration);
- memcpy(qhdr->addr1, tx_ppdu_info->rx_status.addr1, ETH_ALEN);
- memcpy(qhdr->addr2, tx_ppdu_info->rx_status.addr2, ETH_ALEN);
- memcpy(qhdr->addr3, tx_ppdu_info->rx_status.addr3, ETH_ALEN);
- memcpy(qhdr->addr4, tx_ppdu_info->rx_status.addr4, ETH_ALEN);
-
- skb_put(skb, sizeof(*qhdr));
- tx_ppdu_info->tx_mon_mpdu->head = skb;
- tx_ppdu_info->tx_mon_mpdu->tail = NULL;
- list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
- &tx_ppdu_info->dp_tx_mon_mpdu_list);
-
- return 0;
-}
-
-static int
-ath12k_dp_mon_tx_gen_ack_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
-{
- struct sk_buff *skb;
- struct dp_mon_frame_min_one *fbmhdr;
-
- skb = ath12k_dp_mon_tx_alloc_skb();
- if (!skb)
- return -ENOMEM;
-
- fbmhdr = (struct dp_mon_frame_min_one *)skb->data;
- memset(fbmhdr, 0, MAX_DUMMY_FRM_BODY);
- fbmhdr->frame_control =
- cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_CFACK);
- memcpy(fbmhdr->addr1, tx_ppdu_info->rx_status.addr1, ETH_ALEN);
-
- /* set duration zero for ack frame */
- fbmhdr->duration = 0;
-
- skb_put(skb, sizeof(*fbmhdr));
- tx_ppdu_info->tx_mon_mpdu->head = skb;
- tx_ppdu_info->tx_mon_mpdu->tail = NULL;
- list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
- &tx_ppdu_info->dp_tx_mon_mpdu_list);
-
- return 0;
-}
-
-static int
-ath12k_dp_mon_tx_gen_prot_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
-{
- int ret = 0;
-
- switch (tx_ppdu_info->rx_status.medium_prot_type) {
- case DP_MON_TX_MEDIUM_RTS_LEGACY:
- case DP_MON_TX_MEDIUM_RTS_11AC_STATIC_BW:
- case DP_MON_TX_MEDIUM_RTS_11AC_DYNAMIC_BW:
- ret = ath12k_dp_mon_tx_gen_rts_frame(tx_ppdu_info);
- break;
- case DP_MON_TX_MEDIUM_CTS2SELF:
- ret = ath12k_dp_mon_tx_gen_cts2self_frame(tx_ppdu_info);
- break;
- case DP_MON_TX_MEDIUM_QOS_NULL_NO_ACK_3ADDR:
- ret = ath12k_dp_mon_tx_gen_3addr_qos_null_frame(tx_ppdu_info);
- break;
- case DP_MON_TX_MEDIUM_QOS_NULL_NO_ACK_4ADDR:
- ret = ath12k_dp_mon_tx_gen_4addr_qos_null_frame(tx_ppdu_info);
- break;
- }
-
- return ret;
-}
-
-static enum dp_mon_tx_tlv_status
-ath12k_dp_mon_tx_parse_status_tlv(struct ath12k_base *ab,
- struct ath12k_mon_data *pmon,
- u16 tlv_tag, const void *tlv_data, u32 userid)
-{
- struct dp_mon_tx_ppdu_info *tx_ppdu_info;
- enum dp_mon_tx_tlv_status status = DP_MON_TX_STATUS_PPDU_NOT_DONE;
- u32 info[7];
-
- tx_ppdu_info = ath12k_dp_mon_hal_tx_ppdu_info(pmon, tlv_tag);
-
- switch (tlv_tag) {
- case HAL_TX_FES_SETUP: {
- const struct hal_tx_fes_setup *tx_fes_setup = tlv_data;
-
- info[0] = __le32_to_cpu(tx_fes_setup->info0);
- tx_ppdu_info->ppdu_id = __le32_to_cpu(tx_fes_setup->schedule_id);
- tx_ppdu_info->num_users =
- u32_get_bits(info[0], HAL_TX_FES_SETUP_INFO0_NUM_OF_USERS);
- status = DP_MON_TX_FES_SETUP;
- break;
- }
-
- case HAL_TX_FES_STATUS_END: {
- const struct hal_tx_fes_status_end *tx_fes_status_end = tlv_data;
- u32 tst_15_0, tst_31_16;
-
- info[0] = __le32_to_cpu(tx_fes_status_end->info0);
- tst_15_0 =
- u32_get_bits(info[0],
- HAL_TX_FES_STATUS_END_INFO0_START_TIMESTAMP_15_0);
- tst_31_16 =
- u32_get_bits(info[0],
- HAL_TX_FES_STATUS_END_INFO0_START_TIMESTAMP_31_16);
-
- tx_ppdu_info->rx_status.ppdu_ts = (tst_15_0 | (tst_31_16 << 16));
- status = DP_MON_TX_FES_STATUS_END;
- break;
- }
-
- case HAL_RX_RESPONSE_REQUIRED_INFO: {
- const struct hal_rx_resp_req_info *rx_resp_req_info = tlv_data;
- u32 addr_32;
- u16 addr_16;
-
- info[0] = __le32_to_cpu(rx_resp_req_info->info0);
- info[1] = __le32_to_cpu(rx_resp_req_info->info1);
- info[2] = __le32_to_cpu(rx_resp_req_info->info2);
- info[3] = __le32_to_cpu(rx_resp_req_info->info3);
- info[4] = __le32_to_cpu(rx_resp_req_info->info4);
- info[5] = __le32_to_cpu(rx_resp_req_info->info5);
-
- tx_ppdu_info->rx_status.ppdu_id =
- u32_get_bits(info[0], HAL_RX_RESP_REQ_INFO0_PPDU_ID);
- tx_ppdu_info->rx_status.reception_type =
- u32_get_bits(info[0], HAL_RX_RESP_REQ_INFO0_RECEPTION_TYPE);
- tx_ppdu_info->rx_status.rx_duration =
- u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_DURATION);
- tx_ppdu_info->rx_status.mcs =
- u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_RATE_MCS);
- tx_ppdu_info->rx_status.sgi =
- u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_SGI);
- tx_ppdu_info->rx_status.is_stbc =
- u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_STBC);
- tx_ppdu_info->rx_status.ldpc =
- u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_LDPC);
- tx_ppdu_info->rx_status.is_ampdu =
- u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_IS_AMPDU);
- tx_ppdu_info->rx_status.num_users =
- u32_get_bits(info[2], HAL_RX_RESP_REQ_INFO2_NUM_USER);
-
- addr_32 = u32_get_bits(info[3], HAL_RX_RESP_REQ_INFO3_ADDR1_31_0);
- addr_16 = u32_get_bits(info[3], HAL_RX_RESP_REQ_INFO4_ADDR1_47_32);
- ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr1);
-
- addr_16 = u32_get_bits(info[4], HAL_RX_RESP_REQ_INFO4_ADDR1_15_0);
- addr_32 = u32_get_bits(info[5], HAL_RX_RESP_REQ_INFO5_ADDR1_47_16);
- ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr2);
-
- if (tx_ppdu_info->rx_status.reception_type == 0)
- ath12k_dp_mon_tx_gen_cts2self_frame(tx_ppdu_info);
- status = DP_MON_RX_RESPONSE_REQUIRED_INFO;
- break;
- }
-
- case HAL_PCU_PPDU_SETUP_INIT: {
- const struct hal_tx_pcu_ppdu_setup_init *ppdu_setup = tlv_data;
- u32 addr_32;
- u16 addr_16;
-
- info[0] = __le32_to_cpu(ppdu_setup->info0);
- info[1] = __le32_to_cpu(ppdu_setup->info1);
- info[2] = __le32_to_cpu(ppdu_setup->info2);
- info[3] = __le32_to_cpu(ppdu_setup->info3);
- info[4] = __le32_to_cpu(ppdu_setup->info4);
- info[5] = __le32_to_cpu(ppdu_setup->info5);
- info[6] = __le32_to_cpu(ppdu_setup->info6);
-
- /* protection frame address 1 */
- addr_32 = u32_get_bits(info[1],
- HAL_TX_PPDU_SETUP_INFO1_PROT_FRAME_ADDR1_31_0);
- addr_16 = u32_get_bits(info[2],
- HAL_TX_PPDU_SETUP_INFO2_PROT_FRAME_ADDR1_47_32);
- ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr1);
-
- /* protection frame address 2 */
- addr_16 = u32_get_bits(info[2],
- HAL_TX_PPDU_SETUP_INFO2_PROT_FRAME_ADDR2_15_0);
- addr_32 = u32_get_bits(info[3],
- HAL_TX_PPDU_SETUP_INFO3_PROT_FRAME_ADDR2_47_16);
- ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr2);
-
- /* protection frame address 3 */
- addr_32 = u32_get_bits(info[4],
- HAL_TX_PPDU_SETUP_INFO4_PROT_FRAME_ADDR3_31_0);
- addr_16 = u32_get_bits(info[5],
- HAL_TX_PPDU_SETUP_INFO5_PROT_FRAME_ADDR3_47_32);
- ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr3);
-
- /* protection frame address 4 */
- addr_16 = u32_get_bits(info[5],
- HAL_TX_PPDU_SETUP_INFO5_PROT_FRAME_ADDR4_15_0);
- addr_32 = u32_get_bits(info[6],
- HAL_TX_PPDU_SETUP_INFO6_PROT_FRAME_ADDR4_47_16);
- ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr4);
-
- status = u32_get_bits(info[0],
- HAL_TX_PPDU_SETUP_INFO0_MEDIUM_PROT_TYPE);
- break;
- }
-
- case HAL_TX_QUEUE_EXTENSION: {
- const struct hal_tx_queue_exten *tx_q_exten = tlv_data;
-
- info[0] = __le32_to_cpu(tx_q_exten->info0);
-
- tx_ppdu_info->rx_status.frame_control =
- u32_get_bits(info[0],
- HAL_TX_Q_EXT_INFO0_FRAME_CTRL);
- tx_ppdu_info->rx_status.fc_valid = true;
- break;
- }
-
- case HAL_TX_FES_STATUS_START: {
- const struct hal_tx_fes_status_start *tx_fes_start = tlv_data;
-
- info[0] = __le32_to_cpu(tx_fes_start->info0);
-
- tx_ppdu_info->rx_status.medium_prot_type =
- u32_get_bits(info[0],
- HAL_TX_FES_STATUS_START_INFO0_MEDIUM_PROT_TYPE);
- break;
- }
-
- case HAL_TX_FES_STATUS_PROT: {
- const struct hal_tx_fes_status_prot *tx_fes_status = tlv_data;
- u32 start_timestamp;
- u32 end_timestamp;
-
- info[0] = __le32_to_cpu(tx_fes_status->info0);
- info[1] = __le32_to_cpu(tx_fes_status->info1);
-
- start_timestamp =
- u32_get_bits(info[0],
- HAL_TX_FES_STAT_PROT_INFO0_STRT_FRM_TS_15_0);
- start_timestamp |=
- u32_get_bits(info[0],
- HAL_TX_FES_STAT_PROT_INFO0_STRT_FRM_TS_31_16) << 15;
- end_timestamp =
- u32_get_bits(info[1],
- HAL_TX_FES_STAT_PROT_INFO1_END_FRM_TS_15_0);
- end_timestamp |=
- u32_get_bits(info[1],
- HAL_TX_FES_STAT_PROT_INFO1_END_FRM_TS_31_16) << 15;
- tx_ppdu_info->rx_status.rx_duration = end_timestamp - start_timestamp;
-
- ath12k_dp_mon_tx_gen_prot_frame(tx_ppdu_info);
- break;
- }
-
- case HAL_TX_FES_STATUS_START_PPDU:
- case HAL_TX_FES_STATUS_START_PROT: {
- const struct hal_tx_fes_status_start_prot *tx_fes_stat_start = tlv_data;
- u64 ppdu_ts;
-
- info[0] = __le32_to_cpu(tx_fes_stat_start->info0);
-
- tx_ppdu_info->rx_status.ppdu_ts =
- u32_get_bits(info[0],
- HAL_TX_FES_STAT_STRT_INFO0_PROT_TS_LOWER_32);
- ppdu_ts = (u32_get_bits(info[1],
- HAL_TX_FES_STAT_STRT_INFO1_PROT_TS_UPPER_32));
- tx_ppdu_info->rx_status.ppdu_ts |= ppdu_ts << 32;
- break;
- }
-
- case HAL_TX_FES_STATUS_USER_PPDU: {
- const struct hal_tx_fes_status_user_ppdu *tx_fes_usr_ppdu = tlv_data;
-
- info[0] = __le32_to_cpu(tx_fes_usr_ppdu->info0);
-
- tx_ppdu_info->rx_status.rx_duration =
- u32_get_bits(info[0],
- HAL_TX_FES_STAT_USR_PPDU_INFO0_DURATION);
- break;
- }
-
- case HAL_MACTX_HE_SIG_A_SU:
- ath12k_dp_mon_parse_he_sig_su(tlv_data, &tx_ppdu_info->rx_status);
- break;
-
- case HAL_MACTX_HE_SIG_A_MU_DL:
- ath12k_dp_mon_parse_he_sig_mu(tlv_data, &tx_ppdu_info->rx_status);
- break;
-
- case HAL_MACTX_HE_SIG_B1_MU:
- ath12k_dp_mon_parse_he_sig_b1_mu(tlv_data, &tx_ppdu_info->rx_status);
- break;
-
- case HAL_MACTX_HE_SIG_B2_MU:
- ath12k_dp_mon_parse_he_sig_b2_mu(tlv_data, &tx_ppdu_info->rx_status);
- break;
-
- case HAL_MACTX_HE_SIG_B2_OFDMA:
- ath12k_dp_mon_parse_he_sig_b2_ofdma(tlv_data, &tx_ppdu_info->rx_status);
- break;
-
- case HAL_MACTX_VHT_SIG_A:
- ath12k_dp_mon_parse_vht_sig_a(tlv_data, &tx_ppdu_info->rx_status);
- break;
-
- case HAL_MACTX_L_SIG_A:
- ath12k_dp_mon_parse_l_sig_a(tlv_data, &tx_ppdu_info->rx_status);
- break;
-
- case HAL_MACTX_L_SIG_B:
- ath12k_dp_mon_parse_l_sig_b(tlv_data, &tx_ppdu_info->rx_status);
- break;
-
- case HAL_RX_FRAME_BITMAP_ACK: {
- const struct hal_rx_frame_bitmap_ack *fbm_ack = tlv_data;
- u32 addr_32;
- u16 addr_16;
-
- info[0] = __le32_to_cpu(fbm_ack->info0);
- info[1] = __le32_to_cpu(fbm_ack->info1);
-
- addr_32 = u32_get_bits(info[0],
- HAL_RX_FBM_ACK_INFO0_ADDR1_31_0);
- addr_16 = u32_get_bits(info[1],
- HAL_RX_FBM_ACK_INFO1_ADDR1_47_32);
- ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr1);
-
- ath12k_dp_mon_tx_gen_ack_frame(tx_ppdu_info);
- break;
- }
-
- case HAL_MACTX_PHY_DESC: {
- const struct hal_tx_phy_desc *tx_phy_desc = tlv_data;
-
- info[0] = __le32_to_cpu(tx_phy_desc->info0);
- info[1] = __le32_to_cpu(tx_phy_desc->info1);
- info[2] = __le32_to_cpu(tx_phy_desc->info2);
- info[3] = __le32_to_cpu(tx_phy_desc->info3);
-
- tx_ppdu_info->rx_status.beamformed =
- u32_get_bits(info[0],
- HAL_TX_PHY_DESC_INFO0_BF_TYPE);
- tx_ppdu_info->rx_status.preamble_type =
- u32_get_bits(info[0],
- HAL_TX_PHY_DESC_INFO0_PREAMBLE_11B);
- tx_ppdu_info->rx_status.mcs =
- u32_get_bits(info[1],
- HAL_TX_PHY_DESC_INFO1_MCS);
- tx_ppdu_info->rx_status.ltf_size =
- u32_get_bits(info[3],
- HAL_TX_PHY_DESC_INFO3_LTF_SIZE);
- tx_ppdu_info->rx_status.nss =
- u32_get_bits(info[2],
- HAL_TX_PHY_DESC_INFO2_NSS);
- tx_ppdu_info->rx_status.chan_num =
- u32_get_bits(info[3],
- HAL_TX_PHY_DESC_INFO3_ACTIVE_CHANNEL);
- tx_ppdu_info->rx_status.bw =
- u32_get_bits(info[0],
- HAL_TX_PHY_DESC_INFO0_BANDWIDTH);
- break;
- }
-
- case HAL_TX_MPDU_START: {
- struct dp_mon_mpdu *mon_mpdu = tx_ppdu_info->tx_mon_mpdu;
-
- mon_mpdu = kzalloc(sizeof(*mon_mpdu), GFP_ATOMIC);
- if (!mon_mpdu)
- return DP_MON_TX_STATUS_PPDU_NOT_DONE;
- status = DP_MON_TX_MPDU_START;
- break;
- }
-
- case HAL_TX_MPDU_END:
- list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
- &tx_ppdu_info->dp_tx_mon_mpdu_list);
- break;
- }
-
- return status;
-}
-
-enum dp_mon_tx_tlv_status
-ath12k_dp_mon_tx_status_get_num_user(u16 tlv_tag,
- struct hal_tlv_hdr *tx_tlv,
- u8 *num_users)
-{
- u32 tlv_status = DP_MON_TX_STATUS_PPDU_NOT_DONE;
- u32 info0;
-
- switch (tlv_tag) {
- case HAL_TX_FES_SETUP: {
- struct hal_tx_fes_setup *tx_fes_setup =
- (struct hal_tx_fes_setup *)tx_tlv;
-
- info0 = __le32_to_cpu(tx_fes_setup->info0);
-
- *num_users = u32_get_bits(info0, HAL_TX_FES_SETUP_INFO0_NUM_OF_USERS);
- tlv_status = DP_MON_TX_FES_SETUP;
- break;
- }
-
- case HAL_RX_RESPONSE_REQUIRED_INFO: {
- /* TODO: need to update *num_users */
- tlv_status = DP_MON_RX_RESPONSE_REQUIRED_INFO;
- break;
- }
- }
-
- return tlv_status;
-}
-
-static void
-ath12k_dp_mon_tx_process_ppdu_info(struct ath12k *ar,
- struct napi_struct *napi,
- struct dp_mon_tx_ppdu_info *tx_ppdu_info)
-{
- struct dp_mon_mpdu *tmp, *mon_mpdu;
-
- list_for_each_entry_safe(mon_mpdu, tmp,
- &tx_ppdu_info->dp_tx_mon_mpdu_list, list) {
- list_del(&mon_mpdu->list);
-
- if (mon_mpdu->head)
- ath12k_dp_mon_rx_deliver(ar, mon_mpdu,
- &tx_ppdu_info->rx_status, napi);
-
- kfree(mon_mpdu);
- }
-}
-
-enum hal_rx_mon_status
-ath12k_dp_mon_tx_parse_mon_status(struct ath12k *ar,
- struct ath12k_mon_data *pmon,
- struct sk_buff *skb,
- struct napi_struct *napi,
- u32 ppdu_id)
-{
- struct ath12k_base *ab = ar->ab;
- struct dp_mon_tx_ppdu_info *tx_prot_ppdu_info, *tx_data_ppdu_info;
- struct hal_tlv_hdr *tlv;
- u8 *ptr = skb->data;
- u16 tlv_tag;
- u16 tlv_len;
- u32 tlv_userid = 0;
- u8 num_user;
- u32 tlv_status = DP_MON_TX_STATUS_PPDU_NOT_DONE;
-
- tx_prot_ppdu_info = ath12k_dp_mon_tx_get_ppdu_info(pmon, ppdu_id,
- DP_MON_TX_PROT_PPDU_INFO);
- if (!tx_prot_ppdu_info)
- return -ENOMEM;
-
- tlv = (struct hal_tlv_hdr *)ptr;
- tlv_tag = le32_get_bits(tlv->tl, HAL_TLV_HDR_TAG);
-
- tlv_status = ath12k_dp_mon_tx_status_get_num_user(tlv_tag, tlv, &num_user);
- if (tlv_status == DP_MON_TX_STATUS_PPDU_NOT_DONE || !num_user)
- return -EINVAL;
-
- tx_data_ppdu_info = ath12k_dp_mon_tx_get_ppdu_info(pmon, ppdu_id,
- DP_MON_TX_DATA_PPDU_INFO);
- if (!tx_data_ppdu_info)
- return -ENOMEM;
-
- do {
- tlv = (struct hal_tlv_hdr *)ptr;
- tlv_tag = le32_get_bits(tlv->tl, HAL_TLV_HDR_TAG);
- tlv_len = le32_get_bits(tlv->tl, HAL_TLV_HDR_LEN);
- tlv_userid = le32_get_bits(tlv->tl, HAL_TLV_USR_ID);
-
- tlv_status = ath12k_dp_mon_tx_parse_status_tlv(ab, pmon,
- tlv_tag, ptr,
- tlv_userid);
- ptr += tlv_len;
- ptr = PTR_ALIGN(ptr, HAL_TLV_ALIGN);
- if ((ptr - skb->data) >= DP_TX_MONITOR_BUF_SIZE)
- break;
- } while (tlv_status != DP_MON_TX_FES_STATUS_END);
-
- ath12k_dp_mon_tx_process_ppdu_info(ar, napi, tx_data_ppdu_info);
- ath12k_dp_mon_tx_process_ppdu_info(ar, napi, tx_prot_ppdu_info);
-
- return tlv_status;
-}
-
static void
ath12k_dp_mon_rx_update_peer_rate_table_stats(struct ath12k_rx_peer_stats *rx_stats,
struct hal_rx_mon_ppdu_info *ppdu_info,
@@ -3465,6 +830,9 @@ ath12k_dp_mon_rx_update_peer_rate_table_stats(struct ath12k_rx_peer_stats *rx_st
u32 gi_idx = ppdu_info->gi;
u32 len;
+ if (!rx_stats)
+ return;
+
if (mcs_idx > HAL_RX_MAX_MCS_HT || nss_idx >= HAL_RX_MAX_NSS ||
bw_idx >= HAL_RX_BW_MAX || gi_idx >= HAL_RX_GI_MAX) {
return;
@@ -3485,15 +853,14 @@ ath12k_dp_mon_rx_update_peer_rate_table_stats(struct ath12k_rx_peer_stats *rx_st
stats->rx_rate[bw_idx][gi_idx][nss_idx][mcs_idx] += len;
}
-static void ath12k_dp_mon_rx_update_peer_su_stats(struct ath12k *ar,
- struct ath12k_link_sta *arsta,
- struct hal_rx_mon_ppdu_info *ppdu_info)
+void ath12k_dp_mon_rx_update_peer_su_stats(struct ath12k_dp_link_peer *peer,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
{
- struct ath12k_rx_peer_stats *rx_stats = arsta->rx_stats;
+ struct ath12k_rx_peer_stats *rx_stats = peer->peer_stats.rx_stats;
u32 num_msdu;
- arsta->rssi_comb = ppdu_info->rssi_comb;
- ewma_avg_rssi_add(&arsta->avg_rssi, ppdu_info->rssi_comb);
+ peer->rssi_comb = ppdu_info->rssi_comb;
+ ewma_avg_rssi_add(&peer->avg_rssi, ppdu_info->rssi_comb);
if (!rx_stats)
return;
@@ -3541,7 +908,7 @@ static void ath12k_dp_mon_rx_update_peer_su_stats(struct ath12k *ar,
rx_stats->dcm_count += ppdu_info->dcm;
rx_stats->rx_duration += ppdu_info->rx_duration;
- arsta->rx_duration = rx_stats->rx_duration;
+ peer->rx_duration = rx_stats->rx_duration;
if (ppdu_info->nss > 0 && ppdu_info->nss <= HAL_RX_MAX_NSS) {
rx_stats->pkt_stats.nss_count[ppdu_info->nss - 1] += num_msdu;
@@ -3594,6 +961,7 @@ static void ath12k_dp_mon_rx_update_peer_su_stats(struct ath12k *ar,
ath12k_dp_mon_rx_update_peer_rate_table_stats(rx_stats, ppdu_info,
NULL, num_msdu);
}
+EXPORT_SYMBOL(ath12k_dp_mon_rx_update_peer_su_stats);
void ath12k_dp_mon_rx_process_ulofdma(struct hal_rx_mon_ppdu_info *ppdu_info)
{
@@ -3642,39 +1010,33 @@ void ath12k_dp_mon_rx_process_ulofdma(struct hal_rx_mon_ppdu_info *ppdu_info)
}
ppdu_info->ldpc = 1;
}
+EXPORT_SYMBOL(ath12k_dp_mon_rx_process_ulofdma);
static void
-ath12k_dp_mon_rx_update_user_stats(struct ath12k *ar,
+ath12k_dp_mon_rx_update_user_stats(struct ath12k_base *ab,
struct hal_rx_mon_ppdu_info *ppdu_info,
u32 uid)
{
- 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;
+ struct ath12k_dp_link_peer *peer;
u32 num_msdu;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
if (user_stats->ast_index == 0 || user_stats->ast_index == 0xFFFF)
return;
- peer = ath12k_peer_find_by_ast(ar->ab, user_stats->ast_index);
+ peer = ath12k_dp_link_peer_find_by_ast(dp, user_stats->ast_index);
if (!peer) {
- ath12k_warn(ar->ab, "peer ast idx %d can't be found\n",
+ ath12k_warn(ab, "peer ast idx %d can't be found\n",
user_stats->ast_index);
return;
}
- arsta = ath12k_peer_get_link_sta(ar->ab, peer);
- if (!arsta) {
- ath12k_warn(ar->ab, "link sta not found on peer %pM id %d\n",
- peer->addr, peer->peer_id);
- return;
- }
-
- arsta->rssi_comb = ppdu_info->rssi_comb;
- ewma_avg_rssi_add(&arsta->avg_rssi, ppdu_info->rssi_comb);
- rx_stats = arsta->rx_stats;
+ peer->rssi_comb = ppdu_info->rssi_comb;
+ ewma_avg_rssi_add(&peer->avg_rssi, ppdu_info->rssi_comb);
+ rx_stats = peer->peer_stats.rx_stats;
if (!rx_stats)
return;
@@ -3718,7 +1080,7 @@ ath12k_dp_mon_rx_update_user_stats(struct ath12k *ar,
rx_stats->ru_alloc_cnt[user_stats->ul_ofdma_ru_size] += num_msdu;
rx_stats->rx_duration += ppdu_info->rx_duration;
- arsta->rx_duration = rx_stats->rx_duration;
+ peer->rx_duration = rx_stats->rx_duration;
if (user_stats->nss > 0 && user_stats->nss <= HAL_RX_MAX_NSS) {
rx_stats->pkt_stats.nss_count[user_stats->nss - 1] += num_msdu;
@@ -3749,8 +1111,8 @@ ath12k_dp_mon_rx_update_user_stats(struct ath12k *ar,
user_stats, num_msdu);
}
-static void
-ath12k_dp_mon_rx_update_peer_mu_stats(struct ath12k *ar,
+void
+ath12k_dp_mon_rx_update_peer_mu_stats(struct ath12k_base *ab,
struct hal_rx_mon_ppdu_info *ppdu_info)
{
u32 num_users, i;
@@ -3760,679 +1122,6 @@ ath12k_dp_mon_rx_update_peer_mu_stats(struct ath12k *ar,
num_users = HAL_MAX_UL_MU_USERS;
for (i = 0; i < num_users; i++)
- ath12k_dp_mon_rx_update_user_stats(ar, ppdu_info, i);
-}
-
-static void
-ath12k_dp_mon_rx_memset_ppdu_info(struct hal_rx_mon_ppdu_info *ppdu_info)
-{
- memset(ppdu_info, 0, sizeof(*ppdu_info));
- ppdu_info->peer_id = HAL_INVALID_PEERID;
-}
-
-int ath12k_dp_mon_srng_process(struct ath12k *ar, int *budget,
- struct napi_struct *napi)
-{
- struct ath12k_base *ab = ar->ab;
- struct ath12k_pdev_dp *pdev_dp = &ar->dp;
- struct ath12k_mon_data *pmon = (struct ath12k_mon_data *)&pdev_dp->mon_data;
- struct hal_rx_mon_ppdu_info *ppdu_info = &pmon->mon_ppdu_info;
- struct ath12k_dp *dp = &ab->dp;
- struct hal_mon_dest_desc *mon_dst_desc;
- struct sk_buff *skb;
- struct ath12k_skb_rxcb *rxcb;
- struct dp_srng *mon_dst_ring;
- struct hal_srng *srng;
- struct dp_rxdma_mon_ring *buf_ring;
- struct ath12k_link_sta *arsta;
- struct ath12k_peer *peer;
- struct sk_buff_head skb_list;
- u64 cookie;
- int num_buffs_reaped = 0, srng_id, buf_id;
- u32 hal_status, end_offset, info0, end_reason;
- u8 pdev_idx = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, ar->pdev_idx);
-
- __skb_queue_head_init(&skb_list);
- srng_id = ath12k_hw_mac_id_to_srng_id(ab->hw_params, pdev_idx);
- mon_dst_ring = &pdev_dp->rxdma_mon_dst_ring[srng_id];
- buf_ring = &dp->rxdma_mon_buf_ring;
-
- srng = &ab->hal.srng_list[mon_dst_ring->ring_id];
- spin_lock_bh(&srng->lock);
- ath12k_hal_srng_access_begin(ab, srng);
-
- while (likely(*budget)) {
- mon_dst_desc = ath12k_hal_srng_dst_peek(ab, srng);
- if (unlikely(!mon_dst_desc))
- break;
-
- /* In case of empty descriptor, the cookie in the ring descriptor
- * is invalid. Therefore, this entry is skipped, and ring processing
- * continues.
- */
- info0 = le32_to_cpu(mon_dst_desc->info0);
- if (u32_get_bits(info0, HAL_MON_DEST_INFO0_EMPTY_DESC))
- goto move_next;
-
- cookie = le32_to_cpu(mon_dst_desc->cookie);
- buf_id = u32_get_bits(cookie, DP_RXDMA_BUF_COOKIE_BUF_ID);
-
- spin_lock_bh(&buf_ring->idr_lock);
- skb = idr_remove(&buf_ring->bufs_idr, buf_id);
- spin_unlock_bh(&buf_ring->idr_lock);
-
- if (unlikely(!skb)) {
- ath12k_warn(ab, "monitor destination with invalid buf_id %d\n",
- buf_id);
- goto move_next;
- }
-
- rxcb = ATH12K_SKB_RXCB(skb);
- dma_unmap_single(ab->dev, rxcb->paddr,
- skb->len + skb_tailroom(skb),
- DMA_FROM_DEVICE);
-
- end_reason = u32_get_bits(info0, HAL_MON_DEST_INFO0_END_REASON);
-
- /* HAL_MON_FLUSH_DETECTED implies that an rx flush received at the end of
- * rx PPDU and HAL_MON_PPDU_TRUNCATED implies that the PPDU got
- * truncated due to a system level error. In both the cases, buffer data
- * can be discarded
- */
- if ((end_reason == HAL_MON_FLUSH_DETECTED) ||
- (end_reason == HAL_MON_PPDU_TRUNCATED)) {
- ath12k_dbg(ab, ATH12K_DBG_DATA,
- "Monitor dest descriptor end reason %d", end_reason);
- dev_kfree_skb_any(skb);
- goto move_next;
- }
-
- /* Calculate the budget when the ring descriptor with the
- * HAL_MON_END_OF_PPDU to ensure that one PPDU worth of data is always
- * reaped. This helps to efficiently utilize the NAPI budget.
- */
- if (end_reason == HAL_MON_END_OF_PPDU) {
- *budget -= 1;
- rxcb->is_end_of_ppdu = true;
- }
-
- end_offset = u32_get_bits(info0, HAL_MON_DEST_INFO0_END_OFFSET);
- if (likely(end_offset <= DP_RX_BUFFER_SIZE)) {
- skb_put(skb, end_offset);
- } else {
- ath12k_warn(ab,
- "invalid offset on mon stats destination %u\n",
- end_offset);
- skb_put(skb, DP_RX_BUFFER_SIZE);
- }
-
- __skb_queue_tail(&skb_list, skb);
-
-move_next:
- ath12k_dp_mon_buf_replenish(ab, buf_ring, 1);
- ath12k_hal_srng_dst_get_next_entry(ab, srng);
- num_buffs_reaped++;
- }
-
- ath12k_hal_srng_access_end(ab, srng);
- spin_unlock_bh(&srng->lock);
-
- if (!num_buffs_reaped)
- return 0;
-
- /* In some cases, one PPDU worth of data can be spread across multiple NAPI
- * schedules, To avoid losing existing parsed ppdu_info information, skip
- * the memset of the ppdu_info structure and continue processing it.
- */
- if (!ppdu_info->ppdu_continuation)
- ath12k_dp_mon_rx_memset_ppdu_info(ppdu_info);
-
- while ((skb = __skb_dequeue(&skb_list))) {
- hal_status = ath12k_dp_mon_rx_parse_mon_status(ar, pmon, skb, napi);
- if (hal_status != HAL_RX_MON_STATUS_PPDU_DONE) {
- ppdu_info->ppdu_continuation = true;
- dev_kfree_skb_any(skb);
- continue;
- }
-
- if (ppdu_info->peer_id == HAL_INVALID_PEERID)
- goto free_skb;
-
- rcu_read_lock();
- spin_lock_bh(&ab->base_lock);
- peer = ath12k_peer_find_by_id(ab, ppdu_info->peer_id);
- if (!peer || !peer->sta) {
- ath12k_dbg(ab, ATH12K_DBG_DATA,
- "failed to find the peer with monitor peer_id %d\n",
- ppdu_info->peer_id);
- goto next_skb;
- }
-
- if (ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_SU) {
- arsta = ath12k_peer_get_link_sta(ar->ab, peer);
- if (!arsta) {
- ath12k_warn(ar->ab, "link sta not found on peer %pM id %d\n",
- peer->addr, peer->peer_id);
- spin_unlock_bh(&ab->base_lock);
- rcu_read_unlock();
- dev_kfree_skb_any(skb);
- continue;
- }
- ath12k_dp_mon_rx_update_peer_su_stats(ar, arsta,
- ppdu_info);
- } else if ((ppdu_info->fc_valid) &&
- (ppdu_info->ast_index != HAL_AST_IDX_INVALID)) {
- ath12k_dp_mon_rx_process_ulofdma(ppdu_info);
- ath12k_dp_mon_rx_update_peer_mu_stats(ar, ppdu_info);
- }
-
-next_skb:
- spin_unlock_bh(&ab->base_lock);
- rcu_read_unlock();
-free_skb:
- dev_kfree_skb_any(skb);
- ath12k_dp_mon_rx_memset_ppdu_info(ppdu_info);
- }
-
- return num_buffs_reaped;
-}
-
-static int ath12k_dp_rx_reap_mon_status_ring(struct ath12k_base *ab, int mac_id,
- int *budget, struct sk_buff_head *skb_list)
-{
- const struct ath12k_hw_hal_params *hal_params;
- int buf_id, srng_id, num_buffs_reaped = 0;
- enum dp_mon_status_buf_state reap_status;
- struct dp_rxdma_mon_ring *rx_ring;
- struct ath12k_mon_data *pmon;
- struct ath12k_skb_rxcb *rxcb;
- struct hal_tlv_64_hdr *tlv;
- void *rx_mon_status_desc;
- struct hal_srng *srng;
- struct ath12k_dp *dp;
- struct sk_buff *skb;
- struct ath12k *ar;
- dma_addr_t paddr;
- u32 cookie;
- u8 rbm;
-
- ar = ab->pdevs[ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id)].ar;
- dp = &ab->dp;
- pmon = &ar->dp.mon_data;
- srng_id = ath12k_hw_mac_id_to_srng_id(ab->hw_params, mac_id);
- rx_ring = &dp->rx_mon_status_refill_ring[srng_id];
-
- srng = &ab->hal.srng_list[rx_ring->refill_buf_ring.ring_id];
-
- spin_lock_bh(&srng->lock);
-
- ath12k_hal_srng_access_begin(ab, srng);
-
- while (*budget) {
- *budget -= 1;
- rx_mon_status_desc = ath12k_hal_srng_src_peek(ab, srng);
- if (!rx_mon_status_desc) {
- pmon->buf_state = DP_MON_STATUS_REPLINISH;
- break;
- }
- ath12k_hal_rx_buf_addr_info_get(rx_mon_status_desc, &paddr,
- &cookie, &rbm);
- if (paddr) {
- buf_id = u32_get_bits(cookie, DP_RXDMA_BUF_COOKIE_BUF_ID);
-
- spin_lock_bh(&rx_ring->idr_lock);
- skb = idr_find(&rx_ring->bufs_idr, buf_id);
- spin_unlock_bh(&rx_ring->idr_lock);
-
- if (!skb) {
- ath12k_warn(ab, "rx monitor status with invalid buf_id %d\n",
- buf_id);
- pmon->buf_state = DP_MON_STATUS_REPLINISH;
- goto move_next;
- }
-
- rxcb = ATH12K_SKB_RXCB(skb);
-
- dma_sync_single_for_cpu(ab->dev, rxcb->paddr,
- skb->len + skb_tailroom(skb),
- DMA_FROM_DEVICE);
-
- tlv = (struct hal_tlv_64_hdr *)skb->data;
- if (le64_get_bits(tlv->tl, HAL_TLV_HDR_TAG) !=
- HAL_RX_STATUS_BUFFER_DONE) {
- pmon->buf_state = DP_MON_STATUS_NO_DMA;
- ath12k_warn(ab,
- "mon status DONE not set %llx, buf_id %d\n",
- le64_get_bits(tlv->tl, HAL_TLV_HDR_TAG),
- buf_id);
- /* RxDMA status done bit might not be set even
- * though tp is moved by HW.
- */
-
- /* If done status is missing:
- * 1. As per MAC team's suggestion,
- * when HP + 1 entry is peeked and if DMA
- * is not done and if HP + 2 entry's DMA done
- * is set. skip HP + 1 entry and
- * start processing in next interrupt.
- * 2. If HP + 2 entry's DMA done is not set,
- * poll onto HP + 1 entry DMA done to be set.
- * Check status for same buffer for next time
- * dp_rx_mon_status_srng_process
- */
- reap_status = ath12k_dp_rx_mon_buf_done(ab, srng,
- rx_ring);
- if (reap_status == DP_MON_STATUS_NO_DMA)
- continue;
-
- spin_lock_bh(&rx_ring->idr_lock);
- idr_remove(&rx_ring->bufs_idr, buf_id);
- spin_unlock_bh(&rx_ring->idr_lock);
-
- dma_unmap_single(ab->dev, rxcb->paddr,
- skb->len + skb_tailroom(skb),
- DMA_FROM_DEVICE);
-
- dev_kfree_skb_any(skb);
- pmon->buf_state = DP_MON_STATUS_REPLINISH;
- goto move_next;
- }
-
- spin_lock_bh(&rx_ring->idr_lock);
- idr_remove(&rx_ring->bufs_idr, buf_id);
- spin_unlock_bh(&rx_ring->idr_lock);
-
- dma_unmap_single(ab->dev, rxcb->paddr,
- skb->len + skb_tailroom(skb),
- DMA_FROM_DEVICE);
-
- if (ath12k_dp_pkt_set_pktlen(skb, RX_MON_STATUS_BUF_SIZE)) {
- dev_kfree_skb_any(skb);
- goto move_next;
- }
- __skb_queue_tail(skb_list, skb);
- } else {
- pmon->buf_state = DP_MON_STATUS_REPLINISH;
- }
-move_next:
- skb = ath12k_dp_rx_alloc_mon_status_buf(ab, rx_ring,
- &buf_id);
-
- if (!skb) {
- ath12k_warn(ab, "failed to alloc buffer for status ring\n");
- hal_params = ab->hw_params->hal_params;
- ath12k_hal_rx_buf_addr_info_set(rx_mon_status_desc, 0, 0,
- hal_params->rx_buf_rbm);
- num_buffs_reaped++;
- break;
- }
- rxcb = ATH12K_SKB_RXCB(skb);
-
- cookie = u32_encode_bits(mac_id, DP_RXDMA_BUF_COOKIE_PDEV_ID) |
- u32_encode_bits(buf_id, DP_RXDMA_BUF_COOKIE_BUF_ID);
-
- ath12k_hal_rx_buf_addr_info_set(rx_mon_status_desc, rxcb->paddr,
- cookie,
- ab->hw_params->hal_params->rx_buf_rbm);
- ath12k_hal_srng_src_get_next_entry(ab, srng);
- num_buffs_reaped++;
- }
- ath12k_hal_srng_access_end(ab, srng);
- spin_unlock_bh(&srng->lock);
-
- return num_buffs_reaped;
-}
-
-static u32
-ath12k_dp_rx_mon_mpdu_pop(struct ath12k *ar, int mac_id,
- void *ring_entry, struct sk_buff **head_msdu,
- struct sk_buff **tail_msdu,
- struct list_head *used_list,
- u32 *npackets, u32 *ppdu_id)
-{
- struct ath12k_mon_data *pmon = (struct ath12k_mon_data *)&ar->dp.mon_data;
- struct ath12k_buffer_addr *p_buf_addr_info, *p_last_buf_addr_info;
- u32 msdu_ppdu_id = 0, msdu_cnt = 0, total_len = 0, frag_len = 0;
- u32 rx_buf_size, rx_pkt_offset, sw_cookie;
- bool is_frag, is_first_msdu, drop_mpdu = false;
- struct hal_reo_entrance_ring *ent_desc =
- (struct hal_reo_entrance_ring *)ring_entry;
- u32 rx_bufs_used = 0, i = 0, desc_bank = 0;
- struct hal_rx_desc *rx_desc, *tail_rx_desc;
- struct hal_rx_msdu_link *msdu_link_desc;
- struct sk_buff *msdu = NULL, *last = NULL;
- struct ath12k_rx_desc_info *desc_info;
- struct ath12k_buffer_addr buf_info;
- struct hal_rx_msdu_list msdu_list;
- struct ath12k_skb_rxcb *rxcb;
- u16 num_msdus = 0;
- dma_addr_t paddr;
- u8 rbm;
-
- ath12k_hal_rx_reo_ent_buf_paddr_get(ring_entry, &paddr,
- &sw_cookie,
- &p_last_buf_addr_info, &rbm,
- &msdu_cnt);
-
- spin_lock_bh(&pmon->mon_lock);
-
- if (le32_get_bits(ent_desc->info1,
- HAL_REO_ENTR_RING_INFO1_RXDMA_PUSH_REASON) ==
- HAL_REO_DEST_RING_PUSH_REASON_ERR_DETECTED) {
- u8 rxdma_err = le32_get_bits(ent_desc->info1,
- HAL_REO_ENTR_RING_INFO1_RXDMA_ERROR_CODE);
- if (rxdma_err == HAL_REO_ENTR_RING_RXDMA_ECODE_FLUSH_REQUEST_ERR ||
- rxdma_err == HAL_REO_ENTR_RING_RXDMA_ECODE_MPDU_LEN_ERR ||
- rxdma_err == HAL_REO_ENTR_RING_RXDMA_ECODE_OVERFLOW_ERR) {
- drop_mpdu = true;
- pmon->rx_mon_stats.dest_mpdu_drop++;
- }
- }
-
- is_frag = false;
- is_first_msdu = true;
- rx_pkt_offset = sizeof(struct hal_rx_desc);
-
- do {
- if (pmon->mon_last_linkdesc_paddr == paddr) {
- pmon->rx_mon_stats.dup_mon_linkdesc_cnt++;
- spin_unlock_bh(&pmon->mon_lock);
- return rx_bufs_used;
- }
-
- desc_bank = u32_get_bits(sw_cookie, DP_LINK_DESC_BANK_MASK);
- msdu_link_desc =
- ar->ab->dp.link_desc_banks[desc_bank].vaddr +
- (paddr - ar->ab->dp.link_desc_banks[desc_bank].paddr);
-
- ath12k_hal_rx_msdu_list_get(ar, msdu_link_desc, &msdu_list,
- &num_msdus);
- desc_info = ath12k_dp_get_rx_desc(ar->ab,
- msdu_list.sw_cookie[num_msdus - 1]);
- tail_rx_desc = (struct hal_rx_desc *)(desc_info->skb)->data;
-
- for (i = 0; i < num_msdus; i++) {
- u32 l2_hdr_offset;
-
- if (pmon->mon_last_buf_cookie == msdu_list.sw_cookie[i]) {
- ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
- "i %d last_cookie %d is same\n",
- i, pmon->mon_last_buf_cookie);
- drop_mpdu = true;
- pmon->rx_mon_stats.dup_mon_buf_cnt++;
- continue;
- }
-
- desc_info =
- ath12k_dp_get_rx_desc(ar->ab, msdu_list.sw_cookie[i]);
- msdu = desc_info->skb;
-
- if (!msdu) {
- ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
- "msdu_pop: invalid msdu (%d/%d)\n",
- i + 1, num_msdus);
- goto next_msdu;
- }
- rxcb = ATH12K_SKB_RXCB(msdu);
- if (rxcb->paddr != msdu_list.paddr[i]) {
- ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
- "i %d paddr %lx != %lx\n",
- i, (unsigned long)rxcb->paddr,
- (unsigned long)msdu_list.paddr[i]);
- drop_mpdu = true;
- continue;
- }
- if (!rxcb->unmapped) {
- dma_unmap_single(ar->ab->dev, rxcb->paddr,
- msdu->len +
- skb_tailroom(msdu),
- DMA_FROM_DEVICE);
- rxcb->unmapped = 1;
- }
- if (drop_mpdu) {
- ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
- "i %d drop msdu %p *ppdu_id %x\n",
- i, msdu, *ppdu_id);
- dev_kfree_skb_any(msdu);
- msdu = NULL;
- goto next_msdu;
- }
-
- rx_desc = (struct hal_rx_desc *)msdu->data;
- l2_hdr_offset = ath12k_dp_rx_h_l3pad(ar->ab, tail_rx_desc);
- if (is_first_msdu) {
- if (!ath12k_dp_rxdesc_mpdu_valid(ar->ab, rx_desc)) {
- drop_mpdu = true;
- dev_kfree_skb_any(msdu);
- msdu = NULL;
- pmon->mon_last_linkdesc_paddr = paddr;
- goto next_msdu;
- }
- msdu_ppdu_id =
- ath12k_dp_rxdesc_get_ppduid(ar->ab, rx_desc);
-
- if (ath12k_dp_mon_comp_ppduid(msdu_ppdu_id,
- ppdu_id)) {
- spin_unlock_bh(&pmon->mon_lock);
- return rx_bufs_used;
- }
- pmon->mon_last_linkdesc_paddr = paddr;
- is_first_msdu = false;
- }
- ath12k_dp_mon_get_buf_len(&msdu_list.msdu_info[i],
- &is_frag, &total_len,
- &frag_len, &msdu_cnt);
- rx_buf_size = rx_pkt_offset + l2_hdr_offset + frag_len;
-
- if (ath12k_dp_pkt_set_pktlen(msdu, rx_buf_size)) {
- dev_kfree_skb_any(msdu);
- goto next_msdu;
- }
-
- if (!(*head_msdu))
- *head_msdu = msdu;
- else if (last)
- last->next = msdu;
-
- last = msdu;
-next_msdu:
- pmon->mon_last_buf_cookie = msdu_list.sw_cookie[i];
- rx_bufs_used++;
- desc_info->skb = NULL;
- list_add_tail(&desc_info->list, used_list);
- }
-
- ath12k_hal_rx_buf_addr_info_set(&buf_info, paddr, sw_cookie, rbm);
-
- ath12k_dp_mon_next_link_desc_get(msdu_link_desc, &paddr,
- &sw_cookie, &rbm,
- &p_buf_addr_info);
-
- ath12k_dp_rx_link_desc_return(ar->ab, &buf_info,
- HAL_WBM_REL_BM_ACT_PUT_IN_IDLE);
-
- p_last_buf_addr_info = p_buf_addr_info;
-
- } while (paddr && msdu_cnt);
-
- spin_unlock_bh(&pmon->mon_lock);
-
- if (last)
- last->next = NULL;
-
- *tail_msdu = msdu;
-
- if (msdu_cnt == 0)
- *npackets = 1;
-
- return rx_bufs_used;
-}
-
-/* The destination ring processing is stuck if the destination is not
- * moving while status ring moves 16 PPDU. The destination ring processing
- * skips this destination ring PPDU as a workaround.
- */
-#define MON_DEST_RING_STUCK_MAX_CNT 16
-
-static void ath12k_dp_rx_mon_dest_process(struct ath12k *ar, int mac_id,
- u32 quota, struct napi_struct *napi)
-{
- struct ath12k_mon_data *pmon = (struct ath12k_mon_data *)&ar->dp.mon_data;
- struct ath12k_pdev_mon_stats *rx_mon_stats;
- u32 ppdu_id, rx_bufs_used = 0, ring_id;
- u32 mpdu_rx_bufs_used, npackets = 0;
- struct ath12k_dp *dp = &ar->ab->dp;
- struct ath12k_base *ab = ar->ab;
- void *ring_entry, *mon_dst_srng;
- struct dp_mon_mpdu *tmp_mpdu;
- LIST_HEAD(rx_desc_used_list);
- struct hal_srng *srng;
-
- ring_id = dp->rxdma_err_dst_ring[mac_id].ring_id;
- srng = &ab->hal.srng_list[ring_id];
-
- mon_dst_srng = &ab->hal.srng_list[ring_id];
-
- spin_lock_bh(&srng->lock);
-
- ath12k_hal_srng_access_begin(ab, mon_dst_srng);
-
- ppdu_id = pmon->mon_ppdu_info.ppdu_id;
- rx_mon_stats = &pmon->rx_mon_stats;
-
- while ((ring_entry = ath12k_hal_srng_dst_peek(ar->ab, mon_dst_srng))) {
- struct sk_buff *head_msdu, *tail_msdu;
-
- head_msdu = NULL;
- tail_msdu = NULL;
-
- mpdu_rx_bufs_used = ath12k_dp_rx_mon_mpdu_pop(ar, mac_id, ring_entry,
- &head_msdu, &tail_msdu,
- &rx_desc_used_list,
- &npackets, &ppdu_id);
-
- rx_bufs_used += mpdu_rx_bufs_used;
-
- if (mpdu_rx_bufs_used) {
- dp->mon_dest_ring_stuck_cnt = 0;
- } else {
- dp->mon_dest_ring_stuck_cnt++;
- rx_mon_stats->dest_mon_not_reaped++;
- }
-
- if (dp->mon_dest_ring_stuck_cnt > MON_DEST_RING_STUCK_MAX_CNT) {
- rx_mon_stats->dest_mon_stuck++;
- ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
- "status ring ppdu_id=%d dest ring ppdu_id=%d mon_dest_ring_stuck_cnt=%d dest_mon_not_reaped=%u dest_mon_stuck=%u\n",
- pmon->mon_ppdu_info.ppdu_id, ppdu_id,
- dp->mon_dest_ring_stuck_cnt,
- rx_mon_stats->dest_mon_not_reaped,
- rx_mon_stats->dest_mon_stuck);
- spin_lock_bh(&pmon->mon_lock);
- pmon->mon_ppdu_info.ppdu_id = ppdu_id;
- spin_unlock_bh(&pmon->mon_lock);
- continue;
- }
-
- if (ppdu_id != pmon->mon_ppdu_info.ppdu_id) {
- spin_lock_bh(&pmon->mon_lock);
- pmon->mon_ppdu_status = DP_PPDU_STATUS_START;
- spin_unlock_bh(&pmon->mon_lock);
- ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
- "dest_rx: new ppdu_id %x != status ppdu_id %x dest_mon_not_reaped = %u dest_mon_stuck = %u\n",
- ppdu_id, pmon->mon_ppdu_info.ppdu_id,
- rx_mon_stats->dest_mon_not_reaped,
- rx_mon_stats->dest_mon_stuck);
- break;
- }
-
- if (head_msdu && tail_msdu) {
- tmp_mpdu = kzalloc(sizeof(*tmp_mpdu), GFP_ATOMIC);
- if (!tmp_mpdu)
- break;
-
- tmp_mpdu->head = head_msdu;
- tmp_mpdu->tail = tail_msdu;
- tmp_mpdu->err_bitmap = pmon->err_bitmap;
- tmp_mpdu->decap_format = pmon->decap_format;
- ath12k_dp_mon_rx_deliver(ar, tmp_mpdu,
- &pmon->mon_ppdu_info, napi);
- rx_mon_stats->dest_mpdu_done++;
- kfree(tmp_mpdu);
- }
-
- ring_entry = ath12k_hal_srng_dst_get_next_entry(ar->ab,
- mon_dst_srng);
- }
- ath12k_hal_srng_access_end(ar->ab, mon_dst_srng);
-
- spin_unlock_bh(&srng->lock);
-
- if (rx_bufs_used) {
- rx_mon_stats->dest_ppdu_done++;
- ath12k_dp_rx_bufs_replenish(ar->ab,
- &dp->rx_refill_buf_ring,
- &rx_desc_used_list,
- rx_bufs_used);
- }
-}
-
-static int
-__ath12k_dp_mon_process_ring(struct ath12k *ar, int mac_id,
- struct napi_struct *napi, int *budget)
-{
- struct ath12k_mon_data *pmon = (struct ath12k_mon_data *)&ar->dp.mon_data;
- struct ath12k_pdev_mon_stats *rx_mon_stats = &pmon->rx_mon_stats;
- struct hal_rx_mon_ppdu_info *ppdu_info = &pmon->mon_ppdu_info;
- enum hal_rx_mon_status hal_status;
- struct sk_buff_head skb_list;
- int num_buffs_reaped;
- struct sk_buff *skb;
-
- __skb_queue_head_init(&skb_list);
-
- num_buffs_reaped = ath12k_dp_rx_reap_mon_status_ring(ar->ab, mac_id,
- budget, &skb_list);
- if (!num_buffs_reaped)
- goto exit;
-
- while ((skb = __skb_dequeue(&skb_list))) {
- memset(ppdu_info, 0, sizeof(*ppdu_info));
- ppdu_info->peer_id = HAL_INVALID_PEERID;
-
- hal_status = ath12k_dp_mon_parse_rx_dest(ar, pmon, skb);
-
- if (ar->monitor_started &&
- pmon->mon_ppdu_status == DP_PPDU_STATUS_START &&
- hal_status == HAL_TLV_STATUS_PPDU_DONE) {
- rx_mon_stats->status_ppdu_done++;
- pmon->mon_ppdu_status = DP_PPDU_STATUS_DONE;
- ath12k_dp_rx_mon_dest_process(ar, mac_id, *budget, napi);
- pmon->mon_ppdu_status = DP_PPDU_STATUS_START;
- }
-
- dev_kfree_skb_any(skb);
- }
-
-exit:
- return num_buffs_reaped;
-}
-
-int ath12k_dp_mon_process_ring(struct ath12k_base *ab, int mac_id,
- struct napi_struct *napi, int budget,
- enum dp_monitor_mode monitor_mode)
-{
- struct ath12k *ar = ath12k_ab_to_ar(ab, mac_id);
- int num_buffs_reaped = 0;
-
- if (ab->hw_params->rxdma1_enable) {
- if (monitor_mode == ATH12K_DP_RX_MONITOR_MODE)
- num_buffs_reaped = ath12k_dp_mon_srng_process(ar, &budget, napi);
- } else {
- if (ar->monitor_started)
- num_buffs_reaped =
- __ath12k_dp_mon_process_ring(ar, mac_id, napi, &budget);
- }
-
- return num_buffs_reaped;
+ ath12k_dp_mon_rx_update_user_stats(ab, ppdu_info, i);
}
+EXPORT_SYMBOL(ath12k_dp_mon_rx_update_peer_mu_stats);
diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.h b/drivers/net/wireless/ath/ath12k/dp_mon.h
index e25595cbdcf3..167028d27513 100644
--- a/drivers/net/wireless/ath/ath12k/dp_mon.h
+++ b/drivers/net/wireless/ath/ath12k/dp_mon.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH12K_DP_MON_H
@@ -12,6 +12,12 @@
#define ATH12K_MON_RX_DOT11_OFFSET 5
#define ATH12K_MON_RX_PKT_OFFSET 8
+#define ATH12K_LE32_DEC_ENC(value, dec_bits, enc_bits) \
+ u32_encode_bits(le32_get_bits(value, dec_bits), enc_bits)
+
+#define ATH12K_LE64_DEC_ENC(value, dec_bits, enc_bits) \
+ u32_encode_bits(le64_get_bits(value, dec_bits), enc_bits)
+
enum dp_monitor_mode {
ATH12K_DP_TX_MONITOR_MODE,
ATH12K_DP_RX_MONITOR_MODE
@@ -77,31 +83,41 @@ struct dp_mon_tx_ppdu_info {
struct dp_mon_mpdu *tx_mon_mpdu;
};
-enum hal_rx_mon_status
-ath12k_dp_mon_rx_parse_mon_status(struct ath12k *ar,
- struct ath12k_mon_data *pmon,
- struct sk_buff *skb,
- struct napi_struct *napi);
int ath12k_dp_mon_buf_replenish(struct ath12k_base *ab,
struct dp_rxdma_mon_ring *buf_ring,
int req_entries);
int ath12k_dp_mon_status_bufs_replenish(struct ath12k_base *ab,
struct dp_rxdma_mon_ring *rx_ring,
int req_entries);
-int ath12k_dp_mon_process_ring(struct ath12k_base *ab, int mac_id,
- struct napi_struct *napi, int budget,
- enum dp_monitor_mode monitor_mode);
-struct sk_buff *ath12k_dp_mon_tx_alloc_skb(void);
-enum dp_mon_tx_tlv_status
-ath12k_dp_mon_tx_status_get_num_user(u16 tlv_tag,
- struct hal_tlv_hdr *tx_tlv,
- u8 *num_users);
-enum hal_rx_mon_status
-ath12k_dp_mon_tx_parse_mon_status(struct ath12k *ar,
- struct ath12k_mon_data *pmon,
- struct sk_buff *skb,
- struct napi_struct *napi,
- u32 ppdu_id);
void ath12k_dp_mon_rx_process_ulofdma(struct hal_rx_mon_ppdu_info *ppdu_info);
-int ath12k_dp_mon_srng_process(struct ath12k *ar, int *budget, struct napi_struct *napi);
+void
+ath12k_dp_mon_rx_update_peer_mu_stats(struct ath12k_base *ab,
+ struct hal_rx_mon_ppdu_info *ppdu_info);
+void ath12k_dp_mon_rx_update_peer_su_stats(struct ath12k_dp_link_peer *peer,
+ struct hal_rx_mon_ppdu_info *ppdu_info);
+int ath12k_dp_pkt_set_pktlen(struct sk_buff *skb, u32 len);
+struct sk_buff
+*ath12k_dp_rx_alloc_mon_status_buf(struct ath12k_base *ab,
+ struct dp_rxdma_mon_ring *rx_ring,
+ int *buf_id);
+u32 ath12k_dp_mon_comp_ppduid(u32 msdu_ppdu_id, u32 *ppdu_id);
+int
+ath12k_dp_mon_parse_status_buf(struct ath12k_pdev_dp *dp_pdev,
+ struct ath12k_mon_data *pmon,
+ const struct dp_mon_packet_info *packet_info);
+void ath12k_dp_mon_update_radiotap(struct ath12k_pdev_dp *dp_pdev,
+ struct hal_rx_mon_ppdu_info *ppduinfo,
+ struct sk_buff *mon_skb,
+ struct ieee80211_rx_status *rxs);
+void ath12k_dp_mon_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev,
+ struct napi_struct *napi,
+ struct sk_buff *msdu,
+ const struct hal_rx_mon_ppdu_info *ppduinfo,
+ struct ieee80211_rx_status *status,
+ u8 decap);
+struct sk_buff *
+ath12k_dp_mon_rx_merg_msdus(struct ath12k_pdev_dp *dp_pdev,
+ struct dp_mon_mpdu *mon_mpdu,
+ struct hal_rx_mon_ppdu_info *ppdu_info,
+ struct ieee80211_rx_status *rxs);
#endif
diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.c b/drivers/net/wireless/ath/ath12k/dp_peer.c
new file mode 100644
index 000000000000..2e66872b5572
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/dp_peer.c
@@ -0,0 +1,690 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include "core.h"
+#include "dp_peer.h"
+#include "debug.h"
+#include "debugfs.h"
+
+void ath12k_dp_link_peer_free(struct ath12k_dp_link_peer *peer)
+{
+ list_del(&peer->list);
+
+ kfree(peer->peer_stats.rx_stats);
+ kfree(peer);
+}
+
+struct ath12k_dp_link_peer *
+ath12k_dp_link_peer_find_by_vdev_and_addr(struct ath12k_dp *dp,
+ int vdev_id, const u8 *addr)
+{
+ struct ath12k_dp_link_peer *peer;
+
+ lockdep_assert_held(&dp->dp_lock);
+
+ list_for_each_entry(peer, &dp->peers, list) {
+ if (peer->vdev_id != vdev_id)
+ continue;
+ if (!ether_addr_equal(peer->addr, addr))
+ continue;
+
+ return peer;
+ }
+
+ return NULL;
+}
+
+struct ath12k_dp_link_peer *
+ath12k_dp_link_peer_find_by_pdev_and_addr(struct ath12k_dp *dp, u8 pdev_idx,
+ const u8 *addr)
+{
+ struct ath12k_dp_link_peer *peer;
+
+ lockdep_assert_held(&dp->dp_lock);
+
+ list_for_each_entry(peer, &dp->peers, list) {
+ if (peer->pdev_idx != pdev_idx)
+ continue;
+ if (!ether_addr_equal(peer->addr, addr))
+ continue;
+
+ return peer;
+ }
+
+ return NULL;
+}
+
+struct ath12k_dp_link_peer *
+ath12k_dp_link_peer_find_by_addr(struct ath12k_dp *dp, const u8 *addr)
+{
+ lockdep_assert_held(&dp->dp_lock);
+
+ return rhashtable_lookup_fast(dp->rhead_peer_addr, addr,
+ dp->rhash_peer_addr_param);
+}
+EXPORT_SYMBOL(ath12k_dp_link_peer_find_by_addr);
+
+static struct ath12k_dp_link_peer *
+ath12k_dp_link_peer_find_by_ml_id(struct ath12k_dp *dp, int ml_peer_id)
+{
+ struct ath12k_dp_link_peer *peer;
+
+ lockdep_assert_held(&dp->dp_lock);
+
+ list_for_each_entry(peer, &dp->peers, list)
+ if (ml_peer_id == peer->ml_id)
+ return peer;
+
+ return NULL;
+}
+
+static struct ath12k_dp_link_peer *
+ath12k_dp_link_peer_search_by_id(struct ath12k_dp *dp, int peer_id)
+{
+ struct ath12k_dp_link_peer *peer;
+
+ lockdep_assert_held(&dp->dp_lock);
+
+ if (peer_id == HAL_INVALID_PEERID)
+ return NULL;
+
+ if (peer_id & ATH12K_PEER_ML_ID_VALID)
+ return ath12k_dp_link_peer_find_by_ml_id(dp, peer_id);
+
+ list_for_each_entry(peer, &dp->peers, list)
+ if (peer_id == peer->peer_id)
+ return peer;
+
+ return NULL;
+}
+
+bool ath12k_dp_link_peer_exist_by_vdev_id(struct ath12k_dp *dp, int vdev_id)
+{
+ struct ath12k_dp_link_peer *peer;
+
+ spin_lock_bh(&dp->dp_lock);
+
+ list_for_each_entry(peer, &dp->peers, list) {
+ if (vdev_id == peer->vdev_id) {
+ spin_unlock_bh(&dp->dp_lock);
+ return true;
+ }
+ }
+ spin_unlock_bh(&dp->dp_lock);
+ return false;
+}
+
+struct ath12k_dp_link_peer *
+ath12k_dp_link_peer_find_by_ast(struct ath12k_dp *dp, int ast_hash)
+{
+ struct ath12k_dp_link_peer *peer;
+
+ lockdep_assert_held(&dp->dp_lock);
+
+ list_for_each_entry(peer, &dp->peers, list)
+ if (ast_hash == peer->ast_hash)
+ return peer;
+
+ return NULL;
+}
+
+void ath12k_dp_link_peer_unmap_event(struct ath12k_base *ab, u16 peer_id)
+{
+ struct ath12k_dp_link_peer *peer;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+
+ spin_lock_bh(&dp->dp_lock);
+
+ peer = ath12k_dp_link_peer_search_by_id(dp, peer_id);
+ if (!peer) {
+ ath12k_warn(ab, "peer-unmap-event: unknown peer id %d\n",
+ peer_id);
+ goto exit;
+ }
+
+ ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "htt peer unmap vdev %d peer %pM id %d\n",
+ peer->vdev_id, peer->addr, peer_id);
+
+ ath12k_dp_link_peer_free(peer);
+ wake_up(&ab->peer_mapping_wq);
+
+exit:
+ spin_unlock_bh(&dp->dp_lock);
+}
+
+void ath12k_dp_link_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_id,
+ u8 *mac_addr, u16 ast_hash, u16 hw_peer_id)
+{
+ struct ath12k_dp_link_peer *peer;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k *ar;
+
+ spin_lock_bh(&dp->dp_lock);
+ peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, mac_addr);
+ if (!peer) {
+ peer = kzalloc(sizeof(*peer), GFP_ATOMIC);
+ if (!peer)
+ goto exit;
+
+ peer->vdev_id = vdev_id;
+ peer->peer_id = peer_id;
+ peer->ast_hash = ast_hash;
+ peer->hw_peer_id = hw_peer_id;
+ ether_addr_copy(peer->addr, mac_addr);
+
+ rcu_read_lock();
+ ar = ath12k_mac_get_ar_by_vdev_id(ab, vdev_id);
+ if (ar && ath12k_debugfs_is_extd_rx_stats_enabled(ar) &&
+ !peer->peer_stats.rx_stats) {
+ peer->peer_stats.rx_stats =
+ kzalloc(sizeof(*peer->peer_stats.rx_stats), GFP_ATOMIC);
+ }
+ rcu_read_unlock();
+
+ list_add(&peer->list, &dp->peers);
+ wake_up(&ab->peer_mapping_wq);
+ ewma_avg_rssi_init(&peer->avg_rssi);
+ }
+ ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "htt peer map vdev %d peer %pM id %d\n",
+ vdev_id, mac_addr, peer_id);
+
+exit:
+ spin_unlock_bh(&dp->dp_lock);
+}
+
+struct ath12k_link_sta *ath12k_dp_link_peer_to_link_sta(struct ath12k_base *ab,
+ struct ath12k_dp_link_peer *peer)
+{
+ struct ath12k_sta *ahsta;
+ struct ath12k_link_sta *arsta;
+
+ RCU_LOCKDEP_WARN(!rcu_read_lock_held(),
+ "ath12k_dp_link_peer to ath12k_link_sta called without rcu lock");
+
+ if (!peer->sta)
+ return NULL;
+
+ ahsta = ath12k_sta_to_ahsta(peer->sta);
+ if (peer->ml_id & ATH12K_PEER_ML_ID_VALID) {
+ if (!(ahsta->links_map & BIT(peer->link_id))) {
+ ath12k_warn(ab, "peer %pM id %d link_id %d can't found in STA link_map 0x%x\n",
+ peer->addr, peer->peer_id, peer->link_id,
+ ahsta->links_map);
+ return NULL;
+ }
+ arsta = rcu_dereference(ahsta->link[peer->link_id]);
+ if (!arsta)
+ return NULL;
+ } else {
+ arsta = &ahsta->deflink;
+ }
+ return arsta;
+}
+
+static int ath12k_dp_link_peer_rhash_addr_tbl_init(struct ath12k_dp *dp)
+{
+ struct ath12k_base *ab = dp->ab;
+ struct rhashtable_params *param;
+ struct rhashtable *rhash_addr_tbl;
+ int ret;
+
+ lockdep_assert_held(&dp->link_peer_rhash_tbl_lock);
+
+ rhash_addr_tbl = kzalloc(sizeof(*dp->rhead_peer_addr), GFP_KERNEL);
+ if (!rhash_addr_tbl)
+ return -ENOMEM;
+
+ param = &dp->rhash_peer_addr_param;
+
+ param->key_offset = offsetof(struct ath12k_dp_link_peer, addr);
+ param->head_offset = offsetof(struct ath12k_dp_link_peer, rhash_addr);
+ param->key_len = sizeof_field(struct ath12k_dp_link_peer, addr);
+ param->automatic_shrinking = true;
+ param->nelem_hint = ab->num_radios * ath12k_core_get_max_peers_per_radio(ab);
+
+ ret = rhashtable_init(rhash_addr_tbl, param);
+ if (ret) {
+ ath12k_warn(ab, "failed to init peer addr rhash table %d\n", ret);
+ goto err_free;
+ }
+
+ dp->rhead_peer_addr = rhash_addr_tbl;
+
+ return 0;
+
+err_free:
+ kfree(rhash_addr_tbl);
+
+ return ret;
+}
+
+int ath12k_dp_link_peer_rhash_tbl_init(struct ath12k_dp *dp)
+{
+ int ret;
+
+ mutex_lock(&dp->link_peer_rhash_tbl_lock);
+ ret = ath12k_dp_link_peer_rhash_addr_tbl_init(dp);
+ mutex_unlock(&dp->link_peer_rhash_tbl_lock);
+
+ return ret;
+}
+
+void ath12k_dp_link_peer_rhash_tbl_destroy(struct ath12k_dp *dp)
+{
+ mutex_lock(&dp->link_peer_rhash_tbl_lock);
+ rhashtable_destroy(dp->rhead_peer_addr);
+ kfree(dp->rhead_peer_addr);
+ dp->rhead_peer_addr = NULL;
+ mutex_unlock(&dp->link_peer_rhash_tbl_lock);
+}
+
+static int ath12k_dp_link_peer_rhash_insert(struct ath12k_dp *dp,
+ struct ath12k_dp_link_peer *peer)
+{
+ struct ath12k_dp_link_peer *tmp;
+
+ lockdep_assert_held(&dp->dp_lock);
+
+ tmp = rhashtable_lookup_get_insert_fast(dp->rhead_peer_addr, &peer->rhash_addr,
+ dp->rhash_peer_addr_param);
+ if (!tmp)
+ return 0;
+ else if (IS_ERR(tmp))
+ return PTR_ERR(tmp);
+ else
+ return -EEXIST;
+}
+
+static int ath12k_dp_link_peer_rhash_remove(struct ath12k_dp *dp,
+ struct ath12k_dp_link_peer *peer)
+{
+ int ret;
+
+ lockdep_assert_held(&dp->dp_lock);
+
+ ret = rhashtable_remove_fast(dp->rhead_peer_addr, &peer->rhash_addr,
+ dp->rhash_peer_addr_param);
+ if (ret && ret != -ENOENT)
+ return ret;
+
+ return 0;
+}
+
+int ath12k_dp_link_peer_rhash_add(struct ath12k_dp *dp,
+ struct ath12k_dp_link_peer *peer)
+{
+ int ret;
+
+ lockdep_assert_held(&dp->dp_lock);
+
+ ret = ath12k_dp_link_peer_rhash_insert(dp, peer);
+ if (ret)
+ ath12k_warn(dp, "failed to add peer %pM with id %d in rhash_addr ret %d\n",
+ peer->addr, peer->peer_id, ret);
+
+ return ret;
+}
+
+void ath12k_dp_link_peer_rhash_delete(struct ath12k_dp *dp,
+ struct ath12k_dp_link_peer *peer)
+{
+ /* No failure handling and hence return type is void */
+ int ret;
+
+ lockdep_assert_held(&dp->dp_lock);
+
+ ret = ath12k_dp_link_peer_rhash_remove(dp, peer);
+ if (ret)
+ ath12k_warn(dp, "failed to remove peer %pM with id %d in rhash_addr ret %d\n",
+ peer->addr, peer->peer_id, ret);
+}
+
+struct ath12k_dp_peer *ath12k_dp_peer_find_by_addr(struct ath12k_dp_hw *dp_hw, u8 *addr)
+{
+ struct ath12k_dp_peer *peer;
+
+ lockdep_assert_held(&dp_hw->peer_lock);
+
+ list_for_each_entry(peer, &dp_hw->dp_peers_list, list) {
+ if (ether_addr_equal(peer->addr, addr))
+ return peer;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL(ath12k_dp_peer_find_by_addr);
+
+struct ath12k_dp_peer *ath12k_dp_peer_find_by_addr_and_sta(struct ath12k_dp_hw *dp_hw,
+ u8 *addr,
+ struct ieee80211_sta *sta)
+{
+ struct ath12k_dp_peer *dp_peer;
+
+ lockdep_assert_held(&dp_hw->peer_lock);
+
+ list_for_each_entry(dp_peer, &dp_hw->dp_peers_list, list) {
+ if (ether_addr_equal(dp_peer->addr, addr) && (dp_peer->sta == sta))
+ return dp_peer;
+ }
+
+ return NULL;
+}
+
+static struct ath12k_dp_peer *ath12k_dp_peer_create_find(struct ath12k_dp_hw *dp_hw,
+ u8 *addr,
+ struct ieee80211_sta *sta,
+ bool mlo_peer)
+{
+ struct ath12k_dp_peer *dp_peer;
+
+ lockdep_assert_held(&dp_hw->peer_lock);
+
+ list_for_each_entry(dp_peer, &dp_hw->dp_peers_list, list) {
+ if (ether_addr_equal(dp_peer->addr, addr)) {
+ if (!sta || mlo_peer || dp_peer->is_mlo ||
+ dp_peer->sta == sta)
+ return dp_peer;
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Index of ath12k_dp_peer for MLO client is same as peer id of ath12k_dp_peer,
+ * while for ath12k_dp_link_peer(mlo and non-mlo) and ath12k_dp_peer for
+ * Non-MLO client it is derived as ((DEVICE_ID << 10) | (10 bits of peer id)).
+ *
+ * This is done because ml_peer_id and peer_id_table are at hw granularity,
+ * while link_peer_id is at device granularity, hence in order to avoid
+ * conflict this approach is followed.
+ */
+#define ATH12K_DP_PEER_TABLE_DEVICE_ID_SHIFT 10
+
+u16 ath12k_dp_peer_get_peerid_index(struct ath12k_dp *dp, u16 peer_id)
+{
+ return (peer_id & ATH12K_PEER_ML_ID_VALID) ? peer_id :
+ ((dp->device_id << ATH12K_DP_PEER_TABLE_DEVICE_ID_SHIFT) | peer_id);
+}
+
+struct ath12k_dp_peer *ath12k_dp_peer_find_by_peerid(struct ath12k_pdev_dp *dp_pdev,
+ u16 peer_id)
+{
+ u16 index;
+ struct ath12k_dp *dp = dp_pdev->dp;
+
+ RCU_LOCKDEP_WARN(!rcu_read_lock_held(),
+ "ath12k dp peer find by peerid index called without rcu lock");
+
+ if (!peer_id || peer_id >= ATH12K_DP_PEER_ID_INVALID)
+ return NULL;
+
+ index = ath12k_dp_peer_get_peerid_index(dp, peer_id);
+
+ return rcu_dereference(dp_pdev->dp_hw->dp_peers[index]);
+}
+EXPORT_SYMBOL(ath12k_dp_peer_find_by_peerid);
+
+struct ath12k_dp_link_peer *
+ath12k_dp_link_peer_find_by_peerid(struct ath12k_pdev_dp *dp_pdev, u16 peer_id)
+{
+ struct ath12k_dp_peer *dp_peer = NULL;
+ u8 link_id;
+
+ RCU_LOCKDEP_WARN(!rcu_read_lock_held(),
+ "ath12k dp link peer find by peerid index called without rcu lock");
+
+ if (dp_pdev->hw_link_id >= ATH12K_GROUP_MAX_RADIO)
+ return NULL;
+
+ dp_peer = ath12k_dp_peer_find_by_peerid(dp_pdev, peer_id);
+ if (!dp_peer)
+ return NULL;
+
+ link_id = dp_peer->hw_links[dp_pdev->hw_link_id];
+
+ return rcu_dereference(dp_peer->link_peers[link_id]);
+}
+EXPORT_SYMBOL(ath12k_dp_link_peer_find_by_peerid);
+
+int ath12k_dp_peer_create(struct ath12k_dp_hw *dp_hw, u8 *addr,
+ struct ath12k_dp_peer_create_params *params)
+{
+ struct ath12k_dp_peer *dp_peer;
+
+ spin_lock_bh(&dp_hw->peer_lock);
+ dp_peer = ath12k_dp_peer_create_find(dp_hw, addr, params->sta, params->is_mlo);
+ if (dp_peer) {
+ spin_unlock_bh(&dp_hw->peer_lock);
+ return -EEXIST;
+ }
+ spin_unlock_bh(&dp_hw->peer_lock);
+
+ dp_peer = kzalloc(sizeof(*dp_peer), GFP_ATOMIC);
+ if (!dp_peer)
+ return -ENOMEM;
+
+ ether_addr_copy(dp_peer->addr, addr);
+ dp_peer->sta = params->sta;
+ dp_peer->is_mlo = params->is_mlo;
+
+ /*
+ * For MLO client, the host assigns the ML peer ID, so set peer_id in dp_peer
+ * For non-MLO client, host gets link peer ID from firmware and will be
+ * assigned at the time of link peer creation
+ */
+ dp_peer->peer_id = params->is_mlo ? params->peer_id : ATH12K_DP_PEER_ID_INVALID;
+ dp_peer->ucast_ra_only = params->ucast_ra_only;
+
+ dp_peer->sec_type = HAL_ENCRYPT_TYPE_OPEN;
+ dp_peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN;
+ dp_peer->ucast_ra_only = params->ucast_ra_only;
+
+ spin_lock_bh(&dp_hw->peer_lock);
+
+ list_add(&dp_peer->list, &dp_hw->dp_peers_list);
+
+ /*
+ * For MLO client, the peer_id for ath12k_dp_peer is allocated by host
+ * and that peer_id is known at this point, and hence this ath12k_dp_peer
+ * can be added to the RCU table using the peer_id.
+ * For non-MLO client, this addition to RCU table shall be done at the
+ * time of assignment of ath12k_dp_link_peer to ath12k_dp_peer.
+ */
+ if (dp_peer->is_mlo)
+ rcu_assign_pointer(dp_hw->dp_peers[dp_peer->peer_id], dp_peer);
+
+ spin_unlock_bh(&dp_hw->peer_lock);
+
+ return 0;
+}
+
+void ath12k_dp_peer_delete(struct ath12k_dp_hw *dp_hw, u8 *addr,
+ struct ieee80211_sta *sta)
+{
+ struct ath12k_dp_peer *dp_peer;
+
+ spin_lock_bh(&dp_hw->peer_lock);
+
+ dp_peer = ath12k_dp_peer_find_by_addr_and_sta(dp_hw, addr, sta);
+ if (!dp_peer) {
+ spin_unlock_bh(&dp_hw->peer_lock);
+ return;
+ }
+
+ if (dp_peer->is_mlo)
+ rcu_assign_pointer(dp_hw->dp_peers[dp_peer->peer_id], NULL);
+
+ list_del(&dp_peer->list);
+
+ spin_unlock_bh(&dp_hw->peer_lock);
+
+ synchronize_rcu();
+ kfree(dp_peer);
+}
+
+int ath12k_dp_link_peer_assign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_hw,
+ u8 vdev_id, struct ieee80211_sta *sta, u8 *addr,
+ u8 link_id, u32 hw_link_id)
+{
+ struct ath12k_dp_peer *dp_peer;
+ struct ath12k_dp_link_peer *peer, *temp_peer;
+ u16 peerid_index;
+ int ret = -EINVAL;
+ u8 *dp_peer_mac = !sta ? addr : sta->addr;
+
+ spin_lock_bh(&dp->dp_lock);
+
+ peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, addr);
+ if (!peer) {
+ ath12k_warn(dp, "failed to find dp_link_peer with mac %pM on vdev %u\n",
+ addr, vdev_id);
+ ret = -ENOENT;
+ goto err_peer;
+ }
+
+ spin_lock_bh(&dp_hw->peer_lock);
+
+ dp_peer = ath12k_dp_peer_find_by_addr_and_sta(dp_hw, dp_peer_mac, sta);
+ if (!dp_peer) {
+ ath12k_warn(dp, "failed to find dp_peer with mac %pM\n", dp_peer_mac);
+ ret = -ENOENT;
+ goto err_dp_peer;
+ }
+
+ /*
+ * Set peer_id in dp_peer for non-mlo client, peer_id for mlo client is
+ * set during dp_peer create
+ */
+ if (!dp_peer->is_mlo)
+ dp_peer->peer_id = peer->peer_id;
+
+ peer->dp_peer = dp_peer;
+ peer->hw_link_id = hw_link_id;
+
+ dp_peer->hw_links[peer->hw_link_id] = link_id;
+
+ peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id);
+
+ rcu_assign_pointer(dp_peer->link_peers[peer->link_id], peer);
+
+ rcu_assign_pointer(dp_hw->dp_peers[peerid_index], dp_peer);
+
+ spin_unlock_bh(&dp_hw->peer_lock);
+
+ /*
+ * In case of Split PHY and roaming scenario, pdev idx
+ * might differ but both the pdev will share same rhash
+ * table. In that case update the rhash table if link_peer is
+ * already present
+ */
+ temp_peer = ath12k_dp_link_peer_find_by_addr(dp, addr);
+ if (temp_peer && temp_peer->hw_link_id != hw_link_id)
+ ath12k_dp_link_peer_rhash_delete(dp, temp_peer);
+
+ ret = ath12k_dp_link_peer_rhash_add(dp, peer);
+ if (ret) {
+ /*
+ * If new entry addition failed, add back old entry
+ * If old entry addition also fails, then nothing
+ * can be done, simply proceed
+ */
+ if (temp_peer)
+ ath12k_dp_link_peer_rhash_add(dp, temp_peer);
+ }
+
+ spin_unlock_bh(&dp->dp_lock);
+
+ return ret;
+
+err_dp_peer:
+ spin_unlock_bh(&dp_hw->peer_lock);
+
+err_peer:
+ spin_unlock_bh(&dp->dp_lock);
+
+ return ret;
+}
+
+void ath12k_dp_link_peer_unassign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_hw,
+ u8 vdev_id, u8 *addr, u32 hw_link_id)
+{
+ struct ath12k_dp_peer *dp_peer;
+ struct ath12k_dp_link_peer *peer, *temp_peer;
+ u16 peerid_index;
+
+ spin_lock_bh(&dp->dp_lock);
+
+ peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, addr);
+ if (!peer || !peer->dp_peer) {
+ spin_unlock_bh(&dp->dp_lock);
+ return;
+ }
+
+ spin_lock_bh(&dp_hw->peer_lock);
+
+ dp_peer = peer->dp_peer;
+ dp_peer->hw_links[peer->hw_link_id] = 0;
+
+ peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id);
+
+ rcu_assign_pointer(dp_peer->link_peers[peer->link_id], NULL);
+
+ rcu_assign_pointer(dp_hw->dp_peers[peerid_index], NULL);
+
+ spin_unlock_bh(&dp_hw->peer_lock);
+
+ /* To handle roaming and split phy scenario */
+ temp_peer = ath12k_dp_link_peer_find_by_addr(dp, addr);
+ if (temp_peer && temp_peer->hw_link_id == hw_link_id)
+ ath12k_dp_link_peer_rhash_delete(dp, peer);
+
+ spin_unlock_bh(&dp->dp_lock);
+
+ synchronize_rcu();
+}
+
+void
+ath12k_dp_link_peer_get_sta_rate_info_stats(struct ath12k_dp *dp, const u8 *addr,
+ struct ath12k_dp_link_peer_rate_info *info)
+{
+ struct ath12k_dp_link_peer *link_peer;
+
+ guard(spinlock_bh)(&dp->dp_lock);
+
+ link_peer = ath12k_dp_link_peer_find_by_addr(dp, addr);
+ if (!link_peer)
+ return;
+
+ info->rx_duration = link_peer->rx_duration;
+ info->tx_duration = link_peer->tx_duration;
+ info->txrate.legacy = link_peer->txrate.legacy;
+ info->txrate.mcs = link_peer->txrate.mcs;
+ info->txrate.nss = link_peer->txrate.nss;
+ info->txrate.bw = link_peer->txrate.bw;
+ info->txrate.he_gi = link_peer->txrate.he_gi;
+ info->txrate.he_dcm = link_peer->txrate.he_dcm;
+ info->txrate.he_ru_alloc = link_peer->txrate.he_ru_alloc;
+ info->txrate.flags = link_peer->txrate.flags;
+ info->rssi_comb = link_peer->rssi_comb;
+ info->signal_avg = ewma_avg_rssi_read(&link_peer->avg_rssi);
+}
+
+void ath12k_dp_link_peer_reset_rx_stats(struct ath12k_dp *dp, const u8 *addr)
+{
+ struct ath12k_rx_peer_stats *rx_stats;
+ struct ath12k_dp_link_peer *link_peer;
+
+ guard(spinlock_bh)(&dp->dp_lock);
+
+ link_peer = ath12k_dp_link_peer_find_by_addr(dp, addr);
+ if (!link_peer || !link_peer->peer_stats.rx_stats)
+ return;
+
+ rx_stats = link_peer->peer_stats.rx_stats;
+ if (rx_stats)
+ memset(rx_stats, 0, sizeof(*rx_stats));
+}
diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.h b/drivers/net/wireless/ath/ath12k/dp_peer.h
new file mode 100644
index 000000000000..20294ff09513
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/dp_peer.h
@@ -0,0 +1,182 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef ATH12K_DP_PEER_H
+#define ATH12K_DP_PEER_H
+
+#include "dp_rx.h"
+
+#define ATH12K_DP_PEER_ID_INVALID 0x3FFF
+
+struct ppdu_user_delayba {
+ u16 sw_peer_id;
+ u32 info0;
+ u16 ru_end;
+ u16 ru_start;
+ u32 info1;
+ u32 rate_flags;
+ u32 resp_rate_flags;
+};
+
+#define ATH12K_PEER_ML_ID_VALID BIT(13)
+
+struct ath12k_rx_peer_rate_stats {
+ u64 ht_mcs_count[HAL_RX_MAX_MCS_HT + 1];
+ u64 vht_mcs_count[HAL_RX_MAX_MCS_VHT + 1];
+ u64 he_mcs_count[HAL_RX_MAX_MCS_HE + 1];
+ u64 be_mcs_count[HAL_RX_MAX_MCS_BE + 1];
+ u64 nss_count[HAL_RX_MAX_NSS];
+ u64 bw_count[HAL_RX_BW_MAX];
+ u64 gi_count[HAL_RX_GI_MAX];
+ u64 legacy_count[HAL_RX_MAX_NUM_LEGACY_RATES];
+ u64 rx_rate[HAL_RX_BW_MAX][HAL_RX_GI_MAX][HAL_RX_MAX_NSS][HAL_RX_MAX_MCS_HT + 1];
+};
+
+struct ath12k_rx_peer_stats {
+ u64 num_msdu;
+ u64 num_mpdu_fcs_ok;
+ u64 num_mpdu_fcs_err;
+ u64 tcp_msdu_count;
+ u64 udp_msdu_count;
+ u64 other_msdu_count;
+ u64 ampdu_msdu_count;
+ u64 non_ampdu_msdu_count;
+ u64 stbc_count;
+ u64 beamformed_count;
+ u64 coding_count[HAL_RX_SU_MU_CODING_MAX];
+ u64 tid_count[IEEE80211_NUM_TIDS + 1];
+ u64 pream_cnt[HAL_RX_PREAMBLE_MAX];
+ u64 reception_type[HAL_RX_RECEPTION_TYPE_MAX];
+ u64 rx_duration;
+ u64 dcm_count;
+ u64 ru_alloc_cnt[HAL_RX_RU_ALLOC_TYPE_MAX];
+ struct ath12k_rx_peer_rate_stats pkt_stats;
+ struct ath12k_rx_peer_rate_stats byte_stats;
+};
+
+struct ath12k_wbm_tx_stats {
+ u64 wbm_tx_comp_stats[HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX];
+};
+
+struct ath12k_dp_peer_stats {
+ struct ath12k_rx_peer_stats *rx_stats;
+ struct ath12k_wbm_tx_stats *wbm_tx_stats;
+};
+
+DECLARE_EWMA(avg_rssi, 10, 8)
+
+struct ath12k_dp_link_peer {
+ struct list_head list;
+ struct ieee80211_sta *sta;
+ struct ath12k_dp_peer *dp_peer;
+ int vdev_id;
+ u8 addr[ETH_ALEN];
+ int peer_id;
+ u16 ast_hash;
+ u8 pdev_idx;
+ u16 hw_peer_id;
+
+ struct ppdu_user_delayba ppdu_stats_delayba;
+ bool delayba_flag;
+ bool is_authorized;
+ bool mlo;
+ /* protected by ab->data_lock */
+
+ u16 ml_id;
+
+ /* any other ML info common for all partners can be added
+ * here and would be same for all partner peers.
+ */
+ u8 ml_addr[ETH_ALEN];
+
+ /* To ensure only certain work related to dp is done once */
+ bool primary_link;
+
+ /* for reference to ath12k_link_sta */
+ u8 link_id;
+
+ /* peer addr based rhashtable list pointer */
+ struct rhash_head rhash_addr;
+
+ u8 hw_link_id;
+ u32 rx_tid_active_bitmask;
+
+ /* link stats */
+ struct rate_info txrate;
+ struct rate_info last_txrate;
+ u64 rx_duration;
+ u64 tx_duration;
+ u8 rssi_comb;
+ struct ewma_avg_rssi avg_rssi;
+ struct ath12k_dp_peer_stats peer_stats;
+ u32 tx_retry_failed;
+ u32 tx_retry_count;
+};
+
+void ath12k_dp_link_peer_unmap_event(struct ath12k_base *ab, u16 peer_id);
+void ath12k_dp_link_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_id,
+ u8 *mac_addr, u16 ast_hash, u16 hw_peer_id);
+
+struct ath12k_dp_peer {
+ struct list_head list;
+ bool is_mlo;
+ bool dp_setup_done;
+
+ u8 ucast_keyidx;
+ u8 addr[ETH_ALEN];
+
+ u8 mcast_keyidx;
+ bool ucast_ra_only;
+ int peer_id;
+ struct ieee80211_sta *sta;
+
+ u8 hw_links[ATH12K_GROUP_MAX_RADIO];
+
+ u16 sec_type_grp;
+ u16 sec_type;
+
+ /* Info used in MMIC verification of * RX fragments */
+ struct crypto_shash *tfm_mmic;
+ struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];
+ struct ath12k_dp_link_peer __rcu *link_peers[ATH12K_NUM_MAX_LINKS];
+ struct ath12k_reoq_buf reoq_bufs[IEEE80211_NUM_TIDS + 1];
+ struct ath12k_dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1];
+};
+
+struct ath12k_dp_link_peer *
+ath12k_dp_link_peer_find_by_vdev_and_addr(struct ath12k_dp *dp,
+ int vdev_id, const u8 *addr);
+struct ath12k_dp_link_peer *
+ath12k_dp_link_peer_find_by_addr(struct ath12k_dp *dp, const u8 *addr);
+bool ath12k_dp_link_peer_exist_by_vdev_id(struct ath12k_dp *dp, int vdev_id);
+struct ath12k_dp_link_peer *
+ath12k_dp_link_peer_find_by_ast(struct ath12k_dp *dp, int ast_hash);
+struct ath12k_dp_link_peer *
+ath12k_dp_link_peer_find_by_pdev_and_addr(struct ath12k_dp *dp, u8 pdev_idx,
+ const u8 *addr);
+struct ath12k_link_sta *ath12k_dp_link_peer_to_link_sta(struct ath12k_base *ab,
+ struct ath12k_dp_link_peer *peer);
+int ath12k_dp_link_peer_rhash_tbl_init(struct ath12k_dp *dp);
+void ath12k_dp_link_peer_rhash_tbl_destroy(struct ath12k_dp *dp);
+int ath12k_dp_link_peer_rhash_add(struct ath12k_dp *dp,
+ struct ath12k_dp_link_peer *peer);
+void ath12k_dp_link_peer_rhash_delete(struct ath12k_dp *dp,
+ struct ath12k_dp_link_peer *peer);
+int ath12k_dp_peer_create(struct ath12k_dp_hw *dp_hw, u8 *addr,
+ struct ath12k_dp_peer_create_params *params);
+void ath12k_dp_peer_delete(struct ath12k_dp_hw *dp_hw, u8 *addr,
+ struct ieee80211_sta *sta);
+struct ath12k_dp_peer *ath12k_dp_peer_find_by_addr(struct ath12k_dp_hw *dp_hw, u8 *addr);
+struct ath12k_dp_peer *ath12k_dp_peer_find_by_addr_and_sta(struct ath12k_dp_hw *dp_hw,
+ u8 *addr,
+ struct ieee80211_sta *sta);
+u16 ath12k_dp_peer_get_peerid_index(struct ath12k_dp *dp, u16 peer_id);
+struct ath12k_dp_peer *ath12k_dp_peer_find_by_peerid(struct ath12k_pdev_dp *dp_pdev,
+ u16 peer_id);
+struct ath12k_dp_link_peer *
+ath12k_dp_link_peer_find_by_peerid(struct ath12k_pdev_dp *dp_pdev, u16 peer_id);
+void ath12k_dp_link_peer_free(struct ath12k_dp_link_peer *peer);
+#endif
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c
index d28d8ffec0f8..a32ee9f8061a 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
@@ -10,257 +10,16 @@
#include <crypto/hash.h>
#include "core.h"
#include "debug.h"
-#include "hal_desc.h"
#include "hw.h"
#include "dp_rx.h"
-#include "hal_rx.h"
#include "dp_tx.h"
#include "peer.h"
#include "dp_mon.h"
#include "debugfs_htt_stats.h"
-#define ATH12K_DP_RX_FRAGMENT_TIMEOUT_MS (2 * HZ)
-
static int ath12k_dp_rx_tid_delete_handler(struct ath12k_base *ab,
struct ath12k_dp_rx_tid_rxq *rx_tid);
-static enum hal_encrypt_type ath12k_dp_rx_h_enctype(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- if (!ab->hal_rx_ops->rx_desc_encrypt_valid(desc))
- return HAL_ENCRYPT_TYPE_OPEN;
-
- return ab->hal_rx_ops->rx_desc_get_encrypt_type(desc);
-}
-
-u8 ath12k_dp_rx_h_decap_type(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->rx_desc_get_decap_type(desc);
-}
-
-static u8 ath12k_dp_rx_h_mesh_ctl_present(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->rx_desc_get_mesh_ctl(desc);
-}
-
-static bool ath12k_dp_rx_h_seq_ctrl_valid(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->rx_desc_get_mpdu_seq_ctl_vld(desc);
-}
-
-static bool ath12k_dp_rx_h_fc_valid(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->rx_desc_get_mpdu_fc_valid(desc);
-}
-
-static bool ath12k_dp_rx_h_more_frags(struct ath12k_base *ab,
- struct sk_buff *skb)
-{
- struct ieee80211_hdr *hdr;
-
- hdr = (struct ieee80211_hdr *)(skb->data + ab->hal.hal_desc_sz);
- return ieee80211_has_morefrags(hdr->frame_control);
-}
-
-static u16 ath12k_dp_rx_h_frag_no(struct ath12k_base *ab,
- struct sk_buff *skb)
-{
- struct ieee80211_hdr *hdr;
-
- hdr = (struct ieee80211_hdr *)(skb->data + ab->hal.hal_desc_sz);
- return le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
-}
-
-static u16 ath12k_dp_rx_h_seq_no(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->rx_desc_get_mpdu_start_seq_no(desc);
-}
-
-static bool ath12k_dp_rx_h_msdu_done(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->dp_rx_h_msdu_done(desc);
-}
-
-static bool ath12k_dp_rx_h_l4_cksum_fail(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->dp_rx_h_l4_cksum_fail(desc);
-}
-
-static bool ath12k_dp_rx_h_ip_cksum_fail(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->dp_rx_h_ip_cksum_fail(desc);
-}
-
-static bool ath12k_dp_rx_h_is_decrypted(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->dp_rx_h_is_decrypted(desc);
-}
-
-u32 ath12k_dp_rx_h_mpdu_err(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->dp_rx_h_mpdu_err(desc);
-}
-
-static u16 ath12k_dp_rx_h_msdu_len(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->rx_desc_get_msdu_len(desc);
-}
-
-static u8 ath12k_dp_rx_h_sgi(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->rx_desc_get_msdu_sgi(desc);
-}
-
-static u8 ath12k_dp_rx_h_rate_mcs(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->rx_desc_get_msdu_rate_mcs(desc);
-}
-
-static u8 ath12k_dp_rx_h_rx_bw(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->rx_desc_get_msdu_rx_bw(desc);
-}
-
-static u32 ath12k_dp_rx_h_freq(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->rx_desc_get_msdu_freq(desc);
-}
-
-static u8 ath12k_dp_rx_h_pkt_type(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->rx_desc_get_msdu_pkt_type(desc);
-}
-
-static u8 ath12k_dp_rx_h_nss(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return hweight8(ab->hal_rx_ops->rx_desc_get_msdu_nss(desc));
-}
-
-static u8 ath12k_dp_rx_h_tid(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->rx_desc_get_mpdu_tid(desc);
-}
-
-static u16 ath12k_dp_rx_h_peer_id(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->rx_desc_get_mpdu_peer_id(desc);
-}
-
-u8 ath12k_dp_rx_h_l3pad(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->rx_desc_get_l3_pad_bytes(desc);
-}
-
-static bool ath12k_dp_rx_h_first_msdu(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->rx_desc_get_first_msdu(desc);
-}
-
-static bool ath12k_dp_rx_h_last_msdu(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->rx_desc_get_last_msdu(desc);
-}
-
-static void ath12k_dp_rx_desc_end_tlv_copy(struct ath12k_base *ab,
- struct hal_rx_desc *fdesc,
- struct hal_rx_desc *ldesc)
-{
- ab->hal_rx_ops->rx_desc_copy_end_tlv(fdesc, ldesc);
-}
-
-static void ath12k_dp_rxdesc_set_msdu_len(struct ath12k_base *ab,
- struct hal_rx_desc *desc,
- u16 len)
-{
- ab->hal_rx_ops->rx_desc_set_msdu_len(desc, len);
-}
-
-u32 ath12k_dp_rxdesc_get_ppduid(struct ath12k_base *ab,
- struct hal_rx_desc *rx_desc)
-{
- return ab->hal_rx_ops->rx_desc_get_mpdu_ppdu_id(rx_desc);
-}
-
-bool ath12k_dp_rxdesc_mpdu_valid(struct ath12k_base *ab,
- struct hal_rx_desc *rx_desc)
-{
- u32 tlv_tag;
-
- tlv_tag = ab->hal_rx_ops->rx_desc_get_mpdu_start_tag(rx_desc);
-
- return tlv_tag == HAL_RX_MPDU_START;
-}
-
-static bool ath12k_dp_rx_h_is_da_mcbc(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return (ath12k_dp_rx_h_first_msdu(ab, desc) &&
- ab->hal_rx_ops->rx_desc_is_da_mcbc(desc));
-}
-
-static bool ath12k_dp_rxdesc_mac_addr2_valid(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->rx_desc_mac_addr2_valid(desc);
-}
-
-static u8 *ath12k_dp_rxdesc_get_mpdu_start_addr2(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->rx_desc_mpdu_start_addr2(desc);
-}
-
-static void ath12k_dp_rx_desc_get_dot11_hdr(struct ath12k_base *ab,
- struct hal_rx_desc *desc,
- struct ieee80211_hdr *hdr)
-{
- ab->hal_rx_ops->rx_desc_get_dot11_hdr(desc, hdr);
-}
-
-static void ath12k_dp_rx_desc_get_crypto_header(struct ath12k_base *ab,
- struct hal_rx_desc *desc,
- u8 *crypto_hdr,
- enum hal_encrypt_type enctype)
-{
- ab->hal_rx_ops->rx_desc_get_crypto_header(desc, crypto_hdr, enctype);
-}
-
-static inline u8 ath12k_dp_rx_get_msdu_src_link(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
-{
- return ab->hal_rx_ops->rx_desc_get_msdu_src_link_id(desc);
-}
-
-static void ath12k_dp_clean_up_skb_list(struct sk_buff_head *skb_list)
-{
- struct sk_buff *skb;
-
- while ((skb = __skb_dequeue(skb_list)))
- dev_kfree_skb_any(skb);
-}
-
static size_t ath12k_dp_list_cut_nodes(struct list_head *list,
struct list_head *head,
size_t count)
@@ -305,11 +64,12 @@ static void ath12k_dp_rx_enqueue_free(struct ath12k_dp *dp,
}
/* Returns number of Rx buffers replenished */
-int ath12k_dp_rx_bufs_replenish(struct ath12k_base *ab,
+int ath12k_dp_rx_bufs_replenish(struct ath12k_dp *dp,
struct dp_rxdma_ring *rx_ring,
struct list_head *used_list,
int req_entries)
{
+ struct ath12k_base *ab = dp->ab;
struct ath12k_buffer_addr *desc;
struct hal_srng *srng;
struct sk_buff *skb;
@@ -317,13 +77,12 @@ int ath12k_dp_rx_bufs_replenish(struct ath12k_base *ab,
int num_remain;
u32 cookie;
dma_addr_t paddr;
- struct ath12k_dp *dp = &ab->dp;
struct ath12k_rx_desc_info *rx_desc;
- enum hal_rx_buf_return_buf_manager mgr = ab->hw_params->hal_params->rx_buf_rbm;
+ enum hal_rx_buf_return_buf_manager mgr = dp->hal->hal_params->rx_buf_rbm;
req_entries = min(req_entries, rx_ring->bufs_max);
- srng = &ab->hal.srng_list[rx_ring->refill_buf_ring.ring_id];
+ srng = &dp->hal->srng_list[rx_ring->refill_buf_ring.ring_id];
spin_lock_bh(&srng->lock);
@@ -362,10 +121,10 @@ int ath12k_dp_rx_bufs_replenish(struct ath12k_base *ab,
skb->data);
}
- paddr = dma_map_single(ab->dev, skb->data,
+ paddr = dma_map_single(dp->dev, skb->data,
skb->len + skb_tailroom(skb),
DMA_FROM_DEVICE);
- if (dma_mapping_error(ab->dev, paddr))
+ if (dma_mapping_error(dp->dev, paddr))
goto fail_free_skb;
rx_desc = list_first_entry_or_null(used_list,
@@ -386,13 +145,14 @@ int ath12k_dp_rx_bufs_replenish(struct ath12k_base *ab,
num_remain--;
- ath12k_hal_rx_buf_addr_info_set(desc, paddr, cookie, mgr);
+ ath12k_hal_rx_buf_addr_info_set(dp->hal, desc, paddr, cookie,
+ mgr);
}
goto out;
fail_dma_unmap:
- dma_unmap_single(ab->dev, paddr, skb->len + skb_tailroom(skb),
+ dma_unmap_single(dp->dev, paddr, skb->len + skb_tailroom(skb),
DMA_FROM_DEVICE);
fail_free_skb:
dev_kfree_skb_any(skb);
@@ -406,6 +166,7 @@ out:
return req_entries - num_remain;
}
+EXPORT_SYMBOL(ath12k_dp_rx_bufs_replenish);
static int ath12k_dp_rxdma_mon_buf_ring_free(struct ath12k_base *ab,
struct dp_rxdma_mon_ring *rx_ring)
@@ -432,7 +193,7 @@ static int ath12k_dp_rxdma_mon_buf_ring_free(struct ath12k_base *ab,
static int ath12k_dp_rxdma_buf_free(struct ath12k_base *ab)
{
- struct ath12k_dp *dp = &ab->dp;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
int i;
ath12k_dp_rxdma_mon_buf_ring_free(ab, &dp->rxdma_mon_buf_ring);
@@ -475,14 +236,14 @@ static int ath12k_dp_rxdma_ring_buf_setup(struct ath12k_base *ab,
rx_ring->bufs_max = rx_ring->refill_buf_ring.size /
ath12k_hal_srng_get_entrysize(ab, HAL_RXDMA_BUF);
- ath12k_dp_rx_bufs_replenish(ab, rx_ring, &list, 0);
+ ath12k_dp_rx_bufs_replenish(ath12k_ab_to_dp(ab), rx_ring, &list, 0);
return 0;
}
static int ath12k_dp_rxdma_buf_setup(struct ath12k_base *ab)
{
- struct ath12k_dp *dp = &ab->dp;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
struct dp_rxdma_mon_ring *mon_ring;
int ret, i;
@@ -529,7 +290,7 @@ static void ath12k_dp_rx_pdev_srng_free(struct ath12k *ar)
void ath12k_dp_rx_pdev_reo_cleanup(struct ath12k_base *ab)
{
- struct ath12k_dp *dp = &ab->dp;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
int i;
for (i = 0; i < DP_REO_DST_RING_MAX; i++)
@@ -538,7 +299,7 @@ void ath12k_dp_rx_pdev_reo_cleanup(struct ath12k_base *ab)
int ath12k_dp_rx_pdev_reo_setup(struct ath12k_base *ab)
{
- struct ath12k_dp *dp = &ab->dp;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
int ret;
int i;
@@ -584,13 +345,15 @@ static int ath12k_dp_rx_pdev_srng_alloc(struct ath12k *ar)
return 0;
}
-static void ath12k_dp_init_rx_tid_rxq(struct ath12k_dp_rx_tid_rxq *rx_tid_rxq,
- struct ath12k_dp_rx_tid *rx_tid)
+void ath12k_dp_init_rx_tid_rxq(struct ath12k_dp_rx_tid_rxq *rx_tid_rxq,
+ struct ath12k_dp_rx_tid *rx_tid,
+ bool active)
{
rx_tid_rxq->tid = rx_tid->tid;
- rx_tid_rxq->active = rx_tid->active;
+ rx_tid_rxq->active = active;
rx_tid_rxq->qbuf = rx_tid->qbuf;
}
+EXPORT_SYMBOL(ath12k_dp_init_rx_tid_rxq);
static void ath12k_dp_rx_tid_cleanup(struct ath12k_base *ab,
struct ath12k_reoq_buf *tid_qbuf)
@@ -605,7 +368,7 @@ static void ath12k_dp_rx_tid_cleanup(struct ath12k_base *ab,
void ath12k_dp_rx_reo_cmd_list_cleanup(struct ath12k_base *ab)
{
- struct ath12k_dp *dp = &ab->dp;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
struct ath12k_dp_rx_reo_cmd *cmd, *tmp;
struct ath12k_dp_rx_reo_cache_flush_elem *cmd_cache, *tmp_cache;
struct dp_reo_update_rx_queue_elem *cmd_queue, *tmp_queue;
@@ -635,8 +398,8 @@ void ath12k_dp_rx_reo_cmd_list_cleanup(struct ath12k_base *ab)
spin_unlock_bh(&dp->reo_cmd_lock);
}
-static void ath12k_dp_reo_cmd_free(struct ath12k_dp *dp, void *ctx,
- enum hal_reo_cmd_status status)
+void ath12k_dp_reo_cmd_free(struct ath12k_dp *dp, void *ctx,
+ enum hal_reo_cmd_status status)
{
struct ath12k_dp_rx_tid_rxq *rx_tid = ctx;
@@ -646,109 +409,9 @@ static void ath12k_dp_reo_cmd_free(struct ath12k_dp *dp, void *ctx,
ath12k_dp_rx_tid_cleanup(dp->ab, &rx_tid->qbuf);
}
+EXPORT_SYMBOL(ath12k_dp_reo_cmd_free);
-static int ath12k_dp_reo_cmd_send(struct ath12k_base *ab,
- struct ath12k_dp_rx_tid_rxq *rx_tid,
- enum hal_reo_cmd_type type,
- struct ath12k_hal_reo_cmd *cmd,
- void (*cb)(struct ath12k_dp *dp, void *ctx,
- enum hal_reo_cmd_status status))
-{
- struct ath12k_dp *dp = &ab->dp;
- struct ath12k_dp_rx_reo_cmd *dp_cmd;
- struct hal_srng *cmd_ring;
- int cmd_num;
-
- cmd_ring = &ab->hal.srng_list[dp->reo_cmd_ring.ring_id];
- cmd_num = ath12k_hal_reo_cmd_send(ab, cmd_ring, type, cmd);
-
- /* cmd_num should start from 1, during failure return the error code */
- if (cmd_num < 0)
- return cmd_num;
-
- /* reo cmd ring descriptors has cmd_num starting from 1 */
- if (cmd_num == 0)
- return -EINVAL;
-
- if (!cb)
- return 0;
-
- /* Can this be optimized so that we keep the pending command list only
- * for tid delete command to free up the resource on the command status
- * indication?
- */
- dp_cmd = kzalloc(sizeof(*dp_cmd), GFP_ATOMIC);
-
- if (!dp_cmd)
- return -ENOMEM;
-
- memcpy(&dp_cmd->data, rx_tid, sizeof(*rx_tid));
- dp_cmd->cmd_num = cmd_num;
- dp_cmd->handler = cb;
-
- spin_lock_bh(&dp->reo_cmd_lock);
- list_add_tail(&dp_cmd->list, &dp->reo_cmd_list);
- spin_unlock_bh(&dp->reo_cmd_lock);
-
- return 0;
-}
-
-static int ath12k_dp_reo_cache_flush(struct ath12k_base *ab,
- struct ath12k_dp_rx_tid_rxq *rx_tid)
-{
- struct ath12k_hal_reo_cmd cmd = {};
- int ret;
-
- cmd.addr_lo = lower_32_bits(rx_tid->qbuf.paddr_aligned);
- cmd.addr_hi = upper_32_bits(rx_tid->qbuf.paddr_aligned);
- /* HAL_REO_CMD_FLG_FLUSH_FWD_ALL_MPDUS - all pending MPDUs
- *in the bitmap will be forwarded/flushed to REO output rings
- */
- cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS |
- HAL_REO_CMD_FLG_FLUSH_FWD_ALL_MPDUS;
-
- /* For all QoS TIDs (except NON_QOS), the driver allocates a maximum
- * window size of 1024. In such cases, the driver can issue a single
- * 1KB descriptor flush command instead of sending multiple 128-byte
- * flush commands for each QoS TID, improving efficiency.
- */
-
- if (rx_tid->tid != HAL_DESC_REO_NON_QOS_TID)
- cmd.flag |= HAL_REO_CMD_FLG_FLUSH_QUEUE_1K_DESC;
-
- ret = ath12k_dp_reo_cmd_send(ab, rx_tid,
- HAL_REO_CMD_FLUSH_CACHE,
- &cmd, ath12k_dp_reo_cmd_free);
- return ret;
-}
-
-static void ath12k_peer_rx_tid_qref_reset(struct ath12k_base *ab, u16 peer_id, u16 tid)
-{
- struct ath12k_reo_queue_ref *qref;
- struct ath12k_dp *dp = &ab->dp;
- bool ml_peer = false;
-
- if (!ab->hw_params->reoq_lut_support)
- return;
-
- if (peer_id & ATH12K_PEER_ML_ID_VALID) {
- peer_id &= ~ATH12K_PEER_ML_ID_VALID;
- ml_peer = true;
- }
-
- if (ml_peer)
- qref = (struct ath12k_reo_queue_ref *)dp->ml_reoq_lut.vaddr +
- (peer_id * (IEEE80211_NUM_TIDS + 1) + tid);
- else
- qref = (struct ath12k_reo_queue_ref *)dp->reoq_lut.vaddr +
- (peer_id * (IEEE80211_NUM_TIDS + 1) + tid);
-
- qref->info0 = u32_encode_bits(0, BUFFER_ADDR_INFO0_ADDR);
- qref->info1 = u32_encode_bits(0, BUFFER_ADDR_INFO1_ADDR) |
- u32_encode_bits(tid, DP_REO_QREF_NUM);
-}
-
-static void ath12k_dp_rx_process_reo_cmd_update_rx_queue_list(struct ath12k_dp *dp)
+void ath12k_dp_rx_process_reo_cmd_update_rx_queue_list(struct ath12k_dp *dp)
{
struct ath12k_base *ab = dp->ab;
struct dp_reo_update_rx_queue_elem *elem, *tmp;
@@ -762,10 +425,10 @@ static void ath12k_dp_rx_process_reo_cmd_update_rx_queue_list(struct ath12k_dp *
if (ath12k_dp_rx_tid_delete_handler(ab, &elem->rx_tid))
break;
- ath12k_peer_rx_tid_qref_reset(ab,
- elem->is_ml_peer ? elem->ml_peer_id :
- elem->peer_id,
- elem->rx_tid.tid);
+ ath12k_dp_arch_peer_rx_tid_qref_reset(dp,
+ elem->is_ml_peer ?
+ elem->ml_peer_id : elem->peer_id,
+ elem->rx_tid.tid);
if (ab->hw_params->reoq_lut_support)
ath12k_hal_reo_shared_qaddr_cache_clear(ab);
@@ -776,9 +439,10 @@ static void ath12k_dp_rx_process_reo_cmd_update_rx_queue_list(struct ath12k_dp *
spin_unlock_bh(&dp->reo_rxq_flush_lock);
}
+EXPORT_SYMBOL(ath12k_dp_rx_process_reo_cmd_update_rx_queue_list);
-static void ath12k_dp_rx_tid_del_func(struct ath12k_dp *dp, void *ctx,
- enum hal_reo_cmd_status status)
+void ath12k_dp_rx_tid_del_func(struct ath12k_dp *dp, void *ctx,
+ enum hal_reo_cmd_status status)
{
struct ath12k_base *ab = dp->ab;
struct ath12k_dp_rx_tid_rxq *rx_tid = ctx;
@@ -796,9 +460,9 @@ static void ath12k_dp_rx_tid_del_func(struct ath12k_dp *dp, void *ctx,
/* Retry the HAL_REO_CMD_UPDATE_RX_QUEUE command for entries
* in the pending queue list marked TID as inactive
*/
- spin_lock_bh(&dp->ab->base_lock);
+ spin_lock_bh(&dp->dp_lock);
ath12k_dp_rx_process_reo_cmd_update_rx_queue_list(dp);
- spin_unlock_bh(&dp->ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
elem = kzalloc(sizeof(*elem), GFP_ATOMIC);
if (!elem)
@@ -825,11 +489,12 @@ static void ath12k_dp_rx_tid_del_func(struct ath12k_dp *dp, void *ctx,
* will be called during core destroy.
*/
- if (ath12k_dp_reo_cache_flush(ab, &elem->data))
+ if (ath12k_dp_arch_reo_cache_flush(dp, &elem->data))
break;
list_del(&elem->list);
dp->reo_cmd_cache_flush_count--;
+
kfree(elem);
}
}
@@ -839,55 +504,17 @@ static void ath12k_dp_rx_tid_del_func(struct ath12k_dp *dp, void *ctx,
free_desc:
ath12k_dp_rx_tid_cleanup(ab, &rx_tid->qbuf);
}
+EXPORT_SYMBOL(ath12k_dp_rx_tid_del_func);
static int ath12k_dp_rx_tid_delete_handler(struct ath12k_base *ab,
struct ath12k_dp_rx_tid_rxq *rx_tid)
{
- struct ath12k_hal_reo_cmd cmd = {};
-
- cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS;
- cmd.addr_lo = lower_32_bits(rx_tid->qbuf.paddr_aligned);
- cmd.addr_hi = upper_32_bits(rx_tid->qbuf.paddr_aligned);
- cmd.upd0 |= HAL_REO_CMD_UPD0_VLD;
- /* Observed flush cache failure, to avoid that set vld bit during delete */
- cmd.upd1 |= HAL_REO_CMD_UPD1_VLD;
-
- return ath12k_dp_reo_cmd_send(ab, rx_tid,
- HAL_REO_CMD_UPDATE_RX_QUEUE, &cmd,
- ath12k_dp_rx_tid_del_func);
-}
-
-static void ath12k_peer_rx_tid_qref_setup(struct ath12k_base *ab, u16 peer_id, u16 tid,
- dma_addr_t paddr)
-{
- struct ath12k_reo_queue_ref *qref;
- struct ath12k_dp *dp = &ab->dp;
- bool ml_peer = false;
-
- if (!ab->hw_params->reoq_lut_support)
- return;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
- if (peer_id & ATH12K_PEER_ML_ID_VALID) {
- peer_id &= ~ATH12K_PEER_ML_ID_VALID;
- ml_peer = true;
- }
-
- if (ml_peer)
- qref = (struct ath12k_reo_queue_ref *)dp->ml_reoq_lut.vaddr +
- (peer_id * (IEEE80211_NUM_TIDS + 1) + tid);
- else
- qref = (struct ath12k_reo_queue_ref *)dp->reoq_lut.vaddr +
- (peer_id * (IEEE80211_NUM_TIDS + 1) + tid);
-
- qref->info0 = u32_encode_bits(lower_32_bits(paddr),
- BUFFER_ADDR_INFO0_ADDR);
- qref->info1 = u32_encode_bits(upper_32_bits(paddr),
- BUFFER_ADDR_INFO1_ADDR) |
- u32_encode_bits(tid, DP_REO_QREF_NUM);
- ath12k_hal_reo_shared_qaddr_cache_clear(ab);
+ return ath12k_dp_arch_rx_tid_delete_handler(dp, rx_tid);
}
-static void ath12k_dp_mark_tid_as_inactive(struct ath12k_dp *dp, int peer_id, u8 tid)
+void ath12k_dp_mark_tid_as_inactive(struct ath12k_dp *dp, int peer_id, u8 tid)
{
struct dp_reo_update_rx_queue_elem *elem;
struct ath12k_dp_rx_tid_rxq *rx_tid;
@@ -904,192 +531,39 @@ static void ath12k_dp_mark_tid_as_inactive(struct ath12k_dp *dp, int peer_id, u8
}
spin_unlock_bh(&dp->reo_rxq_flush_lock);
}
+EXPORT_SYMBOL(ath12k_dp_mark_tid_as_inactive);
-void ath12k_dp_rx_peer_tid_delete(struct ath12k *ar,
- struct ath12k_peer *peer, u8 tid)
-{
- struct ath12k_dp_rx_tid *rx_tid = &peer->rx_tid[tid];
- struct ath12k_base *ab = ar->ab;
- struct ath12k_dp *dp = &ab->dp;
-
- if (!rx_tid->active)
- return;
-
- rx_tid->active = false;
-
- ath12k_dp_mark_tid_as_inactive(dp, peer->peer_id, tid);
- ath12k_dp_rx_process_reo_cmd_update_rx_queue_list(dp);
-}
-
-int ath12k_dp_rx_link_desc_return(struct ath12k_base *ab,
- struct ath12k_buffer_addr *buf_addr_info,
- enum hal_wbm_rel_bm_act action)
-{
- struct hal_wbm_release_ring *desc;
- struct ath12k_dp *dp = &ab->dp;
- struct hal_srng *srng;
- int ret = 0;
-
- srng = &ab->hal.srng_list[dp->wbm_desc_rel_ring.ring_id];
-
- spin_lock_bh(&srng->lock);
-
- ath12k_hal_srng_access_begin(ab, srng);
-
- desc = ath12k_hal_srng_src_get_next_entry(ab, srng);
- if (!desc) {
- ret = -ENOBUFS;
- goto exit;
- }
-
- ath12k_hal_rx_msdu_link_desc_set(ab, desc, buf_addr_info, action);
-
-exit:
- ath12k_hal_srng_access_end(ab, srng);
-
- spin_unlock_bh(&srng->lock);
-
- return ret;
-}
-
-static void ath12k_dp_rx_frags_cleanup(struct ath12k_dp_rx_tid *rx_tid,
- bool rel_link_desc)
-{
- struct ath12k_buffer_addr *buf_addr_info;
- struct ath12k_base *ab = rx_tid->ab;
-
- lockdep_assert_held(&ab->base_lock);
-
- if (rx_tid->dst_ring_desc) {
- if (rel_link_desc) {
- buf_addr_info = &rx_tid->dst_ring_desc->buf_addr_info;
- ath12k_dp_rx_link_desc_return(ab, buf_addr_info,
- HAL_WBM_REL_BM_ACT_PUT_IN_IDLE);
- }
- kfree(rx_tid->dst_ring_desc);
- rx_tid->dst_ring_desc = NULL;
- }
-
- rx_tid->cur_sn = 0;
- rx_tid->last_frag_no = 0;
- rx_tid->rx_frag_bitmap = 0;
- __skb_queue_purge(&rx_tid->rx_frags);
-}
-
-void ath12k_dp_rx_peer_tid_cleanup(struct ath12k *ar, struct ath12k_peer *peer)
+void ath12k_dp_rx_peer_tid_cleanup(struct ath12k *ar, struct ath12k_dp_link_peer *peer)
{
struct ath12k_dp_rx_tid *rx_tid;
int i;
+ struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+
+ lockdep_assert_held(&dp->dp_lock);
- lockdep_assert_held(&ar->ab->base_lock);
+ if (!peer->primary_link)
+ return;
for (i = 0; i <= IEEE80211_NUM_TIDS; i++) {
- rx_tid = &peer->rx_tid[i];
+ rx_tid = &peer->dp_peer->rx_tid[i];
- ath12k_dp_rx_peer_tid_delete(ar, peer, i);
- ath12k_dp_rx_frags_cleanup(rx_tid, true);
+ ath12k_dp_arch_rx_peer_tid_delete(dp, peer, i);
+ ath12k_dp_arch_rx_frags_cleanup(dp, rx_tid, true);
- spin_unlock_bh(&ar->ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
timer_delete_sync(&rx_tid->frag_timer);
- spin_lock_bh(&ar->ab->base_lock);
+ spin_lock_bh(&dp->dp_lock);
}
}
-static int ath12k_peer_rx_tid_reo_update(struct ath12k *ar,
- struct ath12k_peer *peer,
- struct ath12k_dp_rx_tid *rx_tid,
- u32 ba_win_sz, u16 ssn,
- bool update_ssn)
-{
- struct ath12k_hal_reo_cmd cmd = {};
- int ret;
- struct ath12k_dp_rx_tid_rxq rx_tid_rxq;
-
- ath12k_dp_init_rx_tid_rxq(&rx_tid_rxq, rx_tid);
-
- cmd.addr_lo = lower_32_bits(rx_tid_rxq.qbuf.paddr_aligned);
- cmd.addr_hi = upper_32_bits(rx_tid_rxq.qbuf.paddr_aligned);
- cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS;
- cmd.upd0 = HAL_REO_CMD_UPD0_BA_WINDOW_SIZE;
- cmd.ba_window_size = ba_win_sz;
-
- if (update_ssn) {
- cmd.upd0 |= HAL_REO_CMD_UPD0_SSN;
- cmd.upd2 = u32_encode_bits(ssn, HAL_REO_CMD_UPD2_SSN);
- }
-
- ret = ath12k_dp_reo_cmd_send(ar->ab, &rx_tid_rxq,
- HAL_REO_CMD_UPDATE_RX_QUEUE, &cmd,
- NULL);
- if (ret) {
- ath12k_warn(ar->ab, "failed to update rx tid queue, tid %d (%d)\n",
- rx_tid_rxq.tid, ret);
- return ret;
- }
-
- rx_tid->ba_win_sz = ba_win_sz;
-
- return 0;
-}
-
-static int ath12k_dp_rx_assign_reoq(struct ath12k_base *ab,
- struct ath12k_sta *ahsta,
- struct ath12k_dp_rx_tid *rx_tid,
- u16 ssn, enum hal_pn_type pn_type)
-{
- u32 ba_win_sz = rx_tid->ba_win_sz;
- struct ath12k_reoq_buf *buf;
- void *vaddr, *vaddr_aligned;
- dma_addr_t paddr_aligned;
- u8 tid = rx_tid->tid;
- u32 hw_desc_sz;
- int ret;
-
- buf = &ahsta->reoq_bufs[tid];
- if (!buf->vaddr) {
- /* TODO: Optimize the memory allocation for qos tid based on
- * the actual BA window size in REO tid update path.
- */
- if (tid == HAL_DESC_REO_NON_QOS_TID)
- hw_desc_sz = ath12k_hal_reo_qdesc_size(ba_win_sz, tid);
- else
- hw_desc_sz = ath12k_hal_reo_qdesc_size(DP_BA_WIN_SZ_MAX, tid);
-
- vaddr = kzalloc(hw_desc_sz + HAL_LINK_DESC_ALIGN - 1, GFP_ATOMIC);
- if (!vaddr)
- return -ENOMEM;
-
- vaddr_aligned = PTR_ALIGN(vaddr, HAL_LINK_DESC_ALIGN);
-
- ath12k_hal_reo_qdesc_setup(vaddr_aligned, tid, ba_win_sz,
- ssn, pn_type);
-
- paddr_aligned = dma_map_single(ab->dev, vaddr_aligned, hw_desc_sz,
- DMA_BIDIRECTIONAL);
- ret = dma_mapping_error(ab->dev, paddr_aligned);
- if (ret) {
- kfree(vaddr);
- return ret;
- }
-
- buf->vaddr = vaddr;
- buf->paddr_aligned = paddr_aligned;
- buf->size = hw_desc_sz;
- }
-
- rx_tid->qbuf = *buf;
- rx_tid->active = true;
-
- return 0;
-}
-
static int ath12k_dp_prepare_reo_update_elem(struct ath12k_dp *dp,
- struct ath12k_peer *peer,
+ struct ath12k_dp_link_peer *peer,
struct ath12k_dp_rx_tid *rx_tid)
{
struct dp_reo_update_rx_queue_elem *elem;
- lockdep_assert_held(&dp->ab->base_lock);
+ lockdep_assert_held(&dp->dp_lock);
elem = kzalloc(sizeof(*elem), GFP_ATOMIC);
if (!elem)
@@ -1099,7 +573,8 @@ static int ath12k_dp_prepare_reo_update_elem(struct ath12k_dp *dp,
elem->is_ml_peer = peer->mlo;
elem->ml_peer_id = peer->ml_id;
- ath12k_dp_init_rx_tid_rxq(&elem->rx_tid, rx_tid);
+ ath12k_dp_init_rx_tid_rxq(&elem->rx_tid, rx_tid,
+ (peer->rx_tid_active_bitmask & (1 << rx_tid->tid)));
spin_lock_bh(&dp->reo_rxq_flush_lock);
list_add_tail(&elem->list, &dp->reo_cmd_update_rx_queue_list);
@@ -1113,31 +588,30 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_
enum hal_pn_type pn_type)
{
struct ath12k_base *ab = ar->ab;
- struct ath12k_dp *dp = &ab->dp;
- struct ath12k_peer *peer;
- struct ath12k_sta *ahsta;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_dp_link_peer *peer;
struct ath12k_dp_rx_tid *rx_tid;
dma_addr_t paddr_aligned;
int ret;
- spin_lock_bh(&ab->base_lock);
+ spin_lock_bh(&dp->dp_lock);
- peer = ath12k_peer_find(ab, vdev_id, peer_mac);
- if (!peer) {
- spin_unlock_bh(&ab->base_lock);
+ peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, peer_mac);
+ if (!peer || !peer->dp_peer) {
+ spin_unlock_bh(&dp->dp_lock);
ath12k_warn(ab, "failed to find the peer to set up rx tid\n");
return -ENOENT;
}
if (ab->hw_params->dp_primary_link_only &&
!peer->primary_link) {
- spin_unlock_bh(&ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
return 0;
}
if (ab->hw_params->reoq_lut_support &&
(!dp->reoq_lut.vaddr || !dp->ml_reoq_lut.vaddr)) {
- spin_unlock_bh(&ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
ath12k_warn(ab, "reo qref table is not setup\n");
return -EINVAL;
}
@@ -1145,16 +619,16 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_
if (peer->peer_id > DP_MAX_PEER_ID || tid > IEEE80211_NUM_TIDS) {
ath12k_warn(ab, "peer id of peer %d or tid %d doesn't allow reoq setup\n",
peer->peer_id, tid);
- spin_unlock_bh(&ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
return -EINVAL;
}
- rx_tid = &peer->rx_tid[tid];
+ rx_tid = &peer->dp_peer->rx_tid[tid];
/* Update the tid queue if it is already setup */
- if (rx_tid->active) {
- ret = ath12k_peer_rx_tid_reo_update(ar, peer, rx_tid,
- ba_win_sz, ssn, true);
- spin_unlock_bh(&ab->base_lock);
+ if (peer->rx_tid_active_bitmask & (1 << tid)) {
+ ret = ath12k_dp_arch_peer_rx_tid_reo_update(dp, peer, rx_tid,
+ ba_win_sz, ssn, true);
+ spin_unlock_bh(&dp->dp_lock);
if (ret) {
ath12k_warn(ab, "failed to update reo for rx tid %d\n", tid);
return ret;
@@ -1180,14 +654,15 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_
rx_tid->ba_win_sz = ba_win_sz;
- ahsta = ath12k_sta_to_ahsta(peer->sta);
- ret = ath12k_dp_rx_assign_reoq(ab, ahsta, rx_tid, ssn, pn_type);
+ ret = ath12k_dp_arch_rx_assign_reoq(dp, peer->dp_peer, rx_tid, ssn, pn_type);
if (ret) {
- spin_unlock_bh(&ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
ath12k_warn(ab, "failed to assign reoq buf for rx tid %u\n", tid);
return ret;
}
+ peer->rx_tid_active_bitmask |= (1 << tid);
+
/* Pre-allocate the update_rxq_list for the corresponding tid
* This will be used during the tid delete. The reason we are not
* allocating during tid delete is that, if any alloc fail in update_rxq_list
@@ -1197,7 +672,7 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_
if (ret) {
ath12k_warn(ab, "failed to alloc update_rxq_list for rx tid %u\n", tid);
ath12k_dp_rx_tid_cleanup(ab, &rx_tid->qbuf);
- spin_unlock_bh(&ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
return ret;
}
@@ -1207,15 +682,15 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_
* and tid with qaddr.
*/
if (peer->mlo)
- ath12k_peer_rx_tid_qref_setup(ab, peer->ml_id, tid,
- paddr_aligned);
+ ath12k_dp_arch_peer_rx_tid_qref_setup(dp, peer->ml_id, tid,
+ paddr_aligned);
else
- ath12k_peer_rx_tid_qref_setup(ab, peer->peer_id, tid,
- paddr_aligned);
+ ath12k_dp_arch_peer_rx_tid_qref_setup(dp, peer->peer_id, tid,
+ paddr_aligned);
- spin_unlock_bh(&ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
} else {
- spin_unlock_bh(&ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
ret = ath12k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, peer_mac,
paddr_aligned, tid, 1,
ba_win_sz);
@@ -1257,7 +732,8 @@ int ath12k_dp_rx_ampdu_stop(struct ath12k *ar,
u8 link_id)
{
struct ath12k_base *ab = ar->ab;
- struct ath12k_peer *peer;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_dp_link_peer *peer;
struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(params->sta);
struct ath12k_link_sta *arsta;
int vdev_id;
@@ -1273,24 +749,30 @@ int ath12k_dp_rx_ampdu_stop(struct ath12k *ar,
vdev_id = arsta->arvif->vdev_id;
- spin_lock_bh(&ab->base_lock);
+ spin_lock_bh(&dp->dp_lock);
- peer = ath12k_peer_find(ab, vdev_id, arsta->addr);
- if (!peer) {
- spin_unlock_bh(&ab->base_lock);
+ peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, arsta->addr);
+ if (!peer || !peer->dp_peer) {
+ spin_unlock_bh(&dp->dp_lock);
ath12k_warn(ab, "failed to find the peer to stop rx aggregation\n");
return -ENOENT;
}
- active = peer->rx_tid[params->tid].active;
+ if (ab->hw_params->dp_primary_link_only &&
+ !peer->primary_link) {
+ spin_unlock_bh(&dp->dp_lock);
+ return 0;
+ }
+ active = peer->rx_tid_active_bitmask & (1 << params->tid);
if (!active) {
- spin_unlock_bh(&ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
return 0;
}
- ret = ath12k_peer_rx_tid_reo_update(ar, peer, peer->rx_tid, 1, 0, false);
- spin_unlock_bh(&ab->base_lock);
+ ret = ath12k_dp_arch_peer_rx_tid_reo_update(dp, peer, peer->dp_peer->rx_tid,
+ 1, 0, false);
+ spin_unlock_bh(&dp->dp_lock);
if (ret) {
ath12k_warn(ab, "failed to update reo for rx tid %d: %d\n",
params->tid, ret);
@@ -1307,8 +789,9 @@ int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif,
{
struct ath12k *ar = arvif->ar;
struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
struct ath12k_hal_reo_cmd cmd = {};
- struct ath12k_peer *peer;
+ struct ath12k_dp_link_peer *peer;
struct ath12k_dp_rx_tid *rx_tid;
struct ath12k_dp_rx_tid_rxq rx_tid_rxq;
u8 tid;
@@ -1321,49 +804,29 @@ int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif,
if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
return 0;
- cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS;
- cmd.upd0 = HAL_REO_CMD_UPD0_PN |
- HAL_REO_CMD_UPD0_PN_SIZE |
- HAL_REO_CMD_UPD0_PN_VALID |
- HAL_REO_CMD_UPD0_PN_CHECK |
- HAL_REO_CMD_UPD0_SVLD;
-
- switch (key->cipher) {
- case WLAN_CIPHER_SUITE_TKIP:
- case WLAN_CIPHER_SUITE_CCMP:
- case WLAN_CIPHER_SUITE_CCMP_256:
- case WLAN_CIPHER_SUITE_GCMP:
- case WLAN_CIPHER_SUITE_GCMP_256:
- if (key_cmd == SET_KEY) {
- cmd.upd1 |= HAL_REO_CMD_UPD1_PN_CHECK;
- cmd.pn_size = 48;
- }
- break;
- default:
- break;
- }
-
- spin_lock_bh(&ab->base_lock);
+ spin_lock_bh(&dp->dp_lock);
- peer = ath12k_peer_find(ab, arvif->vdev_id, peer_addr);
- if (!peer) {
- spin_unlock_bh(&ab->base_lock);
+ peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id,
+ peer_addr);
+ if (!peer || !peer->dp_peer) {
+ spin_unlock_bh(&dp->dp_lock);
ath12k_warn(ab, "failed to find the peer %pM to configure pn replay detection\n",
peer_addr);
return -ENOENT;
}
for (tid = 0; tid <= IEEE80211_NUM_TIDS; tid++) {
- rx_tid = &peer->rx_tid[tid];
- if (!rx_tid->active)
+ if (!(peer->rx_tid_active_bitmask & (1 << tid)))
continue;
- ath12k_dp_init_rx_tid_rxq(&rx_tid_rxq, rx_tid);
- cmd.addr_lo = lower_32_bits(rx_tid_rxq.qbuf.paddr_aligned);
- cmd.addr_hi = upper_32_bits(rx_tid_rxq.qbuf.paddr_aligned);
- ret = ath12k_dp_reo_cmd_send(ab, &rx_tid_rxq,
- HAL_REO_CMD_UPDATE_RX_QUEUE,
- &cmd, NULL);
+ rx_tid = &peer->dp_peer->rx_tid[tid];
+ ath12k_dp_init_rx_tid_rxq(&rx_tid_rxq, rx_tid,
+ (peer->rx_tid_active_bitmask & (1 << tid)));
+ ath12k_dp_arch_setup_pn_check_reo_cmd(dp, &cmd, rx_tid, key->cipher,
+ key_cmd);
+ ret = ath12k_dp_arch_reo_cmd_send(dp, &rx_tid_rxq,
+ HAL_REO_CMD_UPDATE_RX_QUEUE,
+ &cmd, NULL);
if (ret) {
ath12k_warn(ab, "failed to configure rx tid %d queue of peer %pM for pn replay detection %d\n",
tid, peer_addr, ret);
@@ -1371,732 +834,14 @@ int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif,
}
}
- spin_unlock_bh(&ab->base_lock);
-
- return ret;
-}
-
-static int ath12k_get_ppdu_user_index(struct htt_ppdu_stats *ppdu_stats,
- u16 peer_id)
-{
- int i;
-
- for (i = 0; i < HTT_PPDU_STATS_MAX_USERS - 1; i++) {
- if (ppdu_stats->user_stats[i].is_valid_peer_id) {
- if (peer_id == ppdu_stats->user_stats[i].peer_id)
- return i;
- } else {
- return i;
- }
- }
-
- return -EINVAL;
-}
-
-static int ath12k_htt_tlv_ppdu_stats_parse(struct ath12k_base *ab,
- u16 tag, u16 len, const void *ptr,
- void *data)
-{
- const struct htt_ppdu_stats_usr_cmpltn_ack_ba_status *ba_status;
- const struct htt_ppdu_stats_usr_cmpltn_cmn *cmplt_cmn;
- const struct htt_ppdu_stats_user_rate *user_rate;
- struct htt_ppdu_stats_info *ppdu_info;
- struct htt_ppdu_user_stats *user_stats;
- int cur_user;
- u16 peer_id;
-
- ppdu_info = data;
-
- switch (tag) {
- case HTT_PPDU_STATS_TAG_COMMON:
- if (len < sizeof(struct htt_ppdu_stats_common)) {
- ath12k_warn(ab, "Invalid len %d for the tag 0x%x\n",
- len, tag);
- return -EINVAL;
- }
- memcpy(&ppdu_info->ppdu_stats.common, ptr,
- sizeof(struct htt_ppdu_stats_common));
- break;
- case HTT_PPDU_STATS_TAG_USR_RATE:
- if (len < sizeof(struct htt_ppdu_stats_user_rate)) {
- ath12k_warn(ab, "Invalid len %d for the tag 0x%x\n",
- len, tag);
- return -EINVAL;
- }
- user_rate = ptr;
- peer_id = le16_to_cpu(user_rate->sw_peer_id);
- cur_user = ath12k_get_ppdu_user_index(&ppdu_info->ppdu_stats,
- peer_id);
- if (cur_user < 0)
- return -EINVAL;
- user_stats = &ppdu_info->ppdu_stats.user_stats[cur_user];
- user_stats->peer_id = peer_id;
- user_stats->is_valid_peer_id = true;
- memcpy(&user_stats->rate, ptr,
- sizeof(struct htt_ppdu_stats_user_rate));
- user_stats->tlv_flags |= BIT(tag);
- break;
- case HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON:
- if (len < sizeof(struct htt_ppdu_stats_usr_cmpltn_cmn)) {
- ath12k_warn(ab, "Invalid len %d for the tag 0x%x\n",
- len, tag);
- return -EINVAL;
- }
-
- cmplt_cmn = ptr;
- peer_id = le16_to_cpu(cmplt_cmn->sw_peer_id);
- cur_user = ath12k_get_ppdu_user_index(&ppdu_info->ppdu_stats,
- peer_id);
- if (cur_user < 0)
- return -EINVAL;
- user_stats = &ppdu_info->ppdu_stats.user_stats[cur_user];
- user_stats->peer_id = peer_id;
- user_stats->is_valid_peer_id = true;
- memcpy(&user_stats->cmpltn_cmn, ptr,
- sizeof(struct htt_ppdu_stats_usr_cmpltn_cmn));
- user_stats->tlv_flags |= BIT(tag);
- break;
- case HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS:
- if (len <
- sizeof(struct htt_ppdu_stats_usr_cmpltn_ack_ba_status)) {
- ath12k_warn(ab, "Invalid len %d for the tag 0x%x\n",
- len, tag);
- return -EINVAL;
- }
-
- ba_status = ptr;
- peer_id = le16_to_cpu(ba_status->sw_peer_id);
- cur_user = ath12k_get_ppdu_user_index(&ppdu_info->ppdu_stats,
- peer_id);
- if (cur_user < 0)
- return -EINVAL;
- user_stats = &ppdu_info->ppdu_stats.user_stats[cur_user];
- user_stats->peer_id = peer_id;
- user_stats->is_valid_peer_id = true;
- memcpy(&user_stats->ack_ba, ptr,
- sizeof(struct htt_ppdu_stats_usr_cmpltn_ack_ba_status));
- user_stats->tlv_flags |= BIT(tag);
- break;
- }
- return 0;
-}
-
-int ath12k_dp_htt_tlv_iter(struct ath12k_base *ab, const void *ptr, size_t len,
- int (*iter)(struct ath12k_base *ar, u16 tag, u16 len,
- const void *ptr, void *data),
- void *data)
-{
- const struct htt_tlv *tlv;
- const void *begin = ptr;
- u16 tlv_tag, tlv_len;
- int ret = -EINVAL;
-
- while (len > 0) {
- if (len < sizeof(*tlv)) {
- ath12k_err(ab, "htt tlv parse failure at byte %zd (%zu bytes left, %zu expected)\n",
- ptr - begin, len, sizeof(*tlv));
- return -EINVAL;
- }
- tlv = (struct htt_tlv *)ptr;
- tlv_tag = le32_get_bits(tlv->header, HTT_TLV_TAG);
- tlv_len = le32_get_bits(tlv->header, HTT_TLV_LEN);
- ptr += sizeof(*tlv);
- len -= sizeof(*tlv);
-
- if (tlv_len > len) {
- ath12k_err(ab, "htt tlv parse failure of tag %u at byte %zd (%zu bytes left, %u expected)\n",
- tlv_tag, ptr - begin, len, tlv_len);
- return -EINVAL;
- }
- ret = iter(ab, tlv_tag, tlv_len, ptr, data);
- if (ret == -ENOMEM)
- return ret;
-
- ptr += tlv_len;
- len -= tlv_len;
- }
- return 0;
-}
-
-static void
-ath12k_update_per_peer_tx_stats(struct ath12k *ar,
- struct htt_ppdu_stats *ppdu_stats, u8 user)
-{
- struct ath12k_base *ab = ar->ab;
- struct ath12k_peer *peer;
- 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];
- struct htt_ppdu_stats_common *common = &ppdu_stats->common;
- int ret;
- u8 flags, mcs, nss, bw, sgi, dcm, ppdu_type, rate_idx = 0;
- u32 v, succ_bytes = 0;
- u16 tones, rate = 0, succ_pkts = 0;
- u32 tx_duration = 0;
- u8 tid = HTT_PPDU_STATS_NON_QOS_TID;
- u16 tx_retry_failed = 0, tx_retry_count = 0;
- bool is_ampdu = false, is_ofdma;
-
- if (!(usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_RATE)))
- return;
-
- if (usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON)) {
- is_ampdu =
- HTT_USR_CMPLTN_IS_AMPDU(usr_stats->cmpltn_cmn.flags);
- tx_retry_failed =
- __le16_to_cpu(usr_stats->cmpltn_cmn.mpdu_tried) -
- __le16_to_cpu(usr_stats->cmpltn_cmn.mpdu_success);
- tx_retry_count =
- HTT_USR_CMPLTN_LONG_RETRY(usr_stats->cmpltn_cmn.flags) +
- HTT_USR_CMPLTN_SHORT_RETRY(usr_stats->cmpltn_cmn.flags);
- }
-
- if (usr_stats->tlv_flags &
- BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS)) {
- succ_bytes = le32_to_cpu(usr_stats->ack_ba.success_bytes);
- succ_pkts = le32_get_bits(usr_stats->ack_ba.info,
- HTT_PPDU_STATS_ACK_BA_INFO_NUM_MSDU_M);
- tid = le32_get_bits(usr_stats->ack_ba.info,
- HTT_PPDU_STATS_ACK_BA_INFO_TID_NUM);
- }
-
- if (common->fes_duration_us)
- tx_duration = le32_to_cpu(common->fes_duration_us);
-
- user_rate = &usr_stats->rate;
- flags = HTT_USR_RATE_PREAMBLE(user_rate->rate_flags);
- bw = HTT_USR_RATE_BW(user_rate->rate_flags) - 2;
- nss = HTT_USR_RATE_NSS(user_rate->rate_flags) + 1;
- mcs = HTT_USR_RATE_MCS(user_rate->rate_flags);
- sgi = HTT_USR_RATE_GI(user_rate->rate_flags);
- dcm = HTT_USR_RATE_DCM(user_rate->rate_flags);
-
- ppdu_type = HTT_USR_RATE_PPDU_TYPE(user_rate->info1);
- is_ofdma = (ppdu_type == HTT_PPDU_STATS_PPDU_TYPE_MU_OFDMA) ||
- (ppdu_type == HTT_PPDU_STATS_PPDU_TYPE_MU_MIMO_OFDMA);
-
- /* Note: If host configured fixed rates and in some other special
- * cases, the broadcast/management frames are sent in different rates.
- * Firmware rate's control to be skipped for this?
- */
-
- if (flags == WMI_RATE_PREAMBLE_HE && mcs > ATH12K_HE_MCS_MAX) {
- ath12k_warn(ab, "Invalid HE mcs %d peer stats", mcs);
- return;
- }
-
- if (flags == WMI_RATE_PREAMBLE_VHT && mcs > ATH12K_VHT_MCS_MAX) {
- ath12k_warn(ab, "Invalid VHT mcs %d peer stats", mcs);
- return;
- }
-
- if (flags == WMI_RATE_PREAMBLE_HT && (mcs > ATH12K_HT_MCS_MAX || nss < 1)) {
- ath12k_warn(ab, "Invalid HT mcs %d nss %d peer stats",
- mcs, nss);
- return;
- }
-
- if (flags == WMI_RATE_PREAMBLE_CCK || flags == WMI_RATE_PREAMBLE_OFDM) {
- ret = ath12k_mac_hw_ratecode_to_legacy_rate(mcs,
- flags,
- &rate_idx,
- &rate);
- if (ret < 0)
- return;
- }
-
- rcu_read_lock();
- spin_lock_bh(&ab->base_lock);
- peer = ath12k_peer_find_by_id(ab, usr_stats->peer_id);
-
- if (!peer || !peer->sta) {
- spin_unlock_bh(&ab->base_lock);
- rcu_read_unlock();
- return;
- }
-
- arsta = ath12k_peer_get_link_sta(ab, peer);
- if (!arsta) {
- spin_unlock_bh(&ab->base_lock);
- rcu_read_unlock();
- return;
- }
-
- memset(&arsta->txrate, 0, sizeof(arsta->txrate));
-
- arsta->txrate.bw = ath12k_mac_bw_to_mac80211_bw(bw);
-
- switch (flags) {
- case WMI_RATE_PREAMBLE_OFDM:
- arsta->txrate.legacy = rate;
- break;
- case WMI_RATE_PREAMBLE_CCK:
- arsta->txrate.legacy = rate;
- break;
- case WMI_RATE_PREAMBLE_HT:
- arsta->txrate.mcs = mcs + 8 * (nss - 1);
- arsta->txrate.flags = RATE_INFO_FLAGS_MCS;
- if (sgi)
- arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
- break;
- case WMI_RATE_PREAMBLE_VHT:
- arsta->txrate.mcs = mcs;
- arsta->txrate.flags = RATE_INFO_FLAGS_VHT_MCS;
- if (sgi)
- arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
- break;
- case WMI_RATE_PREAMBLE_HE:
- arsta->txrate.mcs = mcs;
- arsta->txrate.flags = RATE_INFO_FLAGS_HE_MCS;
- arsta->txrate.he_dcm = dcm;
- arsta->txrate.he_gi = ath12k_he_gi_to_nl80211_he_gi(sgi);
- tones = le16_to_cpu(user_rate->ru_end) -
- le16_to_cpu(user_rate->ru_start) + 1;
- v = ath12k_he_ru_tones_to_nl80211_he_ru_alloc(tones);
- arsta->txrate.he_ru_alloc = v;
- if (is_ofdma)
- arsta->txrate.bw = RATE_INFO_BW_HE_RU;
- break;
- case WMI_RATE_PREAMBLE_EHT:
- arsta->txrate.mcs = mcs;
- arsta->txrate.flags = RATE_INFO_FLAGS_EHT_MCS;
- arsta->txrate.he_dcm = dcm;
- arsta->txrate.eht_gi = ath12k_mac_eht_gi_to_nl80211_eht_gi(sgi);
- tones = le16_to_cpu(user_rate->ru_end) -
- le16_to_cpu(user_rate->ru_start) + 1;
- v = ath12k_mac_eht_ru_tones_to_nl80211_eht_ru_alloc(tones);
- arsta->txrate.eht_ru_alloc = v;
- if (is_ofdma)
- arsta->txrate.bw = RATE_INFO_BW_EHT_RU;
- break;
- }
-
- arsta->tx_retry_failed += tx_retry_failed;
- arsta->tx_retry_count += tx_retry_count;
- arsta->txrate.nss = nss;
- arsta->tx_duration += tx_duration;
- memcpy(&arsta->last_txrate, &arsta->txrate, sizeof(struct rate_info));
-
- /* PPDU stats reported for mgmt packet doesn't have valid tx bytes.
- * So skip peer stats update for mgmt packets.
- */
- if (tid < HTT_PPDU_STATS_NON_QOS_TID) {
- memset(peer_stats, 0, sizeof(*peer_stats));
- peer_stats->succ_pkts = succ_pkts;
- peer_stats->succ_bytes = succ_bytes;
- peer_stats->is_ampdu = is_ampdu;
- peer_stats->duration = tx_duration;
- peer_stats->ba_fails =
- HTT_USR_CMPLTN_LONG_RETRY(usr_stats->cmpltn_cmn.flags) +
- HTT_USR_CMPLTN_SHORT_RETRY(usr_stats->cmpltn_cmn.flags);
- }
-
- spin_unlock_bh(&ab->base_lock);
- rcu_read_unlock();
-}
-
-static void ath12k_htt_update_ppdu_stats(struct ath12k *ar,
- struct htt_ppdu_stats *ppdu_stats)
-{
- u8 user;
-
- for (user = 0; user < HTT_PPDU_STATS_MAX_USERS - 1; user++)
- ath12k_update_per_peer_tx_stats(ar, ppdu_stats, user);
-}
-
-static
-struct htt_ppdu_stats_info *ath12k_dp_htt_get_ppdu_desc(struct ath12k *ar,
- u32 ppdu_id)
-{
- struct htt_ppdu_stats_info *ppdu_info;
-
- lockdep_assert_held(&ar->data_lock);
- if (!list_empty(&ar->ppdu_stats_info)) {
- list_for_each_entry(ppdu_info, &ar->ppdu_stats_info, list) {
- if (ppdu_info->ppdu_id == ppdu_id)
- return ppdu_info;
- }
-
- if (ar->ppdu_stat_list_depth > HTT_PPDU_DESC_MAX_DEPTH) {
- ppdu_info = list_first_entry(&ar->ppdu_stats_info,
- typeof(*ppdu_info), list);
- list_del(&ppdu_info->list);
- ar->ppdu_stat_list_depth--;
- ath12k_htt_update_ppdu_stats(ar, &ppdu_info->ppdu_stats);
- kfree(ppdu_info);
- }
- }
-
- ppdu_info = kzalloc(sizeof(*ppdu_info), GFP_ATOMIC);
- if (!ppdu_info)
- return NULL;
-
- list_add_tail(&ppdu_info->list, &ar->ppdu_stats_info);
- ar->ppdu_stat_list_depth++;
-
- return ppdu_info;
-}
-
-static void ath12k_copy_to_delay_stats(struct ath12k_peer *peer,
- struct htt_ppdu_user_stats *usr_stats)
-{
- peer->ppdu_stats_delayba.sw_peer_id = le16_to_cpu(usr_stats->rate.sw_peer_id);
- peer->ppdu_stats_delayba.info0 = le32_to_cpu(usr_stats->rate.info0);
- peer->ppdu_stats_delayba.ru_end = le16_to_cpu(usr_stats->rate.ru_end);
- peer->ppdu_stats_delayba.ru_start = le16_to_cpu(usr_stats->rate.ru_start);
- peer->ppdu_stats_delayba.info1 = le32_to_cpu(usr_stats->rate.info1);
- peer->ppdu_stats_delayba.rate_flags = le32_to_cpu(usr_stats->rate.rate_flags);
- peer->ppdu_stats_delayba.resp_rate_flags =
- le32_to_cpu(usr_stats->rate.resp_rate_flags);
-
- peer->delayba_flag = true;
-}
-
-static void ath12k_copy_to_bar(struct ath12k_peer *peer,
- struct htt_ppdu_user_stats *usr_stats)
-{
- usr_stats->rate.sw_peer_id = cpu_to_le16(peer->ppdu_stats_delayba.sw_peer_id);
- usr_stats->rate.info0 = cpu_to_le32(peer->ppdu_stats_delayba.info0);
- usr_stats->rate.ru_end = cpu_to_le16(peer->ppdu_stats_delayba.ru_end);
- usr_stats->rate.ru_start = cpu_to_le16(peer->ppdu_stats_delayba.ru_start);
- usr_stats->rate.info1 = cpu_to_le32(peer->ppdu_stats_delayba.info1);
- usr_stats->rate.rate_flags = cpu_to_le32(peer->ppdu_stats_delayba.rate_flags);
- usr_stats->rate.resp_rate_flags =
- cpu_to_le32(peer->ppdu_stats_delayba.resp_rate_flags);
-
- peer->delayba_flag = false;
-}
-
-static int ath12k_htt_pull_ppdu_stats(struct ath12k_base *ab,
- struct sk_buff *skb)
-{
- struct ath12k_htt_ppdu_stats_msg *msg;
- struct htt_ppdu_stats_info *ppdu_info;
- struct ath12k_peer *peer = NULL;
- struct htt_ppdu_user_stats *usr_stats = NULL;
- u32 peer_id = 0;
- struct ath12k *ar;
- int ret, i;
- u8 pdev_id;
- u32 ppdu_id, len;
-
- msg = (struct ath12k_htt_ppdu_stats_msg *)skb->data;
- len = le32_get_bits(msg->info, HTT_T2H_PPDU_STATS_INFO_PAYLOAD_SIZE);
- if (len > (skb->len - struct_size(msg, data, 0))) {
- ath12k_warn(ab,
- "HTT PPDU STATS event has unexpected payload size %u, should be smaller than %u\n",
- len, skb->len);
- return -EINVAL;
- }
-
- pdev_id = le32_get_bits(msg->info, HTT_T2H_PPDU_STATS_INFO_PDEV_ID);
- ppdu_id = le32_to_cpu(msg->ppdu_id);
-
- rcu_read_lock();
- ar = ath12k_mac_get_ar_by_pdev_id(ab, pdev_id);
- if (!ar) {
- ret = -EINVAL;
- goto exit;
- }
-
- spin_lock_bh(&ar->data_lock);
- ppdu_info = ath12k_dp_htt_get_ppdu_desc(ar, ppdu_id);
- if (!ppdu_info) {
- spin_unlock_bh(&ar->data_lock);
- ret = -EINVAL;
- goto exit;
- }
-
- ppdu_info->ppdu_id = ppdu_id;
- ret = ath12k_dp_htt_tlv_iter(ab, msg->data, len,
- ath12k_htt_tlv_ppdu_stats_parse,
- (void *)ppdu_info);
- if (ret) {
- spin_unlock_bh(&ar->data_lock);
- ath12k_warn(ab, "Failed to parse tlv %d\n", ret);
- goto exit;
- }
-
- if (ppdu_info->ppdu_stats.common.num_users >= HTT_PPDU_STATS_MAX_USERS) {
- spin_unlock_bh(&ar->data_lock);
- ath12k_warn(ab,
- "HTT PPDU STATS event has unexpected num_users %u, should be smaller than %u\n",
- ppdu_info->ppdu_stats.common.num_users,
- HTT_PPDU_STATS_MAX_USERS);
- ret = -EINVAL;
- goto exit;
- }
-
- /* back up data rate tlv for all peers */
- if (ppdu_info->frame_type == HTT_STATS_PPDU_FTYPE_DATA &&
- (ppdu_info->tlv_bitmap & (1 << HTT_PPDU_STATS_TAG_USR_COMMON)) &&
- ppdu_info->delay_ba) {
- for (i = 0; i < ppdu_info->ppdu_stats.common.num_users; i++) {
- peer_id = ppdu_info->ppdu_stats.user_stats[i].peer_id;
- spin_lock_bh(&ab->base_lock);
- peer = ath12k_peer_find_by_id(ab, peer_id);
- if (!peer) {
- spin_unlock_bh(&ab->base_lock);
- continue;
- }
-
- usr_stats = &ppdu_info->ppdu_stats.user_stats[i];
- if (usr_stats->delay_ba)
- ath12k_copy_to_delay_stats(peer, usr_stats);
- spin_unlock_bh(&ab->base_lock);
- }
- }
-
- /* restore all peers' data rate tlv to mu-bar tlv */
- if (ppdu_info->frame_type == HTT_STATS_PPDU_FTYPE_BAR &&
- (ppdu_info->tlv_bitmap & (1 << HTT_PPDU_STATS_TAG_USR_COMMON))) {
- for (i = 0; i < ppdu_info->bar_num_users; i++) {
- peer_id = ppdu_info->ppdu_stats.user_stats[i].peer_id;
- spin_lock_bh(&ab->base_lock);
- peer = ath12k_peer_find_by_id(ab, peer_id);
- if (!peer) {
- spin_unlock_bh(&ab->base_lock);
- continue;
- }
-
- usr_stats = &ppdu_info->ppdu_stats.user_stats[i];
- if (peer->delayba_flag)
- ath12k_copy_to_bar(peer, usr_stats);
- spin_unlock_bh(&ab->base_lock);
- }
- }
-
- spin_unlock_bh(&ar->data_lock);
-
-exit:
- rcu_read_unlock();
+ spin_unlock_bh(&dp->dp_lock);
return ret;
}
+EXPORT_SYMBOL(ath12k_dp_rx_get_msdu_last_buf);
-static void ath12k_htt_mlo_offset_event_handler(struct ath12k_base *ab,
- struct sk_buff *skb)
-{
- struct ath12k_htt_mlo_offset_msg *msg;
- struct ath12k_pdev *pdev;
- struct ath12k *ar;
- u8 pdev_id;
-
- msg = (struct ath12k_htt_mlo_offset_msg *)skb->data;
- pdev_id = u32_get_bits(__le32_to_cpu(msg->info),
- HTT_T2H_MLO_OFFSET_INFO_PDEV_ID);
-
- rcu_read_lock();
- ar = ath12k_mac_get_ar_by_pdev_id(ab, pdev_id);
- if (!ar) {
- /* It is possible that the ar is not yet active (started).
- * The above function will only look for the active pdev
- * and hence %NULL return is possible. Just silently
- * discard this message
- */
- goto exit;
- }
-
- spin_lock_bh(&ar->data_lock);
- pdev = ar->pdev;
-
- pdev->timestamp.info = __le32_to_cpu(msg->info);
- pdev->timestamp.sync_timestamp_lo_us = __le32_to_cpu(msg->sync_timestamp_lo_us);
- pdev->timestamp.sync_timestamp_hi_us = __le32_to_cpu(msg->sync_timestamp_hi_us);
- pdev->timestamp.mlo_offset_lo = __le32_to_cpu(msg->mlo_offset_lo);
- pdev->timestamp.mlo_offset_hi = __le32_to_cpu(msg->mlo_offset_hi);
- pdev->timestamp.mlo_offset_clks = __le32_to_cpu(msg->mlo_offset_clks);
- pdev->timestamp.mlo_comp_clks = __le32_to_cpu(msg->mlo_comp_clks);
- pdev->timestamp.mlo_comp_timer = __le32_to_cpu(msg->mlo_comp_timer);
-
- spin_unlock_bh(&ar->data_lock);
-exit:
- rcu_read_unlock();
-}
-
-void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab,
- struct sk_buff *skb)
-{
- struct ath12k_dp *dp = &ab->dp;
- struct htt_resp_msg *resp = (struct htt_resp_msg *)skb->data;
- enum htt_t2h_msg_type type;
- u16 peer_id;
- u8 vdev_id;
- u8 mac_addr[ETH_ALEN];
- u16 peer_mac_h16;
- u16 ast_hash = 0;
- u16 hw_peer_id;
-
- type = le32_get_bits(resp->version_msg.version, HTT_T2H_MSG_TYPE);
-
- ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "dp_htt rx msg type :0x%0x\n", type);
-
- switch (type) {
- case HTT_T2H_MSG_TYPE_VERSION_CONF:
- dp->htt_tgt_ver_major = le32_get_bits(resp->version_msg.version,
- HTT_T2H_VERSION_CONF_MAJOR);
- dp->htt_tgt_ver_minor = le32_get_bits(resp->version_msg.version,
- HTT_T2H_VERSION_CONF_MINOR);
- complete(&dp->htt_tgt_version_received);
- break;
- /* TODO: remove unused peer map versions after testing */
- case HTT_T2H_MSG_TYPE_PEER_MAP:
- vdev_id = le32_get_bits(resp->peer_map_ev.info,
- HTT_T2H_PEER_MAP_INFO_VDEV_ID);
- peer_id = le32_get_bits(resp->peer_map_ev.info,
- HTT_T2H_PEER_MAP_INFO_PEER_ID);
- peer_mac_h16 = le32_get_bits(resp->peer_map_ev.info1,
- HTT_T2H_PEER_MAP_INFO1_MAC_ADDR_H16);
- ath12k_dp_get_mac_addr(le32_to_cpu(resp->peer_map_ev.mac_addr_l32),
- peer_mac_h16, mac_addr);
- ath12k_peer_map_event(ab, vdev_id, peer_id, mac_addr, 0, 0);
- break;
- case HTT_T2H_MSG_TYPE_PEER_MAP2:
- vdev_id = le32_get_bits(resp->peer_map_ev.info,
- HTT_T2H_PEER_MAP_INFO_VDEV_ID);
- peer_id = le32_get_bits(resp->peer_map_ev.info,
- HTT_T2H_PEER_MAP_INFO_PEER_ID);
- peer_mac_h16 = le32_get_bits(resp->peer_map_ev.info1,
- HTT_T2H_PEER_MAP_INFO1_MAC_ADDR_H16);
- ath12k_dp_get_mac_addr(le32_to_cpu(resp->peer_map_ev.mac_addr_l32),
- peer_mac_h16, mac_addr);
- ast_hash = le32_get_bits(resp->peer_map_ev.info2,
- HTT_T2H_PEER_MAP_INFO2_AST_HASH_VAL);
- hw_peer_id = le32_get_bits(resp->peer_map_ev.info1,
- HTT_T2H_PEER_MAP_INFO1_HW_PEER_ID);
- ath12k_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash,
- hw_peer_id);
- break;
- case HTT_T2H_MSG_TYPE_PEER_MAP3:
- vdev_id = le32_get_bits(resp->peer_map_ev.info,
- HTT_T2H_PEER_MAP_INFO_VDEV_ID);
- peer_id = le32_get_bits(resp->peer_map_ev.info,
- HTT_T2H_PEER_MAP_INFO_PEER_ID);
- peer_mac_h16 = le32_get_bits(resp->peer_map_ev.info1,
- HTT_T2H_PEER_MAP_INFO1_MAC_ADDR_H16);
- ath12k_dp_get_mac_addr(le32_to_cpu(resp->peer_map_ev.mac_addr_l32),
- peer_mac_h16, mac_addr);
- ast_hash = le32_get_bits(resp->peer_map_ev.info2,
- HTT_T2H_PEER_MAP3_INFO2_AST_HASH_VAL);
- hw_peer_id = le32_get_bits(resp->peer_map_ev.info2,
- HTT_T2H_PEER_MAP3_INFO2_HW_PEER_ID);
- ath12k_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash,
- hw_peer_id);
- break;
- case HTT_T2H_MSG_TYPE_PEER_UNMAP:
- case HTT_T2H_MSG_TYPE_PEER_UNMAP2:
- peer_id = le32_get_bits(resp->peer_unmap_ev.info,
- HTT_T2H_PEER_UNMAP_INFO_PEER_ID);
- ath12k_peer_unmap_event(ab, peer_id);
- break;
- case HTT_T2H_MSG_TYPE_PPDU_STATS_IND:
- ath12k_htt_pull_ppdu_stats(ab, skb);
- break;
- case HTT_T2H_MSG_TYPE_EXT_STATS_CONF:
- ath12k_debugfs_htt_ext_stats_handler(ab, skb);
- break;
- case HTT_T2H_MSG_TYPE_MLO_TIMESTAMP_OFFSET_IND:
- ath12k_htt_mlo_offset_event_handler(ab, skb);
- break;
- default:
- ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "dp_htt event %d not handled\n",
- type);
- break;
- }
-
- dev_kfree_skb_any(skb);
-}
-
-static int ath12k_dp_rx_msdu_coalesce(struct ath12k *ar,
- struct sk_buff_head *msdu_list,
- struct sk_buff *first, struct sk_buff *last,
- u8 l3pad_bytes, int msdu_len)
-{
- struct ath12k_base *ab = ar->ab;
- struct sk_buff *skb;
- struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(first);
- int buf_first_hdr_len, buf_first_len;
- struct hal_rx_desc *ldesc;
- int space_extra, rem_len, buf_len;
- u32 hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
- bool is_continuation;
-
- /* As the msdu is spread across multiple rx buffers,
- * find the offset to the start of msdu for computing
- * the length of the msdu in the first buffer.
- */
- buf_first_hdr_len = hal_rx_desc_sz + l3pad_bytes;
- buf_first_len = DP_RX_BUFFER_SIZE - buf_first_hdr_len;
-
- if (WARN_ON_ONCE(msdu_len <= buf_first_len)) {
- skb_put(first, buf_first_hdr_len + msdu_len);
- skb_pull(first, buf_first_hdr_len);
- return 0;
- }
-
- ldesc = (struct hal_rx_desc *)last->data;
- rxcb->is_first_msdu = ath12k_dp_rx_h_first_msdu(ab, ldesc);
- rxcb->is_last_msdu = ath12k_dp_rx_h_last_msdu(ab, ldesc);
-
- /* MSDU spans over multiple buffers because the length of the MSDU
- * exceeds DP_RX_BUFFER_SIZE - HAL_RX_DESC_SIZE. So assume the data
- * in the first buf is of length DP_RX_BUFFER_SIZE - HAL_RX_DESC_SIZE.
- */
- skb_put(first, DP_RX_BUFFER_SIZE);
- skb_pull(first, buf_first_hdr_len);
-
- /* When an MSDU spread over multiple buffers MSDU_END
- * tlvs are valid only in the last buffer. Copy those tlvs.
- */
- ath12k_dp_rx_desc_end_tlv_copy(ab, rxcb->rx_desc, ldesc);
-
- space_extra = msdu_len - (buf_first_len + skb_tailroom(first));
- if (space_extra > 0 &&
- (pskb_expand_head(first, 0, space_extra, GFP_ATOMIC) < 0)) {
- /* Free up all buffers of the MSDU */
- while ((skb = __skb_dequeue(msdu_list)) != NULL) {
- rxcb = ATH12K_SKB_RXCB(skb);
- if (!rxcb->is_continuation) {
- dev_kfree_skb_any(skb);
- break;
- }
- dev_kfree_skb_any(skb);
- }
- return -ENOMEM;
- }
-
- rem_len = msdu_len - buf_first_len;
- while ((skb = __skb_dequeue(msdu_list)) != NULL && rem_len > 0) {
- rxcb = ATH12K_SKB_RXCB(skb);
- is_continuation = rxcb->is_continuation;
- if (is_continuation)
- buf_len = DP_RX_BUFFER_SIZE - hal_rx_desc_sz;
- else
- buf_len = rem_len;
-
- if (buf_len > (DP_RX_BUFFER_SIZE - hal_rx_desc_sz)) {
- WARN_ON_ONCE(1);
- dev_kfree_skb_any(skb);
- return -EINVAL;
- }
-
- skb_put(skb, buf_len + hal_rx_desc_sz);
- skb_pull(skb, hal_rx_desc_sz);
- skb_copy_from_linear_data(skb, skb_put(first, buf_len),
- buf_len);
- dev_kfree_skb_any(skb);
-
- rem_len -= buf_len;
- if (!is_continuation)
- break;
- }
-
- return 0;
-}
-
-static struct sk_buff *ath12k_dp_rx_get_msdu_last_buf(struct sk_buff_head *msdu_list,
- struct sk_buff *first)
+struct sk_buff *ath12k_dp_rx_get_msdu_last_buf(struct sk_buff_head *msdu_list,
+ struct sk_buff *first)
{
struct sk_buff *skb;
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(first);
@@ -2113,14 +858,7 @@ static struct sk_buff *ath12k_dp_rx_get_msdu_last_buf(struct sk_buff_head *msdu_
return NULL;
}
-static void ath12k_dp_rx_h_csum_offload(struct sk_buff *msdu,
- struct ath12k_dp_rx_info *rx_info)
-{
- msdu->ip_summed = (rx_info->ip_csum_fail || rx_info->l4_csum_fail) ?
- CHECKSUM_NONE : CHECKSUM_UNNECESSARY;
-}
-
-int ath12k_dp_rx_crypto_mic_len(struct ath12k *ar, enum hal_encrypt_type enctype)
+int ath12k_dp_rx_crypto_mic_len(struct ath12k_dp *dp, enum hal_encrypt_type enctype)
{
switch (enctype) {
case HAL_ENCRYPT_TYPE_OPEN:
@@ -2142,11 +880,11 @@ int ath12k_dp_rx_crypto_mic_len(struct ath12k *ar, enum hal_encrypt_type enctype
break;
}
- ath12k_warn(ar->ab, "unsupported encryption type %d for mic len\n", enctype);
+ ath12k_warn(dp->ab, "unsupported encryption type %d for mic len\n", enctype);
return 0;
}
-static int ath12k_dp_rx_crypto_param_len(struct ath12k *ar,
+static int ath12k_dp_rx_crypto_param_len(struct ath12k_pdev_dp *dp_pdev,
enum hal_encrypt_type enctype)
{
switch (enctype) {
@@ -2170,11 +908,11 @@ static int ath12k_dp_rx_crypto_param_len(struct ath12k *ar,
break;
}
- ath12k_warn(ar->ab, "unsupported encryption type %d\n", enctype);
+ ath12k_warn(dp_pdev->dp->ab, "unsupported encryption type %d\n", enctype);
return 0;
}
-static int ath12k_dp_rx_crypto_icv_len(struct ath12k *ar,
+static int ath12k_dp_rx_crypto_icv_len(struct ath12k_pdev_dp *dp_pdev,
enum hal_encrypt_type enctype)
{
switch (enctype) {
@@ -2195,16 +933,15 @@ static int ath12k_dp_rx_crypto_icv_len(struct ath12k *ar,
break;
}
- ath12k_warn(ar->ab, "unsupported encryption type %d\n", enctype);
+ ath12k_warn(dp_pdev->dp->ab, "unsupported encryption type %d\n", enctype);
return 0;
}
-static void ath12k_dp_rx_h_undecap_nwifi(struct ath12k *ar,
+static void ath12k_dp_rx_h_undecap_nwifi(struct ath12k_pdev_dp *dp_pdev,
struct sk_buff *msdu,
enum hal_encrypt_type enctype,
- struct ieee80211_rx_status *status)
+ struct hal_rx_desc_data *rx_info)
{
- struct ath12k_base *ab = ar->ab;
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
u8 decap_hdr[DP_MAX_NWIFI_HDR_LEN];
struct ieee80211_hdr *hdr;
@@ -2225,7 +962,7 @@ static void ath12k_dp_rx_h_undecap_nwifi(struct ath12k *ar,
qos_ctl = rxcb->tid;
- if (ath12k_dp_rx_h_mesh_ctl_present(ab, rxcb->rx_desc))
+ if (rx_info->mesh_ctrl_present)
qos_ctl |= IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT;
/* TODO: Add other QoS ctl fields when required */
@@ -2234,9 +971,10 @@ static void ath12k_dp_rx_h_undecap_nwifi(struct ath12k *ar,
memcpy(decap_hdr, hdr, hdr_len);
/* Rebuild crypto header for mac80211 use */
- if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
- crypto_hdr = skb_push(msdu, ath12k_dp_rx_crypto_param_len(ar, enctype));
- ath12k_dp_rx_desc_get_crypto_header(ar->ab,
+ if (!(rx_info->rx_status->flag & RX_FLAG_IV_STRIPPED)) {
+ crypto_hdr = skb_push(msdu,
+ ath12k_dp_rx_crypto_param_len(dp_pdev, enctype));
+ ath12k_dp_rx_desc_get_crypto_header(dp_pdev->dp->hal,
rxcb->rx_desc, crypto_hdr,
enctype);
}
@@ -2247,11 +985,13 @@ static void ath12k_dp_rx_h_undecap_nwifi(struct ath12k *ar,
memcpy(skb_push(msdu, hdr_len), decap_hdr, hdr_len);
}
-static void ath12k_dp_rx_h_undecap_raw(struct ath12k *ar, struct sk_buff *msdu,
+static void ath12k_dp_rx_h_undecap_raw(struct ath12k_pdev_dp *dp_pdev,
+ struct sk_buff *msdu,
enum hal_encrypt_type enctype,
struct ieee80211_rx_status *status,
bool decrypted)
{
+ struct ath12k_dp *dp = dp_pdev->dp;
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
struct ieee80211_hdr *hdr;
size_t hdr_len;
@@ -2273,20 +1013,20 @@ static void ath12k_dp_rx_h_undecap_raw(struct ath12k *ar, struct sk_buff *msdu,
/* Tail */
if (status->flag & RX_FLAG_IV_STRIPPED) {
skb_trim(msdu, msdu->len -
- ath12k_dp_rx_crypto_mic_len(ar, enctype));
+ ath12k_dp_rx_crypto_mic_len(dp, enctype));
skb_trim(msdu, msdu->len -
- ath12k_dp_rx_crypto_icv_len(ar, enctype));
+ ath12k_dp_rx_crypto_icv_len(dp_pdev, enctype));
} else {
/* MIC */
if (status->flag & RX_FLAG_MIC_STRIPPED)
skb_trim(msdu, msdu->len -
- ath12k_dp_rx_crypto_mic_len(ar, enctype));
+ ath12k_dp_rx_crypto_mic_len(dp, enctype));
/* ICV */
if (status->flag & RX_FLAG_ICV_STRIPPED)
skb_trim(msdu, msdu->len -
- ath12k_dp_rx_crypto_icv_len(ar, enctype));
+ ath12k_dp_rx_crypto_icv_len(dp_pdev, enctype));
}
/* MMIC */
@@ -2298,58 +1038,59 @@ static void ath12k_dp_rx_h_undecap_raw(struct ath12k *ar, struct sk_buff *msdu,
/* Head */
if (status->flag & RX_FLAG_IV_STRIPPED) {
hdr_len = ieee80211_hdrlen(hdr->frame_control);
- crypto_len = ath12k_dp_rx_crypto_param_len(ar, enctype);
+ crypto_len = ath12k_dp_rx_crypto_param_len(dp_pdev, enctype);
memmove(msdu->data + crypto_len, msdu->data, hdr_len);
skb_pull(msdu, crypto_len);
}
}
-static void ath12k_get_dot11_hdr_from_rx_desc(struct ath12k *ar,
+static void ath12k_get_dot11_hdr_from_rx_desc(struct ath12k_pdev_dp *dp_pdev,
struct sk_buff *msdu,
struct ath12k_skb_rxcb *rxcb,
- struct ieee80211_rx_status *status,
- enum hal_encrypt_type enctype)
+ enum hal_encrypt_type enctype,
+ struct hal_rx_desc_data *rx_info)
{
struct hal_rx_desc *rx_desc = rxcb->rx_desc;
- struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_hal *hal = dp->hal;
size_t hdr_len, crypto_len;
struct ieee80211_hdr hdr;
__le16 qos_ctl;
- u8 *crypto_hdr, mesh_ctrl;
+ u8 *crypto_hdr;
- ath12k_dp_rx_desc_get_dot11_hdr(ab, rx_desc, &hdr);
+ ath12k_dp_rx_desc_get_dot11_hdr(hal, rx_desc, &hdr);
hdr_len = ieee80211_hdrlen(hdr.frame_control);
- mesh_ctrl = ath12k_dp_rx_h_mesh_ctl_present(ab, rx_desc);
- if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
- crypto_len = ath12k_dp_rx_crypto_param_len(ar, enctype);
+ if (!(rx_info->rx_status->flag & RX_FLAG_IV_STRIPPED)) {
+ crypto_len = ath12k_dp_rx_crypto_param_len(dp_pdev, enctype);
crypto_hdr = skb_push(msdu, crypto_len);
- ath12k_dp_rx_desc_get_crypto_header(ab, rx_desc, crypto_hdr, enctype);
+ ath12k_dp_rx_desc_get_crypto_header(dp->hal, rx_desc, crypto_hdr,
+ enctype);
}
skb_push(msdu, hdr_len);
memcpy(msdu->data, &hdr, min(hdr_len, sizeof(hdr)));
if (rxcb->is_mcbc)
- status->flag &= ~RX_FLAG_PN_VALIDATED;
+ rx_info->rx_status->flag &= ~RX_FLAG_PN_VALIDATED;
/* Add QOS header */
if (ieee80211_is_data_qos(hdr.frame_control)) {
struct ieee80211_hdr *qos_ptr = (struct ieee80211_hdr *)msdu->data;
qos_ctl = cpu_to_le16(rxcb->tid & IEEE80211_QOS_CTL_TID_MASK);
- if (mesh_ctrl)
+ if (rx_info->mesh_ctrl_present)
qos_ctl |= cpu_to_le16(IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT);
memcpy(ieee80211_get_qos_ctl(qos_ptr), &qos_ctl, IEEE80211_QOS_CTL_LEN);
}
}
-static void ath12k_dp_rx_h_undecap_eth(struct ath12k *ar,
+static void ath12k_dp_rx_h_undecap_eth(struct ath12k_pdev_dp *dp_pdev,
struct sk_buff *msdu,
enum hal_encrypt_type enctype,
- struct ieee80211_rx_status *status)
+ struct hal_rx_desc_data *rx_info)
{
struct ieee80211_hdr *hdr;
struct ethhdr *eth;
@@ -2365,7 +1106,7 @@ static void ath12k_dp_rx_h_undecap_eth(struct ath12k *ar,
skb_pull(msdu, sizeof(*eth));
memcpy(skb_push(msdu, sizeof(rfc)), &rfc,
sizeof(rfc));
- ath12k_get_dot11_hdr_from_rx_desc(ar, msdu, rxcb, status, enctype);
+ ath12k_get_dot11_hdr_from_rx_desc(dp_pdev, msdu, rxcb, enctype, rx_info);
/* original 802.11 header has a different DA and in
* case of 4addr it may also have different SA
@@ -2375,24 +1116,20 @@ static void ath12k_dp_rx_h_undecap_eth(struct ath12k *ar,
ether_addr_copy(ieee80211_get_SA(hdr), sa);
}
-static void ath12k_dp_rx_h_undecap(struct ath12k *ar, struct sk_buff *msdu,
- struct hal_rx_desc *rx_desc,
- enum hal_encrypt_type enctype,
- struct ieee80211_rx_status *status,
- bool decrypted)
+void ath12k_dp_rx_h_undecap(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu,
+ struct hal_rx_desc *rx_desc,
+ enum hal_encrypt_type enctype,
+ bool decrypted,
+ struct hal_rx_desc_data *rx_info)
{
- struct ath12k_base *ab = ar->ab;
- u8 decap;
struct ethhdr *ehdr;
- decap = ath12k_dp_rx_h_decap_type(ab, rx_desc);
-
- switch (decap) {
+ switch (rx_info->decap_type) {
case DP_RX_DECAP_TYPE_NATIVE_WIFI:
- ath12k_dp_rx_h_undecap_nwifi(ar, msdu, enctype, status);
+ ath12k_dp_rx_h_undecap_nwifi(dp_pdev, msdu, enctype, rx_info);
break;
case DP_RX_DECAP_TYPE_RAW:
- ath12k_dp_rx_h_undecap_raw(ar, msdu, enctype, status,
+ ath12k_dp_rx_h_undecap_raw(dp_pdev, msdu, enctype, rx_info->rx_status,
decrypted);
break;
case DP_RX_DECAP_TYPE_ETHERNET2_DIX:
@@ -2401,7 +1138,7 @@ static void ath12k_dp_rx_h_undecap(struct ath12k *ar, struct sk_buff *msdu,
/* mac80211 allows fast path only for authorized STA */
if (ehdr->h_proto == cpu_to_be16(ETH_P_PAE)) {
ATH12K_SKB_RXCB(msdu)->is_eapol = true;
- ath12k_dp_rx_h_undecap_eth(ar, msdu, enctype, status);
+ ath12k_dp_rx_h_undecap_eth(dp_pdev, msdu, enctype, rx_info);
break;
}
@@ -2409,125 +1146,53 @@ static void ath12k_dp_rx_h_undecap(struct ath12k *ar, struct sk_buff *msdu,
* remove eth header and add 802.11 header.
*/
if (ATH12K_SKB_RXCB(msdu)->is_mcbc && decrypted)
- ath12k_dp_rx_h_undecap_eth(ar, msdu, enctype, status);
+ ath12k_dp_rx_h_undecap_eth(dp_pdev, msdu, enctype, rx_info);
break;
case DP_RX_DECAP_TYPE_8023:
/* TODO: Handle undecap for these formats */
break;
}
}
+EXPORT_SYMBOL(ath12k_dp_rx_h_undecap);
-struct ath12k_peer *
-ath12k_dp_rx_h_find_peer(struct ath12k_base *ab, struct sk_buff *msdu,
- struct ath12k_dp_rx_info *rx_info)
+struct ath12k_dp_link_peer *
+ath12k_dp_rx_h_find_link_peer(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu,
+ struct hal_rx_desc_data *rx_info)
{
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
- struct ath12k_peer *peer = NULL;
+ struct ath12k_dp_link_peer *peer = NULL;
+ struct ath12k_dp *dp = dp_pdev->dp;
- lockdep_assert_held(&ab->base_lock);
+ lockdep_assert_held(&dp->dp_lock);
if (rxcb->peer_id)
- peer = ath12k_peer_find_by_id(ab, rxcb->peer_id);
+ peer = ath12k_dp_link_peer_find_by_peerid(dp_pdev, rxcb->peer_id);
if (peer)
return peer;
if (rx_info->addr2_present)
- peer = ath12k_peer_find_by_addr(ab, rx_info->addr2);
+ peer = ath12k_dp_link_peer_find_by_addr(dp, rx_info->addr2);
return peer;
}
-static void ath12k_dp_rx_h_mpdu(struct ath12k *ar,
- struct sk_buff *msdu,
- struct hal_rx_desc *rx_desc,
- struct ath12k_dp_rx_info *rx_info)
-{
- struct ath12k_base *ab = ar->ab;
- struct ath12k_skb_rxcb *rxcb;
- enum hal_encrypt_type enctype;
- bool is_decrypted = false;
- struct ieee80211_hdr *hdr;
- struct ath12k_peer *peer;
- struct ieee80211_rx_status *rx_status = rx_info->rx_status;
- u32 err_bitmap;
-
- /* PN for multicast packets will be checked in mac80211 */
- rxcb = ATH12K_SKB_RXCB(msdu);
- rxcb->is_mcbc = rx_info->is_mcbc;
-
- if (rxcb->is_mcbc)
- rxcb->peer_id = rx_info->peer_id;
-
- spin_lock_bh(&ar->ab->base_lock);
- peer = ath12k_dp_rx_h_find_peer(ar->ab, msdu, rx_info);
- if (peer) {
- /* resetting mcbc bit because mcbc packets are unicast
- * packets only for AP as STA sends unicast packets.
- */
- rxcb->is_mcbc = rxcb->is_mcbc && !peer->ucast_ra_only;
-
- if (rxcb->is_mcbc)
- enctype = peer->sec_type_grp;
- else
- enctype = peer->sec_type;
- } else {
- enctype = HAL_ENCRYPT_TYPE_OPEN;
- }
- spin_unlock_bh(&ar->ab->base_lock);
-
- err_bitmap = ath12k_dp_rx_h_mpdu_err(ab, rx_desc);
- if (enctype != HAL_ENCRYPT_TYPE_OPEN && !err_bitmap)
- is_decrypted = ath12k_dp_rx_h_is_decrypted(ab, rx_desc);
-
- /* Clear per-MPDU flags while leaving per-PPDU flags intact */
- rx_status->flag &= ~(RX_FLAG_FAILED_FCS_CRC |
- RX_FLAG_MMIC_ERROR |
- RX_FLAG_DECRYPTED |
- RX_FLAG_IV_STRIPPED |
- RX_FLAG_MMIC_STRIPPED);
-
- if (err_bitmap & HAL_RX_MPDU_ERR_FCS)
- rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
- if (err_bitmap & HAL_RX_MPDU_ERR_TKIP_MIC)
- rx_status->flag |= RX_FLAG_MMIC_ERROR;
-
- if (is_decrypted) {
- rx_status->flag |= RX_FLAG_DECRYPTED | RX_FLAG_MMIC_STRIPPED;
-
- if (rx_info->is_mcbc)
- rx_status->flag |= RX_FLAG_MIC_STRIPPED |
- RX_FLAG_ICV_STRIPPED;
- else
- rx_status->flag |= RX_FLAG_IV_STRIPPED |
- RX_FLAG_PN_VALIDATED;
- }
-
- ath12k_dp_rx_h_csum_offload(msdu, rx_info);
- ath12k_dp_rx_h_undecap(ar, msdu, rx_desc,
- enctype, rx_status, is_decrypted);
-
- if (!is_decrypted || rx_info->is_mcbc)
- return;
-
- if (rx_info->decap_type != DP_RX_DECAP_TYPE_ETHERNET2_DIX) {
- hdr = (void *)msdu->data;
- hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
- }
-}
-
-static void ath12k_dp_rx_h_rate(struct ath12k *ar, struct ath12k_dp_rx_info *rx_info)
+static void ath12k_dp_rx_h_rate(struct ath12k_pdev_dp *dp_pdev,
+ struct hal_rx_desc_data *rx_info)
{
+ struct ath12k_dp *dp = dp_pdev->dp;
struct ieee80211_supported_band *sband;
struct ieee80211_rx_status *rx_status = rx_info->rx_status;
enum rx_msdu_start_pkt_type pkt_type = rx_info->pkt_type;
u8 bw = rx_info->bw, sgi = rx_info->sgi;
u8 rate_mcs = rx_info->rate_mcs, nss = rx_info->nss;
bool is_cck;
+ struct ath12k *ar;
switch (pkt_type) {
case RX_MSDU_START_PKT_TYPE_11A:
case RX_MSDU_START_PKT_TYPE_11B:
+ ar = ath12k_pdev_dp_to_ar(dp_pdev);
is_cck = (pkt_type == RX_MSDU_START_PKT_TYPE_11B);
sband = &ar->mac.sbands[rx_status->band];
rx_status->rate_idx = ath12k_mac_hw_rate_to_idx(sband, rate_mcs,
@@ -2536,7 +1201,7 @@ static void ath12k_dp_rx_h_rate(struct ath12k *ar, struct ath12k_dp_rx_info *rx_
case RX_MSDU_START_PKT_TYPE_11N:
rx_status->encoding = RX_ENC_HT;
if (rate_mcs > ATH12K_HT_MCS_MAX) {
- ath12k_warn(ar->ab,
+ ath12k_warn(dp->ab,
"Received with invalid mcs in HT mode %d\n",
rate_mcs);
break;
@@ -2550,7 +1215,7 @@ static void ath12k_dp_rx_h_rate(struct ath12k *ar, struct ath12k_dp_rx_info *rx_
rx_status->encoding = RX_ENC_VHT;
rx_status->rate_idx = rate_mcs;
if (rate_mcs > ATH12K_VHT_MCS_MAX) {
- ath12k_warn(ar->ab,
+ ath12k_warn(dp->ab,
"Received with invalid mcs in VHT mode %d\n",
rate_mcs);
break;
@@ -2563,7 +1228,7 @@ static void ath12k_dp_rx_h_rate(struct ath12k *ar, struct ath12k_dp_rx_info *rx_
case RX_MSDU_START_PKT_TYPE_11AX:
rx_status->rate_idx = rate_mcs;
if (rate_mcs > ATH12K_HE_MCS_MAX) {
- ath12k_warn(ar->ab,
+ ath12k_warn(dp->ab,
"Received with invalid mcs in HE mode %d\n",
rate_mcs);
break;
@@ -2577,7 +1242,7 @@ static void ath12k_dp_rx_h_rate(struct ath12k *ar, struct ath12k_dp_rx_info *rx_
rx_status->rate_idx = rate_mcs;
if (rate_mcs > ATH12K_EHT_MCS_MAX) {
- ath12k_warn(ar->ab,
+ ath12k_warn(dp->ab,
"Received with invalid mcs in EHT mode %d\n",
rate_mcs);
break;
@@ -2593,33 +1258,8 @@ static void ath12k_dp_rx_h_rate(struct ath12k *ar, struct ath12k_dp_rx_info *rx_
}
}
-void ath12k_dp_rx_h_fetch_info(struct ath12k_base *ab, struct hal_rx_desc *rx_desc,
- struct ath12k_dp_rx_info *rx_info)
-{
- rx_info->ip_csum_fail = ath12k_dp_rx_h_ip_cksum_fail(ab, rx_desc);
- rx_info->l4_csum_fail = ath12k_dp_rx_h_l4_cksum_fail(ab, rx_desc);
- rx_info->is_mcbc = ath12k_dp_rx_h_is_da_mcbc(ab, rx_desc);
- rx_info->decap_type = ath12k_dp_rx_h_decap_type(ab, rx_desc);
- rx_info->pkt_type = ath12k_dp_rx_h_pkt_type(ab, rx_desc);
- rx_info->sgi = ath12k_dp_rx_h_sgi(ab, rx_desc);
- rx_info->rate_mcs = ath12k_dp_rx_h_rate_mcs(ab, rx_desc);
- rx_info->bw = ath12k_dp_rx_h_rx_bw(ab, rx_desc);
- rx_info->nss = ath12k_dp_rx_h_nss(ab, rx_desc);
- rx_info->tid = ath12k_dp_rx_h_tid(ab, rx_desc);
- rx_info->peer_id = ath12k_dp_rx_h_peer_id(ab, rx_desc);
- rx_info->phy_meta_data = ath12k_dp_rx_h_freq(ab, rx_desc);
-
- if (ath12k_dp_rxdesc_mac_addr2_valid(ab, rx_desc)) {
- ether_addr_copy(rx_info->addr2,
- ath12k_dp_rxdesc_get_mpdu_start_addr2(ab, rx_desc));
- rx_info->addr2_present = true;
- }
-
- ath12k_dbg_dump(ab, ATH12K_DBG_DATA, NULL, "rx_desc: ",
- rx_desc, sizeof(*rx_desc));
-}
-
-void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct ath12k_dp_rx_info *rx_info)
+void ath12k_dp_rx_h_ppdu(struct ath12k_pdev_dp *dp_pdev,
+ struct hal_rx_desc_data *rx_info)
{
struct ieee80211_rx_status *rx_status = rx_info->rx_status;
u8 channel_num;
@@ -2652,7 +1292,9 @@ void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct ath12k_dp_rx_info *rx_info)
}
if (unlikely(rx_status->band == NUM_NL80211_BANDS ||
- !ath12k_ar_to_hw(ar)->wiphy->bands[rx_status->band])) {
+ !ath12k_pdev_dp_to_hw(dp_pdev)->wiphy->bands[rx_status->band])) {
+ struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev);
+
ath12k_warn(ar->ab, "sband is NULL for status band %d channel_num %d center_freq %d pdev_id %d\n",
rx_status->band, channel_num, center_freq, ar->pdev_idx);
@@ -2676,43 +1318,41 @@ void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct ath12k_dp_rx_info *rx_info)
rx_status->band);
h_rate:
- ath12k_dp_rx_h_rate(ar, rx_info);
+ ath12k_dp_rx_h_rate(dp_pdev, rx_info);
}
+EXPORT_SYMBOL(ath12k_dp_rx_h_ppdu);
-static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *napi,
- struct sk_buff *msdu,
- struct ath12k_dp_rx_info *rx_info)
+void ath12k_dp_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct napi_struct *napi,
+ struct sk_buff *msdu,
+ struct hal_rx_desc_data *rx_info)
{
- struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = dp_pdev->dp;
struct ieee80211_rx_status *rx_status;
struct ieee80211_sta *pubsta;
- struct ath12k_peer *peer;
+ struct ath12k_dp_peer *peer;
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
struct ieee80211_rx_status *status = rx_info->rx_status;
u8 decap = rx_info->decap_type;
bool is_mcbc = rxcb->is_mcbc;
bool is_eapol = rxcb->is_eapol;
- spin_lock_bh(&ab->base_lock);
- peer = ath12k_dp_rx_h_find_peer(ab, msdu, rx_info);
+ peer = ath12k_dp_peer_find_by_peerid(dp_pdev, rx_info->peer_id);
pubsta = peer ? peer->sta : NULL;
if (pubsta && pubsta->valid_links) {
status->link_valid = 1;
- status->link_id = peer->link_id;
+ status->link_id = peer->hw_links[rxcb->hw_link_id];
}
- spin_unlock_bh(&ab->base_lock);
-
- ath12k_dbg(ab, ATH12K_DBG_DATA,
+ ath12k_dbg(dp->ab, ATH12K_DBG_DATA,
"rx skb %p len %u peer %pM %d %s sn %u %s%s%s%s%s%s%s%s%s%s rate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
msdu,
msdu->len,
peer ? peer->addr : NULL,
rxcb->tid,
is_mcbc ? "mcast" : "ucast",
- ath12k_dp_rx_h_seq_no(ab, rxcb->rx_desc),
+ rx_info->seq_no,
(status->encoding == RX_ENC_LEGACY) ? "legacy" : "",
(status->encoding == RX_ENC_HT) ? "ht" : "",
(status->encoding == RX_ENC_VHT) ? "vht" : "",
@@ -2731,7 +1371,7 @@ static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *nap
!!(status->flag & RX_FLAG_MMIC_ERROR),
!!(status->flag & RX_FLAG_AMSDU_MORE));
- ath12k_dbg_dump(ab, ATH12K_DBG_DP_RX, NULL, "dp rx msdu: ",
+ ath12k_dbg_dump(dp->ab, ATH12K_DBG_DP_RX, NULL, "dp rx msdu: ",
msdu->data, msdu->len);
rx_status = IEEE80211_SKB_RXCB(msdu);
@@ -2748,19 +1388,19 @@ static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *nap
!(is_mcbc && rx_status->flag & RX_FLAG_DECRYPTED))
rx_status->flag |= RX_FLAG_8023;
- ieee80211_rx_napi(ath12k_ar_to_hw(ar), pubsta, msdu, napi);
+ ieee80211_rx_napi(ath12k_pdev_dp_to_hw(dp_pdev), pubsta, msdu, napi);
}
+EXPORT_SYMBOL(ath12k_dp_rx_deliver_msdu);
-static bool ath12k_dp_rx_check_nwifi_hdr_len_valid(struct ath12k_base *ab,
- struct hal_rx_desc *rx_desc,
- struct sk_buff *msdu)
+bool ath12k_dp_rx_check_nwifi_hdr_len_valid(struct ath12k_dp *dp,
+ struct hal_rx_desc *rx_desc,
+ struct sk_buff *msdu,
+ struct hal_rx_desc_data *rx_info)
{
struct ieee80211_hdr *hdr;
- u8 decap_type;
u32 hdr_len;
- decap_type = ath12k_dp_rx_h_decap_type(ab, rx_desc);
- if (decap_type != DP_RX_DECAP_TYPE_NATIVE_WIFI)
+ if (rx_info->decap_type != DP_RX_DECAP_TYPE_NATIVE_WIFI)
return true;
hdr = (struct ieee80211_hdr *)msdu->data;
@@ -2769,385 +1409,73 @@ static bool ath12k_dp_rx_check_nwifi_hdr_len_valid(struct ath12k_base *ab,
if ((likely(hdr_len <= DP_MAX_NWIFI_HDR_LEN)))
return true;
- ab->device_stats.invalid_rbm++;
+ dp->device_stats.invalid_rbm++;
WARN_ON_ONCE(1);
return false;
}
-
-static int ath12k_dp_rx_process_msdu(struct ath12k *ar,
- struct sk_buff *msdu,
- struct sk_buff_head *msdu_list,
- struct ath12k_dp_rx_info *rx_info)
-{
- struct ath12k_base *ab = ar->ab;
- struct hal_rx_desc *rx_desc, *lrx_desc;
- struct ath12k_skb_rxcb *rxcb;
- struct sk_buff *last_buf;
- u8 l3_pad_bytes;
- u16 msdu_len;
- int ret;
- u32 hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
-
- last_buf = ath12k_dp_rx_get_msdu_last_buf(msdu_list, msdu);
- if (!last_buf) {
- ath12k_warn(ab,
- "No valid Rx buffer to access MSDU_END tlv\n");
- ret = -EIO;
- goto free_out;
- }
-
- rx_desc = (struct hal_rx_desc *)msdu->data;
- lrx_desc = (struct hal_rx_desc *)last_buf->data;
- if (!ath12k_dp_rx_h_msdu_done(ab, lrx_desc)) {
- ath12k_warn(ab, "msdu_done bit in msdu_end is not set\n");
- ret = -EIO;
- goto free_out;
- }
-
- rxcb = ATH12K_SKB_RXCB(msdu);
- rxcb->rx_desc = rx_desc;
- msdu_len = ath12k_dp_rx_h_msdu_len(ab, lrx_desc);
- l3_pad_bytes = ath12k_dp_rx_h_l3pad(ab, lrx_desc);
-
- if (rxcb->is_frag) {
- skb_pull(msdu, hal_rx_desc_sz);
- } else if (!rxcb->is_continuation) {
- if ((msdu_len + hal_rx_desc_sz) > DP_RX_BUFFER_SIZE) {
- ret = -EINVAL;
- ath12k_warn(ab, "invalid msdu len %u\n", msdu_len);
- ath12k_dbg_dump(ab, ATH12K_DBG_DATA, NULL, "", rx_desc,
- sizeof(*rx_desc));
- goto free_out;
- }
- skb_put(msdu, hal_rx_desc_sz + l3_pad_bytes + msdu_len);
- skb_pull(msdu, hal_rx_desc_sz + l3_pad_bytes);
- } else {
- ret = ath12k_dp_rx_msdu_coalesce(ar, msdu_list,
- msdu, last_buf,
- l3_pad_bytes, msdu_len);
- if (ret) {
- ath12k_warn(ab,
- "failed to coalesce msdu rx buffer%d\n", ret);
- goto free_out;
- }
- }
-
- if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(ab, rx_desc, msdu))) {
- ret = -EINVAL;
- goto free_out;
- }
-
- ath12k_dp_rx_h_fetch_info(ab, rx_desc, rx_info);
- ath12k_dp_rx_h_ppdu(ar, rx_info);
- ath12k_dp_rx_h_mpdu(ar, msdu, rx_desc, rx_info);
-
- rx_info->rx_status->flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED;
-
- return 0;
-
-free_out:
- return ret;
-}
-
-static void ath12k_dp_rx_process_received_packets(struct ath12k_base *ab,
- struct napi_struct *napi,
- struct sk_buff_head *msdu_list,
- int ring_id)
-{
- struct ath12k_hw_group *ag = ab->ag;
- struct ieee80211_rx_status rx_status = {};
- struct ath12k_skb_rxcb *rxcb;
- struct sk_buff *msdu;
- struct ath12k *ar;
- struct ath12k_hw_link *hw_links = ag->hw_links;
- struct ath12k_base *partner_ab;
- struct ath12k_dp_rx_info rx_info;
- u8 hw_link_id, pdev_id;
- int ret;
-
- if (skb_queue_empty(msdu_list))
- return;
-
- rx_info.addr2_present = false;
- rx_info.rx_status = &rx_status;
-
- rcu_read_lock();
-
- while ((msdu = __skb_dequeue(msdu_list))) {
- rxcb = ATH12K_SKB_RXCB(msdu);
- hw_link_id = rxcb->hw_link_id;
- partner_ab = ath12k_ag_to_ab(ag,
- hw_links[hw_link_id].device_id);
- pdev_id = ath12k_hw_mac_id_to_pdev_id(partner_ab->hw_params,
- hw_links[hw_link_id].pdev_idx);
- ar = partner_ab->pdevs[pdev_id].ar;
- if (!rcu_dereference(partner_ab->pdevs_active[pdev_id])) {
- dev_kfree_skb_any(msdu);
- continue;
- }
-
- if (test_bit(ATH12K_FLAG_CAC_RUNNING, &ar->dev_flags)) {
- dev_kfree_skb_any(msdu);
- continue;
- }
-
- ret = ath12k_dp_rx_process_msdu(ar, msdu, msdu_list, &rx_info);
- if (ret) {
- ath12k_dbg(ab, ATH12K_DBG_DATA,
- "Unable to process msdu %d", ret);
- dev_kfree_skb_any(msdu);
- continue;
- }
-
- ath12k_dp_rx_deliver_msdu(ar, napi, msdu, &rx_info);
- }
-
- rcu_read_unlock();
-}
-
-static u16 ath12k_dp_rx_get_peer_id(struct ath12k_base *ab,
- enum ath12k_peer_metadata_version ver,
- __le32 peer_metadata)
-{
- switch (ver) {
- default:
- ath12k_warn(ab, "Unknown peer metadata version: %d", ver);
- fallthrough;
- case ATH12K_PEER_METADATA_V0:
- return le32_get_bits(peer_metadata,
- RX_MPDU_DESC_META_DATA_V0_PEER_ID);
- case ATH12K_PEER_METADATA_V1:
- return le32_get_bits(peer_metadata,
- RX_MPDU_DESC_META_DATA_V1_PEER_ID);
- case ATH12K_PEER_METADATA_V1A:
- return le32_get_bits(peer_metadata,
- RX_MPDU_DESC_META_DATA_V1A_PEER_ID);
- case ATH12K_PEER_METADATA_V1B:
- return le32_get_bits(peer_metadata,
- RX_MPDU_DESC_META_DATA_V1B_PEER_ID);
- }
-}
-
-int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id,
- struct napi_struct *napi, int budget)
-{
- struct ath12k_hw_group *ag = ab->ag;
- struct list_head rx_desc_used_list[ATH12K_MAX_DEVICES];
- struct ath12k_hw_link *hw_links = ag->hw_links;
- int num_buffs_reaped[ATH12K_MAX_DEVICES] = {};
- struct ath12k_rx_desc_info *desc_info;
- struct ath12k_dp *dp = &ab->dp;
- struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring;
- struct hal_reo_dest_ring *desc;
- struct ath12k_base *partner_ab;
- struct sk_buff_head msdu_list;
- struct ath12k_skb_rxcb *rxcb;
- int total_msdu_reaped = 0;
- u8 hw_link_id, device_id;
- struct hal_srng *srng;
- struct sk_buff *msdu;
- bool done = false;
- u64 desc_va;
-
- __skb_queue_head_init(&msdu_list);
-
- for (device_id = 0; device_id < ATH12K_MAX_DEVICES; device_id++)
- INIT_LIST_HEAD(&rx_desc_used_list[device_id]);
-
- srng = &ab->hal.srng_list[dp->reo_dst_ring[ring_id].ring_id];
-
- spin_lock_bh(&srng->lock);
-
-try_again:
- ath12k_hal_srng_access_begin(ab, srng);
-
- while ((desc = ath12k_hal_srng_dst_get_next_entry(ab, srng))) {
- struct rx_mpdu_desc *mpdu_info;
- struct rx_msdu_desc *msdu_info;
- enum hal_reo_dest_ring_push_reason push_reason;
- u32 cookie;
-
- cookie = le32_get_bits(desc->buf_addr_info.info1,
- BUFFER_ADDR_INFO1_SW_COOKIE);
-
- hw_link_id = le32_get_bits(desc->info0,
- HAL_REO_DEST_RING_INFO0_SRC_LINK_ID);
-
- desc_va = ((u64)le32_to_cpu(desc->buf_va_hi) << 32 |
- le32_to_cpu(desc->buf_va_lo));
- desc_info = (struct ath12k_rx_desc_info *)((unsigned long)desc_va);
-
- device_id = hw_links[hw_link_id].device_id;
- partner_ab = ath12k_ag_to_ab(ag, device_id);
- if (unlikely(!partner_ab)) {
- if (desc_info->skb) {
- dev_kfree_skb_any(desc_info->skb);
- desc_info->skb = NULL;
- }
-
- continue;
- }
-
- /* retry manual desc retrieval */
- if (!desc_info) {
- desc_info = ath12k_dp_get_rx_desc(partner_ab, cookie);
- if (!desc_info) {
- ath12k_warn(partner_ab, "Invalid cookie in manual descriptor retrieval: 0x%x\n",
- cookie);
- continue;
- }
- }
-
- if (desc_info->magic != ATH12K_DP_RX_DESC_MAGIC)
- ath12k_warn(ab, "Check HW CC implementation");
-
- msdu = desc_info->skb;
- desc_info->skb = NULL;
-
- list_add_tail(&desc_info->list, &rx_desc_used_list[device_id]);
-
- rxcb = ATH12K_SKB_RXCB(msdu);
- dma_unmap_single(partner_ab->dev, rxcb->paddr,
- msdu->len + skb_tailroom(msdu),
- DMA_FROM_DEVICE);
-
- num_buffs_reaped[device_id]++;
- ab->device_stats.reo_rx[ring_id][ab->device_id]++;
-
- push_reason = le32_get_bits(desc->info0,
- HAL_REO_DEST_RING_INFO0_PUSH_REASON);
- if (push_reason !=
- HAL_REO_DEST_RING_PUSH_REASON_ROUTING_INSTRUCTION) {
- dev_kfree_skb_any(msdu);
- ab->device_stats.hal_reo_error[ring_id]++;
- continue;
- }
-
- msdu_info = &desc->rx_msdu_info;
- mpdu_info = &desc->rx_mpdu_info;
-
- rxcb->is_first_msdu = !!(le32_to_cpu(msdu_info->info0) &
- RX_MSDU_DESC_INFO0_FIRST_MSDU_IN_MPDU);
- rxcb->is_last_msdu = !!(le32_to_cpu(msdu_info->info0) &
- RX_MSDU_DESC_INFO0_LAST_MSDU_IN_MPDU);
- rxcb->is_continuation = !!(le32_to_cpu(msdu_info->info0) &
- RX_MSDU_DESC_INFO0_MSDU_CONTINUATION);
- rxcb->hw_link_id = hw_link_id;
- rxcb->peer_id = ath12k_dp_rx_get_peer_id(ab, dp->peer_metadata_ver,
- mpdu_info->peer_meta_data);
- rxcb->tid = le32_get_bits(mpdu_info->info0,
- RX_MPDU_DESC_INFO0_TID);
-
- __skb_queue_tail(&msdu_list, msdu);
-
- if (!rxcb->is_continuation) {
- total_msdu_reaped++;
- done = true;
- } else {
- done = false;
- }
-
- if (total_msdu_reaped >= budget)
- break;
- }
-
- /* Hw might have updated the head pointer after we cached it.
- * In this case, even though there are entries in the ring we'll
- * get rx_desc NULL. Give the read another try with updated cached
- * head pointer so that we can reap complete MPDU in the current
- * rx processing.
- */
- if (!done && ath12k_hal_srng_dst_num_free(ab, srng, true)) {
- ath12k_hal_srng_access_end(ab, srng);
- goto try_again;
- }
-
- ath12k_hal_srng_access_end(ab, srng);
-
- spin_unlock_bh(&srng->lock);
-
- if (!total_msdu_reaped)
- goto exit;
-
- for (device_id = 0; device_id < ATH12K_MAX_DEVICES; device_id++) {
- if (!num_buffs_reaped[device_id])
- continue;
-
- partner_ab = ath12k_ag_to_ab(ag, device_id);
- rx_ring = &partner_ab->dp.rx_refill_buf_ring;
-
- ath12k_dp_rx_bufs_replenish(partner_ab, rx_ring,
- &rx_desc_used_list[device_id],
- num_buffs_reaped[device_id]);
- }
-
- ath12k_dp_rx_process_received_packets(ab, napi, &msdu_list,
- ring_id);
-
-exit:
- return total_msdu_reaped;
-}
+EXPORT_SYMBOL(ath12k_dp_rx_check_nwifi_hdr_len_valid);
static void ath12k_dp_rx_frag_timer(struct timer_list *timer)
{
struct ath12k_dp_rx_tid *rx_tid = timer_container_of(rx_tid, timer,
frag_timer);
- spin_lock_bh(&rx_tid->ab->base_lock);
+ spin_lock_bh(&rx_tid->dp->dp_lock);
if (rx_tid->last_frag_no &&
rx_tid->rx_frag_bitmap == GENMASK(rx_tid->last_frag_no, 0)) {
- spin_unlock_bh(&rx_tid->ab->base_lock);
+ spin_unlock_bh(&rx_tid->dp->dp_lock);
return;
}
- ath12k_dp_rx_frags_cleanup(rx_tid, true);
- spin_unlock_bh(&rx_tid->ab->base_lock);
+ ath12k_dp_arch_rx_frags_cleanup(rx_tid->dp, rx_tid, true);
+ spin_unlock_bh(&rx_tid->dp->dp_lock);
}
int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_id)
{
struct ath12k_base *ab = ar->ab;
struct crypto_shash *tfm;
- struct ath12k_peer *peer;
+ struct ath12k_dp_link_peer *peer;
struct ath12k_dp_rx_tid *rx_tid;
int i;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
tfm = crypto_alloc_shash("michael_mic", 0, 0);
if (IS_ERR(tfm))
return PTR_ERR(tfm);
- spin_lock_bh(&ab->base_lock);
+ spin_lock_bh(&dp->dp_lock);
- peer = ath12k_peer_find(ab, vdev_id, peer_mac);
- if (!peer) {
- spin_unlock_bh(&ab->base_lock);
+ peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, peer_mac);
+ if (!peer || !peer->dp_peer) {
+ spin_unlock_bh(&dp->dp_lock);
crypto_free_shash(tfm);
ath12k_warn(ab, "failed to find the peer to set up fragment info\n");
return -ENOENT;
}
if (!peer->primary_link) {
- spin_unlock_bh(&ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
crypto_free_shash(tfm);
return 0;
}
for (i = 0; i <= IEEE80211_NUM_TIDS; i++) {
- rx_tid = &peer->rx_tid[i];
- rx_tid->ab = ab;
+ rx_tid = &peer->dp_peer->rx_tid[i];
+ rx_tid->dp = dp;
timer_setup(&rx_tid->frag_timer, ath12k_dp_rx_frag_timer, 0);
skb_queue_head_init(&rx_tid->rx_frags);
}
- peer->tfm_mmic = tfm;
- peer->dp_setup_done = true;
- spin_unlock_bh(&ab->base_lock);
+ peer->dp_peer->tfm_mmic = tfm;
+ peer->dp_peer->dp_setup_done = true;
+ spin_unlock_bh(&dp->dp_lock);
return 0;
}
-static int ath12k_dp_rx_h_michael_mic(struct crypto_shash *tfm, u8 *key,
- struct ieee80211_hdr *hdr, u8 *data,
- size_t data_len, u8 *mic)
+int ath12k_dp_rx_h_michael_mic(struct crypto_shash *tfm, u8 *key,
+ struct ieee80211_hdr *hdr, u8 *data,
+ size_t data_len, u8 *mic)
{
SHASH_DESC_ON_STACK(desc, tfm);
u8 mic_hdr[16] = {};
@@ -3185,78 +1513,16 @@ out:
shash_desc_zero(desc);
return ret;
}
+EXPORT_SYMBOL(ath12k_dp_rx_h_michael_mic);
-static int ath12k_dp_rx_h_verify_tkip_mic(struct ath12k *ar, struct ath12k_peer *peer,
- struct sk_buff *msdu)
-{
- struct ath12k_base *ab = ar->ab;
- struct hal_rx_desc *rx_desc = (struct hal_rx_desc *)msdu->data;
- struct ieee80211_rx_status *rxs = IEEE80211_SKB_RXCB(msdu);
- struct ieee80211_key_conf *key_conf;
- struct ieee80211_hdr *hdr;
- struct ath12k_dp_rx_info rx_info;
- u8 mic[IEEE80211_CCMP_MIC_LEN];
- int head_len, tail_len, ret;
- size_t data_len;
- u32 hdr_len, hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
- u8 *key, *data;
- u8 key_idx;
-
- if (ath12k_dp_rx_h_enctype(ab, rx_desc) != HAL_ENCRYPT_TYPE_TKIP_MIC)
- return 0;
-
- rx_info.addr2_present = false;
- rx_info.rx_status = rxs;
-
- hdr = (struct ieee80211_hdr *)(msdu->data + hal_rx_desc_sz);
- hdr_len = ieee80211_hdrlen(hdr->frame_control);
- head_len = hdr_len + hal_rx_desc_sz + IEEE80211_TKIP_IV_LEN;
- tail_len = IEEE80211_CCMP_MIC_LEN + IEEE80211_TKIP_ICV_LEN + FCS_LEN;
-
- if (!is_multicast_ether_addr(hdr->addr1))
- key_idx = peer->ucast_keyidx;
- else
- key_idx = peer->mcast_keyidx;
-
- key_conf = peer->keys[key_idx];
-
- data = msdu->data + head_len;
- data_len = msdu->len - head_len - tail_len;
- key = &key_conf->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY];
-
- ret = ath12k_dp_rx_h_michael_mic(peer->tfm_mmic, key, hdr, data, data_len, mic);
- if (ret || memcmp(mic, data + data_len, IEEE80211_CCMP_MIC_LEN))
- goto mic_fail;
-
- return 0;
-
-mic_fail:
- (ATH12K_SKB_RXCB(msdu))->is_first_msdu = true;
- (ATH12K_SKB_RXCB(msdu))->is_last_msdu = true;
-
- ath12k_dp_rx_h_fetch_info(ab, rx_desc, &rx_info);
-
- rxs->flag |= RX_FLAG_MMIC_ERROR | RX_FLAG_MMIC_STRIPPED |
- RX_FLAG_IV_STRIPPED | RX_FLAG_DECRYPTED;
- skb_pull(msdu, hal_rx_desc_sz);
-
- if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(ab, rx_desc, msdu)))
- return -EINVAL;
-
- ath12k_dp_rx_h_ppdu(ar, &rx_info);
- ath12k_dp_rx_h_undecap(ar, msdu, rx_desc,
- HAL_ENCRYPT_TYPE_TKIP_MIC, rxs, true);
- ieee80211_rx(ath12k_ar_to_hw(ar), msdu);
- return -EINVAL;
-}
-
-static void ath12k_dp_rx_h_undecap_frag(struct ath12k *ar, struct sk_buff *msdu,
- enum hal_encrypt_type enctype, u32 flags)
+void ath12k_dp_rx_h_undecap_frag(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu,
+ enum hal_encrypt_type enctype, u32 flags)
{
+ struct ath12k_dp *dp = dp_pdev->dp;
struct ieee80211_hdr *hdr;
size_t hdr_len;
size_t crypto_len;
- u32 hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
+ u32 hal_rx_desc_sz = dp->ab->hal.hal_desc_sz;
if (!flags)
return;
@@ -3265,258 +1531,43 @@ static void ath12k_dp_rx_h_undecap_frag(struct ath12k *ar, struct sk_buff *msdu,
if (flags & RX_FLAG_MIC_STRIPPED)
skb_trim(msdu, msdu->len -
- ath12k_dp_rx_crypto_mic_len(ar, enctype));
+ ath12k_dp_rx_crypto_mic_len(dp, enctype));
if (flags & RX_FLAG_ICV_STRIPPED)
skb_trim(msdu, msdu->len -
- ath12k_dp_rx_crypto_icv_len(ar, enctype));
+ ath12k_dp_rx_crypto_icv_len(dp_pdev, enctype));
if (flags & RX_FLAG_IV_STRIPPED) {
hdr_len = ieee80211_hdrlen(hdr->frame_control);
- crypto_len = ath12k_dp_rx_crypto_param_len(ar, enctype);
+ crypto_len = ath12k_dp_rx_crypto_param_len(dp_pdev, enctype);
memmove(msdu->data + hal_rx_desc_sz + crypto_len,
msdu->data + hal_rx_desc_sz, hdr_len);
skb_pull(msdu, crypto_len);
}
}
+EXPORT_SYMBOL(ath12k_dp_rx_h_undecap_frag);
-static int ath12k_dp_rx_h_defrag(struct ath12k *ar,
- struct ath12k_peer *peer,
- struct ath12k_dp_rx_tid *rx_tid,
- struct sk_buff **defrag_skb)
-{
- struct ath12k_base *ab = ar->ab;
- struct hal_rx_desc *rx_desc;
- struct sk_buff *skb, *first_frag, *last_frag;
- struct ieee80211_hdr *hdr;
- enum hal_encrypt_type enctype;
- bool is_decrypted = false;
- int msdu_len = 0;
- int extra_space;
- u32 flags, hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
-
- first_frag = skb_peek(&rx_tid->rx_frags);
- last_frag = skb_peek_tail(&rx_tid->rx_frags);
-
- skb_queue_walk(&rx_tid->rx_frags, skb) {
- flags = 0;
- rx_desc = (struct hal_rx_desc *)skb->data;
- hdr = (struct ieee80211_hdr *)(skb->data + hal_rx_desc_sz);
-
- enctype = ath12k_dp_rx_h_enctype(ab, rx_desc);
- if (enctype != HAL_ENCRYPT_TYPE_OPEN)
- is_decrypted = ath12k_dp_rx_h_is_decrypted(ab,
- rx_desc);
-
- if (is_decrypted) {
- if (skb != first_frag)
- flags |= RX_FLAG_IV_STRIPPED;
- if (skb != last_frag)
- flags |= RX_FLAG_ICV_STRIPPED |
- RX_FLAG_MIC_STRIPPED;
- }
-
- /* RX fragments are always raw packets */
- if (skb != last_frag)
- skb_trim(skb, skb->len - FCS_LEN);
- ath12k_dp_rx_h_undecap_frag(ar, skb, enctype, flags);
-
- if (skb != first_frag)
- skb_pull(skb, hal_rx_desc_sz +
- ieee80211_hdrlen(hdr->frame_control));
- msdu_len += skb->len;
- }
-
- extra_space = msdu_len - (DP_RX_BUFFER_SIZE + skb_tailroom(first_frag));
- if (extra_space > 0 &&
- (pskb_expand_head(first_frag, 0, extra_space, GFP_ATOMIC) < 0))
- return -ENOMEM;
-
- __skb_unlink(first_frag, &rx_tid->rx_frags);
- while ((skb = __skb_dequeue(&rx_tid->rx_frags))) {
- skb_put_data(first_frag, skb->data, skb->len);
- dev_kfree_skb_any(skb);
- }
-
- hdr = (struct ieee80211_hdr *)(first_frag->data + hal_rx_desc_sz);
- hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_MOREFRAGS);
- ATH12K_SKB_RXCB(first_frag)->is_frag = 1;
-
- if (ath12k_dp_rx_h_verify_tkip_mic(ar, peer, first_frag))
- first_frag = NULL;
-
- *defrag_skb = first_frag;
- return 0;
-}
-
-static int ath12k_dp_rx_h_defrag_reo_reinject(struct ath12k *ar,
- struct ath12k_dp_rx_tid *rx_tid,
- struct sk_buff *defrag_skb)
-{
- struct ath12k_base *ab = ar->ab;
- struct ath12k_dp *dp = &ab->dp;
- struct hal_rx_desc *rx_desc = (struct hal_rx_desc *)defrag_skb->data;
- struct hal_reo_entrance_ring *reo_ent_ring;
- struct hal_reo_dest_ring *reo_dest_ring;
- struct dp_link_desc_bank *link_desc_banks;
- struct hal_rx_msdu_link *msdu_link;
- struct hal_rx_msdu_details *msdu0;
- struct hal_srng *srng;
- dma_addr_t link_paddr, buf_paddr;
- u32 desc_bank, msdu_info, msdu_ext_info, mpdu_info;
- u32 cookie, hal_rx_desc_sz, dest_ring_info0, queue_addr_hi;
- int ret;
- struct ath12k_rx_desc_info *desc_info;
- enum hal_rx_buf_return_buf_manager idle_link_rbm = dp->idle_link_rbm;
- u8 dst_ind;
-
- hal_rx_desc_sz = ab->hal.hal_desc_sz;
- link_desc_banks = dp->link_desc_banks;
- reo_dest_ring = rx_tid->dst_ring_desc;
-
- ath12k_hal_rx_reo_ent_paddr_get(ab, &reo_dest_ring->buf_addr_info,
- &link_paddr, &cookie);
- desc_bank = u32_get_bits(cookie, DP_LINK_DESC_BANK_MASK);
-
- msdu_link = (struct hal_rx_msdu_link *)(link_desc_banks[desc_bank].vaddr +
- (link_paddr - link_desc_banks[desc_bank].paddr));
- msdu0 = &msdu_link->msdu_link[0];
- msdu_ext_info = le32_to_cpu(msdu0->rx_msdu_ext_info.info0);
- dst_ind = u32_get_bits(msdu_ext_info, RX_MSDU_EXT_DESC_INFO0_REO_DEST_IND);
-
- memset(msdu0, 0, sizeof(*msdu0));
-
- msdu_info = u32_encode_bits(1, RX_MSDU_DESC_INFO0_FIRST_MSDU_IN_MPDU) |
- u32_encode_bits(1, RX_MSDU_DESC_INFO0_LAST_MSDU_IN_MPDU) |
- u32_encode_bits(0, RX_MSDU_DESC_INFO0_MSDU_CONTINUATION) |
- u32_encode_bits(defrag_skb->len - hal_rx_desc_sz,
- RX_MSDU_DESC_INFO0_MSDU_LENGTH) |
- u32_encode_bits(1, RX_MSDU_DESC_INFO0_VALID_SA) |
- u32_encode_bits(1, RX_MSDU_DESC_INFO0_VALID_DA);
- msdu0->rx_msdu_info.info0 = cpu_to_le32(msdu_info);
- msdu0->rx_msdu_ext_info.info0 = cpu_to_le32(msdu_ext_info);
-
- /* change msdu len in hal rx desc */
- ath12k_dp_rxdesc_set_msdu_len(ab, rx_desc, defrag_skb->len - hal_rx_desc_sz);
-
- buf_paddr = dma_map_single(ab->dev, defrag_skb->data,
- defrag_skb->len + skb_tailroom(defrag_skb),
- DMA_TO_DEVICE);
- if (dma_mapping_error(ab->dev, buf_paddr))
- return -ENOMEM;
-
- spin_lock_bh(&dp->rx_desc_lock);
- desc_info = list_first_entry_or_null(&dp->rx_desc_free_list,
- struct ath12k_rx_desc_info,
- list);
- if (!desc_info) {
- spin_unlock_bh(&dp->rx_desc_lock);
- ath12k_warn(ab, "failed to find rx desc for reinject\n");
- ret = -ENOMEM;
- goto err_unmap_dma;
- }
-
- desc_info->skb = defrag_skb;
- desc_info->in_use = true;
-
- list_del(&desc_info->list);
- spin_unlock_bh(&dp->rx_desc_lock);
-
- ATH12K_SKB_RXCB(defrag_skb)->paddr = buf_paddr;
-
- ath12k_hal_rx_buf_addr_info_set(&msdu0->buf_addr_info, buf_paddr,
- desc_info->cookie,
- HAL_RX_BUF_RBM_SW3_BM);
-
- /* Fill mpdu details into reo entrance ring */
- srng = &ab->hal.srng_list[dp->reo_reinject_ring.ring_id];
-
- spin_lock_bh(&srng->lock);
- ath12k_hal_srng_access_begin(ab, srng);
-
- reo_ent_ring = ath12k_hal_srng_src_get_next_entry(ab, srng);
- if (!reo_ent_ring) {
- ath12k_hal_srng_access_end(ab, srng);
- spin_unlock_bh(&srng->lock);
- ret = -ENOSPC;
- goto err_free_desc;
- }
- memset(reo_ent_ring, 0, sizeof(*reo_ent_ring));
-
- ath12k_hal_rx_buf_addr_info_set(&reo_ent_ring->buf_addr_info, link_paddr,
- cookie,
- idle_link_rbm);
-
- mpdu_info = u32_encode_bits(1, RX_MPDU_DESC_INFO0_MSDU_COUNT) |
- u32_encode_bits(0, RX_MPDU_DESC_INFO0_FRAG_FLAG) |
- u32_encode_bits(1, RX_MPDU_DESC_INFO0_RAW_MPDU) |
- u32_encode_bits(1, RX_MPDU_DESC_INFO0_VALID_PN) |
- u32_encode_bits(rx_tid->tid, RX_MPDU_DESC_INFO0_TID);
-
- reo_ent_ring->rx_mpdu_info.info0 = cpu_to_le32(mpdu_info);
- reo_ent_ring->rx_mpdu_info.peer_meta_data =
- reo_dest_ring->rx_mpdu_info.peer_meta_data;
-
- if (ab->hw_params->reoq_lut_support) {
- reo_ent_ring->queue_addr_lo = reo_dest_ring->rx_mpdu_info.peer_meta_data;
- queue_addr_hi = 0;
- } else {
- reo_ent_ring->queue_addr_lo =
- cpu_to_le32(lower_32_bits(rx_tid->qbuf.paddr_aligned));
- queue_addr_hi = upper_32_bits(rx_tid->qbuf.paddr_aligned);
- }
-
- reo_ent_ring->info0 = le32_encode_bits(queue_addr_hi,
- HAL_REO_ENTR_RING_INFO0_QUEUE_ADDR_HI) |
- le32_encode_bits(dst_ind,
- HAL_REO_ENTR_RING_INFO0_DEST_IND);
-
- reo_ent_ring->info1 = le32_encode_bits(rx_tid->cur_sn,
- HAL_REO_ENTR_RING_INFO1_MPDU_SEQ_NUM);
- dest_ring_info0 = le32_get_bits(reo_dest_ring->info0,
- HAL_REO_DEST_RING_INFO0_SRC_LINK_ID);
- reo_ent_ring->info2 =
- cpu_to_le32(u32_get_bits(dest_ring_info0,
- HAL_REO_ENTR_RING_INFO2_SRC_LINK_ID));
-
- ath12k_hal_srng_access_end(ab, srng);
- spin_unlock_bh(&srng->lock);
-
- return 0;
-
-err_free_desc:
- spin_lock_bh(&dp->rx_desc_lock);
- desc_info->in_use = false;
- desc_info->skb = NULL;
- list_add_tail(&desc_info->list, &dp->rx_desc_free_list);
- spin_unlock_bh(&dp->rx_desc_lock);
-err_unmap_dma:
- dma_unmap_single(ab->dev, buf_paddr, defrag_skb->len + skb_tailroom(defrag_skb),
- DMA_TO_DEVICE);
- return ret;
-}
-
-static int ath12k_dp_rx_h_cmp_frags(struct ath12k_base *ab,
+static int ath12k_dp_rx_h_cmp_frags(struct ath12k_hal *hal,
struct sk_buff *a, struct sk_buff *b)
{
int frag1, frag2;
- frag1 = ath12k_dp_rx_h_frag_no(ab, a);
- frag2 = ath12k_dp_rx_h_frag_no(ab, b);
+ frag1 = ath12k_dp_rx_h_frag_no(hal, a);
+ frag2 = ath12k_dp_rx_h_frag_no(hal, b);
return frag1 - frag2;
}
-static void ath12k_dp_rx_h_sort_frags(struct ath12k_base *ab,
- struct sk_buff_head *frag_list,
- struct sk_buff *cur_frag)
+void ath12k_dp_rx_h_sort_frags(struct ath12k_hal *hal,
+ struct sk_buff_head *frag_list,
+ struct sk_buff *cur_frag)
{
struct sk_buff *skb;
int cmp;
skb_queue_walk(frag_list, skb) {
- cmp = ath12k_dp_rx_h_cmp_frags(ab, skb, cur_frag);
+ cmp = ath12k_dp_rx_h_cmp_frags(hal, skb, cur_frag);
if (cmp < 0)
continue;
__skb_queue_before(frag_list, skb, cur_frag);
@@ -3524,13 +1575,14 @@ static void ath12k_dp_rx_h_sort_frags(struct ath12k_base *ab,
}
__skb_queue_tail(frag_list, cur_frag);
}
+EXPORT_SYMBOL(ath12k_dp_rx_h_sort_frags);
-static u64 ath12k_dp_rx_h_get_pn(struct ath12k *ar, struct sk_buff *skb)
+u64 ath12k_dp_rx_h_get_pn(struct ath12k_dp *dp, struct sk_buff *skb)
{
struct ieee80211_hdr *hdr;
u64 pn = 0;
u8 *ehdr;
- u32 hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
+ u32 hal_rx_desc_sz = dp->ab->hal.hal_desc_sz;
hdr = (struct ieee80211_hdr *)(skb->data + hal_rx_desc_sz);
ehdr = skb->data + hal_rx_desc_sz + ieee80211_hdrlen(hdr->frame_control);
@@ -3544,956 +1596,11 @@ static u64 ath12k_dp_rx_h_get_pn(struct ath12k *ar, struct sk_buff *skb)
return pn;
}
-
-static bool
-ath12k_dp_rx_h_defrag_validate_incr_pn(struct ath12k *ar, struct ath12k_dp_rx_tid *rx_tid)
-{
- struct ath12k_base *ab = ar->ab;
- enum hal_encrypt_type encrypt_type;
- struct sk_buff *first_frag, *skb;
- struct hal_rx_desc *desc;
- u64 last_pn;
- u64 cur_pn;
-
- first_frag = skb_peek(&rx_tid->rx_frags);
- desc = (struct hal_rx_desc *)first_frag->data;
-
- encrypt_type = ath12k_dp_rx_h_enctype(ab, desc);
- if (encrypt_type != HAL_ENCRYPT_TYPE_CCMP_128 &&
- encrypt_type != HAL_ENCRYPT_TYPE_CCMP_256 &&
- encrypt_type != HAL_ENCRYPT_TYPE_GCMP_128 &&
- encrypt_type != HAL_ENCRYPT_TYPE_AES_GCMP_256)
- return true;
-
- last_pn = ath12k_dp_rx_h_get_pn(ar, first_frag);
- skb_queue_walk(&rx_tid->rx_frags, skb) {
- if (skb == first_frag)
- continue;
-
- cur_pn = ath12k_dp_rx_h_get_pn(ar, skb);
- if (cur_pn != last_pn + 1)
- return false;
- last_pn = cur_pn;
- }
- return true;
-}
-
-static int ath12k_dp_rx_frag_h_mpdu(struct ath12k *ar,
- struct sk_buff *msdu,
- struct hal_reo_dest_ring *ring_desc)
-{
- struct ath12k_base *ab = ar->ab;
- struct hal_rx_desc *rx_desc;
- struct ath12k_peer *peer;
- struct ath12k_dp_rx_tid *rx_tid;
- struct sk_buff *defrag_skb = NULL;
- u32 peer_id;
- u16 seqno, frag_no;
- u8 tid;
- int ret = 0;
- bool more_frags;
-
- rx_desc = (struct hal_rx_desc *)msdu->data;
- peer_id = ath12k_dp_rx_h_peer_id(ab, rx_desc);
- tid = ath12k_dp_rx_h_tid(ab, rx_desc);
- seqno = ath12k_dp_rx_h_seq_no(ab, rx_desc);
- frag_no = ath12k_dp_rx_h_frag_no(ab, msdu);
- more_frags = ath12k_dp_rx_h_more_frags(ab, msdu);
-
- if (!ath12k_dp_rx_h_seq_ctrl_valid(ab, rx_desc) ||
- !ath12k_dp_rx_h_fc_valid(ab, rx_desc) ||
- tid > IEEE80211_NUM_TIDS)
- return -EINVAL;
-
- /* received unfragmented packet in reo
- * exception ring, this shouldn't happen
- * as these packets typically come from
- * reo2sw srngs.
- */
- if (WARN_ON_ONCE(!frag_no && !more_frags))
- return -EINVAL;
-
- spin_lock_bh(&ab->base_lock);
- peer = ath12k_peer_find_by_id(ab, peer_id);
- if (!peer) {
- ath12k_warn(ab, "failed to find the peer to de-fragment received fragment peer_id %d\n",
- peer_id);
- ret = -ENOENT;
- goto out_unlock;
- }
-
- if (!peer->dp_setup_done) {
- ath12k_warn(ab, "The peer %pM [%d] has uninitialized datapath\n",
- peer->addr, peer_id);
- ret = -ENOENT;
- goto out_unlock;
- }
-
- rx_tid = &peer->rx_tid[tid];
-
- if ((!skb_queue_empty(&rx_tid->rx_frags) && seqno != rx_tid->cur_sn) ||
- skb_queue_empty(&rx_tid->rx_frags)) {
- /* Flush stored fragments and start a new sequence */
- ath12k_dp_rx_frags_cleanup(rx_tid, true);
- rx_tid->cur_sn = seqno;
- }
-
- if (rx_tid->rx_frag_bitmap & BIT(frag_no)) {
- /* Fragment already present */
- ret = -EINVAL;
- goto out_unlock;
- }
-
- if ((!rx_tid->rx_frag_bitmap || frag_no > __fls(rx_tid->rx_frag_bitmap)))
- __skb_queue_tail(&rx_tid->rx_frags, msdu);
- else
- ath12k_dp_rx_h_sort_frags(ab, &rx_tid->rx_frags, msdu);
-
- rx_tid->rx_frag_bitmap |= BIT(frag_no);
- if (!more_frags)
- rx_tid->last_frag_no = frag_no;
-
- if (frag_no == 0) {
- rx_tid->dst_ring_desc = kmemdup(ring_desc,
- sizeof(*rx_tid->dst_ring_desc),
- GFP_ATOMIC);
- if (!rx_tid->dst_ring_desc) {
- ret = -ENOMEM;
- goto out_unlock;
- }
- } else {
- ath12k_dp_rx_link_desc_return(ab, &ring_desc->buf_addr_info,
- HAL_WBM_REL_BM_ACT_PUT_IN_IDLE);
- }
-
- if (!rx_tid->last_frag_no ||
- rx_tid->rx_frag_bitmap != GENMASK(rx_tid->last_frag_no, 0)) {
- mod_timer(&rx_tid->frag_timer, jiffies +
- ATH12K_DP_RX_FRAGMENT_TIMEOUT_MS);
- goto out_unlock;
- }
-
- spin_unlock_bh(&ab->base_lock);
- timer_delete_sync(&rx_tid->frag_timer);
- spin_lock_bh(&ab->base_lock);
-
- peer = ath12k_peer_find_by_id(ab, peer_id);
- if (!peer)
- goto err_frags_cleanup;
-
- if (!ath12k_dp_rx_h_defrag_validate_incr_pn(ar, rx_tid))
- goto err_frags_cleanup;
-
- if (ath12k_dp_rx_h_defrag(ar, peer, rx_tid, &defrag_skb))
- goto err_frags_cleanup;
-
- if (!defrag_skb)
- goto err_frags_cleanup;
-
- if (ath12k_dp_rx_h_defrag_reo_reinject(ar, rx_tid, defrag_skb))
- goto err_frags_cleanup;
-
- ath12k_dp_rx_frags_cleanup(rx_tid, false);
- goto out_unlock;
-
-err_frags_cleanup:
- dev_kfree_skb_any(defrag_skb);
- ath12k_dp_rx_frags_cleanup(rx_tid, true);
-out_unlock:
- spin_unlock_bh(&ab->base_lock);
- return ret;
-}
-
-static int
-ath12k_dp_process_rx_err_buf(struct ath12k *ar, struct hal_reo_dest_ring *desc,
- struct list_head *used_list,
- bool drop, u32 cookie)
-{
- struct ath12k_base *ab = ar->ab;
- struct sk_buff *msdu;
- struct ath12k_skb_rxcb *rxcb;
- struct hal_rx_desc *rx_desc;
- u16 msdu_len;
- u32 hal_rx_desc_sz = ab->hal.hal_desc_sz;
- struct ath12k_rx_desc_info *desc_info;
- u64 desc_va;
-
- desc_va = ((u64)le32_to_cpu(desc->buf_va_hi) << 32 |
- le32_to_cpu(desc->buf_va_lo));
- desc_info = (struct ath12k_rx_desc_info *)((unsigned long)desc_va);
-
- /* retry manual desc retrieval */
- if (!desc_info) {
- desc_info = ath12k_dp_get_rx_desc(ab, cookie);
- if (!desc_info) {
- ath12k_warn(ab, "Invalid cookie in DP rx error descriptor retrieval: 0x%x\n",
- cookie);
- return -EINVAL;
- }
- }
-
- if (desc_info->magic != ATH12K_DP_RX_DESC_MAGIC)
- ath12k_warn(ab, " RX Exception, Check HW CC implementation");
-
- msdu = desc_info->skb;
- desc_info->skb = NULL;
-
- list_add_tail(&desc_info->list, used_list);
-
- rxcb = ATH12K_SKB_RXCB(msdu);
- dma_unmap_single(ar->ab->dev, rxcb->paddr,
- msdu->len + skb_tailroom(msdu),
- DMA_FROM_DEVICE);
-
- if (drop) {
- dev_kfree_skb_any(msdu);
- return 0;
- }
-
- rcu_read_lock();
- if (!rcu_dereference(ar->ab->pdevs_active[ar->pdev_idx])) {
- dev_kfree_skb_any(msdu);
- goto exit;
- }
-
- if (test_bit(ATH12K_FLAG_CAC_RUNNING, &ar->dev_flags)) {
- dev_kfree_skb_any(msdu);
- goto exit;
- }
-
- rx_desc = (struct hal_rx_desc *)msdu->data;
- msdu_len = ath12k_dp_rx_h_msdu_len(ar->ab, rx_desc);
- if ((msdu_len + hal_rx_desc_sz) > DP_RX_BUFFER_SIZE) {
- ath12k_warn(ar->ab, "invalid msdu leng %u", msdu_len);
- ath12k_dbg_dump(ar->ab, ATH12K_DBG_DATA, NULL, "", rx_desc,
- sizeof(*rx_desc));
- dev_kfree_skb_any(msdu);
- goto exit;
- }
-
- skb_put(msdu, hal_rx_desc_sz + msdu_len);
-
- if (ath12k_dp_rx_frag_h_mpdu(ar, msdu, desc)) {
- dev_kfree_skb_any(msdu);
- ath12k_dp_rx_link_desc_return(ar->ab, &desc->buf_addr_info,
- HAL_WBM_REL_BM_ACT_PUT_IN_IDLE);
- }
-exit:
- rcu_read_unlock();
- return 0;
-}
-
-static int ath12k_dp_h_msdu_buffer_type(struct ath12k_base *ab,
- struct list_head *list,
- struct hal_reo_dest_ring *desc)
-{
- struct ath12k_rx_desc_info *desc_info;
- struct ath12k_skb_rxcb *rxcb;
- struct sk_buff *msdu;
- u64 desc_va;
-
- ab->device_stats.reo_excep_msdu_buf_type++;
-
- desc_va = (u64)le32_to_cpu(desc->buf_va_hi) << 32 |
- le32_to_cpu(desc->buf_va_lo);
- desc_info = (struct ath12k_rx_desc_info *)(uintptr_t)desc_va;
- if (!desc_info) {
- u32 cookie;
-
- cookie = le32_get_bits(desc->buf_addr_info.info1,
- BUFFER_ADDR_INFO1_SW_COOKIE);
- desc_info = ath12k_dp_get_rx_desc(ab, cookie);
- if (!desc_info) {
- ath12k_warn(ab, "Invalid cookie in manual descriptor retrieval: 0x%x\n",
- cookie);
- return -EINVAL;
- }
- }
-
- if (desc_info->magic != ATH12K_DP_RX_DESC_MAGIC) {
- ath12k_warn(ab, "rx exception, magic check failed with value: %u\n",
- desc_info->magic);
- return -EINVAL;
- }
-
- msdu = desc_info->skb;
- desc_info->skb = NULL;
- list_add_tail(&desc_info->list, list);
- rxcb = ATH12K_SKB_RXCB(msdu);
- dma_unmap_single(ab->dev, rxcb->paddr, msdu->len + skb_tailroom(msdu),
- DMA_FROM_DEVICE);
- dev_kfree_skb_any(msdu);
-
- return 0;
-}
-
-int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
- int budget)
-{
- struct ath12k_hw_group *ag = ab->ag;
- struct list_head rx_desc_used_list[ATH12K_MAX_DEVICES];
- u32 msdu_cookies[HAL_NUM_RX_MSDUS_PER_LINK_DESC];
- int num_buffs_reaped[ATH12K_MAX_DEVICES] = {};
- struct dp_link_desc_bank *link_desc_banks;
- enum hal_rx_buf_return_buf_manager rbm;
- struct hal_rx_msdu_link *link_desc_va;
- int tot_n_bufs_reaped, quota, ret, i;
- struct hal_reo_dest_ring *reo_desc;
- struct dp_rxdma_ring *rx_ring;
- struct dp_srng *reo_except;
- struct ath12k_hw_link *hw_links = ag->hw_links;
- struct ath12k_base *partner_ab;
- u8 hw_link_id, device_id;
- u32 desc_bank, num_msdus;
- struct hal_srng *srng;
- struct ath12k *ar;
- dma_addr_t paddr;
- bool is_frag;
- bool drop;
- int pdev_id;
-
- tot_n_bufs_reaped = 0;
- quota = budget;
-
- for (device_id = 0; device_id < ATH12K_MAX_DEVICES; device_id++)
- INIT_LIST_HEAD(&rx_desc_used_list[device_id]);
-
- reo_except = &ab->dp.reo_except_ring;
-
- srng = &ab->hal.srng_list[reo_except->ring_id];
-
- spin_lock_bh(&srng->lock);
-
- ath12k_hal_srng_access_begin(ab, srng);
-
- while (budget &&
- (reo_desc = ath12k_hal_srng_dst_get_next_entry(ab, srng))) {
- drop = false;
- ab->device_stats.err_ring_pkts++;
-
- hw_link_id = le32_get_bits(reo_desc->info0,
- HAL_REO_DEST_RING_INFO0_SRC_LINK_ID);
- device_id = hw_links[hw_link_id].device_id;
- partner_ab = ath12k_ag_to_ab(ag, device_id);
-
- /* Below case is added to handle data packet from un-associated clients.
- * As it is expected that AST lookup will fail for
- * un-associated station's data packets.
- */
- if (le32_get_bits(reo_desc->info0, HAL_REO_DEST_RING_INFO0_BUFFER_TYPE) ==
- HAL_REO_DEST_RING_BUFFER_TYPE_MSDU) {
- if (!ath12k_dp_h_msdu_buffer_type(partner_ab,
- &rx_desc_used_list[device_id],
- reo_desc)) {
- num_buffs_reaped[device_id]++;
- tot_n_bufs_reaped++;
- }
- goto next_desc;
- }
-
- ret = ath12k_hal_desc_reo_parse_err(ab, reo_desc, &paddr,
- &desc_bank);
- if (ret) {
- ath12k_warn(ab, "failed to parse error reo desc %d\n",
- ret);
- continue;
- }
-
- pdev_id = ath12k_hw_mac_id_to_pdev_id(partner_ab->hw_params,
- hw_links[hw_link_id].pdev_idx);
- ar = partner_ab->pdevs[pdev_id].ar;
-
- link_desc_banks = partner_ab->dp.link_desc_banks;
- link_desc_va = link_desc_banks[desc_bank].vaddr +
- (paddr - link_desc_banks[desc_bank].paddr);
- ath12k_hal_rx_msdu_link_info_get(link_desc_va, &num_msdus, msdu_cookies,
- &rbm);
- if (rbm != partner_ab->dp.idle_link_rbm &&
- rbm != HAL_RX_BUF_RBM_SW3_BM &&
- rbm != partner_ab->hw_params->hal_params->rx_buf_rbm) {
- ab->device_stats.invalid_rbm++;
- ath12k_warn(ab, "invalid return buffer manager %d\n", rbm);
- ath12k_dp_rx_link_desc_return(partner_ab,
- &reo_desc->buf_addr_info,
- HAL_WBM_REL_BM_ACT_REL_MSDU);
- continue;
- }
-
- is_frag = !!(le32_to_cpu(reo_desc->rx_mpdu_info.info0) &
- RX_MPDU_DESC_INFO0_FRAG_FLAG);
-
- /* Process only rx fragments with one msdu per link desc below, and drop
- * msdu's indicated due to error reasons.
- * Dynamic fragmentation not supported in Multi-link client, so drop the
- * partner device buffers.
- */
- if (!is_frag || num_msdus > 1 ||
- partner_ab->device_id != ab->device_id) {
- drop = true;
-
- /* Return the link desc back to wbm idle list */
- ath12k_dp_rx_link_desc_return(partner_ab,
- &reo_desc->buf_addr_info,
- HAL_WBM_REL_BM_ACT_PUT_IN_IDLE);
- }
-
- for (i = 0; i < num_msdus; i++) {
- if (!ath12k_dp_process_rx_err_buf(ar, reo_desc,
- &rx_desc_used_list[device_id],
- drop,
- msdu_cookies[i])) {
- num_buffs_reaped[device_id]++;
- tot_n_bufs_reaped++;
- }
- }
-
-next_desc:
- if (tot_n_bufs_reaped >= quota) {
- tot_n_bufs_reaped = quota;
- goto exit;
- }
-
- budget = quota - tot_n_bufs_reaped;
- }
-
-exit:
- ath12k_hal_srng_access_end(ab, srng);
-
- spin_unlock_bh(&srng->lock);
-
- for (device_id = 0; device_id < ATH12K_MAX_DEVICES; device_id++) {
- if (!num_buffs_reaped[device_id])
- continue;
-
- partner_ab = ath12k_ag_to_ab(ag, device_id);
- rx_ring = &partner_ab->dp.rx_refill_buf_ring;
-
- ath12k_dp_rx_bufs_replenish(partner_ab, rx_ring,
- &rx_desc_used_list[device_id],
- num_buffs_reaped[device_id]);
- }
-
- return tot_n_bufs_reaped;
-}
-
-static void ath12k_dp_rx_null_q_desc_sg_drop(struct ath12k *ar,
- int msdu_len,
- struct sk_buff_head *msdu_list)
-{
- struct sk_buff *skb, *tmp;
- struct ath12k_skb_rxcb *rxcb;
- int n_buffs;
-
- n_buffs = DIV_ROUND_UP(msdu_len,
- (DP_RX_BUFFER_SIZE - ar->ab->hal.hal_desc_sz));
-
- skb_queue_walk_safe(msdu_list, skb, tmp) {
- rxcb = ATH12K_SKB_RXCB(skb);
- if (rxcb->err_rel_src == HAL_WBM_REL_SRC_MODULE_REO &&
- rxcb->err_code == HAL_REO_DEST_RING_ERROR_CODE_DESC_ADDR_ZERO) {
- if (!n_buffs)
- break;
- __skb_unlink(skb, msdu_list);
- dev_kfree_skb_any(skb);
- n_buffs--;
- }
- }
-}
-
-static int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu,
- struct ath12k_dp_rx_info *rx_info,
- struct sk_buff_head *msdu_list)
-{
- struct ath12k_base *ab = ar->ab;
- u16 msdu_len;
- struct hal_rx_desc *desc = (struct hal_rx_desc *)msdu->data;
- u8 l3pad_bytes;
- struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
- u32 hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
-
- msdu_len = ath12k_dp_rx_h_msdu_len(ab, desc);
-
- if (!rxcb->is_frag && ((msdu_len + hal_rx_desc_sz) > DP_RX_BUFFER_SIZE)) {
- /* First buffer will be freed by the caller, so deduct it's length */
- msdu_len = msdu_len - (DP_RX_BUFFER_SIZE - hal_rx_desc_sz);
- ath12k_dp_rx_null_q_desc_sg_drop(ar, msdu_len, msdu_list);
- return -EINVAL;
- }
-
- /* Even after cleaning up the sg buffers in the msdu list with above check
- * any msdu received with continuation flag needs to be dropped as invalid.
- * This protects against some random err frame with continuation flag.
- */
- if (rxcb->is_continuation)
- return -EINVAL;
-
- if (!ath12k_dp_rx_h_msdu_done(ab, desc)) {
- ath12k_warn(ar->ab,
- "msdu_done bit not set in null_q_des processing\n");
- __skb_queue_purge(msdu_list);
- return -EIO;
- }
-
- /* Handle NULL queue descriptor violations arising out a missing
- * REO queue for a given peer or a given TID. This typically
- * may happen if a packet is received on a QOS enabled TID before the
- * ADDBA negotiation for that TID, when the TID queue is setup. Or
- * it may also happen for MC/BC frames if they are not routed to the
- * non-QOS TID queue, in the absence of any other default TID queue.
- * This error can show up both in a REO destination or WBM release ring.
- */
-
- if (rxcb->is_frag) {
- skb_pull(msdu, hal_rx_desc_sz);
- } else {
- l3pad_bytes = ath12k_dp_rx_h_l3pad(ab, desc);
-
- if ((hal_rx_desc_sz + l3pad_bytes + msdu_len) > DP_RX_BUFFER_SIZE)
- return -EINVAL;
-
- skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len);
- skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes);
- }
- if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(ab, desc, msdu)))
- return -EINVAL;
-
- ath12k_dp_rx_h_fetch_info(ab, desc, rx_info);
- ath12k_dp_rx_h_ppdu(ar, rx_info);
- ath12k_dp_rx_h_mpdu(ar, msdu, desc, rx_info);
-
- rxcb->tid = rx_info->tid;
-
- /* Please note that caller will having the access to msdu and completing
- * rx with mac80211. Need not worry about cleaning up amsdu_list.
- */
-
- return 0;
-}
-
-static bool ath12k_dp_rx_h_reo_err(struct ath12k *ar, struct sk_buff *msdu,
- struct ath12k_dp_rx_info *rx_info,
- struct sk_buff_head *msdu_list)
-{
- struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
- bool drop = false;
-
- ar->ab->device_stats.reo_error[rxcb->err_code]++;
-
- switch (rxcb->err_code) {
- case HAL_REO_DEST_RING_ERROR_CODE_DESC_ADDR_ZERO:
- if (ath12k_dp_rx_h_null_q_desc(ar, msdu, rx_info, msdu_list))
- drop = true;
- break;
- case HAL_REO_DEST_RING_ERROR_CODE_PN_CHECK_FAILED:
- /* TODO: Do not drop PN failed packets in the driver;
- * instead, it is good to drop such packets in mac80211
- * after incrementing the replay counters.
- */
- fallthrough;
- default:
- /* TODO: Review other errors and process them to mac80211
- * as appropriate.
- */
- drop = true;
- break;
- }
-
- return drop;
-}
-
-static bool ath12k_dp_rx_h_tkip_mic_err(struct ath12k *ar, struct sk_buff *msdu,
- struct ath12k_dp_rx_info *rx_info)
-{
- struct ath12k_base *ab = ar->ab;
- u16 msdu_len;
- struct hal_rx_desc *desc = (struct hal_rx_desc *)msdu->data;
- u8 l3pad_bytes;
- struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
- u32 hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
-
- rxcb->is_first_msdu = ath12k_dp_rx_h_first_msdu(ab, desc);
- rxcb->is_last_msdu = ath12k_dp_rx_h_last_msdu(ab, desc);
-
- l3pad_bytes = ath12k_dp_rx_h_l3pad(ab, desc);
- msdu_len = ath12k_dp_rx_h_msdu_len(ab, desc);
-
- if ((hal_rx_desc_sz + l3pad_bytes + msdu_len) > DP_RX_BUFFER_SIZE) {
- ath12k_dbg(ab, ATH12K_DBG_DATA,
- "invalid msdu len in tkip mic err %u\n", msdu_len);
- ath12k_dbg_dump(ab, ATH12K_DBG_DATA, NULL, "", desc,
- sizeof(*desc));
- return true;
- }
-
- skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len);
- skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes);
-
- if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(ab, desc, msdu)))
- return true;
-
- ath12k_dp_rx_h_ppdu(ar, rx_info);
-
- rx_info->rx_status->flag |= (RX_FLAG_MMIC_STRIPPED | RX_FLAG_MMIC_ERROR |
- RX_FLAG_DECRYPTED);
-
- ath12k_dp_rx_h_undecap(ar, msdu, desc,
- HAL_ENCRYPT_TYPE_TKIP_MIC, rx_info->rx_status, false);
- return false;
-}
-
-static bool ath12k_dp_rx_h_rxdma_err(struct ath12k *ar, struct sk_buff *msdu,
- struct ath12k_dp_rx_info *rx_info)
-{
- struct ath12k_base *ab = ar->ab;
- struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
- struct hal_rx_desc *rx_desc = (struct hal_rx_desc *)msdu->data;
- bool drop = false;
- u32 err_bitmap;
-
- ar->ab->device_stats.rxdma_error[rxcb->err_code]++;
-
- switch (rxcb->err_code) {
- case HAL_REO_ENTR_RING_RXDMA_ECODE_DECRYPT_ERR:
- case HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR:
- err_bitmap = ath12k_dp_rx_h_mpdu_err(ab, rx_desc);
- if (err_bitmap & HAL_RX_MPDU_ERR_TKIP_MIC) {
- ath12k_dp_rx_h_fetch_info(ab, rx_desc, rx_info);
- drop = ath12k_dp_rx_h_tkip_mic_err(ar, msdu, rx_info);
- break;
- }
- fallthrough;
- default:
- /* TODO: Review other rxdma error code to check if anything is
- * worth reporting to mac80211
- */
- drop = true;
- break;
- }
-
- return drop;
-}
-
-static void ath12k_dp_rx_wbm_err(struct ath12k *ar,
- struct napi_struct *napi,
- struct sk_buff *msdu,
- struct sk_buff_head *msdu_list)
-{
- struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
- struct ieee80211_rx_status rxs = {};
- struct ath12k_dp_rx_info rx_info;
- bool drop = true;
-
- rx_info.addr2_present = false;
- rx_info.rx_status = &rxs;
-
- switch (rxcb->err_rel_src) {
- case HAL_WBM_REL_SRC_MODULE_REO:
- drop = ath12k_dp_rx_h_reo_err(ar, msdu, &rx_info, msdu_list);
- break;
- case HAL_WBM_REL_SRC_MODULE_RXDMA:
- drop = ath12k_dp_rx_h_rxdma_err(ar, msdu, &rx_info);
- break;
- default:
- /* msdu will get freed */
- break;
- }
-
- if (drop) {
- dev_kfree_skb_any(msdu);
- return;
- }
-
- rx_info.rx_status->flag |= RX_FLAG_SKIP_MONITOR;
-
- ath12k_dp_rx_deliver_msdu(ar, napi, msdu, &rx_info);
-}
-
-int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
- struct napi_struct *napi, int budget)
-{
- struct list_head rx_desc_used_list[ATH12K_MAX_DEVICES];
- struct ath12k_hw_group *ag = ab->ag;
- struct ath12k *ar;
- struct ath12k_dp *dp = &ab->dp;
- struct dp_rxdma_ring *rx_ring;
- struct hal_rx_wbm_rel_info err_info;
- struct hal_srng *srng;
- struct sk_buff *msdu;
- struct sk_buff_head msdu_list, scatter_msdu_list;
- struct ath12k_skb_rxcb *rxcb;
- void *rx_desc;
- int num_buffs_reaped[ATH12K_MAX_DEVICES] = {};
- int total_num_buffs_reaped = 0;
- struct ath12k_rx_desc_info *desc_info;
- struct ath12k_device_dp_stats *device_stats = &ab->device_stats;
- struct ath12k_hw_link *hw_links = ag->hw_links;
- struct ath12k_base *partner_ab;
- u8 hw_link_id, device_id;
- int ret, pdev_id;
- struct hal_rx_desc *msdu_data;
-
- __skb_queue_head_init(&msdu_list);
- __skb_queue_head_init(&scatter_msdu_list);
-
- for (device_id = 0; device_id < ATH12K_MAX_DEVICES; device_id++)
- INIT_LIST_HEAD(&rx_desc_used_list[device_id]);
-
- srng = &ab->hal.srng_list[dp->rx_rel_ring.ring_id];
- spin_lock_bh(&srng->lock);
-
- ath12k_hal_srng_access_begin(ab, srng);
-
- while (budget) {
- rx_desc = ath12k_hal_srng_dst_get_next_entry(ab, srng);
- if (!rx_desc)
- break;
-
- ret = ath12k_hal_wbm_desc_parse_err(ab, rx_desc, &err_info);
- if (ret) {
- ath12k_warn(ab,
- "failed to parse rx error in wbm_rel ring desc %d\n",
- ret);
- continue;
- }
-
- desc_info = err_info.rx_desc;
-
- /* retry manual desc retrieval if hw cc is not done */
- if (!desc_info) {
- desc_info = ath12k_dp_get_rx_desc(ab, err_info.cookie);
- if (!desc_info) {
- ath12k_warn(ab, "Invalid cookie in DP WBM rx error descriptor retrieval: 0x%x\n",
- err_info.cookie);
- continue;
- }
- }
-
- if (desc_info->magic != ATH12K_DP_RX_DESC_MAGIC)
- ath12k_warn(ab, "WBM RX err, Check HW CC implementation");
-
- msdu = desc_info->skb;
- desc_info->skb = NULL;
-
- device_id = desc_info->device_id;
- partner_ab = ath12k_ag_to_ab(ag, device_id);
- if (unlikely(!partner_ab)) {
- dev_kfree_skb_any(msdu);
-
- /* In any case continuation bit is set
- * in the previous record, cleanup scatter_msdu_list
- */
- ath12k_dp_clean_up_skb_list(&scatter_msdu_list);
- continue;
- }
-
- list_add_tail(&desc_info->list, &rx_desc_used_list[device_id]);
-
- rxcb = ATH12K_SKB_RXCB(msdu);
- dma_unmap_single(partner_ab->dev, rxcb->paddr,
- msdu->len + skb_tailroom(msdu),
- DMA_FROM_DEVICE);
-
- num_buffs_reaped[device_id]++;
- total_num_buffs_reaped++;
-
- if (!err_info.continuation)
- budget--;
-
- if (err_info.push_reason !=
- HAL_REO_DEST_RING_PUSH_REASON_ERR_DETECTED) {
- dev_kfree_skb_any(msdu);
- continue;
- }
-
- msdu_data = (struct hal_rx_desc *)msdu->data;
- rxcb->err_rel_src = err_info.err_rel_src;
- rxcb->err_code = err_info.err_code;
- rxcb->is_first_msdu = err_info.first_msdu;
- rxcb->is_last_msdu = err_info.last_msdu;
- rxcb->is_continuation = err_info.continuation;
- rxcb->rx_desc = msdu_data;
-
- if (err_info.continuation) {
- __skb_queue_tail(&scatter_msdu_list, msdu);
- continue;
- }
-
- hw_link_id = ath12k_dp_rx_get_msdu_src_link(partner_ab,
- msdu_data);
- if (hw_link_id >= ATH12K_GROUP_MAX_RADIO) {
- dev_kfree_skb_any(msdu);
-
- /* In any case continuation bit is set
- * in the previous record, cleanup scatter_msdu_list
- */
- ath12k_dp_clean_up_skb_list(&scatter_msdu_list);
- continue;
- }
-
- if (!skb_queue_empty(&scatter_msdu_list)) {
- struct sk_buff *msdu;
-
- skb_queue_walk(&scatter_msdu_list, msdu) {
- rxcb = ATH12K_SKB_RXCB(msdu);
- rxcb->hw_link_id = hw_link_id;
- }
-
- skb_queue_splice_tail_init(&scatter_msdu_list,
- &msdu_list);
- }
-
- rxcb = ATH12K_SKB_RXCB(msdu);
- rxcb->hw_link_id = hw_link_id;
- __skb_queue_tail(&msdu_list, msdu);
- }
-
- /* In any case continuation bit is set in the
- * last record, cleanup scatter_msdu_list
- */
- ath12k_dp_clean_up_skb_list(&scatter_msdu_list);
-
- ath12k_hal_srng_access_end(ab, srng);
-
- spin_unlock_bh(&srng->lock);
-
- if (!total_num_buffs_reaped)
- goto done;
-
- for (device_id = 0; device_id < ATH12K_MAX_DEVICES; device_id++) {
- if (!num_buffs_reaped[device_id])
- continue;
-
- partner_ab = ath12k_ag_to_ab(ag, device_id);
- rx_ring = &partner_ab->dp.rx_refill_buf_ring;
-
- ath12k_dp_rx_bufs_replenish(ab, rx_ring,
- &rx_desc_used_list[device_id],
- num_buffs_reaped[device_id]);
- }
-
- rcu_read_lock();
- while ((msdu = __skb_dequeue(&msdu_list))) {
- rxcb = ATH12K_SKB_RXCB(msdu);
- hw_link_id = rxcb->hw_link_id;
-
- device_id = hw_links[hw_link_id].device_id;
- partner_ab = ath12k_ag_to_ab(ag, device_id);
- if (unlikely(!partner_ab)) {
- ath12k_dbg(ab, ATH12K_DBG_DATA,
- "Unable to process WBM error msdu due to invalid hw link id %d device id %d\n",
- hw_link_id, device_id);
- dev_kfree_skb_any(msdu);
- continue;
- }
-
- pdev_id = ath12k_hw_mac_id_to_pdev_id(partner_ab->hw_params,
- hw_links[hw_link_id].pdev_idx);
- ar = partner_ab->pdevs[pdev_id].ar;
-
- if (!ar || !rcu_dereference(ar->ab->pdevs_active[pdev_id])) {
- dev_kfree_skb_any(msdu);
- continue;
- }
-
- if (test_bit(ATH12K_FLAG_CAC_RUNNING, &ar->dev_flags)) {
- dev_kfree_skb_any(msdu);
- continue;
- }
-
- if (rxcb->err_rel_src < HAL_WBM_REL_SRC_MODULE_MAX) {
- device_id = ar->ab->device_id;
- device_stats->rx_wbm_rel_source[rxcb->err_rel_src][device_id]++;
- }
-
- ath12k_dp_rx_wbm_err(ar, napi, msdu, &msdu_list);
- }
- rcu_read_unlock();
-done:
- return total_num_buffs_reaped;
-}
-
-void ath12k_dp_rx_process_reo_status(struct ath12k_base *ab)
-{
- struct ath12k_dp *dp = &ab->dp;
- struct hal_tlv_64_hdr *hdr;
- struct hal_srng *srng;
- struct ath12k_dp_rx_reo_cmd *cmd, *tmp;
- bool found = false;
- u16 tag;
- struct hal_reo_status reo_status;
-
- srng = &ab->hal.srng_list[dp->reo_status_ring.ring_id];
-
- memset(&reo_status, 0, sizeof(reo_status));
-
- spin_lock_bh(&srng->lock);
-
- ath12k_hal_srng_access_begin(ab, srng);
-
- while ((hdr = ath12k_hal_srng_dst_get_next_entry(ab, srng))) {
- tag = le64_get_bits(hdr->tl, HAL_SRNG_TLV_HDR_TAG);
-
- switch (tag) {
- case HAL_REO_GET_QUEUE_STATS_STATUS:
- ath12k_hal_reo_status_queue_stats(ab, hdr,
- &reo_status);
- break;
- case HAL_REO_FLUSH_QUEUE_STATUS:
- ath12k_hal_reo_flush_queue_status(ab, hdr,
- &reo_status);
- break;
- case HAL_REO_FLUSH_CACHE_STATUS:
- ath12k_hal_reo_flush_cache_status(ab, hdr,
- &reo_status);
- break;
- case HAL_REO_UNBLOCK_CACHE_STATUS:
- ath12k_hal_reo_unblk_cache_status(ab, hdr,
- &reo_status);
- break;
- case HAL_REO_FLUSH_TIMEOUT_LIST_STATUS:
- ath12k_hal_reo_flush_timeout_list_status(ab, hdr,
- &reo_status);
- break;
- case HAL_REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS:
- ath12k_hal_reo_desc_thresh_reached_status(ab, hdr,
- &reo_status);
- break;
- case HAL_REO_UPDATE_RX_REO_QUEUE_STATUS:
- ath12k_hal_reo_update_rx_reo_queue_status(ab, hdr,
- &reo_status);
- break;
- default:
- ath12k_warn(ab, "Unknown reo status type %d\n", tag);
- continue;
- }
-
- spin_lock_bh(&dp->reo_cmd_lock);
- list_for_each_entry_safe(cmd, tmp, &dp->reo_cmd_list, list) {
- if (reo_status.uniform_hdr.cmd_num == cmd->cmd_num) {
- found = true;
- list_del(&cmd->list);
- break;
- }
- }
- spin_unlock_bh(&dp->reo_cmd_lock);
-
- if (found) {
- cmd->handler(dp, (void *)&cmd->data,
- reo_status.uniform_hdr.cmd_status);
- kfree(cmd);
- }
-
- found = false;
- }
-
- ath12k_hal_srng_access_end(ab, srng);
-
- spin_unlock_bh(&srng->lock);
-}
+EXPORT_SYMBOL(ath12k_dp_rx_h_get_pn);
void ath12k_dp_rx_free(struct ath12k_base *ab)
{
- struct ath12k_dp *dp = &ab->dp;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
struct dp_srng *srng;
int i;
@@ -4523,92 +1630,9 @@ void ath12k_dp_rx_pdev_free(struct ath12k_base *ab, int mac_id)
ath12k_dp_rx_pdev_srng_free(ar);
}
-int ath12k_dp_rxdma_ring_sel_config_qcn9274(struct ath12k_base *ab)
-{
- struct ath12k_dp *dp = &ab->dp;
- struct htt_rx_ring_tlv_filter tlv_filter = {};
- u32 ring_id;
- int ret;
- u32 hal_rx_desc_sz = ab->hal.hal_desc_sz;
-
- ring_id = dp->rx_refill_buf_ring.refill_buf_ring.ring_id;
-
- tlv_filter.rx_filter = HTT_RX_TLV_FLAGS_RXDMA_RING;
- tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_BAR;
- tlv_filter.pkt_filter_flags3 = HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_MCAST |
- HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_UCAST |
- HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA;
- tlv_filter.offset_valid = true;
- tlv_filter.rx_packet_offset = hal_rx_desc_sz;
-
- tlv_filter.rx_mpdu_start_offset =
- ab->hal_rx_ops->rx_desc_get_mpdu_start_offset();
- tlv_filter.rx_msdu_end_offset =
- ab->hal_rx_ops->rx_desc_get_msdu_end_offset();
-
- if (ath12k_dp_wmask_compaction_rx_tlv_supported(ab)) {
- tlv_filter.rx_mpdu_start_wmask =
- ab->hw_params->hal_ops->rxdma_ring_wmask_rx_mpdu_start();
- tlv_filter.rx_msdu_end_wmask =
- ab->hw_params->hal_ops->rxdma_ring_wmask_rx_msdu_end();
- ath12k_dbg(ab, ATH12K_DBG_DATA,
- "Configuring compact tlv masks rx_mpdu_start_wmask 0x%x rx_msdu_end_wmask 0x%x\n",
- tlv_filter.rx_mpdu_start_wmask, tlv_filter.rx_msdu_end_wmask);
- }
-
- ret = ath12k_dp_tx_htt_rx_filter_setup(ab, ring_id, 0,
- HAL_RXDMA_BUF,
- DP_RXDMA_REFILL_RING_SIZE,
- &tlv_filter);
-
- return ret;
-}
-
-int ath12k_dp_rxdma_ring_sel_config_wcn7850(struct ath12k_base *ab)
-{
- struct ath12k_dp *dp = &ab->dp;
- struct htt_rx_ring_tlv_filter tlv_filter = {};
- u32 ring_id;
- int ret = 0;
- u32 hal_rx_desc_sz = ab->hal.hal_desc_sz;
- int i;
-
- ring_id = dp->rx_refill_buf_ring.refill_buf_ring.ring_id;
-
- tlv_filter.rx_filter = HTT_RX_TLV_FLAGS_RXDMA_RING;
- tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_BAR;
- tlv_filter.pkt_filter_flags3 = HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_MCAST |
- HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_UCAST |
- HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA;
- tlv_filter.offset_valid = true;
- tlv_filter.rx_packet_offset = hal_rx_desc_sz;
-
- tlv_filter.rx_header_offset = offsetof(struct hal_rx_desc_wcn7850, pkt_hdr_tlv);
-
- tlv_filter.rx_mpdu_start_offset =
- ab->hal_rx_ops->rx_desc_get_mpdu_start_offset();
- tlv_filter.rx_msdu_end_offset =
- ab->hal_rx_ops->rx_desc_get_msdu_end_offset();
-
- /* TODO: Selectively subscribe to required qwords within msdu_end
- * and mpdu_start and setup the mask in below msg
- * and modify the rx_desc struct
- */
-
- for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {
- ring_id = dp->rx_mac_buf_ring[i].ring_id;
- ret = ath12k_dp_tx_htt_rx_filter_setup(ab, ring_id, i,
- HAL_RXDMA_BUF,
- DP_RXDMA_REFILL_RING_SIZE,
- &tlv_filter);
- }
-
- return ret;
-}
-
int ath12k_dp_rx_htt_setup(struct ath12k_base *ab)
{
- struct ath12k_dp *dp = &ab->dp;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
u32 ring_id;
int i, ret;
@@ -4680,7 +1704,7 @@ int ath12k_dp_rx_htt_setup(struct ath12k_base *ab)
int ath12k_dp_rx_alloc(struct ath12k_base *ab)
{
- struct ath12k_dp *dp = &ab->dp;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
struct dp_srng *srng;
int i, ret;
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.h b/drivers/net/wireless/ath/ath12k/dp_rx.h
index 69d0a36a91d8..1ec5382f5995 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.h
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.h
@@ -1,21 +1,26 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH12K_DP_RX_H
#define ATH12K_DP_RX_H
+#include <crypto/hash.h>
#include "core.h"
-#include "rx_desc.h"
#include "debug.h"
#define DP_MAX_NWIFI_HDR_LEN 30
+struct ath12k_reoq_buf {
+ void *vaddr;
+ dma_addr_t paddr_aligned;
+ u32 size;
+};
+
struct ath12k_dp_rx_tid {
u8 tid;
u32 ba_win_sz;
- bool active;
struct ath12k_reoq_buf qbuf;
/* Info related to rx fragments */
@@ -28,7 +33,7 @@ struct ath12k_dp_rx_tid {
/* Timer info related to fragments */
struct timer_list frag_timer;
- struct ath12k_base *ab;
+ struct ath12k_dp *dp;
};
struct ath12k_dp_rx_tid_rxq {
@@ -59,6 +64,8 @@ struct ath12k_dp_rx_reo_cmd {
enum hal_reo_cmd_status status);
};
+#define ATH12K_DP_RX_FRAGMENT_TIMEOUT_MS (2 * HZ)
+
#define ATH12K_DP_RX_REO_DESC_FREE_THRES 64
#define ATH12K_DP_RX_REO_DESC_FREE_TIMEOUT_MS 1000
@@ -77,24 +84,6 @@ struct ath12k_dp_rx_rfc1042_hdr {
__be16 snap_type;
} __packed;
-struct ath12k_dp_rx_info {
- struct ieee80211_rx_status *rx_status;
- u32 phy_meta_data;
- u16 peer_id;
- u8 decap_type;
- u8 pkt_type;
- u8 sgi;
- u8 rate_mcs;
- u8 bw;
- u8 nss;
- u8 addr2[ETH_ALEN];
- u8 tid;
- bool ip_csum_fail;
- bool l4_csum_fail;
- bool is_mcbc;
- bool addr2_present;
-};
-
static inline u32 ath12k_he_gi_to_nl80211_he_gi(u8 sgi)
{
u32 ret = 0;
@@ -117,6 +106,109 @@ static inline u32 ath12k_he_gi_to_nl80211_he_gi(u8 sgi)
return ret;
}
+static inline bool ath12k_dp_rx_h_more_frags(struct ath12k_hal *hal,
+ struct sk_buff *skb)
+{
+ struct ieee80211_hdr *hdr;
+
+ hdr = (struct ieee80211_hdr *)(skb->data + hal->hal_desc_sz);
+ return ieee80211_has_morefrags(hdr->frame_control);
+}
+
+static inline u16 ath12k_dp_rx_h_frag_no(struct ath12k_hal *hal,
+ struct sk_buff *skb)
+{
+ struct ieee80211_hdr *hdr;
+
+ hdr = (struct ieee80211_hdr *)(skb->data + hal->hal_desc_sz);
+ return le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
+}
+
+static inline u8 ath12k_dp_rx_h_l3pad(struct ath12k_base *ab,
+ struct hal_rx_desc *desc)
+{
+ return ab->hal.ops->rx_desc_get_l3_pad_bytes(desc);
+}
+
+static inline void ath12k_dp_rx_desc_end_tlv_copy(struct ath12k_hal *hal,
+ struct hal_rx_desc *fdesc,
+ struct hal_rx_desc *ldesc)
+{
+ hal->ops->rx_desc_copy_end_tlv(fdesc, ldesc);
+}
+
+static inline void ath12k_dp_rxdesc_set_msdu_len(struct ath12k_hal *hal,
+ struct hal_rx_desc *desc,
+ u16 len)
+{
+ hal->ops->rx_desc_set_msdu_len(desc, len);
+}
+
+static inline u32 ath12k_dp_rxdesc_get_ppduid(struct ath12k_base *ab,
+ struct hal_rx_desc *rx_desc)
+{
+ return ab->hal.ops->rx_desc_get_mpdu_ppdu_id(rx_desc);
+}
+
+static inline void ath12k_dp_rx_desc_get_dot11_hdr(struct ath12k_hal *hal,
+ struct hal_rx_desc *desc,
+ struct ieee80211_hdr *hdr)
+{
+ hal->ops->rx_desc_get_dot11_hdr(desc, hdr);
+}
+
+static inline void ath12k_dp_rx_desc_get_crypto_header(struct ath12k_hal *hal,
+ struct hal_rx_desc *desc,
+ u8 *crypto_hdr,
+ enum hal_encrypt_type enctype)
+{
+ hal->ops->rx_desc_get_crypto_header(desc, crypto_hdr, enctype);
+}
+
+static inline u8 ath12k_dp_rx_get_msdu_src_link(struct ath12k_hal *hal,
+ struct hal_rx_desc *desc)
+{
+ return hal->ops->rx_desc_get_msdu_src_link_id(desc);
+}
+
+static inline void ath12k_dp_clean_up_skb_list(struct sk_buff_head *skb_list)
+{
+ struct sk_buff *skb;
+
+ while ((skb = __skb_dequeue(skb_list)))
+ dev_kfree_skb_any(skb);
+}
+
+static inline
+void ath12k_dp_extract_rx_desc_data(struct ath12k_hal *hal,
+ struct hal_rx_desc_data *rx_info,
+ struct hal_rx_desc *rx_desc,
+ struct hal_rx_desc *ldesc)
+{
+ hal->ops->extract_rx_desc_data(rx_info, rx_desc, ldesc);
+}
+
+void ath12k_dp_rx_h_undecap(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu,
+ struct hal_rx_desc *rx_desc,
+ enum hal_encrypt_type enctype,
+ bool decrypted,
+ struct hal_rx_desc_data *rx_info);
+void ath12k_dp_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct napi_struct *napi,
+ struct sk_buff *msdu,
+ struct hal_rx_desc_data *rx_info);
+bool ath12k_dp_rx_check_nwifi_hdr_len_valid(struct ath12k_dp *dp,
+ struct hal_rx_desc *rx_desc,
+ struct sk_buff *msdu,
+ struct hal_rx_desc_data *rx_info);
+u64 ath12k_dp_rx_h_get_pn(struct ath12k_dp *dp, struct sk_buff *skb);
+void ath12k_dp_rx_h_sort_frags(struct ath12k_hal *hal,
+ struct sk_buff_head *frag_list,
+ struct sk_buff *cur_frag);
+void ath12k_dp_rx_h_undecap_frag(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu,
+ enum hal_encrypt_type enctype, u32 flags);
+int ath12k_dp_rx_h_michael_mic(struct crypto_shash *tfm, u8 *key,
+ struct ieee80211_hdr *hdr, u8 *data,
+ size_t data_len, u8 *mic);
int ath12k_dp_rx_ampdu_start(struct ath12k *ar,
struct ieee80211_ampdu_params *params,
u8 link_id);
@@ -127,14 +219,12 @@ 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);
-void ath12k_dp_rx_peer_tid_cleanup(struct ath12k *ar, struct ath12k_peer *peer);
+void ath12k_dp_rx_peer_tid_cleanup(struct ath12k *ar, struct ath12k_dp_link_peer *peer);
void ath12k_dp_rx_peer_tid_delete(struct ath12k *ar,
- struct ath12k_peer *peer, u8 tid);
+ struct ath12k_dp_link_peer *peer, u8 tid);
int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_id,
u8 tid, u32 ba_win_sz, u16 ssn,
enum hal_pn_type pn_type);
-void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab,
- struct sk_buff *skb);
int ath12k_dp_rx_pdev_reo_setup(struct ath12k_base *ab);
void ath12k_dp_rx_pdev_reo_cleanup(struct ath12k_base *ab);
int ath12k_dp_rx_htt_setup(struct ath12k_base *ab);
@@ -143,15 +233,7 @@ void ath12k_dp_rx_free(struct ath12k_base *ab);
int ath12k_dp_rx_pdev_alloc(struct ath12k_base *ab, int pdev_idx);
void ath12k_dp_rx_pdev_free(struct ath12k_base *ab, int pdev_idx);
void ath12k_dp_rx_reo_cmd_list_cleanup(struct ath12k_base *ab);
-void ath12k_dp_rx_process_reo_status(struct ath12k_base *ab);
-int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
- struct napi_struct *napi, int budget);
-int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
- int budget);
-int ath12k_dp_rx_process(struct ath12k_base *ab, int mac_id,
- struct napi_struct *napi,
- int budget);
-int ath12k_dp_rx_bufs_replenish(struct ath12k_base *ab,
+int ath12k_dp_rx_bufs_replenish(struct ath12k_dp *dp,
struct dp_rxdma_ring *rx_ring,
struct list_head *used_list,
int req_entries);
@@ -160,32 +242,27 @@ int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev
u8 ath12k_dp_rx_h_l3pad(struct ath12k_base *ab,
struct hal_rx_desc *desc);
-struct ath12k_peer *
-ath12k_dp_rx_h_find_peer(struct ath12k_base *ab, struct sk_buff *msdu,
- struct ath12k_dp_rx_info *rx_info);
+struct ath12k_dp_link_peer *
+ath12k_dp_rx_h_find_link_peer(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu,
+ struct hal_rx_desc_data *rx_info);
u8 ath12k_dp_rx_h_decap_type(struct ath12k_base *ab,
struct hal_rx_desc *desc);
u32 ath12k_dp_rx_h_mpdu_err(struct ath12k_base *ab,
struct hal_rx_desc *desc);
-void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct ath12k_dp_rx_info *rx_info);
-int ath12k_dp_rxdma_ring_sel_config_qcn9274(struct ath12k_base *ab);
-int ath12k_dp_rxdma_ring_sel_config_wcn7850(struct ath12k_base *ab);
-
-int ath12k_dp_htt_tlv_iter(struct ath12k_base *ab, const void *ptr, size_t len,
- int (*iter)(struct ath12k_base *ar, u16 tag, u16 len,
- const void *ptr, void *data),
- void *data);
-void ath12k_dp_rx_h_fetch_info(struct ath12k_base *ab, struct hal_rx_desc *rx_desc,
- struct ath12k_dp_rx_info *rx_info);
-
-int ath12k_dp_rx_crypto_mic_len(struct ath12k *ar, enum hal_encrypt_type enctype);
+int ath12k_dp_rx_crypto_mic_len(struct ath12k_dp *dp, enum hal_encrypt_type enctype);
u32 ath12k_dp_rxdesc_get_ppduid(struct ath12k_base *ab,
struct hal_rx_desc *rx_desc);
-bool ath12k_dp_rxdesc_mpdu_valid(struct ath12k_base *ab,
- struct hal_rx_desc *rx_desc);
-int ath12k_dp_rx_link_desc_return(struct ath12k_base *ab,
- struct ath12k_buffer_addr *buf_addr_info,
- enum hal_wbm_rel_bm_act action);
-bool ath12k_dp_rxdesc_mpdu_valid(struct ath12k_base *ab,
- struct hal_rx_desc *rx_desc);
+void ath12k_dp_rx_h_ppdu(struct ath12k_pdev_dp *dp_pdev,
+ struct hal_rx_desc_data *rx_info);
+struct sk_buff *ath12k_dp_rx_get_msdu_last_buf(struct sk_buff_head *msdu_list,
+ struct sk_buff *first);
+void ath12k_dp_reo_cmd_free(struct ath12k_dp *dp, void *ctx,
+ enum hal_reo_cmd_status status);
+void ath12k_dp_rx_tid_del_func(struct ath12k_dp *dp, void *ctx,
+ enum hal_reo_cmd_status status);
+void ath12k_dp_rx_process_reo_cmd_update_rx_queue_list(struct ath12k_dp *dp);
+void ath12k_dp_init_rx_tid_rxq(struct ath12k_dp_rx_tid_rxq *rx_tid_rxq,
+ struct ath12k_dp_rx_tid *rx_tid,
+ bool active);
+void ath12k_dp_mark_tid_as_inactive(struct ath12k_dp *dp, int peer_id, u8 tid);
#endif /* ATH12K_DP_RX_H */
diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c
index abc84ca8467a..c10da6195c9c 100644
--- a/drivers/net/wireless/ath/ath12k/dp_tx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_tx.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-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include "core.h"
@@ -12,7 +12,7 @@
#include "peer.h"
#include "mac.h"
-static enum hal_tcl_encap_type
+enum hal_tcl_encap_type
ath12k_dp_tx_get_encap_type(struct ath12k_base *ab, struct sk_buff *skb)
{
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -25,8 +25,9 @@ ath12k_dp_tx_get_encap_type(struct ath12k_base *ab, struct sk_buff *skb)
return HAL_TCL_ENCAP_TYPE_NATIVE_WIFI;
}
+EXPORT_SYMBOL(ath12k_dp_tx_get_encap_type);
-static void ath12k_dp_tx_encap_nwifi(struct sk_buff *skb)
+void ath12k_dp_tx_encap_nwifi(struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (void *)skb->data;
u8 *qos_ctl;
@@ -42,8 +43,9 @@ static void ath12k_dp_tx_encap_nwifi(struct sk_buff *skb)
hdr = (void *)skb->data;
hdr->frame_control &= ~__cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
}
+EXPORT_SYMBOL(ath12k_dp_tx_encap_nwifi);
-static u8 ath12k_dp_tx_get_tid(struct sk_buff *skb)
+u8 ath12k_dp_tx_get_tid(struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (void *)skb->data;
struct ath12k_skb_cb *cb = ATH12K_SKB_CB(skb);
@@ -55,6 +57,7 @@ static u8 ath12k_dp_tx_get_tid(struct sk_buff *skb)
else
return skb->priority & IEEE80211_QOS_CTL_TID_MASK;
}
+EXPORT_SYMBOL(ath12k_dp_tx_get_tid);
enum hal_encrypt_type ath12k_dp_tx_get_encrypt_type(u32 cipher)
{
@@ -77,19 +80,21 @@ enum hal_encrypt_type ath12k_dp_tx_get_encrypt_type(u32 cipher)
return HAL_ENCRYPT_TYPE_OPEN;
}
}
+EXPORT_SYMBOL(ath12k_dp_tx_get_encrypt_type);
-static void ath12k_dp_tx_release_txbuf(struct ath12k_dp *dp,
- struct ath12k_tx_desc_info *tx_desc,
- u8 pool_id)
+void ath12k_dp_tx_release_txbuf(struct ath12k_dp *dp,
+ struct ath12k_tx_desc_info *tx_desc,
+ u8 pool_id)
{
spin_lock_bh(&dp->tx_desc_lock[pool_id]);
tx_desc->skb_ext_desc = NULL;
list_move_tail(&tx_desc->list, &dp->tx_desc_free_list[pool_id]);
spin_unlock_bh(&dp->tx_desc_lock[pool_id]);
}
+EXPORT_SYMBOL(ath12k_dp_tx_release_txbuf);
-static struct ath12k_tx_desc_info *ath12k_dp_tx_assign_buffer(struct ath12k_dp *dp,
- u8 pool_id)
+struct ath12k_tx_desc_info *ath12k_dp_tx_assign_buffer(struct ath12k_dp *dp,
+ u8 pool_id)
{
struct ath12k_tx_desc_info *desc;
@@ -108,28 +113,9 @@ static struct ath12k_tx_desc_info *ath12k_dp_tx_assign_buffer(struct ath12k_dp *
return desc;
}
+EXPORT_SYMBOL(ath12k_dp_tx_assign_buffer);
-static void ath12k_hal_tx_cmd_ext_desc_setup(struct ath12k_base *ab,
- struct hal_tx_msdu_ext_desc *tcl_ext_cmd,
- struct hal_tx_info *ti)
-{
- tcl_ext_cmd->info0 = le32_encode_bits(ti->paddr,
- HAL_TX_MSDU_EXT_INFO0_BUF_PTR_LO);
- tcl_ext_cmd->info1 = le32_encode_bits(0x0,
- HAL_TX_MSDU_EXT_INFO1_BUF_PTR_HI) |
- le32_encode_bits(ti->data_len,
- HAL_TX_MSDU_EXT_INFO1_BUF_LEN);
-
- tcl_ext_cmd->info1 |= le32_encode_bits(1, HAL_TX_MSDU_EXT_INFO1_EXTN_OVERRIDE) |
- le32_encode_bits(ti->encap_type,
- HAL_TX_MSDU_EXT_INFO1_ENCAP_TYPE) |
- le32_encode_bits(ti->encrypt_type,
- HAL_TX_MSDU_EXT_INFO1_ENCRYPT_TYPE);
-}
-
-#define HTT_META_DATA_ALIGNMENT 0x8
-
-static void *ath12k_dp_metadata_align_skb(struct sk_buff *skb, u8 tail_len)
+void *ath12k_dp_metadata_align_skb(struct sk_buff *skb, u8 tail_len)
{
struct sk_buff *tail;
void *metadata;
@@ -141,29 +127,7 @@ static void *ath12k_dp_metadata_align_skb(struct sk_buff *skb, u8 tail_len)
memset(metadata, 0, tail_len);
return metadata;
}
-
-/* Preparing HTT Metadata when utilized with ext MSDU */
-static int ath12k_dp_prepare_htt_metadata(struct sk_buff *skb)
-{
- struct hal_tx_msdu_metadata *desc_ext;
- u8 htt_desc_size;
- /* Size rounded of multiple of 8 bytes */
- u8 htt_desc_size_aligned;
-
- htt_desc_size = sizeof(struct hal_tx_msdu_metadata);
- htt_desc_size_aligned = ALIGN(htt_desc_size, HTT_META_DATA_ALIGNMENT);
-
- desc_ext = ath12k_dp_metadata_align_skb(skb, htt_desc_size_aligned);
- if (!desc_ext)
- return -ENOMEM;
-
- desc_ext->info0 = le32_encode_bits(1, HAL_TX_MSDU_METADATA_INFO0_ENCRYPT_FLAG) |
- le32_encode_bits(0, HAL_TX_MSDU_METADATA_INFO0_ENCRYPT_TYPE) |
- le32_encode_bits(1,
- HAL_TX_MSDU_METADATA_INFO0_HOST_TX_DESC_POOL);
-
- return 0;
-}
+EXPORT_SYMBOL(ath12k_dp_metadata_align_skb);
static void ath12k_dp_tx_move_payload(struct sk_buff *skb,
unsigned long delta,
@@ -182,10 +146,9 @@ static void ath12k_dp_tx_move_payload(struct sk_buff *skb,
}
}
-static int ath12k_dp_tx_align_payload(struct ath12k_base *ab,
- struct sk_buff **pskb)
+int ath12k_dp_tx_align_payload(struct ath12k_dp *dp, struct sk_buff **pskb)
{
- u32 iova_mask = ab->hw_params->iova_mask;
+ u32 iova_mask = dp->hw_params->iova_mask;
unsigned long offset, delta1, delta2;
struct sk_buff *skb2, *skb = *pskb;
unsigned int headroom = skb_headroom(skb);
@@ -218,1564 +181,33 @@ static int ath12k_dp_tx_align_payload(struct ath12k_base *ab,
out:
return ret;
}
+EXPORT_SYMBOL(ath12k_dp_tx_align_payload);
-int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
- struct sk_buff *skb, bool gsn_valid, int mcbc_gsn,
- bool is_mcast)
-{
- struct ath12k_base *ab = ar->ab;
- struct ath12k_dp *dp = &ab->dp;
- struct hal_tx_info ti = {};
- struct ath12k_tx_desc_info *tx_desc;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb);
- struct hal_tcl_data_cmd *hal_tcl_desc;
- struct hal_tx_msdu_ext_desc *msg;
- struct sk_buff *skb_ext_desc = NULL;
- 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;
- int ret;
- u8 ring_selector, ring_map = 0;
- bool tcl_ring_retry;
- bool msdu_ext_desc = false;
- bool add_htt_metadata = false;
- u32 iova_mask = ab->hw_params->iova_mask;
- bool is_diff_encap = false;
- bool is_null_frame = false;
-
- if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
- return -ESHUTDOWN;
-
- if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
- !ieee80211_is_data(hdr->frame_control))
- return -EOPNOTSUPP;
-
- pool_id = skb_get_queue_mapping(skb) & (ATH12K_HW_MAX_QUEUES - 1);
-
- /* Let the default ring selection be based on current processor
- * number, where one of the 3 tcl rings are selected based on
- * the smp_processor_id(). In case that ring
- * is full/busy, we resort to other available rings.
- * If all rings are full, we drop the packet.
- * TODO: Add throttling logic when all rings are full
- */
- ring_selector = ab->hw_params->hw_ops->get_ring_selector(skb);
-
-tcl_ring_sel:
- tcl_ring_retry = false;
- ti.ring_id = ring_selector % ab->hw_params->max_tx_ring;
-
- ring_map |= BIT(ti.ring_id);
- ti.rbm_id = ab->hw_params->hal_ops->tcl_to_wbm_rbm_map[ti.ring_id].rbm_id;
-
- tx_ring = &dp->tx_ring[ti.ring_id];
-
- tx_desc = ath12k_dp_tx_assign_buffer(dp, pool_id);
- if (!tx_desc)
- return -ENOMEM;
-
- ti.bank_id = arvif->bank_id;
- ti.meta_data_flags = arvif->tcl_metadata;
-
- 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 =
- ath12k_dp_tx_get_encrypt_type(skb_cb->cipher);
-
- if (ieee80211_has_protected(hdr->frame_control))
- skb_put(skb, IEEE80211_CCMP_MIC_LEN);
- } else {
- ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN;
- }
-
- msdu_ext_desc = true;
- }
-
- if (gsn_valid) {
- /* Reset and Initialize meta_data_flags with Global Sequence
- * Number (GSN) info.
- */
- ti.meta_data_flags =
- u32_encode_bits(HTT_TCL_META_DATA_TYPE_GLOBAL_SEQ_NUM,
- HTT_TCL_META_DATA_TYPE) |
- u32_encode_bits(mcbc_gsn, HTT_TCL_META_DATA_GLOBAL_SEQ_NUM);
- }
-
- ti.encap_type = ath12k_dp_tx_get_encap_type(ab, skb);
- ti.addr_search_flags = arvif->hal_addr_search_flags;
- ti.search_type = arvif->search_type;
- ti.type = HAL_TCL_DESC_TYPE_BUFFER;
- ti.pkt_offset = 0;
- ti.lmac_id = ar->lmac_id;
-
- ti.vdev_id = arvif->vdev_id;
- if (gsn_valid)
- ti.vdev_id += HTT_TX_MLO_MCAST_HOST_REINJECT_BASE_VDEV_ID;
-
- ti.bss_ast_hash = arvif->ast_hash;
- ti.bss_ast_idx = arvif->ast_idx;
- ti.dscp_tid_tbl_idx = 0;
-
- if (skb->ip_summed == CHECKSUM_PARTIAL &&
- ti.encap_type != HAL_TCL_ENCAP_TYPE_RAW) {
- ti.flags0 |= u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_IP4_CKSUM_EN) |
- u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_UDP4_CKSUM_EN) |
- u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_UDP6_CKSUM_EN) |
- u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_TCP4_CKSUM_EN) |
- u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_TCP6_CKSUM_EN);
- }
-
- ti.flags1 |= u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO3_TID_OVERWRITE);
-
- ti.tid = ath12k_dp_tx_get_tid(skb);
-
- switch (ti.encap_type) {
- case HAL_TCL_ENCAP_TYPE_NATIVE_WIFI:
- is_null_frame = ieee80211_is_nullfunc(hdr->frame_control);
- if (ahvif->vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED) {
- if (skb->protocol == cpu_to_be16(ETH_P_PAE) || is_null_frame)
- is_diff_encap = true;
-
- /* Firmware expects msdu ext descriptor for nwifi/raw packets
- * received in ETH mode. Without this, observed tx fail for
- * Multicast packets in ETH mode.
- */
- msdu_ext_desc = true;
- } else {
- ath12k_dp_tx_encap_nwifi(skb);
- }
- break;
- case HAL_TCL_ENCAP_TYPE_RAW:
- if (!test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) {
- ret = -EINVAL;
- goto fail_remove_tx_buf;
- }
- break;
- case HAL_TCL_ENCAP_TYPE_ETHERNET:
- /* no need to encap */
- break;
- case HAL_TCL_ENCAP_TYPE_802_3:
- default:
- /* TODO: Take care of other encap modes as well */
- ret = -EINVAL;
- atomic_inc(&ab->device_stats.tx_err.misc_fail);
- goto fail_remove_tx_buf;
- }
-
- if (iova_mask &&
- (unsigned long)skb->data & iova_mask) {
- ret = ath12k_dp_tx_align_payload(ab, &skb);
- if (ret) {
- ath12k_warn(ab, "failed to align TX buffer %d\n", ret);
- /* don't bail out, give original buffer
- * a chance even unaligned.
- */
- goto map;
- }
-
- /* hdr is pointing to a wrong place after alignment,
- * so refresh it for later use.
- */
- hdr = (void *)skb->data;
- }
-map:
- ti.paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE);
- if (dma_mapping_error(ab->dev, ti.paddr)) {
- atomic_inc(&ab->device_stats.tx_err.misc_fail);
- ath12k_warn(ab, "failed to DMA map data Tx buffer\n");
- ret = -ENOMEM;
- goto fail_remove_tx_buf;
- }
-
- if ((!test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags) &&
- !(skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP) &&
- !(skb_cb->flags & ATH12K_SKB_CIPHER_SET) &&
- ieee80211_has_protected(hdr->frame_control)) ||
- is_diff_encap) {
- /* Firmware is not expecting meta data for qos null
- * nwifi packet received in ETH encap mode.
- */
- if (is_null_frame && msdu_ext_desc)
- goto skip_htt_meta;
-
- /* Add metadata for sw encrypted vlan group traffic
- * and EAPOL nwifi packet received in ETH encap mode.
- */
- add_htt_metadata = true;
- msdu_ext_desc = true;
- ti.meta_data_flags |= HTT_TCL_META_DATA_VALID_HTT;
-skip_htt_meta:
- ti.flags0 |= u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_TO_FW);
- ti.encap_type = HAL_TCL_ENCAP_TYPE_RAW;
- ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN;
- }
-
- tx_desc->skb = skb;
- tx_desc->mac_id = ar->pdev_idx;
- ti.desc_id = tx_desc->desc_id;
- ti.data_len = skb->len;
- skb_cb->paddr = ti.paddr;
- skb_cb->vif = ahvif->vif;
- skb_cb->ar = ar;
-
- if (msdu_ext_desc) {
- skb_ext_desc = dev_alloc_skb(sizeof(struct hal_tx_msdu_ext_desc));
- if (!skb_ext_desc) {
- ret = -ENOMEM;
- goto fail_unmap_dma;
- }
-
- skb_put(skb_ext_desc, sizeof(struct hal_tx_msdu_ext_desc));
- memset(skb_ext_desc->data, 0, skb_ext_desc->len);
-
- msg = (struct hal_tx_msdu_ext_desc *)skb_ext_desc->data;
- ath12k_hal_tx_cmd_ext_desc_setup(ab, msg, &ti);
-
- if (add_htt_metadata) {
- ret = ath12k_dp_prepare_htt_metadata(skb_ext_desc);
- if (ret < 0) {
- ath12k_dbg(ab, ATH12K_DBG_DP_TX,
- "Failed to add HTT meta data, dropping packet\n");
- goto fail_free_ext_skb;
- }
- }
-
- ti.paddr = dma_map_single(ab->dev, skb_ext_desc->data,
- skb_ext_desc->len, DMA_TO_DEVICE);
- ret = dma_mapping_error(ab->dev, ti.paddr);
- if (ret)
- goto fail_free_ext_skb;
-
- ti.data_len = skb_ext_desc->len;
- ti.type = HAL_TCL_DESC_TYPE_EXT_DESC;
-
- skb_cb->paddr_ext_desc = ti.paddr;
- tx_desc->skb_ext_desc = skb_ext_desc;
- }
-
- hal_ring_id = tx_ring->tcl_data_ring.ring_id;
- tcl_ring = &ab->hal.srng_list[hal_ring_id];
-
- spin_lock_bh(&tcl_ring->lock);
-
- ath12k_hal_srng_access_begin(ab, tcl_ring);
-
- hal_tcl_desc = ath12k_hal_srng_src_get_next_entry(ab, tcl_ring);
- if (!hal_tcl_desc) {
- /* NOTE: It is highly unlikely we'll be running out of tcl_ring
- * desc because the desc is directly enqueued onto hw queue.
- */
- ath12k_hal_srng_access_end(ab, tcl_ring);
- ab->device_stats.tx_err.desc_na[ti.ring_id]++;
- spin_unlock_bh(&tcl_ring->lock);
- ret = -ENOMEM;
-
- /* Checking for available tcl descriptors in another ring in
- * case of failure due to full tcl ring now, is better than
- * checking this ring earlier for each pkt tx.
- * Restart ring selection if some rings are not checked yet.
- */
- if (ring_map != (BIT(ab->hw_params->max_tx_ring) - 1) &&
- ab->hw_params->tcl_ring_retry) {
- tcl_ring_retry = true;
- ring_selector++;
- }
-
- goto fail_unmap_dma_ext;
- }
-
- spin_lock_bh(&arvif->link_stats_lock);
- arvif->link_stats.tx_encap_type[ti.encap_type]++;
- arvif->link_stats.tx_encrypt_type[ti.encrypt_type]++;
- arvif->link_stats.tx_desc_type[ti.type]++;
-
- if (is_mcast)
- arvif->link_stats.tx_bcast_mcast++;
- else
- arvif->link_stats.tx_enqueued++;
- spin_unlock_bh(&arvif->link_stats_lock);
-
- ab->device_stats.tx_enqueued[ti.ring_id]++;
-
- ath12k_hal_tx_cmd_desc_setup(ab, hal_tcl_desc, &ti);
-
- ath12k_hal_srng_access_end(ab, tcl_ring);
-
- spin_unlock_bh(&tcl_ring->lock);
-
- ath12k_dbg_dump(ab, ATH12K_DBG_DP_TX, NULL, "dp tx msdu: ",
- skb->data, skb->len);
-
- atomic_inc(&ar->dp.num_tx_pending);
-
- return 0;
-
-fail_unmap_dma_ext:
- if (skb_cb->paddr_ext_desc)
- dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc,
- skb_ext_desc->len,
- DMA_TO_DEVICE);
-fail_free_ext_skb:
- kfree_skb(skb_ext_desc);
-
-fail_unmap_dma:
- dma_unmap_single(ab->dev, ti.paddr, ti.data_len, DMA_TO_DEVICE);
-
-fail_remove_tx_buf:
- ath12k_dp_tx_release_txbuf(dp, tx_desc, pool_id);
-
- spin_lock_bh(&arvif->link_stats_lock);
- arvif->link_stats.tx_dropped++;
- spin_unlock_bh(&arvif->link_stats_lock);
-
- if (tcl_ring_retry)
- goto tcl_ring_sel;
-
- return ret;
-}
-
-static void ath12k_dp_tx_free_txbuf(struct ath12k_base *ab,
- struct dp_tx_ring *tx_ring,
- struct ath12k_tx_desc_params *desc_params)
+void ath12k_dp_tx_free_txbuf(struct ath12k_dp *dp,
+ struct dp_tx_ring *tx_ring,
+ struct ath12k_tx_desc_params *desc_params)
{
- struct ath12k *ar;
+ struct ath12k_pdev_dp *dp_pdev;
struct sk_buff *msdu = desc_params->skb;
struct ath12k_skb_cb *skb_cb;
- u8 pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, desc_params->mac_id);
+ u8 pdev_idx = ath12k_hw_mac_id_to_pdev_id(dp->hw_params, desc_params->mac_id);
skb_cb = ATH12K_SKB_CB(msdu);
- ar = ab->pdevs[pdev_id].ar;
- dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
+ dma_unmap_single(dp->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
if (skb_cb->paddr_ext_desc) {
- dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc,
+ dma_unmap_single(dp->dev, skb_cb->paddr_ext_desc,
desc_params->skb_ext_desc->len, DMA_TO_DEVICE);
dev_kfree_skb_any(desc_params->skb_ext_desc);
}
- ieee80211_free_txskb(ar->ah->hw, msdu);
-
- if (atomic_dec_and_test(&ar->dp.num_tx_pending))
- wake_up(&ar->dp.tx_empty_waitq);
-}
-
-static void
-ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab,
- struct ath12k_tx_desc_params *desc_params,
- struct dp_tx_ring *tx_ring,
- struct ath12k_dp_htt_wbm_tx_status *ts,
- u16 peer_id)
-{
- struct ieee80211_tx_info *info;
- struct ath12k_link_vif *arvif;
- struct ath12k_skb_cb *skb_cb;
- struct ieee80211_vif *vif;
- struct ath12k_vif *ahvif;
- struct ath12k *ar;
- struct sk_buff *msdu = desc_params->skb;
- s32 noise_floor;
- struct ieee80211_tx_status status = {};
- struct ath12k_peer *peer;
-
- skb_cb = ATH12K_SKB_CB(msdu);
- info = IEEE80211_SKB_CB(msdu);
-
- ar = skb_cb->ar;
- ab->device_stats.tx_completed[tx_ring->tcl_data_ring_id]++;
-
- if (atomic_dec_and_test(&ar->dp.num_tx_pending))
- wake_up(&ar->dp.tx_empty_waitq);
-
- dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
- if (skb_cb->paddr_ext_desc) {
- dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc,
- desc_params->skb_ext_desc->len, DMA_TO_DEVICE);
- dev_kfree_skb_any(desc_params->skb_ext_desc);
- }
-
- vif = skb_cb->vif;
- if (vif) {
- ahvif = ath12k_vif_to_ahvif(vif);
- rcu_read_lock();
- arvif = rcu_dereference(ahvif->link[skb_cb->link_id]);
- if (arvif) {
- spin_lock_bh(&arvif->link_stats_lock);
- arvif->link_stats.tx_completed++;
- spin_unlock_bh(&arvif->link_stats_lock);
- }
- rcu_read_unlock();
- }
-
- memset(&info->status, 0, sizeof(info->status));
-
- if (ts->acked) {
- if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
- info->flags |= IEEE80211_TX_STAT_ACK;
- info->status.ack_signal = ts->ack_rssi;
-
- if (!test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,
- ab->wmi_ab.svc_map)) {
- spin_lock_bh(&ar->data_lock);
- noise_floor = ath12k_pdev_get_noise_floor(ar);
- spin_unlock_bh(&ar->data_lock);
-
- info->status.ack_signal += noise_floor;
- }
-
- info->status.flags = IEEE80211_TX_STATUS_ACK_SIGNAL_VALID;
- } else {
- info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
- }
- }
- rcu_read_lock();
- spin_lock_bh(&ab->base_lock);
- peer = ath12k_peer_find_by_id(ab, peer_id);
- if (!peer || !peer->sta) {
- ath12k_dbg(ab, ATH12K_DBG_DATA,
- "dp_tx: failed to find the peer with peer_id %d\n", peer_id);
- spin_unlock_bh(&ab->base_lock);
- ieee80211_free_txskb(ath12k_ar_to_hw(ar), msdu);
- goto exit;
- } else {
- status.sta = peer->sta;
- }
- spin_unlock_bh(&ab->base_lock);
-
- status.info = info;
- status.skb = msdu;
- ieee80211_tx_status_ext(ath12k_ar_to_hw(ar), &status);
-exit:
- rcu_read_unlock();
-}
-
-static void
-ath12k_dp_tx_process_htt_tx_complete(struct ath12k_base *ab, void *desc,
- struct dp_tx_ring *tx_ring,
- struct ath12k_tx_desc_params *desc_params)
-{
- struct htt_tx_wbm_completion *status_desc;
- struct ath12k_dp_htt_wbm_tx_status ts = {};
- enum hal_wbm_htt_tx_comp_status wbm_status;
- u16 peer_id;
-
- status_desc = desc;
-
- wbm_status = le32_get_bits(status_desc->info0,
- HTT_TX_WBM_COMP_INFO0_STATUS);
- ab->device_stats.fw_tx_status[wbm_status]++;
-
- switch (wbm_status) {
- case HAL_WBM_REL_HTT_TX_COMP_STATUS_OK:
- ts.acked = (wbm_status == HAL_WBM_REL_HTT_TX_COMP_STATUS_OK);
- ts.ack_rssi = le32_get_bits(status_desc->info2,
- HTT_TX_WBM_COMP_INFO2_ACK_RSSI);
-
- peer_id = le32_get_bits(((struct hal_wbm_completion_ring_tx *)desc)->
- info3, HAL_WBM_COMPL_TX_INFO3_PEER_ID);
-
- ath12k_dp_tx_htt_tx_complete_buf(ab, desc_params, tx_ring, &ts, peer_id);
- break;
- case HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP:
- case HAL_WBM_REL_HTT_TX_COMP_STATUS_TTL:
- case HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ:
- case HAL_WBM_REL_HTT_TX_COMP_STATUS_INSPECT:
- case HAL_WBM_REL_HTT_TX_COMP_STATUS_VDEVID_MISMATCH:
- ath12k_dp_tx_free_txbuf(ab, tx_ring, desc_params);
- break;
- case HAL_WBM_REL_HTT_TX_COMP_STATUS_MEC_NOTIFY:
- /* This event is to be handled only when the driver decides to
- * use WDS offload functionality.
- */
- break;
- default:
- ath12k_warn(ab, "Unknown htt wbm tx status %d\n", wbm_status);
- break;
- }
-}
-
-static void ath12k_dp_tx_update_txcompl(struct ath12k *ar, struct hal_tx_status *ts)
-{
- struct ath12k_base *ab = ar->ab;
- struct ath12k_peer *peer;
- struct ieee80211_sta *sta;
- struct ath12k_sta *ahsta;
- struct ath12k_link_sta *arsta;
- struct rate_info txrate = {};
- u16 rate, ru_tones;
- u8 rate_idx = 0;
- int ret;
-
- spin_lock_bh(&ab->base_lock);
- peer = ath12k_peer_find_by_id(ab, ts->peer_id);
- if (!peer || !peer->sta) {
- ath12k_dbg(ab, ATH12K_DBG_DP_TX,
- "failed to find the peer by id %u\n", ts->peer_id);
- spin_unlock_bh(&ab->base_lock);
- return;
- }
- sta = peer->sta;
- ahsta = ath12k_sta_to_ahsta(sta);
- arsta = &ahsta->deflink;
-
- /* This is to prefer choose the real NSS value arsta->last_txrate.nss,
- * if it is invalid, then choose the NSS value while assoc.
- */
- if (arsta->last_txrate.nss)
- txrate.nss = arsta->last_txrate.nss;
- else
- txrate.nss = arsta->peer_nss;
- spin_unlock_bh(&ab->base_lock);
-
- switch (ts->pkt_type) {
- case HAL_TX_RATE_STATS_PKT_TYPE_11A:
- case HAL_TX_RATE_STATS_PKT_TYPE_11B:
- ret = ath12k_mac_hw_ratecode_to_legacy_rate(ts->mcs,
- ts->pkt_type,
- &rate_idx,
- &rate);
- if (ret < 0) {
- ath12k_warn(ab, "Invalid tx legacy rate %d\n", ret);
- return;
- }
-
- txrate.legacy = rate;
- break;
- case HAL_TX_RATE_STATS_PKT_TYPE_11N:
- if (ts->mcs > ATH12K_HT_MCS_MAX) {
- ath12k_warn(ab, "Invalid HT mcs index %d\n", ts->mcs);
- return;
- }
-
- if (txrate.nss != 0)
- txrate.mcs = ts->mcs + 8 * (txrate.nss - 1);
-
- txrate.flags = RATE_INFO_FLAGS_MCS;
-
- if (ts->sgi)
- txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
- break;
- case HAL_TX_RATE_STATS_PKT_TYPE_11AC:
- if (ts->mcs > ATH12K_VHT_MCS_MAX) {
- ath12k_warn(ab, "Invalid VHT mcs index %d\n", ts->mcs);
- return;
- }
-
- txrate.mcs = ts->mcs;
- txrate.flags = RATE_INFO_FLAGS_VHT_MCS;
-
- if (ts->sgi)
- txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
- break;
- case HAL_TX_RATE_STATS_PKT_TYPE_11AX:
- if (ts->mcs > ATH12K_HE_MCS_MAX) {
- ath12k_warn(ab, "Invalid HE mcs index %d\n", ts->mcs);
- return;
- }
-
- txrate.mcs = ts->mcs;
- txrate.flags = RATE_INFO_FLAGS_HE_MCS;
- txrate.he_gi = ath12k_he_gi_to_nl80211_he_gi(ts->sgi);
- break;
- case HAL_TX_RATE_STATS_PKT_TYPE_11BE:
- if (ts->mcs > ATH12K_EHT_MCS_MAX) {
- ath12k_warn(ab, "Invalid EHT mcs index %d\n", ts->mcs);
- return;
- }
-
- txrate.mcs = ts->mcs;
- txrate.flags = RATE_INFO_FLAGS_EHT_MCS;
- txrate.eht_gi = ath12k_mac_eht_gi_to_nl80211_eht_gi(ts->sgi);
- break;
- default:
- ath12k_warn(ab, "Invalid tx pkt type: %d\n", ts->pkt_type);
- return;
- }
-
- txrate.bw = ath12k_mac_bw_to_mac80211_bw(ts->bw);
-
- if (ts->ofdma && ts->pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11AX) {
- txrate.bw = RATE_INFO_BW_HE_RU;
- ru_tones = ath12k_mac_he_convert_tones_to_ru_tones(ts->tones);
- txrate.he_ru_alloc =
- ath12k_he_ru_tones_to_nl80211_he_ru_alloc(ru_tones);
- }
-
- if (ts->ofdma && ts->pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11BE) {
- txrate.bw = RATE_INFO_BW_EHT_RU;
- txrate.eht_ru_alloc =
- ath12k_mac_eht_ru_tones_to_nl80211_eht_ru_alloc(ts->tones);
- }
-
- spin_lock_bh(&ab->base_lock);
- arsta->txrate = txrate;
- spin_unlock_bh(&ab->base_lock);
-}
-
-static void ath12k_dp_tx_complete_msdu(struct ath12k *ar,
- struct ath12k_tx_desc_params *desc_params,
- struct hal_tx_status *ts,
- int ring)
-{
- struct ath12k_base *ab = ar->ab;
- struct ath12k_hw *ah = ar->ah;
- struct ieee80211_tx_info *info;
- struct ath12k_link_vif *arvif;
- struct ath12k_skb_cb *skb_cb;
- struct ieee80211_vif *vif;
- struct ath12k_vif *ahvif;
- struct sk_buff *msdu = desc_params->skb;
- s32 noise_floor;
- struct ieee80211_tx_status status = {};
- struct ieee80211_rate_status status_rate = {};
- struct ath12k_peer *peer;
- struct ath12k_link_sta *arsta;
- struct ath12k_sta *ahsta;
- struct rate_info rate;
-
- if (WARN_ON_ONCE(ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM)) {
- /* Must not happen */
- return;
- }
-
- skb_cb = ATH12K_SKB_CB(msdu);
- ab->device_stats.tx_completed[ring]++;
-
- dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
- if (skb_cb->paddr_ext_desc) {
- dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc,
- desc_params->skb_ext_desc->len, DMA_TO_DEVICE);
- dev_kfree_skb_any(desc_params->skb_ext_desc);
- }
-
- rcu_read_lock();
-
- if (!rcu_dereference(ab->pdevs_active[ar->pdev_idx])) {
- ieee80211_free_txskb(ah->hw, msdu);
- goto exit;
- }
-
- if (!skb_cb->vif) {
- ieee80211_free_txskb(ah->hw, msdu);
- goto exit;
- }
-
- vif = skb_cb->vif;
- if (vif) {
- ahvif = ath12k_vif_to_ahvif(vif);
- arvif = rcu_dereference(ahvif->link[skb_cb->link_id]);
- if (arvif) {
- spin_lock_bh(&arvif->link_stats_lock);
- arvif->link_stats.tx_completed++;
- spin_unlock_bh(&arvif->link_stats_lock);
- }
- }
-
- info = IEEE80211_SKB_CB(msdu);
- memset(&info->status, 0, sizeof(info->status));
-
- /* skip tx rate update from ieee80211_status*/
- info->status.rates[0].idx = -1;
-
- switch (ts->status) {
- case HAL_WBM_TQM_REL_REASON_FRAME_ACKED:
- if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
- info->flags |= IEEE80211_TX_STAT_ACK;
- info->status.ack_signal = ts->ack_rssi;
-
- if (!test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,
- ab->wmi_ab.svc_map)) {
- spin_lock_bh(&ar->data_lock);
- noise_floor = ath12k_pdev_get_noise_floor(ar);
- spin_unlock_bh(&ar->data_lock);
-
- info->status.ack_signal += noise_floor;
- }
-
- info->status.flags = IEEE80211_TX_STATUS_ACK_SIGNAL_VALID;
- }
- break;
- case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_TX:
- if (info->flags & IEEE80211_TX_CTL_NO_ACK) {
- info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
- break;
- }
- fallthrough;
- case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_MPDU:
- case HAL_WBM_TQM_REL_REASON_DROP_THRESHOLD:
- case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_AGED_FRAMES:
- /* The failure status is due to internal firmware tx failure
- * hence drop the frame; do not update the status of frame to
- * the upper layer
- */
- ieee80211_free_txskb(ah->hw, msdu);
- goto exit;
- default:
- ath12k_dbg(ab, ATH12K_DBG_DP_TX, "tx frame is not acked status %d\n",
- ts->status);
- break;
- }
-
- /* NOTE: Tx rate status reporting. Tx completion status does not have
- * necessary information (for example nss) to build the tx rate.
- * Might end up reporting it out-of-band from HTT stats.
- */
-
- ath12k_dp_tx_update_txcompl(ar, ts);
-
- spin_lock_bh(&ab->base_lock);
- peer = ath12k_peer_find_by_id(ab, ts->peer_id);
- if (!peer || !peer->sta) {
- ath12k_err(ab,
- "dp_tx: failed to find the peer with peer_id %d\n",
- ts->peer_id);
- spin_unlock_bh(&ab->base_lock);
- ieee80211_free_txskb(ath12k_ar_to_hw(ar), msdu);
- goto exit;
- }
- ahsta = ath12k_sta_to_ahsta(peer->sta);
- arsta = &ahsta->deflink;
-
- spin_unlock_bh(&ab->base_lock);
-
- status.sta = peer->sta;
- status.info = info;
- status.skb = msdu;
- rate = arsta->last_txrate;
-
- status_rate.rate_idx = rate;
- status_rate.try_count = 1;
-
- status.rates = &status_rate;
- status.n_rates = 1;
- ieee80211_tx_status_ext(ath12k_ar_to_hw(ar), &status);
-
-exit:
- rcu_read_unlock();
-}
-
-static void ath12k_dp_tx_status_parse(struct ath12k_base *ab,
- struct hal_wbm_completion_ring_tx *desc,
- struct hal_tx_status *ts)
-{
- u32 info0 = le32_to_cpu(desc->rate_stats.info0);
-
- ts->buf_rel_source =
- le32_get_bits(desc->info0, HAL_WBM_COMPL_TX_INFO0_REL_SRC_MODULE);
- if (ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_FW &&
- ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM)
- return;
-
- if (ts->buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW)
- return;
-
- ts->status = le32_get_bits(desc->info0,
- HAL_WBM_COMPL_TX_INFO0_TQM_RELEASE_REASON);
-
- ts->ppdu_id = le32_get_bits(desc->info1,
- HAL_WBM_COMPL_TX_INFO1_TQM_STATUS_NUMBER);
-
- ts->peer_id = le32_get_bits(desc->info3, HAL_WBM_COMPL_TX_INFO3_PEER_ID);
-
- ts->ack_rssi = le32_get_bits(desc->info2,
- HAL_WBM_COMPL_TX_INFO2_ACK_FRAME_RSSI);
-
- if (info0 & HAL_TX_RATE_STATS_INFO0_VALID) {
- ts->pkt_type = u32_get_bits(info0, HAL_TX_RATE_STATS_INFO0_PKT_TYPE);
- ts->mcs = u32_get_bits(info0, HAL_TX_RATE_STATS_INFO0_MCS);
- ts->sgi = u32_get_bits(info0, HAL_TX_RATE_STATS_INFO0_SGI);
- ts->bw = u32_get_bits(info0, HAL_TX_RATE_STATS_INFO0_BW);
- ts->tones = u32_get_bits(info0, HAL_TX_RATE_STATS_INFO0_TONES_IN_RU);
- ts->ofdma = u32_get_bits(info0, HAL_TX_RATE_STATS_INFO0_OFDMA_TX);
- }
-}
-
-void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id)
-{
- struct ath12k *ar;
- struct ath12k_dp *dp = &ab->dp;
- int hal_ring_id = dp->tx_ring[ring_id].tcl_comp_ring.ring_id;
- struct hal_srng *status_ring = &ab->hal.srng_list[hal_ring_id];
- struct ath12k_tx_desc_info *tx_desc = NULL;
- struct hal_tx_status ts = {};
- struct ath12k_tx_desc_params desc_params;
- struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id];
- struct hal_wbm_release_ring *desc;
- u8 pdev_id;
- u64 desc_va;
- enum hal_wbm_rel_src_module buf_rel_source;
- enum hal_wbm_tqm_rel_reason rel_status;
-
- spin_lock_bh(&status_ring->lock);
-
- ath12k_hal_srng_access_begin(ab, status_ring);
-
- while (ATH12K_TX_COMPL_NEXT(ab, tx_ring->tx_status_head) !=
- tx_ring->tx_status_tail) {
- desc = ath12k_hal_srng_dst_get_next_entry(ab, status_ring);
- if (!desc)
- break;
-
- memcpy(&tx_ring->tx_status[tx_ring->tx_status_head],
- desc, sizeof(*desc));
- tx_ring->tx_status_head =
- ATH12K_TX_COMPL_NEXT(ab, tx_ring->tx_status_head);
- }
-
- if (ath12k_hal_srng_dst_peek(ab, status_ring) &&
- (ATH12K_TX_COMPL_NEXT(ab, tx_ring->tx_status_head) ==
- tx_ring->tx_status_tail)) {
- /* TODO: Process pending tx_status messages when kfifo_is_full() */
- ath12k_warn(ab, "Unable to process some of the tx_status ring desc because status_fifo is full\n");
- }
-
- ath12k_hal_srng_access_end(ab, status_ring);
-
- spin_unlock_bh(&status_ring->lock);
-
- while (ATH12K_TX_COMPL_NEXT(ab, tx_ring->tx_status_tail) !=
- tx_ring->tx_status_head) {
- struct hal_wbm_completion_ring_tx *tx_status;
- u32 desc_id;
-
- tx_ring->tx_status_tail =
- ATH12K_TX_COMPL_NEXT(ab, tx_ring->tx_status_tail);
- tx_status = &tx_ring->tx_status[tx_ring->tx_status_tail];
- ath12k_dp_tx_status_parse(ab, tx_status, &ts);
-
- if (le32_get_bits(tx_status->info0, HAL_WBM_COMPL_TX_INFO0_CC_DONE)) {
- /* HW done cookie conversion */
- desc_va = ((u64)le32_to_cpu(tx_status->buf_va_hi) << 32 |
- le32_to_cpu(tx_status->buf_va_lo));
- tx_desc = (struct ath12k_tx_desc_info *)((unsigned long)desc_va);
- } else {
- /* SW does cookie conversion to VA */
- desc_id = le32_get_bits(tx_status->buf_va_hi,
- BUFFER_ADDR_INFO1_SW_COOKIE);
-
- tx_desc = ath12k_dp_get_tx_desc(ab, desc_id);
- }
- if (!tx_desc) {
- ath12k_warn(ab, "unable to retrieve tx_desc!");
- continue;
- }
-
- desc_params.mac_id = tx_desc->mac_id;
- desc_params.skb = tx_desc->skb;
- desc_params.skb_ext_desc = tx_desc->skb_ext_desc;
-
- /* Find the HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE value */
- buf_rel_source = le32_get_bits(tx_status->info0,
- HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE);
- ab->device_stats.tx_wbm_rel_source[buf_rel_source]++;
-
- rel_status = le32_get_bits(tx_status->info0,
- HAL_WBM_COMPL_TX_INFO0_TQM_RELEASE_REASON);
- ab->device_stats.tqm_rel_reason[rel_status]++;
-
- /* Release descriptor as soon as extracting necessary info
- * to reduce contention
- */
- ath12k_dp_tx_release_txbuf(dp, tx_desc, tx_desc->pool_id);
- if (ts.buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW) {
- ath12k_dp_tx_process_htt_tx_complete(ab, (void *)tx_status,
- tx_ring, &desc_params);
- continue;
- }
-
- pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, desc_params.mac_id);
- ar = ab->pdevs[pdev_id].ar;
-
- if (atomic_dec_and_test(&ar->dp.num_tx_pending))
- wake_up(&ar->dp.tx_empty_waitq);
-
- ath12k_dp_tx_complete_msdu(ar, &desc_params, &ts,
- tx_ring->tcl_data_ring_id);
- }
-}
-
-static int
-ath12k_dp_tx_get_ring_id_type(struct ath12k_base *ab,
- int mac_id, u32 ring_id,
- enum hal_ring_type ring_type,
- enum htt_srng_ring_type *htt_ring_type,
- enum htt_srng_ring_id *htt_ring_id)
-{
- int ret = 0;
-
- switch (ring_type) {
- case HAL_RXDMA_BUF:
- /* for some targets, host fills rx buffer to fw and fw fills to
- * rxbuf ring for each rxdma
- */
- if (!ab->hw_params->rx_mac_buf_ring) {
- if (!(ring_id == HAL_SRNG_SW2RXDMA_BUF0 ||
- ring_id == HAL_SRNG_SW2RXDMA_BUF1)) {
- ret = -EINVAL;
- }
- *htt_ring_id = HTT_RXDMA_HOST_BUF_RING;
- *htt_ring_type = HTT_SW_TO_HW_RING;
- } else {
- if (ring_id == HAL_SRNG_SW2RXDMA_BUF0) {
- *htt_ring_id = HTT_HOST1_TO_FW_RXBUF_RING;
- *htt_ring_type = HTT_SW_TO_SW_RING;
- } else {
- *htt_ring_id = HTT_RXDMA_HOST_BUF_RING;
- *htt_ring_type = HTT_SW_TO_HW_RING;
- }
- }
- break;
- case HAL_RXDMA_DST:
- *htt_ring_id = HTT_RXDMA_NON_MONITOR_DEST_RING;
- *htt_ring_type = HTT_HW_TO_SW_RING;
- break;
- case HAL_RXDMA_MONITOR_BUF:
- *htt_ring_id = HTT_RX_MON_HOST2MON_BUF_RING;
- *htt_ring_type = HTT_SW_TO_HW_RING;
- break;
- case HAL_RXDMA_MONITOR_STATUS:
- *htt_ring_id = HTT_RXDMA_MONITOR_STATUS_RING;
- *htt_ring_type = HTT_SW_TO_HW_RING;
- break;
- case HAL_RXDMA_MONITOR_DST:
- *htt_ring_id = HTT_RX_MON_MON2HOST_DEST_RING;
- *htt_ring_type = HTT_HW_TO_SW_RING;
- break;
- case HAL_RXDMA_MONITOR_DESC:
- *htt_ring_id = HTT_RXDMA_MONITOR_DESC_RING;
- *htt_ring_type = HTT_SW_TO_HW_RING;
- break;
- default:
- ath12k_warn(ab, "Unsupported ring type in DP :%d\n", ring_type);
- ret = -EINVAL;
- }
- return ret;
-}
-
-int ath12k_dp_tx_htt_srng_setup(struct ath12k_base *ab, u32 ring_id,
- int mac_id, enum hal_ring_type ring_type)
-{
- struct htt_srng_setup_cmd *cmd;
- struct hal_srng *srng = &ab->hal.srng_list[ring_id];
- struct hal_srng_params params;
- struct sk_buff *skb;
- u32 ring_entry_sz;
- int len = sizeof(*cmd);
- dma_addr_t hp_addr, tp_addr;
- enum htt_srng_ring_type htt_ring_type;
- enum htt_srng_ring_id htt_ring_id;
- int ret;
-
- skb = ath12k_htc_alloc_skb(ab, len);
- if (!skb)
- return -ENOMEM;
-
- memset(&params, 0, sizeof(params));
- ath12k_hal_srng_get_params(ab, srng, &params);
-
- hp_addr = ath12k_hal_srng_get_hp_addr(ab, srng);
- tp_addr = ath12k_hal_srng_get_tp_addr(ab, srng);
-
- ret = ath12k_dp_tx_get_ring_id_type(ab, mac_id, ring_id,
- ring_type, &htt_ring_type,
- &htt_ring_id);
- if (ret)
- goto err_free;
+ guard(rcu)();
- skb_put(skb, len);
- cmd = (struct htt_srng_setup_cmd *)skb->data;
- cmd->info0 = le32_encode_bits(HTT_H2T_MSG_TYPE_SRING_SETUP,
- HTT_SRNG_SETUP_CMD_INFO0_MSG_TYPE);
- if (htt_ring_type == HTT_SW_TO_HW_RING ||
- htt_ring_type == HTT_HW_TO_SW_RING)
- cmd->info0 |= le32_encode_bits(DP_SW2HW_MACID(mac_id),
- HTT_SRNG_SETUP_CMD_INFO0_PDEV_ID);
- else
- cmd->info0 |= le32_encode_bits(mac_id,
- HTT_SRNG_SETUP_CMD_INFO0_PDEV_ID);
- cmd->info0 |= le32_encode_bits(htt_ring_type,
- HTT_SRNG_SETUP_CMD_INFO0_RING_TYPE);
- cmd->info0 |= le32_encode_bits(htt_ring_id,
- HTT_SRNG_SETUP_CMD_INFO0_RING_ID);
-
- cmd->ring_base_addr_lo = cpu_to_le32(params.ring_base_paddr &
- HAL_ADDR_LSB_REG_MASK);
-
- cmd->ring_base_addr_hi = cpu_to_le32((u64)params.ring_base_paddr >>
- HAL_ADDR_MSB_REG_SHIFT);
-
- ret = ath12k_hal_srng_get_entrysize(ab, ring_type);
- if (ret < 0)
- goto err_free;
-
- ring_entry_sz = ret;
-
- ring_entry_sz >>= 2;
- cmd->info1 = le32_encode_bits(ring_entry_sz,
- HTT_SRNG_SETUP_CMD_INFO1_RING_ENTRY_SIZE);
- cmd->info1 |= le32_encode_bits(params.num_entries * ring_entry_sz,
- HTT_SRNG_SETUP_CMD_INFO1_RING_SIZE);
- cmd->info1 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_MSI_SWAP),
- HTT_SRNG_SETUP_CMD_INFO1_RING_FLAGS_MSI_SWAP);
- cmd->info1 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP),
- HTT_SRNG_SETUP_CMD_INFO1_RING_FLAGS_TLV_SWAP);
- cmd->info1 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_RING_PTR_SWAP),
- HTT_SRNG_SETUP_CMD_INFO1_RING_FLAGS_HOST_FW_SWAP);
- if (htt_ring_type == HTT_SW_TO_HW_RING)
- cmd->info1 |= cpu_to_le32(HTT_SRNG_SETUP_CMD_INFO1_RING_LOOP_CNT_DIS);
-
- cmd->ring_head_off32_remote_addr_lo = cpu_to_le32(lower_32_bits(hp_addr));
- cmd->ring_head_off32_remote_addr_hi = cpu_to_le32(upper_32_bits(hp_addr));
-
- cmd->ring_tail_off32_remote_addr_lo = cpu_to_le32(lower_32_bits(tp_addr));
- cmd->ring_tail_off32_remote_addr_hi = cpu_to_le32(upper_32_bits(tp_addr));
-
- cmd->ring_msi_addr_lo = cpu_to_le32(lower_32_bits(params.msi_addr));
- cmd->ring_msi_addr_hi = cpu_to_le32(upper_32_bits(params.msi_addr));
- cmd->msi_data = cpu_to_le32(params.msi_data);
-
- cmd->intr_info =
- le32_encode_bits(params.intr_batch_cntr_thres_entries * ring_entry_sz,
- HTT_SRNG_SETUP_CMD_INTR_INFO_BATCH_COUNTER_THRESH);
- cmd->intr_info |=
- le32_encode_bits(params.intr_timer_thres_us >> 3,
- HTT_SRNG_SETUP_CMD_INTR_INFO_INTR_TIMER_THRESH);
-
- cmd->info2 = 0;
- if (params.flags & HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN) {
- cmd->info2 = le32_encode_bits(params.low_threshold,
- HTT_SRNG_SETUP_CMD_INFO2_INTR_LOW_THRESH);
- }
+ dp_pdev = ath12k_dp_to_pdev_dp(dp, pdev_idx);
- ath12k_dbg(ab, ATH12K_DBG_HAL,
- "%s msi_addr_lo:0x%x, msi_addr_hi:0x%x, msi_data:0x%x\n",
- __func__, cmd->ring_msi_addr_lo, cmd->ring_msi_addr_hi,
- cmd->msi_data);
+ ieee80211_free_txskb(ath12k_pdev_dp_to_hw(dp_pdev), msdu);
- ath12k_dbg(ab, ATH12K_DBG_HAL,
- "ring_id:%d, ring_type:%d, intr_info:0x%x, flags:0x%x\n",
- ring_id, ring_type, cmd->intr_info, cmd->info2);
-
- ret = ath12k_htc_send(&ab->htc, ab->dp.eid, skb);
- if (ret)
- goto err_free;
-
- return 0;
-
-err_free:
- dev_kfree_skb_any(skb);
-
- return ret;
-}
-
-#define HTT_TARGET_VERSION_TIMEOUT_HZ (3 * HZ)
-
-int ath12k_dp_tx_htt_h2t_ver_req_msg(struct ath12k_base *ab)
-{
- struct ath12k_dp *dp = &ab->dp;
- struct sk_buff *skb;
- struct htt_ver_req_cmd *cmd;
- int len = sizeof(*cmd);
- u32 metadata_version;
- int ret;
-
- init_completion(&dp->htt_tgt_version_received);
-
- skb = ath12k_htc_alloc_skb(ab, len);
- if (!skb)
- return -ENOMEM;
-
- skb_put(skb, len);
- cmd = (struct htt_ver_req_cmd *)skb->data;
- cmd->ver_reg_info = le32_encode_bits(HTT_H2T_MSG_TYPE_VERSION_REQ,
- HTT_OPTION_TAG);
- metadata_version = ath12k_ftm_mode ? HTT_OPTION_TCL_METADATA_VER_V1 :
- HTT_OPTION_TCL_METADATA_VER_V2;
-
- cmd->tcl_metadata_version = le32_encode_bits(HTT_TAG_TCL_METADATA_VERSION,
- HTT_OPTION_TAG) |
- le32_encode_bits(HTT_TCL_METADATA_VER_SZ,
- HTT_OPTION_LEN) |
- le32_encode_bits(metadata_version,
- HTT_OPTION_VALUE);
-
- ret = ath12k_htc_send(&ab->htc, dp->eid, skb);
- if (ret) {
- dev_kfree_skb_any(skb);
- return ret;
- }
-
- ret = wait_for_completion_timeout(&dp->htt_tgt_version_received,
- HTT_TARGET_VERSION_TIMEOUT_HZ);
- if (ret == 0) {
- ath12k_warn(ab, "htt target version request timed out\n");
- return -ETIMEDOUT;
- }
-
- if (dp->htt_tgt_ver_major != HTT_TARGET_VERSION_MAJOR) {
- ath12k_err(ab, "unsupported htt major version %d supported version is %d\n",
- dp->htt_tgt_ver_major, HTT_TARGET_VERSION_MAJOR);
- return -EOPNOTSUPP;
- }
-
- return 0;
-}
-
-int ath12k_dp_tx_htt_h2t_ppdu_stats_req(struct ath12k *ar, u32 mask)
-{
- struct ath12k_base *ab = ar->ab;
- struct ath12k_dp *dp = &ab->dp;
- struct sk_buff *skb;
- struct htt_ppdu_stats_cfg_cmd *cmd;
- int len = sizeof(*cmd);
- u8 pdev_mask;
- int ret;
- int i;
-
- for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {
- skb = ath12k_htc_alloc_skb(ab, len);
- if (!skb)
- return -ENOMEM;
-
- skb_put(skb, len);
- cmd = (struct htt_ppdu_stats_cfg_cmd *)skb->data;
- cmd->msg = le32_encode_bits(HTT_H2T_MSG_TYPE_PPDU_STATS_CFG,
- HTT_PPDU_STATS_CFG_MSG_TYPE);
-
- pdev_mask = 1 << (i + ar->pdev_idx);
- cmd->msg |= le32_encode_bits(pdev_mask, HTT_PPDU_STATS_CFG_PDEV_ID);
- cmd->msg |= le32_encode_bits(mask, HTT_PPDU_STATS_CFG_TLV_TYPE_BITMASK);
-
- ret = ath12k_htc_send(&ab->htc, dp->eid, skb);
- if (ret) {
- dev_kfree_skb_any(skb);
- return ret;
- }
- }
-
- return 0;
-}
-
-int ath12k_dp_tx_htt_rx_filter_setup(struct ath12k_base *ab, u32 ring_id,
- int mac_id, enum hal_ring_type ring_type,
- int rx_buf_size,
- struct htt_rx_ring_tlv_filter *tlv_filter)
-{
- struct htt_rx_ring_selection_cfg_cmd *cmd;
- struct hal_srng *srng = &ab->hal.srng_list[ring_id];
- struct hal_srng_params params;
- struct sk_buff *skb;
- int len = sizeof(*cmd);
- enum htt_srng_ring_type htt_ring_type;
- enum htt_srng_ring_id htt_ring_id;
- int ret;
-
- skb = ath12k_htc_alloc_skb(ab, len);
- if (!skb)
- return -ENOMEM;
-
- memset(&params, 0, sizeof(params));
- ath12k_hal_srng_get_params(ab, srng, &params);
-
- ret = ath12k_dp_tx_get_ring_id_type(ab, mac_id, ring_id,
- ring_type, &htt_ring_type,
- &htt_ring_id);
- if (ret)
- goto err_free;
-
- skb_put(skb, len);
- cmd = (struct htt_rx_ring_selection_cfg_cmd *)skb->data;
- cmd->info0 = le32_encode_bits(HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG,
- HTT_RX_RING_SELECTION_CFG_CMD_INFO0_MSG_TYPE);
- if (htt_ring_type == HTT_SW_TO_HW_RING ||
- htt_ring_type == HTT_HW_TO_SW_RING)
- cmd->info0 |=
- le32_encode_bits(DP_SW2HW_MACID(mac_id),
- HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID);
- else
- cmd->info0 |=
- le32_encode_bits(mac_id,
- HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID);
- cmd->info0 |= le32_encode_bits(htt_ring_id,
- HTT_RX_RING_SELECTION_CFG_CMD_INFO0_RING_ID);
- cmd->info0 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_MSI_SWAP),
- HTT_RX_RING_SELECTION_CFG_CMD_INFO0_SS);
- cmd->info0 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP),
- HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PS);
- cmd->info0 |= le32_encode_bits(tlv_filter->offset_valid,
- HTT_RX_RING_SELECTION_CFG_CMD_INFO0_OFFSET_VALID);
- cmd->info0 |=
- le32_encode_bits(tlv_filter->drop_threshold_valid,
- HTT_RX_RING_SELECTION_CFG_CMD_INFO0_DROP_THRES_VAL);
- cmd->info0 |= le32_encode_bits(!tlv_filter->rxmon_disable,
- HTT_RX_RING_SELECTION_CFG_CMD_INFO0_EN_RXMON);
-
- cmd->info1 = le32_encode_bits(rx_buf_size,
- HTT_RX_RING_SELECTION_CFG_CMD_INFO1_BUF_SIZE);
- cmd->info1 |= le32_encode_bits(tlv_filter->conf_len_mgmt,
- HTT_RX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_MGMT);
- cmd->info1 |= le32_encode_bits(tlv_filter->conf_len_ctrl,
- HTT_RX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_CTRL);
- cmd->info1 |= le32_encode_bits(tlv_filter->conf_len_data,
- HTT_RX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_DATA);
- cmd->pkt_type_en_flags0 = cpu_to_le32(tlv_filter->pkt_filter_flags0);
- cmd->pkt_type_en_flags1 = cpu_to_le32(tlv_filter->pkt_filter_flags1);
- cmd->pkt_type_en_flags2 = cpu_to_le32(tlv_filter->pkt_filter_flags2);
- cmd->pkt_type_en_flags3 = cpu_to_le32(tlv_filter->pkt_filter_flags3);
- cmd->rx_filter_tlv = cpu_to_le32(tlv_filter->rx_filter);
-
- cmd->info2 = le32_encode_bits(tlv_filter->rx_drop_threshold,
- HTT_RX_RING_SELECTION_CFG_CMD_INFO2_DROP_THRESHOLD);
- cmd->info2 |=
- le32_encode_bits(tlv_filter->enable_log_mgmt_type,
- HTT_RX_RING_SELECTION_CFG_CMD_INFO2_EN_LOG_MGMT_TYPE);
- cmd->info2 |=
- le32_encode_bits(tlv_filter->enable_log_ctrl_type,
- HTT_RX_RING_SELECTION_CFG_CMD_INFO2_EN_CTRL_TYPE);
- cmd->info2 |=
- le32_encode_bits(tlv_filter->enable_log_data_type,
- HTT_RX_RING_SELECTION_CFG_CMD_INFO2_EN_LOG_DATA_TYPE);
-
- cmd->info3 =
- le32_encode_bits(tlv_filter->enable_rx_tlv_offset,
- HTT_RX_RING_SELECTION_CFG_CMD_INFO3_EN_TLV_PKT_OFFSET);
- cmd->info3 |=
- le32_encode_bits(tlv_filter->rx_tlv_offset,
- HTT_RX_RING_SELECTION_CFG_CMD_INFO3_PKT_TLV_OFFSET);
-
- if (tlv_filter->offset_valid) {
- cmd->rx_packet_offset =
- le32_encode_bits(tlv_filter->rx_packet_offset,
- HTT_RX_RING_SELECTION_CFG_RX_PACKET_OFFSET);
-
- cmd->rx_packet_offset |=
- le32_encode_bits(tlv_filter->rx_header_offset,
- HTT_RX_RING_SELECTION_CFG_RX_HEADER_OFFSET);
-
- cmd->rx_mpdu_offset =
- le32_encode_bits(tlv_filter->rx_mpdu_end_offset,
- HTT_RX_RING_SELECTION_CFG_RX_MPDU_END_OFFSET);
-
- cmd->rx_mpdu_offset |=
- le32_encode_bits(tlv_filter->rx_mpdu_start_offset,
- HTT_RX_RING_SELECTION_CFG_RX_MPDU_START_OFFSET);
-
- cmd->rx_msdu_offset =
- le32_encode_bits(tlv_filter->rx_msdu_end_offset,
- HTT_RX_RING_SELECTION_CFG_RX_MSDU_END_OFFSET);
-
- cmd->rx_msdu_offset |=
- le32_encode_bits(tlv_filter->rx_msdu_start_offset,
- HTT_RX_RING_SELECTION_CFG_RX_MSDU_START_OFFSET);
-
- cmd->rx_attn_offset =
- le32_encode_bits(tlv_filter->rx_attn_offset,
- HTT_RX_RING_SELECTION_CFG_RX_ATTENTION_OFFSET);
- }
-
- if (tlv_filter->rx_mpdu_start_wmask > 0 &&
- tlv_filter->rx_msdu_end_wmask > 0) {
- cmd->info2 |=
- le32_encode_bits(true,
- HTT_RX_RING_SELECTION_CFG_WORD_MASK_COMPACT_SET);
- cmd->rx_mpdu_start_end_mask =
- le32_encode_bits(tlv_filter->rx_mpdu_start_wmask,
- HTT_RX_RING_SELECTION_CFG_RX_MPDU_START_MASK);
- /* mpdu_end is not used for any hardwares so far
- * please assign it in future if any chip is
- * using through hal ops
- */
- cmd->rx_mpdu_start_end_mask |=
- le32_encode_bits(tlv_filter->rx_mpdu_end_wmask,
- HTT_RX_RING_SELECTION_CFG_RX_MPDU_END_MASK);
- cmd->rx_msdu_end_word_mask =
- le32_encode_bits(tlv_filter->rx_msdu_end_wmask,
- HTT_RX_RING_SELECTION_CFG_RX_MSDU_END_MASK);
- }
-
- ret = ath12k_htc_send(&ab->htc, ab->dp.eid, skb);
- if (ret)
- goto err_free;
-
- return 0;
-
-err_free:
- dev_kfree_skb_any(skb);
-
- return ret;
-}
-
-int
-ath12k_dp_tx_htt_h2t_ext_stats_req(struct ath12k *ar, u8 type,
- struct htt_ext_stats_cfg_params *cfg_params,
- u64 cookie)
-{
- struct ath12k_base *ab = ar->ab;
- struct ath12k_dp *dp = &ab->dp;
- struct sk_buff *skb;
- struct htt_ext_stats_cfg_cmd *cmd;
- int len = sizeof(*cmd);
- int ret;
- u32 pdev_id;
-
- skb = ath12k_htc_alloc_skb(ab, len);
- if (!skb)
- return -ENOMEM;
-
- skb_put(skb, len);
-
- cmd = (struct htt_ext_stats_cfg_cmd *)skb->data;
- memset(cmd, 0, sizeof(*cmd));
- cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_EXT_STATS_CFG;
-
- pdev_id = ath12k_mac_get_target_pdev_id(ar);
- cmd->hdr.pdev_mask = 1 << pdev_id;
-
- cmd->hdr.stats_type = type;
- cmd->cfg_param0 = cpu_to_le32(cfg_params->cfg0);
- cmd->cfg_param1 = cpu_to_le32(cfg_params->cfg1);
- cmd->cfg_param2 = cpu_to_le32(cfg_params->cfg2);
- cmd->cfg_param3 = cpu_to_le32(cfg_params->cfg3);
- cmd->cookie_lsb = cpu_to_le32(lower_32_bits(cookie));
- cmd->cookie_msb = cpu_to_le32(upper_32_bits(cookie));
-
- ret = ath12k_htc_send(&ab->htc, dp->eid, skb);
- if (ret) {
- ath12k_warn(ab, "failed to send htt type stats request: %d",
- ret);
- dev_kfree_skb_any(skb);
- return ret;
- }
-
- return 0;
-}
-
-int ath12k_dp_tx_htt_monitor_mode_ring_config(struct ath12k *ar, bool reset)
-{
- struct ath12k_base *ab = ar->ab;
- int ret;
-
- ret = ath12k_dp_tx_htt_rx_monitor_mode_ring_config(ar, reset);
- if (ret) {
- ath12k_err(ab, "failed to setup rx monitor filter %d\n", ret);
- return ret;
- }
-
- return 0;
-}
-
-int ath12k_dp_tx_htt_rx_monitor_mode_ring_config(struct ath12k *ar, bool reset)
-{
- struct ath12k_base *ab = ar->ab;
- struct htt_rx_ring_tlv_filter tlv_filter = {};
- int ret, ring_id, i;
-
- tlv_filter.offset_valid = false;
-
- if (!reset) {
- tlv_filter.rx_filter = HTT_RX_MON_FILTER_TLV_FLAGS_MON_DEST_RING;
-
- tlv_filter.drop_threshold_valid = true;
- tlv_filter.rx_drop_threshold = HTT_RX_RING_TLV_DROP_THRESHOLD_VALUE;
-
- tlv_filter.enable_log_mgmt_type = true;
- tlv_filter.enable_log_ctrl_type = true;
- tlv_filter.enable_log_data_type = true;
-
- tlv_filter.conf_len_ctrl = HTT_RX_RING_DEFAULT_DMA_LENGTH;
- tlv_filter.conf_len_mgmt = HTT_RX_RING_DEFAULT_DMA_LENGTH;
- tlv_filter.conf_len_data = HTT_RX_RING_DEFAULT_DMA_LENGTH;
-
- tlv_filter.enable_rx_tlv_offset = true;
- tlv_filter.rx_tlv_offset = HTT_RX_RING_PKT_TLV_OFFSET;
-
- tlv_filter.pkt_filter_flags0 =
- HTT_RX_MON_FP_MGMT_FILTER_FLAGS0 |
- HTT_RX_MON_MO_MGMT_FILTER_FLAGS0;
- tlv_filter.pkt_filter_flags1 =
- HTT_RX_MON_FP_MGMT_FILTER_FLAGS1 |
- HTT_RX_MON_MO_MGMT_FILTER_FLAGS1;
- tlv_filter.pkt_filter_flags2 =
- HTT_RX_MON_FP_CTRL_FILTER_FLASG2 |
- HTT_RX_MON_MO_CTRL_FILTER_FLASG2;
- tlv_filter.pkt_filter_flags3 =
- HTT_RX_MON_FP_CTRL_FILTER_FLASG3 |
- HTT_RX_MON_MO_CTRL_FILTER_FLASG3 |
- HTT_RX_MON_FP_DATA_FILTER_FLASG3 |
- HTT_RX_MON_MO_DATA_FILTER_FLASG3;
- } else {
- tlv_filter = ath12k_mac_mon_status_filter_default;
-
- if (ath12k_debugfs_is_extd_rx_stats_enabled(ar))
- tlv_filter.rx_filter = ath12k_debugfs_rx_filter(ar);
- }
-
- if (ab->hw_params->rxdma1_enable) {
- for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {
- ring_id = ar->dp.rxdma_mon_dst_ring[i].ring_id;
- ret = ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id,
- ar->dp.mac_id + i,
- HAL_RXDMA_MONITOR_DST,
- DP_RXDMA_REFILL_RING_SIZE,
- &tlv_filter);
- if (ret) {
- ath12k_err(ab,
- "failed to setup filter for monitor buf %d\n",
- ret);
- return ret;
- }
- }
- return 0;
- }
-
- if (!reset) {
- for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {
- ring_id = ab->dp.rx_mac_buf_ring[i].ring_id;
- ret = ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id,
- i,
- HAL_RXDMA_BUF,
- DP_RXDMA_REFILL_RING_SIZE,
- &tlv_filter);
- if (ret) {
- ath12k_err(ab,
- "failed to setup filter for mon rx buf %d\n",
- ret);
- return ret;
- }
- }
- }
-
- for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {
- ring_id = ab->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
- if (!reset) {
- tlv_filter.rx_filter =
- HTT_RX_MON_FILTER_TLV_FLAGS_MON_STATUS_RING;
- }
-
- ret = ath12k_dp_tx_htt_rx_filter_setup(ab, ring_id,
- i,
- HAL_RXDMA_MONITOR_STATUS,
- RX_MON_STATUS_BUF_SIZE,
- &tlv_filter);
- if (ret) {
- ath12k_err(ab,
- "failed to setup filter for mon status buf %d\n",
- ret);
- return ret;
- }
- }
-
- return 0;
-}
-
-int ath12k_dp_tx_htt_tx_filter_setup(struct ath12k_base *ab, u32 ring_id,
- int mac_id, enum hal_ring_type ring_type,
- int tx_buf_size,
- struct htt_tx_ring_tlv_filter *htt_tlv_filter)
-{
- struct htt_tx_ring_selection_cfg_cmd *cmd;
- struct hal_srng *srng = &ab->hal.srng_list[ring_id];
- struct hal_srng_params params;
- struct sk_buff *skb;
- int len = sizeof(*cmd);
- enum htt_srng_ring_type htt_ring_type;
- enum htt_srng_ring_id htt_ring_id;
- int ret;
-
- skb = ath12k_htc_alloc_skb(ab, len);
- if (!skb)
- return -ENOMEM;
-
- memset(&params, 0, sizeof(params));
- ath12k_hal_srng_get_params(ab, srng, &params);
-
- ret = ath12k_dp_tx_get_ring_id_type(ab, mac_id, ring_id,
- ring_type, &htt_ring_type,
- &htt_ring_id);
-
- if (ret)
- goto err_free;
-
- skb_put(skb, len);
- cmd = (struct htt_tx_ring_selection_cfg_cmd *)skb->data;
- cmd->info0 = le32_encode_bits(HTT_H2T_MSG_TYPE_TX_MONITOR_CFG,
- HTT_TX_RING_SELECTION_CFG_CMD_INFO0_MSG_TYPE);
- if (htt_ring_type == HTT_SW_TO_HW_RING ||
- htt_ring_type == HTT_HW_TO_SW_RING)
- cmd->info0 |=
- le32_encode_bits(DP_SW2HW_MACID(mac_id),
- HTT_TX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID);
- else
- cmd->info0 |=
- le32_encode_bits(mac_id,
- HTT_TX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID);
- cmd->info0 |= le32_encode_bits(htt_ring_id,
- HTT_TX_RING_SELECTION_CFG_CMD_INFO0_RING_ID);
- cmd->info0 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_MSI_SWAP),
- HTT_TX_RING_SELECTION_CFG_CMD_INFO0_SS);
- cmd->info0 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP),
- HTT_TX_RING_SELECTION_CFG_CMD_INFO0_PS);
-
- cmd->info1 |=
- le32_encode_bits(tx_buf_size,
- HTT_TX_RING_SELECTION_CFG_CMD_INFO1_RING_BUFF_SIZE);
-
- if (htt_tlv_filter->tx_mon_mgmt_filter) {
- cmd->info1 |=
- le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_MGMT,
- HTT_TX_RING_SELECTION_CFG_CMD_INFO1_PKT_TYPE);
- cmd->info1 |=
- le32_encode_bits(htt_tlv_filter->tx_mon_pkt_dma_len,
- HTT_TX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_MGMT);
- cmd->info2 |=
- le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_MGMT,
- HTT_TX_RING_SELECTION_CFG_CMD_INFO2_PKT_TYPE_EN_FLAG);
- }
-
- if (htt_tlv_filter->tx_mon_data_filter) {
- cmd->info1 |=
- le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_CTRL,
- HTT_TX_RING_SELECTION_CFG_CMD_INFO1_PKT_TYPE);
- cmd->info1 |=
- le32_encode_bits(htt_tlv_filter->tx_mon_pkt_dma_len,
- HTT_TX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_CTRL);
- cmd->info2 |=
- le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_CTRL,
- HTT_TX_RING_SELECTION_CFG_CMD_INFO2_PKT_TYPE_EN_FLAG);
- }
-
- if (htt_tlv_filter->tx_mon_ctrl_filter) {
- cmd->info1 |=
- le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_DATA,
- HTT_TX_RING_SELECTION_CFG_CMD_INFO1_PKT_TYPE);
- cmd->info1 |=
- le32_encode_bits(htt_tlv_filter->tx_mon_pkt_dma_len,
- HTT_TX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_DATA);
- cmd->info2 |=
- le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_DATA,
- HTT_TX_RING_SELECTION_CFG_CMD_INFO2_PKT_TYPE_EN_FLAG);
- }
-
- cmd->tlv_filter_mask_in0 =
- cpu_to_le32(htt_tlv_filter->tx_mon_downstream_tlv_flags);
- cmd->tlv_filter_mask_in1 =
- cpu_to_le32(htt_tlv_filter->tx_mon_upstream_tlv_flags0);
- cmd->tlv_filter_mask_in2 =
- cpu_to_le32(htt_tlv_filter->tx_mon_upstream_tlv_flags1);
- cmd->tlv_filter_mask_in3 =
- cpu_to_le32(htt_tlv_filter->tx_mon_upstream_tlv_flags2);
-
- ret = ath12k_htc_send(&ab->htc, ab->dp.eid, skb);
- if (ret)
- goto err_free;
-
- return 0;
-
-err_free:
- dev_kfree_skb_any(skb);
- return ret;
+ if (atomic_dec_and_test(&dp_pdev->num_tx_pending))
+ wake_up(&dp_pdev->tx_empty_waitq);
}
+EXPORT_SYMBOL(ath12k_dp_tx_free_txbuf);
diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.h b/drivers/net/wireless/ath/ath12k/dp_tx.h
index 10acdcf1fa8f..7cef20540179 100644
--- a/drivers/net/wireless/ath/ath12k/dp_tx.h
+++ b/drivers/net/wireless/ath/ath12k/dp_tx.h
@@ -1,41 +1,32 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022, 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH12K_DP_TX_H
#define ATH12K_DP_TX_H
#include "core.h"
-#include "hal_tx.h"
struct ath12k_dp_htt_wbm_tx_status {
bool acked;
s8 ack_rssi;
};
-int ath12k_dp_tx_htt_h2t_ver_req_msg(struct ath12k_base *ab);
-int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
- struct sk_buff *skb, bool gsn_valid, int mcbc_gsn,
- bool is_mcast);
-void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id);
-
-int ath12k_dp_tx_htt_h2t_ppdu_stats_req(struct ath12k *ar, u32 mask);
-int
-ath12k_dp_tx_htt_h2t_ext_stats_req(struct ath12k *ar, u8 type,
- struct htt_ext_stats_cfg_params *cfg_params,
- u64 cookie);
-int ath12k_dp_tx_htt_rx_monitor_mode_ring_config(struct ath12k *ar, bool reset);
-
-int ath12k_dp_tx_htt_rx_filter_setup(struct ath12k_base *ab, u32 ring_id,
- int mac_id, enum hal_ring_type ring_type,
- int rx_buf_size,
- struct htt_rx_ring_tlv_filter *tlv_filter);
void ath12k_dp_tx_put_bank_profile(struct ath12k_dp *dp, u8 bank_id);
-int ath12k_dp_tx_htt_tx_filter_setup(struct ath12k_base *ab, u32 ring_id,
- int mac_id, enum hal_ring_type ring_type,
- int tx_buf_size,
- struct htt_tx_ring_tlv_filter *htt_tlv_filter);
-int ath12k_dp_tx_htt_monitor_mode_ring_config(struct ath12k *ar, bool reset);
+enum hal_tcl_encap_type
+ath12k_dp_tx_get_encap_type(struct ath12k_base *ab, struct sk_buff *skb);
+void ath12k_dp_tx_encap_nwifi(struct sk_buff *skb);
+u8 ath12k_dp_tx_get_tid(struct sk_buff *skb);
+void *ath12k_dp_metadata_align_skb(struct sk_buff *skb, u8 tail_len);
+int ath12k_dp_tx_align_payload(struct ath12k_dp *dp, struct sk_buff **pskb);
+void ath12k_dp_tx_release_txbuf(struct ath12k_dp *dp,
+ struct ath12k_tx_desc_info *tx_desc,
+ u8 pool_id);
+struct ath12k_tx_desc_info *ath12k_dp_tx_assign_buffer(struct ath12k_dp *dp,
+ u8 pool_id);
+void ath12k_dp_tx_free_txbuf(struct ath12k_dp *dp,
+ struct dp_tx_ring *tx_ring,
+ struct ath12k_tx_desc_params *desc_params);
#endif
diff --git a/drivers/net/wireless/ath/ath12k/fw.c b/drivers/net/wireless/ath/ath12k/fw.c
index 5ac497f80cad..22074653cbb8 100644
--- a/drivers/net/wireless/ath/ath12k/fw.c
+++ b/drivers/net/wireless/ath/ath12k/fw.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
- * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include "core.h"
@@ -121,6 +121,14 @@ static int ath12k_fw_request_firmware_api_n(struct ath12k_base *ab,
ab->fw.m3_data = data;
ab->fw.m3_len = ie_len;
break;
+ case ATH12K_FW_IE_AUX_UC_IMAGE:
+ ath12k_dbg(ab, ATH12K_DBG_BOOT,
+ "found aux_uc image ie (%zd B)\n",
+ ie_len);
+
+ ab->fw.aux_uc_data = data;
+ ab->fw.aux_uc_len = ie_len;
+ break;
case ATH12K_FW_IE_AMSS_DUALMAC_IMAGE:
ath12k_dbg(ab, ATH12K_DBG_BOOT,
"found dualmac fw image ie (%zd B)\n",
diff --git a/drivers/net/wireless/ath/ath12k/fw.h b/drivers/net/wireless/ath/ath12k/fw.h
index 7afaefed5086..e146d24dfea4 100644
--- a/drivers/net/wireless/ath/ath12k/fw.h
+++ b/drivers/net/wireless/ath/ath12k/fw.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
- * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH12K_FW_H
@@ -15,6 +15,7 @@ enum ath12k_fw_ie_type {
ATH12K_FW_IE_AMSS_IMAGE = 2,
ATH12K_FW_IE_M3_IMAGE = 3,
ATH12K_FW_IE_AMSS_DUALMAC_IMAGE = 4,
+ ATH12K_FW_IE_AUX_UC_IMAGE = 5,
};
enum ath12k_fw_features {
diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c
index 6406fcf5d69f..a164563fff28 100644
--- a/drivers/net/wireless/ath/ath12k/hal.c
+++ b/drivers/net/wireless/ath/ath12k/hal.c
@@ -1,1573 +1,162 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/dma-mapping.h>
-#include "hal_tx.h"
-#include "hal_rx.h"
#include "debug.h"
-#include "hal_desc.h"
#include "hif.h"
-static const struct hal_srng_config hw_srng_config_template[] = {
- /* TODO: max_rings can populated by querying HW capabilities */
- [HAL_REO_DST] = {
- .start_ring_id = HAL_SRNG_RING_ID_REO2SW1,
- .max_rings = 8,
- .entry_size = sizeof(struct hal_reo_dest_ring) >> 2,
- .mac_type = ATH12K_HAL_SRNG_UMAC,
- .ring_dir = HAL_SRNG_DIR_DST,
- .max_size = HAL_REO_REO2SW1_RING_BASE_MSB_RING_SIZE,
- },
- [HAL_REO_EXCEPTION] = {
- /* Designating REO2SW0 ring as exception ring.
- * Any of theREO2SW rings can be used as exception ring.
- */
- .start_ring_id = HAL_SRNG_RING_ID_REO2SW0,
- .max_rings = 1,
- .entry_size = sizeof(struct hal_reo_dest_ring) >> 2,
- .mac_type = ATH12K_HAL_SRNG_UMAC,
- .ring_dir = HAL_SRNG_DIR_DST,
- .max_size = HAL_REO_REO2SW0_RING_BASE_MSB_RING_SIZE,
- },
- [HAL_REO_REINJECT] = {
- .start_ring_id = HAL_SRNG_RING_ID_SW2REO,
- .max_rings = 4,
- .entry_size = sizeof(struct hal_reo_entrance_ring) >> 2,
- .mac_type = ATH12K_HAL_SRNG_UMAC,
- .ring_dir = HAL_SRNG_DIR_SRC,
- .max_size = HAL_REO_SW2REO_RING_BASE_MSB_RING_SIZE,
- },
- [HAL_REO_CMD] = {
- .start_ring_id = HAL_SRNG_RING_ID_REO_CMD,
- .max_rings = 1,
- .entry_size = (sizeof(struct hal_tlv_64_hdr) +
- sizeof(struct hal_reo_get_queue_stats)) >> 2,
- .mac_type = ATH12K_HAL_SRNG_UMAC,
- .ring_dir = HAL_SRNG_DIR_SRC,
- .max_size = HAL_REO_CMD_RING_BASE_MSB_RING_SIZE,
- },
- [HAL_REO_STATUS] = {
- .start_ring_id = HAL_SRNG_RING_ID_REO_STATUS,
- .max_rings = 1,
- .entry_size = (sizeof(struct hal_tlv_64_hdr) +
- sizeof(struct hal_reo_get_queue_stats_status)) >> 2,
- .mac_type = ATH12K_HAL_SRNG_UMAC,
- .ring_dir = HAL_SRNG_DIR_DST,
- .max_size = HAL_REO_STATUS_RING_BASE_MSB_RING_SIZE,
- },
- [HAL_TCL_DATA] = {
- .start_ring_id = HAL_SRNG_RING_ID_SW2TCL1,
- .max_rings = 6,
- .entry_size = sizeof(struct hal_tcl_data_cmd) >> 2,
- .mac_type = ATH12K_HAL_SRNG_UMAC,
- .ring_dir = HAL_SRNG_DIR_SRC,
- .max_size = HAL_SW2TCL1_RING_BASE_MSB_RING_SIZE,
- },
- [HAL_TCL_CMD] = {
- .start_ring_id = HAL_SRNG_RING_ID_SW2TCL_CMD,
- .max_rings = 1,
- .entry_size = sizeof(struct hal_tcl_gse_cmd) >> 2,
- .mac_type = ATH12K_HAL_SRNG_UMAC,
- .ring_dir = HAL_SRNG_DIR_SRC,
- .max_size = HAL_SW2TCL1_CMD_RING_BASE_MSB_RING_SIZE,
- },
- [HAL_TCL_STATUS] = {
- .start_ring_id = HAL_SRNG_RING_ID_TCL_STATUS,
- .max_rings = 1,
- .entry_size = (sizeof(struct hal_tlv_hdr) +
- sizeof(struct hal_tcl_status_ring)) >> 2,
- .mac_type = ATH12K_HAL_SRNG_UMAC,
- .ring_dir = HAL_SRNG_DIR_DST,
- .max_size = HAL_TCL_STATUS_RING_BASE_MSB_RING_SIZE,
- },
- [HAL_CE_SRC] = {
- .start_ring_id = HAL_SRNG_RING_ID_CE0_SRC,
- .max_rings = 16,
- .entry_size = sizeof(struct hal_ce_srng_src_desc) >> 2,
- .mac_type = ATH12K_HAL_SRNG_UMAC,
- .ring_dir = HAL_SRNG_DIR_SRC,
- .max_size = HAL_CE_SRC_RING_BASE_MSB_RING_SIZE,
- },
- [HAL_CE_DST] = {
- .start_ring_id = HAL_SRNG_RING_ID_CE0_DST,
- .max_rings = 16,
- .entry_size = sizeof(struct hal_ce_srng_dest_desc) >> 2,
- .mac_type = ATH12K_HAL_SRNG_UMAC,
- .ring_dir = HAL_SRNG_DIR_SRC,
- .max_size = HAL_CE_DST_RING_BASE_MSB_RING_SIZE,
- },
- [HAL_CE_DST_STATUS] = {
- .start_ring_id = HAL_SRNG_RING_ID_CE0_DST_STATUS,
- .max_rings = 16,
- .entry_size = sizeof(struct hal_ce_srng_dst_status_desc) >> 2,
- .mac_type = ATH12K_HAL_SRNG_UMAC,
- .ring_dir = HAL_SRNG_DIR_DST,
- .max_size = HAL_CE_DST_STATUS_RING_BASE_MSB_RING_SIZE,
- },
- [HAL_WBM_IDLE_LINK] = {
- .start_ring_id = HAL_SRNG_RING_ID_WBM_IDLE_LINK,
- .max_rings = 1,
- .entry_size = sizeof(struct hal_wbm_link_desc) >> 2,
- .mac_type = ATH12K_HAL_SRNG_UMAC,
- .ring_dir = HAL_SRNG_DIR_SRC,
- .max_size = HAL_WBM_IDLE_LINK_RING_BASE_MSB_RING_SIZE,
- },
- [HAL_SW2WBM_RELEASE] = {
- .start_ring_id = HAL_SRNG_RING_ID_WBM_SW0_RELEASE,
- .max_rings = 2,
- .entry_size = sizeof(struct hal_wbm_release_ring) >> 2,
- .mac_type = ATH12K_HAL_SRNG_UMAC,
- .ring_dir = HAL_SRNG_DIR_SRC,
- .max_size = HAL_SW2WBM_RELEASE_RING_BASE_MSB_RING_SIZE,
- },
- [HAL_WBM2SW_RELEASE] = {
- .start_ring_id = HAL_SRNG_RING_ID_WBM2SW0_RELEASE,
- .max_rings = 8,
- .entry_size = sizeof(struct hal_wbm_release_ring) >> 2,
- .mac_type = ATH12K_HAL_SRNG_UMAC,
- .ring_dir = HAL_SRNG_DIR_DST,
- .max_size = HAL_WBM2SW_RELEASE_RING_BASE_MSB_RING_SIZE,
- },
- [HAL_RXDMA_BUF] = {
- .start_ring_id = HAL_SRNG_SW2RXDMA_BUF0,
- .max_rings = 1,
- .entry_size = sizeof(struct hal_wbm_buffer_ring) >> 2,
- .mac_type = ATH12K_HAL_SRNG_DMAC,
- .ring_dir = HAL_SRNG_DIR_SRC,
- .max_size = HAL_RXDMA_RING_MAX_SIZE_BE,
- },
- [HAL_RXDMA_DST] = {
- .start_ring_id = HAL_SRNG_RING_ID_WMAC1_RXDMA2SW0,
- .max_rings = 0,
- .entry_size = 0,
- .mac_type = ATH12K_HAL_SRNG_PMAC,
- .ring_dir = HAL_SRNG_DIR_DST,
- .max_size = HAL_RXDMA_RING_MAX_SIZE_BE,
- },
- [HAL_RXDMA_MONITOR_BUF] = {
- .start_ring_id = HAL_SRNG_SW2RXMON_BUF0,
- .max_rings = 1,
- .entry_size = sizeof(struct hal_mon_buf_ring) >> 2,
- .mac_type = ATH12K_HAL_SRNG_PMAC,
- .ring_dir = HAL_SRNG_DIR_SRC,
- .max_size = HAL_RXDMA_RING_MAX_SIZE_BE,
- },
- [HAL_RXDMA_MONITOR_STATUS] = {
- .start_ring_id = HAL_SRNG_RING_ID_WMAC1_SW2RXDMA1_STATBUF,
- .max_rings = 1,
- .entry_size = sizeof(struct hal_wbm_buffer_ring) >> 2,
- .mac_type = ATH12K_HAL_SRNG_PMAC,
- .ring_dir = HAL_SRNG_DIR_SRC,
- .max_size = HAL_RXDMA_RING_MAX_SIZE_BE,
- },
- [HAL_RXDMA_MONITOR_DESC] = { 0, },
- [HAL_RXDMA_DIR_BUF] = {
- .start_ring_id = HAL_SRNG_RING_ID_RXDMA_DIR_BUF,
- .max_rings = 2,
- .entry_size = 8 >> 2, /* TODO: Define the struct */
- .mac_type = ATH12K_HAL_SRNG_PMAC,
- .ring_dir = HAL_SRNG_DIR_SRC,
- .max_size = HAL_RXDMA_RING_MAX_SIZE_BE,
- },
- [HAL_PPE2TCL] = {
- .start_ring_id = HAL_SRNG_RING_ID_PPE2TCL1,
- .max_rings = 1,
- .entry_size = sizeof(struct hal_tcl_entrance_from_ppe_ring) >> 2,
- .mac_type = ATH12K_HAL_SRNG_PMAC,
- .ring_dir = HAL_SRNG_DIR_SRC,
- .max_size = HAL_SW2TCL1_RING_BASE_MSB_RING_SIZE,
- },
- [HAL_PPE_RELEASE] = {
- .start_ring_id = HAL_SRNG_RING_ID_WBM_PPE_RELEASE,
- .max_rings = 1,
- .entry_size = sizeof(struct hal_wbm_release_ring) >> 2,
- .mac_type = ATH12K_HAL_SRNG_PMAC,
- .ring_dir = HAL_SRNG_DIR_SRC,
- .max_size = HAL_WBM2PPE_RELEASE_RING_BASE_MSB_RING_SIZE,
- },
- [HAL_TX_MONITOR_BUF] = {
- .start_ring_id = HAL_SRNG_RING_ID_WMAC1_SW2TXMON_BUF0,
- .max_rings = 1,
- .entry_size = sizeof(struct hal_mon_buf_ring) >> 2,
- .mac_type = ATH12K_HAL_SRNG_PMAC,
- .ring_dir = HAL_SRNG_DIR_SRC,
- .max_size = HAL_RXDMA_RING_MAX_SIZE_BE,
- },
- [HAL_RXDMA_MONITOR_DST] = {
- .start_ring_id = HAL_SRNG_RING_ID_WMAC1_SW2RXMON_BUF0,
- .max_rings = 1,
- .entry_size = sizeof(struct hal_mon_dest_desc) >> 2,
- .mac_type = ATH12K_HAL_SRNG_PMAC,
- .ring_dir = HAL_SRNG_DIR_DST,
- .max_size = HAL_RXDMA_RING_MAX_SIZE_BE,
- },
- [HAL_TX_MONITOR_DST] = {
- .start_ring_id = HAL_SRNG_RING_ID_WMAC1_TXMON2SW0_BUF0,
- .max_rings = 1,
- .entry_size = sizeof(struct hal_mon_dest_desc) >> 2,
- .mac_type = ATH12K_HAL_SRNG_PMAC,
- .ring_dir = HAL_SRNG_DIR_DST,
- .max_size = HAL_RXDMA_RING_MAX_SIZE_BE,
- }
-};
-
-static const struct ath12k_hal_tcl_to_wbm_rbm_map
-ath12k_hal_qcn9274_tcl_to_wbm_rbm_map[DP_TCL_NUM_RING_MAX] = {
- {
- .wbm_ring_num = 0,
- .rbm_id = HAL_RX_BUF_RBM_SW0_BM,
- },
- {
- .wbm_ring_num = 1,
- .rbm_id = HAL_RX_BUF_RBM_SW1_BM,
- },
- {
- .wbm_ring_num = 2,
- .rbm_id = HAL_RX_BUF_RBM_SW2_BM,
- },
- {
- .wbm_ring_num = 4,
- .rbm_id = HAL_RX_BUF_RBM_SW4_BM,
- }
-};
-
-static const struct ath12k_hal_tcl_to_wbm_rbm_map
-ath12k_hal_wcn7850_tcl_to_wbm_rbm_map[DP_TCL_NUM_RING_MAX] = {
- {
- .wbm_ring_num = 0,
- .rbm_id = HAL_RX_BUF_RBM_SW0_BM,
- },
- {
- .wbm_ring_num = 2,
- .rbm_id = HAL_RX_BUF_RBM_SW2_BM,
- },
- {
- .wbm_ring_num = 4,
- .rbm_id = HAL_RX_BUF_RBM_SW4_BM,
- },
-};
-
-static unsigned int ath12k_hal_reo1_ring_id_offset(struct ath12k_base *ab)
-{
- return HAL_REO1_RING_ID(ab) - HAL_REO1_RING_BASE_LSB(ab);
-}
-
-static unsigned int ath12k_hal_reo1_ring_msi1_base_lsb_offset(struct ath12k_base *ab)
-{
- return HAL_REO1_RING_MSI1_BASE_LSB(ab) - HAL_REO1_RING_BASE_LSB(ab);
-}
-
-static unsigned int ath12k_hal_reo1_ring_msi1_base_msb_offset(struct ath12k_base *ab)
-{
- return HAL_REO1_RING_MSI1_BASE_MSB(ab) - HAL_REO1_RING_BASE_LSB(ab);
-}
-
-static unsigned int ath12k_hal_reo1_ring_msi1_data_offset(struct ath12k_base *ab)
-{
- return HAL_REO1_RING_MSI1_DATA(ab) - HAL_REO1_RING_BASE_LSB(ab);
-}
-
-static unsigned int ath12k_hal_reo1_ring_base_msb_offset(struct ath12k_base *ab)
-{
- return HAL_REO1_RING_BASE_MSB(ab) - HAL_REO1_RING_BASE_LSB(ab);
-}
-
-static unsigned int ath12k_hal_reo1_ring_producer_int_setup_offset(struct ath12k_base *ab)
-{
- return HAL_REO1_RING_PRODUCER_INT_SETUP(ab) - HAL_REO1_RING_BASE_LSB(ab);
-}
-
-static unsigned int ath12k_hal_reo1_ring_hp_addr_lsb_offset(struct ath12k_base *ab)
-{
- return HAL_REO1_RING_HP_ADDR_LSB(ab) - HAL_REO1_RING_BASE_LSB(ab);
-}
-
-static unsigned int ath12k_hal_reo1_ring_hp_addr_msb_offset(struct ath12k_base *ab)
-{
- return HAL_REO1_RING_HP_ADDR_MSB(ab) - HAL_REO1_RING_BASE_LSB(ab);
-}
-
-static unsigned int ath12k_hal_reo1_ring_misc_offset(struct ath12k_base *ab)
-{
- return HAL_REO1_RING_MISC(ab) - HAL_REO1_RING_BASE_LSB(ab);
-}
-
-static bool ath12k_hw_qcn9274_rx_desc_get_first_msdu(struct hal_rx_desc *desc)
-{
- return !!le16_get_bits(desc->u.qcn9274.msdu_end.info5,
- RX_MSDU_END_INFO5_FIRST_MSDU);
-}
-
-static bool ath12k_hw_qcn9274_rx_desc_get_last_msdu(struct hal_rx_desc *desc)
-{
- return !!le16_get_bits(desc->u.qcn9274.msdu_end.info5,
- RX_MSDU_END_INFO5_LAST_MSDU);
-}
-
-static u8 ath12k_hw_qcn9274_rx_desc_get_l3_pad_bytes(struct hal_rx_desc *desc)
-{
- return le16_get_bits(desc->u.qcn9274.msdu_end.info5,
- RX_MSDU_END_INFO5_L3_HDR_PADDING);
-}
-
-static bool ath12k_hw_qcn9274_rx_desc_encrypt_valid(struct hal_rx_desc *desc)
-{
- return !!le32_get_bits(desc->u.qcn9274.mpdu_start.info4,
- RX_MPDU_START_INFO4_ENCRYPT_INFO_VALID);
-}
-
-static u32 ath12k_hw_qcn9274_rx_desc_get_encrypt_type(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.qcn9274.mpdu_start.info2,
- RX_MPDU_START_INFO2_ENC_TYPE);
-}
-
-static u8 ath12k_hw_qcn9274_rx_desc_get_decap_type(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.qcn9274.msdu_end.info11,
- RX_MSDU_END_INFO11_DECAP_FORMAT);
-}
-
-static u8 ath12k_hw_qcn9274_rx_desc_get_mesh_ctl(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.qcn9274.msdu_end.info11,
- RX_MSDU_END_INFO11_MESH_CTRL_PRESENT);
-}
-
-static bool ath12k_hw_qcn9274_rx_desc_get_mpdu_seq_ctl_vld(struct hal_rx_desc *desc)
-{
- return !!le32_get_bits(desc->u.qcn9274.mpdu_start.info4,
- RX_MPDU_START_INFO4_MPDU_SEQ_CTRL_VALID);
-}
-
-static bool ath12k_hw_qcn9274_rx_desc_get_mpdu_fc_valid(struct hal_rx_desc *desc)
-{
- return !!le32_get_bits(desc->u.qcn9274.mpdu_start.info4,
- RX_MPDU_START_INFO4_MPDU_FCTRL_VALID);
-}
-
-static u16 ath12k_hw_qcn9274_rx_desc_get_mpdu_start_seq_no(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.qcn9274.mpdu_start.info4,
- RX_MPDU_START_INFO4_MPDU_SEQ_NUM);
-}
-
-static u16 ath12k_hw_qcn9274_rx_desc_get_msdu_len(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.qcn9274.msdu_end.info10,
- RX_MSDU_END_INFO10_MSDU_LENGTH);
-}
-
-static u8 ath12k_hw_qcn9274_rx_desc_get_msdu_sgi(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.qcn9274.msdu_end.info12,
- RX_MSDU_END_INFO12_SGI);
-}
-
-static u8 ath12k_hw_qcn9274_rx_desc_get_msdu_rate_mcs(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.qcn9274.msdu_end.info12,
- RX_MSDU_END_INFO12_RATE_MCS);
-}
-
-static u8 ath12k_hw_qcn9274_rx_desc_get_msdu_rx_bw(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.qcn9274.msdu_end.info12,
- RX_MSDU_END_INFO12_RECV_BW);
-}
-
-static u32 ath12k_hw_qcn9274_rx_desc_get_msdu_freq(struct hal_rx_desc *desc)
-{
- return __le32_to_cpu(desc->u.qcn9274.msdu_end.phy_meta_data);
-}
-
-static u8 ath12k_hw_qcn9274_rx_desc_get_msdu_pkt_type(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.qcn9274.msdu_end.info12,
- RX_MSDU_END_INFO12_PKT_TYPE);
-}
-
-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_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_INFO5_TID);
-}
-
-static u16 ath12k_hw_qcn9274_rx_desc_get_mpdu_peer_id(struct hal_rx_desc *desc)
-{
- return __le16_to_cpu(desc->u.qcn9274.mpdu_start.sw_peer_id);
-}
-
-static void ath12k_hw_qcn9274_rx_desc_copy_end_tlv(struct hal_rx_desc *fdesc,
- struct hal_rx_desc *ldesc)
-{
- memcpy(&fdesc->u.qcn9274.msdu_end, &ldesc->u.qcn9274.msdu_end,
- sizeof(struct rx_msdu_end_qcn9274));
-}
-
-static u32 ath12k_hw_qcn9274_rx_desc_get_mpdu_ppdu_id(struct hal_rx_desc *desc)
-{
- return __le16_to_cpu(desc->u.qcn9274.mpdu_start.phy_ppdu_id);
-}
-
-static void ath12k_hw_qcn9274_rx_desc_set_msdu_len(struct hal_rx_desc *desc, u16 len)
-{
- u32 info = __le32_to_cpu(desc->u.qcn9274.msdu_end.info10);
-
- info &= ~RX_MSDU_END_INFO10_MSDU_LENGTH;
- info |= u32_encode_bits(len, RX_MSDU_END_INFO10_MSDU_LENGTH);
-
- desc->u.qcn9274.msdu_end.info10 = __cpu_to_le32(info);
-}
-
-static u8 *ath12k_hw_qcn9274_rx_desc_get_msdu_payload(struct hal_rx_desc *desc)
-{
- return &desc->u.qcn9274.msdu_payload[0];
-}
-
-static u32 ath12k_hw_qcn9274_rx_desc_get_mpdu_start_offset(void)
-{
- return offsetof(struct hal_rx_desc_qcn9274, mpdu_start);
-}
-
-static u32 ath12k_hw_qcn9274_rx_desc_get_msdu_end_offset(void)
-{
- return offsetof(struct hal_rx_desc_qcn9274, msdu_end);
-}
-
-static bool ath12k_hw_qcn9274_rx_desc_mac_addr2_valid(struct hal_rx_desc *desc)
-{
- return __le32_to_cpu(desc->u.qcn9274.mpdu_start.info4) &
- RX_MPDU_START_INFO4_MAC_ADDR2_VALID;
-}
-
-static u8 *ath12k_hw_qcn9274_rx_desc_mpdu_start_addr2(struct hal_rx_desc *desc)
-{
- return desc->u.qcn9274.mpdu_start.addr2;
-}
-
-static bool ath12k_hw_qcn9274_rx_desc_is_da_mcbc(struct hal_rx_desc *desc)
-{
- return __le16_to_cpu(desc->u.qcn9274.msdu_end.info5) &
- RX_MSDU_END_INFO5_DA_IS_MCBC;
-}
-
-static void ath12k_hw_qcn9274_rx_desc_get_dot11_hdr(struct hal_rx_desc *desc,
- struct ieee80211_hdr *hdr)
-{
- hdr->frame_control = desc->u.qcn9274.mpdu_start.frame_ctrl;
- hdr->duration_id = desc->u.qcn9274.mpdu_start.duration;
- ether_addr_copy(hdr->addr1, desc->u.qcn9274.mpdu_start.addr1);
- ether_addr_copy(hdr->addr2, desc->u.qcn9274.mpdu_start.addr2);
- ether_addr_copy(hdr->addr3, desc->u.qcn9274.mpdu_start.addr3);
- if (__le32_to_cpu(desc->u.qcn9274.mpdu_start.info4) &
- RX_MPDU_START_INFO4_MAC_ADDR4_VALID) {
- ether_addr_copy(hdr->addr4, desc->u.qcn9274.mpdu_start.addr4);
- }
- hdr->seq_ctrl = desc->u.qcn9274.mpdu_start.seq_ctrl;
-}
-
-static void ath12k_hw_qcn9274_rx_desc_get_crypto_hdr(struct hal_rx_desc *desc,
- u8 *crypto_hdr,
- enum hal_encrypt_type enctype)
-{
- unsigned int key_id;
-
- switch (enctype) {
- case HAL_ENCRYPT_TYPE_OPEN:
- return;
- case HAL_ENCRYPT_TYPE_TKIP_NO_MIC:
- case HAL_ENCRYPT_TYPE_TKIP_MIC:
- crypto_hdr[0] =
- HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.qcn9274.mpdu_start.pn[0]);
- crypto_hdr[1] = 0;
- crypto_hdr[2] =
- HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.qcn9274.mpdu_start.pn[0]);
- break;
- case HAL_ENCRYPT_TYPE_CCMP_128:
- case HAL_ENCRYPT_TYPE_CCMP_256:
- case HAL_ENCRYPT_TYPE_GCMP_128:
- case HAL_ENCRYPT_TYPE_AES_GCMP_256:
- crypto_hdr[0] =
- HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.qcn9274.mpdu_start.pn[0]);
- crypto_hdr[1] =
- HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.qcn9274.mpdu_start.pn[0]);
- crypto_hdr[2] = 0;
- break;
- case HAL_ENCRYPT_TYPE_WEP_40:
- case HAL_ENCRYPT_TYPE_WEP_104:
- case HAL_ENCRYPT_TYPE_WEP_128:
- case HAL_ENCRYPT_TYPE_WAPI_GCM_SM4:
- case HAL_ENCRYPT_TYPE_WAPI:
- return;
- }
- key_id = le32_get_bits(desc->u.qcn9274.mpdu_start.info5,
- RX_MPDU_START_INFO5_KEY_ID);
- crypto_hdr[3] = 0x20 | (key_id << 6);
- crypto_hdr[4] = HAL_RX_MPDU_INFO_PN_GET_BYTE3(desc->u.qcn9274.mpdu_start.pn[0]);
- crypto_hdr[5] = HAL_RX_MPDU_INFO_PN_GET_BYTE4(desc->u.qcn9274.mpdu_start.pn[0]);
- crypto_hdr[6] = HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.qcn9274.mpdu_start.pn[1]);
- crypto_hdr[7] = HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.qcn9274.mpdu_start.pn[1]);
-}
-
-static int ath12k_hal_srng_create_config_qcn9274(struct ath12k_base *ab)
-{
- struct ath12k_hal *hal = &ab->hal;
- struct hal_srng_config *s;
-
- hal->srng_config = kmemdup(hw_srng_config_template,
- sizeof(hw_srng_config_template),
- GFP_KERNEL);
- if (!hal->srng_config)
- return -ENOMEM;
-
- s = &hal->srng_config[HAL_REO_DST];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_RING_HP;
- s->reg_size[0] = HAL_REO2_RING_BASE_LSB(ab) - HAL_REO1_RING_BASE_LSB(ab);
- s->reg_size[1] = HAL_REO2_RING_HP - HAL_REO1_RING_HP;
-
- s = &hal->srng_config[HAL_REO_EXCEPTION];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_SW0_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_SW0_RING_HP;
-
- s = &hal->srng_config[HAL_REO_REINJECT];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_HP;
- s->reg_size[0] = HAL_SW2REO1_RING_BASE_LSB(ab) - HAL_SW2REO_RING_BASE_LSB(ab);
- s->reg_size[1] = HAL_SW2REO1_RING_HP - HAL_SW2REO_RING_HP;
-
- s = &hal->srng_config[HAL_REO_CMD];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_HP;
-
- s = &hal->srng_config[HAL_REO_STATUS];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_HP;
-
- s = &hal->srng_config[HAL_TCL_DATA];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_HP;
- s->reg_size[0] = HAL_TCL2_RING_BASE_LSB(ab) - HAL_TCL1_RING_BASE_LSB(ab);
- s->reg_size[1] = HAL_TCL2_RING_HP - HAL_TCL1_RING_HP;
-
- s = &hal->srng_config[HAL_TCL_CMD];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_RING_HP;
-
- s = &hal->srng_config[HAL_TCL_STATUS];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_STATUS_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_STATUS_RING_HP;
-
- s = &hal->srng_config[HAL_CE_SRC];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_BASE_LSB;
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_HP;
- s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) -
- HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab);
- s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) -
- HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab);
-
- s = &hal->srng_config[HAL_CE_DST];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_BASE_LSB;
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_HP;
- s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
- HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
- s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
- HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
-
- s = &hal->srng_config[HAL_CE_DST_STATUS];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) +
- HAL_CE_DST_STATUS_RING_BASE_LSB;
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_STATUS_RING_HP;
- s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
- HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
- s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
- HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
-
- s = &hal->srng_config[HAL_WBM_IDLE_LINK];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_IDLE_LINK_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_IDLE_LINK_RING_HP;
-
- s = &hal->srng_config[HAL_SW2WBM_RELEASE];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG +
- HAL_WBM_SW_RELEASE_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_SW_RELEASE_RING_HP;
- s->reg_size[0] = HAL_WBM_SW1_RELEASE_RING_BASE_LSB(ab) -
- HAL_WBM_SW_RELEASE_RING_BASE_LSB(ab);
- s->reg_size[1] = HAL_WBM_SW1_RELEASE_RING_HP - HAL_WBM_SW_RELEASE_RING_HP;
-
- s = &hal->srng_config[HAL_WBM2SW_RELEASE];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM0_RELEASE_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM0_RELEASE_RING_HP;
- s->reg_size[0] = HAL_WBM1_RELEASE_RING_BASE_LSB(ab) -
- HAL_WBM0_RELEASE_RING_BASE_LSB(ab);
- s->reg_size[1] = HAL_WBM1_RELEASE_RING_HP - HAL_WBM0_RELEASE_RING_HP;
-
- /* Some LMAC rings are not accessed from the host:
- * RXDMA_BUG, RXDMA_DST, RXDMA_MONITOR_BUF, RXDMA_MONITOR_STATUS,
- * RXDMA_MONITOR_DST, RXDMA_MONITOR_DESC, RXDMA_DIR_BUF_SRC,
- * RXDMA_RX_MONITOR_BUF, TX_MONITOR_BUF, TX_MONITOR_DST, SW2RXDMA
- */
- s = &hal->srng_config[HAL_PPE2TCL];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_PPE2TCL1_RING_BASE_LSB;
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_PPE2TCL1_RING_HP;
-
- s = &hal->srng_config[HAL_PPE_RELEASE];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG +
- HAL_WBM_PPE_RELEASE_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_PPE_RELEASE_RING_HP;
-
- return 0;
-}
-
-static u16 ath12k_hal_qcn9274_rx_mpdu_start_wmask_get(void)
-{
- return QCN9274_MPDU_START_WMASK;
-}
-
-static u32 ath12k_hal_qcn9274_rx_msdu_end_wmask_get(void)
-{
- return QCN9274_MSDU_END_WMASK;
-}
-
-static const struct hal_rx_ops *ath12k_hal_qcn9274_get_hal_rx_compact_ops(void)
-{
- return &hal_rx_qcn9274_compact_ops;
-}
-
-static bool ath12k_hw_qcn9274_dp_rx_h_msdu_done(struct hal_rx_desc *desc)
-{
- return !!le32_get_bits(desc->u.qcn9274.msdu_end.info14,
- RX_MSDU_END_INFO14_MSDU_DONE);
-}
-
-static bool ath12k_hw_qcn9274_dp_rx_h_l4_cksum_fail(struct hal_rx_desc *desc)
-{
- return !!le32_get_bits(desc->u.qcn9274.msdu_end.info13,
- RX_MSDU_END_INFO13_TCP_UDP_CKSUM_FAIL);
-}
-
-static bool ath12k_hw_qcn9274_dp_rx_h_ip_cksum_fail(struct hal_rx_desc *desc)
-{
- return !!le32_get_bits(desc->u.qcn9274.msdu_end.info13,
- RX_MSDU_END_INFO13_IP_CKSUM_FAIL);
-}
-
-static bool ath12k_hw_qcn9274_dp_rx_h_is_decrypted(struct hal_rx_desc *desc)
-{
- return (le32_get_bits(desc->u.qcn9274.msdu_end.info14,
- RX_MSDU_END_INFO14_DECRYPT_STATUS_CODE) ==
- RX_DESC_DECRYPT_STATUS_CODE_OK);
-}
-
-static u32 ath12k_hw_qcn9274_dp_rx_h_mpdu_err(struct hal_rx_desc *desc)
-{
- u32 info = __le32_to_cpu(desc->u.qcn9274.msdu_end.info13);
- u32 errmap = 0;
-
- if (info & RX_MSDU_END_INFO13_FCS_ERR)
- errmap |= HAL_RX_MPDU_ERR_FCS;
-
- if (info & RX_MSDU_END_INFO13_DECRYPT_ERR)
- errmap |= HAL_RX_MPDU_ERR_DECRYPT;
-
- if (info & RX_MSDU_END_INFO13_TKIP_MIC_ERR)
- errmap |= HAL_RX_MPDU_ERR_TKIP_MIC;
-
- if (info & RX_MSDU_END_INFO13_A_MSDU_ERROR)
- errmap |= HAL_RX_MPDU_ERR_AMSDU_ERR;
-
- if (info & RX_MSDU_END_INFO13_OVERFLOW_ERR)
- errmap |= HAL_RX_MPDU_ERR_OVERFLOW;
-
- if (info & RX_MSDU_END_INFO13_MSDU_LEN_ERR)
- errmap |= HAL_RX_MPDU_ERR_MSDU_LEN;
-
- if (info & RX_MSDU_END_INFO13_MPDU_LEN_ERR)
- errmap |= HAL_RX_MPDU_ERR_MPDU_LEN;
-
- return errmap;
-}
-
-static u32 ath12k_hw_qcn9274_get_rx_desc_size(void)
-{
- return sizeof(struct hal_rx_desc_qcn9274);
-}
-
-static u8 ath12k_hw_qcn9274_rx_desc_get_msdu_src_link(struct hal_rx_desc *desc)
-{
- return 0;
-}
-
-const struct hal_rx_ops hal_rx_qcn9274_ops = {
- .rx_desc_get_first_msdu = ath12k_hw_qcn9274_rx_desc_get_first_msdu,
- .rx_desc_get_last_msdu = ath12k_hw_qcn9274_rx_desc_get_last_msdu,
- .rx_desc_get_l3_pad_bytes = ath12k_hw_qcn9274_rx_desc_get_l3_pad_bytes,
- .rx_desc_encrypt_valid = ath12k_hw_qcn9274_rx_desc_encrypt_valid,
- .rx_desc_get_encrypt_type = ath12k_hw_qcn9274_rx_desc_get_encrypt_type,
- .rx_desc_get_decap_type = ath12k_hw_qcn9274_rx_desc_get_decap_type,
- .rx_desc_get_mesh_ctl = ath12k_hw_qcn9274_rx_desc_get_mesh_ctl,
- .rx_desc_get_mpdu_seq_ctl_vld = ath12k_hw_qcn9274_rx_desc_get_mpdu_seq_ctl_vld,
- .rx_desc_get_mpdu_fc_valid = ath12k_hw_qcn9274_rx_desc_get_mpdu_fc_valid,
- .rx_desc_get_mpdu_start_seq_no = ath12k_hw_qcn9274_rx_desc_get_mpdu_start_seq_no,
- .rx_desc_get_msdu_len = ath12k_hw_qcn9274_rx_desc_get_msdu_len,
- .rx_desc_get_msdu_sgi = ath12k_hw_qcn9274_rx_desc_get_msdu_sgi,
- .rx_desc_get_msdu_rate_mcs = ath12k_hw_qcn9274_rx_desc_get_msdu_rate_mcs,
- .rx_desc_get_msdu_rx_bw = ath12k_hw_qcn9274_rx_desc_get_msdu_rx_bw,
- .rx_desc_get_msdu_freq = ath12k_hw_qcn9274_rx_desc_get_msdu_freq,
- .rx_desc_get_msdu_pkt_type = ath12k_hw_qcn9274_rx_desc_get_msdu_pkt_type,
- .rx_desc_get_msdu_nss = ath12k_hw_qcn9274_rx_desc_get_msdu_nss,
- .rx_desc_get_mpdu_tid = ath12k_hw_qcn9274_rx_desc_get_mpdu_tid,
- .rx_desc_get_mpdu_peer_id = ath12k_hw_qcn9274_rx_desc_get_mpdu_peer_id,
- .rx_desc_copy_end_tlv = ath12k_hw_qcn9274_rx_desc_copy_end_tlv,
- .rx_desc_get_mpdu_ppdu_id = ath12k_hw_qcn9274_rx_desc_get_mpdu_ppdu_id,
- .rx_desc_set_msdu_len = ath12k_hw_qcn9274_rx_desc_set_msdu_len,
- .rx_desc_get_msdu_payload = ath12k_hw_qcn9274_rx_desc_get_msdu_payload,
- .rx_desc_get_mpdu_start_offset = ath12k_hw_qcn9274_rx_desc_get_mpdu_start_offset,
- .rx_desc_get_msdu_end_offset = ath12k_hw_qcn9274_rx_desc_get_msdu_end_offset,
- .rx_desc_mac_addr2_valid = ath12k_hw_qcn9274_rx_desc_mac_addr2_valid,
- .rx_desc_mpdu_start_addr2 = ath12k_hw_qcn9274_rx_desc_mpdu_start_addr2,
- .rx_desc_is_da_mcbc = ath12k_hw_qcn9274_rx_desc_is_da_mcbc,
- .rx_desc_get_dot11_hdr = ath12k_hw_qcn9274_rx_desc_get_dot11_hdr,
- .rx_desc_get_crypto_header = ath12k_hw_qcn9274_rx_desc_get_crypto_hdr,
- .dp_rx_h_msdu_done = ath12k_hw_qcn9274_dp_rx_h_msdu_done,
- .dp_rx_h_l4_cksum_fail = ath12k_hw_qcn9274_dp_rx_h_l4_cksum_fail,
- .dp_rx_h_ip_cksum_fail = ath12k_hw_qcn9274_dp_rx_h_ip_cksum_fail,
- .dp_rx_h_is_decrypted = ath12k_hw_qcn9274_dp_rx_h_is_decrypted,
- .dp_rx_h_mpdu_err = ath12k_hw_qcn9274_dp_rx_h_mpdu_err,
- .rx_desc_get_desc_size = ath12k_hw_qcn9274_get_rx_desc_size,
- .rx_desc_get_msdu_src_link_id = ath12k_hw_qcn9274_rx_desc_get_msdu_src_link,
-};
-
-static bool ath12k_hw_qcn9274_compact_rx_desc_get_first_msdu(struct hal_rx_desc *desc)
-{
- return !!le16_get_bits(desc->u.qcn9274_compact.msdu_end.info5,
- RX_MSDU_END_INFO5_FIRST_MSDU);
-}
-
-static bool ath12k_hw_qcn9274_compact_rx_desc_get_last_msdu(struct hal_rx_desc *desc)
-{
- return !!le16_get_bits(desc->u.qcn9274_compact.msdu_end.info5,
- RX_MSDU_END_INFO5_LAST_MSDU);
-}
-
-static u8 ath12k_hw_qcn9274_compact_rx_desc_get_l3_pad_bytes(struct hal_rx_desc *desc)
-{
- return le16_get_bits(desc->u.qcn9274_compact.msdu_end.info5,
- RX_MSDU_END_INFO5_L3_HDR_PADDING);
-}
-
-static bool ath12k_hw_qcn9274_compact_rx_desc_encrypt_valid(struct hal_rx_desc *desc)
-{
- return !!le32_get_bits(desc->u.qcn9274_compact.mpdu_start.info4,
- RX_MPDU_START_INFO4_ENCRYPT_INFO_VALID);
-}
-
-static u32 ath12k_hw_qcn9274_compact_rx_desc_get_encrypt_type(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.qcn9274_compact.mpdu_start.info2,
- RX_MPDU_START_INFO2_ENC_TYPE);
-}
-
-static u8 ath12k_hw_qcn9274_compact_rx_desc_get_decap_type(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info11,
- RX_MSDU_END_INFO11_DECAP_FORMAT);
-}
-
-static u8 ath12k_hw_qcn9274_compact_rx_desc_get_mesh_ctl(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.qcn9274.msdu_end.info11,
- RX_MSDU_END_INFO11_MESH_CTRL_PRESENT);
-}
-
-static bool
-ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_seq_ctl_vld(struct hal_rx_desc *desc)
-{
- return !!le32_get_bits(desc->u.qcn9274_compact.mpdu_start.info4,
- RX_MPDU_START_INFO4_MPDU_SEQ_CTRL_VALID);
-}
-
-static bool ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_fc_valid(struct hal_rx_desc *desc)
-{
- return !!le32_get_bits(desc->u.qcn9274_compact.mpdu_start.info4,
- RX_MPDU_START_INFO4_MPDU_FCTRL_VALID);
-}
-
-static u16
-ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_start_seq_no(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.qcn9274_compact.mpdu_start.info4,
- RX_MPDU_START_INFO4_MPDU_SEQ_NUM);
-}
-
-static u16 ath12k_hw_qcn9274_compact_rx_desc_get_msdu_len(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info10,
- RX_MSDU_END_INFO10_MSDU_LENGTH);
-}
-
-static u8 ath12k_hw_qcn9274_compact_rx_desc_get_msdu_sgi(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info12,
- RX_MSDU_END_INFO12_SGI);
-}
-
-static u8 ath12k_hw_qcn9274_compact_rx_desc_get_msdu_rate_mcs(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info12,
- RX_MSDU_END_INFO12_RATE_MCS);
-}
-
-static u8 ath12k_hw_qcn9274_compact_rx_desc_get_msdu_rx_bw(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info12,
- RX_MSDU_END_INFO12_RECV_BW);
-}
-
-static u32 ath12k_hw_qcn9274_compact_rx_desc_get_msdu_freq(struct hal_rx_desc *desc)
-{
- return __le32_to_cpu(desc->u.qcn9274_compact.msdu_end.phy_meta_data);
-}
-
-static u8 ath12k_hw_qcn9274_compact_rx_desc_get_msdu_pkt_type(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info12,
- RX_MSDU_END_INFO12_PKT_TYPE);
-}
-
-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_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_INFO5_TID);
-}
-
-static u16 ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_peer_id(struct hal_rx_desc *desc)
-{
- return __le16_to_cpu(desc->u.qcn9274_compact.mpdu_start.sw_peer_id);
-}
-
-static void ath12k_hw_qcn9274_compact_rx_desc_copy_end_tlv(struct hal_rx_desc *fdesc,
- struct hal_rx_desc *ldesc)
-{
- fdesc->u.qcn9274_compact.msdu_end = ldesc->u.qcn9274_compact.msdu_end;
-}
-
-static u32 ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_ppdu_id(struct hal_rx_desc *desc)
-{
- return __le16_to_cpu(desc->u.qcn9274_compact.mpdu_start.phy_ppdu_id);
-}
-
-static void
-ath12k_hw_qcn9274_compact_rx_desc_set_msdu_len(struct hal_rx_desc *desc, u16 len)
-{
- u32 info = __le32_to_cpu(desc->u.qcn9274_compact.msdu_end.info10);
-
- info = u32_replace_bits(info, len, RX_MSDU_END_INFO10_MSDU_LENGTH);
- desc->u.qcn9274_compact.msdu_end.info10 = __cpu_to_le32(info);
-}
-
-static u8 *ath12k_hw_qcn9274_compact_rx_desc_get_msdu_payload(struct hal_rx_desc *desc)
-{
- return &desc->u.qcn9274_compact.msdu_payload[0];
-}
-
-static u32 ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_start_offset(void)
-{
- return offsetof(struct hal_rx_desc_qcn9274_compact, mpdu_start);
-}
-
-static u32 ath12k_hw_qcn9274_compact_rx_desc_get_msdu_end_offset(void)
-{
- return offsetof(struct hal_rx_desc_qcn9274_compact, msdu_end);
-}
-
-static bool ath12k_hw_qcn9274_compact_rx_desc_mac_addr2_valid(struct hal_rx_desc *desc)
-{
- return __le32_to_cpu(desc->u.qcn9274_compact.mpdu_start.info4) &
- RX_MPDU_START_INFO4_MAC_ADDR2_VALID;
-}
-
-static u8 *ath12k_hw_qcn9274_compact_rx_desc_mpdu_start_addr2(struct hal_rx_desc *desc)
-{
- return desc->u.qcn9274_compact.mpdu_start.addr2;
-}
-
-static bool ath12k_hw_qcn9274_compact_rx_desc_is_da_mcbc(struct hal_rx_desc *desc)
-{
- return __le16_to_cpu(desc->u.qcn9274_compact.msdu_end.info5) &
- RX_MSDU_END_INFO5_DA_IS_MCBC;
-}
-
-static void ath12k_hw_qcn9274_compact_rx_desc_get_dot11_hdr(struct hal_rx_desc *desc,
- struct ieee80211_hdr *hdr)
-{
- hdr->frame_control = desc->u.qcn9274_compact.mpdu_start.frame_ctrl;
- hdr->duration_id = desc->u.qcn9274_compact.mpdu_start.duration;
- ether_addr_copy(hdr->addr1, desc->u.qcn9274_compact.mpdu_start.addr1);
- ether_addr_copy(hdr->addr2, desc->u.qcn9274_compact.mpdu_start.addr2);
- ether_addr_copy(hdr->addr3, desc->u.qcn9274_compact.mpdu_start.addr3);
- if (__le32_to_cpu(desc->u.qcn9274_compact.mpdu_start.info4) &
- RX_MPDU_START_INFO4_MAC_ADDR4_VALID) {
- ether_addr_copy(hdr->addr4, desc->u.qcn9274_compact.mpdu_start.addr4);
- }
- hdr->seq_ctrl = desc->u.qcn9274_compact.mpdu_start.seq_ctrl;
-}
-
-static void
-ath12k_hw_qcn9274_compact_rx_desc_get_crypto_hdr(struct hal_rx_desc *desc,
- u8 *crypto_hdr,
- enum hal_encrypt_type enctype)
-{
- unsigned int key_id;
-
- switch (enctype) {
- case HAL_ENCRYPT_TYPE_OPEN:
- return;
- case HAL_ENCRYPT_TYPE_TKIP_NO_MIC:
- case HAL_ENCRYPT_TYPE_TKIP_MIC:
- crypto_hdr[0] =
- HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.qcn9274_compact.mpdu_start.pn[0]);
- crypto_hdr[1] = 0;
- crypto_hdr[2] =
- HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.qcn9274_compact.mpdu_start.pn[0]);
- break;
- case HAL_ENCRYPT_TYPE_CCMP_128:
- case HAL_ENCRYPT_TYPE_CCMP_256:
- case HAL_ENCRYPT_TYPE_GCMP_128:
- case HAL_ENCRYPT_TYPE_AES_GCMP_256:
- crypto_hdr[0] =
- HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.qcn9274_compact.mpdu_start.pn[0]);
- crypto_hdr[1] =
- HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.qcn9274_compact.mpdu_start.pn[0]);
- crypto_hdr[2] = 0;
- break;
- case HAL_ENCRYPT_TYPE_WEP_40:
- case HAL_ENCRYPT_TYPE_WEP_104:
- case HAL_ENCRYPT_TYPE_WEP_128:
- case HAL_ENCRYPT_TYPE_WAPI_GCM_SM4:
- case HAL_ENCRYPT_TYPE_WAPI:
- return;
- }
- key_id = le32_get_bits(desc->u.qcn9274_compact.mpdu_start.info5,
- RX_MPDU_START_INFO5_KEY_ID);
- crypto_hdr[3] = 0x20 | (key_id << 6);
- crypto_hdr[4] =
- HAL_RX_MPDU_INFO_PN_GET_BYTE3(desc->u.qcn9274_compact.mpdu_start.pn[0]);
- crypto_hdr[5] =
- HAL_RX_MPDU_INFO_PN_GET_BYTE4(desc->u.qcn9274_compact.mpdu_start.pn[0]);
- crypto_hdr[6] =
- HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.qcn9274_compact.mpdu_start.pn[1]);
- crypto_hdr[7] =
- HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.qcn9274_compact.mpdu_start.pn[1]);
-}
-
-static bool ath12k_hw_qcn9274_compact_dp_rx_h_msdu_done(struct hal_rx_desc *desc)
-{
- return !!le32_get_bits(desc->u.qcn9274_compact.msdu_end.info14,
- RX_MSDU_END_INFO14_MSDU_DONE);
-}
-
-static bool ath12k_hw_qcn9274_compact_dp_rx_h_l4_cksum_fail(struct hal_rx_desc *desc)
-{
- return !!le32_get_bits(desc->u.qcn9274_compact.msdu_end.info13,
- RX_MSDU_END_INFO13_TCP_UDP_CKSUM_FAIL);
-}
-
-static bool ath12k_hw_qcn9274_compact_dp_rx_h_ip_cksum_fail(struct hal_rx_desc *desc)
-{
- return !!le32_get_bits(desc->u.qcn9274_compact.msdu_end.info13,
- RX_MSDU_END_INFO13_IP_CKSUM_FAIL);
-}
-
-static bool ath12k_hw_qcn9274_compact_dp_rx_h_is_decrypted(struct hal_rx_desc *desc)
-{
- return (le32_get_bits(desc->u.qcn9274_compact.msdu_end.info14,
- RX_MSDU_END_INFO14_DECRYPT_STATUS_CODE) ==
- RX_DESC_DECRYPT_STATUS_CODE_OK);
-}
-
-static u32 ath12k_hw_qcn9274_compact_dp_rx_h_mpdu_err(struct hal_rx_desc *desc)
-{
- u32 info = __le32_to_cpu(desc->u.qcn9274_compact.msdu_end.info13);
- u32 errmap = 0;
-
- if (info & RX_MSDU_END_INFO13_FCS_ERR)
- errmap |= HAL_RX_MPDU_ERR_FCS;
-
- if (info & RX_MSDU_END_INFO13_DECRYPT_ERR)
- errmap |= HAL_RX_MPDU_ERR_DECRYPT;
-
- if (info & RX_MSDU_END_INFO13_TKIP_MIC_ERR)
- errmap |= HAL_RX_MPDU_ERR_TKIP_MIC;
-
- if (info & RX_MSDU_END_INFO13_A_MSDU_ERROR)
- errmap |= HAL_RX_MPDU_ERR_AMSDU_ERR;
-
- if (info & RX_MSDU_END_INFO13_OVERFLOW_ERR)
- errmap |= HAL_RX_MPDU_ERR_OVERFLOW;
-
- if (info & RX_MSDU_END_INFO13_MSDU_LEN_ERR)
- errmap |= HAL_RX_MPDU_ERR_MSDU_LEN;
-
- if (info & RX_MSDU_END_INFO13_MPDU_LEN_ERR)
- errmap |= HAL_RX_MPDU_ERR_MPDU_LEN;
-
- return errmap;
-}
-
-static u32 ath12k_hw_qcn9274_compact_get_rx_desc_size(void)
-{
- return sizeof(struct hal_rx_desc_qcn9274_compact);
-}
-
-static u8 ath12k_hw_qcn9274_compact_rx_desc_get_msdu_src_link(struct hal_rx_desc *desc)
-{
- return le64_get_bits(desc->u.qcn9274_compact.msdu_end.msdu_end_tag,
- RX_MSDU_END_64_TLV_SRC_LINK_ID);
-}
-
-const struct hal_rx_ops hal_rx_qcn9274_compact_ops = {
- .rx_desc_get_first_msdu = ath12k_hw_qcn9274_compact_rx_desc_get_first_msdu,
- .rx_desc_get_last_msdu = ath12k_hw_qcn9274_compact_rx_desc_get_last_msdu,
- .rx_desc_get_l3_pad_bytes = ath12k_hw_qcn9274_compact_rx_desc_get_l3_pad_bytes,
- .rx_desc_encrypt_valid = ath12k_hw_qcn9274_compact_rx_desc_encrypt_valid,
- .rx_desc_get_encrypt_type = ath12k_hw_qcn9274_compact_rx_desc_get_encrypt_type,
- .rx_desc_get_decap_type = ath12k_hw_qcn9274_compact_rx_desc_get_decap_type,
- .rx_desc_get_mesh_ctl = ath12k_hw_qcn9274_compact_rx_desc_get_mesh_ctl,
- .rx_desc_get_mpdu_seq_ctl_vld =
- ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_seq_ctl_vld,
- .rx_desc_get_mpdu_fc_valid = ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_fc_valid,
- .rx_desc_get_mpdu_start_seq_no =
- ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_start_seq_no,
- .rx_desc_get_msdu_len = ath12k_hw_qcn9274_compact_rx_desc_get_msdu_len,
- .rx_desc_get_msdu_sgi = ath12k_hw_qcn9274_compact_rx_desc_get_msdu_sgi,
- .rx_desc_get_msdu_rate_mcs = ath12k_hw_qcn9274_compact_rx_desc_get_msdu_rate_mcs,
- .rx_desc_get_msdu_rx_bw = ath12k_hw_qcn9274_compact_rx_desc_get_msdu_rx_bw,
- .rx_desc_get_msdu_freq = ath12k_hw_qcn9274_compact_rx_desc_get_msdu_freq,
- .rx_desc_get_msdu_pkt_type = ath12k_hw_qcn9274_compact_rx_desc_get_msdu_pkt_type,
- .rx_desc_get_msdu_nss = ath12k_hw_qcn9274_compact_rx_desc_get_msdu_nss,
- .rx_desc_get_mpdu_tid = ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_tid,
- .rx_desc_get_mpdu_peer_id = ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_peer_id,
- .rx_desc_copy_end_tlv = ath12k_hw_qcn9274_compact_rx_desc_copy_end_tlv,
- .rx_desc_get_mpdu_ppdu_id = ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_ppdu_id,
- .rx_desc_set_msdu_len = ath12k_hw_qcn9274_compact_rx_desc_set_msdu_len,
- .rx_desc_get_msdu_payload = ath12k_hw_qcn9274_compact_rx_desc_get_msdu_payload,
- .rx_desc_get_mpdu_start_offset =
- ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_start_offset,
- .rx_desc_get_msdu_end_offset =
- ath12k_hw_qcn9274_compact_rx_desc_get_msdu_end_offset,
- .rx_desc_mac_addr2_valid = ath12k_hw_qcn9274_compact_rx_desc_mac_addr2_valid,
- .rx_desc_mpdu_start_addr2 = ath12k_hw_qcn9274_compact_rx_desc_mpdu_start_addr2,
- .rx_desc_is_da_mcbc = ath12k_hw_qcn9274_compact_rx_desc_is_da_mcbc,
- .rx_desc_get_dot11_hdr = ath12k_hw_qcn9274_compact_rx_desc_get_dot11_hdr,
- .rx_desc_get_crypto_header = ath12k_hw_qcn9274_compact_rx_desc_get_crypto_hdr,
- .dp_rx_h_msdu_done = ath12k_hw_qcn9274_compact_dp_rx_h_msdu_done,
- .dp_rx_h_l4_cksum_fail = ath12k_hw_qcn9274_compact_dp_rx_h_l4_cksum_fail,
- .dp_rx_h_ip_cksum_fail = ath12k_hw_qcn9274_compact_dp_rx_h_ip_cksum_fail,
- .dp_rx_h_is_decrypted = ath12k_hw_qcn9274_compact_dp_rx_h_is_decrypted,
- .dp_rx_h_mpdu_err = ath12k_hw_qcn9274_compact_dp_rx_h_mpdu_err,
- .rx_desc_get_desc_size = ath12k_hw_qcn9274_compact_get_rx_desc_size,
- .rx_desc_get_msdu_src_link_id =
- ath12k_hw_qcn9274_compact_rx_desc_get_msdu_src_link,
-};
-
-const struct hal_ops hal_qcn9274_ops = {
- .create_srng_config = ath12k_hal_srng_create_config_qcn9274,
- .tcl_to_wbm_rbm_map = ath12k_hal_qcn9274_tcl_to_wbm_rbm_map,
- .rxdma_ring_wmask_rx_mpdu_start = ath12k_hal_qcn9274_rx_mpdu_start_wmask_get,
- .rxdma_ring_wmask_rx_msdu_end = ath12k_hal_qcn9274_rx_msdu_end_wmask_get,
- .get_hal_rx_compact_ops = ath12k_hal_qcn9274_get_hal_rx_compact_ops,
-};
-
-static bool ath12k_hw_wcn7850_rx_desc_get_first_msdu(struct hal_rx_desc *desc)
-{
- return !!le16_get_bits(desc->u.wcn7850.msdu_end.info5,
- RX_MSDU_END_INFO5_FIRST_MSDU);
-}
-
-static bool ath12k_hw_wcn7850_rx_desc_get_last_msdu(struct hal_rx_desc *desc)
-{
- return !!le16_get_bits(desc->u.wcn7850.msdu_end.info5,
- RX_MSDU_END_INFO5_LAST_MSDU);
-}
-
-static u8 ath12k_hw_wcn7850_rx_desc_get_l3_pad_bytes(struct hal_rx_desc *desc)
-{
- return le16_get_bits(desc->u.wcn7850.msdu_end.info5,
- RX_MSDU_END_INFO5_L3_HDR_PADDING);
-}
-
-static bool ath12k_hw_wcn7850_rx_desc_encrypt_valid(struct hal_rx_desc *desc)
-{
- return !!le32_get_bits(desc->u.wcn7850.mpdu_start.info4,
- RX_MPDU_START_INFO4_ENCRYPT_INFO_VALID);
-}
-
-static u32 ath12k_hw_wcn7850_rx_desc_get_encrypt_type(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.wcn7850.mpdu_start.info2,
- RX_MPDU_START_INFO2_ENC_TYPE);
-}
-
-static u8 ath12k_hw_wcn7850_rx_desc_get_decap_type(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.wcn7850.msdu_end.info11,
- RX_MSDU_END_INFO11_DECAP_FORMAT);
-}
-
-static u8 ath12k_hw_wcn7850_rx_desc_get_mesh_ctl(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.wcn7850.msdu_end.info11,
- RX_MSDU_END_INFO11_MESH_CTRL_PRESENT);
-}
-
-static bool ath12k_hw_wcn7850_rx_desc_get_mpdu_seq_ctl_vld(struct hal_rx_desc *desc)
-{
- return !!le32_get_bits(desc->u.wcn7850.mpdu_start.info4,
- RX_MPDU_START_INFO4_MPDU_SEQ_CTRL_VALID);
-}
-
-static bool ath12k_hw_wcn7850_rx_desc_get_mpdu_fc_valid(struct hal_rx_desc *desc)
-{
- return !!le32_get_bits(desc->u.wcn7850.mpdu_start.info4,
- RX_MPDU_START_INFO4_MPDU_FCTRL_VALID);
-}
-
-static u16 ath12k_hw_wcn7850_rx_desc_get_mpdu_start_seq_no(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.wcn7850.mpdu_start.info4,
- RX_MPDU_START_INFO4_MPDU_SEQ_NUM);
-}
-
-static u16 ath12k_hw_wcn7850_rx_desc_get_msdu_len(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.wcn7850.msdu_end.info10,
- RX_MSDU_END_INFO10_MSDU_LENGTH);
-}
-
-static u8 ath12k_hw_wcn7850_rx_desc_get_msdu_sgi(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.wcn7850.msdu_end.info12,
- RX_MSDU_END_INFO12_SGI);
-}
-
-static u8 ath12k_hw_wcn7850_rx_desc_get_msdu_rate_mcs(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.wcn7850.msdu_end.info12,
- RX_MSDU_END_INFO12_RATE_MCS);
-}
-
-static u8 ath12k_hw_wcn7850_rx_desc_get_msdu_rx_bw(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.wcn7850.msdu_end.info12,
- RX_MSDU_END_INFO12_RECV_BW);
-}
-
-static u32 ath12k_hw_wcn7850_rx_desc_get_msdu_freq(struct hal_rx_desc *desc)
-{
- return __le32_to_cpu(desc->u.wcn7850.msdu_end.phy_meta_data);
-}
-
-static u8 ath12k_hw_wcn7850_rx_desc_get_msdu_pkt_type(struct hal_rx_desc *desc)
-{
- return le32_get_bits(desc->u.wcn7850.msdu_end.info12,
- RX_MSDU_END_INFO12_PKT_TYPE);
-}
-
-static u8 ath12k_hw_wcn7850_rx_desc_get_msdu_nss(struct hal_rx_desc *desc)
+static void ath12k_hal_ce_dst_setup(struct ath12k_base *ab,
+ struct hal_srng *srng, int ring_num)
{
- return le32_get_bits(desc->u.wcn7850.msdu_end.info12,
- RX_MSDU_END_INFO12_MIMO_SS_BITMAP);
+ ab->hal.ops->ce_dst_setup(ab, srng, ring_num);
}
-static u8 ath12k_hw_wcn7850_rx_desc_get_mpdu_tid(struct hal_rx_desc *desc)
+static void ath12k_hal_srng_src_hw_init(struct ath12k_base *ab,
+ struct hal_srng *srng)
{
- return le32_get_bits(desc->u.wcn7850.mpdu_start.info2,
- RX_MPDU_START_INFO2_TID);
+ ab->hal.ops->srng_src_hw_init(ab, srng);
}
-static u16 ath12k_hw_wcn7850_rx_desc_get_mpdu_peer_id(struct hal_rx_desc *desc)
+static void ath12k_hal_srng_dst_hw_init(struct ath12k_base *ab,
+ struct hal_srng *srng)
{
- return __le16_to_cpu(desc->u.wcn7850.mpdu_start.sw_peer_id);
+ ab->hal.ops->srng_dst_hw_init(ab, srng);
}
-static void ath12k_hw_wcn7850_rx_desc_copy_end_tlv(struct hal_rx_desc *fdesc,
- struct hal_rx_desc *ldesc)
+static void ath12k_hal_set_umac_srng_ptr_addr(struct ath12k_base *ab,
+ struct hal_srng *srng)
{
- memcpy(&fdesc->u.wcn7850.msdu_end, &ldesc->u.wcn7850.msdu_end,
- sizeof(struct rx_msdu_end_qcn9274));
+ ab->hal.ops->set_umac_srng_ptr_addr(ab, srng);
}
-static u32 ath12k_hw_wcn7850_rx_desc_get_mpdu_start_tag(struct hal_rx_desc *desc)
+static int ath12k_hal_srng_get_ring_id(struct ath12k_hal *hal,
+ enum hal_ring_type type,
+ int ring_num, int mac_id)
{
- return le64_get_bits(desc->u.wcn7850.mpdu_start_tag,
- HAL_TLV_HDR_TAG);
+ return hal->ops->srng_get_ring_id(hal, type, ring_num, mac_id);
}
-static u32 ath12k_hw_wcn7850_rx_desc_get_mpdu_ppdu_id(struct hal_rx_desc *desc)
+int ath12k_hal_srng_update_shadow_config(struct ath12k_base *ab,
+ enum hal_ring_type ring_type,
+ int ring_num)
{
- return __le16_to_cpu(desc->u.wcn7850.mpdu_start.phy_ppdu_id);
+ return ab->hal.ops->srng_update_shadow_config(ab, ring_type,
+ ring_num);
}
-static void ath12k_hw_wcn7850_rx_desc_set_msdu_len(struct hal_rx_desc *desc, u16 len)
+u32 ath12k_hal_ce_get_desc_size(struct ath12k_hal *hal, enum hal_ce_desc type)
{
- u32 info = __le32_to_cpu(desc->u.wcn7850.msdu_end.info10);
-
- info &= ~RX_MSDU_END_INFO10_MSDU_LENGTH;
- info |= u32_encode_bits(len, RX_MSDU_END_INFO10_MSDU_LENGTH);
-
- desc->u.wcn7850.msdu_end.info10 = __cpu_to_le32(info);
+ return hal->ops->ce_get_desc_size(type);
}
-static u8 *ath12k_hw_wcn7850_rx_desc_get_msdu_payload(struct hal_rx_desc *desc)
+void ath12k_hal_tx_set_dscp_tid_map(struct ath12k_base *ab, int id)
{
- return &desc->u.wcn7850.msdu_payload[0];
+ ab->hal.ops->tx_set_dscp_tid_map(ab, id);
}
-static u32 ath12k_hw_wcn7850_rx_desc_get_mpdu_start_offset(void)
+void ath12k_hal_tx_configure_bank_register(struct ath12k_base *ab,
+ u32 bank_config, u8 bank_id)
{
- return offsetof(struct hal_rx_desc_wcn7850, mpdu_start_tag);
+ ab->hal.ops->tx_configure_bank_register(ab, bank_config, bank_id);
}
-static u32 ath12k_hw_wcn7850_rx_desc_get_msdu_end_offset(void)
+void ath12k_hal_reoq_lut_addr_read_enable(struct ath12k_base *ab)
{
- return offsetof(struct hal_rx_desc_wcn7850, msdu_end_tag);
+ ab->hal.ops->reoq_lut_addr_read_enable(ab);
}
-static bool ath12k_hw_wcn7850_rx_desc_mac_addr2_valid(struct hal_rx_desc *desc)
+void ath12k_hal_reoq_lut_set_max_peerid(struct ath12k_base *ab)
{
- return __le32_to_cpu(desc->u.wcn7850.mpdu_start.info4) &
- RX_MPDU_START_INFO4_MAC_ADDR2_VALID;
+ ab->hal.ops->reoq_lut_set_max_peerid(ab);
}
-static u8 *ath12k_hw_wcn7850_rx_desc_mpdu_start_addr2(struct hal_rx_desc *desc)
+void ath12k_hal_write_ml_reoq_lut_addr(struct ath12k_base *ab, dma_addr_t paddr)
{
- return desc->u.wcn7850.mpdu_start.addr2;
+ ab->hal.ops->write_ml_reoq_lut_addr(ab, paddr);
}
-static bool ath12k_hw_wcn7850_rx_desc_is_da_mcbc(struct hal_rx_desc *desc)
+void ath12k_hal_write_reoq_lut_addr(struct ath12k_base *ab, dma_addr_t paddr)
{
- return __le32_to_cpu(desc->u.wcn7850.msdu_end.info13) &
- RX_MSDU_END_INFO13_MCAST_BCAST;
+ ab->hal.ops->write_reoq_lut_addr(ab, paddr);
}
-static void ath12k_hw_wcn7850_rx_desc_get_dot11_hdr(struct hal_rx_desc *desc,
- struct ieee80211_hdr *hdr)
+void ath12k_hal_setup_link_idle_list(struct ath12k_base *ab,
+ struct hal_wbm_idle_scatter_list *sbuf,
+ u32 nsbufs, u32 tot_link_desc,
+ u32 end_offset)
{
- hdr->frame_control = desc->u.wcn7850.mpdu_start.frame_ctrl;
- hdr->duration_id = desc->u.wcn7850.mpdu_start.duration;
- ether_addr_copy(hdr->addr1, desc->u.wcn7850.mpdu_start.addr1);
- ether_addr_copy(hdr->addr2, desc->u.wcn7850.mpdu_start.addr2);
- ether_addr_copy(hdr->addr3, desc->u.wcn7850.mpdu_start.addr3);
- if (__le32_to_cpu(desc->u.wcn7850.mpdu_start.info4) &
- RX_MPDU_START_INFO4_MAC_ADDR4_VALID) {
- ether_addr_copy(hdr->addr4, desc->u.wcn7850.mpdu_start.addr4);
- }
- hdr->seq_ctrl = desc->u.wcn7850.mpdu_start.seq_ctrl;
+ ab->hal.ops->setup_link_idle_list(ab, sbuf, nsbufs, tot_link_desc,
+ end_offset);
}
-static void ath12k_hw_wcn7850_rx_desc_get_crypto_hdr(struct hal_rx_desc *desc,
- u8 *crypto_hdr,
- enum hal_encrypt_type enctype)
+void ath12k_hal_reo_hw_setup(struct ath12k_base *ab, u32 ring_hash_map)
{
- unsigned int key_id;
-
- switch (enctype) {
- case HAL_ENCRYPT_TYPE_OPEN:
- return;
- case HAL_ENCRYPT_TYPE_TKIP_NO_MIC:
- case HAL_ENCRYPT_TYPE_TKIP_MIC:
- crypto_hdr[0] =
- HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.wcn7850.mpdu_start.pn[0]);
- crypto_hdr[1] = 0;
- crypto_hdr[2] =
- HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.wcn7850.mpdu_start.pn[0]);
- break;
- case HAL_ENCRYPT_TYPE_CCMP_128:
- case HAL_ENCRYPT_TYPE_CCMP_256:
- case HAL_ENCRYPT_TYPE_GCMP_128:
- case HAL_ENCRYPT_TYPE_AES_GCMP_256:
- crypto_hdr[0] =
- HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.wcn7850.mpdu_start.pn[0]);
- crypto_hdr[1] =
- HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.wcn7850.mpdu_start.pn[0]);
- crypto_hdr[2] = 0;
- break;
- case HAL_ENCRYPT_TYPE_WEP_40:
- case HAL_ENCRYPT_TYPE_WEP_104:
- case HAL_ENCRYPT_TYPE_WEP_128:
- case HAL_ENCRYPT_TYPE_WAPI_GCM_SM4:
- case HAL_ENCRYPT_TYPE_WAPI:
- return;
- }
- key_id = u32_get_bits(__le32_to_cpu(desc->u.wcn7850.mpdu_start.info5),
- RX_MPDU_START_INFO5_KEY_ID);
- crypto_hdr[3] = 0x20 | (key_id << 6);
- crypto_hdr[4] = HAL_RX_MPDU_INFO_PN_GET_BYTE3(desc->u.wcn7850.mpdu_start.pn[0]);
- crypto_hdr[5] = HAL_RX_MPDU_INFO_PN_GET_BYTE4(desc->u.wcn7850.mpdu_start.pn[0]);
- crypto_hdr[6] = HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.wcn7850.mpdu_start.pn[1]);
- crypto_hdr[7] = HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.wcn7850.mpdu_start.pn[1]);
+ ab->hal.ops->reo_hw_setup(ab, ring_hash_map);
}
-static int ath12k_hal_srng_create_config_wcn7850(struct ath12k_base *ab)
+void ath12k_hal_reo_init_cmd_ring(struct ath12k_base *ab, struct hal_srng *srng)
{
- struct ath12k_hal *hal = &ab->hal;
- struct hal_srng_config *s;
-
- hal->srng_config = kmemdup(hw_srng_config_template,
- sizeof(hw_srng_config_template),
- GFP_KERNEL);
- if (!hal->srng_config)
- return -ENOMEM;
-
- s = &hal->srng_config[HAL_REO_DST];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_RING_HP;
- s->reg_size[0] = HAL_REO2_RING_BASE_LSB(ab) - HAL_REO1_RING_BASE_LSB(ab);
- s->reg_size[1] = HAL_REO2_RING_HP - HAL_REO1_RING_HP;
-
- s = &hal->srng_config[HAL_REO_EXCEPTION];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_SW0_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_SW0_RING_HP;
-
- s = &hal->srng_config[HAL_REO_REINJECT];
- s->max_rings = 1;
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_HP;
-
- s = &hal->srng_config[HAL_REO_CMD];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_HP;
-
- s = &hal->srng_config[HAL_REO_STATUS];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_HP;
-
- s = &hal->srng_config[HAL_TCL_DATA];
- s->max_rings = 5;
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_HP;
- s->reg_size[0] = HAL_TCL2_RING_BASE_LSB(ab) - HAL_TCL1_RING_BASE_LSB(ab);
- s->reg_size[1] = HAL_TCL2_RING_HP - HAL_TCL1_RING_HP;
-
- s = &hal->srng_config[HAL_TCL_CMD];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_RING_HP;
-
- s = &hal->srng_config[HAL_TCL_STATUS];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_STATUS_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_STATUS_RING_HP;
-
- s = &hal->srng_config[HAL_CE_SRC];
- s->max_rings = 12;
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_BASE_LSB;
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_HP;
- s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) -
- HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab);
- s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) -
- HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab);
-
- s = &hal->srng_config[HAL_CE_DST];
- s->max_rings = 12;
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_BASE_LSB;
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_HP;
- s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
- HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
- s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
- HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
-
- s = &hal->srng_config[HAL_CE_DST_STATUS];
- s->max_rings = 12;
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) +
- HAL_CE_DST_STATUS_RING_BASE_LSB;
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_STATUS_RING_HP;
- s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
- HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
- s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
- HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
-
- s = &hal->srng_config[HAL_WBM_IDLE_LINK];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_IDLE_LINK_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_IDLE_LINK_RING_HP;
-
- s = &hal->srng_config[HAL_SW2WBM_RELEASE];
- s->max_rings = 1;
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG +
- HAL_WBM_SW_RELEASE_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_SW_RELEASE_RING_HP;
-
- s = &hal->srng_config[HAL_WBM2SW_RELEASE];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM0_RELEASE_RING_BASE_LSB(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM0_RELEASE_RING_HP;
- s->reg_size[0] = HAL_WBM1_RELEASE_RING_BASE_LSB(ab) -
- HAL_WBM0_RELEASE_RING_BASE_LSB(ab);
- s->reg_size[1] = HAL_WBM1_RELEASE_RING_HP - HAL_WBM0_RELEASE_RING_HP;
-
- s = &hal->srng_config[HAL_RXDMA_BUF];
- s->max_rings = 2;
- s->mac_type = ATH12K_HAL_SRNG_PMAC;
-
- s = &hal->srng_config[HAL_RXDMA_DST];
- s->max_rings = 1;
- s->entry_size = sizeof(struct hal_reo_entrance_ring) >> 2;
-
- /* below rings are not used */
- s = &hal->srng_config[HAL_RXDMA_DIR_BUF];
- s->max_rings = 0;
-
- s = &hal->srng_config[HAL_PPE2TCL];
- s->max_rings = 0;
-
- s = &hal->srng_config[HAL_PPE_RELEASE];
- s->max_rings = 0;
-
- s = &hal->srng_config[HAL_TX_MONITOR_BUF];
- s->max_rings = 0;
-
- s = &hal->srng_config[HAL_TX_MONITOR_DST];
- s->max_rings = 0;
-
- s = &hal->srng_config[HAL_PPE2TCL];
- s->max_rings = 0;
-
- return 0;
+ ab->hal.ops->reo_init_cmd_ring(ab, srng);
}
-static bool ath12k_hw_wcn7850_dp_rx_h_msdu_done(struct hal_rx_desc *desc)
+void ath12k_hal_reo_shared_qaddr_cache_clear(struct ath12k_base *ab)
{
- return !!le32_get_bits(desc->u.wcn7850.msdu_end.info14,
- RX_MSDU_END_INFO14_MSDU_DONE);
+ ab->hal.ops->reo_shared_qaddr_cache_clear(ab);
}
+EXPORT_SYMBOL(ath12k_hal_reo_shared_qaddr_cache_clear);
-static bool ath12k_hw_wcn7850_dp_rx_h_l4_cksum_fail(struct hal_rx_desc *desc)
+void ath12k_hal_rx_buf_addr_info_set(struct ath12k_hal *hal,
+ struct ath12k_buffer_addr *binfo,
+ dma_addr_t paddr, u32 cookie, u8 manager)
{
- return !!le32_get_bits(desc->u.wcn7850.msdu_end.info13,
- RX_MSDU_END_INFO13_TCP_UDP_CKSUM_FAIL);
+ hal->ops->rx_buf_addr_info_set(binfo, paddr, cookie, manager);
}
-static bool ath12k_hw_wcn7850_dp_rx_h_ip_cksum_fail(struct hal_rx_desc *desc)
+void ath12k_hal_rx_buf_addr_info_get(struct ath12k_hal *hal,
+ struct ath12k_buffer_addr *binfo,
+ dma_addr_t *paddr, u32 *msdu_cookies,
+ u8 *rbm)
{
- return !!le32_get_bits(desc->u.wcn7850.msdu_end.info13,
- RX_MSDU_END_INFO13_IP_CKSUM_FAIL);
+ hal->ops->rx_buf_addr_info_get(binfo, paddr, msdu_cookies, rbm);
}
-static bool ath12k_hw_wcn7850_dp_rx_h_is_decrypted(struct hal_rx_desc *desc)
+void ath12k_hal_rx_msdu_list_get(struct ath12k_hal *hal, struct ath12k *ar,
+ void *link_desc,
+ void *msdu_list,
+ u16 *num_msdus)
{
- return (le32_get_bits(desc->u.wcn7850.msdu_end.info14,
- RX_MSDU_END_INFO14_DECRYPT_STATUS_CODE) ==
- RX_DESC_DECRYPT_STATUS_CODE_OK);
+ hal->ops->rx_msdu_list_get(ar, link_desc, msdu_list, num_msdus);
}
-static u32 ath12k_hw_wcn7850_dp_rx_h_mpdu_err(struct hal_rx_desc *desc)
+void ath12k_hal_rx_reo_ent_buf_paddr_get(struct ath12k_hal *hal, void *rx_desc,
+ dma_addr_t *paddr,
+ u32 *sw_cookie,
+ struct ath12k_buffer_addr **pp_buf_addr,
+ u8 *rbm, u32 *msdu_cnt)
{
- u32 info = __le32_to_cpu(desc->u.wcn7850.msdu_end.info13);
- u32 errmap = 0;
-
- if (info & RX_MSDU_END_INFO13_FCS_ERR)
- errmap |= HAL_RX_MPDU_ERR_FCS;
-
- if (info & RX_MSDU_END_INFO13_DECRYPT_ERR)
- errmap |= HAL_RX_MPDU_ERR_DECRYPT;
-
- if (info & RX_MSDU_END_INFO13_TKIP_MIC_ERR)
- errmap |= HAL_RX_MPDU_ERR_TKIP_MIC;
-
- if (info & RX_MSDU_END_INFO13_A_MSDU_ERROR)
- errmap |= HAL_RX_MPDU_ERR_AMSDU_ERR;
-
- if (info & RX_MSDU_END_INFO13_OVERFLOW_ERR)
- errmap |= HAL_RX_MPDU_ERR_OVERFLOW;
-
- if (info & RX_MSDU_END_INFO13_MSDU_LEN_ERR)
- errmap |= HAL_RX_MPDU_ERR_MSDU_LEN;
-
- if (info & RX_MSDU_END_INFO13_MPDU_LEN_ERR)
- errmap |= HAL_RX_MPDU_ERR_MPDU_LEN;
-
- return errmap;
+ hal->ops->rx_reo_ent_buf_paddr_get(rx_desc, paddr, sw_cookie,
+ pp_buf_addr, rbm, msdu_cnt);
}
-static u32 ath12k_hw_wcn7850_get_rx_desc_size(void)
+void ath12k_hal_cc_config(struct ath12k_base *ab)
{
- return sizeof(struct hal_rx_desc_wcn7850);
+ ab->hal.ops->cc_config(ab);
}
-static u8 ath12k_hw_wcn7850_rx_desc_get_msdu_src_link(struct hal_rx_desc *desc)
+enum hal_rx_buf_return_buf_manager
+ath12k_hal_get_idle_link_rbm(struct ath12k_hal *hal, u8 device_id)
{
- return 0;
+ return hal->ops->get_idle_link_rbm(hal, device_id);
}
-const struct hal_rx_ops hal_rx_wcn7850_ops = {
- .rx_desc_get_first_msdu = ath12k_hw_wcn7850_rx_desc_get_first_msdu,
- .rx_desc_get_last_msdu = ath12k_hw_wcn7850_rx_desc_get_last_msdu,
- .rx_desc_get_l3_pad_bytes = ath12k_hw_wcn7850_rx_desc_get_l3_pad_bytes,
- .rx_desc_encrypt_valid = ath12k_hw_wcn7850_rx_desc_encrypt_valid,
- .rx_desc_get_encrypt_type = ath12k_hw_wcn7850_rx_desc_get_encrypt_type,
- .rx_desc_get_decap_type = ath12k_hw_wcn7850_rx_desc_get_decap_type,
- .rx_desc_get_mesh_ctl = ath12k_hw_wcn7850_rx_desc_get_mesh_ctl,
- .rx_desc_get_mpdu_seq_ctl_vld = ath12k_hw_wcn7850_rx_desc_get_mpdu_seq_ctl_vld,
- .rx_desc_get_mpdu_fc_valid = ath12k_hw_wcn7850_rx_desc_get_mpdu_fc_valid,
- .rx_desc_get_mpdu_start_seq_no = ath12k_hw_wcn7850_rx_desc_get_mpdu_start_seq_no,
- .rx_desc_get_msdu_len = ath12k_hw_wcn7850_rx_desc_get_msdu_len,
- .rx_desc_get_msdu_sgi = ath12k_hw_wcn7850_rx_desc_get_msdu_sgi,
- .rx_desc_get_msdu_rate_mcs = ath12k_hw_wcn7850_rx_desc_get_msdu_rate_mcs,
- .rx_desc_get_msdu_rx_bw = ath12k_hw_wcn7850_rx_desc_get_msdu_rx_bw,
- .rx_desc_get_msdu_freq = ath12k_hw_wcn7850_rx_desc_get_msdu_freq,
- .rx_desc_get_msdu_pkt_type = ath12k_hw_wcn7850_rx_desc_get_msdu_pkt_type,
- .rx_desc_get_msdu_nss = ath12k_hw_wcn7850_rx_desc_get_msdu_nss,
- .rx_desc_get_mpdu_tid = ath12k_hw_wcn7850_rx_desc_get_mpdu_tid,
- .rx_desc_get_mpdu_peer_id = ath12k_hw_wcn7850_rx_desc_get_mpdu_peer_id,
- .rx_desc_copy_end_tlv = ath12k_hw_wcn7850_rx_desc_copy_end_tlv,
- .rx_desc_get_mpdu_start_tag = ath12k_hw_wcn7850_rx_desc_get_mpdu_start_tag,
- .rx_desc_get_mpdu_ppdu_id = ath12k_hw_wcn7850_rx_desc_get_mpdu_ppdu_id,
- .rx_desc_set_msdu_len = ath12k_hw_wcn7850_rx_desc_set_msdu_len,
- .rx_desc_get_msdu_payload = ath12k_hw_wcn7850_rx_desc_get_msdu_payload,
- .rx_desc_get_mpdu_start_offset = ath12k_hw_wcn7850_rx_desc_get_mpdu_start_offset,
- .rx_desc_get_msdu_end_offset = ath12k_hw_wcn7850_rx_desc_get_msdu_end_offset,
- .rx_desc_mac_addr2_valid = ath12k_hw_wcn7850_rx_desc_mac_addr2_valid,
- .rx_desc_mpdu_start_addr2 = ath12k_hw_wcn7850_rx_desc_mpdu_start_addr2,
- .rx_desc_is_da_mcbc = ath12k_hw_wcn7850_rx_desc_is_da_mcbc,
- .rx_desc_get_dot11_hdr = ath12k_hw_wcn7850_rx_desc_get_dot11_hdr,
- .rx_desc_get_crypto_header = ath12k_hw_wcn7850_rx_desc_get_crypto_hdr,
- .dp_rx_h_msdu_done = ath12k_hw_wcn7850_dp_rx_h_msdu_done,
- .dp_rx_h_l4_cksum_fail = ath12k_hw_wcn7850_dp_rx_h_l4_cksum_fail,
- .dp_rx_h_ip_cksum_fail = ath12k_hw_wcn7850_dp_rx_h_ip_cksum_fail,
- .dp_rx_h_is_decrypted = ath12k_hw_wcn7850_dp_rx_h_is_decrypted,
- .dp_rx_h_mpdu_err = ath12k_hw_wcn7850_dp_rx_h_mpdu_err,
- .rx_desc_get_desc_size = ath12k_hw_wcn7850_get_rx_desc_size,
- .rx_desc_get_msdu_src_link_id = ath12k_hw_wcn7850_rx_desc_get_msdu_src_link,
-};
-
-const struct hal_ops hal_wcn7850_ops = {
- .create_srng_config = ath12k_hal_srng_create_config_wcn7850,
- .tcl_to_wbm_rbm_map = ath12k_hal_wcn7850_tcl_to_wbm_rbm_map,
- .rxdma_ring_wmask_rx_mpdu_start = NULL,
- .rxdma_ring_wmask_rx_msdu_end = NULL,
- .get_hal_rx_compact_ops = NULL,
-};
-
-static int ath12k_hal_alloc_cont_rdp(struct ath12k_base *ab)
+static int ath12k_hal_alloc_cont_rdp(struct ath12k_hal *hal)
{
- struct ath12k_hal *hal = &ab->hal;
size_t size;
size = sizeof(u32) * HAL_SRNG_RING_ID_MAX;
- hal->rdp.vaddr = dma_alloc_coherent(ab->dev, size, &hal->rdp.paddr,
+ hal->rdp.vaddr = dma_alloc_coherent(hal->dev, size, &hal->rdp.paddr,
GFP_KERNEL);
if (!hal->rdp.vaddr)
return -ENOMEM;
@@ -1575,27 +164,25 @@ static int ath12k_hal_alloc_cont_rdp(struct ath12k_base *ab)
return 0;
}
-static void ath12k_hal_free_cont_rdp(struct ath12k_base *ab)
+static void ath12k_hal_free_cont_rdp(struct ath12k_hal *hal)
{
- struct ath12k_hal *hal = &ab->hal;
size_t size;
if (!hal->rdp.vaddr)
return;
size = sizeof(u32) * HAL_SRNG_RING_ID_MAX;
- dma_free_coherent(ab->dev, size,
+ dma_free_coherent(hal->dev, size,
hal->rdp.vaddr, hal->rdp.paddr);
hal->rdp.vaddr = NULL;
}
-static int ath12k_hal_alloc_cont_wrp(struct ath12k_base *ab)
+static int ath12k_hal_alloc_cont_wrp(struct ath12k_hal *hal)
{
- struct ath12k_hal *hal = &ab->hal;
size_t size;
size = sizeof(u32) * (HAL_SRNG_NUM_PMAC_RINGS + HAL_SRNG_NUM_DMAC_RINGS);
- hal->wrp.vaddr = dma_alloc_coherent(ab->dev, size, &hal->wrp.paddr,
+ hal->wrp.vaddr = dma_alloc_coherent(hal->dev, size, &hal->wrp.paddr,
GFP_KERNEL);
if (!hal->wrp.vaddr)
return -ENOMEM;
@@ -1603,209 +190,19 @@ static int ath12k_hal_alloc_cont_wrp(struct ath12k_base *ab)
return 0;
}
-static void ath12k_hal_free_cont_wrp(struct ath12k_base *ab)
+static void ath12k_hal_free_cont_wrp(struct ath12k_hal *hal)
{
- struct ath12k_hal *hal = &ab->hal;
size_t size;
if (!hal->wrp.vaddr)
return;
size = sizeof(u32) * (HAL_SRNG_NUM_PMAC_RINGS + HAL_SRNG_NUM_DMAC_RINGS);
- dma_free_coherent(ab->dev, size,
+ dma_free_coherent(hal->dev, size,
hal->wrp.vaddr, hal->wrp.paddr);
hal->wrp.vaddr = NULL;
}
-static void ath12k_hal_ce_dst_setup(struct ath12k_base *ab,
- struct hal_srng *srng, int ring_num)
-{
- struct hal_srng_config *srng_config = &ab->hal.srng_config[HAL_CE_DST];
- u32 addr;
- u32 val;
-
- addr = HAL_CE_DST_RING_CTRL +
- srng_config->reg_start[HAL_SRNG_REG_GRP_R0] +
- ring_num * srng_config->reg_size[HAL_SRNG_REG_GRP_R0];
-
- val = ath12k_hif_read32(ab, addr);
- val &= ~HAL_CE_DST_R0_DEST_CTRL_MAX_LEN;
- val |= u32_encode_bits(srng->u.dst_ring.max_buffer_length,
- HAL_CE_DST_R0_DEST_CTRL_MAX_LEN);
- ath12k_hif_write32(ab, addr, val);
-}
-
-static void ath12k_hal_srng_dst_hw_init(struct ath12k_base *ab,
- struct hal_srng *srng)
-{
- struct ath12k_hal *hal = &ab->hal;
- u32 val;
- u64 hp_addr;
- u32 reg_base;
-
- reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0];
-
- if (srng->flags & HAL_SRNG_FLAGS_MSI_INTR) {
- ath12k_hif_write32(ab, reg_base +
- ath12k_hal_reo1_ring_msi1_base_lsb_offset(ab),
- srng->msi_addr);
-
- val = u32_encode_bits(((u64)srng->msi_addr >> HAL_ADDR_MSB_REG_SHIFT),
- HAL_REO1_RING_MSI1_BASE_MSB_ADDR) |
- HAL_REO1_RING_MSI1_BASE_MSB_MSI1_ENABLE;
- ath12k_hif_write32(ab, reg_base +
- ath12k_hal_reo1_ring_msi1_base_msb_offset(ab), val);
-
- ath12k_hif_write32(ab,
- reg_base + ath12k_hal_reo1_ring_msi1_data_offset(ab),
- srng->msi_data);
- }
-
- ath12k_hif_write32(ab, reg_base, srng->ring_base_paddr);
-
- val = u32_encode_bits(((u64)srng->ring_base_paddr >> HAL_ADDR_MSB_REG_SHIFT),
- HAL_REO1_RING_BASE_MSB_RING_BASE_ADDR_MSB) |
- u32_encode_bits((srng->entry_size * srng->num_entries),
- HAL_REO1_RING_BASE_MSB_RING_SIZE);
- ath12k_hif_write32(ab, reg_base + ath12k_hal_reo1_ring_base_msb_offset(ab), val);
-
- val = u32_encode_bits(srng->ring_id, HAL_REO1_RING_ID_RING_ID) |
- u32_encode_bits(srng->entry_size, HAL_REO1_RING_ID_ENTRY_SIZE);
- ath12k_hif_write32(ab, reg_base + ath12k_hal_reo1_ring_id_offset(ab), val);
-
- /* interrupt setup */
- val = u32_encode_bits((srng->intr_timer_thres_us >> 3),
- HAL_REO1_RING_PRDR_INT_SETUP_INTR_TMR_THOLD);
-
- val |= u32_encode_bits((srng->intr_batch_cntr_thres_entries * srng->entry_size),
- HAL_REO1_RING_PRDR_INT_SETUP_BATCH_COUNTER_THOLD);
-
- ath12k_hif_write32(ab,
- reg_base + ath12k_hal_reo1_ring_producer_int_setup_offset(ab),
- val);
-
- hp_addr = hal->rdp.paddr +
- ((unsigned long)srng->u.dst_ring.hp_addr -
- (unsigned long)hal->rdp.vaddr);
- ath12k_hif_write32(ab, reg_base + ath12k_hal_reo1_ring_hp_addr_lsb_offset(ab),
- hp_addr & HAL_ADDR_LSB_REG_MASK);
- ath12k_hif_write32(ab, reg_base + ath12k_hal_reo1_ring_hp_addr_msb_offset(ab),
- hp_addr >> HAL_ADDR_MSB_REG_SHIFT);
-
- /* Initialize head and tail pointers to indicate ring is empty */
- reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R2];
- ath12k_hif_write32(ab, reg_base, 0);
- ath12k_hif_write32(ab, reg_base + HAL_REO1_RING_TP_OFFSET, 0);
- *srng->u.dst_ring.hp_addr = 0;
-
- reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0];
- val = 0;
- if (srng->flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP)
- val |= HAL_REO1_RING_MISC_DATA_TLV_SWAP;
- if (srng->flags & HAL_SRNG_FLAGS_RING_PTR_SWAP)
- val |= HAL_REO1_RING_MISC_HOST_FW_SWAP;
- if (srng->flags & HAL_SRNG_FLAGS_MSI_SWAP)
- val |= HAL_REO1_RING_MISC_MSI_SWAP;
- val |= HAL_REO1_RING_MISC_SRNG_ENABLE;
-
- ath12k_hif_write32(ab, reg_base + ath12k_hal_reo1_ring_misc_offset(ab), val);
-}
-
-static void ath12k_hal_srng_src_hw_init(struct ath12k_base *ab,
- struct hal_srng *srng)
-{
- struct ath12k_hal *hal = &ab->hal;
- u32 val;
- u64 tp_addr;
- u32 reg_base;
-
- reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0];
-
- if (srng->flags & HAL_SRNG_FLAGS_MSI_INTR) {
- ath12k_hif_write32(ab, reg_base +
- HAL_TCL1_RING_MSI1_BASE_LSB_OFFSET(ab),
- srng->msi_addr);
-
- val = u32_encode_bits(((u64)srng->msi_addr >> HAL_ADDR_MSB_REG_SHIFT),
- HAL_TCL1_RING_MSI1_BASE_MSB_ADDR) |
- HAL_TCL1_RING_MSI1_BASE_MSB_MSI1_ENABLE;
- ath12k_hif_write32(ab, reg_base +
- HAL_TCL1_RING_MSI1_BASE_MSB_OFFSET(ab),
- val);
-
- ath12k_hif_write32(ab, reg_base +
- HAL_TCL1_RING_MSI1_DATA_OFFSET(ab),
- srng->msi_data);
- }
-
- ath12k_hif_write32(ab, reg_base, srng->ring_base_paddr);
-
- val = u32_encode_bits(((u64)srng->ring_base_paddr >> HAL_ADDR_MSB_REG_SHIFT),
- HAL_TCL1_RING_BASE_MSB_RING_BASE_ADDR_MSB) |
- u32_encode_bits((srng->entry_size * srng->num_entries),
- HAL_TCL1_RING_BASE_MSB_RING_SIZE);
- ath12k_hif_write32(ab, reg_base + HAL_TCL1_RING_BASE_MSB_OFFSET(ab), val);
-
- val = u32_encode_bits(srng->entry_size, HAL_REO1_RING_ID_ENTRY_SIZE);
- ath12k_hif_write32(ab, reg_base + HAL_TCL1_RING_ID_OFFSET(ab), val);
-
- val = u32_encode_bits(srng->intr_timer_thres_us,
- HAL_TCL1_RING_CONSR_INT_SETUP_IX0_INTR_TMR_THOLD);
-
- val |= u32_encode_bits((srng->intr_batch_cntr_thres_entries * srng->entry_size),
- HAL_TCL1_RING_CONSR_INT_SETUP_IX0_BATCH_COUNTER_THOLD);
-
- ath12k_hif_write32(ab,
- reg_base + HAL_TCL1_RING_CONSR_INT_SETUP_IX0_OFFSET(ab),
- val);
-
- val = 0;
- if (srng->flags & HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN) {
- val |= u32_encode_bits(srng->u.src_ring.low_threshold,
- HAL_TCL1_RING_CONSR_INT_SETUP_IX1_LOW_THOLD);
- }
- ath12k_hif_write32(ab,
- reg_base + HAL_TCL1_RING_CONSR_INT_SETUP_IX1_OFFSET(ab),
- val);
-
- if (srng->ring_id != HAL_SRNG_RING_ID_WBM_IDLE_LINK) {
- tp_addr = hal->rdp.paddr +
- ((unsigned long)srng->u.src_ring.tp_addr -
- (unsigned long)hal->rdp.vaddr);
- ath12k_hif_write32(ab,
- reg_base + HAL_TCL1_RING_TP_ADDR_LSB_OFFSET(ab),
- tp_addr & HAL_ADDR_LSB_REG_MASK);
- ath12k_hif_write32(ab,
- reg_base + HAL_TCL1_RING_TP_ADDR_MSB_OFFSET(ab),
- tp_addr >> HAL_ADDR_MSB_REG_SHIFT);
- }
-
- /* Initialize head and tail pointers to indicate ring is empty */
- reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R2];
- ath12k_hif_write32(ab, reg_base, 0);
- ath12k_hif_write32(ab, reg_base + HAL_TCL1_RING_TP_OFFSET, 0);
- *srng->u.src_ring.tp_addr = 0;
-
- reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0];
- val = 0;
- if (srng->flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP)
- val |= HAL_TCL1_RING_MISC_DATA_TLV_SWAP;
- if (srng->flags & HAL_SRNG_FLAGS_RING_PTR_SWAP)
- val |= HAL_TCL1_RING_MISC_HOST_FW_SWAP;
- if (srng->flags & HAL_SRNG_FLAGS_MSI_SWAP)
- val |= HAL_TCL1_RING_MISC_MSI_SWAP;
-
- /* Loop count is not used for SRC rings */
- val |= HAL_TCL1_RING_MISC_MSI_LOOPCNT_DISABLE;
-
- val |= HAL_TCL1_RING_MISC_SRNG_ENABLE;
-
- if (srng->ring_id == HAL_SRNG_RING_ID_WBM_IDLE_LINK)
- val |= HAL_TCL1_RING_MISC_MSI_RING_ID_DISABLE;
-
- ath12k_hif_write32(ab, reg_base + HAL_TCL1_RING_MISC_OFFSET(ab), val);
-}
-
static void ath12k_hal_srng_hw_init(struct ath12k_base *ab,
struct hal_srng *srng)
{
@@ -1815,28 +212,6 @@ static void ath12k_hal_srng_hw_init(struct ath12k_base *ab,
ath12k_hal_srng_dst_hw_init(ab, srng);
}
-static int ath12k_hal_srng_get_ring_id(struct ath12k_base *ab,
- enum hal_ring_type type,
- int ring_num, int mac_id)
-{
- struct hal_srng_config *srng_config = &ab->hal.srng_config[type];
- int ring_id;
-
- if (ring_num >= srng_config->max_rings) {
- ath12k_warn(ab, "invalid ring number :%d\n", ring_num);
- return -EINVAL;
- }
-
- ring_id = srng_config->start_ring_id + ring_num;
- if (srng_config->mac_type == ATH12K_HAL_SRNG_PMAC)
- ring_id += mac_id * HAL_SRNG_RINGS_PER_PMAC;
-
- if (WARN_ON(ring_id >= HAL_SRNG_RING_ID_MAX))
- return -EINVAL;
-
- return ring_id;
-}
-
int ath12k_hal_srng_get_entrysize(struct ath12k_base *ab, u32 ring_type)
{
struct hal_srng_config *srng_config;
@@ -1848,6 +223,7 @@ int ath12k_hal_srng_get_entrysize(struct ath12k_base *ab, u32 ring_type)
return (srng_config->entry_size << 2);
}
+EXPORT_SYMBOL(ath12k_hal_srng_get_entrysize);
int ath12k_hal_srng_get_max_entries(struct ath12k_base *ab, u32 ring_type)
{
@@ -1877,6 +253,7 @@ void ath12k_hal_srng_get_params(struct ath12k_base *ab, struct hal_srng *srng,
params->msi2_data = srng->msi2_data;
params->flags = srng->flags;
}
+EXPORT_SYMBOL(ath12k_hal_srng_get_params);
dma_addr_t ath12k_hal_srng_get_hp_addr(struct ath12k_base *ab,
struct hal_srng *srng)
@@ -1910,63 +287,32 @@ dma_addr_t ath12k_hal_srng_get_tp_addr(struct ath12k_base *ab,
(unsigned long)ab->hal.wrp.vaddr);
}
-u32 ath12k_hal_ce_get_desc_size(enum hal_ce_desc type)
-{
- switch (type) {
- case HAL_CE_DESC_SRC:
- return sizeof(struct hal_ce_srng_src_desc);
- case HAL_CE_DESC_DST:
- return sizeof(struct hal_ce_srng_dest_desc);
- case HAL_CE_DESC_DST_STATUS:
- return sizeof(struct hal_ce_srng_dst_status_desc);
- }
-
- return 0;
-}
-
-void ath12k_hal_ce_src_set_desc(struct hal_ce_srng_src_desc *desc, dma_addr_t paddr,
- u32 len, u32 id, u8 byte_swap_data)
+void ath12k_hal_ce_src_set_desc(struct ath12k_hal *hal,
+ struct hal_ce_srng_src_desc *desc,
+ dma_addr_t paddr, u32 len, u32 id,
+ u8 byte_swap_data)
{
- desc->buffer_addr_low = cpu_to_le32(paddr & HAL_ADDR_LSB_REG_MASK);
- desc->buffer_addr_info =
- le32_encode_bits(((u64)paddr >> HAL_ADDR_MSB_REG_SHIFT),
- HAL_CE_SRC_DESC_ADDR_INFO_ADDR_HI) |
- le32_encode_bits(byte_swap_data,
- HAL_CE_SRC_DESC_ADDR_INFO_BYTE_SWAP) |
- le32_encode_bits(0, HAL_CE_SRC_DESC_ADDR_INFO_GATHER) |
- le32_encode_bits(len, HAL_CE_SRC_DESC_ADDR_INFO_LEN);
- desc->meta_info = le32_encode_bits(id, HAL_CE_SRC_DESC_META_INFO_DATA);
+ hal->ops->ce_src_set_desc(desc, paddr, len, id, byte_swap_data);
}
-void ath12k_hal_ce_dst_set_desc(struct hal_ce_srng_dest_desc *desc, dma_addr_t paddr)
+void ath12k_hal_ce_dst_set_desc(struct ath12k_hal *hal,
+ struct hal_ce_srng_dest_desc *desc,
+ dma_addr_t paddr)
{
- desc->buffer_addr_low = cpu_to_le32(paddr & HAL_ADDR_LSB_REG_MASK);
- desc->buffer_addr_info =
- le32_encode_bits(((u64)paddr >> HAL_ADDR_MSB_REG_SHIFT),
- HAL_CE_DEST_DESC_ADDR_INFO_ADDR_HI);
+ hal->ops->ce_dst_set_desc(desc, paddr);
}
-u32 ath12k_hal_ce_dst_status_get_length(struct hal_ce_srng_dst_status_desc *desc)
+u32 ath12k_hal_ce_dst_status_get_length(struct ath12k_hal *hal,
+ struct hal_ce_srng_dst_status_desc *desc)
{
- u32 len;
-
- len = le32_get_bits(desc->flags, HAL_CE_DST_STATUS_DESC_FLAGS_LEN);
- desc->flags &= ~cpu_to_le32(HAL_CE_DST_STATUS_DESC_FLAGS_LEN);
-
- return len;
+ return hal->ops->ce_dst_status_get_length(desc);
}
-void ath12k_hal_set_link_desc_addr(struct hal_wbm_link_desc *desc, u32 cookie,
- dma_addr_t paddr,
- enum hal_rx_buf_return_buf_manager rbm)
+void ath12k_hal_set_link_desc_addr(struct ath12k_hal *hal,
+ struct hal_wbm_link_desc *desc, u32 cookie,
+ dma_addr_t paddr, int rbm)
{
- desc->buf_addr_info.info0 = le32_encode_bits((paddr & HAL_ADDR_LSB_REG_MASK),
- BUFFER_ADDR_INFO0_ADDR);
- desc->buf_addr_info.info1 =
- le32_encode_bits(((u64)paddr >> HAL_ADDR_MSB_REG_SHIFT),
- BUFFER_ADDR_INFO1_ADDR) |
- le32_encode_bits(rbm, BUFFER_ADDR_INFO1_RET_BUF_MGR) |
- le32_encode_bits(cookie, BUFFER_ADDR_INFO1_SW_COOKIE);
+ hal->ops->set_link_desc_addr(desc, cookie, paddr, rbm);
}
void *ath12k_hal_srng_dst_peek(struct ath12k_base *ab, struct hal_srng *srng)
@@ -1978,6 +324,7 @@ void *ath12k_hal_srng_dst_peek(struct ath12k_base *ab, struct hal_srng *srng)
return NULL;
}
+EXPORT_SYMBOL(ath12k_hal_srng_dst_peek);
void *ath12k_hal_srng_dst_get_next_entry(struct ath12k_base *ab,
struct hal_srng *srng)
@@ -1996,6 +343,7 @@ void *ath12k_hal_srng_dst_get_next_entry(struct ath12k_base *ab,
return desc;
}
+EXPORT_SYMBOL(ath12k_hal_srng_dst_get_next_entry);
int ath12k_hal_srng_dst_num_free(struct ath12k_base *ab, struct hal_srng *srng,
bool sync_hw_ptr)
@@ -2018,6 +366,7 @@ int ath12k_hal_srng_dst_num_free(struct ath12k_base *ab, struct hal_srng *srng,
else
return (srng->ring_size - tp + hp) / srng->entry_size;
}
+EXPORT_SYMBOL(ath12k_hal_srng_dst_num_free);
/* Returns number of available entries in src ring */
int ath12k_hal_srng_src_num_free(struct ath12k_base *ab, struct hal_srng *srng,
@@ -2059,6 +408,7 @@ void *ath12k_hal_srng_src_next_peek(struct ath12k_base *ab,
return desc;
}
+EXPORT_SYMBOL(ath12k_hal_srng_src_next_peek);
void *ath12k_hal_srng_src_get_next_entry(struct ath12k_base *ab,
struct hal_srng *srng)
@@ -2092,6 +442,7 @@ void *ath12k_hal_srng_src_get_next_entry(struct ath12k_base *ab,
return desc;
}
+EXPORT_SYMBOL(ath12k_hal_srng_src_get_next_entry);
void *ath12k_hal_srng_src_peek(struct ath12k_base *ab, struct hal_srng *srng)
{
@@ -2103,6 +454,7 @@ void *ath12k_hal_srng_src_peek(struct ath12k_base *ab, struct hal_srng *srng)
return srng->ring_base_vaddr + srng->u.src_ring.hp;
}
+EXPORT_SYMBOL(ath12k_hal_srng_src_peek);
void *ath12k_hal_srng_src_reap_next(struct ath12k_base *ab,
struct hal_srng *srng)
@@ -2162,6 +514,7 @@ void ath12k_hal_srng_access_begin(struct ath12k_base *ab, struct hal_srng *srng)
}
}
}
+EXPORT_SYMBOL(ath12k_hal_srng_access_begin);
/* Update cached ring head/tail pointers to HW. ath12k_hal_srng_access_begin()
* should have been called before this.
@@ -2217,112 +570,7 @@ void ath12k_hal_srng_access_end(struct ath12k_base *ab, struct hal_srng *srng)
srng->timestamp = jiffies;
}
-
-void ath12k_hal_setup_link_idle_list(struct ath12k_base *ab,
- struct hal_wbm_idle_scatter_list *sbuf,
- u32 nsbufs, u32 tot_link_desc,
- u32 end_offset)
-{
- struct ath12k_buffer_addr *link_addr;
- int i;
- u32 reg_scatter_buf_sz = HAL_WBM_IDLE_SCATTER_BUF_SIZE / 64;
- u32 val;
-
- link_addr = (void *)sbuf[0].vaddr + HAL_WBM_IDLE_SCATTER_BUF_SIZE;
-
- for (i = 1; i < nsbufs; i++) {
- link_addr->info0 = cpu_to_le32(sbuf[i].paddr & HAL_ADDR_LSB_REG_MASK);
-
- link_addr->info1 =
- le32_encode_bits((u64)sbuf[i].paddr >> HAL_ADDR_MSB_REG_SHIFT,
- HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32) |
- le32_encode_bits(BASE_ADDR_MATCH_TAG_VAL,
- HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_MATCH_TAG);
-
- link_addr = (void *)sbuf[i].vaddr +
- HAL_WBM_IDLE_SCATTER_BUF_SIZE;
- }
-
- val = u32_encode_bits(reg_scatter_buf_sz, HAL_WBM_SCATTER_BUFFER_SIZE) |
- u32_encode_bits(0x1, HAL_WBM_LINK_DESC_IDLE_LIST_MODE);
-
- ath12k_hif_write32(ab,
- HAL_SEQ_WCSS_UMAC_WBM_REG +
- HAL_WBM_R0_IDLE_LIST_CONTROL_ADDR(ab),
- val);
-
- val = u32_encode_bits(reg_scatter_buf_sz * nsbufs,
- HAL_WBM_SCATTER_RING_SIZE_OF_IDLE_LINK_DESC_LIST);
- ath12k_hif_write32(ab,
- HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_R0_IDLE_LIST_SIZE_ADDR(ab),
- val);
-
- val = u32_encode_bits(sbuf[0].paddr & HAL_ADDR_LSB_REG_MASK,
- BUFFER_ADDR_INFO0_ADDR);
- ath12k_hif_write32(ab,
- HAL_SEQ_WCSS_UMAC_WBM_REG +
- HAL_WBM_SCATTERED_RING_BASE_LSB(ab),
- val);
-
- val = u32_encode_bits(BASE_ADDR_MATCH_TAG_VAL,
- HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_MATCH_TAG) |
- u32_encode_bits((u64)sbuf[0].paddr >> HAL_ADDR_MSB_REG_SHIFT,
- HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32);
- ath12k_hif_write32(ab,
- HAL_SEQ_WCSS_UMAC_WBM_REG +
- HAL_WBM_SCATTERED_RING_BASE_MSB(ab),
- val);
-
- /* Setup head and tail pointers for the idle list */
- val = u32_encode_bits(sbuf[nsbufs - 1].paddr, BUFFER_ADDR_INFO0_ADDR);
- ath12k_hif_write32(ab,
- HAL_SEQ_WCSS_UMAC_WBM_REG +
- HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX0(ab),
- val);
-
- val = u32_encode_bits(((u64)sbuf[nsbufs - 1].paddr >> HAL_ADDR_MSB_REG_SHIFT),
- HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32) |
- u32_encode_bits((end_offset >> 2),
- HAL_WBM_SCATTERED_DESC_HEAD_P_OFFSET_IX1);
- ath12k_hif_write32(ab,
- HAL_SEQ_WCSS_UMAC_WBM_REG +
- HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX1(ab),
- val);
-
- val = u32_encode_bits(sbuf[0].paddr, BUFFER_ADDR_INFO0_ADDR);
- ath12k_hif_write32(ab,
- HAL_SEQ_WCSS_UMAC_WBM_REG +
- HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX0(ab),
- val);
-
- val = u32_encode_bits(sbuf[0].paddr, BUFFER_ADDR_INFO0_ADDR);
- ath12k_hif_write32(ab,
- HAL_SEQ_WCSS_UMAC_WBM_REG +
- HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX0(ab),
- val);
-
- val = u32_encode_bits(((u64)sbuf[0].paddr >> HAL_ADDR_MSB_REG_SHIFT),
- HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32) |
- u32_encode_bits(0, HAL_WBM_SCATTERED_DESC_TAIL_P_OFFSET_IX1);
- ath12k_hif_write32(ab,
- HAL_SEQ_WCSS_UMAC_WBM_REG +
- HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX1(ab),
- val);
-
- val = 2 * tot_link_desc;
- ath12k_hif_write32(ab,
- HAL_SEQ_WCSS_UMAC_WBM_REG +
- HAL_WBM_SCATTERED_DESC_PTR_HP_ADDR(ab),
- val);
-
- /* Enable the SRNG */
- val = u32_encode_bits(1, HAL_WBM_IDLE_LINK_RING_MISC_SRNG_ENABLE) |
- u32_encode_bits(1, HAL_WBM_IDLE_LINK_RING_MISC_RIND_ID_DISABLE);
- ath12k_hif_write32(ab,
- HAL_SEQ_WCSS_UMAC_WBM_REG +
- HAL_WBM_IDLE_LINK_RING_MISC_ADDR(ab),
- val);
-}
+EXPORT_SYMBOL(ath12k_hal_srng_access_end);
int ath12k_hal_srng_setup(struct ath12k_base *ab, enum hal_ring_type type,
int ring_num, int mac_id,
@@ -2334,9 +582,8 @@ int ath12k_hal_srng_setup(struct ath12k_base *ab, enum hal_ring_type type,
int ring_id;
u32 idx;
int i;
- u32 reg_base;
- ring_id = ath12k_hal_srng_get_ring_id(ab, type, ring_num, mac_id);
+ ring_id = ath12k_hal_srng_get_ring_id(hal, type, ring_num, mac_id);
if (ring_id < 0)
return ring_id;
@@ -2369,8 +616,6 @@ int ath12k_hal_srng_setup(struct ath12k_base *ab, enum hal_ring_type type,
memset(srng->ring_base_vaddr, 0,
(srng->entry_size * srng->num_entries) << 2);
- reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R2];
-
if (srng->ring_dir == HAL_SRNG_DIR_SRC) {
srng->u.src_ring.hp = 0;
srng->u.src_ring.cached_tp = 0;
@@ -2379,16 +624,7 @@ int ath12k_hal_srng_setup(struct ath12k_base *ab, enum hal_ring_type type,
srng->u.src_ring.low_threshold = params->low_threshold *
srng->entry_size;
if (srng_config->mac_type == ATH12K_HAL_SRNG_UMAC) {
- if (!ab->hw_params->supports_shadow_regs)
- srng->u.src_ring.hp_addr =
- (u32 *)((unsigned long)ab->mem + reg_base);
- else
- ath12k_dbg(ab, ATH12K_DBG_HAL,
- "hal type %d ring_num %d reg_base 0x%x shadow 0x%lx\n",
- type, ring_num,
- reg_base,
- (unsigned long)srng->u.src_ring.hp_addr -
- (unsigned long)ab->mem);
+ ath12k_hal_set_umac_srng_ptr_addr(ab, srng);
} else {
idx = ring_id - HAL_SRNG_RING_ID_DMAC_CMN_ID_START;
srng->u.src_ring.hp_addr = (void *)(hal->wrp.vaddr +
@@ -2409,17 +645,7 @@ int ath12k_hal_srng_setup(struct ath12k_base *ab, enum hal_ring_type type,
srng->u.dst_ring.cached_hp = 0;
srng->u.dst_ring.hp_addr = (void *)(hal->rdp.vaddr + ring_id);
if (srng_config->mac_type == ATH12K_HAL_SRNG_UMAC) {
- if (!ab->hw_params->supports_shadow_regs)
- srng->u.dst_ring.tp_addr =
- (u32 *)((unsigned long)ab->mem + reg_base +
- (HAL_REO1_RING_TP - HAL_REO1_RING_HP));
- else
- ath12k_dbg(ab, ATH12K_DBG_HAL,
- "type %d ring_num %d target_reg 0x%x shadow 0x%lx\n",
- type, ring_num,
- reg_base + HAL_REO1_RING_TP - HAL_REO1_RING_HP,
- (unsigned long)srng->u.dst_ring.tp_addr -
- (unsigned long)ab->mem);
+ ath12k_hal_set_umac_srng_ptr_addr(ab, srng);
} else {
/* For PMAC & DMAC rings, tail pointer updates will be done
* through FW by writing to a shared memory location
@@ -2444,68 +670,6 @@ int ath12k_hal_srng_setup(struct ath12k_base *ab, enum hal_ring_type type,
return ring_id;
}
-static void ath12k_hal_srng_update_hp_tp_addr(struct ath12k_base *ab,
- int shadow_cfg_idx,
- enum hal_ring_type ring_type,
- int ring_num)
-{
- struct hal_srng *srng;
- struct ath12k_hal *hal = &ab->hal;
- int ring_id;
- struct hal_srng_config *srng_config = &hal->srng_config[ring_type];
-
- ring_id = ath12k_hal_srng_get_ring_id(ab, ring_type, ring_num, 0);
- if (ring_id < 0)
- return;
-
- srng = &hal->srng_list[ring_id];
-
- if (srng_config->ring_dir == HAL_SRNG_DIR_DST)
- srng->u.dst_ring.tp_addr = (u32 *)(HAL_SHADOW_REG(shadow_cfg_idx) +
- (unsigned long)ab->mem);
- else
- srng->u.src_ring.hp_addr = (u32 *)(HAL_SHADOW_REG(shadow_cfg_idx) +
- (unsigned long)ab->mem);
-}
-
-int ath12k_hal_srng_update_shadow_config(struct ath12k_base *ab,
- enum hal_ring_type ring_type,
- int ring_num)
-{
- struct ath12k_hal *hal = &ab->hal;
- struct hal_srng_config *srng_config = &hal->srng_config[ring_type];
- int shadow_cfg_idx = hal->num_shadow_reg_configured;
- u32 target_reg;
-
- if (shadow_cfg_idx >= HAL_SHADOW_NUM_REGS)
- return -EINVAL;
-
- hal->num_shadow_reg_configured++;
-
- target_reg = srng_config->reg_start[HAL_HP_OFFSET_IN_REG_START];
- target_reg += srng_config->reg_size[HAL_HP_OFFSET_IN_REG_START] *
- ring_num;
-
- /* For destination ring, shadow the TP */
- if (srng_config->ring_dir == HAL_SRNG_DIR_DST)
- target_reg += HAL_OFFSET_FROM_HP_TO_TP;
-
- hal->shadow_reg_addr[shadow_cfg_idx] = target_reg;
-
- /* update hp/tp addr to hal structure*/
- ath12k_hal_srng_update_hp_tp_addr(ab, shadow_cfg_idx, ring_type,
- ring_num);
-
- ath12k_dbg(ab, ATH12K_DBG_HAL,
- "target_reg %x, shadow reg 0x%x shadow_idx 0x%x, ring_type %d, ring num %d",
- target_reg,
- HAL_SHADOW_REG(shadow_cfg_idx),
- shadow_cfg_idx,
- ring_type, ring_num);
-
- return 0;
-}
-
void ath12k_hal_srng_shadow_config(struct ath12k_base *ab)
{
struct ath12k_hal *hal = &ab->hal;
@@ -2551,18 +715,16 @@ void ath12k_hal_srng_shadow_update_hp_tp(struct ath12k_base *ab,
ath12k_hal_srng_access_end(ab, srng);
}
-static void ath12k_hal_register_srng_lock_keys(struct ath12k_base *ab)
+static void ath12k_hal_register_srng_lock_keys(struct ath12k_hal *hal)
{
- struct ath12k_hal *hal = &ab->hal;
u32 ring_id;
for (ring_id = 0; ring_id < HAL_SRNG_RING_ID_MAX; ring_id++)
lockdep_register_key(&hal->srng_list[ring_id].lock_key);
}
-static void ath12k_hal_unregister_srng_lock_keys(struct ath12k_base *ab)
+static void ath12k_hal_unregister_srng_lock_keys(struct ath12k_hal *hal)
{
- struct ath12k_hal *hal = &ab->hal;
u32 ring_id;
for (ring_id = 0; ring_id < HAL_SRNG_RING_ID_MAX; ring_id++)
@@ -2574,26 +736,26 @@ int ath12k_hal_srng_init(struct ath12k_base *ab)
struct ath12k_hal *hal = &ab->hal;
int ret;
- memset(hal, 0, sizeof(*hal));
-
- ret = ab->hw_params->hal_ops->create_srng_config(ab);
+ ret = hal->ops->create_srng_config(hal);
if (ret)
goto err_hal;
- ret = ath12k_hal_alloc_cont_rdp(ab);
+ hal->dev = ab->dev;
+
+ ret = ath12k_hal_alloc_cont_rdp(hal);
if (ret)
goto err_hal;
- ret = ath12k_hal_alloc_cont_wrp(ab);
+ ret = ath12k_hal_alloc_cont_wrp(hal);
if (ret)
goto err_free_cont_rdp;
- ath12k_hal_register_srng_lock_keys(ab);
+ ath12k_hal_register_srng_lock_keys(hal);
return 0;
err_free_cont_rdp:
- ath12k_hal_free_cont_rdp(ab);
+ ath12k_hal_free_cont_rdp(hal);
err_hal:
return ret;
@@ -2603,9 +765,9 @@ void ath12k_hal_srng_deinit(struct ath12k_base *ab)
{
struct ath12k_hal *hal = &ab->hal;
- ath12k_hal_unregister_srng_lock_keys(ab);
- ath12k_hal_free_cont_rdp(ab);
- ath12k_hal_free_cont_wrp(ab);
+ ath12k_hal_unregister_srng_lock_keys(hal);
+ ath12k_hal_free_cont_rdp(hal);
+ ath12k_hal_free_cont_wrp(hal);
kfree(hal->srng_config);
hal->srng_config = NULL;
}
@@ -2661,3 +823,49 @@ void ath12k_hal_dump_srng_stats(struct ath12k_base *ab)
jiffies_to_msecs(jiffies - srng->timestamp));
}
}
+
+void *ath12k_hal_encode_tlv64_hdr(void *tlv, u64 tag, u64 len)
+{
+ struct hal_tlv_64_hdr *tlv64 = tlv;
+
+ tlv64->tl = le64_encode_bits(tag, HAL_TLV_HDR_TAG) |
+ le64_encode_bits(len, HAL_TLV_HDR_LEN);
+
+ return tlv64->value;
+}
+EXPORT_SYMBOL(ath12k_hal_encode_tlv64_hdr);
+
+void *ath12k_hal_encode_tlv32_hdr(void *tlv, u64 tag, u64 len)
+{
+ struct hal_tlv_hdr *tlv32 = tlv;
+
+ tlv32->tl = le32_encode_bits(tag, HAL_TLV_HDR_TAG) |
+ le32_encode_bits(len, HAL_TLV_HDR_LEN);
+
+ return tlv32->value;
+}
+EXPORT_SYMBOL(ath12k_hal_encode_tlv32_hdr);
+
+u16 ath12k_hal_decode_tlv64_hdr(void *tlv, void **desc)
+{
+ struct hal_tlv_64_hdr *tlv64 = tlv;
+ u16 tag;
+
+ tag = le64_get_bits(tlv64->tl, HAL_SRNG_TLV_HDR_TAG);
+ *desc = tlv64->value;
+
+ return tag;
+}
+EXPORT_SYMBOL(ath12k_hal_decode_tlv64_hdr);
+
+u16 ath12k_hal_decode_tlv32_hdr(void *tlv, void **desc)
+{
+ struct hal_tlv_hdr *tlv32 = tlv;
+ u16 tag;
+
+ tag = le32_get_bits(tlv32->tl, HAL_SRNG_TLV_HDR_TAG);
+ *desc = tlv32->value;
+
+ return tag;
+}
+EXPORT_SYMBOL(ath12k_hal_decode_tlv32_hdr);
diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h
index efe00e167998..43e3880f8257 100644
--- a/drivers/net/wireless/ath/ath12k/hal.h
+++ b/drivers/net/wireless/ath/ath12k/hal.h
@@ -1,16 +1,43 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH12K_HAL_H
#define ATH12K_HAL_H
-#include "hal_desc.h"
-#include "rx_desc.h"
+#include "hw.h"
struct ath12k_base;
+
+#define HAL_DESC_REO_NON_QOS_TID 16
+
+#define HAL_INVALID_PEERID 0x3fff
+#define VHT_SIG_SU_NSS_MASK 0x7
+
+#define HAL_TX_ADDRX_EN 1
+#define HAL_TX_ADDRY_EN 2
+
+#define HAL_TX_ADDR_SEARCH_DEFAULT 0
+#define HAL_TX_ADDR_SEARCH_INDEX 1
+
+#define HAL_RX_MAX_MPDU 256
+#define HAL_RX_NUM_WORDS_PER_PPDU_BITMAP (HAL_RX_MAX_MPDU >> 5)
+
+/* TODO: 16 entries per radio times MAX_VAPS_SUPPORTED */
+#define HAL_DSCP_TID_MAP_TBL_NUM_ENTRIES_MAX 32
+#define HAL_DSCP_TID_TBL_SIZE 24
+
+#define EHT_MAX_USER_INFO 4
+#define HAL_RX_MON_MAX_AGGR_SIZE 128
+#define HAL_MAX_UL_MU_USERS 37
+
+#define MAX_USER_POS 8
+#define MAX_MU_GROUP_ID 64
+#define MAX_MU_GROUP_SHOW 16
+#define MAX_MU_GROUP_LENGTH (6 * MAX_MU_GROUP_SHOW)
+
#define HAL_CE_REMAP_REG_BASE (ab->ce_remap_base_addr)
#define HAL_LINK_DESC_SIZE (32 << 2)
@@ -24,364 +51,37 @@ struct ath12k_base;
#define HAL_RING_BASE_ALIGN 8
#define HAL_REO_QLUT_ADDR_ALIGN 256
+#define HAL_ADDR_LSB_REG_MASK 0xffffffff
+#define HAL_ADDR_MSB_REG_SHIFT 32
+
+#define HAL_WBM2SW_REL_ERR_RING_NUM 3
+
+#define HAL_SHADOW_NUM_REGS_MAX 40
+
#define HAL_WBM_IDLE_SCATTER_BUF_SIZE_MAX 32704
/* TODO: Check with hw team on the supported scatter buf size */
#define HAL_WBM_IDLE_SCATTER_NEXT_PTR_SIZE 8
#define HAL_WBM_IDLE_SCATTER_BUF_SIZE (HAL_WBM_IDLE_SCATTER_BUF_SIZE_MAX - \
HAL_WBM_IDLE_SCATTER_NEXT_PTR_SIZE)
-/* TODO: 16 entries per radio times MAX_VAPS_SUPPORTED */
-#define HAL_DSCP_TID_MAP_TBL_NUM_ENTRIES_MAX 32
-#define HAL_DSCP_TID_TBL_SIZE 24
-
-/* calculate the register address from bar0 of shadow register x */
-#define HAL_SHADOW_BASE_ADDR 0x000008fc
-#define HAL_SHADOW_NUM_REGS 40
-#define HAL_HP_OFFSET_IN_REG_START 1
-#define HAL_OFFSET_FROM_HP_TO_TP 4
-
-#define HAL_SHADOW_REG(x) (HAL_SHADOW_BASE_ADDR + (4 * (x)))
-#define HAL_REO_QDESC_MAX_PEERID 8191
-
-/* WCSS Relative address */
-#define HAL_SEQ_WCSS_CMEM_OFFSET 0x00100000
-#define HAL_SEQ_WCSS_UMAC_OFFSET 0x00a00000
-#define HAL_SEQ_WCSS_UMAC_REO_REG 0x00a38000
-#define HAL_SEQ_WCSS_UMAC_TCL_REG 0x00a44000
-#define HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) \
- ((ab)->hw_params->regs->hal_umac_ce0_src_reg_base)
-#define HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) \
- ((ab)->hw_params->regs->hal_umac_ce0_dest_reg_base)
-#define HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) \
- ((ab)->hw_params->regs->hal_umac_ce1_src_reg_base)
-#define HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) \
- ((ab)->hw_params->regs->hal_umac_ce1_dest_reg_base)
-#define HAL_SEQ_WCSS_UMAC_WBM_REG 0x00a34000
-
-#define HAL_CE_WFSS_CE_REG_BASE 0x01b80000
-
-#define HAL_TCL_SW_CONFIG_BANK_ADDR 0x00a4408c
-
-/* SW2TCL(x) R0 ring configuration address */
-#define HAL_TCL1_RING_CMN_CTRL_REG 0x00000020
-#define HAL_TCL1_RING_DSCP_TID_MAP 0x00000240
-#define HAL_TCL1_RING_BASE_LSB(ab) \
- ((ab)->hw_params->regs->hal_tcl1_ring_base_lsb)
-#define HAL_TCL1_RING_BASE_MSB(ab) \
- ((ab)->hw_params->regs->hal_tcl1_ring_base_msb)
-#define HAL_TCL1_RING_ID(ab) ((ab)->hw_params->regs->hal_tcl1_ring_id)
-#define HAL_TCL1_RING_MISC(ab) \
- ((ab)->hw_params->regs->hal_tcl1_ring_misc)
-#define HAL_TCL1_RING_TP_ADDR_LSB(ab) \
- ((ab)->hw_params->regs->hal_tcl1_ring_tp_addr_lsb)
-#define HAL_TCL1_RING_TP_ADDR_MSB(ab) \
- ((ab)->hw_params->regs->hal_tcl1_ring_tp_addr_msb)
-#define HAL_TCL1_RING_CONSUMER_INT_SETUP_IX0(ab) \
- ((ab)->hw_params->regs->hal_tcl1_ring_consumer_int_setup_ix0)
-#define HAL_TCL1_RING_CONSUMER_INT_SETUP_IX1(ab) \
- ((ab)->hw_params->regs->hal_tcl1_ring_consumer_int_setup_ix1)
-#define HAL_TCL1_RING_MSI1_BASE_LSB(ab) \
- ((ab)->hw_params->regs->hal_tcl1_ring_msi1_base_lsb)
-#define HAL_TCL1_RING_MSI1_BASE_MSB(ab) \
- ((ab)->hw_params->regs->hal_tcl1_ring_msi1_base_msb)
-#define HAL_TCL1_RING_MSI1_DATA(ab) \
- ((ab)->hw_params->regs->hal_tcl1_ring_msi1_data)
-#define HAL_TCL2_RING_BASE_LSB(ab) \
- ((ab)->hw_params->regs->hal_tcl2_ring_base_lsb)
-#define HAL_TCL_RING_BASE_LSB(ab) \
- ((ab)->hw_params->regs->hal_tcl_ring_base_lsb)
-
-#define HAL_TCL1_RING_MSI1_BASE_LSB_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
- (HAL_TCL1_RING_MSI1_BASE_LSB(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
-#define HAL_TCL1_RING_MSI1_BASE_MSB_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
- (HAL_TCL1_RING_MSI1_BASE_MSB(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
-#define HAL_TCL1_RING_MSI1_DATA_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
- (HAL_TCL1_RING_MSI1_DATA(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
-#define HAL_TCL1_RING_BASE_MSB_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
- (HAL_TCL1_RING_BASE_MSB(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
-#define HAL_TCL1_RING_ID_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
- (HAL_TCL1_RING_ID(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
-#define HAL_TCL1_RING_CONSR_INT_SETUP_IX0_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
- (HAL_TCL1_RING_CONSUMER_INT_SETUP_IX0(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
-#define HAL_TCL1_RING_CONSR_INT_SETUP_IX1_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
- (HAL_TCL1_RING_CONSUMER_INT_SETUP_IX1(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
-#define HAL_TCL1_RING_TP_ADDR_LSB_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
- (HAL_TCL1_RING_TP_ADDR_LSB(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
-#define HAL_TCL1_RING_TP_ADDR_MSB_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
- (HAL_TCL1_RING_TP_ADDR_MSB(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
-#define HAL_TCL1_RING_MISC_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
- (HAL_TCL1_RING_MISC(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
-
-/* SW2TCL(x) R2 ring pointers (head/tail) address */
-#define HAL_TCL1_RING_HP 0x00002000
-#define HAL_TCL1_RING_TP 0x00002004
-#define HAL_TCL2_RING_HP 0x00002008
-#define HAL_TCL_RING_HP 0x00002028
-
-#define HAL_TCL1_RING_TP_OFFSET \
- (HAL_TCL1_RING_TP - HAL_TCL1_RING_HP)
-
-/* TCL STATUS ring address */
-#define HAL_TCL_STATUS_RING_BASE_LSB(ab) \
- ((ab)->hw_params->regs->hal_tcl_status_ring_base_lsb)
-#define HAL_TCL_STATUS_RING_HP 0x00002048
-
-/* PPE2TCL1 Ring address */
-#define HAL_TCL_PPE2TCL1_RING_BASE_LSB 0x00000c48
-#define HAL_TCL_PPE2TCL1_RING_HP 0x00002038
-
-/* WBM PPE Release Ring address */
-#define HAL_WBM_PPE_RELEASE_RING_BASE_LSB(ab) \
- ((ab)->hw_params->regs->hal_ppe_rel_ring_base)
-#define HAL_WBM_PPE_RELEASE_RING_HP 0x00003020
-
-/* REO2SW(x) R0 ring configuration address */
-#define HAL_REO1_GEN_ENABLE 0x00000000
-#define HAL_REO1_MISC_CTRL_ADDR(ab) \
- ((ab)->hw_params->regs->hal_reo1_misc_ctrl_addr)
-#define HAL_REO1_DEST_RING_CTRL_IX_0 0x00000004
-#define HAL_REO1_DEST_RING_CTRL_IX_1 0x00000008
-#define HAL_REO1_DEST_RING_CTRL_IX_2 0x0000000c
-#define HAL_REO1_DEST_RING_CTRL_IX_3 0x00000010
-#define HAL_REO1_QDESC_ADDR(ab) ((ab)->hw_params->regs->hal_reo1_qdesc_addr)
-#define HAL_REO1_QDESC_MAX_PEERID(ab) ((ab)->hw_params->regs->hal_reo1_qdesc_max_peerid)
-#define HAL_REO1_SW_COOKIE_CFG0(ab) ((ab)->hw_params->regs->hal_reo1_sw_cookie_cfg0)
-#define HAL_REO1_SW_COOKIE_CFG1(ab) ((ab)->hw_params->regs->hal_reo1_sw_cookie_cfg1)
-#define HAL_REO1_QDESC_LUT_BASE0(ab) ((ab)->hw_params->regs->hal_reo1_qdesc_lut_base0)
-#define HAL_REO1_QDESC_LUT_BASE1(ab) ((ab)->hw_params->regs->hal_reo1_qdesc_lut_base1)
-#define HAL_REO1_RING_BASE_LSB(ab) ((ab)->hw_params->regs->hal_reo1_ring_base_lsb)
-#define HAL_REO1_RING_BASE_MSB(ab) ((ab)->hw_params->regs->hal_reo1_ring_base_msb)
-#define HAL_REO1_RING_ID(ab) ((ab)->hw_params->regs->hal_reo1_ring_id)
-#define HAL_REO1_RING_MISC(ab) ((ab)->hw_params->regs->hal_reo1_ring_misc)
-#define HAL_REO1_RING_HP_ADDR_LSB(ab) ((ab)->hw_params->regs->hal_reo1_ring_hp_addr_lsb)
-#define HAL_REO1_RING_HP_ADDR_MSB(ab) ((ab)->hw_params->regs->hal_reo1_ring_hp_addr_msb)
-#define HAL_REO1_RING_PRODUCER_INT_SETUP(ab) \
- ((ab)->hw_params->regs->hal_reo1_ring_producer_int_setup)
-#define HAL_REO1_RING_MSI1_BASE_LSB(ab) \
- ((ab)->hw_params->regs->hal_reo1_ring_msi1_base_lsb)
-#define HAL_REO1_RING_MSI1_BASE_MSB(ab) \
- ((ab)->hw_params->regs->hal_reo1_ring_msi1_base_msb)
-#define HAL_REO1_RING_MSI1_DATA(ab) ((ab)->hw_params->regs->hal_reo1_ring_msi1_data)
-#define HAL_REO2_RING_BASE_LSB(ab) ((ab)->hw_params->regs->hal_reo2_ring_base)
-#define HAL_REO1_AGING_THRESH_IX_0(ab) ((ab)->hw_params->regs->hal_reo1_aging_thres_ix0)
-#define HAL_REO1_AGING_THRESH_IX_1(ab) ((ab)->hw_params->regs->hal_reo1_aging_thres_ix1)
-#define HAL_REO1_AGING_THRESH_IX_2(ab) ((ab)->hw_params->regs->hal_reo1_aging_thres_ix2)
-#define HAL_REO1_AGING_THRESH_IX_3(ab) ((ab)->hw_params->regs->hal_reo1_aging_thres_ix3)
-
-/* REO2SW(x) R2 ring pointers (head/tail) address */
-#define HAL_REO1_RING_HP 0x00003048
-#define HAL_REO1_RING_TP 0x0000304c
-#define HAL_REO2_RING_HP 0x00003050
-
-#define HAL_REO1_RING_TP_OFFSET (HAL_REO1_RING_TP - HAL_REO1_RING_HP)
-
-/* REO2SW0 ring configuration address */
-#define HAL_REO_SW0_RING_BASE_LSB(ab) \
- ((ab)->hw_params->regs->hal_reo2_sw0_ring_base)
-
-/* REO2SW0 R2 ring pointer (head/tail) address */
-#define HAL_REO_SW0_RING_HP 0x00003088
-
-/* REO CMD R0 address */
-#define HAL_REO_CMD_RING_BASE_LSB(ab) \
- ((ab)->hw_params->regs->hal_reo_cmd_ring_base)
-
-/* REO CMD R2 address */
-#define HAL_REO_CMD_HP 0x00003020
-
-/* SW2REO R0 address */
-#define HAL_SW2REO_RING_BASE_LSB(ab) \
- ((ab)->hw_params->regs->hal_sw2reo_ring_base)
-#define HAL_SW2REO1_RING_BASE_LSB(ab) \
- ((ab)->hw_params->regs->hal_sw2reo1_ring_base)
-
-/* SW2REO R2 address */
-#define HAL_SW2REO_RING_HP 0x00003028
-#define HAL_SW2REO1_RING_HP 0x00003030
-
-/* CE ring R0 address */
-#define HAL_CE_SRC_RING_BASE_LSB 0x00000000
-#define HAL_CE_DST_RING_BASE_LSB 0x00000000
-#define HAL_CE_DST_STATUS_RING_BASE_LSB 0x00000058
-#define HAL_CE_DST_RING_CTRL 0x000000b0
-
-/* CE ring R2 address */
-#define HAL_CE_DST_RING_HP 0x00000400
-#define HAL_CE_DST_STATUS_RING_HP 0x00000408
-
-/* REO status address */
-#define HAL_REO_STATUS_RING_BASE_LSB(ab) \
- ((ab)->hw_params->regs->hal_reo_status_ring_base)
-#define HAL_REO_STATUS_HP 0x000030a8
-
-/* WBM Idle R0 address */
-#define HAL_WBM_IDLE_LINK_RING_BASE_LSB(ab) \
- ((ab)->hw_params->regs->hal_wbm_idle_ring_base_lsb)
-#define HAL_WBM_IDLE_LINK_RING_MISC_ADDR(ab) \
- ((ab)->hw_params->regs->hal_wbm_idle_ring_misc_addr)
-#define HAL_WBM_R0_IDLE_LIST_CONTROL_ADDR(ab) \
- ((ab)->hw_params->regs->hal_wbm_r0_idle_list_cntl_addr)
-#define HAL_WBM_R0_IDLE_LIST_SIZE_ADDR(ab) \
- ((ab)->hw_params->regs->hal_wbm_r0_idle_list_size_addr)
-#define HAL_WBM_SCATTERED_RING_BASE_LSB(ab) \
- ((ab)->hw_params->regs->hal_wbm_scattered_ring_base_lsb)
-#define HAL_WBM_SCATTERED_RING_BASE_MSB(ab) \
- ((ab)->hw_params->regs->hal_wbm_scattered_ring_base_msb)
-#define HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX0(ab) \
- ((ab)->hw_params->regs->hal_wbm_scattered_desc_head_info_ix0)
-#define HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX1(ab) \
- ((ab)->hw_params->regs->hal_wbm_scattered_desc_head_info_ix1)
-#define HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX0(ab) \
- ((ab)->hw_params->regs->hal_wbm_scattered_desc_tail_info_ix0)
-#define HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX1(ab) \
- ((ab)->hw_params->regs->hal_wbm_scattered_desc_tail_info_ix1)
-#define HAL_WBM_SCATTERED_DESC_PTR_HP_ADDR(ab) \
- ((ab)->hw_params->regs->hal_wbm_scattered_desc_ptr_hp_addr)
-
-/* WBM Idle R2 address */
-#define HAL_WBM_IDLE_LINK_RING_HP 0x000030b8
-
-/* SW2WBM R0 release address */
-#define HAL_WBM_SW_RELEASE_RING_BASE_LSB(ab) \
- ((ab)->hw_params->regs->hal_wbm_sw_release_ring_base_lsb)
-#define HAL_WBM_SW1_RELEASE_RING_BASE_LSB(ab) \
- ((ab)->hw_params->regs->hal_wbm_sw1_release_ring_base_lsb)
-
-/* SW2WBM R2 release address */
-#define HAL_WBM_SW_RELEASE_RING_HP 0x00003010
-#define HAL_WBM_SW1_RELEASE_RING_HP 0x00003018
-
-/* WBM2SW R0 release address */
-#define HAL_WBM0_RELEASE_RING_BASE_LSB(ab) \
- ((ab)->hw_params->regs->hal_wbm0_release_ring_base_lsb)
-
-#define HAL_WBM1_RELEASE_RING_BASE_LSB(ab) \
- ((ab)->hw_params->regs->hal_wbm1_release_ring_base_lsb)
-
-/* WBM2SW R2 release address */
-#define HAL_WBM0_RELEASE_RING_HP 0x000030c8
-#define HAL_WBM1_RELEASE_RING_HP 0x000030d0
-
-/* WBM cookie config address and mask */
-#define HAL_WBM_SW_COOKIE_CFG0 0x00000040
-#define HAL_WBM_SW_COOKIE_CFG1 0x00000044
-#define HAL_WBM_SW_COOKIE_CFG2 0x00000090
-#define HAL_WBM_SW_COOKIE_CONVERT_CFG 0x00000094
-
-#define HAL_WBM_SW_COOKIE_CFG_CMEM_BASE_ADDR_MSB GENMASK(7, 0)
-#define HAL_WBM_SW_COOKIE_CFG_COOKIE_PPT_MSB GENMASK(12, 8)
-#define HAL_WBM_SW_COOKIE_CFG_COOKIE_SPT_MSB GENMASK(17, 13)
-#define HAL_WBM_SW_COOKIE_CFG_ALIGN BIT(18)
-#define HAL_WBM_SW_COOKIE_CFG_RELEASE_PATH_EN BIT(0)
-#define HAL_WBM_SW_COOKIE_CFG_ERR_PATH_EN BIT(1)
-#define HAL_WBM_SW_COOKIE_CFG_CONV_IND_EN BIT(3)
-
-#define HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW0_EN BIT(1)
-#define HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW1_EN BIT(2)
-#define HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW2_EN BIT(3)
-#define HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW3_EN BIT(4)
-#define HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW4_EN BIT(5)
-#define HAL_WBM_SW_COOKIE_CONV_CFG_GLOBAL_EN BIT(8)
-
-/* TCL ring field mask and offset */
-#define HAL_TCL1_RING_BASE_MSB_RING_SIZE GENMASK(27, 8)
-#define HAL_TCL1_RING_BASE_MSB_RING_BASE_ADDR_MSB GENMASK(7, 0)
-#define HAL_TCL1_RING_ID_ENTRY_SIZE GENMASK(7, 0)
-#define HAL_TCL1_RING_MISC_MSI_RING_ID_DISABLE BIT(0)
-#define HAL_TCL1_RING_MISC_MSI_LOOPCNT_DISABLE BIT(1)
-#define HAL_TCL1_RING_MISC_MSI_SWAP BIT(3)
-#define HAL_TCL1_RING_MISC_HOST_FW_SWAP BIT(4)
-#define HAL_TCL1_RING_MISC_DATA_TLV_SWAP BIT(5)
-#define HAL_TCL1_RING_MISC_SRNG_ENABLE BIT(6)
-#define HAL_TCL1_RING_CONSR_INT_SETUP_IX0_INTR_TMR_THOLD GENMASK(31, 16)
-#define HAL_TCL1_RING_CONSR_INT_SETUP_IX0_BATCH_COUNTER_THOLD GENMASK(14, 0)
-#define HAL_TCL1_RING_CONSR_INT_SETUP_IX1_LOW_THOLD GENMASK(15, 0)
-#define HAL_TCL1_RING_MSI1_BASE_MSB_MSI1_ENABLE BIT(8)
-#define HAL_TCL1_RING_MSI1_BASE_MSB_ADDR GENMASK(7, 0)
-#define HAL_TCL1_RING_CMN_CTRL_DSCP_TID_MAP_PROG_EN BIT(23)
-#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP GENMASK(31, 0)
-#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP0 GENMASK(2, 0)
-#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP1 GENMASK(5, 3)
-#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP2 GENMASK(8, 6)
-#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP3 GENMASK(11, 9)
-#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP4 GENMASK(14, 12)
-#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP5 GENMASK(17, 15)
-#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP6 GENMASK(20, 18)
-#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP7 GENMASK(23, 21)
-
-/* REO ring field mask and offset */
-#define HAL_REO1_RING_BASE_MSB_RING_SIZE GENMASK(27, 8)
-#define HAL_REO1_RING_BASE_MSB_RING_BASE_ADDR_MSB GENMASK(7, 0)
-#define HAL_REO1_RING_ID_RING_ID GENMASK(15, 8)
-#define HAL_REO1_RING_ID_ENTRY_SIZE GENMASK(7, 0)
-#define HAL_REO1_RING_MISC_MSI_SWAP BIT(3)
-#define HAL_REO1_RING_MISC_HOST_FW_SWAP BIT(4)
-#define HAL_REO1_RING_MISC_DATA_TLV_SWAP BIT(5)
-#define HAL_REO1_RING_MISC_SRNG_ENABLE BIT(6)
-#define HAL_REO1_RING_PRDR_INT_SETUP_INTR_TMR_THOLD GENMASK(31, 16)
-#define HAL_REO1_RING_PRDR_INT_SETUP_BATCH_COUNTER_THOLD GENMASK(14, 0)
-#define HAL_REO1_RING_MSI1_BASE_MSB_MSI1_ENABLE BIT(8)
-#define HAL_REO1_RING_MSI1_BASE_MSB_ADDR GENMASK(7, 0)
-#define HAL_REO1_MISC_CTL_FRAG_DST_RING GENMASK(20, 17)
-#define HAL_REO1_MISC_CTL_BAR_DST_RING GENMASK(24, 21)
-#define HAL_REO1_GEN_ENABLE_AGING_LIST_ENABLE BIT(2)
-#define HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE BIT(3)
-#define HAL_REO1_SW_COOKIE_CFG_CMEM_BASE_ADDR_MSB GENMASK(7, 0)
-#define HAL_REO1_SW_COOKIE_CFG_COOKIE_PPT_MSB GENMASK(12, 8)
-#define HAL_REO1_SW_COOKIE_CFG_COOKIE_SPT_MSB GENMASK(17, 13)
-#define HAL_REO1_SW_COOKIE_CFG_ALIGN BIT(18)
-#define HAL_REO1_SW_COOKIE_CFG_ENABLE BIT(19)
-#define HAL_REO1_SW_COOKIE_CFG_GLOBAL_ENABLE BIT(20)
-#define HAL_REO_QDESC_ADDR_READ_LUT_ENABLE BIT(7)
-#define HAL_REO_QDESC_ADDR_READ_CLEAR_QDESC_ARRAY BIT(6)
-
-/* CE ring bit field mask and shift */
-#define HAL_CE_DST_R0_DEST_CTRL_MAX_LEN GENMASK(15, 0)
-
-#define HAL_ADDR_LSB_REG_MASK 0xffffffff
-
-#define HAL_ADDR_MSB_REG_SHIFT 32
-
-/* WBM ring bit field mask and shift */
-#define HAL_WBM_LINK_DESC_IDLE_LIST_MODE BIT(1)
-#define HAL_WBM_SCATTER_BUFFER_SIZE GENMASK(10, 2)
-#define HAL_WBM_SCATTER_RING_SIZE_OF_IDLE_LINK_DESC_LIST GENMASK(31, 16)
-#define HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32 GENMASK(7, 0)
-#define HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_MATCH_TAG GENMASK(31, 8)
-
-#define HAL_WBM_SCATTERED_DESC_HEAD_P_OFFSET_IX1 GENMASK(20, 8)
-#define HAL_WBM_SCATTERED_DESC_TAIL_P_OFFSET_IX1 GENMASK(20, 8)
-
-#define HAL_WBM_IDLE_LINK_RING_MISC_SRNG_ENABLE BIT(6)
-#define HAL_WBM_IDLE_LINK_RING_MISC_RIND_ID_DISABLE BIT(0)
-
-#define BASE_ADDR_MATCH_TAG_VAL 0x5
-
-#define HAL_REO_REO2SW1_RING_BASE_MSB_RING_SIZE 0x000fffff
-#define HAL_REO_REO2SW0_RING_BASE_MSB_RING_SIZE 0x000fffff
-#define HAL_REO_SW2REO_RING_BASE_MSB_RING_SIZE 0x0000ffff
-#define HAL_REO_CMD_RING_BASE_MSB_RING_SIZE 0x0000ffff
-#define HAL_REO_STATUS_RING_BASE_MSB_RING_SIZE 0x0000ffff
-#define HAL_SW2TCL1_RING_BASE_MSB_RING_SIZE 0x000fffff
-#define HAL_SW2TCL1_CMD_RING_BASE_MSB_RING_SIZE 0x000fffff
-#define HAL_TCL_STATUS_RING_BASE_MSB_RING_SIZE 0x0000ffff
-#define HAL_CE_SRC_RING_BASE_MSB_RING_SIZE 0x0000ffff
-#define HAL_CE_DST_RING_BASE_MSB_RING_SIZE 0x0000ffff
-#define HAL_CE_DST_STATUS_RING_BASE_MSB_RING_SIZE 0x0000ffff
-#define HAL_WBM_IDLE_LINK_RING_BASE_MSB_RING_SIZE 0x000fffff
-#define HAL_SW2WBM_RELEASE_RING_BASE_MSB_RING_SIZE 0x0000ffff
-#define HAL_WBM2SW_RELEASE_RING_BASE_MSB_RING_SIZE 0x000fffff
-#define HAL_RXDMA_RING_MAX_SIZE 0x0000ffff
-#define HAL_RXDMA_RING_MAX_SIZE_BE 0x000fffff
-#define HAL_WBM2PPE_RELEASE_RING_BASE_MSB_RING_SIZE 0x000fffff
-
-#define HAL_WBM2SW_REL_ERR_RING_NUM 3
-/* Add any other errors here and return them in
- * ath12k_hal_rx_desc_get_err().
- */
-
-#define HAL_IPQ5332_CE_WFSS_REG_BASE 0x740000
-#define HAL_IPQ5332_CE_SIZE 0x100000
+#define HAL_AST_IDX_INVALID 0xFFFF
+#define HAL_RX_MAX_MCS 12
+#define HAL_RX_MAX_MCS_HT 31
+#define HAL_RX_MAX_MCS_VHT 9
+#define HAL_RX_MAX_MCS_HE 11
+#define HAL_RX_MAX_MCS_BE 15
+#define HAL_RX_MAX_NSS 8
+#define HAL_RX_MAX_NUM_LEGACY_RATES 12
+
+#define HAL_RX_UL_OFDMA_USER_INFO_V0_W0_VALID BIT(30)
+#define HAL_RX_UL_OFDMA_USER_INFO_V0_W0_VER BIT(31)
+#define HAL_RX_UL_OFDMA_USER_INFO_V0_W1_NSS GENMASK(2, 0)
+#define HAL_RX_UL_OFDMA_USER_INFO_V0_W1_MCS GENMASK(6, 3)
+#define HAL_RX_UL_OFDMA_USER_INFO_V0_W1_LDPC BIT(7)
+#define HAL_RX_UL_OFDMA_USER_INFO_V0_W1_DCM BIT(8)
+#define HAL_RX_UL_OFDMA_USER_INFO_V0_W1_RU_START GENMASK(15, 9)
+#define HAL_RX_UL_OFDMA_USER_INFO_V0_W1_RU_SIZE GENMASK(18, 16)
+#define HAL_RX_FCS_LEN 4
enum hal_srng_ring_id {
HAL_SRNG_RING_ID_REO2SW0 = 0,
@@ -525,6 +225,64 @@ enum hal_srng_ring_id {
#define HAL_SRNG_RING_ID_MAX (HAL_SRNG_RING_ID_DMAC_CMN_ID_END + \
HAL_SRNG_NUM_PMAC_RINGS)
+enum hal_rx_su_mu_coding {
+ HAL_RX_SU_MU_CODING_BCC,
+ HAL_RX_SU_MU_CODING_LDPC,
+ HAL_RX_SU_MU_CODING_MAX,
+};
+
+enum hal_rx_gi {
+ HAL_RX_GI_0_8_US,
+ HAL_RX_GI_0_4_US,
+ HAL_RX_GI_1_6_US,
+ HAL_RX_GI_3_2_US,
+ HAL_RX_GI_MAX,
+};
+
+enum hal_rx_bw {
+ HAL_RX_BW_20MHZ,
+ HAL_RX_BW_40MHZ,
+ HAL_RX_BW_80MHZ,
+ HAL_RX_BW_160MHZ,
+ HAL_RX_BW_320MHZ,
+ HAL_RX_BW_MAX,
+};
+
+enum hal_rx_preamble {
+ HAL_RX_PREAMBLE_11A,
+ HAL_RX_PREAMBLE_11B,
+ HAL_RX_PREAMBLE_11N,
+ HAL_RX_PREAMBLE_11AC,
+ HAL_RX_PREAMBLE_11AX,
+ HAL_RX_PREAMBLE_11BA,
+ HAL_RX_PREAMBLE_11BE,
+ HAL_RX_PREAMBLE_MAX,
+};
+
+enum hal_rx_reception_type {
+ HAL_RX_RECEPTION_TYPE_SU,
+ HAL_RX_RECEPTION_TYPE_MU_MIMO,
+ HAL_RX_RECEPTION_TYPE_MU_OFDMA,
+ HAL_RX_RECEPTION_TYPE_MU_OFDMA_MIMO,
+ HAL_RX_RECEPTION_TYPE_MAX,
+};
+
+enum hal_rx_legacy_rate {
+ HAL_RX_LEGACY_RATE_1_MBPS,
+ HAL_RX_LEGACY_RATE_2_MBPS,
+ HAL_RX_LEGACY_RATE_5_5_MBPS,
+ HAL_RX_LEGACY_RATE_6_MBPS,
+ HAL_RX_LEGACY_RATE_9_MBPS,
+ HAL_RX_LEGACY_RATE_11_MBPS,
+ HAL_RX_LEGACY_RATE_12_MBPS,
+ HAL_RX_LEGACY_RATE_18_MBPS,
+ HAL_RX_LEGACY_RATE_24_MBPS,
+ HAL_RX_LEGACY_RATE_36_MBPS,
+ HAL_RX_LEGACY_RATE_48_MBPS,
+ HAL_RX_LEGACY_RATE_54_MBPS,
+ HAL_RX_LEGACY_RATE_INVALID,
+};
+
enum hal_ring_type {
HAL_REO_DST,
HAL_REO_EXCEPTION,
@@ -554,11 +312,6 @@ enum hal_ring_type {
HAL_MAX_RING_TYPES,
};
-#define HAL_RX_MAX_BA_WINDOW 256
-
-#define HAL_DEFAULT_BE_BK_VI_REO_TIMEOUT_USEC (100 * 1000)
-#define HAL_DEFAULT_VO_REO_TIMEOUT_USEC (40 * 1000)
-
/**
* enum hal_reo_cmd_type: Enum for REO command type
* @HAL_REO_CMD_GET_QUEUE_STATS: Get REO queue status/stats
@@ -597,6 +350,128 @@ enum hal_reo_cmd_status {
HAL_REO_CMD_DRAIN = 0xff,
};
+enum hal_tcl_encap_type {
+ HAL_TCL_ENCAP_TYPE_RAW,
+ HAL_TCL_ENCAP_TYPE_NATIVE_WIFI,
+ HAL_TCL_ENCAP_TYPE_ETHERNET,
+ HAL_TCL_ENCAP_TYPE_802_3 = 3,
+ HAL_TCL_ENCAP_TYPE_MAX
+};
+
+enum hal_tcl_desc_type {
+ HAL_TCL_DESC_TYPE_BUFFER,
+ HAL_TCL_DESC_TYPE_EXT_DESC,
+ HAL_TCL_DESC_TYPE_MAX,
+};
+
+enum hal_reo_dest_ring_buffer_type {
+ HAL_REO_DEST_RING_BUFFER_TYPE_MSDU,
+ HAL_REO_DEST_RING_BUFFER_TYPE_LINK_DESC,
+};
+
+enum hal_reo_dest_ring_push_reason {
+ HAL_REO_DEST_RING_PUSH_REASON_ERR_DETECTED,
+ HAL_REO_DEST_RING_PUSH_REASON_ROUTING_INSTRUCTION,
+};
+
+enum hal_reo_entr_rxdma_push_reason {
+ HAL_REO_ENTR_RING_RXDMA_PUSH_REASON_ERR_DETECTED,
+ HAL_REO_ENTR_RING_RXDMA_PUSH_REASON_ROUTING_INSTRUCTION,
+ HAL_REO_ENTR_RING_RXDMA_PUSH_REASON_RX_FLUSH,
+};
+
+enum hal_reo_dest_ring_error_code {
+ HAL_REO_DEST_RING_ERROR_CODE_DESC_ADDR_ZERO,
+ HAL_REO_DEST_RING_ERROR_CODE_DESC_INVALID,
+ HAL_REO_DEST_RING_ERROR_CODE_AMPDU_IN_NON_BA,
+ HAL_REO_DEST_RING_ERROR_CODE_NON_BA_DUPLICATE,
+ HAL_REO_DEST_RING_ERROR_CODE_BA_DUPLICATE,
+ HAL_REO_DEST_RING_ERROR_CODE_FRAME_2K_JUMP,
+ HAL_REO_DEST_RING_ERROR_CODE_BAR_2K_JUMP,
+ HAL_REO_DEST_RING_ERROR_CODE_FRAME_OOR,
+ HAL_REO_DEST_RING_ERROR_CODE_BAR_OOR,
+ HAL_REO_DEST_RING_ERROR_CODE_NO_BA_SESSION,
+ HAL_REO_DEST_RING_ERROR_CODE_FRAME_SN_EQUALS_SSN,
+ HAL_REO_DEST_RING_ERROR_CODE_PN_CHECK_FAILED,
+ HAL_REO_DEST_RING_ERROR_CODE_2K_ERR_FLAG_SET,
+ HAL_REO_DEST_RING_ERROR_CODE_PN_ERR_FLAG_SET,
+ HAL_REO_DEST_RING_ERROR_CODE_DESC_BLOCKED,
+ HAL_REO_DEST_RING_ERROR_CODE_MAX,
+};
+
+enum hal_reo_entr_rxdma_ecode {
+ HAL_REO_ENTR_RING_RXDMA_ECODE_OVERFLOW_ERR,
+ HAL_REO_ENTR_RING_RXDMA_ECODE_MPDU_LEN_ERR,
+ HAL_REO_ENTR_RING_RXDMA_ECODE_FCS_ERR,
+ HAL_REO_ENTR_RING_RXDMA_ECODE_DECRYPT_ERR,
+ HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR,
+ HAL_REO_ENTR_RING_RXDMA_ECODE_UNECRYPTED_ERR,
+ HAL_REO_ENTR_RING_RXDMA_ECODE_MSDU_LEN_ERR,
+ HAL_REO_ENTR_RING_RXDMA_ECODE_MSDU_LIMIT_ERR,
+ HAL_REO_ENTR_RING_RXDMA_ECODE_WIFI_PARSE_ERR,
+ HAL_REO_ENTR_RING_RXDMA_ECODE_AMSDU_PARSE_ERR,
+ HAL_REO_ENTR_RING_RXDMA_ECODE_SA_TIMEOUT_ERR,
+ HAL_REO_ENTR_RING_RXDMA_ECODE_DA_TIMEOUT_ERR,
+ HAL_REO_ENTR_RING_RXDMA_ECODE_FLOW_TIMEOUT_ERR,
+ HAL_REO_ENTR_RING_RXDMA_ECODE_FLUSH_REQUEST_ERR,
+ HAL_REO_ENTR_RING_RXDMA_ECODE_AMSDU_FRAG_ERR,
+ HAL_REO_ENTR_RING_RXDMA_ECODE_MULTICAST_ECHO_ERR,
+ HAL_REO_ENTR_RING_RXDMA_ECODE_AMSDU_MISMATCH_ERR,
+ HAL_REO_ENTR_RING_RXDMA_ECODE_UNAUTH_WDS_ERR,
+ HAL_REO_ENTR_RING_RXDMA_ECODE_GRPCAST_AMSDU_WDS_ERR,
+ HAL_REO_ENTR_RING_RXDMA_ECODE_MAX,
+};
+
+enum hal_wbm_htt_tx_comp_status {
+ HAL_WBM_REL_HTT_TX_COMP_STATUS_OK,
+ HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP,
+ HAL_WBM_REL_HTT_TX_COMP_STATUS_TTL,
+ HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ,
+ HAL_WBM_REL_HTT_TX_COMP_STATUS_INSPECT,
+ HAL_WBM_REL_HTT_TX_COMP_STATUS_MEC_NOTIFY,
+ HAL_WBM_REL_HTT_TX_COMP_STATUS_VDEVID_MISMATCH,
+ HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX,
+};
+
+enum hal_encrypt_type {
+ HAL_ENCRYPT_TYPE_WEP_40,
+ HAL_ENCRYPT_TYPE_WEP_104,
+ HAL_ENCRYPT_TYPE_TKIP_NO_MIC,
+ HAL_ENCRYPT_TYPE_WEP_128,
+ HAL_ENCRYPT_TYPE_TKIP_MIC,
+ HAL_ENCRYPT_TYPE_WAPI,
+ HAL_ENCRYPT_TYPE_CCMP_128,
+ HAL_ENCRYPT_TYPE_OPEN,
+ HAL_ENCRYPT_TYPE_CCMP_256,
+ HAL_ENCRYPT_TYPE_GCMP_128,
+ HAL_ENCRYPT_TYPE_AES_GCMP_256,
+ HAL_ENCRYPT_TYPE_WAPI_GCM_SM4,
+};
+
+enum hal_tx_rate_stats_bw {
+ HAL_TX_RATE_STATS_BW_20,
+ HAL_TX_RATE_STATS_BW_40,
+ HAL_TX_RATE_STATS_BW_80,
+ HAL_TX_RATE_STATS_BW_160,
+};
+
+enum hal_tx_rate_stats_pkt_type {
+ HAL_TX_RATE_STATS_PKT_TYPE_11A,
+ HAL_TX_RATE_STATS_PKT_TYPE_11B,
+ HAL_TX_RATE_STATS_PKT_TYPE_11N,
+ HAL_TX_RATE_STATS_PKT_TYPE_11AC,
+ HAL_TX_RATE_STATS_PKT_TYPE_11AX,
+ HAL_TX_RATE_STATS_PKT_TYPE_11BA,
+ HAL_TX_RATE_STATS_PKT_TYPE_11BE,
+};
+
+enum hal_tx_rate_stats_sgi {
+ HAL_TX_RATE_STATS_SGI_08US,
+ HAL_TX_RATE_STATS_SGI_04US,
+ HAL_TX_RATE_STATS_SGI_16US,
+ HAL_TX_RATE_STATS_SGI_32US,
+};
+
struct hal_wbm_idle_scatter_list {
dma_addr_t paddr;
struct hal_wbm_link_desc *vaddr;
@@ -625,6 +500,339 @@ enum hal_srng_dir {
HAL_SRNG_DIR_DST
};
+enum rx_msdu_start_pkt_type {
+ RX_MSDU_START_PKT_TYPE_11A,
+ RX_MSDU_START_PKT_TYPE_11B,
+ RX_MSDU_START_PKT_TYPE_11N,
+ RX_MSDU_START_PKT_TYPE_11AC,
+ RX_MSDU_START_PKT_TYPE_11AX,
+ RX_MSDU_START_PKT_TYPE_11BA,
+ RX_MSDU_START_PKT_TYPE_11BE,
+};
+
+enum rx_msdu_start_sgi {
+ RX_MSDU_START_SGI_0_8_US,
+ RX_MSDU_START_SGI_0_4_US,
+ RX_MSDU_START_SGI_1_6_US,
+ RX_MSDU_START_SGI_3_2_US,
+};
+
+enum rx_msdu_start_recv_bw {
+ RX_MSDU_START_RECV_BW_20MHZ,
+ RX_MSDU_START_RECV_BW_40MHZ,
+ RX_MSDU_START_RECV_BW_80MHZ,
+ RX_MSDU_START_RECV_BW_160MHZ,
+};
+
+enum rx_msdu_start_reception_type {
+ RX_MSDU_START_RECEPTION_TYPE_SU,
+ RX_MSDU_START_RECEPTION_TYPE_DL_MU_MIMO,
+ RX_MSDU_START_RECEPTION_TYPE_DL_MU_OFDMA,
+ RX_MSDU_START_RECEPTION_TYPE_DL_MU_OFDMA_MIMO,
+ RX_MSDU_START_RECEPTION_TYPE_UL_MU_MIMO,
+ RX_MSDU_START_RECEPTION_TYPE_UL_MU_OFDMA,
+ RX_MSDU_START_RECEPTION_TYPE_UL_MU_OFDMA_MIMO,
+};
+
+enum rx_desc_decap_type {
+ RX_DESC_DECAP_TYPE_RAW,
+ RX_DESC_DECAP_TYPE_NATIVE_WIFI,
+ RX_DESC_DECAP_TYPE_ETHERNET2_DIX,
+ RX_DESC_DECAP_TYPE_8023,
+};
+
+struct hal_rx_user_status {
+ u32 mcs:4,
+ nss:3,
+ ofdma_info_valid:1,
+ ul_ofdma_ru_start_index:7,
+ ul_ofdma_ru_width:7,
+ ul_ofdma_ru_size:8;
+ u32 ul_ofdma_user_v0_word0;
+ u32 ul_ofdma_user_v0_word1;
+ u32 ast_index;
+ u32 tid;
+ u16 tcp_msdu_count;
+ u16 tcp_ack_msdu_count;
+ u16 udp_msdu_count;
+ u16 other_msdu_count;
+ u16 frame_control;
+ u8 frame_control_info_valid;
+ u8 data_sequence_control_info_valid;
+ u16 first_data_seq_ctrl;
+ u32 preamble_type;
+ u16 ht_flags;
+ u16 vht_flags;
+ u16 he_flags;
+ u8 rs_flags;
+ u8 ldpc;
+ u32 mpdu_cnt_fcs_ok;
+ u32 mpdu_cnt_fcs_err;
+ u32 mpdu_fcs_ok_bitmap[HAL_RX_NUM_WORDS_PER_PPDU_BITMAP];
+ u32 mpdu_ok_byte_count;
+ u32 mpdu_err_byte_count;
+ bool ampdu_present;
+ u16 ampdu_id;
+};
+
+struct hal_rx_u_sig_info {
+ bool ul_dl;
+ u8 bw;
+ u8 ppdu_type_comp_mode;
+ u8 eht_sig_mcs;
+ u8 num_eht_sig_sym;
+ struct ieee80211_radiotap_eht_usig usig;
+};
+
+struct hal_rx_tlv_aggr_info {
+ bool in_progress;
+ u16 cur_len;
+ u16 tlv_tag;
+ u8 buf[HAL_RX_MON_MAX_AGGR_SIZE];
+};
+
+struct hal_rx_radiotap_eht {
+ __le32 known;
+ __le32 data[9];
+};
+
+struct hal_rx_eht_info {
+ u8 num_user_info;
+ struct hal_rx_radiotap_eht eht;
+ u32 user_info[EHT_MAX_USER_INFO];
+};
+
+struct hal_rx_msdu_desc_info {
+ u32 msdu_flags;
+ u16 msdu_len; /* 14 bits for length */
+};
+
+/* hal_mon_buf_ring
+ * Producer : SW
+ * Consumer : Monitor
+ *
+ * paddr_lo
+ * Lower 32-bit physical address of the buffer pointer from the source ring.
+ * paddr_hi
+ * bit range 7-0 : upper 8 bit of the physical address.
+ * bit range 31-8 : reserved.
+ * cookie
+ * Consumer: RxMon/TxMon 64 bit cookie of the buffers.
+ */
+struct hal_mon_buf_ring {
+ __le32 paddr_lo;
+ __le32 paddr_hi;
+ __le64 cookie;
+};
+
+struct hal_rx_mon_ppdu_info {
+ u32 ppdu_id;
+ u32 last_ppdu_id;
+ u64 ppdu_ts;
+ u32 num_mpdu_fcs_ok;
+ u32 num_mpdu_fcs_err;
+ u32 preamble_type;
+ u32 mpdu_len;
+ u16 chan_num;
+ u16 freq;
+ u16 tcp_msdu_count;
+ u16 tcp_ack_msdu_count;
+ u16 udp_msdu_count;
+ u16 other_msdu_count;
+ u16 peer_id;
+ u8 rate;
+ u8 mcs;
+ u8 nss;
+ u8 bw;
+ u8 vht_flag_values1;
+ u8 vht_flag_values2;
+ u8 vht_flag_values3[4];
+ u8 vht_flag_values4;
+ u8 vht_flag_values5;
+ u16 vht_flag_values6;
+ u8 is_stbc;
+ u8 gi;
+ u8 sgi;
+ u8 ldpc;
+ u8 beamformed;
+ u8 rssi_comb;
+ u16 tid;
+ u8 fc_valid;
+ u16 ht_flags;
+ u16 vht_flags;
+ u16 he_flags;
+ u16 he_mu_flags;
+ u8 dcm;
+ u8 ru_alloc;
+ u8 reception_type;
+ u64 tsft;
+ u64 rx_duration;
+ u16 frame_control;
+ u32 ast_index;
+ u8 rs_fcs_err;
+ u8 rs_flags;
+ u8 cck_flag;
+ u8 ofdm_flag;
+ u8 ulofdma_flag;
+ u8 frame_control_info_valid;
+ u16 he_per_user_1;
+ u16 he_per_user_2;
+ u8 he_per_user_position;
+ u8 he_per_user_known;
+ u16 he_flags1;
+ u16 he_flags2;
+ u8 he_RU[4];
+ u16 he_data1;
+ u16 he_data2;
+ u16 he_data3;
+ u16 he_data4;
+ u16 he_data5;
+ u16 he_data6;
+ u32 ppdu_len;
+ u32 prev_ppdu_id;
+ u32 device_id;
+ u16 first_data_seq_ctrl;
+ u8 monitor_direct_used;
+ u8 data_sequence_control_info_valid;
+ u8 ltf_size;
+ u8 rxpcu_filter_pass;
+ s8 rssi_chain[8][8];
+ u32 num_users;
+ u32 mpdu_fcs_ok_bitmap[HAL_RX_NUM_WORDS_PER_PPDU_BITMAP];
+ u8 addr1[ETH_ALEN];
+ u8 addr2[ETH_ALEN];
+ u8 addr3[ETH_ALEN];
+ u8 addr4[ETH_ALEN];
+ struct hal_rx_user_status userstats[HAL_MAX_UL_MU_USERS];
+ u8 userid;
+ bool first_msdu_in_mpdu;
+ bool is_ampdu;
+ u8 medium_prot_type;
+ bool ppdu_continuation;
+ bool eht_usig;
+ struct hal_rx_u_sig_info u_sig_info;
+ bool is_eht;
+ struct hal_rx_eht_info eht_info;
+ struct hal_rx_tlv_aggr_info tlv_aggr;
+};
+
+struct hal_rx_desc_data {
+ struct ieee80211_rx_status *rx_status;
+ u32 phy_meta_data;
+ u32 err_bitmap;
+ u32 enctype;
+ u32 msdu_done:1,
+ is_decrypted:1,
+ ip_csum_fail:1,
+ l4_csum_fail:1,
+ is_first_msdu:1,
+ is_last_msdu:1,
+ mesh_ctrl_present:1,
+ addr2_present:1,
+ is_mcbc:1,
+ seq_ctl_valid:1,
+ fc_valid:1;
+ u16 msdu_len;
+ u16 peer_id;
+ u16 seq_no;
+ u8 *addr2;
+ u8 pkt_type;
+ u8 l3_pad_bytes;
+ u8 decap_type;
+ u8 bw;
+ u8 rate_mcs;
+ u8 nss;
+ u8 sgi;
+ u8 tid;
+};
+
+#define BUFFER_ADDR_INFO0_ADDR GENMASK(31, 0)
+
+#define BUFFER_ADDR_INFO1_ADDR GENMASK(7, 0)
+#define BUFFER_ADDR_INFO1_RET_BUF_MGR GENMASK(11, 8)
+#define BUFFER_ADDR_INFO1_SW_COOKIE GENMASK(31, 12)
+
+struct ath12k_buffer_addr {
+ __le32 info0;
+ __le32 info1;
+} __packed;
+
+/* ath12k_buffer_addr
+ *
+ * buffer_addr_31_0
+ * Address (lower 32 bits) of the MSDU buffer or MSDU_EXTENSION
+ * descriptor or Link descriptor
+ *
+ * buffer_addr_39_32
+ * Address (upper 8 bits) of the MSDU buffer or MSDU_EXTENSION
+ * descriptor or Link descriptor
+ *
+ * return_buffer_manager (RBM)
+ * Consumer: WBM
+ * Producer: SW/FW
+ * Indicates to which buffer manager the buffer or MSDU_EXTENSION
+ * descriptor or link descriptor that is being pointed to shall be
+ * returned after the frame has been processed. It is used by WBM
+ * for routing purposes.
+ *
+ * Values are defined in enum %HAL_RX_BUF_RBM_
+ *
+ * sw_buffer_cookie
+ * Cookie field exclusively used by SW. HW ignores the contents,
+ * accept that it passes the programmed value on to other
+ * descriptors together with the physical address.
+ *
+ * Field can be used by SW to for example associate the buffers
+ * physical address with the virtual address.
+ *
+ * NOTE1:
+ * The three most significant bits can have a special meaning
+ * in case this struct is embedded in a TX_MPDU_DETAILS STRUCT,
+ * and field transmit_bw_restriction is set
+ *
+ * In case of NON punctured transmission:
+ * Sw_buffer_cookie[19:17] = 3'b000: 20 MHz TX only
+ * Sw_buffer_cookie[19:17] = 3'b001: 40 MHz TX only
+ * Sw_buffer_cookie[19:17] = 3'b010: 80 MHz TX only
+ * Sw_buffer_cookie[19:17] = 3'b011: 160 MHz TX only
+ * Sw_buffer_cookie[19:17] = 3'b101: 240 MHz TX only
+ * Sw_buffer_cookie[19:17] = 3'b100: 320 MHz TX only
+ * Sw_buffer_cookie[19:18] = 2'b11: reserved
+ *
+ * In case of punctured transmission:
+ * Sw_buffer_cookie[19:16] = 4'b0000: pattern 0 only
+ * Sw_buffer_cookie[19:16] = 4'b0001: pattern 1 only
+ * Sw_buffer_cookie[19:16] = 4'b0010: pattern 2 only
+ * Sw_buffer_cookie[19:16] = 4'b0011: pattern 3 only
+ * Sw_buffer_cookie[19:16] = 4'b0100: pattern 4 only
+ * Sw_buffer_cookie[19:16] = 4'b0101: pattern 5 only
+ * Sw_buffer_cookie[19:16] = 4'b0110: pattern 6 only
+ * Sw_buffer_cookie[19:16] = 4'b0111: pattern 7 only
+ * Sw_buffer_cookie[19:16] = 4'b1000: pattern 8 only
+ * Sw_buffer_cookie[19:16] = 4'b1001: pattern 9 only
+ * Sw_buffer_cookie[19:16] = 4'b1010: pattern 10 only
+ * Sw_buffer_cookie[19:16] = 4'b1011: pattern 11 only
+ * Sw_buffer_cookie[19:18] = 2'b11: reserved
+ *
+ * Note: a punctured transmission is indicated by the presence
+ * of TLV TX_PUNCTURE_SETUP embedded in the scheduler TLV
+ *
+ * Sw_buffer_cookie[20:17]: Tid: The TID field in the QoS control
+ * field
+ *
+ * Sw_buffer_cookie[16]: Mpdu_qos_control_valid: This field
+ * indicates MPDUs with a QoS control field.
+ *
+ */
+
+struct hal_ce_srng_dest_desc;
+struct hal_ce_srng_dst_status_desc;
+struct hal_ce_srng_src_desc;
+
+struct hal_wbm_link_desc {
+ struct ath12k_buffer_addr buf_addr_info;
+} __packed;
+
/* srng flags */
#define HAL_SRNG_FLAGS_MSI_SWAP 0x00000008
#define HAL_SRNG_FLAGS_RING_PTR_SWAP 0x00000010
@@ -634,9 +842,6 @@ enum hal_srng_dir {
#define HAL_SRNG_FLAGS_HIGH_THRESH_INTR_EN 0x00080000
#define HAL_SRNG_FLAGS_LMAC_RING 0x80000000
-#define HAL_SRNG_TLV_HDR_TAG GENMASK(9, 1)
-#define HAL_SRNG_TLV_HDR_LEN GENMASK(25, 10)
-
/* Common SRNG ring structure for source and destination rings */
struct hal_srng {
/* Unique SRNG ring ID */
@@ -758,6 +963,51 @@ struct hal_srng {
} u;
};
+/* hal_wbm_link_desc
+ *
+ * Producer: WBM
+ * Consumer: WBM
+ *
+ * buf_addr_info
+ * Details of the physical address of a buffer or MSDU
+ * link descriptor.
+ */
+
+enum hal_wbm_rel_src_module {
+ HAL_WBM_REL_SRC_MODULE_TQM,
+ HAL_WBM_REL_SRC_MODULE_RXDMA,
+ HAL_WBM_REL_SRC_MODULE_REO,
+ HAL_WBM_REL_SRC_MODULE_FW,
+ HAL_WBM_REL_SRC_MODULE_SW,
+ HAL_WBM_REL_SRC_MODULE_MAX,
+};
+
+/* hal_wbm_rel_desc_type
+ *
+ * msdu_buffer
+ * The address points to an MSDU buffer
+ *
+ * msdu_link_descriptor
+ * The address points to an Tx MSDU link descriptor
+ *
+ * mpdu_link_descriptor
+ * The address points to an MPDU link descriptor
+ *
+ * msdu_ext_descriptor
+ * The address points to an MSDU extension descriptor
+ *
+ * queue_ext_descriptor
+ * The address points to an TQM queue extension descriptor. WBM should
+ * treat this is the same way as a link descriptor.
+ */
+enum hal_wbm_rel_desc_type {
+ HAL_WBM_REL_DESC_TYPE_REL_MSDU,
+ HAL_WBM_REL_DESC_TYPE_MSDU_LINK,
+ HAL_WBM_REL_DESC_TYPE_MPDU_LINK,
+ HAL_WBM_REL_DESC_TYPE_MSDU_EXT,
+ HAL_WBM_REL_DESC_TYPE_QUEUE_EXT,
+};
+
/* Interrupt mitigation - Batch threshold in terms of number of frames */
#define HAL_SRNG_INT_BATCH_THRESHOLD_TX 256
#define HAL_SRNG_INT_BATCH_THRESHOLD_RX 128
@@ -821,66 +1071,6 @@ enum hal_rx_buf_return_buf_manager {
HAL_RX_BUF_RBM_SW6_BM,
};
-#define HAL_SRNG_DESC_LOOP_CNT 0xf0000000
-
-#define HAL_REO_CMD_FLG_NEED_STATUS BIT(0)
-#define HAL_REO_CMD_FLG_STATS_CLEAR BIT(1)
-#define HAL_REO_CMD_FLG_FLUSH_BLOCK_LATER BIT(2)
-#define HAL_REO_CMD_FLG_FLUSH_RELEASE_BLOCKING BIT(3)
-#define HAL_REO_CMD_FLG_FLUSH_NO_INVAL BIT(4)
-#define HAL_REO_CMD_FLG_FLUSH_FWD_ALL_MPDUS BIT(5)
-#define HAL_REO_CMD_FLG_FLUSH_ALL BIT(6)
-#define HAL_REO_CMD_FLG_UNBLK_RESOURCE BIT(7)
-#define HAL_REO_CMD_FLG_UNBLK_CACHE BIT(8)
-#define HAL_REO_CMD_FLG_FLUSH_QUEUE_1K_DESC BIT(9)
-
-/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO0_UPD_* fields */
-#define HAL_REO_CMD_UPD0_RX_QUEUE_NUM BIT(8)
-#define HAL_REO_CMD_UPD0_VLD BIT(9)
-#define HAL_REO_CMD_UPD0_ALDC BIT(10)
-#define HAL_REO_CMD_UPD0_DIS_DUP_DETECTION BIT(11)
-#define HAL_REO_CMD_UPD0_SOFT_REORDER_EN BIT(12)
-#define HAL_REO_CMD_UPD0_AC BIT(13)
-#define HAL_REO_CMD_UPD0_BAR BIT(14)
-#define HAL_REO_CMD_UPD0_RETRY BIT(15)
-#define HAL_REO_CMD_UPD0_CHECK_2K_MODE BIT(16)
-#define HAL_REO_CMD_UPD0_OOR_MODE BIT(17)
-#define HAL_REO_CMD_UPD0_BA_WINDOW_SIZE BIT(18)
-#define HAL_REO_CMD_UPD0_PN_CHECK BIT(19)
-#define HAL_REO_CMD_UPD0_EVEN_PN BIT(20)
-#define HAL_REO_CMD_UPD0_UNEVEN_PN BIT(21)
-#define HAL_REO_CMD_UPD0_PN_HANDLE_ENABLE BIT(22)
-#define HAL_REO_CMD_UPD0_PN_SIZE BIT(23)
-#define HAL_REO_CMD_UPD0_IGNORE_AMPDU_FLG BIT(24)
-#define HAL_REO_CMD_UPD0_SVLD BIT(25)
-#define HAL_REO_CMD_UPD0_SSN BIT(26)
-#define HAL_REO_CMD_UPD0_SEQ_2K_ERR BIT(27)
-#define HAL_REO_CMD_UPD0_PN_ERR BIT(28)
-#define HAL_REO_CMD_UPD0_PN_VALID BIT(29)
-#define HAL_REO_CMD_UPD0_PN BIT(30)
-
-/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO1_* fields */
-#define HAL_REO_CMD_UPD1_VLD BIT(16)
-#define HAL_REO_CMD_UPD1_ALDC GENMASK(18, 17)
-#define HAL_REO_CMD_UPD1_DIS_DUP_DETECTION BIT(19)
-#define HAL_REO_CMD_UPD1_SOFT_REORDER_EN BIT(20)
-#define HAL_REO_CMD_UPD1_AC GENMASK(22, 21)
-#define HAL_REO_CMD_UPD1_BAR BIT(23)
-#define HAL_REO_CMD_UPD1_RETRY BIT(24)
-#define HAL_REO_CMD_UPD1_CHECK_2K_MODE BIT(25)
-#define HAL_REO_CMD_UPD1_OOR_MODE BIT(26)
-#define HAL_REO_CMD_UPD1_PN_CHECK BIT(27)
-#define HAL_REO_CMD_UPD1_EVEN_PN BIT(28)
-#define HAL_REO_CMD_UPD1_UNEVEN_PN BIT(29)
-#define HAL_REO_CMD_UPD1_PN_HANDLE_ENABLE BIT(30)
-#define HAL_REO_CMD_UPD1_IGNORE_AMPDU_FLG BIT(31)
-
-/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO2_* fields */
-#define HAL_REO_CMD_UPD2_SVLD BIT(10)
-#define HAL_REO_CMD_UPD2_SSN GENMASK(22, 11)
-#define HAL_REO_CMD_UPD2_SEQ_2K_ERR BIT(23)
-#define HAL_REO_CMD_UPD2_PN_ERR BIT(24)
-
struct ath12k_hal_reo_cmd {
u32 addr_lo;
u32 flag;
@@ -926,91 +1116,93 @@ struct hal_reo_status_header {
u32 timestamp;
};
-struct hal_reo_status_queue_stats {
- u16 ssn;
- u16 curr_idx;
- u32 pn[4];
- u32 last_rx_queue_ts;
- u32 last_rx_dequeue_ts;
- u32 rx_bitmap[8]; /* Bitmap from 0-255 */
- u32 curr_mpdu_cnt;
- u32 curr_msdu_cnt;
- u16 fwd_due_to_bar_cnt;
- u16 dup_cnt;
- u32 frames_in_order_cnt;
- u32 num_mpdu_processed_cnt;
- u32 num_msdu_processed_cnt;
- u32 total_num_processed_byte_cnt;
- u32 late_rx_mpdu_cnt;
- u32 reorder_hole_cnt;
- u8 timeout_cnt;
- u8 bar_rx_cnt;
- u8 num_window_2k_jump_cnt;
-};
-
-struct hal_reo_status_flush_queue {
- bool err_detected;
+struct ath12k_hw_hal_params {
+ enum hal_rx_buf_return_buf_manager rx_buf_rbm;
+ u32 wbm2sw_cc_enable;
};
-enum hal_reo_status_flush_cache_err_code {
- HAL_REO_STATUS_FLUSH_CACHE_ERR_CODE_SUCCESS,
- HAL_REO_STATUS_FLUSH_CACHE_ERR_CODE_IN_USE,
- HAL_REO_STATUS_FLUSH_CACHE_ERR_CODE_NOT_FOUND,
-};
-
-struct hal_reo_status_flush_cache {
- bool err_detected;
- enum hal_reo_status_flush_cache_err_code err_code;
- bool cache_controller_flush_status_hit;
- u8 cache_controller_flush_status_desc_type;
- u8 cache_controller_flush_status_client_id;
- u8 cache_controller_flush_status_err;
- u8 cache_controller_flush_status_cnt;
-};
-
-enum hal_reo_status_unblock_cache_type {
- HAL_REO_STATUS_UNBLOCK_BLOCKING_RESOURCE,
- HAL_REO_STATUS_UNBLOCK_ENTIRE_CACHE_USAGE,
-};
-
-struct hal_reo_status_unblock_cache {
- bool err_detected;
- enum hal_reo_status_unblock_cache_type unblock_type;
-};
-
-struct hal_reo_status_flush_timeout_list {
- bool err_detected;
- bool list_empty;
- u16 release_desc_cnt;
- u16 fwd_buf_cnt;
-};
-
-enum hal_reo_threshold_idx {
- HAL_REO_THRESHOLD_IDX_DESC_COUNTER0,
- HAL_REO_THRESHOLD_IDX_DESC_COUNTER1,
- HAL_REO_THRESHOLD_IDX_DESC_COUNTER2,
- HAL_REO_THRESHOLD_IDX_DESC_COUNTER_SUM,
-};
-
-struct hal_reo_status_desc_thresh_reached {
- enum hal_reo_threshold_idx threshold_idx;
- u32 link_desc_counter0;
- u32 link_desc_counter1;
- u32 link_desc_counter2;
- u32 link_desc_counter_sum;
-};
-
-struct hal_reo_status {
- struct hal_reo_status_header uniform_hdr;
- u8 loop_cnt;
- union {
- struct hal_reo_status_queue_stats queue_stats;
- struct hal_reo_status_flush_queue flush_queue;
- struct hal_reo_status_flush_cache flush_cache;
- struct hal_reo_status_unblock_cache unblock_cache;
- struct hal_reo_status_flush_timeout_list timeout_list;
- struct hal_reo_status_desc_thresh_reached desc_thresh_reached;
- } u;
+#define ATH12K_HW_REG_UNDEFINED 0xdeadbeaf
+
+struct ath12k_hw_regs {
+ u32 tcl1_ring_id;
+ u32 tcl1_ring_misc;
+ u32 tcl1_ring_tp_addr_lsb;
+ u32 tcl1_ring_tp_addr_msb;
+ u32 tcl1_ring_consumer_int_setup_ix0;
+ u32 tcl1_ring_consumer_int_setup_ix1;
+ u32 tcl1_ring_msi1_base_lsb;
+ u32 tcl1_ring_msi1_base_msb;
+ u32 tcl1_ring_msi1_data;
+ u32 tcl_ring_base_lsb;
+ u32 tcl1_ring_base_lsb;
+ u32 tcl1_ring_base_msb;
+ u32 tcl2_ring_base_lsb;
+
+ u32 tcl_status_ring_base_lsb;
+
+ u32 reo1_qdesc_addr;
+ u32 reo1_qdesc_max_peerid;
+
+ u32 wbm_idle_ring_base_lsb;
+ u32 wbm_idle_ring_misc_addr;
+ u32 wbm_r0_idle_list_cntl_addr;
+ u32 wbm_r0_idle_list_size_addr;
+ u32 wbm_scattered_ring_base_lsb;
+ u32 wbm_scattered_ring_base_msb;
+ u32 wbm_scattered_desc_head_info_ix0;
+ u32 wbm_scattered_desc_head_info_ix1;
+ u32 wbm_scattered_desc_tail_info_ix0;
+ u32 wbm_scattered_desc_tail_info_ix1;
+ u32 wbm_scattered_desc_ptr_hp_addr;
+
+ u32 wbm_sw_release_ring_base_lsb;
+ u32 wbm_sw1_release_ring_base_lsb;
+ u32 wbm0_release_ring_base_lsb;
+ u32 wbm1_release_ring_base_lsb;
+
+ u32 pcie_qserdes_sysclk_en_sel;
+ u32 pcie_pcs_osc_dtct_config_base;
+
+ u32 umac_ce0_src_reg_base;
+ u32 umac_ce0_dest_reg_base;
+ u32 umac_ce1_src_reg_base;
+ u32 umac_ce1_dest_reg_base;
+
+ u32 ppe_rel_ring_base;
+
+ u32 reo2_ring_base;
+ u32 reo1_misc_ctrl_addr;
+ u32 reo1_sw_cookie_cfg0;
+ u32 reo1_sw_cookie_cfg1;
+ u32 reo1_qdesc_lut_base0;
+ u32 reo1_qdesc_lut_base1;
+ u32 reo1_ring_base_lsb;
+ u32 reo1_ring_base_msb;
+ u32 reo1_ring_id;
+ u32 reo1_ring_misc;
+ u32 reo1_ring_hp_addr_lsb;
+ u32 reo1_ring_hp_addr_msb;
+ u32 reo1_ring_producer_int_setup;
+ u32 reo1_ring_msi1_base_lsb;
+ u32 reo1_ring_msi1_base_msb;
+ u32 reo1_ring_msi1_data;
+ u32 reo1_aging_thres_ix0;
+ u32 reo1_aging_thres_ix1;
+ u32 reo1_aging_thres_ix2;
+ u32 reo1_aging_thres_ix3;
+
+ u32 reo2_sw0_ring_base;
+
+ u32 sw2reo_ring_base;
+ u32 sw2reo1_ring_base;
+
+ u32 reo_cmd_ring_base;
+
+ u32 reo_status_ring_base;
+
+ u32 gcc_gcc_pcie_hot_rst;
+
+ u32 qrtr_node_id;
};
/* HAL context to be used to access SRNG APIs (currently used by data path
@@ -1036,16 +1228,23 @@ struct ath12k_hal {
dma_addr_t paddr;
} wrp;
+ struct device *dev;
+ const struct hal_ops *ops;
+ const struct ath12k_hw_regs *regs;
+ const struct ath12k_hw_hal_params *hal_params;
/* Available REO blocking resources bitmap */
u8 avail_blk_resource;
u8 current_blk_index;
/* shadow register configuration */
- u32 shadow_reg_addr[HAL_SHADOW_NUM_REGS];
+ u32 shadow_reg_addr[HAL_SHADOW_NUM_REGS_MAX];
int num_shadow_reg_configured;
u32 hal_desc_sz;
+ u32 hal_wbm_release_ring_tx_size;
+
+ const struct ath12k_hal_tcl_to_wbm_rbm_map *tcl_to_wbm_rbm_map;
};
/* Maps WBM ring number and Return Buffer Manager Id per TCL ring */
@@ -1054,92 +1253,223 @@ struct ath12k_hal_tcl_to_wbm_rbm_map {
u8 rbm_id;
};
-struct hal_rx_ops {
- bool (*rx_desc_get_first_msdu)(struct hal_rx_desc *desc);
- bool (*rx_desc_get_last_msdu)(struct hal_rx_desc *desc);
- u8 (*rx_desc_get_l3_pad_bytes)(struct hal_rx_desc *desc);
- u8 *(*rx_desc_get_hdr_status)(struct hal_rx_desc *desc);
- bool (*rx_desc_encrypt_valid)(struct hal_rx_desc *desc);
- u32 (*rx_desc_get_encrypt_type)(struct hal_rx_desc *desc);
- u8 (*rx_desc_get_decap_type)(struct hal_rx_desc *desc);
- u8 (*rx_desc_get_mesh_ctl)(struct hal_rx_desc *desc);
- bool (*rx_desc_get_mpdu_seq_ctl_vld)(struct hal_rx_desc *desc);
- bool (*rx_desc_get_mpdu_fc_valid)(struct hal_rx_desc *desc);
- u16 (*rx_desc_get_mpdu_start_seq_no)(struct hal_rx_desc *desc);
- u16 (*rx_desc_get_msdu_len)(struct hal_rx_desc *desc);
- u8 (*rx_desc_get_msdu_sgi)(struct hal_rx_desc *desc);
- u8 (*rx_desc_get_msdu_rate_mcs)(struct hal_rx_desc *desc);
- u8 (*rx_desc_get_msdu_rx_bw)(struct hal_rx_desc *desc);
- u32 (*rx_desc_get_msdu_freq)(struct hal_rx_desc *desc);
- u8 (*rx_desc_get_msdu_pkt_type)(struct hal_rx_desc *desc);
- u8 (*rx_desc_get_msdu_nss)(struct hal_rx_desc *desc);
- u8 (*rx_desc_get_mpdu_tid)(struct hal_rx_desc *desc);
- u16 (*rx_desc_get_mpdu_peer_id)(struct hal_rx_desc *desc);
- void (*rx_desc_copy_end_tlv)(struct hal_rx_desc *fdesc,
- struct hal_rx_desc *ldesc);
- u32 (*rx_desc_get_mpdu_start_tag)(struct hal_rx_desc *desc);
- u32 (*rx_desc_get_mpdu_ppdu_id)(struct hal_rx_desc *desc);
+enum hal_wbm_rel_bm_act {
+ HAL_WBM_REL_BM_ACT_PUT_IN_IDLE,
+ HAL_WBM_REL_BM_ACT_REL_MSDU,
+};
+
+/* hal_wbm_rel_bm_act
+ *
+ * put_in_idle_list
+ * Put the buffer or descriptor back in the idle list. In case of MSDU or
+ * MDPU link descriptor, BM does not need to check to release any
+ * individual MSDU buffers.
+ *
+ * release_msdu_list
+ * This BM action can only be used in combination with desc_type being
+ * msdu_link_descriptor. Field first_msdu_index points out which MSDU
+ * pointer in the MSDU link descriptor is the first of an MPDU that is
+ * released. BM shall release all the MSDU buffers linked to this first
+ * MSDU buffer pointer. All related MSDU buffer pointer entries shall be
+ * set to value 0, which represents the 'NULL' pointer. When all MSDU
+ * buffer pointers in the MSDU link descriptor are 'NULL', the MSDU link
+ * descriptor itself shall also be released.
+ */
+
+#define RU_INVALID 0
+#define RU_26 1
+#define RU_52 2
+#define RU_106 4
+#define RU_242 9
+#define RU_484 18
+#define RU_996 37
+#define RU_2X996 74
+#define RU_3X996 111
+#define RU_4X996 148
+#define RU_52_26 (RU_52 + RU_26)
+#define RU_106_26 (RU_106 + RU_26)
+#define RU_484_242 (RU_484 + RU_242)
+#define RU_996_484 (RU_996 + RU_484)
+#define RU_996_484_242 (RU_996 + RU_484_242)
+#define RU_2X996_484 (RU_2X996 + RU_484)
+#define RU_3X996_484 (RU_3X996 + RU_484)
+
+enum ath12k_eht_ru_size {
+ ATH12K_EHT_RU_26,
+ ATH12K_EHT_RU_52,
+ ATH12K_EHT_RU_106,
+ ATH12K_EHT_RU_242,
+ ATH12K_EHT_RU_484,
+ ATH12K_EHT_RU_996,
+ ATH12K_EHT_RU_996x2,
+ ATH12K_EHT_RU_996x4,
+ ATH12K_EHT_RU_52_26,
+ ATH12K_EHT_RU_106_26,
+ ATH12K_EHT_RU_484_242,
+ ATH12K_EHT_RU_996_484,
+ ATH12K_EHT_RU_996_484_242,
+ ATH12K_EHT_RU_996x2_484,
+ ATH12K_EHT_RU_996x3,
+ ATH12K_EHT_RU_996x3_484,
+
+ /* Keep last */
+ ATH12K_EHT_RU_INVALID,
+};
+
+#define HAL_RX_RU_ALLOC_TYPE_MAX ATH12K_EHT_RU_INVALID
+
+static inline
+enum nl80211_he_ru_alloc ath12k_he_ru_tones_to_nl80211_he_ru_alloc(u16 ru_tones)
+{
+ enum nl80211_he_ru_alloc ret;
+
+ switch (ru_tones) {
+ case RU_52:
+ ret = NL80211_RATE_INFO_HE_RU_ALLOC_52;
+ break;
+ case RU_106:
+ ret = NL80211_RATE_INFO_HE_RU_ALLOC_106;
+ break;
+ case RU_242:
+ ret = NL80211_RATE_INFO_HE_RU_ALLOC_242;
+ break;
+ case RU_484:
+ ret = NL80211_RATE_INFO_HE_RU_ALLOC_484;
+ break;
+ case RU_996:
+ ret = NL80211_RATE_INFO_HE_RU_ALLOC_996;
+ break;
+ case RU_2X996:
+ ret = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
+ break;
+ case RU_26:
+ fallthrough;
+ default:
+ ret = NL80211_RATE_INFO_HE_RU_ALLOC_26;
+ break;
+ }
+ return ret;
+}
+
+struct ath12k_hw_version_map {
+ const struct hal_ops *hal_ops;
+ u32 hal_desc_sz;
+ const struct ath12k_hal_tcl_to_wbm_rbm_map *tcl_to_wbm_rbm_map;
+ const struct ath12k_hw_hal_params *hal_params;
+ const struct ath12k_hw_regs *hw_regs;
+};
+
+struct hal_ops {
+ int (*create_srng_config)(struct ath12k_hal *hal);
void (*rx_desc_set_msdu_len)(struct hal_rx_desc *desc, u16 len);
- struct rx_attention *(*rx_desc_get_attention)(struct hal_rx_desc *desc);
- u8 *(*rx_desc_get_msdu_payload)(struct hal_rx_desc *desc);
- u32 (*rx_desc_get_mpdu_start_offset)(void);
- u32 (*rx_desc_get_msdu_end_offset)(void);
- bool (*rx_desc_mac_addr2_valid)(struct hal_rx_desc *desc);
- u8* (*rx_desc_mpdu_start_addr2)(struct hal_rx_desc *desc);
- bool (*rx_desc_is_da_mcbc)(struct hal_rx_desc *desc);
void (*rx_desc_get_dot11_hdr)(struct hal_rx_desc *desc,
struct ieee80211_hdr *hdr);
void (*rx_desc_get_crypto_header)(struct hal_rx_desc *desc,
u8 *crypto_hdr,
enum hal_encrypt_type enctype);
- bool (*dp_rx_h_msdu_done)(struct hal_rx_desc *desc);
- bool (*dp_rx_h_l4_cksum_fail)(struct hal_rx_desc *desc);
- bool (*dp_rx_h_ip_cksum_fail)(struct hal_rx_desc *desc);
- bool (*dp_rx_h_is_decrypted)(struct hal_rx_desc *desc);
- u32 (*dp_rx_h_mpdu_err)(struct hal_rx_desc *desc);
- u32 (*rx_desc_get_desc_size)(void);
+ void (*rx_desc_copy_end_tlv)(struct hal_rx_desc *fdesc,
+ struct hal_rx_desc *ldesc);
u8 (*rx_desc_get_msdu_src_link_id)(struct hal_rx_desc *desc);
+ void (*extract_rx_desc_data)(struct hal_rx_desc_data *rx_desc_data,
+ struct hal_rx_desc *rx_desc,
+ struct hal_rx_desc *ldesc);
+ u32 (*rx_desc_get_mpdu_start_tag)(struct hal_rx_desc *desc);
+ u32 (*rx_desc_get_mpdu_ppdu_id)(struct hal_rx_desc *desc);
+ u8 (*rx_desc_get_l3_pad_bytes)(struct hal_rx_desc *desc);
+ u8 *(*rx_desc_get_msdu_payload)(struct hal_rx_desc *desc);
+ void (*ce_dst_setup)(struct ath12k_base *ab,
+ struct hal_srng *srng, int ring_num);
+ void (*set_umac_srng_ptr_addr)(struct ath12k_base *ab,
+ struct hal_srng *srng);
+ void (*srng_src_hw_init)(struct ath12k_base *ab, struct hal_srng *srng);
+ void (*srng_dst_hw_init)(struct ath12k_base *ab, struct hal_srng *srng);
+ int (*srng_update_shadow_config)(struct ath12k_base *ab,
+ enum hal_ring_type ring_type,
+ int ring_num);
+ int (*srng_get_ring_id)(struct ath12k_hal *hal, enum hal_ring_type type,
+ int ring_num, int mac_id);
+ u32 (*ce_get_desc_size)(enum hal_ce_desc type);
+ void (*ce_src_set_desc)(struct hal_ce_srng_src_desc *desc,
+ dma_addr_t paddr, u32 len, u32 id,
+ u8 byte_swap_data);
+ void (*ce_dst_set_desc)(struct hal_ce_srng_dest_desc *desc,
+ dma_addr_t paddr);
+ u32 (*ce_dst_status_get_length)(struct hal_ce_srng_dst_status_desc *desc);
+ void (*set_link_desc_addr)(struct hal_wbm_link_desc *desc, u32 cookie,
+ dma_addr_t paddr,
+ enum hal_rx_buf_return_buf_manager rbm);
+ void (*tx_set_dscp_tid_map)(struct ath12k_base *ab, int id);
+ void (*tx_configure_bank_register)(struct ath12k_base *ab,
+ u32 bank_config, u8 bank_id);
+ void (*reoq_lut_addr_read_enable)(struct ath12k_base *ab);
+ void (*reoq_lut_set_max_peerid)(struct ath12k_base *ab);
+ void (*write_ml_reoq_lut_addr)(struct ath12k_base *ab,
+ dma_addr_t paddr);
+ void (*write_reoq_lut_addr)(struct ath12k_base *ab, dma_addr_t paddr);
+ void (*setup_link_idle_list)(struct ath12k_base *ab,
+ struct hal_wbm_idle_scatter_list *sbuf,
+ u32 nsbufs, u32 tot_link_desc,
+ u32 end_offset);
+ void (*reo_init_cmd_ring)(struct ath12k_base *ab,
+ struct hal_srng *srng);
+ void (*reo_shared_qaddr_cache_clear)(struct ath12k_base *ab);
+ void (*reo_hw_setup)(struct ath12k_base *ab, u32 ring_hash_map);
+ void (*rx_buf_addr_info_set)(struct ath12k_buffer_addr *binfo,
+ dma_addr_t paddr, u32 cookie, u8 manager);
+ void (*rx_buf_addr_info_get)(struct ath12k_buffer_addr *binfo,
+ dma_addr_t *paddr, u32 *msdu_cookies,
+ u8 *rbm);
+ void (*cc_config)(struct ath12k_base *ab);
+ enum hal_rx_buf_return_buf_manager
+ (*get_idle_link_rbm)(struct ath12k_hal *hal, u8 device_id);
+ void (*rx_msdu_list_get)(struct ath12k *ar,
+ void *link_desc,
+ void *msdu_list,
+ u16 *num_msdus);
+ void (*rx_reo_ent_buf_paddr_get)(void *rx_desc, dma_addr_t *paddr,
+ u32 *sw_cookie,
+ struct ath12k_buffer_addr **pp_buf_addr,
+ u8 *rbm, u32 *msdu_cnt);
+ void *(*reo_cmd_enc_tlv_hdr)(void *tlv, u64 tag, u64 len);
+ u16 (*reo_status_dec_tlv_hdr)(void *tlv, void **desc);
};
-struct hal_ops {
- int (*create_srng_config)(struct ath12k_base *ab);
- u16 (*rxdma_ring_wmask_rx_mpdu_start)(void);
- u32 (*rxdma_ring_wmask_rx_msdu_end)(void);
- const struct hal_rx_ops *(*get_hal_rx_compact_ops)(void);
- const struct ath12k_hal_tcl_to_wbm_rbm_map *tcl_to_wbm_rbm_map;
-};
+#define HAL_TLV_HDR_TAG GENMASK(9, 1)
+#define HAL_TLV_HDR_LEN GENMASK(25, 10)
+#define HAL_TLV_USR_ID GENMASK(31, 26)
-extern const struct hal_ops hal_qcn9274_ops;
-extern const struct hal_ops hal_wcn7850_ops;
+#define HAL_TLV_ALIGN 4
-extern const struct hal_rx_ops hal_rx_qcn9274_ops;
-extern const struct hal_rx_ops hal_rx_qcn9274_compact_ops;
-extern const struct hal_rx_ops hal_rx_wcn7850_ops;
+struct hal_tlv_hdr {
+ __le32 tl;
+ u8 value[];
+} __packed;
-u32 ath12k_hal_reo_qdesc_size(u32 ba_window_size, u8 tid);
-void ath12k_hal_reo_qdesc_setup(struct hal_rx_reo_queue *qdesc,
- int tid, u32 ba_window_size,
- u32 start_seq, enum hal_pn_type type);
-void ath12k_hal_reo_init_cmd_ring(struct ath12k_base *ab,
- struct hal_srng *srng);
-void ath12k_hal_reo_hw_setup(struct ath12k_base *ab, u32 ring_hash_map);
-void ath12k_hal_setup_link_idle_list(struct ath12k_base *ab,
- struct hal_wbm_idle_scatter_list *sbuf,
- u32 nsbufs, u32 tot_link_desc,
- u32 end_offset);
+#define HAL_TLV_64_HDR_TAG GENMASK(9, 1)
+#define HAL_TLV_64_HDR_LEN GENMASK(21, 10)
+#define HAL_TLV_64_USR_ID GENMASK(31, 26)
+#define HAL_TLV_64_ALIGN 8
+
+struct hal_tlv_64_hdr {
+ __le64 tl;
+ u8 value[];
+} __packed;
+
+#define HAL_SRNG_TLV_HDR_TAG GENMASK(9, 1)
+#define HAL_SRNG_TLV_HDR_LEN GENMASK(25, 10)
dma_addr_t ath12k_hal_srng_get_tp_addr(struct ath12k_base *ab,
struct hal_srng *srng);
dma_addr_t ath12k_hal_srng_get_hp_addr(struct ath12k_base *ab,
struct hal_srng *srng);
-void ath12k_hal_set_link_desc_addr(struct hal_wbm_link_desc *desc, u32 cookie,
- dma_addr_t paddr,
- enum hal_rx_buf_return_buf_manager rbm);
-u32 ath12k_hal_ce_get_desc_size(enum hal_ce_desc type);
-void ath12k_hal_ce_src_set_desc(struct hal_ce_srng_src_desc *desc, dma_addr_t paddr,
- u32 len, u32 id, u8 byte_swap_data);
-void ath12k_hal_ce_dst_set_desc(struct hal_ce_srng_dest_desc *desc, dma_addr_t paddr);
-u32 ath12k_hal_ce_dst_status_get_length(struct hal_ce_srng_dst_status_desc *desc);
+u32 ath12k_hal_ce_get_desc_size(struct ath12k_hal *hal, enum hal_ce_desc type);
+void ath12k_hal_ce_dst_set_desc(struct ath12k_hal *hal,
+ struct hal_ce_srng_dest_desc *desc,
+ dma_addr_t paddr);
+void ath12k_hal_ce_src_set_desc(struct ath12k_hal *hal,
+ struct hal_ce_srng_src_desc *desc,
+ dma_addr_t paddr, u32 len, u32 id,
+ u8 byte_swap_data);
int ath12k_hal_srng_get_entrysize(struct ath12k_base *ab, u32 ring_type);
int ath12k_hal_srng_get_max_entries(struct ath12k_base *ab, u32 ring_type);
void ath12k_hal_srng_get_params(struct ath12k_base *ab, struct hal_srng *srng,
@@ -1178,4 +1508,45 @@ void ath12k_hal_srng_shadow_config(struct ath12k_base *ab);
void ath12k_hal_srng_shadow_update_hp_tp(struct ath12k_base *ab,
struct hal_srng *srng);
void ath12k_hal_reo_shared_qaddr_cache_clear(struct ath12k_base *ab);
+void ath12k_hal_set_link_desc_addr(struct ath12k_hal *hal,
+ struct hal_wbm_link_desc *desc, u32 cookie,
+ dma_addr_t paddr, int rbm);
+void ath12k_hal_setup_link_idle_list(struct ath12k_base *ab,
+ struct hal_wbm_idle_scatter_list *sbuf,
+ u32 nsbufs, u32 tot_link_desc,
+ u32 end_offset);
+u32
+ath12k_hal_ce_dst_status_get_length(struct ath12k_hal *hal,
+ struct hal_ce_srng_dst_status_desc *desc);
+void ath12k_hal_tx_set_dscp_tid_map(struct ath12k_base *ab, int id);
+void ath12k_hal_tx_configure_bank_register(struct ath12k_base *ab,
+ u32 bank_config, u8 bank_id);
+void ath12k_hal_reoq_lut_addr_read_enable(struct ath12k_base *ab);
+void ath12k_hal_reoq_lut_set_max_peerid(struct ath12k_base *ab);
+void ath12k_hal_write_reoq_lut_addr(struct ath12k_base *ab, dma_addr_t paddr);
+void
+ath12k_hal_write_ml_reoq_lut_addr(struct ath12k_base *ab, dma_addr_t paddr);
+void ath12k_hal_reo_init_cmd_ring(struct ath12k_base *ab, struct hal_srng *srng);
+void ath12k_hal_reo_hw_setup(struct ath12k_base *ab, u32 ring_hash_map);
+void ath12k_hal_rx_buf_addr_info_set(struct ath12k_hal *hal,
+ struct ath12k_buffer_addr *binfo,
+ dma_addr_t paddr, u32 cookie, u8 manager);
+void ath12k_hal_rx_buf_addr_info_get(struct ath12k_hal *hal,
+ struct ath12k_buffer_addr *binfo,
+ dma_addr_t *paddr, u32 *msdu_cookies,
+ u8 *rbm);
+void ath12k_hal_cc_config(struct ath12k_base *ab);
+enum hal_rx_buf_return_buf_manager
+ath12k_hal_get_idle_link_rbm(struct ath12k_hal *hal, u8 device_id);
+void ath12k_hal_rx_msdu_list_get(struct ath12k_hal *hal, struct ath12k *ar,
+ void *link_desc, void *msdu_list,
+ u16 *num_msdus);
+void ath12k_hal_rx_reo_ent_buf_paddr_get(struct ath12k_hal *hal, void *rx_desc,
+ dma_addr_t *paddr, u32 *sw_cookie,
+ struct ath12k_buffer_addr **pp_buf_addr,
+ u8 *rbm, u32 *msdu_cnt);
+void *ath12k_hal_encode_tlv64_hdr(void *tlv, u64 tag, u64 len);
+void *ath12k_hal_encode_tlv32_hdr(void *tlv, u64 tag, u64 len);
+u16 ath12k_hal_decode_tlv64_hdr(void *tlv, void **desc);
+u16 ath12k_hal_decode_tlv32_hdr(void *tlv, void **desc);
#endif
diff --git a/drivers/net/wireless/ath/ath12k/htc.c b/drivers/net/wireless/ath/ath12k/htc.c
index d13616bf07f4..92138caa2a82 100644
--- a/drivers/net/wireless/ath/ath12k/htc.c
+++ b/drivers/net/wireless/ath/ath12k/htc.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, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/skbuff.h>
#include <linux/ctype.h>
@@ -376,6 +376,7 @@ void ath12k_htc_rx_completion_handler(struct ath12k_base *ab,
out:
kfree_skb(skb);
}
+EXPORT_SYMBOL(ath12k_htc_rx_completion_handler);
static void ath12k_htc_control_rx_complete(struct ath12k_base *ab,
struct sk_buff *skb)
diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c
deleted file mode 100644
index 6791ae1d64e5..000000000000
--- a/drivers/net/wireless/ath/ath12k/hw.c
+++ /dev/null
@@ -1,1680 +0,0 @@
-// SPDX-License-Identifier: BSD-3-Clause-Clear
-/*
- * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
- */
-
-#include <linux/types.h>
-#include <linux/bitops.h>
-#include <linux/bitfield.h>
-
-#include "debug.h"
-#include "core.h"
-#include "ce.h"
-#include "hw.h"
-#include "mhi.h"
-#include "dp_rx.h"
-#include "peer.h"
-
-static const guid_t wcn7850_uuid = GUID_INIT(0xf634f534, 0x6147, 0x11ec,
- 0x90, 0xd6, 0x02, 0x42,
- 0xac, 0x12, 0x00, 0x03);
-
-static u8 ath12k_hw_qcn9274_mac_from_pdev_id(int pdev_idx)
-{
- return pdev_idx;
-}
-
-static int ath12k_hw_mac_id_to_pdev_id_qcn9274(const struct ath12k_hw_params *hw,
- int mac_id)
-{
- return mac_id;
-}
-
-static int ath12k_hw_mac_id_to_srng_id_qcn9274(const struct ath12k_hw_params *hw,
- int mac_id)
-{
- return 0;
-}
-
-static u8 ath12k_hw_get_ring_selector_qcn9274(struct sk_buff *skb)
-{
- return smp_processor_id();
-}
-
-static bool ath12k_dp_srng_is_comp_ring_qcn9274(int ring_num)
-{
- if (ring_num < 3 || ring_num == 4)
- return true;
-
- return false;
-}
-
-static bool ath12k_is_frame_link_agnostic_qcn9274(struct ath12k_link_vif *arvif,
- struct ieee80211_mgmt *mgmt)
-{
- return ieee80211_is_action(mgmt->frame_control);
-}
-
-static int ath12k_hw_mac_id_to_pdev_id_wcn7850(const struct ath12k_hw_params *hw,
- int mac_id)
-{
- return 0;
-}
-
-static int ath12k_hw_mac_id_to_srng_id_wcn7850(const struct ath12k_hw_params *hw,
- int mac_id)
-{
- return mac_id;
-}
-
-static u8 ath12k_hw_get_ring_selector_wcn7850(struct sk_buff *skb)
-{
- return skb_get_queue_mapping(skb);
-}
-
-static bool ath12k_dp_srng_is_comp_ring_wcn7850(int ring_num)
-{
- if (ring_num == 0 || ring_num == 2 || ring_num == 4)
- return true;
-
- return false;
-}
-
-static bool ath12k_is_addba_resp_action_code(struct ieee80211_mgmt *mgmt)
-{
- if (!ieee80211_is_action(mgmt->frame_control))
- return false;
-
- if (mgmt->u.action.category != WLAN_CATEGORY_BACK)
- return false;
-
- if (mgmt->u.action.u.addba_resp.action_code != WLAN_ACTION_ADDBA_RESP)
- return false;
-
- return true;
-}
-
-static bool ath12k_is_frame_link_agnostic_wcn7850(struct ath12k_link_vif *arvif,
- struct ieee80211_mgmt *mgmt)
-{
- struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
- struct ath12k_hw *ah = ath12k_ar_to_ah(arvif->ar);
- struct ath12k_base *ab = arvif->ar->ab;
- __le16 fc = mgmt->frame_control;
-
- spin_lock_bh(&ab->base_lock);
- if (!ath12k_peer_find_by_addr(ab, mgmt->da) &&
- !ath12k_peer_ml_find(ah, mgmt->da)) {
- spin_unlock_bh(&ab->base_lock);
- return false;
- }
- spin_unlock_bh(&ab->base_lock);
-
- if (vif->type == NL80211_IFTYPE_STATION)
- return arvif->is_up &&
- (vif->valid_links == vif->active_links) &&
- !ieee80211_is_probe_req(fc) &&
- !ieee80211_is_auth(fc) &&
- !ieee80211_is_deauth(fc) &&
- !ath12k_is_addba_resp_action_code(mgmt);
-
- if (vif->type == NL80211_IFTYPE_AP)
- return !(ieee80211_is_probe_resp(fc) || ieee80211_is_auth(fc) ||
- ieee80211_is_assoc_resp(fc) || ieee80211_is_reassoc_resp(fc) ||
- ath12k_is_addba_resp_action_code(mgmt));
-
- return false;
-}
-
-static const struct ath12k_hw_ops qcn9274_ops = {
- .get_hw_mac_from_pdev_id = ath12k_hw_qcn9274_mac_from_pdev_id,
- .mac_id_to_pdev_id = ath12k_hw_mac_id_to_pdev_id_qcn9274,
- .mac_id_to_srng_id = ath12k_hw_mac_id_to_srng_id_qcn9274,
- .rxdma_ring_sel_config = ath12k_dp_rxdma_ring_sel_config_qcn9274,
- .get_ring_selector = ath12k_hw_get_ring_selector_qcn9274,
- .dp_srng_is_tx_comp_ring = ath12k_dp_srng_is_comp_ring_qcn9274,
- .is_frame_link_agnostic = ath12k_is_frame_link_agnostic_qcn9274,
-};
-
-static const struct ath12k_hw_ops wcn7850_ops = {
- .get_hw_mac_from_pdev_id = ath12k_hw_qcn9274_mac_from_pdev_id,
- .mac_id_to_pdev_id = ath12k_hw_mac_id_to_pdev_id_wcn7850,
- .mac_id_to_srng_id = ath12k_hw_mac_id_to_srng_id_wcn7850,
- .rxdma_ring_sel_config = ath12k_dp_rxdma_ring_sel_config_wcn7850,
- .get_ring_selector = ath12k_hw_get_ring_selector_wcn7850,
- .dp_srng_is_tx_comp_ring = ath12k_dp_srng_is_comp_ring_wcn7850,
- .is_frame_link_agnostic = ath12k_is_frame_link_agnostic_wcn7850,
-};
-
-#define ATH12K_TX_RING_MASK_0 0x1
-#define ATH12K_TX_RING_MASK_1 0x2
-#define ATH12K_TX_RING_MASK_2 0x4
-#define ATH12K_TX_RING_MASK_3 0x8
-#define ATH12K_TX_RING_MASK_4 0x10
-
-#define ATH12K_RX_RING_MASK_0 0x1
-#define ATH12K_RX_RING_MASK_1 0x2
-#define ATH12K_RX_RING_MASK_2 0x4
-#define ATH12K_RX_RING_MASK_3 0x8
-
-#define ATH12K_RX_ERR_RING_MASK_0 0x1
-
-#define ATH12K_RX_WBM_REL_RING_MASK_0 0x1
-
-#define ATH12K_REO_STATUS_RING_MASK_0 0x1
-
-#define ATH12K_HOST2RXDMA_RING_MASK_0 0x1
-
-#define ATH12K_RX_MON_RING_MASK_0 0x1
-#define ATH12K_RX_MON_RING_MASK_1 0x2
-#define ATH12K_RX_MON_RING_MASK_2 0x4
-
-#define ATH12K_TX_MON_RING_MASK_0 0x1
-#define ATH12K_TX_MON_RING_MASK_1 0x2
-
-#define ATH12K_RX_MON_STATUS_RING_MASK_0 0x1
-#define ATH12K_RX_MON_STATUS_RING_MASK_1 0x2
-#define ATH12K_RX_MON_STATUS_RING_MASK_2 0x4
-
-/* Target firmware's Copy Engine configuration. */
-static const struct ce_pipe_config ath12k_target_ce_config_wlan_qcn9274[] = {
- /* CE0: host->target HTC control and raw streams */
- {
- .pipenum = __cpu_to_le32(0),
- .pipedir = __cpu_to_le32(PIPEDIR_OUT),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(2048),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
-
- /* CE1: target->host HTT + HTC control */
- {
- .pipenum = __cpu_to_le32(1),
- .pipedir = __cpu_to_le32(PIPEDIR_IN),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(2048),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
-
- /* CE2: target->host WMI */
- {
- .pipenum = __cpu_to_le32(2),
- .pipedir = __cpu_to_le32(PIPEDIR_IN),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(2048),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
-
- /* CE3: host->target WMI (mac0) */
- {
- .pipenum = __cpu_to_le32(3),
- .pipedir = __cpu_to_le32(PIPEDIR_OUT),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(2048),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
-
- /* CE4: host->target HTT */
- {
- .pipenum = __cpu_to_le32(4),
- .pipedir = __cpu_to_le32(PIPEDIR_OUT),
- .nentries = __cpu_to_le32(256),
- .nbytes_max = __cpu_to_le32(256),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
- .reserved = __cpu_to_le32(0),
- },
-
- /* CE5: target->host Pktlog */
- {
- .pipenum = __cpu_to_le32(5),
- .pipedir = __cpu_to_le32(PIPEDIR_IN),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(2048),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
-
- /* CE6: Reserved for target autonomous hif_memcpy */
- {
- .pipenum = __cpu_to_le32(6),
- .pipedir = __cpu_to_le32(PIPEDIR_INOUT),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(16384),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
-
- /* CE7: host->target WMI (mac1) */
- {
- .pipenum = __cpu_to_le32(7),
- .pipedir = __cpu_to_le32(PIPEDIR_OUT),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(2048),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
-
- /* CE8: Reserved for target autonomous hif_memcpy */
- {
- .pipenum = __cpu_to_le32(8),
- .pipedir = __cpu_to_le32(PIPEDIR_INOUT),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(16384),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
-
- /* CE9, 10 and 11: Reserved for MHI */
-
- /* CE12: Target CV prefetch */
- {
- .pipenum = __cpu_to_le32(12),
- .pipedir = __cpu_to_le32(PIPEDIR_OUT),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(2048),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
-
- /* CE13: Target CV prefetch */
- {
- .pipenum = __cpu_to_le32(13),
- .pipedir = __cpu_to_le32(PIPEDIR_OUT),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(2048),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
-
- /* CE14: WMI logging/CFR/Spectral/Radar */
- {
- .pipenum = __cpu_to_le32(14),
- .pipedir = __cpu_to_le32(PIPEDIR_IN),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(2048),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
-
- /* CE15: Reserved */
-};
-
-/* Target firmware's Copy Engine configuration. */
-static const struct ce_pipe_config ath12k_target_ce_config_wlan_wcn7850[] = {
- /* CE0: host->target HTC control and raw streams */
- {
- .pipenum = __cpu_to_le32(0),
- .pipedir = __cpu_to_le32(PIPEDIR_OUT),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(2048),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
-
- /* CE1: target->host HTT + HTC control */
- {
- .pipenum = __cpu_to_le32(1),
- .pipedir = __cpu_to_le32(PIPEDIR_IN),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(2048),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
-
- /* CE2: target->host WMI */
- {
- .pipenum = __cpu_to_le32(2),
- .pipedir = __cpu_to_le32(PIPEDIR_IN),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(2048),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
-
- /* CE3: host->target WMI */
- {
- .pipenum = __cpu_to_le32(3),
- .pipedir = __cpu_to_le32(PIPEDIR_OUT),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(2048),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
-
- /* CE4: host->target HTT */
- {
- .pipenum = __cpu_to_le32(4),
- .pipedir = __cpu_to_le32(PIPEDIR_OUT),
- .nentries = __cpu_to_le32(256),
- .nbytes_max = __cpu_to_le32(256),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
- .reserved = __cpu_to_le32(0),
- },
-
- /* CE5: target->host Pktlog */
- {
- .pipenum = __cpu_to_le32(5),
- .pipedir = __cpu_to_le32(PIPEDIR_IN),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(2048),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
-
- /* CE6: Reserved for target autonomous hif_memcpy */
- {
- .pipenum = __cpu_to_le32(6),
- .pipedir = __cpu_to_le32(PIPEDIR_INOUT),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(16384),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
-
- /* CE7 used only by Host */
- {
- .pipenum = __cpu_to_le32(7),
- .pipedir = __cpu_to_le32(PIPEDIR_INOUT_H2H),
- .nentries = __cpu_to_le32(0),
- .nbytes_max = __cpu_to_le32(0),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
- .reserved = __cpu_to_le32(0),
- },
-
- /* CE8 target->host used only by IPA */
- {
- .pipenum = __cpu_to_le32(8),
- .pipedir = __cpu_to_le32(PIPEDIR_INOUT),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(16384),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
- /* CE 9, 10, 11 are used by MHI driver */
-};
-
-/* Map from service/endpoint to Copy Engine.
- * This table is derived from the CE_PCI TABLE, above.
- * It is passed to the Target at startup for use by firmware.
- */
-static const struct service_to_pipe ath12k_target_service_to_ce_map_wlan_qcn9274[] = {
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VO),
- __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
- __cpu_to_le32(3),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VO),
- __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
- __cpu_to_le32(2),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BK),
- __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
- __cpu_to_le32(3),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BK),
- __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
- __cpu_to_le32(2),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BE),
- __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
- __cpu_to_le32(3),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BE),
- __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
- __cpu_to_le32(2),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VI),
- __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
- __cpu_to_le32(3),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VI),
- __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
- __cpu_to_le32(2),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL),
- __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
- __cpu_to_le32(3),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL),
- __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
- __cpu_to_le32(2),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_RSVD_CTRL),
- __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
- __cpu_to_le32(0),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_RSVD_CTRL),
- __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
- __cpu_to_le32(1),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_TEST_RAW_STREAMS),
- __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
- __cpu_to_le32(0),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_TEST_RAW_STREAMS),
- __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
- __cpu_to_le32(1),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_HTT_DATA_MSG),
- __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
- __cpu_to_le32(4),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_HTT_DATA_MSG),
- __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
- __cpu_to_le32(1),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL_MAC1),
- __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
- __cpu_to_le32(7),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL_MAC1),
- __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
- __cpu_to_le32(2),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_PKT_LOG),
- __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
- __cpu_to_le32(5),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL_DIAG),
- __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
- __cpu_to_le32(14),
- },
-
- /* (Additions here) */
-
- { /* must be last */
- __cpu_to_le32(0),
- __cpu_to_le32(0),
- __cpu_to_le32(0),
- },
-};
-
-static const struct service_to_pipe ath12k_target_service_to_ce_map_wlan_wcn7850[] = {
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VO),
- __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
- __cpu_to_le32(3),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VO),
- __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
- __cpu_to_le32(2),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BK),
- __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
- __cpu_to_le32(3),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BK),
- __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
- __cpu_to_le32(2),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BE),
- __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
- __cpu_to_le32(3),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BE),
- __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
- __cpu_to_le32(2),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VI),
- __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
- __cpu_to_le32(3),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VI),
- __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
- __cpu_to_le32(2),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL),
- __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
- __cpu_to_le32(3),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL),
- __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
- __cpu_to_le32(2),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_RSVD_CTRL),
- __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
- __cpu_to_le32(0),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_RSVD_CTRL),
- __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
- __cpu_to_le32(2),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_HTT_DATA_MSG),
- __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
- __cpu_to_le32(4),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_HTT_DATA_MSG),
- __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
- __cpu_to_le32(1),
- },
-
- /* (Additions here) */
-
- { /* must be last */
- __cpu_to_le32(0),
- __cpu_to_le32(0),
- __cpu_to_le32(0),
- },
-};
-
-static const struct ce_pipe_config ath12k_target_ce_config_wlan_ipq5332[] = {
- /* host->target HTC control and raw streams */
- {
- .pipenum = __cpu_to_le32(0),
- .pipedir = __cpu_to_le32(PIPEDIR_OUT),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(2048),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
- /* target->host HTT */
- {
- .pipenum = __cpu_to_le32(1),
- .pipedir = __cpu_to_le32(PIPEDIR_IN),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(2048),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
- /* target->host WMI + HTC control */
- {
- .pipenum = __cpu_to_le32(2),
- .pipedir = __cpu_to_le32(PIPEDIR_IN),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(2048),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
- /* host->target WMI */
- {
- .pipenum = __cpu_to_le32(3),
- .pipedir = __cpu_to_le32(PIPEDIR_OUT),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(2048),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
- /* host->target HTT */
- {
- .pipenum = __cpu_to_le32(4),
- .pipedir = __cpu_to_le32(PIPEDIR_OUT),
- .nentries = __cpu_to_le32(256),
- .nbytes_max = __cpu_to_le32(256),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
- .reserved = __cpu_to_le32(0),
- },
- /* Target -> host PKTLOG */
- {
- .pipenum = __cpu_to_le32(5),
- .pipedir = __cpu_to_le32(PIPEDIR_IN),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(2048),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
- /* Reserved for target autonomous HIF_memcpy */
- {
- .pipenum = __cpu_to_le32(6),
- .pipedir = __cpu_to_le32(PIPEDIR_INOUT),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(16384),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
- /* CE7 Reserved for CV Prefetch */
- {
- .pipenum = __cpu_to_le32(7),
- .pipedir = __cpu_to_le32(PIPEDIR_OUT),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(2048),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
- /* CE8 Reserved for target generic HIF memcpy */
- {
- .pipenum = __cpu_to_le32(8),
- .pipedir = __cpu_to_le32(PIPEDIR_INOUT),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(16384),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
- /* CE9 WMI logging/CFR/Spectral/Radar/ */
- {
- .pipenum = __cpu_to_le32(9),
- .pipedir = __cpu_to_le32(PIPEDIR_IN),
- .nentries = __cpu_to_le32(32),
- .nbytes_max = __cpu_to_le32(2048),
- .flags = __cpu_to_le32(CE_ATTR_FLAGS),
- .reserved = __cpu_to_le32(0),
- },
- /* Unused TBD */
- {
- .pipenum = __cpu_to_le32(10),
- .pipedir = __cpu_to_le32(PIPEDIR_NONE),
- .nentries = __cpu_to_le32(0),
- .nbytes_max = __cpu_to_le32(0),
- .flags = __cpu_to_le32(0),
- .reserved = __cpu_to_le32(0),
- },
- /* Unused TBD */
- {
- .pipenum = __cpu_to_le32(11),
- .pipedir = __cpu_to_le32(PIPEDIR_NONE),
- .nentries = __cpu_to_le32(0),
- .nbytes_max = __cpu_to_le32(0),
- .flags = __cpu_to_le32(0),
- .reserved = __cpu_to_le32(0),
- },
-};
-
-static const struct service_to_pipe ath12k_target_service_to_ce_map_wlan_ipq5332[] = {
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VO),
- __cpu_to_le32(PIPEDIR_OUT),
- __cpu_to_le32(3),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VO),
- __cpu_to_le32(PIPEDIR_IN),
- __cpu_to_le32(2),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BK),
- __cpu_to_le32(PIPEDIR_OUT),
- __cpu_to_le32(3),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BK),
- __cpu_to_le32(PIPEDIR_IN),
- __cpu_to_le32(2),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BE),
- __cpu_to_le32(PIPEDIR_OUT),
- __cpu_to_le32(3),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BE),
- __cpu_to_le32(PIPEDIR_IN),
- __cpu_to_le32(2),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VI),
- __cpu_to_le32(PIPEDIR_OUT),
- __cpu_to_le32(3),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VI),
- __cpu_to_le32(PIPEDIR_IN),
- __cpu_to_le32(2),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL),
- __cpu_to_le32(PIPEDIR_OUT),
- __cpu_to_le32(3),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL),
- __cpu_to_le32(PIPEDIR_IN),
- __cpu_to_le32(2),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_RSVD_CTRL),
- __cpu_to_le32(PIPEDIR_OUT),
- __cpu_to_le32(0),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_RSVD_CTRL),
- __cpu_to_le32(PIPEDIR_IN),
- __cpu_to_le32(1),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_TEST_RAW_STREAMS),
- __cpu_to_le32(PIPEDIR_OUT),
- __cpu_to_le32(0),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_TEST_RAW_STREAMS),
- __cpu_to_le32(PIPEDIR_IN),
- __cpu_to_le32(1),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_HTT_DATA_MSG),
- __cpu_to_le32(PIPEDIR_OUT),
- __cpu_to_le32(4),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_HTT_DATA_MSG),
- __cpu_to_le32(PIPEDIR_IN),
- __cpu_to_le32(1),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_PKT_LOG),
- __cpu_to_le32(PIPEDIR_IN),
- __cpu_to_le32(5),
- },
- {
- __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL_DIAG),
- __cpu_to_le32(PIPEDIR_IN),
- __cpu_to_le32(9),
- },
- /* (Additions here) */
-
- { /* must be last */
- __cpu_to_le32(0),
- __cpu_to_le32(0),
- __cpu_to_le32(0),
- },
-};
-
-static const struct ath12k_hw_ring_mask ath12k_hw_ring_mask_qcn9274 = {
- .tx = {
- ATH12K_TX_RING_MASK_0,
- ATH12K_TX_RING_MASK_1,
- ATH12K_TX_RING_MASK_2,
- ATH12K_TX_RING_MASK_3,
- },
- .rx_mon_dest = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- ATH12K_RX_MON_RING_MASK_0,
- ATH12K_RX_MON_RING_MASK_1,
- ATH12K_RX_MON_RING_MASK_2,
- },
- .rx = {
- 0, 0, 0, 0,
- ATH12K_RX_RING_MASK_0,
- ATH12K_RX_RING_MASK_1,
- ATH12K_RX_RING_MASK_2,
- ATH12K_RX_RING_MASK_3,
- },
- .rx_err = {
- 0, 0, 0,
- ATH12K_RX_ERR_RING_MASK_0,
- },
- .rx_wbm_rel = {
- 0, 0, 0,
- ATH12K_RX_WBM_REL_RING_MASK_0,
- },
- .reo_status = {
- 0, 0, 0,
- ATH12K_REO_STATUS_RING_MASK_0,
- },
- .host2rxdma = {
- 0, 0, 0,
- ATH12K_HOST2RXDMA_RING_MASK_0,
- },
- .tx_mon_dest = {
- 0, 0, 0,
- },
-};
-
-static const struct ath12k_hw_ring_mask ath12k_hw_ring_mask_ipq5332 = {
- .tx = {
- ATH12K_TX_RING_MASK_0,
- ATH12K_TX_RING_MASK_1,
- ATH12K_TX_RING_MASK_2,
- ATH12K_TX_RING_MASK_3,
- },
- .rx_mon_dest = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- ATH12K_RX_MON_RING_MASK_0,
- },
- .rx = {
- 0, 0, 0, 0,
- ATH12K_RX_RING_MASK_0,
- ATH12K_RX_RING_MASK_1,
- ATH12K_RX_RING_MASK_2,
- ATH12K_RX_RING_MASK_3,
- },
- .rx_err = {
- 0, 0, 0,
- ATH12K_RX_ERR_RING_MASK_0,
- },
- .rx_wbm_rel = {
- 0, 0, 0,
- ATH12K_RX_WBM_REL_RING_MASK_0,
- },
- .reo_status = {
- 0, 0, 0,
- ATH12K_REO_STATUS_RING_MASK_0,
- },
- .host2rxdma = {
- 0, 0, 0,
- ATH12K_HOST2RXDMA_RING_MASK_0,
- },
- .tx_mon_dest = {
- ATH12K_TX_MON_RING_MASK_0,
- ATH12K_TX_MON_RING_MASK_1,
- },
-};
-
-static const struct ath12k_hw_ring_mask ath12k_hw_ring_mask_wcn7850 = {
- .tx = {
- ATH12K_TX_RING_MASK_0,
- ATH12K_TX_RING_MASK_1,
- ATH12K_TX_RING_MASK_2,
- },
- .rx_mon_dest = {
- },
- .rx_mon_status = {
- 0, 0, 0, 0,
- ATH12K_RX_MON_STATUS_RING_MASK_0,
- ATH12K_RX_MON_STATUS_RING_MASK_1,
- ATH12K_RX_MON_STATUS_RING_MASK_2,
- },
- .rx = {
- 0, 0, 0,
- ATH12K_RX_RING_MASK_0,
- ATH12K_RX_RING_MASK_1,
- ATH12K_RX_RING_MASK_2,
- ATH12K_RX_RING_MASK_3,
- },
- .rx_err = {
- ATH12K_RX_ERR_RING_MASK_0,
- },
- .rx_wbm_rel = {
- ATH12K_RX_WBM_REL_RING_MASK_0,
- },
- .reo_status = {
- ATH12K_REO_STATUS_RING_MASK_0,
- },
- .host2rxdma = {
- },
- .tx_mon_dest = {
- },
-};
-
-static const struct ath12k_hw_regs qcn9274_v1_regs = {
- /* SW2TCL(x) R0 ring configuration address */
- .hal_tcl1_ring_id = 0x00000908,
- .hal_tcl1_ring_misc = 0x00000910,
- .hal_tcl1_ring_tp_addr_lsb = 0x0000091c,
- .hal_tcl1_ring_tp_addr_msb = 0x00000920,
- .hal_tcl1_ring_consumer_int_setup_ix0 = 0x00000930,
- .hal_tcl1_ring_consumer_int_setup_ix1 = 0x00000934,
- .hal_tcl1_ring_msi1_base_lsb = 0x00000948,
- .hal_tcl1_ring_msi1_base_msb = 0x0000094c,
- .hal_tcl1_ring_msi1_data = 0x00000950,
- .hal_tcl_ring_base_lsb = 0x00000b58,
- .hal_tcl1_ring_base_lsb = 0x00000900,
- .hal_tcl1_ring_base_msb = 0x00000904,
- .hal_tcl2_ring_base_lsb = 0x00000978,
-
- /* TCL STATUS ring address */
- .hal_tcl_status_ring_base_lsb = 0x00000d38,
-
- .hal_wbm_idle_ring_base_lsb = 0x00000d0c,
- .hal_wbm_idle_ring_misc_addr = 0x00000d1c,
- .hal_wbm_r0_idle_list_cntl_addr = 0x00000210,
- .hal_wbm_r0_idle_list_size_addr = 0x00000214,
- .hal_wbm_scattered_ring_base_lsb = 0x00000220,
- .hal_wbm_scattered_ring_base_msb = 0x00000224,
- .hal_wbm_scattered_desc_head_info_ix0 = 0x00000230,
- .hal_wbm_scattered_desc_head_info_ix1 = 0x00000234,
- .hal_wbm_scattered_desc_tail_info_ix0 = 0x00000240,
- .hal_wbm_scattered_desc_tail_info_ix1 = 0x00000244,
- .hal_wbm_scattered_desc_ptr_hp_addr = 0x0000024c,
-
- .hal_wbm_sw_release_ring_base_lsb = 0x0000034c,
- .hal_wbm_sw1_release_ring_base_lsb = 0x000003c4,
- .hal_wbm0_release_ring_base_lsb = 0x00000dd8,
- .hal_wbm1_release_ring_base_lsb = 0x00000e50,
-
- /* PCIe base address */
- .pcie_qserdes_sysclk_en_sel = 0x01e0c0a8,
- .pcie_pcs_osc_dtct_config_base = 0x01e0d45c,
-
- /* PPE release ring address */
- .hal_ppe_rel_ring_base = 0x0000043c,
-
- /* REO DEST ring address */
- .hal_reo2_ring_base = 0x0000055c,
- .hal_reo1_misc_ctrl_addr = 0x00000b7c,
- .hal_reo1_sw_cookie_cfg0 = 0x00000050,
- .hal_reo1_sw_cookie_cfg1 = 0x00000054,
- .hal_reo1_qdesc_lut_base0 = 0x00000058,
- .hal_reo1_qdesc_lut_base1 = 0x0000005c,
- .hal_reo1_ring_base_lsb = 0x000004e4,
- .hal_reo1_ring_base_msb = 0x000004e8,
- .hal_reo1_ring_id = 0x000004ec,
- .hal_reo1_ring_misc = 0x000004f4,
- .hal_reo1_ring_hp_addr_lsb = 0x000004f8,
- .hal_reo1_ring_hp_addr_msb = 0x000004fc,
- .hal_reo1_ring_producer_int_setup = 0x00000508,
- .hal_reo1_ring_msi1_base_lsb = 0x0000052C,
- .hal_reo1_ring_msi1_base_msb = 0x00000530,
- .hal_reo1_ring_msi1_data = 0x00000534,
- .hal_reo1_aging_thres_ix0 = 0x00000b08,
- .hal_reo1_aging_thres_ix1 = 0x00000b0c,
- .hal_reo1_aging_thres_ix2 = 0x00000b10,
- .hal_reo1_aging_thres_ix3 = 0x00000b14,
-
- /* REO Exception ring address */
- .hal_reo2_sw0_ring_base = 0x000008a4,
-
- /* REO Reinject ring address */
- .hal_sw2reo_ring_base = 0x00000304,
- .hal_sw2reo1_ring_base = 0x0000037c,
-
- /* REO cmd ring address */
- .hal_reo_cmd_ring_base = 0x0000028c,
-
- /* REO status ring address */
- .hal_reo_status_ring_base = 0x00000a84,
-
- /* CE base address */
- .hal_umac_ce0_src_reg_base = 0x01b80000,
- .hal_umac_ce0_dest_reg_base = 0x01b81000,
- .hal_umac_ce1_src_reg_base = 0x01b82000,
- .hal_umac_ce1_dest_reg_base = 0x01b83000,
-
- .gcc_gcc_pcie_hot_rst = 0x1e38338,
-};
-
-static const struct ath12k_hw_regs qcn9274_v2_regs = {
- /* SW2TCL(x) R0 ring configuration address */
- .hal_tcl1_ring_id = 0x00000908,
- .hal_tcl1_ring_misc = 0x00000910,
- .hal_tcl1_ring_tp_addr_lsb = 0x0000091c,
- .hal_tcl1_ring_tp_addr_msb = 0x00000920,
- .hal_tcl1_ring_consumer_int_setup_ix0 = 0x00000930,
- .hal_tcl1_ring_consumer_int_setup_ix1 = 0x00000934,
- .hal_tcl1_ring_msi1_base_lsb = 0x00000948,
- .hal_tcl1_ring_msi1_base_msb = 0x0000094c,
- .hal_tcl1_ring_msi1_data = 0x00000950,
- .hal_tcl_ring_base_lsb = 0x00000b58,
- .hal_tcl1_ring_base_lsb = 0x00000900,
- .hal_tcl1_ring_base_msb = 0x00000904,
- .hal_tcl2_ring_base_lsb = 0x00000978,
-
- /* TCL STATUS ring address */
- .hal_tcl_status_ring_base_lsb = 0x00000d38,
-
- /* WBM idle link ring address */
- .hal_wbm_idle_ring_base_lsb = 0x00000d3c,
- .hal_wbm_idle_ring_misc_addr = 0x00000d4c,
- .hal_wbm_r0_idle_list_cntl_addr = 0x00000240,
- .hal_wbm_r0_idle_list_size_addr = 0x00000244,
- .hal_wbm_scattered_ring_base_lsb = 0x00000250,
- .hal_wbm_scattered_ring_base_msb = 0x00000254,
- .hal_wbm_scattered_desc_head_info_ix0 = 0x00000260,
- .hal_wbm_scattered_desc_head_info_ix1 = 0x00000264,
- .hal_wbm_scattered_desc_tail_info_ix0 = 0x00000270,
- .hal_wbm_scattered_desc_tail_info_ix1 = 0x00000274,
- .hal_wbm_scattered_desc_ptr_hp_addr = 0x0000027c,
-
- /* SW2WBM release ring address */
- .hal_wbm_sw_release_ring_base_lsb = 0x0000037c,
- .hal_wbm_sw1_release_ring_base_lsb = 0x000003f4,
-
- /* WBM2SW release ring address */
- .hal_wbm0_release_ring_base_lsb = 0x00000e08,
- .hal_wbm1_release_ring_base_lsb = 0x00000e80,
-
- /* PCIe base address */
- .pcie_qserdes_sysclk_en_sel = 0x01e0c0a8,
- .pcie_pcs_osc_dtct_config_base = 0x01e0d45c,
-
- /* PPE release ring address */
- .hal_ppe_rel_ring_base = 0x0000046c,
-
- /* REO DEST ring address */
- .hal_reo2_ring_base = 0x00000578,
- .hal_reo1_misc_ctrl_addr = 0x00000b9c,
- .hal_reo1_sw_cookie_cfg0 = 0x0000006c,
- .hal_reo1_sw_cookie_cfg1 = 0x00000070,
- .hal_reo1_qdesc_lut_base0 = 0x00000074,
- .hal_reo1_qdesc_lut_base1 = 0x00000078,
- .hal_reo1_qdesc_addr = 0x0000007c,
- .hal_reo1_qdesc_max_peerid = 0x00000088,
- .hal_reo1_ring_base_lsb = 0x00000500,
- .hal_reo1_ring_base_msb = 0x00000504,
- .hal_reo1_ring_id = 0x00000508,
- .hal_reo1_ring_misc = 0x00000510,
- .hal_reo1_ring_hp_addr_lsb = 0x00000514,
- .hal_reo1_ring_hp_addr_msb = 0x00000518,
- .hal_reo1_ring_producer_int_setup = 0x00000524,
- .hal_reo1_ring_msi1_base_lsb = 0x00000548,
- .hal_reo1_ring_msi1_base_msb = 0x0000054C,
- .hal_reo1_ring_msi1_data = 0x00000550,
- .hal_reo1_aging_thres_ix0 = 0x00000B28,
- .hal_reo1_aging_thres_ix1 = 0x00000B2C,
- .hal_reo1_aging_thres_ix2 = 0x00000B30,
- .hal_reo1_aging_thres_ix3 = 0x00000B34,
-
- /* REO Exception ring address */
- .hal_reo2_sw0_ring_base = 0x000008c0,
-
- /* REO Reinject ring address */
- .hal_sw2reo_ring_base = 0x00000320,
- .hal_sw2reo1_ring_base = 0x00000398,
-
- /* REO cmd ring address */
- .hal_reo_cmd_ring_base = 0x000002A8,
-
- /* REO status ring address */
- .hal_reo_status_ring_base = 0x00000aa0,
-
- /* CE base address */
- .hal_umac_ce0_src_reg_base = 0x01b80000,
- .hal_umac_ce0_dest_reg_base = 0x01b81000,
- .hal_umac_ce1_src_reg_base = 0x01b82000,
- .hal_umac_ce1_dest_reg_base = 0x01b83000,
-
- .gcc_gcc_pcie_hot_rst = 0x1e38338,
-};
-
-static const struct ath12k_hw_regs ipq5332_regs = {
- /* SW2TCL(x) R0 ring configuration address */
- .hal_tcl1_ring_id = 0x00000918,
- .hal_tcl1_ring_misc = 0x00000920,
- .hal_tcl1_ring_tp_addr_lsb = 0x0000092c,
- .hal_tcl1_ring_tp_addr_msb = 0x00000930,
- .hal_tcl1_ring_consumer_int_setup_ix0 = 0x00000940,
- .hal_tcl1_ring_consumer_int_setup_ix1 = 0x00000944,
- .hal_tcl1_ring_msi1_base_lsb = 0x00000958,
- .hal_tcl1_ring_msi1_base_msb = 0x0000095c,
- .hal_tcl1_ring_base_lsb = 0x00000910,
- .hal_tcl1_ring_base_msb = 0x00000914,
- .hal_tcl1_ring_msi1_data = 0x00000960,
- .hal_tcl2_ring_base_lsb = 0x00000988,
- .hal_tcl_ring_base_lsb = 0x00000b68,
-
- /* TCL STATUS ring address */
- .hal_tcl_status_ring_base_lsb = 0x00000d48,
-
- /* REO DEST ring address */
- .hal_reo2_ring_base = 0x00000578,
- .hal_reo1_misc_ctrl_addr = 0x00000b9c,
- .hal_reo1_sw_cookie_cfg0 = 0x0000006c,
- .hal_reo1_sw_cookie_cfg1 = 0x00000070,
- .hal_reo1_qdesc_lut_base0 = 0x00000074,
- .hal_reo1_qdesc_lut_base1 = 0x00000078,
- .hal_reo1_ring_base_lsb = 0x00000500,
- .hal_reo1_ring_base_msb = 0x00000504,
- .hal_reo1_ring_id = 0x00000508,
- .hal_reo1_ring_misc = 0x00000510,
- .hal_reo1_ring_hp_addr_lsb = 0x00000514,
- .hal_reo1_ring_hp_addr_msb = 0x00000518,
- .hal_reo1_ring_producer_int_setup = 0x00000524,
- .hal_reo1_ring_msi1_base_lsb = 0x00000548,
- .hal_reo1_ring_msi1_base_msb = 0x0000054C,
- .hal_reo1_ring_msi1_data = 0x00000550,
- .hal_reo1_aging_thres_ix0 = 0x00000B28,
- .hal_reo1_aging_thres_ix1 = 0x00000B2C,
- .hal_reo1_aging_thres_ix2 = 0x00000B30,
- .hal_reo1_aging_thres_ix3 = 0x00000B34,
-
- /* REO Exception ring address */
- .hal_reo2_sw0_ring_base = 0x000008c0,
-
- /* REO Reinject ring address */
- .hal_sw2reo_ring_base = 0x00000320,
- .hal_sw2reo1_ring_base = 0x00000398,
-
- /* REO cmd ring address */
- .hal_reo_cmd_ring_base = 0x000002A8,
-
- /* REO status ring address */
- .hal_reo_status_ring_base = 0x00000aa0,
-
- /* WBM idle link ring address */
- .hal_wbm_idle_ring_base_lsb = 0x00000d3c,
- .hal_wbm_idle_ring_misc_addr = 0x00000d4c,
- .hal_wbm_r0_idle_list_cntl_addr = 0x00000240,
- .hal_wbm_r0_idle_list_size_addr = 0x00000244,
- .hal_wbm_scattered_ring_base_lsb = 0x00000250,
- .hal_wbm_scattered_ring_base_msb = 0x00000254,
- .hal_wbm_scattered_desc_head_info_ix0 = 0x00000260,
- .hal_wbm_scattered_desc_head_info_ix1 = 0x00000264,
- .hal_wbm_scattered_desc_tail_info_ix0 = 0x00000270,
- .hal_wbm_scattered_desc_tail_info_ix1 = 0x00000274,
- .hal_wbm_scattered_desc_ptr_hp_addr = 0x0000027c,
-
- /* SW2WBM release ring address */
- .hal_wbm_sw_release_ring_base_lsb = 0x0000037c,
-
- /* WBM2SW release ring address */
- .hal_wbm0_release_ring_base_lsb = 0x00000e08,
- .hal_wbm1_release_ring_base_lsb = 0x00000e80,
-
- /* PPE release ring address */
- .hal_ppe_rel_ring_base = 0x0000046c,
-
- /* CE address */
- .hal_umac_ce0_src_reg_base = 0x00740000 -
- HAL_IPQ5332_CE_WFSS_REG_BASE,
- .hal_umac_ce0_dest_reg_base = 0x00741000 -
- HAL_IPQ5332_CE_WFSS_REG_BASE,
- .hal_umac_ce1_src_reg_base = 0x00742000 -
- HAL_IPQ5332_CE_WFSS_REG_BASE,
- .hal_umac_ce1_dest_reg_base = 0x00743000 -
- HAL_IPQ5332_CE_WFSS_REG_BASE,
-};
-
-static const struct ath12k_hw_regs wcn7850_regs = {
- /* SW2TCL(x) R0 ring configuration address */
- .hal_tcl1_ring_id = 0x00000908,
- .hal_tcl1_ring_misc = 0x00000910,
- .hal_tcl1_ring_tp_addr_lsb = 0x0000091c,
- .hal_tcl1_ring_tp_addr_msb = 0x00000920,
- .hal_tcl1_ring_consumer_int_setup_ix0 = 0x00000930,
- .hal_tcl1_ring_consumer_int_setup_ix1 = 0x00000934,
- .hal_tcl1_ring_msi1_base_lsb = 0x00000948,
- .hal_tcl1_ring_msi1_base_msb = 0x0000094c,
- .hal_tcl1_ring_msi1_data = 0x00000950,
- .hal_tcl_ring_base_lsb = 0x00000b58,
- .hal_tcl1_ring_base_lsb = 0x00000900,
- .hal_tcl1_ring_base_msb = 0x00000904,
- .hal_tcl2_ring_base_lsb = 0x00000978,
-
- /* TCL STATUS ring address */
- .hal_tcl_status_ring_base_lsb = 0x00000d38,
-
- .hal_wbm_idle_ring_base_lsb = 0x00000d3c,
- .hal_wbm_idle_ring_misc_addr = 0x00000d4c,
- .hal_wbm_r0_idle_list_cntl_addr = 0x00000240,
- .hal_wbm_r0_idle_list_size_addr = 0x00000244,
- .hal_wbm_scattered_ring_base_lsb = 0x00000250,
- .hal_wbm_scattered_ring_base_msb = 0x00000254,
- .hal_wbm_scattered_desc_head_info_ix0 = 0x00000260,
- .hal_wbm_scattered_desc_head_info_ix1 = 0x00000264,
- .hal_wbm_scattered_desc_tail_info_ix0 = 0x00000270,
- .hal_wbm_scattered_desc_tail_info_ix1 = 0x00000274,
- .hal_wbm_scattered_desc_ptr_hp_addr = 0x00000027c,
-
- .hal_wbm_sw_release_ring_base_lsb = 0x0000037c,
- .hal_wbm_sw1_release_ring_base_lsb = 0x00000284,
- .hal_wbm0_release_ring_base_lsb = 0x00000e08,
- .hal_wbm1_release_ring_base_lsb = 0x00000e80,
-
- /* PCIe base address */
- .pcie_qserdes_sysclk_en_sel = 0x01e0e0a8,
- .pcie_pcs_osc_dtct_config_base = 0x01e0f45c,
-
- /* PPE release ring address */
- .hal_ppe_rel_ring_base = 0x0000043c,
-
- /* REO DEST ring address */
- .hal_reo2_ring_base = 0x0000055c,
- .hal_reo1_misc_ctrl_addr = 0x00000b7c,
- .hal_reo1_sw_cookie_cfg0 = 0x00000050,
- .hal_reo1_sw_cookie_cfg1 = 0x00000054,
- .hal_reo1_qdesc_lut_base0 = 0x00000058,
- .hal_reo1_qdesc_lut_base1 = 0x0000005c,
- .hal_reo1_ring_base_lsb = 0x000004e4,
- .hal_reo1_ring_base_msb = 0x000004e8,
- .hal_reo1_ring_id = 0x000004ec,
- .hal_reo1_ring_misc = 0x000004f4,
- .hal_reo1_ring_hp_addr_lsb = 0x000004f8,
- .hal_reo1_ring_hp_addr_msb = 0x000004fc,
- .hal_reo1_ring_producer_int_setup = 0x00000508,
- .hal_reo1_ring_msi1_base_lsb = 0x0000052C,
- .hal_reo1_ring_msi1_base_msb = 0x00000530,
- .hal_reo1_ring_msi1_data = 0x00000534,
- .hal_reo1_aging_thres_ix0 = 0x00000b08,
- .hal_reo1_aging_thres_ix1 = 0x00000b0c,
- .hal_reo1_aging_thres_ix2 = 0x00000b10,
- .hal_reo1_aging_thres_ix3 = 0x00000b14,
-
- /* REO Exception ring address */
- .hal_reo2_sw0_ring_base = 0x000008a4,
-
- /* REO Reinject ring address */
- .hal_sw2reo_ring_base = 0x00000304,
- .hal_sw2reo1_ring_base = 0x0000037c,
-
- /* REO cmd ring address */
- .hal_reo_cmd_ring_base = 0x0000028c,
-
- /* REO status ring address */
- .hal_reo_status_ring_base = 0x00000a84,
-
- /* CE base address */
- .hal_umac_ce0_src_reg_base = 0x01b80000,
- .hal_umac_ce0_dest_reg_base = 0x01b81000,
- .hal_umac_ce1_src_reg_base = 0x01b82000,
- .hal_umac_ce1_dest_reg_base = 0x01b83000,
-
- .gcc_gcc_pcie_hot_rst = 0x1e40304,
-};
-
-static const struct ath12k_hw_hal_params ath12k_hw_hal_params_qcn9274 = {
- .rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM,
- .wbm2sw_cc_enable = HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW0_EN |
- HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW1_EN |
- HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW2_EN |
- HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW3_EN |
- HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW4_EN,
-};
-
-static const struct ath12k_hw_hal_params ath12k_hw_hal_params_wcn7850 = {
- .rx_buf_rbm = HAL_RX_BUF_RBM_SW1_BM,
- .wbm2sw_cc_enable = HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW0_EN |
- HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW2_EN |
- HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW3_EN |
- HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW4_EN,
-};
-
-static const struct ath12k_hw_hal_params ath12k_hw_hal_params_ipq5332 = {
- .rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM,
- .wbm2sw_cc_enable = HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW0_EN |
- HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW1_EN |
- HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW2_EN |
- HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW3_EN |
- HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW4_EN,
-};
-
-static const struct ce_ie_addr ath12k_ce_ie_addr_ipq5332 = {
- .ie1_reg_addr = CE_HOST_IE_ADDRESS - HAL_IPQ5332_CE_WFSS_REG_BASE,
- .ie2_reg_addr = CE_HOST_IE_2_ADDRESS - HAL_IPQ5332_CE_WFSS_REG_BASE,
- .ie3_reg_addr = CE_HOST_IE_3_ADDRESS - HAL_IPQ5332_CE_WFSS_REG_BASE,
-};
-
-static const struct ce_remap ath12k_ce_remap_ipq5332 = {
- .base = HAL_IPQ5332_CE_WFSS_REG_BASE,
- .size = HAL_IPQ5332_CE_SIZE,
-};
-
-static const struct ath12k_hw_params ath12k_hw_params[] = {
- {
- .name = "qcn9274 hw1.0",
- .hw_rev = ATH12K_HW_QCN9274_HW10,
- .fw = {
- .dir = "QCN9274/hw1.0",
- .board_size = 256 * 1024,
- .cal_offset = 128 * 1024,
- .m3_loader = ath12k_m3_fw_loader_driver,
- },
- .max_radios = 1,
- .single_pdev_only = false,
- .qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_QCN9274,
- .internal_sleep_clock = false,
-
- .hw_ops = &qcn9274_ops,
- .ring_mask = &ath12k_hw_ring_mask_qcn9274,
- .regs = &qcn9274_v1_regs,
-
- .host_ce_config = ath12k_host_ce_config_qcn9274,
- .ce_count = 16,
- .target_ce_config = ath12k_target_ce_config_wlan_qcn9274,
- .target_ce_count = 12,
- .svc_to_ce_map = ath12k_target_service_to_ce_map_wlan_qcn9274,
- .svc_to_ce_map_len = 18,
-
- .hal_params = &ath12k_hw_hal_params_qcn9274,
-
- .rxdma1_enable = false,
- .num_rxdma_per_pdev = 1,
- .num_rxdma_dst_ring = 0,
- .rx_mac_buf_ring = false,
- .vdev_start_delay = false,
-
- .interface_modes = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_AP) |
- BIT(NL80211_IFTYPE_MESH_POINT) |
- BIT(NL80211_IFTYPE_AP_VLAN),
- .supports_monitor = false,
-
- .idle_ps = false,
- .download_calib = true,
- .supports_suspend = false,
- .tcl_ring_retry = true,
- .reoq_lut_support = true,
- .supports_shadow_regs = false,
-
- .num_tcl_banks = 48,
- .max_tx_ring = 4,
-
- .mhi_config = &ath12k_mhi_config_qcn9274,
-
- .wmi_init = ath12k_wmi_init_qcn9274,
-
- .hal_ops = &hal_qcn9274_ops,
-
- .qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01),
-
- .rfkill_pin = 0,
- .rfkill_cfg = 0,
- .rfkill_on_level = 0,
-
- .rddm_size = 0x600000,
-
- .def_num_link = 0,
- .max_mlo_peer = 256,
-
- .otp_board_id_register = QCN9274_QFPROM_RAW_RFA_PDET_ROW13_LSB,
-
- .supports_sta_ps = false,
-
- .acpi_guid = NULL,
- .supports_dynamic_smps_6ghz = true,
-
- .iova_mask = 0,
-
- .supports_aspm = false,
-
- .ce_ie_addr = NULL,
- .ce_remap = NULL,
- .bdf_addr_offset = 0,
-
- .current_cc_support = false,
-
- .dp_primary_link_only = true,
- },
- {
- .name = "wcn7850 hw2.0",
- .hw_rev = ATH12K_HW_WCN7850_HW20,
-
- .fw = {
- .dir = "WCN7850/hw2.0",
- .board_size = 256 * 1024,
- .cal_offset = 256 * 1024,
- .m3_loader = ath12k_m3_fw_loader_driver,
- },
-
- .max_radios = 1,
- .single_pdev_only = true,
- .qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_WCN7850,
- .internal_sleep_clock = true,
-
- .hw_ops = &wcn7850_ops,
- .ring_mask = &ath12k_hw_ring_mask_wcn7850,
- .regs = &wcn7850_regs,
-
- .host_ce_config = ath12k_host_ce_config_wcn7850,
- .ce_count = 9,
- .target_ce_config = ath12k_target_ce_config_wlan_wcn7850,
- .target_ce_count = 9,
- .svc_to_ce_map = ath12k_target_service_to_ce_map_wlan_wcn7850,
- .svc_to_ce_map_len = 14,
-
- .hal_params = &ath12k_hw_hal_params_wcn7850,
-
- .rxdma1_enable = false,
- .num_rxdma_per_pdev = 2,
- .num_rxdma_dst_ring = 1,
- .rx_mac_buf_ring = true,
- .vdev_start_delay = true,
-
- .interface_modes = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_AP) |
- BIT(NL80211_IFTYPE_P2P_DEVICE) |
- BIT(NL80211_IFTYPE_P2P_CLIENT) |
- BIT(NL80211_IFTYPE_P2P_GO),
- .supports_monitor = true,
-
- .idle_ps = true,
- .download_calib = false,
- .supports_suspend = true,
- .tcl_ring_retry = false,
- .reoq_lut_support = false,
- .supports_shadow_regs = true,
-
- .num_tcl_banks = 7,
- .max_tx_ring = 3,
-
- .mhi_config = &ath12k_mhi_config_wcn7850,
-
- .wmi_init = ath12k_wmi_init_wcn7850,
-
- .hal_ops = &hal_wcn7850_ops,
-
- .qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01) |
- BIT(CNSS_PCIE_PERST_NO_PULL_V01),
-
- .rfkill_pin = 48,
- .rfkill_cfg = 0,
- .rfkill_on_level = 1,
-
- .rddm_size = 0x780000,
-
- .def_num_link = 2,
- .max_mlo_peer = 32,
-
- .otp_board_id_register = 0,
-
- .supports_sta_ps = true,
-
- .acpi_guid = &wcn7850_uuid,
- .supports_dynamic_smps_6ghz = false,
-
- .iova_mask = ATH12K_PCIE_MAX_PAYLOAD_SIZE - 1,
-
- .supports_aspm = true,
-
- .ce_ie_addr = NULL,
- .ce_remap = NULL,
- .bdf_addr_offset = 0,
-
- .current_cc_support = true,
-
- .dp_primary_link_only = false,
- },
- {
- .name = "qcn9274 hw2.0",
- .hw_rev = ATH12K_HW_QCN9274_HW20,
- .fw = {
- .dir = "QCN9274/hw2.0",
- .board_size = 256 * 1024,
- .cal_offset = 128 * 1024,
- .m3_loader = ath12k_m3_fw_loader_driver,
- },
- .max_radios = 2,
- .single_pdev_only = false,
- .qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_QCN9274,
- .internal_sleep_clock = false,
-
- .hw_ops = &qcn9274_ops,
- .ring_mask = &ath12k_hw_ring_mask_qcn9274,
- .regs = &qcn9274_v2_regs,
-
- .host_ce_config = ath12k_host_ce_config_qcn9274,
- .ce_count = 16,
- .target_ce_config = ath12k_target_ce_config_wlan_qcn9274,
- .target_ce_count = 12,
- .svc_to_ce_map = ath12k_target_service_to_ce_map_wlan_qcn9274,
- .svc_to_ce_map_len = 18,
-
- .hal_params = &ath12k_hw_hal_params_qcn9274,
-
- .rxdma1_enable = true,
- .num_rxdma_per_pdev = 1,
- .num_rxdma_dst_ring = 0,
- .rx_mac_buf_ring = false,
- .vdev_start_delay = false,
-
- .interface_modes = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_AP) |
- BIT(NL80211_IFTYPE_MESH_POINT) |
- BIT(NL80211_IFTYPE_AP_VLAN),
- .supports_monitor = true,
-
- .idle_ps = false,
- .download_calib = true,
- .supports_suspend = false,
- .tcl_ring_retry = true,
- .reoq_lut_support = true,
- .supports_shadow_regs = false,
-
- .num_tcl_banks = 48,
- .max_tx_ring = 4,
-
- .mhi_config = &ath12k_mhi_config_qcn9274,
-
- .wmi_init = ath12k_wmi_init_qcn9274,
-
- .hal_ops = &hal_qcn9274_ops,
-
- .qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01),
-
- .rfkill_pin = 0,
- .rfkill_cfg = 0,
- .rfkill_on_level = 0,
-
- .rddm_size = 0x600000,
-
- .def_num_link = 0,
- .max_mlo_peer = 256,
-
- .otp_board_id_register = QCN9274_QFPROM_RAW_RFA_PDET_ROW13_LSB,
-
- .supports_sta_ps = false,
-
- .acpi_guid = NULL,
- .supports_dynamic_smps_6ghz = true,
-
- .iova_mask = 0,
-
- .supports_aspm = false,
-
- .ce_ie_addr = NULL,
- .ce_remap = NULL,
- .bdf_addr_offset = 0,
-
- .current_cc_support = false,
-
- .dp_primary_link_only = true,
- },
- {
- .name = "ipq5332 hw1.0",
- .hw_rev = ATH12K_HW_IPQ5332_HW10,
- .fw = {
- .dir = "IPQ5332/hw1.0",
- .board_size = 256 * 1024,
- .cal_offset = 128 * 1024,
- .m3_loader = ath12k_m3_fw_loader_remoteproc,
- },
- .max_radios = 1,
- .single_pdev_only = false,
- .qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ5332,
- .internal_sleep_clock = false,
-
- .hw_ops = &qcn9274_ops,
- .regs = &ipq5332_regs,
- .ring_mask = &ath12k_hw_ring_mask_ipq5332,
-
- .host_ce_config = ath12k_host_ce_config_ipq5332,
- .ce_count = 12,
- .target_ce_config = ath12k_target_ce_config_wlan_ipq5332,
- .target_ce_count = 12,
- .svc_to_ce_map = ath12k_target_service_to_ce_map_wlan_ipq5332,
- .svc_to_ce_map_len = 18,
-
- .hal_params = &ath12k_hw_hal_params_ipq5332,
-
- .rxdma1_enable = false,
- .num_rxdma_per_pdev = 1,
- .num_rxdma_dst_ring = 0,
- .rx_mac_buf_ring = false,
- .vdev_start_delay = false,
-
- .interface_modes = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_AP) |
- BIT(NL80211_IFTYPE_MESH_POINT),
- .supports_monitor = false,
-
- .idle_ps = false,
- .download_calib = true,
- .supports_suspend = false,
- .tcl_ring_retry = true,
- .reoq_lut_support = false,
- .supports_shadow_regs = false,
-
- .num_tcl_banks = 48,
- .max_tx_ring = 4,
-
- .wmi_init = &ath12k_wmi_init_qcn9274,
-
- .hal_ops = &hal_qcn9274_ops,
-
- .qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01),
-
- .rfkill_pin = 0,
- .rfkill_cfg = 0,
- .rfkill_on_level = 0,
-
- .rddm_size = 0,
-
- .def_num_link = 0,
- .max_mlo_peer = 256,
-
- .otp_board_id_register = 0,
-
- .supports_sta_ps = false,
-
- .acpi_guid = NULL,
- .supports_dynamic_smps_6ghz = false,
- .iova_mask = 0,
- .supports_aspm = false,
-
- .ce_ie_addr = &ath12k_ce_ie_addr_ipq5332,
- .ce_remap = &ath12k_ce_remap_ipq5332,
- .bdf_addr_offset = 0xC00000,
-
- .dp_primary_link_only = true,
- },
-};
-
-int ath12k_hw_init(struct ath12k_base *ab)
-{
- const struct ath12k_hw_params *hw_params = NULL;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(ath12k_hw_params); i++) {
- hw_params = &ath12k_hw_params[i];
-
- if (hw_params->hw_rev == ab->hw_rev)
- break;
- }
-
- if (i == ARRAY_SIZE(ath12k_hw_params)) {
- ath12k_err(ab, "Unsupported hardware version: 0x%x\n", ab->hw_rev);
- return -EINVAL;
- }
-
- ab->hw_params = hw_params;
-
- ath12k_info(ab, "Hardware name: %s\n", ab->hw_params->name);
-
- return 0;
-}
diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h
index 8ce11c3e6d5c..a9888e0521a1 100644
--- a/drivers/net/wireless/ath/ath12k/hw.h
+++ b/drivers/net/wireless/ath/ath12k/hw.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-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH12K_HW_H
@@ -78,6 +78,7 @@
#define ATH12K_DEFAULT_CAL_FILE "caldata.bin"
#define ATH12K_AMSS_FILE "amss.bin"
#define ATH12K_M3_FILE "m3.bin"
+#define ATH12K_AUX_UC_FILE "aux_ucode.bin"
#define ATH12K_REGDB_FILE_NAME "regdb.bin"
#define ATH12K_PCIE_MAX_PAYLOAD_SIZE 128
@@ -128,11 +129,6 @@ struct ath12k_hw_ring_mask {
u8 tx_mon_dest[ATH12K_EXT_IRQ_GRP_NUM_MAX];
};
-struct ath12k_hw_hal_params {
- enum hal_rx_buf_return_buf_manager rx_buf_rbm;
- u32 wbm2sw_cc_enable;
-};
-
enum ath12k_m3_fw_loaders {
ath12k_m3_fw_loader_driver,
ath12k_m3_fw_loader_remoteproc,
@@ -147,6 +143,7 @@ struct ath12k_hw_params {
size_t board_size;
size_t cal_offset;
enum ath12k_m3_fw_loaders m3_loader;
+ bool download_aux_ucode:1;
} fw;
u8 max_radios;
@@ -156,7 +153,6 @@ struct ath12k_hw_params {
const struct ath12k_hw_ops *hw_ops;
const struct ath12k_hw_ring_mask *ring_mask;
- const struct ath12k_hw_regs *regs;
const struct ce_attr *host_ce_config;
u32 ce_count;
@@ -165,8 +161,6 @@ struct ath12k_hw_params {
const struct service_to_pipe *svc_to_ce_map;
u32 svc_to_ce_map_len;
- const struct ath12k_hw_hal_params *hal_params;
-
bool rxdma1_enable:1;
int num_rxdma_per_pdev;
int num_rxdma_dst_ring;
@@ -193,8 +187,6 @@ struct ath12k_hw_params {
void (*wmi_init)(struct ath12k_base *ab,
struct ath12k_wmi_resource_config_arg *config);
- const struct hal_ops *hal_ops;
-
u64 qmi_cnss_feature_bitmap;
u32 rfkill_pin;
@@ -285,86 +277,6 @@ enum ath12k_bd_ie_type {
ATH12K_BD_IE_REGDB = 1,
};
-struct ath12k_hw_regs {
- u32 hal_tcl1_ring_id;
- u32 hal_tcl1_ring_misc;
- u32 hal_tcl1_ring_tp_addr_lsb;
- u32 hal_tcl1_ring_tp_addr_msb;
- u32 hal_tcl1_ring_consumer_int_setup_ix0;
- u32 hal_tcl1_ring_consumer_int_setup_ix1;
- u32 hal_tcl1_ring_msi1_base_lsb;
- u32 hal_tcl1_ring_msi1_base_msb;
- u32 hal_tcl1_ring_msi1_data;
- u32 hal_tcl_ring_base_lsb;
- u32 hal_tcl1_ring_base_lsb;
- u32 hal_tcl1_ring_base_msb;
- u32 hal_tcl2_ring_base_lsb;
-
- u32 hal_tcl_status_ring_base_lsb;
-
- u32 hal_reo1_qdesc_addr;
- u32 hal_reo1_qdesc_max_peerid;
-
- u32 hal_wbm_idle_ring_base_lsb;
- u32 hal_wbm_idle_ring_misc_addr;
- u32 hal_wbm_r0_idle_list_cntl_addr;
- u32 hal_wbm_r0_idle_list_size_addr;
- u32 hal_wbm_scattered_ring_base_lsb;
- u32 hal_wbm_scattered_ring_base_msb;
- u32 hal_wbm_scattered_desc_head_info_ix0;
- u32 hal_wbm_scattered_desc_head_info_ix1;
- u32 hal_wbm_scattered_desc_tail_info_ix0;
- u32 hal_wbm_scattered_desc_tail_info_ix1;
- u32 hal_wbm_scattered_desc_ptr_hp_addr;
-
- u32 hal_wbm_sw_release_ring_base_lsb;
- u32 hal_wbm_sw1_release_ring_base_lsb;
- u32 hal_wbm0_release_ring_base_lsb;
- u32 hal_wbm1_release_ring_base_lsb;
-
- u32 pcie_qserdes_sysclk_en_sel;
- u32 pcie_pcs_osc_dtct_config_base;
-
- u32 hal_umac_ce0_src_reg_base;
- u32 hal_umac_ce0_dest_reg_base;
- u32 hal_umac_ce1_src_reg_base;
- u32 hal_umac_ce1_dest_reg_base;
-
- u32 hal_ppe_rel_ring_base;
-
- u32 hal_reo2_ring_base;
- u32 hal_reo1_misc_ctrl_addr;
- u32 hal_reo1_sw_cookie_cfg0;
- u32 hal_reo1_sw_cookie_cfg1;
- u32 hal_reo1_qdesc_lut_base0;
- u32 hal_reo1_qdesc_lut_base1;
- u32 hal_reo1_ring_base_lsb;
- u32 hal_reo1_ring_base_msb;
- u32 hal_reo1_ring_id;
- u32 hal_reo1_ring_misc;
- u32 hal_reo1_ring_hp_addr_lsb;
- u32 hal_reo1_ring_hp_addr_msb;
- u32 hal_reo1_ring_producer_int_setup;
- u32 hal_reo1_ring_msi1_base_lsb;
- u32 hal_reo1_ring_msi1_base_msb;
- u32 hal_reo1_ring_msi1_data;
- u32 hal_reo1_aging_thres_ix0;
- u32 hal_reo1_aging_thres_ix1;
- u32 hal_reo1_aging_thres_ix2;
- u32 hal_reo1_aging_thres_ix3;
-
- u32 hal_reo2_sw0_ring_base;
-
- u32 hal_sw2reo_ring_base;
- u32 hal_sw2reo1_ring_base;
-
- u32 hal_reo_cmd_ring_base;
-
- u32 hal_reo_status_ring_base;
-
- u32 gcc_gcc_pcie_hot_rst;
-};
-
static inline const char *ath12k_bd_ie_type_str(enum ath12k_bd_ie_type type)
{
switch (type) {
@@ -377,6 +289,4 @@ static inline const char *ath12k_bd_ie_type_str(enum ath12k_bd_ie_type type)
return "unknown";
}
-int ath12k_hw_init(struct ath12k_base *ab);
-
#endif
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index e0e49f782bf8..68431a0e128e 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -21,6 +21,8 @@
#include "hif.h"
#include "wow.h"
#include "debugfs_sta.h"
+#include "dp.h"
+#include "dp_cmn.h"
#define CHAN2G(_channel, _freq, _flags) { \
.band = NL80211_BAND_2GHZ, \
@@ -361,6 +363,7 @@ u16 ath12k_mac_he_convert_tones_to_ru_tones(u16 tones)
return RU_26;
}
}
+EXPORT_SYMBOL(ath12k_mac_he_convert_tones_to_ru_tones);
enum nl80211_eht_gi ath12k_mac_eht_gi_to_nl80211_eht_gi(u8 sgi)
{
@@ -375,6 +378,7 @@ enum nl80211_eht_gi ath12k_mac_eht_gi_to_nl80211_eht_gi(u8 sgi)
return NL80211_RATE_INFO_EHT_GI_0_8;
}
}
+EXPORT_SYMBOL(ath12k_mac_eht_gi_to_nl80211_eht_gi);
enum nl80211_eht_ru_alloc ath12k_mac_eht_ru_tones_to_nl80211_eht_ru_alloc(u16 ru_tones)
{
@@ -415,6 +419,7 @@ enum nl80211_eht_ru_alloc ath12k_mac_eht_ru_tones_to_nl80211_eht_ru_alloc(u16 ru
return NL80211_RATE_INFO_EHT_RU_ALLOC_26;
}
}
+EXPORT_SYMBOL(ath12k_mac_eht_ru_tones_to_nl80211_eht_ru_alloc);
enum rate_info_bw
ath12k_mac_bw_to_mac80211_bw(enum ath12k_supported_bw bw)
@@ -441,6 +446,7 @@ ath12k_mac_bw_to_mac80211_bw(enum ath12k_supported_bw bw)
return ret;
}
+EXPORT_SYMBOL(ath12k_mac_bw_to_mac80211_bw);
enum ath12k_supported_bw ath12k_mac_mac80211_bw_to_ath12k_bw(enum rate_info_bw bw)
{
@@ -484,6 +490,7 @@ int ath12k_mac_hw_ratecode_to_legacy_rate(u8 hw_rc, u8 preamble, u8 *rateidx,
return -EINVAL;
}
+EXPORT_SYMBOL(ath12k_mac_hw_ratecode_to_legacy_rate);
u8 ath12k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
u32 bitrate)
@@ -1167,26 +1174,119 @@ static int ath12k_mac_set_kickout(struct ath12k_link_vif *arvif)
return 0;
}
+static void ath12k_mac_link_sta_rhash_cleanup(void *data, struct ieee80211_sta *sta)
+{
+ u8 link_id;
+ unsigned long links_map;
+ struct ath12k_sta *ahsta;
+ struct ath12k *ar = data;
+ struct ath12k_link_sta *arsta;
+ struct ath12k_link_vif *arvif;
+ struct ath12k_base *ab = ar->ab;
+
+ ahsta = ath12k_sta_to_ahsta(sta);
+ links_map = ahsta->links_map;
+
+ rcu_read_lock();
+ for_each_set_bit(link_id, &links_map, IEEE80211_MLD_MAX_NUM_LINKS) {
+ arsta = rcu_dereference(ahsta->link[link_id]);
+ if (!arsta)
+ continue;
+ arvif = arsta->arvif;
+ if (!(arvif->ar == ar))
+ continue;
+
+ spin_lock_bh(&ab->base_lock);
+ ath12k_link_sta_rhash_delete(ab, arsta);
+ spin_unlock_bh(&ab->base_lock);
+ }
+ rcu_read_unlock();
+}
+
void ath12k_mac_peer_cleanup_all(struct ath12k *ar)
{
- struct ath12k_peer *peer, *tmp;
+ struct ath12k_dp_link_peer *peer, *tmp;
struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_link_vif *arvif, *tmp_vif;
+ struct ath12k_dp_hw *dp_hw = &ar->ah->dp_hw;
+ struct ath12k_dp_peer *dp_peer = NULL;
+ u16 peerid_index;
+ struct list_head peers;
+
+ INIT_LIST_HEAD(&peers);
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) {
+ spin_lock_bh(&dp->dp_lock);
+ list_for_each_entry_safe(peer, tmp, &dp->peers, list) {
/* Skip Rx TID cleanup for self peer */
- if (peer->sta)
+ if (peer->sta && peer->dp_peer)
ath12k_dp_rx_peer_tid_cleanup(ar, peer);
- list_del(&peer->list);
- kfree(peer);
+ /* cleanup dp peer */
+ spin_lock_bh(&dp_hw->peer_lock);
+ dp_peer = peer->dp_peer;
+ peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id);
+ rcu_assign_pointer(dp_peer->link_peers[peer->link_id], NULL);
+ rcu_assign_pointer(dp_hw->dp_peers[peerid_index], NULL);
+ spin_unlock_bh(&dp_hw->peer_lock);
+
+ ath12k_dp_link_peer_rhash_delete(dp, peer);
+
+ list_move(&peer->list, &peers);
+ }
+ spin_unlock_bh(&dp->dp_lock);
+
+ synchronize_rcu();
+
+ list_for_each_entry_safe(peer, tmp, &peers, list) {
+ ath12k_dp_link_peer_free(peer);
}
- spin_unlock_bh(&ab->base_lock);
ar->num_peers = 0;
ar->num_stations = 0;
+
+ /* Cleanup rhash table maintained for arsta by iterating over sta */
+ ieee80211_iterate_stations_mtx(ar->ah->hw, ath12k_mac_link_sta_rhash_cleanup,
+ ar);
+
+ /* Delete all the self dp_peers on asserted radio */
+ list_for_each_entry_safe_reverse(arvif, tmp_vif, &ar->arvifs, list) {
+ if ((arvif->ahvif->vdev_type == WMI_VDEV_TYPE_AP) &&
+ (arvif->link_id < IEEE80211_MLD_MAX_NUM_LINKS)) {
+ ath12k_dp_peer_delete(dp_hw, arvif->bssid, NULL);
+ arvif->num_stations = 0;
+ }
+ }
+}
+
+void ath12k_mac_dp_peer_cleanup(struct ath12k_hw *ah)
+{
+ struct list_head peers;
+ struct ath12k_dp_peer *dp_peer, *tmp;
+ struct ath12k_dp_hw *dp_hw = &ah->dp_hw;
+
+ INIT_LIST_HEAD(&peers);
+
+ spin_lock_bh(&dp_hw->peer_lock);
+ list_for_each_entry_safe(dp_peer, tmp, &dp_hw->dp_peers_list, list) {
+ if (dp_peer->is_mlo) {
+ rcu_assign_pointer(dp_hw->dp_peers[dp_peer->peer_id], NULL);
+ clear_bit(dp_peer->peer_id, ah->free_ml_peer_id_map);
+ }
+
+ list_move(&dp_peer->list, &peers);
+ }
+
+ spin_unlock_bh(&dp_hw->peer_lock);
+
+ synchronize_rcu();
+
+ list_for_each_entry_safe(dp_peer, tmp, &peers, list) {
+ list_del(&dp_peer->list);
+ kfree(dp_peer);
+ }
}
static int ath12k_mac_vdev_setup_sync(struct ath12k *ar)
@@ -1458,10 +1558,11 @@ err:
return ret;
}
-static int ath12k_mac_op_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
+int ath12k_mac_op_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
{
return 0;
}
+EXPORT_SYMBOL(ath12k_mac_op_config);
static int ath12k_mac_setup_bcn_p2p_ie(struct ath12k_link_vif *arvif,
struct sk_buff *bcn)
@@ -3728,10 +3829,11 @@ static void ath12k_bss_assoc(struct ath12k *ar,
struct ath12k_link_sta *arsta;
struct ieee80211_sta *ap_sta;
struct ath12k_sta *ahsta;
- struct ath12k_peer *peer;
+ struct ath12k_dp_link_peer *peer;
bool is_auth = false;
u32 hemode = 0;
int ret;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ar->ab);
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
@@ -3843,13 +3945,14 @@ static void ath12k_bss_assoc(struct ath12k *ar,
"mac vdev %d up (associated) bssid %pM aid %d\n",
arvif->vdev_id, bss_conf->bssid, vif->cfg.aid);
- spin_lock_bh(&ar->ab->base_lock);
+ spin_lock_bh(&dp->dp_lock);
- peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arvif->bssid);
+ peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id,
+ arvif->bssid);
if (peer && peer->is_authorized)
is_auth = true;
- spin_unlock_bh(&ar->ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
/* Authorize BSS Peer */
if (is_auth) {
@@ -4085,6 +4188,9 @@ static void ath12k_mac_remove_link_interface(struct ieee80211_hw *hw,
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);
+
+ if (arvif->link_id < IEEE80211_MLD_MAX_NUM_LINKS)
+ ath12k_dp_peer_delete(&ah->dp_hw, arvif->bssid, NULL);
}
ath12k_mac_vdev_delete(ar, arvif);
}
@@ -4138,7 +4244,7 @@ static void ath12k_mac_unassign_link_vif(struct ath12k_link_vif *arvif)
memset(arvif, 0, sizeof(*arvif));
}
-static int
+int
ath12k_mac_op_change_vif_links(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u16 old_links, u16 new_links,
@@ -4175,8 +4281,10 @@ ath12k_mac_op_change_vif_links(struct ieee80211_hw *hw,
if (WARN_ON(!arvif))
return -EINVAL;
- if (!arvif->is_created)
+ if (!arvif->is_created) {
+ ath12k_mac_unassign_link_vif(arvif);
continue;
+ }
if (WARN_ON(!arvif->ar))
return -EINVAL;
@@ -4187,6 +4295,7 @@ ath12k_mac_op_change_vif_links(struct ieee80211_hw *hw,
return 0;
}
+EXPORT_SYMBOL(ath12k_mac_op_change_vif_links);
static int ath12k_mac_fils_discovery(struct ath12k_link_vif *arvif,
struct ieee80211_bss_conf *info)
@@ -4235,9 +4344,9 @@ static int ath12k_mac_fils_discovery(struct ath12k_link_vif *arvif,
return ret;
}
-static void ath12k_mac_op_vif_cfg_changed(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- u64 changed)
+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;
@@ -4305,6 +4414,7 @@ static void ath12k_mac_op_vif_cfg_changed(struct ieee80211_hw *hw,
}
}
}
+EXPORT_SYMBOL(ath12k_mac_op_vif_cfg_changed);
static void ath12k_mac_vif_setup_ps(struct ath12k_link_vif *arvif)
{
@@ -4397,6 +4507,166 @@ static void ath12k_wmi_vdev_params_up(struct ath12k *ar,
arvif->vdev_id, ret);
}
+static int ath12k_mac_config_obss_pd(struct ath12k_link_vif *arvif,
+ const struct ieee80211_he_obss_pd *he_obss_pd)
+{
+ struct ath12k_wmi_obss_pd_arg obss_pd_arg = {};
+ u32 srg_bitmap[2], non_srg_bitmap[2];
+ struct ath12k *ar = arvif->ar;
+ u32 param_id, pdev_id;
+ u32 param_val;
+ int ret;
+
+ if (ar->ab->hw_params->single_pdev_only)
+ pdev_id = ath12k_mac_get_target_pdev_id_from_vif(arvif);
+ else
+ pdev_id = ar->pdev->pdev_id;
+
+ /* Set and enable SRG/non-SRG OBSS PD threshold */
+ param_id = WMI_PDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD;
+ if (ar->monitor_started || !he_obss_pd->enable) {
+ ret = ath12k_wmi_pdev_set_param(ar, param_id, 0, pdev_id);
+ if (ret)
+ ath12k_warn(ar->ab,
+ "failed to set OBSS PD threshold for pdev %u: %d\n",
+ pdev_id, ret);
+ return ret;
+ }
+
+ /*
+ * This service flag indicates firmware support for SRG/SRP-based
+ * spatial reuse. It also specifies whether OBSS PD threshold values
+ * should be interpreted as dB (offset) or dBm (absolute) units.
+ */
+ obss_pd_arg.srp_support = test_bit(WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT,
+ ar->ab->wmi_ab.svc_map);
+
+ if (!(he_obss_pd->sr_ctrl &
+ IEEE80211_HE_SPR_NON_SRG_OBSS_PD_SR_DISALLOWED)) {
+ if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT)
+ obss_pd_arg.non_srg_th = ATH12K_OBSS_PD_MAX_THRESHOLD +
+ he_obss_pd->non_srg_max_offset;
+ else
+ obss_pd_arg.non_srg_th = ATH12K_OBSS_PD_NON_SRG_MAX_THRESHOLD;
+
+ if (!obss_pd_arg.srp_support)
+ obss_pd_arg.non_srg_th -= ATH12K_DEFAULT_NOISE_FLOOR;
+
+ obss_pd_arg.non_srg_enabled = true;
+ }
+
+ if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT) {
+ obss_pd_arg.srg_th = ATH12K_OBSS_PD_MAX_THRESHOLD +
+ he_obss_pd->max_offset;
+ obss_pd_arg.srg_enabled = true;
+ }
+
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
+ "pdev %u OBSS PD sr_ctrl 0x%x srg_th %d dBm non_srg_th %d dBm\n",
+ pdev_id, he_obss_pd->sr_ctrl,
+ obss_pd_arg.srg_th, obss_pd_arg.non_srg_th);
+
+ param_val = ath12k_wmi_build_obss_pd(&obss_pd_arg);
+ ret = ath12k_wmi_pdev_set_param(ar, param_id, param_val, pdev_id);
+ if (ret) {
+ ath12k_warn(ar->ab,
+ "failed to set OBSS PD threshold for pdev %u: %d\n",
+ pdev_id, ret);
+ return ret;
+ }
+
+ /* Enable OBSS PD for all access category */
+ param_id = WMI_PDEV_PARAM_SET_CMD_OBSS_PD_PER_AC;
+ param_val = 0xf;
+ ret = ath12k_wmi_pdev_set_param(ar, param_id, param_val, pdev_id);
+ if (ret) {
+ ath12k_warn(ar->ab,
+ "failed to set OBSS PD per ac for pdev %u: %d\n",
+ pdev_id, ret);
+ return ret;
+ }
+
+ /* Set SR prohibit */
+ param_id = WMI_PDEV_PARAM_ENABLE_SR_PROHIBIT;
+ param_val = !!(he_obss_pd->sr_ctrl &
+ IEEE80211_HE_SPR_HESIGA_SR_VAL15_ALLOWED);
+ ret = ath12k_wmi_pdev_set_param(ar, param_id, param_val, pdev_id);
+ if (ret) {
+ ath12k_warn(ar->ab, "failed to set SR prohibit for pdev %u: %d\n",
+ pdev_id, ret);
+ return ret;
+ }
+
+ if (!obss_pd_arg.srp_support)
+ return 0;
+
+ memcpy(srg_bitmap, he_obss_pd->bss_color_bitmap, sizeof(srg_bitmap));
+ /* Set SRG BSS color bitmap */
+ ret = ath12k_wmi_pdev_set_srg_bss_color_bitmap(ar, pdev_id, srg_bitmap);
+ if (ret) {
+ ath12k_warn(ar->ab,
+ "failed to set SRG bss color bitmap for pdev %u: %d\n",
+ pdev_id, ret);
+ return ret;
+ }
+
+ /* Enable BSS colors for SRG */
+ ret = ath12k_wmi_pdev_srg_obss_color_enable_bitmap(ar, pdev_id, srg_bitmap);
+ if (ret) {
+ ath12k_warn(ar->ab,
+ "failed to enable SRG bss color bitmap pdev %u: %d\n",
+ pdev_id, ret);
+ return ret;
+ }
+
+ memcpy(srg_bitmap, he_obss_pd->partial_bssid_bitmap, sizeof(srg_bitmap));
+ /* Set SRG partial bssid bitmap */
+ ret = ath12k_wmi_pdev_set_srg_partial_bssid_bitmap(ar, pdev_id, srg_bitmap);
+ if (ret) {
+ ath12k_warn(ar->ab,
+ "failed to set SRG partial bssid bitmap for pdev %u: %d\n",
+ pdev_id, ret);
+ return ret;
+ }
+
+ /* Enable partial bssid mask for SRG */
+ ret = ath12k_wmi_pdev_srg_obss_bssid_enable_bitmap(ar, pdev_id, srg_bitmap);
+ if (ret) {
+ ath12k_warn(ar->ab,
+ "failed to enable SRG bssid bitmap pdev %u: %d\n",
+ pdev_id, ret);
+ return ret;
+ }
+
+ /*
+ * No explicit non-SRG bitmap from mac80211; enable all colors/bssids
+ * as non-SRG candidates. Actual SRG members are filtered by SRG bitmaps.
+ */
+ memset(non_srg_bitmap, 0xff, sizeof(non_srg_bitmap));
+
+ /* Enable BSS colors for non-SRG */
+ ret = ath12k_wmi_pdev_non_srg_obss_color_enable_bitmap(ar, pdev_id,
+ non_srg_bitmap);
+ if (ret) {
+ ath12k_warn(ar->ab,
+ "failed to enable non SRG color bitmap pdev %u: %d\n",
+ pdev_id, ret);
+ return ret;
+ }
+
+ /* Enable partial bssid mask for non-SRG */
+ ret = ath12k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(ar, pdev_id,
+ non_srg_bitmap);
+ if (ret) {
+ ath12k_warn(ar->ab,
+ "failed to enable non SRG bssid bitmap pdev %u: %d\n",
+ pdev_id, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
static void ath12k_mac_bss_info_changed(struct ath12k *ar,
struct ath12k_link_vif *arvif,
struct ieee80211_bss_conf *info,
@@ -4688,9 +4958,13 @@ skip_vdev_up:
ath12k_wmi_send_twt_disable_cmd(ar, ar->pdev->pdev_id);
}
- if (changed & BSS_CHANGED_HE_OBSS_PD)
- ath12k_wmi_send_obss_spr_cmd(ar, arvif->vdev_id,
- &info->he_obss_pd);
+ if (changed & BSS_CHANGED_HE_OBSS_PD) {
+ if (vif->type == NL80211_IFTYPE_AP)
+ ath12k_mac_config_obss_pd(arvif, &info->he_obss_pd);
+ else
+ ath12k_wmi_send_obss_spr_cmd(ar, arvif->vdev_id,
+ &info->he_obss_pd);
+ }
if (changed & BSS_CHANGED_HE_BSS_COLOR) {
if (vif->type == NL80211_IFTYPE_AP) {
@@ -4780,10 +5054,10 @@ static void ath12k_ahvif_put_link_cache(struct ath12k_vif *ahvif, u8 link_id)
ahvif->cache[link_id] = NULL;
}
-static void ath12k_mac_op_link_info_changed(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *info,
- u64 changed)
+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 *ahvif = ath12k_vif_to_ahvif(vif);
@@ -4813,6 +5087,7 @@ static void ath12k_mac_op_link_info_changed(struct ieee80211_hw *hw,
ath12k_mac_bss_info_changed(ar, arvif, info, changed);
}
+EXPORT_SYMBOL(ath12k_mac_op_link_info_changed);
static struct ath12k*
ath12k_mac_select_scan_device(struct ieee80211_hw *hw,
@@ -5114,10 +5389,10 @@ int ath12k_mac_get_fw_stats(struct ath12k *ar,
return 0;
}
-static int ath12k_mac_op_get_txpower(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- unsigned int link_id,
- int *dbm)
+int ath12k_mac_op_get_txpower(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ unsigned int link_id,
+ int *dbm)
{
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_fw_stats_req_params params = {};
@@ -5191,6 +5466,7 @@ err_fallback:
*dbm);
return 0;
}
+EXPORT_SYMBOL(ath12k_mac_op_get_txpower);
static u8
ath12k_mac_find_link_id_by_ar(struct ath12k_vif *ahvif, struct ath12k *ar)
@@ -5402,9 +5678,9 @@ exit:
return ret;
}
-static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_scan_request *hw_req)
+int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_scan_request *hw_req)
{
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ieee80211_channel **chan_list, *chan;
@@ -5482,9 +5758,10 @@ abort:
kfree(chan_list);
return ret;
}
+EXPORT_SYMBOL(ath12k_mac_op_hw_scan);
-static void ath12k_mac_op_cancel_hw_scan(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+void ath12k_mac_op_cancel_hw_scan(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
unsigned long link_id, links_map = ahvif->links_map;
@@ -5506,6 +5783,7 @@ static void ath12k_mac_op_cancel_hw_scan(struct ieee80211_hw *hw,
cancel_delayed_work_sync(&ar->scan.timeout);
}
}
+EXPORT_SYMBOL(ath12k_mac_op_cancel_hw_scan);
static int ath12k_install_key(struct ath12k_link_vif *arvif,
struct ieee80211_key_conf *key,
@@ -5613,7 +5891,7 @@ install:
return -ETIMEDOUT;
if (ether_addr_equal(arg.macaddr, arvif->bssid))
- ahvif->key_cipher = arg.ieee80211_key_cipher;
+ ahvif->dp_vif.key_cipher = arg.ieee80211_key_cipher;
if (ar->install_key_status) {
ret = -EINVAL;
@@ -5656,27 +5934,40 @@ static int ath12k_clear_peer_keys(struct ath12k_link_vif *arvif,
{
struct ath12k *ar = arvif->ar;
struct ath12k_base *ab = ar->ab;
- struct ath12k_peer *peer;
+ struct ath12k_dp_link_peer *peer;
int first_errno = 0;
int ret;
- int i;
+ int i, len;
u32 flags = 0;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1] = {};
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- spin_lock_bh(&ab->base_lock);
- peer = ath12k_peer_find(ab, arvif->vdev_id, addr);
- spin_unlock_bh(&ab->base_lock);
-
- if (!peer)
+ spin_lock_bh(&dp->dp_lock);
+ peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id, addr);
+ if (!peer || !peer->dp_peer) {
+ spin_unlock_bh(&dp->dp_lock);
return -ENOENT;
+ }
+
+ len = ARRAY_SIZE(peer->dp_peer->keys);
+ for (i = 0; i < len; i++) {
+ if (!peer->dp_peer->keys[i])
+ continue;
- for (i = 0; i < ARRAY_SIZE(peer->keys); i++) {
- if (!peer->keys[i])
+ keys[i] = peer->dp_peer->keys[i];
+ peer->dp_peer->keys[i] = NULL;
+ }
+
+ spin_unlock_bh(&dp->dp_lock);
+
+ for (i = 0; i < len; i++) {
+ if (!keys[i])
continue;
/* key flags are not required to delete the key */
- ret = ath12k_install_key(arvif, peer->keys[i],
+ ret = ath12k_install_key(arvif, keys[i],
DISABLE_KEY, addr, flags);
if (ret < 0 && first_errno == 0)
first_errno = ret;
@@ -5684,10 +5975,6 @@ static int ath12k_clear_peer_keys(struct ath12k_link_vif *arvif,
if (ret < 0)
ath12k_warn(ab, "failed to remove peer key %d: %d\n",
i, ret);
-
- spin_lock_bh(&ab->base_lock);
- peer->keys[i] = NULL;
- spin_unlock_bh(&ab->base_lock);
}
return first_errno;
@@ -5700,11 +5987,12 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
{
struct ieee80211_sta *sta = NULL;
struct ath12k_base *ab = ar->ab;
- struct ath12k_peer *peer;
+ struct ath12k_dp_link_peer *peer;
struct ath12k_sta *ahsta;
const u8 *peer_addr;
int ret;
u32 flags = 0;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
@@ -5724,11 +6012,12 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
/* the peer should not disappear in mid-way (unless FW goes awry) since
* 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);
- spin_unlock_bh(&ab->base_lock);
+ spin_lock_bh(&dp->dp_lock);
+ peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id,
+ peer_addr);
+ if (!peer || !peer->dp_peer) {
+ spin_unlock_bh(&dp->dp_lock);
- if (!peer) {
if (cmd == SET_KEY) {
ath12k_warn(ab, "cannot install key for non-existent peer %pM\n",
peer_addr);
@@ -5741,6 +6030,8 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
return 0;
}
+ spin_unlock_bh(&dp->dp_lock);
+
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
flags = WMI_KEY_PAIRWISE;
else
@@ -5758,23 +6049,26 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
return ret;
}
- spin_lock_bh(&ab->base_lock);
- peer = ath12k_peer_find(ab, arvif->vdev_id, peer_addr);
- if (peer && cmd == SET_KEY) {
- peer->keys[key->keyidx] = key;
+ spin_lock_bh(&dp->dp_lock);
+ peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id,
+ peer_addr);
+ if (peer && peer->dp_peer && cmd == SET_KEY) {
+ peer->dp_peer->keys[key->keyidx] = key;
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
- peer->ucast_keyidx = key->keyidx;
- peer->sec_type = ath12k_dp_tx_get_encrypt_type(key->cipher);
+ peer->dp_peer->ucast_keyidx = key->keyidx;
+ peer->dp_peer->sec_type =
+ ath12k_dp_tx_get_encrypt_type(key->cipher);
} else {
- peer->mcast_keyidx = key->keyidx;
- peer->sec_type_grp = ath12k_dp_tx_get_encrypt_type(key->cipher);
+ peer->dp_peer->mcast_keyidx = key->keyidx;
+ peer->dp_peer->sec_type_grp =
+ ath12k_dp_tx_get_encrypt_type(key->cipher);
}
- } else if (peer && cmd == DISABLE_KEY) {
- peer->keys[key->keyidx] = NULL;
+ } else if (peer && peer->dp_peer && cmd == DISABLE_KEY) {
+ peer->dp_peer->keys[key->keyidx] = NULL;
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
- peer->ucast_keyidx = 0;
+ peer->dp_peer->ucast_keyidx = 0;
else
- peer->mcast_keyidx = 0;
+ peer->dp_peer->mcast_keyidx = 0;
} else if (!peer)
/* impossible unless FW goes crazy */
ath12k_warn(ab, "peer %pM disappeared!\n", peer_addr);
@@ -5799,7 +6093,7 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
}
}
- spin_unlock_bh(&ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
return 0;
}
@@ -5843,9 +6137,9 @@ static int ath12k_mac_update_key_cache(struct ath12k_vif_cache *cache,
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)
+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 *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_link_vif *arvif;
@@ -5932,6 +6226,7 @@ static int ath12k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return 0;
}
+EXPORT_SYMBOL(ath12k_mac_op_set_key);
static int
ath12k_mac_bitrate_mask_num_vht_rates(struct ath12k *ar,
@@ -6557,46 +6852,47 @@ static void ath12k_mac_station_post_remove(struct ath12k *ar,
{
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
- struct ath12k_peer *peer;
+ struct ath12k_dp_link_peer *peer;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ar->ab);
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
ath12k_mac_dec_num_stations(arvif, arsta);
- spin_lock_bh(&ar->ab->base_lock);
+ spin_lock_bh(&dp->dp_lock);
- peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arsta->addr);
+ peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id,
+ arsta->addr);
if (peer && peer->sta == sta) {
ath12k_warn(ar->ab, "Found peer entry %pM n vdev %i after it was supposedly removed\n",
vif->addr, arvif->vdev_id);
peer->sta = NULL;
- list_del(&peer->list);
- kfree(peer);
+
+ ath12k_dp_link_peer_free(peer);
ar->num_peers--;
}
- spin_unlock_bh(&ar->ab->base_lock);
-
- kfree(arsta->rx_stats);
- arsta->rx_stats = NULL;
+ spin_unlock_bh(&dp->dp_lock);
}
static int ath12k_mac_station_unauthorize(struct ath12k *ar,
struct ath12k_link_vif *arvif,
struct ath12k_link_sta *arsta)
{
- struct ath12k_peer *peer;
+ struct ath12k_dp_link_peer *peer;
int ret;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ar->ab);
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- spin_lock_bh(&ar->ab->base_lock);
+ spin_lock_bh(&dp->dp_lock);
- peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arsta->addr);
+ peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id,
+ arsta->addr);
if (peer)
peer->is_authorized = false;
- spin_unlock_bh(&ar->ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
/* Driver must clear the keys during the state change from
* IEEE80211_STA_AUTHORIZED to IEEE80211_STA_ASSOC, since after
@@ -6618,19 +6914,21 @@ static int ath12k_mac_station_authorize(struct ath12k *ar,
struct ath12k_link_vif *arvif,
struct ath12k_link_sta *arsta)
{
- struct ath12k_peer *peer;
+ struct ath12k_dp_link_peer *peer;
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
int ret;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ar->ab);
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- spin_lock_bh(&ar->ab->base_lock);
+ spin_lock_bh(&dp->dp_lock);
- peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arsta->addr);
+ peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id,
+ arsta->addr);
if (peer)
peer->is_authorized = true;
- spin_unlock_bh(&ar->ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
if (vif->type == NL80211_IFTYPE_STATION && arvif->is_up) {
ret = ath12k_wmi_set_peer_param(ar, arsta->addr,
@@ -6654,6 +6952,7 @@ static int ath12k_mac_station_remove(struct ath12k *ar,
struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct ath12k_vif *ahvif = arvif->ahvif;
int ret = 0;
+ struct ath12k_link_sta *temp_arsta;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
@@ -6682,6 +6981,15 @@ static int ath12k_mac_station_remove(struct ath12k *ar,
ath12k_mac_station_post_remove(ar, arvif, arsta);
+ spin_lock_bh(&ar->ab->base_lock);
+
+ /* To handle roaming and split phy scenario */
+ temp_arsta = ath12k_link_sta_find_by_addr(ar->ab, arsta->addr);
+ if (temp_arsta && temp_arsta->arvif->ar == ar)
+ ath12k_link_sta_rhash_delete(ar->ab, arsta);
+
+ spin_unlock_bh(&ar->ab->base_lock);
+
if (sta->valid_links)
ath12k_mac_free_unassign_link_sta(ahvif->ah,
arsta->ahsta, arsta->link_id);
@@ -6698,6 +7006,7 @@ static int ath12k_mac_station_add(struct ath12k *ar,
struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct ath12k_wmi_peer_create_arg peer_param = {};
int ret;
+ struct ath12k_link_sta *temp_arsta;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
@@ -6708,12 +7017,24 @@ static int ath12k_mac_station_add(struct ath12k *ar,
goto exit;
}
- if (ath12k_debugfs_is_extd_rx_stats_enabled(ar) && !arsta->rx_stats) {
- arsta->rx_stats = kzalloc(sizeof(*arsta->rx_stats), GFP_KERNEL);
- if (!arsta->rx_stats) {
- ret = -ENOMEM;
- goto dec_num_station;
- }
+ spin_lock_bh(&ab->base_lock);
+
+ /*
+ * In case of Split PHY and roaming scenario, pdev idx
+ * might differ but both the pdev will share same rhash
+ * table. In that case update the rhash table if link_sta is
+ * already present
+ */
+ temp_arsta = ath12k_link_sta_find_by_addr(ab, arsta->addr);
+ if (temp_arsta && temp_arsta->arvif->ar != ar)
+ ath12k_link_sta_rhash_delete(ab, temp_arsta);
+
+ ret = ath12k_link_sta_rhash_add(ab, arsta);
+ spin_unlock_bh(&ab->base_lock);
+ if (ret) {
+ ath12k_warn(ab, "Failed to add arsta: %pM to hash table, ret: %d",
+ arsta->addr, ret);
+ goto dec_num_station;
}
peer_param.vdev_id = arvif->vdev_id;
@@ -6759,13 +7080,13 @@ static int ath12k_mac_station_add(struct ath12k *ar,
}
}
- ewma_avg_rssi_init(&arsta->avg_rssi);
return 0;
free_peer:
ath12k_peer_delete(ar, arvif->vdev_id, arsta->addr);
- kfree(arsta->rx_stats);
- arsta->rx_stats = NULL;
+ spin_lock_bh(&ab->base_lock);
+ ath12k_link_sta_rhash_delete(ab, arsta);
+ spin_unlock_bh(&ab->base_lock);
dec_num_station:
ath12k_mac_dec_num_stations(arvif, arsta);
exit:
@@ -6842,10 +7163,17 @@ static void ath12k_mac_ml_station_remove(struct ath12k_vif *ahvif,
ath12k_mac_station_post_remove(ar, arvif, arsta);
+ spin_lock_bh(&ar->ab->base_lock);
+ ath12k_link_sta_rhash_delete(ar->ab, arsta);
+ spin_unlock_bh(&ar->ab->base_lock);
+
ath12k_mac_free_unassign_link_sta(ah, ahsta, link_id);
}
- ath12k_peer_ml_delete(ah, sta);
+ if (sta->mlo) {
+ clear_bit(ahsta->ml_peer_id, ah->free_ml_peer_id_map);
+ ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
+ }
}
static int ath12k_mac_handle_link_sta_state(struct ieee80211_hw *hw,
@@ -7268,11 +7596,11 @@ static int ath12k_mac_select_links(struct ath12k_base *ab,
return 0;
}
-static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- enum ieee80211_sta_state old_state,
- enum ieee80211_sta_state new_state)
+int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ 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);
@@ -7284,7 +7612,8 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
u16 selected_links = 0;
u8 link_id = 0, i;
struct ath12k *ar;
- int ret;
+ int ret = -EINVAL;
+ struct ath12k_dp_peer_create_params dp_params = {};
lockdep_assert_wiphy(hw->wiphy);
@@ -7307,12 +7636,28 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
/* ML sta */
if (sta->mlo && !ahsta->links_map &&
(hweight16(sta->valid_links) == 1)) {
- ret = ath12k_peer_ml_create(ah, sta);
- if (ret) {
- ath12k_hw_warn(ah, "unable to create ML peer for sta %pM",
+ ahsta->ml_peer_id = ath12k_peer_ml_alloc(ah);
+ if (ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID) {
+ ath12k_hw_warn(ah, "unable to allocate ML peer id for sta %pM",
sta->addr);
goto exit;
}
+
+ dp_params.is_mlo = true;
+ dp_params.peer_id = ahsta->ml_peer_id | ATH12K_PEER_ML_ID_VALID;
+ }
+
+ dp_params.sta = sta;
+
+ if (vif->type == NL80211_IFTYPE_AP)
+ dp_params.ucast_ra_only = true;
+
+ ret = ath12k_dp_peer_create(&ah->dp_hw, sta->addr, &dp_params);
+ if (ret) {
+ ath12k_hw_warn(ah, "unable to create ath12k_dp_peer for sta %pM, ret: %d",
+ sta->addr, ret);
+
+ goto ml_peer_id_clear;
}
ret = ath12k_mac_assign_link_sta(ah, ahsta, arsta, ahvif,
@@ -7320,7 +7665,7 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
if (ret) {
ath12k_hw_warn(ah, "unable assign link %d for sta %pM",
link_id, sta->addr);
- goto exit;
+ goto peer_delete;
}
/* above arsta will get memset, hence do this after assign
@@ -7390,7 +7735,12 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
if (ret) {
ath12k_hw_warn(ah, "unable to move link sta %d of sta %pM from state %d to %d",
link_id, arsta->addr, old_state, new_state);
- goto exit;
+
+ if (old_state == IEEE80211_STA_NOTEXIST &&
+ new_state == IEEE80211_STA_NONE)
+ goto peer_delete;
+ else
+ goto exit;
}
}
@@ -7418,11 +7768,23 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
* handler below
*/
if (old_state == IEEE80211_STA_NONE &&
- new_state == IEEE80211_STA_NOTEXIST && sta->mlo)
- ath12k_mac_ml_station_remove(ahvif, ahsta);
+ new_state == IEEE80211_STA_NOTEXIST) {
+ if (sta->mlo)
+ ath12k_mac_ml_station_remove(ahvif, ahsta);
+
+ ath12k_dp_peer_delete(&ah->dp_hw, sta->addr, sta);
+ }
ret = 0;
+ goto exit;
+peer_delete:
+ ath12k_dp_peer_delete(&ah->dp_hw, sta->addr, sta);
+ml_peer_id_clear:
+ if (sta->mlo) {
+ clear_bit(ahsta->ml_peer_id, ah->free_ml_peer_id_map);
+ ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
+ }
exit:
/* update the state if everything went well */
if (!ret)
@@ -7430,10 +7792,11 @@ exit:
return ret;
}
+EXPORT_SYMBOL(ath12k_mac_op_sta_state);
-static int ath12k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+int ath12k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
{
struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
struct ath12k *ar;
@@ -7480,11 +7843,12 @@ static int ath12k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw,
out:
return ret;
}
+EXPORT_SYMBOL(ath12k_mac_op_sta_set_txpwr);
-static void ath12k_mac_op_link_sta_rc_update(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_link_sta *link_sta,
- u32 changed)
+void ath12k_mac_op_link_sta_rc_update(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_link_sta *link_sta,
+ u32 changed)
{
struct ieee80211_sta *sta = link_sta->sta;
struct ath12k *ar;
@@ -7493,8 +7857,9 @@ static void ath12k_mac_op_link_sta_rc_update(struct ieee80211_hw *hw,
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k_link_sta *arsta;
struct ath12k_link_vif *arvif;
- struct ath12k_peer *peer;
+ struct ath12k_dp_link_peer *peer;
u32 bw, smps;
+ struct ath12k_dp *dp;
rcu_read_lock();
arvif = rcu_dereference(ahvif->link[link_sta->link_id]);
@@ -7506,6 +7871,7 @@ static void ath12k_mac_op_link_sta_rc_update(struct ieee80211_hw *hw,
}
ar = arvif->ar;
+ dp = ath12k_ab_to_dp(ar->ab);
arsta = rcu_dereference(ahsta->link[link_sta->link_id]);
if (!arsta) {
@@ -7514,18 +7880,19 @@ static void ath12k_mac_op_link_sta_rc_update(struct ieee80211_hw *hw,
link_sta->link_id, sta->addr);
return;
}
- spin_lock_bh(&ar->ab->base_lock);
+ spin_lock_bh(&dp->dp_lock);
- peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arsta->addr);
+ peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arvif->vdev_id,
+ arsta->addr);
if (!peer) {
- spin_unlock_bh(&ar->ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
rcu_read_unlock();
ath12k_warn(ar->ab, "mac sta rc update failed to find peer %pM on vdev %i\n",
arsta->addr, arvif->vdev_id);
return;
}
- spin_unlock_bh(&ar->ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
if (arsta->link_id >= IEEE80211_MLD_MAX_NUM_LINKS) {
rcu_read_unlock();
@@ -7588,6 +7955,7 @@ static void ath12k_mac_op_link_sta_rc_update(struct ieee80211_hw *hw,
rcu_read_unlock();
}
+EXPORT_SYMBOL(ath12k_mac_op_link_sta_rc_update);
static struct ath12k_link_sta *ath12k_mac_alloc_assign_link_sta(struct ath12k_hw *ah,
struct ath12k_sta *ahsta,
@@ -7619,10 +7987,10 @@ static struct ath12k_link_sta *ath12k_mac_alloc_assign_link_sta(struct ath12k_hw
return arsta;
}
-static int ath12k_mac_op_change_sta_links(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- u16 old_links, u16 new_links)
+int ath12k_mac_op_change_sta_links(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ u16 old_links, u16 new_links)
{
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
@@ -7683,15 +8051,17 @@ static int ath12k_mac_op_change_sta_links(struct ieee80211_hw *hw,
return 0;
}
+EXPORT_SYMBOL(ath12k_mac_op_change_sta_links);
-static bool ath12k_mac_op_can_activate_links(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- u16 active_links)
+bool ath12k_mac_op_can_activate_links(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ u16 active_links)
{
/* TODO: Handle recovery case */
return true;
}
+EXPORT_SYMBOL(ath12k_mac_op_can_activate_links);
static int ath12k_conf_tx_uapsd(struct ath12k_link_vif *arvif,
u16 ac, bool enable)
@@ -7803,10 +8173,10 @@ exit:
return ret;
}
-static int ath12k_mac_op_conf_tx(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- unsigned int link_id, u16 ac,
- const struct ieee80211_tx_queue_params *params)
+int ath12k_mac_op_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ unsigned int link_id, u16 ac,
+ const struct ieee80211_tx_queue_params *params)
{
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_link_vif *arvif;
@@ -7835,6 +8205,7 @@ static int ath12k_mac_op_conf_tx(struct ieee80211_hw *hw,
return ret;
}
+EXPORT_SYMBOL(ath12k_mac_op_conf_tx);
static struct ieee80211_sta_ht_cap
ath12k_create_ht_cap(struct ath12k *ar, u32 ar_ht_cap, u32 rate_cap_rx_chainmask)
@@ -8686,7 +9057,7 @@ static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_link_vif *arv
ieee80211_is_disassoc(hdr->frame_control)) &&
ieee80211_has_protected(hdr->frame_control)) {
enctype = ath12k_dp_tx_get_encrypt_type(skb_cb->cipher);
- mic_len = ath12k_dp_rx_crypto_mic_len(ar, enctype);
+ mic_len = ath12k_dp_rx_crypto_mic_len(ab->dp, enctype);
skb_put(skb, mic_len);
}
}
@@ -8957,8 +9328,8 @@ static void ath12k_mgmt_over_wmi_tx_work(struct wiphy *wiphy, struct wiphy_work
}
}
-static int ath12k_mac_mgmt_tx(struct ath12k *ar, struct sk_buff *skb,
- bool is_prb_rsp)
+int ath12k_mac_mgmt_tx(struct ath12k *ar, struct sk_buff *skb,
+ bool is_prb_rsp)
{
struct sk_buff_head *q = &ar->wmi_mgmt_tx_queue;
@@ -8988,11 +9359,12 @@ static int ath12k_mac_mgmt_tx(struct ath12k *ar, struct sk_buff *skb,
return 0;
}
+EXPORT_SYMBOL(ath12k_mac_mgmt_tx);
-static void ath12k_mac_add_p2p_noa_ie(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct sk_buff *skb,
- bool is_prb_rsp)
+void ath12k_mac_add_p2p_noa_ie(struct ath12k *ar,
+ struct ieee80211_vif *vif,
+ struct sk_buff *skb,
+ bool is_prb_rsp)
{
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
@@ -9009,11 +9381,12 @@ static void ath12k_mac_add_p2p_noa_ie(struct ath12k *ar,
spin_unlock_bh(&ar->data_lock);
}
+EXPORT_SYMBOL(ath12k_mac_add_p2p_noa_ie);
/* Note: called under rcu_read_lock() */
-static void ath12k_mlo_mcast_update_tx_link_address(struct ieee80211_vif *vif,
- u8 link_id, struct sk_buff *skb,
- u32 info_flags)
+void ath12k_mlo_mcast_update_tx_link_address(struct ieee80211_vif *vif,
+ u8 link_id, struct sk_buff *skb,
+ u32 info_flags)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_bss_conf *bss_conf;
@@ -9025,10 +9398,11 @@ static void ath12k_mlo_mcast_update_tx_link_address(struct ieee80211_vif *vif,
if (bss_conf)
ether_addr_copy(hdr->addr2, bss_conf->addr);
}
+EXPORT_SYMBOL(ath12k_mlo_mcast_update_tx_link_address);
/* Note: called under rcu_read_lock() */
-static u8 ath12k_mac_get_tx_link(struct ieee80211_sta *sta, struct ieee80211_vif *vif,
- u8 link, struct sk_buff *skb, u32 info_flags)
+u8 ath12k_mac_get_tx_link(struct ieee80211_sta *sta, struct ieee80211_vif *vif,
+ u8 link, struct sk_buff *skb, u32 info_flags)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
@@ -9123,193 +9497,7 @@ static u8 ath12k_mac_get_tx_link(struct ieee80211_sta *sta, struct ieee80211_vif
return link;
}
-
-/* Note: called under rcu_read_lock() */
-static void ath12k_mac_op_tx(struct ieee80211_hw *hw,
- struct ieee80211_tx_control *control,
- struct sk_buff *skb)
-{
- 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 *ahvif = ath12k_vif_to_ahvif(vif);
- struct ath12k_link_vif *arvif = &ahvif->deflink;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct ieee80211_key_conf *key = info->control.hw_key;
- struct ieee80211_sta *sta = control->sta;
- struct ath12k_link_vif *tmp_arvif;
- u32 info_flags = info->flags;
- struct sk_buff *msdu_copied;
- struct ath12k *ar, *tmp_ar;
- struct ath12k_peer *peer;
- unsigned long links_map;
- bool is_mcast = false;
- bool is_dvlan = false;
- struct ethhdr *eth;
- bool is_prb_rsp;
- u16 mcbc_gsn;
- u8 link_id;
- int ret;
-
- if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
- ieee80211_free_txskb(hw, skb);
- return;
- }
-
- link_id = u32_get_bits(info->control.flags, IEEE80211_TX_CTRL_MLO_LINK);
- memset(skb_cb, 0, sizeof(*skb_cb));
- skb_cb->vif = vif;
-
- if (key) {
- skb_cb->cipher = key->cipher;
- skb_cb->flags |= ATH12K_SKB_CIPHER_SET;
- }
-
- /* handle only for MLO case, use deflink for non MLO case */
- if (ieee80211_vif_is_mld(vif)) {
- link_id = ath12k_mac_get_tx_link(sta, vif, link_id, skb, info_flags);
- if (link_id >= IEEE80211_MLD_MAX_NUM_LINKS) {
- ieee80211_free_txskb(hw, skb);
- return;
- }
- } else {
- if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
- link_id = ATH12K_FIRST_SCAN_LINK;
- else
- link_id = 0;
- }
-
- arvif = rcu_dereference(ahvif->link[link_id]);
- if (!arvif || !arvif->ar) {
- ath12k_warn(ahvif->ah, "failed to find arvif link id %u for frame transmission",
- link_id);
- ieee80211_free_txskb(hw, skb);
- return;
- }
-
- ar = arvif->ar;
- skb_cb->link_id = link_id;
- is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control);
-
- if (info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
- eth = (struct ethhdr *)skb->data;
- is_mcast = is_multicast_ether_addr(eth->h_dest);
-
- skb_cb->flags |= ATH12K_SKB_HW_80211_ENCAP;
- } else if (ieee80211_is_mgmt(hdr->frame_control)) {
- if (sta && sta->mlo)
- skb_cb->flags |= ATH12K_SKB_MLO_STA;
-
- ret = ath12k_mac_mgmt_tx(ar, skb, is_prb_rsp);
- if (ret) {
- ath12k_warn(ar->ab, "failed to queue management frame %d\n",
- ret);
- ieee80211_free_txskb(hw, skb);
- }
- return;
- }
-
- if (!(info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP))
- is_mcast = is_multicast_ether_addr(hdr->addr1);
-
- /* This is case only for P2P_GO */
- if (vif->type == NL80211_IFTYPE_AP && vif->p2p)
- ath12k_mac_add_p2p_noa_ie(ar, vif, skb, is_prb_rsp);
-
- /* Checking if it is a DVLAN frame */
- if (!test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags) &&
- !(skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP) &&
- !(skb_cb->flags & ATH12K_SKB_CIPHER_SET) &&
- ieee80211_has_protected(hdr->frame_control))
- is_dvlan = true;
-
- if (!vif->valid_links || !is_mcast || is_dvlan ||
- (skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP) ||
- test_bit(ATH12K_FLAG_RAW_MODE, &ar->ab->dev_flags)) {
- ret = ath12k_dp_tx(ar, arvif, skb, false, 0, is_mcast);
- if (unlikely(ret)) {
- ath12k_warn(ar->ab, "failed to transmit frame %d\n", ret);
- ieee80211_free_txskb(ar->ah->hw, skb);
- return;
- }
- } else {
- mcbc_gsn = atomic_inc_return(&ahvif->mcbc_gsn) & 0xfff;
-
- links_map = ahvif->links_map;
- for_each_set_bit(link_id, &links_map,
- IEEE80211_MLD_MAX_NUM_LINKS) {
- tmp_arvif = rcu_dereference(ahvif->link[link_id]);
- if (!tmp_arvif || !tmp_arvif->is_up)
- continue;
-
- tmp_ar = tmp_arvif->ar;
- msdu_copied = skb_copy(skb, GFP_ATOMIC);
- if (!msdu_copied) {
- ath12k_err(ar->ab,
- "skb copy failure link_id 0x%X vdevid 0x%X\n",
- link_id, tmp_arvif->vdev_id);
- continue;
- }
-
- ath12k_mlo_mcast_update_tx_link_address(vif, link_id,
- msdu_copied,
- info_flags);
-
- skb_cb = ATH12K_SKB_CB(msdu_copied);
- skb_cb->link_id = link_id;
-
- /* For open mode, skip peer find logic */
- if (unlikely(!ahvif->key_cipher))
- goto skip_peer_find;
-
- spin_lock_bh(&tmp_ar->ab->base_lock);
- peer = ath12k_peer_find_by_addr(tmp_ar->ab, tmp_arvif->bssid);
- if (!peer) {
- spin_unlock_bh(&tmp_ar->ab->base_lock);
- ath12k_warn(tmp_ar->ab,
- "failed to find peer for vdev_id 0x%X addr %pM link_map 0x%X\n",
- tmp_arvif->vdev_id, tmp_arvif->bssid,
- ahvif->links_map);
- dev_kfree_skb_any(msdu_copied);
- continue;
- }
-
- key = peer->keys[peer->mcast_keyidx];
- if (key) {
- skb_cb->cipher = key->cipher;
- skb_cb->flags |= ATH12K_SKB_CIPHER_SET;
-
- hdr = (struct ieee80211_hdr *)msdu_copied->data;
- if (!ieee80211_has_protected(hdr->frame_control))
- hdr->frame_control |=
- cpu_to_le16(IEEE80211_FCTL_PROTECTED);
- }
- spin_unlock_bh(&tmp_ar->ab->base_lock);
-
-skip_peer_find:
- ret = ath12k_dp_tx(tmp_ar, tmp_arvif,
- msdu_copied, true, mcbc_gsn, is_mcast);
- if (unlikely(ret)) {
- if (ret == -ENOMEM) {
- /* Drops are expected during heavy multicast
- * frame flood. Print with debug log
- * level to avoid lot of console prints
- */
- ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
- "failed to transmit frame %d\n",
- ret);
- } else {
- ath12k_warn(ar->ab,
- "failed to transmit frame %d\n",
- ret);
- }
-
- dev_kfree_skb_any(msdu_copied);
- }
- }
- ieee80211_free_txskb(ar->ah->hw, skb);
- }
-}
+EXPORT_SYMBOL(ath12k_mac_get_tx_link);
void ath12k_mac_drain_tx(struct ath12k *ar)
{
@@ -9484,7 +9672,7 @@ static void ath12k_drain_tx(struct ath12k_hw *ah)
ath12k_mac_drain_tx(ar);
}
-static int ath12k_mac_op_start(struct ieee80211_hw *hw)
+int ath12k_mac_op_start(struct ieee80211_hw *hw)
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
@@ -9537,6 +9725,7 @@ fail_start:
return ret;
}
+EXPORT_SYMBOL(ath12k_mac_op_start);
int ath12k_mac_rfkill_config(struct ath12k *ar)
{
@@ -9597,6 +9786,7 @@ int ath12k_mac_rfkill_enable_radio(struct ath12k *ar, bool enable)
static void ath12k_mac_stop(struct ath12k *ar)
{
+ struct ath12k_pdev_dp *dp_pdev = &ar->dp;
struct ath12k_hw *ah = ar->ah;
struct htt_ppdu_stats_info *ppdu_stats, *tmp;
struct ath12k_wmi_scan_chan_list_arg *arg;
@@ -9621,13 +9811,14 @@ static void ath12k_mac_stop(struct ath12k *ar)
ar->state_11d = ATH12K_11D_IDLE;
complete(&ar->completed_11d_scan);
- spin_lock_bh(&ar->data_lock);
-
- list_for_each_entry_safe(ppdu_stats, tmp, &ar->ppdu_stats_info, list) {
+ spin_lock_bh(&dp_pdev->ppdu_list_lock);
+ list_for_each_entry_safe(ppdu_stats, tmp, &dp_pdev->ppdu_stats_info, list) {
list_del(&ppdu_stats->list);
kfree(ppdu_stats);
}
+ spin_unlock_bh(&dp_pdev->ppdu_list_lock);
+ spin_lock_bh(&ar->data_lock);
while ((arg = list_first_entry_or_null(&ar->regd_channel_update_queue,
struct ath12k_wmi_scan_chan_list_arg,
list))) {
@@ -9643,7 +9834,7 @@ static void ath12k_mac_stop(struct ath12k *ar)
atomic_set(&ar->num_pending_mgmt_tx, 0);
}
-static void ath12k_mac_op_stop(struct ieee80211_hw *hw, bool suspend)
+void ath12k_mac_op_stop(struct ieee80211_hw *hw, bool suspend)
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
@@ -9662,6 +9853,7 @@ static void ath12k_mac_op_stop(struct ieee80211_hw *hw, bool suspend)
mutex_unlock(&ah->hw_mutex);
}
+EXPORT_SYMBOL(ath12k_mac_op_stop);
static u8
ath12k_mac_get_vdev_stats_id(struct ath12k_link_vif *arvif)
@@ -9795,14 +9987,14 @@ static void ath12k_mac_update_vif_offload(struct ath12k_link_vif *arvif)
IEEE80211_OFFLOAD_DECAP_ENABLED);
if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED)
- ahvif->tx_encap_type = ATH12K_HW_TXRX_ETHERNET;
+ ahvif->dp_vif.tx_encap_type = ATH12K_HW_TXRX_ETHERNET;
else if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags))
- ahvif->tx_encap_type = ATH12K_HW_TXRX_RAW;
+ ahvif->dp_vif.tx_encap_type = ATH12K_HW_TXRX_RAW;
else
- ahvif->tx_encap_type = ATH12K_HW_TXRX_NATIVE_WIFI;
+ ahvif->dp_vif.tx_encap_type = ATH12K_HW_TXRX_NATIVE_WIFI;
ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
- param_id, ahvif->tx_encap_type);
+ param_id, ahvif->dp_vif.tx_encap_type);
if (ret) {
ath12k_warn(ab, "failed to set vdev %d tx encap mode: %d\n",
arvif->vdev_id, ret);
@@ -9826,8 +10018,8 @@ static void ath12k_mac_update_vif_offload(struct ath12k_link_vif *arvif)
}
}
-static void ath12k_mac_op_update_vif_offload(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+void ath12k_mac_op_update_vif_offload(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_link_vif *arvif;
@@ -9851,6 +10043,7 @@ static void ath12k_mac_op_update_vif_offload(struct ieee80211_hw *hw,
ath12k_mac_update_vif_offload(&ahvif->deflink);
}
+EXPORT_SYMBOL(ath12k_mac_op_update_vif_offload);
static bool ath12k_mac_vif_ap_active_any(struct ath12k_base *ab)
{
@@ -10016,6 +10209,9 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
int i;
int ret, vdev_id;
u8 link_id;
+ struct ath12k_dp_link_vif *dp_link_vif = NULL;
+ struct ath12k_dp_peer_create_params params = {};
+ bool dp_peer_created = false;
lockdep_assert_wiphy(hw->wiphy);
@@ -10097,8 +10293,26 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
goto err_vdev_del;
}
+ dp_link_vif = ath12k_dp_vif_to_dp_link_vif(&ahvif->dp_vif, arvif->link_id);
+
+ dp_link_vif->vdev_id = arvif->vdev_id;
+ dp_link_vif->lmac_id = ar->lmac_id;
+ dp_link_vif->pdev_idx = ar->pdev_idx;
+
switch (ahvif->vdev_type) {
case WMI_VDEV_TYPE_AP:
+ params.ucast_ra_only = true;
+
+ if (arvif->link_id < IEEE80211_MLD_MAX_NUM_LINKS) {
+ ret = ath12k_dp_peer_create(&ah->dp_hw, arvif->bssid, &params);
+ if (ret) {
+ ath12k_warn(ab, "failed to vdev %d create dp_peer for AP: %d\n",
+ arvif->vdev_id, ret);
+ goto err_vdev_del;
+ }
+ dp_peer_created = true;
+ }
+
peer_param.vdev_id = arvif->vdev_id;
peer_param.peer_addr = arvif->bssid;
peer_param.peer_type = WMI_PEER_TYPE_DEFAULT;
@@ -10106,7 +10320,7 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
if (ret) {
ath12k_warn(ab, "failed to vdev %d create peer for AP: %d\n",
arvif->vdev_id, ret);
- goto err_vdev_del;
+ goto err_dp_peer_del;
}
ret = ath12k_mac_set_kickout(arvif);
@@ -10212,6 +10426,10 @@ err_peer_del:
ar->num_peers--;
}
+err_dp_peer_del:
+ if (dp_peer_created)
+ ath12k_dp_peer_delete(&ah->dp_hw, arvif->bssid, NULL);
+
err_vdev_del:
if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
ar->monitor_vdev_id = -1;
@@ -10406,8 +10624,8 @@ unlock:
return arvif->ar;
}
-static int ath12k_mac_op_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+int ath12k_mac_op_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
@@ -10454,6 +10672,7 @@ static int ath12k_mac_op_add_interface(struct ieee80211_hw *hw,
*/
return 0;
}
+EXPORT_SYMBOL(ath12k_mac_op_add_interface);
static void ath12k_mac_vif_unref(struct ath12k_dp *dp, struct ieee80211_vif *vif)
{
@@ -10484,6 +10703,7 @@ static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ath12k_link_vif *arv
{
struct ath12k_vif *ahvif = arvif->ahvif;
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
+ struct ath12k_dp_link_vif *dp_link_vif;
struct ath12k_base *ab = ar->ab;
unsigned long time_left;
int ret;
@@ -10529,8 +10749,10 @@ err_vdev_del:
idr_for_each(&ar->txmgmt_idr,
ath12k_mac_vif_txmgmt_idr_remove, vif);
- ath12k_mac_vif_unref(&ab->dp, vif);
- ath12k_dp_tx_put_bank_profile(&ab->dp, arvif->bank_id);
+ ath12k_mac_vif_unref(ath12k_ab_to_dp(ab), vif);
+
+ dp_link_vif = ath12k_dp_vif_to_dp_link_vif(&ahvif->dp_vif, arvif->link_id);
+ ath12k_dp_tx_put_bank_profile(ath12k_ab_to_dp(ab), dp_link_vif->bank_id);
/* Recalc txpower for remaining vdev */
ath12k_mac_txpower_recalc(ar);
@@ -10542,8 +10764,8 @@ err_vdev_del:
return ret;
}
-static void ath12k_mac_op_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+void ath12k_mac_op_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_link_vif *arvif;
@@ -10590,6 +10812,7 @@ static void ath12k_mac_op_remove_interface(struct ieee80211_hw *hw,
ath12k_mac_unassign_link_vif(arvif);
}
}
+EXPORT_SYMBOL(ath12k_mac_op_remove_interface);
/* FIXME: Has to be verified. */
#define SUPPORTED_FILTERS \
@@ -10601,10 +10824,10 @@ static void ath12k_mac_op_remove_interface(struct ieee80211_hw *hw,
FIF_PROBE_REQ | \
FIF_FCSFAIL)
-static void ath12k_mac_op_configure_filter(struct ieee80211_hw *hw,
- unsigned int changed_flags,
- unsigned int *total_flags,
- u64 multicast)
+void ath12k_mac_op_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed_flags,
+ unsigned int *total_flags,
+ u64 multicast)
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
@@ -10616,9 +10839,10 @@ static void ath12k_mac_op_configure_filter(struct ieee80211_hw *hw,
*total_flags &= SUPPORTED_FILTERS;
ar->filter_flags = *total_flags;
}
+EXPORT_SYMBOL(ath12k_mac_op_configure_filter);
-static int ath12k_mac_op_get_antenna(struct ieee80211_hw *hw, int radio_idx,
- u32 *tx_ant, u32 *rx_ant)
+int ath12k_mac_op_get_antenna(struct ieee80211_hw *hw, int radio_idx,
+ u32 *tx_ant, u32 *rx_ant)
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
int antennas_rx = 0, antennas_tx = 0;
@@ -10637,9 +10861,10 @@ static int ath12k_mac_op_get_antenna(struct ieee80211_hw *hw, int radio_idx,
return 0;
}
+EXPORT_SYMBOL(ath12k_mac_op_get_antenna);
-static int ath12k_mac_op_set_antenna(struct ieee80211_hw *hw, int radio_idx,
- u32 tx_ant, u32 rx_ant)
+int ath12k_mac_op_set_antenna(struct ieee80211_hw *hw, int radio_idx,
+ u32 tx_ant, u32 rx_ant)
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
@@ -10656,6 +10881,7 @@ static int ath12k_mac_op_set_antenna(struct ieee80211_hw *hw, int radio_idx,
return ret;
}
+EXPORT_SYMBOL(ath12k_mac_op_set_antenna);
static int ath12k_mac_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -10697,9 +10923,9 @@ static int ath12k_mac_ampdu_action(struct ieee80211_hw *hw,
return ret;
}
-static int ath12k_mac_op_ampdu_action(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_ampdu_params *params)
+int ath12k_mac_op_ampdu_action(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_ampdu_params *params)
{
struct ieee80211_sta *sta = params->sta;
struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
@@ -10720,9 +10946,10 @@ static int ath12k_mac_op_ampdu_action(struct ieee80211_hw *hw,
return 0;
}
+EXPORT_SYMBOL(ath12k_mac_op_ampdu_action);
-static int ath12k_mac_op_add_chanctx(struct ieee80211_hw *hw,
- struct ieee80211_chanctx_conf *ctx)
+int ath12k_mac_op_add_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *ctx)
{
struct ath12k *ar;
struct ath12k_base *ab;
@@ -10749,9 +10976,10 @@ static int ath12k_mac_op_add_chanctx(struct ieee80211_hw *hw,
return 0;
}
+EXPORT_SYMBOL(ath12k_mac_op_add_chanctx);
-static void ath12k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
- struct ieee80211_chanctx_conf *ctx)
+void ath12k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *ctx)
{
struct ath12k *ar;
struct ath12k_base *ab;
@@ -10776,6 +11004,7 @@ static void ath12k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
spin_unlock_bh(&ar->data_lock);
ar->chan_tx_pwr = ATH12K_PDEV_TX_POWER_INVALID;
}
+EXPORT_SYMBOL(ath12k_mac_op_remove_chanctx);
static enum wmi_phy_mode
ath12k_mac_check_down_grade_phy_mode(struct ath12k *ar,
@@ -11334,9 +11563,9 @@ ath12k_mac_update_active_vif_chan(struct ath12k *ar,
kfree(arg.vifs);
}
-static void ath12k_mac_op_change_chanctx(struct ieee80211_hw *hw,
- struct ieee80211_chanctx_conf *ctx,
- u32 changed)
+void ath12k_mac_op_change_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *ctx,
+ u32 changed)
{
struct ath12k *ar;
struct ath12k_base *ab;
@@ -11366,6 +11595,7 @@ static void ath12k_mac_op_change_chanctx(struct ieee80211_hw *hw,
/* TODO: Recalc radar detection */
}
+EXPORT_SYMBOL(ath12k_mac_op_change_chanctx);
static int ath12k_start_vdev_delay(struct ath12k *ar,
struct ath12k_link_vif *arvif)
@@ -11807,7 +12037,7 @@ static void ath12k_mac_parse_tx_pwr_env(struct ath12k *ar,
}
}
-static int
+int
ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
@@ -11856,7 +12086,7 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
if (ab->hw_params->vdev_start_delay &&
ahvif->vdev_type != WMI_VDEV_TYPE_AP &&
ahvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
- !ath12k_peer_exist_by_vdev_id(ab, arvif->vdev_id)) {
+ !ath12k_dp_link_peer_exist_by_vdev_id(ath12k_ab_to_dp(ab), arvif->vdev_id)) {
ret = 0;
goto out;
}
@@ -11892,8 +12122,9 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
out:
return ret;
}
+EXPORT_SYMBOL(ath12k_mac_op_assign_vif_chanctx);
-static void
+void
ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
@@ -11960,8 +12191,9 @@ ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
ar->scan.arvif = NULL;
}
}
+EXPORT_SYMBOL(ath12k_mac_op_unassign_vif_chanctx);
-static int
+int
ath12k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_vif_chanctx_switch *vifs,
int n_vifs,
@@ -11986,6 +12218,7 @@ ath12k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
return 0;
}
+EXPORT_SYMBOL(ath12k_mac_op_switch_vif_chanctx);
static int
ath12k_set_vdev_param_to_all_vifs(struct ath12k *ar, int param, u32 value)
@@ -12014,8 +12247,8 @@ ath12k_set_vdev_param_to_all_vifs(struct ath12k *ar, int param, u32 value)
/* mac80211 stores device specific RTS/Fragmentation threshold value,
* this is set interface specific to firmware from ath12k driver
*/
-static int ath12k_mac_op_set_rts_threshold(struct ieee80211_hw *hw,
- int radio_idx, u32 value)
+int ath12k_mac_op_set_rts_threshold(struct ieee80211_hw *hw,
+ int radio_idx, u32 value)
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct wiphy *wiphy = hw->wiphy;
@@ -12074,9 +12307,10 @@ static int ath12k_mac_op_set_rts_threshold(struct ieee80211_hw *hw,
return ret;
}
+EXPORT_SYMBOL(ath12k_mac_op_set_rts_threshold);
-static int ath12k_mac_op_set_frag_threshold(struct ieee80211_hw *hw,
- int radio_idx, u32 value)
+int ath12k_mac_op_set_frag_threshold(struct ieee80211_hw *hw,
+ int radio_idx, u32 value)
{
/* Even though there's a WMI vdev param for fragmentation threshold no
* known firmware actually implements it. Moreover it is not possible to
@@ -12093,6 +12327,7 @@ static int ath12k_mac_op_set_frag_threshold(struct ieee80211_hw *hw,
return -EOPNOTSUPP;
}
+EXPORT_SYMBOL(ath12k_mac_op_set_frag_threshold);
static int ath12k_mac_flush(struct ath12k *ar)
{
@@ -12130,8 +12365,8 @@ int ath12k_mac_wait_tx_complete(struct ath12k *ar)
return ath12k_mac_flush(ar);
}
-static void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- u32 queues, bool drop)
+void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ u32 queues, bool drop)
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k_link_vif *arvif;
@@ -12166,6 +12401,7 @@ static void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *v
ath12k_mac_flush(arvif->ar);
}
}
+EXPORT_SYMBOL(ath12k_mac_op_flush);
static int
ath12k_mac_bitrate_mask_num_ht_rates(struct ath12k *ar,
@@ -12729,9 +12965,11 @@ ath12k_mac_validate_fixed_rate_settings(struct ath12k *ar, enum nl80211_band ban
bool eht_fixed_rate = false, he_fixed_rate = false, vht_fixed_rate = false;
const u16 *vht_mcs_mask, *he_mcs_mask, *eht_mcs_mask;
struct ieee80211_link_sta *link_sta;
- struct ath12k_peer *peer, *tmp;
+ struct ath12k_dp_link_peer *peer, *tmp;
u8 vht_nss, he_nss, eht_nss;
int ret = true;
+ struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
vht_mcs_mask = mask->control[band].vht_mcs;
he_mcs_mask = mask->control[band].he_mcs;
@@ -12754,8 +12992,8 @@ ath12k_mac_validate_fixed_rate_settings(struct ath12k *ar, enum nl80211_band ban
eht_nss = ath12k_mac_max_eht_nss(eht_mcs_mask);
rcu_read_lock();
- spin_lock_bh(&ar->ab->base_lock);
- list_for_each_entry_safe(peer, tmp, &ar->ab->peers, list) {
+ spin_lock_bh(&dp->dp_lock);
+ list_for_each_entry_safe(peer, tmp, &dp->peers, list) {
if (peer->sta) {
link_sta = rcu_dereference(peer->sta->link[link_id]);
if (!link_sta) {
@@ -12781,12 +13019,12 @@ ath12k_mac_validate_fixed_rate_settings(struct ath12k *ar, enum nl80211_band ban
}
}
exit:
- spin_unlock_bh(&ar->ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
rcu_read_unlock();
return ret;
}
-static int
+int
ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
const struct cfg80211_bitrate_mask *mask)
@@ -12965,8 +13203,9 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
out:
return ret;
}
+EXPORT_SYMBOL(ath12k_mac_op_set_bitrate_mask);
-static void
+void
ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
enum ieee80211_reconfig_type reconfig_type)
{
@@ -13027,7 +13266,7 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
ahvif = arvif->ahvif;
ath12k_dbg(ab, ATH12K_DBG_BOOT,
"reconfig cipher %d up %d vdev type %d\n",
- ahvif->key_cipher,
+ ahvif->dp_vif.key_cipher,
arvif->is_up,
ahvif->vdev_type);
@@ -13047,6 +13286,7 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
}
}
}
+EXPORT_SYMBOL(ath12k_mac_op_reconfig_complete);
static void
ath12k_mac_update_bss_chan_survey(struct ath12k *ar,
@@ -13080,8 +13320,8 @@ ath12k_mac_update_bss_chan_survey(struct ath12k *ar,
ath12k_warn(ar->ab, "bss channel survey timed out\n");
}
-static int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx,
- struct survey_info *survey)
+int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx,
+ struct survey_info *survey)
{
struct ath12k *ar;
struct ieee80211_supported_band *sband;
@@ -13135,6 +13375,7 @@ static int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx,
return 0;
}
+EXPORT_SYMBOL(ath12k_mac_op_get_survey);
static void ath12k_mac_put_chain_rssi(struct station_info *sinfo,
struct ath12k_link_sta *arsta)
@@ -13157,15 +13398,18 @@ static void ath12k_mac_put_chain_rssi(struct station_info *sinfo,
}
}
-static void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct station_info *sinfo)
+void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct station_info *sinfo)
{
struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
+ struct ath12k_dp_link_peer_rate_info rate_info = {};
struct ath12k_fw_stats_req_params params = {};
+ struct ath12k_dp_link_peer *peer;
struct ath12k_link_sta *arsta;
s8 signal, noise_floor;
+ struct ath12k_dp *dp;
struct ath12k *ar;
bool db2dbm;
@@ -13176,34 +13420,37 @@ static void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw,
if (!ar)
return;
+ dp = ath12k_ab_to_dp(ar->ab);
+ ath12k_dp_link_peer_get_sta_rate_info_stats(dp, arsta->addr, &rate_info);
+
db2dbm = test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,
ar->ab->wmi_ab.svc_map);
- sinfo->rx_duration = arsta->rx_duration;
+ sinfo->rx_duration = rate_info.rx_duration;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
- sinfo->tx_duration = arsta->tx_duration;
+ sinfo->tx_duration = rate_info.tx_duration;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_DURATION);
- if (arsta->txrate.legacy || arsta->txrate.nss) {
- if (arsta->txrate.legacy) {
- sinfo->txrate.legacy = arsta->txrate.legacy;
+ if (rate_info.txrate.legacy || rate_info.txrate.nss) {
+ if (rate_info.txrate.legacy) {
+ sinfo->txrate.legacy = rate_info.txrate.legacy;
} else {
- sinfo->txrate.mcs = arsta->txrate.mcs;
- sinfo->txrate.nss = arsta->txrate.nss;
- sinfo->txrate.bw = arsta->txrate.bw;
- sinfo->txrate.he_gi = arsta->txrate.he_gi;
- sinfo->txrate.he_dcm = arsta->txrate.he_dcm;
- sinfo->txrate.he_ru_alloc = arsta->txrate.he_ru_alloc;
- sinfo->txrate.eht_gi = arsta->txrate.eht_gi;
- sinfo->txrate.eht_ru_alloc = arsta->txrate.eht_ru_alloc;
- }
- sinfo->txrate.flags = arsta->txrate.flags;
+ sinfo->txrate.mcs = rate_info.txrate.mcs;
+ sinfo->txrate.nss = rate_info.txrate.nss;
+ sinfo->txrate.bw = rate_info.txrate.bw;
+ sinfo->txrate.he_gi = rate_info.txrate.he_gi;
+ sinfo->txrate.he_dcm = rate_info.txrate.he_dcm;
+ sinfo->txrate.he_ru_alloc = rate_info.txrate.he_ru_alloc;
+ sinfo->txrate.eht_gi = rate_info.txrate.eht_gi;
+ sinfo->txrate.eht_ru_alloc = rate_info.txrate.eht_ru_alloc;
+ }
+ sinfo->txrate.flags = rate_info.txrate.flags;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
}
/* TODO: Use real NF instead of default one. */
- signal = arsta->rssi_comb;
+ signal = rate_info.rssi_comb;
params.pdev_id = ar->pdev->pdev_id;
params.vdev_id = 0;
@@ -13233,26 +13480,37 @@ static void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw,
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
}
- sinfo->signal_avg = ewma_avg_rssi_read(&arsta->avg_rssi);
+ sinfo->signal_avg = rate_info.signal_avg;
if (!db2dbm)
sinfo->signal_avg += noise_floor;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
- sinfo->tx_retries = arsta->tx_retry_count;
- sinfo->tx_failed = arsta->tx_retry_failed;
+ spin_lock_bh(&dp->dp_lock);
+ peer = ath12k_dp_link_peer_find_by_addr(dp, arsta->addr);
+ if (!peer) {
+ spin_unlock_bh(&dp->dp_lock);
+ return;
+ }
+
+ sinfo->tx_retries = peer->tx_retry_count;
+ sinfo->tx_failed = peer->tx_retry_failed;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
+
+ spin_unlock_bh(&dp->dp_lock);
}
+EXPORT_SYMBOL(ath12k_mac_op_sta_statistics);
-static void ath12k_mac_op_link_sta_statistics(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_link_sta *link_sta,
- struct link_station_info *link_sinfo)
+void ath12k_mac_op_link_sta_statistics(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_link_sta *link_sta,
+ struct link_station_info *link_sinfo)
{
struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(link_sta->sta);
struct ath12k_fw_stats_req_params params = {};
+ struct ath12k_dp_link_peer *peer;
struct ath12k_link_sta *arsta;
struct ath12k *ar;
s8 signal;
@@ -13272,43 +13530,64 @@ static void ath12k_mac_op_link_sta_statistics(struct ieee80211_hw *hw,
db2dbm = test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,
ar->ab->wmi_ab.svc_map);
- link_sinfo->rx_duration = arsta->rx_duration;
+ spin_lock_bh(&ar->ab->dp->dp_lock);
+ peer = ath12k_dp_link_peer_find_by_addr(ar->ab->dp, arsta->addr);
+ if (!peer) {
+ spin_unlock_bh(&ar->ab->dp->dp_lock);
+ return;
+ }
+
+ link_sinfo->rx_duration = peer->rx_duration;
link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
- link_sinfo->tx_duration = arsta->tx_duration;
+ link_sinfo->tx_duration = peer->tx_duration;
link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_DURATION);
- if (arsta->txrate.legacy || arsta->txrate.nss) {
- if (arsta->txrate.legacy) {
- link_sinfo->txrate.legacy = arsta->txrate.legacy;
+ if (peer->txrate.legacy || peer->txrate.nss) {
+ if (peer->txrate.legacy) {
+ link_sinfo->txrate.legacy = peer->txrate.legacy;
} else {
- link_sinfo->txrate.mcs = arsta->txrate.mcs;
- link_sinfo->txrate.nss = arsta->txrate.nss;
- link_sinfo->txrate.bw = arsta->txrate.bw;
- link_sinfo->txrate.he_gi = arsta->txrate.he_gi;
- link_sinfo->txrate.he_dcm = arsta->txrate.he_dcm;
+ link_sinfo->txrate.mcs = peer->txrate.mcs;
+ link_sinfo->txrate.nss = peer->txrate.nss;
+ link_sinfo->txrate.bw = peer->txrate.bw;
+ link_sinfo->txrate.he_gi = peer->txrate.he_gi;
+ link_sinfo->txrate.he_dcm = peer->txrate.he_dcm;
link_sinfo->txrate.he_ru_alloc =
- arsta->txrate.he_ru_alloc;
- link_sinfo->txrate.eht_gi = arsta->txrate.eht_gi;
+ peer->txrate.he_ru_alloc;
+ link_sinfo->txrate.eht_gi = peer->txrate.eht_gi;
link_sinfo->txrate.eht_ru_alloc =
- arsta->txrate.eht_ru_alloc;
+ peer->txrate.eht_ru_alloc;
}
- link_sinfo->txrate.flags = arsta->txrate.flags;
+ link_sinfo->txrate.flags = peer->txrate.flags;
link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
}
+ link_sinfo->signal_avg = ewma_avg_rssi_read(&peer->avg_rssi);
+
+ if (!db2dbm)
+ link_sinfo->signal_avg += ATH12K_DEFAULT_NOISE_FLOOR;
+
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
+
+ link_sinfo->tx_retries = peer->tx_retry_count;
+ link_sinfo->tx_failed = peer->tx_retry_failed;
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
+ link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
+
/* TODO: Use real NF instead of default one. */
- signal = arsta->rssi_comb;
+ signal = peer->rssi_comb;
- params.pdev_id = ar->pdev->pdev_id;
- params.vdev_id = 0;
- params.stats_id = WMI_REQUEST_VDEV_STAT;
+ spin_unlock_bh(&ar->ab->dp->dp_lock);
- if (!signal &&
- ahsta->ahvif->vdev_type == WMI_VDEV_TYPE_STA &&
- !(ath12k_mac_get_fw_stats(ar, &params))) {
- signal = arsta->rssi_beacon;
- ath12k_fw_stats_reset(ar);
+ if (!signal && ahsta->ahvif->vdev_type == WMI_VDEV_TYPE_STA) {
+ params.pdev_id = ar->pdev->pdev_id;
+ params.vdev_id = 0;
+ params.stats_id = WMI_REQUEST_VDEV_STAT;
+
+ if (!ath12k_mac_get_fw_stats(ar, &params)) {
+ signal = arsta->rssi_beacon;
+ ath12k_fw_stats_reset(ar);
+ }
}
if (signal) {
@@ -13316,22 +13595,11 @@ static void ath12k_mac_op_link_sta_statistics(struct ieee80211_hw *hw,
db2dbm ? signal : signal + ATH12K_DEFAULT_NOISE_FLOOR;
link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
}
-
- link_sinfo->signal_avg = ewma_avg_rssi_read(&arsta->avg_rssi);
-
- if (!db2dbm)
- link_sinfo->signal_avg += ATH12K_DEFAULT_NOISE_FLOOR;
-
- link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
-
- link_sinfo->tx_retries = arsta->tx_retry_count;
- link_sinfo->tx_failed = arsta->tx_retry_failed;
- link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
- link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
}
+EXPORT_SYMBOL(ath12k_mac_op_link_sta_statistics);
-static int ath12k_mac_op_cancel_remain_on_channel(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+int ath12k_mac_op_cancel_remain_on_channel(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
@@ -13351,12 +13619,13 @@ static int ath12k_mac_op_cancel_remain_on_channel(struct ieee80211_hw *hw,
return 0;
}
+EXPORT_SYMBOL(ath12k_mac_op_cancel_remain_on_channel);
-static int ath12k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_channel *chan,
- int duration,
- enum ieee80211_roc_type type)
+int ath12k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_channel *chan,
+ int duration,
+ enum ieee80211_roc_type type)
{
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
@@ -13491,10 +13760,11 @@ static int ath12k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
return 0;
}
+EXPORT_SYMBOL(ath12k_mac_op_remain_on_channel);
-static void ath12k_mac_op_set_rekey_data(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct cfg80211_gtk_rekey_data *data)
+void ath12k_mac_op_set_rekey_data(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_gtk_rekey_data *data)
{
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_rekey_data *rekey_data;
@@ -13527,63 +13797,7 @@ static void ath12k_mac_op_set_rekey_data(struct ieee80211_hw *hw,
ath12k_dbg_dump(ar->ab, ATH12K_DBG_MAC, "replay ctr", NULL,
&rekey_data->replay_ctr, sizeof(rekey_data->replay_ctr));
}
-
-static const struct ieee80211_ops ath12k_ops = {
- .tx = ath12k_mac_op_tx,
- .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = ath12k_mac_op_start,
- .stop = ath12k_mac_op_stop,
- .reconfig_complete = ath12k_mac_op_reconfig_complete,
- .add_interface = ath12k_mac_op_add_interface,
- .remove_interface = ath12k_mac_op_remove_interface,
- .update_vif_offload = ath12k_mac_op_update_vif_offload,
- .config = ath12k_mac_op_config,
- .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,
- .set_key = ath12k_mac_op_set_key,
- .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,
- .link_sta_rc_update = ath12k_mac_op_link_sta_rc_update,
- .conf_tx = ath12k_mac_op_conf_tx,
- .set_antenna = ath12k_mac_op_set_antenna,
- .get_antenna = ath12k_mac_op_get_antenna,
- .ampdu_action = ath12k_mac_op_ampdu_action,
- .add_chanctx = ath12k_mac_op_add_chanctx,
- .remove_chanctx = ath12k_mac_op_remove_chanctx,
- .change_chanctx = ath12k_mac_op_change_chanctx,
- .assign_vif_chanctx = ath12k_mac_op_assign_vif_chanctx,
- .unassign_vif_chanctx = ath12k_mac_op_unassign_vif_chanctx,
- .switch_vif_chanctx = ath12k_mac_op_switch_vif_chanctx,
- .get_txpower = ath12k_mac_op_get_txpower,
- .set_rts_threshold = ath12k_mac_op_set_rts_threshold,
- .set_frag_threshold = ath12k_mac_op_set_frag_threshold,
- .set_bitrate_mask = ath12k_mac_op_set_bitrate_mask,
- .get_survey = ath12k_mac_op_get_survey,
- .flush = ath12k_mac_op_flush,
- .sta_statistics = ath12k_mac_op_sta_statistics,
- .link_sta_statistics = ath12k_mac_op_link_sta_statistics,
- .remain_on_channel = ath12k_mac_op_remain_on_channel,
- .cancel_remain_on_channel = ath12k_mac_op_cancel_remain_on_channel,
- .change_sta_links = ath12k_mac_op_change_sta_links,
- .can_activate_links = ath12k_mac_op_can_activate_links,
-#ifdef CONFIG_PM
- .suspend = ath12k_wow_op_suspend,
- .resume = ath12k_wow_op_resume,
- .set_wakeup = ath12k_wow_op_set_wakeup,
-#endif
-#ifdef CONFIG_ATH12K_DEBUGFS
- .vif_add_debugfs = ath12k_debugfs_op_vif_add,
-#endif
- CFG80211_TESTMODE_CMD(ath12k_tm_cmd)
-#ifdef CONFIG_ATH12K_DEBUGFS
- .link_sta_add_debugfs = ath12k_debugfs_link_sta_op_add,
-#endif
-};
+EXPORT_SYMBOL(ath12k_mac_op_set_rekey_data);
void ath12k_mac_update_freq_range(struct ath12k *ar,
u32 freq_low, u32 freq_high)
@@ -14483,7 +14697,7 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah)
if (is_monitor_disable)
/* There's a race between calling ieee80211_register_hw()
* and here where the monitor mode is enabled for a little
- * while. But that time is so short and in practise it make
+ * while. But that time is so short and in practice it doesn't make
* a difference in real life.
*/
wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MONITOR);
@@ -14562,8 +14776,9 @@ static void ath12k_mac_setup(struct ath12k *ar)
ar->vdev_id_11d_scan = ATH12K_11D_INVALID_VDEV_ID;
spin_lock_init(&ar->data_lock);
+ spin_lock_init(&ar->dp.ppdu_list_lock);
INIT_LIST_HEAD(&ar->arvifs);
- INIT_LIST_HEAD(&ar->ppdu_stats_info);
+ INIT_LIST_HEAD(&ar->dp.ppdu_stats_info);
init_completion(&ar->vdev_setup_done);
init_completion(&ar->vdev_delete_done);
@@ -14802,7 +15017,7 @@ static struct ath12k_hw *ath12k_mac_hw_allocate(struct ath12k_hw_group *ag,
u8 pdev_idx;
hw = ieee80211_alloc_hw(struct_size(ah, radio, num_pdev_map),
- &ath12k_ops);
+ pdev_map->ab->ath12k_ops);
if (!hw)
return NULL;
@@ -14811,7 +15026,9 @@ static struct ath12k_hw *ath12k_mac_hw_allocate(struct ath12k_hw_group *ag,
ah->num_radio = num_pdev_map;
mutex_init(&ah->hw_mutex);
- INIT_LIST_HEAD(&ah->ml_peers);
+
+ spin_lock_init(&ah->dp_hw.peer_lock);
+ INIT_LIST_HEAD(&ah->dp_hw.dp_peers_list);
for (i = 0; i < num_pdev_map; i++) {
ab = pdev_map[i].ab;
diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h
index 1f689e367c8a..7b50c5976384 100644
--- a/drivers/net/wireless/ath/ath12k/mac.h
+++ b/drivers/net/wireless/ath/ath12k/mac.h
@@ -54,9 +54,6 @@ struct ath12k_generic_iter {
* for driver usage purpose.
*/
#define ATH12K_FIRST_SCAN_LINK IEEE80211_MLD_MAX_NUM_LINKS
-#define ATH12K_SCAN_MAX_LINKS ATH12K_GROUP_MAX_RADIO
-/* Define 1 scan link for each radio for parallel scan purposes */
-#define ATH12K_NUM_MAX_LINKS (IEEE80211_MLD_MAX_NUM_LINKS + ATH12K_SCAN_MAX_LINKS)
#define ATH12K_SCAN_LINKS_MASK GENMASK(ATH12K_NUM_MAX_LINKS, IEEE80211_MLD_MAX_NUM_LINKS)
#define ATH12K_NUM_MAX_ACTIVE_LINKS_PER_DEVICE 2
@@ -141,6 +138,9 @@ struct ath12k_reg_tpc_power_info {
struct ath12k_chan_power_info chan_power_info[ATH12K_NUM_PWR_LEVELS];
};
+#define ATH12K_OBSS_PD_MAX_THRESHOLD -82
+#define ATH12K_OBSS_PD_NON_SRG_MAX_THRESHOLD -62
+
extern const struct htt_rx_ring_tlv_filter ath12k_mac_mon_status_filter_default;
#define ATH12K_SCAN_11D_INTERVAL 600000
@@ -172,6 +172,7 @@ struct ath12k *ath12k_mac_get_ar_by_pdev_id(struct ath12k_base *ab, u32 pdev_id)
void ath12k_mac_drain_tx(struct ath12k *ar);
void ath12k_mac_peer_cleanup_all(struct ath12k *ar);
+void ath12k_mac_dp_peer_cleanup(struct ath12k_hw *ah);
int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx);
enum rate_info_bw ath12k_mac_bw_to_mac80211_bw(enum ath12k_supported_bw bw);
enum ath12k_supported_bw ath12k_mac_mac80211_bw_to_ath12k_bw(enum rate_info_bw bw);
@@ -206,4 +207,139 @@ void ath12k_mac_update_freq_range(struct ath12k *ar,
void ath12k_mac_fill_reg_tpc_info(struct ath12k *ar,
struct ath12k_link_vif *arvif,
struct ieee80211_chanctx_conf *ctx);
+int ath12k_mac_op_start(struct ieee80211_hw *hw);
+void ath12k_mac_op_stop(struct ieee80211_hw *hw, bool suspend);
+void
+ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
+ enum ieee80211_reconfig_type reconfig_type);
+int ath12k_mac_op_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+void ath12k_mac_op_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+void ath12k_mac_op_update_vif_offload(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+int ath12k_mac_op_config(struct ieee80211_hw *hw, int radio_idx, u32 changed);
+void ath12k_mac_op_link_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *info,
+ u64 changed);
+void ath12k_mac_op_vif_cfg_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ u64 changed);
+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]);
+void ath12k_mac_op_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed_flags,
+ unsigned int *total_flags,
+ u64 multicast);
+int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_scan_request *hw_req);
+void ath12k_mac_op_cancel_hw_scan(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+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);
+void ath12k_mac_op_set_rekey_data(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_gtk_rekey_data *data);
+int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ enum ieee80211_sta_state old_state,
+ enum ieee80211_sta_state new_state);
+int ath12k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+void ath12k_mac_op_link_sta_rc_update(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_link_sta *link_sta,
+ u32 changed);
+int ath12k_mac_op_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ unsigned int link_id, u16 ac,
+ const struct ieee80211_tx_queue_params *params);
+int ath12k_mac_op_set_antenna(struct ieee80211_hw *hw, int radio_idx,
+ u32 tx_ant, u32 rx_ant);
+int ath12k_mac_op_get_antenna(struct ieee80211_hw *hw, int radio_idx,
+ u32 *tx_ant, u32 *rx_ant);
+int ath12k_mac_op_ampdu_action(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_ampdu_params *params);
+int ath12k_mac_op_add_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *ctx);
+void ath12k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *ctx);
+void ath12k_mac_op_change_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *ctx,
+ u32 changed);
+int
+ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
+ struct ieee80211_chanctx_conf *ctx);
+void
+ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf,
+ struct ieee80211_chanctx_conf *ctx);
+int
+ath12k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_vif_chanctx_switch *vifs,
+ int n_vifs,
+ enum ieee80211_chanctx_switch_mode mode);
+int ath12k_mac_op_set_rts_threshold(struct ieee80211_hw *hw,
+ int radio_idx, u32 value);
+int ath12k_mac_op_set_frag_threshold(struct ieee80211_hw *hw,
+ int radio_idx, u32 value);
+int
+ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ const struct cfg80211_bitrate_mask *mask);
+int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx,
+ struct survey_info *survey);
+void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ u32 queues, bool drop);
+void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct station_info *sinfo);
+void ath12k_mac_op_link_sta_statistics(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_link_sta *link_sta,
+ struct link_station_info *link_sinfo);
+int ath12k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_channel *chan,
+ int duration,
+ enum ieee80211_roc_type type);
+int ath12k_mac_op_cancel_remain_on_channel(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+int ath12k_mac_op_change_sta_links(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ u16 old_links, u16 new_links);
+bool ath12k_mac_op_can_activate_links(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ u16 active_links);
+int ath12k_mac_op_get_txpower(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ unsigned int link_id,
+ int *dbm);
+int ath12k_mac_mgmt_tx(struct ath12k *ar, struct sk_buff *skb,
+ bool is_prb_rsp);
+void ath12k_mac_add_p2p_noa_ie(struct ath12k *ar,
+ struct ieee80211_vif *vif,
+ struct sk_buff *skb,
+ bool is_prb_rsp);
+u8 ath12k_mac_get_tx_link(struct ieee80211_sta *sta, struct ieee80211_vif *vif,
+ u8 link, struct sk_buff *skb, u32 info_flags);
+
+void ath12k_mlo_mcast_update_tx_link_address(struct ieee80211_vif *vif,
+ u8 link_id, struct sk_buff *skb,
+ u32 info_flags);
#endif
diff --git a/drivers/net/wireless/ath/ath12k/mhi.c b/drivers/net/wireless/ath/ath12k/mhi.c
index 08f44baf182a..45c0f66dcc5e 100644
--- a/drivers/net/wireless/ath/ath12k/mhi.c
+++ b/drivers/net/wireless/ath/ath12k/mhi.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/msi.h>
@@ -18,136 +18,6 @@
#define OTP_VALID_DUALMAC_BOARD_ID_MASK 0x1000
#define MHI_CB_INVALID 0xff
-static const struct mhi_channel_config ath12k_mhi_channels_qcn9274[] = {
- {
- .num = 20,
- .name = "IPCR",
- .num_elements = 32,
- .event_ring = 1,
- .dir = DMA_TO_DEVICE,
- .ee_mask = 0x4,
- .pollcfg = 0,
- .doorbell = MHI_DB_BRST_DISABLE,
- .lpm_notify = false,
- .offload_channel = false,
- .doorbell_mode_switch = false,
- .auto_queue = false,
- },
- {
- .num = 21,
- .name = "IPCR",
- .num_elements = 32,
- .event_ring = 1,
- .dir = DMA_FROM_DEVICE,
- .ee_mask = 0x4,
- .pollcfg = 0,
- .doorbell = MHI_DB_BRST_DISABLE,
- .lpm_notify = false,
- .offload_channel = false,
- .doorbell_mode_switch = false,
- .auto_queue = true,
- },
-};
-
-static struct mhi_event_config ath12k_mhi_events_qcn9274[] = {
- {
- .num_elements = 32,
- .irq_moderation_ms = 0,
- .irq = 1,
- .data_type = MHI_ER_CTRL,
- .mode = MHI_DB_BRST_DISABLE,
- .hardware_event = false,
- .client_managed = false,
- .offload_channel = false,
- },
- {
- .num_elements = 256,
- .irq_moderation_ms = 1,
- .irq = 2,
- .mode = MHI_DB_BRST_DISABLE,
- .priority = 1,
- .hardware_event = false,
- .client_managed = false,
- .offload_channel = false,
- },
-};
-
-const struct mhi_controller_config ath12k_mhi_config_qcn9274 = {
- .max_channels = 30,
- .timeout_ms = 10000,
- .use_bounce_buf = false,
- .buf_len = 0,
- .num_channels = ARRAY_SIZE(ath12k_mhi_channels_qcn9274),
- .ch_cfg = ath12k_mhi_channels_qcn9274,
- .num_events = ARRAY_SIZE(ath12k_mhi_events_qcn9274),
- .event_cfg = ath12k_mhi_events_qcn9274,
-};
-
-static const struct mhi_channel_config ath12k_mhi_channels_wcn7850[] = {
- {
- .num = 20,
- .name = "IPCR",
- .num_elements = 64,
- .event_ring = 1,
- .dir = DMA_TO_DEVICE,
- .ee_mask = 0x4,
- .pollcfg = 0,
- .doorbell = MHI_DB_BRST_DISABLE,
- .lpm_notify = false,
- .offload_channel = false,
- .doorbell_mode_switch = false,
- .auto_queue = false,
- },
- {
- .num = 21,
- .name = "IPCR",
- .num_elements = 64,
- .event_ring = 1,
- .dir = DMA_FROM_DEVICE,
- .ee_mask = 0x4,
- .pollcfg = 0,
- .doorbell = MHI_DB_BRST_DISABLE,
- .lpm_notify = false,
- .offload_channel = false,
- .doorbell_mode_switch = false,
- .auto_queue = true,
- },
-};
-
-static struct mhi_event_config ath12k_mhi_events_wcn7850[] = {
- {
- .num_elements = 32,
- .irq_moderation_ms = 0,
- .irq = 1,
- .mode = MHI_DB_BRST_DISABLE,
- .data_type = MHI_ER_CTRL,
- .hardware_event = false,
- .client_managed = false,
- .offload_channel = false,
- },
- {
- .num_elements = 256,
- .irq_moderation_ms = 1,
- .irq = 2,
- .mode = MHI_DB_BRST_DISABLE,
- .priority = 1,
- .hardware_event = false,
- .client_managed = false,
- .offload_channel = false,
- },
-};
-
-const struct mhi_controller_config ath12k_mhi_config_wcn7850 = {
- .max_channels = 128,
- .timeout_ms = 2000,
- .use_bounce_buf = false,
- .buf_len = 8192,
- .num_channels = ARRAY_SIZE(ath12k_mhi_channels_wcn7850),
- .ch_cfg = ath12k_mhi_channels_wcn7850,
- .num_events = ARRAY_SIZE(ath12k_mhi_events_wcn7850),
- .event_cfg = ath12k_mhi_events_wcn7850,
-};
-
void ath12k_mhi_set_mhictrl_reset(struct ath12k_base *ab)
{
u32 val;
diff --git a/drivers/net/wireless/ath/ath12k/mhi.h b/drivers/net/wireless/ath/ath12k/mhi.h
index 7358b8477536..367432676385 100644
--- a/drivers/net/wireless/ath/ath12k/mhi.h
+++ b/drivers/net/wireless/ath/ath12k/mhi.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef _ATH12K_MHI_H
#define _ATH12K_MHI_H
@@ -31,9 +31,6 @@ enum ath12k_mhi_state {
ATH12K_MHI_RDDM_DONE,
};
-extern const struct mhi_controller_config ath12k_mhi_config_qcn9274;
-extern const struct mhi_controller_config ath12k_mhi_config_wcn7850;
-
int ath12k_mhi_start(struct ath12k_pci *ar_pci);
void ath12k_mhi_stop(struct ath12k_pci *ar_pci, bool is_suspend);
int ath12k_mhi_register(struct ath12k_pci *ar_pci);
diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c
index a12c8379cb46..375277ca2b89 100644
--- a/drivers/net/wireless/ath/ath12k/pci.c
+++ b/drivers/net/wireless/ath/ath12k/pci.c
@@ -15,6 +15,7 @@
#include "hif.h"
#include "mhi.h"
#include "debug.h"
+#include "hal.h"
#define ATH12K_PCI_BAR_NUM 0
#define ATH12K_PCI_DMA_MASK 36
@@ -22,50 +23,18 @@
#define ATH12K_PCI_IRQ_CE0_OFFSET 3
#define WINDOW_ENABLE_BIT 0x40000000
-#define WINDOW_REG_ADDRESS 0x310c
#define WINDOW_VALUE_MASK GENMASK(24, 19)
#define WINDOW_START 0x80000
#define WINDOW_RANGE_MASK GENMASK(18, 0)
#define WINDOW_STATIC_MASK GENMASK(31, 6)
-#define TCSR_SOC_HW_VERSION 0x1B00000
-#define TCSR_SOC_HW_VERSION_MAJOR_MASK GENMASK(11, 8)
-#define TCSR_SOC_HW_VERSION_MINOR_MASK GENMASK(7, 4)
-
/* BAR0 + 4k is always accessible, and no
* need to force wakeup.
* 4K - 32 = 0xFE0
*/
#define ACCESS_ALWAYS_OFF 0xFE0
-#define QCN9274_DEVICE_ID 0x1109
-#define WCN7850_DEVICE_ID 0x1107
-
-#define PCIE_LOCAL_REG_QRTR_NODE_ID 0x1E03164
-#define DOMAIN_NUMBER_MASK GENMASK(7, 4)
-#define BUS_NUMBER_MASK GENMASK(3, 0)
-
-static const struct pci_device_id ath12k_pci_id_table[] = {
- { PCI_VDEVICE(QCOM, QCN9274_DEVICE_ID) },
- { PCI_VDEVICE(QCOM, WCN7850_DEVICE_ID) },
- {}
-};
-
-MODULE_DEVICE_TABLE(pci, ath12k_pci_id_table);
-
-/* TODO: revisit IRQ mapping for new SRNG's */
-static const struct ath12k_msi_config ath12k_msi_config[] = {
- {
- .total_vectors = 16,
- .total_users = 3,
- .users = (struct ath12k_msi_user[]) {
- { .name = "MHI", .num_vectors = 3, .base_vector = 0 },
- { .name = "CE", .num_vectors = 5, .base_vector = 3 },
- { .name = "DP", .num_vectors = 8, .base_vector = 8 },
- },
- },
-};
-
+static struct ath12k_pci_driver *ath12k_pci_family_drivers[ATH12K_DEVICE_FAMILY_MAX];
static const struct ath12k_msi_config msi_config_one_msi = {
.total_vectors = 1,
.total_users = 4,
@@ -136,30 +105,6 @@ static const char *irq_name[ATH12K_IRQ_NUM_MAX] = {
"tcl2host-status-ring",
};
-static int ath12k_pci_bus_wake_up(struct ath12k_base *ab)
-{
- struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
-
- return mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
-}
-
-static void ath12k_pci_bus_release(struct ath12k_base *ab)
-{
- struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
-
- mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
-}
-
-static const struct ath12k_pci_ops ath12k_pci_ops_qcn9274 = {
- .wakeup = NULL,
- .release = NULL,
-};
-
-static const struct ath12k_pci_ops ath12k_pci_ops_wcn7850 = {
- .wakeup = ath12k_pci_bus_wake_up,
- .release = ath12k_pci_bus_release,
-};
-
static void ath12k_pci_select_window(struct ath12k_pci *ab_pci, u32 offset)
{
struct ath12k_base *ab = ab_pci->ab;
@@ -175,37 +120,40 @@ static void ath12k_pci_select_window(struct ath12k_pci *ab_pci, u32 offset)
if (window != ab_pci->register_window) {
iowrite32(WINDOW_ENABLE_BIT | window,
- ab->mem + WINDOW_REG_ADDRESS);
- ioread32(ab->mem + WINDOW_REG_ADDRESS);
+ ab->mem + ab_pci->window_reg_addr);
+ ioread32(ab->mem + ab_pci->window_reg_addr);
ab_pci->register_window = window;
}
}
static void ath12k_pci_select_static_window(struct ath12k_pci *ab_pci)
{
- u32 umac_window = u32_get_bits(HAL_SEQ_WCSS_UMAC_OFFSET, WINDOW_VALUE_MASK);
- u32 ce_window = u32_get_bits(HAL_CE_WFSS_CE_REG_BASE, WINDOW_VALUE_MASK);
+ u32 umac_window;
+ u32 ce_window;
u32 window;
+ umac_window = u32_get_bits(ab_pci->reg_base->umac_base, WINDOW_VALUE_MASK);
+ ce_window = u32_get_bits(ab_pci->reg_base->ce_reg_base, WINDOW_VALUE_MASK);
window = (umac_window << 12) | (ce_window << 6);
spin_lock_bh(&ab_pci->window_lock);
ab_pci->register_window = window;
spin_unlock_bh(&ab_pci->window_lock);
- iowrite32(WINDOW_ENABLE_BIT | window, ab_pci->ab->mem + WINDOW_REG_ADDRESS);
+ iowrite32(WINDOW_ENABLE_BIT | window, ab_pci->ab->mem + ab_pci->window_reg_addr);
}
static u32 ath12k_pci_get_window_start(struct ath12k_base *ab,
u32 offset)
{
+ struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
u32 window_start;
/* If offset lies within DP register range, use 3rd window */
- if ((offset ^ HAL_SEQ_WCSS_UMAC_OFFSET) < WINDOW_RANGE_MASK)
+ if ((offset ^ ab_pci->reg_base->umac_base) < WINDOW_RANGE_MASK)
window_start = 3 * WINDOW_START;
/* If offset lies within CE register range, use 2nd window */
- else if ((offset ^ HAL_CE_WFSS_CE_REG_BASE) < WINDOW_RANGE_MASK)
+ else if ((offset ^ ab_pci->reg_base->ce_reg_base) < WINDOW_RANGE_MASK)
window_start = 2 * WINDOW_START;
else
window_start = WINDOW_START;
@@ -225,8 +173,8 @@ static void ath12k_pci_restore_window(struct ath12k_base *ab)
spin_lock_bh(&ab_pci->window_lock);
iowrite32(WINDOW_ENABLE_BIT | ab_pci->register_window,
- ab->mem + WINDOW_REG_ADDRESS);
- ioread32(ab->mem + WINDOW_REG_ADDRESS);
+ ab->mem + ab_pci->window_reg_addr);
+ ioread32(ab->mem + ab_pci->window_reg_addr);
spin_unlock_bh(&ab_pci->window_lock);
}
@@ -544,10 +492,11 @@ static int ath12k_pci_ext_grp_napi_poll(struct napi_struct *napi, int budget)
struct ath12k_ext_irq_grp,
napi);
struct ath12k_base *ab = irq_grp->ab;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
int work_done;
int i;
- work_done = ath12k_dp_service_srng(ab, irq_grp, budget);
+ work_done = ath12k_dp_service_srng(dp, irq_grp, budget);
if (work_done < budget) {
napi_complete_done(napi, work_done);
for (i = 0; i < irq_grp->num_irq; i++)
@@ -965,7 +914,7 @@ static void ath12k_pci_update_qrtr_node_id(struct ath12k_base *ab)
* writes to the given register, it is available for firmware when the QMI service
* is spawned.
*/
- reg = PCIE_LOCAL_REG_QRTR_NODE_ID & WINDOW_RANGE_MASK;
+ reg = PCIE_LOCAL_REG_QRTR_NODE_ID(ab) & WINDOW_RANGE_MASK;
ath12k_pci_write32(ab, reg, ab_pci->qmi_instance);
ath12k_dbg(ab, ATH12K_DBG_PCI, "pci reg 0x%x instance 0x%x read val 0x%x\n",
@@ -1244,6 +1193,7 @@ u32 ath12k_pci_read32(struct ath12k_base *ab, u32 offset)
ab_pci->pci_ops->release(ab);
return val;
}
+EXPORT_SYMBOL(ath12k_pci_read32);
void ath12k_pci_write32(struct ath12k_base *ab, u32 offset, u32 value)
{
@@ -1549,28 +1499,34 @@ static const struct ath12k_hif_ops ath12k_pci_hif_ops = {
#endif
};
-static
-void ath12k_pci_read_hw_version(struct ath12k_base *ab, u32 *major, u32 *minor)
+static enum ath12k_device_family
+ath12k_get_device_family(const struct pci_device_id *pci_dev)
{
- u32 soc_hw_version;
+ enum ath12k_device_family device_family_id;
+ const struct pci_device_id *id;
+
+ for (device_family_id = ATH12K_DEVICE_FAMILY_START;
+ device_family_id < ATH12K_DEVICE_FAMILY_MAX; device_family_id++) {
+ if (!ath12k_pci_family_drivers[device_family_id])
+ continue;
- soc_hw_version = ath12k_pci_read32(ab, TCSR_SOC_HW_VERSION);
- *major = FIELD_GET(TCSR_SOC_HW_VERSION_MAJOR_MASK,
- soc_hw_version);
- *minor = FIELD_GET(TCSR_SOC_HW_VERSION_MINOR_MASK,
- soc_hw_version);
+ id = ath12k_pci_family_drivers[device_family_id]->id_table;
+ while (id->device) {
+ if (id->device == pci_dev->device)
+ return device_family_id;
+ id += 1;
+ }
+ }
- ath12k_dbg(ab, ATH12K_DBG_PCI,
- "pci tcsr_soc_hw_version major %d minor %d\n",
- *major, *minor);
+ return ATH12K_DEVICE_FAMILY_MAX;
}
static int ath12k_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *pci_dev)
{
- struct ath12k_base *ab;
+ enum ath12k_device_family device_id;
struct ath12k_pci *ab_pci;
- u32 soc_hw_version_major, soc_hw_version_minor;
+ struct ath12k_base *ab;
int ret;
ab = ath12k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH12K_BUS_PCI);
@@ -1580,7 +1536,6 @@ static int ath12k_pci_probe(struct pci_dev *pdev,
}
ab->dev = &pdev->dev;
- pci_set_drvdata(pdev, ab);
ab_pci = ath12k_pci_priv(ab);
ab_pci->dev_id = pci_dev->device;
ab_pci->ab = ab;
@@ -1605,56 +1560,25 @@ static int ath12k_pci_probe(struct pci_dev *pdev,
ab->id.subsystem_vendor = pdev->subsystem_vendor;
ab->id.subsystem_device = pdev->subsystem_device;
- switch (pci_dev->device) {
- case QCN9274_DEVICE_ID:
- ab_pci->msi_config = &ath12k_msi_config[0];
- ab->static_window_map = true;
- ab_pci->pci_ops = &ath12k_pci_ops_qcn9274;
- ab->hal_rx_ops = &hal_rx_qcn9274_ops;
- ath12k_pci_read_hw_version(ab, &soc_hw_version_major,
- &soc_hw_version_minor);
- ab->target_mem_mode = ath12k_core_get_memory_mode(ab);
- switch (soc_hw_version_major) {
- case ATH12K_PCI_SOC_HW_VERSION_2:
- ab->hw_rev = ATH12K_HW_QCN9274_HW20;
- break;
- case ATH12K_PCI_SOC_HW_VERSION_1:
- ab->hw_rev = ATH12K_HW_QCN9274_HW10;
- break;
- default:
- dev_err(&pdev->dev,
- "Unknown hardware version found for QCN9274: 0x%x\n",
- soc_hw_version_major);
- ret = -EOPNOTSUPP;
- goto err_pci_free_region;
- }
- break;
- case WCN7850_DEVICE_ID:
- ab->id.bdf_search = ATH12K_BDF_SEARCH_BUS_AND_BOARD;
- ab_pci->msi_config = &ath12k_msi_config[0];
- ab->static_window_map = false;
- ab_pci->pci_ops = &ath12k_pci_ops_wcn7850;
- ab->hal_rx_ops = &hal_rx_wcn7850_ops;
- ath12k_pci_read_hw_version(ab, &soc_hw_version_major,
- &soc_hw_version_minor);
- ab->target_mem_mode = ATH12K_QMI_MEMORY_MODE_DEFAULT;
- switch (soc_hw_version_major) {
- case ATH12K_PCI_SOC_HW_VERSION_2:
- ab->hw_rev = ATH12K_HW_WCN7850_HW20;
- break;
- default:
- dev_err(&pdev->dev,
- "Unknown hardware version found for WCN7850: 0x%x\n",
- soc_hw_version_major);
- ret = -EOPNOTSUPP;
- goto err_pci_free_region;
- }
- break;
+ device_id = ath12k_get_device_family(pci_dev);
+ if (device_id >= ATH12K_DEVICE_FAMILY_MAX) {
+ ath12k_err(ab, "failed to get device family id\n");
+ ret = -EINVAL;
+ goto err_pci_free_region;
+ }
+
+ ath12k_dbg(ab, ATH12K_DBG_PCI, "PCI device family id: %d\n", device_id);
- default:
- dev_err(&pdev->dev, "Unknown PCI device found: 0x%x\n",
- pci_dev->device);
- ret = -EOPNOTSUPP;
+ ab_pci->device_family_ops = &ath12k_pci_family_drivers[device_id]->ops;
+ ab_pci->reg_base = ath12k_pci_family_drivers[device_id]->reg_base;
+
+ /* Call device specific probe. This is the callback that can
+ * be used to override any ops in future
+ * probe is validated for NULL during registration.
+ */
+ ret = ab_pci->device_family_ops->probe(pdev, pci_dev);
+ if (ret) {
+ ath12k_err(ab, "failed to probe device: %d\n", ret);
goto err_pci_free_region;
}
@@ -1709,13 +1633,25 @@ static int ath12k_pci_probe(struct pci_dev *pdev,
goto err_free_irq;
}
+ /* Invoke arch_init here so that arch-specific init operations
+ * can utilize already initialized ab fields, such as HAL SRNGs.
+ */
+ ret = ab_pci->device_family_ops->arch_init(ab);
+ if (ret) {
+ ath12k_err(ab, "PCI arch_init failed %d\n", ret);
+ goto err_pci_msi_free;
+ }
+
ret = ath12k_core_init(ab);
if (ret) {
ath12k_err(ab, "failed to init core: %d\n", ret);
- goto err_free_irq;
+ goto err_deinit_arch;
}
return 0;
+err_deinit_arch:
+ ab_pci->device_family_ops->arch_deinit(ab);
+
err_free_irq:
/* __free_irq() expects the caller to have cleared the affinity hint */
ath12k_pci_set_irq_affinity_hint(ab_pci, NULL);
@@ -1774,6 +1710,9 @@ qmi_fail:
ath12k_hal_srng_deinit(ab);
ath12k_ce_free_pipes(ab);
+
+ ab_pci->device_family_ops->arch_deinit(ab);
+
ath12k_core_free(ab);
}
@@ -1862,33 +1801,47 @@ static const struct dev_pm_ops __maybe_unused ath12k_pci_pm_ops = {
ath12k_pci_pm_resume_early)
};
-static struct pci_driver ath12k_pci_driver = {
- .name = "ath12k_pci",
- .id_table = ath12k_pci_id_table,
- .probe = ath12k_pci_probe,
- .remove = ath12k_pci_remove,
- .shutdown = ath12k_pci_shutdown,
- .driver.pm = &ath12k_pci_pm_ops,
-};
-
-int ath12k_pci_init(void)
+int ath12k_pci_register_driver(const enum ath12k_device_family device_id,
+ struct ath12k_pci_driver *driver)
{
- int ret;
+ struct pci_driver *pci_driver;
- ret = pci_register_driver(&ath12k_pci_driver);
- if (ret) {
- pr_err("failed to register ath12k pci driver: %d\n",
- ret);
- return ret;
+ if (device_id >= ATH12K_DEVICE_FAMILY_MAX)
+ return -EINVAL;
+
+ if (!driver || !driver->ops.probe ||
+ !driver->ops.arch_init || !driver->ops.arch_deinit)
+ return -EINVAL;
+
+ if (ath12k_pci_family_drivers[device_id]) {
+ pr_err("Driver already registered for %d\n", device_id);
+ return -EALREADY;
}
- return 0;
+ ath12k_pci_family_drivers[device_id] = driver;
+
+ pci_driver = &ath12k_pci_family_drivers[device_id]->driver;
+ pci_driver->name = driver->name;
+ pci_driver->id_table = driver->id_table;
+ pci_driver->probe = ath12k_pci_probe;
+ pci_driver->remove = ath12k_pci_remove;
+ pci_driver->shutdown = ath12k_pci_shutdown;
+ pci_driver->driver.pm = &ath12k_pci_pm_ops;
+
+ return pci_register_driver(pci_driver);
}
+EXPORT_SYMBOL(ath12k_pci_register_driver);
-void ath12k_pci_exit(void)
+void ath12k_pci_unregister_driver(const enum ath12k_device_family device_id)
{
- pci_unregister_driver(&ath12k_pci_driver);
+ if (device_id >= ATH12K_DEVICE_FAMILY_MAX ||
+ !ath12k_pci_family_drivers[device_id])
+ return;
+
+ pci_unregister_driver(&ath12k_pci_family_drivers[device_id]->driver);
+ ath12k_pci_family_drivers[device_id] = NULL;
}
+EXPORT_SYMBOL(ath12k_pci_unregister_driver);
/* firmware files */
MODULE_FIRMWARE(ATH12K_FW_DIR "/QCN9274/hw2.0/*");
diff --git a/drivers/net/wireless/ath/ath12k/pci.h b/drivers/net/wireless/ath/ath12k/pci.h
index d1ec8aad7f6c..0e0e2020c6ae 100644
--- a/drivers/net/wireless/ath/ath12k/pci.h
+++ b/drivers/net/wireless/ath/ath12k/pci.h
@@ -1,12 +1,13 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH12K_PCI_H
#define ATH12K_PCI_H
#include <linux/mhi.h>
+#include <linux/pci.h>
#include "core.h"
@@ -29,7 +30,7 @@
#define PARM_LTSSM_VALUE 0x111
#define GCC_GCC_PCIE_HOT_RST(ab) \
- ((ab)->hw_params->regs->gcc_gcc_pcie_hot_rst)
+ ((ab)->hal.regs->gcc_gcc_pcie_hot_rst)
#define GCC_GCC_PCIE_HOT_RST_VAL 0x10
@@ -38,17 +39,17 @@
#define PCIE_INT_CLEAR_ALL 0xffffffff
#define PCIE_QSERDES_COM_SYSCLK_EN_SEL_REG(ab) \
- ((ab)->hw_params->regs->pcie_qserdes_sysclk_en_sel)
+ ((ab)->hal.regs->pcie_qserdes_sysclk_en_sel)
#define PCIE_QSERDES_COM_SYSCLK_EN_SEL_VAL 0x10
#define PCIE_QSERDES_COM_SYSCLK_EN_SEL_MSK 0xffffffff
#define PCIE_PCS_OSC_DTCT_CONFIG1_REG(ab) \
- ((ab)->hw_params->regs->pcie_pcs_osc_dtct_config_base)
+ ((ab)->hal.regs->pcie_pcs_osc_dtct_config_base)
#define PCIE_PCS_OSC_DTCT_CONFIG1_VAL 0x02
#define PCIE_PCS_OSC_DTCT_CONFIG2_REG(ab) \
- ((ab)->hw_params->regs->pcie_pcs_osc_dtct_config_base + 0x4)
+ ((ab)->hal.regs->pcie_pcs_osc_dtct_config_base + 0x4)
#define PCIE_PCS_OSC_DTCT_CONFIG2_VAL 0x52
#define PCIE_PCS_OSC_DTCT_CONFIG4_REG(ab) \
- ((ab)->hw_params->regs->pcie_pcs_osc_dtct_config_base + 0xc)
+ ((ab)->hal.regs->pcie_pcs_osc_dtct_config_base + 0xc)
#define PCIE_PCS_OSC_DTCT_CONFIG4_VAL 0xff
#define PCIE_PCS_OSC_DTCT_CONFIG_MSK 0x000000ff
@@ -58,6 +59,11 @@
#define QCN9274_QFPROM_RAW_RFA_PDET_ROW13_LSB 0x1E20338
#define OTP_BOARD_ID_MASK GENMASK(15, 0)
+#define PCIE_LOCAL_REG_QRTR_NODE_ID(ab) \
+ ((ab)->hal.regs->qrtr_node_id)
+#define DOMAIN_NUMBER_MASK GENMASK(7, 4)
+#define BUS_NUMBER_MASK GENMASK(3, 0)
+
#define PCI_BAR_WINDOW0_BASE 0x1E00000
#define PCI_BAR_WINDOW0_END 0x1E7FFFC
#define PCI_SOC_RANGE_MASK 0x3FFF
@@ -70,9 +76,6 @@
#define QRTR_PCI_DOMAIN_NR_MASK GENMASK(7, 4)
#define QRTR_PCI_BUS_NUMBER_MASK GENMASK(3, 0)
-#define ATH12K_PCI_SOC_HW_VERSION_1 1
-#define ATH12K_PCI_SOC_HW_VERSION_2 2
-
struct ath12k_msi_user {
const char *name;
int num_vectors;
@@ -97,6 +100,17 @@ struct ath12k_pci_ops {
void (*release)(struct ath12k_base *ab);
};
+struct ath12k_pci_device_family_ops {
+ int (*probe)(struct pci_dev *pdev, const struct pci_device_id *pci_dev);
+ int (*arch_init)(struct ath12k_base *ab);
+ void (*arch_deinit)(struct ath12k_base *ab);
+};
+
+struct ath12k_pci_reg_base {
+ u32 umac_base;
+ u32 ce_reg_base;
+};
+
struct ath12k_pci {
struct pci_dev *pdev;
struct ath12k_base *ab;
@@ -119,6 +133,18 @@ struct ath12k_pci {
const struct ath12k_pci_ops *pci_ops;
u32 qmi_instance;
u64 dma_mask;
+ const struct ath12k_pci_device_family_ops *device_family_ops;
+ const struct ath12k_pci_reg_base *reg_base;
+
+ u32 window_reg_addr;
+};
+
+struct ath12k_pci_driver {
+ const char *name;
+ const struct pci_device_id *id_table;
+ struct ath12k_pci_device_family_ops ops;
+ struct pci_driver driver;
+ const struct ath12k_pci_reg_base *reg_base;
};
static inline struct ath12k_pci *ath12k_pci_priv(struct ath12k_base *ab)
@@ -148,6 +174,7 @@ void ath12k_pci_stop(struct ath12k_base *ab);
int ath12k_pci_start(struct ath12k_base *ab);
int ath12k_pci_power_up(struct ath12k_base *ab);
void ath12k_pci_power_down(struct ath12k_base *ab, bool is_suspend);
-int ath12k_pci_init(void);
-void ath12k_pci_exit(void);
+int ath12k_pci_register_driver(const enum ath12k_device_family device_id,
+ struct ath12k_pci_driver *driver);
+void ath12k_pci_unregister_driver(const enum ath12k_device_family device_id);
#endif /* ATH12K_PCI_H */
diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c
index f1ae9e5b5af7..5f3bd3b9a3e9 100644
--- a/drivers/net/wireless/ath/ath12k/peer.c
+++ b/drivers/net/wireless/ath/ath12k/peer.c
@@ -1,211 +1,28 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022, 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include "core.h"
#include "peer.h"
#include "debug.h"
+#include "debugfs.h"
-struct ath12k_ml_peer *ath12k_peer_ml_find(struct ath12k_hw *ah, const u8 *addr)
-{
- struct ath12k_ml_peer *ml_peer;
-
- lockdep_assert_wiphy(ah->hw->wiphy);
-
- list_for_each_entry(ml_peer, &ah->ml_peers, list) {
- if (!ether_addr_equal(ml_peer->addr, addr))
- continue;
-
- return ml_peer;
- }
-
- return NULL;
-}
-
-struct ath12k_peer *ath12k_peer_find(struct ath12k_base *ab, int vdev_id,
- const u8 *addr)
-{
- struct ath12k_peer *peer;
-
- lockdep_assert_held(&ab->base_lock);
-
- list_for_each_entry(peer, &ab->peers, list) {
- if (peer->vdev_id != vdev_id)
- continue;
- if (!ether_addr_equal(peer->addr, addr))
- continue;
-
- return peer;
- }
-
- return NULL;
-}
-
-static struct ath12k_peer *ath12k_peer_find_by_pdev_idx(struct ath12k_base *ab,
- u8 pdev_idx, const u8 *addr)
-{
- struct ath12k_peer *peer;
-
- lockdep_assert_held(&ab->base_lock);
-
- list_for_each_entry(peer, &ab->peers, list) {
- if (peer->pdev_idx != pdev_idx)
- continue;
- if (!ether_addr_equal(peer->addr, addr))
- continue;
-
- return peer;
- }
-
- return NULL;
-}
-
-struct ath12k_peer *ath12k_peer_find_by_addr(struct ath12k_base *ab,
- const u8 *addr)
-{
- struct ath12k_peer *peer;
-
- lockdep_assert_held(&ab->base_lock);
-
- list_for_each_entry(peer, &ab->peers, list) {
- if (!ether_addr_equal(peer->addr, addr))
- continue;
-
- return peer;
- }
-
- return NULL;
-}
-
-static struct ath12k_peer *ath12k_peer_find_by_ml_id(struct ath12k_base *ab,
- int ml_peer_id)
-{
- struct ath12k_peer *peer;
-
- lockdep_assert_held(&ab->base_lock);
-
- list_for_each_entry(peer, &ab->peers, list)
- if (ml_peer_id == peer->ml_id)
- return peer;
-
- return NULL;
-}
-
-struct ath12k_peer *ath12k_peer_find_by_id(struct ath12k_base *ab,
- int peer_id)
-{
- struct ath12k_peer *peer;
-
- lockdep_assert_held(&ab->base_lock);
-
- if (peer_id == HAL_INVALID_PEERID)
- return NULL;
-
- if (peer_id & ATH12K_PEER_ML_ID_VALID)
- return ath12k_peer_find_by_ml_id(ab, peer_id);
-
- list_for_each_entry(peer, &ab->peers, list)
- if (peer_id == peer->peer_id)
- return peer;
-
- return NULL;
-}
-
-bool ath12k_peer_exist_by_vdev_id(struct ath12k_base *ab, int vdev_id)
-{
- struct ath12k_peer *peer;
-
- spin_lock_bh(&ab->base_lock);
-
- list_for_each_entry(peer, &ab->peers, list) {
- if (vdev_id == peer->vdev_id) {
- spin_unlock_bh(&ab->base_lock);
- return true;
- }
- }
- spin_unlock_bh(&ab->base_lock);
- return false;
-}
-
-struct ath12k_peer *ath12k_peer_find_by_ast(struct ath12k_base *ab,
- int ast_hash)
-{
- struct ath12k_peer *peer;
-
- lockdep_assert_held(&ab->base_lock);
-
- list_for_each_entry(peer, &ab->peers, list)
- if (ast_hash == peer->ast_hash)
- return peer;
-
- return NULL;
-}
-
-void ath12k_peer_unmap_event(struct ath12k_base *ab, u16 peer_id)
-{
- struct ath12k_peer *peer;
-
- spin_lock_bh(&ab->base_lock);
-
- peer = ath12k_peer_find_by_id(ab, peer_id);
- if (!peer) {
- ath12k_warn(ab, "peer-unmap-event: unknown peer id %d\n",
- peer_id);
- goto exit;
- }
-
- ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "htt peer unmap vdev %d peer %pM id %d\n",
- peer->vdev_id, peer->addr, peer_id);
-
- list_del(&peer->list);
- kfree(peer);
- wake_up(&ab->peer_mapping_wq);
-
-exit:
- spin_unlock_bh(&ab->base_lock);
-}
-
-void ath12k_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_id,
- u8 *mac_addr, u16 ast_hash, u16 hw_peer_id)
-{
- struct ath12k_peer *peer;
-
- spin_lock_bh(&ab->base_lock);
- peer = ath12k_peer_find(ab, vdev_id, mac_addr);
- if (!peer) {
- peer = kzalloc(sizeof(*peer), GFP_ATOMIC);
- if (!peer)
- goto exit;
-
- peer->vdev_id = vdev_id;
- peer->peer_id = peer_id;
- peer->ast_hash = ast_hash;
- peer->hw_peer_id = hw_peer_id;
- ether_addr_copy(peer->addr, mac_addr);
- list_add(&peer->list, &ab->peers);
- wake_up(&ab->peer_mapping_wq);
- }
-
- ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "htt peer map vdev %d peer %pM id %d\n",
- vdev_id, mac_addr, peer_id);
-
-exit:
- spin_unlock_bh(&ab->base_lock);
-}
-
-static int ath12k_wait_for_peer_common(struct ath12k_base *ab, int vdev_id,
- const u8 *addr, bool expect_mapped)
+static int ath12k_wait_for_dp_link_peer_common(struct ath12k_base *ab, int vdev_id,
+ const u8 *addr, bool expect_mapped)
{
int ret;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
ret = wait_event_timeout(ab->peer_mapping_wq, ({
bool mapped;
- spin_lock_bh(&ab->base_lock);
- mapped = !!ath12k_peer_find(ab, vdev_id, addr);
- spin_unlock_bh(&ab->base_lock);
+ spin_lock_bh(&dp->dp_lock);
+ mapped = !!ath12k_dp_link_peer_find_by_vdev_and_addr(dp,
+ vdev_id,
+ addr);
+ spin_unlock_bh(&dp->dp_lock);
(mapped == expect_mapped ||
test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags));
@@ -219,30 +36,30 @@ static int ath12k_wait_for_peer_common(struct ath12k_base *ab, int vdev_id,
void ath12k_peer_cleanup(struct ath12k *ar, u32 vdev_id)
{
- struct ath12k_peer *peer, *tmp;
+ struct ath12k_dp_link_peer *peer, *tmp;
struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
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) {
+ spin_lock_bh(&dp->dp_lock);
+ list_for_each_entry_safe(peer, tmp, &dp->peers, list) {
if (peer->vdev_id != vdev_id)
continue;
ath12k_warn(ab, "removing stale peer %pM from vdev_id %d\n",
peer->addr, vdev_id);
- list_del(&peer->list);
- kfree(peer);
+ ath12k_dp_link_peer_free(peer);
ar->num_peers--;
}
- spin_unlock_bh(&ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
}
static int ath12k_wait_for_peer_deleted(struct ath12k *ar, int vdev_id, const u8 *addr)
{
- return ath12k_wait_for_peer_common(ar->ab, vdev_id, addr, false);
+ return ath12k_wait_for_dp_link_peer_common(ar->ab, vdev_id, addr, false);
}
int ath12k_wait_for_peer_delete_done(struct ath12k *ar, u32 vdev_id,
@@ -293,6 +110,10 @@ int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr)
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+ ath12k_dp_link_peer_unassign(ath12k_ab_to_dp(ar->ab),
+ &(ath12k_ar_to_ah(ar)->dp_hw), vdev_id,
+ addr, ar->hw_link_id);
+
ret = ath12k_peer_delete_send(ar, vdev_id, addr);
if (ret)
return ret;
@@ -308,7 +129,7 @@ int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr)
static int ath12k_wait_for_peer_created(struct ath12k *ar, int vdev_id, const u8 *addr)
{
- return ath12k_wait_for_peer_common(ar->ab, vdev_id, addr, true);
+ return ath12k_wait_for_dp_link_peer_common(ar->ab, vdev_id, addr, true);
}
int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
@@ -316,28 +137,34 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
struct ath12k_wmi_peer_create_arg *arg)
{
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ath12k_dp_link_vif *dp_link_vif;
struct ath12k_link_sta *arsta;
u8 link_id = arvif->link_id;
- struct ath12k_peer *peer;
+ struct ath12k_dp_link_peer *peer;
struct ath12k_sta *ahsta;
u16 ml_peer_id;
int ret;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ar->ab);
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+ dp_link_vif = ath12k_dp_vif_to_dp_link_vif(&ahvif->dp_vif, link_id);
+
if (ar->num_peers > (ar->max_num_peers - 1)) {
ath12k_warn(ar->ab,
"failed to create peer due to insufficient peer entry resource in firmware\n");
return -ENOBUFS;
}
- spin_lock_bh(&ar->ab->base_lock);
- peer = ath12k_peer_find_by_pdev_idx(ar->ab, ar->pdev_idx, arg->peer_addr);
+ spin_lock_bh(&dp->dp_lock);
+ peer = ath12k_dp_link_peer_find_by_pdev_and_addr(dp, ar->pdev_idx,
+ arg->peer_addr);
if (peer) {
- spin_unlock_bh(&ar->ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
return -EINVAL;
}
- spin_unlock_bh(&ar->ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
ret = ath12k_wmi_send_peer_create_cmd(ar, arg);
if (ret) {
@@ -352,11 +179,12 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
if (ret)
return ret;
- spin_lock_bh(&ar->ab->base_lock);
+ spin_lock_bh(&dp->dp_lock);
- peer = ath12k_peer_find(ar->ab, arg->vdev_id, arg->peer_addr);
+ peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arg->vdev_id,
+ arg->peer_addr);
if (!peer) {
- spin_unlock_bh(&ar->ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
ath12k_warn(ar->ab, "failed to find peer %pM on vdev %i after creation\n",
arg->peer_addr, arg->vdev_id);
@@ -382,13 +210,10 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
peer->sta = sta;
if (vif->type == NL80211_IFTYPE_STATION) {
- arvif->ast_hash = peer->ast_hash;
- arvif->ast_idx = peer->hw_peer_id;
+ dp_link_vif->ast_hash = peer->ast_hash;
+ dp_link_vif->ast_idx = peer->hw_peer_id;
}
- if (vif->type == NL80211_IFTYPE_AP)
- peer->ucast_ra_only = true;
-
if (sta) {
ahsta = ath12k_sta_to_ahsta(sta);
arsta = wiphy_dereference(ath12k_ar_to_hw(ar)->wiphy,
@@ -412,17 +237,22 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
}
}
- peer->sec_type = HAL_ENCRYPT_TYPE_OPEN;
- peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN;
-
ar->num_peers++;
- spin_unlock_bh(&ar->ab->base_lock);
+ spin_unlock_bh(&dp->dp_lock);
- return 0;
+ if (arvif->link_id < IEEE80211_MLD_MAX_NUM_LINKS) {
+ ret = ath12k_dp_link_peer_assign(ath12k_ab_to_dp(ar->ab),
+ &(ath12k_ar_to_ah(ar)->dp_hw),
+ arvif->vdev_id, sta,
+ (u8 *)arg->peer_addr, link_id,
+ ar->hw_link_id);
+ }
+
+ return ret;
}
-static u16 ath12k_peer_ml_alloc(struct ath12k_hw *ah)
+u16 ath12k_peer_ml_alloc(struct ath12k_hw *ah)
{
u16 ml_peer_id;
@@ -442,68 +272,6 @@ static u16 ath12k_peer_ml_alloc(struct ath12k_hw *ah)
return ml_peer_id;
}
-int ath12k_peer_ml_create(struct ath12k_hw *ah, struct ieee80211_sta *sta)
-{
- struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
- struct ath12k_ml_peer *ml_peer;
-
- lockdep_assert_wiphy(ah->hw->wiphy);
-
- if (!sta->mlo)
- return -EINVAL;
-
- ml_peer = ath12k_peer_ml_find(ah, sta->addr);
- if (ml_peer) {
- ath12k_hw_warn(ah, "ML peer %d exists already, unable to add new entry for %pM",
- ml_peer->id, sta->addr);
- return -EEXIST;
- }
-
- ml_peer = kzalloc(sizeof(*ml_peer), GFP_ATOMIC);
- if (!ml_peer)
- return -ENOMEM;
-
- ahsta->ml_peer_id = ath12k_peer_ml_alloc(ah);
-
- if (ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID) {
- ath12k_hw_warn(ah, "unable to allocate ML peer id for sta %pM",
- sta->addr);
- kfree(ml_peer);
- return -ENOMEM;
- }
-
- ether_addr_copy(ml_peer->addr, sta->addr);
- ml_peer->id = ahsta->ml_peer_id;
- list_add(&ml_peer->list, &ah->ml_peers);
-
- return 0;
-}
-
-int ath12k_peer_ml_delete(struct ath12k_hw *ah, struct ieee80211_sta *sta)
-{
- struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
- struct ath12k_ml_peer *ml_peer;
-
- lockdep_assert_wiphy(ah->hw->wiphy);
-
- if (!sta->mlo)
- return -EINVAL;
-
- clear_bit(ahsta->ml_peer_id, ah->free_ml_peer_id_map);
- ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
-
- ml_peer = ath12k_peer_ml_find(ah, sta->addr);
- if (!ml_peer) {
- ath12k_hw_warn(ah, "ML peer for %pM not found", sta->addr);
- return -EINVAL;
- }
-
- list_del(&ml_peer->list);
- kfree(ml_peer);
-
- return 0;
-}
-
int ath12k_peer_mlo_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_sta *ahsta)
{
struct ieee80211_sta *sta = ath12k_ahsta_to_sta(ahsta);
@@ -536,6 +304,11 @@ int ath12k_peer_mlo_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_st
ath12k_dp_peer_cleanup(ar, arvif->vdev_id, arsta->addr);
+ ath12k_dp_link_peer_unassign(ath12k_ab_to_dp(ar->ab),
+ &(ath12k_ar_to_ah(ar)->dp_hw),
+ arvif->vdev_id, arsta->addr,
+ ar->hw_link_id);
+
ret = ath12k_peer_delete_send(ar, arvif->vdev_id, arsta->addr);
if (ret) {
ath12k_warn(ar->ab,
@@ -568,3 +341,119 @@ int ath12k_peer_mlo_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_st
return err_ret;
}
+
+static int ath12k_link_sta_rhash_insert(struct ath12k_base *ab,
+ struct ath12k_link_sta *arsta)
+{
+ struct ath12k_link_sta *tmp;
+
+ lockdep_assert_held(&ab->base_lock);
+
+ tmp = rhashtable_lookup_get_insert_fast(ab->rhead_sta_addr, &arsta->rhash_addr,
+ ab->rhash_sta_addr_param);
+ if (!tmp)
+ return 0;
+ else if (IS_ERR(tmp))
+ return PTR_ERR(tmp);
+ else
+ return -EEXIST;
+}
+
+static int ath12k_link_sta_rhash_remove(struct ath12k_base *ab,
+ struct ath12k_link_sta *arsta)
+{
+ int ret;
+
+ lockdep_assert_held(&ab->base_lock);
+
+ ret = rhashtable_remove_fast(ab->rhead_sta_addr, &arsta->rhash_addr,
+ ab->rhash_sta_addr_param);
+ if (ret && ret != -ENOENT)
+ return ret;
+
+ return 0;
+}
+
+int ath12k_link_sta_rhash_add(struct ath12k_base *ab,
+ struct ath12k_link_sta *arsta)
+{
+ int ret;
+
+ lockdep_assert_held(&ab->base_lock);
+
+ ret = ath12k_link_sta_rhash_insert(ab, arsta);
+ if (ret)
+ ath12k_warn(ab, "failed to add arsta %pM in rhash_addr ret %d\n",
+ arsta->addr, ret);
+
+ return ret;
+}
+
+void ath12k_link_sta_rhash_delete(struct ath12k_base *ab,
+ struct ath12k_link_sta *arsta)
+{
+ /*
+ * Return type of this function is void since there is nothing to be
+ * done in failure case
+ */
+ int ret;
+
+ lockdep_assert_held(&ab->base_lock);
+
+ ret = ath12k_link_sta_rhash_remove(ab, arsta);
+ if (ret)
+ ath12k_warn(ab,
+ "failed to remove arsta %pM in rhash_addr ret %d\n",
+ arsta->addr, ret);
+}
+
+int ath12k_link_sta_rhash_tbl_init(struct ath12k_base *ab)
+{
+ struct rhashtable_params *param;
+ struct rhashtable *rhash_addr_tbl;
+ int ret;
+
+ rhash_addr_tbl = kzalloc(sizeof(*ab->rhead_sta_addr), GFP_KERNEL);
+ if (!rhash_addr_tbl)
+ return -ENOMEM;
+
+ param = &ab->rhash_sta_addr_param;
+
+ param->key_offset = offsetof(struct ath12k_link_sta, addr);
+ param->head_offset = offsetof(struct ath12k_link_sta, rhash_addr);
+ param->key_len = sizeof_field(struct ath12k_link_sta, addr);
+ param->automatic_shrinking = true;
+ param->nelem_hint = ab->num_radios * ath12k_core_get_max_peers_per_radio(ab);
+
+ ret = rhashtable_init(rhash_addr_tbl, param);
+ if (ret) {
+ ath12k_warn(ab, "failed to init peer addr rhash table %d\n",
+ ret);
+ goto err_free;
+ }
+
+ ab->rhead_sta_addr = rhash_addr_tbl;
+
+ return 0;
+
+err_free:
+ kfree(rhash_addr_tbl);
+
+ return ret;
+}
+
+void ath12k_link_sta_rhash_tbl_destroy(struct ath12k_base *ab)
+{
+ rhashtable_destroy(ab->rhead_sta_addr);
+ kfree(ab->rhead_sta_addr);
+ ab->rhead_sta_addr = NULL;
+}
+
+struct ath12k_link_sta *ath12k_link_sta_find_by_addr(struct ath12k_base *ab,
+ const u8 *addr)
+{
+ lockdep_assert_held(&ab->base_lock);
+
+ return rhashtable_lookup_fast(ab->rhead_sta_addr, addr,
+ ab->rhash_sta_addr_param);
+}
diff --git a/drivers/net/wireless/ath/ath12k/peer.h b/drivers/net/wireless/ath/ath12k/peer.h
index 44afc0b7dd53..49d89796bc46 100644
--- a/drivers/net/wireless/ath/ath12k/peer.h
+++ b/drivers/net/wireless/ath/ath12k/peer.h
@@ -1,84 +1,14 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH12K_PEER_H
#define ATH12K_PEER_H
-#include "dp_rx.h"
+#include "dp_peer.h"
-struct ppdu_user_delayba {
- u16 sw_peer_id;
- u32 info0;
- u16 ru_end;
- u16 ru_start;
- u32 info1;
- u32 rate_flags;
- u32 resp_rate_flags;
-};
-
-#define ATH12K_PEER_ML_ID_VALID BIT(13)
-
-struct ath12k_peer {
- struct list_head list;
- struct ieee80211_sta *sta;
- int vdev_id;
- u8 addr[ETH_ALEN];
- int peer_id;
- u16 ast_hash;
- u8 pdev_idx;
- u16 hw_peer_id;
-
- /* protected by ab->data_lock */
- struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];
- struct ath12k_dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1];
-
- /* Info used in MMIC verification of
- * RX fragments
- */
- struct crypto_shash *tfm_mmic;
- u8 mcast_keyidx;
- u8 ucast_keyidx;
- u16 sec_type;
- u16 sec_type_grp;
- struct ppdu_user_delayba ppdu_stats_delayba;
- bool delayba_flag;
- bool is_authorized;
- bool mlo;
- /* protected by ab->data_lock */
- bool dp_setup_done;
-
- u16 ml_id;
-
- /* any other ML info common for all partners can be added
- * here and would be same for all partner peers.
- */
- u8 ml_addr[ETH_ALEN];
-
- /* To ensure only certain work related to dp is done once */
- bool primary_link;
-
- /* for reference to ath12k_link_sta */
- u8 link_id;
- bool ucast_ra_only;
-};
-
-struct ath12k_ml_peer {
- struct list_head list;
- u8 addr[ETH_ALEN];
- u16 id;
-};
-
-void ath12k_peer_unmap_event(struct ath12k_base *ab, u16 peer_id);
-void ath12k_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_id,
- u8 *mac_addr, u16 ast_hash, u16 hw_peer_id);
-struct ath12k_peer *ath12k_peer_find(struct ath12k_base *ab, int vdev_id,
- const u8 *addr);
-struct ath12k_peer *ath12k_peer_find_by_addr(struct ath12k_base *ab,
- const u8 *addr);
-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_link_vif *arvif,
@@ -86,38 +16,14 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
struct ath12k_wmi_peer_create_arg *arg);
int ath12k_wait_for_peer_delete_done(struct ath12k *ar, u32 vdev_id,
const u8 *addr);
-bool ath12k_peer_exist_by_vdev_id(struct ath12k_base *ab, int vdev_id);
-struct ath12k_peer *ath12k_peer_find_by_ast(struct ath12k_base *ab, int ast_hash);
-int ath12k_peer_ml_create(struct ath12k_hw *ah, struct ieee80211_sta *sta);
-int ath12k_peer_ml_delete(struct ath12k_hw *ah, struct ieee80211_sta *sta);
int ath12k_peer_mlo_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_sta *ahsta);
struct ath12k_ml_peer *ath12k_peer_ml_find(struct ath12k_hw *ah,
const u8 *addr);
-static inline
-struct ath12k_link_sta *ath12k_peer_get_link_sta(struct ath12k_base *ab,
- struct ath12k_peer *peer)
-{
- struct ath12k_sta *ahsta;
- struct ath12k_link_sta *arsta;
-
- if (!peer->sta)
- return NULL;
-
- ahsta = ath12k_sta_to_ahsta(peer->sta);
- if (peer->ml_id & ATH12K_PEER_ML_ID_VALID) {
- if (!(ahsta->links_map & BIT(peer->link_id))) {
- ath12k_warn(ab, "peer %pM id %d link_id %d can't found in STA link_map 0x%x\n",
- peer->addr, peer->peer_id, peer->link_id,
- ahsta->links_map);
- return NULL;
- }
- arsta = rcu_dereference(ahsta->link[peer->link_id]);
- if (!arsta)
- return NULL;
- } else {
- arsta = &ahsta->deflink;
- }
- return arsta;
-}
-
+int ath12k_link_sta_rhash_tbl_init(struct ath12k_base *ab);
+void ath12k_link_sta_rhash_tbl_destroy(struct ath12k_base *ab);
+void ath12k_link_sta_rhash_delete(struct ath12k_base *ab, struct ath12k_link_sta *arsta);
+int ath12k_link_sta_rhash_add(struct ath12k_base *ab, struct ath12k_link_sta *arsta);
+struct ath12k_link_sta *ath12k_link_sta_find_by_addr(struct ath12k_base *ab,
+ const u8 *addr);
+u16 ath12k_peer_ml_alloc(struct ath12k_hw *ah);
#endif /* _PEER_H_ */
diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c
index b7c48b6706df..cfde4147c8fc 100644
--- a/drivers/net/wireless/ath/ath12k/qmi.c
+++ b/drivers/net/wireless/ath/ath12k/qmi.c
@@ -1623,6 +1623,47 @@ static const struct qmi_elem_info qmi_wlanfw_m3_info_resp_msg_v01_ei[] = {
},
};
+static const struct qmi_elem_info qmi_wlanfw_aux_uc_info_req_msg_v01_ei[] = {
+ {
+ .data_type = QMI_UNSIGNED_8_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u64),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct qmi_wlanfw_aux_uc_info_req_msg_v01, addr),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u32),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct qmi_wlanfw_aux_uc_info_req_msg_v01, size),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .array_type = NO_ARRAY,
+ .tlv_type = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+static const struct qmi_elem_info qmi_wlanfw_aux_uc_info_resp_msg_v01_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct qmi_wlanfw_aux_uc_info_resp_msg_v01, resp),
+ .ei_array = qmi_response_type_v01_ei,
+ },
+ {
+ .data_type = QMI_EOTI,
+ .array_type = NO_ARRAY,
+ .tlv_type = QMI_COMMON_TLV_TYPE,
+ },
+};
+
static const struct qmi_elem_info qmi_wlanfw_ce_tgt_pipe_cfg_s_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_4_BYTE,
@@ -2609,6 +2650,7 @@ static int ath12k_qmi_alloc_target_mem_chunk(struct ath12k_base *ab)
case M3_DUMP_REGION_TYPE:
case PAGEABLE_MEM_REGION_TYPE:
case CALDB_MEM_REGION_TYPE:
+ case LPASS_SHARED_V01_REGION_TYPE:
ret = ath12k_qmi_alloc_chunk(ab, chunk);
if (ret)
goto err;
@@ -3236,6 +3278,131 @@ out:
return ret;
}
+static void ath12k_qmi_aux_uc_free(struct ath12k_base *ab)
+{
+ struct m3_mem_region *aux_uc_mem = &ab->qmi.aux_uc_mem;
+
+ if (!aux_uc_mem->vaddr)
+ return;
+
+ dma_free_coherent(ab->dev, aux_uc_mem->total_size,
+ aux_uc_mem->vaddr, aux_uc_mem->paddr);
+ aux_uc_mem->vaddr = NULL;
+ aux_uc_mem->total_size = 0;
+ aux_uc_mem->size = 0;
+}
+
+static int ath12k_qmi_aux_uc_load(struct ath12k_base *ab)
+{
+ struct m3_mem_region *aux_uc_mem = &ab->qmi.aux_uc_mem;
+ const struct firmware *fw = NULL;
+ const void *aux_uc_data;
+ char path[100];
+ size_t aux_uc_len;
+ int ret;
+
+ if (ab->fw.aux_uc_data && ab->fw.aux_uc_len > 0) {
+ /* firmware-N.bin had a aux_uc firmware file so use that */
+ aux_uc_data = ab->fw.aux_uc_data;
+ aux_uc_len = ab->fw.aux_uc_len;
+ } else {
+ /*
+ * No aux_uc file in firmware-N.bin so try to request old
+ * separate aux_ucode.bin.
+ */
+ fw = ath12k_core_firmware_request(ab, ATH12K_AUX_UC_FILE);
+ if (IS_ERR(fw)) {
+ ret = PTR_ERR(fw);
+ ath12k_core_create_firmware_path(ab, ATH12K_AUX_UC_FILE,
+ path, sizeof(path));
+ ath12k_err(ab, "failed to load %s: %d\n", path, ret);
+ return ret;
+ }
+
+ aux_uc_data = fw->data;
+ aux_uc_len = fw->size;
+ }
+
+ /* In recovery/resume cases, AUX_UC buffer is not freed, try to reuse that */
+ if (aux_uc_mem->vaddr) {
+ if (aux_uc_mem->total_size >= aux_uc_len)
+ goto copy;
+
+ /* Old buffer is too small, free and reallocate */
+ ath12k_qmi_aux_uc_free(ab);
+ }
+
+ aux_uc_mem->vaddr = dma_alloc_coherent(ab->dev, aux_uc_len,
+ &aux_uc_mem->paddr, GFP_KERNEL);
+ if (!aux_uc_mem->vaddr) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ aux_uc_mem->total_size = aux_uc_len;
+
+copy:
+ memcpy(aux_uc_mem->vaddr, aux_uc_data, aux_uc_len);
+ aux_uc_mem->size = aux_uc_len;
+
+ ret = 0;
+
+out:
+ release_firmware(fw);
+
+ return ret;
+}
+
+static noinline_for_stack
+int ath12k_qmi_wlanfw_aux_uc_info_send(struct ath12k_base *ab)
+{
+ struct m3_mem_region *aux_uc_mem = &ab->qmi.aux_uc_mem;
+ struct qmi_wlanfw_aux_uc_info_req_msg_v01 req = {};
+ struct qmi_wlanfw_aux_uc_info_resp_msg_v01 resp = {};
+ struct qmi_txn txn;
+ int ret = 0;
+
+ ret = ath12k_qmi_aux_uc_load(ab);
+ if (ret) {
+ ath12k_err(ab, "failed to load aux_uc firmware: %d", ret);
+ return ret;
+ }
+
+ req.addr = aux_uc_mem->paddr;
+ req.size = aux_uc_mem->size;
+
+ ret = qmi_txn_init(&ab->qmi.handle, &txn,
+ qmi_wlanfw_aux_uc_info_resp_msg_v01_ei, &resp);
+ if (ret < 0)
+ goto out;
+
+ ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
+ QMI_WLANFW_AUX_UC_INFO_REQ_V01,
+ QMI_WLANFW_AUX_UC_INFO_REQ_MSG_V01_MAX_MSG_LEN,
+ qmi_wlanfw_aux_uc_info_req_msg_v01_ei, &req);
+ if (ret < 0) {
+ qmi_txn_cancel(&txn);
+ ath12k_warn(ab, "qmi failed to send AUX_UC information request, err = %d\n",
+ ret);
+ goto out;
+ }
+
+ ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH12K_QMI_WLANFW_TIMEOUT_MS));
+ if (ret < 0) {
+ ath12k_warn(ab, "qmi failed AUX_UC information request %d\n", ret);
+ goto out;
+ }
+
+ if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
+ ath12k_warn(ab, "qmi AUX_UC info request failed, result: %d, err: %d\n",
+ resp.resp.result, resp.resp.error);
+ ret = -EINVAL;
+ goto out;
+ }
+out:
+ return ret;
+}
+
static int ath12k_qmi_wlanfw_mode_send(struct ath12k_base *ab,
u32 mode)
{
@@ -3600,6 +3767,7 @@ static noinline_for_stack
int ath12k_qmi_event_load_bdf(struct ath12k_qmi *qmi)
{
struct ath12k_base *ab = qmi->ab;
+ const struct ath12k_hw_params *hw_params = ab->hw_params;
int ret;
ret = ath12k_qmi_request_target_cap(ab);
@@ -3620,7 +3788,7 @@ int ath12k_qmi_event_load_bdf(struct ath12k_qmi *qmi)
return ret;
}
- if (ab->hw_params->download_calib) {
+ if (hw_params->download_calib) {
ret = ath12k_qmi_load_bdf_qmi(ab, ATH12K_QMI_BDF_TYPE_CALIBRATION);
if (ret < 0)
ath12k_warn(ab, "qmi failed to load calibrated data :%d\n", ret);
@@ -3632,6 +3800,14 @@ int ath12k_qmi_event_load_bdf(struct ath12k_qmi *qmi)
return ret;
}
+ if (hw_params->fw.download_aux_ucode) {
+ ret = ath12k_qmi_wlanfw_aux_uc_info_send(ab);
+ if (ret < 0) {
+ ath12k_warn(ab, "qmi failed to send aux_uc info req: %d\n", ret);
+ return ret;
+ }
+ }
+
return ret;
}
@@ -3905,6 +4081,7 @@ void ath12k_qmi_deinit_service(struct ath12k_base *ab)
qmi_handle_release(&ab->qmi.handle);
cancel_work_sync(&ab->qmi.event_work);
destroy_workqueue(ab->qmi.event_wq);
+ ath12k_qmi_aux_uc_free(ab);
ath12k_qmi_m3_free(ab);
ath12k_qmi_free_target_mem_chunk(ab);
ab->qmi.ab = NULL;
@@ -3913,5 +4090,6 @@ void ath12k_qmi_deinit_service(struct ath12k_base *ab)
void ath12k_qmi_free_resource(struct ath12k_base *ab)
{
ath12k_qmi_free_target_mem_chunk(ab);
+ ath12k_qmi_aux_uc_free(ab);
ath12k_qmi_m3_free(ab);
}
diff --git a/drivers/net/wireless/ath/ath12k/qmi.h b/drivers/net/wireless/ath/ath12k/qmi.h
index 7a88268aa1e9..b5a4a01391cb 100644
--- a/drivers/net/wireless/ath/ath12k/qmi.h
+++ b/drivers/net/wireless/ath/ath12k/qmi.h
@@ -154,6 +154,7 @@ struct ath12k_qmi {
u8 num_radios;
struct target_info target;
struct m3_mem_region m3_mem;
+ struct m3_mem_region aux_uc_mem;
unsigned int service_ins_id;
struct dev_mem_info dev_mem[ATH12K_QMI_WLFW_MAX_DEV_MEM_NUM_V01];
};
@@ -178,6 +179,7 @@ enum ath12k_qmi_target_mem {
CALDB_MEM_REGION_TYPE = 0x4,
MLO_GLOBAL_MEM_REGION_TYPE = 0x8,
PAGEABLE_MEM_REGION_TYPE = 0x9,
+ LPASS_SHARED_V01_REGION_TYPE = 0xb,
};
enum qmi_wlanfw_host_build_type {
@@ -202,6 +204,7 @@ enum ath12k_qmi_cnss_feature {
CNSS_FEATURE_MIN_ENUM_VAL_V01 = INT_MIN,
CNSS_QDSS_CFG_MISS_V01 = 3,
CNSS_PCIE_PERST_NO_PULL_V01 = 4,
+ CNSS_AUX_UC_SUPPORT_V01 = 6,
CNSS_MAX_FEATURE_V01 = 64,
CNSS_FEATURE_MAX_ENUM_VAL_V01 = INT_MAX,
};
@@ -540,6 +543,19 @@ struct qmi_wlanfw_m3_info_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
+#define QMI_WLANFW_AUX_UC_INFO_REQ_MSG_V01_MAX_MSG_LEN 18
+#define QMI_WLANFW_AUX_UC_INFO_RESP_MSG_V01_MAX_MSG_LEN 7
+#define QMI_WLANFW_AUX_UC_INFO_REQ_V01 0x005A
+
+struct qmi_wlanfw_aux_uc_info_req_msg_v01 {
+ u64 addr;
+ u32 size;
+};
+
+struct qmi_wlanfw_aux_uc_info_resp_msg_v01 {
+ struct qmi_response_type_v01 resp;
+};
+
#define QMI_WLANFW_WLAN_MODE_REQ_MSG_V01_MAX_LEN 11
#define QMI_WLANFW_WLAN_MODE_RESP_MSG_V01_MAX_LEN 7
#define QMI_WLANFW_WLAN_CFG_REQ_MSG_V01_MAX_LEN 803
diff --git a/drivers/net/wireless/ath/ath12k/testmode.c b/drivers/net/wireless/ath/ath12k/testmode.c
index fb6af7ccf71f..05a65970c862 100644
--- a/drivers/net/wireless/ath/ath12k/testmode.c
+++ b/drivers/net/wireless/ath/ath12k/testmode.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-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include "testmode.h"
@@ -393,3 +393,4 @@ int ath12k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
return -EOPNOTSUPP;
}
}
+EXPORT_SYMBOL(ath12k_tm_cmd);
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/Makefile b/drivers/net/wireless/ath/ath12k/wifi7/Makefile
new file mode 100644
index 000000000000..45b561cdba4b
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/Makefile
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: BSD-3-Clause-Clear
+obj-$(CONFIG_ATH12K) += ath12k_wifi7.o
+ath12k_wifi7-y += core.o \
+ pci.o \
+ wmi.o \
+ mhi.o \
+ ce.o \
+ hw.o \
+ hal_tx.o \
+ hal_rx.o \
+ dp_rx.o \
+ dp_tx.o \
+ dp.o \
+ dp_mon.o \
+ hal.o \
+ hal_qcn9274.o \
+ hal_wcn7850.o \
+ hal_qcc2072.o
+
+ath12k_wifi7-$(CONFIG_ATH12K_AHB) += ahb.o
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/ahb.c b/drivers/net/wireless/ath/ath12k/wifi7/ahb.c
new file mode 100644
index 000000000000..a6c5f7689edd
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/ahb.c
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/soc/qcom/mdt_loader.h>
+#include "../ahb.h"
+#include "ahb.h"
+#include "../debug.h"
+#include "../hif.h"
+#include "hw.h"
+#include "dp.h"
+#include "core.h"
+
+static const struct of_device_id ath12k_wifi7_ahb_of_match[] = {
+ { .compatible = "qcom,ipq5332-wifi",
+ .data = (void *)ATH12K_HW_IPQ5332_HW10,
+ },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, ath12k_wifi7_ahb_of_match);
+
+static int ath12k_wifi7_ahb_probe(struct platform_device *pdev)
+{
+ struct ath12k_ahb *ab_ahb;
+ enum ath12k_hw_rev hw_rev;
+ struct ath12k_base *ab;
+ int ret;
+
+ ab = platform_get_drvdata(pdev);
+ ab_ahb = ath12k_ab_to_ahb(ab);
+
+ hw_rev = (enum ath12k_hw_rev)(kernel_ulong_t)of_device_get_match_data(&pdev->dev);
+ switch (hw_rev) {
+ case ATH12K_HW_IPQ5332_HW10:
+ ab_ahb->userpd_id = ATH12K_IPQ5332_USERPD_ID;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ ab->target_mem_mode = ATH12K_QMI_MEMORY_MODE_DEFAULT;
+ ab->hw_rev = hw_rev;
+
+ ret = ath12k_wifi7_hw_init(ab);
+ if (ret) {
+ ath12k_err(ab, "WiFi-7 hw_init for AHB failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct ath12k_ahb_driver ath12k_wifi7_ahb_driver = {
+ .name = "ath12k_wifi7_ahb",
+ .id_table = ath12k_wifi7_ahb_of_match,
+ .ops.probe = ath12k_wifi7_ahb_probe,
+ .ops.arch_init = ath12k_wifi7_arch_init,
+ .ops.arch_deinit = ath12k_wifi7_arch_deinit,
+};
+
+int ath12k_wifi7_ahb_init(void)
+{
+ return ath12k_ahb_register_driver(ATH12K_DEVICE_FAMILY_WIFI7,
+ &ath12k_wifi7_ahb_driver);
+}
+
+void ath12k_wifi7_ahb_exit(void)
+{
+ ath12k_ahb_unregister_driver(ATH12K_DEVICE_FAMILY_WIFI7);
+}
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/ahb.h b/drivers/net/wireless/ath/ath12k/wifi7/ahb.h
new file mode 100644
index 000000000000..5974c7cad69a
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/ahb.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+#ifndef ATH12K_AHB_WIFI7_H
+#define ATH12K_AHB_WIFI7_H
+
+#ifdef CONFIG_ATH12K_AHB
+int ath12k_wifi7_ahb_init(void);
+void ath12k_wifi7_ahb_exit(void);
+#else
+static inline int ath12k_wifi7_ahb_init(void)
+{
+ return 0;
+}
+
+static inline void ath12k_wifi7_ahb_exit(void) {}
+#endif
+#endif /* ATH12K_AHB_WIFI7_H */
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/ce.c b/drivers/net/wireless/ath/ath12k/wifi7/ce.c
new file mode 100644
index 000000000000..952d6c39c333
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/ce.c
@@ -0,0 +1,973 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/bitfield.h>
+
+#include "../core.h"
+#include "../ce.h"
+#include "ce.h"
+#include "../dp_rx.h"
+
+/* Copy Engine (CE) configs for QCN9274 */
+/* Target firmware's Copy Engine configuration. */
+const struct ce_pipe_config ath12k_wifi7_target_ce_config_wlan_qcn9274[] = {
+ /* CE0: host->target HTC control and raw streams */
+ {
+ .pipenum = __cpu_to_le32(0),
+ .pipedir = __cpu_to_le32(PIPEDIR_OUT),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE1: target->host HTT + HTC control */
+ {
+ .pipenum = __cpu_to_le32(1),
+ .pipedir = __cpu_to_le32(PIPEDIR_IN),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE2: target->host WMI */
+ {
+ .pipenum = __cpu_to_le32(2),
+ .pipedir = __cpu_to_le32(PIPEDIR_IN),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE3: host->target WMI (mac0) */
+ {
+ .pipenum = __cpu_to_le32(3),
+ .pipedir = __cpu_to_le32(PIPEDIR_OUT),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE4: host->target HTT */
+ {
+ .pipenum = __cpu_to_le32(4),
+ .pipedir = __cpu_to_le32(PIPEDIR_OUT),
+ .nentries = __cpu_to_le32(256),
+ .nbytes_max = __cpu_to_le32(256),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE5: target->host Pktlog */
+ {
+ .pipenum = __cpu_to_le32(5),
+ .pipedir = __cpu_to_le32(PIPEDIR_IN),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE6: Reserved for target autonomous hif_memcpy */
+ {
+ .pipenum = __cpu_to_le32(6),
+ .pipedir = __cpu_to_le32(PIPEDIR_INOUT),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(16384),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE7: host->target WMI (mac1) */
+ {
+ .pipenum = __cpu_to_le32(7),
+ .pipedir = __cpu_to_le32(PIPEDIR_OUT),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE8: Reserved for target autonomous hif_memcpy */
+ {
+ .pipenum = __cpu_to_le32(8),
+ .pipedir = __cpu_to_le32(PIPEDIR_INOUT),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(16384),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE9, 10 and 11: Reserved for MHI */
+
+ /* CE12: Target CV prefetch */
+ {
+ .pipenum = __cpu_to_le32(12),
+ .pipedir = __cpu_to_le32(PIPEDIR_OUT),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE13: Target CV prefetch */
+ {
+ .pipenum = __cpu_to_le32(13),
+ .pipedir = __cpu_to_le32(PIPEDIR_OUT),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE14: WMI logging/CFR/Spectral/Radar */
+ {
+ .pipenum = __cpu_to_le32(14),
+ .pipedir = __cpu_to_le32(PIPEDIR_IN),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE15: Reserved */
+};
+
+/* Map from service/endpoint to Copy Engine.
+ * This table is derived from the CE_PCI TABLE, above.
+ * It is passed to the Target at startup for use by firmware.
+ * Pipe direction:
+ * PIPEDIR_OUT = UL = host -> target
+ * PIPEDIR_IN = DL = target -> host
+ */
+const struct service_to_pipe
+ath12k_wifi7_target_service_to_ce_map_wlan_qcn9274[] = {
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VO),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(3),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VO),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BK),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(3),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BK),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BE),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(3),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BE),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VI),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(3),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VI),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(3),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_RSVD_CTRL),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(0),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_RSVD_CTRL),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(1),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_TEST_RAW_STREAMS),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(0),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_TEST_RAW_STREAMS),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(1),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_HTT_DATA_MSG),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(4),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_HTT_DATA_MSG),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(1),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL_MAC1),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(7),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL_MAC1),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_PKT_LOG),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(5),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL_DIAG),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(14),
+ },
+
+ /* (Additions here) */
+
+ { /* must be last */
+ __cpu_to_le32(0),
+ __cpu_to_le32(0),
+ __cpu_to_le32(0),
+ },
+};
+
+const struct ce_attr ath12k_wifi7_host_ce_config_qcn9274[] = {
+ /* CE0: host->target HTC control and raw streams */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 16,
+ .src_sz_max = 2048,
+ .dest_nentries = 0,
+ },
+
+ /* CE1: target->host HTT + HTC control */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
+ .dest_nentries = 512,
+ .recv_cb = ath12k_htc_rx_completion_handler,
+ },
+
+ /* CE2: target->host WMI */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
+ .dest_nentries = 128,
+ .recv_cb = ath12k_htc_rx_completion_handler,
+ },
+
+ /* CE3: host->target WMI (mac0) */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 32,
+ .src_sz_max = 2048,
+ .dest_nentries = 0,
+ },
+
+ /* CE4: host->target HTT */
+ {
+ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
+ .src_nentries = 2048,
+ .src_sz_max = 256,
+ .dest_nentries = 0,
+ },
+
+ /* CE5: target->host pktlog */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
+ .dest_nentries = 512,
+ .recv_cb = ath12k_dp_htt_htc_t2h_msg_handler,
+ },
+
+ /* CE6: target autonomous hif_memcpy */
+ {
+ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
+ .src_nentries = 0,
+ .src_sz_max = 0,
+ .dest_nentries = 0,
+ },
+
+ /* CE7: host->target WMI (mac1) */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 32,
+ .src_sz_max = 2048,
+ .dest_nentries = 0,
+ },
+
+ /* CE8: target autonomous hif_memcpy */
+ {
+ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
+ .src_nentries = 0,
+ .src_sz_max = 0,
+ .dest_nentries = 0,
+ },
+
+ /* CE9: MHI */
+ {
+ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
+ .src_nentries = 0,
+ .src_sz_max = 0,
+ .dest_nentries = 0,
+ },
+
+ /* CE10: MHI */
+ {
+ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
+ .src_nentries = 0,
+ .src_sz_max = 0,
+ .dest_nentries = 0,
+ },
+
+ /* CE11: MHI */
+ {
+ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
+ .src_nentries = 0,
+ .src_sz_max = 0,
+ .dest_nentries = 0,
+ },
+
+ /* CE12: CV Prefetch */
+ {
+ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
+ .src_nentries = 0,
+ .src_sz_max = 0,
+ .dest_nentries = 0,
+ },
+
+ /* CE13: CV Prefetch */
+ {
+ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
+ .src_nentries = 0,
+ .src_sz_max = 0,
+ .dest_nentries = 0,
+ },
+
+ /* CE14: target->host dbg log */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
+ .dest_nentries = 512,
+ .recv_cb = ath12k_htc_rx_completion_handler,
+ },
+
+ /* CE15: reserved for future use */
+ {
+ .flags = (CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
+ .src_nentries = 0,
+ .src_sz_max = 0,
+ .dest_nentries = 0,
+ },
+};
+
+/* Copy Engine (CE) configs for WCN7850 */
+/* Target firmware's Copy Engine configuration. */
+const struct ce_pipe_config ath12k_wifi7_target_ce_config_wlan_wcn7850[] = {
+ /* CE0: host->target HTC control and raw streams */
+ {
+ .pipenum = __cpu_to_le32(0),
+ .pipedir = __cpu_to_le32(PIPEDIR_OUT),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE1: target->host HTT + HTC control */
+ {
+ .pipenum = __cpu_to_le32(1),
+ .pipedir = __cpu_to_le32(PIPEDIR_IN),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE2: target->host WMI */
+ {
+ .pipenum = __cpu_to_le32(2),
+ .pipedir = __cpu_to_le32(PIPEDIR_IN),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE3: host->target WMI */
+ {
+ .pipenum = __cpu_to_le32(3),
+ .pipedir = __cpu_to_le32(PIPEDIR_OUT),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE4: host->target HTT */
+ {
+ .pipenum = __cpu_to_le32(4),
+ .pipedir = __cpu_to_le32(PIPEDIR_OUT),
+ .nentries = __cpu_to_le32(256),
+ .nbytes_max = __cpu_to_le32(256),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE5: target->host Pktlog */
+ {
+ .pipenum = __cpu_to_le32(5),
+ .pipedir = __cpu_to_le32(PIPEDIR_IN),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE6: Reserved for target autonomous hif_memcpy */
+ {
+ .pipenum = __cpu_to_le32(6),
+ .pipedir = __cpu_to_le32(PIPEDIR_INOUT),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(16384),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE7 used only by Host */
+ {
+ .pipenum = __cpu_to_le32(7),
+ .pipedir = __cpu_to_le32(PIPEDIR_INOUT_H2H),
+ .nentries = __cpu_to_le32(0),
+ .nbytes_max = __cpu_to_le32(0),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE8 target->host used only by IPA */
+ {
+ .pipenum = __cpu_to_le32(8),
+ .pipedir = __cpu_to_le32(PIPEDIR_INOUT),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(16384),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+ /* CE 9, 10, 11 are used by MHI driver */
+};
+
+const struct service_to_pipe
+ath12k_wifi7_target_service_to_ce_map_wlan_wcn7850[] = {
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VO),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(3),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VO),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BK),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(3),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BK),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BE),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(3),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BE),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VI),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(3),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VI),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(3),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_RSVD_CTRL),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(0),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_RSVD_CTRL),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_HTT_DATA_MSG),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(4),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_HTT_DATA_MSG),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(1),
+ },
+
+ /* (Additions here) */
+
+ { /* must be last */
+ __cpu_to_le32(0),
+ __cpu_to_le32(0),
+ __cpu_to_le32(0),
+ },
+};
+
+const struct ce_attr ath12k_wifi7_host_ce_config_wcn7850[] = {
+ /* CE0: host->target HTC control and raw streams */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 16,
+ .src_sz_max = 2048,
+ .dest_nentries = 0,
+ },
+
+ /* CE1: target->host HTT + HTC control */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
+ .dest_nentries = 512,
+ .recv_cb = ath12k_htc_rx_completion_handler,
+ },
+
+ /* CE2: target->host WMI */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
+ .dest_nentries = 64,
+ .recv_cb = ath12k_htc_rx_completion_handler,
+ },
+
+ /* CE3: host->target WMI (mac0) */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 32,
+ .src_sz_max = 2048,
+ .dest_nentries = 0,
+ },
+
+ /* CE4: host->target HTT */
+ {
+ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
+ .src_nentries = 2048,
+ .src_sz_max = 256,
+ .dest_nentries = 0,
+ },
+
+ /* CE5: target->host pktlog */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 0,
+ .dest_nentries = 0,
+ },
+
+ /* CE6: target autonomous hif_memcpy */
+ {
+ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
+ .src_nentries = 0,
+ .src_sz_max = 0,
+ .dest_nentries = 0,
+ },
+
+ /* CE7: host->target WMI (mac1) */
+ {
+ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
+ .dest_nentries = 0,
+ },
+
+ /* CE8: target autonomous hif_memcpy */
+ {
+ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
+ .src_nentries = 0,
+ .src_sz_max = 0,
+ .dest_nentries = 0,
+ },
+};
+
+/* Copy Engine (CE) configs for IPQ5332 */
+/* Target firmware's Copy Engine configuration. */
+const struct ce_pipe_config ath12k_wifi7_target_ce_config_wlan_ipq5332[] = {
+ /* CE0: host->target HTC control and raw streams */
+ {
+ .pipenum = __cpu_to_le32(0),
+ .pipedir = __cpu_to_le32(PIPEDIR_OUT),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE1: target->host HTT */
+ {
+ .pipenum = __cpu_to_le32(1),
+ .pipedir = __cpu_to_le32(PIPEDIR_IN),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE2: target->host WMI + HTC control */
+ {
+ .pipenum = __cpu_to_le32(2),
+ .pipedir = __cpu_to_le32(PIPEDIR_IN),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE3: host->target WMI */
+ {
+ .pipenum = __cpu_to_le32(3),
+ .pipedir = __cpu_to_le32(PIPEDIR_OUT),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE4: host->target HTT */
+ {
+ .pipenum = __cpu_to_le32(4),
+ .pipedir = __cpu_to_le32(PIPEDIR_OUT),
+ .nentries = __cpu_to_le32(256),
+ .nbytes_max = __cpu_to_le32(256),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE5: Target -> host PKTLOG */
+ {
+ .pipenum = __cpu_to_le32(5),
+ .pipedir = __cpu_to_le32(PIPEDIR_IN),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE6: Reserved for target autonomous HIF_memcpy */
+ {
+ .pipenum = __cpu_to_le32(6),
+ .pipedir = __cpu_to_le32(PIPEDIR_INOUT),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(16384),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE7: Reserved for CV Prefetch */
+ {
+ .pipenum = __cpu_to_le32(7),
+ .pipedir = __cpu_to_le32(PIPEDIR_OUT),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE8: Reserved for target generic HIF memcpy */
+ {
+ .pipenum = __cpu_to_le32(8),
+ .pipedir = __cpu_to_le32(PIPEDIR_INOUT),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(16384),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE9: WMI logging/CFR/Spectral/Radar/ */
+ {
+ .pipenum = __cpu_to_le32(9),
+ .pipedir = __cpu_to_le32(PIPEDIR_IN),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE10: Unused TBD */
+ {
+ .pipenum = __cpu_to_le32(10),
+ .pipedir = __cpu_to_le32(PIPEDIR_NONE),
+ .nentries = __cpu_to_le32(0),
+ .nbytes_max = __cpu_to_le32(0),
+ .flags = __cpu_to_le32(0),
+ .reserved = __cpu_to_le32(0),
+ },
+ /* CE11: Unused TBD */
+ {
+ .pipenum = __cpu_to_le32(11),
+ .pipedir = __cpu_to_le32(PIPEDIR_NONE),
+ .nentries = __cpu_to_le32(0),
+ .nbytes_max = __cpu_to_le32(0),
+ .flags = __cpu_to_le32(0),
+ .reserved = __cpu_to_le32(0),
+ },
+};
+
+const struct service_to_pipe
+ath12k_wifi7_target_service_to_ce_map_wlan_ipq5332[] = {
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VO),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(3),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VO),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BK),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(3),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BK),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BE),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(3),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BE),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VI),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(3),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VI),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(3),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_RSVD_CTRL),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(0),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_RSVD_CTRL),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(1),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_TEST_RAW_STREAMS),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(0),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_TEST_RAW_STREAMS),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(1),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_HTT_DATA_MSG),
+ __cpu_to_le32(PIPEDIR_OUT),
+ __cpu_to_le32(4),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_HTT_DATA_MSG),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(1),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_PKT_LOG),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(5),
+ },
+ {
+ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL_DIAG),
+ __cpu_to_le32(PIPEDIR_IN),
+ __cpu_to_le32(9),
+ },
+ /* (Additions here) */
+
+ { /* must be last */
+ __cpu_to_le32(0),
+ __cpu_to_le32(0),
+ __cpu_to_le32(0),
+ },
+};
+
+const struct ce_attr ath12k_wifi7_host_ce_config_ipq5332[] = {
+ /* CE0: host->target HTC control and raw streams */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 16,
+ .src_sz_max = 2048,
+ .dest_nentries = 0,
+ },
+
+ /* CE1: target->host HTT + HTC control */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
+ .dest_nentries = 512,
+ .recv_cb = ath12k_htc_rx_completion_handler,
+ },
+
+ /* CE2: target->host WMI */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
+ .dest_nentries = 128,
+ .recv_cb = ath12k_htc_rx_completion_handler,
+ },
+
+ /* CE3: host->target WMI */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 32,
+ .src_sz_max = 2048,
+ .dest_nentries = 0,
+ },
+
+ /* CE4: host->target HTT */
+ {
+ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
+ .src_nentries = 2048,
+ .src_sz_max = 256,
+ .dest_nentries = 0,
+ },
+
+ /* CE5: target -> host PKTLOG */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
+ .dest_nentries = 512,
+ .recv_cb = ath12k_dp_htt_htc_t2h_msg_handler,
+ },
+
+ /* CE6: Target autonomous HIF_memcpy */
+ {
+ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
+ .src_nentries = 0,
+ .src_sz_max = 0,
+ .dest_nentries = 0,
+ },
+
+ /* CE7: CV Prefetch */
+ {
+ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
+ .src_nentries = 0,
+ .src_sz_max = 0,
+ .dest_nentries = 0,
+ },
+
+ /* CE8: Target HIF memcpy (Generic HIF memcypy) */
+ {
+ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
+ .src_nentries = 0,
+ .src_sz_max = 0,
+ .dest_nentries = 0,
+ },
+
+ /* CE9: WMI logging/CFR/Spectral/Radar */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
+ .dest_nentries = 128,
+ },
+
+ /* CE10: Unused */
+ {
+ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
+ .src_nentries = 0,
+ .src_sz_max = 0,
+ .dest_nentries = 0,
+ },
+
+ /* CE11: Unused */
+ {
+ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
+ .src_nentries = 0,
+ .src_sz_max = 0,
+ .dest_nentries = 0,
+ },
+};
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/ce.h b/drivers/net/wireless/ath/ath12k/wifi7/ce.h
new file mode 100644
index 000000000000..369a14472913
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/ce.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef ATH12K_WIFI7_CE_H
+#define ATH12K_WIFI7_CE_H
+
+extern const struct ce_pipe_config ath12k_wifi7_target_ce_config_wlan_qcn9274[];
+extern const struct ce_pipe_config ath12k_wifi7_target_ce_config_wlan_wcn7850[];
+extern const struct ce_pipe_config ath12k_wifi7_target_ce_config_wlan_ipq5332[];
+
+extern const struct service_to_pipe ath12k_wifi7_target_service_to_ce_map_wlan_qcn9274[];
+extern const struct service_to_pipe ath12k_wifi7_target_service_to_ce_map_wlan_wcn7850[];
+extern const struct service_to_pipe ath12k_wifi7_target_service_to_ce_map_wlan_ipq5332[];
+
+extern const struct ce_attr ath12k_wifi7_host_ce_config_qcn9274[];
+extern const struct ce_attr ath12k_wifi7_host_ce_config_wcn7850[];
+extern const struct ce_attr ath12k_wifi7_host_ce_config_ipq5332[];
+
+#endif /* ATH12K_WIFI7_CE_H */
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/core.c b/drivers/net/wireless/ath/ath12k/wifi7/core.c
new file mode 100644
index 000000000000..a02c57acf137
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/core.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/module.h>
+#include "../ahb.h"
+#include "../pci.h"
+#include "pci.h"
+#include "ahb.h"
+#include "core.h"
+#include "dp.h"
+#include "../debug.h"
+
+static int ahb_err, pci_err;
+
+int ath12k_wifi7_arch_init(struct ath12k_base *ab)
+{
+ struct ath12k_dp *dp;
+
+ dp = ath12k_wifi7_dp_device_alloc(ab);
+ if (!dp) {
+ ath12k_err(ab, "dp alloc failed");
+ return -EINVAL;
+ }
+
+ ab->dp = dp;
+
+ return 0;
+}
+
+void ath12k_wifi7_arch_deinit(struct ath12k_base *ab)
+{
+ ath12k_wifi7_dp_device_free(ab->dp);
+ ab->dp = NULL;
+}
+
+static int ath12k_wifi7_init(void)
+{
+ ahb_err = ath12k_wifi7_ahb_init();
+ if (ahb_err)
+ pr_warn("Failed to initialize ath12k Wi-Fi 7 AHB device: %d\n",
+ ahb_err);
+
+ pci_err = ath12k_wifi7_pci_init();
+ if (pci_err)
+ pr_warn("Failed to initialize ath12k Wi-Fi 7 PCI device: %d\n",
+ pci_err);
+
+ /* If both failed, return one of the failures (arbitrary) */
+ return ahb_err && pci_err ? ahb_err : 0;
+}
+
+static void ath12k_wifi7_exit(void)
+{
+ if (!pci_err)
+ ath12k_wifi7_pci_exit();
+
+ if (!ahb_err)
+ ath12k_wifi7_ahb_exit();
+}
+
+module_init(ath12k_wifi7_init);
+module_exit(ath12k_wifi7_exit);
+
+MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11be WLAN devices");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/core.h b/drivers/net/wireless/ath/ath12k/wifi7/core.h
new file mode 100644
index 000000000000..7e9689d2ddd7
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/core.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+#ifndef ATH12K_CORE_WIFI7_H
+#define ATH12K_CORE_WIFI7_H
+
+int ath12k_wifi7_arch_init(struct ath12k_base *ab);
+void ath12k_wifi7_arch_deinit(struct ath12k_base *ab);
+
+#endif
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp.c b/drivers/net/wireless/ath/ath12k/wifi7/dp.c
new file mode 100644
index 000000000000..2b194879ee80
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp.c
@@ -0,0 +1,181 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+#include "../core.h"
+#include "../debug.h"
+#include "../dp_rx.h"
+#include "../dp_tx.h"
+#include "hal_desc.h"
+#include "../dp_mon.h"
+#include "dp_mon.h"
+#include "../dp_cmn.h"
+#include "dp_rx.h"
+#include "dp.h"
+#include "dp_tx.h"
+#include "hal.h"
+
+static int ath12k_wifi7_dp_service_srng(struct ath12k_dp *dp,
+ struct ath12k_ext_irq_grp *irq_grp,
+ int budget)
+{
+ struct napi_struct *napi = &irq_grp->napi;
+ int grp_id = irq_grp->grp_id;
+ int work_done = 0;
+ int i = 0, j;
+ int tot_work_done = 0;
+ enum dp_monitor_mode monitor_mode;
+ u8 ring_mask;
+
+ if (dp->hw_params->ring_mask->tx[grp_id]) {
+ i = fls(dp->hw_params->ring_mask->tx[grp_id]) - 1;
+ ath12k_wifi7_dp_tx_completion_handler(dp, i);
+ }
+
+ if (dp->hw_params->ring_mask->rx_err[grp_id]) {
+ work_done = ath12k_wifi7_dp_rx_process_err(dp, napi, budget);
+ budget -= work_done;
+ tot_work_done += work_done;
+ if (budget <= 0)
+ goto done;
+ }
+
+ if (dp->hw_params->ring_mask->rx_wbm_rel[grp_id]) {
+ work_done = ath12k_wifi7_dp_rx_process_wbm_err(dp, napi, budget);
+ budget -= work_done;
+ tot_work_done += work_done;
+
+ if (budget <= 0)
+ goto done;
+ }
+
+ if (dp->hw_params->ring_mask->rx[grp_id]) {
+ i = fls(dp->hw_params->ring_mask->rx[grp_id]) - 1;
+ work_done = ath12k_wifi7_dp_rx_process(dp, i, napi, budget);
+ budget -= work_done;
+ tot_work_done += work_done;
+ if (budget <= 0)
+ goto done;
+ }
+
+ if (dp->hw_params->ring_mask->rx_mon_status[grp_id]) {
+ ring_mask = dp->hw_params->ring_mask->rx_mon_status[grp_id];
+ for (i = 0; i < dp->ab->num_radios; i++) {
+ for (j = 0; j < dp->hw_params->num_rxdma_per_pdev; j++) {
+ int id = i * dp->hw_params->num_rxdma_per_pdev + j;
+
+ if (ring_mask & BIT(id)) {
+ work_done =
+ ath12k_wifi7_dp_mon_process_ring(dp, id, napi,
+ budget,
+ 0);
+ budget -= work_done;
+ tot_work_done += work_done;
+ if (budget <= 0)
+ goto done;
+ }
+ }
+ }
+ }
+
+ if (dp->hw_params->ring_mask->rx_mon_dest[grp_id]) {
+ monitor_mode = ATH12K_DP_RX_MONITOR_MODE;
+ ring_mask = dp->hw_params->ring_mask->rx_mon_dest[grp_id];
+ for (i = 0; i < dp->ab->num_radios; i++) {
+ for (j = 0; j < dp->hw_params->num_rxdma_per_pdev; j++) {
+ int id = i * dp->hw_params->num_rxdma_per_pdev + j;
+
+ if (ring_mask & BIT(id)) {
+ work_done =
+ ath12k_wifi7_dp_mon_process_ring(dp, id, napi,
+ budget,
+ monitor_mode);
+ budget -= work_done;
+ tot_work_done += work_done;
+
+ if (budget <= 0)
+ goto done;
+ }
+ }
+ }
+ }
+
+ if (dp->hw_params->ring_mask->tx_mon_dest[grp_id]) {
+ monitor_mode = ATH12K_DP_TX_MONITOR_MODE;
+ ring_mask = dp->hw_params->ring_mask->tx_mon_dest[grp_id];
+ for (i = 0; i < dp->ab->num_radios; i++) {
+ for (j = 0; j < dp->hw_params->num_rxdma_per_pdev; j++) {
+ int id = i * dp->hw_params->num_rxdma_per_pdev + j;
+
+ if (ring_mask & BIT(id)) {
+ work_done =
+ ath12k_wifi7_dp_mon_process_ring(dp, id,
+ napi, budget,
+ monitor_mode);
+ budget -= work_done;
+ tot_work_done += work_done;
+
+ if (budget <= 0)
+ goto done;
+ }
+ }
+ }
+ }
+
+ if (dp->hw_params->ring_mask->reo_status[grp_id])
+ ath12k_wifi7_dp_rx_process_reo_status(dp);
+
+ if (dp->hw_params->ring_mask->host2rxdma[grp_id]) {
+ struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring;
+ LIST_HEAD(list);
+
+ ath12k_dp_rx_bufs_replenish(dp, rx_ring, &list, 0);
+ }
+
+ /* TODO: Implement handler for other interrupts */
+
+done:
+ return tot_work_done;
+}
+
+static struct ath12k_dp_arch_ops ath12k_wifi7_dp_arch_ops = {
+ .service_srng = ath12k_wifi7_dp_service_srng,
+ .tx_get_vdev_bank_config = ath12k_wifi7_dp_tx_get_vdev_bank_config,
+ .reo_cmd_send = ath12k_wifi7_dp_reo_cmd_send,
+ .setup_pn_check_reo_cmd = ath12k_wifi7_dp_setup_pn_check_reo_cmd,
+ .rx_peer_tid_delete = ath12k_wifi7_dp_rx_peer_tid_delete,
+ .reo_cache_flush = ath12k_wifi7_dp_reo_cache_flush,
+ .rx_link_desc_return = ath12k_wifi7_dp_rx_link_desc_return,
+ .rx_frags_cleanup = ath12k_wifi7_dp_rx_frags_cleanup,
+ .peer_rx_tid_reo_update = ath12k_wifi7_peer_rx_tid_reo_update,
+ .rx_assign_reoq = ath12k_wifi7_dp_rx_assign_reoq,
+ .peer_rx_tid_qref_setup = ath12k_wifi7_peer_rx_tid_qref_setup,
+ .peer_rx_tid_qref_reset = ath12k_wifi7_peer_rx_tid_qref_reset,
+ .rx_tid_delete_handler = ath12k_wifi7_dp_rx_tid_delete_handler,
+};
+
+/* TODO: remove export once this file is built with wifi7 ko */
+struct ath12k_dp *ath12k_wifi7_dp_device_alloc(struct ath12k_base *ab)
+{
+ struct ath12k_dp *dp;
+
+ /* TODO: align dp later if cache alignment becomes a bottleneck */
+ dp = kzalloc(sizeof(*dp), GFP_KERNEL);
+ if (!dp)
+ return NULL;
+
+ dp->ab = ab;
+ dp->dev = ab->dev;
+ dp->hw_params = ab->hw_params;
+ dp->hal = &ab->hal;
+
+ dp->ops = &ath12k_wifi7_dp_arch_ops;
+
+ return dp;
+}
+
+void ath12k_wifi7_dp_device_free(struct ath12k_dp *dp)
+{
+ kfree(dp);
+}
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp.h b/drivers/net/wireless/ath/ath12k/wifi7/dp.h
new file mode 100644
index 000000000000..a5f0941d34e2
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef ATH12K_DP_WIFI7_H
+#define ATH12K_DP_WIFI7_H
+
+#include "../dp_cmn.h"
+#include "hw.h"
+
+struct ath12k_base;
+struct ath12k_dp;
+enum dp_monitor_mode;
+
+struct ath12k_dp *ath12k_wifi7_dp_device_alloc(struct ath12k_base *ab);
+void ath12k_wifi7_dp_device_free(struct ath12k_dp *dp);
+
+#endif
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c
new file mode 100644
index 000000000000..bd741532b7dc
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c
@@ -0,0 +1,3385 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include "hal_desc.h"
+#include "../dp_mon.h"
+#include "dp_mon.h"
+#include "../debug.h"
+#include "hal_qcn9274.h"
+#include "dp_rx.h"
+#include "../dp_tx.h"
+#include "../peer.h"
+
+static void
+ath12k_wifi7_dp_mon_hal_aggr_tlv(struct hal_rx_mon_ppdu_info *ppdu_info,
+ u16 tlv_len, const void *tlv_data)
+{
+ if (tlv_len <= HAL_RX_MON_MAX_AGGR_SIZE - ppdu_info->tlv_aggr.cur_len) {
+ memcpy(ppdu_info->tlv_aggr.buf + ppdu_info->tlv_aggr.cur_len,
+ tlv_data, tlv_len);
+ ppdu_info->tlv_aggr.cur_len += tlv_len;
+ }
+}
+
+static void
+ath12k_wifi7_dp_mon_rx_memset_ppdu_info(struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ memset(ppdu_info, 0, sizeof(*ppdu_info));
+ ppdu_info->peer_id = HAL_INVALID_PEERID;
+}
+
+/* Hardware fill buffer with 128 bytes aligned. So need to reap it
+ * with 128 bytes aligned.
+ */
+#define RXDMA_DATA_DMA_BLOCK_SIZE 128
+
+static void
+ath12k_wifi7_dp_mon_get_buf_len(struct hal_rx_msdu_desc_info *info,
+ bool *is_frag, u32 *total_len,
+ u32 *frag_len, u32 *msdu_cnt)
+{
+ if (info->msdu_flags & RX_MSDU_DESC_INFO0_MSDU_CONTINUATION) {
+ *is_frag = true;
+ *frag_len = (RX_MON_STATUS_BASE_BUF_SIZE -
+ sizeof(struct hal_rx_desc)) &
+ ~(RXDMA_DATA_DMA_BLOCK_SIZE - 1);
+ *total_len += *frag_len;
+ } else {
+ if (*is_frag)
+ *frag_len = info->msdu_len - *total_len;
+ else
+ *frag_len = info->msdu_len;
+
+ *msdu_cnt -= 1;
+ }
+}
+
+static void
+ath12k_wifi7_dp_mon_rx_handle_ofdma_info(const struct hal_rx_ppdu_end_user_stats *ppdu_end_user,
+ struct hal_rx_user_status *rx_user_status)
+{
+ rx_user_status->ul_ofdma_user_v0_word0 =
+ __le32_to_cpu(ppdu_end_user->usr_resp_ref);
+ rx_user_status->ul_ofdma_user_v0_word1 =
+ __le32_to_cpu(ppdu_end_user->usr_resp_ref_ext);
+}
+
+static void
+ath12k_wifi7_dp_mon_rx_populate_byte_count(const struct hal_rx_ppdu_end_user_stats *stats,
+ void *ppduinfo,
+ struct hal_rx_user_status *rx_user_status)
+{
+ rx_user_status->mpdu_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 =
+ le32_get_bits(stats->info8,
+ HAL_RX_PPDU_END_USER_STATS_INFO8_MPDU_ERR_BYTE_COUNT);
+}
+
+static void
+ath12k_wifi7_dp_mon_rx_populate_mu_user_info(const struct hal_rx_ppdu_end_user_stats *rx_tlv,
+ struct hal_rx_mon_ppdu_info *ppdu_info,
+ struct hal_rx_user_status *rx_user_status)
+{
+ rx_user_status->ast_index = ppdu_info->ast_index;
+ rx_user_status->tid = ppdu_info->tid;
+ rx_user_status->tcp_ack_msdu_count =
+ ppdu_info->tcp_ack_msdu_count;
+ rx_user_status->tcp_msdu_count =
+ ppdu_info->tcp_msdu_count;
+ rx_user_status->udp_msdu_count =
+ ppdu_info->udp_msdu_count;
+ rx_user_status->other_msdu_count =
+ ppdu_info->other_msdu_count;
+ rx_user_status->frame_control = ppdu_info->frame_control;
+ rx_user_status->frame_control_info_valid =
+ ppdu_info->frame_control_info_valid;
+ rx_user_status->data_sequence_control_info_valid =
+ ppdu_info->data_sequence_control_info_valid;
+ rx_user_status->first_data_seq_ctrl =
+ ppdu_info->first_data_seq_ctrl;
+ rx_user_status->preamble_type = ppdu_info->preamble_type;
+ rx_user_status->ht_flags = ppdu_info->ht_flags;
+ rx_user_status->vht_flags = ppdu_info->vht_flags;
+ rx_user_status->he_flags = ppdu_info->he_flags;
+ rx_user_status->rs_flags = ppdu_info->rs_flags;
+
+ rx_user_status->mpdu_cnt_fcs_ok =
+ ppdu_info->num_mpdu_fcs_ok;
+ rx_user_status->mpdu_cnt_fcs_err =
+ ppdu_info->num_mpdu_fcs_err;
+ memcpy(&rx_user_status->mpdu_fcs_ok_bitmap[0], &ppdu_info->mpdu_fcs_ok_bitmap[0],
+ HAL_RX_NUM_WORDS_PER_PPDU_BITMAP *
+ sizeof(ppdu_info->mpdu_fcs_ok_bitmap[0]));
+
+ ath12k_wifi7_dp_mon_rx_populate_byte_count(rx_tlv, ppdu_info, rx_user_status);
+}
+
+static inline enum ath12k_eht_ru_size
+hal_rx_mon_hal_ru_size_to_ath12k_ru_size(u32 hal_ru_size)
+{
+ switch (hal_ru_size) {
+ case HAL_EHT_RU_26:
+ return ATH12K_EHT_RU_26;
+ case HAL_EHT_RU_52:
+ return ATH12K_EHT_RU_52;
+ case HAL_EHT_RU_78:
+ return ATH12K_EHT_RU_52_26;
+ case HAL_EHT_RU_106:
+ return ATH12K_EHT_RU_106;
+ case HAL_EHT_RU_132:
+ return ATH12K_EHT_RU_106_26;
+ case HAL_EHT_RU_242:
+ return ATH12K_EHT_RU_242;
+ case HAL_EHT_RU_484:
+ return ATH12K_EHT_RU_484;
+ case HAL_EHT_RU_726:
+ return ATH12K_EHT_RU_484_242;
+ case HAL_EHT_RU_996:
+ return ATH12K_EHT_RU_996;
+ case HAL_EHT_RU_996x2:
+ return ATH12K_EHT_RU_996x2;
+ case HAL_EHT_RU_996x3:
+ return ATH12K_EHT_RU_996x3;
+ case HAL_EHT_RU_996x4:
+ return ATH12K_EHT_RU_996x4;
+ case HAL_EHT_RU_NONE:
+ return ATH12K_EHT_RU_INVALID;
+ case HAL_EHT_RU_996_484:
+ return ATH12K_EHT_RU_996_484;
+ case HAL_EHT_RU_996x2_484:
+ return ATH12K_EHT_RU_996x2_484;
+ case HAL_EHT_RU_996x3_484:
+ return ATH12K_EHT_RU_996x3_484;
+ case HAL_EHT_RU_996_484_242:
+ return ATH12K_EHT_RU_996_484_242;
+ default:
+ return ATH12K_EHT_RU_INVALID;
+ }
+}
+
+static inline u32
+hal_rx_ul_ofdma_ru_size_to_width(enum ath12k_eht_ru_size ru_size)
+{
+ switch (ru_size) {
+ case ATH12K_EHT_RU_26:
+ return RU_26;
+ case ATH12K_EHT_RU_52:
+ return RU_52;
+ case ATH12K_EHT_RU_52_26:
+ return RU_52_26;
+ case ATH12K_EHT_RU_106:
+ return RU_106;
+ case ATH12K_EHT_RU_106_26:
+ return RU_106_26;
+ case ATH12K_EHT_RU_242:
+ return RU_242;
+ case ATH12K_EHT_RU_484:
+ return RU_484;
+ case ATH12K_EHT_RU_484_242:
+ return RU_484_242;
+ case ATH12K_EHT_RU_996:
+ return RU_996;
+ case ATH12K_EHT_RU_996_484:
+ return RU_996_484;
+ case ATH12K_EHT_RU_996_484_242:
+ return RU_996_484_242;
+ case ATH12K_EHT_RU_996x2:
+ return RU_2X996;
+ case ATH12K_EHT_RU_996x2_484:
+ return RU_2X996_484;
+ case ATH12K_EHT_RU_996x3:
+ return RU_3X996;
+ case ATH12K_EHT_RU_996x3_484:
+ return RU_3X996_484;
+ case ATH12K_EHT_RU_996x4:
+ return RU_4X996;
+ default:
+ return RU_INVALID;
+ }
+}
+
+static void
+ath12k_wifi7_dp_mon_hal_rx_parse_user_info(const struct hal_receive_user_info *rx_usr_info,
+ u16 user_id,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ struct hal_rx_user_status *mon_rx_user_status = NULL;
+ struct hal_rx_radiotap_eht *eht = &ppdu_info->eht_info.eht;
+ enum ath12k_eht_ru_size rtap_ru_size = ATH12K_EHT_RU_INVALID;
+ u32 ru_width, reception_type, ru_index = HAL_EHT_RU_INVALID;
+ u32 ru_type_80_0, ru_start_index_80_0;
+ u32 ru_type_80_1, ru_start_index_80_1;
+ u32 ru_type_80_2, ru_start_index_80_2;
+ u32 ru_type_80_3, ru_start_index_80_3;
+ u32 ru_size = 0, num_80mhz_with_ru = 0;
+ u64 ru_index_320mhz = 0;
+ u32 ru_index_per80mhz;
+
+ reception_type = le32_get_bits(rx_usr_info->info0,
+ HAL_RX_USR_INFO0_RECEPTION_TYPE);
+
+ switch (reception_type) {
+ case HAL_RECEPTION_TYPE_SU:
+ ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_SU;
+ break;
+ case HAL_RECEPTION_TYPE_DL_MU_MIMO:
+ case HAL_RECEPTION_TYPE_UL_MU_MIMO:
+ ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_MU_MIMO;
+ break;
+ case HAL_RECEPTION_TYPE_DL_MU_OFMA:
+ case HAL_RECEPTION_TYPE_UL_MU_OFDMA:
+ ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_MU_OFDMA;
+ break;
+ case HAL_RECEPTION_TYPE_DL_MU_OFDMA_MIMO:
+ case HAL_RECEPTION_TYPE_UL_MU_OFDMA_MIMO:
+ ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_MU_OFDMA_MIMO;
+ }
+
+ ppdu_info->is_stbc = le32_get_bits(rx_usr_info->info0, HAL_RX_USR_INFO0_STBC);
+ ppdu_info->ldpc = le32_get_bits(rx_usr_info->info2, HAL_RX_USR_INFO2_LDPC);
+ ppdu_info->dcm = le32_get_bits(rx_usr_info->info2, HAL_RX_USR_INFO2_STA_DCM);
+ ppdu_info->bw = le32_get_bits(rx_usr_info->info1, HAL_RX_USR_INFO1_RX_BW);
+ ppdu_info->mcs = le32_get_bits(rx_usr_info->info1, HAL_RX_USR_INFO1_MCS);
+ ppdu_info->nss = le32_get_bits(rx_usr_info->info2, HAL_RX_USR_INFO2_NSS) + 1;
+
+ if (user_id < HAL_MAX_UL_MU_USERS) {
+ mon_rx_user_status = &ppdu_info->userstats[user_id];
+ mon_rx_user_status->mcs = ppdu_info->mcs;
+ mon_rx_user_status->nss = ppdu_info->nss;
+ }
+
+ if (!(ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_MU_MIMO ||
+ ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_MU_OFDMA ||
+ ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_MU_OFDMA_MIMO))
+ return;
+
+ /* RU allocation present only for OFDMA reception */
+ ru_type_80_0 = le32_get_bits(rx_usr_info->info2, HAL_RX_USR_INFO2_RU_TYPE_80_0);
+ ru_start_index_80_0 = le32_get_bits(rx_usr_info->info3,
+ HAL_RX_USR_INFO3_RU_START_IDX_80_0);
+ if (ru_type_80_0 != HAL_EHT_RU_NONE) {
+ ru_size += ru_type_80_0;
+ ru_index_per80mhz = ru_start_index_80_0;
+ ru_index = ru_index_per80mhz;
+ ru_index_320mhz |= HAL_RU_PER80(ru_type_80_0, 0, ru_index_per80mhz);
+ num_80mhz_with_ru++;
+ }
+
+ ru_type_80_1 = le32_get_bits(rx_usr_info->info2, HAL_RX_USR_INFO2_RU_TYPE_80_1);
+ ru_start_index_80_1 = le32_get_bits(rx_usr_info->info3,
+ HAL_RX_USR_INFO3_RU_START_IDX_80_1);
+ if (ru_type_80_1 != HAL_EHT_RU_NONE) {
+ ru_size += ru_type_80_1;
+ ru_index_per80mhz = ru_start_index_80_1;
+ ru_index = ru_index_per80mhz;
+ ru_index_320mhz |= HAL_RU_PER80(ru_type_80_1, 1, ru_index_per80mhz);
+ num_80mhz_with_ru++;
+ }
+
+ ru_type_80_2 = le32_get_bits(rx_usr_info->info2, HAL_RX_USR_INFO2_RU_TYPE_80_2);
+ ru_start_index_80_2 = le32_get_bits(rx_usr_info->info3,
+ HAL_RX_USR_INFO3_RU_START_IDX_80_2);
+ if (ru_type_80_2 != HAL_EHT_RU_NONE) {
+ ru_size += ru_type_80_2;
+ ru_index_per80mhz = ru_start_index_80_2;
+ ru_index = ru_index_per80mhz;
+ ru_index_320mhz |= HAL_RU_PER80(ru_type_80_2, 2, ru_index_per80mhz);
+ num_80mhz_with_ru++;
+ }
+
+ ru_type_80_3 = le32_get_bits(rx_usr_info->info2, HAL_RX_USR_INFO2_RU_TYPE_80_3);
+ ru_start_index_80_3 = le32_get_bits(rx_usr_info->info2,
+ HAL_RX_USR_INFO3_RU_START_IDX_80_3);
+ if (ru_type_80_3 != HAL_EHT_RU_NONE) {
+ ru_size += ru_type_80_3;
+ ru_index_per80mhz = ru_start_index_80_3;
+ ru_index = ru_index_per80mhz;
+ ru_index_320mhz |= HAL_RU_PER80(ru_type_80_3, 3, ru_index_per80mhz);
+ num_80mhz_with_ru++;
+ }
+
+ if (num_80mhz_with_ru > 1) {
+ /* Calculate the MRU index */
+ switch (ru_index_320mhz) {
+ case HAL_EHT_RU_996_484_0:
+ case HAL_EHT_RU_996x2_484_0:
+ case HAL_EHT_RU_996x3_484_0:
+ ru_index = 0;
+ break;
+ case HAL_EHT_RU_996_484_1:
+ case HAL_EHT_RU_996x2_484_1:
+ case HAL_EHT_RU_996x3_484_1:
+ ru_index = 1;
+ break;
+ case HAL_EHT_RU_996_484_2:
+ case HAL_EHT_RU_996x2_484_2:
+ case HAL_EHT_RU_996x3_484_2:
+ ru_index = 2;
+ break;
+ case HAL_EHT_RU_996_484_3:
+ case HAL_EHT_RU_996x2_484_3:
+ case HAL_EHT_RU_996x3_484_3:
+ ru_index = 3;
+ break;
+ case HAL_EHT_RU_996_484_4:
+ case HAL_EHT_RU_996x2_484_4:
+ case HAL_EHT_RU_996x3_484_4:
+ ru_index = 4;
+ break;
+ case HAL_EHT_RU_996_484_5:
+ case HAL_EHT_RU_996x2_484_5:
+ case HAL_EHT_RU_996x3_484_5:
+ ru_index = 5;
+ break;
+ case HAL_EHT_RU_996_484_6:
+ case HAL_EHT_RU_996x2_484_6:
+ case HAL_EHT_RU_996x3_484_6:
+ ru_index = 6;
+ break;
+ case HAL_EHT_RU_996_484_7:
+ case HAL_EHT_RU_996x2_484_7:
+ case HAL_EHT_RU_996x3_484_7:
+ ru_index = 7;
+ break;
+ case HAL_EHT_RU_996x2_484_8:
+ ru_index = 8;
+ break;
+ case HAL_EHT_RU_996x2_484_9:
+ ru_index = 9;
+ break;
+ case HAL_EHT_RU_996x2_484_10:
+ ru_index = 10;
+ break;
+ case HAL_EHT_RU_996x2_484_11:
+ ru_index = 11;
+ break;
+ default:
+ ru_index = HAL_EHT_RU_INVALID;
+ break;
+ }
+
+ ru_size += 4;
+ }
+
+ rtap_ru_size = hal_rx_mon_hal_ru_size_to_ath12k_ru_size(ru_size);
+ if (rtap_ru_size != ATH12K_EHT_RU_INVALID) {
+ u32 known, data;
+
+ known = __le32_to_cpu(eht->known);
+ known |= IEEE80211_RADIOTAP_EHT_KNOWN_RU_MRU_SIZE_OM;
+ eht->known = cpu_to_le32(known);
+
+ data = __le32_to_cpu(eht->data[1]);
+ data |= u32_encode_bits(rtap_ru_size,
+ IEEE80211_RADIOTAP_EHT_DATA1_RU_SIZE);
+ eht->data[1] = cpu_to_le32(data);
+ }
+
+ if (ru_index != HAL_EHT_RU_INVALID) {
+ u32 known, data;
+
+ known = __le32_to_cpu(eht->known);
+ known |= IEEE80211_RADIOTAP_EHT_KNOWN_RU_MRU_INDEX_OM;
+ eht->known = cpu_to_le32(known);
+
+ data = __le32_to_cpu(eht->data[1]);
+ data |= u32_encode_bits(rtap_ru_size,
+ IEEE80211_RADIOTAP_EHT_DATA1_RU_INDEX);
+ eht->data[1] = cpu_to_le32(data);
+ }
+
+ if (mon_rx_user_status && ru_index != HAL_EHT_RU_INVALID &&
+ rtap_ru_size != ATH12K_EHT_RU_INVALID) {
+ mon_rx_user_status->ul_ofdma_ru_start_index = ru_index;
+ mon_rx_user_status->ul_ofdma_ru_size = rtap_ru_size;
+
+ ru_width = hal_rx_ul_ofdma_ru_size_to_width(rtap_ru_size);
+
+ mon_rx_user_status->ul_ofdma_ru_width = ru_width;
+ mon_rx_user_status->ofdma_info_valid = 1;
+ }
+}
+
+static void
+ath12k_wifi7_dp_mon_parse_l_sig_b(const struct hal_rx_lsig_b_info *lsigb,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ u32 info0 = __le32_to_cpu(lsigb->info0);
+ u8 rate;
+
+ rate = u32_get_bits(info0, HAL_RX_LSIG_B_INFO_INFO0_RATE);
+ switch (rate) {
+ case 1:
+ rate = HAL_RX_LEGACY_RATE_1_MBPS;
+ break;
+ case 2:
+ case 5:
+ rate = HAL_RX_LEGACY_RATE_2_MBPS;
+ break;
+ case 3:
+ case 6:
+ rate = HAL_RX_LEGACY_RATE_5_5_MBPS;
+ break;
+ case 4:
+ case 7:
+ rate = HAL_RX_LEGACY_RATE_11_MBPS;
+ break;
+ default:
+ rate = HAL_RX_LEGACY_RATE_INVALID;
+ }
+
+ ppdu_info->rate = rate;
+ ppdu_info->cck_flag = 1;
+}
+
+static void
+ath12k_wifi7_dp_mon_parse_l_sig_a(const struct hal_rx_lsig_a_info *lsiga,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ u32 info0 = __le32_to_cpu(lsiga->info0);
+ u8 rate;
+
+ rate = u32_get_bits(info0, HAL_RX_LSIG_A_INFO_INFO0_RATE);
+ switch (rate) {
+ case 8:
+ rate = HAL_RX_LEGACY_RATE_48_MBPS;
+ break;
+ case 9:
+ rate = HAL_RX_LEGACY_RATE_24_MBPS;
+ break;
+ case 10:
+ rate = HAL_RX_LEGACY_RATE_12_MBPS;
+ break;
+ case 11:
+ rate = HAL_RX_LEGACY_RATE_6_MBPS;
+ break;
+ case 12:
+ rate = HAL_RX_LEGACY_RATE_54_MBPS;
+ break;
+ case 13:
+ rate = HAL_RX_LEGACY_RATE_36_MBPS;
+ break;
+ case 14:
+ rate = HAL_RX_LEGACY_RATE_18_MBPS;
+ break;
+ case 15:
+ rate = HAL_RX_LEGACY_RATE_9_MBPS;
+ break;
+ default:
+ rate = HAL_RX_LEGACY_RATE_INVALID;
+ }
+
+ ppdu_info->rate = rate;
+}
+
+static void
+ath12k_wifi7_dp_mon_hal_rx_parse_u_sig_cmn(const struct hal_mon_usig_cmn *cmn,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ u32 common;
+
+ ppdu_info->u_sig_info.bw = le32_get_bits(cmn->info0,
+ HAL_RX_USIG_CMN_INFO0_BW);
+ ppdu_info->u_sig_info.ul_dl = le32_get_bits(cmn->info0,
+ HAL_RX_USIG_CMN_INFO0_UL_DL);
+
+ common = __le32_to_cpu(ppdu_info->u_sig_info.usig.common);
+ common |= IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER_KNOWN |
+ IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_KNOWN |
+ IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL_KNOWN |
+ IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR_KNOWN |
+ IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP_KNOWN |
+ ATH12K_LE32_DEC_ENC(cmn->info0,
+ HAL_RX_USIG_CMN_INFO0_PHY_VERSION,
+ IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER) |
+ u32_encode_bits(ppdu_info->u_sig_info.bw,
+ IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW) |
+ u32_encode_bits(ppdu_info->u_sig_info.ul_dl,
+ IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL) |
+ ATH12K_LE32_DEC_ENC(cmn->info0,
+ HAL_RX_USIG_CMN_INFO0_BSS_COLOR,
+ IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR) |
+ ATH12K_LE32_DEC_ENC(cmn->info0,
+ HAL_RX_USIG_CMN_INFO0_TXOP,
+ IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP);
+ ppdu_info->u_sig_info.usig.common = cpu_to_le32(common);
+
+ switch (ppdu_info->u_sig_info.bw) {
+ default:
+ fallthrough;
+ case HAL_EHT_BW_20:
+ ppdu_info->bw = HAL_RX_BW_20MHZ;
+ break;
+ case HAL_EHT_BW_40:
+ ppdu_info->bw = HAL_RX_BW_40MHZ;
+ break;
+ case HAL_EHT_BW_80:
+ ppdu_info->bw = HAL_RX_BW_80MHZ;
+ break;
+ case HAL_EHT_BW_160:
+ ppdu_info->bw = HAL_RX_BW_160MHZ;
+ break;
+ case HAL_EHT_BW_320_1:
+ case HAL_EHT_BW_320_2:
+ ppdu_info->bw = HAL_RX_BW_320MHZ;
+ break;
+ }
+}
+
+static void
+ath12k_wifi7_dp_mon_hal_rx_parse_u_sig_tb(const struct hal_mon_usig_tb *usig_tb,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ struct ieee80211_radiotap_eht_usig *usig = &ppdu_info->u_sig_info.usig;
+ enum ieee80211_radiotap_eht_usig_tb spatial_reuse1, spatial_reuse2;
+ u32 common, value, mask;
+
+ spatial_reuse1 = IEEE80211_RADIOTAP_EHT_USIG2_TB_B3_B6_SPATIAL_REUSE_1;
+ spatial_reuse2 = IEEE80211_RADIOTAP_EHT_USIG2_TB_B7_B10_SPATIAL_REUSE_2;
+
+ common = __le32_to_cpu(usig->common);
+ value = __le32_to_cpu(usig->value);
+ mask = __le32_to_cpu(usig->mask);
+
+ ppdu_info->u_sig_info.ppdu_type_comp_mode =
+ le32_get_bits(usig_tb->info0,
+ HAL_RX_USIG_TB_INFO0_PPDU_TYPE_COMP_MODE);
+
+ common |= ATH12K_LE32_DEC_ENC(usig_tb->info0,
+ HAL_RX_USIG_TB_INFO0_RX_INTEG_CHECK_PASS,
+ IEEE80211_RADIOTAP_EHT_USIG_COMMON_BAD_USIG_CRC);
+
+ value |= IEEE80211_RADIOTAP_EHT_USIG1_TB_B20_B25_DISREGARD |
+ u32_encode_bits(ppdu_info->u_sig_info.ppdu_type_comp_mode,
+ IEEE80211_RADIOTAP_EHT_USIG2_TB_B0_B1_PPDU_TYPE) |
+ IEEE80211_RADIOTAP_EHT_USIG2_TB_B2_VALIDATE |
+ ATH12K_LE32_DEC_ENC(usig_tb->info0,
+ HAL_RX_USIG_TB_INFO0_SPATIAL_REUSE_1,
+ spatial_reuse1) |
+ ATH12K_LE32_DEC_ENC(usig_tb->info0,
+ HAL_RX_USIG_TB_INFO0_SPATIAL_REUSE_2,
+ spatial_reuse2) |
+ IEEE80211_RADIOTAP_EHT_USIG2_TB_B11_B15_DISREGARD |
+ ATH12K_LE32_DEC_ENC(usig_tb->info0,
+ HAL_RX_USIG_TB_INFO0_CRC,
+ IEEE80211_RADIOTAP_EHT_USIG2_TB_B16_B19_CRC) |
+ ATH12K_LE32_DEC_ENC(usig_tb->info0,
+ HAL_RX_USIG_TB_INFO0_TAIL,
+ IEEE80211_RADIOTAP_EHT_USIG2_TB_B20_B25_TAIL);
+
+ mask |= IEEE80211_RADIOTAP_EHT_USIG1_TB_B20_B25_DISREGARD |
+ IEEE80211_RADIOTAP_EHT_USIG2_TB_B0_B1_PPDU_TYPE |
+ IEEE80211_RADIOTAP_EHT_USIG2_TB_B2_VALIDATE |
+ spatial_reuse1 | spatial_reuse2 |
+ IEEE80211_RADIOTAP_EHT_USIG2_TB_B11_B15_DISREGARD |
+ IEEE80211_RADIOTAP_EHT_USIG2_TB_B16_B19_CRC |
+ IEEE80211_RADIOTAP_EHT_USIG2_TB_B20_B25_TAIL;
+
+ usig->common = cpu_to_le32(common);
+ usig->value = cpu_to_le32(value);
+ usig->mask = cpu_to_le32(mask);
+}
+
+static void
+ath12k_wifi7_dp_mon_hal_rx_parse_u_sig_mu(const struct hal_mon_usig_mu *usig_mu,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ struct ieee80211_radiotap_eht_usig *usig = &ppdu_info->u_sig_info.usig;
+ enum ieee80211_radiotap_eht_usig_mu sig_symb, punc;
+ u32 common, value, mask;
+
+ sig_symb = IEEE80211_RADIOTAP_EHT_USIG2_MU_B11_B15_EHT_SIG_SYMBOLS;
+ punc = IEEE80211_RADIOTAP_EHT_USIG2_MU_B3_B7_PUNCTURED_INFO;
+
+ common = __le32_to_cpu(usig->common);
+ value = __le32_to_cpu(usig->value);
+ mask = __le32_to_cpu(usig->mask);
+
+ ppdu_info->u_sig_info.ppdu_type_comp_mode =
+ le32_get_bits(usig_mu->info0,
+ HAL_RX_USIG_MU_INFO0_PPDU_TYPE_COMP_MODE);
+ ppdu_info->u_sig_info.eht_sig_mcs =
+ le32_get_bits(usig_mu->info0,
+ HAL_RX_USIG_MU_INFO0_EHT_SIG_MCS);
+ ppdu_info->u_sig_info.num_eht_sig_sym =
+ le32_get_bits(usig_mu->info0,
+ HAL_RX_USIG_MU_INFO0_NUM_EHT_SIG_SYM);
+
+ common |= ATH12K_LE32_DEC_ENC(usig_mu->info0,
+ HAL_RX_USIG_MU_INFO0_RX_INTEG_CHECK_PASS,
+ IEEE80211_RADIOTAP_EHT_USIG_COMMON_BAD_USIG_CRC);
+
+ value |= IEEE80211_RADIOTAP_EHT_USIG1_MU_B20_B24_DISREGARD |
+ IEEE80211_RADIOTAP_EHT_USIG1_MU_B25_VALIDATE |
+ u32_encode_bits(ppdu_info->u_sig_info.ppdu_type_comp_mode,
+ IEEE80211_RADIOTAP_EHT_USIG2_MU_B0_B1_PPDU_TYPE) |
+ IEEE80211_RADIOTAP_EHT_USIG2_MU_B2_VALIDATE |
+ ATH12K_LE32_DEC_ENC(usig_mu->info0,
+ HAL_RX_USIG_MU_INFO0_PUNC_CH_INFO,
+ punc) |
+ IEEE80211_RADIOTAP_EHT_USIG2_MU_B8_VALIDATE |
+ u32_encode_bits(ppdu_info->u_sig_info.eht_sig_mcs,
+ IEEE80211_RADIOTAP_EHT_USIG2_MU_B9_B10_SIG_MCS) |
+ u32_encode_bits(ppdu_info->u_sig_info.num_eht_sig_sym,
+ sig_symb) |
+ ATH12K_LE32_DEC_ENC(usig_mu->info0,
+ HAL_RX_USIG_MU_INFO0_CRC,
+ IEEE80211_RADIOTAP_EHT_USIG2_MU_B16_B19_CRC) |
+ ATH12K_LE32_DEC_ENC(usig_mu->info0,
+ HAL_RX_USIG_MU_INFO0_TAIL,
+ IEEE80211_RADIOTAP_EHT_USIG2_MU_B20_B25_TAIL);
+
+ mask |= IEEE80211_RADIOTAP_EHT_USIG1_MU_B20_B24_DISREGARD |
+ IEEE80211_RADIOTAP_EHT_USIG1_MU_B25_VALIDATE |
+ IEEE80211_RADIOTAP_EHT_USIG2_MU_B0_B1_PPDU_TYPE |
+ IEEE80211_RADIOTAP_EHT_USIG2_MU_B2_VALIDATE |
+ punc |
+ IEEE80211_RADIOTAP_EHT_USIG2_MU_B8_VALIDATE |
+ IEEE80211_RADIOTAP_EHT_USIG2_MU_B9_B10_SIG_MCS |
+ sig_symb |
+ IEEE80211_RADIOTAP_EHT_USIG2_MU_B16_B19_CRC |
+ IEEE80211_RADIOTAP_EHT_USIG2_MU_B20_B25_TAIL;
+
+ usig->common = cpu_to_le32(common);
+ usig->value = cpu_to_le32(value);
+ usig->mask = cpu_to_le32(mask);
+}
+
+static void
+ath12k_wifi7_dp_mon_hal_rx_parse_u_sig_hdr(const struct hal_mon_usig_hdr *usig,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ u8 comp_mode;
+
+ ppdu_info->eht_usig = true;
+
+ ath12k_wifi7_dp_mon_hal_rx_parse_u_sig_cmn(&usig->cmn, ppdu_info);
+
+ comp_mode = le32_get_bits(usig->non_cmn.mu.info0,
+ HAL_RX_USIG_MU_INFO0_PPDU_TYPE_COMP_MODE);
+
+ if (comp_mode == 0 && ppdu_info->u_sig_info.ul_dl)
+ ath12k_wifi7_dp_mon_hal_rx_parse_u_sig_tb(&usig->non_cmn.tb, ppdu_info);
+ else
+ ath12k_wifi7_dp_mon_hal_rx_parse_u_sig_mu(&usig->non_cmn.mu, ppdu_info);
+}
+
+static void
+ath12k_wifi7_dp_mon_parse_vht_sig_a(const struct hal_rx_vht_sig_a_info *vht_sig,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ u32 nsts, info0, info1;
+ u8 gi_setting;
+
+ info0 = __le32_to_cpu(vht_sig->info0);
+ info1 = __le32_to_cpu(vht_sig->info1);
+
+ ppdu_info->ldpc = u32_get_bits(info1, HAL_RX_VHT_SIG_A_INFO_INFO1_SU_MU_CODING);
+ ppdu_info->mcs = u32_get_bits(info1, HAL_RX_VHT_SIG_A_INFO_INFO1_MCS);
+ gi_setting = u32_get_bits(info1, HAL_RX_VHT_SIG_A_INFO_INFO1_GI_SETTING);
+ switch (gi_setting) {
+ case HAL_RX_VHT_SIG_A_NORMAL_GI:
+ ppdu_info->gi = HAL_RX_GI_0_8_US;
+ break;
+ case HAL_RX_VHT_SIG_A_SHORT_GI:
+ case HAL_RX_VHT_SIG_A_SHORT_GI_AMBIGUITY:
+ ppdu_info->gi = HAL_RX_GI_0_4_US;
+ break;
+ }
+
+ ppdu_info->is_stbc = u32_get_bits(info0, HAL_RX_VHT_SIG_A_INFO_INFO0_STBC);
+ nsts = u32_get_bits(info0, HAL_RX_VHT_SIG_A_INFO_INFO0_NSTS);
+ if (ppdu_info->is_stbc && nsts > 0)
+ nsts = ((nsts + 1) >> 1) - 1;
+
+ ppdu_info->nss = u32_get_bits(nsts, VHT_SIG_SU_NSS_MASK) + 1;
+ ppdu_info->bw = u32_get_bits(info0, HAL_RX_VHT_SIG_A_INFO_INFO0_BW);
+ ppdu_info->beamformed = u32_get_bits(info1,
+ HAL_RX_VHT_SIG_A_INFO_INFO1_BEAMFORMED);
+ ppdu_info->vht_flag_values5 = u32_get_bits(info0,
+ HAL_RX_VHT_SIG_A_INFO_INFO0_GROUP_ID);
+ ppdu_info->vht_flag_values3[0] = (((ppdu_info->mcs) << 4) |
+ ppdu_info->nss);
+ ppdu_info->vht_flag_values2 = ppdu_info->bw;
+ ppdu_info->vht_flag_values4 =
+ u32_get_bits(info1, HAL_RX_VHT_SIG_A_INFO_INFO1_SU_MU_CODING);
+}
+
+static void
+ath12k_wifi7_dp_mon_parse_ht_sig(const struct hal_rx_ht_sig_info *ht_sig,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ u32 info0 = __le32_to_cpu(ht_sig->info0);
+ u32 info1 = __le32_to_cpu(ht_sig->info1);
+
+ ppdu_info->mcs = u32_get_bits(info0, HAL_RX_HT_SIG_INFO_INFO0_MCS);
+ ppdu_info->bw = u32_get_bits(info0, HAL_RX_HT_SIG_INFO_INFO0_BW);
+ ppdu_info->is_stbc = u32_get_bits(info1, HAL_RX_HT_SIG_INFO_INFO1_STBC);
+ ppdu_info->ldpc = u32_get_bits(info1, HAL_RX_HT_SIG_INFO_INFO1_FEC_CODING);
+ ppdu_info->gi = u32_get_bits(info1, HAL_RX_HT_SIG_INFO_INFO1_GI);
+ ppdu_info->nss = (ppdu_info->mcs >> 3) + 1;
+}
+
+static void
+ath12k_wifi7_dp_mon_parse_he_sig_b2_ofdma(const struct hal_rx_he_sig_b2_ofdma_info *ofdma,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ u32 info0, value;
+
+ info0 = __le32_to_cpu(ofdma->info0);
+
+ ppdu_info->he_data1 |= HE_MCS_KNOWN | HE_DCM_KNOWN | HE_CODING_KNOWN;
+
+ /* HE-data2 */
+ ppdu_info->he_data2 |= HE_TXBF_KNOWN;
+
+ ppdu_info->mcs = u32_get_bits(info0, HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_MCS);
+ value = ppdu_info->mcs << HE_TRANSMIT_MCS_SHIFT;
+ ppdu_info->he_data3 |= value;
+
+ value = u32_get_bits(info0, HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_DCM);
+ value = value << HE_DCM_SHIFT;
+ ppdu_info->he_data3 |= value;
+
+ value = u32_get_bits(info0, HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_CODING);
+ ppdu_info->ldpc = value;
+ value = value << HE_CODING_SHIFT;
+ ppdu_info->he_data3 |= value;
+
+ /* HE-data4 */
+ value = u32_get_bits(info0, HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_ID);
+ value = value << HE_STA_ID_SHIFT;
+ ppdu_info->he_data4 |= value;
+
+ ppdu_info->nss =
+ u32_get_bits(info0,
+ HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_NSTS) + 1;
+ ppdu_info->beamformed = u32_get_bits(info0,
+ HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_TXBF);
+}
+
+static void
+ath12k_wifi7_dp_mon_parse_he_sig_b2_mu(const struct hal_rx_he_sig_b2_mu_info *he_sig_b2_mu,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ u32 info0, value;
+
+ info0 = __le32_to_cpu(he_sig_b2_mu->info0);
+
+ ppdu_info->he_data1 |= HE_MCS_KNOWN | HE_CODING_KNOWN;
+
+ ppdu_info->mcs = u32_get_bits(info0, HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_MCS);
+ value = ppdu_info->mcs << HE_TRANSMIT_MCS_SHIFT;
+ ppdu_info->he_data3 |= value;
+
+ value = u32_get_bits(info0, HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_CODING);
+ ppdu_info->ldpc = value;
+ value = value << HE_CODING_SHIFT;
+ ppdu_info->he_data3 |= value;
+
+ value = u32_get_bits(info0, HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_ID);
+ value = value << HE_STA_ID_SHIFT;
+ ppdu_info->he_data4 |= value;
+
+ ppdu_info->nss =
+ u32_get_bits(info0,
+ HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_NSTS) + 1;
+}
+
+static void
+ath12k_wifi7_dp_mon_parse_he_sig_b1_mu(const struct hal_rx_he_sig_b1_mu_info *he_sig_b1_mu,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ u32 info0 = __le32_to_cpu(he_sig_b1_mu->info0);
+ u16 ru_tones;
+
+ ru_tones = u32_get_bits(info0,
+ HAL_RX_HE_SIG_B1_MU_INFO_INFO0_RU_ALLOCATION);
+ ppdu_info->ru_alloc = ath12k_he_ru_tones_to_nl80211_he_ru_alloc(ru_tones);
+ ppdu_info->he_RU[0] = ru_tones;
+}
+
+static void
+ath12k_wifi7_dp_mon_parse_he_sig_mu(const struct hal_rx_he_sig_a_mu_dl_info *he_sig_a_mu_dl,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ u32 info0, info1, value;
+ u16 he_gi = 0, he_ltf = 0;
+
+ info0 = __le32_to_cpu(he_sig_a_mu_dl->info0);
+ info1 = __le32_to_cpu(he_sig_a_mu_dl->info1);
+
+ ppdu_info->he_mu_flags = 1;
+
+ ppdu_info->he_data1 = HE_MU_FORMAT_TYPE;
+ ppdu_info->he_data1 |=
+ HE_BSS_COLOR_KNOWN |
+ HE_DL_UL_KNOWN |
+ HE_LDPC_EXTRA_SYMBOL_KNOWN |
+ HE_STBC_KNOWN |
+ HE_DATA_BW_RU_KNOWN |
+ HE_DOPPLER_KNOWN;
+
+ ppdu_info->he_data2 =
+ HE_GI_KNOWN |
+ HE_LTF_SYMBOLS_KNOWN |
+ HE_PRE_FEC_PADDING_KNOWN |
+ HE_PE_DISAMBIGUITY_KNOWN |
+ HE_TXOP_KNOWN |
+ HE_MIDABLE_PERIODICITY_KNOWN;
+
+ /* data3 */
+ ppdu_info->he_data3 = u32_get_bits(info0, HAL_RX_HE_SIG_A_MU_DL_INFO0_BSS_COLOR);
+ value = u32_get_bits(info0, HAL_RX_HE_SIG_A_MU_DL_INFO0_UL_FLAG);
+ value = value << HE_DL_UL_SHIFT;
+ ppdu_info->he_data3 |= value;
+
+ value = u32_get_bits(info1, HAL_RX_HE_SIG_A_MU_DL_INFO1_LDPC_EXTRA);
+ value = value << HE_LDPC_EXTRA_SYMBOL_SHIFT;
+ ppdu_info->he_data3 |= value;
+
+ value = u32_get_bits(info1, HAL_RX_HE_SIG_A_MU_DL_INFO1_STBC);
+ value = value << HE_STBC_SHIFT;
+ ppdu_info->he_data3 |= value;
+
+ /* data4 */
+ ppdu_info->he_data4 = u32_get_bits(info0,
+ HAL_RX_HE_SIG_A_MU_DL_INFO0_SPATIAL_REUSE);
+ ppdu_info->he_data4 = value;
+
+ /* data5 */
+ value = u32_get_bits(info0, HAL_RX_HE_SIG_A_MU_DL_INFO0_TRANSMIT_BW);
+ ppdu_info->he_data5 = value;
+ ppdu_info->bw = value;
+
+ value = u32_get_bits(info0, HAL_RX_HE_SIG_A_MU_DL_INFO0_CP_LTF_SIZE);
+ switch (value) {
+ case 0:
+ he_gi = HE_GI_0_8;
+ he_ltf = HE_LTF_4_X;
+ break;
+ case 1:
+ he_gi = HE_GI_0_8;
+ he_ltf = HE_LTF_2_X;
+ break;
+ case 2:
+ he_gi = HE_GI_1_6;
+ he_ltf = HE_LTF_2_X;
+ break;
+ case 3:
+ he_gi = HE_GI_3_2;
+ he_ltf = HE_LTF_4_X;
+ break;
+ }
+
+ ppdu_info->gi = he_gi;
+ value = he_gi << HE_GI_SHIFT;
+ ppdu_info->he_data5 |= value;
+
+ value = he_ltf << HE_LTF_SIZE_SHIFT;
+ ppdu_info->he_data5 |= value;
+
+ value = u32_get_bits(info1, HAL_RX_HE_SIG_A_MU_DL_INFO1_NUM_LTF_SYMB);
+ value = (value << HE_LTF_SYM_SHIFT);
+ ppdu_info->he_data5 |= value;
+
+ value = u32_get_bits(info1, HAL_RX_HE_SIG_A_MU_DL_INFO1_PKT_EXT_FACTOR);
+ value = value << HE_PRE_FEC_PAD_SHIFT;
+ ppdu_info->he_data5 |= value;
+
+ value = u32_get_bits(info1, HAL_RX_HE_SIG_A_MU_DL_INFO1_PKT_EXT_PE_DISAM);
+ value = value << HE_PE_DISAMBIGUITY_SHIFT;
+ ppdu_info->he_data5 |= value;
+
+ /*data6*/
+ value = u32_get_bits(info0, HAL_RX_HE_SIG_A_MU_DL_INFO0_DOPPLER_INDICATION);
+ value = value << HE_DOPPLER_SHIFT;
+ ppdu_info->he_data6 |= value;
+
+ value = u32_get_bits(info1, HAL_RX_HE_SIG_A_MU_DL_INFO1_TXOP_DURATION);
+ value = value << HE_TXOP_SHIFT;
+ ppdu_info->he_data6 |= value;
+
+ /* HE-MU Flags */
+ /* HE-MU-flags1 */
+ ppdu_info->he_flags1 =
+ HE_SIG_B_MCS_KNOWN |
+ HE_SIG_B_DCM_KNOWN |
+ HE_SIG_B_COMPRESSION_FLAG_1_KNOWN |
+ HE_SIG_B_SYM_NUM_KNOWN |
+ HE_RU_0_KNOWN;
+
+ value = u32_get_bits(info0, HAL_RX_HE_SIG_A_MU_DL_INFO0_MCS_OF_SIGB);
+ ppdu_info->he_flags1 |= value;
+ value = u32_get_bits(info0, HAL_RX_HE_SIG_A_MU_DL_INFO0_DCM_OF_SIGB);
+ value = value << HE_DCM_FLAG_1_SHIFT;
+ ppdu_info->he_flags1 |= value;
+
+ /* HE-MU-flags2 */
+ ppdu_info->he_flags2 = HE_BW_KNOWN;
+
+ value = u32_get_bits(info0, HAL_RX_HE_SIG_A_MU_DL_INFO0_TRANSMIT_BW);
+ ppdu_info->he_flags2 |= value;
+ value = u32_get_bits(info0, HAL_RX_HE_SIG_A_MU_DL_INFO0_COMP_MODE_SIGB);
+ value = value << HE_SIG_B_COMPRESSION_FLAG_2_SHIFT;
+ ppdu_info->he_flags2 |= value;
+ value = u32_get_bits(info0, HAL_RX_HE_SIG_A_MU_DL_INFO0_NUM_SIGB_SYMB);
+ value = value - 1;
+ value = value << HE_NUM_SIG_B_SYMBOLS_SHIFT;
+ ppdu_info->he_flags2 |= value;
+
+ ppdu_info->is_stbc = info1 &
+ HAL_RX_HE_SIG_A_MU_DL_INFO1_STBC;
+}
+
+static void
+ath12k_wifi7_dp_mon_parse_he_sig_su(const struct hal_rx_he_sig_a_su_info *he_sig_a,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ u32 info0, info1, value;
+ u32 dcm;
+ u8 he_dcm = 0, he_stbc = 0;
+ u16 he_gi = 0, he_ltf = 0;
+
+ ppdu_info->he_flags = 1;
+
+ info0 = __le32_to_cpu(he_sig_a->info0);
+ info1 = __le32_to_cpu(he_sig_a->info1);
+
+ value = u32_get_bits(info0, HAL_RX_HE_SIG_A_SU_INFO_INFO0_FORMAT_IND);
+ if (value == 0)
+ ppdu_info->he_data1 = HE_TRIG_FORMAT_TYPE;
+ else
+ ppdu_info->he_data1 = HE_SU_FORMAT_TYPE;
+
+ ppdu_info->he_data1 |=
+ HE_BSS_COLOR_KNOWN |
+ HE_BEAM_CHANGE_KNOWN |
+ HE_DL_UL_KNOWN |
+ HE_MCS_KNOWN |
+ HE_DCM_KNOWN |
+ HE_CODING_KNOWN |
+ HE_LDPC_EXTRA_SYMBOL_KNOWN |
+ HE_STBC_KNOWN |
+ HE_DATA_BW_RU_KNOWN |
+ HE_DOPPLER_KNOWN;
+
+ ppdu_info->he_data2 |=
+ HE_GI_KNOWN |
+ HE_TXBF_KNOWN |
+ HE_PE_DISAMBIGUITY_KNOWN |
+ HE_TXOP_KNOWN |
+ HE_LTF_SYMBOLS_KNOWN |
+ HE_PRE_FEC_PADDING_KNOWN |
+ HE_MIDABLE_PERIODICITY_KNOWN;
+
+ ppdu_info->he_data3 = u32_get_bits(info0,
+ HAL_RX_HE_SIG_A_SU_INFO_INFO0_BSS_COLOR);
+ value = u32_get_bits(info0, HAL_RX_HE_SIG_A_SU_INFO_INFO0_BEAM_CHANGE);
+ value = value << HE_BEAM_CHANGE_SHIFT;
+ ppdu_info->he_data3 |= value;
+ value = u32_get_bits(info0, HAL_RX_HE_SIG_A_SU_INFO_INFO0_DL_UL_FLAG);
+ value = value << HE_DL_UL_SHIFT;
+ ppdu_info->he_data3 |= value;
+
+ value = u32_get_bits(info0, HAL_RX_HE_SIG_A_SU_INFO_INFO0_TRANSMIT_MCS);
+ ppdu_info->mcs = value;
+ value = value << HE_TRANSMIT_MCS_SHIFT;
+ ppdu_info->he_data3 |= value;
+
+ value = u32_get_bits(info0, HAL_RX_HE_SIG_A_SU_INFO_INFO0_DCM);
+ he_dcm = value;
+ value = value << HE_DCM_SHIFT;
+ ppdu_info->he_data3 |= value;
+ value = u32_get_bits(info1, HAL_RX_HE_SIG_A_SU_INFO_INFO1_CODING);
+ value = value << HE_CODING_SHIFT;
+ ppdu_info->he_data3 |= value;
+ value = u32_get_bits(info1, HAL_RX_HE_SIG_A_SU_INFO_INFO1_LDPC_EXTRA);
+ value = value << HE_LDPC_EXTRA_SYMBOL_SHIFT;
+ ppdu_info->he_data3 |= value;
+ value = u32_get_bits(info1, HAL_RX_HE_SIG_A_SU_INFO_INFO1_STBC);
+ he_stbc = value;
+ value = value << HE_STBC_SHIFT;
+ ppdu_info->he_data3 |= value;
+
+ /* data4 */
+ ppdu_info->he_data4 = u32_get_bits(info0,
+ HAL_RX_HE_SIG_A_SU_INFO_INFO0_SPATIAL_REUSE);
+
+ /* data5 */
+ value = u32_get_bits(info0,
+ HAL_RX_HE_SIG_A_SU_INFO_INFO0_TRANSMIT_BW);
+ ppdu_info->he_data5 = value;
+ ppdu_info->bw = value;
+ value = u32_get_bits(info0, HAL_RX_HE_SIG_A_SU_INFO_INFO0_CP_LTF_SIZE);
+ switch (value) {
+ case 0:
+ he_gi = HE_GI_0_8;
+ he_ltf = HE_LTF_1_X;
+ break;
+ case 1:
+ he_gi = HE_GI_0_8;
+ he_ltf = HE_LTF_2_X;
+ break;
+ case 2:
+ he_gi = HE_GI_1_6;
+ he_ltf = HE_LTF_2_X;
+ break;
+ case 3:
+ if (he_dcm && he_stbc) {
+ he_gi = HE_GI_0_8;
+ he_ltf = HE_LTF_4_X;
+ } else {
+ he_gi = HE_GI_3_2;
+ he_ltf = HE_LTF_4_X;
+ }
+ break;
+ }
+ ppdu_info->gi = he_gi;
+ value = he_gi << HE_GI_SHIFT;
+ ppdu_info->he_data5 |= value;
+ value = he_ltf << HE_LTF_SIZE_SHIFT;
+ ppdu_info->ltf_size = he_ltf;
+ ppdu_info->he_data5 |= value;
+
+ value = u32_get_bits(info0, HAL_RX_HE_SIG_A_SU_INFO_INFO0_NSTS);
+ value = (value << HE_LTF_SYM_SHIFT);
+ ppdu_info->he_data5 |= value;
+
+ value = u32_get_bits(info1, HAL_RX_HE_SIG_A_SU_INFO_INFO1_PKT_EXT_FACTOR);
+ value = value << HE_PRE_FEC_PAD_SHIFT;
+ ppdu_info->he_data5 |= value;
+
+ value = u32_get_bits(info1, HAL_RX_HE_SIG_A_SU_INFO_INFO1_TXBF);
+ value = value << HE_TXBF_SHIFT;
+ ppdu_info->he_data5 |= value;
+ value = u32_get_bits(info1, HAL_RX_HE_SIG_A_SU_INFO_INFO1_PKT_EXT_PE_DISAM);
+ value = value << HE_PE_DISAMBIGUITY_SHIFT;
+ ppdu_info->he_data5 |= value;
+
+ /* data6 */
+ value = u32_get_bits(info0, HAL_RX_HE_SIG_A_SU_INFO_INFO0_NSTS);
+ value++;
+ ppdu_info->he_data6 = value;
+ value = u32_get_bits(info1, HAL_RX_HE_SIG_A_SU_INFO_INFO1_DOPPLER_IND);
+ value = value << HE_DOPPLER_SHIFT;
+ ppdu_info->he_data6 |= value;
+ value = u32_get_bits(info1, HAL_RX_HE_SIG_A_SU_INFO_INFO1_TXOP_DURATION);
+ value = value << HE_TXOP_SHIFT;
+ ppdu_info->he_data6 |= value;
+
+ ppdu_info->mcs =
+ u32_get_bits(info0, HAL_RX_HE_SIG_A_SU_INFO_INFO0_TRANSMIT_MCS);
+ ppdu_info->bw =
+ u32_get_bits(info0, HAL_RX_HE_SIG_A_SU_INFO_INFO0_TRANSMIT_BW);
+ ppdu_info->ldpc = u32_get_bits(info1, HAL_RX_HE_SIG_A_SU_INFO_INFO1_CODING);
+ ppdu_info->is_stbc = u32_get_bits(info1, HAL_RX_HE_SIG_A_SU_INFO_INFO1_STBC);
+ ppdu_info->beamformed = u32_get_bits(info1, HAL_RX_HE_SIG_A_SU_INFO_INFO1_TXBF);
+ dcm = u32_get_bits(info0, HAL_RX_HE_SIG_A_SU_INFO_INFO0_DCM);
+ ppdu_info->nss = u32_get_bits(info0,
+ HAL_RX_HE_SIG_A_SU_INFO_INFO0_NSTS) + 1;
+ ppdu_info->dcm = dcm;
+}
+
+static inline bool
+ath12k_wifi7_dp_mon_hal_rx_is_non_ofdma(const struct hal_rx_u_sig_info *usig_info)
+{
+ u32 ppdu_type_comp_mode = usig_info->ppdu_type_comp_mode;
+ u32 ul_dl = usig_info->ul_dl;
+
+ if ((ppdu_type_comp_mode == HAL_RX_RECEPTION_TYPE_MU_MIMO && ul_dl == 0) ||
+ (ppdu_type_comp_mode == HAL_RX_RECEPTION_TYPE_MU_OFDMA && ul_dl == 0) ||
+ (ppdu_type_comp_mode == HAL_RX_RECEPTION_TYPE_MU_MIMO && ul_dl == 1))
+ return true;
+
+ return false;
+}
+
+static inline bool
+ath12k_wifi7_dp_mon_hal_rx_is_ofdma(const struct hal_rx_u_sig_info *usig_info)
+{
+ if (usig_info->ppdu_type_comp_mode == 0 && usig_info->ul_dl == 0)
+ return true;
+
+ return false;
+}
+
+static inline bool
+ath12k_wifi7_dp_mon_hal_rx_is_frame_type_ndp(const struct hal_rx_u_sig_info *usig_info)
+{
+ if (usig_info->ppdu_type_comp_mode == 1 &&
+ usig_info->eht_sig_mcs == 0 &&
+ usig_info->num_eht_sig_sym == 0)
+ return true;
+
+ return false;
+}
+
+static void
+ath12k_wifi7_dp_mon_hal_rx_parse_eht_sig_ndp(const struct hal_eht_sig_ndp_cmn_eb *eht_sig_ndp,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ struct hal_rx_radiotap_eht *eht = &ppdu_info->eht_info.eht;
+ u32 known, data;
+
+ known = __le32_to_cpu(eht->known);
+ known |= IEEE80211_RADIOTAP_EHT_KNOWN_SPATIAL_REUSE |
+ IEEE80211_RADIOTAP_EHT_KNOWN_EHT_LTF |
+ IEEE80211_RADIOTAP_EHT_KNOWN_NSS_S |
+ IEEE80211_RADIOTAP_EHT_KNOWN_BEAMFORMED_S |
+ IEEE80211_RADIOTAP_EHT_KNOWN_DISREGARD_S |
+ IEEE80211_RADIOTAP_EHT_KNOWN_CRC1 |
+ IEEE80211_RADIOTAP_EHT_KNOWN_TAIL1;
+ eht->known = cpu_to_le32(known);
+
+ data = __le32_to_cpu(eht->data[0]);
+ data |= ATH12K_LE32_DEC_ENC(eht_sig_ndp->info0,
+ HAL_RX_EHT_SIG_NDP_CMN_INFO0_SPATIAL_REUSE,
+ IEEE80211_RADIOTAP_EHT_DATA0_SPATIAL_REUSE);
+ /* GI and LTF size are separately indicated in radiotap header
+ * and hence will be parsed from other TLV
+ */
+ data |= ATH12K_LE32_DEC_ENC(eht_sig_ndp->info0,
+ HAL_RX_EHT_SIG_NDP_CMN_INFO0_NUM_LTF_SYM,
+ IEEE80211_RADIOTAP_EHT_DATA0_EHT_LTF);
+
+ data |= ATH12K_LE32_DEC_ENC(eht_sig_ndp->info0,
+ HAL_RX_EHT_SIG_NDP_CMN_INFO0_CRC,
+ IEEE80211_RADIOTAP_EHT_DATA0_CRC1_O);
+
+ data |= ATH12K_LE32_DEC_ENC(eht_sig_ndp->info0,
+ HAL_RX_EHT_SIG_NDP_CMN_INFO0_DISREGARD,
+ IEEE80211_RADIOTAP_EHT_DATA0_DISREGARD_S);
+ eht->data[0] = cpu_to_le32(data);
+
+ data = __le32_to_cpu(eht->data[7]);
+ data |= ATH12K_LE32_DEC_ENC(eht_sig_ndp->info0,
+ HAL_RX_EHT_SIG_NDP_CMN_INFO0_NSS,
+ IEEE80211_RADIOTAP_EHT_DATA7_NSS_S);
+
+ data |= ATH12K_LE32_DEC_ENC(eht_sig_ndp->info0,
+ HAL_RX_EHT_SIG_NDP_CMN_INFO0_BEAMFORMED,
+ IEEE80211_RADIOTAP_EHT_DATA7_BEAMFORMED_S);
+ eht->data[7] = cpu_to_le32(data);
+}
+
+static void
+ath12k_wifi7_dp_mon_hal_rx_parse_usig_overflow(const struct hal_eht_sig_usig_overflow *ovflow,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ struct hal_rx_radiotap_eht *eht = &ppdu_info->eht_info.eht;
+ u32 known, data;
+
+ known = __le32_to_cpu(eht->known);
+ known |= IEEE80211_RADIOTAP_EHT_KNOWN_SPATIAL_REUSE |
+ IEEE80211_RADIOTAP_EHT_KNOWN_EHT_LTF |
+ IEEE80211_RADIOTAP_EHT_KNOWN_LDPC_EXTRA_SYM_OM |
+ IEEE80211_RADIOTAP_EHT_KNOWN_PRE_PADD_FACOR_OM |
+ IEEE80211_RADIOTAP_EHT_KNOWN_PE_DISAMBIGUITY_OM |
+ IEEE80211_RADIOTAP_EHT_KNOWN_DISREGARD_O;
+ eht->known = cpu_to_le32(known);
+
+ data = __le32_to_cpu(eht->data[0]);
+ data |= ATH12K_LE32_DEC_ENC(ovflow->info0,
+ HAL_RX_EHT_SIG_OVERFLOW_INFO0_SPATIAL_REUSE,
+ IEEE80211_RADIOTAP_EHT_DATA0_SPATIAL_REUSE);
+
+ /* GI and LTF size are separately indicated in radiotap header
+ * and hence will be parsed from other TLV
+ */
+ data |= ATH12K_LE32_DEC_ENC(ovflow->info0,
+ HAL_RX_EHT_SIG_OVERFLOW_INFO0_NUM_LTF_SYM,
+ IEEE80211_RADIOTAP_EHT_DATA0_EHT_LTF);
+
+ data |= ATH12K_LE32_DEC_ENC(ovflow->info0,
+ HAL_RX_EHT_SIG_OVERFLOW_INFO0_LDPC_EXTA_SYM,
+ IEEE80211_RADIOTAP_EHT_DATA0_LDPC_EXTRA_SYM_OM);
+
+ data |= ATH12K_LE32_DEC_ENC(ovflow->info0,
+ HAL_RX_EHT_SIG_OVERFLOW_INFO0_PRE_FEC_PAD_FACTOR,
+ IEEE80211_RADIOTAP_EHT_DATA0_PRE_PADD_FACOR_OM);
+
+ data |= ATH12K_LE32_DEC_ENC(ovflow->info0,
+ HAL_RX_EHT_SIG_OVERFLOW_INFO0_DISAMBIGUITY,
+ IEEE80211_RADIOTAP_EHT_DATA0_PE_DISAMBIGUITY_OM);
+
+ data |= ATH12K_LE32_DEC_ENC(ovflow->info0,
+ HAL_RX_EHT_SIG_OVERFLOW_INFO0_DISREGARD,
+ IEEE80211_RADIOTAP_EHT_DATA0_DISREGARD_O);
+ eht->data[0] = cpu_to_le32(data);
+}
+
+static void
+ath12k_wifi7_dp_mon_hal_rx_parse_non_ofdma_users(const struct hal_eht_sig_non_ofdma_cmn_eb *eb,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ struct hal_rx_radiotap_eht *eht = &ppdu_info->eht_info.eht;
+ u32 known, data;
+
+ known = __le32_to_cpu(eht->known);
+ known |= IEEE80211_RADIOTAP_EHT_KNOWN_NR_NON_OFDMA_USERS_M;
+ eht->known = cpu_to_le32(known);
+
+ data = __le32_to_cpu(eht->data[7]);
+ data |= ATH12K_LE32_DEC_ENC(eb->info0,
+ HAL_RX_EHT_SIG_NON_OFDMA_INFO0_NUM_USERS,
+ IEEE80211_RADIOTAP_EHT_DATA7_NUM_OF_NON_OFDMA_USERS);
+ eht->data[7] = cpu_to_le32(data);
+}
+
+static void
+ath12k_wifi7_dp_mon_hal_rx_parse_eht_mumimo_user(const struct hal_eht_sig_mu_mimo *user,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ struct hal_rx_eht_info *eht_info = &ppdu_info->eht_info;
+ u32 user_idx;
+
+ if (eht_info->num_user_info >= ARRAY_SIZE(eht_info->user_info))
+ return;
+
+ user_idx = eht_info->num_user_info++;
+
+ eht_info->user_info[user_idx] |=
+ IEEE80211_RADIOTAP_EHT_USER_INFO_STA_ID_KNOWN |
+ IEEE80211_RADIOTAP_EHT_USER_INFO_MCS_KNOWN |
+ IEEE80211_RADIOTAP_EHT_USER_INFO_CODING_KNOWN |
+ IEEE80211_RADIOTAP_EHT_USER_INFO_SPATIAL_CONFIG_KNOWN_M |
+ ATH12K_LE32_DEC_ENC(user->info0,
+ HAL_RX_EHT_SIG_MUMIMO_USER_INFO0_STA_ID,
+ IEEE80211_RADIOTAP_EHT_USER_INFO_STA_ID) |
+ ATH12K_LE32_DEC_ENC(user->info0,
+ HAL_RX_EHT_SIG_MUMIMO_USER_INFO0_CODING,
+ IEEE80211_RADIOTAP_EHT_USER_INFO_CODING) |
+ ATH12K_LE32_DEC_ENC(user->info0,
+ HAL_RX_EHT_SIG_MUMIMO_USER_INFO0_MCS,
+ IEEE80211_RADIOTAP_EHT_USER_INFO_MCS) |
+ ATH12K_LE32_DEC_ENC(user->info0,
+ HAL_RX_EHT_SIG_MUMIMO_USER_INFO0_SPATIAL_CODING,
+ IEEE80211_RADIOTAP_EHT_USER_INFO_SPATIAL_CONFIG_M);
+
+ ppdu_info->mcs = le32_get_bits(user->info0,
+ HAL_RX_EHT_SIG_MUMIMO_USER_INFO0_MCS);
+}
+
+static void
+ath12k_wifi7_dp_mon_hal_rx_parse_eht_non_mumimo_user(const struct hal_eht_sig_non_mu_mimo *user,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ struct hal_rx_eht_info *eht_info = &ppdu_info->eht_info;
+ u32 user_idx;
+
+ if (eht_info->num_user_info >= ARRAY_SIZE(eht_info->user_info))
+ return;
+
+ user_idx = eht_info->num_user_info++;
+
+ eht_info->user_info[user_idx] |=
+ IEEE80211_RADIOTAP_EHT_USER_INFO_STA_ID_KNOWN |
+ IEEE80211_RADIOTAP_EHT_USER_INFO_MCS_KNOWN |
+ IEEE80211_RADIOTAP_EHT_USER_INFO_CODING_KNOWN |
+ IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_KNOWN_O |
+ IEEE80211_RADIOTAP_EHT_USER_INFO_BEAMFORMING_KNOWN_O |
+ ATH12K_LE32_DEC_ENC(user->info0,
+ HAL_RX_EHT_SIG_NON_MUMIMO_USER_INFO0_STA_ID,
+ IEEE80211_RADIOTAP_EHT_USER_INFO_STA_ID) |
+ ATH12K_LE32_DEC_ENC(user->info0,
+ HAL_RX_EHT_SIG_NON_MUMIMO_USER_INFO0_CODING,
+ IEEE80211_RADIOTAP_EHT_USER_INFO_CODING) |
+ ATH12K_LE32_DEC_ENC(user->info0,
+ HAL_RX_EHT_SIG_NON_MUMIMO_USER_INFO0_MCS,
+ IEEE80211_RADIOTAP_EHT_USER_INFO_MCS) |
+ ATH12K_LE32_DEC_ENC(user->info0,
+ HAL_RX_EHT_SIG_NON_MUMIMO_USER_INFO0_NSS,
+ IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_O) |
+ ATH12K_LE32_DEC_ENC(user->info0,
+ HAL_RX_EHT_SIG_NON_MUMIMO_USER_INFO0_BEAMFORMED,
+ IEEE80211_RADIOTAP_EHT_USER_INFO_BEAMFORMING_O);
+
+ ppdu_info->mcs = le32_get_bits(user->info0,
+ HAL_RX_EHT_SIG_NON_MUMIMO_USER_INFO0_MCS);
+
+ ppdu_info->nss = le32_get_bits(user->info0,
+ HAL_RX_EHT_SIG_NON_MUMIMO_USER_INFO0_NSS) + 1;
+}
+
+static inline bool
+ath12k_wifi7_dp_mon_hal_rx_is_mu_mimo_user(const struct hal_rx_u_sig_info *usig_info)
+{
+ if (usig_info->ppdu_type_comp_mode == HAL_RX_RECEPTION_TYPE_SU &&
+ usig_info->ul_dl == 1)
+ return true;
+
+ return false;
+}
+
+static void
+ath12k_wifi7_dp_mon_hal_rx_parse_eht_sig_non_ofdma(const void *tlv,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ const struct hal_eht_sig_non_ofdma_cmn_eb *eb = tlv;
+
+ ath12k_wifi7_dp_mon_hal_rx_parse_usig_overflow(tlv, ppdu_info);
+ ath12k_wifi7_dp_mon_hal_rx_parse_non_ofdma_users(eb, ppdu_info);
+
+ if (ath12k_wifi7_dp_mon_hal_rx_is_mu_mimo_user(&ppdu_info->u_sig_info))
+ ath12k_wifi7_dp_mon_hal_rx_parse_eht_mumimo_user(&eb->user_field.mu_mimo,
+ ppdu_info);
+ else
+ ath12k_wifi7_dp_mon_hal_rx_parse_eht_non_mumimo_user(&eb->user_field.n_mu_mimo,
+ ppdu_info);
+}
+
+static void
+ath12k_wifi7_dp_mon_hal_rx_parse_ru_allocation(const struct hal_eht_sig_ofdma_cmn_eb *eb,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ const struct hal_eht_sig_ofdma_cmn_eb1 *ofdma_cmn_eb1 = &eb->eb1;
+ const struct hal_eht_sig_ofdma_cmn_eb2 *ofdma_cmn_eb2 = &eb->eb2;
+ struct hal_rx_radiotap_eht *eht = &ppdu_info->eht_info.eht;
+ enum ieee80211_radiotap_eht_data ru_123, ru_124, ru_125, ru_126;
+ enum ieee80211_radiotap_eht_data ru_121, ru_122, ru_112, ru_111;
+ u32 data;
+
+ ru_123 = IEEE80211_RADIOTAP_EHT_DATA4_RU_ALLOC_CC_1_2_3;
+ ru_124 = IEEE80211_RADIOTAP_EHT_DATA5_RU_ALLOC_CC_1_2_4;
+ ru_125 = IEEE80211_RADIOTAP_EHT_DATA5_RU_ALLOC_CC_1_2_5;
+ ru_126 = IEEE80211_RADIOTAP_EHT_DATA6_RU_ALLOC_CC_1_2_6;
+ ru_121 = IEEE80211_RADIOTAP_EHT_DATA3_RU_ALLOC_CC_1_2_1;
+ ru_122 = IEEE80211_RADIOTAP_EHT_DATA3_RU_ALLOC_CC_1_2_2;
+ ru_112 = IEEE80211_RADIOTAP_EHT_DATA2_RU_ALLOC_CC_1_1_2;
+ ru_111 = IEEE80211_RADIOTAP_EHT_DATA1_RU_ALLOC_CC_1_1_1;
+
+ switch (ppdu_info->u_sig_info.bw) {
+ case HAL_EHT_BW_320_2:
+ case HAL_EHT_BW_320_1:
+ data = __le32_to_cpu(eht->data[4]);
+ /* CC1 2::3 */
+ data |= IEEE80211_RADIOTAP_EHT_DATA4_RU_ALLOC_CC_1_2_3_KNOWN |
+ ATH12K_LE64_DEC_ENC(ofdma_cmn_eb2->info0,
+ HAL_RX_EHT_SIG_OFDMA_EB2_RU_ALLOC_2_3,
+ ru_123);
+ eht->data[4] = cpu_to_le32(data);
+
+ data = __le32_to_cpu(eht->data[5]);
+ /* CC1 2::4 */
+ data |= IEEE80211_RADIOTAP_EHT_DATA5_RU_ALLOC_CC_1_2_4_KNOWN |
+ ATH12K_LE64_DEC_ENC(ofdma_cmn_eb2->info0,
+ HAL_RX_EHT_SIG_OFDMA_EB2_RU_ALLOC_2_4,
+ ru_124);
+
+ /* CC1 2::5 */
+ data |= IEEE80211_RADIOTAP_EHT_DATA5_RU_ALLOC_CC_1_2_5_KNOWN |
+ ATH12K_LE64_DEC_ENC(ofdma_cmn_eb2->info0,
+ HAL_RX_EHT_SIG_OFDMA_EB2_RU_ALLOC_2_5,
+ ru_125);
+ eht->data[5] = cpu_to_le32(data);
+
+ data = __le32_to_cpu(eht->data[6]);
+ /* CC1 2::6 */
+ data |= IEEE80211_RADIOTAP_EHT_DATA6_RU_ALLOC_CC_1_2_6_KNOWN |
+ ATH12K_LE64_DEC_ENC(ofdma_cmn_eb2->info0,
+ HAL_RX_EHT_SIG_OFDMA_EB2_RU_ALLOC_2_6,
+ ru_126);
+ eht->data[6] = cpu_to_le32(data);
+
+ fallthrough;
+ case HAL_EHT_BW_160:
+ data = __le32_to_cpu(eht->data[3]);
+ /* CC1 2::1 */
+ data |= IEEE80211_RADIOTAP_EHT_DATA3_RU_ALLOC_CC_1_2_1_KNOWN |
+ ATH12K_LE64_DEC_ENC(ofdma_cmn_eb2->info0,
+ HAL_RX_EHT_SIG_OFDMA_EB2_RU_ALLOC_2_1,
+ ru_121);
+ /* CC1 2::2 */
+ data |= IEEE80211_RADIOTAP_EHT_DATA3_RU_ALLOC_CC_1_2_2_KNOWN |
+ ATH12K_LE64_DEC_ENC(ofdma_cmn_eb2->info0,
+ HAL_RX_EHT_SIG_OFDMA_EB2_RU_ALLOC_2_2,
+ ru_122);
+ eht->data[3] = cpu_to_le32(data);
+
+ fallthrough;
+ case HAL_EHT_BW_80:
+ data = __le32_to_cpu(eht->data[2]);
+ /* CC1 1::2 */
+ data |= IEEE80211_RADIOTAP_EHT_DATA2_RU_ALLOC_CC_1_1_2_KNOWN |
+ ATH12K_LE64_DEC_ENC(ofdma_cmn_eb1->info0,
+ HAL_RX_EHT_SIG_OFDMA_EB1_RU_ALLOC_1_2,
+ ru_112);
+ eht->data[2] = cpu_to_le32(data);
+
+ fallthrough;
+ case HAL_EHT_BW_40:
+ fallthrough;
+ case HAL_EHT_BW_20:
+ data = __le32_to_cpu(eht->data[1]);
+ /* CC1 1::1 */
+ data |= IEEE80211_RADIOTAP_EHT_DATA1_RU_ALLOC_CC_1_1_1_KNOWN |
+ ATH12K_LE64_DEC_ENC(ofdma_cmn_eb1->info0,
+ HAL_RX_EHT_SIG_OFDMA_EB1_RU_ALLOC_1_1,
+ ru_111);
+ eht->data[1] = cpu_to_le32(data);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+ath12k_wifi7_dp_mon_hal_rx_parse_eht_sig_ofdma(const void *tlv,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ const struct hal_eht_sig_ofdma_cmn_eb *ofdma = tlv;
+
+ ath12k_wifi7_dp_mon_hal_rx_parse_usig_overflow(tlv, ppdu_info);
+ ath12k_wifi7_dp_mon_hal_rx_parse_ru_allocation(ofdma, ppdu_info);
+
+ ath12k_wifi7_dp_mon_hal_rx_parse_eht_non_mumimo_user(&ofdma->user_field.n_mu_mimo,
+ ppdu_info);
+}
+
+static void
+ath12k_wifi7_dp_mon_parse_eht_sig_hdr(struct hal_rx_mon_ppdu_info *ppdu_info,
+ const void *tlv_data)
+{
+ ppdu_info->is_eht = true;
+
+ if (ath12k_wifi7_dp_mon_hal_rx_is_frame_type_ndp(&ppdu_info->u_sig_info))
+ ath12k_wifi7_dp_mon_hal_rx_parse_eht_sig_ndp(tlv_data, ppdu_info);
+ else if (ath12k_wifi7_dp_mon_hal_rx_is_non_ofdma(&ppdu_info->u_sig_info))
+ ath12k_wifi7_dp_mon_hal_rx_parse_eht_sig_non_ofdma(tlv_data, ppdu_info);
+ else if (ath12k_wifi7_dp_mon_hal_rx_is_ofdma(&ppdu_info->u_sig_info))
+ ath12k_wifi7_dp_mon_hal_rx_parse_eht_sig_ofdma(tlv_data, ppdu_info);
+}
+
+static void ath12k_wifi7_dp_mon_parse_rx_msdu_end_err(u32 info, u32 *errmap)
+{
+ if (info & RX_MSDU_END_INFO13_FCS_ERR)
+ *errmap |= HAL_RX_MPDU_ERR_FCS;
+
+ if (info & RX_MSDU_END_INFO13_DECRYPT_ERR)
+ *errmap |= HAL_RX_MPDU_ERR_DECRYPT;
+
+ if (info & RX_MSDU_END_INFO13_TKIP_MIC_ERR)
+ *errmap |= HAL_RX_MPDU_ERR_TKIP_MIC;
+
+ if (info & RX_MSDU_END_INFO13_A_MSDU_ERROR)
+ *errmap |= HAL_RX_MPDU_ERR_AMSDU_ERR;
+
+ if (info & RX_MSDU_END_INFO13_OVERFLOW_ERR)
+ *errmap |= HAL_RX_MPDU_ERR_OVERFLOW;
+
+ if (info & RX_MSDU_END_INFO13_MSDU_LEN_ERR)
+ *errmap |= HAL_RX_MPDU_ERR_MSDU_LEN;
+
+ if (info & RX_MSDU_END_INFO13_MPDU_LEN_ERR)
+ *errmap |= HAL_RX_MPDU_ERR_MPDU_LEN;
+}
+
+static void
+ath12k_wifi7_parse_cmn_usr_info(const struct hal_phyrx_common_user_info *cmn_usr_info,
+ struct hal_rx_mon_ppdu_info *ppdu_info)
+{
+ struct hal_rx_radiotap_eht *eht = &ppdu_info->eht_info.eht;
+ u32 known, data, cp_setting, ltf_size;
+
+ known = __le32_to_cpu(eht->known);
+ known |= IEEE80211_RADIOTAP_EHT_KNOWN_GI |
+ IEEE80211_RADIOTAP_EHT_KNOWN_EHT_LTF;
+ eht->known = cpu_to_le32(known);
+
+ cp_setting = le32_get_bits(cmn_usr_info->info0,
+ HAL_RX_CMN_USR_INFO0_CP_SETTING);
+ ltf_size = le32_get_bits(cmn_usr_info->info0,
+ HAL_RX_CMN_USR_INFO0_LTF_SIZE);
+
+ data = __le32_to_cpu(eht->data[0]);
+ data |= u32_encode_bits(cp_setting, IEEE80211_RADIOTAP_EHT_DATA0_GI);
+ data |= u32_encode_bits(ltf_size, IEEE80211_RADIOTAP_EHT_DATA0_LTF);
+ eht->data[0] = cpu_to_le32(data);
+
+ if (!ppdu_info->ltf_size)
+ ppdu_info->ltf_size = ltf_size;
+ if (!ppdu_info->gi)
+ ppdu_info->gi = cp_setting;
+}
+
+static void
+ath12k_wifi7_dp_mon_parse_status_msdu_end(struct ath12k_mon_data *pmon,
+ const struct hal_rx_msdu_end *msdu_end)
+{
+ ath12k_wifi7_dp_mon_parse_rx_msdu_end_err(__le32_to_cpu(msdu_end->info2),
+ &pmon->err_bitmap);
+ pmon->decap_format = le32_get_bits(msdu_end->info1,
+ RX_MSDU_END_INFO11_DECAP_FORMAT);
+}
+
+static enum hal_rx_mon_status
+ath12k_wifi7_dp_mon_rx_parse_status_tlv(struct ath12k_pdev_dp *dp_pdev,
+ struct ath12k_mon_data *pmon,
+ const struct hal_tlv_64_hdr *tlv)
+{
+ struct hal_rx_mon_ppdu_info *ppdu_info = &pmon->mon_ppdu_info;
+ const void *tlv_data = tlv->value;
+ u32 info[7], userid;
+ u16 tlv_tag, tlv_len;
+
+ tlv_tag = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_TAG);
+ tlv_len = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_LEN);
+ userid = le64_get_bits(tlv->tl, HAL_TLV_64_USR_ID);
+
+ if (ppdu_info->tlv_aggr.in_progress && ppdu_info->tlv_aggr.tlv_tag != tlv_tag) {
+ ath12k_wifi7_dp_mon_parse_eht_sig_hdr(ppdu_info,
+ ppdu_info->tlv_aggr.buf);
+
+ ppdu_info->tlv_aggr.in_progress = false;
+ ppdu_info->tlv_aggr.cur_len = 0;
+ }
+
+ switch (tlv_tag) {
+ case HAL_RX_PPDU_START: {
+ const struct hal_rx_ppdu_start *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);
+
+ 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;
+ ppdu_info->num_users = 0;
+ memset(&ppdu_info->mpdu_fcs_ok_bitmap, 0,
+ HAL_RX_NUM_WORDS_PER_PPDU_BITMAP *
+ sizeof(ppdu_info->mpdu_fcs_ok_bitmap[0]));
+ }
+ break;
+ }
+ case HAL_RX_PPDU_END_USER_STATS: {
+ const struct hal_rx_ppdu_end_user_stats *eu_stats = tlv_data;
+ u32 tid_bitmap;
+
+ info[0] = __le32_to_cpu(eu_stats->info0);
+ info[1] = __le32_to_cpu(eu_stats->info1);
+ info[2] = __le32_to_cpu(eu_stats->info2);
+ info[4] = __le32_to_cpu(eu_stats->info4);
+ info[5] = __le32_to_cpu(eu_stats->info5);
+ info[6] = __le32_to_cpu(eu_stats->info6);
+
+ ppdu_info->ast_index =
+ u32_get_bits(info[2], HAL_RX_PPDU_END_USER_STATS_INFO2_AST_INDEX);
+ ppdu_info->fc_valid =
+ u32_get_bits(info[1], HAL_RX_PPDU_END_USER_STATS_INFO1_FC_VALID);
+ tid_bitmap = u32_get_bits(info[6],
+ HAL_RX_PPDU_END_USER_STATS_INFO6_TID_BITMAP);
+ ppdu_info->tid = ffs(tid_bitmap) - 1;
+ ppdu_info->tcp_msdu_count =
+ u32_get_bits(info[4],
+ HAL_RX_PPDU_END_USER_STATS_INFO4_TCP_MSDU_CNT);
+ ppdu_info->udp_msdu_count =
+ u32_get_bits(info[4],
+ HAL_RX_PPDU_END_USER_STATS_INFO4_UDP_MSDU_CNT);
+ ppdu_info->other_msdu_count =
+ u32_get_bits(info[5],
+ HAL_RX_PPDU_END_USER_STATS_INFO5_OTHER_MSDU_CNT);
+ ppdu_info->tcp_ack_msdu_count =
+ u32_get_bits(info[5],
+ HAL_RX_PPDU_END_USER_STATS_INFO5_TCP_ACK_MSDU_CNT);
+ ppdu_info->preamble_type =
+ u32_get_bits(info[1],
+ HAL_RX_PPDU_END_USER_STATS_INFO1_PKT_TYPE);
+ ppdu_info->num_mpdu_fcs_ok =
+ u32_get_bits(info[1],
+ HAL_RX_PPDU_END_USER_STATS_INFO1_MPDU_CNT_FCS_OK);
+ ppdu_info->num_mpdu_fcs_err =
+ u32_get_bits(info[0],
+ HAL_RX_PPDU_END_USER_STATS_INFO0_MPDU_CNT_FCS_ERR);
+ ppdu_info->peer_id =
+ u32_get_bits(info[0], HAL_RX_PPDU_END_USER_STATS_INFO0_PEER_ID);
+
+ switch (ppdu_info->preamble_type) {
+ case HAL_RX_PREAMBLE_11N:
+ ppdu_info->ht_flags = 1;
+ break;
+ case HAL_RX_PREAMBLE_11AC:
+ ppdu_info->vht_flags = 1;
+ break;
+ case HAL_RX_PREAMBLE_11AX:
+ ppdu_info->he_flags = 1;
+ break;
+ case HAL_RX_PREAMBLE_11BE:
+ ppdu_info->is_eht = true;
+ break;
+ default:
+ break;
+ }
+
+ if (userid < HAL_MAX_UL_MU_USERS) {
+ struct hal_rx_user_status *rxuser_stats =
+ &ppdu_info->userstats[userid];
+
+ if (ppdu_info->num_mpdu_fcs_ok > 1 ||
+ ppdu_info->num_mpdu_fcs_err > 1)
+ ppdu_info->userstats[userid].ampdu_present = true;
+
+ ppdu_info->num_users += 1;
+
+ ath12k_wifi7_dp_mon_rx_handle_ofdma_info(eu_stats, rxuser_stats);
+ ath12k_wifi7_dp_mon_rx_populate_mu_user_info(eu_stats, ppdu_info,
+ rxuser_stats);
+ }
+ ppdu_info->mpdu_fcs_ok_bitmap[0] = __le32_to_cpu(eu_stats->rsvd1[0]);
+ ppdu_info->mpdu_fcs_ok_bitmap[1] = __le32_to_cpu(eu_stats->rsvd1[1]);
+ break;
+ }
+ case HAL_RX_PPDU_END_USER_STATS_EXT: {
+ const struct hal_rx_ppdu_end_user_stats_ext *eu_stats = tlv_data;
+
+ ppdu_info->mpdu_fcs_ok_bitmap[2] = __le32_to_cpu(eu_stats->info1);
+ ppdu_info->mpdu_fcs_ok_bitmap[3] = __le32_to_cpu(eu_stats->info2);
+ ppdu_info->mpdu_fcs_ok_bitmap[4] = __le32_to_cpu(eu_stats->info3);
+ ppdu_info->mpdu_fcs_ok_bitmap[5] = __le32_to_cpu(eu_stats->info4);
+ ppdu_info->mpdu_fcs_ok_bitmap[6] = __le32_to_cpu(eu_stats->info5);
+ ppdu_info->mpdu_fcs_ok_bitmap[7] = __le32_to_cpu(eu_stats->info6);
+ break;
+ }
+ case HAL_PHYRX_HT_SIG:
+ ath12k_wifi7_dp_mon_parse_ht_sig(tlv_data, ppdu_info);
+ break;
+
+ case HAL_PHYRX_L_SIG_B:
+ ath12k_wifi7_dp_mon_parse_l_sig_b(tlv_data, ppdu_info);
+ break;
+
+ case HAL_PHYRX_L_SIG_A:
+ ath12k_wifi7_dp_mon_parse_l_sig_a(tlv_data, ppdu_info);
+ break;
+
+ case HAL_PHYRX_VHT_SIG_A:
+ ath12k_wifi7_dp_mon_parse_vht_sig_a(tlv_data, ppdu_info);
+ break;
+
+ case HAL_PHYRX_HE_SIG_A_SU:
+ ath12k_wifi7_dp_mon_parse_he_sig_su(tlv_data, ppdu_info);
+ break;
+
+ case HAL_PHYRX_HE_SIG_A_MU_DL:
+ ath12k_wifi7_dp_mon_parse_he_sig_mu(tlv_data, ppdu_info);
+ break;
+
+ case HAL_PHYRX_HE_SIG_B1_MU:
+ ath12k_wifi7_dp_mon_parse_he_sig_b1_mu(tlv_data, ppdu_info);
+ break;
+
+ case HAL_PHYRX_HE_SIG_B2_MU:
+ ath12k_wifi7_dp_mon_parse_he_sig_b2_mu(tlv_data, ppdu_info);
+ break;
+
+ case HAL_PHYRX_HE_SIG_B2_OFDMA:
+ ath12k_wifi7_dp_mon_parse_he_sig_b2_ofdma(tlv_data, ppdu_info);
+ break;
+
+ case HAL_PHYRX_RSSI_LEGACY: {
+ const struct hal_rx_phyrx_rssi_legacy_info *rssi = tlv_data;
+
+ info[0] = __le32_to_cpu(rssi->info0);
+ info[2] = __le32_to_cpu(rssi->info2);
+
+ /* 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[2],
+ HAL_RX_RSSI_LEGACY_INFO_INFO2_RSSI_COMB_PPDU);
+
+ ppdu_info->bw = u32_get_bits(info[0],
+ HAL_RX_RSSI_LEGACY_INFO_INFO0_RX_BW);
+ break;
+ }
+ case HAL_PHYRX_COMMON_USER_INFO: {
+ ath12k_wifi7_parse_cmn_usr_info(tlv_data, ppdu_info);
+ break;
+ }
+ case HAL_RX_PPDU_START_USER_INFO:
+ ath12k_wifi7_dp_mon_hal_rx_parse_user_info(tlv_data, userid, ppdu_info);
+ break;
+
+ case HAL_RXPCU_PPDU_END_INFO: {
+ const struct hal_rx_ppdu_end_duration *ppdu_rx_duration = tlv_data;
+
+ info[0] = __le32_to_cpu(ppdu_rx_duration->info0);
+ ppdu_info->rx_duration =
+ u32_get_bits(info[0], HAL_RX_PPDU_END_DURATION);
+ ppdu_info->tsft = __le32_to_cpu(ppdu_rx_duration->rsvd0[1]);
+ ppdu_info->tsft = (ppdu_info->tsft << 32) |
+ __le32_to_cpu(ppdu_rx_duration->rsvd0[0]);
+ break;
+ }
+ case HAL_RX_MPDU_START: {
+ const struct hal_rx_mpdu_start *mpdu_start = tlv_data;
+ u16 peer_id;
+
+ info[1] = __le32_to_cpu(mpdu_start->info1);
+ peer_id = u32_get_bits(info[1], HAL_RX_MPDU_START_INFO1_PEERID);
+ if (peer_id)
+ ppdu_info->peer_id = peer_id;
+
+ ppdu_info->mpdu_len += u32_get_bits(info[1],
+ HAL_RX_MPDU_START_INFO2_MPDU_LEN);
+ if (userid < HAL_MAX_UL_MU_USERS) {
+ info[0] = __le32_to_cpu(mpdu_start->info0);
+ ppdu_info->userid = userid;
+ ppdu_info->userstats[userid].ampdu_id =
+ u32_get_bits(info[0], HAL_RX_MPDU_START_INFO0_PPDU_ID);
+ }
+
+ return HAL_RX_MON_STATUS_MPDU_START;
+ }
+ case HAL_RX_MSDU_START:
+ /* TODO: add msdu start parsing logic */
+ break;
+ case HAL_MON_BUF_ADDR:
+ return HAL_RX_MON_STATUS_BUF_ADDR;
+ case HAL_RX_MSDU_END:
+ ath12k_wifi7_dp_mon_parse_status_msdu_end(pmon, tlv_data);
+ return HAL_RX_MON_STATUS_MSDU_END;
+ case HAL_RX_MPDU_END:
+ return HAL_RX_MON_STATUS_MPDU_END;
+ case HAL_PHYRX_GENERIC_U_SIG:
+ ath12k_wifi7_dp_mon_hal_rx_parse_u_sig_hdr(tlv_data, ppdu_info);
+ break;
+ case HAL_PHYRX_GENERIC_EHT_SIG:
+ /* Handle the case where aggregation is in progress
+ * or the current TLV is one of the TLVs which should be
+ * aggregated
+ */
+ if (!ppdu_info->tlv_aggr.in_progress) {
+ ppdu_info->tlv_aggr.in_progress = true;
+ ppdu_info->tlv_aggr.tlv_tag = tlv_tag;
+ ppdu_info->tlv_aggr.cur_len = 0;
+ }
+
+ ppdu_info->is_eht = true;
+
+ ath12k_wifi7_dp_mon_hal_aggr_tlv(ppdu_info, tlv_len, tlv_data);
+ break;
+ case HAL_DUMMY:
+ return HAL_RX_MON_STATUS_BUF_DONE;
+ case HAL_RX_PPDU_END_STATUS_DONE:
+ case 0:
+ return HAL_RX_MON_STATUS_PPDU_DONE;
+ default:
+ break;
+ }
+
+ return HAL_RX_MON_STATUS_PPDU_NOT_DONE;
+}
+
+static int
+ath12k_wifi7_dp_mon_parse_rx_dest_tlv(struct ath12k_pdev_dp *dp_pdev,
+ struct ath12k_mon_data *pmon,
+ enum hal_rx_mon_status hal_status,
+ const void *tlv_data)
+{
+ switch (hal_status) {
+ case HAL_RX_MON_STATUS_MPDU_START:
+ if (WARN_ON_ONCE(pmon->mon_mpdu))
+ break;
+
+ pmon->mon_mpdu = kzalloc(sizeof(*pmon->mon_mpdu), GFP_ATOMIC);
+ if (!pmon->mon_mpdu)
+ return -ENOMEM;
+ break;
+ case HAL_RX_MON_STATUS_BUF_ADDR:
+ return ath12k_dp_mon_parse_status_buf(dp_pdev, pmon, tlv_data);
+ case HAL_RX_MON_STATUS_MPDU_END:
+ /* If no MSDU then free empty MPDU */
+ if (pmon->mon_mpdu->tail) {
+ pmon->mon_mpdu->tail->next = NULL;
+ list_add_tail(&pmon->mon_mpdu->list, &pmon->dp_rx_mon_mpdu_list);
+ } else {
+ kfree(pmon->mon_mpdu);
+ }
+ pmon->mon_mpdu = NULL;
+ break;
+ case HAL_RX_MON_STATUS_MSDU_END:
+ pmon->mon_mpdu->decap_format = pmon->decap_format;
+ pmon->mon_mpdu->err_bitmap = pmon->err_bitmap;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static struct dp_mon_tx_ppdu_info *
+ath12k_wifi7_dp_mon_tx_get_ppdu_info(struct ath12k_mon_data *pmon,
+ unsigned int ppdu_id,
+ enum dp_mon_tx_ppdu_info_type type)
+{
+ struct dp_mon_tx_ppdu_info *tx_ppdu_info;
+
+ if (type == DP_MON_TX_PROT_PPDU_INFO) {
+ tx_ppdu_info = pmon->tx_prot_ppdu_info;
+
+ if (tx_ppdu_info && !tx_ppdu_info->is_used)
+ return tx_ppdu_info;
+ kfree(tx_ppdu_info);
+ } else {
+ tx_ppdu_info = pmon->tx_data_ppdu_info;
+
+ if (tx_ppdu_info && !tx_ppdu_info->is_used)
+ return tx_ppdu_info;
+ kfree(tx_ppdu_info);
+ }
+
+ /* allocate new tx_ppdu_info */
+ tx_ppdu_info = kzalloc(sizeof(*tx_ppdu_info), GFP_ATOMIC);
+ if (!tx_ppdu_info)
+ return NULL;
+
+ tx_ppdu_info->is_used = 0;
+ tx_ppdu_info->ppdu_id = ppdu_id;
+
+ if (type == DP_MON_TX_PROT_PPDU_INFO)
+ pmon->tx_prot_ppdu_info = tx_ppdu_info;
+ else
+ pmon->tx_data_ppdu_info = tx_ppdu_info;
+
+ return tx_ppdu_info;
+}
+
+static struct dp_mon_tx_ppdu_info *
+ath12k_wifi7_dp_mon_hal_tx_ppdu_info(struct ath12k_mon_data *pmon,
+ u16 tlv_tag)
+{
+ switch (tlv_tag) {
+ case HAL_TX_FES_SETUP:
+ case HAL_TX_FLUSH:
+ case HAL_PCU_PPDU_SETUP_INIT:
+ case HAL_TX_PEER_ENTRY:
+ case HAL_TX_QUEUE_EXTENSION:
+ case HAL_TX_MPDU_START:
+ case HAL_TX_MSDU_START:
+ case HAL_TX_DATA:
+ case HAL_MON_BUF_ADDR:
+ case HAL_TX_MPDU_END:
+ case HAL_TX_LAST_MPDU_FETCHED:
+ case HAL_TX_LAST_MPDU_END:
+ case HAL_COEX_TX_REQ:
+ case HAL_TX_RAW_OR_NATIVE_FRAME_SETUP:
+ case HAL_SCH_CRITICAL_TLV_REFERENCE:
+ case HAL_TX_FES_SETUP_COMPLETE:
+ case HAL_TQM_MPDU_GLOBAL_START:
+ case HAL_SCHEDULER_END:
+ case HAL_TX_FES_STATUS_USER_PPDU:
+ break;
+ case HAL_TX_FES_STATUS_PROT: {
+ if (!pmon->tx_prot_ppdu_info->is_used)
+ pmon->tx_prot_ppdu_info->is_used = true;
+
+ return pmon->tx_prot_ppdu_info;
+ }
+ }
+
+ if (!pmon->tx_data_ppdu_info->is_used)
+ pmon->tx_data_ppdu_info->is_used = true;
+
+ return pmon->tx_data_ppdu_info;
+}
+
+#define MAX_MONITOR_HEADER 512
+#define MAX_DUMMY_FRM_BODY 128
+
+static struct
+sk_buff *ath12k_wifi7_dp_mon_tx_alloc_skb(void)
+{
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(MAX_MONITOR_HEADER + MAX_DUMMY_FRM_BODY);
+ if (!skb)
+ return NULL;
+
+ skb_reserve(skb, MAX_MONITOR_HEADER);
+
+ if (!IS_ALIGNED((unsigned long)skb->data, 4))
+ skb_pull(skb, PTR_ALIGN(skb->data, 4) - skb->data);
+
+ return skb;
+}
+
+static int
+ath12k_wifi7_dp_mon_tx_gen_cts2self_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
+{
+ struct sk_buff *skb;
+ struct ieee80211_cts *cts;
+
+ skb = ath12k_wifi7_dp_mon_tx_alloc_skb();
+ if (!skb)
+ return -ENOMEM;
+
+ cts = (struct ieee80211_cts *)skb->data;
+ memset(cts, 0, MAX_DUMMY_FRM_BODY);
+ cts->frame_control =
+ cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS);
+ cts->duration = cpu_to_le16(tx_ppdu_info->rx_status.rx_duration);
+ memcpy(cts->ra, tx_ppdu_info->rx_status.addr1, sizeof(cts->ra));
+
+ skb_put(skb, sizeof(*cts));
+ tx_ppdu_info->tx_mon_mpdu->head = skb;
+ tx_ppdu_info->tx_mon_mpdu->tail = NULL;
+ list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
+ &tx_ppdu_info->dp_tx_mon_mpdu_list);
+
+ return 0;
+}
+
+static int
+ath12k_wifi7_dp_mon_tx_gen_rts_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
+{
+ struct sk_buff *skb;
+ struct ieee80211_rts *rts;
+
+ skb = ath12k_wifi7_dp_mon_tx_alloc_skb();
+ if (!skb)
+ return -ENOMEM;
+
+ rts = (struct ieee80211_rts *)skb->data;
+ memset(rts, 0, MAX_DUMMY_FRM_BODY);
+ rts->frame_control =
+ cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
+ rts->duration = cpu_to_le16(tx_ppdu_info->rx_status.rx_duration);
+ memcpy(rts->ra, tx_ppdu_info->rx_status.addr1, sizeof(rts->ra));
+ memcpy(rts->ta, tx_ppdu_info->rx_status.addr2, sizeof(rts->ta));
+
+ skb_put(skb, sizeof(*rts));
+ tx_ppdu_info->tx_mon_mpdu->head = skb;
+ tx_ppdu_info->tx_mon_mpdu->tail = NULL;
+ list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
+ &tx_ppdu_info->dp_tx_mon_mpdu_list);
+
+ return 0;
+}
+
+static int
+ath12k_wifi7_dp_mon_tx_gen_3addr_qos_null_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
+{
+ struct sk_buff *skb;
+ struct ieee80211_qos_hdr *qhdr;
+
+ skb = ath12k_wifi7_dp_mon_tx_alloc_skb();
+ if (!skb)
+ return -ENOMEM;
+
+ qhdr = (struct ieee80211_qos_hdr *)skb->data;
+ memset(qhdr, 0, MAX_DUMMY_FRM_BODY);
+ qhdr->frame_control =
+ cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC);
+ qhdr->duration_id = cpu_to_le16(tx_ppdu_info->rx_status.rx_duration);
+ memcpy(qhdr->addr1, tx_ppdu_info->rx_status.addr1, ETH_ALEN);
+ memcpy(qhdr->addr2, tx_ppdu_info->rx_status.addr2, ETH_ALEN);
+ memcpy(qhdr->addr3, tx_ppdu_info->rx_status.addr3, ETH_ALEN);
+
+ skb_put(skb, sizeof(*qhdr));
+ tx_ppdu_info->tx_mon_mpdu->head = skb;
+ tx_ppdu_info->tx_mon_mpdu->tail = NULL;
+ list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
+ &tx_ppdu_info->dp_tx_mon_mpdu_list);
+
+ return 0;
+}
+
+static int
+ath12k_wifi7_dp_mon_tx_gen_4addr_qos_null_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
+{
+ struct sk_buff *skb;
+ struct dp_mon_qosframe_addr4 *qhdr;
+
+ skb = ath12k_wifi7_dp_mon_tx_alloc_skb();
+ if (!skb)
+ return -ENOMEM;
+
+ qhdr = (struct dp_mon_qosframe_addr4 *)skb->data;
+ memset(qhdr, 0, MAX_DUMMY_FRM_BODY);
+ qhdr->frame_control =
+ cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC);
+ qhdr->duration = cpu_to_le16(tx_ppdu_info->rx_status.rx_duration);
+ memcpy(qhdr->addr1, tx_ppdu_info->rx_status.addr1, ETH_ALEN);
+ memcpy(qhdr->addr2, tx_ppdu_info->rx_status.addr2, ETH_ALEN);
+ memcpy(qhdr->addr3, tx_ppdu_info->rx_status.addr3, ETH_ALEN);
+ memcpy(qhdr->addr4, tx_ppdu_info->rx_status.addr4, ETH_ALEN);
+
+ skb_put(skb, sizeof(*qhdr));
+ tx_ppdu_info->tx_mon_mpdu->head = skb;
+ tx_ppdu_info->tx_mon_mpdu->tail = NULL;
+ list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
+ &tx_ppdu_info->dp_tx_mon_mpdu_list);
+
+ return 0;
+}
+
+static int
+ath12k_wifi7_dp_mon_tx_gen_ack_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
+{
+ struct sk_buff *skb;
+ struct dp_mon_frame_min_one *fbmhdr;
+
+ skb = ath12k_wifi7_dp_mon_tx_alloc_skb();
+ if (!skb)
+ return -ENOMEM;
+
+ fbmhdr = (struct dp_mon_frame_min_one *)skb->data;
+ memset(fbmhdr, 0, MAX_DUMMY_FRM_BODY);
+ fbmhdr->frame_control =
+ cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_CFACK);
+ memcpy(fbmhdr->addr1, tx_ppdu_info->rx_status.addr1, ETH_ALEN);
+
+ /* set duration zero for ack frame */
+ fbmhdr->duration = 0;
+
+ skb_put(skb, sizeof(*fbmhdr));
+ tx_ppdu_info->tx_mon_mpdu->head = skb;
+ tx_ppdu_info->tx_mon_mpdu->tail = NULL;
+ list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
+ &tx_ppdu_info->dp_tx_mon_mpdu_list);
+
+ return 0;
+}
+
+static int
+ath12k_wifi7_dp_mon_tx_gen_prot_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
+{
+ int ret = 0;
+
+ switch (tx_ppdu_info->rx_status.medium_prot_type) {
+ case DP_MON_TX_MEDIUM_RTS_LEGACY:
+ case DP_MON_TX_MEDIUM_RTS_11AC_STATIC_BW:
+ case DP_MON_TX_MEDIUM_RTS_11AC_DYNAMIC_BW:
+ ret = ath12k_wifi7_dp_mon_tx_gen_rts_frame(tx_ppdu_info);
+ break;
+ case DP_MON_TX_MEDIUM_CTS2SELF:
+ ret = ath12k_wifi7_dp_mon_tx_gen_cts2self_frame(tx_ppdu_info);
+ break;
+ case DP_MON_TX_MEDIUM_QOS_NULL_NO_ACK_3ADDR:
+ ret = ath12k_wifi7_dp_mon_tx_gen_3addr_qos_null_frame(tx_ppdu_info);
+ break;
+ case DP_MON_TX_MEDIUM_QOS_NULL_NO_ACK_4ADDR:
+ ret = ath12k_wifi7_dp_mon_tx_gen_4addr_qos_null_frame(tx_ppdu_info);
+ break;
+ }
+
+ return ret;
+}
+
+static enum dp_mon_tx_tlv_status
+ath12k_wifi7_dp_mon_tx_parse_status_tlv(struct ath12k_base *ab,
+ struct ath12k_mon_data *pmon,
+ u16 tlv_tag, const void *tlv_data,
+ u32 userid)
+{
+ struct dp_mon_tx_ppdu_info *tx_ppdu_info;
+ enum dp_mon_tx_tlv_status status = DP_MON_TX_STATUS_PPDU_NOT_DONE;
+ u32 info[7];
+
+ tx_ppdu_info = ath12k_wifi7_dp_mon_hal_tx_ppdu_info(pmon, tlv_tag);
+
+ switch (tlv_tag) {
+ case HAL_TX_FES_SETUP: {
+ const struct hal_tx_fes_setup *tx_fes_setup = tlv_data;
+
+ info[0] = __le32_to_cpu(tx_fes_setup->info0);
+ tx_ppdu_info->ppdu_id = __le32_to_cpu(tx_fes_setup->schedule_id);
+ tx_ppdu_info->num_users =
+ u32_get_bits(info[0], HAL_TX_FES_SETUP_INFO0_NUM_OF_USERS);
+ status = DP_MON_TX_FES_SETUP;
+ break;
+ }
+
+ case HAL_TX_FES_STATUS_END: {
+ const struct hal_tx_fes_status_end *tx_fes_status_end = tlv_data;
+ u32 tst_15_0, tst_31_16;
+
+ info[0] = __le32_to_cpu(tx_fes_status_end->info0);
+ tst_15_0 =
+ u32_get_bits(info[0],
+ HAL_TX_FES_STATUS_END_INFO0_START_TIMESTAMP_15_0);
+ tst_31_16 =
+ u32_get_bits(info[0],
+ HAL_TX_FES_STATUS_END_INFO0_START_TIMESTAMP_31_16);
+
+ tx_ppdu_info->rx_status.ppdu_ts = (tst_15_0 | (tst_31_16 << 16));
+ status = DP_MON_TX_FES_STATUS_END;
+ break;
+ }
+
+ case HAL_RX_RESPONSE_REQUIRED_INFO: {
+ const struct hal_rx_resp_req_info *rx_resp_req_info = tlv_data;
+ u32 addr_32;
+ u16 addr_16;
+
+ info[0] = __le32_to_cpu(rx_resp_req_info->info0);
+ info[1] = __le32_to_cpu(rx_resp_req_info->info1);
+ info[2] = __le32_to_cpu(rx_resp_req_info->info2);
+ info[3] = __le32_to_cpu(rx_resp_req_info->info3);
+ info[4] = __le32_to_cpu(rx_resp_req_info->info4);
+ info[5] = __le32_to_cpu(rx_resp_req_info->info5);
+
+ tx_ppdu_info->rx_status.ppdu_id =
+ u32_get_bits(info[0], HAL_RX_RESP_REQ_INFO0_PPDU_ID);
+ tx_ppdu_info->rx_status.reception_type =
+ u32_get_bits(info[0], HAL_RX_RESP_REQ_INFO0_RECEPTION_TYPE);
+ tx_ppdu_info->rx_status.rx_duration =
+ u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_DURATION);
+ tx_ppdu_info->rx_status.mcs =
+ u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_RATE_MCS);
+ tx_ppdu_info->rx_status.sgi =
+ u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_SGI);
+ tx_ppdu_info->rx_status.is_stbc =
+ u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_STBC);
+ tx_ppdu_info->rx_status.ldpc =
+ u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_LDPC);
+ tx_ppdu_info->rx_status.is_ampdu =
+ u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_IS_AMPDU);
+ tx_ppdu_info->rx_status.num_users =
+ u32_get_bits(info[2], HAL_RX_RESP_REQ_INFO2_NUM_USER);
+
+ addr_32 = u32_get_bits(info[3], HAL_RX_RESP_REQ_INFO3_ADDR1_31_0);
+ addr_16 = u32_get_bits(info[3], HAL_RX_RESP_REQ_INFO4_ADDR1_47_32);
+ ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr1);
+
+ addr_16 = u32_get_bits(info[4], HAL_RX_RESP_REQ_INFO4_ADDR1_15_0);
+ addr_32 = u32_get_bits(info[5], HAL_RX_RESP_REQ_INFO5_ADDR1_47_16);
+ ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr2);
+
+ if (tx_ppdu_info->rx_status.reception_type == 0)
+ ath12k_wifi7_dp_mon_tx_gen_cts2self_frame(tx_ppdu_info);
+ status = DP_MON_RX_RESPONSE_REQUIRED_INFO;
+ break;
+ }
+
+ case HAL_PCU_PPDU_SETUP_INIT: {
+ const struct hal_tx_pcu_ppdu_setup_init *ppdu_setup = tlv_data;
+ u32 addr_32;
+ u16 addr_16;
+
+ info[0] = __le32_to_cpu(ppdu_setup->info0);
+ info[1] = __le32_to_cpu(ppdu_setup->info1);
+ info[2] = __le32_to_cpu(ppdu_setup->info2);
+ info[3] = __le32_to_cpu(ppdu_setup->info3);
+ info[4] = __le32_to_cpu(ppdu_setup->info4);
+ info[5] = __le32_to_cpu(ppdu_setup->info5);
+ info[6] = __le32_to_cpu(ppdu_setup->info6);
+
+ /* protection frame address 1 */
+ addr_32 = u32_get_bits(info[1],
+ HAL_TX_PPDU_SETUP_INFO1_PROT_FRAME_ADDR1_31_0);
+ addr_16 = u32_get_bits(info[2],
+ HAL_TX_PPDU_SETUP_INFO2_PROT_FRAME_ADDR1_47_32);
+ ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr1);
+
+ /* protection frame address 2 */
+ addr_16 = u32_get_bits(info[2],
+ HAL_TX_PPDU_SETUP_INFO2_PROT_FRAME_ADDR2_15_0);
+ addr_32 = u32_get_bits(info[3],
+ HAL_TX_PPDU_SETUP_INFO3_PROT_FRAME_ADDR2_47_16);
+ ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr2);
+
+ /* protection frame address 3 */
+ addr_32 = u32_get_bits(info[4],
+ HAL_TX_PPDU_SETUP_INFO4_PROT_FRAME_ADDR3_31_0);
+ addr_16 = u32_get_bits(info[5],
+ HAL_TX_PPDU_SETUP_INFO5_PROT_FRAME_ADDR3_47_32);
+ ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr3);
+
+ /* protection frame address 4 */
+ addr_16 = u32_get_bits(info[5],
+ HAL_TX_PPDU_SETUP_INFO5_PROT_FRAME_ADDR4_15_0);
+ addr_32 = u32_get_bits(info[6],
+ HAL_TX_PPDU_SETUP_INFO6_PROT_FRAME_ADDR4_47_16);
+ ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr4);
+
+ status = u32_get_bits(info[0],
+ HAL_TX_PPDU_SETUP_INFO0_MEDIUM_PROT_TYPE);
+ break;
+ }
+
+ case HAL_TX_QUEUE_EXTENSION: {
+ const struct hal_tx_queue_exten *tx_q_exten = tlv_data;
+
+ info[0] = __le32_to_cpu(tx_q_exten->info0);
+
+ tx_ppdu_info->rx_status.frame_control =
+ u32_get_bits(info[0],
+ HAL_TX_Q_EXT_INFO0_FRAME_CTRL);
+ tx_ppdu_info->rx_status.fc_valid = true;
+ break;
+ }
+
+ case HAL_TX_FES_STATUS_START: {
+ const struct hal_tx_fes_status_start *tx_fes_start = tlv_data;
+
+ info[0] = __le32_to_cpu(tx_fes_start->info0);
+
+ tx_ppdu_info->rx_status.medium_prot_type =
+ u32_get_bits(info[0],
+ HAL_TX_FES_STATUS_START_INFO0_MEDIUM_PROT_TYPE);
+ break;
+ }
+
+ case HAL_TX_FES_STATUS_PROT: {
+ const struct hal_tx_fes_status_prot *tx_fes_status = tlv_data;
+ u32 start_timestamp;
+ u32 end_timestamp;
+
+ info[0] = __le32_to_cpu(tx_fes_status->info0);
+ info[1] = __le32_to_cpu(tx_fes_status->info1);
+
+ start_timestamp =
+ u32_get_bits(info[0],
+ HAL_TX_FES_STAT_PROT_INFO0_STRT_FRM_TS_15_0);
+ start_timestamp |=
+ u32_get_bits(info[0],
+ HAL_TX_FES_STAT_PROT_INFO0_STRT_FRM_TS_31_16) << 15;
+ end_timestamp =
+ u32_get_bits(info[1],
+ HAL_TX_FES_STAT_PROT_INFO1_END_FRM_TS_15_0);
+ end_timestamp |=
+ u32_get_bits(info[1],
+ HAL_TX_FES_STAT_PROT_INFO1_END_FRM_TS_31_16) << 15;
+ tx_ppdu_info->rx_status.rx_duration = end_timestamp - start_timestamp;
+
+ ath12k_wifi7_dp_mon_tx_gen_prot_frame(tx_ppdu_info);
+ break;
+ }
+
+ case HAL_TX_FES_STATUS_START_PPDU:
+ case HAL_TX_FES_STATUS_START_PROT: {
+ const struct hal_tx_fes_status_start_prot *tx_fes_stat_start = tlv_data;
+ u64 ppdu_ts;
+
+ info[0] = __le32_to_cpu(tx_fes_stat_start->info0);
+
+ tx_ppdu_info->rx_status.ppdu_ts =
+ u32_get_bits(info[0],
+ HAL_TX_FES_STAT_STRT_INFO0_PROT_TS_LOWER_32);
+ ppdu_ts = (u32_get_bits(info[1],
+ HAL_TX_FES_STAT_STRT_INFO1_PROT_TS_UPPER_32));
+ tx_ppdu_info->rx_status.ppdu_ts |= ppdu_ts << 32;
+ break;
+ }
+
+ case HAL_TX_FES_STATUS_USER_PPDU: {
+ const struct hal_tx_fes_status_user_ppdu *tx_fes_usr_ppdu = tlv_data;
+
+ info[0] = __le32_to_cpu(tx_fes_usr_ppdu->info0);
+
+ tx_ppdu_info->rx_status.rx_duration =
+ u32_get_bits(info[0],
+ HAL_TX_FES_STAT_USR_PPDU_INFO0_DURATION);
+ break;
+ }
+
+ case HAL_MACTX_HE_SIG_A_SU:
+ ath12k_wifi7_dp_mon_parse_he_sig_su(tlv_data,
+ &tx_ppdu_info->rx_status);
+ break;
+
+ case HAL_MACTX_HE_SIG_A_MU_DL:
+ ath12k_wifi7_dp_mon_parse_he_sig_mu(tlv_data, &tx_ppdu_info->rx_status);
+ break;
+
+ case HAL_MACTX_HE_SIG_B1_MU:
+ ath12k_wifi7_dp_mon_parse_he_sig_b1_mu(tlv_data,
+ &tx_ppdu_info->rx_status);
+ break;
+
+ case HAL_MACTX_HE_SIG_B2_MU:
+ ath12k_wifi7_dp_mon_parse_he_sig_b2_mu(tlv_data,
+ &tx_ppdu_info->rx_status);
+ break;
+
+ case HAL_MACTX_HE_SIG_B2_OFDMA:
+ ath12k_wifi7_dp_mon_parse_he_sig_b2_ofdma(tlv_data,
+ &tx_ppdu_info->rx_status);
+ break;
+
+ case HAL_MACTX_VHT_SIG_A:
+ ath12k_wifi7_dp_mon_parse_vht_sig_a(tlv_data, &tx_ppdu_info->rx_status);
+ break;
+
+ case HAL_MACTX_L_SIG_A:
+ ath12k_wifi7_dp_mon_parse_l_sig_a(tlv_data, &tx_ppdu_info->rx_status);
+ break;
+
+ case HAL_MACTX_L_SIG_B:
+ ath12k_wifi7_dp_mon_parse_l_sig_b(tlv_data, &tx_ppdu_info->rx_status);
+ break;
+
+ case HAL_RX_FRAME_BITMAP_ACK: {
+ const struct hal_rx_frame_bitmap_ack *fbm_ack = tlv_data;
+ u32 addr_32;
+ u16 addr_16;
+
+ info[0] = __le32_to_cpu(fbm_ack->info0);
+ info[1] = __le32_to_cpu(fbm_ack->info1);
+
+ addr_32 = u32_get_bits(info[0],
+ HAL_RX_FBM_ACK_INFO0_ADDR1_31_0);
+ addr_16 = u32_get_bits(info[1],
+ HAL_RX_FBM_ACK_INFO1_ADDR1_47_32);
+ ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr1);
+
+ ath12k_wifi7_dp_mon_tx_gen_ack_frame(tx_ppdu_info);
+ break;
+ }
+
+ case HAL_MACTX_PHY_DESC: {
+ const struct hal_tx_phy_desc *tx_phy_desc = tlv_data;
+
+ info[0] = __le32_to_cpu(tx_phy_desc->info0);
+ info[1] = __le32_to_cpu(tx_phy_desc->info1);
+ info[2] = __le32_to_cpu(tx_phy_desc->info2);
+ info[3] = __le32_to_cpu(tx_phy_desc->info3);
+
+ tx_ppdu_info->rx_status.beamformed =
+ u32_get_bits(info[0],
+ HAL_TX_PHY_DESC_INFO0_BF_TYPE);
+ tx_ppdu_info->rx_status.preamble_type =
+ u32_get_bits(info[0],
+ HAL_TX_PHY_DESC_INFO0_PREAMBLE_11B);
+ tx_ppdu_info->rx_status.mcs =
+ u32_get_bits(info[1],
+ HAL_TX_PHY_DESC_INFO1_MCS);
+ tx_ppdu_info->rx_status.ltf_size =
+ u32_get_bits(info[3],
+ HAL_TX_PHY_DESC_INFO3_LTF_SIZE);
+ tx_ppdu_info->rx_status.nss =
+ u32_get_bits(info[2],
+ HAL_TX_PHY_DESC_INFO2_NSS);
+ tx_ppdu_info->rx_status.chan_num =
+ u32_get_bits(info[3],
+ HAL_TX_PHY_DESC_INFO3_ACTIVE_CHANNEL);
+ tx_ppdu_info->rx_status.bw =
+ u32_get_bits(info[0],
+ HAL_TX_PHY_DESC_INFO0_BANDWIDTH);
+ break;
+ }
+
+ case HAL_TX_MPDU_START: {
+ struct dp_mon_mpdu *mon_mpdu = tx_ppdu_info->tx_mon_mpdu;
+
+ mon_mpdu = kzalloc(sizeof(*mon_mpdu), GFP_ATOMIC);
+ if (!mon_mpdu)
+ return DP_MON_TX_STATUS_PPDU_NOT_DONE;
+ status = DP_MON_TX_MPDU_START;
+ break;
+ }
+
+ case HAL_TX_MPDU_END:
+ list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
+ &tx_ppdu_info->dp_tx_mon_mpdu_list);
+ break;
+ }
+
+ return status;
+}
+
+static enum dp_mon_tx_tlv_status
+ath12k_wifi7_dp_mon_tx_status_get_num_user(u16 tlv_tag,
+ struct hal_tlv_hdr *tx_tlv,
+ u8 *num_users)
+{
+ u32 tlv_status = DP_MON_TX_STATUS_PPDU_NOT_DONE;
+ u32 info0;
+
+ switch (tlv_tag) {
+ case HAL_TX_FES_SETUP: {
+ struct hal_tx_fes_setup *tx_fes_setup =
+ (struct hal_tx_fes_setup *)tx_tlv;
+
+ info0 = __le32_to_cpu(tx_fes_setup->info0);
+
+ *num_users = u32_get_bits(info0, HAL_TX_FES_SETUP_INFO0_NUM_OF_USERS);
+ tlv_status = DP_MON_TX_FES_SETUP;
+ break;
+ }
+
+ case HAL_RX_RESPONSE_REQUIRED_INFO: {
+ /* TODO: need to update *num_users */
+ tlv_status = DP_MON_RX_RESPONSE_REQUIRED_INFO;
+ break;
+ }
+ }
+
+ return tlv_status;
+}
+
+static int
+ath12k_wifi7_dp_mon_rx_deliver(struct ath12k_pdev_dp *dp_pdev,
+ struct dp_mon_mpdu *mon_mpdu,
+ struct hal_rx_mon_ppdu_info *ppduinfo,
+ struct napi_struct *napi)
+{
+ struct sk_buff *mon_skb, *skb_next, *header;
+ struct ieee80211_rx_status *rxs = &dp_pdev->rx_status;
+ u8 decap = DP_RX_DECAP_TYPE_RAW;
+
+ mon_skb = ath12k_dp_mon_rx_merg_msdus(dp_pdev, mon_mpdu, ppduinfo, rxs);
+ if (!mon_skb)
+ goto mon_deliver_fail;
+
+ header = mon_skb;
+ rxs->flag = 0;
+
+ if (mon_mpdu->err_bitmap & HAL_RX_MPDU_ERR_FCS)
+ rxs->flag = RX_FLAG_FAILED_FCS_CRC;
+
+ do {
+ skb_next = mon_skb->next;
+ if (!skb_next)
+ rxs->flag &= ~RX_FLAG_AMSDU_MORE;
+ else
+ rxs->flag |= RX_FLAG_AMSDU_MORE;
+
+ if (mon_skb == header) {
+ header = NULL;
+ rxs->flag &= ~RX_FLAG_ALLOW_SAME_PN;
+ } else {
+ rxs->flag |= RX_FLAG_ALLOW_SAME_PN;
+ }
+ rxs->flag |= RX_FLAG_ONLY_MONITOR;
+
+ if (!(rxs->flag & RX_FLAG_ONLY_MONITOR))
+ decap = mon_mpdu->decap_format;
+
+ ath12k_dp_mon_update_radiotap(dp_pdev, ppduinfo, mon_skb, rxs);
+ ath12k_dp_mon_rx_deliver_msdu(dp_pdev, napi, mon_skb, ppduinfo,
+ rxs, decap);
+ mon_skb = skb_next;
+ } while (mon_skb);
+ rxs->flag = 0;
+
+ return 0;
+
+mon_deliver_fail:
+ mon_skb = mon_mpdu->head;
+ while (mon_skb) {
+ skb_next = mon_skb->next;
+ dev_kfree_skb_any(mon_skb);
+ mon_skb = skb_next;
+ }
+ return -EINVAL;
+}
+
+static void
+ath12k_wifi7_dp_mon_tx_process_ppdu_info(struct ath12k_pdev_dp *dp_pdev,
+ struct napi_struct *napi,
+ struct dp_mon_tx_ppdu_info *tx_ppdu_info)
+{
+ struct dp_mon_mpdu *tmp, *mon_mpdu;
+
+ list_for_each_entry_safe(mon_mpdu, tmp,
+ &tx_ppdu_info->dp_tx_mon_mpdu_list, list) {
+ list_del(&mon_mpdu->list);
+
+ if (mon_mpdu->head)
+ ath12k_wifi7_dp_mon_rx_deliver(dp_pdev, mon_mpdu,
+ &tx_ppdu_info->rx_status, napi);
+
+ kfree(mon_mpdu);
+ }
+}
+
+enum hal_rx_mon_status
+ath12k_wifi7_dp_mon_tx_parse_mon_status(struct ath12k_pdev_dp *dp_pdev,
+ struct ath12k_mon_data *pmon,
+ struct sk_buff *skb,
+ struct napi_struct *napi,
+ u32 ppdu_id)
+{
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
+ struct dp_mon_tx_ppdu_info *tx_prot_ppdu_info, *tx_data_ppdu_info;
+ struct hal_tlv_hdr *tlv;
+ u8 *ptr = skb->data;
+ u16 tlv_tag;
+ u16 tlv_len;
+ u32 tlv_userid = 0;
+ u8 num_user;
+ u32 tlv_status = DP_MON_TX_STATUS_PPDU_NOT_DONE;
+
+ tx_prot_ppdu_info =
+ ath12k_wifi7_dp_mon_tx_get_ppdu_info(pmon, ppdu_id,
+ DP_MON_TX_PROT_PPDU_INFO);
+ if (!tx_prot_ppdu_info)
+ return -ENOMEM;
+
+ tlv = (struct hal_tlv_hdr *)ptr;
+ tlv_tag = le32_get_bits(tlv->tl, HAL_TLV_HDR_TAG);
+
+ tlv_status = ath12k_wifi7_dp_mon_tx_status_get_num_user(tlv_tag, tlv,
+ &num_user);
+ if (tlv_status == DP_MON_TX_STATUS_PPDU_NOT_DONE || !num_user)
+ return -EINVAL;
+
+ tx_data_ppdu_info =
+ ath12k_wifi7_dp_mon_tx_get_ppdu_info(pmon, ppdu_id,
+ DP_MON_TX_DATA_PPDU_INFO);
+ if (!tx_data_ppdu_info)
+ return -ENOMEM;
+
+ do {
+ tlv = (struct hal_tlv_hdr *)ptr;
+ tlv_tag = le32_get_bits(tlv->tl, HAL_TLV_HDR_TAG);
+ tlv_len = le32_get_bits(tlv->tl, HAL_TLV_HDR_LEN);
+ tlv_userid = le32_get_bits(tlv->tl, HAL_TLV_USR_ID);
+
+ tlv_status = ath12k_wifi7_dp_mon_tx_parse_status_tlv(ab, pmon,
+ tlv_tag, ptr,
+ tlv_userid);
+ ptr += tlv_len;
+ ptr = PTR_ALIGN(ptr, HAL_TLV_ALIGN);
+ if ((ptr - skb->data) >= DP_TX_MONITOR_BUF_SIZE)
+ break;
+ } while (tlv_status != DP_MON_TX_FES_STATUS_END);
+
+ ath12k_wifi7_dp_mon_tx_process_ppdu_info(dp_pdev, napi, tx_data_ppdu_info);
+ ath12k_wifi7_dp_mon_tx_process_ppdu_info(dp_pdev, napi, tx_prot_ppdu_info);
+
+ return tlv_status;
+}
+
+static void
+ath12k_wifi7_dp_mon_next_link_desc_get(struct ath12k_base *ab,
+ struct hal_rx_msdu_link *msdu_link,
+ dma_addr_t *paddr, u32 *sw_cookie, u8 *rbm,
+ struct ath12k_buffer_addr **pp_buf_addr_info)
+{
+ struct ath12k_buffer_addr *buf_addr_info;
+
+ buf_addr_info = &msdu_link->buf_addr_info;
+
+ ath12k_wifi7_hal_rx_buf_addr_info_get(buf_addr_info, paddr, sw_cookie, rbm);
+
+ *pp_buf_addr_info = buf_addr_info;
+}
+
+static u32
+ath12k_wifi7_dp_rx_mon_mpdu_pop(struct ath12k *ar, int mac_id,
+ void *ring_entry, struct sk_buff **head_msdu,
+ struct sk_buff **tail_msdu,
+ struct list_head *used_list,
+ u32 *npackets, u32 *ppdu_id)
+{
+ struct ath12k_mon_data *pmon = (struct ath12k_mon_data *)&ar->dp.mon_data;
+ struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_buffer_addr *p_buf_addr_info, *p_last_buf_addr_info;
+ u32 msdu_ppdu_id = 0, msdu_cnt = 0, total_len = 0, frag_len = 0;
+ u32 rx_buf_size, rx_pkt_offset, sw_cookie;
+ bool is_frag, is_first_msdu, drop_mpdu = false;
+ struct hal_reo_entrance_ring *ent_desc =
+ (struct hal_reo_entrance_ring *)ring_entry;
+ u32 rx_bufs_used = 0, i = 0, desc_bank = 0;
+ struct hal_rx_desc *rx_desc, *tail_rx_desc;
+ struct hal_rx_msdu_link *msdu_link_desc;
+ struct sk_buff *msdu = NULL, *last = NULL;
+ struct ath12k_rx_desc_info *desc_info;
+ struct ath12k_buffer_addr buf_info;
+ struct hal_rx_msdu_list msdu_list;
+ struct ath12k_skb_rxcb *rxcb;
+ u16 num_msdus = 0;
+ dma_addr_t paddr;
+ u8 rbm;
+
+ ath12k_wifi7_hal_rx_reo_ent_buf_paddr_get(ring_entry, &paddr,
+ &sw_cookie,
+ &p_last_buf_addr_info,
+ &rbm,
+ &msdu_cnt);
+
+ spin_lock_bh(&pmon->mon_lock);
+
+ if (le32_get_bits(ent_desc->info1,
+ HAL_REO_ENTR_RING_INFO1_RXDMA_PUSH_REASON) ==
+ HAL_REO_DEST_RING_PUSH_REASON_ERR_DETECTED) {
+ u8 rxdma_err = le32_get_bits(ent_desc->info1,
+ HAL_REO_ENTR_RING_INFO1_RXDMA_ERROR_CODE);
+ if (rxdma_err == HAL_REO_ENTR_RING_RXDMA_ECODE_FLUSH_REQUEST_ERR ||
+ rxdma_err == HAL_REO_ENTR_RING_RXDMA_ECODE_MPDU_LEN_ERR ||
+ rxdma_err == HAL_REO_ENTR_RING_RXDMA_ECODE_OVERFLOW_ERR) {
+ drop_mpdu = true;
+ pmon->rx_mon_stats.dest_mpdu_drop++;
+ }
+ }
+
+ is_frag = false;
+ is_first_msdu = true;
+ rx_pkt_offset = sizeof(struct hal_rx_desc);
+
+ do {
+ if (pmon->mon_last_linkdesc_paddr == paddr) {
+ pmon->rx_mon_stats.dup_mon_linkdesc_cnt++;
+ spin_unlock_bh(&pmon->mon_lock);
+ return rx_bufs_used;
+ }
+
+ desc_bank = u32_get_bits(sw_cookie, DP_LINK_DESC_BANK_MASK);
+ msdu_link_desc =
+ dp->link_desc_banks[desc_bank].vaddr +
+ (paddr - dp->link_desc_banks[desc_bank].paddr);
+
+ ath12k_wifi7_hal_rx_msdu_list_get(ar, msdu_link_desc, &msdu_list,
+ &num_msdus);
+ desc_info = ath12k_dp_get_rx_desc(ar->ab->dp,
+ msdu_list.sw_cookie[num_msdus - 1]);
+ tail_rx_desc = (struct hal_rx_desc *)(desc_info->skb)->data;
+
+ for (i = 0; i < num_msdus; i++) {
+ u32 l2_hdr_offset;
+
+ if (pmon->mon_last_buf_cookie == msdu_list.sw_cookie[i]) {
+ ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
+ "i %d last_cookie %d is same\n",
+ i, pmon->mon_last_buf_cookie);
+ drop_mpdu = true;
+ pmon->rx_mon_stats.dup_mon_buf_cnt++;
+ continue;
+ }
+
+ desc_info =
+ ath12k_dp_get_rx_desc(ar->ab->dp, msdu_list.sw_cookie[i]);
+ msdu = desc_info->skb;
+
+ if (!msdu) {
+ ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
+ "msdu_pop: invalid msdu (%d/%d)\n",
+ i + 1, num_msdus);
+ goto next_msdu;
+ }
+ rxcb = ATH12K_SKB_RXCB(msdu);
+ if (rxcb->paddr != msdu_list.paddr[i]) {
+ ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
+ "i %d paddr %lx != %lx\n",
+ i, (unsigned long)rxcb->paddr,
+ (unsigned long)msdu_list.paddr[i]);
+ drop_mpdu = true;
+ continue;
+ }
+ if (!rxcb->unmapped) {
+ dma_unmap_single(ar->ab->dev, rxcb->paddr,
+ msdu->len +
+ skb_tailroom(msdu),
+ DMA_FROM_DEVICE);
+ rxcb->unmapped = 1;
+ }
+ if (drop_mpdu) {
+ ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
+ "i %d drop msdu %p *ppdu_id %x\n",
+ i, msdu, *ppdu_id);
+ dev_kfree_skb_any(msdu);
+ msdu = NULL;
+ goto next_msdu;
+ }
+
+ rx_desc = (struct hal_rx_desc *)msdu->data;
+ l2_hdr_offset = ath12k_dp_rx_h_l3pad(ar->ab, tail_rx_desc);
+ if (is_first_msdu) {
+ if (!ath12k_wifi7_dp_rxdesc_mpdu_valid(ar->ab,
+ rx_desc)) {
+ drop_mpdu = true;
+ dev_kfree_skb_any(msdu);
+ msdu = NULL;
+ pmon->mon_last_linkdesc_paddr = paddr;
+ goto next_msdu;
+ }
+ msdu_ppdu_id =
+ ath12k_dp_rxdesc_get_ppduid(ar->ab, rx_desc);
+
+ if (ath12k_dp_mon_comp_ppduid(msdu_ppdu_id,
+ ppdu_id)) {
+ spin_unlock_bh(&pmon->mon_lock);
+ return rx_bufs_used;
+ }
+ pmon->mon_last_linkdesc_paddr = paddr;
+ is_first_msdu = false;
+ }
+ ath12k_wifi7_dp_mon_get_buf_len(&msdu_list.msdu_info[i],
+ &is_frag, &total_len,
+ &frag_len, &msdu_cnt);
+ rx_buf_size = rx_pkt_offset + l2_hdr_offset + frag_len;
+
+ if (ath12k_dp_pkt_set_pktlen(msdu, rx_buf_size)) {
+ dev_kfree_skb_any(msdu);
+ goto next_msdu;
+ }
+
+ if (!(*head_msdu))
+ *head_msdu = msdu;
+ else if (last)
+ last->next = msdu;
+
+ last = msdu;
+next_msdu:
+ pmon->mon_last_buf_cookie = msdu_list.sw_cookie[i];
+ rx_bufs_used++;
+ desc_info->skb = NULL;
+ list_add_tail(&desc_info->list, used_list);
+ }
+
+ ath12k_wifi7_hal_rx_buf_addr_info_set(&buf_info, paddr,
+ sw_cookie, rbm);
+
+ ath12k_wifi7_dp_mon_next_link_desc_get(ab,
+ msdu_link_desc, &paddr,
+ &sw_cookie, &rbm,
+ &p_buf_addr_info);
+
+ ath12k_dp_arch_rx_link_desc_return(ar->ab->dp, &buf_info,
+ HAL_WBM_REL_BM_ACT_PUT_IN_IDLE);
+
+ p_last_buf_addr_info = p_buf_addr_info;
+
+ } while (paddr && msdu_cnt);
+
+ spin_unlock_bh(&pmon->mon_lock);
+
+ if (last)
+ last->next = NULL;
+
+ *tail_msdu = msdu;
+
+ if (msdu_cnt == 0)
+ *npackets = 1;
+
+ return rx_bufs_used;
+}
+
+/* The destination ring processing is stuck if the destination is not
+ * moving while status ring moves 16 PPDU. The destination ring processing
+ * skips this destination ring PPDU as a workaround.
+ */
+#define MON_DEST_RING_STUCK_MAX_CNT 16
+
+static void
+ath12k_wifi7_dp_rx_mon_dest_process(struct ath12k *ar, int mac_id,
+ u32 quota, struct napi_struct *napi)
+{
+ struct ath12k_mon_data *pmon = (struct ath12k_mon_data *)&ar->dp.mon_data;
+ struct ath12k_pdev_mon_stats *rx_mon_stats;
+ u32 ppdu_id, rx_bufs_used = 0, ring_id;
+ u32 mpdu_rx_bufs_used, npackets = 0;
+ struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ void *ring_entry, *mon_dst_srng;
+ struct dp_mon_mpdu *tmp_mpdu;
+ LIST_HEAD(rx_desc_used_list);
+ struct hal_srng *srng;
+
+ ring_id = dp->rxdma_err_dst_ring[mac_id].ring_id;
+ srng = &ab->hal.srng_list[ring_id];
+
+ mon_dst_srng = &ab->hal.srng_list[ring_id];
+
+ spin_lock_bh(&srng->lock);
+
+ ath12k_hal_srng_access_begin(ab, mon_dst_srng);
+
+ ppdu_id = pmon->mon_ppdu_info.ppdu_id;
+ rx_mon_stats = &pmon->rx_mon_stats;
+
+ while ((ring_entry = ath12k_hal_srng_dst_peek(ar->ab, mon_dst_srng))) {
+ struct sk_buff *head_msdu, *tail_msdu;
+
+ head_msdu = NULL;
+ tail_msdu = NULL;
+
+ mpdu_rx_bufs_used = ath12k_wifi7_dp_rx_mon_mpdu_pop(ar, mac_id,
+ ring_entry,
+ &head_msdu,
+ &tail_msdu,
+ &rx_desc_used_list,
+ &npackets,
+ &ppdu_id);
+
+ rx_bufs_used += mpdu_rx_bufs_used;
+
+ if (mpdu_rx_bufs_used) {
+ dp->mon_dest_ring_stuck_cnt = 0;
+ } else {
+ dp->mon_dest_ring_stuck_cnt++;
+ rx_mon_stats->dest_mon_not_reaped++;
+ }
+
+ if (dp->mon_dest_ring_stuck_cnt > MON_DEST_RING_STUCK_MAX_CNT) {
+ rx_mon_stats->dest_mon_stuck++;
+ ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
+ "status ring ppdu_id=%d dest ring ppdu_id=%d mon_dest_ring_stuck_cnt=%d dest_mon_not_reaped=%u dest_mon_stuck=%u\n",
+ pmon->mon_ppdu_info.ppdu_id, ppdu_id,
+ dp->mon_dest_ring_stuck_cnt,
+ rx_mon_stats->dest_mon_not_reaped,
+ rx_mon_stats->dest_mon_stuck);
+ spin_lock_bh(&pmon->mon_lock);
+ pmon->mon_ppdu_info.ppdu_id = ppdu_id;
+ spin_unlock_bh(&pmon->mon_lock);
+ continue;
+ }
+
+ if (ppdu_id != pmon->mon_ppdu_info.ppdu_id) {
+ spin_lock_bh(&pmon->mon_lock);
+ pmon->mon_ppdu_status = DP_PPDU_STATUS_START;
+ spin_unlock_bh(&pmon->mon_lock);
+ ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
+ "dest_rx: new ppdu_id %x != status ppdu_id %x dest_mon_not_reaped = %u dest_mon_stuck = %u\n",
+ ppdu_id, pmon->mon_ppdu_info.ppdu_id,
+ rx_mon_stats->dest_mon_not_reaped,
+ rx_mon_stats->dest_mon_stuck);
+ break;
+ }
+
+ if (head_msdu && tail_msdu) {
+ tmp_mpdu = kzalloc(sizeof(*tmp_mpdu), GFP_ATOMIC);
+ if (!tmp_mpdu)
+ break;
+
+ tmp_mpdu->head = head_msdu;
+ tmp_mpdu->tail = tail_msdu;
+ tmp_mpdu->err_bitmap = pmon->err_bitmap;
+ tmp_mpdu->decap_format = pmon->decap_format;
+ ath12k_wifi7_dp_mon_rx_deliver(&ar->dp, tmp_mpdu,
+ &pmon->mon_ppdu_info, napi);
+ rx_mon_stats->dest_mpdu_done++;
+ kfree(tmp_mpdu);
+ }
+
+ ring_entry = ath12k_hal_srng_dst_get_next_entry(ar->ab,
+ mon_dst_srng);
+ }
+ ath12k_hal_srng_access_end(ar->ab, mon_dst_srng);
+
+ spin_unlock_bh(&srng->lock);
+
+ if (rx_bufs_used) {
+ rx_mon_stats->dest_ppdu_done++;
+ ath12k_dp_rx_bufs_replenish(ar->ab->dp,
+ &dp->rx_refill_buf_ring,
+ &rx_desc_used_list,
+ rx_bufs_used);
+ }
+}
+
+static enum dp_mon_status_buf_state
+ath12k_wifi7_dp_rx_mon_buf_done(struct ath12k_base *ab, struct hal_srng *srng,
+ struct dp_rxdma_mon_ring *rx_ring)
+{
+ struct ath12k_skb_rxcb *rxcb;
+ struct hal_tlv_64_hdr *tlv;
+ struct sk_buff *skb;
+ void *status_desc;
+ dma_addr_t paddr;
+ u32 cookie;
+ int buf_id;
+ u8 rbm;
+
+ status_desc = ath12k_hal_srng_src_next_peek(ab, srng);
+ if (!status_desc)
+ return DP_MON_STATUS_NO_DMA;
+
+ ath12k_wifi7_hal_rx_buf_addr_info_get(status_desc, &paddr, &cookie, &rbm);
+
+ buf_id = u32_get_bits(cookie, DP_RXDMA_BUF_COOKIE_BUF_ID);
+
+ spin_lock_bh(&rx_ring->idr_lock);
+ skb = idr_find(&rx_ring->bufs_idr, buf_id);
+ spin_unlock_bh(&rx_ring->idr_lock);
+
+ if (!skb)
+ return DP_MON_STATUS_NO_DMA;
+
+ rxcb = ATH12K_SKB_RXCB(skb);
+ dma_sync_single_for_cpu(ab->dev, rxcb->paddr,
+ skb->len + skb_tailroom(skb),
+ DMA_FROM_DEVICE);
+
+ tlv = (struct hal_tlv_64_hdr *)skb->data;
+ if (le64_get_bits(tlv->tl, HAL_TLV_HDR_TAG) != HAL_RX_STATUS_BUFFER_DONE)
+ return DP_MON_STATUS_NO_DMA;
+
+ return DP_MON_STATUS_REPLINISH;
+}
+
+static enum hal_rx_mon_status
+ath12k_wifi7_dp_mon_parse_rx_dest(struct ath12k_pdev_dp *dp_pdev,
+ struct ath12k_mon_data *pmon,
+ struct sk_buff *skb)
+{
+ struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev);
+ struct hal_tlv_64_hdr *tlv;
+ struct ath12k_skb_rxcb *rxcb;
+ enum hal_rx_mon_status hal_status;
+ u16 tlv_tag, tlv_len;
+ u8 *ptr = skb->data;
+
+ do {
+ tlv = (struct hal_tlv_64_hdr *)ptr;
+ tlv_tag = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_TAG);
+
+ /* The actual length of PPDU_END is the combined length of many PHY
+ * TLVs that follow. Skip the TLV header and
+ * rx_rxpcu_classification_overview that follows the header to get to
+ * next TLV.
+ */
+
+ if (tlv_tag == HAL_RX_PPDU_END)
+ tlv_len = sizeof(struct hal_rx_rxpcu_classification_overview);
+ else
+ tlv_len = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_LEN);
+
+ hal_status = ath12k_wifi7_dp_mon_rx_parse_status_tlv(dp_pdev, pmon,
+ tlv);
+
+ if (ar->monitor_started && ar->ab->hw_params->rxdma1_enable &&
+ ath12k_wifi7_dp_mon_parse_rx_dest_tlv(dp_pdev, pmon, hal_status,
+ tlv->value))
+ return HAL_RX_MON_STATUS_PPDU_DONE;
+
+ ptr += sizeof(*tlv) + tlv_len;
+ ptr = PTR_ALIGN(ptr, HAL_TLV_64_ALIGN);
+
+ if ((ptr - skb->data) > skb->len)
+ break;
+
+ } while ((hal_status == HAL_RX_MON_STATUS_PPDU_NOT_DONE) ||
+ (hal_status == HAL_RX_MON_STATUS_BUF_ADDR) ||
+ (hal_status == HAL_RX_MON_STATUS_MPDU_START) ||
+ (hal_status == HAL_RX_MON_STATUS_MPDU_END) ||
+ (hal_status == HAL_RX_MON_STATUS_MSDU_END));
+
+ rxcb = ATH12K_SKB_RXCB(skb);
+ if (rxcb->is_end_of_ppdu)
+ hal_status = HAL_RX_MON_STATUS_PPDU_DONE;
+
+ return hal_status;
+}
+
+static enum hal_rx_mon_status
+ath12k_wifi7_dp_mon_rx_parse_mon_status(struct ath12k_pdev_dp *dp_pdev,
+ struct ath12k_mon_data *pmon,
+ struct sk_buff *skb,
+ struct napi_struct *napi)
+{
+ struct hal_rx_mon_ppdu_info *ppdu_info = &pmon->mon_ppdu_info;
+ struct dp_mon_mpdu *tmp;
+ struct dp_mon_mpdu *mon_mpdu = pmon->mon_mpdu;
+ enum hal_rx_mon_status hal_status;
+
+ hal_status = ath12k_wifi7_dp_mon_parse_rx_dest(dp_pdev, pmon, skb);
+ if (hal_status != HAL_RX_MON_STATUS_PPDU_DONE)
+ return hal_status;
+
+ list_for_each_entry_safe(mon_mpdu, tmp, &pmon->dp_rx_mon_mpdu_list, list) {
+ list_del(&mon_mpdu->list);
+
+ if (mon_mpdu->head && mon_mpdu->tail)
+ ath12k_wifi7_dp_mon_rx_deliver(dp_pdev, mon_mpdu,
+ ppdu_info, napi);
+
+ kfree(mon_mpdu);
+ }
+
+ return hal_status;
+}
+
+static int
+ath12k_wifi7_dp_rx_reap_mon_status_ring(struct ath12k_base *ab, int mac_id,
+ int *budget, struct sk_buff_head *skb_list)
+{
+ const struct ath12k_hw_hal_params *hal_params;
+ int buf_id, srng_id, num_buffs_reaped = 0;
+ enum dp_mon_status_buf_state reap_status;
+ struct dp_rxdma_mon_ring *rx_ring;
+ struct ath12k_mon_data *pmon;
+ struct ath12k_skb_rxcb *rxcb;
+ struct hal_tlv_64_hdr *tlv;
+ void *rx_mon_status_desc;
+ struct hal_srng *srng;
+ struct ath12k_dp *dp;
+ struct sk_buff *skb;
+ struct ath12k *ar;
+ dma_addr_t paddr;
+ u32 cookie;
+ u8 rbm;
+
+ ar = ab->pdevs[ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id)].ar;
+ dp = ath12k_ab_to_dp(ab);
+ pmon = &ar->dp.mon_data;
+ srng_id = ath12k_hw_mac_id_to_srng_id(ab->hw_params, mac_id);
+ rx_ring = &dp->rx_mon_status_refill_ring[srng_id];
+
+ srng = &ab->hal.srng_list[rx_ring->refill_buf_ring.ring_id];
+
+ spin_lock_bh(&srng->lock);
+
+ ath12k_hal_srng_access_begin(ab, srng);
+
+ while (*budget) {
+ *budget -= 1;
+ rx_mon_status_desc = ath12k_hal_srng_src_peek(ab, srng);
+ if (!rx_mon_status_desc) {
+ pmon->buf_state = DP_MON_STATUS_REPLINISH;
+ break;
+ }
+ ath12k_wifi7_hal_rx_buf_addr_info_get(rx_mon_status_desc, &paddr,
+ &cookie, &rbm);
+ if (paddr) {
+ buf_id = u32_get_bits(cookie, DP_RXDMA_BUF_COOKIE_BUF_ID);
+
+ spin_lock_bh(&rx_ring->idr_lock);
+ skb = idr_find(&rx_ring->bufs_idr, buf_id);
+ spin_unlock_bh(&rx_ring->idr_lock);
+
+ if (!skb) {
+ ath12k_warn(ab, "rx monitor status with invalid buf_id %d\n",
+ buf_id);
+ pmon->buf_state = DP_MON_STATUS_REPLINISH;
+ goto move_next;
+ }
+
+ rxcb = ATH12K_SKB_RXCB(skb);
+
+ dma_sync_single_for_cpu(ab->dev, rxcb->paddr,
+ skb->len + skb_tailroom(skb),
+ DMA_FROM_DEVICE);
+
+ tlv = (struct hal_tlv_64_hdr *)skb->data;
+ if (le64_get_bits(tlv->tl, HAL_TLV_HDR_TAG) !=
+ HAL_RX_STATUS_BUFFER_DONE) {
+ pmon->buf_state = DP_MON_STATUS_NO_DMA;
+ ath12k_warn(ab,
+ "mon status DONE not set %llx, buf_id %d\n",
+ le64_get_bits(tlv->tl, HAL_TLV_HDR_TAG),
+ buf_id);
+ /* RxDMA status done bit might not be set even
+ * though tp is moved by HW.
+ */
+
+ /* If done status is missing:
+ * 1. As per MAC team's suggestion,
+ * when HP + 1 entry is peeked and if DMA
+ * is not done and if HP + 2 entry's DMA done
+ * is set. skip HP + 1 entry and
+ * start processing in next interrupt.
+ * 2. If HP + 2 entry's DMA done is not set,
+ * poll onto HP + 1 entry DMA done to be set.
+ * Check status for same buffer for next time
+ * dp_rx_mon_status_srng_process
+ */
+ reap_status = ath12k_wifi7_dp_rx_mon_buf_done(ab, srng,
+ rx_ring);
+ if (reap_status == DP_MON_STATUS_NO_DMA)
+ continue;
+
+ spin_lock_bh(&rx_ring->idr_lock);
+ idr_remove(&rx_ring->bufs_idr, buf_id);
+ spin_unlock_bh(&rx_ring->idr_lock);
+
+ dma_unmap_single(ab->dev, rxcb->paddr,
+ skb->len + skb_tailroom(skb),
+ DMA_FROM_DEVICE);
+
+ dev_kfree_skb_any(skb);
+ pmon->buf_state = DP_MON_STATUS_REPLINISH;
+ goto move_next;
+ }
+
+ spin_lock_bh(&rx_ring->idr_lock);
+ idr_remove(&rx_ring->bufs_idr, buf_id);
+ spin_unlock_bh(&rx_ring->idr_lock);
+
+ dma_unmap_single(ab->dev, rxcb->paddr,
+ skb->len + skb_tailroom(skb),
+ DMA_FROM_DEVICE);
+
+ if (ath12k_dp_pkt_set_pktlen(skb, RX_MON_STATUS_BUF_SIZE)) {
+ dev_kfree_skb_any(skb);
+ goto move_next;
+ }
+ __skb_queue_tail(skb_list, skb);
+ } else {
+ pmon->buf_state = DP_MON_STATUS_REPLINISH;
+ }
+move_next:
+ skb = ath12k_dp_rx_alloc_mon_status_buf(ab, rx_ring,
+ &buf_id);
+ hal_params = ab->hal.hal_params;
+
+ if (!skb) {
+ ath12k_warn(ab, "failed to alloc buffer for status ring\n");
+ ath12k_wifi7_hal_rx_buf_addr_info_set(rx_mon_status_desc,
+ 0, 0,
+ hal_params->rx_buf_rbm);
+ num_buffs_reaped++;
+ break;
+ }
+ rxcb = ATH12K_SKB_RXCB(skb);
+
+ cookie = u32_encode_bits(mac_id, DP_RXDMA_BUF_COOKIE_PDEV_ID) |
+ u32_encode_bits(buf_id, DP_RXDMA_BUF_COOKIE_BUF_ID);
+
+ ath12k_wifi7_hal_rx_buf_addr_info_set(rx_mon_status_desc, rxcb->paddr,
+ cookie, hal_params->rx_buf_rbm);
+ ath12k_hal_srng_src_get_next_entry(ab, srng);
+ num_buffs_reaped++;
+ }
+ ath12k_hal_srng_access_end(ab, srng);
+ spin_unlock_bh(&srng->lock);
+
+ return num_buffs_reaped;
+}
+
+static int
+__ath12k_wifi7_dp_mon_process_ring(struct ath12k *ar, int mac_id,
+ struct napi_struct *napi, int *budget)
+{
+ struct ath12k_mon_data *pmon = (struct ath12k_mon_data *)&ar->dp.mon_data;
+ struct ath12k_pdev_mon_stats *rx_mon_stats = &pmon->rx_mon_stats;
+ struct hal_rx_mon_ppdu_info *ppdu_info = &pmon->mon_ppdu_info;
+ enum hal_rx_mon_status hal_status;
+ struct sk_buff_head skb_list;
+ int num_buffs_reaped;
+ struct sk_buff *skb;
+
+ __skb_queue_head_init(&skb_list);
+
+ num_buffs_reaped = ath12k_wifi7_dp_rx_reap_mon_status_ring(ar->ab, mac_id,
+ budget, &skb_list);
+ if (!num_buffs_reaped)
+ goto exit;
+
+ while ((skb = __skb_dequeue(&skb_list))) {
+ memset(ppdu_info, 0, sizeof(*ppdu_info));
+ ppdu_info->peer_id = HAL_INVALID_PEERID;
+
+ hal_status = ath12k_wifi7_dp_mon_parse_rx_dest(&ar->dp, pmon, skb);
+
+ if (ar->monitor_started &&
+ pmon->mon_ppdu_status == DP_PPDU_STATUS_START &&
+ hal_status == HAL_TLV_STATUS_PPDU_DONE) {
+ rx_mon_stats->status_ppdu_done++;
+ pmon->mon_ppdu_status = DP_PPDU_STATUS_DONE;
+ ath12k_wifi7_dp_rx_mon_dest_process(ar, mac_id, *budget, napi);
+ pmon->mon_ppdu_status = DP_PPDU_STATUS_START;
+ }
+
+ dev_kfree_skb_any(skb);
+ }
+
+exit:
+ return num_buffs_reaped;
+}
+
+static int
+ath12k_wifi7_dp_mon_srng_process(struct ath12k_pdev_dp *pdev_dp, int *budget,
+ struct napi_struct *napi)
+{
+ struct ath12k_dp *dp = pdev_dp->dp;
+ struct ath12k_base *ab = dp->ab;
+ struct ath12k_mon_data *pmon = (struct ath12k_mon_data *)&pdev_dp->mon_data;
+ struct hal_rx_mon_ppdu_info *ppdu_info = &pmon->mon_ppdu_info;
+ struct hal_mon_dest_desc *mon_dst_desc;
+ struct sk_buff *skb;
+ struct ath12k_skb_rxcb *rxcb;
+ struct dp_srng *mon_dst_ring;
+ struct hal_srng *srng;
+ struct dp_rxdma_mon_ring *buf_ring;
+ struct ath12k_dp_link_peer *peer;
+ struct sk_buff_head skb_list;
+ u64 cookie;
+ int num_buffs_reaped = 0, srng_id, buf_id;
+ u32 hal_status, end_offset, info0, end_reason;
+ u8 pdev_idx = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, pdev_dp->mac_id);
+
+ __skb_queue_head_init(&skb_list);
+ srng_id = ath12k_hw_mac_id_to_srng_id(ab->hw_params, pdev_idx);
+ mon_dst_ring = &pdev_dp->rxdma_mon_dst_ring[srng_id];
+ buf_ring = &dp->rxdma_mon_buf_ring;
+
+ srng = &ab->hal.srng_list[mon_dst_ring->ring_id];
+ spin_lock_bh(&srng->lock);
+ ath12k_hal_srng_access_begin(ab, srng);
+
+ while (likely(*budget)) {
+ mon_dst_desc = ath12k_hal_srng_dst_peek(ab, srng);
+ if (unlikely(!mon_dst_desc))
+ break;
+
+ /* In case of empty descriptor, the cookie in the ring descriptor
+ * is invalid. Therefore, this entry is skipped, and ring processing
+ * continues.
+ */
+ info0 = le32_to_cpu(mon_dst_desc->info0);
+ if (u32_get_bits(info0, HAL_MON_DEST_INFO0_EMPTY_DESC))
+ goto move_next;
+
+ cookie = le32_to_cpu(mon_dst_desc->cookie);
+ buf_id = u32_get_bits(cookie, DP_RXDMA_BUF_COOKIE_BUF_ID);
+
+ spin_lock_bh(&buf_ring->idr_lock);
+ skb = idr_remove(&buf_ring->bufs_idr, buf_id);
+ spin_unlock_bh(&buf_ring->idr_lock);
+
+ if (unlikely(!skb)) {
+ ath12k_warn(ab, "monitor destination with invalid buf_id %d\n",
+ buf_id);
+ goto move_next;
+ }
+
+ rxcb = ATH12K_SKB_RXCB(skb);
+ dma_unmap_single(ab->dev, rxcb->paddr,
+ skb->len + skb_tailroom(skb),
+ DMA_FROM_DEVICE);
+
+ end_reason = u32_get_bits(info0, HAL_MON_DEST_INFO0_END_REASON);
+
+ /* HAL_MON_FLUSH_DETECTED implies that an rx flush received at the end of
+ * rx PPDU and HAL_MON_PPDU_TRUNCATED implies that the PPDU got
+ * truncated due to a system level error. In both the cases, buffer data
+ * can be discarded
+ */
+ if ((end_reason == HAL_MON_FLUSH_DETECTED) ||
+ (end_reason == HAL_MON_PPDU_TRUNCATED)) {
+ ath12k_dbg(ab, ATH12K_DBG_DATA,
+ "Monitor dest descriptor end reason %d", end_reason);
+ dev_kfree_skb_any(skb);
+ goto move_next;
+ }
+
+ /* Calculate the budget when the ring descriptor with the
+ * HAL_MON_END_OF_PPDU to ensure that one PPDU worth of data is always
+ * reaped. This helps to efficiently utilize the NAPI budget.
+ */
+ if (end_reason == HAL_MON_END_OF_PPDU) {
+ *budget -= 1;
+ rxcb->is_end_of_ppdu = true;
+ }
+
+ end_offset = u32_get_bits(info0, HAL_MON_DEST_INFO0_END_OFFSET);
+ if (likely(end_offset <= DP_RX_BUFFER_SIZE)) {
+ skb_put(skb, end_offset);
+ } else {
+ ath12k_warn(ab,
+ "invalid offset on mon stats destination %u\n",
+ end_offset);
+ skb_put(skb, DP_RX_BUFFER_SIZE);
+ }
+
+ __skb_queue_tail(&skb_list, skb);
+
+move_next:
+ ath12k_dp_mon_buf_replenish(ab, buf_ring, 1);
+ ath12k_hal_srng_dst_get_next_entry(ab, srng);
+ num_buffs_reaped++;
+ }
+
+ ath12k_hal_srng_access_end(ab, srng);
+ spin_unlock_bh(&srng->lock);
+
+ if (!num_buffs_reaped)
+ return 0;
+
+ /* In some cases, one PPDU worth of data can be spread across multiple NAPI
+ * schedules, To avoid losing existing parsed ppdu_info information, skip
+ * the memset of the ppdu_info structure and continue processing it.
+ */
+ if (!ppdu_info->ppdu_continuation)
+ ath12k_wifi7_dp_mon_rx_memset_ppdu_info(ppdu_info);
+
+ while ((skb = __skb_dequeue(&skb_list))) {
+ hal_status = ath12k_wifi7_dp_mon_rx_parse_mon_status(pdev_dp, pmon,
+ skb, napi);
+ if (hal_status != HAL_RX_MON_STATUS_PPDU_DONE) {
+ ppdu_info->ppdu_continuation = true;
+ dev_kfree_skb_any(skb);
+ continue;
+ }
+
+ if (ppdu_info->peer_id == HAL_INVALID_PEERID)
+ goto free_skb;
+
+ rcu_read_lock();
+ peer = ath12k_dp_link_peer_find_by_peerid(pdev_dp, ppdu_info->peer_id);
+ if (!peer || !peer->sta) {
+ ath12k_dbg(ab, ATH12K_DBG_DATA,
+ "failed to find the peer with monitor peer_id %d\n",
+ ppdu_info->peer_id);
+ goto next_skb;
+ }
+
+ if (ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_SU) {
+ ath12k_dp_mon_rx_update_peer_su_stats(peer, ppdu_info);
+ } else if ((ppdu_info->fc_valid) &&
+ (ppdu_info->ast_index != HAL_AST_IDX_INVALID)) {
+ ath12k_dp_mon_rx_process_ulofdma(ppdu_info);
+ ath12k_dp_mon_rx_update_peer_mu_stats(ab, ppdu_info);
+ }
+
+next_skb:
+ rcu_read_unlock();
+free_skb:
+ dev_kfree_skb_any(skb);
+ ath12k_wifi7_dp_mon_rx_memset_ppdu_info(ppdu_info);
+ }
+
+ return num_buffs_reaped;
+}
+
+int ath12k_wifi7_dp_mon_process_ring(struct ath12k_dp *dp, int mac_id,
+ struct napi_struct *napi, int budget,
+ enum dp_monitor_mode monitor_mode)
+{
+ u8 pdev_idx = ath12k_hw_mac_id_to_pdev_id(dp->hw_params, mac_id);
+ struct ath12k_pdev_dp *dp_pdev;
+ struct ath12k *ar;
+ int num_buffs_reaped = 0;
+
+ rcu_read_lock();
+
+ dp_pdev = ath12k_dp_to_pdev_dp(dp, pdev_idx);
+ if (!dp_pdev) {
+ rcu_read_unlock();
+ return 0;
+ }
+
+ if (dp->hw_params->rxdma1_enable) {
+ if (monitor_mode == ATH12K_DP_RX_MONITOR_MODE)
+ num_buffs_reaped = ath12k_wifi7_dp_mon_srng_process(dp_pdev,
+ &budget,
+ napi);
+ } else {
+ ar = ath12k_pdev_dp_to_ar(dp_pdev);
+
+ if (ar->monitor_started)
+ num_buffs_reaped =
+ __ath12k_wifi7_dp_mon_process_ring(ar, mac_id, napi,
+ &budget);
+ }
+
+ rcu_read_unlock();
+
+ return num_buffs_reaped;
+}
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.h b/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.h
new file mode 100644
index 000000000000..148d1e0b70fe
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef ATH12K_DP_MON_WIFI7_H
+#define ATH12K_DP_MON_WIFI7_H
+
+#include "hw.h"
+
+enum dp_monitor_mode;
+
+int ath12k_wifi7_dp_mon_process_ring(struct ath12k_dp *dp, int mac_id,
+ struct napi_struct *napi, int budget,
+ enum dp_monitor_mode monitor_mode);
+enum hal_rx_mon_status
+ath12k_wifi7_dp_mon_tx_parse_mon_status(struct ath12k_pdev_dp *dp_pdev,
+ struct ath12k_mon_data *pmon,
+ struct sk_buff *skb,
+ struct napi_struct *napi,
+ u32 ppdu_id);
+#endif
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
new file mode 100644
index 000000000000..7450938adf65
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
@@ -0,0 +1,2246 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include "dp_rx.h"
+#include "../dp_tx.h"
+#include "../peer.h"
+#include "hal_qcn9274.h"
+#include "hal_wcn7850.h"
+#include "hal_qcc2072.h"
+
+static u16 ath12k_wifi7_dp_rx_get_peer_id(struct ath12k_dp *dp,
+ enum ath12k_peer_metadata_version ver,
+ __le32 peer_metadata)
+{
+ switch (ver) {
+ default:
+ ath12k_warn(dp->ab, "Unknown peer metadata version: %d", ver);
+ fallthrough;
+ case ATH12K_PEER_METADATA_V0:
+ return le32_get_bits(peer_metadata,
+ RX_MPDU_DESC_META_DATA_V0_PEER_ID);
+ case ATH12K_PEER_METADATA_V1:
+ return le32_get_bits(peer_metadata,
+ RX_MPDU_DESC_META_DATA_V1_PEER_ID);
+ case ATH12K_PEER_METADATA_V1A:
+ return le32_get_bits(peer_metadata,
+ RX_MPDU_DESC_META_DATA_V1A_PEER_ID);
+ case ATH12K_PEER_METADATA_V1B:
+ return le32_get_bits(peer_metadata,
+ RX_MPDU_DESC_META_DATA_V1B_PEER_ID);
+ }
+}
+
+void ath12k_wifi7_peer_rx_tid_qref_setup(struct ath12k_base *ab, u16 peer_id, u16 tid,
+ dma_addr_t paddr)
+{
+ struct ath12k_reo_queue_ref *qref;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ bool ml_peer = false;
+
+ if (!ab->hw_params->reoq_lut_support)
+ return;
+
+ if (peer_id & ATH12K_PEER_ML_ID_VALID) {
+ peer_id &= ~ATH12K_PEER_ML_ID_VALID;
+ ml_peer = true;
+ }
+
+ if (ml_peer)
+ qref = (struct ath12k_reo_queue_ref *)dp->ml_reoq_lut.vaddr +
+ (peer_id * (IEEE80211_NUM_TIDS + 1) + tid);
+ else
+ qref = (struct ath12k_reo_queue_ref *)dp->reoq_lut.vaddr +
+ (peer_id * (IEEE80211_NUM_TIDS + 1) + tid);
+
+ qref->info0 = u32_encode_bits(lower_32_bits(paddr),
+ BUFFER_ADDR_INFO0_ADDR);
+ qref->info1 = u32_encode_bits(upper_32_bits(paddr),
+ BUFFER_ADDR_INFO1_ADDR) |
+ u32_encode_bits(tid, DP_REO_QREF_NUM);
+
+ ath12k_hal_reo_shared_qaddr_cache_clear(ab);
+}
+
+void ath12k_wifi7_peer_rx_tid_qref_reset(struct ath12k_base *ab,
+ u16 peer_id, u16 tid)
+{
+ struct ath12k_reo_queue_ref *qref;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ bool ml_peer = false;
+
+ if (!ab->hw_params->reoq_lut_support)
+ return;
+
+ if (peer_id & ATH12K_PEER_ML_ID_VALID) {
+ peer_id &= ~ATH12K_PEER_ML_ID_VALID;
+ ml_peer = true;
+ }
+
+ if (ml_peer)
+ qref = (struct ath12k_reo_queue_ref *)dp->ml_reoq_lut.vaddr +
+ (peer_id * (IEEE80211_NUM_TIDS + 1) + tid);
+ else
+ qref = (struct ath12k_reo_queue_ref *)dp->reoq_lut.vaddr +
+ (peer_id * (IEEE80211_NUM_TIDS + 1) + tid);
+
+ qref->info0 = u32_encode_bits(0, BUFFER_ADDR_INFO0_ADDR);
+ qref->info1 = u32_encode_bits(0, BUFFER_ADDR_INFO1_ADDR) |
+ u32_encode_bits(tid, DP_REO_QREF_NUM);
+}
+
+void ath12k_wifi7_dp_rx_peer_tid_delete(struct ath12k_base *ab,
+ struct ath12k_dp_link_peer *peer, u8 tid)
+{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+
+ if (!(peer->rx_tid_active_bitmask & (1 << tid)))
+ return;
+
+ ath12k_dp_mark_tid_as_inactive(dp, peer->peer_id, tid);
+ ath12k_dp_rx_process_reo_cmd_update_rx_queue_list(dp);
+}
+
+int ath12k_wifi7_dp_rx_link_desc_return(struct ath12k_dp *dp,
+ struct ath12k_buffer_addr *buf_addr_info,
+ enum hal_wbm_rel_bm_act action)
+{
+ struct ath12k_base *ab = dp->ab;
+ struct hal_wbm_release_ring *desc;
+ struct hal_srng *srng;
+ int ret = 0;
+
+ srng = &dp->hal->srng_list[dp->wbm_desc_rel_ring.ring_id];
+
+ spin_lock_bh(&srng->lock);
+
+ ath12k_hal_srng_access_begin(ab, srng);
+
+ desc = ath12k_hal_srng_src_get_next_entry(ab, srng);
+ if (!desc) {
+ ret = -ENOBUFS;
+ goto exit;
+ }
+
+ ath12k_wifi7_hal_rx_msdu_link_desc_set(ab, desc, buf_addr_info, action);
+
+exit:
+ ath12k_hal_srng_access_end(ab, srng);
+
+ spin_unlock_bh(&srng->lock);
+
+ return ret;
+}
+
+int ath12k_wifi7_dp_reo_cmd_send(struct ath12k_base *ab,
+ struct ath12k_dp_rx_tid_rxq *rx_tid,
+ enum hal_reo_cmd_type type,
+ struct ath12k_hal_reo_cmd *cmd,
+ void (*cb)(struct ath12k_dp *dp, void *ctx,
+ enum hal_reo_cmd_status status))
+{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_dp_rx_reo_cmd *dp_cmd;
+ struct hal_srng *cmd_ring;
+ int cmd_num;
+
+ cmd_ring = &ab->hal.srng_list[dp->reo_cmd_ring.ring_id];
+ cmd_num = ath12k_wifi7_hal_reo_cmd_send(ab, cmd_ring, type, cmd);
+
+ /* cmd_num should start from 1, during failure return the error code */
+ if (cmd_num < 0)
+ return cmd_num;
+
+ /* reo cmd ring descriptors has cmd_num starting from 1 */
+ if (cmd_num == 0)
+ return -EINVAL;
+
+ if (!cb)
+ return 0;
+
+ /* Can this be optimized so that we keep the pending command list only
+ * for tid delete command to free up the resource on the command status
+ * indication?
+ */
+ dp_cmd = kzalloc(sizeof(*dp_cmd), GFP_ATOMIC);
+
+ if (!dp_cmd)
+ return -ENOMEM;
+
+ memcpy(&dp_cmd->data, rx_tid, sizeof(*rx_tid));
+ dp_cmd->cmd_num = cmd_num;
+ dp_cmd->handler = cb;
+
+ spin_lock_bh(&dp->reo_cmd_lock);
+ list_add_tail(&dp_cmd->list, &dp->reo_cmd_list);
+ spin_unlock_bh(&dp->reo_cmd_lock);
+
+ return 0;
+}
+
+int ath12k_wifi7_peer_rx_tid_reo_update(struct ath12k_dp *dp,
+ struct ath12k_dp_link_peer *peer,
+ struct ath12k_dp_rx_tid *rx_tid,
+ u32 ba_win_sz, u16 ssn,
+ bool update_ssn)
+{
+ struct ath12k_hal_reo_cmd cmd = {};
+ struct ath12k_base *ab = dp->ab;
+ int ret;
+ struct ath12k_dp_rx_tid_rxq rx_tid_rxq;
+
+ ath12k_dp_init_rx_tid_rxq(&rx_tid_rxq, rx_tid,
+ (peer->rx_tid_active_bitmask & (1 << rx_tid->tid)));
+
+ cmd.addr_lo = lower_32_bits(rx_tid_rxq.qbuf.paddr_aligned);
+ cmd.addr_hi = upper_32_bits(rx_tid_rxq.qbuf.paddr_aligned);
+ cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS;
+ cmd.upd0 = HAL_REO_CMD_UPD0_BA_WINDOW_SIZE;
+ cmd.ba_window_size = ba_win_sz;
+
+ if (update_ssn) {
+ cmd.upd0 |= HAL_REO_CMD_UPD0_SSN;
+ cmd.upd2 = u32_encode_bits(ssn, HAL_REO_CMD_UPD2_SSN);
+ }
+
+ ret = ath12k_wifi7_dp_reo_cmd_send(ab, &rx_tid_rxq,
+ HAL_REO_CMD_UPDATE_RX_QUEUE, &cmd,
+ NULL);
+ if (ret) {
+ ath12k_warn(ab, "failed to update rx tid queue, tid %d (%d)\n",
+ rx_tid_rxq.tid, ret);
+ return ret;
+ }
+
+ rx_tid->ba_win_sz = ba_win_sz;
+
+ return 0;
+}
+
+int ath12k_wifi7_dp_reo_cache_flush(struct ath12k_base *ab,
+ struct ath12k_dp_rx_tid_rxq *rx_tid)
+{
+ struct ath12k_hal_reo_cmd cmd = {};
+ int ret;
+
+ cmd.addr_lo = lower_32_bits(rx_tid->qbuf.paddr_aligned);
+ cmd.addr_hi = upper_32_bits(rx_tid->qbuf.paddr_aligned);
+ /* HAL_REO_CMD_FLG_FLUSH_FWD_ALL_MPDUS - all pending MPDUs
+ *in the bitmap will be forwarded/flushed to REO output rings
+ */
+ cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS |
+ HAL_REO_CMD_FLG_FLUSH_FWD_ALL_MPDUS;
+
+ /* For all QoS TIDs (except NON_QOS), the driver allocates a maximum
+ * window size of 1024. In such cases, the driver can issue a single
+ * 1KB descriptor flush command instead of sending multiple 128-byte
+ * flush commands for each QoS TID, improving efficiency.
+ */
+
+ if (rx_tid->tid != HAL_DESC_REO_NON_QOS_TID)
+ cmd.flag |= HAL_REO_CMD_FLG_FLUSH_QUEUE_1K_DESC;
+
+ ret = ath12k_wifi7_dp_reo_cmd_send(ab, rx_tid,
+ HAL_REO_CMD_FLUSH_CACHE,
+ &cmd, ath12k_dp_reo_cmd_free);
+ return ret;
+}
+
+int ath12k_wifi7_dp_rx_assign_reoq(struct ath12k_base *ab, struct ath12k_dp_peer *dp_peer,
+ struct ath12k_dp_rx_tid *rx_tid,
+ u16 ssn, enum hal_pn_type pn_type)
+{
+ u32 ba_win_sz = rx_tid->ba_win_sz;
+ struct ath12k_reoq_buf *buf;
+ void *vaddr, *vaddr_aligned;
+ dma_addr_t paddr_aligned;
+ u8 tid = rx_tid->tid;
+ u32 hw_desc_sz;
+ int ret;
+
+ buf = &dp_peer->reoq_bufs[tid];
+ if (!buf->vaddr) {
+ /* TODO: Optimize the memory allocation for qos tid based on
+ * the actual BA window size in REO tid update path.
+ */
+ if (tid == HAL_DESC_REO_NON_QOS_TID)
+ hw_desc_sz = ath12k_wifi7_hal_reo_qdesc_size(ba_win_sz, tid);
+ else
+ hw_desc_sz = ath12k_wifi7_hal_reo_qdesc_size(DP_BA_WIN_SZ_MAX,
+ tid);
+
+ vaddr = kzalloc(hw_desc_sz + HAL_LINK_DESC_ALIGN - 1, GFP_ATOMIC);
+ if (!vaddr)
+ return -ENOMEM;
+
+ vaddr_aligned = PTR_ALIGN(vaddr, HAL_LINK_DESC_ALIGN);
+
+ ath12k_wifi7_hal_reo_qdesc_setup(vaddr_aligned, tid, ba_win_sz,
+ ssn, pn_type);
+
+ paddr_aligned = dma_map_single(ab->dev, vaddr_aligned, hw_desc_sz,
+ DMA_BIDIRECTIONAL);
+ ret = dma_mapping_error(ab->dev, paddr_aligned);
+ if (ret) {
+ kfree(vaddr);
+ return ret;
+ }
+
+ buf->vaddr = vaddr;
+ buf->paddr_aligned = paddr_aligned;
+ buf->size = hw_desc_sz;
+ }
+
+ rx_tid->qbuf = *buf;
+
+ return 0;
+}
+
+int ath12k_wifi7_dp_rx_tid_delete_handler(struct ath12k_base *ab,
+ struct ath12k_dp_rx_tid_rxq *rx_tid)
+{
+ struct ath12k_hal_reo_cmd cmd = {};
+
+ cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS;
+ cmd.addr_lo = lower_32_bits(rx_tid->qbuf.paddr_aligned);
+ cmd.addr_hi = upper_32_bits(rx_tid->qbuf.paddr_aligned);
+ cmd.upd0 |= HAL_REO_CMD_UPD0_VLD;
+ /* Observed flush cache failure, to avoid that set vld bit during delete */
+ cmd.upd1 |= HAL_REO_CMD_UPD1_VLD;
+
+ return ath12k_wifi7_dp_reo_cmd_send(ab, rx_tid,
+ HAL_REO_CMD_UPDATE_RX_QUEUE, &cmd,
+ ath12k_dp_rx_tid_del_func);
+}
+
+static void ath12k_wifi7_dp_rx_h_csum_offload(struct sk_buff *msdu,
+ struct hal_rx_desc_data *rx_info)
+{
+ msdu->ip_summed = (rx_info->ip_csum_fail || rx_info->l4_csum_fail) ?
+ CHECKSUM_NONE : CHECKSUM_UNNECESSARY;
+}
+
+static void ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev,
+ struct sk_buff *msdu,
+ struct hal_rx_desc *rx_desc,
+ struct hal_rx_desc_data *rx_info)
+{
+ struct ath12k_skb_rxcb *rxcb;
+ enum hal_encrypt_type enctype;
+ bool is_decrypted = false;
+ struct ieee80211_hdr *hdr;
+ struct ath12k_dp_peer *peer;
+ struct ieee80211_rx_status *rx_status = rx_info->rx_status;
+ u32 err_bitmap = rx_info->err_bitmap;
+
+ RCU_LOCKDEP_WARN(!rcu_read_lock_held(),
+ "dp_rx_h_mpdu called without rcu lock");
+
+ /* PN for multicast packets will be checked in mac80211 */
+ rxcb = ATH12K_SKB_RXCB(msdu);
+ rxcb->is_mcbc = rx_info->is_mcbc;
+
+ if (rxcb->is_mcbc)
+ rxcb->peer_id = rx_info->peer_id;
+
+ peer = ath12k_dp_peer_find_by_peerid(dp_pdev, rxcb->peer_id);
+ if (peer) {
+ /* resetting mcbc bit because mcbc packets are unicast
+ * packets only for AP as STA sends unicast packets.
+ */
+ rxcb->is_mcbc = rxcb->is_mcbc && !peer->ucast_ra_only;
+
+ if (rxcb->is_mcbc)
+ enctype = peer->sec_type_grp;
+ else
+ enctype = peer->sec_type;
+ } else {
+ enctype = HAL_ENCRYPT_TYPE_OPEN;
+ }
+
+ if (enctype != HAL_ENCRYPT_TYPE_OPEN && !err_bitmap)
+ is_decrypted = rx_info->is_decrypted;
+
+ /* Clear per-MPDU flags while leaving per-PPDU flags intact */
+ rx_status->flag &= ~(RX_FLAG_FAILED_FCS_CRC |
+ RX_FLAG_MMIC_ERROR |
+ RX_FLAG_DECRYPTED |
+ RX_FLAG_IV_STRIPPED |
+ RX_FLAG_MMIC_STRIPPED);
+
+ if (err_bitmap & HAL_RX_MPDU_ERR_FCS)
+ rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+ if (err_bitmap & HAL_RX_MPDU_ERR_TKIP_MIC)
+ rx_status->flag |= RX_FLAG_MMIC_ERROR;
+
+ if (is_decrypted) {
+ rx_status->flag |= RX_FLAG_DECRYPTED | RX_FLAG_MMIC_STRIPPED;
+
+ if (rx_info->is_mcbc)
+ rx_status->flag |= RX_FLAG_MIC_STRIPPED |
+ RX_FLAG_ICV_STRIPPED;
+ else
+ rx_status->flag |= RX_FLAG_IV_STRIPPED |
+ RX_FLAG_PN_VALIDATED;
+ }
+
+ ath12k_wifi7_dp_rx_h_csum_offload(msdu, rx_info);
+ ath12k_dp_rx_h_undecap(dp_pdev, msdu, rx_desc,
+ enctype, is_decrypted, rx_info);
+
+ if (!is_decrypted || rx_info->is_mcbc)
+ return;
+
+ if (rx_info->decap_type != DP_RX_DECAP_TYPE_ETHERNET2_DIX) {
+ hdr = (void *)msdu->data;
+ hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+ }
+}
+
+static int ath12k_wifi7_dp_rx_msdu_coalesce(struct ath12k_hal *hal,
+ struct sk_buff_head *msdu_list,
+ struct sk_buff *first, struct sk_buff *last,
+ u8 l3pad_bytes, int msdu_len,
+ struct hal_rx_desc_data *rx_info)
+{
+ struct sk_buff *skb;
+ struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(first);
+ int buf_first_hdr_len, buf_first_len;
+ struct hal_rx_desc *ldesc;
+ int space_extra, rem_len, buf_len;
+ u32 hal_rx_desc_sz = hal->hal_desc_sz;
+ bool is_continuation;
+
+ /* As the msdu is spread across multiple rx buffers,
+ * find the offset to the start of msdu for computing
+ * the length of the msdu in the first buffer.
+ */
+ buf_first_hdr_len = hal_rx_desc_sz + l3pad_bytes;
+ buf_first_len = DP_RX_BUFFER_SIZE - buf_first_hdr_len;
+
+ if (WARN_ON_ONCE(msdu_len <= buf_first_len)) {
+ skb_put(first, buf_first_hdr_len + msdu_len);
+ skb_pull(first, buf_first_hdr_len);
+ return 0;
+ }
+
+ ldesc = (struct hal_rx_desc *)last->data;
+ rxcb->is_first_msdu = rx_info->is_first_msdu;
+ rxcb->is_last_msdu = rx_info->is_last_msdu;
+
+ /* MSDU spans over multiple buffers because the length of the MSDU
+ * exceeds DP_RX_BUFFER_SIZE - HAL_RX_DESC_SIZE. So assume the data
+ * in the first buf is of length DP_RX_BUFFER_SIZE - HAL_RX_DESC_SIZE.
+ */
+ skb_put(first, DP_RX_BUFFER_SIZE);
+ skb_pull(first, buf_first_hdr_len);
+
+ /* When an MSDU spread over multiple buffers MSDU_END
+ * tlvs are valid only in the last buffer. Copy those tlvs.
+ */
+ ath12k_dp_rx_desc_end_tlv_copy(hal, rxcb->rx_desc, ldesc);
+
+ space_extra = msdu_len - (buf_first_len + skb_tailroom(first));
+ if (space_extra > 0 &&
+ (pskb_expand_head(first, 0, space_extra, GFP_ATOMIC) < 0)) {
+ /* Free up all buffers of the MSDU */
+ while ((skb = __skb_dequeue(msdu_list)) != NULL) {
+ rxcb = ATH12K_SKB_RXCB(skb);
+ if (!rxcb->is_continuation) {
+ dev_kfree_skb_any(skb);
+ break;
+ }
+ dev_kfree_skb_any(skb);
+ }
+ return -ENOMEM;
+ }
+
+ rem_len = msdu_len - buf_first_len;
+ while ((skb = __skb_dequeue(msdu_list)) != NULL && rem_len > 0) {
+ rxcb = ATH12K_SKB_RXCB(skb);
+ is_continuation = rxcb->is_continuation;
+ if (is_continuation)
+ buf_len = DP_RX_BUFFER_SIZE - hal_rx_desc_sz;
+ else
+ buf_len = rem_len;
+
+ if (buf_len > (DP_RX_BUFFER_SIZE - hal_rx_desc_sz)) {
+ WARN_ON_ONCE(1);
+ dev_kfree_skb_any(skb);
+ return -EINVAL;
+ }
+
+ skb_put(skb, buf_len + hal_rx_desc_sz);
+ skb_pull(skb, hal_rx_desc_sz);
+ skb_copy_from_linear_data(skb, skb_put(first, buf_len),
+ buf_len);
+ dev_kfree_skb_any(skb);
+
+ rem_len -= buf_len;
+ if (!is_continuation)
+ break;
+ }
+
+ return 0;
+}
+
+static int ath12k_wifi7_dp_rx_process_msdu(struct ath12k_pdev_dp *dp_pdev,
+ struct sk_buff *msdu,
+ struct sk_buff_head *msdu_list,
+ struct hal_rx_desc_data *rx_info)
+{
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct hal_rx_desc *rx_desc, *lrx_desc;
+ struct ath12k_skb_rxcb *rxcb;
+ struct sk_buff *last_buf;
+ struct ath12k_hal *hal = dp->hal;
+ u8 l3_pad_bytes;
+ u16 msdu_len;
+ int ret;
+ u32 hal_rx_desc_sz = hal->hal_desc_sz;
+
+ last_buf = ath12k_dp_rx_get_msdu_last_buf(msdu_list, msdu);
+ if (!last_buf) {
+ ath12k_warn(dp->ab,
+ "No valid Rx buffer to access MSDU_END tlv\n");
+ ret = -EIO;
+ goto free_out;
+ }
+
+ rx_desc = (struct hal_rx_desc *)msdu->data;
+ lrx_desc = (struct hal_rx_desc *)last_buf->data;
+
+ ath12k_dp_extract_rx_desc_data(hal, rx_info, rx_desc, lrx_desc);
+ if (!rx_info->msdu_done) {
+ ath12k_warn(dp->ab, "msdu_done bit in msdu_end is not set\n");
+ ret = -EIO;
+ goto free_out;
+ }
+
+ rxcb = ATH12K_SKB_RXCB(msdu);
+ rxcb->rx_desc = rx_desc;
+ msdu_len = rx_info->msdu_len;
+ l3_pad_bytes = rx_info->l3_pad_bytes;
+
+ if (rxcb->is_frag) {
+ skb_pull(msdu, hal_rx_desc_sz);
+ } else if (!rxcb->is_continuation) {
+ if ((msdu_len + hal_rx_desc_sz) > DP_RX_BUFFER_SIZE) {
+ ret = -EINVAL;
+ ath12k_warn(dp->ab, "invalid msdu len %u\n", msdu_len);
+ ath12k_dbg_dump(dp->ab, ATH12K_DBG_DATA, NULL, "", rx_desc,
+ sizeof(*rx_desc));
+ goto free_out;
+ }
+ skb_put(msdu, hal_rx_desc_sz + l3_pad_bytes + msdu_len);
+ skb_pull(msdu, hal_rx_desc_sz + l3_pad_bytes);
+ } else {
+ ret = ath12k_wifi7_dp_rx_msdu_coalesce(hal, msdu_list,
+ msdu, last_buf,
+ l3_pad_bytes, msdu_len,
+ rx_info);
+ if (ret) {
+ ath12k_warn(dp->ab,
+ "failed to coalesce msdu rx buffer%d\n", ret);
+ goto free_out;
+ }
+ }
+
+ if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(dp, rx_desc, msdu,
+ rx_info))) {
+ ret = -EINVAL;
+ goto free_out;
+ }
+
+ ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
+ ath12k_wifi7_dp_rx_h_mpdu(dp_pdev, msdu, rx_desc, rx_info);
+
+ rx_info->rx_status->flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED;
+
+ return 0;
+
+free_out:
+ return ret;
+}
+
+static void
+ath12k_wifi7_dp_rx_process_received_packets(struct ath12k_dp *dp,
+ struct napi_struct *napi,
+ struct sk_buff_head *msdu_list,
+ int ring_id)
+{
+ struct ath12k_hw_group *ag = dp->ag;
+ struct ath12k_dp_hw_group *dp_hw_grp = &ag->dp_hw_grp;
+ struct ieee80211_rx_status rx_status = {};
+ struct ath12k_skb_rxcb *rxcb;
+ struct sk_buff *msdu;
+ struct ath12k *ar;
+ struct ath12k_pdev_dp *dp_pdev;
+ struct ath12k_hw_link *hw_links = ag->hw_links;
+ struct ath12k_base *partner_ab;
+ struct hal_rx_desc_data rx_info;
+ struct ath12k_dp *partner_dp;
+ u8 hw_link_id, pdev_idx;
+ int ret;
+
+ if (skb_queue_empty(msdu_list))
+ return;
+
+ rx_info.addr2_present = false;
+ rx_info.rx_status = &rx_status;
+
+ rcu_read_lock();
+
+ while ((msdu = __skb_dequeue(msdu_list))) {
+ rxcb = ATH12K_SKB_RXCB(msdu);
+ hw_link_id = rxcb->hw_link_id;
+ partner_dp = ath12k_dp_hw_grp_to_dp(dp_hw_grp,
+ hw_links[hw_link_id].device_id);
+ pdev_idx = ath12k_hw_mac_id_to_pdev_id(partner_dp->hw_params,
+ hw_links[hw_link_id].pdev_idx);
+ partner_ab = partner_dp->ab;
+ ar = partner_ab->pdevs[pdev_idx].ar;
+ if (!rcu_dereference(partner_ab->pdevs_active[pdev_idx])) {
+ dev_kfree_skb_any(msdu);
+ continue;
+ }
+
+ if (test_bit(ATH12K_FLAG_CAC_RUNNING, &ar->dev_flags)) {
+ dev_kfree_skb_any(msdu);
+ continue;
+ }
+
+ dp_pdev = ath12k_dp_to_pdev_dp(partner_dp, pdev_idx);
+ if (!dp_pdev) {
+ dev_kfree_skb_any(msdu);
+ continue;
+ }
+
+ ret = ath12k_wifi7_dp_rx_process_msdu(dp_pdev, msdu, msdu_list, &rx_info);
+ if (ret) {
+ ath12k_dbg(dp->ab, ATH12K_DBG_DATA,
+ "Unable to process msdu %d", ret);
+ dev_kfree_skb_any(msdu);
+ continue;
+ }
+
+ ath12k_dp_rx_deliver_msdu(dp_pdev, napi, msdu, &rx_info);
+ }
+
+ rcu_read_unlock();
+}
+
+int ath12k_wifi7_dp_rx_process(struct ath12k_dp *dp, int ring_id,
+ struct napi_struct *napi, int budget)
+{
+ struct ath12k_hw_group *ag = dp->ag;
+ struct ath12k_base *ab = dp->ab;
+ struct ath12k_hal *hal = dp->hal;
+ struct ath12k_dp_hw_group *dp_hw_grp = &ag->dp_hw_grp;
+ struct list_head rx_desc_used_list[ATH12K_MAX_DEVICES];
+ struct ath12k_hw_link *hw_links = ag->hw_links;
+ int num_buffs_reaped[ATH12K_MAX_DEVICES] = {};
+ struct ath12k_rx_desc_info *desc_info;
+ struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring;
+ struct hal_reo_dest_ring *desc;
+ struct ath12k_dp *partner_dp;
+ struct sk_buff_head msdu_list;
+ struct ath12k_skb_rxcb *rxcb;
+ int total_msdu_reaped = 0;
+ u8 hw_link_id, device_id;
+ struct hal_srng *srng;
+ struct sk_buff *msdu;
+ bool done = false;
+ u64 desc_va;
+
+ __skb_queue_head_init(&msdu_list);
+
+ for (device_id = 0; device_id < ATH12K_MAX_DEVICES; device_id++)
+ INIT_LIST_HEAD(&rx_desc_used_list[device_id]);
+
+ srng = &hal->srng_list[dp->reo_dst_ring[ring_id].ring_id];
+
+ spin_lock_bh(&srng->lock);
+
+try_again:
+ ath12k_hal_srng_access_begin(ab, srng);
+
+ while ((desc = ath12k_hal_srng_dst_get_next_entry(ab, srng))) {
+ struct rx_mpdu_desc *mpdu_info;
+ struct rx_msdu_desc *msdu_info;
+ enum hal_reo_dest_ring_push_reason push_reason;
+ u32 cookie;
+
+ cookie = le32_get_bits(desc->buf_addr_info.info1,
+ BUFFER_ADDR_INFO1_SW_COOKIE);
+
+ hw_link_id = le32_get_bits(desc->info0,
+ HAL_REO_DEST_RING_INFO0_SRC_LINK_ID);
+
+ desc_va = ((u64)le32_to_cpu(desc->buf_va_hi) << 32 |
+ le32_to_cpu(desc->buf_va_lo));
+ desc_info = (struct ath12k_rx_desc_info *)((unsigned long)desc_va);
+
+ device_id = hw_links[hw_link_id].device_id;
+ partner_dp = ath12k_dp_hw_grp_to_dp(dp_hw_grp, device_id);
+ if (unlikely(!partner_dp)) {
+ if (desc_info->skb) {
+ dev_kfree_skb_any(desc_info->skb);
+ desc_info->skb = NULL;
+ }
+
+ continue;
+ }
+
+ /* retry manual desc retrieval */
+ if (!desc_info) {
+ desc_info = ath12k_dp_get_rx_desc(partner_dp, cookie);
+ if (!desc_info) {
+ ath12k_warn(partner_dp->ab, "Invalid cookie in manual descriptor retrieval: 0x%x\n",
+ cookie);
+ continue;
+ }
+ }
+
+ if (desc_info->magic != ATH12K_DP_RX_DESC_MAGIC)
+ ath12k_warn(ab, "Check HW CC implementation");
+
+ msdu = desc_info->skb;
+ desc_info->skb = NULL;
+
+ list_add_tail(&desc_info->list, &rx_desc_used_list[device_id]);
+
+ rxcb = ATH12K_SKB_RXCB(msdu);
+ dma_unmap_single(partner_dp->dev, rxcb->paddr,
+ msdu->len + skb_tailroom(msdu),
+ DMA_FROM_DEVICE);
+
+ num_buffs_reaped[device_id]++;
+ dp->device_stats.reo_rx[ring_id][dp->device_id]++;
+
+ push_reason = le32_get_bits(desc->info0,
+ HAL_REO_DEST_RING_INFO0_PUSH_REASON);
+ if (push_reason !=
+ HAL_REO_DEST_RING_PUSH_REASON_ROUTING_INSTRUCTION) {
+ dev_kfree_skb_any(msdu);
+ dp->device_stats.hal_reo_error[ring_id]++;
+ continue;
+ }
+
+ msdu_info = &desc->rx_msdu_info;
+ mpdu_info = &desc->rx_mpdu_info;
+
+ rxcb->is_first_msdu = !!(le32_to_cpu(msdu_info->info0) &
+ RX_MSDU_DESC_INFO0_FIRST_MSDU_IN_MPDU);
+ rxcb->is_last_msdu = !!(le32_to_cpu(msdu_info->info0) &
+ RX_MSDU_DESC_INFO0_LAST_MSDU_IN_MPDU);
+ rxcb->is_continuation = !!(le32_to_cpu(msdu_info->info0) &
+ RX_MSDU_DESC_INFO0_MSDU_CONTINUATION);
+ rxcb->hw_link_id = hw_link_id;
+ rxcb->peer_id = ath12k_wifi7_dp_rx_get_peer_id(dp, dp->peer_metadata_ver,
+ mpdu_info->peer_meta_data);
+ rxcb->tid = le32_get_bits(mpdu_info->info0,
+ RX_MPDU_DESC_INFO0_TID);
+
+ __skb_queue_tail(&msdu_list, msdu);
+
+ if (!rxcb->is_continuation) {
+ total_msdu_reaped++;
+ done = true;
+ } else {
+ done = false;
+ }
+
+ if (total_msdu_reaped >= budget)
+ break;
+ }
+
+ /* Hw might have updated the head pointer after we cached it.
+ * In this case, even though there are entries in the ring we'll
+ * get rx_desc NULL. Give the read another try with updated cached
+ * head pointer so that we can reap complete MPDU in the current
+ * rx processing.
+ */
+ if (!done && ath12k_hal_srng_dst_num_free(ab, srng, true)) {
+ ath12k_hal_srng_access_end(ab, srng);
+ goto try_again;
+ }
+
+ ath12k_hal_srng_access_end(ab, srng);
+
+ spin_unlock_bh(&srng->lock);
+
+ if (!total_msdu_reaped)
+ goto exit;
+
+ for (device_id = 0; device_id < ATH12K_MAX_DEVICES; device_id++) {
+ if (!num_buffs_reaped[device_id])
+ continue;
+
+ partner_dp = ath12k_dp_hw_grp_to_dp(dp_hw_grp, device_id);
+ rx_ring = &partner_dp->rx_refill_buf_ring;
+
+ ath12k_dp_rx_bufs_replenish(partner_dp, rx_ring,
+ &rx_desc_used_list[device_id],
+ num_buffs_reaped[device_id]);
+ }
+
+ ath12k_wifi7_dp_rx_process_received_packets(dp, napi, &msdu_list,
+ ring_id);
+
+exit:
+ return total_msdu_reaped;
+}
+
+static bool
+ath12k_wifi7_dp_rx_h_defrag_validate_incr_pn(struct ath12k_pdev_dp *dp_pdev,
+ struct ath12k_dp_rx_tid *rx_tid,
+ enum hal_encrypt_type encrypt_type)
+{
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct sk_buff *first_frag, *skb;
+ u64 last_pn;
+ u64 cur_pn;
+
+ first_frag = skb_peek(&rx_tid->rx_frags);
+
+ if (encrypt_type != HAL_ENCRYPT_TYPE_CCMP_128 &&
+ encrypt_type != HAL_ENCRYPT_TYPE_CCMP_256 &&
+ encrypt_type != HAL_ENCRYPT_TYPE_GCMP_128 &&
+ encrypt_type != HAL_ENCRYPT_TYPE_AES_GCMP_256)
+ return true;
+
+ last_pn = ath12k_dp_rx_h_get_pn(dp, first_frag);
+ skb_queue_walk(&rx_tid->rx_frags, skb) {
+ if (skb == first_frag)
+ continue;
+
+ cur_pn = ath12k_dp_rx_h_get_pn(dp, skb);
+ if (cur_pn != last_pn + 1)
+ return false;
+ last_pn = cur_pn;
+ }
+ return true;
+}
+
+static int ath12k_wifi7_dp_rx_h_defrag_reo_reinject(struct ath12k_dp *dp,
+ struct ath12k_dp_rx_tid *rx_tid,
+ struct sk_buff *defrag_skb)
+{
+ struct ath12k_base *ab = dp->ab;
+ struct ath12k_hal *hal = dp->hal;
+ struct hal_rx_desc *rx_desc = (struct hal_rx_desc *)defrag_skb->data;
+ struct hal_reo_entrance_ring *reo_ent_ring;
+ struct hal_reo_dest_ring *reo_dest_ring;
+ struct dp_link_desc_bank *link_desc_banks;
+ struct hal_rx_msdu_link *msdu_link;
+ struct hal_rx_msdu_details *msdu0;
+ struct hal_srng *srng;
+ dma_addr_t link_paddr, buf_paddr;
+ u32 desc_bank, msdu_info, msdu_ext_info, mpdu_info;
+ u32 cookie, hal_rx_desc_sz, dest_ring_info0, queue_addr_hi;
+ int ret;
+ struct ath12k_rx_desc_info *desc_info;
+ enum hal_rx_buf_return_buf_manager idle_link_rbm = dp->idle_link_rbm;
+ u8 dst_ind;
+
+ hal_rx_desc_sz = hal->hal_desc_sz;
+ link_desc_banks = dp->link_desc_banks;
+ reo_dest_ring = rx_tid->dst_ring_desc;
+
+ ath12k_wifi7_hal_rx_reo_ent_paddr_get(&reo_dest_ring->buf_addr_info,
+ &link_paddr, &cookie);
+ desc_bank = u32_get_bits(cookie, DP_LINK_DESC_BANK_MASK);
+
+ msdu_link = (struct hal_rx_msdu_link *)(link_desc_banks[desc_bank].vaddr +
+ (link_paddr - link_desc_banks[desc_bank].paddr));
+ msdu0 = &msdu_link->msdu_link[0];
+ msdu_ext_info = le32_to_cpu(msdu0->rx_msdu_ext_info.info0);
+ dst_ind = u32_get_bits(msdu_ext_info, RX_MSDU_EXT_DESC_INFO0_REO_DEST_IND);
+
+ memset(msdu0, 0, sizeof(*msdu0));
+
+ msdu_info = u32_encode_bits(1, RX_MSDU_DESC_INFO0_FIRST_MSDU_IN_MPDU) |
+ u32_encode_bits(1, RX_MSDU_DESC_INFO0_LAST_MSDU_IN_MPDU) |
+ u32_encode_bits(0, RX_MSDU_DESC_INFO0_MSDU_CONTINUATION) |
+ u32_encode_bits(defrag_skb->len - hal_rx_desc_sz,
+ RX_MSDU_DESC_INFO0_MSDU_LENGTH) |
+ u32_encode_bits(1, RX_MSDU_DESC_INFO0_VALID_SA) |
+ u32_encode_bits(1, RX_MSDU_DESC_INFO0_VALID_DA);
+ msdu0->rx_msdu_info.info0 = cpu_to_le32(msdu_info);
+ msdu0->rx_msdu_ext_info.info0 = cpu_to_le32(msdu_ext_info);
+
+ /* change msdu len in hal rx desc */
+ ath12k_dp_rxdesc_set_msdu_len(hal, rx_desc, defrag_skb->len - hal_rx_desc_sz);
+
+ buf_paddr = dma_map_single(dp->dev, defrag_skb->data,
+ defrag_skb->len + skb_tailroom(defrag_skb),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dp->dev, buf_paddr))
+ return -ENOMEM;
+
+ spin_lock_bh(&dp->rx_desc_lock);
+ desc_info = list_first_entry_or_null(&dp->rx_desc_free_list,
+ struct ath12k_rx_desc_info,
+ list);
+ if (!desc_info) {
+ spin_unlock_bh(&dp->rx_desc_lock);
+ ath12k_warn(ab, "failed to find rx desc for reinject\n");
+ ret = -ENOMEM;
+ goto err_unmap_dma;
+ }
+
+ desc_info->skb = defrag_skb;
+ desc_info->in_use = true;
+
+ list_del(&desc_info->list);
+ spin_unlock_bh(&dp->rx_desc_lock);
+
+ ATH12K_SKB_RXCB(defrag_skb)->paddr = buf_paddr;
+
+ ath12k_wifi7_hal_rx_buf_addr_info_set(&msdu0->buf_addr_info, buf_paddr,
+ desc_info->cookie,
+ HAL_RX_BUF_RBM_SW3_BM);
+
+ /* Fill mpdu details into reo entrance ring */
+ srng = &hal->srng_list[dp->reo_reinject_ring.ring_id];
+
+ spin_lock_bh(&srng->lock);
+ ath12k_hal_srng_access_begin(ab, srng);
+
+ reo_ent_ring = ath12k_hal_srng_src_get_next_entry(ab, srng);
+ if (!reo_ent_ring) {
+ ath12k_hal_srng_access_end(ab, srng);
+ spin_unlock_bh(&srng->lock);
+ ret = -ENOSPC;
+ goto err_free_desc;
+ }
+ memset(reo_ent_ring, 0, sizeof(*reo_ent_ring));
+
+ ath12k_wifi7_hal_rx_buf_addr_info_set(&reo_ent_ring->buf_addr_info, link_paddr,
+ cookie, idle_link_rbm);
+
+ mpdu_info = u32_encode_bits(1, RX_MPDU_DESC_INFO0_MSDU_COUNT) |
+ u32_encode_bits(0, RX_MPDU_DESC_INFO0_FRAG_FLAG) |
+ u32_encode_bits(1, RX_MPDU_DESC_INFO0_RAW_MPDU) |
+ u32_encode_bits(1, RX_MPDU_DESC_INFO0_VALID_PN) |
+ u32_encode_bits(rx_tid->tid, RX_MPDU_DESC_INFO0_TID);
+
+ reo_ent_ring->rx_mpdu_info.info0 = cpu_to_le32(mpdu_info);
+ reo_ent_ring->rx_mpdu_info.peer_meta_data =
+ reo_dest_ring->rx_mpdu_info.peer_meta_data;
+
+ if (dp->hw_params->reoq_lut_support) {
+ reo_ent_ring->queue_addr_lo = reo_dest_ring->rx_mpdu_info.peer_meta_data;
+ queue_addr_hi = 0;
+ } else {
+ reo_ent_ring->queue_addr_lo =
+ cpu_to_le32(lower_32_bits(rx_tid->qbuf.paddr_aligned));
+ queue_addr_hi = upper_32_bits(rx_tid->qbuf.paddr_aligned);
+ }
+
+ reo_ent_ring->info0 = le32_encode_bits(queue_addr_hi,
+ HAL_REO_ENTR_RING_INFO0_QUEUE_ADDR_HI) |
+ le32_encode_bits(dst_ind,
+ HAL_REO_ENTR_RING_INFO0_DEST_IND);
+
+ reo_ent_ring->info1 = le32_encode_bits(rx_tid->cur_sn,
+ HAL_REO_ENTR_RING_INFO1_MPDU_SEQ_NUM);
+ dest_ring_info0 = le32_get_bits(reo_dest_ring->info0,
+ HAL_REO_DEST_RING_INFO0_SRC_LINK_ID);
+ reo_ent_ring->info2 =
+ cpu_to_le32(u32_get_bits(dest_ring_info0,
+ HAL_REO_ENTR_RING_INFO2_SRC_LINK_ID));
+
+ ath12k_hal_srng_access_end(ab, srng);
+ spin_unlock_bh(&srng->lock);
+
+ return 0;
+
+err_free_desc:
+ spin_lock_bh(&dp->rx_desc_lock);
+ desc_info->in_use = false;
+ desc_info->skb = NULL;
+ list_add_tail(&desc_info->list, &dp->rx_desc_free_list);
+ spin_unlock_bh(&dp->rx_desc_lock);
+err_unmap_dma:
+ dma_unmap_single(dp->dev, buf_paddr, defrag_skb->len + skb_tailroom(defrag_skb),
+ DMA_TO_DEVICE);
+ return ret;
+}
+
+static int ath12k_wifi7_dp_rx_h_verify_tkip_mic(struct ath12k_pdev_dp *dp_pdev,
+ struct ath12k_dp_peer *peer,
+ enum hal_encrypt_type enctype,
+ struct sk_buff *msdu,
+ struct hal_rx_desc_data *rx_info)
+{
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_hal *hal = dp->hal;
+ struct hal_rx_desc *rx_desc = (struct hal_rx_desc *)msdu->data;
+ struct ieee80211_rx_status *rxs = IEEE80211_SKB_RXCB(msdu);
+ struct ieee80211_key_conf *key_conf;
+ struct ieee80211_hdr *hdr;
+ u8 mic[IEEE80211_CCMP_MIC_LEN];
+ int head_len, tail_len, ret;
+ size_t data_len;
+ u32 hdr_len, hal_rx_desc_sz = hal->hal_desc_sz;
+ u8 *key, *data;
+ u8 key_idx;
+
+ if (enctype != HAL_ENCRYPT_TYPE_TKIP_MIC)
+ return 0;
+
+ rx_info->addr2_present = false;
+ rx_info->rx_status = rxs;
+
+ hdr = (struct ieee80211_hdr *)(msdu->data + hal_rx_desc_sz);
+ hdr_len = ieee80211_hdrlen(hdr->frame_control);
+ head_len = hdr_len + hal_rx_desc_sz + IEEE80211_TKIP_IV_LEN;
+ tail_len = IEEE80211_CCMP_MIC_LEN + IEEE80211_TKIP_ICV_LEN + FCS_LEN;
+
+ if (!is_multicast_ether_addr(hdr->addr1))
+ key_idx = peer->ucast_keyidx;
+ else
+ key_idx = peer->mcast_keyidx;
+
+ key_conf = peer->keys[key_idx];
+
+ data = msdu->data + head_len;
+ data_len = msdu->len - head_len - tail_len;
+ key = &key_conf->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY];
+
+ ret = ath12k_dp_rx_h_michael_mic(peer->tfm_mmic, key, hdr, data,
+ data_len, mic);
+ if (ret || memcmp(mic, data + data_len, IEEE80211_CCMP_MIC_LEN))
+ goto mic_fail;
+
+ return 0;
+
+mic_fail:
+ (ATH12K_SKB_RXCB(msdu))->is_first_msdu = true;
+ (ATH12K_SKB_RXCB(msdu))->is_last_msdu = true;
+
+ ath12k_dp_extract_rx_desc_data(hal, rx_info, rx_desc, rx_desc);
+
+ rxs->flag |= RX_FLAG_MMIC_ERROR | RX_FLAG_MMIC_STRIPPED |
+ RX_FLAG_IV_STRIPPED | RX_FLAG_DECRYPTED;
+ skb_pull(msdu, hal_rx_desc_sz);
+
+ if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(dp, rx_desc, msdu,
+ rx_info)))
+ return -EINVAL;
+
+ ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
+ ath12k_dp_rx_h_undecap(dp_pdev, msdu, rx_desc,
+ HAL_ENCRYPT_TYPE_TKIP_MIC, true, rx_info);
+ ieee80211_rx(ath12k_pdev_dp_to_hw(dp_pdev), msdu);
+ return -EINVAL;
+}
+
+static int ath12k_wifi7_dp_rx_h_defrag(struct ath12k_pdev_dp *dp_pdev,
+ struct ath12k_dp_peer *peer,
+ struct ath12k_dp_rx_tid *rx_tid,
+ struct sk_buff **defrag_skb,
+ enum hal_encrypt_type enctype,
+ struct hal_rx_desc_data *rx_info)
+{
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
+ struct sk_buff *skb, *first_frag, *last_frag;
+ struct ieee80211_hdr *hdr;
+ bool is_decrypted = false;
+ int msdu_len = 0;
+ int extra_space;
+ u32 flags, hal_rx_desc_sz = ab->hal.hal_desc_sz;
+
+ first_frag = skb_peek(&rx_tid->rx_frags);
+ last_frag = skb_peek_tail(&rx_tid->rx_frags);
+
+ skb_queue_walk(&rx_tid->rx_frags, skb) {
+ flags = 0;
+ hdr = (struct ieee80211_hdr *)(skb->data + hal_rx_desc_sz);
+
+ if (enctype != HAL_ENCRYPT_TYPE_OPEN)
+ is_decrypted = rx_info->is_decrypted;
+
+ if (is_decrypted) {
+ if (skb != first_frag)
+ flags |= RX_FLAG_IV_STRIPPED;
+ if (skb != last_frag)
+ flags |= RX_FLAG_ICV_STRIPPED |
+ RX_FLAG_MIC_STRIPPED;
+ }
+
+ /* RX fragments are always raw packets */
+ if (skb != last_frag)
+ skb_trim(skb, skb->len - FCS_LEN);
+ ath12k_dp_rx_h_undecap_frag(dp_pdev, skb, enctype, flags);
+
+ if (skb != first_frag)
+ skb_pull(skb, hal_rx_desc_sz +
+ ieee80211_hdrlen(hdr->frame_control));
+ msdu_len += skb->len;
+ }
+
+ extra_space = msdu_len - (DP_RX_BUFFER_SIZE + skb_tailroom(first_frag));
+ if (extra_space > 0 &&
+ (pskb_expand_head(first_frag, 0, extra_space, GFP_ATOMIC) < 0))
+ return -ENOMEM;
+
+ __skb_unlink(first_frag, &rx_tid->rx_frags);
+ while ((skb = __skb_dequeue(&rx_tid->rx_frags))) {
+ skb_put_data(first_frag, skb->data, skb->len);
+ dev_kfree_skb_any(skb);
+ }
+
+ hdr = (struct ieee80211_hdr *)(first_frag->data + hal_rx_desc_sz);
+ hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_MOREFRAGS);
+ ATH12K_SKB_RXCB(first_frag)->is_frag = 1;
+
+ if (ath12k_wifi7_dp_rx_h_verify_tkip_mic(dp_pdev, peer, enctype, first_frag,
+ rx_info))
+ first_frag = NULL;
+
+ *defrag_skb = first_frag;
+ return 0;
+}
+
+void ath12k_wifi7_dp_rx_frags_cleanup(struct ath12k_dp_rx_tid *rx_tid,
+ bool rel_link_desc)
+{
+ enum hal_wbm_rel_bm_act act = HAL_WBM_REL_BM_ACT_PUT_IN_IDLE;
+ struct ath12k_buffer_addr *buf_addr_info;
+ struct ath12k_dp *dp = rx_tid->dp;
+
+ lockdep_assert_held(&dp->dp_lock);
+
+ if (rx_tid->dst_ring_desc) {
+ if (rel_link_desc) {
+ buf_addr_info = &rx_tid->dst_ring_desc->buf_addr_info;
+ ath12k_wifi7_dp_rx_link_desc_return(dp, buf_addr_info, act);
+ }
+ kfree(rx_tid->dst_ring_desc);
+ rx_tid->dst_ring_desc = NULL;
+ }
+
+ rx_tid->cur_sn = 0;
+ rx_tid->last_frag_no = 0;
+ rx_tid->rx_frag_bitmap = 0;
+ __skb_queue_purge(&rx_tid->rx_frags);
+}
+
+static int ath12k_wifi7_dp_rx_frag_h_mpdu(struct ath12k_pdev_dp *dp_pdev,
+ struct sk_buff *msdu,
+ struct hal_reo_dest_ring *ring_desc,
+ struct hal_rx_desc_data *rx_info)
+{
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_hal *hal = dp->hal;
+ struct ath12k_base *ab = dp->ab;
+ struct ath12k_dp_peer *peer;
+ struct ath12k_dp_rx_tid *rx_tid;
+ struct sk_buff *defrag_skb = NULL;
+ u32 peer_id = rx_info->peer_id;
+ u16 seqno, frag_no;
+ u8 tid = rx_info->tid;
+ int ret = 0;
+ bool more_frags;
+ enum hal_encrypt_type enctype = rx_info->enctype;
+
+ frag_no = ath12k_dp_rx_h_frag_no(hal, msdu);
+ more_frags = ath12k_dp_rx_h_more_frags(hal, msdu);
+ seqno = rx_info->seq_no;
+
+ if (!rx_info->seq_ctl_valid || !rx_info->fc_valid ||
+ tid > IEEE80211_NUM_TIDS)
+ return -EINVAL;
+
+ /* received unfragmented packet in reo
+ * exception ring, this shouldn't happen
+ * as these packets typically come from
+ * reo2sw srngs.
+ */
+ if (WARN_ON_ONCE(!frag_no && !more_frags))
+ return -EINVAL;
+
+ spin_lock_bh(&dp->dp_lock);
+ peer = ath12k_dp_peer_find_by_peerid(dp_pdev, peer_id);
+ if (!peer) {
+ ath12k_warn(ab, "failed to find the peer to de-fragment received fragment peer_id %d\n",
+ peer_id);
+ ret = -ENOENT;
+ goto out_unlock;
+ }
+
+ if (!peer->dp_setup_done) {
+ ath12k_warn(ab, "The peer %pM [%d] has uninitialized datapath\n",
+ peer->addr, peer_id);
+ ret = -ENOENT;
+ goto out_unlock;
+ }
+
+ rx_tid = &peer->rx_tid[tid];
+
+ if ((!skb_queue_empty(&rx_tid->rx_frags) && seqno != rx_tid->cur_sn) ||
+ skb_queue_empty(&rx_tid->rx_frags)) {
+ /* Flush stored fragments and start a new sequence */
+ ath12k_wifi7_dp_rx_frags_cleanup(rx_tid, true);
+ rx_tid->cur_sn = seqno;
+ }
+
+ if (rx_tid->rx_frag_bitmap & BIT(frag_no)) {
+ /* Fragment already present */
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ if ((!rx_tid->rx_frag_bitmap || frag_no > __fls(rx_tid->rx_frag_bitmap)))
+ __skb_queue_tail(&rx_tid->rx_frags, msdu);
+ else
+ ath12k_dp_rx_h_sort_frags(hal, &rx_tid->rx_frags, msdu);
+
+ rx_tid->rx_frag_bitmap |= BIT(frag_no);
+ if (!more_frags)
+ rx_tid->last_frag_no = frag_no;
+
+ if (frag_no == 0) {
+ rx_tid->dst_ring_desc = kmemdup(ring_desc,
+ sizeof(*rx_tid->dst_ring_desc),
+ GFP_ATOMIC);
+ if (!rx_tid->dst_ring_desc) {
+ ret = -ENOMEM;
+ goto out_unlock;
+ }
+ } else {
+ ath12k_wifi7_dp_rx_link_desc_return(dp, &ring_desc->buf_addr_info,
+ HAL_WBM_REL_BM_ACT_PUT_IN_IDLE);
+ }
+
+ if (!rx_tid->last_frag_no ||
+ rx_tid->rx_frag_bitmap != GENMASK(rx_tid->last_frag_no, 0)) {
+ mod_timer(&rx_tid->frag_timer, jiffies +
+ ATH12K_DP_RX_FRAGMENT_TIMEOUT_MS);
+ goto out_unlock;
+ }
+
+ spin_unlock_bh(&dp->dp_lock);
+ timer_delete_sync(&rx_tid->frag_timer);
+ spin_lock_bh(&dp->dp_lock);
+
+ peer = ath12k_dp_peer_find_by_peerid(dp_pdev, peer_id);
+ if (!peer)
+ goto err_frags_cleanup;
+
+ if (!ath12k_wifi7_dp_rx_h_defrag_validate_incr_pn(dp_pdev, rx_tid, enctype))
+ goto err_frags_cleanup;
+
+ if (ath12k_wifi7_dp_rx_h_defrag(dp_pdev, peer, rx_tid, &defrag_skb,
+ enctype, rx_info))
+ goto err_frags_cleanup;
+
+ if (!defrag_skb)
+ goto err_frags_cleanup;
+
+ if (ath12k_wifi7_dp_rx_h_defrag_reo_reinject(dp, rx_tid, defrag_skb))
+ goto err_frags_cleanup;
+
+ ath12k_wifi7_dp_rx_frags_cleanup(rx_tid, false);
+ goto out_unlock;
+
+err_frags_cleanup:
+ dev_kfree_skb_any(defrag_skb);
+ ath12k_wifi7_dp_rx_frags_cleanup(rx_tid, true);
+out_unlock:
+ spin_unlock_bh(&dp->dp_lock);
+ return ret;
+}
+
+static int
+ath12k_wifi7_dp_process_rx_err_buf(struct ath12k_pdev_dp *dp_pdev,
+ struct hal_reo_dest_ring *desc,
+ struct list_head *used_list,
+ bool drop, u32 cookie)
+{
+ struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev);
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_hal *hal = dp->hal;
+ struct sk_buff *msdu;
+ struct ath12k_skb_rxcb *rxcb;
+ struct hal_rx_desc_data rx_info;
+ struct hal_rx_desc *rx_desc;
+ u16 msdu_len;
+ u32 hal_rx_desc_sz = hal->hal_desc_sz;
+ struct ath12k_rx_desc_info *desc_info;
+ u64 desc_va;
+
+ desc_va = ((u64)le32_to_cpu(desc->buf_va_hi) << 32 |
+ le32_to_cpu(desc->buf_va_lo));
+ desc_info = (struct ath12k_rx_desc_info *)((unsigned long)desc_va);
+
+ /* retry manual desc retrieval */
+ if (!desc_info) {
+ desc_info = ath12k_dp_get_rx_desc(dp, cookie);
+ if (!desc_info) {
+ ath12k_warn(dp->ab,
+ "Invalid cookie in DP rx error descriptor retrieval: 0x%x\n",
+ cookie);
+ return -EINVAL;
+ }
+ }
+
+ if (desc_info->magic != ATH12K_DP_RX_DESC_MAGIC)
+ ath12k_warn(dp->ab, "RX Exception, Check HW CC implementation");
+
+ msdu = desc_info->skb;
+ desc_info->skb = NULL;
+
+ list_add_tail(&desc_info->list, used_list);
+
+ rxcb = ATH12K_SKB_RXCB(msdu);
+ dma_unmap_single(dp->dev, rxcb->paddr,
+ msdu->len + skb_tailroom(msdu),
+ DMA_FROM_DEVICE);
+
+ if (drop) {
+ dev_kfree_skb_any(msdu);
+ return 0;
+ }
+
+ rcu_read_lock();
+ if (!rcu_dereference(ar->ab->pdevs_active[ar->pdev_idx])) {
+ dev_kfree_skb_any(msdu);
+ goto exit;
+ }
+
+ if (test_bit(ATH12K_FLAG_CAC_RUNNING, &ar->dev_flags)) {
+ dev_kfree_skb_any(msdu);
+ goto exit;
+ }
+
+ rx_desc = (struct hal_rx_desc *)msdu->data;
+ ath12k_dp_extract_rx_desc_data(hal, &rx_info, rx_desc, rx_desc);
+
+ msdu_len = rx_info.msdu_len;
+ if ((msdu_len + hal_rx_desc_sz) > DP_RX_BUFFER_SIZE) {
+ ath12k_warn(dp->ab, "invalid msdu leng %u", msdu_len);
+ ath12k_dbg_dump(dp->ab, ATH12K_DBG_DATA, NULL, "", rx_desc,
+ sizeof(*rx_desc));
+ dev_kfree_skb_any(msdu);
+ goto exit;
+ }
+
+ skb_put(msdu, hal_rx_desc_sz + msdu_len);
+
+ if (ath12k_wifi7_dp_rx_frag_h_mpdu(dp_pdev, msdu, desc, &rx_info)) {
+ dev_kfree_skb_any(msdu);
+ ath12k_wifi7_dp_rx_link_desc_return(dp, &desc->buf_addr_info,
+ HAL_WBM_REL_BM_ACT_PUT_IN_IDLE);
+ }
+exit:
+ rcu_read_unlock();
+ return 0;
+}
+
+static int ath12k_dp_h_msdu_buffer_type(struct ath12k_dp *dp,
+ struct list_head *list,
+ struct hal_reo_dest_ring *desc)
+{
+ struct ath12k_rx_desc_info *desc_info;
+ struct ath12k_skb_rxcb *rxcb;
+ struct sk_buff *msdu;
+ u64 desc_va;
+
+ dp->device_stats.reo_excep_msdu_buf_type++;
+
+ desc_va = (u64)le32_to_cpu(desc->buf_va_hi) << 32 |
+ le32_to_cpu(desc->buf_va_lo);
+ desc_info = (struct ath12k_rx_desc_info *)(uintptr_t)desc_va;
+ if (!desc_info) {
+ u32 cookie;
+
+ cookie = le32_get_bits(desc->buf_addr_info.info1,
+ BUFFER_ADDR_INFO1_SW_COOKIE);
+ desc_info = ath12k_dp_get_rx_desc(dp, cookie);
+ if (!desc_info) {
+ ath12k_warn(dp->ab, "Invalid cookie in manual descriptor retrieval: 0x%x\n",
+ cookie);
+ return -EINVAL;
+ }
+ }
+
+ if (desc_info->magic != ATH12K_DP_RX_DESC_MAGIC) {
+ ath12k_warn(dp->ab, "rx exception, magic check failed with value: %u\n",
+ desc_info->magic);
+ return -EINVAL;
+ }
+
+ msdu = desc_info->skb;
+ desc_info->skb = NULL;
+ list_add_tail(&desc_info->list, list);
+ rxcb = ATH12K_SKB_RXCB(msdu);
+ dma_unmap_single(dp->dev, rxcb->paddr, msdu->len + skb_tailroom(msdu),
+ DMA_FROM_DEVICE);
+ dev_kfree_skb_any(msdu);
+
+ return 0;
+}
+
+int ath12k_wifi7_dp_rx_process_err(struct ath12k_dp *dp, struct napi_struct *napi,
+ int budget)
+{
+ struct ath12k_base *ab = dp->ab;
+ struct ath12k_hal *hal = dp->hal;
+ struct ath12k_hw_group *ag = dp->ag;
+ struct ath12k_dp_hw_group *dp_hw_grp = &ag->dp_hw_grp;
+ struct ath12k_dp *partner_dp;
+ struct list_head rx_desc_used_list[ATH12K_MAX_DEVICES];
+ u32 msdu_cookies[HAL_NUM_RX_MSDUS_PER_LINK_DESC];
+ int num_buffs_reaped[ATH12K_MAX_DEVICES] = {};
+ struct dp_link_desc_bank *link_desc_banks;
+ enum hal_rx_buf_return_buf_manager rbm;
+ struct hal_rx_msdu_link *link_desc_va;
+ int tot_n_bufs_reaped, quota, ret, i;
+ struct hal_reo_dest_ring *reo_desc;
+ struct dp_rxdma_ring *rx_ring;
+ struct dp_srng *reo_except;
+ struct ath12k_hw_link *hw_links = ag->hw_links;
+ struct ath12k_pdev_dp *dp_pdev;
+ u8 hw_link_id, device_id;
+ u32 desc_bank, num_msdus;
+ struct hal_srng *srng;
+ dma_addr_t paddr;
+ bool is_frag;
+ bool drop;
+ int pdev_idx;
+ struct list_head *used_list;
+ enum hal_wbm_rel_bm_act act;
+
+ tot_n_bufs_reaped = 0;
+ quota = budget;
+
+ for (device_id = 0; device_id < ATH12K_MAX_DEVICES; device_id++)
+ INIT_LIST_HEAD(&rx_desc_used_list[device_id]);
+
+ reo_except = &dp->reo_except_ring;
+
+ srng = &hal->srng_list[reo_except->ring_id];
+
+ spin_lock_bh(&srng->lock);
+
+ ath12k_hal_srng_access_begin(ab, srng);
+
+ while (budget &&
+ (reo_desc = ath12k_hal_srng_dst_get_next_entry(ab, srng))) {
+ drop = false;
+ dp->device_stats.err_ring_pkts++;
+
+ hw_link_id = le32_get_bits(reo_desc->info0,
+ HAL_REO_DEST_RING_INFO0_SRC_LINK_ID);
+ device_id = hw_links[hw_link_id].device_id;
+ partner_dp = ath12k_dp_hw_grp_to_dp(dp_hw_grp, device_id);
+
+ /* Below case is added to handle data packet from un-associated clients.
+ * As it is expected that AST lookup will fail for
+ * un-associated station's data packets.
+ */
+ if (le32_get_bits(reo_desc->info0, HAL_REO_DEST_RING_INFO0_BUFFER_TYPE) ==
+ HAL_REO_DEST_RING_BUFFER_TYPE_MSDU) {
+ if (!ath12k_dp_h_msdu_buffer_type(partner_dp,
+ &rx_desc_used_list[device_id],
+ reo_desc)) {
+ num_buffs_reaped[device_id]++;
+ tot_n_bufs_reaped++;
+ }
+ goto next_desc;
+ }
+
+ ret = ath12k_wifi7_hal_desc_reo_parse_err(dp, reo_desc, &paddr,
+ &desc_bank);
+ if (ret) {
+ ath12k_warn(ab, "failed to parse error reo desc %d\n",
+ ret);
+ continue;
+ }
+
+ pdev_idx = ath12k_hw_mac_id_to_pdev_id(partner_dp->hw_params,
+ hw_links[hw_link_id].pdev_idx);
+
+ link_desc_banks = partner_dp->link_desc_banks;
+ link_desc_va = link_desc_banks[desc_bank].vaddr +
+ (paddr - link_desc_banks[desc_bank].paddr);
+ ath12k_wifi7_hal_rx_msdu_link_info_get(link_desc_va, &num_msdus,
+ msdu_cookies, &rbm);
+ if (rbm != partner_dp->idle_link_rbm &&
+ rbm != HAL_RX_BUF_RBM_SW3_BM &&
+ rbm != partner_dp->hal->hal_params->rx_buf_rbm) {
+ act = HAL_WBM_REL_BM_ACT_REL_MSDU;
+ dp->device_stats.invalid_rbm++;
+ ath12k_warn(ab, "invalid return buffer manager %d\n", rbm);
+ ath12k_wifi7_dp_rx_link_desc_return(partner_dp,
+ &reo_desc->buf_addr_info,
+ act);
+ continue;
+ }
+
+ is_frag = !!(le32_to_cpu(reo_desc->rx_mpdu_info.info0) &
+ RX_MPDU_DESC_INFO0_FRAG_FLAG);
+
+ /* Process only rx fragments with one msdu per link desc below, and drop
+ * msdu's indicated due to error reasons.
+ * Dynamic fragmentation not supported in Multi-link client, so drop the
+ * partner device buffers.
+ */
+ if (!is_frag || num_msdus > 1 ||
+ partner_dp->device_id != dp->device_id) {
+ drop = true;
+ act = HAL_WBM_REL_BM_ACT_PUT_IN_IDLE;
+
+ /* Return the link desc back to wbm idle list */
+ ath12k_wifi7_dp_rx_link_desc_return(partner_dp,
+ &reo_desc->buf_addr_info,
+ act);
+ }
+
+ rcu_read_lock();
+
+ dp_pdev = ath12k_dp_to_pdev_dp(dp, pdev_idx);
+ if (!dp_pdev) {
+ rcu_read_unlock();
+ continue;
+ }
+
+ for (i = 0; i < num_msdus; i++) {
+ used_list = &rx_desc_used_list[device_id];
+
+ if (!ath12k_wifi7_dp_process_rx_err_buf(dp_pdev, reo_desc,
+ used_list,
+ drop,
+ msdu_cookies[i])) {
+ num_buffs_reaped[device_id]++;
+ tot_n_bufs_reaped++;
+ }
+ }
+
+ rcu_read_unlock();
+
+next_desc:
+ if (tot_n_bufs_reaped >= quota) {
+ tot_n_bufs_reaped = quota;
+ goto exit;
+ }
+
+ budget = quota - tot_n_bufs_reaped;
+ }
+
+exit:
+ ath12k_hal_srng_access_end(ab, srng);
+
+ spin_unlock_bh(&srng->lock);
+
+ for (device_id = 0; device_id < ATH12K_MAX_DEVICES; device_id++) {
+ if (!num_buffs_reaped[device_id])
+ continue;
+
+ partner_dp = ath12k_dp_hw_grp_to_dp(dp_hw_grp, device_id);
+ rx_ring = &partner_dp->rx_refill_buf_ring;
+
+ ath12k_dp_rx_bufs_replenish(partner_dp, rx_ring,
+ &rx_desc_used_list[device_id],
+ num_buffs_reaped[device_id]);
+ }
+
+ return tot_n_bufs_reaped;
+}
+
+static void
+ath12k_wifi7_dp_rx_null_q_desc_sg_drop(struct ath12k_dp *dp, int msdu_len,
+ struct sk_buff_head *msdu_list)
+{
+ struct sk_buff *skb, *tmp;
+ struct ath12k_skb_rxcb *rxcb;
+ int n_buffs;
+
+ n_buffs = DIV_ROUND_UP(msdu_len,
+ (DP_RX_BUFFER_SIZE - dp->ab->hal.hal_desc_sz));
+
+ skb_queue_walk_safe(msdu_list, skb, tmp) {
+ rxcb = ATH12K_SKB_RXCB(skb);
+ if (rxcb->err_rel_src == HAL_WBM_REL_SRC_MODULE_REO &&
+ rxcb->err_code == HAL_REO_DEST_RING_ERROR_CODE_DESC_ADDR_ZERO) {
+ if (!n_buffs)
+ break;
+ __skb_unlink(skb, msdu_list);
+ dev_kfree_skb_any(skb);
+ n_buffs--;
+ }
+ }
+}
+
+static int ath12k_wifi7_dp_rx_h_null_q_desc(struct ath12k_pdev_dp *dp_pdev,
+ struct sk_buff *msdu,
+ struct hal_rx_desc_data *rx_info,
+ struct sk_buff_head *msdu_list)
+{
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
+ u16 msdu_len = rx_info->msdu_len;
+ struct hal_rx_desc *desc = (struct hal_rx_desc *)msdu->data;
+ u8 l3pad_bytes = rx_info->l3_pad_bytes;
+ struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
+ u32 hal_rx_desc_sz = dp->ab->hal.hal_desc_sz;
+
+ if (!rxcb->is_frag && ((msdu_len + hal_rx_desc_sz) > DP_RX_BUFFER_SIZE)) {
+ /* First buffer will be freed by the caller, so deduct it's length */
+ msdu_len = msdu_len - (DP_RX_BUFFER_SIZE - hal_rx_desc_sz);
+ ath12k_wifi7_dp_rx_null_q_desc_sg_drop(dp, msdu_len, msdu_list);
+ return -EINVAL;
+ }
+
+ /* Even after cleaning up the sg buffers in the msdu list with above check
+ * any msdu received with continuation flag needs to be dropped as invalid.
+ * This protects against some random err frame with continuation flag.
+ */
+ if (rxcb->is_continuation)
+ return -EINVAL;
+
+ if (!rx_info->msdu_done) {
+ ath12k_warn(ab,
+ "msdu_done bit not set in null_q_des processing\n");
+ __skb_queue_purge(msdu_list);
+ return -EIO;
+ }
+
+ /* Handle NULL queue descriptor violations arising out a missing
+ * REO queue for a given peer or a given TID. This typically
+ * may happen if a packet is received on a QOS enabled TID before the
+ * ADDBA negotiation for that TID, when the TID queue is setup. Or
+ * it may also happen for MC/BC frames if they are not routed to the
+ * non-QOS TID queue, in the absence of any other default TID queue.
+ * This error can show up both in a REO destination or WBM release ring.
+ */
+
+ if (rxcb->is_frag) {
+ skb_pull(msdu, hal_rx_desc_sz);
+ } else {
+ if ((hal_rx_desc_sz + l3pad_bytes + msdu_len) > DP_RX_BUFFER_SIZE)
+ return -EINVAL;
+
+ skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len);
+ skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes);
+ }
+ if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(dp, desc, msdu, rx_info)))
+ return -EINVAL;
+
+ ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
+ ath12k_wifi7_dp_rx_h_mpdu(dp_pdev, msdu, desc, rx_info);
+
+ rxcb->tid = rx_info->tid;
+
+ /* Please note that caller will having the access to msdu and completing
+ * rx with mac80211. Need not worry about cleaning up amsdu_list.
+ */
+
+ return 0;
+}
+
+static bool ath12k_wifi7_dp_rx_h_tkip_mic_err(struct ath12k_pdev_dp *dp_pdev,
+ struct sk_buff *msdu,
+ struct hal_rx_desc_data *rx_info)
+{
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
+ u16 msdu_len = rx_info->msdu_len;
+ struct hal_rx_desc *desc = (struct hal_rx_desc *)msdu->data;
+ u8 l3pad_bytes = rx_info->l3_pad_bytes;
+ struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
+ u32 hal_rx_desc_sz = ab->hal.hal_desc_sz;
+
+ rxcb->is_first_msdu = rx_info->is_first_msdu;
+ rxcb->is_last_msdu = rx_info->is_last_msdu;
+
+ if ((hal_rx_desc_sz + l3pad_bytes + msdu_len) > DP_RX_BUFFER_SIZE) {
+ ath12k_dbg(ab, ATH12K_DBG_DATA,
+ "invalid msdu len in tkip mic err %u\n", msdu_len);
+ ath12k_dbg_dump(ab, ATH12K_DBG_DATA, NULL, "", desc,
+ sizeof(*desc));
+ return true;
+ }
+
+ skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len);
+ skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes);
+
+ if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(dp, desc, msdu, rx_info)))
+ return true;
+
+ ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
+
+ rx_info->rx_status->flag |= (RX_FLAG_MMIC_STRIPPED | RX_FLAG_MMIC_ERROR |
+ RX_FLAG_DECRYPTED);
+
+ ath12k_dp_rx_h_undecap(dp_pdev, msdu, desc,
+ HAL_ENCRYPT_TYPE_TKIP_MIC, false, rx_info);
+ return false;
+}
+
+static bool ath12k_wifi7_dp_rx_h_rxdma_err(struct ath12k_pdev_dp *dp_pdev,
+ struct sk_buff *msdu,
+ struct hal_rx_desc_data *rx_info)
+{
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
+ bool drop = false;
+
+ dp->device_stats.rxdma_error[rxcb->err_code]++;
+
+ switch (rxcb->err_code) {
+ case HAL_REO_ENTR_RING_RXDMA_ECODE_DECRYPT_ERR:
+ case HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR:
+ if (rx_info->err_bitmap & HAL_RX_MPDU_ERR_TKIP_MIC) {
+ drop = ath12k_wifi7_dp_rx_h_tkip_mic_err(dp_pdev, msdu, rx_info);
+ break;
+ }
+ fallthrough;
+ default:
+ /* TODO: Review other rxdma error code to check if anything is
+ * worth reporting to mac80211
+ */
+ drop = true;
+ break;
+ }
+
+ return drop;
+}
+
+static bool ath12k_wifi7_dp_rx_h_reo_err(struct ath12k_pdev_dp *dp_pdev,
+ struct sk_buff *msdu,
+ struct hal_rx_desc_data *rx_info,
+ struct sk_buff_head *msdu_list)
+{
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
+ bool drop = false;
+
+ dp->device_stats.reo_error[rxcb->err_code]++;
+
+ switch (rxcb->err_code) {
+ case HAL_REO_DEST_RING_ERROR_CODE_DESC_ADDR_ZERO:
+ if (ath12k_wifi7_dp_rx_h_null_q_desc(dp_pdev, msdu, rx_info, msdu_list))
+ drop = true;
+ break;
+ case HAL_REO_DEST_RING_ERROR_CODE_PN_CHECK_FAILED:
+ /* TODO: Do not drop PN failed packets in the driver;
+ * instead, it is good to drop such packets in mac80211
+ * after incrementing the replay counters.
+ */
+ fallthrough;
+ default:
+ /* TODO: Review other errors and process them to mac80211
+ * as appropriate.
+ */
+ drop = true;
+ break;
+ }
+
+ return drop;
+}
+
+static void ath12k_wifi7_dp_rx_wbm_err(struct ath12k_pdev_dp *dp_pdev,
+ struct napi_struct *napi,
+ struct sk_buff *msdu,
+ struct sk_buff_head *msdu_list)
+{
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct hal_rx_desc *rx_desc = (struct hal_rx_desc *)msdu->data;
+ struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
+ struct ieee80211_rx_status rxs = {};
+ struct hal_rx_desc_data rx_info;
+ bool drop = true;
+
+ rx_info.addr2_present = false;
+ rx_info.rx_status = &rxs;
+
+ ath12k_dp_extract_rx_desc_data(dp->hal, &rx_info, rx_desc, rx_desc);
+
+ switch (rxcb->err_rel_src) {
+ case HAL_WBM_REL_SRC_MODULE_REO:
+ drop = ath12k_wifi7_dp_rx_h_reo_err(dp_pdev, msdu, &rx_info, msdu_list);
+ break;
+ case HAL_WBM_REL_SRC_MODULE_RXDMA:
+ drop = ath12k_wifi7_dp_rx_h_rxdma_err(dp_pdev, msdu, &rx_info);
+ break;
+ default:
+ /* msdu will get freed */
+ break;
+ }
+
+ if (drop) {
+ dev_kfree_skb_any(msdu);
+ return;
+ }
+
+ rx_info.rx_status->flag |= RX_FLAG_SKIP_MONITOR;
+
+ ath12k_dp_rx_deliver_msdu(dp_pdev, napi, msdu, &rx_info);
+}
+
+void ath12k_wifi7_dp_setup_pn_check_reo_cmd(struct ath12k_hal_reo_cmd *cmd,
+ struct ath12k_dp_rx_tid *rx_tid,
+ u32 cipher, enum set_key_cmd key_cmd)
+{
+ cmd->flag = HAL_REO_CMD_FLG_NEED_STATUS;
+ cmd->upd0 = HAL_REO_CMD_UPD0_PN |
+ HAL_REO_CMD_UPD0_PN_SIZE |
+ HAL_REO_CMD_UPD0_PN_VALID |
+ HAL_REO_CMD_UPD0_PN_CHECK |
+ HAL_REO_CMD_UPD0_SVLD;
+
+ switch (cipher) {
+ case WLAN_CIPHER_SUITE_TKIP:
+ case WLAN_CIPHER_SUITE_CCMP:
+ case WLAN_CIPHER_SUITE_CCMP_256:
+ case WLAN_CIPHER_SUITE_GCMP:
+ case WLAN_CIPHER_SUITE_GCMP_256:
+ if (key_cmd == SET_KEY) {
+ cmd->upd1 |= HAL_REO_CMD_UPD1_PN_CHECK;
+ cmd->pn_size = 48;
+ }
+ break;
+ default:
+ break;
+ }
+
+ cmd->addr_lo = lower_32_bits(rx_tid->qbuf.paddr_aligned);
+ cmd->addr_hi = upper_32_bits(rx_tid->qbuf.paddr_aligned);
+}
+
+int ath12k_wifi7_dp_rx_process_wbm_err(struct ath12k_dp *dp,
+ struct napi_struct *napi, int budget)
+{
+ struct list_head rx_desc_used_list[ATH12K_MAX_DEVICES];
+ struct ath12k_base *ab = dp->ab;
+ struct ath12k_hal *hal = dp->hal;
+ struct ath12k *ar;
+ struct ath12k_pdev_dp *dp_pdev;
+ struct ath12k_hw_group *ag = dp->ag;
+ struct ath12k_dp_hw_group *dp_hw_grp = &ag->dp_hw_grp;
+ struct ath12k_dp *partner_dp;
+ struct dp_rxdma_ring *rx_ring;
+ struct hal_rx_wbm_rel_info err_info;
+ struct hal_srng *srng;
+ struct sk_buff *msdu;
+ struct sk_buff_head msdu_list, scatter_msdu_list;
+ struct ath12k_skb_rxcb *rxcb;
+ void *rx_desc;
+ int num_buffs_reaped[ATH12K_MAX_DEVICES] = {};
+ int total_num_buffs_reaped = 0;
+ struct ath12k_rx_desc_info *desc_info;
+ struct ath12k_device_dp_stats *device_stats = &dp->device_stats;
+ struct ath12k_hw_link *hw_links = ag->hw_links;
+ u8 hw_link_id, device_id;
+ int ret, pdev_idx;
+ struct hal_rx_desc *msdu_data;
+
+ __skb_queue_head_init(&msdu_list);
+ __skb_queue_head_init(&scatter_msdu_list);
+
+ for (device_id = 0; device_id < ATH12K_MAX_DEVICES; device_id++)
+ INIT_LIST_HEAD(&rx_desc_used_list[device_id]);
+
+ srng = &hal->srng_list[dp->rx_rel_ring.ring_id];
+ spin_lock_bh(&srng->lock);
+
+ ath12k_hal_srng_access_begin(ab, srng);
+
+ while (budget) {
+ rx_desc = ath12k_hal_srng_dst_get_next_entry(ab, srng);
+ if (!rx_desc)
+ break;
+
+ ret = ath12k_wifi7_hal_wbm_desc_parse_err(dp, rx_desc,
+ &err_info);
+ if (ret) {
+ ath12k_warn(ab, "failed to parse rx error in wbm_rel ring desc %d\n",
+ ret);
+ continue;
+ }
+
+ desc_info = err_info.rx_desc;
+
+ /* retry manual desc retrieval if hw cc is not done */
+ if (!desc_info) {
+ desc_info = ath12k_dp_get_rx_desc(dp, err_info.cookie);
+ if (!desc_info) {
+ ath12k_warn(ab, "Invalid cookie in DP WBM rx error descriptor retrieval: 0x%x\n",
+ err_info.cookie);
+ continue;
+ }
+ }
+
+ if (desc_info->magic != ATH12K_DP_RX_DESC_MAGIC)
+ ath12k_warn(ab, "WBM RX err, Check HW CC implementation");
+
+ msdu = desc_info->skb;
+ desc_info->skb = NULL;
+
+ device_id = desc_info->device_id;
+ partner_dp = ath12k_dp_hw_grp_to_dp(dp_hw_grp, device_id);
+ if (unlikely(!partner_dp)) {
+ dev_kfree_skb_any(msdu);
+
+ /* In any case continuation bit is set
+ * in the previous record, cleanup scatter_msdu_list
+ */
+ ath12k_dp_clean_up_skb_list(&scatter_msdu_list);
+ continue;
+ }
+
+ list_add_tail(&desc_info->list, &rx_desc_used_list[device_id]);
+
+ rxcb = ATH12K_SKB_RXCB(msdu);
+ dma_unmap_single(partner_dp->dev, rxcb->paddr,
+ msdu->len + skb_tailroom(msdu),
+ DMA_FROM_DEVICE);
+
+ num_buffs_reaped[device_id]++;
+ total_num_buffs_reaped++;
+
+ if (!err_info.continuation)
+ budget--;
+
+ if (err_info.push_reason !=
+ HAL_REO_DEST_RING_PUSH_REASON_ERR_DETECTED) {
+ dev_kfree_skb_any(msdu);
+ continue;
+ }
+
+ msdu_data = (struct hal_rx_desc *)msdu->data;
+ rxcb->err_rel_src = err_info.err_rel_src;
+ rxcb->err_code = err_info.err_code;
+ rxcb->is_first_msdu = err_info.first_msdu;
+ rxcb->is_last_msdu = err_info.last_msdu;
+ rxcb->is_continuation = err_info.continuation;
+ rxcb->rx_desc = msdu_data;
+ rxcb->peer_id = ath12k_wifi7_dp_rx_get_peer_id(dp, dp->peer_metadata_ver,
+ err_info.peer_metadata);
+
+ if (err_info.continuation) {
+ __skb_queue_tail(&scatter_msdu_list, msdu);
+ continue;
+ }
+
+ hw_link_id = ath12k_dp_rx_get_msdu_src_link(partner_dp->hal,
+ msdu_data);
+ if (hw_link_id >= ATH12K_GROUP_MAX_RADIO) {
+ dev_kfree_skb_any(msdu);
+
+ /* In any case continuation bit is set
+ * in the previous record, cleanup scatter_msdu_list
+ */
+ ath12k_dp_clean_up_skb_list(&scatter_msdu_list);
+ continue;
+ }
+
+ if (!skb_queue_empty(&scatter_msdu_list)) {
+ struct sk_buff *msdu;
+
+ skb_queue_walk(&scatter_msdu_list, msdu) {
+ rxcb = ATH12K_SKB_RXCB(msdu);
+ rxcb->hw_link_id = hw_link_id;
+ }
+
+ skb_queue_splice_tail_init(&scatter_msdu_list,
+ &msdu_list);
+ }
+
+ rxcb = ATH12K_SKB_RXCB(msdu);
+ rxcb->hw_link_id = hw_link_id;
+ __skb_queue_tail(&msdu_list, msdu);
+ }
+
+ /* In any case continuation bit is set in the
+ * last record, cleanup scatter_msdu_list
+ */
+ ath12k_dp_clean_up_skb_list(&scatter_msdu_list);
+
+ ath12k_hal_srng_access_end(ab, srng);
+
+ spin_unlock_bh(&srng->lock);
+
+ if (!total_num_buffs_reaped)
+ goto done;
+
+ for (device_id = 0; device_id < ATH12K_MAX_DEVICES; device_id++) {
+ if (!num_buffs_reaped[device_id])
+ continue;
+
+ partner_dp = ath12k_dp_hw_grp_to_dp(dp_hw_grp, device_id);
+ rx_ring = &partner_dp->rx_refill_buf_ring;
+
+ ath12k_dp_rx_bufs_replenish(dp, rx_ring,
+ &rx_desc_used_list[device_id],
+ num_buffs_reaped[device_id]);
+ }
+
+ rcu_read_lock();
+ while ((msdu = __skb_dequeue(&msdu_list))) {
+ rxcb = ATH12K_SKB_RXCB(msdu);
+ hw_link_id = rxcb->hw_link_id;
+
+ device_id = hw_links[hw_link_id].device_id;
+ partner_dp = ath12k_dp_hw_grp_to_dp(dp_hw_grp, device_id);
+ if (unlikely(!partner_dp)) {
+ ath12k_dbg(ab, ATH12K_DBG_DATA,
+ "Unable to process WBM error msdu due to invalid hw link id %d device id %d\n",
+ hw_link_id, device_id);
+ dev_kfree_skb_any(msdu);
+ continue;
+ }
+
+ pdev_idx = ath12k_hw_mac_id_to_pdev_id(partner_dp->hw_params,
+ hw_links[hw_link_id].pdev_idx);
+
+ dp_pdev = ath12k_dp_to_pdev_dp(partner_dp, pdev_idx);
+ if (!dp_pdev) {
+ dev_kfree_skb_any(msdu);
+ continue;
+ }
+ ar = ath12k_pdev_dp_to_ar(dp_pdev);
+
+ if (!ar || !rcu_dereference(ar->ab->pdevs_active[pdev_idx])) {
+ dev_kfree_skb_any(msdu);
+ continue;
+ }
+
+ if (test_bit(ATH12K_FLAG_CAC_RUNNING, &ar->dev_flags)) {
+ dev_kfree_skb_any(msdu);
+ continue;
+ }
+
+ if (rxcb->err_rel_src < HAL_WBM_REL_SRC_MODULE_MAX) {
+ device_id = dp_pdev->dp->device_id;
+ device_stats->rx_wbm_rel_source[rxcb->err_rel_src][device_id]++;
+ }
+
+ ath12k_wifi7_dp_rx_wbm_err(dp_pdev, napi, msdu, &msdu_list);
+ }
+ rcu_read_unlock();
+done:
+ return total_num_buffs_reaped;
+}
+
+int ath12k_dp_rxdma_ring_sel_config_qcn9274(struct ath12k_base *ab)
+{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct htt_rx_ring_tlv_filter tlv_filter = {};
+ u32 ring_id;
+ int ret;
+ u32 hal_rx_desc_sz = ab->hal.hal_desc_sz;
+
+ ring_id = dp->rx_refill_buf_ring.refill_buf_ring.ring_id;
+
+ tlv_filter.rx_filter = HTT_RX_TLV_FLAGS_RXDMA_RING;
+ tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_BAR;
+ tlv_filter.pkt_filter_flags3 = HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_MCAST |
+ HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_UCAST |
+ HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA;
+ tlv_filter.offset_valid = true;
+ tlv_filter.rx_packet_offset = hal_rx_desc_sz;
+
+ tlv_filter.rx_mpdu_start_offset =
+ ath12k_hal_rx_desc_get_mpdu_start_offset_qcn9274();
+ tlv_filter.rx_msdu_end_offset =
+ ath12k_hal_rx_desc_get_msdu_end_offset_qcn9274();
+
+ tlv_filter.rx_mpdu_start_wmask = ath12k_hal_rx_mpdu_start_wmask_get_qcn9274();
+ tlv_filter.rx_msdu_end_wmask = ath12k_hal_rx_msdu_end_wmask_get_qcn9274();
+ ath12k_dbg(ab, ATH12K_DBG_DATA,
+ "Configuring compact tlv masks rx_mpdu_start_wmask 0x%x rx_msdu_end_wmask 0x%x\n",
+ tlv_filter.rx_mpdu_start_wmask, tlv_filter.rx_msdu_end_wmask);
+
+ ret = ath12k_dp_tx_htt_rx_filter_setup(ab, ring_id, 0,
+ HAL_RXDMA_BUF,
+ DP_RXDMA_REFILL_RING_SIZE,
+ &tlv_filter);
+
+ return ret;
+}
+
+int ath12k_dp_rxdma_ring_sel_config_wcn7850(struct ath12k_base *ab)
+{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct htt_rx_ring_tlv_filter tlv_filter = {};
+ u32 ring_id;
+ int ret = 0;
+ u32 hal_rx_desc_sz = ab->hal.hal_desc_sz;
+ int i;
+
+ ring_id = dp->rx_refill_buf_ring.refill_buf_ring.ring_id;
+
+ tlv_filter.rx_filter = HTT_RX_TLV_FLAGS_RXDMA_RING;
+ tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_BAR;
+ tlv_filter.pkt_filter_flags3 = HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_MCAST |
+ HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_UCAST |
+ HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA;
+ tlv_filter.offset_valid = true;
+ tlv_filter.rx_packet_offset = hal_rx_desc_sz;
+
+ tlv_filter.rx_header_offset = offsetof(struct hal_rx_desc_wcn7850, pkt_hdr_tlv);
+
+ tlv_filter.rx_mpdu_start_offset =
+ ath12k_hal_rx_desc_get_mpdu_start_offset_wcn7850();
+ tlv_filter.rx_msdu_end_offset =
+ ath12k_hal_rx_desc_get_msdu_end_offset_wcn7850();
+
+ /* TODO: Selectively subscribe to required qwords within msdu_end
+ * and mpdu_start and setup the mask in below msg
+ * and modify the rx_desc struct
+ */
+
+ for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {
+ ring_id = dp->rx_mac_buf_ring[i].ring_id;
+ ret = ath12k_dp_tx_htt_rx_filter_setup(ab, ring_id, i,
+ HAL_RXDMA_BUF,
+ DP_RXDMA_REFILL_RING_SIZE,
+ &tlv_filter);
+ }
+
+ return ret;
+}
+
+int ath12k_dp_rxdma_ring_sel_config_qcc2072(struct ath12k_base *ab)
+{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct htt_rx_ring_tlv_filter tlv_filter = {};
+ u32 ring_id;
+ int ret = 0;
+ u32 hal_rx_desc_sz = ab->hal.hal_desc_sz;
+ int i;
+
+ ring_id = dp->rx_refill_buf_ring.refill_buf_ring.ring_id;
+
+ tlv_filter.rx_filter = HTT_RX_TLV_FLAGS_RXDMA_RING;
+ tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_BAR;
+ tlv_filter.pkt_filter_flags3 = HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_MCAST |
+ HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_UCAST |
+ HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA;
+ tlv_filter.offset_valid = true;
+ tlv_filter.rx_packet_offset = hal_rx_desc_sz;
+
+ tlv_filter.rx_header_offset = offsetof(struct hal_rx_desc_qcc2072, pkt_hdr_tlv);
+
+ tlv_filter.rx_mpdu_start_offset =
+ ath12k_hal_rx_desc_get_mpdu_start_offset_qcc2072();
+ tlv_filter.rx_msdu_end_offset =
+ ath12k_hal_rx_desc_get_msdu_end_offset_qcc2072();
+
+ /*
+ * TODO: Selectively subscribe to required qwords within msdu_end
+ * and mpdu_start and setup the mask in below msg
+ * and modify the rx_desc struct
+ */
+
+ for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {
+ ring_id = dp->rx_mac_buf_ring[i].ring_id;
+ ret = ath12k_dp_tx_htt_rx_filter_setup(ab, ring_id, i,
+ HAL_RXDMA_BUF,
+ DP_RXDMA_REFILL_RING_SIZE,
+ &tlv_filter);
+ }
+
+ return ret;
+}
+
+void ath12k_wifi7_dp_rx_process_reo_status(struct ath12k_dp *dp)
+{
+ struct ath12k_base *ab = dp->ab;
+ struct ath12k_hal *hal = dp->hal;
+ struct hal_srng *srng;
+ struct ath12k_dp_rx_reo_cmd *cmd, *tmp;
+ bool found = false;
+ u16 tag;
+ struct hal_reo_status reo_status;
+ void *hdr, *desc;
+
+ srng = &hal->srng_list[dp->reo_status_ring.ring_id];
+
+ memset(&reo_status, 0, sizeof(reo_status));
+
+ spin_lock_bh(&srng->lock);
+
+ ath12k_hal_srng_access_begin(ab, srng);
+
+ while ((hdr = ath12k_hal_srng_dst_get_next_entry(ab, srng))) {
+ tag = hal->ops->reo_status_dec_tlv_hdr(hdr, &desc);
+
+ switch (tag) {
+ case HAL_REO_GET_QUEUE_STATS_STATUS:
+ ath12k_wifi7_hal_reo_status_queue_stats(ab, desc,
+ &reo_status);
+ break;
+ case HAL_REO_FLUSH_QUEUE_STATUS:
+ ath12k_wifi7_hal_reo_flush_queue_status(ab, desc,
+ &reo_status);
+ break;
+ case HAL_REO_FLUSH_CACHE_STATUS:
+ ath12k_wifi7_hal_reo_flush_cache_status(ab, desc,
+ &reo_status);
+ break;
+ case HAL_REO_UNBLOCK_CACHE_STATUS:
+ ath12k_wifi7_hal_reo_unblk_cache_status(ab, desc,
+ &reo_status);
+ break;
+ case HAL_REO_FLUSH_TIMEOUT_LIST_STATUS:
+ ath12k_wifi7_hal_reo_flush_timeout_list_status(ab, desc,
+ &reo_status);
+ break;
+ case HAL_REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS:
+ ath12k_wifi7_hal_reo_desc_thresh_reached_status(ab, desc,
+ &reo_status);
+ break;
+ case HAL_REO_UPDATE_RX_REO_QUEUE_STATUS:
+ ath12k_wifi7_hal_reo_update_rx_reo_queue_status(ab, desc,
+ &reo_status);
+ break;
+ default:
+ ath12k_warn(ab, "Unknown reo status type %d\n", tag);
+ continue;
+ }
+
+ spin_lock_bh(&dp->reo_cmd_lock);
+ list_for_each_entry_safe(cmd, tmp, &dp->reo_cmd_list, list) {
+ if (reo_status.uniform_hdr.cmd_num == cmd->cmd_num) {
+ found = true;
+ list_del(&cmd->list);
+ break;
+ }
+ }
+ spin_unlock_bh(&dp->reo_cmd_lock);
+
+ if (found) {
+ cmd->handler(dp, (void *)&cmd->data,
+ reo_status.uniform_hdr.cmd_status);
+ kfree(cmd);
+ }
+
+ found = false;
+ }
+
+ ath12k_hal_srng_access_end(ab, srng);
+
+ spin_unlock_bh(&srng->lock);
+}
+
+bool
+ath12k_wifi7_dp_rxdesc_mpdu_valid(struct ath12k_base *ab,
+ struct hal_rx_desc *rx_desc)
+{
+ u32 tlv_tag;
+
+ tlv_tag = ab->hal.ops->rx_desc_get_mpdu_start_tag(rx_desc);
+
+ return tlv_tag == HAL_RX_MPDU_START;
+}
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h
new file mode 100644
index 000000000000..8aa79faf567f
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+#ifndef ATH12K_DP_RX_WIFI7_H
+#define ATH12K_DP_RX_WIFI7_H
+
+#include "../core.h"
+#include "../dp_rx.h"
+#include "hal_rx_desc.h"
+
+struct ath12k_hal_reo_cmd;
+
+int ath12k_wifi7_dp_rx_process_wbm_err(struct ath12k_dp *dp,
+ struct napi_struct *napi, int budget);
+int ath12k_wifi7_dp_rx_process_err(struct ath12k_dp *dp, struct napi_struct *napi,
+ int budget);
+int ath12k_wifi7_dp_rx_process(struct ath12k_dp *dp, int mac_id,
+ struct napi_struct *napi,
+ int budget);
+void ath12k_wifi7_dp_rx_process_reo_status(struct ath12k_dp *dp);
+int ath12k_dp_rxdma_ring_sel_config_qcn9274(struct ath12k_base *ab);
+int ath12k_dp_rxdma_ring_sel_config_wcn7850(struct ath12k_base *ab);
+int ath12k_dp_rxdma_ring_sel_config_qcc2072(struct ath12k_base *ab);
+void ath12k_wifi7_dp_setup_pn_check_reo_cmd(struct ath12k_hal_reo_cmd *cmd,
+ struct ath12k_dp_rx_tid *rx_tid,
+ u32 cipher, enum set_key_cmd key_cmd);
+int ath12k_wifi7_dp_rx_assign_reoq(struct ath12k_base *ab, struct ath12k_dp_peer *dp_peer,
+ struct ath12k_dp_rx_tid *rx_tid,
+ u16 ssn, enum hal_pn_type pn_type);
+int ath12k_wifi7_dp_rx_link_desc_return(struct ath12k_dp *dp,
+ struct ath12k_buffer_addr *buf_addr_info,
+ enum hal_wbm_rel_bm_act action);
+void ath12k_wifi7_dp_rx_frags_cleanup(struct ath12k_dp_rx_tid *rx_tid,
+ bool rel_link_desc);
+void ath12k_wifi7_peer_rx_tid_qref_setup(struct ath12k_base *ab, u16 peer_id, u16 tid,
+ dma_addr_t paddr);
+void ath12k_wifi7_dp_rx_peer_tid_delete(struct ath12k_base *ab,
+ struct ath12k_dp_link_peer *peer, u8 tid);
+int ath12k_wifi7_dp_reo_cmd_send(struct ath12k_base *ab,
+ struct ath12k_dp_rx_tid_rxq *rx_tid,
+ enum hal_reo_cmd_type type,
+ struct ath12k_hal_reo_cmd *cmd,
+ void (*cb)(struct ath12k_dp *dp, void *ctx,
+ enum hal_reo_cmd_status status));
+int ath12k_wifi7_dp_reo_cache_flush(struct ath12k_base *ab,
+ struct ath12k_dp_rx_tid_rxq *rx_tid);
+int ath12k_wifi7_peer_rx_tid_reo_update(struct ath12k_dp *dp,
+ struct ath12k_dp_link_peer *peer,
+ struct ath12k_dp_rx_tid *rx_tid,
+ u32 ba_win_sz, u16 ssn,
+ bool update_ssn);
+void ath12k_wifi7_peer_rx_tid_qref_reset(struct ath12k_base *ab, u16 peer_id, u16 tid);
+bool
+ath12k_wifi7_dp_rxdesc_mpdu_valid(struct ath12k_base *ab,
+ struct hal_rx_desc *rx_desc);
+int ath12k_wifi7_dp_rx_tid_delete_handler(struct ath12k_base *ab,
+ struct ath12k_dp_rx_tid_rxq *rx_tid);
+#endif
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c
new file mode 100644
index 000000000000..629084aa36d8
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c
@@ -0,0 +1,978 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include "../core.h"
+#include "../debug.h"
+#include "../dp_tx.h"
+#include "../peer.h"
+#include "dp_tx.h"
+#include "hal_desc.h"
+#include "hal.h"
+#include "hal_tx.h"
+
+static void
+ath12k_wifi7_hal_tx_cmd_ext_desc_setup(struct ath12k_base *ab,
+ struct hal_tx_msdu_ext_desc *tcl_ext_cmd,
+ struct hal_tx_info *ti)
+{
+ tcl_ext_cmd->info0 = le32_encode_bits(ti->paddr,
+ HAL_TX_MSDU_EXT_INFO0_BUF_PTR_LO);
+ tcl_ext_cmd->info1 = le32_encode_bits(0x0,
+ HAL_TX_MSDU_EXT_INFO1_BUF_PTR_HI) |
+ le32_encode_bits(ti->data_len,
+ HAL_TX_MSDU_EXT_INFO1_BUF_LEN);
+
+ tcl_ext_cmd->info1 |= le32_encode_bits(1, HAL_TX_MSDU_EXT_INFO1_EXTN_OVERRIDE) |
+ le32_encode_bits(ti->encap_type,
+ HAL_TX_MSDU_EXT_INFO1_ENCAP_TYPE) |
+ le32_encode_bits(ti->encrypt_type,
+ HAL_TX_MSDU_EXT_INFO1_ENCRYPT_TYPE);
+}
+
+#define HTT_META_DATA_ALIGNMENT 0x8
+
+/* Preparing HTT Metadata when utilized with ext MSDU */
+static int ath12k_wifi7_dp_prepare_htt_metadata(struct sk_buff *skb)
+{
+ struct hal_tx_msdu_metadata *desc_ext;
+ u8 htt_desc_size;
+ /* Size rounded of multiple of 8 bytes */
+ u8 htt_desc_size_aligned;
+
+ htt_desc_size = sizeof(struct hal_tx_msdu_metadata);
+ htt_desc_size_aligned = ALIGN(htt_desc_size, HTT_META_DATA_ALIGNMENT);
+
+ desc_ext = ath12k_dp_metadata_align_skb(skb, htt_desc_size_aligned);
+ if (!desc_ext)
+ return -ENOMEM;
+
+ desc_ext->info0 = le32_encode_bits(1, HAL_TX_MSDU_METADATA_INFO0_ENCRYPT_FLAG) |
+ le32_encode_bits(0, HAL_TX_MSDU_METADATA_INFO0_ENCRYPT_TYPE) |
+ le32_encode_bits(1,
+ HAL_TX_MSDU_METADATA_INFO0_HOST_TX_DESC_POOL);
+
+ return 0;
+}
+
+/* TODO: Remove the export once this file is built with wifi7 ko */
+int ath12k_wifi7_dp_tx(struct ath12k_pdev_dp *dp_pdev, struct ath12k_link_vif *arvif,
+ struct sk_buff *skb, bool gsn_valid, int mcbc_gsn,
+ bool is_mcast)
+{
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_hal *hal = dp->hal;
+ struct ath12k_base *ab = dp->ab;
+ struct hal_tx_info ti = {};
+ struct ath12k_tx_desc_info *tx_desc;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb);
+ struct hal_tcl_data_cmd *hal_tcl_desc;
+ struct hal_tx_msdu_ext_desc *msg;
+ struct sk_buff *skb_ext_desc = NULL;
+ struct hal_srng *tcl_ring;
+ struct ieee80211_hdr *hdr = (void *)skb->data;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ath12k_dp_vif *dp_vif = &ahvif->dp_vif;
+ struct ath12k_dp_link_vif *dp_link_vif;
+ struct dp_tx_ring *tx_ring;
+ u8 pool_id;
+ u8 hal_ring_id;
+ int ret;
+ u8 ring_selector, ring_map = 0;
+ bool tcl_ring_retry;
+ bool msdu_ext_desc = false;
+ bool add_htt_metadata = false;
+ u32 iova_mask = dp->hw_params->iova_mask;
+ bool is_diff_encap = false;
+ bool is_null_frame = false;
+
+ if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags))
+ return -ESHUTDOWN;
+
+ if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
+ !ieee80211_is_data(hdr->frame_control))
+ return -EOPNOTSUPP;
+
+ pool_id = skb_get_queue_mapping(skb) & (ATH12K_HW_MAX_QUEUES - 1);
+
+ /* Let the default ring selection be based on current processor
+ * number, where one of the 3 tcl rings are selected based on
+ * the smp_processor_id(). In case that ring
+ * is full/busy, we resort to other available rings.
+ * If all rings are full, we drop the packet.
+ * TODO: Add throttling logic when all rings are full
+ */
+ ring_selector = dp->hw_params->hw_ops->get_ring_selector(skb);
+
+tcl_ring_sel:
+ tcl_ring_retry = false;
+ ti.ring_id = ring_selector % dp->hw_params->max_tx_ring;
+
+ ring_map |= BIT(ti.ring_id);
+ ti.rbm_id = hal->tcl_to_wbm_rbm_map[ti.ring_id].rbm_id;
+
+ tx_ring = &dp->tx_ring[ti.ring_id];
+
+ tx_desc = ath12k_dp_tx_assign_buffer(dp, pool_id);
+ if (!tx_desc)
+ return -ENOMEM;
+
+ dp_link_vif = ath12k_dp_vif_to_dp_link_vif(&ahvif->dp_vif, arvif->link_id);
+
+ ti.bank_id = dp_link_vif->bank_id;
+ ti.meta_data_flags = dp_link_vif->tcl_metadata;
+
+ if (dp_vif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW &&
+ test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags)) {
+ if (skb_cb->flags & ATH12K_SKB_CIPHER_SET) {
+ ti.encrypt_type =
+ ath12k_dp_tx_get_encrypt_type(skb_cb->cipher);
+
+ if (ieee80211_has_protected(hdr->frame_control))
+ skb_put(skb, IEEE80211_CCMP_MIC_LEN);
+ } else {
+ ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN;
+ }
+
+ msdu_ext_desc = true;
+ }
+
+ if (gsn_valid) {
+ /* Reset and Initialize meta_data_flags with Global Sequence
+ * Number (GSN) info.
+ */
+ ti.meta_data_flags =
+ u32_encode_bits(HTT_TCL_META_DATA_TYPE_GLOBAL_SEQ_NUM,
+ HTT_TCL_META_DATA_TYPE) |
+ u32_encode_bits(mcbc_gsn, HTT_TCL_META_DATA_GLOBAL_SEQ_NUM);
+ }
+
+ ti.encap_type = ath12k_dp_tx_get_encap_type(ab, skb);
+ ti.addr_search_flags = dp_link_vif->hal_addr_search_flags;
+ ti.search_type = dp_link_vif->search_type;
+ ti.type = HAL_TCL_DESC_TYPE_BUFFER;
+ ti.pkt_offset = 0;
+ ti.lmac_id = dp_link_vif->lmac_id;
+
+ ti.vdev_id = dp_link_vif->vdev_id;
+ if (gsn_valid)
+ ti.vdev_id += HTT_TX_MLO_MCAST_HOST_REINJECT_BASE_VDEV_ID;
+
+ ti.bss_ast_hash = dp_link_vif->ast_hash;
+ ti.bss_ast_idx = dp_link_vif->ast_idx;
+ ti.dscp_tid_tbl_idx = 0;
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL &&
+ ti.encap_type != HAL_TCL_ENCAP_TYPE_RAW) {
+ ti.flags0 |= u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_IP4_CKSUM_EN) |
+ u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_UDP4_CKSUM_EN) |
+ u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_UDP6_CKSUM_EN) |
+ u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_TCP4_CKSUM_EN) |
+ u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_TCP6_CKSUM_EN);
+ }
+
+ ti.flags1 |= u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO3_TID_OVERWRITE);
+
+ ti.tid = ath12k_dp_tx_get_tid(skb);
+
+ switch (ti.encap_type) {
+ case HAL_TCL_ENCAP_TYPE_NATIVE_WIFI:
+ is_null_frame = ieee80211_is_nullfunc(hdr->frame_control);
+ if (ahvif->vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED) {
+ if (skb->protocol == cpu_to_be16(ETH_P_PAE) || is_null_frame)
+ is_diff_encap = true;
+
+ /* Firmware expects msdu ext descriptor for nwifi/raw packets
+ * received in ETH mode. Without this, observed tx fail for
+ * Multicast packets in ETH mode.
+ */
+ msdu_ext_desc = true;
+ } else {
+ ath12k_dp_tx_encap_nwifi(skb);
+ }
+ break;
+ case HAL_TCL_ENCAP_TYPE_RAW:
+ if (!test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) {
+ ret = -EINVAL;
+ goto fail_remove_tx_buf;
+ }
+ break;
+ case HAL_TCL_ENCAP_TYPE_ETHERNET:
+ /* no need to encap */
+ break;
+ case HAL_TCL_ENCAP_TYPE_802_3:
+ default:
+ /* TODO: Take care of other encap modes as well */
+ ret = -EINVAL;
+ atomic_inc(&dp->device_stats.tx_err.misc_fail);
+ goto fail_remove_tx_buf;
+ }
+
+ if (iova_mask &&
+ (unsigned long)skb->data & iova_mask) {
+ ret = ath12k_dp_tx_align_payload(dp, &skb);
+ if (ret) {
+ ath12k_warn(ab, "failed to align TX buffer %d\n", ret);
+ /* don't bail out, give original buffer
+ * a chance even unaligned.
+ */
+ goto map;
+ }
+
+ /* hdr is pointing to a wrong place after alignment,
+ * so refresh it for later use.
+ */
+ hdr = (void *)skb->data;
+ }
+map:
+ ti.paddr = dma_map_single(dp->dev, skb->data, skb->len, DMA_TO_DEVICE);
+ if (dma_mapping_error(dp->dev, ti.paddr)) {
+ atomic_inc(&dp->device_stats.tx_err.misc_fail);
+ ath12k_warn(ab, "failed to DMA map data Tx buffer\n");
+ ret = -ENOMEM;
+ goto fail_remove_tx_buf;
+ }
+
+ if ((!test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags) &&
+ !(skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP) &&
+ !(skb_cb->flags & ATH12K_SKB_CIPHER_SET) &&
+ ieee80211_has_protected(hdr->frame_control)) ||
+ is_diff_encap) {
+ /* Firmware is not expecting meta data for qos null
+ * nwifi packet received in ETH encap mode.
+ */
+ if (is_null_frame && msdu_ext_desc)
+ goto skip_htt_meta;
+
+ /* Add metadata for sw encrypted vlan group traffic
+ * and EAPOL nwifi packet received in ETH encap mode.
+ */
+ add_htt_metadata = true;
+ msdu_ext_desc = true;
+ ti.meta_data_flags |= HTT_TCL_META_DATA_VALID_HTT;
+skip_htt_meta:
+ ti.flags0 |= u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_TO_FW);
+ ti.encap_type = HAL_TCL_ENCAP_TYPE_RAW;
+ ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN;
+ }
+
+ tx_desc->skb = skb;
+ tx_desc->mac_id = dp_link_vif->pdev_idx;
+ ti.desc_id = tx_desc->desc_id;
+ ti.data_len = skb->len;
+ skb_cb->paddr = ti.paddr;
+
+ if (msdu_ext_desc) {
+ skb_ext_desc = dev_alloc_skb(sizeof(struct hal_tx_msdu_ext_desc));
+ if (!skb_ext_desc) {
+ ret = -ENOMEM;
+ goto fail_unmap_dma;
+ }
+
+ skb_put(skb_ext_desc, sizeof(struct hal_tx_msdu_ext_desc));
+ memset(skb_ext_desc->data, 0, skb_ext_desc->len);
+
+ msg = (struct hal_tx_msdu_ext_desc *)skb_ext_desc->data;
+ ath12k_wifi7_hal_tx_cmd_ext_desc_setup(ab, msg, &ti);
+
+ if (add_htt_metadata) {
+ ret = ath12k_wifi7_dp_prepare_htt_metadata(skb_ext_desc);
+ if (ret < 0) {
+ ath12k_dbg(ab, ATH12K_DBG_DP_TX,
+ "Failed to add HTT meta data, dropping packet\n");
+ goto fail_free_ext_skb;
+ }
+ }
+
+ ti.paddr = dma_map_single(dp->dev, skb_ext_desc->data,
+ skb_ext_desc->len, DMA_TO_DEVICE);
+ ret = dma_mapping_error(dp->dev, ti.paddr);
+ if (ret)
+ goto fail_free_ext_skb;
+
+ ti.data_len = skb_ext_desc->len;
+ ti.type = HAL_TCL_DESC_TYPE_EXT_DESC;
+
+ skb_cb->paddr_ext_desc = ti.paddr;
+ tx_desc->skb_ext_desc = skb_ext_desc;
+ }
+
+ hal_ring_id = tx_ring->tcl_data_ring.ring_id;
+ tcl_ring = &hal->srng_list[hal_ring_id];
+
+ spin_lock_bh(&tcl_ring->lock);
+
+ ath12k_hal_srng_access_begin(ab, tcl_ring);
+
+ hal_tcl_desc = ath12k_hal_srng_src_get_next_entry(ab, tcl_ring);
+ if (!hal_tcl_desc) {
+ /* NOTE: It is highly unlikely we'll be running out of tcl_ring
+ * desc because the desc is directly enqueued onto hw queue.
+ */
+ ath12k_hal_srng_access_end(ab, tcl_ring);
+ dp->device_stats.tx_err.desc_na[ti.ring_id]++;
+ spin_unlock_bh(&tcl_ring->lock);
+ ret = -ENOMEM;
+
+ /* Checking for available tcl descriptors in another ring in
+ * case of failure due to full tcl ring now, is better than
+ * checking this ring earlier for each pkt tx.
+ * Restart ring selection if some rings are not checked yet.
+ */
+ if (ring_map != (BIT(dp->hw_params->max_tx_ring) - 1) &&
+ dp->hw_params->tcl_ring_retry) {
+ tcl_ring_retry = true;
+ ring_selector++;
+ }
+
+ goto fail_unmap_dma_ext;
+ }
+
+ spin_lock_bh(&arvif->link_stats_lock);
+ arvif->link_stats.tx_encap_type[ti.encap_type]++;
+ arvif->link_stats.tx_encrypt_type[ti.encrypt_type]++;
+ arvif->link_stats.tx_desc_type[ti.type]++;
+
+ if (is_mcast)
+ arvif->link_stats.tx_bcast_mcast++;
+ else
+ arvif->link_stats.tx_enqueued++;
+ spin_unlock_bh(&arvif->link_stats_lock);
+
+ dp->device_stats.tx_enqueued[ti.ring_id]++;
+
+ ath12k_wifi7_hal_tx_cmd_desc_setup(ab, hal_tcl_desc, &ti);
+
+ ath12k_hal_srng_access_end(ab, tcl_ring);
+
+ spin_unlock_bh(&tcl_ring->lock);
+
+ ath12k_dbg_dump(ab, ATH12K_DBG_DP_TX, NULL, "dp tx msdu: ",
+ skb->data, skb->len);
+
+ atomic_inc(&dp_pdev->num_tx_pending);
+
+ return 0;
+
+fail_unmap_dma_ext:
+ if (skb_cb->paddr_ext_desc)
+ dma_unmap_single(dp->dev, skb_cb->paddr_ext_desc,
+ skb_ext_desc->len,
+ DMA_TO_DEVICE);
+fail_free_ext_skb:
+ kfree_skb(skb_ext_desc);
+
+fail_unmap_dma:
+ dma_unmap_single(dp->dev, ti.paddr, ti.data_len, DMA_TO_DEVICE);
+
+fail_remove_tx_buf:
+ ath12k_dp_tx_release_txbuf(dp, tx_desc, pool_id);
+
+ spin_lock_bh(&arvif->link_stats_lock);
+ arvif->link_stats.tx_dropped++;
+ spin_unlock_bh(&arvif->link_stats_lock);
+
+ if (tcl_ring_retry)
+ goto tcl_ring_sel;
+
+ return ret;
+}
+
+static void
+ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_dp *dp,
+ struct ath12k_tx_desc_params *desc_params,
+ struct dp_tx_ring *tx_ring,
+ struct ath12k_dp_htt_wbm_tx_status *ts,
+ u16 peer_id)
+{
+ struct ath12k_base *ab = dp->ab;
+ struct ieee80211_tx_info *info;
+ struct ath12k_link_vif *arvif;
+ struct ath12k_skb_cb *skb_cb;
+ struct ieee80211_vif *vif;
+ struct ath12k_vif *ahvif;
+ struct sk_buff *msdu = desc_params->skb;
+ s32 noise_floor;
+ struct ieee80211_tx_status status = {};
+ struct ath12k_dp_link_peer *peer;
+ struct ath12k_pdev_dp *dp_pdev;
+ u8 pdev_id;
+
+ skb_cb = ATH12K_SKB_CB(msdu);
+ info = IEEE80211_SKB_CB(msdu);
+
+ pdev_id = ath12k_hw_mac_id_to_pdev_id(dp->hw_params, desc_params->mac_id);
+
+ rcu_read_lock();
+ dp_pdev = ath12k_dp_to_pdev_dp(dp, pdev_id);
+ if (!dp_pdev) {
+ rcu_read_unlock();
+ return;
+ }
+
+ dp->device_stats.tx_completed[tx_ring->tcl_data_ring_id]++;
+
+ if (atomic_dec_and_test(&dp_pdev->num_tx_pending))
+ wake_up(&dp_pdev->tx_empty_waitq);
+
+ dma_unmap_single(dp->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
+ if (skb_cb->paddr_ext_desc) {
+ dma_unmap_single(dp->dev, skb_cb->paddr_ext_desc,
+ desc_params->skb_ext_desc->len, DMA_TO_DEVICE);
+ dev_kfree_skb_any(desc_params->skb_ext_desc);
+ }
+
+ vif = skb_cb->vif;
+ if (vif) {
+ ahvif = ath12k_vif_to_ahvif(vif);
+ arvif = rcu_dereference(ahvif->link[skb_cb->link_id]);
+ if (arvif) {
+ spin_lock_bh(&arvif->link_stats_lock);
+ arvif->link_stats.tx_completed++;
+ spin_unlock_bh(&arvif->link_stats_lock);
+ }
+ }
+
+ memset(&info->status, 0, sizeof(info->status));
+
+ if (ts->acked) {
+ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
+ info->flags |= IEEE80211_TX_STAT_ACK;
+ info->status.ack_signal = ts->ack_rssi;
+
+ if (!test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,
+ ab->wmi_ab.svc_map)) {
+ struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev);
+
+ spin_lock_bh(&ar->data_lock);
+ noise_floor = ath12k_pdev_get_noise_floor(ar);
+ spin_unlock_bh(&ar->data_lock);
+
+ info->status.ack_signal += noise_floor;
+ }
+
+ info->status.flags = IEEE80211_TX_STATUS_ACK_SIGNAL_VALID;
+ } else {
+ info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
+ }
+ }
+
+ peer = ath12k_dp_link_peer_find_by_peerid(dp_pdev, peer_id);
+ if (!peer || !peer->sta) {
+ ath12k_dbg(ab, ATH12K_DBG_DATA,
+ "dp_tx: failed to find the peer with peer_id %d\n", peer_id);
+ ieee80211_free_txskb(ath12k_pdev_dp_to_hw(dp_pdev), msdu);
+ goto exit;
+ } else {
+ status.sta = peer->sta;
+ }
+
+ status.info = info;
+ status.skb = msdu;
+ ieee80211_tx_status_ext(ath12k_pdev_dp_to_hw(dp_pdev), &status);
+exit:
+ rcu_read_unlock();
+}
+
+static void
+ath12k_dp_tx_process_htt_tx_complete(struct ath12k_dp *dp, void *desc,
+ struct dp_tx_ring *tx_ring,
+ struct ath12k_tx_desc_params *desc_params)
+{
+ struct htt_tx_wbm_completion *status_desc;
+ struct ath12k_dp_htt_wbm_tx_status ts = {};
+ enum hal_wbm_htt_tx_comp_status wbm_status;
+ u16 peer_id;
+
+ status_desc = desc;
+
+ wbm_status = le32_get_bits(status_desc->info0,
+ HTT_TX_WBM_COMP_INFO0_STATUS);
+ dp->device_stats.fw_tx_status[wbm_status]++;
+
+ switch (wbm_status) {
+ case HAL_WBM_REL_HTT_TX_COMP_STATUS_OK:
+ ts.acked = (wbm_status == HAL_WBM_REL_HTT_TX_COMP_STATUS_OK);
+ ts.ack_rssi = le32_get_bits(status_desc->info2,
+ HTT_TX_WBM_COMP_INFO2_ACK_RSSI);
+
+ peer_id = le32_get_bits(((struct hal_wbm_completion_ring_tx *)desc)->
+ info3, HAL_WBM_COMPL_TX_INFO3_PEER_ID);
+
+ ath12k_dp_tx_htt_tx_complete_buf(dp, desc_params, tx_ring, &ts, peer_id);
+ break;
+ case HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP:
+ case HAL_WBM_REL_HTT_TX_COMP_STATUS_TTL:
+ case HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ:
+ case HAL_WBM_REL_HTT_TX_COMP_STATUS_INSPECT:
+ case HAL_WBM_REL_HTT_TX_COMP_STATUS_VDEVID_MISMATCH:
+ ath12k_dp_tx_free_txbuf(dp, tx_ring, desc_params);
+ break;
+ case HAL_WBM_REL_HTT_TX_COMP_STATUS_MEC_NOTIFY:
+ /* This event is to be handled only when the driver decides to
+ * use WDS offload functionality.
+ */
+ break;
+ default:
+ ath12k_warn(dp->ab, "Unknown htt wbm tx status %d\n", wbm_status);
+ break;
+ }
+}
+
+static void ath12k_wifi7_dp_tx_update_txcompl(struct ath12k_pdev_dp *dp_pdev,
+ struct hal_tx_status *ts)
+{
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_dp_link_peer *peer;
+ struct ath12k_link_sta *arsta;
+ struct rate_info txrate = {};
+ struct ieee80211_sta *sta;
+ struct ath12k_sta *ahsta;
+ u16 rate, ru_tones;
+ u8 rate_idx = 0;
+ int ret;
+
+ peer = ath12k_dp_link_peer_find_by_peerid(dp_pdev, ts->peer_id);
+ if (!peer || !peer->sta) {
+ ath12k_dbg(dp->ab, ATH12K_DBG_DP_TX,
+ "failed to find the peer by id %u\n", ts->peer_id);
+ return;
+ }
+
+ spin_lock_bh(&dp->dp_lock);
+
+ sta = peer->sta;
+ ahsta = ath12k_sta_to_ahsta(sta);
+ arsta = &ahsta->deflink;
+
+ spin_unlock_bh(&dp->dp_lock);
+
+ /* This is to prefer choose the real NSS value arsta->last_txrate.nss,
+ * if it is invalid, then choose the NSS value while assoc.
+ */
+ if (peer->last_txrate.nss)
+ txrate.nss = peer->last_txrate.nss;
+ else
+ txrate.nss = arsta->peer_nss;
+
+ switch (ts->pkt_type) {
+ case HAL_TX_RATE_STATS_PKT_TYPE_11A:
+ case HAL_TX_RATE_STATS_PKT_TYPE_11B:
+ ret = ath12k_mac_hw_ratecode_to_legacy_rate(ts->mcs,
+ ts->pkt_type,
+ &rate_idx,
+ &rate);
+ if (ret < 0) {
+ ath12k_warn(dp->ab, "Invalid tx legacy rate %d\n", ret);
+ return;
+ }
+
+ txrate.legacy = rate;
+ break;
+ case HAL_TX_RATE_STATS_PKT_TYPE_11N:
+ if (ts->mcs > ATH12K_HT_MCS_MAX) {
+ ath12k_warn(dp->ab, "Invalid HT mcs index %d\n", ts->mcs);
+ return;
+ }
+
+ if (txrate.nss != 0)
+ txrate.mcs = ts->mcs + 8 * (txrate.nss - 1);
+
+ txrate.flags = RATE_INFO_FLAGS_MCS;
+
+ if (ts->sgi)
+ txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+ break;
+ case HAL_TX_RATE_STATS_PKT_TYPE_11AC:
+ if (ts->mcs > ATH12K_VHT_MCS_MAX) {
+ ath12k_warn(dp->ab, "Invalid VHT mcs index %d\n", ts->mcs);
+ return;
+ }
+
+ txrate.mcs = ts->mcs;
+ txrate.flags = RATE_INFO_FLAGS_VHT_MCS;
+
+ if (ts->sgi)
+ txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+ break;
+ case HAL_TX_RATE_STATS_PKT_TYPE_11AX:
+ if (ts->mcs > ATH12K_HE_MCS_MAX) {
+ ath12k_warn(dp->ab, "Invalid HE mcs index %d\n", ts->mcs);
+ return;
+ }
+
+ txrate.mcs = ts->mcs;
+ txrate.flags = RATE_INFO_FLAGS_HE_MCS;
+ txrate.he_gi = ath12k_he_gi_to_nl80211_he_gi(ts->sgi);
+ break;
+ case HAL_TX_RATE_STATS_PKT_TYPE_11BE:
+ if (ts->mcs > ATH12K_EHT_MCS_MAX) {
+ ath12k_warn(dp->ab, "Invalid EHT mcs index %d\n", ts->mcs);
+ return;
+ }
+
+ txrate.mcs = ts->mcs;
+ txrate.flags = RATE_INFO_FLAGS_EHT_MCS;
+ txrate.eht_gi = ath12k_mac_eht_gi_to_nl80211_eht_gi(ts->sgi);
+ break;
+ default:
+ ath12k_warn(dp->ab, "Invalid tx pkt type: %d\n", ts->pkt_type);
+ return;
+ }
+
+ txrate.bw = ath12k_mac_bw_to_mac80211_bw(ts->bw);
+
+ if (ts->ofdma && ts->pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11AX) {
+ txrate.bw = RATE_INFO_BW_HE_RU;
+ ru_tones = ath12k_mac_he_convert_tones_to_ru_tones(ts->tones);
+ txrate.he_ru_alloc =
+ ath12k_he_ru_tones_to_nl80211_he_ru_alloc(ru_tones);
+ }
+
+ if (ts->ofdma && ts->pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11BE) {
+ txrate.bw = RATE_INFO_BW_EHT_RU;
+ txrate.eht_ru_alloc =
+ ath12k_mac_eht_ru_tones_to_nl80211_eht_ru_alloc(ts->tones);
+ }
+
+ spin_lock_bh(&dp->dp_lock);
+ peer->txrate = txrate;
+ spin_unlock_bh(&dp->dp_lock);
+}
+
+static void ath12k_wifi7_dp_tx_complete_msdu(struct ath12k_pdev_dp *dp_pdev,
+ struct ath12k_tx_desc_params *desc_params,
+ struct hal_tx_status *ts,
+ int ring)
+{
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
+ struct ieee80211_tx_info *info;
+ struct ath12k_link_vif *arvif;
+ struct ath12k_skb_cb *skb_cb;
+ struct ieee80211_vif *vif;
+ struct ath12k_vif *ahvif;
+ struct sk_buff *msdu = desc_params->skb;
+ s32 noise_floor;
+ struct ieee80211_tx_status status = {};
+ struct ieee80211_rate_status status_rate = {};
+ struct ath12k_dp_link_peer *peer;
+ struct rate_info rate;
+
+ if (WARN_ON_ONCE(ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM)) {
+ /* Must not happen */
+ return;
+ }
+
+ skb_cb = ATH12K_SKB_CB(msdu);
+ dp->device_stats.tx_completed[ring]++;
+
+ dma_unmap_single(dp->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
+ if (skb_cb->paddr_ext_desc) {
+ dma_unmap_single(dp->dev, skb_cb->paddr_ext_desc,
+ desc_params->skb_ext_desc->len, DMA_TO_DEVICE);
+ dev_kfree_skb_any(desc_params->skb_ext_desc);
+ }
+
+ rcu_read_lock();
+
+ if (!rcu_dereference(ab->pdevs_active[dp_pdev->mac_id])) {
+ ieee80211_free_txskb(ath12k_pdev_dp_to_hw(dp_pdev), msdu);
+ goto exit;
+ }
+
+ if (!skb_cb->vif) {
+ ieee80211_free_txskb(ath12k_pdev_dp_to_hw(dp_pdev), msdu);
+ goto exit;
+ }
+
+ vif = skb_cb->vif;
+ if (vif) {
+ ahvif = ath12k_vif_to_ahvif(vif);
+ arvif = rcu_dereference(ahvif->link[skb_cb->link_id]);
+ if (arvif) {
+ spin_lock_bh(&arvif->link_stats_lock);
+ arvif->link_stats.tx_completed++;
+ spin_unlock_bh(&arvif->link_stats_lock);
+ }
+ }
+
+ info = IEEE80211_SKB_CB(msdu);
+ memset(&info->status, 0, sizeof(info->status));
+
+ /* skip tx rate update from ieee80211_status*/
+ info->status.rates[0].idx = -1;
+
+ switch (ts->status) {
+ case HAL_WBM_TQM_REL_REASON_FRAME_ACKED:
+ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
+ info->flags |= IEEE80211_TX_STAT_ACK;
+ info->status.ack_signal = ts->ack_rssi;
+
+ if (!test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,
+ ab->wmi_ab.svc_map)) {
+ struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev);
+
+ spin_lock_bh(&ar->data_lock);
+ noise_floor = ath12k_pdev_get_noise_floor(ar);
+ spin_unlock_bh(&ar->data_lock);
+
+ info->status.ack_signal += noise_floor;
+ }
+
+ info->status.flags = IEEE80211_TX_STATUS_ACK_SIGNAL_VALID;
+ }
+ break;
+ case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_TX:
+ if (info->flags & IEEE80211_TX_CTL_NO_ACK) {
+ info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
+ break;
+ }
+ fallthrough;
+ case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_MPDU:
+ case HAL_WBM_TQM_REL_REASON_DROP_THRESHOLD:
+ case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_AGED_FRAMES:
+ /* The failure status is due to internal firmware tx failure
+ * hence drop the frame; do not update the status of frame to
+ * the upper layer
+ */
+ ieee80211_free_txskb(ath12k_pdev_dp_to_hw(dp_pdev), msdu);
+ goto exit;
+ default:
+ ath12k_dbg(ab, ATH12K_DBG_DP_TX, "tx frame is not acked status %d\n",
+ ts->status);
+ break;
+ }
+
+ /* NOTE: Tx rate status reporting. Tx completion status does not have
+ * necessary information (for example nss) to build the tx rate.
+ * Might end up reporting it out-of-band from HTT stats.
+ */
+
+ ath12k_wifi7_dp_tx_update_txcompl(dp_pdev, ts);
+
+ peer = ath12k_dp_link_peer_find_by_peerid(dp_pdev, ts->peer_id);
+ if (!peer || !peer->sta) {
+ ath12k_err(ab,
+ "dp_tx: failed to find the peer with peer_id %d\n",
+ ts->peer_id);
+ ieee80211_free_txskb(ath12k_pdev_dp_to_hw(dp_pdev), msdu);
+ goto exit;
+ }
+
+ status.sta = peer->sta;
+ status.info = info;
+ status.skb = msdu;
+ rate = peer->last_txrate;
+
+ status_rate.rate_idx = rate;
+ status_rate.try_count = 1;
+
+ status.rates = &status_rate;
+ status.n_rates = 1;
+ ieee80211_tx_status_ext(ath12k_pdev_dp_to_hw(dp_pdev), &status);
+
+exit:
+ rcu_read_unlock();
+}
+
+static void
+ath12k_wifi7_dp_tx_status_parse(struct ath12k_dp *dp,
+ struct hal_wbm_completion_ring_tx *desc,
+ struct hal_tx_status *ts)
+{
+ u32 info0 = le32_to_cpu(desc->rate_stats.info0);
+
+ ts->buf_rel_source =
+ le32_get_bits(desc->info0, HAL_WBM_COMPL_TX_INFO0_REL_SRC_MODULE);
+ if (ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_FW &&
+ ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM)
+ return;
+
+ if (ts->buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW)
+ return;
+
+ ts->status = le32_get_bits(desc->info0,
+ HAL_WBM_COMPL_TX_INFO0_TQM_RELEASE_REASON);
+
+ ts->ppdu_id = le32_get_bits(desc->info1,
+ HAL_WBM_COMPL_TX_INFO1_TQM_STATUS_NUMBER);
+
+ ts->peer_id = le32_get_bits(desc->info3, HAL_WBM_COMPL_TX_INFO3_PEER_ID);
+
+ ts->ack_rssi = le32_get_bits(desc->info2,
+ HAL_WBM_COMPL_TX_INFO2_ACK_FRAME_RSSI);
+
+ if (info0 & HAL_TX_RATE_STATS_INFO0_VALID) {
+ ts->pkt_type = u32_get_bits(info0, HAL_TX_RATE_STATS_INFO0_PKT_TYPE);
+ ts->mcs = u32_get_bits(info0, HAL_TX_RATE_STATS_INFO0_MCS);
+ ts->sgi = u32_get_bits(info0, HAL_TX_RATE_STATS_INFO0_SGI);
+ ts->bw = u32_get_bits(info0, HAL_TX_RATE_STATS_INFO0_BW);
+ ts->tones = u32_get_bits(info0, HAL_TX_RATE_STATS_INFO0_TONES_IN_RU);
+ ts->ofdma = u32_get_bits(info0, HAL_TX_RATE_STATS_INFO0_OFDMA_TX);
+ }
+}
+
+void ath12k_wifi7_dp_tx_completion_handler(struct ath12k_dp *dp, int ring_id)
+{
+ struct ath12k_base *ab = dp->ab;
+ struct ath12k_pdev_dp *dp_pdev;
+ int hal_ring_id = dp->tx_ring[ring_id].tcl_comp_ring.ring_id;
+ struct hal_srng *status_ring = &dp->hal->srng_list[hal_ring_id];
+ struct ath12k_tx_desc_info *tx_desc = NULL;
+ struct hal_tx_status ts = {};
+ struct ath12k_tx_desc_params desc_params;
+ struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id];
+ struct hal_wbm_release_ring *desc;
+ u8 pdev_idx;
+ u64 desc_va;
+ enum hal_wbm_rel_src_module buf_rel_source;
+ enum hal_wbm_tqm_rel_reason rel_status;
+
+ spin_lock_bh(&status_ring->lock);
+
+ ath12k_hal_srng_access_begin(ab, status_ring);
+
+ while (ATH12K_TX_COMPL_NEXT(ab, tx_ring->tx_status_head) !=
+ tx_ring->tx_status_tail) {
+ desc = ath12k_hal_srng_dst_get_next_entry(ab, status_ring);
+ if (!desc)
+ break;
+
+ memcpy(&tx_ring->tx_status[tx_ring->tx_status_head],
+ desc, sizeof(*desc));
+ tx_ring->tx_status_head =
+ ATH12K_TX_COMPL_NEXT(ab, tx_ring->tx_status_head);
+ }
+
+ if (ath12k_hal_srng_dst_peek(ab, status_ring) &&
+ (ATH12K_TX_COMPL_NEXT(ab, tx_ring->tx_status_head) ==
+ tx_ring->tx_status_tail)) {
+ /* TODO: Process pending tx_status messages when kfifo_is_full() */
+ ath12k_warn(ab, "Unable to process some of the tx_status ring desc because status_fifo is full\n");
+ }
+
+ ath12k_hal_srng_access_end(ab, status_ring);
+
+ spin_unlock_bh(&status_ring->lock);
+
+ while (ATH12K_TX_COMPL_NEXT(ab, tx_ring->tx_status_tail) !=
+ tx_ring->tx_status_head) {
+ struct hal_wbm_completion_ring_tx *tx_status;
+ u32 desc_id;
+
+ tx_ring->tx_status_tail =
+ ATH12K_TX_COMPL_NEXT(ab, tx_ring->tx_status_tail);
+ tx_status = &tx_ring->tx_status[tx_ring->tx_status_tail];
+ ath12k_wifi7_dp_tx_status_parse(dp, tx_status, &ts);
+
+ if (le32_get_bits(tx_status->info0, HAL_WBM_COMPL_TX_INFO0_CC_DONE)) {
+ /* HW done cookie conversion */
+ desc_va = ((u64)le32_to_cpu(tx_status->buf_va_hi) << 32 |
+ le32_to_cpu(tx_status->buf_va_lo));
+ tx_desc = (struct ath12k_tx_desc_info *)((unsigned long)desc_va);
+ } else {
+ /* SW does cookie conversion to VA */
+ desc_id = le32_get_bits(tx_status->buf_va_hi,
+ BUFFER_ADDR_INFO1_SW_COOKIE);
+
+ tx_desc = ath12k_dp_get_tx_desc(dp, desc_id);
+ }
+ if (!tx_desc) {
+ ath12k_warn(ab, "unable to retrieve tx_desc!");
+ continue;
+ }
+
+ desc_params.mac_id = tx_desc->mac_id;
+ desc_params.skb = tx_desc->skb;
+ desc_params.skb_ext_desc = tx_desc->skb_ext_desc;
+
+ /* Find the HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE value */
+ buf_rel_source = le32_get_bits(tx_status->info0,
+ HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE);
+ dp->device_stats.tx_wbm_rel_source[buf_rel_source]++;
+
+ rel_status = le32_get_bits(tx_status->info0,
+ HAL_WBM_COMPL_TX_INFO0_TQM_RELEASE_REASON);
+ dp->device_stats.tqm_rel_reason[rel_status]++;
+
+ /* Release descriptor as soon as extracting necessary info
+ * to reduce contention
+ */
+ ath12k_dp_tx_release_txbuf(dp, tx_desc, tx_desc->pool_id);
+ if (ts.buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW) {
+ ath12k_dp_tx_process_htt_tx_complete(dp, (void *)tx_status,
+ tx_ring, &desc_params);
+ continue;
+ }
+
+ pdev_idx = ath12k_hw_mac_id_to_pdev_id(dp->hw_params, desc_params.mac_id);
+
+ rcu_read_lock();
+
+ dp_pdev = ath12k_dp_to_pdev_dp(dp, pdev_idx);
+ if (!dp_pdev) {
+ rcu_read_unlock();
+ continue;
+ }
+
+ if (atomic_dec_and_test(&dp_pdev->num_tx_pending))
+ wake_up(&dp_pdev->tx_empty_waitq);
+
+ ath12k_wifi7_dp_tx_complete_msdu(dp_pdev, &desc_params, &ts,
+ tx_ring->tcl_data_ring_id);
+ rcu_read_unlock();
+ }
+}
+
+u32 ath12k_wifi7_dp_tx_get_vdev_bank_config(struct ath12k_base *ab,
+ struct ath12k_link_vif *arvif)
+{
+ u32 bank_config = 0;
+ u8 link_id = arvif->link_id;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ath12k_dp_vif *dp_vif = &ahvif->dp_vif;
+ struct ath12k_dp_link_vif *dp_link_vif;
+
+ dp_link_vif = ath12k_dp_vif_to_dp_link_vif(dp_vif, link_id);
+
+ /* Only valid for raw frames with HW crypto enabled.
+ * With SW crypto, mac80211 sets key per packet
+ */
+ if (dp_vif->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(dp_vif->key_cipher),
+ HAL_TX_BANK_CONFIG_ENCRYPT_TYPE);
+
+ bank_config |= u32_encode_bits(dp_vif->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) |
+ u32_encode_bits(0, HAL_TX_BANK_CONFIG_EPD);
+
+ /* only valid if idx_lookup_override is not set in tcl_data_cmd */
+ if (ahvif->vdev_type == WMI_VDEV_TYPE_STA)
+ bank_config |= u32_encode_bits(1, HAL_TX_BANK_CONFIG_INDEX_LOOKUP_EN);
+ else
+ bank_config |= u32_encode_bits(0, HAL_TX_BANK_CONFIG_INDEX_LOOKUP_EN);
+
+ bank_config |= u32_encode_bits(dp_link_vif->hal_addr_search_flags &
+ HAL_TX_ADDRX_EN,
+ HAL_TX_BANK_CONFIG_ADDRX_EN) |
+ u32_encode_bits(!!(dp_link_vif->hal_addr_search_flags &
+ HAL_TX_ADDRY_EN),
+ HAL_TX_BANK_CONFIG_ADDRY_EN);
+
+ bank_config |= u32_encode_bits(ieee80211_vif_is_mesh(ahvif->vif) ? 3 : 0,
+ HAL_TX_BANK_CONFIG_MESH_EN) |
+ u32_encode_bits(dp_link_vif->vdev_id_check_en,
+ HAL_TX_BANK_CONFIG_VDEV_ID_CHECK_EN);
+
+ bank_config |= u32_encode_bits(0, HAL_TX_BANK_CONFIG_DSCP_TIP_MAP_ID);
+
+ return bank_config;
+}
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.h b/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.h
new file mode 100644
index 000000000000..24cf7972d41b
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef ATH12K_DP_TX_WIFI7_H
+#define ATH12K_DP_TX_WIFI7_H
+
+int ath12k_wifi7_dp_tx(struct ath12k_pdev_dp *dp_pdev, struct ath12k_link_vif *arvif,
+ struct sk_buff *skb, bool gsn_valid, int mcbc_gsn,
+ bool is_mcast);
+void ath12k_wifi7_dp_tx_completion_handler(struct ath12k_dp *dp, int ring_id);
+u32 ath12k_wifi7_dp_tx_get_vdev_bank_config(struct ath12k_base *ab,
+ struct ath12k_link_vif *arvif);
+#endif
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal.c b/drivers/net/wireless/ath/ath12k/wifi7/hal.c
new file mode 100644
index 000000000000..bd1753ca0db6
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal.c
@@ -0,0 +1,713 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+#include "hw.h"
+#include "hal_desc.h"
+#include "../hal.h"
+#include "hal.h"
+#include "hal_tx.h"
+#include "../debug.h"
+#include "../hif.h"
+#include "hal_qcn9274.h"
+#include "hal_wcn7850.h"
+#include "hal_qcc2072.h"
+
+static const struct ath12k_hw_version_map ath12k_wifi7_hw_ver_map[] = {
+ [ATH12K_HW_QCN9274_HW10] = {
+ .hal_ops = &hal_qcn9274_ops,
+ .hal_desc_sz = sizeof(struct hal_rx_desc_qcn9274_compact),
+ .tcl_to_wbm_rbm_map = ath12k_hal_tcl_to_wbm_rbm_map_qcn9274,
+ .hal_params = &ath12k_hw_hal_params_qcn9274,
+ .hw_regs = &qcn9274_v1_regs,
+ },
+ [ATH12K_HW_QCN9274_HW20] = {
+ .hal_ops = &hal_qcn9274_ops,
+ .hal_desc_sz = sizeof(struct hal_rx_desc_qcn9274_compact),
+ .tcl_to_wbm_rbm_map = ath12k_hal_tcl_to_wbm_rbm_map_qcn9274,
+ .hal_params = &ath12k_hw_hal_params_qcn9274,
+ .hw_regs = &qcn9274_v2_regs,
+ },
+ [ATH12K_HW_WCN7850_HW20] = {
+ .hal_ops = &hal_wcn7850_ops,
+ .hal_desc_sz = sizeof(struct hal_rx_desc_wcn7850),
+ .tcl_to_wbm_rbm_map = ath12k_hal_tcl_to_wbm_rbm_map_wcn7850,
+ .hal_params = &ath12k_hw_hal_params_wcn7850,
+ .hw_regs = &wcn7850_regs,
+ },
+ [ATH12K_HW_IPQ5332_HW10] = {
+ .hal_ops = &hal_qcn9274_ops,
+ .hal_desc_sz = sizeof(struct hal_rx_desc_qcn9274_compact),
+ .tcl_to_wbm_rbm_map = ath12k_hal_tcl_to_wbm_rbm_map_qcn9274,
+ .hal_params = &ath12k_hw_hal_params_ipq5332,
+ .hw_regs = &ipq5332_regs,
+ },
+ [ATH12K_HW_QCC2072_HW10] = {
+ .hal_ops = &hal_qcc2072_ops,
+ .hal_desc_sz = sizeof(struct hal_rx_desc_qcc2072),
+ .tcl_to_wbm_rbm_map = ath12k_hal_tcl_to_wbm_rbm_map_wcn7850,
+ .hal_params = &ath12k_hw_hal_params_wcn7850,
+ .hw_regs = &qcc2072_regs,
+ },
+};
+
+int ath12k_wifi7_hal_init(struct ath12k_base *ab)
+{
+ struct ath12k_hal *hal = &ab->hal;
+
+ memset(hal, 0, sizeof(*hal));
+
+ hal->ops = ath12k_wifi7_hw_ver_map[ab->hw_rev].hal_ops;
+ hal->hal_desc_sz = ath12k_wifi7_hw_ver_map[ab->hw_rev].hal_desc_sz;
+ hal->tcl_to_wbm_rbm_map = ath12k_wifi7_hw_ver_map[ab->hw_rev].tcl_to_wbm_rbm_map;
+ hal->regs = ath12k_wifi7_hw_ver_map[ab->hw_rev].hw_regs;
+ hal->hal_params = ath12k_wifi7_hw_ver_map[ab->hw_rev].hal_params;
+ hal->hal_wbm_release_ring_tx_size = sizeof(struct hal_wbm_release_ring_tx);
+
+ return 0;
+}
+
+static unsigned int ath12k_wifi7_hal_reo1_ring_id_offset(struct ath12k_hal *hal)
+{
+ return HAL_REO1_RING_ID(hal) - HAL_REO1_RING_BASE_LSB(hal);
+}
+
+static unsigned
+int ath12k_wifi7_hal_reo1_ring_msi1_base_lsb_offset(struct ath12k_hal *hal)
+{
+ return HAL_REO1_RING_MSI1_BASE_LSB(hal) - HAL_REO1_RING_BASE_LSB(hal);
+}
+
+static unsigned
+int ath12k_wifi7_hal_reo1_ring_msi1_base_msb_offset(struct ath12k_hal *hal)
+{
+ return HAL_REO1_RING_MSI1_BASE_MSB(hal) - HAL_REO1_RING_BASE_LSB(hal);
+}
+
+static unsigned int ath12k_wifi7_hal_reo1_ring_msi1_data_offset(struct ath12k_hal *hal)
+{
+ return HAL_REO1_RING_MSI1_DATA(hal) - HAL_REO1_RING_BASE_LSB(hal);
+}
+
+static unsigned int ath12k_wifi7_hal_reo1_ring_base_msb_offset(struct ath12k_hal *hal)
+{
+ return HAL_REO1_RING_BASE_MSB(hal) - HAL_REO1_RING_BASE_LSB(hal);
+}
+
+static unsigned
+int ath12k_wifi7_hal_reo1_ring_producer_int_setup_offset(struct ath12k_hal *hal)
+{
+ return HAL_REO1_RING_PRODUCER_INT_SETUP(hal) - HAL_REO1_RING_BASE_LSB(hal);
+}
+
+static unsigned int ath12k_wifi7_hal_reo1_ring_hp_addr_lsb_offset(struct ath12k_hal *hal)
+{
+ return HAL_REO1_RING_HP_ADDR_LSB(hal) - HAL_REO1_RING_BASE_LSB(hal);
+}
+
+static unsigned int ath12k_wifi7_hal_reo1_ring_hp_addr_msb_offset(struct ath12k_hal *hal)
+{
+ return HAL_REO1_RING_HP_ADDR_MSB(hal) - HAL_REO1_RING_BASE_LSB(hal);
+}
+
+static unsigned int ath12k_wifi7_hal_reo1_ring_misc_offset(struct ath12k_hal *hal)
+{
+ return HAL_REO1_RING_MISC(hal) - HAL_REO1_RING_BASE_LSB(hal);
+}
+
+void ath12k_wifi7_hal_ce_dst_setup(struct ath12k_base *ab,
+ struct hal_srng *srng, int ring_num)
+{
+ struct hal_srng_config *srng_config = &ab->hal.srng_config[HAL_CE_DST];
+ u32 addr;
+ u32 val;
+
+ addr = HAL_CE_DST_RING_CTRL +
+ srng_config->reg_start[HAL_SRNG_REG_GRP_R0] +
+ ring_num * srng_config->reg_size[HAL_SRNG_REG_GRP_R0];
+
+ val = ath12k_hif_read32(ab, addr);
+ val &= ~HAL_CE_DST_R0_DEST_CTRL_MAX_LEN;
+ val |= u32_encode_bits(srng->u.dst_ring.max_buffer_length,
+ HAL_CE_DST_R0_DEST_CTRL_MAX_LEN);
+ ath12k_hif_write32(ab, addr, val);
+}
+
+void ath12k_wifi7_hal_srng_dst_hw_init(struct ath12k_base *ab,
+ struct hal_srng *srng)
+{
+ struct ath12k_hal *hal = &ab->hal;
+ u32 val;
+ u64 hp_addr;
+ u32 reg_base;
+
+ reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0];
+
+ if (srng->flags & HAL_SRNG_FLAGS_MSI_INTR) {
+ ath12k_hif_write32(ab, reg_base +
+ ath12k_wifi7_hal_reo1_ring_msi1_base_lsb_offset(hal),
+ srng->msi_addr);
+
+ val = u32_encode_bits(((u64)srng->msi_addr >> HAL_ADDR_MSB_REG_SHIFT),
+ HAL_REO1_RING_MSI1_BASE_MSB_ADDR) |
+ HAL_REO1_RING_MSI1_BASE_MSB_MSI1_ENABLE;
+ ath12k_hif_write32(ab, reg_base +
+ ath12k_wifi7_hal_reo1_ring_msi1_base_msb_offset(hal),
+ val);
+
+ ath12k_hif_write32(ab,
+ reg_base +
+ ath12k_wifi7_hal_reo1_ring_msi1_data_offset(hal),
+ srng->msi_data);
+ }
+
+ ath12k_hif_write32(ab, reg_base, srng->ring_base_paddr);
+
+ val = u32_encode_bits(((u64)srng->ring_base_paddr >> HAL_ADDR_MSB_REG_SHIFT),
+ HAL_REO1_RING_BASE_MSB_RING_BASE_ADDR_MSB) |
+ u32_encode_bits((srng->entry_size * srng->num_entries),
+ HAL_REO1_RING_BASE_MSB_RING_SIZE);
+ ath12k_hif_write32(ab, reg_base + ath12k_wifi7_hal_reo1_ring_base_msb_offset(hal),
+ val);
+
+ val = u32_encode_bits(srng->ring_id, HAL_REO1_RING_ID_RING_ID) |
+ u32_encode_bits(srng->entry_size, HAL_REO1_RING_ID_ENTRY_SIZE);
+ ath12k_hif_write32(ab, reg_base + ath12k_wifi7_hal_reo1_ring_id_offset(hal), val);
+
+ /* interrupt setup */
+ val = u32_encode_bits((srng->intr_timer_thres_us >> 3),
+ HAL_REO1_RING_PRDR_INT_SETUP_INTR_TMR_THOLD);
+
+ val |= u32_encode_bits((srng->intr_batch_cntr_thres_entries * srng->entry_size),
+ HAL_REO1_RING_PRDR_INT_SETUP_BATCH_COUNTER_THOLD);
+
+ ath12k_hif_write32(ab,
+ reg_base +
+ ath12k_wifi7_hal_reo1_ring_producer_int_setup_offset(hal),
+ val);
+
+ hp_addr = hal->rdp.paddr +
+ ((unsigned long)srng->u.dst_ring.hp_addr -
+ (unsigned long)hal->rdp.vaddr);
+ ath12k_hif_write32(ab, reg_base +
+ ath12k_wifi7_hal_reo1_ring_hp_addr_lsb_offset(hal),
+ hp_addr & HAL_ADDR_LSB_REG_MASK);
+ ath12k_hif_write32(ab, reg_base +
+ ath12k_wifi7_hal_reo1_ring_hp_addr_msb_offset(hal),
+ hp_addr >> HAL_ADDR_MSB_REG_SHIFT);
+
+ /* Initialize head and tail pointers to indicate ring is empty */
+ reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R2];
+ ath12k_hif_write32(ab, reg_base, 0);
+ ath12k_hif_write32(ab, reg_base + HAL_REO1_RING_TP_OFFSET, 0);
+ *srng->u.dst_ring.hp_addr = 0;
+
+ reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0];
+ val = 0;
+ if (srng->flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP)
+ val |= HAL_REO1_RING_MISC_DATA_TLV_SWAP;
+ if (srng->flags & HAL_SRNG_FLAGS_RING_PTR_SWAP)
+ val |= HAL_REO1_RING_MISC_HOST_FW_SWAP;
+ if (srng->flags & HAL_SRNG_FLAGS_MSI_SWAP)
+ val |= HAL_REO1_RING_MISC_MSI_SWAP;
+ val |= HAL_REO1_RING_MISC_SRNG_ENABLE;
+
+ ath12k_hif_write32(ab, reg_base + ath12k_wifi7_hal_reo1_ring_misc_offset(hal),
+ val);
+}
+
+void ath12k_wifi7_hal_srng_src_hw_init(struct ath12k_base *ab,
+ struct hal_srng *srng)
+{
+ struct ath12k_hal *hal = &ab->hal;
+ u32 val;
+ u64 tp_addr;
+ u32 reg_base;
+
+ reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0];
+
+ if (srng->flags & HAL_SRNG_FLAGS_MSI_INTR) {
+ ath12k_hif_write32(ab, reg_base +
+ HAL_TCL1_RING_MSI1_BASE_LSB_OFFSET(hal),
+ srng->msi_addr);
+
+ val = u32_encode_bits(((u64)srng->msi_addr >> HAL_ADDR_MSB_REG_SHIFT),
+ HAL_TCL1_RING_MSI1_BASE_MSB_ADDR) |
+ HAL_TCL1_RING_MSI1_BASE_MSB_MSI1_ENABLE;
+ ath12k_hif_write32(ab, reg_base +
+ HAL_TCL1_RING_MSI1_BASE_MSB_OFFSET(hal),
+ val);
+
+ ath12k_hif_write32(ab, reg_base +
+ HAL_TCL1_RING_MSI1_DATA_OFFSET(hal),
+ srng->msi_data);
+ }
+
+ ath12k_hif_write32(ab, reg_base, srng->ring_base_paddr);
+
+ val = u32_encode_bits(((u64)srng->ring_base_paddr >> HAL_ADDR_MSB_REG_SHIFT),
+ HAL_TCL1_RING_BASE_MSB_RING_BASE_ADDR_MSB) |
+ u32_encode_bits((srng->entry_size * srng->num_entries),
+ HAL_TCL1_RING_BASE_MSB_RING_SIZE);
+ ath12k_hif_write32(ab, reg_base + HAL_TCL1_RING_BASE_MSB_OFFSET(hal), val);
+
+ val = u32_encode_bits(srng->entry_size, HAL_REO1_RING_ID_ENTRY_SIZE);
+ ath12k_hif_write32(ab, reg_base + HAL_TCL1_RING_ID_OFFSET(hal), val);
+
+ val = u32_encode_bits(srng->intr_timer_thres_us,
+ HAL_TCL1_RING_CONSR_INT_SETUP_IX0_INTR_TMR_THOLD);
+
+ val |= u32_encode_bits((srng->intr_batch_cntr_thres_entries * srng->entry_size),
+ HAL_TCL1_RING_CONSR_INT_SETUP_IX0_BATCH_COUNTER_THOLD);
+
+ ath12k_hif_write32(ab,
+ reg_base + HAL_TCL1_RING_CONSR_INT_SETUP_IX0_OFFSET(hal),
+ val);
+
+ val = 0;
+ if (srng->flags & HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN) {
+ val |= u32_encode_bits(srng->u.src_ring.low_threshold,
+ HAL_TCL1_RING_CONSR_INT_SETUP_IX1_LOW_THOLD);
+ }
+ ath12k_hif_write32(ab,
+ reg_base + HAL_TCL1_RING_CONSR_INT_SETUP_IX1_OFFSET(hal),
+ val);
+
+ if (srng->ring_id != HAL_SRNG_RING_ID_WBM_IDLE_LINK) {
+ tp_addr = hal->rdp.paddr +
+ ((unsigned long)srng->u.src_ring.tp_addr -
+ (unsigned long)hal->rdp.vaddr);
+ ath12k_hif_write32(ab,
+ reg_base + HAL_TCL1_RING_TP_ADDR_LSB_OFFSET(hal),
+ tp_addr & HAL_ADDR_LSB_REG_MASK);
+ ath12k_hif_write32(ab,
+ reg_base + HAL_TCL1_RING_TP_ADDR_MSB_OFFSET(hal),
+ tp_addr >> HAL_ADDR_MSB_REG_SHIFT);
+ }
+
+ /* Initialize head and tail pointers to indicate ring is empty */
+ reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R2];
+ ath12k_hif_write32(ab, reg_base, 0);
+ ath12k_hif_write32(ab, reg_base + HAL_TCL1_RING_TP_OFFSET, 0);
+ *srng->u.src_ring.tp_addr = 0;
+
+ reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0];
+ val = 0;
+ if (srng->flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP)
+ val |= HAL_TCL1_RING_MISC_DATA_TLV_SWAP;
+ if (srng->flags & HAL_SRNG_FLAGS_RING_PTR_SWAP)
+ val |= HAL_TCL1_RING_MISC_HOST_FW_SWAP;
+ if (srng->flags & HAL_SRNG_FLAGS_MSI_SWAP)
+ val |= HAL_TCL1_RING_MISC_MSI_SWAP;
+
+ /* Loop count is not used for SRC rings */
+ val |= HAL_TCL1_RING_MISC_MSI_LOOPCNT_DISABLE;
+
+ val |= HAL_TCL1_RING_MISC_SRNG_ENABLE;
+
+ if (srng->ring_id == HAL_SRNG_RING_ID_WBM_IDLE_LINK)
+ val |= HAL_TCL1_RING_MISC_MSI_RING_ID_DISABLE;
+
+ ath12k_hif_write32(ab, reg_base + HAL_TCL1_RING_MISC_OFFSET(hal), val);
+}
+
+void ath12k_wifi7_hal_set_umac_srng_ptr_addr(struct ath12k_base *ab,
+ struct hal_srng *srng)
+{
+ u32 reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R2];
+
+ if (srng->ring_dir == HAL_SRNG_DIR_SRC) {
+ if (!ab->hw_params->supports_shadow_regs) {
+ srng->u.src_ring.hp_addr =
+ (u32 *)((unsigned long)ab->mem + reg_base);
+ } else {
+ ath12k_dbg(ab, ATH12K_DBG_HAL,
+ "hal reg_base 0x%x shadow 0x%lx\n",
+ reg_base,
+ (unsigned long)srng->u.src_ring.hp_addr -
+ (unsigned long)ab->mem);
+ }
+ } else {
+ if (!ab->hw_params->supports_shadow_regs) {
+ srng->u.dst_ring.tp_addr =
+ (u32 *)((unsigned long)ab->mem + reg_base +
+ (HAL_REO1_RING_TP - HAL_REO1_RING_HP));
+ } else {
+ ath12k_dbg(ab, ATH12K_DBG_HAL,
+ "target_reg 0x%x shadow 0x%lx\n",
+ reg_base + HAL_REO1_RING_TP - HAL_REO1_RING_HP,
+ (unsigned long)srng->u.dst_ring.tp_addr -
+ (unsigned long)ab->mem);
+ }
+ }
+}
+
+int ath12k_wifi7_hal_srng_get_ring_id(struct ath12k_hal *hal,
+ enum hal_ring_type type,
+ int ring_num, int mac_id)
+{
+ struct hal_srng_config *srng_config = &hal->srng_config[type];
+ int ring_id;
+
+ if (ring_num >= srng_config->max_rings) {
+ ath12k_warn(hal, "invalid ring number :%d\n", ring_num);
+ return -EINVAL;
+ }
+
+ ring_id = srng_config->start_ring_id + ring_num;
+ if (srng_config->mac_type == ATH12K_HAL_SRNG_PMAC)
+ ring_id += mac_id * HAL_SRNG_RINGS_PER_PMAC;
+
+ if (WARN_ON(ring_id >= HAL_SRNG_RING_ID_MAX))
+ return -EINVAL;
+
+ return ring_id;
+}
+
+static
+void ath12k_wifi7_hal_srng_update_hp_tp_addr(struct ath12k_base *ab,
+ int shadow_cfg_idx,
+ enum hal_ring_type ring_type,
+ int ring_num)
+{
+ struct hal_srng *srng;
+ struct ath12k_hal *hal = &ab->hal;
+ int ring_id;
+ struct hal_srng_config *srng_config = &hal->srng_config[ring_type];
+
+ ring_id = ath12k_wifi7_hal_srng_get_ring_id(hal, ring_type, ring_num,
+ 0);
+ if (ring_id < 0)
+ return;
+
+ srng = &hal->srng_list[ring_id];
+
+ if (srng_config->ring_dir == HAL_SRNG_DIR_DST)
+ srng->u.dst_ring.tp_addr = (u32 *)(HAL_SHADOW_REG(shadow_cfg_idx) +
+ (unsigned long)ab->mem);
+ else
+ srng->u.src_ring.hp_addr = (u32 *)(HAL_SHADOW_REG(shadow_cfg_idx) +
+ (unsigned long)ab->mem);
+}
+
+u32 ath12k_wifi7_hal_ce_get_desc_size(enum hal_ce_desc type)
+{
+ switch (type) {
+ case HAL_CE_DESC_SRC:
+ return sizeof(struct hal_ce_srng_src_desc);
+ case HAL_CE_DESC_DST:
+ return sizeof(struct hal_ce_srng_dest_desc);
+ case HAL_CE_DESC_DST_STATUS:
+ return sizeof(struct hal_ce_srng_dst_status_desc);
+ }
+
+ return 0;
+}
+
+int ath12k_wifi7_hal_srng_update_shadow_config(struct ath12k_base *ab,
+ enum hal_ring_type ring_type,
+ int ring_num)
+{
+ struct ath12k_hal *hal = &ab->hal;
+ struct hal_srng_config *srng_config = &hal->srng_config[ring_type];
+ int shadow_cfg_idx = hal->num_shadow_reg_configured;
+ u32 target_reg;
+
+ if (shadow_cfg_idx >= HAL_SHADOW_NUM_REGS_MAX)
+ return -EINVAL;
+
+ hal->num_shadow_reg_configured++;
+
+ target_reg = srng_config->reg_start[HAL_HP_OFFSET_IN_REG_START];
+ target_reg += srng_config->reg_size[HAL_HP_OFFSET_IN_REG_START] *
+ ring_num;
+
+ /* For destination ring, shadow the TP */
+ if (srng_config->ring_dir == HAL_SRNG_DIR_DST)
+ target_reg += HAL_OFFSET_FROM_HP_TO_TP;
+
+ hal->shadow_reg_addr[shadow_cfg_idx] = target_reg;
+
+ /* update hp/tp addr to hal structure*/
+ ath12k_wifi7_hal_srng_update_hp_tp_addr(ab, shadow_cfg_idx, ring_type,
+ ring_num);
+
+ ath12k_dbg(ab, ATH12K_DBG_HAL,
+ "target_reg %x, shadow reg 0x%x shadow_idx 0x%x, ring_type %d, ring num %d",
+ target_reg,
+ HAL_SHADOW_REG(shadow_cfg_idx),
+ shadow_cfg_idx,
+ ring_type, ring_num);
+
+ return 0;
+}
+
+void ath12k_wifi7_hal_ce_src_set_desc(struct hal_ce_srng_src_desc *desc,
+ dma_addr_t paddr,
+ u32 len, u32 id, u8 byte_swap_data)
+{
+ desc->buffer_addr_low = cpu_to_le32(paddr & HAL_ADDR_LSB_REG_MASK);
+ desc->buffer_addr_info =
+ le32_encode_bits(((u64)paddr >> HAL_ADDR_MSB_REG_SHIFT),
+ HAL_CE_SRC_DESC_ADDR_INFO_ADDR_HI) |
+ le32_encode_bits(byte_swap_data,
+ HAL_CE_SRC_DESC_ADDR_INFO_BYTE_SWAP) |
+ le32_encode_bits(0, HAL_CE_SRC_DESC_ADDR_INFO_GATHER) |
+ le32_encode_bits(len, HAL_CE_SRC_DESC_ADDR_INFO_LEN);
+ desc->meta_info = le32_encode_bits(id, HAL_CE_SRC_DESC_META_INFO_DATA);
+}
+
+void ath12k_wifi7_hal_ce_dst_set_desc(struct hal_ce_srng_dest_desc *desc,
+ dma_addr_t paddr)
+{
+ desc->buffer_addr_low = cpu_to_le32(paddr & HAL_ADDR_LSB_REG_MASK);
+ desc->buffer_addr_info =
+ le32_encode_bits(((u64)paddr >> HAL_ADDR_MSB_REG_SHIFT),
+ HAL_CE_DEST_DESC_ADDR_INFO_ADDR_HI);
+}
+
+void ath12k_wifi7_hal_set_link_desc_addr(struct hal_wbm_link_desc *desc,
+ u32 cookie, dma_addr_t paddr,
+ enum hal_rx_buf_return_buf_manager rbm)
+{
+ desc->buf_addr_info.info0 = le32_encode_bits((paddr & HAL_ADDR_LSB_REG_MASK),
+ BUFFER_ADDR_INFO0_ADDR);
+ desc->buf_addr_info.info1 =
+ le32_encode_bits(((u64)paddr >> HAL_ADDR_MSB_REG_SHIFT),
+ BUFFER_ADDR_INFO1_ADDR) |
+ le32_encode_bits(rbm, BUFFER_ADDR_INFO1_RET_BUF_MGR) |
+ le32_encode_bits(cookie, BUFFER_ADDR_INFO1_SW_COOKIE);
+}
+
+u32 ath12k_wifi7_hal_ce_dst_status_get_length(struct hal_ce_srng_dst_status_desc *desc)
+{
+ u32 len;
+
+ len = le32_get_bits(READ_ONCE(desc->flags), HAL_CE_DST_STATUS_DESC_FLAGS_LEN);
+ desc->flags &= ~cpu_to_le32(HAL_CE_DST_STATUS_DESC_FLAGS_LEN);
+
+ return len;
+}
+
+void
+ath12k_wifi7_hal_setup_link_idle_list(struct ath12k_base *ab,
+ struct hal_wbm_idle_scatter_list *sbuf,
+ u32 nsbufs, u32 tot_link_desc,
+ u32 end_offset)
+{
+ struct ath12k_hal *hal = &ab->hal;
+ struct ath12k_buffer_addr *link_addr;
+ int i;
+ u32 reg_scatter_buf_sz = HAL_WBM_IDLE_SCATTER_BUF_SIZE / 64;
+ u32 val;
+
+ link_addr = (void *)sbuf[0].vaddr + HAL_WBM_IDLE_SCATTER_BUF_SIZE;
+
+ for (i = 1; i < nsbufs; i++) {
+ link_addr->info0 = cpu_to_le32(sbuf[i].paddr & HAL_ADDR_LSB_REG_MASK);
+
+ link_addr->info1 =
+ le32_encode_bits((u64)sbuf[i].paddr >> HAL_ADDR_MSB_REG_SHIFT,
+ HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32) |
+ le32_encode_bits(BASE_ADDR_MATCH_TAG_VAL,
+ HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_MATCH_TAG);
+
+ link_addr = (void *)sbuf[i].vaddr +
+ HAL_WBM_IDLE_SCATTER_BUF_SIZE;
+ }
+
+ val = u32_encode_bits(reg_scatter_buf_sz, HAL_WBM_SCATTER_BUFFER_SIZE) |
+ u32_encode_bits(0x1, HAL_WBM_LINK_DESC_IDLE_LIST_MODE);
+
+ ath12k_hif_write32(ab,
+ HAL_SEQ_WCSS_UMAC_WBM_REG +
+ HAL_WBM_R0_IDLE_LIST_CONTROL_ADDR(hal),
+ val);
+
+ val = u32_encode_bits(reg_scatter_buf_sz * nsbufs,
+ HAL_WBM_SCATTER_RING_SIZE_OF_IDLE_LINK_DESC_LIST);
+ ath12k_hif_write32(ab,
+ HAL_SEQ_WCSS_UMAC_WBM_REG +
+ HAL_WBM_R0_IDLE_LIST_SIZE_ADDR(hal),
+ val);
+
+ val = u32_encode_bits(sbuf[0].paddr & HAL_ADDR_LSB_REG_MASK,
+ BUFFER_ADDR_INFO0_ADDR);
+ ath12k_hif_write32(ab,
+ HAL_SEQ_WCSS_UMAC_WBM_REG +
+ HAL_WBM_SCATTERED_RING_BASE_LSB(hal),
+ val);
+
+ val = u32_encode_bits(BASE_ADDR_MATCH_TAG_VAL,
+ HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_MATCH_TAG) |
+ u32_encode_bits((u64)sbuf[0].paddr >> HAL_ADDR_MSB_REG_SHIFT,
+ HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32);
+ ath12k_hif_write32(ab,
+ HAL_SEQ_WCSS_UMAC_WBM_REG +
+ HAL_WBM_SCATTERED_RING_BASE_MSB(hal),
+ val);
+
+ /* Setup head and tail pointers for the idle list */
+ val = u32_encode_bits(sbuf[nsbufs - 1].paddr, BUFFER_ADDR_INFO0_ADDR);
+ ath12k_hif_write32(ab,
+ HAL_SEQ_WCSS_UMAC_WBM_REG +
+ HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX0(hal),
+ val);
+
+ val = u32_encode_bits(((u64)sbuf[nsbufs - 1].paddr >> HAL_ADDR_MSB_REG_SHIFT),
+ HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32) |
+ u32_encode_bits((end_offset >> 2),
+ HAL_WBM_SCATTERED_DESC_HEAD_P_OFFSET_IX1);
+ ath12k_hif_write32(ab,
+ HAL_SEQ_WCSS_UMAC_WBM_REG +
+ HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX1(hal),
+ val);
+
+ val = u32_encode_bits(sbuf[0].paddr, BUFFER_ADDR_INFO0_ADDR);
+ ath12k_hif_write32(ab,
+ HAL_SEQ_WCSS_UMAC_WBM_REG +
+ HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX0(hal),
+ val);
+
+ val = u32_encode_bits(sbuf[0].paddr, BUFFER_ADDR_INFO0_ADDR);
+ ath12k_hif_write32(ab,
+ HAL_SEQ_WCSS_UMAC_WBM_REG +
+ HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX0(hal),
+ val);
+
+ val = u32_encode_bits(((u64)sbuf[0].paddr >> HAL_ADDR_MSB_REG_SHIFT),
+ HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32) |
+ u32_encode_bits(0, HAL_WBM_SCATTERED_DESC_TAIL_P_OFFSET_IX1);
+ ath12k_hif_write32(ab,
+ HAL_SEQ_WCSS_UMAC_WBM_REG +
+ HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX1(hal),
+ val);
+
+ val = 2 * tot_link_desc;
+ ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_WBM_REG +
+ HAL_WBM_SCATTERED_DESC_PTR_HP_ADDR(hal),
+ val);
+
+ /* Enable the SRNG */
+ val = u32_encode_bits(1, HAL_WBM_IDLE_LINK_RING_MISC_SRNG_ENABLE) |
+ u32_encode_bits(1, HAL_WBM_IDLE_LINK_RING_MISC_RIND_ID_DISABLE);
+ ath12k_hif_write32(ab,
+ HAL_SEQ_WCSS_UMAC_WBM_REG +
+ HAL_WBM_IDLE_LINK_RING_MISC_ADDR(hal),
+ val);
+}
+
+void ath12k_wifi7_hal_tx_configure_bank_register(struct ath12k_base *ab,
+ u32 bank_config,
+ u8 bank_id)
+{
+ ath12k_hif_write32(ab, HAL_TCL_SW_CONFIG_BANK_ADDR + 4 * bank_id,
+ bank_config);
+}
+
+void ath12k_wifi7_hal_reoq_lut_addr_read_enable(struct ath12k_base *ab)
+{
+ struct ath12k_hal *hal = &ab->hal;
+
+ u32 val = ath12k_hif_read32(ab, HAL_SEQ_WCSS_UMAC_REO_REG +
+ HAL_REO1_QDESC_ADDR(hal));
+
+ ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_ADDR(hal),
+ val | HAL_REO_QDESC_ADDR_READ_LUT_ENABLE);
+}
+
+void ath12k_wifi7_hal_reoq_lut_set_max_peerid(struct ath12k_base *ab)
+{
+ struct ath12k_hal *hal = &ab->hal;
+
+ ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_MAX_PEERID(hal),
+ HAL_REO_QDESC_MAX_PEERID);
+}
+
+void ath12k_wifi7_hal_write_reoq_lut_addr(struct ath12k_base *ab,
+ dma_addr_t paddr)
+{
+ ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG +
+ HAL_REO1_QDESC_LUT_BASE0(&ab->hal), paddr);
+}
+
+void ath12k_wifi7_hal_write_ml_reoq_lut_addr(struct ath12k_base *ab,
+ dma_addr_t paddr)
+{
+ ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG +
+ HAL_REO1_QDESC_LUT_BASE1(&ab->hal), paddr);
+}
+
+void ath12k_wifi7_hal_cc_config(struct ath12k_base *ab)
+{
+ u32 cmem_base = ab->qmi.dev_mem[ATH12K_QMI_DEVMEM_CMEM_INDEX].start;
+ u32 reo_base = HAL_SEQ_WCSS_UMAC_REO_REG;
+ u32 wbm_base = HAL_SEQ_WCSS_UMAC_WBM_REG;
+ u32 val = 0;
+ struct ath12k_hal *hal = &ab->hal;
+
+ if (ath12k_ftm_mode)
+ return;
+
+ ath12k_hif_write32(ab, reo_base + HAL_REO1_SW_COOKIE_CFG0(hal), cmem_base);
+
+ val |= u32_encode_bits(ATH12K_CMEM_ADDR_MSB,
+ HAL_REO1_SW_COOKIE_CFG_CMEM_BASE_ADDR_MSB) |
+ u32_encode_bits(ATH12K_CC_PPT_MSB,
+ HAL_REO1_SW_COOKIE_CFG_COOKIE_PPT_MSB) |
+ u32_encode_bits(ATH12K_CC_SPT_MSB,
+ HAL_REO1_SW_COOKIE_CFG_COOKIE_SPT_MSB) |
+ u32_encode_bits(1, HAL_REO1_SW_COOKIE_CFG_ALIGN) |
+ u32_encode_bits(1, HAL_REO1_SW_COOKIE_CFG_ENABLE) |
+ u32_encode_bits(1, HAL_REO1_SW_COOKIE_CFG_GLOBAL_ENABLE);
+
+ ath12k_hif_write32(ab, reo_base + HAL_REO1_SW_COOKIE_CFG1(hal), val);
+
+ /* Enable HW CC for WBM */
+ ath12k_hif_write32(ab, wbm_base + HAL_WBM_SW_COOKIE_CFG0, cmem_base);
+
+ val = u32_encode_bits(ATH12K_CMEM_ADDR_MSB,
+ HAL_WBM_SW_COOKIE_CFG_CMEM_BASE_ADDR_MSB) |
+ u32_encode_bits(ATH12K_CC_PPT_MSB,
+ HAL_WBM_SW_COOKIE_CFG_COOKIE_PPT_MSB) |
+ u32_encode_bits(ATH12K_CC_SPT_MSB,
+ HAL_WBM_SW_COOKIE_CFG_COOKIE_SPT_MSB) |
+ u32_encode_bits(1, HAL_WBM_SW_COOKIE_CFG_ALIGN);
+
+ ath12k_hif_write32(ab, wbm_base + HAL_WBM_SW_COOKIE_CFG1, val);
+
+ /* Enable conversion complete indication */
+ val = ath12k_hif_read32(ab, wbm_base + HAL_WBM_SW_COOKIE_CFG2);
+ val |= u32_encode_bits(1, HAL_WBM_SW_COOKIE_CFG_RELEASE_PATH_EN) |
+ u32_encode_bits(1, HAL_WBM_SW_COOKIE_CFG_ERR_PATH_EN) |
+ u32_encode_bits(1, HAL_WBM_SW_COOKIE_CFG_CONV_IND_EN);
+
+ ath12k_hif_write32(ab, wbm_base + HAL_WBM_SW_COOKIE_CFG2, val);
+
+ /* Enable Cookie conversion for WBM2SW Rings */
+ val = ath12k_hif_read32(ab, wbm_base + HAL_WBM_SW_COOKIE_CONVERT_CFG);
+ val |= u32_encode_bits(1, HAL_WBM_SW_COOKIE_CONV_CFG_GLOBAL_EN) |
+ hal->hal_params->wbm2sw_cc_enable;
+
+ ath12k_hif_write32(ab, wbm_base + HAL_WBM_SW_COOKIE_CONVERT_CFG, val);
+}
+
+enum hal_rx_buf_return_buf_manager
+ath12k_wifi7_hal_get_idle_link_rbm(struct ath12k_hal *hal, u8 device_id)
+{
+ switch (device_id) {
+ case 0:
+ return HAL_RX_BUF_RBM_WBM_DEV0_IDLE_DESC_LIST;
+ case 1:
+ return HAL_RX_BUF_RBM_WBM_DEV1_IDLE_DESC_LIST;
+ case 2:
+ return HAL_RX_BUF_RBM_WBM_DEV2_IDLE_DESC_LIST;
+ default:
+ ath12k_warn(hal,
+ "invalid %d device id, so choose default rbm\n",
+ device_id);
+ WARN_ON(1);
+ return HAL_RX_BUF_RBM_WBM_DEV0_IDLE_DESC_LIST;
+ }
+}
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal.h b/drivers/net/wireless/ath/ath12k/wifi7/hal.h
new file mode 100644
index 000000000000..9337225a5253
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal.h
@@ -0,0 +1,561 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef ATH12K_HAL_WIFI7_H
+#define ATH12K_HAL_WIFI7_H
+
+#include "../core.h"
+#include "../hal.h"
+#include "hal_desc.h"
+#include "hal_tx.h"
+#include "hal_rx.h"
+#include "hal_rx_desc.h"
+
+/* calculate the register address from bar0 of shadow register x */
+#define HAL_SHADOW_BASE_ADDR 0x000008fc
+#define HAL_SHADOW_NUM_REGS 40
+#define HAL_HP_OFFSET_IN_REG_START 1
+#define HAL_OFFSET_FROM_HP_TO_TP 4
+
+#define HAL_SHADOW_REG(x) (HAL_SHADOW_BASE_ADDR + (4 * (x)))
+#define HAL_REO_QDESC_MAX_PEERID 8191
+
+/* WCSS Relative address */
+#define HAL_SEQ_WCSS_CMEM_OFFSET 0x00100000
+#define HAL_SEQ_WCSS_UMAC_OFFSET 0x00a00000
+#define HAL_SEQ_WCSS_UMAC_REO_REG 0x00a38000
+#define HAL_SEQ_WCSS_UMAC_TCL_REG 0x00a44000
+#define HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(hal) \
+ ((hal)->regs->umac_ce0_src_reg_base)
+#define HAL_SEQ_WCSS_UMAC_CE0_DST_REG(hal) \
+ ((hal)->regs->umac_ce0_dest_reg_base)
+#define HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(hal) \
+ ((hal)->regs->umac_ce1_src_reg_base)
+#define HAL_SEQ_WCSS_UMAC_CE1_DST_REG(hal) \
+ ((hal)->regs->umac_ce1_dest_reg_base)
+#define HAL_SEQ_WCSS_UMAC_WBM_REG 0x00a34000
+
+#define HAL_CE_WFSS_CE_REG_BASE 0x01b80000
+
+#define HAL_TCL_SW_CONFIG_BANK_ADDR 0x00a4408c
+
+/* SW2TCL(x) R0 ring configuration address */
+#define HAL_TCL1_RING_CMN_CTRL_REG 0x00000020
+#define HAL_TCL1_RING_DSCP_TID_MAP 0x00000240
+
+#define HAL_TCL1_RING_BASE_LSB(hal) \
+ ((hal)->regs->tcl1_ring_base_lsb)
+#define HAL_TCL1_RING_BASE_MSB(hal) \
+ ((hal)->regs->tcl1_ring_base_msb)
+#define HAL_TCL1_RING_ID(hal) ((hal)->regs->tcl1_ring_id)
+#define HAL_TCL1_RING_MISC(hal) \
+ ((hal)->regs->tcl1_ring_misc)
+#define HAL_TCL1_RING_TP_ADDR_LSB(hal) \
+ ((hal)->regs->tcl1_ring_tp_addr_lsb)
+#define HAL_TCL1_RING_TP_ADDR_MSB(hal) \
+ ((hal)->regs->tcl1_ring_tp_addr_msb)
+#define HAL_TCL1_RING_CONSUMER_INT_SETUP_IX0(hal) \
+ ((hal)->regs->tcl1_ring_consumer_int_setup_ix0)
+#define HAL_TCL1_RING_CONSUMER_INT_SETUP_IX1(hal) \
+ ((hal)->regs->tcl1_ring_consumer_int_setup_ix1)
+#define HAL_TCL1_RING_MSI1_BASE_LSB(hal) \
+ ((hal)->regs->tcl1_ring_msi1_base_lsb)
+#define HAL_TCL1_RING_MSI1_BASE_MSB(hal) \
+ ((hal)->regs->tcl1_ring_msi1_base_msb)
+#define HAL_TCL1_RING_MSI1_DATA(hal) \
+ ((hal)->regs->tcl1_ring_msi1_data)
+#define HAL_TCL2_RING_BASE_LSB(hal) \
+ ((hal)->regs->tcl2_ring_base_lsb)
+#define HAL_TCL_RING_BASE_LSB(hal) \
+ ((hal)->regs->tcl_ring_base_lsb)
+
+#define HAL_TCL1_RING_MSI1_BASE_LSB_OFFSET(hal) ({ typeof(hal) _hal = (hal); \
+ (HAL_TCL1_RING_MSI1_BASE_LSB(_hal) - HAL_TCL1_RING_BASE_LSB(_hal)); })
+#define HAL_TCL1_RING_MSI1_BASE_MSB_OFFSET(hal) ({ typeof(hal) _hal = (hal); \
+ (HAL_TCL1_RING_MSI1_BASE_MSB(_hal) - HAL_TCL1_RING_BASE_LSB(_hal)); })
+#define HAL_TCL1_RING_MSI1_DATA_OFFSET(hal) ({ typeof(hal) _hal = (hal); \
+ (HAL_TCL1_RING_MSI1_DATA(_hal) - HAL_TCL1_RING_BASE_LSB(_hal)); })
+#define HAL_TCL1_RING_BASE_MSB_OFFSET(hal) ({ typeof(hal) _hal = (hal); \
+ (HAL_TCL1_RING_BASE_MSB(_hal) - HAL_TCL1_RING_BASE_LSB(_hal)); })
+#define HAL_TCL1_RING_ID_OFFSET(hal) ({ typeof(hal) _hal = (hal); \
+ (HAL_TCL1_RING_ID(_hal) - HAL_TCL1_RING_BASE_LSB(_hal)); })
+#define HAL_TCL1_RING_CONSR_INT_SETUP_IX0_OFFSET(hal) ({ typeof(hal) _hal = (hal); \
+ (HAL_TCL1_RING_CONSUMER_INT_SETUP_IX0(_hal) - HAL_TCL1_RING_BASE_LSB(_hal)); })
+#define HAL_TCL1_RING_CONSR_INT_SETUP_IX1_OFFSET(hal) ({ typeof(hal) _hal = (hal); \
+ (HAL_TCL1_RING_CONSUMER_INT_SETUP_IX1(_hal) - HAL_TCL1_RING_BASE_LSB(_hal)); })
+#define HAL_TCL1_RING_TP_ADDR_LSB_OFFSET(hal) ({ typeof(hal) _hal = (hal); \
+ (HAL_TCL1_RING_TP_ADDR_LSB(_hal) - HAL_TCL1_RING_BASE_LSB(_hal)); })
+#define HAL_TCL1_RING_TP_ADDR_MSB_OFFSET(hal) ({ typeof(hal) _hal = (hal); \
+ (HAL_TCL1_RING_TP_ADDR_MSB(_hal) - HAL_TCL1_RING_BASE_LSB(_hal)); })
+#define HAL_TCL1_RING_MISC_OFFSET(hal) ({ typeof(hal) _hal = (hal); \
+ (HAL_TCL1_RING_MISC(_hal) - HAL_TCL1_RING_BASE_LSB(_hal)); })
+
+/* SW2TCL(x) R2 ring pointers (head/tail) address */
+#define HAL_TCL1_RING_HP 0x00002000
+#define HAL_TCL1_RING_TP 0x00002004
+#define HAL_TCL2_RING_HP 0x00002008
+#define HAL_TCL_RING_HP 0x00002028
+
+#define HAL_TCL1_RING_TP_OFFSET \
+ (HAL_TCL1_RING_TP - HAL_TCL1_RING_HP)
+
+/* TCL STATUS ring address */
+#define HAL_TCL_STATUS_RING_BASE_LSB(hal) \
+ ((hal)->regs->tcl_status_ring_base_lsb)
+#define HAL_TCL_STATUS_RING_HP 0x00002048
+
+/* PPE2TCL1 Ring address */
+#define HAL_TCL_PPE2TCL1_RING_BASE_LSB 0x00000c48
+#define HAL_TCL_PPE2TCL1_RING_HP 0x00002038
+
+/* WBM PPE Release Ring address */
+#define HAL_WBM_PPE_RELEASE_RING_BASE_LSB(hal) \
+ ((hal)->regs->ppe_rel_ring_base)
+#define HAL_WBM_PPE_RELEASE_RING_HP 0x00003020
+
+/* REO2SW(x) R0 ring configuration address */
+#define HAL_REO1_GEN_ENABLE 0x00000000
+#define HAL_REO1_MISC_CTRL_ADDR(hal) \
+ ((hal)->regs->reo1_misc_ctrl_addr)
+#define HAL_REO1_DEST_RING_CTRL_IX_0 0x00000004
+#define HAL_REO1_DEST_RING_CTRL_IX_1 0x00000008
+#define HAL_REO1_DEST_RING_CTRL_IX_2 0x0000000c
+#define HAL_REO1_DEST_RING_CTRL_IX_3 0x00000010
+#define HAL_REO1_QDESC_ADDR(hal) ((hal)->regs->reo1_qdesc_addr)
+#define HAL_REO1_QDESC_MAX_PEERID(hal) ((hal)->regs->reo1_qdesc_max_peerid)
+#define HAL_REO1_SW_COOKIE_CFG0(hal) ((hal)->regs->reo1_sw_cookie_cfg0)
+#define HAL_REO1_SW_COOKIE_CFG1(hal) ((hal)->regs->reo1_sw_cookie_cfg1)
+#define HAL_REO1_QDESC_LUT_BASE0(hal) ((hal)->regs->reo1_qdesc_lut_base0)
+#define HAL_REO1_QDESC_LUT_BASE1(hal) ((hal)->regs->reo1_qdesc_lut_base1)
+#define HAL_REO1_RING_BASE_LSB(hal) ((hal)->regs->reo1_ring_base_lsb)
+#define HAL_REO1_RING_BASE_MSB(hal) ((hal)->regs->reo1_ring_base_msb)
+#define HAL_REO1_RING_ID(hal) ((hal)->regs->reo1_ring_id)
+#define HAL_REO1_RING_MISC(hal) ((hal)->regs->reo1_ring_misc)
+#define HAL_REO1_RING_HP_ADDR_LSB(hal) ((hal)->regs->reo1_ring_hp_addr_lsb)
+#define HAL_REO1_RING_HP_ADDR_MSB(hal) ((hal)->regs->reo1_ring_hp_addr_msb)
+#define HAL_REO1_RING_PRODUCER_INT_SETUP(hal) \
+ ((hal)->regs->reo1_ring_producer_int_setup)
+#define HAL_REO1_RING_MSI1_BASE_LSB(hal) \
+ ((hal)->regs->reo1_ring_msi1_base_lsb)
+#define HAL_REO1_RING_MSI1_BASE_MSB(hal) \
+ ((hal)->regs->reo1_ring_msi1_base_msb)
+#define HAL_REO1_RING_MSI1_DATA(hal) ((hal)->regs->reo1_ring_msi1_data)
+#define HAL_REO2_RING_BASE_LSB(hal) ((hal)->regs->reo2_ring_base)
+#define HAL_REO1_AGING_THRESH_IX_0(hal) ((hal)->regs->reo1_aging_thres_ix0)
+#define HAL_REO1_AGING_THRESH_IX_1(hal) ((hal)->regs->reo1_aging_thres_ix1)
+#define HAL_REO1_AGING_THRESH_IX_2(hal) ((hal)->regs->reo1_aging_thres_ix2)
+#define HAL_REO1_AGING_THRESH_IX_3(hal) ((hal)->regs->reo1_aging_thres_ix3)
+
+/* REO2SW(x) R2 ring pointers (head/tail) address */
+#define HAL_REO1_RING_HP 0x00003048
+#define HAL_REO1_RING_TP 0x0000304c
+#define HAL_REO2_RING_HP 0x00003050
+
+#define HAL_REO1_RING_TP_OFFSET (HAL_REO1_RING_TP - HAL_REO1_RING_HP)
+
+/* REO2SW0 ring configuration address */
+#define HAL_REO_SW0_RING_BASE_LSB(hal) \
+ ((hal)->regs->reo2_sw0_ring_base)
+
+/* REO2SW0 R2 ring pointer (head/tail) address */
+#define HAL_REO_SW0_RING_HP 0x00003088
+
+/* REO CMD R0 address */
+#define HAL_REO_CMD_RING_BASE_LSB(hal) \
+ ((hal)->regs->reo_cmd_ring_base)
+
+/* REO CMD R2 address */
+#define HAL_REO_CMD_HP 0x00003020
+
+/* SW2REO R0 address */
+#define HAL_SW2REO_RING_BASE_LSB(hal) \
+ ((hal)->regs->sw2reo_ring_base)
+#define HAL_SW2REO1_RING_BASE_LSB(hal) \
+ ((hal)->regs->sw2reo1_ring_base)
+
+/* SW2REO R2 address */
+#define HAL_SW2REO_RING_HP 0x00003028
+#define HAL_SW2REO1_RING_HP 0x00003030
+
+/* CE ring R0 address */
+#define HAL_CE_SRC_RING_BASE_LSB 0x00000000
+#define HAL_CE_DST_RING_BASE_LSB 0x00000000
+#define HAL_CE_DST_STATUS_RING_BASE_LSB 0x00000058
+#define HAL_CE_DST_RING_CTRL 0x000000b0
+
+/* CE ring R2 address */
+#define HAL_CE_DST_RING_HP 0x00000400
+#define HAL_CE_DST_STATUS_RING_HP 0x00000408
+
+/* REO status address */
+#define HAL_REO_STATUS_RING_BASE_LSB(hal) \
+ ((hal)->regs->reo_status_ring_base)
+#define HAL_REO_STATUS_HP 0x000030a8
+
+/* WBM Idle R0 address */
+#define HAL_WBM_IDLE_LINK_RING_BASE_LSB(hal) \
+ ((hal)->regs->wbm_idle_ring_base_lsb)
+#define HAL_WBM_IDLE_LINK_RING_MISC_ADDR(hal) \
+ ((hal)->regs->wbm_idle_ring_misc_addr)
+#define HAL_WBM_R0_IDLE_LIST_CONTROL_ADDR(hal) \
+ ((hal)->regs->wbm_r0_idle_list_cntl_addr)
+#define HAL_WBM_R0_IDLE_LIST_SIZE_ADDR(hal) \
+ ((hal)->regs->wbm_r0_idle_list_size_addr)
+#define HAL_WBM_SCATTERED_RING_BASE_LSB(hal) \
+ ((hal)->regs->wbm_scattered_ring_base_lsb)
+#define HAL_WBM_SCATTERED_RING_BASE_MSB(hal) \
+ ((hal)->regs->wbm_scattered_ring_base_msb)
+#define HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX0(hal) \
+ ((hal)->regs->wbm_scattered_desc_head_info_ix0)
+#define HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX1(hal) \
+ ((hal)->regs->wbm_scattered_desc_head_info_ix1)
+#define HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX0(hal) \
+ ((hal)->regs->wbm_scattered_desc_tail_info_ix0)
+#define HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX1(hal) \
+ ((hal)->regs->wbm_scattered_desc_tail_info_ix1)
+#define HAL_WBM_SCATTERED_DESC_PTR_HP_ADDR(hal) \
+ ((hal)->regs->wbm_scattered_desc_ptr_hp_addr)
+
+/* WBM Idle R2 address */
+#define HAL_WBM_IDLE_LINK_RING_HP 0x000030b8
+
+/* SW2WBM R0 release address */
+#define HAL_WBM_SW_RELEASE_RING_BASE_LSB(hal) \
+ ((hal)->regs->wbm_sw_release_ring_base_lsb)
+#define HAL_WBM_SW1_RELEASE_RING_BASE_LSB(hal) \
+ ((hal)->regs->wbm_sw1_release_ring_base_lsb)
+
+/* SW2WBM R2 release address */
+#define HAL_WBM_SW_RELEASE_RING_HP 0x00003010
+#define HAL_WBM_SW1_RELEASE_RING_HP 0x00003018
+
+/* WBM2SW R0 release address */
+#define HAL_WBM0_RELEASE_RING_BASE_LSB(hal) \
+ ((hal)->regs->wbm0_release_ring_base_lsb)
+
+#define HAL_WBM1_RELEASE_RING_BASE_LSB(hal) \
+ ((hal)->regs->wbm1_release_ring_base_lsb)
+
+/* WBM2SW R2 release address */
+#define HAL_WBM0_RELEASE_RING_HP 0x000030c8
+#define HAL_WBM1_RELEASE_RING_HP 0x000030d0
+
+/* WBM cookie config address and mask */
+#define HAL_WBM_SW_COOKIE_CFG0 0x00000040
+#define HAL_WBM_SW_COOKIE_CFG1 0x00000044
+#define HAL_WBM_SW_COOKIE_CFG2 0x00000090
+#define HAL_WBM_SW_COOKIE_CONVERT_CFG 0x00000094
+
+#define HAL_WBM_SW_COOKIE_CFG_CMEM_BASE_ADDR_MSB GENMASK(7, 0)
+#define HAL_WBM_SW_COOKIE_CFG_COOKIE_PPT_MSB GENMASK(12, 8)
+#define HAL_WBM_SW_COOKIE_CFG_COOKIE_SPT_MSB GENMASK(17, 13)
+#define HAL_WBM_SW_COOKIE_CFG_ALIGN BIT(18)
+#define HAL_WBM_SW_COOKIE_CFG_RELEASE_PATH_EN BIT(0)
+#define HAL_WBM_SW_COOKIE_CFG_ERR_PATH_EN BIT(1)
+#define HAL_WBM_SW_COOKIE_CFG_CONV_IND_EN BIT(3)
+
+#define HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW0_EN BIT(1)
+#define HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW1_EN BIT(2)
+#define HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW2_EN BIT(3)
+#define HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW3_EN BIT(4)
+#define HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW4_EN BIT(5)
+#define HAL_WBM_SW_COOKIE_CONV_CFG_GLOBAL_EN BIT(8)
+
+/* TCL ring field mask and offset */
+#define HAL_TCL1_RING_BASE_MSB_RING_SIZE GENMASK(27, 8)
+#define HAL_TCL1_RING_BASE_MSB_RING_BASE_ADDR_MSB GENMASK(7, 0)
+#define HAL_TCL1_RING_ID_ENTRY_SIZE GENMASK(7, 0)
+#define HAL_TCL1_RING_MISC_MSI_RING_ID_DISABLE BIT(0)
+#define HAL_TCL1_RING_MISC_MSI_LOOPCNT_DISABLE BIT(1)
+#define HAL_TCL1_RING_MISC_MSI_SWAP BIT(3)
+#define HAL_TCL1_RING_MISC_HOST_FW_SWAP BIT(4)
+#define HAL_TCL1_RING_MISC_DATA_TLV_SWAP BIT(5)
+#define HAL_TCL1_RING_MISC_SRNG_ENABLE BIT(6)
+#define HAL_TCL1_RING_CONSR_INT_SETUP_IX0_INTR_TMR_THOLD GENMASK(31, 16)
+#define HAL_TCL1_RING_CONSR_INT_SETUP_IX0_BATCH_COUNTER_THOLD GENMASK(14, 0)
+#define HAL_TCL1_RING_CONSR_INT_SETUP_IX1_LOW_THOLD GENMASK(15, 0)
+#define HAL_TCL1_RING_MSI1_BASE_MSB_MSI1_ENABLE BIT(8)
+#define HAL_TCL1_RING_MSI1_BASE_MSB_ADDR GENMASK(7, 0)
+#define HAL_TCL1_RING_CMN_CTRL_DSCP_TID_MAP_PROG_EN BIT(23)
+#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP GENMASK(31, 0)
+#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP0 GENMASK(2, 0)
+#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP1 GENMASK(5, 3)
+#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP2 GENMASK(8, 6)
+#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP3 GENMASK(11, 9)
+#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP4 GENMASK(14, 12)
+#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP5 GENMASK(17, 15)
+#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP6 GENMASK(20, 18)
+#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP7 GENMASK(23, 21)
+
+/* REO ring field mask and offset */
+#define HAL_REO1_RING_BASE_MSB_RING_SIZE GENMASK(27, 8)
+#define HAL_REO1_RING_BASE_MSB_RING_BASE_ADDR_MSB GENMASK(7, 0)
+#define HAL_REO1_RING_ID_RING_ID GENMASK(15, 8)
+#define HAL_REO1_RING_ID_ENTRY_SIZE GENMASK(7, 0)
+#define HAL_REO1_RING_MISC_MSI_SWAP BIT(3)
+#define HAL_REO1_RING_MISC_HOST_FW_SWAP BIT(4)
+#define HAL_REO1_RING_MISC_DATA_TLV_SWAP BIT(5)
+#define HAL_REO1_RING_MISC_SRNG_ENABLE BIT(6)
+#define HAL_REO1_RING_PRDR_INT_SETUP_INTR_TMR_THOLD GENMASK(31, 16)
+#define HAL_REO1_RING_PRDR_INT_SETUP_BATCH_COUNTER_THOLD GENMASK(14, 0)
+#define HAL_REO1_RING_MSI1_BASE_MSB_MSI1_ENABLE BIT(8)
+#define HAL_REO1_RING_MSI1_BASE_MSB_ADDR GENMASK(7, 0)
+#define HAL_REO1_MISC_CTL_FRAG_DST_RING GENMASK(20, 17)
+#define HAL_REO1_MISC_CTL_BAR_DST_RING GENMASK(24, 21)
+#define HAL_REO1_GEN_ENABLE_AGING_LIST_ENABLE BIT(2)
+#define HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE BIT(3)
+#define HAL_REO1_SW_COOKIE_CFG_CMEM_BASE_ADDR_MSB GENMASK(7, 0)
+#define HAL_REO1_SW_COOKIE_CFG_COOKIE_PPT_MSB GENMASK(12, 8)
+#define HAL_REO1_SW_COOKIE_CFG_COOKIE_SPT_MSB GENMASK(17, 13)
+#define HAL_REO1_SW_COOKIE_CFG_ALIGN BIT(18)
+#define HAL_REO1_SW_COOKIE_CFG_ENABLE BIT(19)
+#define HAL_REO1_SW_COOKIE_CFG_GLOBAL_ENABLE BIT(20)
+#define HAL_REO_QDESC_ADDR_READ_LUT_ENABLE BIT(7)
+#define HAL_REO_QDESC_ADDR_READ_CLEAR_QDESC_ARRAY BIT(6)
+
+/* CE ring bit field mask and shift */
+#define HAL_CE_DST_R0_DEST_CTRL_MAX_LEN GENMASK(15, 0)
+
+#define HAL_ADDR_LSB_REG_MASK 0xffffffff
+
+#define HAL_ADDR_MSB_REG_SHIFT 32
+
+/* WBM ring bit field mask and shift */
+#define HAL_WBM_LINK_DESC_IDLE_LIST_MODE BIT(1)
+#define HAL_WBM_SCATTER_BUFFER_SIZE GENMASK(10, 2)
+#define HAL_WBM_SCATTER_RING_SIZE_OF_IDLE_LINK_DESC_LIST GENMASK(31, 16)
+#define HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32 GENMASK(7, 0)
+#define HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_MATCH_TAG GENMASK(31, 8)
+
+#define HAL_WBM_SCATTERED_DESC_HEAD_P_OFFSET_IX1 GENMASK(20, 8)
+#define HAL_WBM_SCATTERED_DESC_TAIL_P_OFFSET_IX1 GENMASK(20, 8)
+
+#define HAL_WBM_IDLE_LINK_RING_MISC_SRNG_ENABLE BIT(6)
+#define HAL_WBM_IDLE_LINK_RING_MISC_RIND_ID_DISABLE BIT(0)
+
+#define BASE_ADDR_MATCH_TAG_VAL 0x5
+
+#define HAL_REO_REO2SW1_RING_BASE_MSB_RING_SIZE 0x000fffff
+#define HAL_REO_REO2SW0_RING_BASE_MSB_RING_SIZE 0x000fffff
+#define HAL_REO_SW2REO_RING_BASE_MSB_RING_SIZE 0x0000ffff
+#define HAL_REO_CMD_RING_BASE_MSB_RING_SIZE 0x0000ffff
+#define HAL_REO_STATUS_RING_BASE_MSB_RING_SIZE 0x0000ffff
+#define HAL_SW2TCL1_RING_BASE_MSB_RING_SIZE 0x000fffff
+#define HAL_SW2TCL1_CMD_RING_BASE_MSB_RING_SIZE 0x000fffff
+#define HAL_TCL_STATUS_RING_BASE_MSB_RING_SIZE 0x0000ffff
+#define HAL_CE_SRC_RING_BASE_MSB_RING_SIZE 0x0000ffff
+#define HAL_CE_DST_RING_BASE_MSB_RING_SIZE 0x0000ffff
+#define HAL_CE_DST_STATUS_RING_BASE_MSB_RING_SIZE 0x0000ffff
+#define HAL_WBM_IDLE_LINK_RING_BASE_MSB_RING_SIZE 0x000fffff
+#define HAL_SW2WBM_RELEASE_RING_BASE_MSB_RING_SIZE 0x0000ffff
+#define HAL_WBM2SW_RELEASE_RING_BASE_MSB_RING_SIZE 0x000fffff
+#define HAL_RXDMA_RING_MAX_SIZE 0x0000ffff
+#define HAL_RXDMA_RING_MAX_SIZE_BE 0x000fffff
+#define HAL_WBM2PPE_RELEASE_RING_BASE_MSB_RING_SIZE 0x000fffff
+
+#define HAL_WBM2SW_REL_ERR_RING_NUM 3
+/* Add any other errors here and return them in
+ * ath12k_hal_rx_desc_get_err().
+ */
+
+#define HAL_IPQ5332_CE_WFSS_REG_BASE 0x740000
+#define HAL_IPQ5332_CE_SIZE 0x100000
+
+#define HAL_RX_MAX_BA_WINDOW 256
+
+#define HAL_DEFAULT_BE_BK_VI_REO_TIMEOUT_USEC (100 * 1000)
+#define HAL_DEFAULT_VO_REO_TIMEOUT_USEC (40 * 1000)
+
+#define HAL_SRNG_DESC_LOOP_CNT 0xf0000000
+
+#define HAL_REO_CMD_FLG_NEED_STATUS BIT(0)
+#define HAL_REO_CMD_FLG_STATS_CLEAR BIT(1)
+#define HAL_REO_CMD_FLG_FLUSH_BLOCK_LATER BIT(2)
+#define HAL_REO_CMD_FLG_FLUSH_RELEASE_BLOCKING BIT(3)
+#define HAL_REO_CMD_FLG_FLUSH_NO_INVAL BIT(4)
+#define HAL_REO_CMD_FLG_FLUSH_FWD_ALL_MPDUS BIT(5)
+#define HAL_REO_CMD_FLG_FLUSH_ALL BIT(6)
+#define HAL_REO_CMD_FLG_UNBLK_RESOURCE BIT(7)
+#define HAL_REO_CMD_FLG_UNBLK_CACHE BIT(8)
+#define HAL_REO_CMD_FLG_FLUSH_QUEUE_1K_DESC BIT(9)
+
+/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO0_UPD_* fields */
+#define HAL_REO_CMD_UPD0_RX_QUEUE_NUM BIT(8)
+#define HAL_REO_CMD_UPD0_VLD BIT(9)
+#define HAL_REO_CMD_UPD0_ALDC BIT(10)
+#define HAL_REO_CMD_UPD0_DIS_DUP_DETECTION BIT(11)
+#define HAL_REO_CMD_UPD0_SOFT_REORDER_EN BIT(12)
+#define HAL_REO_CMD_UPD0_AC BIT(13)
+#define HAL_REO_CMD_UPD0_BAR BIT(14)
+#define HAL_REO_CMD_UPD0_RETRY BIT(15)
+#define HAL_REO_CMD_UPD0_CHECK_2K_MODE BIT(16)
+#define HAL_REO_CMD_UPD0_OOR_MODE BIT(17)
+#define HAL_REO_CMD_UPD0_BA_WINDOW_SIZE BIT(18)
+#define HAL_REO_CMD_UPD0_PN_CHECK BIT(19)
+#define HAL_REO_CMD_UPD0_EVEN_PN BIT(20)
+#define HAL_REO_CMD_UPD0_UNEVEN_PN BIT(21)
+#define HAL_REO_CMD_UPD0_PN_HANDLE_ENABLE BIT(22)
+#define HAL_REO_CMD_UPD0_PN_SIZE BIT(23)
+#define HAL_REO_CMD_UPD0_IGNORE_AMPDU_FLG BIT(24)
+#define HAL_REO_CMD_UPD0_SVLD BIT(25)
+#define HAL_REO_CMD_UPD0_SSN BIT(26)
+#define HAL_REO_CMD_UPD0_SEQ_2K_ERR BIT(27)
+#define HAL_REO_CMD_UPD0_PN_ERR BIT(28)
+#define HAL_REO_CMD_UPD0_PN_VALID BIT(29)
+#define HAL_REO_CMD_UPD0_PN BIT(30)
+
+/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO1_* fields */
+#define HAL_REO_CMD_UPD1_VLD BIT(16)
+#define HAL_REO_CMD_UPD1_ALDC GENMASK(18, 17)
+#define HAL_REO_CMD_UPD1_DIS_DUP_DETECTION BIT(19)
+#define HAL_REO_CMD_UPD1_SOFT_REORDER_EN BIT(20)
+#define HAL_REO_CMD_UPD1_AC GENMASK(22, 21)
+#define HAL_REO_CMD_UPD1_BAR BIT(23)
+#define HAL_REO_CMD_UPD1_RETRY BIT(24)
+#define HAL_REO_CMD_UPD1_CHECK_2K_MODE BIT(25)
+#define HAL_REO_CMD_UPD1_OOR_MODE BIT(26)
+#define HAL_REO_CMD_UPD1_PN_CHECK BIT(27)
+#define HAL_REO_CMD_UPD1_EVEN_PN BIT(28)
+#define HAL_REO_CMD_UPD1_UNEVEN_PN BIT(29)
+#define HAL_REO_CMD_UPD1_PN_HANDLE_ENABLE BIT(30)
+#define HAL_REO_CMD_UPD1_IGNORE_AMPDU_FLG BIT(31)
+
+/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO2_* fields */
+#define HAL_REO_CMD_UPD2_SVLD BIT(10)
+#define HAL_REO_CMD_UPD2_SSN GENMASK(22, 11)
+#define HAL_REO_CMD_UPD2_SEQ_2K_ERR BIT(23)
+#define HAL_REO_CMD_UPD2_PN_ERR BIT(24)
+
+struct hal_reo_status_queue_stats {
+ u16 ssn;
+ u16 curr_idx;
+ u32 pn[4];
+ u32 last_rx_queue_ts;
+ u32 last_rx_dequeue_ts;
+ u32 rx_bitmap[8]; /* Bitmap from 0-255 */
+ u32 curr_mpdu_cnt;
+ u32 curr_msdu_cnt;
+ u16 fwd_due_to_bar_cnt;
+ u16 dup_cnt;
+ u32 frames_in_order_cnt;
+ u32 num_mpdu_processed_cnt;
+ u32 num_msdu_processed_cnt;
+ u32 total_num_processed_byte_cnt;
+ u32 late_rx_mpdu_cnt;
+ u32 reorder_hole_cnt;
+ u8 timeout_cnt;
+ u8 bar_rx_cnt;
+ u8 num_window_2k_jump_cnt;
+};
+
+struct hal_reo_status_flush_queue {
+ bool err_detected;
+};
+
+enum hal_reo_status_flush_cache_err_code {
+ HAL_REO_STATUS_FLUSH_CACHE_ERR_CODE_SUCCESS,
+ HAL_REO_STATUS_FLUSH_CACHE_ERR_CODE_IN_USE,
+ HAL_REO_STATUS_FLUSH_CACHE_ERR_CODE_NOT_FOUND,
+};
+
+struct hal_reo_status_flush_cache {
+ bool err_detected;
+ enum hal_reo_status_flush_cache_err_code err_code;
+ bool cache_controller_flush_status_hit;
+ u8 cache_controller_flush_status_desc_type;
+ u8 cache_controller_flush_status_client_id;
+ u8 cache_controller_flush_status_err;
+ u8 cache_controller_flush_status_cnt;
+};
+
+enum hal_reo_status_unblock_cache_type {
+ HAL_REO_STATUS_UNBLOCK_BLOCKING_RESOURCE,
+ HAL_REO_STATUS_UNBLOCK_ENTIRE_CACHE_USAGE,
+};
+
+struct hal_reo_status_unblock_cache {
+ bool err_detected;
+ enum hal_reo_status_unblock_cache_type unblock_type;
+};
+
+struct hal_reo_status_flush_timeout_list {
+ bool err_detected;
+ bool list_empty;
+ u16 release_desc_cnt;
+ u16 fwd_buf_cnt;
+};
+
+enum hal_reo_threshold_idx {
+ HAL_REO_THRESHOLD_IDX_DESC_COUNTER0,
+ HAL_REO_THRESHOLD_IDX_DESC_COUNTER1,
+ HAL_REO_THRESHOLD_IDX_DESC_COUNTER2,
+ HAL_REO_THRESHOLD_IDX_DESC_COUNTER_SUM,
+};
+
+struct hal_reo_status_desc_thresh_reached {
+ enum hal_reo_threshold_idx threshold_idx;
+ u32 link_desc_counter0;
+ u32 link_desc_counter1;
+ u32 link_desc_counter2;
+ u32 link_desc_counter_sum;
+};
+
+struct hal_reo_status {
+ struct hal_reo_status_header uniform_hdr;
+ u8 loop_cnt;
+ union {
+ struct hal_reo_status_queue_stats queue_stats;
+ struct hal_reo_status_flush_queue flush_queue;
+ struct hal_reo_status_flush_cache flush_cache;
+ struct hal_reo_status_unblock_cache unblock_cache;
+ struct hal_reo_status_flush_timeout_list timeout_list;
+ struct hal_reo_status_desc_thresh_reached desc_thresh_reached;
+ } u;
+};
+
+int ath12k_wifi7_hal_init(struct ath12k_base *ab);
+void ath12k_wifi7_hal_ce_dst_setup(struct ath12k_base *ab,
+ struct hal_srng *srng, int ring_num);
+void ath12k_wifi7_hal_srng_dst_hw_init(struct ath12k_base *ab,
+ struct hal_srng *srng);
+void ath12k_wifi7_hal_srng_src_hw_init(struct ath12k_base *ab,
+ struct hal_srng *srng);
+void ath12k_wifi7_hal_set_umac_srng_ptr_addr(struct ath12k_base *ab,
+ struct hal_srng *srng);
+int ath12k_wifi7_hal_srng_update_shadow_config(struct ath12k_base *ab,
+ enum hal_ring_type ring_type,
+ int ring_num);
+int ath12k_wifi7_hal_srng_get_ring_id(struct ath12k_hal *hal,
+ enum hal_ring_type type,
+ int ring_num, int mac_id);
+u32 ath12k_wifi7_hal_ce_get_desc_size(enum hal_ce_desc type);
+void ath12k_wifi7_hal_cc_config(struct ath12k_base *ab);
+enum hal_rx_buf_return_buf_manager
+ath12k_wifi7_hal_get_idle_link_rbm(struct ath12k_hal *hal, u8 device_id);
+void ath12k_wifi7_hal_ce_src_set_desc(struct hal_ce_srng_src_desc *desc,
+ dma_addr_t paddr,
+ u32 len, u32 id, u8 byte_swap_data);
+void ath12k_wifi7_hal_ce_dst_set_desc(struct hal_ce_srng_dest_desc *desc,
+ dma_addr_t paddr);
+void
+ath12k_wifi7_hal_set_link_desc_addr(struct hal_wbm_link_desc *desc,
+ u32 cookie, dma_addr_t paddr,
+ enum hal_rx_buf_return_buf_manager rbm);
+u32
+ath12k_wifi7_hal_ce_dst_status_get_length(struct hal_ce_srng_dst_status_desc *desc);
+void
+ath12k_wifi7_hal_setup_link_idle_list(struct ath12k_base *ab,
+ struct hal_wbm_idle_scatter_list *sbuf,
+ u32 nsbufs, u32 tot_link_desc,
+ u32 end_offset);
+void ath12k_wifi7_hal_reoq_lut_addr_read_enable(struct ath12k_base *ab);
+void ath12k_wifi7_hal_reoq_lut_set_max_peerid(struct ath12k_base *ab);
+void ath12k_wifi7_hal_write_reoq_lut_addr(struct ath12k_base *ab,
+ dma_addr_t paddr);
+void ath12k_wifi7_hal_write_ml_reoq_lut_addr(struct ath12k_base *ab,
+ dma_addr_t paddr);
+u32 ath12k_wifi7_hal_reo_qdesc_size(u32 ba_window_size, u8 tid);
+#endif
diff --git a/drivers/net/wireless/ath/ath12k/hal_desc.h b/drivers/net/wireless/ath/ath12k/wifi7/hal_desc.h
index 13ddac4a9412..e1ab47b44433 100644
--- a/drivers/net/wireless/ath/ath12k/hal_desc.h
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_desc.h
@@ -1,92 +1,13 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022, 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
-#include "core.h"
+#include "../core.h"
#ifndef ATH12K_HAL_DESC_H
#define ATH12K_HAL_DESC_H
-#define BUFFER_ADDR_INFO0_ADDR GENMASK(31, 0)
-
-#define BUFFER_ADDR_INFO1_ADDR GENMASK(7, 0)
-#define BUFFER_ADDR_INFO1_RET_BUF_MGR GENMASK(11, 8)
-#define BUFFER_ADDR_INFO1_SW_COOKIE GENMASK(31, 12)
-
-struct ath12k_buffer_addr {
- __le32 info0;
- __le32 info1;
-} __packed;
-
-/* ath12k_buffer_addr
- *
- * buffer_addr_31_0
- * Address (lower 32 bits) of the MSDU buffer or MSDU_EXTENSION
- * descriptor or Link descriptor
- *
- * buffer_addr_39_32
- * Address (upper 8 bits) of the MSDU buffer or MSDU_EXTENSION
- * descriptor or Link descriptor
- *
- * return_buffer_manager (RBM)
- * Consumer: WBM
- * Producer: SW/FW
- * Indicates to which buffer manager the buffer or MSDU_EXTENSION
- * descriptor or link descriptor that is being pointed to shall be
- * returned after the frame has been processed. It is used by WBM
- * for routing purposes.
- *
- * Values are defined in enum %HAL_RX_BUF_RBM_
- *
- * sw_buffer_cookie
- * Cookie field exclusively used by SW. HW ignores the contents,
- * accept that it passes the programmed value on to other
- * descriptors together with the physical address.
- *
- * Field can be used by SW to for example associate the buffers
- * physical address with the virtual address.
- *
- * NOTE1:
- * The three most significant bits can have a special meaning
- * in case this struct is embedded in a TX_MPDU_DETAILS STRUCT,
- * and field transmit_bw_restriction is set
- *
- * In case of NON punctured transmission:
- * Sw_buffer_cookie[19:17] = 3'b000: 20 MHz TX only
- * Sw_buffer_cookie[19:17] = 3'b001: 40 MHz TX only
- * Sw_buffer_cookie[19:17] = 3'b010: 80 MHz TX only
- * Sw_buffer_cookie[19:17] = 3'b011: 160 MHz TX only
- * Sw_buffer_cookie[19:17] = 3'b101: 240 MHz TX only
- * Sw_buffer_cookie[19:17] = 3'b100: 320 MHz TX only
- * Sw_buffer_cookie[19:18] = 2'b11: reserved
- *
- * In case of punctured transmission:
- * Sw_buffer_cookie[19:16] = 4'b0000: pattern 0 only
- * Sw_buffer_cookie[19:16] = 4'b0001: pattern 1 only
- * Sw_buffer_cookie[19:16] = 4'b0010: pattern 2 only
- * Sw_buffer_cookie[19:16] = 4'b0011: pattern 3 only
- * Sw_buffer_cookie[19:16] = 4'b0100: pattern 4 only
- * Sw_buffer_cookie[19:16] = 4'b0101: pattern 5 only
- * Sw_buffer_cookie[19:16] = 4'b0110: pattern 6 only
- * Sw_buffer_cookie[19:16] = 4'b0111: pattern 7 only
- * Sw_buffer_cookie[19:16] = 4'b1000: pattern 8 only
- * Sw_buffer_cookie[19:16] = 4'b1001: pattern 9 only
- * Sw_buffer_cookie[19:16] = 4'b1010: pattern 10 only
- * Sw_buffer_cookie[19:16] = 4'b1011: pattern 11 only
- * Sw_buffer_cookie[19:18] = 2'b11: reserved
- *
- * Note: a punctured transmission is indicated by the presence
- * of TLV TX_PUNCTURE_SETUP embedded in the scheduler TLV
- *
- * Sw_buffer_cookie[20:17]: Tid: The TID field in the QoS control
- * field
- *
- * Sw_buffer_cookie[16]: Mpdu_qos_control_valid: This field
- * indicates MPDUs with a QoS control field.
- *
- */
-
enum hal_tlv_tag {
HAL_MACTX_CBF_START = 0 /* 0x0 */,
HAL_PHYRX_DATA = 1 /* 0x1 */,
@@ -566,27 +487,6 @@ enum hal_tlv_tag {
HAL_TLV_BASE = 511 /* 0x1ff */,
};
-#define HAL_TLV_HDR_TAG GENMASK(9, 1)
-#define HAL_TLV_HDR_LEN GENMASK(25, 10)
-#define HAL_TLV_USR_ID GENMASK(31, 26)
-
-#define HAL_TLV_ALIGN 4
-
-struct hal_tlv_hdr {
- __le32 tl;
- u8 value[];
-} __packed;
-
-#define HAL_TLV_64_HDR_TAG GENMASK(9, 1)
-#define HAL_TLV_64_HDR_LEN GENMASK(21, 10)
-#define HAL_TLV_64_USR_ID GENMASK(31, 26)
-#define HAL_TLV_64_ALIGN 8
-
-struct hal_tlv_64_hdr {
- __le64 tl;
- u8 value[];
-} __packed;
-
#define RX_MPDU_DESC_INFO0_MSDU_COUNT GENMASK(7, 0)
#define RX_MPDU_DESC_INFO0_FRAG_FLAG BIT(8)
#define RX_MPDU_DESC_INFO0_MPDU_RETRY BIT(9)
@@ -820,35 +720,6 @@ struct rx_msdu_ext_desc {
* Set to the link ID of the PMAC that received the frame
*/
-enum hal_reo_dest_ring_buffer_type {
- HAL_REO_DEST_RING_BUFFER_TYPE_MSDU,
- HAL_REO_DEST_RING_BUFFER_TYPE_LINK_DESC,
-};
-
-enum hal_reo_dest_ring_push_reason {
- HAL_REO_DEST_RING_PUSH_REASON_ERR_DETECTED,
- HAL_REO_DEST_RING_PUSH_REASON_ROUTING_INSTRUCTION,
-};
-
-enum hal_reo_dest_ring_error_code {
- HAL_REO_DEST_RING_ERROR_CODE_DESC_ADDR_ZERO,
- HAL_REO_DEST_RING_ERROR_CODE_DESC_INVALID,
- HAL_REO_DEST_RING_ERROR_CODE_AMPDU_IN_NON_BA,
- HAL_REO_DEST_RING_ERROR_CODE_NON_BA_DUPLICATE,
- HAL_REO_DEST_RING_ERROR_CODE_BA_DUPLICATE,
- HAL_REO_DEST_RING_ERROR_CODE_FRAME_2K_JUMP,
- HAL_REO_DEST_RING_ERROR_CODE_BAR_2K_JUMP,
- HAL_REO_DEST_RING_ERROR_CODE_FRAME_OOR,
- HAL_REO_DEST_RING_ERROR_CODE_BAR_OOR,
- HAL_REO_DEST_RING_ERROR_CODE_NO_BA_SESSION,
- HAL_REO_DEST_RING_ERROR_CODE_FRAME_SN_EQUALS_SSN,
- HAL_REO_DEST_RING_ERROR_CODE_PN_CHECK_FAILED,
- HAL_REO_DEST_RING_ERROR_CODE_2K_ERR_FLAG_SET,
- HAL_REO_DEST_RING_ERROR_CODE_PN_ERR_FLAG_SET,
- HAL_REO_DEST_RING_ERROR_CODE_DESC_BLOCKED,
- HAL_REO_DEST_RING_ERROR_CODE_MAX,
-};
-
#define HAL_REO_DEST_RING_INFO0_BUFFER_TYPE BIT(0)
#define HAL_REO_DEST_RING_INFO0_PUSH_REASON GENMASK(2, 1)
#define HAL_REO_DEST_RING_INFO0_ERROR_CODE GENMASK(7, 3)
@@ -986,35 +857,6 @@ struct hal_reo_to_ppe_ring {
* More Segments followed
*/
-enum hal_reo_entr_rxdma_push_reason {
- HAL_REO_ENTR_RING_RXDMA_PUSH_REASON_ERR_DETECTED,
- HAL_REO_ENTR_RING_RXDMA_PUSH_REASON_ROUTING_INSTRUCTION,
- HAL_REO_ENTR_RING_RXDMA_PUSH_REASON_RX_FLUSH,
-};
-
-enum hal_reo_entr_rxdma_ecode {
- HAL_REO_ENTR_RING_RXDMA_ECODE_OVERFLOW_ERR,
- HAL_REO_ENTR_RING_RXDMA_ECODE_MPDU_LEN_ERR,
- HAL_REO_ENTR_RING_RXDMA_ECODE_FCS_ERR,
- HAL_REO_ENTR_RING_RXDMA_ECODE_DECRYPT_ERR,
- HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR,
- HAL_REO_ENTR_RING_RXDMA_ECODE_UNECRYPTED_ERR,
- HAL_REO_ENTR_RING_RXDMA_ECODE_MSDU_LEN_ERR,
- HAL_REO_ENTR_RING_RXDMA_ECODE_MSDU_LIMIT_ERR,
- HAL_REO_ENTR_RING_RXDMA_ECODE_WIFI_PARSE_ERR,
- HAL_REO_ENTR_RING_RXDMA_ECODE_AMSDU_PARSE_ERR,
- HAL_REO_ENTR_RING_RXDMA_ECODE_SA_TIMEOUT_ERR,
- HAL_REO_ENTR_RING_RXDMA_ECODE_DA_TIMEOUT_ERR,
- HAL_REO_ENTR_RING_RXDMA_ECODE_FLOW_TIMEOUT_ERR,
- HAL_REO_ENTR_RING_RXDMA_ECODE_FLUSH_REQUEST_ERR,
- HAL_REO_ENTR_RING_RXDMA_ECODE_AMSDU_FRAG_ERR,
- HAL_REO_ENTR_RING_RXDMA_ECODE_MULTICAST_ECHO_ERR,
- HAL_REO_ENTR_RING_RXDMA_ECODE_AMSDU_MISMATCH_ERR,
- HAL_REO_ENTR_RING_RXDMA_ECODE_UNAUTH_WDS_ERR,
- HAL_REO_ENTR_RING_RXDMA_ECODE_GRPCAST_AMSDU_WDS_ERR,
- HAL_REO_ENTR_RING_RXDMA_ECODE_MAX,
-};
-
enum hal_rx_reo_dest_ring {
HAL_RX_REO_DEST_RING_TCL,
HAL_RX_REO_DEST_RING_SW1,
@@ -1207,6 +1049,13 @@ struct hal_reo_get_queue_stats {
* Hole_count
*/
+struct hal_reo_get_queue_stats_qcc2072 {
+ struct hal_reo_cmd_hdr cmd;
+ __le32 queue_addr_lo;
+ __le32 info0;
+ __le32 rsvd0[6];
+} __packed;
+
#define HAL_REO_FLUSH_QUEUE_INFO0_DESC_ADDR_HI GENMASK(7, 0)
#define HAL_REO_FLUSH_QUEUE_INFO0_BLOCK_DESC_ADDR BIT(8)
#define HAL_REO_FLUSH_QUEUE_INFO0_BLOCK_RESRC_IDX GENMASK(10, 9)
@@ -1269,46 +1118,6 @@ struct hal_reo_flush_cache {
#define HAL_TCL_DATA_CMD_INFO5_RING_ID GENMASK(27, 20)
#define HAL_TCL_DATA_CMD_INFO5_LOOPING_COUNT GENMASK(31, 28)
-enum hal_encrypt_type {
- HAL_ENCRYPT_TYPE_WEP_40,
- HAL_ENCRYPT_TYPE_WEP_104,
- HAL_ENCRYPT_TYPE_TKIP_NO_MIC,
- HAL_ENCRYPT_TYPE_WEP_128,
- HAL_ENCRYPT_TYPE_TKIP_MIC,
- HAL_ENCRYPT_TYPE_WAPI,
- HAL_ENCRYPT_TYPE_CCMP_128,
- HAL_ENCRYPT_TYPE_OPEN,
- HAL_ENCRYPT_TYPE_CCMP_256,
- HAL_ENCRYPT_TYPE_GCMP_128,
- HAL_ENCRYPT_TYPE_AES_GCMP_256,
- HAL_ENCRYPT_TYPE_WAPI_GCM_SM4,
-};
-
-enum hal_tcl_encap_type {
- HAL_TCL_ENCAP_TYPE_RAW,
- HAL_TCL_ENCAP_TYPE_NATIVE_WIFI,
- HAL_TCL_ENCAP_TYPE_ETHERNET,
- HAL_TCL_ENCAP_TYPE_802_3 = 3,
- HAL_TCL_ENCAP_TYPE_MAX
-};
-
-enum hal_tcl_desc_type {
- HAL_TCL_DESC_TYPE_BUFFER,
- HAL_TCL_DESC_TYPE_EXT_DESC,
- HAL_TCL_DESC_TYPE_MAX,
-};
-
-enum hal_wbm_htt_tx_comp_status {
- HAL_WBM_REL_HTT_TX_COMP_STATUS_OK,
- HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP,
- HAL_WBM_REL_HTT_TX_COMP_STATUS_TTL,
- HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ,
- HAL_WBM_REL_HTT_TX_COMP_STATUS_INSPECT,
- HAL_WBM_REL_HTT_TX_COMP_STATUS_MEC_NOTIFY,
- HAL_WBM_REL_HTT_TX_COMP_STATUS_VDEVID_MISMATCH,
- HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX,
-};
-
struct hal_tcl_data_cmd {
struct ath12k_buffer_addr buf_addr_info;
__le32 info0;
@@ -1765,107 +1574,11 @@ struct hal_ce_srng_dst_status_desc {
#define HAL_TX_RATE_STATS_INFO0_OFDMA_TX BIT(16)
#define HAL_TX_RATE_STATS_INFO0_TONES_IN_RU GENMASK(28, 17)
-enum hal_tx_rate_stats_bw {
- HAL_TX_RATE_STATS_BW_20,
- HAL_TX_RATE_STATS_BW_40,
- HAL_TX_RATE_STATS_BW_80,
- HAL_TX_RATE_STATS_BW_160,
-};
-
-enum hal_tx_rate_stats_pkt_type {
- HAL_TX_RATE_STATS_PKT_TYPE_11A,
- HAL_TX_RATE_STATS_PKT_TYPE_11B,
- HAL_TX_RATE_STATS_PKT_TYPE_11N,
- HAL_TX_RATE_STATS_PKT_TYPE_11AC,
- HAL_TX_RATE_STATS_PKT_TYPE_11AX,
- HAL_TX_RATE_STATS_PKT_TYPE_11BA,
- HAL_TX_RATE_STATS_PKT_TYPE_11BE,
-};
-
-enum hal_tx_rate_stats_sgi {
- HAL_TX_RATE_STATS_SGI_08US,
- HAL_TX_RATE_STATS_SGI_04US,
- HAL_TX_RATE_STATS_SGI_16US,
- HAL_TX_RATE_STATS_SGI_32US,
-};
-
struct hal_tx_rate_stats {
__le32 info0;
__le32 tsf;
} __packed;
-struct hal_wbm_link_desc {
- struct ath12k_buffer_addr buf_addr_info;
-} __packed;
-
-/* hal_wbm_link_desc
- *
- * Producer: WBM
- * Consumer: WBM
- *
- * buf_addr_info
- * Details of the physical address of a buffer or MSDU
- * link descriptor.
- */
-
-enum hal_wbm_rel_src_module {
- HAL_WBM_REL_SRC_MODULE_TQM,
- HAL_WBM_REL_SRC_MODULE_RXDMA,
- HAL_WBM_REL_SRC_MODULE_REO,
- HAL_WBM_REL_SRC_MODULE_FW,
- HAL_WBM_REL_SRC_MODULE_SW,
- HAL_WBM_REL_SRC_MODULE_MAX,
-};
-
-enum hal_wbm_rel_desc_type {
- HAL_WBM_REL_DESC_TYPE_REL_MSDU,
- HAL_WBM_REL_DESC_TYPE_MSDU_LINK,
- HAL_WBM_REL_DESC_TYPE_MPDU_LINK,
- HAL_WBM_REL_DESC_TYPE_MSDU_EXT,
- HAL_WBM_REL_DESC_TYPE_QUEUE_EXT,
-};
-
-/* hal_wbm_rel_desc_type
- *
- * msdu_buffer
- * The address points to an MSDU buffer
- *
- * msdu_link_descriptor
- * The address points to an Tx MSDU link descriptor
- *
- * mpdu_link_descriptor
- * The address points to an MPDU link descriptor
- *
- * msdu_ext_descriptor
- * The address points to an MSDU extension descriptor
- *
- * queue_ext_descriptor
- * The address points to an TQM queue extension descriptor. WBM should
- * treat this is the same way as a link descriptor.
- */
-
-enum hal_wbm_rel_bm_act {
- HAL_WBM_REL_BM_ACT_PUT_IN_IDLE,
- HAL_WBM_REL_BM_ACT_REL_MSDU,
-};
-
-/* hal_wbm_rel_bm_act
- *
- * put_in_idle_list
- * Put the buffer or descriptor back in the idle list. In case of MSDU or
- * MDPU link descriptor, BM does not need to check to release any
- * individual MSDU buffers.
- *
- * release_msdu_list
- * This BM action can only be used in combination with desc_type being
- * msdu_link_descriptor. Field first_msdu_index points out which MSDU
- * pointer in the MSDU link descriptor is the first of an MPDU that is
- * released. BM shall release all the MSDU buffers linked to this first
- * MSDU buffer pointer. All related MSDU buffer pointer entries shall be
- * set to value 0, which represents the 'NULL' pointer. When all MSDU
- * buffer pointers in the MSDU link descriptor are 'NULL', the MSDU link
- * descriptor itself shall also be released.
- */
#define HAL_WBM_COMPL_RX_INFO0_REL_SRC_MODULE GENMASK(2, 0)
#define HAL_WBM_COMPL_RX_INFO0_BM_ACTION GENMASK(5, 3)
#define HAL_WBM_COMPL_RX_INFO0_DESC_TYPE GENMASK(8, 6)
@@ -2007,7 +1720,6 @@ struct hal_wbm_release_ring_cc_rx {
#define HAL_WBM_RELEASE_INFO3_CONTINUATION BIT(2)
#define HAL_WBM_RELEASE_INFO5_LOOPING_COUNT GENMASK(31, 28)
-#define HAL_ENCRYPT_TYPE_MAX 12
struct hal_wbm_release_ring {
struct ath12k_buffer_addr buf_addr_info;
@@ -2331,7 +2043,6 @@ enum hal_desc_buf_type {
#define HAL_DESC_REO_OWNED 4
#define HAL_DESC_REO_QUEUE_DESC 8
#define HAL_DESC_REO_QUEUE_EXT_DESC 9
-#define HAL_DESC_REO_NON_QOS_TID 16
#define HAL_DESC_HDR_INFO0_OWNER GENMASK(3, 0)
#define HAL_DESC_HDR_INFO0_BUF_TYPE GENMASK(7, 4)
@@ -2728,6 +2439,11 @@ struct hal_reo_get_queue_stats_status {
* entries into this Ring has looped around the ring.
*/
+struct hal_reo_get_queue_stats_status_qcc2072 {
+ __le32 tlv32_padding;
+ struct hal_reo_get_queue_stats_status status;
+} __packed;
+
#define HAL_REO_STATUS_LOOP_CNT GENMASK(31, 28)
#define HAL_REO_FLUSH_QUEUE_INFO0_ERR_DETECTED BIT(0)
@@ -2957,25 +2673,6 @@ struct hal_tcl_entrance_from_ppe_ring {
__le32 info0;
} __packed;
-struct hal_mon_buf_ring {
- __le32 paddr_lo;
- __le32 paddr_hi;
- __le64 cookie;
-};
-
-/* hal_mon_buf_ring
- * Producer : SW
- * Consumer : Monitor
- *
- * paddr_lo
- * Lower 32-bit physical address of the buffer pointer from the source ring.
- * paddr_hi
- * bit range 7-0 : upper 8 bit of the physical address.
- * bit range 31-8 : reserved.
- * cookie
- * Consumer: RxMon/TxMon 64 bit cookie of the buffers.
- */
-
#define HAL_MON_DEST_COOKIE_BUF_ID GENMASK(17, 0)
#define HAL_MON_DEST_INFO0_END_OFFSET GENMASK(11, 0)
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c
new file mode 100644
index 000000000000..1eefb931a853
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c
@@ -0,0 +1,503 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include "hal_qcc2072.h"
+#include "hal_wcn7850.h"
+
+const struct ath12k_hw_regs qcc2072_regs = {
+ /* SW2TCL(x) R0 ring configuration address */
+ .tcl1_ring_id = 0x00000920,
+ .tcl1_ring_misc = 0x00000928,
+ .tcl1_ring_tp_addr_lsb = 0x00000934,
+ .tcl1_ring_tp_addr_msb = 0x00000938,
+ .tcl1_ring_consumer_int_setup_ix0 = 0x00000948,
+ .tcl1_ring_consumer_int_setup_ix1 = 0x0000094c,
+ .tcl1_ring_msi1_base_lsb = 0x00000960,
+ .tcl1_ring_msi1_base_msb = 0x00000964,
+ .tcl1_ring_msi1_data = 0x00000968,
+ .tcl_ring_base_lsb = 0x00000b70,
+ .tcl1_ring_base_lsb = 0x00000918,
+ .tcl1_ring_base_msb = 0x0000091c,
+ .tcl2_ring_base_lsb = 0x00000990,
+
+ /* TCL STATUS ring address */
+ .tcl_status_ring_base_lsb = 0x00000d50,
+
+ .wbm_idle_ring_base_lsb = 0x00000d3c,
+ .wbm_idle_ring_misc_addr = 0x00000d4c,
+ .wbm_r0_idle_list_cntl_addr = 0x00000240,
+ .wbm_r0_idle_list_size_addr = 0x00000244,
+ .wbm_scattered_ring_base_lsb = 0x00000250,
+ .wbm_scattered_ring_base_msb = 0x00000254,
+ .wbm_scattered_desc_head_info_ix0 = 0x00000260,
+ .wbm_scattered_desc_head_info_ix1 = 0x00000264,
+ .wbm_scattered_desc_tail_info_ix0 = 0x00000270,
+ .wbm_scattered_desc_tail_info_ix1 = 0x00000274,
+ .wbm_scattered_desc_ptr_hp_addr = 0x00000027c,
+
+ .wbm_sw_release_ring_base_lsb = 0x0000037c,
+ .wbm_sw1_release_ring_base_lsb = ATH12K_HW_REG_UNDEFINED,
+ .wbm0_release_ring_base_lsb = 0x00000e08,
+ .wbm1_release_ring_base_lsb = 0x00000e80,
+
+ /* PCIe base address */
+ .pcie_qserdes_sysclk_en_sel = 0x01e0c0ac,
+ .pcie_pcs_osc_dtct_config_base = 0x01e0cc58,
+
+ /* PPE release ring address */
+ .ppe_rel_ring_base = 0x0000046c,
+
+ /* REO DEST ring address */
+ .reo2_ring_base = 0x00000578,
+ .reo1_misc_ctrl_addr = 0x00000ba0,
+ .reo1_sw_cookie_cfg0 = 0x0000006c,
+ .reo1_sw_cookie_cfg1 = 0x00000070,
+ .reo1_qdesc_lut_base0 = ATH12K_HW_REG_UNDEFINED,
+ .reo1_qdesc_lut_base1 = ATH12K_HW_REG_UNDEFINED,
+
+ .reo1_ring_base_lsb = 0x00000500,
+ .reo1_ring_base_msb = 0x00000504,
+ .reo1_ring_id = 0x00000508,
+ .reo1_ring_misc = 0x00000510,
+ .reo1_ring_hp_addr_lsb = 0x00000514,
+ .reo1_ring_hp_addr_msb = 0x00000518,
+ .reo1_ring_producer_int_setup = 0x00000524,
+ .reo1_ring_msi1_base_lsb = 0x00000548,
+ .reo1_ring_msi1_base_msb = 0x0000054c,
+ .reo1_ring_msi1_data = 0x00000550,
+ .reo1_aging_thres_ix0 = 0x00000b2c,
+ .reo1_aging_thres_ix1 = 0x00000b30,
+ .reo1_aging_thres_ix2 = 0x00000b34,
+ .reo1_aging_thres_ix3 = 0x00000b38,
+
+ /* REO Exception ring address */
+ .reo2_sw0_ring_base = 0x000008c0,
+
+ /* REO Reinject ring address */
+ .sw2reo_ring_base = 0x00000320,
+ .sw2reo1_ring_base = 0x00000398,
+
+ /* REO cmd ring address */
+ .reo_cmd_ring_base = 0x000002a8,
+
+ /* REO status ring address */
+ .reo_status_ring_base = 0x00000aa0,
+
+ /* CE base address */
+ .umac_ce0_src_reg_base = 0x01b80000,
+ .umac_ce0_dest_reg_base = 0x01b81000,
+ .umac_ce1_src_reg_base = 0x01b82000,
+ .umac_ce1_dest_reg_base = 0x01b83000,
+
+ .gcc_gcc_pcie_hot_rst = 0x1e65304,
+
+ .qrtr_node_id = 0x1e03300,
+};
+
+static void ath12k_hal_rx_desc_set_msdu_len_qcc2072(struct hal_rx_desc *desc, u16 len)
+{
+ u32 info = __le32_to_cpu(desc->u.qcc2072.msdu_end.info10);
+
+ info &= ~RX_MSDU_END_INFO10_MSDU_LENGTH;
+ info |= u32_encode_bits(len, RX_MSDU_END_INFO10_MSDU_LENGTH);
+
+ desc->u.qcc2072.msdu_end.info10 = __cpu_to_le32(info);
+}
+
+static void ath12k_hal_rx_desc_get_dot11_hdr_qcc2072(struct hal_rx_desc *desc,
+ struct ieee80211_hdr *hdr)
+{
+ hdr->frame_control = desc->u.qcc2072.mpdu_start.frame_ctrl;
+ hdr->duration_id = desc->u.qcc2072.mpdu_start.duration;
+ ether_addr_copy(hdr->addr1, desc->u.qcc2072.mpdu_start.addr1);
+ ether_addr_copy(hdr->addr2, desc->u.qcc2072.mpdu_start.addr2);
+ ether_addr_copy(hdr->addr3, desc->u.qcc2072.mpdu_start.addr3);
+
+ if (__le32_to_cpu(desc->u.qcc2072.mpdu_start.info4) &
+ RX_MPDU_START_INFO4_MAC_ADDR4_VALID)
+ ether_addr_copy(hdr->addr4, desc->u.qcc2072.mpdu_start.addr4);
+
+ hdr->seq_ctrl = desc->u.qcc2072.mpdu_start.seq_ctrl;
+}
+
+static void ath12k_hal_rx_desc_get_crypto_hdr_qcc2072(struct hal_rx_desc *desc,
+ u8 *crypto_hdr,
+ enum hal_encrypt_type enctype)
+{
+ unsigned int key_id;
+
+ switch (enctype) {
+ case HAL_ENCRYPT_TYPE_OPEN:
+ return;
+ case HAL_ENCRYPT_TYPE_TKIP_NO_MIC:
+ case HAL_ENCRYPT_TYPE_TKIP_MIC:
+ crypto_hdr[0] =
+ HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.qcc2072.mpdu_start.pn[0]);
+ crypto_hdr[1] = 0;
+ crypto_hdr[2] =
+ HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.qcc2072.mpdu_start.pn[0]);
+ break;
+ case HAL_ENCRYPT_TYPE_CCMP_128:
+ case HAL_ENCRYPT_TYPE_CCMP_256:
+ case HAL_ENCRYPT_TYPE_GCMP_128:
+ case HAL_ENCRYPT_TYPE_AES_GCMP_256:
+ crypto_hdr[0] =
+ HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.qcc2072.mpdu_start.pn[0]);
+ crypto_hdr[1] =
+ HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.qcc2072.mpdu_start.pn[0]);
+ crypto_hdr[2] = 0;
+ break;
+ case HAL_ENCRYPT_TYPE_WEP_40:
+ case HAL_ENCRYPT_TYPE_WEP_104:
+ case HAL_ENCRYPT_TYPE_WEP_128:
+ case HAL_ENCRYPT_TYPE_WAPI_GCM_SM4:
+ case HAL_ENCRYPT_TYPE_WAPI:
+ return;
+ }
+
+ key_id = u32_get_bits(__le32_to_cpu(desc->u.qcc2072.mpdu_start.info5),
+ RX_MPDU_START_INFO5_KEY_ID);
+ crypto_hdr[3] = 0x20 | (key_id << 6);
+ crypto_hdr[4] = HAL_RX_MPDU_INFO_PN_GET_BYTE3(desc->u.qcc2072.mpdu_start.pn[0]);
+ crypto_hdr[5] = HAL_RX_MPDU_INFO_PN_GET_BYTE4(desc->u.qcc2072.mpdu_start.pn[0]);
+ crypto_hdr[6] = HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.qcc2072.mpdu_start.pn[1]);
+ crypto_hdr[7] = HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.qcc2072.mpdu_start.pn[1]);
+}
+
+static void ath12k_hal_rx_desc_copy_end_tlv_qcc2072(struct hal_rx_desc *fdesc,
+ struct hal_rx_desc *ldesc)
+{
+ memcpy(&fdesc->u.qcc2072.msdu_end, &ldesc->u.qcc2072.msdu_end,
+ sizeof(struct rx_msdu_end_qcn9274));
+}
+
+static u8 ath12k_hal_rx_desc_get_msdu_src_link_qcc2072(struct hal_rx_desc *desc)
+{
+ return 0;
+}
+
+static u8 ath12k_hal_rx_desc_get_l3_pad_bytes_qcc2072(struct hal_rx_desc *desc)
+{
+ return le16_get_bits(desc->u.qcc2072.msdu_end.info5,
+ RX_MSDU_END_INFO5_L3_HDR_PADDING);
+}
+
+static u32 ath12k_hal_rx_desc_get_mpdu_start_tag_qcc2072(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.qcc2072.mpdu_start_tag,
+ HAL_TLV_HDR_TAG);
+}
+
+static u32 ath12k_hal_rx_desc_get_mpdu_ppdu_id_qcc2072(struct hal_rx_desc *desc)
+{
+ return __le16_to_cpu(desc->u.qcc2072.mpdu_start.phy_ppdu_id);
+}
+
+static u8 *ath12k_hal_rx_desc_get_msdu_payload_qcc2072(struct hal_rx_desc *desc)
+{
+ return &desc->u.qcc2072.msdu_payload[0];
+}
+
+static bool ath12k_hal_rx_desc_get_first_msdu_qcc2072(struct hal_rx_desc *desc)
+{
+ return !!le16_get_bits(desc->u.qcc2072.msdu_end.info5,
+ RX_MSDU_END_INFO5_FIRST_MSDU);
+}
+
+static bool ath12k_hal_rx_desc_get_last_msdu_qcc2072(struct hal_rx_desc *desc)
+{
+ return !!le16_get_bits(desc->u.qcc2072.msdu_end.info5,
+ RX_MSDU_END_INFO5_LAST_MSDU);
+}
+
+static bool ath12k_hal_rx_desc_encrypt_valid_qcc2072(struct hal_rx_desc *desc)
+{
+ return !!le32_get_bits(desc->u.qcc2072.mpdu_start.info4,
+ RX_MPDU_START_INFO4_ENCRYPT_INFO_VALID);
+}
+
+static u32 ath12k_hal_rx_desc_get_encrypt_type_qcc2072(struct hal_rx_desc *desc)
+{
+ if (!ath12k_hal_rx_desc_encrypt_valid_qcc2072(desc))
+ return HAL_ENCRYPT_TYPE_OPEN;
+
+ return le32_get_bits(desc->u.qcc2072.mpdu_start.info2,
+ RX_MPDU_START_INFO2_ENC_TYPE);
+}
+
+static u8 ath12k_hal_rx_desc_get_decap_type_qcc2072(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.qcc2072.msdu_end.info11,
+ RX_MSDU_END_INFO11_DECAP_FORMAT);
+}
+
+static u8 ath12k_hal_rx_desc_get_mesh_ctl_qcc2072(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.qcc2072.msdu_end.info11,
+ RX_MSDU_END_INFO11_MESH_CTRL_PRESENT);
+}
+
+static bool ath12k_hal_rx_desc_get_mpdu_seq_ctl_vld_qcc2072(struct hal_rx_desc *desc)
+{
+ return !!le32_get_bits(desc->u.qcc2072.mpdu_start.info4,
+ RX_MPDU_START_INFO4_MPDU_SEQ_CTRL_VALID);
+}
+
+static bool ath12k_hal_rx_desc_get_mpdu_fc_valid_qcc2072(struct hal_rx_desc *desc)
+{
+ return !!le32_get_bits(desc->u.qcc2072.mpdu_start.info4,
+ RX_MPDU_START_INFO4_MPDU_FCTRL_VALID);
+}
+
+static u16 ath12k_hal_rx_desc_get_mpdu_start_seq_no_qcc2072(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.qcc2072.mpdu_start.info4,
+ RX_MPDU_START_INFO4_MPDU_SEQ_NUM);
+}
+
+static u16 ath12k_hal_rx_desc_get_msdu_len_qcc2072(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.qcc2072.msdu_end.info10,
+ RX_MSDU_END_INFO10_MSDU_LENGTH);
+}
+
+static u8 ath12k_hal_rx_desc_get_msdu_sgi_qcc2072(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.qcc2072.msdu_end.info12,
+ RX_MSDU_END_INFO12_SGI);
+}
+
+static u8 ath12k_hal_rx_desc_get_msdu_rate_mcs_qcc2072(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.qcc2072.msdu_end.info12,
+ RX_MSDU_END_INFO12_RATE_MCS);
+}
+
+static u8 ath12k_hal_rx_desc_get_msdu_rx_bw_qcc2072(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.qcc2072.msdu_end.info12,
+ RX_MSDU_END_INFO12_RECV_BW);
+}
+
+static u32 ath12k_hal_rx_desc_get_msdu_freq_qcc2072(struct hal_rx_desc *desc)
+{
+ return __le32_to_cpu(desc->u.qcc2072.msdu_end.phy_meta_data);
+}
+
+static u8 ath12k_hal_rx_desc_get_msdu_pkt_type_qcc2072(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.qcc2072.msdu_end.info12,
+ RX_MSDU_END_INFO12_PKT_TYPE);
+}
+
+static u8 ath12k_hal_rx_desc_get_msdu_nss_qcc2072(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.qcc2072.msdu_end.info12,
+ RX_MSDU_END_INFO12_MIMO_SS_BITMAP);
+}
+
+static u8 ath12k_hal_rx_desc_get_mpdu_tid_qcc2072(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.qcc2072.mpdu_start.info2,
+ RX_MPDU_START_INFO2_TID);
+}
+
+static u16 ath12k_hal_rx_desc_get_mpdu_peer_id_qcc2072(struct hal_rx_desc *desc)
+{
+ return __le16_to_cpu(desc->u.qcc2072.mpdu_start.sw_peer_id);
+}
+
+static bool ath12k_hal_rx_desc_mac_addr2_valid_qcc2072(struct hal_rx_desc *desc)
+{
+ return __le32_to_cpu(desc->u.qcc2072.mpdu_start.info4) &
+ RX_MPDU_START_INFO4_MAC_ADDR2_VALID;
+}
+
+static u8 *ath12k_hal_rx_desc_mpdu_start_addr2_qcc2072(struct hal_rx_desc *desc)
+{
+ return desc->u.qcc2072.mpdu_start.addr2;
+}
+
+static bool ath12k_hal_rx_desc_is_da_mcbc_qcc2072(struct hal_rx_desc *desc)
+{
+ return __le32_to_cpu(desc->u.qcc2072.msdu_end.info13) &
+ RX_MSDU_END_INFO13_MCAST_BCAST;
+}
+
+static bool ath12k_hal_rx_h_msdu_done_qcc2072(struct hal_rx_desc *desc)
+{
+ return !!le32_get_bits(desc->u.qcc2072.msdu_end.info14,
+ RX_MSDU_END_INFO14_MSDU_DONE);
+}
+
+static bool ath12k_hal_rx_h_l4_cksum_fail_qcc2072(struct hal_rx_desc *desc)
+{
+ return !!le32_get_bits(desc->u.qcc2072.msdu_end.info13,
+ RX_MSDU_END_INFO13_TCP_UDP_CKSUM_FAIL);
+}
+
+static bool ath12k_hal_rx_h_ip_cksum_fail_qcc2072(struct hal_rx_desc *desc)
+{
+ return !!le32_get_bits(desc->u.qcc2072.msdu_end.info13,
+ RX_MSDU_END_INFO13_IP_CKSUM_FAIL);
+}
+
+static bool ath12k_hal_rx_h_is_decrypted_qcc2072(struct hal_rx_desc *desc)
+{
+ return (le32_get_bits(desc->u.qcc2072.msdu_end.info14,
+ RX_MSDU_END_INFO14_DECRYPT_STATUS_CODE) ==
+ RX_DESC_DECRYPT_STATUS_CODE_OK);
+}
+
+static u32 ath12k_hal_rx_h_mpdu_err_qcc2072(struct hal_rx_desc *desc)
+{
+ u32 info = __le32_to_cpu(desc->u.qcc2072.msdu_end.info13);
+ u32 errmap = 0;
+
+ if (info & RX_MSDU_END_INFO13_FCS_ERR)
+ errmap |= HAL_RX_MPDU_ERR_FCS;
+
+ if (info & RX_MSDU_END_INFO13_DECRYPT_ERR)
+ errmap |= HAL_RX_MPDU_ERR_DECRYPT;
+
+ if (info & RX_MSDU_END_INFO13_TKIP_MIC_ERR)
+ errmap |= HAL_RX_MPDU_ERR_TKIP_MIC;
+
+ if (info & RX_MSDU_END_INFO13_A_MSDU_ERROR)
+ errmap |= HAL_RX_MPDU_ERR_AMSDU_ERR;
+
+ if (info & RX_MSDU_END_INFO13_OVERFLOW_ERR)
+ errmap |= HAL_RX_MPDU_ERR_OVERFLOW;
+
+ if (info & RX_MSDU_END_INFO13_MSDU_LEN_ERR)
+ errmap |= HAL_RX_MPDU_ERR_MSDU_LEN;
+
+ if (info & RX_MSDU_END_INFO13_MPDU_LEN_ERR)
+ errmap |= HAL_RX_MPDU_ERR_MPDU_LEN;
+
+ return errmap;
+}
+
+static void ath12k_hal_extract_rx_desc_data_qcc2072(struct hal_rx_desc_data *rx_desc_data,
+ struct hal_rx_desc *rx_desc,
+ struct hal_rx_desc *ldesc)
+{
+ rx_desc_data->is_first_msdu = ath12k_hal_rx_desc_get_first_msdu_qcc2072(ldesc);
+ rx_desc_data->is_last_msdu = ath12k_hal_rx_desc_get_last_msdu_qcc2072(ldesc);
+ rx_desc_data->l3_pad_bytes = ath12k_hal_rx_desc_get_l3_pad_bytes_qcc2072(ldesc);
+ rx_desc_data->enctype = ath12k_hal_rx_desc_get_encrypt_type_qcc2072(rx_desc);
+ rx_desc_data->decap_type = ath12k_hal_rx_desc_get_decap_type_qcc2072(rx_desc);
+ rx_desc_data->mesh_ctrl_present =
+ ath12k_hal_rx_desc_get_mesh_ctl_qcc2072(rx_desc);
+ rx_desc_data->seq_ctl_valid =
+ ath12k_hal_rx_desc_get_mpdu_seq_ctl_vld_qcc2072(rx_desc);
+ rx_desc_data->fc_valid = ath12k_hal_rx_desc_get_mpdu_fc_valid_qcc2072(rx_desc);
+ rx_desc_data->seq_no = ath12k_hal_rx_desc_get_mpdu_start_seq_no_qcc2072(rx_desc);
+ rx_desc_data->msdu_len = ath12k_hal_rx_desc_get_msdu_len_qcc2072(ldesc);
+ rx_desc_data->sgi = ath12k_hal_rx_desc_get_msdu_sgi_qcc2072(rx_desc);
+ rx_desc_data->rate_mcs = ath12k_hal_rx_desc_get_msdu_rate_mcs_qcc2072(rx_desc);
+ rx_desc_data->bw = ath12k_hal_rx_desc_get_msdu_rx_bw_qcc2072(rx_desc);
+ rx_desc_data->phy_meta_data = ath12k_hal_rx_desc_get_msdu_freq_qcc2072(rx_desc);
+ rx_desc_data->pkt_type = ath12k_hal_rx_desc_get_msdu_pkt_type_qcc2072(rx_desc);
+ rx_desc_data->nss = hweight8(ath12k_hal_rx_desc_get_msdu_nss_qcc2072(rx_desc));
+ rx_desc_data->tid = ath12k_hal_rx_desc_get_mpdu_tid_qcc2072(rx_desc);
+ rx_desc_data->peer_id = ath12k_hal_rx_desc_get_mpdu_peer_id_qcc2072(rx_desc);
+ rx_desc_data->addr2_present = ath12k_hal_rx_desc_mac_addr2_valid_qcc2072(rx_desc);
+ rx_desc_data->addr2 = ath12k_hal_rx_desc_mpdu_start_addr2_qcc2072(rx_desc);
+ rx_desc_data->is_mcbc = ath12k_hal_rx_desc_is_da_mcbc_qcc2072(rx_desc);
+ rx_desc_data->msdu_done = ath12k_hal_rx_h_msdu_done_qcc2072(ldesc);
+ rx_desc_data->l4_csum_fail = ath12k_hal_rx_h_l4_cksum_fail_qcc2072(rx_desc);
+ rx_desc_data->ip_csum_fail = ath12k_hal_rx_h_ip_cksum_fail_qcc2072(rx_desc);
+ rx_desc_data->is_decrypted = ath12k_hal_rx_h_is_decrypted_qcc2072(rx_desc);
+ rx_desc_data->err_bitmap = ath12k_hal_rx_h_mpdu_err_qcc2072(rx_desc);
+}
+
+static int ath12k_hal_srng_create_config_qcc2072(struct ath12k_hal *hal)
+{
+ struct hal_srng_config *s;
+ int ret;
+
+ ret = ath12k_hal_srng_create_config_wcn7850(hal);
+ if (ret)
+ return ret;
+
+ s = &hal->srng_config[HAL_REO_CMD];
+ s->entry_size = (sizeof(struct hal_tlv_hdr) +
+ sizeof(struct hal_reo_get_queue_stats_qcc2072)) >> 2;
+
+ s = &hal->srng_config[HAL_REO_STATUS];
+ s->entry_size = (sizeof(struct hal_tlv_hdr) +
+ sizeof(struct hal_reo_get_queue_stats_status_qcc2072)) >> 2;
+
+ return 0;
+}
+
+static u16 ath12k_hal_reo_status_dec_tlv_hdr_qcc2072(void *tlv, void **desc)
+{
+ struct hal_reo_get_queue_stats_status_qcc2072 *status_tlv;
+ u16 tag;
+
+ tag = ath12k_hal_decode_tlv32_hdr(tlv, (void **)&status_tlv);
+ /*
+ * actual desc of REO status entry starts after tlv32_padding,
+ * see hal_reo_get_queue_stats_status_qcc2072
+ */
+ *desc = &status_tlv->status;
+
+ return tag;
+}
+
+const struct hal_ops hal_qcc2072_ops = {
+ .create_srng_config = ath12k_hal_srng_create_config_qcc2072,
+ .rx_desc_set_msdu_len = ath12k_hal_rx_desc_set_msdu_len_qcc2072,
+ .rx_desc_get_dot11_hdr = ath12k_hal_rx_desc_get_dot11_hdr_qcc2072,
+ .rx_desc_get_crypto_header = ath12k_hal_rx_desc_get_crypto_hdr_qcc2072,
+ .rx_desc_copy_end_tlv = ath12k_hal_rx_desc_copy_end_tlv_qcc2072,
+ .rx_desc_get_msdu_src_link_id = ath12k_hal_rx_desc_get_msdu_src_link_qcc2072,
+ .extract_rx_desc_data = ath12k_hal_extract_rx_desc_data_qcc2072,
+ .rx_desc_get_l3_pad_bytes = ath12k_hal_rx_desc_get_l3_pad_bytes_qcc2072,
+ .rx_desc_get_mpdu_start_tag = ath12k_hal_rx_desc_get_mpdu_start_tag_qcc2072,
+ .rx_desc_get_mpdu_ppdu_id = ath12k_hal_rx_desc_get_mpdu_ppdu_id_qcc2072,
+ .rx_desc_get_msdu_payload = ath12k_hal_rx_desc_get_msdu_payload_qcc2072,
+ .ce_dst_setup = ath12k_wifi7_hal_ce_dst_setup,
+ .srng_src_hw_init = ath12k_wifi7_hal_srng_src_hw_init,
+ .srng_dst_hw_init = ath12k_wifi7_hal_srng_dst_hw_init,
+ .set_umac_srng_ptr_addr = ath12k_wifi7_hal_set_umac_srng_ptr_addr,
+ .srng_update_shadow_config = ath12k_wifi7_hal_srng_update_shadow_config,
+ .srng_get_ring_id = ath12k_wifi7_hal_srng_get_ring_id,
+ .ce_get_desc_size = ath12k_wifi7_hal_ce_get_desc_size,
+ .ce_src_set_desc = ath12k_wifi7_hal_ce_src_set_desc,
+ .ce_dst_set_desc = ath12k_wifi7_hal_ce_dst_set_desc,
+ .ce_dst_status_get_length = ath12k_wifi7_hal_ce_dst_status_get_length,
+ .set_link_desc_addr = ath12k_wifi7_hal_set_link_desc_addr,
+ .tx_set_dscp_tid_map = ath12k_wifi7_hal_tx_set_dscp_tid_map,
+ .tx_configure_bank_register =
+ ath12k_wifi7_hal_tx_configure_bank_register,
+ .reoq_lut_addr_read_enable = ath12k_wifi7_hal_reoq_lut_addr_read_enable,
+ .reoq_lut_set_max_peerid = ath12k_wifi7_hal_reoq_lut_set_max_peerid,
+ .write_reoq_lut_addr = ath12k_wifi7_hal_write_reoq_lut_addr,
+ .write_ml_reoq_lut_addr = ath12k_wifi7_hal_write_ml_reoq_lut_addr,
+ .setup_link_idle_list = ath12k_wifi7_hal_setup_link_idle_list,
+ .reo_init_cmd_ring = ath12k_wifi7_hal_reo_init_cmd_ring_tlv32,
+ .reo_hw_setup = ath12k_wifi7_hal_reo_hw_setup,
+ .rx_buf_addr_info_set = ath12k_wifi7_hal_rx_buf_addr_info_set,
+ .rx_buf_addr_info_get = ath12k_wifi7_hal_rx_buf_addr_info_get,
+ .cc_config = ath12k_wifi7_hal_cc_config,
+ .get_idle_link_rbm = ath12k_wifi7_hal_get_idle_link_rbm,
+ .rx_msdu_list_get = ath12k_wifi7_hal_rx_msdu_list_get,
+ .rx_reo_ent_buf_paddr_get = ath12k_wifi7_hal_rx_reo_ent_buf_paddr_get,
+ .reo_cmd_enc_tlv_hdr = ath12k_hal_encode_tlv32_hdr,
+ .reo_status_dec_tlv_hdr = ath12k_hal_reo_status_dec_tlv_hdr_qcc2072,
+};
+
+u32 ath12k_hal_rx_desc_get_mpdu_start_offset_qcc2072(void)
+{
+ return offsetof(struct hal_rx_desc_qcc2072, mpdu_start_tag);
+}
+
+u32 ath12k_hal_rx_desc_get_msdu_end_offset_qcc2072(void)
+{
+ return offsetof(struct hal_rx_desc_qcc2072, msdu_end_tag);
+}
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.h b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.h
new file mode 100644
index 000000000000..6de943df7786
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include "../hal.h"
+#include "hal.h"
+
+extern const struct ath12k_hw_regs qcc2072_regs;
+extern const struct hal_ops hal_qcc2072_ops;
+
+u32 ath12k_hal_rx_desc_get_mpdu_start_offset_qcc2072(void);
+u32 ath12k_hal_rx_desc_get_msdu_end_offset_qcc2072(void);
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c
new file mode 100644
index 000000000000..41c918eb1767
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c
@@ -0,0 +1,1038 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+#include "hal_desc.h"
+#include "hal_qcn9274.h"
+#include "hw.h"
+#include "hal.h"
+#include "hal_tx.h"
+
+static const struct hal_srng_config hw_srng_config_template[] = {
+ /* TODO: max_rings can populated by querying HW capabilities */
+ [HAL_REO_DST] = {
+ .start_ring_id = HAL_SRNG_RING_ID_REO2SW1,
+ .max_rings = 8,
+ .entry_size = sizeof(struct hal_reo_dest_ring) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_DST,
+ .max_size = HAL_REO_REO2SW1_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_REO_EXCEPTION] = {
+ /* Designating REO2SW0 ring as exception ring.
+ * Any of theREO2SW rings can be used as exception ring.
+ */
+ .start_ring_id = HAL_SRNG_RING_ID_REO2SW0,
+ .max_rings = 1,
+ .entry_size = sizeof(struct hal_reo_dest_ring) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_DST,
+ .max_size = HAL_REO_REO2SW0_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_REO_REINJECT] = {
+ .start_ring_id = HAL_SRNG_RING_ID_SW2REO,
+ .max_rings = 4,
+ .entry_size = sizeof(struct hal_reo_entrance_ring) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_REO_SW2REO_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_REO_CMD] = {
+ .start_ring_id = HAL_SRNG_RING_ID_REO_CMD,
+ .max_rings = 1,
+ .entry_size = (sizeof(struct hal_tlv_64_hdr) +
+ sizeof(struct hal_reo_get_queue_stats)) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_REO_CMD_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_REO_STATUS] = {
+ .start_ring_id = HAL_SRNG_RING_ID_REO_STATUS,
+ .max_rings = 1,
+ .entry_size = (sizeof(struct hal_tlv_64_hdr) +
+ sizeof(struct hal_reo_get_queue_stats_status)) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_DST,
+ .max_size = HAL_REO_STATUS_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_TCL_DATA] = {
+ .start_ring_id = HAL_SRNG_RING_ID_SW2TCL1,
+ .max_rings = 6,
+ .entry_size = sizeof(struct hal_tcl_data_cmd) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_SW2TCL1_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_TCL_CMD] = {
+ .start_ring_id = HAL_SRNG_RING_ID_SW2TCL_CMD,
+ .max_rings = 1,
+ .entry_size = sizeof(struct hal_tcl_gse_cmd) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_SW2TCL1_CMD_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_TCL_STATUS] = {
+ .start_ring_id = HAL_SRNG_RING_ID_TCL_STATUS,
+ .max_rings = 1,
+ .entry_size = (sizeof(struct hal_tlv_hdr) +
+ sizeof(struct hal_tcl_status_ring)) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_DST,
+ .max_size = HAL_TCL_STATUS_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_CE_SRC] = {
+ .start_ring_id = HAL_SRNG_RING_ID_CE0_SRC,
+ .max_rings = 16,
+ .entry_size = sizeof(struct hal_ce_srng_src_desc) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_CE_SRC_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_CE_DST] = {
+ .start_ring_id = HAL_SRNG_RING_ID_CE0_DST,
+ .max_rings = 16,
+ .entry_size = sizeof(struct hal_ce_srng_dest_desc) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_CE_DST_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_CE_DST_STATUS] = {
+ .start_ring_id = HAL_SRNG_RING_ID_CE0_DST_STATUS,
+ .max_rings = 16,
+ .entry_size = sizeof(struct hal_ce_srng_dst_status_desc) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_DST,
+ .max_size = HAL_CE_DST_STATUS_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_WBM_IDLE_LINK] = {
+ .start_ring_id = HAL_SRNG_RING_ID_WBM_IDLE_LINK,
+ .max_rings = 1,
+ .entry_size = sizeof(struct hal_wbm_link_desc) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_WBM_IDLE_LINK_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_SW2WBM_RELEASE] = {
+ .start_ring_id = HAL_SRNG_RING_ID_WBM_SW0_RELEASE,
+ .max_rings = 2,
+ .entry_size = sizeof(struct hal_wbm_release_ring) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_SW2WBM_RELEASE_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_WBM2SW_RELEASE] = {
+ .start_ring_id = HAL_SRNG_RING_ID_WBM2SW0_RELEASE,
+ .max_rings = 8,
+ .entry_size = sizeof(struct hal_wbm_release_ring) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_DST,
+ .max_size = HAL_WBM2SW_RELEASE_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_RXDMA_BUF] = {
+ .start_ring_id = HAL_SRNG_SW2RXDMA_BUF0,
+ .max_rings = 1,
+ .entry_size = sizeof(struct hal_wbm_buffer_ring) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_DMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_RXDMA_RING_MAX_SIZE_BE,
+ },
+ [HAL_RXDMA_DST] = {
+ .start_ring_id = HAL_SRNG_RING_ID_WMAC1_RXDMA2SW0,
+ .max_rings = 0,
+ .entry_size = 0,
+ .mac_type = ATH12K_HAL_SRNG_PMAC,
+ .ring_dir = HAL_SRNG_DIR_DST,
+ .max_size = HAL_RXDMA_RING_MAX_SIZE_BE,
+ },
+ [HAL_RXDMA_MONITOR_BUF] = {
+ .start_ring_id = HAL_SRNG_SW2RXMON_BUF0,
+ .max_rings = 1,
+ .entry_size = sizeof(struct hal_mon_buf_ring) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_PMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_RXDMA_RING_MAX_SIZE_BE,
+ },
+ [HAL_RXDMA_MONITOR_STATUS] = {
+ .start_ring_id = HAL_SRNG_RING_ID_WMAC1_SW2RXDMA1_STATBUF,
+ .max_rings = 1,
+ .entry_size = sizeof(struct hal_wbm_buffer_ring) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_PMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_RXDMA_RING_MAX_SIZE_BE,
+ },
+ [HAL_RXDMA_MONITOR_DESC] = { 0, },
+ [HAL_RXDMA_DIR_BUF] = {
+ .start_ring_id = HAL_SRNG_RING_ID_RXDMA_DIR_BUF,
+ .max_rings = 2,
+ .entry_size = 8 >> 2, /* TODO: Define the struct */
+ .mac_type = ATH12K_HAL_SRNG_PMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_RXDMA_RING_MAX_SIZE_BE,
+ },
+ [HAL_PPE2TCL] = {
+ .start_ring_id = HAL_SRNG_RING_ID_PPE2TCL1,
+ .max_rings = 1,
+ .entry_size = sizeof(struct hal_tcl_entrance_from_ppe_ring) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_PMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_SW2TCL1_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_PPE_RELEASE] = {
+ .start_ring_id = HAL_SRNG_RING_ID_WBM_PPE_RELEASE,
+ .max_rings = 1,
+ .entry_size = sizeof(struct hal_wbm_release_ring) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_PMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_WBM2PPE_RELEASE_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_TX_MONITOR_BUF] = {
+ .start_ring_id = HAL_SRNG_RING_ID_WMAC1_SW2TXMON_BUF0,
+ .max_rings = 1,
+ .entry_size = sizeof(struct hal_mon_buf_ring) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_PMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_RXDMA_RING_MAX_SIZE_BE,
+ },
+ [HAL_RXDMA_MONITOR_DST] = {
+ .start_ring_id = HAL_SRNG_RING_ID_WMAC1_SW2RXMON_BUF0,
+ .max_rings = 1,
+ .entry_size = sizeof(struct hal_mon_dest_desc) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_PMAC,
+ .ring_dir = HAL_SRNG_DIR_DST,
+ .max_size = HAL_RXDMA_RING_MAX_SIZE_BE,
+ },
+ [HAL_TX_MONITOR_DST] = {
+ .start_ring_id = HAL_SRNG_RING_ID_WMAC1_TXMON2SW0_BUF0,
+ .max_rings = 1,
+ .entry_size = sizeof(struct hal_mon_dest_desc) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_PMAC,
+ .ring_dir = HAL_SRNG_DIR_DST,
+ .max_size = HAL_RXDMA_RING_MAX_SIZE_BE,
+ }
+};
+
+const struct ath12k_hw_regs qcn9274_v1_regs = {
+ /* SW2TCL(x) R0 ring configuration address */
+ .tcl1_ring_id = 0x00000908,
+ .tcl1_ring_misc = 0x00000910,
+ .tcl1_ring_tp_addr_lsb = 0x0000091c,
+ .tcl1_ring_tp_addr_msb = 0x00000920,
+ .tcl1_ring_consumer_int_setup_ix0 = 0x00000930,
+ .tcl1_ring_consumer_int_setup_ix1 = 0x00000934,
+ .tcl1_ring_msi1_base_lsb = 0x00000948,
+ .tcl1_ring_msi1_base_msb = 0x0000094c,
+ .tcl1_ring_msi1_data = 0x00000950,
+ .tcl_ring_base_lsb = 0x00000b58,
+ .tcl1_ring_base_lsb = 0x00000900,
+ .tcl1_ring_base_msb = 0x00000904,
+ .tcl2_ring_base_lsb = 0x00000978,
+
+ /* TCL STATUS ring address */
+ .tcl_status_ring_base_lsb = 0x00000d38,
+
+ .wbm_idle_ring_base_lsb = 0x00000d0c,
+ .wbm_idle_ring_misc_addr = 0x00000d1c,
+ .wbm_r0_idle_list_cntl_addr = 0x00000210,
+ .wbm_r0_idle_list_size_addr = 0x00000214,
+ .wbm_scattered_ring_base_lsb = 0x00000220,
+ .wbm_scattered_ring_base_msb = 0x00000224,
+ .wbm_scattered_desc_head_info_ix0 = 0x00000230,
+ .wbm_scattered_desc_head_info_ix1 = 0x00000234,
+ .wbm_scattered_desc_tail_info_ix0 = 0x00000240,
+ .wbm_scattered_desc_tail_info_ix1 = 0x00000244,
+ .wbm_scattered_desc_ptr_hp_addr = 0x0000024c,
+
+ .wbm_sw_release_ring_base_lsb = 0x0000034c,
+ .wbm_sw1_release_ring_base_lsb = 0x000003c4,
+ .wbm0_release_ring_base_lsb = 0x00000dd8,
+ .wbm1_release_ring_base_lsb = 0x00000e50,
+
+ /* PCIe base address */
+ .pcie_qserdes_sysclk_en_sel = 0x01e0c0a8,
+ .pcie_pcs_osc_dtct_config_base = 0x01e0d45c,
+
+ /* PPE release ring address */
+ .ppe_rel_ring_base = 0x0000043c,
+
+ /* REO DEST ring address */
+ .reo2_ring_base = 0x0000055c,
+ .reo1_misc_ctrl_addr = 0x00000b7c,
+ .reo1_sw_cookie_cfg0 = 0x00000050,
+ .reo1_sw_cookie_cfg1 = 0x00000054,
+ .reo1_qdesc_lut_base0 = 0x00000058,
+ .reo1_qdesc_lut_base1 = 0x0000005c,
+ .reo1_ring_base_lsb = 0x000004e4,
+ .reo1_ring_base_msb = 0x000004e8,
+ .reo1_ring_id = 0x000004ec,
+ .reo1_ring_misc = 0x000004f4,
+ .reo1_ring_hp_addr_lsb = 0x000004f8,
+ .reo1_ring_hp_addr_msb = 0x000004fc,
+ .reo1_ring_producer_int_setup = 0x00000508,
+ .reo1_ring_msi1_base_lsb = 0x0000052C,
+ .reo1_ring_msi1_base_msb = 0x00000530,
+ .reo1_ring_msi1_data = 0x00000534,
+ .reo1_aging_thres_ix0 = 0x00000b08,
+ .reo1_aging_thres_ix1 = 0x00000b0c,
+ .reo1_aging_thres_ix2 = 0x00000b10,
+ .reo1_aging_thres_ix3 = 0x00000b14,
+
+ /* REO Exception ring address */
+ .reo2_sw0_ring_base = 0x000008a4,
+
+ /* REO Reinject ring address */
+ .sw2reo_ring_base = 0x00000304,
+ .sw2reo1_ring_base = 0x0000037c,
+
+ /* REO cmd ring address */
+ .reo_cmd_ring_base = 0x0000028c,
+
+ /* REO status ring address */
+ .reo_status_ring_base = 0x00000a84,
+
+ /* CE base address */
+ .umac_ce0_src_reg_base = 0x01b80000,
+ .umac_ce0_dest_reg_base = 0x01b81000,
+ .umac_ce1_src_reg_base = 0x01b82000,
+ .umac_ce1_dest_reg_base = 0x01b83000,
+
+ .gcc_gcc_pcie_hot_rst = 0x1e38338,
+
+ .qrtr_node_id = 0x1e03164,
+};
+
+const struct ath12k_hw_regs qcn9274_v2_regs = {
+ /* SW2TCL(x) R0 ring configuration address */
+ .tcl1_ring_id = 0x00000908,
+ .tcl1_ring_misc = 0x00000910,
+ .tcl1_ring_tp_addr_lsb = 0x0000091c,
+ .tcl1_ring_tp_addr_msb = 0x00000920,
+ .tcl1_ring_consumer_int_setup_ix0 = 0x00000930,
+ .tcl1_ring_consumer_int_setup_ix1 = 0x00000934,
+ .tcl1_ring_msi1_base_lsb = 0x00000948,
+ .tcl1_ring_msi1_base_msb = 0x0000094c,
+ .tcl1_ring_msi1_data = 0x00000950,
+ .tcl_ring_base_lsb = 0x00000b58,
+ .tcl1_ring_base_lsb = 0x00000900,
+ .tcl1_ring_base_msb = 0x00000904,
+ .tcl2_ring_base_lsb = 0x00000978,
+
+ /* TCL STATUS ring address */
+ .tcl_status_ring_base_lsb = 0x00000d38,
+
+ /* WBM idle link ring address */
+ .wbm_idle_ring_base_lsb = 0x00000d3c,
+ .wbm_idle_ring_misc_addr = 0x00000d4c,
+ .wbm_r0_idle_list_cntl_addr = 0x00000240,
+ .wbm_r0_idle_list_size_addr = 0x00000244,
+ .wbm_scattered_ring_base_lsb = 0x00000250,
+ .wbm_scattered_ring_base_msb = 0x00000254,
+ .wbm_scattered_desc_head_info_ix0 = 0x00000260,
+ .wbm_scattered_desc_head_info_ix1 = 0x00000264,
+ .wbm_scattered_desc_tail_info_ix0 = 0x00000270,
+ .wbm_scattered_desc_tail_info_ix1 = 0x00000274,
+ .wbm_scattered_desc_ptr_hp_addr = 0x0000027c,
+
+ /* SW2WBM release ring address */
+ .wbm_sw_release_ring_base_lsb = 0x0000037c,
+ .wbm_sw1_release_ring_base_lsb = 0x000003f4,
+
+ /* WBM2SW release ring address */
+ .wbm0_release_ring_base_lsb = 0x00000e08,
+ .wbm1_release_ring_base_lsb = 0x00000e80,
+
+ /* PCIe base address */
+ .pcie_qserdes_sysclk_en_sel = 0x01e0c0a8,
+ .pcie_pcs_osc_dtct_config_base = 0x01e0d45c,
+
+ /* PPE release ring address */
+ .ppe_rel_ring_base = 0x0000046c,
+
+ /* REO DEST ring address */
+ .reo2_ring_base = 0x00000578,
+ .reo1_misc_ctrl_addr = 0x00000b9c,
+ .reo1_sw_cookie_cfg0 = 0x0000006c,
+ .reo1_sw_cookie_cfg1 = 0x00000070,
+ .reo1_qdesc_lut_base0 = 0x00000074,
+ .reo1_qdesc_lut_base1 = 0x00000078,
+ .reo1_qdesc_addr = 0x0000007c,
+ .reo1_qdesc_max_peerid = 0x00000088,
+ .reo1_ring_base_lsb = 0x00000500,
+ .reo1_ring_base_msb = 0x00000504,
+ .reo1_ring_id = 0x00000508,
+ .reo1_ring_misc = 0x00000510,
+ .reo1_ring_hp_addr_lsb = 0x00000514,
+ .reo1_ring_hp_addr_msb = 0x00000518,
+ .reo1_ring_producer_int_setup = 0x00000524,
+ .reo1_ring_msi1_base_lsb = 0x00000548,
+ .reo1_ring_msi1_base_msb = 0x0000054C,
+ .reo1_ring_msi1_data = 0x00000550,
+ .reo1_aging_thres_ix0 = 0x00000B28,
+ .reo1_aging_thres_ix1 = 0x00000B2C,
+ .reo1_aging_thres_ix2 = 0x00000B30,
+ .reo1_aging_thres_ix3 = 0x00000B34,
+
+ /* REO Exception ring address */
+ .reo2_sw0_ring_base = 0x000008c0,
+
+ /* REO Reinject ring address */
+ .sw2reo_ring_base = 0x00000320,
+ .sw2reo1_ring_base = 0x00000398,
+
+ /* REO cmd ring address */
+ .reo_cmd_ring_base = 0x000002A8,
+
+ /* REO status ring address */
+ .reo_status_ring_base = 0x00000aa0,
+
+ /* CE base address */
+ .umac_ce0_src_reg_base = 0x01b80000,
+ .umac_ce0_dest_reg_base = 0x01b81000,
+ .umac_ce1_src_reg_base = 0x01b82000,
+ .umac_ce1_dest_reg_base = 0x01b83000,
+
+ .gcc_gcc_pcie_hot_rst = 0x1e38338,
+
+ .qrtr_node_id = 0x1e03164,
+};
+
+const struct ath12k_hw_regs ipq5332_regs = {
+ /* SW2TCL(x) R0 ring configuration address */
+ .tcl1_ring_id = 0x00000918,
+ .tcl1_ring_misc = 0x00000920,
+ .tcl1_ring_tp_addr_lsb = 0x0000092c,
+ .tcl1_ring_tp_addr_msb = 0x00000930,
+ .tcl1_ring_consumer_int_setup_ix0 = 0x00000940,
+ .tcl1_ring_consumer_int_setup_ix1 = 0x00000944,
+ .tcl1_ring_msi1_base_lsb = 0x00000958,
+ .tcl1_ring_msi1_base_msb = 0x0000095c,
+ .tcl1_ring_base_lsb = 0x00000910,
+ .tcl1_ring_base_msb = 0x00000914,
+ .tcl1_ring_msi1_data = 0x00000960,
+ .tcl2_ring_base_lsb = 0x00000988,
+ .tcl_ring_base_lsb = 0x00000b68,
+
+ /* TCL STATUS ring address */
+ .tcl_status_ring_base_lsb = 0x00000d48,
+
+ /* REO DEST ring address */
+ .reo2_ring_base = 0x00000578,
+ .reo1_misc_ctrl_addr = 0x00000b9c,
+ .reo1_sw_cookie_cfg0 = 0x0000006c,
+ .reo1_sw_cookie_cfg1 = 0x00000070,
+ .reo1_qdesc_lut_base0 = 0x00000074,
+ .reo1_qdesc_lut_base1 = 0x00000078,
+ .reo1_ring_base_lsb = 0x00000500,
+ .reo1_ring_base_msb = 0x00000504,
+ .reo1_ring_id = 0x00000508,
+ .reo1_ring_misc = 0x00000510,
+ .reo1_ring_hp_addr_lsb = 0x00000514,
+ .reo1_ring_hp_addr_msb = 0x00000518,
+ .reo1_ring_producer_int_setup = 0x00000524,
+ .reo1_ring_msi1_base_lsb = 0x00000548,
+ .reo1_ring_msi1_base_msb = 0x0000054C,
+ .reo1_ring_msi1_data = 0x00000550,
+ .reo1_aging_thres_ix0 = 0x00000B28,
+ .reo1_aging_thres_ix1 = 0x00000B2C,
+ .reo1_aging_thres_ix2 = 0x00000B30,
+ .reo1_aging_thres_ix3 = 0x00000B34,
+
+ /* REO Exception ring address */
+ .reo2_sw0_ring_base = 0x000008c0,
+
+ /* REO Reinject ring address */
+ .sw2reo_ring_base = 0x00000320,
+ .sw2reo1_ring_base = 0x00000398,
+
+ /* REO cmd ring address */
+ .reo_cmd_ring_base = 0x000002A8,
+
+ /* REO status ring address */
+ .reo_status_ring_base = 0x00000aa0,
+
+ /* WBM idle link ring address */
+ .wbm_idle_ring_base_lsb = 0x00000d3c,
+ .wbm_idle_ring_misc_addr = 0x00000d4c,
+ .wbm_r0_idle_list_cntl_addr = 0x00000240,
+ .wbm_r0_idle_list_size_addr = 0x00000244,
+ .wbm_scattered_ring_base_lsb = 0x00000250,
+ .wbm_scattered_ring_base_msb = 0x00000254,
+ .wbm_scattered_desc_head_info_ix0 = 0x00000260,
+ .wbm_scattered_desc_head_info_ix1 = 0x00000264,
+ .wbm_scattered_desc_tail_info_ix0 = 0x00000270,
+ .wbm_scattered_desc_tail_info_ix1 = 0x00000274,
+ .wbm_scattered_desc_ptr_hp_addr = 0x0000027c,
+
+ /* SW2WBM release ring address */
+ .wbm_sw_release_ring_base_lsb = 0x0000037c,
+
+ /* WBM2SW release ring address */
+ .wbm0_release_ring_base_lsb = 0x00000e08,
+ .wbm1_release_ring_base_lsb = 0x00000e80,
+
+ /* PPE release ring address */
+ .ppe_rel_ring_base = 0x0000046c,
+
+ /* CE address */
+ .umac_ce0_src_reg_base = 0x00740000 -
+ HAL_IPQ5332_CE_WFSS_REG_BASE,
+ .umac_ce0_dest_reg_base = 0x00741000 -
+ HAL_IPQ5332_CE_WFSS_REG_BASE,
+ .umac_ce1_src_reg_base = 0x00742000 -
+ HAL_IPQ5332_CE_WFSS_REG_BASE,
+ .umac_ce1_dest_reg_base = 0x00743000 -
+ HAL_IPQ5332_CE_WFSS_REG_BASE,
+};
+
+static inline
+bool ath12k_hal_rx_desc_get_first_msdu_qcn9274(struct hal_rx_desc *desc)
+{
+ return !!le16_get_bits(desc->u.qcn9274_compact.msdu_end.info5,
+ RX_MSDU_END_INFO5_FIRST_MSDU);
+}
+
+static inline
+bool ath12k_hal_rx_desc_get_last_msdu_qcn9274(struct hal_rx_desc *desc)
+{
+ return !!le16_get_bits(desc->u.qcn9274_compact.msdu_end.info5,
+ RX_MSDU_END_INFO5_LAST_MSDU);
+}
+
+u8 ath12k_hal_rx_desc_get_l3_pad_bytes_qcn9274(struct hal_rx_desc *desc)
+{
+ return le16_get_bits(desc->u.qcn9274_compact.msdu_end.info5,
+ RX_MSDU_END_INFO5_L3_HDR_PADDING);
+}
+
+static inline
+bool ath12k_hal_rx_desc_encrypt_valid_qcn9274(struct hal_rx_desc *desc)
+{
+ return !!le32_get_bits(desc->u.qcn9274_compact.mpdu_start.info4,
+ RX_MPDU_START_INFO4_ENCRYPT_INFO_VALID);
+}
+
+static inline
+u32 ath12k_hal_rx_desc_get_encrypt_type_qcn9274(struct hal_rx_desc *desc)
+{
+ if (!ath12k_hal_rx_desc_encrypt_valid_qcn9274(desc))
+ return HAL_ENCRYPT_TYPE_OPEN;
+
+ return le32_get_bits(desc->u.qcn9274_compact.mpdu_start.info2,
+ RX_MPDU_START_INFO2_ENC_TYPE);
+}
+
+static inline
+u8 ath12k_hal_rx_desc_get_decap_type_qcn9274(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info11,
+ RX_MSDU_END_INFO11_DECAP_FORMAT);
+}
+
+static inline
+u8 ath12k_hal_rx_desc_get_mesh_ctl_qcn9274(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info11,
+ RX_MSDU_END_INFO11_MESH_CTRL_PRESENT);
+}
+
+static inline
+bool ath12k_hal_rx_desc_get_mpdu_seq_ctl_vld_qcn9274(struct hal_rx_desc *desc)
+{
+ return !!le32_get_bits(desc->u.qcn9274_compact.mpdu_start.info4,
+ RX_MPDU_START_INFO4_MPDU_SEQ_CTRL_VALID);
+}
+
+static inline
+bool ath12k_hal_rx_desc_get_mpdu_fc_valid_qcn9274(struct hal_rx_desc *desc)
+{
+ return !!le32_get_bits(desc->u.qcn9274_compact.mpdu_start.info4,
+ RX_MPDU_START_INFO4_MPDU_FCTRL_VALID);
+}
+
+static inline
+u16 ath12k_hal_rx_desc_get_mpdu_start_seq_no_qcn9274(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.qcn9274_compact.mpdu_start.info4,
+ RX_MPDU_START_INFO4_MPDU_SEQ_NUM);
+}
+
+static inline
+u16 ath12k_hal_rx_desc_get_msdu_len_qcn9274(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info10,
+ RX_MSDU_END_INFO10_MSDU_LENGTH);
+}
+
+static inline
+u8 ath12k_hal_rx_desc_get_msdu_sgi_qcn9274(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info12,
+ RX_MSDU_END_INFO12_SGI);
+}
+
+static inline
+u8 ath12k_hal_rx_desc_get_msdu_rate_mcs_qcn9274(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info12,
+ RX_MSDU_END_INFO12_RATE_MCS);
+}
+
+static inline
+u8 ath12k_hal_rx_desc_get_msdu_rx_bw_qcn9274(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info12,
+ RX_MSDU_END_INFO12_RECV_BW);
+}
+
+static inline
+u32 ath12k_hal_rx_desc_get_msdu_freq_qcn9274(struct hal_rx_desc *desc)
+{
+ return __le32_to_cpu(desc->u.qcn9274_compact.msdu_end.phy_meta_data);
+}
+
+static inline
+u8 ath12k_hal_rx_desc_get_msdu_pkt_type_qcn9274(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info12,
+ RX_MSDU_END_INFO12_PKT_TYPE);
+}
+
+static inline
+u8 ath12k_hal_rx_desc_get_msdu_nss_qcn9274(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info12,
+ RX_MSDU_END_INFO12_MIMO_SS_BITMAP);
+}
+
+static inline
+u8 ath12k_hal_rx_desc_get_mpdu_tid_qcn9274(struct hal_rx_desc *desc)
+{
+ return le16_get_bits(desc->u.qcn9274_compact.msdu_end.info5,
+ RX_MSDU_END_INFO5_TID);
+}
+
+static inline
+u16 ath12k_hal_rx_desc_get_mpdu_peer_id_qcn9274(struct hal_rx_desc *desc)
+{
+ return __le16_to_cpu(desc->u.qcn9274_compact.mpdu_start.sw_peer_id);
+}
+
+void ath12k_hal_rx_desc_copy_end_tlv_qcn9274(struct hal_rx_desc *fdesc,
+ struct hal_rx_desc *ldesc)
+{
+ fdesc->u.qcn9274_compact.msdu_end = ldesc->u.qcn9274_compact.msdu_end;
+}
+
+u32 ath12k_hal_rx_desc_get_mpdu_ppdu_id_qcn9274(struct hal_rx_desc *desc)
+{
+ return __le16_to_cpu(desc->u.qcn9274_compact.mpdu_start.phy_ppdu_id);
+}
+
+void ath12k_hal_rx_desc_set_msdu_len_qcn9274(struct hal_rx_desc *desc, u16 len)
+{
+ u32 info = __le32_to_cpu(desc->u.qcn9274_compact.msdu_end.info10);
+
+ info = u32_replace_bits(info, len, RX_MSDU_END_INFO10_MSDU_LENGTH);
+ desc->u.qcn9274_compact.msdu_end.info10 = __cpu_to_le32(info);
+}
+
+u8 *ath12k_hal_rx_desc_get_msdu_payload_qcn9274(struct hal_rx_desc *desc)
+{
+ return &desc->u.qcn9274_compact.msdu_payload[0];
+}
+
+u32 ath12k_hal_rx_desc_get_mpdu_start_offset_qcn9274(void)
+{
+ return offsetof(struct hal_rx_desc_qcn9274_compact, mpdu_start);
+}
+
+u32 ath12k_hal_rx_desc_get_msdu_end_offset_qcn9274(void)
+{
+ return offsetof(struct hal_rx_desc_qcn9274_compact, msdu_end);
+}
+
+static inline
+bool ath12k_hal_rx_desc_mac_addr2_valid_qcn9274(struct hal_rx_desc *desc)
+{
+ return __le32_to_cpu(desc->u.qcn9274_compact.mpdu_start.info4) &
+ RX_MPDU_START_INFO4_MAC_ADDR2_VALID;
+}
+
+static inline
+u8 *ath12k_hal_rx_desc_mpdu_start_addr2_qcn9274(struct hal_rx_desc *desc)
+{
+ return desc->u.qcn9274_compact.mpdu_start.addr2;
+}
+
+static inline
+bool ath12k_hal_rx_desc_is_da_mcbc_qcn9274(struct hal_rx_desc *desc)
+{
+ return __le16_to_cpu(desc->u.qcn9274_compact.msdu_end.info5) &
+ RX_MSDU_END_INFO5_DA_IS_MCBC;
+}
+
+static inline
+bool ath12k_hal_rx_h_msdu_done_qcn9274(struct hal_rx_desc *desc)
+{
+ return !!le32_get_bits(desc->u.qcn9274_compact.msdu_end.info14,
+ RX_MSDU_END_INFO14_MSDU_DONE);
+}
+
+static inline
+bool ath12k_hal_rx_h_l4_cksum_fail_qcn9274(struct hal_rx_desc *desc)
+{
+ return !!le32_get_bits(desc->u.qcn9274_compact.msdu_end.info13,
+ RX_MSDU_END_INFO13_TCP_UDP_CKSUM_FAIL);
+}
+
+static inline
+bool ath12k_hal_rx_h_ip_cksum_fail_qcn9274(struct hal_rx_desc *desc)
+{
+ return !!le32_get_bits(desc->u.qcn9274_compact.msdu_end.info13,
+ RX_MSDU_END_INFO13_IP_CKSUM_FAIL);
+}
+
+static inline
+bool ath12k_hal_rx_h_is_decrypted_qcn9274(struct hal_rx_desc *desc)
+{
+ return (le32_get_bits(desc->u.qcn9274_compact.msdu_end.info14,
+ RX_MSDU_END_INFO14_DECRYPT_STATUS_CODE) ==
+ RX_DESC_DECRYPT_STATUS_CODE_OK);
+}
+
+u32 ath12k_hal_get_rx_desc_size_qcn9274(void)
+{
+ return sizeof(struct hal_rx_desc_qcn9274_compact);
+}
+
+u8 ath12k_hal_rx_desc_get_msdu_src_link_qcn9274(struct hal_rx_desc *desc)
+{
+ return le64_get_bits(desc->u.qcn9274_compact.msdu_end.msdu_end_tag,
+ RX_MSDU_END_64_TLV_SRC_LINK_ID);
+}
+
+u16 ath12k_hal_rx_mpdu_start_wmask_get_qcn9274(void)
+{
+ return QCN9274_MPDU_START_WMASK;
+}
+
+u32 ath12k_hal_rx_msdu_end_wmask_get_qcn9274(void)
+{
+ return QCN9274_MSDU_END_WMASK;
+}
+
+static u32 ath12k_hal_rx_h_mpdu_err_qcn9274(struct hal_rx_desc *desc)
+{
+ u32 info = __le32_to_cpu(desc->u.qcn9274_compact.msdu_end.info13);
+ u32 errmap = 0;
+
+ if (info & RX_MSDU_END_INFO13_FCS_ERR)
+ errmap |= HAL_RX_MPDU_ERR_FCS;
+
+ if (info & RX_MSDU_END_INFO13_DECRYPT_ERR)
+ errmap |= HAL_RX_MPDU_ERR_DECRYPT;
+
+ if (info & RX_MSDU_END_INFO13_TKIP_MIC_ERR)
+ errmap |= HAL_RX_MPDU_ERR_TKIP_MIC;
+
+ if (info & RX_MSDU_END_INFO13_A_MSDU_ERROR)
+ errmap |= HAL_RX_MPDU_ERR_AMSDU_ERR;
+
+ if (info & RX_MSDU_END_INFO13_OVERFLOW_ERR)
+ errmap |= HAL_RX_MPDU_ERR_OVERFLOW;
+
+ if (info & RX_MSDU_END_INFO13_MSDU_LEN_ERR)
+ errmap |= HAL_RX_MPDU_ERR_MSDU_LEN;
+
+ if (info & RX_MSDU_END_INFO13_MPDU_LEN_ERR)
+ errmap |= HAL_RX_MPDU_ERR_MPDU_LEN;
+
+ return errmap;
+}
+
+void ath12k_hal_rx_desc_get_crypto_hdr_qcn9274(struct hal_rx_desc *desc,
+ u8 *crypto_hdr,
+ enum hal_encrypt_type enctype)
+{
+ unsigned int key_id;
+
+ switch (enctype) {
+ case HAL_ENCRYPT_TYPE_OPEN:
+ return;
+ case HAL_ENCRYPT_TYPE_TKIP_NO_MIC:
+ case HAL_ENCRYPT_TYPE_TKIP_MIC:
+ crypto_hdr[0] =
+ HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.qcn9274_compact.mpdu_start.pn[0]);
+ crypto_hdr[1] = 0;
+ crypto_hdr[2] =
+ HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.qcn9274_compact.mpdu_start.pn[0]);
+ break;
+ case HAL_ENCRYPT_TYPE_CCMP_128:
+ case HAL_ENCRYPT_TYPE_CCMP_256:
+ case HAL_ENCRYPT_TYPE_GCMP_128:
+ case HAL_ENCRYPT_TYPE_AES_GCMP_256:
+ crypto_hdr[0] =
+ HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.qcn9274_compact.mpdu_start.pn[0]);
+ crypto_hdr[1] =
+ HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.qcn9274_compact.mpdu_start.pn[0]);
+ crypto_hdr[2] = 0;
+ break;
+ case HAL_ENCRYPT_TYPE_WEP_40:
+ case HAL_ENCRYPT_TYPE_WEP_104:
+ case HAL_ENCRYPT_TYPE_WEP_128:
+ case HAL_ENCRYPT_TYPE_WAPI_GCM_SM4:
+ case HAL_ENCRYPT_TYPE_WAPI:
+ return;
+ }
+ key_id = le32_get_bits(desc->u.qcn9274_compact.mpdu_start.info5,
+ RX_MPDU_START_INFO5_KEY_ID);
+ crypto_hdr[3] = 0x20 | (key_id << 6);
+ crypto_hdr[4] =
+ HAL_RX_MPDU_INFO_PN_GET_BYTE3(desc->u.qcn9274_compact.mpdu_start.pn[0]);
+ crypto_hdr[5] =
+ HAL_RX_MPDU_INFO_PN_GET_BYTE4(desc->u.qcn9274_compact.mpdu_start.pn[0]);
+ crypto_hdr[6] =
+ HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.qcn9274_compact.mpdu_start.pn[1]);
+ crypto_hdr[7] =
+ HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.qcn9274_compact.mpdu_start.pn[1]);
+}
+
+void ath12k_hal_rx_desc_get_dot11_hdr_qcn9274(struct hal_rx_desc *desc,
+ struct ieee80211_hdr *hdr)
+{
+ hdr->frame_control = desc->u.qcn9274_compact.mpdu_start.frame_ctrl;
+ hdr->duration_id = desc->u.qcn9274_compact.mpdu_start.duration;
+ ether_addr_copy(hdr->addr1, desc->u.qcn9274_compact.mpdu_start.addr1);
+ ether_addr_copy(hdr->addr2, desc->u.qcn9274_compact.mpdu_start.addr2);
+ ether_addr_copy(hdr->addr3, desc->u.qcn9274_compact.mpdu_start.addr3);
+ if (__le32_to_cpu(desc->u.qcn9274_compact.mpdu_start.info4) &
+ RX_MPDU_START_INFO4_MAC_ADDR4_VALID) {
+ ether_addr_copy(hdr->addr4, desc->u.qcn9274_compact.mpdu_start.addr4);
+ }
+ hdr->seq_ctrl = desc->u.qcn9274_compact.mpdu_start.seq_ctrl;
+}
+
+void ath12k_hal_extract_rx_desc_data_qcn9274(struct hal_rx_desc_data *rx_desc_data,
+ struct hal_rx_desc *rx_desc,
+ struct hal_rx_desc *ldesc)
+{
+ rx_desc_data->is_first_msdu = ath12k_hal_rx_desc_get_first_msdu_qcn9274(ldesc);
+ rx_desc_data->is_last_msdu = ath12k_hal_rx_desc_get_last_msdu_qcn9274(ldesc);
+ rx_desc_data->l3_pad_bytes = ath12k_hal_rx_desc_get_l3_pad_bytes_qcn9274(ldesc);
+ rx_desc_data->enctype = ath12k_hal_rx_desc_get_encrypt_type_qcn9274(rx_desc);
+ rx_desc_data->decap_type = ath12k_hal_rx_desc_get_decap_type_qcn9274(rx_desc);
+ rx_desc_data->mesh_ctrl_present =
+ ath12k_hal_rx_desc_get_mesh_ctl_qcn9274(rx_desc);
+ rx_desc_data->seq_ctl_valid =
+ ath12k_hal_rx_desc_get_mpdu_seq_ctl_vld_qcn9274(rx_desc);
+ rx_desc_data->fc_valid = ath12k_hal_rx_desc_get_mpdu_fc_valid_qcn9274(rx_desc);
+ rx_desc_data->seq_no = ath12k_hal_rx_desc_get_mpdu_start_seq_no_qcn9274(rx_desc);
+ rx_desc_data->msdu_len = ath12k_hal_rx_desc_get_msdu_len_qcn9274(ldesc);
+ rx_desc_data->sgi = ath12k_hal_rx_desc_get_msdu_sgi_qcn9274(rx_desc);
+ rx_desc_data->rate_mcs = ath12k_hal_rx_desc_get_msdu_rate_mcs_qcn9274(rx_desc);
+ rx_desc_data->bw = ath12k_hal_rx_desc_get_msdu_rx_bw_qcn9274(rx_desc);
+ rx_desc_data->phy_meta_data = ath12k_hal_rx_desc_get_msdu_freq_qcn9274(rx_desc);
+ rx_desc_data->pkt_type = ath12k_hal_rx_desc_get_msdu_pkt_type_qcn9274(rx_desc);
+ rx_desc_data->nss = hweight8(ath12k_hal_rx_desc_get_msdu_nss_qcn9274(rx_desc));
+ rx_desc_data->tid = ath12k_hal_rx_desc_get_mpdu_tid_qcn9274(rx_desc);
+ rx_desc_data->peer_id = ath12k_hal_rx_desc_get_mpdu_peer_id_qcn9274(rx_desc);
+ rx_desc_data->addr2_present = ath12k_hal_rx_desc_mac_addr2_valid_qcn9274(rx_desc);
+ rx_desc_data->addr2 = ath12k_hal_rx_desc_mpdu_start_addr2_qcn9274(rx_desc);
+ rx_desc_data->is_mcbc = ath12k_hal_rx_desc_is_da_mcbc_qcn9274(rx_desc);
+ rx_desc_data->msdu_done = ath12k_hal_rx_h_msdu_done_qcn9274(ldesc);
+ rx_desc_data->l4_csum_fail = ath12k_hal_rx_h_l4_cksum_fail_qcn9274(rx_desc);
+ rx_desc_data->ip_csum_fail = ath12k_hal_rx_h_ip_cksum_fail_qcn9274(rx_desc);
+ rx_desc_data->is_decrypted = ath12k_hal_rx_h_is_decrypted_qcn9274(rx_desc);
+ rx_desc_data->err_bitmap = ath12k_hal_rx_h_mpdu_err_qcn9274(rx_desc);
+}
+
+const struct ath12k_hw_hal_params ath12k_hw_hal_params_qcn9274 = {
+ .rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM,
+ .wbm2sw_cc_enable = HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW0_EN |
+ HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW1_EN |
+ HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW2_EN |
+ HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW3_EN |
+ HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW4_EN,
+};
+
+const struct ath12k_hw_hal_params ath12k_hw_hal_params_ipq5332 = {
+ .rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM,
+ .wbm2sw_cc_enable = HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW0_EN |
+ HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW1_EN |
+ HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW2_EN |
+ HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW3_EN |
+ HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW4_EN,
+};
+
+static int ath12k_hal_srng_create_config_qcn9274(struct ath12k_hal *hal)
+{
+ struct hal_srng_config *s;
+
+ hal->srng_config = kmemdup(hw_srng_config_template,
+ sizeof(hw_srng_config_template),
+ GFP_KERNEL);
+ if (!hal->srng_config)
+ return -ENOMEM;
+
+ s = &hal->srng_config[HAL_REO_DST];
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_RING_HP;
+ s->reg_size[0] = HAL_REO2_RING_BASE_LSB(hal) - HAL_REO1_RING_BASE_LSB(hal);
+ s->reg_size[1] = HAL_REO2_RING_HP - HAL_REO1_RING_HP;
+
+ s = &hal->srng_config[HAL_REO_EXCEPTION];
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_SW0_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_SW0_RING_HP;
+
+ s = &hal->srng_config[HAL_REO_REINJECT];
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_HP;
+ s->reg_size[0] = HAL_SW2REO1_RING_BASE_LSB(hal) - HAL_SW2REO_RING_BASE_LSB(hal);
+ s->reg_size[1] = HAL_SW2REO1_RING_HP - HAL_SW2REO_RING_HP;
+
+ s = &hal->srng_config[HAL_REO_CMD];
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_HP;
+
+ s = &hal->srng_config[HAL_REO_STATUS];
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_HP;
+
+ s = &hal->srng_config[HAL_TCL_DATA];
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_HP;
+ s->reg_size[0] = HAL_TCL2_RING_BASE_LSB(hal) - HAL_TCL1_RING_BASE_LSB(hal);
+ s->reg_size[1] = HAL_TCL2_RING_HP - HAL_TCL1_RING_HP;
+
+ s = &hal->srng_config[HAL_TCL_CMD];
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_RING_HP;
+
+ s = &hal->srng_config[HAL_TCL_STATUS];
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_STATUS_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_STATUS_RING_HP;
+
+ s = &hal->srng_config[HAL_CE_SRC];
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(hal) + HAL_CE_DST_RING_BASE_LSB;
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(hal) + HAL_CE_DST_RING_HP;
+ s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(hal) -
+ HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(hal);
+ s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(hal) -
+ HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(hal);
+
+ s = &hal->srng_config[HAL_CE_DST];
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(hal) + HAL_CE_DST_RING_BASE_LSB;
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(hal) + HAL_CE_DST_RING_HP;
+ s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(hal) -
+ HAL_SEQ_WCSS_UMAC_CE0_DST_REG(hal);
+ s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(hal) -
+ HAL_SEQ_WCSS_UMAC_CE0_DST_REG(hal);
+
+ s = &hal->srng_config[HAL_CE_DST_STATUS];
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(hal) +
+ HAL_CE_DST_STATUS_RING_BASE_LSB;
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(hal) + HAL_CE_DST_STATUS_RING_HP;
+ s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(hal) -
+ HAL_SEQ_WCSS_UMAC_CE0_DST_REG(hal);
+ s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(hal) -
+ HAL_SEQ_WCSS_UMAC_CE0_DST_REG(hal);
+
+ s = &hal->srng_config[HAL_WBM_IDLE_LINK];
+ s->reg_start[0] =
+ HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_IDLE_LINK_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_IDLE_LINK_RING_HP;
+
+ s = &hal->srng_config[HAL_SW2WBM_RELEASE];
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG +
+ HAL_WBM_SW_RELEASE_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_SW_RELEASE_RING_HP;
+ s->reg_size[0] = HAL_WBM_SW1_RELEASE_RING_BASE_LSB(hal) -
+ HAL_WBM_SW_RELEASE_RING_BASE_LSB(hal);
+ s->reg_size[1] = HAL_WBM_SW1_RELEASE_RING_HP - HAL_WBM_SW_RELEASE_RING_HP;
+
+ s = &hal->srng_config[HAL_WBM2SW_RELEASE];
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM0_RELEASE_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM0_RELEASE_RING_HP;
+ s->reg_size[0] = HAL_WBM1_RELEASE_RING_BASE_LSB(hal) -
+ HAL_WBM0_RELEASE_RING_BASE_LSB(hal);
+ s->reg_size[1] = HAL_WBM1_RELEASE_RING_HP - HAL_WBM0_RELEASE_RING_HP;
+
+ /* Some LMAC rings are not accessed from the host:
+ * RXDMA_BUG, RXDMA_DST, RXDMA_MONITOR_BUF, RXDMA_MONITOR_STATUS,
+ * RXDMA_MONITOR_DST, RXDMA_MONITOR_DESC, RXDMA_DIR_BUF_SRC,
+ * RXDMA_RX_MONITOR_BUF, TX_MONITOR_BUF, TX_MONITOR_DST, SW2RXDMA
+ */
+ s = &hal->srng_config[HAL_PPE2TCL];
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_PPE2TCL1_RING_BASE_LSB;
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_PPE2TCL1_RING_HP;
+
+ s = &hal->srng_config[HAL_PPE_RELEASE];
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG +
+ HAL_WBM_PPE_RELEASE_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_PPE_RELEASE_RING_HP;
+
+ return 0;
+}
+
+const struct ath12k_hal_tcl_to_wbm_rbm_map
+ath12k_hal_tcl_to_wbm_rbm_map_qcn9274[DP_TCL_NUM_RING_MAX] = {
+ {
+ .wbm_ring_num = 0,
+ .rbm_id = HAL_RX_BUF_RBM_SW0_BM,
+ },
+ {
+ .wbm_ring_num = 1,
+ .rbm_id = HAL_RX_BUF_RBM_SW1_BM,
+ },
+ {
+ .wbm_ring_num = 2,
+ .rbm_id = HAL_RX_BUF_RBM_SW2_BM,
+ },
+ {
+ .wbm_ring_num = 4,
+ .rbm_id = HAL_RX_BUF_RBM_SW4_BM,
+ },
+};
+
+const struct hal_ops hal_qcn9274_ops = {
+ .create_srng_config = ath12k_hal_srng_create_config_qcn9274,
+ .rx_desc_set_msdu_len = ath12k_hal_rx_desc_set_msdu_len_qcn9274,
+ .rx_desc_get_dot11_hdr = ath12k_hal_rx_desc_get_dot11_hdr_qcn9274,
+ .rx_desc_get_crypto_header = ath12k_hal_rx_desc_get_crypto_hdr_qcn9274,
+ .rx_desc_copy_end_tlv = ath12k_hal_rx_desc_copy_end_tlv_qcn9274,
+ .rx_desc_get_msdu_src_link_id = ath12k_hal_rx_desc_get_msdu_src_link_qcn9274,
+ .extract_rx_desc_data = ath12k_hal_extract_rx_desc_data_qcn9274,
+ .rx_desc_get_l3_pad_bytes = ath12k_hal_rx_desc_get_l3_pad_bytes_qcn9274,
+ .rx_desc_get_mpdu_ppdu_id = ath12k_hal_rx_desc_get_mpdu_ppdu_id_qcn9274,
+ .rx_desc_get_msdu_payload = ath12k_hal_rx_desc_get_msdu_payload_qcn9274,
+ .ce_dst_setup = ath12k_wifi7_hal_ce_dst_setup,
+ .srng_src_hw_init = ath12k_wifi7_hal_srng_src_hw_init,
+ .srng_dst_hw_init = ath12k_wifi7_hal_srng_dst_hw_init,
+ .set_umac_srng_ptr_addr = ath12k_wifi7_hal_set_umac_srng_ptr_addr,
+ .srng_update_shadow_config = ath12k_wifi7_hal_srng_update_shadow_config,
+ .srng_get_ring_id = ath12k_wifi7_hal_srng_get_ring_id,
+ .ce_get_desc_size = ath12k_wifi7_hal_ce_get_desc_size,
+ .ce_src_set_desc = ath12k_wifi7_hal_ce_src_set_desc,
+ .ce_dst_set_desc = ath12k_wifi7_hal_ce_dst_set_desc,
+ .ce_dst_status_get_length = ath12k_wifi7_hal_ce_dst_status_get_length,
+ .set_link_desc_addr = ath12k_wifi7_hal_set_link_desc_addr,
+ .tx_set_dscp_tid_map = ath12k_wifi7_hal_tx_set_dscp_tid_map,
+ .tx_configure_bank_register =
+ ath12k_wifi7_hal_tx_configure_bank_register,
+ .reoq_lut_addr_read_enable = ath12k_wifi7_hal_reoq_lut_addr_read_enable,
+ .reoq_lut_set_max_peerid = ath12k_wifi7_hal_reoq_lut_set_max_peerid,
+ .write_reoq_lut_addr = ath12k_wifi7_hal_write_reoq_lut_addr,
+ .write_ml_reoq_lut_addr = ath12k_wifi7_hal_write_ml_reoq_lut_addr,
+ .setup_link_idle_list = ath12k_wifi7_hal_setup_link_idle_list,
+ .reo_init_cmd_ring = ath12k_wifi7_hal_reo_init_cmd_ring_tlv64,
+ .reo_hw_setup = ath12k_wifi7_hal_reo_hw_setup,
+ .reo_shared_qaddr_cache_clear = ath12k_wifi7_hal_reo_shared_qaddr_cache_clear,
+ .rx_buf_addr_info_set = ath12k_wifi7_hal_rx_buf_addr_info_set,
+ .rx_buf_addr_info_get = ath12k_wifi7_hal_rx_buf_addr_info_get,
+ .cc_config = ath12k_wifi7_hal_cc_config,
+ .get_idle_link_rbm = ath12k_wifi7_hal_get_idle_link_rbm,
+ .rx_msdu_list_get = ath12k_wifi7_hal_rx_msdu_list_get,
+ .rx_reo_ent_buf_paddr_get = ath12k_wifi7_hal_rx_reo_ent_buf_paddr_get,
+ .reo_cmd_enc_tlv_hdr = ath12k_hal_encode_tlv64_hdr,
+ .reo_status_dec_tlv_hdr = ath12k_hal_decode_tlv64_hdr,
+};
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.h b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.h
new file mode 100644
index 000000000000..08c0a0469474
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear*/
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef ATH12K_HAL_QCN9274_H
+#define ATH12K_HAL_QCN9274_H
+
+#include <linux/ieee80211.h>
+#include <linux/etherdevice.h>
+#include "../hal.h"
+#include "hal_rx.h"
+#include "hal.h"
+
+extern const struct hal_ops hal_qcn9274_ops;
+extern const struct ath12k_hw_regs qcn9274_v1_regs;
+extern const struct ath12k_hw_regs qcn9274_v2_regs;
+extern const struct ath12k_hw_regs ipq5332_regs;
+extern const struct ath12k_hal_tcl_to_wbm_rbm_map
+ath12k_hal_tcl_to_wbm_rbm_map_qcn9274[DP_TCL_NUM_RING_MAX];
+extern const struct ath12k_hw_hal_params ath12k_hw_hal_params_qcn9274;
+extern const struct ath12k_hw_hal_params ath12k_hw_hal_params_ipq5332;
+
+u8 ath12k_hal_rx_desc_get_l3_pad_bytes_qcn9274(struct hal_rx_desc *desc);
+void ath12k_hal_rx_desc_copy_end_tlv_qcn9274(struct hal_rx_desc *fdesc,
+ struct hal_rx_desc *ldesc);
+u32 ath12k_hal_rx_desc_get_mpdu_ppdu_id_qcn9274(struct hal_rx_desc *desc);
+void ath12k_hal_rx_desc_set_msdu_len_qcn9274(struct hal_rx_desc *desc, u16 len);
+u8 *ath12k_hal_rx_desc_get_msdu_payload_qcn9274(struct hal_rx_desc *desc);
+u32 ath12k_hal_rx_desc_get_mpdu_start_offset_qcn9274(void);
+u32 ath12k_hal_rx_desc_get_msdu_end_offset_qcn9274(void);
+u32 ath12k_hal_get_rx_desc_size_qcn9274(void);
+u8 ath12k_hal_rx_desc_get_msdu_src_link_qcn9274(struct hal_rx_desc *desc);
+u16 ath12k_hal_rx_mpdu_start_wmask_get_qcn9274(void);
+u32 ath12k_hal_rx_msdu_end_wmask_get_qcn9274(void);
+void ath12k_hal_rx_desc_get_crypto_hdr_qcn9274(struct hal_rx_desc *desc,
+ u8 *crypto_hdr,
+ enum hal_encrypt_type enctype);
+void ath12k_hal_rx_desc_get_dot11_hdr_qcn9274(struct hal_rx_desc *desc,
+ struct ieee80211_hdr *hdr);
+void ath12k_hal_extract_rx_desc_data_qcn9274(struct hal_rx_desc_data *rx_desc_data,
+ struct hal_rx_desc *rx_desc,
+ struct hal_rx_desc *ldesc);
+#endif
diff --git a/drivers/net/wireless/ath/ath12k/hal_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_rx.c
index c4443ca05cd6..49c693289709 100644
--- a/drivers/net/wireless/ath/ath12k/hal_rx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_rx.c
@@ -4,15 +4,17 @@
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
-#include "debug.h"
-#include "hal.h"
+#include "../debug.h"
+#include "../hal.h"
+#include "../hif.h"
#include "hal_tx.h"
#include "hal_rx.h"
#include "hal_desc.h"
-#include "hif.h"
+#include "hal.h"
-static void ath12k_hal_reo_set_desc_hdr(struct hal_desc_header *hdr,
- u8 owner, u8 buffer_type, u32 magic)
+static
+void ath12k_wifi7_hal_reo_set_desc_hdr(struct hal_desc_header *hdr,
+ u8 owner, u8 buffer_type, u32 magic)
{
hdr->info0 = le32_encode_bits(owner, HAL_DESC_HDR_INFO0_OWNER) |
le32_encode_bits(buffer_type, HAL_DESC_HDR_INFO0_BUF_TYPE);
@@ -21,15 +23,13 @@ static void ath12k_hal_reo_set_desc_hdr(struct hal_desc_header *hdr,
hdr->info0 |= le32_encode_bits(magic, HAL_DESC_HDR_INFO0_DBG_RESERVED);
}
-static int ath12k_hal_reo_cmd_queue_stats(struct hal_tlv_64_hdr *tlv,
- struct ath12k_hal_reo_cmd *cmd)
+static int ath12k_wifi7_hal_reo_cmd_queue_stats(struct ath12k_hal *hal, void *tlv,
+ struct ath12k_hal_reo_cmd *cmd)
{
struct hal_reo_get_queue_stats *desc;
- tlv->tl = le64_encode_bits(HAL_REO_GET_QUEUE_STATS, HAL_TLV_HDR_TAG) |
- le64_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN);
-
- desc = (struct hal_reo_get_queue_stats *)tlv->value;
+ desc = hal->ops->reo_cmd_enc_tlv_hdr(tlv, HAL_REO_GET_QUEUE_STATS,
+ sizeof(*desc));
memset_startat(desc, 0, queue_addr_lo);
desc->cmd.info0 &= ~cpu_to_le32(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED);
@@ -45,9 +45,8 @@ static int ath12k_hal_reo_cmd_queue_stats(struct hal_tlv_64_hdr *tlv,
return le32_get_bits(desc->cmd.info0, HAL_REO_CMD_HDR_INFO0_CMD_NUMBER);
}
-static int ath12k_hal_reo_cmd_flush_cache(struct ath12k_hal *hal,
- struct hal_tlv_64_hdr *tlv,
- struct ath12k_hal_reo_cmd *cmd)
+static int ath12k_wifi7_hal_reo_cmd_flush_cache(struct ath12k_hal *hal, void *tlv,
+ struct ath12k_hal_reo_cmd *cmd)
{
struct hal_reo_flush_cache *desc;
u8 avail_slot = ffz(hal->avail_blk_resource);
@@ -59,10 +58,8 @@ static int ath12k_hal_reo_cmd_flush_cache(struct ath12k_hal *hal,
hal->current_blk_index = avail_slot;
}
- tlv->tl = le64_encode_bits(HAL_REO_FLUSH_CACHE, HAL_TLV_HDR_TAG) |
- le64_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN);
-
- desc = (struct hal_reo_flush_cache *)tlv->value;
+ desc = hal->ops->reo_cmd_enc_tlv_hdr(tlv, HAL_REO_FLUSH_CACHE,
+ sizeof(*desc));
memset_startat(desc, 0, cache_addr_lo);
desc->cmd.info0 &= ~cpu_to_le32(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED);
@@ -95,15 +92,14 @@ static int ath12k_hal_reo_cmd_flush_cache(struct ath12k_hal *hal,
return le32_get_bits(desc->cmd.info0, HAL_REO_CMD_HDR_INFO0_CMD_NUMBER);
}
-static int ath12k_hal_reo_cmd_update_rx_queue(struct hal_tlv_64_hdr *tlv,
- struct ath12k_hal_reo_cmd *cmd)
+static int
+ath12k_wifi7_hal_reo_cmd_update_rx_queue(struct ath12k_hal *hal, void *tlv,
+ struct ath12k_hal_reo_cmd *cmd)
{
struct hal_reo_update_rx_queue *desc;
- tlv->tl = le64_encode_bits(HAL_REO_UPDATE_RX_REO_QUEUE, HAL_TLV_HDR_TAG) |
- le64_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN);
-
- desc = (struct hal_reo_update_rx_queue *)tlv->value;
+ desc = hal->ops->reo_cmd_enc_tlv_hdr(tlv, HAL_REO_UPDATE_RX_REO_QUEUE,
+ sizeof(*desc));
memset_startat(desc, 0, queue_addr_lo);
desc->cmd.info0 &= ~cpu_to_le32(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED);
@@ -220,11 +216,12 @@ static int ath12k_hal_reo_cmd_update_rx_queue(struct hal_tlv_64_hdr *tlv,
return le32_get_bits(desc->cmd.info0, HAL_REO_CMD_HDR_INFO0_CMD_NUMBER);
}
-int ath12k_hal_reo_cmd_send(struct ath12k_base *ab, struct hal_srng *srng,
- enum hal_reo_cmd_type type,
- struct ath12k_hal_reo_cmd *cmd)
+int ath12k_wifi7_hal_reo_cmd_send(struct ath12k_base *ab, struct hal_srng *srng,
+ enum hal_reo_cmd_type type,
+ struct ath12k_hal_reo_cmd *cmd)
{
- struct hal_tlv_64_hdr *reo_desc;
+ struct ath12k_hal *hal = &ab->hal;
+ void *reo_desc;
int ret;
spin_lock_bh(&srng->lock);
@@ -238,13 +235,13 @@ int ath12k_hal_reo_cmd_send(struct ath12k_base *ab, struct hal_srng *srng,
switch (type) {
case HAL_REO_CMD_GET_QUEUE_STATS:
- ret = ath12k_hal_reo_cmd_queue_stats(reo_desc, cmd);
+ ret = ath12k_wifi7_hal_reo_cmd_queue_stats(hal, reo_desc, cmd);
break;
case HAL_REO_CMD_FLUSH_CACHE:
- ret = ath12k_hal_reo_cmd_flush_cache(&ab->hal, reo_desc, cmd);
+ ret = ath12k_wifi7_hal_reo_cmd_flush_cache(hal, reo_desc, cmd);
break;
case HAL_REO_CMD_UPDATE_RX_QUEUE:
- ret = ath12k_hal_reo_cmd_update_rx_queue(reo_desc, cmd);
+ ret = ath12k_wifi7_hal_reo_cmd_update_rx_queue(hal, reo_desc, cmd);
break;
case HAL_REO_CMD_FLUSH_QUEUE:
case HAL_REO_CMD_UNBLOCK_CACHE:
@@ -265,8 +262,9 @@ out:
return ret;
}
-void ath12k_hal_rx_buf_addr_info_set(struct ath12k_buffer_addr *binfo,
- dma_addr_t paddr, u32 cookie, u8 manager)
+void ath12k_wifi7_hal_rx_buf_addr_info_set(struct ath12k_buffer_addr *binfo,
+ dma_addr_t paddr, u32 cookie,
+ u8 manager)
{
u32 paddr_lo, paddr_hi;
@@ -278,9 +276,9 @@ void ath12k_hal_rx_buf_addr_info_set(struct ath12k_buffer_addr *binfo,
le32_encode_bits(manager, BUFFER_ADDR_INFO1_RET_BUF_MGR);
}
-void ath12k_hal_rx_buf_addr_info_get(struct ath12k_buffer_addr *binfo,
- dma_addr_t *paddr,
- u32 *cookie, u8 *rbm)
+void ath12k_wifi7_hal_rx_buf_addr_info_get(struct ath12k_buffer_addr *binfo,
+ dma_addr_t *paddr,
+ u32 *cookie, u8 *rbm)
{
*paddr = (((u64)le32_get_bits(binfo->info1, BUFFER_ADDR_INFO1_ADDR)) << 32) |
le32_get_bits(binfo->info0, BUFFER_ADDR_INFO0_ADDR);
@@ -288,9 +286,10 @@ void ath12k_hal_rx_buf_addr_info_get(struct ath12k_buffer_addr *binfo,
*rbm = le32_get_bits(binfo->info1, BUFFER_ADDR_INFO1_RET_BUF_MGR);
}
-void ath12k_hal_rx_msdu_link_info_get(struct hal_rx_msdu_link *link, u32 *num_msdus,
- u32 *msdu_cookies,
- enum hal_rx_buf_return_buf_manager *rbm)
+void
+ath12k_wifi7_hal_rx_msdu_link_info_get(struct hal_rx_msdu_link *link,
+ u32 *num_msdus, u32 *msdu_cookies,
+ enum hal_rx_buf_return_buf_manager *rbm)
{
struct hal_rx_msdu_details *msdu;
u32 val;
@@ -317,10 +316,11 @@ void ath12k_hal_rx_msdu_link_info_get(struct hal_rx_msdu_link *link, u32 *num_ms
}
}
-int ath12k_hal_desc_reo_parse_err(struct ath12k_base *ab,
- struct hal_reo_dest_ring *desc,
- dma_addr_t *paddr, u32 *desc_bank)
+int ath12k_wifi7_hal_desc_reo_parse_err(struct ath12k_dp *dp,
+ struct hal_reo_dest_ring *desc,
+ dma_addr_t *paddr, u32 *desc_bank)
{
+ struct ath12k_base *ab = dp->ab;
enum hal_reo_dest_ring_push_reason push_reason;
enum hal_reo_dest_ring_error_code err_code;
u32 cookie;
@@ -329,7 +329,7 @@ int ath12k_hal_desc_reo_parse_err(struct ath12k_base *ab,
HAL_REO_DEST_RING_INFO0_PUSH_REASON);
err_code = le32_get_bits(desc->info0,
HAL_REO_DEST_RING_INFO0_ERROR_CODE);
- ab->device_stats.reo_error[err_code]++;
+ dp->device_stats.reo_error[err_code]++;
if (push_reason != HAL_REO_DEST_RING_PUSH_REASON_ERR_DETECTED &&
push_reason != HAL_REO_DEST_RING_PUSH_REASON_ROUTING_INSTRUCTION) {
@@ -338,14 +338,15 @@ int ath12k_hal_desc_reo_parse_err(struct ath12k_base *ab,
return -EINVAL;
}
- ath12k_hal_rx_reo_ent_paddr_get(ab, &desc->buf_addr_info, paddr, &cookie);
+ ath12k_wifi7_hal_rx_reo_ent_paddr_get(&desc->buf_addr_info, paddr,
+ &cookie);
*desc_bank = u32_get_bits(cookie, DP_LINK_DESC_BANK_MASK);
return 0;
}
-int ath12k_hal_wbm_desc_parse_err(struct ath12k_base *ab, void *desc,
- struct hal_rx_wbm_rel_info *rel_info)
+int ath12k_wifi7_hal_wbm_desc_parse_err(struct ath12k_dp *dp, void *desc,
+ struct hal_rx_wbm_rel_info *rel_info)
{
struct hal_wbm_release_ring *wbm_desc = desc;
struct hal_wbm_release_ring_cc_rx *wbm_cc_desc = desc;
@@ -378,7 +379,7 @@ int ath12k_hal_wbm_desc_parse_err(struct ath12k_base *ab, void *desc,
val = le32_get_bits(wbm_desc->buf_addr_info.info1,
BUFFER_ADDR_INFO1_RET_BUF_MGR);
if (val != HAL_RX_BUF_RBM_SW3_BM) {
- ab->device_stats.invalid_rbm++;
+ dp->device_stats.invalid_rbm++;
return -EINVAL;
}
@@ -390,7 +391,7 @@ int ath12k_hal_wbm_desc_parse_err(struct ath12k_base *ab, void *desc,
val = le32_get_bits(wbm_cc_desc->info0,
HAL_WBM_RELEASE_RX_CC_INFO0_RBM);
if (val != HAL_RX_BUF_RBM_SW3_BM) {
- ab->device_stats.invalid_rbm++;
+ dp->device_stats.invalid_rbm++;
return -EINVAL;
}
@@ -429,12 +430,13 @@ int ath12k_hal_wbm_desc_parse_err(struct ath12k_base *ab, void *desc,
HAL_WBM_RELEASE_INFO0_RXDMA_ERROR_CODE);
}
+ rel_info->peer_metadata = wbm_desc->info2;
+
return 0;
}
-void ath12k_hal_rx_reo_ent_paddr_get(struct ath12k_base *ab,
- struct ath12k_buffer_addr *buff_addr,
- dma_addr_t *paddr, u32 *cookie)
+void ath12k_wifi7_hal_rx_reo_ent_paddr_get(struct ath12k_buffer_addr *buff_addr,
+ dma_addr_t *paddr, u32 *cookie)
{
*paddr = ((u64)(le32_get_bits(buff_addr->info1,
BUFFER_ADDR_INFO1_ADDR)) << 32) |
@@ -443,10 +445,10 @@ void ath12k_hal_rx_reo_ent_paddr_get(struct ath12k_base *ab,
*cookie = le32_get_bits(buff_addr->info1, BUFFER_ADDR_INFO1_SW_COOKIE);
}
-void ath12k_hal_rx_reo_ent_buf_paddr_get(void *rx_desc, dma_addr_t *paddr,
- u32 *sw_cookie,
- struct ath12k_buffer_addr **pp_buf_addr,
- u8 *rbm, u32 *msdu_cnt)
+void ath12k_wifi7_hal_rx_reo_ent_buf_paddr_get(void *rx_desc, dma_addr_t *paddr,
+ u32 *sw_cookie,
+ struct ath12k_buffer_addr **pp_buf_addr,
+ u8 *rbm, u32 *msdu_cnt)
{
struct hal_reo_entrance_ring *reo_ent_ring =
(struct hal_reo_entrance_ring *)rx_desc;
@@ -474,11 +476,14 @@ void ath12k_hal_rx_reo_ent_buf_paddr_get(void *rx_desc, dma_addr_t *paddr,
*pp_buf_addr = (void *)buf_addr_info;
}
-void ath12k_hal_rx_msdu_list_get(struct ath12k *ar,
- struct hal_rx_msdu_link *link_desc,
- struct hal_rx_msdu_list *msdu_list,
- u16 *num_msdus)
+void ath12k_wifi7_hal_rx_msdu_list_get(struct ath12k *ar,
+ void *link_desc_opaque,
+ void *msdu_list_opaque, u16 *num_msdus)
{
+ struct hal_rx_msdu_link *link_desc =
+ (struct hal_rx_msdu_link *)link_desc_opaque;
+ struct hal_rx_msdu_list *msdu_list =
+ (struct hal_rx_msdu_list *)msdu_list_opaque;
struct hal_rx_msdu_details *msdu_details = NULL;
struct rx_msdu_desc *msdu_desc_info = NULL;
u32 last = 0, first = 0;
@@ -523,10 +528,11 @@ void ath12k_hal_rx_msdu_list_get(struct ath12k *ar,
*num_msdus = i;
}
-void ath12k_hal_rx_msdu_link_desc_set(struct ath12k_base *ab,
- struct hal_wbm_release_ring *desc,
- struct ath12k_buffer_addr *buf_addr_info,
- enum hal_wbm_rel_bm_act action)
+void
+ath12k_wifi7_hal_rx_msdu_link_desc_set(struct ath12k_base *ab,
+ struct hal_wbm_release_ring *desc,
+ struct ath12k_buffer_addr *buf_addr_info,
+ enum hal_wbm_rel_bm_act action)
{
desc->buf_addr_info = *buf_addr_info;
desc->info0 |= le32_encode_bits(HAL_WBM_REL_SRC_MODULE_SW,
@@ -536,12 +542,10 @@ void ath12k_hal_rx_msdu_link_desc_set(struct ath12k_base *ab,
HAL_WBM_RELEASE_INFO0_DESC_TYPE);
}
-void ath12k_hal_reo_status_queue_stats(struct ath12k_base *ab, struct hal_tlv_64_hdr *tlv,
- struct hal_reo_status *status)
+void ath12k_wifi7_hal_reo_status_queue_stats(struct ath12k_base *ab,
+ struct hal_reo_get_queue_stats_status *desc,
+ struct hal_reo_status *status)
{
- struct hal_reo_get_queue_stats_status *desc =
- (struct hal_reo_get_queue_stats_status *)tlv->value;
-
status->uniform_hdr.cmd_num =
le32_get_bits(desc->hdr.info0,
HAL_REO_STATUS_HDR_INFO0_STATUS_NUM);
@@ -599,12 +603,10 @@ void ath12k_hal_reo_status_queue_stats(struct ath12k_base *ab, struct hal_tlv_64
HAL_REO_GET_QUEUE_STATS_STATUS_INFO5_LOOPING_CNT));
}
-void ath12k_hal_reo_flush_queue_status(struct ath12k_base *ab, struct hal_tlv_64_hdr *tlv,
- struct hal_reo_status *status)
+void ath12k_wifi7_hal_reo_flush_queue_status(struct ath12k_base *ab,
+ struct hal_reo_flush_queue_status *desc,
+ struct hal_reo_status *status)
{
- struct hal_reo_flush_queue_status *desc =
- (struct hal_reo_flush_queue_status *)tlv->value;
-
status->uniform_hdr.cmd_num =
le32_get_bits(desc->hdr.info0,
HAL_REO_STATUS_HDR_INFO0_STATUS_NUM);
@@ -616,12 +618,12 @@ void ath12k_hal_reo_flush_queue_status(struct ath12k_base *ab, struct hal_tlv_64
HAL_REO_FLUSH_QUEUE_INFO0_ERR_DETECTED);
}
-void ath12k_hal_reo_flush_cache_status(struct ath12k_base *ab, struct hal_tlv_64_hdr *tlv,
- struct hal_reo_status *status)
+void
+ath12k_wifi7_hal_reo_flush_cache_status(struct ath12k_base *ab,
+ struct hal_reo_flush_cache_status *desc,
+ struct hal_reo_status *status)
{
struct ath12k_hal *hal = &ab->hal;
- struct hal_reo_flush_cache_status *desc =
- (struct hal_reo_flush_cache_status *)tlv->value;
status->uniform_hdr.cmd_num =
le32_get_bits(desc->hdr.info0,
@@ -657,12 +659,11 @@ void ath12k_hal_reo_flush_cache_status(struct ath12k_base *ab, struct hal_tlv_64
HAL_REO_FLUSH_CACHE_STATUS_INFO0_FLUSH_COUNT);
}
-void ath12k_hal_reo_unblk_cache_status(struct ath12k_base *ab, struct hal_tlv_64_hdr *tlv,
- struct hal_reo_status *status)
+void ath12k_wifi7_hal_reo_unblk_cache_status(struct ath12k_base *ab,
+ struct hal_reo_unblock_cache_status *desc,
+ struct hal_reo_status *status)
{
struct ath12k_hal *hal = &ab->hal;
- struct hal_reo_unblock_cache_status *desc =
- (struct hal_reo_unblock_cache_status *)tlv->value;
status->uniform_hdr.cmd_num =
le32_get_bits(desc->hdr.info0,
@@ -684,13 +685,11 @@ void ath12k_hal_reo_unblk_cache_status(struct ath12k_base *ab, struct hal_tlv_64
hal->avail_blk_resource &= ~BIT(hal->current_blk_index);
}
-void ath12k_hal_reo_flush_timeout_list_status(struct ath12k_base *ab,
- struct hal_tlv_64_hdr *tlv,
- struct hal_reo_status *status)
+void
+ath12k_wifi7_hal_reo_flush_timeout_list_status(struct ath12k_base *ab,
+ struct hal_reo_flush_timeout_list_status *desc,
+ struct hal_reo_status *status)
{
- struct hal_reo_flush_timeout_list_status *desc =
- (struct hal_reo_flush_timeout_list_status *)tlv->value;
-
status->uniform_hdr.cmd_num =
le32_get_bits(desc->hdr.info0,
HAL_REO_STATUS_HDR_INFO0_STATUS_NUM);
@@ -713,13 +712,11 @@ void ath12k_hal_reo_flush_timeout_list_status(struct ath12k_base *ab,
HAL_REO_FLUSH_TIMEOUT_STATUS_INFO1_FWD_BUF_COUNT);
}
-void ath12k_hal_reo_desc_thresh_reached_status(struct ath12k_base *ab,
- struct hal_tlv_64_hdr *tlv,
- struct hal_reo_status *status)
+void
+ath12k_wifi7_hal_reo_desc_thresh_reached_status(struct ath12k_base *ab,
+ struct hal_reo_desc_thresh_reached_status *desc,
+ struct hal_reo_status *status)
{
- struct hal_reo_desc_thresh_reached_status *desc =
- (struct hal_reo_desc_thresh_reached_status *)tlv->value;
-
status->uniform_hdr.cmd_num =
le32_get_bits(desc->hdr.info0,
HAL_REO_STATUS_HDR_INFO0_STATUS_NUM);
@@ -748,13 +745,10 @@ void ath12k_hal_reo_desc_thresh_reached_status(struct ath12k_base *ab,
HAL_REO_DESC_THRESH_STATUS_INFO4_LINK_DESC_COUNTER_SUM);
}
-void ath12k_hal_reo_update_rx_reo_queue_status(struct ath12k_base *ab,
- struct hal_tlv_64_hdr *tlv,
- struct hal_reo_status *status)
+void ath12k_wifi7_hal_reo_update_rx_reo_queue_status(struct ath12k_base *ab,
+ struct hal_reo_status_hdr *desc,
+ struct hal_reo_status *status)
{
- struct hal_reo_status_hdr *desc =
- (struct hal_reo_status_hdr *)tlv->value;
-
status->uniform_hdr.cmd_num =
le32_get_bits(desc->info0,
HAL_REO_STATUS_HDR_INFO0_STATUS_NUM);
@@ -763,7 +757,7 @@ void ath12k_hal_reo_update_rx_reo_queue_status(struct ath12k_base *ab,
HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS);
}
-u32 ath12k_hal_reo_qdesc_size(u32 ba_window_size, u8 tid)
+u32 ath12k_wifi7_hal_reo_qdesc_size(u32 ba_window_size, u8 tid)
{
u32 num_ext_desc, num_1k_desc = 0;
@@ -789,15 +783,15 @@ u32 ath12k_hal_reo_qdesc_size(u32 ba_window_size, u8 tid)
(num_1k_desc * sizeof(struct hal_rx_reo_queue_1k));
}
-void ath12k_hal_reo_qdesc_setup(struct hal_rx_reo_queue *qdesc,
- int tid, u32 ba_window_size,
- u32 start_seq, enum hal_pn_type type)
+void ath12k_wifi7_hal_reo_qdesc_setup(struct hal_rx_reo_queue *qdesc,
+ int tid, u32 ba_window_size,
+ u32 start_seq, enum hal_pn_type type)
{
struct hal_rx_reo_queue_ext *ext_desc;
- ath12k_hal_reo_set_desc_hdr(&qdesc->desc_hdr, HAL_DESC_REO_OWNED,
- HAL_DESC_REO_QUEUE_DESC,
- REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_0);
+ ath12k_wifi7_hal_reo_set_desc_hdr(&qdesc->desc_hdr, HAL_DESC_REO_OWNED,
+ HAL_DESC_REO_QUEUE_DESC,
+ REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_0);
qdesc->rx_queue_num = le32_encode_bits(tid, HAL_RX_REO_QUEUE_RX_QUEUE_NUMBER);
@@ -855,21 +849,24 @@ void ath12k_hal_reo_qdesc_setup(struct hal_rx_reo_queue *qdesc,
* queue descriptor in Rx peer entry as part of dp_rx_tid_update.
*/
memset(ext_desc, 0, 3 * sizeof(*ext_desc));
- ath12k_hal_reo_set_desc_hdr(&ext_desc->desc_hdr, HAL_DESC_REO_OWNED,
- HAL_DESC_REO_QUEUE_EXT_DESC,
- REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_1);
+ ath12k_wifi7_hal_reo_set_desc_hdr(&ext_desc->desc_hdr,
+ HAL_DESC_REO_OWNED,
+ HAL_DESC_REO_QUEUE_EXT_DESC,
+ REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_1);
ext_desc++;
- ath12k_hal_reo_set_desc_hdr(&ext_desc->desc_hdr, HAL_DESC_REO_OWNED,
- HAL_DESC_REO_QUEUE_EXT_DESC,
- REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_2);
+ ath12k_wifi7_hal_reo_set_desc_hdr(&ext_desc->desc_hdr,
+ HAL_DESC_REO_OWNED,
+ HAL_DESC_REO_QUEUE_EXT_DESC,
+ REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_2);
ext_desc++;
- ath12k_hal_reo_set_desc_hdr(&ext_desc->desc_hdr, HAL_DESC_REO_OWNED,
- HAL_DESC_REO_QUEUE_EXT_DESC,
- REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_3);
+ ath12k_wifi7_hal_reo_set_desc_hdr(&ext_desc->desc_hdr,
+ HAL_DESC_REO_OWNED,
+ HAL_DESC_REO_QUEUE_EXT_DESC,
+ REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_3);
}
-void ath12k_hal_reo_init_cmd_ring(struct ath12k_base *ab,
- struct hal_srng *srng)
+void ath12k_wifi7_hal_reo_init_cmd_ring_tlv64(struct ath12k_base *ab,
+ struct hal_srng *srng)
{
struct hal_srng_params params;
struct hal_tlv_64_hdr *tlv;
@@ -893,8 +890,35 @@ void ath12k_hal_reo_init_cmd_ring(struct ath12k_base *ab,
}
}
-void ath12k_hal_reo_hw_setup(struct ath12k_base *ab, u32 ring_hash_map)
+void ath12k_wifi7_hal_reo_init_cmd_ring_tlv32(struct ath12k_base *ab,
+ struct hal_srng *srng)
{
+ struct hal_reo_get_queue_stats *desc;
+ struct hal_srng_params params;
+ struct hal_tlv_hdr *tlv;
+ int i, cmd_num = 1;
+ int entry_size;
+ u8 *entry;
+
+ memset(&params, 0, sizeof(params));
+
+ entry_size = ath12k_hal_srng_get_entrysize(ab, HAL_REO_CMD);
+ ath12k_hal_srng_get_params(ab, srng, &params);
+ entry = (u8 *)params.ring_base_vaddr;
+
+ for (i = 0; i < params.num_entries; i++) {
+ tlv = (struct hal_tlv_hdr *)entry;
+ desc = (struct hal_reo_get_queue_stats *)tlv->value;
+ desc->cmd.info0 = le32_encode_bits(cmd_num++,
+ HAL_REO_CMD_HDR_INFO0_CMD_NUMBER);
+ entry += entry_size;
+ }
+}
+
+void ath12k_wifi7_hal_reo_hw_setup(struct ath12k_base *ab, u32 ring_hash_map)
+{
+ struct ath12k_hal *hal = &ab->hal;
+
u32 reo_base = HAL_SEQ_WCSS_UMAC_REO_REG;
u32 val;
@@ -904,7 +928,7 @@ void ath12k_hal_reo_hw_setup(struct ath12k_base *ab, u32 ring_hash_map)
u32_encode_bits(1, HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE);
ath12k_hif_write32(ab, reo_base + HAL_REO1_GEN_ENABLE, val);
- val = ath12k_hif_read32(ab, reo_base + HAL_REO1_MISC_CTRL_ADDR(ab));
+ val = ath12k_hif_read32(ab, reo_base + HAL_REO1_MISC_CTRL_ADDR(hal));
val &= ~(HAL_REO1_MISC_CTL_FRAG_DST_RING |
HAL_REO1_MISC_CTL_BAR_DST_RING);
@@ -912,15 +936,15 @@ void ath12k_hal_reo_hw_setup(struct ath12k_base *ab, u32 ring_hash_map)
HAL_REO1_MISC_CTL_FRAG_DST_RING);
val |= u32_encode_bits(HAL_SRNG_RING_ID_REO2SW0,
HAL_REO1_MISC_CTL_BAR_DST_RING);
- ath12k_hif_write32(ab, reo_base + HAL_REO1_MISC_CTRL_ADDR(ab), val);
+ ath12k_hif_write32(ab, reo_base + HAL_REO1_MISC_CTRL_ADDR(hal), val);
- ath12k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_0(ab),
+ ath12k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_0(hal),
HAL_DEFAULT_BE_BK_VI_REO_TIMEOUT_USEC);
- ath12k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_1(ab),
+ ath12k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_1(hal),
HAL_DEFAULT_BE_BK_VI_REO_TIMEOUT_USEC);
- ath12k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_2(ab),
+ ath12k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_2(hal),
HAL_DEFAULT_BE_BK_VI_REO_TIMEOUT_USEC);
- ath12k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_3(ab),
+ ath12k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_3(hal),
HAL_DEFAULT_VO_REO_TIMEOUT_USEC);
ath12k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_2,
@@ -929,19 +953,21 @@ void ath12k_hal_reo_hw_setup(struct ath12k_base *ab, u32 ring_hash_map)
ring_hash_map);
}
-void ath12k_hal_reo_shared_qaddr_cache_clear(struct ath12k_base *ab)
+void ath12k_wifi7_hal_reo_shared_qaddr_cache_clear(struct ath12k_base *ab)
{
u32 val;
+ struct ath12k_hal *hal = &ab->hal;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
- lockdep_assert_held(&ab->base_lock);
+ lockdep_assert_held(&dp->dp_lock);
val = ath12k_hif_read32(ab, HAL_SEQ_WCSS_UMAC_REO_REG +
- HAL_REO1_QDESC_ADDR(ab));
+ HAL_REO1_QDESC_ADDR(hal));
val |= u32_encode_bits(1, HAL_REO_QDESC_ADDR_READ_CLEAR_QDESC_ARRAY);
ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG +
- HAL_REO1_QDESC_ADDR(ab), val);
+ HAL_REO1_QDESC_ADDR(hal), val);
val &= ~HAL_REO_QDESC_ADDR_READ_CLEAR_QDESC_ARRAY;
ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG +
- HAL_REO1_QDESC_ADDR(ab), val);
+ HAL_REO1_QDESC_ADDR(hal), val);
}
diff --git a/drivers/net/wireless/ath/ath12k/hal_rx.h b/drivers/net/wireless/ath/ath12k/wifi7/hal_rx.h
index d1ad7747b82c..ac2a8ac03288 100644
--- a/drivers/net/wireless/ath/ath12k/hal_rx.h
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_rx.h
@@ -1,12 +1,16 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH12K_HAL_RX_H
#define ATH12K_HAL_RX_H
+#include "hal_desc.h"
+
+struct hal_reo_status;
+
struct hal_rx_wbm_rel_info {
u32 cookie;
enum hal_wbm_rel_src_module err_rel_src;
@@ -17,11 +21,9 @@ struct hal_rx_wbm_rel_info {
bool continuation;
void *rx_desc;
bool hw_cc_done;
+ __le32 peer_metadata;
};
-#define HAL_INVALID_PEERID 0x3fff
-#define VHT_SIG_SU_NSS_MASK 0x7
-
#define HAL_RX_MPDU_INFO_PN_GET_BYTE1(__val) \
le32_get_bits((__val), GENMASK(7, 0))
@@ -39,69 +41,10 @@ struct hal_rx_mon_status_tlv_hdr {
u8 value[];
};
-enum hal_rx_su_mu_coding {
- HAL_RX_SU_MU_CODING_BCC,
- HAL_RX_SU_MU_CODING_LDPC,
- HAL_RX_SU_MU_CODING_MAX,
-};
-
-enum hal_rx_gi {
- HAL_RX_GI_0_8_US,
- HAL_RX_GI_0_4_US,
- HAL_RX_GI_1_6_US,
- HAL_RX_GI_3_2_US,
- HAL_RX_GI_MAX,
-};
-
-enum hal_rx_bw {
- HAL_RX_BW_20MHZ,
- HAL_RX_BW_40MHZ,
- HAL_RX_BW_80MHZ,
- HAL_RX_BW_160MHZ,
- HAL_RX_BW_320MHZ,
- HAL_RX_BW_MAX,
-};
-
-enum hal_rx_preamble {
- HAL_RX_PREAMBLE_11A,
- HAL_RX_PREAMBLE_11B,
- HAL_RX_PREAMBLE_11N,
- HAL_RX_PREAMBLE_11AC,
- HAL_RX_PREAMBLE_11AX,
- HAL_RX_PREAMBLE_11BA,
- HAL_RX_PREAMBLE_11BE,
- HAL_RX_PREAMBLE_MAX,
-};
-
-enum hal_rx_reception_type {
- HAL_RX_RECEPTION_TYPE_SU,
- HAL_RX_RECEPTION_TYPE_MU_MIMO,
- HAL_RX_RECEPTION_TYPE_MU_OFDMA,
- HAL_RX_RECEPTION_TYPE_MU_OFDMA_MIMO,
- HAL_RX_RECEPTION_TYPE_MAX,
-};
-
-enum hal_rx_legacy_rate {
- HAL_RX_LEGACY_RATE_1_MBPS,
- HAL_RX_LEGACY_RATE_2_MBPS,
- HAL_RX_LEGACY_RATE_5_5_MBPS,
- HAL_RX_LEGACY_RATE_6_MBPS,
- HAL_RX_LEGACY_RATE_9_MBPS,
- HAL_RX_LEGACY_RATE_11_MBPS,
- HAL_RX_LEGACY_RATE_12_MBPS,
- HAL_RX_LEGACY_RATE_18_MBPS,
- HAL_RX_LEGACY_RATE_24_MBPS,
- HAL_RX_LEGACY_RATE_36_MBPS,
- HAL_RX_LEGACY_RATE_48_MBPS,
- HAL_RX_LEGACY_RATE_54_MBPS,
- HAL_RX_LEGACY_RATE_INVALID,
-};
-
#define HAL_TLV_STATUS_PPDU_NOT_DONE 0
#define HAL_TLV_STATUS_PPDU_DONE 1
#define HAL_TLV_STATUS_BUF_DONE 2
#define HAL_TLV_STATUS_PPDU_NON_STD_DONE 3
-#define HAL_RX_FCS_LEN 4
enum hal_rx_mon_status {
HAL_RX_MON_STATUS_PPDU_NOT_DONE,
@@ -113,167 +56,6 @@ enum hal_rx_mon_status {
HAL_RX_MON_STATUS_MSDU_END,
};
-#define HAL_RX_MAX_MPDU 1024
-#define HAL_RX_NUM_WORDS_PER_PPDU_BITMAP (HAL_RX_MAX_MPDU >> 5)
-
-struct hal_rx_user_status {
- u32 mcs:4,
- nss:3,
- ofdma_info_valid:1,
- ul_ofdma_ru_start_index:7,
- ul_ofdma_ru_width:7,
- ul_ofdma_ru_size:8;
- u32 ul_ofdma_user_v0_word0;
- u32 ul_ofdma_user_v0_word1;
- u32 ast_index;
- u32 tid;
- u16 tcp_msdu_count;
- u16 tcp_ack_msdu_count;
- u16 udp_msdu_count;
- u16 other_msdu_count;
- u16 frame_control;
- u8 frame_control_info_valid;
- u8 data_sequence_control_info_valid;
- u16 first_data_seq_ctrl;
- u32 preamble_type;
- u16 ht_flags;
- u16 vht_flags;
- u16 he_flags;
- u8 rs_flags;
- u8 ldpc;
- u32 mpdu_cnt_fcs_ok;
- u32 mpdu_cnt_fcs_err;
- u32 mpdu_fcs_ok_bitmap[HAL_RX_NUM_WORDS_PER_PPDU_BITMAP];
- u32 mpdu_ok_byte_count;
- u32 mpdu_err_byte_count;
- bool ampdu_present;
- u16 ampdu_id;
-};
-
-#define HAL_MAX_UL_MU_USERS 37
-
-struct hal_rx_u_sig_info {
- bool ul_dl;
- u8 bw;
- u8 ppdu_type_comp_mode;
- u8 eht_sig_mcs;
- u8 num_eht_sig_sym;
- struct ieee80211_radiotap_eht_usig usig;
-};
-
-#define HAL_RX_MON_MAX_AGGR_SIZE 128
-
-struct hal_rx_tlv_aggr_info {
- bool in_progress;
- u16 cur_len;
- u16 tlv_tag;
- u8 buf[HAL_RX_MON_MAX_AGGR_SIZE];
-};
-
-struct hal_rx_radiotap_eht {
- __le32 known;
- __le32 data[9];
-};
-
-#define EHT_MAX_USER_INFO 4
-
-struct hal_rx_eht_info {
- u8 num_user_info;
- struct hal_rx_radiotap_eht eht;
- u32 user_info[EHT_MAX_USER_INFO];
-};
-
-struct hal_rx_mon_ppdu_info {
- u32 ppdu_id;
- u32 last_ppdu_id;
- u64 ppdu_ts;
- u32 num_mpdu_fcs_ok;
- u32 num_mpdu_fcs_err;
- u32 preamble_type;
- u32 mpdu_len;
- u16 chan_num;
- u16 freq;
- u16 tcp_msdu_count;
- u16 tcp_ack_msdu_count;
- u16 udp_msdu_count;
- u16 other_msdu_count;
- u16 peer_id;
- u8 rate;
- u8 mcs;
- u8 nss;
- u8 bw;
- u8 vht_flag_values1;
- u8 vht_flag_values2;
- u8 vht_flag_values3[4];
- u8 vht_flag_values4;
- u8 vht_flag_values5;
- u16 vht_flag_values6;
- u8 is_stbc;
- u8 gi;
- u8 sgi;
- u8 ldpc;
- u8 beamformed;
- u8 rssi_comb;
- u16 tid;
- u8 fc_valid;
- u16 ht_flags;
- u16 vht_flags;
- u16 he_flags;
- u16 he_mu_flags;
- u8 dcm;
- u8 ru_alloc;
- u8 reception_type;
- u64 tsft;
- u64 rx_duration;
- u16 frame_control;
- u32 ast_index;
- u8 rs_fcs_err;
- u8 rs_flags;
- u8 cck_flag;
- u8 ofdm_flag;
- u8 ulofdma_flag;
- u8 frame_control_info_valid;
- u16 he_per_user_1;
- u16 he_per_user_2;
- u8 he_per_user_position;
- u8 he_per_user_known;
- u16 he_flags1;
- u16 he_flags2;
- u8 he_RU[4];
- u16 he_data1;
- u16 he_data2;
- u16 he_data3;
- u16 he_data4;
- u16 he_data5;
- u16 he_data6;
- u32 ppdu_len;
- u32 prev_ppdu_id;
- u32 device_id;
- u16 first_data_seq_ctrl;
- u8 monitor_direct_used;
- u8 data_sequence_control_info_valid;
- u8 ltf_size;
- u8 rxpcu_filter_pass;
- s8 rssi_chain[8][8];
- u32 num_users;
- u32 mpdu_fcs_ok_bitmap[HAL_RX_NUM_WORDS_PER_PPDU_BITMAP];
- u8 addr1[ETH_ALEN];
- u8 addr2[ETH_ALEN];
- u8 addr3[ETH_ALEN];
- u8 addr4[ETH_ALEN];
- struct hal_rx_user_status userstats[HAL_MAX_UL_MU_USERS];
- u8 userid;
- bool first_msdu_in_mpdu;
- bool is_ampdu;
- u8 medium_prot_type;
- bool ppdu_continuation;
- bool eht_usig;
- struct hal_rx_u_sig_info u_sig_info;
- bool is_eht;
- struct hal_rx_eht_info eht_info;
- struct hal_rx_tlv_aggr_info tlv_aggr;
-};
-
#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)
@@ -531,11 +313,6 @@ struct hal_rx_rxpcu_classification_overview {
u32 rsvd0;
} __packed;
-struct hal_rx_msdu_desc_info {
- u32 msdu_flags;
- u16 msdu_len; /* 14 bits for length */
-};
-
#define HAL_RX_NUM_MSDU_DESC 6
struct hal_rx_msdu_list {
struct hal_rx_msdu_desc_info msdu_info[HAL_RX_NUM_MSDU_DESC];
@@ -588,15 +365,6 @@ struct hal_rx_resp_req_info {
#define REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_2 0xBDBEEF
#define REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_3 0xCDBEEF
-#define HAL_RX_UL_OFDMA_USER_INFO_V0_W0_VALID BIT(30)
-#define HAL_RX_UL_OFDMA_USER_INFO_V0_W0_VER BIT(31)
-#define HAL_RX_UL_OFDMA_USER_INFO_V0_W1_NSS GENMASK(2, 0)
-#define HAL_RX_UL_OFDMA_USER_INFO_V0_W1_MCS GENMASK(6, 3)
-#define HAL_RX_UL_OFDMA_USER_INFO_V0_W1_LDPC BIT(7)
-#define HAL_RX_UL_OFDMA_USER_INFO_V0_W1_DCM BIT(8)
-#define HAL_RX_UL_OFDMA_USER_INFO_V0_W1_RU_START GENMASK(15, 9)
-#define HAL_RX_UL_OFDMA_USER_INFO_V0_W1_RU_SIZE GENMASK(18, 16)
-
/* HE Radiotap data1 Mask */
#define HE_SU_FORMAT_TYPE 0x0000
#define HE_EXT_SU_FORMAT_TYPE 0x0001
@@ -1044,128 +812,64 @@ enum hal_mon_reception_type {
#define HAL_RU_PER80(ru_per80, num_80mhz, ru_idx_per80mhz) \
(HAL_RU(ru_per80, num_80mhz, ru_idx_per80mhz))
-#define RU_INVALID 0
-#define RU_26 1
-#define RU_52 2
-#define RU_106 4
-#define RU_242 9
-#define RU_484 18
-#define RU_996 37
-#define RU_2X996 74
-#define RU_3X996 111
-#define RU_4X996 148
-#define RU_52_26 (RU_52 + RU_26)
-#define RU_106_26 (RU_106 + RU_26)
-#define RU_484_242 (RU_484 + RU_242)
-#define RU_996_484 (RU_996 + RU_484)
-#define RU_996_484_242 (RU_996 + RU_484_242)
-#define RU_2X996_484 (RU_2X996 + RU_484)
-#define RU_3X996_484 (RU_3X996 + RU_484)
-
-enum ath12k_eht_ru_size {
- ATH12K_EHT_RU_26,
- ATH12K_EHT_RU_52,
- ATH12K_EHT_RU_106,
- ATH12K_EHT_RU_242,
- ATH12K_EHT_RU_484,
- ATH12K_EHT_RU_996,
- ATH12K_EHT_RU_996x2,
- ATH12K_EHT_RU_996x4,
- ATH12K_EHT_RU_52_26,
- ATH12K_EHT_RU_106_26,
- ATH12K_EHT_RU_484_242,
- ATH12K_EHT_RU_996_484,
- ATH12K_EHT_RU_996_484_242,
- ATH12K_EHT_RU_996x2_484,
- ATH12K_EHT_RU_996x3,
- ATH12K_EHT_RU_996x3_484,
-
- /* Keep last */
- ATH12K_EHT_RU_INVALID,
-};
-
-#define HAL_RX_RU_ALLOC_TYPE_MAX ATH12K_EHT_RU_INVALID
-
-static inline
-enum nl80211_he_ru_alloc ath12k_he_ru_tones_to_nl80211_he_ru_alloc(u16 ru_tones)
-{
- enum nl80211_he_ru_alloc ret;
-
- switch (ru_tones) {
- case RU_52:
- ret = NL80211_RATE_INFO_HE_RU_ALLOC_52;
- break;
- case RU_106:
- ret = NL80211_RATE_INFO_HE_RU_ALLOC_106;
- break;
- case RU_242:
- ret = NL80211_RATE_INFO_HE_RU_ALLOC_242;
- break;
- case RU_484:
- ret = NL80211_RATE_INFO_HE_RU_ALLOC_484;
- break;
- case RU_996:
- ret = NL80211_RATE_INFO_HE_RU_ALLOC_996;
- break;
- case RU_2X996:
- ret = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
- break;
- case RU_26:
- fallthrough;
- default:
- ret = NL80211_RATE_INFO_HE_RU_ALLOC_26;
- break;
- }
- return ret;
-}
-
-void ath12k_hal_reo_status_queue_stats(struct ath12k_base *ab,
- struct hal_tlv_64_hdr *tlv,
- struct hal_reo_status *status);
-void ath12k_hal_reo_flush_queue_status(struct ath12k_base *ab,
- struct hal_tlv_64_hdr *tlv,
- struct hal_reo_status *status);
-void ath12k_hal_reo_flush_cache_status(struct ath12k_base *ab,
- struct hal_tlv_64_hdr *tlv,
- struct hal_reo_status *status);
-void ath12k_hal_reo_unblk_cache_status(struct ath12k_base *ab,
- struct hal_tlv_64_hdr *tlv,
- struct hal_reo_status *status);
-void ath12k_hal_reo_flush_timeout_list_status(struct ath12k_base *ab,
- struct hal_tlv_64_hdr *tlv,
- struct hal_reo_status *status);
-void ath12k_hal_reo_desc_thresh_reached_status(struct ath12k_base *ab,
- struct hal_tlv_64_hdr *tlv,
- struct hal_reo_status *status);
-void ath12k_hal_reo_update_rx_reo_queue_status(struct ath12k_base *ab,
- struct hal_tlv_64_hdr *tlv,
+void ath12k_wifi7_hal_reo_status_queue_stats(struct ath12k_base *ab,
+ struct hal_reo_get_queue_stats_status *desc,
+ struct hal_reo_status *status);
+void ath12k_wifi7_hal_reo_flush_queue_status(struct ath12k_base *ab,
+ struct hal_reo_flush_queue_status *desc,
+ struct hal_reo_status *status);
+void ath12k_wifi7_hal_reo_flush_cache_status(struct ath12k_base *ab,
+ struct hal_reo_flush_cache_status *desc,
+ struct hal_reo_status *status);
+void ath12k_wifi7_hal_reo_unblk_cache_status(struct ath12k_base *ab,
+ struct hal_reo_unblock_cache_status *desc,
+ struct hal_reo_status *status);
+void
+ath12k_wifi7_hal_reo_flush_timeout_list_status(struct ath12k_base *ab,
+ struct hal_reo_flush_timeout_list_status *desc,
struct hal_reo_status *status);
-void ath12k_hal_rx_msdu_link_info_get(struct hal_rx_msdu_link *link, u32 *num_msdus,
- u32 *msdu_cookies,
- enum hal_rx_buf_return_buf_manager *rbm);
-void ath12k_hal_rx_msdu_link_desc_set(struct ath12k_base *ab,
- struct hal_wbm_release_ring *desc,
- struct ath12k_buffer_addr *buf_addr_info,
- enum hal_wbm_rel_bm_act action);
-void ath12k_hal_rx_buf_addr_info_set(struct ath12k_buffer_addr *binfo,
- dma_addr_t paddr, u32 cookie, u8 manager);
-void ath12k_hal_rx_buf_addr_info_get(struct ath12k_buffer_addr *binfo,
- dma_addr_t *paddr,
- u32 *cookie, u8 *rbm);
-int ath12k_hal_desc_reo_parse_err(struct ath12k_base *ab,
- struct hal_reo_dest_ring *desc,
- dma_addr_t *paddr, u32 *desc_bank);
-int ath12k_hal_wbm_desc_parse_err(struct ath12k_base *ab, void *desc,
- struct hal_rx_wbm_rel_info *rel_info);
-void ath12k_hal_rx_reo_ent_paddr_get(struct ath12k_base *ab,
- struct ath12k_buffer_addr *buff_addr,
- dma_addr_t *paddr, u32 *cookie);
-void ath12k_hal_rx_reo_ent_buf_paddr_get(void *rx_desc, dma_addr_t *paddr, u32 *sw_cookie,
- struct ath12k_buffer_addr **pp_buf_addr,
- u8 *rbm, u32 *msdu_cnt);
-void ath12k_hal_rx_msdu_list_get(struct ath12k *ar,
- struct hal_rx_msdu_link *link_desc,
- struct hal_rx_msdu_list *msdu_list,
- u16 *num_msdus);
+void
+ath12k_wifi7_hal_reo_desc_thresh_reached_status(struct ath12k_base *ab,
+ struct hal_reo_desc_thresh_reached_status *desc,
+ struct hal_reo_status *status);
+void ath12k_wifi7_hal_reo_update_rx_reo_queue_status(struct ath12k_base *ab,
+ struct hal_reo_status_hdr *desc,
+ struct hal_reo_status *status);
+void ath12k_wifi7_hal_rx_msdu_link_info_get(struct hal_rx_msdu_link *link, u32 *num_msdus,
+ u32 *msdu_cookies,
+ enum hal_rx_buf_return_buf_manager *rbm);
+void ath12k_wifi7_hal_rx_msdu_link_desc_set(struct ath12k_base *ab,
+ struct hal_wbm_release_ring *desc,
+ struct ath12k_buffer_addr *buf_addr_info,
+ enum hal_wbm_rel_bm_act action);
+void ath12k_wifi7_hal_rx_buf_addr_info_set(struct ath12k_buffer_addr *binfo,
+ dma_addr_t paddr, u32 cookie, u8 manager);
+void ath12k_wifi7_hal_rx_buf_addr_info_get(struct ath12k_buffer_addr *binfo,
+ dma_addr_t *paddr,
+ u32 *cookie, u8 *rbm);
+int ath12k_wifi7_hal_desc_reo_parse_err(struct ath12k_dp *dp,
+ struct hal_reo_dest_ring *desc,
+ dma_addr_t *paddr, u32 *desc_bank);
+int ath12k_wifi7_hal_wbm_desc_parse_err(struct ath12k_dp *dp, void *desc,
+ struct hal_rx_wbm_rel_info *rel_info);
+void ath12k_wifi7_hal_rx_reo_ent_paddr_get(struct ath12k_buffer_addr *buff_addr,
+ dma_addr_t *paddr, u32 *cookie);
+void ath12k_wifi7_hal_rx_reo_ent_buf_paddr_get(void *rx_desc, dma_addr_t *paddr,
+ u32 *sw_cookie,
+ struct ath12k_buffer_addr **pp_buf_addr,
+ u8 *rbm, u32 *msdu_cnt);
+void ath12k_wifi7_hal_rx_msdu_list_get(struct ath12k *ar,
+ void *link_desc,
+ void *msdu_list_opaque,
+ u16 *num_msdus);
+void ath12k_wifi7_hal_reo_init_cmd_ring_tlv64(struct ath12k_base *ab,
+ struct hal_srng *srng);
+void ath12k_wifi7_hal_reo_init_cmd_ring_tlv32(struct ath12k_base *ab,
+ struct hal_srng *srng);
+void ath12k_wifi7_hal_reo_shared_qaddr_cache_clear(struct ath12k_base *ab);
+void ath12k_wifi7_hal_reo_hw_setup(struct ath12k_base *ab, u32 ring_hash_map);
+void ath12k_wifi7_hal_reo_qdesc_setup(struct hal_rx_reo_queue *qdesc,
+ int tid, u32 ba_window_size,
+ u32 start_seq, enum hal_pn_type type);
#endif
diff --git a/drivers/net/wireless/ath/ath12k/rx_desc.h b/drivers/net/wireless/ath/ath12k/wifi7/hal_rx_desc.h
index 6c600473b402..0d19a9cbb68c 100644
--- a/drivers/net/wireless/ath/ath12k/rx_desc.h
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_rx_desc.h
@@ -1,18 +1,11 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH12K_RX_DESC_H
#define ATH12K_RX_DESC_H
-enum rx_desc_decap_type {
- RX_DESC_DECAP_TYPE_RAW,
- RX_DESC_DECAP_TYPE_NATIVE_WIFI,
- RX_DESC_DECAP_TYPE_ETHERNET2_DIX,
- RX_DESC_DECAP_TYPE_8023,
-};
-
enum rx_desc_decrypt_status_code {
RX_DESC_DECRYPT_STATUS_CODE_OK,
RX_DESC_DECRYPT_STATUS_CODE_UNPROTECTED_FRAME,
@@ -631,40 +624,6 @@ struct rx_mpdu_start_qcn9274_compact {
*
*/
-enum rx_msdu_start_pkt_type {
- RX_MSDU_START_PKT_TYPE_11A,
- RX_MSDU_START_PKT_TYPE_11B,
- RX_MSDU_START_PKT_TYPE_11N,
- RX_MSDU_START_PKT_TYPE_11AC,
- RX_MSDU_START_PKT_TYPE_11AX,
- RX_MSDU_START_PKT_TYPE_11BA,
- RX_MSDU_START_PKT_TYPE_11BE,
-};
-
-enum rx_msdu_start_sgi {
- RX_MSDU_START_SGI_0_8_US,
- RX_MSDU_START_SGI_0_4_US,
- RX_MSDU_START_SGI_1_6_US,
- RX_MSDU_START_SGI_3_2_US,
-};
-
-enum rx_msdu_start_recv_bw {
- RX_MSDU_START_RECV_BW_20MHZ,
- RX_MSDU_START_RECV_BW_40MHZ,
- RX_MSDU_START_RECV_BW_80MHZ,
- RX_MSDU_START_RECV_BW_160MHZ,
-};
-
-enum rx_msdu_start_reception_type {
- RX_MSDU_START_RECEPTION_TYPE_SU,
- RX_MSDU_START_RECEPTION_TYPE_DL_MU_MIMO,
- RX_MSDU_START_RECEPTION_TYPE_DL_MU_OFDMA,
- RX_MSDU_START_RECEPTION_TYPE_DL_MU_OFDMA_MIMO,
- RX_MSDU_START_RECEPTION_TYPE_UL_MU_MIMO,
- RX_MSDU_START_RECEPTION_TYPE_UL_MU_OFDMA,
- RX_MSDU_START_RECEPTION_TYPE_UL_MU_OFDMA_MIMO,
-};
-
#define RX_MSDU_END_64_TLV_SRC_LINK_ID GENMASK(24, 22)
#define RX_MSDU_END_INFO0_RXPCU_MPDU_FITLER GENMASK(1, 0)
@@ -1495,12 +1454,6 @@ struct rx_msdu_end_qcn9274_compact {
*
*/
-struct hal_rx_desc_qcn9274 {
- struct rx_msdu_end_qcn9274 msdu_end;
- struct rx_mpdu_start_qcn9274 mpdu_start;
- u8 msdu_payload[];
-} __packed;
-
struct hal_rx_desc_qcn9274_compact {
struct rx_msdu_end_qcn9274_compact msdu_end;
struct rx_mpdu_start_qcn9274_compact mpdu_start;
@@ -1528,17 +1481,28 @@ struct hal_rx_desc_wcn7850 {
u8 msdu_payload[];
};
+struct rx_pkt_hdr_tlv_qcc2072 {
+ __le32 tag;
+ __le64 phy_ppdu_id;
+ u8 rx_pkt_hdr[HAL_RX_BE_PKT_HDR_TLV_LEN];
+};
+
+struct hal_rx_desc_qcc2072 {
+ __le32 msdu_end_tag;
+ struct rx_msdu_end_qcn9274 msdu_end;
+ u8 rx_padding0[RX_BE_PADDING0_BYTES];
+ __le32 mpdu_start_tag;
+ struct rx_mpdu_start_qcn9274 mpdu_start;
+ struct rx_pkt_hdr_tlv_qcc2072 pkt_hdr_tlv;
+ u8 msdu_payload[];
+};
+
struct hal_rx_desc {
union {
- struct hal_rx_desc_qcn9274 qcn9274;
struct hal_rx_desc_qcn9274_compact qcn9274_compact;
struct hal_rx_desc_wcn7850 wcn7850;
+ struct hal_rx_desc_qcc2072 qcc2072;
} u;
} __packed;
-#define MAX_USER_POS 8
-#define MAX_MU_GROUP_ID 64
-#define MAX_MU_GROUP_SHOW 16
-#define MAX_MU_GROUP_LENGTH (6 * MAX_MU_GROUP_SHOW)
-
#endif /* ATH12K_RX_DESC_H */
diff --git a/drivers/net/wireless/ath/ath12k/hal_tx.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_tx.c
index 869e07e406fe..02d3cadf03fe 100644
--- a/drivers/net/wireless/ath/ath12k/hal_tx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_tx.c
@@ -1,13 +1,13 @@
// 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) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
-#include "hal_desc.h"
-#include "hal.h"
+#include "../hal.h"
#include "hal_tx.h"
-#include "hif.h"
+#include "../hif.h"
+#include "hal.h"
#define DSCP_TID_MAP_TBL_ENTRY_SIZE 64
@@ -29,9 +29,9 @@ static inline u8 dscp2tid(u8 dscp)
return dscp >> 3;
}
-void ath12k_hal_tx_cmd_desc_setup(struct ath12k_base *ab,
- struct hal_tcl_data_cmd *tcl_cmd,
- struct hal_tx_info *ti)
+void ath12k_wifi7_hal_tx_cmd_desc_setup(struct ath12k_base *ab,
+ struct hal_tcl_data_cmd *tcl_cmd,
+ struct hal_tx_info *ti)
{
tcl_cmd->buf_addr_info.info0 =
le32_encode_bits(ti->paddr, BUFFER_ADDR_INFO0_ADDR);
@@ -66,7 +66,7 @@ void ath12k_hal_tx_cmd_desc_setup(struct ath12k_base *ab,
tcl_cmd->info5 = 0;
}
-void ath12k_hal_tx_set_dscp_tid_map(struct ath12k_base *ab, int id)
+void ath12k_wifi7_hal_tx_set_dscp_tid_map(struct ath12k_base *ab, int id)
{
u32 ctrl_reg_val;
u32 addr;
@@ -136,10 +136,3 @@ void ath12k_hal_tx_set_dscp_tid_map(struct ath12k_base *ab, int id)
HAL_TCL1_RING_CMN_CTRL_REG,
ctrl_reg_val);
}
-
-void ath12k_hal_tx_configure_bank_register(struct ath12k_base *ab, u32 bank_config,
- u8 bank_id)
-{
- ath12k_hif_write32(ab, HAL_TCL_SW_CONFIG_BANK_ADDR + 4 * bank_id,
- bank_config);
-}
diff --git a/drivers/net/wireless/ath/ath12k/hal_tx.h b/drivers/net/wireless/ath/ath12k/wifi7/hal_tx.h
index eb065a79f6c6..9d2b1552c2f5 100644
--- a/drivers/net/wireless/ath/ath12k/hal_tx.h
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_tx.h
@@ -1,21 +1,14 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022, 2024-2025 Qualcomm Innovation Center, Inc.
- * All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH12K_HAL_TX_H
#define ATH12K_HAL_TX_H
+#include "../mac.h"
#include "hal_desc.h"
-#include "core.h"
-
-#define HAL_TX_ADDRX_EN 1
-#define HAL_TX_ADDRY_EN 2
-
-#define HAL_TX_ADDR_SEARCH_DEFAULT 0
-#define HAL_TX_ADDR_SEARCH_INDEX 1
/* TODO: check all these data can be managed with struct ath12k_tx_desc_info for perf */
struct hal_tx_info {
@@ -188,13 +181,14 @@ struct hal_tx_fes_status_end {
/* STA mode will have MCAST_PKT_CTRL instead of DSCP_TID_MAP bitfield */
#define HAL_TX_BANK_CONFIG_DSCP_TIP_MAP_ID GENMASK(22, 17)
-void ath12k_hal_tx_cmd_desc_setup(struct ath12k_base *ab,
- struct hal_tcl_data_cmd *tcl_cmd,
- struct hal_tx_info *ti);
-void ath12k_hal_tx_set_dscp_tid_map(struct ath12k_base *ab, int id);
-int ath12k_hal_reo_cmd_send(struct ath12k_base *ab, struct hal_srng *srng,
- enum hal_reo_cmd_type type,
- struct ath12k_hal_reo_cmd *cmd);
-void ath12k_hal_tx_configure_bank_register(struct ath12k_base *ab, u32 bank_config,
- u8 bank_id);
+void ath12k_wifi7_hal_tx_set_dscp_tid_map(struct ath12k_base *ab, int id);
+void ath12k_wifi7_hal_tx_cmd_desc_setup(struct ath12k_base *ab,
+ struct hal_tcl_data_cmd *tcl_cmd,
+ struct hal_tx_info *ti);
+int ath12k_wifi7_hal_reo_cmd_send(struct ath12k_base *ab, struct hal_srng *srng,
+ enum hal_reo_cmd_type type,
+ struct ath12k_hal_reo_cmd *cmd);
+void ath12k_wifi7_hal_tx_configure_bank_register(struct ath12k_base *ab,
+ u32 bank_config,
+ u8 bank_id);
#endif
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c
new file mode 100644
index 000000000000..e64e512cac7d
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c
@@ -0,0 +1,809 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include "hal_desc.h"
+#include "hal_wcn7850.h"
+#include "hw.h"
+#include "hal.h"
+#include "hal_tx.h"
+
+static const struct hal_srng_config hw_srng_config_template[] = {
+ /* TODO: max_rings can populated by querying HW capabilities */
+ [HAL_REO_DST] = {
+ .start_ring_id = HAL_SRNG_RING_ID_REO2SW1,
+ .max_rings = 8,
+ .entry_size = sizeof(struct hal_reo_dest_ring) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_DST,
+ .max_size = HAL_REO_REO2SW1_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_REO_EXCEPTION] = {
+ /* Designating REO2SW0 ring as exception ring.
+ * Any of theREO2SW rings can be used as exception ring.
+ */
+ .start_ring_id = HAL_SRNG_RING_ID_REO2SW0,
+ .max_rings = 1,
+ .entry_size = sizeof(struct hal_reo_dest_ring) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_DST,
+ .max_size = HAL_REO_REO2SW0_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_REO_REINJECT] = {
+ .start_ring_id = HAL_SRNG_RING_ID_SW2REO,
+ .max_rings = 4,
+ .entry_size = sizeof(struct hal_reo_entrance_ring) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_REO_SW2REO_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_REO_CMD] = {
+ .start_ring_id = HAL_SRNG_RING_ID_REO_CMD,
+ .max_rings = 1,
+ .entry_size = (sizeof(struct hal_tlv_64_hdr) +
+ sizeof(struct hal_reo_get_queue_stats)) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_REO_CMD_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_REO_STATUS] = {
+ .start_ring_id = HAL_SRNG_RING_ID_REO_STATUS,
+ .max_rings = 1,
+ .entry_size = (sizeof(struct hal_tlv_64_hdr) +
+ sizeof(struct hal_reo_get_queue_stats_status)) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_DST,
+ .max_size = HAL_REO_STATUS_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_TCL_DATA] = {
+ .start_ring_id = HAL_SRNG_RING_ID_SW2TCL1,
+ .max_rings = 6,
+ .entry_size = sizeof(struct hal_tcl_data_cmd) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_SW2TCL1_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_TCL_CMD] = {
+ .start_ring_id = HAL_SRNG_RING_ID_SW2TCL_CMD,
+ .max_rings = 1,
+ .entry_size = sizeof(struct hal_tcl_gse_cmd) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_SW2TCL1_CMD_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_TCL_STATUS] = {
+ .start_ring_id = HAL_SRNG_RING_ID_TCL_STATUS,
+ .max_rings = 1,
+ .entry_size = (sizeof(struct hal_tlv_hdr) +
+ sizeof(struct hal_tcl_status_ring)) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_DST,
+ .max_size = HAL_TCL_STATUS_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_CE_SRC] = {
+ .start_ring_id = HAL_SRNG_RING_ID_CE0_SRC,
+ .max_rings = 16,
+ .entry_size = sizeof(struct hal_ce_srng_src_desc) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_CE_SRC_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_CE_DST] = {
+ .start_ring_id = HAL_SRNG_RING_ID_CE0_DST,
+ .max_rings = 16,
+ .entry_size = sizeof(struct hal_ce_srng_dest_desc) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_CE_DST_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_CE_DST_STATUS] = {
+ .start_ring_id = HAL_SRNG_RING_ID_CE0_DST_STATUS,
+ .max_rings = 16,
+ .entry_size = sizeof(struct hal_ce_srng_dst_status_desc) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_DST,
+ .max_size = HAL_CE_DST_STATUS_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_WBM_IDLE_LINK] = {
+ .start_ring_id = HAL_SRNG_RING_ID_WBM_IDLE_LINK,
+ .max_rings = 1,
+ .entry_size = sizeof(struct hal_wbm_link_desc) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_WBM_IDLE_LINK_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_SW2WBM_RELEASE] = {
+ .start_ring_id = HAL_SRNG_RING_ID_WBM_SW0_RELEASE,
+ .max_rings = 2,
+ .entry_size = sizeof(struct hal_wbm_release_ring) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_SW2WBM_RELEASE_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_WBM2SW_RELEASE] = {
+ .start_ring_id = HAL_SRNG_RING_ID_WBM2SW0_RELEASE,
+ .max_rings = 8,
+ .entry_size = sizeof(struct hal_wbm_release_ring) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_UMAC,
+ .ring_dir = HAL_SRNG_DIR_DST,
+ .max_size = HAL_WBM2SW_RELEASE_RING_BASE_MSB_RING_SIZE,
+ },
+ [HAL_RXDMA_BUF] = {
+ .start_ring_id = HAL_SRNG_SW2RXDMA_BUF0,
+ .max_rings = 1,
+ .entry_size = sizeof(struct hal_wbm_buffer_ring) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_DMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_RXDMA_RING_MAX_SIZE_BE,
+ },
+ [HAL_RXDMA_DST] = {
+ .start_ring_id = HAL_SRNG_RING_ID_WMAC1_RXDMA2SW0,
+ .max_rings = 0,
+ .entry_size = 0,
+ .mac_type = ATH12K_HAL_SRNG_PMAC,
+ .ring_dir = HAL_SRNG_DIR_DST,
+ .max_size = HAL_RXDMA_RING_MAX_SIZE_BE,
+ },
+ [HAL_RXDMA_MONITOR_BUF] = {},
+ [HAL_RXDMA_MONITOR_STATUS] = {
+ .start_ring_id = HAL_SRNG_RING_ID_WMAC1_SW2RXDMA1_STATBUF,
+ .max_rings = 1,
+ .entry_size = sizeof(struct hal_wbm_buffer_ring) >> 2,
+ .mac_type = ATH12K_HAL_SRNG_PMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_RXDMA_RING_MAX_SIZE_BE,
+ },
+ [HAL_RXDMA_MONITOR_DESC] = { 0, },
+ [HAL_RXDMA_DIR_BUF] = {
+ .start_ring_id = HAL_SRNG_RING_ID_RXDMA_DIR_BUF,
+ .max_rings = 2,
+ .entry_size = 8 >> 2, /* TODO: Define the struct */
+ .mac_type = ATH12K_HAL_SRNG_PMAC,
+ .ring_dir = HAL_SRNG_DIR_SRC,
+ .max_size = HAL_RXDMA_RING_MAX_SIZE_BE,
+ },
+ [HAL_PPE2TCL] = {},
+ [HAL_PPE_RELEASE] = {},
+ [HAL_TX_MONITOR_BUF] = {},
+ [HAL_RXDMA_MONITOR_DST] = {},
+ [HAL_TX_MONITOR_DST] = {}
+};
+
+const struct ath12k_hw_regs wcn7850_regs = {
+ /* SW2TCL(x) R0 ring configuration address */
+ .tcl1_ring_id = 0x00000908,
+ .tcl1_ring_misc = 0x00000910,
+ .tcl1_ring_tp_addr_lsb = 0x0000091c,
+ .tcl1_ring_tp_addr_msb = 0x00000920,
+ .tcl1_ring_consumer_int_setup_ix0 = 0x00000930,
+ .tcl1_ring_consumer_int_setup_ix1 = 0x00000934,
+ .tcl1_ring_msi1_base_lsb = 0x00000948,
+ .tcl1_ring_msi1_base_msb = 0x0000094c,
+ .tcl1_ring_msi1_data = 0x00000950,
+ .tcl_ring_base_lsb = 0x00000b58,
+ .tcl1_ring_base_lsb = 0x00000900,
+ .tcl1_ring_base_msb = 0x00000904,
+ .tcl2_ring_base_lsb = 0x00000978,
+
+ /* TCL STATUS ring address */
+ .tcl_status_ring_base_lsb = 0x00000d38,
+
+ .wbm_idle_ring_base_lsb = 0x00000d3c,
+ .wbm_idle_ring_misc_addr = 0x00000d4c,
+ .wbm_r0_idle_list_cntl_addr = 0x00000240,
+ .wbm_r0_idle_list_size_addr = 0x00000244,
+ .wbm_scattered_ring_base_lsb = 0x00000250,
+ .wbm_scattered_ring_base_msb = 0x00000254,
+ .wbm_scattered_desc_head_info_ix0 = 0x00000260,
+ .wbm_scattered_desc_head_info_ix1 = 0x00000264,
+ .wbm_scattered_desc_tail_info_ix0 = 0x00000270,
+ .wbm_scattered_desc_tail_info_ix1 = 0x00000274,
+ .wbm_scattered_desc_ptr_hp_addr = 0x00000027c,
+
+ .wbm_sw_release_ring_base_lsb = 0x0000037c,
+ .wbm_sw1_release_ring_base_lsb = 0x00000284,
+ .wbm0_release_ring_base_lsb = 0x00000e08,
+ .wbm1_release_ring_base_lsb = 0x00000e80,
+
+ /* PCIe base address */
+ .pcie_qserdes_sysclk_en_sel = 0x01e0e0a8,
+ .pcie_pcs_osc_dtct_config_base = 0x01e0f45c,
+
+ /* PPE release ring address */
+ .ppe_rel_ring_base = 0x0000043c,
+
+ /* REO DEST ring address */
+ .reo2_ring_base = 0x0000055c,
+ .reo1_misc_ctrl_addr = 0x00000b7c,
+ .reo1_sw_cookie_cfg0 = 0x00000050,
+ .reo1_sw_cookie_cfg1 = 0x00000054,
+ .reo1_qdesc_lut_base0 = 0x00000058,
+ .reo1_qdesc_lut_base1 = 0x0000005c,
+ .reo1_ring_base_lsb = 0x000004e4,
+ .reo1_ring_base_msb = 0x000004e8,
+ .reo1_ring_id = 0x000004ec,
+ .reo1_ring_misc = 0x000004f4,
+ .reo1_ring_hp_addr_lsb = 0x000004f8,
+ .reo1_ring_hp_addr_msb = 0x000004fc,
+ .reo1_ring_producer_int_setup = 0x00000508,
+ .reo1_ring_msi1_base_lsb = 0x0000052C,
+ .reo1_ring_msi1_base_msb = 0x00000530,
+ .reo1_ring_msi1_data = 0x00000534,
+ .reo1_aging_thres_ix0 = 0x00000b08,
+ .reo1_aging_thres_ix1 = 0x00000b0c,
+ .reo1_aging_thres_ix2 = 0x00000b10,
+ .reo1_aging_thres_ix3 = 0x00000b14,
+
+ /* REO Exception ring address */
+ .reo2_sw0_ring_base = 0x000008a4,
+
+ /* REO Reinject ring address */
+ .sw2reo_ring_base = 0x00000304,
+ .sw2reo1_ring_base = 0x0000037c,
+
+ /* REO cmd ring address */
+ .reo_cmd_ring_base = 0x0000028c,
+
+ /* REO status ring address */
+ .reo_status_ring_base = 0x00000a84,
+
+ /* CE base address */
+ .umac_ce0_src_reg_base = 0x01b80000,
+ .umac_ce0_dest_reg_base = 0x01b81000,
+ .umac_ce1_src_reg_base = 0x01b82000,
+ .umac_ce1_dest_reg_base = 0x01b83000,
+
+ .gcc_gcc_pcie_hot_rst = 0x1e40304,
+
+ .qrtr_node_id = 0x1e03164,
+};
+
+static inline
+bool ath12k_hal_rx_desc_get_first_msdu_wcn7850(struct hal_rx_desc *desc)
+{
+ return !!le16_get_bits(desc->u.wcn7850.msdu_end.info5,
+ RX_MSDU_END_INFO5_FIRST_MSDU);
+}
+
+static inline
+bool ath12k_hal_rx_desc_get_last_msdu_wcn7850(struct hal_rx_desc *desc)
+{
+ return !!le16_get_bits(desc->u.wcn7850.msdu_end.info5,
+ RX_MSDU_END_INFO5_LAST_MSDU);
+}
+
+u8 ath12k_hal_rx_desc_get_l3_pad_bytes_wcn7850(struct hal_rx_desc *desc)
+{
+ return le16_get_bits(desc->u.wcn7850.msdu_end.info5,
+ RX_MSDU_END_INFO5_L3_HDR_PADDING);
+}
+
+static inline
+bool ath12k_hal_rx_desc_encrypt_valid_wcn7850(struct hal_rx_desc *desc)
+{
+ return !!le32_get_bits(desc->u.wcn7850.mpdu_start.info4,
+ RX_MPDU_START_INFO4_ENCRYPT_INFO_VALID);
+}
+
+static inline
+u32 ath12k_hal_rx_desc_get_encrypt_type_wcn7850(struct hal_rx_desc *desc)
+{
+ if (!ath12k_hal_rx_desc_encrypt_valid_wcn7850(desc))
+ return HAL_ENCRYPT_TYPE_OPEN;
+
+ return le32_get_bits(desc->u.wcn7850.mpdu_start.info2,
+ RX_MPDU_START_INFO2_ENC_TYPE);
+}
+
+static inline
+u8 ath12k_hal_rx_desc_get_decap_type_wcn7850(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.wcn7850.msdu_end.info11,
+ RX_MSDU_END_INFO11_DECAP_FORMAT);
+}
+
+static inline
+u8 ath12k_hal_rx_desc_get_mesh_ctl_wcn7850(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.wcn7850.msdu_end.info11,
+ RX_MSDU_END_INFO11_MESH_CTRL_PRESENT);
+}
+
+static inline
+bool ath12k_hal_rx_desc_get_mpdu_seq_ctl_vld_wcn7850(struct hal_rx_desc *desc)
+{
+ return !!le32_get_bits(desc->u.wcn7850.mpdu_start.info4,
+ RX_MPDU_START_INFO4_MPDU_SEQ_CTRL_VALID);
+}
+
+static inline
+bool ath12k_hal_rx_desc_get_mpdu_fc_valid_wcn7850(struct hal_rx_desc *desc)
+{
+ return !!le32_get_bits(desc->u.wcn7850.mpdu_start.info4,
+ RX_MPDU_START_INFO4_MPDU_FCTRL_VALID);
+}
+
+static inline
+u16 ath12k_hal_rx_desc_get_mpdu_start_seq_no_wcn7850(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.wcn7850.mpdu_start.info4,
+ RX_MPDU_START_INFO4_MPDU_SEQ_NUM);
+}
+
+static inline
+u16 ath12k_hal_rx_desc_get_msdu_len_wcn7850(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.wcn7850.msdu_end.info10,
+ RX_MSDU_END_INFO10_MSDU_LENGTH);
+}
+
+static inline
+u8 ath12k_hal_rx_desc_get_msdu_sgi_wcn7850(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.wcn7850.msdu_end.info12,
+ RX_MSDU_END_INFO12_SGI);
+}
+
+static inline
+u8 ath12k_hal_rx_desc_get_msdu_rate_mcs_wcn7850(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.wcn7850.msdu_end.info12,
+ RX_MSDU_END_INFO12_RATE_MCS);
+}
+
+static inline
+u8 ath12k_hal_rx_desc_get_msdu_rx_bw_wcn7850(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.wcn7850.msdu_end.info12,
+ RX_MSDU_END_INFO12_RECV_BW);
+}
+
+static inline
+u32 ath12k_hal_rx_desc_get_msdu_freq_wcn7850(struct hal_rx_desc *desc)
+{
+ return __le32_to_cpu(desc->u.wcn7850.msdu_end.phy_meta_data);
+}
+
+static inline
+u8 ath12k_hal_rx_desc_get_msdu_pkt_type_wcn7850(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.wcn7850.msdu_end.info12,
+ RX_MSDU_END_INFO12_PKT_TYPE);
+}
+
+static inline
+u8 ath12k_hal_rx_desc_get_msdu_nss_wcn7850(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.wcn7850.msdu_end.info12,
+ RX_MSDU_END_INFO12_MIMO_SS_BITMAP);
+}
+
+static inline
+u8 ath12k_hal_rx_desc_get_mpdu_tid_wcn7850(struct hal_rx_desc *desc)
+{
+ return le32_get_bits(desc->u.wcn7850.mpdu_start.info2,
+ RX_MPDU_START_INFO2_TID);
+}
+
+static inline
+u16 ath12k_hal_rx_desc_get_mpdu_peer_id_wcn7850(struct hal_rx_desc *desc)
+{
+ return __le16_to_cpu(desc->u.wcn7850.mpdu_start.sw_peer_id);
+}
+
+void ath12k_hal_rx_desc_copy_end_tlv_wcn7850(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_qcn9274));
+}
+
+u32 ath12k_hal_rx_desc_get_mpdu_start_tag_wcn7850(struct hal_rx_desc *desc)
+{
+ return le64_get_bits(desc->u.wcn7850.mpdu_start_tag,
+ HAL_TLV_HDR_TAG);
+}
+
+u32 ath12k_hal_rx_desc_get_mpdu_ppdu_id_wcn7850(struct hal_rx_desc *desc)
+{
+ return __le16_to_cpu(desc->u.wcn7850.mpdu_start.phy_ppdu_id);
+}
+
+void ath12k_hal_rx_desc_set_msdu_len_wcn7850(struct hal_rx_desc *desc, u16 len)
+{
+ u32 info = __le32_to_cpu(desc->u.wcn7850.msdu_end.info10);
+
+ info &= ~RX_MSDU_END_INFO10_MSDU_LENGTH;
+ info |= u32_encode_bits(len, RX_MSDU_END_INFO10_MSDU_LENGTH);
+
+ desc->u.wcn7850.msdu_end.info10 = __cpu_to_le32(info);
+}
+
+u8 *ath12k_hal_rx_desc_get_msdu_payload_wcn7850(struct hal_rx_desc *desc)
+{
+ return &desc->u.wcn7850.msdu_payload[0];
+}
+
+u32 ath12k_hal_rx_desc_get_mpdu_start_offset_wcn7850(void)
+{
+ return offsetof(struct hal_rx_desc_wcn7850, mpdu_start_tag);
+}
+
+u32 ath12k_hal_rx_desc_get_msdu_end_offset_wcn7850(void)
+{
+ return offsetof(struct hal_rx_desc_wcn7850, msdu_end_tag);
+}
+
+static inline
+bool ath12k_hal_rx_desc_mac_addr2_valid_wcn7850(struct hal_rx_desc *desc)
+{
+ return __le32_to_cpu(desc->u.wcn7850.mpdu_start.info4) &
+ RX_MPDU_START_INFO4_MAC_ADDR2_VALID;
+}
+
+static inline
+u8 *ath12k_hal_rx_desc_mpdu_start_addr2_wcn7850(struct hal_rx_desc *desc)
+{
+ return desc->u.wcn7850.mpdu_start.addr2;
+}
+
+static inline
+bool ath12k_hal_rx_desc_is_da_mcbc_wcn7850(struct hal_rx_desc *desc)
+{
+ return __le32_to_cpu(desc->u.wcn7850.msdu_end.info13) &
+ RX_MSDU_END_INFO13_MCAST_BCAST;
+}
+
+static inline
+bool ath12k_hal_rx_h_msdu_done_wcn7850(struct hal_rx_desc *desc)
+{
+ return !!le32_get_bits(desc->u.wcn7850.msdu_end.info14,
+ RX_MSDU_END_INFO14_MSDU_DONE);
+}
+
+static inline
+bool ath12k_hal_rx_h_l4_cksum_fail_wcn7850(struct hal_rx_desc *desc)
+{
+ return !!le32_get_bits(desc->u.wcn7850.msdu_end.info13,
+ RX_MSDU_END_INFO13_TCP_UDP_CKSUM_FAIL);
+}
+
+static inline
+bool ath12k_hal_rx_h_ip_cksum_fail_wcn7850(struct hal_rx_desc *desc)
+{
+ return !!le32_get_bits(desc->u.wcn7850.msdu_end.info13,
+ RX_MSDU_END_INFO13_IP_CKSUM_FAIL);
+}
+
+static inline
+bool ath12k_hal_rx_h_is_decrypted_wcn7850(struct hal_rx_desc *desc)
+{
+ return (le32_get_bits(desc->u.wcn7850.msdu_end.info14,
+ RX_MSDU_END_INFO14_DECRYPT_STATUS_CODE) ==
+ RX_DESC_DECRYPT_STATUS_CODE_OK);
+}
+
+u32 ath12k_hal_get_rx_desc_size_wcn7850(void)
+{
+ return sizeof(struct hal_rx_desc_wcn7850);
+}
+
+u8 ath12k_hal_rx_desc_get_msdu_src_link_wcn7850(struct hal_rx_desc *desc)
+{
+ return 0;
+}
+
+static u32 ath12k_hal_rx_h_mpdu_err_wcn7850(struct hal_rx_desc *desc)
+{
+ u32 info = __le32_to_cpu(desc->u.wcn7850.msdu_end.info13);
+ u32 errmap = 0;
+
+ if (info & RX_MSDU_END_INFO13_FCS_ERR)
+ errmap |= HAL_RX_MPDU_ERR_FCS;
+
+ if (info & RX_MSDU_END_INFO13_DECRYPT_ERR)
+ errmap |= HAL_RX_MPDU_ERR_DECRYPT;
+
+ if (info & RX_MSDU_END_INFO13_TKIP_MIC_ERR)
+ errmap |= HAL_RX_MPDU_ERR_TKIP_MIC;
+
+ if (info & RX_MSDU_END_INFO13_A_MSDU_ERROR)
+ errmap |= HAL_RX_MPDU_ERR_AMSDU_ERR;
+
+ if (info & RX_MSDU_END_INFO13_OVERFLOW_ERR)
+ errmap |= HAL_RX_MPDU_ERR_OVERFLOW;
+
+ if (info & RX_MSDU_END_INFO13_MSDU_LEN_ERR)
+ errmap |= HAL_RX_MPDU_ERR_MSDU_LEN;
+
+ if (info & RX_MSDU_END_INFO13_MPDU_LEN_ERR)
+ errmap |= HAL_RX_MPDU_ERR_MPDU_LEN;
+
+ return errmap;
+}
+
+void ath12k_hal_rx_desc_get_crypto_hdr_wcn7850(struct hal_rx_desc *desc,
+ u8 *crypto_hdr,
+ enum hal_encrypt_type enctype)
+{
+ unsigned int key_id;
+
+ switch (enctype) {
+ case HAL_ENCRYPT_TYPE_OPEN:
+ return;
+ case HAL_ENCRYPT_TYPE_TKIP_NO_MIC:
+ case HAL_ENCRYPT_TYPE_TKIP_MIC:
+ crypto_hdr[0] =
+ HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.wcn7850.mpdu_start.pn[0]);
+ crypto_hdr[1] = 0;
+ crypto_hdr[2] =
+ HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.wcn7850.mpdu_start.pn[0]);
+ break;
+ case HAL_ENCRYPT_TYPE_CCMP_128:
+ case HAL_ENCRYPT_TYPE_CCMP_256:
+ case HAL_ENCRYPT_TYPE_GCMP_128:
+ case HAL_ENCRYPT_TYPE_AES_GCMP_256:
+ crypto_hdr[0] =
+ HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.wcn7850.mpdu_start.pn[0]);
+ crypto_hdr[1] =
+ HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.wcn7850.mpdu_start.pn[0]);
+ crypto_hdr[2] = 0;
+ break;
+ case HAL_ENCRYPT_TYPE_WEP_40:
+ case HAL_ENCRYPT_TYPE_WEP_104:
+ case HAL_ENCRYPT_TYPE_WEP_128:
+ case HAL_ENCRYPT_TYPE_WAPI_GCM_SM4:
+ case HAL_ENCRYPT_TYPE_WAPI:
+ return;
+ }
+ key_id = u32_get_bits(__le32_to_cpu(desc->u.wcn7850.mpdu_start.info5),
+ RX_MPDU_START_INFO5_KEY_ID);
+ crypto_hdr[3] = 0x20 | (key_id << 6);
+ crypto_hdr[4] = HAL_RX_MPDU_INFO_PN_GET_BYTE3(desc->u.wcn7850.mpdu_start.pn[0]);
+ crypto_hdr[5] = HAL_RX_MPDU_INFO_PN_GET_BYTE4(desc->u.wcn7850.mpdu_start.pn[0]);
+ crypto_hdr[6] = HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.wcn7850.mpdu_start.pn[1]);
+ crypto_hdr[7] = HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.wcn7850.mpdu_start.pn[1]);
+}
+
+void ath12k_hal_rx_desc_get_dot11_hdr_wcn7850(struct hal_rx_desc *desc,
+ struct ieee80211_hdr *hdr)
+{
+ hdr->frame_control = desc->u.wcn7850.mpdu_start.frame_ctrl;
+ hdr->duration_id = desc->u.wcn7850.mpdu_start.duration;
+ ether_addr_copy(hdr->addr1, desc->u.wcn7850.mpdu_start.addr1);
+ ether_addr_copy(hdr->addr2, desc->u.wcn7850.mpdu_start.addr2);
+ ether_addr_copy(hdr->addr3, desc->u.wcn7850.mpdu_start.addr3);
+ if (__le32_to_cpu(desc->u.wcn7850.mpdu_start.info4) &
+ RX_MPDU_START_INFO4_MAC_ADDR4_VALID) {
+ ether_addr_copy(hdr->addr4, desc->u.wcn7850.mpdu_start.addr4);
+ }
+ hdr->seq_ctrl = desc->u.wcn7850.mpdu_start.seq_ctrl;
+}
+
+void ath12k_hal_extract_rx_desc_data_wcn7850(struct hal_rx_desc_data *rx_desc_data,
+ struct hal_rx_desc *rx_desc,
+ struct hal_rx_desc *ldesc)
+{
+ rx_desc_data->is_first_msdu = ath12k_hal_rx_desc_get_first_msdu_wcn7850(ldesc);
+ rx_desc_data->is_last_msdu = ath12k_hal_rx_desc_get_last_msdu_wcn7850(ldesc);
+ rx_desc_data->l3_pad_bytes = ath12k_hal_rx_desc_get_l3_pad_bytes_wcn7850(ldesc);
+ rx_desc_data->enctype = ath12k_hal_rx_desc_get_encrypt_type_wcn7850(rx_desc);
+ rx_desc_data->decap_type = ath12k_hal_rx_desc_get_decap_type_wcn7850(rx_desc);
+ rx_desc_data->mesh_ctrl_present =
+ ath12k_hal_rx_desc_get_mesh_ctl_wcn7850(rx_desc);
+ rx_desc_data->seq_ctl_valid =
+ ath12k_hal_rx_desc_get_mpdu_seq_ctl_vld_wcn7850(rx_desc);
+ rx_desc_data->fc_valid = ath12k_hal_rx_desc_get_mpdu_fc_valid_wcn7850(rx_desc);
+ rx_desc_data->seq_no = ath12k_hal_rx_desc_get_mpdu_start_seq_no_wcn7850(rx_desc);
+ rx_desc_data->msdu_len = ath12k_hal_rx_desc_get_msdu_len_wcn7850(ldesc);
+ rx_desc_data->sgi = ath12k_hal_rx_desc_get_msdu_sgi_wcn7850(rx_desc);
+ rx_desc_data->rate_mcs = ath12k_hal_rx_desc_get_msdu_rate_mcs_wcn7850(rx_desc);
+ rx_desc_data->bw = ath12k_hal_rx_desc_get_msdu_rx_bw_wcn7850(rx_desc);
+ rx_desc_data->phy_meta_data = ath12k_hal_rx_desc_get_msdu_freq_wcn7850(rx_desc);
+ rx_desc_data->pkt_type = ath12k_hal_rx_desc_get_msdu_pkt_type_wcn7850(rx_desc);
+ rx_desc_data->nss = hweight8(ath12k_hal_rx_desc_get_msdu_nss_wcn7850(rx_desc));
+ rx_desc_data->tid = ath12k_hal_rx_desc_get_mpdu_tid_wcn7850(rx_desc);
+ rx_desc_data->peer_id = ath12k_hal_rx_desc_get_mpdu_peer_id_wcn7850(rx_desc);
+ rx_desc_data->addr2_present = ath12k_hal_rx_desc_mac_addr2_valid_wcn7850(rx_desc);
+ rx_desc_data->addr2 = ath12k_hal_rx_desc_mpdu_start_addr2_wcn7850(rx_desc);
+ rx_desc_data->is_mcbc = ath12k_hal_rx_desc_is_da_mcbc_wcn7850(rx_desc);
+ rx_desc_data->msdu_done = ath12k_hal_rx_h_msdu_done_wcn7850(ldesc);
+ rx_desc_data->l4_csum_fail = ath12k_hal_rx_h_l4_cksum_fail_wcn7850(rx_desc);
+ rx_desc_data->ip_csum_fail = ath12k_hal_rx_h_ip_cksum_fail_wcn7850(rx_desc);
+ rx_desc_data->is_decrypted = ath12k_hal_rx_h_is_decrypted_wcn7850(rx_desc);
+ rx_desc_data->err_bitmap = ath12k_hal_rx_h_mpdu_err_wcn7850(rx_desc);
+}
+
+int ath12k_hal_srng_create_config_wcn7850(struct ath12k_hal *hal)
+{
+ struct hal_srng_config *s;
+
+ hal->srng_config = kmemdup(hw_srng_config_template,
+ sizeof(hw_srng_config_template),
+ GFP_KERNEL);
+ if (!hal->srng_config)
+ return -ENOMEM;
+
+ s = &hal->srng_config[HAL_REO_DST];
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_RING_HP;
+ s->reg_size[0] = HAL_REO2_RING_BASE_LSB(hal) - HAL_REO1_RING_BASE_LSB(hal);
+ s->reg_size[1] = HAL_REO2_RING_HP - HAL_REO1_RING_HP;
+
+ s = &hal->srng_config[HAL_REO_EXCEPTION];
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_SW0_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_SW0_RING_HP;
+
+ s = &hal->srng_config[HAL_REO_REINJECT];
+ s->max_rings = 1;
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_HP;
+
+ s = &hal->srng_config[HAL_REO_CMD];
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_HP;
+
+ s = &hal->srng_config[HAL_REO_STATUS];
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_HP;
+
+ s = &hal->srng_config[HAL_TCL_DATA];
+ s->max_rings = 5;
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_HP;
+ s->reg_size[0] = HAL_TCL2_RING_BASE_LSB(hal) - HAL_TCL1_RING_BASE_LSB(hal);
+ s->reg_size[1] = HAL_TCL2_RING_HP - HAL_TCL1_RING_HP;
+
+ s = &hal->srng_config[HAL_TCL_CMD];
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_RING_HP;
+
+ s = &hal->srng_config[HAL_TCL_STATUS];
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_STATUS_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_STATUS_RING_HP;
+
+ s = &hal->srng_config[HAL_CE_SRC];
+ s->max_rings = 12;
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(hal) + HAL_CE_DST_RING_BASE_LSB;
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(hal) + HAL_CE_DST_RING_HP;
+ s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(hal) -
+ HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(hal);
+ s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(hal) -
+ HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(hal);
+
+ s = &hal->srng_config[HAL_CE_DST];
+ s->max_rings = 12;
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(hal) + HAL_CE_DST_RING_BASE_LSB;
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(hal) + HAL_CE_DST_RING_HP;
+ s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(hal) -
+ HAL_SEQ_WCSS_UMAC_CE0_DST_REG(hal);
+ s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(hal) -
+ HAL_SEQ_WCSS_UMAC_CE0_DST_REG(hal);
+
+ s = &hal->srng_config[HAL_CE_DST_STATUS];
+ s->max_rings = 12;
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(hal) +
+ HAL_CE_DST_STATUS_RING_BASE_LSB;
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(hal) + HAL_CE_DST_STATUS_RING_HP;
+ s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(hal) -
+ HAL_SEQ_WCSS_UMAC_CE0_DST_REG(hal);
+ s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(hal) -
+ HAL_SEQ_WCSS_UMAC_CE0_DST_REG(hal);
+
+ s = &hal->srng_config[HAL_WBM_IDLE_LINK];
+ s->reg_start[0] =
+ HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_IDLE_LINK_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_IDLE_LINK_RING_HP;
+
+ s = &hal->srng_config[HAL_SW2WBM_RELEASE];
+ s->max_rings = 1;
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG +
+ HAL_WBM_SW_RELEASE_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_SW_RELEASE_RING_HP;
+
+ s = &hal->srng_config[HAL_WBM2SW_RELEASE];
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM0_RELEASE_RING_BASE_LSB(hal);
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM0_RELEASE_RING_HP;
+ s->reg_size[0] = HAL_WBM1_RELEASE_RING_BASE_LSB(hal) -
+ HAL_WBM0_RELEASE_RING_BASE_LSB(hal);
+ s->reg_size[1] = HAL_WBM1_RELEASE_RING_HP - HAL_WBM0_RELEASE_RING_HP;
+
+ s = &hal->srng_config[HAL_RXDMA_BUF];
+ s->max_rings = 2;
+ s->mac_type = ATH12K_HAL_SRNG_PMAC;
+
+ s = &hal->srng_config[HAL_RXDMA_DST];
+ s->max_rings = 1;
+ s->entry_size = sizeof(struct hal_reo_entrance_ring) >> 2;
+
+ /* below rings are not used */
+ s = &hal->srng_config[HAL_RXDMA_DIR_BUF];
+ s->max_rings = 0;
+
+ s = &hal->srng_config[HAL_PPE2TCL];
+ s->max_rings = 0;
+
+ s = &hal->srng_config[HAL_PPE_RELEASE];
+ s->max_rings = 0;
+
+ s = &hal->srng_config[HAL_TX_MONITOR_BUF];
+ s->max_rings = 0;
+
+ s = &hal->srng_config[HAL_TX_MONITOR_DST];
+ s->max_rings = 0;
+
+ s = &hal->srng_config[HAL_PPE2TCL];
+ s->max_rings = 0;
+
+ return 0;
+}
+
+const struct ath12k_hal_tcl_to_wbm_rbm_map
+ath12k_hal_tcl_to_wbm_rbm_map_wcn7850[DP_TCL_NUM_RING_MAX] = {
+ {
+ .wbm_ring_num = 0,
+ .rbm_id = HAL_RX_BUF_RBM_SW0_BM,
+ },
+ {
+ .wbm_ring_num = 2,
+ .rbm_id = HAL_RX_BUF_RBM_SW2_BM,
+ },
+ {
+ .wbm_ring_num = 4,
+ .rbm_id = HAL_RX_BUF_RBM_SW4_BM,
+ },
+};
+
+const struct ath12k_hw_hal_params ath12k_hw_hal_params_wcn7850 = {
+ .rx_buf_rbm = HAL_RX_BUF_RBM_SW1_BM,
+ .wbm2sw_cc_enable = HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW0_EN |
+ HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW2_EN |
+ HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW3_EN |
+ HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW4_EN,
+};
+
+const struct hal_ops hal_wcn7850_ops = {
+ .create_srng_config = ath12k_hal_srng_create_config_wcn7850,
+ .rx_desc_set_msdu_len = ath12k_hal_rx_desc_set_msdu_len_wcn7850,
+ .rx_desc_get_dot11_hdr = ath12k_hal_rx_desc_get_dot11_hdr_wcn7850,
+ .rx_desc_get_crypto_header = ath12k_hal_rx_desc_get_crypto_hdr_wcn7850,
+ .rx_desc_copy_end_tlv = ath12k_hal_rx_desc_copy_end_tlv_wcn7850,
+ .rx_desc_get_msdu_src_link_id = ath12k_hal_rx_desc_get_msdu_src_link_wcn7850,
+ .extract_rx_desc_data = ath12k_hal_extract_rx_desc_data_wcn7850,
+ .rx_desc_get_l3_pad_bytes = ath12k_hal_rx_desc_get_l3_pad_bytes_wcn7850,
+ .rx_desc_get_mpdu_start_tag = ath12k_hal_rx_desc_get_mpdu_start_tag_wcn7850,
+ .rx_desc_get_mpdu_ppdu_id = ath12k_hal_rx_desc_get_mpdu_ppdu_id_wcn7850,
+ .rx_desc_get_msdu_payload = ath12k_hal_rx_desc_get_msdu_payload_wcn7850,
+ .ce_dst_setup = ath12k_wifi7_hal_ce_dst_setup,
+ .srng_src_hw_init = ath12k_wifi7_hal_srng_src_hw_init,
+ .srng_dst_hw_init = ath12k_wifi7_hal_srng_dst_hw_init,
+ .set_umac_srng_ptr_addr = ath12k_wifi7_hal_set_umac_srng_ptr_addr,
+ .srng_update_shadow_config = ath12k_wifi7_hal_srng_update_shadow_config,
+ .srng_get_ring_id = ath12k_wifi7_hal_srng_get_ring_id,
+ .ce_get_desc_size = ath12k_wifi7_hal_ce_get_desc_size,
+ .ce_src_set_desc = ath12k_wifi7_hal_ce_src_set_desc,
+ .ce_dst_set_desc = ath12k_wifi7_hal_ce_dst_set_desc,
+ .ce_dst_status_get_length = ath12k_wifi7_hal_ce_dst_status_get_length,
+ .set_link_desc_addr = ath12k_wifi7_hal_set_link_desc_addr,
+ .tx_set_dscp_tid_map = ath12k_wifi7_hal_tx_set_dscp_tid_map,
+ .tx_configure_bank_register =
+ ath12k_wifi7_hal_tx_configure_bank_register,
+ .reoq_lut_addr_read_enable = ath12k_wifi7_hal_reoq_lut_addr_read_enable,
+ .reoq_lut_set_max_peerid = ath12k_wifi7_hal_reoq_lut_set_max_peerid,
+ .write_reoq_lut_addr = ath12k_wifi7_hal_write_reoq_lut_addr,
+ .write_ml_reoq_lut_addr = ath12k_wifi7_hal_write_ml_reoq_lut_addr,
+ .setup_link_idle_list = ath12k_wifi7_hal_setup_link_idle_list,
+ .reo_init_cmd_ring = ath12k_wifi7_hal_reo_init_cmd_ring_tlv64,
+ .reo_shared_qaddr_cache_clear = ath12k_wifi7_hal_reo_shared_qaddr_cache_clear,
+ .reo_hw_setup = ath12k_wifi7_hal_reo_hw_setup,
+ .rx_buf_addr_info_set = ath12k_wifi7_hal_rx_buf_addr_info_set,
+ .rx_buf_addr_info_get = ath12k_wifi7_hal_rx_buf_addr_info_get,
+ .cc_config = ath12k_wifi7_hal_cc_config,
+ .get_idle_link_rbm = ath12k_wifi7_hal_get_idle_link_rbm,
+ .rx_msdu_list_get = ath12k_wifi7_hal_rx_msdu_list_get,
+ .rx_reo_ent_buf_paddr_get = ath12k_wifi7_hal_rx_reo_ent_buf_paddr_get,
+ .reo_cmd_enc_tlv_hdr = ath12k_hal_encode_tlv64_hdr,
+ .reo_status_dec_tlv_hdr = ath12k_hal_decode_tlv64_hdr,
+};
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.h b/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.h
new file mode 100644
index 000000000000..a56ca9fd3de4
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef ATH12K_HAL_WCN7850_H
+#define ATH12K_HAL_WCN7850_H
+
+#include "../hal.h"
+#include "hal_rx.h"
+#include "hal.h"
+
+extern const struct hal_ops hal_wcn7850_ops;
+extern const struct ath12k_hw_regs wcn7850_regs;
+extern const struct ath12k_hal_tcl_to_wbm_rbm_map
+ath12k_hal_tcl_to_wbm_rbm_map_wcn7850[DP_TCL_NUM_RING_MAX];
+extern const struct ath12k_hw_hal_params ath12k_hw_hal_params_wcn7850;
+
+u8 ath12k_hal_rx_desc_get_l3_pad_bytes_wcn7850(struct hal_rx_desc *desc);
+void ath12k_hal_rx_desc_copy_end_tlv_wcn7850(struct hal_rx_desc *fdesc,
+ struct hal_rx_desc *ldesc);
+u32 ath12k_hal_rx_desc_get_mpdu_start_tag_wcn7850(struct hal_rx_desc *desc);
+u32 ath12k_hal_rx_desc_get_mpdu_ppdu_id_wcn7850(struct hal_rx_desc *desc);
+void ath12k_hal_rx_desc_set_msdu_len_wcn7850(struct hal_rx_desc *desc, u16 len);
+u8 *ath12k_hal_rx_desc_get_msdu_payload_wcn7850(struct hal_rx_desc *desc);
+u32 ath12k_hal_rx_desc_get_mpdu_start_offset_wcn7850(void);
+u32 ath12k_hal_rx_desc_get_msdu_end_offset_wcn7850(void);
+u32 ath12k_hal_get_rx_desc_size_wcn7850(void);
+u8 ath12k_hal_rx_desc_get_msdu_src_link_wcn7850(struct hal_rx_desc *desc);
+void ath12k_hal_rx_desc_get_crypto_hdr_wcn7850(struct hal_rx_desc *desc,
+ u8 *crypto_hdr,
+ enum hal_encrypt_type enctype);
+void ath12k_hal_rx_desc_get_dot11_hdr_wcn7850(struct hal_rx_desc *desc,
+ struct ieee80211_hdr *hdr);
+void ath12k_hal_extract_rx_desc_data_wcn7850(struct hal_rx_desc_data *rx_desc_data,
+ struct hal_rx_desc *rx_desc,
+ struct hal_rx_desc *ldesc);
+int ath12k_hal_srng_create_config_wcn7850(struct ath12k_hal *hal);
+#endif
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hw.c b/drivers/net/wireless/ath/ath12k/wifi7/hw.c
new file mode 100644
index 000000000000..df045ddf42da
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hw.c
@@ -0,0 +1,1049 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/bitfield.h>
+
+#include "../debug.h"
+#include "../core.h"
+#include "../ce.h"
+#include "ce.h"
+#include "../hw.h"
+#include "hw.h"
+#include "../mhi.h"
+#include "mhi.h"
+#include "dp_rx.h"
+#include "../peer.h"
+#include "wmi.h"
+#include "../wow.h"
+#include "../debugfs.h"
+#include "../debugfs_sta.h"
+#include "../testmode.h"
+#include "hal.h"
+#include "dp_tx.h"
+
+static const guid_t wcn7850_uuid = GUID_INIT(0xf634f534, 0x6147, 0x11ec,
+ 0x90, 0xd6, 0x02, 0x42,
+ 0xac, 0x12, 0x00, 0x03);
+
+static u8 ath12k_wifi7_hw_qcn9274_mac_from_pdev_id(int pdev_idx)
+{
+ return pdev_idx;
+}
+
+static int
+ath12k_wifi7_hw_mac_id_to_pdev_id_qcn9274(const struct ath12k_hw_params *hw,
+ int mac_id)
+{
+ return mac_id;
+}
+
+static int
+ath12k_wifi7_hw_mac_id_to_srng_id_qcn9274(const struct ath12k_hw_params *hw,
+ int mac_id)
+{
+ return 0;
+}
+
+static u8 ath12k_wifi7_hw_get_ring_selector_qcn9274(struct sk_buff *skb)
+{
+ return smp_processor_id();
+}
+
+static bool ath12k_wifi7_dp_srng_is_comp_ring_qcn9274(int ring_num)
+{
+ if (ring_num < 3 || ring_num == 4)
+ return true;
+
+ return false;
+}
+
+static bool
+ath12k_wifi7_is_frame_link_agnostic_qcn9274(struct ath12k_link_vif *arvif,
+ struct ieee80211_mgmt *mgmt)
+{
+ return ieee80211_is_action(mgmt->frame_control);
+}
+
+static int
+ath12k_wifi7_hw_mac_id_to_pdev_id_wcn7850(const struct ath12k_hw_params *hw,
+ int mac_id)
+{
+ return 0;
+}
+
+static int
+ath12k_wifi7_hw_mac_id_to_srng_id_wcn7850(const struct ath12k_hw_params *hw,
+ int mac_id)
+{
+ return mac_id;
+}
+
+static u8 ath12k_wifi7_hw_get_ring_selector_wcn7850(struct sk_buff *skb)
+{
+ return skb_get_queue_mapping(skb);
+}
+
+static bool ath12k_wifi7_dp_srng_is_comp_ring_wcn7850(int ring_num)
+{
+ if (ring_num == 0 || ring_num == 2 || ring_num == 4)
+ return true;
+
+ return false;
+}
+
+static bool ath12k_is_addba_resp_action_code(struct ieee80211_mgmt *mgmt)
+{
+ if (!ieee80211_is_action(mgmt->frame_control))
+ return false;
+
+ if (mgmt->u.action.category != WLAN_CATEGORY_BACK)
+ return false;
+
+ if (mgmt->u.action.u.addba_resp.action_code != WLAN_ACTION_ADDBA_RESP)
+ return false;
+
+ return true;
+}
+
+static bool
+ath12k_wifi7_is_frame_link_agnostic_wcn7850(struct ath12k_link_vif *arvif,
+ struct ieee80211_mgmt *mgmt)
+{
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ath12k_hw *ah = ath12k_ar_to_ah(arvif->ar);
+ struct ath12k_base *ab = arvif->ar->ab;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_dp_peer *peer;
+ __le16 fc = mgmt->frame_control;
+
+ spin_lock_bh(&dp->dp_lock);
+ if (!ath12k_dp_link_peer_find_by_addr(dp, mgmt->da)) {
+ spin_lock_bh(&ah->dp_hw.peer_lock);
+ peer = ath12k_dp_peer_find_by_addr(&ah->dp_hw, mgmt->da);
+ if (!peer || (peer && !peer->is_mlo)) {
+ spin_unlock_bh(&ah->dp_hw.peer_lock);
+ spin_unlock_bh(&dp->dp_lock);
+ return false;
+ }
+ spin_unlock_bh(&ah->dp_hw.peer_lock);
+ }
+ spin_unlock_bh(&dp->dp_lock);
+
+ if (vif->type == NL80211_IFTYPE_STATION)
+ return arvif->is_up &&
+ (vif->valid_links == vif->active_links) &&
+ !ieee80211_is_probe_req(fc) &&
+ !ieee80211_is_auth(fc) &&
+ !ieee80211_is_deauth(fc) &&
+ !ath12k_is_addba_resp_action_code(mgmt);
+
+ if (vif->type == NL80211_IFTYPE_AP)
+ return !(ieee80211_is_probe_resp(fc) || ieee80211_is_auth(fc) ||
+ ieee80211_is_assoc_resp(fc) || ieee80211_is_reassoc_resp(fc) ||
+ ath12k_is_addba_resp_action_code(mgmt));
+
+ return false;
+}
+
+static const struct ath12k_hw_ops qcn9274_ops = {
+ .get_hw_mac_from_pdev_id = ath12k_wifi7_hw_qcn9274_mac_from_pdev_id,
+ .mac_id_to_pdev_id = ath12k_wifi7_hw_mac_id_to_pdev_id_qcn9274,
+ .mac_id_to_srng_id = ath12k_wifi7_hw_mac_id_to_srng_id_qcn9274,
+ .rxdma_ring_sel_config = ath12k_dp_rxdma_ring_sel_config_qcn9274,
+ .get_ring_selector = ath12k_wifi7_hw_get_ring_selector_qcn9274,
+ .dp_srng_is_tx_comp_ring = ath12k_wifi7_dp_srng_is_comp_ring_qcn9274,
+ .is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_qcn9274,
+};
+
+static const struct ath12k_hw_ops wcn7850_ops = {
+ .get_hw_mac_from_pdev_id = ath12k_wifi7_hw_qcn9274_mac_from_pdev_id,
+ .mac_id_to_pdev_id = ath12k_wifi7_hw_mac_id_to_pdev_id_wcn7850,
+ .mac_id_to_srng_id = ath12k_wifi7_hw_mac_id_to_srng_id_wcn7850,
+ .rxdma_ring_sel_config = ath12k_dp_rxdma_ring_sel_config_wcn7850,
+ .get_ring_selector = ath12k_wifi7_hw_get_ring_selector_wcn7850,
+ .dp_srng_is_tx_comp_ring = ath12k_wifi7_dp_srng_is_comp_ring_wcn7850,
+ .is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_wcn7850,
+};
+
+static const struct ath12k_hw_ops qcc2072_ops = {
+ .get_hw_mac_from_pdev_id = ath12k_wifi7_hw_qcn9274_mac_from_pdev_id,
+ .mac_id_to_pdev_id = ath12k_wifi7_hw_mac_id_to_pdev_id_wcn7850,
+ .mac_id_to_srng_id = ath12k_wifi7_hw_mac_id_to_srng_id_wcn7850,
+ .rxdma_ring_sel_config = ath12k_dp_rxdma_ring_sel_config_qcc2072,
+ .get_ring_selector = ath12k_wifi7_hw_get_ring_selector_wcn7850,
+ .dp_srng_is_tx_comp_ring = ath12k_wifi7_dp_srng_is_comp_ring_wcn7850,
+ .is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_wcn7850,
+};
+
+#define ATH12K_TX_RING_MASK_0 0x1
+#define ATH12K_TX_RING_MASK_1 0x2
+#define ATH12K_TX_RING_MASK_2 0x4
+#define ATH12K_TX_RING_MASK_3 0x8
+#define ATH12K_TX_RING_MASK_4 0x10
+
+#define ATH12K_RX_RING_MASK_0 0x1
+#define ATH12K_RX_RING_MASK_1 0x2
+#define ATH12K_RX_RING_MASK_2 0x4
+#define ATH12K_RX_RING_MASK_3 0x8
+
+#define ATH12K_RX_ERR_RING_MASK_0 0x1
+
+#define ATH12K_RX_WBM_REL_RING_MASK_0 0x1
+
+#define ATH12K_REO_STATUS_RING_MASK_0 0x1
+
+#define ATH12K_HOST2RXDMA_RING_MASK_0 0x1
+
+#define ATH12K_RX_MON_RING_MASK_0 0x1
+#define ATH12K_RX_MON_RING_MASK_1 0x2
+#define ATH12K_RX_MON_RING_MASK_2 0x4
+
+#define ATH12K_TX_MON_RING_MASK_0 0x1
+#define ATH12K_TX_MON_RING_MASK_1 0x2
+
+#define ATH12K_RX_MON_STATUS_RING_MASK_0 0x1
+#define ATH12K_RX_MON_STATUS_RING_MASK_1 0x2
+#define ATH12K_RX_MON_STATUS_RING_MASK_2 0x4
+
+static const struct ath12k_hw_ring_mask ath12k_wifi7_hw_ring_mask_qcn9274 = {
+ .tx = {
+ ATH12K_TX_RING_MASK_0,
+ ATH12K_TX_RING_MASK_1,
+ ATH12K_TX_RING_MASK_2,
+ ATH12K_TX_RING_MASK_3,
+ },
+ .rx_mon_dest = {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ ATH12K_RX_MON_RING_MASK_0,
+ ATH12K_RX_MON_RING_MASK_1,
+ ATH12K_RX_MON_RING_MASK_2,
+ },
+ .rx = {
+ 0, 0, 0, 0,
+ ATH12K_RX_RING_MASK_0,
+ ATH12K_RX_RING_MASK_1,
+ ATH12K_RX_RING_MASK_2,
+ ATH12K_RX_RING_MASK_3,
+ },
+ .rx_err = {
+ 0, 0, 0,
+ ATH12K_RX_ERR_RING_MASK_0,
+ },
+ .rx_wbm_rel = {
+ 0, 0, 0,
+ ATH12K_RX_WBM_REL_RING_MASK_0,
+ },
+ .reo_status = {
+ 0, 0, 0,
+ ATH12K_REO_STATUS_RING_MASK_0,
+ },
+ .host2rxdma = {
+ 0, 0, 0,
+ ATH12K_HOST2RXDMA_RING_MASK_0,
+ },
+ .tx_mon_dest = {
+ 0, 0, 0,
+ },
+};
+
+static const struct ath12k_hw_ring_mask ath12k_wifi7_hw_ring_mask_ipq5332 = {
+ .tx = {
+ ATH12K_TX_RING_MASK_0,
+ ATH12K_TX_RING_MASK_1,
+ ATH12K_TX_RING_MASK_2,
+ ATH12K_TX_RING_MASK_3,
+ },
+ .rx_mon_dest = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ ATH12K_RX_MON_RING_MASK_0,
+ },
+ .rx = {
+ 0, 0, 0, 0,
+ ATH12K_RX_RING_MASK_0,
+ ATH12K_RX_RING_MASK_1,
+ ATH12K_RX_RING_MASK_2,
+ ATH12K_RX_RING_MASK_3,
+ },
+ .rx_err = {
+ 0, 0, 0,
+ ATH12K_RX_ERR_RING_MASK_0,
+ },
+ .rx_wbm_rel = {
+ 0, 0, 0,
+ ATH12K_RX_WBM_REL_RING_MASK_0,
+ },
+ .reo_status = {
+ 0, 0, 0,
+ ATH12K_REO_STATUS_RING_MASK_0,
+ },
+ .host2rxdma = {
+ 0, 0, 0,
+ ATH12K_HOST2RXDMA_RING_MASK_0,
+ },
+ .tx_mon_dest = {
+ ATH12K_TX_MON_RING_MASK_0,
+ ATH12K_TX_MON_RING_MASK_1,
+ },
+};
+
+static const struct ath12k_hw_ring_mask ath12k_wifi7_hw_ring_mask_wcn7850 = {
+ .tx = {
+ ATH12K_TX_RING_MASK_0,
+ ATH12K_TX_RING_MASK_1,
+ ATH12K_TX_RING_MASK_2,
+ },
+ .rx_mon_dest = {
+ },
+ .rx_mon_status = {
+ 0, 0, 0, 0,
+ ATH12K_RX_MON_STATUS_RING_MASK_0,
+ ATH12K_RX_MON_STATUS_RING_MASK_1,
+ ATH12K_RX_MON_STATUS_RING_MASK_2,
+ },
+ .rx = {
+ 0, 0, 0,
+ ATH12K_RX_RING_MASK_0,
+ ATH12K_RX_RING_MASK_1,
+ ATH12K_RX_RING_MASK_2,
+ ATH12K_RX_RING_MASK_3,
+ },
+ .rx_err = {
+ ATH12K_RX_ERR_RING_MASK_0,
+ },
+ .rx_wbm_rel = {
+ ATH12K_RX_WBM_REL_RING_MASK_0,
+ },
+ .reo_status = {
+ ATH12K_REO_STATUS_RING_MASK_0,
+ },
+ .host2rxdma = {
+ },
+ .tx_mon_dest = {
+ },
+};
+
+static const struct ce_ie_addr ath12k_wifi7_ce_ie_addr_ipq5332 = {
+ .ie1_reg_addr = CE_HOST_IE_ADDRESS - HAL_IPQ5332_CE_WFSS_REG_BASE,
+ .ie2_reg_addr = CE_HOST_IE_2_ADDRESS - HAL_IPQ5332_CE_WFSS_REG_BASE,
+ .ie3_reg_addr = CE_HOST_IE_3_ADDRESS - HAL_IPQ5332_CE_WFSS_REG_BASE,
+};
+
+static const struct ce_remap ath12k_wifi7_ce_remap_ipq5332 = {
+ .base = HAL_IPQ5332_CE_WFSS_REG_BASE,
+ .size = HAL_IPQ5332_CE_SIZE,
+ .cmem_offset = HAL_SEQ_WCSS_CMEM_OFFSET,
+};
+
+static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
+ {
+ .name = "qcn9274 hw1.0",
+ .hw_rev = ATH12K_HW_QCN9274_HW10,
+ .fw = {
+ .dir = "QCN9274/hw1.0",
+ .board_size = 256 * 1024,
+ .cal_offset = 128 * 1024,
+ .m3_loader = ath12k_m3_fw_loader_driver,
+ .download_aux_ucode = false,
+ },
+ .max_radios = 1,
+ .single_pdev_only = false,
+ .qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_QCN9274,
+ .internal_sleep_clock = false,
+
+ .hw_ops = &qcn9274_ops,
+ .ring_mask = &ath12k_wifi7_hw_ring_mask_qcn9274,
+
+ .host_ce_config = ath12k_wifi7_host_ce_config_qcn9274,
+ .ce_count = 16,
+ .target_ce_config = ath12k_wifi7_target_ce_config_wlan_qcn9274,
+ .target_ce_count = 12,
+ .svc_to_ce_map =
+ ath12k_wifi7_target_service_to_ce_map_wlan_qcn9274,
+ .svc_to_ce_map_len = 18,
+
+ .rxdma1_enable = false,
+ .num_rxdma_per_pdev = 1,
+ .num_rxdma_dst_ring = 0,
+ .rx_mac_buf_ring = false,
+ .vdev_start_delay = false,
+
+ .interface_modes = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_MESH_POINT) |
+ BIT(NL80211_IFTYPE_AP_VLAN),
+ .supports_monitor = false,
+
+ .idle_ps = false,
+ .download_calib = true,
+ .supports_suspend = false,
+ .tcl_ring_retry = true,
+ .reoq_lut_support = true,
+ .supports_shadow_regs = false,
+
+ .num_tcl_banks = 48,
+ .max_tx_ring = 4,
+
+ .mhi_config = &ath12k_wifi7_mhi_config_qcn9274,
+
+ .wmi_init = ath12k_wifi7_wmi_init_qcn9274,
+
+ .qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01),
+
+ .rfkill_pin = 0,
+ .rfkill_cfg = 0,
+ .rfkill_on_level = 0,
+
+ .rddm_size = 0x600000,
+
+ .def_num_link = 0,
+ .max_mlo_peer = 256,
+
+ .otp_board_id_register = QCN9274_QFPROM_RAW_RFA_PDET_ROW13_LSB,
+
+ .supports_sta_ps = false,
+
+ .acpi_guid = NULL,
+ .supports_dynamic_smps_6ghz = true,
+
+ .iova_mask = 0,
+
+ .supports_aspm = false,
+
+ .ce_ie_addr = NULL,
+ .ce_remap = NULL,
+ .bdf_addr_offset = 0,
+
+ .current_cc_support = false,
+
+ .dp_primary_link_only = true,
+ },
+ {
+ .name = "wcn7850 hw2.0",
+ .hw_rev = ATH12K_HW_WCN7850_HW20,
+
+ .fw = {
+ .dir = "WCN7850/hw2.0",
+ .board_size = 256 * 1024,
+ .cal_offset = 256 * 1024,
+ .m3_loader = ath12k_m3_fw_loader_driver,
+ .download_aux_ucode = false,
+ },
+
+ .max_radios = 1,
+ .single_pdev_only = true,
+ .qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_WCN7850,
+ .internal_sleep_clock = true,
+
+ .hw_ops = &wcn7850_ops,
+ .ring_mask = &ath12k_wifi7_hw_ring_mask_wcn7850,
+
+ .host_ce_config = ath12k_wifi7_host_ce_config_wcn7850,
+ .ce_count = 9,
+ .target_ce_config = ath12k_wifi7_target_ce_config_wlan_wcn7850,
+ .target_ce_count = 9,
+ .svc_to_ce_map =
+ ath12k_wifi7_target_service_to_ce_map_wlan_wcn7850,
+ .svc_to_ce_map_len = 14,
+
+ .rxdma1_enable = false,
+ .num_rxdma_per_pdev = 2,
+ .num_rxdma_dst_ring = 1,
+ .rx_mac_buf_ring = true,
+ .vdev_start_delay = true,
+
+ .interface_modes = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_P2P_DEVICE) |
+ BIT(NL80211_IFTYPE_P2P_CLIENT) |
+ BIT(NL80211_IFTYPE_P2P_GO),
+ .supports_monitor = true,
+
+ .idle_ps = true,
+ .download_calib = false,
+ .supports_suspend = true,
+ .tcl_ring_retry = false,
+ .reoq_lut_support = false,
+ .supports_shadow_regs = true,
+
+ .num_tcl_banks = 7,
+ .max_tx_ring = 3,
+
+ .mhi_config = &ath12k_wifi7_mhi_config_wcn7850,
+
+ .wmi_init = ath12k_wifi7_wmi_init_wcn7850,
+
+ .qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01) |
+ BIT(CNSS_PCIE_PERST_NO_PULL_V01),
+
+ .rfkill_pin = 48,
+ .rfkill_cfg = 0,
+ .rfkill_on_level = 1,
+
+ .rddm_size = 0x780000,
+
+ .def_num_link = 2,
+ .max_mlo_peer = 32,
+
+ .otp_board_id_register = 0,
+
+ .supports_sta_ps = true,
+
+ .acpi_guid = &wcn7850_uuid,
+ .supports_dynamic_smps_6ghz = false,
+
+ .iova_mask = ATH12K_PCIE_MAX_PAYLOAD_SIZE - 1,
+
+ .supports_aspm = true,
+
+ .ce_ie_addr = NULL,
+ .ce_remap = NULL,
+ .bdf_addr_offset = 0,
+
+ .current_cc_support = true,
+
+ .dp_primary_link_only = false,
+ },
+ {
+ .name = "qcn9274 hw2.0",
+ .hw_rev = ATH12K_HW_QCN9274_HW20,
+ .fw = {
+ .dir = "QCN9274/hw2.0",
+ .board_size = 256 * 1024,
+ .cal_offset = 128 * 1024,
+ .m3_loader = ath12k_m3_fw_loader_driver,
+ .download_aux_ucode = false,
+ },
+ .max_radios = 2,
+ .single_pdev_only = false,
+ .qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_QCN9274,
+ .internal_sleep_clock = false,
+
+ .hw_ops = &qcn9274_ops,
+ .ring_mask = &ath12k_wifi7_hw_ring_mask_qcn9274,
+
+ .host_ce_config = ath12k_wifi7_host_ce_config_qcn9274,
+ .ce_count = 16,
+ .target_ce_config = ath12k_wifi7_target_ce_config_wlan_qcn9274,
+ .target_ce_count = 12,
+ .svc_to_ce_map =
+ ath12k_wifi7_target_service_to_ce_map_wlan_qcn9274,
+ .svc_to_ce_map_len = 18,
+
+ .rxdma1_enable = true,
+ .num_rxdma_per_pdev = 1,
+ .num_rxdma_dst_ring = 0,
+ .rx_mac_buf_ring = false,
+ .vdev_start_delay = false,
+
+ .interface_modes = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_MESH_POINT) |
+ BIT(NL80211_IFTYPE_AP_VLAN),
+ .supports_monitor = true,
+
+ .idle_ps = false,
+ .download_calib = true,
+ .supports_suspend = false,
+ .tcl_ring_retry = true,
+ .reoq_lut_support = true,
+ .supports_shadow_regs = false,
+
+ .num_tcl_banks = 48,
+ .max_tx_ring = 4,
+
+ .mhi_config = &ath12k_wifi7_mhi_config_qcn9274,
+
+ .wmi_init = ath12k_wifi7_wmi_init_qcn9274,
+
+ .qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01),
+
+ .rfkill_pin = 0,
+ .rfkill_cfg = 0,
+ .rfkill_on_level = 0,
+
+ .rddm_size = 0x600000,
+
+ .def_num_link = 0,
+ .max_mlo_peer = 256,
+
+ .otp_board_id_register = QCN9274_QFPROM_RAW_RFA_PDET_ROW13_LSB,
+
+ .supports_sta_ps = false,
+
+ .acpi_guid = NULL,
+ .supports_dynamic_smps_6ghz = true,
+
+ .iova_mask = 0,
+
+ .supports_aspm = false,
+
+ .ce_ie_addr = NULL,
+ .ce_remap = NULL,
+ .bdf_addr_offset = 0,
+
+ .current_cc_support = false,
+
+ .dp_primary_link_only = true,
+ },
+ {
+ .name = "ipq5332 hw1.0",
+ .hw_rev = ATH12K_HW_IPQ5332_HW10,
+ .fw = {
+ .dir = "IPQ5332/hw1.0",
+ .board_size = 256 * 1024,
+ .cal_offset = 128 * 1024,
+ .m3_loader = ath12k_m3_fw_loader_remoteproc,
+ .download_aux_ucode = false,
+ },
+ .max_radios = 1,
+ .single_pdev_only = false,
+ .qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ5332,
+ .internal_sleep_clock = false,
+
+ .hw_ops = &qcn9274_ops,
+ .ring_mask = &ath12k_wifi7_hw_ring_mask_ipq5332,
+
+ .host_ce_config = ath12k_wifi7_host_ce_config_ipq5332,
+ .ce_count = 12,
+ .target_ce_config = ath12k_wifi7_target_ce_config_wlan_ipq5332,
+ .target_ce_count = 12,
+ .svc_to_ce_map =
+ ath12k_wifi7_target_service_to_ce_map_wlan_ipq5332,
+ .svc_to_ce_map_len = 18,
+
+ .rxdma1_enable = false,
+ .num_rxdma_per_pdev = 1,
+ .num_rxdma_dst_ring = 0,
+ .rx_mac_buf_ring = false,
+ .vdev_start_delay = false,
+
+ .interface_modes = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_MESH_POINT),
+ .supports_monitor = false,
+
+ .idle_ps = false,
+ .download_calib = true,
+ .supports_suspend = false,
+ .tcl_ring_retry = true,
+ .reoq_lut_support = false,
+ .supports_shadow_regs = false,
+
+ .num_tcl_banks = 48,
+ .max_tx_ring = 4,
+
+ .wmi_init = &ath12k_wifi7_wmi_init_qcn9274,
+
+ .qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01),
+
+ .rfkill_pin = 0,
+ .rfkill_cfg = 0,
+ .rfkill_on_level = 0,
+
+ .rddm_size = 0,
+
+ .def_num_link = 0,
+ .max_mlo_peer = 256,
+
+ .otp_board_id_register = 0,
+
+ .supports_sta_ps = false,
+
+ .acpi_guid = NULL,
+ .supports_dynamic_smps_6ghz = false,
+ .iova_mask = 0,
+ .supports_aspm = false,
+
+ .ce_ie_addr = &ath12k_wifi7_ce_ie_addr_ipq5332,
+ .ce_remap = &ath12k_wifi7_ce_remap_ipq5332,
+ .bdf_addr_offset = 0xC00000,
+
+ .dp_primary_link_only = true,
+ },
+ {
+ .name = "qcc2072 hw1.0",
+ .hw_rev = ATH12K_HW_QCC2072_HW10,
+
+ .fw = {
+ .dir = "QCC2072/hw1.0",
+ .board_size = 256 * 1024,
+ .cal_offset = 256 * 1024,
+ .m3_loader = ath12k_m3_fw_loader_driver,
+ .download_aux_ucode = true,
+ },
+
+ .max_radios = 1,
+ .single_pdev_only = true,
+ .qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_WCN7850,
+ .internal_sleep_clock = true,
+
+ .hw_ops = &qcc2072_ops,
+ .ring_mask = &ath12k_wifi7_hw_ring_mask_wcn7850,
+
+ .host_ce_config = ath12k_wifi7_host_ce_config_wcn7850,
+ .ce_count = 9,
+ .target_ce_config = ath12k_wifi7_target_ce_config_wlan_wcn7850,
+ .target_ce_count = 9,
+ .svc_to_ce_map =
+ ath12k_wifi7_target_service_to_ce_map_wlan_wcn7850,
+ .svc_to_ce_map_len = 14,
+
+ .rxdma1_enable = false,
+ .num_rxdma_per_pdev = 2,
+ .num_rxdma_dst_ring = 1,
+ .rx_mac_buf_ring = true,
+ .vdev_start_delay = true,
+
+ .interface_modes = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_P2P_DEVICE) |
+ BIT(NL80211_IFTYPE_P2P_CLIENT) |
+ BIT(NL80211_IFTYPE_P2P_GO),
+ .supports_monitor = true,
+
+ .idle_ps = true,
+ .download_calib = false,
+ .supports_suspend = true,
+ .tcl_ring_retry = false,
+ .reoq_lut_support = false,
+ .supports_shadow_regs = true,
+
+ .num_tcl_banks = 7,
+ .max_tx_ring = 3,
+
+ .mhi_config = &ath12k_wifi7_mhi_config_wcn7850,
+
+ .wmi_init = ath12k_wifi7_wmi_init_wcn7850,
+
+ .qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01) |
+ BIT(CNSS_PCIE_PERST_NO_PULL_V01) |
+ BIT(CNSS_AUX_UC_SUPPORT_V01),
+
+ .rfkill_pin = 0,
+ .rfkill_cfg = 0,
+ .rfkill_on_level = 0,
+
+ .rddm_size = 0x780000,
+
+ .def_num_link = 2,
+ .max_mlo_peer = 32,
+
+ .otp_board_id_register = 0,
+
+ .supports_sta_ps = true,
+
+ .acpi_guid = &wcn7850_uuid,
+ .supports_dynamic_smps_6ghz = false,
+
+ .iova_mask = 0,
+
+ .supports_aspm = true,
+
+ .ce_ie_addr = NULL,
+ .ce_remap = NULL,
+ .bdf_addr_offset = 0,
+
+ .current_cc_support = true,
+
+ .dp_primary_link_only = false,
+ },
+};
+
+/* Note: called under rcu_read_lock() */
+static void ath12k_wifi7_mac_op_tx(struct ieee80211_hw *hw,
+ struct ieee80211_tx_control *control,
+ struct sk_buff *skb)
+{
+ 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 *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif = &ahvif->deflink;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_key_conf *key = info->control.hw_key;
+ struct ieee80211_sta *sta = control->sta;
+ struct ath12k_link_vif *tmp_arvif;
+ u32 info_flags = info->flags;
+ struct sk_buff *msdu_copied;
+ struct ath12k *ar, *tmp_ar;
+ struct ath12k_pdev_dp *dp_pdev, *tmp_dp_pdev;
+ struct ath12k_dp_link_peer *peer;
+ unsigned long links_map;
+ bool is_mcast = false;
+ bool is_dvlan = false;
+ struct ethhdr *eth;
+ bool is_prb_rsp;
+ u16 mcbc_gsn;
+ u8 link_id;
+ int ret;
+ struct ath12k_dp *tmp_dp;
+
+ if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
+ ieee80211_free_txskb(hw, skb);
+ return;
+ }
+
+ link_id = u32_get_bits(info->control.flags, IEEE80211_TX_CTRL_MLO_LINK);
+ memset(skb_cb, 0, sizeof(*skb_cb));
+ skb_cb->vif = vif;
+
+ if (key) {
+ skb_cb->cipher = key->cipher;
+ skb_cb->flags |= ATH12K_SKB_CIPHER_SET;
+ }
+
+ /* handle only for MLO case, use deflink for non MLO case */
+ if (ieee80211_vif_is_mld(vif)) {
+ link_id = ath12k_mac_get_tx_link(sta, vif, link_id, skb, info_flags);
+ if (link_id >= IEEE80211_MLD_MAX_NUM_LINKS) {
+ ieee80211_free_txskb(hw, skb);
+ return;
+ }
+ } else {
+ if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
+ link_id = ATH12K_FIRST_SCAN_LINK;
+ else
+ link_id = 0;
+ }
+
+ arvif = rcu_dereference(ahvif->link[link_id]);
+ if (!arvif || !arvif->ar) {
+ ath12k_warn(ahvif->ah, "failed to find arvif link id %u for frame transmission",
+ link_id);
+ ieee80211_free_txskb(hw, skb);
+ return;
+ }
+
+ ar = arvif->ar;
+ skb_cb->link_id = link_id;
+ /*
+ * as skb_cb is common currently for dp and mgmt tx processing
+ * set this in the common mac op tx function.
+ */
+ skb_cb->ar = ar;
+ is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control);
+
+ if (info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
+ eth = (struct ethhdr *)skb->data;
+ is_mcast = is_multicast_ether_addr(eth->h_dest);
+
+ skb_cb->flags |= ATH12K_SKB_HW_80211_ENCAP;
+ } else if (ieee80211_is_mgmt(hdr->frame_control)) {
+ if (sta && sta->mlo)
+ skb_cb->flags |= ATH12K_SKB_MLO_STA;
+
+ ret = ath12k_mac_mgmt_tx(ar, skb, is_prb_rsp);
+ if (ret) {
+ ath12k_warn(ar->ab, "failed to queue management frame %d\n",
+ ret);
+ ieee80211_free_txskb(hw, skb);
+ }
+ return;
+ }
+
+ if (!(info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP))
+ is_mcast = is_multicast_ether_addr(hdr->addr1);
+
+ /* This is case only for P2P_GO */
+ if (vif->type == NL80211_IFTYPE_AP && vif->p2p)
+ ath12k_mac_add_p2p_noa_ie(ar, vif, skb, is_prb_rsp);
+
+ dp_pdev = ath12k_dp_to_pdev_dp(ar->ab->dp, ar->pdev_idx);
+ if (!dp_pdev) {
+ ieee80211_free_txskb(hw, skb);
+ return;
+ }
+
+ /* Checking if it is a DVLAN frame */
+ if (!test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags) &&
+ !(skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP) &&
+ !(skb_cb->flags & ATH12K_SKB_CIPHER_SET) &&
+ ieee80211_has_protected(hdr->frame_control))
+ is_dvlan = true;
+
+ if (!vif->valid_links || !is_mcast || is_dvlan ||
+ (skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP) ||
+ test_bit(ATH12K_FLAG_RAW_MODE, &ar->ab->dev_flags)) {
+ ret = ath12k_wifi7_dp_tx(dp_pdev, arvif, skb, false, 0, is_mcast);
+ if (unlikely(ret)) {
+ ath12k_warn(ar->ab, "failed to transmit frame %d\n", ret);
+ ieee80211_free_txskb(ar->ah->hw, skb);
+ return;
+ }
+ } else {
+ mcbc_gsn = atomic_inc_return(&ahvif->dp_vif.mcbc_gsn) & 0xfff;
+
+ links_map = ahvif->links_map;
+ for_each_set_bit(link_id, &links_map,
+ IEEE80211_MLD_MAX_NUM_LINKS) {
+ tmp_arvif = rcu_dereference(ahvif->link[link_id]);
+ if (!tmp_arvif || !tmp_arvif->is_up)
+ continue;
+
+ tmp_ar = tmp_arvif->ar;
+ tmp_dp_pdev = ath12k_dp_to_pdev_dp(tmp_ar->ab->dp,
+ tmp_ar->pdev_idx);
+ if (!tmp_dp_pdev)
+ continue;
+ msdu_copied = skb_copy(skb, GFP_ATOMIC);
+ if (!msdu_copied) {
+ ath12k_err(ar->ab,
+ "skb copy failure link_id 0x%X vdevid 0x%X\n",
+ link_id, tmp_arvif->vdev_id);
+ continue;
+ }
+
+ ath12k_mlo_mcast_update_tx_link_address(vif, link_id,
+ msdu_copied,
+ info_flags);
+
+ skb_cb = ATH12K_SKB_CB(msdu_copied);
+ skb_cb->link_id = link_id;
+ skb_cb->vif = vif;
+ skb_cb->ar = tmp_ar;
+
+ /* For open mode, skip peer find logic */
+ if (unlikely(!ahvif->dp_vif.key_cipher))
+ goto skip_peer_find;
+
+ tmp_dp = ath12k_ab_to_dp(tmp_ar->ab);
+ spin_lock_bh(&tmp_dp->dp_lock);
+ peer = ath12k_dp_link_peer_find_by_addr(tmp_dp,
+ tmp_arvif->bssid);
+ if (!peer || !peer->dp_peer) {
+ spin_unlock_bh(&tmp_dp->dp_lock);
+ ath12k_warn(tmp_ar->ab,
+ "failed to find peer for vdev_id 0x%X addr %pM link_map 0x%X\n",
+ tmp_arvif->vdev_id, tmp_arvif->bssid,
+ ahvif->links_map);
+ dev_kfree_skb_any(msdu_copied);
+ continue;
+ }
+
+ key = peer->dp_peer->keys[peer->dp_peer->mcast_keyidx];
+ if (key) {
+ skb_cb->cipher = key->cipher;
+ skb_cb->flags |= ATH12K_SKB_CIPHER_SET;
+
+ hdr = (struct ieee80211_hdr *)msdu_copied->data;
+ if (!ieee80211_has_protected(hdr->frame_control))
+ hdr->frame_control |=
+ cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+ }
+ spin_unlock_bh(&tmp_dp->dp_lock);
+
+skip_peer_find:
+ ret = ath12k_wifi7_dp_tx(tmp_dp_pdev, tmp_arvif,
+ msdu_copied, true, mcbc_gsn, is_mcast);
+ if (unlikely(ret)) {
+ if (ret == -ENOMEM) {
+ /* Drops are expected during heavy multicast
+ * frame flood. Print with debug log
+ * level to avoid lot of console prints
+ */
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
+ "failed to transmit frame %d\n",
+ ret);
+ } else {
+ ath12k_warn(ar->ab,
+ "failed to transmit frame %d\n",
+ ret);
+ }
+
+ dev_kfree_skb_any(msdu_copied);
+ }
+ }
+ ieee80211_free_txskb(ar->ah->hw, skb);
+ }
+}
+
+static const struct ieee80211_ops ath12k_ops_wifi7 = {
+ .tx = ath12k_wifi7_mac_op_tx,
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
+ .start = ath12k_mac_op_start,
+ .stop = ath12k_mac_op_stop,
+ .reconfig_complete = ath12k_mac_op_reconfig_complete,
+ .add_interface = ath12k_mac_op_add_interface,
+ .remove_interface = ath12k_mac_op_remove_interface,
+ .update_vif_offload = ath12k_mac_op_update_vif_offload,
+ .config = ath12k_mac_op_config,
+ .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,
+ .set_key = ath12k_mac_op_set_key,
+ .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,
+ .link_sta_rc_update = ath12k_mac_op_link_sta_rc_update,
+ .conf_tx = ath12k_mac_op_conf_tx,
+ .set_antenna = ath12k_mac_op_set_antenna,
+ .get_antenna = ath12k_mac_op_get_antenna,
+ .ampdu_action = ath12k_mac_op_ampdu_action,
+ .add_chanctx = ath12k_mac_op_add_chanctx,
+ .remove_chanctx = ath12k_mac_op_remove_chanctx,
+ .change_chanctx = ath12k_mac_op_change_chanctx,
+ .assign_vif_chanctx = ath12k_mac_op_assign_vif_chanctx,
+ .unassign_vif_chanctx = ath12k_mac_op_unassign_vif_chanctx,
+ .switch_vif_chanctx = ath12k_mac_op_switch_vif_chanctx,
+ .get_txpower = ath12k_mac_op_get_txpower,
+ .set_rts_threshold = ath12k_mac_op_set_rts_threshold,
+ .set_frag_threshold = ath12k_mac_op_set_frag_threshold,
+ .set_bitrate_mask = ath12k_mac_op_set_bitrate_mask,
+ .get_survey = ath12k_mac_op_get_survey,
+ .flush = ath12k_mac_op_flush,
+ .sta_statistics = ath12k_mac_op_sta_statistics,
+ .link_sta_statistics = ath12k_mac_op_link_sta_statistics,
+ .remain_on_channel = ath12k_mac_op_remain_on_channel,
+ .cancel_remain_on_channel = ath12k_mac_op_cancel_remain_on_channel,
+ .change_sta_links = ath12k_mac_op_change_sta_links,
+ .can_activate_links = ath12k_mac_op_can_activate_links,
+#ifdef CONFIG_PM
+ .suspend = ath12k_wow_op_suspend,
+ .resume = ath12k_wow_op_resume,
+ .set_wakeup = ath12k_wow_op_set_wakeup,
+#endif
+#ifdef CONFIG_ATH12K_DEBUGFS
+ .vif_add_debugfs = ath12k_debugfs_op_vif_add,
+#endif
+ CFG80211_TESTMODE_CMD(ath12k_tm_cmd)
+#ifdef CONFIG_ATH12K_DEBUGFS
+ .link_sta_add_debugfs = ath12k_debugfs_link_sta_op_add,
+#endif
+};
+
+int ath12k_wifi7_hw_init(struct ath12k_base *ab)
+{
+ const struct ath12k_hw_params *hw_params = NULL;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ath12k_wifi7_hw_params); i++) {
+ hw_params = &ath12k_wifi7_hw_params[i];
+
+ if (hw_params->hw_rev == ab->hw_rev)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(ath12k_wifi7_hw_params)) {
+ ath12k_err(ab, "Unsupported Wi-Fi 7 hardware version: 0x%x\n",
+ ab->hw_rev);
+ return -EINVAL;
+ }
+
+ ab->hw_params = hw_params;
+ ab->ath12k_ops = &ath12k_ops_wifi7;
+
+ ath12k_wifi7_hal_init(ab);
+
+ ath12k_info(ab, "Wi-Fi 7 Hardware name: %s\n", ab->hw_params->name);
+
+ return 0;
+}
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hw.h b/drivers/net/wireless/ath/ath12k/wifi7/hw.h
new file mode 100644
index 000000000000..643b6fdfdb66
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hw.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef ATH12K_WIFI7_HW_H
+#define ATH12K_WIFI7_HW_H
+
+struct ath12k_base;
+int ath12k_wifi7_hw_init(struct ath12k_base *ab);
+
+#endif /* ATH12K_WIFI7_HW_H */
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/mhi.c b/drivers/net/wireless/ath/ath12k/wifi7/mhi.c
new file mode 100644
index 000000000000..b8d972659314
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/mhi.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include "../mhi.h"
+#include "mhi.h"
+
+static const struct mhi_channel_config ath12k_wifi7_mhi_channels_qcn9274[] = {
+ {
+ .num = 20,
+ .name = "IPCR",
+ .num_elements = 32,
+ .event_ring = 1,
+ .dir = DMA_TO_DEVICE,
+ .ee_mask = 0x4,
+ .pollcfg = 0,
+ .doorbell = MHI_DB_BRST_DISABLE,
+ .lpm_notify = false,
+ .offload_channel = false,
+ .doorbell_mode_switch = false,
+ .auto_queue = false,
+ },
+ {
+ .num = 21,
+ .name = "IPCR",
+ .num_elements = 32,
+ .event_ring = 1,
+ .dir = DMA_FROM_DEVICE,
+ .ee_mask = 0x4,
+ .pollcfg = 0,
+ .doorbell = MHI_DB_BRST_DISABLE,
+ .lpm_notify = false,
+ .offload_channel = false,
+ .doorbell_mode_switch = false,
+ .auto_queue = true,
+ },
+};
+
+static struct mhi_event_config ath12k_wifi7_mhi_events_qcn9274[] = {
+ {
+ .num_elements = 32,
+ .irq_moderation_ms = 0,
+ .irq = 1,
+ .data_type = MHI_ER_CTRL,
+ .mode = MHI_DB_BRST_DISABLE,
+ .hardware_event = false,
+ .client_managed = false,
+ .offload_channel = false,
+ },
+ {
+ .num_elements = 256,
+ .irq_moderation_ms = 1,
+ .irq = 2,
+ .mode = MHI_DB_BRST_DISABLE,
+ .priority = 1,
+ .hardware_event = false,
+ .client_managed = false,
+ .offload_channel = false,
+ },
+};
+
+const struct mhi_controller_config ath12k_wifi7_mhi_config_qcn9274 = {
+ .max_channels = 30,
+ .timeout_ms = 10000,
+ .use_bounce_buf = false,
+ .buf_len = 0,
+ .num_channels = ARRAY_SIZE(ath12k_wifi7_mhi_channels_qcn9274),
+ .ch_cfg = ath12k_wifi7_mhi_channels_qcn9274,
+ .num_events = ARRAY_SIZE(ath12k_wifi7_mhi_events_qcn9274),
+ .event_cfg = ath12k_wifi7_mhi_events_qcn9274,
+};
+
+static const struct mhi_channel_config ath12k_wifi7_mhi_channels_wcn7850[] = {
+ {
+ .num = 20,
+ .name = "IPCR",
+ .num_elements = 64,
+ .event_ring = 1,
+ .dir = DMA_TO_DEVICE,
+ .ee_mask = 0x4,
+ .pollcfg = 0,
+ .doorbell = MHI_DB_BRST_DISABLE,
+ .lpm_notify = false,
+ .offload_channel = false,
+ .doorbell_mode_switch = false,
+ .auto_queue = false,
+ },
+ {
+ .num = 21,
+ .name = "IPCR",
+ .num_elements = 64,
+ .event_ring = 1,
+ .dir = DMA_FROM_DEVICE,
+ .ee_mask = 0x4,
+ .pollcfg = 0,
+ .doorbell = MHI_DB_BRST_DISABLE,
+ .lpm_notify = false,
+ .offload_channel = false,
+ .doorbell_mode_switch = false,
+ .auto_queue = true,
+ },
+};
+
+static struct mhi_event_config ath12k_wifi7_mhi_events_wcn7850[] = {
+ {
+ .num_elements = 32,
+ .irq_moderation_ms = 0,
+ .irq = 1,
+ .mode = MHI_DB_BRST_DISABLE,
+ .data_type = MHI_ER_CTRL,
+ .hardware_event = false,
+ .client_managed = false,
+ .offload_channel = false,
+ },
+ {
+ .num_elements = 256,
+ .irq_moderation_ms = 1,
+ .irq = 2,
+ .mode = MHI_DB_BRST_DISABLE,
+ .priority = 1,
+ .hardware_event = false,
+ .client_managed = false,
+ .offload_channel = false,
+ },
+};
+
+const struct mhi_controller_config ath12k_wifi7_mhi_config_wcn7850 = {
+ .max_channels = 128,
+ .timeout_ms = 2000,
+ .use_bounce_buf = false,
+ .buf_len = 8192,
+ .num_channels = ARRAY_SIZE(ath12k_wifi7_mhi_channels_wcn7850),
+ .ch_cfg = ath12k_wifi7_mhi_channels_wcn7850,
+ .num_events = ARRAY_SIZE(ath12k_wifi7_mhi_events_wcn7850),
+ .event_cfg = ath12k_wifi7_mhi_events_wcn7850,
+};
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/mhi.h b/drivers/net/wireless/ath/ath12k/wifi7/mhi.h
new file mode 100644
index 000000000000..2e2dd3503d83
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/mhi.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef _ATH12K_WIFI7_MHI_H
+#define _ATH12K_WIFI7_MHI_H
+extern const struct mhi_controller_config ath12k_wifi7_mhi_config_qcn9274;
+extern const struct mhi_controller_config ath12k_wifi7_mhi_config_wcn7850;
+#endif /* _ATH12K_WIFI7_MHI_H */
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/pci.c b/drivers/net/wireless/ath/ath12k/wifi7/pci.c
new file mode 100644
index 000000000000..6c96b52dec13
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/pci.c
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/pci.h>
+
+#include "../pci.h"
+#include "pci.h"
+#include "../core.h"
+#include "../hif.h"
+#include "../mhi.h"
+#include "hw.h"
+#include "../hal.h"
+#include "dp.h"
+#include "core.h"
+#include "hal.h"
+
+#define QCN9274_DEVICE_ID 0x1109
+#define WCN7850_DEVICE_ID 0x1107
+#define QCC2072_DEVICE_ID 0x1112
+
+#define ATH12K_PCI_W7_SOC_HW_VERSION_1 1
+#define ATH12K_PCI_W7_SOC_HW_VERSION_2 2
+
+#define TCSR_SOC_HW_VERSION 0x1B00000
+#define TCSR_SOC_HW_VERSION_MAJOR_MASK GENMASK(11, 8)
+#define TCSR_SOC_HW_VERSION_MINOR_MASK GENMASK(7, 4)
+
+#define WINDOW_REG_ADDRESS 0x310c
+#define WINDOW_REG_ADDRESS_QCC2072 0x3278
+
+static const struct pci_device_id ath12k_wifi7_pci_id_table[] = {
+ { PCI_VDEVICE(QCOM, QCN9274_DEVICE_ID) },
+ { PCI_VDEVICE(QCOM, WCN7850_DEVICE_ID) },
+ { PCI_VDEVICE(QCOM, QCC2072_DEVICE_ID) },
+ {}
+};
+
+MODULE_DEVICE_TABLE(pci, ath12k_wifi7_pci_id_table);
+
+/* TODO: revisit IRQ mapping for new SRNG's */
+static const struct ath12k_msi_config ath12k_wifi7_msi_config[] = {
+ {
+ .total_vectors = 16,
+ .total_users = 3,
+ .users = (struct ath12k_msi_user[]) {
+ { .name = "MHI", .num_vectors = 3, .base_vector = 0 },
+ { .name = "CE", .num_vectors = 5, .base_vector = 3 },
+ { .name = "DP", .num_vectors = 8, .base_vector = 8 },
+ },
+ },
+};
+
+static const struct ath12k_pci_ops ath12k_wifi7_pci_ops_qcn9274 = {
+ .wakeup = NULL,
+ .release = NULL,
+};
+
+static int ath12k_wifi7_pci_bus_wake_up(struct ath12k_base *ab)
+{
+ struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
+
+ return mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
+}
+
+static void ath12k_wifi7_pci_bus_release(struct ath12k_base *ab)
+{
+ struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
+
+ mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
+}
+
+static const struct ath12k_pci_ops ath12k_wifi7_pci_ops_wcn7850 = {
+ .wakeup = ath12k_wifi7_pci_bus_wake_up,
+ .release = ath12k_wifi7_pci_bus_release,
+};
+
+static
+void ath12k_wifi7_pci_read_hw_version(struct ath12k_base *ab,
+ u32 *major, u32 *minor)
+{
+ u32 soc_hw_version;
+
+ soc_hw_version = ath12k_pci_read32(ab, TCSR_SOC_HW_VERSION);
+ *major = u32_get_bits(soc_hw_version, TCSR_SOC_HW_VERSION_MAJOR_MASK);
+ *minor = u32_get_bits(soc_hw_version, TCSR_SOC_HW_VERSION_MINOR_MASK);
+}
+
+static int ath12k_wifi7_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *pci_dev)
+{
+ u32 soc_hw_version_major, soc_hw_version_minor;
+ struct ath12k_pci *ab_pci;
+ struct ath12k_base *ab;
+ int ret;
+
+ ab = pci_get_drvdata(pdev);
+ if (!ab)
+ return -EINVAL;
+
+ ab_pci = ath12k_pci_priv(ab);
+ if (!ab_pci)
+ return -EINVAL;
+
+ switch (pci_dev->device) {
+ case QCN9274_DEVICE_ID:
+ ab_pci->msi_config = &ath12k_wifi7_msi_config[0];
+ ab->static_window_map = true;
+ ab_pci->pci_ops = &ath12k_wifi7_pci_ops_qcn9274;
+ /*
+ * init window reg addr before reading hardware version
+ * as it will be used there
+ */
+ ab_pci->window_reg_addr = WINDOW_REG_ADDRESS;
+ ath12k_wifi7_pci_read_hw_version(ab, &soc_hw_version_major,
+ &soc_hw_version_minor);
+ ab->target_mem_mode = ath12k_core_get_memory_mode(ab);
+ switch (soc_hw_version_major) {
+ case ATH12K_PCI_W7_SOC_HW_VERSION_2:
+ ab->hw_rev = ATH12K_HW_QCN9274_HW20;
+ break;
+ case ATH12K_PCI_W7_SOC_HW_VERSION_1:
+ ab->hw_rev = ATH12K_HW_QCN9274_HW10;
+ break;
+ default:
+ dev_err(&pdev->dev,
+ "Unknown hardware version found for QCN9274: 0x%x\n",
+ soc_hw_version_major);
+ return -EOPNOTSUPP;
+ }
+ break;
+ case WCN7850_DEVICE_ID:
+ ab->id.bdf_search = ATH12K_BDF_SEARCH_BUS_AND_BOARD;
+ ab_pci->msi_config = &ath12k_wifi7_msi_config[0];
+ ab->static_window_map = false;
+ ab_pci->pci_ops = &ath12k_wifi7_pci_ops_wcn7850;
+ /*
+ * init window reg addr before reading hardware version
+ * as it will be used there
+ */
+ ab_pci->window_reg_addr = WINDOW_REG_ADDRESS;
+ ath12k_wifi7_pci_read_hw_version(ab, &soc_hw_version_major,
+ &soc_hw_version_minor);
+ ab->target_mem_mode = ATH12K_QMI_MEMORY_MODE_DEFAULT;
+ switch (soc_hw_version_major) {
+ case ATH12K_PCI_W7_SOC_HW_VERSION_2:
+ ab->hw_rev = ATH12K_HW_WCN7850_HW20;
+ break;
+ default:
+ dev_err(&pdev->dev,
+ "Unknown hardware version found for WCN7850: 0x%x\n",
+ soc_hw_version_major);
+ return -EOPNOTSUPP;
+ }
+ break;
+ case QCC2072_DEVICE_ID:
+ ab->id.bdf_search = ATH12K_BDF_SEARCH_BUS_AND_BOARD;
+ ab_pci->msi_config = &ath12k_wifi7_msi_config[0];
+ ab->static_window_map = false;
+ ab_pci->pci_ops = &ath12k_wifi7_pci_ops_wcn7850;
+ ab_pci->window_reg_addr = WINDOW_REG_ADDRESS_QCC2072;
+ ab->target_mem_mode = ATH12K_QMI_MEMORY_MODE_DEFAULT;
+ /* there is only one version till now */
+ ab->hw_rev = ATH12K_HW_QCC2072_HW10;
+ break;
+ default:
+ dev_err(&pdev->dev, "Unknown Wi-Fi 7 PCI device found: 0x%x\n",
+ pci_dev->device);
+ return -EOPNOTSUPP;
+ }
+
+ ret = ath12k_wifi7_hw_init(ab);
+ if (ret) {
+ dev_err(&pdev->dev, "WiFi-7 hw_init for PCI failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct ath12k_pci_reg_base ath12k_wifi7_reg_base = {
+ .umac_base = HAL_SEQ_WCSS_UMAC_OFFSET,
+ .ce_reg_base = HAL_CE_WFSS_CE_REG_BASE,
+};
+
+static struct ath12k_pci_driver ath12k_wifi7_pci_driver = {
+ .name = "ath12k_wifi7_pci",
+ .id_table = ath12k_wifi7_pci_id_table,
+ .ops.probe = ath12k_wifi7_pci_probe,
+ .reg_base = &ath12k_wifi7_reg_base,
+ .ops.arch_init = ath12k_wifi7_arch_init,
+ .ops.arch_deinit = ath12k_wifi7_arch_deinit,
+};
+
+int ath12k_wifi7_pci_init(void)
+{
+ int ret;
+
+ ret = ath12k_pci_register_driver(ATH12K_DEVICE_FAMILY_WIFI7,
+ &ath12k_wifi7_pci_driver);
+ if (ret) {
+ pr_err("Failed to register ath12k Wi-Fi 7 driver: %d\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+void ath12k_wifi7_pci_exit(void)
+{
+ ath12k_pci_unregister_driver(ATH12K_DEVICE_FAMILY_WIFI7);
+}
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/pci.h b/drivers/net/wireless/ath/ath12k/wifi7/pci.h
new file mode 100644
index 000000000000..662a8bab0ce7
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/pci.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+#ifndef ATH12K_PCI_WIFI7_H
+#define ATH12K_PCI_WIFI7_H
+
+int ath12k_wifi7_pci_init(void);
+void ath12k_wifi7_pci_exit(void);
+
+#endif /* ATH12K_PCI_WIFI7_H */
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/wmi.c b/drivers/net/wireless/ath/ath12k/wifi7/wmi.c
new file mode 100644
index 000000000000..ed538d20d324
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/wmi.c
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include "../core.h"
+#include "wmi.h"
+
+void ath12k_wifi7_wmi_init_qcn9274(struct ath12k_base *ab,
+ struct ath12k_wmi_resource_config_arg *config)
+{
+ config->num_vdevs = ab->num_radios * TARGET_NUM_VDEVS(ab);
+ config->num_peers = ab->num_radios *
+ ath12k_core_get_max_peers_per_radio(ab);
+ config->num_offload_peers = TARGET_NUM_OFFLD_PEERS;
+ config->num_offload_reorder_buffs = TARGET_NUM_OFFLD_REORDER_BUFFS;
+ config->num_peer_keys = TARGET_NUM_PEER_KEYS;
+ config->ast_skid_limit = TARGET_AST_SKID_LIMIT;
+ config->tx_chain_mask = (1 << ab->target_caps.num_rf_chains) - 1;
+ config->rx_chain_mask = (1 << ab->target_caps.num_rf_chains) - 1;
+ config->rx_timeout_pri[0] = TARGET_RX_TIMEOUT_LO_PRI;
+ config->rx_timeout_pri[1] = TARGET_RX_TIMEOUT_LO_PRI;
+ config->rx_timeout_pri[2] = TARGET_RX_TIMEOUT_LO_PRI;
+ config->rx_timeout_pri[3] = TARGET_RX_TIMEOUT_HI_PRI;
+
+ if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags))
+ config->rx_decap_mode = TARGET_DECAP_MODE_RAW;
+ else
+ config->rx_decap_mode = TARGET_DECAP_MODE_NATIVE_WIFI;
+
+ config->scan_max_pending_req = TARGET_SCAN_MAX_PENDING_REQS;
+ config->bmiss_offload_max_vdev = TARGET_BMISS_OFFLOAD_MAX_VDEV;
+ config->roam_offload_max_vdev = TARGET_ROAM_OFFLOAD_MAX_VDEV;
+ config->roam_offload_max_ap_profiles = TARGET_ROAM_OFFLOAD_MAX_AP_PROFILES;
+ config->num_mcast_groups = TARGET_NUM_MCAST_GROUPS;
+ config->num_mcast_table_elems = TARGET_NUM_MCAST_TABLE_ELEMS;
+ config->mcast2ucast_mode = TARGET_MCAST2UCAST_MODE;
+ config->tx_dbg_log_size = TARGET_TX_DBG_LOG_SIZE;
+ config->num_wds_entries = TARGET_NUM_WDS_ENTRIES;
+ config->dma_burst_size = TARGET_DMA_BURST_SIZE;
+ config->rx_skip_defrag_timeout_dup_detection_check =
+ TARGET_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK;
+ config->vow_config = TARGET_VOW_CONFIG;
+ config->gtk_offload_max_vdev = TARGET_GTK_OFFLOAD_MAX_VDEV;
+ config->num_msdu_desc = TARGET_NUM_MSDU_DESC;
+ config->beacon_tx_offload_max_vdev = ab->num_radios * TARGET_MAX_BCN_OFFLD;
+ config->rx_batchmode = TARGET_RX_BATCHMODE;
+ /* Indicates host supports peer map v3 and unmap v2 support */
+ config->peer_map_unmap_version = 0x32;
+ config->twt_ap_pdev_count = ab->num_radios;
+ config->twt_ap_sta_count = 1000;
+ config->ema_max_vap_cnt = ab->num_radios;
+ config->ema_max_profile_period = TARGET_EMA_MAX_PROFILE_PERIOD;
+ config->beacon_tx_offload_max_vdev += config->ema_max_vap_cnt;
+
+ if (test_bit(WMI_TLV_SERVICE_PEER_METADATA_V1A_V1B_SUPPORT, ab->wmi_ab.svc_map))
+ config->peer_metadata_ver = ATH12K_PEER_METADATA_V1B;
+}
+
+void ath12k_wifi7_wmi_init_wcn7850(struct ath12k_base *ab,
+ struct ath12k_wmi_resource_config_arg *config)
+{
+ config->num_vdevs = 4;
+ config->num_peers = 16;
+ config->num_tids = 32;
+
+ config->num_offload_peers = 3;
+ config->num_offload_reorder_buffs = 3;
+ config->num_peer_keys = TARGET_NUM_PEER_KEYS;
+ config->ast_skid_limit = TARGET_AST_SKID_LIMIT;
+ config->tx_chain_mask = (1 << ab->target_caps.num_rf_chains) - 1;
+ config->rx_chain_mask = (1 << ab->target_caps.num_rf_chains) - 1;
+ config->rx_timeout_pri[0] = TARGET_RX_TIMEOUT_LO_PRI;
+ config->rx_timeout_pri[1] = TARGET_RX_TIMEOUT_LO_PRI;
+ config->rx_timeout_pri[2] = TARGET_RX_TIMEOUT_LO_PRI;
+ config->rx_timeout_pri[3] = TARGET_RX_TIMEOUT_HI_PRI;
+ config->rx_decap_mode = TARGET_DECAP_MODE_NATIVE_WIFI;
+ config->scan_max_pending_req = TARGET_SCAN_MAX_PENDING_REQS;
+ config->bmiss_offload_max_vdev = TARGET_BMISS_OFFLOAD_MAX_VDEV;
+ config->roam_offload_max_vdev = TARGET_ROAM_OFFLOAD_MAX_VDEV;
+ config->roam_offload_max_ap_profiles = TARGET_ROAM_OFFLOAD_MAX_AP_PROFILES;
+ config->num_mcast_groups = 0;
+ config->num_mcast_table_elems = 0;
+ config->mcast2ucast_mode = 0;
+ config->tx_dbg_log_size = TARGET_TX_DBG_LOG_SIZE;
+ config->num_wds_entries = 0;
+ config->dma_burst_size = 0;
+ config->rx_skip_defrag_timeout_dup_detection_check = 0;
+ config->vow_config = TARGET_VOW_CONFIG;
+ config->gtk_offload_max_vdev = 2;
+ config->num_msdu_desc = 0x400;
+ config->beacon_tx_offload_max_vdev = 2;
+ config->rx_batchmode = TARGET_RX_BATCHMODE;
+
+ config->peer_map_unmap_version = 0x1;
+ config->use_pdev_id = 1;
+ config->max_frag_entries = 0xa;
+ config->num_tdls_vdevs = 0x1;
+ config->num_tdls_conn_table_entries = 8;
+ config->beacon_tx_offload_max_vdev = 0x2;
+ config->num_multicast_filter_entries = 0x20;
+ config->num_wow_filters = 0x16;
+ config->num_keep_alive_pattern = 0;
+
+ if (test_bit(WMI_TLV_SERVICE_PEER_METADATA_V1A_V1B_SUPPORT, ab->wmi_ab.svc_map))
+ config->peer_metadata_ver = ATH12K_PEER_METADATA_V1A;
+ else
+ config->peer_metadata_ver = ab->wmi_ab.dp_peer_meta_data_ver;
+}
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/wmi.h b/drivers/net/wireless/ath/ath12k/wifi7/wmi.h
new file mode 100644
index 000000000000..ae74e176fa2d
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/wifi7/wmi.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef ATH12K_WMI_WIFI7_H
+#define ATH12K_WMI_WIFI7_H
+
+void ath12k_wifi7_wmi_init_qcn9274(struct ath12k_base *ab,
+ struct ath12k_wmi_resource_config_arg *config);
+void ath12k_wifi7_wmi_init_wcn7850(struct ath12k_base *ab,
+ struct ath12k_wmi_resource_config_arg *config);
+
+#endif
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index 3ce5fcb0e460..7617fc3a2479 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -126,6 +126,14 @@ struct wmi_tlv_mgmt_rx_parse {
bool frame_buf_done;
};
+struct wmi_pdev_set_obss_bitmap_arg {
+ u32 tlv_tag;
+ u32 pdev_id;
+ u32 cmd_id;
+ const u32 *bitmap;
+ const char *label;
+};
+
static const struct ath12k_wmi_tlv_policy ath12k_wmi_tlv_policies[] = {
[WMI_TAG_ARRAY_BYTE] = { .min_len = 0 },
[WMI_TAG_ARRAY_UINT32] = { .min_len = 0 },
@@ -206,103 +214,6 @@ static __le32 ath12k_wmi_tlv_cmd_hdr(u32 cmd, u32 len)
return ath12k_wmi_tlv_hdr(cmd, len - TLV_HDR_SIZE);
}
-void ath12k_wmi_init_qcn9274(struct ath12k_base *ab,
- struct ath12k_wmi_resource_config_arg *config)
-{
- config->num_vdevs = ab->num_radios * TARGET_NUM_VDEVS(ab);
- config->num_peers = ab->num_radios *
- ath12k_core_get_max_peers_per_radio(ab);
- config->num_offload_peers = TARGET_NUM_OFFLD_PEERS;
- config->num_offload_reorder_buffs = TARGET_NUM_OFFLD_REORDER_BUFFS;
- config->num_peer_keys = TARGET_NUM_PEER_KEYS;
- config->ast_skid_limit = TARGET_AST_SKID_LIMIT;
- config->tx_chain_mask = (1 << ab->target_caps.num_rf_chains) - 1;
- config->rx_chain_mask = (1 << ab->target_caps.num_rf_chains) - 1;
- config->rx_timeout_pri[0] = TARGET_RX_TIMEOUT_LO_PRI;
- config->rx_timeout_pri[1] = TARGET_RX_TIMEOUT_LO_PRI;
- config->rx_timeout_pri[2] = TARGET_RX_TIMEOUT_LO_PRI;
- config->rx_timeout_pri[3] = TARGET_RX_TIMEOUT_HI_PRI;
-
- if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags))
- config->rx_decap_mode = TARGET_DECAP_MODE_RAW;
- else
- config->rx_decap_mode = TARGET_DECAP_MODE_NATIVE_WIFI;
-
- config->scan_max_pending_req = TARGET_SCAN_MAX_PENDING_REQS;
- config->bmiss_offload_max_vdev = TARGET_BMISS_OFFLOAD_MAX_VDEV;
- config->roam_offload_max_vdev = TARGET_ROAM_OFFLOAD_MAX_VDEV;
- config->roam_offload_max_ap_profiles = TARGET_ROAM_OFFLOAD_MAX_AP_PROFILES;
- config->num_mcast_groups = TARGET_NUM_MCAST_GROUPS;
- config->num_mcast_table_elems = TARGET_NUM_MCAST_TABLE_ELEMS;
- config->mcast2ucast_mode = TARGET_MCAST2UCAST_MODE;
- config->tx_dbg_log_size = TARGET_TX_DBG_LOG_SIZE;
- config->num_wds_entries = TARGET_NUM_WDS_ENTRIES;
- config->dma_burst_size = TARGET_DMA_BURST_SIZE;
- config->rx_skip_defrag_timeout_dup_detection_check =
- TARGET_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK;
- config->vow_config = TARGET_VOW_CONFIG;
- config->gtk_offload_max_vdev = TARGET_GTK_OFFLOAD_MAX_VDEV;
- config->num_msdu_desc = TARGET_NUM_MSDU_DESC;
- config->beacon_tx_offload_max_vdev = ab->num_radios * TARGET_MAX_BCN_OFFLD;
- config->rx_batchmode = TARGET_RX_BATCHMODE;
- /* Indicates host supports peer map v3 and unmap v2 support */
- config->peer_map_unmap_version = 0x32;
- config->twt_ap_pdev_count = ab->num_radios;
- config->twt_ap_sta_count = 1000;
- config->ema_max_vap_cnt = ab->num_radios;
- config->ema_max_profile_period = TARGET_EMA_MAX_PROFILE_PERIOD;
- config->beacon_tx_offload_max_vdev += config->ema_max_vap_cnt;
-
- if (test_bit(WMI_TLV_SERVICE_PEER_METADATA_V1A_V1B_SUPPORT, ab->wmi_ab.svc_map))
- config->peer_metadata_ver = ATH12K_PEER_METADATA_V1B;
-}
-
-void ath12k_wmi_init_wcn7850(struct ath12k_base *ab,
- struct ath12k_wmi_resource_config_arg *config)
-{
- config->num_vdevs = 4;
- config->num_peers = 16;
- config->num_tids = 32;
-
- config->num_offload_peers = 3;
- config->num_offload_reorder_buffs = 3;
- config->num_peer_keys = TARGET_NUM_PEER_KEYS;
- config->ast_skid_limit = TARGET_AST_SKID_LIMIT;
- config->tx_chain_mask = (1 << ab->target_caps.num_rf_chains) - 1;
- config->rx_chain_mask = (1 << ab->target_caps.num_rf_chains) - 1;
- config->rx_timeout_pri[0] = TARGET_RX_TIMEOUT_LO_PRI;
- config->rx_timeout_pri[1] = TARGET_RX_TIMEOUT_LO_PRI;
- config->rx_timeout_pri[2] = TARGET_RX_TIMEOUT_LO_PRI;
- config->rx_timeout_pri[3] = TARGET_RX_TIMEOUT_HI_PRI;
- config->rx_decap_mode = TARGET_DECAP_MODE_NATIVE_WIFI;
- config->scan_max_pending_req = TARGET_SCAN_MAX_PENDING_REQS;
- config->bmiss_offload_max_vdev = TARGET_BMISS_OFFLOAD_MAX_VDEV;
- config->roam_offload_max_vdev = TARGET_ROAM_OFFLOAD_MAX_VDEV;
- config->roam_offload_max_ap_profiles = TARGET_ROAM_OFFLOAD_MAX_AP_PROFILES;
- config->num_mcast_groups = 0;
- config->num_mcast_table_elems = 0;
- config->mcast2ucast_mode = 0;
- config->tx_dbg_log_size = TARGET_TX_DBG_LOG_SIZE;
- config->num_wds_entries = 0;
- config->dma_burst_size = 0;
- config->rx_skip_defrag_timeout_dup_detection_check = 0;
- config->vow_config = TARGET_VOW_CONFIG;
- config->gtk_offload_max_vdev = 2;
- config->num_msdu_desc = 0x400;
- config->beacon_tx_offload_max_vdev = 2;
- config->rx_batchmode = TARGET_RX_BATCHMODE;
-
- config->peer_map_unmap_version = 0x1;
- config->use_pdev_id = 1;
- config->max_frag_entries = 0xa;
- config->num_tdls_vdevs = 0x1;
- config->num_tdls_conn_table_entries = 8;
- config->beacon_tx_offload_max_vdev = 0x2;
- config->num_multicast_filter_entries = 0x20;
- config->num_wow_filters = 0x16;
- config->num_keep_alive_pattern = 0;
-}
-
#define PRIMAP(_hw_mode_) \
[_hw_mode_] = _hw_mode_##_PRI
@@ -496,6 +407,7 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
struct ath12k_band_cap *cap_band;
struct ath12k_pdev_cap *pdev_cap = &pdev->cap;
struct ath12k_fw_pdev *fw_pdev;
+ u32 supported_bands;
u32 phy_map;
u32 hw_idx, phy_idx = 0;
int i;
@@ -519,14 +431,19 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
return -EINVAL;
mac_caps = wmi_mac_phy_caps + phy_idx;
+ supported_bands = le32_to_cpu(mac_caps->supported_bands);
+
+ if (!(supported_bands & WMI_HOST_WLAN_2GHZ_CAP) &&
+ !(supported_bands & WMI_HOST_WLAN_5GHZ_CAP))
+ return -EINVAL;
pdev->pdev_id = ath12k_wmi_mac_phy_get_pdev_id(mac_caps);
pdev->hw_link_id = ath12k_wmi_mac_phy_get_hw_link_id(mac_caps);
- pdev_cap->supported_bands |= le32_to_cpu(mac_caps->supported_bands);
+ pdev_cap->supported_bands |= supported_bands;
pdev_cap->ampdu_density = le32_to_cpu(mac_caps->ampdu_density);
fw_pdev = &ab->fw_pdev[ab->fw_pdev_count];
- fw_pdev->supported_bands = le32_to_cpu(mac_caps->supported_bands);
+ fw_pdev->supported_bands = supported_bands;
fw_pdev->pdev_id = ath12k_wmi_mac_phy_get_pdev_id(mac_caps);
fw_pdev->phy_id = le32_to_cpu(mac_caps->phy_id);
ab->fw_pdev_count++;
@@ -535,10 +452,12 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
* band to band for a single radio, need to see how this should be
* handled.
*/
- if (le32_to_cpu(mac_caps->supported_bands) & WMI_HOST_WLAN_2GHZ_CAP) {
+ if (supported_bands & WMI_HOST_WLAN_2GHZ_CAP) {
pdev_cap->tx_chain_mask = le32_to_cpu(mac_caps->tx_chain_mask_2g);
pdev_cap->rx_chain_mask = le32_to_cpu(mac_caps->rx_chain_mask_2g);
- } else if (le32_to_cpu(mac_caps->supported_bands) & WMI_HOST_WLAN_5GHZ_CAP) {
+ }
+
+ if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP) {
pdev_cap->vht_cap = le32_to_cpu(mac_caps->vht_cap_info_5g);
pdev_cap->vht_mcs = le32_to_cpu(mac_caps->vht_supp_mcs_5g);
pdev_cap->he_mcs = le32_to_cpu(mac_caps->he_supp_mcs_5g);
@@ -548,8 +467,6 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
WMI_NSS_RATIO_EN_DIS_GET(mac_caps->nss_ratio);
pdev_cap->nss_ratio_info =
WMI_NSS_RATIO_INFO_GET(mac_caps->nss_ratio);
- } else {
- return -EINVAL;
}
/* tx/rx chainmask reported from fw depends on the actual hw chains used,
@@ -565,7 +482,7 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
pdev_cap->rx_chain_mask_shift =
find_first_bit((unsigned long *)&pdev_cap->rx_chain_mask, 32);
- if (le32_to_cpu(mac_caps->supported_bands) & WMI_HOST_WLAN_2GHZ_CAP) {
+ if (supported_bands & WMI_HOST_WLAN_2GHZ_CAP) {
cap_band = &pdev_cap->band[NL80211_BAND_2GHZ];
cap_band->phy_id = le32_to_cpu(mac_caps->phy_id);
cap_band->max_bw_supported = le32_to_cpu(mac_caps->max_bw_supported_2g);
@@ -585,7 +502,7 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
le32_to_cpu(mac_caps->he_ppet2g.ppet16_ppet8_ru3_ru0[i]);
}
- if (le32_to_cpu(mac_caps->supported_bands) & WMI_HOST_WLAN_5GHZ_CAP) {
+ if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP) {
cap_band = &pdev_cap->band[NL80211_BAND_5GHZ];
cap_band->phy_id = le32_to_cpu(mac_caps->phy_id);
cap_band->max_bw_supported =
@@ -2897,7 +2814,8 @@ int ath12k_wmi_send_scan_chan_list_cmd(struct ath12k *ar,
max_chan_limit = (wmi->wmi_ab->max_msg_len[ar->pdev_idx] - len) /
sizeof(*chan_info);
- num_send_chans = min(arg->nallchans, max_chan_limit);
+ num_send_chans = min3(arg->nallchans, max_chan_limit,
+ ATH12K_WMI_MAX_NUM_CHAN_PER_CMD);
arg->nallchans -= num_send_chans;
len += sizeof(*chan_info) * num_send_chans;
@@ -3650,6 +3568,140 @@ ath12k_wmi_send_obss_spr_cmd(struct ath12k *ar, u32 vdev_id,
return ret;
}
+u32 ath12k_wmi_build_obss_pd(const struct ath12k_wmi_obss_pd_arg *arg)
+{
+ u32 param_val = 0;
+
+ param_val |= u32_encode_bits((u8)arg->srg_th, GENMASK(15, 8));
+ param_val |= u32_encode_bits((u8)arg->non_srg_th, GENMASK(7, 0));
+
+ if (arg->srp_support)
+ param_val |= ATH12K_OBSS_PD_THRESHOLD_IN_DBM;
+
+ if (arg->srg_enabled && arg->srp_support)
+ param_val |= ATH12K_OBSS_PD_SRG_EN;
+
+ if (arg->non_srg_enabled)
+ param_val |= ATH12K_OBSS_PD_NON_SRG_EN;
+
+ return param_val;
+}
+
+static int ath12k_wmi_pdev_set_obss_bitmap(struct ath12k *ar,
+ const struct wmi_pdev_set_obss_bitmap_arg *arg)
+{
+ struct wmi_pdev_obss_pd_bitmap_cmd *cmd;
+ struct ath12k_wmi_pdev *wmi = ar->wmi;
+ const int len = sizeof(*cmd);
+ struct sk_buff *skb;
+ int ret;
+
+ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_pdev_obss_pd_bitmap_cmd *)skb->data;
+ cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(arg->tlv_tag, len);
+ cmd->pdev_id = cpu_to_le32(arg->pdev_id);
+ memcpy(cmd->bitmap, arg->bitmap, sizeof(cmd->bitmap));
+
+ ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
+ "wmi set pdev %u %s %08x %08x\n",
+ arg->pdev_id, arg->label, arg->bitmap[0], arg->bitmap[1]);
+
+ ret = ath12k_wmi_cmd_send(wmi, skb, arg->cmd_id);
+ if (ret) {
+ ath12k_warn(ar->ab, "failed to send %s: %d\n", arg->label, ret);
+ dev_kfree_skb(skb);
+ }
+
+ return ret;
+}
+
+int ath12k_wmi_pdev_set_srg_bss_color_bitmap(struct ath12k *ar,
+ u32 pdev_id, const u32 *bitmap)
+{
+ struct wmi_pdev_set_obss_bitmap_arg arg = {
+ .tlv_tag = WMI_TAG_PDEV_SRG_BSS_COLOR_BITMAP_CMD,
+ .pdev_id = pdev_id,
+ .cmd_id = WMI_PDEV_SET_SRG_BSS_COLOR_BITMAP_CMDID,
+ .bitmap = bitmap,
+ .label = "SRG bss color bitmap",
+ };
+
+ return ath12k_wmi_pdev_set_obss_bitmap(ar, &arg);
+}
+
+int ath12k_wmi_pdev_set_srg_partial_bssid_bitmap(struct ath12k *ar,
+ u32 pdev_id, const u32 *bitmap)
+{
+ struct wmi_pdev_set_obss_bitmap_arg arg = {
+ .tlv_tag = WMI_TAG_PDEV_SRG_PARTIAL_BSSID_BITMAP_CMD,
+ .pdev_id = pdev_id,
+ .cmd_id = WMI_PDEV_SET_SRG_PARTIAL_BSSID_BITMAP_CMDID,
+ .bitmap = bitmap,
+ .label = "SRG partial bssid bitmap",
+ };
+
+ return ath12k_wmi_pdev_set_obss_bitmap(ar, &arg);
+}
+
+int ath12k_wmi_pdev_srg_obss_color_enable_bitmap(struct ath12k *ar,
+ u32 pdev_id, const u32 *bitmap)
+{
+ struct wmi_pdev_set_obss_bitmap_arg arg = {
+ .tlv_tag = WMI_TAG_PDEV_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD,
+ .pdev_id = pdev_id,
+ .cmd_id = WMI_PDEV_SET_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID,
+ .bitmap = bitmap,
+ .label = "SRG obss color enable bitmap",
+ };
+
+ return ath12k_wmi_pdev_set_obss_bitmap(ar, &arg);
+}
+
+int ath12k_wmi_pdev_srg_obss_bssid_enable_bitmap(struct ath12k *ar,
+ u32 pdev_id, const u32 *bitmap)
+{
+ struct wmi_pdev_set_obss_bitmap_arg arg = {
+ .tlv_tag = WMI_TAG_PDEV_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD,
+ .pdev_id = pdev_id,
+ .cmd_id = WMI_PDEV_SET_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID,
+ .bitmap = bitmap,
+ .label = "SRG obss bssid enable bitmap",
+ };
+
+ return ath12k_wmi_pdev_set_obss_bitmap(ar, &arg);
+}
+
+int ath12k_wmi_pdev_non_srg_obss_color_enable_bitmap(struct ath12k *ar,
+ u32 pdev_id, const u32 *bitmap)
+{
+ struct wmi_pdev_set_obss_bitmap_arg arg = {
+ .tlv_tag = WMI_TAG_PDEV_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD,
+ .pdev_id = pdev_id,
+ .cmd_id = WMI_PDEV_SET_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID,
+ .bitmap = bitmap,
+ .label = "non SRG obss color enable bitmap",
+ };
+
+ return ath12k_wmi_pdev_set_obss_bitmap(ar, &arg);
+}
+
+int ath12k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(struct ath12k *ar,
+ u32 pdev_id, const u32 *bitmap)
+{
+ struct wmi_pdev_set_obss_bitmap_arg arg = {
+ .tlv_tag = WMI_TAG_PDEV_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD,
+ .pdev_id = pdev_id,
+ .cmd_id = WMI_PDEV_SET_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID,
+ .bitmap = bitmap,
+ .label = "non SRG obss bssid enable bitmap",
+ };
+
+ return ath12k_wmi_pdev_set_obss_bitmap(ar, &arg);
+}
+
int ath12k_wmi_obss_color_cfg_cmd(struct ath12k *ar, u32 vdev_id,
u8 bss_color, u32 period,
bool enable)
@@ -4217,6 +4269,7 @@ int ath12k_wmi_set_hw_mode(struct ath12k_base *ab,
int ath12k_wmi_cmd_init(struct ath12k_base *ab)
{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
struct ath12k_wmi_base *wmi_ab = &ab->wmi_ab;
struct ath12k_wmi_init_cmd_arg arg = {};
@@ -4237,7 +4290,7 @@ int ath12k_wmi_cmd_init(struct ath12k_base *ab)
arg.num_band_to_mac = ab->num_radios;
ath12k_fill_band_to_mac_param(ab, arg.band_to_mac);
- ab->dp.peer_metadata_ver = arg.res_cfg.peer_metadata_ver;
+ dp->peer_metadata_ver = arg.res_cfg.peer_metadata_ver;
return ath12k_init_cmd_send(&wmi_ab->wmi[0], &arg);
}
@@ -4545,7 +4598,7 @@ static int ath12k_wmi_hw_mode_caps(struct ath12k_base *soc,
pref = soc->wmi_ab.preferred_hw_mode;
- if (ath12k_hw_mode_pri_map[mode] < ath12k_hw_mode_pri_map[pref]) {
+ if (ath12k_hw_mode_pri_map[mode] <= ath12k_hw_mode_pri_map[pref]) {
svc_rdy_ext->pref_hw_mode_caps = *hw_mode_caps;
soc->wmi_ab.preferred_hw_mode = mode;
}
@@ -5014,19 +5067,10 @@ ath12k_wmi_tlv_mac_phy_caps_ext_parse(struct ath12k_base *ab,
const struct ath12k_wmi_caps_ext_params *caps,
struct ath12k_pdev *pdev)
{
- struct ath12k_band_cap *cap_band;
- u32 bands, support_320mhz;
+ u32 bands;
int i;
if (ab->hw_params->single_pdev_only) {
- if (caps->hw_mode_id == WMI_HOST_HW_MODE_SINGLE) {
- support_320mhz = le32_to_cpu(caps->eht_cap_phy_info_5ghz[0]) &
- IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
- cap_band = &pdev->cap.band[NL80211_BAND_6GHZ];
- cap_band->eht_cap_phy_info[0] |= support_320mhz;
- return 0;
- }
-
for (i = 0; i < ab->fw_pdev_count; i++) {
struct ath12k_fw_pdev *fw_pdev = &ab->fw_pdev[i];
@@ -5079,14 +5123,22 @@ static int ath12k_wmi_tlv_mac_phy_caps_ext(struct ath12k_base *ab, u16 tag,
void *data)
{
const struct ath12k_wmi_caps_ext_params *caps = ptr;
+ struct ath12k_band_cap *cap_band;
+ u32 support_320mhz;
int i = 0, ret;
if (tag != WMI_TAG_MAC_PHY_CAPABILITIES_EXT)
return -EPROTO;
if (ab->hw_params->single_pdev_only) {
- if (ab->wmi_ab.preferred_hw_mode != le32_to_cpu(caps->hw_mode_id) &&
- caps->hw_mode_id != WMI_HOST_HW_MODE_SINGLE)
+ if (caps->hw_mode_id == WMI_HOST_HW_MODE_SINGLE) {
+ support_320mhz = le32_to_cpu(caps->eht_cap_phy_info_5ghz[0]) &
+ IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
+ cap_band = &ab->pdevs[0].cap.band[NL80211_BAND_6GHZ];
+ cap_band->eht_cap_phy_info[0] |= support_320mhz;
+ }
+
+ if (ab->wmi_ab.preferred_hw_mode != le32_to_cpu(caps->hw_mode_id))
return 0;
} else {
for (i = 0; i < ab->num_radios; i++) {
@@ -5567,6 +5619,10 @@ static int ath12k_wmi_svc_rdy_ext2_parse(struct ath12k_base *ab,
ret);
return ret;
}
+
+ ab->wmi_ab.dp_peer_meta_data_ver =
+ u32_get_bits(parse->arg.target_cap_flags,
+ WMI_TARGET_CAP_FLAGS_RX_PEER_METADATA_VERSION);
break;
case WMI_TAG_ARRAY_STRUCT:
@@ -7372,8 +7428,8 @@ static void ath12k_peer_sta_kickout_event(struct ath12k_base *ab, struct sk_buff
struct wmi_peer_sta_kickout_arg arg = {};
struct ath12k_link_vif *arvif;
struct ieee80211_sta *sta;
- struct ath12k_peer *peer;
- unsigned int link_id;
+ struct ath12k_sta *ahsta;
+ struct ath12k_link_sta *arsta;
struct ath12k *ar;
if (ath12k_pull_peer_sta_kickout_ev(ab, skb, &arg) != 0) {
@@ -7385,42 +7441,24 @@ static void ath12k_peer_sta_kickout_event(struct ath12k_base *ab, struct sk_buff
spin_lock_bh(&ab->base_lock);
- peer = ath12k_peer_find_by_addr(ab, arg.mac_addr);
+ arsta = ath12k_link_sta_find_by_addr(ab, arg.mac_addr);
- if (!peer) {
- ath12k_warn(ab, "peer not found %pM\n",
+ if (!arsta) {
+ ath12k_warn(ab, "arsta not found %pM\n",
arg.mac_addr);
goto exit;
}
- arvif = ath12k_mac_get_arvif_by_vdev_id(ab, peer->vdev_id);
+ arvif = arsta->arvif;
if (!arvif) {
- ath12k_warn(ab, "invalid vdev id in peer sta kickout ev %d",
- peer->vdev_id);
+ ath12k_warn(ab, "invalid arvif in peer sta kickout ev for STA %pM",
+ arg.mac_addr);
goto exit;
}
ar = arvif->ar;
-
- if (peer->mlo) {
- sta = ieee80211_find_sta_by_link_addrs(ath12k_ar_to_hw(ar),
- arg.mac_addr,
- NULL, &link_id);
- if (peer->link_id != link_id) {
- ath12k_warn(ab,
- "Spurious quick kickout for MLO STA %pM with invalid link_id, peer: %d, sta: %d\n",
- arg.mac_addr, peer->link_id, link_id);
- goto exit;
- }
- } else {
- sta = ieee80211_find_sta_by_ifaddr(ath12k_ar_to_hw(ar),
- arg.mac_addr, NULL);
- }
- if (!sta) {
- ath12k_warn(ab, "Spurious quick kickout for %sSTA %pM\n",
- peer->mlo ? "MLO " : "", arg.mac_addr);
- goto exit;
- }
+ ahsta = arsta->ahsta;
+ sta = ath12k_ahsta_to_sta(ahsta);
ath12k_dbg(ab, ATH12K_DBG_WMI,
"peer sta kickout event %pM reason: %d rssi: %d\n",
diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h
index f99fced1610e..0bf0a7941cd3 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -9,6 +9,7 @@
#include <net/mac80211.h>
#include "htc.h"
+#include "cmn_defs.h"
/* Naming conventions for structures:
*
@@ -373,6 +374,12 @@ enum wmi_tlv_cmd_id {
WMI_PDEV_DMA_RING_CFG_REQ_CMDID,
WMI_PDEV_HE_TB_ACTION_FRM_CMDID,
WMI_PDEV_PKTLOG_FILTER_CMDID,
+ WMI_PDEV_SET_SRG_BSS_COLOR_BITMAP_CMDID = 0x403b,
+ WMI_PDEV_SET_SRG_PARTIAL_BSSID_BITMAP_CMDID,
+ WMI_PDEV_SET_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID,
+ WMI_PDEV_SET_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID,
+ WMI_PDEV_SET_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID,
+ WMI_PDEV_SET_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID,
WMI_PDEV_SET_BIOS_SAR_TABLE_CMDID = 0x4044,
WMI_PDEV_SET_BIOS_GEO_TABLE_CMDID = 0x4045,
WMI_PDEV_SET_BIOS_INTERFACE_CMDID = 0x404A,
@@ -1075,6 +1082,9 @@ enum wmi_tlv_pdev_param {
WMI_PDEV_PARAM_RADIO_CHAN_STATS_ENABLE,
WMI_PDEV_PARAM_RADIO_DIAGNOSIS_ENABLE,
WMI_PDEV_PARAM_MESH_MCAST_ENABLE,
+ WMI_PDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD = 0xbc,
+ WMI_PDEV_PARAM_SET_CMD_OBSS_PD_PER_AC = 0xbe,
+ WMI_PDEV_PARAM_ENABLE_SR_PROHIBIT = 0xc6,
};
enum wmi_tlv_vdev_param {
@@ -1986,6 +1996,12 @@ enum wmi_tlv_tag {
WMI_TAG_SERVICE_READY_EXT2_EVENT = 0x334,
WMI_TAG_FILS_DISCOVERY_TMPL_CMD = 0x344,
WMI_TAG_MAC_PHY_CAPABILITIES_EXT = 0x36F,
+ WMI_TAG_PDEV_SRG_BSS_COLOR_BITMAP_CMD = 0x37b,
+ WMI_TAG_PDEV_SRG_PARTIAL_BSSID_BITMAP_CMD,
+ WMI_TAG_PDEV_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD = 0x381,
+ WMI_TAG_PDEV_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD,
+ WMI_TAG_PDEV_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD,
+ WMI_TAG_PDEV_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD,
WMI_TAG_REGULATORY_RULE_EXT_STRUCT = 0x3A9,
WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT,
WMI_TAG_TPC_STATS_GET_CMD = 0x38B,
@@ -2243,6 +2259,7 @@ enum wmi_tlv_service {
WMI_TLV_SERVICE_FREQINFO_IN_METADATA = 219,
WMI_TLV_SERVICE_EXT2_MSG = 220,
WMI_TLV_SERVICE_BEACON_PROTECTION_SUPPORT = 244,
+ WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249,
WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT = 253,
WMI_MAX_EXT_SERVICE = 256,
@@ -2782,6 +2799,8 @@ enum wmi_channel_width {
#define WMI_EHT_MCS_NSS_10_11 GENMASK(11, 8)
#define WMI_EHT_MCS_NSS_12_13 GENMASK(15, 12)
+#define WMI_TARGET_CAP_FLAGS_RX_PEER_METADATA_VERSION GENMASK(1, 0)
+
struct wmi_service_ready_ext2_event {
__le32 reg_db_version;
__le32 hw_min_max_tx_power_2ghz;
@@ -4922,6 +4941,12 @@ struct wmi_obss_spatial_reuse_params_cmd {
__le32 vdev_id;
} __packed;
+struct wmi_pdev_obss_pd_bitmap_cmd {
+ __le32 tlv_header;
+ __le32 pdev_id;
+ __le32 bitmap[2];
+} __packed;
+
#define ATH12K_BSS_COLOR_COLLISION_SCAN_PERIOD_MS 200
#define ATH12K_OBSS_COLOR_COLLISION_DETECTION_DISABLE 0
#define ATH12K_OBSS_COLOR_COLLISION_DETECTION 1
@@ -5151,8 +5176,6 @@ struct wmi_probe_tmpl_cmd {
__le32 buf_len;
} __packed;
-#define MAX_RADIOS 2
-
#define WMI_MLO_CMD_TIMEOUT_HZ (5 * HZ)
#define WMI_SERVICE_READY_TIMEOUT_HZ (5 * HZ)
#define WMI_SEND_TIMEOUT_HZ (3 * HZ)
@@ -5231,6 +5254,8 @@ struct ath12k_wmi_base {
struct ath12k_svc_ext_info svc_ext_info;
u32 sbs_lower_band_end_freq;
struct ath12k_hw_mode_info hw_mode_info;
+
+ u8 dp_peer_meta_data_ver;
};
struct wmi_pdev_set_bios_interface_cmd {
@@ -6323,10 +6348,21 @@ struct ath12k_wmi_rssi_dbm_conv_info_arg {
s8 min_nf_dbm;
};
-void ath12k_wmi_init_qcn9274(struct ath12k_base *ab,
- struct ath12k_wmi_resource_config_arg *config);
-void ath12k_wmi_init_wcn7850(struct ath12k_base *ab,
- struct ath12k_wmi_resource_config_arg *config);
+/* each WMI cmd can hold 58 channel entries at most */
+#define ATH12K_WMI_MAX_NUM_CHAN_PER_CMD 58
+
+#define ATH12K_OBSS_PD_THRESHOLD_IN_DBM BIT(29)
+#define ATH12K_OBSS_PD_SRG_EN BIT(30)
+#define ATH12K_OBSS_PD_NON_SRG_EN BIT(31)
+
+struct ath12k_wmi_obss_pd_arg {
+ bool srp_support;
+ bool srg_enabled;
+ bool non_srg_enabled;
+ s8 srg_th;
+ s8 non_srg_th;
+};
+
int ath12k_wmi_cmd_send(struct ath12k_wmi_pdev *wmi, struct sk_buff *skb,
u32 cmd_id);
struct sk_buff *ath12k_wmi_alloc_skb(struct ath12k_wmi_base *wmi_sc, u32 len);
@@ -6430,6 +6466,19 @@ int ath12k_wmi_send_twt_enable_cmd(struct ath12k *ar, u32 pdev_id);
int ath12k_wmi_send_twt_disable_cmd(struct ath12k *ar, u32 pdev_id);
int ath12k_wmi_send_obss_spr_cmd(struct ath12k *ar, u32 vdev_id,
struct ieee80211_he_obss_pd *he_obss_pd);
+u32 ath12k_wmi_build_obss_pd(const struct ath12k_wmi_obss_pd_arg *arg);
+int ath12k_wmi_pdev_set_srg_bss_color_bitmap(struct ath12k *ar, u32 pdev_id,
+ const u32 *bitmap);
+int ath12k_wmi_pdev_set_srg_partial_bssid_bitmap(struct ath12k *ar, u32 pdev_id,
+ const u32 *bitmap);
+int ath12k_wmi_pdev_srg_obss_color_enable_bitmap(struct ath12k *ar, u32 pdev_id,
+ const u32 *bitmap);
+int ath12k_wmi_pdev_srg_obss_bssid_enable_bitmap(struct ath12k *ar, u32 pdev_id,
+ const u32 *bitmap);
+int ath12k_wmi_pdev_non_srg_obss_color_enable_bitmap(struct ath12k *ar, u32 pdev_id,
+ const u32 *bitmap);
+int ath12k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(struct ath12k *ar, u32 pdev_id,
+ const u32 *bitmap);
int ath12k_wmi_obss_color_cfg_cmd(struct ath12k *ar, u32 vdev_id,
u8 bss_color, u32 period,
bool enable);
diff --git a/drivers/net/wireless/ath/ath12k/wow.c b/drivers/net/wireless/ath/ath12k/wow.c
index e8481626f194..bb08e1740582 100644
--- a/drivers/net/wireless/ath/ath12k/wow.c
+++ b/drivers/net/wireless/ath/ath12k/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-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/delay.h>
@@ -135,6 +135,9 @@ static int ath12k_wow_cleanup(struct ath12k *ar)
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
+ if (arvif != &arvif->ahvif->deflink)
+ continue;
+
ret = ath12k_wow_vif_cleanup(arvif);
if (ret) {
ath12k_warn(ar->ab, "failed to clean wow wakeups on vdev %i: %d\n",
@@ -479,8 +482,12 @@ static int ath12k_wow_set_wakeups(struct ath12k *ar,
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
+ if (arvif != &arvif->ahvif->deflink)
+ continue;
+
if (ath12k_wow_is_p2p_vdev(arvif->ahvif))
continue;
+
ret = ath12k_wow_vif_set_wakeups(arvif, wowlan);
if (ret) {
ath12k_warn(ar->ab, "failed to set wow wakeups on vdev %i: %d\n",
@@ -538,6 +545,9 @@ static int ath12k_wow_nlo_cleanup(struct ath12k *ar)
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
+ if (arvif != &arvif->ahvif->deflink)
+ continue;
+
if (ath12k_wow_is_p2p_vdev(arvif->ahvif))
continue;
@@ -745,6 +755,9 @@ static int ath12k_wow_arp_ns_offload(struct ath12k *ar, bool enable)
list_for_each_entry(arvif, &ar->arvifs, list) {
ahvif = arvif->ahvif;
+ if (arvif != &ahvif->deflink)
+ continue;
+
if (ahvif->vdev_type != WMI_VDEV_TYPE_STA)
continue;
@@ -776,6 +789,9 @@ static int ath12k_gtk_rekey_offload(struct ath12k *ar, bool enable)
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
+ if (arvif != &arvif->ahvif->deflink)
+ continue;
+
if (arvif->ahvif->vdev_type != WMI_VDEV_TYPE_STA ||
!arvif->is_up ||
!arvif->rekey_data.enable_offload)
@@ -919,6 +935,7 @@ cleanup:
exit:
return ret ? 1 : 0;
}
+EXPORT_SYMBOL(ath12k_wow_op_suspend);
void ath12k_wow_op_set_wakeup(struct ieee80211_hw *hw, bool enabled)
{
@@ -929,6 +946,7 @@ void ath12k_wow_op_set_wakeup(struct ieee80211_hw *hw, bool enabled)
device_set_wakeup_enable(ar->ab->dev, enabled);
}
+EXPORT_SYMBOL(ath12k_wow_op_set_wakeup);
int ath12k_wow_op_resume(struct ieee80211_hw *hw)
{
@@ -1001,6 +1019,7 @@ exit:
return ret;
}
+EXPORT_SYMBOL(ath12k_wow_op_resume);
int ath12k_wow_init(struct ath12k *ar)
{
diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h
index 0a3f916a1ef3..fd323ae84c95 100644
--- a/drivers/net/wireless/ath/ath5k/debug.h
+++ b/drivers/net/wireless/ath/ath5k/debug.h
@@ -80,11 +80,9 @@ struct ath5k_dbg_info {
* @ATH5K_DEBUG_CALIBRATE: periodic calibration
* @ATH5K_DEBUG_TXPOWER: transmit power setting
* @ATH5K_DEBUG_LED: led management
- * @ATH5K_DEBUG_DUMP_RX: print received skb content
- * @ATH5K_DEBUG_DUMP_TX: print transmit skb content
* @ATH5K_DEBUG_DUMPBANDS: dump bands
* @ATH5K_DEBUG_DMA: debug dma start/stop
- * @ATH5K_DEBUG_TRACE: trace function calls
+ * @ATH5K_DEBUG_ANI: debug Adaptive Noise Immunity
* @ATH5K_DEBUG_DESC: descriptor setup
* @ATH5K_DEBUG_ANY: show at any debug level
*
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index 0c47be06c153..47d570a5ca6a 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -47,7 +47,7 @@ config ATH9K_PCI
config ATH9K_AHB
bool "Atheros ath9k AHB bus support"
- depends on ATH9K
+ depends on ATH9K && OF
default n
help
This option enables the AHB bus support in ath9k.
diff --git a/drivers/net/wireless/ath/ath9k/common-debug.h b/drivers/net/wireless/ath/ath9k/common-debug.h
index 2938b5b96b07..97948af97682 100644
--- a/drivers/net/wireless/ath/ath9k/common-debug.h
+++ b/drivers/net/wireless/ath/ath9k/common-debug.h
@@ -19,14 +19,14 @@
/**
* struct ath_rx_stats - RX Statistics
* @rx_pkts_all: No. of total frames received, including ones that
- may have had errors.
+ * may have had errors.
* @rx_bytes_all: No. of total bytes received, including ones that
- may have had errors.
+ * may have had errors.
* @crc_err: No. of frames with incorrect CRC value
* @decrypt_crc_err: No. of frames whose CRC check failed after
- decryption process completed
+ * decryption process completed
* @phy_err: No. of frames whose reception failed because the PHY
- encountered an error
+ * encountered an error
* @mic_err: No. of frames with incorrect TKIP MIC verification failure
* @pre_delim_crc_err: Pre-Frame delimiter CRC error detections
* @post_delim_crc_err: Post-Frame delimiter CRC error detections
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index ffcf2276eb92..f55b3afb3777 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -403,15 +403,3 @@ void ath9k_cmn_init_crypto(struct ath_hw *ah)
ath_hw_keyreset(common, (u16) i);
}
EXPORT_SYMBOL(ath9k_cmn_init_crypto);
-
-static int __init ath9k_cmn_init(void)
-{
- return 0;
-}
-module_init(ath9k_cmn_init);
-
-static void __exit ath9k_cmn_exit(void)
-{
- return;
-}
-module_exit(ath9k_cmn_exit);
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index cb3e75969875..804e2a0a0c20 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -142,11 +142,12 @@ struct ath_interrupt_stats {
/**
* struct ath_tx_stats - Statistics about TX
* @tx_pkts_all: No. of total frames transmitted, including ones that
- may have had errors.
+ * may have had errors.
* @tx_bytes_all: No. of total bytes transmitted, including ones that
- may have had errors.
+ * may have had errors.
* @queued: Total MPDUs (non-aggr) queued
* @completed: Total MPDUs (non-aggr) completed
+ * @xretries: Total MPDUs with xretries
* @a_aggr: Total no. of aggregates queued
* @a_queued_hw: Total AMPDUs queued to hardware
* @a_completed: Total AMPDUs completed
@@ -154,14 +155,14 @@ struct ath_interrupt_stats {
* @a_xretries: No. of AMPDUs dropped due to xretries
* @txerr_filtered: No. of frames with TXERR_FILT flag set.
* @fifo_underrun: FIFO underrun occurrences
- Valid only for:
- - non-aggregate condition.
- - first packet of aggregate.
+ * Valid only for:
+ * - non-aggregate condition.
+ * - first packet of aggregate.
* @xtxop: No. of frames filtered because of TXOP limit
* @timer_exp: Transmit timer expiry
* @desc_cfg_err: Descriptor configuration errors
- * @data_urn: TX data underrun errors
- * @delim_urn: TX delimiter underrun errors
+ * @data_underrun: TX data underrun errors
+ * @delim_underrun: TX delimiter underrun errors
* @puttxbuf: Number of times hardware was given txbuf to write.
* @txstart: Number of times hardware was told to start tx.
* @txprocdesc: Number of times tx descriptor was processed
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 9bd1286d2857..31e107c81e2d 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -58,7 +58,7 @@ union wil_tx_desc;
*/
#define WIL_MAX_VIFS 4
-/**
+/*
* extract bits [@b0:@b1] (inclusive) from the value @x
* it should be @b0 <= @b1, or result is incorrect
*/
@@ -433,7 +433,7 @@ extern struct fw_map fw_mapping[MAX_FW_MAPPING_TABLE_SIZE];
* @cid: CID value
* @tid: TID value
*
- * @cidxtid field encoded as bits 0..3 - CID; 4..7 - TID
+ * Returns: @cidxtid field encoded as bits 0..3 - CID; 4..7 - TID
*/
static inline u8 mk_cidxtid(u8 cid, u8 tid)
{
@@ -444,8 +444,7 @@ static inline u8 mk_cidxtid(u8 cid, u8 tid)
* parse_cidxtid - parse @cidxtid field
* @cid: store CID value here
* @tid: store TID value here
- *
- * @cidxtid field encoded as bits 0..3 - CID; 4..7 - TID
+ * @cidxtid: field encoded as bits 0..3 - CID; 4..7 - TID
*/
static inline void parse_cidxtid(u8 cidxtid, u8 *cid, u8 *tid)
{
@@ -500,7 +499,7 @@ enum { /* for wil_ctx.mapped_as */
wil_mapped_as_page = 2,
};
-/**
+/*
* struct wil_ctx - software context for ring descriptor
*/
struct wil_ctx {
@@ -514,7 +513,7 @@ struct wil_desc_ring_rx_swtail { /* relevant for enhanced DMA only */
dma_addr_t pa;
};
-/**
+/*
* A general ring structure, used for RX and TX.
* In legacy DMA it represents the vring,
* In enahnced DMA it represents the descriptor ring (vrings are handled by FW)
@@ -531,7 +530,7 @@ struct wil_ring {
bool is_rx;
};
-/**
+/*
* Additional data for Rx ring.
* Used for enhanced DMA RX chaining.
*/
@@ -543,7 +542,7 @@ struct wil_ring_rx_data {
u16 buff_size;
};
-/**
+/*
* Status ring structure, used for enhanced DMA completions for RX and TX.
*/
struct wil_status_ring {
@@ -586,8 +585,8 @@ struct wil_net_stats {
u32 ft_roams; /* relevant in STA mode */
};
-/**
- * struct tx_rx_ops - different TX/RX ops for legacy and enhanced
+/*
+ * struct wil_txrx_ops - different TX/RX ops for legacy and enhanced
* DMA flow
*/
struct wil_txrx_ops {
@@ -627,7 +626,7 @@ struct wil_txrx_ops {
irqreturn_t (*irq_rx)(int irq, void *cookie);
};
-/**
+/*
* Additional data for Tx ring
*/
struct wil_ring_tx_data {
@@ -658,7 +657,7 @@ enum { /* for wil6210_priv.status */
struct pci_dev;
/**
- * struct tid_ampdu_rx - TID aggregation information (Rx).
+ * struct wil_tid_ampdu_rx - TID aggregation information (Rx).
*
* @reorder_buf: buffer to reorder incoming aggregated MPDUs
* @last_rx: jiffies of last rx activity
@@ -728,7 +727,7 @@ enum wil_rekey_state {
WIL_REKEY_WAIT_M4_SENT = 2,
};
-/**
+/*
* struct wil_sta_info - data for peer
*
* Peer identified by its CID (connection ID)
@@ -741,7 +740,7 @@ struct wil_sta_info {
u8 mid;
enum wil_sta_status status;
struct wil_net_stats stats;
- /**
+ /*
* 20 latency bins. 1st bin counts packets with latency
* of 0..tx_latency_res, last bin counts packets with latency
* of 19*tx_latency_res and above.
@@ -882,7 +881,7 @@ struct wil6210_vif {
struct work_struct enable_tx_key_worker;
};
-/**
+/*
* RX buffer allocated for enhanced DMA RX descriptors
*/
struct wil_rx_buff {
@@ -891,7 +890,7 @@ struct wil_rx_buff {
int id;
};
-/**
+/*
* During Rx completion processing, the driver extracts a buffer ID which
* is used as an index to the rx_buff_mgmt.buff_arr array and then the SKB
* is given to the network stack and the buffer is moved from the 'active'
@@ -1147,7 +1146,7 @@ static inline void wil_c(struct wil6210_priv *wil, u32 reg, u32 val)
wil_w(wil, reg, wil_r(wil, reg) & ~val);
}
-/**
+/*
* wil_cid_valid - check cid is valid
*/
static inline bool wil_cid_valid(struct wil6210_priv *wil, int cid)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index bb96b87b2a6e..61f7e620cab3 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -932,7 +932,7 @@ static struct wireless_dev *brcmf_mon_add_vif(struct wiphy *wiphy,
ndev->type = ARPHRD_IEEE80211_RADIOTAP;
ndev->ieee80211_ptr = &vif->wdev;
ndev->needs_free_netdev = true;
- ndev->priv_destructor = brcmf_cfg80211_free_netdev;
+ ndev->priv_destructor = brcmf_cfg80211_free_vif;
SET_NETDEV_DEV(ndev, wiphy_dev(cfg->wiphy));
ifp = netdev_priv(ndev);
@@ -6082,7 +6082,7 @@ void brcmf_free_vif(struct brcmf_cfg80211_vif *vif)
kfree(vif);
}
-void brcmf_cfg80211_free_netdev(struct net_device *ndev)
+void brcmf_cfg80211_free_vif(struct net_device *ndev)
{
struct brcmf_cfg80211_vif *vif;
struct brcmf_if *ifp;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
index 273c80f2d483..6ceb30142905 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
@@ -182,7 +182,7 @@ struct brcmf_cfg80211_profile {
* @BRCMF_VIF_STATUS_CONNECTED: connected/joined successfully.
* @BRCMF_VIF_STATUS_DISCONNECTING: disconnect/disable in progress.
* @BRCMF_VIF_STATUS_AP_CREATED: AP operation started.
- * @BRCMF_VIF_STATUS_EAP_SUCCUSS: EAPOL handshake successful.
+ * @BRCMF_VIF_STATUS_EAP_SUCCESS: EAPOL handshake successful.
* @BRCMF_VIF_STATUS_ASSOC_SUCCESS: successful SET_SSID received.
*/
enum brcmf_vif_status {
@@ -201,10 +201,12 @@ enum brcmf_vif_status {
* @probe_req_ie: IE info for probe request.
* @probe_res_ie: IE info for probe response.
* @beacon_ie: IE info for beacon frame.
+ * @assoc_req_ie: IE info for association request frame.
* @assoc_res_ie: IE info for association response frame.
* @probe_req_ie_len: IE info length for probe request.
* @probe_res_ie_len: IE info length for probe response.
* @beacon_ie_len: IE info length for beacon frame.
+ * @assoc_req_ie_len: IE info length for association request frame.
* @assoc_res_ie_len: IE info length for association response frame.
*/
struct vif_saved_ie {
@@ -227,12 +229,14 @@ struct vif_saved_ie {
* @wdev: wireless device.
* @profile: profile information.
* @sme_state: SME state using enum brcmf_vif_status bits.
+ * @saved_ie: saved IE info for a vif.
* @list: linked list.
* @mgmt_tx: completion for management frame transmit.
* @mgmt_tx_status: status of last management frame sent to firmware.
* @mgmt_tx_id:
* @mgmt_rx_reg: registered rx mgmt frame types.
* @mbss: Multiple BSS type, set if not first AP (not relevant for P2P).
+ * @is_11d: beacon contains country IE, enable regulatory 802.11d support
* @cqm_rssi_low: Lower RSSI limit for CQM monitoring
* @cqm_rssi_high: Upper RSSI limit for CQM monitoring
* @cqm_rssi_last: Last RSSI reading for CQM monitoring
@@ -489,7 +493,7 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
void brcmf_set_mpc(struct brcmf_if *ndev, int mpc);
bool brcmf_is_apmode_operating(struct wiphy *wiphy);
void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg);
-void brcmf_cfg80211_free_netdev(struct net_device *ndev);
+void brcmf_cfg80211_free_vif(struct net_device *ndev);
int brcmf_set_wsec(struct brcmf_if *ifp, const u8 *key, u16 key_len, u16 flags);
int brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index 862a0336a0b5..616885d6db3f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -674,7 +674,7 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool locked)
netif_carrier_off(ndev);
- ndev->priv_destructor = brcmf_cfg80211_free_netdev;
+ ndev->priv_destructor = brcmf_cfg80211_free_vif;
brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
return 0;
@@ -692,7 +692,7 @@ void brcmf_net_detach(struct net_device *ndev, bool locked)
else
unregister_netdev(ndev);
} else {
- brcmf_cfg80211_free_netdev(ndev);
+ brcmf_cfg80211_free_vif(ndev);
free_netdev(ndev);
}
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c
index b4bba67a45ec..5258681218ea 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c
@@ -4790,7 +4790,7 @@ void wlc_phy_init_lcnphy(struct brcms_phy *pi)
wlc_lcnphy_calib_modes(pi, PHY_PERICAL_PHYINIT);
}
-static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi)
+static void wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi)
{
s8 txpwr = 0;
int i;
@@ -4879,8 +4879,6 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi)
sprom->ant_available_bg);
}
pi_lcn->lcnphy_cck_dig_filt_type = -1;
-
- return true;
}
void wlc_2064_vco_cal(struct brcms_phy *pi)
@@ -4992,10 +4990,7 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi)
pi->pi_fptr.radioloftget = wlc_lcnphy_get_radio_loft;
pi->pi_fptr.detach = wlc_phy_detach_lcnphy;
- if (!wlc_phy_txpwr_srom_read_lcnphy(pi)) {
- kfree(pi->u.pi_lcnphy);
- return false;
- }
+ wlc_phy_txpwr_srom_read_lcnphy(pi);
if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
if (pi_lcn->lcnphy_tempsense_option == 3) {
diff --git a/drivers/net/wireless/intel/iwlegacy/3945-mac.c b/drivers/net/wireless/intel/iwlegacy/3945-mac.c
index 104748fcdc33..54991f31c52c 100644
--- a/drivers/net/wireless/intel/iwlegacy/3945-mac.c
+++ b/drivers/net/wireless/intel/iwlegacy/3945-mac.c
@@ -3224,7 +3224,9 @@ il3945_store_measurement(struct device *d, struct device_attribute *attr,
D_INFO("Invoking measurement of type %d on " "channel %d (for '%s')\n",
type, params.channel, buf);
+ mutex_lock(&il->mutex);
il3945_get_measurement(il, &params, type);
+ mutex_unlock(&il->mutex);
return count;
}
diff --git a/drivers/net/wireless/intel/iwlegacy/3945-rs.c b/drivers/net/wireless/intel/iwlegacy/3945-rs.c
index 1826c37c090c..ecc6c8d2a4c5 100644
--- a/drivers/net/wireless/intel/iwlegacy/3945-rs.c
+++ b/drivers/net/wireless/intel/iwlegacy/3945-rs.c
@@ -448,11 +448,6 @@ il3945_rs_tx_status(void *il_rate, struct ieee80211_supported_band *sband,
return;
}
- if (!il_sta) {
- D_RATE("leave: No STA il data to update!\n");
- return;
- }
-
/* Treat uninitialized rate scaling data same as non-existing. */
if (!rs_sta->il) {
D_RATE("leave: STA il data uninitialized!\n");
@@ -627,7 +622,7 @@ il3945_rs_get_rate(void *il_r, struct ieee80211_sta *sta, void *il_sta,
D_RATE("enter\n");
/* Treat uninitialized rate scaling data same as non-existing. */
- if (rs_sta && !rs_sta->il) {
+ if (!rs_sta->il) {
D_RATE("Rate scaling information not initialized yet.\n");
il_sta = NULL;
}
diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/wireless/intel/iwlegacy/4965-mac.c
index 3588dec75ebd..57fa866efd9f 100644
--- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c
@@ -4606,7 +4606,9 @@ il4965_store_tx_power(struct device *d, struct device_attribute *attr,
if (ret)
IL_INFO("%s is not in decimal form.\n", buf);
else {
+ mutex_lock(&il->mutex);
ret = il_set_tx_power(il, val, false);
+ mutex_unlock(&il->mutex);
if (ret)
IL_ERR("failed setting tx power (0x%08x).\n", ret);
else
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
index d25445bd1e5c..77db8c75e6e2 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
@@ -19,12 +19,6 @@
#define IWL_BZ_SMEM_OFFSET 0x400000
#define IWL_BZ_SMEM_LEN 0xD0000
-#define IWL_BZ_A_FM_B_FW_PRE "iwlwifi-bz-a0-fm-b0"
-#define IWL_BZ_A_FM_C_FW_PRE "iwlwifi-bz-a0-fm-c0"
-#define IWL_BZ_A_FM4_B_FW_PRE "iwlwifi-bz-a0-fm4-b0"
-#define IWL_GL_B_FM_B_FW_PRE "iwlwifi-gl-b0-fm-b0"
-#define IWL_GL_C_FM_C_FW_PRE "iwlwifi-gl-c0-fm-c0"
-
static const struct iwl_family_base_params iwl_bz_base = {
.num_of_queues = 512,
.max_tfd_queue_size = 65536,
@@ -100,9 +94,3 @@ const struct iwl_mac_cfg iwl_gl_mac_cfg = {
.xtal_latency = 12000,
.low_latency_xtal = true,
};
-
-IWL_CORE_FW(IWL_BZ_A_FM_B_FW_PRE, IWL_BZ_UCODE_CORE_MAX);
-IWL_CORE_FW(IWL_BZ_A_FM_C_FW_PRE, IWL_BZ_UCODE_CORE_MAX);
-IWL_CORE_FW(IWL_BZ_A_FM4_B_FW_PRE, IWL_BZ_UCODE_CORE_MAX);
-IWL_CORE_FW(IWL_GL_B_FM_B_FW_PRE, IWL_BZ_UCODE_CORE_MAX);
-IWL_CORE_FW(IWL_GL_C_FM_C_FW_PRE, IWL_BZ_UCODE_CORE_MAX);
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/rf-fm.c b/drivers/net/wireless/intel/iwlwifi/cfg/rf-fm.c
index fd82050e33a3..ad2536f53084 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/rf-fm.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/rf-fm.c
@@ -5,6 +5,12 @@
*/
#include "iwl-config.h"
+#define IWL_BZ_A_FM_B_FW_PRE "iwlwifi-bz-a0-fm-b0"
+#define IWL_BZ_A_FM_C_FW_PRE "iwlwifi-bz-a0-fm-c0"
+#define IWL_BZ_A_FM4_B_FW_PRE "iwlwifi-bz-a0-fm4-b0"
+#define IWL_GL_B_FM_B_FW_PRE "iwlwifi-gl-b0-fm-b0"
+#define IWL_GL_C_FM_C_FW_PRE "iwlwifi-gl-c0-fm-c0"
+
/* NVM versions */
#define IWL_FM_NVM_VERSION 0x0a1d
@@ -50,3 +56,9 @@ const char iwl_be201_name[] = "Intel(R) Wi-Fi 7 BE201 320MHz";
const char iwl_be200_name[] = "Intel(R) Wi-Fi 7 BE200 320MHz";
const char iwl_be202_name[] = "Intel(R) Wi-Fi 7 BE202 160MHz";
const char iwl_be401_name[] = "Intel(R) Wi-Fi 7 BE401 320MHz";
+
+IWL_CORE_FW(IWL_BZ_A_FM_B_FW_PRE, IWL_BZ_UCODE_CORE_MAX);
+IWL_CORE_FW(IWL_BZ_A_FM_C_FW_PRE, IWL_BZ_UCODE_CORE_MAX);
+IWL_CORE_FW(IWL_BZ_A_FM4_B_FW_PRE, IWL_BZ_UCODE_CORE_MAX);
+IWL_CORE_FW(IWL_GL_B_FM_B_FW_PRE, IWL_BZ_UCODE_CORE_MAX);
+IWL_CORE_FW(IWL_GL_C_FM_C_FW_PRE, IWL_BZ_UCODE_CORE_MAX);
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/rf-pe.c b/drivers/net/wireless/intel/iwlwifi/cfg/rf-pe.c
index 408b9850bd10..2c29054ce7b8 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/rf-pe.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/rf-pe.c
@@ -13,5 +13,4 @@ const char iwl_killer_bn1850i_name[] =
const char iwl_bn201_name[] = "Intel(R) Wi-Fi 8 BN201";
const char iwl_bn203_name[] = "Intel(R) Wi-Fi 8 BN203";
-const char iwl_be221_name[] = "Intel(R) Wi-Fi 7 BE221";
const char iwl_be223_name[] = "Intel(R) Wi-Fi 7 BE223";
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
index 52edc19d8cdd..de9aef0d924c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
@@ -28,6 +28,8 @@ static const size_t acpi_dsm_size[DSM_FUNC_NUM_FUNCS] = {
[DSM_FUNC_ENERGY_DETECTION_THRESHOLD] = sizeof(u32),
[DSM_FUNC_RFI_CONFIG] = sizeof(u32),
[DSM_FUNC_ENABLE_11BE] = sizeof(u32),
+ [DSM_FUNC_ENABLE_UNII_9] = sizeof(u32),
+ [DSM_FUNC_ENABLE_11BN] = sizeof(u32),
};
static int iwl_acpi_get_handle(struct device *dev, acpi_string method,
@@ -156,61 +158,104 @@ out:
}
/*
- * This function receives a DSM function number, calculates its expected size
- * according to Intel BIOS spec, and fills in the value in a 32-bit field.
+ * This function loads all the DSM functions, it checks the size and populates
+ * the cache with the values in a 32-bit field.
* In case the expected size is smaller than 32-bit, padding will be added.
*/
-int iwl_acpi_get_dsm(struct iwl_fw_runtime *fwrt,
- enum iwl_dsm_funcs func, u32 *value)
+static int iwl_acpi_load_dsm_values(struct iwl_fw_runtime *fwrt)
{
- size_t expected_size;
- u64 tmp;
+ u64 query_func_val;
int ret;
BUILD_BUG_ON(ARRAY_SIZE(acpi_dsm_size) != DSM_FUNC_NUM_FUNCS);
- if (WARN_ON(func >= ARRAY_SIZE(acpi_dsm_size) || !func))
- return -EINVAL;
+ ret = iwl_acpi_get_dsm_integer(fwrt->dev, ACPI_DSM_REV,
+ DSM_FUNC_QUERY,
+ &iwl_guid, &query_func_val,
+ acpi_dsm_size[DSM_FUNC_QUERY]);
- expected_size = acpi_dsm_size[func];
+ if (ret) {
+ IWL_DEBUG_RADIO(fwrt, "ACPI QUERY FUNC not valid: %d\n", ret);
+ return ret;
+ }
- /* Currently all ACPI DSMs are either 8-bit or 32-bit */
- if (expected_size != sizeof(u8) && expected_size != sizeof(u32))
- return -EOPNOTSUPP;
+ fwrt->dsm_revision = ACPI_DSM_REV;
+ fwrt->dsm_source = BIOS_SOURCE_ACPI;
- if (!fwrt->acpi_dsm_funcs_valid) {
- ret = iwl_acpi_get_dsm_integer(fwrt->dev, ACPI_DSM_REV,
- DSM_FUNC_QUERY,
- &iwl_guid, &tmp,
- acpi_dsm_size[DSM_FUNC_QUERY]);
- if (ret) {
- /* always indicate BIT(0) to avoid re-reading */
- fwrt->acpi_dsm_funcs_valid = BIT(0);
- return ret;
+ IWL_DEBUG_RADIO(fwrt, "ACPI DSM validity bitmap 0x%x\n",
+ (u32)query_func_val);
+
+ /* DSM_FUNC_QUERY is 0, start from 1 */
+ for (int func = 1; func < ARRAY_SIZE(fwrt->dsm_values); func++) {
+ size_t expected_size = acpi_dsm_size[func];
+ u64 tmp;
+
+ if (!(query_func_val & BIT(func))) {
+ IWL_DEBUG_RADIO(fwrt,
+ "ACPI DSM %d not indicated as valid\n",
+ func);
+ continue;
}
- IWL_DEBUG_RADIO(fwrt, "ACPI DSM validity bitmap 0x%x\n",
- (u32)tmp);
- /* always indicate BIT(0) to avoid re-reading */
- fwrt->acpi_dsm_funcs_valid = tmp | BIT(0);
+ /* This is an invalid function (5 for example) */
+ if (!expected_size)
+ continue;
+
+ /* Currently all ACPI DSMs are either 8-bit or 32-bit */
+ if (expected_size != sizeof(u8) && expected_size != sizeof(u32))
+ continue;
+
+ ret = iwl_acpi_get_dsm_integer(fwrt->dev, ACPI_DSM_REV, func,
+ &iwl_guid, &tmp, expected_size);
+ if (ret)
+ continue;
+
+ if ((expected_size == sizeof(u8) && tmp != (u8)tmp) ||
+ (expected_size == sizeof(u32) && tmp != (u32)tmp))
+ IWL_DEBUG_RADIO(fwrt,
+ "DSM value overflows the expected size, truncating\n");
+ fwrt->dsm_values[func] = (u32)tmp;
+ fwrt->dsm_funcs_valid |= BIT(func);
+ }
+
+ return 0;
+}
+
+/*
+ * This function receives a DSM function number, calculates its expected size
+ * according to Intel BIOS spec, and fills in the value in a 32-bit field.
+ * In case the expected size is smaller than 32-bit, padding will be added.
+ */
+int iwl_acpi_get_dsm(struct iwl_fw_runtime *fwrt,
+ enum iwl_dsm_funcs func, u32 *value)
+{
+ if (!fwrt->dsm_funcs_valid) {
+ int ret = iwl_acpi_load_dsm_values(fwrt);
+
+ /*
+ * Always set the valid bit for DSM_FUNC_QUERY so that even if
+ * DSM_FUNC_QUERY returns 0 (no DSM function is valid), we will
+ * still consider the cache as valid.
+ */
+ fwrt->dsm_funcs_valid |= BIT(DSM_FUNC_QUERY);
+
+ if (ret)
+ return ret;
}
- if (!(fwrt->acpi_dsm_funcs_valid & BIT(func))) {
+ BUILD_BUG_ON(ARRAY_SIZE(fwrt->dsm_values) != DSM_FUNC_NUM_FUNCS);
+ BUILD_BUG_ON(BITS_PER_TYPE(fwrt->dsm_funcs_valid) < DSM_FUNC_NUM_FUNCS);
+
+ if (WARN_ON(func >= ARRAY_SIZE(fwrt->dsm_values) || !func))
+ return -EINVAL;
+
+ if (!(fwrt->dsm_funcs_valid & BIT(func))) {
IWL_DEBUG_RADIO(fwrt, "ACPI DSM %d not indicated as valid\n",
func);
return -ENODATA;
}
- ret = iwl_acpi_get_dsm_integer(fwrt->dev, ACPI_DSM_REV, func,
- &iwl_guid, &tmp, expected_size);
- if (ret)
- return ret;
-
- if ((expected_size == sizeof(u8) && tmp != (u8)tmp) ||
- (expected_size == sizeof(u32) && tmp != (u32)tmp))
- IWL_DEBUG_RADIO(fwrt,
- "DSM value overflows the expected size, truncating\n");
- *value = (u32)tmp;
+ *value = fwrt->dsm_values[func];
return 0;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
index f76cea6e9ec8..c7a833f8041a 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
@@ -66,6 +66,18 @@ enum iwl_mac_conf_subcmd_ids {
*/
TWT_OPERATION_CMD = 0x10,
/**
+ * @NAN_CFG_CMD: &struct iwl_nan_config_cmd
+ */
+ NAN_CFG_CMD = 0x12,
+ /**
+ * @NAN_DW_END_NOTIF: &struct iwl_nan_dw_end_notif
+ */
+ NAN_DW_END_NOTIF = 0xf4,
+ /**
+ * @NAN_JOINED_CLUSTER_NOTIF: &struct iwl_nan_cluster_notif
+ */
+ NAN_JOINED_CLUSTER_NOTIF = 0xf5,
+ /**
* @MISSED_BEACONS_NOTIF: &struct iwl_missed_beacons_notif
*/
MISSED_BEACONS_NOTIF = 0xF6,
@@ -492,22 +504,36 @@ enum iwl_link_modify_bandwidth {
};
/**
+ * enum iwl_npca_flags - NPCA flags
+ * @IWL_NPCA_FLAG_MAC_HDR_BASED: MAC header based NPCA operation
+ * permitted in the BSS (MOPLEN)
+ */
+enum iwl_npca_flags {
+ IWL_NPCA_FLAG_MAC_HDR_BASED = BIT(0),
+}; /* NPCA_FLAG_E */
+
+/**
* struct iwl_npca_params - NPCA parameters (non-primary channel access)
*
+ * @dis_subch_bmap: disabled subchannel bitmap for NPCA
* @switch_delay: after switch, delay TX according to destination AP
* @switch_back_delay: switch back to control channel before OBSS frame end
+ * @initial_qsrc: Indicates the value that is used to initialize the
+ * EDCAF QSRC[AC] variables
* @min_dur_threshold: minimum PPDU time to switch to the non-primary
- * NPCA channel
- * @flags: NPCA flags - bit 0: puncturing allowed, bit 1: new TX allowed
+ * NPCA channel (usec)
+ * @flags: NPCA flags, see &enum iwl_npca_flags
* @reserved: reserved for alignment purposes
*/
struct iwl_npca_params {
+ __le16 dis_subch_bmap;
u8 switch_delay;
u8 switch_back_delay;
- __le16 min_dur_threshold;
- __le16 flags;
- __le16 reserved;
-} __packed; /* NPCA_PARAM_API_S_VER_1 */
+ u8 initial_qsrc;
+ u8 min_dur_threshold;
+ u8 flags;
+ u8 reserved;
+} __packed; /* NPCA_PARAM_API_S_VER_2 */
/**
* struct iwl_link_config_cmd - command structure to configure the LINK context
@@ -618,7 +644,8 @@ struct iwl_link_config_cmd {
struct iwl_npca_params npca_params; /* since _VER_7 */
struct iwl_ac_qos prio_edca_params; /* since _VER_7 */
__le32 reserved3[4];
-} __packed; /* LINK_CONTEXT_CONFIG_CMD_API_S_VER_1, _VER_2, _VER_3, _VER_4, _VER_5, _VER_6, _VER_7 */
+} __packed; /* LINK_CONTEXT_CONFIG_CMD_API_S_VER_1, _VER_2, _VER_3, _VER_4,
+ * _VER_5, _VER_6, _VER_7, _VER_8 */
/* Currently FW supports link ids in the range 0-3 and can have
* at most two active links for each vif.
@@ -990,4 +1017,122 @@ struct iwl_twt_operation_cmd {
u8 ul_tid_bitmap;
} __packed; /* TWT_OPERATION_API_S_VER_1 */
+enum iwl_nan_band {
+ IWL_NAN_BAND_5GHZ = 0,
+ IWL_NAN_BAND_2GHZ = 1,
+ IWL_NUM_NAN_BANDS,
+};
+
+/**
+ * struct iwl_nan_band_config - NAN band configuration
+ *
+ * @rssi_close: RSSI threshold for close proximity in dBm
+ * @rssi_middle: RSSI threshold for middle proximity in dBm
+ * @dw_interval: Discovery Window (DW) interval for synchronization beacons and
+ * SDFs. Valid values of DW interval are: 1, 2, 3, 4 and 5 corresponding to
+ * 1, 2, 4, 8, and 16 DWs.
+ * @reserved: reserved
+ */
+struct iwl_nan_band_config {
+ u8 rssi_close;
+ u8 rssi_middle;
+ u8 dw_interval;
+ u8 reserved;
+}; /* NAN_BAND_SPECIFIC_CONFIG_API_S_VER_1 */
+
+/**
+ * enum iwl_nan_flags - flags for NAN configuration
+ *
+ * @IWL_NAN_FLAG_DW_END_NOTIF_ENABLED: indicates that the host wants to receive
+ * notifications when a DW ends.
+ */
+enum iwl_nan_flags {
+ IWL_NAN_FLAG_DW_END_NOTIF_ENABLED = BIT(0),
+};
+
+/**
+ * struct iwl_nan_config_cmd - NAN configuration command
+ *
+ * @action: action to perform, see &enum iwl_ctxt_action
+ * @nmi_addr: NAN Management Interface (NMI) address
+ * @reserved_for_nmi_addr: reserved
+ * @discovery_beacon_interval: discovery beacon interval in TUs
+ * @cluster_id: lower last two bytes of the cluster ID, in case the local
+ * device starts a cluster
+ * @sta_id: station ID of the NAN station
+ * @hb_channel: channel for 5 GHz if the device supports operation on 5 GHz.
+ * Valid values are 44 and 149, which correspond to the 5 GHz channel, and
+ * 0 which means that NAN operation on the 5 GHz band is disabled.
+ * @master_pref: master preference
+ * @dwell_time: dwell time on the discovery channel during scan (milliseconds).
+ * If set to 0, the dwell time is determined by the firmware.
+ * @scan_period: scan period in seconds. If set to 0, the scan period is
+ * determined by the firmware.
+ * @flags: flags for NAN configuration, see &enum iwl_nan_flags
+ * @band_config: band configuration for NAN, one for each band
+ * @nan_attr_len: length of the NAN attributes to be added to the beacon (bytes)
+ * @nan_vendor_elems_len: length of the NAN vendor elements to be added to the
+ * beacon (bytes)
+ * @beacon_data: variable length data that contains the NAN attributes
+ * (&nan_attr_len) followed by the NAN vendor elements
+ * (&nan_vendor_elems_len).
+ */
+struct iwl_nan_config_cmd {
+ __le32 action;
+ u8 nmi_addr[6];
+ __le16 reserved_for_nmi_addr;
+ __le32 discovery_beacon_interval;
+
+ u8 cluster_id[2];
+ u8 sta_id;
+ u8 hb_channel;
+
+ u8 master_pref;
+ u8 dwell_time;
+ u8 scan_period;
+ u8 flags;
+
+ struct iwl_nan_band_config band_config[IWL_NUM_NAN_BANDS];
+
+ __le32 nan_attr_len;
+ __le32 nan_vendor_elems_len;
+ u8 beacon_data[];
+} __packed; /* NAN_CONFIG_CMD_API_S_VER_1 */
+
+/**
+ * enum iwl_nan_cluster_notif_flags - flags for the cluster notification
+ *
+ * @IWL_NAN_CLUSTER_NOTIF_FLAG_NEW_CLUSTER: indicates that the device has
+ * started a new cluster. If not set, the device has joined an existing
+ * cluster.
+ */
+enum iwl_nan_cluster_notif_flags {
+ IWL_NAN_CLUSTER_NOTIF_FLAG_NEW_CLUSTER = BIT(0),
+}; /* NAN_JOINED_CLUSTER_FLAG_E_VER_1 */
+
+/**
+ * struct iwl_nan_cluster_notif - event sent when the device starts or joins a
+ * NAN cluster.
+ *
+ * @cluster_id: the last two bytes of the cluster ID
+ * @flags: combination of &enum iwl_nan_cluster_notif_flags
+ * @reserved: reserved
+ */
+struct iwl_nan_cluster_notif {
+ u8 cluster_id[2];
+ u8 flags;
+ u8 reserved;
+}; /* NAN_JOINED_CLUSTER_NTF_API_S_VER_1 */
+
+/**
+ * struct iwl_nan_dw_end_notif - sent to notify the host the end of a DW.
+ *
+ * @band: band on which the DW ended. See &enum iwl_nan_band.
+ * @reserved: reserved
+ */
+struct iwl_nan_dw_end_notif {
+ u8 band;
+ u8 reserved[3];
+} __packed; /* NAN_DW_END_NTF_API_S_VER_1 */
+
#endif /* __iwl_fw_api_mac_cfg_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
index 4644fc1aa1ec..bd6bf931866f 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
@@ -503,18 +503,26 @@ enum bios_source {
};
/**
- * struct bios_value_u32 - BIOS configuration.
+ * struct iwl_bios_config_hdr - BIOS configuration header
* @table_source: see &enum bios_source
* @table_revision: table revision.
* @reserved: reserved
- * @value: value in bios.
*/
-struct bios_value_u32 {
+struct iwl_bios_config_hdr {
u8 table_source;
u8 table_revision;
u8 reserved[2];
+} __packed; /* BIOS_CONFIG_HDR_API_S_VER_1 */
+
+/**
+ * struct bios_value_u32 - BIOS configuration.
+ * @hdr: bios config header
+ * @value: value in bios.
+ */
+struct bios_value_u32 {
+ struct iwl_bios_config_hdr hdr;
__le32 value;
-} __packed; /* BIOS_TABLE_SOURCE_U32_S_VER_1 */
+} __packed; /* BIOS_CONFIG_DATA_U32_API_S_VER_1 */
/**
* struct iwl_tas_config_cmd - configures the TAS.
@@ -650,6 +658,10 @@ struct iwl_lari_config_change_cmd_v8 {
* bit0: enable 11be in China(CB/CN).
* bit1: enable 11be in South Korea.
* bit 2 - 31: reserved.
+ * @oem_11bn_allow_bitmap: Bitmap of 11bn allowed MCCs. The firmware expects to
+ * get the data from the BIOS.
+ * @oem_unii9_enable: UNII-9 enablement as read from the BIOS
+ * @bios_hdr: bios config header
*/
struct iwl_lari_config_change_cmd {
__le32 config_bitmap;
@@ -661,8 +673,16 @@ struct iwl_lari_config_change_cmd {
__le32 edt_bitmap;
__le32 oem_320mhz_allow_bitmap;
__le32 oem_11be_allow_bitmap;
+ /* since version 13 */
+ __le32 oem_11bn_allow_bitmap;
+ /* since version 13 */
+ __le32 oem_unii9_enable;
+ /* since version 13 */
+ struct iwl_bios_config_hdr bios_hdr;
} __packed;
-/* LARI_CHANGE_CONF_CMD_S_VER_12 */
+/* LARI_CHANGE_CONF_CMD_S_VER_12
+ * LARI_CHANGE_CONF_CMD_S_VER_13
+ */
/* Activate UNII-1 (5.2GHz) for World Wide */
#define ACTIVATE_5G2_IN_WW_MASK BIT(4)
@@ -682,11 +702,11 @@ struct iwl_pnvm_init_complete_ntfy {
/**
* struct iwl_mcc_allowed_ap_type_cmd - struct for MCC_ALLOWED_AP_TYPE_CMD
- * @offset_map: mapping a mcc to UHB AP type support (UATS) allowed
+ * @mcc_to_ap_type_map: mapping an MCC to 6 GHz AP type support (UATS)
* @reserved: reserved
*/
struct iwl_mcc_allowed_ap_type_cmd {
- u8 offset_map[UATS_TABLE_ROW_SIZE][UATS_TABLE_COL_SIZE];
+ u8 mcc_to_ap_type_map[UATS_TABLE_ROW_SIZE][UATS_TABLE_COL_SIZE];
__le16 reserved;
} __packed; /* MCC_ALLOWED_AP_TYPE_CMD_API_S_VER_1 */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h
index 535864e22626..0cd8a12e0f7c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h
@@ -766,7 +766,7 @@ enum iwl_6ghz_ap_type {
* AP_TX_POWER_CONSTRAINTS_CMD
* Used for VLP/LPI/AFC Access Point power constraints for 6GHz channels
* @link_id: linkId
- * @ap_type: see &enum iwl_ap_type
+ * @ap_type: see &enum iwl_6ghz_ap_type
* @eirp_pwr: 8-bit 2s complement signed integer in the range
* -64 dBm to 63 dBm with a 0.5 dB step
* default &DEFAULT_TPE_TX_POWER (no maximum limit)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h
index 9c464e7aba10..ae6be3ed32f8 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h
@@ -73,6 +73,7 @@ enum iwl_tlc_mng_cfg_chains {
* @IWL_TLC_MNG_MODE_VHT: enable VHT
* @IWL_TLC_MNG_MODE_HE: enable HE
* @IWL_TLC_MNG_MODE_EHT: enable EHT
+ * @IWL_TLC_MNG_MODE_UHR: enable UHR
*/
enum iwl_tlc_mng_cfg_mode {
IWL_TLC_MNG_MODE_CCK = 0,
@@ -82,6 +83,7 @@ enum iwl_tlc_mng_cfg_mode {
IWL_TLC_MNG_MODE_VHT,
IWL_TLC_MNG_MODE_HE,
IWL_TLC_MNG_MODE_EHT,
+ IWL_TLC_MNG_MODE_UHR,
};
/**
@@ -205,7 +207,7 @@ struct iwl_tlc_config_cmd_v4 {
} __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_4 */
/**
- * struct iwl_tlc_config_cmd - TLC configuration
+ * struct iwl_tlc_config_cmd_v5 - TLC configuration
* @sta_id: station id
* @reserved1: reserved
* @max_ch_width: max supported channel width from &enum iwl_tlc_mng_cfg_cw
@@ -221,7 +223,7 @@ struct iwl_tlc_config_cmd_v4 {
* @max_tx_op: max TXOP in uSecs for all AC (BK, BE, VO, VI),
* set zero for no limit.
*/
-struct iwl_tlc_config_cmd {
+struct iwl_tlc_config_cmd_v5 {
u8 sta_id;
u8 reserved1[3];
u8 max_ch_width;
@@ -236,6 +238,38 @@ struct iwl_tlc_config_cmd {
} __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_5 */
/**
+ * struct iwl_tlc_config_cmd - TLC configuration
+ * @sta_mask: station mask (in NAN we can have multiple logical stations of
+ * the same peer (with the same TLC configuration)).
+ * @phy_id: the phy id to used for this TLC configuration
+ * @max_ch_width: max supported channel width from &enum iwl_tlc_mng_cfg_cw
+ * @mode: &enum iwl_tlc_mng_cfg_mode
+ * @chains: bitmask of &enum iwl_tlc_mng_cfg_chains
+ * @sgi_ch_width_supp: bitmap of SGI support per channel width
+ * use BIT(&enum iwl_tlc_mng_cfg_cw)
+ * @flags: bitmask of &enum iwl_tlc_mng_cfg_flags
+ * @non_ht_rates: bitmap of supported legacy rates
+ * @ht_rates: bitmap of &enum iwl_tlc_mng_ht_rates, per <nss, channel-width>
+ * pair (0 - 80mhz width and below, 1 - 160mhz, 2 - 320mhz).
+ * @max_mpdu_len: max MPDU length, in bytes
+ * @max_tx_op: max TXOP in uSecs for all AC (BK, BE, VO, VI),
+ * set zero for no limit.
+ */
+struct iwl_tlc_config_cmd {
+ __le32 sta_mask;
+ __le32 phy_id;
+ u8 max_ch_width;
+ u8 mode;
+ u8 chains;
+ u8 sgi_ch_width_supp;
+ __le16 flags;
+ __le16 non_ht_rates;
+ __le32 ht_rates[IWL_TLC_NSS_MAX][IWL_TLC_MCS_PER_BW_NUM_V4];
+ __le16 max_mpdu_len;
+ __le16 max_tx_op;
+} __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_6 */
+
+/**
* enum iwl_tlc_update_flags - updated fields
* @IWL_TLC_NOTIF_FLAG_RATE: last initial rate update
* @IWL_TLC_NOTIF_FLAG_AMSDU: umsdu parameters update
@@ -706,10 +740,11 @@ enum {
#define RATE_MCS_HE_SU_4_LTF 3
#define RATE_MCS_HE_SU_4_LTF_08_GI 4
-/* Bit 24-23: HE type. (0) SU, (1) SU_EXT, (2) MU, (3) trigger based */
+/* Bit 24-23: HE type. (0) SU, (1) HE SU_EXT/UHR ELR, (2) MU, (3) trigger based */
#define RATE_MCS_HE_TYPE_POS 23
#define RATE_MCS_HE_TYPE_SU (0 << RATE_MCS_HE_TYPE_POS)
#define RATE_MCS_HE_TYPE_EXT_SU (1 << RATE_MCS_HE_TYPE_POS)
+#define RATE_MCS_HE_TYPE_UHR_ELR (1 << RATE_MCS_HE_TYPE_POS)
#define RATE_MCS_HE_TYPE_MU (2 << RATE_MCS_HE_TYPE_POS)
#define RATE_MCS_HE_TYPE_TRIG (3 << RATE_MCS_HE_TYPE_POS)
#define RATE_MCS_HE_TYPE_MSK (3 << RATE_MCS_HE_TYPE_POS)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
index 3ed7e0807b90..ac6c1ef2cbcd 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
@@ -1062,13 +1062,37 @@ struct iwl_vht_sigs {
#define OFDM_RX_FRAME_VHT_NUM_OF_DATA_SYM 0x000007ff
#define OFDM_RX_FRAME_VHT_NUM_OF_DATA_SYM_VALID 0x80000000
__le32 a0;
- __le32 a1, a2;
+#define OFDM_RX_FRAME_VHT_BANDWIDTH 0x00000003
+#define OFDM_RX_FRAME_VHT_STBC 0x00000008
+#define OFDM_RX_FRAME_VHT_GRP_ID 0x000003f0
+#define OFDM_RX_FRAME_VHT_STS_USER0 0x00001c00
+#define OFDM_RX_FRAME_VHT_MU_STS_USER1 0x0000e000
+#define OFDM_RX_FRAME_VHT_MU_STS_USER2 0x00070000
+#define OFDM_RX_FRAME_VHT_MU_STS_USER3 0x00380000
+#define OFDM_RX_FRAME_VHT_PARTIAL_AID_OR_MU_STS 0x003fe000
+#define OFDM_RX_FRAME_VHT_MU_MIMO_USER_POSITION 0x03000000
+#define OFDM_RX_FRAME_VHT_NO_STREAMS 0x04000000
+#define OFDM_RX_FRAME_VHT_STS 0x38000000
+ __le32 a1;
+#define OFDM_RX_FRAME_VHT_SHORT_GI 0x00000001
+#define OFDM_RX_FRAME_VHT_SHORT_GI_AMBIG 0x00000002
+#define OFDM_RX_FRAME_VHT_CODING 0x00000004
+#define OFDM_RX_FRAME_VHT_CODING_EXTRA_SYM 0x00000008
+#define OFDM_RX_FRAME_VHT_MCS_OR_MU_CODING 0x000000f0
+#define OFDM_RX_FRAME_VHT_BF_OR_MU_RESERVED 0x00000100
+#define OFDM_RX_FRAME_VHT_CRC 0x0003fc00
+#define OFDM_RX_FRAME_VHT_CRC_OK_BIT 0x00040000
+#define OFDM_RX_FRAME_VHT_CUR_USER_CODING 0x00080000
+#define OFDM_RX_FRAME_VHT_CUR_USER_STS 0x00700000
+ __le32 a2;
};
struct iwl_he_sigs {
#define OFDM_RX_FRAME_HE_BEAM_CHANGE 0x00000001
#define OFDM_RX_FRAME_HE_UL_FLAG 0x00000002
+/* SU/ER-SU: MCS, MU: SIG-B MCS */
#define OFDM_RX_FRAME_HE_MCS 0x0000003c
+/* SU/ER-SU: DCM, MU: SIG-B DCM */
#define OFDM_RX_FRAME_HE_DCM 0x00000040
#define OFDM_RX_FRAME_HE_BSS_COLOR 0x00001f80
#define OFDM_RX_FRAME_HE_SPATIAL_REUSE 0x0001e000
@@ -1247,19 +1271,82 @@ struct iwl_eht_tb_sigs {
};
struct iwl_uhr_sigs {
- __le32 usig_a1, usig_a1_uhr, usig_a2_uhr, b1, b2;
+ /* same as EHT above */
+ __le32 usig_a1;
+#define OFDM_RX_FRAME_UHR_BSS_COLOR2 0x0000003f
+ __le32 usig_a1_uhr;
+#define OFDM_RX_FRAME_UHR_PPDU_TYPE 0x00000003
+#define OFDM_RX_FRAME_UHR_COBF_CSR_DISABLE 0x00000004
+#define OFDM_RX_FRAME_UHR_PUNC_CHANNEL 0x000000f8
+#define OFDM_RX_FRAME_UHR_USIG2_VALIDATE_B8 0x00000100
+#define OFDM_RX_FRAME_UHR_SIG_MCS 0x00000600
+#define OFDM_RX_FRAME_UHR_SIG_SYM_NUM 0x0000f800
+#define OFDM_RX_FRAME_UHR_TRIG_SPATIAL_REUSE_1 0x000f0000
+#define OFDM_RX_FRAME_UHR_TRIG_SPATIAL_REUSE_2 0x00f00000
+#define OFDM_RX_FRAME_UHR_TRIG_USIG2_DISREGARD 0x1f000000
+ __le32 usig_a2_uhr;
+#define OFDM_RX_FRAME_UHR_SPATIAL_REUSE 0x0000000f
+#define OFDM_RX_FRAME_UHR_GI_LTF_TYPE 0x00000030
+#define OFDM_RX_FRAME_UHR_NUM_OF_LTF_SYM 0x000001c0
+#define OFDM_RX_FRAME_UHR_CODING_EXTRA_SYM 0x00000200
+#define OFDM_RX_FRAME_UHR_PE_A_FACTOR 0x00000c00
+#define OFDM_RX_FRAME_UHR_PE_DISAMBIGUITY 0x00001000
+#define OFDM_RX_FRAME_UHR_IM_DISABLE 0x00002000
+#define OFDM_RX_FRAME_UHR_USIG_OVF_DISREGARD 0x0000c000
+#define OFDM_RX_FRAME_UHR_NUM_OF_USERS 0x00070000
+#define OFDM_RX_FRAME_UHR_NSTS 0x00f00000
+#define OFDM_RX_FRAME_UHR_BF 0x01000000
+#define OFDM_RX_FRAME_UHR_USIG_OVF_NDP_DISREGARD 0x06000000
+#define OFDM_RX_FRAME_UHR_COMM_CC1_CRC_OK 0x08000000
+#define OFDM_RX_FRAME_UHR_COMM_CC2_CRC_OK 0x10000000
+#define OFDM_RX_FRAME_UHR_NON_VALID_RU_ALLOC 0x20000000
+ __le32 b1;
+#define OFDM_RX_FRAME_UHR_MCS 0x000001f0
+#define OFDM_RX_FRAME_UHR_CODING 0x00000200
+#define OFDM_RX_FRAME_UHR_SPATIAL_CONFIG 0x00003c00
+#define OFDM_RX_FRAME_UHR_STA_RU 0x003fc000
+#define OFDM_RX_FRAME_UHR_STA_RU_PS160 0x00400000
+#define OFDM_RX_FRAME_UHR_UEQM 0x00800000
+#define OFDM_RX_FRAME_UHR_2XLDPC 0x01000000
+#define OFDM_RX_FRAME_UHR_UEQM_PATTERN 0x06000000
+#define OFDM_RX_FRAME_UHR_IS_MU_MIMO_USER_FIELD 0x08000000
+#define OFDM_RX_FRAME_UHR_USER_FIELD_CRC_OK 0x40000000
+ __le32 b2;
+#define OFDM_RX_UHR_NUM_OF_DATA_SYM 0x000007ff
+#define OFDM_RX_UHR_PE_DURATION 0x00003800
__le32 sig2;
+ /* same as EHT above: OFDM_RX_FRAME_EHT_RU_ALLOC_* */
__le32 cmn[6];
+#define OFDM_RX_FRAME_UHR_USER_FIELD_ID 0x000007ff
__le32 user_id;
};
struct iwl_uhr_tb_sigs {
- __le32 usig_a1, usig_a2_uhr, tb_rx0, tb_rx1;
+ /* same as UHR above */
+ __le32 usig_a1, usig_a2_uhr;
+ /* same as HE above */
+ __le32 tb_rx0, tb_rx1;
};
struct iwl_uhr_elr_sigs {
+ /* same as UHR above */
__le32 usig_a1, usig_a2_uhr;
- __le32 uhr_sig_elr1, uhr_sig_elr2;
+#define OFDM_RX_VECTOR_UHR_ELR_VER_ID 0x00000007
+#define OFDM_RX_VECTOR_UHR_ELR_UPLINK_FLAG 0x00000008
+#define OFDM_RX_VECTOR_UHR_ELR_MCS 0x00000010
+#define OFDM_RX_VECTOR_UHR_ELR_CODING 0x00000020
+#define OFDM_RX_VECTOR_UHR_ELR_LENGTH_IN_SYM 0x00007fc0
+#define OFDM_RX_VECTOR_UHR_ELR_CODING_EXTRA_SYM 0x00008000
+#define OFDM_RX_VECTOR_UHR_ELR_SIG1_CRC_OK 0x00010000
+#define OFDM_RX_VECTOR_UHR_ELR_STA_ID 0x0ffe0000
+#define OFDM_RX_VECTOR_UHR_ELR_DISREGARD 0x70000000
+ __le32 uhr_sig_elr1;
+#define OFDM_RX_VECTOR_UHR_ELR_MARK_BSS_COLOR 0x0000003f
+#define OFDM_RX_VECTOR_UHR_ELR_SIG_ID_INDX 0x00000e00
+#define OFDM_RX_VECTOR_UHR_ELR_STA_RU 0x000ff000
+#define OFDM_RX_VECTOR_UHR_ELR_STA_RU_PS160 0x00100000
+#define OFDM_RX_VECTOR_UHR_ELR_SIG2_CRC_OK 0x00200000
+ __le32 uhr_sig_elr2;
};
union iwl_sigs {
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h
index b9e0b69c6680..378788de1d74 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/file.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h
@@ -447,6 +447,7 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
* during assert handling even if the dump isn't split
* @IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE: Firmware has capability of
* handling raw DSM table data.
+ * @IWL_UCODE_TLV_CAPA_NAN_SYNC_SUPPORT: Supports NAN synchronization
*
* @NUM_IWL_UCODE_TLV_CAPA: number of bits used
*/
@@ -550,6 +551,7 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_RESET_DURING_ASSERT = (__force iwl_ucode_tlv_capa_t)(4 * 32 + 0),
IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE = (__force iwl_ucode_tlv_capa_t)(4 * 32 + 1),
+ IWL_UCODE_TLV_CAPA_NAN_SYNC_SUPPORT = (__force iwl_ucode_tlv_capa_t)(4 * 32 + 2),
NUM_IWL_UCODE_TLV_CAPA
/*
* This construction make both sparse (which cannot increment the previous
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c
index d2ad169ae880..958e71a3c958 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c
@@ -376,8 +376,10 @@ int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
gain = cmd->v7.gain[0];
*cmd_size = sizeof(cmd->v7);
- cmd->v7.ppag_config_info.table_source = fwrt->ppag_bios_source;
- cmd->v7.ppag_config_info.table_revision = fwrt->ppag_bios_rev;
+ cmd->v7.ppag_config_info.hdr.table_source =
+ fwrt->ppag_bios_source;
+ cmd->v7.ppag_config_info.hdr.table_revision =
+ fwrt->ppag_bios_rev;
cmd->v7.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags);
} else {
IWL_DEBUG_RADIO(fwrt, "Unsupported PPAG command version\n");
@@ -488,206 +490,6 @@ bool iwl_add_mcc_to_tas_block_list(u16 *list, u8 *size, u16 mcc)
}
IWL_EXPORT_SYMBOL(iwl_add_mcc_to_tas_block_list);
-__le32 iwl_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt)
-{
- int ret;
- u32 val;
- __le32 config_bitmap = 0;
-
- switch (CSR_HW_RFID_TYPE(fwrt->trans->info.hw_rf_id)) {
- case IWL_CFG_RF_TYPE_HR1:
- case IWL_CFG_RF_TYPE_HR2:
- case IWL_CFG_RF_TYPE_JF1:
- case IWL_CFG_RF_TYPE_JF2:
- ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_INDONESIA_5G2,
- &val);
-
- if (!ret && val == DSM_VALUE_INDONESIA_ENABLE)
- config_bitmap |=
- cpu_to_le32(LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK);
- break;
- default:
- break;
- }
-
- ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_DISABLE_SRD, &val);
- if (!ret) {
- if (val == DSM_VALUE_SRD_PASSIVE)
- config_bitmap |=
- cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_PASSIVE_MSK);
- else if (val == DSM_VALUE_SRD_DISABLE)
- config_bitmap |=
- cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_DISABLED_MSK);
- }
-
- if (fw_has_capa(&fwrt->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_CHINA_22_REG_SUPPORT)) {
- ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_REGULATORY_CONFIG,
- &val);
- /*
- * China 2022 enable if the BIOS object does not exist or
- * if it is enabled in BIOS.
- */
- if (ret < 0 || val & DSM_MASK_CHINA_22_REG)
- config_bitmap |=
- cpu_to_le32(LARI_CONFIG_ENABLE_CHINA_22_REG_SUPPORT_MSK);
- }
-
- return config_bitmap;
-}
-IWL_EXPORT_SYMBOL(iwl_get_lari_config_bitmap);
-
-static size_t iwl_get_lari_config_cmd_size(u8 cmd_ver)
-{
- size_t cmd_size;
-
- switch (cmd_ver) {
- case 12:
- cmd_size = sizeof(struct iwl_lari_config_change_cmd);
- break;
- case 8:
- cmd_size = sizeof(struct iwl_lari_config_change_cmd_v8);
- break;
- case 6:
- cmd_size = sizeof(struct iwl_lari_config_change_cmd_v6);
- break;
- default:
- cmd_size = sizeof(struct iwl_lari_config_change_cmd_v1);
- break;
- }
- return cmd_size;
-}
-
-int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt,
- struct iwl_lari_config_change_cmd *cmd,
- size_t *cmd_size)
-{
- int ret;
- u32 value;
- bool has_raw_dsm_capa = fw_has_capa(&fwrt->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE);
- u8 cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
- WIDE_ID(REGULATORY_AND_NVM_GROUP,
- LARI_CONFIG_CHANGE), 1);
-
- if (WARN_ONCE(cmd_ver > 12,
- "Don't add newer versions to this function\n"))
- return -EINVAL;
-
- memset(cmd, 0, sizeof(*cmd));
- *cmd_size = iwl_get_lari_config_cmd_size(cmd_ver);
-
- cmd->config_bitmap = iwl_get_lari_config_bitmap(fwrt);
-
- ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_11AX_ENABLEMENT, &value);
- if (!ret) {
- if (!has_raw_dsm_capa)
- value &= DSM_11AX_ALLOW_BITMAP;
- cmd->oem_11ax_allow_bitmap = cpu_to_le32(value);
- }
-
- ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_UNII4_CHAN, &value);
- if (!ret) {
- if (!has_raw_dsm_capa)
- value &= DSM_UNII4_ALLOW_BITMAP;
-
- /* Since version 12, bits 4 and 5 are supported
- * regardless of this capability, By pass this masking
- * if firmware has capability of accepting raw DSM table.
- */
- if (!has_raw_dsm_capa && cmd_ver < 12 &&
- !fw_has_capa(&fwrt->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_5G9_FOR_CA))
- value &= ~(DSM_VALUE_UNII4_CANADA_OVERRIDE_MSK |
- DSM_VALUE_UNII4_CANADA_EN_MSK);
-
- cmd->oem_unii4_allow_bitmap = cpu_to_le32(value);
- }
-
- ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ACTIVATE_CHANNEL, &value);
- if (!ret) {
- if (!has_raw_dsm_capa)
- value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V12;
-
- if (!has_raw_dsm_capa && cmd_ver < 8)
- value &= ~ACTIVATE_5G2_IN_WW_MASK;
-
- /* Since version 12, bits 5 and 6 are supported
- * regardless of this capability, By pass this masking
- * if firmware has capability of accepting raw DSM table.
- */
- if (!has_raw_dsm_capa && cmd_ver < 12 &&
- !fw_has_capa(&fwrt->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_UNII4_US_CA))
- value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V8;
-
- cmd->chan_state_active_bitmap = cpu_to_le32(value);
- }
-
- ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_6E, &value);
- if (!ret)
- cmd->oem_uhb_allow_bitmap = cpu_to_le32(value);
-
- ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_FORCE_DISABLE_CHANNELS, &value);
- if (!ret) {
- if (!has_raw_dsm_capa)
- value &= DSM_FORCE_DISABLE_CHANNELS_ALLOWED_BITMAP;
- cmd->force_disable_channels_bitmap = cpu_to_le32(value);
- }
-
- ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENERGY_DETECTION_THRESHOLD,
- &value);
- if (!ret) {
- if (!has_raw_dsm_capa)
- value &= DSM_EDT_ALLOWED_BITMAP;
- cmd->edt_bitmap = cpu_to_le32(value);
- }
-
- ret = iwl_bios_get_wbem(fwrt, &value);
- if (!ret)
- cmd->oem_320mhz_allow_bitmap = cpu_to_le32(value);
-
- ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_11BE, &value);
- if (!ret)
- cmd->oem_11be_allow_bitmap = cpu_to_le32(value);
-
- if (cmd->config_bitmap ||
- cmd->oem_uhb_allow_bitmap ||
- cmd->oem_11ax_allow_bitmap ||
- cmd->oem_unii4_allow_bitmap ||
- cmd->chan_state_active_bitmap ||
- cmd->force_disable_channels_bitmap ||
- cmd->edt_bitmap ||
- cmd->oem_320mhz_allow_bitmap ||
- cmd->oem_11be_allow_bitmap) {
- IWL_DEBUG_RADIO(fwrt,
- "sending LARI_CONFIG_CHANGE, config_bitmap=0x%x, oem_11ax_allow_bitmap=0x%x\n",
- le32_to_cpu(cmd->config_bitmap),
- le32_to_cpu(cmd->oem_11ax_allow_bitmap));
- IWL_DEBUG_RADIO(fwrt,
- "sending LARI_CONFIG_CHANGE, oem_unii4_allow_bitmap=0x%x, chan_state_active_bitmap=0x%x, cmd_ver=%d\n",
- le32_to_cpu(cmd->oem_unii4_allow_bitmap),
- le32_to_cpu(cmd->chan_state_active_bitmap),
- cmd_ver);
- IWL_DEBUG_RADIO(fwrt,
- "sending LARI_CONFIG_CHANGE, oem_uhb_allow_bitmap=0x%x, force_disable_channels_bitmap=0x%x\n",
- le32_to_cpu(cmd->oem_uhb_allow_bitmap),
- le32_to_cpu(cmd->force_disable_channels_bitmap));
- IWL_DEBUG_RADIO(fwrt,
- "sending LARI_CONFIG_CHANGE, edt_bitmap=0x%x, oem_320mhz_allow_bitmap=0x%x\n",
- le32_to_cpu(cmd->edt_bitmap),
- le32_to_cpu(cmd->oem_320mhz_allow_bitmap));
- IWL_DEBUG_RADIO(fwrt,
- "sending LARI_CONFIG_CHANGE, oem_11be_allow_bitmap=0x%x\n",
- le32_to_cpu(cmd->oem_11be_allow_bitmap));
- } else {
- return 1;
- }
-
- return 0;
-}
-IWL_EXPORT_SYMBOL(iwl_fill_lari_config);
-
int iwl_bios_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
u32 *value)
{
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h
index 735482e7adf5..1489031687b7 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h
@@ -125,7 +125,9 @@ enum iwl_dsm_funcs {
DSM_FUNC_ENERGY_DETECTION_THRESHOLD = 10,
DSM_FUNC_RFI_CONFIG = 11,
DSM_FUNC_ENABLE_11BE = 12,
- DSM_FUNC_NUM_FUNCS = 13,
+ DSM_FUNC_ENABLE_11BN = 13,
+ DSM_FUNC_ENABLE_UNII_9 = 14,
+ DSM_FUNC_NUM_FUNCS,
};
enum iwl_dsm_values_srd {
@@ -218,11 +220,6 @@ int iwl_bios_get_mcc(struct iwl_fw_runtime *fwrt, char *mcc);
int iwl_bios_get_eckv(struct iwl_fw_runtime *fwrt, u32 *ext_clk);
int iwl_bios_get_wbem(struct iwl_fw_runtime *fwrt, u32 *value);
-__le32 iwl_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt);
-int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt,
- struct iwl_lari_config_change_cmd *cmd,
- size_t *cmd_size);
-
int iwl_bios_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
u32 *value);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
index 57570ff15622..ff186fb2e0da 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
@@ -116,10 +116,14 @@ struct iwl_txf_iter_data {
* @phy_filters: specific phy filters as read from WPFC BIOS table
* @ppag_bios_rev: PPAG BIOS revision
* @ppag_bios_source: see &enum bios_source
- * @acpi_dsm_funcs_valid: bitmap indicating which DSM values are valid,
+ * @dsm_funcs_valid: bitmap indicating which DSM values are valid,
* zero (default initialization) means it hasn't been read yet,
* and BIT(0) is set when it has since function 0 also has this
- * bitmap and is always supported
+ * bitmap and is always supported.
+ * If the bit is set for a specific function, then the corresponding
+ * entry in &dsm_values is valid.
+ * @dsm_values: cache of the DSM values. The validity of each entry is
+ * determined by &dsm_funcs_valid.
* @geo_enabled: WGDS table is present
* @geo_num_profiles: number of geo profiles
* @geo_rev: geo profiles table revision
@@ -137,6 +141,8 @@ struct iwl_txf_iter_data {
* @timestamp.seq: timestamp marking sequence
* @timestamp.delay: timestamp marking worker delay
* @tpc_enabled: TPC enabled
+ * @dsm_source: one of &enum bios_source. UEFI, ACPI or NONE
+ * @dsm_revision: the revision of the DSM table
*/
struct iwl_fw_runtime {
struct iwl_trans *trans;
@@ -211,9 +217,12 @@ struct iwl_fw_runtime {
bool uats_valid;
u8 uefi_tables_lock_status;
struct iwl_phy_specific_cfg phy_filters;
+ enum bios_source dsm_source;
+ u8 dsm_revision;
-#ifdef CONFIG_ACPI
- u32 acpi_dsm_funcs_valid;
+#if defined(CONFIG_ACPI) || defined(CONFIG_EFI)
+ u32 dsm_funcs_valid;
+ u32 dsm_values[DSM_FUNC_NUM_FUNCS];
#endif
};
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/smem.c b/drivers/net/wireless/intel/iwlwifi/fw/smem.c
index 90fd69b4860c..344ddde85b18 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/smem.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/smem.c
@@ -6,6 +6,7 @@
*/
#include "iwl-drv.h"
#include "runtime.h"
+#include "dbg.h"
#include "fw/api/commands.h"
static void iwl_parse_shared_mem_22000(struct iwl_fw_runtime *fwrt,
@@ -17,7 +18,9 @@ static void iwl_parse_shared_mem_22000(struct iwl_fw_runtime *fwrt,
u8 api_ver = iwl_fw_lookup_notif_ver(fwrt->fw, SYSTEM_GROUP,
SHARED_MEM_CFG_CMD, 0);
- if (WARN_ON(lmac_num > ARRAY_SIZE(mem_cfg->lmac_smem)))
+ /* Note: notification has 3 entries, but we only expect 2 */
+ if (IWL_FW_CHECK(fwrt, lmac_num > ARRAY_SIZE(fwrt->smem_cfg.lmac),
+ "FW advertises %d LMACs\n", lmac_num))
return;
fwrt->smem_cfg.num_lmacs = lmac_num;
@@ -26,7 +29,8 @@ static void iwl_parse_shared_mem_22000(struct iwl_fw_runtime *fwrt,
fwrt->smem_cfg.rxfifo2_size = le32_to_cpu(mem_cfg->rxfifo2_size);
if (api_ver >= 4 &&
- !WARN_ON_ONCE(iwl_rx_packet_payload_len(pkt) < sizeof(*mem_cfg))) {
+ !IWL_FW_CHECK(fwrt, iwl_rx_packet_payload_len(pkt) < sizeof(*mem_cfg),
+ "bad shared mem notification size\n")) {
fwrt->smem_cfg.rxfifo2_control_size =
le32_to_cpu(mem_cfg->rxfifo2_control_size);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
index 4ae4d215e633..a7ba86e06c09 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
@@ -402,8 +402,9 @@ static int iwl_uefi_uats_parse(struct uefi_cnv_wlan_uats_data *uats_data,
if (uats_data->revision != 1)
return -EINVAL;
- memcpy(fwrt->uats_table.offset_map, uats_data->offset_map,
- sizeof(fwrt->uats_table.offset_map));
+ memcpy(fwrt->uats_table.mcc_to_ap_type_map,
+ uats_data->mcc_to_ap_type_map,
+ sizeof(fwrt->uats_table.mcc_to_ap_type_map));
fwrt->uats_valid = true;
@@ -721,17 +722,12 @@ out:
return ret;
}
-int iwl_uefi_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
- u32 *value)
+static int iwl_uefi_load_dsm_values(struct iwl_fw_runtime *fwrt)
{
struct uefi_cnv_var_general_cfg *data;
int ret = -EINVAL;
- BUILD_BUG_ON(ARRAY_SIZE(data->functions) < DSM_FUNC_NUM_FUNCS);
-
- /* Not supported function index */
- if (func >= DSM_FUNC_NUM_FUNCS || func == 5)
- return -EOPNOTSUPP;
+ BUILD_BUG_ON(ARRAY_SIZE(data->functions) < ARRAY_SIZE(fwrt->dsm_values));
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_DSM_NAME,
"DSM", sizeof(*data), NULL);
@@ -743,24 +739,66 @@ int iwl_uefi_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
data->revision);
goto out;
}
+ fwrt->dsm_revision = data->revision;
+ fwrt->dsm_source = BIOS_SOURCE_UEFI;
- if (!(data->functions[DSM_FUNC_QUERY] & BIT(func))) {
- IWL_DEBUG_RADIO(fwrt, "DSM func %d not in 0x%x\n",
- func, data->functions[DSM_FUNC_QUERY]);
- goto out;
- }
+ fwrt->dsm_funcs_valid = data->functions[DSM_FUNC_QUERY];
- *value = data->functions[func];
+ /*
+ * Make sure we don't load the DSM values twice. Set this only after we
+ * validated the DSM table so that if the table in UEFI is not valid,
+ * we will fallback to ACPI.
+ */
+ fwrt->dsm_funcs_valid |= BIT(DSM_FUNC_QUERY);
- IWL_DEBUG_RADIO(fwrt,
- "UEFI: DSM func=%d: value=%d\n", func, *value);
+ for (int func = 1; func < ARRAY_SIZE(fwrt->dsm_values); func++) {
+ if (!(fwrt->dsm_funcs_valid & BIT(func))) {
+ IWL_DEBUG_RADIO(fwrt, "DSM func %d not in 0x%x\n",
+ func, fwrt->dsm_funcs_valid);
+ continue;
+ }
+ fwrt->dsm_values[func] = data->functions[func];
+
+ IWL_DEBUG_RADIO(fwrt,
+ "UEFI: DSM func=%d: value=%d\n", func,
+ fwrt->dsm_values[func]);
+ }
ret = 0;
+
out:
kfree(data);
return ret;
}
+int iwl_uefi_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
+ u32 *value)
+{
+ /* Not supported function index */
+ if (func >= DSM_FUNC_NUM_FUNCS || func == 5)
+ return -EOPNOTSUPP;
+
+ if (!fwrt->dsm_funcs_valid) {
+ int ret = iwl_uefi_load_dsm_values(fwrt);
+
+ if (ret)
+ return ret;
+ }
+
+ if (!(fwrt->dsm_funcs_valid & BIT(func))) {
+ IWL_DEBUG_RADIO(fwrt, "DSM func %d not in 0x%x\n",
+ func, fwrt->dsm_funcs_valid);
+ return -EINVAL;
+ }
+
+ *value = fwrt->dsm_values[func];
+
+ IWL_DEBUG_RADIO(fwrt,
+ "UEFI: DSM func=%d: value=%d\n", func, *value);
+
+ return 0;
+}
+
int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt)
{
struct uefi_cnv_var_puncturing_data *data;
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
index 5a4c557e47c7..349ac1505ad7 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
@@ -60,7 +60,7 @@ struct uefi_cnv_wlan_sgom_data {
struct uefi_cnv_wlan_uats_data {
u8 revision;
- u8 offset_map[IWL_UATS_MAP_SIZE - 1];
+ u8 mcc_to_ap_type_map[IWL_UATS_MAP_SIZE - 1];
} __packed;
struct uefi_cnv_common_step_data {
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
index 076810ee5d34..45cf2bc68e41 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
@@ -687,7 +687,6 @@ extern const char iwl_killer_bn1850w2_name[];
extern const char iwl_killer_bn1850i_name[];
extern const char iwl_bn201_name[];
extern const char iwl_bn203_name[];
-extern const char iwl_be221_name[];
extern const char iwl_be223_name[];
extern const char iwl_ax221_name[];
#if IS_ENABLED(CONFIG_IWLDVM)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/Makefile b/drivers/net/wireless/intel/iwlwifi/mld/Makefile
index c966e573f430..5740c0510b61 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/Makefile
+++ b/drivers/net/wireless/intel/iwlwifi/mld/Makefile
@@ -4,7 +4,7 @@ obj-$(CONFIG_IWLWIFI_KUNIT_TESTS) += tests/
iwlmld-y += mld.o notif.o mac80211.o fw.o power.o iface.o link.o rx.o mcc.o session-protect.o phy.o
iwlmld-y += scan.o sta.o tx.o coex.o tlc.o agg.o key.o regulatory.o ap.o thermal.o roc.o stats.o
-iwlmld-y += low_latency.o mlo.o ptp.o time_sync.o ftm-initiator.o
+iwlmld-y += low_latency.o mlo.o ptp.o time_sync.o ftm-initiator.o nan.o
iwlmld-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
iwlmld-$(CONFIG_IWLWIFI_LEDS) += led.o
iwlmld-$(CONFIG_PM_SLEEP) += d3.o
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/d3.c b/drivers/net/wireless/intel/iwlwifi/mld/d3.c
index dd85be94433c..6595542e95cf 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/d3.c
@@ -996,8 +996,6 @@ static void iwl_mld_mlo_rekey(struct iwl_mld *mld,
struct iwl_mld_wowlan_status *wowlan_status,
struct ieee80211_vif *vif)
{
- struct iwl_mld_old_mlo_keys *old_keys __free(kfree) = NULL;
-
IWL_DEBUG_WOWLAN(mld, "Num of MLO Keys: %d\n", wowlan_status->num_mlo_keys);
if (!wowlan_status->num_mlo_keys)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c
index b9c9cd3f44e4..5c2a2033b3fd 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c
@@ -244,7 +244,7 @@ static size_t iwl_mld_dump_tas_resp(struct iwl_dhc_tas_status_resp *resp,
}
pos += scnprintf(buf + pos, count - pos, "TAS Report\n");
- switch (resp->tas_config_info.table_source) {
+ switch (resp->tas_config_info.hdr.table_source) {
case BIOS_SOURCE_NONE:
pos += scnprintf(buf + pos, count - pos,
"BIOS SOURCE NONE ");
@@ -260,13 +260,13 @@ static size_t iwl_mld_dump_tas_resp(struct iwl_dhc_tas_status_resp *resp,
default:
pos += scnprintf(buf + pos, count - pos,
"BIOS SOURCE UNKNOWN (%d) ",
- resp->tas_config_info.table_source);
+ resp->tas_config_info.hdr.table_source);
break;
}
pos += scnprintf(buf + pos, count - pos,
"revision is: %d data is: 0x%08x\n",
- resp->tas_config_info.table_revision,
+ resp->tas_config_info.hdr.table_revision,
resp->tas_config_info.value);
pos += scnprintf(buf + pos, count - pos, "Current MCC: 0x%x\n",
le16_to_cpu(resp->curr_mcc));
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/iface.c b/drivers/net/wireless/intel/iwlwifi/mld/iface.c
index f15d1f5d1bf5..743e44ff19cf 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/iface.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/iface.c
@@ -337,6 +337,10 @@ int iwl_mld_mac_fw_action(struct iwl_mld *mld, struct ieee80211_vif *vif,
lockdep_assert_wiphy(mld->wiphy);
+ /* NAN interface type is not known to FW */
+ if (vif->type == NL80211_IFTYPE_NAN)
+ return 0;
+
if (action == FW_CTXT_ACTION_REMOVE)
return iwl_mld_rm_mac_from_fw(mld, vif);
@@ -385,21 +389,16 @@ static void iwl_mld_mlo_scan_start_wk(struct wiphy *wiphy,
IWL_MLD_ALLOC_FN(vif, vif)
/* Constructor function for struct iwl_mld_vif */
-static int
+static void
iwl_mld_init_vif(struct iwl_mld *mld, struct ieee80211_vif *vif)
{
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
- int ret;
lockdep_assert_wiphy(mld->wiphy);
mld_vif->mld = mld;
mld_vif->roc_activity = ROC_NUM_ACTIVITIES;
- ret = iwl_mld_allocate_vif_fw_id(mld, &mld_vif->fw_id, vif);
- if (ret)
- return ret;
-
if (!mld->fw_status.in_hw_restart) {
wiphy_work_init(&mld_vif->emlsr.unblock_tpt_wk,
iwl_mld_emlsr_unblock_tpt_wk);
@@ -413,8 +412,6 @@ iwl_mld_init_vif(struct iwl_mld *mld, struct ieee80211_vif *vif)
iwl_mld_mlo_scan_start_wk);
}
iwl_mld_init_internal_sta(&mld_vif->aux_sta);
-
- return 0;
}
int iwl_mld_add_vif(struct iwl_mld *mld, struct ieee80211_vif *vif)
@@ -424,7 +421,13 @@ int iwl_mld_add_vif(struct iwl_mld *mld, struct ieee80211_vif *vif)
lockdep_assert_wiphy(mld->wiphy);
- ret = iwl_mld_init_vif(mld, vif);
+ iwl_mld_init_vif(mld, vif);
+
+ /* NAN interface type is not known to FW */
+ if (vif->type == NL80211_IFTYPE_NAN)
+ return 0;
+
+ ret = iwl_mld_allocate_vif_fw_id(mld, &mld_vif->fw_id, vif);
if (ret)
return ret;
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/iface.h b/drivers/net/wireless/intel/iwlwifi/mld/iface.h
index a3573d20f214..62fca166afd1 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/iface.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/iface.h
@@ -32,6 +32,7 @@ enum iwl_mld_cca_40mhz_wa_status {
* link is preventing EMLSR. This is a temporary blocking that is set when
* there is an indication that a non-BSS interface is to be added.
* @IWL_MLD_EMLSR_BLOCKED_TPT: throughput is too low to make EMLSR worthwhile
+ * @IWL_MLD_EMLSR_BLOCKED_NAN: NAN is preventing EMLSR.
*/
enum iwl_mld_emlsr_blocked {
IWL_MLD_EMLSR_BLOCKED_PREVENTION = 0x1,
@@ -40,6 +41,7 @@ enum iwl_mld_emlsr_blocked {
IWL_MLD_EMLSR_BLOCKED_NON_BSS = 0x8,
IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS = 0x10,
IWL_MLD_EMLSR_BLOCKED_TPT = 0x20,
+ IWL_MLD_EMLSR_BLOCKED_NAN = 0x40,
};
/**
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
index cd0dce8de856..3414b04a6953 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
@@ -50,7 +50,7 @@
{ \
.max = 1, \
.types = BIT(NL80211_IFTYPE_P2P_DEVICE), \
- }
+ },
static const struct ieee80211_iface_limit iwl_mld_limits[] = {
IWL_MLD_LIMITS(0)
@@ -60,6 +60,22 @@ static const struct ieee80211_iface_limit iwl_mld_limits_ap[] = {
IWL_MLD_LIMITS(BIT(NL80211_IFTYPE_AP))
};
+static const struct ieee80211_iface_limit iwl_mld_limits_nan[] = {
+ {
+ .max = 2,
+ .types = BIT(NL80211_IFTYPE_STATION),
+ },
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_NAN),
+ },
+ /* Removed when two channels are permitted */
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_AP),
+ },
+};
+
static const struct ieee80211_iface_combination
iwl_mld_iface_combinations[] = {
{
@@ -74,6 +90,19 @@ iwl_mld_iface_combinations[] = {
.limits = iwl_mld_limits_ap,
.n_limits = ARRAY_SIZE(iwl_mld_limits_ap),
},
+ /* NAN combinations follow, these exclude P2P */
+ {
+ .num_different_channels = 2,
+ .max_interfaces = 3,
+ .limits = iwl_mld_limits_nan,
+ .n_limits = ARRAY_SIZE(iwl_mld_limits_nan) - 1,
+ },
+ {
+ .num_different_channels = 1,
+ .max_interfaces = 4,
+ .limits = iwl_mld_limits_nan,
+ .n_limits = ARRAY_SIZE(iwl_mld_limits_nan),
+ }
};
static const u8 ext_capa_base[IWL_MLD_STA_EXT_CAPA_SIZE] = {
@@ -305,8 +334,38 @@ static void iwl_mac_hw_set_wiphy(struct iwl_mld *mld)
wiphy->hw_timestamp_max_peers = 1;
- wiphy->iface_combinations = iwl_mld_iface_combinations;
- wiphy->n_iface_combinations = ARRAY_SIZE(iwl_mld_iface_combinations);
+ if (iwl_mld_nan_supported(mld)) {
+ hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_NAN);
+ hw->wiphy->iface_combinations = iwl_mld_iface_combinations;
+ hw->wiphy->n_iface_combinations =
+ ARRAY_SIZE(iwl_mld_iface_combinations);
+
+ hw->wiphy->nan_supported_bands = BIT(NL80211_BAND_2GHZ);
+ if (mld->nvm_data->bands[NL80211_BAND_5GHZ].n_channels)
+ hw->wiphy->nan_supported_bands |=
+ BIT(NL80211_BAND_5GHZ);
+
+ hw->wiphy->nan_capa.flags = WIPHY_NAN_FLAGS_CONFIGURABLE_SYNC |
+ WIPHY_NAN_FLAGS_USERSPACE_DE;
+
+ hw->wiphy->nan_capa.op_mode = NAN_OP_MODE_PHY_MODE_MASK |
+ NAN_OP_MODE_80P80MHZ |
+ NAN_OP_MODE_160MHZ;
+
+ /* Support 2 antenna's for Tx and Rx */
+ hw->wiphy->nan_capa.n_antennas = 0x22;
+
+ /* Maximal channel switch time is 4 msec */
+ hw->wiphy->nan_capa.max_channel_switch_time = 4;
+ hw->wiphy->nan_capa.dev_capabilities =
+ NAN_DEV_CAPA_EXT_KEY_ID_SUPPORTED |
+ NAN_DEV_CAPA_NDPE_SUPPORTED;
+ } else {
+ wiphy->iface_combinations = iwl_mld_iface_combinations;
+ /* Do not include NAN combinations */
+ wiphy->n_iface_combinations =
+ ARRAY_SIZE(iwl_mld_iface_combinations) - 2;
+ }
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_DFS_CONCURRENT);
@@ -318,6 +377,8 @@ static void iwl_mac_hw_set_wiphy(struct iwl_mld *mld)
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER);
+ wiphy_ext_feature_set(wiphy,
+ NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SPP_AMSDU_SUPPORT);
if (fw_has_capa(ucode_capa, IWL_UCODE_TLV_CAPA_PROTECTED_TWT))
@@ -616,10 +677,11 @@ int iwl_mld_mac80211_add_interface(struct ieee80211_hw *hw,
* Add the default link, but not if this is an MLD vif as that implies
* the HW is restarting and it will be configured by change_vif_links.
*/
- if (!ieee80211_vif_is_mld(vif))
+ if (vif->type != NL80211_IFTYPE_NAN && !ieee80211_vif_is_mld(vif)) {
ret = iwl_mld_add_link(mld, &vif->bss_conf);
- if (ret)
- goto err;
+ if (ret)
+ goto err;
+ }
if (vif->type == NL80211_IFTYPE_STATION) {
vif->driver_flags |= IEEE80211_VIF_REMOVE_AP_AFTER_DISASSOC;
@@ -647,6 +709,9 @@ int iwl_mld_mac80211_add_interface(struct ieee80211_hw *hw,
if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
mld->p2p_device_vif = vif;
+ if (vif->type == NL80211_IFTYPE_NAN)
+ mld->nan_device_vif = vif;
+
return 0;
err:
@@ -674,7 +739,10 @@ void iwl_mld_mac80211_remove_interface(struct ieee80211_hw *hw,
if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
mld->p2p_device_vif = NULL;
- iwl_mld_remove_link(mld, &vif->bss_conf);
+ if (vif->type == NL80211_IFTYPE_NAN)
+ mld->nan_device_vif = NULL;
+ else
+ iwl_mld_remove_link(mld, &vif->bss_conf);
#ifdef CONFIG_IWLWIFI_DEBUGFS
debugfs_remove(iwl_mld_vif_from_mac80211(vif)->dbgfs_slink);
@@ -984,7 +1052,9 @@ int iwl_mld_assign_vif_chanctx(struct ieee80211_hw *hw,
{
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
struct iwl_mld_link *mld_link = iwl_mld_link_from_mac80211(link);
- unsigned int n_active = iwl_mld_count_active_links(mld, vif);
+ struct iwl_mld_link *temp_mld_link;
+ struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
+ u16 final_active_links = 0;
int ret;
lockdep_assert_wiphy(mld->wiphy);
@@ -992,10 +1062,7 @@ int iwl_mld_assign_vif_chanctx(struct ieee80211_hw *hw,
if (WARN_ON(!mld_link))
return -EINVAL;
- /* if the assigned one was not counted yet, count it now */
if (!rcu_access_pointer(mld_link->chan_ctx)) {
- n_active++;
-
/* Track addition of non-BSS link */
if (ieee80211_vif_type_p2p(vif) != NL80211_IFTYPE_STATION) {
ret = iwl_mld_emlsr_check_non_bss_block(mld, 1);
@@ -1016,17 +1083,25 @@ int iwl_mld_assign_vif_chanctx(struct ieee80211_hw *hw,
rcu_assign_pointer(mld_link->chan_ctx, ctx);
- if (n_active > 1) {
- struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
+ /* We cannot rely on vif->active_links at this stage as it contains
+ * both the removed links and the newly added links.
+ * Therefore, we create our own bitmap of the final active links,
+ * which does not include the removed links.
+ */
+ for_each_mld_vif_valid_link(mld_vif, temp_mld_link) {
+ if (rcu_access_pointer(temp_mld_link->chan_ctx))
+ final_active_links |= BIT(link_id);
+ }
+ if (hweight16(final_active_links) > 1) {
/* Indicate to mac80211 that EML is enabled */
vif->driver_flags |= IEEE80211_VIF_EML_ACTIVE;
mld_vif->emlsr.last_entry_ts = jiffies;
- if (vif->active_links & BIT(mld_vif->emlsr.selected_links))
+ if (final_active_links == mld_vif->emlsr.selected_links)
mld_vif->emlsr.primary = mld_vif->emlsr.selected_primary;
else
- mld_vif->emlsr.primary = __ffs(vif->active_links);
+ mld_vif->emlsr.primary = __ffs(final_active_links);
iwl_dbg_tlv_time_point(&mld->fwrt, IWL_FW_INI_TIME_ESR_LINK_UP,
NULL);
@@ -1506,6 +1581,9 @@ iwl_mld_mac80211_conf_tx(struct ieee80211_hw *hw,
lockdep_assert_wiphy(mld->wiphy);
+ if (vif->type == NL80211_IFTYPE_NAN)
+ return 0;
+
link = iwl_mld_link_dereference_check(mld_vif, link_id);
if (!link)
return -EINVAL;
@@ -1706,6 +1784,9 @@ static int iwl_mld_move_sta_state_up(struct iwl_mld *mld,
/* Ensure any block due to a non-BSS link is synced */
iwl_mld_emlsr_check_non_bss_block(mld, 0);
+ /* Ensure NAN block is synced */
+ iwl_mld_emlsr_check_nan_block(mld, vif);
+
/* Block EMLSR until a certain throughput it reached */
if (!mld->fw_status.in_hw_restart &&
IWL_MLD_ENTER_EMLSR_TPT_THRESH > 0)
@@ -2701,4 +2782,7 @@ const struct ieee80211_ops iwl_mld_hw_ops = {
.set_hw_timestamp = iwl_mld_set_hw_timestamp,
.start_pmsr = iwl_mld_start_pmsr,
.can_neg_ttlm = iwl_mld_can_neg_ttlm,
+ .start_nan = iwl_mld_start_nan,
+ .stop_nan = iwl_mld_stop_nan,
+ .nan_change_conf = iwl_mld_nan_change_config,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mld.c b/drivers/net/wireless/intel/iwlwifi/mld/mld.c
index 8a4c96385640..495e9d8f3af6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mld.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mld.c
@@ -234,6 +234,9 @@ static const struct iwl_hcmd_names iwl_mld_mac_conf_names[] = {
HCMD_NAME(AUX_STA_CMD),
HCMD_NAME(STA_REMOVE_CMD),
HCMD_NAME(ROC_CMD),
+ HCMD_NAME(NAN_CFG_CMD),
+ HCMD_NAME(NAN_DW_END_NOTIF),
+ HCMD_NAME(NAN_JOINED_CLUSTER_NOTIF),
HCMD_NAME(MISSED_BEACONS_NOTIF),
HCMD_NAME(EMLSR_TRANS_FAIL_NOTIF),
HCMD_NAME(ROC_NOTIF),
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mld.h b/drivers/net/wireless/intel/iwlwifi/mld/mld.h
index 22efe8e10f53..66c7a7d31409 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mld.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mld.h
@@ -35,6 +35,7 @@
#include "ptp.h"
#include "time_sync.h"
#include "ftm-initiator.h"
+#include "nan.h"
/**
* DOC: Introduction
@@ -199,6 +200,7 @@
* @ptp_data: data of the PTP clock
* @time_sync: time sync data.
* @ftm_initiator: FTM initiator data
+ * @nan_device_vif: points to the NAN device vif if exists
*/
struct iwl_mld {
/* Add here fields that need clean up on restart */
@@ -228,6 +230,7 @@ struct iwl_mld {
#endif /* CONFIG_PM_SLEEP */
struct ieee80211_vif *p2p_device_vif;
bool bt_is_active;
+ struct ieee80211_vif *nan_device_vif;
);
struct ieee80211_link_sta __rcu *fw_id_to_link_sta[IWL_STATION_COUNT_MAX];
/* And here fields that survive a fw restart */
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c
index c6b151f26921..f842f5183223 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c
@@ -12,7 +12,8 @@
HOW(ROC) \
HOW(NON_BSS) \
HOW(TMP_NON_BSS) \
- HOW(TPT)
+ HOW(TPT) \
+ HOW(NAN)
static const char *
iwl_mld_get_emlsr_blocked_string(enum iwl_mld_emlsr_blocked blocked)
@@ -451,29 +452,49 @@ static void iwl_mld_count_non_bss_links(void *_data, u8 *mac,
struct iwl_mld_update_emlsr_block_data {
bool block;
+ enum iwl_mld_emlsr_blocked reason;
int result;
};
static void
-iwl_mld_vif_iter_update_emlsr_non_bss_block(void *_data, u8 *mac,
- struct ieee80211_vif *vif)
+iwl_mld_vif_iter_update_emlsr_block(void *_data, u8 *mac,
+ struct ieee80211_vif *vif)
{
struct iwl_mld_update_emlsr_block_data *data = _data;
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
int ret;
+ if (!iwl_mld_vif_has_emlsr_cap(vif))
+ return;
+
if (data->block) {
ret = iwl_mld_block_emlsr_sync(mld_vif->mld, vif,
- IWL_MLD_EMLSR_BLOCKED_NON_BSS,
+ data->reason,
iwl_mld_get_primary_link(vif));
if (ret)
data->result = ret;
} else {
iwl_mld_unblock_emlsr(mld_vif->mld, vif,
- IWL_MLD_EMLSR_BLOCKED_NON_BSS);
+ data->reason);
}
}
+int iwl_mld_update_emlsr_block(struct iwl_mld *mld, bool block,
+ enum iwl_mld_emlsr_blocked reason)
+{
+ struct iwl_mld_update_emlsr_block_data block_data = {
+ .block = block,
+ .reason = reason,
+ };
+
+ ieee80211_iterate_active_interfaces_mtx(mld->hw,
+ IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mld_vif_iter_update_emlsr_block,
+ &block_data);
+
+ return block_data.result;
+}
+
int iwl_mld_emlsr_check_non_bss_block(struct iwl_mld *mld,
int pending_link_changes)
{
@@ -481,7 +502,6 @@ int iwl_mld_emlsr_check_non_bss_block(struct iwl_mld *mld,
* block EMLSR on the bss vif. Upon deactivation, check if this link
* was the last non-station link active, and if so unblock the bss vif
*/
- struct iwl_mld_update_emlsr_block_data block_data = {};
int count = pending_link_changes;
/* No need to count if we are activating a non-BSS link */
@@ -495,14 +515,8 @@ int iwl_mld_emlsr_check_non_bss_block(struct iwl_mld *mld,
* We could skip updating it if the block change did not change (and
* pending_link_changes is non-zero).
*/
- block_data.block = !!count;
-
- ieee80211_iterate_active_interfaces_mtx(mld->hw,
- IEEE80211_IFACE_ITER_NORMAL,
- iwl_mld_vif_iter_update_emlsr_non_bss_block,
- &block_data);
-
- return block_data.result;
+ return iwl_mld_update_emlsr_block(mld, !!count,
+ IWL_MLD_EMLSR_BLOCKED_NON_BSS);
}
#define EMLSR_SEC_LINK_MIN_PERC 10
@@ -844,9 +858,9 @@ iwl_mld_emlsr_pair_state(struct ieee80211_vif *vif,
if (c_low->chan->center_freq > c_high->chan->center_freq)
swap(c_low, c_high);
- c_low_upper_edge = c_low->chan->center_freq +
+ c_low_upper_edge = c_low->center_freq1 +
cfg80211_chandef_get_width(c_low) / 2;
- c_high_lower_edge = c_high->chan->center_freq -
+ c_high_lower_edge = c_high->center_freq1 -
cfg80211_chandef_get_width(c_high) / 2;
if (a->chandef->chan->band == NL80211_BAND_5GHZ &&
@@ -1197,3 +1211,16 @@ void iwl_mld_stop_ignoring_tpt_updates(struct iwl_mld *mld)
iwl_mld_ignore_tpt_iter,
&start);
}
+
+int iwl_mld_emlsr_check_nan_block(struct iwl_mld *mld, struct ieee80211_vif *vif)
+{
+ if (mld->nan_device_vif &&
+ ieee80211_vif_nan_started(mld->nan_device_vif))
+ return iwl_mld_block_emlsr_sync(mld, vif,
+ IWL_MLD_EMLSR_BLOCKED_NAN,
+ iwl_mld_get_primary_link(vif));
+
+ iwl_mld_unblock_emlsr(mld, vif, IWL_MLD_EMLSR_BLOCKED_NAN);
+
+ return 0;
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mlo.h b/drivers/net/wireless/intel/iwlwifi/mld/mlo.h
index d936589fe39d..ccc3a7afa095 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mlo.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mlo.h
@@ -150,6 +150,11 @@ void iwl_mld_emlsr_check_chan_load(struct ieee80211_hw *hw,
*/
void iwl_mld_retry_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif);
+int iwl_mld_emlsr_check_nan_block(struct iwl_mld *mld, struct ieee80211_vif *vif);
+
+int iwl_mld_update_emlsr_block(struct iwl_mld *mld, bool block,
+ enum iwl_mld_emlsr_blocked reason);
+
struct iwl_mld_link_sel_data {
u8 link_id;
const struct cfg80211_chan_def *chandef;
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/nan.c b/drivers/net/wireless/intel/iwlwifi/mld/nan.c
new file mode 100644
index 000000000000..2dbd3d58b0c6
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/mld/nan.c
@@ -0,0 +1,299 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (C) 2025 Intel Corporation
+ */
+
+#include "mld.h"
+#include "iface.h"
+#include "mlo.h"
+#include "fw/api/mac-cfg.h"
+
+#define IWL_NAN_DISOVERY_BEACON_INTERNVAL_TU 512
+#define IWL_NAN_RSSI_CLOSE 55
+#define IWL_NAN_RSSI_MIDDLE 70
+
+bool iwl_mld_nan_supported(struct iwl_mld *mld)
+{
+ return fw_has_capa(&mld->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_NAN_SYNC_SUPPORT);
+}
+
+static int iwl_mld_nan_send_config_cmd(struct iwl_mld *mld,
+ struct iwl_nan_config_cmd *cmd,
+ u8 *beacon_data, size_t beacon_data_len)
+{
+ struct iwl_host_cmd hcmd = {
+ .id = WIDE_ID(MAC_CONF_GROUP, NAN_CFG_CMD),
+ };
+
+ hcmd.len[0] = sizeof(*cmd);
+ hcmd.data[0] = cmd;
+
+ if (beacon_data_len) {
+ hcmd.len[1] = beacon_data_len;
+ hcmd.data[1] = beacon_data;
+ hcmd.dataflags[1] = IWL_HCMD_DFL_DUP;
+ }
+
+ return iwl_mld_send_cmd(mld, &hcmd);
+}
+
+static int iwl_mld_nan_config(struct iwl_mld *mld,
+ struct ieee80211_vif *vif,
+ struct cfg80211_nan_conf *conf,
+ enum iwl_ctxt_action action)
+{
+ struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
+ struct iwl_nan_config_cmd cmd = {
+ .action = cpu_to_le32(action),
+ };
+ u8 *data __free(kfree) = NULL;
+
+ lockdep_assert_wiphy(mld->wiphy);
+
+ ether_addr_copy(cmd.nmi_addr, vif->addr);
+ cmd.master_pref = conf->master_pref;
+
+ if (conf->cluster_id)
+ memcpy(cmd.cluster_id, conf->cluster_id + 4,
+ sizeof(cmd.cluster_id));
+
+ cmd.scan_period = conf->scan_period < 255 ? conf->scan_period : 255;
+ cmd.dwell_time =
+ conf->scan_dwell_time < 255 ? conf->scan_dwell_time : 255;
+
+ if (conf->discovery_beacon_interval)
+ cmd.discovery_beacon_interval =
+ cpu_to_le32(conf->discovery_beacon_interval);
+ else
+ cmd.discovery_beacon_interval =
+ cpu_to_le32(IWL_NAN_DISOVERY_BEACON_INTERNVAL_TU);
+
+ if (conf->enable_dw_notification)
+ cmd.flags = IWL_NAN_FLAG_DW_END_NOTIF_ENABLED;
+
+ /* 2 GHz band must be supported */
+ cmd.band_config[IWL_NAN_BAND_2GHZ].rssi_close =
+ abs(conf->band_cfgs[NL80211_BAND_2GHZ].rssi_close);
+ cmd.band_config[IWL_NAN_BAND_2GHZ].rssi_middle =
+ abs(conf->band_cfgs[NL80211_BAND_2GHZ].rssi_middle);
+ cmd.band_config[IWL_NAN_BAND_2GHZ].dw_interval =
+ conf->band_cfgs[NL80211_BAND_2GHZ].awake_dw_interval;
+
+ /* 5 GHz band operation is optional. Configure its operation if
+ * supported. Note that conf->bands might be zero, so we need to check
+ * the channel pointer, not the band mask.
+ */
+ if (conf->band_cfgs[NL80211_BAND_5GHZ].chan) {
+ cmd.hb_channel =
+ conf->band_cfgs[NL80211_BAND_5GHZ].chan->hw_value;
+
+ cmd.band_config[IWL_NAN_BAND_5GHZ].rssi_close =
+ abs(conf->band_cfgs[NL80211_BAND_5GHZ].rssi_close);
+ cmd.band_config[IWL_NAN_BAND_5GHZ].rssi_middle =
+ abs(conf->band_cfgs[NL80211_BAND_5GHZ].rssi_middle);
+ cmd.band_config[IWL_NAN_BAND_5GHZ].dw_interval =
+ conf->band_cfgs[NL80211_BAND_5GHZ].awake_dw_interval;
+ }
+
+ if (conf->extra_nan_attrs_len || conf->vendor_elems_len) {
+ data = kmalloc(conf->extra_nan_attrs_len +
+ conf->vendor_elems_len, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ cmd.nan_attr_len = cpu_to_le32(conf->extra_nan_attrs_len);
+ cmd.nan_vendor_elems_len = cpu_to_le32(conf->vendor_elems_len);
+
+ if (conf->extra_nan_attrs_len)
+ memcpy(data, conf->extra_nan_attrs,
+ conf->extra_nan_attrs_len);
+
+ if (conf->vendor_elems_len)
+ memcpy(data + conf->extra_nan_attrs_len,
+ conf->vendor_elems,
+ conf->vendor_elems_len);
+ }
+
+ cmd.sta_id = mld_vif->aux_sta.sta_id;
+ return iwl_mld_nan_send_config_cmd(mld, &cmd, data,
+ conf->extra_nan_attrs_len +
+ conf->vendor_elems_len);
+}
+
+int iwl_mld_start_nan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct cfg80211_nan_conf *conf)
+{
+ struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
+ struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
+ struct iwl_mld_int_sta *aux_sta = &mld_vif->aux_sta;
+ int ret;
+
+ IWL_DEBUG_MAC80211(mld, "NAN: start: bands=0x%x\n", conf->bands);
+
+ ret = iwl_mld_update_emlsr_block(mld, true, IWL_MLD_EMLSR_BLOCKED_NAN);
+ if (ret)
+ return ret;
+
+ ret = iwl_mld_add_aux_sta(mld, aux_sta);
+ if (ret)
+ goto unblock_emlsr;
+
+ ret = iwl_mld_nan_config(mld, vif, conf, FW_CTXT_ACTION_ADD);
+ if (ret) {
+ IWL_ERR(mld, "Failed to start NAN. ret=%d\n", ret);
+ goto remove_aux;
+ }
+ return 0;
+
+remove_aux:
+ iwl_mld_remove_aux_sta(mld, vif);
+unblock_emlsr:
+ iwl_mld_update_emlsr_block(mld, false, IWL_MLD_EMLSR_BLOCKED_NAN);
+
+ return ret;
+}
+
+int iwl_mld_nan_change_config(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_nan_conf *conf,
+ u32 changes)
+{
+ struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
+
+ IWL_DEBUG_MAC80211(mld, "NAN: change: changes=0x%x, bands=0x%x\n",
+ changes, conf->bands);
+
+ /* Note that we do not use 'changes' as the FW always expects the
+ * complete configuration, and mac80211 always provides the complete
+ * configuration.
+ */
+ return iwl_mld_nan_config(mld, vif, conf, FW_CTXT_ACTION_MODIFY);
+}
+
+int iwl_mld_stop_nan(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
+ struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
+ struct iwl_nan_config_cmd cmd = {
+ .action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
+ };
+ int ret;
+
+ lockdep_assert_wiphy(mld->wiphy);
+
+ ret = iwl_mld_send_cmd_pdu(mld,
+ WIDE_ID(MAC_CONF_GROUP, NAN_CFG_CMD),
+ &cmd);
+ if (ret)
+ IWL_ERR(mld, "NAN: Failed to stop NAN. ret=%d\n", ret);
+
+ /* assume that higher layer guarantees that no additional frames are
+ * added before calling this callback
+ */
+ iwl_mld_flush_link_sta_txqs(mld, mld_vif->aux_sta.sta_id);
+ iwl_mld_remove_aux_sta(mld, vif);
+
+ /* cancel based on object type being NAN, as the NAN objects do
+ * not have a unique identifier associated with them
+ */
+ iwl_mld_cancel_notifications_of_object(mld,
+ IWL_MLD_OBJECT_TYPE_NAN,
+ 0);
+
+ iwl_mld_update_emlsr_block(mld, false, IWL_MLD_EMLSR_BLOCKED_NAN);
+
+ return 0;
+}
+
+void iwl_mld_handle_nan_cluster_notif(struct iwl_mld *mld,
+ struct iwl_rx_packet *pkt)
+{
+ struct iwl_nan_cluster_notif *notif = (void *)pkt->data;
+ struct wireless_dev *wdev = mld->nan_device_vif ?
+ ieee80211_vif_to_wdev(mld->nan_device_vif) : NULL;
+ bool new_cluster = !!(notif->flags &
+ IWL_NAN_CLUSTER_NOTIF_FLAG_NEW_CLUSTER);
+ u8 cluster_id[ETH_ALEN] = {
+ 0x50, 0x6f, 0x9a, 0x01,
+ notif->cluster_id[0], notif->cluster_id[1]
+ };
+
+ IWL_DEBUG_INFO(mld,
+ "NAN: cluster event: cluster_id=%pM, flags=0x%x\n",
+ cluster_id, notif->flags);
+
+ if (IWL_FW_CHECK(mld, !wdev, "NAN: cluster event without wdev\n"))
+ return;
+
+ if (IWL_FW_CHECK(mld, !ieee80211_vif_nan_started(mld->nan_device_vif),
+ "NAN: cluster event without NAN started\n"))
+ return;
+
+ cfg80211_nan_cluster_joined(wdev, cluster_id, new_cluster, GFP_KERNEL);
+}
+
+bool iwl_mld_cancel_nan_cluster_notif(struct iwl_mld *mld,
+ struct iwl_rx_packet *pkt,
+ u32 obj_id)
+{
+ return true;
+}
+
+bool iwl_mld_cancel_nan_dw_end_notif(struct iwl_mld *mld,
+ struct iwl_rx_packet *pkt,
+ u32 obj_id)
+{
+ return true;
+}
+
+void iwl_mld_handle_nan_dw_end_notif(struct iwl_mld *mld,
+ struct iwl_rx_packet *pkt)
+{
+ struct iwl_nan_dw_end_notif *notif = (void *)pkt->data;
+ struct iwl_mld_vif *mld_vif = mld->nan_device_vif ?
+ iwl_mld_vif_from_mac80211(mld->nan_device_vif) :
+ NULL;
+ struct wireless_dev *wdev;
+ struct ieee80211_channel *chan;
+
+ IWL_INFO(mld, "NAN: DW end: band=%u\n", notif->band);
+
+ if (IWL_FW_CHECK(mld, !mld_vif, "NAN: DW end without mld_vif\n"))
+ return;
+
+ if (IWL_FW_CHECK(mld, !ieee80211_vif_nan_started(mld->nan_device_vif),
+ "NAN: DW end without NAN started\n"))
+ return;
+
+ if (WARN_ON(mld_vif->aux_sta.sta_id == IWL_INVALID_STA))
+ return;
+
+ IWL_DEBUG_INFO(mld, "NAN: flush queues for aux sta=%u\n",
+ mld_vif->aux_sta.sta_id);
+
+ iwl_mld_flush_link_sta_txqs(mld, mld_vif->aux_sta.sta_id);
+
+ /* TODO: currently the notification specified the band on which the DW
+ * ended. Need to change that to the actual channel on which the next DW
+ * will be started.
+ */
+ switch (notif->band) {
+ case IWL_NAN_BAND_2GHZ:
+ chan = ieee80211_get_channel(mld->wiphy, 2437);
+ break;
+ case IWL_NAN_BAND_5GHZ:
+ /* TODO: use the actual channel */
+ chan = ieee80211_get_channel(mld->wiphy, 5745);
+ break;
+ default:
+ IWL_FW_CHECK(mld, false,
+ "NAN: Invalid band %u in DW end notif\n",
+ notif->band);
+ return;
+ }
+
+ wdev = ieee80211_vif_to_wdev(mld->nan_device_vif);
+ cfg80211_next_nan_dw_notif(wdev, chan, GFP_KERNEL);
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/nan.h b/drivers/net/wireless/intel/iwlwifi/mld/nan.h
new file mode 100644
index 000000000000..c9c83d1012f0
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/mld/nan.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/*
+ * Copyright (C) 2025 Intel Corporation
+ */
+
+#include <net/cfg80211.h>
+#include <linux/etherdevice.h>
+
+bool iwl_mld_nan_supported(struct iwl_mld *mld);
+int iwl_mld_start_nan(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_nan_conf *conf);
+int iwl_mld_nan_change_config(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_nan_conf *conf,
+ u32 changes);
+int iwl_mld_stop_nan(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+void iwl_mld_handle_nan_cluster_notif(struct iwl_mld *mld,
+ struct iwl_rx_packet *pkt);
+void iwl_mld_handle_nan_dw_end_notif(struct iwl_mld *mld,
+ struct iwl_rx_packet *pkt);
+bool iwl_mld_cancel_nan_cluster_notif(struct iwl_mld *mld,
+ struct iwl_rx_packet *pkt,
+ u32 obj_id);
+bool iwl_mld_cancel_nan_dw_end_notif(struct iwl_mld *mld,
+ struct iwl_rx_packet *pkt,
+ u32 obj_id);
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/notif.c b/drivers/net/wireless/intel/iwlwifi/mld/notif.c
index 4cf3920b005f..35356b244c0a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/notif.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/notif.c
@@ -111,6 +111,9 @@ static bool iwl_mld_cancel_##name##_notif(struct iwl_mld *mld, \
#define RX_HANDLER_OF_FTM_REQ(_grp, _cmd, _name) \
RX_HANDLER_OF_OBJ(_grp, _cmd, _name, FTM_REQ)
+#define RX_HANDLER_OF_NAN(_grp, _cmd, _name) \
+ RX_HANDLER_OF_OBJ(_grp, _cmd, _name, NAN)
+
static void iwl_mld_handle_mfuart_notif(struct iwl_mld *mld,
struct iwl_rx_packet *pkt)
{
@@ -344,6 +347,8 @@ CMD_VERSIONS(time_sync_confirm_notif,
CMD_VER_ENTRY(1, iwl_time_msmt_cfm_notify))
CMD_VERSIONS(ftm_resp_notif, CMD_VER_ENTRY(10, iwl_tof_range_rsp_ntfy))
CMD_VERSIONS(beacon_filter_notif, CMD_VER_ENTRY(2, iwl_beacon_filter_notif))
+CMD_VERSIONS(nan_cluster_notif, CMD_VER_ENTRY(1, iwl_nan_cluster_notif))
+CMD_VERSIONS(nan_dw_end_notif, CMD_VER_ENTRY(1, iwl_nan_dw_end_notif))
DEFINE_SIMPLE_CANCELLATION(session_prot, iwl_session_prot_notif, mac_link_id)
DEFINE_SIMPLE_CANCELLATION(tlc, iwl_tlc_update_notif, sta_id)
@@ -459,6 +464,10 @@ const struct iwl_rx_handler iwl_mld_rx_handlers[] = {
beacon_filter_notif)
RX_HANDLER_OF_FTM_REQ(LOCATION_GROUP, TOF_RANGE_RESPONSE_NOTIF,
ftm_resp_notif)
+ RX_HANDLER_OF_NAN(MAC_CONF_GROUP, NAN_JOINED_CLUSTER_NOTIF,
+ nan_cluster_notif)
+ RX_HANDLER_OF_NAN(MAC_CONF_GROUP, NAN_DW_END_NOTIF,
+ nan_dw_end_notif)
};
EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_rx_handlers);
@@ -531,6 +540,8 @@ static void iwl_mld_rx_notif(struct iwl_mld *mld,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_rx_packet *pkt)
{
+ union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt };
+
for (int i = 0; i < ARRAY_SIZE(iwl_mld_rx_handlers); i++) {
const struct iwl_rx_handler *rx_h = &iwl_mld_rx_handlers[i];
struct iwl_async_handler_entry *entry;
@@ -571,6 +582,8 @@ static void iwl_mld_rx_notif(struct iwl_mld *mld,
}
iwl_notification_wait_notify(&mld->notif_wait, pkt);
+ iwl_dbg_tlv_time_point(&mld->fwrt,
+ IWL_FW_INI_TIME_POINT_FW_RSP_OR_NOTIF, &tp_data);
}
void iwl_mld_rx(struct iwl_op_mode *op_mode, struct napi_struct *napi,
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/notif.h b/drivers/net/wireless/intel/iwlwifi/mld/notif.h
index adcdd9dec192..373c1a90d98e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/notif.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/notif.h
@@ -25,6 +25,7 @@ enum iwl_mld_object_type {
IWL_MLD_OBJECT_TYPE_ROC,
IWL_MLD_OBJECT_TYPE_SCAN,
IWL_MLD_OBJECT_TYPE_FTM_REQ,
+ IWL_MLD_OBJECT_TYPE_NAN,
};
void iwl_mld_cancel_notifications_of_object(struct iwl_mld *mld,
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/power.c b/drivers/net/wireless/intel/iwlwifi/mld/power.c
index f664b277adf7..c3318e84f4a2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/power.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/power.c
@@ -328,6 +328,33 @@ iwl_mld_tpe_sta_cmd_data(struct iwl_txpower_constraints_cmd *cmd,
link->tpe.max_reg_client[0].power[i]);
}
+static int
+iwl_mld_set_ap_power_type(struct iwl_txpower_constraints_cmd *cmd,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link)
+{
+ if (vif->type == NL80211_IFTYPE_AP) {
+ cmd->ap_type = cpu_to_le16(IWL_6GHZ_AP_TYPE_VLP);
+ return 0;
+ }
+
+ switch (link->power_type) {
+ case IEEE80211_REG_LPI_AP:
+ cmd->ap_type = cpu_to_le16(IWL_6GHZ_AP_TYPE_LPI);
+ break;
+ case IEEE80211_REG_SP_AP:
+ cmd->ap_type = cpu_to_le16(IWL_6GHZ_AP_TYPE_SP);
+ break;
+ case IEEE80211_REG_VLP_AP:
+ cmd->ap_type = cpu_to_le16(IWL_6GHZ_AP_TYPE_VLP);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
void
iwl_mld_send_ap_tx_power_constraint_cmd(struct iwl_mld *mld,
struct ieee80211_vif *vif,
@@ -349,15 +376,13 @@ iwl_mld_send_ap_tx_power_constraint_cmd(struct iwl_mld *mld,
memset(cmd.psd_pwr, DEFAULT_TPE_TX_POWER, sizeof(cmd.psd_pwr));
memset(cmd.eirp_pwr, DEFAULT_TPE_TX_POWER, sizeof(cmd.eirp_pwr));
- if (vif->type == NL80211_IFTYPE_AP) {
- cmd.ap_type = cpu_to_le16(IWL_6GHZ_AP_TYPE_VLP);
- } else if (link->power_type == IEEE80211_REG_UNSET_AP) {
+ if (iwl_mld_set_ap_power_type(&cmd, vif, link))
return;
- } else {
- cmd.ap_type = cpu_to_le16(link->power_type - 1);
+
+ if (vif->type != NL80211_IFTYPE_AP)
iwl_mld_tpe_sta_cmd_data(&cmd, link);
- }
+ IWL_DEBUG_POWER(mld, "AP power type: %d\n", le16_to_cpu(cmd.ap_type));
ret = iwl_mld_send_cmd_pdu(mld,
WIDE_ID(PHY_OPS_GROUP,
AP_TX_POWER_CONSTRAINTS_CMD),
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c
index 40571125b3ab..6ab5a3410353 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c
@@ -165,8 +165,8 @@ static int iwl_mld_ppag_send_cmd(struct iwl_mld *mld)
{
struct iwl_fw_runtime *fwrt = &mld->fwrt;
union iwl_ppag_table_cmd cmd = {
- .v7.ppag_config_info.table_source = fwrt->ppag_bios_source,
- .v7.ppag_config_info.table_revision = fwrt->ppag_bios_rev,
+ .v7.ppag_config_info.hdr.table_source = fwrt->ppag_bios_source,
+ .v7.ppag_config_info.hdr.table_revision = fwrt->ppag_bios_rev,
.v7.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags),
};
int ret;
@@ -206,11 +206,27 @@ int iwl_mld_init_ppag(struct iwl_mld *mld)
return iwl_mld_ppag_send_cmd(mld);
}
+static __le32 iwl_mld_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt)
+{
+ int ret;
+ u32 val;
+
+ ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_DISABLE_SRD, &val);
+ if (!ret) {
+ if (val == DSM_VALUE_SRD_PASSIVE)
+ return cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_PASSIVE_MSK);
+ else if (val == DSM_VALUE_SRD_DISABLE)
+ return cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_DISABLED_MSK);
+ }
+
+ return 0;
+}
+
void iwl_mld_configure_lari(struct iwl_mld *mld)
{
struct iwl_fw_runtime *fwrt = &mld->fwrt;
struct iwl_lari_config_change_cmd cmd = {
- .config_bitmap = iwl_get_lari_config_bitmap(fwrt),
+ .config_bitmap = iwl_mld_get_lari_config_bitmap(fwrt),
};
bool has_raw_dsm_capa = fw_has_capa(&fwrt->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE);
@@ -265,6 +281,14 @@ void iwl_mld_configure_lari(struct iwl_mld *mld)
if (!ret)
cmd.oem_11be_allow_bitmap = cpu_to_le32(value);
+ ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_11BN, &value);
+ if (!ret)
+ cmd.oem_11bn_allow_bitmap = cpu_to_le32(value);
+
+ ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_UNII_9, &value);
+ if (!ret)
+ cmd.oem_unii9_enable = cpu_to_le32(value);
+
if (!cmd.config_bitmap &&
!cmd.oem_uhb_allow_bitmap &&
!cmd.oem_11ax_allow_bitmap &&
@@ -273,9 +297,14 @@ void iwl_mld_configure_lari(struct iwl_mld *mld)
!cmd.force_disable_channels_bitmap &&
!cmd.edt_bitmap &&
!cmd.oem_320mhz_allow_bitmap &&
- !cmd.oem_11be_allow_bitmap)
+ !cmd.oem_11be_allow_bitmap &&
+ !cmd.oem_11bn_allow_bitmap &&
+ !cmd.oem_unii9_enable)
return;
+ cmd.bios_hdr.table_source = fwrt->dsm_source;
+ cmd.bios_hdr.table_revision = fwrt->dsm_revision;
+
IWL_DEBUG_RADIO(mld,
"sending LARI_CONFIG_CHANGE, config_bitmap=0x%x, oem_11ax_allow_bitmap=0x%x\n",
le32_to_cpu(cmd.config_bitmap),
@@ -295,9 +324,28 @@ void iwl_mld_configure_lari(struct iwl_mld *mld)
IWL_DEBUG_RADIO(mld,
"sending LARI_CONFIG_CHANGE, oem_11be_allow_bitmap=0x%x\n",
le32_to_cpu(cmd.oem_11be_allow_bitmap));
-
- ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(REGULATORY_AND_NVM_GROUP,
- LARI_CONFIG_CHANGE), &cmd);
+ IWL_DEBUG_RADIO(mld,
+ "sending LARI_CONFIG_CHANGE, oem_11bn_allow_bitmap=0x%x\n",
+ le32_to_cpu(cmd.oem_11bn_allow_bitmap));
+ IWL_DEBUG_RADIO(mld,
+ "sending LARI_CONFIG_CHANGE, oem_unii9_enable=0x%x\n",
+ le32_to_cpu(cmd.oem_unii9_enable));
+
+ if (iwl_fw_lookup_cmd_ver(mld->fw,
+ WIDE_ID(REGULATORY_AND_NVM_GROUP,
+ LARI_CONFIG_CHANGE), 12) == 12) {
+ int cmd_size = offsetof(typeof(cmd), oem_11bn_allow_bitmap);
+
+ ret = iwl_mld_send_cmd_pdu(mld,
+ WIDE_ID(REGULATORY_AND_NVM_GROUP,
+ LARI_CONFIG_CHANGE),
+ &cmd, cmd_size);
+ } else {
+ ret = iwl_mld_send_cmd_pdu(mld,
+ WIDE_ID(REGULATORY_AND_NVM_GROUP,
+ LARI_CONFIG_CHANGE),
+ &cmd);
+ }
if (ret)
IWL_DEBUG_RADIO(mld,
"Failed to send LARI_CONFIG_CHANGE (%d)\n",
@@ -373,8 +421,8 @@ void iwl_mld_init_tas(struct iwl_mld *mld)
for (u8 i = 0; i < data.block_list_size; i++)
cmd.block_list_array[i] =
cpu_to_le16(data.block_list_array[i]);
- cmd.tas_config_info.table_source = data.table_source;
- cmd.tas_config_info.table_revision = data.table_revision;
+ cmd.tas_config_info.hdr.table_source = data.table_source;
+ cmd.tas_config_info.hdr.table_revision = data.table_revision;
cmd.tas_config_info.value = cpu_to_le32(data.tas_selection);
ret = iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd);
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/rx.c b/drivers/net/wireless/intel/iwlwifi/mld/rx.c
index 6a76e3fcb581..214dcfde2fb4 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/rx.c
@@ -208,6 +208,134 @@ static void iwl_mld_fill_signal(struct iwl_mld *mld, int link_id,
}
static void
+iwl_mld_decode_vht_phy_data(struct iwl_mld_rx_phy_data *phy_data,
+ struct ieee80211_radiotap_vht *vht,
+ struct ieee80211_rx_status *rx_status)
+{
+ bool stbc;
+
+ vht->known = cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH |
+ IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID |
+ IEEE80211_RADIOTAP_VHT_KNOWN_STBC |
+ IEEE80211_RADIOTAP_VHT_KNOWN_GI |
+ IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS |
+ IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM |
+ IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED);
+
+ switch (le32_get_bits(phy_data->ntfy->sigs.vht.a1,
+ OFDM_RX_FRAME_VHT_BANDWIDTH)) {
+ case 0:
+ vht->bandwidth = IEEE80211_RADIOTAP_VHT_BW_20;
+ break;
+ case 1:
+ vht->bandwidth = IEEE80211_RADIOTAP_VHT_BW_40;
+ break;
+ case 2:
+ vht->bandwidth = IEEE80211_RADIOTAP_VHT_BW_80;
+ break;
+ case 3:
+ vht->bandwidth = IEEE80211_RADIOTAP_VHT_BW_160;
+ break;
+ }
+
+ vht->group_id = le32_get_bits(phy_data->ntfy->sigs.vht.a1,
+ OFDM_RX_FRAME_VHT_GRP_ID);
+
+ stbc = le32_get_bits(phy_data->ntfy->sigs.vht.a1,
+ OFDM_RX_FRAME_VHT_STBC);
+ if (stbc)
+ vht->flags |= IEEE80211_RADIOTAP_VHT_FLAG_STBC;
+
+ if (le32_get_bits(phy_data->ntfy->sigs.vht.a2,
+ OFDM_RX_FRAME_VHT_SHORT_GI))
+ vht->flags |= IEEE80211_RADIOTAP_VHT_FLAG_SGI;
+
+ if (le32_get_bits(phy_data->ntfy->sigs.vht.a2,
+ OFDM_RX_FRAME_VHT_SHORT_GI_AMBIG))
+ vht->flags |= IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9;
+
+ if (le32_get_bits(phy_data->ntfy->sigs.vht.a2,
+ OFDM_RX_FRAME_VHT_CODING_EXTRA_SYM))
+ vht->flags |= IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM;
+
+ if (vht->group_id != 0 && vht->group_id != 63) {
+ /* MU frame */
+ int user = le32_get_bits(phy_data->ntfy->sigs.vht.a1,
+ OFDM_RX_FRAME_VHT_MU_MIMO_USER_POSITION);
+ int nsts;
+
+ /* Always beamformed */
+ vht->flags |= IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED;
+
+ /* No MCS information in the a1/a2 data for MU frames */
+ nsts = le32_get_bits(phy_data->ntfy->sigs.vht.a1,
+ OFDM_RX_FRAME_VHT_STS_USER0);
+ vht->mcs_nss[0] = (stbc ? nsts / 2 : nsts) | 0xf0;
+
+ nsts = le32_get_bits(phy_data->ntfy->sigs.vht.a1,
+ OFDM_RX_FRAME_VHT_MU_STS_USER1);
+ vht->mcs_nss[1] = (stbc ? nsts / 2 : nsts) | 0xf0;
+
+ nsts = le32_get_bits(phy_data->ntfy->sigs.vht.a1,
+ OFDM_RX_FRAME_VHT_MU_STS_USER2);
+ vht->mcs_nss[2] = (stbc ? nsts / 2 : nsts) | 0xf0;
+
+ nsts = le32_get_bits(phy_data->ntfy->sigs.vht.a1,
+ OFDM_RX_FRAME_VHT_MU_STS_USER3);
+ vht->mcs_nss[3] = (stbc ? nsts / 2 : nsts) | 0xf0;
+
+ /* Report current user MCS from rate_n_flags via rx_status */
+ vht->mcs_nss[user] &= 0x0f;
+ vht->mcs_nss[user] |= rx_status->rate_idx << 4;
+
+ /* Report LDPC for current user */
+ if (rx_status->enc_flags & RX_ENC_FLAG_LDPC)
+ vht->coding = 0x1 << user;
+ } else {
+ int nsts;
+
+ /* SU frame */
+ vht->known |= cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID);
+
+ if (le32_get_bits(phy_data->ntfy->sigs.vht.a2,
+ OFDM_RX_FRAME_VHT_BF_OR_MU_RESERVED))
+ vht->flags |= IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED;
+
+ vht->partial_aid =
+ cpu_to_le16(le32_get_bits(phy_data->ntfy->sigs.vht.a1,
+ OFDM_RX_FRAME_VHT_PARTIAL_AID_OR_MU_STS));
+
+ nsts = le32_get_bits(phy_data->ntfy->sigs.vht.a1,
+ OFDM_RX_FRAME_VHT_STS) + 1;
+ vht->mcs_nss[0] =
+ (stbc ? nsts / 2 : nsts) |
+ le32_get_bits(phy_data->ntfy->sigs.vht.a2,
+ OFDM_RX_FRAME_VHT_MCS_OR_MU_CODING) << 4;
+ vht->mcs_nss[1] = 0;
+ vht->mcs_nss[2] = 0;
+ vht->mcs_nss[3] = 0;
+
+ if (rx_status->enc_flags & RX_ENC_FLAG_LDPC)
+ vht->coding = 0x1;
+ }
+}
+
+static void iwl_mld_rx_vht(struct sk_buff *skb,
+ struct iwl_mld_rx_phy_data *phy_data)
+{
+ struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
+ struct ieee80211_radiotap_vht *vht;
+
+ if (likely(!phy_data->ntfy))
+ return;
+
+ vht = skb_put_zero(skb, sizeof(*vht));
+ rx_status->flag |= RX_FLAG_RADIOTAP_VHT;
+
+ iwl_mld_decode_vht_phy_data(phy_data, vht, rx_status);
+}
+
+static void
iwl_mld_he_set_ru_alloc(struct ieee80211_rx_status *rx_status,
struct ieee80211_radiotap_he *he,
u8 ru_with_p80)
@@ -268,11 +396,11 @@ iwl_mld_decode_he_mu(struct iwl_mld_rx_phy_data *phy_data,
{
u32 rate_n_flags = phy_data->rate_n_flags;
- he_mu->flags1 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.b,
- OFDM_RX_FRAME_HE_SIGB_DCM,
+ he_mu->flags1 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.a1,
+ OFDM_RX_FRAME_HE_DCM,
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM);
- he_mu->flags1 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.b,
- OFDM_RX_FRAME_HE_SIGB_MCS,
+ he_mu->flags1 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.a1,
+ OFDM_RX_FRAME_HE_MCS,
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS);
he_mu->flags2 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.a1,
OFDM_RX_FRAME_HE_PRMBL_PUNC_TYPE,
@@ -280,7 +408,7 @@ iwl_mld_decode_he_mu(struct iwl_mld_rx_phy_data *phy_data,
he_mu->flags2 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.a2,
OFDM_RX_FRAME_HE_MU_NUM_OF_SIGB_SYM_OR_USER_NUM,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS);
- he_mu->flags2 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.b,
+ he_mu->flags2 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.a2,
OFDM_RX_FRAME_HE_MU_SIGB_COMP,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP);
@@ -1377,6 +1505,10 @@ static void iwl_mld_rx_fill_status(struct iwl_mld *mld, int link_id,
iwl_mld_set_rx_rate(mld, phy_data, rx_status);
+ /* must be before HE data (radiotap field order) */
+ if (format == RATE_MCS_MOD_TYPE_VHT)
+ iwl_mld_rx_vht(skb, phy_data);
+
/* must be before L-SIG data (radiotap field order) */
if (format == RATE_MCS_MOD_TYPE_HE)
iwl_mld_rx_he(skb, phy_data);
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/scan.c b/drivers/net/wireless/intel/iwlwifi/mld/scan.c
index fd1022ddc912..16f48087a888 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/scan.c
@@ -1063,14 +1063,15 @@ static int
iwl_mld_scan_cmd_set_6ghz_chan_params(struct iwl_mld *mld,
struct iwl_mld_scan_params *params,
struct ieee80211_vif *vif,
- struct iwl_scan_req_params_v17 *scan_p,
- enum iwl_mld_scan_status scan_status)
+ struct iwl_scan_req_params_v17 *scan_p)
{
struct iwl_scan_channel_params_v7 *chan_p = &scan_p->channel_params;
struct iwl_scan_probe_params_v4 *probe_p = &scan_p->probe_params;
- chan_p->flags = iwl_mld_scan_get_cmd_gen_flags(mld, params, vif,
- scan_status);
+ /* Explicitly clear the flags since most of them are not
+ * relevant for 6 GHz scan.
+ */
+ chan_p->flags = 0;
chan_p->count = iwl_mld_scan_cfg_channels_6g(mld, params,
params->n_channels,
probe_p, chan_p,
@@ -1106,8 +1107,7 @@ iwl_mld_scan_cmd_set_chan_params(struct iwl_mld *mld,
if (params->scan_6ghz)
return iwl_mld_scan_cmd_set_6ghz_chan_params(mld, params,
- vif, scan_p,
- scan_status);
+ vif, scan_p);
/* relevant only for 2.4 GHz/5 GHz scan */
cp->flags = iwl_mld_scan_cmd_set_chan_flags(mld, params, vif,
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/sta.c b/drivers/net/wireless/intel/iwlwifi/mld/sta.c
index 61ecc33116cf..6056a306f7cb 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/sta.c
@@ -1163,7 +1163,8 @@ void iwl_mld_remove_aux_sta(struct iwl_mld *mld,
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
if (WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE &&
- vif->type != NL80211_IFTYPE_STATION))
+ vif->type != NL80211_IFTYPE_STATION &&
+ vif->type != NL80211_IFTYPE_NAN))
return;
iwl_mld_remove_internal_sta(mld, &mld_vif->aux_sta, false,
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tlc.c b/drivers/net/wireless/intel/iwlwifi/mld/tlc.c
index 0e172281b0c8..62a54c37a98c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tlc.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tlc.c
@@ -8,6 +8,7 @@
#include "tlc.h"
#include "hcmd.h"
#include "sta.h"
+#include "phy.h"
#include "fw/api/rs.h"
#include "fw/api/context.h"
@@ -447,11 +448,48 @@ iwl_mld_fill_supp_rates(struct iwl_mld *mld, struct ieee80211_vif *vif,
}
}
-static void iwl_mld_convert_tlc_cmd_to_v4(struct iwl_tlc_config_cmd *cmd,
- struct iwl_tlc_config_cmd_v4 *cmd_v4)
+static int iwl_mld_convert_tlc_cmd_to_v5(struct iwl_tlc_config_cmd *cmd,
+ struct iwl_tlc_config_cmd_v5 *cmd_v5)
{
+ if (WARN_ON_ONCE(hweight32(le32_to_cpu(cmd->sta_mask)) != 1))
+ return -EINVAL;
+
+ /* Convert sta_mask to sta_id */
+ cmd_v5->sta_id = __ffs(le32_to_cpu(cmd->sta_mask));
+
+ /* Copy all the rest */
+ cmd_v5->max_ch_width = cmd->max_ch_width;
+ cmd_v5->mode = cmd->mode;
+ cmd_v5->chains = cmd->chains;
+ cmd_v5->sgi_ch_width_supp = cmd->sgi_ch_width_supp;
+ cmd_v5->flags = cmd->flags;
+ cmd_v5->non_ht_rates = cmd->non_ht_rates;
+
+ BUILD_BUG_ON(sizeof(cmd_v5->ht_rates) != sizeof(cmd->ht_rates));
+ memcpy(cmd_v5->ht_rates, cmd->ht_rates, sizeof(cmd->ht_rates));
+
+ cmd_v5->max_mpdu_len = cmd->max_mpdu_len;
+ cmd_v5->max_tx_op = cmd->max_tx_op;
+
+ return 0;
+}
+
+static int iwl_mld_convert_tlc_cmd_to_v4(struct iwl_tlc_config_cmd *cmd,
+ struct iwl_tlc_config_cmd_v4 *cmd_v4)
+{
+ if (WARN_ON_ONCE(hweight32(le32_to_cpu(cmd->sta_mask)) != 1))
+ return -EINVAL;
+
+ /* Convert sta_mask to sta_id */
+ cmd_v4->sta_id = __ffs(le32_to_cpu(cmd->sta_mask));
+
/* Copy everything until ht_rates */
- memcpy(cmd_v4, cmd, offsetof(struct iwl_tlc_config_cmd, ht_rates));
+ cmd_v4->max_ch_width = cmd->max_ch_width;
+ cmd_v4->mode = cmd->mode;
+ cmd_v4->chains = cmd->chains;
+ cmd_v4->sgi_ch_width_supp = cmd->sgi_ch_width_supp;
+ cmd_v4->flags = cmd->flags;
+ cmd_v4->non_ht_rates = cmd->non_ht_rates;
/* Convert ht_rates from __le32 to __le16 */
BUILD_BUG_ON(ARRAY_SIZE(cmd_v4->ht_rates) != ARRAY_SIZE(cmd->ht_rates));
@@ -465,14 +503,17 @@ static void iwl_mld_convert_tlc_cmd_to_v4(struct iwl_tlc_config_cmd *cmd,
/* Copy the rest */
cmd_v4->max_mpdu_len = cmd->max_mpdu_len;
cmd_v4->max_tx_op = cmd->max_tx_op;
+
+ return 0;
}
static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld,
struct ieee80211_vif *vif,
struct ieee80211_link_sta *link_sta,
- enum nl80211_band band)
+ struct ieee80211_bss_conf *link)
{
struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(link_sta->sta);
+ enum nl80211_band band = link->chanreq.oper.chan->band;
struct ieee80211_supported_band *sband = mld->hw->wiphy->bands[band];
const struct ieee80211_sta_he_cap *own_he_cap =
ieee80211_get_he_iftype_cap_vif(sband, vif);
@@ -492,25 +533,44 @@ static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld,
int fw_sta_id = iwl_mld_fw_sta_id_from_link_sta(mld, link_sta);
u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, TLC_MNG_CONFIG_CMD);
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 0);
- struct iwl_tlc_config_cmd_v4 cmd_v4;
+ struct ieee80211_chanctx_conf *chan_ctx;
+ struct iwl_tlc_config_cmd_v5 cmd_v5 = {};
+ struct iwl_tlc_config_cmd_v4 cmd_v4 = {};
void *cmd_ptr;
u8 cmd_size;
+ u32 phy_id;
int ret;
if (fw_sta_id < 0)
return;
- cmd.sta_id = fw_sta_id;
+ cmd.sta_mask = cpu_to_le32(BIT(fw_sta_id));
+
+ chan_ctx = rcu_dereference_wiphy(mld->wiphy, link->chanctx_conf);
+ if (WARN_ON(!chan_ctx))
+ return;
+
+ phy_id = iwl_mld_phy_from_mac80211(chan_ctx)->fw_id;
+ cmd.phy_id = cpu_to_le32(phy_id);
iwl_mld_fill_supp_rates(mld, vif, link_sta, sband,
own_he_cap, own_eht_cap,
&cmd);
- if (cmd_ver == 5) {
+ if (cmd_ver == 6) {
cmd_ptr = &cmd;
cmd_size = sizeof(cmd);
+ } else if (cmd_ver == 5) {
+ /* TODO: remove support once FW moves to version 6 */
+ ret = iwl_mld_convert_tlc_cmd_to_v5(&cmd, &cmd_v5);
+ if (ret)
+ return;
+ cmd_ptr = &cmd_v5;
+ cmd_size = sizeof(cmd_v5);
} else if (cmd_ver == 4) {
- iwl_mld_convert_tlc_cmd_to_v4(&cmd, &cmd_v4);
+ ret = iwl_mld_convert_tlc_cmd_to_v4(&cmd, &cmd_v4);
+ if (ret)
+ return;
cmd_ptr = &cmd_v4;
cmd_size = sizeof(cmd_v4);
} else {
@@ -520,8 +580,9 @@ static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld,
}
IWL_DEBUG_RATE(mld,
- "TLC CONFIG CMD, sta_id=%d, max_ch_width=%d, mode=%d\n",
- cmd.sta_id, cmd.max_ch_width, cmd.mode);
+ "TLC CONFIG CMD, sta_mask=0x%x, max_ch_width=%d, mode=%d, phy_id=%d\n",
+ le32_to_cpu(cmd.sta_mask), cmd.max_ch_width, cmd.mode,
+ le32_to_cpu(cmd.phy_id));
/* Send async since this can be called within a RCU-read section */
ret = iwl_mld_send_cmd_with_flags_pdu(mld, cmd_id, CMD_ASYNC, cmd_ptr,
@@ -561,7 +622,6 @@ void iwl_mld_config_tlc_link(struct iwl_mld *mld,
struct ieee80211_link_sta *link_sta)
{
struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(link_sta->sta);
- enum nl80211_band band;
if (WARN_ON_ONCE(!link_conf->chanreq.oper.chan))
return;
@@ -575,8 +635,7 @@ void iwl_mld_config_tlc_link(struct iwl_mld *mld,
ieee80211_sta_recalc_aggregates(link_sta->sta);
}
- band = link_conf->chanreq.oper.chan->band;
- iwl_mld_send_tlc_cmd(mld, vif, link_sta, band);
+ iwl_mld_send_tlc_cmd(mld, vif, link_sta, link_conf);
}
void iwl_mld_config_tlc(struct iwl_mld *mld, struct ieee80211_vif *vif,
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tx.c b/drivers/net/wireless/intel/iwlwifi/mld/tx.c
index 3b4b575aadaa..546d09a38dab 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tx.c
@@ -345,6 +345,11 @@ u8 iwl_mld_get_lowest_rate(struct iwl_mld *mld,
iwl_mld_get_basic_rates_and_band(mld, vif, info, &basic_rates, &band);
+ if (band >= NUM_NL80211_BANDS) {
+ WARN_ON(vif->type != NL80211_IFTYPE_NAN);
+ return IWL_FIRST_OFDM_RATE;
+ }
+
sband = mld->hw->wiphy->bands[band];
for_each_set_bit(i, &basic_rates, BITS_PER_LONG) {
u16 hw = sband->bitrates[i].hw_value;
@@ -667,6 +672,12 @@ iwl_mld_get_tx_queue_id(struct iwl_mld *mld, struct ieee80211_txq *txq,
WARN_ON(!ieee80211_is_mgmt(fc));
return mld_vif->aux_sta.queue_id;
+ case NL80211_IFTYPE_NAN:
+ mld_vif = iwl_mld_vif_from_mac80211(info->control.vif);
+
+ WARN_ON(!ieee80211_is_mgmt(fc));
+
+ return mld_vif->aux_sta.queue_id;
default:
WARN_ONCE(1, "Unsupported vif type\n");
break;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index af1a45845999..6c225861db61 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -726,8 +726,7 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_time_quota_data *quota;
u32 status;
- if (WARN_ON_ONCE(iwl_mvm_is_cdb_supported(mvm) ||
- ieee80211_vif_is_mld(vif)))
+ if (WARN_ON_ONCE(iwl_mvm_is_cdb_supported(mvm)))
return -EINVAL;
/* add back the PHY */
@@ -1248,7 +1247,6 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
struct ieee80211_vif *vif = NULL;
struct iwl_mvm_vif *mvmvif = NULL;
struct ieee80211_sta *ap_sta = NULL;
- struct iwl_mvm_vif_link_info *mvm_link;
struct iwl_d3_manager_config d3_cfg_cmd = {
/*
* Program the minimum sleep time to 10 seconds, as many
@@ -1280,13 +1278,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
mvmvif = iwl_mvm_vif_from_mac80211(vif);
- mvm_link = mvmvif->link[iwl_mvm_get_primary_link(vif)];
- if (WARN_ON_ONCE(!mvm_link)) {
- ret = -EINVAL;
- goto out_noreset;
- }
-
- if (mvm_link->ap_sta_id == IWL_INVALID_STA) {
+ if (mvmvif->deflink.ap_sta_id == IWL_INVALID_STA) {
/* if we're not associated, this must be netdetect */
if (!wowlan->nd_config) {
ret = 1;
@@ -1304,10 +1296,10 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
.offloading_tid = 0,
};
- wowlan_config_cmd.sta_id = mvm_link->ap_sta_id;
+ wowlan_config_cmd.sta_id = mvmvif->deflink.ap_sta_id;
ap_sta = rcu_dereference_protected(
- mvm->fw_id_to_mac_id[mvm_link->ap_sta_id],
+ mvm->fw_id_to_mac_id[mvmvif->deflink.ap_sta_id],
lockdep_is_held(&mvm->mutex));
if (IS_ERR_OR_NULL(ap_sta)) {
ret = -EINVAL;
@@ -1324,7 +1316,8 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
if (ret)
goto out_noreset;
ret = iwl_mvm_wowlan_config(mvm, wowlan, &wowlan_config_cmd,
- vif, mvmvif, mvm_link, ap_sta);
+ vif, mvmvif, &mvmvif->deflink,
+ ap_sta);
if (ret)
goto out;
@@ -1819,10 +1812,6 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
struct iwl_mvm_d3_gtk_iter_data *data = _data;
struct iwl_wowlan_status_data *status = data->status;
s8 keyidx;
- int link_id = vif->active_links ? __ffs(vif->active_links) : -1;
-
- if (link_id >= 0 && key->link_id >= 0 && link_id != key->link_id)
- return;
switch (key->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
@@ -1876,7 +1865,6 @@ static bool iwl_mvm_gtk_rekey(struct iwl_wowlan_status_data *status,
{
int i, j;
struct ieee80211_key_conf *key;
- int link_id = vif->active_links ? __ffs(vif->active_links) : -1;
for (i = 0; i < ARRAY_SIZE(status->gtk); i++) {
if (!status->gtk[i].len)
@@ -1888,8 +1876,7 @@ static bool iwl_mvm_gtk_rekey(struct iwl_wowlan_status_data *status,
key = ieee80211_gtk_rekey_add(vif, status->gtk[i].id,
status->gtk[i].key,
- sizeof(status->gtk[i].key),
- link_id);
+ sizeof(status->gtk[i].key), -1);
if (IS_ERR(key)) {
/* FW may send also the old keys */
if (PTR_ERR(key) == -EALREADY)
@@ -1918,14 +1905,13 @@ iwl_mvm_d3_igtk_bigtk_rekey_add(struct iwl_wowlan_status_data *status,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_key_conf *key_config;
struct ieee80211_key_seq seq;
- int link_id = vif->active_links ? __ffs(vif->active_links) : -1;
s8 keyidx = key_data->id;
if (!key_data->len)
return true;
key_config = ieee80211_gtk_rekey_add(vif, keyidx, key_data->key,
- sizeof(key_data->key), link_id);
+ sizeof(key_data->key), -1);
if (IS_ERR(key_config)) {
/* FW may send also the old keys */
return PTR_ERR(key_config) == -EALREADY;
@@ -1935,13 +1921,9 @@ iwl_mvm_d3_igtk_bigtk_rekey_add(struct iwl_wowlan_status_data *status,
ieee80211_set_key_rx_seq(key_config, 0, &seq);
if (keyidx == 4 || keyidx == 5) {
- struct iwl_mvm_vif_link_info *mvm_link;
-
- link_id = link_id < 0 ? 0 : link_id;
- mvm_link = mvmvif->link[link_id];
- if (mvm_link->igtk)
- mvm_link->igtk->hw_key_idx = STA_KEY_IDX_INVALID;
- mvm_link->igtk = key_config;
+ if (mvmvif->deflink.igtk)
+ mvmvif->deflink.igtk->hw_key_idx = STA_KEY_IDX_INVALID;
+ mvmvif->deflink.igtk = key_config;
}
if (vif->type == NL80211_IFTYPE_STATION && (keyidx == 6 || keyidx == 7))
@@ -2396,23 +2378,19 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
bool keep = false;
struct iwl_mvm_sta *mvm_ap_sta;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- int link_id = vif->active_links ? __ffs(vif->active_links) : 0;
- struct iwl_mvm_vif_link_info *mvm_link = mvmvif->link[link_id];
int wowlan_info_ver = iwl_fw_lookup_notif_ver(mvm->fw,
PROT_OFFLOAD_GROUP,
WOWLAN_INFO_NOTIFICATION,
IWL_FW_CMD_VER_UNKNOWN);
- if (WARN_ON(!mvm_link))
- goto out_unlock;
-
if (!status)
goto out_unlock;
IWL_DEBUG_WOWLAN(mvm, "wakeup reason 0x%x\n",
status->wakeup_reasons);
- mvm_ap_sta = iwl_mvm_sta_from_staid_protected(mvm, mvm_link->ap_sta_id);
+ mvm_ap_sta = iwl_mvm_sta_from_staid_protected(mvm,
+ mvmvif->deflink.ap_sta_id);
if (!mvm_ap_sta)
goto out_unlock;
@@ -2756,9 +2734,6 @@ iwl_mvm_choose_query_wakeup_reasons(struct iwl_mvm *mvm,
u8 sta_id = mvm->net_detect ? IWL_INVALID_STA :
mvmvif->deflink.ap_sta_id;
- /* bug - FW with MLO has status notification */
- WARN_ON(ieee80211_vif_is_mld(vif));
-
d3_data->status = iwl_mvm_send_wowlan_get_status(mvm, sta_id);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index edae13755ee6..43cf94c9a36b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -1135,8 +1135,9 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
for (u16 i = 0; i < data.block_list_size; i++)
cmd_v5.block_list_array[i] =
cpu_to_le16(data.block_list_array[i]);
- cmd_v5.tas_config_info.table_source = data.table_source;
- cmd_v5.tas_config_info.table_revision = data.table_revision;
+ cmd_v5.tas_config_info.hdr.table_source = data.table_source;
+ cmd_v5.tas_config_info.hdr.table_revision =
+ data.table_revision;
cmd_v5.tas_config_info.value = cpu_to_le32(data.tas_selection);
} else if (fw_ver == 4) {
cmd_size = sizeof(cmd_v2_v4.common) + sizeof(cmd_v2_v4.v4);
@@ -1165,13 +1166,208 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
IWL_DEBUG_RADIO(mvm, "failed to send TAS_CONFIG (%d)\n", ret);
}
+static __le32 iwl_mvm_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt)
+{
+ int ret;
+ u32 val;
+ __le32 config_bitmap = 0;
+
+ switch (CSR_HW_RFID_TYPE(fwrt->trans->info.hw_rf_id)) {
+ case IWL_CFG_RF_TYPE_HR1:
+ case IWL_CFG_RF_TYPE_HR2:
+ case IWL_CFG_RF_TYPE_JF1:
+ case IWL_CFG_RF_TYPE_JF2:
+ ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_INDONESIA_5G2,
+ &val);
+
+ if (!ret && val == DSM_VALUE_INDONESIA_ENABLE)
+ config_bitmap |=
+ cpu_to_le32(LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK);
+ break;
+ default:
+ break;
+ }
+
+ ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_DISABLE_SRD, &val);
+ if (!ret) {
+ if (val == DSM_VALUE_SRD_PASSIVE)
+ config_bitmap |=
+ cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_PASSIVE_MSK);
+ else if (val == DSM_VALUE_SRD_DISABLE)
+ config_bitmap |=
+ cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_DISABLED_MSK);
+ }
+
+ if (fw_has_capa(&fwrt->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_CHINA_22_REG_SUPPORT)) {
+ ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_REGULATORY_CONFIG,
+ &val);
+ /*
+ * China 2022 enable if the BIOS object does not exist or
+ * if it is enabled in BIOS.
+ */
+ if (ret < 0 || val & DSM_MASK_CHINA_22_REG)
+ config_bitmap |=
+ cpu_to_le32(LARI_CONFIG_ENABLE_CHINA_22_REG_SUPPORT_MSK);
+ }
+
+ return config_bitmap;
+}
+
+static size_t iwl_mvm_get_lari_config_cmd_size(u8 cmd_ver)
+{
+ size_t cmd_size;
+
+ switch (cmd_ver) {
+ case 12:
+ cmd_size = offsetof(struct iwl_lari_config_change_cmd,
+ oem_11bn_allow_bitmap);
+ break;
+ case 8:
+ cmd_size = sizeof(struct iwl_lari_config_change_cmd_v8);
+ break;
+ case 6:
+ cmd_size = sizeof(struct iwl_lari_config_change_cmd_v6);
+ break;
+ default:
+ cmd_size = sizeof(struct iwl_lari_config_change_cmd_v1);
+ break;
+ }
+ return cmd_size;
+}
+
+static int iwl_mvm_fill_lari_config(struct iwl_fw_runtime *fwrt,
+ struct iwl_lari_config_change_cmd *cmd,
+ size_t *cmd_size)
+{
+ int ret;
+ u32 value;
+ bool has_raw_dsm_capa = fw_has_capa(&fwrt->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE);
+ u8 cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
+ WIDE_ID(REGULATORY_AND_NVM_GROUP,
+ LARI_CONFIG_CHANGE), 1);
+
+ memset(cmd, 0, sizeof(*cmd));
+ *cmd_size = iwl_mvm_get_lari_config_cmd_size(cmd_ver);
+
+ cmd->config_bitmap = iwl_mvm_get_lari_config_bitmap(fwrt);
+
+ ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_11AX_ENABLEMENT, &value);
+ if (!ret) {
+ if (!has_raw_dsm_capa)
+ value &= DSM_11AX_ALLOW_BITMAP;
+ cmd->oem_11ax_allow_bitmap = cpu_to_le32(value);
+ }
+
+ ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_UNII4_CHAN, &value);
+ if (!ret) {
+ if (!has_raw_dsm_capa)
+ value &= DSM_UNII4_ALLOW_BITMAP;
+
+ /* Since version 12, bits 4 and 5 are supported
+ * regardless of this capability, By pass this masking
+ * if firmware has capability of accepting raw DSM table.
+ */
+ if (!has_raw_dsm_capa && cmd_ver < 12 &&
+ !fw_has_capa(&fwrt->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_5G9_FOR_CA))
+ value &= ~(DSM_VALUE_UNII4_CANADA_OVERRIDE_MSK |
+ DSM_VALUE_UNII4_CANADA_EN_MSK);
+
+ cmd->oem_unii4_allow_bitmap = cpu_to_le32(value);
+ }
+
+ ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ACTIVATE_CHANNEL, &value);
+ if (!ret) {
+ if (!has_raw_dsm_capa)
+ value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V12;
+
+ if (!has_raw_dsm_capa && cmd_ver < 8)
+ value &= ~ACTIVATE_5G2_IN_WW_MASK;
+
+ /* Since version 12, bits 5 and 6 are supported
+ * regardless of this capability, By pass this masking
+ * if firmware has capability of accepting raw DSM table.
+ */
+ if (!has_raw_dsm_capa && cmd_ver < 12 &&
+ !fw_has_capa(&fwrt->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_UNII4_US_CA))
+ value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V8;
+
+ cmd->chan_state_active_bitmap = cpu_to_le32(value);
+ }
+
+ ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_6E, &value);
+ if (!ret)
+ cmd->oem_uhb_allow_bitmap = cpu_to_le32(value);
+
+ ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_FORCE_DISABLE_CHANNELS, &value);
+ if (!ret) {
+ if (!has_raw_dsm_capa)
+ value &= DSM_FORCE_DISABLE_CHANNELS_ALLOWED_BITMAP;
+ cmd->force_disable_channels_bitmap = cpu_to_le32(value);
+ }
+
+ ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENERGY_DETECTION_THRESHOLD,
+ &value);
+ if (!ret) {
+ if (!has_raw_dsm_capa)
+ value &= DSM_EDT_ALLOWED_BITMAP;
+ cmd->edt_bitmap = cpu_to_le32(value);
+ }
+
+ ret = iwl_bios_get_wbem(fwrt, &value);
+ if (!ret)
+ cmd->oem_320mhz_allow_bitmap = cpu_to_le32(value);
+
+ ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_11BE, &value);
+ if (!ret)
+ cmd->oem_11be_allow_bitmap = cpu_to_le32(value);
+
+ if (cmd->config_bitmap ||
+ cmd->oem_uhb_allow_bitmap ||
+ cmd->oem_11ax_allow_bitmap ||
+ cmd->oem_unii4_allow_bitmap ||
+ cmd->chan_state_active_bitmap ||
+ cmd->force_disable_channels_bitmap ||
+ cmd->edt_bitmap ||
+ cmd->oem_320mhz_allow_bitmap ||
+ cmd->oem_11be_allow_bitmap) {
+ IWL_DEBUG_RADIO(fwrt,
+ "sending LARI_CONFIG_CHANGE, config_bitmap=0x%x, oem_11ax_allow_bitmap=0x%x\n",
+ le32_to_cpu(cmd->config_bitmap),
+ le32_to_cpu(cmd->oem_11ax_allow_bitmap));
+ IWL_DEBUG_RADIO(fwrt,
+ "sending LARI_CONFIG_CHANGE, oem_unii4_allow_bitmap=0x%x, chan_state_active_bitmap=0x%x, cmd_ver=%d\n",
+ le32_to_cpu(cmd->oem_unii4_allow_bitmap),
+ le32_to_cpu(cmd->chan_state_active_bitmap),
+ cmd_ver);
+ IWL_DEBUG_RADIO(fwrt,
+ "sending LARI_CONFIG_CHANGE, oem_uhb_allow_bitmap=0x%x, force_disable_channels_bitmap=0x%x\n",
+ le32_to_cpu(cmd->oem_uhb_allow_bitmap),
+ le32_to_cpu(cmd->force_disable_channels_bitmap));
+ IWL_DEBUG_RADIO(fwrt,
+ "sending LARI_CONFIG_CHANGE, edt_bitmap=0x%x, oem_320mhz_allow_bitmap=0x%x\n",
+ le32_to_cpu(cmd->edt_bitmap),
+ le32_to_cpu(cmd->oem_320mhz_allow_bitmap));
+ IWL_DEBUG_RADIO(fwrt,
+ "sending LARI_CONFIG_CHANGE, oem_11be_allow_bitmap=0x%x\n",
+ le32_to_cpu(cmd->oem_11be_allow_bitmap));
+ } else {
+ return 1;
+ }
+
+ return 0;
+}
+
static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
{
struct iwl_lari_config_change_cmd cmd;
size_t cmd_size;
int ret;
- ret = iwl_fill_lari_config(&mvm->fwrt, &cmd, &cmd_size);
+ ret = iwl_mvm_fill_lari_config(&mvm->fwrt, &cmd, &cmd_size);
if (!ret) {
ret = iwl_mvm_send_cmd_pdu(mvm,
WIDE_ID(REGULATORY_AND_NVM_GROUP,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
index 738facceb240..b5d252ece2d9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
@@ -285,28 +285,6 @@ int iwl_mvm_disable_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return ret;
}
-u8 iwl_mvm_get_primary_link(struct ieee80211_vif *vif)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-
- /* relevant data is written with both locks held, so read with either */
- lockdep_assert(lockdep_is_held(&mvmvif->mvm->mutex) ||
- lockdep_is_held(&mvmvif->mvm->hw->wiphy->mtx));
-
- if (!ieee80211_vif_is_mld(vif))
- return 0;
-
- /* In AP mode, there is no primary link */
- if (vif->type == NL80211_IFTYPE_AP)
- return __ffs(vif->active_links);
-
- if (mvmvif->esr_active &&
- !WARN_ON(!(BIT(mvmvif->primary_link) & vif->active_links)))
- return mvmvif->primary_link;
-
- return __ffs(vif->active_links);
-}
-
void iwl_mvm_init_link(struct iwl_mvm_vif_link_info *link)
{
link->bcast_sta.sta_id = IWL_INVALID_STA;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index 867807abde66..0e5820c13523 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -873,7 +873,6 @@ u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct iwl_mvm *mvm,
struct ieee80211_tx_info *info,
struct ieee80211_vif *vif)
{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_supported_band *sband;
unsigned long basic = vif->bss_conf.basic_rates;
u16 lowest_cck = IWL_RATE_COUNT, lowest_ofdm = IWL_RATE_COUNT;
@@ -883,16 +882,6 @@ u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct iwl_mvm *mvm,
u8 rate;
u32 i;
- if (link_id == IEEE80211_LINK_UNSPECIFIED && ieee80211_vif_is_mld(vif)) {
- for (i = 0; i < ARRAY_SIZE(mvmvif->link); i++) {
- if (!mvmvif->link[i])
- continue;
- /* shouldn't do this when >1 link is active */
- WARN_ON_ONCE(link_id != IEEE80211_LINK_UNSPECIFIED);
- link_id = i;
- }
- }
-
if (link_id < IEEE80211_LINK_UNSPECIFIED) {
struct ieee80211_bss_conf *link_conf;
@@ -1761,6 +1750,20 @@ void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm,
mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ /*
+ * len_low should be 2 + n*13 (where n is the number of descriptors.
+ * 13 is the size of a NoA descriptor). We can have either one or two
+ * descriptors.
+ */
+ if (IWL_FW_CHECK(mvm, notif->noa_active &&
+ notif->noa_attr.len_low != 2 +
+ sizeof(struct ieee80211_p2p_noa_desc) &&
+ notif->noa_attr.len_low != 2 +
+ sizeof(struct ieee80211_p2p_noa_desc) * 2,
+ "Invalid noa_attr.len_low (%d)\n",
+ notif->noa_attr.len_low))
+ return;
+
new_data = kzalloc(sizeof(*new_data), GFP_KERNEL);
if (!new_data)
return;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 44029ceb8f77..169c87588938 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -1109,7 +1109,6 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
mvmvif->ba_enabled = false;
mvmvif->ap_sta = NULL;
- mvmvif->esr_active = false;
vif->driver_flags &= ~IEEE80211_VIF_EML_ACTIVE;
for_each_mvm_vif_valid_link(mvmvif, link_id) {
@@ -1129,39 +1128,6 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
RCU_INIT_POINTER(mvmvif->deflink.probe_resp_data, NULL);
}
-static void iwl_mvm_cleanup_sta_iterator(void *data, struct ieee80211_sta *sta)
-{
- struct iwl_mvm *mvm = data;
- struct iwl_mvm_sta *mvm_sta;
- struct ieee80211_vif *vif;
- int link_id;
-
- mvm_sta = iwl_mvm_sta_from_mac80211(sta);
- vif = mvm_sta->vif;
-
- if (!sta->valid_links)
- return;
-
- for (link_id = 0; link_id < ARRAY_SIZE((sta)->link); link_id++) {
- struct iwl_mvm_link_sta *mvm_link_sta;
-
- mvm_link_sta =
- rcu_dereference_check(mvm_sta->link[link_id],
- lockdep_is_held(&mvm->mutex));
- if (mvm_link_sta && !(vif->active_links & BIT(link_id))) {
- /*
- * We have a link STA but the link is inactive in
- * mac80211. This will happen if we failed to
- * deactivate the link but mac80211 roll back the
- * deactivation of the link.
- * Delete the stale data to avoid issues later on.
- */
- iwl_mvm_mld_free_sta_link(mvm, mvm_sta, mvm_link_sta,
- link_id);
- }
- }
-}
-
static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
{
iwl_mvm_stop_device(mvm);
@@ -1184,10 +1150,6 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
*/
ieee80211_iterate_interfaces(mvm->hw, 0, iwl_mvm_cleanup_iterator, mvm);
- /* cleanup stations as links may be gone after restart */
- ieee80211_iterate_stations_atomic(mvm->hw,
- iwl_mvm_cleanup_sta_iterator, mvm);
-
mvm->p2p_device_vif = NULL;
iwl_mvm_reset_phy_ctxts(mvm);
@@ -2639,7 +2601,7 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
}
void iwl_mvm_protect_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- u32 duration_override, unsigned int link_id)
+ u32 duration_override)
{
u32 duration = IWL_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS;
u32 min_duration = IWL_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS;
@@ -2659,8 +2621,7 @@ void iwl_mvm_protect_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD))
iwl_mvm_schedule_session_protection(mvm, vif, 900,
- min_duration, false,
- link_id);
+ min_duration, false);
else
iwl_mvm_protect_session(mvm, vif, duration,
min_duration, 500, false);
@@ -2860,7 +2821,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
* time could be small without us having heard
* a beacon yet.
*/
- iwl_mvm_protect_assoc(mvm, vif, 0, 0);
+ iwl_mvm_protect_assoc(mvm, vif, 0);
}
iwl_mvm_sf_update(mvm, vif, false);
@@ -3921,12 +3882,6 @@ iwl_mvm_sta_state_assoc_to_authorized(struct iwl_mvm *mvm,
mvmvif->authorized = 1;
- if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
- mvmvif->link_selection_res = vif->active_links;
- mvmvif->link_selection_primary =
- vif->active_links ? __ffs(vif->active_links) : 0;
- }
-
callbacks->mac_ctxt_changed(mvm, vif, false);
iwl_mvm_mei_host_associated(mvm, vif, mvm_sta);
}
@@ -3972,7 +3927,6 @@ iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm,
* time.
*/
mvmvif->authorized = 0;
- mvmvif->link_selection_res = 0;
/* disable beacon filtering */
iwl_mvm_disable_beacon_filter(mvm, vif);
@@ -4197,7 +4151,7 @@ void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
return;
guard(mvm)(mvm);
- iwl_mvm_protect_assoc(mvm, vif, info->duration, info->link_id);
+ iwl_mvm_protect_assoc(mvm, vif, info->duration);
}
void iwl_mvm_mac_mgd_complete_tx(struct ieee80211_hw *hw,
@@ -5568,8 +5522,7 @@ static int iwl_mvm_pre_channel_switch(struct iwl_mvm *mvm,
if (!vif->cfg.assoc || !vif->bss_conf.dtim_period)
return -EBUSY;
- if (chsw->delay > IWL_MAX_CSA_BLOCK_TX &&
- hweight16(vif->valid_links) <= 1)
+ if (chsw->delay > IWL_MAX_CSA_BLOCK_TX)
schedule_delayed_work(&mvmvif->csa_work, 0);
if (chsw->block_tx) {
@@ -5733,15 +5686,8 @@ void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
return;
}
- if (!drop && hweight16(vif->active_links) <= 1) {
- int link_id = vif->active_links ? __ffs(vif->active_links) : 0;
- struct ieee80211_bss_conf *link_conf;
-
- link_conf = wiphy_dereference(hw->wiphy,
- vif->link_conf[link_id]);
- if (WARN_ON(!link_conf))
- return;
- if (link_conf->csa_active && mvmvif->csa_blocks_tx)
+ if (!drop) {
+ if (vif->bss_conf.csa_active && mvmvif->csa_blocks_tx)
drop = true;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
index ef0be44207e1..9bb253dcf4a7 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2022 - 2024 Intel Corporation
+ * Copyright (C) 2022 - 2025 Intel Corporation
*/
#include <linux/kernel.h>
#include <net/mac80211.h>
@@ -43,11 +43,11 @@ static u32 iwl_mvm_get_sec_sta_mask(struct iwl_mvm *mvm,
* group keys have no sta pointer), so we don't have a STA now.
* Since this happens for group keys only, just use the link_info as
* the group keys are per link; make sure that is the case by checking
- * we do have a link_id or are not doing MLO.
+ * we do have a link_id.
* Of course the same can be done during add as well, but we must do
* it during remove, since we don't have the mvmvif->ap_sta pointer.
*/
- if (!sta && (keyconf->link_id >= 0 || !ieee80211_vif_is_mld(vif)))
+ if (!sta && keyconf->link_id >= 0)
return BIT(link_info->ap_sta_id);
/* STA should be non-NULL now, but iwl_mvm_sta_fw_id_mask() checks */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
index 2d116a41913c..bf54b90a7c51 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
@@ -56,23 +56,6 @@ static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
if (iwlwifi_mod_params.disable_11ax)
return;
- /* If we have MLO enabled, then the firmware needs to enable
- * address translation for the station(s) we add. That depends
- * on having EHT enabled in firmware, which in turn depends on
- * mac80211 in the code below.
- * However, mac80211 doesn't enable HE/EHT until it has parsed
- * the association response successfully, so just skip all that
- * and enable both when we have MLO.
- */
- if (ieee80211_vif_is_mld(vif)) {
- iwl_mvm_mld_set_he_support(mvm, vif, cmd, cmd_ver);
- if (cmd_ver == 2)
- cmd->wifi_gen_v2.eht_support = cpu_to_le32(1);
- else
- cmd->wifi_gen.eht_support = 1;
- return;
- }
-
rcu_read_lock();
for (link_id = 0; link_id < ARRAY_SIZE((vif)->link_conf); link_id++) {
link_conf = rcu_dereference(vif->link_conf[link_id]);
@@ -116,7 +99,6 @@ static int iwl_mvm_mld_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
u32 action, bool force_assoc_off)
{
struct iwl_mac_config_cmd cmd = {};
- u16 esr_transition_timeout;
WARN_ON(vif->type != NL80211_IFTYPE_STATION);
@@ -154,17 +136,6 @@ static int iwl_mvm_mld_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
}
cmd.client.assoc_id = cpu_to_le16(vif->cfg.aid);
- if (ieee80211_vif_is_mld(vif)) {
- esr_transition_timeout =
- u16_get_bits(vif->cfg.eml_cap,
- IEEE80211_EML_CAP_TRANSITION_TIMEOUT);
-
- cmd.client.esr_transition_timeout =
- min_t(u16, IEEE80211_EML_CAP_TRANSITION_TIMEOUT_128TU,
- esr_transition_timeout);
- cmd.client.medium_sync_delay =
- cpu_to_le16(vif->cfg.eml_med_sync_delay);
- }
if (vif->probe_req_reg && vif->cfg.assoc && vif->p2p)
cmd.filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_PROBE_REQ);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index 380b6f8a53fd..075ff09e93cc 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -60,19 +60,12 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
IEEE80211_VIF_SUPPORTS_CQM_RSSI;
}
- /* We want link[0] to point to the default link, unless we have MLO and
- * in this case this will be modified later by .change_vif_links()
- * If we are in the restart flow with an MLD connection, we will wait
- * to .change_vif_links() to setup the links.
- */
- if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) ||
- !ieee80211_vif_is_mld(vif)) {
- mvmvif->link[0] = &mvmvif->deflink;
+ /* We want link[0] to point to the default link. */
+ mvmvif->link[0] = &mvmvif->deflink;
- ret = iwl_mvm_add_link(mvm, vif, &vif->bss_conf);
- if (ret)
- goto out_free_bf;
- }
+ ret = iwl_mvm_add_link(mvm, vif, &vif->bss_conf);
+ if (ret)
+ goto out_free_bf;
/* Save a pointer to p2p device vif, so it can later be used to
* update the p2p device MAC when a GO is started/stopped
@@ -181,58 +174,6 @@ static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw,
}
}
-static unsigned int iwl_mvm_mld_count_active_links(struct iwl_mvm_vif *mvmvif)
-{
- unsigned int n_active = 0;
- int i;
-
- for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
- if (mvmvif->link[i] && mvmvif->link[i]->phy_ctxt)
- n_active++;
- }
-
- return n_active;
-}
-
-static int iwl_mvm_esr_mode_active(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- int link_id, ret = 0;
-
- mvmvif->esr_active = true;
-
- /* Indicate to mac80211 that EML is enabled */
- vif->driver_flags |= IEEE80211_VIF_EML_ACTIVE;
-
- iwl_mvm_update_smps_on_active_links(mvm, vif, IWL_MVM_SMPS_REQ_FW,
- IEEE80211_SMPS_OFF);
-
- for_each_mvm_vif_valid_link(mvmvif, link_id) {
- struct iwl_mvm_vif_link_info *link = mvmvif->link[link_id];
-
- if (!link->phy_ctxt)
- continue;
-
- ret = iwl_mvm_phy_send_rlc(mvm, link->phy_ctxt, 2, 2);
- if (ret)
- break;
-
- link->phy_ctxt->rlc_disabled = true;
- }
-
- if (vif->active_links == mvmvif->link_selection_res &&
- !WARN_ON(!(vif->active_links & BIT(mvmvif->link_selection_primary))))
- mvmvif->primary_link = mvmvif->link_selection_primary;
- else
- mvmvif->primary_link = __ffs(vif->active_links);
-
- iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_ESR_LINK_UP,
- NULL);
-
- return ret;
-}
-
static int
__iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
@@ -243,17 +184,12 @@ __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- unsigned int n_active = iwl_mvm_mld_count_active_links(mvmvif);
unsigned int link_id = link_conf->link_id;
int ret;
if (WARN_ON_ONCE(!mvmvif->link[link_id]))
return -EINVAL;
- /* if the assigned one was not counted yet, count it now */
- if (!mvmvif->link[link_id]->phy_ctxt)
- n_active++;
-
/* mac parameters such as HE support can change at this stage
* For sta, need first to configure correct state from drv_sta_state
* and only after that update mac config.
@@ -268,15 +204,6 @@ __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
mvmvif->link[link_id]->phy_ctxt = phy_ctxt;
- if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) {
- mvmvif->link[link_id]->listen_lmac = true;
- ret = iwl_mvm_esr_mode_active(mvm, vif);
- if (ret) {
- IWL_ERR(mvm, "failed to activate ESR mode (%d)\n", ret);
- goto out;
- }
- }
-
if (switching_chanctx) {
/* reactivate if we turned this off during channel switch */
if (vif->type == NL80211_IFTYPE_AP)
@@ -341,55 +268,6 @@ static int iwl_mvm_mld_assign_vif_chanctx(struct ieee80211_hw *hw,
return __iwl_mvm_mld_assign_vif_chanctx(mvm, vif, link_conf, ctx, false);
}
-static int iwl_mvm_esr_mode_inactive(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct ieee80211_bss_conf *link_conf;
- int link_id, ret = 0;
-
- mvmvif->esr_active = false;
-
- vif->driver_flags &= ~IEEE80211_VIF_EML_ACTIVE;
-
- iwl_mvm_update_smps_on_active_links(mvm, vif, IWL_MVM_SMPS_REQ_FW,
- IEEE80211_SMPS_AUTOMATIC);
-
- for_each_vif_active_link(vif, link_conf, link_id) {
- struct ieee80211_chanctx_conf *chanctx_conf;
- struct iwl_mvm_phy_ctxt *phy_ctxt;
- u8 static_chains, dynamic_chains;
-
- mvmvif->link[link_id]->listen_lmac = false;
-
- rcu_read_lock();
-
- chanctx_conf = rcu_dereference(link_conf->chanctx_conf);
- phy_ctxt = mvmvif->link[link_id]->phy_ctxt;
-
- if (!chanctx_conf || !phy_ctxt) {
- rcu_read_unlock();
- continue;
- }
-
- phy_ctxt->rlc_disabled = false;
- static_chains = chanctx_conf->rx_chains_static;
- dynamic_chains = chanctx_conf->rx_chains_dynamic;
-
- rcu_read_unlock();
-
- ret = iwl_mvm_phy_send_rlc(mvm, phy_ctxt, static_chains,
- dynamic_chains);
- if (ret)
- break;
- }
-
- iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_ESR_LINK_DOWN,
- NULL);
-
- return ret;
-}
-
static void
__iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
@@ -399,7 +277,6 @@ __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- unsigned int n_active = iwl_mvm_mld_count_active_links(mvmvif);
unsigned int link_id = link_conf->link_id;
/* shouldn't happen, but verify link_id is valid before accessing */
@@ -421,14 +298,6 @@ __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
iwl_mvm_link_changed(mvm, vif, link_conf,
LINK_CONTEXT_MODIFY_ACTIVE, false);
- if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) {
- int ret = iwl_mvm_esr_mode_inactive(mvm, vif);
-
- if (ret)
- IWL_ERR(mvm, "failed to deactivate ESR mode (%d)\n",
- ret);
- }
-
if (vif->type == NL80211_IFTYPE_MONITOR)
iwl_mvm_mld_rm_snif_sta(mvm, vif);
@@ -448,9 +317,8 @@ static void iwl_mvm_mld_unassign_vif_chanctx(struct ieee80211_hw *hw,
mutex_lock(&mvm->mutex);
__iwl_mvm_mld_unassign_vif_chanctx(mvm, vif, link_conf, ctx, false);
- /* in the non-MLD case, remove/re-add the link to clean up FW state */
- if (!ieee80211_vif_is_mld(vif) && !mvmvif->ap_sta &&
- !WARN_ON_ONCE(vif->cfg.assoc)) {
+ /* Remove/re-add the link to clean up FW state */
+ if (!mvmvif->ap_sta && !WARN_ON_ONCE(vif->cfg.assoc)) {
iwl_mvm_remove_link(mvm, vif, link_conf);
iwl_mvm_add_link(mvm, vif, link_conf);
}
@@ -785,12 +653,6 @@ static void iwl_mvm_mld_vif_cfg_changed_station(struct iwl_mvm *mvm,
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
protect) {
- /* We are in assoc so only one link is active-
- * The association link
- */
- unsigned int link_id =
- ffs(vif->active_links) - 1;
-
/* If we're not restarting and still haven't
* heard a beacon (dtim period unknown) then
* make sure we still have enough minimum time
@@ -800,7 +662,7 @@ static void iwl_mvm_mld_vif_cfg_changed_station(struct iwl_mvm *mvm,
* time could be small without us having heard
* a beacon yet.
*/
- iwl_mvm_protect_assoc(mvm, vif, 0, link_id);
+ iwl_mvm_protect_assoc(mvm, vif, 0);
}
iwl_mvm_sf_update(mvm, vif, false);
@@ -1096,14 +958,6 @@ iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
if (new_links == 0) {
mvmvif->link[0] = &mvmvif->deflink;
err = iwl_mvm_add_link(mvm, vif, &vif->bss_conf);
- if (err == 0)
- mvmvif->primary_link = 0;
- } else if (!(new_links & BIT(mvmvif->primary_link))) {
- /*
- * Ensure we always have a valid primary_link, the real
- * decision happens later when PHY is activated.
- */
- mvmvif->primary_link = __ffs(new_links);
}
out_err:
@@ -1128,44 +982,17 @@ iwl_mvm_mld_change_sta_links(struct ieee80211_hw *hw,
return iwl_mvm_mld_update_sta_links(mvm, vif, sta, old_links, new_links);
}
-bool iwl_mvm_vif_has_esr_cap(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
-{
- const struct wiphy_iftype_ext_capab *ext_capa;
-
- lockdep_assert_held(&mvm->mutex);
-
- if (!ieee80211_vif_is_mld(vif) || !vif->cfg.assoc ||
- hweight16(ieee80211_vif_usable_links(vif)) == 1)
- return false;
-
- if (!(vif->cfg.eml_cap & IEEE80211_EML_CAP_EMLSR_SUPP))
- return false;
-
- ext_capa = cfg80211_get_iftype_ext_capa(mvm->hw->wiphy,
- ieee80211_vif_type_p2p(vif));
- return (ext_capa &&
- (ext_capa->eml_capabilities & IEEE80211_EML_CAP_EMLSR_SUPP));
-}
-
static bool iwl_mvm_mld_can_activate_links(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u16 desired_links)
{
- struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int n_links = hweight16(desired_links);
if (n_links <= 1)
return true;
- guard(mvm)(mvm);
-
- /* Check if HW supports the wanted number of links */
- if (n_links > iwl_mvm_max_active_links(mvm, vif))
- return false;
-
- /* If it is an eSR device, check that we can enter eSR */
- return iwl_mvm_is_esr_supported(mvm->fwrt.trans) &&
- iwl_mvm_vif_has_esr_cap(mvm, vif);
+ WARN_ON(1);
+ return false;
}
static enum ieee80211_neg_ttlm_res
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
index d9a2801636cf..1100d763ceb6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
@@ -9,40 +9,14 @@
u32 iwl_mvm_sta_fw_id_mask(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
int filter_link_id)
{
- struct ieee80211_link_sta *link_sta;
struct iwl_mvm_sta *mvmsta;
- struct ieee80211_vif *vif;
- unsigned int link_id;
- u32 result = 0;
if (!sta)
return 0;
mvmsta = iwl_mvm_sta_from_mac80211(sta);
- vif = mvmsta->vif;
-
- /* it's easy when the STA is not an MLD */
- if (!sta->valid_links)
- return BIT(mvmsta->deflink.sta_id);
-
- /* but if it is an MLD, get the mask of all the FW STAs it has ... */
- for_each_sta_active_link(vif, sta, link_sta, link_id) {
- struct iwl_mvm_link_sta *mvm_link_sta;
-
- /* unless we have a specific link in mind */
- if (filter_link_id >= 0 && link_id != filter_link_id)
- continue;
-
- mvm_link_sta =
- rcu_dereference_check(mvmsta->link[link_id],
- lockdep_is_held(&mvm->mutex));
- if (!mvm_link_sta)
- continue;
-
- result |= BIT(mvm_link_sta->sta_id);
- }
- return result;
+ return BIT(mvmsta->deflink.sta_id);
}
static int iwl_mvm_mld_send_sta_cmd(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 301d590fe0bd..db5f9804b529 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -120,7 +120,6 @@ struct iwl_mvm_time_event_data {
* if the te is in the time event list or not (when id == TE_MAX)
*/
u32 id;
- s8 link_id;
};
/* Power management */
@@ -380,14 +379,7 @@ struct iwl_mvm_vif_link_info {
* @bcn_prot: beacon protection data (keys; FIXME: needs to be per link)
* @deflink: default link data for use in non-MLO
* @link: link data for each link in MLO
- * @esr_active: indicates eSR mode is active
* @pm_enabled: indicates powersave is enabled
- * @link_selection_res: bitmap of active links as it was decided in the last
- * link selection. Valid only for a MLO vif after assoc. 0 if there wasn't
- * any link selection yet.
- * @link_selection_primary: primary link selected by link selection
- * @primary_link: primary link in eSR. Valid only for an associated MLD vif,
- * and in eSR mode. Valid only for a STA.
* @roc_activity: currently running ROC activity for this vif (or
* ROC_NUM_ACTIVITIES if no activity is running).
* @session_prot_connection_loss: the connection was lost due to session
@@ -434,7 +426,6 @@ struct iwl_mvm_vif {
bool ap_ibss_active;
bool pm_enabled;
bool monitor_active;
- bool esr_active;
bool session_prot_connection_loss;
u8 low_latency: 6;
@@ -515,10 +506,6 @@ struct iwl_mvm_vif {
u16 max_tx_op;
- u16 link_selection_res;
- u8 link_selection_primary;
- u8 primary_link;
-
struct iwl_mvm_vif_link_info deflink;
struct iwl_mvm_vif_link_info *link[IEEE80211_MLD_MAX_NUM_LINKS];
};
@@ -1619,40 +1606,6 @@ static inline bool iwl_mvm_is_ctdp_supported(struct iwl_mvm *mvm)
IWL_UCODE_TLV_CAPA_CTDP_SUPPORT);
}
-static inline bool iwl_mvm_is_esr_supported(struct iwl_trans *trans)
-{
- if (CSR_HW_RFID_IS_CDB(trans->info.hw_rf_id))
- return false;
-
- switch (CSR_HW_RFID_TYPE(trans->info.hw_rf_id)) {
- case IWL_CFG_RF_TYPE_FM:
- /* Step A doesn't support eSR */
- return CSR_HW_RFID_STEP(trans->info.hw_rf_id);
- case IWL_CFG_RF_TYPE_WH:
- case IWL_CFG_RF_TYPE_PE:
- return true;
- default:
- return false;
- }
-}
-
-static inline int iwl_mvm_max_active_links(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif)
-{
- struct iwl_trans *trans = mvm->fwrt.trans;
-
- if (vif->type == NL80211_IFTYPE_AP)
- return mvm->fw->ucode_capa.num_beacons;
-
- /* Check if HW supports eSR or STR */
- if (iwl_mvm_is_esr_supported(trans) ||
- (CSR_HW_RFID_TYPE(trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_FM &&
- CSR_HW_RFID_IS_CDB(trans->info.hw_rf_id)))
- return IWL_FW_MAX_ACTIVE_LINKS_NUM;
-
- return 1;
-}
-
extern const u8 iwl_mvm_ac_to_tx_fifo[];
extern const u8 iwl_mvm_ac_to_gen2_tx_fifo[];
extern const u8 iwl_mvm_ac_to_bz_tx_fifo[];
@@ -2008,15 +1961,6 @@ int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
int iwl_mvm_disable_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf);
-u8 iwl_mvm_get_primary_link(struct ieee80211_vif *vif);
-
-struct iwl_mvm_link_sel_data {
- u8 link_id;
- const struct cfg80211_chan_def *chandef;
- s32 signal;
- u16 grade;
-};
-
#if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS)
extern const struct iwl_hcmd_arr iwl_mvm_groups[];
extern const unsigned int iwl_mvm_groups_size;
@@ -2064,7 +2008,7 @@ int iwl_mvm_cancel_roc(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
/*Session Protection */
void iwl_mvm_protect_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- u32 duration_override, unsigned int link_id);
+ u32 duration_override);
/* Quota management */
static inline size_t iwl_mvm_quota_cmd_size(struct iwl_mvm *mvm)
@@ -2884,8 +2828,6 @@ int iwl_mvm_roc_add_cmd(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
int duration, enum iwl_roc_activity activity);
-/* EMLSR */
-bool iwl_mvm_vif_has_esr_cap(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
void
iwl_mvm_send_ap_tx_power_constraint_cmd(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
index d35c63a673b6..7f0b4f5daa21 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
@@ -2254,17 +2254,9 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
IWL_RX_MPDU_STATUS_STA_ID);
if (!WARN_ON_ONCE(sta_id >= mvm->fw->ucode_capa.num_stations)) {
- struct ieee80211_link_sta *link_sta;
-
sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
if (IS_ERR(sta))
sta = NULL;
- link_sta = rcu_dereference(mvm->fw_id_to_link_sta[sta_id]);
-
- if (sta && sta->valid_links && link_sta) {
- rx_status->link_valid = 1;
- rx_status->link_id = link_sta->link_id;
- }
}
} else if (!is_multicast_ether_addr(hdr->addr2)) {
/*
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index b588f1dcf20d..9c51953d255d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -2568,16 +2568,16 @@ static int iwl_mvm_scan_umac_v14_and_above(struct iwl_mvm *mvm,
bitmap_ssid,
version);
return 0;
- } else {
- pb->preq = params->preq;
}
- cp->flags = iwl_mvm_scan_umac_chan_flags_v2(mvm, params, vif);
- cp->n_aps_override[0] = IWL_SCAN_ADWELL_N_APS_GO_FRIENDLY;
- cp->n_aps_override[1] = IWL_SCAN_ADWELL_N_APS_SOCIAL_CHS;
+ pb->preq = params->preq;
iwl_mvm_umac_scan_fill_6g_chan_list(mvm, params, pb);
+ /* Explicitly clear the flags since most of them are not
+ * relevant for 6 GHz scan.
+ */
+ cp->flags = 0;
cp->count = iwl_mvm_umac_scan_cfg_channels_v7_6g(mvm, params,
params->n_channels,
pb, cp, vif->type,
@@ -3023,12 +3023,8 @@ static int _iwl_mvm_single_scan_start(struct iwl_mvm *mvm,
params.iter_notif = true;
params.tsf_report_link_id = req->tsf_report_link_id;
- if (params.tsf_report_link_id < 0) {
- if (vif->active_links)
- params.tsf_report_link_id = __ffs(vif->active_links);
- else
- params.tsf_report_link_id = 0;
- }
+ if (params.tsf_report_link_id < 0)
+ params.tsf_report_link_id = 0;
iwl_mvm_build_scan_probe(mvm, vif, ies, &params);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
index 36379b738de1..4945ebf19f6b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2014 Intel Mobile Communications GmbH
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2020, 2022-2024 Intel Corporation
+ * Copyright (C) 2018-2020, 2022-2025 Intel Corporation
*/
#include <linux/etherdevice.h>
#include "mvm.h"
@@ -155,7 +155,7 @@ void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD))
iwl_mvm_schedule_session_protection(mvm, vif, duration,
- duration, true, link_id);
+ duration, true);
else
iwl_mvm_protect_session(mvm, vif, duration,
duration, 100, true);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
index 0b12ee8ad618..2b52a4f3bff9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
@@ -42,7 +42,6 @@ void iwl_mvm_te_clear_data(struct iwl_mvm *mvm,
te_data->uid = 0;
te_data->id = TE_MAX;
te_data->vif = NULL;
- te_data->link_id = -1;
}
static void iwl_mvm_cleanup_roc(struct iwl_mvm *mvm)
@@ -721,8 +720,7 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
/* Determine whether mac or link id should be used, and validate the link id */
static int iwl_mvm_get_session_prot_id(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- s8 link_id)
+ struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ver = iwl_fw_lookup_cmd_ver(mvm->fw,
@@ -732,22 +730,18 @@ static int iwl_mvm_get_session_prot_id(struct iwl_mvm *mvm,
if (ver < 2)
return mvmvif->id;
- if (WARN(link_id < 0 || !mvmvif->link[link_id],
- "Invalid link ID for session protection: %u\n", link_id))
- return -EINVAL;
-
- if (WARN(!mvmvif->link[link_id]->active,
- "Session Protection on an inactive link: %u\n", link_id))
+ if (WARN(!mvmvif->deflink.active,
+ "Session Protection on an inactive link\n"))
return -EINVAL;
- return mvmvif->link[link_id]->fw_link_id;
+ return mvmvif->deflink.fw_link_id;
}
static void iwl_mvm_cancel_session_protection(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
- u32 id, s8 link_id)
+ u32 id)
{
- int mac_link_id = iwl_mvm_get_session_prot_id(mvm, vif, link_id);
+ int mac_link_id = iwl_mvm_get_session_prot_id(mvm, vif);
struct iwl_session_prot_cmd cmd = {
.id_and_color = cpu_to_le32(mac_link_id),
.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
@@ -791,7 +785,6 @@ static bool __iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
struct ieee80211_vif *vif = te_data->vif;
struct iwl_mvm_vif *mvmvif;
enum nl80211_iftype iftype;
- s8 link_id;
bool p2p_aux = iwl_mvm_has_p2p_over_aux(mvm);
u8 roc_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
WIDE_ID(MAC_CONF_GROUP, ROC_CMD), 0);
@@ -811,7 +804,6 @@ static bool __iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
/* Save time event uid before clearing its data */
*uid = te_data->uid;
id = te_data->id;
- link_id = te_data->link_id;
/*
* The clear_data function handles time events that were already removed
@@ -837,8 +829,7 @@ static bool __iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
*/
if (mvmvif && id < SESSION_PROTECT_CONF_MAX_ID) {
/* Session protection is still ongoing. Cancel it */
- iwl_mvm_cancel_session_protection(mvm, vif, id,
- link_id);
+ iwl_mvm_cancel_session_protection(mvm, vif, id);
if (iftype == NL80211_IFTYPE_P2P_DEVICE) {
iwl_mvm_roc_finished(mvm);
}
@@ -1007,7 +998,6 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm,
if (!le32_to_cpu(notif->status) || !le32_to_cpu(notif->start)) {
/* End TE, notify mac80211 */
mvmvif->time_event_data.id = SESSION_PROTECT_CONF_MAX_ID;
- mvmvif->time_event_data.link_id = -1;
/* set the bit so the ROC cleanup will actually clean up */
set_bit(IWL_MVM_STATUS_ROC_P2P_RUNNING, &mvm->status);
iwl_mvm_roc_finished(mvm);
@@ -1132,7 +1122,7 @@ iwl_mvm_start_p2p_roc_session_protection(struct iwl_mvm *mvm,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_session_prot_cmd cmd = {
.id_and_color =
- cpu_to_le32(iwl_mvm_get_session_prot_id(mvm, vif, 0)),
+ cpu_to_le32(iwl_mvm_get_session_prot_id(mvm, vif)),
.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
.duration_tu = cpu_to_le32(MSEC_TO_TU(duration)),
};
@@ -1143,8 +1133,6 @@ iwl_mvm_start_p2p_roc_session_protection(struct iwl_mvm *mvm,
* protection's configuration.
*/
- mvmvif->time_event_data.link_id = 0;
-
switch (type) {
case IEEE80211_ROC_TYPE_NORMAL:
mvmvif->time_event_data.id =
@@ -1290,8 +1278,7 @@ void iwl_mvm_stop_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
return;
}
iwl_mvm_cancel_session_protection(mvm, vif,
- te_data->id,
- te_data->link_id);
+ te_data->id);
} else {
iwl_mvm_remove_aux_roc_te(mvm, mvmvif,
&mvmvif->hs_time_event_data);
@@ -1423,14 +1410,13 @@ static bool iwl_mvm_session_prot_notif(struct iwl_notif_wait_data *notif_wait,
void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
u32 duration, u32 min_duration,
- bool wait_for_notif,
- unsigned int link_id)
+ bool wait_for_notif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
const u16 notif[] = { WIDE_ID(MAC_CONF_GROUP, SESSION_PROTECTION_NOTIF) };
struct iwl_notification_wait wait_notif;
- int mac_link_id = iwl_mvm_get_session_prot_id(mvm, vif, (s8)link_id);
+ int mac_link_id = iwl_mvm_get_session_prot_id(mvm, vif);
struct iwl_session_prot_cmd cmd = {
.id_and_color = cpu_to_le32(mac_link_id),
.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
@@ -1444,7 +1430,7 @@ void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex);
spin_lock_bh(&mvm->time_event_lock);
- if (te_data->running && te_data->link_id == link_id &&
+ if (te_data->running &&
time_after(te_data->end_jiffies, TU_TO_EXP_TIME(min_duration))) {
IWL_DEBUG_TE(mvm, "We have enough time in the current TE: %u\n",
jiffies_to_msecs(te_data->end_jiffies - jiffies));
@@ -1461,7 +1447,6 @@ void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
te_data->id = le32_to_cpu(cmd.conf_id);
te_data->duration = le32_to_cpu(cmd.duration_tu);
te_data->vif = vif;
- te_data->link_id = link_id;
spin_unlock_bh(&mvm->time_event_lock);
IWL_DEBUG_TE(mvm, "Add new session protection, duration %d TU\n",
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.h b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.h
index 1ef8768756db..3f8628cbd480 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.h
@@ -210,13 +210,11 @@ iwl_mvm_te_scheduled(struct iwl_mvm_time_event_data *te_data)
* @duration: the requested duration of the protection
* @min_duration: the minimum duration of the protection
* @wait_for_notif: if true, will block until the start of the protection
- * @link_id: The link to schedule a session protection for
*/
void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
u32 duration, u32 min_duration,
- bool wait_for_notif,
- unsigned int link_id);
+ bool wait_for_notif);
/**
* iwl_mvm_rx_session_protect_notif - handles %SESSION_PROTECTION_NOTIF
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index bb97837baeda..bca13417e82c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -817,28 +817,15 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
NL80211_IFTYPE_P2P_DEVICE ||
info.control.vif->type == NL80211_IFTYPE_AP ||
info.control.vif->type == NL80211_IFTYPE_ADHOC) {
- u32 link_id = u32_get_bits(info.control.flags,
- IEEE80211_TX_CTRL_MLO_LINK);
- struct iwl_mvm_vif_link_info *link;
-
- if (link_id == IEEE80211_LINK_UNSPECIFIED) {
- if (info.control.vif->active_links)
- link_id = ffs(info.control.vif->active_links) - 1;
- else
- link_id = 0;
- }
-
- link = mvmvif->link[link_id];
- if (WARN_ON(!link))
- return -1;
if (!ieee80211_is_data(hdr->frame_control))
- sta_id = link->bcast_sta.sta_id;
+ sta_id = mvmvif->deflink.bcast_sta.sta_id;
else
- sta_id = link->mcast_sta.sta_id;
+ sta_id = mvmvif->deflink.mcast_sta.sta_id;
- queue = iwl_mvm_get_ctrl_vif_queue(mvm, link, &info,
- skb);
+ queue = iwl_mvm_get_ctrl_vif_queue(mvm,
+ &mvmvif->deflink,
+ &info, skb);
} else if (info.control.vif->type == NL80211_IFTYPE_MONITOR) {
queue = mvm->snif_queue;
sta_id = mvm->snif_sta.sta_id;
@@ -895,33 +882,9 @@ unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm,
*/
val = mvmsta->max_amsdu_len;
- if (hweight16(sta->valid_links) <= 1) {
- if (sta->valid_links) {
- struct ieee80211_bss_conf *link_conf;
- unsigned int link = ffs(sta->valid_links) - 1;
+ band = mvmsta->vif->bss_conf.chanreq.oper.chan->band;
- rcu_read_lock();
- link_conf = rcu_dereference(mvmsta->vif->link_conf[link]);
- if (WARN_ON(!link_conf))
- band = NL80211_BAND_2GHZ;
- else
- band = link_conf->chanreq.oper.chan->band;
- rcu_read_unlock();
- } else {
- band = mvmsta->vif->bss_conf.chanreq.oper.chan->band;
- }
-
- lmac = iwl_mvm_get_lmac_id(mvm, band);
- } else if (fw_has_capa(&mvm->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_CDB_SUPPORT)) {
- /* for real MLO restrict to both LMACs if they exist */
- lmac = IWL_LMAC_5G_INDEX;
- val = min_t(unsigned int, val,
- mvm->fwrt.smem_cfg.lmac[lmac].txfifo_size[txf] - 256);
- lmac = IWL_LMAC_24G_INDEX;
- } else {
- lmac = IWL_LMAC_24G_INDEX;
- }
+ lmac = iwl_mvm_get_lmac_id(mvm, band);
return min_t(unsigned int, val,
mvm->fwrt.smem_cfg.lmac[lmac].txfifo_size[txf] - 256);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
index 1a6c1f8706e1..4a33a032c2a7 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
@@ -308,10 +308,6 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
smps_mode = IEEE80211_SMPS_DYNAMIC;
}
- /* SMPS is disabled in eSR */
- if (mvmvif->esr_active)
- smps_mode = IEEE80211_SMPS_OFF;
-
ieee80211_request_smps(vif, link_id, smps_mode);
}
diff --git a/drivers/net/wireless/intersil/p54/main.c b/drivers/net/wireless/intersil/p54/main.c
index 2ec3655f1a9c..57a62108cbc3 100644
--- a/drivers/net/wireless/intersil/p54/main.c
+++ b/drivers/net/wireless/intersil/p54/main.c
@@ -143,8 +143,10 @@ static int p54_beacon_update(struct p54_common *priv,
if (!beacon)
return -ENOMEM;
ret = p54_beacon_format_ie_tim(beacon);
- if (ret)
+ if (ret) {
+ dev_kfree_skb_any(beacon);
return ret;
+ }
/*
* During operation, the firmware takes care of beaconing.
diff --git a/drivers/net/wireless/marvell/libertas/if_usb.c b/drivers/net/wireless/marvell/libertas/if_usb.c
index b3c4040257a6..924ab93b7b67 100644
--- a/drivers/net/wireless/marvell/libertas/if_usb.c
+++ b/drivers/net/wireless/marvell/libertas/if_usb.c
@@ -426,6 +426,8 @@ static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb
goto tx_ret;
}
+ usb_kill_urb(cardp->tx_urb);
+
usb_fill_bulk_urb(cardp->tx_urb, cardp->udev,
usb_sndbulkpipe(cardp->udev,
cardp->ep_out),
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index be23a29e7de0..a66d18e380fc 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -3147,10 +3147,14 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
SET_NETDEV_DEV(dev, adapter->dev);
- priv->dfs_cac_workqueue = alloc_workqueue("MWIFIEX_DFS_CAC%s",
+ ret = dev_alloc_name(dev, name);
+ if (ret)
+ goto err_alloc_name;
+
+ priv->dfs_cac_workqueue = alloc_workqueue("MWIFIEX_DFS_CAC-%s",
WQ_HIGHPRI |
WQ_MEM_RECLAIM |
- WQ_UNBOUND, 0, name);
+ WQ_UNBOUND, 0, dev->name);
if (!priv->dfs_cac_workqueue) {
mwifiex_dbg(adapter, ERROR, "cannot alloc DFS CAC queue\n");
ret = -ENOMEM;
@@ -3159,9 +3163,9 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
INIT_DELAYED_WORK(&priv->dfs_cac_work, mwifiex_dfs_cac_work_queue);
- priv->dfs_chan_sw_workqueue = alloc_workqueue("MWIFIEX_DFS_CHSW%s",
+ priv->dfs_chan_sw_workqueue = alloc_workqueue("MWIFIEX_DFS_CHSW-%s",
WQ_HIGHPRI | WQ_UNBOUND |
- WQ_MEM_RECLAIM, 0, name);
+ WQ_MEM_RECLAIM, 0, dev->name);
if (!priv->dfs_chan_sw_workqueue) {
mwifiex_dbg(adapter, ERROR, "cannot alloc DFS channel sw queue\n");
ret = -ENOMEM;
@@ -3198,6 +3202,7 @@ err_alloc_chsw:
destroy_workqueue(priv->dfs_cac_workqueue);
priv->dfs_cac_workqueue = NULL;
err_alloc_cac:
+err_alloc_name:
free_netdev(dev);
priv->netdev = NULL;
err_sta_init:
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/core.c b/drivers/net/wireless/realtek/rtl8xxxu/core.c
index c06ad064f37c..f9a527f6a175 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/core.c
@@ -7826,6 +7826,7 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
goto err_set_intfdata;
hw->vif_data_size = sizeof(struct rtl8xxxu_vif);
+ hw->sta_data_size = sizeof(struct rtl8xxxu_sta_info);
hw->wiphy->max_scan_ssids = 1;
hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
index 4641999f3fe9..e88d92d3ae7a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
@@ -519,16 +519,3 @@ MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>");
MODULE_AUTHOR("Larry Finger <Larry.FInger@lwfinger.net>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core");
-
-static int __init rtl_btcoexist_module_init(void)
-{
- return 0;
-}
-
-static void __exit rtl_btcoexist_module_exit(void)
-{
- return;
-}
-
-module_init(rtl_btcoexist_module_init);
-module_exit(rtl_btcoexist_module_exit);
diff --git a/drivers/net/wireless/realtek/rtlwifi/regd.c b/drivers/net/wireless/realtek/rtlwifi/regd.c
index 0bc4afa4fda3..fd967006b3e1 100644
--- a/drivers/net/wireless/realtek/rtlwifi/regd.c
+++ b/drivers/net/wireless/realtek/rtlwifi/regd.c
@@ -206,7 +206,7 @@ static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy,
}
/*
- *If a country IE has been recieved check its rule for this
+ *If a country IE has been received check its rule for this
*channel first before enabling active scan. The passive scan
*would have been enforced by the initial processing of our
*custom regulatory domain.
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index fa0ed39cb199..c4f9758b4e96 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -730,10 +730,10 @@ void rtw_set_rx_freq_band(struct rtw_rx_pkt_stat *pkt_stat, u8 channel)
}
EXPORT_SYMBOL(rtw_set_rx_freq_band);
-void rtw_set_dtim_period(struct rtw_dev *rtwdev, int dtim_period)
+void rtw_set_dtim_period(struct rtw_dev *rtwdev, u8 dtim_period)
{
rtw_write32_set(rtwdev, REG_TCR, BIT_TCR_UPDATE_TIMIE);
- rtw_write8(rtwdev, REG_DTIM_COUNTER_ROOT, dtim_period - 1);
+ rtw_write8(rtwdev, REG_DTIM_COUNTER_ROOT, dtim_period ? dtim_period - 1 : 0);
}
void rtw_update_channel(struct rtw_dev *rtwdev, u8 center_channel,
@@ -1483,6 +1483,8 @@ void rtw_core_scan_start(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif,
set_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags);
set_bit(RTW_FLAG_SCANNING, rtwdev->flags);
+
+ rtw_phy_dig_set_max_coverage(rtwdev);
}
void rtw_core_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
@@ -1494,6 +1496,7 @@ void rtw_core_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
if (!rtwvif)
return;
+ rtw_phy_dig_reset(rtwdev);
clear_bit(RTW_FLAG_SCANNING, rtwdev->flags);
clear_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags);
@@ -1658,14 +1661,41 @@ static u16 rtw_get_max_scan_ie_len(struct rtw_dev *rtwdev)
return len;
}
+static struct ieee80211_supported_band *
+rtw_sband_dup(struct rtw_dev *rtwdev,
+ const struct ieee80211_supported_band *sband)
+{
+ struct ieee80211_supported_band *dup;
+
+ dup = devm_kmemdup(rtwdev->dev, sband, sizeof(*sband), GFP_KERNEL);
+ if (!dup)
+ return NULL;
+
+ dup->channels = devm_kmemdup_array(rtwdev->dev, sband->channels,
+ sband->n_channels,
+ sizeof(*sband->channels),
+ GFP_KERNEL);
+ if (!dup->channels)
+ return NULL;
+
+ dup->bitrates = devm_kmemdup_array(rtwdev->dev, sband->bitrates,
+ sband->n_bitrates,
+ sizeof(*sband->bitrates),
+ GFP_KERNEL);
+ if (!dup->bitrates)
+ return NULL;
+
+ return dup;
+}
+
static void rtw_set_supported_band(struct ieee80211_hw *hw,
const struct rtw_chip_info *chip)
{
- struct rtw_dev *rtwdev = hw->priv;
struct ieee80211_supported_band *sband;
+ struct rtw_dev *rtwdev = hw->priv;
if (chip->band & RTW_BAND_2G) {
- sband = kmemdup(&rtw_band_2ghz, sizeof(*sband), GFP_KERNEL);
+ sband = rtw_sband_dup(rtwdev, &rtw_band_2ghz);
if (!sband)
goto err_out;
if (chip->ht_supported)
@@ -1674,7 +1704,7 @@ static void rtw_set_supported_band(struct ieee80211_hw *hw,
}
if (chip->band & RTW_BAND_5G) {
- sband = kmemdup(&rtw_band_5ghz, sizeof(*sband), GFP_KERNEL);
+ sband = rtw_sband_dup(rtwdev, &rtw_band_5ghz);
if (!sband)
goto err_out;
if (chip->ht_supported)
@@ -1690,13 +1720,6 @@ err_out:
rtw_err(rtwdev, "failed to set supported band\n");
}
-static void rtw_unset_supported_band(struct ieee80211_hw *hw,
- const struct rtw_chip_info *chip)
-{
- kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]);
- kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]);
-}
-
static void rtw_vif_smps_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
@@ -2320,10 +2343,7 @@ EXPORT_SYMBOL(rtw_register_hw);
void rtw_unregister_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw)
{
- const struct rtw_chip_info *chip = rtwdev->chip;
-
ieee80211_unregister_hw(hw);
- rtw_unset_supported_band(hw, chip);
rtw_debugfs_deinit(rtwdev);
rtw_led_deinit(rtwdev);
}
@@ -2444,10 +2464,10 @@ void rtw_core_enable_beacon(struct rtw_dev *rtwdev, bool enable)
if (enable) {
rtw_write32_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
- rtw_write32_clr(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE);
+ rtw_write8_clr(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE);
} else {
rtw_write32_clr(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
- rtw_write32_set(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE);
+ rtw_write8_set(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE);
}
}
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index 43ed6d6b4291..1ab70214ce36 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -2226,7 +2226,7 @@ enum nl80211_band rtw_hw_to_nl80211_band(enum rtw_supported_band hw_band)
}
void rtw_set_rx_freq_band(struct rtw_rx_pkt_stat *pkt_stat, u8 channel);
-void rtw_set_dtim_period(struct rtw_dev *rtwdev, int dtim_period);
+void rtw_set_dtim_period(struct rtw_dev *rtwdev, u8 dtim_period);
void rtw_get_channel_params(struct cfg80211_chan_def *chandef,
struct rtw_channel_params *ch_param);
bool check_hw_ready(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 target);
diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c
index 55be0d8e0c28..e2ac5c6fd500 100644
--- a/drivers/net/wireless/realtek/rtw88/phy.c
+++ b/drivers/net/wireless/realtek/rtw88/phy.c
@@ -370,6 +370,26 @@ static void rtw_phy_statistics(struct rtw_dev *rtwdev)
#define DIG_CVRG_MIN 0x1c
#define DIG_RSSI_GAIN_OFFSET 15
+void rtw_phy_dig_set_max_coverage(struct rtw_dev *rtwdev)
+{
+ /* Lower values result in greater coverage. */
+ rtw_dbg(rtwdev, RTW_DBG_PHY, "Setting IGI=%#x for max coverage\n",
+ DIG_CVRG_MIN);
+
+ rtw_phy_dig_write(rtwdev, DIG_CVRG_MIN);
+}
+
+void rtw_phy_dig_reset(struct rtw_dev *rtwdev)
+{
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+ u8 last_igi;
+
+ last_igi = dm_info->igi_history[0];
+ rtw_dbg(rtwdev, RTW_DBG_PHY, "Resetting IGI=%#x\n", last_igi);
+
+ rtw_phy_dig_write(rtwdev, last_igi);
+}
+
static bool
rtw_phy_dig_check_damping(struct rtw_dm_info *dm_info)
{
diff --git a/drivers/net/wireless/realtek/rtw88/phy.h b/drivers/net/wireless/realtek/rtw88/phy.h
index c9e6b869661d..8449936497bb 100644
--- a/drivers/net/wireless/realtek/rtw88/phy.h
+++ b/drivers/net/wireless/realtek/rtw88/phy.h
@@ -146,6 +146,8 @@ static inline int rtw_check_supported_rfe(struct rtw_dev *rtwdev)
}
void rtw_phy_dig_write(struct rtw_dev *rtwdev, u8 igi);
+void rtw_phy_dig_reset(struct rtw_dev *rtwdev);
+void rtw_phy_dig_set_max_coverage(struct rtw_dev *rtwdev);
struct rtw_power_params {
u8 pwr_base;
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723cs.c b/drivers/net/wireless/realtek/rtw88/rtw8723cs.c
index 1f98d35a8dd1..2018c9d76dd1 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723cs.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723cs.c
@@ -23,9 +23,9 @@ static struct sdio_driver rtw_8723cs_driver = {
.id_table = rtw_8723cs_id_table,
.probe = rtw_sdio_probe,
.remove = rtw_sdio_remove,
+ .shutdown = rtw_sdio_shutdown,
.drv = {
.pm = &rtw_sdio_pm_ops,
- .shutdown = rtw_sdio_shutdown
}};
module_sdio_driver(rtw_8723cs_driver);
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723ds.c b/drivers/net/wireless/realtek/rtw88/rtw8723ds.c
index 206b77e5b98e..e38c90b769a2 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723ds.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723ds.c
@@ -28,10 +28,10 @@ static struct sdio_driver rtw_8723ds_driver = {
.name = KBUILD_MODNAME,
.probe = rtw_sdio_probe,
.remove = rtw_sdio_remove,
+ .shutdown = rtw_sdio_shutdown,
.id_table = rtw_8723ds_id_table,
.drv = {
.pm = &rtw_sdio_pm_ops,
- .shutdown = rtw_sdio_shutdown,
}
};
module_sdio_driver(rtw_8723ds_driver);
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821cs.c b/drivers/net/wireless/realtek/rtw88/rtw8821cs.c
index 6d94162213c6..58e0ef219cdc 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8821cs.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821cs.c
@@ -23,10 +23,10 @@ static struct sdio_driver rtw_8821cs_driver = {
.name = KBUILD_MODNAME,
.probe = rtw_sdio_probe,
.remove = rtw_sdio_remove,
+ .shutdown = rtw_sdio_shutdown,
.id_table = rtw_8821cs_id_table,
.drv = {
.pm = &rtw_sdio_pm_ops,
- .shutdown = rtw_sdio_shutdown,
}
};
module_sdio_driver(rtw_8821cs_driver);
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821cu.c b/drivers/net/wireless/realtek/rtw88/rtw8821cu.c
index 7a0fffc359e2..8cd09d66655d 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8821cu.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821cu.c
@@ -37,6 +37,8 @@ static const struct usb_device_id rtw_8821cu_id_table[] = {
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* Edimax */
{ USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xd811, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* Edimax */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2c4e, 0x0105, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* Mercusys */
{},
};
MODULE_DEVICE_TABLE(usb, rtw_8821cu_id_table);
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
index 89b6485b229a..4d88cc2f4148 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
@@ -1005,7 +1005,8 @@ static int rtw8822b_set_antenna(struct rtw_dev *rtwdev,
hal->antenna_tx = antenna_tx;
hal->antenna_rx = antenna_rx;
- rtw8822b_config_trx_mode(rtwdev, antenna_tx, antenna_rx, false);
+ if (test_bit(RTW_FLAG_POWERON, rtwdev->flags))
+ rtw8822b_config_trx_mode(rtwdev, antenna_tx, antenna_rx, false);
return 0;
}
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822bs.c b/drivers/net/wireless/realtek/rtw88/rtw8822bs.c
index 744781dcb419..2de9b11540c5 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822bs.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822bs.c
@@ -23,10 +23,10 @@ static struct sdio_driver rtw_8822bs_driver = {
.name = KBUILD_MODNAME,
.probe = rtw_sdio_probe,
.remove = rtw_sdio_remove,
+ .shutdown = rtw_sdio_shutdown,
.id_table = rtw_8822bs_id_table,
.drv = {
.pm = &rtw_sdio_pm_ops,
- .shutdown = rtw_sdio_shutdown,
}
};
module_sdio_driver(rtw_8822bs_driver);
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822cs.c b/drivers/net/wireless/realtek/rtw88/rtw8822cs.c
index 322281e07eb8..b00ef4173962 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822cs.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822cs.c
@@ -23,10 +23,10 @@ static struct sdio_driver rtw_8822cs_driver = {
.name = KBUILD_MODNAME,
.probe = rtw_sdio_probe,
.remove = rtw_sdio_remove,
+ .shutdown = rtw_sdio_shutdown,
.id_table = rtw_8822cs_id_table,
.drv = {
.pm = &rtw_sdio_pm_ops,
- .shutdown = rtw_sdio_shutdown,
}
};
module_sdio_driver(rtw_8822cs_driver);
diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c
index e35de52d8eb4..138e9e348c6c 100644
--- a/drivers/net/wireless/realtek/rtw88/sdio.c
+++ b/drivers/net/wireless/realtek/rtw88/sdio.c
@@ -1414,9 +1414,8 @@ void rtw_sdio_remove(struct sdio_func *sdio_func)
}
EXPORT_SYMBOL(rtw_sdio_remove);
-void rtw_sdio_shutdown(struct device *dev)
+void rtw_sdio_shutdown(struct sdio_func *sdio_func)
{
- struct sdio_func *sdio_func = dev_to_sdio_func(dev);
const struct rtw_chip_info *chip;
struct ieee80211_hw *hw;
struct rtw_dev *rtwdev;
diff --git a/drivers/net/wireless/realtek/rtw88/sdio.h b/drivers/net/wireless/realtek/rtw88/sdio.h
index 3c659ed180f0..457e8b02380e 100644
--- a/drivers/net/wireless/realtek/rtw88/sdio.h
+++ b/drivers/net/wireless/realtek/rtw88/sdio.h
@@ -166,7 +166,7 @@ extern const struct dev_pm_ops rtw_sdio_pm_ops;
int rtw_sdio_probe(struct sdio_func *sdio_func,
const struct sdio_device_id *id);
void rtw_sdio_remove(struct sdio_func *sdio_func);
-void rtw_sdio_shutdown(struct device *dev);
+void rtw_sdio_shutdown(struct sdio_func *sdio_func);
static inline bool rtw_sdio_is_sdio30_supported(struct rtw_dev *rtwdev)
{
diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
index 3b5126ffc81a..db60e142268d 100644
--- a/drivers/net/wireless/realtek/rtw88/usb.c
+++ b/drivers/net/wireless/realtek/rtw88/usb.c
@@ -965,7 +965,8 @@ static int rtw_usb_init_rx(struct rtw_dev *rtwdev)
struct sk_buff *rx_skb;
int i;
- rtwusb->rxwq = alloc_workqueue("rtw88_usb: rx wq", WQ_BH, 0);
+ rtwusb->rxwq = alloc_workqueue("rtw88_usb: rx wq", WQ_BH | WQ_PERCPU,
+ 0);
if (!rtwusb->rxwq) {
rtw_err(rtwdev, "failed to create RX work queue\n");
return -ENOMEM;
diff --git a/drivers/net/wireless/realtek/rtw89/cam.c b/drivers/net/wireless/realtek/rtw89/cam.c
index 9370cbda945c..9f63d67777fa 100644
--- a/drivers/net/wireless/realtek/rtw89/cam.c
+++ b/drivers/net/wireless/realtek/rtw89/cam.c
@@ -1140,3 +1140,137 @@ void rtw89_cam_fill_dctl_sec_cam_info_v2(struct rtw89_dev *rtwdev,
le32_encode_bits(mld_bssid[5], DCTLINFO_V2_W12_MLD_BSSID_5);
h2c->m12 = cpu_to_le32(DCTLINFO_V2_W12_ALL);
}
+
+void rtw89_cam_fill_dctl_sec_cam_info_v3(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
+ struct rtw89_h2c_dctlinfo_ud_v3 *h2c)
+{
+ struct ieee80211_sta *sta = rtwsta_link_to_sta_safe(rtwsta_link);
+ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link->rtwvif);
+ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
+ struct rtw89_addr_cam_entry *addr_cam =
+ rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link);
+ bool is_mld = sta ? sta->mlo : ieee80211_vif_is_mld(vif);
+ struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
+ u8 *ptk_tx_iv = rtw_wow->key_info.ptk_tx_iv;
+ u8 *mld_sma, *mld_tma, *mld_bssid;
+
+ h2c->c0 = le32_encode_bits(rtwsta_link ? rtwsta_link->mac_id :
+ rtwvif_link->mac_id,
+ DCTLINFO_V3_C0_MACID) |
+ le32_encode_bits(1, DCTLINFO_V3_C0_OP);
+
+ h2c->w2 = le32_encode_bits(is_mld, DCTLINFO_V3_W2_IS_MLD);
+ h2c->m2 = cpu_to_le32(DCTLINFO_V3_W2_IS_MLD);
+
+ h2c->w4 = le32_encode_bits(addr_cam->sec_ent_keyid[0],
+ DCTLINFO_V3_W4_SEC_ENT0_KEYID) |
+ le32_encode_bits(addr_cam->sec_ent_keyid[1],
+ DCTLINFO_V3_W4_SEC_ENT1_KEYID) |
+ le32_encode_bits(addr_cam->sec_ent_keyid[2],
+ DCTLINFO_V3_W4_SEC_ENT2_KEYID) |
+ le32_encode_bits(addr_cam->sec_ent_keyid[3],
+ DCTLINFO_V3_W4_SEC_ENT3_KEYID) |
+ le32_encode_bits(addr_cam->sec_ent_keyid[4],
+ DCTLINFO_V3_W4_SEC_ENT4_KEYID) |
+ le32_encode_bits(addr_cam->sec_ent_keyid[5],
+ DCTLINFO_V3_W4_SEC_ENT5_KEYID) |
+ le32_encode_bits(addr_cam->sec_ent_keyid[6],
+ DCTLINFO_V3_W4_SEC_ENT6_KEYID);
+ h2c->m4 = cpu_to_le32(DCTLINFO_V3_W4_SEC_ENT0_KEYID |
+ DCTLINFO_V3_W4_SEC_ENT1_KEYID |
+ DCTLINFO_V3_W4_SEC_ENT2_KEYID |
+ DCTLINFO_V3_W4_SEC_ENT3_KEYID |
+ DCTLINFO_V3_W4_SEC_ENT4_KEYID |
+ DCTLINFO_V3_W4_SEC_ENT5_KEYID |
+ DCTLINFO_V3_W4_SEC_ENT6_KEYID);
+
+ h2c->w5 = le32_encode_bits(addr_cam->sec_cam_map[0],
+ DCTLINFO_V3_W5_SEC_ENT_VALID_V1);
+ h2c->m5 = cpu_to_le32(DCTLINFO_V3_W5_SEC_ENT_VALID_V1);
+
+ h2c->w6 = le32_encode_bits(addr_cam->sec_ent[0],
+ DCTLINFO_V3_W6_SEC_ENT0_V2) |
+ le32_encode_bits(addr_cam->sec_ent[1],
+ DCTLINFO_V3_W6_SEC_ENT1_V2) |
+ le32_encode_bits(addr_cam->sec_ent[2],
+ DCTLINFO_V3_W6_SEC_ENT2_V2);
+ h2c->m6 = cpu_to_le32(DCTLINFO_V3_W6_SEC_ENT0_V2 |
+ DCTLINFO_V3_W6_SEC_ENT1_V2 |
+ DCTLINFO_V3_W6_SEC_ENT2_V2);
+
+ h2c->w7 = le32_encode_bits(addr_cam->sec_ent[3],
+ DCTLINFO_V3_W7_SEC_ENT3_V2) |
+ le32_encode_bits(addr_cam->sec_ent[4],
+ DCTLINFO_V3_W7_SEC_ENT4_V2) |
+ le32_encode_bits(addr_cam->sec_ent[5],
+ DCTLINFO_V3_W7_SEC_ENT5_V2);
+ h2c->m7 = cpu_to_le32(DCTLINFO_V3_W7_SEC_ENT3_V2 |
+ DCTLINFO_V3_W7_SEC_ENT4_V2 |
+ DCTLINFO_V3_W7_SEC_ENT5_V2);
+
+ h2c->w8 = le32_encode_bits(addr_cam->sec_ent[6],
+ DCTLINFO_V3_W8_SEC_ENT6_V2);
+ h2c->m8 = cpu_to_le32(DCTLINFO_V3_W8_SEC_ENT6_V2);
+
+ if (rtw_wow->ptk_alg) {
+ h2c->w0 = le32_encode_bits(ptk_tx_iv[0] | ptk_tx_iv[1] << 8,
+ DCTLINFO_V3_W0_AES_IV_L);
+ h2c->m0 = cpu_to_le32(DCTLINFO_V3_W0_AES_IV_L);
+
+ h2c->w1 = le32_encode_bits(ptk_tx_iv[4] |
+ ptk_tx_iv[5] << 8 |
+ ptk_tx_iv[6] << 16 |
+ ptk_tx_iv[7] << 24,
+ DCTLINFO_V3_W1_AES_IV_H);
+ h2c->m1 = cpu_to_le32(DCTLINFO_V3_W1_AES_IV_H);
+
+ h2c->w4 |= le32_encode_bits(rtw_wow->ptk_keyidx,
+ DCTLINFO_V3_W4_SEC_KEY_ID);
+ h2c->m4 |= cpu_to_le32(DCTLINFO_V3_W4_SEC_KEY_ID);
+ }
+
+ if (!is_mld)
+ return;
+
+ if (rtwvif_link->net_type == RTW89_NET_TYPE_INFRA) {
+ mld_sma = rtwvif->mac_addr;
+ mld_tma = vif->cfg.ap_addr;
+ mld_bssid = vif->cfg.ap_addr;
+ } else if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE && sta) {
+ mld_sma = rtwvif->mac_addr;
+ mld_tma = sta->addr;
+ mld_bssid = rtwvif->mac_addr;
+ } else {
+ return;
+ }
+
+ h2c->w9 = le32_encode_bits(mld_sma[0], DCTLINFO_V3_W9_MLD_SMA_0_V2) |
+ le32_encode_bits(mld_sma[1], DCTLINFO_V3_W9_MLD_SMA_1_V2) |
+ le32_encode_bits(mld_sma[2], DCTLINFO_V3_W9_MLD_SMA_2_V2) |
+ le32_encode_bits(mld_sma[3], DCTLINFO_V3_W9_MLD_SMA_3_V2);
+ h2c->m9 = cpu_to_le32(DCTLINFO_V3_W9_ALL);
+
+ h2c->w10 = le32_encode_bits(mld_sma[4], DCTLINFO_V3_W10_MLD_SMA_4_V2) |
+ le32_encode_bits(mld_sma[5], DCTLINFO_V3_W10_MLD_SMA_5_V2) |
+ le32_encode_bits(mld_tma[0], DCTLINFO_V3_W10_MLD_TMA_0_V2) |
+ le32_encode_bits(mld_tma[1], DCTLINFO_V3_W10_MLD_TMA_1_V2);
+ h2c->m10 = cpu_to_le32(DCTLINFO_V3_W10_ALL);
+
+ h2c->w11 = le32_encode_bits(mld_tma[2], DCTLINFO_V3_W11_MLD_TMA_2_V2) |
+ le32_encode_bits(mld_tma[3], DCTLINFO_V3_W11_MLD_TMA_3_V2) |
+ le32_encode_bits(mld_tma[4], DCTLINFO_V3_W11_MLD_TMA_4_V2) |
+ le32_encode_bits(mld_tma[5], DCTLINFO_V3_W11_MLD_TMA_5_V2);
+ h2c->m11 = cpu_to_le32(DCTLINFO_V3_W11_ALL);
+
+ h2c->w12 = le32_encode_bits(mld_bssid[0], DCTLINFO_V3_W12_MLD_TA_BSSID_0_V2) |
+ le32_encode_bits(mld_bssid[1], DCTLINFO_V3_W12_MLD_TA_BSSID_1_V2) |
+ le32_encode_bits(mld_bssid[2], DCTLINFO_V3_W12_MLD_TA_BSSID_2_V2) |
+ le32_encode_bits(mld_bssid[3], DCTLINFO_V3_W12_MLD_TA_BSSID_3_V2);
+ h2c->m12 = cpu_to_le32(DCTLINFO_V3_W12_ALL);
+
+ h2c->w13 = le32_encode_bits(mld_bssid[4], DCTLINFO_V3_W13_MLD_TA_BSSID_4_V2) |
+ le32_encode_bits(mld_bssid[5], DCTLINFO_V3_W13_MLD_TA_BSSID_5_V2);
+ h2c->m13 = cpu_to_le32(DCTLINFO_V3_W13_ALL);
+}
diff --git a/drivers/net/wireless/realtek/rtw89/cam.h b/drivers/net/wireless/realtek/rtw89/cam.h
index c46b6f91bbdb..22868f262243 100644
--- a/drivers/net/wireless/realtek/rtw89/cam.h
+++ b/drivers/net/wireless/realtek/rtw89/cam.h
@@ -302,6 +302,131 @@ struct rtw89_h2c_dctlinfo_ud_v2 {
#define DCTLINFO_V2_W12_MLD_BSSID_5 GENMASK(15, 8)
#define DCTLINFO_V2_W12_ALL GENMASK(15, 0)
+struct rtw89_h2c_dctlinfo_ud_v3 {
+ __le32 c0;
+ __le32 w0;
+ __le32 w1;
+ __le32 w2;
+ __le32 w3;
+ __le32 w4;
+ __le32 w5;
+ __le32 w6;
+ __le32 w7;
+ __le32 w8;
+ __le32 w9;
+ __le32 w10;
+ __le32 w11;
+ __le32 w12;
+ __le32 w13;
+ __le32 w14;
+ __le32 w15;
+ __le32 m0;
+ __le32 m1;
+ __le32 m2;
+ __le32 m3;
+ __le32 m4;
+ __le32 m5;
+ __le32 m6;
+ __le32 m7;
+ __le32 m8;
+ __le32 m9;
+ __le32 m10;
+ __le32 m11;
+ __le32 m12;
+ __le32 m13;
+ __le32 m14;
+ __le32 m15;
+} __packed;
+
+#define DCTLINFO_V3_C0_MACID GENMASK(15, 0)
+#define DCTLINFO_V3_C0_OP BIT(16)
+
+#define DCTLINFO_V3_W0_QOS_FIELD_H GENMASK(7, 0)
+#define DCTLINFO_V3_W0_HW_EXSEQ_MACID GENMASK(14, 8)
+#define DCTLINFO_V3_W0_QOS_DATA BIT(15)
+#define DCTLINFO_V3_W0_AES_IV_L GENMASK(31, 16)
+#define DCTLINFO_V3_W0_ALL GENMASK(31, 0)
+#define DCTLINFO_V3_W1_AES_IV_H GENMASK(31, 0)
+#define DCTLINFO_V3_W1_ALL GENMASK(31, 0)
+#define DCTLINFO_V3_W2_SEQ0 GENMASK(11, 0)
+#define DCTLINFO_V3_W2_SEQ1 GENMASK(23, 12)
+#define DCTLINFO_V3_W2_AMSDU_MAX_LEN GENMASK(26, 24)
+#define DCTLINFO_V3_W2_STA_AMSDU_EN BIT(27)
+#define DCTLINFO_V3_W2_CHKSUM_OFLD_EN BIT(28)
+#define DCTLINFO_V3_W2_WITH_LLC BIT(29)
+#define DCTLINFO_V3_W2_NAT25_EN BIT(30)
+#define DCTLINFO_V3_W2_IS_MLD BIT(31)
+#define DCTLINFO_V3_W2_ALL GENMASK(31, 0)
+#define DCTLINFO_V3_W3_SEQ2 GENMASK(11, 0)
+#define DCTLINFO_V3_W3_SEQ3 GENMASK(23, 12)
+#define DCTLINFO_V3_W3_TGT_IND GENMASK(27, 24)
+#define DCTLINFO_V3_W3_TGT_IND_EN BIT(28)
+#define DCTLINFO_V3_W3_HTC_LB GENMASK(31, 29)
+#define DCTLINFO_V3_W3_ALL GENMASK(31, 0)
+#define DCTLINFO_V3_W4_VLAN_TAG_SEL GENMASK(7, 5)
+#define DCTLINFO_V3_W4_HTC_ORDER BIT(8)
+#define DCTLINFO_V3_W4_SEC_KEY_ID GENMASK(10, 9)
+#define DCTLINFO_V3_W4_VLAN_RX_DYNAMIC_PCP_EN BIT(11)
+#define DCTLINFO_V3_W4_VLAN_RX_PKT_DROP BIT(12)
+#define DCTLINFO_V3_W4_VLAN_RX_VALID BIT(13)
+#define DCTLINFO_V3_W4_VLAN_TX_VALID BIT(14)
+#define DCTLINFO_V3_W4_WAPI BIT(15)
+#define DCTLINFO_V3_W4_SEC_ENT_MODE GENMASK(17, 16)
+#define DCTLINFO_V3_W4_SEC_ENT0_KEYID GENMASK(19, 18)
+#define DCTLINFO_V3_W4_SEC_ENT1_KEYID GENMASK(21, 20)
+#define DCTLINFO_V3_W4_SEC_ENT2_KEYID GENMASK(23, 22)
+#define DCTLINFO_V3_W4_SEC_ENT3_KEYID GENMASK(25, 24)
+#define DCTLINFO_V3_W4_SEC_ENT4_KEYID GENMASK(27, 26)
+#define DCTLINFO_V3_W4_SEC_ENT5_KEYID GENMASK(29, 28)
+#define DCTLINFO_V3_W4_SEC_ENT6_KEYID GENMASK(31, 30)
+#define DCTLINFO_V3_W4_ALL GENMASK(31, 5)
+#define DCTLINFO_V3_W5_SEC_ENT7_KEYID GENMASK(1, 0)
+#define DCTLINFO_V3_W5_SEC_ENT8_KEYID GENMASK(3, 2)
+#define DCTLINFO_V3_W5_SEC_ENT_VALID_V1 GENMASK(23, 8)
+#define DCTLINFO_V3_W5_ALL (GENMASK(23, 8) | GENMASK(3, 0))
+#define DCTLINFO_V3_W6_SEC_ENT0_V2 GENMASK(8, 0)
+#define DCTLINFO_V3_W6_SEC_ENT1_V2 GENMASK(18, 10)
+#define DCTLINFO_V3_W6_SEC_ENT2_V2 GENMASK(28, 20)
+#define DCTLINFO_V3_W6_ALL GENMASK(28, 0)
+#define DCTLINFO_V3_W7_SEC_ENT3_V2 GENMASK(8, 0)
+#define DCTLINFO_V3_W7_SEC_ENT4_V2 GENMASK(18, 10)
+#define DCTLINFO_V3_W7_SEC_ENT5_V2 GENMASK(28, 20)
+#define DCTLINFO_V3_W7_ALL GENMASK(28, 0)
+#define DCTLINFO_V3_W8_SEC_ENT6_V2 GENMASK(8, 0)
+#define DCTLINFO_V3_W8_SEC_ENT7_V1 GENMASK(18, 10)
+#define DCTLINFO_V3_W8_SEC_ENT8_V1 GENMASK(28, 20)
+#define DCTLINFO_V3_W8_ALL GENMASK(28, 0)
+#define DCTLINFO_V3_W9_MLD_SMA_0_V2 GENMASK(7, 0)
+#define DCTLINFO_V3_W9_MLD_SMA_1_V2 GENMASK(15, 8)
+#define DCTLINFO_V3_W9_MLD_SMA_2_V2 GENMASK(23, 16)
+#define DCTLINFO_V3_W9_MLD_SMA_3_V2 GENMASK(31, 24)
+#define DCTLINFO_V3_W9_MLD_SMA_L_V2 GENMASK(31, 0)
+#define DCTLINFO_V3_W9_ALL GENMASK(31, 0)
+#define DCTLINFO_V3_W10_MLD_SMA_4_V2 GENMASK(7, 0)
+#define DCTLINFO_V3_W10_MLD_SMA_5_V2 GENMASK(15, 8)
+#define DCTLINFO_V3_W10_MLD_SMA_H_V2 GENMASK(15, 0)
+#define DCTLINFO_V3_W10_MLD_TMA_0_V2 GENMASK(23, 16)
+#define DCTLINFO_V3_W10_MLD_TMA_1_V2 GENMASK(31, 24)
+#define DCTLINFO_V3_W10_MLD_TMA_L_V2 GENMASK(31, 16)
+#define DCTLINFO_V3_W10_ALL GENMASK(31, 0)
+#define DCTLINFO_V3_W11_MLD_TMA_2_V2 GENMASK(7, 0)
+#define DCTLINFO_V3_W11_MLD_TMA_3_V2 GENMASK(15, 8)
+#define DCTLINFO_V3_W11_MLD_TMA_4_V2 GENMASK(23, 16)
+#define DCTLINFO_V3_W11_MLD_TMA_5_V2 GENMASK(31, 24)
+#define DCTLINFO_V3_W11_MLD_TMA_H_V2 GENMASK(31, 0)
+#define DCTLINFO_V3_W11_ALL GENMASK(31, 0)
+#define DCTLINFO_V3_W12_MLD_TA_BSSID_0_V2 GENMASK(7, 0)
+#define DCTLINFO_V3_W12_MLD_TA_BSSID_1_V2 GENMASK(15, 8)
+#define DCTLINFO_V3_W12_MLD_TA_BSSID_2_V2 GENMASK(23, 16)
+#define DCTLINFO_V3_W12_MLD_TA_BSSID_3_V2 GENMASK(31, 24)
+#define DCTLINFO_V3_W12_MLD_TA_BSSID_L_V2 GENMASK(31, 0)
+#define DCTLINFO_V3_W12_ALL GENMASK(31, 0)
+#define DCTLINFO_V3_W13_MLD_TA_BSSID_4_V2 GENMASK(7, 0)
+#define DCTLINFO_V3_W13_MLD_TA_BSSID_5_V2 GENMASK(15, 8)
+#define DCTLINFO_V3_W13_MLD_TA_BSSID_H_V2 GENMASK(15, 0)
+#define DCTLINFO_V3_W13_HW_EXSEQ_MACID_V1 GENMASK(24, 16)
+#define DCTLINFO_V3_W13_ALL GENMASK(24, 0)
+
int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif);
void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif);
int rtw89_cam_init_addr_cam(struct rtw89_dev *rtwdev,
@@ -328,6 +453,10 @@ void rtw89_cam_fill_dctl_sec_cam_info_v2(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_link,
struct rtw89_h2c_dctlinfo_ud_v2 *h2c);
+void rtw89_cam_fill_dctl_sec_cam_info_v3(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
+ struct rtw89_h2c_dctlinfo_ud_v3 *h2c);
int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_link,
diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c
index 86f1b39a967f..9b2f6f0a00fd 100644
--- a/drivers/net/wireless/realtek/rtw89/chan.c
+++ b/drivers/net/wireless/realtek/rtw89/chan.c
@@ -60,6 +60,28 @@ static enum rtw89_subband rtw89_get_subband_type(enum rtw89_band band,
}
}
+static enum rtw89_tx_comp_band rtw89_get_tx_comp_band(enum rtw89_band band,
+ u8 center_chan)
+{
+ switch (band) {
+ default:
+ case RTW89_BAND_2G:
+ return RTW89_TX_COMP_BAND_2GHZ;
+ case RTW89_BAND_5G:
+ if (center_chan < 149)
+ return RTW89_TX_COMP_BAND_5GHZ_L;
+ else
+ return RTW89_TX_COMP_BAND_5GHZ_H;
+ case RTW89_BAND_6G:
+ if (center_chan < 65)
+ return RTW89_TX_COMP_BAND_5GHZ_H;
+ else if (center_chan < 193)
+ return RTW89_TX_COMP_BAND_6GHZ_M;
+ else
+ return RTW89_TX_COMP_BAND_6GHZ_UH;
+ }
+}
+
static enum rtw89_sc_offset rtw89_get_primary_chan_idx(enum rtw89_bandwidth bw,
u32 center_freq,
u32 primary_freq)
@@ -123,6 +145,7 @@ void rtw89_chan_create(struct rtw89_chan *chan, u8 center_chan, u8 primary_chan,
chan->freq = center_freq;
chan->subband_type = rtw89_get_subband_type(band, center_chan);
+ chan->tx_comp_band = rtw89_get_tx_comp_band(band, center_chan);
chan->pri_ch_idx = rtw89_get_primary_chan_idx(bandwidth, center_freq,
primary_freq);
chan->pri_sb_idx = rtw89_get_primary_sb_idx(center_chan, primary_chan,
@@ -295,6 +318,8 @@ void rtw89_entity_init(struct rtw89_dev *rtwdev)
mgnt->chanctx_tbl[i][j] = RTW89_CHANCTX_IDLE;
}
+ hal->entity_force_hw = RTW89_PHY_NUM;
+
rtw89_config_default_chandef(rtwdev);
}
@@ -347,8 +372,8 @@ static void rtw89_normalize_link_chanctx(struct rtw89_dev *rtwdev,
if (unlikely(!rtwvif_link->chanctx_assigned))
return;
- cur = rtw89_vif_get_link_inst(rtwvif, 0);
- if (!cur || !cur->chanctx_assigned)
+ cur = rtw89_get_designated_link(rtwvif);
+ if (unlikely(!cur) || !cur->chanctx_assigned)
return;
if (cur == rtwvif_link)
@@ -417,12 +442,43 @@ dflt:
}
EXPORT_SYMBOL(__rtw89_mgnt_chan_get);
+bool rtw89_entity_check_hw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
+{
+ switch (rtwdev->mlo_dbcc_mode) {
+ case MLO_2_PLUS_0_1RF:
+ return phy_idx == RTW89_PHY_0;
+ case MLO_0_PLUS_2_1RF:
+ return phy_idx == RTW89_PHY_1;
+ default:
+ return false;
+ }
+}
+
+void rtw89_entity_force_hw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
+{
+ rtwdev->hal.entity_force_hw = phy_idx;
+
+ if (phy_idx != RTW89_PHY_NUM)
+ rtw89_debug(rtwdev, RTW89_DBG_CHAN, "%s: %d\n", __func__, phy_idx);
+ else
+ rtw89_debug(rtwdev, RTW89_DBG_CHAN, "%s: (none)\n", __func__);
+}
+
static enum rtw89_mlo_dbcc_mode
rtw89_entity_sel_mlo_dbcc_mode(struct rtw89_dev *rtwdev, u8 active_hws)
{
if (rtwdev->chip->chip_gen != RTW89_CHIP_BE)
return MLO_DBCC_NOT_SUPPORT;
+ switch (rtwdev->hal.entity_force_hw) {
+ case RTW89_PHY_0:
+ return MLO_2_PLUS_0_1RF;
+ case RTW89_PHY_1:
+ return MLO_0_PLUS_2_1RF;
+ default:
+ break;
+ }
+
switch (active_hws) {
case BIT(0):
return MLO_2_PLUS_0_1RF;
@@ -466,8 +522,8 @@ static void rtw89_entity_recalc_mgnt_roles(struct rtw89_dev *rtwdev)
}
/* To be consistent with legacy behavior, expect the first active role
- * which uses RTW89_CHANCTX_0 to put at position 0, and make its first
- * link instance take RTW89_CHANCTX_0. (normalizing)
+ * which uses RTW89_CHANCTX_0 to put at position 0 and its designated
+ * link take RTW89_CHANCTX_0. (normalizing)
*/
list_for_each_entry(role, &mgnt->active_list, mgnt_entry) {
for (i = 0; i < role->links_inst_valid_num; i++) {
@@ -2608,17 +2664,20 @@ bool rtw89_mcc_detect_go_bcn(struct rtw89_dev *rtwdev,
static void rtw89_mcc_detect_connection(struct rtw89_dev *rtwdev,
struct rtw89_mcc_role *role)
{
+ struct rtw89_vif_link *rtwvif_link = role->rtwvif_link;
struct ieee80211_vif *vif;
bool start_detect;
int ret;
ret = rtw89_core_send_nullfunc(rtwdev, role->rtwvif_link, true, false,
RTW89_MCC_PROBE_TIMEOUT);
- if (ret)
+ if (ret &&
+ READ_ONCE(rtwvif_link->sync_bcn_tsf) == rtwvif_link->last_sync_bcn_tsf)
role->probe_count++;
else
role->probe_count = 0;
+ rtwvif_link->last_sync_bcn_tsf = READ_ONCE(rtwvif_link->sync_bcn_tsf);
if (role->probe_count < RTW89_MCC_PROBE_MAX_TRIES)
return;
diff --git a/drivers/net/wireless/realtek/rtw89/chan.h b/drivers/net/wireless/realtek/rtw89/chan.h
index 5b22764d5329..c797cda2e763 100644
--- a/drivers/net/wireless/realtek/rtw89/chan.h
+++ b/drivers/net/wireless/realtek/rtw89/chan.h
@@ -166,6 +166,8 @@ void rtw89_config_roc_chandef(struct rtw89_dev *rtwdev,
const struct cfg80211_chan_def *chandef);
void rtw89_entity_init(struct rtw89_dev *rtwdev);
enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev);
+bool rtw89_entity_check_hw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
+void rtw89_entity_force_hw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
void rtw89_chanctx_work(struct wiphy *wiphy, struct wiphy_work *work);
void rtw89_queue_chanctx_work(struct rtw89_dev *rtwdev);
void rtw89_queue_chanctx_change(struct rtw89_dev *rtwdev,
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 0824940c91ae..6e77522bcd8f 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -470,6 +470,32 @@ void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev)
__rtw89_core_set_chip_txpwr(rtwdev, chan, RTW89_PHY_1);
}
+void rtw89_chip_rfk_channel(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ bool mon = !!rtwdev->pure_monitor_mode_vif;
+ bool prehdl_link = false;
+
+ if (chip->chip_gen != RTW89_CHIP_AX &&
+ !RTW89_CHK_FW_FEATURE_GROUP(WITH_RFK_PRE_NOTIFY, &rtwdev->fw) &&
+ !mon && !rtw89_entity_check_hw(rtwdev, rtwvif_link->phy_idx))
+ prehdl_link = true;
+
+ if (prehdl_link) {
+ rtw89_entity_force_hw(rtwdev, rtwvif_link->phy_idx);
+ rtw89_set_channel(rtwdev);
+ }
+
+ if (chip->ops->rfk_channel)
+ chip->ops->rfk_channel(rtwdev, rtwvif_link);
+
+ if (prehdl_link) {
+ rtw89_entity_force_hw(rtwdev, RTW89_PHY_NUM);
+ rtw89_set_channel(rtwdev);
+ }
+}
+
static void rtw89_chip_rfk_channel_for_pure_mon_vif(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx)
{
@@ -548,7 +574,7 @@ rtw89_core_get_tx_type(struct rtw89_dev *rtwdev,
struct ieee80211_hdr *hdr = (void *)skb->data;
__le16 fc = hdr->frame_control;
- if (ieee80211_is_mgmt(fc) || ieee80211_is_nullfunc(fc))
+ if (ieee80211_is_mgmt(fc) || ieee80211_is_any_nullfunc(fc))
return RTW89_CORE_TX_TYPE_MGMT;
return RTW89_CORE_TX_TYPE_DATA;
@@ -833,6 +859,7 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev,
desc_info->qsel = qsel;
desc_info->ch_dma = ch_dma;
+ desc_info->sw_mld = true;
desc_info->port = desc_info->hiq ? rtwvif_link->port : 0;
desc_info->mac_id = rtw89_core_tx_get_mac_id(rtwdev, tx_req);
desc_info->hw_ssn_sel = RTW89_MGMT_HW_SSN_SEL;
@@ -1051,6 +1078,7 @@ rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev,
desc_info->ch_dma = ch_dma;
desc_info->tid_indicate = tid_indicate;
desc_info->qsel = qsel;
+ desc_info->sw_mld = false;
desc_info->mac_id = rtw89_core_tx_get_mac_id(rtwdev, tx_req);
desc_info->port = desc_info->hiq ? rtwvif_link->port : 0;
desc_info->er_cap = rtwsta_link ? rtwsta_link->er_cap : false;
@@ -1207,7 +1235,7 @@ rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev,
if (addr_cam->valid && desc_info->mlo)
upd_wlan_hdr = true;
- if (rtw89_is_tx_rpt_skb(rtwdev, tx_req->skb))
+ if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS || tx_req->with_wait)
rtw89_tx_rpt_init(rtwdev, tx_req);
is_bmc = (is_broadcast_ether_addr(hdr->addr1) ||
@@ -1326,7 +1354,7 @@ int rtw89_h2c_tx(struct rtw89_dev *rtwdev,
static int rtw89_core_tx_write_link(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_link,
- struct sk_buff *skb, int *qsel, bool sw_mld,
+ struct sk_buff *skb, int *qsel,
struct rtw89_tx_wait_info *wait)
{
struct ieee80211_sta *sta = rtwsta_link_to_sta_safe(rtwsta_link);
@@ -1341,14 +1369,15 @@ static int rtw89_core_tx_write_link(struct rtw89_dev *rtwdev,
tx_req.sta = sta;
tx_req.rtwvif_link = rtwvif_link;
tx_req.rtwsta_link = rtwsta_link;
- tx_req.desc_info.sw_mld = sw_mld;
- rcu_assign_pointer(skb_data->wait, wait);
+ tx_req.with_wait = !!wait;
rtw89_traffic_stats_accu(rtwdev, rtwvif, skb, true, true);
rtw89_wow_parse_akm(rtwdev, skb);
rtw89_core_tx_update_desc_info(rtwdev, &tx_req);
rtw89_core_tx_wake(rtwdev, &tx_req);
+ rcu_assign_pointer(skb_data->wait, wait);
+
ret = rtw89_hci_tx_write(rtwdev, &tx_req);
if (ret) {
rtw89_err(rtwdev, "failed to transmit skb to HCI\n");
@@ -1385,8 +1414,7 @@ int rtw89_core_tx_write(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
}
}
- return rtw89_core_tx_write_link(rtwdev, rtwvif_link, rtwsta_link, skb, qsel, false,
- NULL);
+ return rtw89_core_tx_write_link(rtwdev, rtwvif_link, rtwsta_link, skb, qsel, NULL);
}
static __le32 rtw89_build_txwd_body0(struct rtw89_tx_desc_info *desc_info)
@@ -1631,6 +1659,17 @@ static __le32 rtw89_build_txwd_body2_v2(struct rtw89_tx_desc_info *desc_info)
return cpu_to_le32(dword);
}
+static __le32 rtw89_build_txwd_body2_v3(struct rtw89_tx_desc_info *desc_info)
+{
+ u32 dword = FIELD_PREP(BE_TXD_BODY2_TID_IND_V1, desc_info->tid_indicate) |
+ FIELD_PREP(BE_TXD_BODY2_QSEL_V1, desc_info->qsel) |
+ FIELD_PREP(BE_TXD_BODY2_TXPKTSIZE, desc_info->pkt_size) |
+ FIELD_PREP(BE_TXD_BODY2_AGG_EN, desc_info->agg_en) |
+ FIELD_PREP(BE_TXD_BODY2_MACID_V1, desc_info->mac_id);
+
+ return cpu_to_le32(dword);
+}
+
static __le32 rtw89_build_txwd_body3_v2(struct rtw89_tx_desc_info *desc_info)
{
u32 dword = FIELD_PREP(BE_TXD_BODY3_WIFI_SEQ, desc_info->seq) |
@@ -1640,6 +1679,16 @@ static __le32 rtw89_build_txwd_body3_v2(struct rtw89_tx_desc_info *desc_info)
return cpu_to_le32(dword);
}
+static __le32 rtw89_build_txwd_body3_v3(struct rtw89_tx_desc_info *desc_info)
+{
+ u32 dword = FIELD_PREP(BE_TXD_BODY3_WIFI_SEQ, desc_info->seq) |
+ FIELD_PREP(BE_TXD_BODY3_MLO_FLAG, desc_info->mlo) |
+ FIELD_PREP(BE_TXD_BODY3_IS_MLD_SW_EN, desc_info->sw_mld) |
+ FIELD_PREP(BE_TXD_BODY3_BK_V1, desc_info->bk);
+
+ return cpu_to_le32(dword);
+}
+
static __le32 rtw89_build_txwd_body4_v2(struct rtw89_tx_desc_info *desc_info)
{
u32 dword = FIELD_PREP(BE_TXD_BODY4_SEC_IV_L0, desc_info->sec_seq[0]) |
@@ -1711,6 +1760,15 @@ static __le32 rtw89_build_txwd_info2_v2(struct rtw89_tx_desc_info *desc_info)
return cpu_to_le32(dword);
}
+static __le32 rtw89_build_txwd_info2_v3(struct rtw89_tx_desc_info *desc_info)
+{
+ u32 dword = FIELD_PREP(BE_TXD_INFO2_AMPDU_DENSITY, desc_info->ampdu_density) |
+ FIELD_PREP(BE_TXD_INFO2_FORCE_KEY_EN_V1, desc_info->sec_en) |
+ FIELD_PREP(BE_TXD_INFO2_SEC_CAM_IDX_V1, desc_info->sec_cam_idx);
+
+ return cpu_to_le32(dword);
+}
+
static __le32 rtw89_build_txwd_info4_v2(struct rtw89_tx_desc_info *desc_info)
{
bool rts_en = !desc_info->is_bmc;
@@ -1749,6 +1807,35 @@ void rtw89_core_fill_txdesc_v2(struct rtw89_dev *rtwdev,
}
EXPORT_SYMBOL(rtw89_core_fill_txdesc_v2);
+void rtw89_core_fill_txdesc_v3(struct rtw89_dev *rtwdev,
+ struct rtw89_tx_desc_info *desc_info,
+ void *txdesc)
+{
+ struct rtw89_txwd_body_v2 *txwd_body = txdesc;
+ struct rtw89_txwd_info_v2 *txwd_info;
+
+ txwd_body->dword0 = rtw89_build_txwd_body0_v2(desc_info);
+ txwd_body->dword1 = rtw89_build_txwd_body1_v2(desc_info);
+ txwd_body->dword2 = rtw89_build_txwd_body2_v3(desc_info);
+ txwd_body->dword3 = rtw89_build_txwd_body3_v3(desc_info);
+ if (desc_info->sec_en) {
+ txwd_body->dword4 = rtw89_build_txwd_body4_v2(desc_info);
+ txwd_body->dword5 = rtw89_build_txwd_body5_v2(desc_info);
+ }
+ txwd_body->dword6 = rtw89_build_txwd_body6_v2(desc_info);
+ txwd_body->dword7 = rtw89_build_txwd_body7_v2(desc_info);
+
+ if (!desc_info->en_wd_info)
+ return;
+
+ txwd_info = (struct rtw89_txwd_info_v2 *)(txwd_body + 1);
+ txwd_info->dword0 = rtw89_build_txwd_info0_v2(desc_info);
+ txwd_info->dword1 = rtw89_build_txwd_info1_v2(desc_info);
+ txwd_info->dword2 = rtw89_build_txwd_info2_v3(desc_info);
+ txwd_info->dword4 = rtw89_build_txwd_info4_v2(desc_info);
+}
+EXPORT_SYMBOL(rtw89_core_fill_txdesc_v3);
+
static __le32 rtw89_build_txwd_fwcmd0_v1(struct rtw89_tx_desc_info *desc_info)
{
u32 dword = FIELD_PREP(AX_RXD_RPKT_LEN_MASK, desc_info->pkt_size) |
@@ -2785,7 +2872,7 @@ static void rtw89_core_bcn_track_assoc(struct rtw89_dev *rtwdev,
rcu_read_lock();
bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
- beacon_int = bss_conf->beacon_int;
+ beacon_int = bss_conf->beacon_int ?: 100;
dtim = bss_conf->dtim_period;
rcu_read_unlock();
@@ -2815,9 +2902,7 @@ static void rtw89_core_bcn_track_reset(struct rtw89_dev *rtwdev)
memset(&rtwdev->bcn_track, 0, sizeof(rtwdev->bcn_track));
}
-static void rtw89_vif_rx_bcn_stat(struct rtw89_dev *rtwdev,
- struct ieee80211_bss_conf *bss_conf,
- struct sk_buff *skb)
+static void rtw89_vif_rx_bcn_stat(struct rtw89_dev *rtwdev, struct sk_buff *skb)
{
#define RTW89_APPEND_TSF_2GHZ 384
#define RTW89_APPEND_TSF_5GHZ 52
@@ -2826,7 +2911,7 @@ static void rtw89_vif_rx_bcn_stat(struct rtw89_dev *rtwdev,
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
struct rtw89_beacon_stat *bcn_stat = &rtwdev->phystat.bcn_stat;
struct rtw89_beacon_track_info *bcn_track = &rtwdev->bcn_track;
- u32 bcn_intvl_us = ieee80211_tu_to_usec(bss_conf->beacon_int);
+ u32 bcn_intvl_us = ieee80211_tu_to_usec(bcn_track->beacon_int);
u64 tsf = le64_to_cpu(mgmt->u.beacon.timestamp);
u8 wp, num = bcn_stat->num;
u16 append;
@@ -2834,6 +2919,10 @@ static void rtw89_vif_rx_bcn_stat(struct rtw89_dev *rtwdev,
if (!RTW89_CHK_FW_FEATURE(BEACON_TRACKING, &rtwdev->fw))
return;
+ /* Skip if not yet associated */
+ if (!bcn_intvl_us)
+ return;
+
switch (rx_status->band) {
default:
case NL80211_BAND_2GHZ:
@@ -2921,7 +3010,7 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
pkt_stat->beacon_rate = desc_info->data_rate;
pkt_stat->beacon_len = skb->len;
- rtw89_vif_rx_bcn_stat(rtwdev, bss_conf, skb);
+ rtw89_vif_rx_bcn_stat(rtwdev, skb);
}
if (!ether_addr_equal(bss_conf->addr, hdr->addr1))
@@ -3408,6 +3497,79 @@ void rtw89_core_query_rxdesc_v2(struct rtw89_dev *rtwdev,
}
EXPORT_SYMBOL(rtw89_core_query_rxdesc_v2);
+void rtw89_core_query_rxdesc_v3(struct rtw89_dev *rtwdev,
+ struct rtw89_rx_desc_info *desc_info,
+ u8 *data, u32 data_offset)
+{
+ struct rtw89_rxdesc_phy_rpt_v2 *rxd_rpt;
+ struct rtw89_rxdesc_short_v3 *rxd_s;
+ struct rtw89_rxdesc_long_v3 *rxd_l;
+ u16 shift_len, drv_info_len, phy_rtp_len, hdr_cnv_len;
+
+ rxd_s = (struct rtw89_rxdesc_short_v3 *)(data + data_offset);
+
+ desc_info->pkt_size = le32_get_bits(rxd_s->dword0, BE_RXD_RPKT_LEN_MASK);
+ desc_info->drv_info_size = le32_get_bits(rxd_s->dword0, BE_RXD_DRV_INFO_SZ_MASK);
+ desc_info->phy_rpt_size = le32_get_bits(rxd_s->dword0, BE_RXD_PHY_RPT_SZ_MASK);
+ desc_info->hdr_cnv_size = le32_get_bits(rxd_s->dword0, BE_RXD_HDR_CNV_SZ_MASK);
+ desc_info->shift = le32_get_bits(rxd_s->dword0, BE_RXD_SHIFT_MASK);
+ desc_info->long_rxdesc = le32_get_bits(rxd_s->dword0, BE_RXD_LONG_RXD);
+ desc_info->pkt_type = le32_get_bits(rxd_s->dword0, BE_RXD_RPKT_TYPE_MASK);
+ desc_info->bb_sel = le32_get_bits(rxd_s->dword0, BE_RXD_BB_SEL);
+ if (desc_info->pkt_type == RTW89_CORE_RX_TYPE_PPDU_STAT)
+ desc_info->mac_info_valid = true;
+
+ desc_info->frame_type = le32_get_bits(rxd_s->dword2, BE_RXD_TYPE_MASK);
+ desc_info->mac_id = le32_get_bits(rxd_s->dword2, BE_RXD_MAC_ID_V1);
+ desc_info->addr_cam_valid = le32_get_bits(rxd_s->dword2, BE_RXD_ADDR_CAM_VLD);
+
+ desc_info->icv_err = le32_get_bits(rxd_s->dword3, BE_RXD_ICV_ERR);
+ desc_info->crc32_err = le32_get_bits(rxd_s->dword3, BE_RXD_CRC32_ERR);
+ desc_info->hw_dec = le32_get_bits(rxd_s->dword3, BE_RXD_HW_DEC);
+ desc_info->sw_dec = le32_get_bits(rxd_s->dword3, BE_RXD_SW_DEC);
+ desc_info->addr1_match = le32_get_bits(rxd_s->dword3, BE_RXD_A1_MATCH);
+
+ desc_info->bw = le32_get_bits(rxd_s->dword4, BE_RXD_BW_MASK);
+ desc_info->data_rate = le32_get_bits(rxd_s->dword4, BE_RXD_RX_DATARATE_MASK);
+ desc_info->gi_ltf = le32_get_bits(rxd_s->dword4, BE_RXD_RX_GI_LTF_MASK);
+ desc_info->ppdu_cnt = le32_get_bits(rxd_s->dword4, BE_RXD_PPDU_CNT_MASK);
+ desc_info->ppdu_type = le32_get_bits(rxd_s->dword4, BE_RXD_PPDU_TYPE_MASK);
+
+ desc_info->free_run_cnt = le32_to_cpu(rxd_s->dword5);
+
+ shift_len = desc_info->shift << 1; /* 2-byte unit */
+ drv_info_len = desc_info->drv_info_size << 3; /* 8-byte unit */
+ phy_rtp_len = desc_info->phy_rpt_size << 3; /* 8-byte unit */
+ hdr_cnv_len = desc_info->hdr_cnv_size << 4; /* 16-byte unit */
+ desc_info->offset = data_offset + shift_len + drv_info_len +
+ phy_rtp_len + hdr_cnv_len;
+
+ if (desc_info->long_rxdesc)
+ desc_info->rxd_len = sizeof(struct rtw89_rxdesc_long_v3);
+ else
+ desc_info->rxd_len = sizeof(struct rtw89_rxdesc_short_v3);
+ desc_info->ready = true;
+
+ if (phy_rtp_len == sizeof(*rxd_rpt)) {
+ rxd_rpt = (struct rtw89_rxdesc_phy_rpt_v2 *)(data + data_offset +
+ desc_info->rxd_len);
+ desc_info->rssi = le32_get_bits(rxd_rpt->dword0, BE_RXD_PHY_RSSI);
+ }
+
+ if (!desc_info->long_rxdesc)
+ return;
+
+ rxd_l = (struct rtw89_rxdesc_long_v3 *)(data + data_offset);
+
+ desc_info->sr_en = le32_get_bits(rxd_l->dword6, BE_RXD_SR_EN);
+ desc_info->user_id = le32_get_bits(rxd_l->dword6, BE_RXD_USER_ID_MASK);
+ desc_info->addr_cam_id = le32_get_bits(rxd_l->dword6, BE_RXD_ADDR_CAM_V1);
+ desc_info->sec_cam_id = le32_get_bits(rxd_l->dword6, BE_RXD_SEC_CAM_IDX_V1);
+
+ desc_info->rx_pl_id = le32_get_bits(rxd_l->dword7, BE_RXD_RX_PL_ID_MASK);
+}
+EXPORT_SYMBOL(rtw89_core_query_rxdesc_v3);
+
struct rtw89_core_iter_rx_status {
struct rtw89_dev *rtwdev;
struct ieee80211_rx_status *rx_status;
@@ -4091,8 +4253,7 @@ int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rt
goto out;
}
- ret = rtw89_core_tx_write_link(rtwdev, rtwvif_link, rtwsta_link, skb, &qsel, true,
- wait);
+ ret = rtw89_core_tx_write_link(rtwdev, rtwvif_link, rtwsta_link, skb, &qsel, wait);
if (ret) {
rtw89_warn(rtwdev, "nullfunc transmit failed: %d\n", ret);
dev_kfree_skb_any(skb);
@@ -5085,7 +5246,7 @@ static void rtw89_init_vht_cap(struct rtw89_dev *rtwdev,
}
vht_cap->vht_supported = true;
- vht_cap->cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
+ vht_cap->cap = chip->max_vht_mpdu_cap |
IEEE80211_VHT_CAP_SHORT_GI_80 |
IEEE80211_VHT_CAP_RXSTBC_1 |
IEEE80211_VHT_CAP_HTC_VHT |
@@ -5213,7 +5374,7 @@ static void rtw89_init_he_cap(struct rtw89_dev *rtwdev,
IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) |
le16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K,
IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) |
- le16_encode_bits(IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454,
+ le16_encode_bits(chip->max_vht_mpdu_cap,
IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN);
iftype_data->he_6ghz_capa.capa = capa;
}
@@ -5234,7 +5395,7 @@ static void rtw89_init_eht_cap(struct rtw89_dev *rtwdev,
u8 val, val_mcs13;
int sts = 8;
- if (chip->chip_gen == RTW89_CHIP_AX)
+ if (chip->chip_gen == RTW89_CHIP_AX || hal->no_eht)
return;
if (hal->no_mcs_12_13)
@@ -5251,7 +5412,7 @@ static void rtw89_init_eht_cap(struct rtw89_dev *rtwdev,
eht_cap->has_eht = true;
eht_cap_elem->mac_cap_info[0] =
- u8_encode_bits(IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_7991,
+ u8_encode_bits(chip->max_eht_mpdu_cap,
IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK);
eht_cap_elem->mac_cap_info[1] = 0;
@@ -5657,6 +5818,7 @@ int rtw89_core_start(struct rtw89_dev *rtwdev)
rtw89_phy_dm_init(rtwdev);
+ rtw89_mac_set_edcca_mode_bands(rtwdev, true);
rtw89_mac_cfg_ppdu_status_bands(rtwdev, true);
rtw89_mac_cfg_phy_rpt_bands(rtwdev, true);
rtw89_mac_update_rts_threshold(rtwdev);
@@ -5923,6 +6085,9 @@ int rtw89_core_init(struct rtw89_dev *rtwdev)
struct rtw89_btc *btc = &rtwdev->btc;
u8 band;
+ bitmap_or(rtwdev->quirks, rtwdev->quirks, &rtwdev->chip->default_quirks,
+ NUM_OF_RTW89_QUIRKS);
+
INIT_LIST_HEAD(&rtwdev->ba_list);
INIT_LIST_HEAD(&rtwdev->forbid_ba_list);
INIT_LIST_HEAD(&rtwdev->rtwvifs_list);
@@ -6080,7 +6245,9 @@ void rtw89_core_scan_complete(struct rtw89_dev *rtwdev,
static void rtw89_read_chip_ver(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
+ struct rtw89_hal *hal = &rtwdev->hal;
int ret;
+ u8 val2;
u8 val;
u8 cv;
@@ -6092,14 +6259,28 @@ static void rtw89_read_chip_ver(struct rtw89_dev *rtwdev)
cv = CHIP_CBV;
}
- rtwdev->hal.cv = cv;
+ hal->cv = cv;
- if (rtw89_is_rtl885xb(rtwdev)) {
+ if (rtw89_is_rtl885xb(rtwdev) || chip->chip_gen >= RTW89_CHIP_BE) {
ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_CV, &val);
if (ret)
return;
- rtwdev->hal.acv = u8_get_bits(val, XTAL_SI_ACV_MASK);
+ hal->acv = u8_get_bits(val, XTAL_SI_ACV_MASK);
+ }
+
+ if (chip->chip_gen >= RTW89_CHIP_BE) {
+ hal->cid =
+ rtw89_read32_mask(rtwdev, R_BE_SYS_CHIPINFO, B_BE_HW_ID_MASK);
+
+ ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_CHIP_ID_L, &val);
+ if (ret)
+ return;
+ ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_CHIP_ID_H, &val2);
+ if (ret)
+ return;
+
+ hal->aid = val | val2 << 8;
}
}
@@ -6198,7 +6379,8 @@ int rtw89_core_mlsr_switch(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
goto wake_queue;
}
- rtw89_chip_rfk_channel(rtwdev, target);
+ if (RTW89_CHK_FW_FEATURE_GROUP(WITH_RFK_PRE_NOTIFY, &rtwdev->fw))
+ rtw89_chip_rfk_channel(rtwdev, target);
rtwvif->mlo_mode = RTW89_MLO_MODE_MLSR;
@@ -6309,6 +6491,8 @@ void rtw89_core_rfkill_poll(struct rtw89_dev *rtwdev, bool force)
int rtw89_chip_info_setup(struct rtw89_dev *rtwdev)
{
+ struct rtw89_efuse *efuse = &rtwdev->efuse;
+ struct rtw89_hal *hal = &rtwdev->hal;
int ret;
rtw89_read_chip_ver(rtwdev);
@@ -6348,6 +6532,9 @@ int rtw89_chip_info_setup(struct rtw89_dev *rtwdev)
rtw89_core_setup_rfe_parms(rtwdev);
rtwdev->ps_mode = rtw89_update_ps_mode(rtwdev);
+ rtw89_info(rtwdev, "chip info CID: %x, CV: %x, AID: %x, ACV: %x, RFE: %d\n",
+ hal->cid, hal->cv, hal->aid, hal->acv, efuse->rfe_type);
+
out:
rtw89_mac_pwr_off(rtwdev);
@@ -6398,8 +6585,8 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
hw->extra_tx_headroom = tx_headroom;
hw->queues = IEEE80211_NUM_ACS;
- hw->max_rx_aggregation_subframes = RTW89_MAX_RX_AGG_NUM;
- hw->max_tx_aggregation_subframes = RTW89_MAX_TX_AGG_NUM;
+ hw->max_rx_aggregation_subframes = chip->max_rx_agg_num;
+ hw->max_tx_aggregation_subframes = chip->max_tx_agg_num;
hw->uapsd_max_sp_len = IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL;
hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_FEC |
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index a9cb47ea0b93..4778957d6b2d 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -23,8 +23,10 @@ struct rtw89_efuse_block_cfg;
struct rtw89_h2c_rf_tssi;
struct rtw89_fw_txpwr_track_cfg;
struct rtw89_phy_rfk_log_fmt;
+struct rtw89_phy_calc_efuse_gain;
struct rtw89_debugfs;
struct rtw89_regd_data;
+struct rtw89_wow_cam_info;
extern const struct ieee80211_ops rtw89_ops;
@@ -113,6 +115,16 @@ enum rtw89_subband {
RTW89_SUBBAND_2GHZ_5GHZ_NR = RTW89_CH_5G_BAND_4 + 1,
};
+enum rtw89_tx_comp_band {
+ RTW89_TX_COMP_BAND_2GHZ,
+ RTW89_TX_COMP_BAND_5GHZ_L,
+ RTW89_TX_COMP_BAND_5GHZ_H,
+ RTW89_TX_COMP_BAND_6GHZ_M,
+ RTW89_TX_COMP_BAND_6GHZ_UH,
+
+ RTW89_TX_COMP_BAND_NR,
+};
+
enum rtw89_gain_offset {
RTW89_GAIN_OFFSET_2G_CCK,
RTW89_GAIN_OFFSET_2G_OFDM,
@@ -158,6 +170,17 @@ enum rtw89_core_chip_id {
RTL8922D,
};
+enum rtw89_core_chip_cid {
+ RTL8922D_CID7025 = 0x74,
+ RTL8922D_CID7090 = 0x79,
+};
+
+enum rtw89_core_chip_aid {
+ RTL8922D_AID1348 = 0x1348,
+ RTL8922D_AID7060 = 0x7060,
+ RTL8922D_AID7102 = 0x7102,
+};
+
enum rtw89_chip_gen {
RTW89_CHIP_AX,
RTW89_CHIP_BE,
@@ -978,6 +1001,7 @@ struct rtw89_chan {
*/
u32 freq;
enum rtw89_subband subband_type;
+ enum rtw89_tx_comp_band tx_comp_band;
enum rtw89_sc_offset pri_ch_idx;
u8 pri_sb_idx;
};
@@ -1125,6 +1149,15 @@ struct rtw89_rxdesc_short_v2 {
__le32 dword5;
} __packed;
+struct rtw89_rxdesc_short_v3 {
+ __le32 dword0;
+ __le32 dword1;
+ __le32 dword2;
+ __le32 dword3;
+ __le32 dword4;
+ __le32 dword5;
+} __packed;
+
struct rtw89_rxdesc_long {
__le32 dword0;
__le32 dword1;
@@ -1149,6 +1182,19 @@ struct rtw89_rxdesc_long_v2 {
__le32 dword9;
} __packed;
+struct rtw89_rxdesc_long_v3 {
+ __le32 dword0;
+ __le32 dword1;
+ __le32 dword2;
+ __le32 dword3;
+ __le32 dword4;
+ __le32 dword5;
+ __le32 dword6;
+ __le32 dword7;
+ __le32 dword8;
+ __le32 dword9;
+} __packed;
+
struct rtw89_rxdesc_phy_rpt_v2 {
__le32 dword0;
__le32 dword1;
@@ -1211,6 +1257,8 @@ struct rtw89_core_tx_request {
struct rtw89_vif_link *rtwvif_link;
struct rtw89_sta_link *rtwsta_link;
struct rtw89_tx_desc_info desc_info;
+
+ bool with_wait;
};
struct rtw89_txq {
@@ -3404,9 +3452,6 @@ struct rtw89_ra_info {
#define RTW89_PPDU_MAC_RX_CNT_SIZE 96
#define RTW89_PPDU_MAC_RX_CNT_SIZE_V1 128
-#define RTW89_MAX_RX_AGG_NUM 64
-#define RTW89_MAX_TX_AGG_NUM 128
-
struct rtw89_ampdu_params {
u16 agg_num;
bool amsdu;
@@ -3789,6 +3834,11 @@ struct rtw89_chip_ops {
s8 pw_ofst, enum rtw89_mac_idx mac_idx);
void (*digital_pwr_comp)(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx);
+ void (*calc_rx_gain_normal)(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_rf_path path,
+ enum rtw89_phy_idx phy_idx,
+ struct rtw89_phy_calc_efuse_gain *calc);
int (*pwr_on_func)(struct rtw89_dev *rtwdev);
int (*pwr_off_func)(struct rtw89_dev *rtwdev);
void (*query_rxdesc)(struct rtw89_dev *rtwdev,
@@ -3833,6 +3883,8 @@ struct rtw89_chip_ops {
struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_link,
bool valid, struct ieee80211_ampdu_params *params);
+ int (*h2c_wow_cam_update)(struct rtw89_dev *rtwdev,
+ struct rtw89_wow_cam_info *cam_info);
void (*btc_set_rfe)(struct rtw89_dev *rtwdev);
void (*btc_init_cfg)(struct rtw89_dev *rtwdev);
@@ -3965,6 +4017,11 @@ struct rtw89_hfc_prec_cfg {
u8 h2c_full_cond;
u8 wp_ch07_full_cond;
u8 wp_ch811_full_cond;
+ /* for WiFi 7 chips after 8922D */
+ u16 ch011_full_page;
+ u16 h2c_full_page;
+ u16 wp_ch07_full_page;
+ u16 wp_ch811_full_page;
};
struct rtw89_hfc_param {
@@ -3989,13 +4046,14 @@ struct rtw89_dle_size {
u16 pge_size;
u16 lnk_pge_num;
u16 unlnk_pge_num;
- /* for WiFi 7 chips below */
+ /* for WiFi 7 chips below (suffix v1) */
u32 srt_ofst;
};
struct rtw89_wde_quota {
u16 hif;
u16 wcpu;
+ /* unused dcpu isn't listed */
u16 pkt_in;
u16 cpu_io;
};
@@ -4013,8 +4071,10 @@ struct rtw89_ple_quota {
u16 wd_rel;
u16 cpu_io;
u16 tx_rpt;
- /* for WiFi 7 chips below */
+ /* for WiFi 7 chips below (suffix v1) */
u16 h2d;
+ /* for WiFi 7 chips after 8922D (suffix v2) */
+ u16 snrpt;
};
struct rtw89_rsvd_quota {
@@ -4035,6 +4095,17 @@ struct rtw89_dle_rsvd_size {
u32 size;
};
+struct rtw89_dle_input {
+ u32 tx_ampdu_num_b0;
+ u32 tx_ampdu_num_b1;
+ u32 tx_amsdu_size; /* unit: KB */
+ u32 h2c_max_size;
+ u32 rx_amsdu_size; /* unit: KB */
+ u32 c2h_max_size;
+ u32 mpdu_info_tbl_b0;
+ u32 mpdu_info_tbl_b1;
+};
+
struct rtw89_dle_mem {
enum rtw89_qta_mode mode;
const struct rtw89_dle_size *wde_size;
@@ -4047,6 +4118,8 @@ struct rtw89_dle_mem {
const struct rtw89_rsvd_quota *rsvd_qt;
const struct rtw89_dle_rsvd_size *rsvd0_size;
const struct rtw89_dle_rsvd_size *rsvd1_size;
+ /* for WiFi 7 chips after 8922D */
+ const struct rtw89_dle_input *dle_input;
};
struct rtw89_reg_def {
@@ -4325,6 +4398,13 @@ struct rtw89_rfkill_regs {
struct rtw89_reg3_def mode;
};
+struct rtw89_sb_regs {
+ struct {
+ u32 cfg;
+ u32 get;
+ } n[2];
+};
+
struct rtw89_dig_regs {
u32 seg0_pd_reg;
u32 pd_lower_bound_mask;
@@ -4424,6 +4504,10 @@ struct rtw89_chip_info {
bool small_fifo_size;
u32 dle_scc_rsvd_size;
u16 max_amsdu_limit;
+ u16 max_vht_mpdu_cap;
+ u16 max_eht_mpdu_cap;
+ u16 max_tx_agg_num;
+ u16 max_rx_agg_num;
bool dis_2g_40m_ul_ofdma;
u32 rsvd_ple_ofst;
const struct rtw89_hfc_param_ini *hfc_param_ini[RTW89_HCI_TYPE_NUM];
@@ -4538,10 +4622,12 @@ struct rtw89_chip_info {
u32 bss_clr_map_reg;
const struct rtw89_rfkill_regs *rfkill_init;
struct rtw89_reg_def rfkill_get;
+ struct rtw89_sb_regs btc_sb;
u32 dma_ch_mask;
const struct rtw89_edcca_regs *edcca_regs;
const struct wiphy_wowlan_support *wowlan_stub;
const struct rtw89_xtal_info *xtal_info;
+ unsigned long default_quirks; /* bitmap of rtw89_quirks */
};
struct rtw89_chip_variant {
@@ -4572,6 +4658,7 @@ enum rtw89_hcifc_mode {
struct rtw89_dle_info {
const struct rtw89_rsvd_quota *rsvd_qt;
+ const struct rtw89_dle_input *dle_input;
enum rtw89_qta_mode qta_mode;
u16 ple_pg_size;
u16 ple_free_pg;
@@ -4664,8 +4751,17 @@ enum rtw89_fw_feature {
RTW89_FW_FEATURE_MACID_PAUSE_SLEEP,
RTW89_FW_FEATURE_SCAN_OFFLOAD_BE_V0,
RTW89_FW_FEATURE_WOW_REASON_V1,
- RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V0,
- RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V1,
+ RTW89_FW_FEATURE_GROUP(WITH_RFK_PRE_NOTIFY,
+ RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V0,
+ RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V1,
+ RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V2,
+ RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V3,
+ ),
+ RTW89_FW_FEATURE_GROUP(WITH_RFK_PRE_NOTIFY_MCC,
+ RTW89_FW_FEATURE_RFK_PRE_NOTIFY_MCC_V0,
+ RTW89_FW_FEATURE_RFK_PRE_NOTIFY_MCC_V1,
+ RTW89_FW_FEATURE_RFK_PRE_NOTIFY_MCC_V2,
+ ),
RTW89_FW_FEATURE_RFK_RXDCK_V0,
RTW89_FW_FEATURE_RFK_IQK_V0,
RTW89_FW_FEATURE_NO_WOW_CPU_IO_RX,
@@ -4680,6 +4776,11 @@ enum rtw89_fw_feature {
RTW89_FW_FEATURE_LPS_DACK_BY_C2H_REG,
RTW89_FW_FEATURE_BEACON_TRACKING,
RTW89_FW_FEATURE_ADDR_CAM_V0,
+ RTW89_FW_FEATURE_SER_L1_BY_EVENT,
+ RTW89_FW_FEATURE_SIM_SER_L0L1_BY_HALT_H2C,
+ RTW89_FW_FEATURE_LPS_ML_INFO_V1,
+
+ NUM_OF_RTW89_FW_FEATURES,
};
struct rtw89_fw_suit {
@@ -4741,6 +4842,7 @@ struct rtw89_fw_elm_info {
const struct rtw89_regd_data *regd;
const struct rtw89_fw_element_hdr *afe;
const struct rtw89_fw_element_hdr *diag_mac;
+ const struct rtw89_fw_element_hdr *tx_comp;
};
enum rtw89_fw_mss_dev_type {
@@ -4771,20 +4873,28 @@ struct rtw89_fw_info {
struct rtw89_fw_suit bbmcu0;
struct rtw89_fw_suit bbmcu1;
struct rtw89_fw_log log;
- u32 feature_map;
struct rtw89_fw_elm_info elm_info;
struct rtw89_fw_secure sec;
+
+ DECLARE_BITMAP(feature_map, NUM_OF_RTW89_FW_FEATURES);
};
#define RTW89_CHK_FW_FEATURE(_feat, _fw) \
- (!!((_fw)->feature_map & BIT(RTW89_FW_FEATURE_ ## _feat)))
+ test_bit(RTW89_FW_FEATURE_ ## _feat, (_fw)->feature_map)
#define RTW89_CHK_FW_FEATURE_GROUP(_grp, _fw) \
- (!!((_fw)->feature_map & GENMASK(RTW89_FW_FEATURE_ ## _grp ## _MAX, \
- RTW89_FW_FEATURE_ ## _grp ## _MIN)))
+({ \
+ unsigned int bit = find_next_bit((_fw)->feature_map, \
+ NUM_OF_RTW89_FW_FEATURES, \
+ RTW89_FW_FEATURE_ ## _grp ## _MIN); \
+ bit <= RTW89_FW_FEATURE_ ## _grp ## _MAX; \
+})
#define RTW89_SET_FW_FEATURE(_fw_feature, _fw) \
- ((_fw)->feature_map |= BIT(_fw_feature))
+ set_bit(_fw_feature, (_fw)->feature_map)
+
+#define RTW89_CLR_FW_FEATURE(_fw_feature, _fw) \
+ clear_bit(_fw_feature, (_fw)->feature_map)
struct rtw89_cam_info {
DECLARE_BITMAP(addr_cam_map, RTW89_MAX_ADDR_CAM_NUM);
@@ -5026,7 +5136,9 @@ enum rtw89_dm_type {
struct rtw89_hal {
u32 rx_fltr;
u8 cv;
+ u8 cid; /* enum rtw89_core_chip_cid */
u8 acv;
+ u16 aid; /* enum rtw89_core_chip_aid */
u32 antenna_tx;
u32 antenna_rx;
u8 tx_nss;
@@ -5037,6 +5149,7 @@ struct rtw89_hal {
bool support_cckpd;
bool support_igi;
bool no_mcs_12_13;
+ bool no_eht;
atomic_t roc_chanctx_idx;
u8 roc_link_index;
@@ -5051,6 +5164,8 @@ struct rtw89_hal {
enum rtw89_entity_mode entity_mode;
struct rtw89_entity_mgnt entity_mgnt;
+ enum rtw89_phy_idx entity_force_hw;
+
u32 disabled_dm_bitmap; /* bitmap of enum rtw89_dm_type */
u8 thermal_prot_th;
@@ -5065,6 +5180,8 @@ enum rtw89_flags {
RTW89_FLAG_DMAC_FUNC,
RTW89_FLAG_CMAC0_FUNC,
RTW89_FLAG_CMAC1_FUNC,
+ RTW89_FLAG_CMAC0_PWR,
+ RTW89_FLAG_CMAC1_PWR,
RTW89_FLAG_FW_RDY,
RTW89_FLAG_RUNNING,
RTW89_FLAG_PROBE_DONE,
@@ -5095,13 +5212,15 @@ enum rtw89_quirks {
};
enum rtw89_custid {
- RTW89_CUSTID_NONE,
- RTW89_CUSTID_ACER,
- RTW89_CUSTID_AMD,
- RTW89_CUSTID_ASUS,
- RTW89_CUSTID_DELL,
- RTW89_CUSTID_HP,
- RTW89_CUSTID_LENOVO,
+ RTW89_CUSTID_NONE = 0,
+ RTW89_CUSTID_HP = 1,
+ RTW89_CUSTID_ASUS = 2,
+ RTW89_CUSTID_ACER = 3,
+ RTW89_CUSTID_LENOVO = 4,
+ RTW89_CUSTID_NEC = 5,
+ RTW89_CUSTID_AMD = 6,
+ RTW89_CUSTID_FUJITSU = 7,
+ RTW89_CUSTID_DELL = 8,
};
enum rtw89_pkt_drop_sel {
@@ -5216,6 +5335,7 @@ struct rtw89_rfk_mcc_info_data {
u8 ch[RTW89_RFK_CHS_NR];
u8 band[RTW89_RFK_CHS_NR];
u8 bw[RTW89_RFK_CHS_NR];
+ u32 rf18[RTW89_RFK_CHS_NR];
u8 table_idx;
};
@@ -5585,7 +5705,7 @@ struct rtw89_env_monitor_info {
u16 ifs_clm_cckfa;
u16 ifs_clm_cckcca_excl_fa;
u16 ifs_clm_total_ifs;
- u8 ifs_clm_his[RTW89_IFS_CLM_NUM];
+ u16 ifs_clm_his[RTW89_IFS_CLM_NUM];
u16 ifs_clm_avg[RTW89_IFS_CLM_NUM];
u16 ifs_clm_cca[RTW89_IFS_CLM_NUM];
u8 ifs_clm_tx_ratio;
@@ -5786,6 +5906,12 @@ struct rtw89_phy_efuse_gain {
s8 comp[RF_PATH_MAX][RTW89_SUBBAND_NR]; /* S(8, 0) */
};
+struct rtw89_phy_calc_efuse_gain {
+ s8 cck_mean_gain_bias;
+ s8 cck_rpl_ofst;
+ s8 rssi_ofst;
+};
+
#define RTW89_MAX_PATTERN_NUM 18
#define RTW89_MAX_PATTERN_MASK_SIZE 4
#define RTW89_MAX_PATTERN_SIZE 128
@@ -5793,7 +5919,7 @@ struct rtw89_phy_efuse_gain {
struct rtw89_wow_cam_info {
bool r_w;
u8 idx;
- u32 mask[RTW89_MAX_PATTERN_MASK_SIZE];
+ __le32 mask[RTW89_MAX_PATTERN_MASK_SIZE];
u16 crc;
bool negative_pattern_match;
bool skip_mac_hdr;
@@ -7100,15 +7226,6 @@ static inline void rtw89_chip_rfk_init_late(struct rtw89_dev *rtwdev)
chip->ops->rfk_init_late(rtwdev);
}
-static inline void rtw89_chip_rfk_channel(struct rtw89_dev *rtwdev,
- struct rtw89_vif_link *rtwvif_link)
-{
- const struct rtw89_chip_info *chip = rtwdev->chip;
-
- if (chip->ops->rfk_channel)
- chip->ops->rfk_channel(rtwdev, rtwvif_link);
-}
-
static inline void rtw89_chip_rfk_band_changed(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx,
const struct rtw89_chan *chan)
@@ -7249,6 +7366,19 @@ static inline void rtw89_chip_digital_pwr_comp(struct rtw89_dev *rtwdev,
chip->ops->digital_pwr_comp(rtwdev, phy_idx);
}
+static inline
+void rtw89_chip_calc_rx_gain_normal(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_rf_path path,
+ enum rtw89_phy_idx phy_idx,
+ struct rtw89_phy_calc_efuse_gain *calc)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+
+ if (chip->ops->calc_rx_gain_normal)
+ chip->ops->calc_rx_gain_normal(rtwdev, chan, path, phy_idx, calc);
+}
+
static inline void rtw89_load_txpwr_table(struct rtw89_dev *rtwdev,
const struct rtw89_txpwr_table *tbl)
{
@@ -7558,6 +7688,9 @@ void rtw89_core_fill_txdesc_v1(struct rtw89_dev *rtwdev,
void rtw89_core_fill_txdesc_v2(struct rtw89_dev *rtwdev,
struct rtw89_tx_desc_info *desc_info,
void *txdesc);
+void rtw89_core_fill_txdesc_v3(struct rtw89_dev *rtwdev,
+ struct rtw89_tx_desc_info *desc_info,
+ void *txdesc);
void rtw89_core_fill_txdesc_fwcmd_v1(struct rtw89_dev *rtwdev,
struct rtw89_tx_desc_info *desc_info,
void *txdesc);
@@ -7576,6 +7709,9 @@ void rtw89_core_query_rxdesc(struct rtw89_dev *rtwdev,
void rtw89_core_query_rxdesc_v2(struct rtw89_dev *rtwdev,
struct rtw89_rx_desc_info *desc_info,
u8 *data, u32 data_offset);
+void rtw89_core_query_rxdesc_v3(struct rtw89_dev *rtwdev,
+ struct rtw89_rx_desc_info *desc_info,
+ u8 *data, u32 data_offset);
void rtw89_core_napi_start(struct rtw89_dev *rtwdev);
void rtw89_core_napi_stop(struct rtw89_dev *rtwdev);
int rtw89_core_napi_init(struct rtw89_dev *rtwdev);
@@ -7622,6 +7758,8 @@ struct rtw89_sta_link *rtw89_sta_set_link(struct rtw89_sta *rtwsta,
unsigned int link_id);
void rtw89_sta_unset_link(struct rtw89_sta *rtwsta, unsigned int link_id);
void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev);
+void rtw89_chip_rfk_channel(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link);
const struct rtw89_6ghz_span *
rtw89_get_6ghz_span(struct rtw89_dev *rtwdev, u32 center_freq);
void rtw89_get_default_chandef(struct cfg80211_chan_def *chandef);
diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c
index 1264c2f82600..d46691fa09bc 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.c
+++ b/drivers/net/wireless/realtek/rtw89/debug.c
@@ -79,6 +79,7 @@ struct rtw89_debugfs {
struct rtw89_debugfs_priv send_h2c;
struct rtw89_debugfs_priv early_h2c;
struct rtw89_debugfs_priv fw_crash;
+ struct rtw89_debugfs_priv ser_counters;
struct rtw89_debugfs_priv btc_info;
struct rtw89_debugfs_priv btc_manual;
struct rtw89_debugfs_priv fw_log_manual;
@@ -825,10 +826,6 @@ static ssize_t __print_txpwr_map(struct rtw89_dev *rtwdev, char *buf, size_t buf
s8 *bufp, tmp;
int ret;
- bufp = vzalloc(map->addr_to - map->addr_from + 4);
- if (!bufp)
- return -ENOMEM;
-
if (path_num == 1)
max_valid_addr = map->addr_to_1ss;
else
@@ -837,6 +834,10 @@ static ssize_t __print_txpwr_map(struct rtw89_dev *rtwdev, char *buf, size_t buf
if (max_valid_addr == 0)
return -EOPNOTSUPP;
+ bufp = vzalloc(map->addr_to - map->addr_from + 4);
+ if (!bufp)
+ return -ENOMEM;
+
for (addr = map->addr_from; addr <= max_valid_addr; addr += 4) {
ret = rtw89_mac_txpwr_read32(rtwdev, RTW89_PHY_0, addr, &val);
if (ret)
@@ -3537,13 +3538,49 @@ out:
return count;
}
-static int rtw89_dbg_trigger_ctrl_error(struct rtw89_dev *rtwdev)
+static int rtw89_dbg_trigger_l1_error_by_halt_h2c_ax(struct rtw89_dev *rtwdev)
+{
+ if (!test_bit(RTW89_FLAG_FW_RDY, rtwdev->flags))
+ return -EBUSY;
+
+ return rtw89_mac_set_err_status(rtwdev, MAC_AX_ERR_L1_RESET_FORCE);
+}
+
+static int rtw89_dbg_trigger_l1_error_by_halt_h2c_be(struct rtw89_dev *rtwdev)
+{
+ if (!test_bit(RTW89_FLAG_FW_RDY, rtwdev->flags))
+ return -EBUSY;
+
+ rtw89_write32_set(rtwdev, R_BE_FW_TRIGGER_IDCT_ISR,
+ B_BE_DMAC_FW_TRIG_IDCT | B_BE_DMAC_FW_ERR_IDCT_IMR);
+
+ return 0;
+}
+
+static int rtw89_dbg_trigger_l1_error_by_halt_h2c(struct rtw89_dev *rtwdev)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+
+ switch (chip->chip_gen) {
+ case RTW89_CHIP_AX:
+ return rtw89_dbg_trigger_l1_error_by_halt_h2c_ax(rtwdev);
+ case RTW89_CHIP_BE:
+ return rtw89_dbg_trigger_l1_error_by_halt_h2c_be(rtwdev);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int rtw89_dbg_trigger_l1_error(struct rtw89_dev *rtwdev)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
struct rtw89_cpuio_ctrl ctrl_para = {0};
u16 pkt_id;
int ret;
+ if (RTW89_CHK_FW_FEATURE(SIM_SER_L0L1_BY_HALT_H2C, &rtwdev->fw))
+ return rtw89_dbg_trigger_l1_error_by_halt_h2c(rtwdev);
+
rtw89_leave_ps_mode(rtwdev);
ret = mac->dle_buf_req(rtwdev, 0x20, true, &pkt_id);
@@ -3564,7 +3601,7 @@ static int rtw89_dbg_trigger_ctrl_error(struct rtw89_dev *rtwdev)
return 0;
}
-static int rtw89_dbg_trigger_mac_error_ax(struct rtw89_dev *rtwdev)
+static int rtw89_dbg_trigger_l0_error_ax(struct rtw89_dev *rtwdev)
{
u16 val16;
u8 val8;
@@ -3586,34 +3623,67 @@ static int rtw89_dbg_trigger_mac_error_ax(struct rtw89_dev *rtwdev)
return 0;
}
-static int rtw89_dbg_trigger_mac_error_be(struct rtw89_dev *rtwdev)
+static int rtw89_dbg_trigger_l0_error_be(struct rtw89_dev *rtwdev)
{
+ u8 val8;
int ret;
ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_CMAC_SEL);
if (ret)
return ret;
+ val8 = rtw89_read8(rtwdev, R_BE_CMAC_FUNC_EN);
+ rtw89_write8(rtwdev, R_BE_CMAC_FUNC_EN, val8 & ~B_BE_TMAC_EN);
+ mdelay(1);
+ rtw89_write8(rtwdev, R_BE_CMAC_FUNC_EN, val8);
+
+ return 0;
+}
+
+static int rtw89_dbg_trigger_l0_error_by_halt_h2c_ax(struct rtw89_dev *rtwdev)
+{
+ if (!test_bit(RTW89_FLAG_FW_RDY, rtwdev->flags))
+ return -EBUSY;
+
+ return rtw89_mac_set_err_status(rtwdev, MAC_AX_ERR_L0_RESET_FORCE);
+}
+
+static int rtw89_dbg_trigger_l0_error_by_halt_h2c_be(struct rtw89_dev *rtwdev)
+{
+ if (!test_bit(RTW89_FLAG_FW_RDY, rtwdev->flags))
+ return -EBUSY;
+
rtw89_write32_set(rtwdev, R_BE_CMAC_FW_TRIGGER_IDCT_ISR,
B_BE_CMAC_FW_TRIG_IDCT | B_BE_CMAC_FW_ERR_IDCT_IMR);
return 0;
}
-static int rtw89_dbg_trigger_mac_error(struct rtw89_dev *rtwdev)
+static int rtw89_dbg_trigger_l0_error(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
-
- rtw89_leave_ps_mode(rtwdev);
+ int (*sim_l0_by_halt_h2c)(struct rtw89_dev *rtwdev);
+ int (*sim_l0)(struct rtw89_dev *rtwdev);
switch (chip->chip_gen) {
case RTW89_CHIP_AX:
- return rtw89_dbg_trigger_mac_error_ax(rtwdev);
+ sim_l0_by_halt_h2c = rtw89_dbg_trigger_l0_error_by_halt_h2c_ax;
+ sim_l0 = rtw89_dbg_trigger_l0_error_ax;
+ break;
case RTW89_CHIP_BE:
- return rtw89_dbg_trigger_mac_error_be(rtwdev);
+ sim_l0_by_halt_h2c = rtw89_dbg_trigger_l0_error_by_halt_h2c_be;
+ sim_l0 = rtw89_dbg_trigger_l0_error_be;
+ break;
default:
return -EOPNOTSUPP;
}
+
+ if (RTW89_CHK_FW_FEATURE(SIM_SER_L0L1_BY_HALT_H2C, &rtwdev->fw))
+ return sim_l0_by_halt_h2c(rtwdev);
+
+ rtw89_leave_ps_mode(rtwdev);
+
+ return sim_l0(rtwdev);
}
static ssize_t
@@ -3630,8 +3700,8 @@ rtw89_debug_priv_fw_crash_get(struct rtw89_dev *rtwdev,
enum rtw89_dbg_crash_simulation_type {
RTW89_DBG_SIM_CPU_EXCEPTION = 1,
- RTW89_DBG_SIM_CTRL_ERROR = 2,
- RTW89_DBG_SIM_MAC_ERROR = 3,
+ RTW89_DBG_SIM_L1_ERROR = 2,
+ RTW89_DBG_SIM_L0_ERROR = 3,
};
static ssize_t
@@ -3656,11 +3726,11 @@ rtw89_debug_priv_fw_crash_set(struct rtw89_dev *rtwdev,
return -EOPNOTSUPP;
sim = rtw89_fw_h2c_trigger_cpu_exception;
break;
- case RTW89_DBG_SIM_CTRL_ERROR:
- sim = rtw89_dbg_trigger_ctrl_error;
+ case RTW89_DBG_SIM_L1_ERROR:
+ sim = rtw89_dbg_trigger_l1_error;
break;
- case RTW89_DBG_SIM_MAC_ERROR:
- sim = rtw89_dbg_trigger_mac_error;
+ case RTW89_DBG_SIM_L0_ERROR:
+ sim = rtw89_dbg_trigger_l0_error;
/* Driver SER flow won't get involved; only FW will. */
announce = false;
@@ -3680,6 +3750,60 @@ rtw89_debug_priv_fw_crash_set(struct rtw89_dev *rtwdev,
return count;
}
+struct rtw89_dbg_ser_counters {
+ unsigned int l0;
+ unsigned int l1;
+ unsigned int l0_to_l1;
+};
+
+static void rtw89_dbg_get_ser_counters_ax(struct rtw89_dev *rtwdev,
+ struct rtw89_dbg_ser_counters *cnt)
+{
+ const u32 val = rtw89_read32(rtwdev, R_AX_SER_DBG_INFO);
+
+ cnt->l0 = u32_get_bits(val, B_AX_SER_L0_COUNTER_MASK);
+ cnt->l1 = u32_get_bits(val, B_AX_SER_L1_COUNTER_MASK);
+ cnt->l0_to_l1 = u32_get_bits(val, B_AX_L0_TO_L1_EVENT_MASK);
+}
+
+static void rtw89_dbg_get_ser_counters_be(struct rtw89_dev *rtwdev,
+ struct rtw89_dbg_ser_counters *cnt)
+{
+ const u32 val = rtw89_read32(rtwdev, R_BE_SER_DBG_INFO);
+
+ cnt->l0 = u32_get_bits(val, B_BE_SER_L0_COUNTER_MASK);
+ cnt->l1 = u32_get_bits(val, B_BE_SER_L1_COUNTER_MASK);
+ cnt->l0_to_l1 = u32_get_bits(val, B_BE_SER_L0_PROMOTE_L1_EVENT_MASK);
+}
+
+static ssize_t rtw89_debug_priv_ser_counters_get(struct rtw89_dev *rtwdev,
+ struct rtw89_debugfs_priv *debugfs_priv,
+ char *buf, size_t bufsz)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ struct rtw89_dbg_ser_counters cnt = {};
+ char *p = buf, *end = buf + bufsz;
+
+ rtw89_leave_ps_mode(rtwdev);
+
+ switch (chip->chip_gen) {
+ case RTW89_CHIP_AX:
+ rtw89_dbg_get_ser_counters_ax(rtwdev, &cnt);
+ break;
+ case RTW89_CHIP_BE:
+ rtw89_dbg_get_ser_counters_be(rtwdev, &cnt);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ p += scnprintf(p, end - p, "SER L0 Count: %d\n", cnt.l0);
+ p += scnprintf(p, end - p, "SER L1 Count: %d\n", cnt.l1);
+ p += scnprintf(p, end - p, "SER L0 promote event: %d\n", cnt.l0_to_l1);
+
+ return p - buf;
+}
+
static ssize_t rtw89_debug_priv_btc_info_get(struct rtw89_dev *rtwdev,
struct rtw89_debugfs_priv *debugfs_priv,
char *buf, size_t bufsz)
@@ -4767,6 +4891,7 @@ static const struct rtw89_debugfs rtw89_debugfs_templ = {
.send_h2c = rtw89_debug_priv_set(send_h2c),
.early_h2c = rtw89_debug_priv_set_and_get(early_h2c, RWLOCK),
.fw_crash = rtw89_debug_priv_set_and_get(fw_crash, WLOCK),
+ .ser_counters = rtw89_debug_priv_get(ser_counters, RLOCK),
.btc_info = rtw89_debug_priv_get(btc_info, RSIZE_12K),
.btc_manual = rtw89_debug_priv_set(btc_manual),
.fw_log_manual = rtw89_debug_priv_set(fw_log_manual, WLOCK),
@@ -4814,6 +4939,7 @@ void rtw89_debugfs_add_sec1(struct rtw89_dev *rtwdev, struct dentry *debugfs_top
rtw89_debugfs_add_w(send_h2c);
rtw89_debugfs_add_rw(early_h2c);
rtw89_debugfs_add_rw(fw_crash);
+ rtw89_debugfs_add_r(ser_counters);
rtw89_debugfs_add_r(btc_info);
rtw89_debugfs_add_w(btc_manual);
rtw89_debugfs_add_w(fw_log_manual);
diff --git a/drivers/net/wireless/realtek/rtw89/debug.h b/drivers/net/wireless/realtek/rtw89/debug.h
index a364e7adb079..7cdceb24f52d 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.h
+++ b/drivers/net/wireless/realtek/rtw89/debug.h
@@ -31,6 +31,7 @@ enum rtw89_debug_mask {
RTW89_DBG_CHAN = BIT(20),
RTW89_DBG_ACPI = BIT(21),
RTW89_DBG_EDCCA = BIT(22),
+ RTW89_DBG_PS = BIT(23),
RTW89_DBG_UNEXP = BIT(31),
};
diff --git a/drivers/net/wireless/realtek/rtw89/efuse.c b/drivers/net/wireless/realtek/rtw89/efuse.c
index 6c6c763510af..a2757a88d55d 100644
--- a/drivers/net/wireless/realtek/rtw89/efuse.c
+++ b/drivers/net/wireless/realtek/rtw89/efuse.c
@@ -7,10 +7,6 @@
#include "mac.h"
#include "reg.h"
-#define EF_FV_OFSET 0x5ea
-#define EF_CV_MASK GENMASK(7, 4)
-#define EF_CV_INV 15
-
#define EFUSE_B1_MSSDEVTYPE_MASK GENMASK(3, 0)
#define EFUSE_B1_MSSCUSTIDX0_MASK GENMASK(7, 4)
#define EFUSE_B2_MSSKEYNUM_MASK GENMASK(3, 0)
diff --git a/drivers/net/wireless/realtek/rtw89/efuse.h b/drivers/net/wireless/realtek/rtw89/efuse.h
index a96fc1044791..a14a9dfed8e8 100644
--- a/drivers/net/wireless/realtek/rtw89/efuse.h
+++ b/drivers/net/wireless/realtek/rtw89/efuse.h
@@ -11,6 +11,11 @@
#define RTW89_EFUSE_BLOCK_SIZE_MASK GENMASK(15, 0)
#define RTW89_EFUSE_MAX_BLOCK_SIZE 0x10000
+#define EF_FV_OFSET 0x5EA
+#define EF_FV_OFSET_BE_V1 0x17CA
+#define EF_CV_MASK GENMASK(7, 4)
+#define EF_CV_INV 15
+
struct rtw89_efuse_block_cfg {
u32 offset;
u32 size;
@@ -26,5 +31,6 @@ int rtw89_read_efuse_ver(struct rtw89_dev *rtwdev, u8 *efv);
int rtw89_efuse_recognize_mss_info_v1(struct rtw89_dev *rtwdev, u8 b1, u8 b2);
int rtw89_efuse_read_fw_secure_ax(struct rtw89_dev *rtwdev);
int rtw89_efuse_read_fw_secure_be(struct rtw89_dev *rtwdev);
+int rtw89_efuse_read_ecv_be(struct rtw89_dev *rtwdev);
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/efuse_be.c b/drivers/net/wireless/realtek/rtw89/efuse_be.c
index 64768923b0f0..70c1b8be662e 100644
--- a/drivers/net/wireless/realtek/rtw89/efuse_be.c
+++ b/drivers/net/wireless/realtek/rtw89/efuse_be.c
@@ -512,3 +512,29 @@ out:
return 0;
}
+
+int rtw89_efuse_read_ecv_be(struct rtw89_dev *rtwdev)
+{
+ u32 dump_addr;
+ u8 buff[4]; /* efuse access must 4 bytes align */
+ int ret;
+ u8 ecv;
+ u8 val;
+
+ dump_addr = ALIGN_DOWN(EF_FV_OFSET_BE_V1, 4);
+
+ ret = rtw89_dump_physical_efuse_map_be(rtwdev, buff, dump_addr, 4, false);
+ if (ret)
+ return ret;
+
+ val = buff[EF_FV_OFSET_BE_V1 & 0x3];
+
+ ecv = u8_get_bits(val, EF_CV_MASK);
+ if (ecv == EF_CV_INV)
+ return -ENOENT;
+
+ rtwdev->hal.cv = ecv;
+
+ return 0;
+}
+EXPORT_SYMBOL(rtw89_efuse_read_ecv_be);
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index 7b9d9989e517..f84726f04669 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -812,6 +812,8 @@ struct __fw_feat_cfg {
enum rtw89_fw_feature feature;
u32 ver_code;
bool (*cond)(u32 suit_ver_code, u32 comp_ver_code);
+ bool disable;
+ int size;
};
#define __CFG_FW_FEAT(_chip, _cond, _maj, _min, _sub, _idx, _feat) \
@@ -822,10 +824,36 @@ struct __fw_feat_cfg {
.cond = __fw_feat_cond_ ## _cond, \
}
+#define __S_DIS_FW_FEAT(_chip, _cond, _maj, _min, _sub, _idx, _feat) \
+ { \
+ .chip_id = _chip, \
+ .feature = RTW89_FW_FEATURE_ ## _feat, \
+ .ver_code = RTW89_FW_VER_CODE(_maj, _min, _sub, _idx), \
+ .cond = __fw_feat_cond_ ## _cond, \
+ .disable = true, \
+ .size = 1, \
+ }
+
+#define __G_DIS_FW_FEAT(_chip, _cond, _maj, _min, _sub, _idx, _grp) \
+ { \
+ .chip_id = _chip, \
+ .feature = RTW89_FW_FEATURE_ ## _grp ## _MIN, \
+ .ver_code = RTW89_FW_VER_CODE(_maj, _min, _sub, _idx), \
+ .cond = __fw_feat_cond_ ## _cond, \
+ .disable = true, \
+ .size = RTW89_FW_FEATURE_ ## _grp ## _MAX - \
+ RTW89_FW_FEATURE_ ## _grp ## _MIN + 1, \
+ }
+
+#define __DIS_FW_FEAT(_chip, _cond, _maj, _min, _sub, _idx, _feat, _type) \
+ __##_type##_DIS_FW_FEAT(_chip, _cond, _maj, _min, _sub, _idx, _feat)
+
static const struct __fw_feat_cfg fw_feat_tbl[] = {
__CFG_FW_FEAT(RTL8851B, ge, 0, 29, 37, 1, TX_WAKE),
__CFG_FW_FEAT(RTL8851B, ge, 0, 29, 37, 1, SCAN_OFFLOAD),
__CFG_FW_FEAT(RTL8851B, ge, 0, 29, 41, 0, CRASH_TRIGGER_TYPE_0),
+ __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 127, 0, SER_L1_BY_EVENT),
+ __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 130, 0, SIM_SER_L0L1_BY_HALT_H2C),
__CFG_FW_FEAT(RTL8852A, le, 0, 13, 29, 0, OLD_HT_RA_FORMAT),
__CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, SCAN_OFFLOAD),
__CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, TX_WAKE),
@@ -837,11 +865,14 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = {
__CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 0, CRASH_TRIGGER_TYPE_0),
__CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 0, SCAN_OFFLOAD),
__CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 7, BEACON_FILTER),
+ __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 15, BEACON_LOSS_COUNT_V1),
__CFG_FW_FEAT(RTL8852B, lt, 0, 29, 30, 0, NO_WOW_CPU_IO_RX),
__CFG_FW_FEAT(RTL8852B, ge, 0, 29, 127, 0, LPS_DACK_BY_C2H_REG),
+ __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 127, 0, SER_L1_BY_EVENT),
__CFG_FW_FEAT(RTL8852B, ge, 0, 29, 128, 0, CRASH_TRIGGER_TYPE_1),
__CFG_FW_FEAT(RTL8852B, ge, 0, 29, 128, 0, SCAN_OFFLOAD_EXTRA_OP),
__CFG_FW_FEAT(RTL8852B, ge, 0, 29, 128, 0, BEACON_TRACKING),
+ __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 130, 0, SIM_SER_L0L1_BY_HALT_H2C),
__CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 74, 0, NO_LPS_PG),
__CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 74, 0, TX_WAKE),
__CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 90, 0, CRASH_TRIGGER_TYPE_0),
@@ -851,8 +882,10 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = {
__CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 127, 0, SCAN_OFFLOAD_EXTRA_OP),
__CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 127, 0, LPS_DACK_BY_C2H_REG),
__CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 127, 0, CRASH_TRIGGER_TYPE_1),
- __CFG_FW_FEAT(RTL8852C, le, 0, 27, 33, 0, NO_DEEP_PS),
+ __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 127, 0, SER_L1_BY_EVENT),
+ __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 130, 0, SIM_SER_L0L1_BY_HALT_H2C),
__CFG_FW_FEAT(RTL8852C, ge, 0, 0, 0, 0, RFK_NTFY_MCC_V0),
+ __CFG_FW_FEAT(RTL8852C, le, 0, 27, 33, 0, NO_DEEP_PS),
__CFG_FW_FEAT(RTL8852C, ge, 0, 27, 34, 0, TX_WAKE),
__CFG_FW_FEAT(RTL8852C, ge, 0, 27, 36, 0, SCAN_OFFLOAD),
__CFG_FW_FEAT(RTL8852C, ge, 0, 27, 40, 0, CRASH_TRIGGER_TYPE_0),
@@ -862,26 +895,34 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = {
__CFG_FW_FEAT(RTL8852C, ge, 0, 27, 128, 0, LPS_DACK_BY_C2H_REG),
__CFG_FW_FEAT(RTL8852C, ge, 0, 27, 128, 0, CRASH_TRIGGER_TYPE_1),
__CFG_FW_FEAT(RTL8852C, ge, 0, 27, 129, 1, BEACON_TRACKING),
- __CFG_FW_FEAT(RTL8922A, ge, 0, 34, 30, 0, CRASH_TRIGGER_TYPE_0),
+ __CFG_FW_FEAT(RTL8852C, ge, 0, 29, 94, 0, SER_L1_BY_EVENT),
+ __CFG_FW_FEAT(RTL8852C, ge, 0, 29, 130, 0, SIM_SER_L0L1_BY_HALT_H2C),
+ __CFG_FW_FEAT(RTL8922A, ge, 0, 0, 0, 0, RFK_PRE_NOTIFY_V0),
__CFG_FW_FEAT(RTL8922A, ge, 0, 34, 11, 0, MACID_PAUSE_SLEEP),
+ __CFG_FW_FEAT(RTL8922A, ge, 0, 34, 30, 0, CRASH_TRIGGER_TYPE_0),
__CFG_FW_FEAT(RTL8922A, ge, 0, 34, 35, 0, SCAN_OFFLOAD),
- __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 21, 0, SCAN_OFFLOAD_BE_V0),
+ __CFG_FW_FEAT(RTL8922A, ge, 0, 34, 35, 0, SCAN_OFFLOAD_EXTRA_OP),
__CFG_FW_FEAT(RTL8922A, ge, 0, 35, 12, 0, BEACON_FILTER),
+ __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 21, 0, SCAN_OFFLOAD_BE_V0),
__CFG_FW_FEAT(RTL8922A, ge, 0, 35, 22, 0, WOW_REASON_V1),
__CFG_FW_FEAT(RTL8922A, lt, 0, 35, 28, 0, RFK_IQK_V0),
- __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 31, 0, RFK_PRE_NOTIFY_V0),
+ __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 31, 0, RFK_PRE_NOTIFY_V1),
__CFG_FW_FEAT(RTL8922A, lt, 0, 35, 31, 0, LPS_CH_INFO),
__CFG_FW_FEAT(RTL8922A, lt, 0, 35, 42, 0, RFK_RXDCK_V0),
__CFG_FW_FEAT(RTL8922A, ge, 0, 35, 46, 0, NOTIFY_AP_INFO),
__CFG_FW_FEAT(RTL8922A, lt, 0, 35, 47, 0, CH_INFO_BE_V0),
- __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 49, 0, RFK_PRE_NOTIFY_V1),
+ __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 49, 0, RFK_PRE_NOTIFY_V2),
+ __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 49, 0, RFK_PRE_NOTIFY_MCC_V0),
__CFG_FW_FEAT(RTL8922A, lt, 0, 35, 51, 0, NO_PHYCAP_P1),
__CFG_FW_FEAT(RTL8922A, lt, 0, 35, 64, 0, NO_POWER_DIFFERENCE),
__CFG_FW_FEAT(RTL8922A, ge, 0, 35, 71, 0, BEACON_LOSS_COUNT_V1),
__CFG_FW_FEAT(RTL8922A, ge, 0, 35, 76, 0, LPS_DACK_BY_C2H_REG),
__CFG_FW_FEAT(RTL8922A, ge, 0, 35, 79, 0, CRASH_TRIGGER_TYPE_1),
__CFG_FW_FEAT(RTL8922A, ge, 0, 35, 80, 0, BEACON_TRACKING),
+ __DIS_FW_FEAT(RTL8922A, ge, 0, 35, 84, 0, WITH_RFK_PRE_NOTIFY, G),
+ __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 84, 0, RFK_PRE_NOTIFY_MCC_V1),
__CFG_FW_FEAT(RTL8922A, lt, 0, 35, 84, 0, ADDR_CAM_V0),
+ __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 97, 0, SIM_SER_L0L1_BY_HALT_H2C),
};
static void rtw89_fw_iterate_feature_cfg(struct rtw89_fw_info *fw,
@@ -896,8 +937,16 @@ static void rtw89_fw_iterate_feature_cfg(struct rtw89_fw_info *fw,
if (chip->chip_id != ent->chip_id)
continue;
- if (ent->cond(ver_code, ent->ver_code))
+ if (!ent->cond(ver_code, ent->ver_code))
+ continue;
+
+ if (!ent->disable) {
RTW89_SET_FW_FEATURE(ent->feature, fw);
+ continue;
+ }
+
+ for (int n = 0; n < ent->size; n++)
+ RTW89_CLR_FW_FEATURE(ent->feature + n, fw);
}
}
@@ -1013,42 +1062,47 @@ int rtw89_build_phy_tbl_from_elm(struct rtw89_dev *rtwdev,
const union rtw89_fw_element_arg arg)
{
struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
- struct rtw89_phy_table *tbl;
+ struct rtw89_hal *hal = &rtwdev->hal;
+ struct rtw89_phy_table *tbl, **pp;
struct rtw89_reg2_def *regs;
- enum rtw89_rf_path rf_path;
+ bool radio = false;
u32 n_regs, i;
+ u16 aid;
u8 idx;
- tbl = kzalloc(sizeof(*tbl), GFP_KERNEL);
- if (!tbl)
- return -ENOMEM;
-
switch (le32_to_cpu(elm->id)) {
case RTW89_FW_ELEMENT_ID_BB_REG:
- elm_info->bb_tbl = tbl;
+ pp = &elm_info->bb_tbl;
break;
case RTW89_FW_ELEMENT_ID_BB_GAIN:
- elm_info->bb_gain = tbl;
+ pp = &elm_info->bb_gain;
break;
case RTW89_FW_ELEMENT_ID_RADIO_A:
case RTW89_FW_ELEMENT_ID_RADIO_B:
case RTW89_FW_ELEMENT_ID_RADIO_C:
case RTW89_FW_ELEMENT_ID_RADIO_D:
- rf_path = arg.rf_path;
idx = elm->u.reg2.idx;
+ pp = &elm_info->rf_radio[idx];
- elm_info->rf_radio[idx] = tbl;
- tbl->rf_path = rf_path;
- tbl->config = rtw89_phy_config_rf_reg_v1;
+ radio = true;
break;
case RTW89_FW_ELEMENT_ID_RF_NCTL:
- elm_info->rf_nctl = tbl;
+ pp = &elm_info->rf_nctl;
break;
default:
- kfree(tbl);
return -ENOENT;
}
+ aid = le16_to_cpu(elm->aid);
+ if (aid && aid != hal->aid)
+ return 1; /* ignore if aid not matched */
+ else if (*pp)
+ return 1; /* ignore if an element is existing */
+
+ tbl = kzalloc(sizeof(*tbl), GFP_KERNEL);
+ if (!tbl)
+ return -ENOMEM;
+
n_regs = le32_to_cpu(elm->size) / sizeof(tbl->regs[0]);
regs = kcalloc(n_regs, sizeof(*regs), GFP_KERNEL);
if (!regs)
@@ -1062,6 +1116,13 @@ int rtw89_build_phy_tbl_from_elm(struct rtw89_dev *rtwdev,
tbl->n_regs = n_regs;
tbl->regs = regs;
+ if (radio) {
+ tbl->rf_path = arg.rf_path;
+ tbl->config = rtw89_phy_config_rf_reg_v1;
+ }
+
+ *pp = tbl;
+
return 0;
out:
@@ -1322,6 +1383,26 @@ int rtw89_recognize_diag_mac_from_elm(struct rtw89_dev *rtwdev,
return 0;
}
+static
+int rtw89_build_tx_comp_from_elm(struct rtw89_dev *rtwdev,
+ const struct rtw89_fw_element_hdr *elm,
+ const union rtw89_fw_element_arg arg)
+{
+ struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
+ struct rtw89_hal *hal = &rtwdev->hal;
+ u16 aid;
+
+ aid = le16_to_cpu(elm->aid);
+ if (aid && aid != hal->aid)
+ return 1; /* ignore if aid not matched */
+ else if (elm_info->tx_comp)
+ return 1; /* ignore if an element is existing */
+
+ elm_info->tx_comp = elm;
+
+ return 0;
+}
+
static const struct rtw89_fw_element_handler __fw_element_handlers[] = {
[RTW89_FW_ELEMENT_ID_BBMCU0] = {__rtw89_fw_recognize_from_elm,
{ .fw_type = RTW89_FW_BBMCU0 }, NULL},
@@ -1413,6 +1494,9 @@ static const struct rtw89_fw_element_handler __fw_element_handlers[] = {
[RTW89_FW_ELEMENT_ID_DIAG_MAC] = {
rtw89_recognize_diag_mac_from_elm, {}, NULL,
},
+ [RTW89_FW_ELEMENT_ID_TX_COMP] = {
+ rtw89_build_tx_comp_from_elm, {}, NULL,
+ },
};
int rtw89_fw_recognize_elements(struct rtw89_dev *rtwdev)
@@ -1481,11 +1565,12 @@ void rtw89_h2c_pkt_set_hdr(struct rtw89_dev *rtwdev, struct sk_buff *skb,
u8 type, u8 cat, u8 class, u8 func,
bool rack, bool dack, u32 len)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
struct fwcmd_hdr *hdr;
hdr = (struct fwcmd_hdr *)skb_push(skb, 8);
- if (!(rtwdev->fw.h2c_seq % 4))
+ if (chip->chip_gen == RTW89_CHIP_AX && !(rtwdev->fw.h2c_seq % 4))
rack = true;
hdr->hdr0 = cpu_to_le32(FIELD_PREP(H2C_HDR_DEL_TYPE, type) |
FIELD_PREP(H2C_HDR_CAT, cat) |
@@ -2267,6 +2352,45 @@ fail:
}
EXPORT_SYMBOL(rtw89_fw_h2c_dctl_sec_cam_v2);
+int rtw89_fw_h2c_dctl_sec_cam_v3(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
+{
+ struct rtw89_h2c_dctlinfo_ud_v3 *h2c;
+ u32 len = sizeof(*h2c);
+ struct sk_buff *skb;
+ int ret;
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+ if (!skb) {
+ rtw89_err(rtwdev, "failed to alloc skb for dctl sec cam\n");
+ return -ENOMEM;
+ }
+ skb_put(skb, len);
+ h2c = (struct rtw89_h2c_dctlinfo_ud_v3 *)skb->data;
+
+ rtw89_cam_fill_dctl_sec_cam_info_v3(rtwdev, rtwvif_link, rtwsta_link, h2c);
+
+ rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+ H2C_CAT_MAC,
+ H2C_CL_MAC_FR_EXCHG,
+ H2C_FUNC_MAC_DCTLINFO_UD_V3, 0, 0,
+ len);
+
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+ goto fail;
+ }
+
+ return 0;
+fail:
+ dev_kfree_skb_any(skb);
+
+ return ret;
+}
+EXPORT_SYMBOL(rtw89_fw_h2c_dctl_sec_cam_v3);
+
int rtw89_fw_h2c_default_dmac_tbl_v2(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_link)
@@ -2322,6 +2446,62 @@ fail:
}
EXPORT_SYMBOL(rtw89_fw_h2c_default_dmac_tbl_v2);
+int rtw89_fw_h2c_default_dmac_tbl_v3(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
+{
+ u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id;
+ struct rtw89_h2c_dctlinfo_ud_v3 *h2c;
+ u32 len = sizeof(*h2c);
+ struct sk_buff *skb;
+ int ret;
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+ if (!skb) {
+ rtw89_err(rtwdev, "failed to alloc skb for dctl v2\n");
+ return -ENOMEM;
+ }
+ skb_put(skb, len);
+ h2c = (struct rtw89_h2c_dctlinfo_ud_v3 *)skb->data;
+
+ h2c->c0 = le32_encode_bits(mac_id, DCTLINFO_V3_C0_MACID) |
+ le32_encode_bits(1, DCTLINFO_V3_C0_OP);
+
+ h2c->m0 = cpu_to_le32(DCTLINFO_V3_W0_ALL);
+ h2c->m1 = cpu_to_le32(DCTLINFO_V3_W1_ALL);
+ h2c->m2 = cpu_to_le32(DCTLINFO_V3_W2_ALL);
+ h2c->m3 = cpu_to_le32(DCTLINFO_V3_W3_ALL);
+ h2c->m4 = cpu_to_le32(DCTLINFO_V3_W4_ALL);
+ h2c->m5 = cpu_to_le32(DCTLINFO_V3_W5_ALL);
+ h2c->m6 = cpu_to_le32(DCTLINFO_V3_W6_ALL);
+ h2c->m7 = cpu_to_le32(DCTLINFO_V3_W7_ALL);
+ h2c->m8 = cpu_to_le32(DCTLINFO_V3_W8_ALL);
+ h2c->m9 = cpu_to_le32(DCTLINFO_V3_W9_ALL);
+ h2c->m10 = cpu_to_le32(DCTLINFO_V3_W10_ALL);
+ h2c->m11 = cpu_to_le32(DCTLINFO_V3_W11_ALL);
+ h2c->m12 = cpu_to_le32(DCTLINFO_V3_W12_ALL);
+ h2c->m13 = cpu_to_le32(DCTLINFO_V3_W13_ALL);
+
+ rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+ H2C_CAT_MAC,
+ H2C_CL_MAC_FR_EXCHG,
+ H2C_FUNC_MAC_DCTLINFO_UD_V3, 0, 0,
+ len);
+
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+ goto fail;
+ }
+
+ return 0;
+fail:
+ dev_kfree_skb_any(skb);
+
+ return ret;
+}
+EXPORT_SYMBOL(rtw89_fw_h2c_default_dmac_tbl_v3);
+
int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_link,
@@ -3108,6 +3288,161 @@ fail:
return ret;
}
+void rtw89_bb_lps_cmn_info_rx_gain_fill(struct rtw89_dev *rtwdev,
+ struct rtw89_bb_link_info_rx_gain *h2c_gain,
+ const struct rtw89_chan *chan, u8 phy_idx)
+{
+ const struct rtw89_phy_bb_gain_info_be *gain = &rtwdev->bb_gain.be;
+ enum rtw89_bb_link_rx_gain_table_type tab_idx;
+ struct rtw89_chan chan_bcn;
+ u8 bw = chan->band_width;
+ u8 gain_band;
+ u8 bw_idx;
+ u8 path;
+ int i;
+
+ rtw89_chan_create(&chan_bcn, chan->primary_channel, chan->primary_channel,
+ chan->band_type, RTW89_CHANNEL_WIDTH_20);
+
+ for (tab_idx = RTW89_BB_PS_LINK_RX_GAIN_TAB_BCN_PATH_A;
+ tab_idx < RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX; tab_idx++) {
+ struct rtw89_phy_calc_efuse_gain calc = {};
+
+ path = (tab_idx & BIT(0)) ? (RF_PATH_B) : (RF_PATH_A);
+ if (tab_idx & BIT(1)) {
+ rtw89_chip_calc_rx_gain_normal(rtwdev, chan, path, phy_idx,
+ &calc);
+ gain_band = rtw89_subband_to_gain_band_be(chan->subband_type);
+ if (bw > RTW89_CHANNEL_WIDTH_40)
+ bw_idx = RTW89_BB_BW_80_160_320;
+ else
+ bw_idx = RTW89_BB_BW_20_40;
+ } else {
+ rtw89_chip_calc_rx_gain_normal(rtwdev, &chan_bcn, path, phy_idx,
+ &calc);
+ gain_band = rtw89_subband_to_gain_band_be(chan_bcn.subband_type);
+ bw_idx = RTW89_BB_BW_20_40;
+ }
+
+ /* efuse ofst and comp */
+ h2c_gain->gain_ofst[tab_idx] = calc.rssi_ofst;
+ h2c_gain->cck_gain_ofst[tab_idx] = calc.cck_rpl_ofst;
+ h2c_gain->cck_rpl_bias_comp[tab_idx][0] = calc.cck_mean_gain_bias;
+ h2c_gain->cck_rpl_bias_comp[tab_idx][1] = calc.cck_mean_gain_bias;
+
+ for (i = 0; i < TIA_GAIN_NUM; i++) {
+ h2c_gain->gain_err_tia[tab_idx][i] =
+ cpu_to_le16(gain->tia_gain[gain_band][bw_idx][path][i]);
+ }
+ memcpy(h2c_gain->gain_err_lna[tab_idx],
+ gain->lna_gain[gain_band][bw_idx][path],
+ LNA_GAIN_NUM);
+ memcpy(h2c_gain->op1db_lna[tab_idx],
+ gain->lna_op1db[gain_band][bw_idx][path],
+ LNA_GAIN_NUM);
+ memcpy(h2c_gain->op1db_tia[tab_idx],
+ gain->tia_lna_op1db[gain_band][bw_idx][path],
+ LNA_GAIN_NUM + 1);
+
+ memcpy(h2c_gain->rpl_bias_comp_bw[tab_idx]._20M,
+ gain->rpl_ofst_20[gain_band][path],
+ RTW89_BW20_SC_20M);
+ memcpy(h2c_gain->rpl_bias_comp_bw[tab_idx]._40M,
+ gain->rpl_ofst_40[gain_band][path],
+ RTW89_BW20_SC_40M);
+ memcpy(h2c_gain->rpl_bias_comp_bw[tab_idx]._80M,
+ gain->rpl_ofst_80[gain_band][path],
+ RTW89_BW20_SC_80M);
+ memcpy(h2c_gain->rpl_bias_comp_bw[tab_idx]._160M,
+ gain->rpl_ofst_160[gain_band][path],
+ RTW89_BW20_SC_160M);
+ }
+}
+
+int rtw89_fw_h2c_lps_ml_cmn_info_v1(struct rtw89_dev *rtwdev,
+ struct rtw89_vif *rtwvif)
+{
+ static const u8 bcn_bw_ofst[] = {0, 0, 0, 3, 6, 9, 0, 12};
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ struct rtw89_efuse *efuse = &rtwdev->efuse;
+ struct rtw89_h2c_lps_ml_cmn_info_v1 *h2c;
+ struct rtw89_vif_link *rtwvif_link;
+ const struct rtw89_chan *chan;
+ struct rtw89_bb_ctx *bb;
+ u32 len = sizeof(*h2c);
+ unsigned int link_id;
+ struct sk_buff *skb;
+ u8 beacon_bw_ofst;
+ u32 done;
+ int ret;
+
+ if (chip->chip_gen != RTW89_CHIP_BE)
+ return 0;
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+ if (!skb) {
+ rtw89_err(rtwdev, "failed to alloc skb for h2c lps_ml_cmn_info_v1\n");
+ return -ENOMEM;
+ }
+ skb_put(skb, len);
+ h2c = (struct rtw89_h2c_lps_ml_cmn_info_v1 *)skb->data;
+
+ h2c->fmt_id = 0x20;
+
+ h2c->mlo_dbcc_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode);
+ h2c->rfe_type = efuse->rfe_type;
+ h2c->rssi_main = U8_MAX;
+
+ memset(h2c->link_id, 0xfe, RTW89_BB_PS_LINK_BUF_MAX);
+
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
+ u8 phy_idx = rtwvif_link->phy_idx;
+
+ bb = rtw89_get_bb_ctx(rtwdev, phy_idx);
+ chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
+
+ h2c->link_id[phy_idx] = phy_idx;
+ h2c->central_ch[phy_idx] = chan->channel;
+ h2c->pri_ch[phy_idx] = chan->primary_channel;
+ h2c->band[phy_idx] = chan->band_type;
+ h2c->bw[phy_idx] = chan->band_width;
+
+ if (rtwvif_link->bcn_bw_idx < ARRAY_SIZE(bcn_bw_ofst)) {
+ beacon_bw_ofst = bcn_bw_ofst[rtwvif_link->bcn_bw_idx];
+ h2c->dup_bcn_ofst[phy_idx] = beacon_bw_ofst;
+ }
+
+ if (h2c->rssi_main > bb->ch_info.rssi_min)
+ h2c->rssi_main = bb->ch_info.rssi_min;
+
+ rtw89_bb_lps_cmn_info_rx_gain_fill(rtwdev,
+ &h2c->rx_gain[phy_idx],
+ chan, phy_idx);
+ }
+
+ rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+ H2C_CAT_OUTSRC, H2C_CL_OUTSRC_DM,
+ H2C_FUNC_FW_LPS_ML_CMN_INFO, 0, 0, len);
+
+ rtw89_phy_write32_mask(rtwdev, R_CHK_LPS_STAT_BE4, B_CHK_LPS_STAT, 0);
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+ goto fail;
+ }
+
+ ret = read_poll_timeout(rtw89_phy_read32_mask, done, done, 50, 5000,
+ true, rtwdev, R_CHK_LPS_STAT_BE4, B_CHK_LPS_STAT);
+ if (ret)
+ rtw89_warn(rtwdev, "h2c_lps_ml_cmn_info done polling timeout\n");
+
+ return 0;
+fail:
+ dev_kfree_skb_any(skb);
+
+ return ret;
+}
+
#define H2C_P2P_ACT_LEN 20
int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
@@ -3318,6 +3653,92 @@ fail:
}
EXPORT_SYMBOL(rtw89_fw_h2c_default_cmac_tbl_g7);
+int rtw89_fw_h2c_default_cmac_tbl_be(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
+{
+ u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id;
+ bool preld = rtw89_mac_chk_preload_allow(rtwdev);
+ struct rtw89_h2c_cctlinfo_ud_be *h2c;
+ u32 len = sizeof(*h2c);
+ struct sk_buff *skb;
+ int ret;
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+ if (!skb) {
+ rtw89_err(rtwdev, "failed to alloc skb for default cmac be\n");
+ return -ENOMEM;
+ }
+ skb_put(skb, len);
+ h2c = (struct rtw89_h2c_cctlinfo_ud_be *)skb->data;
+
+ h2c->c0 = le32_encode_bits(mac_id, BE_CCTL_INFO_C0_V1_MACID) |
+ le32_encode_bits(1, BE_CCTL_INFO_C0_V1_OP);
+
+ h2c->w0 = le32_encode_bits(4, BE_CCTL_INFO_W0_DATARATE);
+ h2c->m0 = cpu_to_le32(BE_CCTL_INFO_W0_ALL);
+
+ h2c->w1 = le32_encode_bits(4, BE_CCTL_INFO_W1_DATA_RTY_LOWEST_RATE) |
+ le32_encode_bits(0xa, BE_CCTL_INFO_W1_RTSRATE) |
+ le32_encode_bits(4, BE_CCTL_INFO_W1_RTS_RTY_LOWEST_RATE);
+ h2c->m1 = cpu_to_le32(BE_CCTL_INFO_W1_ALL);
+
+ h2c->w1 = le32_encode_bits(preld, BE_CCTL_INFO_W2_PRELOAD_ENABLE);
+ h2c->m2 = cpu_to_le32(BE_CCTL_INFO_W2_ALL);
+
+ h2c->m3 = cpu_to_le32(BE_CCTL_INFO_W3_ALL);
+
+ h2c->w4 = le32_encode_bits(0xFFFF, BE_CCTL_INFO_W4_ACT_SUBCH_CBW);
+ h2c->m4 = cpu_to_le32(BE_CCTL_INFO_W4_ALL);
+
+ h2c->w5 = le32_encode_bits(2, BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING0_V1) |
+ le32_encode_bits(2, BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING1_V1) |
+ le32_encode_bits(2, BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING2_V1) |
+ le32_encode_bits(2, BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING3_V1) |
+ le32_encode_bits(2, BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING4_V1);
+ h2c->m5 = cpu_to_le32(BE_CCTL_INFO_W5_ALL);
+
+ h2c->w6 = le32_encode_bits(0xb, BE_CCTL_INFO_W6_RESP_REF_RATE);
+ h2c->m6 = cpu_to_le32(BE_CCTL_INFO_W6_ALL);
+
+ h2c->w7 = le32_encode_bits(1, BE_CCTL_INFO_W7_NC) |
+ le32_encode_bits(1, BE_CCTL_INFO_W7_NR) |
+ le32_encode_bits(1, BE_CCTL_INFO_W7_CB) |
+ le32_encode_bits(0x1, BE_CCTL_INFO_W7_CSI_PARA_EN) |
+ le32_encode_bits(0xb, BE_CCTL_INFO_W7_CSI_FIX_RATE);
+ h2c->m7 = cpu_to_le32(BE_CCTL_INFO_W7_ALL);
+
+ h2c->m8 = cpu_to_le32(BE_CCTL_INFO_W8_ALL);
+
+ h2c->w14 = le32_encode_bits(0, BE_CCTL_INFO_W14_VO_CURR_RATE) |
+ le32_encode_bits(0, BE_CCTL_INFO_W14_VI_CURR_RATE) |
+ le32_encode_bits(0, BE_CCTL_INFO_W14_BE_CURR_RATE_L);
+ h2c->m14 = cpu_to_le32(BE_CCTL_INFO_W14_ALL);
+
+ h2c->w15 = le32_encode_bits(0, BE_CCTL_INFO_W15_BE_CURR_RATE_H) |
+ le32_encode_bits(0, BE_CCTL_INFO_W15_BK_CURR_RATE) |
+ le32_encode_bits(0, BE_CCTL_INFO_W15_MGNT_CURR_RATE);
+ h2c->m15 = cpu_to_le32(BE_CCTL_INFO_W15_ALL);
+
+ rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+ H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG,
+ H2C_FUNC_MAC_CCTLINFO_UD_G7, 0, 1,
+ len);
+
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+ goto fail;
+ }
+
+ return 0;
+fail:
+ dev_kfree_skb_any(skb);
+
+ return ret;
+}
+EXPORT_SYMBOL(rtw89_fw_h2c_default_cmac_tbl_be);
+
static void __get_sta_he_pkt_padding(struct rtw89_dev *rtwdev,
struct ieee80211_link_sta *link_sta,
u8 *pads)
@@ -3648,6 +4069,134 @@ fail:
}
EXPORT_SYMBOL(rtw89_fw_h2c_assoc_cmac_tbl_g7);
+int rtw89_fw_h2c_assoc_cmac_tbl_be(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
+{
+ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
+ u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id;
+ struct rtw89_h2c_cctlinfo_ud_be *h2c;
+ struct ieee80211_bss_conf *bss_conf;
+ struct ieee80211_link_sta *link_sta;
+ u8 pads[RTW89_PPE_BW_NUM];
+ u32 len = sizeof(*h2c);
+ struct sk_buff *skb;
+ u16 lowest_rate;
+ int ret;
+
+ memset(pads, 0, sizeof(pads));
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+ if (!skb) {
+ rtw89_err(rtwdev, "failed to alloc skb for assoc cmac be\n");
+ return -ENOMEM;
+ }
+
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
+
+ if (rtwsta_link) {
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true);
+
+ if (link_sta->eht_cap.has_eht)
+ __get_sta_eht_pkt_padding(rtwdev, link_sta, pads);
+ else if (link_sta->he_cap.has_he)
+ __get_sta_he_pkt_padding(rtwdev, link_sta, pads);
+ }
+
+ if (vif->p2p)
+ lowest_rate = RTW89_HW_RATE_OFDM6;
+ else if (chan->band_type == RTW89_BAND_2G)
+ lowest_rate = RTW89_HW_RATE_CCK1;
+ else
+ lowest_rate = RTW89_HW_RATE_OFDM6;
+
+ skb_put(skb, len);
+ h2c = (struct rtw89_h2c_cctlinfo_ud_be *)skb->data;
+
+ h2c->c0 = le32_encode_bits(mac_id, BE_CCTL_INFO_C0_V1_MACID) |
+ le32_encode_bits(1, BE_CCTL_INFO_C0_V1_OP);
+
+ h2c->w0 = le32_encode_bits(1, BE_CCTL_INFO_W0_DISRTSFB) |
+ le32_encode_bits(1, BE_CCTL_INFO_W0_DISDATAFB);
+ h2c->m0 = cpu_to_le32(BE_CCTL_INFO_W0_DISRTSFB |
+ BE_CCTL_INFO_W0_DISDATAFB);
+
+ h2c->w1 = le32_encode_bits(lowest_rate, BE_CCTL_INFO_W1_RTS_RTY_LOWEST_RATE);
+ h2c->m1 = cpu_to_le32(BE_CCTL_INFO_W1_RTS_RTY_LOWEST_RATE);
+
+ h2c->w2 = le32_encode_bits(0, BE_CCTL_INFO_W2_DATA_TXCNT_LMT_SEL);
+ h2c->m2 = cpu_to_le32(BE_CCTL_INFO_W2_DATA_TXCNT_LMT_SEL);
+
+ h2c->w3 = le32_encode_bits(0, BE_CCTL_INFO_W3_RTS_TXCNT_LMT_SEL);
+ h2c->m3 = cpu_to_le32(BE_CCTL_INFO_W3_RTS_TXCNT_LMT_SEL);
+
+ h2c->w4 = le32_encode_bits(rtwvif_link->port, BE_CCTL_INFO_W4_MULTI_PORT_ID);
+ h2c->m4 = cpu_to_le32(BE_CCTL_INFO_W4_MULTI_PORT_ID);
+
+ if (bss_conf->eht_support) {
+ u16 punct = bss_conf->chanreq.oper.punctured;
+
+ h2c->w4 |= le32_encode_bits(~punct,
+ BE_CCTL_INFO_W4_ACT_SUBCH_CBW);
+ h2c->m4 |= cpu_to_le32(BE_CCTL_INFO_W4_ACT_SUBCH_CBW);
+ }
+
+ h2c->w5 = le32_encode_bits(pads[RTW89_CHANNEL_WIDTH_20],
+ BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING0_V1) |
+ le32_encode_bits(pads[RTW89_CHANNEL_WIDTH_40],
+ BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING1_V1) |
+ le32_encode_bits(pads[RTW89_CHANNEL_WIDTH_80],
+ BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING2_V1) |
+ le32_encode_bits(pads[RTW89_CHANNEL_WIDTH_160],
+ BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING3_V1) |
+ le32_encode_bits(pads[RTW89_CHANNEL_WIDTH_320],
+ BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING4_V1);
+ h2c->m5 = cpu_to_le32(BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING0_V1 |
+ BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING1_V1 |
+ BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING2_V1 |
+ BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING3_V1 |
+ BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING4_V1);
+
+ if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) {
+ h2c->w5 |= le32_encode_bits(0, BE_CCTL_INFO_W5_DATA_DCM_V1);
+ h2c->m5 |= cpu_to_le32(BE_CCTL_INFO_W5_DATA_DCM_V1);
+ }
+
+ h2c->w6 = le32_encode_bits(vif->cfg.aid, BE_CCTL_INFO_W6_AID12_PAID) |
+ le32_encode_bits(vif->type == NL80211_IFTYPE_STATION ? 1 : 0,
+ BE_CCTL_INFO_W6_ULDL);
+ h2c->m6 = cpu_to_le32(BE_CCTL_INFO_W6_AID12_PAID | BE_CCTL_INFO_W6_ULDL);
+
+ if (rtwsta_link) {
+ h2c->w8 = le32_encode_bits(link_sta->he_cap.has_he,
+ BE_CCTL_INFO_W8_BSR_QUEUE_SIZE_FORMAT_V1);
+ h2c->m8 = cpu_to_le32(BE_CCTL_INFO_W8_BSR_QUEUE_SIZE_FORMAT_V1);
+ }
+
+ rcu_read_unlock();
+
+ rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+ H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG,
+ H2C_FUNC_MAC_CCTLINFO_UD_G7, 0, 1,
+ len);
+
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+ goto fail;
+ }
+
+ return 0;
+fail:
+ dev_kfree_skb_any(skb);
+
+ return ret;
+}
+EXPORT_SYMBOL(rtw89_fw_h2c_assoc_cmac_tbl_be);
+
int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_link)
@@ -3714,6 +4263,72 @@ fail:
}
EXPORT_SYMBOL(rtw89_fw_h2c_ampdu_cmac_tbl_g7);
+int rtw89_fw_h2c_ampdu_cmac_tbl_be(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
+{
+ struct rtw89_sta *rtwsta = rtwsta_link->rtwsta;
+ struct rtw89_h2c_cctlinfo_ud_be *h2c;
+ u32 len = sizeof(*h2c);
+ struct sk_buff *skb;
+ u16 agg_num = 0;
+ u8 ba_bmap = 0;
+ int ret;
+ u8 tid;
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+ if (!skb) {
+ rtw89_err(rtwdev, "failed to alloc skb for ampdu cmac be\n");
+ return -ENOMEM;
+ }
+ skb_put(skb, len);
+ h2c = (struct rtw89_h2c_cctlinfo_ud_be *)skb->data;
+
+ for_each_set_bit(tid, rtwsta->ampdu_map, IEEE80211_NUM_TIDS) {
+ if (agg_num == 0)
+ agg_num = rtwsta->ampdu_params[tid].agg_num;
+ else
+ agg_num = min(agg_num, rtwsta->ampdu_params[tid].agg_num);
+ }
+
+ if (agg_num <= 0x20)
+ ba_bmap = 3;
+ else if (agg_num > 0x20 && agg_num <= 0x40)
+ ba_bmap = 0;
+ else if (agg_num > 0x40 && agg_num <= 0x80)
+ ba_bmap = 1;
+ else if (agg_num > 0x80 && agg_num <= 0x100)
+ ba_bmap = 2;
+ else if (agg_num > 0x100 && agg_num <= 0x200)
+ ba_bmap = 4;
+ else if (agg_num > 0x200 && agg_num <= 0x400)
+ ba_bmap = 5;
+
+ h2c->c0 = le32_encode_bits(rtwsta_link->mac_id, BE_CCTL_INFO_C0_V1_MACID) |
+ le32_encode_bits(1, BE_CCTL_INFO_C0_V1_OP);
+
+ h2c->w3 = le32_encode_bits(ba_bmap, BE_CCTL_INFO_W3_BA_BMAP);
+ h2c->m3 = cpu_to_le32(BE_CCTL_INFO_W3_BA_BMAP);
+
+ rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+ H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG,
+ H2C_FUNC_MAC_CCTLINFO_UD_G7, 0, 0,
+ len);
+
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+ goto fail;
+ }
+
+ return 0;
+fail:
+ dev_kfree_skb_any(skb);
+
+ return ret;
+}
+EXPORT_SYMBOL(rtw89_fw_h2c_ampdu_cmac_tbl_be);
+
int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev,
struct rtw89_sta_link *rtwsta_link)
{
@@ -3811,6 +4426,60 @@ fail:
}
EXPORT_SYMBOL(rtw89_fw_h2c_txtime_cmac_tbl_g7);
+int rtw89_fw_h2c_txtime_cmac_tbl_be(struct rtw89_dev *rtwdev,
+ struct rtw89_sta_link *rtwsta_link)
+{
+ struct rtw89_h2c_cctlinfo_ud_be *h2c;
+ u32 len = sizeof(*h2c);
+ struct sk_buff *skb;
+ int ret;
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+ if (!skb) {
+ rtw89_err(rtwdev, "failed to alloc skb for txtime_cmac_be\n");
+ return -ENOMEM;
+ }
+ skb_put(skb, len);
+ h2c = (struct rtw89_h2c_cctlinfo_ud_be *)skb->data;
+
+ h2c->c0 = le32_encode_bits(rtwsta_link->mac_id, BE_CCTL_INFO_C0_V1_MACID) |
+ le32_encode_bits(1, BE_CCTL_INFO_C0_V1_OP);
+
+ if (rtwsta_link->cctl_tx_time) {
+ h2c->w3 |= le32_encode_bits(1, BE_CCTL_INFO_W3_AMPDU_TIME_SEL);
+ h2c->m3 |= cpu_to_le32(BE_CCTL_INFO_W3_AMPDU_TIME_SEL);
+
+ h2c->w2 |= le32_encode_bits(rtwsta_link->ampdu_max_time,
+ BE_CCTL_INFO_W2_AMPDU_MAX_TIME);
+ h2c->m2 |= cpu_to_le32(BE_CCTL_INFO_W2_AMPDU_MAX_TIME);
+ }
+ if (rtwsta_link->cctl_tx_retry_limit) {
+ h2c->w2 |= le32_encode_bits(1, BE_CCTL_INFO_W2_DATA_TXCNT_LMT_SEL) |
+ le32_encode_bits(rtwsta_link->data_tx_cnt_lmt,
+ BE_CCTL_INFO_W2_DATA_TX_CNT_LMT);
+ h2c->m2 |= cpu_to_le32(BE_CCTL_INFO_W2_DATA_TXCNT_LMT_SEL |
+ BE_CCTL_INFO_W2_DATA_TX_CNT_LMT);
+ }
+
+ rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+ H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG,
+ H2C_FUNC_MAC_CCTLINFO_UD_G7, 0, 1,
+ len);
+
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+ goto fail;
+ }
+
+ return 0;
+fail:
+ dev_kfree_skb_any(skb);
+
+ return ret;
+}
+EXPORT_SYMBOL(rtw89_fw_h2c_txtime_cmac_tbl_be);
+
int rtw89_fw_h2c_punctured_cmac_tbl_g7(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
u16 punctured)
@@ -3854,6 +4523,48 @@ fail:
}
EXPORT_SYMBOL(rtw89_fw_h2c_punctured_cmac_tbl_g7);
+int rtw89_fw_h2c_punctured_cmac_tbl_be(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ u16 punctured)
+{
+ struct rtw89_h2c_cctlinfo_ud_be *h2c;
+ u32 len = sizeof(*h2c);
+ struct sk_buff *skb;
+ int ret;
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+ if (!skb) {
+ rtw89_err(rtwdev, "failed to alloc skb for punctured cmac be\n");
+ return -ENOMEM;
+ }
+ skb_put(skb, len);
+ h2c = (struct rtw89_h2c_cctlinfo_ud_be *)skb->data;
+
+ h2c->c0 = le32_encode_bits(rtwvif_link->mac_id, BE_CCTL_INFO_C0_V1_MACID) |
+ le32_encode_bits(1, BE_CCTL_INFO_C0_V1_OP);
+
+ h2c->w4 = le32_encode_bits(~punctured, BE_CCTL_INFO_W4_ACT_SUBCH_CBW);
+ h2c->m4 = cpu_to_le32(BE_CCTL_INFO_W4_ACT_SUBCH_CBW);
+
+ rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+ H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG,
+ H2C_FUNC_MAC_CCTLINFO_UD_G7, 0, 1,
+ len);
+
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+ goto fail;
+ }
+
+ return 0;
+fail:
+ dev_kfree_skb_any(skb);
+
+ return ret;
+}
+EXPORT_SYMBOL(rtw89_fw_h2c_punctured_cmac_tbl_be);
+
int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev,
struct rtw89_sta_link *rtwsta_link)
{
@@ -5935,27 +6646,18 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev,
u8 scan_offload_ver = U8_MAX;
u8 cfg_len = sizeof(*h2c);
unsigned int cond;
- u8 ap_idx = U8_MAX;
u8 ver = U8_MAX;
u8 policy_val;
void *ptr;
+ u8 txnull;
u8 txbcn;
int ret;
u32 len;
u8 i;
- scan_op[0].macid = rtwvif_link->mac_id;
- scan_op[0].port = rtwvif_link->port;
- scan_op[0].chan = *op;
- vif = rtwvif_to_vif(rtwvif_link->rtwvif);
- if (vif->type == NL80211_IFTYPE_AP)
- ap_idx = 0;
-
- if (ext->set) {
- scan_op[1] = *ext;
- vif = rtwvif_to_vif(ext->rtwvif_link->rtwvif);
- if (vif->type == NL80211_IFTYPE_AP)
- ap_idx = 1;
+ if (option->num_opch > RTW89_MAX_OP_NUM_BE) {
+ rtw89_err(rtwdev, "num of scan OP chan %d over limit\n", option->num_opch);
+ return -ENOENT;
}
rtw89_scan_get_6g_disabled_chan(rtwdev, option);
@@ -6060,11 +6762,29 @@ flex_member:
}
for (i = 0; i < option->num_opch; i++) {
- bool is_ap_idx = i == ap_idx;
+ struct rtw89_vif_link *rtwvif_link_op;
+ bool is_ap;
+
+ switch (i) {
+ case 0:
+ scan_op[0].macid = rtwvif_link->mac_id;
+ scan_op[0].port = rtwvif_link->port;
+ scan_op[0].chan = *op;
+ rtwvif_link_op = rtwvif_link;
+ break;
+ case 1:
+ scan_op[1] = *ext;
+ rtwvif_link_op = ext->rtwvif_link;
+ break;
+ }
- opmode = is_ap_idx ? RTW89_SCAN_OPMODE_TBTT : RTW89_SCAN_OPMODE_INTV;
- policy_val = is_ap_idx ? 2 : RTW89_OFF_CHAN_TIME / 10;
- txbcn = is_ap_idx ? 1 : 0;
+ vif = rtwvif_to_vif(rtwvif_link_op->rtwvif);
+ is_ap = vif->type == NL80211_IFTYPE_AP;
+ txnull = !is_zero_ether_addr(rtwvif_link_op->bssid) &&
+ vif->type != NL80211_IFTYPE_AP;
+ opmode = is_ap ? RTW89_SCAN_OPMODE_TBTT : RTW89_SCAN_OPMODE_INTV;
+ policy_val = is_ap ? 2 : RTW89_OFF_CHAN_TIME / 10;
+ txbcn = is_ap ? 1 : 0;
opch = ptr;
opch->w0 = le32_encode_bits(scan_op[i].macid,
@@ -6075,7 +6795,7 @@ flex_member:
RTW89_H2C_SCANOFLD_BE_OPCH_W0_PORT) |
le32_encode_bits(opmode,
RTW89_H2C_SCANOFLD_BE_OPCH_W0_POLICY) |
- le32_encode_bits(true,
+ le32_encode_bits(txnull,
RTW89_H2C_SCANOFLD_BE_OPCH_W0_TXNULL) |
le32_encode_bits(policy_val,
RTW89_H2C_SCANOFLD_BE_OPCH_W0_POLICY_VAL);
@@ -6349,6 +7069,7 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev,
struct rtw89_fw_h2c_rfk_pre_info_common *common;
struct rtw89_fw_h2c_rfk_pre_info_v0 *h2c_v0;
struct rtw89_fw_h2c_rfk_pre_info_v1 *h2c_v1;
+ struct rtw89_fw_h2c_rfk_pre_info_v2 *h2c_v2;
struct rtw89_fw_h2c_rfk_pre_info *h2c;
u8 tbl_sel[NUM_OF_RTW89_FW_RFK_PATH];
u32 len = sizeof(*h2c);
@@ -6358,7 +7079,11 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev,
u32 val32;
int ret;
- if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_V1, &rtwdev->fw)) {
+ if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_V3, &rtwdev->fw)) {
+ } else if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_V2, &rtwdev->fw)) {
+ len = sizeof(*h2c_v2);
+ ver = 2;
+ } else if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_V1, &rtwdev->fw)) {
len = sizeof(*h2c_v1);
ver = 1;
} else if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_V0, &rtwdev->fw)) {
@@ -6372,8 +7097,21 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev,
return -ENOMEM;
}
skb_put(skb, len);
+
+ if (ver <= 2)
+ goto old_format;
+
h2c = (struct rtw89_fw_h2c_rfk_pre_info *)skb->data;
- common = &h2c->base_v1.common;
+
+ h2c->mlo_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode);
+ h2c->phy_idx = cpu_to_le32(phy_idx);
+ h2c->mlo_1_1 = cpu_to_le32(rtw89_is_mlo_1_1(rtwdev));
+
+ goto done;
+
+old_format:
+ h2c_v2 = (struct rtw89_fw_h2c_rfk_pre_info_v2 *)skb->data;
+ common = &h2c_v2->base_v1.common;
common->mlo_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode);
@@ -6400,7 +7138,7 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev,
if (ver <= 1)
continue;
- h2c->cur_bandwidth[path] =
+ h2c_v2->cur_bandwidth[path] =
cpu_to_le32(rfk_mcc->data[path].bw[tbl_sel[path]]);
}
@@ -6431,7 +7169,7 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev,
}
if (rtw89_is_mlo_1_1(rtwdev)) {
- h2c_v1 = &h2c->base_v1;
+ h2c_v1 = &h2c_v2->base_v1;
h2c_v1->mlo_1_1 = cpu_to_le32(1);
}
done:
@@ -6453,9 +7191,108 @@ fail:
return ret;
}
+int rtw89_fw_h2c_rf_pre_ntfy_mcc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
+{
+ struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data;
+ struct rtw89_rfk_mcc_info *rfk_mcc_v0 = &rtwdev->rfk_mcc;
+ struct rtw89_fw_h2c_rfk_pre_info_mcc_v0 *h2c_v0;
+ struct rtw89_fw_h2c_rfk_pre_info_mcc_v1 *h2c_v1;
+ struct rtw89_fw_h2c_rfk_pre_info_mcc *h2c;
+ struct rtw89_hal *hal = &rtwdev->hal;
+ u32 len = sizeof(*h2c);
+ struct sk_buff *skb;
+ u8 ver = U8_MAX;
+ u8 tbl, path;
+ u8 tbl_sel;
+ int ret;
+
+ if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_MCC_V2, &rtwdev->fw)) {
+ } else if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_MCC_V1, &rtwdev->fw)) {
+ len = sizeof(*h2c_v1);
+ ver = 1;
+ } else if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_MCC_V0, &rtwdev->fw)) {
+ len = sizeof(*h2c_v0);
+ ver = 0;
+ }
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+ if (!skb) {
+ rtw89_err(rtwdev, "failed to alloc skb for h2c rfk_pre_ntfy_mcc\n");
+ return -ENOMEM;
+ }
+ skb_put(skb, len);
+
+ if (ver != 0)
+ goto v1;
+
+ h2c_v0 = (struct rtw89_fw_h2c_rfk_pre_info_mcc_v0 *)skb->data;
+ for (tbl = 0; tbl < NUM_OF_RTW89_FW_RFK_TBL; tbl++) {
+ for (path = 0; path < NUM_OF_RTW89_FW_RFK_PATH; path++) {
+ h2c_v0->tbl_18[tbl][path] =
+ cpu_to_le32(rfk_mcc_v0->data[path].rf18[tbl]);
+ tbl_sel = rfk_mcc_v0->data[path].table_idx;
+ h2c_v0->cur_18[path] =
+ cpu_to_le32(rfk_mcc_v0->data[path].rf18[tbl_sel]);
+ }
+ }
+
+ h2c_v0->mlo_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode);
+ goto done;
+
+v1:
+ h2c_v1 = (struct rtw89_fw_h2c_rfk_pre_info_mcc_v1 *)skb->data;
+
+ BUILD_BUG_ON(NUM_OF_RTW89_FW_RFK_TBL > RTW89_RFK_CHS_NR);
+
+ for (tbl = 0; tbl < NUM_OF_RTW89_FW_RFK_TBL; tbl++)
+ h2c_v1->tbl_18[tbl] = cpu_to_le32(rfk_mcc->rf18[tbl]);
+
+ BUILD_BUG_ON(ARRAY_SIZE(rtwdev->rfk_mcc.data) < NUM_OF_RTW89_FW_RFK_PATH);
+
+ /* shared table array, but tbl_sel can be independent by path */
+ for (path = 0; path < NUM_OF_RTW89_FW_RFK_PATH; path++) {
+ tbl = rfk_mcc[path].table_idx;
+ h2c_v1->cur_18[path] = cpu_to_le32(rfk_mcc->rf18[tbl]);
+
+ if (path == phy_idx)
+ h2c_v1->tbl_idx = tbl;
+ }
+
+ h2c_v1->mlo_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode);
+ h2c_v1->phy_idx = phy_idx;
+
+ if (rtw89_is_mlo_1_1(rtwdev))
+ h2c_v1->mlo_1_1 = cpu_to_le32(1);
+
+ if (ver == 1)
+ goto done;
+
+ h2c = (struct rtw89_fw_h2c_rfk_pre_info_mcc *)skb->data;
+
+ h2c->aid = cpu_to_le32(hal->aid);
+
+done:
+ rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+ H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_NOTIFY,
+ H2C_FUNC_OUTSRC_RF_MCC_INFO, 0, 0, len);
+
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+ goto fail;
+ }
+
+ return 0;
+fail:
+ dev_kfree_skb_any(skb);
+
+ return ret;
+}
+
int rtw89_fw_h2c_rf_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
const struct rtw89_chan *chan, enum rtw89_tssi_mode tssi_mode)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_efuse *efuse = &rtwdev->efuse;
struct rtw89_hal *hal = &rtwdev->hal;
struct rtw89_h2c_rf_tssi *h2c;
@@ -6476,11 +7313,15 @@ int rtw89_fw_h2c_rf_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
h2c->ch = chan->channel;
h2c->bw = chan->band_width;
h2c->band = chan->band_type;
- h2c->hwtx_en = true;
h2c->cv = hal->cv;
h2c->tssi_mode = tssi_mode;
h2c->rfe_type = efuse->rfe_type;
+ if (chip->chip_id == RTL8922A)
+ h2c->hwtx_en = true;
+ else
+ h2c->hwtx_en = false;
+
rtw89_phy_rfk_tssi_fill_fwcmd_efuse_to_de(rtwdev, phy_idx, chan, h2c);
rtw89_phy_rfk_tssi_fill_fwcmd_tmeter_tbl(rtwdev, phy_idx, chan, h2c);
@@ -6663,9 +7504,9 @@ int rtw89_fw_h2c_rf_dack(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
skb_put(skb, len);
h2c = (struct rtw89_h2c_rf_dack *)skb->data;
- h2c->len = cpu_to_le32(len);
- h2c->phy = cpu_to_le32(phy_idx);
- h2c->type = cpu_to_le32(0);
+ h2c->len = len;
+ h2c->phy = phy_idx;
+ h2c->type = 0;
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK,
@@ -6774,6 +7615,90 @@ fail:
return ret;
}
+int rtw89_fw_h2c_rf_txiqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ const struct rtw89_chan *chan)
+{
+ struct rtw89_h2c_rf_txiqk *h2c;
+ u32 len = sizeof(*h2c);
+ struct sk_buff *skb;
+ int ret;
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+ if (!skb) {
+ rtw89_err(rtwdev, "failed to alloc skb for h2c RF TXIQK\n");
+ return -ENOMEM;
+ }
+ skb_put(skb, len);
+ h2c = (struct rtw89_h2c_rf_txiqk *)skb->data;
+
+ h2c->len = len;
+ h2c->phy = phy_idx;
+ h2c->txiqk_enable = true;
+ h2c->is_wb_txiqk = true;
+ h2c->kpath = RF_AB;
+ h2c->cur_band = chan->band_type;
+ h2c->cur_bw = chan->band_width;
+ h2c->cur_ch = chan->channel;
+ h2c->txiqk_dbg_en = rtw89_debug_is_enabled(rtwdev, RTW89_DBG_RFK);
+
+ rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+ H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK,
+ H2C_FUNC_RFK_TXIQK_OFFOAD, 0, 0, len);
+
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+ goto fail;
+ }
+
+ return 0;
+fail:
+ dev_kfree_skb_any(skb);
+
+ return ret;
+}
+
+int rtw89_fw_h2c_rf_cim3k(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ const struct rtw89_chan *chan)
+{
+ struct rtw89_h2c_rf_cim3k *h2c;
+ u32 len = sizeof(*h2c);
+ struct sk_buff *skb;
+ int ret;
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+ if (!skb) {
+ rtw89_err(rtwdev, "failed to alloc skb for h2c RF CIM3K\n");
+ return -ENOMEM;
+ }
+ skb_put(skb, len);
+ h2c = (struct rtw89_h2c_rf_cim3k *)skb->data;
+
+ h2c->len = len;
+ h2c->phy = phy_idx;
+ h2c->kpath = RF_AB;
+ h2c->cur_band = chan->band_type;
+ h2c->cur_bw = chan->band_width;
+ h2c->cur_ch = chan->channel;
+ h2c->cim3k_dbg_en = rtw89_debug_is_enabled(rtwdev, RTW89_DBG_RFK);
+
+ rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+ H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK,
+ H2C_FUNC_RFK_CIM3K_OFFOAD, 0, 0, len);
+
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+ goto fail;
+ }
+
+ return 0;
+fail:
+ dev_kfree_skb_any(skb);
+
+ return ret;
+}
+
int rtw89_fw_h2c_raw_with_hdr(struct rtw89_dev *rtwdev,
u8 h2c_class, u8 h2c_func, u8 *buf, u16 len,
bool rack, bool dack)
@@ -6859,6 +7784,17 @@ void rtw89_fw_free_all_early_h2c(struct rtw89_dev *rtwdev)
__rtw89_fw_free_all_early_h2c(rtwdev);
}
+void rtw89_fw_c2h_dummy_handler(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
+{
+ struct rtw89_fw_c2h_attr *attr = RTW89_SKB_C2H_CB(c2h);
+ u8 category = attr->category;
+ u8 class = attr->class;
+ u8 func = attr->func;
+
+ rtw89_debug(rtwdev, RTW89_DBG_FW,
+ "C2H cate=%u cls=%u func=%u is dummy\n", category, class, func);
+}
+
static void rtw89_fw_c2h_parse_attr(struct sk_buff *c2h)
{
const struct rtw89_c2h_hdr *hdr = (const struct rtw89_c2h_hdr *)c2h->data;
@@ -7044,6 +7980,9 @@ static int rtw89_fw_read_c2h_reg(struct rtw89_dev *rtwdev,
else
timeout = RTW89_C2H_TIMEOUT;
+ if (info->timeout)
+ timeout = info->timeout;
+
ret = read_poll_timeout_atomic(rtw89_read8, val, val, 1,
timeout, false, rtwdev,
chip->c2h_ctrl_reg);
@@ -7384,6 +8323,7 @@ static void rtw89_hw_scan_add_chan_ax(struct rtw89_dev *rtwdev, int chan_type,
struct cfg80211_scan_request *req = rtwvif->scan_req;
struct rtw89_chan *op = &rtwdev->scan_info.op_chan;
struct rtw89_pktofld_info *info;
+ struct ieee80211_vif *vif;
u8 band, probe_count = 0;
int ret;
@@ -7436,7 +8376,9 @@ static void rtw89_hw_scan_add_chan_ax(struct rtw89_dev *rtwdev, int chan_type,
ch_info->pri_ch = op->primary_channel;
ch_info->ch_band = op->band_type;
ch_info->bw = op->band_width;
- ch_info->tx_null = true;
+ vif = rtwvif_link_to_vif(rtwvif_link);
+ ch_info->tx_null = !is_zero_ether_addr(rtwvif_link->bssid) &&
+ vif->type != NL80211_IFTYPE_AP;
ch_info->num_pkt = 0;
break;
case RTW89_CHAN_DFS:
@@ -7454,7 +8396,9 @@ static void rtw89_hw_scan_add_chan_ax(struct rtw89_dev *rtwdev, int chan_type,
ch_info->pri_ch = ext->chan.primary_channel;
ch_info->ch_band = ext->chan.band_type;
ch_info->bw = ext->chan.band_width;
- ch_info->tx_null = true;
+ vif = rtwvif_link_to_vif(ext->rtwvif_link);
+ ch_info->tx_null = !is_zero_ether_addr(ext->rtwvif_link->bssid) &&
+ vif->type != NL80211_IFTYPE_AP;
ch_info->num_pkt = 0;
ch_info->macid_tx = true;
break;
@@ -8083,12 +9027,9 @@ static void rtw89_hw_scan_set_extra_op_info(struct rtw89_dev *rtwdev,
if (tmp == scan_rtwvif)
continue;
- tmp_link = rtw89_vif_get_link_inst(tmp, 0);
- if (unlikely(!tmp_link)) {
- rtw89_debug(rtwdev, RTW89_DBG_HW_SCAN,
- "hw scan: no HW-0 link for extra op\n");
+ tmp_link = rtw89_get_designated_link(tmp);
+ if (unlikely(!tmp_link))
continue;
- }
tmp_chan = rtw89_chan_get(rtwdev, tmp_link->chanctx_idx);
*ext = (struct rtw89_hw_scan_extra_op){
@@ -8114,6 +9055,7 @@ int rtw89_hw_scan_start(struct rtw89_dev *rtwdev,
struct cfg80211_scan_request *req = &scan_req->req;
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
rtwvif_link->chanctx_idx);
+ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
struct rtw89_chanctx_pause_parm pause_parm = {
.rsn = RTW89_CHANCTX_PAUSE_REASON_HW_SCAN,
@@ -8142,6 +9084,8 @@ int rtw89_hw_scan_start(struct rtw89_dev *rtwdev,
if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
get_random_mask_addr(mac_addr, req->mac_addr,
req->mac_addr_mask);
+ else if (ieee80211_vif_is_mld(vif))
+ ether_addr_copy(mac_addr, vif->addr);
else
ether_addr_copy(mac_addr, rtwvif_link->mac_addr);
@@ -8705,44 +9649,106 @@ fail:
return ret;
}
-#define H2C_WOW_CAM_UPD_LEN 24
-int rtw89_fw_wow_cam_update(struct rtw89_dev *rtwdev,
- struct rtw89_wow_cam_info *cam_info)
+int rtw89_fw_h2c_wow_cam_update(struct rtw89_dev *rtwdev,
+ struct rtw89_wow_cam_info *cam_info)
{
+ struct rtw89_h2c_wow_cam_update *h2c;
+ u32 len = sizeof(*h2c);
struct sk_buff *skb;
int ret;
- skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_WOW_CAM_UPD_LEN);
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
if (!skb) {
- rtw89_err(rtwdev, "failed to alloc skb for keep alive\n");
+ rtw89_err(rtwdev, "failed to alloc skb for wow cam update\n");
return -ENOMEM;
}
+ skb_put(skb, len);
+ h2c = (struct rtw89_h2c_wow_cam_update *)skb->data;
+
+ h2c->w0 = le32_encode_bits(cam_info->r_w, RTW89_H2C_WOW_CAM_UPD_W0_R_W) |
+ le32_encode_bits(cam_info->idx, RTW89_H2C_WOW_CAM_UPD_W0_IDX);
+
+ if (!cam_info->valid)
+ goto fill_valid;
+
+ h2c->wkfm0 = cam_info->mask[0];
+ h2c->wkfm1 = cam_info->mask[1];
+ h2c->wkfm2 = cam_info->mask[2];
+ h2c->wkfm3 = cam_info->mask[3];
+ h2c->w5 = le32_encode_bits(cam_info->crc, RTW89_H2C_WOW_CAM_UPD_W5_CRC) |
+ le32_encode_bits(cam_info->negative_pattern_match,
+ RTW89_H2C_WOW_CAM_UPD_W5_NEGATIVE_PATTERN_MATCH) |
+ le32_encode_bits(cam_info->skip_mac_hdr,
+ RTW89_H2C_WOW_CAM_UPD_W5_SKIP_MAC_HDR) |
+ le32_encode_bits(cam_info->uc, RTW89_H2C_WOW_CAM_UPD_W5_UC) |
+ le32_encode_bits(cam_info->mc, RTW89_H2C_WOW_CAM_UPD_W5_MC) |
+ le32_encode_bits(cam_info->bc, RTW89_H2C_WOW_CAM_UPD_W5_BC);
+fill_valid:
+ h2c->w5 |= le32_encode_bits(cam_info->valid, RTW89_H2C_WOW_CAM_UPD_W5_VALID);
- skb_put(skb, H2C_WOW_CAM_UPD_LEN);
+ rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+ H2C_CAT_MAC,
+ H2C_CL_MAC_WOW,
+ H2C_FUNC_WOW_CAM_UPD, 0, 1,
+ len);
- RTW89_SET_WOW_CAM_UPD_R_W(skb->data, cam_info->r_w);
- RTW89_SET_WOW_CAM_UPD_IDX(skb->data, cam_info->idx);
- if (cam_info->valid) {
- RTW89_SET_WOW_CAM_UPD_WKFM1(skb->data, cam_info->mask[0]);
- RTW89_SET_WOW_CAM_UPD_WKFM2(skb->data, cam_info->mask[1]);
- RTW89_SET_WOW_CAM_UPD_WKFM3(skb->data, cam_info->mask[2]);
- RTW89_SET_WOW_CAM_UPD_WKFM4(skb->data, cam_info->mask[3]);
- RTW89_SET_WOW_CAM_UPD_CRC(skb->data, cam_info->crc);
- RTW89_SET_WOW_CAM_UPD_NEGATIVE_PATTERN_MATCH(skb->data,
- cam_info->negative_pattern_match);
- RTW89_SET_WOW_CAM_UPD_SKIP_MAC_HDR(skb->data,
- cam_info->skip_mac_hdr);
- RTW89_SET_WOW_CAM_UPD_UC(skb->data, cam_info->uc);
- RTW89_SET_WOW_CAM_UPD_MC(skb->data, cam_info->mc);
- RTW89_SET_WOW_CAM_UPD_BC(skb->data, cam_info->bc);
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+ goto fail;
}
- RTW89_SET_WOW_CAM_UPD_VALID(skb->data, cam_info->valid);
+ return 0;
+fail:
+ dev_kfree_skb_any(skb);
+
+ return ret;
+}
+EXPORT_SYMBOL(rtw89_fw_h2c_wow_cam_update);
+
+int rtw89_fw_h2c_wow_cam_update_v1(struct rtw89_dev *rtwdev,
+ struct rtw89_wow_cam_info *cam_info)
+{
+ struct rtw89_h2c_wow_payload_cam_update *h2c;
+ u32 len = sizeof(*h2c);
+ struct sk_buff *skb;
+ int ret;
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+ if (!skb) {
+ rtw89_err(rtwdev, "failed to alloc skb for wow payload cam update\n");
+ return -ENOMEM;
+ }
+ skb_put(skb, len);
+ h2c = (struct rtw89_h2c_wow_payload_cam_update *)skb->data;
+
+ h2c->w0 = le32_encode_bits(cam_info->r_w, RTW89_H2C_WOW_PLD_CAM_UPD_W0_R_W) |
+ le32_encode_bits(cam_info->idx, RTW89_H2C_WOW_PLD_CAM_UPD_W0_IDX);
+ h2c->w8 = le32_encode_bits(cam_info->valid, RTW89_H2C_WOW_PLD_CAM_UPD_W8_VALID) |
+ le32_encode_bits(1, RTW89_H2C_WOW_PLD_CAM_UPD_W8_WOW_PTR);
+
+ if (!cam_info->valid)
+ goto done;
+
+ h2c->wkfm0 = cam_info->mask[0];
+ h2c->wkfm1 = cam_info->mask[1];
+ h2c->wkfm2 = cam_info->mask[2];
+ h2c->wkfm3 = cam_info->mask[3];
+ h2c->w5 = le32_encode_bits(cam_info->uc, RTW89_H2C_WOW_PLD_CAM_UPD_W5_UC) |
+ le32_encode_bits(cam_info->mc, RTW89_H2C_WOW_PLD_CAM_UPD_W5_MC) |
+ le32_encode_bits(cam_info->bc, RTW89_H2C_WOW_PLD_CAM_UPD_W5_BC) |
+ le32_encode_bits(cam_info->skip_mac_hdr,
+ RTW89_H2C_WOW_PLD_CAM_UPD_W5_SKIP_MAC_HDR);
+ h2c->w6 = le32_encode_bits(cam_info->crc, RTW89_H2C_WOW_PLD_CAM_UPD_W6_CRC);
+ h2c->w7 = le32_encode_bits(cam_info->negative_pattern_match,
+ RTW89_H2C_WOW_PLD_CAM_UPD_W7_NEGATIVE_PATTERN_MATCH);
+
+done:
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_MAC,
H2C_CL_MAC_WOW,
- H2C_FUNC_WOW_CAM_UPD, 0, 1,
- H2C_WOW_CAM_UPD_LEN);
+ H2C_FUNC_WOW_PLD_CAM_UPD, 0, 1,
+ len);
ret = rtw89_h2c_tx(rtwdev, skb, false);
if (ret) {
@@ -8756,6 +9762,7 @@ fail:
return ret;
}
+EXPORT_SYMBOL(rtw89_fw_h2c_wow_cam_update_v1);
int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
index cedb4a47a769..d45b6ea6ea1b 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.h
+++ b/drivers/net/wireless/realtek/rtw89/fw.h
@@ -42,6 +42,10 @@ struct rtw89_c2hreg_phycap {
#define RTW89_C2HREG_PHYCAP_W0_BW GENMASK(31, 24)
#define RTW89_C2HREG_PHYCAP_W1_TX_NSS GENMASK(7, 0)
#define RTW89_C2HREG_PHYCAP_W1_PROT GENMASK(15, 8)
+#define RTW89_C2HREG_PHYCAP_W1_PROT_11N 1
+#define RTW89_C2HREG_PHYCAP_W1_PROT_11AC 2
+#define RTW89_C2HREG_PHYCAP_W1_PROT_11AX 3
+#define RTW89_C2HREG_PHYCAP_W1_PROT_11BE 4
#define RTW89_C2HREG_PHYCAP_W1_NIC GENMASK(23, 16)
#define RTW89_C2HREG_PHYCAP_W1_WL_FUNC GENMASK(31, 24)
#define RTW89_C2HREG_PHYCAP_W2_HW_TYPE GENMASK(7, 0)
@@ -120,6 +124,7 @@ struct rtw89_h2creg_sch_tx_en {
struct rtw89_mac_c2h_info {
u8 id;
u8 content_len;
+ u32 timeout;
union {
u32 c2hreg[RTW89_C2HREG_MAX];
struct rtw89_c2hreg_hdr hdr;
@@ -1517,6 +1522,153 @@ struct rtw89_h2c_cctlinfo_ud_g7 {
#define CCTLINFO_G7_W15_MGNT_CURR_RATE GENMASK(27, 16)
#define CCTLINFO_G7_W15_ALL GENMASK(27, 0)
+struct rtw89_h2c_cctlinfo_ud_be {
+ __le32 c0;
+ __le32 w0;
+ __le32 w1;
+ __le32 w2;
+ __le32 w3;
+ __le32 w4;
+ __le32 w5;
+ __le32 w6;
+ __le32 w7;
+ __le32 w8;
+ __le32 w9;
+ __le32 w10;
+ __le32 w11;
+ __le32 w12;
+ __le32 w13;
+ __le32 w14;
+ __le32 w15;
+ __le32 m0;
+ __le32 m1;
+ __le32 m2;
+ __le32 m3;
+ __le32 m4;
+ __le32 m5;
+ __le32 m6;
+ __le32 m7;
+ __le32 m8;
+ __le32 m9;
+ __le32 m10;
+ __le32 m11;
+ __le32 m12;
+ __le32 m13;
+ __le32 m14;
+ __le32 m15;
+} __packed;
+
+#define BE_CCTL_INFO_C0_V1_MACID GENMASK(9, 0)
+#define BE_CCTL_INFO_C0_V1_OP BIT(10)
+
+#define BE_CCTL_INFO_W0_DATARATE GENMASK(11, 0)
+#define BE_CCTL_INFO_W0_DATA_GI_LTF GENMASK(14, 12)
+#define BE_CCTL_INFO_W0_TRYRATE BIT(15)
+#define BE_CCTL_INFO_W0_ARFR_CTRL GENMASK(17, 16)
+#define BE_CCTL_INFO_W0_DIS_HE1SS_STBC BIT(18)
+#define BE_CCTL_INFO_W0_ACQ_RPT_EN BIT(20)
+#define BE_CCTL_INFO_W0_MGQ_RPT_EN BIT(21)
+#define BE_CCTL_INFO_W0_ULQ_RPT_EN BIT(22)
+#define BE_CCTL_INFO_W0_TWTQ_RPT_EN BIT(23)
+#define BE_CCTL_INFO_W0_FORCE_TXOP BIT(24)
+#define BE_CCTL_INFO_W0_DISRTSFB BIT(25)
+#define BE_CCTL_INFO_W0_DISDATAFB BIT(26)
+#define BE_CCTL_INFO_W0_NSTR_EN BIT(27)
+#define BE_CCTL_INFO_W0_AMPDU_DENSITY GENMASK(31, 28)
+#define BE_CCTL_INFO_W0_ALL (GENMASK(31, 20) | GENMASK(18, 0))
+#define BE_CCTL_INFO_W1_DATA_RTY_LOWEST_RATE GENMASK(11, 0)
+#define BE_CCTL_INFO_W1_RTS_TXCNT_LMT GENMASK(15, 12)
+#define BE_CCTL_INFO_W1_RTSRATE GENMASK(27, 16)
+#define BE_CCTL_INFO_W1_RTS_RTY_LOWEST_RATE GENMASK(31, 28)
+#define BE_CCTL_INFO_W1_ALL GENMASK(31, 0)
+#define BE_CCTL_INFO_W2_DATA_TX_CNT_LMT GENMASK(5, 0)
+#define BE_CCTL_INFO_W2_DATA_TXCNT_LMT_SEL BIT(6)
+#define BE_CCTL_INFO_W2_MAX_AGG_NUM_SEL BIT(7)
+#define BE_CCTL_INFO_W2_RTS_EN BIT(8)
+#define BE_CCTL_INFO_W2_CTS2SELF_EN BIT(9)
+#define BE_CCTL_INFO_W2_CCA_RTS GENMASK(11, 10)
+#define BE_CCTL_INFO_W2_HW_RTS_EN BIT(12)
+#define BE_CCTL_INFO_W2_RTS_DROP_DATA_MODE GENMASK(14, 13)
+#define BE_CCTL_INFO_W2_PRELOAD_ENABLE BIT(15)
+#define BE_CCTL_INFO_W2_AMPDU_MAX_LEN GENMASK(26, 16)
+#define BE_CCTL_INFO_W2_UL_MU_DIS BIT(27)
+#define BE_CCTL_INFO_W2_AMPDU_MAX_TIME GENMASK(31, 28)
+#define BE_CCTL_INFO_W2_ALL GENMASK(31, 0)
+#define BE_CCTL_INFO_W3_MAX_AGG_NUM GENMASK(7, 0)
+#define BE_CCTL_INFO_W3_DATA_BW GENMASK(10, 8)
+#define BE_CCTL_INFO_W3_DATA_BW_ER BIT(11)
+#define BE_CCTL_INFO_W3_BA_BMAP GENMASK(14, 12)
+#define BE_CCTL_INFO_W3_VCS_STBC BIT(15)
+#define BE_CCTL_INFO_W3_VO_LFTIME_SEL GENMASK(18, 16)
+#define BE_CCTL_INFO_W3_VI_LFTIME_SEL GENMASK(21, 19)
+#define BE_CCTL_INFO_W3_BE_LFTIME_SEL GENMASK(24, 22)
+#define BE_CCTL_INFO_W3_BK_LFTIME_SEL GENMASK(27, 25)
+#define BE_CCTL_INFO_W3_AMPDU_TIME_SEL BIT(28)
+#define BE_CCTL_INFO_W3_AMPDU_LEN_SEL BIT(29)
+#define BE_CCTL_INFO_W3_RTS_TXCNT_LMT_SEL BIT(30)
+#define BE_CCTL_INFO_W3_LSIG_TXOP_EN BIT(31)
+#define BE_CCTL_INFO_W3_ALL GENMASK(31, 0)
+#define BE_CCTL_INFO_W4_MULTI_PORT_ID GENMASK(2, 0)
+#define BE_CCTL_INFO_W4_BYPASS_PUNC BIT(3)
+#define BE_CCTL_INFO_W4_MBSSID GENMASK(7, 4)
+#define BE_CCTL_INFO_W4_TID_DISABLE_V1 GENMASK(15, 8)
+#define BE_CCTL_INFO_W4_ACT_SUBCH_CBW GENMASK(31, 16)
+#define BE_CCTL_INFO_W4_ALL GENMASK(31, 0)
+#define BE_CCTL_INFO_W5_ADDR_CAM_INDEX_V1 GENMASK(9, 0)
+#define BE_CCTL_INFO_W5_SR_MCS_SU GENMASK(14, 10)
+#define BE_CCTL_INFO_W5_A_CTRL_BQR_V1 BIT(15)
+#define BE_CCTL_INFO_W5_A_CTRL_BSR_V1 BIT(16)
+#define BE_CCTL_INFO_W5_A_CTRL_CAS_V1 BIT(17)
+#define BE_CCTL_INFO_W5_DATA_ER_V1 BIT(18)
+#define BE_CCTL_INFO_W5_DATA_DCM_V1 BIT(19)
+#define BE_CCTL_INFO_W5_DATA_LDPC_V1 BIT(20)
+#define BE_CCTL_INFO_W5_DATA_STBC_V1 BIT(21)
+#define BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING0_V1 GENMASK(23, 22)
+#define BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING1_V1 GENMASK(25, 24)
+#define BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING2_V1 GENMASK(27, 26)
+#define BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING3_V1 GENMASK(29, 28)
+#define BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING4_V1 GENMASK(31, 30)
+#define BE_CCTL_INFO_W5_ALL GENMASK(31, 0)
+#define BE_CCTL_INFO_W6_AID12_PAID GENMASK(11, 0)
+#define BE_CCTL_INFO_W6_RESP_REF_RATE GENMASK(23, 12)
+#define BE_CCTL_INFO_W6_ULDL BIT(31)
+#define BE_CCTL_INFO_W6_ALL (BIT(31) | GENMASK(23, 0))
+#define BE_CCTL_INFO_W7_NC GENMASK(2, 0)
+#define BE_CCTL_INFO_W7_NR GENMASK(5, 3)
+#define BE_CCTL_INFO_W7_NG GENMASK(7, 6)
+#define BE_CCTL_INFO_W7_CB GENMASK(9, 8)
+#define BE_CCTL_INFO_W7_CS GENMASK(11, 10)
+#define BE_CCTL_INFO_W7_CSI_STBC_EN BIT(13)
+#define BE_CCTL_INFO_W7_CSI_LDPC_EN BIT(14)
+#define BE_CCTL_INFO_W7_CSI_PARA_EN BIT(15)
+#define BE_CCTL_INFO_W7_CSI_FIX_RATE GENMASK(27, 16)
+#define BE_CCTL_INFO_W7_CSI_BW GENMASK(31, 29)
+#define BE_CCTL_INFO_W7_ALL GENMASK(31, 0)
+#define BE_CCTL_INFO_W8_ALL_ACK_SUPPORT_V1 BIT(0)
+#define BE_CCTL_INFO_W8_BSR_QUEUE_SIZE_FORMAT_V1 BIT(1)
+#define BE_CCTL_INFO_W8_BSR_OM_UPD_EN_V1 BIT(2)
+#define BE_CCTL_INFO_W8_MACID_FWD_IDC_V1 BIT(3)
+#define BE_CCTL_INFO_W8_AZ_SEC_EN BIT(4)
+#define BE_CCTL_INFO_W8_BF_SEC_EN BIT(5)
+#define BE_CCTL_INFO_W8_FIX_UL_ADDRCAM_IDX_V1 BIT(6)
+#define BE_CCTL_INFO_W8_CTRL_CNT_VLD_V1 BIT(7)
+#define BE_CCTL_INFO_W8_CTRL_CNT_V1 GENMASK(11, 8)
+#define BE_CCTL_INFO_W8_RESP_SEC_TYPE GENMASK(15, 12)
+#define BE_CCTL_INFO_W8_ALL GENMASK(15, 0)
+#define BE_CCTL_INFO_W9_EMLSR_TRANS_DLY GENMASK(2, 0)
+#define BE_CCTL_INFO_W9_ALL GENMASK(2, 0)
+#define BE_CCTL_INFO_W10_SW_EHT_NLTF GENMASK(1, 0)
+#define BE_CCTL_INFO_W10_TB_MLO_MODE BIT(2)
+#define BE_CCTL_INFO_W10_ALL GENMASK(2, 0)
+#define BE_CCTL_INFO_W14_VO_CURR_RATE GENMASK(11, 0)
+#define BE_CCTL_INFO_W14_VI_CURR_RATE GENMASK(23, 12)
+#define BE_CCTL_INFO_W14_BE_CURR_RATE_L GENMASK(31, 24)
+#define BE_CCTL_INFO_W14_ALL GENMASK(31, 0)
+#define BE_CCTL_INFO_W15_BE_CURR_RATE_H GENMASK(3, 0)
+#define BE_CCTL_INFO_W15_BK_CURR_RATE GENMASK(15, 4)
+#define BE_CCTL_INFO_W15_MGNT_CURR_RATE GENMASK(27, 16)
+#define BE_CCTL_INFO_W15_ALL GENMASK(27, 0)
+
struct rtw89_h2c_bcn_upd {
__le32 w0;
__le32 w1;
@@ -1865,6 +2017,66 @@ struct rtw89_h2c_lps_ml_cmn_info {
u8 dup_bcn_ofst[RTW89_PHY_NUM];
} __packed;
+#define BB_RX_GAIN_TB_RSSI_COMP_NUM 3
+#define BB_RX_GAIN_CCK_RPL_BIAS_COMP_NUM 2
+#define BB_GT2_GS_IDX_NUM 11
+#define BB_GT2_WB_GIDX_ELNA_NUM 16
+#define BB_GT2_G_ELNA_NUM 2
+
+enum rtw89_bb_link_rx_gain_table_type {
+ RTW89_BB_PS_LINK_RX_GAIN_TAB_BCN_PATH_A = 0x00,
+ RTW89_BB_PS_LINK_RX_GAIN_TAB_BCN_PATH_B = 0x01,
+ RTW89_BB_PS_LINK_RX_GAIN_TAB_NOR_PATH_A = 0x02,
+ RTW89_BB_PS_LINK_RX_GAIN_TAB_NOR_PATH_B = 0x03,
+ RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX,
+};
+
+enum rtw89_bb_ps_link_buf_id {
+ RTW89_BB_PS_LINK_BUF_0 = 0x00,
+ RTW89_BB_PS_LINK_BUF_1 = 0x01,
+ RTW89_BB_PS_LINK_BUF_2 = 0x02,
+ RTW89_BB_PS_LINK_BUF_MAX,
+};
+
+struct rtw89_bb_link_info_rx_gain {
+ u8 gain_ofst[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX];
+ __le16 rpl_bias_comp[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX];
+ u8 tb_rssi_m_bias_comp[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX]
+ [BB_RX_GAIN_TB_RSSI_COMP_NUM];
+ u8 cck_gain_ofst[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX];
+ u8 cck_rpl_bias_comp[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX]
+ [BB_RX_GAIN_CCK_RPL_BIAS_COMP_NUM];
+ u8 gain_err_lna[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX][LNA_GAIN_NUM];
+ __le16 gain_err_tia[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX][TIA_GAIN_NUM];
+ u8 op1db_lna[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX][LNA_GAIN_NUM];
+ u8 op1db_tia[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX][TIA_LNA_OP1DB_NUM];
+ struct {
+ u8 _20M[RTW89_BW20_SC_20M];
+ u8 _40M[RTW89_BW20_SC_40M];
+ u8 _80M[RTW89_BW20_SC_80M];
+ u8 _160M[RTW89_BW20_SC_160M];
+ } rpl_bias_comp_bw[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX];
+ u8 wb_gs[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX][BB_GT2_GS_IDX_NUM];
+ u8 bypass_lna[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX][LNA_GAIN_NUM];
+ u8 wb_lna_tia[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX][BB_GT2_WB_GIDX_ELNA_NUM];
+ u8 wb_g_elna[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX][BB_GT2_G_ELNA_NUM];
+} __packed;
+
+struct rtw89_h2c_lps_ml_cmn_info_v1 {
+ u8 fmt_id;
+ u8 rfe_type;
+ u8 rssi_main;
+ u8 rsvd0;
+ __le32 mlo_dbcc_mode;
+ u8 link_id[RTW89_BB_PS_LINK_BUF_MAX];
+ u8 central_ch[RTW89_BB_PS_LINK_BUF_MAX];
+ u8 pri_ch[RTW89_BB_PS_LINK_BUF_MAX];
+ u8 bw[RTW89_BB_PS_LINK_BUF_MAX];
+ u8 band[RTW89_BB_PS_LINK_BUF_MAX];
+ u8 dup_bcn_ofst[RTW89_BB_PS_LINK_BUF_MAX];
+ struct rtw89_bb_link_info_rx_gain rx_gain[RTW89_BB_PS_LINK_BUF_MAX];
+} __packed;
+
struct rtw89_h2c_trig_cpu_except {
__le32 w0;
} __packed;
@@ -2052,70 +2264,55 @@ static inline void RTW89_SET_WOW_WAKEUP_CTRL_MAC_ID(void *h2c, u32 val)
le32p_replace_bits((__le32 *)h2c, val, GENMASK(31, 24));
}
-static inline void RTW89_SET_WOW_CAM_UPD_R_W(void *h2c, u32 val)
-{
- le32p_replace_bits((__le32 *)h2c, val, BIT(0));
-}
-
-static inline void RTW89_SET_WOW_CAM_UPD_IDX(void *h2c, u32 val)
-{
- le32p_replace_bits((__le32 *)h2c, val, GENMASK(7, 1));
-}
-
-static inline void RTW89_SET_WOW_CAM_UPD_WKFM1(void *h2c, u32 val)
-{
- le32p_replace_bits((__le32 *)h2c + 1, val, GENMASK(31, 0));
-}
-
-static inline void RTW89_SET_WOW_CAM_UPD_WKFM2(void *h2c, u32 val)
-{
- le32p_replace_bits((__le32 *)h2c + 2, val, GENMASK(31, 0));
-}
-
-static inline void RTW89_SET_WOW_CAM_UPD_WKFM3(void *h2c, u32 val)
-{
- le32p_replace_bits((__le32 *)h2c + 3, val, GENMASK(31, 0));
-}
-
-static inline void RTW89_SET_WOW_CAM_UPD_WKFM4(void *h2c, u32 val)
-{
- le32p_replace_bits((__le32 *)h2c + 4, val, GENMASK(31, 0));
-}
-
-static inline void RTW89_SET_WOW_CAM_UPD_CRC(void *h2c, u32 val)
-{
- le32p_replace_bits((__le32 *)h2c + 5, val, GENMASK(15, 0));
-}
-
-static inline void RTW89_SET_WOW_CAM_UPD_NEGATIVE_PATTERN_MATCH(void *h2c, u32 val)
-{
- le32p_replace_bits((__le32 *)h2c + 5, val, BIT(22));
-}
-
-static inline void RTW89_SET_WOW_CAM_UPD_SKIP_MAC_HDR(void *h2c, u32 val)
-{
- le32p_replace_bits((__le32 *)h2c + 5, val, BIT(23));
-}
-
-static inline void RTW89_SET_WOW_CAM_UPD_UC(void *h2c, u32 val)
-{
- le32p_replace_bits((__le32 *)h2c + 5, val, BIT(24));
-}
-
-static inline void RTW89_SET_WOW_CAM_UPD_MC(void *h2c, u32 val)
-{
- le32p_replace_bits((__le32 *)h2c + 5, val, BIT(25));
-}
+struct rtw89_h2c_wow_cam_update {
+ __le32 w0;
+ __le32 wkfm0;
+ __le32 wkfm1;
+ __le32 wkfm2;
+ __le32 wkfm3;
+ __le32 w5;
+} __packed;
-static inline void RTW89_SET_WOW_CAM_UPD_BC(void *h2c, u32 val)
-{
- le32p_replace_bits((__le32 *)h2c + 5, val, BIT(26));
-}
+#define RTW89_H2C_WOW_CAM_UPD_W0_R_W BIT(0)
+#define RTW89_H2C_WOW_CAM_UPD_W0_IDX GENMASK(7, 1)
+#define RTW89_H2C_WOW_CAM_UPD_WKFM0 GENMASK(31, 0)
+#define RTW89_H2C_WOW_CAM_UPD_WKFM1 GENMASK(31, 0)
+#define RTW89_H2C_WOW_CAM_UPD_WKFM2 GENMASK(31, 0)
+#define RTW89_H2C_WOW_CAM_UPD_WKFM3 GENMASK(31, 0)
+#define RTW89_H2C_WOW_CAM_UPD_W5_CRC GENMASK(15, 0)
+#define RTW89_H2C_WOW_CAM_UPD_W5_NEGATIVE_PATTERN_MATCH BIT(22)
+#define RTW89_H2C_WOW_CAM_UPD_W5_SKIP_MAC_HDR BIT(23)
+#define RTW89_H2C_WOW_CAM_UPD_W5_UC BIT(24)
+#define RTW89_H2C_WOW_CAM_UPD_W5_MC BIT(25)
+#define RTW89_H2C_WOW_CAM_UPD_W5_BC BIT(26)
+#define RTW89_H2C_WOW_CAM_UPD_W5_VALID BIT(31)
+
+struct rtw89_h2c_wow_payload_cam_update {
+ __le32 w0;
+ __le32 wkfm0;
+ __le32 wkfm1;
+ __le32 wkfm2;
+ __le32 wkfm3;
+ __le32 w5;
+ __le32 w6;
+ __le32 w7;
+ __le32 w8;
+} __packed;
-static inline void RTW89_SET_WOW_CAM_UPD_VALID(void *h2c, u32 val)
-{
- le32p_replace_bits((__le32 *)h2c + 5, val, BIT(31));
-}
+#define RTW89_H2C_WOW_PLD_CAM_UPD_W0_R_W BIT(0)
+#define RTW89_H2C_WOW_PLD_CAM_UPD_W0_IDX GENMASK(7, 1)
+#define RTW89_H2C_WOW_PLD_CAM_UPD_WKFM0 GENMASK(31, 0)
+#define RTW89_H2C_WOW_PLD_CAM_UPD_WKFM1 GENMASK(31, 0)
+#define RTW89_H2C_WOW_PLD_CAM_UPD_WKFM2 GENMASK(31, 0)
+#define RTW89_H2C_WOW_PLD_CAM_UPD_WKFM3 GENMASK(31, 0)
+#define RTW89_H2C_WOW_PLD_CAM_UPD_W5_UC BIT(0)
+#define RTW89_H2C_WOW_PLD_CAM_UPD_W5_MC BIT(1)
+#define RTW89_H2C_WOW_PLD_CAM_UPD_W5_BC BIT(2)
+#define RTW89_H2C_WOW_PLD_CAM_UPD_W5_SKIP_MAC_HDR BIT(7)
+#define RTW89_H2C_WOW_PLD_CAM_UPD_W6_CRC GENMASK(15, 0)
+#define RTW89_H2C_WOW_PLD_CAM_UPD_W7_NEGATIVE_PATTERN_MATCH BIT(0)
+#define RTW89_H2C_WOW_PLD_CAM_UPD_W8_VALID BIT(0)
+#define RTW89_H2C_WOW_PLD_CAM_UPD_W8_WOW_PTR BIT(1)
struct rtw89_h2c_wow_gtk_ofld {
__le32 w0;
@@ -2826,6 +3023,7 @@ struct rtw89_h2c_scanofld_be_macc_role {
__le32 w0;
} __packed;
+#define RTW89_MAX_OP_NUM_BE 2
#define RTW89_H2C_SCANOFLD_BE_MACC_ROLE_W0_BAND GENMASK(1, 0)
#define RTW89_H2C_SCANOFLD_BE_MACC_ROLE_W0_PORT GENMASK(4, 2)
#define RTW89_H2C_SCANOFLD_BE_MACC_ROLE_W0_MACID GENMASK(23, 8)
@@ -3691,6 +3889,26 @@ struct rtw89_c2h_ra_rpt {
#define RTW89_C2H_RA_RPT_W3_MD_SEL_B2 BIT(15)
#define RTW89_C2H_RA_RPT_W3_BW_B2 BIT(16)
+struct rtw89_c2h_lps_rpt {
+ struct rtw89_c2h_hdr hdr;
+ u8 type;
+ u8 cnt_bbcr;
+ u8 cnt_bbmcucr;
+ u8 cnt_rfcr;
+ u8 data[];
+ /*
+ * The layout of data:
+ * u8 info[][4], size = total_len - size of below fields
+ * __le16 bbcr_addr[], size = cnt_bbcr
+ * __le32 bbcr_data[], size = cnt_bbcr
+ * __le16 bbmcucr_addr[], size = cnt_bbmcucr
+ * __le32 bbmcucr_data[], size = cnt_bbmcucr
+ * __le16 rfcr_addr[], size = cnt_rfcr
+ * __le32 rfcr_data_a[], size = cnt_rfcr
+ * __le32 rfcr_data_b[], size = cnt_rfcr
+ */
+} __packed;
+
struct rtw89_c2h_fw_scan_rpt {
struct rtw89_c2h_hdr hdr;
u8 phy_idx;
@@ -4044,6 +4262,7 @@ enum rtw89_fw_element_id {
RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_RU_6GHZ = 26,
RTW89_FW_ELEMENT_ID_AFE_PWR_SEQ = 27,
RTW89_FW_ELEMENT_ID_DIAG_MAC = 28,
+ RTW89_FW_ELEMENT_ID_TX_COMP = 29,
RTW89_FW_ELEMENT_ID_NUM,
};
@@ -4177,7 +4396,8 @@ struct rtw89_fw_element_hdr {
__le32 id; /* enum rtw89_fw_element_id */
__le32 size; /* exclude header size */
u8 ver[4];
- __le32 rsvd0;
+ __le16 aid; /* should match rtw89_hal::aid */
+ __le16 rsvd0;
__le32 rsvd1;
__le32 rsvd2;
union {
@@ -4307,6 +4527,7 @@ enum rtw89_wow_h2c_func {
H2C_FUNC_WAKEUP_CTRL = 0x8,
H2C_FUNC_WOW_CAM_UPD = 0xC,
H2C_FUNC_AOAC_REPORT_REQ = 0xD,
+ H2C_FUNC_WOW_PLD_CAM_UPD = 0x12,
NUM_OF_RTW89_WOW_H2C_FUNC,
};
@@ -4347,6 +4568,7 @@ enum rtw89_ps_h2c_func {
#define H2C_FUNC_MAC_CCTLINFO_UD_V1 0xa
#define H2C_FUNC_MAC_DCTLINFO_UD_V2 0xc
#define H2C_FUNC_MAC_BCN_UPD_BE 0xd
+#define H2C_FUNC_MAC_DCTLINFO_UD_V3 0x10
#define H2C_FUNC_MAC_CCTLINFO_UD_G7 0x11
/* CLASS 6 - Address CAM */
@@ -4483,6 +4705,7 @@ enum rtw89_mrc_h2c_func {
#define H2C_CL_OUTSRC_RF_REG_B 0x9
#define H2C_CL_OUTSRC_RF_FW_NOTIFY 0xa
#define H2C_FUNC_OUTSRC_RF_GET_MCCCH 0x2
+#define H2C_FUNC_OUTSRC_RF_MCC_INFO 0xf
#define H2C_FUNC_OUTSRC_RF_PS_INFO 0x10
#define H2C_CL_OUTSRC_RF_FW_RFK 0xb
@@ -4495,6 +4718,8 @@ enum rtw89_rfk_offload_h2c_func {
H2C_FUNC_RFK_RXDCK_OFFLOAD = 0x6,
H2C_FUNC_RFK_PRE_NOTIFY = 0x8,
H2C_FUNC_RFK_TAS_OFFLOAD = 0x9,
+ H2C_FUNC_RFK_TXIQK_OFFOAD = 0xc,
+ H2C_FUNC_RFK_CIM3K_OFFOAD = 0xe,
};
struct rtw89_fw_h2c_rf_get_mccch {
@@ -4586,11 +4811,38 @@ struct rtw89_fw_h2c_rfk_pre_info_v1 {
__le32 mlo_1_1;
} __packed;
-struct rtw89_fw_h2c_rfk_pre_info {
+struct rtw89_fw_h2c_rfk_pre_info_v2 {
struct rtw89_fw_h2c_rfk_pre_info_v1 base_v1;
__le32 cur_bandwidth[NUM_OF_RTW89_FW_RFK_PATH];
} __packed;
+struct rtw89_fw_h2c_rfk_pre_info {
+ __le32 mlo_mode;
+ __le32 phy_idx;
+ __le32 mlo_1_1;
+} __packed;
+
+struct rtw89_fw_h2c_rfk_pre_info_mcc_v0 {
+ __le32 tbl_18[NUM_OF_RTW89_FW_RFK_TBL][NUM_OF_RTW89_FW_RFK_PATH];
+ __le32 cur_18[NUM_OF_RTW89_FW_RFK_PATH];
+ __le32 mlo_mode;
+} __packed;
+
+struct rtw89_fw_h2c_rfk_pre_info_mcc_v1 {
+ __le32 tbl_18[NUM_OF_RTW89_FW_RFK_TBL];
+ __le32 cur_18[NUM_OF_RTW89_FW_RFK_PATH];
+ __le32 mlo_mode;
+ __le32 mlo_1_1;
+ u8 phy_idx;
+ u8 tbl_idx;
+} __packed;
+
+struct rtw89_fw_h2c_rfk_pre_info_mcc {
+ struct rtw89_fw_h2c_rfk_pre_info_mcc_v1 base;
+ u8 rsvd[2];
+ __le32 aid;
+} __packed;
+
struct rtw89_h2c_rf_tssi {
__le16 len;
u8 phy;
@@ -4660,9 +4912,9 @@ struct rtw89_h2c_rf_txgapk {
} __packed;
struct rtw89_h2c_rf_dack {
- __le32 len;
- __le32 phy;
- __le32 type;
+ u8 len;
+ u8 phy;
+ u8 type;
} __packed;
struct rtw89_h2c_rf_rxdck_v0 {
@@ -4685,6 +4937,30 @@ struct rtw89_h2c_rf_rxdck {
u8 is_chl_k;
} __packed;
+struct rtw89_h2c_rf_txiqk {
+ u8 len;
+ u8 phy;
+ u8 txiqk_enable;
+ u8 is_wb_txiqk;
+ u8 kpath;
+ u8 cur_band;
+ u8 cur_bw;
+ u8 cur_ch;
+ u8 txiqk_dbg_en;
+} __packed;
+
+struct rtw89_h2c_rf_cim3k {
+ u8 len;
+ u8 phy;
+ u8 su_cim3k_enable[2];
+ u8 ru_cim3k_enable[2];
+ u8 kpath;
+ u8 cur_band;
+ u8 cur_bw;
+ u8 cur_ch;
+ u8 cim3k_dbg_en;
+} __packed;
+
enum rtw89_rf_log_type {
RTW89_RF_RUN_LOG = 0,
RTW89_RF_RPT_LOG = 1,
@@ -4729,12 +5005,16 @@ struct rtw89_c2h_rf_iqk_rpt_log {
u8 rsvd;
__le32 reload_cnt;
__le32 iqk_fail_cnt;
+ __le32 rf_0x18[2];
__le32 lok_idac[2];
__le32 lok_vbuf[2];
- __le32 rftxgain[2][4];
- __le32 rfrxgain[2][4];
- __le32 tx_xym[2][4];
- __le32 rx_xym[2][4];
+ __le32 rftxgain[2][6];
+ __le32 rfrxgain[2][6];
+ __le32 tx_xym[2][6];
+ __le32 rx_xym[2][6];
+ __le32 rx_wb_xym[2][32];
+ bool is_radar;
+ u8 rsvd1[3];
} __packed;
struct rtw89_c2h_rf_dpk_rpt_log {
@@ -4777,6 +5057,7 @@ struct rtw89_c2h_rf_dack_rpt_log {
u8 dack_fail;
u8 wbdck_d[2];
u8 rck_d;
+ u8 adgaink_ex_d;
} __packed;
struct rtw89_c2h_rf_rxdck_rpt_log {
@@ -4803,7 +5084,57 @@ struct rtw89_c2h_rf_txgapk_rpt_log {
u8 is_txgapk_ok;
u8 chk_id;
u8 ver;
- u8 rsv1;
+ u8 d_bnd_ok;
+ __le32 stage[2];
+ __le16 failcode[2];
+ u8 rsvd[4];
+} __packed;
+
+struct rtw89_c2h_rf_txiqk_rpt_log {
+ u8 fw_txiqk_ver;
+ u8 iqk_band[2];
+ u8 iqk_ch[2];
+ u8 iqk_bw[2];
+ bool tx_iqk_fail[2];
+ bool is_iqk_init;
+ bool txiqk_en;
+ bool lok_en;
+ bool lok_fail[2];
+ u8 rsvd[2];
+ __le32 iqk_times;
+ bool txiqk_nctldone[2];
+ u8 rsvd2[2];
+ __le32 txgain[2][6];
+ __le32 tx_iqc[2][6];
+ __le32 tx_xym[2][6][14];
+ __le32 kidx[2];
+} __packed;
+
+struct rtw89_c2h_rf_cim3k_rpt_log {
+ u8 cim3k_band[2];
+ u8 cim3k_ch[2];
+ u8 cim3k_bw[2];
+ u8 su_path_ok[2];
+ u8 ru_path_ok[2];
+ u8 txagc_cim3k[2];
+ u8 ther_cim3k[2];
+ u8 cim3k_gs[2];
+ __le16 cim3k_pwsf[2];
+ bool cim3k_nctldone[2];
+ u8 rsvd[2];
+ __le32 cim3k_rxiqc[2];
+ __le32 cim3k_su_coef[2][3];
+ __le16 dc_i[2];
+ __le16 dc_q[2];
+ u8 corr_val[2];
+ u8 corr_idx[2];
+ u8 rxbb_ov[2];
+ u8 cim3k_txiqc[2];
+ u8 kidx[2];
+ u8 fw_cim3k_ver;
+ bool su_cim3k_en[2];
+ bool ru_cim3k_en[2];
+ u8 rsvd1;
} __packed;
struct rtw89_c2h_rfk_report {
@@ -4858,25 +5189,42 @@ int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev,
int rtw89_fw_h2c_default_cmac_tbl_g7(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_link);
+int rtw89_fw_h2c_default_cmac_tbl_be(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
int rtw89_fw_h2c_default_dmac_tbl_v2(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_link);
+int rtw89_fw_h2c_default_dmac_tbl_v3(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_link);
int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_link);
+int rtw89_fw_h2c_assoc_cmac_tbl_be(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_link);
+int rtw89_fw_h2c_ampdu_cmac_tbl_be(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev,
struct rtw89_sta_link *rtwsta_link);
int rtw89_fw_h2c_txtime_cmac_tbl_g7(struct rtw89_dev *rtwdev,
struct rtw89_sta_link *rtwsta_link);
+int rtw89_fw_h2c_txtime_cmac_tbl_be(struct rtw89_dev *rtwdev,
+ struct rtw89_sta_link *rtwsta_link);
int rtw89_fw_h2c_punctured_cmac_tbl_g7(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
u16 punctured);
+int rtw89_fw_h2c_punctured_cmac_tbl_be(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ u16 punctured);
int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev,
struct rtw89_sta_link *rtwsta_link);
int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev,
@@ -4895,9 +5243,13 @@ int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev,
int rtw89_fw_h2c_dctl_sec_cam_v2(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_link);
+int rtw89_fw_h2c_dctl_sec_cam_v3(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
void rtw89_fw_c2h_irqsafe(struct rtw89_dev *rtwdev, struct sk_buff *c2h);
void rtw89_fw_c2h_work(struct wiphy *wiphy, struct wiphy_work *work);
void rtw89_fw_c2h_purge_obsoleted_scan_events(struct rtw89_dev *rtwdev);
+void rtw89_fw_c2h_dummy_handler(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len);
int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_link,
@@ -4948,6 +5300,7 @@ int rtw89_fw_h2c_rf_ntfy_mcc(struct rtw89_dev *rtwdev);
int rtw89_fw_h2c_rf_ps_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx);
+int rtw89_fw_h2c_rf_pre_ntfy_mcc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
int rtw89_fw_h2c_mcc_dig(struct rtw89_dev *rtwdev,
enum rtw89_chanctx_idx chanctx_idx,
u8 mcc_role_idx, u8 pd_val, bool en);
@@ -4964,6 +5317,10 @@ int rtw89_fw_h2c_rf_dack(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
int rtw89_fw_h2c_rf_rxdck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
const struct rtw89_chan *chan, bool is_chl_k);
int rtw89_fw_h2c_rf_tas_trigger(struct rtw89_dev *rtwdev, bool enable);
+int rtw89_fw_h2c_rf_txiqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ const struct rtw89_chan *chan);
+int rtw89_fw_h2c_rf_cim3k(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ const struct rtw89_chan *chan);
int rtw89_fw_h2c_raw_with_hdr(struct rtw89_dev *rtwdev,
u8 h2c_class, u8 h2c_func, u8 *buf, u16 len,
bool rack, bool dack);
@@ -4994,6 +5351,11 @@ int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev,
int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
int rtw89_fw_h2c_lps_ml_cmn_info(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif);
+void rtw89_bb_lps_cmn_info_rx_gain_fill(struct rtw89_dev *rtwdev,
+ struct rtw89_bb_link_info_rx_gain *h2c_gain,
+ const struct rtw89_chan *chan, u8 phy_idx);
+int rtw89_fw_h2c_lps_ml_cmn_info_v1(struct rtw89_dev *rtwdev,
+ struct rtw89_vif *rtwvif);
int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
bool enable);
struct sk_buff *rtw89_fw_h2c_alloc_skb_with_hdr(struct rtw89_dev *rtwdev, u32 len);
@@ -5054,8 +5416,10 @@ int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtw
bool enable);
int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link, bool enable);
-int rtw89_fw_wow_cam_update(struct rtw89_dev *rtwdev,
- struct rtw89_wow_cam_info *cam_info);
+int rtw89_fw_h2c_wow_cam_update(struct rtw89_dev *rtwdev,
+ struct rtw89_wow_cam_info *cam_info);
+int rtw89_fw_h2c_wow_cam_update_v1(struct rtw89_dev *rtwdev,
+ struct rtw89_wow_cam_info *cam_info);
int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
bool enable);
@@ -5219,6 +5583,15 @@ int rtw89_chip_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
return 0;
}
+static inline
+int rtw89_chip_h2c_wow_cam_update(struct rtw89_dev *rtwdev,
+ struct rtw89_wow_cam_info *cam_info)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+
+ return chip->ops->h2c_wow_cam_update(rtwdev, cam_info);
+}
+
/* Must consider compatibility; don't insert new in the mid.
* Fill each field's default value in rtw89_regd_entcpy().
*/
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index d78fbe73e365..8472f1a63951 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -848,6 +848,7 @@ EXPORT_SYMBOL(rtw89_mac_get_err_status);
int rtw89_mac_set_err_status(struct rtw89_dev *rtwdev, u32 err)
{
struct rtw89_ser *ser = &rtwdev->ser;
+ bool ser_l1_hdl = false;
u32 halt;
int ret = 0;
@@ -856,6 +857,12 @@ int rtw89_mac_set_err_status(struct rtw89_dev *rtwdev, u32 err)
return -EINVAL;
}
+ if (err == MAC_AX_ERR_L1_DISABLE_EN || err == MAC_AX_ERR_L1_RCVY_EN)
+ ser_l1_hdl = true;
+
+ if (RTW89_CHK_FW_FEATURE(SER_L1_BY_EVENT, &rtwdev->fw) && ser_l1_hdl)
+ goto set;
+
ret = read_poll_timeout(rtw89_read32, halt, (halt == 0x0), 1000,
100000, false, rtwdev, R_AX_HALT_H2C_CTRL);
if (ret) {
@@ -863,10 +870,10 @@ int rtw89_mac_set_err_status(struct rtw89_dev *rtwdev, u32 err)
return -EFAULT;
}
+set:
rtw89_write32(rtwdev, R_AX_HALT_H2C, err);
- if (ser->prehandle_l1 &&
- (err == MAC_AX_ERR_L1_DISABLE_EN || err == MAC_AX_ERR_L1_RCVY_EN))
+ if (ser->prehandle_l1 && ser_l1_hdl)
return 0;
rtw89_write32(rtwdev, R_AX_HALT_H2C_CTRL, B_AX_HALT_H2C_TRIGGER);
@@ -1476,15 +1483,37 @@ static void rtw89_mac_power_switch_boot_mode(struct rtw89_dev *rtwdev)
rtw89_write32_clr(rtwdev, R_AX_RSV_CTRL, B_AX_R_DIS_PRST);
}
+static int rtw89_mac_pwr_off_func_for_unplugged(struct rtw89_dev *rtwdev)
+{
+ /*
+ * Avoid accessing IO for unplugged power-off to prevent warnings,
+ * especially XTAL SI.
+ */
+ return 0;
+}
+
+static void rtw89_mac_update_scoreboard(struct rtw89_dev *rtwdev, u8 val)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ u32 reg;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(chip->btc_sb.n); i++) {
+ reg = chip->btc_sb.n[i].cfg;
+ if (!reg)
+ continue;
+
+ rtw89_write8(rtwdev, reg + 3, val);
+ }
+}
+
static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
{
-#define PWR_ACT 1
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_chip_info *chip = rtwdev->chip;
const struct rtw89_pwr_cfg * const *cfg_seq;
int (*cfg_func)(struct rtw89_dev *rtwdev);
int ret;
- u8 val;
rtw89_mac_power_switch_boot_mode(rtwdev);
@@ -1492,17 +1521,22 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
cfg_seq = chip->pwr_on_seq;
cfg_func = chip->ops->pwr_on_func;
} else {
- cfg_seq = chip->pwr_off_seq;
- cfg_func = chip->ops->pwr_off_func;
+ if (test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags)) {
+ cfg_seq = NULL;
+ cfg_func = rtw89_mac_pwr_off_func_for_unplugged;
+ } else {
+ cfg_seq = chip->pwr_off_seq;
+ cfg_func = chip->ops->pwr_off_func;
+ }
}
if (test_bit(RTW89_FLAG_FW_RDY, rtwdev->flags))
__rtw89_leave_ps_mode(rtwdev);
- val = rtw89_read32_mask(rtwdev, R_AX_IC_PWR_STATE, B_AX_WLMAC_PWR_STE_MASK);
- if (on && val == PWR_ACT) {
- rtw89_err(rtwdev, "MAC has already powered on\n");
- return -EBUSY;
+ if (on) {
+ ret = mac->reset_pwr_state(rtwdev);
+ if (ret)
+ return ret;
}
ret = cfg_func ? cfg_func(rtwdev) : rtw89_mac_pwr_seq(rtwdev, cfg_seq);
@@ -1510,26 +1544,32 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
return ret;
if (on) {
- if (!test_bit(RTW89_FLAG_PROBE_DONE, rtwdev->flags))
+ if (!test_bit(RTW89_FLAG_PROBE_DONE, rtwdev->flags)) {
+ rtw89_mac_efuse_read_ecv(rtwdev);
mac->efuse_read_fw_secure(rtwdev);
+ }
set_bit(RTW89_FLAG_POWERON, rtwdev->flags);
set_bit(RTW89_FLAG_DMAC_FUNC, rtwdev->flags);
set_bit(RTW89_FLAG_CMAC0_FUNC, rtwdev->flags);
- rtw89_write8(rtwdev, R_AX_SCOREBOARD + 3, MAC_AX_NOTIFY_TP_MAJOR);
+
+ rtw89_mac_update_scoreboard(rtwdev, MAC_AX_NOTIFY_TP_MAJOR);
+ rtw89_mac_clr_aon_intr(rtwdev);
} else {
clear_bit(RTW89_FLAG_POWERON, rtwdev->flags);
clear_bit(RTW89_FLAG_DMAC_FUNC, rtwdev->flags);
clear_bit(RTW89_FLAG_CMAC0_FUNC, rtwdev->flags);
clear_bit(RTW89_FLAG_CMAC1_FUNC, rtwdev->flags);
+ clear_bit(RTW89_FLAG_CMAC0_PWR, rtwdev->flags);
+ clear_bit(RTW89_FLAG_CMAC1_PWR, rtwdev->flags);
clear_bit(RTW89_FLAG_FW_RDY, rtwdev->flags);
- rtw89_write8(rtwdev, R_AX_SCOREBOARD + 3, MAC_AX_NOTIFY_PWR_MAJOR);
+
+ rtw89_mac_update_scoreboard(rtwdev, MAC_AX_NOTIFY_PWR_MAJOR);
rtw89_set_entity_state(rtwdev, RTW89_PHY_0, false);
rtw89_set_entity_state(rtwdev, RTW89_PHY_1, false);
}
return 0;
-#undef PWR_ACT
}
int rtw89_mac_pwr_on(struct rtw89_dev *rtwdev)
@@ -1664,8 +1704,8 @@ static int sys_init_ax(struct rtw89_dev *rtwdev)
const struct rtw89_mac_size_set rtw89_mac_size = {
.hfc_preccfg_pcie = {2, 40, 0, 0, 1, 0, 0, 0},
- .hfc_prec_cfg_c0 = {2, 32, 0, 0, 0, 0, 0, 0},
- .hfc_prec_cfg_c2 = {0, 256, 0, 0, 0, 0, 0, 0},
+ .hfc_prec_cfg_c0 = {2, 32, 0, 0, 0, 0, 0, 0, 2, 32, 0, 0},
+ .hfc_prec_cfg_c2 = {0, 256, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0},
/* PCIE 64 */
.wde_size0 = {RTW89_WDE_PG_64, 4095, 1,},
.wde_size0_v1 = {RTW89_WDE_PG_64, 3328, 0, 0,},
@@ -1680,10 +1720,12 @@ const struct rtw89_mac_size_set rtw89_mac_size = {
.wde_size7 = {RTW89_WDE_PG_64, 510, 2,},
/* DLFW */
.wde_size9 = {RTW89_WDE_PG_64, 0, 1024,},
+ .wde_size16_v1 = {RTW89_WDE_PG_64, 639, 1, 0,},
/* 8852C USB3.0 */
.wde_size17 = {RTW89_WDE_PG_64, 354, 30,},
/* 8852C DLFW */
.wde_size18 = {RTW89_WDE_PG_64, 0, 2048,},
+ .wde_size18_v1 = {RTW89_WDE_PG_64, 0, 640, 0,},
/* 8852C PCIE SCC */
.wde_size19 = {RTW89_WDE_PG_64, 3328, 0,},
.wde_size23 = {RTW89_WDE_PG_64, 1022, 2,},
@@ -1710,6 +1752,8 @@ const struct rtw89_mac_size_set rtw89_mac_size = {
.ple_size18 = {RTW89_PLE_PG_128, 2544, 16,},
/* 8852C PCIE SCC */
.ple_size19 = {RTW89_PLE_PG_128, 1904, 16,},
+ .ple_size20_v1 = {RTW89_PLE_PG_128, 2554, 182, 40960,},
+ .ple_size22_v1 = {RTW89_PLE_PG_128, 2736, 0, 40960,},
/* 8852B USB2.0 SCC */
.ple_size32 = {RTW89_PLE_PG_128, 620, 20,},
/* 8852B USB3.0 SCC */
@@ -1721,6 +1765,7 @@ const struct rtw89_mac_size_set rtw89_mac_size = {
.wde_qt0_v1 = {3302, 6, 0, 20,},
/* 8852A USB */
.wde_qt1 = {512, 196, 0, 60,},
+ .wde_qt3 = {0, 0, 0, 0,},
/* DLFW */
.wde_qt4 = {0, 0, 0, 0,},
/* PCIE 64 */
@@ -1733,6 +1778,7 @@ const struct rtw89_mac_size_set rtw89_mac_size = {
.wde_qt17 = {0, 0, 0, 0,},
/* 8852C PCIE SCC */
.wde_qt18 = {3228, 60, 0, 40,},
+ .wde_qt19_v1 = {613, 6, 0, 20,},
.wde_qt23 = {958, 48, 0, 16,},
/* 8852B USB2.0/USB3.0 SCC */
.wde_qt25 = {152, 2, 0, 8,},
@@ -1744,6 +1790,7 @@ const struct rtw89_mac_size_set rtw89_mac_size = {
.ple_qt4 = {264, 0, 16, 20, 26, 13, 356, 0, 32, 40, 8,},
/* PCIE SCC */
.ple_qt5 = {264, 0, 32, 20, 64, 13, 1101, 0, 64, 128, 120,},
+ .ple_qt5_v2 = {0, 0, 32, 256, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,},
.ple_qt9 = {0, 0, 32, 256, 0, 0, 0, 0, 0, 0, 1, 0, 0,},
/* DLFW */
.ple_qt13 = {0, 0, 16, 48, 0, 0, 0, 0, 0, 0, 0,},
@@ -1754,8 +1801,10 @@ const struct rtw89_mac_size_set rtw89_mac_size = {
.ple_qt26 = {2654, 0, 1134, 48, 64, 13, 1478, 0, 64, 128, 120, 0,},
/* USB 52C USB3.0 */
.ple_qt42 = {1068, 0, 16, 48, 4, 13, 178, 0, 16, 1, 8, 16, 0,},
+ .ple_qt42_v2 = {91, 91, 32, 16, 19, 13, 91, 91, 44, 18, 1, 4, 0, 0,},
/* USB 52C USB3.0 */
.ple_qt43 = {3068, 0, 32, 48, 4, 13, 178, 0, 16, 1, 8, 16, 0,},
+ .ple_qt43_v2 = {645, 645, 32, 16, 2062, 2056, 2134, 2134, 2087, 2061, 1, 2047, 0, 0,},
/* DLFW 52C */
.ple_qt44 = {0, 0, 16, 256, 0, 0, 0, 0, 0, 0, 0, 0,},
/* DLFW 52C */
@@ -1789,8 +1838,13 @@ const struct rtw89_mac_size_set rtw89_mac_size = {
.ple_qt_51b_wow = {147, 0, 16, 20, 157, 13, 133, 0, 172, 14, 24, 0,},
.ple_rsvd_qt0 = {2, 107, 107, 6, 6, 6, 6, 0, 0, 0,},
.ple_rsvd_qt1 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+ .ple_rsvd_qt9 = {1, 44, 44, 6, 6, 6, 6, 69, 0, 0,},
.rsvd0_size0 = {212992, 0,},
+ .rsvd0_size6 = {40960, 0,},
.rsvd1_size0 = {587776, 2048,},
+ .rsvd1_size2 = {391168, 2048,},
+ .dle_input3 = {0, 0, 0, 16384, 0, 2048, 0, 0,},
+ .dle_input18 = {128, 128, 11454, 2048, 0, 2048, 24, 24,},
};
EXPORT_SYMBOL(rtw89_mac_size);
@@ -1811,6 +1865,7 @@ static const struct rtw89_dle_mem *get_dle_mem_cfg(struct rtw89_dev *rtwdev,
}
mac->dle_info.rsvd_qt = cfg->rsvd_qt;
+ mac->dle_info.dle_input = cfg->dle_input;
mac->dle_info.ple_pg_size = cfg->ple_size->pge_size;
mac->dle_info.ple_free_pg = cfg->ple_size->lnk_pge_num;
mac->dle_info.qta_mode = mode;
@@ -2231,8 +2286,8 @@ error:
return ret;
}
-static int preload_init_set(struct rtw89_dev *rtwdev, enum rtw89_mac_idx mac_idx,
- enum rtw89_qta_mode mode)
+static int preload_init_set_ax(struct rtw89_dev *rtwdev, u8 mac_idx,
+ enum rtw89_qta_mode mode)
{
u32 reg, max_preld_size, min_rsvd_size;
@@ -2260,13 +2315,14 @@ static bool is_qta_poh(struct rtw89_dev *rtwdev)
int rtw89_mac_preload_init(struct rtw89_dev *rtwdev, enum rtw89_mac_idx mac_idx,
enum rtw89_qta_mode mode)
{
+ const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_chip_info *chip = rtwdev->chip;
if (chip->chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev) ||
!is_qta_poh(rtwdev))
return 0;
- return preload_init_set(rtwdev, mac_idx, mode);
+ return mac->preload_init(rtwdev, mac_idx, mode);
}
static bool dle_is_txq_empty(struct rtw89_dev *rtwdev)
@@ -3061,6 +3117,7 @@ static int rtw89_mac_setup_phycap_part0(struct rtw89_dev *rtwdev)
struct rtw89_efuse *efuse = &rtwdev->efuse;
struct rtw89_mac_c2h_info c2h_info = {};
struct rtw89_hal *hal = &rtwdev->hal;
+ u8 protocol;
u8 tx_nss;
u8 rx_nss;
u8 tx_ant;
@@ -3108,6 +3165,10 @@ static int rtw89_mac_setup_phycap_part0(struct rtw89_dev *rtwdev)
rtw89_debug(rtwdev, RTW89_DBG_FW, "TX path diversity=%d\n", hal->tx_path_diversity);
rtw89_debug(rtwdev, RTW89_DBG_FW, "Antenna diversity=%d\n", hal->ant_diversity);
+ protocol = u32_get_bits(phycap->w1, RTW89_C2HREG_PHYCAP_W1_PROT);
+ if (protocol < RTW89_C2HREG_PHYCAP_W1_PROT_11BE)
+ hal->no_eht = true;
+
return 0;
}
@@ -3931,6 +3992,29 @@ static int rtw89_mac_feat_init(struct rtw89_dev *rtwdev)
return 0;
}
+static int rtw89_mac_reset_pwr_state_ax(struct rtw89_dev *rtwdev)
+{
+ u8 val;
+
+ val = rtw89_read32_mask(rtwdev, R_AX_IC_PWR_STATE, B_AX_WLMAC_PWR_STE_MASK);
+ if (val == MAC_AX_MAC_ON) {
+ /*
+ * A USB adapter might play as USB mass storage with driver and
+ * then switch to WiFi adapter, causing it stays on power-on
+ * state when doing WiFi USB probe. Return EAGAIN to caller to
+ * power-off and power-on again to reset the state.
+ */
+ if (rtwdev->hci.type == RTW89_HCI_TYPE_USB &&
+ !test_bit(RTW89_FLAG_PROBE_DONE, rtwdev->flags))
+ return -EAGAIN;
+
+ rtw89_err(rtwdev, "MAC has already powered on\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
static void rtw89_disable_fw_watchdog(struct rtw89_dev *rtwdev)
{
u32 val32;
@@ -4145,12 +4229,19 @@ int rtw89_mac_partial_init(struct rtw89_dev *rtwdev, bool include_bb)
int rtw89_mac_preinit(struct rtw89_dev *rtwdev)
{
+ const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
int ret;
ret = rtw89_mac_pwr_on(rtwdev);
if (ret)
return ret;
+ if (mac->mac_func_en) {
+ ret = mac->mac_func_en(rtwdev);
+ if (ret)
+ return ret;
+ }
+
return 0;
}
@@ -4283,6 +4374,12 @@ static const struct rtw89_port_reg rtw89_port_base_ax = {
R_AX_PORT_HGQ_WINDOW_CFG + 3},
};
+static const struct rtw89_mac_mu_gid_addr rtw89_mac_mu_gid_addr_ax = {
+ .position_en = {R_AX_GID_POSITION_EN0, R_AX_GID_POSITION_EN1},
+ .position = {R_AX_GID_POSITION0, R_AX_GID_POSITION1,
+ R_AX_GID_POSITION2, R_AX_GID_POSITION3},
+};
+
static void rtw89_mac_check_packet_ctrl(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link, u8 type)
{
@@ -4341,6 +4438,7 @@ static void rtw89_mac_bcn_drop(struct rtw89_dev *rtwdev,
#define BCN_HOLD_DEF 200
#define BCN_MASK_DEF 0
#define TBTT_ERLY_DEF 5
+#define TBTT_AGG_DEF 1
#define BCN_SET_UNIT 32
#define BCN_ERLY_SET_DLY (10 * 2)
@@ -4644,6 +4742,16 @@ static void rtw89_mac_port_cfg_tbtt_early(struct rtw89_dev *rtwdev,
B_AX_TBTTERLY_MASK, TBTT_ERLY_DEF);
}
+static void rtw89_mac_port_cfg_tbtt_agg(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
+{
+ const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
+ const struct rtw89_port_reg *p = mac->port_base;
+
+ rtw89_write16_port_mask(rtwdev, rtwvif_link, p->tbtt_agg,
+ B_AX_TBTT_AGG_NUM_MASK, TBTT_AGG_DEF);
+}
+
static void rtw89_mac_port_cfg_bss_color(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link)
{
@@ -4904,6 +5012,7 @@ int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvi
rtw89_mac_port_cfg_bcn_hold_time(rtwdev, rtwvif_link);
rtw89_mac_port_cfg_bcn_mask_area(rtwdev, rtwvif_link);
rtw89_mac_port_cfg_tbtt_early(rtwdev, rtwvif_link);
+ rtw89_mac_port_cfg_tbtt_agg(rtwdev, rtwvif_link);
rtw89_mac_port_cfg_bss_color(rtwdev, rtwvif_link);
rtw89_mac_port_cfg_mbssid(rtwdev, rtwvif_link);
rtw89_mac_port_cfg_func_en(rtwdev, rtwvif_link, true);
@@ -5198,10 +5307,10 @@ rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_l
if (start_detect)
return;
- ieee80211_connection_loss(vif);
- } else {
- rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true);
+ ieee80211_beacon_loss(vif);
}
+
+ rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true);
return;
case RTW89_BCN_FLTR_NOTIFY:
nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
@@ -6358,9 +6467,11 @@ int rtw89_mac_cfg_plt_ax(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_plt *plt)
void rtw89_mac_cfg_sb(struct rtw89_dev *rtwdev, u32 val)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ u32 reg = chip->btc_sb.n[0].cfg;
u32 fw_sb;
- fw_sb = rtw89_read32(rtwdev, R_AX_SCOREBOARD);
+ fw_sb = rtw89_read32(rtwdev, reg);
fw_sb = FIELD_GET(B_MAC_AX_SB_FW_MASK, fw_sb);
fw_sb = fw_sb & ~B_MAC_AX_BTGS1_NOTIFY;
if (!test_bit(RTW89_FLAG_POWERON, rtwdev->flags))
@@ -6371,13 +6482,16 @@ void rtw89_mac_cfg_sb(struct rtw89_dev *rtwdev, u32 val)
val = B_AX_TOGGLE |
FIELD_PREP(B_MAC_AX_SB_DRV_MASK, val) |
FIELD_PREP(B_MAC_AX_SB_FW_MASK, fw_sb);
- rtw89_write32(rtwdev, R_AX_SCOREBOARD, val);
+ rtw89_write32(rtwdev, reg, val);
fsleep(1000); /* avoid BT FW loss information */
}
u32 rtw89_mac_get_sb(struct rtw89_dev *rtwdev)
{
- return rtw89_read32(rtwdev, R_AX_SCOREBOARD);
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ u32 reg = chip->btc_sb.n[0].get;
+
+ return rtw89_read32(rtwdev, reg);
}
int rtw89_mac_cfg_ctrl_path(struct rtw89_dev *rtwdev, bool wl)
@@ -6662,6 +6776,8 @@ void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev,
void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *conf)
{
+ const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
+ const struct rtw89_mac_mu_gid_addr *addr = mac->mu_gid;
struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
struct rtw89_vif_link *rtwvif_link;
u8 mac_idx;
@@ -6681,20 +6797,20 @@ void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif *
p = (__le32 *)conf->mu_group.membership;
rtw89_write32(rtwdev,
- rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION_EN0, mac_idx),
+ rtw89_mac_reg_by_idx(rtwdev, addr->position_en[0], mac_idx),
le32_to_cpu(p[0]));
rtw89_write32(rtwdev,
- rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION_EN1, mac_idx),
+ rtw89_mac_reg_by_idx(rtwdev, addr->position_en[1], mac_idx),
le32_to_cpu(p[1]));
p = (__le32 *)conf->mu_group.position;
- rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION0, mac_idx),
+ rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, addr->position[0], mac_idx),
le32_to_cpu(p[0]));
- rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION1, mac_idx),
+ rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, addr->position[1], mac_idx),
le32_to_cpu(p[1]));
- rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION2, mac_idx),
+ rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, addr->position[2], mac_idx),
le32_to_cpu(p[2]));
- rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION3, mac_idx),
+ rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, addr->position[3], mac_idx),
le32_to_cpu(p[3]));
}
@@ -6942,6 +7058,12 @@ int rtw89_mac_write_xtal_si_ax(struct rtw89_dev *rtwdev, u8 offset, u8 val, u8 m
return ret;
}
+ if (!test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags) &&
+ (u32_get_bits(val32, B_AX_WL_XTAL_SI_ADDR_MASK) != offset ||
+ u32_get_bits(val32, B_AX_WL_XTAL_SI_DATA_MASK) != val))
+ rtw89_warn(rtwdev, "xtal si write: offset=%x val=%x poll=%x\n",
+ offset, val, val32);
+
return 0;
}
@@ -6965,7 +7087,12 @@ int rtw89_mac_read_xtal_si_ax(struct rtw89_dev *rtwdev, u8 offset, u8 *val)
return ret;
}
- *val = rtw89_read8(rtwdev, R_AX_WLAN_XTAL_SI_CTRL + 1);
+ if (!test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags) &&
+ u32_get_bits(val32, B_AX_WL_XTAL_SI_ADDR_MASK) != offset)
+ rtw89_warn(rtwdev, "xtal si read: offset=%x poll=%x\n",
+ offset, val32);
+
+ *val = u32_get_bits(val32, B_AX_WL_XTAL_SI_DATA_MASK);
return 0;
}
@@ -7163,6 +7290,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = {
.port_base = &rtw89_port_base_ax,
.agg_len_ht = R_AX_AGG_LEN_HT_0,
.ps_status = R_AX_PPWRBIT_SETTING,
+ .mu_gid = &rtw89_mac_mu_gid_addr_ax,
.muedca_ctrl = {
.addr = R_AX_MUEDCA_EN,
@@ -7184,6 +7312,10 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = {
.check_mac_en = rtw89_mac_check_mac_en_ax,
.sys_init = sys_init_ax,
.trx_init = trx_init_ax,
+ .preload_init = preload_init_set_ax,
+ .clr_aon_intr = NULL,
+ .err_imr_ctrl = err_imr_ctrl_ax,
+ .mac_func_en = NULL,
.hci_func_en = rtw89_mac_hci_func_en_ax,
.dmac_func_pre_en = rtw89_mac_dmac_func_pre_en_ax,
.dle_func_en = dle_func_en_ax,
@@ -7193,6 +7325,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = {
.typ_fltr_opt = rtw89_mac_typ_fltr_opt_ax,
.cfg_ppdu_status = rtw89_mac_cfg_ppdu_status_ax,
.cfg_phy_rpt = NULL,
+ .set_edcca_mode = NULL,
.dle_mix_cfg = dle_mix_cfg_ax,
.chk_dle_rdy = chk_dle_rdy_ax,
@@ -7206,6 +7339,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = {
.set_cpuio = set_cpuio_ax,
.dle_quota_change = dle_quota_change_ax,
+ .reset_pwr_state = rtw89_mac_reset_pwr_state_ax,
.disable_cpu = rtw89_mac_disable_cpu_ax,
.fwdl_enable_wcpu = rtw89_mac_enable_cpu_ax,
.fwdl_get_status = rtw89_fw_get_rdy_ax,
@@ -7215,6 +7349,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = {
.parse_phycap_map = rtw89_parse_phycap_map_ax,
.cnv_efuse_state = rtw89_cnv_efuse_state_ax,
.efuse_read_fw_secure = rtw89_efuse_read_fw_secure_ax,
+ .efuse_read_ecv = NULL,
.cfg_plt = rtw89_mac_cfg_plt_ax,
.get_plt_cnt = rtw89_mac_get_plt_cnt_ax,
diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
index 0007229d6753..e71a71648ab8 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.h
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
@@ -914,6 +914,9 @@ enum mac_ax_err_info {
MAC_AX_ERR_L0_CFG_DIS_NOTIFY = 0x0011,
MAC_AX_ERR_L0_CFG_HANDSHAKE = 0x0012,
MAC_AX_ERR_L0_RCVY_EN = 0x0013,
+ MAC_AX_ERR_L0_RESET_FORCE = 0x0020,
+ MAC_AX_ERR_L0_RESET_FORCE_C1 = 0x0021,
+ MAC_AX_ERR_L1_RESET_FORCE = 0x0022,
MAC_AX_SET_ERR_MAX,
};
@@ -929,8 +932,10 @@ struct rtw89_mac_size_set {
const struct rtw89_dle_size wde_size6;
const struct rtw89_dle_size wde_size7;
const struct rtw89_dle_size wde_size9;
+ const struct rtw89_dle_size wde_size16_v1;
const struct rtw89_dle_size wde_size17;
const struct rtw89_dle_size wde_size18;
+ const struct rtw89_dle_size wde_size18_v1;
const struct rtw89_dle_size wde_size19;
const struct rtw89_dle_size wde_size23;
const struct rtw89_dle_size wde_size25;
@@ -946,18 +951,22 @@ struct rtw89_mac_size_set {
const struct rtw89_dle_size ple_size17;
const struct rtw89_dle_size ple_size18;
const struct rtw89_dle_size ple_size19;
+ const struct rtw89_dle_size ple_size20_v1;
+ const struct rtw89_dle_size ple_size22_v1;
const struct rtw89_dle_size ple_size32;
const struct rtw89_dle_size ple_size33;
const struct rtw89_dle_size ple_size34;
const struct rtw89_wde_quota wde_qt0;
const struct rtw89_wde_quota wde_qt1;
const struct rtw89_wde_quota wde_qt0_v1;
+ const struct rtw89_wde_quota wde_qt3;
const struct rtw89_wde_quota wde_qt4;
const struct rtw89_wde_quota wde_qt6;
const struct rtw89_wde_quota wde_qt7;
const struct rtw89_wde_quota wde_qt16;
const struct rtw89_wde_quota wde_qt17;
const struct rtw89_wde_quota wde_qt18;
+ const struct rtw89_wde_quota wde_qt19_v1;
const struct rtw89_wde_quota wde_qt23;
const struct rtw89_wde_quota wde_qt25;
const struct rtw89_wde_quota wde_qt31;
@@ -965,13 +974,16 @@ struct rtw89_mac_size_set {
const struct rtw89_ple_quota ple_qt1;
const struct rtw89_ple_quota ple_qt4;
const struct rtw89_ple_quota ple_qt5;
+ const struct rtw89_ple_quota ple_qt5_v2;
const struct rtw89_ple_quota ple_qt9;
const struct rtw89_ple_quota ple_qt13;
const struct rtw89_ple_quota ple_qt18;
const struct rtw89_ple_quota ple_qt25;
const struct rtw89_ple_quota ple_qt26;
const struct rtw89_ple_quota ple_qt42;
+ const struct rtw89_ple_quota ple_qt42_v2;
const struct rtw89_ple_quota ple_qt43;
+ const struct rtw89_ple_quota ple_qt43_v2;
const struct rtw89_ple_quota ple_qt44;
const struct rtw89_ple_quota ple_qt45;
const struct rtw89_ple_quota ple_qt46;
@@ -991,12 +1003,23 @@ struct rtw89_mac_size_set {
const struct rtw89_ple_quota ple_qt_51b_wow;
const struct rtw89_rsvd_quota ple_rsvd_qt0;
const struct rtw89_rsvd_quota ple_rsvd_qt1;
+ const struct rtw89_rsvd_quota ple_rsvd_qt1_v1;
+ const struct rtw89_rsvd_quota ple_rsvd_qt9;
const struct rtw89_dle_rsvd_size rsvd0_size0;
+ const struct rtw89_dle_rsvd_size rsvd0_size6;
const struct rtw89_dle_rsvd_size rsvd1_size0;
+ const struct rtw89_dle_rsvd_size rsvd1_size2;
+ const struct rtw89_dle_input dle_input3;
+ const struct rtw89_dle_input dle_input18;
};
extern const struct rtw89_mac_size_set rtw89_mac_size;
+struct rtw89_mac_mu_gid_addr {
+ u32 position_en[2];
+ u32 position[4];
+};
+
struct rtw89_mac_gen_def {
u32 band1_offset;
u32 filter_model_addr;
@@ -1007,6 +1030,7 @@ struct rtw89_mac_gen_def {
const struct rtw89_port_reg *port_base;
u32 agg_len_ht;
u32 ps_status;
+ const struct rtw89_mac_mu_gid_addr *mu_gid;
struct rtw89_reg_def muedca_ctrl;
struct rtw89_reg_def bfee_ctrl;
@@ -1019,6 +1043,11 @@ struct rtw89_mac_gen_def {
enum rtw89_mac_hwmod_sel sel);
int (*sys_init)(struct rtw89_dev *rtwdev);
int (*trx_init)(struct rtw89_dev *rtwdev);
+ int (*preload_init)(struct rtw89_dev *rtwdev, u8 mac_idx,
+ enum rtw89_qta_mode mode);
+ void (*clr_aon_intr)(struct rtw89_dev *rtwdev);
+ void (*err_imr_ctrl)(struct rtw89_dev *rtwdev, bool en);
+ int (*mac_func_en)(struct rtw89_dev *rtwdev);
void (*hci_func_en)(struct rtw89_dev *rtwdev);
void (*dmac_func_pre_en)(struct rtw89_dev *rtwdev);
void (*dle_func_en)(struct rtw89_dev *rtwdev, bool enable);
@@ -1033,6 +1062,7 @@ struct rtw89_mac_gen_def {
u8 mac_idx);
int (*cfg_ppdu_status)(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable);
void (*cfg_phy_rpt)(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable);
+ void (*set_edcca_mode)(struct rtw89_dev *rtwdev, u8 mac_idx, bool normal);
int (*dle_mix_cfg)(struct rtw89_dev *rtwdev, const struct rtw89_dle_mem *cfg);
int (*chk_dle_rdy)(struct rtw89_dev *rtwdev, bool wde_or_ple);
@@ -1052,6 +1082,7 @@ struct rtw89_mac_gen_def {
struct rtw89_cpuio_ctrl *ctrl_para, bool wd);
int (*dle_quota_change)(struct rtw89_dev *rtwdev, bool band1_en);
+ int (*reset_pwr_state)(struct rtw89_dev *rtwdev);
void (*disable_cpu)(struct rtw89_dev *rtwdev);
int (*fwdl_enable_wcpu)(struct rtw89_dev *rtwdev, u8 boot_reason,
bool dlfw, bool include_bb);
@@ -1062,6 +1093,7 @@ struct rtw89_mac_gen_def {
int (*parse_phycap_map)(struct rtw89_dev *rtwdev);
int (*cnv_efuse_state)(struct rtw89_dev *rtwdev, bool idle);
int (*efuse_read_fw_secure)(struct rtw89_dev *rtwdev);
+ int (*efuse_read_ecv)(struct rtw89_dev *rtwdev);
int (*cfg_plt)(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_plt *plt);
u16 (*get_plt_cnt)(struct rtw89_dev *rtwdev, u8 band);
@@ -1105,6 +1137,22 @@ u32 rtw89_mac_reg_by_idx(struct rtw89_dev *rtwdev, u32 reg_base, u8 band)
return band == 0 ? reg_base : (reg_base + mac->band1_offset);
}
+static inline void
+rtw89_write16_idx(struct rtw89_dev *rtwdev, u32 addr, u16 data, u8 band)
+{
+ addr = rtw89_mac_reg_by_idx(rtwdev, addr, band);
+
+ rtw89_write16(rtwdev, addr, data);
+}
+
+static inline void
+rtw89_write32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask, u32 data, u8 band)
+{
+ addr = rtw89_mac_reg_by_idx(rtwdev, addr, band);
+
+ rtw89_write32_mask(rtwdev, addr, mask, data);
+}
+
static inline
u32 rtw89_mac_reg_by_port(struct rtw89_dev *rtwdev, u32 base, u8 port, u8 mac_idx)
{
@@ -1218,6 +1266,14 @@ int rtw89_mac_check_mac_en(struct rtw89_dev *rtwdev, u8 band,
return mac->check_mac_en(rtwdev, band, sel);
}
+static inline void rtw89_mac_clr_aon_intr(struct rtw89_dev *rtwdev)
+{
+ const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
+
+ if (mac->clr_aon_intr)
+ mac->clr_aon_intr(rtwdev);
+}
+
int rtw89_mac_write_lte(struct rtw89_dev *rtwdev, const u32 offset, u32 val);
int rtw89_mac_read_lte(struct rtw89_dev *rtwdev, const u32 offset, u32 *val);
int rtw89_mac_dle_dfi_cfg(struct rtw89_dev *rtwdev, struct rtw89_mac_dle_dfi_ctrl *ctrl);
@@ -1340,6 +1396,24 @@ int rtw89_mac_cfg_ppdu_status_bands(struct rtw89_dev *rtwdev, bool enable)
return rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_1, enable);
}
+static inline
+void rtw89_mac_set_edcca_mode(struct rtw89_dev *rtwdev, u8 mac_idx, bool normal)
+{
+ const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
+
+ if (!mac->set_edcca_mode)
+ return;
+
+ mac->set_edcca_mode(rtwdev, mac_idx, normal);
+}
+
+static inline
+void rtw89_mac_set_edcca_mode_bands(struct rtw89_dev *rtwdev, bool normal)
+{
+ rtw89_mac_set_edcca_mode(rtwdev, RTW89_MAC_0, normal);
+ rtw89_mac_set_edcca_mode(rtwdev, RTW89_MAC_1, normal);
+}
+
void rtw89_mac_set_rx_fltr(struct rtw89_dev *rtwdev, u8 mac_idx, u32 rx_fltr);
void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev);
void rtw89_mac_flush_txq(struct rtw89_dev *rtwdev, u32 queues, bool drop);
@@ -1352,6 +1426,8 @@ int rtw89_mac_cfg_gnt_v1(struct rtw89_dev *rtwdev,
const struct rtw89_mac_ax_coex_gnt *gnt_cfg);
int rtw89_mac_cfg_gnt_v2(struct rtw89_dev *rtwdev,
const struct rtw89_mac_ax_coex_gnt *gnt_cfg);
+int rtw89_mac_cfg_gnt_v3(struct rtw89_dev *rtwdev,
+ const struct rtw89_mac_ax_coex_gnt *gnt_cfg);
static inline
int rtw89_mac_cfg_plt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_plt *plt)
@@ -1567,6 +1643,8 @@ enum rtw89_mac_xtal_si_offset {
XTAL_SI_APBT = 0xD1,
XTAL_SI_PLL = 0xE0,
XTAL_SI_PLL_1 = 0xE1,
+ XTAL_SI_CHIP_ID_L = 0xFD,
+ XTAL_SI_CHIP_ID_H = 0xFE,
};
static inline
@@ -1597,6 +1675,16 @@ int rtw89_mac_get_dle_rsvd_qt_cfg(struct rtw89_dev *rtwdev,
struct rtw89_mac_dle_rsvd_qt_cfg *cfg);
int rtw89_mac_cpu_io_rx(struct rtw89_dev *rtwdev, bool wow_enable);
+static inline int rtw89_mac_efuse_read_ecv(struct rtw89_dev *rtwdev)
+{
+ const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
+
+ if (!mac->efuse_read_ecv)
+ return -ENOENT;
+
+ return mac->efuse_read_ecv(rtwdev);
+}
+
static inline
void rtw89_fwdl_secure_idmem_share_mode(struct rtw89_dev *rtwdev, u8 mode)
{
@@ -1605,7 +1693,7 @@ void rtw89_fwdl_secure_idmem_share_mode(struct rtw89_dev *rtwdev, u8 mode)
if (!mac->fwdl_secure_idmem_share_mode)
return;
- return mac->fwdl_secure_idmem_share_mode(rtwdev, mode);
+ mac->fwdl_secure_idmem_share_mode(rtwdev, mode);
}
static inline
@@ -1719,4 +1807,16 @@ void rtw89_tx_rpt_skbs_purge(struct rtw89_dev *rtwdev)
rtw89_tx_rpt_tx_status(rtwdev, skbs[i],
RTW89_TX_MACID_DROP);
}
+
+static inline bool rtw89_mac_chk_preload_allow(struct rtw89_dev *rtwdev)
+{
+ if (rtwdev->hci.type != RTW89_HCI_TYPE_PCIE)
+ return false;
+
+ if (rtwdev->chip->chip_id == RTL8922D && rtwdev->hal.cid == RTL8922D_CID7090)
+ return true;
+
+ return false;
+}
+
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index f39ca1c2ed10..315bb0d0759f 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -127,6 +127,7 @@ static int __rtw89_ops_add_iface_link(struct rtw89_dev *rtwdev,
rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
rtwvif_link->rand_tsf_done = false;
rtwvif_link->detect_bcn_count = 0;
+ rtwvif_link->last_sync_bcn_tsf = 0;
rcu_read_lock();
@@ -719,7 +720,8 @@ static void rtw89_ops_vif_cfg_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_MLD_VALID_LINKS) {
struct rtw89_vif_link *cur = rtw89_get_designated_link(rtwvif);
- rtw89_chip_rfk_channel(rtwdev, cur);
+ if (RTW89_CHK_FW_FEATURE_GROUP(WITH_RFK_PRE_NOTIFY, &rtwdev->fw))
+ rtw89_chip_rfk_channel(rtwdev, cur);
if (hweight16(vif->active_links) == 1)
rtwvif->mlo_mode = RTW89_MLO_MODE_MLSR;
@@ -1436,9 +1438,9 @@ static void rtw89_ops_channel_switch_beacon(struct ieee80211_hw *hw,
BUILD_BUG_ON(RTW89_MLD_NON_STA_LINK_NUM != 1);
- rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
+ rtwvif_link = rtw89_get_designated_link(rtwvif);
if (unlikely(!rtwvif_link)) {
- rtw89_err(rtwdev, "chsw bcn: find no link on HW-0\n");
+ rtw89_err(rtwdev, "chsw bcn: find no designated link\n");
return;
}
@@ -1612,12 +1614,23 @@ static int __rtw89_ops_set_vif_links(struct rtw89_dev *rtwdev,
return 0;
}
-static void rtw89_vif_cfg_fw_links(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- unsigned long links, bool en)
+static void rtw89_vif_update_fw_links(struct rtw89_dev *rtwdev,
+ struct rtw89_vif *rtwvif,
+ u16 current_links, bool en)
{
+ struct rtw89_vif_ml_trans *trans = &rtwvif->ml_trans;
struct rtw89_vif_link *rtwvif_link;
unsigned int link_id;
+ unsigned long links;
+
+ /* Do follow-up when all updating links exist. */
+ if (current_links != trans->mediate_links)
+ return;
+
+ if (en)
+ links = trans->links_to_add;
+ else
+ links = trans->links_to_del;
for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
rtwvif_link = rtwvif->links[link_id];
@@ -1628,20 +1641,6 @@ static void rtw89_vif_cfg_fw_links(struct rtw89_dev *rtwdev,
}
}
-static void rtw89_vif_update_fw_links(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- u16 current_links)
-{
- struct rtw89_vif_ml_trans *trans = &rtwvif->ml_trans;
-
- /* Do follow-up when all updating links exist. */
- if (current_links != trans->mediate_links)
- return;
-
- rtw89_vif_cfg_fw_links(rtwdev, rtwvif, trans->links_to_del, false);
- rtw89_vif_cfg_fw_links(rtwdev, rtwvif, trans->links_to_add, true);
-}
-
static
int rtw89_ops_change_vif_links(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -1683,7 +1682,7 @@ int rtw89_ops_change_vif_links(struct ieee80211_hw *hw,
if (rtwdev->scanning)
rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);
- rtw89_vif_update_fw_links(rtwdev, rtwvif, old_links);
+ rtw89_vif_update_fw_links(rtwdev, rtwvif, old_links, true);
if (!old_links)
__rtw89_ops_clr_vif_links(rtwdev, rtwvif,
@@ -1716,6 +1715,9 @@ int rtw89_ops_change_vif_links(struct ieee80211_hw *hw,
BIT(RTW89_VIF_IDLE_LINK_ID));
}
+ if (!ret)
+ rtw89_vif_update_fw_links(rtwdev, rtwvif, new_links, false);
+
rtw89_enter_ips_by_hwflags(rtwdev);
return ret;
}
diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c
index 556e5f98e8d4..dc66b1ee851a 100644
--- a/drivers/net/wireless/realtek/rtw89/mac_be.c
+++ b/drivers/net/wireless/realtek/rtw89/mac_be.c
@@ -62,6 +62,12 @@ static const struct rtw89_port_reg rtw89_port_base_be = {
R_BE_PORT_HGQ_WINDOW_CFG + 3},
};
+static const struct rtw89_mac_mu_gid_addr rtw89_mac_mu_gid_addr_be = {
+ .position_en = {R_BE_GID_POSITION_EN0, R_BE_GID_POSITION_EN1},
+ .position = {R_BE_GID_POSITION0, R_BE_GID_POSITION1,
+ R_BE_GID_POSITION2, R_BE_GID_POSITION3},
+};
+
static int rtw89_mac_check_mac_en_be(struct rtw89_dev *rtwdev, u8 mac_idx,
enum rtw89_mac_hwmod_sel sel)
{
@@ -89,6 +95,7 @@ static void hfc_get_mix_info_be(struct rtw89_dev *rtwdev)
struct rtw89_hfc_prec_cfg *prec_cfg = &param->prec_cfg;
struct rtw89_hfc_pub_cfg *pub_cfg = &param->pub_cfg;
struct rtw89_hfc_pub_info *info = &param->pub_info;
+ const struct rtw89_chip_info *chip = rtwdev->chip;
u32 val;
val = rtw89_read32(rtwdev, R_BE_PUB_PAGE_INFO1);
@@ -116,14 +123,23 @@ static void hfc_get_mix_info_be(struct rtw89_dev *rtwdev)
val = rtw89_read32(rtwdev, R_BE_CH_PAGE_CTRL);
prec_cfg->ch011_prec = u32_get_bits(val, B_BE_PREC_PAGE_CH011_V1_MASK);
+ if (chip->chip_id == RTL8922D)
+ prec_cfg->ch011_full_page = u32_get_bits(val, B_BE_FULL_WD_PG_MASK);
prec_cfg->h2c_prec = u32_get_bits(val, B_BE_PREC_PAGE_CH12_V1_MASK);
val = rtw89_read32(rtwdev, R_BE_PUB_PAGE_CTRL2);
pub_cfg->pub_max = u32_get_bits(val, B_BE_PUBPG_ALL_MASK);
val = rtw89_read32(rtwdev, R_BE_WP_PAGE_CTRL1);
- prec_cfg->wp_ch07_prec = u32_get_bits(val, B_BE_PREC_PAGE_WP_CH07_MASK);
- prec_cfg->wp_ch811_prec = u32_get_bits(val, B_BE_PREC_PAGE_WP_CH811_MASK);
+ if (chip->chip_id == RTL8922D) {
+ prec_cfg->wp_ch07_prec = u32_get_bits(val, B_BE_PREC_PAGE_WP_CH07_V1_MASK);
+ prec_cfg->wp_ch07_full_page = u32_get_bits(val, B_BE_FULL_PAGE_WP_CH07_MASK);
+ prec_cfg->wp_ch811_prec = u32_get_bits(val, B_BE_PREC_PAGE_WP_CH811_V1_MASK);
+ prec_cfg->wp_ch811_full_page = u32_get_bits(val, B_BE_FULL_PAGE_WP_CH811_MASK);
+ } else {
+ prec_cfg->wp_ch07_prec = u32_get_bits(val, B_BE_PREC_PAGE_WP_CH07_MASK);
+ prec_cfg->wp_ch811_prec = u32_get_bits(val, B_BE_PREC_PAGE_WP_CH811_MASK);
+ }
val = rtw89_read32(rtwdev, R_BE_WP_PAGE_CTRL2);
pub_cfg->wp_thrd = u32_get_bits(val, B_BE_WP_THRD_MASK);
@@ -148,17 +164,26 @@ static void hfc_mix_cfg_be(struct rtw89_dev *rtwdev)
struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
const struct rtw89_hfc_prec_cfg *prec_cfg = &param->prec_cfg;
const struct rtw89_hfc_pub_cfg *pub_cfg = &param->pub_cfg;
+ const struct rtw89_chip_info *chip = rtwdev->chip;
u32 val;
val = u32_encode_bits(prec_cfg->ch011_prec, B_BE_PREC_PAGE_CH011_V1_MASK) |
u32_encode_bits(prec_cfg->h2c_prec, B_BE_PREC_PAGE_CH12_V1_MASK);
+ if (chip->chip_id == RTL8922D)
+ val = u32_replace_bits(val, prec_cfg->ch011_full_page, B_BE_FULL_WD_PG_MASK);
rtw89_write32(rtwdev, R_BE_CH_PAGE_CTRL, val);
val = u32_encode_bits(pub_cfg->pub_max, B_BE_PUBPG_ALL_MASK);
rtw89_write32(rtwdev, R_BE_PUB_PAGE_CTRL2, val);
- val = u32_encode_bits(prec_cfg->wp_ch07_prec, B_BE_PREC_PAGE_WP_CH07_MASK) |
- u32_encode_bits(prec_cfg->wp_ch811_prec, B_BE_PREC_PAGE_WP_CH811_MASK);
+ if (chip->chip_id == RTL8922D)
+ val = u32_encode_bits(prec_cfg->wp_ch07_prec, B_BE_PREC_PAGE_WP_CH07_V1_MASK) |
+ u32_encode_bits(prec_cfg->wp_ch07_full_page, B_BE_FULL_PAGE_WP_CH07_MASK) |
+ u32_encode_bits(prec_cfg->wp_ch811_prec, B_BE_PREC_PAGE_WP_CH811_V1_MASK) |
+ u32_encode_bits(prec_cfg->wp_ch811_full_page, B_BE_FULL_PAGE_WP_CH811_MASK);
+ else
+ val = u32_encode_bits(prec_cfg->wp_ch07_prec, B_BE_PREC_PAGE_WP_CH07_MASK) |
+ u32_encode_bits(prec_cfg->wp_ch811_prec, B_BE_PREC_PAGE_WP_CH811_MASK);
rtw89_write32(rtwdev, R_BE_WP_PAGE_CTRL1, val);
val = u32_replace_bits(rtw89_read32(rtwdev, R_BE_HCI_FC_CTRL),
@@ -200,6 +225,9 @@ static void dle_func_en_be(struct rtw89_dev *rtwdev, bool enable)
static void dle_clk_en_be(struct rtw89_dev *rtwdev, bool enable)
{
+ if (rtwdev->chip->chip_id != RTL8922A)
+ return;
+
if (enable)
rtw89_write32_set(rtwdev, R_BE_DMAC_CLK_EN,
B_BE_DLE_WDE_CLK_EN | B_BE_DLE_PLE_CLK_EN);
@@ -331,6 +359,11 @@ static void ple_quota_cfg_be(struct rtw89_dev *rtwdev,
SET_QUOTA(cpu_io, PLE, 10);
SET_QUOTA(tx_rpt, PLE, 11);
SET_QUOTA(h2d, PLE, 12);
+
+ if (rtwdev->chip->chip_id == RTL8922A)
+ return;
+
+ SET_QUOTA(snrpt, PLE, 13);
}
static void rtw89_mac_hci_func_en_be(struct rtw89_dev *rtwdev)
@@ -341,6 +374,8 @@ static void rtw89_mac_hci_func_en_be(struct rtw89_dev *rtwdev)
static void rtw89_mac_dmac_func_pre_en_be(struct rtw89_dev *rtwdev)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ u32 mask;
u32 val;
val = rtw89_read32(rtwdev, R_BE_HAXI_INIT_CFG1);
@@ -364,12 +399,12 @@ static void rtw89_mac_dmac_func_pre_en_be(struct rtw89_dev *rtwdev)
rtw89_write32(rtwdev, R_BE_HAXI_INIT_CFG1, val);
- rtw89_write32_clr(rtwdev, R_BE_HAXI_DMA_STOP1,
- B_BE_STOP_CH0 | B_BE_STOP_CH1 | B_BE_STOP_CH2 |
- B_BE_STOP_CH3 | B_BE_STOP_CH4 | B_BE_STOP_CH5 |
- B_BE_STOP_CH6 | B_BE_STOP_CH7 | B_BE_STOP_CH8 |
- B_BE_STOP_CH9 | B_BE_STOP_CH10 | B_BE_STOP_CH11 |
- B_BE_STOP_CH12 | B_BE_STOP_CH13 | B_BE_STOP_CH14);
+ if (chip->chip_id == RTL8922A)
+ mask = B_BE_TX_STOP1_MASK;
+ else
+ mask = B_BE_TX_STOP1_MASK_V1;
+
+ rtw89_write32_clr(rtwdev, R_BE_HAXI_DMA_STOP1, mask);
rtw89_write32_set(rtwdev, R_BE_DMAC_TABLE_CTRL, B_BE_DMAC_ADDR_MODE);
}
@@ -396,6 +431,12 @@ int rtw89_mac_write_xtal_si_be(struct rtw89_dev *rtwdev, u8 offset, u8 val, u8 m
return ret;
}
+ if (!test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags) &&
+ (u32_get_bits(val32, B_BE_WL_XTAL_SI_ADDR_MASK) != offset ||
+ u32_get_bits(val32, B_BE_WL_XTAL_SI_DATA_MASK) != val))
+ rtw89_warn(rtwdev, "xtal si write: offset=%x val=%x poll=%x\n",
+ offset, val, val32);
+
return 0;
}
@@ -420,7 +461,141 @@ int rtw89_mac_read_xtal_si_be(struct rtw89_dev *rtwdev, u8 offset, u8 *val)
return ret;
}
- *val = rtw89_read8(rtwdev, R_BE_WLAN_XTAL_SI_CTRL + 1);
+ if (!test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags) &&
+ u32_get_bits(val32, B_BE_WL_XTAL_SI_ADDR_MASK) != offset)
+ rtw89_warn(rtwdev, "xtal si read: offset=%x poll=%x\n",
+ offset, val32);
+
+ *val = u32_get_bits(val32, B_BE_WL_XTAL_SI_DATA_MASK);
+
+ return 0;
+}
+
+static int rtw89_mac_reset_pwr_state_be(struct rtw89_dev *rtwdev)
+{
+ u32 val32;
+ int ret;
+
+ val32 = rtw89_read32(rtwdev, R_BE_SYSON_FSM_MON);
+ val32 &= WLAN_FSM_MASK;
+ val32 |= WLAN_FSM_SET;
+ rtw89_write32(rtwdev, R_BE_SYSON_FSM_MON, val32);
+
+ ret = read_poll_timeout(rtw89_read32_mask, val32, val32 == WLAN_FSM_IDLE,
+ 1000, 2000000, false,
+ rtwdev, R_BE_SYSON_FSM_MON, WLAN_FSM_STATE_MASK);
+ if (ret) {
+ rtw89_err(rtwdev, "[ERR]Polling WLAN PMC timeout= %X\n", val32);
+ return ret;
+ }
+
+ val32 = rtw89_read32_mask(rtwdev, R_BE_IC_PWR_STATE, B_BE_WLMAC_PWR_STE_MASK);
+ if (val32 == MAC_AX_MAC_OFF) {
+ rtw89_write32_clr(rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HAXIDMA_IO_EN);
+
+ ret = read_poll_timeout(rtw89_read32_mask, val32, !val32,
+ 1000, 2000000, false,
+ rtwdev, R_BE_HCI_OPT_CTRL,
+ B_BE_HAXIDMA_IO_ST | B_BE_HAXIDMA_BACKUP_RESTORE_ST);
+ if (ret) {
+ rtw89_err(rtwdev, "[ERR]Polling HAXI IO timeout= %X\n", val32);
+ return ret;
+ }
+
+ rtw89_write32_clr(rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HCI_WLAN_IO_EN);
+
+ ret = read_poll_timeout(rtw89_read32_mask, val32, !val32,
+ 1000, 2000000, false,
+ rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HCI_WLAN_IO_ST);
+ if (ret) {
+ rtw89_err(rtwdev, "[ERR]Polling WLAN IO timeout= %X\n", val32);
+ return ret;
+ }
+
+ rtw89_write32_clr(rtwdev, R_BE_SYS_PW_CTRL, B_BE_EN_WLON);
+ rtw89_write32_clr(rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFM_SWLPS);
+ } else if (val32 == MAC_AX_MAC_ON) {
+ rtw89_write32_clr(rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HAXIDMA_IO_EN);
+
+ ret = read_poll_timeout(rtw89_read32_mask, val32, !val32,
+ 1000, 2000000, false,
+ rtwdev, R_BE_HCI_OPT_CTRL,
+ B_BE_HAXIDMA_IO_ST | B_BE_HAXIDMA_BACKUP_RESTORE_ST);
+ if (ret) {
+ rtw89_err(rtwdev, "[ERR]Polling HAXI IO timeout= %X\n", val32);
+ return ret;
+ }
+
+ rtw89_write32_clr(rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HCI_WLAN_IO_EN);
+
+ ret = read_poll_timeout(rtw89_read32_mask, val32, !val32,
+ 1000, 2000000, false,
+ rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HCI_WLAN_IO_ST);
+ if (ret) {
+ rtw89_err(rtwdev, "[ERR]Polling WLAN IO timeout= %X\n", val32);
+ return ret;
+ }
+
+ rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_EN_WLON);
+ rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFM_OFFMAC);
+
+ ret = read_poll_timeout(rtw89_read32_mask, val32, val32 == MAC_AX_MAC_OFF,
+ 1000, 2000000, false,
+ rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFM_OFFMAC);
+ if (ret) {
+ rtw89_err(rtwdev, "[ERR]Polling MAC state timeout= %X\n", val32);
+ return ret;
+ }
+
+ rtw89_write32_clr(rtwdev, R_BE_SYS_PW_CTRL, B_BE_EN_WLON);
+ rtw89_write32_clr(rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFM_SWLPS);
+ } else if (val32 == MAC_AX_MAC_LPS) {
+ rtw89_write32_clr(rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HAXIDMA_IO_EN);
+
+ ret = read_poll_timeout(rtw89_read32_mask, val32, !val32,
+ 1000, 2000000, false,
+ rtwdev, R_BE_HCI_OPT_CTRL,
+ B_BE_HAXIDMA_IO_ST | B_BE_HAXIDMA_BACKUP_RESTORE_ST);
+ if (ret) {
+ rtw89_err(rtwdev, "[ERR]Polling HAXI IO timeout= %X\n", val32);
+ return ret;
+ }
+
+ rtw89_write32_clr(rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HCI_WLAN_IO_EN);
+
+ ret = read_poll_timeout(rtw89_read32_mask, val32, !val32,
+ 1000, 2000000, false,
+ rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HCI_WLAN_IO_ST);
+ if (ret) {
+ rtw89_err(rtwdev, "[ERR]Polling WLAN IO timeout= %X\n", val32);
+ return ret;
+ }
+
+ rtw89_write32_set(rtwdev, R_BE_WLLPS_CTRL, B_BE_FORCE_LEAVE_LPS);
+
+ ret = read_poll_timeout(rtw89_read32_mask, val32, val32 == MAC_AX_MAC_ON,
+ 1000, 2000000, false,
+ rtwdev, R_BE_IC_PWR_STATE, B_BE_WLMAC_PWR_STE_MASK);
+ if (ret) {
+ rtw89_err(rtwdev, "[ERR]Polling MAC STS timeout= %X\n", val32);
+ return ret;
+ }
+
+ rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_EN_WLON);
+ rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFM_OFFMAC);
+
+ ret = read_poll_timeout(rtw89_read32_mask, val32, val32 == MAC_AX_MAC_OFF,
+ 1000, 2000000, false,
+ rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFM_OFFMAC);
+ if (ret) {
+ rtw89_err(rtwdev, "[ERR]Polling MAC state timeout= %X\n", val32);
+ return ret;
+ }
+
+ rtw89_write32_clr(rtwdev, R_BE_WLLPS_CTRL, B_BE_FORCE_LEAVE_LPS);
+ rtw89_write32_clr(rtwdev, R_BE_SYS_PW_CTRL, B_BE_EN_WLON);
+ rtw89_write32_clr(rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFM_SWLPS);
+ }
return 0;
}
@@ -439,7 +614,8 @@ static void rtw89_mac_disable_cpu_be(struct rtw89_dev *rtwdev)
val32 &= B_BE_RUN_ENV_MASK;
rtw89_write32(rtwdev, R_BE_WCPU_FW_CTRL, val32);
- rtw89_write32_set(rtwdev, R_BE_DCPU_PLATFORM_ENABLE, B_BE_DCPU_PLATFORM_EN);
+ if (rtwdev->chip->chip_id == RTL8922A)
+ rtw89_write32_set(rtwdev, R_BE_DCPU_PLATFORM_ENABLE, B_BE_DCPU_PLATFORM_EN);
rtw89_write32(rtwdev, R_BE_UDM0, 0);
rtw89_write32(rtwdev, R_BE_HALT_C2H, 0);
@@ -585,31 +761,125 @@ static int rtw89_fwdl_check_path_ready_be(struct rtw89_dev *rtwdev,
static int dmac_func_en_be(struct rtw89_dev *rtwdev)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+
+ if (chip->chip_id == RTL8922A)
+ return 0;
+
+ rtw89_write32_set(rtwdev, R_BE_DMAC_FUNC_EN,
+ B_BE_MAC_FUNC_EN | B_BE_DMAC_FUNC_EN |
+ B_BE_MPDU_PROC_EN | B_BE_WD_RLS_EN |
+ B_BE_DLE_WDE_EN | B_BE_TXPKT_CTRL_EN |
+ B_BE_STA_SCH_EN | B_BE_DLE_PLE_EN |
+ B_BE_PKT_BUF_EN | B_BE_DMAC_TBL_EN |
+ B_BE_PKT_IN_EN | B_BE_DLE_CPUIO_EN |
+ B_BE_DISPATCHER_EN | B_BE_BBRPT_EN |
+ B_BE_MAC_SEC_EN | B_BE_H_AXIDMA_EN |
+ B_BE_DMAC_MLO_EN | B_BE_PLRLS_EN |
+ B_BE_P_AXIDMA_EN | B_BE_DLE_DATACPUIO_EN);
+
+ return 0;
+}
+
+static int cmac_share_func_en_be(struct rtw89_dev *rtwdev)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+
+ if (chip->chip_id == RTL8922A)
+ return 0;
+
+ rtw89_write32_set(rtwdev, R_BE_CMAC_SHARE_FUNC_EN,
+ B_BE_CMAC_SHARE_EN | B_BE_RESPBA_EN |
+ B_BE_ADDRSRCH_EN | B_BE_BTCOEX_EN);
+
+ return 0;
+}
+
+static int cmac_pwr_en_be(struct rtw89_dev *rtwdev, u8 mac_idx, bool en)
+{
+ if (mac_idx > RTW89_MAC_1)
+ return -EINVAL;
+
+ if (mac_idx == RTW89_MAC_0) {
+ if (en == test_bit(RTW89_FLAG_CMAC0_PWR, rtwdev->flags))
+ return 0;
+
+ if (en) {
+ rtw89_write32_set(rtwdev, R_BE_AFE_CTRL1,
+ B_BE_R_SYM_WLCMAC0_ALL_EN);
+ rtw89_write32_clr(rtwdev, R_BE_FEN_RST_ENABLE,
+ B_BE_R_SYM_ISO_CMAC02PP);
+ rtw89_write32_set(rtwdev, R_BE_FEN_RST_ENABLE,
+ B_BE_CMAC0_FEN);
+
+ set_bit(RTW89_FLAG_CMAC0_PWR, rtwdev->flags);
+ } else {
+ rtw89_write32_clr(rtwdev, R_BE_FEN_RST_ENABLE,
+ B_BE_CMAC0_FEN);
+ rtw89_write32_set(rtwdev, R_BE_FEN_RST_ENABLE,
+ B_BE_R_SYM_ISO_CMAC02PP);
+ rtw89_write32_clr(rtwdev, R_BE_AFE_CTRL1,
+ B_BE_R_SYM_WLCMAC0_ALL_EN);
+
+ clear_bit(RTW89_FLAG_CMAC0_PWR, rtwdev->flags);
+ }
+ } else {
+ if (en == test_bit(RTW89_FLAG_CMAC1_PWR, rtwdev->flags))
+ return 0;
+
+ if (en) {
+ rtw89_write32_set(rtwdev, R_BE_AFE_CTRL1,
+ B_BE_R_SYM_WLCMAC1_ALL_EN);
+ rtw89_write32_clr(rtwdev, R_BE_FEN_RST_ENABLE,
+ B_BE_R_SYM_ISO_CMAC12PP);
+ rtw89_write32_set(rtwdev, R_BE_FEN_RST_ENABLE,
+ B_BE_CMAC1_FEN);
+
+ set_bit(RTW89_FLAG_CMAC1_PWR, rtwdev->flags);
+ } else {
+ rtw89_write32_clr(rtwdev, R_BE_FEN_RST_ENABLE,
+ B_BE_CMAC1_FEN);
+ rtw89_write32_set(rtwdev, R_BE_FEN_RST_ENABLE,
+ B_BE_R_SYM_ISO_CMAC12PP);
+ rtw89_write32_clr(rtwdev, R_BE_AFE_CTRL1,
+ B_BE_R_SYM_WLCMAC1_ALL_EN);
+
+ clear_bit(RTW89_FLAG_CMAC1_PWR, rtwdev->flags);
+ }
+ }
+
return 0;
}
static int cmac_func_en_be(struct rtw89_dev *rtwdev, u8 mac_idx, bool en)
{
+ enum rtw89_flags pwr_flag, func_flag;
u32 reg;
if (mac_idx > RTW89_MAC_1)
return -EINVAL;
- if (mac_idx == RTW89_MAC_0)
+ if (mac_idx == RTW89_MAC_0) {
+ pwr_flag = RTW89_FLAG_CMAC0_PWR;
+ func_flag = RTW89_FLAG_CMAC0_FUNC;
+ } else {
+ pwr_flag = RTW89_FLAG_CMAC1_PWR;
+ func_flag = RTW89_FLAG_CMAC1_FUNC;
+ }
+
+ if (!test_bit(pwr_flag, rtwdev->flags)) {
+ rtw89_warn(rtwdev, "CMAC %u power cut did not release\n", mac_idx);
return 0;
+ }
if (en) {
- rtw89_write32_set(rtwdev, R_BE_AFE_CTRL1, B_BE_AFE_CTRL1_SET);
- rtw89_write32_clr(rtwdev, R_BE_SYS_ISO_CTRL_EXTEND, B_BE_R_SYM_ISO_CMAC12PP);
- rtw89_write32_set(rtwdev, R_BE_FEN_RST_ENABLE, B_BE_CMAC1_FEN);
-
reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_CK_EN, mac_idx);
rtw89_write32_set(rtwdev, reg, B_BE_CK_EN_SET);
reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_CMAC_FUNC_EN, mac_idx);
rtw89_write32_set(rtwdev, reg, B_BE_CMAC_FUNC_EN_SET);
- set_bit(RTW89_FLAG_CMAC1_FUNC, rtwdev->flags);
+ set_bit(func_flag, rtwdev->flags);
} else {
reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_CMAC_FUNC_EN, mac_idx);
rtw89_write32_clr(rtwdev, reg, B_BE_CMAC_FUNC_EN_SET);
@@ -617,11 +887,7 @@ static int cmac_func_en_be(struct rtw89_dev *rtwdev, u8 mac_idx, bool en)
reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_CK_EN, mac_idx);
rtw89_write32_clr(rtwdev, reg, B_BE_CK_EN_SET);
- rtw89_write32_clr(rtwdev, R_BE_FEN_RST_ENABLE, B_BE_CMAC1_FEN);
- rtw89_write32_set(rtwdev, R_BE_SYS_ISO_CTRL_EXTEND, B_BE_R_SYM_ISO_CMAC12PP);
- rtw89_write32_clr(rtwdev, R_BE_AFE_CTRL1, B_BE_AFE_CTRL1_SET);
-
- clear_bit(RTW89_FLAG_CMAC1_FUNC, rtwdev->flags);
+ clear_bit(func_flag, rtwdev->flags);
}
return 0;
@@ -640,6 +906,14 @@ static int sys_init_be(struct rtw89_dev *rtwdev)
if (ret)
return ret;
+ ret = cmac_share_func_en_be(rtwdev);
+ if (ret)
+ return ret;
+
+ ret = cmac_pwr_en_be(rtwdev, RTW89_MAC_0, true);
+ if (ret)
+ return ret;
+
ret = cmac_func_en_be(rtwdev, RTW89_MAC_0, true);
if (ret)
return ret;
@@ -651,11 +925,53 @@ static int sys_init_be(struct rtw89_dev *rtwdev)
return ret;
}
+static int mac_func_en_be(struct rtw89_dev *rtwdev)
+{
+ u32 val;
+ int ret;
+
+ ret = dmac_func_en_be(rtwdev);
+ if (ret)
+ return ret;
+
+ ret = cmac_share_func_en_be(rtwdev);
+ if (ret)
+ return ret;
+
+ val = rtw89_read32(rtwdev, R_BE_FEN_RST_ENABLE);
+ if (val & B_BE_CMAC0_FEN) {
+ ret = cmac_pwr_en_be(rtwdev, RTW89_MAC_0, true);
+ if (ret)
+ return ret;
+
+ ret = cmac_func_en_be(rtwdev, RTW89_MAC_0, true);
+ if (ret)
+ return ret;
+ }
+
+ if (val & B_BE_CMAC1_FEN) {
+ ret = cmac_pwr_en_be(rtwdev, RTW89_MAC_1, true);
+ if (ret)
+ return ret;
+
+ ret = cmac_func_en_be(rtwdev, RTW89_MAC_1, true);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
static int sta_sch_init_be(struct rtw89_dev *rtwdev)
{
u32 p_val;
int ret;
+ if (rtwdev->chip->chip_id == RTL8922D) {
+ rtw89_write32_set(rtwdev, R_BE_SS_LITE_TXL_MACID, B_BE_RPT_OTHER_BAND_EN);
+ return 0;
+ }
+
ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL);
if (ret)
return ret;
@@ -685,14 +1001,16 @@ static int mpdu_proc_init_be(struct rtw89_dev *rtwdev)
return ret;
rtw89_write32_set(rtwdev, R_BE_MPDU_PROC, B_BE_APPEND_FCS);
- rtw89_write32(rtwdev, R_BE_CUT_AMSDU_CTRL, TRXCFG_MPDU_PROC_CUT_CTRL);
+ rtw89_write32(rtwdev, R_BE_CUT_AMSDU_CTRL, TRXCFG_MPDU_PROC_CUT_CTRL |
+ B_BE_CA_CHK_ADDRCAM_EN);
val32 = rtw89_read32(rtwdev, R_BE_HDR_SHCUT_SETTING);
val32 |= (B_BE_TX_HW_SEQ_EN | B_BE_TX_HW_ACK_POLICY_EN | B_BE_TX_MAC_MPDU_PROC_EN);
val32 &= ~B_BE_TX_ADDR_MLD_TO_LIK;
rtw89_write32_set(rtwdev, R_BE_HDR_SHCUT_SETTING, val32);
- rtw89_write32(rtwdev, R_BE_RX_HDRTRNS, TRXCFG_MPDU_PROC_RX_HDR_CONV);
+ rtw89_write32(rtwdev, R_BE_RX_HDRTRNS, TRXCFG_MPDU_PROC_RX_HDR_CONV |
+ B_BE_HC_ADDR_HIT_EN);
val32 = rtw89_read32(rtwdev, R_BE_DISP_FWD_WLAN_0);
val32 = u32_replace_bits(val32, 1, B_BE_FWD_WLAN_CPU_TYPE_0_DATA_MASK);
@@ -728,7 +1046,10 @@ static int sec_eng_init_be(struct rtw89_dev *rtwdev)
static int txpktctrl_init_be(struct rtw89_dev *rtwdev)
{
+ struct rtw89_mac_info *mac = &rtwdev->mac;
struct rtw89_mac_dle_rsvd_qt_cfg qt_cfg;
+ const struct rtw89_dle_input *dle_input;
+ u32 mpdu_info_b1_ofst;
u32 val32;
int ret;
@@ -739,9 +1060,16 @@ static int txpktctrl_init_be(struct rtw89_dev *rtwdev)
return ret;
}
+ dle_input = mac->dle_info.dle_input;
+ if (dle_input)
+ mpdu_info_b1_ofst = DIV_ROUND_UP(dle_input->mpdu_info_tbl_b0,
+ BIT(MPDU_INFO_TBL_FACTOR));
+ else
+ mpdu_info_b1_ofst = MPDU_INFO_B1_OFST;
+
val32 = rtw89_read32(rtwdev, R_BE_TXPKTCTL_MPDUINFO_CFG);
val32 = u32_replace_bits(val32, qt_cfg.pktid, B_BE_MPDUINFO_PKTID_MASK);
- val32 = u32_replace_bits(val32, MPDU_INFO_B1_OFST, B_BE_MPDUINFO_B1_BADDR_MASK);
+ val32 = u32_replace_bits(val32, mpdu_info_b1_ofst, B_BE_MPDUINFO_B1_BADDR_MASK);
val32 |= B_BE_MPDUINFO_FEN;
rtw89_write32(rtwdev, R_BE_TXPKTCTL_MPDUINFO_CFG, val32);
@@ -750,7 +1078,9 @@ static int txpktctrl_init_be(struct rtw89_dev *rtwdev)
static int mlo_init_be(struct rtw89_dev *rtwdev)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
u32 val32;
+ u32 reg;
int ret;
val32 = rtw89_read32(rtwdev, R_BE_MLO_INIT_CTL);
@@ -766,7 +1096,12 @@ static int mlo_init_be(struct rtw89_dev *rtwdev)
if (ret)
rtw89_err(rtwdev, "[MLO]%s: MLO init polling timeout\n", __func__);
- rtw89_write32_set(rtwdev, R_BE_SS_CTRL, B_BE_MLO_HW_CHGLINK_EN);
+ if (chip->chip_id == RTL8922A)
+ reg = R_BE_SS_CTRL;
+ else
+ reg = R_BE_SS_CTRL_V1;
+
+ rtw89_write32_set(rtwdev, reg, B_BE_MLO_HW_CHGLINK_EN);
rtw89_write32_set(rtwdev, R_BE_CMAC_SHARE_ACQCHK_CFG_0, B_BE_R_MACID_ACQ_CHK_EN);
return ret;
@@ -829,6 +1164,7 @@ static int dmac_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
static int scheduler_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
u32 val32;
u32 reg;
int ret;
@@ -837,6 +1173,11 @@ static int scheduler_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
if (ret)
return ret;
+ if (chip->chip_id == RTL8922D) {
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_SCH_EXT_CTRL, mac_idx);
+ rtw89_write32_set(rtwdev, reg, B_BE_CWCNT_PLUS_MODE);
+ }
+
reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_HE_CTN_CHK_CCA_NAV, mac_idx);
val32 = B_BE_HE_CTN_CHK_CCA_P20 | B_BE_HE_CTN_CHK_EDCCA_P20 |
B_BE_HE_CTN_CHK_CCA_BITMAP | B_BE_HE_CTN_CHK_EDCCA_BITMAP |
@@ -870,6 +1211,11 @@ static int scheduler_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
rtw89_write32_mask(rtwdev, reg, B_BE_BCNQ_CW_MASK, 0x32);
rtw89_write32_mask(rtwdev, reg, B_BE_BCNQ_AIFS_MASK, BCN_IFS_25US);
+ if (chip->chip_id == RTL8922D) {
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_SCH_EDCA_RST_CFG, mac_idx);
+ rtw89_write32_set(rtwdev, reg, B_BE_TX_NAV_RST_EDCA_EN);
+ }
+
return 0;
}
@@ -985,6 +1331,12 @@ static int nav_ctrl_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
rtw89_write32(rtwdev, reg, val32);
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_SPECIAL_TX_SETTING, mac_idx);
+ rtw89_write32_clr(rtwdev, reg, B_BE_BMC_NAV_PROTECT);
+
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TRXPTCL_RESP_0, mac_idx);
+ rtw89_write32_set(rtwdev, reg, B_BE_WMAC_MBA_DUR_FORCE);
+
return 0;
}
@@ -1008,14 +1360,23 @@ static int spatial_reuse_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
static int tmac_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ struct rtw89_hal *hal = &rtwdev->hal;
u32 reg;
reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TB_PPDU_CTRL, mac_idx);
rtw89_write32_clr(rtwdev, reg, B_BE_QOSNULL_UPD_MUEDCA_EN);
- reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_WMTX_TCR_BE_4, mac_idx);
- rtw89_write32_mask(rtwdev, reg, B_BE_EHT_HE_PPDU_4XLTF_ZLD_USTIMER_MASK, 0x12);
- rtw89_write32_mask(rtwdev, reg, B_BE_EHT_HE_PPDU_2XLTF_ZLD_USTIMER_MASK, 0xe);
+ if (chip->chip_id == RTL8922A) {
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_WMTX_TCR_BE_4, mac_idx);
+ rtw89_write32_mask(rtwdev, reg, B_BE_EHT_HE_PPDU_4XLTF_ZLD_USTIMER_MASK, 0x12);
+ rtw89_write32_mask(rtwdev, reg, B_BE_EHT_HE_PPDU_2XLTF_ZLD_USTIMER_MASK, 0xe);
+ }
+
+ if (chip->chip_id == RTL8922D && hal->cid != RTL8922D_CID7090) {
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_COMMON_PHYINTF_CTRL_0, mac_idx);
+ rtw89_write32_clr(rtwdev, reg, CLEAR_DTOP_DIS);
+ }
return 0;
}
@@ -1040,6 +1401,15 @@ static int trxptcl_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
val32 &= ~B_BE_MACLBK_EN;
rtw89_write32(rtwdev, reg, val32);
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_CMAC_FUNC_EN, mac_idx);
+ rtw89_write32_set(rtwdev, reg, B_BE_PHYINTF_EN);
+
+ if (chip->chip_id == RTL8922D) {
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_RX_PLCP_EXT_OPTION_2, mac_idx);
+ rtw89_write32_set(rtwdev, reg, B_BE_PLCP_PHASE_B_CRC_CHK_EN |
+ B_BE_PLCP_PHASE_A_CRC_CHK_EN);
+ }
+
reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TRXPTCL_RESP_0, mac_idx);
val32 = rtw89_read32(rtwdev, reg);
val32 = u32_replace_bits(val32, WMAC_SPEC_SIFS_CCK,
@@ -1109,6 +1479,7 @@ static int rst_bacam_be(struct rtw89_dev *rtwdev)
static int rmac_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
u32 rx_min_qta, rx_max_len, rx_max_pg;
u16 val16;
u32 reg;
@@ -1152,6 +1523,17 @@ static int rmac_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_RX_PLCP_EXT_OPTION_1, mac_idx);
rtw89_write16_set(rtwdev, reg, B_BE_PLCP_SU_PSDU_LEN_SRC);
+ if (chip->chip_id == RTL8922D) {
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_BSR_UPD_CTRL, mac_idx);
+ rtw89_write32_set(rtwdev, reg, B_BE_QSIZE_RULE);
+
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_RXGCK_CTRL, mac_idx);
+ rtw89_write16_mask(rtwdev, reg, B_BE_RXGCK_GCK_RATE_LIMIT_MASK, RX_GCK_LEGACY);
+
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_PLCP_HDR_FLTR, mac_idx);
+ rtw89_write32_set(rtwdev, reg, B_BE_DIS_CHK_MIN_LEN);
+ }
+
return 0;
}
@@ -1175,7 +1557,7 @@ static int resp_pktctl_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_RESP_CSI_RESERVED_PAGE, mac_idx);
rtw89_write32_mask(rtwdev, reg, B_BE_CSI_RESERVED_START_PAGE_MASK, qt_cfg.pktid);
- rtw89_write32_mask(rtwdev, reg, B_BE_CSI_RESERVED_PAGE_NUM_MASK, qt_cfg.pg_num);
+ rtw89_write32_mask(rtwdev, reg, B_BE_CSI_RESERVED_PAGE_NUM_MASK, qt_cfg.pg_num + 1);
return 0;
}
@@ -1210,6 +1592,7 @@ static int cmac_com_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
static int ptcl_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
u32 val32;
u8 val8;
u32 reg;
@@ -1224,8 +1607,9 @@ static int ptcl_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
val32 = rtw89_read32(rtwdev, reg);
val32 = u32_replace_bits(val32, S_AX_CTS2S_TH_1K,
B_BE_HW_CTS2SELF_PKT_LEN_TH_MASK);
- val32 = u32_replace_bits(val32, S_AX_CTS2S_TH_SEC_256B,
- B_BE_HW_CTS2SELF_PKT_LEN_TH_TWW_MASK);
+ if (chip->chip_id == RTL8922A)
+ val32 = u32_replace_bits(val32, S_AX_CTS2S_TH_SEC_256B,
+ B_BE_HW_CTS2SELF_PKT_LEN_TH_TWW_MASK);
val32 |= B_BE_HW_CTS2SELF_EN;
rtw89_write32(rtwdev, reg, val32);
@@ -1246,7 +1630,46 @@ static int ptcl_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
rtw89_write8(rtwdev, reg, val8);
reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_AMPDU_AGG_LIMIT, mac_idx);
- rtw89_write32_mask(rtwdev, reg, B_BE_AMPDU_MAX_TIME_MASK, AMPDU_MAX_TIME);
+ if (chip->chip_id == RTL8922A)
+ val32 = AMPDU_MAX_TIME;
+ else
+ val32 = AMPDU_MAX_TIME_V1;
+ rtw89_write32_mask(rtwdev, reg, B_BE_AMPDU_MAX_TIME_MASK, val32);
+
+ if (chip->chip_id == RTL8922D) {
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_AGG_BK_0, mac_idx);
+ rtw89_write32_clr(rtwdev, reg, B_BE_WDBK_CFG | B_BE_EN_RTY_BK |
+ B_BE_EN_RTY_BK_COD);
+
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_AMPDU_AGG_LIMIT, mac_idx);
+ rtw89_write32_mask(rtwdev, reg, B_BE_MAX_AGG_NUM_MASK,
+ MAX_TX_AMPDU_NUM_V1 - 1);
+ }
+
+ if (rtw89_mac_chk_preload_allow(rtwdev)) {
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_AGG_BK_0, mac_idx);
+ rtw89_write32_set(rtwdev, reg, B_BE_PRELD_MGQ0_EN |
+ B_BE_PRELD_HIQ_P4_EN |
+ B_BE_PRELD_HIQ_P3_EN |
+ B_BE_PRELD_HIQ_P2_EN |
+ B_BE_PRELD_HIQ_P1_EN |
+ B_BE_PRELD_HIQ_P0MB15_EN |
+ B_BE_PRELD_HIQ_P0MB14_EN |
+ B_BE_PRELD_HIQ_P0MB13_EN |
+ B_BE_PRELD_HIQ_P0MB12_EN |
+ B_BE_PRELD_HIQ_P0MB11_EN |
+ B_BE_PRELD_HIQ_P0MB10_EN |
+ B_BE_PRELD_HIQ_P0MB9_EN |
+ B_BE_PRELD_HIQ_P0MB8_EN |
+ B_BE_PRELD_HIQ_P0MB7_EN |
+ B_BE_PRELD_HIQ_P0MB6_EN |
+ B_BE_PRELD_HIQ_P0MB5_EN |
+ B_BE_PRELD_HIQ_P0MB4_EN |
+ B_BE_PRELD_HIQ_P0MB3_EN |
+ B_BE_PRELD_HIQ_P0MB2_EN |
+ B_BE_PRELD_HIQ_P0MB1_EN |
+ B_BE_PRELD_HIQ_P0_EN);
+ }
return 0;
}
@@ -1533,22 +1956,22 @@ static int dle_quota_change_be(struct rtw89_dev *rtwdev, bool band1_en)
static int preload_init_be(struct rtw89_dev *rtwdev, u8 mac_idx,
enum rtw89_qta_mode mode)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
u32 max_preld_size, min_rsvd_size;
+ u8 preld_acq, preld_miscq;
u32 val32;
u32 reg;
+ if (!(chip->chip_id == RTL8922A || rtw89_mac_chk_preload_allow(rtwdev)))
+ return 0;
+
max_preld_size = mac_idx == RTW89_MAC_0 ?
PRELD_B0_ENT_NUM : PRELD_B1_ENT_NUM;
+ if (chip->chip_id == RTL8922D)
+ max_preld_size = PRELD_B01_ENT_NUM_8922D;
max_preld_size *= PRELD_AMSDU_SIZE;
+ min_rsvd_size = PRELD_NEXT_MIN_SIZE;
- reg = mac_idx == RTW89_MAC_0 ? R_BE_TXPKTCTL_B0_PRELD_CFG0 :
- R_BE_TXPKTCTL_B1_PRELD_CFG0;
- val32 = rtw89_read32(rtwdev, reg);
- val32 = u32_replace_bits(val32, max_preld_size, B_BE_B0_PRELD_USEMAXSZ_MASK);
- val32 |= B_BE_B0_PRELD_FEN;
- rtw89_write32(rtwdev, reg, val32);
-
- min_rsvd_size = PRELD_AMSDU_SIZE;
reg = mac_idx == RTW89_MAC_0 ? R_BE_TXPKTCTL_B0_PRELD_CFG1 :
R_BE_TXPKTCTL_B1_PRELD_CFG1;
val32 = rtw89_read32(rtwdev, reg);
@@ -1556,9 +1979,36 @@ static int preload_init_be(struct rtw89_dev *rtwdev, u8 mac_idx,
val32 = u32_replace_bits(val32, min_rsvd_size, B_BE_B0_PRELD_NXT_RSVMINSZ_MASK);
rtw89_write32(rtwdev, reg, val32);
+ reg = mac_idx == RTW89_MAC_0 ? R_BE_TXPKTCTL_B0_PRELD_CFG0 :
+ R_BE_TXPKTCTL_B1_PRELD_CFG0;
+ if (chip->chip_id == RTL8922D) {
+ preld_acq = PRELD_ACQ_ENT_NUM_8922D;
+ preld_miscq = PRELD_MISCQ_ENT_NUM_8922D;
+ } else {
+ preld_acq = mac_idx == RTW89_MAC_0 ? PRELD_B0_ACQ_ENT_NUM_8922A :
+ PRELD_B1_ACQ_ENT_NUM_8922A;
+ preld_miscq = PRELD_MISCQ_ENT_NUM_8922A;
+ }
+
+ val32 = rtw89_read32(rtwdev, reg);
+ val32 = u32_replace_bits(val32, preld_acq, B_BE_B0_PRELD_CAM_G0ENTNUM_MASK);
+ val32 = u32_replace_bits(val32, preld_miscq, B_BE_B0_PRELD_CAM_G1ENTNUM_MASK);
+ val32 = u32_replace_bits(val32, max_preld_size, B_BE_B0_PRELD_USEMAXSZ_MASK);
+ val32 |= B_BE_B0_PRELD_FEN;
+ rtw89_write32(rtwdev, reg, val32);
+
return 0;
}
+static void clr_aon_intr_be(struct rtw89_dev *rtwdev)
+{
+ if (rtwdev->hci.type != RTW89_HCI_TYPE_PCIE)
+ return;
+
+ rtw89_write32_clr(rtwdev, R_BE_FWS0IMR, B_BE_FS_GPIOA_INT_EN);
+ rtw89_write32_set(rtwdev, R_BE_FWS0ISR, B_BE_FS_GPIOA_INT);
+}
+
static int dbcc_bb_ctrl_be(struct rtw89_dev *rtwdev, bool bb1_en)
{
u32 set = B_BE_FEN_BB1PLAT_RSTB | B_BE_FEN_BB1_IP_RSTN;
@@ -1588,6 +2038,10 @@ static int enable_imr_be(struct rtw89_dev *rtwdev, u8 mac_idx,
else
return -EINVAL;
+ if (chip->chip_id == RTL8922D)
+ rtw89_write32_mask(rtwdev, R_BE_NO_RX_ERR_CFG,
+ B_BE_NO_RX_ERR_TO_MASK, 0);
+
for (i = 0; i < table->n_regs; i++) {
reg = &table->regs[i];
addr = rtw89_mac_reg_by_idx(rtwdev, reg->addr, mac_idx);
@@ -1638,6 +2092,12 @@ static int band1_enable_be(struct rtw89_dev *rtwdev)
return ret;
}
+ ret = cmac_pwr_en_be(rtwdev, RTW89_MAC_1, true);
+ if (ret) {
+ rtw89_err(rtwdev, "[ERR]CMAC%d pwr en %d\n", RTW89_MAC_1, ret);
+ return ret;
+ }
+
ret = cmac_func_en_be(rtwdev, RTW89_MAC_1, true);
if (ret) {
rtw89_err(rtwdev, "[ERR]CMAC%d func en %d\n", RTW89_MAC_1, ret);
@@ -1681,6 +2141,12 @@ static int band1_disable_be(struct rtw89_dev *rtwdev)
return ret;
}
+ ret = cmac_pwr_en_be(rtwdev, RTW89_MAC_1, false);
+ if (ret) {
+ rtw89_err(rtwdev, "[ERR]CMAC%d pwr dis %d\n", RTW89_MAC_1, ret);
+ return ret;
+ }
+
ret = rtw89_mac_dle_quota_change(rtwdev, rtwdev->mac.qta_mode, false);
if (ret) {
rtw89_err(rtwdev, "[ERR]DLE quota change %d\n", ret);
@@ -1731,26 +2197,40 @@ static int dbcc_enable_be(struct rtw89_dev *rtwdev, bool enable)
static int set_host_rpr_be(struct rtw89_dev *rtwdev)
{
+ enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
u32 val32;
u32 mode;
u32 fltr;
+ u32 qid;
bool poh;
poh = is_qta_poh(rtwdev);
if (poh) {
mode = RTW89_RPR_MODE_POH;
- fltr = S_BE_WDRLS_FLTR_TXOK | S_BE_WDRLS_FLTR_RTYLMT |
- S_BE_WDRLS_FLTR_LIFTIM | S_BE_WDRLS_FLTR_MACID;
+ qid = WDRLS_DEST_QID_POH;
} else {
mode = RTW89_RPR_MODE_STF;
fltr = 0;
+ qid = WDRLS_DEST_QID_STF;
+ }
+
+ if (chip_id == RTL8922A) {
+ fltr = S_BE_WDRLS_FLTR_TXOK | S_BE_WDRLS_FLTR_RTYLMT |
+ S_BE_WDRLS_FLTR_LIFTIM | S_BE_WDRLS_FLTR_MACID;
+ } else {
+ fltr = S_BE_WDRLS_FLTR_TXOK_V1 | S_BE_WDRLS_FLTR_RTYLMT_V1 |
+ S_BE_WDRLS_FLTR_LIFTIM_V1 | S_BE_WDRLS_FLTR_MACID_V1;
}
rtw89_write32_mask(rtwdev, R_BE_WDRLS_CFG, B_BE_WDRLS_MODE_MASK, mode);
+ rtw89_write32_mask(rtwdev, R_BE_RLSRPT0_CFG0, B_BE_RLSRPT0_QID_MASK, qid);
val32 = rtw89_read32(rtwdev, R_BE_RLSRPT0_CFG1);
- val32 = u32_replace_bits(val32, fltr, B_BE_RLSRPT0_FLTR_MAP_MASK);
+ if (chip_id == RTL8922A)
+ val32 = u32_replace_bits(val32, fltr, B_BE_RLSRPT0_FLTR_MAP_MASK);
+ else
+ val32 = u32_replace_bits(val32, fltr, B_BE_RLSRPT0_FLTR_MAP_V1_MASK);
val32 = u32_replace_bits(val32, 30, B_BE_RLSRPT0_AGGNUM_MASK);
val32 = u32_replace_bits(val32, 255, B_BE_RLSRPT0_TO_MASK);
rtw89_write32(rtwdev, R_BE_RLSRPT0_CFG1, val32);
@@ -1863,12 +2343,65 @@ int rtw89_mac_cfg_gnt_v2(struct rtw89_dev *rtwdev,
}
EXPORT_SYMBOL(rtw89_mac_cfg_gnt_v2);
+int rtw89_mac_cfg_gnt_v3(struct rtw89_dev *rtwdev,
+ const struct rtw89_mac_ax_coex_gnt *gnt_cfg)
+{
+ u32 val = 0;
+
+ if (gnt_cfg->band[0].gnt_bt)
+ val |= B_BE_PTA_GNT_BT0_BB_VAL | B_BE_PTA_GNT_BT0_RX_BB0_VAL |
+ B_BE_PTA_GNT_BT0_TX_BB0_VAL;
+
+ if (gnt_cfg->band[0].gnt_bt_sw_en)
+ val |= B_BE_PTA_GNT_BT0_BB_SWCTRL | B_BE_PTA_GNT_BT0_RX_BB0_SWCTRL |
+ B_BE_PTA_GNT_BT0_TX_BB0_SWCTRL;
+
+ if (gnt_cfg->band[0].gnt_wl)
+ val |= B_BE_PTA_GNT_WL_BB0_VAL;
+
+ if (gnt_cfg->band[0].gnt_wl_sw_en)
+ val |= B_BE_PTA_GNT_WL_BB0_SWCTRL;
+
+ if (gnt_cfg->band[1].gnt_bt)
+ val |= B_BE_PTA_GNT_BT0_BB_VAL | B_BE_PTA_GNT_BT0_RX_BB1_VAL |
+ B_BE_PTA_GNT_BT0_TX_BB1_VAL;
+
+ if (gnt_cfg->band[1].gnt_bt_sw_en)
+ val |= B_BE_PTA_GNT_BT0_BB_SWCTRL | B_BE_PTA_GNT_BT0_RX_BB1_SWCTRL |
+ B_BE_PTA_GNT_BT0_TX_BB1_SWCTRL;
+
+ if (gnt_cfg->band[1].gnt_wl)
+ val |= B_BE_PTA_GNT_WL_BB1_VAL;
+
+ if (gnt_cfg->band[1].gnt_wl_sw_en)
+ val |= B_BE_PTA_GNT_WL_BB1_SWCTRL;
+
+ if (gnt_cfg->bt[0].wlan_act_en)
+ val |= B_BE_PTA_WL_ACT0_SWCTRL | B_BE_PTA_WL_ACT_RX_BT0_SWCTRL |
+ B_BE_PTA_WL_ACT_TX_BT0_SWCTRL;
+ if (gnt_cfg->bt[0].wlan_act)
+ val |= B_BE_PTA_WL_ACT0_VAL | B_BE_PTA_WL_ACT_RX_BT0_VAL |
+ B_BE_PTA_WL_ACT_TX_BT0_VAL;
+ if (gnt_cfg->bt[1].wlan_act_en)
+ val |= B_BE_PTA_WL_ACT1_SWCTRL | B_BE_PTA_WL_ACT_RX_BT1_SWCTRL |
+ B_BE_PTA_WL_ACT_TX_BT1_SWCTRL;
+ if (gnt_cfg->bt[1].wlan_act)
+ val |= B_BE_PTA_WL_ACT1_VAL | B_BE_PTA_WL_ACT_RX_BT1_VAL |
+ B_BE_PTA_WL_ACT_TX_BT1_VAL;
+
+ rtw89_write32(rtwdev, R_BE_PTA_GNT_SW_CTRL, val);
+
+ return 0;
+}
+EXPORT_SYMBOL(rtw89_mac_cfg_gnt_v3);
+
int rtw89_mac_cfg_ctrl_path_v2(struct rtw89_dev *rtwdev, bool wl)
{
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_dm *dm = &btc->dm;
struct rtw89_mac_ax_gnt *g = dm->gnt.band;
struct rtw89_mac_ax_wl_act *gbt = dm->gnt.bt;
+ const struct rtw89_chip_info *chip = rtwdev->chip;
int i;
if (wl)
@@ -1883,7 +2416,11 @@ int rtw89_mac_cfg_ctrl_path_v2(struct rtw89_dev *rtwdev, bool wl)
gbt[i].wlan_act_en = 0;
}
- return rtw89_mac_cfg_gnt_v2(rtwdev, &dm->gnt);
+ if (chip->chip_id == RTL8922A)
+ return rtw89_mac_cfg_gnt_v2(rtwdev, &dm->gnt);
+ else
+ return rtw89_mac_cfg_gnt_v3(rtwdev, &dm->gnt);
+
}
EXPORT_SYMBOL(rtw89_mac_cfg_ctrl_path_v2);
@@ -2012,6 +2549,65 @@ void rtw89_mac_cfg_phy_rpt_be(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable)
EXPORT_SYMBOL(rtw89_mac_cfg_phy_rpt_be);
static
+void rtw89_mac_set_edcca_mode_be(struct rtw89_dev *rtwdev, u8 mac_idx, bool normal)
+{
+ u16 resp_ack, resp_rts, resp_rts_punc, resp_normal, resp_normal_punc;
+
+ if (rtwdev->chip->chip_id == RTL8922A)
+ return;
+
+ resp_ack = RESP_ACK_CFG_BE;
+ resp_rts = RESP_RTS_CFG_BE;
+ resp_rts_punc = RESP_RTS_PUNC_CFG_BE;
+ resp_normal = RESP_NORMAL_CFG_BE;
+ resp_normal_punc = RESP_NORMAL_PUNC_CFG_BE;
+
+ if (normal) {
+ rtw89_write16_idx(rtwdev, R_BE_WMAC_ACK_BA_RESP_LEGACY,
+ resp_ack, mac_idx);
+ rtw89_write16_idx(rtwdev, R_BE_WMAC_ACK_BA_RESP_HE,
+ resp_ack, mac_idx);
+ rtw89_write16_idx(rtwdev, R_BE_WMAC_ACK_BA_RESP_EHT_LEG_PUNC,
+ resp_ack, mac_idx);
+ rtw89_write16_idx(rtwdev, R_BE_WMAC_RX_RTS_RESP_LEGACY,
+ resp_rts, mac_idx);
+ rtw89_write16_idx(rtwdev, R_BE_WMAC_RX_RTS_RESP_LEGACY_PUNC,
+ resp_rts_punc, mac_idx);
+ rtw89_write16_idx(rtwdev, R_BE_WMAC_RX_MURTS_RESP_LEGACY,
+ resp_normal, mac_idx);
+ rtw89_write16_idx(rtwdev, R_BE_WMAC_RX_MURTS_RESP_LEGACY_PUNC,
+ resp_normal_punc, mac_idx);
+ rtw89_write16_idx(rtwdev, R_BE_WMAC_OTHERS_RESP_LEGACY,
+ resp_normal, mac_idx);
+ rtw89_write16_idx(rtwdev, R_BE_WMAC_OTHERS_RESP_HE,
+ resp_normal_punc, mac_idx);
+ rtw89_write16_idx(rtwdev, R_BE_WMAC_OTHERS_RESP_EHT_LEG_PUNC,
+ resp_normal_punc, mac_idx);
+ } else {
+ rtw89_write16_idx(rtwdev, R_BE_WMAC_ACK_BA_RESP_LEGACY,
+ resp_normal, mac_idx);
+ rtw89_write16_idx(rtwdev, R_BE_WMAC_ACK_BA_RESP_HE,
+ resp_normal_punc, mac_idx);
+ rtw89_write16_idx(rtwdev, R_BE_WMAC_ACK_BA_RESP_EHT_LEG_PUNC,
+ resp_normal_punc, mac_idx);
+ rtw89_write16_idx(rtwdev, R_BE_WMAC_RX_RTS_RESP_LEGACY,
+ resp_rts, mac_idx);
+ rtw89_write16_idx(rtwdev, R_BE_WMAC_RX_RTS_RESP_LEGACY_PUNC,
+ resp_rts_punc, mac_idx);
+ rtw89_write16_idx(rtwdev, R_BE_WMAC_RX_MURTS_RESP_LEGACY,
+ resp_normal, mac_idx);
+ rtw89_write16_idx(rtwdev, R_BE_WMAC_RX_MURTS_RESP_LEGACY_PUNC,
+ resp_normal_punc, mac_idx);
+ rtw89_write16_idx(rtwdev, R_BE_WMAC_OTHERS_RESP_LEGACY,
+ resp_normal, mac_idx);
+ rtw89_write16_idx(rtwdev, R_BE_WMAC_OTHERS_RESP_HE,
+ resp_normal_punc, mac_idx);
+ rtw89_write16_idx(rtwdev, R_BE_WMAC_OTHERS_RESP_EHT_LEG_PUNC,
+ resp_normal_punc, mac_idx);
+ }
+}
+
+static
int rtw89_mac_cfg_ppdu_status_be(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable)
{
u32 reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_PPDU_STAT, mac_idx);
@@ -2580,6 +3176,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = {
.port_base = &rtw89_port_base_be,
.agg_len_ht = R_BE_AGG_LEN_HT_0,
.ps_status = R_BE_WMTX_POWER_BE_BIT_CTL,
+ .mu_gid = &rtw89_mac_mu_gid_addr_be,
.muedca_ctrl = {
.addr = R_BE_MUEDCA_EN,
@@ -2601,6 +3198,10 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = {
.check_mac_en = rtw89_mac_check_mac_en_be,
.sys_init = sys_init_be,
.trx_init = trx_init_be,
+ .preload_init = preload_init_be,
+ .clr_aon_intr = clr_aon_intr_be,
+ .err_imr_ctrl = err_imr_ctrl_be,
+ .mac_func_en = mac_func_en_be,
.hci_func_en = rtw89_mac_hci_func_en_be,
.dmac_func_pre_en = rtw89_mac_dmac_func_pre_en_be,
.dle_func_en = dle_func_en_be,
@@ -2610,6 +3211,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = {
.typ_fltr_opt = rtw89_mac_typ_fltr_opt_be,
.cfg_ppdu_status = rtw89_mac_cfg_ppdu_status_be,
.cfg_phy_rpt = rtw89_mac_cfg_phy_rpt_be,
+ .set_edcca_mode = rtw89_mac_set_edcca_mode_be,
.dle_mix_cfg = dle_mix_cfg_be,
.chk_dle_rdy = chk_dle_rdy_be,
@@ -2623,6 +3225,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = {
.set_cpuio = set_cpuio_be,
.dle_quota_change = dle_quota_change_be,
+ .reset_pwr_state = rtw89_mac_reset_pwr_state_be,
.disable_cpu = rtw89_mac_disable_cpu_be,
.fwdl_enable_wcpu = rtw89_mac_fwdl_enable_wcpu_be,
.fwdl_get_status = fwdl_get_status_be,
@@ -2632,6 +3235,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = {
.parse_phycap_map = rtw89_parse_phycap_map_be,
.cnv_efuse_state = rtw89_cnv_efuse_state_be,
.efuse_read_fw_secure = rtw89_efuse_read_fw_secure_be,
+ .efuse_read_ecv = rtw89_efuse_read_ecv_be,
.cfg_plt = rtw89_mac_cfg_plt_be,
.get_plt_cnt = rtw89_mac_get_plt_cnt_be,
diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c
index a66fcdb0293b..43c61b3dc969 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.c
+++ b/drivers/net/wireless/realtek/rtw89/pci.c
@@ -604,8 +604,15 @@ static void rtw89_pci_release_rpp(struct rtw89_dev *rtwdev, void *rpp)
info->parse_rpp(rtwdev, rpp, &rpp_info);
- if (rpp_info.txch == RTW89_TXCH_CH12) {
- rtw89_warn(rtwdev, "should no fwcmd release report\n");
+ if (unlikely(rpp_info.txch >= RTW89_TXCH_NUM ||
+ info->tx_dma_ch_mask & BIT(rpp_info.txch))) {
+ rtw89_warn(rtwdev, "should no release report on txch %d\n",
+ rpp_info.txch);
+ return;
+ }
+
+ if (unlikely(rpp_info.seq >= RTW89_PCI_TXWD_NUM_MAX)) {
+ rtw89_warn(rtwdev, "invalid seq %d\n", rpp_info.seq);
return;
}
@@ -963,6 +970,9 @@ static irqreturn_t rtw89_pci_interrupt_threadfn(int irq, void *dev)
if (unlikely(isrs.halt_c2h_isrs & isr_def->isr_wdt_timeout))
rtw89_ser_notify(rtwdev, MAC_AX_ERR_L2_ERR_WDT_TIMEOUT_INT);
+ if (unlikely(isrs.halt_c2h_isrs & isr_def->isr_sps_ocp))
+ rtw89_warn(rtwdev, "SPS OCP alarm 0x%x\n", isrs.halt_c2h_isrs);
+
if (unlikely(rtwpci->under_recovery))
goto enable_intr;
@@ -3998,7 +4008,8 @@ static void rtw89_pci_recovery_intr_mask_v3(struct rtw89_dev *rtwdev)
struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
rtwpci->ind_intrs = B_BE_HS0_IND_INT_EN0;
- rtwpci->halt_c2h_intrs = B_BE_HALT_C2H_INT_EN | B_BE_WDT_TIMEOUT_INT_EN;
+ rtwpci->halt_c2h_intrs = B_BE_HALT_C2H_INT_EN | B_BE_WDT_TIMEOUT_INT_EN |
+ B_BE_SPSANA_OCP_INT_EN | B_BE_SPS_OCP_INT_EN;
rtwpci->intrs[0] = 0;
rtwpci->intrs[1] = 0;
}
@@ -4008,7 +4019,8 @@ static void rtw89_pci_default_intr_mask_v3(struct rtw89_dev *rtwdev)
struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
rtwpci->ind_intrs = B_BE_HS0_IND_INT_EN0;
- rtwpci->halt_c2h_intrs = B_BE_HALT_C2H_INT_EN | B_BE_WDT_TIMEOUT_INT_EN;
+ rtwpci->halt_c2h_intrs = B_BE_HALT_C2H_INT_EN | B_BE_WDT_TIMEOUT_INT_EN |
+ B_BE_SPSANA_OCP_INT_EN | B_BE_SPS_OCP_INT_EN;
rtwpci->intrs[0] = 0;
rtwpci->intrs[1] = B_BE_PCIE_RDU_CH1_IMR |
B_BE_PCIE_RDU_CH0_IMR |
@@ -4598,6 +4610,7 @@ static int __maybe_unused rtw89_pci_resume(struct device *dev)
rtw89_write32_clr(rtwdev, R_AX_PCIE_PS_CTRL_V1,
B_AX_SEL_REQ_ENTR_L1);
}
+ rtw89_pci_hci_ldo(rtwdev);
rtw89_pci_l2_hci_ldo(rtwdev);
rtw89_pci_basic_cfg(rtwdev, true);
@@ -4649,6 +4662,7 @@ const struct rtw89_pci_isr_def rtw89_pci_isr_ax = {
.isr_rdu = B_AX_RDU_INT,
.isr_halt_c2h = B_AX_HALT_C2H_INT_EN,
.isr_wdt_timeout = B_AX_WDT_TIMEOUT_INT_EN,
+ .isr_sps_ocp = 0,
.isr_clear_rpq = {R_AX_PCIE_HISR00, B_AX_RPQDMA_INT | B_AX_RPQBD_FULL_INT},
.isr_clear_rxq = {R_AX_PCIE_HISR00, B_AX_RXP1DMA_INT | B_AX_RXDMA_INT |
B_AX_RDU_INT},
diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h
index 16dfb0e79d77..ccfa6d33623a 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.h
+++ b/drivers/net/wireless/realtek/rtw89/pci.h
@@ -55,6 +55,8 @@
#define B_AX_CALIB_EN BIT(13)
#define B_AX_DIV GENMASK(15, 14)
#define RAC_SET_PPR_V1 0x31
+#define RAC_ANA41 0x41
+#define PHY_ERR_FLAG_EN BIT(6)
#define R_AX_DBI_FLAG 0x1090
#define B_AX_DBI_RFLAG BIT(17)
@@ -145,6 +147,11 @@
#define R_RAC_DIRECT_OFFSET_BE_LANE0_G2 0x3900
#define R_RAC_DIRECT_OFFSET_BE_LANE1_G2 0x3980
+#define RAC_DIRECT_OFFESET_L0_G1 0x3800
+#define RAC_DIRECT_OFFESET_L1_G1 0x3900
+#define RAC_DIRECT_OFFESET_L0_G2 0x3A00
+#define RAC_DIRECT_OFFESET_L1_G2 0x3B00
+
#define RTW89_PCI_WR_RETRY_CNT 20
/* Interrupts */
@@ -296,6 +303,10 @@
#define B_BE_PCIE_EN_AUX_CLK BIT(0)
#define R_BE_PCIE_PS_CTRL 0x3008
+#define B_BE_ASPM_L11_EN BIT(19)
+#define B_BE_ASPM_L12_EN BIT(18)
+#define B_BE_PCIPM_L11_EN BIT(17)
+#define B_BE_PCIPM_L12_EN BIT(16)
#define B_BE_RSM_L0S_EN BIT(8)
#define B_BE_CMAC_EXIT_L1_EN BIT(7)
#define B_BE_DMAC0_EXIT_L1_EN BIT(6)
@@ -767,31 +778,6 @@
#define R_AX_WP_ADDR_H_SEL8_11 0x133C
#define R_AX_WP_ADDR_H_SEL12_15 0x1340
-#define R_BE_HAXI_DMA_STOP1 0xB010
-#define B_BE_STOP_WPDMA BIT(31)
-#define B_BE_STOP_CH14 BIT(14)
-#define B_BE_STOP_CH13 BIT(13)
-#define B_BE_STOP_CH12 BIT(12)
-#define B_BE_STOP_CH11 BIT(11)
-#define B_BE_STOP_CH10 BIT(10)
-#define B_BE_STOP_CH9 BIT(9)
-#define B_BE_STOP_CH8 BIT(8)
-#define B_BE_STOP_CH7 BIT(7)
-#define B_BE_STOP_CH6 BIT(6)
-#define B_BE_STOP_CH5 BIT(5)
-#define B_BE_STOP_CH4 BIT(4)
-#define B_BE_STOP_CH3 BIT(3)
-#define B_BE_STOP_CH2 BIT(2)
-#define B_BE_STOP_CH1 BIT(1)
-#define B_BE_STOP_CH0 BIT(0)
-#define B_BE_TX_STOP1_MASK (B_BE_STOP_CH0 | B_BE_STOP_CH1 | \
- B_BE_STOP_CH2 | B_BE_STOP_CH3 | \
- B_BE_STOP_CH4 | B_BE_STOP_CH5 | \
- B_BE_STOP_CH6 | B_BE_STOP_CH7 | \
- B_BE_STOP_CH8 | B_BE_STOP_CH9 | \
- B_BE_STOP_CH10 | B_BE_STOP_CH11 | \
- B_BE_STOP_CH12)
-
#define R_BE_CH0_TXBD_NUM_V1 0xB030
#define R_BE_CH1_TXBD_NUM_V1 0xB032
#define R_BE_CH2_TXBD_NUM_V1 0xB034
@@ -974,6 +960,12 @@
#define R_BE_PCIE_CRPWM 0x30C4
#define R_BE_L1_2_CTRL_HCILDO 0x3110
+#define B_BE_PM_CLKREQ_EXT_RB BIT(11)
+#define B_BE_PCIE_DIS_RTK_PRST_N_L1_2 BIT(10)
+#define B_BE_PCIE_PRST_IN_L1_2_RB BIT(9)
+#define B_BE_PCIE_PRST_SEL_RB_V1 BIT(8)
+#define B_BE_PCIE_DIS_L2_CTRL_APHY_SUSB BIT(7)
+#define B_BE_PCIE_DIS_L1_2_CTRL_APHY_SUSB BIT(6)
#define B_BE_PCIE_DIS_L1_2_CTRL_HCILDO BIT(0)
#define R_BE_PL1_DBG_INFO 0x3120
@@ -1023,9 +1015,11 @@
#define B_BE_PL1_SER_PL1_EN BIT(31)
#define B_BE_PL1_IGNORE_HOT_RST BIT(30)
#define B_BE_PL1_TIMER_UNIT_MASK GENMASK(19, 17)
+#define PCIE_SER_TIMER_UNIT 0x2
#define B_BE_PL1_TIMER_CLEAR BIT(0)
#define R_BE_REG_PL1_MASK 0x34B0
+#define B_BE_SER_LTSSM_UNSTABLE_MASK BIT(6)
#define B_BE_SER_PCLKREQ_ACK_MASK BIT(5)
#define B_BE_SER_PM_CLK_MASK BIT(4)
#define B_BE_SER_LTSSM_IMR BIT(3)
@@ -1055,6 +1049,18 @@
#define B_BE_CLR_CH2_IDX BIT(2)
#define B_BE_CLR_CH1_IDX BIT(1)
#define B_BE_CLR_CH0_IDX BIT(0)
+#define B_BE_CLR_ALL_IDX_MASK (B_BE_CLR_CH0_IDX | B_BE_CLR_CH1_IDX | \
+ B_BE_CLR_CH2_IDX | B_BE_CLR_CH3_IDX | \
+ B_BE_CLR_CH4_IDX | B_BE_CLR_CH5_IDX | \
+ B_BE_CLR_CH6_IDX | B_BE_CLR_CH7_IDX | \
+ B_BE_CLR_CH8_IDX | B_BE_CLR_CH9_IDX | \
+ B_BE_CLR_CH10_IDX | B_BE_CLR_CH11_IDX | \
+ B_BE_CLR_CH12_IDX | B_BE_CLR_CH13_IDX | \
+ B_BE_CLR_CH14_IDX)
+#define B_BE_CLR_ALL_IDX_MASK_V1 (B_BE_CLR_CH0_IDX | B_BE_CLR_CH2_IDX | \
+ B_BE_CLR_CH4_IDX | B_BE_CLR_CH6_IDX | \
+ B_BE_CLR_CH8_IDX | B_BE_CLR_CH10_IDX | \
+ B_BE_CLR_CH12_IDX)
#define R_BE_RXBD_RWPTR_CLR1_V1 0xB018
#define B_BE_CLR_ROQ1_IDX_V1 BIT(5)
@@ -1325,6 +1331,7 @@ struct rtw89_pci_isr_def {
u32 isr_rdu;
u32 isr_halt_c2h;
u32 isr_wdt_timeout;
+ u32 isr_sps_ocp;
struct rtw89_reg2_def isr_clear_rpq;
struct rtw89_reg2_def isr_clear_rxq;
};
diff --git a/drivers/net/wireless/realtek/rtw89/pci_be.c b/drivers/net/wireless/realtek/rtw89/pci_be.c
index e4590879b800..114f40c6c31b 100644
--- a/drivers/net/wireless/realtek/rtw89/pci_be.c
+++ b/drivers/net/wireless/realtek/rtw89/pci_be.c
@@ -46,6 +46,14 @@ static void rtw89_pci_aspm_set_be(struct rtw89_dev *rtwdev, bool enable)
static void rtw89_pci_l1ss_set_be(struct rtw89_dev *rtwdev, bool enable)
{
+ enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
+ struct rtw89_hal *hal = &rtwdev->hal;
+
+ if (enable && chip_id == RTL8922D && hal->cid == RTL8922D_CID7090)
+ rtw89_write32_set(rtwdev, R_BE_PCIE_PS_CTRL,
+ B_BE_ASPM_L11_EN | B_BE_ASPM_L12_EN |
+ B_BE_PCIPM_L11_EN | B_BE_PCIPM_L12_EN);
+
if (enable)
rtw89_write32_set(rtwdev, R_BE_PCIE_MIX_CFG,
B_BE_L1SUB_ENABLE);
@@ -154,7 +162,7 @@ static void rtw89_pci_ctrl_trxdma_pcie_be(struct rtw89_dev *rtwdev,
rtw89_write32(rtwdev, R_BE_HAXI_INIT_CFG1, val);
- if (io_en == MAC_AX_PCIE_ENABLE)
+ if (io_en == MAC_AX_PCIE_ENABLE && rtwdev->chip->chip_id == RTL8922A)
rtw89_write32_mask(rtwdev, R_BE_HAXI_MST_WDT_TIMEOUT_SEL_V1,
B_BE_HAXI_MST_WDT_TIMEOUT_SEL_MASK, 4);
}
@@ -162,14 +170,15 @@ static void rtw89_pci_ctrl_trxdma_pcie_be(struct rtw89_dev *rtwdev,
static void rtw89_pci_clr_idx_all_be(struct rtw89_dev *rtwdev)
{
struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
+ const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_pci_rx_ring *rx_ring;
u32 val;
- val = B_BE_CLR_CH0_IDX | B_BE_CLR_CH1_IDX | B_BE_CLR_CH2_IDX |
- B_BE_CLR_CH3_IDX | B_BE_CLR_CH4_IDX | B_BE_CLR_CH5_IDX |
- B_BE_CLR_CH6_IDX | B_BE_CLR_CH7_IDX | B_BE_CLR_CH8_IDX |
- B_BE_CLR_CH9_IDX | B_BE_CLR_CH10_IDX | B_BE_CLR_CH11_IDX |
- B_BE_CLR_CH12_IDX | B_BE_CLR_CH13_IDX | B_BE_CLR_CH14_IDX;
+ if (chip->chip_id == RTL8922A)
+ val = B_BE_CLR_ALL_IDX_MASK;
+ else
+ val = B_BE_CLR_ALL_IDX_MASK_V1;
+
rtw89_write32(rtwdev, R_BE_TXBD_RWPTR_CLR1, val);
rtw89_write32(rtwdev, R_BE_RXBD_RWPTR_CLR1_V1,
@@ -184,10 +193,13 @@ static void rtw89_pci_clr_idx_all_be(struct rtw89_dev *rtwdev)
static int rtw89_pci_poll_txdma_ch_idle_be(struct rtw89_dev *rtwdev)
{
+ const struct rtw89_pci_info *info = rtwdev->pci_info;
+ u32 dma_busy1 = info->dma_busy1.addr;
+ u32 check = info->dma_busy1.mask;
u32 val;
- return read_poll_timeout(rtw89_read32, val, (val & DMA_BUSY1_CHECK_BE) == 0,
- 10, 1000, false, rtwdev, R_BE_HAXI_DMA_BUSY1);
+ return read_poll_timeout(rtw89_read32, val, (val & check) == 0,
+ 10, 1000, false, rtwdev, dma_busy1);
}
static int rtw89_pci_poll_rxdma_ch_idle_be(struct rtw89_dev *rtwdev)
@@ -223,20 +235,24 @@ static int rtw89_pci_poll_dma_all_idle_be(struct rtw89_dev *rtwdev)
static void rtw89_pci_mode_op_be(struct rtw89_dev *rtwdev)
{
const struct rtw89_pci_info *info = rtwdev->pci_info;
+ const struct rtw89_chip_info *chip = rtwdev->chip;
u32 val32_init1, val32_rxapp, val32_exp;
val32_init1 = rtw89_read32(rtwdev, R_BE_HAXI_INIT_CFG1);
- val32_rxapp = rtw89_read32(rtwdev, R_BE_RX_APPEND_MODE);
+ if (chip->chip_id == RTL8922A)
+ val32_rxapp = rtw89_read32(rtwdev, R_BE_RX_APPEND_MODE);
val32_exp = rtw89_read32(rtwdev, R_BE_HAXI_EXP_CTRL_V1);
- if (info->rxbd_mode == MAC_AX_RXBD_PKT) {
- val32_init1 = u32_replace_bits(val32_init1, PCIE_RXBD_NORM,
- B_BE_RXQ_RXBD_MODE_MASK);
- } else if (info->rxbd_mode == MAC_AX_RXBD_SEP) {
- val32_init1 = u32_replace_bits(val32_init1, PCIE_RXBD_SEP,
- B_BE_RXQ_RXBD_MODE_MASK);
- val32_rxapp = u32_replace_bits(val32_rxapp, 0,
- B_BE_APPEND_LEN_MASK);
+ if (chip->chip_id == RTL8922A) {
+ if (info->rxbd_mode == MAC_AX_RXBD_PKT) {
+ val32_init1 = u32_replace_bits(val32_init1, PCIE_RXBD_NORM,
+ B_BE_RXQ_RXBD_MODE_MASK);
+ } else if (info->rxbd_mode == MAC_AX_RXBD_SEP) {
+ val32_init1 = u32_replace_bits(val32_init1, PCIE_RXBD_SEP,
+ B_BE_RXQ_RXBD_MODE_MASK);
+ val32_rxapp = u32_replace_bits(val32_rxapp, 0,
+ B_BE_APPEND_LEN_MASK);
+ }
}
val32_init1 = u32_replace_bits(val32_init1, info->tx_burst,
@@ -251,7 +267,8 @@ static void rtw89_pci_mode_op_be(struct rtw89_dev *rtwdev)
B_BE_CFG_WD_PERIOD_ACTIVE_MASK);
rtw89_write32(rtwdev, R_BE_HAXI_INIT_CFG1, val32_init1);
- rtw89_write32(rtwdev, R_BE_RX_APPEND_MODE, val32_rxapp);
+ if (chip->chip_id == RTL8922A)
+ rtw89_write32(rtwdev, R_BE_RX_APPEND_MODE, val32_rxapp);
rtw89_write32(rtwdev, R_BE_HAXI_EXP_CTRL_V1, val32_exp);
}
@@ -277,6 +294,10 @@ static void rtw89_pci_debounce_be(struct rtw89_dev *rtwdev)
static void rtw89_pci_ldo_low_pwr_be(struct rtw89_dev *rtwdev)
{
+ enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
+ struct rtw89_hal *hal = &rtwdev->hal;
+ u32 clr;
+
rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_PSUS_OFF_CAPC_EN);
rtw89_write32_set(rtwdev, R_BE_SYS_PAGE_CLK_GATED,
B_BE_SOP_OFFPOOBS_PC | B_BE_CPHY_AUXCLK_OP |
@@ -284,7 +305,16 @@ static void rtw89_pci_ldo_low_pwr_be(struct rtw89_dev *rtwdev)
rtw89_write32_clr(rtwdev, R_BE_SYS_SDIO_CTRL, B_BE_PCIE_FORCE_IBX_EN |
B_BE_PCIE_DIS_L2_RTK_PERST |
B_BE_PCIE_DIS_L2__CTRL_LDO_HCI);
- rtw89_write32_clr(rtwdev, R_BE_L1_2_CTRL_HCILDO, B_BE_PCIE_DIS_L1_2_CTRL_HCILDO);
+
+ if (chip_id == RTL8922D && hal->cid == RTL8922D_CID7090)
+ clr = B_BE_PCIE_DIS_L1_2_CTRL_HCILDO |
+ B_BE_PCIE_DIS_L1_2_CTRL_APHY_SUSB |
+ B_BE_PCIE_DIS_RTK_PRST_N_L1_2 |
+ B_BE_PCIE_DIS_L2_CTRL_APHY_SUSB;
+ else
+ clr = B_BE_PCIE_DIS_L1_2_CTRL_HCILDO;
+
+ rtw89_write32_clr(rtwdev, R_BE_L1_2_CTRL_HCILDO, clr);
}
static void rtw89_pci_pcie_setting_be(struct rtw89_dev *rtwdev)
@@ -300,11 +330,25 @@ static void rtw89_pci_pcie_setting_be(struct rtw89_dev *rtwdev)
rtw89_write32_set(rtwdev, R_BE_EFUSE_CTRL_2_V1, B_BE_R_SYM_AUTOLOAD_WITH_PMC_SEL);
rtw89_write32_set(rtwdev, R_BE_PCIE_LAT_CTRL, B_BE_SYM_AUX_CLK_SEL);
+
+ if (chip->chip_id != RTL8922D)
+ return;
+
+ rtw89_write32_set(rtwdev, R_BE_RSV_CTRL, B_BE_R_SYM_PRST_CPHY_RST);
+ rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_USUS_OFFCAPC_EN);
}
static void rtw89_pci_ser_setting_be(struct rtw89_dev *rtwdev)
{
+ enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
+ struct rtw89_hal *hal = &rtwdev->hal;
u32 val32;
+ int ret;
+
+ if (chip_id == RTL8922D)
+ goto be2_chips;
+ else if (chip_id != RTL8922A)
+ return;
rtw89_write32(rtwdev, R_BE_PL1_DBG_INFO, 0x0);
rtw89_write32_set(rtwdev, R_BE_FWS1IMR, B_BE_PCIE_SER_TIMEOUT_INDIC_EN);
@@ -315,10 +359,48 @@ static void rtw89_pci_ser_setting_be(struct rtw89_dev *rtwdev)
val32 |= B_BE_SER_PMU_IMR | B_BE_SER_L1SUB_IMR | B_BE_SER_PM_MASTER_IMR |
B_BE_SER_LTSSM_IMR | B_BE_SER_PM_CLK_MASK | B_BE_SER_PCLKREQ_ACK_MASK;
rtw89_write32(rtwdev, R_BE_REG_PL1_MASK, val32);
+
+ return;
+
+be2_chips:
+ rtw89_write32_clr(rtwdev, R_BE_PCIE_SER_DBG, B_BE_PCIE_SER_FLUSH_RSTB);
+ rtw89_write32_set(rtwdev, R_BE_PCIE_SER_DBG, B_BE_PCIE_SER_FLUSH_RSTB);
+
+ rtw89_write16_clr(rtwdev, RAC_DIRECT_OFFESET_L0_G1 +
+ RAC_ANA41 * RAC_MULT, PHY_ERR_FLAG_EN);
+ rtw89_write16_clr(rtwdev, RAC_DIRECT_OFFESET_L0_G2 +
+ RAC_ANA41 * RAC_MULT, PHY_ERR_FLAG_EN);
+ rtw89_write16_set(rtwdev, RAC_DIRECT_OFFESET_L0_G1 +
+ RAC_ANA41 * RAC_MULT, PHY_ERR_FLAG_EN);
+ rtw89_write16_set(rtwdev, RAC_DIRECT_OFFESET_L0_G2 +
+ RAC_ANA41 * RAC_MULT, PHY_ERR_FLAG_EN);
+
+ val32 = rtw89_read32(rtwdev, R_BE_SER_PL1_CTRL);
+ val32 &= ~B_BE_PL1_SER_PL1_EN;
+ rtw89_write32(rtwdev, R_BE_SER_PL1_CTRL, val32);
+
+ ret = read_poll_timeout_atomic(rtw89_read32, val32, !val32,
+ 1, 1000, false, rtwdev, R_BE_REG_PL1_ISR);
+ if (ret)
+ rtw89_warn(rtwdev, "[ERR] PCIE SER clear poll fail\n");
+
+ val32 = rtw89_read32(rtwdev, R_BE_REG_PL1_MASK);
+ val32 |= B_BE_SER_PMU_IMR | B_BE_SER_L1SUB_IMR | B_BE_SER_PM_MASTER_IMR |
+ B_BE_SER_LTSSM_IMR | B_BE_SER_PM_CLK_MASK | B_BE_SER_PCLKREQ_ACK_MASK |
+ B_BE_SER_LTSSM_UNSTABLE_MASK;
+ rtw89_write32(rtwdev, R_BE_REG_PL1_MASK, val32);
+
+ rtw89_write32_mask(rtwdev, R_BE_SER_PL1_CTRL, B_BE_PL1_TIMER_UNIT_MASK,
+ PCIE_SER_TIMER_UNIT);
+ rtw89_write32_set(rtwdev, R_BE_SER_PL1_CTRL, B_BE_PL1_SER_PL1_EN);
+
+ if (hal->cid == RTL8922D_CID7090)
+ rtw89_write32_set(rtwdev, R_BE_SYS_SDIO_CTRL, B_BE_SER_DETECT_EN);
}
static void rtw89_pci_ctrl_txdma_ch_be(struct rtw89_dev *rtwdev, bool enable)
{
+ const struct rtw89_pci_info *info = rtwdev->pci_info;
u32 mask_all;
u32 val;
@@ -327,6 +409,9 @@ static void rtw89_pci_ctrl_txdma_ch_be(struct rtw89_dev *rtwdev, bool enable)
B_BE_STOP_CH6 | B_BE_STOP_CH7 | B_BE_STOP_CH8 |
B_BE_STOP_CH9 | B_BE_STOP_CH10 | B_BE_STOP_CH11;
+ /* mask out unsupported channels for certains chips */
+ mask_all &= info->dma_stop1.mask;
+
val = rtw89_read32(rtwdev, R_BE_HAXI_DMA_STOP1);
val |= B_BE_STOP_CH13 | B_BE_STOP_CH14;
@@ -409,6 +494,7 @@ static int rtw89_pci_ops_mac_pre_deinit_be(struct rtw89_dev *rtwdev)
int rtw89_pci_ltr_set_v2(struct rtw89_dev *rtwdev, bool en)
{
u32 ctrl0, cfg0, cfg1, dec_ctrl, idle_ltcy, act_ltcy, dis_ltcy;
+ u32 ltr_idle_lat_ctrl, ltr_act_lat_ctrl;
ctrl0 = rtw89_read32(rtwdev, R_BE_LTR_CTRL_0);
if (rtw89_pci_ltr_is_err_reg_val(ctrl0))
@@ -451,8 +537,16 @@ int rtw89_pci_ltr_set_v2(struct rtw89_dev *rtwdev, bool en)
cfg0 = u32_replace_bits(cfg0, 3, B_BE_LTR_IDX_IDLE_MASK);
dec_ctrl = u32_replace_bits(dec_ctrl, 0, B_BE_LTR_IDX_DISABLE_V1_MASK);
- rtw89_write32(rtwdev, R_BE_LTR_LATENCY_IDX3_V1, 0x90039003);
- rtw89_write32(rtwdev, R_BE_LTR_LATENCY_IDX1_V1, 0x880b880b);
+ if (rtwdev->chip->chip_id == RTL8922A) {
+ ltr_idle_lat_ctrl = 0x90039003;
+ ltr_act_lat_ctrl = 0x880b880b;
+ } else {
+ ltr_idle_lat_ctrl = 0x90019001;
+ ltr_act_lat_ctrl = 0x88018801;
+ }
+
+ rtw89_write32(rtwdev, R_BE_LTR_LATENCY_IDX3_V1, ltr_idle_lat_ctrl);
+ rtw89_write32(rtwdev, R_BE_LTR_LATENCY_IDX1_V1, ltr_act_lat_ctrl);
rtw89_write32(rtwdev, R_BE_LTR_LATENCY_IDX0_V1, 0);
rtw89_write32(rtwdev, R_BE_LTR_DECISION_CTRL_V1, dec_ctrl);
rtw89_write32(rtwdev, R_BE_LTR_CFG_0, cfg0);
@@ -669,6 +763,7 @@ const struct rtw89_pci_isr_def rtw89_pci_isr_be = {
.isr_rdu = B_BE_RDU_CH1_INT_V1 | B_BE_RDU_CH0_INT_V1,
.isr_halt_c2h = B_BE_HALT_C2H_INT,
.isr_wdt_timeout = B_BE_WDT_TIMEOUT_INT,
+ .isr_sps_ocp = 0,
.isr_clear_rpq = {R_BE_PCIE_DMA_ISR, B_BE_PCIE_RX_RPQ0_ISR_V1},
.isr_clear_rxq = {R_BE_PCIE_DMA_ISR, B_BE_PCIE_RX_RX0P2_ISR_V1},
};
@@ -678,6 +773,7 @@ const struct rtw89_pci_isr_def rtw89_pci_isr_be_v1 = {
.isr_rdu = B_BE_PCIE_RDU_CH1_INT | B_BE_PCIE_RDU_CH0_INT,
.isr_halt_c2h = B_BE_HALT_C2H_INT,
.isr_wdt_timeout = B_BE_WDT_TIMEOUT_INT,
+ .isr_sps_ocp = B_BE_SPS_OCP_INT | B_BE_SPSANA_OCP_INT,
.isr_clear_rpq = {R_BE_PCIE_DMA_ISR, B_BE_PCIE_RX_RPQ0_ISR_V1},
.isr_clear_rxq = {R_BE_PCIE_DMA_ISR, B_BE_PCIE_RX_RX0P2_ISR_V1},
};
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index 9f418b1fb7ed..6c6d5f1da867 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -281,8 +281,7 @@ static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev,
struct cfg80211_bitrate_mask *mask = &rtwsta_link->mask;
u8 band = chan->band_type;
enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
- u8 he_ltf = mask->control[nl_band].he_ltf;
- u8 he_gi = mask->control[nl_band].he_gi;
+ u8 ltf, gi;
*fix_giltf_en = true;
@@ -293,22 +292,31 @@ static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev,
else
*fix_giltf = RTW89_GILTF_2XHE08;
- if (!(rtwsta_link->use_cfg_mask && link_sta->he_cap.has_he))
+ if (!rtwsta_link->use_cfg_mask)
return;
- if (he_ltf == 2 && he_gi == 2) {
+ if (link_sta->eht_cap.has_eht) {
+ ltf = mask->control[nl_band].eht_ltf;
+ gi = mask->control[nl_band].eht_gi;
+ } else if (link_sta->he_cap.has_he) {
+ ltf = mask->control[nl_band].he_ltf;
+ gi = mask->control[nl_band].he_gi;
+ } else {
+ return;
+ }
+
+ if (ltf == 2 && gi == 2)
*fix_giltf = RTW89_GILTF_LGI_4XHE32;
- } else if (he_ltf == 2 && he_gi == 0) {
+ else if (ltf == 2 && gi == 0)
*fix_giltf = RTW89_GILTF_SGI_4XHE08;
- } else if (he_ltf == 1 && he_gi == 1) {
+ else if (ltf == 1 && gi == 1)
*fix_giltf = RTW89_GILTF_2XHE16;
- } else if (he_ltf == 1 && he_gi == 0) {
+ else if (ltf == 1 && gi == 0)
*fix_giltf = RTW89_GILTF_2XHE08;
- } else if (he_ltf == 0 && he_gi == 1) {
+ else if (ltf == 0 && gi == 1)
*fix_giltf = RTW89_GILTF_1XHE16;
- } else if (he_ltf == 0 && he_gi == 0) {
+ else if (ltf == 0 && gi == 0)
*fix_giltf = RTW89_GILTF_1XHE08;
- }
}
static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
@@ -1028,6 +1036,68 @@ u32 rtw89_phy_read_rf_v2(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
}
EXPORT_SYMBOL(rtw89_phy_read_rf_v2);
+static u32 rtw89_phy_read_full_rf_v3_a(struct rtw89_dev *rtwdev,
+ enum rtw89_rf_path rf_path, u32 addr)
+{
+ bool done;
+ u32 busy;
+ int ret;
+ u32 val;
+
+ ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, busy, !busy,
+ 1, 30, false,
+ rtwdev, R_SW_SI_DATA_BE4,
+ B_SW_SI_W_BUSY_BE4 | B_SW_SI_R_BUSY_BE4);
+ if (ret) {
+ rtw89_warn(rtwdev, "poll HWSI is busy\n");
+ return INV_RF_DATA;
+ }
+
+ val = u32_encode_bits(rf_path, GENMASK(10, 8)) |
+ u32_encode_bits(addr, GENMASK(7, 0));
+
+ rtw89_phy_write32_mask(rtwdev, R_SW_SI_READ_ADDR_BE4, B_SW_SI_READ_ADDR_BE4, val);
+
+ ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, done, done,
+ 1, 30, false,
+ rtwdev, R_SW_SI_DATA_BE4, B_SW_SI_READ_DATA_DONE_BE4);
+ if (ret) {
+ rtw89_warn(rtwdev, "read HWSI is busy\n");
+ return INV_RF_DATA;
+ }
+
+ val = rtw89_phy_read32_mask(rtwdev, R_SW_SI_DATA_BE4, B_SW_SI_READ_DATA_BE4);
+
+ return val;
+}
+
+static u32 rtw89_phy_read_rf_v3_a(struct rtw89_dev *rtwdev,
+ enum rtw89_rf_path rf_path, u32 addr, u32 mask)
+{
+ u32 val;
+
+ val = rtw89_phy_read_full_rf_v3_a(rtwdev, rf_path, addr);
+
+ return (val & mask) >> __ffs(mask);
+}
+
+u32 rtw89_phy_read_rf_v3(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
+ u32 addr, u32 mask)
+{
+ bool ad_sel = u32_get_bits(addr, RTW89_RF_ADDR_ADSEL_MASK);
+
+ if (rf_path >= rtwdev->chip->rf_path_num) {
+ rtw89_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
+ return INV_RF_DATA;
+ }
+
+ if (ad_sel)
+ return rtw89_phy_read_rf(rtwdev, rf_path, addr, mask);
+ else
+ return rtw89_phy_read_rf_v3_a(rtwdev, rf_path, addr, mask);
+}
+EXPORT_SYMBOL(rtw89_phy_read_rf_v3);
+
bool rtw89_phy_write_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
u32 addr, u32 mask, u32 data)
{
@@ -1167,6 +1237,66 @@ bool rtw89_phy_write_rf_v2(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
}
EXPORT_SYMBOL(rtw89_phy_write_rf_v2);
+static
+bool rtw89_phy_write_full_rf_v3_a(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
+ u32 addr, u32 data)
+{
+ u32 busy;
+ u32 val;
+ int ret;
+
+ ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, busy, !busy,
+ 1, 30, false,
+ rtwdev, R_SW_SI_DATA_BE4,
+ B_SW_SI_W_BUSY_BE4 | B_SW_SI_R_BUSY_BE4);
+ if (ret) {
+ rtw89_warn(rtwdev, "[%s] HWSI is busy\n", __func__);
+ return false;
+ }
+
+ val = u32_encode_bits(rf_path, B_SW_SI_DATA_PATH_BE4) |
+ u32_encode_bits(addr, B_SW_SI_DATA_ADR_BE4) |
+ u32_encode_bits(data, B_SW_SI_DATA_DAT_BE4);
+
+ rtw89_phy_write32(rtwdev, R_SW_SI_WDATA_BE4, val);
+
+ return true;
+}
+
+static
+bool rtw89_phy_write_rf_a_v3(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
+ u32 addr, u32 mask, u32 data)
+{
+ u32 val;
+
+ if (mask == RFREG_MASK) {
+ val = data;
+ } else {
+ val = rtw89_phy_read_full_rf_v3_a(rtwdev, rf_path, addr);
+ val &= ~mask;
+ val |= (data << __ffs(mask)) & mask;
+ }
+
+ return rtw89_phy_write_full_rf_v3_a(rtwdev, rf_path, addr, val);
+}
+
+bool rtw89_phy_write_rf_v3(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
+ u32 addr, u32 mask, u32 data)
+{
+ bool ad_sel = u32_get_bits(addr, RTW89_RF_ADDR_ADSEL_MASK);
+
+ if (rf_path >= rtwdev->chip->rf_path_num) {
+ rtw89_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
+ return INV_RF_DATA;
+ }
+
+ if (ad_sel)
+ return rtw89_phy_write_rf(rtwdev, rf_path, addr, mask, data);
+ else
+ return rtw89_phy_write_rf_a_v3(rtwdev, rf_path, addr, mask, data);
+}
+EXPORT_SYMBOL(rtw89_phy_write_rf_v3);
+
static bool rtw89_chip_rf_v1(struct rtw89_dev *rtwdev)
{
return rtwdev->chip->ops->write_rf == rtw89_phy_write_rf_v1;
@@ -3202,6 +3332,7 @@ void (* const rtw89_phy_c2h_ra_handler[])(struct rtw89_dev *rtwdev,
[RTW89_PHY_C2H_FUNC_STS_RPT] = rtw89_phy_c2h_ra_rpt,
[RTW89_PHY_C2H_FUNC_MU_GPTBL_RPT] = NULL,
[RTW89_PHY_C2H_FUNC_TXSTS] = NULL,
+ [RTW89_PHY_C2H_FUNC_ACCELERATE_EN] = rtw89_fw_c2h_dummy_handler,
};
static void
@@ -3210,6 +3341,64 @@ rtw89_phy_c2h_lowrt_rty(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
}
static void
+rtw89_phy_c2h_lps_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
+{
+ const struct rtw89_c2h_lps_rpt *c2h_rpt = (const void *)c2h->data;
+ const __le32 *data_a, *data_b;
+ u16 len_info, cr_len, idx;
+ const __le16 *addr;
+ const u8 *info;
+
+ /* elements size of BBCR/BBMCUCR/RFCR are 6/6/10 bytes respectively */
+ cr_len = c2h_rpt->cnt_bbcr * 6 +
+ c2h_rpt->cnt_bbmcucr * 6 +
+ c2h_rpt->cnt_rfcr * 10;
+ len_info = len - (sizeof(*c2h_rpt) + cr_len);
+
+ if (len < sizeof(*c2h_rpt) + cr_len || len_info % 4 != 0) {
+ rtw89_debug(rtwdev, RTW89_DBG_PS,
+ "Invalid LPS RPT len(%d) TYPE(%d) CRCNT: BB(%d) MCU(%d) RF(%d)\n",
+ len, c2h_rpt->type, c2h_rpt->cnt_bbcr,
+ c2h_rpt->cnt_bbmcucr, c2h_rpt->cnt_rfcr);
+ return;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_PS,
+ "LPS RPT TYPE(%d), CRCNT: BB(%d) MCU(%d) RF(%d)\n",
+ c2h_rpt->type, c2h_rpt->cnt_bbcr,
+ c2h_rpt->cnt_bbmcucr, c2h_rpt->cnt_rfcr);
+
+ info = &c2h_rpt->data[0];
+ for (idx = 0; idx < len_info; idx += 4, info += 4)
+ rtw89_debug(rtwdev, RTW89_DBG_PS,
+ "BB LPS INFO (%02d) - 0x%02x,0x%02x,0x%02x,0x%02x\n",
+ idx, info[3], info[2], info[1], info[0]);
+
+ addr = (const void *)(info);
+ data_a = (const void *)(addr + c2h_rpt->cnt_bbcr);
+ for (idx = 0; idx < c2h_rpt->cnt_bbcr; idx++, addr++, data_a++)
+ rtw89_debug(rtwdev, RTW89_DBG_PS,
+ "LPS BB CR - 0x%04x=0x%08x\n",
+ le16_to_cpu(*addr), le32_to_cpu(*data_a));
+
+ addr = (const void *)data_a;
+ data_a = (const void *)(addr + c2h_rpt->cnt_bbmcucr);
+ for (idx = 0; idx < c2h_rpt->cnt_bbmcucr; idx++, addr++, data_a++)
+ rtw89_debug(rtwdev, RTW89_DBG_PS,
+ "LPS BBMCU - 0x%04x=0x%08x\n",
+ le16_to_cpu(*addr), le32_to_cpu(*data_a));
+
+ addr = (const void *)data_a;
+ data_a = (const void *)(addr + c2h_rpt->cnt_rfcr);
+ data_b = (const void *)(data_a + c2h_rpt->cnt_rfcr);
+ for (idx = 0; idx < c2h_rpt->cnt_rfcr; idx++, addr++, data_a++, data_b++)
+ rtw89_debug(rtwdev, RTW89_DBG_PS,
+ "LPS RFCR - 0x%04x=0x%05x,0x%05x\n",
+ le16_to_cpu(*addr), le32_to_cpu(*data_a),
+ le32_to_cpu(*data_b));
+}
+
+static void
rtw89_phy_c2h_fw_scan_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
{
const struct rtw89_c2h_fw_scan_rpt *c2h_rpt =
@@ -3230,6 +3419,8 @@ void (* const rtw89_phy_c2h_dm_handler[])(struct rtw89_dev *rtwdev,
[RTW89_PHY_C2H_DM_FUNC_SIGB] = NULL,
[RTW89_PHY_C2H_DM_FUNC_LOWRT_RTY] = rtw89_phy_c2h_lowrt_rty,
[RTW89_PHY_C2H_DM_FUNC_MCC_DIG] = NULL,
+ [RTW89_PHY_C2H_DM_FUNC_LPS] = rtw89_phy_c2h_lps_rpt,
+ [RTW89_PHY_C2H_DM_FUNC_ENV_MNTR] = rtw89_fw_c2h_dummy_handler,
[RTW89_PHY_C2H_DM_FUNC_FW_SCAN] = rtw89_phy_c2h_fw_scan_rpt,
};
@@ -3267,6 +3458,8 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev,
{
struct rtw89_c2h_rf_txgapk_rpt_log *txgapk;
struct rtw89_c2h_rf_rxdck_rpt_log *rxdck;
+ struct rtw89_c2h_rf_txiqk_rpt_log *txiqk;
+ struct rtw89_c2h_rf_cim3k_rpt_log *cim3k;
struct rtw89_c2h_rf_dack_rpt_log *dack;
struct rtw89_c2h_rf_tssi_rpt_log *tssi;
struct rtw89_c2h_rf_dpk_rpt_log *dpk;
@@ -3321,6 +3514,8 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev,
i, iqk->iqk_ch[i]);
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_bw[%d] = %x\n",
i, iqk->iqk_bw[i]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->rf_0x18[%d] = %x\n",
+ i, le32_to_cpu(iqk->rf_0x18[i]));
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->lok_idac[%d] = %x\n",
i, le32_to_cpu(iqk->lok_idac[i]));
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->lok_vbuf[%d] = %x\n",
@@ -3329,22 +3524,30 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev,
i, iqk->iqk_tx_fail[i]);
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_rx_fail[%d] = %x\n",
i, iqk->iqk_rx_fail[i]);
- for (j = 0; j < 4; j++)
+ for (j = 0; j < 6; j++)
rtw89_debug(rtwdev, RTW89_DBG_RFK,
"[IQK] iqk->rftxgain[%d][%d] = %x\n",
i, j, le32_to_cpu(iqk->rftxgain[i][j]));
- for (j = 0; j < 4; j++)
+ for (j = 0; j < 6; j++)
rtw89_debug(rtwdev, RTW89_DBG_RFK,
"[IQK] iqk->tx_xym[%d][%d] = %x\n",
i, j, le32_to_cpu(iqk->tx_xym[i][j]));
- for (j = 0; j < 4; j++)
+ for (j = 0; j < 6; j++)
rtw89_debug(rtwdev, RTW89_DBG_RFK,
"[IQK] iqk->rfrxgain[%d][%d] = %x\n",
i, j, le32_to_cpu(iqk->rfrxgain[i][j]));
- for (j = 0; j < 4; j++)
+ for (j = 0; j < 6; j++)
rtw89_debug(rtwdev, RTW89_DBG_RFK,
"[IQK] iqk->rx_xym[%d][%d] = %x\n",
i, j, le32_to_cpu(iqk->rx_xym[i][j]));
+
+ if (!iqk->iqk_xym_en)
+ continue;
+
+ for (j = 0; j < 32; j++)
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK] iqk->rx_wb_xym[%d][%d] = %x\n",
+ i, j, iqk->rx_wb_xym[i][j]);
}
return;
case RTW89_PHY_C2H_RFK_LOG_FUNC_DPK:
@@ -3500,8 +3703,16 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev,
le32_to_cpu(txgapk->chk_cnt));
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt ver = 0x%x\n",
txgapk->ver);
- rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt rsv1 = %d\n",
- txgapk->rsv1);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt d_bnd_ok = %d\n",
+ txgapk->d_bnd_ok);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt stage[0] = 0x%x\n",
+ le32_to_cpu(txgapk->stage[0]));
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt stage[1] = 0x%x\n",
+ le32_to_cpu(txgapk->stage[1]));
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]failcode[0] = 0x%x\n",
+ le16_to_cpu(txgapk->failcode[0]));
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]failcode[1] = 0x%x\n",
+ le16_to_cpu(txgapk->failcode[1]));
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt track_d[0] = %*ph\n",
(int)sizeof(txgapk->track_d[0]), txgapk->track_d[0]);
@@ -3517,7 +3728,14 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev,
goto out;
rtw89_phy_c2h_rfk_tas_pwr(rtwdev, content);
-
+ return;
+ case RTW89_PHY_C2H_RFK_LOG_FUNC_TXIQK:
+ if (len != sizeof(*txiqk))
+ goto out;
+ return;
+ case RTW89_PHY_C2H_RFK_LOG_FUNC_CIM3K:
+ if (len != sizeof(*cim3k))
+ goto out;
return;
default:
break;
@@ -3654,6 +3872,20 @@ rtw89_phy_c2h_rfk_log_tas_pwr(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32
RTW89_PHY_C2H_RFK_LOG_FUNC_TAS_PWR, "TAS");
}
+static void
+rtw89_phy_c2h_rfk_log_txiqk(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
+{
+ rtw89_phy_c2h_rfk_log(rtwdev, c2h, len,
+ RTW89_PHY_C2H_RFK_LOG_FUNC_TXIQK, "TXIQK");
+}
+
+static void
+rtw89_phy_c2h_rfk_log_cim3k(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
+{
+ rtw89_phy_c2h_rfk_log(rtwdev, c2h, len,
+ RTW89_PHY_C2H_RFK_LOG_FUNC_CIM3K, "CIM3K");
+}
+
static
void (* const rtw89_phy_c2h_rfk_log_handler[])(struct rtw89_dev *rtwdev,
struct sk_buff *c2h, u32 len) = {
@@ -3664,6 +3896,8 @@ void (* const rtw89_phy_c2h_rfk_log_handler[])(struct rtw89_dev *rtwdev,
[RTW89_PHY_C2H_RFK_LOG_FUNC_TSSI] = rtw89_phy_c2h_rfk_log_tssi,
[RTW89_PHY_C2H_RFK_LOG_FUNC_TXGAPK] = rtw89_phy_c2h_rfk_log_txgapk,
[RTW89_PHY_C2H_RFK_LOG_FUNC_TAS_PWR] = rtw89_phy_c2h_rfk_log_tas_pwr,
+ [RTW89_PHY_C2H_RFK_LOG_FUNC_TXIQK] = rtw89_phy_c2h_rfk_log_txiqk,
+ [RTW89_PHY_C2H_RFK_LOG_FUNC_CIM3K] = rtw89_phy_c2h_rfk_log_cim3k,
};
static
@@ -3752,6 +3986,7 @@ bool rtw89_phy_c2h_chk_atomic(struct rtw89_dev *rtwdev, u8 class, u8 func)
case RTW89_PHY_C2H_RFK_LOG_FUNC_RXDCK:
case RTW89_PHY_C2H_RFK_LOG_FUNC_TSSI:
case RTW89_PHY_C2H_RFK_LOG_FUNC_TXGAPK:
+ case RTW89_PHY_C2H_RFK_LOG_FUNC_TXIQK:
return true;
default:
return false;
@@ -3776,7 +4011,7 @@ void rtw89_phy_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
switch (class) {
case RTW89_PHY_C2H_CLASS_RA:
- if (func < RTW89_PHY_C2H_FUNC_RA_MAX)
+ if (func < ARRAY_SIZE(rtw89_phy_c2h_ra_handler))
handler = rtw89_phy_c2h_ra_handler[func];
break;
case RTW89_PHY_C2H_RFK_LOG:
@@ -3808,13 +4043,22 @@ int rtw89_phy_rfk_pre_ntfy_and_wait(struct rtw89_dev *rtwdev,
{
int ret;
- rtw89_phy_rfk_report_prep(rtwdev);
+ if (RTW89_CHK_FW_FEATURE_GROUP(WITH_RFK_PRE_NOTIFY, &rtwdev->fw)) {
+ rtw89_phy_rfk_report_prep(rtwdev);
+ rtw89_fw_h2c_rf_pre_ntfy(rtwdev, phy_idx);
+ ret = rtw89_phy_rfk_report_wait(rtwdev, "PRE_NTFY", ms);
+ if (ret)
+ return ret;
+ }
- ret = rtw89_fw_h2c_rf_pre_ntfy(rtwdev, phy_idx);
- if (ret)
- return ret;
+ if (RTW89_CHK_FW_FEATURE_GROUP(WITH_RFK_PRE_NOTIFY_MCC, &rtwdev->fw)) {
+ ret = rtw89_fw_h2c_rf_pre_ntfy_mcc(rtwdev, phy_idx);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
- return rtw89_phy_rfk_report_wait(rtwdev, "PRE_NTFY", ms);
}
EXPORT_SYMBOL(rtw89_phy_rfk_pre_ntfy_and_wait);
@@ -3921,6 +4165,40 @@ int rtw89_phy_rfk_rxdck_and_wait(struct rtw89_dev *rtwdev,
}
EXPORT_SYMBOL(rtw89_phy_rfk_rxdck_and_wait);
+int rtw89_phy_rfk_txiqk_and_wait(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx,
+ const struct rtw89_chan *chan,
+ unsigned int ms)
+{
+ int ret;
+
+ rtw89_phy_rfk_report_prep(rtwdev);
+
+ ret = rtw89_fw_h2c_rf_txiqk(rtwdev, phy_idx, chan);
+ if (ret)
+ return ret;
+
+ return rtw89_phy_rfk_report_wait(rtwdev, "TX_IQK", ms);
+}
+EXPORT_SYMBOL(rtw89_phy_rfk_txiqk_and_wait);
+
+int rtw89_phy_rfk_cim3k_and_wait(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx,
+ const struct rtw89_chan *chan,
+ unsigned int ms)
+{
+ int ret;
+
+ rtw89_phy_rfk_report_prep(rtwdev);
+
+ ret = rtw89_fw_h2c_rf_cim3k(rtwdev, phy_idx, chan);
+ if (ret)
+ return ret;
+
+ return rtw89_phy_rfk_report_wait(rtwdev, "CIM3k", ms);
+}
+EXPORT_SYMBOL(rtw89_phy_rfk_cim3k_and_wait);
+
static u32 phy_tssi_get_cck_group(u8 ch)
{
switch (ch) {
@@ -4368,6 +4646,7 @@ void rtw89_phy_rfk_tssi_fill_fwcmd_efuse_to_de(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
struct rtw89_h2c_rf_tssi *h2c)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
u8 ch = chan->channel;
s8 trim_de;
@@ -4391,9 +4670,14 @@ void rtw89_phy_rfk_tssi_fill_fwcmd_efuse_to_de(struct rtw89_dev *rtwdev,
cck_de = tssi_info->tssi_cck[i][gidx];
val = u32_get_bits(cck_de + trim_de, 0xff);
- h2c->curr_tssi_cck_de[i] = 0x0;
- h2c->curr_tssi_cck_de_20m[i] = val;
- h2c->curr_tssi_cck_de_40m[i] = val;
+ if (chip->chip_id == RTL8922A) {
+ h2c->curr_tssi_cck_de[i] = 0x0;
+ h2c->curr_tssi_cck_de_20m[i] = val;
+ h2c->curr_tssi_cck_de_40m[i] = val;
+ } else {
+ h2c->curr_tssi_cck_de[i] = val;
+ }
+
h2c->curr_tssi_efuse_cck_de[i] = cck_de;
rtw89_debug(rtwdev, RTW89_DBG_TSSI,
@@ -4402,12 +4686,17 @@ void rtw89_phy_rfk_tssi_fill_fwcmd_efuse_to_de(struct rtw89_dev *rtwdev,
ofdm_de = phy_tssi_get_ofdm_de(rtwdev, phy, chan, i);
val = u32_get_bits(ofdm_de + trim_de, 0xff);
- h2c->curr_tssi_ofdm_de[i] = 0x0;
- h2c->curr_tssi_ofdm_de_20m[i] = val;
- h2c->curr_tssi_ofdm_de_40m[i] = val;
- h2c->curr_tssi_ofdm_de_80m[i] = val;
- h2c->curr_tssi_ofdm_de_160m[i] = val;
- h2c->curr_tssi_ofdm_de_320m[i] = val;
+ if (chip->chip_id == RTL8922A) {
+ h2c->curr_tssi_ofdm_de[i] = 0x0;
+ h2c->curr_tssi_ofdm_de_20m[i] = val;
+ h2c->curr_tssi_ofdm_de_40m[i] = val;
+ h2c->curr_tssi_ofdm_de_80m[i] = val;
+ h2c->curr_tssi_ofdm_de_160m[i] = val;
+ h2c->curr_tssi_ofdm_de_320m[i] = val;
+ } else {
+ h2c->curr_tssi_ofdm_de[i] = val;
+ }
+
h2c->curr_tssi_efuse_ofdm_de[i] = ofdm_de;
rtw89_debug(rtwdev, RTW89_DBG_TSSI,
@@ -4422,10 +4711,12 @@ void rtw89_phy_rfk_tssi_fill_fwcmd_tmeter_tbl(struct rtw89_dev *rtwdev,
{
struct rtw89_fw_txpwr_track_cfg *trk = rtwdev->fw.elm_info.txpwr_trk;
struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
+ const struct rtw89_chip_info *chip = rtwdev->chip;
const s8 *thm_up[RF_PATH_B + 1] = {};
const s8 *thm_down[RF_PATH_B + 1] = {};
u8 subband = chan->subband_type;
- s8 thm_ofst[128] = {0};
+ s8 thm_ofst[128] = {};
+ int multiplier;
u8 thermal;
u8 path;
u8 i, j;
@@ -4489,6 +4780,11 @@ void rtw89_phy_rfk_tssi_fill_fwcmd_tmeter_tbl(struct rtw89_dev *rtwdev,
rtw89_debug(rtwdev, RTW89_DBG_TSSI,
"[TSSI] tmeter tbl on subband: %u\n", subband);
+ if (chip->chip_id == RTL8922A)
+ multiplier = 1;
+ else
+ multiplier = -1;
+
for (path = RF_PATH_A; path <= RF_PATH_B; path++) {
thermal = tssi_info->thermal[path];
rtw89_debug(rtwdev, RTW89_DBG_TSSI,
@@ -4503,16 +4799,20 @@ void rtw89_phy_rfk_tssi_fill_fwcmd_tmeter_tbl(struct rtw89_dev *rtwdev,
h2c->pg_thermal[path] = thermal;
i = 0;
- for (j = 0; j < 64; j++)
+ for (j = 0; j < 64; j++) {
thm_ofst[j] = i < DELTA_SWINGIDX_SIZE ?
thm_up[path][i++] :
thm_up[path][DELTA_SWINGIDX_SIZE - 1];
+ thm_ofst[j] *= multiplier;
+ }
i = 1;
- for (j = 127; j >= 64; j--)
+ for (j = 127; j >= 64; j--) {
thm_ofst[j] = i < DELTA_SWINGIDX_SIZE ?
-thm_down[path][i++] :
-thm_down[path][DELTA_SWINGIDX_SIZE - 1];
+ thm_ofst[j] *= multiplier;
+ }
for (i = 0; i < 128; i += 4) {
h2c->ftable[path][i + 0] = thm_ofst[i + 3];
@@ -6001,11 +6301,12 @@ static bool rtw89_phy_ifs_clm_get_result(struct rtw89_dev *rtwdev,
env->ifs_clm_his[1] =
rtw89_phy_read32_idx(rtwdev, ccx->ifs_his_addr,
ccx->ifs_t2_his_mask, bb->phy_idx);
+
env->ifs_clm_his[2] =
- rtw89_phy_read32_idx(rtwdev, ccx->ifs_his_addr,
+ rtw89_phy_read32_idx(rtwdev, ccx->ifs_his_addr2,
ccx->ifs_t3_his_mask, bb->phy_idx);
env->ifs_clm_his[3] =
- rtw89_phy_read32_idx(rtwdev, ccx->ifs_his_addr,
+ rtw89_phy_read32_idx(rtwdev, ccx->ifs_his_addr2,
ccx->ifs_t4_his_mask, bb->phy_idx);
env->ifs_clm_avg[0] =
@@ -6268,14 +6569,16 @@ static bool rtw89_physts_ie_page_valid(struct rtw89_dev *rtwdev,
return true;
}
-static u32 rtw89_phy_get_ie_bitmap_addr(enum rtw89_phy_status_bitmap ie_page)
+static u32 rtw89_phy_get_ie_bitmap_addr(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_status_bitmap ie_page)
{
+ const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
static const u8 ie_page_shift = 2;
if (ie_page == RTW89_EHT_PKT)
- return R_PHY_STS_BITMAP_EHT;
+ return phy->physt_bmp_eht;
- return R_PHY_STS_BITMAP_ADDR_START + (ie_page << ie_page_shift);
+ return phy->physt_bmp_start + (ie_page << ie_page_shift);
}
static u32 rtw89_physts_get_ie_bitmap(struct rtw89_dev *rtwdev,
@@ -6287,7 +6590,7 @@ static u32 rtw89_physts_get_ie_bitmap(struct rtw89_dev *rtwdev,
if (!rtw89_physts_ie_page_valid(rtwdev, &ie_page))
return 0;
- addr = rtw89_phy_get_ie_bitmap_addr(ie_page);
+ addr = rtw89_phy_get_ie_bitmap_addr(rtwdev, ie_page);
return rtw89_phy_read32_idx(rtwdev, addr, MASKDWORD, phy_idx);
}
@@ -6305,7 +6608,7 @@ static void rtw89_physts_set_ie_bitmap(struct rtw89_dev *rtwdev,
if (chip->chip_id == RTL8852A)
val &= B_PHY_STS_BITMAP_MSK_52A;
- addr = rtw89_phy_get_ie_bitmap_addr(ie_page);
+ addr = rtw89_phy_get_ie_bitmap_addr(rtwdev, ie_page);
rtw89_phy_write32_idx(rtwdev, addr, MASKDWORD, val, phy_idx);
}
@@ -6329,6 +6632,17 @@ static void rtw89_physts_enable_fail_report(struct rtw89_dev *rtwdev,
}
}
+static void rtw89_physts_enable_hdr_2(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+
+ if (chip->chip_gen == RTW89_CHIP_AX || chip->chip_id == RTL8922A)
+ return;
+
+ rtw89_phy_write32_idx_set(rtwdev, R_STS_HDR2_PARSING_BE4,
+ B_STS_HDR2_PARSING_BE4, phy_idx);
+}
+
static void __rtw89_physts_parsing_init(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx)
{
@@ -6338,6 +6652,9 @@ static void __rtw89_physts_parsing_init(struct rtw89_dev *rtwdev,
rtw89_physts_enable_fail_report(rtwdev, false, phy_idx);
+ /* enable hdr_2 for 8922D (PHYSTS_BE_GEN2 above) */
+ rtw89_physts_enable_hdr_2(rtwdev, phy_idx);
+
for (i = 0; i < RTW89_PHYSTS_BITMAP_NUM; i++) {
if (i == RTW89_RSVD_9 ||
(i == RTW89_EHT_PKT && chip->chip_gen == RTW89_CHIP_AX))
@@ -6703,6 +7020,9 @@ static void rtw89_phy_dig_sdagc_follow_pagc_config(struct rtw89_dev *rtwdev,
{
const struct rtw89_dig_regs *dig_regs = rtwdev->chip->dig_regs;
+ if (rtwdev->chip->chip_gen != RTW89_CHIP_AX)
+ return;
+
rtw89_phy_write32_idx(rtwdev, dig_regs->p0_p20_pagcugc_en.addr,
dig_regs->p0_p20_pagcugc_en.mask, enable, bb->phy_idx);
rtw89_phy_write32_idx(rtwdev, dig_regs->p0_s20_pagcugc_en.addr,
@@ -7762,6 +8082,7 @@ static void rtw89_phy_edcca_log(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *b
bool flag_fb, flag_p20, flag_s20, flag_s40, flag_s80;
s8 pwdb_fb, pwdb_p20, pwdb_s20, pwdb_s40, pwdb_s80;
u8 path, per20_bitmap = 0;
+ u8 pwdb_sel = 5;
u8 pwdb[8];
u32 tmp;
@@ -7773,12 +8094,14 @@ static void rtw89_phy_edcca_log(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *b
else
edcca_p_regs = &edcca_regs->p[RTW89_PHY_0];
- if (rtwdev->chip->chip_id == RTL8922A)
- rtw89_phy_write32_mask(rtwdev, edcca_regs->rpt_sel_be,
- edcca_regs->rpt_sel_be_mask, 0);
-
rtw89_phy_write32_mask(rtwdev, edcca_p_regs->rpt_sel,
edcca_p_regs->rpt_sel_mask, 0);
+ if (rtwdev->chip->chip_id == RTL8922A || rtwdev->chip->chip_id == RTL8922D) {
+ rtw89_phy_write32_mask(rtwdev, edcca_regs->rpt_sel_be,
+ edcca_regs->rpt_sel_be_mask, 0);
+ per20_bitmap = rtw89_phy_read32_mask(rtwdev, edcca_p_regs->rpt_a,
+ MASKBYTE0);
+ }
tmp = rtw89_phy_read32(rtwdev, edcca_p_regs->rpt_b);
path = u32_get_bits(tmp, B_EDCCA_RPT_B_PATH_MASK);
flag_s80 = u32_get_bits(tmp, B_EDCCA_RPT_B_S80);
@@ -7790,13 +8113,16 @@ static void rtw89_phy_edcca_log(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *b
pwdb_p20 = u32_get_bits(tmp, MASKBYTE2);
pwdb_fb = u32_get_bits(tmp, MASKBYTE3);
+ if (rtwdev->chip->chip_id == RTL8922D)
+ pwdb_sel = 2;
+
rtw89_phy_write32_mask(rtwdev, edcca_p_regs->rpt_sel,
- edcca_p_regs->rpt_sel_mask, 5);
+ edcca_p_regs->rpt_sel_mask, pwdb_sel);
tmp = rtw89_phy_read32(rtwdev, edcca_p_regs->rpt_b);
pwdb_s80 = u32_get_bits(tmp, MASKBYTE1);
pwdb_s40 = u32_get_bits(tmp, MASKBYTE2);
- if (rtwdev->chip->chip_id == RTL8922A) {
+ if (rtwdev->chip->chip_id == RTL8922A || rtwdev->chip->chip_id == RTL8922D) {
rtw89_phy_write32_mask(rtwdev, edcca_regs->rpt_sel_be,
edcca_regs->rpt_sel_be_mask, 4);
tmp = rtw89_phy_read32(rtwdev, edcca_p_regs->rpt_b);
@@ -7804,8 +8130,6 @@ static void rtw89_phy_edcca_log(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *b
pwdb[1] = u32_get_bits(tmp, MASKBYTE2);
pwdb[2] = u32_get_bits(tmp, MASKBYTE1);
pwdb[3] = u32_get_bits(tmp, MASKBYTE0);
- per20_bitmap = rtw89_phy_read32_mask(rtwdev, edcca_p_regs->rpt_a,
- MASKBYTE0);
rtw89_phy_write32_mask(rtwdev, edcca_regs->rpt_sel_be,
edcca_regs->rpt_sel_be_mask, 5);
@@ -8027,6 +8351,7 @@ static const struct rtw89_ccx_regs rtw89_ccx_regs_ax = {
.ifs_clm_ofdm_fa_mask = B_IFS_CLM_OFDM_FA_MSK,
.ifs_clm_cck_fa_mask = B_IFS_CLM_CCK_FA_MSK,
.ifs_his_addr = R_IFS_HIS,
+ .ifs_his_addr2 = R_IFS_HIS,
.ifs_t4_his_mask = B_IFS_T4_HIS_MSK,
.ifs_t3_his_mask = B_IFS_T3_HIS_MSK,
.ifs_t2_his_mask = B_IFS_T2_HIS_MSK,
@@ -8072,9 +8397,12 @@ static const struct rtw89_cfo_regs rtw89_cfo_regs_ax = {
const struct rtw89_phy_gen_def rtw89_phy_gen_ax = {
.cr_base = 0x10000,
+ .physt_bmp_start = R_PHY_STS_BITMAP_ADDR_START,
+ .physt_bmp_eht = 0xfc,
.ccx = &rtw89_ccx_regs_ax,
.physts = &rtw89_physts_regs_ax,
.cfo = &rtw89_cfo_regs_ax,
+ .bb_wrap = NULL,
.phy0_phy1_offset = rtw89_phy0_phy1_offset_ax,
.config_bb_gain = rtw89_phy_config_bb_gain_ax,
.preinit_rf_nctl = rtw89_phy_preinit_rf_nctl_ax,
diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index 9caacffd0af8..ab263738d212 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -139,7 +139,9 @@ enum rtw89_phy_c2h_ra_func {
RTW89_PHY_C2H_FUNC_STS_RPT,
RTW89_PHY_C2H_FUNC_MU_GPTBL_RPT,
RTW89_PHY_C2H_FUNC_TXSTS,
- RTW89_PHY_C2H_FUNC_RA_MAX,
+ RTW89_PHY_C2H_FUNC_ACCELERATE_EN = 0x7,
+
+ RTW89_PHY_C2H_FUNC_RA_NUM,
};
enum rtw89_phy_c2h_rfk_log_func {
@@ -150,6 +152,8 @@ enum rtw89_phy_c2h_rfk_log_func {
RTW89_PHY_C2H_RFK_LOG_FUNC_TSSI = 4,
RTW89_PHY_C2H_RFK_LOG_FUNC_TXGAPK = 5,
RTW89_PHY_C2H_RFK_LOG_FUNC_TAS_PWR = 9,
+ RTW89_PHY_C2H_RFK_LOG_FUNC_TXIQK = 0xc,
+ RTW89_PHY_C2H_RFK_LOG_FUNC_CIM3K = 0xe,
RTW89_PHY_C2H_RFK_LOG_FUNC_NUM,
};
@@ -165,6 +169,8 @@ enum rtw89_phy_c2h_dm_func {
RTW89_PHY_C2H_DM_FUNC_SIGB,
RTW89_PHY_C2H_DM_FUNC_LOWRT_RTY,
RTW89_PHY_C2H_DM_FUNC_MCC_DIG,
+ RTW89_PHY_C2H_DM_FUNC_LPS = 0x9,
+ RTW89_PHY_C2H_DM_FUNC_ENV_MNTR = 0xa,
RTW89_PHY_C2H_DM_FUNC_FW_SCAN = 0xc,
RTW89_PHY_C2H_DM_FUNC_NUM,
};
@@ -416,6 +422,7 @@ struct rtw89_ccx_regs {
u32 ifs_clm_ofdm_fa_mask;
u32 ifs_clm_cck_fa_mask;
u32 ifs_his_addr;
+ u32 ifs_his_addr2;
u32 ifs_t4_his_mask;
u32 ifs_t3_his_mask;
u32 ifs_t2_his_mask;
@@ -459,6 +466,11 @@ struct rtw89_cfo_regs {
u32 valid_0_mask;
};
+struct rtw89_bb_wrap_regs {
+ u32 pwr_macid_lmt;
+ u32 pwr_macid_path;
+};
+
enum rtw89_bandwidth_section_num_ax {
RTW89_BW20_SEC_NUM_AX = 8,
RTW89_BW40_SEC_NUM_AX = 4,
@@ -531,9 +543,12 @@ struct rtw89_phy_rfk_log_fmt {
struct rtw89_phy_gen_def {
u32 cr_base;
+ u32 physt_bmp_start;
+ u32 physt_bmp_eht;
const struct rtw89_ccx_regs *ccx;
const struct rtw89_physts_regs *physts;
const struct rtw89_cfo_regs *cfo;
+ const struct rtw89_bb_wrap_regs *bb_wrap;
u32 (*phy0_phy1_offset)(struct rtw89_dev *rtwdev, u32 addr);
void (*config_bb_gain)(struct rtw89_dev *rtwdev,
const struct rtw89_reg2_def *reg,
@@ -559,6 +574,7 @@ struct rtw89_phy_gen_def {
extern const struct rtw89_phy_gen_def rtw89_phy_gen_ax;
extern const struct rtw89_phy_gen_def rtw89_phy_gen_be;
+extern const struct rtw89_phy_gen_def rtw89_phy_gen_be_v1;
static inline void rtw89_phy_write8(struct rtw89_dev *rtwdev,
u32 addr, u8 data)
@@ -823,12 +839,16 @@ u32 rtw89_phy_read_rf_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
u32 addr, u32 mask);
u32 rtw89_phy_read_rf_v2(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
u32 addr, u32 mask);
+u32 rtw89_phy_read_rf_v3(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
+ u32 addr, u32 mask);
bool rtw89_phy_write_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
u32 addr, u32 mask, u32 data);
bool rtw89_phy_write_rf_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
u32 addr, u32 mask, u32 data);
bool rtw89_phy_write_rf_v2(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
u32 addr, u32 mask, u32 data);
+bool rtw89_phy_write_rf_v3(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
+ u32 addr, u32 mask, u32 data);
void rtw89_phy_init_bb_reg(struct rtw89_dev *rtwdev);
void rtw89_phy_init_bb_afe(struct rtw89_dev *rtwdev);
void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev, bool noio);
@@ -879,6 +899,12 @@ static inline void rtw89_phy_bb_wrap_init(struct rtw89_dev *rtwdev)
phy->bb_wrap_init(rtwdev);
}
+void rtw89_phy_bb_wrap_set_rfsi_ct_opt(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx);
+void rtw89_phy_bb_wrap_set_rfsi_bandedge_ch(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx);
+
static inline void rtw89_phy_ch_info_init(struct rtw89_dev *rtwdev)
{
const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
@@ -1010,6 +1036,14 @@ int rtw89_phy_rfk_rxdck_and_wait(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx,
const struct rtw89_chan *chan,
bool is_chl_k, unsigned int ms);
+int rtw89_phy_rfk_txiqk_and_wait(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx,
+ const struct rtw89_chan *chan,
+ unsigned int ms);
+int rtw89_phy_rfk_cim3k_and_wait(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx,
+ const struct rtw89_chan *chan,
+ unsigned int ms);
void rtw89_phy_rfk_tssi_fill_fwcmd_efuse_to_de(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy,
const struct rtw89_chan *chan,
diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c
index bd17714f13d1..08fd24a55d85 100644
--- a/drivers/net/wireless/realtek/rtw89/phy_be.c
+++ b/drivers/net/wireless/realtek/rtw89/phy_be.c
@@ -2,6 +2,7 @@
/* Copyright(c) 2023 Realtek Corporation
*/
+#include "chan.h"
#include "debug.h"
#include "mac.h"
#include "phy.h"
@@ -44,6 +45,7 @@ static const struct rtw89_ccx_regs rtw89_ccx_regs_be = {
.ifs_clm_ofdm_fa_mask = B_IFS_CLM_OFDM_FA_MSK,
.ifs_clm_cck_fa_mask = B_IFS_CLM_CCK_FA_MSK,
.ifs_his_addr = R_IFS_HIS_V1,
+ .ifs_his_addr2 = R_IFS_HIS_V1,
.ifs_t4_his_mask = B_IFS_T4_HIS_MSK,
.ifs_t3_his_mask = B_IFS_T3_HIS_MSK,
.ifs_t2_his_mask = B_IFS_T2_HIS_MSK,
@@ -74,17 +76,99 @@ static const struct rtw89_ccx_regs rtw89_ccx_regs_be = {
.nhm_pwr_method_msk = B_NHM_PWDB_METHOD_MSK,
};
+static const struct rtw89_ccx_regs rtw89_ccx_regs_be_v1 = {
+ .setting_addr = R_CCX_BE4,
+ .edcca_opt_mask = B_CCX_EDCCA_OPT_MSK_V1,
+ .measurement_trig_mask = B_MEASUREMENT_TRIG_MSK,
+ .trig_opt_mask = B_CCX_TRIG_OPT_MSK,
+ .en_mask = B_CCX_EN_MSK,
+ .ifs_cnt_addr = R_IFS_COUNTER_BE4,
+ .ifs_clm_period_mask = B_IFS_CLM_PERIOD_MSK,
+ .ifs_clm_cnt_unit_mask = B_IFS_CLM_COUNTER_UNIT_MSK,
+ .ifs_clm_cnt_clear_mask = B_IFS_COUNTER_CLR_MSK,
+ .ifs_collect_en_mask = B_IFS_COLLECT_EN,
+ .ifs_t1_addr = R_IFS_T1_BE4,
+ .ifs_t1_th_h_mask = B_IFS_T1_TH_HIGH_MSK,
+ .ifs_t1_en_mask = B_IFS_T1_EN_MSK,
+ .ifs_t1_th_l_mask = B_IFS_T1_TH_LOW_MSK,
+ .ifs_t2_addr = R_IFS_T2_BE4,
+ .ifs_t2_th_h_mask = B_IFS_T2_TH_HIGH_MSK,
+ .ifs_t2_en_mask = B_IFS_T2_EN_MSK,
+ .ifs_t2_th_l_mask = B_IFS_T2_TH_LOW_MSK,
+ .ifs_t3_addr = R_IFS_T3_BE4,
+ .ifs_t3_th_h_mask = B_IFS_T3_TH_HIGH_MSK,
+ .ifs_t3_en_mask = B_IFS_T3_EN_MSK,
+ .ifs_t3_th_l_mask = B_IFS_T3_TH_LOW_MSK,
+ .ifs_t4_addr = R_IFS_T4_BE4,
+ .ifs_t4_th_h_mask = B_IFS_T4_TH_HIGH_MSK,
+ .ifs_t4_en_mask = B_IFS_T4_EN_MSK,
+ .ifs_t4_th_l_mask = B_IFS_T4_TH_LOW_MSK,
+ .ifs_clm_tx_cnt_addr = R_IFS_CLM_TX_CNT_BE4,
+ .ifs_clm_edcca_excl_cca_fa_mask = B_IFS_CLM_EDCCA_EXCLUDE_CCA_FA_MSK,
+ .ifs_clm_tx_cnt_msk = B_IFS_CLM_TX_CNT_MSK,
+ .ifs_clm_cca_addr = R_IFS_CLM_CCA_BE4,
+ .ifs_clm_ofdmcca_excl_fa_mask = B_IFS_CLM_OFDMCCA_EXCLUDE_FA_MSK,
+ .ifs_clm_cckcca_excl_fa_mask = B_IFS_CLM_CCKCCA_EXCLUDE_FA_MSK,
+ .ifs_clm_fa_addr = R_IFS_CLM_FA_BE4,
+ .ifs_clm_ofdm_fa_mask = B_IFS_CLM_OFDM_FA_MSK,
+ .ifs_clm_cck_fa_mask = B_IFS_CLM_CCK_FA_MSK,
+ .ifs_his_addr = R_IFS_T1_HIS_BE4,
+ .ifs_his_addr2 = R_IFS_T3_HIS_BE4, /* for 3/4 */
+ .ifs_t4_his_mask = B_IFS_T4_HIS_BE4,
+ .ifs_t3_his_mask = B_IFS_T3_HIS_BE4,
+ .ifs_t2_his_mask = B_IFS_T2_HIS_BE4,
+ .ifs_t1_his_mask = B_IFS_T1_HIS_BE4,
+ .ifs_avg_l_addr = R_IFS_T1_AVG_BE4,
+ .ifs_t2_avg_mask = B_IFS_T2_AVG_BE4,
+ .ifs_t1_avg_mask = B_IFS_T1_AVG_BE4,
+ .ifs_avg_h_addr = R_IFS_T3_AVG_BE4,
+ .ifs_t4_avg_mask = B_IFS_T4_AVG_BE4,
+ .ifs_t3_avg_mask = B_IFS_T3_AVG_BE4,
+ .ifs_cca_l_addr = R_IFS_T1_CLM_BE4,
+ .ifs_t2_cca_mask = B_IFS_T2_CLM_BE4,
+ .ifs_t1_cca_mask = B_IFS_T1_CLM_BE4,
+ .ifs_cca_h_addr = R_IFS_T3_CLM_BE4,
+ .ifs_t4_cca_mask = B_IFS_T4_CLM_BE4,
+ .ifs_t3_cca_mask = B_IFS_T3_CLM_BE4,
+ .ifs_total_addr = R_IFS_TOTAL_BE4,
+ .ifs_cnt_done_mask = B_IFS_CNT_DONE_BE4,
+ .ifs_total_mask = B_IFS_TOTAL_BE4,
+};
+
static const struct rtw89_physts_regs rtw89_physts_regs_be = {
.setting_addr = R_PLCP_HISTOGRAM,
.dis_trigger_fail_mask = B_STS_DIS_TRIG_BY_FAIL,
.dis_trigger_brk_mask = B_STS_DIS_TRIG_BY_BRK,
};
+static const struct rtw89_physts_regs rtw89_physts_regs_be_v1 = {
+ .setting_addr = R_PLCP_HISTOGRAM_BE_V1,
+ .dis_trigger_fail_mask = B_STS_DIS_TRIG_BY_FAIL,
+ .dis_trigger_brk_mask = B_STS_DIS_TRIG_BY_BRK,
+};
+
static const struct rtw89_cfo_regs rtw89_cfo_regs_be = {
- .comp = R_DCFO_WEIGHT_V1,
- .weighting_mask = B_DCFO_WEIGHT_MSK_V1,
- .comp_seg0 = R_DCFO_OPT_V1,
- .valid_0_mask = B_DCFO_OPT_EN_V1,
+ .comp = R_DCFO_WEIGHT_BE,
+ .weighting_mask = B_DCFO_WEIGHT_MSK_BE,
+ .comp_seg0 = R_DCFO_OPT_BE,
+ .valid_0_mask = B_DCFO_OPT_EN_BE,
+};
+
+static const struct rtw89_cfo_regs rtw89_cfo_regs_be_v1 = {
+ .comp = R_DCFO_WEIGHT_BE_V1,
+ .weighting_mask = B_DCFO_WEIGHT_MSK_BE,
+ .comp_seg0 = R_DCFO_OPT_BE_V1,
+ .valid_0_mask = B_DCFO_OPT_EN_BE,
+};
+
+static const struct rtw89_bb_wrap_regs rtw89_bb_wrap_regs_be = {
+ .pwr_macid_lmt = R_BE_PWR_MACID_LMT_BASE,
+ .pwr_macid_path = R_BE_PWR_MACID_PATH_BASE,
+};
+
+static const struct rtw89_bb_wrap_regs rtw89_bb_wrap_regs_be_v1 = {
+ .pwr_macid_lmt = R_BE_PWR_MACID_LMT_BASE_V1,
+ .pwr_macid_path = R_BE_PWR_MACID_PATH_BASE_V1,
};
static u32 rtw89_phy0_phy1_offset_be(struct rtw89_dev *rtwdev, u32 addr)
@@ -105,6 +189,25 @@ static u32 rtw89_phy0_phy1_offset_be(struct rtw89_dev *rtwdev, u32 addr)
return ofst;
}
+static u32 rtw89_phy0_phy1_offset_be_v1(struct rtw89_dev *rtwdev, u32 addr)
+{
+ u32 phy_page = addr >> 8;
+ u32 ofst = 0;
+
+ if ((phy_page >= 0x204 && phy_page <= 0x20F) ||
+ (phy_page >= 0x220 && phy_page <= 0x22F) ||
+ (phy_page >= 0x240 && phy_page <= 0x24f) ||
+ (phy_page >= 0x260 && phy_page <= 0x26f) ||
+ (phy_page >= 0x2C0 && phy_page <= 0x2C9) ||
+ (phy_page >= 0x2E4 && phy_page <= 0x2E8) ||
+ phy_page == 0x2EE)
+ ofst = 0x1000;
+ else
+ ofst = 0x0;
+
+ return ofst;
+}
+
union rtw89_phy_bb_gain_arg_be {
u32 addr;
struct {
@@ -301,40 +404,101 @@ static void rtw89_phy_preinit_rf_nctl_be(struct rtw89_dev *rtwdev)
}
}
+static void rtw89_phy_preinit_rf_nctl_be_v1(struct rtw89_dev *rtwdev)
+{
+ rtw89_phy_write32_mask(rtwdev, R_GOTX_IQKDPK_C0_BE4, B_GOTX_IQKDPK, 0x3);
+ rtw89_phy_write32_mask(rtwdev, R_GOTX_IQKDPK_C1_BE4, B_GOTX_IQKDPK, 0x3);
+ rtw89_phy_write32_mask(rtwdev, R_IOQ_IQK_DPK_BE4, B_IOQ_IQK_DPK_RST, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DPK_RST_BE4, B_IQK_DPK_RST, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DPK_PRST_BE4, B_IQK_DPK_PRST, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DPK_PRST_C1_BE4, B_IQK_DPK_PRST, 0x1);
+}
+
+static u32 rtw89_phy_bb_wrap_flush_addr(struct rtw89_dev *rtwdev, u32 addr)
+{
+ struct rtw89_hal *hal = &rtwdev->hal;
+
+ if (!test_bit(RTW89_FLAG_RUNNING, rtwdev->flags))
+ return 0;
+
+ if (rtwdev->chip->chip_id == RTL8922D && hal->cid == RTL8922D_CID7025) {
+ if (addr >= R_BE_PWR_MACID_PATH_BASE_V1 &&
+ addr <= R_BE_PWR_MACID_PATH_BASE_V1 + 0xFF)
+ return addr + 0x800;
+
+ if (addr >= R_BE_PWR_MACID_LMT_BASE_V1 &&
+ addr <= R_BE_PWR_MACID_LMT_BASE_V1 + 0xFF)
+ return addr - 0x800;
+ }
+
+ return 0;
+}
+
+static
+void rtw89_write_bb_wrap_flush(struct rtw89_dev *rtwdev, u32 addr, u32 data)
+{
+ /* To write registers of pwr_macid_lmt and pwr_macid_path with flush */
+ u32 flush_addr;
+ u32 val32;
+
+ flush_addr = rtw89_phy_bb_wrap_flush_addr(rtwdev, addr);
+ if (flush_addr) {
+ val32 = rtw89_read32(rtwdev, flush_addr);
+ rtw89_write32(rtwdev, flush_addr, val32);
+ }
+
+ rtw89_write32(rtwdev, addr, data);
+}
+
static
void rtw89_phy_bb_wrap_pwr_by_macid_init(struct rtw89_dev *rtwdev)
{
- u32 macid_idx, cr, base_macid_lmt, max_macid = 32;
+ const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
+ const struct rtw89_bb_wrap_regs *bb_wrap = phy->bb_wrap;
+ u32 max_macid = rtwdev->chip->support_macid_num;
+ u32 macid_idx, cr, base_macid_lmt;
- base_macid_lmt = R_BE_PWR_MACID_LMT_BASE;
+ base_macid_lmt = bb_wrap->pwr_macid_lmt;
for (macid_idx = 0; macid_idx < 4 * max_macid; macid_idx += 4) {
cr = base_macid_lmt + macid_idx;
- rtw89_write32(rtwdev, cr, 0x03007F7F);
+ rtw89_write_bb_wrap_flush(rtwdev, cr, 0);
}
}
static
void rtw89_phy_bb_wrap_tx_path_by_macid_init(struct rtw89_dev *rtwdev)
{
- int i, max_macid = 32;
- u32 cr = R_BE_PWR_MACID_PATH_BASE;
+ const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
+ const struct rtw89_bb_wrap_regs *bb_wrap = phy->bb_wrap;
+ u32 max_macid = rtwdev->chip->support_macid_num;
+ u32 cr = bb_wrap->pwr_macid_path;
+ int i;
for (i = 0; i < max_macid; i++, cr += 4)
- rtw89_write32(rtwdev, cr, 0x03C86000);
+ rtw89_write_bb_wrap_flush(rtwdev, cr, 0);
}
static void rtw89_phy_bb_wrap_tpu_set_all(struct rtw89_dev *rtwdev,
enum rtw89_mac_idx mac_idx)
{
- u32 addr;
+ u32 addr, t;
- for (addr = R_BE_PWR_BY_RATE; addr <= R_BE_PWR_BY_RATE_END; addr += 4)
- rtw89_write32(rtwdev, addr, 0);
- for (addr = R_BE_PWR_RULMT_START; addr <= R_BE_PWR_RULMT_END; addr += 4)
- rtw89_write32(rtwdev, addr, 0);
- for (addr = R_BE_PWR_RATE_OFST_CTRL; addr <= R_BE_PWR_RATE_OFST_END; addr += 4)
- rtw89_write32(rtwdev, addr, 0);
+ addr = rtw89_mac_reg_by_idx(rtwdev, R_BE_PWR_FTM_SS, mac_idx);
+ rtw89_write32_mask(rtwdev, addr, B_BE_PWR_BY_RATE_DBW_ON, 0x3);
+
+ for (addr = R_BE_PWR_BY_RATE; addr <= R_BE_PWR_BY_RATE_END; addr += 4) {
+ t = rtw89_mac_reg_by_idx(rtwdev, addr, mac_idx);
+ rtw89_write32(rtwdev, t, 0);
+ }
+ for (addr = R_BE_PWR_RULMT_START; addr <= R_BE_PWR_RULMT_END; addr += 4) {
+ t = rtw89_mac_reg_by_idx(rtwdev, addr, mac_idx);
+ rtw89_write32(rtwdev, t, 0);
+ }
+ for (addr = R_BE_PWR_RATE_OFST_CTRL; addr <= R_BE_PWR_RATE_OFST_END; addr += 4) {
+ t = rtw89_mac_reg_by_idx(rtwdev, addr, mac_idx);
+ rtw89_write32(rtwdev, t, 0);
+ }
addr = rtw89_mac_reg_by_idx(rtwdev, R_BE_PWR_REF_CTRL, mac_idx);
rtw89_write32_mask(rtwdev, addr, B_BE_PWR_OFST_LMT_DB, 0);
@@ -394,6 +558,332 @@ static void rtw89_phy_bb_wrap_ftm_init(struct rtw89_dev *rtwdev,
rtw89_write32_mask(rtwdev, addr, 0x7, 0);
}
+static u32 rtw89_phy_bb_wrap_be_bandedge_decision(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan)
+{
+ u8 pri_ch = chan->primary_channel;
+ u32 val = 0;
+
+ switch (chan->band_type) {
+ default:
+ case RTW89_BAND_2G:
+ if (pri_ch == 1 || pri_ch == 13)
+ val = BIT(1) | BIT(0);
+ else if (pri_ch == 3 || pri_ch == 11)
+ val = BIT(1);
+ break;
+ case RTW89_BAND_5G:
+ if (pri_ch == 36 || pri_ch == 64 || pri_ch == 100)
+ val = BIT(3) | BIT(2) | BIT(1) | BIT(0);
+ else if (pri_ch == 40 || pri_ch == 60 || pri_ch == 104)
+ val = BIT(3) | BIT(2) | BIT(1);
+ else if ((pri_ch > 40 && pri_ch < 60) || pri_ch == 108 || pri_ch == 112)
+ val = BIT(3) | BIT(2);
+ else if (pri_ch > 112 && pri_ch < 132)
+ val = BIT(3);
+ break;
+ case RTW89_BAND_6G:
+ if (pri_ch == 233)
+ val = BIT(0);
+ break;
+ }
+
+ return val;
+}
+
+void rtw89_phy_bb_wrap_set_rfsi_ct_opt(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx)
+{
+ u32 reg;
+
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_RFSI_CT_OPT_0_BE4, phy_idx);
+ rtw89_write32(rtwdev, reg, 0x00010001);
+
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_RFSI_CT_OPT_8_BE4, phy_idx);
+ rtw89_write32(rtwdev, reg, 0x00010001);
+}
+EXPORT_SYMBOL(rtw89_phy_bb_wrap_set_rfsi_ct_opt);
+
+void rtw89_phy_bb_wrap_set_rfsi_bandedge_ch(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ u32 reg;
+ u32 val;
+
+ val = rtw89_phy_bb_wrap_be_bandedge_decision(rtwdev, chan);
+
+ rtw89_phy_write32_idx(rtwdev, R_TX_CFR_MANUAL_EN_BE4, B_TX_CFR_MANUAL_EN_BE4_M,
+ chan->primary_channel == 13, phy_idx);
+
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_BANDEDGE_DBWX_BE4, phy_idx);
+ rtw89_write32_mask(rtwdev, reg, B_BANDEDGE_DBW20_BE4, val & BIT(0));
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_BANDEDGE_DBWX_BE4, phy_idx);
+ rtw89_write32_mask(rtwdev, reg, B_BANDEDGE_DBW40_BE4, (val & BIT(1)) >> 1);
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_BANDEDGE_DBWX_BE4, phy_idx);
+ rtw89_write32_mask(rtwdev, reg, B_BANDEDGE_DBW80_BE4, (val & BIT(2)) >> 2);
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_BANDEDGE_DBWY_BE4, phy_idx);
+ rtw89_write32_mask(rtwdev, reg, B_BANDEDGE_DBW160_BE4, (val & BIT(3)) >> 3);
+}
+EXPORT_SYMBOL(rtw89_phy_bb_wrap_set_rfsi_bandedge_ch);
+
+static void rtw89_phy_bb_wrap_tx_rfsi_qam_comp_th_init(struct rtw89_dev *rtwdev,
+ enum rtw89_mac_idx mac_idx)
+{
+ /* TH0 */
+ rtw89_write32_idx(rtwdev, R_QAM_TH0_BE4, B_QAM_TH0_0_BE4, 0x1, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_TH0_BE4, B_QAM_TH0_3_BE4, 0x1, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_1_BE4, 0x1, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_4_BE4, 0x1, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_7_BE4, 0x1, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_0_BE4, 0x1, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_3_BE4, 0x1, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_6_BE4, 0x1, mac_idx);
+ /* TH1 */
+ rtw89_write32_idx(rtwdev, R_QAM_TH0_BE4, B_QAM_TH0_1_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_TH0_BE4, B_QAM_TH0_4_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_2_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_5_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_8_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_1_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_4_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_7_BE4, 0x2, mac_idx);
+ /* TH2 */
+ rtw89_write32_idx(rtwdev, R_QAM_TH0_BE4, B_QAM_TH0_2_BE4, 0x4, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_0_BE4, 0x4, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_3_BE4, 0x4, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_6_BE4, 0x4, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_9_BE4, 0x4, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_2_BE4, 0x4, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_5_BE4, 0x4, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_8_BE4, 0x4, mac_idx);
+ /* DPD 160M */
+ rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH0_BE4, B_DPD_DBW160_TH0_0_BE4, 0x1, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH0_BE4, B_DPD_DBW160_TH0_1_BE4, 0x1, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH0_BE4, B_DPD_DBW160_TH0_2_BE4, 0x1, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH0_BE4, B_DPD_DBW160_TH0_3_BE4, 0x1, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH0_BE4, B_DPD_DBW160_TH0_4_BE4, 0x1, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH1_BE4, B_DPD_DBW160_TH1_5_BE4, 0x1, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH1_BE4, B_DPD_DBW160_TH1_6_BE4, 0x1, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH1_BE4, B_DPD_DBW160_TH1_7_BE4, 0x1, mac_idx);
+ /* DPD 20M */
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH0_BE4, B_DPD_CBW20_TH0_0_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH0_BE4, B_DPD_CBW20_TH0_1_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH0_BE4, B_DPD_CBW20_TH0_2_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH0_BE4, B_DPD_CBW20_TH0_3_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH0_BE4, B_DPD_CBW20_TH0_4_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH0_BE4, B_DPD_CBW20_TH0_5_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH0_BE4, B_DPD_CBW20_TH0_6_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH1_BE4, B_DPD_CBW20_TH1_7_BE4, 0x2, mac_idx);
+ /* DPD 40M */
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH1_BE4, B_DPD_CBW40_TH1_0_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH1_BE4, B_DPD_CBW40_TH1_1_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH1_BE4, B_DPD_CBW40_TH1_2_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH1_BE4, B_DPD_CBW40_TH1_3_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH1_BE4, B_DPD_CBW40_TH1_4_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH1_BE4, B_DPD_CBW20_TH0_3_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH1_BE4, B_DPD_CBW20_TH0_4_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH1_BE4, B_DPD_CBW20_TH0_5_BE4, 0x2, mac_idx);
+ /* DPD 80M */
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH1_BE4, B_DPD_CBW80_TH1_0_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH2_BE4, B_DPD_CBW80_TH2_1_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH2_BE4, B_DPD_CBW80_TH2_2_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH2_BE4, B_DPD_CBW80_TH2_3_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH2_BE4, B_DPD_CBW80_TH2_4_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH2_BE4, B_DPD_CBW80_TH2_5_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH2_BE4, B_DPD_CBW80_TH2_6_BE4, 0x2, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW_TH2_BE4, B_DPD_CBW80_TH2_7_BE4, 0x2, mac_idx);
+ /* CIM3K */
+ rtw89_write32_idx(rtwdev, R_COMP_CIM3K_BE4, B_COMP_CIM3K_TH2_BE4, 0x2, mac_idx);
+}
+
+static void rtw89_phy_bb_wrap_tx_rfsi_scenario_def(struct rtw89_dev *rtwdev,
+ enum rtw89_mac_idx mac_idx)
+{
+ rtw89_write32_idx(rtwdev, R_RFSI_CT_DEF_BE4, B_RFSI_CT_ER_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_RFSI_CT_DEF_BE4, B_RFSI_CT_SUBF_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_RFSI_CT_DEF_BE4, B_RFSI_CT_FTM_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_RFSI_CT_DEF_BE4, B_RFSI_CT_SENS_BE4, 0x0, mac_idx);
+
+ rtw89_write32_idx(rtwdev, R_FBTB_CT_DEF_BE4, B_FBTB_CT_DEF_BE, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_FBTB_CT_DEF_BE4, B_FBTB_CT_PB_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_FBTB_CT_DEF_BE4, B_FBTB_CT_DL_WO_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_FBTB_CT_DEF_BE4, B_FBTB_CT_DL_BF_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_FBTB_CT_DEF_BE4, B_FBTB_CT_MUMIMO_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_FBTB_CT_DEF_BE4, B_FBTB_CT_FTM_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_FBTB_CT_DEF_BE4, B_FBTB_CT_SENS_BE4, 0x0, mac_idx);
+}
+
+static void rtw89_phy_bb_wrap_tx_rfsi_qam_comp_val(struct rtw89_dev *rtwdev,
+ enum rtw89_mac_idx mac_idx)
+{
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH0_BE4, MASKLWORD, 0x4010, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH0_BE4, MASKHWORD, 0x4410, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH1_BE4, MASKLWORD, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH1_BE4, MASKHWORD, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH2_BE4, MASKLWORD, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH2_BE4, MASKHWORD, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH3_BE4, MASKLWORD, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH3_BE4, MASKHWORD, 0x0, mac_idx);
+
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_L, 0x8, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_M, 0x8, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_H, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_L, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_M, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_H, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH6_BE4, B_QAM_COMP_TH6_L, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH6_BE4, B_QAM_COMP_TH6_M, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_2L, 0x8, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_2M, 0x8, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_2H, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_2L, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_2M, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_2H, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH6_BE4, B_QAM_COMP_TH6_2L, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH6_BE4, B_QAM_COMP_TH6_2M, 0x0, mac_idx);
+
+ rtw89_write32_idx(rtwdev, R_OW_VAL_0_BE4, MASKLWORD, 0x4010, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OW_VAL_0_BE4, MASKHWORD, 0x4010, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OW_VAL_1_BE4, MASKLWORD, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OW_VAL_1_BE4, MASKHWORD, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OW_VAL_2_BE4, MASKLWORD, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OW_VAL_2_BE4, MASKHWORD, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OW_VAL_3_BE4, MASKLWORD, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OW_VAL_3_BE4, MASKHWORD, 0x0, mac_idx);
+}
+
+static void rtw89_phy_bb_set_oob_dpd_qam_comp_val(struct rtw89_dev *rtwdev,
+ enum rtw89_mac_idx mac_idx)
+{
+ rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK0_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK1_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK2_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK3_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK4_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK5_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK6_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK7_BE4, 0x0, mac_idx);
+
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK0_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK1_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK2_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK3_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK4_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK5_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK6_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK7_BE4, 0x0, mac_idx);
+
+ rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH0_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH1_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH2_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH3_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH4_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH5_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH6_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH7_BE4, 0x0, mac_idx);
+
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH0_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH1_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH2_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH3_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH4_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH5_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH6_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH7_BE4, 0x0, mac_idx);
+
+ rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH0_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH1_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH2_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH3_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH4_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH5_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH6_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH7_BE4, 0x0, mac_idx);
+
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW0_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW1_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW2_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW3_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW4_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW5_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW6_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW7_BE4, 0x0, mac_idx);
+
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW0_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW1_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW2_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW3_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW4_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW5_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW6_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW7_BE4, 0x0, mac_idx);
+
+ rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW0_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW1_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW2_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW3_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW4_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW5_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW6_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW7_BE4, 0x0, mac_idx);
+}
+
+static void rtw89_phy_bb_set_mdpd_qam_comp_val(struct rtw89_dev *rtwdev,
+ enum rtw89_mac_idx mac_idx)
+{
+ rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH0_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH1_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH2_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH3_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH4_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH5_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH6_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH7_BE4, 0x0, mac_idx);
+
+ rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW0_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW1_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW2_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW3_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW4_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW5_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW6_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW7_BE4, 0x0, mac_idx);
+}
+
+static void rtw89_phy_bb_set_cim3k_val(struct rtw89_dev *rtwdev,
+ enum rtw89_mac_idx mac_idx)
+{
+ rtw89_write32_idx(rtwdev, R_COMP_CIM3K_BE4, B_COMP_CIM3K_TH_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_COMP_CIM3K_BE4, B_COMP_CIM3K_OW_BE4, 0x0, mac_idx);
+ rtw89_write32_idx(rtwdev, R_COMP_CIM3K_BE4, B_COMP_CIM3K_NONBE_BE4, 0x1, mac_idx);
+ rtw89_write32_idx(rtwdev, R_COMP_CIM3K_BE4, B_COMP_CIM3K_BANDEDGE_BE4, 0x1, mac_idx);
+}
+
+static void rtw89_phy_bb_wrap_tx_rfsi_ctrl_init(struct rtw89_dev *rtwdev,
+ enum rtw89_mac_idx mac_idx)
+{
+ enum rtw89_phy_idx phy_idx = mac_idx != RTW89_MAC_0 ? RTW89_PHY_1 : RTW89_PHY_0;
+ enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
+ const struct rtw89_chan *chan;
+
+ if (chip_id != RTL8922D)
+ return;
+
+ rtw89_phy_bb_wrap_tx_rfsi_qam_comp_th_init(rtwdev, mac_idx);
+ rtw89_phy_bb_wrap_tx_rfsi_scenario_def(rtwdev, mac_idx);
+ rtw89_phy_bb_wrap_tx_rfsi_qam_comp_val(rtwdev, mac_idx);
+ rtw89_phy_bb_set_oob_dpd_qam_comp_val(rtwdev, mac_idx);
+ rtw89_phy_bb_set_mdpd_qam_comp_val(rtwdev, mac_idx);
+ rtw89_phy_bb_set_cim3k_val(rtwdev, mac_idx);
+
+ rtw89_phy_bb_wrap_set_rfsi_ct_opt(rtwdev, phy_idx);
+
+ chan = rtw89_mgnt_chan_get(rtwdev, phy_idx);
+ if (chan)
+ rtw89_phy_bb_wrap_set_rfsi_bandedge_ch(rtwdev, chan, phy_idx);
+}
+
static void rtw89_phy_bb_wrap_ul_pwr(struct rtw89_dev *rtwdev)
{
enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
@@ -414,12 +904,13 @@ static void rtw89_phy_bb_wrap_ul_pwr(struct rtw89_dev *rtwdev)
static void __rtw89_phy_bb_wrap_init_be(struct rtw89_dev *rtwdev,
enum rtw89_mac_idx mac_idx)
{
- rtw89_phy_bb_wrap_pwr_by_macid_init(rtwdev);
rtw89_phy_bb_wrap_tx_path_by_macid_init(rtwdev);
- rtw89_phy_bb_wrap_listen_path_en_init(rtwdev);
+ rtw89_phy_bb_wrap_pwr_by_macid_init(rtwdev);
+ rtw89_phy_bb_wrap_tpu_set_all(rtwdev, mac_idx);
+ rtw89_phy_bb_wrap_tx_rfsi_ctrl_init(rtwdev, mac_idx);
rtw89_phy_bb_wrap_force_cr_init(rtwdev, mac_idx);
rtw89_phy_bb_wrap_ftm_init(rtwdev, mac_idx);
- rtw89_phy_bb_wrap_tpu_set_all(rtwdev, mac_idx);
+ rtw89_phy_bb_wrap_listen_path_en_init(rtwdev);
rtw89_phy_bb_wrap_ul_pwr(rtwdev);
}
@@ -441,6 +932,14 @@ static void rtw89_phy_ch_info_init_be(struct rtw89_dev *rtwdev)
rtw89_phy_set_phy_regs(rtwdev, R_CHINFO_TYPE_SCAL, B_CHINFO_SCAL, 0x0);
}
+static void rtw89_phy_ch_info_init_be_v1(struct rtw89_dev *rtwdev)
+{
+ rtw89_phy_write32_mask(rtwdev, R_CHINFO_SEG_BE4, B_CHINFO_SEG_LEN_BE4, 0);
+ rtw89_phy_set_phy_regs(rtwdev, R_CHINFO_OPT_BE4, B_CHINFO_OPT_BE4, 0x3);
+ rtw89_phy_set_phy_regs(rtwdev, R_CHINFO_NX_BE4, B_CHINFO_NX_BE4, 0x669);
+ rtw89_phy_set_phy_regs(rtwdev, R_CHINFO_ALG_BE4, B_CHINFO_ALG_BE4, 0);
+}
+
struct rtw89_byr_spec_ent_be {
struct rtw89_rate_desc init;
u8 num_of_idx;
@@ -1004,9 +1503,12 @@ static void rtw89_phy_set_txpwr_limit_ru_be(struct rtw89_dev *rtwdev,
const struct rtw89_phy_gen_def rtw89_phy_gen_be = {
.cr_base = 0x20000,
+ .physt_bmp_start = R_PHY_STS_BITMAP_ADDR_START,
+ .physt_bmp_eht = R_PHY_STS_BITMAP_EHT,
.ccx = &rtw89_ccx_regs_be,
.physts = &rtw89_physts_regs_be,
.cfo = &rtw89_cfo_regs_be,
+ .bb_wrap = &rtw89_bb_wrap_regs_be,
.phy0_phy1_offset = rtw89_phy0_phy1_offset_be,
.config_bb_gain = rtw89_phy_config_bb_gain_be,
.preinit_rf_nctl = rtw89_phy_preinit_rf_nctl_be,
@@ -1019,3 +1521,24 @@ const struct rtw89_phy_gen_def rtw89_phy_gen_be = {
.set_txpwr_limit_ru = rtw89_phy_set_txpwr_limit_ru_be,
};
EXPORT_SYMBOL(rtw89_phy_gen_be);
+
+const struct rtw89_phy_gen_def rtw89_phy_gen_be_v1 = {
+ .cr_base = 0x0,
+ .physt_bmp_start = R_PHY_STS_BITMAP_ADDR_START_BE4,
+ .physt_bmp_eht = R_PHY_STS_BITMAP_EHT_BE4,
+ .ccx = &rtw89_ccx_regs_be_v1,
+ .physts = &rtw89_physts_regs_be_v1,
+ .cfo = &rtw89_cfo_regs_be_v1,
+ .bb_wrap = &rtw89_bb_wrap_regs_be_v1,
+ .phy0_phy1_offset = rtw89_phy0_phy1_offset_be_v1,
+ .config_bb_gain = rtw89_phy_config_bb_gain_be,
+ .preinit_rf_nctl = rtw89_phy_preinit_rf_nctl_be_v1,
+ .bb_wrap_init = rtw89_phy_bb_wrap_init_be,
+ .ch_info_init = rtw89_phy_ch_info_init_be_v1,
+
+ .set_txpwr_byrate = rtw89_phy_set_txpwr_byrate_be,
+ .set_txpwr_offset = rtw89_phy_set_txpwr_offset_be,
+ .set_txpwr_limit = rtw89_phy_set_txpwr_limit_be,
+ .set_txpwr_limit_ru = rtw89_phy_set_txpwr_limit_ru_be,
+};
+EXPORT_SYMBOL(rtw89_phy_gen_be_v1);
diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c
index 3f69dd4361c3..aad2ee7926d6 100644
--- a/drivers/net/wireless/realtek/rtw89/ps.c
+++ b/drivers/net/wireless/realtek/rtw89/ps.c
@@ -16,7 +16,7 @@
static int rtw89_fw_receive_lps_h2c_check(struct rtw89_dev *rtwdev, u8 macid)
{
- struct rtw89_mac_c2h_info c2h_info = {};
+ struct rtw89_mac_c2h_info c2h_info = {.timeout = 5000};
u16 c2hreg_macid;
u32 c2hreg_ret;
int ret;
@@ -189,6 +189,8 @@ void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
if (RTW89_CHK_FW_FEATURE(LPS_CH_INFO, &rtwdev->fw))
rtw89_fw_h2c_lps_ch_info(rtwdev, rtwvif);
+ else if (RTW89_CHK_FW_FEATURE(LPS_ML_INFO_V1, &rtwdev->fw))
+ rtw89_fw_h2c_lps_ml_cmn_info_v1(rtwdev, rtwvif);
else
rtw89_fw_h2c_lps_ml_cmn_info(rtwdev, rtwvif);
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 5b4a459cf29c..9b605617c3f0 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -149,6 +149,7 @@
#define R_AX_WLLPS_CTRL 0x0090
#define B_AX_LPSOP_ASWRM BIT(17)
#define B_AX_LPSOP_DSWRM BIT(9)
+#define B_AX_FORCE_LEAVE_LPS BIT(3)
#define B_AX_DIS_WLBT_LPSEN_LOPC BIT(1)
#define SW_LPS_OPTION 0x0001A0B2
@@ -313,13 +314,18 @@
#define R_AX_IC_PWR_STATE 0x03F0
#define B_AX_WHOLE_SYS_PWR_STE_MASK GENMASK(25, 16)
#define B_AX_WLMAC_PWR_STE_MASK GENMASK(9, 8)
+#define MAC_AX_MAC_OFF 0
+#define MAC_AX_MAC_ON 1
+#define MAC_AX_MAC_LPS 2
#define B_AX_UART_HCISYS_PWR_STE_MASK GENMASK(7, 6)
#define B_AX_SDIO_HCISYS_PWR_STE_MASK GENMASK(5, 4)
#define B_AX_USB_HCISYS_PWR_STE_MASK GENMASK(3, 2)
#define B_AX_PCIE_HCISYS_PWR_STE_MASK GENMASK(1, 0)
#define R_AX_SPS_DIG_OFF_CTRL0 0x0400
+#define B_AX_R1_L1_MASK GENMASK(7, 6)
#define B_AX_C3_L1_MASK GENMASK(5, 4)
+#define B_AX_C2_L1_MASK GENMASK(3, 2)
#define B_AX_C1_L1_MASK GENMASK(1, 0)
#define R_AX_AFE_OFF_CTRL1 0x0444
@@ -603,6 +609,9 @@
#define R_AX_SER_DBG_INFO 0x8424
#define B_AX_L0_TO_L1_EVENT_MASK GENMASK(31, 28)
+#define B_AX_SER_L1_COUNTER_MASK GENMASK(27, 24)
+#define B_AX_RMAC_PPDU_HANG_CNT_MASK GENMASK(23, 16)
+#define B_AX_SER_L0_COUNTER_MASK GENMASK(7, 0)
#define R_AX_DLE_EMPTY0 0x8430
#define B_AX_PLE_EMPTY_QTA_DMAC_CPUIO BIT(26)
@@ -1958,7 +1967,9 @@
#define B_AX_B0_PRELD_FEN BIT(31)
#define B_AX_B0_PRELD_USEMAXSZ_MASK GENMASK(25, 16)
#define PRELD_B0_ENT_NUM 10
+#define PRELD_B01_ENT_NUM_8922D 2
#define PRELD_AMSDU_SIZE 52
+#define PRELD_NEXT_MIN_SIZE 255
#define B_AX_B0_PRELD_CAM_G1ENTNUM_MASK GENMASK(12, 8)
#define B_AX_B0_PRELD_CAM_G0ENTNUM_MASK GENMASK(4, 0)
@@ -2094,6 +2105,7 @@
#define B_AX_B1_ISR_ERR_USRCTL_REINIT BIT(0)
#define R_AX_AFE_CTRL1 0x0024
+#define B_AX_CMAC_CLK_SEL BIT(21)
#define B_AX_R_SYM_WLCMAC1_P4_PC_EN BIT(4)
#define B_AX_R_SYM_WLCMAC1_P3_PC_EN BIT(3)
@@ -2107,6 +2119,12 @@
#define B_AX_R_SYM_FEN_WLBBFUN_1 BIT(16)
#define B_AX_R_SYM_ISO_CMAC12PP BIT(5)
+#define R_AX_SYSON_FSM_MON 0x00A0
+#define B_AX_FSM_MON_SEL_MASK GENMASK(26, 24)
+#define B_AX_DOP_ELDO BIT(23)
+#define B_AX_FSM_MON_UPD BIT(15)
+#define B_AX_FSM_PAR_MASK GENMASK(14, 0)
+
#define R_AX_CMAC_REG_START 0xC000
#define R_AX_CMAC_FUNC_EN 0xC000
@@ -3813,6 +3831,7 @@
#define B_BE_EN_WLON BIT(16)
#define B_BE_APDM_HPDN BIT(15)
#define B_BE_PSUS_OFF_CAPC_EN BIT(14)
+#define B_BE_USUS_OFFCAPC_EN BIT(13)
#define B_BE_AFSM_PCIE_SUS_EN BIT(12)
#define B_BE_AFSM_WLSUS_EN BIT(11)
#define B_BE_APFM_SWLPS BIT(10)
@@ -3881,6 +3900,8 @@
#define B_BE_SYM_PADPDN_WL_RFC0_1P3 BIT(5)
#define R_BE_RSV_CTRL 0x001C
+#define B_BE_R_SYM_PRST_CPHY_RST BIT(25)
+#define B_BE_R_SYM_PRST_PDN_EN BIT(24)
#define B_BE_HR_BE_DBG GENMASK(23, 12)
#define B_BE_R_SYM_DIS_PCIE_FLR BIT(9)
#define B_BE_R_EN_HRST_PWRON BIT(8)
@@ -3927,6 +3948,11 @@
#define B_BE_R_SYM_WLCMAC0_P2_PC_EN BIT(26)
#define B_BE_R_SYM_WLCMAC0_P1_PC_EN BIT(25)
#define B_BE_R_SYM_WLCMAC0_PC_EN BIT(24)
+#define B_BE_R_SYM_WLCMAC0_ALL_EN (B_BE_R_SYM_WLCMAC0_PC_EN | \
+ B_BE_R_SYM_WLCMAC0_P1_PC_EN | \
+ B_BE_R_SYM_WLCMAC0_P2_PC_EN | \
+ B_BE_R_SYM_WLCMAC0_P3_PC_EN | \
+ B_BE_R_SYM_WLCMAC0_P4_PC_EN)
#define B_BE_DATAMEM_PC3_EN BIT(23)
#define B_BE_DATAMEM_PC2_EN BIT(22)
#define B_BE_DATAMEM_PC1_EN BIT(21)
@@ -3948,11 +3974,11 @@
#define B_BE_R_SYM_WLCMAC1_P2_PC_EN BIT(2)
#define B_BE_R_SYM_WLCMAC1_P1_PC_EN BIT(1)
#define B_BE_R_SYM_WLCMAC1_PC_EN BIT(0)
-#define B_BE_AFE_CTRL1_SET (B_BE_R_SYM_WLCMAC1_PC_EN | \
- B_BE_R_SYM_WLCMAC1_P1_PC_EN | \
- B_BE_R_SYM_WLCMAC1_P2_PC_EN | \
- B_BE_R_SYM_WLCMAC1_P3_PC_EN | \
- B_BE_R_SYM_WLCMAC1_P4_PC_EN)
+#define B_BE_R_SYM_WLCMAC1_ALL_EN (B_BE_R_SYM_WLCMAC1_PC_EN | \
+ B_BE_R_SYM_WLCMAC1_P1_PC_EN | \
+ B_BE_R_SYM_WLCMAC1_P2_PC_EN | \
+ B_BE_R_SYM_WLCMAC1_P3_PC_EN | \
+ B_BE_R_SYM_WLCMAC1_P4_PC_EN)
#define R_BE_EFUSE_CTRL 0x0030
#define B_BE_EF_MODE_SEL_MASK GENMASK(31, 30)
@@ -4015,6 +4041,7 @@
#define R_BE_SYS_SDIO_CTRL 0x0070
#define B_BE_MCM_FLASH_EN BIT(28)
+#define B_BE_SER_DETECT_EN BIT(26)
#define B_BE_PCIE_SEC_LOAD BIT(26)
#define B_BE_PCIE_SER_RSTB BIT(25)
#define B_BE_PCIE_SEC_LOAD_CLR BIT(24)
@@ -4172,6 +4199,22 @@
#define B_BE_LPSROP_LOWPWRPLL BIT(7)
#define B_BE_LPSROP_DSWRSD_SEL_MASK GENMASK(5, 4)
+#define R_BE_SYSON_FSM_MON 0x00A0
+#define B_BE_FSM_MON_SEL_MASK GENMASK(26, 24)
+#define B_BE_DOP_ELDO BIT(23)
+#define B_BE_AFE_PLL_BYPASS BIT(22)
+#define B_BE_PON_SWR_BYPASS BIT(21)
+#define B_BE_PON_ADIE_BYPASS BIT(20)
+#define B_BE_AFE_LS_BYPASS BIT(19)
+#define B_BE_BTPMC_XTAL_SI_BYPASS BIT(17)
+#define B_BE_WLPMC_XTAL_SI_BYPASS BIT(16)
+#define B_BE_FSM_MON_UPD BIT(15)
+#define B_BE_FSM_PAR_MASK GENMASK(14, 0)
+#define WLAN_FSM_MASK 0xFFFFFF
+#define WLAN_FSM_SET 0x4000000
+#define WLAN_FSM_STATE_MASK 0x1FF
+#define WLAN_FSM_IDLE 0
+
#define R_BE_EFUSE_CTRL_2_V1 0x00A4
#define B_BE_EF_ENT BIT(31)
#define B_BE_EF_TCOLUMN_EN BIT(29)
@@ -4188,6 +4231,10 @@
#define B_BE_EF_DSB_EN BIT(11)
#define B_BE_EF_DLY_SEL_MASK GENMASK(3, 0)
+#define R_BE_SCOREBOARD 0x00AC
+#define B_BE_TOGGLE BIT(31)
+#define B_BE_DATA_LINE_MASK GENMASK(30, 0)
+
#define R_BE_PMC_DBG_CTRL2 0x00CC
#define B_BE_EFUSE_BURN_GNT_MASK GENMASK(31, 24)
#define B_BE_DIS_IOWRAP_TIMEOUT BIT(16)
@@ -4237,6 +4284,13 @@
#define R_BE_PCIE_MIO_INTD 0x00E8
#define B_BE_PCIE_MIO_DATA_MASK GENMASK(31, 0)
+#define R_BE_SYS_CHIPINFO 0x00FC
+#define B_BE_USB2_SEL BIT(31)
+#define B_BE_U3PHY_RST_V1 BIT(30)
+#define B_BE_U3_TERM_DETECT BIT(29)
+#define B_BE_VERIFY_ENV_MASK GENMASK(9, 8)
+#define B_BE_HW_ID_MASK GENMASK(7, 0)
+
#define R_BE_HALT_H2C_CTRL 0x0160
#define B_BE_HALT_H2C_TRIGGER BIT(0)
@@ -4261,6 +4315,72 @@
#define R_BE_SECURE_BOOT_MALLOC_INFO 0x0184
+#define R_BE_FWS0IMR 0x0190
+#define B_BE_FS_HALT_H2C_INT_EN BIT(31)
+#define B_BE_FS_FSM_HIOE_TO_EVENT_INT_EN BIT(30)
+#define B_BE_FS_HCI_SUS_INT_EN BIT(29)
+#define B_BE_FS_HCI_RES_INT_EN BIT(28)
+#define B_BE_FS_HCI_RESET_INT_EN BIT(27)
+#define B_BE_FS_BT_SB1_INT_EN BIT(26)
+#define B_BE_FS_ACT2RECOVERY_INT_EN BIT(25)
+#define B_BE_FS_GEN1GEN2_SWITCH_INT_EN BIT(24)
+#define B_BE_FS_USB_LPMRSM_INT_EN BIT(22)
+#define B_BE_FS_USB_LPMINT_INT_EN BIT(21)
+#define B_BE_FS_PWMERR_INT_EN BIT(20)
+#define B_BE_FS_PDNINT_EN BIT(19)
+#define B_BE_FS_SPSA_OCP_INT_EN BIT(18)
+#define B_BE_FS_SPSD_OCP_INT_EN BIT(17)
+#define B_BE_FS_BT_SB0_INT_EN BIT(16)
+#define B_BE_FS_GPIOF_INT_EN BIT(15)
+#define B_BE_FS_GPIOE_INT_EN BIT(14)
+#define B_BE_FS_GPIOD_INT_EN BIT(13)
+#define B_BE_FS_GPIOC_INT_EN BIT(12)
+#define B_BE_FS_GPIOB_INT_EN BIT(11)
+#define B_BE_FS_GPIOA_INT_EN BIT(10)
+#define B_BE_FS_GPIO9_INT_EN BIT(9)
+#define B_BE_FS_GPIO8_INT_EN BIT(8)
+#define B_BE_FS_GPIO7_INT_EN BIT(7)
+#define B_BE_FS_GPIO6_INT_EN BIT(6)
+#define B_BE_FS_GPIO5_INT_EN BIT(5)
+#define B_BE_FS_GPIO4_INT_EN BIT(4)
+#define B_BE_FS_GPIO3_INT_EN BIT(3)
+#define B_BE_FS_GPIO2_INT_EN BIT(2)
+#define B_BE_FS_GPIO1_INT_EN BIT(1)
+#define B_BE_FS_GPIO0_INT_EN BIT(0)
+
+#define R_BE_FWS0ISR 0x0194
+#define B_BE_FS_HALT_H2C_INT BIT(31)
+#define B_BE_FS_FSM_HIOE_TO_EVENT_INT BIT(30)
+#define B_BE_FS_HCI_SUS_INT BIT(29)
+#define B_BE_FS_HCI_RES_INT BIT(28)
+#define B_BE_FS_HCI_RESET_INT BIT(27)
+#define B_BE_FS_BT_SB1_INT BIT(26)
+#define B_BE_FS_ACT2RECOVERY_INT BIT(25)
+#define B_BE_FS_GEN1GEN2_SWITCH_INT BIT(24)
+#define B_BE_FS_USB_LPMRSM_INT BIT(22)
+#define B_BE_FS_USB_LPMINT_INT BIT(21)
+#define B_BE_FS_PWMERR_INT BIT(20)
+#define B_BE_FS_PDNINT BIT(19)
+#define B_BE_FS_SPSA_OCP_INT BIT(18)
+#define B_BE_FS_SPSD_OCP_INT BIT(17)
+#define B_BE_FS_BT_SB0_INT BIT(16)
+#define B_BE_FS_GPIOF_INT BIT(15)
+#define B_BE_FS_GPIOE_INT BIT(14)
+#define B_BE_FS_GPIOD_INT BIT(13)
+#define B_BE_FS_GPIOC_INT BIT(12)
+#define B_BE_FS_GPIOB_INT BIT(11)
+#define B_BE_FS_GPIOA_INT BIT(10)
+#define B_BE_FS_GPIO9_INT BIT(9)
+#define B_BE_FS_GPIO8_INT BIT(8)
+#define B_BE_FS_GPIO7_INT BIT(7)
+#define B_BE_FS_GPIO6_INT BIT(6)
+#define B_BE_FS_GPIO5_INT BIT(5)
+#define B_BE_FS_GPIO4_INT BIT(4)
+#define B_BE_FS_GPIO3_INT BIT(3)
+#define B_BE_FS_GPIO2_INT BIT(2)
+#define B_BE_FS_GPIO1_INT BIT(1)
+#define B_BE_FS_GPIO0_INT BIT(0)
+
#define R_BE_FWS1IMR 0x0198
#define B_BE_FS_RPWM_INT_EN_V1 BIT(24)
#define B_BE_PCIE_HOTRST_EN BIT(22)
@@ -4447,6 +4567,16 @@
#define B_BE_WL_XTAL_SI_DATA_MASK GENMASK(15, 8)
#define B_BE_WL_XTAL_SI_ADDR_MASK GENMASK(7, 0)
+#define R_BE_PCIE_SER_DBG 0x02FC
+#define B_BE_PCIE_SER_DBG_MASK GENMASK(31, 10)
+#define B_BE_PCIE_SER_PHY_PROTECT BIT(9)
+#define B_BE_PCIE_SER_MAC_PROTECT BIT(8)
+#define B_BE_PCIE_SER_FLUSH_RSTB BIT(4)
+#define B_BE_PCIE_AXI_BRG_FLUSH_EN BIT(3)
+#define B_BE_PCIE_SER_AUXCLK_RDY BIT(2)
+#define B_BE_PCIE_SER_FRZ_REG_RST BIT(1)
+#define B_BE_PCIE_SER_FRZ_CFG_SPC_RST BIT(0)
+
#define R_BE_IC_PWR_STATE 0x03F0
#define B_BE_WHOLE_SYS_PWR_STE_MASK GENMASK(25, 16)
#define MAC_AX_SYS_ACT 0x220
@@ -4599,6 +4729,10 @@
#define R_BE_LTR_LATENCY_IDX2_V1 0x361C
#define R_BE_LTR_LATENCY_IDX3_V1 0x3620
+#define R_BE_HCI_BUF_IMR 0x6018
+#define B_BE_HCI_BUF_IMR_CLR 0xC0000303
+#define B_BE_HCI_BUF_IMR_SET 0xC0000301
+
#define R_BE_H2CREG_DATA0 0x7140
#define R_BE_H2CREG_DATA1 0x7144
#define R_BE_H2CREG_DATA2 0x7148
@@ -4693,6 +4827,9 @@
#define B_BE_LTR_CMAC1_RX_USE_PG_TH_MASK GENMASK(27, 16)
#define B_BE_LTR_CMAC0_RX_USE_PG_TH_MASK GENMASK(11, 0)
+#define R_BE_NO_RX_ERR_CFG 0x841C
+#define B_BE_NO_RX_ERR_TO_MASK GENMASK(31, 29)
+
#define R_BE_DMAC_TABLE_CTRL 0x8420
#define B_BE_HWAMSDU_PADDING_MODE BIT(31)
#define B_BE_MACID_MPDU_PROCESSOR_OFFSET_MASK GENMASK(26, 16)
@@ -4704,7 +4841,7 @@
#define B_BE_SER_L0_PROMOTE_L1_EVENT_MASK GENMASK(31, 28)
#define B_BE_SER_L1_COUNTER_MASK GENMASK(27, 24)
#define B_BE_RMAC_PPDU_HANG_CNT_MASK GENMASK(23, 16)
-#define B_BE_SER_L0_COUNTER_MASK GENMASK(8, 0)
+#define B_BE_SER_L0_COUNTER_MASK GENMASK(7, 0)
#define R_BE_DMAC_SYS_CR32B 0x842C
#define B_BE_DMAC_BB_PHY1_MASK GENMASK(31, 16)
@@ -4823,6 +4960,10 @@
#define R_BE_SER_L1_DBG_CNT_7 0x845C
#define B_BE_SER_L1_DBG_2_MASK GENMASK(31, 0)
+#define R_BE_FW_TRIGGER_IDCT_ISR 0x8508
+#define B_BE_DMAC_FW_ERR_IDCT_IMR BIT(31)
+#define B_BE_DMAC_FW_TRIG_IDCT BIT(0)
+
#define R_BE_DMAC_ERR_IMR 0x8520
#define B_BE_DMAC_NOTX_ERR_INT_EN BIT(21)
#define B_BE_DMAC_NORX_ERR_INT_EN BIT(20)
@@ -5026,6 +5167,8 @@
B_BE_STF_WRFF_UNDERFLOW_ERR_INT_EN | \
B_BE_STF_OQT_OVERFLOW_ERR_INT_EN | \
B_BE_STF_OQT_UNDERFLOW_ERR_INT_EN)
+#define B_BE_DISP_OTHER_IMR_CLR_V1 0xFFFFFFFF
+#define B_BE_DISP_OTHER_IMR_SET_V1 0x3F002000
#define R_BE_DISP_HOST_IMR 0x8874
#define B_BE_HR_WRFF_UNDERFLOW_ERR_INT_EN BIT(31)
@@ -5103,6 +5246,8 @@
B_BE_HR_DMA_PROCESS_ERR_INT_EN | \
B_BE_HR_WRFF_OVERFLOW_ERR_INT_EN | \
B_BE_HR_WRFF_UNDERFLOW_ERR_INT_EN)
+#define B_BE_DISP_HOST_IMR_CLR_V1 0xFBFFFFFF
+#define B_BE_DISP_HOST_IMR_SET_V1 0xC8B3E579
#define R_BE_DISP_CPU_IMR 0x8878
#define B_BE_CR_PLD_LEN_ERR_INT_EN BIT(30)
@@ -5177,6 +5322,8 @@
B_BE_CR_DMA_PROCESS_ERR_INT_EN | \
B_BE_CR_WRFF_OVERFLOW_ERR_INT_EN | \
B_BE_CR_WRFF_UNDERFLOW_ERR_INT_EN)
+#define B_BE_DISP_CPU_IMR_CLR_V1 0x7DFFFFFD
+#define B_BE_DISP_CPU_IMR_SET_V1 0x34F938FD
#define R_BE_RX_STOP 0x8914
#define B_BE_CPU_RX_STOP BIT(17)
@@ -5471,6 +5618,10 @@
#define B_BE_PLE_Q12_MAX_SIZE_MASK GENMASK(27, 16)
#define B_BE_PLE_Q12_MIN_SIZE_MASK GENMASK(11, 0)
+#define R_BE_PLE_QTA13_CFG 0x9074
+#define B_BE_PLE_Q13_MAX_SIZE_MASK GENMASK(27, 16)
+#define B_BE_PLE_Q13_MIN_SIZE_MASK GENMASK(11, 0)
+
#define R_BE_PLE_ERRFLAG1_IMR 0x90C0
#define B_BE_PLE_SRCHPG_PGOFST_IMR BIT(26)
#define B_BE_PLE_SRCHPG_STRPG_IMR BIT(25)
@@ -5528,7 +5679,21 @@
B_BE_WDRLS_RPT1_AGGNUM0_ERR_INT_EN | \
B_BE_WDRLS_RPT1_FRZTO_ERR_INT_EN)
+#define R_BE_RLSRPT0_CFG0 0x9440
+#define B_BE_RLSRPT0_FWRLS BIT(31)
+#define B_BE_RLSRPT0_FWD_TRGT_MASK GENMASK(23, 16)
+#define B_BE_RLSRPT0_PID_MASK GENMASK(10, 8)
+#define B_BE_RLSRPT0_QID_MASK GENMASK(5, 0)
+#define WDRLS_DEST_QID_POH 1
+#define WDRLS_DEST_QID_STF 0
+
#define R_BE_RLSRPT0_CFG1 0x9444
+#define B_BE_RLSRPT0_FLTR_MAP_V1_MASK GENMASK(28, 24)
+#define S_BE_WDRLS_FLTR_TXOK_V1 BIT(0)
+#define S_BE_WDRLS_FLTR_RTYLMT_V1 BIT(1)
+#define S_BE_WDRLS_FLTR_LIFTIM_V1 BIT(2)
+#define S_BE_WDRLS_FLTR_MACID_V1 BIT(3)
+#define S_BE_WDRLS_FLTR_RELINK_V1 BIT(4)
#define B_BE_RLSRPT0_FLTR_MAP_MASK GENMASK(27, 24)
#define S_BE_WDRLS_FLTR_TXOK 1
#define S_BE_WDRLS_FLTR_RTYLMT 2
@@ -5822,12 +5987,18 @@
#define B_BE_MPDUINFO_PKTID_MASK GENMASK(27, 16)
#define B_BE_MPDUINFO_B1_BADDR_MASK GENMASK(5, 0)
#define MPDU_INFO_B1_OFST 18
+#define MPDU_INFO_TBL_FACTOR 3
#define R_BE_TXPKTCTL_B0_PRELD_CFG0 0x9F48
#define B_BE_B0_PRELD_FEN BIT(31)
#define B_BE_B0_PRELD_USEMAXSZ_MASK GENMASK(25, 16)
#define B_BE_B0_PRELD_CAM_G1ENTNUM_MASK GENMASK(12, 8)
+#define PRELD_MISCQ_ENT_NUM_8922A 2
+#define PRELD_MISCQ_ENT_NUM_8922D 1
#define B_BE_B0_PRELD_CAM_G0ENTNUM_MASK GENMASK(4, 0)
+#define PRELD_B0_ACQ_ENT_NUM_8922A 8
+#define PRELD_B1_ACQ_ENT_NUM_8922A 2
+#define PRELD_ACQ_ENT_NUM_8922D 1
#define R_BE_TXPKTCTL_B0_PRELD_CFG1 0x9F4C
#define B_BE_B0_PRELD_NXT_TXENDWIN_MASK GENMASK(11, 8)
@@ -5939,6 +6110,7 @@
#define B_BE_PLRLS_CTL_FRZTO_ISR BIT(0)
#define R_BE_SS_CTRL 0xA310
+#define R_BE_SS_CTRL_V1 0xA610
#define B_BE_SS_INIT_DONE BIT(31)
#define B_BE_WDE_STA_DIS BIT(30)
#define B_BE_WARM_INIT BIT(29)
@@ -5978,6 +6150,24 @@
#define B_BE_RPT_TIMEOUT_ISR BIT(1)
#define B_BE_SEARCH_TIMEOUT_ISR BIT(0)
+#define R_BE_PLRLS_ERR_IMR_V1 0xA518
+#define B_BE_PLRLS_DUMMY_ISR6 BIT(7)
+#define B_BE_PLRLS_DUMMY_ISR5 BIT(6)
+#define B_BE_PLRLS_DUMMY_ISR4 BIT(5)
+#define B_BE_PLRLS_DUMMY_ISR3 BIT(4)
+#define B_BE_PLRLS_DUMMY_ISR2 BIT(3)
+#define B_BE_PLRLS_DUMMY_ISR1 BIT(2)
+#define B_BE_PLRLS_DUMMY_ISR0 BIT(1)
+#define B_BE_PLRLS_ERR_IMR_V1_CLR 0x1
+#define B_BE_PLRLS_ERR_IMR_V1_SET 0x1
+
+#define R_BE_SS_LITE_TXL_MACID 0xA790
+#define B_BE_RPT_OTHER_BAND_EN BIT(31)
+#define B_BE_TXL_CMD_EN BIT(30)
+#define B_BE_TXL_READ_MACID_MASK GENMASK(29, 20)
+#define B_BE_TXL_MACID_1_MASK GENMASK(19, 10)
+#define B_BE_TXL_MACID_0_MASK GENMASK(9, 0)
+
#define R_BE_HAXI_INIT_CFG1 0xB000
#define B_BE_CFG_WD_PERIOD_IDLE_MASK GENMASK(31, 28)
#define B_BE_CFG_WD_PERIOD_ACTIVE_MASK GENMASK(27, 24)
@@ -6017,6 +6207,18 @@
#define B_BE_STOP_CH2 BIT(2)
#define B_BE_STOP_CH1 BIT(1)
#define B_BE_STOP_CH0 BIT(0)
+#define B_BE_TX_STOP1_MASK (B_BE_STOP_CH0 | B_BE_STOP_CH1 | \
+ B_BE_STOP_CH2 | B_BE_STOP_CH3 | \
+ B_BE_STOP_CH4 | B_BE_STOP_CH5 | \
+ B_BE_STOP_CH6 | B_BE_STOP_CH7 | \
+ B_BE_STOP_CH8 | B_BE_STOP_CH9 | \
+ B_BE_STOP_CH10 | B_BE_STOP_CH11 | \
+ B_BE_STOP_CH12 | B_BE_STOP_CH13 | \
+ B_BE_STOP_CH14)
+#define B_BE_TX_STOP1_MASK_V1 (B_BE_STOP_CH0 | B_BE_STOP_CH2 | \
+ B_BE_STOP_CH4 | B_BE_STOP_CH6 | \
+ B_BE_STOP_CH8 | B_BE_STOP_CH10 | \
+ B_BE_STOP_CH12)
#define R_BE_HAXI_MST_WDT_TIMEOUT_SEL_V1 0xB02C
#define B_BE_HAXI_MST_WDT_TIMEOUT_SEL_MASK GENMASK(4, 0)
@@ -6069,6 +6271,7 @@
#define R_BE_CH_PAGE_CTRL 0xB704
#define B_BE_PREC_PAGE_CH12_V1_MASK GENMASK(21, 16)
+#define B_BE_FULL_WD_PG_MASK GENMASK(15, 8)
#define B_BE_PREC_PAGE_CH011_V1_MASK GENMASK(5, 0)
#define R_BE_CH0_PAGE_CTRL 0xB718
@@ -6101,6 +6304,10 @@
#define R_BE_WP_PAGE_CTRL1 0xB7A4
#define B_BE_PREC_PAGE_WP_CH811_MASK GENMASK(24, 16)
#define B_BE_PREC_PAGE_WP_CH07_MASK GENMASK(8, 0)
+#define B_BE_FULL_PAGE_WP_CH811_MASK GENMASK(31, 24)
+#define B_BE_PREC_PAGE_WP_CH811_V1_MASK GENMASK(23, 16)
+#define B_BE_FULL_PAGE_WP_CH07_MASK GENMASK(15, 8)
+#define B_BE_PREC_PAGE_WP_CH07_V1_MASK GENMASK(7, 0)
#define R_BE_WP_PAGE_CTRL2 0xB7A8
#define B_BE_WP_THRD_MASK GENMASK(12, 0)
@@ -6159,8 +6366,79 @@
#define B_BE_GNT_WL_BB_PWR_VAL BIT(1)
#define B_BE_GNT_WL_BB_PWR_SWCTRL BIT(0)
+#define R_BE_PTA_GNT_SW_CTRL 0x0E348
+#define B_BE_PTA_WL_ACT0_VAL BIT(19)
+#define B_BE_PTA_WL_ACT0_SWCTRL BIT(18)
+#define B_BE_PTA_GNT_BT0_RX_BB1_VAL BIT(17)
+#define B_BE_PTA_GNT_BT0_RX_BB1_SWCTRL BIT(16)
+#define B_BE_PTA_GNT_BT0_TX_BB1_VAL BIT(15)
+#define B_BE_PTA_GNT_BT0_TX_BB1_SWCTRL BIT(14)
+#define B_BE_PTA_GNT_BT0_RX_BB0_VAL BIT(13)
+#define B_BE_PTA_GNT_BT0_RX_BB0_SWCTRL BIT(12)
+#define B_BE_PTA_GNT_BT0_TX_BB0_VAL BIT(11)
+#define B_BE_PTA_GNT_BT0_TX_BB0_SWCTRL BIT(10)
+#define B_BE_PTA_GNT_BT0_BB_VAL BIT(9)
+#define B_BE_PTA_GNT_BT0_BB_SWCTRL BIT(8)
+#define B_BE_PTA_WL_ACT_RX_BT0_VAL BIT(7)
+#define B_BE_PTA_WL_ACT_RX_BT0_SWCTRL BIT(6)
+#define B_BE_PTA_WL_ACT_TX_BT0_VAL BIT(5)
+#define B_BE_PTA_WL_ACT_TX_BT0_SWCTRL BIT(4)
+#define B_BE_PTA_GNT_WL_BB1_VAL BIT(3)
+#define B_BE_PTA_GNT_WL_BB1_SWCTRL BIT(2)
+#define B_BE_PTA_GNT_WL_BB0_VAL BIT(1)
+#define B_BE_PTA_GNT_WL_BB0_SWCTRL BIT(0)
+
+#define R_BE_PTA_GNT_VAL 0x0E34C
+#define B_BE_PTA_WL_ACT2 BIT(20)
+#define B_BE_PTA_GNT_ZB_TX_BB1 BIT(19)
+#define B_BE_PTA_GNT_ZB_TX_BB0 BIT(18)
+#define B_BE_PTA_WL_ACT1 BIT(17)
+#define B_BE_PTA_GNT_BT1_RX_BB1 BIT(16)
+#define B_BE_PTA_GNT_BT1_RX_BB0 BIT(15)
+#define B_BE_PTA_GNT_BT1_TX_BB1 BIT(14)
+#define B_BE_PTA_GNT_BT1_TX_BB0 BIT(13)
+#define B_BE_PTA_WL_ACT_RX_BT1 BIT(12)
+#define B_BE_PTA_WL_ACT_TX_BT1 BIT(11)
+#define B_BE_PTA_GNT_BT1_BB BIT(10)
+#define B_BE_PTA_WL_ACT0 BIT(9)
+#define B_BE_PTA_GNT_BT0_RX_BB1 BIT(8)
+#define B_BE_PTA_GNT_BT0_TX_BB1 BIT(7)
+#define B_BE_PTA_GNT_BT0_RX_BB0 BIT(6)
+#define B_BE_PTA_GNT_BT0_TX_BB0 BIT(5)
+#define B_BE_PTA_GNT_BT0_BB BIT(4)
+#define B_BE_PTA_WL_ACT_RX_BT0 BIT(3)
+#define B_BE_PTA_WL_ACT_TX_BT0 BIT(2)
+#define B_BE_PTA_GNT_WL_BB1 BIT(1)
+#define B_BE_PTA_GNT_WL_BB0 BIT(0)
+
+#define R_BE_PTA_GNT_ZL_SW_CTRL 0x0E350
+#define B_BE_PTA_WL_ACT2_VAL BIT(21)
+#define B_BE_PTA_WL_ACT2_SWCTRL BIT(20)
+#define B_BE_PTA_GNT_ZB_TX_BB1_VAL BIT(19)
+#define B_BE_PTA_GNT_ZB_TX_BB1_SWCTRL BIT(18)
+#define B_BE_PTA_GNT_ZB_TX_BB0_VAL BIT(17)
+#define B_BE_PTA_GNT_ZB_TX_BB0_SWCTRL BIT(16)
+#define B_BE_PTA_WL_ACT1_VAL BIT(15)
+#define B_BE_PTA_WL_ACT1_SWCTRL BIT(14)
+#define B_BE_PTA_GNT_BT1_RX_BB1_VAL BIT(13)
+#define B_BE_PTA_GNT_BT1_RX_BB1_SWCTRL BIT(12)
+#define B_BE_PTA_GNT_BT1_RX_BB0_VAL BIT(11)
+#define B_BE_PTA_GNT_BT1_RX_BB0_SWCTRL BIT(10)
+#define B_BE_PTA_GNT_BT1_TX_BB1_VAL BIT(9)
+#define B_BE_PTA_GNT_BT1_TX_BB1_SWCTRL BIT(8)
+#define B_BE_PTA_GNT_BT1_TX_BB0_VAL BIT(7)
+#define B_BE_PTA_GNT_BT1_TX_BB0_SWCTRL BIT(6)
+#define B_BE_PTA_WL_ACT_RX_BT1_VAL BIT(5)
+#define B_BE_PTA_WL_ACT_RX_BT1_SWCTRL BIT(4)
+#define B_BE_PTA_WL_ACT_TX_BT1_VAL BIT(3)
+#define B_BE_PTA_WL_ACT_TX_BT1_SWCTRL BIT(2)
+#define B_BE_PTA_GNT_BT1_BB_VAL BIT(1)
+#define B_BE_PTA_GNT_BT1_BB_SWCTRL BIT(0)
+
#define R_BE_PWR_MACID_PATH_BASE 0x0E500
+#define R_BE_PWR_MACID_PATH_BASE_V1 0x1C000
#define R_BE_PWR_MACID_LMT_BASE 0x0ED00
+#define R_BE_PWR_MACID_LMT_BASE_V1 0x1C800
#define R_BE_CMAC_FUNC_EN 0x10000
#define R_BE_CMAC_FUNC_EN_C1 0x14000
@@ -6223,6 +6501,19 @@
#define BE_WMAC_RFMOD_160M 3
#define BE_WMAC_RFMOD_320M 4
+#define R_BE_GID_POSITION0 0x10070
+#define R_BE_GID_POSITION0_C1 0x14070
+#define R_BE_GID_POSITION1 0x10074
+#define R_BE_GID_POSITION1_C1 0x14074
+#define R_BE_GID_POSITION2 0x10078
+#define R_BE_GID_POSITION2_C1 0x14078
+#define R_BE_GID_POSITION3 0x1007C
+#define R_BE_GID_POSITION3_C1 0x1407C
+#define R_BE_GID_POSITION_EN0 0x10080
+#define R_BE_GID_POSITION_EN0_C1 0x14080
+#define R_BE_GID_POSITION_EN1 0x10084
+#define R_BE_GID_POSITION_EN1_C1 0x14084
+
#define R_BE_TX_SUB_BAND_VALUE 0x10088
#define R_BE_TX_SUB_BAND_VALUE_C1 0x14088
#define B_BE_PRI20_BITMAP_MASK GENMASK(31, 16)
@@ -6257,6 +6548,21 @@
#define B_BE_RSC_MASK GENMASK(7, 6)
#define B_BE_RRSR_CCK_MASK GENMASK(3, 0)
+#define R_BE_COMMON_PHYINTF_CTRL_0 0x100B8
+#define R_BE_COMMON_PHYINTF_CTRL_0_C1 0x140B8
+#define B_BE_SEQ_EN_GUARD_CYE_MASK GENMASK(23, 20)
+#define B_BE_PARA_FIFO_CRC_EN BIT(18)
+#define B_BE_SEQ_FIFO_TO_EN BIT(17)
+#define B_BE_PARA_FIFO_TO_EN BIT(16)
+#define B_BE_SEQ_FIFO_CLR_EN BIT(6)
+#define B_BE_PARA_FIFO_CLR_EN_V1 BIT(5)
+#define B_BE_CSI_FIFO_CLR_EN_V1 BIT(4)
+#define B_BE_FTM_FIFO_CLR_EN_V1 BIT(3)
+#define B_BE_RXD_FIFO_CLR_EN_V1 BIT(2)
+#define B_BE_TXD_FIFO_CLR_EN_V1 BIT(1)
+#define B_BE_TXUID_FIFO_CLR_EN_V1 BIT(0)
+#define CLEAR_DTOP_DIS (BIT(1) | BIT(5) | BIT(6))
+
#define R_BE_CMAC_ERR_IMR 0x10160
#define R_BE_CMAC_ERR_IMR_C1 0x14160
#define B_BE_CMAC_FW_ERR_IDCT_EN BIT(16)
@@ -6349,6 +6655,25 @@
#define B_BE_P0_SYNC_PORT_SRC_SEL_MASK GENMASK(26, 24)
#define B_BE_P0_TSFTR_SYNC_OFFSET_MASK GENMASK(18, 0)
+#define R_BE_SCH_EDCA_RST_CFG 0x102E4
+#define R_BE_SCH_EDCA_RST_CFG_C1 0x142E4
+#define B_BE_EDCCA_S160_RST_EDCA_EN BIT(23)
+#define B_BE_EDCCA_S80_RST_EDCA_EN BIT(22)
+#define B_BE_EDCCA_S40_RST_EDCA_EN BIT(21)
+#define B_BE_EDCCA_S20_RST_EDCA_EN BIT(20)
+#define B_BE_OFDM_CCA_S160_RST_EDCA_EN BIT(19)
+#define B_BE_CCA_PEB_BE_BITMAP_RST_EDCA_EN BIT(18)
+#define B_BE_RX_INTRA_NAV_RST_EDCA_EN BIT(15)
+#define B_BE_RX_BASIC_NAV_RST_EDCA_EN BIT(14)
+#define B_BE_EDCCA_PER20_BITMAP_SIFS_RST_EDCA_EN BIT(10)
+#define B_BE_TX_NAV_RST_EDCA_EN BIT(7)
+#define B_BE_NO_GNT_WL_RST_EDCA_EN BIT(5)
+#define B_BE_EDCCA_P20_RST_EDCA_EN BIT(4)
+#define B_BE_OFDM_CCA_S80_RST_EDCA_EN BIT(3)
+#define B_BE_OFDM_CCA_S40_RST_EDCA_EN BIT(2)
+#define B_BE_OFDM_CCA_S20_RST_EDCA_EN BIT(1)
+#define B_BE_CCA_P20_RST_EDCA_EN BIT(0)
+
#define R_BE_EDCA_BCNQ_PARAM 0x10324
#define R_BE_EDCA_BCNQ_PARAM_C1 0x14324
#define B_BE_BCNQ_CW_MASK GENMASK(31, 24)
@@ -6639,6 +6964,34 @@
#define B_BE_CMAC_TX_MODE_1 BIT(1)
#define B_BE_CMAC_TX_MODE_0 BIT(0)
+#define R_BE_AGG_BK_0 0x10804
+#define R_BE_AGG_BK_0_C1 0x14804
+#define B_BE_DIS_SAMPDU_TXIME_SR_CHECK BIT(24)
+#define B_BE_TX_PAIR_MACID_LEN_EN BIT(23)
+#define B_BE_DIS_SND_STS_CHECK_SU BIT(22)
+#define B_BE_MAX_AGG_NUM_FIX_MODE_EN_V1 BIT(21)
+#define B_BE_DIS_SIFS_BK_AGG_AMPDU BIT(20)
+#define B_BE_EN_MU2SU_CHK_PROTECT_PPDU BIT(19)
+#define B_BE_RPT_TXOP_START_PROTECT BIT(18)
+#define B_BE_RANDOM_GEN_CMD_ABORT_EN BIT(17)
+#define B_BE_PHYTXON_ENDPS_RESP_CHK BIT(16)
+#define B_BE_CTN_CHK_SEQ_REQ_EN BIT(15)
+#define B_BE_PTCL_RLS_ALLFAIL_EN BIT(14)
+#define B_BE_DIS_MURU_PRI_Q_EMPTY_CHK BIT(13)
+#define B_BE_DIS_MURU_SEC_Q_EMPTY_CHK BIT(12)
+#define B_BE_EN_SAMPDU_TXIME_TWT_CHECK BIT(11)
+#define B_BE_DIS_SAMPDU_TXIME_P2P_CHECK BIT(10)
+#define B_BE_DIS_SAMPDU_TXIME_BCN_CHECK BIT(9)
+#define B_BE_DIS_UL_SEQ_ABORT_CHECK BIT(8)
+#define B_BE_DIS_SND_STS_CHECK BIT(7)
+#define B_BE_NAV_PAUS_PHB_EN BIT(6)
+#define B_BE_TXOP_SHT_PHB_EN BIT(5)
+#define B_BE_AGG_BRK_PHB_EN BIT(4)
+#define B_BE_DIS_SSN_CHK BIT(3)
+#define B_BE_WDBK_CFG BIT(2)
+#define B_BE_EN_RTY_BK BIT(1)
+#define B_BE_EN_RTY_BK_COD BIT(0)
+
#define R_BE_TB_PPDU_CTRL 0x1080C
#define R_BE_TB_PPDU_CTRL_C1 0x1480C
#define B_BE_TB_PPDU_BK_DIS BIT(15)
@@ -6653,9 +7006,11 @@
#define R_BE_AMPDU_AGG_LIMIT_C1 0x14810
#define B_BE_AMPDU_MAX_TIME_MASK GENMASK(31, 24)
#define AMPDU_MAX_TIME 0x9E
+#define AMPDU_MAX_TIME_V1 0xA4
#define B_BE_RA_TRY_RATE_AGG_LMT_MASK GENMASK(23, 16)
#define B_BE_RTS_MAX_AGG_NUM_MASK GENMASK(15, 8)
#define B_BE_MAX_AGG_NUM_MASK GENMASK(7, 0)
+#define MAX_TX_AMPDU_NUM_V1 128
#define R_BE_AGG_LEN_HT_0 0x10814
#define R_BE_AGG_LEN_HT_0_C1 0x14814
@@ -6663,6 +7018,20 @@
#define B_BE_RTS_TXTIME_TH_MASK GENMASK(15, 8)
#define B_BE_RTS_LEN_TH_MASK GENMASK(7, 0)
+#define R_BE_SPECIAL_TX_SETTING 0x10820
+#define R_BE_SPECIAL_TX_SETTING_C1 0x14820
+#define B_BE_TRI_PADDING_EXTEND BIT(31)
+#define B_BE_TX_SN_BYPASS_EN BIT(30)
+#define B_BE_USE_DATA_BW BIT(29)
+#define B_BE_BW_SIGTA_MASK GENMASK(28, 27)
+#define B_BE_BMC_NAV_PROTECT BIT(26)
+#define B_BE_F2P_KEEP_NON_SR_CMD BIT(25)
+#define B_BE_F2P_SU_FIXRATE_OVER_WD BIT(24)
+#define B_BE_BAR_TXRATE_FOR_NULL_WD_MASK GENMASK(23, 20)
+#define B_BE_STBC_CFEND_MASK GENMASK(19, 18)
+#define B_BE_STBC_CFEND_RATE_MASK GENMASK(17, 9)
+#define B_BE_BASIC_CFEND_RATE_MASK GENMASK(8, 0)
+
#define R_BE_SIFS_SETTING 0x10824
#define R_BE_SIFS_SETTING_C1 0x14824
#define B_BE_HW_CTS2SELF_PKT_LEN_TH_MASK GENMASK(31, 24)
@@ -6696,6 +7065,44 @@
#define B_BE_PORT_DROP_4_0_MASK GENMASK(20, 16)
#define B_BE_MBSSID_DROP_15_0_MASK GENMASK(15, 0)
+#define R_BE_PTCL_PRELD_CTRL 0x10868
+#define R_BE_PTCL_PRELD_CTRL_C1 0x14868
+#define B_BE_PRELD_MGQ2_EN BIT(22)
+#define B_BE_PRELD_MGQ1_EN BIT(21)
+#define B_BE_PRELD_MGQ0_EN BIT(20)
+#define B_BE_PRELD_HIQ_P4_EN BIT(19)
+#define B_BE_PRELD_HIQ_P3_EN BIT(18)
+#define B_BE_PRELD_HIQ_P2_EN BIT(17)
+#define B_BE_PRELD_HIQ_P1_EN BIT(16)
+#define B_BE_PRELD_HIQ_P0MB15_EN BIT(15)
+#define B_BE_PRELD_HIQ_P0MB14_EN BIT(14)
+#define B_BE_PRELD_HIQ_P0MB13_EN BIT(13)
+#define B_BE_PRELD_HIQ_P0MB12_EN BIT(12)
+#define B_BE_PRELD_HIQ_P0MB11_EN BIT(11)
+#define B_BE_PRELD_HIQ_P0MB10_EN BIT(10)
+#define B_BE_PRELD_HIQ_P0MB9_EN BIT(9)
+#define B_BE_PRELD_HIQ_P0MB8_EN BIT(8)
+#define B_BE_PRELD_HIQ_P0MB7_EN BIT(7)
+#define B_BE_PRELD_HIQ_P0MB6_EN BIT(6)
+#define B_BE_PRELD_HIQ_P0MB5_EN BIT(5)
+#define B_BE_PRELD_HIQ_P0MB4_EN BIT(4)
+#define B_BE_PRELD_HIQ_P0MB3_EN BIT(3)
+#define B_BE_PRELD_HIQ_P0MB2_EN BIT(2)
+#define B_BE_PRELD_HIQ_P0MB1_EN BIT(1)
+#define B_BE_PRELD_HIQ_P0_EN BIT(0)
+#define B_BE_PRELD_HIQ_ALL_EN (B_BE_PRELD_HIQ_P0_EN | B_BE_PRELD_HIQ_P1_EN | \
+ B_BE_PRELD_HIQ_P2_EN | B_BE_PRELD_HIQ_P3_EN | \
+ B_BE_PRELD_HIQ_P4_EN)
+#define B_BE_PRELD_HIQ_P0MB_ALL_EN \
+ (B_BE_PRELD_HIQ_P0_EN | B_BE_PRELD_HIQ_P0MB1_EN | \
+ B_BE_PRELD_HIQ_P0MB2_EN | B_BE_PRELD_HIQ_P0MB3_EN | \
+ B_BE_PRELD_HIQ_P0MB4_EN | B_BE_PRELD_HIQ_P0MB5_EN | \
+ B_BE_PRELD_HIQ_P0MB6_EN | B_BE_PRELD_HIQ_P0MB7_EN | \
+ B_BE_PRELD_HIQ_P0MB8_EN | B_BE_PRELD_HIQ_P0MB9_EN | \
+ B_BE_PRELD_HIQ_P0MB10_EN | B_BE_PRELD_HIQ_P0MB11_EN | \
+ B_BE_PRELD_HIQ_P0MB12_EN | B_BE_PRELD_HIQ_P0MB13_EN | \
+ B_BE_PRELD_HIQ_P0MB14_EN | B_BE_PRELD_HIQ_P0MB15_EN)
+
#define R_BE_BT_PLT 0x1087C
#define R_BE_BT_PLT_C1 0x1487C
#define B_BE_BT_PLT_PKT_CNT_MASK GENMASK(31, 16)
@@ -6936,6 +7343,8 @@
B_BE_RX_RU1_FSM_HANG_ERROR_IMR | \
B_BE_RX_RU0_FSM_HANG_ERROR_IMR | \
B_BE_RX_GET_NULL_PKT_ERROR_IMR)
+#define B_BE_RX_ERROR_FLAG_IMR_CLR_V1 0x7FFFFFF8
+#define B_BE_RX_ERROR_FLAG_IMR_SET_V1 0x7FFFFF38
#define R_BE_RX_CTRL_1 0x10C0C
#define R_BE_RX_CTRL_1_C1 0x14C0C
@@ -7349,6 +7758,8 @@
#define B_BE_ACK_BA_RESP_LEGACY_CHK_SEC_CCA20 BIT(2)
#define B_BE_ACK_BA_RESP_LEGACY_CHK_EDCCA BIT(1)
#define B_BE_ACK_BA_RESP_LEGACY_CHK_CCA BIT(0)
+#define RESP_ACK_CFG_BE (B_BE_ACK_BA_RESP_LEGACY_CHK_BTCCA | \
+ B_BE_ACK_BA_RESP_LEGACY_CHK_TX_NAV)
#define R_BE_WMAC_ACK_BA_RESP_HE 0x11204
#define R_BE_WMAC_ACK_BA_RESP_HE_C1 0x15204
@@ -7390,6 +7801,188 @@
#define B_BE_ACK_BA_EHT_LEG_PUNC_CHK_EDCCA BIT(1)
#define B_BE_ACK_BA_EHT_LEG_PUNC_CHK_CCA BIT(0)
+#define R_BE_WMAC_RX_RTS_RESP_LEGACY 0x1120C
+#define R_BE_WMAC_RX_RTS_RESP_LEGACY_C1 0x1520C
+#define B_BE_RX_RTS_RESP_LEGACY_CHK_NSTR BIT(16)
+#define B_BE_RX_RTS_RESP_LEGACY_CHK_TX_NAV BIT(15)
+#define B_BE_RX_RTS_RESP_LEGACY_CHK_INTRA_NAV BIT(14)
+#define B_BE_RX_RTS_RESP_LEGACY_CHK_BASIC_NAV BIT(13)
+#define B_BE_RX_RTS_RESP_LEGACY_CHK_BTCCA BIT(12)
+#define B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA160 BIT(11)
+#define B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA80 BIT(10)
+#define B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA40 BIT(9)
+#define B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA20 BIT(8)
+#define B_BE_RX_RTS_RESP_LEGACY_CHK_EDCCA_PER20_BMP BIT(7)
+#define B_BE_RX_RTS_RESP_LEGACY_CHK_CCA_PER20_BMP BIT(6)
+#define B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA160 BIT(5)
+#define B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA80 BIT(4)
+#define B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA40 BIT(3)
+#define B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA20 BIT(2)
+#define B_BE_RX_RTS_RESP_LEGACY_CHK_EDCCA BIT(1)
+#define B_BE_RX_RTS_RESP_LEGACY_CHK_CCA BIT(0)
+#define RESP_RTS_CFG_BE (B_BE_RX_RTS_RESP_LEGACY_CHK_CCA | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_EDCCA | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA20 | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA40 | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA80 | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA160 | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA20 | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA40 | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA80 | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA160 | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_BTCCA | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_BASIC_NAV | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_INTRA_NAV | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_TX_NAV)
+#define RESP_RTS_PUNC_CFG_BE (B_BE_RX_RTS_RESP_LEGACY_CHK_CCA | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_EDCCA | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_CCA_PER20_BMP | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_EDCCA_PER20_BMP | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_BTCCA | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_BASIC_NAV | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_INTRA_NAV | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_TX_NAV)
+#define RESP_NORMAL_CFG_BE (B_BE_RX_RTS_RESP_LEGACY_CHK_CCA | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_EDCCA | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA20 | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA40 | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA80 | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA160 | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA20 | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA40 | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA80 | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA160 | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_BTCCA | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_BASIC_NAV | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_TX_NAV)
+#define RESP_NORMAL_PUNC_CFG_BE (B_BE_RX_RTS_RESP_LEGACY_CHK_CCA | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_EDCCA | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_CCA_PER20_BMP | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_EDCCA_PER20_BMP | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_BTCCA | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_BASIC_NAV | \
+ B_BE_RX_RTS_RESP_LEGACY_CHK_TX_NAV)
+
+#define R_BE_WMAC_RX_RTS_RESP_LEGACY_PUNC 0x11210
+#define R_BE_WMAC_RX_RTS_RESP_LEGACY_PUNC_C1 0x15210
+#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_NSTR BIT(16)
+#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_TX_NAV BIT(15)
+#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_INTRA_NAV BIT(14)
+#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_BASIC_NAV BIT(13)
+#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_BTCCA BIT(12)
+#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_SEC_EDCCA160 BIT(11)
+#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_SEC_EDCCA80 BIT(10)
+#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_SEC_EDCCA40 BIT(9)
+#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_SEC_EDCCA20 BIT(8)
+#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_EDCCA_PER20_BMP BIT(7)
+#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_CCA_PER20_BMP BIT(6)
+#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_SEC_CCA160 BIT(5)
+#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_SEC_CCA80 BIT(4)
+#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_SEC_CCA40 BIT(3)
+#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_SEC_CCA20 BIT(2)
+#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_EDCCA BIT(1)
+#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_CCA BIT(0)
+
+#define R_BE_WMAC_RX_MURTS_RESP_LEGACY 0x11214
+#define R_BE_WMAC_RX_MURTS_RESP_LEGACY_C1 0x15214
+#define B_BE_MURTS_RESP_LEGACY_CHK_NSTR BIT(16)
+#define B_BE_MURTS_RESP_LEGACY_CHK_TX_NAV BIT(15)
+#define B_BE_MURTS_RESP_LEGACY_CHK_INTRA_NAV BIT(14)
+#define B_BE_MURTS_RESP_LEGACY_CHK_BASIC_NAV BIT(13)
+#define B_BE_MURTS_RESP_LEGACY_CHK_BTCCA BIT(12)
+#define B_BE_MURTS_RESP_LEGACY_CHK_SEC_EDCCA160 BIT(11)
+#define B_BE_MURTS_RESP_LEGACY_CHK_SEC_EDCCA80 BIT(10)
+#define B_BE_MURTS_RESP_LEGACY_CHK_SEC_EDCCA40 BIT(9)
+#define B_BE_MURTS_RESP_LEGACY_CHK_SEC_EDCCA20 BIT(8)
+#define B_BE_MURTS_RESP_LEGACY_CHK_EDCCA_PER20_BMP BIT(7)
+#define B_BE_MURTS_RESP_LEGACY_CHK_CCA_PER20_BMP BIT(6)
+#define B_BE_MURTS_RESP_LEGACY_CHK_SEC_CCA160 BIT(5)
+#define B_BE_MURTS_RESP_LEGACY_CHK_SEC_CCA80 BIT(4)
+#define B_BE_MURTS_RESP_LEGACY_CHK_SEC_CCA40 BIT(3)
+#define B_BE_MURTS_RESP_LEGACY_CHK_SEC_CCA20 BIT(2)
+#define B_BE_MURTS_RESP_LEGACY_CHK_EDCCA BIT(1)
+#define B_BE_MURTS_RESP_LEGACY_CHK_CCA BIT(0)
+
+#define R_BE_WMAC_RX_MURTS_RESP_LEGACY_PUNC 0x11218
+#define R_BE_WMAC_RX_MURTS_RESP_LEGACY_PUNC_C1 0x15218
+#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_NSTR BIT(16)
+#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_TX_NAV BIT(15)
+#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_INTRA_NAV BIT(14)
+#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_BASIC_NAV BIT(13)
+#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_BTCCA BIT(12)
+#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_SEC_EDCCA160 BIT(11)
+#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_SEC_EDCCA80 BIT(10)
+#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_SEC_EDCCA40 BIT(9)
+#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_SEC_EDCCA20 BIT(8)
+#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_EDCCA_PER20_BMP BIT(7)
+#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_CCA_PER20_BMP BIT(6)
+#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_SEC_CCA160 BIT(5)
+#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_SEC_CCA80 BIT(4)
+#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_SEC_CCA40 BIT(3)
+#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_SEC_CCA20 BIT(2)
+#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_EDCCA BIT(1)
+#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_CCA BIT(0)
+
+#define R_BE_WMAC_OTHERS_RESP_LEGACY 0x1121C
+#define R_BE_WMAC_OTHERS_RESP_LEGACY_C1 0x1521C
+#define B_BE_OTHERS_RESP_LEGACY_CHK_NSTR BIT(16)
+#define B_BE_OTHERS_RESP_LEGACY_CHK_TX_NAV BIT(15)
+#define B_BE_OTHERS_RESP_LEGACY_CHK_INTRA_NAV BIT(14)
+#define B_BE_OTHERS_RESP_LEGACY_CHK_BASIC_NAV BIT(13)
+#define B_BE_OTHERS_RESP_LEGACY_CHK_BTCCA BIT(12)
+#define B_BE_OTHERS_RESP_LEGACY_CHK_SEC_EDCCA160 BIT(11)
+#define B_BE_OTHERS_RESP_LEGACY_CHK_SEC_EDCCA80 BIT(10)
+#define B_BE_OTHERS_RESP_LEGACY_CHK_SEC_EDCCA40 BIT(9)
+#define B_BE_OTHERS_RESP_LEGACY_CHK_SEC_EDCCA20 BIT(8)
+#define B_BE_OTHERS_RESP_LEGACY_CHK_EDCCA_PER20_BMP BIT(7)
+#define B_BE_OTHERS_RESP_LEGACY_CHK_CCA_PER20_BMP BIT(6)
+#define B_BE_OTHERS_RESP_LEGACY_CHK_SEC_CCA160 BIT(5)
+#define B_BE_OTHERS_RESP_LEGACY_CHK_SEC_CCA80 BIT(4)
+#define B_BE_OTHERS_RESP_LEGACY_CHK_SEC_CCA40 BIT(3)
+#define B_BE_OTHERS_RESP_LEGACY_CHK_SEC_CCA20 BIT(2)
+#define B_BE_OTHERS_RESP_LEGACY_CHK_EDCCA BIT(1)
+#define B_BE_OTHERS_RESP_LEGACY_CHK_CCA BIT(0)
+
+#define R_BE_WMAC_OTHERS_RESP_HE 0x11220
+#define R_BE_WMAC_OTHERS_RESP_HE_C1 0x15220
+#define B_BE_OTHERS_RESP_HE_CHK_NSTR BIT(16)
+#define B_BE_OTHERS_RESP_HE_CHK_TX_NAV BIT(15)
+#define B_BE_OTHERS_RESP_HE_CHK_INTRA_NAV BIT(14)
+#define B_BE_OTHERS_RESP_HE_CHK_BASIC_NAV BIT(13)
+#define B_BE_OTHERS_RESP_HE_CHK_BTCCA BIT(12)
+#define B_BE_OTHERS_RESP_HE_CHK_SEC_EDCCA160 BIT(11)
+#define B_BE_OTHERS_RESP_HE_CHK_SEC_EDCCA80 BIT(10)
+#define B_BE_OTHERS_RESP_HE_CHK_SEC_EDCCA40 BIT(9)
+#define B_BE_OTHERS_RESP_HE_CHK_SEC_EDCCA20 BIT(8)
+#define B_BE_OTHERS_RESP_HE_CHK_EDCCA_PER20_BMP BIT(7)
+#define B_BE_OTHERS_RESP_HE_CHK_CCA_PER20_BMP BIT(6)
+#define B_BE_OTHERS_RESP_HE_CHK_SEC_CCA160 BIT(5)
+#define B_BE_OTHERS_RESP_HE_CHK_SEC_CCA80 BIT(4)
+#define B_BE_OTHERS_RESP_HE_CHK_SEC_CCA40 BIT(3)
+#define B_BE_OTHERS_RESP_HE_CHK_SEC_CCA20 BIT(2)
+#define B_BE_OTHERS_RESP_HE_CHK_EDCCA BIT(1)
+#define B_BE_OTHERS_RESP_HE_CHK_CCA BIT(0)
+
+#define R_BE_WMAC_OTHERS_RESP_EHT_LEG_PUNC 0x11224
+#define R_BE_WMAC_OTHERS_RESP_EHT_LEG_PUNC_C1 0x15224
+#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_NSTR BIT(16)
+#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_TX_NAV BIT(15)
+#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_INTRA_NAV BIT(14)
+#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_BASIC_NAV BIT(13)
+#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_BTCCA BIT(12)
+#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_SEC_EDCCA160 BIT(11)
+#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_SEC_EDCCA80 BIT(10)
+#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_SEC_EDCCA40 BIT(9)
+#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_SEC_EDCCA20 BIT(8)
+#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_EDCCA_PER20_BMP BIT(7)
+#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_CCA_PER20_BMP BIT(6)
+#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_SEC_CCA160 BIT(5)
+#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_SEC_CCA80 BIT(4)
+#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_SEC_CCA40 BIT(3)
+#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_SEC_CCA20 BIT(2)
+#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_EDCCA BIT(1)
+#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_CCA BIT(0)
+
#define R_BE_RCR 0x11400
#define R_BE_RCR_C1 0x15400
#define B_BE_BUSY_CHKSN BIT(15)
@@ -7427,6 +8020,17 @@
#define B_BE_CCK_SIG_CHK BIT(1)
#define B_BE_CCK_CRC_CHK BIT(0)
+#define R_BE_RXGCK_CTRL 0x11406
+#define R_BE_RXGCK_CTRL_C1 0x15406
+#define B_BE_RXGCK_BCNPRS_DISGCLK BIT(12)
+#define B_BE_RXGCK_GCK_RATE_LIMIT_MASK GENMASK(9, 8)
+#define RX_GCK_LEGACY 2
+#define B_BE_RXGCK_DISREG_GCLK BIT(7)
+#define B_BE_RXGCK_ENTRY_DELAY_MASK GENMASK(6, 4)
+#define B_BE_RXGCK_GCK_CYCLE_MASK GENMASK(3, 2)
+#define B_BE_RXGCK_CCA_EN BIT(1)
+#define B_BE_DISGCLK BIT(0)
+
#define R_BE_RX_FLTR_OPT 0x11420
#define R_BE_RX_FLTR_OPT_C1 0x15420
#define B_BE_UID_FILTER_MASK GENMASK(31, 24)
@@ -7521,6 +8125,11 @@
#define B_BE_CSIPRT_HESU_AID_EN BIT(25)
#define B_BE_CSIPRT_VHTSU_AID_EN BIT(24)
+#define R_BE_BSR_UPD_CTRL 0x11468
+#define R_BE_BSR_UPD_CTRL_C1 0x15468
+#define B_BE_QSIZE_RULE BIT(1)
+#define B_BE_QSIZE_UPD BIT(0)
+
#define R_BE_DRV_INFO_OPTION 0x11470
#define R_BE_DRV_INFO_OPTION_C1 0x15470
#define B_BE_DRV_INFO_PHYRPT_EN BIT(0)
@@ -7586,11 +8195,35 @@
#define B_BE_PLCP_CH20_WIDATA_SRC BIT(1)
#define B_BE_PLCP_PPDU_TYPE_SRC BIT(0)
+#define R_BE_RX_PLCP_EXT_OPTION_2 0x11518
+#define R_BE_RX_PLCP_EXT_OPTION_2_C1 0x15518
+#define B_BE_PLCP_PHASE_B_CRC_CHK_EN BIT(17)
+#define B_BE_PLCP_PHASE_A_CRC_CHK_EN BIT(16)
+#define B_BE_EHTTB_EHTSIG_CRC_CHK_EN BIT(3)
+#define B_BE_EHTTB_USIG_CRC_CHK_EN BIT(2)
+#define B_BE_EHTMU_EHTSIG_CRC_CHK_EN BIT(1)
+#define B_BE_EHTMU_USIG_CRC_CHK_EN BIT(0)
+
#define R_BE_RESP_CSI_RESERVED_PAGE 0x11810
#define R_BE_RESP_CSI_RESERVED_PAGE_C1 0x15810
#define B_BE_CSI_RESERVED_PAGE_NUM_MASK GENMASK(27, 16)
#define B_BE_CSI_RESERVED_START_PAGE_MASK GENMASK(11, 0)
+#define R_BE_RESP_IMR1 0x11878
+#define R_BE_RESP_IMR1_C1 0x15878
+#define B_BE_RESP_IMR_1_MASK GENMASK(31, 9)
+#define B_BE_FSM_TIMEOUT_ERR_IMR BIT(8)
+#define B_BE_SEC_DOUBLE_HIT_ERR_IMR BIT(7)
+#define B_BE_WRPTR_ERR_IMR BIT(6)
+#define B_BE_SMR_TOO_MANY_PLD_ERR_IMR BIT(5)
+#define B_BE_LMR_TOO_MANY_PLD_ERR_IMR BIT(4)
+#define B_BE_CSI_TOO_MANY_PLD_ERR_IMR BIT(3)
+#define B_BE_FTM_LMR_PLDID_READY_ERR_IMR BIT(2)
+#define B_BE_SMR_PLDID_READY_ERR_IMR BIT(1)
+#define B_BE_CSI_PLDID_READY_ERR_IMR BIT(0)
+#define B_BE_RESP_IMR1_CLR 0x1FF
+#define B_BE_RESP_IMR1_SET 0xFF
+
#define R_BE_RESP_IMR 0x11884
#define R_BE_RESP_IMR_C1 0x15884
#define B_BE_RESP_TBL_FLAG_ERR_ISR_EN BIT(17)
@@ -7635,6 +8268,8 @@
B_BE_RESP_PLDID_RDY_ERR_ISR_EN | \
B_BE_RESP_WRPTR_CROSS_ERR_ISR_EN | \
B_BE_RESP_SEC_DOUBLE_HIT_ERR_ISR_EN)
+#define B_BE_RESP_IMR_CLR_V1 0xFFFFFFFF
+#define B_BE_RESP_IMR_SET_V1 0xFFFFFFFF
#define R_BE_PWR_MODULE 0x11900
#define R_BE_PWR_MODULE_C1 0x15900
@@ -7693,6 +8328,7 @@
#define R_BE_PWR_FTM 0x11B00
#define R_BE_PWR_FTM_SS 0x11B04
+#define B_BE_PWR_BY_RATE_DBW_ON GENMASK(27, 26)
#define R_BE_PWR_BY_RATE 0x11E00
#define R_BE_PWR_BY_RATE_MAX 0x11FA8
@@ -7713,6 +8349,10 @@
#define R_BE_TXPWR_ERR_FLAG_C1 0x158E4
#define R_BE_TXPWR_ERR_IMR_C1 0x158E0
+#define R_BE_SCH_EXT_CTRL 0x103FC
+#define R_BE_SCH_EXT_CTRL_C1 0x143FC
+#define B_BE_CWCNT_PLUS_MODE BIT(31)
+
#define CMAC1_START_ADDR_BE 0x14000
#define CMAC1_END_ADDR_BE 0x17FFF
@@ -7997,6 +8637,7 @@
#define B_UPD_P0_EN BIT(31)
#define R_EMLSR 0x0044
#define B_EMLSR_PARM GENMASK(27, 12)
+#define R_CHK_LPS_STAT_BE4 0x3007C
#define R_CHK_LPS_STAT 0x0058
#define B_CHK_LPS_STAT BIT(0)
#define R_SPOOF_CG 0x00B4
@@ -8070,10 +8711,12 @@
#define R_MAC_PIN_SEL 0x0734
#define B_CH_IDX_SEG0 GENMASK(23, 16)
#define R_PLCP_HISTOGRAM 0x0738
+#define R_PLCP_HISTOGRAM_BE_V1 0x20738
#define B_STS_PARSING_TIME GENMASK(19, 16)
#define B_STS_DIS_TRIG_BY_FAIL BIT(3)
#define B_STS_DIS_TRIG_BY_BRK BIT(2)
#define R_PHY_STS_BITMAP_ADDR_START R_PHY_STS_BITMAP_SEARCH_FAIL
+#define R_PHY_STS_BITMAP_ADDR_START_BE4 0x2073C
#define B_PHY_STS_BITMAP_ADDR_MASK GENMASK(6, 2)
#define R_PHY_STS_BITMAP_SEARCH_FAIL 0x073C
#define B_PHY_STS_BITMAP_MSK_52A 0x337cff3f
@@ -8092,6 +8735,7 @@
#define R_PHY_STS_BITMAP_VHT 0x0770
#define R_PHY_STS_BITMAP_HE 0x0774
#define R_PHY_STS_BITMAP_EHT 0x0788
+#define R_PHY_STS_BITMAP_EHT_BE4 0x20788
#define R_EDCCA_RPTREG_SEL_BE 0x078C
#define B_EDCCA_RPTREG_SEL_BE_MSK GENMASK(22, 20)
#define R_PMAC_GNT 0x0980
@@ -8122,6 +8766,7 @@
#define R_DBCC_80P80_SEL_EVM_RPT 0x0A10
#define B_DBCC_80P80_SEL_EVM_RPT_EN BIT(0)
#define R_CCX 0x0C00
+#define R_CCX_BE4 0x20C00
#define B_CCX_EDCCA_OPT_MSK GENMASK(6, 4)
#define B_CCX_EDCCA_OPT_MSK_V1 GENMASK(7, 4)
#define B_MEASUREMENT_TRIG_MSK BIT(2)
@@ -8150,34 +8795,42 @@
#define R_FAHM 0x0C1C
#define B_RXTD_CKEN BIT(2)
#define R_IFS_COUNTER 0x0C28
+#define R_IFS_COUNTER_BE4 0x20C28
#define B_IFS_CLM_PERIOD_MSK GENMASK(31, 16)
#define B_IFS_CLM_COUNTER_UNIT_MSK GENMASK(15, 14)
#define B_IFS_COUNTER_CLR_MSK BIT(13)
#define B_IFS_COLLECT_EN BIT(12)
#define R_IFS_T1 0x0C2C
+#define R_IFS_T1_BE4 0x20C2C
#define B_IFS_T1_TH_HIGH_MSK GENMASK(31, 16)
#define B_IFS_T1_EN_MSK BIT(15)
#define B_IFS_T1_TH_LOW_MSK GENMASK(14, 0)
#define R_IFS_T2 0x0C30
+#define R_IFS_T2_BE4 0x20C30
#define B_IFS_T2_TH_HIGH_MSK GENMASK(31, 16)
#define B_IFS_T2_EN_MSK BIT(15)
#define B_IFS_T2_TH_LOW_MSK GENMASK(14, 0)
#define R_IFS_T3 0x0C34
+#define R_IFS_T3_BE4 0x20C34
#define B_IFS_T3_TH_HIGH_MSK GENMASK(31, 16)
#define B_IFS_T3_EN_MSK BIT(15)
#define B_IFS_T3_TH_LOW_MSK GENMASK(14, 0)
#define R_IFS_T4 0x0C38
+#define R_IFS_T4_BE4 0x20C38
#define B_IFS_T4_TH_HIGH_MSK GENMASK(31, 16)
#define B_IFS_T4_EN_MSK BIT(15)
#define B_IFS_T4_TH_LOW_MSK GENMASK(14, 0)
#define R_PD_CTRL 0x0C3C
#define B_PD_HIT_DIS BIT(9)
#define R_IOQ_IQK_DPK 0x0C60
+#define R_IOQ_IQK_DPK_BE4 0x20C60
#define B_IOQ_IQK_DPK_CLKEN GENMASK(1, 0)
#define B_IOQ_IQK_DPK_EN BIT(1)
+#define B_IOQ_IQK_DPK_RST BIT(0)
#define R_GNT_BT_WGT_EN 0x0C6C
#define B_GNT_BT_WGT_EN BIT(21)
#define R_IQK_DPK_RST 0x0C6C
+#define R_IQK_DPK_RST_BE4 0x20C6C
#define R_IQK_DPK_RST_C1 0x1C6C
#define B_IQK_DPK_RST BIT(0)
#define R_TX_COLLISION_T2R_ST 0x0C70
@@ -8295,14 +8948,17 @@
#define B_NHM_READY_MSK BIT(16)
#define R_IFS_CLM_TX_CNT 0x1ACC
#define R_IFS_CLM_TX_CNT_V1 0x0ECC
+#define R_IFS_CLM_TX_CNT_BE4 0x20ECC
#define B_IFS_CLM_EDCCA_EXCLUDE_CCA_FA_MSK GENMASK(31, 16)
#define B_IFS_CLM_TX_CNT_MSK GENMASK(15, 0)
#define R_IFS_CLM_CCA 0x1AD0
#define R_IFS_CLM_CCA_V1 0x0ED0
+#define R_IFS_CLM_CCA_BE4 0x20ED0
#define B_IFS_CLM_OFDMCCA_EXCLUDE_FA_MSK GENMASK(31, 16)
#define B_IFS_CLM_CCKCCA_EXCLUDE_FA_MSK GENMASK(15, 0)
#define R_IFS_CLM_FA 0x1AD4
#define R_IFS_CLM_FA_V1 0x0ED4
+#define R_IFS_CLM_FA_BE4 0x20ED4
#define B_IFS_CLM_OFDM_FA_MSK GENMASK(31, 16)
#define B_IFS_CLM_CCK_FA_MSK GENMASK(15, 0)
#define R_IFS_HIS 0x1AD8
@@ -8959,12 +9615,14 @@
#define B_S0_DACKQ7_K GENMASK(15, 8)
#define R_S0_DACKQ8 0x5E98
#define B_S0_DACKQ8_K GENMASK(15, 8)
-#define R_DCFO_WEIGHT_V1 0x6244
-#define B_DCFO_WEIGHT_MSK_V1 GENMASK(31, 28)
+#define R_DCFO_WEIGHT_BE 0x6244
+#define R_DCFO_WEIGHT_BE_V1 0x24808
+#define B_DCFO_WEIGHT_MSK_BE GENMASK(31, 28)
#define R_DAC_CLK 0x625C
#define B_DAC_CLK GENMASK(31, 30)
-#define R_DCFO_OPT_V1 0x6260
-#define B_DCFO_OPT_EN_V1 BIT(17)
+#define R_DCFO_OPT_BE 0x6260
+#define R_DCFO_OPT_BE_V1 0x24824
+#define B_DCFO_OPT_EN_BE BIT(17)
#define R_TXFCTR 0x627C
#define B_TXFCTR_THD GENMASK(19, 10)
#define R_TXSCALE 0x6284
@@ -9474,10 +10132,14 @@
#define R_GAIN_MAP1 0xE54C
#define B_GAIN_MAP1_EN BIT(0)
#define R_GOTX_IQKDPK_C0 0xE464
+#define R_GOTX_IQKDPK_C0_BE4 0x2E464
#define R_GOTX_IQKDPK_C1 0xE564
+#define R_GOTX_IQKDPK_C1_BE4 0x2E564
#define B_GOTX_IQKDPK GENMASK(28, 27)
#define R_IQK_DPK_PRST 0xE4AC
+#define R_IQK_DPK_PRST_BE4 0x2E4AC
#define R_IQK_DPK_PRST_C1 0xE5AC
+#define R_IQK_DPK_PRST_C1_BE4 0x2E5AC
#define B_IQK_DPK_PRST BIT(27)
#define R_TXPWR_RSTA 0xE60C
#define B_TXPWR_RSTA BIT(16)
@@ -9504,6 +10166,258 @@
#define R_TSSI_K_P1 0xE7A0
#define B_TSSI_K_OFDM_P1 GENMASK(29, 20)
+#define R_COMP_CIM3K_BE4 0x11998
+#define B_COMP_CIM3K_OW_BE4 BIT(1)
+#define B_COMP_CIM3K_TH_BE4 BIT(2)
+#define B_COMP_CIM3K_TH2_BE4 GENMASK(5, 3)
+#define B_COMP_CIM3K_TXPWR_EN_BE4 BIT(6)
+#define B_COMP_CIM3K_NONBE_BE4 BIT(7)
+#define B_COMP_CIM3K_BANDEDGE_BE4 BIT(8)
+#define R_DPD_CBW160_BE4 0x119B4
+#define B_DPD_CBW160_TH0_BE4 BIT(0)
+#define B_DPD_CBW160_TH1_BE4 BIT(1)
+#define B_DPD_CBW160_TH2_BE4 BIT(2)
+#define B_DPD_CBW160_TH3_BE4 BIT(3)
+#define B_DPD_CBW160_TH4_BE4 BIT(4)
+#define B_DPD_CBW160_TH5_BE4 BIT(5)
+#define B_DPD_CBW160_TH6_BE4 BIT(6)
+#define B_DPD_CBW160_TH7_BE4 BIT(7)
+#define B_DPD_CBW160_OW0_BE4 BIT(8)
+#define B_DPD_CBW160_OW1_BE4 BIT(9)
+#define B_DPD_CBW160_OW2_BE4 BIT(10)
+#define B_DPD_CBW160_OW3_BE4 BIT(11)
+#define B_DPD_CBW160_OW4_BE4 BIT(12)
+#define B_DPD_CBW160_OW5_BE4 BIT(13)
+#define B_DPD_CBW160_OW6_BE4 BIT(14)
+#define B_DPD_CBW160_OW7_BE4 BIT(15)
+#define R_OOB_CBW20_BE4 0x119B4
+#define B_OOB_CBW20_CCK0_BE4 BIT(16)
+#define B_OOB_CBW20_CCK1_BE4 BIT(17)
+#define B_OOB_CBW20_CCK2_BE4 BIT(18)
+#define B_OOB_CBW20_CCK3_BE4 BIT(19)
+#define B_OOB_CBW20_CCK4_BE4 BIT(20)
+#define B_OOB_CBW20_CCK5_BE4 BIT(21)
+#define B_OOB_CBW20_CCK6_BE4 BIT(22)
+#define B_OOB_CBW20_CCK7_BE4 BIT(23)
+#define B_OOB_CBW20_TH0_BE4 BIT(24)
+#define B_OOB_CBW20_TH1_BE4 BIT(25)
+#define B_OOB_CBW20_TH2_BE4 BIT(26)
+#define B_OOB_CBW20_TH3_BE4 BIT(27)
+#define B_OOB_CBW20_TH4_BE4 BIT(28)
+#define B_OOB_CBW20_TH5_BE4 BIT(29)
+#define B_OOB_CBW20_TH6_BE4 BIT(30)
+#define B_OOB_CBW20_TH7_BE4 BIT(31)
+#define R_OOB_CBW40_BE4 0x119B8
+#define B_OOB_CBW20_OW0_BE4 BIT(0)
+#define B_OOB_CBW20_OW1_BE4 BIT(1)
+#define B_OOB_CBW20_OW2_BE4 BIT(2)
+#define B_OOB_CBW20_OW3_BE4 BIT(3)
+#define B_OOB_CBW20_OW4_BE4 BIT(4)
+#define B_OOB_CBW20_OW5_BE4 BIT(5)
+#define B_OOB_CBW20_OW6_BE4 BIT(6)
+#define B_OOB_CBW20_OW7_BE4 BIT(7)
+#define B_OOB_CBW40_CCK0_BE4 BIT(8)
+#define B_OOB_CBW40_CCK1_BE4 BIT(9)
+#define B_OOB_CBW40_CCK2_BE4 BIT(10)
+#define B_OOB_CBW40_CCK3_BE4 BIT(11)
+#define B_OOB_CBW40_CCK4_BE4 BIT(12)
+#define B_OOB_CBW40_CCK5_BE4 BIT(13)
+#define B_OOB_CBW40_CCK6_BE4 BIT(14)
+#define B_OOB_CBW40_CCK7_BE4 BIT(15)
+#define B_OOB_CBW40_TH0_BE4 BIT(16)
+#define B_OOB_CBW40_TH1_BE4 BIT(17)
+#define B_OOB_CBW40_TH2_BE4 BIT(18)
+#define B_OOB_CBW40_TH3_BE4 BIT(19)
+#define B_OOB_CBW40_TH4_BE4 BIT(20)
+#define B_OOB_CBW40_TH5_BE4 BIT(21)
+#define B_OOB_CBW40_TH6_BE4 BIT(22)
+#define B_OOB_CBW40_TH7_BE4 BIT(23)
+#define B_OOB_CBW40_OW0_BE4 BIT(24)
+#define B_OOB_CBW40_OW1_BE4 BIT(25)
+#define B_OOB_CBW40_OW2_BE4 BIT(26)
+#define B_OOB_CBW40_OW3_BE4 BIT(27)
+#define B_OOB_CBW40_OW4_BE4 BIT(28)
+#define B_OOB_CBW40_OW5_BE4 BIT(29)
+#define B_OOB_CBW40_OW6_BE4 BIT(30)
+#define B_OOB_CBW40_OW7_BE4 BIT(31)
+#define R_OOB_CBW80_BE4 0x119BC
+#define B_OOB_CBW80_TH0_BE4 BIT(0)
+#define B_OOB_CBW80_TH1_BE4 BIT(1)
+#define B_OOB_CBW80_TH2_BE4 BIT(2)
+#define B_OOB_CBW80_TH3_BE4 BIT(3)
+#define B_OOB_CBW80_TH4_BE4 BIT(4)
+#define B_OOB_CBW80_TH5_BE4 BIT(5)
+#define B_OOB_CBW80_TH6_BE4 BIT(6)
+#define B_OOB_CBW80_TH7_BE4 BIT(7)
+#define B_OOB_CBW80_OW0_BE4 BIT(8)
+#define B_OOB_CBW80_OW1_BE4 BIT(9)
+#define B_OOB_CBW80_OW2_BE4 BIT(10)
+#define B_OOB_CBW80_OW3_BE4 BIT(11)
+#define B_OOB_CBW80_OW4_BE4 BIT(12)
+#define B_OOB_CBW80_OW5_BE4 BIT(13)
+#define B_OOB_CBW80_OW6_BE4 BIT(14)
+#define B_OOB_CBW80_OW7_BE4 BIT(15)
+#define R_DPD_DBW160_TH0_BE4 0x119BC
+#define B_DPD_DBW160_TH0_0_BE4 GENMASK(18, 16)
+#define B_DPD_DBW160_TH0_1_BE4 GENMASK(21, 19)
+#define B_DPD_DBW160_TH0_2_BE4 GENMASK(24, 22)
+#define B_DPD_DBW160_TH0_3_BE4 GENMASK(27, 25)
+#define B_DPD_DBW160_TH0_4_BE4 GENMASK(30, 28)
+#define R_DPD_DBW160_TH1_BE4 0x119C0
+#define B_DPD_DBW160_TH1_5_BE4 GENMASK(2, 0)
+#define B_DPD_DBW160_TH1_6_BE4 GENMASK(5, 3)
+#define B_DPD_DBW160_TH1_7_BE4 GENMASK(8, 6)
+#define R_DPD_CBW_TH0_BE4 0x119C0
+#define B_DPD_CBW20_TH0_0_BE4 GENMASK(11, 9)
+#define B_DPD_CBW20_TH0_1_BE4 GENMASK(14, 12)
+#define B_DPD_CBW20_TH0_2_BE4 GENMASK(17, 15)
+#define B_DPD_CBW20_TH0_3_BE4 GENMASK(20, 18)
+#define B_DPD_CBW20_TH0_4_BE4 GENMASK(23, 21)
+#define B_DPD_CBW20_TH0_5_BE4 GENMASK(26, 24)
+#define B_DPD_CBW20_TH0_6_BE4 GENMASK(29, 27)
+#define R_DPD_CBW_TH1_BE4 0x119C4
+#define B_DPD_CBW20_TH1_7_BE4 GENMASK(2, 0)
+#define B_DPD_CBW40_TH1_0_BE4 GENMASK(5, 3)
+#define B_DPD_CBW40_TH1_1_BE4 GENMASK(8, 6)
+#define B_DPD_CBW40_TH1_2_BE4 GENMASK(11, 9)
+#define B_DPD_CBW40_TH1_3_BE4 GENMASK(14, 12)
+#define B_DPD_CBW40_TH1_4_BE4 GENMASK(17, 15)
+#define B_DPD_CBW40_TH1_5_BE4 GENMASK(20, 18)
+#define B_DPD_CBW40_TH1_6_BE4 GENMASK(23, 21)
+#define B_DPD_CBW40_TH1_7_BE4 GENMASK(26, 24)
+#define B_DPD_CBW80_TH1_0_BE4 GENMASK(29, 27)
+#define R_DPD_CBW_TH2_BE4 0x119C8
+#define B_DPD_CBW80_TH2_1_BE4 GENMASK(2, 0)
+#define B_DPD_CBW80_TH2_2_BE4 GENMASK(5, 3)
+#define B_DPD_CBW80_TH2_3_BE4 GENMASK(8, 6)
+#define B_DPD_CBW80_TH2_4_BE4 GENMASK(11, 9)
+#define B_DPD_CBW80_TH2_5_BE4 GENMASK(14, 12)
+#define B_DPD_CBW80_TH2_6_BE4 GENMASK(17, 15)
+#define B_DPD_CBW80_TH2_7_BE4 GENMASK(20, 18)
+#define R_QAM_TH0_BE4 0x119E4
+#define B_QAM_TH0_0_BE4 GENMASK(18, 16)
+#define B_QAM_TH0_1_BE4 GENMASK(21, 19)
+#define B_QAM_TH0_2_BE4 GENMASK(24, 22)
+#define B_QAM_TH0_3_BE4 GENMASK(27, 25)
+#define B_QAM_TH0_4_BE4 GENMASK(30, 28)
+#define R_QAM_TH1_BE4 0x119E8
+#define B_QAM_TH1_0_BE4 GENMASK(2, 0)
+#define B_QAM_TH1_1_BE4 GENMASK(5, 3)
+#define B_QAM_TH1_2_BE4 GENMASK(8, 6)
+#define B_QAM_TH1_3_BE4 GENMASK(11, 9)
+#define B_QAM_TH1_4_BE4 GENMASK(14, 12)
+#define B_QAM_TH1_5_BE4 GENMASK(17, 15)
+#define B_QAM_TH1_6_BE4 GENMASK(20, 18)
+#define B_QAM_TH1_7_BE4 GENMASK(23, 21)
+#define B_QAM_TH1_8_BE4 GENMASK(26, 24)
+#define B_QAM_TH1_9_BE4 GENMASK(29, 27)
+#define R_QAM_TH2_BE4 0x119EC
+#define B_QAM_TH2_0_BE4 GENMASK(2, 0)
+#define B_QAM_TH2_1_BE4 GENMASK(5, 3)
+#define B_QAM_TH2_2_BE4 GENMASK(8, 6)
+#define B_QAM_TH2_3_BE4 GENMASK(11, 9)
+#define B_QAM_TH2_4_BE4 GENMASK(14, 12)
+#define B_QAM_TH2_5_BE4 GENMASK(17, 15)
+#define B_QAM_TH2_6_BE4 GENMASK(20, 18)
+#define B_QAM_TH2_7_BE4 GENMASK(23, 21)
+#define B_QAM_TH2_8_BE4 GENMASK(26, 24)
+#define R_RFSI_CT_DEF_BE4 0x119F0
+#define B_RFSI_CT_ER_BE4 GENMASK(18, 15)
+#define B_RFSI_CT_SUBF_BE4 GENMASK(22, 19)
+#define B_RFSI_CT_FTM_BE4 GENMASK(26, 23)
+#define B_RFSI_CT_SENS_BE4 GENMASK(30, 27)
+#define R_FBTB_CT_DEF_BE4 0x119F4
+#define B_FBTB_CT_DEF_BE GENMASK(3, 0)
+#define B_FBTB_CT_PB_BE4 GENMASK(7, 4)
+#define B_FBTB_CT_DL_WO_BE4 GENMASK(11, 8)
+#define B_FBTB_CT_DL_BF_BE4 GENMASK(15, 12)
+#define B_FBTB_CT_MUMIMO_BE4 GENMASK(19, 16)
+#define B_FBTB_CT_FTM_BE4 GENMASK(23, 20)
+#define B_FBTB_CT_SENS_BE4 GENMASK(27, 24)
+#define R_RFSI_CT_OPT_0_BE4 0x11A94
+#define R_RFSI_CT_OPT_8_BE4 0x11A98
+#define R_QAM_COMP_TH0_BE4 0x11A9C
+#define R_QAM_COMP_TH1_BE4 0x11AA0
+#define R_QAM_COMP_TH2_BE4 0x11AA4
+#define R_QAM_COMP_TH3_BE4 0x11AA8
+#define R_QAM_COMP_TH4_BE4 0x11ABC
+#define B_QAM_COMP_TH4_L GENMASK(4, 0)
+#define B_QAM_COMP_TH4_M GENMASK(14, 10)
+#define B_QAM_COMP_TH4_H GENMASK(24, 20)
+#define B_QAM_COMP_TH4_2L GENMASK(9, 5)
+#define B_QAM_COMP_TH4_2M GENMASK(19, 15)
+#define B_QAM_COMP_TH4_2H GENMASK(29, 25)
+#define R_QAM_COMP_TH5_BE4 0x11AC0
+#define B_QAM_COMP_TH5_L GENMASK(4, 0)
+#define B_QAM_COMP_TH5_M GENMASK(14, 10)
+#define B_QAM_COMP_TH5_H GENMASK(24, 20)
+#define B_QAM_COMP_TH5_2L GENMASK(9, 5)
+#define B_QAM_COMP_TH5_2M GENMASK(19, 15)
+#define B_QAM_COMP_TH5_2H GENMASK(29, 25)
+#define R_QAM_COMP_TH6_BE4 0x11AC4
+#define B_QAM_COMP_TH6_L GENMASK(4, 0)
+#define B_QAM_COMP_TH6_M GENMASK(14, 10)
+#define B_QAM_COMP_TH6_2L GENMASK(9, 5)
+#define B_QAM_COMP_TH6_2M GENMASK(19, 15)
+#define R_OW_VAL_0_BE4 0x11AAC
+#define R_OW_VAL_1_BE4 0x11AB0
+#define R_OW_VAL_2_BE4 0x11AB4
+#define R_OW_VAL_3_BE4 0x11AB8
+#define R_BANDEDGE_DBWX_BE4 0x11ACC
+#define B_BANDEDGE_DBW20_BE4 BIT(29)
+#define B_BANDEDGE_DBW40_BE4 BIT(30)
+#define B_BANDEDGE_DBW80_BE4 BIT(31)
+#define R_BANDEDGE_DBWY_BE4 0x11AD0
+#define B_BANDEDGE_DBW160_BE4 BIT(0)
+
+#define R_CHINFO_SEG_BE4 0x200B4
+#define B_CHINFO_SEG_LEN_BE4 GENMASK(12, 10)
+#define R_STS_HDR2_PARSING_BE4 0x2070C
+#define B_STS_HDR2_PARSING_BE4 BIT(10)
+#define R_SW_SI_WDATA_BE4 0x20370
+#define B_SW_SI_DATA_PATH_BE4 GENMASK(31, 28)
+#define B_SW_SI_DATA_ADR_BE4 GENMASK(27, 20)
+#define B_SW_SI_DATA_DAT_BE4 GENMASK(19, 0)
+#define R_SW_SI_READ_ADDR_BE4 0x20378
+#define B_SW_SI_READ_ADDR_BE4 GENMASK(10, 0)
+#define R_IFS_T1_AVG_BE4 0x20EDC
+#define B_IFS_T1_AVG_BE4 GENMASK(15, 0)
+#define B_IFS_T2_AVG_BE4 GENMASK(31, 16)
+#define R_IFS_T3_AVG_BE4 0x20EE0
+#define B_IFS_T3_AVG_BE4 GENMASK(15, 0)
+#define B_IFS_T4_AVG_BE4 GENMASK(31, 16)
+#define R_IFS_T1_CLM_BE4 0x20EE4
+#define B_IFS_T1_CLM_BE4 GENMASK(15, 0)
+#define B_IFS_T2_CLM_BE4 GENMASK(31, 16)
+#define R_IFS_T3_CLM_BE4 0x20EE8
+#define B_IFS_T3_CLM_BE4 GENMASK(15, 0)
+#define B_IFS_T4_CLM_BE4 GENMASK(31, 16)
+#define R_IFS_TOTAL_BE4 0x20EEC
+#define B_IFS_TOTAL_BE4 GENMASK(15, 0)
+#define B_IFS_CNT_DONE_BE4 BIT(16)
+#define R_IFS_T1_HIS_BE4 0x20F50
+#define B_IFS_T1_HIS_BE4 GENMASK(15, 0)
+#define B_IFS_T2_HIS_BE4 GENMASK(31, 16)
+#define R_IFS_T3_HIS_BE4 0x20F54
+#define B_IFS_T3_HIS_BE4 GENMASK(15, 0)
+#define B_IFS_T4_HIS_BE4 GENMASK(31, 16)
+
+#define R_TX_CFR_MANUAL_EN_BE4 0x2483C
+#define B_TX_CFR_MANUAL_EN_BE4_M BIT(30)
+
+#define R_CHINFO_OPT_BE4 0x267C8
+#define B_CHINFO_OPT_BE4 GENMASK(14, 13)
+#define R_CHINFO_NX_BE4 0x267D0
+#define B_CHINFO_NX_BE4 GENMASK(16, 6)
+#define R_CHINFO_ALG_BE4 0x267C8
+#define B_CHINFO_ALG_BE4 GENMASK(31, 30)
+
+#define R_SW_SI_DATA_BE4 0x2CF4C
+#define B_SW_SI_READ_DATA_BE4 GENMASK(19, 0)
+#define B_SW_SI_W_BUSY_BE4 BIT(24)
+#define B_SW_SI_R_BUSY_BE4 BIT(25)
+#define B_SW_SI_READ_DATA_DONE_BE4 BIT(26)
+
/* WiFi CPU local domain */
#define R_AX_WDT_CTRL 0x0040
#define B_AX_WDT_EN BIT(31)
diff --git a/drivers/net/wireless/realtek/rtw89/regd.c b/drivers/net/wireless/realtek/rtw89/regd.c
index 209d84909f88..28466cb35ea2 100644
--- a/drivers/net/wireless/realtek/rtw89/regd.c
+++ b/drivers/net/wireless/realtek/rtw89/regd.c
@@ -38,7 +38,7 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("MX", RTW89_MEXICO, RTW89_MEXICO, RTW89_FCC, 0x0),
COUNTRY_REGD("NI", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
COUNTRY_REGD("PA", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
- COUNTRY_REGD("PY", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
+ COUNTRY_REGD("PY", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
COUNTRY_REGD("PE", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
COUNTRY_REGD("US", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x1),
COUNTRY_REGD("UY", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
@@ -95,7 +95,7 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("MK", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
COUNTRY_REGD("MA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
COUNTRY_REGD("MZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
- COUNTRY_REGD("NA", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
+ COUNTRY_REGD("NA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
COUNTRY_REGD("NG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
COUNTRY_REGD("OM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
COUNTRY_REGD("QA", RTW89_QATAR, RTW89_QATAR, RTW89_QATAR, 0x0),
@@ -111,12 +111,12 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("AE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
COUNTRY_REGD("YE", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
COUNTRY_REGD("ZW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
- COUNTRY_REGD("BD", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
+ COUNTRY_REGD("BD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
COUNTRY_REGD("KH", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
COUNTRY_REGD("CN", RTW89_CN, RTW89_CN, RTW89_CN, 0x0),
COUNTRY_REGD("HK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
COUNTRY_REGD("IN", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
- COUNTRY_REGD("ID", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
+ COUNTRY_REGD("ID", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
COUNTRY_REGD("KR", RTW89_KCC, RTW89_KCC, RTW89_KCC, 0x1),
COUNTRY_REGD("MY", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
COUNTRY_REGD("PK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
@@ -125,7 +125,7 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("LK", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
COUNTRY_REGD("TW", RTW89_FCC, RTW89_FCC, RTW89_ETSI, 0x0),
COUNTRY_REGD("TH", RTW89_THAILAND, RTW89_THAILAND, RTW89_THAILAND, 0x0),
- COUNTRY_REGD("VN", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
+ COUNTRY_REGD("VN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
COUNTRY_REGD("AU", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA, 0x0),
COUNTRY_REGD("NZ", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA, 0x0),
COUNTRY_REGD("PG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
@@ -134,7 +134,7 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("JM", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
COUNTRY_REGD("AN", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
COUNTRY_REGD("TT", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
- COUNTRY_REGD("TN", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
+ COUNTRY_REGD("TN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
COUNTRY_REGD("AF", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
COUNTRY_REGD("DZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
COUNTRY_REGD("AS", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
@@ -187,9 +187,9 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("GM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
COUNTRY_REGD("GE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
COUNTRY_REGD("GI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
- COUNTRY_REGD("GL", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
+ COUNTRY_REGD("GL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
COUNTRY_REGD("GD", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
- COUNTRY_REGD("GP", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
+ COUNTRY_REGD("GP", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
COUNTRY_REGD("GU", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
COUNTRY_REGD("GG", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
COUNTRY_REGD("GN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
@@ -214,7 +214,7 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("MQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
COUNTRY_REGD("MR", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
COUNTRY_REGD("MU", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
- COUNTRY_REGD("YT", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
+ COUNTRY_REGD("YT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
COUNTRY_REGD("FM", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
COUNTRY_REGD("MD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
COUNTRY_REGD("MN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
@@ -260,7 +260,7 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("UZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
COUNTRY_REGD("VU", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
COUNTRY_REGD("WF", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
- COUNTRY_REGD("EH", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
+ COUNTRY_REGD("EH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
COUNTRY_REGD("ZM", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
COUNTRY_REGD("CU", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
COUNTRY_REGD("IR", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
@@ -1142,6 +1142,7 @@ static int rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev,
}
} else {
rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
+ dflt = true;
}
rcu_read_unlock();
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
index 84b628d23882..d6deb44a685b 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
@@ -633,8 +633,6 @@ static int rtw8851b_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map,
efuse->rfe_type = map->rfe_type;
efuse->xtal_cap = map->xtal_k;
- rtw89_info(rtwdev, "chip rfe_type is %d\n", efuse->rfe_type);
-
return 0;
}
@@ -2532,6 +2530,7 @@ static const struct rtw89_chip_ops rtw8851b_chip_ops = {
.cfg_txrx_path = rtw8851b_bb_cfg_txrx_path,
.set_txpwr_ul_tb_offset = rtw8851b_set_txpwr_ul_tb_offset,
.digital_pwr_comp = NULL,
+ .calc_rx_gain_normal = NULL,
.pwr_on_func = rtw8851b_pwr_on_func,
.pwr_off_func = rtw8851b_pwr_off_func,
.query_rxdesc = rtw89_core_query_rxdesc,
@@ -2553,6 +2552,7 @@ static const struct rtw89_chip_ops rtw8851b_chip_ops = {
.h2c_default_dmac_tbl = NULL,
.h2c_update_beacon = rtw89_fw_h2c_update_beacon,
.h2c_ba_cam = rtw89_fw_h2c_ba_cam,
+ .h2c_wow_cam_update = rtw89_fw_h2c_wow_cam_update,
.btc_set_rfe = rtw8851b_btc_set_rfe,
.btc_init_cfg = rtw8851b_btc_init_cfg,
@@ -2590,6 +2590,10 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
.small_fifo_size = true,
.dle_scc_rsvd_size = 98304,
.max_amsdu_limit = 3500,
+ .max_vht_mpdu_cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454,
+ .max_eht_mpdu_cap = 0,
+ .max_tx_agg_num = 128,
+ .max_rx_agg_num = 64,
.dis_2g_40m_ul_ofdma = true,
.rsvd_ple_ofst = 0x2f800,
.hfc_param_ini = {rtw8851b_hfc_param_ini_pcie,
@@ -2704,6 +2708,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
.bss_clr_map_reg = R_BSS_CLR_MAP_V1,
.rfkill_init = &rtw8851b_rfkill_regs,
.rfkill_get = {R_AX_GPIO_EXT_CTRL, B_AX_GPIO_IN_9},
+ .btc_sb = {{{R_AX_SCOREBOARD, R_AX_SCOREBOARD},}},
.dma_ch_mask = BIT(RTW89_DMA_ACH4) | BIT(RTW89_DMA_ACH5) |
BIT(RTW89_DMA_ACH6) | BIT(RTW89_DMA_ACH7) |
BIT(RTW89_DMA_B1MG) | BIT(RTW89_DMA_B1HI),
@@ -2712,6 +2717,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
.wowlan_stub = &rtw_wowlan_stub_8851b,
#endif
.xtal_info = &rtw8851b_xtal_info,
+ .default_quirks = 0,
};
EXPORT_SYMBOL(rtw8851b_chip_info);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
index 8677723e3561..5ea7a36ab5ab 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
@@ -678,8 +678,6 @@ static int rtw8852a_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map,
efuse->rfe_type = map->rfe_type;
efuse->xtal_cap = map->xtal_k;
- rtw89_info(rtwdev, "chip rfe_type is %d\n", efuse->rfe_type);
-
return 0;
}
@@ -2226,6 +2224,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = {
.cfg_txrx_path = NULL,
.set_txpwr_ul_tb_offset = rtw8852a_set_txpwr_ul_tb_offset,
.digital_pwr_comp = NULL,
+ .calc_rx_gain_normal = NULL,
.pwr_on_func = NULL,
.pwr_off_func = NULL,
.query_rxdesc = rtw89_core_query_rxdesc,
@@ -2247,6 +2246,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = {
.h2c_default_dmac_tbl = NULL,
.h2c_update_beacon = rtw89_fw_h2c_update_beacon,
.h2c_ba_cam = rtw89_fw_h2c_ba_cam,
+ .h2c_wow_cam_update = rtw89_fw_h2c_wow_cam_update,
.btc_set_rfe = rtw8852a_btc_set_rfe,
.btc_init_cfg = rtw8852a_btc_init_cfg,
@@ -2275,6 +2275,10 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
.small_fifo_size = false,
.dle_scc_rsvd_size = 0,
.max_amsdu_limit = 3500,
+ .max_vht_mpdu_cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454,
+ .max_eht_mpdu_cap = 0,
+ .max_tx_agg_num = 128,
+ .max_rx_agg_num = 64,
.dis_2g_40m_ul_ofdma = true,
.rsvd_ple_ofst = 0x6f800,
.hfc_param_ini = {rtw8852a_hfc_param_ini_pcie,
@@ -2391,12 +2395,14 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
.bss_clr_map_reg = R_BSS_CLR_MAP,
.rfkill_init = &rtw8852a_rfkill_regs,
.rfkill_get = {R_AX_GPIO_EXT_CTRL, B_AX_GPIO_IN_9},
+ .btc_sb = {{{R_AX_SCOREBOARD, R_AX_SCOREBOARD},}},
.dma_ch_mask = 0,
.edcca_regs = &rtw8852a_edcca_regs,
#ifdef CONFIG_PM
.wowlan_stub = &rtw_wowlan_stub_8852a,
#endif
.xtal_info = &rtw8852a_xtal_info,
+ .default_quirks = 0,
};
EXPORT_SYMBOL(rtw8852a_chip_info);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852au.c b/drivers/net/wireless/realtek/rtw89/rtw8852au.c
index ca782469c455..ccdbcc178c2a 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852au.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852au.c
@@ -52,6 +52,8 @@ static const struct usb_device_id rtw_8852au_id_table[] = {
.driver_info = (kernel_ulong_t)&rtw89_8852au_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3321, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&rtw89_8852au_info },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3323, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&rtw89_8852au_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x332c, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&rtw89_8852au_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x013f, 0xff, 0xff, 0xff),
@@ -60,6 +62,8 @@ static const struct usb_device_id rtw_8852au_id_table[] = {
.driver_info = (kernel_ulong_t)&rtw89_8852au_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0141, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&rtw89_8852au_info },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3625, 0x010d, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&rtw89_8852au_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x3625, 0x010f, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&rtw89_8852au_info },
{},
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
index 70fb05bc5e98..197e3f5fb21b 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
@@ -313,6 +313,27 @@ static void rtw8852b_pwr_sps_ana(struct rtw89_dev *rtwdev)
rtw89_write16(rtwdev, R_AX_SPS_ANA_ON_CTRL2, RTL8852B_RFE_05_SPS_ANA);
}
+static void rtw8852b_pwr_sps_dig_off(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_efuse *efuse = &rtwdev->efuse;
+
+ if (efuse->rfe_type == 0x5) {
+ rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_OFF_CTRL0,
+ B_AX_C1_L1_MASK, 0x1);
+ rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_OFF_CTRL0,
+ B_AX_C2_L1_MASK, 0x1);
+ rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_OFF_CTRL0,
+ B_AX_C3_L1_MASK, 0x2);
+ rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_OFF_CTRL0,
+ B_AX_R1_L1_MASK, 0x1);
+ } else {
+ rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_OFF_CTRL0,
+ B_AX_C1_L1_MASK, 0x1);
+ rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_OFF_CTRL0,
+ B_AX_C3_L1_MASK, 0x3);
+ }
+}
+
static int rtw8852b_pwr_on_func(struct rtw89_dev *rtwdev)
{
u32 val32;
@@ -338,8 +359,7 @@ static int rtw8852b_pwr_on_func(struct rtw89_dev *rtwdev)
if (ret)
return ret;
- rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_OFF_CTRL0, B_AX_C1_L1_MASK, 0x1);
- rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_OFF_CTRL0, B_AX_C3_L1_MASK, 0x3);
+ rtw8852b_pwr_sps_dig_off(rtwdev);
rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_EN_WLON);
rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFN_ONMAC);
@@ -837,6 +857,7 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = {
.cfg_txrx_path = rtw8852bx_bb_cfg_txrx_path,
.set_txpwr_ul_tb_offset = rtw8852bx_set_txpwr_ul_tb_offset,
.digital_pwr_comp = NULL,
+ .calc_rx_gain_normal = NULL,
.pwr_on_func = rtw8852b_pwr_on_func,
.pwr_off_func = rtw8852b_pwr_off_func,
.query_rxdesc = rtw89_core_query_rxdesc,
@@ -858,6 +879,7 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = {
.h2c_default_dmac_tbl = NULL,
.h2c_update_beacon = rtw89_fw_h2c_update_beacon,
.h2c_ba_cam = rtw89_fw_h2c_ba_cam,
+ .h2c_wow_cam_update = rtw89_fw_h2c_wow_cam_update,
.btc_set_rfe = rtw8852b_btc_set_rfe,
.btc_init_cfg = rtw8852bx_btc_init_cfg,
@@ -899,6 +921,10 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
.small_fifo_size = true,
.dle_scc_rsvd_size = 98304,
.max_amsdu_limit = 5000,
+ .max_vht_mpdu_cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454,
+ .max_eht_mpdu_cap = 0,
+ .max_tx_agg_num = 128,
+ .max_rx_agg_num = 64,
.dis_2g_40m_ul_ofdma = true,
.rsvd_ple_ofst = 0x2f800,
.hfc_param_ini = {rtw8852b_hfc_param_ini_pcie,
@@ -1016,6 +1042,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
.bss_clr_map_reg = R_BSS_CLR_MAP_V1,
.rfkill_init = &rtw8852b_rfkill_regs,
.rfkill_get = {R_AX_GPIO_EXT_CTRL, B_AX_GPIO_IN_9},
+ .btc_sb = {{{R_AX_SCOREBOARD, R_AX_SCOREBOARD},}},
.dma_ch_mask = BIT(RTW89_DMA_ACH4) | BIT(RTW89_DMA_ACH5) |
BIT(RTW89_DMA_ACH6) | BIT(RTW89_DMA_ACH7) |
BIT(RTW89_DMA_B1MG) | BIT(RTW89_DMA_B1HI),
@@ -1024,6 +1051,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
.wowlan_stub = &rtw_wowlan_stub_8852b,
#endif
.xtal_info = NULL,
+ .default_quirks = 0,
};
EXPORT_SYMBOL(rtw8852b_chip_info);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c b/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c
index 4e72f4961837..65b839323e3e 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c
@@ -265,8 +265,6 @@ static int __rtw8852bx_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map,
efuse->rfe_type = map->rfe_type;
efuse->xtal_cap = map->xtal_k;
- rtw89_info(rtwdev, "chip rfe_type is %d\n", efuse->rfe_type);
-
return 0;
}
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
index f956474c3b72..92bbd6e5d699 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
@@ -703,6 +703,7 @@ static const struct rtw89_chip_ops rtw8852bt_chip_ops = {
.cfg_txrx_path = rtw8852bx_bb_cfg_txrx_path,
.set_txpwr_ul_tb_offset = rtw8852bx_set_txpwr_ul_tb_offset,
.digital_pwr_comp = NULL,
+ .calc_rx_gain_normal = NULL,
.pwr_on_func = rtw8852bt_pwr_on_func,
.pwr_off_func = rtw8852bt_pwr_off_func,
.query_rxdesc = rtw89_core_query_rxdesc,
@@ -724,6 +725,7 @@ static const struct rtw89_chip_ops rtw8852bt_chip_ops = {
.h2c_default_dmac_tbl = NULL,
.h2c_update_beacon = rtw89_fw_h2c_update_beacon,
.h2c_ba_cam = rtw89_fw_h2c_ba_cam,
+ .h2c_wow_cam_update = rtw89_fw_h2c_wow_cam_update,
.btc_set_rfe = rtw8852bt_btc_set_rfe,
.btc_init_cfg = rtw8852bx_btc_init_cfg,
@@ -765,6 +767,10 @@ const struct rtw89_chip_info rtw8852bt_chip_info = {
.small_fifo_size = true,
.dle_scc_rsvd_size = 98304,
.max_amsdu_limit = 5000,
+ .max_vht_mpdu_cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454,
+ .max_eht_mpdu_cap = 0,
+ .max_tx_agg_num = 128,
+ .max_rx_agg_num = 64,
.dis_2g_40m_ul_ofdma = true,
.rsvd_ple_ofst = 0x6f800,
.hfc_param_ini = {rtw8852bt_hfc_param_ini_pcie, NULL, NULL},
@@ -873,6 +879,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = {
.bss_clr_map_reg = R_BSS_CLR_MAP_V1,
.rfkill_init = &rtw8852bt_rfkill_regs,
.rfkill_get = {R_AX_GPIO_EXT_CTRL, B_AX_GPIO_IN_9},
+ .btc_sb = {{{R_AX_SCOREBOARD, R_AX_SCOREBOARD},}},
.dma_ch_mask = BIT(RTW89_DMA_ACH4) | BIT(RTW89_DMA_ACH5) |
BIT(RTW89_DMA_ACH6) | BIT(RTW89_DMA_ACH7) |
BIT(RTW89_DMA_B1MG) | BIT(RTW89_DMA_B1HI),
@@ -881,6 +888,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = {
.wowlan_stub = &rtw_wowlan_stub_8852bt,
#endif
.xtal_info = NULL,
+ .default_quirks = 0,
};
EXPORT_SYMBOL(rtw8852bt_chip_info);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bu.c b/drivers/net/wireless/realtek/rtw89/rtw8852bu.c
index 980d17ef68d0..84cd3ec971f9 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852bu.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852bu.c
@@ -54,6 +54,8 @@ static const struct usb_device_id rtw_8852bu_id_table[] = {
.driver_info = (kernel_ulong_t)&rtw89_8852bu_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x0db0, 0x6931, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&rtw89_8852bu_info },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0db0, 0xf0c8, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&rtw89_8852bu_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3327, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&rtw89_8852bu_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x3574, 0x6121, 0xff, 0xff, 0xff),
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
index db99450e9158..de5d343f80a5 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
@@ -600,8 +600,6 @@ static int rtw8852c_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map,
efuse->rfe_type = map->rfe_type;
efuse->xtal_cap = map->xtal_k;
- rtw89_info(rtwdev, "chip rfe_type is %d\n", efuse->rfe_type);
-
return 0;
}
@@ -3067,6 +3065,7 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
.cfg_txrx_path = rtw8852c_bb_cfg_txrx_path,
.set_txpwr_ul_tb_offset = rtw8852c_set_txpwr_ul_tb_offset,
.digital_pwr_comp = NULL,
+ .calc_rx_gain_normal = NULL,
.pwr_on_func = rtw8852c_pwr_on_func,
.pwr_off_func = rtw8852c_pwr_off_func,
.query_rxdesc = rtw89_core_query_rxdesc,
@@ -3088,6 +3087,7 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
.h2c_default_dmac_tbl = NULL,
.h2c_update_beacon = rtw89_fw_h2c_update_beacon,
.h2c_ba_cam = rtw89_fw_h2c_ba_cam,
+ .h2c_wow_cam_update = rtw89_fw_h2c_wow_cam_update,
.btc_set_rfe = rtw8852c_btc_set_rfe,
.btc_init_cfg = rtw8852c_btc_init_cfg,
@@ -3116,6 +3116,10 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
.small_fifo_size = false,
.dle_scc_rsvd_size = 0,
.max_amsdu_limit = 8000,
+ .max_vht_mpdu_cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454,
+ .max_eht_mpdu_cap = 0,
+ .max_tx_agg_num = 128,
+ .max_rx_agg_num = 64,
.dis_2g_40m_ul_ofdma = false,
.rsvd_ple_ofst = 0x6f800,
.hfc_param_ini = {rtw8852c_hfc_param_ini_pcie,
@@ -3236,12 +3240,14 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
.bss_clr_map_reg = R_BSS_CLR_MAP,
.rfkill_init = &rtw8852c_rfkill_regs,
.rfkill_get = {R_AX_GPIO_EXT_CTRL, B_AX_GPIO_IN_9},
+ .btc_sb = {{{R_AX_SCOREBOARD, R_AX_SCOREBOARD},}},
.dma_ch_mask = 0,
.edcca_regs = &rtw8852c_edcca_regs,
#ifdef CONFIG_PM
.wowlan_stub = &rtw_wowlan_stub_8852c,
#endif
.xtal_info = NULL,
+ .default_quirks = 0,
};
EXPORT_SYMBOL(rtw8852c_chip_info);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852cu.c b/drivers/net/wireless/realtek/rtw89/rtw8852cu.c
index 2708b523ca14..3b9825c92a0d 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852cu.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852cu.c
@@ -46,6 +46,8 @@ static const struct usb_device_id rtw_8852cu_id_table[] = {
.driver_info = (kernel_ulong_t)&rtw89_8852cu_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x0db0, 0x991d, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&rtw89_8852cu_info },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x28de, 0x2432, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&rtw89_8852cu_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x35b2, 0x0502, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&rtw89_8852cu_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x35bc, 0x0101, 0xff, 0xff, 0xff),
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
index 4437279c554b..f41b66b362c4 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
@@ -628,24 +628,36 @@ static int rtw8922a_read_efuse_rf(struct rtw89_dev *rtwdev, u8 *log_map)
rtw8922a_efuse_parsing_tssi(rtwdev, map);
rtw8922a_efuse_parsing_gain_offset(rtwdev, map);
- rtw89_info(rtwdev, "chip rfe_type is %d\n", efuse->rfe_type);
-
return 0;
}
static int rtw8922a_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map,
enum rtw89_efuse_block block)
{
+ struct rtw89_efuse *efuse = &rtwdev->efuse;
+ int ret;
+
switch (block) {
case RTW89_EFUSE_BLOCK_HCI_DIG_PCIE_SDIO:
- return rtw8922a_read_efuse_pci_sdio(rtwdev, log_map);
+ ret = rtw8922a_read_efuse_pci_sdio(rtwdev, log_map);
+ break;
case RTW89_EFUSE_BLOCK_HCI_DIG_USB:
- return rtw8922a_read_efuse_usb(rtwdev, log_map);
+ ret = rtw8922a_read_efuse_usb(rtwdev, log_map);
+ break;
case RTW89_EFUSE_BLOCK_RF:
- return rtw8922a_read_efuse_rf(rtwdev, log_map);
+ ret = rtw8922a_read_efuse_rf(rtwdev, log_map);
+ break;
default:
- return 0;
+ ret = 0;
+ break;
+ }
+
+ if (!ret && is_zero_ether_addr(efuse->addr)) {
+ rtw89_info(rtwdev, "efuse mac address is zero, using random mac\n");
+ eth_random_addr(efuse->addr);
}
+
+ return ret;
}
#define THM_TRIM_POSITIVE_MASK BIT(6)
@@ -1756,6 +1768,32 @@ static int rtw8922a_ctrl_rx_path_tmac(struct rtw89_dev *rtwdev,
}
#define DIGITAL_PWR_COMP_REG_NUM 22
+static const u32 rtw8922a_digital_pwr_comp_2g_s0_val[][DIGITAL_PWR_COMP_REG_NUM] = {
+ {0x012C0064, 0x04B00258, 0x00432710, 0x019000A7, 0x06400320,
+ 0x0D05091D, 0x14D50FA0, 0x00000000, 0x01010000, 0x00000101,
+ 0x01010101, 0x02020201, 0x02010000, 0x03030202, 0x00000303,
+ 0x03020101, 0x06060504, 0x01010000, 0x06050403, 0x01000606,
+ 0x05040202, 0x07070706},
+ {0x012C0064, 0x04B00258, 0x00432710, 0x019000A7, 0x06400320,
+ 0x0D05091D, 0x14D50FA0, 0x00000000, 0x01010100, 0x00000101,
+ 0x01000000, 0x01010101, 0x01010000, 0x02020202, 0x00000404,
+ 0x03020101, 0x04040303, 0x02010000, 0x03030303, 0x00000505,
+ 0x03030201, 0x05050303},
+};
+
+static const u32 rtw8922a_digital_pwr_comp_2g_s1_val[][DIGITAL_PWR_COMP_REG_NUM] = {
+ {0x012C0064, 0x04B00258, 0x00432710, 0x019000A7, 0x06400320,
+ 0x0D05091D, 0x14D50FA0, 0x01010000, 0x01010101, 0x00000101,
+ 0x01010100, 0x01010101, 0x01010000, 0x02020202, 0x01000202,
+ 0x02020101, 0x03030202, 0x02010000, 0x05040403, 0x01000606,
+ 0x05040302, 0x07070605},
+ {0x012C0064, 0x04B00258, 0x00432710, 0x019000A7, 0x06400320,
+ 0x0D05091D, 0x14D50FA0, 0x00000000, 0x01010100, 0x00000101,
+ 0x01010000, 0x02020201, 0x02010100, 0x03030202, 0x01000404,
+ 0x04030201, 0x05050404, 0x01010100, 0x04030303, 0x01000505,
+ 0x03030101, 0x05050404},
+};
+
static const u32 rtw8922a_digital_pwr_comp_val[][DIGITAL_PWR_COMP_REG_NUM] = {
{0x012C0096, 0x044C02BC, 0x00322710, 0x015E0096, 0x03C8028A,
0x0BB80708, 0x17701194, 0x02020100, 0x03030303, 0x01000303,
@@ -1770,7 +1808,7 @@ static const u32 rtw8922a_digital_pwr_comp_val[][DIGITAL_PWR_COMP_REG_NUM] = {
};
static void rtw8922a_set_digital_pwr_comp(struct rtw89_dev *rtwdev,
- bool enable, u8 nss,
+ u8 band, u8 nss,
enum rtw89_rf_path path)
{
static const u32 ltpc_t0[2] = {R_BE_LTPC_T0_PATH0, R_BE_LTPC_T0_PATH1};
@@ -1778,14 +1816,25 @@ static void rtw8922a_set_digital_pwr_comp(struct rtw89_dev *rtwdev,
u32 addr, val;
u32 i;
- if (nss == 1)
- digital_pwr_comp = rtw8922a_digital_pwr_comp_val[0];
- else
- digital_pwr_comp = rtw8922a_digital_pwr_comp_val[1];
+ if (nss == 1) {
+ if (band == RTW89_BAND_2G)
+ digital_pwr_comp = path == RF_PATH_A ?
+ rtw8922a_digital_pwr_comp_2g_s0_val[0] :
+ rtw8922a_digital_pwr_comp_2g_s1_val[0];
+ else
+ digital_pwr_comp = rtw8922a_digital_pwr_comp_val[0];
+ } else {
+ if (band == RTW89_BAND_2G)
+ digital_pwr_comp = path == RF_PATH_A ?
+ rtw8922a_digital_pwr_comp_2g_s0_val[1] :
+ rtw8922a_digital_pwr_comp_2g_s1_val[1];
+ else
+ digital_pwr_comp = rtw8922a_digital_pwr_comp_val[1];
+ }
addr = ltpc_t0[path];
for (i = 0; i < DIGITAL_PWR_COMP_REG_NUM; i++, addr += 4) {
- val = enable ? digital_pwr_comp[i] : 0;
+ val = digital_pwr_comp[i];
rtw89_phy_write32(rtwdev, addr, val);
}
}
@@ -1794,7 +1843,7 @@ static void rtw8922a_digital_pwr_comp(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx)
{
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_CHANCTX_0);
- bool enable = chan->band_type != RTW89_BAND_2G;
+ u8 band = chan->band_type;
u8 path;
if (rtwdev->mlo_dbcc_mode == MLO_1_PLUS_1_1RF) {
@@ -1802,10 +1851,10 @@ static void rtw8922a_digital_pwr_comp(struct rtw89_dev *rtwdev,
path = RF_PATH_A;
else
path = RF_PATH_B;
- rtw8922a_set_digital_pwr_comp(rtwdev, enable, 1, path);
+ rtw8922a_set_digital_pwr_comp(rtwdev, band, 1, path);
} else {
- rtw8922a_set_digital_pwr_comp(rtwdev, enable, 2, RF_PATH_A);
- rtw8922a_set_digital_pwr_comp(rtwdev, enable, 2, RF_PATH_B);
+ rtw8922a_set_digital_pwr_comp(rtwdev, band, 2, RF_PATH_A);
+ rtw8922a_set_digital_pwr_comp(rtwdev, band, 2, RF_PATH_B);
}
}
@@ -2826,6 +2875,7 @@ static const struct rtw89_chip_ops rtw8922a_chip_ops = {
.cfg_txrx_path = rtw8922a_bb_cfg_txrx_path,
.set_txpwr_ul_tb_offset = NULL,
.digital_pwr_comp = rtw8922a_digital_pwr_comp,
+ .calc_rx_gain_normal = NULL,
.pwr_on_func = rtw8922a_pwr_on_func,
.pwr_off_func = rtw8922a_pwr_off_func,
.query_rxdesc = rtw89_core_query_rxdesc_v2,
@@ -2847,6 +2897,7 @@ static const struct rtw89_chip_ops rtw8922a_chip_ops = {
.h2c_default_dmac_tbl = rtw89_fw_h2c_default_dmac_tbl_v2,
.h2c_update_beacon = rtw89_fw_h2c_update_beacon_be,
.h2c_ba_cam = rtw89_fw_h2c_ba_cam_v1,
+ .h2c_wow_cam_update = rtw89_fw_h2c_wow_cam_update,
.btc_set_rfe = rtw8922a_btc_set_rfe,
.btc_init_cfg = rtw8922a_btc_init_cfg,
@@ -2875,6 +2926,10 @@ const struct rtw89_chip_info rtw8922a_chip_info = {
.small_fifo_size = false,
.dle_scc_rsvd_size = 0,
.max_amsdu_limit = 8000,
+ .max_vht_mpdu_cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454,
+ .max_eht_mpdu_cap = IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_7991,
+ .max_tx_agg_num = 128,
+ .max_rx_agg_num = 64,
.dis_2g_40m_ul_ofdma = false,
.rsvd_ple_ofst = 0x8f800,
.hfc_param_ini = {rtw8922a_hfc_param_ini_pcie, NULL, NULL},
@@ -2988,12 +3043,14 @@ const struct rtw89_chip_info rtw8922a_chip_info = {
.bss_clr_map_reg = R_BSS_CLR_MAP_V2,
.rfkill_init = &rtw8922a_rfkill_regs,
.rfkill_get = {R_BE_GPIO_EXT_CTRL, B_BE_GPIO_IN_9},
+ .btc_sb = {{{R_BE_SCOREBOARD, R_BE_SCOREBOARD},}},
.dma_ch_mask = 0,
.edcca_regs = &rtw8922a_edcca_regs,
#ifdef CONFIG_PM
.wowlan_stub = &rtw_wowlan_stub_8922a,
#endif
.xtal_info = NULL,
+ .default_quirks = 0,
};
EXPORT_SYMBOL(rtw8922a_chip_info);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c
index fce094c7ce93..98f14b31cf52 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c
@@ -205,11 +205,11 @@ static void rtw8922a_chlk_ktbl_sel(struct rtw89_dev *rtwdev, u8 kpath, u8 idx)
}
}
-static u8 rtw8922a_chlk_reload_sel_tbl(struct rtw89_dev *rtwdev,
- const struct rtw89_chan *chan, u8 path)
+static u8 rtw8922a_chlk_reload_sel_tbl_v0(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan, u8 path)
{
- struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc;
struct rtw89_rfk_chan_desc desc[__RTW89_RFK_CHS_NR_V1] = {};
+ struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc;
u8 tbl_sel;
for (tbl_sel = 0; tbl_sel < ARRAY_SIZE(desc); tbl_sel++) {
@@ -229,11 +229,53 @@ static u8 rtw8922a_chlk_reload_sel_tbl(struct rtw89_dev *rtwdev,
rfk_mcc->data[path].ch[tbl_sel] = chan->channel;
rfk_mcc->data[path].band[tbl_sel] = chan->band_type;
rfk_mcc->data[path].bw[tbl_sel] = chan->band_width;
+ rfk_mcc->data[path].rf18[tbl_sel] = rtw89_chip_chan_to_rf18_val(rtwdev, chan);
rfk_mcc->data[path].table_idx = tbl_sel;
return tbl_sel;
}
+static u8 rtw8922a_chlk_reload_sel_tbl_v1(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan, u8 path)
+{
+ struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data;
+ struct rtw89_rfk_chan_desc desc[__RTW89_RFK_CHS_NR_V1] = {};
+ u8 tbl_sel;
+
+ for (tbl_sel = 0; tbl_sel < ARRAY_SIZE(desc); tbl_sel++) {
+ struct rtw89_rfk_chan_desc *p = &desc[tbl_sel];
+
+ p->ch = rfk_mcc->ch[tbl_sel];
+
+ p->has_band = true;
+ p->band = rfk_mcc->band[tbl_sel];
+
+ p->has_bw = true;
+ p->bw = rfk_mcc->bw[tbl_sel];
+ }
+
+ tbl_sel = rtw89_rfk_chan_lookup(rtwdev, desc, ARRAY_SIZE(desc), chan);
+
+ rfk_mcc->ch[tbl_sel] = chan->channel;
+ rfk_mcc->band[tbl_sel] = chan->band_type;
+ rfk_mcc->bw[tbl_sel] = chan->band_width;
+ rfk_mcc->rf18[tbl_sel] = rtw89_chip_chan_to_rf18_val(rtwdev, chan);
+
+ /* shared table array, but tbl_sel can be independent by path */
+ rfk_mcc[path].table_idx = tbl_sel;
+
+ return tbl_sel;
+}
+
+static u8 rtw8922a_chlk_reload_sel_tbl(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan, u8 path)
+{
+ if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_MCC_V1, &rtwdev->fw))
+ return rtw8922a_chlk_reload_sel_tbl_v1(rtwdev, chan, path);
+ else
+ return rtw8922a_chlk_reload_sel_tbl_v0(rtwdev, chan, path);
+}
+
static void rtw8922a_chlk_reload(struct rtw89_dev *rtwdev)
{
const struct rtw89_chan *chan0, *chan1;
diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c
index f99e179f7ff9..7fdc69578da3 100644
--- a/drivers/net/wireless/realtek/rtw89/ser.c
+++ b/drivers/net/wireless/realtek/rtw89/ser.c
@@ -431,6 +431,14 @@ static void hal_send_m4_event(struct rtw89_ser *ser)
rtw89_mac_set_err_status(rtwdev, MAC_AX_ERR_L1_RCVY_EN);
}
+static void hal_enable_err_imr(struct rtw89_ser *ser)
+{
+ struct rtw89_dev *rtwdev = container_of(ser, struct rtw89_dev, ser);
+ const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
+
+ mac->err_imr_ctrl(rtwdev, true);
+}
+
/* state handler */
static void ser_idle_st_hdl(struct rtw89_ser *ser, u8 evt)
{
@@ -552,6 +560,8 @@ static void ser_do_hci_st_hdl(struct rtw89_ser *ser, u8 evt)
break;
case SER_EV_MAC_RESET_DONE:
+ hal_enable_err_imr(ser);
+
ser_state_goto(ser, SER_IDLE_ST);
break;
diff --git a/drivers/net/wireless/realtek/rtw89/txrx.h b/drivers/net/wireless/realtek/rtw89/txrx.h
index fa324b4a1dde..b69a2529aefc 100644
--- a/drivers/net/wireless/realtek/rtw89/txrx.h
+++ b/drivers/net/wireless/realtek/rtw89/txrx.h
@@ -188,12 +188,16 @@ static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate)
#define BE_TXD_BODY2_QSEL GENMASK(22, 17)
#define BE_TXD_BODY2_TID_IND BIT(23)
#define BE_TXD_BODY2_MACID GENMASK(31, 24)
+#define BE_TXD_BODY2_QSEL_V1 GENMASK(20, 15)
+#define BE_TXD_BODY2_TID_IND_V1 BIT(21)
+#define BE_TXD_BODY2_MACID_V1 GENMASK(31, 22)
/* TX WD BODY DWORD 3 */
#define BE_TXD_BODY3_WIFI_SEQ GENMASK(11, 0)
#define BE_TXD_BODY3_MLO_FLAG BIT(12)
#define BE_TXD_BODY3_IS_MLD_SW_EN BIT(13)
#define BE_TXD_BODY3_TRY_RATE BIT(14)
+#define BE_TXD_BODY3_BK_V1 BIT(14)
#define BE_TXD_BODY3_RELINK_FLAG_V1 BIT(15)
#define BE_TXD_BODY3_BAND0_SU_TC_V1 GENMASK(21, 16)
#define BE_TXD_BODY3_TOTAL_TC GENMASK(27, 22)
@@ -201,6 +205,7 @@ static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate)
#define BE_TXD_BODY3_MU_PRI_RTY BIT(29)
#define BE_TXD_BODY3_MU_2ND_RTY BIT(30)
#define BE_TXD_BODY3_BAND1_SU_RTY_V1 BIT(31)
+#define BE_TXD_BODY3_DRIVER_QUEUE_TIME GENMASK(31, 16)
/* TX WD BODY DWORD 4 */
#define BE_TXD_BODY4_TXDESC_CHECKSUM GENMASK(15, 0)
@@ -224,6 +229,10 @@ static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate)
#define BE_TXD_BODY6_EOSP_BIT BIT(15)
#define BE_TXD_BODY6_S_IDX GENMASK(23, 16)
#define BE_TXD_BODY6_RU_POS GENMASK(31, 24)
+#define BE_TXD_BODY6_MU_TC_V1 GENMASK(3, 0)
+#define BE_TXD_BODY6_RU_TC_V1 GENMASK(8, 5)
+#define BE_TXD_BODY6_RELINK_EN BIT(9)
+#define BE_TXD_BODY6_RELINK_LAST BIT(10)
/* TX WD BODY DWORD 7 */
#define BE_TXD_BODY7_RTS_TC GENMASK(5, 0)
@@ -262,6 +271,8 @@ static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate)
/* TX WD INFO DWORD 2 */
#define BE_TXD_INFO2_SEC_CAM_IDX GENMASK(7, 0)
#define BE_TXD_INFO2_FORCE_KEY_EN BIT(8)
+#define BE_TXD_INFO2_SEC_CAM_IDX_V1 GENMASK(9, 0)
+#define BE_TXD_INFO2_FORCE_KEY_EN_V1 BIT(10)
#define BE_TXD_INFO2_LIFETIME_SEL GENMASK(15, 13)
#define BE_TXD_INFO2_FORCE_TXOP BIT(17)
#define BE_TXD_INFO2_AMPDU_DENSITY GENMASK(20, 18)
@@ -277,6 +288,7 @@ static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate)
#define BE_TXD_INFO3_RTT_EN BIT(9)
#define BE_TXD_INFO3_HT_DATA_SND_V1 BIT(10)
#define BE_TXD_INFO3_BT_NULL BIT(11)
+#define BE_TXD_INFO3_DISABLE_TXBF BIT(11)
#define BE_TXD_INFO3_TRI_FRAME BIT(12)
#define BE_TXD_INFO3_NULL_0 BIT(13)
#define BE_TXD_INFO3_NULL_1 BIT(14)
@@ -292,6 +304,8 @@ static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate)
#define BE_TXD_INFO4_PUNC_MODE GENMASK(17, 16)
#define BE_TXD_INFO4_SW_TX_OK_0 BIT(18)
#define BE_TXD_INFO4_SW_TX_OK_1 BIT(19)
+#define BE_TXD_INFO4_SW_EHT_NLTF_SWITCH BIT(20)
+#define BE_TXD_INFO4_SW_EHT_NLTF GENMASK(22, 21)
#define BE_TXD_INFO4_SW_TX_PWR_DBM GENMASK(26, 23)
#define BE_TXD_INFO4_RTS_EN BIT(27)
#define BE_TXD_INFO4_CTS2SELF BIT(28)
@@ -308,6 +322,7 @@ static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate)
#define BE_TXD_INFO6_UL_GI_LTF GENMASK(14, 12)
#define BE_TXD_INFO6_UL_DOPPLER BIT(15)
#define BE_TXD_INFO6_UL_STBC BIT(16)
+#define BE_TXD_INFO6_UL_MU_MIMO_EN BIT(17)
#define BE_TXD_INFO6_UL_LENGTH_REF GENMASK(21, 18)
#define BE_TXD_INFO6_UL_RF_GAIN_IDX GENMASK(31, 22)
@@ -322,6 +337,7 @@ static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate)
#define BE_TXD_INFO7_UL_HELTF_SYMBOL_NUM GENMASK(19, 17)
#define BE_TXD_INFO7_ULBW GENMASK(21, 20)
#define BE_TXD_INFO7_ULBW_EXT GENMASK(23, 22)
+#define BE_TXD_INFO7_UL_TRI_PAD_TSF BIT(24)
#define BE_TXD_INFO7_USE_WD_UL GENMASK(25, 24)
#define BE_TXD_INFO7_EXTEND_MODE_SEL GENMASK(31, 28)
@@ -488,6 +504,7 @@ struct rtw89_phy_sts_iehdr {
/* BE RXD dword2 */
#define BE_RXD_MAC_ID_MASK GENMASK(7, 0)
+#define BE_RXD_MAC_ID_V1 GENMASK(9, 0)
#define BE_RXD_TYPE_MASK GENMASK(11, 10)
#define BE_RXD_LAST_MSDU BIT(12)
#define BE_RXD_AMSDU_CUT BIT(13)
@@ -519,6 +536,7 @@ struct rtw89_phy_sts_iehdr {
#define BE_RXD_QNULL BIT(22)
#define BE_RXD_A4_FRAME BIT(23)
#define BE_RXD_FRAG_MASK GENMASK(27, 24)
+#define BE_RXD_GET_CH_INFO_V2 GENMASK(31, 29)
#define BE_RXD_GET_CH_INFO_V1_MASK GENMASK(31, 30)
/* BE RXD dword4 */
@@ -534,10 +552,14 @@ struct rtw89_phy_sts_iehdr {
/* BE RXD dword6 */
#define BE_RXD_ADDR_CAM_MASK GENMASK(7, 0)
+#define BE_RXD_ADDR_CAM_V1 GENMASK(9, 0)
+#define BE_RXD_RX_STATISTICS_V1 BIT(11)
+#define BE_RXD_SMART_ANT_V1 BIT(12)
#define BE_RXD_SR_EN BIT(13)
#define BE_RXD_NON_SRG_PPDU BIT(14)
#define BE_RXD_INTER_PPDU BIT(15)
#define BE_RXD_USER_ID_MASK GENMASK(21, 16)
+#define BE_RXD_SEC_CAM_IDX_V1 GENMASK(31, 22)
#define BE_RXD_RX_STATISTICS BIT(22)
#define BE_RXD_SMART_ANT BIT(23)
#define BE_RXD_SEC_CAM_IDX_MASK GENMASK(31, 24)
diff --git a/drivers/net/wireless/realtek/rtw89/usb.c b/drivers/net/wireless/realtek/rtw89/usb.c
index d7d968207a39..e77561a4d971 100644
--- a/drivers/net/wireless/realtek/rtw89/usb.c
+++ b/drivers/net/wireless/realtek/rtw89/usb.c
@@ -620,7 +620,7 @@ static int rtw89_usb_init_rx(struct rtw89_dev *rtwdev)
struct sk_buff *rx_skb;
int i;
- rtwusb->rxwq = alloc_workqueue("rtw89_usb: rx wq", WQ_BH, 0);
+ rtwusb->rxwq = alloc_workqueue("rtw89_usb: rx wq", WQ_BH | WQ_PERCPU, 0);
if (!rtwusb->rxwq) {
rtw89_err(rtwdev, "failed to create RX work queue\n");
return -ENOMEM;
diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c
index 46aba4cb2ee9..b67ceda59e92 100644
--- a/drivers/net/wireless/realtek/rtw89/wow.c
+++ b/drivers/net/wireless/realtek/rtw89/wow.c
@@ -809,6 +809,10 @@ static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev)
reason = rtw89_read8(rtwdev, wow_reason_reg);
switch (reason) {
+ case RTW89_WOW_RSN_RX_DISASSOC:
+ wakeup.disconnect = true;
+ rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: Rx disassoc\n");
+ break;
case RTW89_WOW_RSN_RX_DEAUTH:
wakeup.disconnect = true;
rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: Rx deauth\n");
@@ -1070,7 +1074,7 @@ static void rtw89_wow_pattern_clear_cam(struct rtw89_dev *rtwdev)
for (i = 0; i < rtw_wow->pattern_cnt; i++) {
rtw_pattern = &rtw_wow->patterns[i];
rtw_pattern->valid = false;
- rtw89_fw_wow_cam_update(rtwdev, rtw_pattern);
+ rtw89_chip_h2c_wow_cam_update(rtwdev, rtw_pattern);
}
}
@@ -1081,7 +1085,7 @@ static void rtw89_wow_pattern_write(struct rtw89_dev *rtwdev)
int i;
for (i = 0; i < rtw_wow->pattern_cnt; i++)
- rtw89_fw_wow_cam_update(rtwdev, rtw_pattern + i);
+ rtw89_chip_h2c_wow_cam_update(rtwdev, rtw_pattern + i);
}
static void rtw89_wow_pattern_clear(struct rtw89_dev *rtwdev)
@@ -1263,15 +1267,15 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow)
enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
const struct rtw89_chip_info *chip = rtwdev->chip;
bool include_bb = !!chip->bbmcu_nr;
- bool disable_intr_for_dlfw = false;
+ bool disable_intr_for_dlfw = true;
struct ieee80211_sta *wow_sta;
struct rtw89_sta_link *rtwsta_link = NULL;
struct rtw89_sta *rtwsta;
bool is_conn = true;
int ret;
- if (chip_id == RTL8852C || chip_id == RTL8922A)
- disable_intr_for_dlfw = true;
+ if (chip->chip_gen == RTW89_CHIP_AX && chip_id != RTL8852C)
+ disable_intr_for_dlfw = false;
wow_sta = ieee80211_find_sta(wow_vif, wow_vif->cfg.ap_addr);
if (wow_sta) {
diff --git a/drivers/net/wireless/realtek/rtw89/wow.h b/drivers/net/wireless/realtek/rtw89/wow.h
index d2ba6cebc2a6..71e07f482174 100644
--- a/drivers/net/wireless/realtek/rtw89/wow.h
+++ b/drivers/net/wireless/realtek/rtw89/wow.h
@@ -33,6 +33,7 @@
enum rtw89_wake_reason {
RTW89_WOW_RSN_RX_PTK_REKEY = 0x1,
RTW89_WOW_RSN_RX_GTK_REKEY = 0x2,
+ RTW89_WOW_RSN_RX_DISASSOC = 0x4,
RTW89_WOW_RSN_RX_DEAUTH = 0x8,
RTW89_WOW_RSN_DISCONNECT = 0x10,
RTW89_WOW_RSN_RX_MAGIC_PKT = 0x21,
diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c
index 2112d8d277a9..a9bb37d5d581 100644
--- a/drivers/net/wireless/rsi/rsi_91x_main.c
+++ b/drivers/net/wireless/rsi/rsi_91x_main.c
@@ -425,35 +425,6 @@ void rsi_91x_deinit(struct rsi_hw *adapter)
}
EXPORT_SYMBOL_GPL(rsi_91x_deinit);
-/**
- * rsi_91x_hal_module_init() - This function is invoked when the module is
- * loaded into the kernel.
- * It registers the client driver.
- * @void: Void.
- *
- * Return: 0 on success, -1 on failure.
- */
-static int rsi_91x_hal_module_init(void)
-{
- rsi_dbg(INIT_ZONE, "%s: Module init called\n", __func__);
- return 0;
-}
-
-/**
- * rsi_91x_hal_module_exit() - This function is called at the time of
- * removing/unloading the module.
- * It unregisters the client driver.
- * @void: Void.
- *
- * Return: None.
- */
-static void rsi_91x_hal_module_exit(void)
-{
- rsi_dbg(INIT_ZONE, "%s: Module exit called\n", __func__);
-}
-
-module_init(rsi_91x_hal_module_init);
-module_exit(rsi_91x_hal_module_exit);
MODULE_AUTHOR("Redpine Signals Inc");
MODULE_DESCRIPTION("Station driver for RSI 91x devices");
MODULE_VERSION("0.1");
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index 1e578533e473..ee7ad81c858d 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -1443,9 +1443,8 @@ static int rsi_thaw(struct device *dev)
return 0;
}
-static void rsi_shutdown(struct device *dev)
+static void rsi_shutdown(struct sdio_func *pfunction)
{
- struct sdio_func *pfunction = dev_to_sdio_func(dev);
struct rsi_hw *adapter = sdio_get_drvdata(pfunction);
struct rsi_91x_sdiodev *sdev = adapter->rsi_dev;
struct ieee80211_hw *hw = adapter->hw;
@@ -1513,9 +1512,9 @@ static struct sdio_driver rsi_driver = {
.remove = rsi_disconnect,
.id_table = rsi_dev_table,
#ifdef CONFIG_PM
+ .shutdown = rsi_shutdown,
.drv = {
.pm = &rsi_pm_ops,
- .shutdown = rsi_shutdown,
}
#endif
};
diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c
index cb8b3102fa6c..166efac812fe 100644
--- a/drivers/net/wireless/ti/wl1251/acx.c
+++ b/drivers/net/wireless/ti/wl1251/acx.c
@@ -3,6 +3,7 @@
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/string.h>
#include "wl1251.h"
#include "reg.h"
@@ -149,15 +150,7 @@ int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len)
goto out;
}
- /* be careful with the buffer sizes */
- strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version)));
-
- /*
- * if the firmware version string is exactly
- * sizeof(rev->fw_version) long or fw_len is less than
- * sizeof(rev->fw_version) it won't be null terminated
- */
- buf[min(len, sizeof(rev->fw_version)) - 1] = '\0';
+ strscpy(buf, rev->fw_version, len);
out:
kfree(rev);
diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h
index d16afb35f9ee..f8160f372bc7 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.h
+++ b/drivers/net/wireless/ti/wlcore/cmd.h
@@ -455,6 +455,7 @@ enum wl1271_cmd_key_type {
KEY_TKIP = 2,
KEY_AES = 3,
KEY_GEM = 4,
+ KEY_IGTK = 5,
};
struct wl1271_cmd_set_keys {
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 12f0167d7380..dce79bce2e3f 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -2419,6 +2419,11 @@ power_off:
strscpy(wiphy->fw_version, wl->chip.fw_ver_str,
sizeof(wiphy->fw_version));
+ /* WLAN_CIPHER_SUITE_AES_CMAC must be last in cipher_suites;
+ support only with firmware 8.9.1 and newer */
+ if (wl->chip.fw_ver[FW_VER_MAJOR] < 1)
+ wl->hw->wiphy->n_cipher_suites--;
+
/*
* Now we know if 11a is supported (info from the NVS), so disable
* 11a channels if not supported
@@ -3585,6 +3590,9 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
case WL1271_CIPHER_SUITE_GEM:
key_type = KEY_GEM;
break;
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ key_type = KEY_IGTK;
+ break;
default:
wl1271_error("Unknown key algo 0x%x", key_conf->cipher);
@@ -6196,6 +6204,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
WLAN_CIPHER_SUITE_TKIP,
WLAN_CIPHER_SUITE_CCMP,
WL1271_CIPHER_SUITE_GEM,
+ WLAN_CIPHER_SUITE_AES_CMAC,
};
/* The tx descriptor buffer */
diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c
index a73207bbe5d7..421d688ae58b 100644
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -370,7 +370,6 @@ static void wl1271_remove(struct sdio_func *func)
platform_device_unregister(glue->core);
}
-#ifdef CONFIG_PM
static int wl1271_suspend(struct device *dev)
{
/* Tell MMC/SDIO core it's OK to power down the card
@@ -422,18 +421,15 @@ static const struct dev_pm_ops wl1271_sdio_pm_ops = {
.suspend = wl1271_suspend,
.resume = wl1271_resume,
};
-#endif
static struct sdio_driver wl1271_sdio_driver = {
.name = "wl1271_sdio",
.id_table = wl1271_devices,
.probe = wl1271_probe,
.remove = wl1271_remove,
-#ifdef CONFIG_PM
.drv = {
- .pm = &wl1271_sdio_pm_ops,
+ .pm = pm_ptr(&wl1271_sdio_pm_ops),
},
-#endif
};
module_sdio_driver(wl1271_sdio_driver);
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
index 79cc63272134..4d9f5f87e814 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -7163,14 +7163,12 @@ static int __init init_mac80211_hwsim(void)
}
param.p2p_device = support_p2p_device;
- param.nan_device = true;
param.mlo = mlo;
param.multi_radio = multi_radio;
param.use_chanctx = channels > 1 || mlo || multi_radio;
param.iftypes = HWSIM_IFTYPE_SUPPORT_MASK;
if (param.p2p_device)
param.iftypes |= BIT(NL80211_IFTYPE_P2P_DEVICE);
- param.iftypes |= BIT(NL80211_IFTYPE_NAN);
err = mac80211_hwsim_new_radio(NULL, &param);
if (err < 0)