ath.git patches for v6.11
We have moved to a new group-managed repo, and this is the first pull request from that repo, and from me. Fingers crossed... We have some new features in ath12k along with some cleanups in ath11k and ath12k. Also notable are some device-tree changes to allow certain ath11k and ath12k devices to work with a new power sequencing subsystem. Major changes: ath12k * DebugFS support for datapath statistics * WCN7850: support for WoW (Wake on WLAN) * WCN7850: device-tree bindings ath11k * QCA6390: device-tree bindings -----BEGIN PGP SIGNATURE----- iIoEABYKADIWIQQ/mtSHzPUi16IfDEksFbugiYzLewUCZoQU7hQcampvaG5zb25A a2VybmVsLm9yZwAKCRAsFbugiYzLe6vCAP9mt6rfI2SWucd0ex9XbXwVkN7vV5Qn NCvRXeT5QlnfFQEAt0DBUnmU/CuShroshEw2kXKLHJpZ1y6Oz6YVN49ECAU= =ArqZ -----END PGP SIGNATURE----- Merge tag 'ath-next-20240702' of git://git.kernel.org/pub/scm/linux/kernel/git/ath/ath ath.git patches for v6.11 We have moved to a new group-managed repo, and this is the first pull request from that repo, and from me. Fingers crossed... We have some new features in ath12k along with some cleanups in ath11k and ath12k. Also notable are some device-tree changes to allow certain ath11k and ath12k devices to work with a new power sequencing subsystem. Major changes: ath12k * DebugFS support for datapath statistics * WCN7850: support for WoW (Wake on WLAN) * WCN7850: device-tree bindings ath11k * QCA6390: device-tree bindings
This commit is contained in:
commit
c1cacb01f3
@ -17,6 +17,7 @@ description: |
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- pci17cb,1101 # QCA6390
|
||||
- pci17cb,1103 # WCN6855
|
||||
|
||||
reg:
|
||||
@ -28,10 +29,55 @@ properties:
|
||||
string to uniquely identify variant of the calibration data for designs
|
||||
with colliding bus and device ids
|
||||
|
||||
vddrfacmn-supply:
|
||||
description: VDD_RFA_CMN supply regulator handle
|
||||
|
||||
vddaon-supply:
|
||||
description: VDD_AON supply regulator handle
|
||||
|
||||
vddwlcx-supply:
|
||||
description: VDD_WL_CX supply regulator handle
|
||||
|
||||
vddwlmx-supply:
|
||||
description: VDD_WL_MX supply regulator handle
|
||||
|
||||
vddrfa0p8-supply:
|
||||
description: VDD_RFA_0P8 supply regulator handle
|
||||
|
||||
vddrfa1p2-supply:
|
||||
description: VDD_RFA_1P2 supply regulator handle
|
||||
|
||||
vddrfa1p7-supply:
|
||||
description: VDD_RFA_1P7 supply regulator handle
|
||||
|
||||
vddpcie0p9-supply:
|
||||
description: VDD_PCIE_0P9 supply regulator handle
|
||||
|
||||
vddpcie1p8-supply:
|
||||
description: VDD_PCIE_1P8 supply regulator handle
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: pci17cb,1101
|
||||
then:
|
||||
required:
|
||||
- vddrfacmn-supply
|
||||
- vddaon-supply
|
||||
- vddwlcx-supply
|
||||
- vddwlmx-supply
|
||||
- vddrfa0p8-supply
|
||||
- vddrfa1p2-supply
|
||||
- vddrfa1p7-supply
|
||||
- vddpcie0p9-supply
|
||||
- vddpcie1p8-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
|
@ -0,0 +1,99 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright (c) 2024 Linaro Limited
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/wireless/qcom,ath12k.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Technologies ath12k wireless devices (PCIe)
|
||||
|
||||
maintainers:
|
||||
- Jeff Johnson <quic_jjohnson@quicinc.com>
|
||||
- Kalle Valo <kvalo@kernel.org>
|
||||
|
||||
description:
|
||||
Qualcomm Technologies IEEE 802.11be PCIe devices.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- pci17cb,1107 # WCN7850
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vddaon-supply:
|
||||
description: VDD_AON supply regulator handle
|
||||
|
||||
vddwlcx-supply:
|
||||
description: VDD_WLCX supply regulator handle
|
||||
|
||||
vddwlmx-supply:
|
||||
description: VDD_WLMX supply regulator handle
|
||||
|
||||
vddrfacmn-supply:
|
||||
description: VDD_RFA_CMN supply regulator handle
|
||||
|
||||
vddrfa0p8-supply:
|
||||
description: VDD_RFA_0P8 supply regulator handle
|
||||
|
||||
vddrfa1p2-supply:
|
||||
description: VDD_RFA_1P2 supply regulator handle
|
||||
|
||||
vddrfa1p8-supply:
|
||||
description: VDD_RFA_1P8 supply regulator handle
|
||||
|
||||
vddpcie0p9-supply:
|
||||
description: VDD_PCIE_0P9 supply regulator handle
|
||||
|
||||
vddpcie1p8-supply:
|
||||
description: VDD_PCIE_1P8 supply regulator handle
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vddaon-supply
|
||||
- vddwlcx-supply
|
||||
- vddwlmx-supply
|
||||
- vddrfacmn-supply
|
||||
- vddrfa0p8-supply
|
||||
- vddrfa1p2-supply
|
||||
- vddrfa1p8-supply
|
||||
- vddpcie0p9-supply
|
||||
- vddpcie1p8-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,rpmh.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
pcie {
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
|
||||
pcie@0 {
|
||||
device_type = "pci";
|
||||
reg = <0x0 0x0 0x0 0x0 0x0>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
bus-range = <0x01 0xff>;
|
||||
|
||||
wifi@0 {
|
||||
compatible = "pci17cb,1107";
|
||||
reg = <0x10000 0x0 0x0 0x0 0x0>;
|
||||
|
||||
vddaon-supply = <&vreg_pmu_aon_0p59>;
|
||||
vddwlcx-supply = <&vreg_pmu_wlcx_0p8>;
|
||||
vddwlmx-supply = <&vreg_pmu_wlmx_0p85>;
|
||||
vddrfacmn-supply = <&vreg_pmu_rfa_cmn>;
|
||||
vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
|
||||
vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
|
||||
vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>;
|
||||
vddpcie0p9-supply = <&vreg_pmu_pcie_0p9>;
|
||||
vddpcie1p8-supply = <&vreg_pmu_pcie_1p8>;
|
||||
};
|
||||
};
|
||||
};
|
@ -1877,8 +1877,7 @@ static void ath11k_dp_rx_h_csum_offload(struct ath11k *ar, struct sk_buff *msdu)
|
||||
CHECKSUM_NONE : CHECKSUM_UNNECESSARY;
|
||||
}
|
||||
|
||||
static int ath11k_dp_rx_crypto_mic_len(struct ath11k *ar,
|
||||
enum hal_encrypt_type enctype)
|
||||
int ath11k_dp_rx_crypto_mic_len(struct ath11k *ar, enum hal_encrypt_type enctype)
|
||||
{
|
||||
switch (enctype) {
|
||||
case HAL_ENCRYPT_TYPE_OPEN:
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef ATH11K_DP_RX_H
|
||||
#define ATH11K_DP_RX_H
|
||||
@ -95,4 +96,6 @@ int ath11k_peer_rx_frag_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id
|
||||
int ath11k_dp_rx_pktlog_start(struct ath11k_base *ab);
|
||||
int ath11k_dp_rx_pktlog_stop(struct ath11k_base *ab, bool stop_timer);
|
||||
|
||||
int ath11k_dp_rx_crypto_mic_len(struct ath11k *ar, enum hal_encrypt_type enctype);
|
||||
|
||||
#endif /* ATH11K_DP_RX_H */
|
||||
|
@ -353,8 +353,12 @@ ath11k_dp_tx_htt_tx_complete_buf(struct ath11k_base *ab,
|
||||
if (ts->acked) {
|
||||
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
info->status.ack_signal = ATH11K_DEFAULT_NOISE_FLOOR +
|
||||
ts->ack_rssi;
|
||||
info->status.ack_signal = ts->ack_rssi;
|
||||
|
||||
if (!test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,
|
||||
ab->wmi_ab.svc_map))
|
||||
info->status.ack_signal += ATH11K_DEFAULT_NOISE_FLOOR;
|
||||
|
||||
info->status.flags |=
|
||||
IEEE80211_TX_STATUS_ACK_SIGNAL_VALID;
|
||||
} else {
|
||||
@ -584,8 +588,12 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar,
|
||||
if (ts->status == HAL_WBM_TQM_REL_REASON_FRAME_ACKED &&
|
||||
!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
info->status.ack_signal = ATH11K_DEFAULT_NOISE_FLOOR +
|
||||
ts->ack_rssi;
|
||||
info->status.ack_signal = ts->ack_rssi;
|
||||
|
||||
if (!test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,
|
||||
ab->wmi_ab.svc_map))
|
||||
info->status.ack_signal += ATH11K_DEFAULT_NOISE_FLOOR;
|
||||
|
||||
info->status.flags |= IEEE80211_TX_STATUS_ACK_SIGNAL_VALID;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* 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) 2021, 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH11K_DP_TX_H
|
||||
@ -13,7 +13,7 @@
|
||||
struct ath11k_dp_htt_wbm_tx_status {
|
||||
u32 msdu_id;
|
||||
bool acked;
|
||||
int ack_rssi;
|
||||
s8 ack_rssi;
|
||||
u16 peer_id;
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH11K_HAL_TX_H
|
||||
@ -54,7 +54,7 @@ struct hal_tx_info {
|
||||
struct hal_tx_status {
|
||||
enum hal_wbm_rel_src_module buf_rel_source;
|
||||
enum hal_wbm_tqm_rel_reason status;
|
||||
u8 ack_rssi;
|
||||
s8 ack_rssi;
|
||||
u32 flags; /* %HAL_TX_STATUS_FLAGS_ */
|
||||
u32 ppdu_id;
|
||||
u8 try_cnt;
|
||||
|
@ -4229,6 +4229,7 @@ static int ath11k_install_key(struct ath11k_vif *arvif,
|
||||
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
case WLAN_CIPHER_SUITE_CCMP_256:
|
||||
arg.key_cipher = WMI_CIPHER_AES_CCM;
|
||||
/* TODO: Re-check if flag is valid */
|
||||
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
|
||||
@ -4238,12 +4239,10 @@ static int ath11k_install_key(struct ath11k_vif *arvif,
|
||||
arg.key_txmic_len = 8;
|
||||
arg.key_rxmic_len = 8;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_CCMP_256:
|
||||
arg.key_cipher = WMI_CIPHER_AES_CCM;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_GCMP:
|
||||
case WLAN_CIPHER_SUITE_GCMP_256:
|
||||
arg.key_cipher = WMI_CIPHER_AES_GCM;
|
||||
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
|
||||
break;
|
||||
default:
|
||||
ath11k_warn(ar->ab, "cipher %d is not supported\n", key->cipher);
|
||||
@ -5903,7 +5902,10 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB(skb);
|
||||
struct ieee80211_tx_info *info;
|
||||
enum hal_encrypt_type enctype;
|
||||
unsigned int mic_len;
|
||||
dma_addr_t paddr;
|
||||
int buf_id;
|
||||
int ret;
|
||||
@ -5927,7 +5929,12 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
|
||||
ieee80211_is_deauth(hdr->frame_control) ||
|
||||
ieee80211_is_disassoc(hdr->frame_control)) &&
|
||||
ieee80211_has_protected(hdr->frame_control)) {
|
||||
skb_put(skb, IEEE80211_CCMP_MIC_LEN);
|
||||
if (!(skb_cb->flags & ATH11K_SKB_CIPHER_SET))
|
||||
ath11k_warn(ab, "WMI management tx frame without ATH11K_SKB_CIPHER_SET");
|
||||
|
||||
enctype = ath11k_dp_tx_get_encrypt_type(skb_cb->cipher);
|
||||
mic_len = ath11k_dp_rx_crypto_mic_len(ar, enctype);
|
||||
skb_put(skb, mic_len);
|
||||
}
|
||||
}
|
||||
|
||||
@ -8977,8 +8984,11 @@ static void ath11k_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) +
|
||||
ATH11K_DEFAULT_NOISE_FLOOR;
|
||||
sinfo->signal_avg = ewma_avg_rssi_read(&arsta->avg_rssi);
|
||||
|
||||
if (!db2dbm)
|
||||
sinfo->signal_avg += ATH11K_DEFAULT_NOISE_FLOOR;
|
||||
|
||||
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
|
||||
}
|
||||
|
||||
@ -9020,7 +9030,12 @@ static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw,
|
||||
offload = &arvif->arp_ns_offload;
|
||||
count = 0;
|
||||
|
||||
/* Note: read_lock_bh() calls rcu_read_lock() */
|
||||
/* The _ipv6_changed() is called with RCU lock already held in
|
||||
* atomic_notifier_call_chain(), so we don't need to call
|
||||
* rcu_read_lock() again here. But note that with CONFIG_PREEMPT_RT
|
||||
* enabled, read_lock_bh() also calls rcu_read_lock(). This is OK
|
||||
* because RCU read critical section is allowed to get nested.
|
||||
*/
|
||||
read_lock_bh(&idev->lock);
|
||||
|
||||
memset(offload->ipv6_addr, 0, sizeof(offload->ipv6_addr));
|
||||
|
@ -2859,7 +2859,7 @@ int ath11k_qmi_firmware_start(struct ath11k_base *ab,
|
||||
|
||||
int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab)
|
||||
{
|
||||
int timeout;
|
||||
long time_left;
|
||||
|
||||
if (!ath11k_core_coldboot_cal_support(ab) ||
|
||||
ab->hw_params.cbcal_restart_fw == 0)
|
||||
@ -2867,11 +2867,11 @@ int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab)
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_QMI, "wait for cold boot done\n");
|
||||
|
||||
timeout = wait_event_timeout(ab->qmi.cold_boot_waitq,
|
||||
(ab->qmi.cal_done == 1),
|
||||
ATH11K_COLD_BOOT_FW_RESET_DELAY);
|
||||
time_left = wait_event_timeout(ab->qmi.cold_boot_waitq,
|
||||
(ab->qmi.cal_done == 1),
|
||||
ATH11K_COLD_BOOT_FW_RESET_DELAY);
|
||||
|
||||
if (timeout <= 0) {
|
||||
if (time_left <= 0) {
|
||||
ath11k_warn(ab, "Coldboot Calibration timed out\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
@ -2886,7 +2886,7 @@ EXPORT_SYMBOL(ath11k_qmi_fwreset_from_cold_boot);
|
||||
|
||||
static int ath11k_qmi_process_coldboot_calibration(struct ath11k_base *ab)
|
||||
{
|
||||
int timeout;
|
||||
long time_left;
|
||||
int ret;
|
||||
|
||||
ret = ath11k_qmi_wlanfw_mode_send(ab, ATH11K_FIRMWARE_MODE_COLD_BOOT);
|
||||
@ -2897,10 +2897,10 @@ static int ath11k_qmi_process_coldboot_calibration(struct ath11k_base *ab)
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_QMI, "Coldboot calibration wait started\n");
|
||||
|
||||
timeout = wait_event_timeout(ab->qmi.cold_boot_waitq,
|
||||
(ab->qmi.cal_done == 1),
|
||||
ATH11K_COLD_BOOT_FW_RESET_DELAY);
|
||||
if (timeout <= 0) {
|
||||
time_left = wait_event_timeout(ab->qmi.cold_boot_waitq,
|
||||
(ab->qmi.cal_done == 1),
|
||||
ATH11K_COLD_BOOT_FW_RESET_DELAY);
|
||||
if (time_left <= 0) {
|
||||
ath11k_warn(ab, "coldboot calibration timed out\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -23,9 +23,10 @@ ath12k-y += core.o \
|
||||
fw.o \
|
||||
p2p.o
|
||||
|
||||
ath12k-$(CONFIG_ATH12K_DEBUGFS) += debugfs.o
|
||||
ath12k-$(CONFIG_ATH12K_DEBUGFS) += debugfs.o debugfs_htt_stats.o
|
||||
ath12k-$(CONFIG_ACPI) += acpi.o
|
||||
ath12k-$(CONFIG_ATH12K_TRACING) += trace.o
|
||||
ath12k-$(CONFIG_PM) += wow.o
|
||||
|
||||
# for tracing framework to find trace.h
|
||||
CFLAGS_trace.o := -I$(src)
|
||||
|
@ -391,4 +391,6 @@ void ath12k_acpi_stop(struct ath12k_base *ab)
|
||||
acpi_remove_notify_handler(ACPI_HANDLE(ab->dev),
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
ath12k_acpi_dsm_notify);
|
||||
|
||||
memset(&ab->acpi, 0, sizeof(ab->acpi));
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "hif.h"
|
||||
#include "fw.h"
|
||||
#include "debugfs.h"
|
||||
#include "wow.h"
|
||||
|
||||
unsigned int ath12k_debug_mask;
|
||||
module_param_named(debug_mask, ath12k_debug_mask, uint, 0644);
|
||||
@ -42,13 +43,37 @@ static int ath12k_core_rfkill_config(struct ath12k_base *ab)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check if we need to continue with suspend/resume operation.
|
||||
* Return:
|
||||
* a negative value: error happens and don't continue.
|
||||
* 0: no error but don't continue.
|
||||
* positive value: no error and do continue.
|
||||
*/
|
||||
static int ath12k_core_continue_suspend_resume(struct ath12k_base *ab)
|
||||
{
|
||||
struct ath12k *ar;
|
||||
|
||||
if (!ab->hw_params->supports_suspend)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* so far single_pdev_only chips have supports_suspend as true
|
||||
* so pass 0 as a dummy pdev_id here.
|
||||
*/
|
||||
ar = ab->pdevs[0].ar;
|
||||
if (!ar || !ar->ah || ar->ah->state != ATH12K_HW_STATE_OFF)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ath12k_core_suspend(struct ath12k_base *ab)
|
||||
{
|
||||
struct ath12k *ar;
|
||||
int ret, i;
|
||||
|
||||
if (!ab->hw_params->supports_suspend)
|
||||
return -EOPNOTSUPP;
|
||||
ret = ath12k_core_continue_suspend_resume(ab);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
ar = ab->pdevs[i].ar;
|
||||
@ -80,8 +105,13 @@ EXPORT_SYMBOL(ath12k_core_suspend);
|
||||
|
||||
int ath12k_core_suspend_late(struct ath12k_base *ab)
|
||||
{
|
||||
if (!ab->hw_params->supports_suspend)
|
||||
return -EOPNOTSUPP;
|
||||
int ret;
|
||||
|
||||
ret = ath12k_core_continue_suspend_resume(ab);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
ath12k_acpi_stop(ab);
|
||||
|
||||
ath12k_hif_irq_disable(ab);
|
||||
ath12k_hif_ce_irq_disable(ab);
|
||||
@ -96,8 +126,9 @@ int ath12k_core_resume_early(struct ath12k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!ab->hw_params->supports_suspend)
|
||||
return -EOPNOTSUPP;
|
||||
ret = ath12k_core_continue_suspend_resume(ab);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
reinit_completion(&ab->restart_completed);
|
||||
ret = ath12k_hif_power_up(ab);
|
||||
@ -111,9 +142,11 @@ EXPORT_SYMBOL(ath12k_core_resume_early);
|
||||
int ath12k_core_resume(struct ath12k_base *ab)
|
||||
{
|
||||
long time_left;
|
||||
int ret;
|
||||
|
||||
if (!ab->hw_params->supports_suspend)
|
||||
return -EOPNOTSUPP;
|
||||
ret = ath12k_core_continue_suspend_resume(ab);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
time_left = wait_for_completion_timeout(&ab->restart_completed,
|
||||
ATH12K_RESET_TIMEOUT_HZ);
|
||||
@ -1059,8 +1092,6 @@ static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
|
||||
/* Restart after all the link/radio halt */
|
||||
ieee80211_restart_hw(ah->hw);
|
||||
break;
|
||||
case ATH12K_HW_STATE_OFF:
|
||||
ath12k_warn(ab,
|
||||
@ -1087,7 +1118,8 @@ static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
|
||||
static void ath12k_core_restart(struct work_struct *work)
|
||||
{
|
||||
struct ath12k_base *ab = container_of(work, struct ath12k_base, restart_work);
|
||||
int ret;
|
||||
struct ath12k_hw *ah;
|
||||
int ret, i;
|
||||
|
||||
ret = ath12k_core_reconfigure_on_crash(ab);
|
||||
if (ret) {
|
||||
@ -1095,8 +1127,12 @@ static void ath12k_core_restart(struct work_struct *work)
|
||||
return;
|
||||
}
|
||||
|
||||
if (ab->is_reset)
|
||||
complete_all(&ab->reconfigure_complete);
|
||||
if (ab->is_reset) {
|
||||
for (i = 0; i < ab->num_hw; i++) {
|
||||
ah = ab->ah[i];
|
||||
ieee80211_restart_hw(ah->hw);
|
||||
}
|
||||
}
|
||||
|
||||
complete(&ab->restart_completed);
|
||||
}
|
||||
@ -1150,20 +1186,14 @@ static void ath12k_core_reset(struct work_struct *work)
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset starting\n");
|
||||
|
||||
ab->is_reset = true;
|
||||
atomic_set(&ab->recovery_start_count, 0);
|
||||
reinit_completion(&ab->recovery_start);
|
||||
atomic_set(&ab->recovery_count, 0);
|
||||
|
||||
ath12k_core_pre_reconfigure_recovery(ab);
|
||||
|
||||
reinit_completion(&ab->reconfigure_complete);
|
||||
ath12k_core_post_reconfigure_recovery(ab);
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "waiting recovery start...\n");
|
||||
|
||||
time_left = wait_for_completion_timeout(&ab->recovery_start,
|
||||
ATH12K_RECOVER_START_TIMEOUT_HZ);
|
||||
|
||||
ath12k_hif_irq_disable(ab);
|
||||
ath12k_hif_ce_irq_disable(ab);
|
||||
|
||||
@ -1275,8 +1305,6 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
|
||||
mutex_init(&ab->core_lock);
|
||||
spin_lock_init(&ab->base_lock);
|
||||
init_completion(&ab->reset_complete);
|
||||
init_completion(&ab->reconfigure_complete);
|
||||
init_completion(&ab->recovery_start);
|
||||
|
||||
INIT_LIST_HEAD(&ab->peers);
|
||||
init_waitqueue_head(&ab->peer_mapping_wq);
|
||||
@ -1288,6 +1316,7 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
|
||||
timer_setup(&ab->rx_replenish_retry, ath12k_ce_rx_replenish_retry, 0);
|
||||
init_completion(&ab->htc_suspend);
|
||||
init_completion(&ab->restart_completed);
|
||||
init_completion(&ab->wow.wakeup_completed);
|
||||
|
||||
ab->dev = dev;
|
||||
ab->hif.bus = bus;
|
||||
|
@ -28,6 +28,8 @@
|
||||
#include "dbring.h"
|
||||
#include "fw.h"
|
||||
#include "acpi.h"
|
||||
#include "wow.h"
|
||||
#include "debugfs_htt_stats.h"
|
||||
|
||||
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
|
||||
|
||||
@ -229,6 +231,13 @@ struct ath12k_vif_cache {
|
||||
u32 bss_conf_changed;
|
||||
};
|
||||
|
||||
struct ath12k_rekey_data {
|
||||
u8 kck[NL80211_KCK_LEN];
|
||||
u8 kek[NL80211_KCK_LEN];
|
||||
u64 replay_ctr;
|
||||
bool enable_offload;
|
||||
};
|
||||
|
||||
struct ath12k_vif {
|
||||
u32 vdev_id;
|
||||
enum wmi_vdev_type vdev_type;
|
||||
@ -285,6 +294,7 @@ struct ath12k_vif {
|
||||
u32 punct_bitmap;
|
||||
bool ps;
|
||||
struct ath12k_vif_cache *cache;
|
||||
struct ath12k_rekey_data rekey_data;
|
||||
};
|
||||
|
||||
struct ath12k_vif_iter {
|
||||
@ -472,8 +482,17 @@ struct ath12k_fw_stats {
|
||||
struct list_head bcn;
|
||||
};
|
||||
|
||||
struct ath12k_dbg_htt_stats {
|
||||
enum ath12k_dbg_htt_ext_stats_type type;
|
||||
u32 cfg_param[4];
|
||||
u8 reset;
|
||||
struct debug_htt_stats_req *stats_req;
|
||||
};
|
||||
|
||||
struct ath12k_debug {
|
||||
struct dentry *debugfs_pdev;
|
||||
struct dentry *debugfs_pdev_symlink;
|
||||
struct ath12k_dbg_htt_stats htt_stats;
|
||||
};
|
||||
|
||||
struct ath12k_per_peer_tx_stats {
|
||||
@ -606,6 +625,9 @@ struct ath12k {
|
||||
struct work_struct wmi_mgmt_tx_work;
|
||||
struct sk_buff_head wmi_mgmt_tx_queue;
|
||||
|
||||
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;
|
||||
@ -625,12 +647,12 @@ struct ath12k {
|
||||
|
||||
u32 freq_low;
|
||||
u32 freq_high;
|
||||
|
||||
bool nlo_enabled;
|
||||
};
|
||||
|
||||
struct ath12k_hw {
|
||||
struct ieee80211_hw *hw;
|
||||
struct ath12k_base *ab;
|
||||
|
||||
/* Protect the write operation of the hardware state ath12k_hw::state
|
||||
* between hardware start<=>reconfigure<=>stop transitions.
|
||||
*/
|
||||
@ -766,6 +788,11 @@ struct ath12k_base {
|
||||
const struct ath12k_hif_ops *ops;
|
||||
} hif;
|
||||
|
||||
struct {
|
||||
struct completion wakeup_completed;
|
||||
u32 wmi_conf_rx_decap_mode;
|
||||
} wow;
|
||||
|
||||
struct ath12k_ce ce;
|
||||
struct timer_list rx_replenish_retry;
|
||||
struct ath12k_hal hal;
|
||||
@ -848,11 +875,8 @@ struct ath12k_base {
|
||||
struct work_struct reset_work;
|
||||
atomic_t reset_count;
|
||||
atomic_t recovery_count;
|
||||
atomic_t recovery_start_count;
|
||||
bool is_reset;
|
||||
struct completion reset_complete;
|
||||
struct completion reconfigure_complete;
|
||||
struct completion recovery_start;
|
||||
/* continuous recovery fail count */
|
||||
atomic_t fail_cont_count;
|
||||
unsigned long reset_fail_timeout;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _ATH12K_DEBUG_H_
|
||||
@ -25,6 +25,7 @@ enum ath12k_debug_mask {
|
||||
ATH12K_DBG_PCI = 0x00001000,
|
||||
ATH12K_DBG_DP_TX = 0x00002000,
|
||||
ATH12K_DBG_DP_RX = 0x00004000,
|
||||
ATH12K_DBG_WOW = 0x00008000,
|
||||
ATH12K_DBG_ANY = 0xffffffff,
|
||||
};
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "core.h"
|
||||
#include "debugfs.h"
|
||||
#include "debugfs_htt_stats.h"
|
||||
|
||||
static ssize_t ath12k_write_simulate_radar(struct file *file,
|
||||
const char __user *user_buf,
|
||||
@ -80,11 +81,27 @@ void ath12k_debugfs_register(struct ath12k *ar)
|
||||
|
||||
/* Create a symlink under ieee80211/phy* */
|
||||
scnprintf(buf, sizeof(buf), "../../ath12k/%pd2", ar->debug.debugfs_pdev);
|
||||
debugfs_create_symlink("ath12k", hw->wiphy->debugfsdir, buf);
|
||||
ar->debug.debugfs_pdev_symlink = debugfs_create_symlink("ath12k",
|
||||
hw->wiphy->debugfsdir,
|
||||
buf);
|
||||
|
||||
if (ar->mac.sbands[NL80211_BAND_5GHZ].channels) {
|
||||
debugfs_create_file("dfs_simulate_radar", 0200,
|
||||
ar->debug.debugfs_pdev, ar,
|
||||
&fops_simulate_radar);
|
||||
}
|
||||
|
||||
ath12k_debugfs_htt_stats_register(ar);
|
||||
}
|
||||
|
||||
void ath12k_debugfs_unregister(struct ath12k *ar)
|
||||
{
|
||||
if (!ar->debug.debugfs_pdev)
|
||||
return;
|
||||
|
||||
/* Remove symlink under ieee80211/phy* */
|
||||
debugfs_remove(ar->debug.debugfs_pdev_symlink);
|
||||
debugfs_remove_recursive(ar->debug.debugfs_pdev);
|
||||
ar->debug.debugfs_pdev_symlink = NULL;
|
||||
ar->debug.debugfs_pdev = NULL;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
void ath12k_debugfs_soc_create(struct ath12k_base *ab);
|
||||
void ath12k_debugfs_soc_destroy(struct ath12k_base *ab);
|
||||
void ath12k_debugfs_register(struct ath12k *ar);
|
||||
|
||||
void ath12k_debugfs_unregister(struct ath12k *ar);
|
||||
#else
|
||||
static inline void ath12k_debugfs_soc_create(struct ath12k_base *ab)
|
||||
{
|
||||
@ -25,6 +25,10 @@ static inline void ath12k_debugfs_register(struct ath12k *ar)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void ath12k_debugfs_unregister(struct ath12k *ar)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ATH12K_DEBUGFS */
|
||||
|
||||
#endif /* _ATH12K_DEBUGFS_H_ */
|
||||
|
1540
drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c
Normal file
1540
drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c
Normal file
File diff suppressed because it is too large
Load Diff
567
drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h
Normal file
567
drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h
Normal file
@ -0,0 +1,567 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef DEBUG_HTT_STATS_H
|
||||
#define DEBUG_HTT_STATS_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)
|
||||
#define ATH12K_HTT_STATS_MAGIC_VALUE 0xF0F0F0F0
|
||||
#define ATH12K_HTT_STATS_SUBTYPE_MAX 16
|
||||
#define ATH12K_HTT_MAX_STRING_LEN 256
|
||||
|
||||
#define ATH12K_HTT_STATS_RESET_BITMAP32_OFFSET(_idx) ((_idx) & 0x1f)
|
||||
#define ATH12K_HTT_STATS_RESET_BITMAP64_OFFSET(_idx) ((_idx) & 0x3f)
|
||||
#define ATH12K_HTT_STATS_RESET_BITMAP32_BIT(_idx) (1 << \
|
||||
ATH12K_HTT_STATS_RESET_BITMAP32_OFFSET(_idx))
|
||||
#define ATH12K_HTT_STATS_RESET_BITMAP64_BIT(_idx) (1 << \
|
||||
ATH12K_HTT_STATS_RESET_BITMAP64_OFFSET(_idx))
|
||||
|
||||
void ath12k_debugfs_htt_stats_register(struct ath12k *ar);
|
||||
|
||||
#ifdef CONFIG_ATH12K_DEBUGFS
|
||||
void ath12k_debugfs_htt_ext_stats_handler(struct ath12k_base *ab,
|
||||
struct sk_buff *skb);
|
||||
#else /* CONFIG_ATH12K_DEBUGFS */
|
||||
static inline void ath12k_debugfs_htt_ext_stats_handler(struct ath12k_base *ab,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* DOC: target -> host extended statistics upload
|
||||
*
|
||||
* The following field definitions describe the format of the HTT
|
||||
* target to host stats upload confirmation message.
|
||||
* The message contains a cookie echoed from the HTT host->target stats
|
||||
* upload request, which identifies which request the confirmation is
|
||||
* for, and a single stats can span over multiple HTT stats indication
|
||||
* due to the HTT message size limitation so every HTT ext stats
|
||||
* indication will have tag-length-value stats information elements.
|
||||
* The tag-length header for each HTT stats IND message also includes a
|
||||
* status field, to indicate whether the request for the stat type in
|
||||
* question was fully met, partially met, unable to be met, or invalid
|
||||
* (if the stat type in question is disabled in the target).
|
||||
* A Done bit 1's indicate the end of the of stats info elements.
|
||||
*
|
||||
*
|
||||
* |31 16|15 12|11|10 8|7 5|4 0|
|
||||
* |--------------------------------------------------------------|
|
||||
* | reserved | msg type |
|
||||
* |--------------------------------------------------------------|
|
||||
* | cookie LSBs |
|
||||
* |--------------------------------------------------------------|
|
||||
* | cookie MSBs |
|
||||
* |--------------------------------------------------------------|
|
||||
* | stats entry length | rsvd | D| S | stat type |
|
||||
* |--------------------------------------------------------------|
|
||||
* | type-specific stats info |
|
||||
* | (see debugfs_htt_stats.h) |
|
||||
* |--------------------------------------------------------------|
|
||||
* Header fields:
|
||||
* - MSG_TYPE
|
||||
* Bits 7:0
|
||||
* Purpose: Identifies this is a extended statistics upload confirmation
|
||||
* message.
|
||||
* Value: 0x1c
|
||||
* - 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: MSBs 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
|
||||
*
|
||||
* Stats Information Element tag-length header fields:
|
||||
* - STAT_TYPE
|
||||
* Bits 7:0
|
||||
* Purpose: identifies the type of statistics info held in the
|
||||
* following information element
|
||||
* Value: ath12k_dbg_htt_ext_stats_type
|
||||
* - STATUS
|
||||
* Bits 10:8
|
||||
* Purpose: indicate whether the requested stats are present
|
||||
* Value:
|
||||
* 0 -> The requested stats have been delivered in full
|
||||
* 1 -> The requested stats have been delivered in part
|
||||
* 2 -> The requested stats could not be delivered (error case)
|
||||
* 3 -> The requested stat type is either not recognized (invalid)
|
||||
* - DONE
|
||||
* Bits 11
|
||||
* Purpose:
|
||||
* Indicates the completion of the stats entry, this will be the last
|
||||
* stats conf HTT segment for the requested stats type.
|
||||
* Value:
|
||||
* 0 -> the stats retrieval is ongoing
|
||||
* 1 -> the stats retrieval is complete
|
||||
* - LENGTH
|
||||
* Bits 31:16
|
||||
* Purpose: indicate the stats information size
|
||||
* Value: This field specifies the number of bytes of stats information
|
||||
* that follows the element tag-length header.
|
||||
* It is expected but not required that this length is a multiple of
|
||||
* 4 bytes.
|
||||
*/
|
||||
|
||||
#define ATH12K_HTT_T2H_EXT_STATS_INFO1_DONE BIT(11)
|
||||
#define ATH12K_HTT_T2H_EXT_STATS_INFO1_LENGTH GENMASK(31, 16)
|
||||
|
||||
struct ath12k_htt_extd_stats_msg {
|
||||
__le32 info0;
|
||||
__le64 cookie;
|
||||
__le32 info1;
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
/* htt_dbg_ext_stats_type */
|
||||
enum ath12k_dbg_htt_ext_stats_type {
|
||||
ATH12K_DBG_HTT_EXT_STATS_RESET = 0,
|
||||
ATH12K_DBG_HTT_EXT_STATS_PDEV_TX = 1,
|
||||
ATH12K_DBG_HTT_EXT_STATS_PDEV_TX_SCHED = 4,
|
||||
ATH12K_DBG_HTT_EXT_STATS_PDEV_ERROR = 5,
|
||||
ATH12K_DBG_HTT_EXT_STATS_PDEV_TQM = 6,
|
||||
|
||||
/* keep this last */
|
||||
ATH12K_DBG_HTT_NUM_EXT_STATS,
|
||||
};
|
||||
|
||||
enum ath12k_dbg_htt_tlv_tag {
|
||||
HTT_STATS_TX_PDEV_CMN_TAG = 0,
|
||||
HTT_STATS_TX_PDEV_UNDERRUN_TAG = 1,
|
||||
HTT_STATS_TX_PDEV_SIFS_TAG = 2,
|
||||
HTT_STATS_TX_PDEV_FLUSH_TAG = 3,
|
||||
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,
|
||||
HTT_STATS_TX_TQM_CMN_TAG = 14,
|
||||
HTT_STATS_TX_TQM_PDEV_TAG = 15,
|
||||
HTT_STATS_TX_PDEV_SCHEDULER_TXQ_STATS_TAG = 36,
|
||||
HTT_STATS_TX_SCHED_CMN_TAG = 37,
|
||||
HTT_STATS_SCHED_TXQ_CMD_POSTED_TAG = 39,
|
||||
HTT_STATS_TX_TQM_ERROR_STATS_TAG = 43,
|
||||
HTT_STATS_SCHED_TXQ_CMD_REAPED_TAG = 44,
|
||||
HTT_STATS_HW_INTR_MISC_TAG = 54,
|
||||
HTT_STATS_HW_PDEV_ERRS_TAG = 56,
|
||||
HTT_STATS_WHAL_TX_TAG = 66,
|
||||
HTT_STATS_TX_PDEV_SIFS_HIST_TAG = 67,
|
||||
HTT_STATS_SCHED_TXQ_SCHED_ORDER_SU_TAG = 86,
|
||||
HTT_STATS_SCHED_TXQ_SCHED_INELIGIBILITY_TAG = 87,
|
||||
HTT_STATS_HW_WAR_TAG = 89,
|
||||
HTT_STATS_SCHED_TXQ_SUPERCYCLE_TRIGGER_TAG = 100,
|
||||
HTT_STATS_PDEV_CTRL_PATH_TX_STATS_TAG = 102,
|
||||
HTT_STATS_MU_PPDU_DIST_TAG = 129,
|
||||
|
||||
HTT_STATS_MAX_TAG,
|
||||
};
|
||||
|
||||
#define ATH12K_HTT_STATS_MAC_ID GENMASK(7, 0)
|
||||
|
||||
#define ATH12K_HTT_TX_PDEV_MAX_SIFS_BURST_STATS 9
|
||||
#define ATH12K_HTT_TX_PDEV_MAX_FLUSH_REASON_STATS 150
|
||||
|
||||
/* MU MIMO distribution stats is a 2-dimensional array
|
||||
* with dimension one denoting stats for nr4[0] or nr8[1]
|
||||
*/
|
||||
#define ATH12K_HTT_STATS_NUM_NR_BINS 2
|
||||
#define ATH12K_HTT_STATS_MAX_NUM_MU_PPDU_PER_BURST 10
|
||||
#define ATH12K_HTT_TX_PDEV_MAX_SIFS_BURST_HIST_STATS 10
|
||||
#define ATH12K_HTT_STATS_MAX_NUM_SCHED_STATUS 9
|
||||
#define ATH12K_HTT_STATS_NUM_SCHED_STATUS_WORDS \
|
||||
(ATH12K_HTT_STATS_NUM_NR_BINS * ATH12K_HTT_STATS_MAX_NUM_SCHED_STATUS)
|
||||
#define ATH12K_HTT_STATS_MU_PPDU_PER_BURST_WORDS \
|
||||
(ATH12K_HTT_STATS_NUM_NR_BINS * ATH12K_HTT_STATS_MAX_NUM_MU_PPDU_PER_BURST)
|
||||
|
||||
enum ath12k_htt_tx_pdev_underrun_enum {
|
||||
HTT_STATS_TX_PDEV_NO_DATA_UNDERRUN = 0,
|
||||
HTT_STATS_TX_PDEV_DATA_UNDERRUN_BETWEEN_MPDU = 1,
|
||||
HTT_STATS_TX_PDEV_DATA_UNDERRUN_WITHIN_MPDU = 2,
|
||||
HTT_TX_PDEV_MAX_URRN_STATS = 3,
|
||||
};
|
||||
|
||||
enum ath12k_htt_stats_reset_cfg_param_alloc_pos {
|
||||
ATH12K_HTT_STATS_RESET_PARAM_CFG_32_BYTES = 1,
|
||||
ATH12K_HTT_STATS_RESET_PARAM_CFG_64_BYTES,
|
||||
ATH12K_HTT_STATS_RESET_PARAM_CFG_128_BYTES,
|
||||
};
|
||||
|
||||
struct debug_htt_stats_req {
|
||||
bool done;
|
||||
bool override_cfg_param;
|
||||
u8 pdev_id;
|
||||
enum ath12k_dbg_htt_ext_stats_type type;
|
||||
u32 cfg_param[4];
|
||||
u8 peer_addr[ETH_ALEN];
|
||||
struct completion htt_stats_rcvd;
|
||||
u32 buf_len;
|
||||
u8 buf[];
|
||||
};
|
||||
|
||||
struct ath12k_htt_tx_pdev_stats_cmn_tlv {
|
||||
__le32 mac_id__word;
|
||||
__le32 hw_queued;
|
||||
__le32 hw_reaped;
|
||||
__le32 underrun;
|
||||
__le32 hw_paused;
|
||||
__le32 hw_flush;
|
||||
__le32 hw_filt;
|
||||
__le32 tx_abort;
|
||||
__le32 mpdu_requed;
|
||||
__le32 tx_xretry;
|
||||
__le32 data_rc;
|
||||
__le32 mpdu_dropped_xretry;
|
||||
__le32 illgl_rate_phy_err;
|
||||
__le32 cont_xretry;
|
||||
__le32 tx_timeout;
|
||||
__le32 pdev_resets;
|
||||
__le32 phy_underrun;
|
||||
__le32 txop_ovf;
|
||||
__le32 seq_posted;
|
||||
__le32 seq_failed_queueing;
|
||||
__le32 seq_completed;
|
||||
__le32 seq_restarted;
|
||||
__le32 mu_seq_posted;
|
||||
__le32 seq_switch_hw_paused;
|
||||
__le32 next_seq_posted_dsr;
|
||||
__le32 seq_posted_isr;
|
||||
__le32 seq_ctrl_cached;
|
||||
__le32 mpdu_count_tqm;
|
||||
__le32 msdu_count_tqm;
|
||||
__le32 mpdu_removed_tqm;
|
||||
__le32 msdu_removed_tqm;
|
||||
__le32 mpdus_sw_flush;
|
||||
__le32 mpdus_hw_filter;
|
||||
__le32 mpdus_truncated;
|
||||
__le32 mpdus_ack_failed;
|
||||
__le32 mpdus_expired;
|
||||
__le32 mpdus_seq_hw_retry;
|
||||
__le32 ack_tlv_proc;
|
||||
__le32 coex_abort_mpdu_cnt_valid;
|
||||
__le32 coex_abort_mpdu_cnt;
|
||||
__le32 num_total_ppdus_tried_ota;
|
||||
__le32 num_data_ppdus_tried_ota;
|
||||
__le32 local_ctrl_mgmt_enqued;
|
||||
__le32 local_ctrl_mgmt_freed;
|
||||
__le32 local_data_enqued;
|
||||
__le32 local_data_freed;
|
||||
__le32 mpdu_tried;
|
||||
__le32 isr_wait_seq_posted;
|
||||
|
||||
__le32 tx_active_dur_us_low;
|
||||
__le32 tx_active_dur_us_high;
|
||||
__le32 remove_mpdus_max_retries;
|
||||
__le32 comp_delivered;
|
||||
__le32 ppdu_ok;
|
||||
__le32 self_triggers;
|
||||
__le32 tx_time_dur_data;
|
||||
__le32 seq_qdepth_repost_stop;
|
||||
__le32 mu_seq_min_msdu_repost_stop;
|
||||
__le32 seq_min_msdu_repost_stop;
|
||||
__le32 seq_txop_repost_stop;
|
||||
__le32 next_seq_cancel;
|
||||
__le32 fes_offsets_err_cnt;
|
||||
__le32 num_mu_peer_blacklisted;
|
||||
__le32 mu_ofdma_seq_posted;
|
||||
__le32 ul_mumimo_seq_posted;
|
||||
__le32 ul_ofdma_seq_posted;
|
||||
|
||||
__le32 thermal_suspend_cnt;
|
||||
__le32 dfs_suspend_cnt;
|
||||
__le32 tx_abort_suspend_cnt;
|
||||
__le32 tgt_specific_opaque_txq_suspend_info;
|
||||
__le32 last_suspend_reason;
|
||||
} __packed;
|
||||
|
||||
struct ath12k_htt_tx_pdev_stats_urrn_tlv {
|
||||
DECLARE_FLEX_ARRAY(__le32, urrn_stats);
|
||||
} __packed;
|
||||
|
||||
struct ath12k_htt_tx_pdev_stats_flush_tlv {
|
||||
DECLARE_FLEX_ARRAY(__le32, flush_errs);
|
||||
} __packed;
|
||||
|
||||
struct ath12k_htt_tx_pdev_stats_phy_err_tlv {
|
||||
DECLARE_FLEX_ARRAY(__le32, phy_errs);
|
||||
} __packed;
|
||||
|
||||
struct ath12k_htt_tx_pdev_stats_sifs_tlv {
|
||||
DECLARE_FLEX_ARRAY(__le32, sifs_status);
|
||||
} __packed;
|
||||
|
||||
struct ath12k_htt_pdev_ctrl_path_tx_stats_tlv {
|
||||
__le32 fw_tx_mgmt_subtype[ATH12K_HTT_STATS_SUBTYPE_MAX];
|
||||
} __packed;
|
||||
|
||||
struct ath12k_htt_tx_pdev_stats_sifs_hist_tlv {
|
||||
DECLARE_FLEX_ARRAY(__le32, sifs_hist_status);
|
||||
} __packed;
|
||||
|
||||
enum ath12k_htt_stats_hw_mode {
|
||||
ATH12K_HTT_STATS_HWMODE_AC = 0,
|
||||
ATH12K_HTT_STATS_HWMODE_AX = 1,
|
||||
ATH12K_HTT_STATS_HWMODE_BE = 2,
|
||||
};
|
||||
|
||||
struct ath12k_htt_tx_pdev_mu_ppdu_dist_stats_tlv {
|
||||
__le32 hw_mode;
|
||||
__le32 num_seq_term_status[ATH12K_HTT_STATS_NUM_SCHED_STATUS_WORDS];
|
||||
__le32 num_ppdu_cmpl_per_burst[ATH12K_HTT_STATS_MU_PPDU_PER_BURST_WORDS];
|
||||
__le32 num_seq_posted[ATH12K_HTT_STATS_NUM_NR_BINS];
|
||||
__le32 num_ppdu_posted_per_burst[ATH12K_HTT_STATS_MU_PPDU_PER_BURST_WORDS];
|
||||
} __packed;
|
||||
|
||||
#define ATH12K_HTT_TX_PDEV_STATS_SCHED_PER_TXQ_MAC_ID GENMASK(7, 0)
|
||||
#define ATH12K_HTT_TX_PDEV_STATS_SCHED_PER_TXQ_ID GENMASK(15, 8)
|
||||
|
||||
#define ATH12K_HTT_TX_PDEV_NUM_SCHED_ORDER_LOG 20
|
||||
|
||||
struct ath12k_htt_stats_tx_sched_cmn_tlv {
|
||||
__le32 mac_id__word;
|
||||
__le32 current_timestamp;
|
||||
} __packed;
|
||||
|
||||
struct ath12k_htt_tx_pdev_stats_sched_per_txq_tlv {
|
||||
__le32 mac_id__word;
|
||||
__le32 sched_policy;
|
||||
__le32 last_sched_cmd_posted_timestamp;
|
||||
__le32 last_sched_cmd_compl_timestamp;
|
||||
__le32 sched_2_tac_lwm_count;
|
||||
__le32 sched_2_tac_ring_full;
|
||||
__le32 sched_cmd_post_failure;
|
||||
__le32 num_active_tids;
|
||||
__le32 num_ps_schedules;
|
||||
__le32 sched_cmds_pending;
|
||||
__le32 num_tid_register;
|
||||
__le32 num_tid_unregister;
|
||||
__le32 num_qstats_queried;
|
||||
__le32 qstats_update_pending;
|
||||
__le32 last_qstats_query_timestamp;
|
||||
__le32 num_tqm_cmdq_full;
|
||||
__le32 num_de_sched_algo_trigger;
|
||||
__le32 num_rt_sched_algo_trigger;
|
||||
__le32 num_tqm_sched_algo_trigger;
|
||||
__le32 notify_sched;
|
||||
__le32 dur_based_sendn_term;
|
||||
__le32 su_notify2_sched;
|
||||
__le32 su_optimal_queued_msdus_sched;
|
||||
__le32 su_delay_timeout_sched;
|
||||
__le32 su_min_txtime_sched_delay;
|
||||
__le32 su_no_delay;
|
||||
__le32 num_supercycles;
|
||||
__le32 num_subcycles_with_sort;
|
||||
__le32 num_subcycles_no_sort;
|
||||
} __packed;
|
||||
|
||||
struct ath12k_htt_sched_txq_cmd_posted_tlv {
|
||||
DECLARE_FLEX_ARRAY(__le32, sched_cmd_posted);
|
||||
} __packed;
|
||||
|
||||
struct ath12k_htt_sched_txq_cmd_reaped_tlv {
|
||||
DECLARE_FLEX_ARRAY(__le32, sched_cmd_reaped);
|
||||
} __packed;
|
||||
|
||||
struct ath12k_htt_sched_txq_sched_order_su_tlv {
|
||||
DECLARE_FLEX_ARRAY(__le32, sched_order_su);
|
||||
} __packed;
|
||||
|
||||
struct ath12k_htt_sched_txq_sched_ineligibility_tlv {
|
||||
DECLARE_FLEX_ARRAY(__le32, sched_ineligibility);
|
||||
} __packed;
|
||||
|
||||
enum ath12k_htt_sched_txq_supercycle_triggers_tlv_enum {
|
||||
ATH12K_HTT_SCHED_SUPERCYCLE_TRIGGER_NONE = 0,
|
||||
ATH12K_HTT_SCHED_SUPERCYCLE_TRIGGER_FORCED,
|
||||
ATH12K_HTT_SCHED_SUPERCYCLE_TRIGGER_LESS_NUM_TIDQ_ENTRIES,
|
||||
ATH12K_HTT_SCHED_SUPERCYCLE_TRIGGER_LESS_NUM_ACTIVE_TIDS,
|
||||
ATH12K_HTT_SCHED_SUPERCYCLE_TRIGGER_MAX_ITR_REACHED,
|
||||
ATH12K_HTT_SCHED_SUPERCYCLE_TRIGGER_DUR_THRESHOLD_REACHED,
|
||||
ATH12K_HTT_SCHED_SUPERCYCLE_TRIGGER_TWT_TRIGGER,
|
||||
ATH12K_HTT_SCHED_SUPERCYCLE_TRIGGER_MAX,
|
||||
};
|
||||
|
||||
struct ath12k_htt_sched_txq_supercycle_triggers_tlv {
|
||||
DECLARE_FLEX_ARRAY(__le32, supercycle_triggers);
|
||||
} __packed;
|
||||
|
||||
struct ath12k_htt_hw_stats_pdev_errs_tlv {
|
||||
__le32 mac_id__word;
|
||||
__le32 tx_abort;
|
||||
__le32 tx_abort_fail_count;
|
||||
__le32 rx_abort;
|
||||
__le32 rx_abort_fail_count;
|
||||
__le32 warm_reset;
|
||||
__le32 cold_reset;
|
||||
__le32 tx_flush;
|
||||
__le32 tx_glb_reset;
|
||||
__le32 tx_txq_reset;
|
||||
__le32 rx_timeout_reset;
|
||||
__le32 mac_cold_reset_restore_cal;
|
||||
__le32 mac_cold_reset;
|
||||
__le32 mac_warm_reset;
|
||||
__le32 mac_only_reset;
|
||||
__le32 phy_warm_reset;
|
||||
__le32 phy_warm_reset_ucode_trig;
|
||||
__le32 mac_warm_reset_restore_cal;
|
||||
__le32 mac_sfm_reset;
|
||||
__le32 phy_warm_reset_m3_ssr;
|
||||
__le32 phy_warm_reset_reason_phy_m3;
|
||||
__le32 phy_warm_reset_reason_tx_hw_stuck;
|
||||
__le32 phy_warm_reset_reason_num_rx_frame_stuck;
|
||||
__le32 phy_warm_reset_reason_wal_rx_rec_rx_busy;
|
||||
__le32 phy_warm_reset_reason_wal_rx_rec_mac_hng;
|
||||
__le32 phy_warm_reset_reason_mac_conv_phy_reset;
|
||||
__le32 wal_rx_recovery_rst_mac_hang_cnt;
|
||||
__le32 wal_rx_recovery_rst_known_sig_cnt;
|
||||
__le32 wal_rx_recovery_rst_no_rx_cnt;
|
||||
__le32 wal_rx_recovery_rst_no_rx_consec_cnt;
|
||||
__le32 wal_rx_recovery_rst_rx_busy_cnt;
|
||||
__le32 wal_rx_recovery_rst_phy_mac_hang_cnt;
|
||||
__le32 rx_flush_cnt;
|
||||
__le32 phy_warm_reset_reason_tx_exp_cca_stuck;
|
||||
__le32 phy_warm_reset_reason_tx_consec_flsh_war;
|
||||
__le32 phy_warm_reset_reason_tx_hwsch_reset_war;
|
||||
__le32 phy_warm_reset_reason_hwsch_cca_wdog_war;
|
||||
__le32 fw_rx_rings_reset;
|
||||
__le32 rx_dest_drain_rx_descs_leak_prevented;
|
||||
__le32 rx_dest_drain_rx_descs_saved_cnt;
|
||||
__le32 rx_dest_drain_rxdma2reo_leak_detected;
|
||||
__le32 rx_dest_drain_rxdma2fw_leak_detected;
|
||||
__le32 rx_dest_drain_rxdma2wbm_leak_detected;
|
||||
__le32 rx_dest_drain_rxdma1_2sw_leak_detected;
|
||||
__le32 rx_dest_drain_rx_drain_ok_mac_idle;
|
||||
__le32 rx_dest_drain_ok_mac_not_idle;
|
||||
__le32 rx_dest_drain_prerequisite_invld;
|
||||
__le32 rx_dest_drain_skip_non_lmac_reset;
|
||||
__le32 rx_dest_drain_hw_fifo_notempty_post_wait;
|
||||
} __packed;
|
||||
|
||||
#define ATH12K_HTT_STATS_MAX_HW_INTR_NAME_LEN 8
|
||||
struct ath12k_htt_hw_stats_intr_misc_tlv {
|
||||
u8 hw_intr_name[ATH12K_HTT_STATS_MAX_HW_INTR_NAME_LEN];
|
||||
__le32 mask;
|
||||
__le32 count;
|
||||
} __packed;
|
||||
|
||||
struct ath12k_htt_hw_stats_whal_tx_tlv {
|
||||
__le32 mac_id__word;
|
||||
__le32 last_unpause_ppdu_id;
|
||||
__le32 hwsch_unpause_wait_tqm_write;
|
||||
__le32 hwsch_dummy_tlv_skipped;
|
||||
__le32 hwsch_misaligned_offset_received;
|
||||
__le32 hwsch_reset_count;
|
||||
__le32 hwsch_dev_reset_war;
|
||||
__le32 hwsch_delayed_pause;
|
||||
__le32 hwsch_long_delayed_pause;
|
||||
__le32 sch_rx_ppdu_no_response;
|
||||
__le32 sch_selfgen_response;
|
||||
__le32 sch_rx_sifs_resp_trigger;
|
||||
} __packed;
|
||||
|
||||
struct ath12k_htt_hw_war_stats_tlv {
|
||||
__le32 mac_id__word;
|
||||
DECLARE_FLEX_ARRAY(__le32, hw_wars);
|
||||
} __packed;
|
||||
|
||||
struct ath12k_htt_tx_tqm_cmn_stats_tlv {
|
||||
__le32 mac_id__word;
|
||||
__le32 max_cmdq_id;
|
||||
__le32 list_mpdu_cnt_hist_intvl;
|
||||
__le32 add_msdu;
|
||||
__le32 q_empty;
|
||||
__le32 q_not_empty;
|
||||
__le32 drop_notification;
|
||||
__le32 desc_threshold;
|
||||
__le32 hwsch_tqm_invalid_status;
|
||||
__le32 missed_tqm_gen_mpdus;
|
||||
__le32 tqm_active_tids;
|
||||
__le32 tqm_inactive_tids;
|
||||
__le32 tqm_active_msduq_flows;
|
||||
__le32 msduq_timestamp_updates;
|
||||
__le32 msduq_updates_mpdu_head_info_cmd;
|
||||
__le32 msduq_updates_emp_to_nonemp_status;
|
||||
__le32 get_mpdu_head_info_cmds_by_query;
|
||||
__le32 get_mpdu_head_info_cmds_by_tac;
|
||||
__le32 gen_mpdu_cmds_by_query;
|
||||
__le32 high_prio_q_not_empty;
|
||||
} __packed;
|
||||
|
||||
struct ath12k_htt_tx_tqm_error_stats_tlv {
|
||||
__le32 q_empty_failure;
|
||||
__le32 q_not_empty_failure;
|
||||
__le32 add_msdu_failure;
|
||||
__le32 tqm_cache_ctl_err;
|
||||
__le32 tqm_soft_reset;
|
||||
__le32 tqm_reset_num_in_use_link_descs;
|
||||
__le32 tqm_reset_num_lost_link_descs;
|
||||
__le32 tqm_reset_num_lost_host_tx_buf_cnt;
|
||||
__le32 tqm_reset_num_in_use_internal_tqm;
|
||||
__le32 tqm_reset_num_in_use_idle_link_rng;
|
||||
__le32 tqm_reset_time_to_tqm_hang_delta_ms;
|
||||
__le32 tqm_reset_recovery_time_ms;
|
||||
__le32 tqm_reset_num_peers_hdl;
|
||||
__le32 tqm_reset_cumm_dirty_hw_mpduq_cnt;
|
||||
__le32 tqm_reset_cumm_dirty_hw_msduq_proc;
|
||||
__le32 tqm_reset_flush_cache_cmd_su_cnt;
|
||||
__le32 tqm_reset_flush_cache_cmd_other_cnt;
|
||||
__le32 tqm_reset_flush_cache_cmd_trig_type;
|
||||
__le32 tqm_reset_flush_cache_cmd_trig_cfg;
|
||||
__le32 tqm_reset_flush_cmd_skp_status_null;
|
||||
} __packed;
|
||||
|
||||
struct ath12k_htt_tx_tqm_gen_mpdu_stats_tlv {
|
||||
DECLARE_FLEX_ARRAY(__le32, gen_mpdu_end_reason);
|
||||
} __packed;
|
||||
|
||||
#define ATH12K_HTT_TX_TQM_MAX_LIST_MPDU_END_REASON 16
|
||||
#define ATH12K_HTT_TX_TQM_MAX_LIST_MPDU_CNT_HISTOGRAM_BINS 16
|
||||
|
||||
struct ath12k_htt_tx_tqm_list_mpdu_stats_tlv {
|
||||
DECLARE_FLEX_ARRAY(__le32, list_mpdu_end_reason);
|
||||
} __packed;
|
||||
|
||||
struct ath12k_htt_tx_tqm_list_mpdu_cnt_tlv {
|
||||
DECLARE_FLEX_ARRAY(__le32, list_mpdu_cnt_hist);
|
||||
} __packed;
|
||||
|
||||
struct ath12k_htt_tx_tqm_pdev_stats_tlv {
|
||||
__le32 msdu_count;
|
||||
__le32 mpdu_count;
|
||||
__le32 remove_msdu;
|
||||
__le32 remove_mpdu;
|
||||
__le32 remove_msdu_ttl;
|
||||
__le32 send_bar;
|
||||
__le32 bar_sync;
|
||||
__le32 notify_mpdu;
|
||||
__le32 sync_cmd;
|
||||
__le32 write_cmd;
|
||||
__le32 hwsch_trigger;
|
||||
__le32 ack_tlv_proc;
|
||||
__le32 gen_mpdu_cmd;
|
||||
__le32 gen_list_cmd;
|
||||
__le32 remove_mpdu_cmd;
|
||||
__le32 remove_mpdu_tried_cmd;
|
||||
__le32 mpdu_queue_stats_cmd;
|
||||
__le32 mpdu_head_info_cmd;
|
||||
__le32 msdu_flow_stats_cmd;
|
||||
__le32 remove_msdu_cmd;
|
||||
__le32 remove_msdu_ttl_cmd;
|
||||
__le32 flush_cache_cmd;
|
||||
__le32 update_mpduq_cmd;
|
||||
__le32 enqueue;
|
||||
__le32 enqueue_notify;
|
||||
__le32 notify_mpdu_at_head;
|
||||
__le32 notify_mpdu_state_valid;
|
||||
__le32 sched_udp_notify1;
|
||||
__le32 sched_udp_notify2;
|
||||
__le32 sched_nonudp_notify1;
|
||||
__le32 sched_nonudp_notify2;
|
||||
} __packed;
|
||||
|
||||
#endif
|
@ -333,6 +333,7 @@ struct ath12k_dp {
|
||||
struct dp_srng reo_except_ring;
|
||||
struct dp_srng reo_cmd_ring;
|
||||
struct dp_srng reo_status_ring;
|
||||
enum ath12k_peer_metadata_version peer_metadata_ver;
|
||||
struct dp_srng reo_dst_ring[DP_REO_DST_RING_MAX];
|
||||
struct dp_tx_ring tx_ring[DP_TCL_NUM_RING_MAX];
|
||||
struct hal_wbm_idle_scatter_list scatter_list[DP_IDLE_SCATTER_BUFS_MAX];
|
||||
|
@ -17,6 +17,7 @@
|
||||
#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)
|
||||
|
||||
@ -1268,10 +1269,10 @@ static int ath12k_htt_tlv_ppdu_stats_parse(struct ath12k_base *ab,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static 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_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;
|
||||
@ -1741,6 +1742,7 @@ void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab,
|
||||
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);
|
||||
@ -2583,6 +2585,29 @@ static void ath12k_dp_rx_process_received_packets(struct ath12k_base *ab,
|
||||
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)
|
||||
{
|
||||
@ -2611,6 +2636,8 @@ 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;
|
||||
|
||||
@ -2658,16 +2685,19 @@ try_again:
|
||||
continue;
|
||||
}
|
||||
|
||||
rxcb->is_first_msdu = !!(le32_to_cpu(desc->rx_msdu_info.info0) &
|
||||
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(desc->rx_msdu_info.info0) &
|
||||
rxcb->is_last_msdu = !!(le32_to_cpu(msdu_info->info0) &
|
||||
RX_MSDU_DESC_INFO0_LAST_MSDU_IN_MPDU);
|
||||
rxcb->is_continuation = !!(le32_to_cpu(desc->rx_msdu_info.info0) &
|
||||
rxcb->is_continuation = !!(le32_to_cpu(msdu_info->info0) &
|
||||
RX_MSDU_DESC_INFO0_MSDU_CONTINUATION);
|
||||
rxcb->mac_id = mac_id;
|
||||
rxcb->peer_id = le32_get_bits(desc->rx_mpdu_info.peer_meta_data,
|
||||
RX_MPDU_DESC_META_DATA_PEER_ID);
|
||||
rxcb->tid = le32_get_bits(desc->rx_mpdu_info.info0,
|
||||
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);
|
||||
@ -3402,7 +3432,7 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
|
||||
struct ath12k *ar;
|
||||
dma_addr_t paddr;
|
||||
bool is_frag;
|
||||
bool drop = false;
|
||||
bool drop;
|
||||
int pdev_id;
|
||||
|
||||
tot_n_bufs_reaped = 0;
|
||||
@ -3420,7 +3450,9 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
|
||||
|
||||
while (budget &&
|
||||
(reo_desc = ath12k_hal_srng_dst_get_next_entry(ab, srng))) {
|
||||
drop = false;
|
||||
ab->soc_stats.err_ring_pkts++;
|
||||
|
||||
ret = ath12k_hal_desc_reo_parse_err(ab, reo_desc, &paddr,
|
||||
&desc_bank);
|
||||
if (ret) {
|
||||
|
@ -139,4 +139,8 @@ ath12k_dp_rx_h_find_peer(struct ath12k_base *ab, struct sk_buff *msdu);
|
||||
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);
|
||||
#endif /* ATH12K_DP_RX_H */
|
||||
|
@ -1086,6 +1086,7 @@ ath12k_dp_tx_htt_h2t_ext_stats_req(struct ath12k *ar, u8 type,
|
||||
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)
|
||||
@ -1097,7 +1098,8 @@ ath12k_dp_tx_htt_h2t_ext_stats_req(struct ath12k *ar, u8 type,
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_EXT_STATS_CFG;
|
||||
|
||||
cmd->hdr.pdev_mask = 1 << ar->pdev->pdev_id;
|
||||
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);
|
||||
|
@ -597,8 +597,30 @@ struct hal_tlv_64_hdr {
|
||||
#define RX_MPDU_DESC_INFO0_MPDU_QOS_CTRL_VALID BIT(27)
|
||||
#define RX_MPDU_DESC_INFO0_TID GENMASK(31, 28)
|
||||
|
||||
/* TODO revisit after meta data is concluded */
|
||||
#define RX_MPDU_DESC_META_DATA_PEER_ID GENMASK(15, 0)
|
||||
/* Peer Metadata classification */
|
||||
|
||||
/* Version 0 */
|
||||
#define RX_MPDU_DESC_META_DATA_V0_PEER_ID GENMASK(15, 0)
|
||||
#define RX_MPDU_DESC_META_DATA_V0_VDEV_ID GENMASK(23, 16)
|
||||
|
||||
/* Version 1 */
|
||||
#define RX_MPDU_DESC_META_DATA_V1_PEER_ID GENMASK(13, 0)
|
||||
#define RX_MPDU_DESC_META_DATA_V1_LOGICAL_LINK_ID GENMASK(15, 14)
|
||||
#define RX_MPDU_DESC_META_DATA_V1_VDEV_ID GENMASK(23, 16)
|
||||
#define RX_MPDU_DESC_META_DATA_V1_LMAC_ID GENMASK(25, 24)
|
||||
#define RX_MPDU_DESC_META_DATA_V1_DEVICE_ID GENMASK(28, 26)
|
||||
|
||||
/* Version 1A */
|
||||
#define RX_MPDU_DESC_META_DATA_V1A_PEER_ID GENMASK(13, 0)
|
||||
#define RX_MPDU_DESC_META_DATA_V1A_VDEV_ID GENMASK(21, 14)
|
||||
#define RX_MPDU_DESC_META_DATA_V1A_LOGICAL_LINK_ID GENMASK(25, 22)
|
||||
#define RX_MPDU_DESC_META_DATA_V1A_DEVICE_ID GENMASK(28, 26)
|
||||
|
||||
/* Version 1B */
|
||||
#define RX_MPDU_DESC_META_DATA_V1B_PEER_ID GENMASK(13, 0)
|
||||
#define RX_MPDU_DESC_META_DATA_V1B_VDEV_ID GENMASK(21, 14)
|
||||
#define RX_MPDU_DESC_META_DATA_V1B_HW_LINK_ID GENMASK(25, 22)
|
||||
#define RX_MPDU_DESC_META_DATA_V1B_DEVICE_ID GENMASK(28, 26)
|
||||
|
||||
struct rx_mpdu_desc {
|
||||
__le32 info0; /* %RX_MPDU_DESC_INFO */
|
||||
|
@ -244,6 +244,11 @@ static void ath12k_htc_suspend_complete(struct ath12k_base *ab, bool ack)
|
||||
complete(&ab->htc_suspend);
|
||||
}
|
||||
|
||||
static void ath12k_htc_wakeup_from_suspend(struct ath12k_base *ab)
|
||||
{
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot wakeup from suspend is received\n");
|
||||
}
|
||||
|
||||
void ath12k_htc_rx_completion_handler(struct ath12k_base *ab,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
@ -349,6 +354,7 @@ void ath12k_htc_rx_completion_handler(struct ath12k_base *ab,
|
||||
ath12k_htc_suspend_complete(ab, false);
|
||||
break;
|
||||
case ATH12K_HTC_MSG_WAKEUP_FROM_SUSPEND_ID:
|
||||
ath12k_htc_wakeup_from_suspend(ab);
|
||||
break;
|
||||
default:
|
||||
ath12k_warn(ab, "ignoring unsolicited htc ep0 event %u\n",
|
||||
|
@ -78,8 +78,6 @@
|
||||
#define TARGET_NUM_WDS_ENTRIES 32
|
||||
#define TARGET_DMA_BURST_SIZE 1
|
||||
#define TARGET_RX_BATCHMODE 1
|
||||
#define TARGET_RX_PEER_METADATA_VER_V1A 2
|
||||
#define TARGET_RX_PEER_METADATA_VER_V1B 3
|
||||
#define TARGET_EMA_MAX_PROFILE_PERIOD 8
|
||||
|
||||
#define ATH12K_HW_DEFAULT_QUEUE 0
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <net/mac80211.h>
|
||||
#include <linux/etherdevice.h>
|
||||
|
||||
#include "mac.h"
|
||||
#include "core.h"
|
||||
#include "debug.h"
|
||||
@ -15,6 +16,8 @@
|
||||
#include "dp_rx.h"
|
||||
#include "peer.h"
|
||||
#include "debugfs.h"
|
||||
#include "hif.h"
|
||||
#include "wow.h"
|
||||
|
||||
#define CHAN2G(_channel, _freq, _flags) { \
|
||||
.band = NL80211_BAND_2GHZ, \
|
||||
@ -670,6 +673,82 @@ static struct ath12k *ath12k_get_ar_by_vif(struct ieee80211_hw *hw,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct ath12k_vif *ath12k_mac_get_vif_up(struct ath12k *ar)
|
||||
{
|
||||
struct ath12k_vif *arvif;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
list_for_each_entry(arvif, &ar->arvifs, list) {
|
||||
if (arvif->is_up)
|
||||
return arvif;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool ath12k_mac_band_match(enum nl80211_band band1, enum WMI_HOST_WLAN_BAND band2)
|
||||
{
|
||||
switch (band1) {
|
||||
case NL80211_BAND_2GHZ:
|
||||
if (band2 & WMI_HOST_WLAN_2G_CAP)
|
||||
return true;
|
||||
break;
|
||||
case NL80211_BAND_5GHZ:
|
||||
case NL80211_BAND_6GHZ:
|
||||
if (band2 & WMI_HOST_WLAN_5G_CAP)
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static u8 ath12k_mac_get_target_pdev_id_from_vif(struct ath12k_vif *arvif)
|
||||
{
|
||||
struct ath12k *ar = arvif->ar;
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
struct ieee80211_vif *vif = arvif->vif;
|
||||
struct cfg80211_chan_def def;
|
||||
enum nl80211_band band;
|
||||
u8 pdev_id = ab->fw_pdev[0].pdev_id;
|
||||
int i;
|
||||
|
||||
if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
|
||||
return pdev_id;
|
||||
|
||||
band = def.chan->band;
|
||||
|
||||
for (i = 0; i < ab->fw_pdev_count; i++) {
|
||||
if (ath12k_mac_band_match(band, ab->fw_pdev[i].supported_bands))
|
||||
return ab->fw_pdev[i].pdev_id;
|
||||
}
|
||||
|
||||
return pdev_id;
|
||||
}
|
||||
|
||||
u8 ath12k_mac_get_target_pdev_id(struct ath12k *ar)
|
||||
{
|
||||
struct ath12k_vif *arvif;
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
|
||||
if (!ab->hw_params->single_pdev_only)
|
||||
return ar->pdev->pdev_id;
|
||||
|
||||
arvif = ath12k_mac_get_vif_up(ar);
|
||||
|
||||
/* fw_pdev array has pdev ids derived from phy capability
|
||||
* service ready event (pdev_and_hw_link_ids).
|
||||
* If no vif is active, return default first index.
|
||||
*/
|
||||
if (!arvif)
|
||||
return ar->ab->fw_pdev[0].pdev_id;
|
||||
|
||||
/* If active vif is found, return the pdev id matching chandef band */
|
||||
return ath12k_mac_get_target_pdev_id_from_vif(arvif);
|
||||
}
|
||||
|
||||
static void ath12k_pdev_caps_update(struct ath12k *ar)
|
||||
{
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
@ -2050,7 +2129,9 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar,
|
||||
{
|
||||
const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
|
||||
int i;
|
||||
u8 ampdu_factor, rx_mcs_80, rx_mcs_160, max_nss;
|
||||
u8 ampdu_factor, max_nss;
|
||||
u8 rx_mcs_80 = IEEE80211_HE_MCS_NOT_SUPPORTED;
|
||||
u8 rx_mcs_160 = IEEE80211_HE_MCS_NOT_SUPPORTED;
|
||||
u16 mcs_160_map, mcs_80_map;
|
||||
bool support_160;
|
||||
u16 v;
|
||||
@ -2255,9 +2336,6 @@ static int ath12k_get_smps_from_capa(const struct ieee80211_sta_ht_cap *ht_cap,
|
||||
const struct ieee80211_he_6ghz_capa *he_6ghz_capa,
|
||||
int *smps)
|
||||
{
|
||||
if (!ht_cap->ht_supported && !he_6ghz_capa->capa)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (ht_cap->ht_supported)
|
||||
*smps = u16_get_bits(ht_cap->cap, IEEE80211_HT_CAP_SM_PS);
|
||||
else
|
||||
@ -2277,6 +2355,9 @@ static void ath12k_peer_assoc_h_smps(struct ieee80211_sta *sta,
|
||||
const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
|
||||
int smps;
|
||||
|
||||
if (!ht_cap->ht_supported && !he_6ghz_capa->capa)
|
||||
return;
|
||||
|
||||
if (ath12k_get_smps_from_capa(ht_cap, he_6ghz_capa, &smps))
|
||||
return;
|
||||
|
||||
@ -2756,6 +2837,9 @@ static int ath12k_setup_peer_smps(struct ath12k *ar, struct ath12k_vif *arvif,
|
||||
{
|
||||
int smps, ret = 0;
|
||||
|
||||
if (!ht_cap->ht_supported && !he_6ghz_capa)
|
||||
return 0;
|
||||
|
||||
ret = ath12k_get_smps_from_capa(ht_cap, he_6ghz_capa, &smps);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -2834,6 +2918,7 @@ static void ath12k_bss_assoc(struct ath12k *ar,
|
||||
}
|
||||
|
||||
arvif->is_up = true;
|
||||
arvif->rekey_data.enable_offload = false;
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
|
||||
"mac vdev %d up (associated) bssid %pM aid %d\n",
|
||||
@ -2881,6 +2966,8 @@ static void ath12k_bss_disassoc(struct ath12k *ar,
|
||||
|
||||
arvif->is_up = false;
|
||||
|
||||
memset(&arvif->rekey_data, 0, sizeof(arvif->rekey_data));
|
||||
|
||||
cancel_delayed_work(&arvif->connection_loss_work);
|
||||
}
|
||||
|
||||
@ -3372,7 +3459,7 @@ static void ath12k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
static struct ath12k*
|
||||
ath12k_mac_select_scan_device(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_scan_request *req)
|
||||
u32 center_freq)
|
||||
{
|
||||
struct ath12k_hw *ah = hw->priv;
|
||||
enum nl80211_band band;
|
||||
@ -3389,9 +3476,9 @@ ath12k_mac_select_scan_device(struct ieee80211_hw *hw,
|
||||
* split the hw request and perform multiple scans
|
||||
*/
|
||||
|
||||
if (req->req.channels[0]->center_freq < ATH12K_MIN_5G_FREQ)
|
||||
if (center_freq < ATH12K_MIN_5G_FREQ)
|
||||
band = NL80211_BAND_2GHZ;
|
||||
else if (req->req.channels[0]->center_freq < ATH12K_MIN_6G_FREQ)
|
||||
else if (center_freq < ATH12K_MIN_6G_FREQ)
|
||||
band = NL80211_BAND_5GHZ;
|
||||
else
|
||||
band = NL80211_BAND_6GHZ;
|
||||
@ -3591,7 +3678,7 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
|
||||
/* Since the targeted scan device could depend on the frequency
|
||||
* requested in the hw_req, select the corresponding radio
|
||||
*/
|
||||
ar = ath12k_mac_select_scan_device(hw, vif, hw_req);
|
||||
ar = ath12k_mac_select_scan_device(hw, vif, hw_req->req.channels[0]->center_freq);
|
||||
if (!ar)
|
||||
return -EINVAL;
|
||||
|
||||
@ -4087,6 +4174,11 @@ static int ath12k_station_assoc(struct ath12k *ar,
|
||||
|
||||
ath12k_peer_assoc_prepare(ar, vif, sta, &peer_arg, reassoc);
|
||||
|
||||
if (peer_arg.peer_nss < 1) {
|
||||
ath12k_warn(ar->ab,
|
||||
"invalid peer NSS %d\n", peer_arg.peer_nss);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n",
|
||||
@ -5834,28 +5926,6 @@ static int ath12k_mac_config_mon_status_default(struct ath12k *ar, bool enable)
|
||||
/* TODO: Need to support new monitor mode */
|
||||
}
|
||||
|
||||
static void ath12k_mac_wait_reconfigure(struct ath12k_base *ab)
|
||||
{
|
||||
int recovery_start_count;
|
||||
|
||||
if (!ab->is_reset)
|
||||
return;
|
||||
|
||||
recovery_start_count = atomic_inc_return(&ab->recovery_start_count);
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_MAC, "recovery start count %d\n", recovery_start_count);
|
||||
|
||||
if (recovery_start_count == ab->num_radios) {
|
||||
complete(&ab->recovery_start);
|
||||
ath12k_dbg(ab, ATH12K_DBG_MAC, "recovery started success\n");
|
||||
}
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_MAC, "waiting reconfigure...\n");
|
||||
|
||||
wait_for_completion_timeout(&ab->reconfigure_complete,
|
||||
ATH12K_RECONFIGURE_TIMEOUT_HZ);
|
||||
}
|
||||
|
||||
static int ath12k_mac_start(struct ath12k *ar)
|
||||
{
|
||||
struct ath12k_hw *ah = ar->ah;
|
||||
@ -5987,7 +6057,6 @@ static int ath12k_mac_op_start(struct ieee80211_hw *hw)
|
||||
break;
|
||||
case ATH12K_HW_STATE_RESTARTING:
|
||||
ah->state = ATH12K_HW_STATE_RESTARTED;
|
||||
ath12k_mac_wait_reconfigure(ah->ab);
|
||||
break;
|
||||
case ATH12K_HW_STATE_RESTARTED:
|
||||
case ATH12K_HW_STATE_WEDGED:
|
||||
@ -8314,10 +8383,6 @@ static int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx,
|
||||
|
||||
if (!sband)
|
||||
sband = hw->wiphy->bands[NL80211_BAND_6GHZ];
|
||||
if (!sband || idx >= sband->n_channels) {
|
||||
idx -= sband->n_channels;
|
||||
sband = NULL;
|
||||
}
|
||||
|
||||
if (!sband || idx >= sband->n_channels)
|
||||
return -ENOENT;
|
||||
@ -8416,12 +8481,68 @@ static int ath12k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
|
||||
struct ath12k_wmi_scan_req_arg arg;
|
||||
struct ath12k *ar;
|
||||
struct ath12k *ar, *prev_ar;
|
||||
u32 scan_time_msec;
|
||||
bool create = true;
|
||||
int ret;
|
||||
|
||||
ar = ath12k_ah_to_ar(ah, 0);
|
||||
if (ah->num_radio == 1) {
|
||||
WARN_ON(!arvif->is_created);
|
||||
ar = ath12k_ah_to_ar(ah, 0);
|
||||
goto scan;
|
||||
}
|
||||
|
||||
ar = ath12k_mac_select_scan_device(hw, vif, chan->center_freq);
|
||||
if (!ar)
|
||||
return -EINVAL;
|
||||
|
||||
/* If the vif is already assigned to a specific vdev of an ar,
|
||||
* check whether its already started, vdev which is started
|
||||
* are not allowed to switch to a new radio.
|
||||
* If the vdev is not started, but was earlier created on a
|
||||
* different ar, delete that vdev and create a new one. We don't
|
||||
* delete at the scan stop as an optimization to avoid redundant
|
||||
* delete-create vdev's for the same ar, in case the request is
|
||||
* always on the same band for the vif
|
||||
*/
|
||||
if (arvif->is_created) {
|
||||
if (WARN_ON(!arvif->ar))
|
||||
return -EINVAL;
|
||||
|
||||
if (ar != arvif->ar && arvif->is_started)
|
||||
return -EBUSY;
|
||||
|
||||
if (ar != arvif->ar) {
|
||||
/* backup the previously used ar ptr, since the vdev delete
|
||||
* would assign the arvif->ar to NULL after the call
|
||||
*/
|
||||
prev_ar = arvif->ar;
|
||||
mutex_lock(&prev_ar->conf_mutex);
|
||||
ret = ath12k_mac_vdev_delete(prev_ar, vif);
|
||||
mutex_unlock(&prev_ar->conf_mutex);
|
||||
if (ret) {
|
||||
ath12k_warn(prev_ar->ab,
|
||||
"unable to delete scan vdev for roc: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
create = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (create) {
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
ret = ath12k_mac_vdev_create(ar, vif);
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "unable to create scan vdev for roc: %d\n",
|
||||
ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
scan:
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
@ -8503,6 +8624,40 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath12k_mac_op_set_rekey_data(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_gtk_rekey_data *data)
|
||||
{
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
struct ath12k_rekey_data *rekey_data = &arvif->rekey_data;
|
||||
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
|
||||
struct ath12k *ar = ath12k_ah_to_ar(ah, 0);
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac set rekey data vdev %d\n",
|
||||
arvif->vdev_id);
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
memcpy(rekey_data->kck, data->kck, NL80211_KCK_LEN);
|
||||
memcpy(rekey_data->kek, data->kek, NL80211_KEK_LEN);
|
||||
|
||||
/* The supplicant works on big-endian, the firmware expects it on
|
||||
* little endian.
|
||||
*/
|
||||
rekey_data->replay_ctr = get_unaligned_be64(data->replay_ctr);
|
||||
|
||||
arvif->rekey_data.enable_offload = true;
|
||||
|
||||
ath12k_dbg_dump(ar->ab, ATH12K_DBG_MAC, "kck", NULL,
|
||||
rekey_data->kck, NL80211_KCK_LEN);
|
||||
ath12k_dbg_dump(ar->ab, ATH12K_DBG_MAC, "kek", NULL,
|
||||
rekey_data->kck, NL80211_KEK_LEN);
|
||||
ath12k_dbg_dump(ar->ab, ATH12K_DBG_MAC, "replay ctr", NULL,
|
||||
&rekey_data->replay_ctr, sizeof(rekey_data->replay_ctr));
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
|
||||
static const struct ieee80211_ops ath12k_ops = {
|
||||
.tx = ath12k_mac_op_tx,
|
||||
.wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
@ -8518,6 +8673,7 @@ static const struct ieee80211_ops ath12k_ops = {
|
||||
.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,
|
||||
.sta_rc_update = ath12k_mac_op_sta_rc_update,
|
||||
@ -8539,6 +8695,12 @@ static const struct ieee80211_ops ath12k_ops = {
|
||||
.sta_statistics = ath12k_mac_op_sta_statistics,
|
||||
.remain_on_channel = ath12k_mac_op_remain_on_channel,
|
||||
.cancel_remain_on_channel = ath12k_mac_op_cancel_remain_on_channel,
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = ath12k_wow_op_suspend,
|
||||
.resume = ath12k_wow_op_resume,
|
||||
.set_wakeup = ath12k_wow_op_set_wakeup,
|
||||
#endif
|
||||
};
|
||||
|
||||
static void ath12k_mac_update_ch_list(struct ath12k *ar,
|
||||
@ -8836,8 +8998,10 @@ static void ath12k_mac_hw_unregister(struct ath12k_hw *ah)
|
||||
struct ath12k *ar;
|
||||
int i;
|
||||
|
||||
for_each_ar(ah, ar, i)
|
||||
for_each_ar(ah, ar, i) {
|
||||
cancel_work_sync(&ar->regd_update_work);
|
||||
ath12k_debugfs_unregister(ar);
|
||||
}
|
||||
|
||||
ieee80211_unregister_hw(hw);
|
||||
|
||||
@ -8901,6 +9065,7 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah)
|
||||
u32 ht_cap = U32_MAX, antennas_rx = 0, antennas_tx = 0;
|
||||
bool is_6ghz = false, is_raw_mode = false, is_monitor_disable = false;
|
||||
u8 *mac_addr = NULL;
|
||||
u8 mbssid_max_interfaces = 0;
|
||||
|
||||
wiphy->max_ap_assoc_sta = 0;
|
||||
|
||||
@ -8944,6 +9109,8 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah)
|
||||
mac_addr = ar->mac_addr;
|
||||
else
|
||||
mac_addr = ab->mac_addr;
|
||||
|
||||
mbssid_max_interfaces += TARGET_NUM_VDEVS;
|
||||
}
|
||||
|
||||
wiphy->available_antennas_rx = antennas_rx;
|
||||
@ -9036,7 +9203,7 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah)
|
||||
wiphy->iftype_ext_capab = ath12k_iftypes_ext_capa;
|
||||
wiphy->num_iftype_ext_capab = ARRAY_SIZE(ath12k_iftypes_ext_capa);
|
||||
|
||||
wiphy->mbssid_max_interfaces = TARGET_NUM_VDEVS;
|
||||
wiphy->mbssid_max_interfaces = mbssid_max_interfaces;
|
||||
wiphy->ema_max_profile_periodicity = TARGET_EMA_MAX_PROFILE_PERIOD;
|
||||
|
||||
if (is_6ghz) {
|
||||
@ -9056,6 +9223,24 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah)
|
||||
ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
|
||||
}
|
||||
|
||||
if (test_bit(WMI_TLV_SERVICE_NLO, ar->wmi->wmi_ab->svc_map)) {
|
||||
wiphy->max_sched_scan_ssids = WMI_PNO_MAX_SUPP_NETWORKS;
|
||||
wiphy->max_match_sets = WMI_PNO_MAX_SUPP_NETWORKS;
|
||||
wiphy->max_sched_scan_ie_len = WMI_PNO_MAX_IE_LENGTH;
|
||||
wiphy->max_sched_scan_plans = WMI_PNO_MAX_SCHED_SCAN_PLANS;
|
||||
wiphy->max_sched_scan_plan_interval =
|
||||
WMI_PNO_MAX_SCHED_SCAN_PLAN_INT;
|
||||
wiphy->max_sched_scan_plan_iterations =
|
||||
WMI_PNO_MAX_SCHED_SCAN_PLAN_ITRNS;
|
||||
wiphy->features |= NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
|
||||
}
|
||||
|
||||
ret = ath12k_wow_init(ar);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to init wow: %d\n", ret);
|
||||
goto err_free_if_combs;
|
||||
}
|
||||
|
||||
ret = ieee80211_register_hw(hw);
|
||||
if (ret) {
|
||||
ath12k_err(ab, "ieee80211 registration failed: %d\n", ret);
|
||||
@ -9077,13 +9262,16 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah)
|
||||
ath12k_err(ar->ab, "ath12k regd update failed: %d\n", ret);
|
||||
goto err_unregister_hw;
|
||||
}
|
||||
}
|
||||
|
||||
ath12k_debugfs_register(ar);
|
||||
ath12k_debugfs_register(ar);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_unregister_hw:
|
||||
for_each_ar(ah, ar, i)
|
||||
ath12k_debugfs_unregister(ar);
|
||||
|
||||
ieee80211_unregister_hw(hw);
|
||||
|
||||
err_free_if_combs:
|
||||
@ -9216,7 +9404,6 @@ static struct ath12k_hw *ath12k_mac_hw_allocate(struct ath12k_base *ab,
|
||||
|
||||
ah = ath12k_hw_to_ah(hw);
|
||||
ah->hw = hw;
|
||||
ah->ab = ab;
|
||||
ah->num_radio = num_pdev_map;
|
||||
|
||||
mutex_init(&ah->hw_mutex);
|
||||
@ -9307,3 +9494,34 @@ err:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_mac_vif_set_keepalive(struct ath12k_vif *arvif,
|
||||
enum wmi_sta_keepalive_method method,
|
||||
u32 interval)
|
||||
{
|
||||
struct wmi_sta_keepalive_arg arg = {};
|
||||
struct ath12k *ar = arvif->ar;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
|
||||
return 0;
|
||||
|
||||
if (!test_bit(WMI_TLV_SERVICE_STA_KEEP_ALIVE, ar->ab->wmi_ab.svc_map))
|
||||
return 0;
|
||||
|
||||
arg.vdev_id = arvif->vdev_id;
|
||||
arg.enabled = 1;
|
||||
arg.method = method;
|
||||
arg.interval = interval;
|
||||
|
||||
ret = ath12k_wmi_sta_keepalive(ar, &arg);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to set keepalive on vdev %i: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include <net/mac80211.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include "wmi.h"
|
||||
|
||||
struct ath12k;
|
||||
struct ath12k_base;
|
||||
@ -81,5 +82,9 @@ int ath12k_mac_rfkill_config(struct ath12k *ar);
|
||||
int ath12k_mac_wait_tx_complete(struct ath12k *ar);
|
||||
void ath12k_mac_handle_beacon(struct ath12k *ar, struct sk_buff *skb);
|
||||
void ath12k_mac_handle_beacon_miss(struct ath12k *ar, u32 vdev_id);
|
||||
int ath12k_mac_vif_set_keepalive(struct ath12k_vif *arvif,
|
||||
enum wmi_sta_keepalive_method method,
|
||||
u32 interval);
|
||||
u8 ath12k_mac_get_target_pdev_id(struct ath12k *ar);
|
||||
|
||||
#endif
|
||||
|
@ -233,7 +233,7 @@ void ath12k_wmi_init_qcn9274(struct ath12k_base *ab,
|
||||
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->dp_peer_meta_data_ver = TARGET_RX_PEER_METADATA_VER_V1B;
|
||||
config->peer_metadata_ver = ATH12K_PEER_METADATA_V1B;
|
||||
}
|
||||
|
||||
void ath12k_wmi_init_wcn7850(struct ath12k_base *ab,
|
||||
@ -3498,7 +3498,7 @@ ath12k_wmi_copy_resource_config(struct ath12k_wmi_resource_config_params *wmi_cf
|
||||
wmi_cfg->sched_params = cpu_to_le32(tg_cfg->sched_params);
|
||||
wmi_cfg->twt_ap_pdev_count = cpu_to_le32(tg_cfg->twt_ap_pdev_count);
|
||||
wmi_cfg->twt_ap_sta_count = cpu_to_le32(tg_cfg->twt_ap_sta_count);
|
||||
wmi_cfg->flags2 = le32_encode_bits(tg_cfg->dp_peer_meta_data_ver,
|
||||
wmi_cfg->flags2 = le32_encode_bits(tg_cfg->peer_metadata_ver,
|
||||
WMI_RSRC_CFG_FLAGS2_RX_PEER_METADATA_VERSION);
|
||||
wmi_cfg->host_service_flags = cpu_to_le32(tg_cfg->is_reg_cc_ext_event_supported <<
|
||||
WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT);
|
||||
@ -3717,6 +3717,7 @@ int ath12k_wmi_cmd_init(struct ath12k_base *ab)
|
||||
arg.res_cfg.is_reg_cc_ext_event_supported = true;
|
||||
|
||||
ab->hw_params->wmi_init(ab, &arg.res_cfg);
|
||||
ab->wow.wmi_conf_rx_decap_mode = arg.res_cfg.rx_decap_mode;
|
||||
|
||||
arg.num_mem_chunks = wmi_ab->num_mem_chunks;
|
||||
arg.hw_mode_id = wmi_ab->preferred_hw_mode;
|
||||
@ -3728,6 +3729,8 @@ 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;
|
||||
|
||||
return ath12k_init_cmd_send(&wmi_ab->wmi[0], &arg);
|
||||
}
|
||||
|
||||
@ -7030,6 +7033,116 @@ exit:
|
||||
kfree(tb);
|
||||
}
|
||||
|
||||
static int ath12k_wmi_wow_wakeup_host_parse(struct ath12k_base *ab,
|
||||
u16 tag, u16 len,
|
||||
const void *ptr, void *data)
|
||||
{
|
||||
const struct wmi_wow_ev_pg_fault_param *pf_param;
|
||||
const struct wmi_wow_ev_param *param;
|
||||
struct wmi_wow_ev_arg *arg = data;
|
||||
int pf_len;
|
||||
|
||||
switch (tag) {
|
||||
case WMI_TAG_WOW_EVENT_INFO:
|
||||
param = ptr;
|
||||
arg->wake_reason = le32_to_cpu(param->wake_reason);
|
||||
ath12k_dbg(ab, ATH12K_DBG_WMI, "wow wakeup host reason %d %s\n",
|
||||
arg->wake_reason, wow_reason(arg->wake_reason));
|
||||
break;
|
||||
|
||||
case WMI_TAG_ARRAY_BYTE:
|
||||
if (arg && arg->wake_reason == WOW_REASON_PAGE_FAULT) {
|
||||
pf_param = ptr;
|
||||
pf_len = le32_to_cpu(pf_param->len);
|
||||
if (pf_len > len - sizeof(pf_len) ||
|
||||
pf_len < 0) {
|
||||
ath12k_warn(ab, "invalid wo reason page fault buffer len %d\n",
|
||||
pf_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
ath12k_dbg(ab, ATH12K_DBG_WMI, "wow_reason_page_fault len %d\n",
|
||||
pf_len);
|
||||
ath12k_dbg_dump(ab, ATH12K_DBG_WMI,
|
||||
"wow_reason_page_fault packet present",
|
||||
"wow_pg_fault ",
|
||||
pf_param->data,
|
||||
pf_len);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath12k_wmi_event_wow_wakeup_host(struct ath12k_base *ab, struct sk_buff *skb)
|
||||
{
|
||||
struct wmi_wow_ev_arg arg = { };
|
||||
int ret;
|
||||
|
||||
ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len,
|
||||
ath12k_wmi_wow_wakeup_host_parse,
|
||||
&arg);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to parse wmi wow wakeup host event tlv: %d\n",
|
||||
ret);
|
||||
return;
|
||||
}
|
||||
|
||||
complete(&ab->wow.wakeup_completed);
|
||||
}
|
||||
|
||||
static void ath12k_wmi_gtk_offload_status_event(struct ath12k_base *ab,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
const struct wmi_gtk_offload_status_event *ev;
|
||||
struct ath12k_vif *arvif;
|
||||
__be64 replay_ctr_be;
|
||||
u64 replay_ctr;
|
||||
const void **tb;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ev = tb[WMI_TAG_GTK_OFFLOAD_STATUS_EVENT];
|
||||
if (!ev) {
|
||||
ath12k_warn(ab, "failed to fetch gtk offload status ev");
|
||||
kfree(tb);
|
||||
return;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
arvif = ath12k_mac_get_arvif_by_vdev_id(ab, le32_to_cpu(ev->vdev_id));
|
||||
if (!arvif) {
|
||||
rcu_read_unlock();
|
||||
ath12k_warn(ab, "failed to get arvif for vdev_id:%d\n",
|
||||
le32_to_cpu(ev->vdev_id));
|
||||
kfree(tb);
|
||||
return;
|
||||
}
|
||||
|
||||
replay_ctr = le64_to_cpu(ev->replay_ctr);
|
||||
arvif->rekey_data.replay_ctr = replay_ctr;
|
||||
ath12k_dbg(ab, ATH12K_DBG_WMI, "wmi gtk offload event refresh_cnt %d replay_ctr %llu\n",
|
||||
le32_to_cpu(ev->refresh_cnt), replay_ctr);
|
||||
|
||||
/* supplicant expects big-endian replay counter */
|
||||
replay_ctr_be = cpu_to_be64(replay_ctr);
|
||||
|
||||
ieee80211_gtk_rekey_notify(arvif->vif, arvif->bssid,
|
||||
(void *)&replay_ctr_be, GFP_ATOMIC);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
kfree(tb);
|
||||
}
|
||||
|
||||
static void ath12k_wmi_op_rx(struct ath12k_base *ab, struct sk_buff *skb)
|
||||
{
|
||||
struct wmi_cmd_hdr *cmd_hdr;
|
||||
@ -7150,6 +7263,12 @@ static void ath12k_wmi_op_rx(struct ath12k_base *ab, struct sk_buff *skb)
|
||||
case WMI_DIAG_EVENTID:
|
||||
ath12k_wmi_diag_event(ab, skb);
|
||||
break;
|
||||
case WMI_WOW_WAKEUP_HOST_EVENTID:
|
||||
ath12k_wmi_event_wow_wakeup_host(ab, skb);
|
||||
break;
|
||||
case WMI_GTK_OFFLOAD_STATUS_EVENTID:
|
||||
ath12k_wmi_gtk_offload_status_event(ab, skb);
|
||||
break;
|
||||
/* TODO: Add remaining events */
|
||||
default:
|
||||
ath12k_dbg(ab, ATH12K_DBG_WMI, "Unknown eventid: 0x%x\n", id);
|
||||
@ -7359,3 +7478,608 @@ void ath12k_wmi_detach(struct ath12k_base *ab)
|
||||
|
||||
ath12k_wmi_free_dbring_caps(ab);
|
||||
}
|
||||
|
||||
int ath12k_wmi_hw_data_filter_cmd(struct ath12k *ar, struct wmi_hw_data_filter_arg *arg)
|
||||
{
|
||||
struct wmi_hw_data_filter_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
int len;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_hw_data_filter_cmd *)skb->data;
|
||||
cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_HW_DATA_FILTER_CMD,
|
||||
sizeof(*cmd));
|
||||
cmd->vdev_id = cpu_to_le32(arg->vdev_id);
|
||||
cmd->enable = cpu_to_le32(arg->enable ? 1 : 0);
|
||||
|
||||
/* Set all modes in case of disable */
|
||||
if (arg->enable)
|
||||
cmd->hw_filter_bitmap = cpu_to_le32(arg->hw_filter_bitmap);
|
||||
else
|
||||
cmd->hw_filter_bitmap = cpu_to_le32((u32)~0U);
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
|
||||
"wmi hw data filter enable %d filter_bitmap 0x%x\n",
|
||||
arg->enable, arg->hw_filter_bitmap);
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_HW_DATA_FILTER_CMDID);
|
||||
}
|
||||
|
||||
int ath12k_wmi_wow_host_wakeup_ind(struct ath12k *ar)
|
||||
{
|
||||
struct wmi_wow_host_wakeup_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_wow_host_wakeup_cmd *)skb->data;
|
||||
cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_WOW_HOSTWAKEUP_FROM_SLEEP_CMD,
|
||||
sizeof(*cmd));
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv wow host wakeup ind\n");
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);
|
||||
}
|
||||
|
||||
int ath12k_wmi_wow_enable(struct ath12k *ar)
|
||||
{
|
||||
struct wmi_wow_enable_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
int len;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_wow_enable_cmd *)skb->data;
|
||||
cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_WOW_ENABLE_CMD,
|
||||
sizeof(*cmd));
|
||||
|
||||
cmd->enable = cpu_to_le32(1);
|
||||
cmd->pause_iface_config = cpu_to_le32(WOW_IFACE_PAUSE_ENABLED);
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv wow enable\n");
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_CMDID);
|
||||
}
|
||||
|
||||
int ath12k_wmi_wow_add_wakeup_event(struct ath12k *ar, u32 vdev_id,
|
||||
enum wmi_wow_wakeup_event event,
|
||||
u32 enable)
|
||||
{
|
||||
struct wmi_wow_add_del_event_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_wow_add_del_event_cmd *)skb->data;
|
||||
cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_WOW_ADD_DEL_EVT_CMD,
|
||||
sizeof(*cmd));
|
||||
cmd->vdev_id = cpu_to_le32(vdev_id);
|
||||
cmd->is_add = cpu_to_le32(enable);
|
||||
cmd->event_bitmap = cpu_to_le32((1 << event));
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv wow add wakeup event %s enable %d vdev_id %d\n",
|
||||
wow_wakeup_event(event), enable, vdev_id);
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID);
|
||||
}
|
||||
|
||||
int ath12k_wmi_wow_add_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id,
|
||||
const u8 *pattern, const u8 *mask,
|
||||
int pattern_len, int pattern_offset)
|
||||
{
|
||||
struct wmi_wow_add_pattern_cmd *cmd;
|
||||
struct wmi_wow_bitmap_pattern_params *bitmap;
|
||||
struct wmi_tlv *tlv;
|
||||
struct sk_buff *skb;
|
||||
void *ptr;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*cmd) +
|
||||
sizeof(*tlv) + /* array struct */
|
||||
sizeof(*bitmap) + /* bitmap */
|
||||
sizeof(*tlv) + /* empty ipv4 sync */
|
||||
sizeof(*tlv) + /* empty ipv6 sync */
|
||||
sizeof(*tlv) + /* empty magic */
|
||||
sizeof(*tlv) + /* empty info timeout */
|
||||
sizeof(*tlv) + sizeof(u32); /* ratelimit interval */
|
||||
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
/* cmd */
|
||||
ptr = skb->data;
|
||||
cmd = ptr;
|
||||
cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_WOW_ADD_PATTERN_CMD,
|
||||
sizeof(*cmd));
|
||||
cmd->vdev_id = cpu_to_le32(vdev_id);
|
||||
cmd->pattern_id = cpu_to_le32(pattern_id);
|
||||
cmd->pattern_type = cpu_to_le32(WOW_BITMAP_PATTERN);
|
||||
|
||||
ptr += sizeof(*cmd);
|
||||
|
||||
/* bitmap */
|
||||
tlv = ptr;
|
||||
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, sizeof(*bitmap));
|
||||
|
||||
ptr += sizeof(*tlv);
|
||||
|
||||
bitmap = ptr;
|
||||
bitmap->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_WOW_BITMAP_PATTERN_T,
|
||||
sizeof(*bitmap));
|
||||
memcpy(bitmap->patternbuf, pattern, pattern_len);
|
||||
memcpy(bitmap->bitmaskbuf, mask, pattern_len);
|
||||
bitmap->pattern_offset = cpu_to_le32(pattern_offset);
|
||||
bitmap->pattern_len = cpu_to_le32(pattern_len);
|
||||
bitmap->bitmask_len = cpu_to_le32(pattern_len);
|
||||
bitmap->pattern_id = cpu_to_le32(pattern_id);
|
||||
|
||||
ptr += sizeof(*bitmap);
|
||||
|
||||
/* ipv4 sync */
|
||||
tlv = ptr;
|
||||
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, 0);
|
||||
|
||||
ptr += sizeof(*tlv);
|
||||
|
||||
/* ipv6 sync */
|
||||
tlv = ptr;
|
||||
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, 0);
|
||||
|
||||
ptr += sizeof(*tlv);
|
||||
|
||||
/* magic */
|
||||
tlv = ptr;
|
||||
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, 0);
|
||||
|
||||
ptr += sizeof(*tlv);
|
||||
|
||||
/* pattern info timeout */
|
||||
tlv = ptr;
|
||||
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, 0);
|
||||
|
||||
ptr += sizeof(*tlv);
|
||||
|
||||
/* ratelimit interval */
|
||||
tlv = ptr;
|
||||
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, sizeof(u32));
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv wow add pattern vdev_id %d pattern_id %d pattern_offset %d pattern_len %d\n",
|
||||
vdev_id, pattern_id, pattern_offset, pattern_len);
|
||||
|
||||
ath12k_dbg_dump(ar->ab, ATH12K_DBG_WMI, NULL, "wow pattern: ",
|
||||
bitmap->patternbuf, pattern_len);
|
||||
ath12k_dbg_dump(ar->ab, ATH12K_DBG_WMI, NULL, "wow bitmask: ",
|
||||
bitmap->bitmaskbuf, pattern_len);
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ADD_WAKE_PATTERN_CMDID);
|
||||
}
|
||||
|
||||
int ath12k_wmi_wow_del_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id)
|
||||
{
|
||||
struct wmi_wow_del_pattern_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_wow_del_pattern_cmd *)skb->data;
|
||||
cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_WOW_DEL_PATTERN_CMD,
|
||||
sizeof(*cmd));
|
||||
cmd->vdev_id = cpu_to_le32(vdev_id);
|
||||
cmd->pattern_id = cpu_to_le32(pattern_id);
|
||||
cmd->pattern_type = cpu_to_le32(WOW_BITMAP_PATTERN);
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv wow del pattern vdev_id %d pattern_id %d\n",
|
||||
vdev_id, pattern_id);
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_DEL_WAKE_PATTERN_CMDID);
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
ath12k_wmi_op_gen_config_pno_start(struct ath12k *ar, u32 vdev_id,
|
||||
struct wmi_pno_scan_req_arg *pno)
|
||||
{
|
||||
struct nlo_configured_params *nlo_list;
|
||||
size_t len, nlo_list_len, channel_list_len;
|
||||
struct wmi_wow_nlo_config_cmd *cmd;
|
||||
__le32 *channel_list;
|
||||
struct wmi_tlv *tlv;
|
||||
struct sk_buff *skb;
|
||||
void *ptr;
|
||||
u32 i;
|
||||
|
||||
len = sizeof(*cmd) +
|
||||
sizeof(*tlv) +
|
||||
/* TLV place holder for array of structures
|
||||
* nlo_configured_params(nlo_list)
|
||||
*/
|
||||
sizeof(*tlv);
|
||||
/* TLV place holder for array of uint32 channel_list */
|
||||
|
||||
channel_list_len = sizeof(u32) * pno->a_networks[0].channel_count;
|
||||
len += channel_list_len;
|
||||
|
||||
nlo_list_len = sizeof(*nlo_list) * pno->uc_networks_count;
|
||||
len += nlo_list_len;
|
||||
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
if (!skb)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ptr = skb->data;
|
||||
cmd = ptr;
|
||||
cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_NLO_CONFIG_CMD, sizeof(*cmd));
|
||||
|
||||
cmd->vdev_id = cpu_to_le32(pno->vdev_id);
|
||||
cmd->flags = cpu_to_le32(WMI_NLO_CONFIG_START | WMI_NLO_CONFIG_SSID_HIDE_EN);
|
||||
|
||||
/* current FW does not support min-max range for dwell time */
|
||||
cmd->active_dwell_time = cpu_to_le32(pno->active_max_time);
|
||||
cmd->passive_dwell_time = cpu_to_le32(pno->passive_max_time);
|
||||
|
||||
if (pno->do_passive_scan)
|
||||
cmd->flags |= cpu_to_le32(WMI_NLO_CONFIG_SCAN_PASSIVE);
|
||||
|
||||
cmd->fast_scan_period = cpu_to_le32(pno->fast_scan_period);
|
||||
cmd->slow_scan_period = cpu_to_le32(pno->slow_scan_period);
|
||||
cmd->fast_scan_max_cycles = cpu_to_le32(pno->fast_scan_max_cycles);
|
||||
cmd->delay_start_time = cpu_to_le32(pno->delay_start_time);
|
||||
|
||||
if (pno->enable_pno_scan_randomization) {
|
||||
cmd->flags |= cpu_to_le32(WMI_NLO_CONFIG_SPOOFED_MAC_IN_PROBE_REQ |
|
||||
WMI_NLO_CONFIG_RANDOM_SEQ_NO_IN_PROBE_REQ);
|
||||
ether_addr_copy(cmd->mac_addr.addr, pno->mac_addr);
|
||||
ether_addr_copy(cmd->mac_mask.addr, pno->mac_addr_mask);
|
||||
}
|
||||
|
||||
ptr += sizeof(*cmd);
|
||||
|
||||
/* nlo_configured_params(nlo_list) */
|
||||
cmd->no_of_ssids = cpu_to_le32(pno->uc_networks_count);
|
||||
tlv = ptr;
|
||||
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, nlo_list_len);
|
||||
|
||||
ptr += sizeof(*tlv);
|
||||
nlo_list = ptr;
|
||||
for (i = 0; i < pno->uc_networks_count; i++) {
|
||||
tlv = (struct wmi_tlv *)(&nlo_list[i].tlv_header);
|
||||
tlv->header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_ARRAY_BYTE,
|
||||
sizeof(*nlo_list));
|
||||
|
||||
nlo_list[i].ssid.valid = cpu_to_le32(1);
|
||||
nlo_list[i].ssid.ssid.ssid_len =
|
||||
cpu_to_le32(pno->a_networks[i].ssid.ssid_len);
|
||||
memcpy(nlo_list[i].ssid.ssid.ssid,
|
||||
pno->a_networks[i].ssid.ssid,
|
||||
le32_to_cpu(nlo_list[i].ssid.ssid.ssid_len));
|
||||
|
||||
if (pno->a_networks[i].rssi_threshold &&
|
||||
pno->a_networks[i].rssi_threshold > -300) {
|
||||
nlo_list[i].rssi_cond.valid = cpu_to_le32(1);
|
||||
nlo_list[i].rssi_cond.rssi =
|
||||
cpu_to_le32(pno->a_networks[i].rssi_threshold);
|
||||
}
|
||||
|
||||
nlo_list[i].bcast_nw_type.valid = cpu_to_le32(1);
|
||||
nlo_list[i].bcast_nw_type.bcast_nw_type =
|
||||
cpu_to_le32(pno->a_networks[i].bcast_nw_type);
|
||||
}
|
||||
|
||||
ptr += nlo_list_len;
|
||||
cmd->num_of_channels = cpu_to_le32(pno->a_networks[0].channel_count);
|
||||
tlv = ptr;
|
||||
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, channel_list_len);
|
||||
ptr += sizeof(*tlv);
|
||||
channel_list = ptr;
|
||||
|
||||
for (i = 0; i < pno->a_networks[0].channel_count; i++)
|
||||
channel_list[i] = cpu_to_le32(pno->a_networks[0].channels[i]);
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv start pno config vdev_id %d\n",
|
||||
vdev_id);
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
static struct sk_buff *ath12k_wmi_op_gen_config_pno_stop(struct ath12k *ar,
|
||||
u32 vdev_id)
|
||||
{
|
||||
struct wmi_wow_nlo_config_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
if (!skb)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
cmd = (struct wmi_wow_nlo_config_cmd *)skb->data;
|
||||
cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_NLO_CONFIG_CMD, len);
|
||||
|
||||
cmd->vdev_id = cpu_to_le32(vdev_id);
|
||||
cmd->flags = cpu_to_le32(WMI_NLO_CONFIG_STOP);
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
|
||||
"wmi tlv stop pno config vdev_id %d\n", vdev_id);
|
||||
return skb;
|
||||
}
|
||||
|
||||
int ath12k_wmi_wow_config_pno(struct ath12k *ar, u32 vdev_id,
|
||||
struct wmi_pno_scan_req_arg *pno_scan)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (pno_scan->enable)
|
||||
skb = ath12k_wmi_op_gen_config_pno_start(ar, vdev_id, pno_scan);
|
||||
else
|
||||
skb = ath12k_wmi_op_gen_config_pno_stop(ar, vdev_id);
|
||||
|
||||
if (IS_ERR_OR_NULL(skb))
|
||||
return -ENOMEM;
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
|
||||
}
|
||||
|
||||
static void ath12k_wmi_fill_ns_offload(struct ath12k *ar,
|
||||
struct wmi_arp_ns_offload_arg *offload,
|
||||
void **ptr,
|
||||
bool enable,
|
||||
bool ext)
|
||||
{
|
||||
struct wmi_ns_offload_params *ns;
|
||||
struct wmi_tlv *tlv;
|
||||
void *buf_ptr = *ptr;
|
||||
u32 ns_cnt, ns_ext_tuples;
|
||||
int i, max_offloads;
|
||||
|
||||
ns_cnt = offload->ipv6_count;
|
||||
|
||||
tlv = buf_ptr;
|
||||
|
||||
if (ext) {
|
||||
ns_ext_tuples = offload->ipv6_count - WMI_MAX_NS_OFFLOADS;
|
||||
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT,
|
||||
ns_ext_tuples * sizeof(*ns));
|
||||
i = WMI_MAX_NS_OFFLOADS;
|
||||
max_offloads = offload->ipv6_count;
|
||||
} else {
|
||||
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT,
|
||||
WMI_MAX_NS_OFFLOADS * sizeof(*ns));
|
||||
i = 0;
|
||||
max_offloads = WMI_MAX_NS_OFFLOADS;
|
||||
}
|
||||
|
||||
buf_ptr += sizeof(*tlv);
|
||||
|
||||
for (; i < max_offloads; i++) {
|
||||
ns = buf_ptr;
|
||||
ns->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_NS_OFFLOAD_TUPLE,
|
||||
sizeof(*ns));
|
||||
|
||||
if (enable) {
|
||||
if (i < ns_cnt)
|
||||
ns->flags |= cpu_to_le32(WMI_NSOL_FLAGS_VALID);
|
||||
|
||||
memcpy(ns->target_ipaddr[0], offload->ipv6_addr[i], 16);
|
||||
memcpy(ns->solicitation_ipaddr, offload->self_ipv6_addr[i], 16);
|
||||
|
||||
if (offload->ipv6_type[i])
|
||||
ns->flags |= cpu_to_le32(WMI_NSOL_FLAGS_IS_IPV6_ANYCAST);
|
||||
|
||||
memcpy(ns->target_mac.addr, offload->mac_addr, ETH_ALEN);
|
||||
|
||||
if (!is_zero_ether_addr(ns->target_mac.addr))
|
||||
ns->flags |= cpu_to_le32(WMI_NSOL_FLAGS_MAC_VALID);
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
|
||||
"wmi index %d ns_solicited %pI6 target %pI6",
|
||||
i, ns->solicitation_ipaddr,
|
||||
ns->target_ipaddr[0]);
|
||||
}
|
||||
|
||||
buf_ptr += sizeof(*ns);
|
||||
}
|
||||
|
||||
*ptr = buf_ptr;
|
||||
}
|
||||
|
||||
static void ath12k_wmi_fill_arp_offload(struct ath12k *ar,
|
||||
struct wmi_arp_ns_offload_arg *offload,
|
||||
void **ptr,
|
||||
bool enable)
|
||||
{
|
||||
struct wmi_arp_offload_params *arp;
|
||||
struct wmi_tlv *tlv;
|
||||
void *buf_ptr = *ptr;
|
||||
int i;
|
||||
|
||||
/* fill arp tuple */
|
||||
tlv = buf_ptr;
|
||||
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT,
|
||||
WMI_MAX_ARP_OFFLOADS * sizeof(*arp));
|
||||
buf_ptr += sizeof(*tlv);
|
||||
|
||||
for (i = 0; i < WMI_MAX_ARP_OFFLOADS; i++) {
|
||||
arp = buf_ptr;
|
||||
arp->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_ARP_OFFLOAD_TUPLE,
|
||||
sizeof(*arp));
|
||||
|
||||
if (enable && i < offload->ipv4_count) {
|
||||
/* Copy the target ip addr and flags */
|
||||
arp->flags = cpu_to_le32(WMI_ARPOL_FLAGS_VALID);
|
||||
memcpy(arp->target_ipaddr, offload->ipv4_addr[i], 4);
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi arp offload address %pI4",
|
||||
arp->target_ipaddr);
|
||||
}
|
||||
|
||||
buf_ptr += sizeof(*arp);
|
||||
}
|
||||
|
||||
*ptr = buf_ptr;
|
||||
}
|
||||
|
||||
int ath12k_wmi_arp_ns_offload(struct ath12k *ar,
|
||||
struct ath12k_vif *arvif,
|
||||
struct wmi_arp_ns_offload_arg *offload,
|
||||
bool enable)
|
||||
{
|
||||
struct wmi_set_arp_ns_offload_cmd *cmd;
|
||||
struct wmi_tlv *tlv;
|
||||
struct sk_buff *skb;
|
||||
void *buf_ptr;
|
||||
size_t len;
|
||||
u8 ns_cnt, ns_ext_tuples = 0;
|
||||
|
||||
ns_cnt = offload->ipv6_count;
|
||||
|
||||
len = sizeof(*cmd) +
|
||||
sizeof(*tlv) +
|
||||
WMI_MAX_NS_OFFLOADS * sizeof(struct wmi_ns_offload_params) +
|
||||
sizeof(*tlv) +
|
||||
WMI_MAX_ARP_OFFLOADS * sizeof(struct wmi_arp_offload_params);
|
||||
|
||||
if (ns_cnt > WMI_MAX_NS_OFFLOADS) {
|
||||
ns_ext_tuples = ns_cnt - WMI_MAX_NS_OFFLOADS;
|
||||
len += sizeof(*tlv) +
|
||||
ns_ext_tuples * sizeof(struct wmi_ns_offload_params);
|
||||
}
|
||||
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
buf_ptr = skb->data;
|
||||
cmd = buf_ptr;
|
||||
cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_SET_ARP_NS_OFFLOAD_CMD,
|
||||
sizeof(*cmd));
|
||||
cmd->flags = cpu_to_le32(0);
|
||||
cmd->vdev_id = cpu_to_le32(arvif->vdev_id);
|
||||
cmd->num_ns_ext_tuples = cpu_to_le32(ns_ext_tuples);
|
||||
|
||||
buf_ptr += sizeof(*cmd);
|
||||
|
||||
ath12k_wmi_fill_ns_offload(ar, offload, &buf_ptr, enable, 0);
|
||||
ath12k_wmi_fill_arp_offload(ar, offload, &buf_ptr, enable);
|
||||
|
||||
if (ns_ext_tuples)
|
||||
ath12k_wmi_fill_ns_offload(ar, offload, &buf_ptr, enable, 1);
|
||||
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_SET_ARP_NS_OFFLOAD_CMDID);
|
||||
}
|
||||
|
||||
int ath12k_wmi_gtk_rekey_offload(struct ath12k *ar,
|
||||
struct ath12k_vif *arvif, bool enable)
|
||||
{
|
||||
struct ath12k_rekey_data *rekey_data = &arvif->rekey_data;
|
||||
struct wmi_gtk_rekey_offload_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
__le64 replay_ctr;
|
||||
int len;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_gtk_rekey_offload_cmd *)skb->data;
|
||||
cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_GTK_OFFLOAD_CMD, sizeof(*cmd));
|
||||
cmd->vdev_id = cpu_to_le32(arvif->vdev_id);
|
||||
|
||||
if (enable) {
|
||||
cmd->flags = cpu_to_le32(GTK_OFFLOAD_ENABLE_OPCODE);
|
||||
|
||||
/* the length in rekey_data and cmd is equal */
|
||||
memcpy(cmd->kck, rekey_data->kck, sizeof(cmd->kck));
|
||||
memcpy(cmd->kek, rekey_data->kek, sizeof(cmd->kek));
|
||||
|
||||
replay_ctr = cpu_to_le64(rekey_data->replay_ctr);
|
||||
memcpy(cmd->replay_ctr, &replay_ctr,
|
||||
sizeof(replay_ctr));
|
||||
} else {
|
||||
cmd->flags = cpu_to_le32(GTK_OFFLOAD_DISABLE_OPCODE);
|
||||
}
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "offload gtk rekey vdev: %d %d\n",
|
||||
arvif->vdev_id, enable);
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);
|
||||
}
|
||||
|
||||
int ath12k_wmi_gtk_rekey_getinfo(struct ath12k *ar,
|
||||
struct ath12k_vif *arvif)
|
||||
{
|
||||
struct wmi_gtk_rekey_offload_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
int len;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_gtk_rekey_offload_cmd *)skb->data;
|
||||
cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_GTK_OFFLOAD_CMD, sizeof(*cmd));
|
||||
cmd->vdev_id = cpu_to_le32(arvif->vdev_id);
|
||||
cmd->flags = cpu_to_le32(GTK_OFFLOAD_REQUEST_STATUS_OPCODE);
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "get gtk rekey vdev_id: %d\n",
|
||||
arvif->vdev_id);
|
||||
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);
|
||||
}
|
||||
|
||||
int ath12k_wmi_sta_keepalive(struct ath12k *ar,
|
||||
const struct wmi_sta_keepalive_arg *arg)
|
||||
{
|
||||
struct wmi_sta_keepalive_arp_resp_params *arp;
|
||||
struct ath12k_wmi_pdev *wmi = ar->wmi;
|
||||
struct wmi_sta_keepalive_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*cmd) + sizeof(*arp);
|
||||
skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_sta_keepalive_cmd *)skb->data;
|
||||
cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_STA_KEEPALIVE_CMD, sizeof(*cmd));
|
||||
cmd->vdev_id = cpu_to_le32(arg->vdev_id);
|
||||
cmd->enabled = cpu_to_le32(arg->enabled);
|
||||
cmd->interval = cpu_to_le32(arg->interval);
|
||||
cmd->method = cpu_to_le32(arg->method);
|
||||
|
||||
arp = (struct wmi_sta_keepalive_arp_resp_params *)(cmd + 1);
|
||||
arp->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_STA_KEEPALVE_ARP_RESPONSE,
|
||||
sizeof(*arp));
|
||||
if (arg->method == WMI_STA_KEEPALIVE_METHOD_UNSOLICITED_ARP_RESPONSE ||
|
||||
arg->method == WMI_STA_KEEPALIVE_METHOD_GRATUITOUS_ARP_REQUEST) {
|
||||
arp->src_ip4_addr = cpu_to_le32(arg->src_ip4_addr);
|
||||
arp->dest_ip4_addr = cpu_to_le32(arg->dest_ip4_addr);
|
||||
ether_addr_copy(arp->dest_mac_addr.addr, arg->dest_mac_addr);
|
||||
}
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
|
||||
"wmi sta keepalive vdev %d enabled %d method %d interval %d\n",
|
||||
arg->vdev_id, arg->enabled, arg->method, arg->interval);
|
||||
|
||||
return ath12k_wmi_cmd_send(wmi, skb, WMI_STA_KEEPALIVE_CMDID);
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
struct ath12k_base;
|
||||
struct ath12k;
|
||||
struct ath12k_vif;
|
||||
|
||||
/* There is no signed version of __le32, so for a temporary solution come
|
||||
* up with our own version. The idea is from fs/ntfs/endian.h.
|
||||
@ -2293,6 +2294,13 @@ struct ath12k_wmi_host_mem_chunk_arg {
|
||||
u32 req_id;
|
||||
};
|
||||
|
||||
enum ath12k_peer_metadata_version {
|
||||
ATH12K_PEER_METADATA_V0,
|
||||
ATH12K_PEER_METADATA_V1,
|
||||
ATH12K_PEER_METADATA_V1A,
|
||||
ATH12K_PEER_METADATA_V1B
|
||||
};
|
||||
|
||||
struct ath12k_wmi_resource_config_arg {
|
||||
u32 num_vdevs;
|
||||
u32 num_peers;
|
||||
@ -2355,10 +2363,10 @@ struct ath12k_wmi_resource_config_arg {
|
||||
u32 sched_params;
|
||||
u32 twt_ap_pdev_count;
|
||||
u32 twt_ap_sta_count;
|
||||
bool is_reg_cc_ext_event_supported;
|
||||
u8 dp_peer_meta_data_ver;
|
||||
enum ath12k_peer_metadata_version peer_metadata_ver;
|
||||
u32 ema_max_vap_cnt;
|
||||
u32 ema_max_profile_period;
|
||||
bool is_reg_cc_ext_event_supported;
|
||||
};
|
||||
|
||||
struct ath12k_wmi_init_cmd_arg {
|
||||
@ -4902,6 +4910,556 @@ struct wmi_twt_disable_event {
|
||||
__le32 status;
|
||||
} __packed;
|
||||
|
||||
/* WOW structures */
|
||||
enum wmi_wow_wakeup_event {
|
||||
WOW_BMISS_EVENT = 0,
|
||||
WOW_BETTER_AP_EVENT,
|
||||
WOW_DEAUTH_RECVD_EVENT,
|
||||
WOW_MAGIC_PKT_RECVD_EVENT,
|
||||
WOW_GTK_ERR_EVENT,
|
||||
WOW_FOURWAY_HSHAKE_EVENT,
|
||||
WOW_EAPOL_RECVD_EVENT,
|
||||
WOW_NLO_DETECTED_EVENT,
|
||||
WOW_DISASSOC_RECVD_EVENT,
|
||||
WOW_PATTERN_MATCH_EVENT,
|
||||
WOW_CSA_IE_EVENT,
|
||||
WOW_PROBE_REQ_WPS_IE_EVENT,
|
||||
WOW_AUTH_REQ_EVENT,
|
||||
WOW_ASSOC_REQ_EVENT,
|
||||
WOW_HTT_EVENT,
|
||||
WOW_RA_MATCH_EVENT,
|
||||
WOW_HOST_AUTO_SHUTDOWN_EVENT,
|
||||
WOW_IOAC_MAGIC_EVENT,
|
||||
WOW_IOAC_SHORT_EVENT,
|
||||
WOW_IOAC_EXTEND_EVENT,
|
||||
WOW_IOAC_TIMER_EVENT,
|
||||
WOW_DFS_PHYERR_RADAR_EVENT,
|
||||
WOW_BEACON_EVENT,
|
||||
WOW_CLIENT_KICKOUT_EVENT,
|
||||
WOW_EVENT_MAX,
|
||||
};
|
||||
|
||||
enum wmi_wow_interface_cfg {
|
||||
WOW_IFACE_PAUSE_ENABLED,
|
||||
WOW_IFACE_PAUSE_DISABLED
|
||||
};
|
||||
|
||||
#define C2S(x) case x: return #x
|
||||
|
||||
static inline const char *wow_wakeup_event(enum wmi_wow_wakeup_event ev)
|
||||
{
|
||||
switch (ev) {
|
||||
C2S(WOW_BMISS_EVENT);
|
||||
C2S(WOW_BETTER_AP_EVENT);
|
||||
C2S(WOW_DEAUTH_RECVD_EVENT);
|
||||
C2S(WOW_MAGIC_PKT_RECVD_EVENT);
|
||||
C2S(WOW_GTK_ERR_EVENT);
|
||||
C2S(WOW_FOURWAY_HSHAKE_EVENT);
|
||||
C2S(WOW_EAPOL_RECVD_EVENT);
|
||||
C2S(WOW_NLO_DETECTED_EVENT);
|
||||
C2S(WOW_DISASSOC_RECVD_EVENT);
|
||||
C2S(WOW_PATTERN_MATCH_EVENT);
|
||||
C2S(WOW_CSA_IE_EVENT);
|
||||
C2S(WOW_PROBE_REQ_WPS_IE_EVENT);
|
||||
C2S(WOW_AUTH_REQ_EVENT);
|
||||
C2S(WOW_ASSOC_REQ_EVENT);
|
||||
C2S(WOW_HTT_EVENT);
|
||||
C2S(WOW_RA_MATCH_EVENT);
|
||||
C2S(WOW_HOST_AUTO_SHUTDOWN_EVENT);
|
||||
C2S(WOW_IOAC_MAGIC_EVENT);
|
||||
C2S(WOW_IOAC_SHORT_EVENT);
|
||||
C2S(WOW_IOAC_EXTEND_EVENT);
|
||||
C2S(WOW_IOAC_TIMER_EVENT);
|
||||
C2S(WOW_DFS_PHYERR_RADAR_EVENT);
|
||||
C2S(WOW_BEACON_EVENT);
|
||||
C2S(WOW_CLIENT_KICKOUT_EVENT);
|
||||
C2S(WOW_EVENT_MAX);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
enum wmi_wow_wake_reason {
|
||||
WOW_REASON_UNSPECIFIED = -1,
|
||||
WOW_REASON_NLOD = 0,
|
||||
WOW_REASON_AP_ASSOC_LOST,
|
||||
WOW_REASON_LOW_RSSI,
|
||||
WOW_REASON_DEAUTH_RECVD,
|
||||
WOW_REASON_DISASSOC_RECVD,
|
||||
WOW_REASON_GTK_HS_ERR,
|
||||
WOW_REASON_EAP_REQ,
|
||||
WOW_REASON_FOURWAY_HS_RECV,
|
||||
WOW_REASON_TIMER_INTR_RECV,
|
||||
WOW_REASON_PATTERN_MATCH_FOUND,
|
||||
WOW_REASON_RECV_MAGIC_PATTERN,
|
||||
WOW_REASON_P2P_DISC,
|
||||
WOW_REASON_WLAN_HB,
|
||||
WOW_REASON_CSA_EVENT,
|
||||
WOW_REASON_PROBE_REQ_WPS_IE_RECV,
|
||||
WOW_REASON_AUTH_REQ_RECV,
|
||||
WOW_REASON_ASSOC_REQ_RECV,
|
||||
WOW_REASON_HTT_EVENT,
|
||||
WOW_REASON_RA_MATCH,
|
||||
WOW_REASON_HOST_AUTO_SHUTDOWN,
|
||||
WOW_REASON_IOAC_MAGIC_EVENT,
|
||||
WOW_REASON_IOAC_SHORT_EVENT,
|
||||
WOW_REASON_IOAC_EXTEND_EVENT,
|
||||
WOW_REASON_IOAC_TIMER_EVENT,
|
||||
WOW_REASON_ROAM_HO,
|
||||
WOW_REASON_DFS_PHYERR_RADADR_EVENT,
|
||||
WOW_REASON_BEACON_RECV,
|
||||
WOW_REASON_CLIENT_KICKOUT_EVENT,
|
||||
WOW_REASON_PAGE_FAULT = 0x3a,
|
||||
WOW_REASON_DEBUG_TEST = 0xFF,
|
||||
};
|
||||
|
||||
static inline const char *wow_reason(enum wmi_wow_wake_reason reason)
|
||||
{
|
||||
switch (reason) {
|
||||
C2S(WOW_REASON_UNSPECIFIED);
|
||||
C2S(WOW_REASON_NLOD);
|
||||
C2S(WOW_REASON_AP_ASSOC_LOST);
|
||||
C2S(WOW_REASON_LOW_RSSI);
|
||||
C2S(WOW_REASON_DEAUTH_RECVD);
|
||||
C2S(WOW_REASON_DISASSOC_RECVD);
|
||||
C2S(WOW_REASON_GTK_HS_ERR);
|
||||
C2S(WOW_REASON_EAP_REQ);
|
||||
C2S(WOW_REASON_FOURWAY_HS_RECV);
|
||||
C2S(WOW_REASON_TIMER_INTR_RECV);
|
||||
C2S(WOW_REASON_PATTERN_MATCH_FOUND);
|
||||
C2S(WOW_REASON_RECV_MAGIC_PATTERN);
|
||||
C2S(WOW_REASON_P2P_DISC);
|
||||
C2S(WOW_REASON_WLAN_HB);
|
||||
C2S(WOW_REASON_CSA_EVENT);
|
||||
C2S(WOW_REASON_PROBE_REQ_WPS_IE_RECV);
|
||||
C2S(WOW_REASON_AUTH_REQ_RECV);
|
||||
C2S(WOW_REASON_ASSOC_REQ_RECV);
|
||||
C2S(WOW_REASON_HTT_EVENT);
|
||||
C2S(WOW_REASON_RA_MATCH);
|
||||
C2S(WOW_REASON_HOST_AUTO_SHUTDOWN);
|
||||
C2S(WOW_REASON_IOAC_MAGIC_EVENT);
|
||||
C2S(WOW_REASON_IOAC_SHORT_EVENT);
|
||||
C2S(WOW_REASON_IOAC_EXTEND_EVENT);
|
||||
C2S(WOW_REASON_IOAC_TIMER_EVENT);
|
||||
C2S(WOW_REASON_ROAM_HO);
|
||||
C2S(WOW_REASON_DFS_PHYERR_RADADR_EVENT);
|
||||
C2S(WOW_REASON_BEACON_RECV);
|
||||
C2S(WOW_REASON_CLIENT_KICKOUT_EVENT);
|
||||
C2S(WOW_REASON_PAGE_FAULT);
|
||||
C2S(WOW_REASON_DEBUG_TEST);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#undef C2S
|
||||
|
||||
#define WOW_DEFAULT_BITMAP_PATTERN_SIZE 148
|
||||
#define WOW_DEFAULT_BITMASK_SIZE 148
|
||||
|
||||
#define WOW_MIN_PATTERN_SIZE 1
|
||||
#define WOW_MAX_PATTERN_SIZE 148
|
||||
#define WOW_MAX_PKT_OFFSET 128
|
||||
#define WOW_HDR_LEN (sizeof(struct ieee80211_hdr_3addr) + \
|
||||
sizeof(struct rfc1042_hdr))
|
||||
#define WOW_MAX_REDUCE (WOW_HDR_LEN - sizeof(struct ethhdr) - \
|
||||
offsetof(struct ieee80211_hdr_3addr, addr1))
|
||||
|
||||
struct wmi_wow_bitmap_pattern_params {
|
||||
__le32 tlv_header;
|
||||
u8 patternbuf[WOW_DEFAULT_BITMAP_PATTERN_SIZE];
|
||||
u8 bitmaskbuf[WOW_DEFAULT_BITMASK_SIZE];
|
||||
__le32 pattern_offset;
|
||||
__le32 pattern_len;
|
||||
__le32 bitmask_len;
|
||||
__le32 pattern_id;
|
||||
} __packed;
|
||||
|
||||
struct wmi_wow_add_pattern_cmd {
|
||||
__le32 tlv_header;
|
||||
__le32 vdev_id;
|
||||
__le32 pattern_id;
|
||||
__le32 pattern_type;
|
||||
} __packed;
|
||||
|
||||
struct wmi_wow_del_pattern_cmd {
|
||||
__le32 tlv_header;
|
||||
__le32 vdev_id;
|
||||
__le32 pattern_id;
|
||||
__le32 pattern_type;
|
||||
} __packed;
|
||||
|
||||
enum wmi_tlv_pattern_type {
|
||||
WOW_PATTERN_MIN = 0,
|
||||
WOW_BITMAP_PATTERN = WOW_PATTERN_MIN,
|
||||
WOW_IPV4_SYNC_PATTERN,
|
||||
WOW_IPV6_SYNC_PATTERN,
|
||||
WOW_WILD_CARD_PATTERN,
|
||||
WOW_TIMER_PATTERN,
|
||||
WOW_MAGIC_PATTERN,
|
||||
WOW_IPV6_RA_PATTERN,
|
||||
WOW_IOAC_PKT_PATTERN,
|
||||
WOW_IOAC_TMR_PATTERN,
|
||||
WOW_PATTERN_MAX
|
||||
};
|
||||
|
||||
struct wmi_wow_add_del_event_cmd {
|
||||
__le32 tlv_header;
|
||||
__le32 vdev_id;
|
||||
__le32 is_add;
|
||||
__le32 event_bitmap;
|
||||
} __packed;
|
||||
|
||||
struct wmi_wow_enable_cmd {
|
||||
__le32 tlv_header;
|
||||
__le32 enable;
|
||||
__le32 pause_iface_config;
|
||||
__le32 flags;
|
||||
} __packed;
|
||||
|
||||
struct wmi_wow_host_wakeup_cmd {
|
||||
__le32 tlv_header;
|
||||
__le32 reserved;
|
||||
} __packed;
|
||||
|
||||
struct wmi_wow_ev_param {
|
||||
__le32 vdev_id;
|
||||
__le32 flag;
|
||||
__le32 wake_reason;
|
||||
__le32 data_len;
|
||||
} __packed;
|
||||
|
||||
struct wmi_wow_ev_pg_fault_param {
|
||||
__le32 len;
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
struct wmi_wow_ev_arg {
|
||||
enum wmi_wow_wake_reason wake_reason;
|
||||
};
|
||||
|
||||
#define WMI_PNO_MAX_SCHED_SCAN_PLANS 2
|
||||
#define WMI_PNO_MAX_SCHED_SCAN_PLAN_INT 7200
|
||||
#define WMI_PNO_MAX_SCHED_SCAN_PLAN_ITRNS 100
|
||||
#define WMI_PNO_MAX_NETW_CHANNELS 26
|
||||
#define WMI_PNO_MAX_NETW_CHANNELS_EX 60
|
||||
#define WMI_PNO_MAX_SUPP_NETWORKS WLAN_SCAN_PARAMS_MAX_SSID
|
||||
#define WMI_PNO_MAX_IE_LENGTH WLAN_SCAN_PARAMS_MAX_IE_LEN
|
||||
|
||||
/* size based of dot11 declaration without extra IEs as we will not carry those for PNO */
|
||||
#define WMI_PNO_MAX_PB_REQ_SIZE 450
|
||||
|
||||
#define WMI_PNO_24GHZ_DEFAULT_CH 1
|
||||
#define WMI_PNO_5GHZ_DEFAULT_CH 36
|
||||
|
||||
#define WMI_ACTIVE_MAX_CHANNEL_TIME 40
|
||||
#define WMI_PASSIVE_MAX_CHANNEL_TIME 110
|
||||
|
||||
/* SSID broadcast type */
|
||||
enum wmi_ssid_bcast_type {
|
||||
BCAST_UNKNOWN = 0,
|
||||
BCAST_NORMAL = 1,
|
||||
BCAST_HIDDEN = 2,
|
||||
};
|
||||
|
||||
#define WMI_NLO_MAX_SSIDS 16
|
||||
#define WMI_NLO_MAX_CHAN 48
|
||||
|
||||
#define WMI_NLO_CONFIG_STOP BIT(0)
|
||||
#define WMI_NLO_CONFIG_START BIT(1)
|
||||
#define WMI_NLO_CONFIG_RESET BIT(2)
|
||||
#define WMI_NLO_CONFIG_SLOW_SCAN BIT(4)
|
||||
#define WMI_NLO_CONFIG_FAST_SCAN BIT(5)
|
||||
#define WMI_NLO_CONFIG_SSID_HIDE_EN BIT(6)
|
||||
|
||||
/* This bit is used to indicate if EPNO or supplicant PNO is enabled.
|
||||
* Only one of them can be enabled at a given time
|
||||
*/
|
||||
#define WMI_NLO_CONFIG_ENLO BIT(7)
|
||||
#define WMI_NLO_CONFIG_SCAN_PASSIVE BIT(8)
|
||||
#define WMI_NLO_CONFIG_ENLO_RESET BIT(9)
|
||||
#define WMI_NLO_CONFIG_SPOOFED_MAC_IN_PROBE_REQ BIT(10)
|
||||
#define WMI_NLO_CONFIG_RANDOM_SEQ_NO_IN_PROBE_REQ BIT(11)
|
||||
#define WMI_NLO_CONFIG_ENABLE_IE_WHITELIST_IN_PROBE_REQ BIT(12)
|
||||
#define WMI_NLO_CONFIG_ENABLE_CNLO_RSSI_CONFIG BIT(13)
|
||||
|
||||
struct wmi_nlo_ssid_params {
|
||||
__le32 valid;
|
||||
struct ath12k_wmi_ssid_params ssid;
|
||||
} __packed;
|
||||
|
||||
struct wmi_nlo_enc_params {
|
||||
__le32 valid;
|
||||
__le32 enc_type;
|
||||
} __packed;
|
||||
|
||||
struct wmi_nlo_auth_params {
|
||||
__le32 valid;
|
||||
__le32 auth_type;
|
||||
} __packed;
|
||||
|
||||
struct wmi_nlo_bcast_nw_params {
|
||||
__le32 valid;
|
||||
__le32 bcast_nw_type;
|
||||
} __packed;
|
||||
|
||||
struct wmi_nlo_rssi_params {
|
||||
__le32 valid;
|
||||
__le32 rssi;
|
||||
} __packed;
|
||||
|
||||
struct nlo_configured_params {
|
||||
/* TLV tag and len;*/
|
||||
__le32 tlv_header;
|
||||
struct wmi_nlo_ssid_params ssid;
|
||||
struct wmi_nlo_enc_params enc_type;
|
||||
struct wmi_nlo_auth_params auth_type;
|
||||
struct wmi_nlo_rssi_params rssi_cond;
|
||||
|
||||
/* indicates if the SSID is hidden or not */
|
||||
struct wmi_nlo_bcast_nw_params bcast_nw_type;
|
||||
} __packed;
|
||||
|
||||
struct wmi_network_type_arg {
|
||||
struct cfg80211_ssid ssid;
|
||||
u32 authentication;
|
||||
u32 encryption;
|
||||
u32 bcast_nw_type;
|
||||
u8 channel_count;
|
||||
u16 channels[WMI_PNO_MAX_NETW_CHANNELS_EX];
|
||||
s32 rssi_threshold;
|
||||
};
|
||||
|
||||
struct wmi_pno_scan_req_arg {
|
||||
u8 enable;
|
||||
u8 vdev_id;
|
||||
u8 uc_networks_count;
|
||||
struct wmi_network_type_arg a_networks[WMI_PNO_MAX_SUPP_NETWORKS];
|
||||
u32 fast_scan_period;
|
||||
u32 slow_scan_period;
|
||||
u8 fast_scan_max_cycles;
|
||||
|
||||
bool do_passive_scan;
|
||||
|
||||
u32 delay_start_time;
|
||||
u32 active_min_time;
|
||||
u32 active_max_time;
|
||||
u32 passive_min_time;
|
||||
u32 passive_max_time;
|
||||
|
||||
/* mac address randomization attributes */
|
||||
u32 enable_pno_scan_randomization;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u8 mac_addr_mask[ETH_ALEN];
|
||||
};
|
||||
|
||||
struct wmi_wow_nlo_config_cmd {
|
||||
__le32 tlv_header;
|
||||
__le32 flags;
|
||||
__le32 vdev_id;
|
||||
__le32 fast_scan_max_cycles;
|
||||
__le32 active_dwell_time;
|
||||
__le32 passive_dwell_time;
|
||||
__le32 probe_bundle_size;
|
||||
|
||||
/* ART = IRT */
|
||||
__le32 rest_time;
|
||||
|
||||
/* max value that can be reached after scan_backoff_multiplier */
|
||||
__le32 max_rest_time;
|
||||
|
||||
__le32 scan_backoff_multiplier;
|
||||
__le32 fast_scan_period;
|
||||
|
||||
/* specific to windows */
|
||||
__le32 slow_scan_period;
|
||||
|
||||
__le32 no_of_ssids;
|
||||
|
||||
__le32 num_of_channels;
|
||||
|
||||
/* NLO scan start delay time in milliseconds */
|
||||
__le32 delay_start_time;
|
||||
|
||||
/* MAC Address to use in Probe Req as SA */
|
||||
struct ath12k_wmi_mac_addr_params mac_addr;
|
||||
|
||||
/* Mask on which MAC has to be randomized */
|
||||
struct ath12k_wmi_mac_addr_params mac_mask;
|
||||
|
||||
/* IE bitmap to use in Probe Req */
|
||||
__le32 ie_bitmap[8];
|
||||
|
||||
/* Number of vendor OUIs. In the TLV vendor_oui[] */
|
||||
__le32 num_vendor_oui;
|
||||
|
||||
/* Number of connected NLO band preferences */
|
||||
__le32 num_cnlo_band_pref;
|
||||
|
||||
/* The TLVs will follow.
|
||||
* nlo_configured_params nlo_list[];
|
||||
* u32 channel_list[num_of_channels];
|
||||
*/
|
||||
} __packed;
|
||||
|
||||
/* Definition of HW data filtering */
|
||||
enum hw_data_filter_type {
|
||||
WMI_HW_DATA_FILTER_DROP_NON_ARP_BC = BIT(0),
|
||||
WMI_HW_DATA_FILTER_DROP_NON_ICMPV6_MC = BIT(1),
|
||||
};
|
||||
|
||||
struct wmi_hw_data_filter_cmd {
|
||||
__le32 tlv_header;
|
||||
__le32 vdev_id;
|
||||
__le32 enable;
|
||||
__le32 hw_filter_bitmap;
|
||||
} __packed;
|
||||
|
||||
struct wmi_hw_data_filter_arg {
|
||||
u32 vdev_id;
|
||||
bool enable;
|
||||
u32 hw_filter_bitmap;
|
||||
};
|
||||
|
||||
#define WMI_IPV6_UC_TYPE 0
|
||||
#define WMI_IPV6_AC_TYPE 1
|
||||
|
||||
#define WMI_IPV6_MAX_COUNT 16
|
||||
#define WMI_IPV4_MAX_COUNT 2
|
||||
|
||||
struct wmi_arp_ns_offload_arg {
|
||||
u8 ipv4_addr[WMI_IPV4_MAX_COUNT][4];
|
||||
u32 ipv4_count;
|
||||
u32 ipv6_count;
|
||||
u8 ipv6_addr[WMI_IPV6_MAX_COUNT][16];
|
||||
u8 self_ipv6_addr[WMI_IPV6_MAX_COUNT][16];
|
||||
u8 ipv6_type[WMI_IPV6_MAX_COUNT];
|
||||
bool ipv6_valid[WMI_IPV6_MAX_COUNT];
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
#define WMI_MAX_NS_OFFLOADS 2
|
||||
#define WMI_MAX_ARP_OFFLOADS 2
|
||||
|
||||
#define WMI_ARPOL_FLAGS_VALID BIT(0)
|
||||
#define WMI_ARPOL_FLAGS_MAC_VALID BIT(1)
|
||||
#define WMI_ARPOL_FLAGS_REMOTE_IP_VALID BIT(2)
|
||||
|
||||
struct wmi_arp_offload_params {
|
||||
__le32 tlv_header;
|
||||
__le32 flags;
|
||||
u8 target_ipaddr[4];
|
||||
u8 remote_ipaddr[4];
|
||||
struct ath12k_wmi_mac_addr_params target_mac;
|
||||
} __packed;
|
||||
|
||||
#define WMI_NSOL_FLAGS_VALID BIT(0)
|
||||
#define WMI_NSOL_FLAGS_MAC_VALID BIT(1)
|
||||
#define WMI_NSOL_FLAGS_REMOTE_IP_VALID BIT(2)
|
||||
#define WMI_NSOL_FLAGS_IS_IPV6_ANYCAST BIT(3)
|
||||
|
||||
#define WMI_NSOL_MAX_TARGET_IPS 2
|
||||
|
||||
struct wmi_ns_offload_params {
|
||||
__le32 tlv_header;
|
||||
__le32 flags;
|
||||
u8 target_ipaddr[WMI_NSOL_MAX_TARGET_IPS][16];
|
||||
u8 solicitation_ipaddr[16];
|
||||
u8 remote_ipaddr[16];
|
||||
struct ath12k_wmi_mac_addr_params target_mac;
|
||||
} __packed;
|
||||
|
||||
struct wmi_set_arp_ns_offload_cmd {
|
||||
__le32 tlv_header;
|
||||
__le32 flags;
|
||||
__le32 vdev_id;
|
||||
__le32 num_ns_ext_tuples;
|
||||
/* The TLVs follow:
|
||||
* wmi_ns_offload_params ns[WMI_MAX_NS_OFFLOADS];
|
||||
* wmi_arp_offload_params arp[WMI_MAX_ARP_OFFLOADS];
|
||||
* wmi_ns_offload_params ns_ext[num_ns_ext_tuples];
|
||||
*/
|
||||
} __packed;
|
||||
|
||||
#define GTK_OFFLOAD_OPCODE_MASK 0xFF000000
|
||||
#define GTK_OFFLOAD_ENABLE_OPCODE 0x01000000
|
||||
#define GTK_OFFLOAD_DISABLE_OPCODE 0x02000000
|
||||
#define GTK_OFFLOAD_REQUEST_STATUS_OPCODE 0x04000000
|
||||
|
||||
#define GTK_OFFLOAD_KEK_BYTES 16
|
||||
#define GTK_OFFLOAD_KCK_BYTES 16
|
||||
#define GTK_REPLAY_COUNTER_BYTES 8
|
||||
#define WMI_MAX_KEY_LEN 32
|
||||
#define IGTK_PN_SIZE 6
|
||||
|
||||
struct wmi_gtk_offload_status_event {
|
||||
__le32 vdev_id;
|
||||
__le32 flags;
|
||||
__le32 refresh_cnt;
|
||||
__le64 replay_ctr;
|
||||
u8 igtk_key_index;
|
||||
u8 igtk_key_length;
|
||||
u8 igtk_key_rsc[IGTK_PN_SIZE];
|
||||
u8 igtk_key[WMI_MAX_KEY_LEN];
|
||||
u8 gtk_key_index;
|
||||
u8 gtk_key_length;
|
||||
u8 gtk_key_rsc[GTK_REPLAY_COUNTER_BYTES];
|
||||
u8 gtk_key[WMI_MAX_KEY_LEN];
|
||||
} __packed;
|
||||
|
||||
struct wmi_gtk_rekey_offload_cmd {
|
||||
__le32 tlv_header;
|
||||
__le32 vdev_id;
|
||||
__le32 flags;
|
||||
u8 kek[GTK_OFFLOAD_KEK_BYTES];
|
||||
u8 kck[GTK_OFFLOAD_KCK_BYTES];
|
||||
u8 replay_ctr[GTK_REPLAY_COUNTER_BYTES];
|
||||
} __packed;
|
||||
|
||||
struct wmi_sta_keepalive_cmd {
|
||||
__le32 tlv_header;
|
||||
__le32 vdev_id;
|
||||
__le32 enabled;
|
||||
|
||||
/* WMI_STA_KEEPALIVE_METHOD_ */
|
||||
__le32 method;
|
||||
|
||||
/* in seconds */
|
||||
__le32 interval;
|
||||
|
||||
/* following this structure is the TLV for struct
|
||||
* wmi_sta_keepalive_arp_resp_params
|
||||
*/
|
||||
} __packed;
|
||||
|
||||
struct wmi_sta_keepalive_arp_resp_params {
|
||||
__le32 tlv_header;
|
||||
__le32 src_ip4_addr;
|
||||
__le32 dest_ip4_addr;
|
||||
struct ath12k_wmi_mac_addr_params dest_mac_addr;
|
||||
} __packed;
|
||||
|
||||
struct wmi_sta_keepalive_arg {
|
||||
u32 vdev_id;
|
||||
u32 enabled;
|
||||
u32 method;
|
||||
u32 interval;
|
||||
u32 src_ip4_addr;
|
||||
u32 dest_ip4_addr;
|
||||
const u8 dest_mac_addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
enum wmi_sta_keepalive_method {
|
||||
WMI_STA_KEEPALIVE_METHOD_NULL_FRAME = 1,
|
||||
WMI_STA_KEEPALIVE_METHOD_UNSOLICITED_ARP_RESPONSE = 2,
|
||||
WMI_STA_KEEPALIVE_METHOD_ETHERNET_LOOPBACK = 3,
|
||||
WMI_STA_KEEPALIVE_METHOD_GRATUITOUS_ARP_REQUEST = 4,
|
||||
WMI_STA_KEEPALIVE_METHOD_MGMT_VENDOR_ACTION = 5,
|
||||
};
|
||||
|
||||
#define WMI_STA_KEEPALIVE_INTERVAL_DEFAULT 30
|
||||
#define WMI_STA_KEEPALIVE_INTERVAL_DISABLE 0
|
||||
|
||||
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,
|
||||
@ -5054,4 +5612,28 @@ ath12k_wmi_mac_phy_get_hw_link_id(const struct ath12k_wmi_mac_phy_caps_params *p
|
||||
WMI_CAPS_PARAMS_HW_LINK_ID);
|
||||
}
|
||||
|
||||
int ath12k_wmi_wow_host_wakeup_ind(struct ath12k *ar);
|
||||
int ath12k_wmi_wow_enable(struct ath12k *ar);
|
||||
int ath12k_wmi_wow_del_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id);
|
||||
int ath12k_wmi_wow_add_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id,
|
||||
const u8 *pattern, const u8 *mask,
|
||||
int pattern_len, int pattern_offset);
|
||||
int ath12k_wmi_wow_add_wakeup_event(struct ath12k *ar, u32 vdev_id,
|
||||
enum wmi_wow_wakeup_event event,
|
||||
u32 enable);
|
||||
int ath12k_wmi_wow_config_pno(struct ath12k *ar, u32 vdev_id,
|
||||
struct wmi_pno_scan_req_arg *pno_scan);
|
||||
int ath12k_wmi_hw_data_filter_cmd(struct ath12k *ar,
|
||||
struct wmi_hw_data_filter_arg *arg);
|
||||
int ath12k_wmi_arp_ns_offload(struct ath12k *ar,
|
||||
struct ath12k_vif *arvif,
|
||||
struct wmi_arp_ns_offload_arg *offload,
|
||||
bool enable);
|
||||
int ath12k_wmi_gtk_rekey_offload(struct ath12k *ar,
|
||||
struct ath12k_vif *arvif, bool enable);
|
||||
int ath12k_wmi_gtk_rekey_getinfo(struct ath12k *ar,
|
||||
struct ath12k_vif *arvif);
|
||||
int ath12k_wmi_sta_keepalive(struct ath12k *ar,
|
||||
const struct wmi_sta_keepalive_arg *arg);
|
||||
|
||||
#endif
|
||||
|
1026
drivers/net/wireless/ath/ath12k/wow.c
Normal file
1026
drivers/net/wireless/ath/ath12k/wow.c
Normal file
File diff suppressed because it is too large
Load Diff
62
drivers/net/wireless/ath/ath12k/wow.h
Normal file
62
drivers/net/wireless/ath/ath12k/wow.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH12K_WOW_H
|
||||
#define ATH12K_WOW_H
|
||||
|
||||
#define ATH12K_WOW_RETRY_NUM 10
|
||||
#define ATH12K_WOW_RETRY_WAIT_MS 200
|
||||
#define ATH12K_WOW_PATTERNS 22
|
||||
|
||||
struct ath12k_wow {
|
||||
u32 max_num_patterns;
|
||||
struct completion wakeup_completed;
|
||||
struct wiphy_wowlan_support wowlan_support;
|
||||
};
|
||||
|
||||
struct ath12k_pkt_pattern {
|
||||
u8 pattern[WOW_MAX_PATTERN_SIZE];
|
||||
u8 bytemask[WOW_MAX_PATTERN_SIZE];
|
||||
int pattern_len;
|
||||
int pkt_offset;
|
||||
};
|
||||
|
||||
struct rfc1042_hdr {
|
||||
u8 llc_dsap;
|
||||
u8 llc_ssap;
|
||||
u8 llc_ctrl;
|
||||
u8 snap_oui[3];
|
||||
__be16 eth_type;
|
||||
} __packed;
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
int ath12k_wow_init(struct ath12k *ar);
|
||||
int ath12k_wow_op_suspend(struct ieee80211_hw *hw,
|
||||
struct cfg80211_wowlan *wowlan);
|
||||
int ath12k_wow_op_resume(struct ieee80211_hw *hw);
|
||||
void ath12k_wow_op_set_wakeup(struct ieee80211_hw *hw, bool enabled);
|
||||
int ath12k_wow_enable(struct ath12k *ar);
|
||||
int ath12k_wow_wakeup(struct ath12k *ar);
|
||||
|
||||
#else
|
||||
|
||||
static inline int ath12k_wow_init(struct ath12k *ar)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ath12k_wow_enable(struct ath12k *ar)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ath12k_wow_wakeup(struct ath12k *ar)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
#endif /* ATH12K_WOW_H */
|
Loading…
x
Reference in New Issue
Block a user