mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 20:14:06 +02:00
ath.git patches for v6.16
ath12k: Enable AHB support for IPQ5332. Add monitor interface support to QCN9274. Add MLO support to WCN7850. Add 802.11d scan offload support to WCN7850. ath11k: Restore hibernation support In addition, perform the usual set of bug fixes and cleanups across all supported drivers. -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQ/mtSHzPUi16IfDEksFbugiYzLewUCaAJ2WAAKCRAsFbugiYzL exnBAQDcBNn9WWQnHOIo4YIY//8Rnw311troRh1V/NLNHTaMmAD9G8SCa8qbI/rs gOxcP5XeDmR3LwKuw4/7emXucX9W+ww= =mAEA -----END PGP SIGNATURE----- Merge tag 'ath-next-20250418' of git://git.kernel.org/pub/scm/linux/kernel/git/ath/ath into wireless-next Jeff Johnson says: ==================== ath.git patches for v6.16 ath12k: Enable AHB support for IPQ5332. Add monitor interface support to QCN9274. Add MLO support to WCN7850. Add 802.11d scan offload support to WCN7850. ath11k: Restore hibernation support In addition, perform the usual set of bug fixes and cleanups across all supported drivers. ==================== Change-Id: I6555e64d7434f3a5fed5faab25057be93106b18e Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
commit
9ceba431a3
|
|
@ -0,0 +1,315 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/wireless/qcom,ipq5332-wifi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Technologies ath12k wireless devices (AHB)
|
||||
|
||||
maintainers:
|
||||
- Jeff Johnson <jjohnson@kernel.org>
|
||||
|
||||
description:
|
||||
Qualcomm Technologies IEEE 802.11be AHB devices.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,ipq5332-wifi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: XO clock used for copy engine
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: xo
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: Fatal interrupt
|
||||
- description: Ready interrupt
|
||||
- description: Spawn acknowledge interrupt
|
||||
- description: Stop acknowledge interrupt
|
||||
- description: misc-pulse1 interrupt events
|
||||
- description: misc-latch interrupt events
|
||||
- description: sw exception interrupt events
|
||||
- description: interrupt event for ring CE0
|
||||
- description: interrupt event for ring CE1
|
||||
- description: interrupt event for ring CE2
|
||||
- description: interrupt event for ring CE3
|
||||
- description: interrupt event for ring CE4
|
||||
- description: interrupt event for ring CE5
|
||||
- description: interrupt event for ring CE6
|
||||
- description: interrupt event for ring CE7
|
||||
- description: interrupt event for ring CE8
|
||||
- description: interrupt event for ring CE9
|
||||
- description: interrupt event for ring CE10
|
||||
- description: interrupt event for ring CE11
|
||||
- description: interrupt event for ring host2wbm-desc-feed
|
||||
- description: interrupt event for ring host2reo-re-injection
|
||||
- description: interrupt event for ring host2reo-command
|
||||
- description: interrupt event for ring host2rxdma-monitor-ring1
|
||||
- description: interrupt event for ring reo2ost-exception
|
||||
- description: interrupt event for ring wbm2host-rx-release
|
||||
- description: interrupt event for ring reo2host-status
|
||||
- description: interrupt event for ring reo2host-destination-ring4
|
||||
- description: interrupt event for ring reo2host-destination-ring3
|
||||
- description: interrupt event for ring reo2host-destination-ring2
|
||||
- description: interrupt event for ring reo2host-destination-ring1
|
||||
- description: interrupt event for ring rxdma2host-monitor-destination-mac3
|
||||
- description: interrupt event for ring rxdma2host-monitor-destination-mac2
|
||||
- description: interrupt event for ring rxdma2host-monitor-destination-mac1
|
||||
- description: interrupt event for ring host2rxdma-host-buf-ring-mac3
|
||||
- description: interrupt event for ring host2rxdma-host-buf-ring-mac2
|
||||
- description: interrupt event for ring host2rxdma-host-buf-ring-mac1
|
||||
- description: interrupt event for ring host2tcl-input-ring4
|
||||
- description: interrupt event for ring host2tcl-input-ring3
|
||||
- description: interrupt event for ring host2tcl-input-ring2
|
||||
- description: interrupt event for ring host2tcl-input-ring1
|
||||
- description: interrupt event for ring wbm2host-tx-completions-ring4
|
||||
- description: interrupt event for ring wbm2host-tx-completions-ring3
|
||||
- description: interrupt event for ring wbm2host-tx-completions-ring2
|
||||
- description: interrupt event for ring wbm2host-tx-completions-ring1
|
||||
- description: interrupt event for ring host2tx-monitor-ring1
|
||||
- description: interrupt event for ring txmon2host-monitor-destination-mac3
|
||||
- description: interrupt event for ring txmon2host-monitor-destination-mac2
|
||||
- description: interrupt event for ring txmon2host-monitor-destination-mac1
|
||||
- description: interrupt event for umac-reset
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: fatal
|
||||
- const: ready
|
||||
- const: spawn
|
||||
- const: stop-ack
|
||||
- const: misc-pulse1
|
||||
- const: misc-latch
|
||||
- const: sw-exception
|
||||
- const: ce0
|
||||
- const: ce1
|
||||
- const: ce2
|
||||
- const: ce3
|
||||
- const: ce4
|
||||
- const: ce5
|
||||
- const: ce6
|
||||
- const: ce7
|
||||
- const: ce8
|
||||
- const: ce9
|
||||
- const: ce10
|
||||
- const: ce11
|
||||
- const: host2wbm-desc-feed
|
||||
- const: host2reo-re-injection
|
||||
- const: host2reo-command
|
||||
- const: host2rxdma-monitor-ring1
|
||||
- const: reo2ost-exception
|
||||
- const: wbm2host-rx-release
|
||||
- const: reo2host-status
|
||||
- const: reo2host-destination-ring4
|
||||
- const: reo2host-destination-ring3
|
||||
- const: reo2host-destination-ring2
|
||||
- const: reo2host-destination-ring1
|
||||
- const: rxdma2host-monitor-destination-mac3
|
||||
- const: rxdma2host-monitor-destination-mac2
|
||||
- const: rxdma2host-monitor-destination-mac1
|
||||
- const: host2rxdma-host-buf-ring-mac3
|
||||
- const: host2rxdma-host-buf-ring-mac2
|
||||
- const: host2rxdma-host-buf-ring-mac1
|
||||
- const: host2tcl-input-ring4
|
||||
- const: host2tcl-input-ring3
|
||||
- const: host2tcl-input-ring2
|
||||
- const: host2tcl-input-ring1
|
||||
- const: wbm2host-tx-completions-ring4
|
||||
- const: wbm2host-tx-completions-ring3
|
||||
- const: wbm2host-tx-completions-ring2
|
||||
- const: wbm2host-tx-completions-ring1
|
||||
- const: host2tx-monitor-ring1
|
||||
- const: txmon2host-monitor-destination-mac3
|
||||
- const: txmon2host-monitor-destination-mac2
|
||||
- const: txmon2host-monitor-destination-mac1
|
||||
- const: umac-reset
|
||||
|
||||
memory-region:
|
||||
description:
|
||||
Memory regions used by the ath12k firmware.
|
||||
items:
|
||||
- description: Q6 memory region
|
||||
- description: m3 dump memory region
|
||||
- description: Q6 caldata memory region
|
||||
- description: Multi Link Operation (MLO) Global memory region
|
||||
|
||||
memory-region-names:
|
||||
items:
|
||||
- const: q6-region
|
||||
- const: m3-dump
|
||||
- const: q6-caldb
|
||||
- const: mlo-global-mem
|
||||
|
||||
qcom,calibration-variant:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description:
|
||||
String to uniquely identify variant of the calibration data for designs
|
||||
with colliding bus and device ids
|
||||
|
||||
qcom,rproc:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
Phandle to the Qualcomm Hexagon DSP(q6 remote processor), which is utilized
|
||||
for offloading WiFi processing tasks, this q6 remote processor operates in
|
||||
conjunction with WiFi.
|
||||
|
||||
qcom,smem-states:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
description: States used by the AP to signal the remote processor
|
||||
items:
|
||||
- description: Shutdown WCSS pd
|
||||
- description: Stop WCSS pd
|
||||
- description: Spawn WCSS pd
|
||||
|
||||
qcom,smem-state-names:
|
||||
description:
|
||||
Names of the states used by the AP to signal the remote processor
|
||||
items:
|
||||
- const: shutdown
|
||||
- const: stop
|
||||
- const: spawn
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
- memory-region
|
||||
- memory-region-names
|
||||
- qcom,rproc
|
||||
- qcom,smem-states
|
||||
- qcom,smem-state-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/qcom,ipq5332-gcc.h>
|
||||
|
||||
wifi0: wifi@c000000 {
|
||||
compatible = "qcom,ipq5332-wifi";
|
||||
reg = <0x0c000000 0x1000000>;
|
||||
clocks = <&gcc GCC_XO_CLK>;
|
||||
clock-names = "xo";
|
||||
interrupts-extended = <&wcss_smp2p_in 8 IRQ_TYPE_NONE>,
|
||||
<&wcss_smp2p_in 9 IRQ_TYPE_NONE>,
|
||||
<&wcss_smp2p_in 12 IRQ_TYPE_NONE>,
|
||||
<&wcss_smp2p_in 11 IRQ_TYPE_NONE>,
|
||||
<&intc GIC_SPI 559 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 560 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 561 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 422 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 423 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 424 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 425 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 426 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 427 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 428 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 429 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 430 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 431 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 432 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 433 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 491 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 495 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 493 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 544 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 457 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 466 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 497 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 454 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 453 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 452 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 451 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 488 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 488 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 484 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 554 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 554 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 549 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 507 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 500 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 499 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 498 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 450 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 449 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 448 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 447 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 543 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 486 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 486 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 482 IRQ_TYPE_EDGE_RISING>,
|
||||
<&intc GIC_SPI 419 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-names = "fatal",
|
||||
"ready",
|
||||
"spawn",
|
||||
"stop-ack",
|
||||
"misc-pulse1",
|
||||
"misc-latch",
|
||||
"sw-exception",
|
||||
"ce0",
|
||||
"ce1",
|
||||
"ce2",
|
||||
"ce3",
|
||||
"ce4",
|
||||
"ce5",
|
||||
"ce6",
|
||||
"ce7",
|
||||
"ce8",
|
||||
"ce9",
|
||||
"ce10",
|
||||
"ce11",
|
||||
"host2wbm-desc-feed",
|
||||
"host2reo-re-injection",
|
||||
"host2reo-command",
|
||||
"host2rxdma-monitor-ring1",
|
||||
"reo2ost-exception",
|
||||
"wbm2host-rx-release",
|
||||
"reo2host-status",
|
||||
"reo2host-destination-ring4",
|
||||
"reo2host-destination-ring3",
|
||||
"reo2host-destination-ring2",
|
||||
"reo2host-destination-ring1",
|
||||
"rxdma2host-monitor-destination-mac3",
|
||||
"rxdma2host-monitor-destination-mac2",
|
||||
"rxdma2host-monitor-destination-mac1",
|
||||
"host2rxdma-host-buf-ring-mac3",
|
||||
"host2rxdma-host-buf-ring-mac2",
|
||||
"host2rxdma-host-buf-ring-mac1",
|
||||
"host2tcl-input-ring4",
|
||||
"host2tcl-input-ring3",
|
||||
"host2tcl-input-ring2",
|
||||
"host2tcl-input-ring1",
|
||||
"wbm2host-tx-completions-ring4",
|
||||
"wbm2host-tx-completions-ring3",
|
||||
"wbm2host-tx-completions-ring2",
|
||||
"wbm2host-tx-completions-ring1",
|
||||
"host2tx-monitor-ring1",
|
||||
"txmon2host-monitor-destination-mac3",
|
||||
"txmon2host-monitor-destination-mac2",
|
||||
"txmon2host-monitor-destination-mac1",
|
||||
"umac-reset";
|
||||
|
||||
memory-region = <&q6_region>, <&m3_dump>, <&q6_caldb>, <&mlo_mem>;
|
||||
memory-region-names = "q6-region", "m3-dump", "q6-caldb", "mlo-global-mem";
|
||||
qcom,calibration-variant = "RDP441_1";
|
||||
qcom,rproc = <&q6v5_wcss>;
|
||||
qcom,smem-states = <&wcss_smp2p_out 8>,
|
||||
<&wcss_smp2p_out 9>,
|
||||
<&wcss_smp2p_out 10>;
|
||||
qcom,smem-state-names = "shutdown",
|
||||
"stop",
|
||||
"spawn";
|
||||
};
|
||||
|
|
@ -497,7 +497,7 @@ static int ath10k_ahb_resource_init(struct ath10k *ar)
|
|||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "irq: %d\n", ar_ahb->irq);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "mem: 0x%pK mem_len: %lu gcc mem: 0x%pK tcsr_mem: 0x%pK\n",
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "mem: 0x%p mem_len: %lu gcc mem: 0x%p tcsr_mem: 0x%p\n",
|
||||
ar_ahb->mem, ar_ahb->mem_len,
|
||||
ar_ahb->gcc_mem, ar_ahb->tcsr_mem);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -349,7 +349,7 @@ static int ath10k_bmi_lz_data_large(struct ath10k *ar, const void *buffer, u32 l
|
|||
int ret;
|
||||
size_t buf_len;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BMI, "large bmi lz data buffer 0x%pK length %d\n",
|
||||
ath10k_dbg(ar, ATH10K_DBG_BMI, "large bmi lz data buffer 0x%p length %d\n",
|
||||
buffer, length);
|
||||
|
||||
if (ar->bmi.done_sent) {
|
||||
|
|
@ -395,7 +395,7 @@ int ath10k_bmi_lz_data(struct ath10k *ar, const void *buffer, u32 length)
|
|||
u32 txlen;
|
||||
int ret;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi lz data buffer 0x%pK length %d\n",
|
||||
ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi lz data buffer 0x%p length %d\n",
|
||||
buffer, length);
|
||||
|
||||
if (ar->bmi.done_sent) {
|
||||
|
|
@ -461,7 +461,7 @@ int ath10k_bmi_fast_download(struct ath10k *ar,
|
|||
int ret;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BMI,
|
||||
"bmi fast download address 0x%x buffer 0x%pK length %d\n",
|
||||
"bmi fast download address 0x%x buffer 0x%p length %d\n",
|
||||
address, buffer, length);
|
||||
|
||||
ret = ath10k_bmi_lz_stream_start(ar, address);
|
||||
|
|
|
|||
|
|
@ -1388,7 +1388,7 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar,
|
|||
ath10k_ce_src_ring_highmark_set(ar, ctrl_addr, nentries);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"boot init ce src ring id %d entries %d base_addr %pK\n",
|
||||
"boot init ce src ring id %d entries %d base_addr %p\n",
|
||||
ce_id, nentries, src_ring->base_addr_owner_space);
|
||||
|
||||
return 0;
|
||||
|
|
@ -1426,7 +1426,7 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar,
|
|||
ath10k_ce_dest_ring_highmark_set(ar, ctrl_addr, nentries);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"boot ce dest ring id %d entries %d base_addr %pK\n",
|
||||
"boot ce dest ring id %d entries %d base_addr %p\n",
|
||||
ce_id, nentries, dest_ring->base_addr_owner_space);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1200,7 +1200,7 @@ static int ath10k_download_fw(struct ath10k *ar)
|
|||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"boot uploading firmware image %pK len %d\n",
|
||||
"boot uploading firmware image %p len %d\n",
|
||||
data, data_len);
|
||||
|
||||
/* Check if device supports to download firmware via
|
||||
|
|
@ -1826,7 +1826,7 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
|
|||
|
||||
if (!ar->running_fw->fw_file.otp_data ||
|
||||
!ar->running_fw->fw_file.otp_len) {
|
||||
ath10k_warn(ar, "Not running otp, calibration will be incorrect (otp-data %pK otp_len %zd)!\n",
|
||||
ath10k_warn(ar, "Not running otp, calibration will be incorrect (otp-data %p otp_len %zd)!\n",
|
||||
ar->running_fw->fw_file.otp_data,
|
||||
ar->running_fw->fw_file.otp_len);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ static struct sk_buff *ath10k_htc_build_tx_ctrl_skb(void *ar)
|
|||
skb_cb = ATH10K_SKB_CB(skb);
|
||||
memset(skb_cb, 0, sizeof(*skb_cb));
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: skb %pK\n", __func__, skb);
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: skb %p\n", __func__, skb);
|
||||
return skb;
|
||||
}
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
|
|||
struct ath10k *ar = ep->htc->ar;
|
||||
struct ath10k_htc_hdr *hdr;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: ep %d skb %pK\n", __func__,
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: ep %d skb %p\n", __func__,
|
||||
ep->eid, skb);
|
||||
|
||||
/* A corner case where the copy completion is reaching to host but still
|
||||
|
|
@ -515,7 +515,7 @@ void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb)
|
|||
/* zero length packet with trailer data, just drop these */
|
||||
goto out;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTC, "htc rx completion ep %d skb %pK\n",
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTC, "htc rx completion ep %d skb %p\n",
|
||||
eid, skb);
|
||||
ep->ep_ops.ep_rx_complete(ar, skb);
|
||||
|
||||
|
|
|
|||
|
|
@ -1373,7 +1373,7 @@ static void ath10k_process_rx(struct ath10k *ar, struct sk_buff *skb)
|
|||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_DATA,
|
||||
"rx skb %pK len %u peer %pM %s %s sn %u %s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
|
||||
"rx skb %p len %u peer %pM %s %s sn %u %s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
|
||||
skb,
|
||||
skb->len,
|
||||
ieee80211_get_SA(hdr),
|
||||
|
|
|
|||
|
|
@ -875,7 +875,7 @@ static void ath10k_peer_map_cleanup(struct ath10k *ar, struct ath10k_peer *peer)
|
|||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) {
|
||||
if (ar->peer_map[i] == peer) {
|
||||
ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %pK idx %d)\n",
|
||||
ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %p idx %d)\n",
|
||||
peer->addr, peer, i);
|
||||
ar->peer_map[i] = NULL;
|
||||
}
|
||||
|
|
@ -4063,7 +4063,7 @@ static int ath10k_mac_tx(struct ath10k *ar,
|
|||
|
||||
if (!noque_offchan && info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
|
||||
if (!ath10k_mac_tx_frm_has_freq(ar)) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac queued offchannel skb %pK len %d\n",
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac queued offchannel skb %p len %d\n",
|
||||
skb, skb->len);
|
||||
|
||||
skb_queue_tail(&ar->offchan_tx_queue, skb);
|
||||
|
|
@ -4126,7 +4126,7 @@ void ath10k_offchan_tx_work(struct work_struct *work)
|
|||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac offchannel skb %pK len %d\n",
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac offchannel skb %p len %d\n",
|
||||
skb, skb->len);
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
|
|
@ -4181,7 +4181,7 @@ void ath10k_offchan_tx_work(struct work_struct *work)
|
|||
time_left =
|
||||
wait_for_completion_timeout(&ar->offchan_tx_completed, 3 * HZ);
|
||||
if (time_left == 0)
|
||||
ath10k_warn(ar, "timed out waiting for offchannel skb %pK, len: %d\n",
|
||||
ath10k_warn(ar, "timed out waiting for offchannel skb %p, len: %d\n",
|
||||
skb, skb->len);
|
||||
|
||||
if (!peer && tmp_peer_created) {
|
||||
|
|
@ -7604,7 +7604,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
|
|||
* Existing station deletion.
|
||||
*/
|
||||
ath10k_dbg(ar, ATH10K_DBG_STA,
|
||||
"mac vdev %d peer delete %pM sta %pK (sta gone)\n",
|
||||
"mac vdev %d peer delete %pM sta %p (sta gone)\n",
|
||||
arvif->vdev_id, sta->addr, sta);
|
||||
|
||||
if (sta->tdls) {
|
||||
|
|
@ -7631,7 +7631,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
|
|||
continue;
|
||||
|
||||
if (peer->sta == sta) {
|
||||
ath10k_warn(ar, "found sta peer %pM (ptr %pK id %d) entry on vdev %i after it was supposedly removed\n",
|
||||
ath10k_warn(ar, "found sta peer %pM (ptr %p id %d) entry on vdev %i after it was supposedly removed\n",
|
||||
sta->addr, peer, i, arvif->vdev_id);
|
||||
peer->sta = NULL;
|
||||
|
||||
|
|
@ -8811,7 +8811,7 @@ ath10k_mac_op_add_chanctx(struct ieee80211_hw *hw,
|
|||
struct ath10k *ar = hw->priv;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"mac chanctx add freq %u width %d ptr %pK\n",
|
||||
"mac chanctx add freq %u width %d ptr %p\n",
|
||||
ctx->def.chan->center_freq, ctx->def.width, ctx);
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
|
@ -8835,7 +8835,7 @@ ath10k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
|
|||
struct ath10k *ar = hw->priv;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"mac chanctx remove freq %u width %d ptr %pK\n",
|
||||
"mac chanctx remove freq %u width %d ptr %p\n",
|
||||
ctx->def.chan->center_freq, ctx->def.width, ctx);
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
|
@ -8900,7 +8900,7 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw,
|
|||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"mac chanctx change freq %u width %d ptr %pK changed %x\n",
|
||||
"mac chanctx change freq %u width %d ptr %p changed %x\n",
|
||||
ctx->def.chan->center_freq, ctx->def.width, ctx, changed);
|
||||
|
||||
/* This shouldn't really happen because channel switching should use
|
||||
|
|
@ -8959,7 +8959,7 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
|
|||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"mac chanctx assign ptr %pK vdev_id %i\n",
|
||||
"mac chanctx assign ptr %p vdev_id %i\n",
|
||||
ctx, arvif->vdev_id);
|
||||
|
||||
if (WARN_ON(arvif->is_started)) {
|
||||
|
|
@ -9039,7 +9039,7 @@ ath10k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
|||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"mac chanctx unassign ptr %pK vdev_id %i\n",
|
||||
"mac chanctx unassign ptr %p vdev_id %i\n",
|
||||
ctx, arvif->vdev_id);
|
||||
|
||||
WARN_ON(!arvif->is_started);
|
||||
|
|
|
|||
|
|
@ -3411,7 +3411,7 @@ static int ath10k_pci_claim(struct ath10k *ar)
|
|||
goto err_region;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot pci_mem 0x%pK\n", ar_pci->mem);
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot pci_mem 0x%p\n", ar_pci->mem);
|
||||
return 0;
|
||||
|
||||
err_region:
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id, struct sk_buff *skb)
|
|||
int ret;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
|
||||
"testmode event wmi cmd_id %d skb %pK skb->len %d\n",
|
||||
"testmode event wmi cmd_id %d skb %p skb->len %d\n",
|
||||
cmd_id, skb, skb->len);
|
||||
|
||||
ath10k_dbg_dump(ar, ATH10K_DBG_TESTMODE, NULL, "", skb->data, skb->len);
|
||||
|
|
@ -397,7 +397,7 @@ static int ath10k_tm_cmd_wmi(struct ath10k *ar, struct nlattr *tb[])
|
|||
cmd_id = nla_get_u32(tb[ATH10K_TM_ATTR_WMI_CMDID]);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
|
||||
"testmode cmd wmi cmd_id %d buf %pK buf_len %d\n",
|
||||
"testmode cmd wmi cmd_id %d buf %p buf_len %d\n",
|
||||
cmd_id, buf, buf_len);
|
||||
|
||||
ath10k_dbg_dump(ar, ATH10K_DBG_TESTMODE, NULL, "", buf, buf_len);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ static void ath10k_report_offchan_tx(struct ath10k *ar, struct sk_buff *skb)
|
|||
complete(&ar->offchan_tx_completed);
|
||||
ar->offchan_tx_skb = NULL; /* just for sanity */
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTT, "completed offchannel skb %pK\n", skb);
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTT, "completed offchannel skb %p\n", skb);
|
||||
out:
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ static void ath10k_usb_recv_complete(struct urb *urb)
|
|||
int status = 0;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_USB_BULK,
|
||||
"usb recv pipe %d stat %d len %d urb 0x%pK\n",
|
||||
"usb recv pipe %d stat %d len %d urb 0x%p\n",
|
||||
pipe->logical_pipe_num, urb->status, urb->actual_length,
|
||||
urb);
|
||||
|
||||
|
|
@ -230,7 +230,7 @@ static void ath10k_usb_post_recv_transfers(struct ath10k *ar,
|
|||
ath10k_usb_recv_complete, urb_context);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_USB_BULK,
|
||||
"usb bulk recv submit %d 0x%x ep 0x%2.2x len %d buf 0x%pK\n",
|
||||
"usb bulk recv submit %d 0x%x ep 0x%2.2x len %d buf 0x%p\n",
|
||||
recv_pipe->logical_pipe_num,
|
||||
recv_pipe->usb_pipe_handle, recv_pipe->ep_address,
|
||||
ATH10K_USB_RX_BUFFER_SIZE, urb_context->skb);
|
||||
|
|
|
|||
|
|
@ -2029,7 +2029,7 @@ ath10k_wmi_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
|
|||
ether_addr_copy(cmd->hdr.peer_macaddr.addr, ieee80211_get_DA(hdr));
|
||||
memcpy(cmd->buf, msdu->data, msdu->len);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi mgmt tx skb %pK len %d ftype %02x stype %02x\n",
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi mgmt tx skb %p len %d ftype %02x stype %02x\n",
|
||||
msdu, skb->len, fc & IEEE80211_FCTL_FTYPE,
|
||||
fc & IEEE80211_FCTL_STYPE);
|
||||
trace_ath10k_tx_hdr(ar, skb->data, skb->len);
|
||||
|
|
@ -2637,7 +2637,7 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
|
|||
status->boottime_ns = ktime_get_boottime_ns();
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MGMT,
|
||||
"event mgmt rx skb %pK len %d ftype %02x stype %02x\n",
|
||||
"event mgmt rx skb %p len %d ftype %02x stype %02x\n",
|
||||
skb, skb->len,
|
||||
fc & IEEE80211_FCTL_FTYPE, fc & IEEE80211_FCTL_STYPE);
|
||||
|
||||
|
|
|
|||
|
|
@ -413,7 +413,7 @@ static int ath11k_ahb_power_up(struct ath11k_base *ab)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void ath11k_ahb_power_down(struct ath11k_base *ab)
|
||||
static void ath11k_ahb_power_down(struct ath11k_base *ab, bool is_suspend)
|
||||
{
|
||||
struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
|
||||
|
||||
|
|
@ -1280,7 +1280,7 @@ static void ath11k_ahb_remove(struct platform_device *pdev)
|
|||
struct ath11k_base *ab = platform_get_drvdata(pdev);
|
||||
|
||||
if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
|
||||
ath11k_ahb_power_down(ab);
|
||||
ath11k_ahb_power_down(ab, false);
|
||||
ath11k_debugfs_soc_destroy(ab);
|
||||
ath11k_qmi_deinit_service(ab);
|
||||
goto qmi_fail;
|
||||
|
|
|
|||
|
|
@ -907,12 +907,51 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static inline struct ath11k_pdev *ath11k_core_get_single_pdev(struct ath11k_base *ab)
|
||||
{
|
||||
WARN_ON(!ab->hw_params.single_pdev_only);
|
||||
|
||||
return &ab->pdevs[0];
|
||||
}
|
||||
static const struct dmi_system_id ath11k_pm_quirk_table[] = {
|
||||
{
|
||||
.driver_data = (void *)ATH11K_PM_WOW,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "21J4"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.driver_data = (void *)ATH11K_PM_WOW,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "21K4"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.driver_data = (void *)ATH11K_PM_WOW,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "21K6"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.driver_data = (void *)ATH11K_PM_WOW,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "21K8"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.driver_data = (void *)ATH11K_PM_WOW,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "21KA"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.driver_data = (void *)ATH11K_PM_WOW,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "21F9"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
void ath11k_fw_stats_pdevs_free(struct list_head *head)
|
||||
{
|
||||
|
|
@ -972,23 +1011,33 @@ bool ath11k_core_coldboot_cal_support(struct ath11k_base *ab)
|
|||
return ab->hw_params.coldboot_cal_mm;
|
||||
}
|
||||
|
||||
int ath11k_core_suspend(struct ath11k_base *ab)
|
||||
/* 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 ath11k_core_continue_suspend_resume(struct ath11k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
struct ath11k_pdev *pdev;
|
||||
struct ath11k *ar;
|
||||
|
||||
if (!ab->hw_params.supports_suspend)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* so far single_pdev_only chips have supports_suspend as true
|
||||
* and only the first pdev is valid.
|
||||
* so pass 0 as a dummy pdev_id here.
|
||||
*/
|
||||
pdev = ath11k_core_get_single_pdev(ab);
|
||||
ar = pdev->ar;
|
||||
ar = ab->pdevs[0].ar;
|
||||
if (!ar || ar->state != ATH11K_STATE_OFF)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ath11k_core_suspend_wow(struct ath11k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ath11k_dp_rx_pktlog_stop(ab, true);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to stop dp rx (and timer) pktlog during suspend: %d\n",
|
||||
|
|
@ -996,7 +1045,10 @@ int ath11k_core_suspend(struct ath11k_base *ab)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = ath11k_mac_wait_tx_complete(ar);
|
||||
/* So far only single_pdev_only devices can reach here,
|
||||
* so it is valid to handle the first, and the only, pdev.
|
||||
*/
|
||||
ret = ath11k_mac_wait_tx_complete(ab->pdevs[0].ar);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to wait tx complete: %d\n", ret);
|
||||
return ret;
|
||||
|
|
@ -1029,25 +1081,147 @@ int ath11k_core_suspend(struct ath11k_base *ab)
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_core_suspend);
|
||||
|
||||
int ath11k_core_resume(struct ath11k_base *ab)
|
||||
static int ath11k_core_suspend_default(struct ath11k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
struct ath11k_pdev *pdev;
|
||||
struct ath11k *ar;
|
||||
|
||||
if (!ab->hw_params.supports_suspend)
|
||||
return -EOPNOTSUPP;
|
||||
ret = ath11k_dp_rx_pktlog_stop(ab, true);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to stop dp rx (and timer) pktlog during suspend: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* so far signle_pdev_only chips have supports_suspend as true
|
||||
* and only the first pdev is valid.
|
||||
/* So far only single_pdev_only devices can reach here,
|
||||
* so it is valid to handle the first, and the only, pdev.
|
||||
*/
|
||||
pdev = ath11k_core_get_single_pdev(ab);
|
||||
ar = pdev->ar;
|
||||
if (!ar || ar->state != ATH11K_STATE_OFF)
|
||||
ret = ath11k_mac_wait_tx_complete(ab->pdevs[0].ar);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to wait tx complete: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath11k_dp_rx_pktlog_stop(ab, false);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to stop dp rx pktlog during suspend: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ath11k_ce_stop_shadow_timers(ab);
|
||||
ath11k_dp_stop_shadow_timers(ab);
|
||||
|
||||
/* PM framework skips suspend_late/resume_early callbacks
|
||||
* if other devices report errors in their suspend callbacks.
|
||||
* However ath11k_core_resume() would still be called because
|
||||
* here we return success thus kernel put us on dpm_suspended_list.
|
||||
* Since we won't go through a power down/up cycle, there is
|
||||
* no chance to call complete(&ab->restart_completed) in
|
||||
* ath11k_core_restart(), making ath11k_core_resume() timeout.
|
||||
* So call it here to avoid this issue. This also works in case
|
||||
* no error happens thus suspend_late/resume_early get called,
|
||||
* because it will be reinitialized in ath11k_core_resume_early().
|
||||
*/
|
||||
complete(&ab->restart_completed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath11k_core_suspend(struct ath11k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ath11k_core_continue_suspend_resume(ab);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
if (ab->actual_pm_policy == ATH11K_PM_WOW)
|
||||
return ath11k_core_suspend_wow(ab);
|
||||
|
||||
return ath11k_core_suspend_default(ab);
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_core_suspend);
|
||||
|
||||
int ath11k_core_suspend_late(struct ath11k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ath11k_core_continue_suspend_resume(ab);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
if (ab->actual_pm_policy == ATH11K_PM_WOW)
|
||||
return 0;
|
||||
|
||||
ath11k_hif_irq_disable(ab);
|
||||
ath11k_hif_ce_irq_disable(ab);
|
||||
|
||||
ath11k_hif_power_down(ab, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_core_suspend_late);
|
||||
|
||||
int ath11k_core_resume_early(struct ath11k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ath11k_core_continue_suspend_resume(ab);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
if (ab->actual_pm_policy == ATH11K_PM_WOW)
|
||||
return 0;
|
||||
|
||||
reinit_completion(&ab->restart_completed);
|
||||
ret = ath11k_hif_power_up(ab);
|
||||
if (ret)
|
||||
ath11k_warn(ab, "failed to power up hif during resume: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_core_resume_early);
|
||||
|
||||
static int ath11k_core_resume_default(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k *ar;
|
||||
long time_left;
|
||||
int ret;
|
||||
|
||||
time_left = wait_for_completion_timeout(&ab->restart_completed,
|
||||
ATH11K_RESET_TIMEOUT_HZ);
|
||||
if (time_left == 0) {
|
||||
ath11k_warn(ab, "timeout while waiting for restart complete");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/* So far only single_pdev_only devices can reach here,
|
||||
* so it is valid to handle the first, and the only, pdev.
|
||||
*/
|
||||
ar = ab->pdevs[0].ar;
|
||||
if (ab->hw_params.current_cc_support &&
|
||||
ar->alpha2[0] != 0 && ar->alpha2[1] != 0) {
|
||||
ret = ath11k_reg_set_cc(ar);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to set country code during resume: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ath11k_dp_rx_pktlog_start(ab);
|
||||
if (ret)
|
||||
ath11k_warn(ab, "failed to start rx pktlog during resume: %d\n",
|
||||
ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath11k_core_resume_wow(struct ath11k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ath11k_hif_resume(ab);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to resume hif during resume: %d\n", ret);
|
||||
|
|
@ -1072,6 +1246,20 @@ int ath11k_core_resume(struct ath11k_base *ab)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath11k_core_resume(struct ath11k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ath11k_core_continue_suspend_resume(ab);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
if (ab->actual_pm_policy == ATH11K_PM_WOW)
|
||||
return ath11k_core_resume_wow(ab);
|
||||
|
||||
return ath11k_core_resume_default(ab);
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_core_resume);
|
||||
|
||||
static void ath11k_core_check_cc_code_bdfext(const struct dmi_header *hdr, void *data)
|
||||
|
|
@ -2050,6 +2238,7 @@ static int ath11k_core_reconfigure_on_crash(struct ath11k_base *ab)
|
|||
void ath11k_core_halt(struct ath11k *ar)
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct list_head *pos, *n;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
|
|
@ -2065,7 +2254,12 @@ void ath11k_core_halt(struct ath11k *ar)
|
|||
|
||||
rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL);
|
||||
synchronize_rcu();
|
||||
INIT_LIST_HEAD(&ar->arvifs);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
list_for_each_safe(pos, n, &ar->arvifs)
|
||||
list_del_init(pos);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
idr_init(&ar->txmgmt_idr);
|
||||
}
|
||||
|
||||
|
|
@ -2205,6 +2399,8 @@ static void ath11k_core_restart(struct work_struct *work)
|
|||
|
||||
if (!ab->is_reset)
|
||||
ath11k_core_post_reconfigure_recovery(ab);
|
||||
|
||||
complete(&ab->restart_completed);
|
||||
}
|
||||
|
||||
static void ath11k_core_reset(struct work_struct *work)
|
||||
|
|
@ -2275,7 +2471,7 @@ static void ath11k_core_reset(struct work_struct *work)
|
|||
ath11k_hif_irq_disable(ab);
|
||||
ath11k_hif_ce_irq_disable(ab);
|
||||
|
||||
ath11k_hif_power_down(ab);
|
||||
ath11k_hif_power_down(ab, false);
|
||||
ath11k_hif_power_up(ab);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset started\n");
|
||||
|
|
@ -2325,10 +2521,62 @@ int ath11k_core_pre_init(struct ath11k_base *ab)
|
|||
}
|
||||
EXPORT_SYMBOL(ath11k_core_pre_init);
|
||||
|
||||
int ath11k_core_init(struct ath11k_base *ab)
|
||||
static int ath11k_core_pm_notify(struct notifier_block *nb,
|
||||
unsigned long action, void *nouse)
|
||||
{
|
||||
struct ath11k_base *ab = container_of(nb, struct ath11k_base,
|
||||
pm_nb);
|
||||
|
||||
switch (action) {
|
||||
case PM_SUSPEND_PREPARE:
|
||||
ab->actual_pm_policy = ab->pm_policy;
|
||||
break;
|
||||
case PM_HIBERNATION_PREPARE:
|
||||
ab->actual_pm_policy = ATH11K_PM_DEFAULT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static int ath11k_core_pm_notifier_register(struct ath11k_base *ab)
|
||||
{
|
||||
ab->pm_nb.notifier_call = ath11k_core_pm_notify;
|
||||
return register_pm_notifier(&ab->pm_nb);
|
||||
}
|
||||
|
||||
void ath11k_core_pm_notifier_unregister(struct ath11k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = unregister_pm_notifier(&ab->pm_nb);
|
||||
if (ret)
|
||||
/* just warn here, there is nothing can be done in fail case */
|
||||
ath11k_warn(ab, "failed to unregister PM notifier %d\n", ret);
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_core_pm_notifier_unregister);
|
||||
|
||||
int ath11k_core_init(struct ath11k_base *ab)
|
||||
{
|
||||
const struct dmi_system_id *dmi_id;
|
||||
int ret;
|
||||
|
||||
dmi_id = dmi_first_match(ath11k_pm_quirk_table);
|
||||
if (dmi_id)
|
||||
ab->pm_policy = (kernel_ulong_t)dmi_id->driver_data;
|
||||
else
|
||||
ab->pm_policy = ATH11K_PM_DEFAULT;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_BOOT, "pm policy %u\n", ab->pm_policy);
|
||||
|
||||
ret = ath11k_core_pm_notifier_register(ab);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to register PM notifier: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath11k_core_soc_create(ab);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to create soc core: %d\n", ret);
|
||||
|
|
@ -2348,9 +2596,10 @@ void ath11k_core_deinit(struct ath11k_base *ab)
|
|||
|
||||
mutex_unlock(&ab->core_lock);
|
||||
|
||||
ath11k_hif_power_down(ab);
|
||||
ath11k_hif_power_down(ab, false);
|
||||
ath11k_mac_destroy(ab);
|
||||
ath11k_core_soc_destroy(ab);
|
||||
ath11k_core_pm_notifier_unregister(ab);
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_core_deinit);
|
||||
|
||||
|
|
@ -2401,6 +2650,7 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,
|
|||
timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0);
|
||||
init_completion(&ab->htc_suspend);
|
||||
init_completion(&ab->wow.wakeup_completed);
|
||||
init_completion(&ab->restart_completed);
|
||||
|
||||
ab->dev = dev;
|
||||
ab->hif.bus = bus;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/rhashtable.h>
|
||||
#include <linux/average.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/suspend.h>
|
||||
|
||||
#include "qmi.h"
|
||||
#include "htc.h"
|
||||
|
|
@ -892,6 +893,11 @@ struct ath11k_msi_config {
|
|||
u16 hw_rev;
|
||||
};
|
||||
|
||||
enum ath11k_pm_policy {
|
||||
ATH11K_PM_DEFAULT,
|
||||
ATH11K_PM_WOW,
|
||||
};
|
||||
|
||||
/* Master structure to hold the hw data which may be used in core module */
|
||||
struct ath11k_base {
|
||||
enum ath11k_hw_rev hw_rev;
|
||||
|
|
@ -1050,6 +1056,8 @@ struct ath11k_base {
|
|||
DECLARE_BITMAP(fw_features, ATH11K_FW_FEATURE_COUNT);
|
||||
} fw;
|
||||
|
||||
struct completion restart_completed;
|
||||
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
struct {
|
||||
u32 data_pos;
|
||||
|
|
@ -1058,6 +1066,10 @@ struct ath11k_base {
|
|||
} testmode;
|
||||
#endif
|
||||
|
||||
enum ath11k_pm_policy pm_policy;
|
||||
enum ath11k_pm_policy actual_pm_policy;
|
||||
struct notifier_block pm_nb;
|
||||
|
||||
/* must be last */
|
||||
u8 drv_priv[] __aligned(sizeof(void *));
|
||||
};
|
||||
|
|
@ -1249,8 +1261,10 @@ void ath11k_core_free_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd);
|
|||
int ath11k_core_check_dt(struct ath11k_base *ath11k);
|
||||
int ath11k_core_check_smbios(struct ath11k_base *ab);
|
||||
void ath11k_core_halt(struct ath11k *ar);
|
||||
int ath11k_core_resume_early(struct ath11k_base *ab);
|
||||
int ath11k_core_resume(struct ath11k_base *ab);
|
||||
int ath11k_core_suspend(struct ath11k_base *ab);
|
||||
int ath11k_core_suspend_late(struct ath11k_base *ab);
|
||||
void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab);
|
||||
bool ath11k_core_coldboot_cal_support(struct ath11k_base *ab);
|
||||
|
||||
|
|
@ -1322,4 +1336,6 @@ static inline const char *ath11k_bus_str(enum ath11k_bus bus)
|
|||
return "unknown";
|
||||
}
|
||||
|
||||
void ath11k_core_pm_notifier_unregister(struct ath11k_base *ab);
|
||||
|
||||
#endif /* _CORE_H_ */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _HIF_H_
|
||||
|
|
@ -18,7 +18,7 @@ struct ath11k_hif_ops {
|
|||
int (*start)(struct ath11k_base *ab);
|
||||
void (*stop)(struct ath11k_base *ab);
|
||||
int (*power_up)(struct ath11k_base *ab);
|
||||
void (*power_down)(struct ath11k_base *ab);
|
||||
void (*power_down)(struct ath11k_base *ab, bool is_suspend);
|
||||
int (*suspend)(struct ath11k_base *ab);
|
||||
int (*resume)(struct ath11k_base *ab);
|
||||
int (*map_service_to_pipe)(struct ath11k_base *ab, u16 service_id,
|
||||
|
|
@ -68,12 +68,18 @@ static inline void ath11k_hif_irq_disable(struct ath11k_base *ab)
|
|||
|
||||
static inline int ath11k_hif_power_up(struct ath11k_base *ab)
|
||||
{
|
||||
if (!ab->hif.ops->power_up)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return ab->hif.ops->power_up(ab);
|
||||
}
|
||||
|
||||
static inline void ath11k_hif_power_down(struct ath11k_base *ab)
|
||||
static inline void ath11k_hif_power_down(struct ath11k_base *ab, bool is_suspend)
|
||||
{
|
||||
ab->hif.ops->power_down(ab);
|
||||
if (!ab->hif.ops->power_down)
|
||||
return;
|
||||
|
||||
ab->hif.ops->power_down(ab, is_suspend);
|
||||
}
|
||||
|
||||
static inline int ath11k_hif_suspend(struct ath11k_base *ab)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/msi.h>
|
||||
|
|
@ -454,9 +454,17 @@ int ath11k_mhi_start(struct ath11k_pci *ab_pci)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ath11k_mhi_stop(struct ath11k_pci *ab_pci)
|
||||
void ath11k_mhi_stop(struct ath11k_pci *ab_pci, bool is_suspend)
|
||||
{
|
||||
mhi_power_down(ab_pci->mhi_ctrl, true);
|
||||
/* During suspend we need to use mhi_power_down_keep_dev()
|
||||
* workaround, otherwise ath11k_core_resume() will timeout
|
||||
* during resume.
|
||||
*/
|
||||
if (is_suspend)
|
||||
mhi_power_down_keep_dev(ab_pci->mhi_ctrl, true);
|
||||
else
|
||||
mhi_power_down(ab_pci->mhi_ctrl, true);
|
||||
|
||||
mhi_unprepare_after_power_down(ab_pci->mhi_ctrl);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* 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.
|
||||
* Copyright (c) 2022, 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef _ATH11K_MHI_H
|
||||
#define _ATH11K_MHI_H
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
#define MHICTRL_RESET_MASK 0x2
|
||||
|
||||
int ath11k_mhi_start(struct ath11k_pci *ar_pci);
|
||||
void ath11k_mhi_stop(struct ath11k_pci *ar_pci);
|
||||
void ath11k_mhi_stop(struct ath11k_pci *ar_pci, bool is_suspend);
|
||||
int ath11k_mhi_register(struct ath11k_pci *ar_pci);
|
||||
void ath11k_mhi_unregister(struct ath11k_pci *ar_pci);
|
||||
void ath11k_mhi_set_mhictrl_reset(struct ath11k_base *ab);
|
||||
|
|
|
|||
|
|
@ -821,7 +821,7 @@ static int ath11k_pci_power_up(struct ath11k_base *ab)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void ath11k_pci_power_down(struct ath11k_base *ab)
|
||||
static void ath11k_pci_power_down(struct ath11k_base *ab, bool is_suspend)
|
||||
{
|
||||
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
|
||||
|
||||
|
|
@ -832,7 +832,7 @@ static void ath11k_pci_power_down(struct ath11k_base *ab)
|
|||
|
||||
ath11k_pci_msi_disable(ab_pci);
|
||||
|
||||
ath11k_mhi_stop(ab_pci);
|
||||
ath11k_mhi_stop(ab_pci, is_suspend);
|
||||
clear_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags);
|
||||
ath11k_pci_sw_reset(ab_pci->ab, false);
|
||||
}
|
||||
|
|
@ -929,7 +929,7 @@ static int ath11k_pci_probe(struct pci_dev *pdev,
|
|||
{
|
||||
struct ath11k_base *ab;
|
||||
struct ath11k_pci *ab_pci;
|
||||
u32 soc_hw_version_major, soc_hw_version_minor, addr;
|
||||
u32 soc_hw_version_major, soc_hw_version_minor;
|
||||
int ret;
|
||||
u32 sub_version;
|
||||
|
||||
|
|
@ -955,8 +955,7 @@ static int ath11k_pci_probe(struct pci_dev *pdev,
|
|||
* from DT. If memory is reserved from DT for FW, ath11k driver need not
|
||||
* allocate memory.
|
||||
*/
|
||||
ret = of_property_read_u32(ab->dev->of_node, "memory-region", &addr);
|
||||
if (!ret)
|
||||
if (of_property_present(ab->dev->of_node, "memory-region"))
|
||||
set_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags);
|
||||
|
||||
ret = ath11k_pci_claim(ab_pci, pdev);
|
||||
|
|
@ -1161,9 +1160,10 @@ static void ath11k_pci_remove(struct pci_dev *pdev)
|
|||
ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);
|
||||
|
||||
if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
|
||||
ath11k_pci_power_down(ab);
|
||||
ath11k_pci_power_down(ab, false);
|
||||
ath11k_debugfs_soc_destroy(ab);
|
||||
ath11k_qmi_deinit_service(ab);
|
||||
ath11k_core_pm_notifier_unregister(ab);
|
||||
goto qmi_fail;
|
||||
}
|
||||
|
||||
|
|
@ -1192,7 +1192,7 @@ static void ath11k_pci_shutdown(struct pci_dev *pdev)
|
|||
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
|
||||
|
||||
ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);
|
||||
ath11k_pci_power_down(ab);
|
||||
ath11k_pci_power_down(ab, false);
|
||||
}
|
||||
|
||||
static __maybe_unused int ath11k_pci_pm_suspend(struct device *dev)
|
||||
|
|
@ -1229,9 +1229,39 @@ static __maybe_unused int ath11k_pci_pm_resume(struct device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(ath11k_pci_pm_ops,
|
||||
ath11k_pci_pm_suspend,
|
||||
ath11k_pci_pm_resume);
|
||||
static __maybe_unused int ath11k_pci_pm_suspend_late(struct device *dev)
|
||||
{
|
||||
struct ath11k_base *ab = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = ath11k_core_suspend_late(ab);
|
||||
if (ret)
|
||||
ath11k_warn(ab, "failed to late suspend core: %d\n", ret);
|
||||
|
||||
/* Similar to ath11k_pci_pm_suspend(), we return success here
|
||||
* even error happens, to allow system suspend/hibernation survive.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __maybe_unused int ath11k_pci_pm_resume_early(struct device *dev)
|
||||
{
|
||||
struct ath11k_base *ab = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = ath11k_core_resume_early(ab);
|
||||
if (ret)
|
||||
ath11k_warn(ab, "failed to early resume core: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops __maybe_unused ath11k_pci_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(ath11k_pci_pm_suspend,
|
||||
ath11k_pci_pm_resume)
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(ath11k_pci_pm_suspend_late,
|
||||
ath11k_pci_pm_resume_early)
|
||||
};
|
||||
|
||||
static struct pci_driver ath11k_pci_driver = {
|
||||
.name = "ath11k_pci",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/elf.h>
|
||||
|
|
@ -2887,7 +2887,7 @@ int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab)
|
|||
}
|
||||
|
||||
/* reset the firmware */
|
||||
ath11k_hif_power_down(ab);
|
||||
ath11k_hif_power_down(ab, false);
|
||||
ath11k_hif_power_up(ab);
|
||||
ath11k_dbg(ab, ATH11K_DBG_QMI, "exit wait for cold boot done\n");
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ static int ath11k_tm_process_event(struct ath11k_base *ab, u32 cmd_id,
|
|||
u32 pdev_id;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_TESTMODE,
|
||||
"event wmi cmd_id %d ftm event msg %pK datalen %d\n",
|
||||
"event wmi cmd_id %d ftm event msg %p datalen %d\n",
|
||||
cmd_id, ftm_msg, length);
|
||||
ath11k_dbg_dump(ab, ATH11K_DBG_TESTMODE, NULL, "", ftm_msg, length);
|
||||
pdev_id = DP_HW2SW_MACID(ftm_msg->seg_hdr.pdev_id);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,14 @@ config ATH12K
|
|||
|
||||
If you choose to build a module, it'll be called ath12k.
|
||||
|
||||
config ATH12K_AHB
|
||||
bool "QTI ath12k AHB support"
|
||||
depends on ATH12K && REMOTEPROC
|
||||
select QCOM_MDT_LOADER
|
||||
select QCOM_SCM
|
||||
help
|
||||
Enable support for Ath12k AHB bus chipsets, example IPQ5332.
|
||||
|
||||
config ATH12K_DEBUG
|
||||
bool "ath12k debugging"
|
||||
depends on ATH12K
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ ath12k-y += core.o \
|
|||
fw.o \
|
||||
p2p.o
|
||||
|
||||
ath12k-$(CONFIG_ATH12K_AHB) += ahb.o
|
||||
ath12k-$(CONFIG_ATH12K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o
|
||||
ath12k-$(CONFIG_ACPI) += acpi.o
|
||||
ath12k-$(CONFIG_ATH12K_TRACING) += trace.o
|
||||
|
|
|
|||
1156
drivers/net/wireless/ath/ath12k/ahb.c
Normal file
1156
drivers/net/wireless/ath/ath12k/ahb.c
Normal file
File diff suppressed because it is too large
Load Diff
80
drivers/net/wireless/ath/ath12k/ahb.h
Normal file
80
drivers/net/wireless/ath/ath12k/ahb.h
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2025, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef ATH12K_AHB_H
|
||||
#define ATH12K_AHB_H
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/remoteproc/qcom_rproc.h>
|
||||
#include "core.h"
|
||||
|
||||
#define ATH12K_AHB_RECOVERY_TIMEOUT (3 * HZ)
|
||||
|
||||
#define ATH12K_AHB_SMP2P_SMEM_MSG GENMASK(15, 0)
|
||||
#define ATH12K_AHB_SMP2P_SMEM_SEQ_NO GENMASK(31, 16)
|
||||
#define ATH12K_AHB_SMP2P_SMEM_VALUE_MASK 0xFFFFFFFF
|
||||
#define ATH12K_PCI_CE_WAKE_IRQ 2
|
||||
#define ATH12K_PCI_IRQ_CE0_OFFSET 3
|
||||
#define ATH12K_ROOTPD_READY_TIMEOUT (5 * HZ)
|
||||
#define ATH12K_RPROC_AFTER_POWERUP QCOM_SSR_AFTER_POWERUP
|
||||
#define ATH12K_AHB_FW_PREFIX "q6_fw"
|
||||
#define ATH12K_AHB_FW_SUFFIX ".mdt"
|
||||
#define ATH12K_AHB_FW2 "iu_fw.mdt"
|
||||
#define ATH12K_AHB_UPD_SWID 0x12
|
||||
#define ATH12K_USERPD_SPAWN_TIMEOUT (5 * HZ)
|
||||
#define ATH12K_USERPD_READY_TIMEOUT (10 * HZ)
|
||||
#define ATH12K_USERPD_STOP_TIMEOUT (5 * HZ)
|
||||
#define ATH12K_USERPD_ID_MASK GENMASK(9, 8)
|
||||
#define ATH12K_USERPD_FW_NAME_LEN 35
|
||||
|
||||
enum ath12k_ahb_smp2p_msg_id {
|
||||
ATH12K_AHB_POWER_SAVE_ENTER = 1,
|
||||
ATH12K_AHB_POWER_SAVE_EXIT,
|
||||
};
|
||||
|
||||
enum ath12k_ahb_userpd_irq {
|
||||
ATH12K_USERPD_SPAWN_IRQ,
|
||||
ATH12K_USERPD_READY_IRQ,
|
||||
ATH12K_USERPD_STOP_ACK_IRQ,
|
||||
ATH12K_USERPD_MAX_IRQ,
|
||||
};
|
||||
|
||||
struct ath12k_base;
|
||||
|
||||
struct ath12k_ahb {
|
||||
struct ath12k_base *ab;
|
||||
struct rproc *tgt_rproc;
|
||||
struct clk *xo_clk;
|
||||
struct completion rootpd_ready;
|
||||
struct notifier_block root_pd_nb;
|
||||
void *root_pd_notifier;
|
||||
struct qcom_smem_state *spawn_state;
|
||||
struct qcom_smem_state *stop_state;
|
||||
struct completion userpd_spawned;
|
||||
struct completion userpd_ready;
|
||||
struct completion userpd_stopped;
|
||||
u32 userpd_id;
|
||||
u32 spawn_bit;
|
||||
u32 stop_bit;
|
||||
int userpd_irq_num[ATH12K_USERPD_MAX_IRQ];
|
||||
};
|
||||
|
||||
static inline struct ath12k_ahb *ath12k_ab_to_ahb(struct ath12k_base *ab)
|
||||
{
|
||||
return (struct ath12k_ahb *)ab->drv_priv;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ATH12K_AHB
|
||||
int ath12k_ahb_init(void);
|
||||
void ath12k_ahb_exit(void);
|
||||
#else
|
||||
static inline int ath12k_ahb_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void ath12k_ahb_exit(void) {};
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -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-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "dp_rx.h"
|
||||
|
|
@ -219,6 +219,96 @@ const struct ce_attr ath12k_host_ce_config_wcn7850[] = {
|
|||
|
||||
};
|
||||
|
||||
const struct ce_attr ath12k_host_ce_config_ipq5332[] = {
|
||||
/* CE0: host->target HTC control and raw streams */
|
||||
{
|
||||
.flags = CE_ATTR_FLAGS,
|
||||
.src_nentries = 16,
|
||||
.src_sz_max = 2048,
|
||||
.dest_nentries = 0,
|
||||
},
|
||||
/* CE1: target->host HTT + HTC control */
|
||||
{
|
||||
.flags = CE_ATTR_FLAGS,
|
||||
.src_nentries = 0,
|
||||
.src_sz_max = 2048,
|
||||
.dest_nentries = 512,
|
||||
.recv_cb = ath12k_htc_rx_completion_handler,
|
||||
},
|
||||
/* CE2: target->host WMI */
|
||||
{
|
||||
.flags = CE_ATTR_FLAGS,
|
||||
.src_nentries = 0,
|
||||
.src_sz_max = 2048,
|
||||
.dest_nentries = 128,
|
||||
.recv_cb = ath12k_htc_rx_completion_handler,
|
||||
},
|
||||
/* CE3: host->target WMI */
|
||||
{
|
||||
.flags = CE_ATTR_FLAGS,
|
||||
.src_nentries = 32,
|
||||
.src_sz_max = 2048,
|
||||
.dest_nentries = 0,
|
||||
},
|
||||
/* CE4: host->target HTT */
|
||||
{
|
||||
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
|
||||
.src_nentries = 2048,
|
||||
.src_sz_max = 256,
|
||||
.dest_nentries = 0,
|
||||
},
|
||||
/* CE5: target -> host PKTLOG */
|
||||
{
|
||||
.flags = CE_ATTR_FLAGS,
|
||||
.src_nentries = 0,
|
||||
.src_sz_max = 2048,
|
||||
.dest_nentries = 512,
|
||||
.recv_cb = ath12k_dp_htt_htc_t2h_msg_handler,
|
||||
},
|
||||
/* CE6: Target autonomous HIF_memcpy */
|
||||
{
|
||||
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
|
||||
.src_nentries = 0,
|
||||
.src_sz_max = 0,
|
||||
.dest_nentries = 0,
|
||||
},
|
||||
/* CE7: CV Prefetch */
|
||||
{
|
||||
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
|
||||
.src_nentries = 0,
|
||||
.src_sz_max = 0,
|
||||
.dest_nentries = 0,
|
||||
},
|
||||
/* CE8: Target HIF memcpy (Generic HIF memcypy) */
|
||||
{
|
||||
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
|
||||
.src_nentries = 0,
|
||||
.src_sz_max = 0,
|
||||
.dest_nentries = 0,
|
||||
},
|
||||
/* CE9: WMI logging/CFR/Spectral/Radar */
|
||||
{
|
||||
.flags = CE_ATTR_FLAGS,
|
||||
.src_nentries = 0,
|
||||
.src_sz_max = 2048,
|
||||
.dest_nentries = 128,
|
||||
},
|
||||
/* CE10: Unused */
|
||||
{
|
||||
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
|
||||
.src_nentries = 0,
|
||||
.src_sz_max = 0,
|
||||
.dest_nentries = 0,
|
||||
},
|
||||
/* CE11: Unused */
|
||||
{
|
||||
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
|
||||
.src_nentries = 0,
|
||||
.src_sz_max = 0,
|
||||
.dest_nentries = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static int ath12k_ce_rx_buf_enqueue_pipe(struct ath12k_ce_pipe *pipe,
|
||||
struct sk_buff *skb, dma_addr_t paddr)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2022, 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH12K_CE_H
|
||||
|
|
@ -39,8 +39,8 @@
|
|||
#define PIPEDIR_INOUT_H2H 4 /* bidirectional, host to host */
|
||||
|
||||
/* CE address/mask */
|
||||
#define CE_HOST_IE_ADDRESS 0x00A1803C
|
||||
#define CE_HOST_IE_2_ADDRESS 0x00A18040
|
||||
#define CE_HOST_IE_ADDRESS 0x75804C
|
||||
#define CE_HOST_IE_2_ADDRESS 0x758050
|
||||
#define CE_HOST_IE_3_ADDRESS CE_HOST_IE_ADDRESS
|
||||
|
||||
#define CE_HOST_IE_3_SHIFT 0xC
|
||||
|
|
@ -76,6 +76,17 @@ struct ce_pipe_config {
|
|||
__le32 reserved;
|
||||
};
|
||||
|
||||
struct ce_ie_addr {
|
||||
u32 ie1_reg_addr;
|
||||
u32 ie2_reg_addr;
|
||||
u32 ie3_reg_addr;
|
||||
};
|
||||
|
||||
struct ce_remap {
|
||||
u32 base;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct ce_attr {
|
||||
/* CE_ATTR_* values */
|
||||
unsigned int flags;
|
||||
|
|
@ -164,6 +175,7 @@ struct ath12k_ce {
|
|||
|
||||
extern const struct ce_attr ath12k_host_ce_config_qcn9274[];
|
||||
extern const struct ce_attr ath12k_host_ce_config_wcn7850[];
|
||||
extern const struct ce_attr ath12k_host_ce_config_ipq5332[];
|
||||
|
||||
void ath12k_ce_cleanup_pipes(struct ath12k_base *ab);
|
||||
void ath12k_ce_rx_replenish_retry(struct timer_list *t);
|
||||
|
|
|
|||
|
|
@ -10,15 +10,18 @@
|
|||
#include <linux/firmware.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include "ahb.h"
|
||||
#include "core.h"
|
||||
#include "dp_tx.h"
|
||||
#include "dp_rx.h"
|
||||
#include "debug.h"
|
||||
#include "hif.h"
|
||||
#include "fw.h"
|
||||
#include "debugfs.h"
|
||||
#include "fw.h"
|
||||
#include "hif.h"
|
||||
#include "pci.h"
|
||||
#include "wow.h"
|
||||
|
||||
static int ahb_err, pci_err;
|
||||
unsigned int ath12k_debug_mask;
|
||||
module_param_named(debug_mask, ath12k_debug_mask, uint, 0644);
|
||||
MODULE_PARM_DESC(debug_mask, "Debugging mask");
|
||||
|
|
@ -612,9 +615,74 @@ u32 ath12k_core_get_max_num_tids(struct ath12k_base *ab)
|
|||
return TARGET_NUM_TIDS(SINGLE);
|
||||
}
|
||||
|
||||
struct reserved_mem *ath12k_core_get_reserved_mem(struct ath12k_base *ab,
|
||||
int index)
|
||||
{
|
||||
struct device *dev = ab->dev;
|
||||
struct reserved_mem *rmem;
|
||||
struct device_node *node;
|
||||
|
||||
node = of_parse_phandle(dev->of_node, "memory-region", index);
|
||||
if (!node) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
||||
"failed to parse memory-region for index %d\n", index);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rmem = of_reserved_mem_lookup(node);
|
||||
of_node_put(node);
|
||||
if (!rmem) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
||||
"unable to get memory-region for index %d\n", index);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rmem;
|
||||
}
|
||||
|
||||
static inline
|
||||
void ath12k_core_to_group_ref_get(struct ath12k_base *ab)
|
||||
{
|
||||
struct ath12k_hw_group *ag = ab->ag;
|
||||
|
||||
lockdep_assert_held(&ag->mutex);
|
||||
|
||||
if (ab->hw_group_ref) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "core already attached to group %d\n",
|
||||
ag->id);
|
||||
return;
|
||||
}
|
||||
|
||||
ab->hw_group_ref = true;
|
||||
ag->num_started++;
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "core attached to group %d, num_started %d\n",
|
||||
ag->id, ag->num_started);
|
||||
}
|
||||
|
||||
static inline
|
||||
void ath12k_core_to_group_ref_put(struct ath12k_base *ab)
|
||||
{
|
||||
struct ath12k_hw_group *ag = ab->ag;
|
||||
|
||||
lockdep_assert_held(&ag->mutex);
|
||||
|
||||
if (!ab->hw_group_ref) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "core already de-attached from group %d\n",
|
||||
ag->id);
|
||||
return;
|
||||
}
|
||||
|
||||
ab->hw_group_ref = false;
|
||||
ag->num_started--;
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "core de-attached from group %d, num_started %d\n",
|
||||
ag->id, ag->num_started);
|
||||
}
|
||||
|
||||
static void ath12k_core_stop(struct ath12k_base *ab)
|
||||
{
|
||||
ath12k_core_stopped(ab);
|
||||
ath12k_core_to_group_ref_put(ab);
|
||||
|
||||
if (!test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags))
|
||||
ath12k_qmi_firmware_stop(ab);
|
||||
|
|
@ -851,9 +919,8 @@ static int ath12k_core_start(struct ath12k_base *ab)
|
|||
|
||||
ath12k_acpi_set_dsm_func(ab);
|
||||
|
||||
if (!test_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags))
|
||||
/* Indicate the core start in the appropriate group */
|
||||
ath12k_core_started(ab);
|
||||
/* Indicate the core start in the appropriate group */
|
||||
ath12k_core_to_group_ref_get(ab);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
@ -891,6 +958,9 @@ static void ath12k_core_hw_group_stop(struct ath12k_hw_group *ag)
|
|||
ab = ag->ab[i];
|
||||
if (!ab)
|
||||
continue;
|
||||
|
||||
clear_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags);
|
||||
|
||||
ath12k_core_device_cleanup(ab);
|
||||
}
|
||||
|
||||
|
|
@ -1026,6 +1096,8 @@ static int ath12k_core_hw_group_start(struct ath12k_hw_group *ag)
|
|||
|
||||
mutex_lock(&ab->core_lock);
|
||||
|
||||
set_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags);
|
||||
|
||||
ret = ath12k_core_pdev_create(ab);
|
||||
if (ret) {
|
||||
ath12k_err(ab, "failed to create pdev core %d\n", ret);
|
||||
|
|
@ -1084,6 +1156,59 @@ bool ath12k_core_hw_group_start_ready(struct ath12k_hw_group *ag)
|
|||
return (ag->num_started == ag->num_devices);
|
||||
}
|
||||
|
||||
static void ath12k_fw_stats_pdevs_free(struct list_head *head)
|
||||
{
|
||||
struct ath12k_fw_stats_pdev *i, *tmp;
|
||||
|
||||
list_for_each_entry_safe(i, tmp, head, list) {
|
||||
list_del(&i->list);
|
||||
kfree(i);
|
||||
}
|
||||
}
|
||||
|
||||
void ath12k_fw_stats_bcn_free(struct list_head *head)
|
||||
{
|
||||
struct ath12k_fw_stats_bcn *i, *tmp;
|
||||
|
||||
list_for_each_entry_safe(i, tmp, head, list) {
|
||||
list_del(&i->list);
|
||||
kfree(i);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath12k_fw_stats_vdevs_free(struct list_head *head)
|
||||
{
|
||||
struct ath12k_fw_stats_vdev *i, *tmp;
|
||||
|
||||
list_for_each_entry_safe(i, tmp, head, list) {
|
||||
list_del(&i->list);
|
||||
kfree(i);
|
||||
}
|
||||
}
|
||||
|
||||
void ath12k_fw_stats_init(struct ath12k *ar)
|
||||
{
|
||||
INIT_LIST_HEAD(&ar->fw_stats.vdevs);
|
||||
INIT_LIST_HEAD(&ar->fw_stats.pdevs);
|
||||
INIT_LIST_HEAD(&ar->fw_stats.bcn);
|
||||
init_completion(&ar->fw_stats_complete);
|
||||
}
|
||||
|
||||
void ath12k_fw_stats_free(struct ath12k_fw_stats *stats)
|
||||
{
|
||||
ath12k_fw_stats_pdevs_free(&stats->pdevs);
|
||||
ath12k_fw_stats_vdevs_free(&stats->vdevs);
|
||||
ath12k_fw_stats_bcn_free(&stats->bcn);
|
||||
}
|
||||
|
||||
void ath12k_fw_stats_reset(struct ath12k *ar)
|
||||
{
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ar->fw_stats.fw_stats_done = false;
|
||||
ath12k_fw_stats_free(&ar->fw_stats);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
||||
static void ath12k_core_trigger_partner(struct ath12k_base *ab)
|
||||
{
|
||||
struct ath12k_hw_group *ag = ab->ag;
|
||||
|
|
@ -1246,6 +1371,7 @@ static void ath12k_rfkill_work(struct work_struct *work)
|
|||
|
||||
void ath12k_core_halt(struct ath12k *ar)
|
||||
{
|
||||
struct list_head *pos, *n;
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
|
||||
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
|
||||
|
|
@ -1258,10 +1384,16 @@ void ath12k_core_halt(struct ath12k *ar)
|
|||
cancel_delayed_work_sync(&ar->scan.timeout);
|
||||
cancel_work_sync(&ar->regd_update_work);
|
||||
cancel_work_sync(&ab->rfkill_work);
|
||||
cancel_work_sync(&ab->update_11d_work);
|
||||
|
||||
rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL);
|
||||
synchronize_rcu();
|
||||
INIT_LIST_HEAD(&ar->arvifs);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
list_for_each_safe(pos, n, &ar->arvifs)
|
||||
list_del_init(pos);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
idr_init(&ar->txmgmt_idr);
|
||||
}
|
||||
|
||||
|
|
@ -1285,14 +1417,28 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
|
|||
ah->state == ATH12K_HW_STATE_TM)
|
||||
continue;
|
||||
|
||||
wiphy_lock(ah->hw->wiphy);
|
||||
|
||||
/* If queue 0 is stopped, it is safe to assume that all
|
||||
* other queues are stopped by driver via
|
||||
* ieee80211_stop_queues() below. This means, there is
|
||||
* no need to stop it again and hence continue
|
||||
*/
|
||||
if (ieee80211_queue_stopped(ah->hw, 0)) {
|
||||
wiphy_unlock(ah->hw->wiphy);
|
||||
continue;
|
||||
}
|
||||
|
||||
ieee80211_stop_queues(ah->hw);
|
||||
|
||||
for (j = 0; j < ah->num_radio; j++) {
|
||||
ar = &ah->radio[j];
|
||||
|
||||
ath12k_mac_drain_tx(ar);
|
||||
ar->state_11d = ATH12K_11D_IDLE;
|
||||
complete(&ar->completed_11d_scan);
|
||||
complete(&ar->scan.started);
|
||||
complete(&ar->scan.completed);
|
||||
complete_all(&ar->scan.completed);
|
||||
complete(&ar->scan.on_channel);
|
||||
complete(&ar->peer_assoc_done);
|
||||
complete(&ar->peer_delete_done);
|
||||
|
|
@ -1306,13 +1452,47 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
|
|||
ath12k_mac_tx_mgmt_pending_free, ar);
|
||||
idr_destroy(&ar->txmgmt_idr);
|
||||
wake_up(&ar->txmgmt_empty_waitq);
|
||||
|
||||
ar->monitor_vdev_id = -1;
|
||||
ar->monitor_vdev_created = false;
|
||||
ar->monitor_started = false;
|
||||
}
|
||||
|
||||
wiphy_unlock(ah->hw->wiphy);
|
||||
}
|
||||
|
||||
wake_up(&ab->wmi_ab.tx_credits_wq);
|
||||
wake_up(&ab->peer_mapping_wq);
|
||||
}
|
||||
|
||||
static void ath12k_update_11d(struct work_struct *work)
|
||||
{
|
||||
struct ath12k_base *ab = container_of(work, struct ath12k_base, update_11d_work);
|
||||
struct ath12k *ar;
|
||||
struct ath12k_pdev *pdev;
|
||||
struct wmi_set_current_country_arg arg = {};
|
||||
int ret, i;
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
memcpy(&arg.alpha2, &ab->new_alpha2, 2);
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_WMI, "update 11d new cc %c%c\n",
|
||||
arg.alpha2[0], arg.alpha2[1]);
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
pdev = &ab->pdevs[i];
|
||||
ar = pdev->ar;
|
||||
|
||||
memcpy(&ar->alpha2, &arg.alpha2, 2);
|
||||
ret = ath12k_wmi_send_set_current_country_cmd(ar, &arg);
|
||||
if (ret)
|
||||
ath12k_warn(ar->ab,
|
||||
"pdev id %d failed set current country code: %d\n",
|
||||
i, ret);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
|
||||
{
|
||||
struct ath12k_hw_group *ag = ab->ag;
|
||||
|
|
@ -1386,19 +1566,30 @@ static void ath12k_core_restart(struct work_struct *work)
|
|||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset success\n");
|
||||
}
|
||||
|
||||
mutex_lock(&ag->mutex);
|
||||
|
||||
if (!ath12k_core_hw_group_start_ready(ag)) {
|
||||
mutex_unlock(&ag->mutex);
|
||||
goto exit_restart;
|
||||
}
|
||||
|
||||
for (i = 0; i < ag->num_hw; i++) {
|
||||
ah = ath12k_ag_to_ah(ab->ag, i);
|
||||
ah = ath12k_ag_to_ah(ag, i);
|
||||
ieee80211_restart_hw(ah->hw);
|
||||
}
|
||||
|
||||
mutex_unlock(&ag->mutex);
|
||||
}
|
||||
|
||||
exit_restart:
|
||||
complete(&ab->restart_completed);
|
||||
}
|
||||
|
||||
static void ath12k_core_reset(struct work_struct *work)
|
||||
{
|
||||
struct ath12k_base *ab = container_of(work, struct ath12k_base, reset_work);
|
||||
int reset_count, fail_cont_count;
|
||||
struct ath12k_hw_group *ag = ab->ag;
|
||||
int reset_count, fail_cont_count, i;
|
||||
long time_left;
|
||||
|
||||
if (!(test_bit(ATH12K_FLAG_QMI_FW_READY_COMPLETE, &ab->dev_flags))) {
|
||||
|
|
@ -1457,9 +1648,34 @@ static void ath12k_core_reset(struct work_struct *work)
|
|||
ath12k_hif_ce_irq_disable(ab);
|
||||
|
||||
ath12k_hif_power_down(ab, false);
|
||||
ath12k_hif_power_up(ab);
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset started\n");
|
||||
/* prepare for power up */
|
||||
ab->qmi.num_radios = U8_MAX;
|
||||
|
||||
mutex_lock(&ag->mutex);
|
||||
ath12k_core_to_group_ref_put(ab);
|
||||
|
||||
if (ag->num_started > 0) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
||||
"waiting for %d partner device(s) to reset\n",
|
||||
ag->num_started);
|
||||
mutex_unlock(&ag->mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Prepare MLO global memory region for power up */
|
||||
ath12k_qmi_reset_mlo_mem(ag);
|
||||
|
||||
for (i = 0; i < ag->num_devices; i++) {
|
||||
ab = ag->ab[i];
|
||||
if (!ab)
|
||||
continue;
|
||||
|
||||
ath12k_hif_power_up(ab);
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset started\n");
|
||||
}
|
||||
|
||||
mutex_unlock(&ag->mutex);
|
||||
}
|
||||
|
||||
int ath12k_core_pre_init(struct ath12k_base *ab)
|
||||
|
|
@ -1843,20 +2059,18 @@ void ath12k_core_hw_group_set_mlo_capable(struct ath12k_hw_group *ag)
|
|||
|
||||
lockdep_assert_held(&ag->mutex);
|
||||
|
||||
/* If more than one devices are grouped, then inter MLO
|
||||
* functionality can work still independent of whether internally
|
||||
* each device supports single_chip_mlo or not.
|
||||
* Only when there is one device, then disable for WCN chipsets
|
||||
* till the required driver implementation is in place.
|
||||
*/
|
||||
if (ag->num_devices == 1) {
|
||||
ab = ag->ab[0];
|
||||
|
||||
/* WCN chipsets does not advertise in firmware features
|
||||
* hence skip checking
|
||||
*/
|
||||
if (ab->hw_params->def_num_link)
|
||||
/* QCN9274 firmware uses firmware IE for MLO advertisement */
|
||||
if (ab->fw.fw_features_valid) {
|
||||
ag->mlo_capable =
|
||||
ath12k_fw_feature_supported(ab, ATH12K_FW_FEATURE_MLO);
|
||||
return;
|
||||
}
|
||||
|
||||
/* while WCN7850 firmware uses QMI single_chip_mlo_support bit */
|
||||
ag->mlo_capable = ab->single_chip_mlo_support;
|
||||
return;
|
||||
}
|
||||
|
||||
ag->mlo_capable = true;
|
||||
|
|
@ -1869,7 +2083,7 @@ void ath12k_core_hw_group_set_mlo_capable(struct ath12k_hw_group *ag)
|
|||
/* even if 1 device's firmware feature indicates MLO
|
||||
* unsupported, make MLO unsupported for the whole group
|
||||
*/
|
||||
if (!test_bit(ATH12K_FW_FEATURE_MLO, ab->fw.fw_features)) {
|
||||
if (!ath12k_fw_feature_supported(ab, ATH12K_FW_FEATURE_MLO)) {
|
||||
ag->mlo_capable = false;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1966,6 +2180,7 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
|
|||
INIT_WORK(&ab->reset_work, ath12k_core_reset);
|
||||
INIT_WORK(&ab->rfkill_work, ath12k_rfkill_work);
|
||||
INIT_WORK(&ab->dump_work, ath12k_coredump_upload);
|
||||
INIT_WORK(&ab->update_11d_work, ath12k_update_11d);
|
||||
|
||||
timer_setup(&ab->rx_replenish_retry, ath12k_ce_rx_replenish_retry, 0);
|
||||
init_completion(&ab->htc_suspend);
|
||||
|
|
@ -1975,6 +2190,7 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
|
|||
ab->dev = dev;
|
||||
ab->hif.bus = bus;
|
||||
ab->qmi.num_radios = U8_MAX;
|
||||
ab->single_chip_mlo_support = false;
|
||||
|
||||
/* Device index used to identify the devices in a group.
|
||||
*
|
||||
|
|
@ -1995,5 +2211,31 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("Core module for Qualcomm Atheros 802.11be wireless LAN cards.");
|
||||
static int ath12k_init(void)
|
||||
{
|
||||
ahb_err = ath12k_ahb_init();
|
||||
if (ahb_err)
|
||||
pr_warn("Failed to initialize ath12k AHB device: %d\n", ahb_err);
|
||||
|
||||
pci_err = ath12k_pci_init();
|
||||
if (pci_err)
|
||||
pr_warn("Failed to initialize ath12k PCI device: %d\n", pci_err);
|
||||
|
||||
/* If both failed, return one of the failures (arbitrary) */
|
||||
return ahb_err && pci_err ? ahb_err : 0;
|
||||
}
|
||||
|
||||
static void ath12k_exit(void)
|
||||
{
|
||||
if (!pci_err)
|
||||
ath12k_pci_exit();
|
||||
|
||||
if (!ahb_err)
|
||||
ath12k_ahb_exit();
|
||||
}
|
||||
|
||||
module_init(ath12k_init);
|
||||
module_exit(ath12k_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11be WLAN devices");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/dmi.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/of_reserved_mem.h>
|
||||
#include <linux/panic_notifier.h>
|
||||
#include <linux/average.h>
|
||||
#include "qmi.h"
|
||||
|
|
@ -147,7 +148,8 @@ struct ath12k_skb_rxcb {
|
|||
enum ath12k_hw_rev {
|
||||
ATH12K_HW_QCN9274_HW10,
|
||||
ATH12K_HW_QCN9274_HW20,
|
||||
ATH12K_HW_WCN7850_HW20
|
||||
ATH12K_HW_WCN7850_HW20,
|
||||
ATH12K_HW_IPQ5332_HW10,
|
||||
};
|
||||
|
||||
enum ath12k_firmware_mode {
|
||||
|
|
@ -160,6 +162,7 @@ enum ath12k_firmware_mode {
|
|||
|
||||
#define ATH12K_IRQ_NUM_MAX 57
|
||||
#define ATH12K_EXT_IRQ_NUM_MAX 16
|
||||
#define ATH12K_MAX_TCL_RING_NUM 3
|
||||
|
||||
struct ath12k_ext_irq_grp {
|
||||
struct ath12k_base *ab;
|
||||
|
|
@ -219,6 +222,12 @@ enum ath12k_scan_state {
|
|||
ATH12K_SCAN_ABORTING,
|
||||
};
|
||||
|
||||
enum ath12k_11d_state {
|
||||
ATH12K_11D_IDLE,
|
||||
ATH12K_11D_PREPARING,
|
||||
ATH12K_11D_RUNNING,
|
||||
};
|
||||
|
||||
enum ath12k_hw_group_flags {
|
||||
ATH12K_GROUP_FLAG_REGISTERED,
|
||||
ATH12K_GROUP_FLAG_UNREGISTER,
|
||||
|
|
@ -238,6 +247,7 @@ enum ath12k_dev_flags {
|
|||
ATH12K_FLAG_EXT_IRQ_ENABLED,
|
||||
ATH12K_FLAG_QMI_FW_READY_COMPLETE,
|
||||
ATH12K_FLAG_FTM_SEGMENTED,
|
||||
ATH12K_FLAG_FIXED_MEM_REGION,
|
||||
};
|
||||
|
||||
struct ath12k_tx_conf {
|
||||
|
|
@ -295,14 +305,18 @@ struct ath12k_link_vif {
|
|||
int txpower;
|
||||
bool rsnie_present;
|
||||
bool wpaie_present;
|
||||
struct ieee80211_chanctx_conf chanctx;
|
||||
u8 vdev_stats_id;
|
||||
u32 punct_bitmap;
|
||||
u8 link_id;
|
||||
struct ath12k_vif *ahvif;
|
||||
struct ath12k_rekey_data rekey_data;
|
||||
struct ath12k_link_stats link_stats;
|
||||
spinlock_t link_stats_lock; /* Protects updates to link_stats */
|
||||
|
||||
u8 current_cntdown_counter;
|
||||
|
||||
/* only used in station mode */
|
||||
bool is_sta_assoc_link;
|
||||
};
|
||||
|
||||
struct ath12k_vif {
|
||||
|
|
@ -364,6 +378,8 @@ struct ath12k_vif_iter {
|
|||
#define HAL_RX_MAX_NSS 8
|
||||
#define HAL_RX_MAX_NUM_LEGACY_RATES 12
|
||||
|
||||
#define ATH12K_SCAN_TIMEOUT_HZ (20 * HZ)
|
||||
|
||||
struct ath12k_rx_peer_rate_stats {
|
||||
u64 ht_mcs_count[HAL_RX_MAX_MCS_HT + 1];
|
||||
u64 vht_mcs_count[HAL_RX_MAX_MCS_VHT + 1];
|
||||
|
|
@ -519,6 +535,12 @@ struct ath12k_link_sta {
|
|||
u8 link_idx;
|
||||
};
|
||||
|
||||
struct ath12k_reoq_buf {
|
||||
void *vaddr;
|
||||
dma_addr_t paddr_aligned;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct ath12k_sta {
|
||||
struct ath12k_vif *ahvif;
|
||||
enum hal_pn_type pn_type;
|
||||
|
|
@ -531,13 +553,25 @@ struct ath12k_sta {
|
|||
u8 num_peer;
|
||||
|
||||
enum ieee80211_sta_state state;
|
||||
|
||||
struct ath12k_reoq_buf reoq_bufs[IEEE80211_NUM_TIDS + 1];
|
||||
};
|
||||
|
||||
#define ATH12K_MIN_5G_FREQ 4150
|
||||
#define ATH12K_MIN_6G_FREQ 5925
|
||||
#define ATH12K_MAX_6G_FREQ 7115
|
||||
#define ATH12K_HALF_20MHZ_BW 10
|
||||
#define ATH12K_2GHZ_MIN_CENTER 2412
|
||||
#define ATH12K_2GHZ_MAX_CENTER 2484
|
||||
#define ATH12K_5GHZ_MIN_CENTER 4900
|
||||
#define ATH12K_5GHZ_MAX_CENTER 5920
|
||||
#define ATH12K_6GHZ_MIN_CENTER 5935
|
||||
#define ATH12K_6GHZ_MAX_CENTER 7115
|
||||
#define ATH12K_MIN_2GHZ_FREQ (ATH12K_2GHZ_MIN_CENTER - ATH12K_HALF_20MHZ_BW - 1)
|
||||
#define ATH12K_MAX_2GHZ_FREQ (ATH12K_2GHZ_MAX_CENTER + ATH12K_HALF_20MHZ_BW + 1)
|
||||
#define ATH12K_MIN_5GHZ_FREQ (ATH12K_5GHZ_MIN_CENTER - ATH12K_HALF_20MHZ_BW)
|
||||
#define ATH12K_MAX_5GHZ_FREQ (ATH12K_5GHZ_MAX_CENTER + ATH12K_HALF_20MHZ_BW)
|
||||
#define ATH12K_MIN_6GHZ_FREQ (ATH12K_6GHZ_MIN_CENTER - ATH12K_HALF_20MHZ_BW)
|
||||
#define ATH12K_MAX_6GHZ_FREQ (ATH12K_6GHZ_MAX_CENTER + ATH12K_HALF_20MHZ_BW)
|
||||
#define ATH12K_NUM_CHANS 101
|
||||
#define ATH12K_MAX_5G_CHAN 173
|
||||
#define ATH12K_MAX_5GHZ_CHAN 173
|
||||
|
||||
enum ath12k_hw_state {
|
||||
ATH12K_HW_STATE_OFF,
|
||||
|
|
@ -728,7 +762,6 @@ struct ath12k {
|
|||
#endif
|
||||
|
||||
bool dfs_block_radar_events;
|
||||
bool monitor_conf_enabled;
|
||||
bool monitor_vdev_created;
|
||||
bool monitor_started;
|
||||
int monitor_vdev_id;
|
||||
|
|
@ -737,12 +770,20 @@ struct ath12k {
|
|||
|
||||
bool nlo_enabled;
|
||||
|
||||
/* Protected by wiphy::mtx lock. */
|
||||
u32 vdev_id_11d_scan;
|
||||
struct completion completed_11d_scan;
|
||||
enum ath12k_11d_state state_11d;
|
||||
u8 alpha2[REG_ALPHA2_LEN];
|
||||
bool regdom_set_by_user;
|
||||
|
||||
struct completion fw_stats_complete;
|
||||
|
||||
struct completion mlo_setup_done;
|
||||
u32 mlo_setup_status;
|
||||
u8 ftm_msgref;
|
||||
struct ath12k_fw_stats fw_stats;
|
||||
unsigned long last_tx_power_update;
|
||||
};
|
||||
|
||||
struct ath12k_hw {
|
||||
|
|
@ -852,6 +893,11 @@ struct ath12k_soc_dp_stats {
|
|||
struct ath12k_soc_dp_tx_err_stats tx_err;
|
||||
};
|
||||
|
||||
struct ath12k_reg_freq {
|
||||
u32 start_freq;
|
||||
u32 end_freq;
|
||||
};
|
||||
|
||||
struct ath12k_mlo_memory {
|
||||
struct target_mem_chunk chunk[ATH12K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01];
|
||||
int mlo_mem_size;
|
||||
|
|
@ -923,6 +969,10 @@ struct ath12k_base {
|
|||
void __iomem *mem;
|
||||
unsigned long mem_len;
|
||||
|
||||
void __iomem *mem_ce;
|
||||
u32 ce_remap_base_addr;
|
||||
bool ce_remap;
|
||||
|
||||
struct {
|
||||
enum ath12k_bus bus;
|
||||
const struct ath12k_hif_ops *ops;
|
||||
|
|
@ -1011,6 +1061,8 @@ struct ath12k_base {
|
|||
/* continuous recovery fail count */
|
||||
atomic_t fail_cont_count;
|
||||
unsigned long reset_fail_timeout;
|
||||
struct work_struct update_11d_work;
|
||||
u8 new_alpha2[2];
|
||||
struct {
|
||||
/* protected by data_lock */
|
||||
u32 fw_crash_counter;
|
||||
|
|
@ -1051,6 +1103,7 @@ struct ath12k_base {
|
|||
size_t m3_len;
|
||||
|
||||
DECLARE_BITMAP(fw_features, ATH12K_FW_FEATURE_COUNT);
|
||||
bool fw_features_valid;
|
||||
} fw;
|
||||
|
||||
const struct hal_rx_ops *hal_rx_ops;
|
||||
|
|
@ -1087,6 +1140,14 @@ struct ath12k_base {
|
|||
struct ath12k_wsi_info wsi_info;
|
||||
enum ath12k_firmware_mode fw_mode;
|
||||
struct ath12k_ftm_event_obj ftm_event_obj;
|
||||
bool hw_group_ref;
|
||||
|
||||
/* Denote whether MLO is possible within the device */
|
||||
bool single_chip_mlo_support;
|
||||
|
||||
struct ath12k_reg_freq reg_freq_2ghz;
|
||||
struct ath12k_reg_freq reg_freq_5ghz;
|
||||
struct ath12k_reg_freq reg_freq_6ghz;
|
||||
|
||||
/* must be last */
|
||||
u8 drv_priv[] __aligned(sizeof(void *));
|
||||
|
|
@ -1215,6 +1276,12 @@ u32 ath12k_core_get_max_peers_per_radio(struct ath12k_base *ab);
|
|||
u32 ath12k_core_get_max_num_tids(struct ath12k_base *ab);
|
||||
|
||||
void ath12k_core_hw_group_set_mlo_capable(struct ath12k_hw_group *ag);
|
||||
void ath12k_fw_stats_init(struct ath12k *ar);
|
||||
void ath12k_fw_stats_bcn_free(struct list_head *head);
|
||||
void ath12k_fw_stats_free(struct ath12k_fw_stats *stats);
|
||||
void ath12k_fw_stats_reset(struct ath12k *ar);
|
||||
struct reserved_mem *ath12k_core_get_reserved_mem(struct ath12k_base *ab,
|
||||
int index);
|
||||
|
||||
static inline const char *ath12k_scan_state_str(enum ath12k_scan_state state)
|
||||
{
|
||||
|
|
@ -1284,6 +1351,8 @@ static inline const char *ath12k_bus_str(enum ath12k_bus bus)
|
|||
switch (bus) {
|
||||
case ATH12K_BUS_PCI:
|
||||
return "pci";
|
||||
case ATH12K_BUS_AHB:
|
||||
return "ahb";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
|
|
@ -1333,20 +1402,6 @@ static inline struct ath12k_hw_group *ath12k_ab_to_ag(struct ath12k_base *ab)
|
|||
return ab->ag;
|
||||
}
|
||||
|
||||
static inline void ath12k_core_started(struct ath12k_base *ab)
|
||||
{
|
||||
lockdep_assert_held(&ab->ag->mutex);
|
||||
|
||||
ab->ag->num_started++;
|
||||
}
|
||||
|
||||
static inline void ath12k_core_stopped(struct ath12k_base *ab)
|
||||
{
|
||||
lockdep_assert_held(&ab->ag->mutex);
|
||||
|
||||
ab->ag->num_started--;
|
||||
}
|
||||
|
||||
static inline struct ath12k_base *ath12k_ag_to_ab(struct ath12k_hw_group *ag,
|
||||
u8 device_id)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -88,8 +88,8 @@ static int ath12k_get_tpc_ctl_mode_idx(struct wmi_tpc_stats_arg *tpc_stats,
|
|||
u32 chan_freq = le32_to_cpu(tpc_stats->tpc_config.chan_freq);
|
||||
u8 band;
|
||||
|
||||
band = ((chan_freq > ATH12K_MIN_6G_FREQ) ? NL80211_BAND_6GHZ :
|
||||
((chan_freq > ATH12K_MIN_5G_FREQ) ? NL80211_BAND_5GHZ :
|
||||
band = ((chan_freq > ATH12K_MIN_6GHZ_FREQ) ? NL80211_BAND_6GHZ :
|
||||
((chan_freq > ATH12K_MIN_5GHZ_FREQ) ? NL80211_BAND_5GHZ :
|
||||
NL80211_BAND_2GHZ));
|
||||
|
||||
if (band == NL80211_BAND_5GHZ || band == NL80211_BAND_6GHZ) {
|
||||
|
|
@ -833,6 +833,124 @@ static const struct file_operations fops_extd_rx_stats = {
|
|||
.open = simple_open,
|
||||
};
|
||||
|
||||
static int ath12k_open_link_stats(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct ath12k_vif *ahvif = inode->i_private;
|
||||
size_t len = 0, buf_len = (PAGE_SIZE * 2);
|
||||
struct ath12k_link_stats linkstat;
|
||||
struct ath12k_link_vif *arvif;
|
||||
unsigned long links_map;
|
||||
struct wiphy *wiphy;
|
||||
int link_id, i;
|
||||
char *buf;
|
||||
|
||||
if (!ahvif)
|
||||
return -EINVAL;
|
||||
|
||||
buf = kzalloc(buf_len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
wiphy = ahvif->ah->hw->wiphy;
|
||||
wiphy_lock(wiphy);
|
||||
|
||||
links_map = ahvif->links_map;
|
||||
for_each_set_bit(link_id, &links_map,
|
||||
IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
arvif = rcu_dereference_protected(ahvif->link[link_id],
|
||||
lockdep_is_held(&wiphy->mtx));
|
||||
|
||||
spin_lock_bh(&arvif->link_stats_lock);
|
||||
linkstat = arvif->link_stats;
|
||||
spin_unlock_bh(&arvif->link_stats_lock);
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"link[%d] Tx Unicast Frames Enqueued = %d\n",
|
||||
link_id, linkstat.tx_enqueued);
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"link[%d] Tx Broadcast Frames Enqueued = %d\n",
|
||||
link_id, linkstat.tx_bcast_mcast);
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"link[%d] Tx Frames Completed = %d\n",
|
||||
link_id, linkstat.tx_completed);
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"link[%d] Tx Frames Dropped = %d\n",
|
||||
link_id, linkstat.tx_dropped);
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"link[%d] Tx Frame descriptor Encap Type = ",
|
||||
link_id);
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
" raw:%d",
|
||||
linkstat.tx_encap_type[0]);
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
" native_wifi:%d",
|
||||
linkstat.tx_encap_type[1]);
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
" ethernet:%d",
|
||||
linkstat.tx_encap_type[2]);
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"\nlink[%d] Tx Frame descriptor Encrypt Type = ",
|
||||
link_id);
|
||||
|
||||
for (i = 0; i < HAL_ENCRYPT_TYPE_MAX; i++) {
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
" %d:%d", i,
|
||||
linkstat.tx_encrypt_type[i]);
|
||||
}
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"\nlink[%d] Tx Frame descriptor Type = buffer:%d extension:%d\n",
|
||||
link_id, linkstat.tx_desc_type[0],
|
||||
linkstat.tx_desc_type[1]);
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"------------------------------------------------------\n");
|
||||
}
|
||||
|
||||
wiphy_unlock(wiphy);
|
||||
|
||||
file->private_data = buf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath12k_release_link_stats(struct inode *inode, struct file *file)
|
||||
{
|
||||
kfree(file->private_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t ath12k_read_link_stats(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
const char *buf = file->private_data;
|
||||
size_t len = strlen(buf);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static const struct file_operations ath12k_fops_link_stats = {
|
||||
.open = ath12k_open_link_stats,
|
||||
.release = ath12k_release_link_stats,
|
||||
.read = ath12k_read_link_stats,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
void ath12k_debugfs_op_vif_add(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
|
||||
|
||||
debugfs_create_file("link_stats", 0400, vif->debugfs_dir, ahvif,
|
||||
&ath12k_fops_link_stats);
|
||||
}
|
||||
|
||||
void ath12k_debugfs_soc_create(struct ath12k_base *ab)
|
||||
{
|
||||
bool dput_needed;
|
||||
|
|
@ -870,102 +988,6 @@ void ath12k_debugfs_soc_destroy(struct ath12k_base *ab)
|
|||
*/
|
||||
}
|
||||
|
||||
static void ath12k_fw_stats_pdevs_free(struct list_head *head)
|
||||
{
|
||||
struct ath12k_fw_stats_pdev *i, *tmp;
|
||||
|
||||
list_for_each_entry_safe(i, tmp, head, list) {
|
||||
list_del(&i->list);
|
||||
kfree(i);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath12k_fw_stats_bcn_free(struct list_head *head)
|
||||
{
|
||||
struct ath12k_fw_stats_bcn *i, *tmp;
|
||||
|
||||
list_for_each_entry_safe(i, tmp, head, list) {
|
||||
list_del(&i->list);
|
||||
kfree(i);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath12k_fw_stats_vdevs_free(struct list_head *head)
|
||||
{
|
||||
struct ath12k_fw_stats_vdev *i, *tmp;
|
||||
|
||||
list_for_each_entry_safe(i, tmp, head, list) {
|
||||
list_del(&i->list);
|
||||
kfree(i);
|
||||
}
|
||||
}
|
||||
|
||||
void ath12k_debugfs_fw_stats_reset(struct ath12k *ar)
|
||||
{
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ar->fw_stats.fw_stats_done = false;
|
||||
ath12k_fw_stats_vdevs_free(&ar->fw_stats.vdevs);
|
||||
ath12k_fw_stats_bcn_free(&ar->fw_stats.bcn);
|
||||
ath12k_fw_stats_pdevs_free(&ar->fw_stats.pdevs);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
||||
static int ath12k_debugfs_fw_stats_request(struct ath12k *ar,
|
||||
struct ath12k_fw_stats_req_params *param)
|
||||
{
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
unsigned long timeout, time_left;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
|
||||
|
||||
/* FW stats can get split when exceeding the stats data buffer limit.
|
||||
* In that case, since there is no end marking for the back-to-back
|
||||
* received 'update stats' event, we keep a 3 seconds timeout in case,
|
||||
* fw_stats_done is not marked yet
|
||||
*/
|
||||
timeout = jiffies + msecs_to_jiffies(3 * 1000);
|
||||
|
||||
ath12k_debugfs_fw_stats_reset(ar);
|
||||
|
||||
reinit_completion(&ar->fw_stats_complete);
|
||||
|
||||
ret = ath12k_wmi_send_stats_request_cmd(ar, param->stats_id,
|
||||
param->vdev_id, param->pdev_id);
|
||||
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "could not request fw stats (%d)\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
time_left = wait_for_completion_timeout(&ar->fw_stats_complete,
|
||||
1 * HZ);
|
||||
/* If the wait timed out, return -ETIMEDOUT */
|
||||
if (!time_left)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
/* Firmware sends WMI_UPDATE_STATS_EVENTID back-to-back
|
||||
* when stats data buffer limit is reached. fw_stats_complete
|
||||
* is completed once host receives first event from firmware, but
|
||||
* still end might not be marked in the TLV.
|
||||
* Below loop is to confirm that firmware completed sending all the event
|
||||
* and fw_stats_done is marked true when end is marked in the TLV
|
||||
*/
|
||||
for (;;) {
|
||||
if (time_after(jiffies, timeout))
|
||||
break;
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
if (ar->fw_stats.fw_stats_done) {
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
break;
|
||||
}
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ath12k_debugfs_fw_stats_process(struct ath12k *ar,
|
||||
struct ath12k_fw_stats *stats)
|
||||
|
|
@ -1022,10 +1044,6 @@ ath12k_debugfs_fw_stats_process(struct ath12k *ar,
|
|||
num_bcn = 0;
|
||||
}
|
||||
}
|
||||
if (stats->stats_id == WMI_REQUEST_PDEV_STAT) {
|
||||
list_splice_tail_init(&stats->pdevs, &ar->fw_stats.pdevs);
|
||||
ar->fw_stats.fw_stats_done = true;
|
||||
}
|
||||
}
|
||||
|
||||
static int ath12k_open_vdev_stats(struct inode *inode, struct file *file)
|
||||
|
|
@ -1052,7 +1070,7 @@ static int ath12k_open_vdev_stats(struct inode *inode, struct file *file)
|
|||
param.vdev_id = 0;
|
||||
param.stats_id = WMI_REQUEST_VDEV_STAT;
|
||||
|
||||
ret = ath12k_debugfs_fw_stats_request(ar, ¶m);
|
||||
ret = ath12k_mac_get_fw_stats(ar, ¶m);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to request fw vdev stats: %d\n", ret);
|
||||
return ret;
|
||||
|
|
@ -1117,7 +1135,7 @@ static int ath12k_open_bcn_stats(struct inode *inode, struct file *file)
|
|||
continue;
|
||||
|
||||
param.vdev_id = arvif->vdev_id;
|
||||
ret = ath12k_debugfs_fw_stats_request(ar, ¶m);
|
||||
ret = ath12k_mac_get_fw_stats(ar, ¶m);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to request fw bcn stats: %d\n", ret);
|
||||
return ret;
|
||||
|
|
@ -1184,7 +1202,7 @@ static int ath12k_open_pdev_stats(struct inode *inode, struct file *file)
|
|||
param.vdev_id = 0;
|
||||
param.stats_id = WMI_REQUEST_PDEV_STAT;
|
||||
|
||||
ret = ath12k_debugfs_fw_stats_request(ar, ¶m);
|
||||
ret = ath12k_mac_get_fw_stats(ar, ¶m);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to request fw pdev stats: %d\n", ret);
|
||||
return ret;
|
||||
|
|
@ -1239,11 +1257,7 @@ void ath12k_debugfs_fw_stats_register(struct ath12k *ar)
|
|||
debugfs_create_file("pdev_stats", 0600, fwstats_dir, ar,
|
||||
&fops_pdev_stats);
|
||||
|
||||
INIT_LIST_HEAD(&ar->fw_stats.vdevs);
|
||||
INIT_LIST_HEAD(&ar->fw_stats.bcn);
|
||||
INIT_LIST_HEAD(&ar->fw_stats.pdevs);
|
||||
|
||||
init_completion(&ar->fw_stats_complete);
|
||||
ath12k_fw_stats_init(ar);
|
||||
}
|
||||
|
||||
void ath12k_debugfs_register(struct ath12k *ar)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ void ath12k_debugfs_register(struct ath12k *ar);
|
|||
void ath12k_debugfs_unregister(struct ath12k *ar);
|
||||
void ath12k_debugfs_fw_stats_process(struct ath12k *ar,
|
||||
struct ath12k_fw_stats *stats);
|
||||
void ath12k_debugfs_fw_stats_reset(struct ath12k *ar);
|
||||
void ath12k_debugfs_op_vif_add(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
|
||||
static inline bool ath12k_debugfs_is_extd_rx_stats_enabled(struct ath12k *ar)
|
||||
{
|
||||
|
|
@ -129,10 +130,6 @@ static inline void ath12k_debugfs_fw_stats_process(struct ath12k *ar,
|
|||
{
|
||||
}
|
||||
|
||||
static inline void ath12k_debugfs_fw_stats_reset(struct ath12k *ar)
|
||||
{
|
||||
}
|
||||
|
||||
static inline bool ath12k_debugfs_is_extd_rx_stats_enabled(struct ath12k *ar)
|
||||
{
|
||||
return false;
|
||||
|
|
@ -142,6 +139,11 @@ static inline int ath12k_debugfs_rx_filter(struct ath12k *ar)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void ath12k_debugfs_op_vif_add(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_ATH12K_DEBUGFS */
|
||||
|
||||
#endif /* _ATH12K_DEBUGFS_H_ */
|
||||
|
|
|
|||
|
|
@ -5377,6 +5377,9 @@ static ssize_t ath12k_write_htt_stats_type(struct file *file,
|
|||
const int size = 32;
|
||||
int num_args;
|
||||
|
||||
if (count > size)
|
||||
return -EINVAL;
|
||||
|
||||
char *buf __free(kfree) = kzalloc(size, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
|
|
|||
|
|
@ -1206,11 +1206,19 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
|
|||
if (!skb)
|
||||
continue;
|
||||
|
||||
skb_cb = ATH12K_SKB_CB(skb);
|
||||
if (skb_cb->paddr_ext_desc) {
|
||||
dma_unmap_single(ab->dev,
|
||||
skb_cb->paddr_ext_desc,
|
||||
tx_desc_info->skb_ext_desc->len,
|
||||
DMA_TO_DEVICE);
|
||||
dev_kfree_skb_any(tx_desc_info->skb_ext_desc);
|
||||
}
|
||||
|
||||
/* if we are unregistering, hw would've been destroyed and
|
||||
* ar is no longer valid.
|
||||
*/
|
||||
if (!(test_bit(ATH12K_FLAG_UNREGISTERING, &ab->dev_flags))) {
|
||||
skb_cb = ATH12K_SKB_CB(skb);
|
||||
ar = skb_cb->ar;
|
||||
|
||||
if (atomic_dec_and_test(&ar->dp.num_tx_pending))
|
||||
|
|
@ -1261,22 +1269,24 @@ static void ath12k_dp_reoq_lut_cleanup(struct ath12k_base *ab)
|
|||
if (!ab->hw_params->reoq_lut_support)
|
||||
return;
|
||||
|
||||
if (dp->reoq_lut.vaddr) {
|
||||
if (dp->reoq_lut.vaddr_unaligned) {
|
||||
ath12k_hif_write32(ab,
|
||||
HAL_SEQ_WCSS_UMAC_REO_REG +
|
||||
HAL_REO1_QDESC_LUT_BASE0(ab), 0);
|
||||
dma_free_coherent(ab->dev, DP_REOQ_LUT_SIZE,
|
||||
dp->reoq_lut.vaddr, dp->reoq_lut.paddr);
|
||||
dp->reoq_lut.vaddr = NULL;
|
||||
dma_free_coherent(ab->dev, dp->reoq_lut.size,
|
||||
dp->reoq_lut.vaddr_unaligned,
|
||||
dp->reoq_lut.paddr_unaligned);
|
||||
dp->reoq_lut.vaddr_unaligned = NULL;
|
||||
}
|
||||
|
||||
if (dp->ml_reoq_lut.vaddr) {
|
||||
if (dp->ml_reoq_lut.vaddr_unaligned) {
|
||||
ath12k_hif_write32(ab,
|
||||
HAL_SEQ_WCSS_UMAC_REO_REG +
|
||||
HAL_REO1_QDESC_LUT_BASE1(ab), 0);
|
||||
dma_free_coherent(ab->dev, DP_REOQ_LUT_SIZE,
|
||||
dp->ml_reoq_lut.vaddr, dp->ml_reoq_lut.paddr);
|
||||
dp->ml_reoq_lut.vaddr = NULL;
|
||||
dma_free_coherent(ab->dev, dp->ml_reoq_lut.size,
|
||||
dp->ml_reoq_lut.vaddr_unaligned,
|
||||
dp->ml_reoq_lut.paddr_unaligned);
|
||||
dp->ml_reoq_lut.vaddr_unaligned = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1608,39 +1618,67 @@ static int ath12k_dp_cc_init(struct ath12k_base *ab)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int ath12k_dp_alloc_reoq_lut(struct ath12k_base *ab,
|
||||
struct ath12k_reo_q_addr_lut *lut)
|
||||
{
|
||||
lut->size = DP_REOQ_LUT_SIZE + HAL_REO_QLUT_ADDR_ALIGN - 1;
|
||||
lut->vaddr_unaligned = dma_alloc_coherent(ab->dev, lut->size,
|
||||
&lut->paddr_unaligned,
|
||||
GFP_KERNEL | __GFP_ZERO);
|
||||
if (!lut->vaddr_unaligned)
|
||||
return -ENOMEM;
|
||||
|
||||
lut->vaddr = PTR_ALIGN(lut->vaddr_unaligned, HAL_REO_QLUT_ADDR_ALIGN);
|
||||
lut->paddr = lut->paddr_unaligned +
|
||||
((unsigned long)lut->vaddr - (unsigned long)lut->vaddr_unaligned);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath12k_dp_reoq_lut_setup(struct ath12k_base *ab)
|
||||
{
|
||||
struct ath12k_dp *dp = &ab->dp;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
if (!ab->hw_params->reoq_lut_support)
|
||||
return 0;
|
||||
|
||||
dp->reoq_lut.vaddr = dma_alloc_coherent(ab->dev,
|
||||
DP_REOQ_LUT_SIZE,
|
||||
&dp->reoq_lut.paddr,
|
||||
GFP_KERNEL | __GFP_ZERO);
|
||||
if (!dp->reoq_lut.vaddr) {
|
||||
ret = ath12k_dp_alloc_reoq_lut(ab, &dp->reoq_lut);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to allocate memory for reoq table");
|
||||
return -ENOMEM;
|
||||
return ret;
|
||||
}
|
||||
|
||||
dp->ml_reoq_lut.vaddr = dma_alloc_coherent(ab->dev,
|
||||
DP_REOQ_LUT_SIZE,
|
||||
&dp->ml_reoq_lut.paddr,
|
||||
GFP_KERNEL | __GFP_ZERO);
|
||||
if (!dp->ml_reoq_lut.vaddr) {
|
||||
ret = ath12k_dp_alloc_reoq_lut(ab, &dp->ml_reoq_lut);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to allocate memory for ML reoq table");
|
||||
dma_free_coherent(ab->dev, DP_REOQ_LUT_SIZE,
|
||||
dp->reoq_lut.vaddr, dp->reoq_lut.paddr);
|
||||
dp->reoq_lut.vaddr = NULL;
|
||||
return -ENOMEM;
|
||||
dma_free_coherent(ab->dev, dp->reoq_lut.size,
|
||||
dp->reoq_lut.vaddr_unaligned,
|
||||
dp->reoq_lut.paddr_unaligned);
|
||||
dp->reoq_lut.vaddr_unaligned = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Bits in the register have address [39:8] LUT base address to be
|
||||
* allocated such that LSBs are assumed to be zero. Also, current
|
||||
* design supports paddr up to 4 GB max hence it fits in 32 bit
|
||||
* register only
|
||||
*/
|
||||
|
||||
ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_LUT_BASE0(ab),
|
||||
dp->reoq_lut.paddr);
|
||||
dp->reoq_lut.paddr >> 8);
|
||||
|
||||
ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_LUT_BASE1(ab),
|
||||
dp->ml_reoq_lut.paddr >> 8);
|
||||
|
||||
val = ath12k_hif_read32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_ADDR(ab));
|
||||
|
||||
ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_ADDR(ab),
|
||||
val | HAL_REO_QDESC_ADDR_READ_LUT_ENABLE);
|
||||
|
||||
ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_MAX_PEERID(ab),
|
||||
HAL_REO_QDESC_MAX_PEERID);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#ifndef ATH12K_DP_H
|
||||
#define ATH12K_DP_H
|
||||
|
||||
#include "hal_desc.h"
|
||||
#include "hal_rx.h"
|
||||
#include "hw.h"
|
||||
|
||||
|
|
@ -106,6 +107,8 @@ struct dp_mon_mpdu {
|
|||
struct list_head list;
|
||||
struct sk_buff *head;
|
||||
struct sk_buff *tail;
|
||||
u32 err_bitmap;
|
||||
u8 decap_format;
|
||||
};
|
||||
|
||||
#define DP_MON_MAX_STATUS_BUF 32
|
||||
|
|
@ -293,11 +296,18 @@ struct ath12k_rx_desc_info {
|
|||
struct ath12k_tx_desc_info {
|
||||
struct list_head list;
|
||||
struct sk_buff *skb;
|
||||
struct sk_buff *skb_ext_desc;
|
||||
u32 desc_id; /* Cookie */
|
||||
u8 mac_id;
|
||||
u8 pool_id;
|
||||
};
|
||||
|
||||
struct ath12k_tx_desc_params {
|
||||
struct sk_buff *skb;
|
||||
struct sk_buff *skb_ext_desc;
|
||||
u8 mac_id;
|
||||
};
|
||||
|
||||
struct ath12k_spt_info {
|
||||
dma_addr_t paddr;
|
||||
u64 *vaddr;
|
||||
|
|
@ -309,8 +319,21 @@ struct ath12k_reo_queue_ref {
|
|||
} __packed;
|
||||
|
||||
struct ath12k_reo_q_addr_lut {
|
||||
dma_addr_t paddr;
|
||||
u32 *vaddr_unaligned;
|
||||
u32 *vaddr;
|
||||
dma_addr_t paddr_unaligned;
|
||||
dma_addr_t paddr;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct ath12k_link_stats {
|
||||
u32 tx_enqueued;
|
||||
u32 tx_completed;
|
||||
u32 tx_bcast_mcast;
|
||||
u32 tx_dropped;
|
||||
u32 tx_encap_type[HAL_TCL_ENCAP_TYPE_MAX];
|
||||
u32 tx_encrypt_type[HAL_ENCRYPT_TYPE_MAX];
|
||||
u32 tx_desc_type[HAL_TCL_DESC_TYPE_MAX];
|
||||
};
|
||||
|
||||
struct ath12k_dp {
|
||||
|
|
|
|||
|
|
@ -1647,7 +1647,7 @@ ath12k_dp_mon_rx_parse_status_tlv(struct ath12k *ar,
|
|||
u32_get_bits(info[0], HAL_RX_MPDU_START_INFO0_PPDU_ID);
|
||||
}
|
||||
|
||||
break;
|
||||
return HAL_RX_MON_STATUS_MPDU_START;
|
||||
}
|
||||
case HAL_RX_MSDU_START:
|
||||
/* TODO: add msdu start parsing logic */
|
||||
|
|
@ -1688,55 +1688,168 @@ ath12k_dp_mon_rx_parse_status_tlv(struct ath12k *ar,
|
|||
return HAL_RX_MON_STATUS_PPDU_NOT_DONE;
|
||||
}
|
||||
|
||||
static void ath12k_dp_mon_rx_msdus_set_payload(struct ath12k *ar,
|
||||
struct sk_buff *head_msdu,
|
||||
struct sk_buff *tail_msdu)
|
||||
static void
|
||||
ath12k_dp_mon_fill_rx_stats_info(struct ath12k *ar,
|
||||
struct hal_rx_mon_ppdu_info *ppdu_info,
|
||||
struct ieee80211_rx_status *rx_status)
|
||||
{
|
||||
u32 rx_pkt_offset, l2_hdr_offset;
|
||||
u32 center_freq = ppdu_info->freq;
|
||||
|
||||
rx_pkt_offset = ar->ab->hal.hal_desc_sz;
|
||||
l2_hdr_offset =
|
||||
ath12k_dp_rx_h_l3pad(ar->ab, (struct hal_rx_desc *)tail_msdu->data);
|
||||
skb_pull(head_msdu, rx_pkt_offset + l2_hdr_offset);
|
||||
rx_status->freq = center_freq;
|
||||
rx_status->bw = ath12k_mac_bw_to_mac80211_bw(ppdu_info->bw);
|
||||
rx_status->nss = ppdu_info->nss;
|
||||
rx_status->rate_idx = 0;
|
||||
rx_status->encoding = RX_ENC_LEGACY;
|
||||
rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
|
||||
|
||||
if (center_freq >= ATH12K_MIN_6GHZ_FREQ &&
|
||||
center_freq <= ATH12K_MAX_6GHZ_FREQ) {
|
||||
rx_status->band = NL80211_BAND_6GHZ;
|
||||
} else if (center_freq >= ATH12K_MIN_2GHZ_FREQ &&
|
||||
center_freq <= ATH12K_MAX_2GHZ_FREQ) {
|
||||
rx_status->band = NL80211_BAND_2GHZ;
|
||||
} else if (center_freq >= ATH12K_MIN_5GHZ_FREQ &&
|
||||
center_freq <= ATH12K_MAX_5GHZ_FREQ) {
|
||||
rx_status->band = NL80211_BAND_5GHZ;
|
||||
} else {
|
||||
rx_status->band = NUM_NL80211_BANDS;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ath12k_dp_mon_fill_rx_rate(struct ath12k *ar,
|
||||
struct hal_rx_mon_ppdu_info *ppdu_info,
|
||||
struct ieee80211_rx_status *rx_status)
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
enum rx_msdu_start_pkt_type pkt_type;
|
||||
u8 rate_mcs, nss, sgi;
|
||||
bool is_cck;
|
||||
|
||||
pkt_type = ppdu_info->preamble_type;
|
||||
rate_mcs = ppdu_info->rate;
|
||||
nss = ppdu_info->nss;
|
||||
sgi = ppdu_info->gi;
|
||||
|
||||
switch (pkt_type) {
|
||||
case RX_MSDU_START_PKT_TYPE_11A:
|
||||
case RX_MSDU_START_PKT_TYPE_11B:
|
||||
is_cck = (pkt_type == RX_MSDU_START_PKT_TYPE_11B);
|
||||
if (rx_status->band < NUM_NL80211_BANDS) {
|
||||
sband = &ar->mac.sbands[rx_status->band];
|
||||
rx_status->rate_idx = ath12k_mac_hw_rate_to_idx(sband, rate_mcs,
|
||||
is_cck);
|
||||
}
|
||||
break;
|
||||
case RX_MSDU_START_PKT_TYPE_11N:
|
||||
rx_status->encoding = RX_ENC_HT;
|
||||
if (rate_mcs > ATH12K_HT_MCS_MAX) {
|
||||
ath12k_warn(ar->ab,
|
||||
"Received with invalid mcs in HT mode %d\n",
|
||||
rate_mcs);
|
||||
break;
|
||||
}
|
||||
rx_status->rate_idx = rate_mcs + (8 * (nss - 1));
|
||||
if (sgi)
|
||||
rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
|
||||
break;
|
||||
case RX_MSDU_START_PKT_TYPE_11AC:
|
||||
rx_status->encoding = RX_ENC_VHT;
|
||||
rx_status->rate_idx = rate_mcs;
|
||||
if (rate_mcs > ATH12K_VHT_MCS_MAX) {
|
||||
ath12k_warn(ar->ab,
|
||||
"Received with invalid mcs in VHT mode %d\n",
|
||||
rate_mcs);
|
||||
break;
|
||||
}
|
||||
if (sgi)
|
||||
rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
|
||||
break;
|
||||
case RX_MSDU_START_PKT_TYPE_11AX:
|
||||
rx_status->rate_idx = rate_mcs;
|
||||
if (rate_mcs > ATH12K_HE_MCS_MAX) {
|
||||
ath12k_warn(ar->ab,
|
||||
"Received with invalid mcs in HE mode %d\n",
|
||||
rate_mcs);
|
||||
break;
|
||||
}
|
||||
rx_status->encoding = RX_ENC_HE;
|
||||
rx_status->he_gi = ath12k_he_gi_to_nl80211_he_gi(sgi);
|
||||
break;
|
||||
case RX_MSDU_START_PKT_TYPE_11BE:
|
||||
rx_status->rate_idx = rate_mcs;
|
||||
if (rate_mcs > ATH12K_EHT_MCS_MAX) {
|
||||
ath12k_warn(ar->ab,
|
||||
"Received with invalid mcs in EHT mode %d\n",
|
||||
rate_mcs);
|
||||
break;
|
||||
}
|
||||
rx_status->encoding = RX_ENC_EHT;
|
||||
rx_status->he_gi = ath12k_he_gi_to_nl80211_he_gi(sgi);
|
||||
break;
|
||||
default:
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
|
||||
"monitor receives invalid preamble type %d",
|
||||
pkt_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
|
||||
struct sk_buff *head_msdu, struct sk_buff *tail_msdu,
|
||||
struct ieee80211_rx_status *rxs, bool *fcs_err)
|
||||
struct dp_mon_mpdu *mon_mpdu,
|
||||
struct hal_rx_mon_ppdu_info *ppdu_info,
|
||||
struct ieee80211_rx_status *rxs)
|
||||
{
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
struct sk_buff *msdu, *mpdu_buf, *prev_buf, *head_frag_list;
|
||||
struct hal_rx_desc *rx_desc, *tail_rx_desc;
|
||||
u8 *hdr_desc, *dest, decap_format;
|
||||
struct sk_buff *head_msdu;
|
||||
struct hal_rx_desc *rx_desc;
|
||||
u8 *hdr_desc, *dest, decap_format = mon_mpdu->decap_format;
|
||||
struct ieee80211_hdr_3addr *wh;
|
||||
u32 err_bitmap, frag_list_sum_len = 0;
|
||||
struct ieee80211_channel *channel;
|
||||
u32 frag_list_sum_len = 0;
|
||||
u8 channel_num = ppdu_info->chan_num;
|
||||
|
||||
mpdu_buf = NULL;
|
||||
head_msdu = mon_mpdu->head;
|
||||
|
||||
if (!head_msdu)
|
||||
goto err_merge_fail;
|
||||
|
||||
rx_desc = (struct hal_rx_desc *)head_msdu->data;
|
||||
tail_rx_desc = (struct hal_rx_desc *)tail_msdu->data;
|
||||
ath12k_dp_mon_fill_rx_stats_info(ar, ppdu_info, rxs);
|
||||
|
||||
err_bitmap = ath12k_dp_rx_h_mpdu_err(ab, tail_rx_desc);
|
||||
if (err_bitmap & HAL_RX_MPDU_ERR_FCS)
|
||||
*fcs_err = true;
|
||||
if (unlikely(rxs->band == NUM_NL80211_BANDS ||
|
||||
!ath12k_ar_to_hw(ar)->wiphy->bands[rxs->band])) {
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
|
||||
"sband is NULL for status band %d channel_num %d center_freq %d pdev_id %d\n",
|
||||
rxs->band, channel_num, ppdu_info->freq, ar->pdev_idx);
|
||||
|
||||
decap_format = ath12k_dp_rx_h_decap_type(ab, tail_rx_desc);
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
channel = ar->rx_channel;
|
||||
if (channel) {
|
||||
rxs->band = channel->band;
|
||||
channel_num =
|
||||
ieee80211_frequency_to_channel(channel->center_freq);
|
||||
}
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
||||
ath12k_dp_rx_h_ppdu(ar, tail_rx_desc, rxs);
|
||||
if (rxs->band < NUM_NL80211_BANDS)
|
||||
rxs->freq = ieee80211_channel_to_frequency(channel_num,
|
||||
rxs->band);
|
||||
|
||||
ath12k_dp_mon_fill_rx_rate(ar, ppdu_info, rxs);
|
||||
|
||||
if (decap_format == DP_RX_DECAP_TYPE_RAW) {
|
||||
ath12k_dp_mon_rx_msdus_set_payload(ar, head_msdu, tail_msdu);
|
||||
skb_pull(head_msdu, ATH12K_MON_RX_PKT_OFFSET);
|
||||
|
||||
prev_buf = head_msdu;
|
||||
msdu = head_msdu->next;
|
||||
head_frag_list = NULL;
|
||||
|
||||
while (msdu) {
|
||||
ath12k_dp_mon_rx_msdus_set_payload(ar, msdu, tail_msdu);
|
||||
skb_pull(msdu, ATH12K_MON_RX_PKT_OFFSET);
|
||||
|
||||
if (!head_frag_list)
|
||||
head_frag_list = msdu;
|
||||
|
|
@ -1748,7 +1861,7 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
|
|||
|
||||
prev_buf->next = NULL;
|
||||
|
||||
skb_trim(prev_buf, prev_buf->len - HAL_RX_FCS_LEN);
|
||||
skb_trim(prev_buf, prev_buf->len);
|
||||
if (head_frag_list) {
|
||||
skb_shinfo(head_msdu)->frag_list = head_frag_list;
|
||||
head_msdu->data_len = frag_list_sum_len;
|
||||
|
|
@ -1771,7 +1884,7 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
|
|||
msdu = head_msdu;
|
||||
|
||||
while (msdu) {
|
||||
ath12k_dp_mon_rx_msdus_set_payload(ar, msdu, tail_msdu);
|
||||
skb_pull(msdu, ATH12K_MON_RX_PKT_OFFSET);
|
||||
if (qos_pkt) {
|
||||
dest = skb_push(msdu, sizeof(__le16));
|
||||
if (!dest)
|
||||
|
|
@ -1954,7 +2067,8 @@ static void ath12k_dp_mon_update_radiotap(struct ath12k *ar,
|
|||
|
||||
static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *napi,
|
||||
struct sk_buff *msdu,
|
||||
struct ieee80211_rx_status *status)
|
||||
struct ieee80211_rx_status *status,
|
||||
u8 decap)
|
||||
{
|
||||
static const struct ieee80211_radiotap_he known = {
|
||||
.data1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN |
|
||||
|
|
@ -1966,10 +2080,12 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k *ar, struct napi_struct
|
|||
struct ieee80211_sta *pubsta = NULL;
|
||||
struct ath12k_peer *peer;
|
||||
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
|
||||
u8 decap = DP_RX_DECAP_TYPE_RAW;
|
||||
struct ath12k_dp_rx_info rx_info;
|
||||
bool is_mcbc = rxcb->is_mcbc;
|
||||
bool is_eapol_tkip = rxcb->is_eapol;
|
||||
|
||||
status->link_valid = 0;
|
||||
|
||||
if ((status->encoding == RX_ENC_HE) && !(status->flag & RX_FLAG_RADIOTAP_HE) &&
|
||||
!(status->flag & RX_FLAG_SKIP_MONITOR)) {
|
||||
he = skb_push(msdu, sizeof(known));
|
||||
|
|
@ -1977,10 +2093,9 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k *ar, struct napi_struct
|
|||
status->flag |= RX_FLAG_RADIOTAP_HE;
|
||||
}
|
||||
|
||||
if (!(status->flag & RX_FLAG_ONLY_MONITOR))
|
||||
decap = ath12k_dp_rx_h_decap_type(ar->ab, rxcb->rx_desc);
|
||||
spin_lock_bh(&ar->ab->base_lock);
|
||||
peer = ath12k_dp_rx_h_find_peer(ar->ab, msdu);
|
||||
rx_info.addr2_present = false;
|
||||
peer = ath12k_dp_rx_h_find_peer(ar->ab, msdu, &rx_info);
|
||||
if (peer && peer->sta) {
|
||||
pubsta = peer->sta;
|
||||
if (pubsta->valid_links) {
|
||||
|
|
@ -2035,25 +2150,23 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k *ar, struct napi_struct
|
|||
}
|
||||
|
||||
static int ath12k_dp_mon_rx_deliver(struct ath12k *ar,
|
||||
struct sk_buff *head_msdu, struct sk_buff *tail_msdu,
|
||||
struct dp_mon_mpdu *mon_mpdu,
|
||||
struct hal_rx_mon_ppdu_info *ppduinfo,
|
||||
struct napi_struct *napi)
|
||||
{
|
||||
struct ath12k_pdev_dp *dp = &ar->dp;
|
||||
struct sk_buff *mon_skb, *skb_next, *header;
|
||||
struct ieee80211_rx_status *rxs = &dp->rx_status;
|
||||
bool fcs_err = false;
|
||||
u8 decap = DP_RX_DECAP_TYPE_RAW;
|
||||
|
||||
mon_skb = ath12k_dp_mon_rx_merg_msdus(ar,
|
||||
head_msdu, tail_msdu,
|
||||
rxs, &fcs_err);
|
||||
mon_skb = ath12k_dp_mon_rx_merg_msdus(ar, mon_mpdu, ppduinfo, rxs);
|
||||
if (!mon_skb)
|
||||
goto mon_deliver_fail;
|
||||
|
||||
header = mon_skb;
|
||||
rxs->flag = 0;
|
||||
|
||||
if (fcs_err)
|
||||
if (mon_mpdu->err_bitmap & HAL_RX_MPDU_ERR_FCS)
|
||||
rxs->flag = RX_FLAG_FAILED_FCS_CRC;
|
||||
|
||||
do {
|
||||
|
|
@ -2070,8 +2183,12 @@ static int ath12k_dp_mon_rx_deliver(struct ath12k *ar,
|
|||
rxs->flag |= RX_FLAG_ALLOW_SAME_PN;
|
||||
}
|
||||
rxs->flag |= RX_FLAG_ONLY_MONITOR;
|
||||
|
||||
if (!(rxs->flag & RX_FLAG_ONLY_MONITOR))
|
||||
decap = mon_mpdu->decap_format;
|
||||
|
||||
ath12k_dp_mon_update_radiotap(ar, ppduinfo, mon_skb, rxs);
|
||||
ath12k_dp_mon_rx_deliver_msdu(ar, napi, mon_skb, rxs);
|
||||
ath12k_dp_mon_rx_deliver_msdu(ar, napi, mon_skb, rxs, decap);
|
||||
mon_skb = skb_next;
|
||||
} while (mon_skb);
|
||||
rxs->flag = 0;
|
||||
|
|
@ -2079,7 +2196,7 @@ static int ath12k_dp_mon_rx_deliver(struct ath12k *ar,
|
|||
return 0;
|
||||
|
||||
mon_deliver_fail:
|
||||
mon_skb = head_msdu;
|
||||
mon_skb = mon_mpdu->head;
|
||||
while (mon_skb) {
|
||||
skb_next = mon_skb->next;
|
||||
dev_kfree_skb_any(mon_skb);
|
||||
|
|
@ -2088,6 +2205,144 @@ static int ath12k_dp_mon_rx_deliver(struct ath12k *ar,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ath12k_dp_pkt_set_pktlen(struct sk_buff *skb, u32 len)
|
||||
{
|
||||
if (skb->len > len) {
|
||||
skb_trim(skb, len);
|
||||
} else {
|
||||
if (skb_tailroom(skb) < len - skb->len) {
|
||||
if ((pskb_expand_head(skb, 0,
|
||||
len - skb->len - skb_tailroom(skb),
|
||||
GFP_ATOMIC))) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
skb_put(skb, (len - skb->len));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath12k_dp_mon_parse_rx_msdu_end_err(u32 info, u32 *errmap)
|
||||
{
|
||||
if (info & RX_MSDU_END_INFO13_FCS_ERR)
|
||||
*errmap |= HAL_RX_MPDU_ERR_FCS;
|
||||
|
||||
if (info & RX_MSDU_END_INFO13_DECRYPT_ERR)
|
||||
*errmap |= HAL_RX_MPDU_ERR_DECRYPT;
|
||||
|
||||
if (info & RX_MSDU_END_INFO13_TKIP_MIC_ERR)
|
||||
*errmap |= HAL_RX_MPDU_ERR_TKIP_MIC;
|
||||
|
||||
if (info & RX_MSDU_END_INFO13_A_MSDU_ERROR)
|
||||
*errmap |= HAL_RX_MPDU_ERR_AMSDU_ERR;
|
||||
|
||||
if (info & RX_MSDU_END_INFO13_OVERFLOW_ERR)
|
||||
*errmap |= HAL_RX_MPDU_ERR_OVERFLOW;
|
||||
|
||||
if (info & RX_MSDU_END_INFO13_MSDU_LEN_ERR)
|
||||
*errmap |= HAL_RX_MPDU_ERR_MSDU_LEN;
|
||||
|
||||
if (info & RX_MSDU_END_INFO13_MPDU_LEN_ERR)
|
||||
*errmap |= HAL_RX_MPDU_ERR_MPDU_LEN;
|
||||
}
|
||||
|
||||
static int
|
||||
ath12k_dp_mon_parse_status_msdu_end(struct ath12k_mon_data *pmon,
|
||||
const struct hal_rx_msdu_end *msdu_end)
|
||||
{
|
||||
struct dp_mon_mpdu *mon_mpdu = pmon->mon_mpdu;
|
||||
|
||||
ath12k_dp_mon_parse_rx_msdu_end_err(__le32_to_cpu(msdu_end->info2),
|
||||
&mon_mpdu->err_bitmap);
|
||||
|
||||
mon_mpdu->decap_format = le32_get_bits(msdu_end->info1,
|
||||
RX_MSDU_END_INFO11_DECAP_FORMAT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ath12k_dp_mon_parse_status_buf(struct ath12k *ar,
|
||||
struct ath12k_mon_data *pmon,
|
||||
const struct dp_mon_packet_info *packet_info)
|
||||
{
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
struct dp_rxdma_mon_ring *buf_ring = &ab->dp.rxdma_mon_buf_ring;
|
||||
struct sk_buff *msdu;
|
||||
int buf_id;
|
||||
u32 offset;
|
||||
|
||||
buf_id = u32_get_bits(packet_info->cookie, DP_RXDMA_BUF_COOKIE_BUF_ID);
|
||||
|
||||
spin_lock_bh(&buf_ring->idr_lock);
|
||||
msdu = idr_remove(&buf_ring->bufs_idr, buf_id);
|
||||
spin_unlock_bh(&buf_ring->idr_lock);
|
||||
|
||||
if (unlikely(!msdu)) {
|
||||
ath12k_warn(ab, "mon dest desc with inval buf_id %d\n", buf_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dma_unmap_single(ab->dev, ATH12K_SKB_RXCB(msdu)->paddr,
|
||||
msdu->len + skb_tailroom(msdu),
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
offset = packet_info->dma_length + ATH12K_MON_RX_DOT11_OFFSET;
|
||||
if (ath12k_dp_pkt_set_pktlen(msdu, offset)) {
|
||||
dev_kfree_skb_any(msdu);
|
||||
goto dest_replenish;
|
||||
}
|
||||
|
||||
if (!pmon->mon_mpdu->head)
|
||||
pmon->mon_mpdu->head = msdu;
|
||||
else
|
||||
pmon->mon_mpdu->tail->next = msdu;
|
||||
|
||||
pmon->mon_mpdu->tail = msdu;
|
||||
|
||||
dest_replenish:
|
||||
ath12k_dp_mon_buf_replenish(ab, buf_ring, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ath12k_dp_mon_parse_rx_dest_tlv(struct ath12k *ar,
|
||||
struct ath12k_mon_data *pmon,
|
||||
enum hal_rx_mon_status hal_status,
|
||||
const void *tlv_data)
|
||||
{
|
||||
switch (hal_status) {
|
||||
case HAL_RX_MON_STATUS_MPDU_START:
|
||||
if (WARN_ON_ONCE(pmon->mon_mpdu))
|
||||
break;
|
||||
|
||||
pmon->mon_mpdu = kzalloc(sizeof(*pmon->mon_mpdu), GFP_ATOMIC);
|
||||
if (!pmon->mon_mpdu)
|
||||
return -ENOMEM;
|
||||
break;
|
||||
case HAL_RX_MON_STATUS_BUF_ADDR:
|
||||
return ath12k_dp_mon_parse_status_buf(ar, pmon, tlv_data);
|
||||
case HAL_RX_MON_STATUS_MPDU_END:
|
||||
/* If no MSDU then free empty MPDU */
|
||||
if (pmon->mon_mpdu->tail) {
|
||||
pmon->mon_mpdu->tail->next = NULL;
|
||||
list_add_tail(&pmon->mon_mpdu->list, &pmon->dp_rx_mon_mpdu_list);
|
||||
} else {
|
||||
kfree(pmon->mon_mpdu);
|
||||
}
|
||||
pmon->mon_mpdu = NULL;
|
||||
break;
|
||||
case HAL_RX_MON_STATUS_MSDU_END:
|
||||
return ath12k_dp_mon_parse_status_msdu_end(pmon, tlv_data);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum hal_rx_mon_status
|
||||
ath12k_dp_mon_parse_rx_dest(struct ath12k *ar, struct ath12k_mon_data *pmon,
|
||||
struct sk_buff *skb)
|
||||
|
|
@ -2114,14 +2369,20 @@ ath12k_dp_mon_parse_rx_dest(struct ath12k *ar, struct ath12k_mon_data *pmon,
|
|||
tlv_len = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_LEN);
|
||||
|
||||
hal_status = ath12k_dp_mon_rx_parse_status_tlv(ar, pmon, tlv);
|
||||
|
||||
if (ar->monitor_started &&
|
||||
ath12k_dp_mon_parse_rx_dest_tlv(ar, pmon, hal_status, tlv->value))
|
||||
return HAL_RX_MON_STATUS_PPDU_DONE;
|
||||
|
||||
ptr += sizeof(*tlv) + tlv_len;
|
||||
ptr = PTR_ALIGN(ptr, HAL_TLV_64_ALIGN);
|
||||
|
||||
if ((ptr - skb->data) >= DP_RX_BUFFER_SIZE)
|
||||
if ((ptr - skb->data) > skb->len)
|
||||
break;
|
||||
|
||||
} while ((hal_status == HAL_RX_MON_STATUS_PPDU_NOT_DONE) ||
|
||||
(hal_status == HAL_RX_MON_STATUS_BUF_ADDR) ||
|
||||
(hal_status == HAL_RX_MON_STATUS_MPDU_START) ||
|
||||
(hal_status == HAL_RX_MON_STATUS_MPDU_END) ||
|
||||
(hal_status == HAL_RX_MON_STATUS_MSDU_END));
|
||||
|
||||
|
|
@ -2141,23 +2402,21 @@ ath12k_dp_mon_rx_parse_mon_status(struct ath12k *ar,
|
|||
struct hal_rx_mon_ppdu_info *ppdu_info = &pmon->mon_ppdu_info;
|
||||
struct dp_mon_mpdu *tmp;
|
||||
struct dp_mon_mpdu *mon_mpdu = pmon->mon_mpdu;
|
||||
struct sk_buff *head_msdu, *tail_msdu;
|
||||
enum hal_rx_mon_status hal_status = HAL_RX_MON_STATUS_BUF_DONE;
|
||||
enum hal_rx_mon_status hal_status;
|
||||
|
||||
ath12k_dp_mon_parse_rx_dest(ar, pmon, skb);
|
||||
hal_status = ath12k_dp_mon_parse_rx_dest(ar, pmon, skb);
|
||||
if (hal_status != HAL_RX_MON_STATUS_PPDU_DONE)
|
||||
return hal_status;
|
||||
|
||||
list_for_each_entry_safe(mon_mpdu, tmp, &pmon->dp_rx_mon_mpdu_list, list) {
|
||||
list_del(&mon_mpdu->list);
|
||||
head_msdu = mon_mpdu->head;
|
||||
tail_msdu = mon_mpdu->tail;
|
||||
|
||||
if (head_msdu && tail_msdu) {
|
||||
ath12k_dp_mon_rx_deliver(ar, head_msdu,
|
||||
tail_msdu, ppdu_info, napi);
|
||||
}
|
||||
if (mon_mpdu->head && mon_mpdu->tail)
|
||||
ath12k_dp_mon_rx_deliver(ar, mon_mpdu, ppdu_info, napi);
|
||||
|
||||
kfree(mon_mpdu);
|
||||
}
|
||||
|
||||
return hal_status;
|
||||
}
|
||||
|
||||
|
|
@ -2838,16 +3097,13 @@ ath12k_dp_mon_tx_process_ppdu_info(struct ath12k *ar,
|
|||
struct dp_mon_tx_ppdu_info *tx_ppdu_info)
|
||||
{
|
||||
struct dp_mon_mpdu *tmp, *mon_mpdu;
|
||||
struct sk_buff *head_msdu, *tail_msdu;
|
||||
|
||||
list_for_each_entry_safe(mon_mpdu, tmp,
|
||||
&tx_ppdu_info->dp_tx_mon_mpdu_list, list) {
|
||||
list_del(&mon_mpdu->list);
|
||||
head_msdu = mon_mpdu->head;
|
||||
tail_msdu = mon_mpdu->tail;
|
||||
|
||||
if (head_msdu)
|
||||
ath12k_dp_mon_rx_deliver(ar, head_msdu, tail_msdu,
|
||||
if (mon_mpdu->head)
|
||||
ath12k_dp_mon_rx_deliver(ar, mon_mpdu,
|
||||
&tx_ppdu_info->rx_status, napi);
|
||||
|
||||
kfree(mon_mpdu);
|
||||
|
|
@ -2949,11 +3205,10 @@ static void ath12k_dp_mon_rx_update_peer_su_stats(struct ath12k *ar,
|
|||
struct ath12k_rx_peer_stats *rx_stats = arsta->rx_stats;
|
||||
u32 num_msdu;
|
||||
|
||||
if (!rx_stats)
|
||||
return;
|
||||
|
||||
arsta->rssi_comb = ppdu_info->rssi_comb;
|
||||
ewma_avg_rssi_add(&arsta->avg_rssi, ppdu_info->rssi_comb);
|
||||
if (!rx_stats)
|
||||
return;
|
||||
|
||||
num_msdu = ppdu_info->tcp_msdu_count + ppdu_info->tcp_ack_msdu_count +
|
||||
ppdu_info->udp_msdu_count + ppdu_info->other_msdu_count;
|
||||
|
|
@ -3126,13 +3381,11 @@ ath12k_dp_mon_rx_update_user_stats(struct ath12k *ar,
|
|||
|
||||
ahsta = ath12k_sta_to_ahsta(peer->sta);
|
||||
arsta = &ahsta->deflink;
|
||||
rx_stats = arsta->rx_stats;
|
||||
|
||||
if (!rx_stats)
|
||||
return;
|
||||
|
||||
arsta->rssi_comb = ppdu_info->rssi_comb;
|
||||
ewma_avg_rssi_add(&arsta->avg_rssi, ppdu_info->rssi_comb);
|
||||
rx_stats = arsta->rx_stats;
|
||||
if (!rx_stats)
|
||||
return;
|
||||
|
||||
num_msdu = user_stats->tcp_msdu_count + user_stats->tcp_ack_msdu_count +
|
||||
user_stats->udp_msdu_count + user_stats->other_msdu_count;
|
||||
|
|
@ -3346,7 +3599,7 @@ int ath12k_dp_mon_srng_process(struct ath12k *ar, int *budget,
|
|||
ath12k_dp_mon_rx_memset_ppdu_info(ppdu_info);
|
||||
|
||||
while ((skb = __skb_dequeue(&skb_list))) {
|
||||
hal_status = ath12k_dp_mon_parse_rx_dest(ar, pmon, skb);
|
||||
hal_status = ath12k_dp_mon_rx_parse_mon_status(ar, pmon, skb, napi);
|
||||
if (hal_status != HAL_RX_MON_STATUS_PPDU_DONE) {
|
||||
ppdu_info->ppdu_continuation = true;
|
||||
dev_kfree_skb_any(skb);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH12K_DP_MON_H
|
||||
|
|
@ -9,6 +9,9 @@
|
|||
|
||||
#include "core.h"
|
||||
|
||||
#define ATH12K_MON_RX_DOT11_OFFSET 5
|
||||
#define ATH12K_MON_RX_PKT_OFFSET 8
|
||||
|
||||
enum dp_monitor_mode {
|
||||
ATH12K_DP_TX_MONITOR_MODE,
|
||||
ATH12K_DP_RX_MONITOR_MODE
|
||||
|
|
|
|||
|
|
@ -228,12 +228,6 @@ static void ath12k_dp_rx_desc_get_crypto_header(struct ath12k_base *ab,
|
|||
ab->hal_rx_ops->rx_desc_get_crypto_header(desc, crypto_hdr, enctype);
|
||||
}
|
||||
|
||||
static u16 ath12k_dp_rxdesc_get_mpdu_frame_ctrl(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hal_rx_ops->rx_desc_get_mpdu_frame_ctl(desc);
|
||||
}
|
||||
|
||||
static inline u8 ath12k_dp_rx_get_msdu_src_link(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
|
|
@ -556,9 +550,9 @@ void ath12k_dp_rx_reo_cmd_list_cleanup(struct ath12k_base *ab)
|
|||
spin_lock_bh(&dp->reo_cmd_lock);
|
||||
list_for_each_entry_safe(cmd, tmp, &dp->reo_cmd_list, list) {
|
||||
list_del(&cmd->list);
|
||||
dma_unmap_single(ab->dev, cmd->data.paddr,
|
||||
cmd->data.size, DMA_BIDIRECTIONAL);
|
||||
kfree(cmd->data.vaddr);
|
||||
dma_unmap_single(ab->dev, cmd->data.qbuf.paddr_aligned,
|
||||
cmd->data.qbuf.size, DMA_BIDIRECTIONAL);
|
||||
kfree(cmd->data.qbuf.vaddr);
|
||||
kfree(cmd);
|
||||
}
|
||||
|
||||
|
|
@ -566,9 +560,9 @@ void ath12k_dp_rx_reo_cmd_list_cleanup(struct ath12k_base *ab)
|
|||
&dp->reo_cmd_cache_flush_list, list) {
|
||||
list_del(&cmd_cache->list);
|
||||
dp->reo_cmd_cache_flush_count--;
|
||||
dma_unmap_single(ab->dev, cmd_cache->data.paddr,
|
||||
cmd_cache->data.size, DMA_BIDIRECTIONAL);
|
||||
kfree(cmd_cache->data.vaddr);
|
||||
dma_unmap_single(ab->dev, cmd_cache->data.qbuf.paddr_aligned,
|
||||
cmd_cache->data.qbuf.size, DMA_BIDIRECTIONAL);
|
||||
kfree(cmd_cache->data.qbuf.vaddr);
|
||||
kfree(cmd_cache);
|
||||
}
|
||||
spin_unlock_bh(&dp->reo_cmd_lock);
|
||||
|
|
@ -583,10 +577,10 @@ static void ath12k_dp_reo_cmd_free(struct ath12k_dp *dp, void *ctx,
|
|||
ath12k_warn(dp->ab, "failed to flush rx tid hw desc, tid %d status %d\n",
|
||||
rx_tid->tid, status);
|
||||
|
||||
dma_unmap_single(dp->ab->dev, rx_tid->paddr, rx_tid->size,
|
||||
dma_unmap_single(dp->ab->dev, rx_tid->qbuf.paddr_aligned, rx_tid->qbuf.size,
|
||||
DMA_BIDIRECTIONAL);
|
||||
kfree(rx_tid->vaddr);
|
||||
rx_tid->vaddr = NULL;
|
||||
kfree(rx_tid->qbuf.vaddr);
|
||||
rx_tid->qbuf.vaddr = NULL;
|
||||
}
|
||||
|
||||
static int ath12k_dp_reo_cmd_send(struct ath12k_base *ab, struct ath12k_dp_rx_tid *rx_tid,
|
||||
|
|
@ -641,13 +635,13 @@ static void ath12k_dp_reo_cache_flush(struct ath12k_base *ab,
|
|||
unsigned long tot_desc_sz, desc_sz;
|
||||
int ret;
|
||||
|
||||
tot_desc_sz = rx_tid->size;
|
||||
tot_desc_sz = rx_tid->qbuf.size;
|
||||
desc_sz = ath12k_hal_reo_qdesc_size(0, HAL_DESC_REO_NON_QOS_TID);
|
||||
|
||||
while (tot_desc_sz > desc_sz) {
|
||||
tot_desc_sz -= desc_sz;
|
||||
cmd.addr_lo = lower_32_bits(rx_tid->paddr + tot_desc_sz);
|
||||
cmd.addr_hi = upper_32_bits(rx_tid->paddr);
|
||||
cmd.addr_lo = lower_32_bits(rx_tid->qbuf.paddr_aligned + tot_desc_sz);
|
||||
cmd.addr_hi = upper_32_bits(rx_tid->qbuf.paddr_aligned);
|
||||
ret = ath12k_dp_reo_cmd_send(ab, rx_tid,
|
||||
HAL_REO_CMD_FLUSH_CACHE, &cmd,
|
||||
NULL);
|
||||
|
|
@ -658,8 +652,8 @@ static void ath12k_dp_reo_cache_flush(struct ath12k_base *ab,
|
|||
}
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.addr_lo = lower_32_bits(rx_tid->paddr);
|
||||
cmd.addr_hi = upper_32_bits(rx_tid->paddr);
|
||||
cmd.addr_lo = lower_32_bits(rx_tid->qbuf.paddr_aligned);
|
||||
cmd.addr_hi = upper_32_bits(rx_tid->qbuf.paddr_aligned);
|
||||
cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS;
|
||||
ret = ath12k_dp_reo_cmd_send(ab, rx_tid,
|
||||
HAL_REO_CMD_FLUSH_CACHE,
|
||||
|
|
@ -667,10 +661,10 @@ static void ath12k_dp_reo_cache_flush(struct ath12k_base *ab,
|
|||
if (ret) {
|
||||
ath12k_err(ab, "failed to send HAL_REO_CMD_FLUSH_CACHE cmd, tid %d (%d)\n",
|
||||
rx_tid->tid, ret);
|
||||
dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size,
|
||||
dma_unmap_single(ab->dev, rx_tid->qbuf.paddr_aligned, rx_tid->qbuf.size,
|
||||
DMA_BIDIRECTIONAL);
|
||||
kfree(rx_tid->vaddr);
|
||||
rx_tid->vaddr = NULL;
|
||||
kfree(rx_tid->qbuf.vaddr);
|
||||
rx_tid->qbuf.vaddr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -729,10 +723,10 @@ static void ath12k_dp_rx_tid_del_func(struct ath12k_dp *dp, void *ctx,
|
|||
|
||||
return;
|
||||
free_desc:
|
||||
dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size,
|
||||
dma_unmap_single(ab->dev, rx_tid->qbuf.paddr_aligned, rx_tid->qbuf.size,
|
||||
DMA_BIDIRECTIONAL);
|
||||
kfree(rx_tid->vaddr);
|
||||
rx_tid->vaddr = NULL;
|
||||
kfree(rx_tid->qbuf.vaddr);
|
||||
rx_tid->qbuf.vaddr = NULL;
|
||||
}
|
||||
|
||||
static void ath12k_peer_rx_tid_qref_setup(struct ath12k_base *ab, u16 peer_id, u16 tid,
|
||||
|
|
@ -762,6 +756,7 @@ static void ath12k_peer_rx_tid_qref_setup(struct ath12k_base *ab, u16 peer_id, u
|
|||
qref->info1 = u32_encode_bits(upper_32_bits(paddr),
|
||||
BUFFER_ADDR_INFO1_ADDR) |
|
||||
u32_encode_bits(tid, DP_REO_QREF_NUM);
|
||||
ath12k_hal_reo_shared_qaddr_cache_clear(ab);
|
||||
}
|
||||
|
||||
static void ath12k_peer_rx_tid_qref_reset(struct ath12k_base *ab, u16 peer_id, u16 tid)
|
||||
|
|
@ -801,8 +796,8 @@ void ath12k_dp_rx_peer_tid_delete(struct ath12k *ar,
|
|||
return;
|
||||
|
||||
cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS;
|
||||
cmd.addr_lo = lower_32_bits(rx_tid->paddr);
|
||||
cmd.addr_hi = upper_32_bits(rx_tid->paddr);
|
||||
cmd.addr_lo = lower_32_bits(rx_tid->qbuf.paddr_aligned);
|
||||
cmd.addr_hi = upper_32_bits(rx_tid->qbuf.paddr_aligned);
|
||||
cmd.upd0 = HAL_REO_CMD_UPD0_VLD;
|
||||
ret = ath12k_dp_reo_cmd_send(ar->ab, rx_tid,
|
||||
HAL_REO_CMD_UPDATE_RX_QUEUE, &cmd,
|
||||
|
|
@ -810,10 +805,10 @@ void ath12k_dp_rx_peer_tid_delete(struct ath12k *ar,
|
|||
if (ret) {
|
||||
ath12k_err(ar->ab, "failed to send HAL_REO_CMD_UPDATE_RX_QUEUE cmd, tid %d (%d)\n",
|
||||
tid, ret);
|
||||
dma_unmap_single(ar->ab->dev, rx_tid->paddr, rx_tid->size,
|
||||
DMA_BIDIRECTIONAL);
|
||||
kfree(rx_tid->vaddr);
|
||||
rx_tid->vaddr = NULL;
|
||||
dma_unmap_single(ar->ab->dev, rx_tid->qbuf.paddr_aligned,
|
||||
rx_tid->qbuf.size, DMA_BIDIRECTIONAL);
|
||||
kfree(rx_tid->qbuf.vaddr);
|
||||
rx_tid->qbuf.vaddr = NULL;
|
||||
}
|
||||
|
||||
if (peer->mlo)
|
||||
|
|
@ -909,8 +904,8 @@ static int ath12k_peer_rx_tid_reo_update(struct ath12k *ar,
|
|||
struct ath12k_hal_reo_cmd cmd = {0};
|
||||
int ret;
|
||||
|
||||
cmd.addr_lo = lower_32_bits(rx_tid->paddr);
|
||||
cmd.addr_hi = upper_32_bits(rx_tid->paddr);
|
||||
cmd.addr_lo = lower_32_bits(rx_tid->qbuf.paddr_aligned);
|
||||
cmd.addr_hi = upper_32_bits(rx_tid->qbuf.paddr_aligned);
|
||||
cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS;
|
||||
cmd.upd0 = HAL_REO_CMD_UPD0_BA_WINDOW_SIZE;
|
||||
cmd.ba_window_size = ba_win_sz;
|
||||
|
|
@ -934,18 +929,67 @@ static int ath12k_peer_rx_tid_reo_update(struct ath12k *ar,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ath12k_dp_rx_assign_reoq(struct ath12k_base *ab,
|
||||
struct ath12k_sta *ahsta,
|
||||
struct ath12k_dp_rx_tid *rx_tid,
|
||||
u16 ssn, enum hal_pn_type pn_type)
|
||||
{
|
||||
u32 ba_win_sz = rx_tid->ba_win_sz;
|
||||
struct ath12k_reoq_buf *buf;
|
||||
void *vaddr, *vaddr_aligned;
|
||||
dma_addr_t paddr_aligned;
|
||||
u8 tid = rx_tid->tid;
|
||||
u32 hw_desc_sz;
|
||||
int ret;
|
||||
|
||||
buf = &ahsta->reoq_bufs[tid];
|
||||
if (!buf->vaddr) {
|
||||
/* TODO: Optimize the memory allocation for qos tid based on
|
||||
* the actual BA window size in REO tid update path.
|
||||
*/
|
||||
if (tid == HAL_DESC_REO_NON_QOS_TID)
|
||||
hw_desc_sz = ath12k_hal_reo_qdesc_size(ba_win_sz, tid);
|
||||
else
|
||||
hw_desc_sz = ath12k_hal_reo_qdesc_size(DP_BA_WIN_SZ_MAX, tid);
|
||||
|
||||
vaddr = kzalloc(hw_desc_sz + HAL_LINK_DESC_ALIGN - 1, GFP_ATOMIC);
|
||||
if (!vaddr)
|
||||
return -ENOMEM;
|
||||
|
||||
vaddr_aligned = PTR_ALIGN(vaddr, HAL_LINK_DESC_ALIGN);
|
||||
|
||||
ath12k_hal_reo_qdesc_setup(vaddr_aligned, tid, ba_win_sz,
|
||||
ssn, pn_type);
|
||||
|
||||
paddr_aligned = dma_map_single(ab->dev, vaddr_aligned, hw_desc_sz,
|
||||
DMA_BIDIRECTIONAL);
|
||||
ret = dma_mapping_error(ab->dev, paddr_aligned);
|
||||
if (ret) {
|
||||
kfree(vaddr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
buf->vaddr = vaddr;
|
||||
buf->paddr_aligned = paddr_aligned;
|
||||
buf->size = hw_desc_sz;
|
||||
}
|
||||
|
||||
rx_tid->qbuf = *buf;
|
||||
rx_tid->active = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_id,
|
||||
u8 tid, u32 ba_win_sz, u16 ssn,
|
||||
enum hal_pn_type pn_type)
|
||||
{
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
struct ath12k_dp *dp = &ab->dp;
|
||||
struct hal_rx_reo_queue *addr_aligned;
|
||||
struct ath12k_peer *peer;
|
||||
struct ath12k_sta *ahsta;
|
||||
struct ath12k_dp_rx_tid *rx_tid;
|
||||
u32 hw_desc_sz;
|
||||
void *vaddr;
|
||||
dma_addr_t paddr;
|
||||
dma_addr_t paddr_aligned;
|
||||
int ret;
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
|
|
@ -957,7 +1001,8 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (!peer->primary_link) {
|
||||
if (ab->hw_params->dp_primary_link_only &&
|
||||
!peer->primary_link) {
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -977,9 +1022,9 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_
|
|||
}
|
||||
|
||||
rx_tid = &peer->rx_tid[tid];
|
||||
paddr_aligned = rx_tid->qbuf.paddr_aligned;
|
||||
/* Update the tid queue if it is already setup */
|
||||
if (rx_tid->active) {
|
||||
paddr = rx_tid->paddr;
|
||||
ret = ath12k_peer_rx_tid_reo_update(ar, peer, rx_tid,
|
||||
ba_win_sz, ssn, true);
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
|
@ -991,8 +1036,8 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_
|
|||
if (!ab->hw_params->reoq_lut_support) {
|
||||
ret = ath12k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id,
|
||||
peer_mac,
|
||||
paddr, tid, 1,
|
||||
ba_win_sz);
|
||||
paddr_aligned, tid,
|
||||
1, ba_win_sz);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to setup peer rx reorder queuefor tid %d: %d\n",
|
||||
tid, ret);
|
||||
|
|
@ -1007,60 +1052,33 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_
|
|||
|
||||
rx_tid->ba_win_sz = ba_win_sz;
|
||||
|
||||
/* TODO: Optimize the memory allocation for qos tid based on
|
||||
* the actual BA window size in REO tid update path.
|
||||
*/
|
||||
if (tid == HAL_DESC_REO_NON_QOS_TID)
|
||||
hw_desc_sz = ath12k_hal_reo_qdesc_size(ba_win_sz, tid);
|
||||
else
|
||||
hw_desc_sz = ath12k_hal_reo_qdesc_size(DP_BA_WIN_SZ_MAX, tid);
|
||||
|
||||
vaddr = kzalloc(hw_desc_sz + HAL_LINK_DESC_ALIGN - 1, GFP_ATOMIC);
|
||||
if (!vaddr) {
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
addr_aligned = PTR_ALIGN(vaddr, HAL_LINK_DESC_ALIGN);
|
||||
|
||||
ath12k_hal_reo_qdesc_setup(addr_aligned, tid, ba_win_sz,
|
||||
ssn, pn_type);
|
||||
|
||||
paddr = dma_map_single(ab->dev, addr_aligned, hw_desc_sz,
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
||||
ret = dma_mapping_error(ab->dev, paddr);
|
||||
ahsta = ath12k_sta_to_ahsta(peer->sta);
|
||||
ret = ath12k_dp_rx_assign_reoq(ab, ahsta, rx_tid, ssn, pn_type);
|
||||
if (ret) {
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
goto err_mem_free;
|
||||
ath12k_warn(ab, "failed to assign reoq buf for rx tid %u\n", tid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
rx_tid->vaddr = vaddr;
|
||||
rx_tid->paddr = paddr;
|
||||
rx_tid->size = hw_desc_sz;
|
||||
rx_tid->active = true;
|
||||
|
||||
if (ab->hw_params->reoq_lut_support) {
|
||||
/* Update the REO queue LUT at the corresponding peer id
|
||||
* and tid with qaddr.
|
||||
*/
|
||||
if (peer->mlo)
|
||||
ath12k_peer_rx_tid_qref_setup(ab, peer->ml_id, tid, paddr);
|
||||
ath12k_peer_rx_tid_qref_setup(ab, peer->ml_id, tid,
|
||||
paddr_aligned);
|
||||
else
|
||||
ath12k_peer_rx_tid_qref_setup(ab, peer->peer_id, tid, paddr);
|
||||
ath12k_peer_rx_tid_qref_setup(ab, peer->peer_id, tid,
|
||||
paddr_aligned);
|
||||
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
} else {
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
ret = ath12k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, peer_mac,
|
||||
paddr, tid, 1, ba_win_sz);
|
||||
paddr_aligned, tid, 1,
|
||||
ba_win_sz);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
err_mem_free:
|
||||
kfree(vaddr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1196,8 +1214,8 @@ int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif,
|
|||
rx_tid = &peer->rx_tid[tid];
|
||||
if (!rx_tid->active)
|
||||
continue;
|
||||
cmd.addr_lo = lower_32_bits(rx_tid->paddr);
|
||||
cmd.addr_hi = upper_32_bits(rx_tid->paddr);
|
||||
cmd.addr_lo = lower_32_bits(rx_tid->qbuf.paddr_aligned);
|
||||
cmd.addr_hi = upper_32_bits(rx_tid->qbuf.paddr_aligned);
|
||||
ret = ath12k_dp_reo_cmd_send(ab, rx_tid,
|
||||
HAL_REO_CMD_UPDATE_RX_QUEUE,
|
||||
&cmd, NULL);
|
||||
|
|
@ -1823,6 +1841,7 @@ static int ath12k_dp_rx_msdu_coalesce(struct ath12k *ar,
|
|||
struct hal_rx_desc *ldesc;
|
||||
int space_extra, rem_len, buf_len;
|
||||
u32 hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
|
||||
bool is_continuation;
|
||||
|
||||
/* As the msdu is spread across multiple rx buffers,
|
||||
* find the offset to the start of msdu for computing
|
||||
|
|
@ -1871,7 +1890,8 @@ static int ath12k_dp_rx_msdu_coalesce(struct ath12k *ar,
|
|||
rem_len = msdu_len - buf_first_len;
|
||||
while ((skb = __skb_dequeue(msdu_list)) != NULL && rem_len > 0) {
|
||||
rxcb = ATH12K_SKB_RXCB(skb);
|
||||
if (rxcb->is_continuation)
|
||||
is_continuation = rxcb->is_continuation;
|
||||
if (is_continuation)
|
||||
buf_len = DP_RX_BUFFER_SIZE - hal_rx_desc_sz;
|
||||
else
|
||||
buf_len = rem_len;
|
||||
|
|
@ -1889,7 +1909,7 @@ static int ath12k_dp_rx_msdu_coalesce(struct ath12k *ar,
|
|||
dev_kfree_skb_any(skb);
|
||||
|
||||
rem_len -= buf_len;
|
||||
if (!rxcb->is_continuation)
|
||||
if (!is_continuation)
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1914,21 +1934,14 @@ static struct sk_buff *ath12k_dp_rx_get_msdu_last_buf(struct sk_buff_head *msdu_
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void ath12k_dp_rx_h_csum_offload(struct ath12k *ar, struct sk_buff *msdu)
|
||||
static void ath12k_dp_rx_h_csum_offload(struct sk_buff *msdu,
|
||||
struct ath12k_dp_rx_info *rx_info)
|
||||
{
|
||||
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
bool ip_csum_fail, l4_csum_fail;
|
||||
|
||||
ip_csum_fail = ath12k_dp_rx_h_ip_cksum_fail(ab, rxcb->rx_desc);
|
||||
l4_csum_fail = ath12k_dp_rx_h_l4_cksum_fail(ab, rxcb->rx_desc);
|
||||
|
||||
msdu->ip_summed = (ip_csum_fail || l4_csum_fail) ?
|
||||
CHECKSUM_NONE : CHECKSUM_UNNECESSARY;
|
||||
msdu->ip_summed = (rx_info->ip_csum_fail || rx_info->l4_csum_fail) ?
|
||||
CHECKSUM_NONE : CHECKSUM_UNNECESSARY;
|
||||
}
|
||||
|
||||
static int ath12k_dp_rx_crypto_mic_len(struct ath12k *ar,
|
||||
enum hal_encrypt_type enctype)
|
||||
int ath12k_dp_rx_crypto_mic_len(struct ath12k *ar, enum hal_encrypt_type enctype)
|
||||
{
|
||||
switch (enctype) {
|
||||
case HAL_ENCRYPT_TYPE_OPEN:
|
||||
|
|
@ -2122,10 +2135,13 @@ static void ath12k_get_dot11_hdr_from_rx_desc(struct ath12k *ar,
|
|||
struct hal_rx_desc *rx_desc = rxcb->rx_desc;
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
size_t hdr_len, crypto_len;
|
||||
struct ieee80211_hdr *hdr;
|
||||
u16 qos_ctl;
|
||||
__le16 fc;
|
||||
u8 *crypto_hdr;
|
||||
struct ieee80211_hdr hdr;
|
||||
__le16 qos_ctl;
|
||||
u8 *crypto_hdr, mesh_ctrl;
|
||||
|
||||
ath12k_dp_rx_desc_get_dot11_hdr(ab, rx_desc, &hdr);
|
||||
hdr_len = ieee80211_hdrlen(hdr.frame_control);
|
||||
mesh_ctrl = ath12k_dp_rx_h_mesh_ctl_present(ab, rx_desc);
|
||||
|
||||
if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
|
||||
crypto_len = ath12k_dp_rx_crypto_param_len(ar, enctype);
|
||||
|
|
@ -2133,27 +2149,21 @@ static void ath12k_get_dot11_hdr_from_rx_desc(struct ath12k *ar,
|
|||
ath12k_dp_rx_desc_get_crypto_header(ab, rx_desc, crypto_hdr, enctype);
|
||||
}
|
||||
|
||||
fc = cpu_to_le16(ath12k_dp_rxdesc_get_mpdu_frame_ctrl(ab, rx_desc));
|
||||
hdr_len = ieee80211_hdrlen(fc);
|
||||
skb_push(msdu, hdr_len);
|
||||
hdr = (struct ieee80211_hdr *)msdu->data;
|
||||
hdr->frame_control = fc;
|
||||
|
||||
/* Get wifi header from rx_desc */
|
||||
ath12k_dp_rx_desc_get_dot11_hdr(ab, rx_desc, hdr);
|
||||
memcpy(msdu->data, &hdr, min(hdr_len, sizeof(hdr)));
|
||||
|
||||
if (rxcb->is_mcbc)
|
||||
status->flag &= ~RX_FLAG_PN_VALIDATED;
|
||||
|
||||
/* Add QOS header */
|
||||
if (ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
qos_ctl = rxcb->tid;
|
||||
if (ath12k_dp_rx_h_mesh_ctl_present(ab, rx_desc))
|
||||
qos_ctl |= IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT;
|
||||
if (ieee80211_is_data_qos(hdr.frame_control)) {
|
||||
struct ieee80211_hdr *qos_ptr = (struct ieee80211_hdr *)msdu->data;
|
||||
|
||||
/* TODO: Add other QoS ctl fields when required */
|
||||
memcpy(msdu->data + (hdr_len - IEEE80211_QOS_CTL_LEN),
|
||||
&qos_ctl, IEEE80211_QOS_CTL_LEN);
|
||||
qos_ctl = cpu_to_le16(rxcb->tid & IEEE80211_QOS_CTL_TID_MASK);
|
||||
if (mesh_ctrl)
|
||||
qos_ctl |= cpu_to_le16(IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT);
|
||||
|
||||
memcpy(ieee80211_get_qos_ctl(qos_ptr), &qos_ctl, IEEE80211_QOS_CTL_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2229,10 +2239,10 @@ static void ath12k_dp_rx_h_undecap(struct ath12k *ar, struct sk_buff *msdu,
|
|||
}
|
||||
|
||||
struct ath12k_peer *
|
||||
ath12k_dp_rx_h_find_peer(struct ath12k_base *ab, struct sk_buff *msdu)
|
||||
ath12k_dp_rx_h_find_peer(struct ath12k_base *ab, struct sk_buff *msdu,
|
||||
struct ath12k_dp_rx_info *rx_info)
|
||||
{
|
||||
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
|
||||
struct hal_rx_desc *rx_desc = rxcb->rx_desc;
|
||||
struct ath12k_peer *peer = NULL;
|
||||
|
||||
lockdep_assert_held(&ab->base_lock);
|
||||
|
|
@ -2243,40 +2253,41 @@ ath12k_dp_rx_h_find_peer(struct ath12k_base *ab, struct sk_buff *msdu)
|
|||
if (peer)
|
||||
return peer;
|
||||
|
||||
if (!rx_desc || !(ath12k_dp_rxdesc_mac_addr2_valid(ab, rx_desc)))
|
||||
return NULL;
|
||||
if (rx_info->addr2_present)
|
||||
peer = ath12k_peer_find_by_addr(ab, rx_info->addr2);
|
||||
|
||||
peer = ath12k_peer_find_by_addr(ab,
|
||||
ath12k_dp_rxdesc_get_mpdu_start_addr2(ab,
|
||||
rx_desc));
|
||||
return peer;
|
||||
}
|
||||
|
||||
static void ath12k_dp_rx_h_mpdu(struct ath12k *ar,
|
||||
struct sk_buff *msdu,
|
||||
struct hal_rx_desc *rx_desc,
|
||||
struct ieee80211_rx_status *rx_status)
|
||||
struct ath12k_dp_rx_info *rx_info)
|
||||
{
|
||||
bool fill_crypto_hdr;
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
struct ath12k_skb_rxcb *rxcb;
|
||||
enum hal_encrypt_type enctype;
|
||||
bool is_decrypted = false;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ath12k_peer *peer;
|
||||
struct ieee80211_rx_status *rx_status = rx_info->rx_status;
|
||||
u32 err_bitmap;
|
||||
|
||||
/* PN for multicast packets will be checked in mac80211 */
|
||||
rxcb = ATH12K_SKB_RXCB(msdu);
|
||||
fill_crypto_hdr = ath12k_dp_rx_h_is_da_mcbc(ar->ab, rx_desc);
|
||||
rxcb->is_mcbc = fill_crypto_hdr;
|
||||
rxcb->is_mcbc = rx_info->is_mcbc;
|
||||
|
||||
if (rxcb->is_mcbc)
|
||||
rxcb->peer_id = ath12k_dp_rx_h_peer_id(ar->ab, rx_desc);
|
||||
rxcb->peer_id = rx_info->peer_id;
|
||||
|
||||
spin_lock_bh(&ar->ab->base_lock);
|
||||
peer = ath12k_dp_rx_h_find_peer(ar->ab, msdu);
|
||||
peer = ath12k_dp_rx_h_find_peer(ar->ab, msdu, rx_info);
|
||||
if (peer) {
|
||||
/* resetting mcbc bit because mcbc packets are unicast
|
||||
* packets only for AP as STA sends unicast packets.
|
||||
*/
|
||||
rxcb->is_mcbc = rxcb->is_mcbc && !peer->ucast_ra_only;
|
||||
|
||||
if (rxcb->is_mcbc)
|
||||
enctype = peer->sec_type_grp;
|
||||
else
|
||||
|
|
@ -2305,7 +2316,7 @@ static void ath12k_dp_rx_h_mpdu(struct ath12k *ar,
|
|||
if (is_decrypted) {
|
||||
rx_status->flag |= RX_FLAG_DECRYPTED | RX_FLAG_MMIC_STRIPPED;
|
||||
|
||||
if (fill_crypto_hdr)
|
||||
if (rx_info->is_mcbc)
|
||||
rx_status->flag |= RX_FLAG_MIC_STRIPPED |
|
||||
RX_FLAG_ICV_STRIPPED;
|
||||
else
|
||||
|
|
@ -2313,37 +2324,28 @@ static void ath12k_dp_rx_h_mpdu(struct ath12k *ar,
|
|||
RX_FLAG_PN_VALIDATED;
|
||||
}
|
||||
|
||||
ath12k_dp_rx_h_csum_offload(ar, msdu);
|
||||
ath12k_dp_rx_h_csum_offload(msdu, rx_info);
|
||||
ath12k_dp_rx_h_undecap(ar, msdu, rx_desc,
|
||||
enctype, rx_status, is_decrypted);
|
||||
|
||||
if (!is_decrypted || fill_crypto_hdr)
|
||||
if (!is_decrypted || rx_info->is_mcbc)
|
||||
return;
|
||||
|
||||
if (ath12k_dp_rx_h_decap_type(ar->ab, rx_desc) !=
|
||||
DP_RX_DECAP_TYPE_ETHERNET2_DIX) {
|
||||
if (rx_info->decap_type != DP_RX_DECAP_TYPE_ETHERNET2_DIX) {
|
||||
hdr = (void *)msdu->data;
|
||||
hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath12k_dp_rx_h_rate(struct ath12k *ar, struct hal_rx_desc *rx_desc,
|
||||
struct ieee80211_rx_status *rx_status)
|
||||
static void ath12k_dp_rx_h_rate(struct ath12k *ar, struct ath12k_dp_rx_info *rx_info)
|
||||
{
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
struct ieee80211_supported_band *sband;
|
||||
enum rx_msdu_start_pkt_type pkt_type;
|
||||
u8 bw;
|
||||
u8 rate_mcs, nss;
|
||||
u8 sgi;
|
||||
struct ieee80211_rx_status *rx_status = rx_info->rx_status;
|
||||
enum rx_msdu_start_pkt_type pkt_type = rx_info->pkt_type;
|
||||
u8 bw = rx_info->bw, sgi = rx_info->sgi;
|
||||
u8 rate_mcs = rx_info->rate_mcs, nss = rx_info->nss;
|
||||
bool is_cck;
|
||||
|
||||
pkt_type = ath12k_dp_rx_h_pkt_type(ab, rx_desc);
|
||||
bw = ath12k_dp_rx_h_rx_bw(ab, rx_desc);
|
||||
rate_mcs = ath12k_dp_rx_h_rate_mcs(ab, rx_desc);
|
||||
nss = ath12k_dp_rx_h_nss(ab, rx_desc);
|
||||
sgi = ath12k_dp_rx_h_sgi(ab, rx_desc);
|
||||
|
||||
switch (pkt_type) {
|
||||
case RX_MSDU_START_PKT_TYPE_11A:
|
||||
case RX_MSDU_START_PKT_TYPE_11B:
|
||||
|
|
@ -2412,10 +2414,35 @@ static void ath12k_dp_rx_h_rate(struct ath12k *ar, struct hal_rx_desc *rx_desc,
|
|||
}
|
||||
}
|
||||
|
||||
void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct hal_rx_desc *rx_desc,
|
||||
struct ieee80211_rx_status *rx_status)
|
||||
void ath12k_dp_rx_h_fetch_info(struct ath12k_base *ab, struct hal_rx_desc *rx_desc,
|
||||
struct ath12k_dp_rx_info *rx_info)
|
||||
{
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
rx_info->ip_csum_fail = ath12k_dp_rx_h_ip_cksum_fail(ab, rx_desc);
|
||||
rx_info->l4_csum_fail = ath12k_dp_rx_h_l4_cksum_fail(ab, rx_desc);
|
||||
rx_info->is_mcbc = ath12k_dp_rx_h_is_da_mcbc(ab, rx_desc);
|
||||
rx_info->decap_type = ath12k_dp_rx_h_decap_type(ab, rx_desc);
|
||||
rx_info->pkt_type = ath12k_dp_rx_h_pkt_type(ab, rx_desc);
|
||||
rx_info->sgi = ath12k_dp_rx_h_sgi(ab, rx_desc);
|
||||
rx_info->rate_mcs = ath12k_dp_rx_h_rate_mcs(ab, rx_desc);
|
||||
rx_info->bw = ath12k_dp_rx_h_rx_bw(ab, rx_desc);
|
||||
rx_info->nss = ath12k_dp_rx_h_nss(ab, rx_desc);
|
||||
rx_info->tid = ath12k_dp_rx_h_tid(ab, rx_desc);
|
||||
rx_info->peer_id = ath12k_dp_rx_h_peer_id(ab, rx_desc);
|
||||
rx_info->phy_meta_data = ath12k_dp_rx_h_freq(ab, rx_desc);
|
||||
|
||||
if (ath12k_dp_rxdesc_mac_addr2_valid(ab, rx_desc)) {
|
||||
ether_addr_copy(rx_info->addr2,
|
||||
ath12k_dp_rxdesc_get_mpdu_start_addr2(ab, rx_desc));
|
||||
rx_info->addr2_present = true;
|
||||
}
|
||||
|
||||
ath12k_dbg_dump(ab, ATH12K_DBG_DATA, NULL, "rx_desc: ",
|
||||
rx_desc, sizeof(*rx_desc));
|
||||
}
|
||||
|
||||
void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct ath12k_dp_rx_info *rx_info)
|
||||
{
|
||||
struct ieee80211_rx_status *rx_status = rx_info->rx_status;
|
||||
u8 channel_num;
|
||||
u32 center_freq, meta_data;
|
||||
struct ieee80211_channel *channel;
|
||||
|
|
@ -2429,12 +2456,12 @@ void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct hal_rx_desc *rx_desc,
|
|||
|
||||
rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
|
||||
|
||||
meta_data = ath12k_dp_rx_h_freq(ab, rx_desc);
|
||||
meta_data = rx_info->phy_meta_data;
|
||||
channel_num = meta_data;
|
||||
center_freq = meta_data >> 16;
|
||||
|
||||
if (center_freq >= ATH12K_MIN_6G_FREQ &&
|
||||
center_freq <= ATH12K_MAX_6G_FREQ) {
|
||||
if (center_freq >= ATH12K_MIN_6GHZ_FREQ &&
|
||||
center_freq <= ATH12K_MAX_6GHZ_FREQ) {
|
||||
rx_status->band = NL80211_BAND_6GHZ;
|
||||
rx_status->freq = center_freq;
|
||||
} else if (channel_num >= 1 && channel_num <= 14) {
|
||||
|
|
@ -2450,20 +2477,18 @@ void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct hal_rx_desc *rx_desc,
|
|||
ieee80211_frequency_to_channel(channel->center_freq);
|
||||
}
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
ath12k_dbg_dump(ar->ab, ATH12K_DBG_DATA, NULL, "rx_desc: ",
|
||||
rx_desc, sizeof(*rx_desc));
|
||||
}
|
||||
|
||||
if (rx_status->band != NL80211_BAND_6GHZ)
|
||||
rx_status->freq = ieee80211_channel_to_frequency(channel_num,
|
||||
rx_status->band);
|
||||
|
||||
ath12k_dp_rx_h_rate(ar, rx_desc, rx_status);
|
||||
ath12k_dp_rx_h_rate(ar, rx_info);
|
||||
}
|
||||
|
||||
static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *napi,
|
||||
struct sk_buff *msdu,
|
||||
struct ieee80211_rx_status *status)
|
||||
struct ath12k_dp_rx_info *rx_info)
|
||||
{
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
static const struct ieee80211_radiotap_he known = {
|
||||
|
|
@ -2476,6 +2501,7 @@ static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *nap
|
|||
struct ieee80211_sta *pubsta;
|
||||
struct ath12k_peer *peer;
|
||||
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
|
||||
struct ieee80211_rx_status *status = rx_info->rx_status;
|
||||
u8 decap = DP_RX_DECAP_TYPE_RAW;
|
||||
bool is_mcbc = rxcb->is_mcbc;
|
||||
bool is_eapol = rxcb->is_eapol;
|
||||
|
|
@ -2488,10 +2514,10 @@ static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *nap
|
|||
}
|
||||
|
||||
if (!(status->flag & RX_FLAG_ONLY_MONITOR))
|
||||
decap = ath12k_dp_rx_h_decap_type(ab, rxcb->rx_desc);
|
||||
decap = rx_info->decap_type;
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
peer = ath12k_dp_rx_h_find_peer(ab, msdu);
|
||||
peer = ath12k_dp_rx_h_find_peer(ab, msdu, rx_info);
|
||||
|
||||
pubsta = peer ? peer->sta : NULL;
|
||||
|
||||
|
|
@ -2574,7 +2600,7 @@ static bool ath12k_dp_rx_check_nwifi_hdr_len_valid(struct ath12k_base *ab,
|
|||
static int ath12k_dp_rx_process_msdu(struct ath12k *ar,
|
||||
struct sk_buff *msdu,
|
||||
struct sk_buff_head *msdu_list,
|
||||
struct ieee80211_rx_status *rx_status)
|
||||
struct ath12k_dp_rx_info *rx_info)
|
||||
{
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
struct hal_rx_desc *rx_desc, *lrx_desc;
|
||||
|
|
@ -2634,10 +2660,11 @@ static int ath12k_dp_rx_process_msdu(struct ath12k *ar,
|
|||
goto free_out;
|
||||
}
|
||||
|
||||
ath12k_dp_rx_h_ppdu(ar, rx_desc, rx_status);
|
||||
ath12k_dp_rx_h_mpdu(ar, msdu, rx_desc, rx_status);
|
||||
ath12k_dp_rx_h_fetch_info(ab, rx_desc, rx_info);
|
||||
ath12k_dp_rx_h_ppdu(ar, rx_info);
|
||||
ath12k_dp_rx_h_mpdu(ar, msdu, rx_desc, rx_info);
|
||||
|
||||
rx_status->flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED;
|
||||
rx_info->rx_status->flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED;
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
@ -2657,12 +2684,16 @@ static void ath12k_dp_rx_process_received_packets(struct ath12k_base *ab,
|
|||
struct ath12k *ar;
|
||||
struct ath12k_hw_link *hw_links = ag->hw_links;
|
||||
struct ath12k_base *partner_ab;
|
||||
struct ath12k_dp_rx_info rx_info;
|
||||
u8 hw_link_id, pdev_id;
|
||||
int ret;
|
||||
|
||||
if (skb_queue_empty(msdu_list))
|
||||
return;
|
||||
|
||||
rx_info.addr2_present = false;
|
||||
rx_info.rx_status = &rx_status;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
while ((msdu = __skb_dequeue(msdu_list))) {
|
||||
|
|
@ -2683,7 +2714,7 @@ static void ath12k_dp_rx_process_received_packets(struct ath12k_base *ab,
|
|||
continue;
|
||||
}
|
||||
|
||||
ret = ath12k_dp_rx_process_msdu(ar, msdu, msdu_list, &rx_status);
|
||||
ret = ath12k_dp_rx_process_msdu(ar, msdu, msdu_list, &rx_info);
|
||||
if (ret) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_DATA,
|
||||
"Unable to process msdu %d", ret);
|
||||
|
|
@ -2691,7 +2722,7 @@ static void ath12k_dp_rx_process_received_packets(struct ath12k_base *ab,
|
|||
continue;
|
||||
}
|
||||
|
||||
ath12k_dp_rx_deliver_msdu(ar, napi, msdu, &rx_status);
|
||||
ath12k_dp_rx_deliver_msdu(ar, napi, msdu, &rx_info);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
|
@ -2984,6 +3015,7 @@ static int ath12k_dp_rx_h_verify_tkip_mic(struct ath12k *ar, struct ath12k_peer
|
|||
struct ieee80211_rx_status *rxs = IEEE80211_SKB_RXCB(msdu);
|
||||
struct ieee80211_key_conf *key_conf;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ath12k_dp_rx_info rx_info;
|
||||
u8 mic[IEEE80211_CCMP_MIC_LEN];
|
||||
int head_len, tail_len, ret;
|
||||
size_t data_len;
|
||||
|
|
@ -2994,6 +3026,9 @@ static int ath12k_dp_rx_h_verify_tkip_mic(struct ath12k *ar, struct ath12k_peer
|
|||
if (ath12k_dp_rx_h_enctype(ab, rx_desc) != HAL_ENCRYPT_TYPE_TKIP_MIC)
|
||||
return 0;
|
||||
|
||||
rx_info.addr2_present = false;
|
||||
rx_info.rx_status = rxs;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)(msdu->data + hal_rx_desc_sz);
|
||||
hdr_len = ieee80211_hdrlen(hdr->frame_control);
|
||||
head_len = hdr_len + hal_rx_desc_sz + IEEE80211_TKIP_IV_LEN;
|
||||
|
|
@ -3020,6 +3055,8 @@ static int ath12k_dp_rx_h_verify_tkip_mic(struct ath12k *ar, struct ath12k_peer
|
|||
(ATH12K_SKB_RXCB(msdu))->is_first_msdu = true;
|
||||
(ATH12K_SKB_RXCB(msdu))->is_last_msdu = true;
|
||||
|
||||
ath12k_dp_rx_h_fetch_info(ab, rx_desc, &rx_info);
|
||||
|
||||
rxs->flag |= RX_FLAG_MMIC_ERROR | RX_FLAG_MMIC_STRIPPED |
|
||||
RX_FLAG_IV_STRIPPED | RX_FLAG_DECRYPTED;
|
||||
skb_pull(msdu, hal_rx_desc_sz);
|
||||
|
|
@ -3027,7 +3064,7 @@ static int ath12k_dp_rx_h_verify_tkip_mic(struct ath12k *ar, struct ath12k_peer
|
|||
if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(ab, rx_desc, msdu)))
|
||||
return -EINVAL;
|
||||
|
||||
ath12k_dp_rx_h_ppdu(ar, rx_desc, rxs);
|
||||
ath12k_dp_rx_h_ppdu(ar, &rx_info);
|
||||
ath12k_dp_rx_h_undecap(ar, msdu, rx_desc,
|
||||
HAL_ENCRYPT_TYPE_TKIP_MIC, rxs, true);
|
||||
ieee80211_rx(ath12k_ar_to_hw(ar), msdu);
|
||||
|
|
@ -3242,8 +3279,15 @@ static int ath12k_dp_rx_h_defrag_reo_reinject(struct ath12k *ar,
|
|||
reo_ent_ring->rx_mpdu_info.peer_meta_data =
|
||||
reo_dest_ring->rx_mpdu_info.peer_meta_data;
|
||||
|
||||
reo_ent_ring->queue_addr_lo = cpu_to_le32(lower_32_bits(rx_tid->paddr));
|
||||
queue_addr_hi = upper_32_bits(rx_tid->paddr);
|
||||
if (ab->hw_params->reoq_lut_support) {
|
||||
reo_ent_ring->queue_addr_lo = reo_dest_ring->rx_mpdu_info.peer_meta_data;
|
||||
queue_addr_hi = 0;
|
||||
} else {
|
||||
reo_ent_ring->queue_addr_lo =
|
||||
cpu_to_le32(lower_32_bits(rx_tid->qbuf.paddr_aligned));
|
||||
queue_addr_hi = upper_32_bits(rx_tid->qbuf.paddr_aligned);
|
||||
}
|
||||
|
||||
reo_ent_ring->info0 = le32_encode_bits(queue_addr_hi,
|
||||
HAL_REO_ENTR_RING_INFO0_QUEUE_ADDR_HI) |
|
||||
le32_encode_bits(dst_ind,
|
||||
|
|
@ -3716,7 +3760,7 @@ static void ath12k_dp_rx_null_q_desc_sg_drop(struct ath12k *ar,
|
|||
}
|
||||
|
||||
static int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu,
|
||||
struct ieee80211_rx_status *status,
|
||||
struct ath12k_dp_rx_info *rx_info,
|
||||
struct sk_buff_head *msdu_list)
|
||||
{
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
|
|
@ -3772,11 +3816,11 @@ static int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu,
|
|||
if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(ab, desc, msdu)))
|
||||
return -EINVAL;
|
||||
|
||||
ath12k_dp_rx_h_ppdu(ar, desc, status);
|
||||
ath12k_dp_rx_h_fetch_info(ab, desc, rx_info);
|
||||
ath12k_dp_rx_h_ppdu(ar, rx_info);
|
||||
ath12k_dp_rx_h_mpdu(ar, msdu, desc, rx_info);
|
||||
|
||||
ath12k_dp_rx_h_mpdu(ar, msdu, desc, status);
|
||||
|
||||
rxcb->tid = ath12k_dp_rx_h_tid(ab, desc);
|
||||
rxcb->tid = rx_info->tid;
|
||||
|
||||
/* Please note that caller will having the access to msdu and completing
|
||||
* rx with mac80211. Need not worry about cleaning up amsdu_list.
|
||||
|
|
@ -3786,7 +3830,7 @@ static int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu,
|
|||
}
|
||||
|
||||
static bool ath12k_dp_rx_h_reo_err(struct ath12k *ar, struct sk_buff *msdu,
|
||||
struct ieee80211_rx_status *status,
|
||||
struct ath12k_dp_rx_info *rx_info,
|
||||
struct sk_buff_head *msdu_list)
|
||||
{
|
||||
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
|
||||
|
|
@ -3796,7 +3840,7 @@ static bool ath12k_dp_rx_h_reo_err(struct ath12k *ar, struct sk_buff *msdu,
|
|||
|
||||
switch (rxcb->err_code) {
|
||||
case HAL_REO_DEST_RING_ERROR_CODE_DESC_ADDR_ZERO:
|
||||
if (ath12k_dp_rx_h_null_q_desc(ar, msdu, status, msdu_list))
|
||||
if (ath12k_dp_rx_h_null_q_desc(ar, msdu, rx_info, msdu_list))
|
||||
drop = true;
|
||||
break;
|
||||
case HAL_REO_DEST_RING_ERROR_CODE_PN_CHECK_FAILED:
|
||||
|
|
@ -3817,7 +3861,7 @@ static bool ath12k_dp_rx_h_reo_err(struct ath12k *ar, struct sk_buff *msdu,
|
|||
}
|
||||
|
||||
static bool ath12k_dp_rx_h_tkip_mic_err(struct ath12k *ar, struct sk_buff *msdu,
|
||||
struct ieee80211_rx_status *status)
|
||||
struct ath12k_dp_rx_info *rx_info)
|
||||
{
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
u16 msdu_len;
|
||||
|
|
@ -3831,24 +3875,33 @@ static bool ath12k_dp_rx_h_tkip_mic_err(struct ath12k *ar, struct sk_buff *msdu,
|
|||
|
||||
l3pad_bytes = ath12k_dp_rx_h_l3pad(ab, desc);
|
||||
msdu_len = ath12k_dp_rx_h_msdu_len(ab, desc);
|
||||
|
||||
if ((hal_rx_desc_sz + l3pad_bytes + msdu_len) > DP_RX_BUFFER_SIZE) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_DATA,
|
||||
"invalid msdu len in tkip mic err %u\n", msdu_len);
|
||||
ath12k_dbg_dump(ab, ATH12K_DBG_DATA, NULL, "", desc,
|
||||
sizeof(*desc));
|
||||
return true;
|
||||
}
|
||||
|
||||
skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len);
|
||||
skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes);
|
||||
|
||||
if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(ab, desc, msdu)))
|
||||
return true;
|
||||
|
||||
ath12k_dp_rx_h_ppdu(ar, desc, status);
|
||||
ath12k_dp_rx_h_ppdu(ar, rx_info);
|
||||
|
||||
status->flag |= (RX_FLAG_MMIC_STRIPPED | RX_FLAG_MMIC_ERROR |
|
||||
RX_FLAG_DECRYPTED);
|
||||
rx_info->rx_status->flag |= (RX_FLAG_MMIC_STRIPPED | RX_FLAG_MMIC_ERROR |
|
||||
RX_FLAG_DECRYPTED);
|
||||
|
||||
ath12k_dp_rx_h_undecap(ar, msdu, desc,
|
||||
HAL_ENCRYPT_TYPE_TKIP_MIC, status, false);
|
||||
HAL_ENCRYPT_TYPE_TKIP_MIC, rx_info->rx_status, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ath12k_dp_rx_h_rxdma_err(struct ath12k *ar, struct sk_buff *msdu,
|
||||
struct ieee80211_rx_status *status)
|
||||
struct ath12k_dp_rx_info *rx_info)
|
||||
{
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
|
||||
|
|
@ -3863,7 +3916,8 @@ static bool ath12k_dp_rx_h_rxdma_err(struct ath12k *ar, struct sk_buff *msdu,
|
|||
case HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR:
|
||||
err_bitmap = ath12k_dp_rx_h_mpdu_err(ab, rx_desc);
|
||||
if (err_bitmap & HAL_RX_MPDU_ERR_TKIP_MIC) {
|
||||
drop = ath12k_dp_rx_h_tkip_mic_err(ar, msdu, status);
|
||||
ath12k_dp_rx_h_fetch_info(ab, rx_desc, rx_info);
|
||||
drop = ath12k_dp_rx_h_tkip_mic_err(ar, msdu, rx_info);
|
||||
break;
|
||||
}
|
||||
fallthrough;
|
||||
|
|
@ -3885,14 +3939,18 @@ static void ath12k_dp_rx_wbm_err(struct ath12k *ar,
|
|||
{
|
||||
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
|
||||
struct ieee80211_rx_status rxs = {0};
|
||||
struct ath12k_dp_rx_info rx_info;
|
||||
bool drop = true;
|
||||
|
||||
rx_info.addr2_present = false;
|
||||
rx_info.rx_status = &rxs;
|
||||
|
||||
switch (rxcb->err_rel_src) {
|
||||
case HAL_WBM_REL_SRC_MODULE_REO:
|
||||
drop = ath12k_dp_rx_h_reo_err(ar, msdu, &rxs, msdu_list);
|
||||
drop = ath12k_dp_rx_h_reo_err(ar, msdu, &rx_info, msdu_list);
|
||||
break;
|
||||
case HAL_WBM_REL_SRC_MODULE_RXDMA:
|
||||
drop = ath12k_dp_rx_h_rxdma_err(ar, msdu, &rxs);
|
||||
drop = ath12k_dp_rx_h_rxdma_err(ar, msdu, &rx_info);
|
||||
break;
|
||||
default:
|
||||
/* msdu will get freed */
|
||||
|
|
@ -3904,7 +3962,7 @@ static void ath12k_dp_rx_wbm_err(struct ath12k *ar,
|
|||
return;
|
||||
}
|
||||
|
||||
ath12k_dp_rx_deliver_msdu(ar, napi, msdu, &rxs);
|
||||
ath12k_dp_rx_deliver_msdu(ar, napi, msdu, &rx_info);
|
||||
}
|
||||
|
||||
int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
|
||||
|
|
@ -4480,6 +4538,8 @@ int ath12k_dp_rx_pdev_mon_attach(struct ath12k *ar)
|
|||
|
||||
pmon->mon_last_linkdesc_paddr = 0;
|
||||
pmon->mon_last_buf_cookie = DP_RX_DESC_COOKIE_MAX + 1;
|
||||
INIT_LIST_HEAD(&pmon->dp_rx_mon_mpdu_list);
|
||||
pmon->mon_mpdu = NULL;
|
||||
spin_lock_init(&pmon->mon_lock);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -14,11 +14,9 @@
|
|||
|
||||
struct ath12k_dp_rx_tid {
|
||||
u8 tid;
|
||||
u32 *vaddr;
|
||||
dma_addr_t paddr;
|
||||
u32 size;
|
||||
u32 ba_win_sz;
|
||||
bool active;
|
||||
struct ath12k_reoq_buf qbuf;
|
||||
|
||||
/* Info related to rx fragments */
|
||||
u32 cur_sn;
|
||||
|
|
@ -65,6 +63,24 @@ struct ath12k_dp_rx_rfc1042_hdr {
|
|||
__be16 snap_type;
|
||||
} __packed;
|
||||
|
||||
struct ath12k_dp_rx_info {
|
||||
struct ieee80211_rx_status *rx_status;
|
||||
u32 phy_meta_data;
|
||||
u16 peer_id;
|
||||
u8 decap_type;
|
||||
u8 pkt_type;
|
||||
u8 sgi;
|
||||
u8 rate_mcs;
|
||||
u8 bw;
|
||||
u8 nss;
|
||||
u8 addr2[ETH_ALEN];
|
||||
u8 tid;
|
||||
bool ip_csum_fail;
|
||||
bool l4_csum_fail;
|
||||
bool is_mcbc;
|
||||
bool addr2_present;
|
||||
};
|
||||
|
||||
static inline u32 ath12k_he_gi_to_nl80211_he_gi(u8 sgi)
|
||||
{
|
||||
u32 ret = 0;
|
||||
|
|
@ -131,13 +147,13 @@ int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev
|
|||
u8 ath12k_dp_rx_h_l3pad(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc);
|
||||
struct ath12k_peer *
|
||||
ath12k_dp_rx_h_find_peer(struct ath12k_base *ab, struct sk_buff *msdu);
|
||||
ath12k_dp_rx_h_find_peer(struct ath12k_base *ab, struct sk_buff *msdu,
|
||||
struct ath12k_dp_rx_info *rx_info);
|
||||
u8 ath12k_dp_rx_h_decap_type(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc);
|
||||
u32 ath12k_dp_rx_h_mpdu_err(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc);
|
||||
void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct hal_rx_desc *rx_desc,
|
||||
struct ieee80211_rx_status *rx_status);
|
||||
void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct ath12k_dp_rx_info *rx_info);
|
||||
int ath12k_dp_rxdma_ring_sel_config_qcn9274(struct ath12k_base *ab);
|
||||
int ath12k_dp_rxdma_ring_sel_config_wcn7850(struct ath12k_base *ab);
|
||||
|
||||
|
|
@ -145,4 +161,9 @@ int ath12k_dp_htt_tlv_iter(struct ath12k_base *ab, const void *ptr, size_t len,
|
|||
int (*iter)(struct ath12k_base *ar, u16 tag, u16 len,
|
||||
const void *ptr, void *data),
|
||||
void *data);
|
||||
void ath12k_dp_rx_h_fetch_info(struct ath12k_base *ab, struct hal_rx_desc *rx_desc,
|
||||
struct ath12k_dp_rx_info *rx_info);
|
||||
|
||||
int ath12k_dp_rx_crypto_mic_len(struct ath12k *ar, enum hal_encrypt_type enctype);
|
||||
|
||||
#endif /* ATH12K_DP_RX_H */
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "core.h"
|
||||
#include "dp_tx.h"
|
||||
#include "debug.h"
|
||||
#include "debugfs.h"
|
||||
#include "hw.h"
|
||||
#include "peer.h"
|
||||
#include "mac.h"
|
||||
|
|
@ -83,6 +84,7 @@ static void ath12k_dp_tx_release_txbuf(struct ath12k_dp *dp,
|
|||
u8 pool_id)
|
||||
{
|
||||
spin_lock_bh(&dp->tx_desc_lock[pool_id]);
|
||||
tx_desc->skb_ext_desc = NULL;
|
||||
list_move_tail(&tx_desc->list, &dp->tx_desc_free_list[pool_id]);
|
||||
spin_unlock_bh(&dp->tx_desc_lock[pool_id]);
|
||||
}
|
||||
|
|
@ -219,7 +221,8 @@ static int ath12k_dp_tx_align_payload(struct ath12k_base *ab,
|
|||
}
|
||||
|
||||
int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
|
||||
struct sk_buff *skb, bool gsn_valid, int mcbc_gsn)
|
||||
struct sk_buff *skb, bool gsn_valid, int mcbc_gsn,
|
||||
bool is_mcast)
|
||||
{
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
struct ath12k_dp *dp = &ab->dp;
|
||||
|
|
@ -229,7 +232,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
|
|||
struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb);
|
||||
struct hal_tcl_data_cmd *hal_tcl_desc;
|
||||
struct hal_tx_msdu_ext_desc *msg;
|
||||
struct sk_buff *skb_ext_desc;
|
||||
struct sk_buff *skb_ext_desc = NULL;
|
||||
struct hal_srng *tcl_ring;
|
||||
struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
struct ath12k_vif *ahvif = arvif->ahvif;
|
||||
|
|
@ -415,23 +418,21 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
|
|||
if (ret < 0) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_DP_TX,
|
||||
"Failed to add HTT meta data, dropping packet\n");
|
||||
kfree_skb(skb_ext_desc);
|
||||
goto fail_unmap_dma;
|
||||
goto fail_free_ext_skb;
|
||||
}
|
||||
}
|
||||
|
||||
ti.paddr = dma_map_single(ab->dev, skb_ext_desc->data,
|
||||
skb_ext_desc->len, DMA_TO_DEVICE);
|
||||
ret = dma_mapping_error(ab->dev, ti.paddr);
|
||||
if (ret) {
|
||||
kfree_skb(skb_ext_desc);
|
||||
goto fail_unmap_dma;
|
||||
}
|
||||
if (ret)
|
||||
goto fail_free_ext_skb;
|
||||
|
||||
ti.data_len = skb_ext_desc->len;
|
||||
ti.type = HAL_TCL_DESC_TYPE_EXT_DESC;
|
||||
|
||||
skb_cb->paddr_ext_desc = ti.paddr;
|
||||
tx_desc->skb_ext_desc = skb_ext_desc;
|
||||
}
|
||||
|
||||
hal_ring_id = tx_ring->tcl_data_ring.ring_id;
|
||||
|
|
@ -462,9 +463,20 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
|
|||
ring_selector++;
|
||||
}
|
||||
|
||||
goto fail_unmap_dma;
|
||||
goto fail_unmap_dma_ext;
|
||||
}
|
||||
|
||||
spin_lock_bh(&arvif->link_stats_lock);
|
||||
arvif->link_stats.tx_encap_type[ti.encap_type]++;
|
||||
arvif->link_stats.tx_encrypt_type[ti.encrypt_type]++;
|
||||
arvif->link_stats.tx_desc_type[ti.type]++;
|
||||
|
||||
if (is_mcast)
|
||||
arvif->link_stats.tx_bcast_mcast++;
|
||||
else
|
||||
arvif->link_stats.tx_enqueued++;
|
||||
spin_unlock_bh(&arvif->link_stats_lock);
|
||||
|
||||
ath12k_hal_tx_cmd_desc_setup(ab, hal_tcl_desc, &ti);
|
||||
|
||||
ath12k_hal_srng_access_end(ab, tcl_ring);
|
||||
|
|
@ -478,16 +490,24 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
|
|||
|
||||
return 0;
|
||||
|
||||
fail_unmap_dma_ext:
|
||||
if (skb_cb->paddr_ext_desc)
|
||||
dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc,
|
||||
skb_ext_desc->len,
|
||||
DMA_TO_DEVICE);
|
||||
fail_free_ext_skb:
|
||||
kfree_skb(skb_ext_desc);
|
||||
|
||||
fail_unmap_dma:
|
||||
dma_unmap_single(ab->dev, ti.paddr, ti.data_len, DMA_TO_DEVICE);
|
||||
|
||||
if (skb_cb->paddr_ext_desc)
|
||||
dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc,
|
||||
sizeof(struct hal_tx_msdu_ext_desc),
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
fail_remove_tx_buf:
|
||||
ath12k_dp_tx_release_txbuf(dp, tx_desc, pool_id);
|
||||
|
||||
spin_lock_bh(&arvif->link_stats_lock);
|
||||
arvif->link_stats.tx_dropped++;
|
||||
spin_unlock_bh(&arvif->link_stats_lock);
|
||||
|
||||
if (tcl_ring_retry)
|
||||
goto tcl_ring_sel;
|
||||
|
||||
|
|
@ -495,20 +515,23 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
|
|||
}
|
||||
|
||||
static void ath12k_dp_tx_free_txbuf(struct ath12k_base *ab,
|
||||
struct sk_buff *msdu, u8 mac_id,
|
||||
struct dp_tx_ring *tx_ring)
|
||||
struct dp_tx_ring *tx_ring,
|
||||
struct ath12k_tx_desc_params *desc_params)
|
||||
{
|
||||
struct ath12k *ar;
|
||||
struct sk_buff *msdu = desc_params->skb;
|
||||
struct ath12k_skb_cb *skb_cb;
|
||||
u8 pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id);
|
||||
u8 pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, desc_params->mac_id);
|
||||
|
||||
skb_cb = ATH12K_SKB_CB(msdu);
|
||||
ar = ab->pdevs[pdev_id].ar;
|
||||
|
||||
dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
|
||||
if (skb_cb->paddr_ext_desc)
|
||||
if (skb_cb->paddr_ext_desc) {
|
||||
dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc,
|
||||
sizeof(struct hal_tx_msdu_ext_desc), DMA_TO_DEVICE);
|
||||
desc_params->skb_ext_desc->len, DMA_TO_DEVICE);
|
||||
dev_kfree_skb_any(desc_params->skb_ext_desc);
|
||||
}
|
||||
|
||||
ieee80211_free_txskb(ar->ah->hw, msdu);
|
||||
|
||||
|
|
@ -518,13 +541,17 @@ static void ath12k_dp_tx_free_txbuf(struct ath12k_base *ab,
|
|||
|
||||
static void
|
||||
ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab,
|
||||
struct sk_buff *msdu,
|
||||
struct ath12k_tx_desc_params *desc_params,
|
||||
struct dp_tx_ring *tx_ring,
|
||||
struct ath12k_dp_htt_wbm_tx_status *ts)
|
||||
{
|
||||
struct ieee80211_tx_info *info;
|
||||
struct ath12k_link_vif *arvif;
|
||||
struct ath12k_skb_cb *skb_cb;
|
||||
struct ieee80211_vif *vif;
|
||||
struct ath12k_vif *ahvif;
|
||||
struct ath12k *ar;
|
||||
struct sk_buff *msdu = desc_params->skb;
|
||||
|
||||
skb_cb = ATH12K_SKB_CB(msdu);
|
||||
info = IEEE80211_SKB_CB(msdu);
|
||||
|
|
@ -535,9 +562,24 @@ ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab,
|
|||
wake_up(&ar->dp.tx_empty_waitq);
|
||||
|
||||
dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
|
||||
if (skb_cb->paddr_ext_desc)
|
||||
if (skb_cb->paddr_ext_desc) {
|
||||
dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc,
|
||||
sizeof(struct hal_tx_msdu_ext_desc), DMA_TO_DEVICE);
|
||||
desc_params->skb_ext_desc->len, DMA_TO_DEVICE);
|
||||
dev_kfree_skb_any(desc_params->skb_ext_desc);
|
||||
}
|
||||
|
||||
vif = skb_cb->vif;
|
||||
if (vif) {
|
||||
ahvif = ath12k_vif_to_ahvif(vif);
|
||||
rcu_read_lock();
|
||||
arvif = rcu_dereference(ahvif->link[skb_cb->link_id]);
|
||||
if (arvif) {
|
||||
spin_lock_bh(&arvif->link_stats_lock);
|
||||
arvif->link_stats.tx_completed++;
|
||||
spin_unlock_bh(&arvif->link_stats_lock);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
|
||||
|
|
@ -560,10 +602,9 @@ ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab,
|
|||
}
|
||||
|
||||
static void
|
||||
ath12k_dp_tx_process_htt_tx_complete(struct ath12k_base *ab,
|
||||
void *desc, u8 mac_id,
|
||||
struct sk_buff *msdu,
|
||||
struct dp_tx_ring *tx_ring)
|
||||
ath12k_dp_tx_process_htt_tx_complete(struct ath12k_base *ab, void *desc,
|
||||
struct dp_tx_ring *tx_ring,
|
||||
struct ath12k_tx_desc_params *desc_params)
|
||||
{
|
||||
struct htt_tx_wbm_completion *status_desc;
|
||||
struct ath12k_dp_htt_wbm_tx_status ts = {0};
|
||||
|
|
@ -579,13 +620,14 @@ ath12k_dp_tx_process_htt_tx_complete(struct ath12k_base *ab,
|
|||
ts.acked = (wbm_status == HAL_WBM_REL_HTT_TX_COMP_STATUS_OK);
|
||||
ts.ack_rssi = le32_get_bits(status_desc->info2,
|
||||
HTT_TX_WBM_COMP_INFO2_ACK_RSSI);
|
||||
ath12k_dp_tx_htt_tx_complete_buf(ab, msdu, tx_ring, &ts);
|
||||
ath12k_dp_tx_htt_tx_complete_buf(ab, desc_params, tx_ring, &ts);
|
||||
break;
|
||||
case HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP:
|
||||
case HAL_WBM_REL_HTT_TX_COMP_STATUS_TTL:
|
||||
case HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ:
|
||||
case HAL_WBM_REL_HTT_TX_COMP_STATUS_INSPECT:
|
||||
ath12k_dp_tx_free_txbuf(ab, msdu, mac_id, tx_ring);
|
||||
case HAL_WBM_REL_HTT_TX_COMP_STATUS_VDEVID_MISMATCH:
|
||||
ath12k_dp_tx_free_txbuf(ab, tx_ring, desc_params);
|
||||
break;
|
||||
case HAL_WBM_REL_HTT_TX_COMP_STATUS_MEC_NOTIFY:
|
||||
/* This event is to be handled only when the driver decides to
|
||||
|
|
@ -593,7 +635,7 @@ ath12k_dp_tx_process_htt_tx_complete(struct ath12k_base *ab,
|
|||
*/
|
||||
break;
|
||||
default:
|
||||
ath12k_warn(ab, "Unknown htt tx status %d\n", wbm_status);
|
||||
ath12k_warn(ab, "Unknown htt wbm tx status %d\n", wbm_status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -717,13 +759,17 @@ static void ath12k_dp_tx_update_txcompl(struct ath12k *ar, struct hal_tx_status
|
|||
}
|
||||
|
||||
static void ath12k_dp_tx_complete_msdu(struct ath12k *ar,
|
||||
struct sk_buff *msdu,
|
||||
struct ath12k_tx_desc_params *desc_params,
|
||||
struct hal_tx_status *ts)
|
||||
{
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
struct ath12k_hw *ah = ar->ah;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct ath12k_link_vif *arvif;
|
||||
struct ath12k_skb_cb *skb_cb;
|
||||
struct ieee80211_vif *vif;
|
||||
struct ath12k_vif *ahvif;
|
||||
struct sk_buff *msdu = desc_params->skb;
|
||||
|
||||
if (WARN_ON_ONCE(ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM)) {
|
||||
/* Must not happen */
|
||||
|
|
@ -733,9 +779,11 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar,
|
|||
skb_cb = ATH12K_SKB_CB(msdu);
|
||||
|
||||
dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
|
||||
if (skb_cb->paddr_ext_desc)
|
||||
if (skb_cb->paddr_ext_desc) {
|
||||
dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc,
|
||||
sizeof(struct hal_tx_msdu_ext_desc), DMA_TO_DEVICE);
|
||||
desc_params->skb_ext_desc->len, DMA_TO_DEVICE);
|
||||
dev_kfree_skb_any(desc_params->skb_ext_desc);
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
|
|
@ -749,6 +797,17 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar,
|
|||
goto exit;
|
||||
}
|
||||
|
||||
vif = skb_cb->vif;
|
||||
if (vif) {
|
||||
ahvif = ath12k_vif_to_ahvif(vif);
|
||||
arvif = rcu_dereference(ahvif->link[skb_cb->link_id]);
|
||||
if (arvif) {
|
||||
spin_lock_bh(&arvif->link_stats_lock);
|
||||
arvif->link_stats.tx_completed++;
|
||||
spin_unlock_bh(&arvif->link_stats_lock);
|
||||
}
|
||||
}
|
||||
|
||||
info = IEEE80211_SKB_CB(msdu);
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
|
||||
|
|
@ -842,11 +901,11 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id)
|
|||
int hal_ring_id = dp->tx_ring[ring_id].tcl_comp_ring.ring_id;
|
||||
struct hal_srng *status_ring = &ab->hal.srng_list[hal_ring_id];
|
||||
struct ath12k_tx_desc_info *tx_desc = NULL;
|
||||
struct sk_buff *msdu;
|
||||
struct hal_tx_status ts = { 0 };
|
||||
struct ath12k_tx_desc_params desc_params;
|
||||
struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id];
|
||||
struct hal_wbm_release_ring *desc;
|
||||
u8 mac_id, pdev_id;
|
||||
u8 pdev_id;
|
||||
u64 desc_va;
|
||||
|
||||
spin_lock_bh(&status_ring->lock);
|
||||
|
|
@ -900,28 +959,27 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id)
|
|||
continue;
|
||||
}
|
||||
|
||||
msdu = tx_desc->skb;
|
||||
mac_id = tx_desc->mac_id;
|
||||
desc_params.mac_id = tx_desc->mac_id;
|
||||
desc_params.skb = tx_desc->skb;
|
||||
desc_params.skb_ext_desc = tx_desc->skb_ext_desc;
|
||||
|
||||
/* Release descriptor as soon as extracting necessary info
|
||||
* to reduce contention
|
||||
*/
|
||||
ath12k_dp_tx_release_txbuf(dp, tx_desc, tx_desc->pool_id);
|
||||
if (ts.buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW) {
|
||||
ath12k_dp_tx_process_htt_tx_complete(ab,
|
||||
(void *)tx_status,
|
||||
mac_id, msdu,
|
||||
tx_ring);
|
||||
ath12k_dp_tx_process_htt_tx_complete(ab, (void *)tx_status,
|
||||
tx_ring, &desc_params);
|
||||
continue;
|
||||
}
|
||||
|
||||
pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id);
|
||||
pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, desc_params.mac_id);
|
||||
ar = ab->pdevs[pdev_id].ar;
|
||||
|
||||
if (atomic_dec_and_test(&ar->dp.num_tx_pending))
|
||||
wake_up(&ar->dp.tx_empty_waitq);
|
||||
|
||||
ath12k_dp_tx_complete_msdu(ar, msdu, &ts);
|
||||
ath12k_dp_tx_complete_msdu(ar, &desc_params, &ts);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1431,6 +1489,11 @@ int ath12k_dp_tx_htt_rx_monitor_mode_ring_config(struct ath12k *ar, bool reset)
|
|||
HTT_RX_MON_MO_CTRL_FILTER_FLASG3 |
|
||||
HTT_RX_MON_FP_DATA_FILTER_FLASG3 |
|
||||
HTT_RX_MON_MO_DATA_FILTER_FLASG3;
|
||||
} else {
|
||||
tlv_filter = ath12k_mac_mon_status_filter_default;
|
||||
|
||||
if (ath12k_debugfs_is_extd_rx_stats_enabled(ar))
|
||||
tlv_filter.rx_filter = ath12k_debugfs_rx_filter(ar);
|
||||
}
|
||||
|
||||
if (ab->hw_params->rxdma1_enable) {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@ struct ath12k_dp_htt_wbm_tx_status {
|
|||
|
||||
int ath12k_dp_tx_htt_h2t_ver_req_msg(struct ath12k_base *ab);
|
||||
int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
|
||||
struct sk_buff *skb, bool gsn_valid, int mcbc_gsn);
|
||||
struct sk_buff *skb, bool gsn_valid, int mcbc_gsn,
|
||||
bool is_mcast);
|
||||
void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id);
|
||||
|
||||
int ath12k_dp_tx_htt_h2t_ppdu_stats_req(struct ath12k *ar, u32 mask);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
|
|
@ -99,6 +99,8 @@ static int ath12k_fw_request_firmware_api_n(struct ath12k_base *ab,
|
|||
__set_bit(i, ab->fw.fw_features);
|
||||
}
|
||||
|
||||
ab->fw.fw_features_valid = true;
|
||||
|
||||
ath12k_dbg_dump(ab, ATH12K_DBG_BOOT, "features", "",
|
||||
ab->fw.fw_features,
|
||||
sizeof(ab->fw.fw_features));
|
||||
|
|
@ -169,3 +171,8 @@ void ath12k_fw_unmap(struct ath12k_base *ab)
|
|||
release_firmware(ab->fw.fw);
|
||||
memset(&ab->fw, 0, sizeof(ab->fw));
|
||||
}
|
||||
|
||||
bool ath12k_fw_feature_supported(struct ath12k_base *ab, enum ath12k_fw_features feat)
|
||||
{
|
||||
return ab->fw.fw_features_valid && test_bit(feat, ab->fw.fw_features);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH12K_FW_H
|
||||
|
|
@ -32,5 +32,6 @@ enum ath12k_fw_features {
|
|||
|
||||
void ath12k_fw_map(struct ath12k_base *ab);
|
||||
void ath12k_fw_unmap(struct ath12k_base *ab);
|
||||
bool ath12k_fw_feature_supported(struct ath12k_base *ab, enum ath12k_fw_features feat);
|
||||
|
||||
#endif /* ATH12K_FW_H */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/dma-mapping.h>
|
||||
#include "hal_tx.h"
|
||||
|
|
@ -449,8 +449,8 @@ static u8 *ath12k_hw_qcn9274_rx_desc_mpdu_start_addr2(struct hal_rx_desc *desc)
|
|||
|
||||
static bool ath12k_hw_qcn9274_rx_desc_is_da_mcbc(struct hal_rx_desc *desc)
|
||||
{
|
||||
return __le32_to_cpu(desc->u.qcn9274.mpdu_start.info6) &
|
||||
RX_MPDU_START_INFO6_MCAST_BCAST;
|
||||
return __le16_to_cpu(desc->u.qcn9274.msdu_end.info5) &
|
||||
RX_MSDU_END_INFO5_DA_IS_MCBC;
|
||||
}
|
||||
|
||||
static void ath12k_hw_qcn9274_rx_desc_get_dot11_hdr(struct hal_rx_desc *desc,
|
||||
|
|
@ -511,11 +511,6 @@ static void ath12k_hw_qcn9274_rx_desc_get_crypto_hdr(struct hal_rx_desc *desc,
|
|||
crypto_hdr[7] = HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.qcn9274.mpdu_start.pn[1]);
|
||||
}
|
||||
|
||||
static u16 ath12k_hw_qcn9274_rx_desc_get_mpdu_frame_ctl(struct hal_rx_desc *desc)
|
||||
{
|
||||
return __le16_to_cpu(desc->u.qcn9274.mpdu_start.frame_ctrl);
|
||||
}
|
||||
|
||||
static int ath12k_hal_srng_create_config_qcn9274(struct ath12k_base *ab)
|
||||
{
|
||||
struct ath12k_hal *hal = &ab->hal;
|
||||
|
|
@ -552,9 +547,9 @@ static int ath12k_hal_srng_create_config_qcn9274(struct ath12k_base *ab)
|
|||
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_HP;
|
||||
|
||||
s = &hal->srng_config[HAL_TCL_DATA];
|
||||
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_BASE_LSB;
|
||||
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_BASE_LSB(ab);
|
||||
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_HP;
|
||||
s->reg_size[0] = HAL_TCL2_RING_BASE_LSB - HAL_TCL1_RING_BASE_LSB;
|
||||
s->reg_size[0] = HAL_TCL2_RING_BASE_LSB(ab) - HAL_TCL1_RING_BASE_LSB(ab);
|
||||
s->reg_size[1] = HAL_TCL2_RING_HP - HAL_TCL1_RING_HP;
|
||||
|
||||
s = &hal->srng_config[HAL_TCL_CMD];
|
||||
|
|
@ -566,29 +561,29 @@ static int ath12k_hal_srng_create_config_qcn9274(struct ath12k_base *ab)
|
|||
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_STATUS_RING_HP;
|
||||
|
||||
s = &hal->srng_config[HAL_CE_SRC];
|
||||
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG + HAL_CE_DST_RING_BASE_LSB;
|
||||
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG + HAL_CE_DST_RING_HP;
|
||||
s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_SRC_REG;
|
||||
s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_SRC_REG;
|
||||
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_BASE_LSB;
|
||||
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_HP;
|
||||
s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab);
|
||||
s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab);
|
||||
|
||||
s = &hal->srng_config[HAL_CE_DST];
|
||||
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG + HAL_CE_DST_RING_BASE_LSB;
|
||||
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG + HAL_CE_DST_RING_HP;
|
||||
s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_DST_REG;
|
||||
s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_DST_REG;
|
||||
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_BASE_LSB;
|
||||
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_HP;
|
||||
s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
|
||||
s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
|
||||
|
||||
s = &hal->srng_config[HAL_CE_DST_STATUS];
|
||||
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG +
|
||||
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) +
|
||||
HAL_CE_DST_STATUS_RING_BASE_LSB;
|
||||
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG + HAL_CE_DST_STATUS_RING_HP;
|
||||
s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_DST_REG;
|
||||
s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_DST_REG;
|
||||
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_STATUS_RING_HP;
|
||||
s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
|
||||
s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
|
||||
|
||||
s = &hal->srng_config[HAL_WBM_IDLE_LINK];
|
||||
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_IDLE_LINK_RING_BASE_LSB(ab);
|
||||
|
|
@ -736,7 +731,6 @@ const struct hal_rx_ops hal_rx_qcn9274_ops = {
|
|||
.rx_desc_is_da_mcbc = ath12k_hw_qcn9274_rx_desc_is_da_mcbc,
|
||||
.rx_desc_get_dot11_hdr = ath12k_hw_qcn9274_rx_desc_get_dot11_hdr,
|
||||
.rx_desc_get_crypto_header = ath12k_hw_qcn9274_rx_desc_get_crypto_hdr,
|
||||
.rx_desc_get_mpdu_frame_ctl = ath12k_hw_qcn9274_rx_desc_get_mpdu_frame_ctl,
|
||||
.dp_rx_h_msdu_done = ath12k_hw_qcn9274_dp_rx_h_msdu_done,
|
||||
.dp_rx_h_l4_cksum_fail = ath12k_hw_qcn9274_dp_rx_h_l4_cksum_fail,
|
||||
.dp_rx_h_ip_cksum_fail = ath12k_hw_qcn9274_dp_rx_h_ip_cksum_fail,
|
||||
|
|
@ -908,8 +902,8 @@ static u8 *ath12k_hw_qcn9274_compact_rx_desc_mpdu_start_addr2(struct hal_rx_desc
|
|||
|
||||
static bool ath12k_hw_qcn9274_compact_rx_desc_is_da_mcbc(struct hal_rx_desc *desc)
|
||||
{
|
||||
return __le32_to_cpu(desc->u.qcn9274_compact.mpdu_start.info6) &
|
||||
RX_MPDU_START_INFO6_MCAST_BCAST;
|
||||
return __le16_to_cpu(desc->u.qcn9274_compact.msdu_end.info5) &
|
||||
RX_MSDU_END_INFO5_DA_IS_MCBC;
|
||||
}
|
||||
|
||||
static void ath12k_hw_qcn9274_compact_rx_desc_get_dot11_hdr(struct hal_rx_desc *desc,
|
||||
|
|
@ -975,11 +969,6 @@ ath12k_hw_qcn9274_compact_rx_desc_get_crypto_hdr(struct hal_rx_desc *desc,
|
|||
HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.qcn9274_compact.mpdu_start.pn[1]);
|
||||
}
|
||||
|
||||
static u16 ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_frame_ctl(struct hal_rx_desc *desc)
|
||||
{
|
||||
return __le16_to_cpu(desc->u.qcn9274_compact.mpdu_start.frame_ctrl);
|
||||
}
|
||||
|
||||
static bool ath12k_hw_qcn9274_compact_dp_rx_h_msdu_done(struct hal_rx_desc *desc)
|
||||
{
|
||||
return !!le32_get_bits(desc->u.qcn9274_compact.msdu_end.info14,
|
||||
|
|
@ -1080,8 +1069,6 @@ const struct hal_rx_ops hal_rx_qcn9274_compact_ops = {
|
|||
.rx_desc_is_da_mcbc = ath12k_hw_qcn9274_compact_rx_desc_is_da_mcbc,
|
||||
.rx_desc_get_dot11_hdr = ath12k_hw_qcn9274_compact_rx_desc_get_dot11_hdr,
|
||||
.rx_desc_get_crypto_header = ath12k_hw_qcn9274_compact_rx_desc_get_crypto_hdr,
|
||||
.rx_desc_get_mpdu_frame_ctl =
|
||||
ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_frame_ctl,
|
||||
.dp_rx_h_msdu_done = ath12k_hw_qcn9274_compact_dp_rx_h_msdu_done,
|
||||
.dp_rx_h_l4_cksum_fail = ath12k_hw_qcn9274_compact_dp_rx_h_l4_cksum_fail,
|
||||
.dp_rx_h_ip_cksum_fail = ath12k_hw_qcn9274_compact_dp_rx_h_ip_cksum_fail,
|
||||
|
|
@ -1330,11 +1317,6 @@ static void ath12k_hw_wcn7850_rx_desc_get_crypto_hdr(struct hal_rx_desc *desc,
|
|||
crypto_hdr[7] = HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.wcn7850.mpdu_start.pn[1]);
|
||||
}
|
||||
|
||||
static u16 ath12k_hw_wcn7850_rx_desc_get_mpdu_frame_ctl(struct hal_rx_desc *desc)
|
||||
{
|
||||
return __le16_to_cpu(desc->u.wcn7850.mpdu_start.frame_ctrl);
|
||||
}
|
||||
|
||||
static int ath12k_hal_srng_create_config_wcn7850(struct ath12k_base *ab)
|
||||
{
|
||||
struct ath12k_hal *hal = &ab->hal;
|
||||
|
|
@ -1371,9 +1353,9 @@ static int ath12k_hal_srng_create_config_wcn7850(struct ath12k_base *ab)
|
|||
|
||||
s = &hal->srng_config[HAL_TCL_DATA];
|
||||
s->max_rings = 5;
|
||||
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_BASE_LSB;
|
||||
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_BASE_LSB(ab);
|
||||
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_HP;
|
||||
s->reg_size[0] = HAL_TCL2_RING_BASE_LSB - HAL_TCL1_RING_BASE_LSB;
|
||||
s->reg_size[0] = HAL_TCL2_RING_BASE_LSB(ab) - HAL_TCL1_RING_BASE_LSB(ab);
|
||||
s->reg_size[1] = HAL_TCL2_RING_HP - HAL_TCL1_RING_HP;
|
||||
|
||||
s = &hal->srng_config[HAL_TCL_CMD];
|
||||
|
|
@ -1386,31 +1368,31 @@ static int ath12k_hal_srng_create_config_wcn7850(struct ath12k_base *ab)
|
|||
|
||||
s = &hal->srng_config[HAL_CE_SRC];
|
||||
s->max_rings = 12;
|
||||
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG + HAL_CE_DST_RING_BASE_LSB;
|
||||
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG + HAL_CE_DST_RING_HP;
|
||||
s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_SRC_REG;
|
||||
s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_SRC_REG;
|
||||
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_BASE_LSB;
|
||||
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_HP;
|
||||
s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab);
|
||||
s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab);
|
||||
|
||||
s = &hal->srng_config[HAL_CE_DST];
|
||||
s->max_rings = 12;
|
||||
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG + HAL_CE_DST_RING_BASE_LSB;
|
||||
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG + HAL_CE_DST_RING_HP;
|
||||
s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_DST_REG;
|
||||
s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_DST_REG;
|
||||
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_BASE_LSB;
|
||||
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_HP;
|
||||
s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
|
||||
s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
|
||||
|
||||
s = &hal->srng_config[HAL_CE_DST_STATUS];
|
||||
s->max_rings = 12;
|
||||
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG +
|
||||
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) +
|
||||
HAL_CE_DST_STATUS_RING_BASE_LSB;
|
||||
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG + HAL_CE_DST_STATUS_RING_HP;
|
||||
s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_DST_REG;
|
||||
s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_DST_REG;
|
||||
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_STATUS_RING_HP;
|
||||
s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
|
||||
s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
|
||||
HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
|
||||
|
||||
s = &hal->srng_config[HAL_WBM_IDLE_LINK];
|
||||
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_IDLE_LINK_RING_BASE_LSB(ab);
|
||||
|
|
@ -1555,7 +1537,6 @@ const struct hal_rx_ops hal_rx_wcn7850_ops = {
|
|||
.rx_desc_is_da_mcbc = ath12k_hw_wcn7850_rx_desc_is_da_mcbc,
|
||||
.rx_desc_get_dot11_hdr = ath12k_hw_wcn7850_rx_desc_get_dot11_hdr,
|
||||
.rx_desc_get_crypto_header = ath12k_hw_wcn7850_rx_desc_get_crypto_hdr,
|
||||
.rx_desc_get_mpdu_frame_ctl = ath12k_hw_wcn7850_rx_desc_get_mpdu_frame_ctl,
|
||||
.dp_rx_h_msdu_done = ath12k_hw_wcn7850_dp_rx_h_msdu_done,
|
||||
.dp_rx_h_l4_cksum_fail = ath12k_hw_wcn7850_dp_rx_h_l4_cksum_fail,
|
||||
.dp_rx_h_ip_cksum_fail = ath12k_hw_wcn7850_dp_rx_h_ip_cksum_fail,
|
||||
|
|
@ -1756,7 +1737,7 @@ static void ath12k_hal_srng_src_hw_init(struct ath12k_base *ab,
|
|||
HAL_TCL1_RING_BASE_MSB_RING_BASE_ADDR_MSB) |
|
||||
u32_encode_bits((srng->entry_size * srng->num_entries),
|
||||
HAL_TCL1_RING_BASE_MSB_RING_SIZE);
|
||||
ath12k_hif_write32(ab, reg_base + HAL_TCL1_RING_BASE_MSB_OFFSET, val);
|
||||
ath12k_hif_write32(ab, reg_base + HAL_TCL1_RING_BASE_MSB_OFFSET(ab), val);
|
||||
|
||||
val = u32_encode_bits(srng->entry_size, HAL_REO1_RING_ID_ENTRY_SIZE);
|
||||
ath12k_hif_write32(ab, reg_base + HAL_TCL1_RING_ID_OFFSET(ab), val);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* 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.
|
||||
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH12K_HAL_H
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
#include "rx_desc.h"
|
||||
|
||||
struct ath12k_base;
|
||||
#define HAL_CE_REMAP_REG_BASE (ab->ce_remap_base_addr)
|
||||
|
||||
#define HAL_LINK_DESC_SIZE (32 << 2)
|
||||
#define HAL_LINK_DESC_ALIGN 128
|
||||
|
|
@ -21,6 +22,7 @@ struct ath12k_base;
|
|||
#define HAL_MAX_AVAIL_BLK_RES 3
|
||||
|
||||
#define HAL_RING_BASE_ALIGN 8
|
||||
#define HAL_REO_QLUT_ADDR_ALIGN 256
|
||||
|
||||
#define HAL_WBM_IDLE_SCATTER_BUF_SIZE_MAX 32704
|
||||
/* TODO: Check with hw team on the supported scatter buf size */
|
||||
|
|
@ -39,15 +41,21 @@ struct ath12k_base;
|
|||
#define HAL_OFFSET_FROM_HP_TO_TP 4
|
||||
|
||||
#define HAL_SHADOW_REG(x) (HAL_SHADOW_BASE_ADDR + (4 * (x)))
|
||||
#define HAL_REO_QDESC_MAX_PEERID 8191
|
||||
|
||||
/* WCSS Relative address */
|
||||
#define HAL_SEQ_WCSS_CMEM_OFFSET 0x00100000
|
||||
#define HAL_SEQ_WCSS_UMAC_OFFSET 0x00a00000
|
||||
#define HAL_SEQ_WCSS_UMAC_REO_REG 0x00a38000
|
||||
#define HAL_SEQ_WCSS_UMAC_TCL_REG 0x00a44000
|
||||
#define HAL_SEQ_WCSS_UMAC_CE0_SRC_REG 0x01b80000
|
||||
#define HAL_SEQ_WCSS_UMAC_CE0_DST_REG 0x01b81000
|
||||
#define HAL_SEQ_WCSS_UMAC_CE1_SRC_REG 0x01b82000
|
||||
#define HAL_SEQ_WCSS_UMAC_CE1_DST_REG 0x01b83000
|
||||
#define HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) \
|
||||
((ab)->hw_params->regs->hal_umac_ce0_src_reg_base)
|
||||
#define HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) \
|
||||
((ab)->hw_params->regs->hal_umac_ce0_dest_reg_base)
|
||||
#define HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) \
|
||||
((ab)->hw_params->regs->hal_umac_ce1_src_reg_base)
|
||||
#define HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) \
|
||||
((ab)->hw_params->regs->hal_umac_ce1_dest_reg_base)
|
||||
#define HAL_SEQ_WCSS_UMAC_WBM_REG 0x00a34000
|
||||
|
||||
#define HAL_CE_WFSS_CE_REG_BASE 0x01b80000
|
||||
|
|
@ -57,8 +65,10 @@ struct ath12k_base;
|
|||
/* SW2TCL(x) R0 ring configuration address */
|
||||
#define HAL_TCL1_RING_CMN_CTRL_REG 0x00000020
|
||||
#define HAL_TCL1_RING_DSCP_TID_MAP 0x00000240
|
||||
#define HAL_TCL1_RING_BASE_LSB 0x00000900
|
||||
#define HAL_TCL1_RING_BASE_MSB 0x00000904
|
||||
#define HAL_TCL1_RING_BASE_LSB(ab) \
|
||||
((ab)->hw_params->regs->hal_tcl1_ring_base_lsb)
|
||||
#define HAL_TCL1_RING_BASE_MSB(ab) \
|
||||
((ab)->hw_params->regs->hal_tcl1_ring_base_msb)
|
||||
#define HAL_TCL1_RING_ID(ab) ((ab)->hw_params->regs->hal_tcl1_ring_id)
|
||||
#define HAL_TCL1_RING_MISC(ab) \
|
||||
((ab)->hw_params->regs->hal_tcl1_ring_misc)
|
||||
|
|
@ -76,30 +86,31 @@ struct ath12k_base;
|
|||
((ab)->hw_params->regs->hal_tcl1_ring_msi1_base_msb)
|
||||
#define HAL_TCL1_RING_MSI1_DATA(ab) \
|
||||
((ab)->hw_params->regs->hal_tcl1_ring_msi1_data)
|
||||
#define HAL_TCL2_RING_BASE_LSB 0x00000978
|
||||
#define HAL_TCL2_RING_BASE_LSB(ab) \
|
||||
((ab)->hw_params->regs->hal_tcl2_ring_base_lsb)
|
||||
#define HAL_TCL_RING_BASE_LSB(ab) \
|
||||
((ab)->hw_params->regs->hal_tcl_ring_base_lsb)
|
||||
|
||||
#define HAL_TCL1_RING_MSI1_BASE_LSB_OFFSET(ab) \
|
||||
(HAL_TCL1_RING_MSI1_BASE_LSB(ab) - HAL_TCL1_RING_BASE_LSB)
|
||||
#define HAL_TCL1_RING_MSI1_BASE_MSB_OFFSET(ab) \
|
||||
(HAL_TCL1_RING_MSI1_BASE_MSB(ab) - HAL_TCL1_RING_BASE_LSB)
|
||||
#define HAL_TCL1_RING_MSI1_DATA_OFFSET(ab) \
|
||||
(HAL_TCL1_RING_MSI1_DATA(ab) - HAL_TCL1_RING_BASE_LSB)
|
||||
#define HAL_TCL1_RING_BASE_MSB_OFFSET \
|
||||
(HAL_TCL1_RING_BASE_MSB - HAL_TCL1_RING_BASE_LSB)
|
||||
#define HAL_TCL1_RING_ID_OFFSET(ab) \
|
||||
(HAL_TCL1_RING_ID(ab) - HAL_TCL1_RING_BASE_LSB)
|
||||
#define HAL_TCL1_RING_CONSR_INT_SETUP_IX0_OFFSET(ab) \
|
||||
(HAL_TCL1_RING_CONSUMER_INT_SETUP_IX0(ab) - HAL_TCL1_RING_BASE_LSB)
|
||||
#define HAL_TCL1_RING_CONSR_INT_SETUP_IX1_OFFSET(ab) \
|
||||
(HAL_TCL1_RING_CONSUMER_INT_SETUP_IX1(ab) - HAL_TCL1_RING_BASE_LSB)
|
||||
#define HAL_TCL1_RING_TP_ADDR_LSB_OFFSET(ab) \
|
||||
(HAL_TCL1_RING_TP_ADDR_LSB(ab) - HAL_TCL1_RING_BASE_LSB)
|
||||
#define HAL_TCL1_RING_TP_ADDR_MSB_OFFSET(ab) \
|
||||
(HAL_TCL1_RING_TP_ADDR_MSB(ab) - HAL_TCL1_RING_BASE_LSB)
|
||||
#define HAL_TCL1_RING_MISC_OFFSET(ab) \
|
||||
(HAL_TCL1_RING_MISC(ab) - HAL_TCL1_RING_BASE_LSB)
|
||||
#define HAL_TCL1_RING_MSI1_BASE_LSB_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
|
||||
(HAL_TCL1_RING_MSI1_BASE_LSB(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
|
||||
#define HAL_TCL1_RING_MSI1_BASE_MSB_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
|
||||
(HAL_TCL1_RING_MSI1_BASE_MSB(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
|
||||
#define HAL_TCL1_RING_MSI1_DATA_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
|
||||
(HAL_TCL1_RING_MSI1_DATA(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
|
||||
#define HAL_TCL1_RING_BASE_MSB_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
|
||||
(HAL_TCL1_RING_BASE_MSB(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
|
||||
#define HAL_TCL1_RING_ID_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
|
||||
(HAL_TCL1_RING_ID(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
|
||||
#define HAL_TCL1_RING_CONSR_INT_SETUP_IX0_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
|
||||
(HAL_TCL1_RING_CONSUMER_INT_SETUP_IX0(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
|
||||
#define HAL_TCL1_RING_CONSR_INT_SETUP_IX1_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
|
||||
(HAL_TCL1_RING_CONSUMER_INT_SETUP_IX1(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
|
||||
#define HAL_TCL1_RING_TP_ADDR_LSB_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
|
||||
(HAL_TCL1_RING_TP_ADDR_LSB(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
|
||||
#define HAL_TCL1_RING_TP_ADDR_MSB_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
|
||||
(HAL_TCL1_RING_TP_ADDR_MSB(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
|
||||
#define HAL_TCL1_RING_MISC_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
|
||||
(HAL_TCL1_RING_MISC(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
|
||||
|
||||
/* SW2TCL(x) R2 ring pointers (head/tail) address */
|
||||
#define HAL_TCL1_RING_HP 0x00002000
|
||||
|
|
@ -132,6 +143,8 @@ struct ath12k_base;
|
|||
#define HAL_REO1_DEST_RING_CTRL_IX_1 0x00000008
|
||||
#define HAL_REO1_DEST_RING_CTRL_IX_2 0x0000000c
|
||||
#define HAL_REO1_DEST_RING_CTRL_IX_3 0x00000010
|
||||
#define HAL_REO1_QDESC_ADDR(ab) ((ab)->hw_params->regs->hal_reo1_qdesc_addr)
|
||||
#define HAL_REO1_QDESC_MAX_PEERID(ab) ((ab)->hw_params->regs->hal_reo1_qdesc_max_peerid)
|
||||
#define HAL_REO1_SW_COOKIE_CFG0(ab) ((ab)->hw_params->regs->hal_reo1_sw_cookie_cfg0)
|
||||
#define HAL_REO1_SW_COOKIE_CFG1(ab) ((ab)->hw_params->regs->hal_reo1_sw_cookie_cfg1)
|
||||
#define HAL_REO1_QDESC_LUT_BASE0(ab) ((ab)->hw_params->regs->hal_reo1_qdesc_lut_base0)
|
||||
|
|
@ -319,6 +332,8 @@ struct ath12k_base;
|
|||
#define HAL_REO1_SW_COOKIE_CFG_ALIGN BIT(18)
|
||||
#define HAL_REO1_SW_COOKIE_CFG_ENABLE BIT(19)
|
||||
#define HAL_REO1_SW_COOKIE_CFG_GLOBAL_ENABLE BIT(20)
|
||||
#define HAL_REO_QDESC_ADDR_READ_LUT_ENABLE BIT(7)
|
||||
#define HAL_REO_QDESC_ADDR_READ_CLEAR_QDESC_ARRAY BIT(6)
|
||||
|
||||
/* CE ring bit field mask and shift */
|
||||
#define HAL_CE_DST_R0_DEST_CTRL_MAX_LEN GENMASK(15, 0)
|
||||
|
|
@ -365,6 +380,9 @@ struct ath12k_base;
|
|||
* ath12k_hal_rx_desc_get_err().
|
||||
*/
|
||||
|
||||
#define HAL_IPQ5332_CE_WFSS_REG_BASE 0x740000
|
||||
#define HAL_IPQ5332_CE_SIZE 0x100000
|
||||
|
||||
enum hal_srng_ring_id {
|
||||
HAL_SRNG_RING_ID_REO2SW0 = 0,
|
||||
HAL_SRNG_RING_ID_REO2SW1,
|
||||
|
|
@ -1068,7 +1086,6 @@ struct hal_rx_ops {
|
|||
bool (*rx_desc_is_da_mcbc)(struct hal_rx_desc *desc);
|
||||
void (*rx_desc_get_dot11_hdr)(struct hal_rx_desc *desc,
|
||||
struct ieee80211_hdr *hdr);
|
||||
u16 (*rx_desc_get_mpdu_frame_ctl)(struct hal_rx_desc *desc);
|
||||
void (*rx_desc_get_crypto_header)(struct hal_rx_desc *desc,
|
||||
u8 *crypto_hdr,
|
||||
enum hal_encrypt_type enctype);
|
||||
|
|
@ -1154,4 +1171,5 @@ int ath12k_hal_srng_update_shadow_config(struct ath12k_base *ab,
|
|||
void ath12k_hal_srng_shadow_config(struct ath12k_base *ab);
|
||||
void ath12k_hal_srng_shadow_update_hp_tp(struct ath12k_base *ab,
|
||||
struct hal_srng *srng);
|
||||
void ath12k_hal_reo_shared_qaddr_cache_clear(struct ath12k_base *ab);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2022, 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#include "core.h"
|
||||
|
||||
|
|
@ -1284,11 +1284,13 @@ enum hal_tcl_encap_type {
|
|||
HAL_TCL_ENCAP_TYPE_NATIVE_WIFI,
|
||||
HAL_TCL_ENCAP_TYPE_ETHERNET,
|
||||
HAL_TCL_ENCAP_TYPE_802_3 = 3,
|
||||
HAL_TCL_ENCAP_TYPE_MAX
|
||||
};
|
||||
|
||||
enum hal_tcl_desc_type {
|
||||
HAL_TCL_DESC_TYPE_BUFFER,
|
||||
HAL_TCL_DESC_TYPE_EXT_DESC,
|
||||
HAL_TCL_DESC_TYPE_MAX,
|
||||
};
|
||||
|
||||
enum hal_wbm_htt_tx_comp_status {
|
||||
|
|
@ -1298,6 +1300,7 @@ enum hal_wbm_htt_tx_comp_status {
|
|||
HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ,
|
||||
HAL_WBM_REL_HTT_TX_COMP_STATUS_INSPECT,
|
||||
HAL_WBM_REL_HTT_TX_COMP_STATUS_MEC_NOTIFY,
|
||||
HAL_WBM_REL_HTT_TX_COMP_STATUS_VDEVID_MISMATCH,
|
||||
HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX,
|
||||
};
|
||||
|
||||
|
|
@ -1998,6 +2001,7 @@ struct hal_wbm_release_ring_cc_rx {
|
|||
#define HAL_WBM_RELEASE_INFO3_CONTINUATION BIT(2)
|
||||
|
||||
#define HAL_WBM_RELEASE_INFO5_LOOPING_COUNT GENMASK(31, 28)
|
||||
#define HAL_ENCRYPT_TYPE_MAX 12
|
||||
|
||||
struct hal_wbm_release_ring {
|
||||
struct ath12k_buffer_addr buf_addr_info;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// 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.
|
||||
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "debug.h"
|
||||
|
|
@ -851,3 +851,20 @@ void ath12k_hal_reo_hw_setup(struct ath12k_base *ab, u32 ring_hash_map)
|
|||
ath12k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_3,
|
||||
ring_hash_map);
|
||||
}
|
||||
|
||||
void ath12k_hal_reo_shared_qaddr_cache_clear(struct ath12k_base *ab)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
lockdep_assert_held(&ab->base_lock);
|
||||
val = ath12k_hif_read32(ab, HAL_SEQ_WCSS_UMAC_REO_REG +
|
||||
HAL_REO1_QDESC_ADDR(ab));
|
||||
|
||||
val |= u32_encode_bits(1, HAL_REO_QDESC_ADDR_READ_CLEAR_QDESC_ARRAY);
|
||||
ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG +
|
||||
HAL_REO1_QDESC_ADDR(ab), val);
|
||||
|
||||
val &= ~HAL_REO_QDESC_ADDR_READ_CLEAR_QDESC_ARRAY;
|
||||
ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG +
|
||||
HAL_REO1_QDESC_ADDR(ab), val);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,11 +108,12 @@ enum hal_rx_mon_status {
|
|||
HAL_RX_MON_STATUS_PPDU_DONE,
|
||||
HAL_RX_MON_STATUS_BUF_DONE,
|
||||
HAL_RX_MON_STATUS_BUF_ADDR,
|
||||
HAL_RX_MON_STATUS_MPDU_START,
|
||||
HAL_RX_MON_STATUS_MPDU_END,
|
||||
HAL_RX_MON_STATUS_MSDU_END,
|
||||
};
|
||||
|
||||
#define HAL_RX_MAX_MPDU 256
|
||||
#define HAL_RX_MAX_MPDU 1024
|
||||
#define HAL_RX_NUM_WORDS_PER_PPDU_BITMAP (HAL_RX_MAX_MPDU >> 5)
|
||||
|
||||
struct hal_rx_user_status {
|
||||
|
|
@ -506,6 +507,18 @@ struct hal_rx_mpdu_start {
|
|||
__le32 rsvd2[16];
|
||||
} __packed;
|
||||
|
||||
struct hal_rx_msdu_end {
|
||||
__le32 info0;
|
||||
__le32 rsvd0[9];
|
||||
__le16 info00;
|
||||
__le16 info01;
|
||||
__le32 rsvd00[8];
|
||||
__le32 info1;
|
||||
__le32 rsvd1[10];
|
||||
__le32 info2;
|
||||
__le32 rsvd2;
|
||||
} __packed;
|
||||
|
||||
#define HAL_RX_PPDU_END_DURATION GENMASK(23, 0)
|
||||
struct hal_rx_ppdu_end_duration {
|
||||
__le32 rsvd0[9];
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// 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.
|
||||
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
|
|
@ -535,6 +535,217 @@ static const struct service_to_pipe ath12k_target_service_to_ce_map_wlan_wcn7850
|
|||
},
|
||||
};
|
||||
|
||||
static const struct ce_pipe_config ath12k_target_ce_config_wlan_ipq5332[] = {
|
||||
/* host->target HTC control and raw streams */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(0),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
/* target->host HTT */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(1),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
/* target->host WMI + HTC control */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
/* host->target WMI */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(3),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
/* host->target HTT */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(4),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
|
||||
.nentries = __cpu_to_le32(256),
|
||||
.nbytes_max = __cpu_to_le32(256),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
/* Target -> host PKTLOG */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(5),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
/* Reserved for target autonomous HIF_memcpy */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(6),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(16384),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
/* CE7 Reserved for CV Prefetch */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(7),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
/* CE8 Reserved for target generic HIF memcpy */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(8),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(16384),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
/* CE9 WMI logging/CFR/Spectral/Radar/ */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(9),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
/* Unused TBD */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(10),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_NONE),
|
||||
.nentries = __cpu_to_le32(0),
|
||||
.nbytes_max = __cpu_to_le32(0),
|
||||
.flags = __cpu_to_le32(0),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
/* Unused TBD */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(11),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_NONE),
|
||||
.nentries = __cpu_to_le32(0),
|
||||
.nbytes_max = __cpu_to_le32(0),
|
||||
.flags = __cpu_to_le32(0),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct service_to_pipe ath12k_target_service_to_ce_map_wlan_ipq5332[] = {
|
||||
{
|
||||
__cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VO),
|
||||
__cpu_to_le32(PIPEDIR_OUT),
|
||||
__cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VO),
|
||||
__cpu_to_le32(PIPEDIR_IN),
|
||||
__cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BK),
|
||||
__cpu_to_le32(PIPEDIR_OUT),
|
||||
__cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BK),
|
||||
__cpu_to_le32(PIPEDIR_IN),
|
||||
__cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BE),
|
||||
__cpu_to_le32(PIPEDIR_OUT),
|
||||
__cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BE),
|
||||
__cpu_to_le32(PIPEDIR_IN),
|
||||
__cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VI),
|
||||
__cpu_to_le32(PIPEDIR_OUT),
|
||||
__cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VI),
|
||||
__cpu_to_le32(PIPEDIR_IN),
|
||||
__cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL),
|
||||
__cpu_to_le32(PIPEDIR_OUT),
|
||||
__cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL),
|
||||
__cpu_to_le32(PIPEDIR_IN),
|
||||
__cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH12K_HTC_SVC_ID_RSVD_CTRL),
|
||||
__cpu_to_le32(PIPEDIR_OUT),
|
||||
__cpu_to_le32(0),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH12K_HTC_SVC_ID_RSVD_CTRL),
|
||||
__cpu_to_le32(PIPEDIR_IN),
|
||||
__cpu_to_le32(1),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH12K_HTC_SVC_ID_TEST_RAW_STREAMS),
|
||||
__cpu_to_le32(PIPEDIR_OUT),
|
||||
__cpu_to_le32(0),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH12K_HTC_SVC_ID_TEST_RAW_STREAMS),
|
||||
__cpu_to_le32(PIPEDIR_IN),
|
||||
__cpu_to_le32(1),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH12K_HTC_SVC_ID_HTT_DATA_MSG),
|
||||
__cpu_to_le32(PIPEDIR_OUT),
|
||||
__cpu_to_le32(4),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH12K_HTC_SVC_ID_HTT_DATA_MSG),
|
||||
__cpu_to_le32(PIPEDIR_IN),
|
||||
__cpu_to_le32(1),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH12K_HTC_SVC_ID_PKT_LOG),
|
||||
__cpu_to_le32(PIPEDIR_IN),
|
||||
__cpu_to_le32(5),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL_DIAG),
|
||||
__cpu_to_le32(PIPEDIR_IN),
|
||||
__cpu_to_le32(9),
|
||||
},
|
||||
/* (Additions here) */
|
||||
|
||||
{ /* must be last */
|
||||
__cpu_to_le32(0),
|
||||
__cpu_to_le32(0),
|
||||
__cpu_to_le32(0),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ath12k_hw_ring_mask ath12k_hw_ring_mask_qcn9274 = {
|
||||
.tx = {
|
||||
ATH12K_TX_RING_MASK_0,
|
||||
|
|
@ -577,6 +788,46 @@ static const struct ath12k_hw_ring_mask ath12k_hw_ring_mask_qcn9274 = {
|
|||
},
|
||||
};
|
||||
|
||||
static const struct ath12k_hw_ring_mask ath12k_hw_ring_mask_ipq5332 = {
|
||||
.tx = {
|
||||
ATH12K_TX_RING_MASK_0,
|
||||
ATH12K_TX_RING_MASK_1,
|
||||
ATH12K_TX_RING_MASK_2,
|
||||
ATH12K_TX_RING_MASK_3,
|
||||
},
|
||||
.rx_mon_dest = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
ATH12K_RX_MON_RING_MASK_0,
|
||||
},
|
||||
.rx = {
|
||||
0, 0, 0, 0,
|
||||
ATH12K_RX_RING_MASK_0,
|
||||
ATH12K_RX_RING_MASK_1,
|
||||
ATH12K_RX_RING_MASK_2,
|
||||
ATH12K_RX_RING_MASK_3,
|
||||
},
|
||||
.rx_err = {
|
||||
0, 0, 0,
|
||||
ATH12K_RX_ERR_RING_MASK_0,
|
||||
},
|
||||
.rx_wbm_rel = {
|
||||
0, 0, 0,
|
||||
ATH12K_RX_WBM_REL_RING_MASK_0,
|
||||
},
|
||||
.reo_status = {
|
||||
0, 0, 0,
|
||||
ATH12K_REO_STATUS_RING_MASK_0,
|
||||
},
|
||||
.host2rxdma = {
|
||||
0, 0, 0,
|
||||
ATH12K_HOST2RXDMA_RING_MASK_0,
|
||||
},
|
||||
.tx_mon_dest = {
|
||||
ATH12K_TX_MON_RING_MASK_0,
|
||||
ATH12K_TX_MON_RING_MASK_1,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ath12k_hw_ring_mask ath12k_hw_ring_mask_wcn7850 = {
|
||||
.tx = {
|
||||
ATH12K_TX_RING_MASK_0,
|
||||
|
|
@ -619,6 +870,9 @@ static const struct ath12k_hw_regs qcn9274_v1_regs = {
|
|||
.hal_tcl1_ring_msi1_base_msb = 0x0000094c,
|
||||
.hal_tcl1_ring_msi1_data = 0x00000950,
|
||||
.hal_tcl_ring_base_lsb = 0x00000b58,
|
||||
.hal_tcl1_ring_base_lsb = 0x00000900,
|
||||
.hal_tcl1_ring_base_msb = 0x00000904,
|
||||
.hal_tcl2_ring_base_lsb = 0x00000978,
|
||||
|
||||
/* TCL STATUS ring address */
|
||||
.hal_tcl_status_ring_base_lsb = 0x00000d38,
|
||||
|
|
@ -681,6 +935,12 @@ static const struct ath12k_hw_regs qcn9274_v1_regs = {
|
|||
|
||||
/* REO status ring address */
|
||||
.hal_reo_status_ring_base = 0x00000a84,
|
||||
|
||||
/* CE base address */
|
||||
.hal_umac_ce0_src_reg_base = 0x01b80000,
|
||||
.hal_umac_ce0_dest_reg_base = 0x01b81000,
|
||||
.hal_umac_ce1_src_reg_base = 0x01b82000,
|
||||
.hal_umac_ce1_dest_reg_base = 0x01b83000,
|
||||
};
|
||||
|
||||
static const struct ath12k_hw_regs qcn9274_v2_regs = {
|
||||
|
|
@ -695,6 +955,9 @@ static const struct ath12k_hw_regs qcn9274_v2_regs = {
|
|||
.hal_tcl1_ring_msi1_base_msb = 0x0000094c,
|
||||
.hal_tcl1_ring_msi1_data = 0x00000950,
|
||||
.hal_tcl_ring_base_lsb = 0x00000b58,
|
||||
.hal_tcl1_ring_base_lsb = 0x00000900,
|
||||
.hal_tcl1_ring_base_msb = 0x00000904,
|
||||
.hal_tcl2_ring_base_lsb = 0x00000978,
|
||||
|
||||
/* TCL STATUS ring address */
|
||||
.hal_tcl_status_ring_base_lsb = 0x00000d38,
|
||||
|
|
@ -734,6 +997,8 @@ static const struct ath12k_hw_regs qcn9274_v2_regs = {
|
|||
.hal_reo1_sw_cookie_cfg1 = 0x00000070,
|
||||
.hal_reo1_qdesc_lut_base0 = 0x00000074,
|
||||
.hal_reo1_qdesc_lut_base1 = 0x00000078,
|
||||
.hal_reo1_qdesc_addr = 0x0000007c,
|
||||
.hal_reo1_qdesc_max_peerid = 0x00000088,
|
||||
.hal_reo1_ring_base_lsb = 0x00000500,
|
||||
.hal_reo1_ring_base_msb = 0x00000504,
|
||||
.hal_reo1_ring_id = 0x00000508,
|
||||
|
|
@ -761,6 +1026,100 @@ static const struct ath12k_hw_regs qcn9274_v2_regs = {
|
|||
|
||||
/* REO status ring address */
|
||||
.hal_reo_status_ring_base = 0x00000aa0,
|
||||
|
||||
/* CE base address */
|
||||
.hal_umac_ce0_src_reg_base = 0x01b80000,
|
||||
.hal_umac_ce0_dest_reg_base = 0x01b81000,
|
||||
.hal_umac_ce1_src_reg_base = 0x01b82000,
|
||||
.hal_umac_ce1_dest_reg_base = 0x01b83000,
|
||||
};
|
||||
|
||||
static const struct ath12k_hw_regs ipq5332_regs = {
|
||||
/* SW2TCL(x) R0 ring configuration address */
|
||||
.hal_tcl1_ring_id = 0x00000918,
|
||||
.hal_tcl1_ring_misc = 0x00000920,
|
||||
.hal_tcl1_ring_tp_addr_lsb = 0x0000092c,
|
||||
.hal_tcl1_ring_tp_addr_msb = 0x00000930,
|
||||
.hal_tcl1_ring_consumer_int_setup_ix0 = 0x00000940,
|
||||
.hal_tcl1_ring_consumer_int_setup_ix1 = 0x00000944,
|
||||
.hal_tcl1_ring_msi1_base_lsb = 0x00000958,
|
||||
.hal_tcl1_ring_msi1_base_msb = 0x0000095c,
|
||||
.hal_tcl1_ring_base_lsb = 0x00000910,
|
||||
.hal_tcl1_ring_base_msb = 0x00000914,
|
||||
.hal_tcl1_ring_msi1_data = 0x00000960,
|
||||
.hal_tcl2_ring_base_lsb = 0x00000988,
|
||||
.hal_tcl_ring_base_lsb = 0x00000b68,
|
||||
|
||||
/* TCL STATUS ring address */
|
||||
.hal_tcl_status_ring_base_lsb = 0x00000d48,
|
||||
|
||||
/* REO DEST ring address */
|
||||
.hal_reo2_ring_base = 0x00000578,
|
||||
.hal_reo1_misc_ctrl_addr = 0x00000b9c,
|
||||
.hal_reo1_sw_cookie_cfg0 = 0x0000006c,
|
||||
.hal_reo1_sw_cookie_cfg1 = 0x00000070,
|
||||
.hal_reo1_qdesc_lut_base0 = 0x00000074,
|
||||
.hal_reo1_qdesc_lut_base1 = 0x00000078,
|
||||
.hal_reo1_ring_base_lsb = 0x00000500,
|
||||
.hal_reo1_ring_base_msb = 0x00000504,
|
||||
.hal_reo1_ring_id = 0x00000508,
|
||||
.hal_reo1_ring_misc = 0x00000510,
|
||||
.hal_reo1_ring_hp_addr_lsb = 0x00000514,
|
||||
.hal_reo1_ring_hp_addr_msb = 0x00000518,
|
||||
.hal_reo1_ring_producer_int_setup = 0x00000524,
|
||||
.hal_reo1_ring_msi1_base_lsb = 0x00000548,
|
||||
.hal_reo1_ring_msi1_base_msb = 0x0000054C,
|
||||
.hal_reo1_ring_msi1_data = 0x00000550,
|
||||
.hal_reo1_aging_thres_ix0 = 0x00000B28,
|
||||
.hal_reo1_aging_thres_ix1 = 0x00000B2C,
|
||||
.hal_reo1_aging_thres_ix2 = 0x00000B30,
|
||||
.hal_reo1_aging_thres_ix3 = 0x00000B34,
|
||||
|
||||
/* REO Exception ring address */
|
||||
.hal_reo2_sw0_ring_base = 0x000008c0,
|
||||
|
||||
/* REO Reinject ring address */
|
||||
.hal_sw2reo_ring_base = 0x00000320,
|
||||
.hal_sw2reo1_ring_base = 0x00000398,
|
||||
|
||||
/* REO cmd ring address */
|
||||
.hal_reo_cmd_ring_base = 0x000002A8,
|
||||
|
||||
/* REO status ring address */
|
||||
.hal_reo_status_ring_base = 0x00000aa0,
|
||||
|
||||
/* WBM idle link ring address */
|
||||
.hal_wbm_idle_ring_base_lsb = 0x00000d3c,
|
||||
.hal_wbm_idle_ring_misc_addr = 0x00000d4c,
|
||||
.hal_wbm_r0_idle_list_cntl_addr = 0x00000240,
|
||||
.hal_wbm_r0_idle_list_size_addr = 0x00000244,
|
||||
.hal_wbm_scattered_ring_base_lsb = 0x00000250,
|
||||
.hal_wbm_scattered_ring_base_msb = 0x00000254,
|
||||
.hal_wbm_scattered_desc_head_info_ix0 = 0x00000260,
|
||||
.hal_wbm_scattered_desc_head_info_ix1 = 0x00000264,
|
||||
.hal_wbm_scattered_desc_tail_info_ix0 = 0x00000270,
|
||||
.hal_wbm_scattered_desc_tail_info_ix1 = 0x00000274,
|
||||
.hal_wbm_scattered_desc_ptr_hp_addr = 0x0000027c,
|
||||
|
||||
/* SW2WBM release ring address */
|
||||
.hal_wbm_sw_release_ring_base_lsb = 0x0000037c,
|
||||
|
||||
/* WBM2SW release ring address */
|
||||
.hal_wbm0_release_ring_base_lsb = 0x00000e08,
|
||||
.hal_wbm1_release_ring_base_lsb = 0x00000e80,
|
||||
|
||||
/* PPE release ring address */
|
||||
.hal_ppe_rel_ring_base = 0x0000046c,
|
||||
|
||||
/* CE address */
|
||||
.hal_umac_ce0_src_reg_base = 0x00740000 -
|
||||
HAL_IPQ5332_CE_WFSS_REG_BASE,
|
||||
.hal_umac_ce0_dest_reg_base = 0x00741000 -
|
||||
HAL_IPQ5332_CE_WFSS_REG_BASE,
|
||||
.hal_umac_ce1_src_reg_base = 0x00742000 -
|
||||
HAL_IPQ5332_CE_WFSS_REG_BASE,
|
||||
.hal_umac_ce1_dest_reg_base = 0x00743000 -
|
||||
HAL_IPQ5332_CE_WFSS_REG_BASE,
|
||||
};
|
||||
|
||||
static const struct ath12k_hw_regs wcn7850_regs = {
|
||||
|
|
@ -775,6 +1134,9 @@ static const struct ath12k_hw_regs wcn7850_regs = {
|
|||
.hal_tcl1_ring_msi1_base_msb = 0x0000094c,
|
||||
.hal_tcl1_ring_msi1_data = 0x00000950,
|
||||
.hal_tcl_ring_base_lsb = 0x00000b58,
|
||||
.hal_tcl1_ring_base_lsb = 0x00000900,
|
||||
.hal_tcl1_ring_base_msb = 0x00000904,
|
||||
.hal_tcl2_ring_base_lsb = 0x00000978,
|
||||
|
||||
/* TCL STATUS ring address */
|
||||
.hal_tcl_status_ring_base_lsb = 0x00000d38,
|
||||
|
|
@ -837,6 +1199,12 @@ static const struct ath12k_hw_regs wcn7850_regs = {
|
|||
|
||||
/* REO status ring address */
|
||||
.hal_reo_status_ring_base = 0x00000a84,
|
||||
|
||||
/* CE base address */
|
||||
.hal_umac_ce0_src_reg_base = 0x01b80000,
|
||||
.hal_umac_ce0_dest_reg_base = 0x01b81000,
|
||||
.hal_umac_ce1_src_reg_base = 0x01b82000,
|
||||
.hal_umac_ce1_dest_reg_base = 0x01b83000,
|
||||
};
|
||||
|
||||
static const struct ath12k_hw_hal_params ath12k_hw_hal_params_qcn9274 = {
|
||||
|
|
@ -856,6 +1224,26 @@ static const struct ath12k_hw_hal_params ath12k_hw_hal_params_wcn7850 = {
|
|||
HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW4_EN,
|
||||
};
|
||||
|
||||
static const struct ath12k_hw_hal_params ath12k_hw_hal_params_ipq5332 = {
|
||||
.rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM,
|
||||
.wbm2sw_cc_enable = HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW0_EN |
|
||||
HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW1_EN |
|
||||
HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW2_EN |
|
||||
HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW3_EN |
|
||||
HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW4_EN,
|
||||
};
|
||||
|
||||
static const struct ce_ie_addr ath12k_ce_ie_addr_ipq5332 = {
|
||||
.ie1_reg_addr = CE_HOST_IE_ADDRESS - HAL_IPQ5332_CE_WFSS_REG_BASE,
|
||||
.ie2_reg_addr = CE_HOST_IE_2_ADDRESS - HAL_IPQ5332_CE_WFSS_REG_BASE,
|
||||
.ie3_reg_addr = CE_HOST_IE_3_ADDRESS - HAL_IPQ5332_CE_WFSS_REG_BASE,
|
||||
};
|
||||
|
||||
static const struct ce_remap ath12k_ce_remap_ipq5332 = {
|
||||
.base = HAL_IPQ5332_CE_WFSS_REG_BASE,
|
||||
.size = HAL_IPQ5332_CE_SIZE,
|
||||
};
|
||||
|
||||
static const struct ath12k_hw_params ath12k_hw_params[] = {
|
||||
{
|
||||
.name = "qcn9274 hw1.0",
|
||||
|
|
@ -864,6 +1252,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
|||
.dir = "QCN9274/hw1.0",
|
||||
.board_size = 256 * 1024,
|
||||
.cal_offset = 128 * 1024,
|
||||
.m3_loader = ath12k_m3_fw_loader_driver,
|
||||
},
|
||||
.max_radios = 1,
|
||||
.single_pdev_only = false,
|
||||
|
|
@ -899,7 +1288,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
|||
.download_calib = true,
|
||||
.supports_suspend = false,
|
||||
.tcl_ring_retry = true,
|
||||
.reoq_lut_support = false,
|
||||
.reoq_lut_support = true,
|
||||
.supports_shadow_regs = false,
|
||||
|
||||
.num_tcl_banks = 48,
|
||||
|
|
@ -932,6 +1321,14 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
|||
.iova_mask = 0,
|
||||
|
||||
.supports_aspm = false,
|
||||
|
||||
.ce_ie_addr = NULL,
|
||||
.ce_remap = NULL,
|
||||
.bdf_addr_offset = 0,
|
||||
|
||||
.current_cc_support = false,
|
||||
|
||||
.dp_primary_link_only = true,
|
||||
},
|
||||
{
|
||||
.name = "wcn7850 hw2.0",
|
||||
|
|
@ -941,6 +1338,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
|||
.dir = "WCN7850/hw2.0",
|
||||
.board_size = 256 * 1024,
|
||||
.cal_offset = 256 * 1024,
|
||||
.m3_loader = ath12k_m3_fw_loader_driver,
|
||||
},
|
||||
|
||||
.max_radios = 1,
|
||||
|
|
@ -1012,6 +1410,14 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
|||
.iova_mask = ATH12K_PCIE_MAX_PAYLOAD_SIZE - 1,
|
||||
|
||||
.supports_aspm = true,
|
||||
|
||||
.ce_ie_addr = NULL,
|
||||
.ce_remap = NULL,
|
||||
.bdf_addr_offset = 0,
|
||||
|
||||
.current_cc_support = true,
|
||||
|
||||
.dp_primary_link_only = false,
|
||||
},
|
||||
{
|
||||
.name = "qcn9274 hw2.0",
|
||||
|
|
@ -1020,6 +1426,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
|||
.dir = "QCN9274/hw2.0",
|
||||
.board_size = 256 * 1024,
|
||||
.cal_offset = 128 * 1024,
|
||||
.m3_loader = ath12k_m3_fw_loader_driver,
|
||||
},
|
||||
.max_radios = 2,
|
||||
.single_pdev_only = false,
|
||||
|
|
@ -1049,7 +1456,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
|||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_MESH_POINT) |
|
||||
BIT(NL80211_IFTYPE_AP_VLAN),
|
||||
.supports_monitor = false,
|
||||
.supports_monitor = true,
|
||||
|
||||
.idle_ps = false,
|
||||
.download_calib = true,
|
||||
|
|
@ -1088,6 +1495,92 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
|||
.iova_mask = 0,
|
||||
|
||||
.supports_aspm = false,
|
||||
|
||||
.ce_ie_addr = NULL,
|
||||
.ce_remap = NULL,
|
||||
.bdf_addr_offset = 0,
|
||||
|
||||
.current_cc_support = false,
|
||||
|
||||
.dp_primary_link_only = true,
|
||||
},
|
||||
{
|
||||
.name = "ipq5332 hw1.0",
|
||||
.hw_rev = ATH12K_HW_IPQ5332_HW10,
|
||||
.fw = {
|
||||
.dir = "IPQ5332/hw1.0",
|
||||
.board_size = 256 * 1024,
|
||||
.cal_offset = 128 * 1024,
|
||||
.m3_loader = ath12k_m3_fw_loader_remoteproc,
|
||||
},
|
||||
.max_radios = 1,
|
||||
.single_pdev_only = false,
|
||||
.qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ5332,
|
||||
.internal_sleep_clock = false,
|
||||
|
||||
.hw_ops = &qcn9274_ops,
|
||||
.regs = &ipq5332_regs,
|
||||
.ring_mask = &ath12k_hw_ring_mask_ipq5332,
|
||||
|
||||
.host_ce_config = ath12k_host_ce_config_ipq5332,
|
||||
.ce_count = 12,
|
||||
.target_ce_config = ath12k_target_ce_config_wlan_ipq5332,
|
||||
.target_ce_count = 12,
|
||||
.svc_to_ce_map = ath12k_target_service_to_ce_map_wlan_ipq5332,
|
||||
.svc_to_ce_map_len = 18,
|
||||
|
||||
.hal_params = &ath12k_hw_hal_params_ipq5332,
|
||||
|
||||
.rxdma1_enable = false,
|
||||
.num_rxdma_per_pdev = 1,
|
||||
.num_rxdma_dst_ring = 0,
|
||||
.rx_mac_buf_ring = false,
|
||||
.vdev_start_delay = false,
|
||||
|
||||
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_MESH_POINT),
|
||||
.supports_monitor = false,
|
||||
|
||||
.idle_ps = false,
|
||||
.download_calib = true,
|
||||
.supports_suspend = false,
|
||||
.tcl_ring_retry = true,
|
||||
.reoq_lut_support = false,
|
||||
.supports_shadow_regs = false,
|
||||
|
||||
.num_tcl_banks = 48,
|
||||
.max_tx_ring = 4,
|
||||
|
||||
.wmi_init = &ath12k_wmi_init_qcn9274,
|
||||
|
||||
.hal_ops = &hal_qcn9274_ops,
|
||||
|
||||
.qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01),
|
||||
|
||||
.rfkill_pin = 0,
|
||||
.rfkill_cfg = 0,
|
||||
.rfkill_on_level = 0,
|
||||
|
||||
.rddm_size = 0,
|
||||
|
||||
.def_num_link = 0,
|
||||
.max_mlo_peer = 256,
|
||||
|
||||
.otp_board_id_register = 0,
|
||||
|
||||
.supports_sta_ps = false,
|
||||
|
||||
.acpi_guid = NULL,
|
||||
.supports_dynamic_smps_6ghz = false,
|
||||
.iova_mask = 0,
|
||||
.supports_aspm = false,
|
||||
|
||||
.ce_ie_addr = &ath12k_ce_ie_addr_ipq5332,
|
||||
.ce_remap = &ath12k_ce_remap_ipq5332,
|
||||
.bdf_addr_offset = 0xC00000,
|
||||
|
||||
.dp_primary_link_only = true,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* 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.
|
||||
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH12K_HW_H
|
||||
|
|
@ -97,6 +97,7 @@
|
|||
#define ATH12K_REGDB_FILE_NAME "regdb.bin"
|
||||
|
||||
#define ATH12K_PCIE_MAX_PAYLOAD_SIZE 128
|
||||
#define ATH12K_IPQ5332_USERPD_ID 1
|
||||
|
||||
enum ath12k_hw_rate_cck {
|
||||
ATH12K_HW_RATE_CCK_LP_11M = 0,
|
||||
|
|
@ -121,6 +122,7 @@ enum ath12k_hw_rate_ofdm {
|
|||
|
||||
enum ath12k_bus {
|
||||
ATH12K_BUS_PCI,
|
||||
ATH12K_BUS_AHB,
|
||||
};
|
||||
|
||||
#define ATH12K_EXT_IRQ_GRP_NUM_MAX 11
|
||||
|
|
@ -146,6 +148,11 @@ struct ath12k_hw_hal_params {
|
|||
u32 wbm2sw_cc_enable;
|
||||
};
|
||||
|
||||
enum ath12k_m3_fw_loaders {
|
||||
ath12k_m3_fw_loader_driver,
|
||||
ath12k_m3_fw_loader_remoteproc,
|
||||
};
|
||||
|
||||
struct ath12k_hw_params {
|
||||
const char *name;
|
||||
u16 hw_rev;
|
||||
|
|
@ -154,6 +161,7 @@ struct ath12k_hw_params {
|
|||
const char *dir;
|
||||
size_t board_size;
|
||||
size_t cal_offset;
|
||||
enum ath12k_m3_fw_loaders m3_loader;
|
||||
} fw;
|
||||
|
||||
u8 max_radios;
|
||||
|
|
@ -190,6 +198,7 @@ struct ath12k_hw_params {
|
|||
bool reoq_lut_support:1;
|
||||
bool supports_shadow_regs:1;
|
||||
bool supports_aspm:1;
|
||||
bool current_cc_support:1;
|
||||
|
||||
u32 num_tcl_banks;
|
||||
u32 max_tx_ring;
|
||||
|
|
@ -220,6 +229,13 @@ struct ath12k_hw_params {
|
|||
bool supports_dynamic_smps_6ghz;
|
||||
|
||||
u32 iova_mask;
|
||||
|
||||
const struct ce_ie_addr *ce_ie_addr;
|
||||
const struct ce_remap *ce_remap;
|
||||
u32 bdf_addr_offset;
|
||||
|
||||
/* setup REO queue, frag etc only for primary link peer */
|
||||
bool dp_primary_link_only:1;
|
||||
};
|
||||
|
||||
struct ath12k_hw_ops {
|
||||
|
|
@ -293,9 +309,15 @@ struct ath12k_hw_regs {
|
|||
u32 hal_tcl1_ring_msi1_base_msb;
|
||||
u32 hal_tcl1_ring_msi1_data;
|
||||
u32 hal_tcl_ring_base_lsb;
|
||||
u32 hal_tcl1_ring_base_lsb;
|
||||
u32 hal_tcl1_ring_base_msb;
|
||||
u32 hal_tcl2_ring_base_lsb;
|
||||
|
||||
u32 hal_tcl_status_ring_base_lsb;
|
||||
|
||||
u32 hal_reo1_qdesc_addr;
|
||||
u32 hal_reo1_qdesc_max_peerid;
|
||||
|
||||
u32 hal_wbm_idle_ring_base_lsb;
|
||||
u32 hal_wbm_idle_ring_misc_addr;
|
||||
u32 hal_wbm_r0_idle_list_cntl_addr;
|
||||
|
|
@ -316,6 +338,11 @@ struct ath12k_hw_regs {
|
|||
u32 pcie_qserdes_sysclk_en_sel;
|
||||
u32 pcie_pcs_osc_dtct_config_base;
|
||||
|
||||
u32 hal_umac_ce0_src_reg_base;
|
||||
u32 hal_umac_ce0_dest_reg_base;
|
||||
u32 hal_umac_ce1_src_reg_base;
|
||||
u32 hal_umac_ce1_dest_reg_base;
|
||||
|
||||
u32 hal_ppe_rel_ring_base;
|
||||
|
||||
u32 hal_reo2_ring_base;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -33,6 +33,9 @@ struct ath12k_generic_iter {
|
|||
#define ATH12K_KEEPALIVE_MAX_IDLE 3895
|
||||
#define ATH12K_KEEPALIVE_MAX_UNRESPONSIVE 3900
|
||||
|
||||
#define ATH12K_PDEV_TX_POWER_INVALID ((u32)-1)
|
||||
#define ATH12K_PDEV_TX_POWER_REFRESH_TIME_MSECS 5000 /* msecs */
|
||||
|
||||
/* FIXME: should these be in ieee80211.h? */
|
||||
#define IEEE80211_VHT_MCS_SUPPORT_0_11_MASK GENMASK(23, 16)
|
||||
#define IEEE80211_DISABLE_VHT_MCS_SUPPORT_0_11 BIT(24)
|
||||
|
|
@ -66,6 +69,13 @@ struct ath12k_mac_get_any_chanctx_conf_arg {
|
|||
|
||||
extern const struct htt_rx_ring_tlv_filter ath12k_mac_mon_status_filter_default;
|
||||
|
||||
#define ATH12K_SCAN_11D_INTERVAL 600000
|
||||
#define ATH12K_11D_INVALID_VDEV_ID 0xFFFF
|
||||
|
||||
void ath12k_mac_11d_scan_start(struct ath12k *ar, u32 vdev_id);
|
||||
void ath12k_mac_11d_scan_stop(struct ath12k *ar);
|
||||
void ath12k_mac_11d_scan_stop_all(struct ath12k_base *ab);
|
||||
|
||||
void ath12k_mac_destroy(struct ath12k_hw_group *ag);
|
||||
void ath12k_mac_unregister(struct ath12k_hw_group *ag);
|
||||
int ath12k_mac_register(struct ath12k_hw_group *ag);
|
||||
|
|
@ -115,4 +125,7 @@ struct ieee80211_bss_conf *ath12k_mac_get_link_bss_conf(struct ath12k_link_vif *
|
|||
struct ath12k *ath12k_get_ar_by_vif(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
u8 link_id);
|
||||
int ath12k_mac_get_fw_stats(struct ath12k *ar, struct ath12k_fw_stats_req_params *param);
|
||||
void ath12k_mac_update_freq_range(struct ath12k *ar,
|
||||
u32 freq_low, u32 freq_high);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/msi.h>
|
||||
|
|
@ -285,8 +285,11 @@ static void ath12k_mhi_op_status_cb(struct mhi_controller *mhi_cntrl,
|
|||
break;
|
||||
}
|
||||
|
||||
if (!(test_bit(ATH12K_FLAG_UNREGISTERING, &ab->dev_flags)))
|
||||
if (!(test_bit(ATH12K_FLAG_UNREGISTERING, &ab->dev_flags))) {
|
||||
set_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags);
|
||||
set_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags);
|
||||
queue_work(ab->workqueue_aux, &ab->reset_work);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -379,7 +382,7 @@ int ath12k_mhi_register(struct ath12k_pci *ab_pci)
|
|||
mhi_ctrl->irq_flags = IRQF_SHARED | IRQF_NOBALANCING;
|
||||
|
||||
mhi_ctrl->iova_start = 0;
|
||||
mhi_ctrl->iova_stop = 0xffffffff;
|
||||
mhi_ctrl->iova_stop = ab_pci->dma_mask;
|
||||
mhi_ctrl->sbl_size = SZ_512K;
|
||||
mhi_ctrl->seg_len = SZ_512K;
|
||||
mhi_ctrl->fbc_download = true;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
#include "debug.h"
|
||||
|
||||
#define ATH12K_PCI_BAR_NUM 0
|
||||
#define ATH12K_PCI_DMA_MASK 32
|
||||
#define ATH12K_PCI_DMA_MASK 36
|
||||
|
||||
#define ATH12K_PCI_IRQ_CE0_OFFSET 3
|
||||
|
||||
|
|
@ -718,7 +718,7 @@ static void ath12k_pci_init_qmi_ce_config(struct ath12k_base *ab)
|
|||
cfg->svc_to_ce_map_len = ab->hw_params->svc_to_ce_map_len;
|
||||
ab->qmi.service_ins_id = ab->hw_params->qmi_service_ins_id;
|
||||
|
||||
if (test_bit(ATH12K_FW_FEATURE_MULTI_QRTR_ID, ab->fw.fw_features)) {
|
||||
if (ath12k_fw_feature_supported(ab, ATH12K_FW_FEATURE_MULTI_QRTR_ID)) {
|
||||
ab_pci->qmi_instance =
|
||||
u32_encode_bits(pci_domain_nr(bus), DOMAIN_NUMBER_MASK) |
|
||||
u32_encode_bits(bus->number, BUS_NUMBER_MASK);
|
||||
|
|
@ -877,13 +877,9 @@ static int ath12k_pci_claim(struct ath12k_pci *ab_pci, struct pci_dev *pdev)
|
|||
goto disable_device;
|
||||
}
|
||||
|
||||
ret = dma_set_mask_and_coherent(&pdev->dev,
|
||||
DMA_BIT_MASK(ATH12K_PCI_DMA_MASK));
|
||||
if (ret) {
|
||||
ath12k_err(ab, "failed to set pci dma mask to %d: %d\n",
|
||||
ATH12K_PCI_DMA_MASK, ret);
|
||||
goto release_region;
|
||||
}
|
||||
ab_pci->dma_mask = DMA_BIT_MASK(ATH12K_PCI_DMA_MASK);
|
||||
dma_set_mask(&pdev->dev, ab_pci->dma_mask);
|
||||
dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
|
|
@ -1472,7 +1468,7 @@ int ath12k_pci_power_up(struct ath12k_base *ab)
|
|||
|
||||
ath12k_pci_msi_enable(ab_pci);
|
||||
|
||||
if (test_bit(ATH12K_FW_FEATURE_MULTI_QRTR_ID, ab->fw.fw_features))
|
||||
if (ath12k_fw_feature_supported(ab, ATH12K_FW_FEATURE_MULTI_QRTR_ID))
|
||||
ath12k_pci_update_qrtr_node_id(ab);
|
||||
|
||||
ret = ath12k_mhi_start(ab_pci);
|
||||
|
|
@ -1491,6 +1487,9 @@ void ath12k_pci_power_down(struct ath12k_base *ab, bool is_suspend)
|
|||
{
|
||||
struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
|
||||
|
||||
if (!test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags))
|
||||
return;
|
||||
|
||||
/* restore aspm in case firmware bootup fails */
|
||||
ath12k_pci_aspm_restore(ab_pci);
|
||||
|
||||
|
|
@ -1710,12 +1709,12 @@ static int ath12k_pci_probe(struct pci_dev *pdev,
|
|||
err_mhi_unregister:
|
||||
ath12k_mhi_unregister(ab_pci);
|
||||
|
||||
err_pci_msi_free:
|
||||
ath12k_pci_msi_free(ab_pci);
|
||||
|
||||
err_irq_affinity_cleanup:
|
||||
ath12k_pci_set_irq_affinity_hint(ab_pci, NULL);
|
||||
|
||||
err_pci_msi_free:
|
||||
ath12k_pci_msi_free(ab_pci);
|
||||
|
||||
err_pci_free_region:
|
||||
ath12k_pci_free_region(ab_pci);
|
||||
|
||||
|
|
@ -1758,13 +1757,34 @@ static void ath12k_pci_remove(struct pci_dev *pdev)
|
|||
ath12k_core_free(ab);
|
||||
}
|
||||
|
||||
static void ath12k_pci_hw_group_power_down(struct ath12k_hw_group *ag)
|
||||
{
|
||||
struct ath12k_base *ab;
|
||||
int i;
|
||||
|
||||
if (!ag)
|
||||
return;
|
||||
|
||||
mutex_lock(&ag->mutex);
|
||||
|
||||
for (i = 0; i < ag->num_devices; i++) {
|
||||
ab = ag->ab[i];
|
||||
if (!ab)
|
||||
continue;
|
||||
|
||||
ath12k_pci_power_down(ab, false);
|
||||
}
|
||||
|
||||
mutex_unlock(&ag->mutex);
|
||||
}
|
||||
|
||||
static void ath12k_pci_shutdown(struct pci_dev *pdev)
|
||||
{
|
||||
struct ath12k_base *ab = pci_get_drvdata(pdev);
|
||||
struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
|
||||
|
||||
ath12k_pci_set_irq_affinity_hint(ab_pci, NULL);
|
||||
ath12k_pci_power_down(ab, false);
|
||||
ath12k_pci_hw_group_power_down(ab->ag);
|
||||
}
|
||||
|
||||
static __maybe_unused int ath12k_pci_pm_suspend(struct device *dev)
|
||||
|
|
@ -1831,7 +1851,7 @@ static struct pci_driver ath12k_pci_driver = {
|
|||
.driver.pm = &ath12k_pci_pm_ops,
|
||||
};
|
||||
|
||||
static int ath12k_pci_init(void)
|
||||
int ath12k_pci_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
|
@ -1844,14 +1864,8 @@ static int ath12k_pci_init(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
module_init(ath12k_pci_init);
|
||||
|
||||
static void ath12k_pci_exit(void)
|
||||
void ath12k_pci_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&ath12k_pci_driver);
|
||||
}
|
||||
|
||||
module_exit(ath12k_pci_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Driver support for Qualcomm Technologies PCIe 802.11be WLAN devices");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef ATH12K_PCI_H
|
||||
#define ATH12K_PCI_H
|
||||
|
|
@ -116,6 +116,7 @@ struct ath12k_pci {
|
|||
unsigned long irq_flags;
|
||||
const struct ath12k_pci_ops *pci_ops;
|
||||
u32 qmi_instance;
|
||||
u64 dma_mask;
|
||||
};
|
||||
|
||||
static inline struct ath12k_pci *ath12k_pci_priv(struct ath12k_base *ab)
|
||||
|
|
@ -145,4 +146,6 @@ void ath12k_pci_stop(struct ath12k_base *ab);
|
|||
int ath12k_pci_start(struct ath12k_base *ab);
|
||||
int ath12k_pci_power_up(struct ath12k_base *ab);
|
||||
void ath12k_pci_power_down(struct ath12k_base *ab, bool is_suspend);
|
||||
int ath12k_pci_init(void);
|
||||
void ath12k_pci_exit(void);
|
||||
#endif /* ATH12K_PCI_H */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2022, 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
|
|
@ -383,6 +383,9 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
|
|||
arvif->ast_idx = peer->hw_peer_id;
|
||||
}
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
peer->ucast_ra_only = true;
|
||||
|
||||
if (sta) {
|
||||
ahsta = ath12k_sta_to_ahsta(sta);
|
||||
arsta = wiphy_dereference(ath12k_ar_to_hw(ar)->wiphy,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* 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.
|
||||
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH12K_PEER_H
|
||||
|
|
@ -62,6 +62,7 @@ struct ath12k_peer {
|
|||
|
||||
/* for reference to ath12k_link_sta */
|
||||
u8 link_id;
|
||||
bool ucast_ra_only;
|
||||
};
|
||||
|
||||
struct ath12k_ml_peer {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
#include "debug.h"
|
||||
#include <linux/of.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/ioport.h>
|
||||
|
||||
#define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02
|
||||
#define HOST_CSTATE_BIT 0x04
|
||||
|
|
@ -2168,10 +2170,12 @@ int ath12k_qmi_host_cap_send(struct ath12k_base *ab)
|
|||
req.bdf_support_valid = 1;
|
||||
req.bdf_support = 1;
|
||||
|
||||
req.m3_support_valid = 1;
|
||||
req.m3_support = 1;
|
||||
req.m3_cache_support_valid = 1;
|
||||
req.m3_cache_support = 1;
|
||||
if (ab->hw_params->fw.m3_loader == ath12k_m3_fw_loader_driver) {
|
||||
req.m3_support_valid = 1;
|
||||
req.m3_support = 1;
|
||||
req.m3_cache_support_valid = 1;
|
||||
req.m3_cache_support = 1;
|
||||
}
|
||||
|
||||
req.cal_done_valid = 1;
|
||||
req.cal_done = ab->qmi.cal_done;
|
||||
|
|
@ -2264,6 +2268,9 @@ static void ath12k_qmi_phy_cap_send(struct ath12k_base *ab)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (resp.single_chip_mlo_support_valid && resp.single_chip_mlo_support)
|
||||
ab->single_chip_mlo_support = true;
|
||||
|
||||
if (!resp.num_phy_valid) {
|
||||
ret = -ENODATA;
|
||||
goto out;
|
||||
|
|
@ -2272,7 +2279,8 @@ static void ath12k_qmi_phy_cap_send(struct ath12k_base *ab)
|
|||
ab->qmi.num_radios = resp.num_phy;
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_QMI,
|
||||
"phy capability resp valid %d num_phy %d valid %d board_id %d\n",
|
||||
"phy capability resp valid %d single_chip_mlo_support %d valid %d num_phy %d valid %d board_id %d\n",
|
||||
resp.single_chip_mlo_support_valid, resp.single_chip_mlo_support,
|
||||
resp.num_phy_valid, resp.num_phy,
|
||||
resp.board_id_valid, resp.board_id);
|
||||
|
||||
|
|
@ -2376,7 +2384,8 @@ int ath12k_qmi_respond_fw_mem_request(struct ath12k_base *ab)
|
|||
* failure to firmware and firmware then request multiple blocks of
|
||||
* small chunk size memory.
|
||||
*/
|
||||
if (ab->qmi.target_mem_delayed) {
|
||||
if (!test_bit(ATH12K_FLAG_FIXED_MEM_REGION, &ab->dev_flags) &&
|
||||
ab->qmi.target_mem_delayed) {
|
||||
delayed = true;
|
||||
ath12k_dbg(ab, ATH12K_DBG_QMI, "qmi delays mem_request %d\n",
|
||||
ab->qmi.mem_seg_count);
|
||||
|
|
@ -2434,12 +2443,35 @@ int ath12k_qmi_respond_fw_mem_request(struct ath12k_base *ab)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void ath12k_qmi_reset_mlo_mem(struct ath12k_hw_group *ag)
|
||||
{
|
||||
struct target_mem_chunk *mlo_chunk;
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(&ag->mutex);
|
||||
|
||||
if (!ag->mlo_mem.init_done || ag->num_started)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ag->mlo_mem.chunk); i++) {
|
||||
mlo_chunk = &ag->mlo_mem.chunk[i];
|
||||
|
||||
if (mlo_chunk->v.addr)
|
||||
/* TODO: Mode 0 recovery is the default mode hence resetting the
|
||||
* whole memory region for now. Once Mode 1 support is added, this
|
||||
* needs to be handled properly
|
||||
*/
|
||||
memset(mlo_chunk->v.addr, 0, mlo_chunk->size);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath12k_qmi_free_mlo_mem_chunk(struct ath12k_base *ab,
|
||||
struct target_mem_chunk *chunk,
|
||||
int idx)
|
||||
{
|
||||
struct ath12k_hw_group *ag = ab->ag;
|
||||
struct target_mem_chunk *mlo_chunk;
|
||||
bool fixed_mem;
|
||||
|
||||
lockdep_assert_held(&ag->mutex);
|
||||
|
||||
|
|
@ -2451,8 +2483,13 @@ static void ath12k_qmi_free_mlo_mem_chunk(struct ath12k_base *ab,
|
|||
return;
|
||||
}
|
||||
|
||||
fixed_mem = test_bit(ATH12K_FLAG_FIXED_MEM_REGION, &ab->dev_flags);
|
||||
mlo_chunk = &ag->mlo_mem.chunk[idx];
|
||||
if (mlo_chunk->v.addr) {
|
||||
|
||||
if (fixed_mem && mlo_chunk->v.ioaddr) {
|
||||
iounmap(mlo_chunk->v.ioaddr);
|
||||
mlo_chunk->v.ioaddr = NULL;
|
||||
} else if (mlo_chunk->v.addr) {
|
||||
dma_free_coherent(ab->dev,
|
||||
mlo_chunk->size,
|
||||
mlo_chunk->v.addr,
|
||||
|
|
@ -2462,7 +2499,10 @@ static void ath12k_qmi_free_mlo_mem_chunk(struct ath12k_base *ab,
|
|||
|
||||
mlo_chunk->paddr = 0;
|
||||
mlo_chunk->size = 0;
|
||||
chunk->v.addr = NULL;
|
||||
if (fixed_mem)
|
||||
chunk->v.ioaddr = NULL;
|
||||
else
|
||||
chunk->v.addr = NULL;
|
||||
chunk->paddr = 0;
|
||||
chunk->size = 0;
|
||||
}
|
||||
|
|
@ -2473,19 +2513,24 @@ static void ath12k_qmi_free_target_mem_chunk(struct ath12k_base *ab)
|
|||
int i, mlo_idx;
|
||||
|
||||
for (i = 0, mlo_idx = 0; i < ab->qmi.mem_seg_count; i++) {
|
||||
if (!ab->qmi.target_mem[i].v.addr)
|
||||
continue;
|
||||
|
||||
if (ab->qmi.target_mem[i].type == MLO_GLOBAL_MEM_REGION_TYPE) {
|
||||
ath12k_qmi_free_mlo_mem_chunk(ab,
|
||||
&ab->qmi.target_mem[i],
|
||||
mlo_idx++);
|
||||
} else {
|
||||
dma_free_coherent(ab->dev,
|
||||
ab->qmi.target_mem[i].prev_size,
|
||||
ab->qmi.target_mem[i].v.addr,
|
||||
ab->qmi.target_mem[i].paddr);
|
||||
ab->qmi.target_mem[i].v.addr = NULL;
|
||||
if (test_bit(ATH12K_FLAG_FIXED_MEM_REGION, &ab->dev_flags) &&
|
||||
ab->qmi.target_mem[i].v.ioaddr) {
|
||||
iounmap(ab->qmi.target_mem[i].v.ioaddr);
|
||||
ab->qmi.target_mem[i].v.ioaddr = NULL;
|
||||
} else {
|
||||
if (!ab->qmi.target_mem[i].v.addr)
|
||||
continue;
|
||||
dma_free_coherent(ab->dev,
|
||||
ab->qmi.target_mem[i].prev_size,
|
||||
ab->qmi.target_mem[i].v.addr,
|
||||
ab->qmi.target_mem[i].paddr);
|
||||
ab->qmi.target_mem[i].v.addr = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2638,6 +2683,130 @@ static int ath12k_qmi_alloc_target_mem_chunk(struct ath12k_base *ab)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int ath12k_qmi_assign_target_mem_chunk(struct ath12k_base *ab)
|
||||
{
|
||||
struct reserved_mem *rmem;
|
||||
size_t avail_rmem_size;
|
||||
int i, idx, ret;
|
||||
|
||||
for (i = 0, idx = 0; i < ab->qmi.mem_seg_count; i++) {
|
||||
switch (ab->qmi.target_mem[i].type) {
|
||||
case HOST_DDR_REGION_TYPE:
|
||||
rmem = ath12k_core_get_reserved_mem(ab, 0);
|
||||
if (!rmem) {
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
avail_rmem_size = rmem->size;
|
||||
if (avail_rmem_size < ab->qmi.target_mem[i].size) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_QMI,
|
||||
"failed to assign mem type %u req size %u avail size %zu\n",
|
||||
ab->qmi.target_mem[i].type,
|
||||
ab->qmi.target_mem[i].size,
|
||||
avail_rmem_size);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ab->qmi.target_mem[idx].paddr = rmem->base;
|
||||
ab->qmi.target_mem[idx].v.ioaddr =
|
||||
ioremap(ab->qmi.target_mem[idx].paddr,
|
||||
ab->qmi.target_mem[i].size);
|
||||
if (!ab->qmi.target_mem[idx].v.ioaddr) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
|
||||
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
|
||||
idx++;
|
||||
break;
|
||||
case BDF_MEM_REGION_TYPE:
|
||||
rmem = ath12k_core_get_reserved_mem(ab, 0);
|
||||
if (!rmem) {
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
avail_rmem_size = rmem->size - ab->hw_params->bdf_addr_offset;
|
||||
if (avail_rmem_size < ab->qmi.target_mem[i].size) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_QMI,
|
||||
"failed to assign mem type %u req size %u avail size %zu\n",
|
||||
ab->qmi.target_mem[i].type,
|
||||
ab->qmi.target_mem[i].size,
|
||||
avail_rmem_size);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
ab->qmi.target_mem[idx].paddr =
|
||||
rmem->base + ab->hw_params->bdf_addr_offset;
|
||||
ab->qmi.target_mem[idx].v.ioaddr =
|
||||
ioremap(ab->qmi.target_mem[idx].paddr,
|
||||
ab->qmi.target_mem[i].size);
|
||||
if (!ab->qmi.target_mem[idx].v.ioaddr) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
|
||||
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
|
||||
idx++;
|
||||
break;
|
||||
case CALDB_MEM_REGION_TYPE:
|
||||
/* Cold boot calibration is not enabled in Ath12k. Hence,
|
||||
* assign paddr = 0.
|
||||
* Once cold boot calibration is enabled add support to
|
||||
* assign reserved memory from DT.
|
||||
*/
|
||||
ab->qmi.target_mem[idx].paddr = 0;
|
||||
ab->qmi.target_mem[idx].v.ioaddr = NULL;
|
||||
ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
|
||||
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
|
||||
idx++;
|
||||
break;
|
||||
case M3_DUMP_REGION_TYPE:
|
||||
rmem = ath12k_core_get_reserved_mem(ab, 1);
|
||||
if (!rmem) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
avail_rmem_size = rmem->size;
|
||||
if (avail_rmem_size < ab->qmi.target_mem[i].size) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_QMI,
|
||||
"failed to assign mem type %u req size %u avail size %zu\n",
|
||||
ab->qmi.target_mem[i].type,
|
||||
ab->qmi.target_mem[i].size,
|
||||
avail_rmem_size);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ab->qmi.target_mem[idx].paddr = rmem->base;
|
||||
ab->qmi.target_mem[idx].v.ioaddr =
|
||||
ioremap(ab->qmi.target_mem[idx].paddr,
|
||||
ab->qmi.target_mem[i].size);
|
||||
if (!ab->qmi.target_mem[idx].v.ioaddr) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
|
||||
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
|
||||
idx++;
|
||||
break;
|
||||
default:
|
||||
ath12k_warn(ab, "qmi ignore invalid mem req type %u\n",
|
||||
ab->qmi.target_mem[i].type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ab->qmi.mem_seg_count = idx;
|
||||
|
||||
return 0;
|
||||
out:
|
||||
ath12k_qmi_free_target_mem_chunk(ab);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* clang stack usage explodes if this is inlined */
|
||||
static noinline_for_stack
|
||||
int ath12k_qmi_request_target_cap(struct ath12k_base *ab)
|
||||
|
|
@ -2939,6 +3108,9 @@ static void ath12k_qmi_m3_free(struct ath12k_base *ab)
|
|||
{
|
||||
struct m3_mem_region *m3_mem = &ab->qmi.m3_mem;
|
||||
|
||||
if (ab->hw_params->fw.m3_loader == ath12k_m3_fw_loader_remoteproc)
|
||||
return;
|
||||
|
||||
if (!m3_mem->vaddr)
|
||||
return;
|
||||
|
||||
|
|
@ -3019,15 +3191,16 @@ int ath12k_qmi_wlanfw_m3_info_send(struct ath12k_base *ab)
|
|||
struct qmi_txn txn;
|
||||
int ret = 0;
|
||||
|
||||
ret = ath12k_qmi_m3_load(ab);
|
||||
if (ret) {
|
||||
ath12k_err(ab, "failed to load m3 firmware: %d", ret);
|
||||
return ret;
|
||||
if (ab->hw_params->fw.m3_loader == ath12k_m3_fw_loader_driver) {
|
||||
ret = ath12k_qmi_m3_load(ab);
|
||||
if (ret) {
|
||||
ath12k_err(ab, "failed to load m3 firmware: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
req.addr = m3_mem->paddr;
|
||||
req.size = m3_mem->size;
|
||||
}
|
||||
|
||||
req.addr = m3_mem->paddr;
|
||||
req.size = m3_mem->size;
|
||||
|
||||
ret = qmi_txn_init(&ab->qmi.handle, &txn,
|
||||
qmi_wlanfw_m3_info_resp_msg_v01_ei, &resp);
|
||||
if (ret < 0)
|
||||
|
|
@ -3477,11 +3650,20 @@ static void ath12k_qmi_msg_mem_request_cb(struct qmi_handle *qmi_hdl,
|
|||
msg->mem_seg[i].type, msg->mem_seg[i].size);
|
||||
}
|
||||
|
||||
ret = ath12k_qmi_alloc_target_mem_chunk(ab);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "qmi failed to alloc target memory: %d\n",
|
||||
ret);
|
||||
return;
|
||||
if (test_bit(ATH12K_FLAG_FIXED_MEM_REGION, &ab->dev_flags)) {
|
||||
ret = ath12k_qmi_assign_target_mem_chunk(ab);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to assign qmi target memory: %d\n",
|
||||
ret);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
ret = ath12k_qmi_alloc_target_mem_chunk(ab);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "qmi failed to alloc target memory: %d\n",
|
||||
ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ath12k_qmi_driver_event_post(qmi, ATH12K_QMI_EVENT_REQUEST_MEM, NULL);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* 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.
|
||||
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH12K_QMI_H
|
||||
|
|
@ -21,6 +21,7 @@
|
|||
#define ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_WCN7850 0x1
|
||||
|
||||
#define ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_QCN9274 0x07
|
||||
#define ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ5332 0x2
|
||||
#define ATH12K_QMI_WLANFW_MAX_TIMESTAMP_LEN_V01 32
|
||||
#define ATH12K_QMI_RESP_LEN_MAX 8192
|
||||
#define ATH12K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01 52
|
||||
|
|
@ -41,6 +42,7 @@
|
|||
#define ATH12K_BOARD_ID_DEFAULT 0xFF
|
||||
|
||||
struct ath12k_base;
|
||||
struct ath12k_hw_group;
|
||||
|
||||
enum ath12k_qmi_file_type {
|
||||
ATH12K_QMI_FILE_TYPE_BDF_GOLDEN = 0,
|
||||
|
|
@ -621,5 +623,6 @@ void ath12k_qmi_deinit_service(struct ath12k_base *ab);
|
|||
int ath12k_qmi_init_service(struct ath12k_base *ab);
|
||||
void ath12k_qmi_free_resource(struct ath12k_base *ab);
|
||||
void ath12k_qmi_trigger_host_cap(struct ath12k_base *ab);
|
||||
void ath12k_qmi_reset_mlo_mem(struct ath12k_hw_group *ag);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
// 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.
|
||||
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/rtnetlink.h>
|
||||
#include "core.h"
|
||||
#include "debug.h"
|
||||
#include "mac.h"
|
||||
|
||||
/* World regdom to be used in case default regd from fw is unavailable */
|
||||
#define ATH12K_2GHZ_CH01_11 REG_RULE(2412 - 10, 2462 + 10, 40, 0, 20, 0)
|
||||
|
|
@ -48,6 +49,7 @@ ath12k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
|
|||
{
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct ath12k_wmi_init_country_arg arg;
|
||||
struct wmi_set_current_country_arg current_arg = {};
|
||||
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
|
||||
struct ath12k *ar = ath12k_ah_to_ar(ah, 0);
|
||||
int ret, i;
|
||||
|
|
@ -55,6 +57,24 @@ ath12k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
|
|||
ath12k_dbg(ar->ab, ATH12K_DBG_REG,
|
||||
"Regulatory Notification received for %s\n", wiphy_name(wiphy));
|
||||
|
||||
if (request->initiator == NL80211_REGDOM_SET_BY_DRIVER) {
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_REG,
|
||||
"driver initiated regd update\n");
|
||||
if (ah->state != ATH12K_HW_STATE_ON)
|
||||
return;
|
||||
|
||||
for_each_ar(ah, ar, i) {
|
||||
ret = ath12k_reg_update_chan_list(ar, true);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab,
|
||||
"failed to update chan list for pdev %u, ret %d\n",
|
||||
i, ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Currently supporting only General User Hints. Cell base user
|
||||
* hints to be handled later.
|
||||
* Hints from other sources like Core, Beacons are not expected for
|
||||
|
|
@ -77,27 +97,38 @@ ath12k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Set the country code to the firmware and wait for
|
||||
* the WMI_REG_CHAN_LIST_CC EVENT for updating the
|
||||
* reg info
|
||||
*/
|
||||
arg.flags = ALPHA_IS_SET;
|
||||
memcpy(&arg.cc_info.alpha2, request->alpha2, 2);
|
||||
arg.cc_info.alpha2[2] = 0;
|
||||
|
||||
/* Allow fresh updates to wiphy regd */
|
||||
ah->regd_updated = false;
|
||||
|
||||
/* Send the reg change request to all the radios */
|
||||
for_each_ar(ah, ar, i) {
|
||||
ret = ath12k_wmi_send_init_country_cmd(ar, &arg);
|
||||
if (ret)
|
||||
ath12k_warn(ar->ab,
|
||||
"INIT Country code set to fw failed : %d\n", ret);
|
||||
if (ar->ab->hw_params->current_cc_support) {
|
||||
memcpy(¤t_arg.alpha2, request->alpha2, 2);
|
||||
memcpy(&ar->alpha2, ¤t_arg.alpha2, 2);
|
||||
ret = ath12k_wmi_send_set_current_country_cmd(ar, ¤t_arg);
|
||||
if (ret)
|
||||
ath12k_warn(ar->ab,
|
||||
"failed set current country code: %d\n", ret);
|
||||
} else {
|
||||
arg.flags = ALPHA_IS_SET;
|
||||
memcpy(&arg.cc_info.alpha2, request->alpha2, 2);
|
||||
arg.cc_info.alpha2[2] = 0;
|
||||
|
||||
ret = ath12k_wmi_send_init_country_cmd(ar, &arg);
|
||||
if (ret)
|
||||
ath12k_warn(ar->ab,
|
||||
"failed set INIT Country code: %d\n", ret);
|
||||
}
|
||||
|
||||
wiphy_lock(wiphy);
|
||||
ath12k_mac_11d_scan_stop(ar);
|
||||
wiphy_unlock(wiphy);
|
||||
|
||||
ar->regdom_set_by_user = true;
|
||||
}
|
||||
}
|
||||
|
||||
int ath12k_reg_update_chan_list(struct ath12k *ar)
|
||||
int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait)
|
||||
{
|
||||
struct ieee80211_supported_band **bands;
|
||||
struct ath12k_wmi_scan_chan_list_arg *arg;
|
||||
|
|
@ -106,7 +137,35 @@ int ath12k_reg_update_chan_list(struct ath12k *ar)
|
|||
struct ath12k_wmi_channel_arg *ch;
|
||||
enum nl80211_band band;
|
||||
int num_channels = 0;
|
||||
int i, ret;
|
||||
int i, ret, left;
|
||||
|
||||
if (wait && ar->state_11d != ATH12K_11D_IDLE) {
|
||||
left = wait_for_completion_timeout(&ar->completed_11d_scan,
|
||||
ATH12K_SCAN_TIMEOUT_HZ);
|
||||
if (!left) {
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_REG,
|
||||
"failed to receive 11d scan complete: timed out\n");
|
||||
ar->state_11d = ATH12K_11D_IDLE;
|
||||
}
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_REG,
|
||||
"reg 11d scan wait left time %d\n", left);
|
||||
}
|
||||
|
||||
if (wait &&
|
||||
(ar->scan.state == ATH12K_SCAN_STARTING ||
|
||||
ar->scan.state == ATH12K_SCAN_RUNNING)) {
|
||||
left = wait_for_completion_timeout(&ar->scan.completed,
|
||||
ATH12K_SCAN_TIMEOUT_HZ);
|
||||
if (!left)
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_REG,
|
||||
"failed to receive hw scan complete: timed out\n");
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_REG,
|
||||
"reg hw scan wait left time %d\n", left);
|
||||
}
|
||||
|
||||
if (ar->ah->state == ATH12K_HW_STATE_RESTARTING)
|
||||
return 0;
|
||||
|
||||
bands = hw->wiphy->bands;
|
||||
for (band = 0; band < NUM_NL80211_BANDS; band++) {
|
||||
|
|
@ -206,15 +265,57 @@ static void ath12k_copy_regd(struct ieee80211_regdomain *regd_orig,
|
|||
|
||||
int ath12k_regd_update(struct ath12k *ar, bool init)
|
||||
{
|
||||
u32 phy_id, freq_low = 0, freq_high = 0, supported_bands, band;
|
||||
struct ath12k_wmi_hal_reg_capabilities_ext_arg *reg_cap;
|
||||
struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
|
||||
struct ieee80211_hw *hw = ah->hw;
|
||||
struct ieee80211_regdomain *regd, *regd_copy = NULL;
|
||||
int ret, regd_len, pdev_id;
|
||||
struct ath12k_base *ab;
|
||||
int i;
|
||||
|
||||
ab = ar->ab;
|
||||
|
||||
supported_bands = ar->pdev->cap.supported_bands;
|
||||
if (supported_bands & WMI_HOST_WLAN_2GHZ_CAP) {
|
||||
band = NL80211_BAND_2GHZ;
|
||||
} else if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP && !ar->supports_6ghz) {
|
||||
band = NL80211_BAND_5GHZ;
|
||||
} else if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP && ar->supports_6ghz) {
|
||||
band = NL80211_BAND_6GHZ;
|
||||
} else {
|
||||
/* This condition is not expected.
|
||||
*/
|
||||
WARN_ON(1);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
reg_cap = &ab->hal_reg_cap[ar->pdev_idx];
|
||||
|
||||
if (ab->hw_params->single_pdev_only && !ar->supports_6ghz) {
|
||||
phy_id = ar->pdev->cap.band[band].phy_id;
|
||||
reg_cap = &ab->hal_reg_cap[phy_id];
|
||||
}
|
||||
|
||||
/* Possible that due to reg change, current limits for supported
|
||||
* frequency changed. Update that
|
||||
*/
|
||||
if (supported_bands & WMI_HOST_WLAN_2GHZ_CAP) {
|
||||
freq_low = max(reg_cap->low_2ghz_chan, ab->reg_freq_2ghz.start_freq);
|
||||
freq_high = min(reg_cap->high_2ghz_chan, ab->reg_freq_2ghz.end_freq);
|
||||
} else if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP && !ar->supports_6ghz) {
|
||||
freq_low = max(reg_cap->low_5ghz_chan, ab->reg_freq_5ghz.start_freq);
|
||||
freq_high = min(reg_cap->high_5ghz_chan, ab->reg_freq_5ghz.end_freq);
|
||||
} else if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP && ar->supports_6ghz) {
|
||||
freq_low = max(reg_cap->low_5ghz_chan, ab->reg_freq_6ghz.start_freq);
|
||||
freq_high = min(reg_cap->high_5ghz_chan, ab->reg_freq_6ghz.end_freq);
|
||||
}
|
||||
|
||||
ath12k_mac_update_freq_range(ar, freq_low, freq_high);
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_REG, "pdev %u reg updated freq limits %u->%u MHz\n",
|
||||
ar->pdev->pdev_id, freq_low, freq_high);
|
||||
|
||||
/* If one of the radios within ah has already updated the regd for
|
||||
* the wiphy, then avoid setting regd again
|
||||
*/
|
||||
|
|
@ -275,11 +376,7 @@ int ath12k_regd_update(struct ath12k *ar, bool init)
|
|||
goto err;
|
||||
}
|
||||
|
||||
rtnl_lock();
|
||||
wiphy_lock(hw->wiphy);
|
||||
ret = regulatory_set_wiphy_regd_sync(hw->wiphy, regd_copy);
|
||||
wiphy_unlock(hw->wiphy);
|
||||
rtnl_unlock();
|
||||
ret = regulatory_set_wiphy_regd(hw->wiphy, regd_copy);
|
||||
|
||||
kfree(regd_copy);
|
||||
|
||||
|
|
@ -290,15 +387,7 @@ int ath12k_regd_update(struct ath12k *ar, bool init)
|
|||
goto skip;
|
||||
|
||||
ah->regd_updated = true;
|
||||
/* Apply the new regd to all the radios, this is expected to be received only once
|
||||
* since we check for ah->regd_updated and allow here only once.
|
||||
*/
|
||||
for_each_ar(ah, ar, i) {
|
||||
ab = ar->ab;
|
||||
ret = ath12k_reg_update_chan_list(ar);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
skip:
|
||||
return 0;
|
||||
err:
|
||||
|
|
@ -611,6 +700,16 @@ ath12k_reg_update_weather_radar_band(struct ath12k_base *ab,
|
|||
*rule_idx = i;
|
||||
}
|
||||
|
||||
static void ath12k_reg_update_freq_range(struct ath12k_reg_freq *reg_freq,
|
||||
struct ath12k_reg_rule *reg_rule)
|
||||
{
|
||||
if (reg_freq->start_freq > reg_rule->start_freq)
|
||||
reg_freq->start_freq = reg_rule->start_freq;
|
||||
|
||||
if (reg_freq->end_freq < reg_rule->end_freq)
|
||||
reg_freq->end_freq = reg_rule->end_freq;
|
||||
}
|
||||
|
||||
struct ieee80211_regdomain *
|
||||
ath12k_reg_build_regd(struct ath12k_base *ab,
|
||||
struct ath12k_reg_info *reg_info, bool intersect)
|
||||
|
|
@ -654,6 +753,16 @@ ath12k_reg_build_regd(struct ath12k_base *ab,
|
|||
"\r\nCountry %s, CFG Regdomain %s FW Regdomain %d, num_reg_rules %d\n",
|
||||
alpha2, ath12k_reg_get_regdom_str(tmp_regd->dfs_region),
|
||||
reg_info->dfs_region, num_rules);
|
||||
|
||||
/* Reset start and end frequency for each band
|
||||
*/
|
||||
ab->reg_freq_5ghz.start_freq = INT_MAX;
|
||||
ab->reg_freq_5ghz.end_freq = 0;
|
||||
ab->reg_freq_2ghz.start_freq = INT_MAX;
|
||||
ab->reg_freq_2ghz.end_freq = 0;
|
||||
ab->reg_freq_6ghz.start_freq = INT_MAX;
|
||||
ab->reg_freq_6ghz.end_freq = 0;
|
||||
|
||||
/* Update reg_rules[] below. Firmware is expected to
|
||||
* send these rules in order(2G rules first and then 5G)
|
||||
*/
|
||||
|
|
@ -664,6 +773,7 @@ ath12k_reg_build_regd(struct ath12k_base *ab,
|
|||
max_bw = min_t(u16, reg_rule->max_bw,
|
||||
reg_info->max_bw_2g);
|
||||
flags = 0;
|
||||
ath12k_reg_update_freq_range(&ab->reg_freq_2ghz, reg_rule);
|
||||
} else if (reg_info->num_5g_reg_rules &&
|
||||
(j < reg_info->num_5g_reg_rules)) {
|
||||
reg_rule = reg_info->reg_rules_5g_ptr + j++;
|
||||
|
|
@ -677,6 +787,7 @@ ath12k_reg_build_regd(struct ath12k_base *ab,
|
|||
* per other BW rule flags we pass from here
|
||||
*/
|
||||
flags = NL80211_RRF_AUTO_BW;
|
||||
ath12k_reg_update_freq_range(&ab->reg_freq_5ghz, reg_rule);
|
||||
} else if (reg_info->is_ext_reg_event &&
|
||||
reg_info->num_6g_reg_rules_ap[WMI_REG_INDOOR_AP] &&
|
||||
(k < reg_info->num_6g_reg_rules_ap[WMI_REG_INDOOR_AP])) {
|
||||
|
|
@ -684,6 +795,7 @@ ath12k_reg_build_regd(struct ath12k_base *ab,
|
|||
max_bw = min_t(u16, reg_rule->max_bw,
|
||||
reg_info->max_bw_6g_ap[WMI_REG_INDOOR_AP]);
|
||||
flags = NL80211_RRF_AUTO_BW;
|
||||
ath12k_reg_update_freq_range(&ab->reg_freq_6ghz, reg_rule);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
|
@ -770,6 +882,7 @@ void ath12k_regd_update_work(struct work_struct *work)
|
|||
void ath12k_reg_init(struct ieee80211_hw *hw)
|
||||
{
|
||||
hw->wiphy->regulatory_flags = REGULATORY_WIPHY_SELF_MANAGED;
|
||||
hw->wiphy->flags |= WIPHY_FLAG_NOTIFY_REGDOM_BY_DRIVER;
|
||||
hw->wiphy->reg_notifier = ath12k_reg_notifier;
|
||||
}
|
||||
|
||||
|
|
@ -777,8 +890,12 @@ void ath12k_reg_free(struct ath12k_base *ab)
|
|||
{
|
||||
int i;
|
||||
|
||||
mutex_lock(&ab->core_lock);
|
||||
for (i = 0; i < ab->hw_params->max_radios; i++) {
|
||||
kfree(ab->default_regd[i]);
|
||||
kfree(ab->new_regd[i]);
|
||||
ab->default_regd[i] = NULL;
|
||||
ab->new_regd[i] = NULL;
|
||||
}
|
||||
mutex_unlock(&ab->core_lock);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,6 +99,6 @@ struct ieee80211_regdomain *ath12k_reg_build_regd(struct ath12k_base *ab,
|
|||
struct ath12k_reg_info *reg_info,
|
||||
bool intersect);
|
||||
int ath12k_regd_update(struct ath12k *ar, bool init);
|
||||
int ath12k_reg_update_chan_list(struct ath12k *ar);
|
||||
int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ void ath12k_tm_process_event(struct ath12k_base *ab, u32 cmd_id,
|
|||
u8 const *buf_pos;
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_TESTMODE,
|
||||
"testmode event wmi cmd_id %d ftm event msg %pK datalen %d\n",
|
||||
"testmode event wmi cmd_id %d ftm event msg %p datalen %d\n",
|
||||
cmd_id, ftm_msg, length);
|
||||
ath12k_dbg_dump(ab, ATH12K_DBG_TESTMODE, NULL, "", ftm_msg, length);
|
||||
pdev_id = DP_HW2SW_MACID(le32_to_cpu(ftm_msg->seg_hdr.pdev_id));
|
||||
|
|
@ -227,7 +227,7 @@ static int ath12k_tm_cmd_process_ftm(struct ath12k *ar, struct nlattr *tb[])
|
|||
buf_len = nla_len(tb[ATH_TM_ATTR_DATA]);
|
||||
cmd_id = WMI_PDEV_UTF_CMDID;
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_TESTMODE,
|
||||
"testmode cmd wmi cmd_id %d buf %pK buf_len %d\n",
|
||||
"testmode cmd wmi cmd_id %d buf %p buf_len %d\n",
|
||||
cmd_id, buf, buf_len);
|
||||
ath12k_dbg_dump(ar->ab, ATH12K_DBG_TESTMODE, NULL, "", buf, buf_len);
|
||||
bufpos = buf;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ struct ath12k_wmi_svc_ready_parse {
|
|||
|
||||
struct wmi_tlv_fw_stats_parse {
|
||||
const struct wmi_stats_event *ev;
|
||||
struct ath12k_fw_stats *stats;
|
||||
};
|
||||
|
||||
struct ath12k_wmi_dma_ring_caps_parse {
|
||||
|
|
@ -177,6 +178,8 @@ static const struct ath12k_wmi_tlv_policy ath12k_wmi_tlv_policies[] = {
|
|||
.min_len = sizeof(struct ath12k_wmi_p2p_noa_info) },
|
||||
[WMI_TAG_P2P_NOA_EVENT] = {
|
||||
.min_len = sizeof(struct wmi_p2p_noa_event) },
|
||||
[WMI_TAG_11D_NEW_COUNTRY_EVENT] = {
|
||||
.min_len = sizeof(struct wmi_11d_new_cc_event) },
|
||||
};
|
||||
|
||||
__le32 ath12k_wmi_tlv_hdr(u32 cmd, u32 len)
|
||||
|
|
@ -520,10 +523,10 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
|
|||
* band to band for a single radio, need to see how this should be
|
||||
* handled.
|
||||
*/
|
||||
if (le32_to_cpu(mac_caps->supported_bands) & WMI_HOST_WLAN_2G_CAP) {
|
||||
if (le32_to_cpu(mac_caps->supported_bands) & WMI_HOST_WLAN_2GHZ_CAP) {
|
||||
pdev_cap->tx_chain_mask = le32_to_cpu(mac_caps->tx_chain_mask_2g);
|
||||
pdev_cap->rx_chain_mask = le32_to_cpu(mac_caps->rx_chain_mask_2g);
|
||||
} else if (le32_to_cpu(mac_caps->supported_bands) & WMI_HOST_WLAN_5G_CAP) {
|
||||
} else if (le32_to_cpu(mac_caps->supported_bands) & WMI_HOST_WLAN_5GHZ_CAP) {
|
||||
pdev_cap->vht_cap = le32_to_cpu(mac_caps->vht_cap_info_5g);
|
||||
pdev_cap->vht_mcs = le32_to_cpu(mac_caps->vht_supp_mcs_5g);
|
||||
pdev_cap->he_mcs = le32_to_cpu(mac_caps->he_supp_mcs_5g);
|
||||
|
|
@ -546,7 +549,7 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
|
|||
pdev_cap->rx_chain_mask_shift =
|
||||
find_first_bit((unsigned long *)&pdev_cap->rx_chain_mask, 32);
|
||||
|
||||
if (le32_to_cpu(mac_caps->supported_bands) & WMI_HOST_WLAN_2G_CAP) {
|
||||
if (le32_to_cpu(mac_caps->supported_bands) & WMI_HOST_WLAN_2GHZ_CAP) {
|
||||
cap_band = &pdev_cap->band[NL80211_BAND_2GHZ];
|
||||
cap_band->phy_id = le32_to_cpu(mac_caps->phy_id);
|
||||
cap_band->max_bw_supported = le32_to_cpu(mac_caps->max_bw_supported_2g);
|
||||
|
|
@ -566,7 +569,7 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
|
|||
le32_to_cpu(mac_caps->he_ppet2g.ppet16_ppet8_ru3_ru0[i]);
|
||||
}
|
||||
|
||||
if (le32_to_cpu(mac_caps->supported_bands) & WMI_HOST_WLAN_5G_CAP) {
|
||||
if (le32_to_cpu(mac_caps->supported_bands) & WMI_HOST_WLAN_5GHZ_CAP) {
|
||||
cap_band = &pdev_cap->band[NL80211_BAND_5GHZ];
|
||||
cap_band->phy_id = le32_to_cpu(mac_caps->phy_id);
|
||||
cap_band->max_bw_supported =
|
||||
|
|
@ -1037,14 +1040,32 @@ int ath12k_wmi_vdev_down(struct ath12k *ar, u8 vdev_id)
|
|||
static void ath12k_wmi_put_wmi_channel(struct ath12k_wmi_channel_params *chan,
|
||||
struct wmi_vdev_start_req_arg *arg)
|
||||
{
|
||||
u32 center_freq1 = arg->band_center_freq1;
|
||||
|
||||
memset(chan, 0, sizeof(*chan));
|
||||
|
||||
chan->mhz = cpu_to_le32(arg->freq);
|
||||
chan->band_center_freq1 = cpu_to_le32(arg->band_center_freq1);
|
||||
if (arg->mode == MODE_11AC_VHT80_80)
|
||||
chan->band_center_freq1 = cpu_to_le32(center_freq1);
|
||||
if (arg->mode == MODE_11BE_EHT320) {
|
||||
if (arg->freq > center_freq1)
|
||||
chan->band_center_freq1 = cpu_to_le32(center_freq1 + 80);
|
||||
else
|
||||
chan->band_center_freq1 = cpu_to_le32(center_freq1 - 80);
|
||||
|
||||
chan->band_center_freq2 = cpu_to_le32(center_freq1);
|
||||
|
||||
} else if (arg->mode == MODE_11BE_EHT160) {
|
||||
if (arg->freq > center_freq1)
|
||||
chan->band_center_freq1 = cpu_to_le32(center_freq1 + 40);
|
||||
else
|
||||
chan->band_center_freq1 = cpu_to_le32(center_freq1 - 40);
|
||||
|
||||
chan->band_center_freq2 = cpu_to_le32(center_freq1);
|
||||
} else if (arg->mode == MODE_11BE_EHT80_80) {
|
||||
chan->band_center_freq2 = cpu_to_le32(arg->band_center_freq2);
|
||||
else
|
||||
} else {
|
||||
chan->band_center_freq2 = 0;
|
||||
}
|
||||
|
||||
chan->info |= le32_encode_bits(arg->mode, WMI_CHAN_INFO_MODE);
|
||||
if (arg->passive)
|
||||
|
|
@ -2351,7 +2372,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
|
|||
|
||||
for (i = 0; i < arg->peer_eht_mcs_count; i++) {
|
||||
eht_mcs = ptr;
|
||||
eht_mcs->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_HE_RATE_SET,
|
||||
eht_mcs->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_EHT_RATE_SET,
|
||||
sizeof(*eht_mcs));
|
||||
|
||||
eht_mcs->rx_mcs_set = cpu_to_le32(arg->peer_eht_rx_mcs_set[i]);
|
||||
|
|
@ -2591,7 +2612,10 @@ int ath12k_wmi_send_scan_start_cmd(struct ath12k *ar,
|
|||
cmd->scan_id = cpu_to_le32(arg->scan_id);
|
||||
cmd->scan_req_id = cpu_to_le32(arg->scan_req_id);
|
||||
cmd->vdev_id = cpu_to_le32(arg->vdev_id);
|
||||
cmd->scan_priority = cpu_to_le32(arg->scan_priority);
|
||||
if (ar->state_11d == ATH12K_11D_PREPARING)
|
||||
arg->scan_priority = WMI_SCAN_PRIORITY_MEDIUM;
|
||||
else
|
||||
arg->scan_priority = WMI_SCAN_PRIORITY_LOW;
|
||||
cmd->notify_scan_events = cpu_to_le32(arg->notify_scan_events);
|
||||
|
||||
ath12k_wmi_copy_scan_event_cntrl_flags(cmd, arg);
|
||||
|
|
@ -3313,6 +3337,110 @@ int ath12k_wmi_send_init_country_cmd(struct ath12k *ar,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_send_set_current_country_cmd(struct ath12k *ar,
|
||||
struct wmi_set_current_country_arg *arg)
|
||||
{
|
||||
struct ath12k_wmi_pdev *wmi = ar->wmi;
|
||||
struct wmi_set_current_country_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
|
||||
skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_set_current_country_cmd *)skb->data;
|
||||
cmd->tlv_header =
|
||||
ath12k_wmi_tlv_cmd_hdr(WMI_TAG_SET_CURRENT_COUNTRY_CMD,
|
||||
sizeof(*cmd));
|
||||
|
||||
cmd->pdev_id = cpu_to_le32(ar->pdev->pdev_id);
|
||||
memcpy(&cmd->new_alpha2, &arg->alpha2, sizeof(arg->alpha2));
|
||||
ret = ath12k_wmi_cmd_send(wmi, skb, WMI_SET_CURRENT_COUNTRY_CMDID);
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
|
||||
"set current country pdev id %d alpha2 %c%c\n",
|
||||
ar->pdev->pdev_id,
|
||||
arg->alpha2[0],
|
||||
arg->alpha2[1]);
|
||||
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab,
|
||||
"failed to send WMI_SET_CURRENT_COUNTRY_CMDID: %d\n", ret);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_send_11d_scan_start_cmd(struct ath12k *ar,
|
||||
struct wmi_11d_scan_start_arg *arg)
|
||||
{
|
||||
struct ath12k_wmi_pdev *wmi = ar->wmi;
|
||||
struct wmi_11d_scan_start_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
|
||||
skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_11d_scan_start_cmd *)skb->data;
|
||||
cmd->tlv_header =
|
||||
ath12k_wmi_tlv_cmd_hdr(WMI_TAG_11D_SCAN_START_CMD,
|
||||
sizeof(*cmd));
|
||||
|
||||
cmd->vdev_id = cpu_to_le32(arg->vdev_id);
|
||||
cmd->scan_period_msec = cpu_to_le32(arg->scan_period_msec);
|
||||
cmd->start_interval_msec = cpu_to_le32(arg->start_interval_msec);
|
||||
ret = ath12k_wmi_cmd_send(wmi, skb, WMI_11D_SCAN_START_CMDID);
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
|
||||
"send 11d scan start vdev id %d period %d ms internal %d ms\n",
|
||||
arg->vdev_id, arg->scan_period_msec,
|
||||
arg->start_interval_msec);
|
||||
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab,
|
||||
"failed to send WMI_11D_SCAN_START_CMDID: %d\n", ret);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_send_11d_scan_stop_cmd(struct ath12k *ar, u32 vdev_id)
|
||||
{
|
||||
struct ath12k_wmi_pdev *wmi = ar->wmi;
|
||||
struct wmi_11d_scan_stop_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
|
||||
skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_11d_scan_stop_cmd *)skb->data;
|
||||
cmd->tlv_header =
|
||||
ath12k_wmi_tlv_cmd_hdr(WMI_TAG_11D_SCAN_STOP_CMD,
|
||||
sizeof(*cmd));
|
||||
|
||||
cmd->vdev_id = cpu_to_le32(vdev_id);
|
||||
ret = ath12k_wmi_cmd_send(wmi, skb, WMI_11D_SCAN_STOP_CMDID);
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
|
||||
"send 11d scan stop vdev id %d\n",
|
||||
cmd->vdev_id);
|
||||
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab,
|
||||
"failed to send WMI_11D_SCAN_STOP_CMDID: %d\n", ret);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
ath12k_wmi_send_twt_enable_cmd(struct ath12k *ar, u32 pdev_id)
|
||||
{
|
||||
|
|
@ -3646,15 +3774,15 @@ ath12k_fill_band_to_mac_param(struct ath12k_base *soc,
|
|||
arg[i].pdev_id = pdev->pdev_id;
|
||||
|
||||
switch (pdev->cap.supported_bands) {
|
||||
case WMI_HOST_WLAN_2G_5G_CAP:
|
||||
case WMI_HOST_WLAN_2GHZ_5GHZ_CAP:
|
||||
arg[i].start_freq = hal_reg_cap->low_2ghz_chan;
|
||||
arg[i].end_freq = hal_reg_cap->high_5ghz_chan;
|
||||
break;
|
||||
case WMI_HOST_WLAN_2G_CAP:
|
||||
case WMI_HOST_WLAN_2GHZ_CAP:
|
||||
arg[i].start_freq = hal_reg_cap->low_2ghz_chan;
|
||||
arg[i].end_freq = hal_reg_cap->high_2ghz_chan;
|
||||
break;
|
||||
case WMI_HOST_WLAN_5G_CAP:
|
||||
case WMI_HOST_WLAN_5GHZ_CAP:
|
||||
arg[i].start_freq = hal_reg_cap->low_5ghz_chan;
|
||||
arg[i].end_freq = hal_reg_cap->high_5ghz_chan;
|
||||
break;
|
||||
|
|
@ -3665,7 +3793,8 @@ ath12k_fill_band_to_mac_param(struct ath12k_base *soc,
|
|||
}
|
||||
|
||||
static void
|
||||
ath12k_wmi_copy_resource_config(struct ath12k_wmi_resource_config_params *wmi_cfg,
|
||||
ath12k_wmi_copy_resource_config(struct ath12k_base *ab,
|
||||
struct ath12k_wmi_resource_config_params *wmi_cfg,
|
||||
struct ath12k_wmi_resource_config_arg *tg_cfg)
|
||||
{
|
||||
wmi_cfg->num_vdevs = cpu_to_le32(tg_cfg->num_vdevs);
|
||||
|
|
@ -3732,6 +3861,9 @@ ath12k_wmi_copy_resource_config(struct ath12k_wmi_resource_config_params *wmi_cf
|
|||
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);
|
||||
if (ab->hw_params->reoq_lut_support)
|
||||
wmi_cfg->host_service_flags |=
|
||||
cpu_to_le32(1 << WMI_RSRC_CFG_HOST_SVC_FLAG_REO_QREF_SUPPORT_BIT);
|
||||
wmi_cfg->ema_max_vap_cnt = cpu_to_le32(tg_cfg->ema_max_vap_cnt);
|
||||
wmi_cfg->ema_max_profile_period = cpu_to_le32(tg_cfg->ema_max_profile_period);
|
||||
wmi_cfg->flags2 |= cpu_to_le32(WMI_RSRC_CFG_FLAGS2_CALC_NEXT_DTIM_COUNT_SET);
|
||||
|
|
@ -3772,7 +3904,7 @@ static int ath12k_init_cmd_send(struct ath12k_wmi_pdev *wmi,
|
|||
ptr = skb->data + sizeof(*cmd);
|
||||
cfg = ptr;
|
||||
|
||||
ath12k_wmi_copy_resource_config(cfg, &arg->res_cfg);
|
||||
ath12k_wmi_copy_resource_config(ab, cfg, &arg->res_cfg);
|
||||
|
||||
cfg->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_RESOURCE_CONFIG,
|
||||
sizeof(*cfg));
|
||||
|
|
@ -4699,7 +4831,7 @@ ath12k_wmi_tlv_mac_phy_caps_ext_parse(struct ath12k_base *ab,
|
|||
bands = pdev->cap.supported_bands;
|
||||
}
|
||||
|
||||
if (bands & WMI_HOST_WLAN_2G_CAP) {
|
||||
if (bands & WMI_HOST_WLAN_2GHZ_CAP) {
|
||||
ath12k_wmi_eht_caps_parse(pdev, NL80211_BAND_2GHZ,
|
||||
caps->eht_cap_mac_info_2ghz,
|
||||
caps->eht_cap_phy_info_2ghz,
|
||||
|
|
@ -4708,7 +4840,7 @@ ath12k_wmi_tlv_mac_phy_caps_ext_parse(struct ath12k_base *ab,
|
|||
caps->eht_cap_info_internal);
|
||||
}
|
||||
|
||||
if (bands & WMI_HOST_WLAN_5G_CAP) {
|
||||
if (bands & WMI_HOST_WLAN_5GHZ_CAP) {
|
||||
ath12k_wmi_eht_caps_parse(pdev, NL80211_BAND_5GHZ,
|
||||
caps->eht_cap_mac_info_5ghz,
|
||||
caps->eht_cap_phy_info_5ghz,
|
||||
|
|
@ -4922,7 +5054,7 @@ static u8 ath12k_wmi_ignore_num_extra_rules(struct ath12k_wmi_reg_rule_ext_param
|
|||
for (count = 0; count < num_reg_rules; count++) {
|
||||
start_freq = le32_get_bits(rule[count].freq_info, REG_RULE_START_FREQ);
|
||||
|
||||
if (start_freq >= ATH12K_MIN_6G_FREQ)
|
||||
if (start_freq >= ATH12K_MIN_6GHZ_FREQ)
|
||||
num_invalid_5ghz_rules++;
|
||||
}
|
||||
|
||||
|
|
@ -4992,9 +5124,9 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
|
|||
for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++) {
|
||||
num_6g_reg_rules_ap[i] = reg_info->num_6g_reg_rules_ap[i];
|
||||
|
||||
if (num_6g_reg_rules_ap[i] > MAX_6G_REG_RULES) {
|
||||
if (num_6g_reg_rules_ap[i] > MAX_6GHZ_REG_RULES) {
|
||||
ath12k_warn(ab, "Num 6G reg rules for AP mode(%d) exceeds max limit (num_6g_reg_rules_ap: %d, max_rules: %d)\n",
|
||||
i, num_6g_reg_rules_ap[i], MAX_6G_REG_RULES);
|
||||
i, num_6g_reg_rules_ap[i], MAX_6GHZ_REG_RULES);
|
||||
kfree(tb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -5015,9 +5147,9 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
|
|||
reg_info->num_6g_reg_rules_cl[WMI_REG_VLP_AP][i];
|
||||
total_reg_rules += num_6g_reg_rules_cl[WMI_REG_VLP_AP][i];
|
||||
|
||||
if (num_6g_reg_rules_cl[WMI_REG_INDOOR_AP][i] > MAX_6G_REG_RULES ||
|
||||
num_6g_reg_rules_cl[WMI_REG_STD_POWER_AP][i] > MAX_6G_REG_RULES ||
|
||||
num_6g_reg_rules_cl[WMI_REG_VLP_AP][i] > MAX_6G_REG_RULES) {
|
||||
if (num_6g_reg_rules_cl[WMI_REG_INDOOR_AP][i] > MAX_6GHZ_REG_RULES ||
|
||||
num_6g_reg_rules_cl[WMI_REG_STD_POWER_AP][i] > MAX_6GHZ_REG_RULES ||
|
||||
num_6g_reg_rules_cl[WMI_REG_VLP_AP][i] > MAX_6GHZ_REG_RULES) {
|
||||
ath12k_warn(ab, "Num 6g client reg rules exceeds max limit, for client(type: %d)\n",
|
||||
i);
|
||||
kfree(tb);
|
||||
|
|
@ -5933,6 +6065,50 @@ static void ath12k_wmi_op_ep_tx_credits(struct ath12k_base *ab)
|
|||
wake_up(&ab->wmi_ab.tx_credits_wq);
|
||||
}
|
||||
|
||||
static int ath12k_reg_11d_new_cc_event(struct ath12k_base *ab, struct sk_buff *skb)
|
||||
{
|
||||
const struct wmi_11d_new_cc_event *ev;
|
||||
struct ath12k *ar;
|
||||
struct ath12k_pdev *pdev;
|
||||
const void **tb;
|
||||
int ret, i;
|
||||
|
||||
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 ret;
|
||||
}
|
||||
|
||||
ev = tb[WMI_TAG_11D_NEW_COUNTRY_EVENT];
|
||||
if (!ev) {
|
||||
kfree(tb);
|
||||
ath12k_warn(ab, "failed to fetch 11d new cc ev");
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
memcpy(&ab->new_alpha2, &ev->new_alpha2, REG_ALPHA2_LEN);
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_WMI, "wmi 11d new cc %c%c\n",
|
||||
ab->new_alpha2[0],
|
||||
ab->new_alpha2[1]);
|
||||
|
||||
kfree(tb);
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
pdev = &ab->pdevs[i];
|
||||
ar = pdev->ar;
|
||||
ar->state_11d = ATH12K_11D_IDLE;
|
||||
complete(&ar->completed_11d_scan);
|
||||
}
|
||||
|
||||
queue_work(ab->workqueue, &ab->update_11d_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath12k_wmi_htc_tx_complete(struct ath12k_base *ab,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
|
|
@ -6317,13 +6493,13 @@ static void ath12k_mgmt_rx_event(struct ath12k_base *ab, struct sk_buff *skb)
|
|||
if (rx_ev.status & WMI_RX_STATUS_ERR_MIC)
|
||||
status->flag |= RX_FLAG_MMIC_ERROR;
|
||||
|
||||
if (rx_ev.chan_freq >= ATH12K_MIN_6G_FREQ &&
|
||||
rx_ev.chan_freq <= ATH12K_MAX_6G_FREQ) {
|
||||
if (rx_ev.chan_freq >= ATH12K_MIN_6GHZ_FREQ &&
|
||||
rx_ev.chan_freq <= ATH12K_MAX_6GHZ_FREQ) {
|
||||
status->band = NL80211_BAND_6GHZ;
|
||||
status->freq = rx_ev.chan_freq;
|
||||
} else if (rx_ev.channel >= 1 && rx_ev.channel <= 14) {
|
||||
status->band = NL80211_BAND_2GHZ;
|
||||
} else if (rx_ev.channel >= 36 && rx_ev.channel <= ATH12K_MAX_5G_CHAN) {
|
||||
} else if (rx_ev.channel >= 36 && rx_ev.channel <= ATH12K_MAX_5GHZ_CHAN) {
|
||||
status->band = NL80211_BAND_5GHZ;
|
||||
} else {
|
||||
/* Shouldn't happen unless list of advertised channels to
|
||||
|
|
@ -7216,7 +7392,7 @@ void ath12k_wmi_fw_stats_dump(struct ath12k *ar,
|
|||
else
|
||||
buf[len] = 0;
|
||||
|
||||
ath12k_debugfs_fw_stats_reset(ar);
|
||||
ath12k_fw_stats_reset(ar);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -7335,7 +7511,7 @@ static int ath12k_wmi_tlv_fw_stats_data_parse(struct ath12k_base *ab,
|
|||
u16 len)
|
||||
{
|
||||
const struct wmi_stats_event *ev = parse->ev;
|
||||
struct ath12k_fw_stats stats = {0};
|
||||
struct ath12k_fw_stats *stats = parse->stats;
|
||||
struct ath12k *ar;
|
||||
struct ath12k_link_vif *arvif;
|
||||
struct ieee80211_sta *sta;
|
||||
|
|
@ -7344,18 +7520,18 @@ static int ath12k_wmi_tlv_fw_stats_data_parse(struct ath12k_base *ab,
|
|||
int i, ret = 0;
|
||||
const void *data = ptr;
|
||||
|
||||
INIT_LIST_HEAD(&stats.vdevs);
|
||||
INIT_LIST_HEAD(&stats.bcn);
|
||||
INIT_LIST_HEAD(&stats.pdevs);
|
||||
|
||||
if (!ev) {
|
||||
ath12k_warn(ab, "failed to fetch update stats ev");
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
if (!stats)
|
||||
return -EINVAL;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
ar = ath12k_mac_get_ar_by_pdev_id(ab, le32_to_cpu(ev->pdev_id));
|
||||
stats->pdev_id = le32_to_cpu(ev->pdev_id);
|
||||
ar = ath12k_mac_get_ar_by_pdev_id(ab, stats->pdev_id);
|
||||
if (!ar) {
|
||||
ath12k_warn(ab, "invalid pdev id %d in update stats event\n",
|
||||
le32_to_cpu(ev->pdev_id));
|
||||
|
|
@ -7398,8 +7574,8 @@ static int ath12k_wmi_tlv_fw_stats_data_parse(struct ath12k_base *ab,
|
|||
if (!dst)
|
||||
continue;
|
||||
ath12k_wmi_pull_vdev_stats(src, dst);
|
||||
stats.stats_id = WMI_REQUEST_VDEV_STAT;
|
||||
list_add_tail(&dst->list, &stats.vdevs);
|
||||
stats->stats_id = WMI_REQUEST_VDEV_STAT;
|
||||
list_add_tail(&dst->list, &stats->vdevs);
|
||||
}
|
||||
for (i = 0; i < le32_to_cpu(ev->num_bcn_stats); i++) {
|
||||
const struct ath12k_wmi_bcn_stats_params *src;
|
||||
|
|
@ -7417,8 +7593,8 @@ static int ath12k_wmi_tlv_fw_stats_data_parse(struct ath12k_base *ab,
|
|||
if (!dst)
|
||||
continue;
|
||||
ath12k_wmi_pull_bcn_stats(src, dst);
|
||||
stats.stats_id = WMI_REQUEST_BCN_STAT;
|
||||
list_add_tail(&dst->list, &stats.bcn);
|
||||
stats->stats_id = WMI_REQUEST_BCN_STAT;
|
||||
list_add_tail(&dst->list, &stats->bcn);
|
||||
}
|
||||
for (i = 0; i < le32_to_cpu(ev->num_pdev_stats); i++) {
|
||||
const struct ath12k_wmi_pdev_stats_params *src;
|
||||
|
|
@ -7430,7 +7606,7 @@ static int ath12k_wmi_tlv_fw_stats_data_parse(struct ath12k_base *ab,
|
|||
goto exit;
|
||||
}
|
||||
|
||||
stats.stats_id = WMI_REQUEST_PDEV_STAT;
|
||||
stats->stats_id = WMI_REQUEST_PDEV_STAT;
|
||||
|
||||
data += sizeof(*src);
|
||||
len -= sizeof(*src);
|
||||
|
|
@ -7442,11 +7618,9 @@ static int ath12k_wmi_tlv_fw_stats_data_parse(struct ath12k_base *ab,
|
|||
ath12k_wmi_pull_pdev_stats_base(&src->base, dst);
|
||||
ath12k_wmi_pull_pdev_stats_tx(&src->tx, dst);
|
||||
ath12k_wmi_pull_pdev_stats_rx(&src->rx, dst);
|
||||
list_add_tail(&dst->list, &stats.pdevs);
|
||||
list_add_tail(&dst->list, &stats->pdevs);
|
||||
}
|
||||
|
||||
complete(&ar->fw_stats_complete);
|
||||
ath12k_debugfs_fw_stats_process(ar, &stats);
|
||||
exit:
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
|
|
@ -7472,16 +7646,74 @@ static int ath12k_wmi_tlv_fw_stats_parse(struct ath12k_base *ab,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void ath12k_update_stats_event(struct ath12k_base *ab, struct sk_buff *skb)
|
||||
static int ath12k_wmi_pull_fw_stats(struct ath12k_base *ab, struct sk_buff *skb,
|
||||
struct ath12k_fw_stats *stats)
|
||||
{
|
||||
int ret;
|
||||
struct wmi_tlv_fw_stats_parse parse = {};
|
||||
|
||||
ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len,
|
||||
ath12k_wmi_tlv_fw_stats_parse,
|
||||
&parse);
|
||||
if (ret)
|
||||
ath12k_warn(ab, "failed to parse fw stats %d\n", ret);
|
||||
stats->stats_id = 0;
|
||||
parse.stats = stats;
|
||||
|
||||
return ath12k_wmi_tlv_iter(ab, skb->data, skb->len,
|
||||
ath12k_wmi_tlv_fw_stats_parse,
|
||||
&parse);
|
||||
}
|
||||
|
||||
static void ath12k_update_stats_event(struct ath12k_base *ab, struct sk_buff *skb)
|
||||
{
|
||||
struct ath12k_fw_stats stats = {};
|
||||
struct ath12k *ar;
|
||||
int ret;
|
||||
|
||||
INIT_LIST_HEAD(&stats.pdevs);
|
||||
INIT_LIST_HEAD(&stats.vdevs);
|
||||
INIT_LIST_HEAD(&stats.bcn);
|
||||
|
||||
ret = ath12k_wmi_pull_fw_stats(ab, skb, &stats);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to pull fw stats: %d\n", ret);
|
||||
goto free;
|
||||
}
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_WMI, "event update stats");
|
||||
|
||||
rcu_read_lock();
|
||||
ar = ath12k_mac_get_ar_by_pdev_id(ab, stats.pdev_id);
|
||||
if (!ar) {
|
||||
rcu_read_unlock();
|
||||
ath12k_warn(ab, "failed to get ar for pdev_id %d: %d\n",
|
||||
stats.pdev_id, ret);
|
||||
goto free;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
/* WMI_REQUEST_PDEV_STAT can be requested via .get_txpower mac ops or via
|
||||
* debugfs fw stats. Therefore, processing it separately.
|
||||
*/
|
||||
if (stats.stats_id == WMI_REQUEST_PDEV_STAT) {
|
||||
list_splice_tail_init(&stats.pdevs, &ar->fw_stats.pdevs);
|
||||
ar->fw_stats.fw_stats_done = true;
|
||||
goto complete;
|
||||
}
|
||||
|
||||
/* WMI_REQUEST_VDEV_STAT and WMI_REQUEST_BCN_STAT are currently requested only
|
||||
* via debugfs fw stats. Hence, processing these in debugfs context.
|
||||
*/
|
||||
ath12k_debugfs_fw_stats_process(ar, &stats);
|
||||
|
||||
complete:
|
||||
complete(&ar->fw_stats_complete);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
rcu_read_unlock();
|
||||
|
||||
/* Since the stats's pdev, vdev and beacon list are spliced and reinitialised
|
||||
* at this point, no need to free the individual list.
|
||||
*/
|
||||
return;
|
||||
|
||||
free:
|
||||
ath12k_fw_stats_free(&stats);
|
||||
}
|
||||
|
||||
/* PDEV_CTL_FAILSAFE_CHECK_EVENT is received from FW when the frequency scanned
|
||||
|
|
@ -8640,6 +8872,9 @@ static void ath12k_wmi_op_rx(struct ath12k_base *ab, struct sk_buff *skb)
|
|||
case WMI_HALPHY_STATS_CTRL_PATH_EVENTID:
|
||||
ath12k_wmi_process_tpc_stats(ab, skb);
|
||||
break;
|
||||
case WMI_11D_NEW_COUNTRY_EVENTID:
|
||||
ath12k_reg_11d_new_cc_event(ab, skb);
|
||||
break;
|
||||
/* add Unsupported events (rare) here */
|
||||
case WMI_TBTTOFFSET_EXT_UPDATE_EVENTID:
|
||||
case WMI_PEER_OPER_MODE_CHANGE_EVENTID:
|
||||
|
|
|
|||
|
|
@ -216,9 +216,9 @@ enum wmi_host_hw_mode_priority {
|
|||
};
|
||||
|
||||
enum WMI_HOST_WLAN_BAND {
|
||||
WMI_HOST_WLAN_2G_CAP = 1,
|
||||
WMI_HOST_WLAN_5G_CAP = 2,
|
||||
WMI_HOST_WLAN_2G_5G_CAP = 3,
|
||||
WMI_HOST_WLAN_2GHZ_CAP = 1,
|
||||
WMI_HOST_WLAN_5GHZ_CAP = 2,
|
||||
WMI_HOST_WLAN_2GHZ_5GHZ_CAP = 3,
|
||||
};
|
||||
|
||||
enum wmi_cmd_group {
|
||||
|
|
@ -2461,6 +2461,7 @@ struct wmi_init_cmd {
|
|||
} __packed;
|
||||
|
||||
#define WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT 4
|
||||
#define WMI_RSRC_CFG_HOST_SVC_FLAG_REO_QREF_SUPPORT_BIT 12
|
||||
#define WMI_RSRC_CFG_FLAGS2_RX_PEER_METADATA_VERSION GENMASK(5, 4)
|
||||
#define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5)
|
||||
#define WMI_RSRC_CFG_FLAGS2_CALC_NEXT_DTIM_COUNT_SET BIT(9)
|
||||
|
|
@ -2690,8 +2691,8 @@ enum wmi_channel_width {
|
|||
* 2 - index for 160 MHz, first 3 bytes valid
|
||||
* 3 - index for 320 MHz, first 3 bytes valid
|
||||
*/
|
||||
#define WMI_MAX_EHT_SUPP_MCS_2G_SIZE 2
|
||||
#define WMI_MAX_EHT_SUPP_MCS_5G_SIZE 4
|
||||
#define WMI_MAX_EHT_SUPP_MCS_2GHZ_SIZE 2
|
||||
#define WMI_MAX_EHT_SUPP_MCS_5GHZ_SIZE 4
|
||||
|
||||
#define WMI_EHTCAP_TXRX_MCS_NSS_IDX_80 0
|
||||
#define WMI_EHTCAP_TXRX_MCS_NSS_IDX_160 1
|
||||
|
|
@ -2730,8 +2731,8 @@ struct ath12k_wmi_caps_ext_params {
|
|||
struct ath12k_wmi_ppe_threshold_params eht_ppet_2ghz;
|
||||
struct ath12k_wmi_ppe_threshold_params eht_ppet_5ghz;
|
||||
__le32 eht_cap_info_internal;
|
||||
__le32 eht_supp_mcs_ext_2ghz[WMI_MAX_EHT_SUPP_MCS_2G_SIZE];
|
||||
__le32 eht_supp_mcs_ext_5ghz[WMI_MAX_EHT_SUPP_MCS_5G_SIZE];
|
||||
__le32 eht_supp_mcs_ext_2ghz[WMI_MAX_EHT_SUPP_MCS_2GHZ_SIZE];
|
||||
__le32 eht_supp_mcs_ext_5ghz[WMI_MAX_EHT_SUPP_MCS_5GHZ_SIZE];
|
||||
__le32 eml_capability;
|
||||
__le32 mld_capability;
|
||||
} __packed;
|
||||
|
|
@ -4026,6 +4027,28 @@ struct wmi_init_country_cmd {
|
|||
} cc_info;
|
||||
} __packed;
|
||||
|
||||
struct wmi_11d_scan_start_arg {
|
||||
u32 vdev_id;
|
||||
u32 scan_period_msec;
|
||||
u32 start_interval_msec;
|
||||
};
|
||||
|
||||
struct wmi_11d_scan_start_cmd {
|
||||
__le32 tlv_header;
|
||||
__le32 vdev_id;
|
||||
__le32 scan_period_msec;
|
||||
__le32 start_interval_msec;
|
||||
} __packed;
|
||||
|
||||
struct wmi_11d_scan_stop_cmd {
|
||||
__le32 tlv_header;
|
||||
__le32 vdev_id;
|
||||
} __packed;
|
||||
|
||||
struct wmi_11d_new_cc_event {
|
||||
__le32 new_alpha2;
|
||||
} __packed;
|
||||
|
||||
struct wmi_delba_send_cmd {
|
||||
__le32 tlv_header;
|
||||
__le32 vdev_id;
|
||||
|
|
@ -4108,7 +4131,17 @@ struct ath12k_wmi_eht_rate_set_params {
|
|||
|
||||
#define MAX_REG_RULES 10
|
||||
#define REG_ALPHA2_LEN 2
|
||||
#define MAX_6G_REG_RULES 5
|
||||
#define MAX_6GHZ_REG_RULES 5
|
||||
|
||||
struct wmi_set_current_country_arg {
|
||||
u8 alpha2[REG_ALPHA2_LEN];
|
||||
};
|
||||
|
||||
struct wmi_set_current_country_cmd {
|
||||
__le32 tlv_header;
|
||||
__le32 pdev_id;
|
||||
__le32 new_alpha2;
|
||||
} __packed;
|
||||
|
||||
enum wmi_start_event_param {
|
||||
WMI_VDEV_START_RESP_EVENT = 0,
|
||||
|
|
@ -5990,11 +6023,17 @@ int ath12k_wmi_send_bcn_offload_control_cmd(struct ath12k *ar,
|
|||
u32 vdev_id, u32 bcn_ctrl_op);
|
||||
int ath12k_wmi_send_init_country_cmd(struct ath12k *ar,
|
||||
struct ath12k_wmi_init_country_arg *arg);
|
||||
int
|
||||
ath12k_wmi_send_set_current_country_cmd(struct ath12k *ar,
|
||||
struct wmi_set_current_country_arg *arg);
|
||||
int ath12k_wmi_peer_rx_reorder_queue_setup(struct ath12k *ar,
|
||||
int vdev_id, const u8 *addr,
|
||||
dma_addr_t paddr, u8 tid,
|
||||
u8 ba_window_size_valid,
|
||||
u32 ba_window_size);
|
||||
int ath12k_wmi_send_11d_scan_start_cmd(struct ath12k *ar,
|
||||
struct wmi_11d_scan_start_arg *arg);
|
||||
int ath12k_wmi_send_11d_scan_stop_cmd(struct ath12k *ar, u32 vdev_id);
|
||||
int
|
||||
ath12k_wmi_rx_reord_queue_remove(struct ath12k *ar,
|
||||
struct ath12k_wmi_rx_reorder_queue_remove_arg *arg);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
#include "fwcmd.h"
|
||||
#include "version.h"
|
||||
|
||||
static const u8 otus_magic[4] = { OTUS_MAGIC };
|
||||
static const u8 otus_magic[4] __nonstring = { OTUS_MAGIC };
|
||||
|
||||
static const void *carl9170_fw_find_desc(struct ar9170 *ar, const u8 descid[4],
|
||||
const unsigned int len, const u8 compatible_revision)
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ static int wcn36xx_tm_cmd_ptt(struct wcn36xx *wcn, struct ieee80211_vif *vif,
|
|||
msg = buf;
|
||||
|
||||
wcn36xx_dbg(WCN36XX_DBG_TESTMODE,
|
||||
"testmode cmd wmi msg_id 0x%04X msg_len %d buf %pK buf_len %d\n",
|
||||
"testmode cmd wmi msg_id 0x%04X msg_len %d buf %p buf_len %d\n",
|
||||
msg->msg_id, msg->msg_body_length,
|
||||
buf, buf_len);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user