Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for v6.4. Major changes: wcn36xx * support for pronto v3 hardware ath11k * PCIe DeviceTree bindings * WCN6750: enable SAR support ath10k * convert DeviceTree bindings to YAML
This commit is contained in:
Коммит
3288ee5844
|
@ -1,215 +0,0 @@
|
|||
* Qualcomm Atheros ath10k wireless devices
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be one of the following:
|
||||
* "qcom,ath10k"
|
||||
* "qcom,ipq4019-wifi"
|
||||
* "qcom,wcn3990-wifi"
|
||||
|
||||
PCI based devices uses compatible string "qcom,ath10k" and takes calibration
|
||||
data along with board specific data via "qcom,ath10k-calibration-data".
|
||||
Rest of the properties are not applicable for PCI based devices.
|
||||
|
||||
AHB based devices (i.e. ipq4019) uses compatible string "qcom,ipq4019-wifi"
|
||||
and also uses most of the properties defined in this doc (except
|
||||
"qcom,ath10k-calibration-data"). It uses "qcom,ath10k-pre-calibration-data"
|
||||
to carry pre calibration data.
|
||||
|
||||
In general, entry "qcom,ath10k-pre-calibration-data" and
|
||||
"qcom,ath10k-calibration-data" conflict with each other and only one
|
||||
can be provided per device.
|
||||
|
||||
SNOC based devices (i.e. wcn3990) uses compatible string "qcom,wcn3990-wifi".
|
||||
|
||||
- reg: Address and length of the register set for the device.
|
||||
- reg-names: Must include the list of following reg names,
|
||||
"membase"
|
||||
- interrupts: reference to the list of 17 interrupt numbers for "qcom,ipq4019-wifi"
|
||||
compatible target.
|
||||
reference to the list of 12 interrupt numbers for "qcom,wcn3990-wifi"
|
||||
compatible target.
|
||||
Must contain interrupt-names property per entry for
|
||||
"qcom,ath10k", "qcom,ipq4019-wifi" compatible targets.
|
||||
|
||||
- interrupt-names: Must include the entries for MSI interrupt
|
||||
names ("msi0" to "msi15") and legacy interrupt
|
||||
name ("legacy") for "qcom,ath10k", "qcom,ipq4019-wifi"
|
||||
compatible targets.
|
||||
|
||||
Optional properties:
|
||||
- resets: Must contain an entry for each entry in reset-names.
|
||||
See ../reset/reseti.txt for details.
|
||||
- reset-names: Must include the list of following reset names,
|
||||
"wifi_cpu_init"
|
||||
"wifi_radio_srif"
|
||||
"wifi_radio_warm"
|
||||
"wifi_radio_cold"
|
||||
"wifi_core_warm"
|
||||
"wifi_core_cold"
|
||||
- clocks: List of clock specifiers, must contain an entry for each required
|
||||
entry in clock-names.
|
||||
- clock-names: Should contain the clock names "wifi_wcss_cmd", "wifi_wcss_ref",
|
||||
"wifi_wcss_rtc" for "qcom,ipq4019-wifi" compatible target and
|
||||
"cxo_ref_clk_pin" and optionally "qdss" for "qcom,wcn3990-wifi"
|
||||
compatible target.
|
||||
- qcom,msi_addr: MSI interrupt address.
|
||||
- qcom,msi_base: Base value to add before writing MSI data into
|
||||
MSI address register.
|
||||
- qcom,ath10k-calibration-variant: string to search for in the board-2.bin
|
||||
variant list with the same bus and device
|
||||
specific ids
|
||||
- qcom,ath10k-calibration-data : calibration data + board specific data
|
||||
as an array, the length can vary between
|
||||
hw versions.
|
||||
- qcom,ath10k-pre-calibration-data : pre calibration data as an array,
|
||||
the length can vary between hw versions.
|
||||
- <supply-name>-supply: handle to the regulator device tree node
|
||||
optional "supply-name" are "vdd-0.8-cx-mx",
|
||||
"vdd-1.8-xo", "vdd-1.3-rfa", "vdd-3.3-ch0",
|
||||
and "vdd-3.3-ch1".
|
||||
- memory-region:
|
||||
Usage: optional
|
||||
Value type: <phandle>
|
||||
Definition: reference to the reserved-memory for the msa region
|
||||
used by the wifi firmware running in Q6.
|
||||
- iommus:
|
||||
Usage: optional
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: A list of phandle and IOMMU specifier pairs.
|
||||
- ext-fem-name:
|
||||
Usage: Optional
|
||||
Value type: string
|
||||
Definition: Name of external front end module used. Some valid FEM names
|
||||
for example: "microsemi-lx5586", "sky85703-11"
|
||||
and "sky85803" etc.
|
||||
- qcom,snoc-host-cap-8bit-quirk:
|
||||
Usage: Optional
|
||||
Value type: <empty>
|
||||
Definition: Quirk specifying that the firmware expects the 8bit version
|
||||
of the host capability QMI request
|
||||
- qcom,xo-cal-data: xo cal offset to be configured in xo trim register.
|
||||
|
||||
- qcom,msa-fixed-perm: Boolean context flag to disable SCM call for statically
|
||||
mapped msa region.
|
||||
|
||||
- qcom,coexist-support : should contain eithr "0" or "1" to indicate coex
|
||||
support by the hardware.
|
||||
- qcom,coexist-gpio-pin : gpio pin number information to support coex
|
||||
which will be used by wifi firmware.
|
||||
|
||||
* Subnodes
|
||||
The ath10k wifi node can contain one optional firmware subnode.
|
||||
Firmware subnode is needed when the platform does not have TustZone.
|
||||
The firmware subnode must have:
|
||||
|
||||
- iommus:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: A list of phandle and IOMMU specifier pairs.
|
||||
|
||||
|
||||
Example (to supply PCI based wifi block details):
|
||||
|
||||
In this example, the node is defined as child node of the PCI controller.
|
||||
|
||||
pci {
|
||||
pcie@0 {
|
||||
reg = <0 0 0 0 0>;
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
device_type = "pci";
|
||||
|
||||
wifi@0,0 {
|
||||
reg = <0 0 0 0 0>;
|
||||
qcom,ath10k-calibration-data = [ 01 02 03 ... ];
|
||||
ext-fem-name = "microsemi-lx5586";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Example (to supply ipq4019 SoC wifi block details):
|
||||
|
||||
wifi0: wifi@a000000 {
|
||||
compatible = "qcom,ipq4019-wifi";
|
||||
reg = <0xa000000 0x200000>;
|
||||
resets = <&gcc WIFI0_CPU_INIT_RESET>,
|
||||
<&gcc WIFI0_RADIO_SRIF_RESET>,
|
||||
<&gcc WIFI0_RADIO_WARM_RESET>,
|
||||
<&gcc WIFI0_RADIO_COLD_RESET>,
|
||||
<&gcc WIFI0_CORE_WARM_RESET>,
|
||||
<&gcc WIFI0_CORE_COLD_RESET>;
|
||||
reset-names = "wifi_cpu_init",
|
||||
"wifi_radio_srif",
|
||||
"wifi_radio_warm",
|
||||
"wifi_radio_cold",
|
||||
"wifi_core_warm",
|
||||
"wifi_core_cold";
|
||||
clocks = <&gcc GCC_WCSS2G_CLK>,
|
||||
<&gcc GCC_WCSS2G_REF_CLK>,
|
||||
<&gcc GCC_WCSS2G_RTC_CLK>;
|
||||
clock-names = "wifi_wcss_cmd",
|
||||
"wifi_wcss_ref",
|
||||
"wifi_wcss_rtc";
|
||||
interrupts = <0 0x20 0x1>,
|
||||
<0 0x21 0x1>,
|
||||
<0 0x22 0x1>,
|
||||
<0 0x23 0x1>,
|
||||
<0 0x24 0x1>,
|
||||
<0 0x25 0x1>,
|
||||
<0 0x26 0x1>,
|
||||
<0 0x27 0x1>,
|
||||
<0 0x28 0x1>,
|
||||
<0 0x29 0x1>,
|
||||
<0 0x2a 0x1>,
|
||||
<0 0x2b 0x1>,
|
||||
<0 0x2c 0x1>,
|
||||
<0 0x2d 0x1>,
|
||||
<0 0x2e 0x1>,
|
||||
<0 0x2f 0x1>,
|
||||
<0 0xa8 0x0>;
|
||||
interrupt-names = "msi0", "msi1", "msi2", "msi3",
|
||||
"msi4", "msi5", "msi6", "msi7",
|
||||
"msi8", "msi9", "msi10", "msi11",
|
||||
"msi12", "msi13", "msi14", "msi15",
|
||||
"legacy";
|
||||
qcom,msi_addr = <0x0b006040>;
|
||||
qcom,msi_base = <0x40>;
|
||||
qcom,ath10k-pre-calibration-data = [ 01 02 03 ... ];
|
||||
qcom,coexist-support = <1>;
|
||||
qcom,coexist-gpio-pin = <0x33>;
|
||||
};
|
||||
|
||||
Example (to supply wcn3990 SoC wifi block details):
|
||||
|
||||
wifi@18000000 {
|
||||
compatible = "qcom,wcn3990-wifi";
|
||||
reg = <0x18800000 0x800000>;
|
||||
reg-names = "membase";
|
||||
clocks = <&clock_gcc clk_rf_clk2_pin>;
|
||||
clock-names = "cxo_ref_clk_pin";
|
||||
interrupts =
|
||||
<GIC_SPI 414 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 415 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 418 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 419 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 420 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH>;
|
||||
vdd-0.8-cx-mx-supply = <&pm8998_l5>;
|
||||
vdd-1.8-xo-supply = <&vreg_l7a_1p8>;
|
||||
vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;
|
||||
vdd-3.3-ch0-supply = <&vreg_l25a_3p3>;
|
||||
vdd-3.3-ch1-supply = <&vreg_l26a_3p3>;
|
||||
memory-region = <&wifi_msa_mem>;
|
||||
iommus = <&apps_smmu 0x0040 0x1>;
|
||||
qcom,msa-fixed-perm;
|
||||
wifi-firmware {
|
||||
iommus = <&apps_iommu 0xc22 0x1>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,358 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/wireless/qcom,ath10k.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Technologies ath10k wireless devices
|
||||
|
||||
maintainers:
|
||||
- Kalle Valo <kvalo@kernel.org>
|
||||
|
||||
description:
|
||||
Qualcomm Technologies, Inc. IEEE 802.11ac devices.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,ath10k # SDIO-based devices
|
||||
- qcom,ipq4019-wifi
|
||||
- qcom,wcn3990-wifi # SNoC-based devices
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: membase
|
||||
|
||||
interrupts:
|
||||
minItems: 12
|
||||
maxItems: 17
|
||||
|
||||
interrupt-names:
|
||||
minItems: 12
|
||||
maxItems: 17
|
||||
|
||||
memory-region:
|
||||
maxItems: 1
|
||||
description:
|
||||
Reference to the MSA memory region used by the Wi-Fi firmware
|
||||
running on the Q6 core.
|
||||
|
||||
iommus:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
resets:
|
||||
maxItems: 6
|
||||
|
||||
reset-names:
|
||||
items:
|
||||
- const: wifi_cpu_init
|
||||
- const: wifi_radio_srif
|
||||
- const: wifi_radio_warm
|
||||
- const: wifi_radio_cold
|
||||
- const: wifi_core_warm
|
||||
- const: wifi_core_cold
|
||||
|
||||
ext-fem-name:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description: Name of external front end module used.
|
||||
enum:
|
||||
- microsemi-lx5586
|
||||
- sky85703-11
|
||||
- sky85803
|
||||
|
||||
wifi-firmware:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description: |
|
||||
The ath10k Wi-Fi node can contain one optional firmware subnode.
|
||||
Firmware subnode is needed when the platform does not have Trustzone.
|
||||
properties:
|
||||
iommus:
|
||||
maxItems: 1
|
||||
required:
|
||||
- iommus
|
||||
|
||||
qcom,ath10k-calibration-data:
|
||||
$ref: /schemas/types.yaml#/definitions/uint8-array
|
||||
description:
|
||||
Calibration data + board-specific data as a byte array. The length
|
||||
can vary between hardware versions.
|
||||
|
||||
qcom,ath10k-calibration-variant:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description:
|
||||
Unique variant identifier of the calibration data in board-2.bin
|
||||
for designs with colliding bus and device specific ids
|
||||
|
||||
qcom,ath10k-pre-calibration-data:
|
||||
$ref: /schemas/types.yaml#/definitions/uint8-array
|
||||
description:
|
||||
Pre-calibration data as a byte array. The length can vary between
|
||||
hardware versions.
|
||||
|
||||
qcom,coexist-support:
|
||||
$ref: /schemas/types.yaml#/definitions/uint8
|
||||
enum: [0, 1]
|
||||
description:
|
||||
Indicate coex support by the hardware.
|
||||
|
||||
qcom,coexist-gpio-pin:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
COEX GPIO number provided to the Wi-Fi firmware.
|
||||
|
||||
qcom,msa-fixed-perm:
|
||||
type: boolean
|
||||
description:
|
||||
Whether to skip executing an SCM call that reassigns the memory
|
||||
region ownership.
|
||||
|
||||
qcom,smem-states:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
description: State bits used by the AP to signal the WLAN Q6.
|
||||
items:
|
||||
- description: Signal bits used to enable/disable low power mode
|
||||
on WCN in the case of WoW (Wake on Wireless).
|
||||
|
||||
qcom,smem-state-names:
|
||||
description: The names of the state bits used for SMP2P output.
|
||||
items:
|
||||
- const: wlan-smp2p-out
|
||||
|
||||
qcom,snoc-host-cap-8bit-quirk:
|
||||
type: boolean
|
||||
description:
|
||||
Quirk specifying that the firmware expects the 8bit version
|
||||
of the host capability QMI request
|
||||
|
||||
qcom,xo-cal-data:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
XO cal offset to be configured in XO trim register.
|
||||
|
||||
vdd-0.8-cx-mx-supply:
|
||||
description: Main logic power rail
|
||||
|
||||
vdd-1.8-xo-supply:
|
||||
description: Crystal oscillator supply
|
||||
|
||||
vdd-1.3-rfa-supply:
|
||||
description: RFA supply
|
||||
|
||||
vdd-3.3-ch0-supply:
|
||||
description: Primary Wi-Fi antenna supply
|
||||
|
||||
vdd-3.3-ch1-supply:
|
||||
description: Secondary Wi-Fi antenna supply
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,ipq4019-wifi
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
minItems: 17
|
||||
maxItems: 17
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: msi0
|
||||
- const: msi1
|
||||
- const: msi2
|
||||
- const: msi3
|
||||
- const: msi4
|
||||
- const: msi5
|
||||
- const: msi6
|
||||
- const: msi7
|
||||
- const: msi8
|
||||
- const: msi9
|
||||
- const: msi10
|
||||
- const: msi11
|
||||
- const: msi12
|
||||
- const: msi13
|
||||
- const: msi14
|
||||
- const: msi15
|
||||
- const: legacy
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Wi-Fi command clock
|
||||
- description: Wi-Fi reference clock
|
||||
- description: Wi-Fi RTC clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: wifi_wcss_cmd
|
||||
- const: wifi_wcss_ref
|
||||
- const: wifi_wcss_rtc
|
||||
|
||||
required:
|
||||
- clocks
|
||||
- clock-names
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
- resets
|
||||
- reset-names
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,wcn3990-wifi
|
||||
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 1
|
||||
items:
|
||||
- description: XO reference clock
|
||||
- description: Qualcomm Debug Subsystem clock
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- const: cxo_ref_clk_pin
|
||||
- const: qdss
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: CE0
|
||||
- description: CE1
|
||||
- description: CE2
|
||||
- description: CE3
|
||||
- description: CE4
|
||||
- description: CE5
|
||||
- description: CE6
|
||||
- description: CE7
|
||||
- description: CE8
|
||||
- description: CE9
|
||||
- description: CE10
|
||||
- description: CE11
|
||||
|
||||
interrupt-names: false
|
||||
|
||||
required:
|
||||
- interrupts
|
||||
|
||||
examples:
|
||||
# SNoC
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,rpmcc.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
wifi@18800000 {
|
||||
compatible = "qcom,wcn3990-wifi";
|
||||
reg = <0x18800000 0x800000>;
|
||||
reg-names = "membase";
|
||||
memory-region = <&wlan_msa_mem>;
|
||||
clocks = <&rpmcc RPM_SMD_RF_CLK2_PIN>;
|
||||
clock-names = "cxo_ref_clk_pin";
|
||||
interrupts = <GIC_SPI 413 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 414 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 415 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 418 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 420 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH>;
|
||||
iommus = <&anoc2_smmu 0x1900>,
|
||||
<&anoc2_smmu 0x1901>;
|
||||
qcom,snoc-host-cap-8bit-quirk;
|
||||
vdd-0.8-cx-mx-supply = <&vreg_l5a_0p8>;
|
||||
vdd-1.8-xo-supply = <&vreg_l7a_1p8>;
|
||||
vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;
|
||||
vdd-3.3-ch0-supply = <&vreg_l25a_3p3>;
|
||||
vdd-3.3-ch1-supply = <&vreg_l23a_3p3>;
|
||||
|
||||
wifi-firmware {
|
||||
iommus = <&apps_smmu 0x1c02 0x1>;
|
||||
};
|
||||
};
|
||||
|
||||
# AHB
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,gcc-ipq4019.h>
|
||||
|
||||
wifi@a000000 {
|
||||
compatible = "qcom,ipq4019-wifi";
|
||||
reg = <0xa000000 0x200000>;
|
||||
resets = <&gcc WIFI0_CPU_INIT_RESET>,
|
||||
<&gcc WIFI0_RADIO_SRIF_RESET>,
|
||||
<&gcc WIFI0_RADIO_WARM_RESET>,
|
||||
<&gcc WIFI0_RADIO_COLD_RESET>,
|
||||
<&gcc WIFI0_CORE_WARM_RESET>,
|
||||
<&gcc WIFI0_CORE_COLD_RESET>;
|
||||
reset-names = "wifi_cpu_init",
|
||||
"wifi_radio_srif",
|
||||
"wifi_radio_warm",
|
||||
"wifi_radio_cold",
|
||||
"wifi_core_warm",
|
||||
"wifi_core_cold";
|
||||
clocks = <&gcc GCC_WCSS2G_CLK>,
|
||||
<&gcc GCC_WCSS2G_REF_CLK>,
|
||||
<&gcc GCC_WCSS2G_RTC_CLK>;
|
||||
clock-names = "wifi_wcss_cmd",
|
||||
"wifi_wcss_ref",
|
||||
"wifi_wcss_rtc";
|
||||
interrupts = <GIC_SPI 32 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 33 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 34 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 35 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 36 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 37 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 38 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 39 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 40 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 41 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 42 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 43 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 44 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 45 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 46 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 47 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "msi0",
|
||||
"msi1",
|
||||
"msi2",
|
||||
"msi3",
|
||||
"msi4",
|
||||
"msi5",
|
||||
"msi6",
|
||||
"msi7",
|
||||
"msi8",
|
||||
"msi9",
|
||||
"msi10",
|
||||
"msi11",
|
||||
"msi12",
|
||||
"msi13",
|
||||
"msi14",
|
||||
"msi15",
|
||||
"legacy";
|
||||
};
|
|
@ -0,0 +1,58 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright (c) 2023 Linaro Limited
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/wireless/qcom,ath11k-pci.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Technologies ath11k wireless devices (PCIe)
|
||||
|
||||
maintainers:
|
||||
- Kalle Valo <kvalo@kernel.org>
|
||||
|
||||
description: |
|
||||
Qualcomm Technologies IEEE 802.11ax PCIe devices
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- pci17cb,1103 # WCN6855
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
qcom,ath11k-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
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
pcie {
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
|
||||
pcie@0 {
|
||||
device_type = "pci";
|
||||
reg = <0x0 0x0 0x0 0x0 0x0>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
bus-range = <0x01 0xff>;
|
||||
|
||||
wifi@0 {
|
||||
compatible = "pci17cb,1103";
|
||||
reg = <0x10000 0x0 0x0 0x0 0x0>;
|
||||
|
||||
qcom,ath11k-calibration-variant = "LE_X13S";
|
||||
};
|
||||
};
|
||||
};
|
|
@ -17218,7 +17218,7 @@ S: Supported
|
|||
W: https://wireless.wiki.kernel.org/en/users/Drivers/ath10k
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
|
||||
F: drivers/net/wireless/ath/ath10k/
|
||||
F: Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
|
||||
F: Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
|
||||
|
||||
QUALCOMM ATHEROS ATH11K WIRELESS DRIVER
|
||||
M: Kalle Valo <kvalo@kernel.org>
|
||||
|
|
|
@ -84,13 +84,6 @@ ath10k_set_ring_byte(unsigned int offset,
|
|||
return ((offset << addr_map->lsb) & addr_map->mask);
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
ath10k_get_ring_byte(unsigned int offset,
|
||||
struct ath10k_hw_ce_regs_addr_map *addr_map)
|
||||
{
|
||||
return ((offset & addr_map->mask) >> (addr_map->lsb));
|
||||
}
|
||||
|
||||
static inline u32 ath10k_ce_read32(struct ath10k *ar, u32 offset)
|
||||
{
|
||||
struct ath10k_ce *ce = ath10k_ce_priv(ar);
|
||||
|
|
|
@ -3406,15 +3406,12 @@ static int ath10k_pci_claim(struct ath10k *ar)
|
|||
if (!ar_pci->mem) {
|
||||
ath10k_err(ar, "failed to iomap BAR%d\n", BAR_NUM);
|
||||
ret = -EIO;
|
||||
goto err_master;
|
||||
goto err_region;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot pci_mem 0x%pK\n", ar_pci->mem);
|
||||
return 0;
|
||||
|
||||
err_master:
|
||||
pci_clear_master(pdev);
|
||||
|
||||
err_region:
|
||||
pci_release_region(pdev, BAR_NUM);
|
||||
|
||||
|
@ -3431,7 +3428,6 @@ static void ath10k_pci_release(struct ath10k *ar)
|
|||
|
||||
pci_iounmap(pdev, ar_pci->mem);
|
||||
pci_release_region(pdev, BAR_NUM);
|
||||
pci_clear_master(pdev);
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
|
||||
|
|
|
@ -1078,6 +1078,12 @@ static int ath11k_ahb_fw_resource_deinit(struct ath11k_base *ab)
|
|||
struct iommu_domain *iommu;
|
||||
size_t unmapped_size;
|
||||
|
||||
/* Chipsets not requiring MSA would have not initialized
|
||||
* MSA resources, return success in such cases.
|
||||
*/
|
||||
if (!ab->hw_params.fixed_fw_mem)
|
||||
return 0;
|
||||
|
||||
if (ab_ahb->fw.use_tz)
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -116,7 +116,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.tcl_ring_retry = true,
|
||||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
.ftm_responder = true,
|
||||
},
|
||||
{
|
||||
.hw_rev = ATH11K_HW_IPQ6018_HW10,
|
||||
|
@ -199,7 +198,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
.support_fw_mac_sequence = false,
|
||||
.ftm_responder = true,
|
||||
},
|
||||
{
|
||||
.name = "qca6390 hw2.0",
|
||||
|
@ -284,7 +282,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
.support_fw_mac_sequence = true,
|
||||
.ftm_responder = false,
|
||||
},
|
||||
{
|
||||
.name = "qcn9074 hw1.0",
|
||||
|
@ -366,7 +363,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
.support_fw_mac_sequence = false,
|
||||
.ftm_responder = true,
|
||||
},
|
||||
{
|
||||
.name = "wcn6855 hw2.0",
|
||||
|
@ -451,7 +447,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
.support_fw_mac_sequence = true,
|
||||
.ftm_responder = false,
|
||||
},
|
||||
{
|
||||
.name = "wcn6855 hw2.1",
|
||||
|
@ -534,7 +529,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
.support_fw_mac_sequence = true,
|
||||
.ftm_responder = false,
|
||||
},
|
||||
{
|
||||
.name = "wcn6750 hw1.0",
|
||||
|
@ -599,7 +593,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.current_cc_support = true,
|
||||
.dbr_debug_support = false,
|
||||
.global_reset = false,
|
||||
.bios_sar_capa = NULL,
|
||||
.bios_sar_capa = &ath11k_hw_sar_capa_wcn6855,
|
||||
.m3_fw_support = false,
|
||||
.fixed_bdf_addr = false,
|
||||
.fixed_mem_region = false,
|
||||
|
@ -615,7 +609,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.tx_ring_size = DP_TCL_DATA_RING_SIZE_WCN6750,
|
||||
.smp2p_wow_exit = true,
|
||||
.support_fw_mac_sequence = true,
|
||||
.ftm_responder = false,
|
||||
},
|
||||
{
|
||||
.hw_rev = ATH11K_HW_IPQ5018_HW10,
|
||||
|
@ -695,7 +688,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
.support_fw_mac_sequence = false,
|
||||
.ftm_responder = true,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -26,13 +26,13 @@ int ath11k_dbring_validate_buffer(struct ath11k *ar, void *buffer, u32 size)
|
|||
static void ath11k_dbring_fill_magic_value(struct ath11k *ar,
|
||||
void *buffer, u32 size)
|
||||
{
|
||||
u32 *temp;
|
||||
int idx;
|
||||
/* memset32 function fills buffer payload with the ATH11K_DB_MAGIC_VALUE
|
||||
* and the variable size is expected to be the number of u32 values
|
||||
* to be stored, not the number of bytes.
|
||||
*/
|
||||
size = size / sizeof(u32);
|
||||
|
||||
size = size >> 2;
|
||||
|
||||
for (idx = 0, temp = buffer; idx < size; idx++, temp++)
|
||||
*temp++ = ATH11K_DB_MAGIC_VALUE;
|
||||
memset32(buffer, ATH11K_DB_MAGIC_VALUE, size);
|
||||
}
|
||||
|
||||
static int ath11k_dbring_bufs_replenish(struct ath11k *ar,
|
||||
|
|
|
@ -143,7 +143,8 @@ enum htt_tx_pdev_underrun_enum {
|
|||
/* Bytes stored in little endian order */
|
||||
/* Length should be multiple of DWORD */
|
||||
struct htt_stats_string_tlv {
|
||||
u32 data[0]; /* Can be variable length */
|
||||
/* Can be variable length */
|
||||
DECLARE_FLEX_ARRAY(u32, data);
|
||||
} __packed;
|
||||
|
||||
#define HTT_STATS_MAC_ID GENMASK(7, 0)
|
||||
|
@ -205,27 +206,32 @@ struct htt_tx_pdev_stats_cmn_tlv {
|
|||
|
||||
/* NOTE: Variable length TLV, use length spec to infer array size */
|
||||
struct htt_tx_pdev_stats_urrn_tlv_v {
|
||||
u32 urrn_stats[0]; /* HTT_TX_PDEV_MAX_URRN_STATS */
|
||||
/* HTT_TX_PDEV_MAX_URRN_STATS */
|
||||
DECLARE_FLEX_ARRAY(u32, urrn_stats);
|
||||
};
|
||||
|
||||
/* NOTE: Variable length TLV, use length spec to infer array size */
|
||||
struct htt_tx_pdev_stats_flush_tlv_v {
|
||||
u32 flush_errs[0]; /* HTT_TX_PDEV_MAX_FLUSH_REASON_STATS */
|
||||
/* HTT_TX_PDEV_MAX_FLUSH_REASON_STATS */
|
||||
DECLARE_FLEX_ARRAY(u32, flush_errs);
|
||||
};
|
||||
|
||||
/* NOTE: Variable length TLV, use length spec to infer array size */
|
||||
struct htt_tx_pdev_stats_sifs_tlv_v {
|
||||
u32 sifs_status[0]; /* HTT_TX_PDEV_MAX_SIFS_BURST_STATS */
|
||||
/* HTT_TX_PDEV_MAX_SIFS_BURST_STATS */
|
||||
DECLARE_FLEX_ARRAY(u32, sifs_status);
|
||||
};
|
||||
|
||||
/* NOTE: Variable length TLV, use length spec to infer array size */
|
||||
struct htt_tx_pdev_stats_phy_err_tlv_v {
|
||||
u32 phy_errs[0]; /* HTT_TX_PDEV_MAX_PHY_ERR_STATS */
|
||||
/* HTT_TX_PDEV_MAX_PHY_ERR_STATS */
|
||||
DECLARE_FLEX_ARRAY(u32, phy_errs);
|
||||
};
|
||||
|
||||
/* NOTE: Variable length TLV, use length spec to infer array size */
|
||||
struct htt_tx_pdev_stats_sifs_hist_tlv_v {
|
||||
u32 sifs_hist_status[0]; /* HTT_TX_PDEV_SIFS_BURST_HIST_STATS */
|
||||
/* HTT_TX_PDEV_SIFS_BURST_HIST_STATS */
|
||||
DECLARE_FLEX_ARRAY(u32, sifs_hist_status);
|
||||
};
|
||||
|
||||
struct htt_tx_pdev_stats_tx_ppdu_stats_tlv_v {
|
||||
|
@ -590,20 +596,20 @@ struct htt_tx_hwq_difs_latency_stats_tlv_v {
|
|||
|
||||
/* NOTE: Variable length TLV, use length spec to infer array size */
|
||||
struct htt_tx_hwq_cmd_result_stats_tlv_v {
|
||||
/* Histogram of sched cmd result */
|
||||
u32 cmd_result[0]; /* HTT_TX_HWQ_MAX_CMD_RESULT_STATS */
|
||||
/* Histogram of sched cmd result, HTT_TX_HWQ_MAX_CMD_RESULT_STATS */
|
||||
DECLARE_FLEX_ARRAY(u32, cmd_result);
|
||||
};
|
||||
|
||||
/* NOTE: Variable length TLV, use length spec to infer array size */
|
||||
struct htt_tx_hwq_cmd_stall_stats_tlv_v {
|
||||
/* Histogram of various pause conitions */
|
||||
u32 cmd_stall_status[0]; /* HTT_TX_HWQ_MAX_CMD_STALL_STATS */
|
||||
/* Histogram of various pause conitions, HTT_TX_HWQ_MAX_CMD_STALL_STATS */
|
||||
DECLARE_FLEX_ARRAY(u32, cmd_stall_status);
|
||||
};
|
||||
|
||||
/* NOTE: Variable length TLV, use length spec to infer array size */
|
||||
struct htt_tx_hwq_fes_result_stats_tlv_v {
|
||||
/* Histogram of number of user fes result */
|
||||
u32 fes_result[0]; /* HTT_TX_HWQ_MAX_FES_RESULT_STATS */
|
||||
/* Histogram of number of user fes result, HTT_TX_HWQ_MAX_FES_RESULT_STATS */
|
||||
DECLARE_FLEX_ARRAY(u32, fes_result);
|
||||
};
|
||||
|
||||
/* NOTE: Variable length TLV, use length spec to infer array size
|
||||
|
@ -635,8 +641,8 @@ struct htt_tx_hwq_tried_mpdu_cnt_hist_tlv_v {
|
|||
* #define WAL_TXOP_USED_HISTOGRAM_INTERVAL 1000 ( 1 ms )
|
||||
*/
|
||||
struct htt_tx_hwq_txop_used_cnt_hist_tlv_v {
|
||||
/* Histogram of txop used cnt */
|
||||
u32 txop_used_cnt_hist[0]; /* HTT_TX_HWQ_TXOP_USED_CNT_HIST */
|
||||
/* Histogram of txop used cnt, HTT_TX_HWQ_TXOP_USED_CNT_HIST */
|
||||
DECLARE_FLEX_ARRAY(u32, txop_used_cnt_hist);
|
||||
};
|
||||
|
||||
/* == TX SELFGEN STATS == */
|
||||
|
@ -804,17 +810,20 @@ struct htt_tx_pdev_mpdu_stats_tlv {
|
|||
/* == TX SCHED STATS == */
|
||||
/* NOTE: Variable length TLV, use length spec to infer array size */
|
||||
struct htt_sched_txq_cmd_posted_tlv_v {
|
||||
u32 sched_cmd_posted[0]; /* HTT_TX_PDEV_SCHED_TX_MODE_MAX */
|
||||
/* HTT_TX_PDEV_SCHED_TX_MODE_MAX */
|
||||
DECLARE_FLEX_ARRAY(u32, sched_cmd_posted);
|
||||
};
|
||||
|
||||
/* NOTE: Variable length TLV, use length spec to infer array size */
|
||||
struct htt_sched_txq_cmd_reaped_tlv_v {
|
||||
u32 sched_cmd_reaped[0]; /* HTT_TX_PDEV_SCHED_TX_MODE_MAX */
|
||||
/* HTT_TX_PDEV_SCHED_TX_MODE_MAX */
|
||||
DECLARE_FLEX_ARRAY(u32, sched_cmd_reaped);
|
||||
};
|
||||
|
||||
/* NOTE: Variable length TLV, use length spec to infer array size */
|
||||
struct htt_sched_txq_sched_order_su_tlv_v {
|
||||
u32 sched_order_su[0]; /* HTT_TX_PDEV_NUM_SCHED_ORDER_LOG */
|
||||
/* HTT_TX_PDEV_NUM_SCHED_ORDER_LOG */
|
||||
DECLARE_FLEX_ARRAY(u32, sched_order_su);
|
||||
};
|
||||
|
||||
enum htt_sched_txq_sched_ineligibility_tlv_enum {
|
||||
|
@ -842,7 +851,7 @@ enum htt_sched_txq_sched_ineligibility_tlv_enum {
|
|||
/* NOTE: Variable length TLV, use length spec to infer array size */
|
||||
struct htt_sched_txq_sched_ineligibility_tlv_v {
|
||||
/* indexed by htt_sched_txq_sched_ineligibility_tlv_enum */
|
||||
u32 sched_ineligibility[0];
|
||||
DECLARE_FLEX_ARRAY(u32, sched_ineligibility);
|
||||
};
|
||||
|
||||
#define HTT_TX_PDEV_STATS_SCHED_PER_TXQ_MAC_ID GENMASK(7, 0)
|
||||
|
@ -888,18 +897,20 @@ struct htt_stats_tx_sched_cmn_tlv {
|
|||
|
||||
/* NOTE: Variable length TLV, use length spec to infer array size */
|
||||
struct htt_tx_tqm_gen_mpdu_stats_tlv_v {
|
||||
u32 gen_mpdu_end_reason[0]; /* HTT_TX_TQM_MAX_GEN_MPDU_END_REASON */
|
||||
/* HTT_TX_TQM_MAX_GEN_MPDU_END_REASON */
|
||||
DECLARE_FLEX_ARRAY(u32, gen_mpdu_end_reason);
|
||||
};
|
||||
|
||||
/* NOTE: Variable length TLV, use length spec to infer array size */
|
||||
struct htt_tx_tqm_list_mpdu_stats_tlv_v {
|
||||
u32 list_mpdu_end_reason[0]; /* HTT_TX_TQM_MAX_LIST_MPDU_END_REASON */
|
||||
/* HTT_TX_TQM_MAX_LIST_MPDU_END_REASON */
|
||||
DECLARE_FLEX_ARRAY(u32, list_mpdu_end_reason);
|
||||
};
|
||||
|
||||
/* NOTE: Variable length TLV, use length spec to infer array size */
|
||||
struct htt_tx_tqm_list_mpdu_cnt_tlv_v {
|
||||
u32 list_mpdu_cnt_hist[0];
|
||||
/* HTT_TX_TQM_MAX_LIST_MPDU_CNT_HISTOGRAM_BINS */
|
||||
DECLARE_FLEX_ARRAY(u32, list_mpdu_cnt_hist);
|
||||
};
|
||||
|
||||
struct htt_tx_tqm_pdev_stats_tlv_v {
|
||||
|
@ -1098,7 +1109,7 @@ struct htt_tx_de_compl_stats_tlv {
|
|||
* ENTRIES_PER_BIN_COUNT)
|
||||
*/
|
||||
struct htt_tx_de_fw2wbm_ring_full_hist_tlv {
|
||||
u32 fw2wbm_ring_full_hist[0];
|
||||
DECLARE_FLEX_ARRAY(u32, fw2wbm_ring_full_hist);
|
||||
};
|
||||
|
||||
struct htt_tx_de_cmn_stats_tlv {
|
||||
|
@ -1151,7 +1162,7 @@ struct htt_ring_if_cmn_tlv {
|
|||
/* NOTE: Variable length TLV, use length spec to infer array size */
|
||||
struct htt_sfm_client_user_tlv_v {
|
||||
/* Number of DWORDS used per user and per client */
|
||||
u32 dwords_used_by_user_n[0];
|
||||
DECLARE_FLEX_ARRAY(u32, dwords_used_by_user_n);
|
||||
};
|
||||
|
||||
struct htt_sfm_client_tlv {
|
||||
|
@ -1436,12 +1447,14 @@ struct htt_rx_soc_fw_stats_tlv {
|
|||
|
||||
/* NOTE: Variable length TLV, use length spec to infer array size */
|
||||
struct htt_rx_soc_fw_refill_ring_empty_tlv_v {
|
||||
u32 refill_ring_empty_cnt[0]; /* HTT_RX_STATS_REFILL_MAX_RING */
|
||||
/* HTT_RX_STATS_REFILL_MAX_RING */
|
||||
DECLARE_FLEX_ARRAY(u32, refill_ring_empty_cnt);
|
||||
};
|
||||
|
||||
/* NOTE: Variable length TLV, use length spec to infer array size */
|
||||
struct htt_rx_soc_fw_refill_ring_num_refill_tlv_v {
|
||||
u32 refill_ring_num_refill[0]; /* HTT_RX_STATS_REFILL_MAX_RING */
|
||||
/* HTT_RX_STATS_REFILL_MAX_RING */
|
||||
DECLARE_FLEX_ARRAY(u32, refill_ring_num_refill);
|
||||
};
|
||||
|
||||
/* RXDMA error code from WBM released packets */
|
||||
|
@ -1473,7 +1486,7 @@ enum htt_rx_rxdma_error_code_enum {
|
|||
|
||||
/* NOTE: Variable length TLV, use length spec to infer array size */
|
||||
struct htt_rx_soc_fw_refill_ring_num_rxdma_err_tlv_v {
|
||||
u32 rxdma_err[0]; /* HTT_RX_RXDMA_MAX_ERR_CODE */
|
||||
DECLARE_FLEX_ARRAY(u32, rxdma_err); /* HTT_RX_RXDMA_MAX_ERR_CODE */
|
||||
};
|
||||
|
||||
/* REO error code from WBM released packets */
|
||||
|
@ -1505,7 +1518,7 @@ enum htt_rx_reo_error_code_enum {
|
|||
|
||||
/* NOTE: Variable length TLV, use length spec to infer array size */
|
||||
struct htt_rx_soc_fw_refill_ring_num_reo_err_tlv_v {
|
||||
u32 reo_err[0]; /* HTT_RX_REO_MAX_ERR_CODE */
|
||||
DECLARE_FLEX_ARRAY(u32, reo_err); /* HTT_RX_REO_MAX_ERR_CODE */
|
||||
};
|
||||
|
||||
/* == RX PDEV STATS == */
|
||||
|
@ -1622,13 +1635,13 @@ struct htt_rx_pdev_fw_stats_phy_err_tlv {
|
|||
/* NOTE: Variable length TLV, use length spec to infer array size */
|
||||
struct htt_rx_pdev_fw_ring_mpdu_err_tlv_v {
|
||||
/* Num error MPDU for each RxDMA error type */
|
||||
u32 fw_ring_mpdu_err[0]; /* HTT_RX_STATS_RXDMA_MAX_ERR */
|
||||
DECLARE_FLEX_ARRAY(u32, fw_ring_mpdu_err); /* HTT_RX_STATS_RXDMA_MAX_ERR */
|
||||
};
|
||||
|
||||
/* NOTE: Variable length TLV, use length spec to infer array size */
|
||||
struct htt_rx_pdev_fw_mpdu_drop_tlv_v {
|
||||
/* Num MPDU dropped */
|
||||
u32 fw_mpdu_drop[0]; /* HTT_RX_STATS_FW_DROP_REASON_MAX */
|
||||
DECLARE_FLEX_ARRAY(u32, fw_mpdu_drop); /* HTT_RX_STATS_FW_DROP_REASON_MAX */
|
||||
};
|
||||
|
||||
#define HTT_PDEV_CCA_STATS_TX_FRAME_INFO_PRESENT (0x1)
|
||||
|
|
|
@ -36,6 +36,7 @@ void ath11k_dp_peer_cleanup(struct ath11k *ar, int vdev_id, const u8 *addr)
|
|||
}
|
||||
|
||||
ath11k_peer_rx_tid_cleanup(ar, peer);
|
||||
peer->dp_setup_done = false;
|
||||
crypto_free_shash(peer->tfm_mmic);
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
}
|
||||
|
@ -72,7 +73,8 @@ int ath11k_dp_peer_setup(struct ath11k *ar, int vdev_id, const u8 *addr)
|
|||
ret = ath11k_peer_rx_frag_setup(ar, addr, vdev_id);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to setup rx defrag context\n");
|
||||
return ret;
|
||||
tid--;
|
||||
goto peer_clean;
|
||||
}
|
||||
|
||||
/* TODO: Setup other peer specific resource used in data path */
|
||||
|
|
|
@ -214,7 +214,7 @@ struct ath11k_pdev_dp {
|
|||
#define DP_REO_REINJECT_RING_SIZE 32
|
||||
#define DP_RX_RELEASE_RING_SIZE 1024
|
||||
#define DP_REO_EXCEPTION_RING_SIZE 128
|
||||
#define DP_REO_CMD_RING_SIZE 128
|
||||
#define DP_REO_CMD_RING_SIZE 256
|
||||
#define DP_REO_STATUS_RING_SIZE 2048
|
||||
#define DP_RXDMA_BUF_RING_SIZE 4096
|
||||
#define DP_RXDMA_REFILL_RING_SIZE 2048
|
||||
|
@ -303,12 +303,16 @@ struct ath11k_dp {
|
|||
|
||||
#define HTT_TX_WBM_COMP_STATUS_OFFSET 8
|
||||
|
||||
#define HTT_INVALID_PEER_ID 0xffff
|
||||
|
||||
/* HTT tx completion is overlaid in wbm_release_ring */
|
||||
#define HTT_TX_WBM_COMP_INFO0_STATUS GENMASK(12, 9)
|
||||
#define HTT_TX_WBM_COMP_INFO0_REINJECT_REASON GENMASK(16, 13)
|
||||
#define HTT_TX_WBM_COMP_INFO0_REINJECT_REASON GENMASK(16, 13)
|
||||
|
||||
#define HTT_TX_WBM_COMP_INFO1_ACK_RSSI GENMASK(31, 24)
|
||||
#define HTT_TX_WBM_COMP_INFO2_SW_PEER_ID GENMASK(15, 0)
|
||||
#define HTT_TX_WBM_COMP_INFO2_VALID BIT(21)
|
||||
|
||||
struct htt_tx_wbm_completion {
|
||||
u32 info0;
|
||||
|
|
|
@ -389,10 +389,10 @@ int ath11k_dp_rxbufs_replenish(struct ath11k_base *ab, int mac_id,
|
|||
goto fail_free_skb;
|
||||
|
||||
spin_lock_bh(&rx_ring->idr_lock);
|
||||
buf_id = idr_alloc(&rx_ring->bufs_idr, skb, 0,
|
||||
rx_ring->bufs_max * 3, GFP_ATOMIC);
|
||||
buf_id = idr_alloc(&rx_ring->bufs_idr, skb, 1,
|
||||
(rx_ring->bufs_max * 3) + 1, GFP_ATOMIC);
|
||||
spin_unlock_bh(&rx_ring->idr_lock);
|
||||
if (buf_id < 0)
|
||||
if (buf_id <= 0)
|
||||
goto fail_dma_unmap;
|
||||
|
||||
desc = ath11k_hal_srng_src_get_next_entry(ab, srng);
|
||||
|
@ -435,7 +435,6 @@ fail_free_skb:
|
|||
static int ath11k_dp_rxdma_buf_ring_free(struct ath11k *ar,
|
||||
struct dp_rxdma_ring *rx_ring)
|
||||
{
|
||||
struct ath11k_pdev_dp *dp = &ar->dp;
|
||||
struct sk_buff *skb;
|
||||
int buf_id;
|
||||
|
||||
|
@ -453,28 +452,6 @@ static int ath11k_dp_rxdma_buf_ring_free(struct ath11k *ar,
|
|||
idr_destroy(&rx_ring->bufs_idr);
|
||||
spin_unlock_bh(&rx_ring->idr_lock);
|
||||
|
||||
/* if rxdma1_enable is false, mon_status_refill_ring
|
||||
* isn't setup, so don't clean.
|
||||
*/
|
||||
if (!ar->ab->hw_params.rxdma1_enable)
|
||||
return 0;
|
||||
|
||||
rx_ring = &dp->rx_mon_status_refill_ring[0];
|
||||
|
||||
spin_lock_bh(&rx_ring->idr_lock);
|
||||
idr_for_each_entry(&rx_ring->bufs_idr, skb, buf_id) {
|
||||
idr_remove(&rx_ring->bufs_idr, buf_id);
|
||||
/* XXX: Understand where internal driver does this dma_unmap
|
||||
* of rxdma_buffer.
|
||||
*/
|
||||
dma_unmap_single(ar->ab->dev, ATH11K_SKB_RXCB(skb)->paddr,
|
||||
skb->len + skb_tailroom(skb), DMA_BIDIRECTIONAL);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
idr_destroy(&rx_ring->bufs_idr);
|
||||
spin_unlock_bh(&rx_ring->idr_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -691,13 +668,18 @@ void ath11k_dp_reo_cmd_list_cleanup(struct ath11k_base *ab)
|
|||
struct ath11k_dp *dp = &ab->dp;
|
||||
struct dp_reo_cmd *cmd, *tmp;
|
||||
struct dp_reo_cache_flush_elem *cmd_cache, *tmp_cache;
|
||||
struct dp_rx_tid *rx_tid;
|
||||
|
||||
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);
|
||||
rx_tid = &cmd->data;
|
||||
if (rx_tid->vaddr) {
|
||||
dma_unmap_single(ab->dev, rx_tid->paddr,
|
||||
rx_tid->size, DMA_BIDIRECTIONAL);
|
||||
kfree(rx_tid->vaddr);
|
||||
rx_tid->vaddr = NULL;
|
||||
}
|
||||
kfree(cmd);
|
||||
}
|
||||
|
||||
|
@ -705,9 +687,13 @@ void ath11k_dp_reo_cmd_list_cleanup(struct ath11k_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);
|
||||
rx_tid = &cmd_cache->data;
|
||||
if (rx_tid->vaddr) {
|
||||
dma_unmap_single(ab->dev, rx_tid->paddr,
|
||||
rx_tid->size, DMA_BIDIRECTIONAL);
|
||||
kfree(rx_tid->vaddr);
|
||||
rx_tid->vaddr = NULL;
|
||||
}
|
||||
kfree(cmd_cache);
|
||||
}
|
||||
spin_unlock_bh(&dp->reo_cmd_lock);
|
||||
|
@ -721,10 +707,12 @@ static void ath11k_dp_reo_cmd_free(struct ath11k_dp *dp, void *ctx,
|
|||
if (status != HAL_REO_CMD_SUCCESS)
|
||||
ath11k_warn(dp->ab, "failed to flush rx tid hw desc, tid %d status %d\n",
|
||||
rx_tid->tid, status);
|
||||
|
||||
if (rx_tid->vaddr) {
|
||||
dma_unmap_single(dp->ab->dev, rx_tid->paddr, rx_tid->size,
|
||||
DMA_BIDIRECTIONAL);
|
||||
kfree(rx_tid->vaddr);
|
||||
rx_tid->vaddr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void ath11k_dp_reo_cache_flush(struct ath11k_base *ab,
|
||||
|
@ -763,6 +751,7 @@ static void ath11k_dp_reo_cache_flush(struct ath11k_base *ab,
|
|||
dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size,
|
||||
DMA_BIDIRECTIONAL);
|
||||
kfree(rx_tid->vaddr);
|
||||
rx_tid->vaddr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -815,6 +804,7 @@ free_desc:
|
|||
dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size,
|
||||
DMA_BIDIRECTIONAL);
|
||||
kfree(rx_tid->vaddr);
|
||||
rx_tid->vaddr = NULL;
|
||||
}
|
||||
|
||||
void ath11k_peer_rx_tid_delete(struct ath11k *ar,
|
||||
|
@ -827,6 +817,8 @@ void ath11k_peer_rx_tid_delete(struct ath11k *ar,
|
|||
if (!rx_tid->active)
|
||||
return;
|
||||
|
||||
rx_tid->active = false;
|
||||
|
||||
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);
|
||||
|
@ -841,9 +833,11 @@ void ath11k_peer_rx_tid_delete(struct ath11k *ar,
|
|||
dma_unmap_single(ar->ab->dev, rx_tid->paddr, rx_tid->size,
|
||||
DMA_BIDIRECTIONAL);
|
||||
kfree(rx_tid->vaddr);
|
||||
rx_tid->vaddr = NULL;
|
||||
}
|
||||
|
||||
rx_tid->active = false;
|
||||
rx_tid->paddr = 0;
|
||||
rx_tid->size = 0;
|
||||
}
|
||||
|
||||
static int ath11k_dp_rx_link_desc_return(struct ath11k_base *ab,
|
||||
|
@ -990,6 +984,7 @@ static void ath11k_dp_rx_tid_mem_free(struct ath11k_base *ab,
|
|||
dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size,
|
||||
DMA_BIDIRECTIONAL);
|
||||
kfree(rx_tid->vaddr);
|
||||
rx_tid->vaddr = NULL;
|
||||
|
||||
rx_tid->active = false;
|
||||
|
||||
|
@ -1014,7 +1009,8 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id,
|
|||
|
||||
peer = ath11k_peer_find(ab, vdev_id, peer_mac);
|
||||
if (!peer) {
|
||||
ath11k_warn(ab, "failed to find the peer to set up rx tid\n");
|
||||
ath11k_warn(ab, "failed to find the peer %pM to set up rx tid\n",
|
||||
peer_mac);
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
@ -1027,7 +1023,8 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id,
|
|||
ba_win_sz, ssn, true);
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to update reo for rx tid %d\n", tid);
|
||||
ath11k_warn(ab, "failed to update reo for peer %pM rx tid %d\n: %d",
|
||||
peer_mac, tid, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1035,8 +1032,8 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id,
|
|||
peer_mac, paddr,
|
||||
tid, 1, ba_win_sz);
|
||||
if (ret)
|
||||
ath11k_warn(ab, "failed to send wmi command to update rx reorder queue, tid :%d (%d)\n",
|
||||
tid, ret);
|
||||
ath11k_warn(ab, "failed to send wmi rx reorder queue for peer %pM tid %d: %d\n",
|
||||
peer_mac, tid, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1069,6 +1066,8 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id,
|
|||
ret = dma_mapping_error(ab->dev, paddr);
|
||||
if (ret) {
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
ath11k_warn(ab, "failed to setup dma map for peer %pM rx tid %d: %d\n",
|
||||
peer_mac, tid, ret);
|
||||
goto err_mem_free;
|
||||
}
|
||||
|
||||
|
@ -1082,15 +1081,16 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id,
|
|||
ret = ath11k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, peer_mac,
|
||||
paddr, tid, 1, ba_win_sz);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to setup rx reorder queue, tid :%d (%d)\n",
|
||||
tid, ret);
|
||||
ath11k_warn(ar->ab, "failed to setup rx reorder queue for peer %pM tid %d: %d\n",
|
||||
peer_mac, tid, ret);
|
||||
ath11k_dp_rx_tid_mem_free(ab, peer_mac, vdev_id, tid);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
err_mem_free:
|
||||
kfree(vaddr);
|
||||
kfree(rx_tid->vaddr);
|
||||
rx_tid->vaddr = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -2665,6 +2665,9 @@ try_again:
|
|||
cookie);
|
||||
mac_id = FIELD_GET(DP_RXDMA_BUF_COOKIE_PDEV_ID, cookie);
|
||||
|
||||
if (unlikely(buf_id == 0))
|
||||
continue;
|
||||
|
||||
ar = ab->pdevs[mac_id].ar;
|
||||
rx_ring = &ar->dp.rx_refill_buf_ring;
|
||||
spin_lock_bh(&rx_ring->idr_lock);
|
||||
|
@ -3029,39 +3032,51 @@ static int ath11k_dp_rx_reap_mon_status_ring(struct ath11k_base *ab, int mac_id,
|
|||
|
||||
spin_lock_bh(&rx_ring->idr_lock);
|
||||
skb = idr_find(&rx_ring->bufs_idr, buf_id);
|
||||
spin_unlock_bh(&rx_ring->idr_lock);
|
||||
|
||||
if (!skb) {
|
||||
ath11k_warn(ab, "rx monitor status with invalid buf_id %d\n",
|
||||
buf_id);
|
||||
spin_unlock_bh(&rx_ring->idr_lock);
|
||||
pmon->buf_state = DP_MON_STATUS_REPLINISH;
|
||||
goto move_next;
|
||||
}
|
||||
|
||||
idr_remove(&rx_ring->bufs_idr, buf_id);
|
||||
spin_unlock_bh(&rx_ring->idr_lock);
|
||||
|
||||
rxcb = ATH11K_SKB_RXCB(skb);
|
||||
|
||||
dma_unmap_single(ab->dev, rxcb->paddr,
|
||||
dma_sync_single_for_cpu(ab->dev, rxcb->paddr,
|
||||
skb->len + skb_tailroom(skb),
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
tlv = (struct hal_tlv_hdr *)skb->data;
|
||||
if (FIELD_GET(HAL_TLV_HDR_TAG, tlv->tl) !=
|
||||
HAL_RX_STATUS_BUFFER_DONE) {
|
||||
ath11k_warn(ab, "mon status DONE not set %lx\n",
|
||||
ath11k_warn(ab, "mon status DONE not set %lx, buf_id %d\n",
|
||||
FIELD_GET(HAL_TLV_HDR_TAG,
|
||||
tlv->tl));
|
||||
dev_kfree_skb_any(skb);
|
||||
tlv->tl), buf_id);
|
||||
/* If done status is missing, hold onto status
|
||||
* ring until status is done for this status
|
||||
* ring buffer.
|
||||
* Keep HP in mon_status_ring unchanged,
|
||||
* and break from here.
|
||||
* Check status for same buffer for next time
|
||||
*/
|
||||
pmon->buf_state = DP_MON_STATUS_NO_DMA;
|
||||
goto move_next;
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock_bh(&rx_ring->idr_lock);
|
||||
idr_remove(&rx_ring->bufs_idr, buf_id);
|
||||
spin_unlock_bh(&rx_ring->idr_lock);
|
||||
if (ab->hw_params.full_monitor_mode) {
|
||||
ath11k_dp_rx_mon_update_status_buf_state(pmon, tlv);
|
||||
if (paddr == pmon->mon_status_paddr)
|
||||
pmon->buf_state = DP_MON_STATUS_MATCH;
|
||||
}
|
||||
|
||||
dma_unmap_single(ab->dev, rxcb->paddr,
|
||||
skb->len + skb_tailroom(skb),
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
__skb_queue_tail(skb_list, skb);
|
||||
} else {
|
||||
pmon->buf_state = DP_MON_STATUS_REPLINISH;
|
||||
|
@ -3117,8 +3132,11 @@ int ath11k_peer_rx_frag_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id
|
|||
int i;
|
||||
|
||||
tfm = crypto_alloc_shash("michael_mic", 0, 0);
|
||||
if (IS_ERR(tfm))
|
||||
if (IS_ERR(tfm)) {
|
||||
ath11k_warn(ab, "failed to allocate michael_mic shash: %ld\n",
|
||||
PTR_ERR(tfm));
|
||||
return PTR_ERR(tfm);
|
||||
}
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
|
||||
|
@ -3138,6 +3156,7 @@ int ath11k_peer_rx_frag_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id
|
|||
}
|
||||
|
||||
peer->tfm_mmic = tfm;
|
||||
peer->dp_setup_done = true;
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
return 0;
|
||||
|
@ -3583,6 +3602,13 @@ static int ath11k_dp_rx_frag_h_mpdu(struct ath11k *ar,
|
|||
ret = -ENOENT;
|
||||
goto out_unlock;
|
||||
}
|
||||
if (!peer->dp_setup_done) {
|
||||
ath11k_warn(ab, "The peer %pM [%d] has uninitialized datapath\n",
|
||||
peer->addr, peer_id);
|
||||
ret = -ENOENT;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
rx_tid = &peer->rx_tid[tid];
|
||||
|
||||
if ((!skb_queue_empty(&rx_tid->rx_frags) && seqno != rx_tid->cur_sn) ||
|
||||
|
@ -3598,7 +3624,7 @@ static int ath11k_dp_rx_frag_h_mpdu(struct ath11k *ar,
|
|||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (frag_no > __fls(rx_tid->rx_frag_bitmap))
|
||||
if (!rx_tid->rx_frag_bitmap || (frag_no > __fls(rx_tid->rx_frag_bitmap)))
|
||||
__skb_queue_tail(&rx_tid->rx_frags, msdu);
|
||||
else
|
||||
ath11k_dp_rx_h_sort_frags(ar, &rx_tid->rx_frags, msdu);
|
||||
|
|
|
@ -316,10 +316,12 @@ ath11k_dp_tx_htt_tx_complete_buf(struct ath11k_base *ab,
|
|||
struct dp_tx_ring *tx_ring,
|
||||
struct ath11k_dp_htt_wbm_tx_status *ts)
|
||||
{
|
||||
struct ieee80211_tx_status status = { 0 };
|
||||
struct sk_buff *msdu;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct ath11k_skb_cb *skb_cb;
|
||||
struct ath11k *ar;
|
||||
struct ath11k_peer *peer;
|
||||
|
||||
spin_lock(&tx_ring->tx_idr_lock);
|
||||
msdu = idr_remove(&tx_ring->txbuf_idr, ts->msdu_id);
|
||||
|
@ -341,6 +343,11 @@ ath11k_dp_tx_htt_tx_complete_buf(struct ath11k_base *ab,
|
|||
|
||||
dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
|
||||
|
||||
if (!skb_cb->vif) {
|
||||
dev_kfree_skb_any(msdu);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
|
||||
if (ts->acked) {
|
||||
|
@ -355,7 +362,23 @@ ath11k_dp_tx_htt_tx_complete_buf(struct ath11k_base *ab,
|
|||
}
|
||||
}
|
||||
|
||||
ieee80211_tx_status(ar->hw, msdu);
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
peer = ath11k_peer_find_by_id(ab, ts->peer_id);
|
||||
if (!peer || !peer->sta) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_DATA,
|
||||
"dp_tx: failed to find the peer with peer_id %d\n",
|
||||
ts->peer_id);
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
dev_kfree_skb_any(msdu);
|
||||
return;
|
||||
}
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
status.sta = peer->sta;
|
||||
status.info = info;
|
||||
status.skb = msdu;
|
||||
|
||||
ieee80211_tx_status_ext(ar->hw, &status);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -379,7 +402,15 @@ ath11k_dp_tx_process_htt_tx_complete(struct ath11k_base *ab,
|
|||
ts.msdu_id = msdu_id;
|
||||
ts.ack_rssi = FIELD_GET(HTT_TX_WBM_COMP_INFO1_ACK_RSSI,
|
||||
status_desc->info1);
|
||||
|
||||
if (FIELD_GET(HTT_TX_WBM_COMP_INFO2_VALID, status_desc->info2))
|
||||
ts.peer_id = FIELD_GET(HTT_TX_WBM_COMP_INFO2_SW_PEER_ID,
|
||||
status_desc->info2);
|
||||
else
|
||||
ts.peer_id = HTT_INVALID_PEER_ID;
|
||||
|
||||
ath11k_dp_tx_htt_tx_complete_buf(ab, tx_ring, &ts);
|
||||
|
||||
break;
|
||||
case HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ:
|
||||
case HAL_WBM_REL_HTT_TX_COMP_STATUS_INSPECT:
|
||||
|
|
|
@ -13,6 +13,7 @@ struct ath11k_dp_htt_wbm_tx_status {
|
|||
u32 msdu_id;
|
||||
bool acked;
|
||||
int ack_rssi;
|
||||
u16 peer_id;
|
||||
};
|
||||
|
||||
void ath11k_dp_tx_update_txcompl(struct ath11k *ar, struct hal_tx_status *ts);
|
||||
|
|
|
@ -865,6 +865,12 @@ ath11k_hal_rx_populate_mu_user_info(void *rx_tlv, struct hal_rx_mon_ppdu_info *p
|
|||
ath11k_hal_rx_populate_byte_count(rx_tlv, ppdu_info, rx_user_status);
|
||||
}
|
||||
|
||||
static u16 ath11k_hal_rx_mpduinfo_get_peerid(struct ath11k_base *ab,
|
||||
struct hal_rx_mpdu_info *mpdu_info)
|
||||
{
|
||||
return ab->hw_params.hw_ops->mpdu_info_get_peerid(mpdu_info);
|
||||
}
|
||||
|
||||
static enum hal_rx_mon_status
|
||||
ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab,
|
||||
struct hal_rx_mon_ppdu_info *ppdu_info,
|
||||
|
@ -1023,7 +1029,7 @@ ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab,
|
|||
info1 = __le32_to_cpu(vht_sig->info1);
|
||||
|
||||
ppdu_info->ldpc = FIELD_GET(HAL_RX_VHT_SIG_A_INFO_INFO1_SU_MU_CODING,
|
||||
info0);
|
||||
info1);
|
||||
ppdu_info->mcs = FIELD_GET(HAL_RX_VHT_SIG_A_INFO_INFO1_MCS,
|
||||
info1);
|
||||
gi_setting = FIELD_GET(HAL_RX_VHT_SIG_A_INFO_INFO1_GI_SETTING,
|
||||
|
@ -1446,7 +1452,7 @@ ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab,
|
|||
* PHYRX_OTHER_RECEIVE_INFO TLV.
|
||||
*/
|
||||
ppdu_info->rssi_comb =
|
||||
FIELD_GET(HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO1_RSSI_COMB,
|
||||
FIELD_GET(HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RSSI_COMB,
|
||||
__le32_to_cpu(rssi->info0));
|
||||
|
||||
if (db2dbm) {
|
||||
|
@ -1459,9 +1465,11 @@ ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab,
|
|||
break;
|
||||
}
|
||||
case HAL_RX_MPDU_START: {
|
||||
struct hal_rx_mpdu_info *mpdu_info =
|
||||
(struct hal_rx_mpdu_info *)tlv_data;
|
||||
u16 peer_id;
|
||||
|
||||
peer_id = ab->hw_params.hw_ops->mpdu_info_get_peerid(tlv_data);
|
||||
peer_id = ath11k_hal_rx_mpduinfo_get_peerid(ab, mpdu_info);
|
||||
if (peer_id)
|
||||
ppdu_info->peer_id = peer_id;
|
||||
break;
|
||||
|
|
|
@ -385,7 +385,7 @@ struct hal_rx_he_sig_b2_ofdma_info {
|
|||
__le32 info0;
|
||||
} __packed;
|
||||
|
||||
#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO1_RSSI_COMB GENMASK(15, 8)
|
||||
#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RSSI_COMB GENMASK(15, 8)
|
||||
|
||||
#define HAL_RX_PHYRX_RSSI_PREAMBLE_PRI20 GENMASK(7, 0)
|
||||
|
||||
|
@ -405,7 +405,7 @@ struct hal_rx_phyrx_rssi_legacy_info {
|
|||
#define HAL_RX_MPDU_INFO_INFO0_PEERID_WCN6855 GENMASK(15, 0)
|
||||
#define HAL_RX_MPDU_INFO_INFO1_MPDU_LEN GENMASK(13, 0)
|
||||
|
||||
struct hal_rx_mpdu_info {
|
||||
struct hal_rx_mpdu_info_ipq8074 {
|
||||
__le32 rsvd0;
|
||||
__le32 info0;
|
||||
__le32 rsvd1[11];
|
||||
|
@ -413,12 +413,28 @@ struct hal_rx_mpdu_info {
|
|||
__le32 rsvd2[9];
|
||||
} __packed;
|
||||
|
||||
struct hal_rx_mpdu_info_qcn9074 {
|
||||
__le32 rsvd0[10];
|
||||
__le32 info0;
|
||||
__le32 rsvd1[2];
|
||||
__le32 info1;
|
||||
__le32 rsvd2[9];
|
||||
} __packed;
|
||||
|
||||
struct hal_rx_mpdu_info_wcn6855 {
|
||||
__le32 rsvd0[8];
|
||||
__le32 info0;
|
||||
__le32 rsvd1[14];
|
||||
} __packed;
|
||||
|
||||
struct hal_rx_mpdu_info {
|
||||
union {
|
||||
struct hal_rx_mpdu_info_ipq8074 ipq8074;
|
||||
struct hal_rx_mpdu_info_qcn9074 qcn9074;
|
||||
struct hal_rx_mpdu_info_wcn6855 wcn6855;
|
||||
} u;
|
||||
} __packed;
|
||||
|
||||
#define HAL_RX_PPDU_END_DURATION GENMASK(23, 0)
|
||||
struct hal_rx_ppdu_end_duration {
|
||||
__le32 rsvd0[9];
|
||||
|
|
|
@ -835,26 +835,35 @@ static void ath11k_hw_ipq5018_reo_setup(struct ath11k_base *ab)
|
|||
ring_hash_map);
|
||||
}
|
||||
|
||||
static u16 ath11k_hw_ipq8074_mpdu_info_get_peerid(u8 *tlv_data)
|
||||
static u16
|
||||
ath11k_hw_ipq8074_mpdu_info_get_peerid(struct hal_rx_mpdu_info *mpdu_info)
|
||||
{
|
||||
u16 peer_id = 0;
|
||||
struct hal_rx_mpdu_info *mpdu_info =
|
||||
(struct hal_rx_mpdu_info *)tlv_data;
|
||||
|
||||
peer_id = FIELD_GET(HAL_RX_MPDU_INFO_INFO0_PEERID,
|
||||
__le32_to_cpu(mpdu_info->info0));
|
||||
__le32_to_cpu(mpdu_info->u.ipq8074.info0));
|
||||
|
||||
return peer_id;
|
||||
}
|
||||
|
||||
static u16 ath11k_hw_wcn6855_mpdu_info_get_peerid(u8 *tlv_data)
|
||||
static u16
|
||||
ath11k_hw_qcn9074_mpdu_info_get_peerid(struct hal_rx_mpdu_info *mpdu_info)
|
||||
{
|
||||
u16 peer_id = 0;
|
||||
|
||||
peer_id = FIELD_GET(HAL_RX_MPDU_INFO_INFO0_PEERID,
|
||||
__le32_to_cpu(mpdu_info->u.qcn9074.info0));
|
||||
|
||||
return peer_id;
|
||||
}
|
||||
|
||||
static u16
|
||||
ath11k_hw_wcn6855_mpdu_info_get_peerid(struct hal_rx_mpdu_info *mpdu_info)
|
||||
{
|
||||
u16 peer_id = 0;
|
||||
struct hal_rx_mpdu_info_wcn6855 *mpdu_info =
|
||||
(struct hal_rx_mpdu_info_wcn6855 *)tlv_data;
|
||||
|
||||
peer_id = FIELD_GET(HAL_RX_MPDU_INFO_INFO0_PEERID_WCN6855,
|
||||
__le32_to_cpu(mpdu_info->info0));
|
||||
__le32_to_cpu(mpdu_info->u.wcn6855.info0));
|
||||
return peer_id;
|
||||
}
|
||||
|
||||
|
@ -1042,7 +1051,7 @@ const struct ath11k_hw_ops qcn9074_ops = {
|
|||
.rx_desc_get_attention = ath11k_hw_qcn9074_rx_desc_get_attention,
|
||||
.rx_desc_get_msdu_payload = ath11k_hw_qcn9074_rx_desc_get_msdu_payload,
|
||||
.reo_setup = ath11k_hw_ipq8074_reo_setup,
|
||||
.mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid,
|
||||
.mpdu_info_get_peerid = ath11k_hw_qcn9074_mpdu_info_get_peerid,
|
||||
.rx_desc_mac_addr2_valid = ath11k_hw_ipq9074_rx_desc_mac_addr2_valid,
|
||||
.rx_desc_mpdu_start_addr2 = ath11k_hw_ipq9074_rx_desc_mpdu_start_addr2,
|
||||
.get_ring_selector = ath11k_hw_ipq8074_get_tcl_ring_selector,
|
||||
|
@ -1224,6 +1233,7 @@ const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_ipq8074 = {
|
|||
ATH11K_RX_WBM_REL_RING_MASK_0,
|
||||
},
|
||||
.reo_status = {
|
||||
0, 0, 0,
|
||||
ATH11K_REO_STATUS_RING_MASK_0,
|
||||
},
|
||||
.rxdma2host = {
|
||||
|
|
|
@ -224,7 +224,6 @@ struct ath11k_hw_params {
|
|||
u32 tx_ring_size;
|
||||
bool smp2p_wow_exit;
|
||||
bool support_fw_mac_sequence;
|
||||
bool ftm_responder;
|
||||
};
|
||||
|
||||
struct ath11k_hw_ops {
|
||||
|
@ -264,7 +263,7 @@ struct ath11k_hw_ops {
|
|||
struct rx_attention *(*rx_desc_get_attention)(struct hal_rx_desc *desc);
|
||||
u8 *(*rx_desc_get_msdu_payload)(struct hal_rx_desc *desc);
|
||||
void (*reo_setup)(struct ath11k_base *ab);
|
||||
u16 (*mpdu_info_get_peerid)(u8 *tlv_data);
|
||||
u16 (*mpdu_info_get_peerid)(struct hal_rx_mpdu_info *mpdu_info);
|
||||
bool (*rx_desc_mac_addr2_valid)(struct hal_rx_desc *desc);
|
||||
u8* (*rx_desc_mpdu_start_addr2)(struct hal_rx_desc *desc);
|
||||
u32 (*get_ring_selector)(struct sk_buff *skb);
|
||||
|
|
|
@ -3538,7 +3538,7 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
|
|||
|
||||
if (changed & BSS_CHANGED_FTM_RESPONDER &&
|
||||
arvif->ftm_responder != info->ftm_responder &&
|
||||
ar->ab->hw_params.ftm_responder &&
|
||||
test_bit(WMI_TLV_SERVICE_RTT, ar->ab->wmi_ab.svc_map) &&
|
||||
(vif->type == NL80211_IFTYPE_AP ||
|
||||
vif->type == NL80211_IFTYPE_MESH_POINT)) {
|
||||
arvif->ftm_responder = info->ftm_responder;
|
||||
|
@ -3755,6 +3755,18 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,
|
|||
int i;
|
||||
u32 scan_timeout;
|
||||
|
||||
/* Firmwares advertising the support of triggering 11D algorithm
|
||||
* on the scan results of a regular scan expects driver to send
|
||||
* WMI_11D_SCAN_START_CMDID before sending WMI_START_SCAN_CMDID.
|
||||
* With this feature, separate 11D scan can be avoided since
|
||||
* regdomain can be determined with the scan results of the
|
||||
* regular scan.
|
||||
*/
|
||||
if (ar->state_11d == ATH11K_11D_PREPARING &&
|
||||
test_bit(WMI_TLV_SERVICE_SUPPORT_11D_FOR_HOST_SCAN,
|
||||
ar->ab->wmi_ab.svc_map))
|
||||
ath11k_mac_11d_scan_start(ar, arvif->vdev_id);
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
@ -3819,9 +3831,30 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,
|
|||
goto exit;
|
||||
}
|
||||
|
||||
for (i = 0; i < arg->num_chan; i++)
|
||||
for (i = 0; i < arg->num_chan; i++) {
|
||||
if (test_bit(WMI_TLV_SERVICE_SCAN_CONFIG_PER_CHANNEL,
|
||||
ar->ab->wmi_ab.svc_map)) {
|
||||
arg->chan_list[i] =
|
||||
u32_encode_bits(req->channels[i]->center_freq,
|
||||
WMI_SCAN_CONFIG_PER_CHANNEL_MASK);
|
||||
|
||||
/* If NL80211_SCAN_FLAG_COLOCATED_6GHZ is set in scan
|
||||
* flags, then scan all PSC channels in 6 GHz band and
|
||||
* those non-PSC channels where RNR IE is found during
|
||||
* the legacy 2.4/5 GHz scan.
|
||||
* If NL80211_SCAN_FLAG_COLOCATED_6GHZ is not set,
|
||||
* then all channels in 6 GHz will be scanned.
|
||||
*/
|
||||
if (req->channels[i]->band == NL80211_BAND_6GHZ &&
|
||||
req->flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ &&
|
||||
!cfg80211_channel_is_psc(req->channels[i]))
|
||||
arg->chan_list[i] |=
|
||||
WMI_SCAN_CH_FLAG_SCAN_ONLY_IF_RNR_FOUND;
|
||||
} else {
|
||||
arg->chan_list[i] = req->channels[i]->center_freq;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
|
||||
arg->scan_f_add_spoofed_mac_in_probe = 1;
|
||||
|
@ -5552,10 +5585,6 @@ static int ath11k_mac_copy_he_cap(struct ath11k *ar,
|
|||
|
||||
he_cap_elem->mac_cap_info[1] &=
|
||||
IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK;
|
||||
he_cap_elem->phy_cap_info[0] &=
|
||||
~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
|
||||
he_cap_elem->phy_cap_info[0] &=
|
||||
~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G;
|
||||
|
||||
he_cap_elem->phy_cap_info[5] &=
|
||||
~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;
|
||||
|
@ -6652,6 +6681,11 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,
|
|||
ath11k_dbg(ab, ATH11K_DBG_MAC, "mac remove interface (vdev %d)\n",
|
||||
arvif->vdev_id);
|
||||
|
||||
ret = ath11k_spectral_vif_stop(arvif);
|
||||
if (ret)
|
||||
ath11k_warn(ab, "failed to stop spectral for vdev %i: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
|
||||
if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
|
||||
ath11k_mac_11d_scan_stop(ar);
|
||||
|
||||
|
@ -9213,7 +9247,7 @@ static int __ath11k_mac_register(struct ath11k *ar)
|
|||
wiphy_ext_feature_set(ar->hw->wiphy,
|
||||
NL80211_EXT_FEATURE_SET_SCAN_DWELL);
|
||||
|
||||
if (ab->hw_params.ftm_responder)
|
||||
if (test_bit(WMI_TLV_SERVICE_RTT, ar->ab->wmi_ab.svc_map))
|
||||
wiphy_ext_feature_set(ar->hw->wiphy,
|
||||
NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER);
|
||||
|
||||
|
|
|
@ -540,7 +540,7 @@ static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev)
|
|||
if (!ab->mem) {
|
||||
ath11k_err(ab, "failed to map pci bar %d\n", ATH11K_PCI_BAR_NUM);
|
||||
ret = -EIO;
|
||||
goto clear_master;
|
||||
goto release_region;
|
||||
}
|
||||
|
||||
ab->mem_ce = ab->mem;
|
||||
|
@ -548,8 +548,6 @@ static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev)
|
|||
ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot pci_mem 0x%pK\n", ab->mem);
|
||||
return 0;
|
||||
|
||||
clear_master:
|
||||
pci_clear_master(pdev);
|
||||
release_region:
|
||||
pci_release_region(pdev, ATH11K_PCI_BAR_NUM);
|
||||
disable_device:
|
||||
|
@ -565,7 +563,6 @@ static void ath11k_pci_free_region(struct ath11k_pci *ab_pci)
|
|||
|
||||
pci_iounmap(pci_dev, ab->mem);
|
||||
ab->mem = NULL;
|
||||
pci_clear_master(pci_dev);
|
||||
pci_release_region(pci_dev, ATH11K_PCI_BAR_NUM);
|
||||
if (pci_is_enabled(pci_dev))
|
||||
pci_disable_device(pci_dev);
|
||||
|
@ -1039,7 +1036,8 @@ module_exit(ath11k_pci_exit);
|
|||
MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN PCIe devices");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
/* QCA639x 2.0 firmware files */
|
||||
MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_BOARD_API2_FILE);
|
||||
MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_AMSS_FILE);
|
||||
MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_M3_FILE);
|
||||
/* firmware files */
|
||||
MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/*");
|
||||
MODULE_FIRMWARE(ATH11K_FW_DIR "/QCN9074/hw1.0/*");
|
||||
MODULE_FIRMWARE(ATH11K_FW_DIR "/WCN6855/hw2.0/*");
|
||||
MODULE_FIRMWARE(ATH11K_FW_DIR "/WCN6855/hw2.1/*");
|
||||
|
|
|
@ -35,6 +35,7 @@ struct ath11k_peer {
|
|||
u16 sec_type;
|
||||
u16 sec_type_grp;
|
||||
bool is_authorized;
|
||||
bool dp_setup_done;
|
||||
};
|
||||
|
||||
void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id);
|
||||
|
|
|
@ -82,6 +82,12 @@ struct wmi_tlv_fw_stats_parse {
|
|||
bool chain_rssi_done;
|
||||
};
|
||||
|
||||
struct wmi_tlv_mgmt_rx_parse {
|
||||
const struct wmi_mgmt_rx_hdr *fixed;
|
||||
const u8 *frame_buf;
|
||||
bool frame_buf_done;
|
||||
};
|
||||
|
||||
static const struct wmi_tlv_policy wmi_tlv_policies[] = {
|
||||
[WMI_TAG_ARRAY_BYTE]
|
||||
= { .min_len = 0 },
|
||||
|
@ -865,7 +871,8 @@ static void ath11k_wmi_put_wmi_channel(struct wmi_channel *chan,
|
|||
|
||||
chan->band_center_freq2 = arg->channel.band_center_freq1;
|
||||
|
||||
} else if (arg->channel.mode == MODE_11AC_VHT80_80) {
|
||||
} else if ((arg->channel.mode == MODE_11AC_VHT80_80) ||
|
||||
(arg->channel.mode == MODE_11AX_HE80_80)) {
|
||||
chan->band_center_freq2 = arg->channel.band_center_freq2;
|
||||
} else {
|
||||
chan->band_center_freq2 = 0;
|
||||
|
@ -5633,28 +5640,49 @@ static int ath11k_pull_vdev_stopped_param_tlv(struct ath11k_base *ab, struct sk_
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ath11k_wmi_tlv_mgmt_rx_parse(struct ath11k_base *ab,
|
||||
u16 tag, u16 len,
|
||||
const void *ptr, void *data)
|
||||
{
|
||||
struct wmi_tlv_mgmt_rx_parse *parse = data;
|
||||
|
||||
switch (tag) {
|
||||
case WMI_TAG_MGMT_RX_HDR:
|
||||
parse->fixed = ptr;
|
||||
break;
|
||||
case WMI_TAG_ARRAY_BYTE:
|
||||
if (!parse->frame_buf_done) {
|
||||
parse->frame_buf = ptr;
|
||||
parse->frame_buf_done = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath11k_pull_mgmt_rx_params_tlv(struct ath11k_base *ab,
|
||||
struct sk_buff *skb,
|
||||
struct mgmt_rx_event_params *hdr)
|
||||
{
|
||||
const void **tb;
|
||||
struct wmi_tlv_mgmt_rx_parse parse = { };
|
||||
const struct wmi_mgmt_rx_hdr *ev;
|
||||
const u8 *frame;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
ret = ath11k_wmi_tlv_iter(ab, skb->data, skb->len,
|
||||
ath11k_wmi_tlv_mgmt_rx_parse,
|
||||
&parse);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to parse mgmt rx tlv %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ev = tb[WMI_TAG_MGMT_RX_HDR];
|
||||
frame = tb[WMI_TAG_ARRAY_BYTE];
|
||||
ev = parse.fixed;
|
||||
frame = parse.frame_buf;
|
||||
|
||||
if (!ev || !frame) {
|
||||
ath11k_warn(ab, "failed to fetch mgmt rx hdr");
|
||||
kfree(tb);
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
|
@ -5673,7 +5701,6 @@ static int ath11k_pull_mgmt_rx_params_tlv(struct ath11k_base *ab,
|
|||
|
||||
if (skb->len < (frame - skb->data) + hdr->buf_len) {
|
||||
ath11k_warn(ab, "invalid length in mgmt rx hdr ev");
|
||||
kfree(tb);
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
|
@ -5685,7 +5712,6 @@ static int ath11k_pull_mgmt_rx_params_tlv(struct ath11k_base *ab,
|
|||
|
||||
ath11k_ce_byte_swap(skb->data, hdr->buf_len);
|
||||
|
||||
kfree(tb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -2100,8 +2100,10 @@ enum wmi_tlv_service {
|
|||
|
||||
/* The second 128 bits */
|
||||
WMI_MAX_EXT_SERVICE = 256,
|
||||
WMI_TLV_SERVICE_SCAN_CONFIG_PER_CHANNEL = 265,
|
||||
WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281,
|
||||
WMI_TLV_SERVICE_BIOS_SAR_SUPPORT = 326,
|
||||
WMI_TLV_SERVICE_SUPPORT_11D_FOR_HOST_SCAN = 357,
|
||||
|
||||
/* The third 128 bits */
|
||||
WMI_MAX_EXT2_SERVICE = 384
|
||||
|
@ -3249,6 +3251,9 @@ struct wmi_start_scan_cmd {
|
|||
#define WMI_SCAN_DWELL_MODE_SHIFT 21
|
||||
#define WMI_SCAN_FLAG_EXT_PASSIVE_SCAN_START_TIME_ENHANCE 0x00000800
|
||||
|
||||
#define WMI_SCAN_CONFIG_PER_CHANNEL_MASK GENMASK(19, 0)
|
||||
#define WMI_SCAN_CH_FLAG_SCAN_ONLY_IF_RNR_FOUND BIT(20)
|
||||
|
||||
enum {
|
||||
WMI_SCAN_DWELL_MODE_DEFAULT = 0,
|
||||
WMI_SCAN_DWELL_MODE_CONSERVATIVE = 1,
|
||||
|
|
|
@ -395,6 +395,7 @@ struct ath12k_sta {
|
|||
u8 rssi_comb;
|
||||
struct ath12k_rx_peer_stats *rx_stats;
|
||||
struct ath12k_wbm_tx_stats *wbm_tx_stats;
|
||||
u32 bw_prev;
|
||||
};
|
||||
|
||||
#define ATH12K_MIN_5G_FREQ 4150
|
||||
|
|
|
@ -196,7 +196,8 @@ static void ath12k_dp_rxdesc_set_msdu_len(struct ath12k_base *ab,
|
|||
static bool ath12k_dp_rx_h_is_mcbc(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->rx_desc_is_mcbc(desc);
|
||||
return (ath12k_dp_rx_h_first_msdu(ab, desc) &&
|
||||
ab->hw_params->hal_ops->rx_desc_is_mcbc(desc));
|
||||
}
|
||||
|
||||
static bool ath12k_dp_rxdesc_mac_addr2_valid(struct ath12k_base *ab,
|
||||
|
@ -3047,10 +3048,14 @@ 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));
|
||||
reo_ent_ring->info0 = le32_encode_bits(upper_32_bits(rx_tid->paddr),
|
||||
HAL_REO_ENTR_RING_INFO0_QUEUE_ADDR_HI) |
|
||||
le32_encode_bits(dst_ind, HAL_REO_ENTR_RING_INFO0_DEST_IND);
|
||||
/* Firmware expects physical address to be filled in queue_addr_lo in
|
||||
* the MLO scenario and in case of non MLO peer meta data needs to be
|
||||
* filled.
|
||||
* TODO: Need to handle for MLO scenario.
|
||||
*/
|
||||
reo_ent_ring->queue_addr_lo = reo_dest_ring->rx_mpdu_info.peer_meta_data;
|
||||
reo_ent_ring->info0 = le32_encode_bits(dst_ind,
|
||||
HAL_REO_ENTR_RING_INFO0_DEST_IND);
|
||||
|
||||
reo_ent_ring->info1 = le32_encode_bits(rx_tid->cur_sn,
|
||||
HAL_REO_ENTR_RING_INFO1_MPDU_SEQ_NUM);
|
||||
|
|
|
@ -13,6 +13,10 @@ static enum hal_tcl_encap_type
|
|||
ath12k_dp_tx_get_encap_type(struct ath12k_vif *arvif, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
struct ath12k_base *ab = arvif->ar->ab;
|
||||
|
||||
if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags))
|
||||
return HAL_TCL_ENCAP_TYPE_RAW;
|
||||
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)
|
||||
return HAL_TCL_ENCAP_TYPE_ETHERNET;
|
||||
|
|
|
@ -944,7 +944,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
|||
.interface_modes = BIT(NL80211_IFTYPE_STATION),
|
||||
.supports_monitor = false,
|
||||
|
||||
.idle_ps = false,
|
||||
.idle_ps = true,
|
||||
.download_calib = false,
|
||||
.supports_suspend = false,
|
||||
.tcl_ring_retry = false,
|
||||
|
|
|
@ -3220,10 +3220,11 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
|
|||
enum nl80211_band band;
|
||||
const u8 *ht_mcs_mask;
|
||||
const u16 *vht_mcs_mask;
|
||||
u32 changed, bw, nss, smps;
|
||||
u32 changed, bw, nss, smps, bw_prev;
|
||||
int err, num_vht_rates;
|
||||
const struct cfg80211_bitrate_mask *mask;
|
||||
struct ath12k_wmi_peer_assoc_arg peer_arg;
|
||||
enum wmi_phy_mode peer_phymode;
|
||||
|
||||
arsta = container_of(wk, struct ath12k_sta, update_wk);
|
||||
sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv);
|
||||
|
@ -3243,6 +3244,7 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
|
|||
arsta->changed = 0;
|
||||
|
||||
bw = arsta->bw;
|
||||
bw_prev = arsta->bw_prev;
|
||||
nss = arsta->nss;
|
||||
smps = arsta->smps;
|
||||
|
||||
|
@ -3255,11 +3257,53 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
|
|||
ath12k_mac_max_vht_nss(vht_mcs_mask)));
|
||||
|
||||
if (changed & IEEE80211_RC_BW_CHANGED) {
|
||||
err = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
|
||||
WMI_PEER_CHWIDTH, bw);
|
||||
ath12k_peer_assoc_h_phymode(ar, arvif->vif, sta, &peer_arg);
|
||||
peer_phymode = peer_arg.peer_phymode;
|
||||
|
||||
if (bw > bw_prev) {
|
||||
/* Phymode shows maximum supported channel width, if we
|
||||
* upgrade bandwidth then due to sanity check of firmware,
|
||||
* we have to send WMI_PEER_PHYMODE followed by
|
||||
* WMI_PEER_CHWIDTH
|
||||
*/
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac bandwidth upgrade for sta %pM new %d old %d\n",
|
||||
sta->addr, bw, bw_prev);
|
||||
err = ath12k_wmi_set_peer_param(ar, sta->addr,
|
||||
arvif->vdev_id, WMI_PEER_PHYMODE,
|
||||
peer_phymode);
|
||||
if (err) {
|
||||
ath12k_warn(ar->ab, "failed to update STA %pM to peer phymode %d: %d\n",
|
||||
sta->addr, peer_phymode, err);
|
||||
goto err_rc_bw_changed;
|
||||
}
|
||||
err = ath12k_wmi_set_peer_param(ar, sta->addr,
|
||||
arvif->vdev_id, WMI_PEER_CHWIDTH,
|
||||
bw);
|
||||
if (err)
|
||||
ath12k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n",
|
||||
ath12k_warn(ar->ab, "failed to update STA %pM to peer bandwidth %d: %d\n",
|
||||
sta->addr, bw, err);
|
||||
} else {
|
||||
/* When we downgrade bandwidth this will conflict with phymode
|
||||
* and cause to trigger firmware crash. In this case we send
|
||||
* WMI_PEER_CHWIDTH followed by WMI_PEER_PHYMODE
|
||||
*/
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac bandwidth downgrade for sta %pM new %d old %d\n",
|
||||
sta->addr, bw, bw_prev);
|
||||
err = ath12k_wmi_set_peer_param(ar, sta->addr,
|
||||
arvif->vdev_id, WMI_PEER_CHWIDTH,
|
||||
bw);
|
||||
if (err) {
|
||||
ath12k_warn(ar->ab, "failed to update STA %pM peer to bandwidth %d: %d\n",
|
||||
sta->addr, bw, err);
|
||||
goto err_rc_bw_changed;
|
||||
}
|
||||
err = ath12k_wmi_set_peer_param(ar, sta->addr,
|
||||
arvif->vdev_id, WMI_PEER_PHYMODE,
|
||||
peer_phymode);
|
||||
if (err)
|
||||
ath12k_warn(ar->ab, "failed to update STA %pM to peer phymode %d: %d\n",
|
||||
sta->addr, peer_phymode, err);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_RC_NSS_CHANGED) {
|
||||
|
@ -3321,7 +3365,7 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
|
|||
sta->addr, arvif->vdev_id);
|
||||
}
|
||||
}
|
||||
|
||||
err_rc_bw_changed:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
|
||||
|
@ -3433,6 +3477,34 @@ exit:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static u32 ath12k_mac_ieee80211_sta_bw_to_wmi(struct ath12k *ar,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
u32 bw = WMI_PEER_CHWIDTH_20MHZ;
|
||||
|
||||
switch (sta->deflink.bandwidth) {
|
||||
case IEEE80211_STA_RX_BW_20:
|
||||
bw = WMI_PEER_CHWIDTH_20MHZ;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_40:
|
||||
bw = WMI_PEER_CHWIDTH_40MHZ;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_80:
|
||||
bw = WMI_PEER_CHWIDTH_80MHZ;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_160:
|
||||
bw = WMI_PEER_CHWIDTH_160MHZ;
|
||||
break;
|
||||
default:
|
||||
ath12k_warn(ar->ab, "Invalid bandwidth %d in rc update for %pM\n",
|
||||
sta->deflink.bandwidth, sta->addr);
|
||||
bw = WMI_PEER_CHWIDTH_20MHZ;
|
||||
break;
|
||||
}
|
||||
|
||||
return bw;
|
||||
}
|
||||
|
||||
static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
|
@ -3498,6 +3570,13 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
|
|||
if (ret)
|
||||
ath12k_warn(ar->ab, "Failed to associate station: %pM\n",
|
||||
sta->addr);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
arsta->bw = ath12k_mac_ieee80211_sta_bw_to_wmi(ar, sta);
|
||||
arsta->bw_prev = sta->deflink.bandwidth;
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
} else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
new_state == IEEE80211_STA_AUTHORIZED) {
|
||||
spin_lock_bh(&ar->ab->base_lock);
|
||||
|
@ -3607,28 +3686,8 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
|
|||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
if (changed & IEEE80211_RC_BW_CHANGED) {
|
||||
bw = WMI_PEER_CHWIDTH_20MHZ;
|
||||
|
||||
switch (sta->deflink.bandwidth) {
|
||||
case IEEE80211_STA_RX_BW_20:
|
||||
bw = WMI_PEER_CHWIDTH_20MHZ;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_40:
|
||||
bw = WMI_PEER_CHWIDTH_40MHZ;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_80:
|
||||
bw = WMI_PEER_CHWIDTH_80MHZ;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_160:
|
||||
bw = WMI_PEER_CHWIDTH_160MHZ;
|
||||
break;
|
||||
default:
|
||||
ath12k_warn(ar->ab, "Invalid bandwidth %d in rc update for %pM\n",
|
||||
sta->deflink.bandwidth, sta->addr);
|
||||
bw = WMI_PEER_CHWIDTH_20MHZ;
|
||||
break;
|
||||
}
|
||||
|
||||
bw = ath12k_mac_ieee80211_sta_bw_to_wmi(ar, sta);
|
||||
arsta->bw_prev = arsta->bw;
|
||||
arsta->bw = bw;
|
||||
}
|
||||
|
||||
|
|
|
@ -755,14 +755,12 @@ static int ath12k_pci_claim(struct ath12k_pci *ab_pci, struct pci_dev *pdev)
|
|||
if (!ab->mem) {
|
||||
ath12k_err(ab, "failed to map pci bar %d\n", ATH12K_PCI_BAR_NUM);
|
||||
ret = -EIO;
|
||||
goto clear_master;
|
||||
goto release_region;
|
||||
}
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot pci_mem 0x%pK\n", ab->mem);
|
||||
return 0;
|
||||
|
||||
clear_master:
|
||||
pci_clear_master(pdev);
|
||||
release_region:
|
||||
pci_release_region(pdev, ATH12K_PCI_BAR_NUM);
|
||||
disable_device:
|
||||
|
@ -778,7 +776,6 @@ static void ath12k_pci_free_region(struct ath12k_pci *ab_pci)
|
|||
|
||||
pci_iounmap(pci_dev, ab->mem);
|
||||
ab->mem = NULL;
|
||||
pci_clear_master(pci_dev);
|
||||
pci_release_region(pci_dev, ATH12K_PCI_BAR_NUM);
|
||||
if (pci_is_enabled(pci_dev))
|
||||
pci_disable_device(pci_dev);
|
||||
|
@ -1223,7 +1220,8 @@ static int ath12k_pci_probe(struct pci_dev *pdev,
|
|||
dev_err(&pdev->dev,
|
||||
"Unknown hardware version found for QCN9274: 0x%x\n",
|
||||
soc_hw_version_major);
|
||||
return -EOPNOTSUPP;
|
||||
ret = -EOPNOTSUPP;
|
||||
goto err_pci_free_region;
|
||||
}
|
||||
break;
|
||||
case WCN7850_DEVICE_ID:
|
||||
|
|
|
@ -2991,7 +2991,7 @@ static void ath12k_qmi_driver_event_work(struct work_struct *work)
|
|||
spin_unlock(&qmi->event_lock);
|
||||
|
||||
if (test_bit(ATH12K_FLAG_UNREGISTERING, &ab->dev_flags))
|
||||
return;
|
||||
goto skip;
|
||||
|
||||
switch (event->type) {
|
||||
case ATH12K_QMI_EVENT_SERVER_ARRIVE:
|
||||
|
@ -3032,6 +3032,8 @@ static void ath12k_qmi_driver_event_work(struct work_struct *work)
|
|||
ath12k_warn(ab, "invalid event type: %d", event->type);
|
||||
break;
|
||||
}
|
||||
|
||||
skip:
|
||||
kfree(event);
|
||||
spin_lock(&qmi->event_lock);
|
||||
}
|
||||
|
|
|
@ -2438,6 +2438,9 @@ int ath12k_wmi_send_scan_chan_list_cmd(struct ath12k *ar,
|
|||
if (channel_arg->psc_channel)
|
||||
chan_info->info |= cpu_to_le32(WMI_CHAN_INFO_PSC);
|
||||
|
||||
if (channel_arg->dfs_set)
|
||||
chan_info->info |= cpu_to_le32(WMI_CHAN_INFO_DFS);
|
||||
|
||||
chan_info->info |= le32_encode_bits(channel_arg->phy_mode,
|
||||
WMI_CHAN_INFO_MODE);
|
||||
*reg1 |= le32_encode_bits(channel_arg->minpower,
|
||||
|
@ -4934,6 +4937,9 @@ static int freq_to_idx(struct ath12k *ar, int freq)
|
|||
int band, ch, idx = 0;
|
||||
|
||||
for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) {
|
||||
if (!ar->mac.sbands[band].channels)
|
||||
continue;
|
||||
|
||||
sband = ar->hw->wiphy->bands[band];
|
||||
if (!sband)
|
||||
continue;
|
||||
|
|
|
@ -42,8 +42,6 @@ static const struct usb_device_id ath9k_hif_usb_ids[] = {
|
|||
|
||||
{ USB_DEVICE(0x0cf3, 0x7015),
|
||||
.driver_info = AR9287_USB }, /* Atheros */
|
||||
{ USB_DEVICE(0x1668, 0x1200),
|
||||
.driver_info = AR9287_USB }, /* Verizon */
|
||||
|
||||
{ USB_DEVICE(0x0cf3, 0x7010),
|
||||
.driver_info = AR9280_USB }, /* Atheros */
|
||||
|
|
|
@ -646,9 +646,7 @@ void ath9k_mci_update_wlan_channels(struct ath_softc *sc, bool allow_all)
|
|||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
|
||||
struct ath9k_channel *chan = ah->curchan;
|
||||
static const u32 channelmap[] = {
|
||||
0x00000000, 0xffff0000, 0xffffffff, 0x7fffffff
|
||||
};
|
||||
u32 channelmap[] = {0x00000000, 0xffff0000, 0xffffffff, 0x7fffffff};
|
||||
int i;
|
||||
s16 chan_start, chan_end;
|
||||
u16 wlan_chan;
|
||||
|
|
|
@ -34,6 +34,12 @@
|
|||
#define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2)
|
||||
#define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18)
|
||||
|
||||
/* Shifts in ar5008_phy.c and ar9003_phy.c are equal for all revisions */
|
||||
#define ATH9K_PWRTBL_11NA_OFDM_SHIFT 0
|
||||
#define ATH9K_PWRTBL_11NG_OFDM_SHIFT 4
|
||||
#define ATH9K_PWRTBL_11NA_HT_SHIFT 8
|
||||
#define ATH9K_PWRTBL_11NG_HT_SHIFT 12
|
||||
|
||||
|
||||
static u16 bits_per_symbol[][2] = {
|
||||
/* 20MHz 40MHz */
|
||||
|
@ -1169,13 +1175,14 @@ void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop)
|
|||
}
|
||||
|
||||
static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf,
|
||||
u8 rateidx, bool is_40, bool is_cck)
|
||||
u8 rateidx, bool is_40, bool is_cck, bool is_mcs)
|
||||
{
|
||||
u8 max_power;
|
||||
struct sk_buff *skb;
|
||||
struct ath_frame_info *fi;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
bool is_2ghz, is_5ghz, use_stbc;
|
||||
|
||||
if (sc->tx99_state || !ah->tpc_enabled)
|
||||
return MAX_RATE_POWER;
|
||||
|
@ -1184,6 +1191,19 @@ static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf,
|
|||
fi = get_frame_info(skb);
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
is_2ghz = info->band == NL80211_BAND_2GHZ;
|
||||
is_5ghz = info->band == NL80211_BAND_5GHZ;
|
||||
use_stbc = is_mcs && rateidx < 8 && (info->flags &
|
||||
IEEE80211_TX_CTL_STBC);
|
||||
|
||||
if (is_mcs)
|
||||
rateidx += is_5ghz ? ATH9K_PWRTBL_11NA_HT_SHIFT
|
||||
: ATH9K_PWRTBL_11NG_HT_SHIFT;
|
||||
else if (is_2ghz && !is_cck)
|
||||
rateidx += ATH9K_PWRTBL_11NG_OFDM_SHIFT;
|
||||
else
|
||||
rateidx += ATH9K_PWRTBL_11NA_OFDM_SHIFT;
|
||||
|
||||
if (!AR_SREV_9300_20_OR_LATER(ah)) {
|
||||
int txpower = fi->tx_power;
|
||||
|
||||
|
@ -1193,10 +1213,8 @@ static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf,
|
|||
u16 eeprom_rev = ah->eep_ops->get_eeprom_rev(ah);
|
||||
|
||||
if (eeprom_rev >= AR5416_EEP_MINOR_VER_2) {
|
||||
bool is_2ghz;
|
||||
struct modal_eep_header *pmodal;
|
||||
|
||||
is_2ghz = info->band == NL80211_BAND_2GHZ;
|
||||
pmodal = &eep->modalHeader[is_2ghz];
|
||||
power_ht40delta = pmodal->ht40PowerIncForPdadc;
|
||||
} else {
|
||||
|
@ -1229,7 +1247,7 @@ static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf,
|
|||
if (!max_power && !AR_SREV_9280_20_OR_LATER(ah))
|
||||
max_power = 1;
|
||||
} else if (!bf->bf_state.bfs_paprd) {
|
||||
if (rateidx < 8 && (info->flags & IEEE80211_TX_CTL_STBC))
|
||||
if (use_stbc)
|
||||
max_power = min_t(u8, ah->tx_power_stbc[rateidx],
|
||||
fi->tx_power);
|
||||
else
|
||||
|
@ -1319,7 +1337,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
|
|||
}
|
||||
|
||||
info->txpower[i] = ath_get_rate_txpower(sc, bf, rix,
|
||||
is_40, false);
|
||||
is_40, false, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1350,7 +1368,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
|
|||
|
||||
is_cck = IS_CCK_RATE(info->rates[i].Rate);
|
||||
info->txpower[i] = ath_get_rate_txpower(sc, bf, rix, false,
|
||||
is_cck);
|
||||
is_cck, false);
|
||||
}
|
||||
|
||||
/* For AR5416 - RTS cannot be followed by a frame larger than 8K */
|
||||
|
|
|
@ -120,7 +120,7 @@ struct carl9170_cmd *carl9170_cmd_buf(struct ar9170 *ar,
|
|||
{
|
||||
struct carl9170_cmd *tmp;
|
||||
|
||||
tmp = kzalloc(sizeof(struct carl9170_cmd_head) + len, GFP_ATOMIC);
|
||||
tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC);
|
||||
if (tmp) {
|
||||
tmp->hdr.cmd = cmd;
|
||||
tmp->hdr.len = len;
|
||||
|
|
|
@ -320,9 +320,9 @@ struct carl9170_rsp {
|
|||
struct carl9170_u32_list rreg_res;
|
||||
struct carl9170_u32_list echo;
|
||||
#ifdef __CARL9170FW__
|
||||
struct carl9170_tx_status tx_status[0];
|
||||
DECLARE_FLEX_ARRAY(struct carl9170_tx_status, tx_status);
|
||||
#endif /* __CARL9170FW__ */
|
||||
struct _carl9170_tx_status _tx_status[0];
|
||||
DECLARE_FLEX_ARRAY(struct _carl9170_tx_status, _tx_status);
|
||||
struct carl9170_gpio gpio;
|
||||
struct carl9170_tsf_rsp tsf;
|
||||
struct carl9170_psm psm;
|
||||
|
|
|
@ -112,8 +112,8 @@ int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn)
|
|||
wcn->dxe_rx_l_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_L;
|
||||
wcn->dxe_rx_h_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_H;
|
||||
|
||||
wcn->dxe_tx_l_ch.dxe_wq = WCN36XX_DXE_WQ_TX_L;
|
||||
wcn->dxe_tx_h_ch.dxe_wq = WCN36XX_DXE_WQ_TX_H;
|
||||
wcn->dxe_tx_l_ch.dxe_wq = WCN36XX_DXE_WQ_TX_L(wcn);
|
||||
wcn->dxe_tx_h_ch.dxe_wq = WCN36XX_DXE_WQ_TX_H(wcn);
|
||||
|
||||
wcn->dxe_tx_l_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_L_BD;
|
||||
wcn->dxe_tx_h_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_H_BD;
|
||||
|
@ -165,8 +165,9 @@ void wcn36xx_dxe_free_ctl_blks(struct wcn36xx *wcn)
|
|||
wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_h_ch);
|
||||
}
|
||||
|
||||
static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn_ch)
|
||||
static int wcn36xx_dxe_init_descs(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *wcn_ch)
|
||||
{
|
||||
struct device *dev = wcn->dev;
|
||||
struct wcn36xx_dxe_desc *cur_dxe = NULL;
|
||||
struct wcn36xx_dxe_desc *prev_dxe = NULL;
|
||||
struct wcn36xx_dxe_ctl *cur_ctl = NULL;
|
||||
|
@ -190,11 +191,11 @@ static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn
|
|||
switch (wcn_ch->ch_type) {
|
||||
case WCN36XX_DXE_CH_TX_L:
|
||||
cur_dxe->ctrl = WCN36XX_DXE_CTRL_TX_L;
|
||||
cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_L;
|
||||
cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_L(wcn);
|
||||
break;
|
||||
case WCN36XX_DXE_CH_TX_H:
|
||||
cur_dxe->ctrl = WCN36XX_DXE_CTRL_TX_H;
|
||||
cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_H;
|
||||
cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_H(wcn);
|
||||
break;
|
||||
case WCN36XX_DXE_CH_RX_L:
|
||||
cur_dxe->ctrl = WCN36XX_DXE_CTRL_RX_L;
|
||||
|
@ -914,7 +915,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
|
|||
/***************************************/
|
||||
/* Init descriptors for TX LOW channel */
|
||||
/***************************************/
|
||||
ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_l_ch);
|
||||
ret = wcn36xx_dxe_init_descs(wcn, &wcn->dxe_tx_l_ch);
|
||||
if (ret) {
|
||||
dev_err(wcn->dev, "Error allocating descriptor\n");
|
||||
return ret;
|
||||
|
@ -928,14 +929,14 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
|
|||
/* Program DMA destination addr for TX LOW */
|
||||
wcn36xx_dxe_write_register(wcn,
|
||||
WCN36XX_DXE_CH_DEST_ADDR_TX_L,
|
||||
WCN36XX_DXE_WQ_TX_L);
|
||||
WCN36XX_DXE_WQ_TX_L(wcn));
|
||||
|
||||
wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, ®_data);
|
||||
|
||||
/***************************************/
|
||||
/* Init descriptors for TX HIGH channel */
|
||||
/***************************************/
|
||||
ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_h_ch);
|
||||
ret = wcn36xx_dxe_init_descs(wcn, &wcn->dxe_tx_h_ch);
|
||||
if (ret) {
|
||||
dev_err(wcn->dev, "Error allocating descriptor\n");
|
||||
goto out_err_txh_ch;
|
||||
|
@ -950,14 +951,14 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
|
|||
/* Program DMA destination addr for TX HIGH */
|
||||
wcn36xx_dxe_write_register(wcn,
|
||||
WCN36XX_DXE_CH_DEST_ADDR_TX_H,
|
||||
WCN36XX_DXE_WQ_TX_H);
|
||||
WCN36XX_DXE_WQ_TX_H(wcn));
|
||||
|
||||
wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, ®_data);
|
||||
|
||||
/***************************************/
|
||||
/* Init descriptors for RX LOW channel */
|
||||
/***************************************/
|
||||
ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_l_ch);
|
||||
ret = wcn36xx_dxe_init_descs(wcn, &wcn->dxe_rx_l_ch);
|
||||
if (ret) {
|
||||
dev_err(wcn->dev, "Error allocating descriptor\n");
|
||||
goto out_err_rxl_ch;
|
||||
|
@ -988,7 +989,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
|
|||
/***************************************/
|
||||
/* Init descriptors for RX HIGH channel */
|
||||
/***************************************/
|
||||
ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_h_ch);
|
||||
ret = wcn36xx_dxe_init_descs(wcn, &wcn->dxe_rx_h_ch);
|
||||
if (ret) {
|
||||
dev_err(wcn->dev, "Error allocating descriptor\n");
|
||||
goto out_err_rxh_ch;
|
||||
|
|
|
@ -135,8 +135,8 @@ H2H_TEST_RX_TX = DMA2
|
|||
WCN36xx_DXE_CTRL_ENDIANNESS)
|
||||
|
||||
/* TODO This must calculated properly but not hardcoded */
|
||||
#define WCN36XX_DXE_WQ_TX_L 0x17
|
||||
#define WCN36XX_DXE_WQ_TX_H 0x17
|
||||
#define WCN36XX_DXE_WQ_TX_L(wcn) ((wcn)->is_pronto_v3 ? 0x6 : 0x17)
|
||||
#define WCN36XX_DXE_WQ_TX_H(wcn) ((wcn)->is_pronto_v3 ? 0x6 : 0x17)
|
||||
#define WCN36XX_DXE_WQ_RX_L 0xB
|
||||
#define WCN36XX_DXE_WQ_RX_H 0x4
|
||||
|
||||
|
|
|
@ -1508,6 +1508,7 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
|
|||
}
|
||||
|
||||
wcn->is_pronto = !!of_device_is_compatible(mmio_node, "qcom,pronto");
|
||||
wcn->is_pronto_v3 = !!of_device_is_compatible(mmio_node, "qcom,pronto-v3-pil");
|
||||
|
||||
/* Map the CCU memory */
|
||||
index = of_property_match_string(mmio_node, "reg-names", "ccu");
|
||||
|
|
|
@ -217,6 +217,7 @@ struct wcn36xx {
|
|||
u8 fw_major;
|
||||
u32 fw_feat_caps[WCN36XX_HAL_CAPS_SIZE];
|
||||
bool is_pronto;
|
||||
bool is_pronto_v3;
|
||||
|
||||
/* extra byte for the NULL termination */
|
||||
u8 crm_version[WCN36XX_HAL_VERSION_LENGTH + 1];
|
||||
|
|
Загрузка…
Ссылка в новой задаче