mirror of
https://github.com/opnsense/src.git
synced 2026-02-18 18:20:26 -05:00
iwlwifi: update Intel's iwlwifi/mvm driver.
This version is based on git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 98f7e32f20d28ec452afb208f9cffc08448a2652 ( tag: v6.11 ). Sponsored by: The FreeBSD Foundation (cherry picked from commit a4128aad8503277614f2d214011ef60a19447b83)
This commit is contained in:
parent
c57e8af7d5
commit
f4e352ef16
127 changed files with 14871 additions and 9059 deletions
|
|
@ -220,15 +220,19 @@ Intel(R) Wi-Fi 6 AX101
|
|||
.It
|
||||
Intel(R) Wi-Fi 6 AX203
|
||||
.It
|
||||
Intel(R) Wi-Fi 6E AX221 160MHz
|
||||
.It
|
||||
Intel(R) Wi-Fi 6E AX231 160MHz
|
||||
.It
|
||||
Intel(R) TBD Bz device
|
||||
Intel(R) Wi-Fi 7 BE201 320MHz
|
||||
.It
|
||||
Intel(R) Wi-Fi 6 AX204 160MHz
|
||||
Intel(R) Wi-Fi 7 BE200 320MHz
|
||||
.It
|
||||
Intel(R) Wi-Fi 7 BE202 160MHz
|
||||
.It
|
||||
Intel(R) TBD Sc device
|
||||
.It
|
||||
Intel(R) TBD Sc2 device
|
||||
.It
|
||||
Intel(R) TBD Sc2f device
|
||||
.\" --------------------------------------------------------------------
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
.\"-
|
||||
.\" Copyright (c) 2021-2023 The FreeBSD Foundation
|
||||
.\" Copyright (c) 2021-2024 The FreeBSD Foundation
|
||||
.\"
|
||||
.\" This documentation was written by Bj\xc3\xb6rn Zeeb under sponsorship from
|
||||
.\" the FreeBSD Foundation.
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd September 21, 2023
|
||||
.Dd October 12, 2024
|
||||
.Dt iwlwififw 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
|
@ -43,13 +43,18 @@ models supported by the
|
|||
.Xr iwlwifi 4
|
||||
driver.
|
||||
.Pp
|
||||
One can use
|
||||
.Xr fwget 8
|
||||
to install the correct firmware package.
|
||||
.Pp
|
||||
.Bl -column -compact "Vendor" "Device" "Subv. " "Subd. " "Firmware-Prefix"
|
||||
.It Ar Name
|
||||
.It Ar Vendor Ta Ar Device Ta Ar Subv. Ta Ar Subd. Ta Ar Firmware-Prefix
|
||||
.\" ---------------------------------------------------------------------
|
||||
.\" This list is manually generated from a sysctl and post-processing.
|
||||
.\" Edits will be overwritten on next update.
|
||||
.\" ---------------------------------------------------------------------
|
||||
.% ---------------------------------------------------------------------
|
||||
.% This list is manually generated from a sysctl and post-processing
|
||||
.% by sys/contrib/dev/iwlwifi/zzz_fw_ports_fwget.sh generating the list.
|
||||
.% Edits will be overwritten on next update.
|
||||
.% ---------------------------------------------------------------------
|
||||
.It ""
|
||||
.It Intel(R) Dual Band Wireless AC 7260
|
||||
.It 0x8086 Ta 0x08b1 Ta any Ta 0x4070 Ta iwlwifi-7260
|
||||
|
|
@ -735,6 +740,198 @@ driver.
|
|||
.It Intel(R) Dual Band Wireless AC 8265
|
||||
.It 0x8086 Ta 0x24fd Ta any Ta 0x9074 Ta iwlwifi-8265
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x2526 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x271b Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x271c Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x30dc Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x31dc Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x9df0 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa370 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x02f0 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x06f0 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x34f0 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x3df0 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x4df0 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x43f0 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa0f0 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x2723 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x2725 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x7a70 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x7af0 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x51f0 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x51f1 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x54f0 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x7f70 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x2729 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x7e40 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x2727 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x272d Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x272b Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 000000 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x0090 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x0094 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x0098 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x009c Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x00c0 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x00c4 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x00e0 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x00e4 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x00e8 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x00ec Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x0100 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x0110 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x0114 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x0118 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x011c Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x0310 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x0314 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x0510 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x0a10 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x1671 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x1672 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x1771 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x1772 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x1791 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x1792 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x4090 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x40c4 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x40e0 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x4110 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xa840 Ta any Ta 0x4314 Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x7740 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x4d40 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xe440 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xe340 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0xd340 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It (unknown)
|
||||
.It 0x8086 Ta 0x6e70 Ta any Ta any Ta (unknown)
|
||||
.It ""
|
||||
.It Killer (R) Wireless-AC 1550 Wireless Network Adapter (9260NGW) 160MHz
|
||||
.It 0x8086 Ta 0x2526 Ta any Ta 0x1550 Ta iwlwifi-9260-th-b0-jf-b0
|
||||
.It ""
|
||||
|
|
@ -1290,9 +1487,6 @@ driver.
|
|||
.It Intel(R) Wi-Fi 6E AX211 160MHz
|
||||
.It 0x8086 Ta any Ta any Ta any Ta (null)
|
||||
.It ""
|
||||
.It Intel(R) Wi-Fi 6E AX221 160MHz
|
||||
.It 0x8086 Ta any Ta any Ta any Ta (null)
|
||||
.It ""
|
||||
.It Intel(R) Wi-Fi 6E AX231 160MHz
|
||||
.It 0x8086 Ta any Ta any Ta any Ta (null)
|
||||
.It ""
|
||||
|
|
@ -1311,9 +1505,6 @@ driver.
|
|||
.It Intel(R) Wi-Fi 6E AX411 160MHz
|
||||
.It 0x8086 Ta any Ta any Ta any Ta iwlwifi-so-a0-gf4-a0
|
||||
.It ""
|
||||
.It Intel(R) TBD Bz device
|
||||
.It 0x8086 Ta any Ta any Ta any Ta (null)
|
||||
.It ""
|
||||
.It Intel(R) Wireless-AC 9560 160MHz
|
||||
.It 0x8086 Ta any Ta any Ta any Ta iwlwifi-so-a0-jf-b0
|
||||
.It ""
|
||||
|
|
@ -1332,14 +1523,23 @@ driver.
|
|||
.It Intel(R) Wireless-AC 9462
|
||||
.It 0x8086 Ta any Ta any Ta any Ta iwlwifi-so-a0-jf-b0
|
||||
.It ""
|
||||
.It Intel(R) Wi-Fi 6 AX204 160MHz
|
||||
.It 0x8086 Ta any Ta any Ta any Ta iwlwifi-so-a0-mr-a0
|
||||
.It Intel(R) Wi-Fi 7 BE201 320MHz
|
||||
.It 0x8086 Ta any Ta any Ta any Ta (null)
|
||||
.It ""
|
||||
.It Intel(R) Wi-Fi 6 AX204 160MHz
|
||||
.It Intel(R) Wi-Fi 7 BE200 320MHz
|
||||
.It 0x8086 Ta any Ta any Ta any Ta (null)
|
||||
.It ""
|
||||
.It Intel(R) Wi-Fi 7 BE202 160MHz
|
||||
.It 0x8086 Ta any Ta any Ta any Ta (null)
|
||||
.It ""
|
||||
.It Intel(R) TBD Sc device
|
||||
.It 0x8086 Ta any Ta any Ta any Ta (null)
|
||||
.It ""
|
||||
.It Intel(R) TBD Sc2 device
|
||||
.It 0x8086 Ta any Ta any Ta any Ta (null)
|
||||
.It ""
|
||||
.It Intel(R) TBD Sc2f device
|
||||
.It 0x8086 Ta any Ta any Ta any Ta (null)
|
||||
.\" ---------------------------------------------------------------------
|
||||
.El
|
||||
.Pp
|
||||
|
|
@ -1350,10 +1550,14 @@ in the above listing).
|
|||
.Sh FILES
|
||||
A copy of the
|
||||
.Xr iwlwifi 4
|
||||
firmware license is installed at
|
||||
.Em /usr/share/doc/legal/intel_iwlwifi_firmware.LICENCE .
|
||||
firmware license is installed along with the
|
||||
.Pa wifi-firmware-iwlwifi-kmod
|
||||
package or the
|
||||
.Pa ports/net/wifi-firmware-iwlwifi-kmod
|
||||
port (or each of its flavors).
|
||||
.Sh SEE ALSO
|
||||
.Xr iwlwifi 4 ,
|
||||
.Xr fwget 8 ,
|
||||
.Xr firmware 9
|
||||
.Sh HISTORY
|
||||
The
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2018-2024 Intel Corporation
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/stringify.h>
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
#define IWL_22000_UCODE_API_MAX 77
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_22000_UCODE_API_MIN 50
|
||||
#define IWL_22000_UCODE_API_MIN 77
|
||||
|
||||
/* NVM versions */
|
||||
#define IWL_22000_NVM_VERSION 0x0a1d
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2018-2024 Intel Corporation
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/stringify.h>
|
||||
|
|
@ -10,10 +10,10 @@
|
|||
#include "fw/api/txq.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL_AX210_UCODE_API_MAX 83
|
||||
#define IWL_AX210_UCODE_API_MAX 89
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_AX210_UCODE_API_MIN 59
|
||||
#define IWL_AX210_UCODE_API_MIN 77
|
||||
|
||||
/* NVM versions */
|
||||
#define IWL_AX210_NVM_VERSION 0x0a1d
|
||||
|
|
@ -299,3 +299,9 @@ MODULE_FIRMWARE(IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
|
|||
MODULE_FIRMWARE(IWL_MA_B_GF_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_MA_B_GF4_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_MA_B_MR_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
|
||||
|
||||
MODULE_FIRMWARE("iwlwifi-so-a0-gf-a0.pnvm");
|
||||
MODULE_FIRMWARE("iwlwifi-so-a0-gf4-a0.pnvm");
|
||||
MODULE_FIRMWARE("iwlwifi-ty-a0-gf-a0.pnvm");
|
||||
MODULE_FIRMWARE("iwlwifi-ma-b0-gf-a0.pnvm");
|
||||
MODULE_FIRMWARE("iwlwifi-ma-b0-gf4-a0.pnvm");
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2018-2024 Intel Corporation
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/stringify.h>
|
||||
|
|
@ -10,10 +10,10 @@
|
|||
#include "fw/api/txq.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL_BZ_UCODE_API_MAX 83
|
||||
#define IWL_BZ_UCODE_API_MAX 92
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_BZ_UCODE_API_MIN 80
|
||||
#define IWL_BZ_UCODE_API_MIN 90
|
||||
|
||||
/* NVM versions */
|
||||
#define IWL_BZ_NVM_VERSION 0x0a1d
|
||||
|
|
@ -129,17 +129,11 @@ static const struct iwl_base_params iwl_bz_base_params = {
|
|||
IWL_DEVICE_BZ_COMMON, \
|
||||
.ht_params = &iwl_22000_ht_params
|
||||
|
||||
#define IWL_DEVICE_GL_A \
|
||||
IWL_DEVICE_BZ_COMMON, \
|
||||
.ht_params = &iwl_gl_a_ht_params
|
||||
|
||||
/*
|
||||
* If the device doesn't support HE, no need to have that many buffers.
|
||||
* These sizes were picked according to 8 MSDUs inside 256 A-MSDUs in an
|
||||
* This size was picked according to 8 MSDUs inside 512 A-MSDUs in an
|
||||
* A-MPDU, with additional overhead to account for processing time.
|
||||
*/
|
||||
#define IWL_NUM_RBDS_NON_HE 512
|
||||
#define IWL_NUM_RBDS_BZ_HE 4096
|
||||
#define IWL_NUM_RBDS_BZ_EHT (512 * 16)
|
||||
|
||||
const struct iwl_cfg_trans_params iwl_bz_trans_cfg = {
|
||||
.device_family = IWL_DEVICE_FAMILY_BZ,
|
||||
|
|
@ -155,21 +149,24 @@ const struct iwl_cfg_trans_params iwl_bz_trans_cfg = {
|
|||
};
|
||||
|
||||
const char iwl_bz_name[] = "Intel(R) TBD Bz device";
|
||||
const char iwl_fm_name[] = "Intel(R) Wi-Fi 7 BE201 320MHz";
|
||||
const char iwl_gl_name[] = "Intel(R) Wi-Fi 7 BE200 320MHz";
|
||||
const char iwl_mtp_name[] = "Intel(R) Wi-Fi 7 BE202 160MHz";
|
||||
|
||||
const struct iwl_cfg iwl_cfg_bz = {
|
||||
.fw_name_mac = "bz",
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_BZ_HE,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_BZ_EHT,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_cfg_gl = {
|
||||
.fw_name_mac = "gl",
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_BZ_HE,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_BZ_EHT,
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -181,3 +178,5 @@ MODULE_FIRMWARE(IWL_BZ_A_FM_C_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
|
|||
MODULE_FIRMWARE(IWL_BZ_A_FM4_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_GL_B_FM_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_GL_C_FM_C_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
|
||||
|
||||
MODULE_FIRMWARE("iwlwifi-gl-c0-fm-c0.pnvm");
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2018-2024 Intel Corporation
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/stringify.h>
|
||||
|
|
@ -10,10 +10,10 @@
|
|||
#include "fw/api/txq.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL_SC_UCODE_API_MAX 83
|
||||
#define IWL_SC_UCODE_API_MAX 92
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_SC_UCODE_API_MIN 82
|
||||
#define IWL_SC_UCODE_API_MIN 90
|
||||
|
||||
/* NVM versions */
|
||||
#define IWL_SC_NVM_VERSION 0x0a1d
|
||||
|
|
@ -33,6 +33,10 @@
|
|||
#define IWL_SC_A_GF_A_FW_PRE "iwlwifi-sc-a0-gf-a0"
|
||||
#define IWL_SC_A_GF4_A_FW_PRE "iwlwifi-sc-a0-gf4-a0"
|
||||
#define IWL_SC_A_WH_A_FW_PRE "iwlwifi-sc-a0-wh-a0"
|
||||
#define IWL_SC2_A_FM_C_FW_PRE "iwlwifi-sc2-a0-fm-c0"
|
||||
#define IWL_SC2_A_WH_A_FW_PRE "iwlwifi-sc2-a0-wh-a0"
|
||||
#define IWL_SC2F_A_FM_C_FW_PRE "iwlwifi-sc2f-a0-fm-c0"
|
||||
#define IWL_SC2F_A_WH_A_FW_PRE "iwlwifi-sc2f-a0-wh-a0"
|
||||
|
||||
#define IWL_SC_A_FM_B_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_SC_A_FM_B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
|
|
@ -48,6 +52,14 @@
|
|||
IWL_SC_A_GF4_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_SC_A_WH_A_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_SC_A_WH_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_SC2_A_FM_C_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_SC2_A_FM_C_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_SC2_A_WH_A_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_SC2_A_WH_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_SC2F_A_FM_C_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_SC2F_A_FM_C_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_SC2F_A_WH_A_FW_MODULE_FIRMWARE(api) \
|
||||
IWL_SC2F_A_WH_A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
|
||||
static const struct iwl_base_params iwl_sc_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
|
||||
|
|
@ -124,15 +136,16 @@ static const struct iwl_base_params iwl_sc_base_params = {
|
|||
|
||||
#define IWL_DEVICE_SC \
|
||||
IWL_DEVICE_BZ_COMMON, \
|
||||
.uhb_supported = true, \
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \
|
||||
.num_rbds = IWL_NUM_RBDS_SC_EHT, \
|
||||
.ht_params = &iwl_22000_ht_params
|
||||
|
||||
/*
|
||||
* If the device doesn't support HE, no need to have that many buffers.
|
||||
* These sizes were picked according to 8 MSDUs inside 256 A-MSDUs in an
|
||||
* This size was picked according to 8 MSDUs inside 512 A-MSDUs in an
|
||||
* A-MPDU, with additional overhead to account for processing time.
|
||||
*/
|
||||
#define IWL_NUM_RBDS_NON_HE 512
|
||||
#define IWL_NUM_RBDS_SC_HE 4096
|
||||
#define IWL_NUM_RBDS_SC_EHT (512 * 16)
|
||||
|
||||
const struct iwl_cfg_trans_params iwl_sc_trans_cfg = {
|
||||
.device_family = IWL_DEVICE_FAMILY_SC,
|
||||
|
|
@ -151,10 +164,21 @@ const char iwl_sc_name[] = "Intel(R) TBD Sc device";
|
|||
|
||||
const struct iwl_cfg iwl_cfg_sc = {
|
||||
.fw_name_mac = "sc",
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_SC,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_SC_HE,
|
||||
};
|
||||
|
||||
const char iwl_sc2_name[] = "Intel(R) TBD Sc2 device";
|
||||
|
||||
const struct iwl_cfg iwl_cfg_sc2 = {
|
||||
.fw_name_mac = "sc2",
|
||||
IWL_DEVICE_SC,
|
||||
};
|
||||
|
||||
const char iwl_sc2f_name[] = "Intel(R) TBD Sc2f device";
|
||||
|
||||
const struct iwl_cfg iwl_cfg_sc2f = {
|
||||
.fw_name_mac = "sc2f",
|
||||
IWL_DEVICE_SC,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL_SC_A_FM_B_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
|
||||
|
|
@ -164,3 +188,7 @@ MODULE_FIRMWARE(IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
|
|||
MODULE_FIRMWARE(IWL_SC_A_GF_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_SC_A_GF4_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_SC_A_WH_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_SC2_A_FM_C_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_SC2_A_WH_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_SC2F_A_FM_C_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_SC2F_A_WH_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2019-2023 Intel Corporation
|
||||
* Copyright (C) 2019-2024 Intel Corporation
|
||||
*/
|
||||
#include <linux/uuid.h>
|
||||
#include <linux/dmi.h>
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "acpi.h"
|
||||
|
|
@ -13,63 +12,22 @@
|
|||
const guid_t iwl_guid = GUID_INIT(0xF21202BF, 0x8F78, 0x4DC6,
|
||||
0xA5, 0xB3, 0x1F, 0x73,
|
||||
0x8E, 0x28, 0x5A, 0xDE);
|
||||
IWL_EXPORT_SYMBOL(iwl_guid);
|
||||
|
||||
const guid_t iwl_rfi_guid = GUID_INIT(0x7266172C, 0x220B, 0x4B29,
|
||||
0x81, 0x4F, 0x75, 0xE4,
|
||||
0xDD, 0x26, 0xB5, 0xFD);
|
||||
IWL_EXPORT_SYMBOL(iwl_rfi_guid);
|
||||
|
||||
static const struct dmi_system_id dmi_ppag_approved_list[] = {
|
||||
{ .ident = "HP",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
||||
},
|
||||
},
|
||||
{ .ident = "SAMSUNG",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"),
|
||||
},
|
||||
},
|
||||
{ .ident = "MSFT",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
|
||||
},
|
||||
},
|
||||
{ .ident = "ASUS",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
},
|
||||
},
|
||||
{ .ident = "GOOGLE-HP",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
|
||||
},
|
||||
},
|
||||
{ .ident = "GOOGLE-ASUS",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek COMPUTER INC."),
|
||||
},
|
||||
},
|
||||
{ .ident = "GOOGLE-SAMSUNG",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"),
|
||||
},
|
||||
},
|
||||
{ .ident = "DELL",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
},
|
||||
},
|
||||
{ .ident = "DELL",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
static const size_t acpi_dsm_size[DSM_FUNC_NUM_FUNCS] = {
|
||||
[DSM_FUNC_QUERY] = sizeof(u32),
|
||||
[DSM_FUNC_DISABLE_SRD] = sizeof(u8),
|
||||
[DSM_FUNC_ENABLE_INDONESIA_5G2] = sizeof(u8),
|
||||
[DSM_FUNC_ENABLE_6E] = sizeof(u32),
|
||||
[DSM_FUNC_REGULATORY_CONFIG] = sizeof(u32),
|
||||
/* Not supported in driver */
|
||||
[5] = (size_t)0,
|
||||
[DSM_FUNC_11AX_ENABLEMENT] = sizeof(u32),
|
||||
[DSM_FUNC_ENABLE_UNII4_CHAN] = sizeof(u32),
|
||||
[DSM_FUNC_ACTIVATE_CHANNEL] = sizeof(u32),
|
||||
[DSM_FUNC_FORCE_DISABLE_CHANNELS] = sizeof(u32),
|
||||
[DSM_FUNC_ENERGY_DETECTION_THRESHOLD] = sizeof(u32),
|
||||
[DSM_FUNC_RFI_CONFIG] = sizeof(u32),
|
||||
[DSM_FUNC_ENABLE_11BE] = sizeof(u32),
|
||||
};
|
||||
|
||||
static int iwl_acpi_get_handle(struct device *dev, acpi_string method,
|
||||
|
|
@ -195,46 +153,41 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* Evaluate a DSM with no arguments and a u8 return value,
|
||||
* This function receives a DSM function number, calculates its expected size
|
||||
* according to Intel BIOS spec, and fills in the value in a 32-bit field.
|
||||
* In case the expected size is smaller than 32-bit, padding will be added.
|
||||
*/
|
||||
int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func,
|
||||
const guid_t *guid, u8 *value)
|
||||
int iwl_acpi_get_dsm(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_dsm_funcs func, u32 *value)
|
||||
{
|
||||
size_t expected_size;
|
||||
u64 tmp;
|
||||
int ret;
|
||||
u64 val;
|
||||
|
||||
ret = iwl_acpi_get_dsm_integer(dev, rev, func,
|
||||
guid, &val, sizeof(u8));
|
||||
BUILD_BUG_ON(ARRAY_SIZE(acpi_dsm_size) != DSM_FUNC_NUM_FUNCS);
|
||||
|
||||
if (ret < 0)
|
||||
if (WARN_ON(func >= ARRAY_SIZE(acpi_dsm_size)))
|
||||
return -EINVAL;
|
||||
|
||||
expected_size = acpi_dsm_size[func];
|
||||
|
||||
/* Currently all ACPI DSMs are either 8-bit or 32-bit */
|
||||
if (expected_size != sizeof(u8) && expected_size != sizeof(u32))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ret = iwl_acpi_get_dsm_integer(fwrt->dev, ACPI_DSM_REV, func,
|
||||
&iwl_guid, &tmp, expected_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* cast val (u64) to be u8 */
|
||||
*value = (u8)val;
|
||||
if ((expected_size == sizeof(u8) && tmp != (u8)tmp) ||
|
||||
(expected_size == sizeof(u32) && tmp != (u32)tmp))
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"DSM value overflows the expected size, truncating\n");
|
||||
*value = (u32)tmp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_acpi_get_dsm_u8);
|
||||
|
||||
/*
|
||||
* Evaluate a DSM with no arguments and a u32 return value,
|
||||
*/
|
||||
int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func,
|
||||
const guid_t *guid, u32 *value)
|
||||
{
|
||||
int ret;
|
||||
u64 val;
|
||||
|
||||
ret = iwl_acpi_get_dsm_integer(dev, rev, func,
|
||||
guid, &val, sizeof(u32));
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* cast val (u64) to be u32 */
|
||||
*value = (u32)val;
|
||||
return 0;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_acpi_get_dsm_u32);
|
||||
|
||||
static union acpi_object *
|
||||
iwl_acpi_get_wifi_pkg_range(struct device *dev,
|
||||
|
|
@ -302,9 +255,8 @@ iwl_acpi_get_wifi_pkg(struct device *dev,
|
|||
tbl_rev);
|
||||
}
|
||||
|
||||
|
||||
int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt,
|
||||
union iwl_tas_config_cmd *cmd, int fw_ver)
|
||||
int iwl_acpi_get_tas_table(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_tas_data *tas_data)
|
||||
{
|
||||
union acpi_object *wifi_pkg, *data;
|
||||
int ret, tbl_rev, i, block_list_size, enabled;
|
||||
|
|
@ -326,22 +278,9 @@ int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt,
|
|||
ACPI_TYPE_INTEGER) {
|
||||
u32 tas_selection =
|
||||
(u32)wifi_pkg->package.elements[1].integer.value;
|
||||
u16 override_iec =
|
||||
(tas_selection & ACPI_WTAS_OVERRIDE_IEC_MSK) >> ACPI_WTAS_OVERRIDE_IEC_POS;
|
||||
u16 enabled_iec = (tas_selection & ACPI_WTAS_ENABLE_IEC_MSK) >>
|
||||
ACPI_WTAS_ENABLE_IEC_POS;
|
||||
u8 usa_tas_uhb = (tas_selection & ACPI_WTAS_USA_UHB_MSK) >> ACPI_WTAS_USA_UHB_POS;
|
||||
|
||||
|
||||
enabled = tas_selection & ACPI_WTAS_ENABLED_MSK;
|
||||
if (fw_ver <= 3) {
|
||||
cmd->v3.override_tas_iec = cpu_to_le16(override_iec);
|
||||
cmd->v3.enable_tas_iec = cpu_to_le16(enabled_iec);
|
||||
} else {
|
||||
cmd->v4.usa_tas_uhb_allowed = usa_tas_uhb;
|
||||
cmd->v4.override_tas_iec = (u8)override_iec;
|
||||
cmd->v4.enable_tas_iec = (u8)enabled_iec;
|
||||
}
|
||||
enabled = iwl_parse_tas_selection(fwrt, tas_data,
|
||||
tas_selection);
|
||||
|
||||
} else if (tbl_rev == 0 &&
|
||||
wifi_pkg->package.elements[1].type == ACPI_TYPE_INTEGER) {
|
||||
|
|
@ -360,22 +299,16 @@ int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt,
|
|||
IWL_DEBUG_RADIO(fwrt, "Reading TAS table revision %d\n", tbl_rev);
|
||||
if (wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER ||
|
||||
wifi_pkg->package.elements[2].integer.value >
|
||||
APCI_WTAS_BLACK_LIST_MAX) {
|
||||
IWL_WTAS_BLACK_LIST_MAX) {
|
||||
IWL_DEBUG_RADIO(fwrt, "TAS invalid array size %llu\n",
|
||||
wifi_pkg->package.elements[2].integer.value);
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
block_list_size = wifi_pkg->package.elements[2].integer.value;
|
||||
cmd->v4.block_list_size = cpu_to_le32(block_list_size);
|
||||
tas_data->block_list_size = cpu_to_le32(block_list_size);
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "TAS array size %u\n", block_list_size);
|
||||
if (block_list_size > APCI_WTAS_BLACK_LIST_MAX) {
|
||||
IWL_DEBUG_RADIO(fwrt, "TAS invalid array size value %u\n",
|
||||
block_list_size);
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
for (i = 0; i < block_list_size; i++) {
|
||||
u32 country;
|
||||
|
|
@ -389,7 +322,7 @@ int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt,
|
|||
}
|
||||
|
||||
country = wifi_pkg->package.elements[3 + i].integer.value;
|
||||
cmd->v4.block_list_array[i] = cpu_to_le32(country);
|
||||
tas_data->block_list_array[i] = cpu_to_le32(country);
|
||||
IWL_DEBUG_RADIO(fwrt, "TAS block list country %d\n", country);
|
||||
}
|
||||
|
||||
|
|
@ -398,19 +331,19 @@ out_free:
|
|||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_acpi_get_tas);
|
||||
|
||||
int iwl_acpi_get_mcc(struct device *dev, char *mcc)
|
||||
int iwl_acpi_get_mcc(struct iwl_fw_runtime *fwrt, char *mcc)
|
||||
{
|
||||
union acpi_object *wifi_pkg, *data;
|
||||
u32 mcc_val;
|
||||
int ret, tbl_rev;
|
||||
|
||||
data = iwl_acpi_get_object(dev, ACPI_WRDD_METHOD);
|
||||
data = iwl_acpi_get_object(fwrt->dev, ACPI_WRDD_METHOD);
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_WRDD_WIFI_DATA_SIZE,
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
|
||||
ACPI_WRDD_WIFI_DATA_SIZE,
|
||||
&tbl_rev);
|
||||
if (IS_ERR(wifi_pkg)) {
|
||||
ret = PTR_ERR(wifi_pkg);
|
||||
|
|
@ -434,46 +367,42 @@ out_free:
|
|||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_acpi_get_mcc);
|
||||
|
||||
u64 iwl_acpi_get_pwr_limit(struct device *dev)
|
||||
int iwl_acpi_get_pwr_limit(struct iwl_fw_runtime *fwrt, u64 *dflt_pwr_limit)
|
||||
{
|
||||
union acpi_object *data, *wifi_pkg;
|
||||
u64 dflt_pwr_limit;
|
||||
int tbl_rev;
|
||||
int tbl_rev, ret = -EINVAL;
|
||||
|
||||
data = iwl_acpi_get_object(dev, ACPI_SPLC_METHOD);
|
||||
if (IS_ERR(data)) {
|
||||
dflt_pwr_limit = 0;
|
||||
*dflt_pwr_limit = 0;
|
||||
data = iwl_acpi_get_object(fwrt->dev, ACPI_SPLC_METHOD);
|
||||
if (IS_ERR(data))
|
||||
goto out;
|
||||
}
|
||||
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data,
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
|
||||
ACPI_SPLC_WIFI_DATA_SIZE, &tbl_rev);
|
||||
if (IS_ERR(wifi_pkg) || tbl_rev != 0 ||
|
||||
wifi_pkg->package.elements[1].integer.value != ACPI_TYPE_INTEGER) {
|
||||
dflt_pwr_limit = 0;
|
||||
wifi_pkg->package.elements[1].integer.value != ACPI_TYPE_INTEGER)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
dflt_pwr_limit = wifi_pkg->package.elements[1].integer.value;
|
||||
*dflt_pwr_limit = wifi_pkg->package.elements[1].integer.value;
|
||||
ret = 0;
|
||||
out_free:
|
||||
kfree(data);
|
||||
out:
|
||||
return dflt_pwr_limit;
|
||||
return ret;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_acpi_get_pwr_limit);
|
||||
|
||||
int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk)
|
||||
int iwl_acpi_get_eckv(struct iwl_fw_runtime *fwrt, u32 *extl_clk)
|
||||
{
|
||||
union acpi_object *wifi_pkg, *data;
|
||||
int ret, tbl_rev;
|
||||
|
||||
data = iwl_acpi_get_object(dev, ACPI_ECKV_METHOD);
|
||||
data = iwl_acpi_get_object(fwrt->dev, ACPI_ECKV_METHOD);
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_ECKV_WIFI_DATA_SIZE,
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
|
||||
ACPI_ECKV_WIFI_DATA_SIZE,
|
||||
&tbl_rev);
|
||||
if (IS_ERR(wifi_pkg)) {
|
||||
ret = PTR_ERR(wifi_pkg);
|
||||
|
|
@ -494,11 +423,11 @@ out_free:
|
|||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_acpi_get_eckv);
|
||||
|
||||
static int iwl_sar_set_profile(union acpi_object *table,
|
||||
struct iwl_sar_profile *profile,
|
||||
bool enabled, u8 num_chains, u8 num_sub_bands)
|
||||
static int iwl_acpi_sar_set_profile(union acpi_object *table,
|
||||
struct iwl_sar_profile *profile,
|
||||
bool enabled, u8 num_chains,
|
||||
u8 num_sub_bands)
|
||||
{
|
||||
int i, j, idx = 0;
|
||||
|
||||
|
|
@ -506,8 +435,8 @@ static int iwl_sar_set_profile(union acpi_object *table,
|
|||
* The table from ACPI is flat, but we store it in a
|
||||
* structured array.
|
||||
*/
|
||||
for (i = 0; i < ACPI_SAR_NUM_CHAINS_REV2; i++) {
|
||||
for (j = 0; j < ACPI_SAR_NUM_SUB_BANDS_REV2; j++) {
|
||||
for (i = 0; i < BIOS_SAR_MAX_CHAINS_PER_PROFILE; i++) {
|
||||
for (j = 0; j < BIOS_SAR_MAX_SUB_BANDS_NUM; j++) {
|
||||
/* if we don't have the values, use the default */
|
||||
if (i >= num_chains || j >= num_sub_bands) {
|
||||
profile->chains[i].subbands[j] = 0;
|
||||
|
|
@ -530,73 +459,7 @@ static int iwl_sar_set_profile(union acpi_object *table,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt,
|
||||
__le16 *per_chain, u32 n_subbands,
|
||||
int prof_a, int prof_b)
|
||||
{
|
||||
int profs[ACPI_SAR_NUM_CHAINS_REV0] = { prof_a, prof_b };
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < ACPI_SAR_NUM_CHAINS_REV0; i++) {
|
||||
struct iwl_sar_profile *prof;
|
||||
|
||||
/* don't allow SAR to be disabled (profile 0 means disable) */
|
||||
if (profs[i] == 0)
|
||||
return -EPERM;
|
||||
|
||||
/* we are off by one, so allow up to ACPI_SAR_PROFILE_NUM */
|
||||
if (profs[i] > ACPI_SAR_PROFILE_NUM)
|
||||
return -EINVAL;
|
||||
|
||||
/* profiles go from 1 to 4, so decrement to access the array */
|
||||
prof = &fwrt->sar_profiles[profs[i] - 1];
|
||||
|
||||
/* if the profile is disabled, do nothing */
|
||||
if (!prof->enabled) {
|
||||
IWL_DEBUG_RADIO(fwrt, "SAR profile %d is disabled.\n",
|
||||
profs[i]);
|
||||
/*
|
||||
* if one of the profiles is disabled, we
|
||||
* ignore all of them and return 1 to
|
||||
* differentiate disabled from other failures.
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(fwrt,
|
||||
"SAR EWRD: chain %d profile index %d\n",
|
||||
i, profs[i]);
|
||||
IWL_DEBUG_RADIO(fwrt, " Chain[%d]:\n", i);
|
||||
for (j = 0; j < n_subbands; j++) {
|
||||
per_chain[i * n_subbands + j] =
|
||||
cpu_to_le16(prof->chains[i].subbands[j]);
|
||||
IWL_DEBUG_RADIO(fwrt, " Band[%d] = %d * .125dBm\n",
|
||||
j, prof->chains[i].subbands[j]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_sar_select_profile(struct iwl_fw_runtime *fwrt,
|
||||
__le16 *per_chain, u32 n_tables, u32 n_subbands,
|
||||
int prof_a, int prof_b)
|
||||
{
|
||||
int i, ret = 0;
|
||||
|
||||
for (i = 0; i < n_tables; i++) {
|
||||
ret = iwl_sar_fill_table(fwrt,
|
||||
&per_chain[i * n_subbands * ACPI_SAR_NUM_CHAINS_REV0],
|
||||
n_subbands, prof_a, prof_b);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_sar_select_profile);
|
||||
|
||||
int iwl_sar_get_wrds_table(struct iwl_fw_runtime *fwrt)
|
||||
int iwl_acpi_get_wrds_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
union acpi_object *wifi_pkg, *table, *data;
|
||||
int ret, tbl_rev;
|
||||
|
|
@ -613,7 +476,7 @@ int iwl_sar_get_wrds_table(struct iwl_fw_runtime *fwrt)
|
|||
&tbl_rev);
|
||||
if (!IS_ERR(wifi_pkg)) {
|
||||
if (tbl_rev != 2) {
|
||||
ret = PTR_ERR(wifi_pkg);
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
|
|
@ -629,7 +492,7 @@ int iwl_sar_get_wrds_table(struct iwl_fw_runtime *fwrt)
|
|||
&tbl_rev);
|
||||
if (!IS_ERR(wifi_pkg)) {
|
||||
if (tbl_rev != 1) {
|
||||
ret = PTR_ERR(wifi_pkg);
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
|
|
@ -645,7 +508,7 @@ int iwl_sar_get_wrds_table(struct iwl_fw_runtime *fwrt)
|
|||
&tbl_rev);
|
||||
if (!IS_ERR(wifi_pkg)) {
|
||||
if (tbl_rev != 0) {
|
||||
ret = PTR_ERR(wifi_pkg);
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
|
|
@ -675,16 +538,15 @@ read_table:
|
|||
/* The profile from WRDS is officially profile 1, but goes
|
||||
* into sar_profiles[0] (because we don't have a profile 0).
|
||||
*/
|
||||
ret = iwl_sar_set_profile(table, &fwrt->sar_profiles[0],
|
||||
flags & IWL_SAR_ENABLE_MSK,
|
||||
num_chains, num_sub_bands);
|
||||
ret = iwl_acpi_sar_set_profile(table, &fwrt->sar_profiles[0],
|
||||
flags & IWL_SAR_ENABLE_MSK,
|
||||
num_chains, num_sub_bands);
|
||||
out_free:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_sar_get_wrds_table);
|
||||
|
||||
int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt)
|
||||
int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
union acpi_object *wifi_pkg, *data;
|
||||
bool enabled;
|
||||
|
|
@ -702,7 +564,7 @@ int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt)
|
|||
&tbl_rev);
|
||||
if (!IS_ERR(wifi_pkg)) {
|
||||
if (tbl_rev != 2) {
|
||||
ret = PTR_ERR(wifi_pkg);
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
|
|
@ -718,7 +580,7 @@ int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt)
|
|||
&tbl_rev);
|
||||
if (!IS_ERR(wifi_pkg)) {
|
||||
if (tbl_rev != 1) {
|
||||
ret = PTR_ERR(wifi_pkg);
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
|
|
@ -734,7 +596,7 @@ int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt)
|
|||
&tbl_rev);
|
||||
if (!IS_ERR(wifi_pkg)) {
|
||||
if (tbl_rev != 0) {
|
||||
ret = PTR_ERR(wifi_pkg);
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
|
|
@ -762,7 +624,7 @@ read_table:
|
|||
* from index 1, so the maximum value allowed here is
|
||||
* ACPI_SAR_PROFILES_NUM - 1.
|
||||
*/
|
||||
if (n_profiles <= 0 || n_profiles >= ACPI_SAR_PROFILE_NUM) {
|
||||
if (n_profiles >= BIOS_SAR_MAX_PROFILE_NUM) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
|
@ -771,13 +633,15 @@ read_table:
|
|||
pos = 3;
|
||||
|
||||
for (i = 0; i < n_profiles; i++) {
|
||||
union acpi_object *table = &wifi_pkg->package.elements[pos];
|
||||
/* The EWRD profiles officially go from 2 to 4, but we
|
||||
* save them in sar_profiles[1-3] (because we don't
|
||||
* have profile 0). So in the array we start from 1.
|
||||
*/
|
||||
ret = iwl_sar_set_profile(&wifi_pkg->package.elements[pos],
|
||||
&fwrt->sar_profiles[i + 1], enabled,
|
||||
num_chains, num_sub_bands);
|
||||
ret = iwl_acpi_sar_set_profile(table,
|
||||
&fwrt->sar_profiles[i + 1],
|
||||
enabled, num_chains,
|
||||
num_sub_bands);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
|
|
@ -789,9 +653,8 @@ out_free:
|
|||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_sar_get_ewrd_table);
|
||||
|
||||
int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt)
|
||||
int iwl_acpi_get_wgds_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
union acpi_object *wifi_pkg, *data;
|
||||
int i, j, k, ret, tbl_rev;
|
||||
|
|
@ -806,7 +669,7 @@ int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt)
|
|||
.revisions = BIT(3),
|
||||
.bands = ACPI_GEO_NUM_BANDS_REV2,
|
||||
.profiles = ACPI_NUM_GEO_PROFILES_REV3,
|
||||
.min_profiles = 3,
|
||||
.min_profiles = BIOS_GEO_MIN_PROFILE_NUM,
|
||||
},
|
||||
{
|
||||
.revisions = BIT(2),
|
||||
|
|
@ -862,22 +725,25 @@ int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt)
|
|||
entry = &wifi_pkg->package.elements[entry_idx];
|
||||
entry_idx++;
|
||||
if (entry->type != ACPI_TYPE_INTEGER ||
|
||||
entry->integer.value > num_profiles) {
|
||||
entry->integer.value > num_profiles ||
|
||||
entry->integer.value <
|
||||
rev_data[idx].min_profiles) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
num_profiles = entry->integer.value;
|
||||
|
||||
/*
|
||||
* this also validates >= min_profiles since we
|
||||
* otherwise wouldn't have gotten the data when
|
||||
* looking up in ACPI
|
||||
* Check to see if we received package count
|
||||
* same as max # of profiles
|
||||
*/
|
||||
if (wifi_pkg->package.count !=
|
||||
hdr_size + profile_size * num_profiles) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* Number of valid profiles */
|
||||
num_profiles = entry->integer.value;
|
||||
}
|
||||
goto read_table;
|
||||
}
|
||||
|
|
@ -892,7 +758,7 @@ int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt)
|
|||
read_table:
|
||||
fwrt->geo_rev = tbl_rev;
|
||||
for (i = 0; i < num_profiles; i++) {
|
||||
for (j = 0; j < ACPI_GEO_NUM_BANDS_REV2; j++) {
|
||||
for (j = 0; j < BIOS_GEO_MAX_NUM_BANDS; j++) {
|
||||
union acpi_object *entry;
|
||||
|
||||
/*
|
||||
|
|
@ -916,7 +782,7 @@ read_table:
|
|||
entry->integer.value;
|
||||
}
|
||||
|
||||
for (k = 0; k < ACPI_GEO_NUM_CHAINS; k++) {
|
||||
for (k = 0; k < BIOS_GEO_NUM_CHAINS; k++) {
|
||||
/* same here as above */
|
||||
if (j >= num_bands) {
|
||||
fwrt->geo_profiles[i].bands[j].chains[k] =
|
||||
|
|
@ -944,123 +810,26 @@ out_free:
|
|||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_sar_get_wgds_table);
|
||||
|
||||
bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
/*
|
||||
* The PER_CHAIN_LIMIT_OFFSET_CMD command is not supported on
|
||||
* earlier firmware versions. Unfortunately, we don't have a
|
||||
* TLV API flag to rely on, so rely on the major version which
|
||||
* is in the first byte of ucode_ver. This was implemented
|
||||
* initially on version 38 and then backported to 17. It was
|
||||
* also backported to 29, but only for 7265D devices. The
|
||||
* intention was to have it in 36 as well, but not all 8000
|
||||
* family got this feature enabled. The 8000 family is the
|
||||
* only one using version 36, so skip this version entirely.
|
||||
*/
|
||||
return IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) >= 38 ||
|
||||
(IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 17 &&
|
||||
fwrt->trans->hw_rev != CSR_HW_REV_TYPE_3160) ||
|
||||
(IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 29 &&
|
||||
((fwrt->trans->hw_rev & CSR_HW_REV_TYPE_MSK) ==
|
||||
CSR_HW_REV_TYPE_7265D));
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_sar_geo_support);
|
||||
|
||||
int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_per_chain_offset *table,
|
||||
u32 n_bands, u32 n_profiles)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (!fwrt->geo_enabled)
|
||||
return -ENODATA;
|
||||
|
||||
if (!iwl_sar_geo_support(fwrt))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
for (i = 0; i < n_profiles; i++) {
|
||||
for (j = 0; j < n_bands; j++) {
|
||||
struct iwl_per_chain_offset *chain =
|
||||
&table[i * n_bands + j];
|
||||
|
||||
chain->max_tx_power =
|
||||
cpu_to_le16(fwrt->geo_profiles[i].bands[j].max);
|
||||
chain->chain_a = fwrt->geo_profiles[i].bands[j].chains[0];
|
||||
chain->chain_b = fwrt->geo_profiles[i].bands[j].chains[1];
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"SAR geographic profile[%d] Band[%d]: chain A = %d chain B = %d max_tx_power = %d\n",
|
||||
i, j,
|
||||
fwrt->geo_profiles[i].bands[j].chains[0],
|
||||
fwrt->geo_profiles[i].bands[j].chains[1],
|
||||
fwrt->geo_profiles[i].bands[j].max);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_sar_geo_init);
|
||||
|
||||
__le32 iwl_acpi_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
int ret;
|
||||
u8 value;
|
||||
__le32 config_bitmap = 0;
|
||||
|
||||
/*
|
||||
** Evaluate func 'DSM_FUNC_ENABLE_INDONESIA_5G2'
|
||||
*/
|
||||
ret = iwl_acpi_get_dsm_u8(fwrt->dev, 0,
|
||||
DSM_FUNC_ENABLE_INDONESIA_5G2,
|
||||
&iwl_guid, &value);
|
||||
|
||||
if (!ret && value == DSM_VALUE_INDONESIA_ENABLE)
|
||||
config_bitmap |=
|
||||
cpu_to_le32(LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK);
|
||||
|
||||
/*
|
||||
** Evaluate func 'DSM_FUNC_DISABLE_SRD'
|
||||
*/
|
||||
ret = iwl_acpi_get_dsm_u8(fwrt->dev, 0,
|
||||
DSM_FUNC_DISABLE_SRD,
|
||||
&iwl_guid, &value);
|
||||
if (!ret) {
|
||||
if (value == DSM_VALUE_SRD_PASSIVE)
|
||||
config_bitmap |=
|
||||
cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_PASSIVE_MSK);
|
||||
else if (value == DSM_VALUE_SRD_DISABLE)
|
||||
config_bitmap |=
|
||||
cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_DISABLED_MSK);
|
||||
}
|
||||
|
||||
return config_bitmap;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_acpi_get_lari_config_bitmap);
|
||||
|
||||
int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
union acpi_object *wifi_pkg, *data, *flags;
|
||||
int i, j, ret, tbl_rev, num_sub_bands = 0;
|
||||
int idx = 2;
|
||||
u8 cmd_ver;
|
||||
|
||||
fwrt->ppag_flags = 0;
|
||||
fwrt->ppag_table_valid = false;
|
||||
|
||||
data = iwl_acpi_get_object(fwrt->dev, ACPI_PPAG_METHOD);
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
/* try to read ppag table rev 2 or 1 (both have the same data size) */
|
||||
/* try to read ppag table rev 3, 2 or 1 (all have the same data size) */
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
|
||||
ACPI_PPAG_WIFI_DATA_SIZE_V2, &tbl_rev);
|
||||
|
||||
if (!IS_ERR(wifi_pkg)) {
|
||||
if (tbl_rev == 1 || tbl_rev == 2) {
|
||||
if (tbl_rev >= 1 && tbl_rev <= 3) {
|
||||
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"Reading PPAG table v2 (tbl_rev=%d)\n",
|
||||
"Reading PPAG table (tbl_rev=%d)\n",
|
||||
tbl_rev);
|
||||
goto read_table;
|
||||
} else {
|
||||
|
|
@ -1083,6 +852,9 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
|
|||
goto read_table;
|
||||
}
|
||||
|
||||
ret = PTR_ERR(wifi_pkg);
|
||||
goto out_free;
|
||||
|
||||
read_table:
|
||||
fwrt->ppag_ver = tbl_rev;
|
||||
flags = &wifi_pkg->package.elements[1];
|
||||
|
|
@ -1092,19 +864,8 @@ read_table:
|
|||
goto out_free;
|
||||
}
|
||||
|
||||
fwrt->ppag_flags = flags->integer.value & ACPI_PPAG_MASK;
|
||||
cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
|
||||
WIDE_ID(PHY_OPS_GROUP,
|
||||
PER_PLATFORM_ANT_GAIN_CMD),
|
||||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
if (cmd_ver == IWL_FW_CMD_VER_UNKNOWN) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
if (!fwrt->ppag_flags && cmd_ver <= 3) {
|
||||
ret = 0;
|
||||
goto out_free;
|
||||
}
|
||||
fwrt->ppag_flags = iwl_bios_get_ppag_flags(flags->integer.value,
|
||||
fwrt->ppag_ver);
|
||||
|
||||
/*
|
||||
* read, verify gain values and save them into the PPAG table.
|
||||
|
|
@ -1122,132 +883,15 @@ read_table:
|
|||
}
|
||||
|
||||
fwrt->ppag_chains[i].subbands[j] = ent->integer.value;
|
||||
/* from ver 4 the fw deals with out of range values */
|
||||
if (cmd_ver >= 4)
|
||||
continue;
|
||||
if ((j == 0 &&
|
||||
(fwrt->ppag_chains[i].subbands[j] > ACPI_PPAG_MAX_LB ||
|
||||
fwrt->ppag_chains[i].subbands[j] < ACPI_PPAG_MIN_LB)) ||
|
||||
(j != 0 &&
|
||||
(fwrt->ppag_chains[i].subbands[j] > ACPI_PPAG_MAX_HB ||
|
||||
fwrt->ppag_chains[i].subbands[j] < ACPI_PPAG_MIN_HB))) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fwrt->ppag_table_valid = true;
|
||||
ret = 0;
|
||||
|
||||
out_free:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_acpi_get_ppag_table);
|
||||
|
||||
int iwl_read_ppag_table(struct iwl_fw_runtime *fwrt, union iwl_ppag_table_cmd *cmd,
|
||||
int *cmd_size)
|
||||
{
|
||||
u8 cmd_ver;
|
||||
int i, j, num_sub_bands;
|
||||
s8 *gain;
|
||||
|
||||
/* many firmware images for JF lie about this */
|
||||
if (CSR_HW_RFID_TYPE(fwrt->trans->hw_rf_id) ==
|
||||
CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_JF))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!fw_has_capa(&fwrt->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_PPAG)) {
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"PPAG capability not supported by FW, command not sent.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
|
||||
WIDE_ID(PHY_OPS_GROUP,
|
||||
PER_PLATFORM_ANT_GAIN_CMD),
|
||||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
if (!fwrt->ppag_table_valid || (cmd_ver <= 3 && !fwrt->ppag_flags)) {
|
||||
IWL_DEBUG_RADIO(fwrt, "PPAG not enabled, command not sent.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* The 'flags' field is the same in v1 and in v2 so we can just
|
||||
* use v1 to access it.
|
||||
*/
|
||||
cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags);
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "PPAG cmd ver is %d\n", cmd_ver);
|
||||
if (cmd_ver == 1) {
|
||||
num_sub_bands = IWL_NUM_SUB_BANDS_V1;
|
||||
gain = cmd->v1.gain[0];
|
||||
*cmd_size = sizeof(cmd->v1);
|
||||
if (fwrt->ppag_ver == 1 || fwrt->ppag_ver == 2) {
|
||||
/* in this case FW supports revision 0 */
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"PPAG table rev is %d, send truncated table\n",
|
||||
fwrt->ppag_ver);
|
||||
}
|
||||
} else if (cmd_ver >= 2 && cmd_ver <= 4) {
|
||||
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
|
||||
gain = cmd->v2.gain[0];
|
||||
*cmd_size = sizeof(cmd->v2);
|
||||
if (fwrt->ppag_ver == 0) {
|
||||
/* in this case FW supports revisions 1 or 2 */
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"PPAG table rev is 0, send padded table\n");
|
||||
}
|
||||
} else {
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported PPAG command version\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* ppag mode */
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"PPAG MODE bits were read from bios: %d\n",
|
||||
cmd->v1.flags & cpu_to_le32(ACPI_PPAG_MASK));
|
||||
if ((cmd_ver == 1 && !fw_has_capa(&fwrt->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) ||
|
||||
(cmd_ver == 2 && fwrt->ppag_ver == 2)) {
|
||||
cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK);
|
||||
IWL_DEBUG_RADIO(fwrt, "masking ppag China bit\n");
|
||||
} else {
|
||||
IWL_DEBUG_RADIO(fwrt, "isn't masking ppag China bit\n");
|
||||
}
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"PPAG MODE bits going to be sent: %d\n",
|
||||
cmd->v1.flags & cpu_to_le32(ACPI_PPAG_MASK));
|
||||
|
||||
for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {
|
||||
for (j = 0; j < num_sub_bands; j++) {
|
||||
gain[i * num_sub_bands + j] =
|
||||
fwrt->ppag_chains[i].subbands[j];
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"PPAG table: chain[%d] band[%d]: gain = %d\n",
|
||||
i, j, gain[i * num_sub_bands + j]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_read_ppag_table);
|
||||
|
||||
bool iwl_acpi_is_ppag_approved(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
|
||||
if (!dmi_check_system(dmi_ppag_approved_list)) {
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"System vendor '%s' is not in the approved list, disabling PPAG.\n",
|
||||
dmi_get_system_info(DMI_SYS_VENDOR));
|
||||
fwrt->ppag_flags = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_acpi_is_ppag_approved);
|
||||
|
||||
void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_phy_specific_cfg *filters)
|
||||
|
|
@ -1260,7 +904,6 @@ void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
|
|||
if (IS_ERR(data))
|
||||
return;
|
||||
|
||||
/* try to read wtas table revision 1 or revision 0*/
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
|
||||
ACPI_WPFC_WIFI_DATA_SIZE,
|
||||
&tbl_rev);
|
||||
|
|
@ -1270,13 +913,14 @@ void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
|
|||
if (tbl_rev != 0)
|
||||
goto out_free;
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(filters->filter_cfg_chains) != ACPI_WPFC_WIFI_DATA_SIZE);
|
||||
BUILD_BUG_ON(ARRAY_SIZE(filters->filter_cfg_chains) !=
|
||||
ACPI_WPFC_WIFI_DATA_SIZE - 1);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(filters->filter_cfg_chains); i++) {
|
||||
if (wifi_pkg->package.elements[i].type != ACPI_TYPE_INTEGER)
|
||||
return;
|
||||
if (wifi_pkg->package.elements[i + 1].type != ACPI_TYPE_INTEGER)
|
||||
goto out_free;
|
||||
tmp.filter_cfg_chains[i] =
|
||||
cpu_to_le32(wifi_pkg->package.elements[i].integer.value);
|
||||
cpu_to_le32(wifi_pkg->package.elements[i + 1].integer.value);
|
||||
}
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "Loaded WPFC filter config from ACPI\n");
|
||||
|
|
@ -1285,3 +929,72 @@ out_free:
|
|||
kfree(data);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_acpi_get_phy_filters);
|
||||
|
||||
void iwl_acpi_get_guid_lock_status(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
union acpi_object *wifi_pkg, *data;
|
||||
int tbl_rev;
|
||||
|
||||
data = iwl_acpi_get_object(fwrt->dev, ACPI_GLAI_METHOD);
|
||||
if (IS_ERR(data))
|
||||
return;
|
||||
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
|
||||
ACPI_GLAI_WIFI_DATA_SIZE,
|
||||
&tbl_rev);
|
||||
if (IS_ERR(wifi_pkg))
|
||||
goto out_free;
|
||||
|
||||
if (tbl_rev != 0) {
|
||||
IWL_DEBUG_RADIO(fwrt, "Invalid GLAI revision: %d\n", tbl_rev);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER ||
|
||||
wifi_pkg->package.elements[1].integer.value > ACPI_GLAI_MAX_STATUS)
|
||||
goto out_free;
|
||||
|
||||
fwrt->uefi_tables_lock_status =
|
||||
wifi_pkg->package.elements[1].integer.value;
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"Loaded UEFI WIFI GUID lock status: %d from ACPI\n",
|
||||
fwrt->uefi_tables_lock_status);
|
||||
out_free:
|
||||
kfree(data);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_acpi_get_guid_lock_status);
|
||||
|
||||
int iwl_acpi_get_wbem(struct iwl_fw_runtime *fwrt, u32 *value)
|
||||
{
|
||||
union acpi_object *wifi_pkg, *data;
|
||||
int ret = -ENOENT;
|
||||
int tbl_rev;
|
||||
|
||||
data = iwl_acpi_get_object(fwrt->dev, ACPI_WBEM_METHOD);
|
||||
if (IS_ERR(data))
|
||||
return ret;
|
||||
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
|
||||
ACPI_WBEM_WIFI_DATA_SIZE,
|
||||
&tbl_rev);
|
||||
if (IS_ERR(wifi_pkg))
|
||||
goto out_free;
|
||||
|
||||
if (tbl_rev != IWL_ACPI_WBEM_REVISION) {
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported ACPI WBEM revision:%d\n",
|
||||
tbl_rev);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER)
|
||||
goto out_free;
|
||||
|
||||
*value = wifi_pkg->package.elements[1].integer.value &
|
||||
IWL_ACPI_WBEM_REV0_MASK;
|
||||
IWL_DEBUG_RADIO(fwrt, "Loaded WBEM config from ACPI\n");
|
||||
ret = 0;
|
||||
out_free:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#define __iwl_fw_acpi__
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include "fw/regulatory.h"
|
||||
#include "fw/api/commands.h"
|
||||
#include "fw/api/power.h"
|
||||
#include "fw/api/phy.h"
|
||||
|
|
@ -25,6 +26,8 @@
|
|||
#define ACPI_PPAG_METHOD "PPAG"
|
||||
#define ACPI_WTAS_METHOD "WTAS"
|
||||
#define ACPI_WPFC_METHOD "WPFC"
|
||||
#define ACPI_GLAI_METHOD "GLAI"
|
||||
#define ACPI_WBEM_METHOD "WBEM"
|
||||
|
||||
#define ACPI_WIFI_DOMAIN (0x07)
|
||||
|
||||
|
|
@ -56,181 +59,100 @@
|
|||
#define ACPI_EWRD_WIFI_DATA_SIZE_REV2 ((ACPI_SAR_PROFILE_NUM - 1) * \
|
||||
ACPI_SAR_NUM_CHAINS_REV2 * \
|
||||
ACPI_SAR_NUM_SUB_BANDS_REV2 + 3)
|
||||
#define ACPI_WPFC_WIFI_DATA_SIZE 4 /* 4 filter config words */
|
||||
#define ACPI_WPFC_WIFI_DATA_SIZE 5 /* domain and 4 filter config words */
|
||||
|
||||
/* revision 0 and 1 are identical, except for the semantics in the FW */
|
||||
#define ACPI_GEO_NUM_BANDS_REV0 2
|
||||
#define ACPI_GEO_NUM_BANDS_REV2 3
|
||||
#define ACPI_GEO_NUM_CHAINS 2
|
||||
|
||||
#define ACPI_WRDD_WIFI_DATA_SIZE 2
|
||||
#define ACPI_SPLC_WIFI_DATA_SIZE 2
|
||||
#define ACPI_ECKV_WIFI_DATA_SIZE 2
|
||||
|
||||
/*
|
||||
* One element for domain type,
|
||||
* and one for enablement of Wi-Fi 320MHz per MCC
|
||||
*/
|
||||
#define ACPI_WBEM_WIFI_DATA_SIZE 2
|
||||
/*
|
||||
* One element for domain type,
|
||||
* and one for the status
|
||||
*/
|
||||
#define ACPI_GLAI_WIFI_DATA_SIZE 2
|
||||
#define ACPI_GLAI_MAX_STATUS 2
|
||||
/*
|
||||
* TAS size: 1 elelment for type,
|
||||
* 1 element for enabled field,
|
||||
* 1 element for block list size,
|
||||
* 16 elements for block list array
|
||||
*/
|
||||
#define APCI_WTAS_BLACK_LIST_MAX 16
|
||||
#define ACPI_WTAS_WIFI_DATA_SIZE (3 + APCI_WTAS_BLACK_LIST_MAX)
|
||||
#define ACPI_WTAS_ENABLED_MSK 0x1
|
||||
#define ACPI_WTAS_OVERRIDE_IEC_MSK 0x2
|
||||
#define ACPI_WTAS_ENABLE_IEC_MSK 0x4
|
||||
#define ACPI_WTAS_OVERRIDE_IEC_POS 0x1
|
||||
#define ACPI_WTAS_ENABLE_IEC_POS 0x2
|
||||
#define ACPI_WTAS_USA_UHB_MSK BIT(16)
|
||||
#define ACPI_WTAS_USA_UHB_POS 16
|
||||
|
||||
#define ACPI_WTAS_WIFI_DATA_SIZE (3 + IWL_WTAS_BLACK_LIST_MAX)
|
||||
|
||||
#define ACPI_PPAG_WIFI_DATA_SIZE_V1 ((IWL_NUM_CHAIN_LIMITS * \
|
||||
IWL_NUM_SUB_BANDS_V1) + 2)
|
||||
#define ACPI_PPAG_WIFI_DATA_SIZE_V2 ((IWL_NUM_CHAIN_LIMITS * \
|
||||
IWL_NUM_SUB_BANDS_V2) + 2)
|
||||
|
||||
/* PPAG gain value bounds in 1/8 dBm */
|
||||
#define ACPI_PPAG_MIN_LB -16
|
||||
#define ACPI_PPAG_MAX_LB 24
|
||||
#define ACPI_PPAG_MIN_HB -16
|
||||
#define ACPI_PPAG_MAX_HB 40
|
||||
#define ACPI_PPAG_MASK 3
|
||||
#define IWL_PPAG_ETSI_MASK BIT(0)
|
||||
|
||||
#define IWL_SAR_ENABLE_MSK BIT(0)
|
||||
#define IWL_REDUCE_POWER_FLAGS_POS 1
|
||||
|
||||
/*
|
||||
* The profile for revision 2 is a superset of revision 1, which is in
|
||||
* turn a superset of revision 0. So we can store all revisions
|
||||
* inside revision 2, which is what we represent here.
|
||||
*/
|
||||
struct iwl_sar_profile_chain {
|
||||
u8 subbands[ACPI_SAR_NUM_SUB_BANDS_REV2];
|
||||
};
|
||||
/* The Inidcator whether UEFI WIFI GUID tables are locked is read from ACPI */
|
||||
#define UEFI_WIFI_GUID_UNLOCKED 0
|
||||
|
||||
struct iwl_sar_profile {
|
||||
bool enabled;
|
||||
struct iwl_sar_profile_chain chains[ACPI_SAR_NUM_CHAINS_REV2];
|
||||
};
|
||||
#define ACPI_DSM_REV 0
|
||||
|
||||
/* Same thing as with SAR, all revisions fit in revision 2 */
|
||||
struct iwl_geo_profile_band {
|
||||
u8 max;
|
||||
u8 chains[ACPI_GEO_NUM_CHAINS];
|
||||
};
|
||||
|
||||
struct iwl_geo_profile {
|
||||
struct iwl_geo_profile_band bands[ACPI_GEO_NUM_BANDS_REV2];
|
||||
};
|
||||
|
||||
/* Same thing as with SAR, all revisions fit in revision 2 */
|
||||
struct iwl_ppag_chain {
|
||||
s8 subbands[ACPI_SAR_NUM_SUB_BANDS_REV2];
|
||||
};
|
||||
|
||||
enum iwl_dsm_funcs_rev_0 {
|
||||
DSM_FUNC_QUERY = 0,
|
||||
DSM_FUNC_DISABLE_SRD = 1,
|
||||
DSM_FUNC_ENABLE_INDONESIA_5G2 = 2,
|
||||
DSM_FUNC_ENABLE_6E = 3,
|
||||
DSM_FUNC_11AX_ENABLEMENT = 6,
|
||||
DSM_FUNC_ENABLE_UNII4_CHAN = 7,
|
||||
DSM_FUNC_ACTIVATE_CHANNEL = 8,
|
||||
DSM_FUNC_FORCE_DISABLE_CHANNELS = 9
|
||||
};
|
||||
|
||||
enum iwl_dsm_values_srd {
|
||||
DSM_VALUE_SRD_ACTIVE,
|
||||
DSM_VALUE_SRD_PASSIVE,
|
||||
DSM_VALUE_SRD_DISABLE,
|
||||
DSM_VALUE_SRD_MAX
|
||||
};
|
||||
|
||||
enum iwl_dsm_values_indonesia {
|
||||
DSM_VALUE_INDONESIA_DISABLE,
|
||||
DSM_VALUE_INDONESIA_ENABLE,
|
||||
DSM_VALUE_INDONESIA_RESERVED,
|
||||
DSM_VALUE_INDONESIA_MAX
|
||||
};
|
||||
|
||||
/* DSM RFI uses a different GUID, so need separate definitions */
|
||||
|
||||
#define DSM_RFI_FUNC_ENABLE 3
|
||||
|
||||
enum iwl_dsm_values_rfi {
|
||||
DSM_VALUE_RFI_ENABLE,
|
||||
DSM_VALUE_RFI_DISABLE,
|
||||
DSM_VALUE_RFI_MAX
|
||||
};
|
||||
#define IWL_ACPI_WBEM_REV0_MASK (BIT(0) | BIT(1))
|
||||
#define IWL_ACPI_WBEM_REVISION 0
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
|
||||
struct iwl_fw_runtime;
|
||||
|
||||
extern const guid_t iwl_guid;
|
||||
extern const guid_t iwl_rfi_guid;
|
||||
|
||||
int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func,
|
||||
const guid_t *guid, u8 *value);
|
||||
|
||||
int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func,
|
||||
const guid_t *guid, u32 *value);
|
||||
|
||||
/**
|
||||
* iwl_acpi_get_mcc - read MCC from ACPI, if available
|
||||
*
|
||||
* @dev: the struct device
|
||||
* @fwrt: the fw runtime struct
|
||||
* @mcc: output buffer (3 bytes) that will get the MCC
|
||||
*
|
||||
* This function tries to read the current MCC from ACPI if available.
|
||||
*/
|
||||
int iwl_acpi_get_mcc(struct device *dev, char *mcc);
|
||||
int iwl_acpi_get_mcc(struct iwl_fw_runtime *fwrt, char *mcc);
|
||||
|
||||
u64 iwl_acpi_get_pwr_limit(struct device *dev);
|
||||
int iwl_acpi_get_pwr_limit(struct iwl_fw_runtime *fwrt, u64 *dflt_pwr_limit);
|
||||
|
||||
/*
|
||||
* iwl_acpi_get_eckv - read external clock validation from ACPI, if available
|
||||
*
|
||||
* @dev: the struct device
|
||||
* @fwrt: the fw runtime struct
|
||||
* @extl_clk: output var (2 bytes) that will get the clk indication.
|
||||
*
|
||||
* This function tries to read the external clock indication
|
||||
* from ACPI if available.
|
||||
*/
|
||||
int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk);
|
||||
int iwl_acpi_get_eckv(struct iwl_fw_runtime *fwrt, u32 *extl_clk);
|
||||
|
||||
int iwl_sar_select_profile(struct iwl_fw_runtime *fwrt,
|
||||
__le16 *per_chain, u32 n_tables, u32 n_subbands,
|
||||
int prof_a, int prof_b);
|
||||
int iwl_acpi_get_wrds_table(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
int iwl_sar_get_wrds_table(struct iwl_fw_runtime *fwrt);
|
||||
int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt);
|
||||
int iwl_acpi_get_wgds_table(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_per_chain_offset *table,
|
||||
u32 n_bands, u32 n_profiles);
|
||||
|
||||
int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt,
|
||||
union iwl_tas_config_cmd *cmd, int fw_ver);
|
||||
|
||||
__le32 iwl_acpi_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt);
|
||||
int iwl_acpi_get_tas_table(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_tas_data *data);
|
||||
|
||||
int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
int iwl_read_ppag_table(struct iwl_fw_runtime *fwrt, union iwl_ppag_table_cmd *cmd,
|
||||
int *cmd_size);
|
||||
|
||||
bool iwl_acpi_is_ppag_approved(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_phy_specific_cfg *filters);
|
||||
|
||||
void iwl_acpi_get_guid_lock_status(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
int iwl_acpi_get_dsm(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_dsm_funcs func, u32 *value);
|
||||
|
||||
int iwl_acpi_get_wbem(struct iwl_fw_runtime *fwrt, u32 *value);
|
||||
#else /* CONFIG_ACPI */
|
||||
|
||||
static inline void *iwl_acpi_get_dsm_object(struct device *dev, int rev,
|
||||
|
|
@ -239,92 +161,66 @@ static inline void *iwl_acpi_get_dsm_object(struct device *dev, int rev,
|
|||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
||||
static inline int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func,
|
||||
const guid_t *guid, u8 *value)
|
||||
static inline int iwl_acpi_get_mcc(struct iwl_fw_runtime *fwrt, char *mcc)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func,
|
||||
const guid_t *guid, u32 *value)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_acpi_get_mcc(struct device *dev, char *mcc)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline u64 iwl_acpi_get_pwr_limit(struct device *dev)
|
||||
static inline int iwl_acpi_get_pwr_limit(struct iwl_fw_runtime *fwrt,
|
||||
u64 *dflt_pwr_limit)
|
||||
{
|
||||
*dflt_pwr_limit = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk)
|
||||
static inline int iwl_acpi_get_eckv(struct iwl_fw_runtime *fwrt, u32 *extl_clk)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_sar_select_profile(struct iwl_fw_runtime *fwrt,
|
||||
__le16 *per_chain, u32 n_tables, u32 n_subbands,
|
||||
int prof_a, int prof_b)
|
||||
static inline int iwl_acpi_get_wrds_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_sar_get_wrds_table(struct iwl_fw_runtime *fwrt)
|
||||
static inline int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt)
|
||||
static inline int iwl_acpi_get_wgds_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt,
|
||||
union iwl_tas_config_cmd *cmd, int fw_ver)
|
||||
static inline int iwl_acpi_get_tas_table(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_tas_data *data)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline __le32 iwl_acpi_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_read_ppag_table(struct iwl_fw_runtime *fwrt,
|
||||
union iwl_ppag_table_cmd *cmd, int *cmd_size)
|
||||
/* macro since the second argument doesn't always exist */
|
||||
#define iwl_acpi_get_phy_filters(fwrt, filters) do { } while (0)
|
||||
|
||||
static inline void iwl_acpi_get_guid_lock_status(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int iwl_acpi_get_dsm(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_dsm_funcs func, u32 *value)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline bool iwl_acpi_is_ppag_approved(struct iwl_fw_runtime *fwrt)
|
||||
static inline int iwl_acpi_get_wbem(struct iwl_fw_runtime *fwrt, u32 *value)
|
||||
{
|
||||
return false;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_phy_specific_cfg *filters)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
#endif /* __iwl_fw_acpi__ */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018, 2020-2021 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018, 2020-2021, 2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -113,7 +113,7 @@ struct iwl_alive_ntf_v6 {
|
|||
} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_6 */
|
||||
|
||||
/**
|
||||
* enum iwl_extended_cfg_flag - commands driver may send before
|
||||
* enum iwl_extended_cfg_flags - commands driver may send before
|
||||
* finishing init flow
|
||||
* @IWL_INIT_DEBUG_CFG: driver is going to send debug config command
|
||||
* @IWL_INIT_NVM: driver is going to send NVM_ACCESS commands
|
||||
|
|
@ -126,7 +126,7 @@ enum iwl_extended_cfg_flags {
|
|||
};
|
||||
|
||||
/**
|
||||
* struct iwl_extended_cfg_cmd - mark what commands ucode should wait for
|
||||
* struct iwl_init_extended_cfg_cmd - mark what commands ucode should wait for
|
||||
* before finishing init flows
|
||||
* @init_flags: values from iwl_extended_cfg_flags
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2020, 2022 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2020, 2022, 2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -77,7 +77,7 @@ struct iwl_time_quota_data_v1 {
|
|||
} __packed; /* TIME_QUOTA_DATA_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_time_quota_cmd - configuration of time quota between bindings
|
||||
* struct iwl_time_quota_cmd_v1 - configuration of time quota between bindings
|
||||
* ( TIME_QUOTA_CMD = 0x2c )
|
||||
* @quotas: allocations per binding
|
||||
* Note: on non-CDB the fourth one is the auxilary mac and is
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2023-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2014, 2018-2019 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2017 Intel Deutschland GmbH
|
||||
|
|
@ -76,73 +77,6 @@ struct iwl_bt_coex_ci_cmd {
|
|||
__le32 secondary_ch_phy_id;
|
||||
} __packed; /* BT_CI_MSG_API_S_VER_2 */
|
||||
|
||||
#define BT_MBOX(n_dw, _msg, _pos, _nbits) \
|
||||
BT_MBOX##n_dw##_##_msg##_POS = (_pos), \
|
||||
BT_MBOX##n_dw##_##_msg = BITS(_nbits) << BT_MBOX##n_dw##_##_msg##_POS
|
||||
|
||||
enum iwl_bt_mxbox_dw0 {
|
||||
BT_MBOX(0, LE_SLAVE_LAT, 0, 3),
|
||||
BT_MBOX(0, LE_PROF1, 3, 1),
|
||||
BT_MBOX(0, LE_PROF2, 4, 1),
|
||||
BT_MBOX(0, LE_PROF_OTHER, 5, 1),
|
||||
BT_MBOX(0, CHL_SEQ_N, 8, 4),
|
||||
BT_MBOX(0, INBAND_S, 13, 1),
|
||||
BT_MBOX(0, LE_MIN_RSSI, 16, 4),
|
||||
BT_MBOX(0, LE_SCAN, 20, 1),
|
||||
BT_MBOX(0, LE_ADV, 21, 1),
|
||||
BT_MBOX(0, LE_MAX_TX_POWER, 24, 4),
|
||||
BT_MBOX(0, OPEN_CON_1, 28, 2),
|
||||
};
|
||||
|
||||
enum iwl_bt_mxbox_dw1 {
|
||||
BT_MBOX(1, BR_MAX_TX_POWER, 0, 4),
|
||||
BT_MBOX(1, IP_SR, 4, 1),
|
||||
BT_MBOX(1, LE_MSTR, 5, 1),
|
||||
BT_MBOX(1, AGGR_TRFC_LD, 8, 6),
|
||||
BT_MBOX(1, MSG_TYPE, 16, 3),
|
||||
BT_MBOX(1, SSN, 19, 2),
|
||||
};
|
||||
|
||||
enum iwl_bt_mxbox_dw2 {
|
||||
BT_MBOX(2, SNIFF_ACT, 0, 3),
|
||||
BT_MBOX(2, PAG, 3, 1),
|
||||
BT_MBOX(2, INQUIRY, 4, 1),
|
||||
BT_MBOX(2, CONN, 5, 1),
|
||||
BT_MBOX(2, SNIFF_INTERVAL, 8, 5),
|
||||
BT_MBOX(2, DISC, 13, 1),
|
||||
BT_MBOX(2, SCO_TX_ACT, 16, 2),
|
||||
BT_MBOX(2, SCO_RX_ACT, 18, 2),
|
||||
BT_MBOX(2, ESCO_RE_TX, 20, 2),
|
||||
BT_MBOX(2, SCO_DURATION, 24, 6),
|
||||
};
|
||||
|
||||
enum iwl_bt_mxbox_dw3 {
|
||||
BT_MBOX(3, SCO_STATE, 0, 1),
|
||||
BT_MBOX(3, SNIFF_STATE, 1, 1),
|
||||
BT_MBOX(3, A2DP_STATE, 2, 1),
|
||||
BT_MBOX(3, ACL_STATE, 3, 1),
|
||||
BT_MBOX(3, MSTR_STATE, 4, 1),
|
||||
BT_MBOX(3, OBX_STATE, 5, 1),
|
||||
BT_MBOX(3, A2DP_SRC, 6, 1),
|
||||
BT_MBOX(3, OPEN_CON_2, 8, 2),
|
||||
BT_MBOX(3, TRAFFIC_LOAD, 10, 2),
|
||||
BT_MBOX(3, CHL_SEQN_LSB, 12, 1),
|
||||
BT_MBOX(3, INBAND_P, 13, 1),
|
||||
BT_MBOX(3, MSG_TYPE_2, 16, 3),
|
||||
BT_MBOX(3, SSN_2, 19, 2),
|
||||
BT_MBOX(3, UPDATE_REQUEST, 21, 1),
|
||||
};
|
||||
|
||||
#define BT_MBOX_MSG(_notif, _num, _field) \
|
||||
((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\
|
||||
>> BT_MBOX##_num##_##_field##_POS)
|
||||
|
||||
#define BT_MBOX_PRINT(_num, _field, _end) \
|
||||
pos += scnprintf(buf + pos, bufsz - pos, \
|
||||
"\t%s: %d%s", \
|
||||
#_field, \
|
||||
BT_MBOX_MSG(notif, _num, _field), \
|
||||
true ? "\n" : ", ")
|
||||
enum iwl_bt_activity_grading {
|
||||
BT_OFF = 0,
|
||||
BT_ON_NO_CONNECTION = 1,
|
||||
|
|
@ -170,7 +104,11 @@ enum iwl_bt_ci_compliance {
|
|||
* @bt_activity_grading: the activity of BT &enum iwl_bt_activity_grading
|
||||
* @ttc_status: is TTC enabled - one bit per PHY
|
||||
* @rrc_status: is RRC enabled - one bit per PHY
|
||||
* @reserved: reserved
|
||||
* The following fields are only for version 5, and are reserved in version 4:
|
||||
* @wifi_loss_low_rssi: The predicted lost WiFi rate (% of air time that BT is
|
||||
* utilizing) when the RSSI is low (<= -65 dBm)
|
||||
* @wifi_loss_mid_high_rssi: The predicted lost WiFi rate (% of air time that
|
||||
* BT is utilizing) when the RSSI is mid/high (>= -65 dBm)
|
||||
*/
|
||||
struct iwl_bt_coex_profile_notif {
|
||||
__le32 mbox_msg[4];
|
||||
|
|
@ -182,7 +120,10 @@ struct iwl_bt_coex_profile_notif {
|
|||
__le32 bt_activity_grading;
|
||||
u8 ttc_status;
|
||||
u8 rrc_status;
|
||||
__le16 reserved;
|
||||
} __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_4 */
|
||||
u8 wifi_loss_low_rssi;
|
||||
u8 wifi_loss_mid_high_rssi;
|
||||
} __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_4
|
||||
* BT_COEX_PROFILE_NTFY_API_S_VER_5
|
||||
*/
|
||||
|
||||
#endif /* __iwl_fw_api_coex_h__ */
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@
|
|||
* @REGULATORY_AND_NVM_GROUP: regulatory/NVM group, uses command IDs from
|
||||
* &enum iwl_regulatory_and_nvm_subcmd_ids
|
||||
* @DEBUG_GROUP: Debug group, uses command IDs from &enum iwl_debug_cmds
|
||||
* @STATISTICS_GROUP: Statistics group, uses command IDs from
|
||||
* &enum iwl_statistics_subcmd_ids
|
||||
*/
|
||||
enum iwl_mvm_command_groups {
|
||||
LEGACY_GROUP = 0x0,
|
||||
|
|
@ -44,6 +46,7 @@ enum iwl_mvm_command_groups {
|
|||
PROT_OFFLOAD_GROUP = 0xb,
|
||||
REGULATORY_AND_NVM_GROUP = 0xc,
|
||||
DEBUG_GROUP = 0xf,
|
||||
STATISTICS_GROUP = 0x10,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -616,10 +619,37 @@ enum iwl_system_subcmd_ids {
|
|||
*/
|
||||
SYSTEM_FEATURES_CONTROL_CMD = 0xd,
|
||||
|
||||
/**
|
||||
* @SYSTEM_STATISTICS_CMD: &struct iwl_system_statistics_cmd
|
||||
*/
|
||||
SYSTEM_STATISTICS_CMD = 0xf,
|
||||
|
||||
/**
|
||||
* @SYSTEM_STATISTICS_END_NOTIF: &struct iwl_system_statistics_end_notif
|
||||
*/
|
||||
SYSTEM_STATISTICS_END_NOTIF = 0xfd,
|
||||
|
||||
/**
|
||||
* @RFI_DEACTIVATE_NOTIF: &struct iwl_rfi_deactivate_notif
|
||||
*/
|
||||
RFI_DEACTIVATE_NOTIF = 0xff,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_statistics_subcmd_ids - Statistics group command IDs
|
||||
*/
|
||||
enum iwl_statistics_subcmd_ids {
|
||||
/**
|
||||
* @STATISTICS_OPER_NOTIF: Notification about operational
|
||||
* statistics &struct iwl_system_statistics_notif_oper
|
||||
*/
|
||||
STATISTICS_OPER_NOTIF = 0x0,
|
||||
|
||||
/**
|
||||
* @STATISTICS_OPER_PART1_NOTIF: Notification about operational part1
|
||||
* statistics &struct iwl_system_statistics_part1_notif_oper
|
||||
*/
|
||||
STATISTICS_OPER_PART1_NOTIF = 0x1,
|
||||
};
|
||||
|
||||
#endif /* __iwl_fw_api_commands_h__ */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2019, 2023 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2019, 2023-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -76,7 +76,7 @@ struct iwl_phy_specific_cfg {
|
|||
} __packed; /* PHY_SPECIFIC_CONFIGURATION_API_VER_1*/
|
||||
|
||||
/**
|
||||
* struct iwl_phy_cfg_cmd - Phy configuration command
|
||||
* struct iwl_phy_cfg_cmd_v1 - Phy configuration command
|
||||
*
|
||||
* @phy_cfg: PHY configuration value, uses &enum iwl_fw_phy_cfg
|
||||
* @calib_control: calibration control data
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -42,7 +42,7 @@ struct iwl_d3_manager_config {
|
|||
/* TODO: OFFLOADS_QUERY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_d3_proto_offloads - enabled protocol offloads
|
||||
* enum iwl_proto_offloads - enabled protocol offloads
|
||||
* @IWL_D3_PROTO_OFFLOAD_ARP: ARP data is enabled
|
||||
* @IWL_D3_PROTO_OFFLOAD_NS: NS (Neighbor Solicitation) is enabled
|
||||
* @IWL_D3_PROTO_IPV4_VALID: IPv4 data is valid
|
||||
|
|
@ -195,7 +195,7 @@ struct iwl_wowlan_pattern_v1 {
|
|||
#define IWL_WOWLAN_MAX_PATTERNS 20
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_patterns_cmd - WoWLAN wakeup patterns
|
||||
* struct iwl_wowlan_patterns_cmd_v1 - WoWLAN wakeup patterns
|
||||
*/
|
||||
struct iwl_wowlan_patterns_cmd_v1 {
|
||||
/**
|
||||
|
|
@ -324,7 +324,7 @@ struct iwl_wowlan_patterns_cmd {
|
|||
u8 n_patterns;
|
||||
|
||||
/**
|
||||
* @n_patterns: sta_id
|
||||
* @sta_id: sta_id
|
||||
*/
|
||||
u8 sta_id;
|
||||
|
||||
|
|
@ -397,6 +397,8 @@ struct iwl_wowlan_config_cmd {
|
|||
#define WOWLAN_GTK_KEYS_NUM 2
|
||||
#define WOWLAN_IGTK_KEYS_NUM 2
|
||||
#define WOWLAN_IGTK_MIN_INDEX 4
|
||||
#define WOWLAN_BIGTK_KEYS_NUM 2
|
||||
#define WOWLAN_BIGTK_MIN_INDEX 6
|
||||
|
||||
/*
|
||||
* WOWLAN_TSC_RSC_PARAMS
|
||||
|
|
@ -621,9 +623,10 @@ struct iwl_wowlan_gtk_status_v3 {
|
|||
* @ipn: the IGTK packet number (replay counter)
|
||||
* @key_len: IGTK length, if set to 0, the key is not available
|
||||
* @key_flags: information about the key:
|
||||
* bits[0]: key index assigned by the AP (0: index 4, 1: index 5)
|
||||
* bits[1:5]: IGTK index of the key in the internal DB
|
||||
* bit[6]: Set iff this is the currently used IGTK
|
||||
* bits[0]: key index assigned by the AP (0: index 4, 1: index 5)
|
||||
* (0: index 6, 1: index 7 with bigtk)
|
||||
* bits[1:5]: IGTK index of the key in the internal DB
|
||||
* bit[6]: Set iff this is the currently used IGTK
|
||||
*/
|
||||
struct iwl_wowlan_igtk_status {
|
||||
u8 key[WOWLAN_KEY_MAX_SIZE];
|
||||
|
|
@ -808,7 +811,7 @@ struct iwl_wowlan_info_notif_v1 {
|
|||
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_info_notif - WoWLAN information notification
|
||||
* struct iwl_wowlan_info_notif_v2 - WoWLAN information notification
|
||||
* @gtk: GTK data
|
||||
* @igtk: IGTK data
|
||||
* @replay_ctr: GTK rekey replay counter
|
||||
|
|
@ -824,7 +827,7 @@ struct iwl_wowlan_info_notif_v1 {
|
|||
* @station_id: station id
|
||||
* @reserved2: reserved
|
||||
*/
|
||||
struct iwl_wowlan_info_notif {
|
||||
struct iwl_wowlan_info_notif_v2 {
|
||||
struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
|
||||
struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
|
||||
__le64 replay_ctr;
|
||||
|
|
@ -840,6 +843,92 @@ struct iwl_wowlan_info_notif {
|
|||
u8 reserved2[2];
|
||||
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_2 */
|
||||
|
||||
/* MAX MLO keys of non-active links that can arrive in the notification */
|
||||
#define WOWLAN_MAX_MLO_KEYS 18
|
||||
|
||||
/**
|
||||
* enum iwl_wowlan_mlo_gtk_type - GTK types
|
||||
* @WOWLAN_MLO_GTK_KEY_TYPE_GTK: GTK
|
||||
* @WOWLAN_MLO_GTK_KEY_TYPE_IGTK: IGTK
|
||||
* @WOWLAN_MLO_GTK_KEY_TYPE_BIGTK: BIGTK
|
||||
* @WOWLAN_MLO_GTK_KEY_NUM_TYPES: number of key types
|
||||
*/
|
||||
enum iwl_wowlan_mlo_gtk_type {
|
||||
WOWLAN_MLO_GTK_KEY_TYPE_GTK,
|
||||
WOWLAN_MLO_GTK_KEY_TYPE_IGTK,
|
||||
WOWLAN_MLO_GTK_KEY_TYPE_BIGTK,
|
||||
WOWLAN_MLO_GTK_KEY_NUM_TYPES
|
||||
}; /* WOWLAN_MLO_GTK_KEY_TYPE_API_E_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_wowlan_mlo_gtk_flag - MLO GTK flags
|
||||
* @WOWLAN_MLO_GTK_FLAG_KEY_LEN_MSK: 0 for len 16, 1 for len 32
|
||||
* @WOWLAN_MLO_GTK_FLAG_KEY_ID_MSK: key id (ranges from 0 to 7)
|
||||
* @WOWLAN_MLO_GTK_FLAG_LINK_ID_MSK: spec link id of the key
|
||||
* @WOWLAN_MLO_GTK_FLAG_KEY_TYPE_MSK: &enum iwl_wowlan_mlo_gtk_type
|
||||
* @WOWLAN_MLO_GTK_FLAG_LAST_KEY_MSK: is this the last given key per
|
||||
* key-type / link-id - the currently used key
|
||||
*/
|
||||
enum iwl_wowlan_mlo_gtk_flag {
|
||||
WOWLAN_MLO_GTK_FLAG_KEY_LEN_MSK = 0x0001,
|
||||
WOWLAN_MLO_GTK_FLAG_KEY_ID_MSK = 0x000E,
|
||||
WOWLAN_MLO_GTK_FLAG_LINK_ID_MSK = 0x00F0,
|
||||
WOWLAN_MLO_GTK_FLAG_KEY_TYPE_MSK = 0x0300,
|
||||
WOWLAN_MLO_GTK_FLAG_LAST_KEY_MSK = 0x0400
|
||||
}; /* WOWLAN_MLO_GTK_FLAG_API_E_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_mlo_gtk - MLO GTK info
|
||||
* @key: key material
|
||||
* @flags: &enum iwl_wowlan_mlo_gtk_flag
|
||||
* @pn: packet number
|
||||
*/
|
||||
struct iwl_wowlan_mlo_gtk {
|
||||
u8 key[WOWLAN_KEY_MAX_SIZE];
|
||||
__le16 flags;
|
||||
u8 pn[6];
|
||||
} __packed; /* WOWLAN_MLO_GTK_KEY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_info_notif - WoWLAN information notification
|
||||
* @gtk: GTK data
|
||||
* @igtk: IGTK data
|
||||
* @bigtk: BIGTK data
|
||||
* @replay_ctr: GTK rekey replay counter
|
||||
* @pattern_number: number of the matched patterns
|
||||
* @reserved1: reserved
|
||||
* @qos_seq_ctr: QoS sequence counters to use next
|
||||
* @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason
|
||||
* @num_of_gtk_rekeys: number of GTK rekeys
|
||||
* @transmitted_ndps: number of transmitted neighbor discovery packets
|
||||
* @received_beacons: number of received beacons
|
||||
* @tid_tear_down: bit mask of tids whose BA sessions were closed
|
||||
* in suspend state
|
||||
* @station_id: station id
|
||||
* @num_mlo_link_keys: number of &struct iwl_wowlan_mlo_gtk structs
|
||||
* following this notif, or reserved in version < 4
|
||||
* @reserved2: reserved
|
||||
* @mlo_gtks: array of GTKs of size num_mlo_link_keys for version >= 4
|
||||
*/
|
||||
struct iwl_wowlan_info_notif {
|
||||
struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
|
||||
struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
|
||||
struct iwl_wowlan_igtk_status bigtk[WOWLAN_BIGTK_KEYS_NUM];
|
||||
__le64 replay_ctr;
|
||||
__le16 pattern_number;
|
||||
__le16 reserved1;
|
||||
__le16 qos_seq_ctr[8];
|
||||
__le32 wakeup_reasons;
|
||||
__le32 num_of_gtk_rekeys;
|
||||
__le32 transmitted_ndps;
|
||||
__le32 received_beacons;
|
||||
u8 tid_tear_down;
|
||||
u8 station_id;
|
||||
u8 num_mlo_link_keys;
|
||||
u8 reserved2;
|
||||
struct iwl_wowlan_mlo_gtk mlo_gtks[];
|
||||
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_3, _VER_4 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_wake_pkt_notif - WoWLAN wake packet notification
|
||||
* @wake_packet_length: wakeup packet length
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
|
|
@ -89,6 +90,12 @@ enum iwl_data_path_subcmd_ids {
|
|||
*/
|
||||
SEC_KEY_CMD = 0x18,
|
||||
|
||||
/**
|
||||
* @ESR_MODE_NOTIF: notification to recommend/force a wanted esr mode,
|
||||
* uses &struct iwl_mvm_esr_mode_notif
|
||||
*/
|
||||
ESR_MODE_NOTIF = 0xF3,
|
||||
|
||||
/**
|
||||
* @MONITOR_NOTIF: Datapath monitoring notification, using
|
||||
* &struct iwl_datapath_monitor_notif
|
||||
|
|
@ -101,7 +108,7 @@ enum iwl_data_path_subcmd_ids {
|
|||
RX_NO_DATA_NOTIF = 0xF5,
|
||||
|
||||
/**
|
||||
* @THERMAL_DUAL_CHAIN_DISABLE_REQ: firmware request for SMPS mode,
|
||||
* @THERMAL_DUAL_CHAIN_REQUEST: firmware request for SMPS mode,
|
||||
* &struct iwl_thermal_dual_chain_request
|
||||
*/
|
||||
THERMAL_DUAL_CHAIN_REQUEST = 0xF6,
|
||||
|
|
@ -224,28 +231,33 @@ struct iwl_synced_time_rsp {
|
|||
#define PTP_CTX_MAX_DATA_SIZE 128
|
||||
|
||||
/**
|
||||
* struct iwl_time_msmt_ptp_ctx - Vendor specific information element
|
||||
* struct iwl_time_msmt_ptp_ctx - Vendor specific element
|
||||
* to allow a space for flexibility for the userspace App
|
||||
*
|
||||
* @element_id: element id of vendor specific ie
|
||||
* @length: length of vendor specific ie
|
||||
* @reserved: for alignment
|
||||
* @data: vendor specific data blob
|
||||
* @ftm: FTM specific vendor element
|
||||
* @ftm.element_id: element id of vendor specific ie
|
||||
* @ftm.length: length of vendor specific ie
|
||||
* @ftm.reserved: for alignment
|
||||
* @ftm.data: vendor specific data blob
|
||||
* @tm: TM specific vendor element
|
||||
* @tm.element_id: element id of vendor specific ie
|
||||
* @tm.length: length of vendor specific ie
|
||||
* @tm.data: vendor specific data blob
|
||||
*/
|
||||
struct iwl_time_msmt_ptp_ctx {
|
||||
/* Differentiate between FTM and TM specific Vendor IEs */
|
||||
/* Differentiate between FTM and TM specific Vendor elements */
|
||||
union {
|
||||
struct {
|
||||
u8 element_id;
|
||||
u8 length;
|
||||
__le16 reserved;
|
||||
u8 data[PTP_CTX_MAX_DATA_SIZE];
|
||||
} ftm; /* FTM specific vendor IE */
|
||||
} ftm;
|
||||
struct {
|
||||
u8 element_id;
|
||||
u8 length;
|
||||
u8 data[PTP_CTX_MAX_DATA_SIZE];
|
||||
} tm; /* TM specific vendor IE */
|
||||
} tm;
|
||||
};
|
||||
} __packed /* PTP_CTX_VER_1 */;
|
||||
|
||||
|
|
@ -524,6 +536,10 @@ struct iwl_rx_baid_cfg_cmd_remove {
|
|||
/**
|
||||
* struct iwl_rx_baid_cfg_cmd - BAID allocation/config command
|
||||
* @action: the action, from &enum iwl_rx_baid_action
|
||||
* @alloc: allocation data
|
||||
* @modify: modify data
|
||||
* @remove_v1: remove data (version 1)
|
||||
* @remove: remove data
|
||||
*/
|
||||
struct iwl_rx_baid_cfg_cmd {
|
||||
__le32 action;
|
||||
|
|
@ -558,6 +574,7 @@ enum iwl_scd_queue_cfg_operation {
|
|||
/**
|
||||
* struct iwl_scd_queue_cfg_cmd - scheduler queue allocation command
|
||||
* @operation: the operation, see &enum iwl_scd_queue_cfg_operation
|
||||
* @u: union depending on command usage
|
||||
* @u.add.sta_mask: station mask
|
||||
* @u.add.tid: TID
|
||||
* @u.add.reserved: reserved
|
||||
|
|
@ -627,6 +644,7 @@ enum iwl_sec_key_flags {
|
|||
/**
|
||||
* struct iwl_sec_key_cmd - security key command
|
||||
* @action: action from &enum iwl_ctxt_action
|
||||
* @u: union depending on command type
|
||||
* @u.add.sta_mask: station mask for the new key
|
||||
* @u.add.key_id: key ID (0-7) for the new key
|
||||
* @u.add.key_flags: key flags per &enum iwl_sec_key_flags
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2018-2024 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_fw_dbg_tlv_h__
|
||||
#define __iwl_fw_dbg_tlv_h__
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
#define IWL_FW_INI_DOMAIN_ALWAYS_ON 0
|
||||
#define IWL_FW_INI_REGION_ID_MASK GENMASK(15, 0)
|
||||
#define IWL_FW_INI_REGION_DUMP_POLICY_MASK GENMASK(31, 16)
|
||||
#define IWL_FW_INI_PRESET_DISABLE 0xff
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_hcmd
|
||||
|
|
@ -41,6 +42,30 @@ struct iwl_fw_ini_header {
|
|||
/* followed by the data */
|
||||
} __packed; /* FW_TLV_DEBUG_HEADER_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_addr_size - Base address and size that defines
|
||||
* a chunk of memory
|
||||
*
|
||||
* @addr: the base address (fixed size - 4 bytes)
|
||||
* @size: the size to read
|
||||
*/
|
||||
struct iwl_fw_ini_addr_size {
|
||||
__le32 addr;
|
||||
__le32 size;
|
||||
} __packed; /* FW_TLV_DEBUG_ADDR_SIZE_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_region_dev_addr_range - Configuration to read
|
||||
* device address range
|
||||
*
|
||||
* @offset: offset to add to the base address of each chunk
|
||||
* The addrs[] array will be treated as an array of &iwl_fw_ini_addr_size -
|
||||
* an array of (addr, size) pairs.
|
||||
*/
|
||||
struct iwl_fw_ini_region_dev_addr_range {
|
||||
__le32 offset;
|
||||
} __packed; /* FW_TLV_DEBUG_DEVICE_ADDR_RANGE_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_region_dev_addr - Configuration to read device addresses
|
||||
*
|
||||
|
|
@ -122,28 +147,34 @@ struct iwl_fw_ini_region_internal_buffer {
|
|||
* Configures parameters for region data collection
|
||||
*
|
||||
* @hdr: debug header
|
||||
* @id: region id. Max id is &IWL_FW_INI_MAX_REGION_ID
|
||||
* @id: region id. Max id is %IWL_FW_INI_MAX_REGION_ID
|
||||
* @type: region type. One of &enum iwl_fw_ini_region_type
|
||||
* @sub_type: region sub type
|
||||
* @sub_type_ver: region sub type version
|
||||
* @reserved: not in use
|
||||
* @name: region name
|
||||
* @dev_addr: device address configuration. Used by
|
||||
* &IWL_FW_INI_REGION_DEVICE_MEMORY, &IWL_FW_INI_REGION_PERIPHERY_MAC,
|
||||
* &IWL_FW_INI_REGION_PERIPHERY_PHY, &IWL_FW_INI_REGION_PERIPHERY_AUX,
|
||||
* &IWL_FW_INI_REGION_PAGING, &IWL_FW_INI_REGION_CSR,
|
||||
* &IWL_FW_INI_REGION_DRAM_IMR and &IWL_FW_INI_REGION_PCI_IOSF_CONFIG
|
||||
* &IWL_FW_INI_REGION_DBGI_SRAM, &FW_TLV_DEBUG_REGION_TYPE_DBGI_SRAM,
|
||||
* @fifos: fifos configuration. Used by &IWL_FW_INI_REGION_TXF and
|
||||
* &IWL_FW_INI_REGION_RXF
|
||||
* %IWL_FW_INI_REGION_DEVICE_MEMORY, %IWL_FW_INI_REGION_PERIPHERY_MAC,
|
||||
* %IWL_FW_INI_REGION_PERIPHERY_PHY, %IWL_FW_INI_REGION_PERIPHERY_AUX,
|
||||
* %IWL_FW_INI_REGION_PAGING, %IWL_FW_INI_REGION_CSR,
|
||||
* %IWL_FW_INI_REGION_DRAM_IMR and %IWL_FW_INI_REGION_PCI_IOSF_CONFIG
|
||||
* %IWL_FW_INI_REGION_DBGI_SRAM, %FW_TLV_DEBUG_REGION_TYPE_DBGI_SRAM,
|
||||
* %IWL_FW_INI_REGION_PERIPHERY_SNPS_DPHYIP,
|
||||
* @dev_addr_range: device address range configuration. Used by
|
||||
* %IWL_FW_INI_REGION_PERIPHERY_MAC_RANGE and
|
||||
* %IWL_FW_INI_REGION_PERIPHERY_PHY_RANGE
|
||||
* @fifos: fifos configuration. Used by %IWL_FW_INI_REGION_TXF and
|
||||
* %IWL_FW_INI_REGION_RXF
|
||||
* @err_table: error table configuration. Used by
|
||||
* IWL_FW_INI_REGION_LMAC_ERROR_TABLE and
|
||||
* IWL_FW_INI_REGION_UMAC_ERROR_TABLE
|
||||
* %IWL_FW_INI_REGION_LMAC_ERROR_TABLE and
|
||||
* %IWL_FW_INI_REGION_UMAC_ERROR_TABLE
|
||||
* @internal_buffer: internal monitor buffer configuration. Used by
|
||||
* &IWL_FW_INI_REGION_INTERNAL_BUFFER
|
||||
* %IWL_FW_INI_REGION_INTERNAL_BUFFER
|
||||
* @special_mem: special device memory region, used by
|
||||
* %IWL_FW_INI_REGION_SPECIAL_DEVICE_MEMORY
|
||||
* @dram_alloc_id: dram allocation id. One of &enum iwl_fw_ini_allocation_id.
|
||||
* Used by &IWL_FW_INI_REGION_DRAM_BUFFER
|
||||
* @tlv_mask: tlv collection mask. Used by &IWL_FW_INI_REGION_TLV
|
||||
* Used by %IWL_FW_INI_REGION_DRAM_BUFFER
|
||||
* @tlv_mask: tlv collection mask. Used by %IWL_FW_INI_REGION_TLV
|
||||
* @addrs: array of addresses attached to the end of the region tlv
|
||||
*/
|
||||
struct iwl_fw_ini_region_tlv {
|
||||
|
|
@ -156,6 +187,7 @@ struct iwl_fw_ini_region_tlv {
|
|||
u8 name[IWL_FW_INI_MAX_NAME];
|
||||
union {
|
||||
struct iwl_fw_ini_region_dev_addr dev_addr;
|
||||
struct iwl_fw_ini_region_dev_addr_range dev_addr_range;
|
||||
struct iwl_fw_ini_region_fifos fifos;
|
||||
struct iwl_fw_ini_region_err_table err_table;
|
||||
struct iwl_fw_ini_region_internal_buffer internal_buffer;
|
||||
|
|
@ -261,7 +293,7 @@ struct iwl_fw_ini_addr_val {
|
|||
} __packed; /* FW_TLV_DEBUG_ADDR_VALUE_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_conf_tlv - configuration TLV to set register/memory.
|
||||
* struct iwl_fw_ini_conf_set_tlv - configuration TLV to set register/memory.
|
||||
*
|
||||
* @hdr: debug header
|
||||
* @time_point: time point to apply config. One of &enum iwl_fw_ini_time_point
|
||||
|
|
@ -289,7 +321,7 @@ struct iwl_fw_ini_conf_set_tlv {
|
|||
* @IWL_FW_INI_CONFIG_SET_TYPE_CSR: for CSR configuration
|
||||
* @IWL_FW_INI_CONFIG_SET_TYPE_DBGC_DRAM_ADDR: for DBGC_DRAM_ADDR configuration
|
||||
* @IWL_FW_INI_CONFIG_SET_TYPE_PERIPH_SCRATCH_HWM: for PERIPH SCRATCH HWM configuration
|
||||
* @IWL_FW_INI_ALLOCATION_NUM: max number of configuration supported
|
||||
* @IWL_FW_INI_CONFIG_SET_TYPE_MAX_NUM: max number of configuration supported
|
||||
*/
|
||||
|
||||
enum iwl_fw_ini_config_set_type {
|
||||
|
|
@ -330,6 +362,7 @@ enum iwl_fw_ini_allocation_id {
|
|||
* @IWL_FW_INI_LOCATION_SRAM_PATH: SRAM location
|
||||
* @IWL_FW_INI_LOCATION_DRAM_PATH: DRAM location
|
||||
* @IWL_FW_INI_LOCATION_NPK_PATH: NPK location
|
||||
* @IWL_FW_INI_LOCATION_NUM: number of valid locations
|
||||
*/
|
||||
enum iwl_fw_ini_buffer_location {
|
||||
IWL_FW_INI_LOCATION_INVALID,
|
||||
|
|
@ -361,6 +394,9 @@ enum iwl_fw_ini_buffer_location {
|
|||
* @IWL_FW_INI_REGION_PCI_IOSF_CONFIG: PCI/IOSF config
|
||||
* @IWL_FW_INI_REGION_SPECIAL_DEVICE_MEMORY: special device memory
|
||||
* @IWL_FW_INI_REGION_DBGI_SRAM: periphery registers of DBGI SRAM
|
||||
* @IWL_FW_INI_REGION_PERIPHERY_MAC_RANGE: a range of periphery registers of MAC
|
||||
* @IWL_FW_INI_REGION_PERIPHERY_PHY_RANGE: a range of periphery registers of PHY
|
||||
* @IWL_FW_INI_REGION_PERIPHERY_SNPS_DPHYIP: periphery registers of SNPS DPHYIP
|
||||
* @IWL_FW_INI_REGION_NUM: number of region types
|
||||
*/
|
||||
enum iwl_fw_ini_region_type {
|
||||
|
|
@ -383,6 +419,9 @@ enum iwl_fw_ini_region_type {
|
|||
IWL_FW_INI_REGION_PCI_IOSF_CONFIG,
|
||||
IWL_FW_INI_REGION_SPECIAL_DEVICE_MEMORY,
|
||||
IWL_FW_INI_REGION_DBGI_SRAM,
|
||||
IWL_FW_INI_REGION_PERIPHERY_MAC_RANGE,
|
||||
IWL_FW_INI_REGION_PERIPHERY_PHY_RANGE,
|
||||
IWL_FW_INI_REGION_PERIPHERY_SNPS_DPHYIP,
|
||||
IWL_FW_INI_REGION_NUM
|
||||
}; /* FW_TLV_DEBUG_REGION_TYPE_API_E */
|
||||
|
||||
|
|
@ -403,6 +442,7 @@ enum iwl_fw_ini_region_device_memory_subtype {
|
|||
* Hard coded time points in which the driver can send hcmd or perform dump
|
||||
* collection
|
||||
*
|
||||
* @IWL_FW_INI_TIME_POINT_INVALID: invalid timepoint
|
||||
* @IWL_FW_INI_TIME_POINT_EARLY: pre loading the FW
|
||||
* @IWL_FW_INI_TIME_POINT_AFTER_ALIVE: first cmd from host after alive notif
|
||||
* @IWL_FW_INI_TIME_POINT_POST_INIT: last cmd in series of init sequence
|
||||
|
|
@ -432,6 +472,10 @@ enum iwl_fw_ini_region_device_memory_subtype {
|
|||
* @IWL_FW_INI_TIME_POINT_EAPOL_FAILED: EAPOL failed
|
||||
* @IWL_FW_INI_TIME_POINT_FAKE_TX: fake Tx
|
||||
* @IWL_FW_INI_TIME_POINT_DEASSOC: de association
|
||||
* @IWL_FW_INI_TIME_POINT_PRESET_OVERRIDE_EXT_REQ: request to override preset
|
||||
* @IWL_FW_INI_TIME_POINT_PRESET_OVERRIDE_START: start handling override preset
|
||||
* request
|
||||
* @IWL_FW_INI_TIME_SCAN_FAILURE: failed scan channel list
|
||||
* @IWL_FW_INI_TIME_POINT_NUM: number of time points
|
||||
*/
|
||||
enum iwl_fw_ini_time_point {
|
||||
|
|
@ -462,6 +506,9 @@ enum iwl_fw_ini_time_point {
|
|||
IWL_FW_INI_TIME_POINT_EAPOL_FAILED,
|
||||
IWL_FW_INI_TIME_POINT_FAKE_TX,
|
||||
IWL_FW_INI_TIME_POINT_DEASSOC,
|
||||
IWL_FW_INI_TIME_POINT_PRESET_OVERRIDE_EXT_REQ,
|
||||
IWL_FW_INI_TIME_POINT_PRESET_OVERRIDE_START,
|
||||
IWL_FW_INI_TIME_SCAN_FAILURE,
|
||||
IWL_FW_INI_TIME_POINT_NUM,
|
||||
}; /* FW_TLV_DEBUG_TIME_POINT_API_E */
|
||||
|
||||
|
|
@ -517,7 +564,7 @@ enum iwl_fw_ini_dump_policy {
|
|||
* enum iwl_fw_ini_dump_type - Determines dump type based on size defined by FW.
|
||||
*
|
||||
* @IWL_FW_INI_DUMP_BRIEF : only dump the most important regions
|
||||
* @IWL_FW_INI_DEBUG_MEDIUM: dump more regions than "brief", but not all regions
|
||||
* @IWL_FW_INI_DUMP_MEDIUM: dump more regions than "brief", but not all regions
|
||||
* @IWL_FW_INI_DUMP_VERBOSE : dump all regions
|
||||
*/
|
||||
enum iwl_fw_ini_dump_type {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
#ifndef __iwl_fw_api_debug_h__
|
||||
#define __iwl_fw_api_debug_h__
|
||||
#include "dbg-tlv.h"
|
||||
|
||||
/**
|
||||
* enum iwl_debug_cmds - debug commands
|
||||
|
|
@ -29,6 +30,11 @@ enum iwl_debug_cmds {
|
|||
* &struct iwl_dbg_host_event_cfg_cmd
|
||||
*/
|
||||
HOST_EVENT_CFG = 0x3,
|
||||
/**
|
||||
* @INVALID_WR_PTR_CMD: invalid write pointer, set in the TFD
|
||||
* when it's not in use
|
||||
*/
|
||||
INVALID_WR_PTR_CMD = 0x6,
|
||||
/**
|
||||
* @DBGC_SUSPEND_RESUME:
|
||||
* DBGC suspend/resume commad. Uses a single dword as data:
|
||||
|
|
@ -54,6 +60,12 @@ enum iwl_debug_cmds {
|
|||
* &struct iwl_dbg_dump_complete_cmd
|
||||
*/
|
||||
FW_DUMP_COMPLETE_CMD = 0xB,
|
||||
/**
|
||||
* @FW_CLEAR_BUFFER:
|
||||
* clears the firmware's internal buffer
|
||||
* no payload
|
||||
*/
|
||||
FW_CLEAR_BUFFER = 0xD,
|
||||
/**
|
||||
* @MFU_ASSERT_DUMP_NTF:
|
||||
* &struct iwl_mfu_assert_dump_notif
|
||||
|
|
@ -377,13 +389,13 @@ struct iwl_buf_alloc_cmd {
|
|||
#define DRAM_INFO_SECOND_MAGIC_WORD 0x89ABCDEF
|
||||
|
||||
/**
|
||||
* struct iwL_dram_info - DRAM fragments allocation struct
|
||||
* struct iwl_dram_info - DRAM fragments allocation struct
|
||||
*
|
||||
* Driver will fill in the first 1K(+) of the pointed DRAM fragment
|
||||
*
|
||||
* @first_word: magic word value
|
||||
* @second_word: magic word value
|
||||
* @framfrags: DRAM fragmentaion detail
|
||||
* @dram_frags: DRAM fragmentaion detail
|
||||
*/
|
||||
struct iwl_dram_info {
|
||||
__le32 first_word;
|
||||
|
|
@ -517,4 +529,26 @@ enum iwl_mvm_tas_statically_disabled_reason {
|
|||
TAS_DISABLED_REASON_MAX,
|
||||
}; /*_TAS_STATICALLY_DISABLED_REASON_E*/
|
||||
|
||||
/**
|
||||
* enum iwl_fw_dbg_config_cmd_type - types of FW debug config command
|
||||
* @DEBUG_TOKEN_CONFIG_TYPE: token config type
|
||||
*/
|
||||
enum iwl_fw_dbg_config_cmd_type {
|
||||
DEBUG_TOKEN_CONFIG_TYPE = 0x2B,
|
||||
}; /* LDBG_CFG_CMD_TYPE_API_E_VER_1 */
|
||||
|
||||
/* this token disables debug asserts in the firmware */
|
||||
#define IWL_FW_DBG_CONFIG_TOKEN 0x00010001
|
||||
|
||||
/**
|
||||
* struct iwl_fw_dbg_config_cmd - configure FW debug
|
||||
*
|
||||
* @type: according to &enum iwl_fw_dbg_config_cmd_type
|
||||
* @conf: FW configuration
|
||||
*/
|
||||
struct iwl_fw_dbg_config_cmd {
|
||||
__le32 type;
|
||||
__le32 conf;
|
||||
} __packed; /* LDBG_CFG_CMD_API_S_VER_7 */
|
||||
|
||||
#endif /* __iwl_fw_api_debug_h__ */
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2024 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_fw_api_location_h__
|
||||
#define __iwl_fw_api_location_h__
|
||||
|
|
@ -390,10 +391,62 @@ struct iwl_tof_responder_config_cmd_v9 {
|
|||
__le16 max_time_between_msr;
|
||||
} __packed; /* TOF_RESPONDER_CONFIG_CMD_API_S_VER_8 */
|
||||
|
||||
/**
|
||||
* struct iwl_tof_responder_config_cmd - ToF AP mode
|
||||
* @cmd_valid_fields: &iwl_tof_responder_cmd_valid_field
|
||||
* @responder_cfg_flags: &iwl_tof_responder_cfg_flags
|
||||
* @format_bw: bits 0 - 3: &enum iwl_location_frame_format.
|
||||
* bits 4 - 7: &enum iwl_location_bw.
|
||||
* @bss_color: current AP bss_color
|
||||
* @channel_num: current AP Channel
|
||||
* @ctrl_ch_position: coding of the control channel position relative to
|
||||
* the center frequency, see iwl_mvm_get_ctrl_pos()
|
||||
* @sta_id: index of the AP STA when in AP mode
|
||||
* @band: current AP band
|
||||
* @toa_offset: Artificial addition [pSec] for the ToA - to be used for debug
|
||||
* purposes, simulating station movement by adding various values
|
||||
* to this field
|
||||
* @common_calib: XVT: common calibration value
|
||||
* @specific_calib: XVT: specific calibration value
|
||||
* @bssid: Current AP BSSID
|
||||
* @r2i_ndp_params: parameters for R2I NDP.
|
||||
* bits 0 - 2: max number of LTF repetitions
|
||||
* bits 3 - 5: max number of spatial streams (supported values are < 2)
|
||||
* bits 6 - 7: max number of total LTFs see
|
||||
* &enum ieee80211_range_params_max_total_ltf
|
||||
* @i2r_ndp_params: parameters for I2R NDP.
|
||||
* bits 0 - 2: max number of LTF repetitions
|
||||
* bits 3 - 5: max number of spatial streams
|
||||
* bits 6 - 7: max number of total LTFs see
|
||||
* &enum ieee80211_range_params_max_total_ltf
|
||||
* @min_time_between_msr: for non trigger based NDP ranging, minimum time
|
||||
* between measurements in milliseconds.
|
||||
* @max_time_between_msr: for non trigger based NDP ranging, maximum time
|
||||
* between measurements in milliseconds.
|
||||
*/
|
||||
struct iwl_tof_responder_config_cmd {
|
||||
__le32 cmd_valid_fields;
|
||||
__le32 responder_cfg_flags;
|
||||
u8 format_bw;
|
||||
u8 bss_color;
|
||||
u8 channel_num;
|
||||
u8 ctrl_ch_position;
|
||||
u8 sta_id;
|
||||
u8 band;
|
||||
__le16 toa_offset;
|
||||
__le16 common_calib;
|
||||
__le16 specific_calib;
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 r2i_ndp_params;
|
||||
u8 i2r_ndp_params;
|
||||
__le16 min_time_between_msr;
|
||||
__le16 max_time_between_msr;
|
||||
} __packed; /* TOF_RESPONDER_CONFIG_CMD_API_S_VER_10 */
|
||||
|
||||
#define IWL_LCI_CIVIC_IE_MAX_SIZE 400
|
||||
|
||||
/**
|
||||
* struct iwl_tof_responder_dyn_config_cmd - Dynamic responder settings
|
||||
* struct iwl_tof_responder_dyn_config_cmd_v2 - Dynamic responder settings
|
||||
* @lci_len: The length of the 1st (LCI) part in the @lci_civic buffer
|
||||
* @civic_len: The length of the 2nd (CIVIC) part in the @lci_civic buffer
|
||||
* @lci_civic: The LCI/CIVIC buffer. LCI data (if exists) comes first, then, if
|
||||
|
|
@ -561,6 +614,8 @@ struct iwl_tof_range_req_ap_entry_v2 {
|
|||
* the responder asked for LMR feedback although the initiator did not set
|
||||
* the LMR feedback bit in the FTM request. If not set, the initiator will
|
||||
* continue with the session and will provide the LMR feedback.
|
||||
* @IWL_INITIATOR_AP_FLAGS_TEST_INCORRECT_SAC: send an incorrect SAC in the
|
||||
* first NDP exchange. This is used for testing.
|
||||
*/
|
||||
enum iwl_initiator_ap_flags {
|
||||
IWL_INITIATOR_AP_FLAGS_ASAP = BIT(1),
|
||||
|
|
@ -577,6 +632,7 @@ enum iwl_initiator_ap_flags {
|
|||
IWL_INITIATOR_AP_FLAGS_USE_CALIB = BIT(13),
|
||||
IWL_INITIATOR_AP_FLAGS_PMF = BIT(14),
|
||||
IWL_INITIATOR_AP_FLAGS_TERMINATE_ON_LMR_FEEDBACK = BIT(15),
|
||||
IWL_INITIATOR_AP_FLAGS_TEST_INCORRECT_SAC = BIT(16),
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -630,6 +686,7 @@ enum iwl_location_frame_format {
|
|||
* @IWL_LOCATION_BW_20MHZ: 20MHz
|
||||
* @IWL_LOCATION_BW_40MHZ: 40MHz
|
||||
* @IWL_LOCATION_BW_80MHZ: 80MHz
|
||||
* @IWL_LOCATION_BW_160MHZ: 160MHz
|
||||
*/
|
||||
enum iwl_location_bw {
|
||||
IWL_LOCATION_BW_20MHZ,
|
||||
|
|
@ -796,6 +853,7 @@ struct iwl_tof_range_req_ap_entry_v7 {
|
|||
} __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_7 */
|
||||
|
||||
#define IWL_LOCATION_MAX_STS_POS 3
|
||||
#define IWL_LOCATION_TOTAL_LTF_POS 6
|
||||
|
||||
/**
|
||||
* struct iwl_tof_range_req_ap_entry_v8 - AP configuration parameters
|
||||
|
|
@ -952,6 +1010,78 @@ struct iwl_tof_range_req_ap_entry_v9 {
|
|||
__le16 min_time_between_msr;
|
||||
} __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_9 */
|
||||
|
||||
/**
|
||||
* struct iwl_tof_range_req_ap_entry_v10 - AP configuration parameters
|
||||
* @initiator_ap_flags: see &enum iwl_initiator_ap_flags.
|
||||
* @band: 0 for 5.2 GHz, 1 for 2.4 GHz, 2 for 6GHz
|
||||
* @channel_num: AP Channel number
|
||||
* @format_bw: bits 0 - 3: &enum iwl_location_frame_format.
|
||||
* bits 4 - 7: &enum iwl_location_bw.
|
||||
* @ctrl_ch_position: Coding of the control channel position relative to the
|
||||
* center frequency, see iwl_mvm_get_ctrl_pos().
|
||||
* @bssid: AP's BSSID
|
||||
* @burst_period: For EDCA based ranging: Recommended value to be sent to the
|
||||
* AP. Measurement periodicity In units of 100ms. ignored if
|
||||
* num_of_bursts_exp = 0.
|
||||
* For non trigger based NDP ranging, the maximum time between
|
||||
* measurements in units of milliseconds.
|
||||
* @samples_per_burst: the number of FTMs pairs in single Burst (1-31);
|
||||
* @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of
|
||||
* the number of measurement iterations (min 2^0 = 1, max 2^14)
|
||||
* @sta_id: the station id of the AP. Only relevant when associated to the AP,
|
||||
* otherwise should be set to &IWL_MVM_INVALID_STA.
|
||||
* @cipher: pairwise cipher suite for secured measurement.
|
||||
* &enum iwl_location_cipher.
|
||||
* @hltk: HLTK to be used for secured 11az measurement
|
||||
* @tk: TK to be used for secured 11az measurement
|
||||
* @calib: An array of calibration values per FTM rx bandwidth.
|
||||
* If &IWL_INITIATOR_AP_FLAGS_USE_CALIB is set, the fw will use the
|
||||
* calibration value that corresponds to the rx bandwidth of the FTM
|
||||
* frame.
|
||||
* @beacon_interval: beacon interval of the AP in TUs. Only required if
|
||||
* &IWL_INITIATOR_AP_FLAGS_TB is set.
|
||||
* @rx_pn: the next expected PN for protected management frames Rx. LE byte
|
||||
* order. Only valid if &IWL_INITIATOR_AP_FLAGS_SECURED is set and sta_id
|
||||
* is set to &IWL_MVM_INVALID_STA.
|
||||
* @tx_pn: the next PN to use for protected management frames Tx. LE byte
|
||||
* order. Only valid if &IWL_INITIATOR_AP_FLAGS_SECURED is set and sta_id
|
||||
* is set to &IWL_MVM_INVALID_STA.
|
||||
* @r2i_ndp_params: parameters for R2I NDP ranging negotiation.
|
||||
* bits 0 - 2: max LTF repetitions
|
||||
* bits 3 - 5: max number of spatial streams
|
||||
* bits 6 - 7: max total LTFs. One of
|
||||
* &enum ieee80211_range_params_max_total_ltf.
|
||||
* @i2r_ndp_params: parameters for I2R NDP ranging negotiation.
|
||||
* bits 0 - 2: max LTF repetitions
|
||||
* bits 3 - 5: max number of spatial streams (supported values are < 2)
|
||||
* bits 6 - 7: max total LTFs. One of
|
||||
* &enum ieee80211_range_params_max_total_ltf.
|
||||
* @min_time_between_msr: For non trigger based NDP ranging, the minimum time
|
||||
* between measurements in units of milliseconds
|
||||
*/
|
||||
struct iwl_tof_range_req_ap_entry_v10 {
|
||||
__le32 initiator_ap_flags;
|
||||
u8 band;
|
||||
u8 channel_num;
|
||||
u8 format_bw;
|
||||
u8 ctrl_ch_position;
|
||||
u8 bssid[ETH_ALEN];
|
||||
__le16 burst_period;
|
||||
u8 samples_per_burst;
|
||||
u8 num_of_bursts;
|
||||
u8 sta_id;
|
||||
u8 cipher;
|
||||
u8 hltk[HLTK_11AZ_LEN];
|
||||
u8 tk[TK_11AZ_LEN];
|
||||
__le16 calib[IWL_TOF_BW_NUM];
|
||||
__le16 beacon_interval;
|
||||
u8 rx_pn[IEEE80211_CCMP_PN_LEN];
|
||||
u8 tx_pn[IEEE80211_CCMP_PN_LEN];
|
||||
u8 r2i_ndp_params;
|
||||
u8 i2r_ndp_params;
|
||||
__le16 min_time_between_msr;
|
||||
} __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_9 */
|
||||
|
||||
/**
|
||||
* enum iwl_tof_response_mode
|
||||
* @IWL_MVM_TOF_RESPONSE_ASAP: report each AP measurement separately as soon as
|
||||
|
|
@ -1229,6 +1359,34 @@ struct iwl_tof_range_req_cmd_v13 {
|
|||
struct iwl_tof_range_req_ap_entry_v9 ap[IWL_MVM_TOF_MAX_APS];
|
||||
} __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_13 */
|
||||
|
||||
/**
|
||||
* struct iwl_tof_range_req_cmd_v14 - start measurement cmd
|
||||
* @initiator_flags: see flags @ iwl_tof_initiator_flags
|
||||
* @request_id: A Token incremented per request. The same Token will be
|
||||
* sent back in the range response
|
||||
* @num_of_ap: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS)
|
||||
* @range_req_bssid: ranging request BSSID
|
||||
* @macaddr_mask: Bits set to 0 shall be copied from the MAC address template.
|
||||
* Bits set to 1 shall be randomized by the UMAC
|
||||
* @macaddr_template: MAC address template to use for non-randomized bits
|
||||
* @req_timeout_ms: Requested timeout of the response in units of milliseconds.
|
||||
* This is the session time for completing the measurement.
|
||||
* @tsf_mac_id: report the measurement start time for each ap in terms of the
|
||||
* TSF of this mac id. 0xff to disable TSF reporting.
|
||||
* @ap: per-AP request data, see &struct iwl_tof_range_req_ap_entry_v10.
|
||||
*/
|
||||
struct iwl_tof_range_req_cmd_v14 {
|
||||
__le32 initiator_flags;
|
||||
u8 request_id;
|
||||
u8 num_of_ap;
|
||||
u8 range_req_bssid[ETH_ALEN];
|
||||
u8 macaddr_mask[ETH_ALEN];
|
||||
u8 macaddr_template[ETH_ALEN];
|
||||
__le32 req_timeout_ms;
|
||||
__le32 tsf_mac_id;
|
||||
struct iwl_tof_range_req_ap_entry_v10 ap[IWL_MVM_TOF_MAX_APS];
|
||||
} __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_13 */
|
||||
|
||||
/*
|
||||
* enum iwl_tof_range_request_status - status of the sent request
|
||||
* @IWL_TOF_RANGE_REQUEST_STATUS_SUCCESSFUL - FW successfully received the
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2019, 2021-2022 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2019, 2021-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -57,6 +57,14 @@ enum iwl_mac_conf_subcmd_ids {
|
|||
* @STA_DISABLE_TX_CMD: &struct iwl_mvm_sta_disable_tx_cmd
|
||||
*/
|
||||
STA_DISABLE_TX_CMD = 0xD,
|
||||
/**
|
||||
* @ROC_CMD: &struct iwl_roc_req
|
||||
*/
|
||||
ROC_CMD = 0xE,
|
||||
/**
|
||||
* @ROC_NOTIF: &struct iwl_roc_notif
|
||||
*/
|
||||
ROC_NOTIF = 0xF8,
|
||||
/**
|
||||
* @SESSION_PROTECTION_NOTIF: &struct iwl_mvm_session_prot_notif
|
||||
*/
|
||||
|
|
@ -136,7 +144,7 @@ struct iwl_missed_vap_notif {
|
|||
} __packed; /* MISSED_VAP_NTFY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_channel_switch_start_notif - Channel switch start notification
|
||||
* struct iwl_channel_switch_start_notif_v1 - Channel switch start notification
|
||||
*
|
||||
* @id_and_color: ID and color of the MAC
|
||||
*/
|
||||
|
|
@ -234,9 +242,9 @@ struct iwl_mac_low_latency_cmd {
|
|||
* @esr_transition_timeout: the timeout required by the AP for the
|
||||
* eSR transition.
|
||||
* Available only from version 2 of the command.
|
||||
* This values comes from the EMLSR transition delay in the EML
|
||||
* This value comes from the EMLSR transition delay in the EML
|
||||
* Capabilities subfield.
|
||||
* @medium_sync_delay: the value as it appeasr in P802.11be_D2.2 Figure 9-1002j.
|
||||
* @medium_sync_delay: the value as it appears in P802.11be_D2.2 Figure 9-1002j.
|
||||
* @assoc_id: unique ID assigned by the AP during association
|
||||
* @reserved1: alignment
|
||||
* @data_policy: see &enum iwl_mac_data_policy
|
||||
|
|
@ -309,7 +317,6 @@ enum iwl_mac_config_filter_flags {
|
|||
* If the NIC is not ACK_ENABLED it may use the EOF-bit in first non-0
|
||||
* len delim to determine if AGG or single.
|
||||
* @client: client mac data
|
||||
* @go_ibss: mac data for go or ibss
|
||||
* @p2p_dev: mac data for p2p device
|
||||
*/
|
||||
struct iwl_mac_config_cmd {
|
||||
|
|
@ -366,7 +373,7 @@ struct iwl_mac_config_cmd {
|
|||
* iwl_link_ctx_cfg_cmd::bss_color_disable
|
||||
* @LINK_CONTEXT_MODIFY_EHT_PARAMS: covers iwl_link_ctx_cfg_cmd::puncture_mask.
|
||||
* This flag can be set only if the MAC that this link relates to has
|
||||
* eht_support set to true.
|
||||
* eht_support set to true. No longer used since _VER_3 of this command.
|
||||
* @LINK_CONTEXT_MODIFY_ALL: set all above flags
|
||||
*/
|
||||
enum iwl_link_ctx_modify_flags {
|
||||
|
|
@ -439,6 +446,7 @@ enum iwl_link_ctx_flags {
|
|||
* @listen_lmac: indicates whether the link should be allocated on the Listen
|
||||
* Lmac or on the Main Lmac. Cannot be changed on an active Link.
|
||||
* Relevant only for eSR.
|
||||
* @reserved1: in version 2, listen_lmac became reserved
|
||||
* @cck_rates: basic rates available for CCK
|
||||
* @ofdm_rates: basic rates available for OFDM
|
||||
* @cck_short_preamble: 1 for enabling short preamble, 0 otherwise
|
||||
|
|
@ -454,7 +462,7 @@ enum iwl_link_ctx_flags {
|
|||
* @bi: beacon interval in TU, applicable only when associated
|
||||
* @dtim_interval: DTIM interval in TU.
|
||||
* Relevant only for GO, otherwise this is offloaded.
|
||||
* @puncture_mask: puncture mask for EHT
|
||||
* @puncture_mask: puncture mask for EHT (removed in VER_3)
|
||||
* @frame_time_rts_th: HE duration RTS threshold, in units of 32us
|
||||
* @flags: a combination from &enum iwl_link_ctx_flags
|
||||
* @flags_mask: what of %flags have changed. Also &enum iwl_link_ctx_flags
|
||||
|
|
@ -464,10 +472,10 @@ enum iwl_link_ctx_flags {
|
|||
* @bssid_index: index of the associated VAP
|
||||
* @bss_color: 11ax AP ID that is used in the HE SIG-A to mark inter BSS frame
|
||||
* @spec_link_id: link_id as the AP knows it
|
||||
* @reserved: alignment
|
||||
* @reserved2: alignment
|
||||
* @ibss_bssid_addr: bssid for ibss
|
||||
* @reserved_for_ibss_bssid_addr: reserved
|
||||
* @reserved1: reserved for future use
|
||||
* @reserved3: reserved for future use
|
||||
*/
|
||||
struct iwl_link_config_cmd {
|
||||
__le32 action;
|
||||
|
|
@ -478,7 +486,10 @@ struct iwl_link_config_cmd {
|
|||
__le16 reserved_for_local_link_addr;
|
||||
__le32 modify_mask;
|
||||
__le32 active;
|
||||
__le32 listen_lmac;
|
||||
union {
|
||||
__le32 listen_lmac;
|
||||
__le32 reserved1;
|
||||
};
|
||||
__le32 cck_rates;
|
||||
__le32 ofdm_rates;
|
||||
__le32 cck_short_preamble;
|
||||
|
|
@ -494,7 +505,7 @@ struct iwl_link_config_cmd {
|
|||
struct iwl_he_backoff_conf trig_based_txf[AC_NUM];
|
||||
__le32 bi;
|
||||
__le32 dtim_interval;
|
||||
__le16 puncture_mask;
|
||||
__le16 puncture_mask; /* removed in _VER_3 */
|
||||
__le16 frame_time_rts_th;
|
||||
__le32 flags;
|
||||
__le32 flags_mask;
|
||||
|
|
@ -504,11 +515,11 @@ struct iwl_link_config_cmd {
|
|||
u8 bssid_index;
|
||||
u8 bss_color;
|
||||
u8 spec_link_id;
|
||||
u8 reserved;
|
||||
u8 reserved2;
|
||||
u8 ibss_bssid_addr[6];
|
||||
__le16 reserved_for_ibss_bssid_addr;
|
||||
__le32 reserved1[8];
|
||||
} __packed; /* LINK_CONTEXT_CONFIG_CMD_API_S_VER_1 */
|
||||
__le32 reserved3[8];
|
||||
} __packed; /* LINK_CONTEXT_CONFIG_CMD_API_S_VER_1, _VER_2, _VER_3 */
|
||||
|
||||
/* Currently FW supports link ids in the range 0-3 and can have
|
||||
* at most two active links for each vif.
|
||||
|
|
@ -631,4 +642,25 @@ struct iwl_mvm_sta_disable_tx_cmd {
|
|||
__le32 disable;
|
||||
} __packed; /* STA_DISABLE_TX_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_mvm_fw_esr_recommendation - FW recommendation code
|
||||
* @ESR_RECOMMEND_LEAVE: recommendation to leave esr
|
||||
* @ESR_FORCE_LEAVE: force exiting esr
|
||||
* @ESR_RECOMMEND_ENTER: recommendation to enter esr
|
||||
*/
|
||||
enum iwl_mvm_fw_esr_recommendation {
|
||||
ESR_RECOMMEND_LEAVE,
|
||||
ESR_FORCE_LEAVE,
|
||||
ESR_RECOMMEND_ENTER,
|
||||
}; /* ESR_MODE_RECOMMENDATION_CODE_API_E_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_esr_mode_notif - FWs recommendation/force for esr mode
|
||||
*
|
||||
* @action: the action to apply on esr state. See &iwl_mvm_fw_esr_recommendation
|
||||
*/
|
||||
struct iwl_mvm_esr_mode_notif {
|
||||
__le32 action;
|
||||
} __packed; /* ESR_MODE_RECOMMENDATION_NTFY_API_S_VER_1 */
|
||||
|
||||
#endif /* __iwl_fw_api_mac_cfg_h__ */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2022, 2024 Intel Corporation
|
||||
* Copyright (C) 2017 Intel Deutschland GmbH
|
||||
*/
|
||||
#ifndef __iwl_fw_api_mac_h__
|
||||
|
|
@ -310,6 +310,13 @@ struct iwl_ac_qos {
|
|||
* @filter_flags: combination of &enum iwl_mac_filter_flags
|
||||
* @qos_flags: from &enum iwl_mac_qos_flags
|
||||
* @ac: one iwl_mac_qos configuration for each AC
|
||||
* @ap: AP specific config data, see &struct iwl_mac_data_ap
|
||||
* @go: GO specific config data, see &struct iwl_mac_data_go
|
||||
* @sta: BSS client specific config data, see &struct iwl_mac_data_sta
|
||||
* @p2p_sta: P2P client specific config data, see &struct iwl_mac_data_p2p_sta
|
||||
* @p2p_dev: P2P-device specific config data, see &struct iwl_mac_data_p2p_dev
|
||||
* @pibss: Pseudo-IBSS specific data, unused; see struct iwl_mac_data_pibss
|
||||
* @ibss: IBSS specific config data, see &struct iwl_mac_data_ibss
|
||||
*/
|
||||
struct iwl_mac_ctx_cmd {
|
||||
/* COMMON_INDEX_HDR_API_S_VER_1 */
|
||||
|
|
@ -431,8 +438,8 @@ enum iwl_he_pkt_ext_constellations {
|
|||
};
|
||||
|
||||
#define MAX_HE_SUPP_NSS 2
|
||||
#define MAX_CHANNEL_BW_INDX_API_D_VER_2 4
|
||||
#define MAX_CHANNEL_BW_INDX_API_D_VER_3 5
|
||||
#define MAX_CHANNEL_BW_INDX_API_D_VER_1 4
|
||||
#define MAX_CHANNEL_BW_INDX_API_D_VER_2 5
|
||||
|
||||
/**
|
||||
* struct iwl_he_pkt_ext_v1 - QAM thresholds
|
||||
|
|
@ -455,7 +462,7 @@ enum iwl_he_pkt_ext_constellations {
|
|||
* (0-low_th, 1-high_th)
|
||||
*/
|
||||
struct iwl_he_pkt_ext_v1 {
|
||||
u8 pkt_ext_qam_th[MAX_HE_SUPP_NSS][MAX_CHANNEL_BW_INDX_API_D_VER_2][2];
|
||||
u8 pkt_ext_qam_th[MAX_HE_SUPP_NSS][MAX_CHANNEL_BW_INDX_API_D_VER_1][2];
|
||||
} __packed; /* PKT_EXT_DOT11AX_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
|
|
@ -480,7 +487,7 @@ struct iwl_he_pkt_ext_v1 {
|
|||
* (0-low_th, 1-high_th)
|
||||
*/
|
||||
struct iwl_he_pkt_ext_v2 {
|
||||
u8 pkt_ext_qam_th[MAX_HE_SUPP_NSS][MAX_CHANNEL_BW_INDX_API_D_VER_3][2];
|
||||
u8 pkt_ext_qam_th[MAX_HE_SUPP_NSS][MAX_CHANNEL_BW_INDX_API_D_VER_2][2];
|
||||
} __packed; /* PKT_EXT_DOT11AX_API_S_VER_2 */
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -21,8 +21,11 @@ enum iwl_regulatory_and_nvm_subcmd_ids {
|
|||
* &struct iwl_lari_config_change_cmd_v2,
|
||||
* &struct iwl_lari_config_change_cmd_v3,
|
||||
* &struct iwl_lari_config_change_cmd_v4,
|
||||
* &struct iwl_lari_config_change_cmd_v5 or
|
||||
* &struct iwl_lari_config_change_cmd_v6
|
||||
* &struct iwl_lari_config_change_cmd_v5,
|
||||
* &struct iwl_lari_config_change_cmd_v6,
|
||||
* &struct iwl_lari_config_change_cmd_v7,
|
||||
* &struct iwl_lari_config_change_cmd_v10 or
|
||||
* &struct iwl_lari_config_change_cmd
|
||||
*/
|
||||
LARI_CONFIG_CHANGE = 0x1,
|
||||
|
||||
|
|
@ -43,6 +46,11 @@ enum iwl_regulatory_and_nvm_subcmd_ids {
|
|||
*/
|
||||
SAR_OFFSET_MAPPING_TABLE_CMD = 0x4,
|
||||
|
||||
/**
|
||||
* @MCC_ALLOWED_AP_TYPE_CMD: &struct iwl_mcc_allowed_ap_type_cmd
|
||||
*/
|
||||
MCC_ALLOWED_AP_TYPE_CMD = 0x5,
|
||||
|
||||
/**
|
||||
* @PNVM_INIT_COMPLETE_NTFY: &struct iwl_pnvm_init_complete_ntfy
|
||||
*/
|
||||
|
|
@ -112,7 +120,7 @@ struct iwl_nvm_access_cmd {
|
|||
} __packed; /* NVM_ACCESS_CMD_API_S_VER_2 */
|
||||
|
||||
/**
|
||||
* struct iwl_nvm_access_resp_ver2 - response to NVM_ACCESS_CMD
|
||||
* struct iwl_nvm_access_resp - response to NVM_ACCESS_CMD
|
||||
* @offset: offset in bytes into the section
|
||||
* @length: in bytes, either how much was written or read
|
||||
* @type: NVM_SECTION_TYPE_*
|
||||
|
|
@ -204,7 +212,7 @@ struct iwl_nvm_get_info_phy {
|
|||
#define IWL_NUM_CHANNELS 110
|
||||
|
||||
/**
|
||||
* struct iwl_nvm_get_info_regulatory - regulatory information
|
||||
* struct iwl_nvm_get_info_regulatory_v1 - regulatory information
|
||||
* @lar_enabled: is LAR enabled
|
||||
* @channel_profile: regulatory data of this channel
|
||||
* @reserved: reserved
|
||||
|
|
@ -263,6 +271,9 @@ struct iwl_nvm_access_complete_cmd {
|
|||
__le32 reserved;
|
||||
} __packed; /* NVM_ACCESS_COMPLETE_CMD_API_S_VER_1 */
|
||||
|
||||
#define IWL_MCC_US 0x5553
|
||||
#define IWL_MCC_CANADA 0x4341
|
||||
|
||||
/**
|
||||
* struct iwl_mcc_update_cmd - Request the device to update geographic
|
||||
* regulatory profile according to the given MCC (Mobile Country Code).
|
||||
|
|
@ -429,36 +440,31 @@ enum iwl_mcc_source {
|
|||
MCC_SOURCE_GETTING_MCC_TEST_MODE = 0x11,
|
||||
};
|
||||
|
||||
#define IWL_TAS_BLOCK_LIST_MAX 16
|
||||
#define IWL_WTAS_BLACK_LIST_MAX 16
|
||||
/**
|
||||
* struct iwl_tas_config_cmd_v2 - configures the TAS
|
||||
* struct iwl_tas_config_cmd_common - configures the TAS.
|
||||
* This is also the v2 structure.
|
||||
* @block_list_size: size of relevant field in block_list_array
|
||||
* @block_list_array: list of countries where TAS must be disabled
|
||||
*/
|
||||
struct iwl_tas_config_cmd_v2 {
|
||||
struct iwl_tas_config_cmd_common {
|
||||
__le32 block_list_size;
|
||||
__le32 block_list_array[IWL_TAS_BLOCK_LIST_MAX];
|
||||
__le32 block_list_array[IWL_WTAS_BLACK_LIST_MAX];
|
||||
} __packed; /* TAS_CONFIG_CMD_API_S_VER_2 */
|
||||
|
||||
/**
|
||||
* struct iwl_tas_config_cmd_v3 - configures the TAS
|
||||
* @block_list_size: size of relevant field in block_list_array
|
||||
* @block_list_array: list of countries where TAS must be disabled
|
||||
* @override_tas_iec: indicates whether to override default value of IEC regulatory
|
||||
* @enable_tas_iec: in case override_tas_iec is set -
|
||||
* indicates whether IEC regulatory is enabled or disabled
|
||||
*/
|
||||
struct iwl_tas_config_cmd_v3 {
|
||||
__le32 block_list_size;
|
||||
__le32 block_list_array[IWL_TAS_BLOCK_LIST_MAX];
|
||||
__le16 override_tas_iec;
|
||||
__le16 enable_tas_iec;
|
||||
} __packed; /* TAS_CONFIG_CMD_API_S_VER_3 */
|
||||
|
||||
/**
|
||||
* struct iwl_tas_config_cmd_v3 - configures the TAS
|
||||
* @block_list_size: size of relevant field in block_list_array
|
||||
* @block_list_array: list of countries where TAS must be disabled
|
||||
* struct iwl_tas_config_cmd_v4 - configures the TAS
|
||||
* @override_tas_iec: indicates whether to override default value of IEC regulatory
|
||||
* @enable_tas_iec: in case override_tas_iec is set -
|
||||
* indicates whether IEC regulatory is enabled or disabled
|
||||
|
|
@ -466,32 +472,35 @@ struct iwl_tas_config_cmd_v3 {
|
|||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_tas_config_cmd_v4 {
|
||||
__le32 block_list_size;
|
||||
__le32 block_list_array[IWL_TAS_BLOCK_LIST_MAX];
|
||||
u8 override_tas_iec;
|
||||
u8 enable_tas_iec;
|
||||
u8 usa_tas_uhb_allowed;
|
||||
u8 reserved;
|
||||
} __packed; /* TAS_CONFIG_CMD_API_S_VER_4 */
|
||||
|
||||
union iwl_tas_config_cmd {
|
||||
struct iwl_tas_config_cmd_v2 v2;
|
||||
struct iwl_tas_config_cmd_v3 v3;
|
||||
struct iwl_tas_config_cmd_v4 v4;
|
||||
struct iwl_tas_config_cmd {
|
||||
struct iwl_tas_config_cmd_common common;
|
||||
union {
|
||||
struct iwl_tas_config_cmd_v3 v3;
|
||||
struct iwl_tas_config_cmd_v4 v4;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_lari_configs - bit masks for the various LARI config operations
|
||||
* enum iwl_lari_config_masks - bit masks for the various LARI config operations
|
||||
* @LARI_CONFIG_DISABLE_11AC_UKRAINE_MSK: disable 11ac in ukraine
|
||||
* @LARI_CONFIG_CHANGE_ETSI_TO_PASSIVE_MSK: ETSI 5.8GHz SRD passive scan
|
||||
* @LARI_CONFIG_CHANGE_ETSI_TO_DISABLED_MSK: ETSI 5.8GHz SRD disabled
|
||||
* @LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK: enable 5.15/5.35GHz bands in
|
||||
* Indonesia
|
||||
* @LARI_CONFIG_ENABLE_CHINA_22_REG_SUPPORT_MSK: enable 2022 china regulatory
|
||||
*/
|
||||
enum iwl_lari_config_masks {
|
||||
LARI_CONFIG_DISABLE_11AC_UKRAINE_MSK = BIT(0),
|
||||
LARI_CONFIG_CHANGE_ETSI_TO_PASSIVE_MSK = BIT(1),
|
||||
LARI_CONFIG_CHANGE_ETSI_TO_DISABLED_MSK = BIT(2),
|
||||
LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK = BIT(3),
|
||||
LARI_CONFIG_ENABLE_CHINA_22_REG_SUPPORT_MSK = BIT(7),
|
||||
};
|
||||
|
||||
#define IWL_11AX_UKRAINE_MASK 3
|
||||
|
|
@ -600,6 +609,136 @@ struct iwl_lari_config_change_cmd_v6 {
|
|||
__le32 force_disable_channels_bitmap;
|
||||
} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_6 */
|
||||
|
||||
/**
|
||||
* struct iwl_lari_config_change_cmd_v7 - change LARI configuration
|
||||
* This structure is used also for lari cmd version 8 and 9.
|
||||
* @config_bitmap: Bitmap of the config commands. Each bit will trigger a
|
||||
* different predefined FW config operation.
|
||||
* @oem_uhb_allow_bitmap: Bitmap of UHB enabled MCC sets.
|
||||
* @oem_11ax_allow_bitmap: Bitmap of 11ax allowed MCCs. There are two bits
|
||||
* per country, one to indicate whether to override and the other to
|
||||
* indicate the value to use.
|
||||
* @oem_unii4_allow_bitmap: Bitmap of unii4 allowed MCCs.There are two bits
|
||||
* per country, one to indicate whether to override and the other to
|
||||
* indicate allow/disallow unii4 channels.
|
||||
* For LARI cmd version 4 to 8 - bits 0:3 are supported.
|
||||
* For LARI cmd version 9 - bits 0:5 are supported.
|
||||
* @chan_state_active_bitmap: Bitmap to enable different bands per country
|
||||
* or region.
|
||||
* Each bit represents a country or region, and a band to activate
|
||||
* according to the BIOS definitions.
|
||||
* For LARI cmd version 7 - bits 0:3 are supported.
|
||||
* For LARI cmd version 8 - bits 0:4 are supported.
|
||||
* @force_disable_channels_bitmap: Bitmap of disabled bands/channels.
|
||||
* Each bit represents a set of channels in a specific band that should be
|
||||
* disabled
|
||||
* @edt_bitmap: Bitmap of energy detection threshold table.
|
||||
* Disable/enable the EDT optimization method for different band.
|
||||
*/
|
||||
struct iwl_lari_config_change_cmd_v7 {
|
||||
__le32 config_bitmap;
|
||||
__le32 oem_uhb_allow_bitmap;
|
||||
__le32 oem_11ax_allow_bitmap;
|
||||
__le32 oem_unii4_allow_bitmap;
|
||||
__le32 chan_state_active_bitmap;
|
||||
__le32 force_disable_channels_bitmap;
|
||||
__le32 edt_bitmap;
|
||||
} __packed;
|
||||
/* LARI_CHANGE_CONF_CMD_S_VER_7 */
|
||||
/* LARI_CHANGE_CONF_CMD_S_VER_8 */
|
||||
/* LARI_CHANGE_CONF_CMD_S_VER_9 */
|
||||
|
||||
/**
|
||||
* struct iwl_lari_config_change_cmd_v10 - change LARI configuration
|
||||
* @config_bitmap: Bitmap of the config commands. Each bit will trigger a
|
||||
* different predefined FW config operation.
|
||||
* @oem_uhb_allow_bitmap: Bitmap of UHB enabled MCC sets.
|
||||
* @oem_11ax_allow_bitmap: Bitmap of 11ax allowed MCCs. There are two bits
|
||||
* per country, one to indicate whether to override and the other to
|
||||
* indicate the value to use.
|
||||
* @oem_unii4_allow_bitmap: Bitmap of unii4 allowed MCCs.There are two bits
|
||||
* per country, one to indicate whether to override and the other to
|
||||
* indicate allow/disallow unii4 channels.
|
||||
* For LARI cmd version 10 - bits 0:5 are supported.
|
||||
* @chan_state_active_bitmap: Bitmap to enable different bands per country
|
||||
* or region.
|
||||
* Each bit represents a country or region, and a band to activate
|
||||
* according to the BIOS definitions.
|
||||
* For LARI cmd version 10 - bits 0:4 are supported.
|
||||
* @force_disable_channels_bitmap: Bitmap of disabled bands/channels.
|
||||
* Each bit represents a set of channels in a specific band that should be
|
||||
* disabled
|
||||
* @edt_bitmap: Bitmap of energy detection threshold table.
|
||||
* Disable/enable the EDT optimization method for different band.
|
||||
* @oem_320mhz_allow_bitmap: 320Mhz bandwidth enablement bitmap per MCC.
|
||||
* bit0: enable 320Mhz in Japan.
|
||||
* bit1: enable 320Mhz in South Korea.
|
||||
* bit 2 - 31: reserved.
|
||||
*/
|
||||
struct iwl_lari_config_change_cmd_v10 {
|
||||
__le32 config_bitmap;
|
||||
__le32 oem_uhb_allow_bitmap;
|
||||
__le32 oem_11ax_allow_bitmap;
|
||||
__le32 oem_unii4_allow_bitmap;
|
||||
__le32 chan_state_active_bitmap;
|
||||
__le32 force_disable_channels_bitmap;
|
||||
__le32 edt_bitmap;
|
||||
__le32 oem_320mhz_allow_bitmap;
|
||||
} __packed;
|
||||
/* LARI_CHANGE_CONF_CMD_S_VER_10 */
|
||||
|
||||
/**
|
||||
* struct iwl_lari_config_change_cmd - change LARI configuration
|
||||
* @config_bitmap: Bitmap of the config commands. Each bit will trigger a
|
||||
* different predefined FW config operation.
|
||||
* @oem_uhb_allow_bitmap: Bitmap of UHB enabled MCC sets.
|
||||
* @oem_11ax_allow_bitmap: Bitmap of 11ax allowed MCCs. There are two bits
|
||||
* per country, one to indicate whether to override and the other to
|
||||
* indicate the value to use.
|
||||
* @oem_unii4_allow_bitmap: Bitmap of unii4 allowed MCCs.There are two bits
|
||||
* per country, one to indicate whether to override and the other to
|
||||
* indicate allow/disallow unii4 channels.
|
||||
* For LARI cmd version 11 - bits 0:5 are supported.
|
||||
* @chan_state_active_bitmap: Bitmap to enable different bands per country
|
||||
* or region.
|
||||
* Each bit represents a country or region, and a band to activate
|
||||
* according to the BIOS definitions.
|
||||
* For LARI cmd version 11 - bits 0:4 are supported.
|
||||
* For LARI cmd version 12 - bits 0:6 are supported and bits 7:31 are
|
||||
* reserved. No need to mask out the reserved bits.
|
||||
* @force_disable_channels_bitmap: Bitmap of disabled bands/channels.
|
||||
* Each bit represents a set of channels in a specific band that should be
|
||||
* disabled
|
||||
* @edt_bitmap: Bitmap of energy detection threshold table.
|
||||
* Disable/enable the EDT optimization method for different band.
|
||||
* @oem_320mhz_allow_bitmap: 320Mhz bandwidth enablement bitmap per MCC.
|
||||
* bit0: enable 320Mhz in Japan.
|
||||
* bit1: enable 320Mhz in South Korea.
|
||||
* bit 2 - 31: reserved.
|
||||
* @oem_11be_allow_bitmap: Bitmap of 11be allowed MCCs. No need to mask out the
|
||||
* unsupported bits
|
||||
* bit0: enable 11be in China(CB/CN).
|
||||
* bit1: enable 11be in South Korea.
|
||||
* bit 2 - 31: reserved.
|
||||
*/
|
||||
struct iwl_lari_config_change_cmd {
|
||||
__le32 config_bitmap;
|
||||
__le32 oem_uhb_allow_bitmap;
|
||||
__le32 oem_11ax_allow_bitmap;
|
||||
__le32 oem_unii4_allow_bitmap;
|
||||
__le32 chan_state_active_bitmap;
|
||||
__le32 force_disable_channels_bitmap;
|
||||
__le32 edt_bitmap;
|
||||
__le32 oem_320mhz_allow_bitmap;
|
||||
__le32 oem_11be_allow_bitmap;
|
||||
} __packed;
|
||||
/* LARI_CHANGE_CONF_CMD_S_VER_11 */
|
||||
/* LARI_CHANGE_CONF_CMD_S_VER_12 */
|
||||
|
||||
/* Activate UNII-1 (5.2GHz) for World Wide */
|
||||
#define ACTIVATE_5G2_IN_WW_MASK BIT(4)
|
||||
#define CHAN_STATE_ACTIVE_BITMAP_CMD_V11 0x1F
|
||||
|
||||
/**
|
||||
* struct iwl_pnvm_init_complete_ntfy - PNVM initialization complete
|
||||
* @status: PNVM image loading status
|
||||
|
|
@ -608,4 +747,17 @@ struct iwl_pnvm_init_complete_ntfy {
|
|||
__le32 status;
|
||||
} __packed; /* PNVM_INIT_COMPLETE_NTFY_S_VER_1 */
|
||||
|
||||
#define UATS_TABLE_ROW_SIZE 26
|
||||
#define UATS_TABLE_COL_SIZE 13
|
||||
|
||||
/**
|
||||
* struct iwl_mcc_allowed_ap_type_cmd - struct for MCC_ALLOWED_AP_TYPE_CMD
|
||||
* @offset_map: mapping a mcc to UHB AP type support (UATS) allowed
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_mcc_allowed_ap_type_cmd {
|
||||
u8 offset_map[UATS_TABLE_ROW_SIZE][UATS_TABLE_COL_SIZE];
|
||||
__le16 reserved;
|
||||
} __packed; /* MCC_ALLOWED_AP_TYPE_CMD_API_S_VER_1 */
|
||||
|
||||
#endif /* __iwl_fw_api_nvm_reg_h__ */
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (C) 2012-2014 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2021-2022 Intel Corporation
|
||||
* Copyright (C) 2021-2024 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_fw_api_offload_h__
|
||||
#define __iwl_fw_api_offload_h__
|
||||
|
|
@ -18,7 +18,9 @@ enum iwl_prot_offload_subcmd_ids {
|
|||
WOWLAN_WAKE_PKT_NOTIFICATION = 0xFC,
|
||||
|
||||
/**
|
||||
* @WOWLAN_INFO_NOTIFICATION: Notification in &struct iwl_wowlan_info_notif
|
||||
* @WOWLAN_INFO_NOTIFICATION: Notification in
|
||||
* &struct iwl_wowlan_info_notif_v1, &struct iwl_wowlan_info_notif_v2,
|
||||
* or &struct iwl_wowlan_info_notif
|
||||
*/
|
||||
WOWLAN_INFO_NOTIFICATION = 0xFD,
|
||||
|
||||
|
|
@ -58,7 +60,7 @@ struct iwl_stored_beacon_notif_common {
|
|||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_stored_beacon_notif - Stored beacon notification
|
||||
* struct iwl_stored_beacon_notif_v2 - Stored beacon notification
|
||||
*
|
||||
* @common: fields common for all versions
|
||||
* @data: beacon data, length in @byte_count
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018, 2020-2022 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018, 2020-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -25,8 +25,8 @@
|
|||
* For legacy set bit means upper channel, otherwise lower.
|
||||
* For VHT - bit-2 marks if the control is lower/upper relative to center-freq
|
||||
* bits-1:0 mark the distance from the center freq. for 20Mhz, offset is 0.
|
||||
* center_freq
|
||||
* For EHT - bit-3 is used for extended distance
|
||||
* center_freq
|
||||
* |
|
||||
* 40Mhz |____|____|
|
||||
* 80Mhz |____|____|____|____|
|
||||
|
|
@ -113,7 +113,7 @@ struct iwl_phy_context_cmd_tail {
|
|||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_phy_context_cmd - config of the PHY context
|
||||
* struct iwl_phy_context_cmd_v1 - config of the PHY context
|
||||
* ( PHY_CONTEXT_CMD = 0x8 )
|
||||
* @id_and_color: ID and color of the relevant Binding
|
||||
* @action: action to perform, see &enum iwl_ctxt_action
|
||||
|
|
@ -142,6 +142,9 @@ struct iwl_phy_context_cmd_v1 {
|
|||
* @lmac_id: the lmac id the phy context belongs to
|
||||
* @ci: channel info
|
||||
* @rxchain_info: ???
|
||||
* @sbb_bandwidth: 0 disabled, 1 - 40Mhz ... 4 - 320MHz
|
||||
* @sbb_ctrl_channel_loc: location of the control channel
|
||||
* @puncture_mask: bitmap of punctured subchannels
|
||||
* @dsp_cfg_flags: set to 0
|
||||
* @reserved: reserved to align to 64 bit
|
||||
*/
|
||||
|
|
@ -152,9 +155,20 @@ struct iwl_phy_context_cmd {
|
|||
/* PHY_CONTEXT_DATA_API_S_VER_3, PHY_CONTEXT_DATA_API_S_VER_4 */
|
||||
struct iwl_fw_channel_info ci;
|
||||
__le32 lmac_id;
|
||||
__le32 rxchain_info; /* reserved in _VER_4 */
|
||||
union {
|
||||
__le32 rxchain_info; /* reserved in _VER_4 */
|
||||
struct { /* used for _VER_5/_VER_6 */
|
||||
u8 sbb_bandwidth;
|
||||
u8 sbb_ctrl_channel_loc;
|
||||
__le16 puncture_mask; /* added in VER_6 */
|
||||
};
|
||||
};
|
||||
__le32 dsp_cfg_flags;
|
||||
__le32 reserved;
|
||||
} __packed; /* PHY_CONTEXT_CMD_API_VER_3, PHY_CONTEXT_CMD_API_VER_4 */
|
||||
} __packed; /* PHY_CONTEXT_CMD_API_VER_3,
|
||||
* PHY_CONTEXT_CMD_API_VER_4,
|
||||
* PHY_CONTEXT_CMD_API_VER_5,
|
||||
* PHY_CONTEXT_CMD_API_VER_6
|
||||
*/
|
||||
|
||||
#endif /* __iwl_fw_api_phy_ctxt_h__ */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2019-2022 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2019-2022, 2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -42,6 +42,11 @@ enum iwl_phy_ops_subcmd_ids {
|
|||
*/
|
||||
PER_PLATFORM_ANT_GAIN_CMD = 0x07,
|
||||
|
||||
/**
|
||||
* @AP_TX_POWER_CONSTRAINTS_CMD: &struct iwl_txpower_constraints_cmd
|
||||
*/
|
||||
AP_TX_POWER_CONSTRAINTS_CMD = 0x0C,
|
||||
|
||||
/**
|
||||
* @CT_KILL_NOTIFICATION: &struct ct_kill_notif
|
||||
*/
|
||||
|
|
@ -190,7 +195,7 @@ struct ct_kill_notif {
|
|||
} __packed; /* CT_KILL_NOTIFICATION_API_S_VER_1, CT_KILL_NOTIFICATION_API_S_VER_2 */
|
||||
|
||||
/**
|
||||
* enum ctdp_cmd_operation - CTDP command operations
|
||||
* enum iwl_mvm_ctdp_cmd_operation - CTDP command operations
|
||||
* @CTDP_CMD_OPERATION_START: update the current budget
|
||||
* @CTDP_CMD_OPERATION_STOP: stop ctdp
|
||||
* @CTDP_CMD_OPERATION_REPORT: get the average budget
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -144,6 +144,8 @@ struct iwl_powertable_cmd {
|
|||
* receiver and transmitter. '0' - does not allow.
|
||||
* @DEVICE_POWER_FLAGS_ALLOW_MEM_RETENTION_MSK:
|
||||
* Device Retention indication, '1' indicate retention is enabled.
|
||||
* @DEVICE_POWER_FLAGS_NO_SLEEP_TILL_D3_MSK:
|
||||
* Prevent power save until entering d3 is completed.
|
||||
* @DEVICE_POWER_FLAGS_32K_CLK_VALID_MSK:
|
||||
* 32Khz external slow clock valid indication, '1' indicate cloack is
|
||||
* valid.
|
||||
|
|
@ -151,6 +153,7 @@ struct iwl_powertable_cmd {
|
|||
enum iwl_device_power_flags {
|
||||
DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0),
|
||||
DEVICE_POWER_FLAGS_ALLOW_MEM_RETENTION_MSK = BIT(1),
|
||||
DEVICE_POWER_FLAGS_NO_SLEEP_TILL_D3_MSK = BIT(7),
|
||||
DEVICE_POWER_FLAGS_32K_CLK_VALID_MSK = BIT(12),
|
||||
};
|
||||
|
||||
|
|
@ -162,7 +165,7 @@ enum iwl_device_power_flags {
|
|||
* @reserved: reserved (padding)
|
||||
*/
|
||||
struct iwl_device_power_cmd {
|
||||
/* PM_POWER_TABLE_CMD_API_S_VER_6 */
|
||||
/* PM_POWER_TABLE_CMD_API_S_VER_7 */
|
||||
__le16 flags;
|
||||
__le16 reserved;
|
||||
} __packed;
|
||||
|
|
@ -382,6 +385,33 @@ struct iwl_dev_tx_power_cmd_v7 {
|
|||
__le32 timer_period;
|
||||
__le32 flags;
|
||||
} __packed; /* TX_REDUCED_POWER_API_S_VER_7 */
|
||||
|
||||
/**
|
||||
* struct iwl_dev_tx_power_cmd_v8 - TX power reduction command version 8
|
||||
* @per_chain: per chain restrictions
|
||||
* @enable_ack_reduction: enable or disable close range ack TX power
|
||||
* reduction.
|
||||
* @per_chain_restriction_changed: is per_chain_restriction has changed
|
||||
* from last command. used if set_mode is
|
||||
* IWL_TX_POWER_MODE_SET_SAR_TIMER.
|
||||
* note: if not changed, the command is used for keep alive only.
|
||||
* @reserved: reserved (padding)
|
||||
* @timer_period: timer in milliseconds. if expires FW will change to default
|
||||
* BIOS values. relevant if setMode is IWL_TX_POWER_MODE_SET_SAR_TIMER
|
||||
* @flags: reduce power flags.
|
||||
* @tpc_vlp_backoff_level: user backoff of UNII5,7 VLP channels in USA.
|
||||
* Not in use.
|
||||
*/
|
||||
struct iwl_dev_tx_power_cmd_v8 {
|
||||
__le16 per_chain[IWL_NUM_CHAIN_TABLES_V2][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
|
||||
u8 enable_ack_reduction;
|
||||
u8 per_chain_restriction_changed;
|
||||
u8 reserved[2];
|
||||
__le32 timer_period;
|
||||
__le32 flags;
|
||||
__le32 tpc_vlp_backoff_level;
|
||||
} __packed; /* TX_REDUCED_POWER_API_S_VER_8 */
|
||||
|
||||
/**
|
||||
* struct iwl_dev_tx_power_cmd - TX power reduction command (multiversion)
|
||||
* @common: common part of the command
|
||||
|
|
@ -389,6 +419,8 @@ struct iwl_dev_tx_power_cmd_v7 {
|
|||
* @v4: version 4 part of the command
|
||||
* @v5: version 5 part of the command
|
||||
* @v6: version 6 part of the command
|
||||
* @v7: version 7 part of the command
|
||||
* @v8: version 8 part of the command
|
||||
*/
|
||||
struct iwl_dev_tx_power_cmd {
|
||||
struct iwl_dev_tx_power_common common;
|
||||
|
|
@ -398,6 +430,7 @@ struct iwl_dev_tx_power_cmd {
|
|||
struct iwl_dev_tx_power_cmd_v5 v5;
|
||||
struct iwl_dev_tx_power_cmd_v6 v6;
|
||||
struct iwl_dev_tx_power_cmd_v7 v7;
|
||||
struct iwl_dev_tx_power_cmd_v8 v8;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -429,7 +462,7 @@ struct iwl_per_chain_offset {
|
|||
} __packed; /* PER_CHAIN_LIMIT_OFFSET_PER_CHAIN_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_geo_tx_power_profile_cmd_v1 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
|
||||
* struct iwl_geo_tx_power_profiles_cmd_v1 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
|
||||
* @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
|
||||
* @table: offset profile per band.
|
||||
*/
|
||||
|
|
@ -439,7 +472,7 @@ struct iwl_geo_tx_power_profiles_cmd_v1 {
|
|||
} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_geo_tx_power_profile_cmd_v2 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
|
||||
* struct iwl_geo_tx_power_profiles_cmd_v2 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
|
||||
* @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
|
||||
* @table: offset profile per band.
|
||||
* @table_revision: 0 for not-South Korea, 1 for South Korea (the name is misleading)
|
||||
|
|
@ -451,7 +484,7 @@ struct iwl_geo_tx_power_profiles_cmd_v2 {
|
|||
} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_2 */
|
||||
|
||||
/**
|
||||
* struct iwl_geo_tx_power_profile_cmd_v3 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
|
||||
* struct iwl_geo_tx_power_profiles_cmd_v3 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
|
||||
* @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
|
||||
* @table: offset profile per band.
|
||||
* @table_revision: 0 for not-South Korea, 1 for South Korea (the name is misleading)
|
||||
|
|
@ -463,7 +496,7 @@ struct iwl_geo_tx_power_profiles_cmd_v3 {
|
|||
} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_3 */
|
||||
|
||||
/**
|
||||
* struct iwl_geo_tx_power_profile_cmd_v4 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
|
||||
* struct iwl_geo_tx_power_profiles_cmd_v4 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
|
||||
* @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
|
||||
* @table: offset profile per band.
|
||||
* @table_revision: 0 for not-South Korea, 1 for South Korea (the name is misleading)
|
||||
|
|
@ -475,7 +508,7 @@ struct iwl_geo_tx_power_profiles_cmd_v4 {
|
|||
} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_4 */
|
||||
|
||||
/**
|
||||
* struct iwl_geo_tx_power_profile_cmd_v5 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
|
||||
* struct iwl_geo_tx_power_profiles_cmd_v5 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
|
||||
* @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
|
||||
* @table: offset profile per band.
|
||||
* @table_revision: 0 for not-South Korea, 1 for South Korea (the name is misleading)
|
||||
|
|
@ -502,16 +535,46 @@ struct iwl_geo_tx_power_profiles_resp {
|
|||
__le32 profile_idx;
|
||||
} __packed; /* PER_CHAIN_LIMIT_OFFSET_RSP */
|
||||
|
||||
/**
|
||||
* enum iwl_ppag_flags - PPAG enable masks
|
||||
* @IWL_PPAG_ETSI_MASK: enable PPAG in ETSI
|
||||
* @IWL_PPAG_CHINA_MASK: enable PPAG in China
|
||||
* @IWL_PPAG_ETSI_LPI_UHB_MASK: enable LPI in ETSI for UHB
|
||||
* @IWL_PPAG_ETSI_VLP_UHB_MASK: enable VLP in ETSI for UHB
|
||||
* @IWL_PPAG_ETSI_SP_UHB_MASK: enable SP in ETSI for UHB
|
||||
* @IWL_PPAG_USA_LPI_UHB_MASK: enable LPI in USA for UHB
|
||||
* @IWL_PPAG_USA_VLP_UHB_MASK: enable VLP in USA for UHB
|
||||
* @IWL_PPAG_USA_SP_UHB_MASK: enable SP in USA for UHB
|
||||
* @IWL_PPAG_CANADA_LPI_UHB_MASK: enable LPI in CANADA for UHB
|
||||
* @IWL_PPAG_CANADA_VLP_UHB_MASK: enable VLP in CANADA for UHB
|
||||
* @IWL_PPAG_CANADA_SP_UHB_MASK: enable SP in CANADA for UHB
|
||||
*/
|
||||
enum iwl_ppag_flags {
|
||||
IWL_PPAG_ETSI_MASK = BIT(0),
|
||||
IWL_PPAG_CHINA_MASK = BIT(1),
|
||||
IWL_PPAG_ETSI_LPI_UHB_MASK = BIT(2),
|
||||
IWL_PPAG_ETSI_VLP_UHB_MASK = BIT(3),
|
||||
IWL_PPAG_ETSI_SP_UHB_MASK = BIT(4),
|
||||
IWL_PPAG_USA_LPI_UHB_MASK = BIT(5),
|
||||
IWL_PPAG_USA_VLP_UHB_MASK = BIT(6),
|
||||
IWL_PPAG_USA_SP_UHB_MASK = BIT(7),
|
||||
IWL_PPAG_CANADA_LPI_UHB_MASK = BIT(8),
|
||||
IWL_PPAG_CANADA_VLP_UHB_MASK = BIT(9),
|
||||
IWL_PPAG_CANADA_SP_UHB_MASK = BIT(10),
|
||||
};
|
||||
|
||||
/**
|
||||
* union iwl_ppag_table_cmd - union for all versions of PPAG command
|
||||
* @v1: version 1
|
||||
* @v2: version 2
|
||||
*
|
||||
* @flags: bit 0 - indicates enablement of PPAG for ETSI
|
||||
* bit 1 - indicates enablement of PPAG for CHINA BIOS
|
||||
* bit 1 can be used only in v3 (identical to v2)
|
||||
* @gain: table of antenna gain values per chain and sub-band
|
||||
* @reserved: reserved
|
||||
* version 3, 4, 5 and 6 are the same structure as v2,
|
||||
* but has a different format of the flags bitmap
|
||||
* @v1.flags: values from &enum iwl_ppag_flags
|
||||
* @v1.gain: table of antenna gain values per chain and sub-band
|
||||
* @v1.reserved: reserved
|
||||
* @v2.flags: values from &enum iwl_ppag_flags
|
||||
* @v2.gain: table of antenna gain values per chain and sub-band
|
||||
* @v2.reserved: reserved
|
||||
*/
|
||||
union iwl_ppag_table_cmd {
|
||||
struct {
|
||||
|
|
@ -526,6 +589,11 @@ union iwl_ppag_table_cmd {
|
|||
} v2;
|
||||
} __packed;
|
||||
|
||||
#define IWL_PPAG_CMD_V4_MASK (IWL_PPAG_ETSI_MASK | IWL_PPAG_CHINA_MASK)
|
||||
#define IWL_PPAG_CMD_V5_MASK (IWL_PPAG_CMD_V4_MASK | \
|
||||
IWL_PPAG_ETSI_LPI_UHB_MASK | \
|
||||
IWL_PPAG_USA_LPI_UHB_MASK)
|
||||
|
||||
#define MCC_TO_SAR_OFFSET_TABLE_ROW_SIZE 26
|
||||
#define MCC_TO_SAR_OFFSET_TABLE_COL_SIZE 13
|
||||
|
||||
|
|
@ -667,4 +735,44 @@ struct iwl_beacon_filter_cmd {
|
|||
|
||||
#define IWL_BF_CMD_CONFIG_DEFAULTS IWL_BF_CMD_CONFIG(_DEFAULT)
|
||||
#define IWL_BF_CMD_CONFIG_D0I3 IWL_BF_CMD_CONFIG(_D0I3)
|
||||
|
||||
#define DEFAULT_TPE_TX_POWER 0x7F
|
||||
|
||||
/*
|
||||
* Bandwidth: 20/40/80/(160/80+80)/320
|
||||
*/
|
||||
#define IWL_MAX_TX_EIRP_PWR_MAX_SIZE 5
|
||||
#define IWL_MAX_TX_EIRP_PSD_PWR_MAX_SIZE 16
|
||||
|
||||
enum iwl_6ghz_ap_type {
|
||||
IWL_6GHZ_AP_TYPE_LPI,
|
||||
IWL_6GHZ_AP_TYPE_SP,
|
||||
IWL_6GHZ_AP_TYPE_VLP,
|
||||
}; /* PHY_AP_TYPE_API_E_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_txpower_constraints_cmd
|
||||
* AP_TX_POWER_CONSTRAINTS_CMD
|
||||
* Used for VLP/LPI/AFC Access Point power constraints for 6GHz channels
|
||||
* @link_id: linkId
|
||||
* @ap_type: see &enum iwl_ap_type
|
||||
* @eirp_pwr: 8-bit 2s complement signed integer in the range
|
||||
* -64 dBm to 63 dBm with a 0.5 dB step
|
||||
* default &DEFAULT_TPE_TX_POWER (no maximum limit)
|
||||
* @psd_pwr: 8-bit 2s complement signed integer in the range
|
||||
* -63.5 to +63 dBm/MHz with a 0.5 step
|
||||
* value - 128 indicates that the corresponding 20
|
||||
* MHz channel cannot be used for transmission.
|
||||
* value +127 indicates that no maximum PSD limit
|
||||
* is specified for the corresponding 20 MHz channel
|
||||
* default &DEFAULT_TPE_TX_POWER (no maximum limit)
|
||||
* @reserved: reserved (padding)
|
||||
*/
|
||||
struct iwl_txpower_constraints_cmd {
|
||||
__le16 link_id;
|
||||
__le16 ap_type;
|
||||
__s8 eirp_pwr[IWL_MAX_TX_EIRP_PWR_MAX_SIZE];
|
||||
__s8 psd_pwr[IWL_MAX_TX_EIRP_PSD_PWR_MAX_SIZE];
|
||||
u8 reserved[3];
|
||||
} __packed; /* PHY_AP_TX_POWER_CONSTRAINTS_CMD_API_S_VER_1 */
|
||||
#endif /* __iwl_fw_api_power_h__ */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2020-2021 Intel Corporation
|
||||
* Copyright (C) 2020-2021, 2023 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_fw_api_rfi_h__
|
||||
#define __iwl_fw_api_rfi_h__
|
||||
|
|
@ -25,8 +25,9 @@ struct iwl_rfi_lut_entry {
|
|||
/**
|
||||
* struct iwl_rfi_config_cmd - RFI configuration table
|
||||
*
|
||||
* @entry: a table can have 24 frequency/channel mappings
|
||||
* @table: a table can have 24 frequency/channel mappings
|
||||
* @oem: specifies if this is the default table or set by OEM
|
||||
* @reserved: (reserved/padding)
|
||||
*/
|
||||
struct iwl_rfi_config_cmd {
|
||||
struct iwl_rfi_lut_entry table[IWL_RFI_LUT_SIZE];
|
||||
|
|
@ -35,7 +36,7 @@ struct iwl_rfi_config_cmd {
|
|||
} __packed; /* RFI_CONFIG_CMD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* iwl_rfi_freq_table_status - status of the frequency table query
|
||||
* enum iwl_rfi_freq_table_status - status of the frequency table query
|
||||
* @RFI_FREQ_TABLE_OK: can be used
|
||||
* @RFI_FREQ_TABLE_DVFS_NOT_READY: DVFS is not ready yet, should try later
|
||||
* @RFI_FREQ_TABLE_DISABLED: the feature is disabled in FW
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2022, 2024 Intel Corporation
|
||||
* Copyright (C) 2017 Intel Deutschland GmbH
|
||||
*/
|
||||
#ifndef __iwl_fw_api_rs_h__
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
#include "mac.h"
|
||||
|
||||
/**
|
||||
* enum iwl_tlc_mng_cfg_flags_enum - options for TLC config flags
|
||||
* enum iwl_tlc_mng_cfg_flags - options for TLC config flags
|
||||
* @IWL_TLC_MNG_CFG_FLAGS_STBC_MSK: enable STBC. For HE this enables STBC for
|
||||
* bandwidths <= 80MHz
|
||||
* @IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK: enable LDPC
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -374,7 +374,7 @@ enum iwl_rx_phy_eht_data1 {
|
|||
IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B1_B7 = 0x0000fe00,
|
||||
};
|
||||
|
||||
/* goes into Metadata DW 7 */
|
||||
/* goes into Metadata DW 7 (Qu) or 8 (So or higher) */
|
||||
enum iwl_rx_phy_he_data2 {
|
||||
/* info type: HE MU-EXT */
|
||||
/* the a1/a2/... is what the PHY/firmware calls the values */
|
||||
|
|
@ -390,7 +390,7 @@ enum iwl_rx_phy_he_data2 {
|
|||
IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE4 = 0x0000f000,
|
||||
};
|
||||
|
||||
/* goes into Metadata DW 8 */
|
||||
/* goes into Metadata DW 8 (Qu) or 7 (So or higher) */
|
||||
enum iwl_rx_phy_he_data3 {
|
||||
/* info type: HE MU-EXT */
|
||||
IWL_RX_PHY_DATA3_HE_MU_EXT_CH1_RU1 = 0x000000ff, /* c1 */
|
||||
|
|
@ -411,10 +411,9 @@ enum iwl_rx_phy_he_he_data4 {
|
|||
IWL_RX_PHY_DATA4_HE_MU_EXT_PREAMBLE_PUNC_TYPE_MASK = 0x0600,
|
||||
};
|
||||
|
||||
/* goes into Metadata DW 7 */
|
||||
/* goes into Metadata DW 8 (Qu has no EHT) */
|
||||
enum iwl_rx_phy_eht_data2 {
|
||||
/* info type: EHT-MU-EXT */
|
||||
/* OFDM_RX_VECTOR_COMMON_RU_ALLOC_0_OUT */
|
||||
IWL_RX_PHY_DATA2_EHT_MU_EXT_RU_ALLOC_A1 = 0x000001ff,
|
||||
IWL_RX_PHY_DATA2_EHT_MU_EXT_RU_ALLOC_A2 = 0x0003fe00,
|
||||
IWL_RX_PHY_DATA2_EHT_MU_EXT_RU_ALLOC_B1 = 0x07fc0000,
|
||||
|
|
@ -423,11 +422,10 @@ enum iwl_rx_phy_eht_data2 {
|
|||
IWL_RX_PHY_DATA2_EHT_TB_EXT_TRIG_SIGA1 = 0xffffffff,
|
||||
};
|
||||
|
||||
/* goes into Metadata DW 8 */
|
||||
/* goes into Metadata DW 7 (Qu has no EHT) */
|
||||
enum iwl_rx_phy_eht_data3 {
|
||||
/* note: low 8 bits cannot be used */
|
||||
/* info type: EHT-MU-EXT */
|
||||
/* OFDM_RX_VECTOR_COMMON_RU_ALLOC_1_OUT */
|
||||
IWL_RX_PHY_DATA3_EHT_MU_EXT_RU_ALLOC_B2 = 0x000001ff,
|
||||
IWL_RX_PHY_DATA3_EHT_MU_EXT_RU_ALLOC_C1 = 0x0003fe00,
|
||||
IWL_RX_PHY_DATA3_EHT_MU_EXT_RU_ALLOC_C2 = 0x07fc0000,
|
||||
};
|
||||
|
|
@ -435,10 +433,10 @@ enum iwl_rx_phy_eht_data3 {
|
|||
/* goes into Metadata DW 4 */
|
||||
enum iwl_rx_phy_eht_data4 {
|
||||
/* info type: EHT-MU-EXT */
|
||||
/* OFDM_RX_VECTOR_COMMON_RU_ALLOC_2_OUT */
|
||||
IWL_RX_PHY_DATA4_EHT_MU_EXT_RU_ALLOC_D1 = 0x000001ff,
|
||||
IWL_RX_PHY_DATA4_EHT_MU_EXT_RU_ALLOC_D2 = 0x0003fe00,
|
||||
IWL_RX_PHY_DATA4_EHT_MU_EXT_SIGB_MCS = 0x000c0000,
|
||||
IWL_RX_PHY_DATA4_EHT_MU_EXT_RU_ALLOC_B2 = 0x1ff00000,
|
||||
};
|
||||
|
||||
/* goes into Metadata DW 16 */
|
||||
|
|
@ -715,7 +713,15 @@ struct iwl_rx_mpdu_desc {
|
|||
__le32 reorder_data;
|
||||
|
||||
union {
|
||||
/**
|
||||
* @v1: version 1 of the remaining RX descriptor,
|
||||
* see &struct iwl_rx_mpdu_desc_v1
|
||||
*/
|
||||
struct iwl_rx_mpdu_desc_v1 v1;
|
||||
/**
|
||||
* @v3: version 3 of the remaining RX descriptor,
|
||||
* see &struct iwl_rx_mpdu_desc_v3
|
||||
*/
|
||||
struct iwl_rx_mpdu_desc_v3 v3;
|
||||
};
|
||||
} __packed; /* RX_MPDU_RES_START_API_S_VER_3,
|
||||
|
|
@ -989,7 +995,7 @@ struct iwl_ba_window_status_notif {
|
|||
} __packed; /* BA_WINDOW_STATUS_NTFY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_rfh_queue_config - RX queue configuration
|
||||
* struct iwl_rfh_queue_data - RX queue configuration
|
||||
* @q_num: Q num
|
||||
* @enable: enable queue
|
||||
* @reserved: alignment
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -13,6 +13,10 @@
|
|||
* enum iwl_scan_subcmd_ids - scan commands
|
||||
*/
|
||||
enum iwl_scan_subcmd_ids {
|
||||
/**
|
||||
* @CHANNEL_SURVEY_NOTIF: &struct iwl_umac_scan_channel_survey_notif
|
||||
*/
|
||||
CHANNEL_SURVEY_NOTIF = 0xFB,
|
||||
/**
|
||||
* @OFFLOAD_MATCH_INFO_NOTIF: &struct iwl_scan_offload_match_info
|
||||
*/
|
||||
|
|
@ -62,6 +66,8 @@ struct iwl_ssid_ie {
|
|||
#define IWL_FAST_SCHED_SCAN_ITERATIONS 3
|
||||
#define IWL_MAX_SCHED_SCAN_PLANS 2
|
||||
|
||||
#define IWL_MAX_NUM_NOISE_RESULTS 22
|
||||
|
||||
enum scan_framework_client {
|
||||
SCAN_CLIENT_SCHED_SCAN = BIT(0),
|
||||
SCAN_CLIENT_NETDETECT = BIT(1),
|
||||
|
|
@ -143,7 +149,7 @@ struct iwl_scan_offload_profile_cfg_data {
|
|||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_scan_offload_profile_cfg
|
||||
* struct iwl_scan_offload_profile_cfg_v1 - scan offload profile config
|
||||
* @profiles: profiles to search for match
|
||||
* @data: the rest of the data for profile_cfg
|
||||
*/
|
||||
|
|
@ -417,7 +423,7 @@ struct iwl_lmac_scan_complete_notif {
|
|||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_scan_offload_complete - PERIODIC_SCAN_COMPLETE_NTF_API_S_VER_2
|
||||
* struct iwl_periodic_scan_complete - PERIODIC_SCAN_COMPLETE_NTF_API_S_VER_2
|
||||
* @last_schedule_line: last schedule line executed (fast or regular)
|
||||
* @last_schedule_iteration: last scan iteration executed before scan abort
|
||||
* @status: &enum iwl_scan_offload_complete_status
|
||||
|
|
@ -437,10 +443,10 @@ struct iwl_periodic_scan_complete {
|
|||
/* UMAC Scan API */
|
||||
|
||||
/* The maximum of either of these cannot exceed 8, because we use an
|
||||
* 8-bit mask (see IWL_MVM_SCAN_MASK in mvm.h).
|
||||
* 8-bit mask (see enum iwl_scan_status).
|
||||
*/
|
||||
#define IWL_MVM_MAX_UMAC_SCANS 4
|
||||
#define IWL_MVM_MAX_LMAC_SCANS 1
|
||||
#define IWL_MAX_UMAC_SCANS 4
|
||||
#define IWL_MAX_LMAC_SCANS 1
|
||||
|
||||
enum scan_config_flags {
|
||||
SCAN_CONFIG_FLAG_ACTIVATE = BIT(0),
|
||||
|
|
@ -642,10 +648,13 @@ enum iwl_umac_scan_general_flags {
|
|||
* notification per channel or not.
|
||||
* @IWL_UMAC_SCAN_GEN_FLAGS2_ALLOW_CHNL_REORDER: Whether to allow channel
|
||||
* reorder optimization or not.
|
||||
* @IWL_UMAC_SCAN_GEN_FLAGS2_COLLECT_CHANNEL_STATS: Enable channel statistics
|
||||
* collection when #IWL_UMAC_SCAN_GEN_FLAGS_V2_FORCE_PASSIVE is set.
|
||||
*/
|
||||
enum iwl_umac_scan_general_flags2 {
|
||||
IWL_UMAC_SCAN_GEN_FLAGS2_NOTIF_PER_CHNL = BIT(0),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS2_ALLOW_CHNL_REORDER = BIT(1),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS2_COLLECT_CHANNEL_STATS = BIT(3),
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -780,7 +789,7 @@ struct iwl_scan_req_umac_tail_v1 {
|
|||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_scan_req_umac_tail - the rest of the UMAC scan request command
|
||||
* struct iwl_scan_req_umac_tail_v2 - the rest of the UMAC scan request command
|
||||
* parameters following channels configuration array.
|
||||
* @schedule: two scheduling plans.
|
||||
* @delay: delay in TUs before starting the first scan iteration
|
||||
|
|
@ -1076,7 +1085,7 @@ struct iwl_scan_req_params_v12 {
|
|||
} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_12 */
|
||||
|
||||
/**
|
||||
* struct iwl_scan_req_params_v16
|
||||
* struct iwl_scan_req_params_v17 - scan request parameters (v17)
|
||||
* @general_params: &struct iwl_scan_general_params_v11
|
||||
* @channel_params: &struct iwl_scan_channel_params_v7
|
||||
* @periodic_params: &struct iwl_scan_periodic_parms_v1
|
||||
|
|
@ -1102,7 +1111,7 @@ struct iwl_scan_req_umac_v12 {
|
|||
} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_12 */
|
||||
|
||||
/**
|
||||
* struct iwl_scan_req_umac_v16
|
||||
* struct iwl_scan_req_umac_v17 - scan request command (v17)
|
||||
* @uid: scan id, &enum iwl_umac_scan_uid_offsets
|
||||
* @ooc_priority: out of channel priority - &enum iwl_scan_priority
|
||||
* @scan_params: scan parameters
|
||||
|
|
@ -1258,4 +1267,26 @@ struct iwl_umac_scan_iter_complete_notif {
|
|||
struct iwl_scan_results_notif results[];
|
||||
} __packed; /* SCAN_ITER_COMPLETE_NTF_UMAC_API_S_VER_2 */
|
||||
|
||||
/**
|
||||
* struct iwl_umac_scan_channel_survey_notif - data for survey
|
||||
* @channel: the channel scanned
|
||||
* @band: band of channel
|
||||
* @noise: noise floor measurements in negative dBm, invalid 0xff
|
||||
* @reserved: for future use and alignment
|
||||
* @active_time: time in ms the radio was turned on (on the channel)
|
||||
* @busy_time: time in ms the channel was sensed busy, 0 for a clean channel
|
||||
* @tx_time: time the radio spent transmitting data
|
||||
* @rx_time: time the radio spent receiving data
|
||||
*/
|
||||
struct iwl_umac_scan_channel_survey_notif {
|
||||
__le32 channel;
|
||||
__le32 band;
|
||||
u8 noise[IWL_MAX_NUM_NOISE_RESULTS];
|
||||
u8 reserved[2];
|
||||
__le32 active_time;
|
||||
__le32 busy_time;
|
||||
__le32 tx_time;
|
||||
__le32 rx_time;
|
||||
} __packed; /* SCAN_CHANNEL_SURVEY_NTF_API_S_VER_1 */
|
||||
|
||||
#endif /* __iwl_fw_api_scan_h__ */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2021 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2021, 2023 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -109,6 +109,7 @@ enum iwl_sta_flags {
|
|||
* @STA_KEY_FLG_EN_MSK: mask for encryption algorithmi value
|
||||
* @STA_KEY_FLG_WEP_KEY_MAP: wep is either a group key (0 - legacy WEP) or from
|
||||
* station info array (1 - n 1X mode)
|
||||
* @STA_KEY_FLG_AMSDU_SPP: SPP (signaling and payload protected) A-MSDU
|
||||
* @STA_KEY_FLG_KEYID_MSK: the index of the key
|
||||
* @STA_KEY_FLG_KEYID_POS: key index bit position
|
||||
* @STA_KEY_NOT_VALID: key is invalid
|
||||
|
|
@ -129,6 +130,7 @@ enum iwl_sta_key_flag {
|
|||
STA_KEY_FLG_EN_MSK = (7 << 0),
|
||||
|
||||
STA_KEY_FLG_WEP_KEY_MAP = BIT(3),
|
||||
STA_KEY_FLG_AMSDU_SPP = BIT(7),
|
||||
STA_KEY_FLG_KEYID_POS = 8,
|
||||
STA_KEY_FLG_KEYID_MSK = (3 << STA_KEY_FLG_KEYID_POS),
|
||||
STA_KEY_NOT_VALID = BIT(11),
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018, 2020 - 2021 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018, 2020 - 2021, 2023 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
#ifndef __iwl_fw_api_stats_h__
|
||||
#define __iwl_fw_api_stats_h__
|
||||
#include "mac.h"
|
||||
#include "mac-cfg.h"
|
||||
|
||||
struct mvm_statistics_dbg {
|
||||
__le32 burst_check;
|
||||
|
|
@ -411,6 +412,49 @@ struct iwl_statistics_cmd {
|
|||
|
||||
#define MAX_BCAST_FILTER_NUM 8
|
||||
|
||||
/**
|
||||
* enum iwl_statistics_notify_type_id - type_id used in system statistics
|
||||
* command
|
||||
* @IWL_STATS_NTFY_TYPE_ID_OPER: request legacy statistics
|
||||
* @IWL_STATS_NTFY_TYPE_ID_OPER_PART1: request operational part1 statistics
|
||||
* @IWL_STATS_NTFY_TYPE_ID_OPER_PART2: request operational part2 statistics
|
||||
* @IWL_STATS_NTFY_TYPE_ID_OPER_PART3: request operational part3 statistics
|
||||
* @IWL_STATS_NTFY_TYPE_ID_OPER_PART4: request operational part4 statistics
|
||||
*/
|
||||
enum iwl_statistics_notify_type_id {
|
||||
IWL_STATS_NTFY_TYPE_ID_OPER = BIT(0),
|
||||
IWL_STATS_NTFY_TYPE_ID_OPER_PART1 = BIT(1),
|
||||
IWL_STATS_NTFY_TYPE_ID_OPER_PART2 = BIT(2),
|
||||
IWL_STATS_NTFY_TYPE_ID_OPER_PART3 = BIT(3),
|
||||
IWL_STATS_NTFY_TYPE_ID_OPER_PART4 = BIT(4),
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_statistics_cfg_flags - cfg_mask used in system statistics command
|
||||
* @IWL_STATS_CFG_FLG_DISABLE_NTFY_MSK: 0 for enable, 1 for disable
|
||||
* @IWL_STATS_CFG_FLG_ON_DEMAND_NTFY_MSK: 0 for periodic, 1 for on-demand
|
||||
* @IWL_STATS_CFG_FLG_RESET_MSK: 0 for reset statistics after
|
||||
* sending the notification, 1 for do not reset statistics after sending
|
||||
* the notification
|
||||
*/
|
||||
enum iwl_statistics_cfg_flags {
|
||||
IWL_STATS_CFG_FLG_DISABLE_NTFY_MSK = BIT(0),
|
||||
IWL_STATS_CFG_FLG_ON_DEMAND_NTFY_MSK = BIT(1),
|
||||
IWL_STATS_CFG_FLG_RESET_MSK = BIT(2),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_system_statistics_cmd - system statistics command
|
||||
* @cfg_mask: configuration mask, &enum iwl_statistics_cfg_flags
|
||||
* @config_time_sec: time in sec for periodic notification
|
||||
* @type_id_mask: type_id masks, &enum iwl_statistics_notify_type_id
|
||||
*/
|
||||
struct iwl_system_statistics_cmd {
|
||||
__le32 cfg_mask;
|
||||
__le32 config_time_sec;
|
||||
__le32 type_id_mask;
|
||||
} __packed; /* STATISTICS_FW_CMD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_fw_statistics_type
|
||||
*
|
||||
|
|
@ -447,7 +491,49 @@ struct iwl_statistics_ntfy_hdr {
|
|||
}; /* STATISTICS_NTFY_HDR_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_statistics_ntfy_per_mac
|
||||
* struct iwl_stats_ntfy_per_link
|
||||
*
|
||||
* @beacon_filter_average_energy: Average energy [-dBm] of the 2
|
||||
* antennas.
|
||||
* @air_time: air time
|
||||
* @beacon_counter: all beacons (both filtered and not filtered)
|
||||
* @beacon_average_energy: Average energy [-dBm] of all beacons
|
||||
* (both filtered and not filtered)
|
||||
* @beacon_rssi_a: beacon RSSI on antenna A
|
||||
* @beacon_rssi_b: beacon RSSI on antenna B
|
||||
* @rx_bytes: RX byte count
|
||||
*/
|
||||
struct iwl_stats_ntfy_per_link {
|
||||
__le32 beacon_filter_average_energy;
|
||||
__le32 air_time;
|
||||
__le32 beacon_counter;
|
||||
__le32 beacon_average_energy;
|
||||
__le32 beacon_rssi_a;
|
||||
__le32 beacon_rssi_b;
|
||||
__le32 rx_bytes;
|
||||
} __packed; /* STATISTICS_NTFY_PER_LINK_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_stats_ntfy_part1_per_link
|
||||
*
|
||||
* @rx_time: rx time
|
||||
* @tx_time: tx time
|
||||
* @rx_action: action frames handled by FW
|
||||
* @tx_action: action frames generated and transmitted by FW
|
||||
* @cca_defers: cca defer count
|
||||
* @beacon_filtered: filtered out beacons
|
||||
*/
|
||||
struct iwl_stats_ntfy_part1_per_link {
|
||||
__le64 rx_time;
|
||||
__le64 tx_time;
|
||||
__le32 rx_action;
|
||||
__le32 tx_action;
|
||||
__le32 cca_defers;
|
||||
__le32 beacon_filtered;
|
||||
} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_PART1_PER_LINK_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_stats_ntfy_per_mac
|
||||
*
|
||||
* @beacon_filter_average_energy: Average energy [-dBm] of the 2
|
||||
* antennas.
|
||||
|
|
@ -459,7 +545,7 @@ struct iwl_statistics_ntfy_hdr {
|
|||
* @beacon_rssi_b: beacon RSSI on antenna B
|
||||
* @rx_bytes: RX byte count
|
||||
*/
|
||||
struct iwl_statistics_ntfy_per_mac {
|
||||
struct iwl_stats_ntfy_per_mac {
|
||||
__le32 beacon_filter_average_energy;
|
||||
__le32 air_time;
|
||||
__le32 beacon_counter;
|
||||
|
|
@ -470,7 +556,7 @@ struct iwl_statistics_ntfy_per_mac {
|
|||
} __packed; /* STATISTICS_NTFY_PER_MAC_API_S_VER_1 */
|
||||
|
||||
#define IWL_STATS_MAX_BW_INDEX 5
|
||||
/** struct iwl_statistics_ntfy_per_phy
|
||||
/** struct iwl_stats_ntfy_per_phy
|
||||
* @channel_load: channel load
|
||||
* @channel_load_by_us: device contribution to MCLM
|
||||
* @channel_load_not_by_us: other devices' contribution to MCLM
|
||||
|
|
@ -485,7 +571,7 @@ struct iwl_statistics_ntfy_per_mac {
|
|||
* per channel BW. note BACK counted as 1
|
||||
* @last_tx_ch_width_indx: last txed frame channel width index
|
||||
*/
|
||||
struct iwl_statistics_ntfy_per_phy {
|
||||
struct iwl_stats_ntfy_per_phy {
|
||||
__le32 channel_load;
|
||||
__le32 channel_load_by_us;
|
||||
__le32 channel_load_not_by_us;
|
||||
|
|
@ -499,23 +585,62 @@ struct iwl_statistics_ntfy_per_phy {
|
|||
} __packed; /* STATISTICS_NTFY_PER_PHY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_statistics_ntfy_per_sta
|
||||
* struct iwl_stats_ntfy_per_sta
|
||||
*
|
||||
* @average_energy: in fact it is minus the energy..
|
||||
*/
|
||||
struct iwl_statistics_ntfy_per_sta {
|
||||
struct iwl_stats_ntfy_per_sta {
|
||||
__le32 average_energy;
|
||||
} __packed; /* STATISTICS_NTFY_PER_STA_API_S_VER_1 */
|
||||
|
||||
#define IWL_STATS_MAX_PHY_OPERTINAL 3
|
||||
#define IWL_STATS_MAX_PHY_OPERATIONAL 3
|
||||
#define IWL_STATS_MAX_FW_LINKS (IWL_MVM_FW_MAX_LINK_ID + 1)
|
||||
|
||||
/**
|
||||
* struct iwl_system_statistics_notif_oper
|
||||
*
|
||||
* @time_stamp: time when the notification is sent from firmware
|
||||
* @per_link: per link statistics, &struct iwl_stats_ntfy_per_link
|
||||
* @per_phy: per phy statistics, &struct iwl_stats_ntfy_per_phy
|
||||
* @per_sta: per sta statistics, &struct iwl_stats_ntfy_per_sta
|
||||
*/
|
||||
struct iwl_system_statistics_notif_oper {
|
||||
__le32 time_stamp;
|
||||
struct iwl_stats_ntfy_per_link per_link[IWL_STATS_MAX_FW_LINKS];
|
||||
struct iwl_stats_ntfy_per_phy per_phy[IWL_STATS_MAX_PHY_OPERATIONAL];
|
||||
struct iwl_stats_ntfy_per_sta per_sta[IWL_MVM_STATION_COUNT_MAX];
|
||||
} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_API_S_VER_3 */
|
||||
|
||||
/**
|
||||
* struct iwl_system_statistics_part1_notif_oper
|
||||
*
|
||||
* @time_stamp: time when the notification is sent from firmware
|
||||
* @per_link: per link statistics &struct iwl_stats_ntfy_part1_per_link
|
||||
* @per_phy_crc_error_stats: per phy crc error statistics
|
||||
*/
|
||||
struct iwl_system_statistics_part1_notif_oper {
|
||||
__le32 time_stamp;
|
||||
struct iwl_stats_ntfy_part1_per_link per_link[IWL_STATS_MAX_FW_LINKS];
|
||||
__le32 per_phy_crc_error_stats[IWL_STATS_MAX_PHY_OPERATIONAL];
|
||||
} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_PART1_API_S_VER_4 */
|
||||
|
||||
/**
|
||||
* struct iwl_system_statistics_end_notif
|
||||
*
|
||||
* @time_stamp: time when the notification is sent from firmware
|
||||
*/
|
||||
struct iwl_system_statistics_end_notif {
|
||||
__le32 time_stamp;
|
||||
} __packed; /* STATISTICS_FW_NTFY_END_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_statistics_operational_ntfy
|
||||
*
|
||||
* @hdr: general statistics header
|
||||
* @flags: bitmap of possible notification structures
|
||||
* @per_mac_stats: per mac statistics, &struct iwl_statistics_ntfy_per_mac
|
||||
* @per_phy_stats: per phy statistics, &struct iwl_statistics_ntfy_per_phy
|
||||
* @per_sta_stats: per sta statistics, &struct iwl_statistics_ntfy_per_sta
|
||||
* @per_mac: per mac statistics, &struct iwl_stats_ntfy_per_mac
|
||||
* @per_phy: per phy statistics, &struct iwl_stats_ntfy_per_phy
|
||||
* @per_sta: per sta statistics, &struct iwl_stats_ntfy_per_sta
|
||||
* @rx_time: rx time
|
||||
* @tx_time: usec the radio is transmitting.
|
||||
* @on_time_rf: The total time in usec the RF is awake.
|
||||
|
|
@ -524,9 +649,9 @@ struct iwl_statistics_ntfy_per_sta {
|
|||
struct iwl_statistics_operational_ntfy {
|
||||
struct iwl_statistics_ntfy_hdr hdr;
|
||||
__le32 flags;
|
||||
struct iwl_statistics_ntfy_per_mac per_mac_stats[MAC_INDEX_AUX];
|
||||
struct iwl_statistics_ntfy_per_phy per_phy_stats[IWL_STATS_MAX_PHY_OPERTINAL];
|
||||
struct iwl_statistics_ntfy_per_sta per_sta_stats[IWL_MVM_STATION_COUNT_MAX];
|
||||
struct iwl_stats_ntfy_per_mac per_mac[MAC_INDEX_AUX];
|
||||
struct iwl_stats_ntfy_per_phy per_phy[IWL_STATS_MAX_PHY_OPERATIONAL];
|
||||
struct iwl_stats_ntfy_per_sta per_sta[IWL_MVM_STATION_COUNT_MAX];
|
||||
__le64 rx_time;
|
||||
__le64 tx_time;
|
||||
__le64 on_time_rf;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2020, 2022 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2020, 2022-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -335,6 +335,65 @@ struct iwl_hs20_roc_res {
|
|||
__le32 status;
|
||||
} __packed; /* HOT_SPOT_RSP_API_S_VER_1 */
|
||||
|
||||
/*
|
||||
* Activity types for the ROC command
|
||||
* @ROC_ACTIVITY_HOTSPOT: ROC for hs20 activity
|
||||
* @ROC_ACTIVITY_P2P_DISC: ROC for p2p discoverability activity
|
||||
* @ROC_ACTIVITY_P2P_TXRX: ROC for p2p action frames activity
|
||||
* @ROC_ACTIVITY_P2P_NEG: ROC for p2p negotiation (used also for TX)
|
||||
*/
|
||||
enum iwl_roc_activity {
|
||||
ROC_ACTIVITY_HOTSPOT,
|
||||
ROC_ACTIVITY_P2P_DISC,
|
||||
ROC_ACTIVITY_P2P_TXRX,
|
||||
ROC_ACTIVITY_P2P_NEG,
|
||||
ROC_NUM_ACTIVITIES
|
||||
}; /* ROC_ACTIVITY_API_E_VER_1 */
|
||||
|
||||
/*
|
||||
* ROC command
|
||||
*
|
||||
* Command requests the firmware to remain on a channel for a certain duration.
|
||||
*
|
||||
* ( MAC_CONF_GROUP 0x3, ROC_CMD 0xE )
|
||||
*
|
||||
* @action: action to perform, see &enum iwl_ctxt_action
|
||||
* @activity: type of activity, see &enum iwl_roc_activity
|
||||
* @sta_id: station id, resumed during "Remain On Channel" activity.
|
||||
* @channel_info: &struct iwl_fw_channel_info
|
||||
* @node_addr: node MAC address for Rx filtering
|
||||
* @reserved: align to a dword
|
||||
* @max_delay: max delay the ROC can start in TU
|
||||
* @duration: remain on channel duration in TU
|
||||
*/
|
||||
struct iwl_roc_req {
|
||||
__le32 action;
|
||||
__le32 activity;
|
||||
__le32 sta_id;
|
||||
struct iwl_fw_channel_info channel_info;
|
||||
u8 node_addr[ETH_ALEN];
|
||||
__le16 reserved;
|
||||
__le32 max_delay;
|
||||
__le32 duration;
|
||||
} __packed; /* ROC_CMD_API_S_VER_3 */
|
||||
|
||||
/*
|
||||
* ROC notification
|
||||
*
|
||||
* Notification when ROC startes and when ROC ended.
|
||||
*
|
||||
* ( MAC_CONF_GROUP 0x3, ROC_NOTIF 0xf8 )
|
||||
*
|
||||
* @status: true if ROC succeeded to start
|
||||
* @start_end: true if ROC started, false if ROC ended
|
||||
* @activity: notification to which activity - &enum iwl_roc_activity
|
||||
*/
|
||||
struct iwl_roc_notif {
|
||||
__le32 success;
|
||||
__le32 started;
|
||||
__le32 activity;
|
||||
} __packed; /* ROC_NOTIF_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_mvm_session_prot_conf_id - session protection's configurations
|
||||
* @SESSION_PROTECT_CONF_ASSOC: Start a session protection for association.
|
||||
|
|
@ -375,8 +434,8 @@ enum iwl_mvm_session_prot_conf_id {
|
|||
|
||||
/**
|
||||
* struct iwl_mvm_session_prot_cmd - configure a session protection
|
||||
* @id_and_color: the id and color of the mac for which this session protection
|
||||
* is sent
|
||||
* @id_and_color: the id and color of the link (or mac, for command version 1)
|
||||
* for which this session protection is sent
|
||||
* @action: can be either FW_CTXT_ACTION_ADD or FW_CTXT_ACTION_REMOVE,
|
||||
* see &enum iwl_ctxt_action
|
||||
* @conf_id: see &enum iwl_mvm_session_prot_conf_id
|
||||
|
|
@ -397,11 +456,15 @@ struct iwl_mvm_session_prot_cmd {
|
|||
__le32 duration_tu;
|
||||
__le32 repetition_count;
|
||||
__le32 interval;
|
||||
} __packed; /* SESSION_PROTECTION_CMD_API_S_VER_1 */
|
||||
} __packed;
|
||||
/* SESSION_PROTECTION_CMD_API_S_VER_1 and
|
||||
* SESSION_PROTECTION_CMD_API_S_VER_2
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_session_prot_notif - session protection started / ended
|
||||
* @mac_id: the mac id for which the session protection started / ended
|
||||
* @mac_link_id: the mac id (or link id, for notif ver > 2) for which the
|
||||
* session protection started / ended
|
||||
* @status: 1 means success, 0 means failure
|
||||
* @start: 1 means the session protection started, 0 means it ended
|
||||
* @conf_id: see &enum iwl_mvm_session_prot_conf_id
|
||||
|
|
@ -410,10 +473,13 @@ struct iwl_mvm_session_prot_cmd {
|
|||
* and end even the firmware could not schedule it.
|
||||
*/
|
||||
struct iwl_mvm_session_prot_notif {
|
||||
__le32 mac_id;
|
||||
__le32 mac_link_id;
|
||||
__le32 status;
|
||||
__le32 start;
|
||||
__le32 conf_id;
|
||||
} __packed; /* SESSION_PROTECTION_NOTIFICATION_API_S_VER_2 */
|
||||
} __packed;
|
||||
/* SESSION_PROTECTION_NOTIFICATION_API_S_VER_2 and
|
||||
* SESSION_PROTECTION_NOTIFICATION_API_S_VER_3
|
||||
*/
|
||||
|
||||
#endif /* __iwl_fw_api_time_event_h__ */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
#ifndef __iwl_fw_api_tx_h__
|
||||
|
|
@ -76,6 +76,8 @@ enum iwl_tx_flags {
|
|||
* to a secured STA
|
||||
* @IWL_TX_FLAGS_HIGH_PRI: high priority frame (like EAPOL) - can affect rate
|
||||
* selection, retry limits and BT kill
|
||||
* @IWL_TX_FLAGS_RTS: firmware used an RTS
|
||||
* @IWL_TX_FLAGS_CTS: firmware used CTS-to-self
|
||||
*/
|
||||
enum iwl_tx_cmd_flags {
|
||||
IWL_TX_FLAGS_CMD_RATE = BIT(0),
|
||||
|
|
@ -696,6 +698,7 @@ enum iwl_mvm_ba_resp_flags {
|
|||
* @query_frame_cnt: SCD query frame count
|
||||
* @txed: number of frames sent in the aggregation (all-TIDs)
|
||||
* @done: number of frames that were Acked by the BA (all-TIDs)
|
||||
* @rts_retry_cnt: RTS retry count
|
||||
* @reserved: reserved (for alignment)
|
||||
* @wireless_time: Wireless-media time
|
||||
* @tx_rate: the rate the aggregation was sent at
|
||||
|
|
@ -716,7 +719,8 @@ struct iwl_mvm_compressed_ba_notif {
|
|||
__le16 query_frame_cnt;
|
||||
__le16 txed;
|
||||
__le16 done;
|
||||
__le16 reserved;
|
||||
u8 rts_retry_cnt;
|
||||
u8 reserved;
|
||||
__le32 wireless_time;
|
||||
__le32 tx_rate;
|
||||
__le16 tfd_cnt;
|
||||
|
|
@ -791,7 +795,8 @@ enum iwl_mac_beacon_flags {
|
|||
* @reserved: reserved
|
||||
* @link_id: the firmware id of the link that will use this beacon
|
||||
* @tim_idx: the offset of the tim IE in the beacon
|
||||
* @tim_size: the length of the tim IE
|
||||
* @tim_size: the length of the tim IE (version < 14)
|
||||
* @btwt_offset: offset to the broadcast TWT IE if present (version >= 14)
|
||||
* @ecsa_offset: offset to the ECSA IE if present
|
||||
* @csa_offset: offset to the CSA IE if present
|
||||
* @frame: the template of the beacon frame
|
||||
|
|
@ -803,14 +808,18 @@ struct iwl_mac_beacon_cmd {
|
|||
__le32 reserved;
|
||||
__le32 link_id;
|
||||
__le32 tim_idx;
|
||||
__le32 tim_size;
|
||||
union {
|
||||
__le32 tim_size;
|
||||
__le32 btwt_offset;
|
||||
};
|
||||
__le32 ecsa_offset;
|
||||
__le32 csa_offset;
|
||||
struct ieee80211_hdr frame[];
|
||||
} __packed; /* BEACON_TEMPLATE_CMD_API_S_VER_10,
|
||||
* BEACON_TEMPLATE_CMD_API_S_VER_11,
|
||||
* BEACON_TEMPLATE_CMD_API_S_VER_12,
|
||||
* BEACON_TEMPLATE_CMD_API_S_VER_13
|
||||
* BEACON_TEMPLATE_CMD_API_S_VER_13,
|
||||
* BEACON_TEMPLATE_CMD_API_S_VER_14
|
||||
*/
|
||||
|
||||
struct iwl_beacon_notif {
|
||||
|
|
@ -857,7 +866,7 @@ enum iwl_dump_control {
|
|||
};
|
||||
|
||||
/**
|
||||
* struct iwl_tx_path_flush_cmd -- queue/FIFO flush command
|
||||
* struct iwl_tx_path_flush_cmd_v1 -- queue/FIFO flush command
|
||||
* @queues_ctl: bitmap of queues to flush
|
||||
* @flush_ctl: control flags
|
||||
* @reserved: reserved
|
||||
|
|
@ -884,6 +893,7 @@ struct iwl_tx_path_flush_cmd {
|
|||
|
||||
/**
|
||||
* struct iwl_flush_queue_info - virtual flush queue info
|
||||
* @tid: the tid to flush
|
||||
* @queue_num: virtual queue id
|
||||
* @read_before_flush: read pointer before flush
|
||||
* @read_after_flush: read pointer after flush
|
||||
|
|
@ -897,6 +907,7 @@ struct iwl_flush_queue_info {
|
|||
|
||||
/**
|
||||
* struct iwl_tx_path_flush_cmd_rsp -- queue/FIFO flush command response
|
||||
* @sta_id: the station for which the queue was flushed
|
||||
* @num_flushed_queues: number of queues in queues array
|
||||
* @queues: all flushed queues
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2019-2021 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2019-2021, 2023-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -66,6 +66,16 @@ enum iwl_gen2_tx_fifo {
|
|||
IWL_GEN2_TRIG_TX_FIFO_VO,
|
||||
};
|
||||
|
||||
enum iwl_bz_tx_fifo {
|
||||
IWL_BZ_EDCA_TX_FIFO_BK,
|
||||
IWL_BZ_EDCA_TX_FIFO_BE,
|
||||
IWL_BZ_EDCA_TX_FIFO_VI,
|
||||
IWL_BZ_EDCA_TX_FIFO_VO,
|
||||
IWL_BZ_TRIG_TX_FIFO_BK,
|
||||
IWL_BZ_TRIG_TX_FIFO_BE,
|
||||
IWL_BZ_TRIG_TX_FIFO_VI,
|
||||
IWL_BZ_TRIG_TX_FIFO_VO,
|
||||
};
|
||||
/**
|
||||
* enum iwl_tx_queue_cfg_actions - TXQ config options
|
||||
* @TX_QUEUE_CFG_ENABLE_QUEUE: enable a queue
|
||||
|
|
@ -76,7 +86,7 @@ enum iwl_tx_queue_cfg_actions {
|
|||
TX_QUEUE_CFG_TFD_SHORT_FORMAT = BIT(1),
|
||||
};
|
||||
|
||||
#define IWL_DEFAULT_QUEUE_SIZE_EHT (1024 * 4)
|
||||
#define IWL_DEFAULT_QUEUE_SIZE_EHT (512 * 4)
|
||||
#define IWL_DEFAULT_QUEUE_SIZE_HE 1024
|
||||
#define IWL_DEFAULT_QUEUE_SIZE 256
|
||||
#define IWL_MGMT_QUEUE_SIZE 16
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -22,7 +22,6 @@
|
|||
* @fwrt_ptr: pointer to the buffer coming from fwrt
|
||||
* @trans_ptr: pointer to struct %iwl_trans_dump_data which contains the
|
||||
* transport's data.
|
||||
* @trans_len: length of the valid data in trans_ptr
|
||||
* @fwrt_len: length of the valid data in fwrt_ptr
|
||||
*/
|
||||
struct iwl_fw_dump_ptrs {
|
||||
|
|
@ -883,14 +882,14 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
|
|||
cpu_to_le32(fwrt->trans->hw_rev_step);
|
||||
memcpy(dump_info->fw_human_readable, fwrt->fw->human_readable,
|
||||
sizeof(dump_info->fw_human_readable));
|
||||
strncpy(dump_info->dev_human_readable, fwrt->trans->name,
|
||||
sizeof(dump_info->dev_human_readable) - 1);
|
||||
strscpy_pad(dump_info->dev_human_readable, fwrt->trans->name,
|
||||
sizeof(dump_info->dev_human_readable));
|
||||
#if defined(__linux__)
|
||||
strncpy(dump_info->bus_human_readable, fwrt->dev->bus->name,
|
||||
sizeof(dump_info->bus_human_readable) - 1);
|
||||
strscpy_pad(dump_info->bus_human_readable, fwrt->dev->bus->name,
|
||||
sizeof(dump_info->bus_human_readable));
|
||||
#elif defined(__FreeBSD__) /* XXX TODO */
|
||||
strncpy(dump_info->bus_human_readable, "<bus>",
|
||||
sizeof(dump_info->bus_human_readable) - 1);
|
||||
strscpy_pad(dump_info->bus_human_readable, "<bus>",
|
||||
sizeof(dump_info->bus_human_readable));
|
||||
#endif
|
||||
dump_info->num_of_lmacs = fwrt->smem_cfg.num_lmacs;
|
||||
dump_info->lmac_err_id[0] =
|
||||
|
|
@ -1029,64 +1028,78 @@ struct iwl_dump_ini_region_data {
|
|||
struct iwl_fwrt_dump_data *dump_data;
|
||||
};
|
||||
|
||||
static int iwl_dump_ini_prph_mac_iter_common(struct iwl_fw_runtime *fwrt,
|
||||
void *range_ptr, u32 addr,
|
||||
__le32 size)
|
||||
{
|
||||
struct iwl_fw_ini_error_dump_range *range = range_ptr;
|
||||
__le32 *val = range->data;
|
||||
int i;
|
||||
|
||||
range->internal_base_addr = cpu_to_le32(addr);
|
||||
range->range_data_size = size;
|
||||
for (i = 0; i < le32_to_cpu(size); i += 4)
|
||||
*val++ = cpu_to_le32(iwl_read_prph(fwrt->trans, addr + i));
|
||||
|
||||
return sizeof(*range) + le32_to_cpu(range->range_data_size);
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_dump_ini_prph_mac_iter(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data,
|
||||
void *range_ptr, u32 range_len, int idx)
|
||||
{
|
||||
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
|
||||
struct iwl_fw_ini_error_dump_range *range = range_ptr;
|
||||
__le32 *val = range->data;
|
||||
u32 prph_val;
|
||||
u32 addr = le32_to_cpu(reg->addrs[idx]) +
|
||||
le32_to_cpu(reg->dev_addr.offset);
|
||||
int i;
|
||||
|
||||
range->internal_base_addr = cpu_to_le32(addr);
|
||||
range->range_data_size = reg->dev_addr.size;
|
||||
for (i = 0; i < le32_to_cpu(reg->dev_addr.size); i += 4) {
|
||||
prph_val = iwl_read_prph(fwrt->trans, addr + i);
|
||||
if (iwl_trans_is_hw_error_value(prph_val))
|
||||
return -EBUSY;
|
||||
*val++ = cpu_to_le32(prph_val);
|
||||
}
|
||||
|
||||
return sizeof(*range) + le32_to_cpu(range->range_data_size);
|
||||
return iwl_dump_ini_prph_mac_iter_common(fwrt, range_ptr, addr,
|
||||
reg->dev_addr.size);
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_dump_ini_prph_phy_iter(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data,
|
||||
void *range_ptr, u32 range_len, int idx)
|
||||
iwl_dump_ini_prph_mac_block_iter(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data,
|
||||
void *range_ptr, u32 range_len, int idx)
|
||||
{
|
||||
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
|
||||
struct iwl_fw_ini_addr_size *pairs = (void *)reg->addrs;
|
||||
u32 addr = le32_to_cpu(reg->dev_addr_range.offset) +
|
||||
le32_to_cpu(pairs[idx].addr);
|
||||
|
||||
return iwl_dump_ini_prph_mac_iter_common(fwrt, range_ptr, addr,
|
||||
pairs[idx].size);
|
||||
}
|
||||
|
||||
static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt,
|
||||
void *range_ptr, u32 addr,
|
||||
__le32 size, __le32 offset)
|
||||
{
|
||||
struct iwl_fw_ini_error_dump_range *range = range_ptr;
|
||||
__le32 *val = range->data;
|
||||
u32 indirect_wr_addr = WMAL_INDRCT_RD_CMD1;
|
||||
u32 indirect_rd_addr = WMAL_MRSPF_1;
|
||||
u32 prph_val;
|
||||
u32 addr = le32_to_cpu(reg->addrs[idx]);
|
||||
u32 dphy_state;
|
||||
u32 dphy_addr;
|
||||
int i;
|
||||
|
||||
range->internal_base_addr = cpu_to_le32(addr);
|
||||
range->range_data_size = reg->dev_addr.size;
|
||||
range->range_data_size = size;
|
||||
|
||||
if (fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
|
||||
indirect_wr_addr = WMAL_INDRCT_CMD1;
|
||||
|
||||
indirect_wr_addr += le32_to_cpu(reg->dev_addr.offset);
|
||||
indirect_rd_addr += le32_to_cpu(reg->dev_addr.offset);
|
||||
indirect_wr_addr += le32_to_cpu(offset);
|
||||
indirect_rd_addr += le32_to_cpu(offset);
|
||||
|
||||
if (!iwl_trans_grab_nic_access(fwrt->trans))
|
||||
return -EBUSY;
|
||||
|
||||
dphy_addr = (reg->dev_addr.offset) ? WFPM_LMAC2_PS_CTL_RW :
|
||||
WFPM_LMAC1_PS_CTL_RW;
|
||||
dphy_addr = (offset) ? WFPM_LMAC2_PS_CTL_RW : WFPM_LMAC1_PS_CTL_RW;
|
||||
dphy_state = iwl_read_umac_prph_no_grab(fwrt->trans, dphy_addr);
|
||||
|
||||
for (i = 0; i < le32_to_cpu(reg->dev_addr.size); i += 4) {
|
||||
for (i = 0; i < le32_to_cpu(size); i += 4) {
|
||||
if (dphy_state == HBUS_TIMEOUT ||
|
||||
(dphy_state & WFPM_PS_CTL_RW_PHYRF_PD_FSM_CURSTATE_MSK) !=
|
||||
WFPM_PHYRF_STATE_ON) {
|
||||
|
|
@ -1105,6 +1118,33 @@ iwl_dump_ini_prph_phy_iter(struct iwl_fw_runtime *fwrt,
|
|||
return sizeof(*range) + le32_to_cpu(range->range_data_size);
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_dump_ini_prph_phy_iter(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data,
|
||||
void *range_ptr, u32 range_len, int idx)
|
||||
{
|
||||
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
|
||||
u32 addr = le32_to_cpu(reg->addrs[idx]);
|
||||
|
||||
return iwl_dump_ini_prph_phy_iter_common(fwrt, range_ptr, addr,
|
||||
reg->dev_addr.size,
|
||||
reg->dev_addr.offset);
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_dump_ini_prph_phy_block_iter(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data,
|
||||
void *range_ptr, u32 range_len, int idx)
|
||||
{
|
||||
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
|
||||
struct iwl_fw_ini_addr_size *pairs = (void *)reg->addrs;
|
||||
u32 addr = le32_to_cpu(pairs[idx].addr);
|
||||
|
||||
return iwl_dump_ini_prph_phy_iter_common(fwrt, range_ptr, addr,
|
||||
pairs[idx].size,
|
||||
reg->dev_addr_range.offset);
|
||||
}
|
||||
|
||||
static int iwl_dump_ini_csr_iter(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data,
|
||||
void *range_ptr, u32 range_len, int idx)
|
||||
|
|
@ -1136,17 +1176,13 @@ static int iwl_dump_ini_config_iter(struct iwl_fw_runtime *fwrt,
|
|||
le32_to_cpu(reg->dev_addr.offset);
|
||||
int i;
|
||||
|
||||
/* we shouldn't get here if the trans doesn't have read_config32 */
|
||||
if (WARN_ON_ONCE(!trans->ops->read_config32))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
range->internal_base_addr = cpu_to_le32(addr);
|
||||
range->range_data_size = reg->dev_addr.size;
|
||||
for (i = 0; i < le32_to_cpu(reg->dev_addr.size); i += 4) {
|
||||
int ret;
|
||||
u32 tmp;
|
||||
|
||||
ret = trans->ops->read_config32(trans, addr + i, &tmp);
|
||||
ret = iwl_trans_read_config32(trans, addr + i, &tmp);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
@ -1378,6 +1414,53 @@ out:
|
|||
return sizeof(*range) + le32_to_cpu(range->range_data_size);
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_dump_ini_prph_snps_dphyip_iter(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data,
|
||||
void *range_ptr, u32 range_len, int idx)
|
||||
{
|
||||
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
|
||||
struct iwl_fw_ini_error_dump_range *range = range_ptr;
|
||||
__le32 *val = range->data;
|
||||
__le32 offset = reg->dev_addr.offset;
|
||||
u32 indirect_rd_wr_addr = DPHYIP_INDIRECT;
|
||||
u32 addr = le32_to_cpu(reg->addrs[idx]);
|
||||
u32 dphy_state, dphy_addr, prph_val;
|
||||
int i;
|
||||
|
||||
range->internal_base_addr = cpu_to_le32(addr);
|
||||
range->range_data_size = reg->dev_addr.size;
|
||||
|
||||
if (!iwl_trans_grab_nic_access(fwrt->trans))
|
||||
return -EBUSY;
|
||||
|
||||
indirect_rd_wr_addr += le32_to_cpu(offset);
|
||||
|
||||
dphy_addr = offset ? WFPM_LMAC2_PS_CTL_RW : WFPM_LMAC1_PS_CTL_RW;
|
||||
dphy_state = iwl_read_umac_prph_no_grab(fwrt->trans, dphy_addr);
|
||||
|
||||
for (i = 0; i < le32_to_cpu(reg->dev_addr.size); i += 4) {
|
||||
if (dphy_state == HBUS_TIMEOUT ||
|
||||
(dphy_state & WFPM_PS_CTL_RW_PHYRF_PD_FSM_CURSTATE_MSK) !=
|
||||
WFPM_PHYRF_STATE_ON) {
|
||||
*val++ = cpu_to_le32(WFPM_DPHY_OFF);
|
||||
continue;
|
||||
}
|
||||
|
||||
iwl_write_prph_no_grab(fwrt->trans, indirect_rd_wr_addr,
|
||||
addr + i);
|
||||
/* wait a bit for value to be ready in register */
|
||||
udelay(1);
|
||||
prph_val = iwl_read_prph_no_grab(fwrt->trans,
|
||||
indirect_rd_wr_addr);
|
||||
*val++ = cpu_to_le32((prph_val & DPHYIP_INDIRECT_RD_MSK) >>
|
||||
DPHYIP_INDIRECT_RD_SHIFT);
|
||||
}
|
||||
|
||||
iwl_trans_release_nic_access(fwrt->trans);
|
||||
return sizeof(*range) + le32_to_cpu(range->range_data_size);
|
||||
}
|
||||
|
||||
struct iwl_ini_rxf_data {
|
||||
u32 fifo_num;
|
||||
u32 size;
|
||||
|
|
@ -1646,10 +1729,12 @@ iwl_dump_ini_mem_fill_header(struct iwl_fw_runtime *fwrt,
|
|||
/**
|
||||
* mask_apply_and_normalize - applies mask on val and normalize the result
|
||||
*
|
||||
* The normalization is based on the first set bit in the mask
|
||||
*
|
||||
* @val: value
|
||||
* @mask: mask to apply and to normalize with
|
||||
*
|
||||
* The normalization is based on the first set bit in the mask
|
||||
*
|
||||
* Returns: the extracted value
|
||||
*/
|
||||
static u32 mask_apply_and_normalize(u32 val, u32 mask)
|
||||
{
|
||||
|
|
@ -1792,6 +1877,16 @@ static u32 iwl_dump_ini_mem_ranges(struct iwl_fw_runtime *fwrt,
|
|||
return iwl_tlv_array_len(reg_data->reg_tlv, reg, addrs);
|
||||
}
|
||||
|
||||
static u32
|
||||
iwl_dump_ini_mem_block_ranges(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data)
|
||||
{
|
||||
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
|
||||
size_t size = sizeof(struct iwl_fw_ini_addr_size);
|
||||
|
||||
return iwl_tlv_array_len_with_size(reg_data->reg_tlv, reg, size);
|
||||
}
|
||||
|
||||
static u32 iwl_dump_ini_paging_ranges(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data)
|
||||
{
|
||||
|
|
@ -1877,6 +1972,25 @@ static u32 iwl_dump_ini_mem_get_size(struct iwl_fw_runtime *fwrt,
|
|||
(size + sizeof(struct iwl_fw_ini_error_dump_range));
|
||||
}
|
||||
|
||||
static u32
|
||||
iwl_dump_ini_mem_block_get_size(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data)
|
||||
{
|
||||
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
|
||||
struct iwl_fw_ini_addr_size *pairs = (void *)reg->addrs;
|
||||
u32 ranges = iwl_dump_ini_mem_block_ranges(fwrt, reg_data);
|
||||
u32 size = sizeof(struct iwl_fw_ini_error_dump);
|
||||
int range;
|
||||
|
||||
if (!ranges)
|
||||
return 0;
|
||||
|
||||
for (range = 0; range < ranges; range++)
|
||||
size += le32_to_cpu(pairs[range].size);
|
||||
|
||||
return size + ranges * sizeof(struct iwl_fw_ini_error_dump_range);
|
||||
}
|
||||
|
||||
static u32
|
||||
iwl_dump_ini_paging_get_size(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data)
|
||||
|
|
@ -2092,15 +2206,16 @@ struct iwl_dump_ini_mem_ops {
|
|||
};
|
||||
|
||||
/**
|
||||
* iwl_dump_ini_mem
|
||||
*
|
||||
* Creates a dump tlv and copy a memory region into it.
|
||||
* Returns the size of the current dump tlv or 0 if failed
|
||||
* iwl_dump_ini_mem - dump memory region
|
||||
*
|
||||
* @fwrt: fw runtime struct
|
||||
* @list: list to add the dump tlv to
|
||||
* @reg_data: memory region
|
||||
* @ops: memory dump operations
|
||||
*
|
||||
* Creates a dump tlv and copy a memory region into it.
|
||||
*
|
||||
* Returns: the size of the current dump tlv or 0 if failed
|
||||
*/
|
||||
static u32 iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, struct list_head *list,
|
||||
struct iwl_dump_ini_region_data *reg_data,
|
||||
|
|
@ -2324,9 +2439,12 @@ static u32 iwl_dump_ini_info(struct iwl_fw_runtime *fwrt,
|
|||
struct iwl_fw_ini_debug_info_tlv *debug_info =
|
||||
(void *)node->tlv.data;
|
||||
|
||||
BUILD_BUG_ON(sizeof(cfg_name->cfg_name) !=
|
||||
sizeof(debug_info->debug_cfg_name));
|
||||
|
||||
cfg_name->image_type = debug_info->image_type;
|
||||
cfg_name->cfg_name_len =
|
||||
cpu_to_le32(IWL_FW_INI_MAX_CFG_NAME);
|
||||
cpu_to_le32(sizeof(cfg_name->cfg_name));
|
||||
memcpy(cfg_name->cfg_name, debug_info->debug_cfg_name,
|
||||
sizeof(cfg_name->cfg_name));
|
||||
cfg_name++;
|
||||
|
|
@ -2432,6 +2550,18 @@ static const struct iwl_dump_ini_mem_ops iwl_dump_ini_region_ops[] = {
|
|||
.fill_mem_hdr = iwl_dump_ini_mem_fill_header,
|
||||
.fill_range = iwl_dump_ini_prph_phy_iter,
|
||||
},
|
||||
[IWL_FW_INI_REGION_PERIPHERY_MAC_RANGE] = {
|
||||
.get_num_of_ranges = iwl_dump_ini_mem_block_ranges,
|
||||
.get_size = iwl_dump_ini_mem_block_get_size,
|
||||
.fill_mem_hdr = iwl_dump_ini_mem_fill_header,
|
||||
.fill_range = iwl_dump_ini_prph_mac_block_iter,
|
||||
},
|
||||
[IWL_FW_INI_REGION_PERIPHERY_PHY_RANGE] = {
|
||||
.get_num_of_ranges = iwl_dump_ini_mem_block_ranges,
|
||||
.get_size = iwl_dump_ini_mem_block_get_size,
|
||||
.fill_mem_hdr = iwl_dump_ini_mem_fill_header,
|
||||
.fill_range = iwl_dump_ini_prph_phy_block_iter,
|
||||
},
|
||||
[IWL_FW_INI_REGION_PERIPHERY_AUX] = {},
|
||||
[IWL_FW_INI_REGION_PAGING] = {
|
||||
.fill_mem_hdr = iwl_dump_ini_mem_fill_header,
|
||||
|
|
@ -2469,6 +2599,12 @@ static const struct iwl_dump_ini_mem_ops iwl_dump_ini_region_ops[] = {
|
|||
.fill_mem_hdr = iwl_dump_ini_mon_dbgi_fill_header,
|
||||
.fill_range = iwl_dump_ini_dbgi_sram_iter,
|
||||
},
|
||||
[IWL_FW_INI_REGION_PERIPHERY_SNPS_DPHYIP] = {
|
||||
.get_num_of_ranges = iwl_dump_ini_mem_ranges,
|
||||
.get_size = iwl_dump_ini_mem_get_size,
|
||||
.fill_mem_hdr = iwl_dump_ini_mem_fill_header,
|
||||
.fill_range = iwl_dump_ini_prph_snps_dphyip_iter,
|
||||
},
|
||||
};
|
||||
|
||||
static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt,
|
||||
|
|
@ -2511,7 +2647,9 @@ static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt,
|
|||
if (reg_type >= ARRAY_SIZE(iwl_dump_ini_region_ops))
|
||||
continue;
|
||||
|
||||
if (reg_type == IWL_FW_INI_REGION_PERIPHERY_PHY &&
|
||||
if ((reg_type == IWL_FW_INI_REGION_PERIPHERY_PHY ||
|
||||
reg_type == IWL_FW_INI_REGION_PERIPHERY_PHY_RANGE ||
|
||||
reg_type == IWL_FW_INI_REGION_PERIPHERY_SNPS_DPHYIP) &&
|
||||
tp_id != IWL_FW_INI_TIME_POINT_FW_ASSERT) {
|
||||
IWL_WARN(fwrt,
|
||||
"WRT: trying to collect phy prph at time point: %d, skipping\n",
|
||||
|
|
@ -2754,7 +2892,8 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
|
|||
IWL_WARN(fwrt, "Collecting data: trigger %d fired.\n",
|
||||
le32_to_cpu(desc->trig_desc.type));
|
||||
|
||||
schedule_delayed_work(&wk_data->wk, usecs_to_jiffies(delay));
|
||||
queue_delayed_work(system_unbound_wq, &wk_data->wk,
|
||||
usecs_to_jiffies(delay));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2956,11 +3095,10 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx)
|
|||
struct iwl_fw_dbg_params params = {0};
|
||||
struct iwl_fwrt_dump_data *dump_data =
|
||||
&fwrt->dump.wks[wk_idx].dump_data;
|
||||
u32 policy;
|
||||
u32 time_point;
|
||||
if (!test_bit(wk_idx, &fwrt->dump.active_wks))
|
||||
return;
|
||||
|
||||
/* also checks 'desc' for pre-ini mode, since that shadows in union */
|
||||
if (!dump_data->trig) {
|
||||
IWL_ERR(fwrt, "dump trigger data is not set\n");
|
||||
goto out;
|
||||
|
|
@ -2988,13 +3126,16 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx)
|
|||
|
||||
iwl_fw_dbg_stop_restart_recording(fwrt, ¶ms, false);
|
||||
|
||||
policy = le32_to_cpu(dump_data->trig->apply_policy);
|
||||
time_point = le32_to_cpu(dump_data->trig->time_point);
|
||||
if (iwl_trans_dbg_ini_valid(fwrt->trans)) {
|
||||
u32 policy = le32_to_cpu(dump_data->trig->apply_policy);
|
||||
u32 time_point = le32_to_cpu(dump_data->trig->time_point);
|
||||
|
||||
if (policy & IWL_FW_INI_APPLY_POLICY_DUMP_COMPLETE_CMD) {
|
||||
IWL_DEBUG_FW_INFO(fwrt, "WRT: sending dump complete\n");
|
||||
iwl_send_dbg_dump_complete_cmd(fwrt, time_point, 0);
|
||||
if (policy & IWL_FW_INI_APPLY_POLICY_DUMP_COMPLETE_CMD) {
|
||||
IWL_DEBUG_FW_INFO(fwrt, "WRT: sending dump complete\n");
|
||||
iwl_send_dbg_dump_complete_cmd(fwrt, time_point, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (fwrt->trans->dbg.last_tp_resetfw == IWL_FW_INI_RESET_FW_MODE_STOP_FW_ONLY)
|
||||
iwl_force_nmi(fwrt->trans);
|
||||
|
||||
|
|
@ -3056,7 +3197,9 @@ int iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt,
|
|||
if (sync)
|
||||
iwl_fw_dbg_collect_sync(fwrt, idx);
|
||||
else
|
||||
schedule_delayed_work(&fwrt->dump.wks[idx].wk, usecs_to_jiffies(delay));
|
||||
queue_delayed_work(system_unbound_wq,
|
||||
&fwrt->dump.wks[idx].wk,
|
||||
usecs_to_jiffies(delay));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -3228,7 +3371,7 @@ void iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
|
|||
{
|
||||
int ret __maybe_unused = 0;
|
||||
|
||||
if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status))
|
||||
if (!iwl_trans_fw_running(fwrt->trans))
|
||||
return;
|
||||
|
||||
if (fw_has_capa(&fwrt->fw->ucode_capa,
|
||||
|
|
@ -3251,3 +3394,47 @@ void iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
|
|||
#endif
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fw_dbg_stop_restart_recording);
|
||||
|
||||
void iwl_fw_disable_dbg_asserts(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct iwl_fw_dbg_config_cmd cmd = {
|
||||
.type = cpu_to_le32(DEBUG_TOKEN_CONFIG_TYPE),
|
||||
.conf = cpu_to_le32(IWL_FW_DBG_CONFIG_TOKEN),
|
||||
};
|
||||
struct iwl_host_cmd hcmd = {
|
||||
.id = WIDE_ID(LONG_GROUP, LDBG_CONFIG_CMD),
|
||||
.data[0] = &cmd,
|
||||
.len[0] = sizeof(cmd),
|
||||
};
|
||||
u32 preset = u32_get_bits(fwrt->trans->dbg.domains_bitmap,
|
||||
GENMASK(31, IWL_FW_DBG_DOMAIN_POS + 1));
|
||||
|
||||
/* supported starting from 9000 devices */
|
||||
if (fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_9000)
|
||||
return;
|
||||
|
||||
if (fwrt->trans->dbg.yoyo_bin_loaded || (preset && preset != 1))
|
||||
return;
|
||||
|
||||
iwl_trans_send_cmd(fwrt->trans, &hcmd);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fw_disable_dbg_asserts);
|
||||
|
||||
void iwl_fw_dbg_clear_monitor_buf(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct iwl_fw_dbg_params params = {0};
|
||||
|
||||
iwl_fw_dbg_stop_sync(fwrt);
|
||||
|
||||
if (fw_has_api(&fwrt->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_INT_DBG_BUF_CLEAR)) {
|
||||
struct iwl_host_cmd hcmd = {
|
||||
.id = WIDE_ID(DEBUG_GROUP, FW_CLEAR_BUFFER),
|
||||
};
|
||||
iwl_trans_send_cmd(fwrt->trans, &hcmd);
|
||||
}
|
||||
|
||||
iwl_dbg_tlv_init_cfg(fwrt);
|
||||
iwl_fw_dbg_stop_restart_recording(fwrt, ¶ms, false);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fw_dbg_clear_monitor_buf);
|
||||
|
|
|
|||
|
|
@ -310,8 +310,6 @@ static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt, bool sync)
|
|||
_iwl_dbg_tlv_time_point(fwrt, tp_id, NULL, sync);
|
||||
}
|
||||
|
||||
void iwl_fw_error_print_fseq_regs(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
static inline void iwl_fwrt_update_fw_versions(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_lmac_alive *lmac,
|
||||
struct iwl_umac_alive *umac)
|
||||
|
|
@ -333,6 +331,8 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt);
|
|||
void iwl_send_dbg_dump_complete_cmd(struct iwl_fw_runtime *fwrt,
|
||||
u32 timepoint,
|
||||
u32 timepoint_data);
|
||||
void iwl_fw_disable_dbg_asserts(struct iwl_fw_runtime *fwrt);
|
||||
void iwl_fw_dbg_clear_monitor_buf(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
#define IWL_FW_CHECK_FAILED(_obj, _fmt, ...) \
|
||||
IWL_ERR_LIMIT(_obj, _fmt, __VA_ARGS__)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2020 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -141,7 +141,11 @@ static int iwl_dbgfs_enabled_severities_write(struct iwl_fw_runtime *fwrt,
|
|||
|
||||
event_cfg.enabled_severities = cpu_to_le32(enabled_severities);
|
||||
|
||||
ret = iwl_trans_send_cmd(fwrt->trans, &hcmd);
|
||||
if (fwrt->ops && fwrt->ops->send_hcmd)
|
||||
ret = fwrt->ops->send_hcmd(fwrt->ops_ctx, &hcmd);
|
||||
else
|
||||
ret = -EPERM;
|
||||
|
||||
IWL_INFO(fwrt,
|
||||
"sent host event cfg with enabled_severities: %u, ret: %d\n",
|
||||
enabled_severities, ret);
|
||||
|
|
@ -226,8 +230,7 @@ static ssize_t iwl_dbgfs_send_hcmd_write(struct iwl_fw_runtime *fwrt, char *buf,
|
|||
.data = { NULL, },
|
||||
};
|
||||
|
||||
if (fwrt->ops && fwrt->ops->fw_running &&
|
||||
!fwrt->ops->fw_running(fwrt->ops_ctx))
|
||||
if (!iwl_trans_fw_running(fwrt->trans))
|
||||
return -EIO;
|
||||
|
||||
if (count < header_size + 1 || count > 1024 * 4)
|
||||
|
|
@ -342,6 +345,12 @@ static int iwl_dbgfs_fw_info_seq_show(struct seq_file *seq, void *v)
|
|||
" %d: %d\n",
|
||||
IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT,
|
||||
has_capa);
|
||||
has_capa = fw_has_capa(&fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_CHINA_22_REG_SUPPORT) ? 1 : 0;
|
||||
seq_printf(seq,
|
||||
" %d: %d\n",
|
||||
IWL_UCODE_TLV_CAPA_CHINA_22_REG_SUPPORT,
|
||||
has_capa);
|
||||
seq_puts(seq, "fw_api_ver:\n");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -182,8 +182,7 @@ static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_nu
|
|||
base = fwrt->fw->inst_errlog_ptr;
|
||||
}
|
||||
|
||||
if ((fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ && !base) ||
|
||||
(fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ && base < 0x400000)) {
|
||||
if (!base) {
|
||||
IWL_ERR(fwrt,
|
||||
"Not valid error log pointer 0x%08X for %s uCode\n",
|
||||
base,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2014-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
/**
|
||||
* enum iwl_fw_error_dump_type - types of data in the dump file
|
||||
* @IWL_FW_ERROR_DUMP_CSR: Control Status Registers - from offset 0
|
||||
* @IWL_FW_ERROR_DUMP_RXF:
|
||||
* @IWL_FW_ERROR_DUMP_RXF: RX FIFO contents
|
||||
* @IWL_FW_ERROR_DUMP_TXCMD: last TX command data, structured as
|
||||
* &struct iwl_fw_error_dump_txcmd packets
|
||||
* @IWL_FW_ERROR_DUMP_DEV_FW_INFO: struct %iwl_fw_error_dump_info
|
||||
|
|
@ -24,21 +24,24 @@
|
|||
* @IWL_FW_ERROR_DUMP_FW_MONITOR: firmware monitor
|
||||
* @IWL_FW_ERROR_DUMP_PRPH: range of periphery registers - there can be several
|
||||
* sections like this in a single file.
|
||||
* @IWL_FW_ERROR_DUMP_TXF: TX FIFO contents
|
||||
* @IWL_FW_ERROR_DUMP_FH_REGS: range of FH registers
|
||||
* @IWL_FW_ERROR_DUMP_MEM: chunk of memory
|
||||
* @IWL_FW_ERROR_DUMP_ERROR_INFO: description of what triggered this dump.
|
||||
* Structured as &struct iwl_fw_error_dump_trigger_desc.
|
||||
* @IWL_FW_ERROR_DUMP_RB: the content of an RB structured as
|
||||
* &struct iwl_fw_error_dump_rb
|
||||
* @IWL_FW_ERROR_PAGING: UMAC's image memory segments which were
|
||||
* @IWL_FW_ERROR_DUMP_PAGING: UMAC's image memory segments which were
|
||||
* paged to the DRAM.
|
||||
* @IWL_FW_ERROR_DUMP_RADIO_REG: Dump the radio registers.
|
||||
* @IWL_FW_ERROR_DUMP_INTERNAL_TXF: internal TX FIFO data
|
||||
* @IWL_FW_ERROR_DUMP_EXTERNAL: used only by external code utilities, and
|
||||
* for that reason is not in use in any other place in the Linux Wi-Fi
|
||||
* stack.
|
||||
* @IWL_FW_ERROR_DUMP_MEM_CFG: the addresses and sizes of fifos in the smem,
|
||||
* which we get from the fw after ALIVE. The content is structured as
|
||||
* &struct iwl_fw_error_dump_smem_cfg.
|
||||
* @IWL_FW_ERROR_DUMP_D3_DEBUG_DATA: D3 debug data
|
||||
*/
|
||||
enum iwl_fw_error_dump_type {
|
||||
/* 0 is deprecated */
|
||||
|
|
@ -59,8 +62,6 @@ enum iwl_fw_error_dump_type {
|
|||
IWL_FW_ERROR_DUMP_EXTERNAL = 15, /* Do not move */
|
||||
IWL_FW_ERROR_DUMP_MEM_CFG = 16,
|
||||
IWL_FW_ERROR_DUMP_D3_DEBUG_DATA = 17,
|
||||
|
||||
IWL_FW_ERROR_DUMP_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -247,7 +248,7 @@ struct iwl_fw_error_dump_mem {
|
|||
#define IWL_INI_DUMP_NAME_TYPE (BIT(31) | BIT(24))
|
||||
|
||||
/**
|
||||
* struct iwl_fw_error_dump_data - data for one type
|
||||
* struct iwl_fw_ini_error_dump_data - data for one type
|
||||
* @type: &enum iwl_fw_ini_region_type
|
||||
* @sub_type: sub type id
|
||||
* @sub_type_ver: sub type version
|
||||
|
|
@ -277,7 +278,7 @@ struct iwl_fw_ini_dump_entry {
|
|||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_fw_error_dump_file - header of dump file
|
||||
* struct iwl_fw_ini_dump_file_hdr - header of dump file
|
||||
* @barker: must be %IWL_FW_INI_ERROR_DUMP_BARKER
|
||||
* @file_len: the length of all the file including the header
|
||||
*/
|
||||
|
|
@ -310,9 +311,9 @@ struct iwl_fw_ini_fifo_hdr {
|
|||
struct iwl_fw_ini_error_dump_range {
|
||||
__le32 range_data_size;
|
||||
union {
|
||||
__le32 internal_base_addr;
|
||||
__le64 dram_base_addr;
|
||||
__le32 page_num;
|
||||
__le32 internal_base_addr __packed;
|
||||
__le64 dram_base_addr __packed;
|
||||
__le32 page_num __packed;
|
||||
struct iwl_fw_ini_fifo_hdr fifo_hdr;
|
||||
struct iwl_cmd_header fw_pkt_hdr;
|
||||
};
|
||||
|
|
@ -442,7 +443,7 @@ struct iwl_fw_ini_err_table_dump {
|
|||
* struct iwl_fw_error_dump_rb - content of an Receive Buffer
|
||||
* @index: the index of the Receive Buffer in the Rx queue
|
||||
* @rxq: the RB's Rx queue
|
||||
* @reserved:
|
||||
* @reserved: reserved
|
||||
* @data: the content of the Receive Buffer
|
||||
*/
|
||||
struct iwl_fw_error_dump_rb {
|
||||
|
|
@ -488,7 +489,7 @@ struct iwl_fw_ini_special_device_memory {
|
|||
* struct iwl_fw_error_dump_paging - content of the UMAC's image page
|
||||
* block on DRAM
|
||||
* @index: the index of the page block
|
||||
* @reserved:
|
||||
* @reserved: reserved
|
||||
* @data: the content of the page block
|
||||
*/
|
||||
struct iwl_fw_error_dump_paging {
|
||||
|
|
@ -511,6 +512,7 @@ iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data)
|
|||
/**
|
||||
* enum iwl_fw_dbg_trigger - triggers available
|
||||
*
|
||||
* @FW_DBG_TRIGGER_INVALID: invalid trigger value
|
||||
* @FW_DBG_TRIGGER_USER: trigger log collection by user
|
||||
* This should not be defined as a trigger to the driver, but a value the
|
||||
* driver should set to indicate that the trigger was initiated by the
|
||||
|
|
@ -530,14 +532,15 @@ iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data)
|
|||
* @FW_DBG_TRIGGER_TIME_EVENT: trigger log collection upon time events related
|
||||
* events.
|
||||
* @FW_DBG_TRIGGER_BA: trigger log collection upon BlockAck related events.
|
||||
* @FW_DBG_TX_LATENCY: trigger log collection when the tx latency goes above a
|
||||
* threshold.
|
||||
* @FW_DBG_TDLS: trigger log collection upon TDLS related events.
|
||||
* @FW_DBG_TRIGGER_TX_LATENCY: trigger log collection when the tx latency
|
||||
* goes above a threshold.
|
||||
* @FW_DBG_TRIGGER_TDLS: trigger log collection upon TDLS related events.
|
||||
* @FW_DBG_TRIGGER_TX_STATUS: trigger log collection upon tx status when
|
||||
* the firmware sends a tx reply.
|
||||
* @FW_DBG_TRIGGER_ALIVE_TIMEOUT: trigger log collection if alive flow timeouts
|
||||
* @FW_DBG_TRIGGER_DRIVER: trigger log collection upon a flow failure
|
||||
* in the driver.
|
||||
* @FW_DBG_TRIGGER_MAX: beyond triggers, number for sizing arrays etc.
|
||||
*/
|
||||
enum iwl_fw_dbg_trigger {
|
||||
FW_DBG_TRIGGER_INVALID = 0,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2008-2014, 2018-2021 Intel Corporation
|
||||
* Copyright (C) 2008-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -20,7 +20,7 @@ struct iwl_ucode_header {
|
|||
__le32 init_size; /* bytes of init code */
|
||||
__le32 init_data_size; /* bytes of init data */
|
||||
__le32 boot_size; /* bytes of bootstrap code */
|
||||
u8 data[0]; /* in same order as sizes */
|
||||
u8 data[]; /* in same order as sizes */
|
||||
} v1;
|
||||
struct {
|
||||
__le32 build; /* build number */
|
||||
|
|
@ -29,7 +29,7 @@ struct iwl_ucode_header {
|
|||
__le32 init_size; /* bytes of init code */
|
||||
__le32 init_data_size; /* bytes of init data */
|
||||
__le32 boot_size; /* bytes of bootstrap code */
|
||||
u8 data[0]; /* in same order as sizes */
|
||||
u8 data[]; /* in same order as sizes */
|
||||
} v2;
|
||||
} u;
|
||||
};
|
||||
|
|
@ -216,6 +216,7 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t;
|
|||
* ADD_MODIFY_STA_KEY_API_S_VER_2.
|
||||
* @IWL_UCODE_TLV_API_STA_TYPE: This ucode supports station type assignement.
|
||||
* @IWL_UCODE_TLV_API_NAN2_VER2: This ucode supports NAN API version 2
|
||||
* @IWL_UCODE_TLV_API_ADAPTIVE_DWELL: support for adaptive dwell in scanning
|
||||
* @IWL_UCODE_TLV_API_NEW_RX_STATS: should new RX STATISTICS API be used
|
||||
* @IWL_UCODE_TLV_API_QUOTA_LOW_LATENCY: Quota command includes a field
|
||||
* indicating low latency direction.
|
||||
|
|
@ -239,10 +240,21 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t;
|
|||
* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S.
|
||||
* @IWL_UCODE_TLV_API_MBSSID_HE: This ucode supports v2 of
|
||||
* STA_CONTEXT_DOT11AX_API_S
|
||||
* @IWL_UCODE_TLV_API_FTM_RTT_ACCURACY: version 7 of the range response API
|
||||
* is supported by FW, this indicates the RTT confidence value
|
||||
* @IWL_UCODE_TLV_API_SAR_TABLE_VER: This ucode supports different sar
|
||||
* version tables.
|
||||
* @IWL_UCODE_TLV_API_REDUCED_SCAN_CONFIG: This ucode supports v3 of
|
||||
* SCAN_CONFIG_DB_CMD_API_S.
|
||||
* SCAN_CONFIG_DB_CMD_API_S.
|
||||
* @IWL_UCODE_TLV_API_ADWELL_HB_DEF_N_AP: support for setting adaptive dwell
|
||||
* number of APs in the 5 GHz band
|
||||
* @IWL_UCODE_TLV_API_BAND_IN_RX_DATA: FW reports band number in RX notification
|
||||
* @IWL_UCODE_TLV_API_NO_HOST_DISABLE_TX: Firmware offloaded the station disable tx
|
||||
* logic.
|
||||
* @IWL_UCODE_TLV_API_INT_DBG_BUF_CLEAR: Firmware supports clearing the debug
|
||||
* internal buffer
|
||||
* @IWL_UCODE_TLV_API_SMART_FIFO_OFFLOAD: Firmware doesn't need the host to
|
||||
* configure the smart fifo
|
||||
*
|
||||
* @NUM_IWL_UCODE_TLV_API: number of bits used
|
||||
*/
|
||||
|
|
@ -280,13 +292,21 @@ enum iwl_ucode_tlv_api {
|
|||
IWL_UCODE_TLV_API_ADWELL_HB_DEF_N_AP = (__force iwl_ucode_tlv_api_t)57,
|
||||
IWL_UCODE_TLV_API_SCAN_EXT_CHAN_VER = (__force iwl_ucode_tlv_api_t)58,
|
||||
IWL_UCODE_TLV_API_BAND_IN_RX_DATA = (__force iwl_ucode_tlv_api_t)59,
|
||||
/* API Set 2 */
|
||||
IWL_UCODE_TLV_API_NO_HOST_DISABLE_TX = (__force iwl_ucode_tlv_api_t)66,
|
||||
IWL_UCODE_TLV_API_INT_DBG_BUF_CLEAR = (__force iwl_ucode_tlv_api_t)67,
|
||||
IWL_UCODE_TLV_API_SMART_FIFO_OFFLOAD = (__force iwl_ucode_tlv_api_t)68,
|
||||
|
||||
|
||||
#ifdef __CHECKER__
|
||||
/* sparse says it cannot increment the previous enum member */
|
||||
#define NUM_IWL_UCODE_TLV_API 128
|
||||
#else
|
||||
NUM_IWL_UCODE_TLV_API
|
||||
/*
|
||||
* This construction make both sparse (which cannot increment the previous
|
||||
* member due to its bitwise type) and kernel-doc (which doesn't understand
|
||||
* the ifdef/else properly) work.
|
||||
*/
|
||||
#ifdef __CHECKER__
|
||||
#define __CHECKER_NUM_IWL_UCODE_TLV_API 128
|
||||
= (__force iwl_ucode_tlv_api_t)__CHECKER_NUM_IWL_UCODE_TLV_API,
|
||||
#define NUM_IWL_UCODE_TLV_API __CHECKER_NUM_IWL_UCODE_TLV_API
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
@ -372,6 +392,11 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
|
|||
* channels even when these are not enabled.
|
||||
* @IWL_UCODE_TLV_CAPA_DUMP_COMPLETE_SUPPORT: Support for indicating dump collection
|
||||
* complete to FW.
|
||||
* @IWL_UCODE_TLV_CAPA_SPP_AMSDU_SUPPORT: Support SPP (signaling and payload
|
||||
* protected) A-MSDU.
|
||||
* @IWL_UCODE_TLV_CAPA_SECURE_LTF_SUPPORT: Support secure LTF measurement.
|
||||
* @IWL_UCODE_TLV_CAPA_MONITOR_PASSIVE_CHANS: Support monitor mode on otherwise
|
||||
* passive channels
|
||||
*
|
||||
* @NUM_IWL_UCODE_TLV_CAPA: number of bits used
|
||||
*/
|
||||
|
|
@ -457,6 +482,7 @@ enum iwl_ucode_tlv_capa {
|
|||
IWL_UCODE_TLV_CAPA_PSC_CHAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)98,
|
||||
|
||||
IWL_UCODE_TLV_CAPA_BIGTK_SUPPORT = (__force iwl_ucode_tlv_capa_t)100,
|
||||
IWL_UCODE_TLV_CAPA_SPP_AMSDU_SUPPORT = (__force iwl_ucode_tlv_capa_t)103,
|
||||
IWL_UCODE_TLV_CAPA_DRAM_FRAG_SUPPORT = (__force iwl_ucode_tlv_capa_t)104,
|
||||
IWL_UCODE_TLV_CAPA_DUMP_COMPLETE_SUPPORT = (__force iwl_ucode_tlv_capa_t)105,
|
||||
IWL_UCODE_TLV_CAPA_SYNCED_TIME = (__force iwl_ucode_tlv_capa_t)106,
|
||||
|
|
@ -468,12 +494,19 @@ enum iwl_ucode_tlv_capa {
|
|||
IWL_UCODE_TLV_CAPA_OFFLOAD_BTM_SUPPORT = (__force iwl_ucode_tlv_capa_t)113,
|
||||
IWL_UCODE_TLV_CAPA_STA_EXP_MFP_SUPPORT = (__force iwl_ucode_tlv_capa_t)114,
|
||||
IWL_UCODE_TLV_CAPA_SNIFF_VALIDATE_SUPPORT = (__force iwl_ucode_tlv_capa_t)116,
|
||||
|
||||
#ifdef __CHECKER__
|
||||
/* sparse says it cannot increment the previous enum member */
|
||||
#define NUM_IWL_UCODE_TLV_CAPA 128
|
||||
#else
|
||||
IWL_UCODE_TLV_CAPA_CHINA_22_REG_SUPPORT = (__force iwl_ucode_tlv_capa_t)117,
|
||||
IWL_UCODE_TLV_CAPA_SECURE_LTF_SUPPORT = (__force iwl_ucode_tlv_capa_t)121,
|
||||
IWL_UCODE_TLV_CAPA_MONITOR_PASSIVE_CHANS = (__force iwl_ucode_tlv_capa_t)122,
|
||||
NUM_IWL_UCODE_TLV_CAPA
|
||||
/*
|
||||
* This construction make both sparse (which cannot increment the previous
|
||||
* member due to its bitwise type) and kernel-doc (which doesn't understand
|
||||
* the ifdef/else properly) work.
|
||||
*/
|
||||
#ifdef __CHECKER__
|
||||
#define __CHECKER_NUM_IWL_UCODE_TLV_CAPA 128
|
||||
= (__force iwl_ucode_tlv_capa_t)__CHECKER_NUM_IWL_UCODE_TLV_CAPA,
|
||||
#define NUM_IWL_UCODE_TLV_CAPA __CHECKER_NUM_IWL_UCODE_TLV_CAPA
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
@ -549,6 +582,7 @@ enum iwl_fw_dbg_reg_operator {
|
|||
* struct iwl_fw_dbg_reg_op - an operation on a register
|
||||
*
|
||||
* @op: &enum iwl_fw_dbg_reg_operator
|
||||
* @reserved: reserved
|
||||
* @addr: offset of the register
|
||||
* @val: value
|
||||
*/
|
||||
|
|
@ -595,6 +629,7 @@ struct iwl_fw_dbg_mem_seg_tlv {
|
|||
* @version: version of the TLV - currently 0
|
||||
* @monitor_mode: &enum iwl_fw_dbg_monitor_mode
|
||||
* @size_power: buffer size will be 2^(size_power + 11)
|
||||
* @reserved: reserved
|
||||
* @base_reg: addr of the base addr register (PRPH)
|
||||
* @end_reg: addr of the end addr register (PRPH)
|
||||
* @write_ptr_reg: the addr of the reg of the write pointer
|
||||
|
|
@ -705,6 +740,8 @@ enum iwl_fw_dbg_trigger_vif_type {
|
|||
* @trig_dis_ms: the time, in milliseconds, after an occurrence of this
|
||||
* trigger in which another occurrence should be ignored.
|
||||
* @flags: &enum iwl_fw_dbg_trigger_flags
|
||||
* @reserved: reserved (for alignment)
|
||||
* @data: trigger data
|
||||
*/
|
||||
struct iwl_fw_dbg_trigger_tlv {
|
||||
__le32 id;
|
||||
|
|
@ -745,7 +782,7 @@ struct iwl_fw_dbg_trigger_missed_bcon {
|
|||
|
||||
/**
|
||||
* struct iwl_fw_dbg_trigger_cmd - configures trigger for messages from FW.
|
||||
* cmds: the list of commands to trigger the collection on
|
||||
* @cmds: the list of commands to trigger the collection on
|
||||
*/
|
||||
struct iwl_fw_dbg_trigger_cmd {
|
||||
struct cmd {
|
||||
|
|
@ -755,7 +792,7 @@ struct iwl_fw_dbg_trigger_cmd {
|
|||
} __packed;
|
||||
|
||||
/**
|
||||
* iwl_fw_dbg_trigger_stats - configures trigger for statistics
|
||||
* struct iwl_fw_dbg_trigger_stats - configures trigger for statistics
|
||||
* @stop_offset: the offset of the value to be monitored
|
||||
* @stop_threshold: the threshold above which to collect
|
||||
* @start_offset: the offset of the value to be monitored
|
||||
|
|
@ -965,4 +1002,6 @@ static inline size_t _iwl_tlv_array_len(const struct iwl_ucode_tlv *tlv,
|
|||
_iwl_tlv_array_len((_tlv_ptr), sizeof(*(_struct_ptr)), \
|
||||
sizeof(_struct_ptr->_memb[0]))
|
||||
|
||||
#define iwl_tlv_array_len_with_size(_tlv_ptr, _struct_ptr, _size) \
|
||||
_iwl_tlv_array_len((_tlv_ptr), sizeof(*(_struct_ptr)), _size)
|
||||
#endif /* __iwl_fw_file_h__ */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2021 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -198,7 +198,7 @@ struct iwl_dump_exclude {
|
|||
struct iwl_fw {
|
||||
u32 ucode_ver;
|
||||
|
||||
char fw_version[64];
|
||||
char fw_version[128];
|
||||
|
||||
/* ucode images */
|
||||
struct fw_img img[IWL_UCODE_TYPE_MAX];
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2019-2021 Intel Corporation
|
||||
* Copyright (C) 2019-2021, 2024 Intel Corporation
|
||||
*/
|
||||
#include "iwl-drv.h"
|
||||
#include "runtime.h"
|
||||
|
|
@ -135,7 +135,9 @@ int iwl_configure_rxq(struct iwl_fw_runtime *fwrt)
|
|||
struct iwl_trans_rxq_dma_data data;
|
||||
|
||||
cmd->data[i].q_num = i + 1;
|
||||
iwl_trans_get_rxq_dma_data(fwrt->trans, i + 1, &data);
|
||||
ret = iwl_trans_get_rxq_dma_data(fwrt->trans, i + 1, &data);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
cmd->data[i].fr_bd_cb = cpu_to_le64(data.fr_bd_cb);
|
||||
cmd->data[i].urbd_stts_wrptr =
|
||||
|
|
@ -149,6 +151,7 @@ int iwl_configure_rxq(struct iwl_fw_runtime *fwrt)
|
|||
|
||||
ret = iwl_trans_send_cmd(fwrt->trans, &hcmd);
|
||||
|
||||
out:
|
||||
kfree(cmd);
|
||||
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2014 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2023 Intel Corporation
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
#ifndef __iwl_notif_wait_h__
|
||||
|
|
@ -25,6 +25,7 @@ struct iwl_notif_wait_data {
|
|||
* returns true, the wait is over, if it returns false then
|
||||
* the waiter stays blocked. If no function is given, any
|
||||
* of the listed commands will unblock the waiter.
|
||||
* @fn_data: pointer to pass to the @fn's data argument
|
||||
* @cmds: command IDs
|
||||
* @n_cmds: number of command IDs
|
||||
* @triggered: waiter should be woken up
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright(c) 2020-2023 Intel Corporation
|
||||
* Copyright(c) 2020-2024 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "iwl-drv.h"
|
||||
|
|
@ -12,6 +12,8 @@
|
|||
#include "fw/api/alive.h"
|
||||
#include "fw/uefi.h"
|
||||
|
||||
#define IWL_PNVM_REDUCED_CAP_BIT BIT(25)
|
||||
|
||||
struct iwl_pnvm_section {
|
||||
__le32 offset;
|
||||
const u8 data[];
|
||||
|
|
@ -173,6 +175,7 @@ static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
|
|||
|
||||
while (len >= sizeof(*tlv)) {
|
||||
u32 tlv_len, tlv_type;
|
||||
u32 rf_type;
|
||||
|
||||
len -= sizeof(*tlv);
|
||||
tlv = (const void *)data;
|
||||
|
|
@ -201,6 +204,16 @@ static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
|
|||
data += sizeof(*tlv) + ALIGN(tlv_len, 4);
|
||||
len -= ALIGN(tlv_len, 4);
|
||||
|
||||
trans->reduced_cap_sku = false;
|
||||
rf_type = CSR_HW_RFID_TYPE(trans->hw_rf_id);
|
||||
if ((trans->sku_id[0] & IWL_PNVM_REDUCED_CAP_BIT) &&
|
||||
rf_type == IWL_CFG_RF_TYPE_FM)
|
||||
trans->reduced_cap_sku = true;
|
||||
|
||||
IWL_DEBUG_FW(trans,
|
||||
"Reduced SKU device %d\n",
|
||||
trans->reduced_cap_sku);
|
||||
|
||||
if (trans->sku_id[0] == le32_to_cpu(sku_id->data[0]) &&
|
||||
trans->sku_id[1] == le32_to_cpu(sku_id->data[1]) &&
|
||||
trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) {
|
||||
|
|
@ -239,7 +252,7 @@ static int iwl_pnvm_get_from_fs(struct iwl_trans *trans, u8 **data, size_t *len)
|
|||
}
|
||||
|
||||
new_len = pnvm->size;
|
||||
*data = kmemdup(pnvm->data, pnvm->size, GFP_KERNEL);
|
||||
*data = kvmemdup(pnvm->data, pnvm->size, GFP_KERNEL);
|
||||
release_firmware(pnvm);
|
||||
|
||||
if (!*data)
|
||||
|
|
@ -255,21 +268,27 @@ static u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len)
|
|||
struct pnvm_sku_package *package;
|
||||
u8 *image = NULL;
|
||||
|
||||
/* First attempt to get the PNVM from BIOS */
|
||||
package = iwl_uefi_get_pnvm(trans_p, len);
|
||||
if (!IS_ERR_OR_NULL(package)) {
|
||||
if (*len >= sizeof(*package)) {
|
||||
/* we need only the data */
|
||||
*len -= sizeof(*package);
|
||||
image = kmemdup(package->data, *len, GFP_KERNEL);
|
||||
/* Get PNVM from BIOS for non-Intel SKU */
|
||||
if (trans_p->sku_id[2]) {
|
||||
package = iwl_uefi_get_pnvm(trans_p, len);
|
||||
if (!IS_ERR_OR_NULL(package)) {
|
||||
if (*len >= sizeof(*package)) {
|
||||
/* we need only the data */
|
||||
*len -= sizeof(*package);
|
||||
image = kvmemdup(package->data,
|
||||
*len, GFP_KERNEL);
|
||||
}
|
||||
/*
|
||||
* free package regardless of whether kmemdup
|
||||
* succeeded
|
||||
*/
|
||||
kfree(package);
|
||||
if (image)
|
||||
return image;
|
||||
}
|
||||
/* free package regardless of whether kmemdup succeeded */
|
||||
kfree(package);
|
||||
if (image)
|
||||
return image;
|
||||
}
|
||||
|
||||
/* If it's not available, try from the filesystem */
|
||||
/* If it's not available, or for Intel SKU, try from the filesystem */
|
||||
if (iwl_pnvm_get_from_fs(trans_p, &image, len))
|
||||
return NULL;
|
||||
return image;
|
||||
|
|
@ -314,7 +333,7 @@ static void iwl_pnvm_load_pnvm_to_trans(struct iwl_trans *trans,
|
|||
set:
|
||||
iwl_trans_set_pnvm(trans, capa);
|
||||
free:
|
||||
kfree(data);
|
||||
kvfree(data);
|
||||
kfree(pnvm_data);
|
||||
}
|
||||
|
||||
|
|
|
|||
639
sys/contrib/dev/iwlwifi/fw/regulatory.c
Normal file
639
sys/contrib/dev/iwlwifi/fw/regulatory.c
Normal file
|
|
@ -0,0 +1,639 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2023 Intel Corporation
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
#include <linux/bitfield.h>
|
||||
#endif
|
||||
#include <linux/dmi.h>
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "regulatory.h"
|
||||
#include "fw/runtime.h"
|
||||
#include "fw/uefi.h"
|
||||
|
||||
#define GET_BIOS_TABLE(__name, ...) \
|
||||
do { \
|
||||
int ret = -ENOENT; \
|
||||
if (fwrt->uefi_tables_lock_status > UEFI_WIFI_GUID_UNLOCKED) \
|
||||
ret = iwl_uefi_get_ ## __name(__VA_ARGS__); \
|
||||
if (ret < 0) \
|
||||
ret = iwl_acpi_get_ ## __name(__VA_ARGS__); \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
#define IWL_BIOS_TABLE_LOADER(__name) \
|
||||
int iwl_bios_get_ ## __name(struct iwl_fw_runtime *fwrt) \
|
||||
{GET_BIOS_TABLE(__name, fwrt); } \
|
||||
IWL_EXPORT_SYMBOL(iwl_bios_get_ ## __name)
|
||||
|
||||
#define IWL_BIOS_TABLE_LOADER_DATA(__name, data_type) \
|
||||
int iwl_bios_get_ ## __name(struct iwl_fw_runtime *fwrt, \
|
||||
data_type * data) \
|
||||
{GET_BIOS_TABLE(__name, fwrt, data); } \
|
||||
IWL_EXPORT_SYMBOL(iwl_bios_get_ ## __name)
|
||||
|
||||
IWL_BIOS_TABLE_LOADER(wrds_table);
|
||||
IWL_BIOS_TABLE_LOADER(ewrd_table);
|
||||
IWL_BIOS_TABLE_LOADER(wgds_table);
|
||||
IWL_BIOS_TABLE_LOADER(ppag_table);
|
||||
IWL_BIOS_TABLE_LOADER_DATA(tas_table, struct iwl_tas_data);
|
||||
IWL_BIOS_TABLE_LOADER_DATA(pwr_limit, u64);
|
||||
IWL_BIOS_TABLE_LOADER_DATA(mcc, char);
|
||||
IWL_BIOS_TABLE_LOADER_DATA(eckv, u32);
|
||||
IWL_BIOS_TABLE_LOADER_DATA(wbem, u32);
|
||||
|
||||
|
||||
static const struct dmi_system_id dmi_ppag_approved_list[] = {
|
||||
{ .ident = "HP",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
||||
},
|
||||
},
|
||||
{ .ident = "SAMSUNG",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"),
|
||||
},
|
||||
},
|
||||
{ .ident = "MSFT",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
|
||||
},
|
||||
},
|
||||
{ .ident = "ASUS",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
},
|
||||
},
|
||||
{ .ident = "GOOGLE-HP",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
|
||||
},
|
||||
},
|
||||
{ .ident = "GOOGLE-ASUS",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek COMPUTER INC."),
|
||||
},
|
||||
},
|
||||
{ .ident = "GOOGLE-SAMSUNG",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"),
|
||||
},
|
||||
},
|
||||
{ .ident = "DELL",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
},
|
||||
},
|
||||
{ .ident = "DELL",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
|
||||
},
|
||||
},
|
||||
{ .ident = "RAZER",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Razer"),
|
||||
},
|
||||
},
|
||||
{ .ident = "Honor",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "HONOR"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct dmi_system_id dmi_tas_approved_list[] = {
|
||||
{ .ident = "HP",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
||||
},
|
||||
},
|
||||
{ .ident = "SAMSUNG",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"),
|
||||
},
|
||||
},
|
||||
{ .ident = "LENOVO",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
},
|
||||
},
|
||||
{ .ident = "DELL",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
},
|
||||
},
|
||||
{ .ident = "MSFT",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
|
||||
},
|
||||
},
|
||||
{ .ident = "Acer",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
},
|
||||
},
|
||||
{ .ident = "ASUS",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
},
|
||||
},
|
||||
{ .ident = "GOOGLE-HP",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
|
||||
},
|
||||
},
|
||||
{ .ident = "MSI",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."),
|
||||
},
|
||||
},
|
||||
{ .ident = "Honor",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "HONOR"),
|
||||
},
|
||||
},
|
||||
/* keep last */
|
||||
{}
|
||||
};
|
||||
|
||||
bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
/*
|
||||
* The PER_CHAIN_LIMIT_OFFSET_CMD command is not supported on
|
||||
* earlier firmware versions. Unfortunately, we don't have a
|
||||
* TLV API flag to rely on, so rely on the major version which
|
||||
* is in the first byte of ucode_ver. This was implemented
|
||||
* initially on version 38 and then backported to 17. It was
|
||||
* also backported to 29, but only for 7265D devices. The
|
||||
* intention was to have it in 36 as well, but not all 8000
|
||||
* family got this feature enabled. The 8000 family is the
|
||||
* only one using version 36, so skip this version entirely.
|
||||
*/
|
||||
return IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) >= 38 ||
|
||||
(IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 17 &&
|
||||
fwrt->trans->hw_rev != CSR_HW_REV_TYPE_3160) ||
|
||||
(IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 29 &&
|
||||
((fwrt->trans->hw_rev & CSR_HW_REV_TYPE_MSK) ==
|
||||
CSR_HW_REV_TYPE_7265D));
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_sar_geo_support);
|
||||
|
||||
int iwl_sar_geo_fill_table(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_per_chain_offset *table,
|
||||
u32 n_bands, u32 n_profiles)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (!fwrt->geo_enabled)
|
||||
return -ENODATA;
|
||||
|
||||
if (!iwl_sar_geo_support(fwrt))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
for (i = 0; i < n_profiles; i++) {
|
||||
for (j = 0; j < n_bands; j++) {
|
||||
struct iwl_per_chain_offset *chain =
|
||||
&table[i * n_bands + j];
|
||||
|
||||
chain->max_tx_power =
|
||||
cpu_to_le16(fwrt->geo_profiles[i].bands[j].max);
|
||||
chain->chain_a =
|
||||
fwrt->geo_profiles[i].bands[j].chains[0];
|
||||
chain->chain_b =
|
||||
fwrt->geo_profiles[i].bands[j].chains[1];
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"SAR geographic profile[%d] Band[%d]: chain A = %d chain B = %d max_tx_power = %d\n",
|
||||
i, j,
|
||||
fwrt->geo_profiles[i].bands[j].chains[0],
|
||||
fwrt->geo_profiles[i].bands[j].chains[1],
|
||||
fwrt->geo_profiles[i].bands[j].max);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_sar_geo_fill_table);
|
||||
|
||||
static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt,
|
||||
__le16 *per_chain, u32 n_subbands,
|
||||
int prof_a, int prof_b)
|
||||
{
|
||||
int profs[BIOS_SAR_NUM_CHAINS] = { prof_a, prof_b };
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < BIOS_SAR_NUM_CHAINS; i++) {
|
||||
struct iwl_sar_profile *prof;
|
||||
|
||||
/* don't allow SAR to be disabled (profile 0 means disable) */
|
||||
if (profs[i] == 0)
|
||||
return -EPERM;
|
||||
|
||||
/* we are off by one, so allow up to BIOS_SAR_MAX_PROFILE_NUM */
|
||||
if (profs[i] > BIOS_SAR_MAX_PROFILE_NUM)
|
||||
return -EINVAL;
|
||||
|
||||
/* profiles go from 1 to 4, so decrement to access the array */
|
||||
prof = &fwrt->sar_profiles[profs[i] - 1];
|
||||
|
||||
/* if the profile is disabled, do nothing */
|
||||
if (!prof->enabled) {
|
||||
IWL_DEBUG_RADIO(fwrt, "SAR profile %d is disabled.\n",
|
||||
profs[i]);
|
||||
/*
|
||||
* if one of the profiles is disabled, we
|
||||
* ignore all of them and return 1 to
|
||||
* differentiate disabled from other failures.
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(fwrt,
|
||||
"SAR EWRD: chain %d profile index %d\n",
|
||||
i, profs[i]);
|
||||
IWL_DEBUG_RADIO(fwrt, " Chain[%d]:\n", i);
|
||||
for (j = 0; j < n_subbands; j++) {
|
||||
per_chain[i * n_subbands + j] =
|
||||
cpu_to_le16(prof->chains[i].subbands[j]);
|
||||
IWL_DEBUG_RADIO(fwrt, " Band[%d] = %d * .125dBm\n",
|
||||
j, prof->chains[i].subbands[j]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_sar_fill_profile(struct iwl_fw_runtime *fwrt,
|
||||
__le16 *per_chain, u32 n_tables, u32 n_subbands,
|
||||
int prof_a, int prof_b)
|
||||
{
|
||||
int i, ret = 0;
|
||||
|
||||
for (i = 0; i < n_tables; i++) {
|
||||
ret = iwl_sar_fill_table(fwrt,
|
||||
&per_chain[i * n_subbands * BIOS_SAR_NUM_CHAINS],
|
||||
n_subbands, prof_a, prof_b);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_sar_fill_profile);
|
||||
|
||||
static bool iwl_ppag_value_valid(struct iwl_fw_runtime *fwrt, int chain,
|
||||
int subband)
|
||||
{
|
||||
s8 ppag_val = fwrt->ppag_chains[chain].subbands[subband];
|
||||
|
||||
if ((subband == 0 &&
|
||||
(ppag_val > IWL_PPAG_MAX_LB || ppag_val < IWL_PPAG_MIN_LB)) ||
|
||||
(subband != 0 &&
|
||||
(ppag_val > IWL_PPAG_MAX_HB || ppag_val < IWL_PPAG_MIN_HB))) {
|
||||
IWL_DEBUG_RADIO(fwrt, "Invalid PPAG value: %d\n", ppag_val);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
|
||||
union iwl_ppag_table_cmd *cmd, int *cmd_size)
|
||||
{
|
||||
u8 cmd_ver;
|
||||
int i, j, num_sub_bands;
|
||||
s8 *gain;
|
||||
bool send_ppag_always;
|
||||
|
||||
/* many firmware images for JF lie about this */
|
||||
if (CSR_HW_RFID_TYPE(fwrt->trans->hw_rf_id) ==
|
||||
CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_JF))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!fw_has_capa(&fwrt->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_PPAG)) {
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"PPAG capability not supported by FW, command not sent.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
|
||||
WIDE_ID(PHY_OPS_GROUP,
|
||||
PER_PLATFORM_ANT_GAIN_CMD), 1);
|
||||
/*
|
||||
* Starting from ver 4, driver needs to send the PPAG CMD regardless
|
||||
* if PPAG is enabled/disabled or valid/invalid.
|
||||
*/
|
||||
send_ppag_always = cmd_ver > 3;
|
||||
|
||||
/* Don't send PPAG if it is disabled */
|
||||
if (!send_ppag_always && !fwrt->ppag_flags) {
|
||||
IWL_DEBUG_RADIO(fwrt, "PPAG not enabled, command not sent.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* The 'flags' field is the same in v1 and in v2 so we can just
|
||||
* use v1 to access it.
|
||||
*/
|
||||
cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags);
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "PPAG cmd ver is %d\n", cmd_ver);
|
||||
if (cmd_ver == 1) {
|
||||
num_sub_bands = IWL_NUM_SUB_BANDS_V1;
|
||||
gain = cmd->v1.gain[0];
|
||||
*cmd_size = sizeof(cmd->v1);
|
||||
if (fwrt->ppag_ver >= 1) {
|
||||
/* in this case FW supports revision 0 */
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"PPAG table rev is %d, send truncated table\n",
|
||||
fwrt->ppag_ver);
|
||||
}
|
||||
} else if (cmd_ver >= 2 && cmd_ver <= 6) {
|
||||
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
|
||||
gain = cmd->v2.gain[0];
|
||||
*cmd_size = sizeof(cmd->v2);
|
||||
if (fwrt->ppag_ver == 0) {
|
||||
/* in this case FW supports revisions 1,2 or 3 */
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"PPAG table rev is 0, send padded table\n");
|
||||
}
|
||||
} else {
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported PPAG command version\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* ppag mode */
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"PPAG MODE bits were read from bios: %d\n",
|
||||
le32_to_cpu(cmd->v1.flags));
|
||||
|
||||
if (cmd_ver == 5)
|
||||
cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V5_MASK);
|
||||
else if (cmd_ver < 5)
|
||||
cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V4_MASK);
|
||||
|
||||
if ((cmd_ver == 1 &&
|
||||
!fw_has_capa(&fwrt->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) ||
|
||||
(cmd_ver == 2 && fwrt->ppag_ver >= 2)) {
|
||||
cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK);
|
||||
IWL_DEBUG_RADIO(fwrt, "masking ppag China bit\n");
|
||||
} else {
|
||||
IWL_DEBUG_RADIO(fwrt, "isn't masking ppag China bit\n");
|
||||
}
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"PPAG MODE bits going to be sent: %d\n",
|
||||
le32_to_cpu(cmd->v1.flags));
|
||||
|
||||
for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {
|
||||
for (j = 0; j < num_sub_bands; j++) {
|
||||
if (!send_ppag_always &&
|
||||
!iwl_ppag_value_valid(fwrt, i, j))
|
||||
return -EINVAL;
|
||||
|
||||
gain[i * num_sub_bands + j] =
|
||||
fwrt->ppag_chains[i].subbands[j];
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"PPAG table: chain[%d] band[%d]: gain = %d\n",
|
||||
i, j, gain[i * num_sub_bands + j]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fill_ppag_table);
|
||||
|
||||
bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
if (!dmi_check_system(dmi_ppag_approved_list)) {
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"System vendor '%s' is not in the approved list, disabling PPAG.\n",
|
||||
dmi_get_system_info(DMI_SYS_VENDOR) ?: "<unknown>");
|
||||
fwrt->ppag_flags = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_is_ppag_approved);
|
||||
|
||||
bool iwl_is_tas_approved(void)
|
||||
{
|
||||
return dmi_check_system(dmi_tas_approved_list);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_is_tas_approved);
|
||||
|
||||
int iwl_parse_tas_selection(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_tas_data *tas_data,
|
||||
const u32 tas_selection)
|
||||
{
|
||||
u8 override_iec = u32_get_bits(tas_selection,
|
||||
IWL_WTAS_OVERRIDE_IEC_MSK);
|
||||
u8 enabled_iec = u32_get_bits(tas_selection, IWL_WTAS_ENABLE_IEC_MSK);
|
||||
u8 usa_tas_uhb = u32_get_bits(tas_selection, IWL_WTAS_USA_UHB_MSK);
|
||||
int enabled = tas_selection & IWL_WTAS_ENABLED_MSK;
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "TAS selection as read from BIOS: 0x%x\n",
|
||||
tas_selection);
|
||||
|
||||
tas_data->usa_tas_uhb_allowed = usa_tas_uhb;
|
||||
tas_data->override_tas_iec = override_iec;
|
||||
tas_data->enable_tas_iec = enabled_iec;
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
static __le32 iwl_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
int ret;
|
||||
u32 val;
|
||||
__le32 config_bitmap = 0;
|
||||
|
||||
switch (CSR_HW_RFID_TYPE(fwrt->trans->hw_rf_id)) {
|
||||
case IWL_CFG_RF_TYPE_HR1:
|
||||
case IWL_CFG_RF_TYPE_HR2:
|
||||
case IWL_CFG_RF_TYPE_JF1:
|
||||
case IWL_CFG_RF_TYPE_JF2:
|
||||
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_INDONESIA_5G2,
|
||||
&val);
|
||||
|
||||
if (!ret && val == DSM_VALUE_INDONESIA_ENABLE)
|
||||
config_bitmap |=
|
||||
cpu_to_le32(LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_DISABLE_SRD, &val);
|
||||
if (!ret) {
|
||||
if (val == DSM_VALUE_SRD_PASSIVE)
|
||||
config_bitmap |=
|
||||
cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_PASSIVE_MSK);
|
||||
else if (val == DSM_VALUE_SRD_DISABLE)
|
||||
config_bitmap |=
|
||||
cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_DISABLED_MSK);
|
||||
}
|
||||
|
||||
if (fw_has_capa(&fwrt->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_CHINA_22_REG_SUPPORT)) {
|
||||
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_REGULATORY_CONFIG,
|
||||
&val);
|
||||
/*
|
||||
* China 2022 enable if the BIOS object does not exist or
|
||||
* if it is enabled in BIOS.
|
||||
*/
|
||||
if (ret < 0 || val & DSM_MASK_CHINA_22_REG)
|
||||
config_bitmap |=
|
||||
cpu_to_le32(LARI_CONFIG_ENABLE_CHINA_22_REG_SUPPORT_MSK);
|
||||
}
|
||||
|
||||
return config_bitmap;
|
||||
}
|
||||
|
||||
static size_t iwl_get_lari_config_cmd_size(u8 cmd_ver)
|
||||
{
|
||||
size_t cmd_size;
|
||||
|
||||
switch (cmd_ver) {
|
||||
case 12:
|
||||
case 11:
|
||||
cmd_size = sizeof(struct iwl_lari_config_change_cmd);
|
||||
break;
|
||||
case 10:
|
||||
cmd_size = sizeof(struct iwl_lari_config_change_cmd_v10);
|
||||
break;
|
||||
case 9:
|
||||
case 8:
|
||||
case 7:
|
||||
cmd_size = sizeof(struct iwl_lari_config_change_cmd_v7);
|
||||
break;
|
||||
case 6:
|
||||
cmd_size = sizeof(struct iwl_lari_config_change_cmd_v6);
|
||||
break;
|
||||
case 5:
|
||||
cmd_size = sizeof(struct iwl_lari_config_change_cmd_v5);
|
||||
break;
|
||||
case 4:
|
||||
cmd_size = sizeof(struct iwl_lari_config_change_cmd_v4);
|
||||
break;
|
||||
case 3:
|
||||
cmd_size = sizeof(struct iwl_lari_config_change_cmd_v3);
|
||||
break;
|
||||
case 2:
|
||||
cmd_size = sizeof(struct iwl_lari_config_change_cmd_v2);
|
||||
break;
|
||||
default:
|
||||
cmd_size = sizeof(struct iwl_lari_config_change_cmd_v1);
|
||||
break;
|
||||
}
|
||||
return cmd_size;
|
||||
}
|
||||
|
||||
int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_lari_config_change_cmd *cmd,
|
||||
size_t *cmd_size)
|
||||
{
|
||||
int ret;
|
||||
u32 value;
|
||||
u8 cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
|
||||
WIDE_ID(REGULATORY_AND_NVM_GROUP,
|
||||
LARI_CONFIG_CHANGE), 1);
|
||||
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
*cmd_size = iwl_get_lari_config_cmd_size(cmd_ver);
|
||||
|
||||
cmd->config_bitmap = iwl_get_lari_config_bitmap(fwrt);
|
||||
|
||||
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_11AX_ENABLEMENT, &value);
|
||||
if (!ret)
|
||||
cmd->oem_11ax_allow_bitmap = cpu_to_le32(value);
|
||||
|
||||
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_UNII4_CHAN, &value);
|
||||
if (!ret) {
|
||||
if (cmd_ver < 9)
|
||||
value &= DSM_UNII4_ALLOW_BITMAP_CMD_V8;
|
||||
else
|
||||
value &= DSM_UNII4_ALLOW_BITMAP;
|
||||
|
||||
cmd->oem_unii4_allow_bitmap = cpu_to_le32(value);
|
||||
}
|
||||
|
||||
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ACTIVATE_CHANNEL, &value);
|
||||
if (!ret) {
|
||||
if (cmd_ver < 8)
|
||||
value &= ~ACTIVATE_5G2_IN_WW_MASK;
|
||||
if (cmd_ver < 12)
|
||||
value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V11;
|
||||
|
||||
cmd->chan_state_active_bitmap = cpu_to_le32(value);
|
||||
}
|
||||
|
||||
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_6E, &value);
|
||||
if (!ret)
|
||||
cmd->oem_uhb_allow_bitmap = cpu_to_le32(value);
|
||||
|
||||
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_FORCE_DISABLE_CHANNELS, &value);
|
||||
if (!ret)
|
||||
cmd->force_disable_channels_bitmap = cpu_to_le32(value);
|
||||
|
||||
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENERGY_DETECTION_THRESHOLD,
|
||||
&value);
|
||||
if (!ret)
|
||||
cmd->edt_bitmap = cpu_to_le32(value);
|
||||
|
||||
ret = iwl_bios_get_wbem(fwrt, &value);
|
||||
if (!ret)
|
||||
cmd->oem_320mhz_allow_bitmap = cpu_to_le32(value);
|
||||
|
||||
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_11BE, &value);
|
||||
if (!ret)
|
||||
cmd->oem_11be_allow_bitmap = cpu_to_le32(value);
|
||||
|
||||
if (cmd->config_bitmap ||
|
||||
cmd->oem_uhb_allow_bitmap ||
|
||||
cmd->oem_11ax_allow_bitmap ||
|
||||
cmd->oem_unii4_allow_bitmap ||
|
||||
cmd->chan_state_active_bitmap ||
|
||||
cmd->force_disable_channels_bitmap ||
|
||||
cmd->edt_bitmap ||
|
||||
cmd->oem_320mhz_allow_bitmap ||
|
||||
cmd->oem_11be_allow_bitmap) {
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"sending LARI_CONFIG_CHANGE, config_bitmap=0x%x, oem_11ax_allow_bitmap=0x%x\n",
|
||||
le32_to_cpu(cmd->config_bitmap),
|
||||
le32_to_cpu(cmd->oem_11ax_allow_bitmap));
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"sending LARI_CONFIG_CHANGE, oem_unii4_allow_bitmap=0x%x, chan_state_active_bitmap=0x%x, cmd_ver=%d\n",
|
||||
le32_to_cpu(cmd->oem_unii4_allow_bitmap),
|
||||
le32_to_cpu(cmd->chan_state_active_bitmap),
|
||||
cmd_ver);
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"sending LARI_CONFIG_CHANGE, oem_uhb_allow_bitmap=0x%x, force_disable_channels_bitmap=0x%x\n",
|
||||
le32_to_cpu(cmd->oem_uhb_allow_bitmap),
|
||||
le32_to_cpu(cmd->force_disable_channels_bitmap));
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"sending LARI_CONFIG_CHANGE, edt_bitmap=0x%x, oem_320mhz_allow_bitmap=0x%x\n",
|
||||
le32_to_cpu(cmd->edt_bitmap),
|
||||
le32_to_cpu(cmd->oem_320mhz_allow_bitmap));
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"sending LARI_CONFIG_CHANGE, oem_11be_allow_bitmap=0x%x\n",
|
||||
le32_to_cpu(cmd->oem_11be_allow_bitmap));
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fill_lari_config);
|
||||
|
||||
int iwl_bios_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
|
||||
u32 *value)
|
||||
{
|
||||
GET_BIOS_TABLE(dsm, fwrt, func, value);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_bios_get_dsm);
|
||||
220
sys/contrib/dev/iwlwifi/fw/regulatory.h
Normal file
220
sys/contrib/dev/iwlwifi/fw/regulatory.h
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2023-2024 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __fw_regulatory_h__
|
||||
#define __fw_regulatory_h__
|
||||
|
||||
#include "fw/img.h"
|
||||
#include "fw/api/commands.h"
|
||||
#include "fw/api/power.h"
|
||||
#include "fw/api/phy.h"
|
||||
#include "fw/api/config.h"
|
||||
#include "fw/api/nvm-reg.h"
|
||||
#include "fw/img.h"
|
||||
#include "iwl-trans.h"
|
||||
|
||||
#define BIOS_SAR_MAX_PROFILE_NUM 4
|
||||
/*
|
||||
* Each SAR profile has (up to, depends on the table revision) 4 chains:
|
||||
* chain A, chain B, chain A when in CDB, chain B when in CDB
|
||||
*/
|
||||
#define BIOS_SAR_MAX_CHAINS_PER_PROFILE 4
|
||||
#define BIOS_SAR_NUM_CHAINS 2
|
||||
#define BIOS_SAR_MAX_SUB_BANDS_NUM 11
|
||||
|
||||
#define BIOS_GEO_NUM_CHAINS 2
|
||||
#define BIOS_GEO_MAX_NUM_BANDS 3
|
||||
#define BIOS_GEO_MAX_PROFILE_NUM 8
|
||||
#define BIOS_GEO_MIN_PROFILE_NUM 3
|
||||
|
||||
#define IWL_SAR_ENABLE_MSK BIT(0)
|
||||
|
||||
/* PPAG gain value bounds in 1/8 dBm */
|
||||
#define IWL_PPAG_MIN_LB -16
|
||||
#define IWL_PPAG_MAX_LB 24
|
||||
#define IWL_PPAG_MIN_HB -16
|
||||
#define IWL_PPAG_MAX_HB 40
|
||||
|
||||
#define IWL_PPAG_ETSI_CHINA_MASK 3
|
||||
#define IWL_PPAG_REV3_MASK 0x7FF
|
||||
|
||||
#define IWL_WTAS_ENABLED_MSK 0x1
|
||||
#define IWL_WTAS_OVERRIDE_IEC_MSK 0x2
|
||||
#define IWL_WTAS_ENABLE_IEC_MSK 0x4
|
||||
#define IWL_WTAS_USA_UHB_MSK BIT(16)
|
||||
|
||||
/*
|
||||
* The profile for revision 2 is a superset of revision 1, which is in
|
||||
* turn a superset of revision 0. So we can store all revisions
|
||||
* inside revision 2, which is what we represent here.
|
||||
*/
|
||||
|
||||
/*
|
||||
* struct iwl_sar_profile_chain - per-chain values of a SAR profile
|
||||
* @subbands: the SAR value for each subband
|
||||
*/
|
||||
struct iwl_sar_profile_chain {
|
||||
u8 subbands[BIOS_SAR_MAX_SUB_BANDS_NUM];
|
||||
};
|
||||
|
||||
/*
|
||||
* struct iwl_sar_profile - SAR profile from SAR tables
|
||||
* @enabled: whether the profile is enabled or not
|
||||
* @chains: per-chain SAR values
|
||||
*/
|
||||
struct iwl_sar_profile {
|
||||
bool enabled;
|
||||
struct iwl_sar_profile_chain chains[BIOS_SAR_MAX_CHAINS_PER_PROFILE];
|
||||
};
|
||||
|
||||
/* Same thing as with SAR, all revisions fit in revision 2 */
|
||||
|
||||
/*
|
||||
* struct iwl_geo_profile_band - per-band geo SAR offsets
|
||||
* @max: the max tx power allowed for the band
|
||||
* @chains: SAR offsets values for each chain
|
||||
*/
|
||||
struct iwl_geo_profile_band {
|
||||
u8 max;
|
||||
u8 chains[BIOS_GEO_NUM_CHAINS];
|
||||
};
|
||||
|
||||
/*
|
||||
* struct iwl_geo_profile - geo profile
|
||||
* @bands: per-band table of the SAR offsets
|
||||
*/
|
||||
struct iwl_geo_profile {
|
||||
struct iwl_geo_profile_band bands[BIOS_GEO_MAX_NUM_BANDS];
|
||||
};
|
||||
|
||||
/* Same thing as with SAR, all revisions fit in revision 2 */
|
||||
struct iwl_ppag_chain {
|
||||
s8 subbands[BIOS_SAR_MAX_SUB_BANDS_NUM];
|
||||
};
|
||||
|
||||
struct iwl_tas_data {
|
||||
__le32 block_list_size;
|
||||
__le32 block_list_array[IWL_WTAS_BLACK_LIST_MAX];
|
||||
u8 override_tas_iec;
|
||||
u8 enable_tas_iec;
|
||||
u8 usa_tas_uhb_allowed;
|
||||
};
|
||||
|
||||
/* For DSM revision 0 and 4 */
|
||||
enum iwl_dsm_funcs {
|
||||
DSM_FUNC_QUERY = 0,
|
||||
DSM_FUNC_DISABLE_SRD = 1,
|
||||
DSM_FUNC_ENABLE_INDONESIA_5G2 = 2,
|
||||
DSM_FUNC_ENABLE_6E = 3,
|
||||
DSM_FUNC_REGULATORY_CONFIG = 4,
|
||||
DSM_FUNC_11AX_ENABLEMENT = 6,
|
||||
DSM_FUNC_ENABLE_UNII4_CHAN = 7,
|
||||
DSM_FUNC_ACTIVATE_CHANNEL = 8,
|
||||
DSM_FUNC_FORCE_DISABLE_CHANNELS = 9,
|
||||
DSM_FUNC_ENERGY_DETECTION_THRESHOLD = 10,
|
||||
DSM_FUNC_RFI_CONFIG = 11,
|
||||
DSM_FUNC_ENABLE_11BE = 12,
|
||||
DSM_FUNC_NUM_FUNCS = 13,
|
||||
};
|
||||
|
||||
enum iwl_dsm_values_srd {
|
||||
DSM_VALUE_SRD_ACTIVE,
|
||||
DSM_VALUE_SRD_PASSIVE,
|
||||
DSM_VALUE_SRD_DISABLE,
|
||||
DSM_VALUE_SRD_MAX
|
||||
};
|
||||
|
||||
enum iwl_dsm_values_indonesia {
|
||||
DSM_VALUE_INDONESIA_DISABLE,
|
||||
DSM_VALUE_INDONESIA_ENABLE,
|
||||
DSM_VALUE_INDONESIA_RESERVED,
|
||||
DSM_VALUE_INDONESIA_MAX
|
||||
};
|
||||
|
||||
enum iwl_dsm_unii4_bitmap {
|
||||
DSM_VALUE_UNII4_US_OVERRIDE_MSK = BIT(0),
|
||||
DSM_VALUE_UNII4_US_EN_MSK = BIT(1),
|
||||
DSM_VALUE_UNII4_ETSI_OVERRIDE_MSK = BIT(2),
|
||||
DSM_VALUE_UNII4_ETSI_EN_MSK = BIT(3),
|
||||
DSM_VALUE_UNII4_CANADA_OVERRIDE_MSK = BIT(4),
|
||||
DSM_VALUE_UNII4_CANADA_EN_MSK = BIT(5),
|
||||
};
|
||||
|
||||
#define DSM_UNII4_ALLOW_BITMAP_CMD_V8 (DSM_VALUE_UNII4_US_OVERRIDE_MSK | \
|
||||
DSM_VALUE_UNII4_US_EN_MSK | \
|
||||
DSM_VALUE_UNII4_ETSI_OVERRIDE_MSK | \
|
||||
DSM_VALUE_UNII4_ETSI_EN_MSK)
|
||||
#define DSM_UNII4_ALLOW_BITMAP (DSM_UNII4_ALLOW_BITMAP_CMD_V8 | \
|
||||
DSM_VALUE_UNII4_CANADA_OVERRIDE_MSK | \
|
||||
DSM_VALUE_UNII4_CANADA_EN_MSK)
|
||||
|
||||
enum iwl_dsm_values_rfi {
|
||||
DSM_VALUE_RFI_DLVR_DISABLE = BIT(0),
|
||||
DSM_VALUE_RFI_DDR_DISABLE = BIT(1),
|
||||
};
|
||||
|
||||
#define DSM_VALUE_RFI_DISABLE (DSM_VALUE_RFI_DLVR_DISABLE |\
|
||||
DSM_VALUE_RFI_DDR_DISABLE)
|
||||
|
||||
enum iwl_dsm_masks_reg {
|
||||
DSM_MASK_CHINA_22_REG = BIT(2)
|
||||
};
|
||||
|
||||
struct iwl_fw_runtime;
|
||||
|
||||
bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
int iwl_sar_geo_fill_table(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_per_chain_offset *table,
|
||||
u32 n_bands, u32 n_profiles);
|
||||
|
||||
int iwl_sar_fill_profile(struct iwl_fw_runtime *fwrt,
|
||||
__le16 *per_chain, u32 n_tables, u32 n_subbands,
|
||||
int prof_a, int prof_b);
|
||||
|
||||
int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
|
||||
union iwl_ppag_table_cmd *cmd,
|
||||
int *cmd_size);
|
||||
|
||||
bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
bool iwl_is_tas_approved(void);
|
||||
|
||||
int iwl_parse_tas_selection(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_tas_data *tas_data,
|
||||
const u32 tas_selection);
|
||||
|
||||
int iwl_bios_get_wrds_table(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
int iwl_bios_get_ewrd_table(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
int iwl_bios_get_wgds_table(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
int iwl_bios_get_ppag_table(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
int iwl_bios_get_tas_table(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_tas_data *data);
|
||||
|
||||
int iwl_bios_get_pwr_limit(struct iwl_fw_runtime *fwrt,
|
||||
u64 *dflt_pwr_limit);
|
||||
|
||||
int iwl_bios_get_mcc(struct iwl_fw_runtime *fwrt, char *mcc);
|
||||
int iwl_bios_get_eckv(struct iwl_fw_runtime *fwrt, u32 *ext_clk);
|
||||
int iwl_bios_get_wbem(struct iwl_fw_runtime *fwrt, u32 *value);
|
||||
|
||||
int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_lari_config_change_cmd *cmd,
|
||||
size_t *cmd_size);
|
||||
|
||||
int iwl_bios_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
|
||||
u32 *value);
|
||||
|
||||
static inline u32 iwl_bios_get_ppag_flags(const u32 ppag_modes,
|
||||
const u8 ppag_ver)
|
||||
{
|
||||
return ppag_modes & (ppag_ver < 3 ? IWL_PPAG_ETSI_CHINA_MASK :
|
||||
IWL_PPAG_REV3_MASK);
|
||||
}
|
||||
#endif /* __fw_regulatory_h__ */
|
||||
|
|
@ -208,7 +208,6 @@ int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate)
|
|||
|
||||
return scnprintf(buf, bufsz, "Legacy | ANT: %s Rate: %s Mbps",
|
||||
iwl_rs_pretty_ant(ant),
|
||||
index == IWL_RATE_INVALID ? "BAD" :
|
||||
iwl_rate_mcs(index)->mbps);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2018-2024 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_fw_runtime_h__
|
||||
#define __iwl_fw_runtime_h__
|
||||
|
|
@ -12,13 +12,13 @@
|
|||
#include "fw/api/debug.h"
|
||||
#include "fw/api/paging.h"
|
||||
#include "fw/api/power.h"
|
||||
#include "iwl-eeprom-parse.h"
|
||||
#include "iwl-nvm-utils.h"
|
||||
#include "fw/acpi.h"
|
||||
#include "fw/regulatory.h"
|
||||
|
||||
struct iwl_fw_runtime_ops {
|
||||
void (*dump_start)(void *ctx);
|
||||
void (*dump_end)(void *ctx);
|
||||
bool (*fw_running)(void *ctx);
|
||||
int (*send_hcmd)(void *ctx, struct iwl_host_cmd *host_cmd);
|
||||
bool (*d3_debug_enable)(void *ctx);
|
||||
};
|
||||
|
|
@ -45,6 +45,10 @@ struct iwl_fwrt_shared_mem_cfg {
|
|||
* struct iwl_fwrt_dump_data - dump data
|
||||
* @trig: trigger the worker was scheduled upon
|
||||
* @fw_pkt: packet received from FW
|
||||
*
|
||||
* Note that the decision which part of the union is used
|
||||
* is based on iwl_trans_dbg_ini_valid(): the 'trig' part
|
||||
* is used if it is %true, the 'desc' part otherwise.
|
||||
*/
|
||||
struct iwl_fwrt_dump_data {
|
||||
union {
|
||||
|
|
@ -53,6 +57,7 @@ struct iwl_fwrt_dump_data {
|
|||
struct iwl_rx_packet *fw_pkt;
|
||||
};
|
||||
struct {
|
||||
/* must be first to be same as 'trig' */
|
||||
const struct iwl_fw_dump_desc *desc;
|
||||
bool monitor_only;
|
||||
};
|
||||
|
|
@ -98,6 +103,12 @@ struct iwl_txf_iter_data {
|
|||
* @cur_fw_img: current firmware image, must be maintained by
|
||||
* the driver by calling &iwl_fw_set_current_image()
|
||||
* @dump: debug dump data
|
||||
* @uats_table: AP type table
|
||||
* @uefi_tables_lock_status: The status of the WIFI GUID UEFI variables lock:
|
||||
* 0: Unlocked, 1 and 2: Locked.
|
||||
* Only read the UEFI variables if locked.
|
||||
* @sar_profiles: sar profiles as read from WRDS/EWRD BIOS tables
|
||||
* @geo_profiles: geographic profiles as read from WGDS BIOS table
|
||||
*/
|
||||
struct iwl_fw_runtime {
|
||||
struct iwl_trans *trans;
|
||||
|
|
@ -156,22 +167,21 @@ struct iwl_fw_runtime {
|
|||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
bool tpc_enabled;
|
||||
#endif /* CONFIG_IWLWIFI_DEBUGFS */
|
||||
#ifdef CONFIG_ACPI
|
||||
struct iwl_sar_profile sar_profiles[ACPI_SAR_PROFILE_NUM];
|
||||
struct iwl_sar_profile sar_profiles[BIOS_SAR_MAX_PROFILE_NUM];
|
||||
u8 sar_chain_a_profile;
|
||||
u8 sar_chain_b_profile;
|
||||
struct iwl_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES_REV3];
|
||||
u8 reduced_power_flags;
|
||||
struct iwl_geo_profile geo_profiles[BIOS_GEO_MAX_PROFILE_NUM];
|
||||
u32 geo_rev;
|
||||
u32 geo_num_profiles;
|
||||
bool geo_enabled;
|
||||
struct iwl_ppag_chain ppag_chains[IWL_NUM_CHAIN_LIMITS];
|
||||
u32 ppag_flags;
|
||||
u32 ppag_ver;
|
||||
bool ppag_table_valid;
|
||||
u8 ppag_ver;
|
||||
struct iwl_sar_offset_mapping_cmd sgom_table;
|
||||
bool sgom_enabled;
|
||||
u8 reduced_power_flags;
|
||||
#endif
|
||||
struct iwl_mcc_allowed_ap_type_cmd uats_table;
|
||||
u8 uefi_tables_lock_status;
|
||||
};
|
||||
|
||||
void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright(c) 2021-2023 Intel Corporation
|
||||
* Copyright(c) 2021-2024 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "iwl-drv.h"
|
||||
|
|
@ -76,6 +76,42 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
|
|||
return data;
|
||||
}
|
||||
|
||||
static
|
||||
void *iwl_uefi_get_verified_variable(struct iwl_trans *trans,
|
||||
efi_char16_t *uefi_var_name,
|
||||
char *var_name,
|
||||
unsigned int expected_size,
|
||||
unsigned long *size)
|
||||
{
|
||||
void *var;
|
||||
unsigned long var_size;
|
||||
|
||||
var = iwl_uefi_get_variable(uefi_var_name, &IWL_EFI_VAR_GUID,
|
||||
&var_size);
|
||||
|
||||
if (IS_ERR(var)) {
|
||||
IWL_DEBUG_RADIO(trans,
|
||||
"%s UEFI variable not found 0x%lx\n", var_name,
|
||||
PTR_ERR(var));
|
||||
return var;
|
||||
}
|
||||
|
||||
if (var_size < expected_size) {
|
||||
IWL_DEBUG_RADIO(trans,
|
||||
"Invalid %s UEFI variable len (%lu)\n",
|
||||
var_name, var_size);
|
||||
kfree(var);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
IWL_DEBUG_RADIO(trans, "%s from UEFI with size %lu\n", var_name,
|
||||
var_size);
|
||||
|
||||
if (size)
|
||||
*size = var_size;
|
||||
return var;
|
||||
}
|
||||
|
||||
int iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data,
|
||||
u32 tlv_len, struct iwl_pnvm_image *pnvm_data)
|
||||
{
|
||||
|
|
@ -230,26 +266,13 @@ u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
|
|||
unsigned long package_size;
|
||||
u8 *data;
|
||||
|
||||
package = iwl_uefi_get_variable(IWL_UEFI_REDUCED_POWER_NAME,
|
||||
&IWL_EFI_VAR_GUID, &package_size);
|
||||
|
||||
if (IS_ERR(package)) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
"Reduced Power UEFI variable not found 0x%lx (len %lu)\n",
|
||||
PTR_ERR(package), package_size);
|
||||
package = iwl_uefi_get_verified_variable(trans,
|
||||
IWL_UEFI_REDUCED_POWER_NAME,
|
||||
"Reduced Power",
|
||||
sizeof(*package),
|
||||
&package_size);
|
||||
if (IS_ERR(package))
|
||||
return ERR_CAST(package);
|
||||
}
|
||||
|
||||
if (package_size < sizeof(*package)) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
"Invalid Reduced Power UEFI variable len (%lu)\n",
|
||||
package_size);
|
||||
kfree(package);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
IWL_DEBUG_FW(trans, "Read reduced power from UEFI with size %lu\n",
|
||||
package_size);
|
||||
|
||||
IWL_DEBUG_FW(trans, "rev %d, total_size %d, n_skus %d\n",
|
||||
package->rev, package->total_size, package->n_skus);
|
||||
|
|
@ -283,32 +306,15 @@ static int iwl_uefi_step_parse(struct uefi_cnv_common_step_data *common_step_dat
|
|||
void iwl_uefi_get_step_table(struct iwl_trans *trans)
|
||||
{
|
||||
struct uefi_cnv_common_step_data *data;
|
||||
unsigned long package_size;
|
||||
int ret;
|
||||
|
||||
if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
|
||||
return;
|
||||
|
||||
data = iwl_uefi_get_variable(IWL_UEFI_STEP_NAME, &IWL_EFI_VAR_GUID,
|
||||
&package_size);
|
||||
|
||||
if (IS_ERR(data)) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
"STEP UEFI variable not found 0x%lx\n",
|
||||
PTR_ERR(data));
|
||||
data = iwl_uefi_get_verified_variable(trans, IWL_UEFI_STEP_NAME,
|
||||
"STEP", sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return;
|
||||
}
|
||||
|
||||
if (package_size < sizeof(*data)) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
"Invalid STEP table UEFI variable len (%lu)\n",
|
||||
package_size);
|
||||
kfree(data);
|
||||
return;
|
||||
}
|
||||
|
||||
IWL_DEBUG_FW(trans, "Read STEP from UEFI with size %lu\n",
|
||||
package_size);
|
||||
|
||||
ret = iwl_uefi_step_parse(data, trans);
|
||||
if (ret < 0)
|
||||
|
|
@ -318,7 +324,6 @@ void iwl_uefi_get_step_table(struct iwl_trans *trans)
|
|||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_uefi_get_step_table);
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static int iwl_uefi_sgom_parse(struct uefi_cnv_wlan_sgom_data *sgom_data,
|
||||
struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
|
|
@ -355,31 +360,15 @@ void iwl_uefi_get_sgom_table(struct iwl_trans *trans,
|
|||
struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct uefi_cnv_wlan_sgom_data *data;
|
||||
unsigned long package_size;
|
||||
int ret;
|
||||
|
||||
if (!fwrt->geo_enabled)
|
||||
return;
|
||||
|
||||
data = iwl_uefi_get_variable(IWL_UEFI_SGOM_NAME, &IWL_EFI_VAR_GUID,
|
||||
&package_size);
|
||||
if (IS_ERR(data)) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
"SGOM UEFI variable not found 0x%lx\n",
|
||||
PTR_ERR(data));
|
||||
data = iwl_uefi_get_verified_variable(trans, IWL_UEFI_SGOM_NAME,
|
||||
"SGOM", sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return;
|
||||
}
|
||||
|
||||
if (package_size < sizeof(*data)) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
"Invalid SGOM table UEFI variable len (%lu)\n",
|
||||
package_size);
|
||||
kfree(data);
|
||||
return;
|
||||
}
|
||||
|
||||
IWL_DEBUG_FW(trans, "Read SGOM from UEFI with size %lu\n",
|
||||
package_size);
|
||||
|
||||
ret = iwl_uefi_sgom_parse(data, fwrt);
|
||||
if (ret < 0)
|
||||
|
|
@ -388,4 +377,355 @@ void iwl_uefi_get_sgom_table(struct iwl_trans *trans,
|
|||
kfree(data);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_uefi_get_sgom_table);
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
static int iwl_uefi_uats_parse(struct uefi_cnv_wlan_uats_data *uats_data,
|
||||
struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
if (uats_data->revision != 1)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(fwrt->uats_table.offset_map, uats_data->offset_map,
|
||||
sizeof(fwrt->uats_table.offset_map));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_uefi_get_uats_table(struct iwl_trans *trans,
|
||||
struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct uefi_cnv_wlan_uats_data *data;
|
||||
int ret;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(trans, IWL_UEFI_UATS_NAME,
|
||||
"UATS", sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
||||
ret = iwl_uefi_uats_parse(data, fwrt);
|
||||
if (ret < 0) {
|
||||
IWL_DEBUG_FW(trans, "Cannot read UATS table. rev is invalid\n");
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_uefi_get_uats_table);
|
||||
|
||||
static void iwl_uefi_set_sar_profile(struct iwl_fw_runtime *fwrt,
|
||||
struct uefi_sar_profile *uefi_sar_prof,
|
||||
u8 prof_index, bool enabled)
|
||||
{
|
||||
memcpy(&fwrt->sar_profiles[prof_index].chains, uefi_sar_prof,
|
||||
sizeof(struct uefi_sar_profile));
|
||||
|
||||
fwrt->sar_profiles[prof_index].enabled = enabled & IWL_SAR_ENABLE_MSK;
|
||||
}
|
||||
|
||||
int iwl_uefi_get_wrds_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct uefi_cnv_var_wrds *data;
|
||||
int ret = 0;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WRDS_NAME,
|
||||
"WRDS", sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
||||
if (data->revision != IWL_UEFI_WRDS_REVISION) {
|
||||
ret = -EINVAL;
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI WRDS revision:%d\n",
|
||||
data->revision);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* The profile from WRDS is officially profile 1, but goes
|
||||
* into sar_profiles[0] (because we don't have a profile 0).
|
||||
*/
|
||||
iwl_uefi_set_sar_profile(fwrt, &data->sar_profile, 0, data->mode);
|
||||
out:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_uefi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct uefi_cnv_var_ewrd *data;
|
||||
int i, ret = 0;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_EWRD_NAME,
|
||||
"EWRD", sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
||||
if (data->revision != IWL_UEFI_EWRD_REVISION) {
|
||||
ret = -EINVAL;
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI EWRD revision:%d\n",
|
||||
data->revision);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (data->num_profiles >= BIOS_SAR_MAX_PROFILE_NUM) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < data->num_profiles; i++)
|
||||
/* The EWRD profiles officially go from 2 to 4, but we
|
||||
* save them in sar_profiles[1-3] (because we don't
|
||||
* have profile 0). So in the array we start from 1.
|
||||
*/
|
||||
iwl_uefi_set_sar_profile(fwrt, &data->sar_profiles[i], i + 1,
|
||||
data->mode);
|
||||
|
||||
out:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct uefi_cnv_var_wgds *data;
|
||||
int i, ret = 0;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WGDS_NAME,
|
||||
"WGDS", sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
||||
if (data->revision != IWL_UEFI_WGDS_REVISION) {
|
||||
ret = -EINVAL;
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI WGDS revision:%d\n",
|
||||
data->revision);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (data->num_profiles < BIOS_GEO_MIN_PROFILE_NUM ||
|
||||
data->num_profiles > BIOS_GEO_MAX_PROFILE_NUM) {
|
||||
ret = -EINVAL;
|
||||
IWL_DEBUG_RADIO(fwrt, "Invalid number of profiles in WGDS: %d\n",
|
||||
data->num_profiles);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fwrt->geo_rev = data->revision;
|
||||
for (i = 0; i < data->num_profiles; i++)
|
||||
memcpy(&fwrt->geo_profiles[i], &data->geo_profiles[i],
|
||||
sizeof(struct iwl_geo_profile));
|
||||
|
||||
fwrt->geo_num_profiles = data->num_profiles;
|
||||
fwrt->geo_enabled = true;
|
||||
out:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct uefi_cnv_var_ppag *data;
|
||||
int ret = 0;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_PPAG_NAME,
|
||||
"PPAG", sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
||||
if (data->revision < IWL_UEFI_MIN_PPAG_REV ||
|
||||
data->revision > IWL_UEFI_MAX_PPAG_REV) {
|
||||
ret = -EINVAL;
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI PPAG revision:%d\n",
|
||||
data->revision);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fwrt->ppag_ver = data->revision;
|
||||
fwrt->ppag_flags = iwl_bios_get_ppag_flags(data->ppag_modes,
|
||||
fwrt->ppag_ver);
|
||||
|
||||
BUILD_BUG_ON(sizeof(fwrt->ppag_chains) != sizeof(data->ppag_chains));
|
||||
memcpy(&fwrt->ppag_chains, &data->ppag_chains,
|
||||
sizeof(data->ppag_chains));
|
||||
out:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_uefi_get_tas_table(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_tas_data *tas_data)
|
||||
{
|
||||
struct uefi_cnv_var_wtas *uefi_tas;
|
||||
int ret = 0, enabled, i;
|
||||
|
||||
uefi_tas = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WTAS_NAME,
|
||||
"WTAS", sizeof(*uefi_tas), NULL);
|
||||
if (IS_ERR(uefi_tas))
|
||||
return -EINVAL;
|
||||
|
||||
if (uefi_tas->revision != IWL_UEFI_WTAS_REVISION) {
|
||||
ret = -EINVAL;
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI WTAS revision:%d\n",
|
||||
uefi_tas->revision);
|
||||
goto out;
|
||||
}
|
||||
|
||||
enabled = iwl_parse_tas_selection(fwrt, tas_data,
|
||||
uefi_tas->tas_selection);
|
||||
if (!enabled) {
|
||||
IWL_DEBUG_RADIO(fwrt, "TAS not enabled\n");
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "Reading TAS table revision %d\n",
|
||||
uefi_tas->revision);
|
||||
if (uefi_tas->black_list_size > IWL_WTAS_BLACK_LIST_MAX) {
|
||||
IWL_DEBUG_RADIO(fwrt, "TAS invalid array size %d\n",
|
||||
uefi_tas->black_list_size);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
tas_data->block_list_size = cpu_to_le32(uefi_tas->black_list_size);
|
||||
IWL_DEBUG_RADIO(fwrt, "TAS array size %u\n", uefi_tas->black_list_size);
|
||||
|
||||
for (i = 0; i < uefi_tas->black_list_size; i++) {
|
||||
tas_data->block_list_array[i] =
|
||||
cpu_to_le32(uefi_tas->black_list[i]);
|
||||
IWL_DEBUG_RADIO(fwrt, "TAS block list country %d\n",
|
||||
uefi_tas->black_list[i]);
|
||||
}
|
||||
out:
|
||||
kfree(uefi_tas);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_uefi_get_pwr_limit(struct iwl_fw_runtime *fwrt,
|
||||
u64 *dflt_pwr_limit)
|
||||
{
|
||||
struct uefi_cnv_var_splc *data;
|
||||
int ret = 0;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_SPLC_NAME,
|
||||
"SPLC", sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
||||
if (data->revision != IWL_UEFI_SPLC_REVISION) {
|
||||
ret = -EINVAL;
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI SPLC revision:%d\n",
|
||||
data->revision);
|
||||
goto out;
|
||||
}
|
||||
*dflt_pwr_limit = data->default_pwr_limit;
|
||||
out:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_uefi_get_mcc(struct iwl_fw_runtime *fwrt, char *mcc)
|
||||
{
|
||||
struct uefi_cnv_var_wrdd *data;
|
||||
int ret = 0;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WRDD_NAME,
|
||||
"WRDD", sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
||||
if (data->revision != IWL_UEFI_WRDD_REVISION) {
|
||||
ret = -EINVAL;
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI WRDD revision:%d\n",
|
||||
data->revision);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (data->mcc != UEFI_MCC_CHINA) {
|
||||
ret = -EINVAL;
|
||||
IWL_DEBUG_RADIO(fwrt, "UEFI WRDD is supported only for CN\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
mcc[0] = (data->mcc >> 8) & 0xff;
|
||||
mcc[1] = data->mcc & 0xff;
|
||||
mcc[2] = '\0';
|
||||
out:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_uefi_get_eckv(struct iwl_fw_runtime *fwrt, u32 *extl_clk)
|
||||
{
|
||||
struct uefi_cnv_var_eckv *data;
|
||||
int ret = 0;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_ECKV_NAME,
|
||||
"ECKV", sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
||||
if (data->revision != IWL_UEFI_ECKV_REVISION) {
|
||||
ret = -EINVAL;
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI WRDD revision:%d\n",
|
||||
data->revision);
|
||||
goto out;
|
||||
}
|
||||
*extl_clk = data->ext_clock_valid;
|
||||
out:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_uefi_get_wbem(struct iwl_fw_runtime *fwrt, u32 *value)
|
||||
{
|
||||
struct uefi_cnv_wlan_wbem_data *data;
|
||||
int ret = 0;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WBEM_NAME,
|
||||
"WBEM", sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
||||
if (data->revision != IWL_UEFI_WBEM_REVISION) {
|
||||
ret = -EINVAL;
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI WBEM revision:%d\n",
|
||||
data->revision);
|
||||
goto out;
|
||||
}
|
||||
*value = data->wbem_320mhz_per_mcc & IWL_UEFI_WBEM_REV0_MASK;
|
||||
IWL_DEBUG_RADIO(fwrt, "Loaded WBEM config from UEFI\n");
|
||||
out:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_uefi_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
|
||||
u32 *value)
|
||||
{
|
||||
struct uefi_cnv_var_general_cfg *data;
|
||||
int ret = -EINVAL;
|
||||
|
||||
/* Not supported function index */
|
||||
if (func >= DSM_FUNC_NUM_FUNCS || func == 5)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_DSM_NAME,
|
||||
"DSM", sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
||||
if (data->revision != IWL_UEFI_DSM_REVISION) {
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI DSM revision:%d\n",
|
||||
data->revision);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ARRAY_SIZE(data->functions) != UEFI_MAX_DSM_FUNCS) {
|
||||
IWL_DEBUG_RADIO(fwrt, "Invalid size of DSM functions array\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
*value = data->functions[func];
|
||||
ret = 0;
|
||||
out:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,43 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright(c) 2021-2023 Intel Corporation
|
||||
* Copyright(c) 2021-2024 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_fw_uefi__
|
||||
#define __iwl_fw_uefi__
|
||||
|
||||
#include "fw/regulatory.h"
|
||||
|
||||
#define IWL_UEFI_OEM_PNVM_NAME L"UefiCnvWlanOemSignedPnvm"
|
||||
#define IWL_UEFI_REDUCED_POWER_NAME L"UefiCnvWlanReducedPower"
|
||||
#define IWL_UEFI_SGOM_NAME L"UefiCnvWlanSarGeoOffsetMapping"
|
||||
#define IWL_UEFI_STEP_NAME L"UefiCnvCommonSTEP"
|
||||
#define IWL_UEFI_UATS_NAME L"CnvUefiWlanUATS"
|
||||
#define IWL_UEFI_WRDS_NAME L"UefiCnvWlanWRDS"
|
||||
#define IWL_UEFI_EWRD_NAME L"UefiCnvWlanEWRD"
|
||||
#define IWL_UEFI_WGDS_NAME L"UefiCnvWlanWGDS"
|
||||
#define IWL_UEFI_PPAG_NAME L"UefiCnvWlanPPAG"
|
||||
#define IWL_UEFI_WTAS_NAME L"UefiCnvWlanWTAS"
|
||||
#define IWL_UEFI_SPLC_NAME L"UefiCnvWlanSPLC"
|
||||
#define IWL_UEFI_WRDD_NAME L"UefiCnvWlanWRDD"
|
||||
#define IWL_UEFI_ECKV_NAME L"UefiCnvWlanECKV"
|
||||
#define IWL_UEFI_DSM_NAME L"UefiCnvWlanGeneralCfg"
|
||||
#define IWL_UEFI_WBEM_NAME L"UefiCnvWlanWBEM"
|
||||
|
||||
|
||||
#define IWL_SGOM_MAP_SIZE 339
|
||||
#define IWL_UATS_MAP_SIZE 339
|
||||
|
||||
#define IWL_UEFI_WRDS_REVISION 2
|
||||
#define IWL_UEFI_EWRD_REVISION 2
|
||||
#define IWL_UEFI_WGDS_REVISION 3
|
||||
#define IWL_UEFI_MIN_PPAG_REV 1
|
||||
#define IWL_UEFI_MAX_PPAG_REV 3
|
||||
#define IWL_UEFI_WTAS_REVISION 1
|
||||
#define IWL_UEFI_SPLC_REVISION 0
|
||||
#define IWL_UEFI_WRDD_REVISION 0
|
||||
#define IWL_UEFI_ECKV_REVISION 0
|
||||
#define IWL_UEFI_WBEM_REVISION 0
|
||||
#define IWL_UEFI_DSM_REVISION 4
|
||||
|
||||
struct pnvm_sku_package {
|
||||
u8 rev;
|
||||
|
|
@ -25,6 +52,11 @@ struct uefi_cnv_wlan_sgom_data {
|
|||
u8 offset_map[IWL_SGOM_MAP_SIZE - 1];
|
||||
} __packed;
|
||||
|
||||
struct uefi_cnv_wlan_uats_data {
|
||||
u8 revision;
|
||||
u8 offset_map[IWL_UATS_MAP_SIZE - 1];
|
||||
} __packed;
|
||||
|
||||
struct uefi_cnv_common_step_data {
|
||||
u8 revision;
|
||||
u8 step_mode;
|
||||
|
|
@ -34,6 +66,134 @@ struct uefi_cnv_common_step_data {
|
|||
u8 radio2;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* struct uefi_sar_profile - a SAR profile as defined in UEFI
|
||||
*
|
||||
* @chains: a per-chain table of SAR values
|
||||
*/
|
||||
struct uefi_sar_profile {
|
||||
struct iwl_sar_profile_chain chains[BIOS_SAR_MAX_CHAINS_PER_PROFILE];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* struct uefi_cnv_var_wrds - WRDS table as defined in UEFI
|
||||
*
|
||||
* @revision: the revision of the table
|
||||
* @mode: is WRDS enbaled/disabled
|
||||
* @sar_profile: sar profile #1
|
||||
*/
|
||||
struct uefi_cnv_var_wrds {
|
||||
u8 revision;
|
||||
u32 mode;
|
||||
struct uefi_sar_profile sar_profile;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* struct uefi_cnv_var_ewrd - EWRD table as defined in UEFI
|
||||
* @revision: the revision of the table
|
||||
* @mode: is WRDS enbaled/disabled
|
||||
* @num_profiles: how many additional profiles we have in this table (0-3)
|
||||
* @sar_profiles: the additional SAR profiles (#2-#4)
|
||||
*/
|
||||
struct uefi_cnv_var_ewrd {
|
||||
u8 revision;
|
||||
u32 mode;
|
||||
u32 num_profiles;
|
||||
struct uefi_sar_profile sar_profiles[BIOS_SAR_MAX_PROFILE_NUM - 1];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* struct uefi_cnv_var_wgds - WGDS table as defined in UEFI
|
||||
* @revision: the revision of the table
|
||||
* @num_profiles: the number of geo profiles we have in the table.
|
||||
* The first 3 are mandatory, and can have up to 8.
|
||||
* @geo_profiles: a per-profile table of the offsets to add to SAR values.
|
||||
*/
|
||||
struct uefi_cnv_var_wgds {
|
||||
u8 revision;
|
||||
u8 num_profiles;
|
||||
struct iwl_geo_profile geo_profiles[BIOS_GEO_MAX_PROFILE_NUM];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* struct uefi_cnv_var_ppag - PPAG table as defined in UEFI
|
||||
* @revision: the revision of the table
|
||||
* @ppag_modes: values from &enum iwl_ppag_flags
|
||||
* @ppag_chains: the PPAG values per chain and band
|
||||
*/
|
||||
struct uefi_cnv_var_ppag {
|
||||
u8 revision;
|
||||
u32 ppag_modes;
|
||||
struct iwl_ppag_chain ppag_chains[IWL_NUM_CHAIN_LIMITS];
|
||||
} __packed;
|
||||
|
||||
/* struct uefi_cnv_var_wtas - WTAS tabled as defined in UEFI
|
||||
* @revision: the revision of the table
|
||||
* @tas_selection: different options of TAS enablement.
|
||||
* @black_list_size: the number of defined entried in the black list
|
||||
* @black_list: a list of countries that are not allowed to use the TAS feature
|
||||
*/
|
||||
struct uefi_cnv_var_wtas {
|
||||
u8 revision;
|
||||
u32 tas_selection;
|
||||
u8 black_list_size;
|
||||
u16 black_list[IWL_WTAS_BLACK_LIST_MAX];
|
||||
} __packed;
|
||||
|
||||
/* struct uefi_cnv_var_splc - SPLC tabled as defined in UEFI
|
||||
* @revision: the revision of the table
|
||||
* @default_pwr_limit: The default maximum power per device
|
||||
*/
|
||||
struct uefi_cnv_var_splc {
|
||||
u8 revision;
|
||||
u32 default_pwr_limit;
|
||||
} __packed;
|
||||
|
||||
#define UEFI_MCC_CHINA 0x434e
|
||||
|
||||
/* struct uefi_cnv_var_wrdd - WRDD table as defined in UEFI
|
||||
* @revision: the revision of the table
|
||||
* @mcc: country identifier as defined in ISO/IEC 3166-1 Alpha 2 code
|
||||
*/
|
||||
struct uefi_cnv_var_wrdd {
|
||||
u8 revision;
|
||||
u32 mcc;
|
||||
} __packed;
|
||||
|
||||
/* struct uefi_cnv_var_eckv - ECKV table as defined in UEFI
|
||||
* @revision: the revision of the table
|
||||
* @ext_clock_valid: indicates if external 32KHz clock is valid
|
||||
*/
|
||||
struct uefi_cnv_var_eckv {
|
||||
u8 revision;
|
||||
u32 ext_clock_valid;
|
||||
} __packed;
|
||||
|
||||
#define UEFI_MAX_DSM_FUNCS 32
|
||||
|
||||
/* struct uefi_cnv_var_general_cfg - DSM-like table as defined in UEFI
|
||||
* @revision: the revision of the table
|
||||
* @functions: payload of the different DSM functions
|
||||
*/
|
||||
struct uefi_cnv_var_general_cfg {
|
||||
u8 revision;
|
||||
u32 functions[UEFI_MAX_DSM_FUNCS];
|
||||
} __packed;
|
||||
|
||||
#define IWL_UEFI_WBEM_REV0_MASK (BIT(0) | BIT(1))
|
||||
/* struct uefi_cnv_wlan_wbem_data - Bandwidth enablement per MCC as defined
|
||||
* in UEFI
|
||||
* @revision: the revision of the table
|
||||
* @wbem_320mhz_per_mcc: enablement of 320MHz bandwidth per MCC
|
||||
* bit 0 - if set, 320MHz is enabled for Japan
|
||||
* bit 1 - if set, 320MHz is enabled for South Korea
|
||||
* bit 2- 31, Reserved
|
||||
*/
|
||||
struct uefi_cnv_wlan_wbem_data {
|
||||
u8 revision;
|
||||
u32 wbem_320mhz_per_mcc;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* This is known to be broken on v4.19 and to work on v5.4. Until we
|
||||
* figure out why this is the case and how to make it work, simply
|
||||
|
|
@ -48,6 +208,22 @@ int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
|
|||
void iwl_uefi_get_step_table(struct iwl_trans *trans);
|
||||
int iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data,
|
||||
u32 tlv_len, struct iwl_pnvm_image *pnvm_data);
|
||||
int iwl_uefi_get_wrds_table(struct iwl_fw_runtime *fwrt);
|
||||
int iwl_uefi_get_ewrd_table(struct iwl_fw_runtime *fwrt);
|
||||
int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt);
|
||||
int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt);
|
||||
int iwl_uefi_get_tas_table(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_tas_data *data);
|
||||
int iwl_uefi_get_pwr_limit(struct iwl_fw_runtime *fwrt,
|
||||
u64 *dflt_pwr_limit);
|
||||
int iwl_uefi_get_mcc(struct iwl_fw_runtime *fwrt, char *mcc);
|
||||
int iwl_uefi_get_eckv(struct iwl_fw_runtime *fwrt, u32 *extl_clk);
|
||||
int iwl_uefi_get_wbem(struct iwl_fw_runtime *fwrt, u32 *value);
|
||||
int iwl_uefi_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
|
||||
u32 *value);
|
||||
void iwl_uefi_get_sgom_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt);
|
||||
int iwl_uefi_get_uats_table(struct iwl_trans *trans,
|
||||
struct iwl_fw_runtime *fwrt);
|
||||
#else /* CONFIG_EFI */
|
||||
static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
|
||||
{
|
||||
|
|
@ -78,14 +254,71 @@ iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data,
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_EFI */
|
||||
|
||||
#if defined(CONFIG_EFI) && defined(CONFIG_ACPI)
|
||||
void iwl_uefi_get_sgom_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt);
|
||||
#else
|
||||
static inline int iwl_uefi_get_wrds_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_uefi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_uefi_get_tas_table(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_tas_data *data)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_uefi_get_pwr_limit(struct iwl_fw_runtime *fwrt,
|
||||
u64 *dflt_pwr_limit)
|
||||
{
|
||||
*dflt_pwr_limit = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int iwl_uefi_get_mcc(struct iwl_fw_runtime *fwrt, char *mcc)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_uefi_get_eckv(struct iwl_fw_runtime *fwrt, u32 *extl_clk)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_uefi_get_wbem(struct iwl_fw_runtime *fwrt, u32 *value)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_uefi_get_dsm(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_dsm_funcs func, u32 *value)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline
|
||||
void iwl_uefi_get_sgom_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline
|
||||
int iwl_uefi_get_uats_table(struct iwl_trans *trans,
|
||||
struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_EFI */
|
||||
#endif /* __iwl_fw_uefi__ */
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2021 Intel Corporation
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2018-2024 Intel Corporation
|
||||
*/
|
||||
#ifndef __IWL_CONFIG_H__
|
||||
#define __IWL_CONFIG_H__
|
||||
|
|
@ -11,7 +11,9 @@
|
|||
#include <linux/netdevice.h>
|
||||
#include <linux/ieee80211.h>
|
||||
#include <linux/nl80211.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include "iwl-csr.h"
|
||||
#include "iwl-drv.h"
|
||||
|
||||
enum iwl_device_family {
|
||||
IWL_DEVICE_FAMILY_UNDEFINED,
|
||||
|
|
@ -122,10 +124,7 @@ enum iwl_nvm_type {
|
|||
#define IWL_DEFAULT_MAX_TX_POWER 22
|
||||
#define IWL_TX_CSUM_NETIF_FLAGS (NETIF_F_IPV6_CSUM | NETIF_F_IP_CSUM |\
|
||||
NETIF_F_TSO | NETIF_F_TSO6)
|
||||
#define IWL_TX_CSUM_NETIF_FLAGS_BZ (NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6)
|
||||
#define IWL_CSUM_NETIF_FLAGS_MASK (IWL_TX_CSUM_NETIF_FLAGS | \
|
||||
IWL_TX_CSUM_NETIF_FLAGS_BZ | \
|
||||
NETIF_F_RXCSUM)
|
||||
#define IWL_CSUM_NETIF_FLAGS_MASK (IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM)
|
||||
|
||||
/* Antenna presence definitions */
|
||||
#define ANT_NONE 0x0
|
||||
|
|
@ -278,7 +277,7 @@ enum iwl_cfg_trans_ltr_delay {
|
|||
};
|
||||
|
||||
/**
|
||||
* struct iwl_cfg_trans - information needed to start the trans
|
||||
* struct iwl_cfg_trans_params - information needed to start the trans
|
||||
*
|
||||
* These values are specific to the device ID and do not change when
|
||||
* multiple configs are used for a single device ID. They values are
|
||||
|
|
@ -286,7 +285,6 @@ enum iwl_cfg_trans_ltr_delay {
|
|||
* RFID can be read before deciding the remaining parameters to use.
|
||||
*
|
||||
* @base_params: pointer to basic parameters
|
||||
* @csr: csr flags and addresses that are different across devices
|
||||
* @device_family: the device family
|
||||
* @umac_prph_offset: offset to add to UMAC periphery address
|
||||
* @xtal_latency: power up latency to get the xtal stabilized
|
||||
|
|
@ -296,6 +294,7 @@ enum iwl_cfg_trans_ltr_delay {
|
|||
* @mq_rx_supported: multi-queue rx support
|
||||
* @integrated: discrete or integrated
|
||||
* @low_latency_xtal: use the low latency xtal if supported
|
||||
* @bisr_workaround: BISR hardware workaround (for 22260 series devices)
|
||||
* @ltr_delay: LTR delay parameter, &enum iwl_cfg_trans_ltr_delay.
|
||||
* @imr_enabled: use the IMR if supported.
|
||||
*/
|
||||
|
|
@ -355,7 +354,6 @@ struct iwl_fw_mon_regs {
|
|||
* @non_shared_ant: the antenna that is for WiFi only
|
||||
* @nvm_ver: NVM version
|
||||
* @nvm_calib_ver: NVM calibration version
|
||||
* @lib: pointer to the lib ops
|
||||
* @ht_params: point to ht parameters
|
||||
* @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off)
|
||||
* @rx_with_siso_diversity: 1x1 device with rx antenna diversity
|
||||
|
|
@ -380,15 +378,12 @@ struct iwl_fw_mon_regs {
|
|||
* @nvm_type: see &enum iwl_nvm_type
|
||||
* @d3_debug_data_base_addr: base address where D3 debug data is stored
|
||||
* @d3_debug_data_length: length of the D3 debug data
|
||||
* @bisr_workaround: BISR hardware workaround (for 22260 series devices)
|
||||
* @min_txq_size: minimum number of slots required in a TX queue
|
||||
* @uhb_supported: ultra high band channels supported
|
||||
* @min_ba_txq_size: minimum number of slots required in a TX queue which
|
||||
* based on hardware support (HE - 256, EHT - 1K).
|
||||
* @num_rbds: number of receive buffer descriptors to use
|
||||
* (only used for multi-queue capable devices)
|
||||
* @mac_addr_csr_base: CSR base register for MAC address access, if not set
|
||||
* assume 0x380
|
||||
*
|
||||
* We enable the driver to be backward compatible wrt. hardware features.
|
||||
* API differences in uCode shouldn't be handled here but through TLVs
|
||||
|
|
@ -421,7 +416,6 @@ struct iwl_cfg {
|
|||
u16 nvm_calib_ver;
|
||||
u32 rx_with_siso_diversity:1,
|
||||
tx_with_siso_diversity:1,
|
||||
bt_shared_single_ant:1,
|
||||
internal_wimax_coex:1,
|
||||
host_interrupt_operation_mode:1,
|
||||
high_temp:1,
|
||||
|
|
@ -463,6 +457,9 @@ struct iwl_cfg {
|
|||
#define IWL_CFG_MAC_TYPE_BZ 0x46
|
||||
#define IWL_CFG_MAC_TYPE_GL 0x47
|
||||
#define IWL_CFG_MAC_TYPE_SC 0x48
|
||||
#define IWL_CFG_MAC_TYPE_SC2 0x49
|
||||
#define IWL_CFG_MAC_TYPE_SC2F 0x4A
|
||||
#define IWL_CFG_MAC_TYPE_BZ_W 0x4B
|
||||
|
||||
#define IWL_CFG_RF_TYPE_TH 0x105
|
||||
#define IWL_CFG_RF_TYPE_TH1 0x108
|
||||
|
|
@ -471,8 +468,6 @@ struct iwl_cfg {
|
|||
#define IWL_CFG_RF_TYPE_HR2 0x10A
|
||||
#define IWL_CFG_RF_TYPE_HR1 0x10C
|
||||
#define IWL_CFG_RF_TYPE_GF 0x10D
|
||||
#define IWL_CFG_RF_TYPE_MR 0x110
|
||||
#define IWL_CFG_RF_TYPE_MS 0x111
|
||||
#define IWL_CFG_RF_TYPE_FM 0x112
|
||||
#define IWL_CFG_RF_TYPE_WH 0x113
|
||||
|
||||
|
|
@ -487,6 +482,9 @@ struct iwl_cfg {
|
|||
#define IWL_CFG_NO_160 0x1
|
||||
#define IWL_CFG_160 0x0
|
||||
|
||||
#define IWL_CFG_NO_320 0x1
|
||||
#define IWL_CFG_320 0x0
|
||||
|
||||
#define IWL_CFG_CORES_BT 0x0
|
||||
#define IWL_CFG_CORES_BT_GNSS 0x5
|
||||
|
||||
|
|
@ -516,6 +514,16 @@ struct iwl_dev_info {
|
|||
const char *name;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS)
|
||||
extern const struct iwl_dev_info iwl_dev_info_table[];
|
||||
extern const unsigned int iwl_dev_info_table_size;
|
||||
const struct iwl_dev_info *
|
||||
iwl_pci_find_dev_info(u16 device, u16 subsystem_device,
|
||||
u16 mac_type, u8 mac_step, u16 rf_type, u8 cdb,
|
||||
u8 jacket, u8 rf_id, u8 no_160, u8 cores, u8 rf_step);
|
||||
extern const struct pci_device_id iwl_hw_card_ids[];
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This list declares the config structures for all devices.
|
||||
*/
|
||||
|
|
@ -571,7 +579,12 @@ extern const char iwl_ax221_name[];
|
|||
extern const char iwl_ax231_name[];
|
||||
extern const char iwl_ax411_name[];
|
||||
extern const char iwl_bz_name[];
|
||||
extern const char iwl_fm_name[];
|
||||
extern const char iwl_gl_name[];
|
||||
extern const char iwl_mtp_name[];
|
||||
extern const char iwl_sc_name[];
|
||||
extern const char iwl_sc2_name[];
|
||||
extern const char iwl_sc2f_name[];
|
||||
#if IS_ENABLED(CONFIG_IWLDVM)
|
||||
extern const struct iwl_cfg iwl5300_agn_cfg;
|
||||
extern const struct iwl_cfg iwl5100_agn_cfg;
|
||||
|
|
@ -677,6 +690,8 @@ extern const struct iwl_cfg iwl_cfg_bz;
|
|||
extern const struct iwl_cfg iwl_cfg_gl;
|
||||
|
||||
extern const struct iwl_cfg iwl_cfg_sc;
|
||||
extern const struct iwl_cfg iwl_cfg_sc2;
|
||||
extern const struct iwl_cfg iwl_cfg_sc2f;
|
||||
#endif /* CONFIG_IWLMVM */
|
||||
|
||||
#endif /* __IWL_CONFIG_H__ */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2018, 2020-2022 Intel Corporation
|
||||
* Copyright (C) 2018, 2020-2024 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_context_info_file_gen3_h__
|
||||
#define __iwl_context_info_file_gen3_h__
|
||||
|
|
@ -44,7 +44,7 @@ enum iwl_prph_scratch_mtr_format {
|
|||
* @IWL_PRPH_SCRATCH_EDBG_DEST_ST_ARBITER: use st arbiter, mainly for
|
||||
* multicomm.
|
||||
* @IWL_PRPH_SCRATCH_EDBG_DEST_TB22DTF: route debug data to SoC HW
|
||||
* @IWL_PRPH_SCTATCH_RB_SIZE_4K: Use 4K RB size (the default is 2K)
|
||||
* @IWL_PRPH_SCRATCH_RB_SIZE_4K: Use 4K RB size (the default is 2K)
|
||||
* @IWL_PRPH_SCRATCH_MTR_MODE: format used for completion - 0: for
|
||||
* completion descriptor, 1 for responses (legacy)
|
||||
* @IWL_PRPH_SCRATCH_MTR_FORMAT: a mask for the size of the tfd.
|
||||
|
|
@ -56,6 +56,8 @@ enum iwl_prph_scratch_mtr_format {
|
|||
* @IWL_PRPH_SCRATCH_RB_SIZE_EXT_8K: 8kB RB size
|
||||
* @IWL_PRPH_SCRATCH_RB_SIZE_EXT_12K: 12kB RB size
|
||||
* @IWL_PRPH_SCRATCH_RB_SIZE_EXT_16K: 16kB RB size
|
||||
* @IWL_PRPH_SCRATCH_SCU_FORCE_ACTIVE: Indicate fw to set SCU_FORCE_ACTIVE
|
||||
* upon reset.
|
||||
*/
|
||||
enum iwl_prph_scratch_flags {
|
||||
IWL_PRPH_SCRATCH_IMR_DEBUG_EN = BIT(1),
|
||||
|
|
@ -71,6 +73,7 @@ enum iwl_prph_scratch_flags {
|
|||
IWL_PRPH_SCRATCH_RB_SIZE_EXT_8K = 8 << 20,
|
||||
IWL_PRPH_SCRATCH_RB_SIZE_EXT_12K = 9 << 20,
|
||||
IWL_PRPH_SCRATCH_RB_SIZE_EXT_16K = 10 << 20,
|
||||
IWL_PRPH_SCRATCH_SCU_FORCE_ACTIVE = BIT(29),
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -187,11 +190,15 @@ struct iwl_prph_scratch_ctrl_cfg {
|
|||
* struct iwl_prph_scratch - peripheral scratch mapping
|
||||
* @ctrl_cfg: control and configuration of prph scratch
|
||||
* @dram: firmware images addresses in DRAM
|
||||
* @fseq_override: FSEQ override parameters
|
||||
* @step_analog_params: STEP analog calibration values
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_prph_scratch {
|
||||
struct iwl_prph_scratch_ctrl_cfg ctrl_cfg;
|
||||
__le32 reserved[10];
|
||||
__le32 fseq_override;
|
||||
__le32 step_analog_params;
|
||||
__le32 reserved[8];
|
||||
struct iwl_context_info_dram dram;
|
||||
} __packed; /* PERIPH_SCRATCH_S */
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -304,15 +304,14 @@
|
|||
#define CSR_HW_RFID_IS_CDB(_val) (((_val) & 0x10000000) >> 28)
|
||||
#define CSR_HW_RFID_IS_JACKET(_val) (((_val) & 0x20000000) >> 29)
|
||||
|
||||
/**
|
||||
* hw_rev values
|
||||
*/
|
||||
/* hw_rev values */
|
||||
enum {
|
||||
SILICON_A_STEP = 0,
|
||||
SILICON_B_STEP,
|
||||
SILICON_C_STEP,
|
||||
SILICON_D_STEP,
|
||||
SILICON_E_STEP,
|
||||
SILICON_TC_STEP = 0xe,
|
||||
SILICON_Z_STEP = 0xf,
|
||||
};
|
||||
|
||||
|
|
@ -353,6 +352,8 @@ enum {
|
|||
#define CSR_HW_RF_ID_TYPE_GF (0x0010D000)
|
||||
#define CSR_HW_RF_ID_TYPE_GF4 (0x0010E000)
|
||||
#define CSR_HW_RF_ID_TYPE_MS (0x00111000)
|
||||
#define CSR_HW_RF_ID_TYPE_FM (0x00112000)
|
||||
#define CSR_HW_RF_ID_TYPE_WP (0x00113000)
|
||||
|
||||
/* HW_RF CHIP STEP */
|
||||
#define CSR_HW_RF_STEP(_val) (((_val) >> 8) & 0xF)
|
||||
|
|
@ -618,6 +619,7 @@ enum msix_hw_int_causes {
|
|||
MSIX_HW_INT_CAUSES_REG_WAKEUP = BIT(1),
|
||||
MSIX_HW_INT_CAUSES_REG_IML = BIT(1),
|
||||
MSIX_HW_INT_CAUSES_REG_RESET_DONE = BIT(2),
|
||||
MSIX_HW_INT_CAUSES_REG_TOP_FATAL_ERR = BIT(3),
|
||||
MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ = BIT(5),
|
||||
MSIX_HW_INT_CAUSES_REG_CT_KILL = BIT(6),
|
||||
MSIX_HW_INT_CAUSES_REG_RF_KILL = BIT(7),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2018-2024 Intel Corporation
|
||||
*/
|
||||
#include <linux/firmware.h>
|
||||
#include "iwl-drv.h"
|
||||
|
|
@ -64,21 +64,22 @@ dbg_ver_table[IWL_DBG_TLV_TYPE_NUM] = {
|
|||
[IWL_DBG_TLV_TYPE_CONF_SET] = {.min_ver = 1, .max_ver = 1,},
|
||||
};
|
||||
|
||||
static int iwl_dbg_tlv_add(const struct iwl_ucode_tlv *tlv,
|
||||
struct list_head *list)
|
||||
/* add a new TLV node, returning it so it can be modified */
|
||||
static struct iwl_ucode_tlv *iwl_dbg_tlv_add(const struct iwl_ucode_tlv *tlv,
|
||||
struct list_head *list)
|
||||
{
|
||||
u32 len = le32_to_cpu(tlv->length);
|
||||
struct iwl_dbg_tlv_node *node;
|
||||
|
||||
node = kzalloc(sizeof(*node) + len, GFP_KERNEL);
|
||||
node = kzalloc(struct_size(node, tlv.data, len), GFP_KERNEL);
|
||||
if (!node)
|
||||
return -ENOMEM;
|
||||
return NULL;
|
||||
|
||||
memcpy(&node->tlv, tlv, sizeof(node->tlv));
|
||||
memcpy(node->tlv.data, tlv->data, len);
|
||||
list_add_tail(&node->list, list);
|
||||
|
||||
return 0;
|
||||
return &node->tlv;
|
||||
}
|
||||
|
||||
static bool iwl_dbg_tlv_ver_support(const struct iwl_ucode_tlv *tlv)
|
||||
|
|
@ -103,10 +104,18 @@ static int iwl_dbg_tlv_alloc_debug_info(struct iwl_trans *trans,
|
|||
if (le32_to_cpu(tlv->length) != sizeof(*debug_info))
|
||||
return -EINVAL;
|
||||
|
||||
/* we use this as a string, ensure input was NUL terminated */
|
||||
if (strnlen(debug_info->debug_cfg_name,
|
||||
sizeof(debug_info->debug_cfg_name)) ==
|
||||
sizeof(debug_info->debug_cfg_name))
|
||||
return -EINVAL;
|
||||
|
||||
IWL_DEBUG_FW(trans, "WRT: Loading debug cfg: %s\n",
|
||||
debug_info->debug_cfg_name);
|
||||
|
||||
return iwl_dbg_tlv_add(tlv, &trans->dbg.debug_info_tlv_list);
|
||||
if (!iwl_dbg_tlv_add(tlv, &trans->dbg.debug_info_tlv_list))
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_dbg_tlv_alloc_buf_alloc(struct iwl_trans *trans,
|
||||
|
|
@ -175,7 +184,9 @@ static int iwl_dbg_tlv_alloc_hcmd(struct iwl_trans *trans,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
return iwl_dbg_tlv_add(tlv, &trans->dbg.time_point[tp].hcmd_list);
|
||||
if (!iwl_dbg_tlv_add(tlv, &trans->dbg.time_point[tp].hcmd_list))
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_dbg_tlv_alloc_region(struct iwl_trans *trans,
|
||||
|
|
@ -212,12 +223,6 @@ static int iwl_dbg_tlv_alloc_region(struct iwl_trans *trans,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (type == IWL_FW_INI_REGION_PCI_IOSF_CONFIG &&
|
||||
!trans->ops->read_config32) {
|
||||
IWL_ERR(trans, "WRT: Unsupported region type %u\n", type);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (type == IWL_FW_INI_REGION_INTERNAL_BUFFER) {
|
||||
trans->dbg.imr_data.sram_addr =
|
||||
le32_to_cpu(reg->internal_buffer.base_addr);
|
||||
|
|
@ -246,11 +251,9 @@ static int iwl_dbg_tlv_alloc_trigger(struct iwl_trans *trans,
|
|||
const struct iwl_ucode_tlv *tlv)
|
||||
{
|
||||
const struct iwl_fw_ini_trigger_tlv *trig = (const void *)tlv->data;
|
||||
struct iwl_fw_ini_trigger_tlv *dup_trig;
|
||||
u32 tp = le32_to_cpu(trig->time_point);
|
||||
u32 rf = le32_to_cpu(trig->reset_fw);
|
||||
struct iwl_ucode_tlv *dup = NULL;
|
||||
int ret;
|
||||
struct iwl_ucode_tlv *new_tlv;
|
||||
|
||||
if (le32_to_cpu(tlv->length) < sizeof(*trig))
|
||||
return -EINVAL;
|
||||
|
|
@ -267,20 +270,18 @@ static int iwl_dbg_tlv_alloc_trigger(struct iwl_trans *trans,
|
|||
"WRT: time point %u for trigger TLV with reset_fw %u\n",
|
||||
tp, rf);
|
||||
trans->dbg.last_tp_resetfw = 0xFF;
|
||||
|
||||
new_tlv = iwl_dbg_tlv_add(tlv, &trans->dbg.time_point[tp].trig_list);
|
||||
if (!new_tlv)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!le32_to_cpu(trig->occurrences)) {
|
||||
dup = kmemdup(tlv, sizeof(*tlv) + le32_to_cpu(tlv->length),
|
||||
GFP_KERNEL);
|
||||
if (!dup)
|
||||
return -ENOMEM;
|
||||
dup_trig = (void *)dup->data;
|
||||
dup_trig->occurrences = cpu_to_le32(-1);
|
||||
tlv = dup;
|
||||
struct iwl_fw_ini_trigger_tlv *new_trig = (void *)new_tlv->data;
|
||||
|
||||
new_trig->occurrences = cpu_to_le32(-1);
|
||||
}
|
||||
|
||||
ret = iwl_dbg_tlv_add(tlv, &trans->dbg.time_point[tp].trig_list);
|
||||
kfree(dup);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_dbg_tlv_config_set(struct iwl_trans *trans,
|
||||
|
|
@ -304,7 +305,9 @@ static int iwl_dbg_tlv_config_set(struct iwl_trans *trans,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
return iwl_dbg_tlv_add(tlv, &trans->dbg.time_point[tp].config_list);
|
||||
if (!iwl_dbg_tlv_add(tlv, &trans->dbg.time_point[tp].config_list))
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int (*dbg_tlv_alloc[])(struct iwl_trans *trans,
|
||||
|
|
@ -509,6 +512,8 @@ void iwl_dbg_tlv_load_bin(struct device *dev, struct iwl_trans *trans)
|
|||
if (res)
|
||||
return;
|
||||
|
||||
trans->dbg.yoyo_bin_loaded = true;
|
||||
|
||||
iwl_dbg_tlv_parse_bin(trans, fw->data, fw->size);
|
||||
|
||||
release_firmware(fw);
|
||||
|
|
@ -1094,7 +1099,7 @@ static int iwl_dbg_tlv_override_trig_node(struct iwl_fw_runtime *fwrt,
|
|||
node_trig = (void *)node_tlv->data;
|
||||
}
|
||||
|
||||
memcpy(node_trig->data + offset, trig->data, trig_data_len);
|
||||
memcpy((u8 *)node_trig->data + offset, trig->data, trig_data_len);
|
||||
node_tlv->length = cpu_to_le32(size);
|
||||
|
||||
if (policy & IWL_FW_INI_APPLY_POLICY_OVERRIDE_CFG) {
|
||||
|
|
@ -1146,7 +1151,9 @@ iwl_dbg_tlv_add_active_trigger(struct iwl_fw_runtime *fwrt,
|
|||
if (!match) {
|
||||
IWL_DEBUG_FW(fwrt, "WRT: Enabling trigger (time point %u)\n",
|
||||
le32_to_cpu(trig->time_point));
|
||||
return iwl_dbg_tlv_add(trig_tlv, trig_list);
|
||||
if (!iwl_dbg_tlv_add(trig_tlv, trig_list))
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return iwl_dbg_tlv_override_trig_node(fwrt, trig_tlv, match);
|
||||
|
|
@ -1232,38 +1239,27 @@ iwl_dbg_tlv_tp_trigger(struct iwl_fw_runtime *fwrt, bool sync,
|
|||
}
|
||||
}
|
||||
|
||||
fwrt->trans->dbg.restart_required = FALSE;
|
||||
IWL_DEBUG_FW(fwrt, "WRT: tp %d, reset_fw %d\n",
|
||||
tp, dump_data.trig->reset_fw);
|
||||
IWL_DEBUG_FW(fwrt,
|
||||
"WRT: restart_required %d, last_tp_resetfw %d\n",
|
||||
fwrt->trans->dbg.restart_required,
|
||||
fwrt->trans->dbg.last_tp_resetfw);
|
||||
fwrt->trans->dbg.restart_required = false;
|
||||
|
||||
if (fwrt->trans->trans_cfg->device_family ==
|
||||
IWL_DEVICE_FAMILY_9000) {
|
||||
fwrt->trans->dbg.restart_required = TRUE;
|
||||
fwrt->trans->dbg.restart_required = true;
|
||||
} else if (tp == IWL_FW_INI_TIME_POINT_FW_ASSERT &&
|
||||
fwrt->trans->dbg.last_tp_resetfw ==
|
||||
IWL_FW_INI_RESET_FW_MODE_STOP_FW_ONLY) {
|
||||
fwrt->trans->dbg.restart_required = FALSE;
|
||||
fwrt->trans->dbg.restart_required = false;
|
||||
fwrt->trans->dbg.last_tp_resetfw = 0xFF;
|
||||
IWL_DEBUG_FW(fwrt, "WRT: FW_ASSERT due to reset_fw_mode-no restart\n");
|
||||
} else if (le32_to_cpu(dump_data.trig->reset_fw) ==
|
||||
IWL_FW_INI_RESET_FW_MODE_STOP_AND_RELOAD_FW) {
|
||||
IWL_DEBUG_FW(fwrt, "WRT: stop and reload firmware\n");
|
||||
fwrt->trans->dbg.restart_required = TRUE;
|
||||
fwrt->trans->dbg.restart_required = true;
|
||||
} else if (le32_to_cpu(dump_data.trig->reset_fw) ==
|
||||
IWL_FW_INI_RESET_FW_MODE_STOP_FW_ONLY) {
|
||||
IWL_DEBUG_FW(fwrt,
|
||||
"WRT: stop only and no reload firmware\n");
|
||||
fwrt->trans->dbg.restart_required = FALSE;
|
||||
fwrt->trans->dbg.restart_required = false;
|
||||
fwrt->trans->dbg.last_tp_resetfw =
|
||||
le32_to_cpu(dump_data.trig->reset_fw);
|
||||
} else if (le32_to_cpu(dump_data.trig->reset_fw) ==
|
||||
IWL_FW_INI_RESET_FW_MODE_NOTHING) {
|
||||
IWL_DEBUG_FW(fwrt,
|
||||
"WRT: nothing need to be done after debug collection\n");
|
||||
/* nothing */
|
||||
} else {
|
||||
IWL_ERR(fwrt, "WRT: wrong resetfw %d\n",
|
||||
le32_to_cpu(dump_data.trig->reset_fw));
|
||||
|
|
@ -1272,7 +1268,7 @@ iwl_dbg_tlv_tp_trigger(struct iwl_fw_runtime *fwrt, bool sync,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt)
|
||||
void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
enum iwl_fw_ini_buffer_location *ini_dest = &fwrt->trans->dbg.ini_dest;
|
||||
int ret, i;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2018-2023 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_dbg_tlv_h__
|
||||
#define __iwl_dbg_tlv_h__
|
||||
|
|
@ -10,7 +10,8 @@
|
|||
#include <fw/file.h>
|
||||
#include <fw/api/dbg-tlv.h>
|
||||
|
||||
#define IWL_DBG_TLV_MAX_PRESET 15
|
||||
#define IWL_DBG_TLV_MAX_PRESET 15
|
||||
#define ENABLE_INI (IWL_DBG_TLV_MAX_PRESET + 1)
|
||||
|
||||
/**
|
||||
* struct iwl_dbg_tlv_node - debug TLV node
|
||||
|
|
@ -56,6 +57,7 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,
|
|||
enum iwl_fw_ini_time_point tp_id,
|
||||
union iwl_dbg_tlv_tp_data *tp_data,
|
||||
bool sync);
|
||||
void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
static inline void iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_fw_ini_time_point tp_id,
|
||||
|
|
|
|||
|
|
@ -150,17 +150,18 @@ void __iwl_dbg(struct device *dev,
|
|||
vaf.va = &args;
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
if (iwl_have_debug_level(level) &&
|
||||
(!limit || net_ratelimit())) {
|
||||
(!limit || net_ratelimit()))
|
||||
#if defined(__linux_)
|
||||
dev_printk(KERN_DEBUG, dev, "%s %pV", function, &vaf);
|
||||
#elif defined(__FreeBSD__)
|
||||
{
|
||||
char *str;
|
||||
vasprintf(&str, M_KMALLOC, vaf.fmt, args);
|
||||
dev_printk(KERN_DEBUG, dev, "%d %u %s %s",
|
||||
curthread->td_tid, (unsigned int)ticks, function, str);
|
||||
free(str, M_KMALLOC);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
trace_iwlwifi_dbg(level, function, &vaf);
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ void trace_iwlwifi_dev_rx_data(const struct device *,
|
|||
#define trace_iwlwifi_dev_tx(...)
|
||||
#define trace_iwlwifi_dev_tx_tb(...)
|
||||
|
||||
#define maybe_trace_iwlwifi_dev_rx(...)
|
||||
|
||||
#define trace_iwlwifi_crit(...)
|
||||
#define trace_iwlwifi_dbg(...)
|
||||
#define trace_iwlwifi_err(...)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2021 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -34,9 +34,11 @@
|
|||
|
||||
#if defined(__linux__)
|
||||
#define DRV_DESCRIPTION "Intel(R) Wireless WiFi driver for Linux"
|
||||
MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
||||
MODULE_LICENSE("GPL");
|
||||
#elif defined(__FreeBSD__)
|
||||
#define DRV_DESCRIPTION "Intel(R) Wireless WiFi based driver for FreeBSD"
|
||||
MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
||||
MODULE_LICENSE("BSD");
|
||||
MODULE_VERSION(if_iwlwifi, 1);
|
||||
MODULE_DEPEND(if_iwlwifi, linuxkpi, 1, 1, 1);
|
||||
|
|
@ -45,7 +47,6 @@ MODULE_DEPEND(if_iwlwifi, linuxkpi_wlan, 1, 1, 1);
|
|||
MODULE_DEPEND(if_iwlwifi, lindebugfs, 1, 1, 1);
|
||||
#endif
|
||||
#endif
|
||||
MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
static struct dentry *iwl_dbgfs_root;
|
||||
|
|
@ -145,6 +146,7 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv)
|
|||
kfree(drv->fw.ucode_capa.cmd_versions);
|
||||
kfree(drv->fw.phy_integration_ver);
|
||||
kfree(drv->trans->dbg.pc_data);
|
||||
drv->trans->dbg.pc_data = NULL;
|
||||
|
||||
for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
|
||||
iwl_free_fw_img(drv, drv->fw.img + i);
|
||||
|
|
@ -179,6 +181,8 @@ static inline char iwl_drv_get_step(int step)
|
|||
{
|
||||
if (step == SILICON_Z_STEP)
|
||||
return 'z';
|
||||
if (step == SILICON_TC_STEP)
|
||||
return 'a';
|
||||
return 'a' + step;
|
||||
}
|
||||
|
||||
|
|
@ -195,25 +199,28 @@ const char *iwl_drv_get_fwname_pre(struct iwl_trans *trans, char *buf)
|
|||
|
||||
mac_step = iwl_drv_get_step(trans->hw_rev_step);
|
||||
|
||||
rf_step = iwl_drv_get_step(CSR_HW_RFID_STEP(trans->hw_rf_id));
|
||||
|
||||
switch (CSR_HW_RFID_TYPE(trans->hw_rf_id)) {
|
||||
case IWL_CFG_RF_TYPE_HR1:
|
||||
case IWL_CFG_RF_TYPE_HR2:
|
||||
rf = "hr";
|
||||
rf_step = 'b';
|
||||
break;
|
||||
case IWL_CFG_RF_TYPE_GF:
|
||||
rf = "gf";
|
||||
break;
|
||||
case IWL_CFG_RF_TYPE_MR:
|
||||
rf = "mr";
|
||||
break;
|
||||
case IWL_CFG_RF_TYPE_MS:
|
||||
rf = "ms";
|
||||
break;
|
||||
case IWL_CFG_RF_TYPE_FM:
|
||||
rf = "fm";
|
||||
break;
|
||||
case IWL_CFG_RF_TYPE_WH:
|
||||
rf = "wh";
|
||||
if (SILICON_Z_STEP ==
|
||||
CSR_HW_RFID_STEP(trans->hw_rf_id)) {
|
||||
rf = "whtc";
|
||||
rf_step = 'a';
|
||||
} else {
|
||||
rf = "wh";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return "unknown-rf";
|
||||
|
|
@ -221,8 +228,6 @@ const char *iwl_drv_get_fwname_pre(struct iwl_trans *trans, char *buf)
|
|||
|
||||
cdb = CSR_HW_RFID_IS_CDB(trans->hw_rf_id) ? "4" : "";
|
||||
|
||||
rf_step = iwl_drv_get_step(CSR_HW_RFID_STEP(trans->hw_rf_id));
|
||||
|
||||
scnprintf(buf, FW_NAME_PRE_BUFSIZE,
|
||||
"iwlwifi-%s-%c0-%s%s-%c0",
|
||||
trans->cfg->fw_name_mac, mac_step,
|
||||
|
|
@ -995,16 +1000,10 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
|||
minor = le32_to_cpup(ptr++);
|
||||
local_comp = le32_to_cpup(ptr);
|
||||
|
||||
if (major >= 35)
|
||||
snprintf(drv->fw.fw_version,
|
||||
sizeof(drv->fw.fw_version),
|
||||
"%u.%08x.%u %s", major, minor,
|
||||
local_comp, iwl_reduced_fw_name(drv));
|
||||
else
|
||||
snprintf(drv->fw.fw_version,
|
||||
sizeof(drv->fw.fw_version),
|
||||
"%u.%u.%u %s", major, minor,
|
||||
local_comp, iwl_reduced_fw_name(drv));
|
||||
snprintf(drv->fw.fw_version,
|
||||
sizeof(drv->fw.fw_version),
|
||||
"%u.%08x.%u %s", major, minor,
|
||||
local_comp, iwl_reduced_fw_name(drv));
|
||||
break;
|
||||
}
|
||||
case IWL_UCODE_TLV_FW_DBG_DEST: {
|
||||
|
|
@ -1320,10 +1319,12 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
|||
case IWL_UCODE_TLV_CURRENT_PC:
|
||||
if (tlv_len < sizeof(struct iwl_pc_data))
|
||||
goto invalid_tlv_len;
|
||||
drv->trans->dbg.num_pc =
|
||||
tlv_len / sizeof(struct iwl_pc_data);
|
||||
drv->trans->dbg.pc_data =
|
||||
kmemdup(tlv_data, tlv_len, GFP_KERNEL);
|
||||
if (!drv->trans->dbg.pc_data)
|
||||
return -ENOMEM;
|
||||
drv->trans->dbg.num_pc =
|
||||
tlv_len / sizeof(struct iwl_pc_data);
|
||||
break;
|
||||
default:
|
||||
IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
|
||||
|
|
@ -1442,35 +1443,34 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op)
|
|||
const struct iwl_op_mode_ops *ops = op->ops;
|
||||
struct dentry *dbgfs_dir = NULL;
|
||||
struct iwl_op_mode *op_mode = NULL;
|
||||
int retry, max_retry = !!iwlwifi_mod_params.fw_restart * IWL_MAX_INIT_RETRY;
|
||||
|
||||
for (retry = 0; retry <= max_retry; retry++) {
|
||||
/* also protects start/stop from racing against each other */
|
||||
lockdep_assert_held(&iwlwifi_opmode_table_mtx);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
drv->dbgfs_op_mode = debugfs_create_dir(op->name,
|
||||
drv->dbgfs_drv);
|
||||
dbgfs_dir = drv->dbgfs_op_mode;
|
||||
drv->dbgfs_op_mode = debugfs_create_dir(op->name,
|
||||
drv->dbgfs_drv);
|
||||
dbgfs_dir = drv->dbgfs_op_mode;
|
||||
#endif
|
||||
|
||||
op_mode = ops->start(drv->trans, drv->trans->cfg,
|
||||
&drv->fw, dbgfs_dir);
|
||||
|
||||
if (op_mode)
|
||||
return op_mode;
|
||||
|
||||
IWL_ERR(drv, "retry init count %d\n", retry);
|
||||
op_mode = ops->start(drv->trans, drv->trans->cfg,
|
||||
&drv->fw, dbgfs_dir);
|
||||
if (op_mode)
|
||||
return op_mode;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
debugfs_remove_recursive(drv->dbgfs_op_mode);
|
||||
drv->dbgfs_op_mode = NULL;
|
||||
debugfs_remove_recursive(drv->dbgfs_op_mode);
|
||||
drv->dbgfs_op_mode = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void _iwl_op_mode_stop(struct iwl_drv *drv)
|
||||
{
|
||||
/* also protects start/stop from racing against each other */
|
||||
lockdep_assert_held(&iwlwifi_opmode_table_mtx);
|
||||
|
||||
/* op_mode can be NULL if its start failed */
|
||||
if (drv->op_mode) {
|
||||
iwl_op_mode_stop(drv->op_mode);
|
||||
|
|
@ -1502,7 +1502,6 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
|||
size_t trigger_tlv_sz[FW_DBG_TRIGGER_MAX];
|
||||
u32 api_ver;
|
||||
int i;
|
||||
bool load_module = false;
|
||||
bool usniffer_images = false;
|
||||
bool failure = true;
|
||||
|
||||
|
|
@ -1750,24 +1749,12 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
|||
goto out_unbind;
|
||||
}
|
||||
} else {
|
||||
load_module = true;
|
||||
request_module_nowait("%s", op->name);
|
||||
}
|
||||
mutex_unlock(&iwlwifi_opmode_table_mtx);
|
||||
|
||||
/*
|
||||
* Complete the firmware request last so that
|
||||
* a driver unbind (stop) doesn't run while we
|
||||
* are doing the start() above.
|
||||
*/
|
||||
complete(&drv->request_firmware_complete);
|
||||
|
||||
/*
|
||||
* Load the module last so we don't block anything
|
||||
* else from proceeding if the module fails to load
|
||||
* or hangs loading.
|
||||
*/
|
||||
if (load_module)
|
||||
request_module("%s", op->name);
|
||||
failure = false;
|
||||
goto free;
|
||||
|
||||
|
|
@ -1827,6 +1814,22 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
|
|||
#endif
|
||||
|
||||
drv->trans->dbg.domains_bitmap = IWL_TRANS_FW_DBG_DOMAIN(drv->trans);
|
||||
if (iwlwifi_mod_params.enable_ini != ENABLE_INI) {
|
||||
/* We have a non-default value in the module parameter,
|
||||
* take its value
|
||||
*/
|
||||
drv->trans->dbg.domains_bitmap &= 0xffff;
|
||||
if (iwlwifi_mod_params.enable_ini != IWL_FW_INI_PRESET_DISABLE) {
|
||||
if (iwlwifi_mod_params.enable_ini > ENABLE_INI) {
|
||||
IWL_ERR(trans,
|
||||
"invalid enable_ini module parameter value: max = %d, using 0 instead\n",
|
||||
ENABLE_INI);
|
||||
iwlwifi_mod_params.enable_ini = 0;
|
||||
}
|
||||
drv->trans->dbg.domains_bitmap =
|
||||
BIT(IWL_FW_DBG_DOMAIN_POS + iwlwifi_mod_params.enable_ini);
|
||||
}
|
||||
}
|
||||
|
||||
ret = iwl_request_firmware(drv, true);
|
||||
if (ret) {
|
||||
|
|
@ -1850,8 +1853,8 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
|
|||
err_fw:
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
debugfs_remove_recursive(drv->dbgfs_drv);
|
||||
iwl_dbg_tlv_free(drv->trans);
|
||||
#endif
|
||||
iwl_dbg_tlv_free(drv->trans);
|
||||
kfree(drv);
|
||||
err:
|
||||
return ERR_PTR(ret);
|
||||
|
|
@ -1865,11 +1868,12 @@ void iwl_drv_stop(struct iwl_drv *drv)
|
|||
wait_for_completion(&drv->drv_start_complete);
|
||||
#endif
|
||||
|
||||
mutex_lock(&iwlwifi_opmode_table_mtx);
|
||||
|
||||
_iwl_op_mode_stop(drv);
|
||||
|
||||
iwl_dealloc_ucode(drv);
|
||||
|
||||
mutex_lock(&iwlwifi_opmode_table_mtx);
|
||||
/*
|
||||
* List is empty (this item wasn't added)
|
||||
* when firmware loading failed -- in that
|
||||
|
|
@ -1880,7 +1884,7 @@ void iwl_drv_stop(struct iwl_drv *drv)
|
|||
mutex_unlock(&iwlwifi_opmode_table_mtx);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
drv->trans->ops->debugfs_cleanup(drv->trans);
|
||||
iwl_trans_debugfs_cleanup(drv->trans);
|
||||
|
||||
debugfs_remove_recursive(drv->dbgfs_drv);
|
||||
#endif
|
||||
|
|
@ -1890,8 +1894,6 @@ void iwl_drv_stop(struct iwl_drv *drv)
|
|||
kfree(drv);
|
||||
}
|
||||
|
||||
#define ENABLE_INI (IWL_DBG_TLV_MAX_PRESET + 1)
|
||||
|
||||
/* shared module parameters */
|
||||
struct iwl_mod_params iwlwifi_mod_params = {
|
||||
.fw_restart = true,
|
||||
|
|
@ -2017,43 +2019,10 @@ module_param_named(uapsd_disable, iwlwifi_mod_params.uapsd_disable, uint, 0644);
|
|||
MODULE_PARM_DESC(uapsd_disable,
|
||||
"disable U-APSD functionality bitmap 1: BSS 2: P2P Client (default: 3)");
|
||||
|
||||
#if defined(__linux__)
|
||||
static int enable_ini_set(const char *arg, const struct kernel_param *kp)
|
||||
{
|
||||
int ret = 0;
|
||||
bool res;
|
||||
__u32 new_enable_ini;
|
||||
|
||||
/* in case the argument type is a number */
|
||||
ret = kstrtou32(arg, 0, &new_enable_ini);
|
||||
if (!ret) {
|
||||
if (new_enable_ini > ENABLE_INI) {
|
||||
pr_err("enable_ini cannot be %d, in range 0-16\n", new_enable_ini);
|
||||
return -EINVAL;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* in case the argument type is boolean */
|
||||
ret = kstrtobool(arg, &res);
|
||||
if (ret)
|
||||
return ret;
|
||||
new_enable_ini = (res ? ENABLE_INI : 0);
|
||||
|
||||
out:
|
||||
iwlwifi_mod_params.enable_ini = new_enable_ini;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct kernel_param_ops enable_ini_ops = {
|
||||
.set = enable_ini_set
|
||||
};
|
||||
|
||||
module_param_cb(enable_ini, &enable_ini_ops, &iwlwifi_mod_params.enable_ini, 0644);
|
||||
module_param_named(enable_ini, iwlwifi_mod_params.enable_ini, uint, 0444);
|
||||
MODULE_PARM_DESC(enable_ini,
|
||||
"0:disable, 1-15:FW_DBG_PRESET Values, 16:enabled without preset value defined,"
|
||||
"Debug INI TLV FW debug infrastructure (default: 16)");
|
||||
#endif
|
||||
|
||||
/*
|
||||
* set bt_coex_active to true, uCode will do kill/defer
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#ifndef __iwl_drv_h__
|
||||
#define __iwl_drv_h__
|
||||
#include <linux/export.h>
|
||||
#include <kunit/visibility.h>
|
||||
|
||||
/* for all modules */
|
||||
#define DRV_NAME "iwlwifi"
|
||||
|
|
@ -56,7 +57,7 @@ struct iwl_cfg;
|
|||
/**
|
||||
* iwl_drv_start - start the drv
|
||||
*
|
||||
* @trans_ops: the ops of the transport
|
||||
* @trans: the transport
|
||||
*
|
||||
* starts the driver: fetches the firmware. This should be called by bus
|
||||
* specific system flows implementations. For example, the bus specific probe
|
||||
|
|
@ -89,8 +90,13 @@ void iwl_drv_stop(struct iwl_drv *drv);
|
|||
#define IWL_EXPORT_SYMBOL(sym)
|
||||
#endif
|
||||
|
||||
/* max retry for init flow */
|
||||
#define IWL_MAX_INIT_RETRY 2
|
||||
#if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS)
|
||||
#define EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(sym) EXPORT_SYMBOL_IF_KUNIT(sym)
|
||||
#define VISIBLE_IF_IWLWIFI_KUNIT
|
||||
#else
|
||||
#define EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(sym)
|
||||
#define VISIBLE_IF_IWLWIFI_KUNIT static
|
||||
#endif
|
||||
|
||||
#define FW_NAME_PRE_BUFSIZE 64
|
||||
struct iwl_trans;
|
||||
|
|
|
|||
|
|
@ -1,879 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2020 Intel Corporation
|
||||
* Copyright (C) 2015 Intel Mobile Communications GmbH
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-modparams.h"
|
||||
#include "iwl-eeprom-parse.h"
|
||||
|
||||
#if IS_ENABLED(CONFIG_IWLDVM)
|
||||
/* EEPROM offset definitions */
|
||||
|
||||
/* indirect access definitions */
|
||||
#define ADDRESS_MSK 0x0000FFFF
|
||||
#define INDIRECT_TYPE_MSK 0x000F0000
|
||||
#define INDIRECT_HOST 0x00010000
|
||||
#define INDIRECT_GENERAL 0x00020000
|
||||
#define INDIRECT_REGULATORY 0x00030000
|
||||
#define INDIRECT_CALIBRATION 0x00040000
|
||||
#define INDIRECT_PROCESS_ADJST 0x00050000
|
||||
#define INDIRECT_OTHERS 0x00060000
|
||||
#define INDIRECT_TXP_LIMIT 0x00070000
|
||||
#define INDIRECT_TXP_LIMIT_SIZE 0x00080000
|
||||
#define INDIRECT_ADDRESS 0x00100000
|
||||
|
||||
/* corresponding link offsets in EEPROM */
|
||||
#define EEPROM_LINK_HOST (2*0x64)
|
||||
#define EEPROM_LINK_GENERAL (2*0x65)
|
||||
#define EEPROM_LINK_REGULATORY (2*0x66)
|
||||
#define EEPROM_LINK_CALIBRATION (2*0x67)
|
||||
#define EEPROM_LINK_PROCESS_ADJST (2*0x68)
|
||||
#define EEPROM_LINK_OTHERS (2*0x69)
|
||||
#define EEPROM_LINK_TXP_LIMIT (2*0x6a)
|
||||
#define EEPROM_LINK_TXP_LIMIT_SIZE (2*0x6b)
|
||||
|
||||
/* General */
|
||||
#define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */
|
||||
#define EEPROM_SUBSYSTEM_ID (2*0x0A) /* 2 bytes */
|
||||
#define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */
|
||||
#define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */
|
||||
#define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */
|
||||
#define EEPROM_VERSION (2*0x44) /* 2 bytes */
|
||||
#define EEPROM_SKU_CAP (2*0x45) /* 2 bytes */
|
||||
#define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */
|
||||
#define EEPROM_RADIO_CONFIG (2*0x48) /* 2 bytes */
|
||||
#define EEPROM_NUM_MAC_ADDRESS (2*0x4C) /* 2 bytes */
|
||||
|
||||
/* calibration */
|
||||
struct iwl_eeprom_calib_hdr {
|
||||
u8 version;
|
||||
u8 pa_type;
|
||||
__le16 voltage;
|
||||
} __packed;
|
||||
|
||||
#define EEPROM_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION)
|
||||
#define EEPROM_XTAL ((2*0x128) | EEPROM_CALIB_ALL)
|
||||
|
||||
/* temperature */
|
||||
#define EEPROM_KELVIN_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL)
|
||||
#define EEPROM_RAW_TEMPERATURE ((2*0x12B) | EEPROM_CALIB_ALL)
|
||||
|
||||
/* SKU Capabilities (actual values from EEPROM definition) */
|
||||
enum eeprom_sku_bits {
|
||||
EEPROM_SKU_CAP_BAND_24GHZ = BIT(4),
|
||||
EEPROM_SKU_CAP_BAND_52GHZ = BIT(5),
|
||||
EEPROM_SKU_CAP_11N_ENABLE = BIT(6),
|
||||
EEPROM_SKU_CAP_AMT_ENABLE = BIT(7),
|
||||
EEPROM_SKU_CAP_IPAN_ENABLE = BIT(8)
|
||||
};
|
||||
|
||||
/* radio config bits (actual values from EEPROM definition) */
|
||||
#define EEPROM_RF_CFG_TYPE_MSK(x) (x & 0x3) /* bits 0-1 */
|
||||
#define EEPROM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */
|
||||
#define EEPROM_RF_CFG_DASH_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */
|
||||
#define EEPROM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */
|
||||
#define EEPROM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */
|
||||
#define EEPROM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */
|
||||
|
||||
|
||||
/*
|
||||
* EEPROM bands
|
||||
* These are the channel numbers from each band in the order
|
||||
* that they are stored in the EEPROM band information. Note
|
||||
* that EEPROM bands aren't the same as mac80211 bands, and
|
||||
* there are even special "ht40 bands" in the EEPROM.
|
||||
*/
|
||||
static const u8 iwl_eeprom_band_1[14] = { /* 2.4 GHz */
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
|
||||
};
|
||||
|
||||
static const u8 iwl_eeprom_band_2[] = { /* 4915-5080MHz */
|
||||
183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16
|
||||
};
|
||||
|
||||
static const u8 iwl_eeprom_band_3[] = { /* 5170-5320MHz */
|
||||
34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
|
||||
};
|
||||
|
||||
static const u8 iwl_eeprom_band_4[] = { /* 5500-5700MHz */
|
||||
100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
|
||||
};
|
||||
|
||||
static const u8 iwl_eeprom_band_5[] = { /* 5725-5825MHz */
|
||||
145, 149, 153, 157, 161, 165
|
||||
};
|
||||
|
||||
static const u8 iwl_eeprom_band_6[] = { /* 2.4 ht40 channel */
|
||||
1, 2, 3, 4, 5, 6, 7
|
||||
};
|
||||
|
||||
static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */
|
||||
36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
|
||||
};
|
||||
|
||||
#define IWL_NUM_CHANNELS (ARRAY_SIZE(iwl_eeprom_band_1) + \
|
||||
ARRAY_SIZE(iwl_eeprom_band_2) + \
|
||||
ARRAY_SIZE(iwl_eeprom_band_3) + \
|
||||
ARRAY_SIZE(iwl_eeprom_band_4) + \
|
||||
ARRAY_SIZE(iwl_eeprom_band_5))
|
||||
|
||||
/* rate data (static) */
|
||||
static struct ieee80211_rate iwl_cfg80211_rates[] = {
|
||||
{ .bitrate = 1 * 10, .hw_value = 0, .hw_value_short = 0, },
|
||||
{ .bitrate = 2 * 10, .hw_value = 1, .hw_value_short = 1,
|
||||
.flags = IEEE80211_RATE_SHORT_PREAMBLE, },
|
||||
{ .bitrate = 5.5 * 10, .hw_value = 2, .hw_value_short = 2,
|
||||
.flags = IEEE80211_RATE_SHORT_PREAMBLE, },
|
||||
{ .bitrate = 11 * 10, .hw_value = 3, .hw_value_short = 3,
|
||||
.flags = IEEE80211_RATE_SHORT_PREAMBLE, },
|
||||
{ .bitrate = 6 * 10, .hw_value = 4, .hw_value_short = 4, },
|
||||
{ .bitrate = 9 * 10, .hw_value = 5, .hw_value_short = 5, },
|
||||
{ .bitrate = 12 * 10, .hw_value = 6, .hw_value_short = 6, },
|
||||
{ .bitrate = 18 * 10, .hw_value = 7, .hw_value_short = 7, },
|
||||
{ .bitrate = 24 * 10, .hw_value = 8, .hw_value_short = 8, },
|
||||
{ .bitrate = 36 * 10, .hw_value = 9, .hw_value_short = 9, },
|
||||
{ .bitrate = 48 * 10, .hw_value = 10, .hw_value_short = 10, },
|
||||
{ .bitrate = 54 * 10, .hw_value = 11, .hw_value_short = 11, },
|
||||
};
|
||||
#define RATES_24_OFFS 0
|
||||
#define N_RATES_24 ARRAY_SIZE(iwl_cfg80211_rates)
|
||||
#define RATES_52_OFFS 4
|
||||
#define N_RATES_52 (N_RATES_24 - RATES_52_OFFS)
|
||||
|
||||
/* EEPROM reading functions */
|
||||
|
||||
static u16 iwl_eeprom_query16(const u8 *eeprom, size_t eeprom_size, int offset)
|
||||
{
|
||||
if (WARN_ON(offset + sizeof(u16) > eeprom_size))
|
||||
return 0;
|
||||
return le16_to_cpup((__le16 *)(eeprom + offset));
|
||||
}
|
||||
|
||||
static u32 eeprom_indirect_address(const u8 *eeprom, size_t eeprom_size,
|
||||
u32 address)
|
||||
{
|
||||
u16 offset = 0;
|
||||
|
||||
if ((address & INDIRECT_ADDRESS) == 0)
|
||||
return address;
|
||||
|
||||
switch (address & INDIRECT_TYPE_MSK) {
|
||||
case INDIRECT_HOST:
|
||||
offset = iwl_eeprom_query16(eeprom, eeprom_size,
|
||||
EEPROM_LINK_HOST);
|
||||
break;
|
||||
case INDIRECT_GENERAL:
|
||||
offset = iwl_eeprom_query16(eeprom, eeprom_size,
|
||||
EEPROM_LINK_GENERAL);
|
||||
break;
|
||||
case INDIRECT_REGULATORY:
|
||||
offset = iwl_eeprom_query16(eeprom, eeprom_size,
|
||||
EEPROM_LINK_REGULATORY);
|
||||
break;
|
||||
case INDIRECT_TXP_LIMIT:
|
||||
offset = iwl_eeprom_query16(eeprom, eeprom_size,
|
||||
EEPROM_LINK_TXP_LIMIT);
|
||||
break;
|
||||
case INDIRECT_TXP_LIMIT_SIZE:
|
||||
offset = iwl_eeprom_query16(eeprom, eeprom_size,
|
||||
EEPROM_LINK_TXP_LIMIT_SIZE);
|
||||
break;
|
||||
case INDIRECT_CALIBRATION:
|
||||
offset = iwl_eeprom_query16(eeprom, eeprom_size,
|
||||
EEPROM_LINK_CALIBRATION);
|
||||
break;
|
||||
case INDIRECT_PROCESS_ADJST:
|
||||
offset = iwl_eeprom_query16(eeprom, eeprom_size,
|
||||
EEPROM_LINK_PROCESS_ADJST);
|
||||
break;
|
||||
case INDIRECT_OTHERS:
|
||||
offset = iwl_eeprom_query16(eeprom, eeprom_size,
|
||||
EEPROM_LINK_OTHERS);
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
break;
|
||||
}
|
||||
|
||||
/* translate the offset from words to byte */
|
||||
return (address & ADDRESS_MSK) + (offset << 1);
|
||||
}
|
||||
|
||||
static const u8 *iwl_eeprom_query_addr(const u8 *eeprom, size_t eeprom_size,
|
||||
u32 offset)
|
||||
{
|
||||
u32 address = eeprom_indirect_address(eeprom, eeprom_size, offset);
|
||||
|
||||
if (WARN_ON(address >= eeprom_size))
|
||||
return NULL;
|
||||
|
||||
return &eeprom[address];
|
||||
}
|
||||
|
||||
static int iwl_eeprom_read_calib(const u8 *eeprom, size_t eeprom_size,
|
||||
struct iwl_nvm_data *data)
|
||||
{
|
||||
struct iwl_eeprom_calib_hdr *hdr;
|
||||
|
||||
hdr = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size,
|
||||
EEPROM_CALIB_ALL);
|
||||
if (!hdr)
|
||||
return -ENODATA;
|
||||
data->calib_version = hdr->version;
|
||||
data->calib_voltage = hdr->voltage;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* enum iwl_eeprom_channel_flags - channel flags in EEPROM
|
||||
* @EEPROM_CHANNEL_VALID: channel is usable for this SKU/geo
|
||||
* @EEPROM_CHANNEL_IBSS: usable as an IBSS channel
|
||||
* @EEPROM_CHANNEL_ACTIVE: active scanning allowed
|
||||
* @EEPROM_CHANNEL_RADAR: radar detection required
|
||||
* @EEPROM_CHANNEL_WIDE: 20 MHz channel okay (?)
|
||||
* @EEPROM_CHANNEL_DFS: dynamic freq selection candidate
|
||||
*/
|
||||
enum iwl_eeprom_channel_flags {
|
||||
EEPROM_CHANNEL_VALID = BIT(0),
|
||||
EEPROM_CHANNEL_IBSS = BIT(1),
|
||||
EEPROM_CHANNEL_ACTIVE = BIT(3),
|
||||
EEPROM_CHANNEL_RADAR = BIT(4),
|
||||
EEPROM_CHANNEL_WIDE = BIT(5),
|
||||
EEPROM_CHANNEL_DFS = BIT(7),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_eeprom_channel - EEPROM channel data
|
||||
* @flags: %EEPROM_CHANNEL_* flags
|
||||
* @max_power_avg: max power (in dBm) on this channel, at most 31 dBm
|
||||
*/
|
||||
struct iwl_eeprom_channel {
|
||||
u8 flags;
|
||||
s8 max_power_avg;
|
||||
} __packed;
|
||||
|
||||
|
||||
enum iwl_eeprom_enhanced_txpwr_flags {
|
||||
IWL_EEPROM_ENH_TXP_FL_VALID = BIT(0),
|
||||
IWL_EEPROM_ENH_TXP_FL_BAND_52G = BIT(1),
|
||||
IWL_EEPROM_ENH_TXP_FL_OFDM = BIT(2),
|
||||
IWL_EEPROM_ENH_TXP_FL_40MHZ = BIT(3),
|
||||
IWL_EEPROM_ENH_TXP_FL_HT_AP = BIT(4),
|
||||
IWL_EEPROM_ENH_TXP_FL_RES1 = BIT(5),
|
||||
IWL_EEPROM_ENH_TXP_FL_RES2 = BIT(6),
|
||||
IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE = BIT(7),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_eeprom_enhanced_txpwr
|
||||
* @flags: entry flags
|
||||
* @channel: channel number
|
||||
* @chain_a_max: chain a max power in 1/2 dBm
|
||||
* @chain_b_max: chain b max power in 1/2 dBm
|
||||
* @chain_c_max: chain c max power in 1/2 dBm
|
||||
* @delta_20_in_40: 20-in-40 deltas (hi/lo)
|
||||
* @mimo2_max: mimo2 max power in 1/2 dBm
|
||||
* @mimo3_max: mimo3 max power in 1/2 dBm
|
||||
*
|
||||
* This structure presents the enhanced regulatory tx power limit layout
|
||||
* in an EEPROM image.
|
||||
*/
|
||||
struct iwl_eeprom_enhanced_txpwr {
|
||||
u8 flags;
|
||||
u8 channel;
|
||||
s8 chain_a_max;
|
||||
s8 chain_b_max;
|
||||
s8 chain_c_max;
|
||||
u8 delta_20_in_40;
|
||||
s8 mimo2_max;
|
||||
s8 mimo3_max;
|
||||
} __packed;
|
||||
|
||||
static s8 iwl_get_max_txpwr_half_dbm(const struct iwl_nvm_data *data,
|
||||
struct iwl_eeprom_enhanced_txpwr *txp)
|
||||
{
|
||||
s8 result = 0; /* (.5 dBm) */
|
||||
|
||||
/* Take the highest tx power from any valid chains */
|
||||
if (data->valid_tx_ant & ANT_A && txp->chain_a_max > result)
|
||||
result = txp->chain_a_max;
|
||||
|
||||
if (data->valid_tx_ant & ANT_B && txp->chain_b_max > result)
|
||||
result = txp->chain_b_max;
|
||||
|
||||
if (data->valid_tx_ant & ANT_C && txp->chain_c_max > result)
|
||||
result = txp->chain_c_max;
|
||||
|
||||
if ((data->valid_tx_ant == ANT_AB ||
|
||||
data->valid_tx_ant == ANT_BC ||
|
||||
data->valid_tx_ant == ANT_AC) && txp->mimo2_max > result)
|
||||
result = txp->mimo2_max;
|
||||
|
||||
if (data->valid_tx_ant == ANT_ABC && txp->mimo3_max > result)
|
||||
result = txp->mimo3_max;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define EEPROM_TXP_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT)
|
||||
#define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr)
|
||||
#define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE)
|
||||
|
||||
#define TXP_CHECK_AND_PRINT(x) \
|
||||
((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) ? # x " " : "")
|
||||
|
||||
static void
|
||||
iwl_eeprom_enh_txp_read_element(struct iwl_nvm_data *data,
|
||||
struct iwl_eeprom_enhanced_txpwr *txp,
|
||||
int n_channels, s8 max_txpower_avg)
|
||||
{
|
||||
int ch_idx;
|
||||
enum nl80211_band band;
|
||||
|
||||
band = txp->flags & IWL_EEPROM_ENH_TXP_FL_BAND_52G ?
|
||||
NL80211_BAND_5GHZ : NL80211_BAND_2GHZ;
|
||||
|
||||
for (ch_idx = 0; ch_idx < n_channels; ch_idx++) {
|
||||
struct ieee80211_channel *chan = &data->channels[ch_idx];
|
||||
|
||||
/* update matching channel or from common data only */
|
||||
if (txp->channel != 0 && chan->hw_value != txp->channel)
|
||||
continue;
|
||||
|
||||
/* update matching band only */
|
||||
if (band != chan->band)
|
||||
continue;
|
||||
|
||||
if (chan->max_power < max_txpower_avg &&
|
||||
!(txp->flags & IWL_EEPROM_ENH_TXP_FL_40MHZ))
|
||||
chan->max_power = max_txpower_avg;
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_eeprom_enhanced_txpower(struct device *dev,
|
||||
struct iwl_nvm_data *data,
|
||||
const u8 *eeprom, size_t eeprom_size,
|
||||
int n_channels)
|
||||
{
|
||||
struct iwl_eeprom_enhanced_txpwr *txp_array, *txp;
|
||||
int idx, entries;
|
||||
__le16 *txp_len;
|
||||
s8 max_txp_avg_halfdbm;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8);
|
||||
|
||||
/* the length is in 16-bit words, but we want entries */
|
||||
txp_len = (__le16 *)iwl_eeprom_query_addr(eeprom, eeprom_size,
|
||||
EEPROM_TXP_SZ_OFFS);
|
||||
entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN;
|
||||
|
||||
txp_array = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size,
|
||||
EEPROM_TXP_OFFS);
|
||||
|
||||
for (idx = 0; idx < entries; idx++) {
|
||||
txp = &txp_array[idx];
|
||||
/* skip invalid entries */
|
||||
if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID))
|
||||
continue;
|
||||
|
||||
IWL_DEBUG_EEPROM(dev, "%s %d:\t %s%s%s%s%s%s%s%s (0x%02x)\n",
|
||||
(txp->channel && (txp->flags &
|
||||
IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE)) ?
|
||||
"Common " : (txp->channel) ?
|
||||
"Channel" : "Common",
|
||||
(txp->channel),
|
||||
TXP_CHECK_AND_PRINT(VALID),
|
||||
TXP_CHECK_AND_PRINT(BAND_52G),
|
||||
TXP_CHECK_AND_PRINT(OFDM),
|
||||
TXP_CHECK_AND_PRINT(40MHZ),
|
||||
TXP_CHECK_AND_PRINT(HT_AP),
|
||||
TXP_CHECK_AND_PRINT(RES1),
|
||||
TXP_CHECK_AND_PRINT(RES2),
|
||||
TXP_CHECK_AND_PRINT(COMMON_TYPE),
|
||||
txp->flags);
|
||||
IWL_DEBUG_EEPROM(dev,
|
||||
"\t\t chain_A: %d chain_B: %d chain_C: %d\n",
|
||||
txp->chain_a_max, txp->chain_b_max,
|
||||
txp->chain_c_max);
|
||||
IWL_DEBUG_EEPROM(dev,
|
||||
"\t\t MIMO2: %d MIMO3: %d High 20_on_40: 0x%02x Low 20_on_40: 0x%02x\n",
|
||||
txp->mimo2_max, txp->mimo3_max,
|
||||
((txp->delta_20_in_40 & 0xf0) >> 4),
|
||||
(txp->delta_20_in_40 & 0x0f));
|
||||
|
||||
max_txp_avg_halfdbm = iwl_get_max_txpwr_half_dbm(data, txp);
|
||||
|
||||
iwl_eeprom_enh_txp_read_element(data, txp, n_channels,
|
||||
DIV_ROUND_UP(max_txp_avg_halfdbm, 2));
|
||||
|
||||
if (max_txp_avg_halfdbm > data->max_tx_pwr_half_dbm)
|
||||
data->max_tx_pwr_half_dbm = max_txp_avg_halfdbm;
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_init_band_reference(const struct iwl_cfg *cfg,
|
||||
const u8 *eeprom, size_t eeprom_size,
|
||||
int eeprom_band, int *eeprom_ch_count,
|
||||
const struct iwl_eeprom_channel **ch_info,
|
||||
const u8 **eeprom_ch_array)
|
||||
{
|
||||
u32 offset = cfg->eeprom_params->regulatory_bands[eeprom_band - 1];
|
||||
|
||||
offset |= INDIRECT_ADDRESS | INDIRECT_REGULATORY;
|
||||
|
||||
*ch_info = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size, offset);
|
||||
|
||||
switch (eeprom_band) {
|
||||
case 1: /* 2.4GHz band */
|
||||
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1);
|
||||
*eeprom_ch_array = iwl_eeprom_band_1;
|
||||
break;
|
||||
case 2: /* 4.9GHz band */
|
||||
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2);
|
||||
*eeprom_ch_array = iwl_eeprom_band_2;
|
||||
break;
|
||||
case 3: /* 5.2GHz band */
|
||||
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3);
|
||||
*eeprom_ch_array = iwl_eeprom_band_3;
|
||||
break;
|
||||
case 4: /* 5.5GHz band */
|
||||
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4);
|
||||
*eeprom_ch_array = iwl_eeprom_band_4;
|
||||
break;
|
||||
case 5: /* 5.7GHz band */
|
||||
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5);
|
||||
*eeprom_ch_array = iwl_eeprom_band_5;
|
||||
break;
|
||||
case 6: /* 2.4GHz ht40 channels */
|
||||
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6);
|
||||
*eeprom_ch_array = iwl_eeprom_band_6;
|
||||
break;
|
||||
case 7: /* 5 GHz ht40 channels */
|
||||
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7);
|
||||
*eeprom_ch_array = iwl_eeprom_band_7;
|
||||
break;
|
||||
default:
|
||||
*eeprom_ch_count = 0;
|
||||
*eeprom_ch_array = NULL;
|
||||
WARN_ON(1);
|
||||
}
|
||||
}
|
||||
|
||||
#define CHECK_AND_PRINT(x) \
|
||||
((eeprom_ch->flags & EEPROM_CHANNEL_##x) ? # x " " : "")
|
||||
|
||||
static void iwl_mod_ht40_chan_info(struct device *dev,
|
||||
struct iwl_nvm_data *data, int n_channels,
|
||||
enum nl80211_band band, u16 channel,
|
||||
const struct iwl_eeprom_channel *eeprom_ch,
|
||||
u8 clear_ht40_extension_channel)
|
||||
{
|
||||
struct ieee80211_channel *chan = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_channels; i++) {
|
||||
if (data->channels[i].band != band)
|
||||
continue;
|
||||
if (data->channels[i].hw_value != channel)
|
||||
continue;
|
||||
chan = &data->channels[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
IWL_DEBUG_EEPROM(dev,
|
||||
"HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n",
|
||||
channel,
|
||||
band == NL80211_BAND_5GHZ ? "5.2" : "2.4",
|
||||
CHECK_AND_PRINT(IBSS),
|
||||
CHECK_AND_PRINT(ACTIVE),
|
||||
CHECK_AND_PRINT(RADAR),
|
||||
CHECK_AND_PRINT(WIDE),
|
||||
CHECK_AND_PRINT(DFS),
|
||||
eeprom_ch->flags,
|
||||
eeprom_ch->max_power_avg,
|
||||
((eeprom_ch->flags & EEPROM_CHANNEL_IBSS) &&
|
||||
!(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ? ""
|
||||
: "not ");
|
||||
|
||||
if (eeprom_ch->flags & EEPROM_CHANNEL_VALID)
|
||||
chan->flags &= ~clear_ht40_extension_channel;
|
||||
}
|
||||
|
||||
#define CHECK_AND_PRINT_I(x) \
|
||||
((eeprom_ch_info[ch_idx].flags & EEPROM_CHANNEL_##x) ? # x " " : "")
|
||||
|
||||
static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||
struct iwl_nvm_data *data,
|
||||
const u8 *eeprom, size_t eeprom_size)
|
||||
{
|
||||
int band, ch_idx;
|
||||
const struct iwl_eeprom_channel *eeprom_ch_info;
|
||||
const u8 *eeprom_ch_array;
|
||||
int eeprom_ch_count;
|
||||
int n_channels = 0;
|
||||
|
||||
/*
|
||||
* Loop through the 5 EEPROM bands and add them to the parse list
|
||||
*/
|
||||
for (band = 1; band <= 5; band++) {
|
||||
struct ieee80211_channel *channel;
|
||||
|
||||
iwl_init_band_reference(cfg, eeprom, eeprom_size, band,
|
||||
&eeprom_ch_count, &eeprom_ch_info,
|
||||
&eeprom_ch_array);
|
||||
|
||||
/* Loop through each band adding each of the channels */
|
||||
for (ch_idx = 0; ch_idx < eeprom_ch_count; ch_idx++) {
|
||||
const struct iwl_eeprom_channel *eeprom_ch;
|
||||
|
||||
eeprom_ch = &eeprom_ch_info[ch_idx];
|
||||
|
||||
if (!(eeprom_ch->flags & EEPROM_CHANNEL_VALID)) {
|
||||
IWL_DEBUG_EEPROM(dev,
|
||||
"Ch. %d Flags %x [%sGHz] - No traffic\n",
|
||||
eeprom_ch_array[ch_idx],
|
||||
eeprom_ch_info[ch_idx].flags,
|
||||
(band != 1) ? "5.2" : "2.4");
|
||||
continue;
|
||||
}
|
||||
|
||||
channel = &data->channels[n_channels];
|
||||
n_channels++;
|
||||
|
||||
channel->hw_value = eeprom_ch_array[ch_idx];
|
||||
channel->band = (band == 1) ? NL80211_BAND_2GHZ
|
||||
: NL80211_BAND_5GHZ;
|
||||
channel->center_freq =
|
||||
ieee80211_channel_to_frequency(
|
||||
channel->hw_value, channel->band);
|
||||
|
||||
/* set no-HT40, will enable as appropriate later */
|
||||
channel->flags = IEEE80211_CHAN_NO_HT40;
|
||||
|
||||
if (!(eeprom_ch->flags & EEPROM_CHANNEL_IBSS))
|
||||
channel->flags |= IEEE80211_CHAN_NO_IR;
|
||||
|
||||
if (!(eeprom_ch->flags & EEPROM_CHANNEL_ACTIVE))
|
||||
channel->flags |= IEEE80211_CHAN_NO_IR;
|
||||
|
||||
if (eeprom_ch->flags & EEPROM_CHANNEL_RADAR)
|
||||
channel->flags |= IEEE80211_CHAN_RADAR;
|
||||
|
||||
/* Initialize regulatory-based run-time data */
|
||||
channel->max_power =
|
||||
eeprom_ch_info[ch_idx].max_power_avg;
|
||||
IWL_DEBUG_EEPROM(dev,
|
||||
"Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n",
|
||||
channel->hw_value,
|
||||
(band != 1) ? "5.2" : "2.4",
|
||||
CHECK_AND_PRINT_I(VALID),
|
||||
CHECK_AND_PRINT_I(IBSS),
|
||||
CHECK_AND_PRINT_I(ACTIVE),
|
||||
CHECK_AND_PRINT_I(RADAR),
|
||||
CHECK_AND_PRINT_I(WIDE),
|
||||
CHECK_AND_PRINT_I(DFS),
|
||||
eeprom_ch_info[ch_idx].flags,
|
||||
eeprom_ch_info[ch_idx].max_power_avg,
|
||||
((eeprom_ch_info[ch_idx].flags &
|
||||
EEPROM_CHANNEL_IBSS) &&
|
||||
!(eeprom_ch_info[ch_idx].flags &
|
||||
EEPROM_CHANNEL_RADAR))
|
||||
? "" : "not ");
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg->eeprom_params->enhanced_txpower) {
|
||||
/*
|
||||
* for newer device (6000 series and up)
|
||||
* EEPROM contain enhanced tx power information
|
||||
* driver need to process addition information
|
||||
* to determine the max channel tx power limits
|
||||
*/
|
||||
iwl_eeprom_enhanced_txpower(dev, data, eeprom, eeprom_size,
|
||||
n_channels);
|
||||
} else {
|
||||
/* All others use data from channel map */
|
||||
int i;
|
||||
|
||||
data->max_tx_pwr_half_dbm = -128;
|
||||
|
||||
for (i = 0; i < n_channels; i++)
|
||||
data->max_tx_pwr_half_dbm =
|
||||
max_t(s8, data->max_tx_pwr_half_dbm,
|
||||
data->channels[i].max_power * 2);
|
||||
}
|
||||
|
||||
/* Check if we do have HT40 channels */
|
||||
if (cfg->eeprom_params->regulatory_bands[5] ==
|
||||
EEPROM_REGULATORY_BAND_NO_HT40 &&
|
||||
cfg->eeprom_params->regulatory_bands[6] ==
|
||||
EEPROM_REGULATORY_BAND_NO_HT40)
|
||||
return n_channels;
|
||||
|
||||
/* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */
|
||||
for (band = 6; band <= 7; band++) {
|
||||
enum nl80211_band ieeeband;
|
||||
|
||||
iwl_init_band_reference(cfg, eeprom, eeprom_size, band,
|
||||
&eeprom_ch_count, &eeprom_ch_info,
|
||||
&eeprom_ch_array);
|
||||
|
||||
/* EEPROM band 6 is 2.4, band 7 is 5 GHz */
|
||||
ieeeband = (band == 6) ? NL80211_BAND_2GHZ
|
||||
: NL80211_BAND_5GHZ;
|
||||
|
||||
/* Loop through each band adding each of the channels */
|
||||
for (ch_idx = 0; ch_idx < eeprom_ch_count; ch_idx++) {
|
||||
/* Set up driver's info for lower half */
|
||||
iwl_mod_ht40_chan_info(dev, data, n_channels, ieeeband,
|
||||
eeprom_ch_array[ch_idx],
|
||||
&eeprom_ch_info[ch_idx],
|
||||
IEEE80211_CHAN_NO_HT40PLUS);
|
||||
|
||||
/* Set up driver's info for upper half */
|
||||
iwl_mod_ht40_chan_info(dev, data, n_channels, ieeeband,
|
||||
eeprom_ch_array[ch_idx] + 4,
|
||||
&eeprom_ch_info[ch_idx],
|
||||
IEEE80211_CHAN_NO_HT40MINUS);
|
||||
}
|
||||
}
|
||||
|
||||
return n_channels;
|
||||
}
|
||||
#endif
|
||||
|
||||
int iwl_init_sband_channels(struct iwl_nvm_data *data,
|
||||
struct ieee80211_supported_band *sband,
|
||||
int n_channels, enum nl80211_band band)
|
||||
{
|
||||
struct ieee80211_channel *chan = &data->channels[0];
|
||||
int n = 0, idx = 0;
|
||||
|
||||
while (idx < n_channels && chan->band != band)
|
||||
chan = &data->channels[++idx];
|
||||
|
||||
sband->channels = &data->channels[idx];
|
||||
|
||||
while (idx < n_channels && chan->band == band) {
|
||||
chan = &data->channels[++idx];
|
||||
n++;
|
||||
}
|
||||
|
||||
sband->n_channels = n;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
|
||||
#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
|
||||
|
||||
void iwl_init_ht_hw_capab(struct iwl_trans *trans,
|
||||
struct iwl_nvm_data *data,
|
||||
struct ieee80211_sta_ht_cap *ht_info,
|
||||
enum nl80211_band band,
|
||||
u8 tx_chains, u8 rx_chains)
|
||||
{
|
||||
const struct iwl_cfg *cfg = trans->cfg;
|
||||
int max_bit_rate = 0;
|
||||
|
||||
tx_chains = hweight8(tx_chains);
|
||||
if (cfg->rx_with_siso_diversity)
|
||||
rx_chains = 1;
|
||||
else
|
||||
rx_chains = hweight8(rx_chains);
|
||||
|
||||
if (!(data->sku_cap_11n_enable) ||
|
||||
(iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL) ||
|
||||
!cfg->ht_params) {
|
||||
ht_info->ht_supported = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->sku_cap_mimo_disabled)
|
||||
rx_chains = 1;
|
||||
|
||||
ht_info->ht_supported = true;
|
||||
ht_info->cap = IEEE80211_HT_CAP_DSSSCCK40;
|
||||
|
||||
if (cfg->ht_params->stbc) {
|
||||
ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
|
||||
|
||||
if (tx_chains > 1)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
|
||||
}
|
||||
|
||||
if (cfg->ht_params->ldpc)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
|
||||
|
||||
if (trans->trans_cfg->mq_rx_supported ||
|
||||
iwlwifi_mod_params.amsdu_size >= IWL_AMSDU_8K)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
|
||||
ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
|
||||
ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_4;
|
||||
|
||||
ht_info->mcs.rx_mask[0] = 0xFF;
|
||||
if (rx_chains >= 2)
|
||||
ht_info->mcs.rx_mask[1] = 0xFF;
|
||||
if (rx_chains >= 3)
|
||||
ht_info->mcs.rx_mask[2] = 0xFF;
|
||||
|
||||
if (cfg->ht_params->ht_greenfield_support)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
|
||||
ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
|
||||
|
||||
max_bit_rate = MAX_BIT_RATE_20_MHZ;
|
||||
|
||||
if (cfg->ht_params->ht40_bands & BIT(band)) {
|
||||
ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
||||
ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
|
||||
max_bit_rate = MAX_BIT_RATE_40_MHZ;
|
||||
}
|
||||
|
||||
/* Highest supported Rx data rate */
|
||||
max_bit_rate *= rx_chains;
|
||||
WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK);
|
||||
ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate);
|
||||
|
||||
/* Tx MCS capabilities */
|
||||
ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
|
||||
if (tx_chains != rx_chains) {
|
||||
ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
|
||||
ht_info->mcs.tx_params |= ((tx_chains - 1) <<
|
||||
IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_IWLDVM)
|
||||
static void iwl_init_sbands(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
struct iwl_nvm_data *data,
|
||||
const u8 *eeprom, size_t eeprom_size)
|
||||
{
|
||||
struct device *dev = trans->dev;
|
||||
int n_channels = iwl_init_channel_map(dev, cfg, data,
|
||||
eeprom, eeprom_size);
|
||||
int n_used = 0;
|
||||
struct ieee80211_supported_band *sband;
|
||||
|
||||
sband = &data->bands[NL80211_BAND_2GHZ];
|
||||
sband->band = NL80211_BAND_2GHZ;
|
||||
sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS];
|
||||
sband->n_bitrates = N_RATES_24;
|
||||
n_used += iwl_init_sband_channels(data, sband, n_channels,
|
||||
NL80211_BAND_2GHZ);
|
||||
iwl_init_ht_hw_capab(trans, data, &sband->ht_cap, NL80211_BAND_2GHZ,
|
||||
data->valid_tx_ant, data->valid_rx_ant);
|
||||
|
||||
sband = &data->bands[NL80211_BAND_5GHZ];
|
||||
sband->band = NL80211_BAND_5GHZ;
|
||||
sband->bitrates = &iwl_cfg80211_rates[RATES_52_OFFS];
|
||||
sband->n_bitrates = N_RATES_52;
|
||||
n_used += iwl_init_sband_channels(data, sband, n_channels,
|
||||
NL80211_BAND_5GHZ);
|
||||
iwl_init_ht_hw_capab(trans, data, &sband->ht_cap, NL80211_BAND_5GHZ,
|
||||
data->valid_tx_ant, data->valid_rx_ant);
|
||||
|
||||
if (n_channels != n_used)
|
||||
IWL_ERR_DEV(dev, "EEPROM: used only %d of %d channels\n",
|
||||
n_used, n_channels);
|
||||
}
|
||||
|
||||
/* EEPROM data functions */
|
||||
|
||||
struct iwl_nvm_data *
|
||||
iwl_parse_eeprom_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
const u8 *eeprom, size_t eeprom_size)
|
||||
{
|
||||
struct iwl_nvm_data *data;
|
||||
struct device *dev = trans->dev;
|
||||
const void *tmp;
|
||||
u16 radio_cfg, sku;
|
||||
|
||||
if (WARN_ON(!cfg || !cfg->eeprom_params))
|
||||
return NULL;
|
||||
|
||||
data = kzalloc(struct_size(data, channels, IWL_NUM_CHANNELS),
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
||||
/* get MAC address(es) */
|
||||
tmp = iwl_eeprom_query_addr(eeprom, eeprom_size, EEPROM_MAC_ADDRESS);
|
||||
if (!tmp)
|
||||
goto err_free;
|
||||
memcpy(data->hw_addr, tmp, ETH_ALEN);
|
||||
data->n_hw_addrs = iwl_eeprom_query16(eeprom, eeprom_size,
|
||||
EEPROM_NUM_MAC_ADDRESS);
|
||||
|
||||
if (iwl_eeprom_read_calib(eeprom, eeprom_size, data))
|
||||
goto err_free;
|
||||
|
||||
tmp = iwl_eeprom_query_addr(eeprom, eeprom_size, EEPROM_XTAL);
|
||||
if (!tmp)
|
||||
goto err_free;
|
||||
memcpy(data->xtal_calib, tmp, sizeof(data->xtal_calib));
|
||||
|
||||
tmp = iwl_eeprom_query_addr(eeprom, eeprom_size,
|
||||
EEPROM_RAW_TEMPERATURE);
|
||||
if (!tmp)
|
||||
goto err_free;
|
||||
data->raw_temperature = *(__le16 *)tmp;
|
||||
|
||||
tmp = iwl_eeprom_query_addr(eeprom, eeprom_size,
|
||||
EEPROM_KELVIN_TEMPERATURE);
|
||||
if (!tmp)
|
||||
goto err_free;
|
||||
data->kelvin_temperature = *(__le16 *)tmp;
|
||||
data->kelvin_voltage = *((__le16 *)tmp + 1);
|
||||
|
||||
radio_cfg = iwl_eeprom_query16(eeprom, eeprom_size,
|
||||
EEPROM_RADIO_CONFIG);
|
||||
data->radio_cfg_dash = EEPROM_RF_CFG_DASH_MSK(radio_cfg);
|
||||
data->radio_cfg_pnum = EEPROM_RF_CFG_PNUM_MSK(radio_cfg);
|
||||
data->radio_cfg_step = EEPROM_RF_CFG_STEP_MSK(radio_cfg);
|
||||
data->radio_cfg_type = EEPROM_RF_CFG_TYPE_MSK(radio_cfg);
|
||||
data->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
|
||||
data->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
|
||||
|
||||
sku = iwl_eeprom_query16(eeprom, eeprom_size,
|
||||
EEPROM_SKU_CAP);
|
||||
data->sku_cap_11n_enable = sku & EEPROM_SKU_CAP_11N_ENABLE;
|
||||
data->sku_cap_amt_enable = sku & EEPROM_SKU_CAP_AMT_ENABLE;
|
||||
data->sku_cap_band_24ghz_enable = sku & EEPROM_SKU_CAP_BAND_24GHZ;
|
||||
data->sku_cap_band_52ghz_enable = sku & EEPROM_SKU_CAP_BAND_52GHZ;
|
||||
data->sku_cap_ipan_enable = sku & EEPROM_SKU_CAP_IPAN_ENABLE;
|
||||
if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL)
|
||||
data->sku_cap_11n_enable = false;
|
||||
|
||||
data->nvm_version = iwl_eeprom_query16(eeprom, eeprom_size,
|
||||
EEPROM_VERSION);
|
||||
|
||||
/* check overrides (some devices have wrong EEPROM) */
|
||||
if (cfg->valid_tx_ant)
|
||||
data->valid_tx_ant = cfg->valid_tx_ant;
|
||||
if (cfg->valid_rx_ant)
|
||||
data->valid_rx_ant = cfg->valid_rx_ant;
|
||||
|
||||
if (!data->valid_tx_ant || !data->valid_rx_ant) {
|
||||
IWL_ERR_DEV(dev, "invalid antennas (0x%x, 0x%x)\n",
|
||||
data->valid_tx_ant, data->valid_rx_ant);
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
iwl_init_sbands(trans, cfg, data, eeprom, eeprom_size);
|
||||
|
||||
return data;
|
||||
err_free:
|
||||
kfree(data);
|
||||
return NULL;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_parse_eeprom_data);
|
||||
#endif
|
||||
|
|
@ -1,397 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2019, 2021 Intel Corporation
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
#if defined(__FreeBSD__)
|
||||
#include <linux/delay.h>
|
||||
#endif
|
||||
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-eeprom-read.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "iwl-csr.h"
|
||||
|
||||
/*
|
||||
* EEPROM access time values:
|
||||
*
|
||||
* Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG.
|
||||
* Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1).
|
||||
* When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec.
|
||||
* Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG.
|
||||
*/
|
||||
#define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */
|
||||
|
||||
/*
|
||||
* The device's EEPROM semaphore prevents conflicts between driver and uCode
|
||||
* when accessing the EEPROM; each access is a series of pulses to/from the
|
||||
* EEPROM chip, not a single event, so even reads could conflict if they
|
||||
* weren't arbitrated by the semaphore.
|
||||
*/
|
||||
#define IWL_EEPROM_SEM_TIMEOUT 10 /* microseconds */
|
||||
#define IWL_EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */
|
||||
|
||||
|
||||
static int iwl_eeprom_acquire_semaphore(struct iwl_trans *trans)
|
||||
{
|
||||
u16 count;
|
||||
int ret;
|
||||
|
||||
for (count = 0; count < IWL_EEPROM_SEM_RETRY_LIMIT; count++) {
|
||||
/* Request semaphore */
|
||||
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
|
||||
|
||||
/* See if we got it */
|
||||
ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
|
||||
IWL_EEPROM_SEM_TIMEOUT);
|
||||
if (ret >= 0) {
|
||||
IWL_DEBUG_EEPROM(trans->dev,
|
||||
"Acquired semaphore after %d tries.\n",
|
||||
count+1);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void iwl_eeprom_release_semaphore(struct iwl_trans *trans)
|
||||
{
|
||||
iwl_clear_bit(trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
|
||||
}
|
||||
|
||||
static int iwl_eeprom_verify_signature(struct iwl_trans *trans, bool nvm_is_otp)
|
||||
{
|
||||
u32 gp = iwl_read32(trans, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK;
|
||||
|
||||
IWL_DEBUG_EEPROM(trans->dev, "EEPROM signature=0x%08x\n", gp);
|
||||
|
||||
switch (gp) {
|
||||
case CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP:
|
||||
if (!nvm_is_otp) {
|
||||
IWL_ERR(trans, "EEPROM with bad signature: 0x%08x\n",
|
||||
gp);
|
||||
return -ENOENT;
|
||||
}
|
||||
return 0;
|
||||
case CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K:
|
||||
case CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K:
|
||||
if (nvm_is_otp) {
|
||||
IWL_ERR(trans, "OTP with bad signature: 0x%08x\n", gp);
|
||||
return -ENOENT;
|
||||
}
|
||||
return 0;
|
||||
case CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP:
|
||||
default:
|
||||
IWL_ERR(trans,
|
||||
"bad EEPROM/OTP signature, type=%s, EEPROM_GP=0x%08x\n",
|
||||
nvm_is_otp ? "OTP" : "EEPROM", gp);
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* OTP related functions
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static void iwl_set_otp_access_absolute(struct iwl_trans *trans)
|
||||
{
|
||||
iwl_read32(trans, CSR_OTP_GP_REG);
|
||||
|
||||
iwl_clear_bit(trans, CSR_OTP_GP_REG,
|
||||
CSR_OTP_GP_REG_OTP_ACCESS_MODE);
|
||||
}
|
||||
|
||||
static int iwl_nvm_is_otp(struct iwl_trans *trans)
|
||||
{
|
||||
u32 otpgp;
|
||||
|
||||
/* OTP only valid for CP/PP and after */
|
||||
switch (trans->hw_rev & CSR_HW_REV_TYPE_MSK) {
|
||||
case CSR_HW_REV_TYPE_NONE:
|
||||
IWL_ERR(trans, "Unknown hardware type\n");
|
||||
return -EIO;
|
||||
case CSR_HW_REV_TYPE_5300:
|
||||
case CSR_HW_REV_TYPE_5350:
|
||||
case CSR_HW_REV_TYPE_5100:
|
||||
case CSR_HW_REV_TYPE_5150:
|
||||
return 0;
|
||||
default:
|
||||
otpgp = iwl_read32(trans, CSR_OTP_GP_REG);
|
||||
if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int iwl_init_otp_access(struct iwl_trans *trans)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = iwl_finish_nic_init(trans);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
iwl_set_bits_prph(trans, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_VAL_RESET_REQ);
|
||||
udelay(5);
|
||||
iwl_clear_bits_prph(trans, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_VAL_RESET_REQ);
|
||||
|
||||
/*
|
||||
* CSR auto clock gate disable bit -
|
||||
* this is only applicable for HW with OTP shadow RAM
|
||||
*/
|
||||
if (trans->trans_cfg->base_params->shadow_ram_support)
|
||||
iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
|
||||
CSR_RESET_LINK_PWR_MGMT_DISABLED);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr,
|
||||
__le16 *eeprom_data)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 r;
|
||||
u32 otpgp;
|
||||
|
||||
iwl_write32(trans, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
|
||||
ret = iwl_poll_bit(trans, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_READ_VALID_MSK,
|
||||
CSR_EEPROM_REG_READ_VALID_MSK,
|
||||
IWL_EEPROM_ACCESS_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
IWL_ERR(trans, "Time out reading OTP[%d]\n", addr);
|
||||
return ret;
|
||||
}
|
||||
r = iwl_read32(trans, CSR_EEPROM_REG);
|
||||
/* check for ECC errors: */
|
||||
otpgp = iwl_read32(trans, CSR_OTP_GP_REG);
|
||||
if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) {
|
||||
/* stop in this case */
|
||||
/* set the uncorrectable OTP ECC bit for acknowledgment */
|
||||
iwl_set_bit(trans, CSR_OTP_GP_REG,
|
||||
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
|
||||
IWL_ERR(trans, "Uncorrectable OTP ECC error, abort OTP read\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) {
|
||||
/* continue in this case */
|
||||
/* set the correctable OTP ECC bit for acknowledgment */
|
||||
iwl_set_bit(trans, CSR_OTP_GP_REG,
|
||||
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
|
||||
IWL_ERR(trans, "Correctable OTP ECC error, continue read\n");
|
||||
}
|
||||
*eeprom_data = cpu_to_le16(r >> 16);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* iwl_is_otp_empty: check for empty OTP
|
||||
*/
|
||||
static bool iwl_is_otp_empty(struct iwl_trans *trans)
|
||||
{
|
||||
u16 next_link_addr = 0;
|
||||
__le16 link_value;
|
||||
bool is_empty = false;
|
||||
|
||||
/* locate the beginning of OTP link list */
|
||||
if (!iwl_read_otp_word(trans, next_link_addr, &link_value)) {
|
||||
if (!link_value) {
|
||||
IWL_ERR(trans, "OTP is empty\n");
|
||||
is_empty = true;
|
||||
}
|
||||
} else {
|
||||
IWL_ERR(trans, "Unable to read first block of OTP list.\n");
|
||||
is_empty = true;
|
||||
}
|
||||
|
||||
return is_empty;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* iwl_find_otp_image: find EEPROM image in OTP
|
||||
* finding the OTP block that contains the EEPROM image.
|
||||
* the last valid block on the link list (the block _before_ the last block)
|
||||
* is the block we should read and used to configure the device.
|
||||
* If all the available OTP blocks are full, the last block will be the block
|
||||
* we should read and used to configure the device.
|
||||
* only perform this operation if shadow RAM is disabled
|
||||
*/
|
||||
static int iwl_find_otp_image(struct iwl_trans *trans,
|
||||
u16 *validblockaddr)
|
||||
{
|
||||
u16 next_link_addr = 0, valid_addr;
|
||||
__le16 link_value = 0;
|
||||
int usedblocks = 0;
|
||||
|
||||
/* set addressing mode to absolute to traverse the link list */
|
||||
iwl_set_otp_access_absolute(trans);
|
||||
|
||||
/* checking for empty OTP or error */
|
||||
if (iwl_is_otp_empty(trans))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* start traverse link list
|
||||
* until reach the max number of OTP blocks
|
||||
* different devices have different number of OTP blocks
|
||||
*/
|
||||
do {
|
||||
/* save current valid block address
|
||||
* check for more block on the link list
|
||||
*/
|
||||
valid_addr = next_link_addr;
|
||||
next_link_addr = le16_to_cpu(link_value) * sizeof(u16);
|
||||
IWL_DEBUG_EEPROM(trans->dev, "OTP blocks %d addr 0x%x\n",
|
||||
usedblocks, next_link_addr);
|
||||
if (iwl_read_otp_word(trans, next_link_addr, &link_value))
|
||||
return -EINVAL;
|
||||
if (!link_value) {
|
||||
/*
|
||||
* reach the end of link list, return success and
|
||||
* set address point to the starting address
|
||||
* of the image
|
||||
*/
|
||||
*validblockaddr = valid_addr;
|
||||
/* skip first 2 bytes (link list pointer) */
|
||||
*validblockaddr += 2;
|
||||
return 0;
|
||||
}
|
||||
/* more in the link list, continue */
|
||||
usedblocks++;
|
||||
} while (usedblocks <= trans->trans_cfg->base_params->max_ll_items);
|
||||
|
||||
/* OTP has no valid blocks */
|
||||
IWL_DEBUG_EEPROM(trans->dev, "OTP has no valid blocks\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* iwl_read_eeprom - read EEPROM contents
|
||||
*
|
||||
* Load the EEPROM contents from adapter and return it
|
||||
* and its size.
|
||||
*
|
||||
* NOTE: This routine uses the non-debug IO access functions.
|
||||
*/
|
||||
int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size)
|
||||
{
|
||||
__le16 *e;
|
||||
u32 gp = iwl_read32(trans, CSR_EEPROM_GP);
|
||||
int sz;
|
||||
int ret;
|
||||
u16 addr;
|
||||
u16 validblockaddr = 0;
|
||||
u16 cache_addr = 0;
|
||||
int nvm_is_otp;
|
||||
|
||||
if (!eeprom || !eeprom_size)
|
||||
return -EINVAL;
|
||||
|
||||
nvm_is_otp = iwl_nvm_is_otp(trans);
|
||||
if (nvm_is_otp < 0)
|
||||
return nvm_is_otp;
|
||||
|
||||
sz = trans->trans_cfg->base_params->eeprom_size;
|
||||
IWL_DEBUG_EEPROM(trans->dev, "NVM size = %d\n", sz);
|
||||
|
||||
e = kmalloc(sz, GFP_KERNEL);
|
||||
if (!e)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = iwl_eeprom_verify_signature(trans, nvm_is_otp);
|
||||
if (ret < 0) {
|
||||
IWL_ERR(trans, "EEPROM not found, EEPROM_GP=0x%08x\n", gp);
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
/* Make sure driver (instead of uCode) is allowed to read EEPROM */
|
||||
ret = iwl_eeprom_acquire_semaphore(trans);
|
||||
if (ret < 0) {
|
||||
IWL_ERR(trans, "Failed to acquire EEPROM semaphore.\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
if (nvm_is_otp) {
|
||||
ret = iwl_init_otp_access(trans);
|
||||
if (ret) {
|
||||
IWL_ERR(trans, "Failed to initialize OTP access.\n");
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
iwl_write32(trans, CSR_EEPROM_GP,
|
||||
iwl_read32(trans, CSR_EEPROM_GP) &
|
||||
~CSR_EEPROM_GP_IF_OWNER_MSK);
|
||||
|
||||
iwl_set_bit(trans, CSR_OTP_GP_REG,
|
||||
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
|
||||
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
|
||||
/* traversing the linked list if no shadow ram supported */
|
||||
if (!trans->trans_cfg->base_params->shadow_ram_support) {
|
||||
ret = iwl_find_otp_image(trans, &validblockaddr);
|
||||
if (ret)
|
||||
goto err_unlock;
|
||||
}
|
||||
for (addr = validblockaddr; addr < validblockaddr + sz;
|
||||
addr += sizeof(u16)) {
|
||||
__le16 eeprom_data;
|
||||
|
||||
ret = iwl_read_otp_word(trans, addr, &eeprom_data);
|
||||
if (ret)
|
||||
goto err_unlock;
|
||||
e[cache_addr / 2] = eeprom_data;
|
||||
cache_addr += sizeof(u16);
|
||||
}
|
||||
} else {
|
||||
/* eeprom is an array of 16bit values */
|
||||
for (addr = 0; addr < sz; addr += sizeof(u16)) {
|
||||
u32 r;
|
||||
|
||||
iwl_write32(trans, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
|
||||
|
||||
ret = iwl_poll_bit(trans, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_READ_VALID_MSK,
|
||||
CSR_EEPROM_REG_READ_VALID_MSK,
|
||||
IWL_EEPROM_ACCESS_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
IWL_ERR(trans,
|
||||
"Time out reading EEPROM[%d]\n", addr);
|
||||
goto err_unlock;
|
||||
}
|
||||
r = iwl_read32(trans, CSR_EEPROM_REG);
|
||||
e[addr / 2] = cpu_to_le16(r >> 16);
|
||||
}
|
||||
}
|
||||
|
||||
IWL_DEBUG_EEPROM(trans->dev, "NVM Type: %s\n",
|
||||
nvm_is_otp ? "OTP" : "EEPROM");
|
||||
|
||||
iwl_eeprom_release_semaphore(trans);
|
||||
|
||||
*eeprom_size = sz;
|
||||
*eeprom = (u8 *)e;
|
||||
return 0;
|
||||
|
||||
err_unlock:
|
||||
iwl_eeprom_release_semaphore(trans);
|
||||
err_free:
|
||||
kfree(e);
|
||||
|
||||
return ret;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_read_eeprom);
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2014 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_eeprom_h__
|
||||
#define __iwl_eeprom_h__
|
||||
|
||||
#include "iwl-trans.h"
|
||||
|
||||
int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size);
|
||||
|
||||
#endif /* __iwl_eeprom_h__ */
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2021, 2023 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2021, 2023-2024 Intel Corporation
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
#ifndef __iwl_fh_h__
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
/* Flow Handler Definitions */
|
||||
/****************************/
|
||||
|
||||
/**
|
||||
/*
|
||||
* This I/O area is directly read/writable by driver (e.g. Linux uses writel())
|
||||
* Addresses are offsets from device's PCI hardware base address.
|
||||
*/
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
#define FH_MEM_LOWER_BOUND_GEN2 (0xa06000)
|
||||
#define FH_MEM_UPPER_BOUND_GEN2 (0xa08000)
|
||||
|
||||
/**
|
||||
/*
|
||||
* Keep-Warm (KW) buffer base address.
|
||||
*
|
||||
* Driver must allocate a 4KByte buffer that is for keeping the
|
||||
|
|
@ -44,7 +44,7 @@
|
|||
#define FH_KW_MEM_ADDR_REG (FH_MEM_LOWER_BOUND + 0x97C)
|
||||
|
||||
|
||||
/**
|
||||
/*
|
||||
* TFD Circular Buffers Base (CBBC) addresses
|
||||
*
|
||||
* Device has 16 base pointer registers, one for each of 16 host-DRAM-resident
|
||||
|
|
@ -143,7 +143,7 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans,
|
|||
*/
|
||||
#define TFH_SRV_DMA_CHNL0_BC (0x1F70)
|
||||
|
||||
/**
|
||||
/*
|
||||
* Rx SRAM Control and Status Registers (RSCSR)
|
||||
*
|
||||
* These registers provide handshake between driver and device for the Rx queue
|
||||
|
|
@ -216,21 +216,21 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans,
|
|||
#define FH_MEM_RSCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xC00)
|
||||
#define FH_MEM_RSCSR_CHNL0 (FH_MEM_RSCSR_LOWER_BOUND)
|
||||
|
||||
/**
|
||||
/*
|
||||
* Physical base address of 8-byte Rx Status buffer.
|
||||
* Bit fields:
|
||||
* 31-0: Rx status buffer physical base address [35:4], must 16-byte aligned.
|
||||
*/
|
||||
#define FH_RSCSR_CHNL0_STTS_WPTR_REG (FH_MEM_RSCSR_CHNL0)
|
||||
|
||||
/**
|
||||
/*
|
||||
* Physical base address of Rx Buffer Descriptor Circular Buffer.
|
||||
* Bit fields:
|
||||
* 27-0: RBD CD physical base address [35:8], must be 256-byte aligned.
|
||||
*/
|
||||
#define FH_RSCSR_CHNL0_RBDCB_BASE_REG (FH_MEM_RSCSR_CHNL0 + 0x004)
|
||||
|
||||
/**
|
||||
/*
|
||||
* Rx write pointer (index, really!).
|
||||
* Bit fields:
|
||||
* 11-0: Index of driver's most recent prepared-to-be-filled RBD, + 1.
|
||||
|
|
@ -242,7 +242,7 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans,
|
|||
#define FW_RSCSR_CHNL0_RXDCB_RDPTR_REG (FH_MEM_RSCSR_CHNL0 + 0x00c)
|
||||
#define FH_RSCSR_CHNL0_RDPTR FW_RSCSR_CHNL0_RXDCB_RDPTR_REG
|
||||
|
||||
/**
|
||||
/*
|
||||
* Rx Config/Status Registers (RCSR)
|
||||
* Rx Config Reg for channel 0 (only channel used)
|
||||
*
|
||||
|
|
@ -300,7 +300,7 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans,
|
|||
#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000)
|
||||
#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000)
|
||||
|
||||
/**
|
||||
/*
|
||||
* Rx Shared Status Registers (RSSR)
|
||||
*
|
||||
* After stopping Rx DMA channel (writing 0 to
|
||||
|
|
@ -356,7 +356,7 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans,
|
|||
#define RFH_RBDBUF_RBD0_LSB 0xA08300
|
||||
#define RFH_RBDBUF_RBD_LSB(q) (RFH_RBDBUF_RBD0_LSB + (q) * 8)
|
||||
|
||||
/**
|
||||
/*
|
||||
* RFH Status Register
|
||||
*
|
||||
* Bit fields:
|
||||
|
|
@ -440,7 +440,7 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans,
|
|||
#define FH_TFDIB_CTRL0_REG(_chnl) (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl))
|
||||
#define FH_TFDIB_CTRL1_REG(_chnl) (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl) + 0x4)
|
||||
|
||||
/**
|
||||
/*
|
||||
* Transmit DMA Channel Control/Status Registers (TCSR)
|
||||
*
|
||||
* Device has one configuration register for each of 8 Tx DMA/FIFO channels
|
||||
|
|
@ -501,7 +501,7 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans,
|
|||
#define FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM (20)
|
||||
#define FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX (12)
|
||||
|
||||
/**
|
||||
/*
|
||||
* Tx Shared Status Registers (TSSR)
|
||||
*
|
||||
* After stopping Tx DMA channel (writing 0 to
|
||||
|
|
@ -518,7 +518,7 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans,
|
|||
|
||||
#define FH_TSSR_TX_STATUS_REG (FH_TSSR_LOWER_BOUND + 0x010)
|
||||
|
||||
/**
|
||||
/*
|
||||
* Bit fields for TSSR(Tx Shared Status & Control) error status register:
|
||||
* 31: Indicates an address error when accessed to internal memory
|
||||
* uCode/driver must write "1" in order to clear this flag
|
||||
|
|
@ -565,21 +565,24 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans,
|
|||
#define RX_QUEUE_MASK 255
|
||||
#define RX_QUEUE_SIZE_LOG 8
|
||||
|
||||
#define IWL_DEFAULT_RX_QUEUE 0
|
||||
|
||||
/**
|
||||
* struct iwl_rb_status - reserve buffer status
|
||||
* host memory mapped FH registers
|
||||
* @closed_rb_num [0:11] - Indicates the index of the RB which was closed
|
||||
* @closed_fr_num [0:11] - Indicates the index of the RX Frame which was closed
|
||||
* @finished_rb_num [0:11] - Indicates the index of the current RB
|
||||
* @closed_rb_num: [0:11] Indicates the index of the RB which was closed
|
||||
* @closed_fr_num: [0:11] Indicates the index of the RX Frame which was closed
|
||||
* @finished_rb_num: [0:11] Indicates the index of the current RB
|
||||
* in which the last frame was written to
|
||||
* @finished_fr_num [0:11] - Indicates the index of the RX Frame
|
||||
* @finished_fr_num: [0:11] Indicates the index of the RX Frame
|
||||
* which was transferred
|
||||
* @__spare: reserved
|
||||
*/
|
||||
struct iwl_rb_status {
|
||||
__le16 closed_rb_num;
|
||||
__le16 closed_fr_num;
|
||||
__le16 finished_rb_num;
|
||||
__le16 finished_fr_nam;
|
||||
__le16 finished_fr_num;
|
||||
__le32 __spare;
|
||||
} __packed;
|
||||
|
||||
|
|
@ -631,7 +634,7 @@ enum iwl_tfd_tb_hi_n_len {
|
|||
};
|
||||
|
||||
/**
|
||||
* struct iwl_tfd_tb transmit buffer descriptor within transmit frame descriptor
|
||||
* struct iwl_tfd_tb - transmit buffer descriptor within transmit frame descriptor
|
||||
*
|
||||
* This structure contains dma address and length of transmission address
|
||||
*
|
||||
|
|
@ -645,19 +648,19 @@ struct iwl_tfd_tb {
|
|||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_tfh_tb transmit buffer descriptor within transmit frame descriptor
|
||||
* struct iwl_tfh_tb - transmit buffer descriptor within transmit frame descriptor
|
||||
*
|
||||
* This structure contains dma address and length of transmission address
|
||||
*
|
||||
* @tb_len length of the tx buffer
|
||||
* @addr 64 bits dma address
|
||||
* @tb_len: length of the tx buffer
|
||||
* @addr: 64 bits dma address
|
||||
*/
|
||||
struct iwl_tfh_tb {
|
||||
__le16 tb_len;
|
||||
__le64 addr;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
/*
|
||||
* Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM.
|
||||
* Both driver and device share these circular buffers, each of which must be
|
||||
* contiguous 256 TFDs.
|
||||
|
|
@ -679,12 +682,13 @@ struct iwl_tfh_tb {
|
|||
|
||||
/**
|
||||
* struct iwl_tfd - Transmit Frame Descriptor (TFD)
|
||||
* @ __reserved1[3] reserved
|
||||
* @ num_tbs 0-4 number of active tbs
|
||||
* 5 reserved
|
||||
* 6-7 padding (not used)
|
||||
* @ tbs[20] transmit frame buffer descriptors
|
||||
* @ __pad padding
|
||||
* @__reserved1: reserved
|
||||
* @num_tbs:
|
||||
* 0-4 number of active tbs
|
||||
* 5 reserved
|
||||
* 6-7 padding (not used)
|
||||
* @tbs: transmit frame buffer descriptors
|
||||
* @__pad: padding
|
||||
*/
|
||||
struct iwl_tfd {
|
||||
u8 __reserved1[3];
|
||||
|
|
@ -695,10 +699,11 @@ struct iwl_tfd {
|
|||
|
||||
/**
|
||||
* struct iwl_tfh_tfd - Transmit Frame Descriptor (TFD)
|
||||
* @ num_tbs 0-4 number of active tbs
|
||||
* 5 -15 reserved
|
||||
* @ tbs[25] transmit frame buffer descriptors
|
||||
* @ __pad padding
|
||||
* @num_tbs:
|
||||
* 0-4 number of active tbs
|
||||
* 5-15 reserved
|
||||
* @tbs: transmit frame buffer descriptors
|
||||
* @__pad: padding
|
||||
*/
|
||||
struct iwl_tfh_tfd {
|
||||
__le16 num_tbs;
|
||||
|
|
@ -712,13 +717,15 @@ struct iwl_tfh_tfd {
|
|||
/* Fixed (non-configurable) rx data from phy */
|
||||
|
||||
/**
|
||||
* struct iwlagn_schedq_bc_tbl scheduler byte count table
|
||||
* struct iwlagn_scd_bc_tbl - scheduler byte count table
|
||||
* base physical address provided by SCD_DRAM_BASE_ADDR
|
||||
* For devices up to 22000:
|
||||
* @tfd_offset 0-12 - tx command byte count
|
||||
* @tfd_offset:
|
||||
* For devices up to 22000:
|
||||
* 0-12 - tx command byte count
|
||||
* 12-16 - station index
|
||||
* For 22000:
|
||||
* @tfd_offset 0-12 - tx command byte count
|
||||
* For 22000:
|
||||
* 0-12 - tx command byte count
|
||||
* 12-13 - number of 64 byte chunks
|
||||
* 14-16 - reserved
|
||||
*/
|
||||
|
|
@ -727,7 +734,7 @@ struct iwlagn_scd_bc_tbl {
|
|||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_gen3_bc_tbl_entry scheduler byte count table entry gen3
|
||||
* struct iwl_gen3_bc_tbl_entry - scheduler byte count table entry gen3
|
||||
* For AX210 and on:
|
||||
* @tfd_offset: 0-12 - tx command byte count
|
||||
* 12-13 - number of 64 byte chunks
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2003-2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2003-2014, 2018-2022, 2024 Intel Corporation
|
||||
* Copyright (C) 2015-2016 Intel Deutschland GmbH
|
||||
*/
|
||||
#include <linux/delay.h>
|
||||
|
|
@ -460,7 +460,7 @@ int iwl_finish_nic_init(struct iwl_trans *trans)
|
|||
*/
|
||||
if (cfg_trans->device_family >= IWL_DEVICE_FAMILY_BZ) {
|
||||
iwl_set_bit(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
|
||||
CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ |
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_INIT);
|
||||
poll_ready = CSR_GP_CNTRL_REG_FLAG_MAC_STATUS;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2022, 2024 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_modparams_h__
|
||||
#define __iwl_modparams_h__
|
||||
|
|
@ -113,4 +113,23 @@ static inline bool iwl_enable_tx_ampdu(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Verify amsdu_size module parameter and convert it to a rxb size */
|
||||
static inline enum iwl_amsdu_size
|
||||
iwl_amsdu_size_to_rxb_size(void)
|
||||
{
|
||||
switch (iwlwifi_mod_params.amsdu_size) {
|
||||
case IWL_AMSDU_8K:
|
||||
return IWL_AMSDU_8K;
|
||||
case IWL_AMSDU_12K:
|
||||
return IWL_AMSDU_12K;
|
||||
default:
|
||||
pr_err("%s: Unsupported amsdu_size: %d\n", KBUILD_MODNAME,
|
||||
iwlwifi_mod_params.amsdu_size);
|
||||
fallthrough;
|
||||
case IWL_AMSDU_DEF:
|
||||
case IWL_AMSDU_4K:
|
||||
return IWL_AMSDU_4K;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* #__iwl_modparams_h__ */
|
||||
|
|
|
|||
|
|
@ -38,16 +38,13 @@ enum nvm_offsets {
|
|||
N_HW_ADDRS = 3,
|
||||
NVM_CHANNELS = 0x1E0 - NVM_SW_SECTION,
|
||||
|
||||
/* NVM calibration section offset (in words) definitions */
|
||||
NVM_CALIB_SECTION = 0x2B8,
|
||||
XTAL_CALIB = 0x316 - NVM_CALIB_SECTION,
|
||||
|
||||
/* NVM REGULATORY -Section offset (in words) definitions */
|
||||
NVM_CHANNELS_SDP = 0,
|
||||
};
|
||||
|
||||
enum ext_nvm_offsets {
|
||||
/* NVM HW-Section offset (in words) definitions */
|
||||
|
||||
MAC_ADDRESS_OVERRIDE_EXT_NVM = 1,
|
||||
|
||||
/* NVM SW-Section offset (in words) definitions */
|
||||
|
|
@ -156,6 +153,8 @@ static struct ieee80211_rate iwl_cfg80211_rates[] = {
|
|||
* @NVM_CHANNEL_80MHZ: 80 MHz channel okay
|
||||
* @NVM_CHANNEL_160MHZ: 160 MHz channel okay
|
||||
* @NVM_CHANNEL_DC_HIGH: DC HIGH required/allowed (?)
|
||||
* @NVM_CHANNEL_VLP: client support connection to UHB VLP AP
|
||||
* @NVM_CHANNEL_AFC: client support connection to UHB AFC AP
|
||||
*/
|
||||
enum iwl_nvm_channel_flags {
|
||||
NVM_CHANNEL_VALID = BIT(0),
|
||||
|
|
@ -170,6 +169,8 @@ enum iwl_nvm_channel_flags {
|
|||
NVM_CHANNEL_80MHZ = BIT(10),
|
||||
NVM_CHANNEL_160MHZ = BIT(11),
|
||||
NVM_CHANNEL_DC_HIGH = BIT(12),
|
||||
NVM_CHANNEL_VLP = BIT(13),
|
||||
NVM_CHANNEL_AFC = BIT(14),
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -309,7 +310,7 @@ static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level,
|
|||
|
||||
/* Note: already can print up to 101 characters, 110 is the limit! */
|
||||
IWL_DEBUG_DEV(dev, level,
|
||||
"Ch. %d: 0x%x:%s%s%s%s%s%s%s%s%s%s%s%s\n",
|
||||
"Ch. %d: 0x%x:%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
|
||||
chan, flags,
|
||||
CHECK_AND_PRINT_I(VALID),
|
||||
CHECK_AND_PRINT_I(IBSS),
|
||||
|
|
@ -322,7 +323,9 @@ static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level,
|
|||
CHECK_AND_PRINT_I(40MHZ),
|
||||
CHECK_AND_PRINT_I(80MHZ),
|
||||
CHECK_AND_PRINT_I(160MHZ),
|
||||
CHECK_AND_PRINT_I(DC_HIGH));
|
||||
CHECK_AND_PRINT_I(DC_HIGH),
|
||||
CHECK_AND_PRINT_I(VLP),
|
||||
CHECK_AND_PRINT_I(AFC));
|
||||
#undef CHECK_AND_PRINT_I
|
||||
}
|
||||
|
||||
|
|
@ -366,6 +369,14 @@ static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, enum nl80211_band band,
|
|||
(flags & IEEE80211_CHAN_NO_IR))
|
||||
flags |= IEEE80211_CHAN_IR_CONCURRENT;
|
||||
|
||||
/* Set the AP type for the UHB case. */
|
||||
if (nvm_flags & NVM_CHANNEL_VLP)
|
||||
flags |= IEEE80211_CHAN_ALLOW_6GHZ_VLP_AP;
|
||||
else
|
||||
flags |= IEEE80211_CHAN_NO_6GHZ_VLP_CLIENT;
|
||||
if (!(nvm_flags & NVM_CHANNEL_AFC))
|
||||
flags |= IEEE80211_CHAN_NO_6GHZ_AFC_CLIENT;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
|
@ -380,11 +391,14 @@ static enum nl80211_band iwl_nl80211_band_from_channel_idx(int ch_idx)
|
|||
return NL80211_BAND_2GHZ;
|
||||
}
|
||||
|
||||
static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||
static int iwl_init_channel_map(struct iwl_trans *trans,
|
||||
const struct iwl_fw *fw,
|
||||
struct iwl_nvm_data *data,
|
||||
const void * const nvm_ch_flags,
|
||||
u32 sbands_flags, bool v4)
|
||||
{
|
||||
const struct iwl_cfg *cfg = trans->cfg;
|
||||
struct device *dev = trans->dev;
|
||||
int ch_idx;
|
||||
int n_channels = 0;
|
||||
struct ieee80211_channel *channel;
|
||||
|
|
@ -466,11 +480,10 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
|||
else
|
||||
channel->flags = 0;
|
||||
|
||||
/* TODO: Don't put limitations on UHB devices as we still don't
|
||||
* have NVM for them
|
||||
*/
|
||||
if (cfg->uhb_supported)
|
||||
channel->flags = 0;
|
||||
if (fw_has_capa(&fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_MONITOR_PASSIVE_CHANS))
|
||||
channel->flags |= IEEE80211_CHAN_CAN_MONITOR;
|
||||
|
||||
iwl_nvm_print_channel_flags(dev, IWL_DL_EEPROM,
|
||||
channel->hw_value, ch_flags);
|
||||
IWL_DEBUG_EEPROM(dev, "Ch. %d: %ddBm\n",
|
||||
|
|
@ -585,7 +598,8 @@ static const u8 iwl_vendor_caps[] = {
|
|||
|
||||
static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
|
||||
{
|
||||
.types_mask = BIT(NL80211_IFTYPE_STATION),
|
||||
.types_mask = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_P2P_CLIENT),
|
||||
.he_cap = {
|
||||
.has_he = true,
|
||||
.he_cap_elem = {
|
||||
|
|
@ -668,10 +682,10 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
|
|||
.has_eht = true,
|
||||
.eht_cap_elem = {
|
||||
.mac_cap_info[0] =
|
||||
IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS |
|
||||
IEEE80211_EHT_MAC_CAP0_OM_CONTROL |
|
||||
IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 |
|
||||
IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2,
|
||||
IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2 |
|
||||
IEEE80211_EHT_MAC_CAP0_SCS_TRAFFIC_DESC,
|
||||
.phy_cap_info[0] =
|
||||
IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ |
|
||||
IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI |
|
||||
|
|
@ -695,10 +709,11 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
|
|||
IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP |
|
||||
IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI,
|
||||
.phy_cap_info[5] =
|
||||
FIELD_PREP_CONST(IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK,
|
||||
IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_16US) |
|
||||
IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK |
|
||||
IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP |
|
||||
IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP |
|
||||
IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT,
|
||||
IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP,
|
||||
.phy_cap_info[6] =
|
||||
IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK |
|
||||
IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP,
|
||||
|
|
@ -732,19 +747,22 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
|
|||
/*
|
||||
* PPE thresholds for NSS = 2, and RU index bitmap set
|
||||
* to 0xc.
|
||||
* Note: just for stating what we want, not present in
|
||||
* the transmitted data due to not including
|
||||
* IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT.
|
||||
*/
|
||||
.eht_ppe_thres = {0xc1, 0x0e, 0xe0 }
|
||||
},
|
||||
},
|
||||
{
|
||||
.types_mask = BIT(NL80211_IFTYPE_AP),
|
||||
.types_mask = BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO),
|
||||
.he_cap = {
|
||||
.has_he = true,
|
||||
.he_cap_elem = {
|
||||
.mac_cap_info[0] =
|
||||
IEEE80211_HE_MAC_CAP0_HTC_HE,
|
||||
.mac_cap_info[1] =
|
||||
IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US |
|
||||
IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8,
|
||||
.mac_cap_info[3] =
|
||||
IEEE80211_HE_MAC_CAP3_OMI_CONTROL,
|
||||
|
|
@ -792,7 +810,6 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
|
|||
.has_eht = true,
|
||||
.eht_cap_elem = {
|
||||
.mac_cap_info[0] =
|
||||
IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS |
|
||||
IEEE80211_EHT_MAC_CAP0_OM_CONTROL |
|
||||
IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 |
|
||||
IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2,
|
||||
|
|
@ -800,7 +817,8 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
|
|||
IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ |
|
||||
IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI,
|
||||
.phy_cap_info[5] =
|
||||
IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT,
|
||||
FIELD_PREP_CONST(IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK,
|
||||
IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_16US),
|
||||
},
|
||||
|
||||
/* For all MCS and bandwidth, set 2 NSS for both Tx and
|
||||
|
|
@ -828,6 +846,9 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
|
|||
/*
|
||||
* PPE thresholds for NSS = 2, and RU index bitmap set
|
||||
* to 0xc.
|
||||
* Note: just for stating what we want, not present in
|
||||
* the transmitted data due to not including
|
||||
* IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT.
|
||||
*/
|
||||
.eht_ppe_thres = {0xc1, 0x0e, 0xe0 }
|
||||
},
|
||||
|
|
@ -888,11 +909,13 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
|
|||
u8 tx_chains, u8 rx_chains,
|
||||
const struct iwl_fw *fw)
|
||||
{
|
||||
bool is_ap = iftype_data->types_mask & BIT(NL80211_IFTYPE_AP);
|
||||
bool is_ap = iftype_data->types_mask & (BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO));
|
||||
bool no_320;
|
||||
|
||||
no_320 = !trans->trans_cfg->integrated &&
|
||||
trans->pcie_link_speed < PCI_EXP_LNKSTA_CLS_8_0GB;
|
||||
no_320 = (!trans->trans_cfg->integrated &&
|
||||
trans->pcie_link_speed < PCI_EXP_LNKSTA_CLS_8_0GB) ||
|
||||
trans->reduced_cap_sku;
|
||||
|
||||
if (!data->sku_cap_11be_enable || iwlwifi_mod_params.disable_11be)
|
||||
iftype_data->eht_cap.has_eht = false;
|
||||
|
|
@ -962,6 +985,9 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
|
|||
}
|
||||
}
|
||||
} else {
|
||||
struct ieee80211_he_mcs_nss_supp *he_mcs_nss_supp =
|
||||
&iftype_data->he_cap.he_mcs_nss_supp;
|
||||
|
||||
if (iftype_data->eht_cap.has_eht) {
|
||||
struct ieee80211_eht_mcs_nss_supp *mcs_nss =
|
||||
&iftype_data->eht_cap.eht_mcs_nss_supp;
|
||||
|
|
@ -980,6 +1006,19 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
|
|||
iftype_data->he_cap.he_cap_elem.phy_cap_info[7] |=
|
||||
IEEE80211_HE_PHY_CAP7_MAX_NC_1;
|
||||
}
|
||||
|
||||
he_mcs_nss_supp->rx_mcs_80 |=
|
||||
cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << 2);
|
||||
he_mcs_nss_supp->tx_mcs_80 |=
|
||||
cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << 2);
|
||||
he_mcs_nss_supp->rx_mcs_160 |=
|
||||
cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << 2);
|
||||
he_mcs_nss_supp->tx_mcs_160 |=
|
||||
cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << 2);
|
||||
he_mcs_nss_supp->rx_mcs_80p80 |=
|
||||
cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << 2);
|
||||
he_mcs_nss_supp->tx_mcs_80p80 |=
|
||||
cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << 2);
|
||||
}
|
||||
|
||||
if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210 && !is_ap)
|
||||
|
|
@ -988,8 +1027,8 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
|
|||
|
||||
switch (CSR_HW_RFID_TYPE(trans->hw_rf_id)) {
|
||||
case IWL_CFG_RF_TYPE_GF:
|
||||
case IWL_CFG_RF_TYPE_MR:
|
||||
case IWL_CFG_RF_TYPE_MS:
|
||||
case IWL_CFG_RF_TYPE_FM:
|
||||
case IWL_CFG_RF_TYPE_WH:
|
||||
iftype_data->he_cap.he_cap_elem.phy_cap_info[9] |=
|
||||
IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU;
|
||||
if (!is_ap)
|
||||
|
|
@ -1001,8 +1040,7 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
|
|||
if (CSR_HW_REV_TYPE(trans->hw_rev) == IWL_CFG_MAC_TYPE_GL &&
|
||||
iftype_data->eht_cap.has_eht) {
|
||||
iftype_data->eht_cap.eht_cap_elem.mac_cap_info[0] &=
|
||||
~(IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS |
|
||||
IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 |
|
||||
~(IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 |
|
||||
IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2);
|
||||
iftype_data->eht_cap.eht_cap_elem.phy_cap_info[3] &=
|
||||
~(IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO |
|
||||
|
|
@ -1010,7 +1048,8 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
|
|||
IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK |
|
||||
IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK |
|
||||
IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK |
|
||||
IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK);
|
||||
IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK |
|
||||
IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK);
|
||||
iftype_data->eht_cap.eht_cap_elem.phy_cap_info[4] &=
|
||||
~(IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO |
|
||||
IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP);
|
||||
|
|
@ -1039,6 +1078,26 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
|
|||
iftype_data->he_cap.he_cap_elem.phy_cap_info[7] &=
|
||||
~IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ;
|
||||
}
|
||||
|
||||
if (trans->step_urm) {
|
||||
iftype_data->eht_cap.eht_mcs_nss_supp.bw._320.rx_tx_mcs11_max_nss = 0;
|
||||
iftype_data->eht_cap.eht_mcs_nss_supp.bw._320.rx_tx_mcs13_max_nss = 0;
|
||||
}
|
||||
|
||||
if (trans->no_160)
|
||||
iftype_data->he_cap.he_cap_elem.phy_cap_info[0] &=
|
||||
~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
|
||||
|
||||
if (trans->reduced_cap_sku) {
|
||||
memset(&iftype_data->eht_cap.eht_mcs_nss_supp.bw._320, 0,
|
||||
sizeof(iftype_data->eht_cap.eht_mcs_nss_supp.bw._320));
|
||||
iftype_data->eht_cap.eht_mcs_nss_supp.bw._80.rx_tx_mcs13_max_nss = 0;
|
||||
iftype_data->eht_cap.eht_mcs_nss_supp.bw._160.rx_tx_mcs13_max_nss = 0;
|
||||
iftype_data->eht_cap.eht_cap_elem.phy_cap_info[8] &=
|
||||
~IEEE80211_EHT_PHY_CAP8_RX_4096QAM_WIDER_BW_DL_OFDMA;
|
||||
iftype_data->eht_cap.eht_cap_elem.phy_cap_info[2] &=
|
||||
~IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_init_he_hw_capab(struct iwl_trans *trans,
|
||||
|
|
@ -1050,10 +1109,6 @@ static void iwl_init_he_hw_capab(struct iwl_trans *trans,
|
|||
struct ieee80211_sband_iftype_data *iftype_data;
|
||||
int i;
|
||||
|
||||
/* should only initialize once */
|
||||
if (WARN_ON(sband->iftype_data))
|
||||
return;
|
||||
|
||||
BUILD_BUG_ON(sizeof(data->iftd.low) != sizeof(iwl_he_eht_capa));
|
||||
BUILD_BUG_ON(sizeof(data->iftd.high) != sizeof(iwl_he_eht_capa));
|
||||
BUILD_BUG_ON(sizeof(data->iftd.uhb) != sizeof(iwl_he_eht_capa));
|
||||
|
|
@ -1075,8 +1130,8 @@ static void iwl_init_he_hw_capab(struct iwl_trans *trans,
|
|||
|
||||
memcpy(iftype_data, iwl_he_eht_capa, sizeof(iwl_he_eht_capa));
|
||||
|
||||
sband->iftype_data = iftype_data;
|
||||
sband->n_iftype_data = ARRAY_SIZE(iwl_he_eht_capa);
|
||||
_ieee80211_set_sband_iftype_data(sband, iftype_data,
|
||||
ARRAY_SIZE(iwl_he_eht_capa));
|
||||
|
||||
for (i = 0; i < sband->n_iftype_data; i++)
|
||||
iwl_nvm_fixup_sband_iftd(trans, data, sband, &iftype_data[i],
|
||||
|
|
@ -1085,6 +1140,37 @@ static void iwl_init_he_hw_capab(struct iwl_trans *trans,
|
|||
iwl_init_he_6ghz_capa(trans, data, sband, tx_chains, rx_chains);
|
||||
}
|
||||
|
||||
void iwl_reinit_cab(struct iwl_trans *trans, struct iwl_nvm_data *data,
|
||||
u8 tx_chains, u8 rx_chains, const struct iwl_fw *fw)
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
|
||||
sband = &data->bands[NL80211_BAND_2GHZ];
|
||||
iwl_init_ht_hw_capab(trans, data, &sband->ht_cap, NL80211_BAND_2GHZ,
|
||||
tx_chains, rx_chains);
|
||||
|
||||
if (data->sku_cap_11ax_enable && !iwlwifi_mod_params.disable_11ax)
|
||||
iwl_init_he_hw_capab(trans, data, sband, tx_chains, rx_chains,
|
||||
fw);
|
||||
|
||||
sband = &data->bands[NL80211_BAND_5GHZ];
|
||||
iwl_init_ht_hw_capab(trans, data, &sband->ht_cap, NL80211_BAND_5GHZ,
|
||||
tx_chains, rx_chains);
|
||||
if (data->sku_cap_11ac_enable && !iwlwifi_mod_params.disable_11ac)
|
||||
iwl_init_vht_hw_capab(trans, data, &sband->vht_cap,
|
||||
tx_chains, rx_chains);
|
||||
|
||||
if (data->sku_cap_11ax_enable && !iwlwifi_mod_params.disable_11ax)
|
||||
iwl_init_he_hw_capab(trans, data, sband, tx_chains, rx_chains,
|
||||
fw);
|
||||
|
||||
sband = &data->bands[NL80211_BAND_6GHZ];
|
||||
if (data->sku_cap_11ax_enable && !iwlwifi_mod_params.disable_11ax)
|
||||
iwl_init_he_hw_capab(trans, data, sband, tx_chains, rx_chains,
|
||||
fw);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_reinit_cab);
|
||||
|
||||
static void iwl_init_sbands(struct iwl_trans *trans,
|
||||
struct iwl_nvm_data *data,
|
||||
const void *nvm_ch_flags, u8 tx_chains,
|
||||
|
|
@ -1092,12 +1178,11 @@ static void iwl_init_sbands(struct iwl_trans *trans,
|
|||
const struct iwl_fw *fw)
|
||||
{
|
||||
struct device *dev = trans->dev;
|
||||
const struct iwl_cfg *cfg = trans->cfg;
|
||||
int n_channels;
|
||||
int n_used = 0;
|
||||
struct ieee80211_supported_band *sband;
|
||||
|
||||
n_channels = iwl_init_channel_map(dev, cfg, data, nvm_ch_flags,
|
||||
n_channels = iwl_init_channel_map(trans, fw, data, nvm_ch_flags,
|
||||
sbands_flags, v4);
|
||||
sband = &data->bands[NL80211_BAND_2GHZ];
|
||||
sband->band = NL80211_BAND_2GHZ;
|
||||
|
|
@ -1368,7 +1453,7 @@ iwl_nvm_no_wide_in_5ghz(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
struct iwl_nvm_data *
|
||||
iwl_parse_mei_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
const struct iwl_mei_nvm *mei_nvm,
|
||||
const struct iwl_fw *fw)
|
||||
const struct iwl_fw *fw, u8 tx_ant, u8 rx_ant)
|
||||
{
|
||||
struct iwl_nvm_data *data;
|
||||
u32 sbands_flags = 0;
|
||||
|
|
@ -1395,6 +1480,10 @@ iwl_parse_mei_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
tx_chains &= data->valid_tx_ant;
|
||||
if (data->valid_rx_ant)
|
||||
rx_chains &= data->valid_rx_ant;
|
||||
if (tx_ant)
|
||||
tx_chains &= tx_ant;
|
||||
if (rx_ant)
|
||||
rx_chains &= rx_ant;
|
||||
|
||||
data->sku_cap_mimo_disabled = false;
|
||||
data->sku_cap_band_24ghz_enable = true;
|
||||
|
|
@ -1489,9 +1578,6 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
®ulatory[NVM_CHANNELS_SDP] :
|
||||
&nvm_sw[NVM_CHANNELS];
|
||||
|
||||
/* in family 8000 Xtal calibration values moved to OTP */
|
||||
data->xtal_calib[0] = *(nvm_calib + XTAL_CALIB);
|
||||
data->xtal_calib[1] = *(nvm_calib + XTAL_CALIB + 1);
|
||||
lar_enabled = true;
|
||||
} else {
|
||||
u16 lar_offset = data->nvm_version < 0xE39 ?
|
||||
|
|
@ -1539,11 +1625,15 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
|
|||
flags &= ~NL80211_RRF_NO_HT40PLUS;
|
||||
if (nvm_chan[ch_idx] >= FIRST_2GHZ_HT_MINUS)
|
||||
flags &= ~NL80211_RRF_NO_HT40MINUS;
|
||||
} else if (nvm_flags & NVM_CHANNEL_40MHZ) {
|
||||
} else if (ch_idx < NUM_2GHZ_CHANNELS + NUM_5GHZ_CHANNELS &&
|
||||
nvm_flags & NVM_CHANNEL_40MHZ) {
|
||||
if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0)
|
||||
flags &= ~NL80211_RRF_NO_HT40PLUS;
|
||||
else
|
||||
flags &= ~NL80211_RRF_NO_HT40MINUS;
|
||||
} else if (nvm_flags & NVM_CHANNEL_40MHZ) {
|
||||
flags &= ~NL80211_RRF_NO_HT40PLUS;
|
||||
flags &= ~NL80211_RRF_NO_HT40MINUS;
|
||||
}
|
||||
|
||||
if (!(nvm_flags & NVM_CHANNEL_80MHZ))
|
||||
|
|
@ -1563,9 +1653,26 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
|
|||
/* Set the GO concurrent flag only in case that NO_IR is set.
|
||||
* Otherwise it is meaningless
|
||||
*/
|
||||
if ((nvm_flags & NVM_CHANNEL_GO_CONCURRENT) &&
|
||||
(flags & NL80211_RRF_NO_IR))
|
||||
flags |= NL80211_RRF_GO_CONCURRENT;
|
||||
if ((nvm_flags & NVM_CHANNEL_GO_CONCURRENT)) {
|
||||
if (flags & NL80211_RRF_NO_IR)
|
||||
flags |= NL80211_RRF_GO_CONCURRENT;
|
||||
if (flags & NL80211_RRF_DFS) {
|
||||
flags |= NL80211_RRF_DFS_CONCURRENT;
|
||||
/* Our device doesn't set active bit for DFS channels
|
||||
* however, once marked as DFS no-ir is not needed.
|
||||
*/
|
||||
flags &= ~NL80211_RRF_NO_IR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the AP type for the UHB case. */
|
||||
if (nvm_flags & NVM_CHANNEL_VLP)
|
||||
flags |= NL80211_RRF_ALLOW_6GHZ_VLP_AP;
|
||||
else
|
||||
flags |= NL80211_RRF_NO_6GHZ_VLP_CLIENT;
|
||||
|
||||
if (!(nvm_flags & NVM_CHANNEL_AFC))
|
||||
flags |= NL80211_RRF_NO_6GHZ_AFC_CLIENT;
|
||||
|
||||
/*
|
||||
* reg_capa is per regulatory domain so apply it for every channel
|
||||
|
|
@ -1629,7 +1736,6 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
|
|||
const u16 *nvm_chan;
|
||||
struct ieee80211_regdomain *regd, *copy_rd;
|
||||
struct ieee80211_reg_rule *rule;
|
||||
enum nl80211_band band;
|
||||
int center_freq, prev_center_freq = 0;
|
||||
int valid_rules = 0;
|
||||
bool new_rule;
|
||||
|
|
@ -1673,8 +1779,10 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
|
|||
reg_capa = iwl_get_reg_capa(cap, resp_ver);
|
||||
|
||||
for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) {
|
||||
enum nl80211_band band =
|
||||
iwl_nl80211_band_from_channel_idx(ch_idx);
|
||||
|
||||
ch_flags = (u16)__le32_to_cpup(channels + ch_idx);
|
||||
band = iwl_nl80211_band_from_channel_idx(ch_idx);
|
||||
center_freq = ieee80211_channel_to_frequency(nvm_chan[ch_idx],
|
||||
band);
|
||||
new_rule = false;
|
||||
|
|
@ -1960,7 +2068,8 @@ out:
|
|||
IWL_EXPORT_SYMBOL(iwl_read_external_nvm);
|
||||
|
||||
struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
|
||||
const struct iwl_fw *fw)
|
||||
const struct iwl_fw *fw,
|
||||
u8 set_tx_ant, u8 set_rx_ant)
|
||||
{
|
||||
struct iwl_nvm_get_info cmd = {};
|
||||
struct iwl_nvm_data *nvm;
|
||||
|
|
@ -1974,6 +2083,9 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
|
|||
bool empty_otp;
|
||||
u32 mac_flags;
|
||||
u32 sbands_flags = 0;
|
||||
u8 tx_ant;
|
||||
u8 rx_ant;
|
||||
|
||||
/*
|
||||
* All the values in iwl_nvm_get_info_rsp v4 are the same as
|
||||
* in v3, except for the channel profile part of the
|
||||
|
|
@ -2047,7 +2159,7 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
|
|||
!!(mac_flags & NVM_MAC_SKU_FLAGS_BAND_5_2_ENABLED);
|
||||
nvm->sku_cap_mimo_disabled =
|
||||
!!(mac_flags & NVM_MAC_SKU_FLAGS_MIMO_DISABLED);
|
||||
if (CSR_HW_RFID_TYPE(trans->hw_rf_id) == IWL_CFG_RF_TYPE_FM)
|
||||
if (CSR_HW_RFID_TYPE(trans->hw_rf_id) >= IWL_CFG_RF_TYPE_FM)
|
||||
nvm->sku_cap_11be_enable = true;
|
||||
|
||||
/* Initialize PHY sku data */
|
||||
|
|
@ -2065,10 +2177,15 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
|
|||
channel_profile = v4 ? (void *)rsp->regulatory.channel_profile :
|
||||
(void *)rsp_v3->regulatory.channel_profile;
|
||||
|
||||
iwl_init_sbands(trans, nvm,
|
||||
channel_profile,
|
||||
nvm->valid_tx_ant & fw->valid_tx_ant,
|
||||
nvm->valid_rx_ant & fw->valid_rx_ant,
|
||||
tx_ant = nvm->valid_tx_ant & fw->valid_tx_ant;
|
||||
rx_ant = nvm->valid_rx_ant & fw->valid_rx_ant;
|
||||
|
||||
if (set_tx_ant)
|
||||
tx_ant &= set_tx_ant;
|
||||
if (set_rx_ant)
|
||||
rx_ant &= set_rx_ant;
|
||||
|
||||
iwl_init_sbands(trans, nvm, channel_profile, tx_ant, rx_ant,
|
||||
sbands_flags, v4, fw);
|
||||
|
||||
iwl_free_resp(&hcmd);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2015, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2005-2015, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
#ifndef __iwl_nvm_parse_h__
|
||||
#define __iwl_nvm_parse_h__
|
||||
|
||||
#include <net/cfg80211.h>
|
||||
#include "iwl-eeprom-parse.h"
|
||||
#include "iwl-nvm-utils.h"
|
||||
#include "mei/iwl-mei.h"
|
||||
|
||||
/**
|
||||
|
|
@ -21,7 +21,7 @@ enum iwl_nvm_sbands_flags {
|
|||
IWL_NVM_SBANDS_FLAGS_NO_WIDE_IN_5GHZ = BIT(1),
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* iwl_parse_nvm_data - parse NVM data and return values
|
||||
*
|
||||
* This function parses all NVM values we need and then
|
||||
|
|
@ -38,7 +38,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
u8 tx_chains, u8 rx_chains);
|
||||
|
||||
/**
|
||||
* iwl_parse_mcc_info - parse MCC (mobile country code) info coming from FW
|
||||
* iwl_parse_nvm_mcc_info - parse MCC (mobile country code) info coming from FW
|
||||
*
|
||||
* This function parses the regulatory channel data received as a
|
||||
* MCC_UPDATE_CMD command. It returns a newly allocation regulatory domain,
|
||||
|
|
@ -73,21 +73,28 @@ int iwl_read_external_nvm(struct iwl_trans *trans,
|
|||
void iwl_nvm_fixups(u32 hw_id, unsigned int section, u8 *data,
|
||||
unsigned int len);
|
||||
|
||||
/**
|
||||
/*
|
||||
* iwl_get_nvm - retrieve NVM data from firmware
|
||||
*
|
||||
* Allocates a new iwl_nvm_data structure, fills it with
|
||||
* NVM data, and returns it to caller.
|
||||
*/
|
||||
struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
|
||||
const struct iwl_fw *fw);
|
||||
const struct iwl_fw *fw,
|
||||
u8 set_tx_ant, u8 set_rx_ant);
|
||||
|
||||
/**
|
||||
/*
|
||||
* iwl_parse_mei_nvm_data - parse the mei_nvm_data and get an iwl_nvm_data
|
||||
*/
|
||||
struct iwl_nvm_data *
|
||||
iwl_parse_mei_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
const struct iwl_mei_nvm *mei_nvm,
|
||||
const struct iwl_fw *fw);
|
||||
const struct iwl_fw *fw, u8 set_tx_ant, u8 set_rx_ant);
|
||||
|
||||
/*
|
||||
* iwl_reinit_cab - to be called when the tx_chains or rx_chains are modified
|
||||
*/
|
||||
void iwl_reinit_cab(struct iwl_trans *trans, struct iwl_nvm_data *data,
|
||||
u8 tx_chains, u8 rx_chains, const struct iwl_fw *fw);
|
||||
|
||||
#endif /* __iwl_nvm_parse_h__ */
|
||||
|
|
|
|||
118
sys/contrib/dev/iwlwifi/iwl-nvm-utils.c
Normal file
118
sys/contrib/dev/iwlwifi/iwl-nvm-utils.c
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2021, 2023 Intel Corporation
|
||||
* Copyright (C) 2015 Intel Mobile Communications GmbH
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-modparams.h"
|
||||
#include "iwl-nvm-utils.h"
|
||||
|
||||
int iwl_init_sband_channels(struct iwl_nvm_data *data,
|
||||
struct ieee80211_supported_band *sband,
|
||||
int n_channels, enum nl80211_band band)
|
||||
{
|
||||
struct ieee80211_channel *chan = &data->channels[0];
|
||||
int n = 0, idx = 0;
|
||||
|
||||
while (idx < n_channels && chan->band != band)
|
||||
chan = &data->channels[++idx];
|
||||
|
||||
sband->channels = &data->channels[idx];
|
||||
|
||||
while (idx < n_channels && chan->band == band) {
|
||||
chan = &data->channels[++idx];
|
||||
n++;
|
||||
}
|
||||
|
||||
sband->n_channels = n;
|
||||
|
||||
return n;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_init_sband_channels);
|
||||
|
||||
#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
|
||||
#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
|
||||
|
||||
void iwl_init_ht_hw_capab(struct iwl_trans *trans,
|
||||
struct iwl_nvm_data *data,
|
||||
struct ieee80211_sta_ht_cap *ht_info,
|
||||
enum nl80211_band band,
|
||||
u8 tx_chains, u8 rx_chains)
|
||||
{
|
||||
const struct iwl_cfg *cfg = trans->cfg;
|
||||
int max_bit_rate = 0;
|
||||
|
||||
tx_chains = hweight8(tx_chains);
|
||||
if (cfg->rx_with_siso_diversity)
|
||||
rx_chains = 1;
|
||||
else
|
||||
rx_chains = hweight8(rx_chains);
|
||||
|
||||
if (!(data->sku_cap_11n_enable) ||
|
||||
(iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL) ||
|
||||
!cfg->ht_params) {
|
||||
ht_info->ht_supported = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->sku_cap_mimo_disabled)
|
||||
rx_chains = 1;
|
||||
|
||||
ht_info->ht_supported = true;
|
||||
ht_info->cap = IEEE80211_HT_CAP_DSSSCCK40;
|
||||
|
||||
if (cfg->ht_params->stbc) {
|
||||
ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
|
||||
|
||||
if (tx_chains > 1)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
|
||||
}
|
||||
|
||||
if (cfg->ht_params->ldpc)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
|
||||
|
||||
if (trans->trans_cfg->mq_rx_supported ||
|
||||
iwlwifi_mod_params.amsdu_size >= IWL_AMSDU_8K)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
|
||||
ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
|
||||
ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_4;
|
||||
|
||||
ht_info->mcs.rx_mask[0] = 0xFF;
|
||||
ht_info->mcs.rx_mask[1] = 0x00;
|
||||
ht_info->mcs.rx_mask[2] = 0x00;
|
||||
|
||||
if (rx_chains >= 2)
|
||||
ht_info->mcs.rx_mask[1] = 0xFF;
|
||||
if (rx_chains >= 3)
|
||||
ht_info->mcs.rx_mask[2] = 0xFF;
|
||||
|
||||
if (cfg->ht_params->ht_greenfield_support)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
|
||||
ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
|
||||
|
||||
max_bit_rate = MAX_BIT_RATE_20_MHZ;
|
||||
|
||||
if (cfg->ht_params->ht40_bands & BIT(band)) {
|
||||
ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
||||
ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
|
||||
max_bit_rate = MAX_BIT_RATE_40_MHZ;
|
||||
}
|
||||
|
||||
/* Highest supported Rx data rate */
|
||||
max_bit_rate *= rx_chains;
|
||||
WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK);
|
||||
ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate);
|
||||
|
||||
/* Tx MCS capabilities */
|
||||
ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
|
||||
if (tx_chains != rx_chains) {
|
||||
ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
|
||||
ht_info->mcs.tx_params |= ((tx_chains - 1) <<
|
||||
IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
|
||||
}
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_init_ht_hw_capab);
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018, 2020-2022 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018, 2020-2023 Intel Corporation
|
||||
* Copyright (C) 2015 Intel Mobile Communications GmbH
|
||||
*/
|
||||
#ifndef __iwl_eeprom_parse_h__
|
||||
|
|
@ -58,23 +58,6 @@ struct iwl_nvm_data {
|
|||
struct ieee80211_channel channels[];
|
||||
};
|
||||
|
||||
/**
|
||||
* iwl_parse_eeprom_data - parse EEPROM data and return values
|
||||
*
|
||||
* @dev: device pointer we're parsing for, for debug only
|
||||
* @cfg: device configuration for parsing and overrides
|
||||
* @eeprom: the EEPROM data
|
||||
* @eeprom_size: length of the EEPROM data
|
||||
*
|
||||
* This function parses all EEPROM values we need and then
|
||||
* returns a (newly allocated) struct containing all the
|
||||
* relevant values for driver use. The struct must be freed
|
||||
* later with iwl_free_nvm_data().
|
||||
*/
|
||||
struct iwl_nvm_data *
|
||||
iwl_parse_eeprom_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
const u8 *eeprom, size_t eeprom_size);
|
||||
|
||||
int iwl_init_sband_channels(struct iwl_nvm_data *data,
|
||||
struct ieee80211_supported_band *sband,
|
||||
int n_channels, enum nl80211_band band);
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2021 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2021, 2024 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -64,15 +64,15 @@ struct iwl_cfg;
|
|||
* received on the RSS queue(s). The queue parameter indicates which of the
|
||||
* RSS queues received this frame; it will always be non-zero.
|
||||
* This method must not sleep.
|
||||
* @async_cb: called when an ASYNC command with CMD_WANT_ASYNC_CALLBACK set
|
||||
* completes. Must be atomic.
|
||||
* @queue_full: notifies that a HW queue is full.
|
||||
* Must be atomic and called with BH disabled.
|
||||
* @queue_not_full: notifies that a HW queue is not full any more.
|
||||
* Must be atomic and called with BH disabled.
|
||||
* @hw_rf_kill:notifies of a change in the HW rf kill switch. True means that
|
||||
* @hw_rf_kill: notifies of a change in the HW rf kill switch. True means that
|
||||
* the radio is killed. Return %true if the device should be stopped by
|
||||
* the transport immediately after the call. May sleep.
|
||||
* Note that this must not return %true for newer devices using gen2 PCIe
|
||||
* transport.
|
||||
* @free_skb: allows the transport layer to free skbs that haven't been
|
||||
* reclaimed by the op_mode. This can happen when the driver is freed and
|
||||
* there are Tx packets pending in the transport layer.
|
||||
|
|
@ -85,6 +85,10 @@ struct iwl_cfg;
|
|||
* May sleep
|
||||
* @wimax_active: invoked when WiMax becomes active. May sleep
|
||||
* @time_point: called when transport layer wants to collect debug data
|
||||
* @device_powered_off: called upon resume from hibernation but not only.
|
||||
* Op_mode needs to reset its internal state because the device did not
|
||||
* survive the system state transition. The firmware is no longer running,
|
||||
* etc...
|
||||
*/
|
||||
struct iwl_op_mode_ops {
|
||||
struct iwl_op_mode *(*start)(struct iwl_trans *trans,
|
||||
|
|
@ -96,8 +100,6 @@ struct iwl_op_mode_ops {
|
|||
struct iwl_rx_cmd_buffer *rxb);
|
||||
void (*rx_rss)(struct iwl_op_mode *op_mode, struct napi_struct *napi,
|
||||
struct iwl_rx_cmd_buffer *rxb, unsigned int queue);
|
||||
void (*async_cb)(struct iwl_op_mode *op_mode,
|
||||
const struct iwl_device_cmd *cmd);
|
||||
void (*queue_full)(struct iwl_op_mode *op_mode, int queue);
|
||||
void (*queue_not_full)(struct iwl_op_mode *op_mode, int queue);
|
||||
bool (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state);
|
||||
|
|
@ -109,6 +111,7 @@ struct iwl_op_mode_ops {
|
|||
void (*time_point)(struct iwl_op_mode *op_mode,
|
||||
enum iwl_fw_ini_time_point tp_id,
|
||||
union iwl_dbg_tlv_tp_data *tp_data);
|
||||
void (*device_powered_off)(struct iwl_op_mode *op_mode);
|
||||
};
|
||||
|
||||
int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops);
|
||||
|
|
@ -147,13 +150,6 @@ static inline void iwl_op_mode_rx_rss(struct iwl_op_mode *op_mode,
|
|||
op_mode->ops->rx_rss(op_mode, napi, rxb, queue);
|
||||
}
|
||||
|
||||
static inline void iwl_op_mode_async_cb(struct iwl_op_mode *op_mode,
|
||||
const struct iwl_device_cmd *cmd)
|
||||
{
|
||||
if (op_mode->ops->async_cb)
|
||||
op_mode->ops->async_cb(op_mode, cmd);
|
||||
}
|
||||
|
||||
static inline void iwl_op_mode_queue_full(struct iwl_op_mode *op_mode,
|
||||
int queue)
|
||||
{
|
||||
|
|
@ -194,7 +190,8 @@ static inline void iwl_op_mode_cmd_queue_full(struct iwl_op_mode *op_mode)
|
|||
static inline void iwl_op_mode_nic_config(struct iwl_op_mode *op_mode)
|
||||
{
|
||||
might_sleep();
|
||||
op_mode->ops->nic_config(op_mode);
|
||||
if (op_mode->ops->nic_config)
|
||||
op_mode->ops->nic_config(op_mode);
|
||||
}
|
||||
|
||||
static inline void iwl_op_mode_wimax_active(struct iwl_op_mode *op_mode)
|
||||
|
|
@ -212,4 +209,11 @@ static inline void iwl_op_mode_time_point(struct iwl_op_mode *op_mode,
|
|||
op_mode->ops->time_point(op_mode, tp_id, tp_data);
|
||||
}
|
||||
|
||||
static inline void iwl_op_mode_device_powered_off(struct iwl_op_mode *op_mode)
|
||||
{
|
||||
if (!op_mode || !op_mode->ops || !op_mode->ops->device_powered_off)
|
||||
return;
|
||||
op_mode->ops->device_powered_off(op_mode);
|
||||
}
|
||||
|
||||
#endif /* __iwl_op_mode_h__ */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -96,7 +96,7 @@
|
|||
#define DTSC_PTAT_AVG (0x00a10650)
|
||||
|
||||
|
||||
/**
|
||||
/*
|
||||
* Tx Scheduler
|
||||
*
|
||||
* The Tx Scheduler selects the next frame to be transmitted, choosing TFDs
|
||||
|
|
@ -169,7 +169,7 @@
|
|||
*/
|
||||
#define SCD_MEM_LOWER_BOUND (0x0000)
|
||||
|
||||
/**
|
||||
/*
|
||||
* Max Tx window size is the max number of contiguous TFDs that the scheduler
|
||||
* can keep track of at one time when creating block-ack chains of frames.
|
||||
* Note that "64" matches the number of ack bits in a block-ack packet.
|
||||
|
|
@ -348,8 +348,8 @@
|
|||
#define RFIC_REG_RD 0xAD0470
|
||||
#define WFPM_CTRL_REG 0xA03030
|
||||
#define WFPM_OTP_CFG1_ADDR 0x00a03098
|
||||
#define WFPM_OTP_CFG1_IS_JACKET_BIT BIT(4)
|
||||
#define WFPM_OTP_CFG1_IS_CDB_BIT BIT(5)
|
||||
#define WFPM_OTP_CFG1_IS_JACKET_BIT BIT(5)
|
||||
#define WFPM_OTP_CFG1_IS_CDB_BIT BIT(4)
|
||||
#define WFPM_OTP_BZ_BNJ_JACKET_BIT 5
|
||||
#define WFPM_OTP_BZ_BNJ_CDB_BIT 4
|
||||
#define WFPM_OTP_CFG1_IS_JACKET(_val) (((_val) & 0x00000020) >> WFPM_OTP_BZ_BNJ_JACKET_BIT)
|
||||
|
|
@ -365,16 +365,25 @@
|
|||
#define DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK 0x00000FFF
|
||||
|
||||
enum {
|
||||
ENABLE_WFPM = BIT(31),
|
||||
WFPM_AUX_CTL_AUX_IF_MAC_OWNER_MSK = 0x80000000,
|
||||
};
|
||||
|
||||
#define CNVI_AUX_MISC_CHIP 0xA200B0
|
||||
#define CNVI_AUX_MISC_CHIP 0xA200B0
|
||||
#define CNVI_AUX_MISC_CHIP_MAC_STEP(_val) (((_val) & 0xf000000) >> 24)
|
||||
#define CNVI_AUX_MISC_CHIP_PROD_TYPE(_val) ((_val) & 0xfff)
|
||||
#define CNVI_AUX_MISC_CHIP_PROD_TYPE_GL 0x910
|
||||
#define CNVI_AUX_MISC_CHIP_PROD_TYPE_BZ_U 0x930
|
||||
#define CNVI_AUX_MISC_CHIP_PROD_TYPE_BZ_I 0x900
|
||||
#define CNVI_AUX_MISC_CHIP_PROD_TYPE_BZ_W 0x901
|
||||
|
||||
#define CNVR_AUX_MISC_CHIP 0xA2B800
|
||||
#define CNVR_SCU_SD_REGS_SD_REG_DIG_DCDC_VTRIM 0xA29890
|
||||
#define CNVR_SCU_SD_REGS_SD_REG_ACTIVE_VDIG_MIRROR 0xA29938
|
||||
#define CNVI_SCU_SEQ_DATA_DW9 0xA27488
|
||||
|
||||
#define CNVI_PMU_STEP_FLOW 0xA2D588
|
||||
#define CNVI_PMU_STEP_FLOW_FORCE_URM BIT(2)
|
||||
|
||||
#define PREG_AUX_BUS_WPROT_0 0xA04CC0
|
||||
|
||||
/* device family 9000 WPROT register */
|
||||
|
|
@ -383,7 +392,7 @@ enum {
|
|||
#define PREG_PRPH_WPROT_22000 0xA04D00
|
||||
|
||||
#define SB_MODIFY_CFG_FLAG 0xA03088
|
||||
#define SB_CFG_RESIDES_IN_OTP_MASK 0x10
|
||||
#define SB_CFG_RESIDES_IN_ROM 0x80
|
||||
#define SB_CPU_1_STATUS 0xA01E30
|
||||
#define SB_CPU_2_STATUS 0xA01E34
|
||||
#define UMAG_SB_CPU_1_STATUS 0xA038C0
|
||||
|
|
@ -424,14 +433,14 @@ enum {
|
|||
* reserved: bits 12-18
|
||||
* slave_exist: bit 19
|
||||
* dash: bits 20-23
|
||||
* step: bits 24-26
|
||||
* flavor: bits 27-31
|
||||
* step: bits 24-27
|
||||
* flavor: bits 28-31
|
||||
*/
|
||||
#define REG_CRF_ID_TYPE(val) (((val) & 0x00000FFF) >> 0)
|
||||
#define REG_CRF_ID_SLAVE(val) (((val) & 0x00080000) >> 19)
|
||||
#define REG_CRF_ID_DASH(val) (((val) & 0x00F00000) >> 20)
|
||||
#define REG_CRF_ID_STEP(val) (((val) & 0x07000000) >> 24)
|
||||
#define REG_CRF_ID_FLAVOR(val) (((val) & 0xF8000000) >> 27)
|
||||
#define REG_CRF_ID_STEP(val) (((val) & 0x0F000000) >> 24)
|
||||
#define REG_CRF_ID_FLAVOR(val) (((val) & 0xF0000000) >> 28)
|
||||
|
||||
#define UREG_CHICK (0xA05C00)
|
||||
#define UREG_CHICK_MSI_ENABLE BIT(24)
|
||||
|
|
@ -447,11 +456,8 @@ enum {
|
|||
#define REG_CRF_ID_TYPE_HR_NONE_CDB_1X1 0x501
|
||||
#define REG_CRF_ID_TYPE_HR_NONE_CDB_CCP 0x532
|
||||
#define REG_CRF_ID_TYPE_GF 0x410
|
||||
#define REG_CRF_ID_TYPE_GF_TC 0xF08
|
||||
#define REG_CRF_ID_TYPE_MR 0x810
|
||||
#define REG_CRF_ID_TYPE_FM 0x910
|
||||
#define REG_CRF_ID_TYPE_FMI 0x930
|
||||
#define REG_CRF_ID_TYPE_FMR 0x900
|
||||
#define REG_CRF_ID_TYPE_WHP 0xA10
|
||||
|
||||
#define HPM_DEBUG 0xA03440
|
||||
#define PERSISTENCE_BIT BIT(12)
|
||||
|
|
@ -516,4 +522,8 @@ enum {
|
|||
#define WFPM_LMAC2_PD_NOTIFICATION 0xA033CC
|
||||
#define WFPM_LMAC2_PD_RE_READ BIT(31)
|
||||
|
||||
#define DPHYIP_INDIRECT 0xA2D800
|
||||
#define DPHYIP_INDIRECT_RD_MSK 0xFF000000
|
||||
#define DPHYIP_INDIRECT_RD_SHIFT 24
|
||||
|
||||
#endif /* __iwl_prph_h__ */
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2019-2021, 2023 Intel Corporation
|
||||
* Copyright (C) 2019-2021, 2023-2024 Intel Corporation
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/bsearch.h>
|
||||
|
|
@ -11,13 +11,13 @@
|
|||
#include "iwl-trans.h"
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-fh.h"
|
||||
#include "queue/tx.h"
|
||||
#include <linux/dmapool.h>
|
||||
#include "fw/api/commands.h"
|
||||
#include "pcie/internal.h"
|
||||
#include "iwl-context-info-gen3.h"
|
||||
|
||||
struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
|
||||
struct device *dev,
|
||||
const struct iwl_trans_ops *ops,
|
||||
const struct iwl_cfg_trans_params *cfg_trans)
|
||||
{
|
||||
struct iwl_trans *trans;
|
||||
|
|
@ -37,22 +37,8 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
|
|||
#endif
|
||||
|
||||
trans->dev = dev;
|
||||
trans->ops = ops;
|
||||
trans->num_rx_queues = 1;
|
||||
|
||||
WARN_ON(!ops->wait_txq_empty && !ops->wait_tx_queues_empty);
|
||||
|
||||
if (trans->trans_cfg->gen2) {
|
||||
trans->txqs.tfd.addr_size = 64;
|
||||
trans->txqs.tfd.max_tbs = IWL_TFH_NUM_TBS;
|
||||
trans->txqs.tfd.size = sizeof(struct iwl_tfh_tfd);
|
||||
} else {
|
||||
trans->txqs.tfd.addr_size = 36;
|
||||
trans->txqs.tfd.max_tbs = IWL_NUM_OF_TBS;
|
||||
trans->txqs.tfd.size = sizeof(struct iwl_tfd);
|
||||
}
|
||||
trans->max_skb_frags = IWL_TRANS_MAX_FRAGS(trans);
|
||||
|
||||
return trans;
|
||||
}
|
||||
|
||||
|
|
@ -78,31 +64,6 @@ int iwl_trans_init(struct iwl_trans *trans)
|
|||
if (WARN_ON(trans->trans_cfg->gen2 && txcmd_size >= txcmd_align))
|
||||
return -EINVAL;
|
||||
|
||||
if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
|
||||
trans->txqs.bc_tbl_size =
|
||||
sizeof(struct iwl_gen3_bc_tbl_entry) * TFD_QUEUE_BC_SIZE_GEN3_BZ;
|
||||
else if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
|
||||
trans->txqs.bc_tbl_size =
|
||||
sizeof(struct iwl_gen3_bc_tbl_entry) * TFD_QUEUE_BC_SIZE_GEN3_AX210;
|
||||
else
|
||||
trans->txqs.bc_tbl_size = sizeof(struct iwlagn_scd_bc_tbl);
|
||||
/*
|
||||
* For gen2 devices, we use a single allocation for each byte-count
|
||||
* table, but they're pretty small (1k) so use a DMA pool that we
|
||||
* allocate here.
|
||||
*/
|
||||
if (trans->trans_cfg->gen2) {
|
||||
trans->txqs.bc_pool = dmam_pool_create("iwlwifi:bc", trans->dev,
|
||||
trans->txqs.bc_tbl_size,
|
||||
256, 0);
|
||||
if (!trans->txqs.bc_pool)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Some things must not change even if the config does */
|
||||
WARN_ON(trans->txqs.tfd.addr_size !=
|
||||
(trans->trans_cfg->gen2 ? 64 : 36));
|
||||
|
||||
snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name),
|
||||
"iwl_cmd_pool:%s", dev_name(trans->dev));
|
||||
trans->dev_cmd_pool =
|
||||
|
|
@ -112,14 +73,6 @@ int iwl_trans_init(struct iwl_trans *trans)
|
|||
if (!trans->dev_cmd_pool)
|
||||
return -ENOMEM;
|
||||
|
||||
#ifdef CONFIG_INET
|
||||
trans->txqs.tso_hdr_page = alloc_percpu(struct iwl_tso_hdr_page);
|
||||
if (!trans->txqs.tso_hdr_page) {
|
||||
kmem_cache_destroy(trans->dev_cmd_pool);
|
||||
return -ENOMEM;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize the wait queue for commands */
|
||||
init_waitqueue_head(&trans->wait_command_queue);
|
||||
|
||||
|
|
@ -128,22 +81,6 @@ int iwl_trans_init(struct iwl_trans *trans)
|
|||
|
||||
void iwl_trans_free(struct iwl_trans *trans)
|
||||
{
|
||||
#ifdef CONFIG_INET
|
||||
int i;
|
||||
|
||||
if (trans->txqs.tso_hdr_page) {
|
||||
for_each_possible_cpu(i) {
|
||||
struct iwl_tso_hdr_page *p =
|
||||
per_cpu_ptr(trans->txqs.tso_hdr_page, i);
|
||||
|
||||
if (p && p->page)
|
||||
__free_page(p->page);
|
||||
}
|
||||
|
||||
free_percpu(trans->txqs.tso_hdr_page);
|
||||
}
|
||||
#endif
|
||||
|
||||
kmem_cache_destroy(trans->dev_cmd_pool);
|
||||
}
|
||||
|
||||
|
|
@ -171,14 +108,9 @@ int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
|||
if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status)))
|
||||
return -EIO;
|
||||
|
||||
if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) {
|
||||
IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
|
||||
if (WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
|
||||
"bad state = %d\n", trans->state))
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (WARN_ON((cmd->flags & CMD_WANT_ASYNC_CALLBACK) &&
|
||||
!(cmd->flags & CMD_ASYNC)))
|
||||
return -EINVAL;
|
||||
|
||||
if (!(cmd->flags & CMD_ASYNC))
|
||||
lock_map_acquire_read(&trans->sync_cmd_lockdep_map);
|
||||
|
|
@ -188,7 +120,7 @@ int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
|||
cmd->id = DEF_ID(cmd->id);
|
||||
}
|
||||
|
||||
ret = iwl_trans_txq_send_hcmd(trans, cmd);
|
||||
ret = iwl_trans_pcie_send_hcmd(trans, cmd);
|
||||
|
||||
if (!(cmd->flags & CMD_ASYNC))
|
||||
lock_map_release(&trans->sync_cmd_lockdep_map);
|
||||
|
|
@ -255,3 +187,379 @@ int iwl_cmd_groups_verify_sorted(const struct iwl_trans_config *trans)
|
|||
return 0;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_cmd_groups_verify_sorted);
|
||||
|
||||
void iwl_trans_configure(struct iwl_trans *trans,
|
||||
const struct iwl_trans_config *trans_cfg)
|
||||
{
|
||||
trans->op_mode = trans_cfg->op_mode;
|
||||
|
||||
iwl_trans_pcie_configure(trans, trans_cfg);
|
||||
WARN_ON(iwl_cmd_groups_verify_sorted(trans_cfg));
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_configure);
|
||||
|
||||
int iwl_trans_start_hw(struct iwl_trans *trans)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
return iwl_trans_pcie_start_hw(trans);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_start_hw);
|
||||
|
||||
void iwl_trans_op_mode_leave(struct iwl_trans *trans)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
iwl_trans_pcie_op_mode_leave(trans);
|
||||
|
||||
trans->op_mode = NULL;
|
||||
|
||||
trans->state = IWL_TRANS_NO_FW;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_op_mode_leave);
|
||||
|
||||
void iwl_trans_write8(struct iwl_trans *trans, u32 ofs, u8 val)
|
||||
{
|
||||
iwl_trans_pcie_write8(trans, ofs, val);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_write8);
|
||||
|
||||
void iwl_trans_write32(struct iwl_trans *trans, u32 ofs, u32 val)
|
||||
{
|
||||
iwl_trans_pcie_write32(trans, ofs, val);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_write32);
|
||||
|
||||
u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
return iwl_trans_pcie_read32(trans, ofs);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_read32);
|
||||
|
||||
u32 iwl_trans_read_prph(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
return iwl_trans_pcie_read_prph(trans, ofs);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_read_prph);
|
||||
|
||||
void iwl_trans_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
|
||||
{
|
||||
return iwl_trans_pcie_write_prph(trans, ofs, val);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_write_prph);
|
||||
|
||||
int iwl_trans_read_mem(struct iwl_trans *trans, u32 addr,
|
||||
void *buf, int dwords)
|
||||
{
|
||||
return iwl_trans_pcie_read_mem(trans, addr, buf, dwords);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_read_mem);
|
||||
|
||||
int iwl_trans_write_mem(struct iwl_trans *trans, u32 addr,
|
||||
const void *buf, int dwords)
|
||||
{
|
||||
return iwl_trans_pcie_write_mem(trans, addr, buf, dwords);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_write_mem);
|
||||
|
||||
void iwl_trans_set_pmi(struct iwl_trans *trans, bool state)
|
||||
{
|
||||
if (state)
|
||||
set_bit(STATUS_TPOWER_PMI, &trans->status);
|
||||
else
|
||||
clear_bit(STATUS_TPOWER_PMI, &trans->status);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_set_pmi);
|
||||
|
||||
int iwl_trans_sw_reset(struct iwl_trans *trans, bool retake_ownership)
|
||||
{
|
||||
return iwl_trans_pcie_sw_reset(trans, retake_ownership);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_sw_reset);
|
||||
|
||||
struct iwl_trans_dump_data *
|
||||
iwl_trans_dump_data(struct iwl_trans *trans, u32 dump_mask,
|
||||
const struct iwl_dump_sanitize_ops *sanitize_ops,
|
||||
void *sanitize_ctx)
|
||||
{
|
||||
return iwl_trans_pcie_dump_data(trans, dump_mask,
|
||||
sanitize_ops, sanitize_ctx);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_dump_data);
|
||||
|
||||
int iwl_trans_d3_suspend(struct iwl_trans *trans, bool test, bool reset)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
return iwl_trans_pcie_d3_suspend(trans, test, reset);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_d3_suspend);
|
||||
|
||||
int iwl_trans_d3_resume(struct iwl_trans *trans, enum iwl_d3_status *status,
|
||||
bool test, bool reset)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
return iwl_trans_pcie_d3_resume(trans, status, test, reset);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_d3_resume);
|
||||
|
||||
void iwl_trans_interrupts(struct iwl_trans *trans, bool enable)
|
||||
{
|
||||
iwl_trans_pci_interrupts(trans, enable);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_interrupts);
|
||||
|
||||
void iwl_trans_sync_nmi(struct iwl_trans *trans)
|
||||
{
|
||||
iwl_trans_pcie_sync_nmi(trans);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_sync_nmi);
|
||||
|
||||
int iwl_trans_write_imr_mem(struct iwl_trans *trans, u32 dst_addr,
|
||||
u64 src_addr, u32 byte_cnt)
|
||||
{
|
||||
return iwl_trans_pcie_copy_imr(trans, dst_addr, src_addr, byte_cnt);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_write_imr_mem);
|
||||
|
||||
void iwl_trans_set_bits_mask(struct iwl_trans *trans, u32 reg,
|
||||
u32 mask, u32 value)
|
||||
{
|
||||
iwl_trans_pcie_set_bits_mask(trans, reg, mask, value);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_set_bits_mask);
|
||||
|
||||
int iwl_trans_read_config32(struct iwl_trans *trans, u32 ofs,
|
||||
u32 *val)
|
||||
{
|
||||
return iwl_trans_pcie_read_config32(trans, ofs, val);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_read_config32);
|
||||
|
||||
bool _iwl_trans_grab_nic_access(struct iwl_trans *trans)
|
||||
{
|
||||
return iwl_trans_pcie_grab_nic_access(trans);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(_iwl_trans_grab_nic_access);
|
||||
|
||||
void __releases(nic_access)
|
||||
iwl_trans_release_nic_access(struct iwl_trans *trans)
|
||||
{
|
||||
iwl_trans_pcie_release_nic_access(trans);
|
||||
__release(nic_access);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_release_nic_access);
|
||||
|
||||
void iwl_trans_fw_alive(struct iwl_trans *trans, u32 scd_addr)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
trans->state = IWL_TRANS_FW_ALIVE;
|
||||
|
||||
if (trans->trans_cfg->gen2)
|
||||
iwl_trans_pcie_gen2_fw_alive(trans);
|
||||
else
|
||||
iwl_trans_pcie_fw_alive(trans, scd_addr);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_fw_alive);
|
||||
|
||||
int iwl_trans_start_fw(struct iwl_trans *trans, const struct fw_img *fw,
|
||||
bool run_in_rfkill)
|
||||
{
|
||||
int ret;
|
||||
|
||||
might_sleep();
|
||||
|
||||
WARN_ON_ONCE(!trans->rx_mpdu_cmd);
|
||||
|
||||
clear_bit(STATUS_FW_ERROR, &trans->status);
|
||||
|
||||
if (trans->trans_cfg->gen2)
|
||||
ret = iwl_trans_pcie_gen2_start_fw(trans, fw, run_in_rfkill);
|
||||
else
|
||||
ret = iwl_trans_pcie_start_fw(trans, fw, run_in_rfkill);
|
||||
|
||||
if (ret == 0)
|
||||
trans->state = IWL_TRANS_FW_STARTED;
|
||||
|
||||
return ret;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_start_fw);
|
||||
|
||||
void iwl_trans_stop_device(struct iwl_trans *trans)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
if (trans->trans_cfg->gen2)
|
||||
iwl_trans_pcie_gen2_stop_device(trans);
|
||||
else
|
||||
iwl_trans_pcie_stop_device(trans);
|
||||
|
||||
trans->state = IWL_TRANS_NO_FW;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_stop_device);
|
||||
|
||||
int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
struct iwl_device_tx_cmd *dev_cmd, int queue)
|
||||
{
|
||||
if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status)))
|
||||
return -EIO;
|
||||
|
||||
if (WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
|
||||
"bad state = %d\n", trans->state))
|
||||
return -EIO;
|
||||
|
||||
if (trans->trans_cfg->gen2)
|
||||
return iwl_txq_gen2_tx(trans, skb, dev_cmd, queue);
|
||||
|
||||
return iwl_trans_pcie_tx(trans, skb, dev_cmd, queue);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_tx);
|
||||
|
||||
void iwl_trans_reclaim(struct iwl_trans *trans, int queue, int ssn,
|
||||
struct sk_buff_head *skbs, bool is_flush)
|
||||
{
|
||||
if (WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
|
||||
"bad state = %d\n", trans->state))
|
||||
return;
|
||||
|
||||
iwl_pcie_reclaim(trans, queue, ssn, skbs, is_flush);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_reclaim);
|
||||
|
||||
void iwl_trans_txq_disable(struct iwl_trans *trans, int queue,
|
||||
bool configure_scd)
|
||||
{
|
||||
iwl_trans_pcie_txq_disable(trans, queue, configure_scd);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_txq_disable);
|
||||
|
||||
bool iwl_trans_txq_enable_cfg(struct iwl_trans *trans, int queue, u16 ssn,
|
||||
const struct iwl_trans_txq_scd_cfg *cfg,
|
||||
unsigned int queue_wdg_timeout)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
if (WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
|
||||
"bad state = %d\n", trans->state))
|
||||
return false;
|
||||
|
||||
return iwl_trans_pcie_txq_enable(trans, queue, ssn,
|
||||
cfg, queue_wdg_timeout);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_txq_enable_cfg);
|
||||
|
||||
int iwl_trans_wait_txq_empty(struct iwl_trans *trans, int queue)
|
||||
{
|
||||
if (WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
|
||||
"bad state = %d\n", trans->state))
|
||||
return -EIO;
|
||||
|
||||
return iwl_trans_pcie_wait_txq_empty(trans, queue);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_wait_txq_empty);
|
||||
|
||||
int iwl_trans_wait_tx_queues_empty(struct iwl_trans *trans, u32 txqs)
|
||||
{
|
||||
if (WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
|
||||
"bad state = %d\n", trans->state))
|
||||
return -EIO;
|
||||
|
||||
return iwl_trans_pcie_wait_txqs_empty(trans, txqs);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_wait_tx_queues_empty);
|
||||
|
||||
void iwl_trans_freeze_txq_timer(struct iwl_trans *trans,
|
||||
unsigned long txqs, bool freeze)
|
||||
{
|
||||
if (WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
|
||||
"bad state = %d\n", trans->state))
|
||||
return;
|
||||
|
||||
iwl_pcie_freeze_txq_timer(trans, txqs, freeze);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_freeze_txq_timer);
|
||||
|
||||
void iwl_trans_txq_set_shared_mode(struct iwl_trans *trans,
|
||||
int txq_id, bool shared_mode)
|
||||
{
|
||||
iwl_trans_pcie_txq_set_shared_mode(trans, txq_id, shared_mode);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_txq_set_shared_mode);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
void iwl_trans_debugfs_cleanup(struct iwl_trans *trans)
|
||||
{
|
||||
iwl_trans_pcie_debugfs_cleanup(trans);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_debugfs_cleanup);
|
||||
#endif
|
||||
|
||||
void iwl_trans_set_q_ptrs(struct iwl_trans *trans, int queue, int ptr)
|
||||
{
|
||||
if (WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
|
||||
"bad state = %d\n", trans->state))
|
||||
return;
|
||||
|
||||
iwl_pcie_set_q_ptrs(trans, queue, ptr);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_set_q_ptrs);
|
||||
|
||||
int iwl_trans_txq_alloc(struct iwl_trans *trans, u32 flags, u32 sta_mask,
|
||||
u8 tid, int size, unsigned int wdg_timeout)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
if (WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
|
||||
"bad state = %d\n", trans->state))
|
||||
return -EIO;
|
||||
|
||||
return iwl_txq_dyn_alloc(trans, flags, sta_mask, tid,
|
||||
size, wdg_timeout);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_txq_alloc);
|
||||
|
||||
void iwl_trans_txq_free(struct iwl_trans *trans, int queue)
|
||||
{
|
||||
iwl_txq_dyn_free(trans, queue);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_txq_free);
|
||||
|
||||
int iwl_trans_get_rxq_dma_data(struct iwl_trans *trans, int queue,
|
||||
struct iwl_trans_rxq_dma_data *data)
|
||||
{
|
||||
return iwl_trans_pcie_rxq_dma_data(trans, queue, data);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_get_rxq_dma_data);
|
||||
|
||||
int iwl_trans_load_pnvm(struct iwl_trans *trans,
|
||||
const struct iwl_pnvm_image *pnvm_data,
|
||||
const struct iwl_ucode_capabilities *capa)
|
||||
{
|
||||
return iwl_trans_pcie_ctx_info_gen3_load_pnvm(trans, pnvm_data, capa);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_load_pnvm);
|
||||
|
||||
void iwl_trans_set_pnvm(struct iwl_trans *trans,
|
||||
const struct iwl_ucode_capabilities *capa)
|
||||
{
|
||||
iwl_trans_pcie_ctx_info_gen3_set_pnvm(trans, capa);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_set_pnvm);
|
||||
|
||||
int iwl_trans_load_reduce_power(struct iwl_trans *trans,
|
||||
const struct iwl_pnvm_image *payloads,
|
||||
const struct iwl_ucode_capabilities *capa)
|
||||
{
|
||||
return iwl_trans_pcie_ctx_info_gen3_load_reduce_power(trans, payloads,
|
||||
capa);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_load_reduce_power);
|
||||
|
||||
void iwl_trans_set_reduce_power(struct iwl_trans *trans,
|
||||
const struct iwl_ucode_capabilities *capa)
|
||||
{
|
||||
iwl_trans_pcie_ctx_info_gen3_set_reduce_power(trans, capa);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_set_reduce_power);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,5 @@
|
|||
/*-
|
||||
* Copyright (c) 2022 The FreeBSD Foundation
|
||||
* Copyright (c) 2022-2024 The FreeBSD Foundation
|
||||
*
|
||||
* This software was developed by Björn Zeeb under sponsorship from
|
||||
* the FreeBSD Foundation.
|
||||
|
|
@ -154,6 +154,11 @@ iwl_mei_pldr_req(void)
|
|||
{
|
||||
return (false);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
iwl_mei_set_power_limit(__le16 *x __unused)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _IWL_MEI_IWL_MEI_H */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2013-2014, 2018-2020, 2022 Intel Corporation
|
||||
* Copyright (C) 2013-2014, 2018-2020, 2022-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
*/
|
||||
#include <linux/ieee80211.h>
|
||||
|
|
@ -116,11 +116,6 @@ iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif)
|
|||
|
||||
ret = BT_COEX_TX_DIS_LUT;
|
||||
|
||||
if (mvm->cfg->bt_shared_single_ant) {
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
phy_ctx_id = *((u16 *)chanctx_conf->drv_priv);
|
||||
primary_ch_phy_id = le32_to_cpu(mvm->last_bt_ci_cmd.primary_ch_phy_id);
|
||||
secondary_ch_phy_id =
|
||||
|
|
@ -186,6 +181,9 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
|
|||
struct iwl_mvm_sta *mvmsta;
|
||||
u32 value;
|
||||
|
||||
if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
|
||||
return 0;
|
||||
|
||||
mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
|
||||
if (!mvmsta)
|
||||
return 0;
|
||||
|
|
@ -221,15 +219,13 @@ struct iwl_bt_iterator_data {
|
|||
|
||||
static inline
|
||||
void iwl_mvm_bt_coex_enable_rssi_event(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mvm_vif_link_info *link_info,
|
||||
bool enable, int rssi)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
mvmvif->bf_data.last_bt_coex_event = rssi;
|
||||
mvmvif->bf_data.bt_coex_max_thold =
|
||||
link_info->bf_data.last_bt_coex_event = rssi;
|
||||
link_info->bf_data.bt_coex_max_thold =
|
||||
enable ? -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH : 0;
|
||||
mvmvif->bf_data.bt_coex_min_thold =
|
||||
link_info->bf_data.bt_coex_min_thold =
|
||||
enable ? -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH : 0;
|
||||
}
|
||||
|
||||
|
|
@ -257,6 +253,77 @@ static void iwl_mvm_bt_coex_tcm_based_ci(struct iwl_mvm *mvm,
|
|||
swap(data->primary, data->secondary);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function receives the LB link id and checks if eSR should be
|
||||
* enabled or disabled (due to BT coex)
|
||||
*/
|
||||
bool
|
||||
iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
s32 link_rssi,
|
||||
bool primary)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
bool have_wifi_loss_rate =
|
||||
iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
|
||||
BT_PROFILE_NOTIFICATION, 0) > 4;
|
||||
u8 wifi_loss_rate;
|
||||
|
||||
if (mvm->last_bt_notif.wifi_loss_low_rssi == BT_OFF)
|
||||
return true;
|
||||
|
||||
if (primary)
|
||||
return false;
|
||||
|
||||
/* The feature is not supported */
|
||||
if (!have_wifi_loss_rate)
|
||||
return true;
|
||||
|
||||
|
||||
/*
|
||||
* In case we don't know the RSSI - take the lower wifi loss,
|
||||
* so we will more likely enter eSR, and if RSSI is low -
|
||||
* we will get an update on this and exit eSR.
|
||||
*/
|
||||
if (!link_rssi)
|
||||
wifi_loss_rate = mvm->last_bt_notif.wifi_loss_mid_high_rssi;
|
||||
|
||||
else if (mvmvif->esr_active)
|
||||
/* RSSI needs to get really low to disable eSR... */
|
||||
wifi_loss_rate =
|
||||
link_rssi <= -IWL_MVM_BT_COEX_DISABLE_ESR_THRESH ?
|
||||
mvm->last_bt_notif.wifi_loss_low_rssi :
|
||||
mvm->last_bt_notif.wifi_loss_mid_high_rssi;
|
||||
else
|
||||
/* ...And really high before we enable it back */
|
||||
wifi_loss_rate =
|
||||
link_rssi <= -IWL_MVM_BT_COEX_ENABLE_ESR_THRESH ?
|
||||
mvm->last_bt_notif.wifi_loss_low_rssi :
|
||||
mvm->last_bt_notif.wifi_loss_mid_high_rssi;
|
||||
|
||||
return wifi_loss_rate <= IWL_MVM_BT_COEX_WIFI_LOSS_THRESH;
|
||||
}
|
||||
|
||||
void iwl_mvm_bt_coex_update_link_esr(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
int link_id)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm_vif_link_info *link = mvmvif->link[link_id];
|
||||
|
||||
if (!ieee80211_vif_is_mld(vif) ||
|
||||
!iwl_mvm_vif_from_mac80211(vif)->authorized ||
|
||||
WARN_ON(!link))
|
||||
return;
|
||||
|
||||
if (!iwl_mvm_bt_coex_calculate_esr_mode(mvm, vif,
|
||||
(s8)link->beacon_stats.avg_signal,
|
||||
link_id == iwl_mvm_get_primary_link(vif)))
|
||||
/* In case we decided to exit eSR - stay with the primary */
|
||||
iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_COEX,
|
||||
iwl_mvm_get_primary_link(vif));
|
||||
}
|
||||
|
||||
static void iwl_mvm_bt_notif_per_link(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_bt_iterator_data *data,
|
||||
|
|
@ -296,12 +363,14 @@ static void iwl_mvm_bt_notif_per_link(struct iwl_mvm *mvm,
|
|||
smps_mode, link_id);
|
||||
iwl_mvm_bt_coex_reduced_txp(mvm, link_info->ap_sta_id,
|
||||
false);
|
||||
/* FIXME: should this be per link? */
|
||||
iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
|
||||
iwl_mvm_bt_coex_enable_rssi_event(mvm, link_info, false,
|
||||
0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
iwl_mvm_bt_coex_update_link_esr(mvm, vif, link_id);
|
||||
|
||||
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2))
|
||||
min_ag_for_static_smps = BT_VERY_HIGH_TRAFFIC;
|
||||
else
|
||||
|
|
@ -383,21 +452,19 @@ static void iwl_mvm_bt_notif_per_link(struct iwl_mvm *mvm,
|
|||
/*
|
||||
* don't reduce the Tx power if one of these is true:
|
||||
* we are in LOOSE
|
||||
* single share antenna product
|
||||
* BT is inactive
|
||||
* we are not associated
|
||||
*/
|
||||
if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
|
||||
mvm->cfg->bt_shared_single_ant || !vif->cfg.assoc ||
|
||||
le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF) {
|
||||
le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF ||
|
||||
!vif->cfg.assoc) {
|
||||
iwl_mvm_bt_coex_reduced_txp(mvm, link_info->ap_sta_id, false);
|
||||
/* FIXME: should this be per link? */
|
||||
iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
|
||||
iwl_mvm_bt_coex_enable_rssi_event(mvm, link_info, false, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* try to get the avg rssi from fw */
|
||||
ave_rssi = mvmvif->bf_data.ave_beacon_signal;
|
||||
ave_rssi = link_info->bf_data.ave_beacon_signal;
|
||||
|
||||
/* if the RSSI isn't valid, fake it is very low */
|
||||
if (!ave_rssi)
|
||||
|
|
@ -413,7 +480,7 @@ static void iwl_mvm_bt_notif_per_link(struct iwl_mvm *mvm,
|
|||
}
|
||||
|
||||
/* Begin to monitor the RSSI: it may influence the reduced Tx power */
|
||||
iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, true, ave_rssi);
|
||||
iwl_mvm_bt_coex_enable_rssi_event(mvm, link_info, true, ave_rssi);
|
||||
}
|
||||
|
||||
/* must be called under rcu_read_lock */
|
||||
|
|
@ -460,6 +527,11 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
|
|||
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
|
||||
iwl_mvm_bt_notif_iterator, &data);
|
||||
|
||||
if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
iwl_mvm_bt_coex_tcm_based_ci(mvm, &data);
|
||||
|
||||
if (data.primary) {
|
||||
|
|
@ -570,7 +642,7 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
* Check if rssi is good enough for reduced Tx power, but not in loose
|
||||
* scheme.
|
||||
*/
|
||||
if (rssi_event == RSSI_EVENT_LOW || mvm->cfg->bt_shared_single_ant ||
|
||||
if (rssi_event == RSSI_EVENT_LOW ||
|
||||
iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT)
|
||||
ret = iwl_mvm_bt_coex_reduced_txp(mvm,
|
||||
mvmvif->deflink.ap_sta_id,
|
||||
|
|
@ -639,10 +711,6 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
|
|||
|
||||
bool iwl_mvm_bt_coex_is_ant_avail(struct iwl_mvm *mvm, u8 ant)
|
||||
{
|
||||
/* there is no other antenna, shared antenna is always available */
|
||||
if (mvm->cfg->bt_shared_single_ant)
|
||||
return true;
|
||||
|
||||
if (ant & mvm->cfg->non_shared_ant)
|
||||
return true;
|
||||
|
||||
|
|
@ -652,10 +720,6 @@ bool iwl_mvm_bt_coex_is_ant_avail(struct iwl_mvm *mvm, u8 ant)
|
|||
|
||||
bool iwl_mvm_bt_coex_is_shared_ant_avail(struct iwl_mvm *mvm)
|
||||
{
|
||||
/* there is no other antenna, shared antenna is always available */
|
||||
if (mvm->cfg->bt_shared_single_ant)
|
||||
return true;
|
||||
|
||||
return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) < BT_HIGH_TRAFFIC;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2013-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2013-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2015 Intel Deutschland GmbH
|
||||
*/
|
||||
#ifndef __MVM_CONSTANTS_H
|
||||
|
|
@ -11,6 +11,11 @@
|
|||
#include "fw-api.h"
|
||||
|
||||
#define IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM 20
|
||||
#define IWL_MVM_BT_COEX_DISABLE_ESR_THRESH 69
|
||||
#define IWL_MVM_BT_COEX_ENABLE_ESR_THRESH 63
|
||||
#define IWL_MVM_BT_COEX_WIFI_LOSS_THRESH 0
|
||||
#define IWL_MVM_TRIGGER_LINK_SEL_TIME_SEC 30
|
||||
#define IWL_MVM_TPT_COUNT_WINDOW_SEC 5
|
||||
|
||||
#define IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
|
||||
#define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
|
||||
|
|
@ -18,7 +23,7 @@
|
|||
#define IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT (10 * USEC_PER_MSEC)
|
||||
#define IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT (2 * 1024) /* defined in TU */
|
||||
#define IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT (40 * 1024) /* defined in TU */
|
||||
#define IWL_MVM_P2P_LOWLATENCY_PS_ENABLE 0
|
||||
#define IWL_MVM_P2P_LOWLATENCY_PS_ENABLE 1
|
||||
#define IWL_MVM_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC)
|
||||
#define IWL_MVM_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC)
|
||||
#define IWL_MVM_UAPSD_QUEUES (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\
|
||||
|
|
@ -51,7 +56,6 @@
|
|||
#define IWL_MVM_RS_80_20_FAR_RANGE_TWEAK 1
|
||||
#define IWL_MVM_TOF_IS_RESPONDER 0
|
||||
#define IWL_MVM_HW_CSUM_DISABLE 0
|
||||
#define IWL_MVM_PARSE_NVM 0
|
||||
#define IWL_MVM_ADWELL_ENABLE 1
|
||||
#define IWL_MVM_ADWELL_MAX_BUDGET 0
|
||||
#define IWL_MVM_TCM_LOAD_MEDIUM_THRESH 10 /* percentage */
|
||||
|
|
@ -60,6 +64,7 @@
|
|||
#define IWL_MVM_UAPSD_NONAGG_PERIOD 5000 /* msecs */
|
||||
#define IWL_MVM_UAPSD_NOAGG_LIST_LEN IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM
|
||||
#define IWL_MVM_NON_TRANSMITTING_AP 0
|
||||
#define IWL_MVM_CONN_LISTEN_INTERVAL 10
|
||||
#define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1
|
||||
#define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE 2
|
||||
#define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE_TW 1
|
||||
|
|
@ -94,6 +99,7 @@
|
|||
#define IWL_MVM_FTM_INITIATOR_ALGO IWL_TOF_ALGO_TYPE_MAX_LIKE
|
||||
#define IWL_MVM_FTM_INITIATOR_DYNACK true
|
||||
#define IWL_MVM_FTM_LMR_FEEDBACK_TERMINATE false
|
||||
#define IWL_MVM_FTM_TEST_INCORRECT_SAC false
|
||||
#define IWL_MVM_FTM_R2I_MAX_REP 7
|
||||
#define IWL_MVM_FTM_I2R_MAX_REP 7
|
||||
#define IWL_MVM_FTM_R2I_MAX_STS 1
|
||||
|
|
@ -108,7 +114,6 @@
|
|||
#define IWL_MVM_D3_DEBUG false
|
||||
#define IWL_MVM_USE_TWT true
|
||||
#define IWL_MVM_AMPDU_CONSEC_DROPS_DELBA 20
|
||||
#define IWL_MVM_USE_NSSN_SYNC 0
|
||||
#define IWL_MVM_FTM_INITIATOR_ENABLE_SMOOTH false
|
||||
#define IWL_MVM_FTM_INITIATOR_SMOOTH_ALPHA 40
|
||||
/* 20016 pSec is 6 meter RTT, meaning 3 meter range */
|
||||
|
|
@ -118,5 +123,18 @@
|
|||
#define IWL_MVM_DISABLE_AP_FILS false
|
||||
#define IWL_MVM_6GHZ_PASSIVE_SCAN_TIMEOUT 3000 /* in seconds */
|
||||
#define IWL_MVM_6GHZ_PASSIVE_SCAN_ASSOC_TIMEOUT 60 /* in seconds */
|
||||
#define IWL_MVM_MIN_BEACON_INTERVAL_TU 16
|
||||
#define IWL_MVM_AUTO_EML_ENABLE true
|
||||
#define IWL_MVM_MISSED_BEACONS_EXIT_ESR_THRESH 7
|
||||
|
||||
#define IWL_MVM_HIGH_RSSI_THRESH_20MHZ -67
|
||||
#define IWL_MVM_LOW_RSSI_THRESH_20MHZ -71
|
||||
#define IWL_MVM_HIGH_RSSI_THRESH_40MHZ -64
|
||||
#define IWL_MVM_LOW_RSSI_THRESH_40MHZ -67
|
||||
#define IWL_MVM_HIGH_RSSI_THRESH_80MHZ -61
|
||||
#define IWL_MVM_LOW_RSSI_THRESH_80MHZ -74
|
||||
#define IWL_MVM_HIGH_RSSI_THRESH_160MHZ -58
|
||||
#define IWL_MVM_LOW_RSSI_THRESH_160MHZ -61
|
||||
|
||||
#define IWL_MVM_ENTER_ESR_TPT_THRESH 400
|
||||
#endif /* __MVM_CONSTANTS_H */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -384,9 +384,9 @@ static ssize_t iwl_dbgfs_bf_params_write(struct ieee80211_vif *vif, char *buf,
|
|||
mutex_lock(&mvm->mutex);
|
||||
iwl_dbgfs_update_bf(vif, param, value);
|
||||
if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value)
|
||||
ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
|
||||
ret = iwl_mvm_disable_beacon_filter(mvm, vif);
|
||||
else
|
||||
ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
|
||||
ret = iwl_mvm_enable_beacon_filter(mvm, vif);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return ret ?: count;
|
||||
|
|
@ -410,7 +410,7 @@ static ssize_t iwl_dbgfs_bf_params_read(struct file *file,
|
|||
};
|
||||
|
||||
iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
|
||||
if (mvmvif->bf_data.bf_enabled)
|
||||
if (mvmvif->bf_enabled)
|
||||
cmd.bf_enable_beacon_filter = cpu_to_le32(1);
|
||||
else
|
||||
cmd.bf_enable_beacon_filter = 0;
|
||||
|
|
@ -585,34 +585,47 @@ static ssize_t iwl_dbgfs_rx_phyinfo_write(struct ieee80211_vif *vif, char *buf,
|
|||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = mvmvif->mvm;
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
struct iwl_mvm_phy_ctxt *phy_ctxt;
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
u16 value;
|
||||
int ret;
|
||||
int link_id, ret = -EINVAL;
|
||||
|
||||
ret = kstrtou16(buf, 0, &value);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
rcu_read_lock();
|
||||
|
||||
chanctx_conf = rcu_dereference(vif->bss_conf.chanctx_conf);
|
||||
/* make sure the channel context is assigned */
|
||||
if (!chanctx_conf) {
|
||||
rcu_read_unlock();
|
||||
mutex_unlock(&mvm->mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
phy_ctxt = &mvm->phy_ctxts[*(u16 *)chanctx_conf->drv_priv];
|
||||
rcu_read_unlock();
|
||||
|
||||
mvm->dbgfs_rx_phyinfo = value;
|
||||
|
||||
ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &chanctx_conf->min_def,
|
||||
chanctx_conf->rx_chains_static,
|
||||
chanctx_conf->rx_chains_dynamic);
|
||||
for_each_vif_active_link(vif, link_conf, link_id) {
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
struct cfg80211_chan_def min_def, ap_def;
|
||||
struct iwl_mvm_phy_ctxt *phy_ctxt;
|
||||
u8 chains_static, chains_dynamic;
|
||||
|
||||
rcu_read_lock();
|
||||
chanctx_conf = rcu_dereference(link_conf->chanctx_conf);
|
||||
if (!chanctx_conf) {
|
||||
rcu_read_unlock();
|
||||
continue;
|
||||
}
|
||||
/* A command can't be sent with RCU lock held, so copy
|
||||
* everything here and use it after unlocking
|
||||
*/
|
||||
min_def = chanctx_conf->min_def;
|
||||
ap_def = chanctx_conf->ap;
|
||||
chains_static = chanctx_conf->rx_chains_static;
|
||||
chains_dynamic = chanctx_conf->rx_chains_dynamic;
|
||||
rcu_read_unlock();
|
||||
|
||||
phy_ctxt = mvmvif->link[link_id]->phy_ctxt;
|
||||
if (!phy_ctxt)
|
||||
continue;
|
||||
|
||||
ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &min_def, &ap_def,
|
||||
chains_static, chains_dynamic);
|
||||
}
|
||||
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return ret ?: count;
|
||||
|
|
@ -686,6 +699,132 @@ static ssize_t iwl_dbgfs_quota_min_read(struct file *file,
|
|||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_max_tx_op_write(struct ieee80211_vif *vif, char *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = mvmvif->mvm;
|
||||
u16 value;
|
||||
int ret;
|
||||
|
||||
ret = kstrtou16(buf, 0, &value);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
mvmvif->max_tx_op = value;
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_max_tx_op_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_vif *vif = file->private_data;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = mvmvif->mvm;
|
||||
char buf[10];
|
||||
int len;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
len = scnprintf(buf, sizeof(buf), "%hu\n", mvmvif->max_tx_op);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_int_mlo_scan_write(struct ieee80211_vif *vif,
|
||||
char *buf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = mvmvif->mvm;
|
||||
u32 action;
|
||||
int ret;
|
||||
|
||||
if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif))
|
||||
return -EINVAL;
|
||||
|
||||
if (kstrtou32(buf, 0, &action))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
if (!action) {
|
||||
ret = iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_INT_MLO, false);
|
||||
} else if (action == 1) {
|
||||
ret = iwl_mvm_int_mlo_scan(mvm, vif);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return ret ?: count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_esr_disable_reason_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_vif *vif = file->private_data;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = mvmvif->mvm;
|
||||
unsigned long esr_mask;
|
||||
char *buf;
|
||||
int bufsz, pos, i;
|
||||
ssize_t rv;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
esr_mask = mvmvif->esr_disable_reason;
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
bufsz = hweight32(esr_mask) * 32 + 40;
|
||||
buf = kmalloc(bufsz, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
pos = scnprintf(buf, bufsz, "EMLSR state: '0x%lx'\nreasons:\n",
|
||||
esr_mask);
|
||||
for_each_set_bit(i, &esr_mask, BITS_PER_LONG)
|
||||
pos += scnprintf(buf + pos, bufsz - pos, " - %s\n",
|
||||
iwl_get_esr_state_string(BIT(i)));
|
||||
|
||||
rv = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
kfree(buf);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_esr_disable_reason_write(struct ieee80211_vif *vif,
|
||||
char *buf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = mvmvif->mvm;
|
||||
u32 reason;
|
||||
u8 block;
|
||||
int ret;
|
||||
|
||||
ret = sscanf(buf, "%u %hhu", &reason, &block);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (hweight16(reason) != 1 || !(reason & IWL_MVM_BLOCK_ESR_REASONS))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
if (block)
|
||||
iwl_mvm_block_esr(mvm, vif, reason,
|
||||
iwl_mvm_get_primary_link(vif));
|
||||
else
|
||||
iwl_mvm_unblock_esr(mvm, vif, reason);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
#define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
|
||||
_MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
|
||||
#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
|
||||
|
|
@ -705,22 +844,15 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(uapsd_misbehaving, 20);
|
|||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(rx_phyinfo, 10);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min, 32);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(os_device_timediff);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(max_tx_op, 10);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(int_mlo_scan, 32);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(esr_disable_reason, 32);
|
||||
|
||||
|
||||
void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
void iwl_mvm_vif_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct dentry *dbgfs_dir = vif->debugfs_dir;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
#if defined(__linux__)
|
||||
char buf[100];
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check if debugfs directory already exist before creating it.
|
||||
* This may happen when, for example, resetting hw or suspend-resume
|
||||
*/
|
||||
if (!dbgfs_dir || mvmvif->dbgfs_dir)
|
||||
return;
|
||||
|
||||
mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir);
|
||||
if (IS_ERR_OR_NULL(mvmvif->dbgfs_dir)) {
|
||||
|
|
@ -742,10 +874,28 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
MVM_DEBUGFS_ADD_FILE_VIF(rx_phyinfo, mvmvif->dbgfs_dir, 0600);
|
||||
MVM_DEBUGFS_ADD_FILE_VIF(quota_min, mvmvif->dbgfs_dir, 0600);
|
||||
MVM_DEBUGFS_ADD_FILE_VIF(os_device_timediff, mvmvif->dbgfs_dir, 0400);
|
||||
MVM_DEBUGFS_ADD_FILE_VIF(max_tx_op, mvmvif->dbgfs_dir, 0600);
|
||||
debugfs_create_bool("ftm_unprotected", 0200, mvmvif->dbgfs_dir,
|
||||
&mvmvif->ftm_unprotected);
|
||||
MVM_DEBUGFS_ADD_FILE_VIF(int_mlo_scan, mvmvif->dbgfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE_VIF(esr_disable_reason, mvmvif->dbgfs_dir, 0600);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
|
||||
mvmvif == mvm->bf_allowed_vif)
|
||||
MVM_DEBUGFS_ADD_FILE_VIF(bf_params, mvmvif->dbgfs_dir, 0600);
|
||||
}
|
||||
|
||||
void iwl_mvm_vif_dbgfs_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct dentry *dbgfs_dir = vif->debugfs_dir;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
char buf[3 * 3 + 11 + (NL80211_WIPHY_NAME_MAXLEN + 1) +
|
||||
(7 + IFNAMSIZ + 1) + 6 + 1];
|
||||
char name[7 + IFNAMSIZ + 1];
|
||||
|
||||
/* this will happen in monitor mode */
|
||||
if (!dbgfs_dir)
|
||||
return;
|
||||
|
||||
#if defined(__linux__)
|
||||
/*
|
||||
|
|
@ -755,22 +905,64 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
* find
|
||||
* netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/
|
||||
*/
|
||||
snprintf(buf, 100, "../../../%pd3/%pd",
|
||||
dbgfs_dir,
|
||||
mvmvif->dbgfs_dir);
|
||||
snprintf(name, sizeof(name), "%pd", dbgfs_dir);
|
||||
snprintf(buf, sizeof(buf), "../../../%pd3/iwlmvm", dbgfs_dir);
|
||||
|
||||
mvmvif->dbgfs_slink = debugfs_create_symlink(dbgfs_dir->d_name.name,
|
||||
mvm->debugfs_dir, buf);
|
||||
mvmvif->dbgfs_slink =
|
||||
debugfs_create_symlink(name, mvm->debugfs_dir, buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
void iwl_mvm_vif_dbgfs_rm_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
debugfs_remove(mvmvif->dbgfs_slink);
|
||||
mvmvif->dbgfs_slink = NULL;
|
||||
|
||||
debugfs_remove_recursive(mvmvif->dbgfs_dir);
|
||||
mvmvif->dbgfs_dir = NULL;
|
||||
}
|
||||
|
||||
#define MVM_DEBUGFS_WRITE_LINK_FILE_OPS(name, bufsz) \
|
||||
_MVM_DEBUGFS_WRITE_FILE_OPS(link_##name, bufsz, \
|
||||
struct ieee80211_bss_conf)
|
||||
#define MVM_DEBUGFS_READ_WRITE_LINK_FILE_OPS(name, bufsz) \
|
||||
_MVM_DEBUGFS_READ_WRITE_FILE_OPS(link_##name, bufsz, \
|
||||
struct ieee80211_bss_conf)
|
||||
#define MVM_DEBUGFS_ADD_LINK_FILE(name, parent, mode) \
|
||||
debugfs_create_file(#name, mode, parent, link_conf, \
|
||||
&iwl_dbgfs_link_##name##_ops)
|
||||
|
||||
static void iwl_mvm_debugfs_add_link_files(struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct dentry *mvm_dir)
|
||||
{
|
||||
/* Add per-link files here*/
|
||||
}
|
||||
|
||||
void iwl_mvm_link_add_debugfs(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct dentry *dir)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = mvmvif->mvm;
|
||||
unsigned int link_id = link_conf->link_id;
|
||||
struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id];
|
||||
struct dentry *mvm_dir;
|
||||
|
||||
if (WARN_ON(!link_info) || !dir)
|
||||
return;
|
||||
|
||||
if (dir == vif->debugfs_dir) {
|
||||
WARN_ON(!mvmvif->dbgfs_dir);
|
||||
mvm_dir = mvmvif->dbgfs_dir;
|
||||
} else {
|
||||
mvm_dir = debugfs_create_dir("iwlmvm", dir);
|
||||
if (IS_ERR_OR_NULL(mvm_dir)) {
|
||||
IWL_ERR(mvm, "Failed to create debugfs directory under %pd\n",
|
||||
dir);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
iwl_mvm_debugfs_add_link_files(vif, link_conf, mvm_dir);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,8 +50,18 @@ static ssize_t iwl_dbgfs_stop_ctdp_write(struct iwl_mvm *mvm, char *buf,
|
|||
size_t count, loff_t *ppos)
|
||||
{
|
||||
int ret;
|
||||
bool force;
|
||||
|
||||
if (!iwl_mvm_is_ctdp_supported(mvm))
|
||||
if (!kstrtobool(buf, &force))
|
||||
IWL_DEBUG_INFO(mvm,
|
||||
"force start is %d [0=disabled, 1=enabled]\n",
|
||||
force);
|
||||
|
||||
/* we allow skipping cap support check and force stop ctdp
|
||||
* statistics collection and with guerantee that it is
|
||||
* safe to use.
|
||||
*/
|
||||
if (!force && !iwl_mvm_is_ctdp_supported(mvm))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!iwl_mvm_firmware_running(mvm) ||
|
||||
|
|
@ -65,6 +75,36 @@ static ssize_t iwl_dbgfs_stop_ctdp_write(struct iwl_mvm *mvm, char *buf,
|
|||
return ret ?: count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_start_ctdp_write(struct iwl_mvm *mvm,
|
||||
char *buf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
int ret;
|
||||
bool force;
|
||||
|
||||
if (!kstrtobool(buf, &force))
|
||||
IWL_DEBUG_INFO(mvm,
|
||||
"force start is %d [0=disabled, 1=enabled]\n",
|
||||
force);
|
||||
|
||||
/* we allow skipping cap support check and force enable ctdp
|
||||
* for statistics collection and with guerantee that it is
|
||||
* safe to use.
|
||||
*/
|
||||
if (!force && !iwl_mvm_is_ctdp_supported(mvm))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!iwl_mvm_firmware_running(mvm) ||
|
||||
mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
|
||||
return -EIO;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
ret = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_START, 0);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return ret ?: count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_force_ctkill_write(struct iwl_mvm *mvm, char *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
|
|
@ -111,37 +151,6 @@ static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
int sta_id, drain, ret;
|
||||
|
||||
if (!iwl_mvm_firmware_running(mvm) ||
|
||||
mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
|
||||
return -EIO;
|
||||
|
||||
if (sscanf(buf, "%d %d", &sta_id, &drain) != 2)
|
||||
return -EINVAL;
|
||||
if (sta_id < 0 || sta_id >= mvm->fw->ucode_capa.num_stations)
|
||||
return -EINVAL;
|
||||
if (drain < 0 || drain > 1)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
|
||||
|
||||
if (!mvmsta)
|
||||
ret = -ENOENT;
|
||||
else
|
||||
ret = iwl_mvm_drain_sta(mvm, mvmsta, drain) ? : count;
|
||||
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
|
|
@ -351,9 +360,7 @@ static ssize_t iwl_dbgfs_wifi_6e_enable_read(struct file *file,
|
|||
char buf[12];
|
||||
u32 value;
|
||||
|
||||
err = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0,
|
||||
DSM_FUNC_ENABLE_6E,
|
||||
&iwl_guid, &value);
|
||||
err = iwl_bios_get_dsm(&mvm->fwrt, DSM_FUNC_ENABLE_6E, &value);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
|
@ -530,193 +537,12 @@ static ssize_t iwl_dbgfs_disable_power_off_write(struct iwl_mvm *mvm, char *buf,
|
|||
return ret ?: count;
|
||||
}
|
||||
|
||||
static
|
||||
int iwl_mvm_coex_dump_mbox(struct iwl_bt_coex_profile_notif *notif, char *buf,
|
||||
int pos, int bufsz)
|
||||
{
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw0:\n");
|
||||
|
||||
BT_MBOX_PRINT(0, LE_SLAVE_LAT, false);
|
||||
BT_MBOX_PRINT(0, LE_PROF1, false);
|
||||
BT_MBOX_PRINT(0, LE_PROF2, false);
|
||||
BT_MBOX_PRINT(0, LE_PROF_OTHER, false);
|
||||
BT_MBOX_PRINT(0, CHL_SEQ_N, false);
|
||||
BT_MBOX_PRINT(0, INBAND_S, false);
|
||||
BT_MBOX_PRINT(0, LE_MIN_RSSI, false);
|
||||
BT_MBOX_PRINT(0, LE_SCAN, false);
|
||||
BT_MBOX_PRINT(0, LE_ADV, false);
|
||||
BT_MBOX_PRINT(0, LE_MAX_TX_POWER, false);
|
||||
BT_MBOX_PRINT(0, OPEN_CON_1, true);
|
||||
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw1:\n");
|
||||
|
||||
BT_MBOX_PRINT(1, BR_MAX_TX_POWER, false);
|
||||
BT_MBOX_PRINT(1, IP_SR, false);
|
||||
BT_MBOX_PRINT(1, LE_MSTR, false);
|
||||
BT_MBOX_PRINT(1, AGGR_TRFC_LD, false);
|
||||
BT_MBOX_PRINT(1, MSG_TYPE, false);
|
||||
BT_MBOX_PRINT(1, SSN, true);
|
||||
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw2:\n");
|
||||
|
||||
BT_MBOX_PRINT(2, SNIFF_ACT, false);
|
||||
BT_MBOX_PRINT(2, PAG, false);
|
||||
BT_MBOX_PRINT(2, INQUIRY, false);
|
||||
BT_MBOX_PRINT(2, CONN, false);
|
||||
BT_MBOX_PRINT(2, SNIFF_INTERVAL, false);
|
||||
BT_MBOX_PRINT(2, DISC, false);
|
||||
BT_MBOX_PRINT(2, SCO_TX_ACT, false);
|
||||
BT_MBOX_PRINT(2, SCO_RX_ACT, false);
|
||||
BT_MBOX_PRINT(2, ESCO_RE_TX, false);
|
||||
BT_MBOX_PRINT(2, SCO_DURATION, true);
|
||||
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw3:\n");
|
||||
|
||||
BT_MBOX_PRINT(3, SCO_STATE, false);
|
||||
BT_MBOX_PRINT(3, SNIFF_STATE, false);
|
||||
BT_MBOX_PRINT(3, A2DP_STATE, false);
|
||||
BT_MBOX_PRINT(3, A2DP_SRC, false);
|
||||
BT_MBOX_PRINT(3, ACL_STATE, false);
|
||||
BT_MBOX_PRINT(3, MSTR_STATE, false);
|
||||
BT_MBOX_PRINT(3, OBX_STATE, false);
|
||||
BT_MBOX_PRINT(3, OPEN_CON_2, false);
|
||||
BT_MBOX_PRINT(3, TRAFFIC_LOAD, false);
|
||||
BT_MBOX_PRINT(3, CHL_SEQN_LSB, false);
|
||||
BT_MBOX_PRINT(3, INBAND_P, false);
|
||||
BT_MBOX_PRINT(3, MSG_TYPE_2, false);
|
||||
BT_MBOX_PRINT(3, SSN_2, false);
|
||||
BT_MBOX_PRINT(3, UPDATE_REQUEST, true);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
|
||||
char *buf;
|
||||
int ret, pos = 0, bufsz = sizeof(char) * 1024;
|
||||
|
||||
buf = kmalloc(bufsz, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
pos += iwl_mvm_coex_dump_mbox(notif, buf, pos, bufsz);
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "bt_ci_compliance = %d\n",
|
||||
notif->bt_ci_compliance);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "primary_ch_lut = %d\n",
|
||||
le32_to_cpu(notif->primary_ch_lut));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "secondary_ch_lut = %d\n",
|
||||
le32_to_cpu(notif->secondary_ch_lut));
|
||||
pos += scnprintf(buf + pos,
|
||||
bufsz - pos, "bt_activity_grading = %d\n",
|
||||
le32_to_cpu(notif->bt_activity_grading));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "bt_rrc = %d\n",
|
||||
notif->rrc_status & 0xF);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "bt_ttc = %d\n",
|
||||
notif->ttc_status & 0xF);
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "sync_sco = %d\n",
|
||||
IWL_MVM_BT_COEX_SYNC2SCO);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "mplut = %d\n",
|
||||
IWL_MVM_BT_COEX_MPLUT);
|
||||
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
kfree(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#undef BT_MBOX_PRINT
|
||||
|
||||
static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd;
|
||||
char buf[256];
|
||||
int bufsz = sizeof(buf);
|
||||
int pos = 0;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "Channel inhibition CMD\n");
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\tPrimary Channel Bitmap 0x%016llx\n",
|
||||
le64_to_cpu(cmd->bt_primary_ci));
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\tSecondary Channel Bitmap 0x%016llx\n",
|
||||
le64_to_cpu(cmd->bt_secondary_ci));
|
||||
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
iwl_dbgfs_bt_tx_prio_write(struct iwl_mvm *mvm, char *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
u32 bt_tx_prio;
|
||||
|
||||
if (sscanf(buf, "%u", &bt_tx_prio) != 1)
|
||||
return -EINVAL;
|
||||
if (bt_tx_prio > 4)
|
||||
return -EINVAL;
|
||||
|
||||
mvm->bt_tx_prio = bt_tx_prio;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
iwl_dbgfs_bt_force_ant_write(struct iwl_mvm *mvm, char *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
static const char * const modes_str[BT_FORCE_ANT_MAX] = {
|
||||
[BT_FORCE_ANT_DIS] = "dis",
|
||||
[BT_FORCE_ANT_AUTO] = "auto",
|
||||
[BT_FORCE_ANT_BT] = "bt",
|
||||
[BT_FORCE_ANT_WIFI] = "wifi",
|
||||
};
|
||||
int ret, bt_force_ant_mode;
|
||||
|
||||
ret = match_string(modes_str, ARRAY_SIZE(modes_str), buf);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
bt_force_ant_mode = ret;
|
||||
ret = 0;
|
||||
mutex_lock(&mvm->mutex);
|
||||
if (mvm->bt_force_ant_mode == bt_force_ant_mode)
|
||||
goto out;
|
||||
|
||||
mvm->bt_force_ant_mode = bt_force_ant_mode;
|
||||
IWL_DEBUG_COEX(mvm, "Force mode: %s\n",
|
||||
modes_str[mvm->bt_force_ant_mode]);
|
||||
|
||||
if (iwl_mvm_firmware_running(mvm))
|
||||
ret = iwl_mvm_send_bt_init_conf(mvm);
|
||||
else
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
mutex_unlock(&mvm->mutex);
|
||||
return ret ?: count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_fw_ver_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
char *buff, *pos, *endpos;
|
||||
static const size_t bufsz = 1024;
|
||||
char _fw_name_pre[FW_NAME_PRE_BUFSIZE];
|
||||
int ret;
|
||||
|
||||
buff = kmalloc(bufsz, GFP_KERNEL);
|
||||
|
|
@ -726,8 +552,8 @@ static ssize_t iwl_dbgfs_fw_ver_read(struct file *file, char __user *user_buf,
|
|||
pos = buff;
|
||||
endpos = pos + bufsz;
|
||||
|
||||
pos += scnprintf(pos, endpos - pos, "FW prefix: %s\n",
|
||||
iwl_drv_get_fwname_pre(mvm->trans, _fw_name_pre));
|
||||
pos += scnprintf(pos, endpos - pos, "FW id: %s\n",
|
||||
mvm->fwrt.fw->fw_version);
|
||||
pos += scnprintf(pos, endpos - pos, "FW: %s\n",
|
||||
mvm->fwrt.fw->human_readable);
|
||||
pos += scnprintf(pos, endpos - pos, "Device: %s\n",
|
||||
|
|
@ -841,14 +667,14 @@ static ssize_t iwl_dbgfs_tas_get_status_read(struct file *file,
|
|||
le16_to_cpu(rsp->curr_mcc));
|
||||
|
||||
pos += scnprintf(pos, endpos - pos, "Block list entries:");
|
||||
for (i = 0; i < APCI_WTAS_BLACK_LIST_MAX; i++)
|
||||
for (i = 0; i < IWL_WTAS_BLACK_LIST_MAX; i++)
|
||||
pos += scnprintf(pos, endpos - pos, " 0x%x",
|
||||
le16_to_cpu(rsp->block_list[i]));
|
||||
|
||||
pos += scnprintf(pos, endpos - pos, "\nOEM name: %s\n",
|
||||
dmi_get_system_info(DMI_SYS_VENDOR));
|
||||
dmi_get_system_info(DMI_SYS_VENDOR) ?: "<unknown>");
|
||||
pos += scnprintf(pos, endpos - pos, "\tVendor In Approved List: %s\n",
|
||||
iwl_mvm_is_vendor_in_approved_list() ? "YES" : "NO");
|
||||
iwl_is_tas_approved() ? "YES" : "NO");
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"\tDo TAS Support Dual Radio?: %s\n",
|
||||
rsp->in_dual_radio ? "TRUE" : "FALSE");
|
||||
|
|
@ -969,6 +795,13 @@ static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file,
|
|||
char *buf;
|
||||
int ret;
|
||||
size_t bufsz;
|
||||
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
|
||||
WIDE_ID(SYSTEM_GROUP,
|
||||
SYSTEM_STATISTICS_CMD),
|
||||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
|
||||
if (cmd_ver != IWL_FW_CMD_VER_UNKNOWN)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (iwl_mvm_has_new_rx_stats_api(mvm))
|
||||
bufsz = ((sizeof(struct mvm_statistics_rx) /
|
||||
|
|
@ -1148,6 +981,101 @@ static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file,
|
|||
}
|
||||
#undef PRINT_STAT_LE32
|
||||
|
||||
static ssize_t iwl_dbgfs_fw_system_stats_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char *buff, *pos, *endpos;
|
||||
int ret;
|
||||
size_t bufsz;
|
||||
int i;
|
||||
struct iwl_mvm_vif *mvmvif;
|
||||
struct ieee80211_vif *vif;
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
|
||||
WIDE_ID(SYSTEM_GROUP,
|
||||
SYSTEM_STATISTICS_CMD),
|
||||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
|
||||
/* in case of a wrong cmd version, allocate buffer only for error msg */
|
||||
bufsz = (cmd_ver == 1) ? 4096 : 64;
|
||||
|
||||
buff = kzalloc(bufsz, GFP_KERNEL);
|
||||
if (!buff)
|
||||
return -ENOMEM;
|
||||
|
||||
pos = buff;
|
||||
endpos = pos + bufsz;
|
||||
|
||||
if (cmd_ver != 1) {
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"System stats not supported:%d\n", cmd_ver);
|
||||
goto send_out;
|
||||
}
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
if (iwl_mvm_firmware_running(mvm))
|
||||
iwl_mvm_request_statistics(mvm, false);
|
||||
|
||||
for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) {
|
||||
vif = iwl_mvm_rcu_dereference_vif_id(mvm, i, false);
|
||||
if (!vif)
|
||||
continue;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == NUM_MAC_INDEX_DRIVER || !vif) {
|
||||
pos += scnprintf(pos, endpos - pos, "vif is NULL\n");
|
||||
goto release_send_out;
|
||||
}
|
||||
|
||||
mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
if (!mvmvif) {
|
||||
pos += scnprintf(pos, endpos - pos, "mvmvif is NULL\n");
|
||||
goto release_send_out;
|
||||
}
|
||||
|
||||
for_each_mvm_vif_valid_link(mvmvif, i) {
|
||||
struct iwl_mvm_vif_link_info *link_info = mvmvif->link[i];
|
||||
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"link_id %d", i);
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
" num_beacons %d",
|
||||
link_info->beacon_stats.num_beacons);
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
" accu_num_beacons %d",
|
||||
link_info->beacon_stats.accu_num_beacons);
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
" avg_signal %d\n",
|
||||
link_info->beacon_stats.avg_signal);
|
||||
}
|
||||
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"radio_stats.rx_time %lld\n",
|
||||
mvm->radio_stats.rx_time);
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"radio_stats.tx_time %lld\n",
|
||||
mvm->radio_stats.tx_time);
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"accu_radio_stats.rx_time %lld\n",
|
||||
mvm->accu_radio_stats.rx_time);
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"accu_radio_stats.tx_time %lld\n",
|
||||
mvm->accu_radio_stats.tx_time);
|
||||
|
||||
release_send_out:
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
send_out:
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff);
|
||||
kfree(buff);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm,
|
||||
char __user *user_buf, size_t count,
|
||||
loff_t *ppos,
|
||||
|
|
@ -1260,6 +1188,8 @@ static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
|
|||
if (!iwl_mvm_firmware_running(mvm))
|
||||
return -EIO;
|
||||
|
||||
IWL_ERR(mvm, "Triggering an NMI from debugfs\n");
|
||||
|
||||
if (count == 6 && !strcmp(buf, "nolog\n"))
|
||||
set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status);
|
||||
|
||||
|
|
@ -1383,7 +1313,7 @@ static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm,
|
|||
|
||||
/* supporting only MQ RX */
|
||||
if (!mvm->trans->trans_cfg->mq_rx_supported)
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
rxb._page = alloc_pages(GFP_ATOMIC, 0);
|
||||
if (!rxb._page)
|
||||
|
|
@ -1481,6 +1411,15 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)
|
|||
&beacon_cmd.tim_size,
|
||||
beacon->data, beacon->len);
|
||||
|
||||
if (iwl_fw_lookup_cmd_ver(mvm->fw,
|
||||
BEACON_TEMPLATE_CMD, 0) >= 14) {
|
||||
u32 offset = iwl_mvm_find_ie_offset(beacon->data,
|
||||
WLAN_EID_S1G_TWT,
|
||||
beacon->len);
|
||||
|
||||
beacon_cmd.btwt_offset = cpu_to_le32(offset);
|
||||
}
|
||||
|
||||
iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
|
||||
sizeof(beacon_cmd));
|
||||
}
|
||||
|
|
@ -1576,6 +1515,20 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm,
|
|||
return count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_fw_dbg_clear_write(struct iwl_mvm *mvm,
|
||||
char *buf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_9000)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
iwl_fw_dbg_clear_monitor_buf(&mvm->fwrt);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_dbg_time_point_write(struct iwl_mvm *mvm,
|
||||
char *buf, size_t count,
|
||||
loff_t *ppos)
|
||||
|
|
@ -1677,7 +1630,7 @@ static ssize_t _iwl_dbgfs_link_sta_##name##_write(struct file *file, \
|
|||
char buf[buflen] = {}; \
|
||||
size_t buf_size = min(count, sizeof(buf) - 1); \
|
||||
\
|
||||
if (copy_from_user(buf, user_buf, sizeof(buf))) \
|
||||
if (copy_from_user(buf, user_buf, buf_size)) \
|
||||
return -EFAULT; \
|
||||
\
|
||||
return _iwl_dbgfs_link_sta_wrap_write(iwl_dbgfs_##name##_write, \
|
||||
|
|
@ -2002,30 +1955,28 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64);
|
|||
/* Device wide debugfs entries */
|
||||
MVM_DEBUGFS_READ_FILE_OPS(ctdp_budget);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(stop_ctdp, 8);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(start_ctdp, 8);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(force_ctkill, 8);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(send_echo_cmd, 8);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(set_nic_temperature, 64);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(nic_temp);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(stations);
|
||||
MVM_DEBUGFS_READ_LINK_STA_FILE_OPS(rs_data);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(bt_notif);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(bt_cmd);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(fw_system_stats);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(fw_ver);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(phy_integration_ver);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(tas_get_status);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_clear, 64);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(dbg_time_point, 64);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl,
|
||||
(IWL_RSS_INDIRECTION_TABLE_SIZE * 2));
|
||||
|
|
@ -2208,28 +2159,26 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm)
|
|||
spin_lock_init(&mvm->drv_stats_lock);
|
||||
|
||||
MVM_DEBUGFS_ADD_FILE(tx_flush, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, 0600);
|
||||
MVM_DEBUGFS_ADD_FILE(set_nic_temperature, mvm->debugfs_dir, 0600);
|
||||
MVM_DEBUGFS_ADD_FILE(nic_temp, mvm->debugfs_dir, 0400);
|
||||
MVM_DEBUGFS_ADD_FILE(ctdp_budget, mvm->debugfs_dir, 0400);
|
||||
MVM_DEBUGFS_ADD_FILE(stop_ctdp, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(start_ctdp, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(force_ctkill, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(stations, mvm->debugfs_dir, 0400);
|
||||
MVM_DEBUGFS_ADD_FILE(bt_notif, mvm->debugfs_dir, 0400);
|
||||
MVM_DEBUGFS_ADD_FILE(bt_cmd, mvm->debugfs_dir, 0400);
|
||||
MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir, 0600);
|
||||
MVM_DEBUGFS_ADD_FILE(fw_ver, mvm->debugfs_dir, 0400);
|
||||
MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, 0400);
|
||||
MVM_DEBUGFS_ADD_FILE(drv_rx_stats, mvm->debugfs_dir, 0400);
|
||||
MVM_DEBUGFS_ADD_FILE(fw_system_stats, mvm->debugfs_dir, 0400);
|
||||
MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(bt_tx_prio, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(bt_force_ant, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir, 0600);
|
||||
MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, 0600);
|
||||
MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, 0600);
|
||||
MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(fw_dbg_clear, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(dbg_time_point, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, 0200);
|
||||
|
|
@ -2283,6 +2232,9 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm)
|
|||
debugfs_create_file("mem", 0600, mvm->debugfs_dir, mvm,
|
||||
&iwl_dbgfs_mem_ops);
|
||||
|
||||
debugfs_create_bool("rx_ts_ptp", 0600, mvm->debugfs_dir,
|
||||
&mvm->rx_ts_ptp);
|
||||
|
||||
#if defined(__linux__)
|
||||
/*
|
||||
* Create a symlink with mac80211. It will be removed when mac80211
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2023 Intel Corporation
|
||||
* Copyright (C) 2012-2014 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2018-2024 Intel Corporation
|
||||
*/
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/math64.h>
|
||||
|
|
@ -40,6 +40,12 @@ struct iwl_mvm_ftm_pasn_entry {
|
|||
u32 flags;
|
||||
};
|
||||
|
||||
struct iwl_mvm_ftm_iter_data {
|
||||
u8 *cipher;
|
||||
u8 *bssid;
|
||||
u8 *tk;
|
||||
};
|
||||
|
||||
int iwl_mvm_ftm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
u8 *addr, u32 cipher, u8 *tk, u32 tk_len,
|
||||
u8 *hltk, u32 hltk_len)
|
||||
|
|
@ -53,6 +59,8 @@ int iwl_mvm_ftm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
if (!pasn)
|
||||
return -ENOBUFS;
|
||||
|
||||
iwl_mvm_ftm_remove_pasn_sta(mvm, addr);
|
||||
|
||||
pasn->cipher = iwl_mvm_cipher_to_location_cipher(cipher);
|
||||
|
||||
switch (pasn->cipher) {
|
||||
|
|
@ -433,9 +441,43 @@ iwl_mvm_ftm_put_target_v2(struct iwl_mvm *mvm,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define FTM_PUT_FLAG(flag) (target->initiator_ap_flags |= \
|
||||
#define FTM_SET_FLAG(flag) (*flags |= \
|
||||
cpu_to_le32(IWL_INITIATOR_AP_FLAGS_##flag))
|
||||
|
||||
static void
|
||||
iwl_mvm_ftm_set_target_flags(struct iwl_mvm *mvm,
|
||||
struct cfg80211_pmsr_request_peer *peer,
|
||||
__le32 *flags)
|
||||
{
|
||||
*flags = cpu_to_le32(0);
|
||||
|
||||
if (peer->ftm.asap)
|
||||
FTM_SET_FLAG(ASAP);
|
||||
|
||||
if (peer->ftm.request_lci)
|
||||
FTM_SET_FLAG(LCI_REQUEST);
|
||||
|
||||
if (peer->ftm.request_civicloc)
|
||||
FTM_SET_FLAG(CIVIC_REQUEST);
|
||||
|
||||
if (IWL_MVM_FTM_INITIATOR_DYNACK)
|
||||
FTM_SET_FLAG(DYN_ACK);
|
||||
|
||||
if (IWL_MVM_FTM_INITIATOR_ALGO == IWL_TOF_ALGO_TYPE_LINEAR_REG)
|
||||
FTM_SET_FLAG(ALGO_LR);
|
||||
else if (IWL_MVM_FTM_INITIATOR_ALGO == IWL_TOF_ALGO_TYPE_FFT)
|
||||
FTM_SET_FLAG(ALGO_FFT);
|
||||
|
||||
if (peer->ftm.trigger_based)
|
||||
FTM_SET_FLAG(TB);
|
||||
else if (peer->ftm.non_trigger_based)
|
||||
FTM_SET_FLAG(NON_TB);
|
||||
|
||||
if ((peer->ftm.trigger_based || peer->ftm.non_trigger_based) &&
|
||||
peer->ftm.lmr_feedback)
|
||||
FTM_SET_FLAG(LMR_FEEDBACK);
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mvm_ftm_put_target_common(struct iwl_mvm *mvm,
|
||||
struct cfg80211_pmsr_request_peer *peer,
|
||||
|
|
@ -447,33 +489,7 @@ iwl_mvm_ftm_put_target_common(struct iwl_mvm *mvm,
|
|||
target->samples_per_burst = peer->ftm.ftms_per_burst;
|
||||
target->num_of_bursts = peer->ftm.num_bursts_exp;
|
||||
target->ftmr_max_retries = peer->ftm.ftmr_retries;
|
||||
target->initiator_ap_flags = cpu_to_le32(0);
|
||||
|
||||
if (peer->ftm.asap)
|
||||
FTM_PUT_FLAG(ASAP);
|
||||
|
||||
if (peer->ftm.request_lci)
|
||||
FTM_PUT_FLAG(LCI_REQUEST);
|
||||
|
||||
if (peer->ftm.request_civicloc)
|
||||
FTM_PUT_FLAG(CIVIC_REQUEST);
|
||||
|
||||
if (IWL_MVM_FTM_INITIATOR_DYNACK)
|
||||
FTM_PUT_FLAG(DYN_ACK);
|
||||
|
||||
if (IWL_MVM_FTM_INITIATOR_ALGO == IWL_TOF_ALGO_TYPE_LINEAR_REG)
|
||||
FTM_PUT_FLAG(ALGO_LR);
|
||||
else if (IWL_MVM_FTM_INITIATOR_ALGO == IWL_TOF_ALGO_TYPE_FFT)
|
||||
FTM_PUT_FLAG(ALGO_FFT);
|
||||
|
||||
if (peer->ftm.trigger_based)
|
||||
FTM_PUT_FLAG(TB);
|
||||
else if (peer->ftm.non_trigger_based)
|
||||
FTM_PUT_FLAG(NON_TB);
|
||||
|
||||
if ((peer->ftm.trigger_based || peer->ftm.non_trigger_based) &&
|
||||
peer->ftm.lmr_feedback)
|
||||
FTM_PUT_FLAG(LMR_FEEDBACK);
|
||||
iwl_mvm_ftm_set_target_flags(mvm, peer, &target->initiator_ap_flags);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -516,6 +532,48 @@ iwl_mvm_ftm_put_target_v4(struct iwl_mvm *mvm,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_mvm_ftm_set_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request_peer *peer,
|
||||
u8 *sta_id, __le32 *flags)
|
||||
{
|
||||
if (vif->cfg.assoc) {
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct ieee80211_sta *sta;
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
unsigned int link_id;
|
||||
|
||||
rcu_read_lock();
|
||||
for_each_vif_active_link(vif, link_conf, link_id) {
|
||||
if (memcmp(peer->addr, link_conf->bssid, ETH_ALEN))
|
||||
continue;
|
||||
|
||||
*sta_id = mvmvif->link[link_id]->ap_sta_id;
|
||||
sta = rcu_dereference(mvm->fw_id_to_mac_id[*sta_id]);
|
||||
if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta))) {
|
||||
rcu_read_unlock();
|
||||
return PTR_ERR_OR_ZERO(sta);
|
||||
}
|
||||
|
||||
if (sta->mfp && (peer->ftm.trigger_based ||
|
||||
peer->ftm.non_trigger_based))
|
||||
FTM_SET_FLAG(PMF);
|
||||
break;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (mvmvif->ftm_unprotected) {
|
||||
*sta_id = IWL_MVM_INVALID_STA;
|
||||
*flags &= ~cpu_to_le32(IWL_INITIATOR_AP_FLAGS_PMF);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
*sta_id = IWL_MVM_INVALID_STA;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_mvm_ftm_put_target(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request_peer *peer,
|
||||
|
|
@ -531,33 +589,8 @@ iwl_mvm_ftm_put_target(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
|
||||
iwl_mvm_ftm_put_target_common(mvm, peer, target);
|
||||
|
||||
if (vif->cfg.assoc) {
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct ieee80211_sta *sta;
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
unsigned int link_id;
|
||||
|
||||
rcu_read_lock();
|
||||
for_each_vif_active_link(vif, link_conf, link_id) {
|
||||
if (memcmp(peer->addr, link_conf->bssid, ETH_ALEN))
|
||||
continue;
|
||||
|
||||
target->sta_id = mvmvif->link[link_id]->ap_sta_id;
|
||||
sta = rcu_dereference(mvm->fw_id_to_mac_id[target->sta_id]);
|
||||
if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta))) {
|
||||
rcu_read_unlock();
|
||||
return PTR_ERR_OR_ZERO(sta);
|
||||
}
|
||||
|
||||
if (sta->mfp && (peer->ftm.trigger_based ||
|
||||
peer->ftm.non_trigger_based))
|
||||
FTM_PUT_FLAG(PMF);
|
||||
break;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
} else {
|
||||
target->sta_id = IWL_MVM_INVALID_STA;
|
||||
}
|
||||
iwl_mvm_ftm_set_sta(mvm, vif, peer, &target->sta_id,
|
||||
&target->initiator_ap_flags);
|
||||
|
||||
/*
|
||||
* TODO: Beacon interval is currently unknown, so use the common value
|
||||
|
|
@ -696,57 +729,62 @@ static void iter(struct ieee80211_hw *hw,
|
|||
struct ieee80211_key_conf *key,
|
||||
void *data)
|
||||
{
|
||||
struct iwl_tof_range_req_ap_entry_v6 *target = data;
|
||||
struct iwl_mvm_ftm_iter_data *target = data;
|
||||
|
||||
if (!sta || memcmp(sta->addr, target->bssid, ETH_ALEN))
|
||||
return;
|
||||
|
||||
WARN_ON(!sta->mfp);
|
||||
|
||||
if (WARN_ON(key->keylen > sizeof(target->tk)))
|
||||
return;
|
||||
|
||||
memcpy(target->tk, key->key, key->keylen);
|
||||
target->cipher = iwl_mvm_cipher_to_location_cipher(key->cipher);
|
||||
WARN_ON(target->cipher == IWL_LOCATION_CIPHER_INVALID);
|
||||
target->tk = key->key;
|
||||
*target->cipher = iwl_mvm_cipher_to_location_cipher(key->cipher);
|
||||
WARN_ON(*target->cipher == IWL_LOCATION_CIPHER_INVALID);
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mvm_ftm_set_secured_ranging(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct iwl_tof_range_req_ap_entry_v7 *target)
|
||||
u8 *bssid, u8 *cipher, u8 *hltk, u8 *tk,
|
||||
u8 *rx_pn, u8 *tx_pn, __le32 *flags)
|
||||
{
|
||||
struct iwl_mvm_ftm_pasn_entry *entry;
|
||||
u32 flags = le32_to_cpu(target->initiator_ap_flags);
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
if (!(flags & (IWL_INITIATOR_AP_FLAGS_NON_TB |
|
||||
if (mvmvif->ftm_unprotected)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (!(le32_to_cpu(*flags) & (IWL_INITIATOR_AP_FLAGS_NON_TB |
|
||||
IWL_INITIATOR_AP_FLAGS_TB)))
|
||||
return;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
list_for_each_entry(entry, &mvm->ftm_initiator.pasn_list, list) {
|
||||
if (memcmp(entry->addr, target->bssid, sizeof(entry->addr)))
|
||||
if (memcmp(entry->addr, bssid, sizeof(entry->addr)))
|
||||
continue;
|
||||
|
||||
target->cipher = entry->cipher;
|
||||
*cipher = entry->cipher;
|
||||
|
||||
if (entry->flags & IWL_MVM_PASN_FLAG_HAS_HLTK)
|
||||
memcpy(target->hltk, entry->hltk, sizeof(target->hltk));
|
||||
memcpy(hltk, entry->hltk, sizeof(entry->hltk));
|
||||
else
|
||||
memset(target->hltk, 0, sizeof(target->hltk));
|
||||
memset(hltk, 0, sizeof(entry->hltk));
|
||||
|
||||
if (vif->cfg.assoc &&
|
||||
!memcmp(vif->bss_conf.bssid, target->bssid,
|
||||
sizeof(target->bssid)))
|
||||
ieee80211_iter_keys(mvm->hw, vif, iter, target);
|
||||
else
|
||||
memcpy(target->tk, entry->tk, sizeof(target->tk));
|
||||
!memcmp(vif->bss_conf.bssid, bssid, ETH_ALEN)) {
|
||||
struct iwl_mvm_ftm_iter_data target;
|
||||
|
||||
memcpy(target->rx_pn, entry->rx_pn, sizeof(target->rx_pn));
|
||||
memcpy(target->tx_pn, entry->tx_pn, sizeof(target->tx_pn));
|
||||
target.bssid = bssid;
|
||||
ieee80211_iter_keys(mvm->hw, vif, iter, &target);
|
||||
} else {
|
||||
memcpy(tk, entry->tk, sizeof(entry->tk));
|
||||
}
|
||||
|
||||
target->initiator_ap_flags |=
|
||||
cpu_to_le32(IWL_INITIATOR_AP_FLAGS_SECURED);
|
||||
memcpy(rx_pn, entry->rx_pn, sizeof(entry->rx_pn));
|
||||
memcpy(tx_pn, entry->tx_pn, sizeof(entry->tx_pn));
|
||||
|
||||
FTM_SET_FLAG(SECURED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -760,7 +798,11 @@ iwl_mvm_ftm_put_target_v7(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
iwl_mvm_ftm_set_secured_ranging(mvm, vif, target);
|
||||
iwl_mvm_ftm_set_secured_ranging(mvm, vif, target->bssid,
|
||||
&target->cipher, target->hltk,
|
||||
target->tk, target->rx_pn,
|
||||
target->tx_pn,
|
||||
&target->initiator_ap_flags);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -825,9 +867,10 @@ iwl_mvm_ftm_put_target_v8(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
* If secure LTF is turned off, replace the flag with PMF only
|
||||
*/
|
||||
flags = le32_to_cpu(target->initiator_ap_flags);
|
||||
if ((flags & IWL_INITIATOR_AP_FLAGS_SECURED) &&
|
||||
!IWL_MVM_FTM_INITIATOR_SECURE_LTF) {
|
||||
flags &= ~IWL_INITIATOR_AP_FLAGS_SECURED;
|
||||
if (flags & IWL_INITIATOR_AP_FLAGS_SECURED) {
|
||||
if (!IWL_MVM_FTM_INITIATOR_SECURE_LTF)
|
||||
flags &= ~IWL_INITIATOR_AP_FLAGS_SECURED;
|
||||
|
||||
flags |= IWL_INITIATOR_AP_FLAGS_PMF;
|
||||
target->initiator_ap_flags = cpu_to_le32(flags);
|
||||
}
|
||||
|
|
@ -906,6 +949,105 @@ static int iwl_mvm_ftm_start_v13(struct iwl_mvm *mvm,
|
|||
return iwl_mvm_ftm_send_cmd(mvm, &hcmd);
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_mvm_ftm_put_target_v10(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request_peer *peer,
|
||||
struct iwl_tof_range_req_ap_entry_v10 *target)
|
||||
{
|
||||
u32 i2r_max_sts, flags;
|
||||
int ret;
|
||||
|
||||
ret = iwl_mvm_ftm_target_chandef_v2(mvm, peer, &target->channel_num,
|
||||
&target->format_bw,
|
||||
&target->ctrl_ch_position);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memcpy(target->bssid, peer->addr, ETH_ALEN);
|
||||
target->burst_period =
|
||||
cpu_to_le16(peer->ftm.burst_period);
|
||||
target->samples_per_burst = peer->ftm.ftms_per_burst;
|
||||
target->num_of_bursts = peer->ftm.num_bursts_exp;
|
||||
iwl_mvm_ftm_set_target_flags(mvm, peer, &target->initiator_ap_flags);
|
||||
iwl_mvm_ftm_set_sta(mvm, vif, peer, &target->sta_id,
|
||||
&target->initiator_ap_flags);
|
||||
iwl_mvm_ftm_set_secured_ranging(mvm, vif, target->bssid,
|
||||
&target->cipher, target->hltk,
|
||||
target->tk, target->rx_pn,
|
||||
target->tx_pn,
|
||||
&target->initiator_ap_flags);
|
||||
|
||||
i2r_max_sts = IWL_MVM_FTM_I2R_MAX_STS > 1 ? 1 :
|
||||
IWL_MVM_FTM_I2R_MAX_STS;
|
||||
|
||||
target->r2i_ndp_params = IWL_MVM_FTM_R2I_MAX_REP |
|
||||
(IWL_MVM_FTM_R2I_MAX_STS << IWL_LOCATION_MAX_STS_POS) |
|
||||
(IWL_MVM_FTM_R2I_MAX_TOTAL_LTF << IWL_LOCATION_TOTAL_LTF_POS);
|
||||
target->i2r_ndp_params = IWL_MVM_FTM_I2R_MAX_REP |
|
||||
(i2r_max_sts << IWL_LOCATION_MAX_STS_POS) |
|
||||
(IWL_MVM_FTM_I2R_MAX_TOTAL_LTF << IWL_LOCATION_TOTAL_LTF_POS);
|
||||
|
||||
if (peer->ftm.non_trigger_based) {
|
||||
target->min_time_between_msr =
|
||||
cpu_to_le16(IWL_MVM_FTM_NON_TB_MIN_TIME_BETWEEN_MSR);
|
||||
target->burst_period =
|
||||
cpu_to_le16(IWL_MVM_FTM_NON_TB_MAX_TIME_BETWEEN_MSR);
|
||||
} else {
|
||||
target->min_time_between_msr = cpu_to_le16(0);
|
||||
}
|
||||
|
||||
target->band =
|
||||
iwl_mvm_phy_band_from_nl80211(peer->chandef.chan->band);
|
||||
|
||||
/*
|
||||
* TODO: Beacon interval is currently unknown, so use the common value
|
||||
* of 100 TUs.
|
||||
*/
|
||||
target->beacon_interval = cpu_to_le16(100);
|
||||
|
||||
/*
|
||||
* If secure LTF is turned off, replace the flag with PMF only
|
||||
*/
|
||||
flags = le32_to_cpu(target->initiator_ap_flags);
|
||||
if (flags & IWL_INITIATOR_AP_FLAGS_SECURED) {
|
||||
if (!IWL_MVM_FTM_INITIATOR_SECURE_LTF)
|
||||
flags &= ~IWL_INITIATOR_AP_FLAGS_SECURED;
|
||||
|
||||
flags |= IWL_INITIATOR_AP_FLAGS_PMF;
|
||||
target->initiator_ap_flags = cpu_to_le32(flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_mvm_ftm_start_v14(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request *req)
|
||||
{
|
||||
struct iwl_tof_range_req_cmd_v14 cmd;
|
||||
struct iwl_host_cmd hcmd = {
|
||||
.id = WIDE_ID(LOCATION_GROUP, TOF_RANGE_REQ_CMD),
|
||||
.dataflags[0] = IWL_HCMD_DFL_DUP,
|
||||
.data[0] = &cmd,
|
||||
.len[0] = sizeof(cmd),
|
||||
};
|
||||
u8 i;
|
||||
int err;
|
||||
|
||||
iwl_mvm_ftm_cmd_common(mvm, vif, (void *)&cmd, req);
|
||||
|
||||
for (i = 0; i < cmd.num_of_ap; i++) {
|
||||
struct cfg80211_pmsr_request_peer *peer = &req->peers[i];
|
||||
struct iwl_tof_range_req_ap_entry_v10 *target = &cmd.ap[i];
|
||||
|
||||
err = iwl_mvm_ftm_put_target_v10(mvm, vif, peer, target);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return iwl_mvm_ftm_send_cmd(mvm, &hcmd);
|
||||
}
|
||||
|
||||
int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request *req)
|
||||
{
|
||||
|
|
@ -924,6 +1066,9 @@ int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
|
||||
switch (cmd_ver) {
|
||||
case 14:
|
||||
err = iwl_mvm_ftm_start_v14(mvm, vif, req);
|
||||
break;
|
||||
case 13:
|
||||
err = iwl_mvm_ftm_start_v13(mvm, vif, req);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2018-2024 Intel Corporation
|
||||
*/
|
||||
#include <net/cfg80211.h>
|
||||
#include <linux/etherdevice.h>
|
||||
|
|
@ -12,6 +12,9 @@ struct iwl_mvm_pasn_sta {
|
|||
struct list_head list;
|
||||
struct iwl_mvm_int_sta int_sta;
|
||||
u8 addr[ETH_ALEN];
|
||||
|
||||
/* must be last as it followed by buffer holding the key */
|
||||
struct ieee80211_key_conf keyconf;
|
||||
};
|
||||
|
||||
struct iwl_mvm_pasn_hltk_data {
|
||||
|
|
@ -39,7 +42,7 @@ static int iwl_mvm_ftm_responder_set_bw_v1(struct cfg80211_chan_def *chandef,
|
|||
*ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef);
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -77,7 +80,7 @@ static int iwl_mvm_ftm_responder_set_bw_v2(struct cfg80211_chan_def *chandef,
|
|||
}
|
||||
fallthrough;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -85,7 +88,7 @@ static int iwl_mvm_ftm_responder_set_bw_v2(struct cfg80211_chan_def *chandef,
|
|||
|
||||
static void
|
||||
iwl_mvm_ftm_responder_set_ndp(struct iwl_mvm *mvm,
|
||||
struct iwl_tof_responder_config_cmd_v9 *cmd)
|
||||
struct iwl_tof_responder_config_cmd *cmd)
|
||||
{
|
||||
/* Up to 2 R2I STS are allowed on the responder */
|
||||
u32 r2i_max_sts = IWL_MVM_FTM_R2I_MAX_STS < 2 ?
|
||||
|
|
@ -114,7 +117,7 @@ iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
|
|||
* field interpretation is different), so the same struct can be use
|
||||
* for all cases.
|
||||
*/
|
||||
struct iwl_tof_responder_config_cmd_v9 cmd = {
|
||||
struct iwl_tof_responder_config_cmd cmd = {
|
||||
.channel_num = chandef->chan->hw_value,
|
||||
.cmd_valid_fields =
|
||||
cpu_to_le32(IWL_TOF_RESPONDER_CMD_VALID_CHAN_INFO |
|
||||
|
|
@ -128,8 +131,13 @@ iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
|
|||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (cmd_ver == 10) {
|
||||
cmd.band =
|
||||
iwl_mvm_phy_band_from_nl80211(chandef->chan->band);
|
||||
}
|
||||
|
||||
/* Use a default of bss_color=1 for now */
|
||||
if (cmd_ver == 9) {
|
||||
if (cmd_ver >= 9) {
|
||||
cmd.cmd_valid_fields |=
|
||||
cpu_to_le32(IWL_TOF_RESPONDER_CMD_VALID_BSS_COLOR |
|
||||
IWL_TOF_RESPONDER_CMD_VALID_MIN_MAX_TIME_BETWEEN_MSR);
|
||||
|
|
@ -145,7 +153,7 @@ iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
|
|||
}
|
||||
|
||||
if (cmd_ver >= 8)
|
||||
iwl_mvm_ftm_responder_set_ndp(mvm, &cmd);
|
||||
iwl_mvm_ftm_responder_set_ndp(mvm, (void *)&cmd);
|
||||
|
||||
if (cmd_ver >= 7)
|
||||
err = iwl_mvm_ftm_responder_set_bw_v2(chandef, &cmd.format_bw,
|
||||
|
|
@ -291,7 +299,7 @@ iwl_mvm_ftm_responder_dyn_cfg_cmd(struct iwl_mvm *mvm,
|
|||
default:
|
||||
IWL_ERR(mvm, "Unsupported DYN_CONFIG_CMD version %u\n",
|
||||
cmd_ver);
|
||||
ret = -ENOTSUPP;
|
||||
ret = -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -302,7 +310,16 @@ static void iwl_mvm_resp_del_pasn_sta(struct iwl_mvm *mvm,
|
|||
struct iwl_mvm_pasn_sta *sta)
|
||||
{
|
||||
list_del(&sta->list);
|
||||
iwl_mvm_rm_sta_id(mvm, vif, sta->int_sta.sta_id);
|
||||
|
||||
if (sta->keyconf.keylen)
|
||||
iwl_mvm_sec_key_del_pasn(mvm, vif, BIT(sta->int_sta.sta_id),
|
||||
&sta->keyconf);
|
||||
|
||||
if (iwl_mvm_has_mld_api(mvm->fw))
|
||||
iwl_mvm_mld_rm_sta_id(mvm, sta->int_sta.sta_id);
|
||||
else
|
||||
iwl_mvm_rm_sta_id(mvm, vif, sta->int_sta.sta_id);
|
||||
|
||||
iwl_mvm_dealloc_int_sta(mvm, &sta->int_sta);
|
||||
kfree(sta);
|
||||
}
|
||||
|
|
@ -329,7 +346,7 @@ int iwl_mvm_ftm_respoder_add_pasn_sta(struct iwl_mvm *mvm,
|
|||
|
||||
if (cmd_ver < 3) {
|
||||
IWL_ERR(mvm, "Adding PASN station not supported by FW\n");
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if ((!hltk || !hltk_len) && (!tk || !tk_len)) {
|
||||
|
|
@ -338,6 +355,12 @@ int iwl_mvm_ftm_respoder_add_pasn_sta(struct iwl_mvm *mvm,
|
|||
}
|
||||
|
||||
if (hltk && hltk_len) {
|
||||
if (!fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_SECURE_LTF_SUPPORT)) {
|
||||
IWL_ERR(mvm, "No support for secure LTF measurement\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hltk_data.cipher = iwl_mvm_cipher_to_location_cipher(cipher);
|
||||
if (hltk_data.cipher == IWL_LOCATION_CIPHER_INVALID) {
|
||||
IWL_ERR(mvm, "invalid cipher: %u\n", cipher);
|
||||
|
|
@ -348,12 +371,12 @@ int iwl_mvm_ftm_respoder_add_pasn_sta(struct iwl_mvm *mvm,
|
|||
}
|
||||
|
||||
if (tk && tk_len) {
|
||||
sta = kzalloc(sizeof(*sta), GFP_KERNEL);
|
||||
sta = kzalloc(sizeof(*sta) + tk_len, GFP_KERNEL);
|
||||
if (!sta)
|
||||
return -ENOBUFS;
|
||||
|
||||
ret = iwl_mvm_add_pasn_sta(mvm, vif, &sta->int_sta, addr,
|
||||
cipher, tk, tk_len);
|
||||
cipher, tk, tk_len, &sta->keyconf);
|
||||
if (ret) {
|
||||
kfree(sta);
|
||||
return ret;
|
||||
|
|
@ -422,7 +445,7 @@ int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
rcu_read_unlock();
|
||||
|
||||
phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
|
||||
ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx.def,
|
||||
ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx.def, &ctx.ap,
|
||||
ctx.rx_chains_static,
|
||||
ctx.rx_chains_dynamic);
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -15,6 +15,8 @@
|
|||
#include "iwl-prph.h"
|
||||
#include "fw/acpi.h"
|
||||
#include "fw/pnvm.h"
|
||||
#include "fw/uefi.h"
|
||||
#include "fw/regulatory.h"
|
||||
|
||||
#include "mvm.h"
|
||||
#include "fw/dbg.h"
|
||||
|
|
@ -23,12 +25,9 @@
|
|||
#include "iwl-nvm-parse.h"
|
||||
#include "time-sync.h"
|
||||
|
||||
#define MVM_UCODE_ALIVE_TIMEOUT (HZ)
|
||||
#define MVM_UCODE_ALIVE_TIMEOUT (2 * HZ)
|
||||
#define MVM_UCODE_CALIB_TIMEOUT (2 * HZ)
|
||||
|
||||
#define IWL_TAS_US_MCC 0x5553
|
||||
#define IWL_TAS_CANADA_MCC 0x4341
|
||||
|
||||
struct iwl_mvm_alive_data {
|
||||
bool valid;
|
||||
u32 scd_base_addr;
|
||||
|
|
@ -92,20 +91,10 @@ void iwl_mvm_mfu_assert_dump_notif(struct iwl_mvm *mvm,
|
|||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_mfu_assert_dump_notif *mfu_dump_notif = (void *)pkt->data;
|
||||
__le32 *dump_data = mfu_dump_notif->data;
|
||||
int n_words = le32_to_cpu(mfu_dump_notif->data_size) / sizeof(__le32);
|
||||
int i;
|
||||
|
||||
if (mfu_dump_notif->index_num == 0)
|
||||
IWL_INFO(mvm, "MFUART assert id 0x%x occurred\n",
|
||||
le32_to_cpu(mfu_dump_notif->assert_id));
|
||||
|
||||
for (i = 0; i < n_words; i++)
|
||||
IWL_DEBUG_INFO(mvm,
|
||||
"MFUART assert dump, dword %u: 0x%08x\n",
|
||||
le16_to_cpu(mfu_dump_notif->index_num) *
|
||||
n_words + i,
|
||||
le32_to_cpu(dump_data[i]));
|
||||
}
|
||||
|
||||
static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
|
||||
|
|
@ -416,7 +405,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
|
|||
UREG_LMAC2_CURRENT_PC));
|
||||
}
|
||||
|
||||
if (ret == -ETIMEDOUT && !mvm->pldr_sync)
|
||||
if (ret == -ETIMEDOUT && !mvm->fw_product_reset)
|
||||
iwl_fw_dbg_error_collect(&mvm->fwrt,
|
||||
FW_DBG_TRIGGER_ALIVE_TIMEOUT);
|
||||
|
||||
|
|
@ -468,12 +457,14 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
|
|||
#endif
|
||||
|
||||
/*
|
||||
* For pre-MLD API (MLD API doesn't use the timestamps):
|
||||
* All the BSSes in the BSS table include the GP2 in the system
|
||||
* at the beacon Rx time, this is of course no longer relevant
|
||||
* since we are resetting the firmware.
|
||||
* Purge all the BSS table.
|
||||
*/
|
||||
cfg80211_bss_flush(mvm->hw->wiphy);
|
||||
if (!mvm->mld_api_is_used)
|
||||
cfg80211_bss_flush(mvm->hw->wiphy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -486,7 +477,47 @@ static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm,
|
|||
#endif /* CONFIG_ACPI */
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ACPI) && defined(CONFIG_EFI)
|
||||
static void iwl_mvm_uats_init(struct iwl_mvm *mvm)
|
||||
{
|
||||
u8 cmd_ver;
|
||||
int ret;
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = WIDE_ID(REGULATORY_AND_NVM_GROUP,
|
||||
MCC_ALLOWED_AP_TYPE_CMD),
|
||||
.flags = 0,
|
||||
.data[0] = &mvm->fwrt.uats_table,
|
||||
.len[0] = sizeof(mvm->fwrt.uats_table),
|
||||
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
|
||||
};
|
||||
|
||||
if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) {
|
||||
IWL_DEBUG_RADIO(mvm, "UATS feature is not supported\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd.id,
|
||||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
if (cmd_ver != 1) {
|
||||
IWL_DEBUG_RADIO(mvm,
|
||||
"MCC_ALLOWED_AP_TYPE_CMD ver %d not supported\n",
|
||||
cmd_ver);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = iwl_uefi_get_uats_table(mvm->trans, &mvm->fwrt);
|
||||
if (ret < 0) {
|
||||
IWL_DEBUG_FW(mvm, "failed to read UATS table (%d)\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||
if (ret < 0)
|
||||
IWL_ERR(mvm, "failed to send MCC_ALLOWED_AP_TYPE_CMD (%d)\n",
|
||||
ret);
|
||||
else
|
||||
IWL_DEBUG_RADIO(mvm, "MCC_ALLOWED_AP_TYPE_CMD sent to FW\n");
|
||||
}
|
||||
|
||||
static int iwl_mvm_sgom_init(struct iwl_mvm *mvm)
|
||||
{
|
||||
u8 cmd_ver;
|
||||
|
|
@ -520,13 +551,6 @@ static int iwl_mvm_sgom_init(struct iwl_mvm *mvm)
|
|||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
|
||||
static int iwl_mvm_sgom_init(struct iwl_mvm *mvm)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
|
||||
{
|
||||
|
|
@ -583,6 +607,7 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm)
|
|||
static const u16 init_complete[] = {
|
||||
INIT_COMPLETE_NOTIF,
|
||||
};
|
||||
u32 sb_cfg;
|
||||
int ret;
|
||||
|
||||
if (mvm->trans->cfg->tx_with_siso_diversity)
|
||||
|
|
@ -592,6 +617,14 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm)
|
|||
|
||||
mvm->rfkill_safe_init_done = false;
|
||||
|
||||
if (mvm->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210) {
|
||||
sb_cfg = iwl_read_umac_prph(mvm->trans, SB_MODIFY_CFG_FLAG);
|
||||
/* if needed, we'll reset this on our way out later */
|
||||
mvm->fw_product_reset = sb_cfg == SB_CFG_RESIDES_IN_ROM;
|
||||
if (mvm->fw_product_reset && iwl_mei_pldr_req())
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
iwl_init_notification_wait(&mvm->notif_wait,
|
||||
&init_wait,
|
||||
init_complete,
|
||||
|
|
@ -605,11 +638,23 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm)
|
|||
ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret);
|
||||
|
||||
/* if we needed reset then fail here, but notify and remove */
|
||||
if (mvm->fw_product_reset) {
|
||||
iwl_mei_alive_notif(false);
|
||||
iwl_trans_pcie_remove(mvm->trans, true);
|
||||
}
|
||||
|
||||
goto error;
|
||||
}
|
||||
iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_AFTER_ALIVE,
|
||||
NULL);
|
||||
|
||||
if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
|
||||
mvm->trans->step_urm = !!(iwl_read_umac_prph(mvm->trans,
|
||||
CNVI_PMU_STEP_FLOW) &
|
||||
CNVI_PMU_STEP_FLOW_FORCE_URM);
|
||||
|
||||
/* Send init config command to mark that we are sending NVM access
|
||||
* commands
|
||||
*/
|
||||
|
|
@ -634,14 +679,6 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm)
|
|||
goto error;
|
||||
}
|
||||
|
||||
if (IWL_MVM_PARSE_NVM && !mvm->nvm_data) {
|
||||
ret = iwl_nvm_init(mvm);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to read NVM: %d\n", ret);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(REGULATORY_AND_NVM_GROUP,
|
||||
NVM_ACCESS_COMPLETE),
|
||||
CMD_SEND_IN_RFKILL,
|
||||
|
|
@ -666,8 +703,9 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm)
|
|||
return ret;
|
||||
|
||||
/* Read the NVM only at driver load time, no need to do this twice */
|
||||
if (!IWL_MVM_PARSE_NVM && !mvm->nvm_data) {
|
||||
mvm->nvm_data = iwl_get_nvm(mvm->trans, mvm->fw);
|
||||
if (!mvm->nvm_data) {
|
||||
mvm->nvm_data = iwl_get_nvm(mvm->trans, mvm->fw,
|
||||
mvm->set_tx_ant, mvm->set_rx_ant);
|
||||
if (IS_ERR(mvm->nvm_data)) {
|
||||
ret = PTR_ERR(mvm->nvm_data);
|
||||
mvm->nvm_data = NULL;
|
||||
|
|
@ -790,7 +828,7 @@ remove_notif:
|
|||
iwl_remove_notification(&mvm->notif_wait, &calib_wait);
|
||||
out:
|
||||
mvm->rfkill_safe_init_done = false;
|
||||
if (iwlmvm_mod_params.init_dbg && !mvm->nvm_data) {
|
||||
if (!mvm->nvm_data) {
|
||||
/* we want to debug INIT and we have no NVM - fake */
|
||||
mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) +
|
||||
sizeof(struct ieee80211_channel) +
|
||||
|
|
@ -822,7 +860,6 @@ static int iwl_mvm_config_ltr(struct iwl_mvm *mvm)
|
|||
sizeof(cmd), &cmd);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
|
||||
{
|
||||
u32 cmd_id = REDUCE_TX_POWER_CMD;
|
||||
|
|
@ -833,13 +870,15 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
|
|||
int ret;
|
||||
u16 len = 0;
|
||||
u32 n_subbands;
|
||||
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id,
|
||||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
if (cmd_ver == 7) {
|
||||
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 3);
|
||||
|
||||
if (cmd_ver >= 7) {
|
||||
len = sizeof(cmd.v7);
|
||||
n_subbands = IWL_NUM_SUB_BANDS_V2;
|
||||
per_chain = cmd.v7.per_chain[0][0];
|
||||
cmd.v7.flags = cpu_to_le32(mvm->fwrt.reduced_power_flags);
|
||||
if (cmd_ver == 8)
|
||||
len = sizeof(cmd.v8);
|
||||
} else if (cmd_ver == 6) {
|
||||
len = sizeof(cmd.v6);
|
||||
n_subbands = IWL_NUM_SUB_BANDS_V2;
|
||||
|
|
@ -863,9 +902,9 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
|
|||
/* all structs have the same common part, add it */
|
||||
len += sizeof(cmd.common);
|
||||
|
||||
ret = iwl_sar_select_profile(&mvm->fwrt, per_chain,
|
||||
IWL_NUM_CHAIN_TABLES,
|
||||
n_subbands, prof_a, prof_b);
|
||||
ret = iwl_sar_fill_profile(&mvm->fwrt, per_chain,
|
||||
IWL_NUM_CHAIN_TABLES,
|
||||
n_subbands, prof_a, prof_b);
|
||||
|
||||
/* return on error or if the profile is disabled (positive number) */
|
||||
if (ret)
|
||||
|
|
@ -921,7 +960,7 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
|
|||
resp = (void *)cmd.resp_pkt->data;
|
||||
ret = le32_to_cpu(resp->profile_idx);
|
||||
|
||||
if (WARN_ON(ret > ACPI_NUM_GEO_PROFILES_REV3))
|
||||
if (WARN_ON(ret > BIOS_GEO_MAX_PROFILE_NUM))
|
||||
ret = -EIO;
|
||||
|
||||
iwl_free_resp(&cmd);
|
||||
|
|
@ -935,7 +974,7 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
|
|||
u16 len;
|
||||
u32 n_bands;
|
||||
u32 n_profiles;
|
||||
u32 sk = 0;
|
||||
__le32 sk = cpu_to_le32(0);
|
||||
int ret;
|
||||
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id,
|
||||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
|
|
@ -952,27 +991,35 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
|
|||
/* the ops field is at the same spot for all versions, so set in v1 */
|
||||
cmd.v1.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES);
|
||||
|
||||
/* Only set to South Korea if the table revision is 1 */
|
||||
if (mvm->fwrt.geo_rev == 1)
|
||||
sk = cpu_to_le32(1);
|
||||
|
||||
if (cmd_ver == 5) {
|
||||
len = sizeof(cmd.v5);
|
||||
n_bands = ARRAY_SIZE(cmd.v5.table[0]);
|
||||
n_profiles = ACPI_NUM_GEO_PROFILES_REV3;
|
||||
n_profiles = BIOS_GEO_MAX_PROFILE_NUM;
|
||||
cmd.v5.table_revision = sk;
|
||||
} else if (cmd_ver == 4) {
|
||||
len = sizeof(cmd.v4);
|
||||
n_bands = ARRAY_SIZE(cmd.v4.table[0]);
|
||||
n_profiles = ACPI_NUM_GEO_PROFILES_REV3;
|
||||
n_profiles = BIOS_GEO_MAX_PROFILE_NUM;
|
||||
cmd.v4.table_revision = sk;
|
||||
} else if (cmd_ver == 3) {
|
||||
len = sizeof(cmd.v3);
|
||||
n_bands = ARRAY_SIZE(cmd.v3.table[0]);
|
||||
n_profiles = ACPI_NUM_GEO_PROFILES;
|
||||
n_profiles = BIOS_GEO_MIN_PROFILE_NUM;
|
||||
cmd.v3.table_revision = sk;
|
||||
} else if (fw_has_api(&mvm->fwrt.fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_SAR_TABLE_VER)) {
|
||||
len = sizeof(cmd.v2);
|
||||
n_bands = ARRAY_SIZE(cmd.v2.table[0]);
|
||||
n_profiles = ACPI_NUM_GEO_PROFILES;
|
||||
n_profiles = BIOS_GEO_MIN_PROFILE_NUM;
|
||||
cmd.v2.table_revision = sk;
|
||||
} else {
|
||||
len = sizeof(cmd.v1);
|
||||
n_bands = ARRAY_SIZE(cmd.v1.table[0]);
|
||||
n_profiles = ACPI_NUM_GEO_PROFILES;
|
||||
n_profiles = BIOS_GEO_MIN_PROFILE_NUM;
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(offsetof(struct iwl_geo_tx_power_profiles_cmd_v1, table) !=
|
||||
|
|
@ -984,8 +1031,8 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
|
|||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v4, table) !=
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v5, table));
|
||||
/* the table is at the same position for all versions, so set use v1 */
|
||||
ret = iwl_sar_geo_init(&mvm->fwrt, &cmd.v1.table[0][0],
|
||||
n_bands, n_profiles);
|
||||
ret = iwl_sar_geo_fill_table(&mvm->fwrt, &cmd.v1.table[0][0],
|
||||
n_bands, n_profiles);
|
||||
|
||||
/*
|
||||
* It is a valid scenario to not support SAR, or miss wgds table,
|
||||
|
|
@ -994,27 +1041,6 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
|
|||
if (ret)
|
||||
return 0;
|
||||
|
||||
/* Only set to South Korea if the table revision is 1 */
|
||||
if (mvm->fwrt.geo_rev == 1)
|
||||
sk = 1;
|
||||
|
||||
/*
|
||||
* Set the table_revision to South Korea (1) or not (0). The
|
||||
* element name is misleading, as it doesn't contain the table
|
||||
* revision number, but whether the South Korea variation
|
||||
* should be used.
|
||||
* This must be done after calling iwl_sar_geo_init().
|
||||
*/
|
||||
if (cmd_ver == 5)
|
||||
cmd.v5.table_revision = cpu_to_le32(sk);
|
||||
else if (cmd_ver == 4)
|
||||
cmd.v4.table_revision = cpu_to_le32(sk);
|
||||
else if (cmd_ver == 3)
|
||||
cmd.v3.table_revision = cpu_to_le32(sk);
|
||||
else if (fw_has_api(&mvm->fwrt.fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_SAR_TABLE_VER))
|
||||
cmd.v2.table_revision = cpu_to_le32(sk);
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, len, &cmd);
|
||||
}
|
||||
|
||||
|
|
@ -1023,7 +1049,7 @@ int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
|
|||
union iwl_ppag_table_cmd cmd;
|
||||
int ret, cmd_size;
|
||||
|
||||
ret = iwl_read_ppag_table(&mvm->fwrt, &cmd, &cmd_size);
|
||||
ret = iwl_fill_ppag_table(&mvm->fwrt, &cmd, &cmd_size);
|
||||
/* Not supporting PPAG table is a valid scenario */
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
|
|
@ -1042,74 +1068,19 @@ int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
|
|||
static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
|
||||
{
|
||||
/* no need to read the table, done in INIT stage */
|
||||
if (!(iwl_acpi_is_ppag_approved(&mvm->fwrt)))
|
||||
if (!(iwl_is_ppag_approved(&mvm->fwrt)))
|
||||
return 0;
|
||||
|
||||
return iwl_mvm_ppag_send_cmd(mvm);
|
||||
}
|
||||
|
||||
static const struct dmi_system_id dmi_tas_approved_list[] = {
|
||||
{ .ident = "HP",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
||||
},
|
||||
},
|
||||
{ .ident = "SAMSUNG",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"),
|
||||
},
|
||||
},
|
||||
{ .ident = "LENOVO",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
},
|
||||
},
|
||||
{ .ident = "DELL",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
},
|
||||
},
|
||||
{ .ident = "MSFT",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
|
||||
},
|
||||
},
|
||||
{ .ident = "Acer",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
},
|
||||
},
|
||||
{ .ident = "ASUS",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
},
|
||||
},
|
||||
{ .ident = "MSI",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."),
|
||||
},
|
||||
},
|
||||
{ .ident = "Honor",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "HONOR"),
|
||||
},
|
||||
},
|
||||
/* keep last */
|
||||
{}
|
||||
};
|
||||
|
||||
bool iwl_mvm_is_vendor_in_approved_list(void)
|
||||
{
|
||||
return dmi_check_system(dmi_tas_approved_list);
|
||||
}
|
||||
|
||||
static bool iwl_mvm_add_to_tas_block_list(__le32 *list, __le32 *le_size, unsigned int mcc)
|
||||
{
|
||||
int i;
|
||||
u32 size = le32_to_cpu(*le_size);
|
||||
|
||||
/* Verify that there is room for another country */
|
||||
if (size >= IWL_TAS_BLOCK_LIST_MAX)
|
||||
if (size >= IWL_WTAS_BLACK_LIST_MAX)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
|
|
@ -1126,21 +1097,21 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
|
|||
{
|
||||
u32 cmd_id = WIDE_ID(REGULATORY_AND_NVM_GROUP, TAS_CONFIG);
|
||||
int ret;
|
||||
union iwl_tas_config_cmd cmd = {};
|
||||
struct iwl_tas_data data = {};
|
||||
struct iwl_tas_config_cmd cmd = {};
|
||||
int cmd_size, fw_ver;
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(cmd.v3.block_list_array) <
|
||||
APCI_WTAS_BLACK_LIST_MAX);
|
||||
BUILD_BUG_ON(ARRAY_SIZE(data.block_list_array) !=
|
||||
IWL_WTAS_BLACK_LIST_MAX);
|
||||
BUILD_BUG_ON(ARRAY_SIZE(cmd.common.block_list_array) !=
|
||||
IWL_WTAS_BLACK_LIST_MAX);
|
||||
|
||||
if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TAS_CFG)) {
|
||||
IWL_DEBUG_RADIO(mvm, "TAS not enabled in FW\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fw_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id,
|
||||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
|
||||
ret = iwl_acpi_get_tas(&mvm->fwrt, &cmd, fw_ver);
|
||||
ret = iwl_bios_get_tas_table(&mvm->fwrt, &data);
|
||||
if (ret < 0) {
|
||||
IWL_DEBUG_RADIO(mvm,
|
||||
"TAS table invalid or unavailable. (%d)\n",
|
||||
|
|
@ -1151,16 +1122,16 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
|
|||
if (ret == 0)
|
||||
return;
|
||||
|
||||
if (!iwl_mvm_is_vendor_in_approved_list()) {
|
||||
if (!iwl_is_tas_approved()) {
|
||||
IWL_DEBUG_RADIO(mvm,
|
||||
"System vendor '%s' is not in the approved list, disabling TAS in US and Canada.\n",
|
||||
dmi_get_system_info(DMI_SYS_VENDOR));
|
||||
if ((!iwl_mvm_add_to_tas_block_list(cmd.v4.block_list_array,
|
||||
&cmd.v4.block_list_size,
|
||||
IWL_TAS_US_MCC)) ||
|
||||
(!iwl_mvm_add_to_tas_block_list(cmd.v4.block_list_array,
|
||||
&cmd.v4.block_list_size,
|
||||
IWL_TAS_CANADA_MCC))) {
|
||||
dmi_get_system_info(DMI_SYS_VENDOR) ?: "<unknown>");
|
||||
if ((!iwl_mvm_add_to_tas_block_list(data.block_list_array,
|
||||
&data.block_list_size,
|
||||
IWL_MCC_US)) ||
|
||||
(!iwl_mvm_add_to_tas_block_list(data.block_list_array,
|
||||
&data.block_list_size,
|
||||
IWL_MCC_CANADA))) {
|
||||
IWL_DEBUG_RADIO(mvm,
|
||||
"Unable to add US/Canada to TAS block list, disabling TAS\n");
|
||||
return;
|
||||
|
|
@ -1168,125 +1139,74 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
|
|||
} else {
|
||||
IWL_DEBUG_RADIO(mvm,
|
||||
"System vendor '%s' is in the approved list.\n",
|
||||
dmi_get_system_info(DMI_SYS_VENDOR));
|
||||
dmi_get_system_info(DMI_SYS_VENDOR) ?: "<unknown>");
|
||||
}
|
||||
|
||||
/* v4 is the same size as v3, so no need to differentiate here */
|
||||
cmd_size = fw_ver < 3 ?
|
||||
sizeof(struct iwl_tas_config_cmd_v2) :
|
||||
sizeof(struct iwl_tas_config_cmd_v3);
|
||||
fw_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id,
|
||||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
|
||||
memcpy(&cmd.common, &data, sizeof(struct iwl_tas_config_cmd_common));
|
||||
|
||||
/* Set v3 or v4 specific parts. will be trunctated for fw_ver < 3 */
|
||||
if (fw_ver == 4) {
|
||||
cmd.v4.override_tas_iec = data.override_tas_iec;
|
||||
cmd.v4.enable_tas_iec = data.enable_tas_iec;
|
||||
cmd.v4.usa_tas_uhb_allowed = data.usa_tas_uhb_allowed;
|
||||
} else {
|
||||
cmd.v3.override_tas_iec = cpu_to_le16(data.override_tas_iec);
|
||||
cmd.v3.enable_tas_iec = cpu_to_le16(data.enable_tas_iec);
|
||||
}
|
||||
|
||||
cmd_size = sizeof(struct iwl_tas_config_cmd_common);
|
||||
if (fw_ver >= 3)
|
||||
/* v4 is the same size as v3 */
|
||||
cmd_size += sizeof(struct iwl_tas_config_cmd_v3);
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, cmd_size, &cmd);
|
||||
if (ret < 0)
|
||||
IWL_DEBUG_RADIO(mvm, "failed to send TAS_CONFIG (%d)\n", ret);
|
||||
}
|
||||
|
||||
static u8 iwl_mvm_eval_dsm_rfi(struct iwl_mvm *mvm)
|
||||
static bool iwl_mvm_eval_dsm_rfi(struct iwl_mvm *mvm)
|
||||
{
|
||||
u8 value;
|
||||
int ret = iwl_acpi_get_dsm_u8(mvm->fwrt.dev, 0, DSM_RFI_FUNC_ENABLE,
|
||||
&iwl_rfi_guid, &value);
|
||||
u32 value = 0;
|
||||
/* default behaviour is disabled */
|
||||
bool bios_enable_rfi = false;
|
||||
int ret = iwl_bios_get_dsm(&mvm->fwrt, DSM_FUNC_RFI_CONFIG, &value);
|
||||
|
||||
|
||||
if (ret < 0) {
|
||||
IWL_DEBUG_RADIO(mvm, "Failed to get DSM RFI, ret=%d\n", ret);
|
||||
|
||||
} else if (value >= DSM_VALUE_RFI_MAX) {
|
||||
IWL_DEBUG_RADIO(mvm, "DSM RFI got invalid value, ret=%d\n",
|
||||
value);
|
||||
|
||||
} else if (value == DSM_VALUE_RFI_ENABLE) {
|
||||
IWL_DEBUG_RADIO(mvm, "DSM RFI is evaluated to enable\n");
|
||||
return DSM_VALUE_RFI_ENABLE;
|
||||
return bios_enable_rfi;
|
||||
}
|
||||
|
||||
IWL_DEBUG_RADIO(mvm, "DSM RFI is disabled\n");
|
||||
value &= DSM_VALUE_RFI_DISABLE;
|
||||
/* RFI BIOS CONFIG value can be 0 or 3 only.
|
||||
* i.e 0 means DDR and DLVR enabled. 3 means DDR and DLVR disabled.
|
||||
* 1 and 2 are invalid BIOS configurations, So, it's not possible to
|
||||
* disable ddr/dlvr separately.
|
||||
*/
|
||||
if (!value) {
|
||||
IWL_DEBUG_RADIO(mvm, "DSM RFI is evaluated to enable\n");
|
||||
bios_enable_rfi = true;
|
||||
} else if (value == DSM_VALUE_RFI_DISABLE) {
|
||||
IWL_DEBUG_RADIO(mvm, "DSM RFI is evaluated to disable\n");
|
||||
} else {
|
||||
IWL_DEBUG_RADIO(mvm,
|
||||
"DSM RFI got invalid value, value=%d\n", value);
|
||||
}
|
||||
|
||||
/* default behaviour is disabled */
|
||||
return DSM_VALUE_RFI_DISABLE;
|
||||
return bios_enable_rfi;
|
||||
}
|
||||
|
||||
static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_lari_config_change_cmd cmd;
|
||||
size_t cmd_size;
|
||||
int ret;
|
||||
u32 value;
|
||||
struct iwl_lari_config_change_cmd_v6 cmd = {};
|
||||
|
||||
cmd.config_bitmap = iwl_acpi_get_lari_config_bitmap(&mvm->fwrt);
|
||||
|
||||
ret = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0, DSM_FUNC_11AX_ENABLEMENT,
|
||||
&iwl_guid, &value);
|
||||
if (!ret)
|
||||
cmd.oem_11ax_allow_bitmap = cpu_to_le32(value);
|
||||
|
||||
ret = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0,
|
||||
DSM_FUNC_ENABLE_UNII4_CHAN,
|
||||
&iwl_guid, &value);
|
||||
if (!ret)
|
||||
cmd.oem_unii4_allow_bitmap = cpu_to_le32(value);
|
||||
|
||||
ret = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0,
|
||||
DSM_FUNC_ACTIVATE_CHANNEL,
|
||||
&iwl_guid, &value);
|
||||
if (!ret)
|
||||
cmd.chan_state_active_bitmap = cpu_to_le32(value);
|
||||
|
||||
ret = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0,
|
||||
DSM_FUNC_ENABLE_6E,
|
||||
&iwl_guid, &value);
|
||||
if (!ret)
|
||||
cmd.oem_uhb_allow_bitmap = cpu_to_le32(value);
|
||||
|
||||
ret = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0,
|
||||
DSM_FUNC_FORCE_DISABLE_CHANNELS,
|
||||
&iwl_guid, &value);
|
||||
if (!ret)
|
||||
cmd.force_disable_channels_bitmap = cpu_to_le32(value);
|
||||
|
||||
if (cmd.config_bitmap ||
|
||||
cmd.oem_uhb_allow_bitmap ||
|
||||
cmd.oem_11ax_allow_bitmap ||
|
||||
cmd.oem_unii4_allow_bitmap ||
|
||||
cmd.chan_state_active_bitmap ||
|
||||
cmd.force_disable_channels_bitmap) {
|
||||
size_t cmd_size;
|
||||
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
|
||||
WIDE_ID(REGULATORY_AND_NVM_GROUP,
|
||||
LARI_CONFIG_CHANGE),
|
||||
1);
|
||||
switch (cmd_ver) {
|
||||
case 6:
|
||||
cmd_size = sizeof(struct iwl_lari_config_change_cmd_v6);
|
||||
break;
|
||||
case 5:
|
||||
cmd_size = sizeof(struct iwl_lari_config_change_cmd_v5);
|
||||
break;
|
||||
case 4:
|
||||
cmd_size = sizeof(struct iwl_lari_config_change_cmd_v4);
|
||||
break;
|
||||
case 3:
|
||||
cmd_size = sizeof(struct iwl_lari_config_change_cmd_v3);
|
||||
break;
|
||||
case 2:
|
||||
cmd_size = sizeof(struct iwl_lari_config_change_cmd_v2);
|
||||
break;
|
||||
default:
|
||||
cmd_size = sizeof(struct iwl_lari_config_change_cmd_v1);
|
||||
break;
|
||||
}
|
||||
|
||||
IWL_DEBUG_RADIO(mvm,
|
||||
"sending LARI_CONFIG_CHANGE, config_bitmap=0x%x, oem_11ax_allow_bitmap=0x%x\n",
|
||||
le32_to_cpu(cmd.config_bitmap),
|
||||
le32_to_cpu(cmd.oem_11ax_allow_bitmap));
|
||||
IWL_DEBUG_RADIO(mvm,
|
||||
"sending LARI_CONFIG_CHANGE, oem_unii4_allow_bitmap=0x%x, chan_state_active_bitmap=0x%x, cmd_ver=%d\n",
|
||||
le32_to_cpu(cmd.oem_unii4_allow_bitmap),
|
||||
le32_to_cpu(cmd.chan_state_active_bitmap),
|
||||
cmd_ver);
|
||||
IWL_DEBUG_RADIO(mvm,
|
||||
"sending LARI_CONFIG_CHANGE, oem_uhb_allow_bitmap=0x%x, force_disable_channels_bitmap=0x%x\n",
|
||||
le32_to_cpu(cmd.oem_uhb_allow_bitmap),
|
||||
le32_to_cpu(cmd.force_disable_channels_bitmap));
|
||||
ret = iwl_fill_lari_config(&mvm->fwrt, &cmd, &cmd_size);
|
||||
if (!ret) {
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm,
|
||||
WIDE_ID(REGULATORY_AND_NVM_GROUP,
|
||||
LARI_CONFIG_CHANGE),
|
||||
|
|
@ -1298,12 +1218,14 @@ static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
|
|||
}
|
||||
}
|
||||
|
||||
void iwl_mvm_get_acpi_tables(struct iwl_mvm *mvm)
|
||||
void iwl_mvm_get_bios_tables(struct iwl_mvm *mvm)
|
||||
{
|
||||
int ret;
|
||||
|
||||
iwl_acpi_get_guid_lock_status(&mvm->fwrt);
|
||||
|
||||
/* read PPAG table */
|
||||
ret = iwl_acpi_get_ppag_table(&mvm->fwrt);
|
||||
ret = iwl_bios_get_ppag_table(&mvm->fwrt);
|
||||
if (ret < 0) {
|
||||
IWL_DEBUG_RADIO(mvm,
|
||||
"PPAG BIOS table invalid or unavailable. (%d)\n",
|
||||
|
|
@ -1311,7 +1233,7 @@ void iwl_mvm_get_acpi_tables(struct iwl_mvm *mvm)
|
|||
}
|
||||
|
||||
/* read SAR tables */
|
||||
ret = iwl_sar_get_wrds_table(&mvm->fwrt);
|
||||
ret = iwl_bios_get_wrds_table(&mvm->fwrt);
|
||||
if (ret < 0) {
|
||||
IWL_DEBUG_RADIO(mvm,
|
||||
"WRDS SAR BIOS table invalid or unavailable. (%d)\n",
|
||||
|
|
@ -1320,7 +1242,7 @@ void iwl_mvm_get_acpi_tables(struct iwl_mvm *mvm)
|
|||
* If not available, don't fail and don't bother with EWRD and
|
||||
* WGDS */
|
||||
|
||||
if (!iwl_sar_get_wgds_table(&mvm->fwrt)) {
|
||||
if (!iwl_bios_get_wgds_table(&mvm->fwrt)) {
|
||||
/*
|
||||
* If basic SAR is not available, we check for WGDS,
|
||||
* which should *not* be available either. If it is
|
||||
|
|
@ -1331,7 +1253,7 @@ void iwl_mvm_get_acpi_tables(struct iwl_mvm *mvm)
|
|||
}
|
||||
|
||||
} else {
|
||||
ret = iwl_sar_get_ewrd_table(&mvm->fwrt);
|
||||
ret = iwl_bios_get_ewrd_table(&mvm->fwrt);
|
||||
/* if EWRD is not available, we can still use
|
||||
* WRDS, so don't fail */
|
||||
if (ret < 0)
|
||||
|
|
@ -1341,7 +1263,7 @@ void iwl_mvm_get_acpi_tables(struct iwl_mvm *mvm)
|
|||
|
||||
/* read geo SAR table */
|
||||
if (iwl_sar_geo_support(&mvm->fwrt)) {
|
||||
ret = iwl_sar_get_wgds_table(&mvm->fwrt);
|
||||
ret = iwl_bios_get_wgds_table(&mvm->fwrt);
|
||||
if (ret < 0)
|
||||
IWL_DEBUG_RADIO(mvm,
|
||||
"Geo SAR BIOS table invalid or unavailable. (%d)\n",
|
||||
|
|
@ -1351,59 +1273,18 @@ void iwl_mvm_get_acpi_tables(struct iwl_mvm *mvm)
|
|||
}
|
||||
|
||||
iwl_acpi_get_phy_filters(&mvm->fwrt, &mvm->phy_filters);
|
||||
}
|
||||
#else /* CONFIG_ACPI */
|
||||
|
||||
inline int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm,
|
||||
int prof_a, int prof_b)
|
||||
if (iwl_bios_get_eckv(&mvm->fwrt, &mvm->ext_clock_valid))
|
||||
IWL_DEBUG_RADIO(mvm, "ECKV table doesn't exist in BIOS\n");
|
||||
}
|
||||
|
||||
static void iwl_mvm_disconnect_iterator(void *data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
return 1;
|
||||
if (vif->type == NL80211_IFTYPE_STATION)
|
||||
ieee80211_hw_restart_disconnect(vif);
|
||||
}
|
||||
|
||||
inline int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
|
||||
{
|
||||
}
|
||||
|
||||
static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
|
||||
{
|
||||
}
|
||||
|
||||
bool iwl_mvm_is_vendor_in_approved_list(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static u8 iwl_mvm_eval_dsm_rfi(struct iwl_mvm *mvm)
|
||||
{
|
||||
return DSM_VALUE_RFI_DISABLE;
|
||||
}
|
||||
|
||||
void iwl_mvm_get_acpi_tables(struct iwl_mvm *mvm)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags)
|
||||
{
|
||||
u32 error_log_size = mvm->fw->ucode_capa.error_log_size;
|
||||
|
|
@ -1448,10 +1329,15 @@ void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags)
|
|||
/* skb respond is only relevant in ERROR_RECOVERY_UPDATE_DB */
|
||||
if (flags & ERROR_RECOVERY_UPDATE_DB) {
|
||||
resp = le32_to_cpu(*(__le32 *)host_cmd.resp_pkt->data);
|
||||
if (resp)
|
||||
if (resp) {
|
||||
IWL_ERR(mvm,
|
||||
"Failed to send recovery cmd blob was invalid %d\n",
|
||||
resp);
|
||||
|
||||
ieee80211_iterate_interfaces(mvm->hw, 0,
|
||||
iwl_mvm_disconnect_iterator,
|
||||
mvm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1471,9 +1357,6 @@ static int iwl_mvm_load_rt_fw(struct iwl_mvm *mvm)
|
|||
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", ret);
|
||||
|
||||
if (iwlmvm_mod_params.init_dbg)
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1499,10 +1382,7 @@ static int iwl_mvm_load_rt_fw(struct iwl_mvm *mvm)
|
|||
int iwl_mvm_up(struct iwl_mvm *mvm)
|
||||
{
|
||||
int ret, i;
|
||||
struct ieee80211_channel *chan;
|
||||
struct cfg80211_chan_def chandef;
|
||||
struct ieee80211_supported_band *sband = NULL;
|
||||
u32 sb_cfg;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
|
|
@ -1510,23 +1390,19 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
sb_cfg = iwl_read_umac_prph(mvm->trans, SB_MODIFY_CFG_FLAG);
|
||||
mvm->pldr_sync = !(sb_cfg & SB_CFG_RESIDES_IN_OTP_MASK);
|
||||
if (mvm->pldr_sync && iwl_mei_pldr_req())
|
||||
return -EBUSY;
|
||||
|
||||
ret = iwl_mvm_load_rt_fw(mvm);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret);
|
||||
if (ret != -ERFKILL && !mvm->pldr_sync)
|
||||
if (ret != -ERFKILL && !mvm->fw_product_reset)
|
||||
iwl_fw_dbg_error_collect(&mvm->fwrt,
|
||||
FW_DBG_TRIGGER_DRIVER);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* FW loaded successfully */
|
||||
mvm->pldr_sync = false;
|
||||
mvm->fw_product_reset = false;
|
||||
|
||||
iwl_fw_disable_dbg_asserts(&mvm->fwrt);
|
||||
iwl_get_shared_mem_conf(&mvm->fwrt);
|
||||
|
||||
ret = iwl_mvm_sf_update(mvm, NULL, false);
|
||||
|
|
@ -1591,8 +1467,6 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
|||
for (i = 0; i < IWL_MVM_FW_MAX_LINK_ID + 1; i++)
|
||||
RCU_INIT_POINTER(mvm->link_id_to_link_conf[i], NULL);
|
||||
|
||||
memset(&mvm->fw_link_ids_map, 0, sizeof(mvm->fw_link_ids_map));
|
||||
|
||||
mvm->tdls_cs.peer.sta_id = IWL_MVM_INVALID_STA;
|
||||
|
||||
/* reset quota debouncing buffer - 0xff will yield invalid data */
|
||||
|
|
@ -1630,21 +1504,6 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
|||
goto error;
|
||||
}
|
||||
|
||||
chan = &sband->channels[0];
|
||||
|
||||
cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
|
||||
for (i = 0; i < NUM_PHY_CTX; i++) {
|
||||
/*
|
||||
* The channel used here isn't relevant as it's
|
||||
* going to be overwritten in the other flows.
|
||||
* For now use the first channel we have.
|
||||
*/
|
||||
ret = iwl_mvm_phy_ctxt_add(mvm, &mvm->phy_ctxts[i],
|
||||
&chandef, 1, 1);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (iwl_mvm_is_tt_in_fw(mvm)) {
|
||||
/* in order to give the responsibility of ct-kill and
|
||||
* TX backoff to FW we need to send empty temperature reporting
|
||||
|
|
@ -1708,9 +1567,6 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
|||
if (!mvm->ptp_data.ptp_clock)
|
||||
iwl_mvm_ptp_init(mvm);
|
||||
|
||||
if (iwl_acpi_get_eckv(mvm->dev, &mvm->ext_clock_valid))
|
||||
IWL_DEBUG_INFO(mvm, "ECKV table doesn't exist in BIOS\n");
|
||||
|
||||
ret = iwl_mvm_ppag_init(mvm);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
|
@ -1727,9 +1583,10 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
|||
|
||||
iwl_mvm_tas_init(mvm);
|
||||
iwl_mvm_leds_sync(mvm);
|
||||
iwl_mvm_uats_init(mvm);
|
||||
|
||||
if (iwl_rfi_supported(mvm)) {
|
||||
if (iwl_mvm_eval_dsm_rfi(mvm) == DSM_VALUE_RFI_ENABLE)
|
||||
if (iwl_mvm_eval_dsm_rfi(mvm))
|
||||
iwl_rfi_send_config_cmd(mvm, NULL);
|
||||
}
|
||||
|
||||
|
|
@ -1738,8 +1595,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
|||
IWL_DEBUG_INFO(mvm, "RT uCode started.\n");
|
||||
return 0;
|
||||
error:
|
||||
if (!iwlmvm_mod_params.init_dbg || !ret)
|
||||
iwl_mvm_stop_device(mvm);
|
||||
iwl_mvm_stop_device(mvm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -31,6 +31,17 @@ const u8 iwl_mvm_ac_to_gen2_tx_fifo[] = {
|
|||
IWL_GEN2_TRIG_TX_FIFO_BK,
|
||||
};
|
||||
|
||||
const u8 iwl_mvm_ac_to_bz_tx_fifo[] = {
|
||||
IWL_BZ_EDCA_TX_FIFO_VO,
|
||||
IWL_BZ_EDCA_TX_FIFO_VI,
|
||||
IWL_BZ_EDCA_TX_FIFO_BE,
|
||||
IWL_BZ_EDCA_TX_FIFO_BK,
|
||||
IWL_BZ_TRIG_TX_FIFO_VO,
|
||||
IWL_BZ_TRIG_TX_FIFO_VI,
|
||||
IWL_BZ_TRIG_TX_FIFO_BE,
|
||||
IWL_BZ_TRIG_TX_FIFO_BK,
|
||||
};
|
||||
|
||||
struct iwl_mvm_mac_iface_iterator_data {
|
||||
struct iwl_mvm *mvm;
|
||||
struct ieee80211_vif *vif;
|
||||
|
|
@ -285,6 +296,11 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
|
||||
INIT_LIST_HEAD(&mvmvif->time_event_data.list);
|
||||
mvmvif->time_event_data.id = TE_MAX;
|
||||
mvmvif->roc_activity = ROC_NUM_ACTIVITIES;
|
||||
|
||||
mvmvif->deflink.bcast_sta.sta_id = IWL_MVM_INVALID_STA;
|
||||
mvmvif->deflink.mcast_sta.sta_id = IWL_MVM_INVALID_STA;
|
||||
mvmvif->deflink.ap_sta_id = IWL_MVM_INVALID_STA;
|
||||
|
||||
/* No need to allocate data queues to P2P Device MAC and NAN.*/
|
||||
if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
|
||||
|
|
@ -300,10 +316,6 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
mvmvif->deflink.cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
|
||||
}
|
||||
|
||||
mvmvif->deflink.bcast_sta.sta_id = IWL_MVM_INVALID_STA;
|
||||
mvmvif->deflink.mcast_sta.sta_id = IWL_MVM_INVALID_STA;
|
||||
mvmvif->deflink.ap_sta_id = IWL_MVM_INVALID_STA;
|
||||
|
||||
for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++)
|
||||
mvmvif->deflink.smps_requests[i] = IEEE80211_SMPS_AUTOMATIC;
|
||||
|
||||
|
|
@ -455,7 +467,7 @@ void iwl_mvm_set_fw_protection_flags(struct iwl_mvm *mvm,
|
|||
break;
|
||||
case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
|
||||
/* Protect when channel wider than 20MHz */
|
||||
if (link_conf->chandef.width > NL80211_CHAN_WIDTH_20)
|
||||
if (link_conf->chanreq.oper.width > NL80211_CHAN_WIDTH_20)
|
||||
*protection_flags |= cpu_to_le32(ht_flag);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -494,7 +506,7 @@ void iwl_mvm_set_fw_qos_params(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
if (link_conf->qos)
|
||||
*qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA);
|
||||
|
||||
if (link_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT)
|
||||
if (link_conf->chanreq.oper.width != NL80211_CHAN_WIDTH_20_NOHT)
|
||||
*qos_flags |= cpu_to_le32(MAC_QOS_FLG_TGN);
|
||||
}
|
||||
|
||||
|
|
@ -862,7 +874,7 @@ void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm,
|
|||
}
|
||||
}
|
||||
|
||||
static u32 iwl_mvm_find_ie_offset(u8 *beacon, u8 eid, u32 frame_size)
|
||||
u32 iwl_mvm_find_ie_offset(u8 *beacon, u8 eid, u32 frame_size)
|
||||
{
|
||||
struct ieee80211_mgmt *mgmt = (void *)beacon;
|
||||
const u8 *ie;
|
||||
|
|
@ -910,8 +922,8 @@ u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct iwl_mvm *mvm,
|
|||
link_conf = rcu_dereference(vif->link_conf[link_id]);
|
||||
if (link_conf) {
|
||||
basic = link_conf->basic_rates;
|
||||
if (link_conf->chandef.chan)
|
||||
band = link_conf->chandef.chan->band;
|
||||
if (link_conf->chanreq.oper.chan)
|
||||
band = link_conf->chanreq.oper.chan->band;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
|
@ -999,12 +1011,13 @@ static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
|
|||
tx->tx_flags = cpu_to_le32(tx_flags);
|
||||
|
||||
if (!fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION))
|
||||
IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION)) {
|
||||
iwl_mvm_toggle_tx_ant(mvm, &mvm->mgmt_last_antenna_idx);
|
||||
|
||||
tx->rate_n_flags =
|
||||
cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) <<
|
||||
RATE_MCS_ANT_POS);
|
||||
tx->rate_n_flags =
|
||||
cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) <<
|
||||
RATE_MCS_ANT_POS);
|
||||
}
|
||||
|
||||
rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif);
|
||||
|
||||
|
|
@ -1083,6 +1096,19 @@ static int iwl_mvm_mac_ctxt_send_beacon_v7(struct iwl_mvm *mvm,
|
|||
sizeof(beacon_cmd));
|
||||
}
|
||||
|
||||
bool iwl_mvm_enable_fils(struct iwl_mvm *mvm,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
if (IWL_MVM_DISABLE_AP_FILS)
|
||||
return false;
|
||||
|
||||
if (cfg80211_channel_is_psc(ctx->def.chan))
|
||||
return true;
|
||||
|
||||
return (ctx->def.chan->band == NL80211_BAND_6GHZ &&
|
||||
ctx->def.width >= NL80211_CHAN_WIDTH_80);
|
||||
}
|
||||
|
||||
static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct sk_buff *beacon,
|
||||
|
|
@ -1102,8 +1128,7 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
|
|||
ctx = rcu_dereference(link_conf->chanctx_conf);
|
||||
channel = ieee80211_frequency_to_channel(ctx->def.chan->center_freq);
|
||||
WARN_ON(channel == 0);
|
||||
if (cfg80211_channel_is_psc(ctx->def.chan) &&
|
||||
!IWL_MVM_DISABLE_AP_FILS) {
|
||||
if (iwl_mvm_enable_fils(mvm, ctx)) {
|
||||
flags |= iwl_fw_lookup_cmd_ver(mvm->fw, BEACON_TEMPLATE_CMD,
|
||||
0) > 10 ?
|
||||
IWL_MAC_BEACON_FILS :
|
||||
|
|
@ -1140,6 +1165,13 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
|
|||
WLAN_EID_EXT_CHANSWITCH_ANN,
|
||||
beacon->len));
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP &&
|
||||
iwl_fw_lookup_cmd_ver(mvm->fw, BEACON_TEMPLATE_CMD, 0) >= 14)
|
||||
beacon_cmd.btwt_offset =
|
||||
cpu_to_le32(iwl_mvm_find_ie_offset(beacon->data,
|
||||
WLAN_EID_S1G_TWT,
|
||||
beacon->len));
|
||||
|
||||
return iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
|
||||
sizeof(beacon_cmd));
|
||||
}
|
||||
|
|
@ -1454,8 +1486,8 @@ static void iwl_mvm_csa_count_down(struct iwl_mvm *mvm,
|
|||
|
||||
mvmvif->csa_countdown = true;
|
||||
|
||||
if (!ieee80211_beacon_cntdwn_is_complete(csa_vif)) {
|
||||
int c = ieee80211_beacon_update_cntdwn(csa_vif);
|
||||
if (!ieee80211_beacon_cntdwn_is_complete(csa_vif, 0)) {
|
||||
int c = ieee80211_beacon_update_cntdwn(csa_vif, 0);
|
||||
|
||||
iwl_mvm_mac_ctxt_beacon_changed(mvm, csa_vif,
|
||||
&csa_vif->bss_conf);
|
||||
|
|
@ -1474,7 +1506,7 @@ static void iwl_mvm_csa_count_down(struct iwl_mvm *mvm,
|
|||
}
|
||||
} else if (!iwl_mvm_te_scheduled(&mvmvif->time_event_data)) {
|
||||
/* we don't have CSA NoA scheduled yet, switch now */
|
||||
ieee80211_csa_finish(csa_vif);
|
||||
ieee80211_csa_finish(csa_vif, 0);
|
||||
RCU_INIT_POINTER(mvm->csa_vif, NULL);
|
||||
}
|
||||
}
|
||||
|
|
@ -1568,23 +1600,23 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
|
|||
u32 id = le32_to_cpu(mb->link_id);
|
||||
union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt };
|
||||
u32 mac_type;
|
||||
int link_id = -1;
|
||||
u8 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
|
||||
MISSED_BEACONS_NOTIFICATION,
|
||||
0);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
/* before version four the ID in the notification refers to mac ID */
|
||||
if (notif_ver < 4) {
|
||||
vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true);
|
||||
vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false);
|
||||
} else {
|
||||
struct ieee80211_bss_conf *bss_conf =
|
||||
iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, id, true);
|
||||
iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, id, false);
|
||||
|
||||
if (!bss_conf)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
vif = bss_conf->vif;
|
||||
link_id = bss_conf->link_id;
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(mvm,
|
||||
|
|
@ -1597,7 +1629,7 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
|
|||
le32_to_cpu(mb->num_expected_beacons));
|
||||
|
||||
if (!vif)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
mac_type = iwl_mvm_get_mac_type(vif);
|
||||
|
||||
|
|
@ -1614,10 +1646,26 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
|
|||
* TODO: the threshold should be adjusted based on latency conditions,
|
||||
* and/or in case of a CS flow on one of the other AP vifs.
|
||||
*/
|
||||
if (rx_missed_bcon > IWL_MVM_MISSED_BEACONS_THRESHOLD_LONG)
|
||||
iwl_mvm_connection_loss(mvm, vif, "missed beacons");
|
||||
else if (rx_missed_bcon_since_rx > IWL_MVM_MISSED_BEACONS_THRESHOLD)
|
||||
ieee80211_beacon_loss(vif);
|
||||
if (rx_missed_bcon >= IWL_MVM_MISSED_BEACONS_THRESHOLD_LONG) {
|
||||
if (rx_missed_bcon_since_rx >= IWL_MVM_MISSED_BEACONS_SINCE_RX_THOLD) {
|
||||
iwl_mvm_connection_loss(mvm, vif, "missed beacons");
|
||||
} else {
|
||||
IWL_WARN(mvm,
|
||||
"missed beacons exceeds threshold, but receiving data. Stay connected, Expect bugs.\n");
|
||||
IWL_WARN(mvm,
|
||||
"missed_beacons:%d, missed_beacons_since_rx:%d\n",
|
||||
rx_missed_bcon, rx_missed_bcon_since_rx);
|
||||
}
|
||||
} else if (rx_missed_bcon >= IWL_MVM_MISSED_BEACONS_EXIT_ESR_THRESH &&
|
||||
link_id >= 0 && hweight16(vif->active_links) > 1) {
|
||||
iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_MISSED_BEACON,
|
||||
iwl_mvm_get_other_link(vif, link_id));
|
||||
} else if (rx_missed_bcon_since_rx > IWL_MVM_MISSED_BEACONS_THRESHOLD) {
|
||||
if (!iwl_mvm_has_new_tx_api(mvm))
|
||||
ieee80211_beacon_loss(vif);
|
||||
else
|
||||
ieee80211_cqm_beacon_loss_notify(vif, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
iwl_dbg_tlv_time_point(&mvm->fwrt,
|
||||
IWL_FW_INI_TIME_POINT_MISSED_BEACONS, &tp_data);
|
||||
|
|
@ -1625,7 +1673,7 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
|
|||
trigger = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif),
|
||||
FW_DBG_TRIGGER_MISSED_BEACONS);
|
||||
if (!trigger)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
bcon_trig = (void *)trigger->data;
|
||||
stop_trig_missed_bcon = le32_to_cpu(bcon_trig->stop_consec_missed_bcon);
|
||||
|
|
@ -1641,9 +1689,6 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
|
|||
#elif defined(__FreeBSD__)
|
||||
iwl_fw_dbg_collect_trig(&mvm->fwrt, trigger, "");
|
||||
#endif
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm,
|
||||
|
|
@ -1765,6 +1810,7 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm,
|
|||
u32 id_n_color, csa_id;
|
||||
/* save mac_id or link_id to use later to cancel csa if needed */
|
||||
u32 id;
|
||||
u32 mac_link_id = 0;
|
||||
u8 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP,
|
||||
CHANNEL_SWITCH_START_NOTIF, 0);
|
||||
bool csa_active;
|
||||
|
|
@ -1794,6 +1840,7 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm,
|
|||
goto out_unlock;
|
||||
|
||||
id = link_id;
|
||||
mac_link_id = bss_conf->link_id;
|
||||
vif = bss_conf->vif;
|
||||
csa_active = bss_conf->csa_active;
|
||||
}
|
||||
|
|
@ -1822,7 +1869,7 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm,
|
|||
msecs_to_jiffies(IWL_MVM_CS_UNBLOCK_TX_TIMEOUT *
|
||||
csa_vif->bss_conf.beacon_int));
|
||||
|
||||
ieee80211_csa_finish(csa_vif);
|
||||
ieee80211_csa_finish(csa_vif, 0);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
|
|
@ -1843,7 +1890,7 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm,
|
|||
|
||||
iwl_mvm_csa_client_absent(mvm, vif);
|
||||
cancel_delayed_work(&mvmvif->csa_work);
|
||||
ieee80211_chswitch_done(vif, true);
|
||||
ieee80211_chswitch_done(vif, true, mac_link_id);
|
||||
break;
|
||||
default:
|
||||
/* should never happen */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2022 - 2023 Intel Corporation
|
||||
* Copyright (C) 2022 - 2024 Intel Corporation
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <net/mac80211.h>
|
||||
|
|
@ -24,10 +24,15 @@ static u32 iwl_mvm_get_sec_sta_mask(struct iwl_mvm *mvm,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* AP group keys are per link and should be on the mcast STA */
|
||||
/* AP group keys are per link and should be on the mcast/bcast STA */
|
||||
if (vif->type == NL80211_IFTYPE_AP &&
|
||||
!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
|
||||
!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
|
||||
/* IGTK/BIGTK to bcast STA */
|
||||
if (keyconf->keyidx >= 4)
|
||||
return BIT(link_info->bcast_sta.sta_id);
|
||||
/* GTK for data to mcast STA */
|
||||
return BIT(link_info->mcast_sta.sta_id);
|
||||
}
|
||||
|
||||
/* for client mode use the AP STA also for group keys */
|
||||
if (!sta && vif->type == NL80211_IFTYPE_STATION)
|
||||
|
|
@ -57,11 +62,13 @@ u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm,
|
|||
struct ieee80211_key_conf *keyconf)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
bool pairwise = keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE;
|
||||
bool igtk = keyconf->keyidx == 4 || keyconf->keyidx == 5;
|
||||
u32 flags = 0;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
|
||||
if (!pairwise)
|
||||
flags |= IWL_SEC_KEY_FLAG_MCAST_KEY;
|
||||
|
||||
switch (keyconf->cipher) {
|
||||
|
|
@ -91,9 +98,19 @@ u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm,
|
|||
if (!sta && vif->type == NL80211_IFTYPE_STATION)
|
||||
sta = mvmvif->ap_sta;
|
||||
|
||||
if (!IS_ERR_OR_NULL(sta) && sta->mfp)
|
||||
/*
|
||||
* If we are installing an iGTK (in AP or STA mode), we need to tell
|
||||
* the firmware this key will en/decrypt MGMT frames.
|
||||
* Same goes if we are installing a pairwise key for an MFP station.
|
||||
* In case we're installing a groupwise key (which is not an iGTK),
|
||||
* then, we will not use this key for MGMT frames.
|
||||
*/
|
||||
if ((!IS_ERR_OR_NULL(sta) && sta->mfp && pairwise) || igtk)
|
||||
flags |= IWL_SEC_KEY_FLAG_MFP;
|
||||
|
||||
if (keyconf->flags & IEEE80211_KEY_FLAG_SPP_AMSDU)
|
||||
flags |= IWL_SEC_KEY_FLAG_SPP_AMSDU;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
|
@ -325,6 +342,21 @@ static int _iwl_mvm_sec_key_del(struct iwl_mvm *mvm,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int iwl_mvm_sec_key_del_pasn(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 sta_mask,
|
||||
struct ieee80211_key_conf *keyconf)
|
||||
{
|
||||
u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, NULL, keyconf) |
|
||||
IWL_SEC_KEY_FLAG_MFP;
|
||||
|
||||
if (WARN_ON(!sta_mask))
|
||||
return -EINVAL;
|
||||
|
||||
return __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, keyconf->keyidx,
|
||||
0);
|
||||
}
|
||||
|
||||
int iwl_mvm_sec_key_del(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2022 - 2023 Intel Corporation
|
||||
* Copyright (C) 2022 - 2024 Intel Corporation
|
||||
*/
|
||||
#include "mvm.h"
|
||||
|
||||
|
|
@ -167,7 +167,7 @@ static int iwl_mvm_mld_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
|
|||
iwl_mvm_mld_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
|
||||
|
||||
cmd.filter_flags = cpu_to_le32(MAC_CFG_FILTER_PROMISC |
|
||||
MAC_FILTER_IN_CONTROL_AND_MGMT |
|
||||
MAC_CFG_FILTER_ACCEPT_CONTROL_AND_MGMT |
|
||||
MAC_CFG_FILTER_ACCEPT_BEACON |
|
||||
MAC_CFG_FILTER_ACCEPT_PROBE_REQ |
|
||||
MAC_CFG_FILTER_ACCEPT_GRP);
|
||||
|
|
@ -205,8 +205,11 @@ static int iwl_mvm_mld_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm,
|
|||
cmd.p2p_dev.is_disc_extended =
|
||||
iwl_mac_ctxt_p2p_dev_has_extended_disc(mvm, vif);
|
||||
|
||||
/* Override the filter flags to accept only probe requests */
|
||||
cmd.filter_flags = cpu_to_le32(MAC_CFG_FILTER_ACCEPT_PROBE_REQ);
|
||||
/* Override the filter flags to accept all management frames. This is
|
||||
* needed to support both P2P device discovery using probe requests and
|
||||
* P2P service discovery using action frames
|
||||
*/
|
||||
cmd.filter_flags = cpu_to_le32(MAC_CFG_FILTER_ACCEPT_CONTROL_AND_MGMT);
|
||||
|
||||
return iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2022-2023 Intel Corporation
|
||||
* Copyright (C) 2022-2024 Intel Corporation
|
||||
*/
|
||||
#include "mvm.h"
|
||||
#include "time-sync.h"
|
||||
|
|
@ -9,7 +9,9 @@
|
|||
u32 iwl_mvm_sta_fw_id_mask(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
int filter_link_id)
|
||||
{
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
struct ieee80211_vif *vif;
|
||||
unsigned int link_id;
|
||||
u32 result = 0;
|
||||
|
||||
|
|
@ -17,26 +19,27 @@ u32 iwl_mvm_sta_fw_id_mask(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|||
return 0;
|
||||
|
||||
mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
vif = mvmsta->vif;
|
||||
|
||||
/* it's easy when the STA is not an MLD */
|
||||
if (!sta->valid_links)
|
||||
return BIT(mvmsta->deflink.sta_id);
|
||||
|
||||
/* but if it is an MLD, get the mask of all the FW STAs it has ... */
|
||||
for (link_id = 0; link_id < ARRAY_SIZE(mvmsta->link); link_id++) {
|
||||
struct iwl_mvm_link_sta *link_sta;
|
||||
for_each_sta_active_link(vif, sta, link_sta, link_id) {
|
||||
struct iwl_mvm_link_sta *mvm_link_sta;
|
||||
|
||||
/* unless we have a specific link in mind */
|
||||
if (filter_link_id >= 0 && link_id != filter_link_id)
|
||||
continue;
|
||||
|
||||
link_sta =
|
||||
mvm_link_sta =
|
||||
rcu_dereference_check(mvmsta->link[link_id],
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
if (!link_sta)
|
||||
if (!mvm_link_sta)
|
||||
continue;
|
||||
|
||||
result |= BIT(link_sta->sta_id);
|
||||
result |= BIT(mvm_link_sta->sta_id);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
@ -238,7 +241,7 @@ int iwl_mvm_mld_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
IWL_MAX_TID_COUNT, &wdg_timeout);
|
||||
}
|
||||
|
||||
/* Allocate a new station entry for the broadcast station to the given vif,
|
||||
/* Allocate a new station entry for the multicast station to the given vif,
|
||||
* and send it to the FW.
|
||||
* Note that each AP/GO mac should have its own multicast station.
|
||||
*/
|
||||
|
|
@ -347,7 +350,7 @@ static int iwl_mvm_mld_rm_int_sta(struct iwl_mvm *mvm,
|
|||
return -EINVAL;
|
||||
|
||||
if (flush)
|
||||
iwl_mvm_flush_sta(mvm, int_sta, true);
|
||||
iwl_mvm_flush_sta(mvm, int_sta->sta_id, int_sta->tfd_queue_msk);
|
||||
|
||||
iwl_mvm_mld_disable_txq(mvm, BIT(int_sta->sta_id), queuptr, tid);
|
||||
|
||||
|
|
@ -467,7 +470,7 @@ static int iwl_mvm_mld_cfg_sta(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|||
break;
|
||||
}
|
||||
|
||||
switch (sta->deflink.smps_mode) {
|
||||
switch (link_sta->smps_mode) {
|
||||
case IEEE80211_SMPS_AUTOMATIC:
|
||||
case IEEE80211_SMPS_NUM_MODES:
|
||||
WARN_ON(1);
|
||||
|
|
@ -512,11 +515,11 @@ static int iwl_mvm_mld_cfg_sta(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|||
return iwl_mvm_mld_send_sta_cmd(mvm, &cmd);
|
||||
}
|
||||
|
||||
static void iwl_mvm_mld_free_sta_link(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_sta *mvm_sta,
|
||||
struct iwl_mvm_link_sta *mvm_sta_link,
|
||||
unsigned int link_id,
|
||||
bool is_in_fw)
|
||||
void iwl_mvm_mld_free_sta_link(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_sta *mvm_sta,
|
||||
struct iwl_mvm_link_sta *mvm_sta_link,
|
||||
unsigned int link_id,
|
||||
bool is_in_fw)
|
||||
{
|
||||
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[mvm_sta_link->sta_id],
|
||||
is_in_fw ? ERR_PTR(-EINVAL) : NULL);
|
||||
|
|
@ -582,14 +585,14 @@ static int iwl_mvm_mld_alloc_sta_links(struct iwl_mvm *mvm,
|
|||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
unsigned int link_id;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
for (link_id = 0; link_id < ARRAY_SIZE(sta->link); link_id++) {
|
||||
if (!rcu_access_pointer(sta->link[link_id]) ||
|
||||
mvm_sta->link[link_id])
|
||||
for_each_sta_active_link(vif, sta, link_sta, link_id) {
|
||||
if (WARN_ON(mvm_sta->link[link_id]))
|
||||
continue;
|
||||
|
||||
ret = iwl_mvm_mld_alloc_sta_link(mvm, vif, sta, link_id);
|
||||
|
|
@ -616,9 +619,6 @@ static void iwl_mvm_mld_set_ap_sta_id(struct ieee80211_sta *sta,
|
|||
}
|
||||
}
|
||||
|
||||
/* FIXME: consider waiting for mac80211 to add the STA instead of allocating
|
||||
* queues here
|
||||
*/
|
||||
static int iwl_mvm_alloc_sta_after_restart(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
|
|
@ -697,6 +697,8 @@ int iwl_mvm_mld_add_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
|
||||
/* at this stage sta link pointers are already allocated */
|
||||
ret = iwl_mvm_mld_update_sta(mvm, vif, sta);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
for_each_sta_active_link(vif, sta, link_sta, link_id) {
|
||||
struct ieee80211_bss_conf *link_conf =
|
||||
|
|
@ -705,8 +707,10 @@ int iwl_mvm_mld_add_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
rcu_dereference_protected(mvm_sta->link[link_id],
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
|
||||
if (WARN_ON(!link_conf || !mvm_link_sta))
|
||||
if (WARN_ON(!link_conf || !mvm_link_sta)) {
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_mld_cfg_sta(mvm, sta, vif, link_sta, link_conf,
|
||||
mvm_link_sta);
|
||||
|
|
@ -719,7 +723,6 @@ int iwl_mvm_mld_add_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
iwl_mvm_mld_set_ap_sta_id(sta, mvm_vif->link[link_id],
|
||||
mvm_link_sta);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
|
|
@ -845,16 +848,23 @@ int iwl_mvm_mld_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
iwl_mvm_mld_free_sta_link(mvm, mvm_sta, mvm_link_sta,
|
||||
link_id, stay_in_fw);
|
||||
}
|
||||
kfree(mvm_sta->mpdu_counters);
|
||||
mvm_sta->mpdu_counters = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_mvm_mld_rm_sta_id(struct iwl_mvm *mvm, u8 sta_id)
|
||||
{
|
||||
int ret = iwl_mvm_mld_rm_sta_from_fw(mvm, sta_id);
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (WARN_ON(sta_id == IWL_MVM_INVALID_STA))
|
||||
return 0;
|
||||
|
||||
ret = iwl_mvm_mld_rm_sta_from_fw(mvm, sta_id);
|
||||
|
||||
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta_id], NULL);
|
||||
RCU_INIT_POINTER(mvm->fw_id_to_link_sta[sta_id], NULL);
|
||||
return ret;
|
||||
|
|
@ -870,6 +880,9 @@ void iwl_mvm_mld_sta_modify_disable_tx(struct iwl_mvm *mvm,
|
|||
cmd.sta_id = cpu_to_le32(mvmsta->deflink.sta_id);
|
||||
cmd.disable = cpu_to_le32(disable);
|
||||
|
||||
if (WARN_ON(iwl_mvm_has_no_host_disable_tx(mvm)))
|
||||
return;
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm,
|
||||
WIDE_ID(MAC_CONF_GROUP, STA_DISABLE_TX_CMD),
|
||||
CMD_ASYNC, sizeof(cmd), &cmd);
|
||||
|
|
@ -977,6 +990,10 @@ static int iwl_mvm_mld_update_sta_baids(struct iwl_mvm *mvm,
|
|||
u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, RX_BAID_ALLOCATION_CONFIG_CMD);
|
||||
int baid;
|
||||
|
||||
/* mac80211 will remove sessions later, but we ignore all that */
|
||||
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
|
||||
return 0;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct iwl_rx_baid_cfg_resp) != sizeof(baid));
|
||||
|
||||
for (baid = 0; baid < ARRAY_SIZE(mvm->baid_map); baid++) {
|
||||
|
|
@ -997,7 +1014,8 @@ static int iwl_mvm_mld_update_sta_baids(struct iwl_mvm *mvm,
|
|||
|
||||
cmd.modify.tid = cpu_to_le32(data->tid);
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd);
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, CMD_SEND_IN_RFKILL,
|
||||
sizeof(cmd), &cmd);
|
||||
data->sta_mask = new_sta_mask;
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -1104,15 +1122,37 @@ int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm,
|
|||
link_sta_dereference_protected(sta, link_id);
|
||||
mvm_vif_link = mvm_vif->link[link_id];
|
||||
|
||||
if (WARN_ON(!mvm_vif_link || !link_conf || !link_sta ||
|
||||
mvm_sta->link[link_id])) {
|
||||
if (WARN_ON(!mvm_vif_link || !link_conf || !link_sta)) {
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_mld_alloc_sta_link(mvm, vif, sta, link_id);
|
||||
if (WARN_ON(ret))
|
||||
goto err;
|
||||
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
|
||||
struct iwl_mvm_link_sta *mvm_link_sta =
|
||||
rcu_dereference_protected(mvm_sta->link[link_id],
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
u32 sta_id;
|
||||
|
||||
if (WARN_ON(!mvm_link_sta)) {
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
sta_id = mvm_link_sta->sta_id;
|
||||
|
||||
rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id], sta);
|
||||
rcu_assign_pointer(mvm->fw_id_to_link_sta[sta_id],
|
||||
link_sta);
|
||||
} else {
|
||||
if (WARN_ON(mvm_sta->link[link_id])) {
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
ret = iwl_mvm_mld_alloc_sta_link(mvm, vif, sta,
|
||||
link_id);
|
||||
if (WARN_ON(ret))
|
||||
goto err;
|
||||
}
|
||||
|
||||
link_sta->agg.max_rc_amsdu_len = 1;
|
||||
ieee80211_sta_recalc_aggregates(sta);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2019, 2021 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2019, 2021-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -11,8 +11,7 @@
|
|||
#include "iwl-trans.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "mvm.h"
|
||||
#include "iwl-eeprom-parse.h"
|
||||
#include "iwl-eeprom-read.h"
|
||||
#include "iwl-nvm-utils.h"
|
||||
#include "iwl-nvm-parse.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "fw/acpi.h"
|
||||
|
|
@ -222,6 +221,8 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
|
|||
struct iwl_nvm_section *sections = mvm->nvm_sections;
|
||||
const __be16 *hw;
|
||||
const __le16 *sw, *calib, *regulatory, *mac_override, *phy_sku;
|
||||
u8 tx_ant = mvm->fw->valid_tx_ant;
|
||||
u8 rx_ant = mvm->fw->valid_rx_ant;
|
||||
int regulatory_type;
|
||||
|
||||
/* Checking for required sections */
|
||||
|
|
@ -272,9 +273,15 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
|
|||
(const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY_SDP].data :
|
||||
(const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY].data;
|
||||
|
||||
if (mvm->set_tx_ant)
|
||||
tx_ant &= mvm->set_tx_ant;
|
||||
|
||||
if (mvm->set_rx_ant)
|
||||
rx_ant &= mvm->set_rx_ant;
|
||||
|
||||
return iwl_parse_nvm_data(mvm->trans, mvm->cfg, mvm->fw, hw, sw, calib,
|
||||
regulatory, mac_override, phy_sku,
|
||||
mvm->fw->valid_tx_ant, mvm->fw->valid_rx_ant);
|
||||
tx_ant, rx_ant);
|
||||
}
|
||||
|
||||
/* Loads the NVM data stored in mvm->nvm_sections into the NIC */
|
||||
|
|
@ -567,7 +574,7 @@ int iwl_mvm_init_mcc(struct iwl_mvm *mvm)
|
|||
* try to replay the last set MCC to FW. If it doesn't exist,
|
||||
* queue an update to cfg80211 to retrieve the default alpha2 from FW.
|
||||
*/
|
||||
retval = iwl_mvm_init_fw_regd(mvm);
|
||||
retval = iwl_mvm_init_fw_regd(mvm, true);
|
||||
if (retval != -ENOENT)
|
||||
return retval;
|
||||
|
||||
|
|
@ -584,7 +591,7 @@ int iwl_mvm_init_mcc(struct iwl_mvm *mvm)
|
|||
return -EIO;
|
||||
|
||||
if (iwl_mvm_is_wifi_mcc_supported(mvm) &&
|
||||
!iwl_acpi_get_mcc(mvm->dev, mcc)) {
|
||||
!iwl_bios_get_mcc(&mvm->fwrt, mcc)) {
|
||||
kfree(regd);
|
||||
regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, mcc,
|
||||
MCC_SOURCE_BIOS, NULL);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2021-2022 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2021-2022, 2024 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -30,7 +30,8 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
|
|||
struct ieee80211_vif *vif,
|
||||
bool disable_offloading,
|
||||
bool offload_ns,
|
||||
u32 cmd_flags)
|
||||
u32 cmd_flags,
|
||||
u8 sta_id)
|
||||
{
|
||||
union {
|
||||
struct iwl_proto_offload_cmd_v1 v1;
|
||||
|
|
@ -205,6 +206,9 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
|
|||
if (!disable_offloading)
|
||||
common->enabled = cpu_to_le32(enabled);
|
||||
|
||||
if (ver >= 4)
|
||||
cmd.v4.sta_id = cpu_to_le32(sta_id);
|
||||
|
||||
hcmd.len[0] = size;
|
||||
return iwl_mvm_send_cmd(mvm, &hcmd);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
#include "iwl-modparams.h"
|
||||
#include "mvm.h"
|
||||
#include "iwl-phy-db.h"
|
||||
#include "iwl-eeprom-parse.h"
|
||||
#include "iwl-nvm-utils.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-prph.h"
|
||||
|
|
@ -36,29 +36,26 @@
|
|||
|
||||
#if defined(__linux__)
|
||||
#define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux"
|
||||
MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
||||
MODULE_LICENSE("GPL");
|
||||
#elif defined(__FreeBSD__)
|
||||
#define DRV_DESCRIPTION "The new Intel(R) wireless AGN/AC/AX based driver for FreeBSD"
|
||||
MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
||||
MODULE_LICENSE("BSD");
|
||||
#endif
|
||||
MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
||||
MODULE_IMPORT_NS(IWLWIFI);
|
||||
|
||||
static const struct iwl_op_mode_ops iwl_mvm_ops;
|
||||
static const struct iwl_op_mode_ops iwl_mvm_ops_mq;
|
||||
|
||||
struct iwl_mvm_mod_params iwlmvm_mod_params = {
|
||||
#if defined(__FreeBSD__)
|
||||
.power_scheme = IWL_POWER_SCHEME_CAM, /* disable default PS */
|
||||
#else
|
||||
#if defined(__linux__)
|
||||
.power_scheme = IWL_POWER_SCHEME_BPS,
|
||||
#elif defined(__FreeBSD__)
|
||||
.power_scheme = IWL_POWER_SCHEME_CAM, /* disable default PS */
|
||||
#endif
|
||||
/* rest of fields are 0 by default */
|
||||
};
|
||||
|
||||
module_param_named(init_dbg, iwlmvm_mod_params.init_dbg, bool, 0444);
|
||||
MODULE_PARM_DESC(init_dbg,
|
||||
"set to true to debug an ASSERT in INIT fw (default: false");
|
||||
module_param_named(power_scheme, iwlmvm_mod_params.power_scheme, int, 0444);
|
||||
MODULE_PARM_DESC(power_scheme,
|
||||
"power management scheme: 1-active, 2-balanced, 3-low power, default: 2");
|
||||
|
|
@ -161,6 +158,24 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
|
|||
~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
|
||||
}
|
||||
|
||||
static void iwl_mvm_rx_esr_mode_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_mvm_esr_mode_notif *notif = (void *)pkt->data;
|
||||
struct ieee80211_vif *vif = iwl_mvm_get_bss_vif(mvm);
|
||||
|
||||
/* FW recommendations is only for entering EMLSR */
|
||||
if (IS_ERR_OR_NULL(vif) || iwl_mvm_vif_from_mac80211(vif)->esr_active)
|
||||
return;
|
||||
|
||||
if (le32_to_cpu(notif->action) == ESR_RECOMMEND_ENTER)
|
||||
iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_FW);
|
||||
else
|
||||
iwl_mvm_block_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_FW,
|
||||
iwl_mvm_get_primary_link(vif));
|
||||
}
|
||||
|
||||
static void iwl_mvm_rx_monitor_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
|
|
@ -177,9 +192,9 @@ static void iwl_mvm_rx_monitor_notif(struct iwl_mvm *mvm,
|
|||
if (!vif || vif->type != NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
if (!vif->bss_conf.chandef.chan ||
|
||||
vif->bss_conf.chandef.chan->band != NL80211_BAND_2GHZ ||
|
||||
vif->bss_conf.chandef.width < NL80211_CHAN_WIDTH_40)
|
||||
if (!vif->bss_conf.chanreq.oper.chan ||
|
||||
vif->bss_conf.chanreq.oper.chan->band != NL80211_BAND_2GHZ ||
|
||||
vif->bss_conf.chanreq.oper.width < NL80211_CHAN_WIDTH_40)
|
||||
return;
|
||||
|
||||
if (!vif->cfg.assoc)
|
||||
|
|
@ -235,7 +250,7 @@ void iwl_mvm_update_link_smps(struct ieee80211_vif *vif,
|
|||
return;
|
||||
|
||||
if (mvm->fw_static_smps_request &&
|
||||
link_conf->chandef.width == NL80211_CHAN_WIDTH_160 &&
|
||||
link_conf->chanreq.oper.width == NL80211_CHAN_WIDTH_160 &&
|
||||
link_conf->he_support)
|
||||
mode = IEEE80211_SMPS_STATIC;
|
||||
|
||||
|
|
@ -275,7 +290,7 @@ static void iwl_mvm_rx_thermal_dual_chain_req(struct iwl_mvm *mvm,
|
|||
}
|
||||
|
||||
/**
|
||||
* enum iwl_rx_handler_context context for Rx handler
|
||||
* enum iwl_rx_handler_context: context for Rx handler
|
||||
* @RX_HANDLER_SYNC : this means that it will be called in the Rx path
|
||||
* which can't acquire mvm->mutex.
|
||||
* @RX_HANDLER_ASYNC_LOCKED : If the handler needs to hold mvm->mutex
|
||||
|
|
@ -283,15 +298,19 @@ static void iwl_mvm_rx_thermal_dual_chain_req(struct iwl_mvm *mvm,
|
|||
* it will be called from a worker with mvm->mutex held.
|
||||
* @RX_HANDLER_ASYNC_UNLOCKED : in case the handler needs to lock the
|
||||
* mutex itself, it will be called from a worker without mvm->mutex held.
|
||||
* @RX_HANDLER_ASYNC_LOCKED_WIPHY: If the handler needs to hold the wiphy lock
|
||||
* and mvm->mutex. Will be handled with the wiphy_work queue infra
|
||||
* instead of regular work queue.
|
||||
*/
|
||||
enum iwl_rx_handler_context {
|
||||
RX_HANDLER_SYNC,
|
||||
RX_HANDLER_ASYNC_LOCKED,
|
||||
RX_HANDLER_ASYNC_UNLOCKED,
|
||||
RX_HANDLER_ASYNC_LOCKED_WIPHY,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_rx_handlers handler for FW notification
|
||||
* struct iwl_rx_handlers: handler for FW notification
|
||||
* @cmd_id: command id
|
||||
* @min_size: minimum size to expect for the notification
|
||||
* @context: see &iwl_rx_handler_context
|
||||
|
|
@ -332,12 +351,26 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
|
|||
struct iwl_tlc_update_notif),
|
||||
|
||||
RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif,
|
||||
RX_HANDLER_ASYNC_LOCKED, struct iwl_bt_coex_profile_notif),
|
||||
RX_HANDLER_ASYNC_LOCKED_WIPHY,
|
||||
struct iwl_bt_coex_profile_notif),
|
||||
RX_HANDLER_NO_SIZE(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif,
|
||||
RX_HANDLER_ASYNC_LOCKED),
|
||||
RX_HANDLER_NO_SIZE(STATISTICS_NOTIFICATION, iwl_mvm_rx_statistics,
|
||||
RX_HANDLER_ASYNC_LOCKED),
|
||||
|
||||
RX_HANDLER_GRP(STATISTICS_GROUP, STATISTICS_OPER_NOTIF,
|
||||
iwl_mvm_handle_rx_system_oper_stats,
|
||||
RX_HANDLER_ASYNC_LOCKED_WIPHY,
|
||||
struct iwl_system_statistics_notif_oper),
|
||||
RX_HANDLER_GRP(STATISTICS_GROUP, STATISTICS_OPER_PART1_NOTIF,
|
||||
iwl_mvm_handle_rx_system_oper_part1_stats,
|
||||
RX_HANDLER_ASYNC_LOCKED,
|
||||
struct iwl_system_statistics_part1_notif_oper),
|
||||
RX_HANDLER_GRP(SYSTEM_GROUP, SYSTEM_STATISTICS_END_NOTIF,
|
||||
iwl_mvm_handle_rx_system_end_stats_notif,
|
||||
RX_HANDLER_ASYNC_LOCKED,
|
||||
struct iwl_system_statistics_end_notif),
|
||||
|
||||
RX_HANDLER(BA_WINDOW_STATUS_NOTIFICATION_ID,
|
||||
iwl_mvm_window_status_notif, RX_HANDLER_SYNC,
|
||||
struct iwl_ba_window_status_notif),
|
||||
|
|
@ -363,13 +396,15 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
|
|||
iwl_mvm_rx_scan_match_found,
|
||||
RX_HANDLER_SYNC),
|
||||
RX_HANDLER(SCAN_COMPLETE_UMAC, iwl_mvm_rx_umac_scan_complete_notif,
|
||||
RX_HANDLER_ASYNC_LOCKED, struct iwl_umac_scan_complete),
|
||||
RX_HANDLER_ASYNC_LOCKED,
|
||||
struct iwl_umac_scan_complete),
|
||||
RX_HANDLER(SCAN_ITERATION_COMPLETE_UMAC,
|
||||
iwl_mvm_rx_umac_scan_iter_complete_notif, RX_HANDLER_SYNC,
|
||||
struct iwl_umac_scan_iter_complete_notif),
|
||||
|
||||
RX_HANDLER(MISSED_BEACONS_NOTIFICATION, iwl_mvm_rx_missed_beacons_notif,
|
||||
RX_HANDLER_SYNC, struct iwl_missed_beacons_notif),
|
||||
RX_HANDLER_ASYNC_LOCKED_WIPHY,
|
||||
struct iwl_missed_beacons_notif),
|
||||
|
||||
RX_HANDLER(REPLY_ERROR, iwl_mvm_rx_fw_error, RX_HANDLER_SYNC,
|
||||
struct iwl_error_resp),
|
||||
|
|
@ -421,6 +456,12 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
|
|||
iwl_mvm_channel_switch_error_notif,
|
||||
RX_HANDLER_ASYNC_UNLOCKED,
|
||||
struct iwl_channel_switch_error_notif),
|
||||
|
||||
RX_HANDLER_GRP(DATA_PATH_GROUP, ESR_MODE_NOTIF,
|
||||
iwl_mvm_rx_esr_mode_notif,
|
||||
RX_HANDLER_ASYNC_LOCKED_WIPHY,
|
||||
struct iwl_mvm_esr_mode_notif),
|
||||
|
||||
RX_HANDLER_GRP(DATA_PATH_GROUP, MONITOR_NOTIF,
|
||||
iwl_mvm_rx_monitor_notif, RX_HANDLER_ASYNC_LOCKED,
|
||||
struct iwl_datapath_monitor_notif),
|
||||
|
|
@ -442,6 +483,12 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
|
|||
WNM_80211V_TIMING_MEASUREMENT_CONFIRM_NOTIFICATION,
|
||||
iwl_mvm_time_sync_msmt_confirm_event, RX_HANDLER_SYNC,
|
||||
struct iwl_time_msmt_cfm_notify),
|
||||
RX_HANDLER_GRP(MAC_CONF_GROUP, ROC_NOTIF,
|
||||
iwl_mvm_rx_roc_notif, RX_HANDLER_ASYNC_LOCKED,
|
||||
struct iwl_roc_notif),
|
||||
RX_HANDLER_GRP(SCAN_GROUP, CHANNEL_SURVEY_NOTIF,
|
||||
iwl_mvm_rx_channel_survey_notif, RX_HANDLER_ASYNC_LOCKED,
|
||||
struct iwl_umac_scan_channel_survey_notif),
|
||||
};
|
||||
#undef RX_HANDLER
|
||||
#undef RX_HANDLER_GRP
|
||||
|
|
@ -538,6 +585,7 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
|
|||
HCMD_NAME(D0I3_END_CMD),
|
||||
HCMD_NAME(LTR_CONFIG),
|
||||
HCMD_NAME(LDBG_CONFIG_CMD),
|
||||
HCMD_NAME(DEBUG_LOG_MSG),
|
||||
};
|
||||
|
||||
/* Please keep this array *SORTED* by hex value.
|
||||
|
|
@ -545,11 +593,14 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
|
|||
*/
|
||||
static const struct iwl_hcmd_names iwl_mvm_system_names[] = {
|
||||
HCMD_NAME(SHARED_MEM_CFG_CMD),
|
||||
HCMD_NAME(SOC_CONFIGURATION_CMD),
|
||||
HCMD_NAME(INIT_EXTENDED_CFG_CMD),
|
||||
HCMD_NAME(FW_ERROR_RECOVERY_CMD),
|
||||
HCMD_NAME(RFI_CONFIG_CMD),
|
||||
HCMD_NAME(RFI_GET_FREQ_TABLE_CMD),
|
||||
HCMD_NAME(SYSTEM_FEATURES_CONTROL_CMD),
|
||||
HCMD_NAME(SYSTEM_STATISTICS_CMD),
|
||||
HCMD_NAME(SYSTEM_STATISTICS_END_NOTIF),
|
||||
HCMD_NAME(RFI_DEACTIVATE_NOTIF),
|
||||
};
|
||||
|
||||
|
|
@ -557,15 +608,22 @@ static const struct iwl_hcmd_names iwl_mvm_system_names[] = {
|
|||
* Access is done through binary search
|
||||
*/
|
||||
static const struct iwl_hcmd_names iwl_mvm_mac_conf_names[] = {
|
||||
HCMD_NAME(LOW_LATENCY_CMD),
|
||||
HCMD_NAME(CHANNEL_SWITCH_TIME_EVENT_CMD),
|
||||
HCMD_NAME(SESSION_PROTECTION_CMD),
|
||||
HCMD_NAME(CANCEL_CHANNEL_SWITCH_CMD),
|
||||
HCMD_NAME(MAC_CONFIG_CMD),
|
||||
HCMD_NAME(LINK_CONFIG_CMD),
|
||||
HCMD_NAME(STA_CONFIG_CMD),
|
||||
HCMD_NAME(AUX_STA_CMD),
|
||||
HCMD_NAME(STA_REMOVE_CMD),
|
||||
HCMD_NAME(STA_DISABLE_TX_CMD),
|
||||
HCMD_NAME(ROC_CMD),
|
||||
HCMD_NAME(ROC_NOTIF),
|
||||
HCMD_NAME(CHANNEL_SWITCH_ERROR_NOTIF),
|
||||
HCMD_NAME(MISSED_VAP_NOTIF),
|
||||
HCMD_NAME(SESSION_PROTECTION_NOTIF),
|
||||
HCMD_NAME(PROBE_RESPONSE_DATA_NOTIF),
|
||||
HCMD_NAME(CHANNEL_SWITCH_START_NOTIF),
|
||||
};
|
||||
|
||||
|
|
@ -577,6 +635,7 @@ static const struct iwl_hcmd_names iwl_mvm_phy_names[] = {
|
|||
HCMD_NAME(CTDP_CONFIG_CMD),
|
||||
HCMD_NAME(TEMP_REPORTING_THRESHOLDS_CMD),
|
||||
HCMD_NAME(PER_CHAIN_LIMIT_OFFSET_CMD),
|
||||
HCMD_NAME(AP_TX_POWER_CONSTRAINTS_CMD),
|
||||
HCMD_NAME(CT_KILL_NOTIFICATION),
|
||||
HCMD_NAME(DTS_MEASUREMENT_NOTIF_WIDE),
|
||||
};
|
||||
|
|
@ -588,6 +647,8 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
|
|||
HCMD_NAME(DQA_ENABLE_CMD),
|
||||
HCMD_NAME(UPDATE_MU_GROUPS_CMD),
|
||||
HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD),
|
||||
HCMD_NAME(WNM_PLATFORM_PTM_REQUEST_CMD),
|
||||
HCMD_NAME(WNM_80211V_TIMING_MEASUREMENT_CONFIG_CMD),
|
||||
HCMD_NAME(STA_HE_CTXT_CMD),
|
||||
HCMD_NAME(RLC_CONFIG_CMD),
|
||||
HCMD_NAME(RFH_QUEUE_CONFIG_CMD),
|
||||
|
|
@ -595,6 +656,7 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
|
|||
HCMD_NAME(CHEST_COLLECTOR_FILTER_CONFIG_CMD),
|
||||
HCMD_NAME(SCD_QUEUE_CONFIG_CMD),
|
||||
HCMD_NAME(SEC_KEY_CMD),
|
||||
HCMD_NAME(ESR_MODE_NOTIF),
|
||||
HCMD_NAME(MONITOR_NOTIF),
|
||||
HCMD_NAME(THERMAL_DUAL_CHAIN_REQUEST),
|
||||
HCMD_NAME(STA_PM_NOTIF),
|
||||
|
|
@ -602,10 +664,34 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
|
|||
HCMD_NAME(RX_QUEUES_NOTIFICATION),
|
||||
};
|
||||
|
||||
/* Please keep this array *SORTED* by hex value.
|
||||
* Access is done through binary search
|
||||
*/
|
||||
static const struct iwl_hcmd_names iwl_mvm_statistics_names[] = {
|
||||
HCMD_NAME(STATISTICS_OPER_NOTIF),
|
||||
HCMD_NAME(STATISTICS_OPER_PART1_NOTIF),
|
||||
};
|
||||
|
||||
/* Please keep this array *SORTED* by hex value.
|
||||
* Access is done through binary search
|
||||
*/
|
||||
static const struct iwl_hcmd_names iwl_mvm_debug_names[] = {
|
||||
HCMD_NAME(LMAC_RD_WR),
|
||||
HCMD_NAME(UMAC_RD_WR),
|
||||
HCMD_NAME(HOST_EVENT_CFG),
|
||||
HCMD_NAME(DBGC_SUSPEND_RESUME),
|
||||
HCMD_NAME(BUFFER_ALLOCATION),
|
||||
HCMD_NAME(GET_TAS_STATUS),
|
||||
HCMD_NAME(FW_DUMP_COMPLETE_CMD),
|
||||
HCMD_NAME(FW_CLEAR_BUFFER),
|
||||
HCMD_NAME(MFU_ASSERT_DUMP_NTF),
|
||||
};
|
||||
|
||||
/* Please keep this array *SORTED* by hex value.
|
||||
* Access is done through binary search
|
||||
*/
|
||||
static const struct iwl_hcmd_names iwl_mvm_scan_names[] = {
|
||||
HCMD_NAME(CHANNEL_SURVEY_NOTIF),
|
||||
HCMD_NAME(OFFLOAD_MATCH_INFO_NOTIF),
|
||||
};
|
||||
|
||||
|
|
@ -656,10 +742,14 @@ static const struct iwl_hcmd_arr iwl_mvm_groups[] = {
|
|||
[PROT_OFFLOAD_GROUP] = HCMD_ARR(iwl_mvm_prot_offload_names),
|
||||
[REGULATORY_AND_NVM_GROUP] =
|
||||
HCMD_ARR(iwl_mvm_regulatory_and_nvm_names),
|
||||
[DEBUG_GROUP] = HCMD_ARR(iwl_mvm_debug_names),
|
||||
[STATISTICS_GROUP] = HCMD_ARR(iwl_mvm_statistics_names),
|
||||
};
|
||||
|
||||
/* this forward declaration can avoid to export the function */
|
||||
static void iwl_mvm_async_handlers_wk(struct work_struct *wk);
|
||||
static void iwl_mvm_async_handlers_wiphy_wk(struct wiphy *wiphy,
|
||||
struct wiphy_work *work);
|
||||
|
||||
static u32 iwl_mvm_min_backoff(struct iwl_mvm *mvm)
|
||||
{
|
||||
|
|
@ -669,7 +759,7 @@ static u32 iwl_mvm_min_backoff(struct iwl_mvm *mvm)
|
|||
if (!backoff)
|
||||
return 0;
|
||||
|
||||
dflt_pwr_limit = iwl_acpi_get_pwr_limit(mvm->dev);
|
||||
iwl_bios_get_pwr_limit(&mvm->fwrt, &dflt_pwr_limit);
|
||||
|
||||
while (backoff->pwr) {
|
||||
if (dflt_pwr_limit >= backoff->pwr)
|
||||
|
|
@ -688,20 +778,18 @@ static void iwl_mvm_tx_unblock_dwork(struct work_struct *work)
|
|||
struct ieee80211_vif *tx_blocked_vif;
|
||||
struct iwl_mvm_vif *mvmvif;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
guard(mvm)(mvm);
|
||||
|
||||
tx_blocked_vif =
|
||||
rcu_dereference_protected(mvm->csa_tx_blocked_vif,
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
|
||||
if (!tx_blocked_vif)
|
||||
goto unlock;
|
||||
return;
|
||||
|
||||
mvmvif = iwl_mvm_vif_from_mac80211(tx_blocked_vif);
|
||||
iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, false);
|
||||
RCU_INIT_POINTER(mvm->csa_tx_blocked_vif, NULL);
|
||||
unlock:
|
||||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
static void iwl_mvm_fwrt_dump_start(void *ctx)
|
||||
|
|
@ -718,21 +806,12 @@ static void iwl_mvm_fwrt_dump_end(void *ctx)
|
|||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
static bool iwl_mvm_fwrt_fw_running(void *ctx)
|
||||
{
|
||||
return iwl_mvm_firmware_running(ctx);
|
||||
}
|
||||
|
||||
static int iwl_mvm_fwrt_send_hcmd(void *ctx, struct iwl_host_cmd *host_cmd)
|
||||
{
|
||||
struct iwl_mvm *mvm = (struct iwl_mvm *)ctx;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
ret = iwl_mvm_send_cmd(mvm, host_cmd);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return ret;
|
||||
guard(mvm)(mvm);
|
||||
return iwl_mvm_send_cmd(mvm, host_cmd);
|
||||
}
|
||||
|
||||
static bool iwl_mvm_d3_debug_enable(void *ctx)
|
||||
|
|
@ -743,7 +822,6 @@ static bool iwl_mvm_d3_debug_enable(void *ctx)
|
|||
static const struct iwl_fw_runtime_ops iwl_mvm_fwrt_ops = {
|
||||
.dump_start = iwl_mvm_fwrt_dump_start,
|
||||
.dump_end = iwl_mvm_fwrt_dump_end,
|
||||
.fw_running = iwl_mvm_fwrt_fw_running,
|
||||
.send_hcmd = iwl_mvm_fwrt_send_hcmd,
|
||||
.d3_debug_enable = iwl_mvm_d3_debug_enable,
|
||||
};
|
||||
|
|
@ -767,7 +845,10 @@ static int iwl_mvm_start_get_nvm(struct iwl_mvm *mvm)
|
|||
*/
|
||||
mvm->nvm_data =
|
||||
iwl_parse_mei_nvm_data(trans, trans->cfg,
|
||||
mvm->mei_nvm_data, mvm->fw);
|
||||
mvm->mei_nvm_data,
|
||||
mvm->fw,
|
||||
mvm->set_tx_ant,
|
||||
mvm->set_rx_ant);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -796,8 +877,7 @@ get_nvm_from_fw:
|
|||
ret = iwl_mvm_init_mcc(mvm);
|
||||
}
|
||||
|
||||
if (!iwlmvm_mod_params.init_dbg || !ret)
|
||||
iwl_mvm_stop_device(mvm);
|
||||
iwl_mvm_stop_device(mvm);
|
||||
|
||||
mutex_unlock(&mvm->mutex);
|
||||
wiphy_unlock(mvm->hw->wiphy);
|
||||
|
|
@ -806,6 +886,9 @@ get_nvm_from_fw:
|
|||
if (ret)
|
||||
IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", ret);
|
||||
|
||||
/* no longer need this regardless of failure or not */
|
||||
mvm->fw_product_reset = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1121,6 +1204,29 @@ static const struct iwl_mei_ops mei_ops = {
|
|||
};
|
||||
#endif
|
||||
|
||||
static void iwl_mvm_find_link_selection_vif(void *_data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
if (ieee80211_vif_is_mld(vif) && mvmvif->authorized)
|
||||
iwl_mvm_select_links(mvmvif->mvm, vif);
|
||||
}
|
||||
|
||||
static void iwl_mvm_trig_link_selection(struct wiphy *wiphy,
|
||||
struct wiphy_work *wk)
|
||||
{
|
||||
struct iwl_mvm *mvm =
|
||||
container_of(wk, struct iwl_mvm, trig_link_selection_wk);
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
ieee80211_iterate_active_interfaces(mvm->hw,
|
||||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
iwl_mvm_find_link_selection_vif,
|
||||
NULL);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
static struct iwl_op_mode *
|
||||
iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
const struct iwl_fw *fw, struct dentry *dbgfs_dir)
|
||||
|
|
@ -1156,7 +1262,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
return NULL;
|
||||
|
||||
if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
|
||||
max_agg = IEEE80211_MAX_AMPDU_BUF_EHT;
|
||||
max_agg = 512;
|
||||
else
|
||||
max_agg = IEEE80211_MAX_AMPDU_BUF_HE;
|
||||
|
||||
|
|
@ -1179,7 +1285,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
iwl_fw_runtime_init(&mvm->fwrt, trans, fw, &iwl_mvm_fwrt_ops, mvm,
|
||||
&iwl_mvm_sanitize_ops, mvm, dbgfs_dir);
|
||||
|
||||
iwl_mvm_get_acpi_tables(mvm);
|
||||
iwl_mvm_get_bios_tables(mvm);
|
||||
iwl_uefi_get_sgom_table(trans, &mvm->fwrt);
|
||||
iwl_uefi_get_step_table(trans);
|
||||
|
||||
|
|
@ -1250,6 +1356,12 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
INIT_LIST_HEAD(&mvm->add_stream_txqs);
|
||||
spin_lock_init(&mvm->add_stream_lock);
|
||||
|
||||
wiphy_work_init(&mvm->async_handlers_wiphy_wk,
|
||||
iwl_mvm_async_handlers_wiphy_wk);
|
||||
|
||||
wiphy_work_init(&mvm->trig_link_selection_wk,
|
||||
iwl_mvm_trig_link_selection);
|
||||
|
||||
init_waitqueue_head(&mvm->rx_sync_waitq);
|
||||
|
||||
mvm->queue_sync_state = 0;
|
||||
|
|
@ -1279,24 +1391,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
trans_cfg.no_reclaim_cmds = no_reclaim_cmds;
|
||||
trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
|
||||
|
||||
switch (iwlwifi_mod_params.amsdu_size) {
|
||||
case IWL_AMSDU_DEF:
|
||||
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
|
||||
break;
|
||||
case IWL_AMSDU_4K:
|
||||
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
|
||||
break;
|
||||
case IWL_AMSDU_8K:
|
||||
trans_cfg.rx_buf_size = IWL_AMSDU_8K;
|
||||
break;
|
||||
case IWL_AMSDU_12K:
|
||||
trans_cfg.rx_buf_size = IWL_AMSDU_12K;
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: Unsupported amsdu_size: %d\n", KBUILD_MODNAME,
|
||||
iwlwifi_mod_params.amsdu_size);
|
||||
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
|
||||
}
|
||||
trans_cfg.rx_buf_size = iwl_amsdu_size_to_rxb_size();
|
||||
|
||||
trans->wide_cmd_header = true;
|
||||
trans_cfg.bc_table_dword =
|
||||
|
|
@ -1318,7 +1413,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
|
||||
snprintf(mvm->hw->wiphy->fw_version,
|
||||
sizeof(mvm->hw->wiphy->fw_version),
|
||||
"%s", fw->fw_version);
|
||||
"%.31s", fw->fw_version);
|
||||
|
||||
trans_cfg.fw_reset_handshake = fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE);
|
||||
|
|
@ -1356,9 +1451,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
goto out_free;
|
||||
}
|
||||
|
||||
IWL_INFO(mvm, "Detected %s, REV=0x%X\n",
|
||||
mvm->trans->name, mvm->trans->hw_rev);
|
||||
|
||||
if (iwlwifi_mod_params.nvm_file)
|
||||
mvm->nvm_file_name = iwlwifi_mod_params.nvm_file;
|
||||
else
|
||||
|
|
@ -1430,8 +1522,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
iwl_fw_flush_dumps(&mvm->fwrt);
|
||||
iwl_fw_runtime_free(&mvm->fwrt);
|
||||
|
||||
if (iwlmvm_mod_params.init_dbg)
|
||||
return op_mode;
|
||||
iwl_phy_db_free(mvm->phy_db);
|
||||
kfree(mvm->scan_cmd);
|
||||
iwl_trans_op_mode_leave(trans);
|
||||
|
|
@ -1448,6 +1538,8 @@ void iwl_mvm_stop_device(struct iwl_mvm *mvm)
|
|||
|
||||
clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
|
||||
|
||||
iwl_mvm_pause_tcm(mvm, false);
|
||||
|
||||
iwl_fw_dbg_stop_sync(&mvm->fwrt);
|
||||
iwl_trans_stop_device(mvm->trans);
|
||||
iwl_free_fw_paging(&mvm->fwrt);
|
||||
|
|
@ -1508,6 +1600,7 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
|
|||
kfree(mvm->temp_nvm_data);
|
||||
for (i = 0; i < NVM_MAX_NUM_SECTIONS; i++)
|
||||
kfree(mvm->nvm_sections[i].data);
|
||||
kfree(mvm->acs_survey);
|
||||
|
||||
cancel_delayed_work_sync(&mvm->tcm.work);
|
||||
|
||||
|
|
@ -1540,35 +1633,62 @@ void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm)
|
|||
spin_unlock_bh(&mvm->async_handlers_lock);
|
||||
}
|
||||
|
||||
static void iwl_mvm_async_handlers_wk(struct work_struct *wk)
|
||||
/*
|
||||
* This function receives a bitmap of rx async handler contexts
|
||||
* (&iwl_rx_handler_context) to handle, and runs only them
|
||||
*/
|
||||
static void iwl_mvm_async_handlers_by_context(struct iwl_mvm *mvm,
|
||||
u8 contexts)
|
||||
{
|
||||
struct iwl_mvm *mvm =
|
||||
container_of(wk, struct iwl_mvm, async_handlers_wk);
|
||||
struct iwl_async_handler_entry *entry, *tmp;
|
||||
LIST_HEAD(local_list);
|
||||
|
||||
/* Ensure that we are not in stop flow (check iwl_mvm_mac_stop) */
|
||||
|
||||
/*
|
||||
* Sync with Rx path with a lock. Remove all the entries from this list,
|
||||
* add them to a local one (lock free), and then handle them.
|
||||
* Sync with Rx path with a lock. Remove all the entries of the
|
||||
* wanted contexts from this list, add them to a local one (lock free),
|
||||
* and then handle them.
|
||||
*/
|
||||
spin_lock_bh(&mvm->async_handlers_lock);
|
||||
list_splice_init(&mvm->async_handlers_list, &local_list);
|
||||
list_for_each_entry_safe(entry, tmp, &mvm->async_handlers_list, list) {
|
||||
if (!(BIT(entry->context) & contexts))
|
||||
continue;
|
||||
list_del(&entry->list);
|
||||
list_add_tail(&entry->list, &local_list);
|
||||
}
|
||||
spin_unlock_bh(&mvm->async_handlers_lock);
|
||||
|
||||
list_for_each_entry_safe(entry, tmp, &local_list, list) {
|
||||
if (entry->context == RX_HANDLER_ASYNC_LOCKED)
|
||||
if (entry->context != RX_HANDLER_ASYNC_UNLOCKED)
|
||||
mutex_lock(&mvm->mutex);
|
||||
entry->fn(mvm, &entry->rxb);
|
||||
iwl_free_rxb(&entry->rxb);
|
||||
list_del(&entry->list);
|
||||
if (entry->context == RX_HANDLER_ASYNC_LOCKED)
|
||||
if (entry->context != RX_HANDLER_ASYNC_UNLOCKED)
|
||||
mutex_unlock(&mvm->mutex);
|
||||
kfree(entry);
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_async_handlers_wiphy_wk(struct wiphy *wiphy,
|
||||
struct wiphy_work *wk)
|
||||
{
|
||||
struct iwl_mvm *mvm =
|
||||
container_of(wk, struct iwl_mvm, async_handlers_wiphy_wk);
|
||||
u8 contexts = BIT(RX_HANDLER_ASYNC_LOCKED_WIPHY);
|
||||
|
||||
iwl_mvm_async_handlers_by_context(mvm, contexts);
|
||||
}
|
||||
|
||||
static void iwl_mvm_async_handlers_wk(struct work_struct *wk)
|
||||
{
|
||||
struct iwl_mvm *mvm =
|
||||
container_of(wk, struct iwl_mvm, async_handlers_wk);
|
||||
u8 contexts = BIT(RX_HANDLER_ASYNC_LOCKED) |
|
||||
BIT(RX_HANDLER_ASYNC_UNLOCKED);
|
||||
|
||||
iwl_mvm_async_handlers_by_context(mvm, contexts);
|
||||
}
|
||||
|
||||
static inline void iwl_mvm_rx_check_trigger(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_packet *pkt)
|
||||
{
|
||||
|
|
@ -1648,7 +1768,11 @@ static void iwl_mvm_rx_common(struct iwl_mvm *mvm,
|
|||
spin_lock(&mvm->async_handlers_lock);
|
||||
list_add_tail(&entry->list, &mvm->async_handlers_list);
|
||||
spin_unlock(&mvm->async_handlers_lock);
|
||||
schedule_work(&mvm->async_handlers_wk);
|
||||
if (rx_h->context == RX_HANDLER_ASYNC_LOCKED_WIPHY)
|
||||
wiphy_work_queue(mvm->hw->wiphy,
|
||||
&mvm->async_handlers_wiphy_wk);
|
||||
else
|
||||
schedule_work(&mvm->async_handlers_wk);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1692,18 +1816,6 @@ void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode,
|
|||
iwl_mvm_rx_common(mvm, rxb, pkt);
|
||||
}
|
||||
|
||||
static void iwl_mvm_async_cb(struct iwl_op_mode *op_mode,
|
||||
const struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
|
||||
|
||||
/*
|
||||
* For now, we only set the CMD_WANT_ASYNC_CALLBACK for ADD_STA
|
||||
* commands that need to block the Tx queues.
|
||||
*/
|
||||
iwl_trans_block_txq_ptrs(mvm->trans, false);
|
||||
}
|
||||
|
||||
static int iwl_mvm_is_static_queue(struct iwl_mvm *mvm, int queue)
|
||||
{
|
||||
return queue == mvm->aux_queue || queue == mvm->probe_queue ||
|
||||
|
|
@ -1789,12 +1901,8 @@ static void iwl_mvm_wake_sw_queue(struct iwl_op_mode *op_mode, int hw_queue)
|
|||
|
||||
static void iwl_mvm_set_rfkill_state(struct iwl_mvm *mvm)
|
||||
{
|
||||
bool state = iwl_mvm_is_radio_killed(mvm);
|
||||
|
||||
if (state)
|
||||
wake_up(&mvm->rx_sync_waitq);
|
||||
|
||||
wiphy_rfkill_set_hw_state(mvm->hw->wiphy, state);
|
||||
wiphy_rfkill_set_hw_state(mvm->hw->wiphy,
|
||||
iwl_mvm_is_radio_killed(mvm));
|
||||
}
|
||||
|
||||
void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state)
|
||||
|
|
@ -1956,7 +2064,7 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
|
|||
ieee80211_restart_hw(mvm->hw);
|
||||
} else if (mvm->fwrt.trans->dbg.restart_required) {
|
||||
IWL_DEBUG_INFO(mvm, "FW restart requested after debug collection\n");
|
||||
mvm->fwrt.trans->dbg.restart_required = FALSE;
|
||||
mvm->fwrt.trans->dbg.restart_required = false;
|
||||
ieee80211_restart_hw(mvm->hw);
|
||||
} else if (mvm->trans->trans_cfg->device_family <= IWL_DEVICE_FAMILY_8000) {
|
||||
ieee80211_restart_hw(mvm->hw);
|
||||
|
|
@ -1968,9 +2076,6 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode, bool sync)
|
|||
{
|
||||
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
|
||||
|
||||
if (mvm->pldr_sync)
|
||||
return;
|
||||
|
||||
if (!test_bit(STATUS_TRANS_DEAD, &mvm->trans->status) &&
|
||||
!test_and_clear_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE,
|
||||
&mvm->status))
|
||||
|
|
@ -2014,9 +2119,22 @@ static void iwl_op_mode_mvm_time_point(struct iwl_op_mode *op_mode,
|
|||
iwl_dbg_tlv_time_point(&mvm->fwrt, tp_id, tp_data);
|
||||
}
|
||||
|
||||
static void iwl_op_mode_mvm_device_powered_off(struct iwl_op_mode *op_mode)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
clear_bit(IWL_MVM_STATUS_IN_D3, &mvm->status);
|
||||
mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
|
||||
iwl_mvm_stop_device(mvm);
|
||||
#ifdef CONFIG_PM
|
||||
mvm->fast_resume = false;
|
||||
#endif
|
||||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
#define IWL_MVM_COMMON_OPS \
|
||||
/* these could be differentiated */ \
|
||||
.async_cb = iwl_mvm_async_cb, \
|
||||
.queue_full = iwl_mvm_stop_sw_queue, \
|
||||
.queue_not_full = iwl_mvm_wake_sw_queue, \
|
||||
.hw_rf_kill = iwl_mvm_set_hw_rfkill_state, \
|
||||
|
|
@ -2027,7 +2145,8 @@ static void iwl_op_mode_mvm_time_point(struct iwl_op_mode *op_mode,
|
|||
/* as we only register one, these MUST be common! */ \
|
||||
.start = iwl_op_mode_mvm_start, \
|
||||
.stop = iwl_op_mode_mvm_stop, \
|
||||
.time_point = iwl_op_mode_mvm_time_point
|
||||
.time_point = iwl_op_mode_mvm_time_point, \
|
||||
.device_powered_off = iwl_op_mode_mvm_device_powered_off
|
||||
|
||||
static const struct iwl_op_mode_ops iwl_mvm_ops = {
|
||||
IWL_MVM_COMMON_OPS,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
#include "mvm.h"
|
||||
|
||||
/* Maps the driver specific channel width definition to the fw values */
|
||||
u8 iwl_mvm_get_channel_width(struct cfg80211_chan_def *chandef)
|
||||
u8 iwl_mvm_get_channel_width(const struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
switch (chandef->width) {
|
||||
case NL80211_CHAN_WIDTH_20_NOHT:
|
||||
|
|
@ -33,7 +33,7 @@ u8 iwl_mvm_get_channel_width(struct cfg80211_chan_def *chandef)
|
|||
* Maps the driver specific control channel position (relative to the center
|
||||
* freq) definitions to the the fw values
|
||||
*/
|
||||
u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef)
|
||||
u8 iwl_mvm_get_ctrl_pos(const struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
int offs = chandef->chan->center_freq - chandef->center_freq1;
|
||||
int abs_offs = abs(offs);
|
||||
|
|
@ -99,17 +99,6 @@ static void iwl_mvm_phy_ctxt_set_rxchain(struct iwl_mvm *mvm,
|
|||
active_cnt = 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the firmware requested it, then we know that it supports
|
||||
* getting zero for the values to indicate "use one, but pick
|
||||
* which one yourself", which means it can dynamically pick one
|
||||
* that e.g. has better RSSI.
|
||||
*/
|
||||
if (mvm->fw_static_smps_request && active_cnt == 1 && idle_cnt == 1) {
|
||||
idle_cnt = 0;
|
||||
active_cnt = 0;
|
||||
}
|
||||
|
||||
*rxchain_info = cpu_to_le32(iwl_mvm_get_valid_rx_ant(mvm) <<
|
||||
PHY_RX_CHAIN_VALID_POS);
|
||||
*rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS);
|
||||
|
|
@ -127,7 +116,7 @@ static void iwl_mvm_phy_ctxt_set_rxchain(struct iwl_mvm *mvm,
|
|||
static void iwl_mvm_phy_ctxt_cmd_data_v1(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_phy_ctxt *ctxt,
|
||||
struct iwl_phy_context_cmd_v1 *cmd,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
const struct cfg80211_chan_def *chandef,
|
||||
u8 chains_static, u8 chains_dynamic)
|
||||
{
|
||||
struct iwl_phy_context_cmd_tail *tail =
|
||||
|
|
@ -148,7 +137,7 @@ static void iwl_mvm_phy_ctxt_cmd_data_v1(struct iwl_mvm *mvm,
|
|||
static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_phy_ctxt *ctxt,
|
||||
struct iwl_phy_context_cmd *cmd,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
const struct cfg80211_chan_def *chandef,
|
||||
u8 chains_static, u8 chains_dynamic)
|
||||
{
|
||||
cmd->lmac_id = cpu_to_le32(iwl_mvm_get_lmac_id(mvm,
|
||||
|
|
@ -192,6 +181,9 @@ int iwl_mvm_phy_send_rlc(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
|||
iwl_mvm_phy_ctxt_set_rxchain(mvm, ctxt, &cmd.rlc.rx_chain_info,
|
||||
chains_static, chains_dynamic);
|
||||
|
||||
IWL_DEBUG_FW(mvm, "Send RLC command: phy=%d, rx_chain_info=0x%x\n",
|
||||
ctxt->id, cmd.rlc.rx_chain_info);
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(RLC_CONFIG_CMD,
|
||||
DATA_PATH_GROUP, 2),
|
||||
0, sizeof(cmd), &cmd);
|
||||
|
|
@ -205,14 +197,18 @@ int iwl_mvm_phy_send_rlc(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
|||
*/
|
||||
static int iwl_mvm_phy_ctxt_apply(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_phy_ctxt *ctxt,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
const struct cfg80211_chan_def *chandef,
|
||||
const struct cfg80211_chan_def *ap,
|
||||
u8 chains_static, u8 chains_dynamic,
|
||||
u32 action)
|
||||
{
|
||||
int ret;
|
||||
int ver = iwl_fw_lookup_cmd_ver(mvm->fw, PHY_CONTEXT_CMD, 1);
|
||||
|
||||
if (ver == 3 || ver == 4) {
|
||||
if (ver < 5 || !ap || !ap->chan)
|
||||
ap = NULL;
|
||||
|
||||
if (ver >= 3 && ver <= 6) {
|
||||
struct iwl_phy_context_cmd cmd = {};
|
||||
|
||||
/* Set the command header fields */
|
||||
|
|
@ -223,6 +219,14 @@ static int iwl_mvm_phy_ctxt_apply(struct iwl_mvm *mvm,
|
|||
chains_static,
|
||||
chains_dynamic);
|
||||
|
||||
if (ap) {
|
||||
cmd.sbb_bandwidth = iwl_mvm_get_channel_width(ap);
|
||||
cmd.sbb_ctrl_channel_loc = iwl_mvm_get_ctrl_pos(ap);
|
||||
}
|
||||
|
||||
if (ver == 6)
|
||||
cmd.puncture_mask = cpu_to_le16(chandef->punctured);
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, PHY_CONTEXT_CMD,
|
||||
0, sizeof(cmd), &cmd);
|
||||
} else if (ver < 3) {
|
||||
|
|
@ -262,9 +266,12 @@ static int iwl_mvm_phy_ctxt_apply(struct iwl_mvm *mvm,
|
|||
* Send a command to add a PHY context based on the current HW configuration.
|
||||
*/
|
||||
int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
const struct cfg80211_chan_def *chandef,
|
||||
const struct cfg80211_chan_def *ap,
|
||||
u8 chains_static, u8 chains_dynamic)
|
||||
{
|
||||
int ret;
|
||||
|
||||
WARN_ON(!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
|
||||
ctxt->ref);
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
|
@ -273,9 +280,16 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
|||
ctxt->width = chandef->width;
|
||||
ctxt->center_freq1 = chandef->center_freq1;
|
||||
|
||||
return iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,
|
||||
chains_static, chains_dynamic,
|
||||
FW_CTXT_ACTION_ADD);
|
||||
ret = iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef, ap,
|
||||
chains_static, chains_dynamic,
|
||||
FW_CTXT_ACTION_ADD);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ctxt->ref++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -285,6 +299,11 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
|||
void iwl_mvm_phy_ctxt_ref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
|
||||
{
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
/* If we were taking the first ref, we should have
|
||||
* called iwl_mvm_phy_ctxt_add.
|
||||
*/
|
||||
WARN_ON(!ctxt->ref);
|
||||
ctxt->ref++;
|
||||
}
|
||||
|
||||
|
|
@ -294,14 +313,19 @@ void iwl_mvm_phy_ctxt_ref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
|
|||
* changed.
|
||||
*/
|
||||
int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
const struct cfg80211_chan_def *chandef,
|
||||
const struct cfg80211_chan_def *ap,
|
||||
u8 chains_static, u8 chains_dynamic)
|
||||
{
|
||||
enum iwl_ctxt_action action = FW_CTXT_ACTION_MODIFY;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (iwl_fw_lookup_cmd_ver(mvm->fw, WIDE_ID(DATA_PATH_GROUP, RLC_CONFIG_CMD), 0) >= 2 &&
|
||||
if (WARN_ON_ONCE(!ctxt->ref))
|
||||
return -EINVAL;
|
||||
|
||||
if (iwl_fw_lookup_cmd_ver(mvm->fw, WIDE_ID(DATA_PATH_GROUP,
|
||||
RLC_CONFIG_CMD), 0) >= 2 &&
|
||||
ctxt->channel == chandef->chan &&
|
||||
ctxt->width == chandef->width &&
|
||||
ctxt->center_freq1 == chandef->center_freq1)
|
||||
|
|
@ -314,7 +338,7 @@ int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
|||
int ret;
|
||||
|
||||
/* ... remove it here ...*/
|
||||
ret = iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,
|
||||
ret = iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef, NULL,
|
||||
chains_static, chains_dynamic,
|
||||
FW_CTXT_ACTION_REMOVE);
|
||||
if (ret)
|
||||
|
|
@ -328,13 +352,14 @@ int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
|||
ctxt->width = chandef->width;
|
||||
ctxt->center_freq1 = chandef->center_freq1;
|
||||
|
||||
return iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,
|
||||
return iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef, ap,
|
||||
chains_static, chains_dynamic,
|
||||
action);
|
||||
}
|
||||
|
||||
void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
|
||||
{
|
||||
struct cfg80211_chan_def chandef;
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (WARN_ON_ONCE(!ctxt))
|
||||
|
|
@ -342,41 +367,13 @@ void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
|
|||
|
||||
ctxt->ref--;
|
||||
|
||||
/*
|
||||
* Move unused phy's to a default channel. When the phy is moved the,
|
||||
* fw will cleanup immediate quiet bit if it was previously set,
|
||||
* otherwise we might not be able to reuse this phy.
|
||||
*/
|
||||
if (ctxt->ref == 0) {
|
||||
struct ieee80211_channel *chan = NULL;
|
||||
struct cfg80211_chan_def chandef;
|
||||
struct ieee80211_supported_band *sband;
|
||||
enum nl80211_band band;
|
||||
int channel;
|
||||
if (ctxt->ref)
|
||||
return;
|
||||
|
||||
for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) {
|
||||
sband = mvm->hw->wiphy->bands[band];
|
||||
cfg80211_chandef_create(&chandef, ctxt->channel, NL80211_CHAN_NO_HT);
|
||||
|
||||
if (!sband)
|
||||
continue;
|
||||
|
||||
for (channel = 0; channel < sband->n_channels; channel++)
|
||||
if (!(sband->channels[channel].flags &
|
||||
IEEE80211_CHAN_DISABLED)) {
|
||||
chan = &sband->channels[channel];
|
||||
break;
|
||||
}
|
||||
|
||||
if (chan)
|
||||
break;
|
||||
}
|
||||
|
||||
if (WARN_ON(!chan))
|
||||
return;
|
||||
|
||||
cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
|
||||
iwl_mvm_phy_ctxt_changed(mvm, ctxt, &chandef, 1, 1);
|
||||
}
|
||||
iwl_mvm_phy_ctxt_apply(mvm, ctxt, &chandef, NULL, 1, 1,
|
||||
FW_CTXT_ACTION_REMOVE);
|
||||
}
|
||||
|
||||
static void iwl_mvm_binding_iterator(void *_data, u8 *mac,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2019, 2021-2023 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2019, 2021-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -20,8 +20,7 @@
|
|||
|
||||
static
|
||||
int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
|
||||
struct iwl_beacon_filter_cmd *cmd,
|
||||
u32 flags)
|
||||
struct iwl_beacon_filter_cmd *cmd)
|
||||
{
|
||||
u16 len;
|
||||
|
||||
|
|
@ -62,7 +61,7 @@ int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
|
|||
len = offsetof(struct iwl_beacon_filter_cmd,
|
||||
bf_threshold_absolute_low);
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, flags,
|
||||
return iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, 0,
|
||||
len, cmd);
|
||||
}
|
||||
|
||||
|
|
@ -80,7 +79,7 @@ void iwl_mvm_beacon_filter_set_cqm_params(struct iwl_mvm *mvm,
|
|||
cmd->bf_roaming_state =
|
||||
cpu_to_le32(-vif->bss_conf.cqm_rssi_thold);
|
||||
}
|
||||
cmd->ba_enable_beacon_abort = cpu_to_le32(mvmvif->bf_data.ba_enabled);
|
||||
cmd->ba_enable_beacon_abort = cpu_to_le32(mvmvif->ba_enabled);
|
||||
}
|
||||
|
||||
static void iwl_mvm_power_log(struct iwl_mvm *mvm,
|
||||
|
|
@ -212,19 +211,37 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,
|
|||
IWL_MVM_PS_HEAVY_RX_THLD_PERCENT;
|
||||
}
|
||||
|
||||
static void iwl_mvm_p2p_standalone_iterator(void *_data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
bool *is_p2p_standalone = _data;
|
||||
struct iwl_allow_uapsd_iface_iterator_data {
|
||||
struct ieee80211_vif *current_vif;
|
||||
bool allow_uapsd;
|
||||
};
|
||||
|
||||
switch (ieee80211_vif_type_p2p(vif)) {
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
static void iwl_mvm_allow_uapsd_iterator(void *_data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_allow_uapsd_iface_iterator_data *data = _data;
|
||||
struct iwl_mvm_vif *other_mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm_vif *curr_mvmvif =
|
||||
iwl_mvm_vif_from_mac80211(data->current_vif);
|
||||
|
||||
/* exclude the given vif */
|
||||
if (vif == data->current_vif)
|
||||
return;
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
*is_p2p_standalone = false;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
case NL80211_IFTYPE_NAN:
|
||||
data->allow_uapsd = false;
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
if (vif->cfg.assoc)
|
||||
*is_p2p_standalone = false;
|
||||
/* allow UAPSD if P2P interface and BSS station interface share
|
||||
* the same channel.
|
||||
*/
|
||||
if (vif->cfg.assoc && other_mvmvif->deflink.phy_ctxt &&
|
||||
curr_mvmvif->deflink.phy_ctxt &&
|
||||
other_mvmvif->deflink.phy_ctxt->id != curr_mvmvif->deflink.phy_ctxt->id)
|
||||
data->allow_uapsd = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -236,6 +253,10 @@ static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
|
|||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_allow_uapsd_iface_iterator_data data = {
|
||||
.current_vif = vif,
|
||||
.allow_uapsd = true,
|
||||
};
|
||||
|
||||
if (ether_addr_equal(mvmvif->uapsd_misbehaving_ap_addr,
|
||||
vif->cfg.ap_addr))
|
||||
|
|
@ -250,88 +271,75 @@ static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
|
|||
IEEE80211_P2P_OPPPS_ENABLE_BIT))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Avoid using uAPSD if client is in DCM -
|
||||
* low latency issue in Miracast
|
||||
*/
|
||||
if (iwl_mvm_phy_ctx_count(mvm) >= 2)
|
||||
if (vif->p2p && !iwl_mvm_is_p2p_scm_uapsd_supported(mvm))
|
||||
return false;
|
||||
|
||||
if (vif->p2p) {
|
||||
/* Allow U-APSD only if p2p is stand alone */
|
||||
bool is_p2p_standalone = true;
|
||||
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
|
||||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
iwl_mvm_allow_uapsd_iterator,
|
||||
&data);
|
||||
|
||||
if (!iwl_mvm_is_p2p_scm_uapsd_supported(mvm))
|
||||
return false;
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
|
||||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
iwl_mvm_p2p_standalone_iterator,
|
||||
&is_p2p_standalone);
|
||||
|
||||
if (!is_p2p_standalone)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return data.allow_uapsd;
|
||||
}
|
||||
|
||||
static bool iwl_mvm_power_is_radar(struct ieee80211_vif *vif)
|
||||
static bool iwl_mvm_power_is_radar(struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
bool radar_detect = false;
|
||||
unsigned int link_id;
|
||||
|
||||
rcu_read_lock();
|
||||
for_each_vif_active_link(vif, link_conf, link_id) {
|
||||
chanctx_conf = rcu_dereference(link_conf->chanctx_conf);
|
||||
/* this happens on link switching, just ignore inactive ones */
|
||||
if (!chanctx_conf)
|
||||
continue;
|
||||
chanctx_conf = rcu_dereference(link_conf->chanctx_conf);
|
||||
|
||||
radar_detect = !!(chanctx_conf->def.chan->flags &
|
||||
IEEE80211_CHAN_RADAR);
|
||||
if (radar_detect)
|
||||
goto out;
|
||||
}
|
||||
/* this happens on link switching, just ignore inactive ones */
|
||||
if (!chanctx_conf)
|
||||
return false;
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
return radar_detect;
|
||||
return chanctx_conf->def.chan->flags & IEEE80211_CHAN_RADAR;
|
||||
}
|
||||
|
||||
static void iwl_mvm_power_config_skip_dtim(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mac_power_cmd *cmd)
|
||||
{
|
||||
int dtimper = vif->bss_conf.dtim_period ?: 1;
|
||||
int skip;
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
unsigned int min_link_skip = ~0;
|
||||
unsigned int link_id;
|
||||
|
||||
/* disable, in case we're supposed to override */
|
||||
cmd->skip_dtim_periods = 0;
|
||||
cmd->flags &= ~cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
|
||||
|
||||
if (iwl_mvm_power_is_radar(vif))
|
||||
return;
|
||||
|
||||
if (dtimper >= 10)
|
||||
return;
|
||||
|
||||
if (!test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status)) {
|
||||
if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_LP)
|
||||
return;
|
||||
skip = 2;
|
||||
} else {
|
||||
int dtimper_tu = dtimper * vif->bss_conf.beacon_int;
|
||||
|
||||
if (WARN_ON(!dtimper_tu))
|
||||
return;
|
||||
/* configure skip over dtim up to 900 TU DTIM interval */
|
||||
skip = max_t(u8, 1, 900 / dtimper_tu);
|
||||
cmd->skip_dtim_periods = 2;
|
||||
cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
|
||||
return;
|
||||
}
|
||||
|
||||
cmd->skip_dtim_periods = skip;
|
||||
rcu_read_lock();
|
||||
for_each_vif_active_link(vif, link_conf, link_id) {
|
||||
unsigned int dtimper = link_conf->dtim_period ?: 1;
|
||||
unsigned int dtimper_tu = dtimper * link_conf->beacon_int;
|
||||
unsigned int skip;
|
||||
|
||||
if (dtimper >= 10 || iwl_mvm_power_is_radar(link_conf)) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
if (WARN_ON(!dtimper_tu))
|
||||
continue;
|
||||
|
||||
/* configure skip over dtim up to 900 TU DTIM interval */
|
||||
skip = max_t(int, 1, 900 / dtimper_tu);
|
||||
min_link_skip = min(min_link_skip, skip);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
/* no WARN_ON, can only happen with WARN_ON above */
|
||||
if (min_link_skip == ~0)
|
||||
return;
|
||||
|
||||
cmd->skip_dtim_periods = min_link_skip;
|
||||
cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
|
||||
}
|
||||
|
||||
|
|
@ -489,6 +497,11 @@ int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
|
|||
if (mvm->ext_clock_valid)
|
||||
cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_32K_CLK_VALID_MSK);
|
||||
|
||||
if (iwl_fw_lookup_cmd_ver(mvm->fw, POWER_TABLE_CMD, 0) >= 7 &&
|
||||
test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))
|
||||
cmd.flags |=
|
||||
cpu_to_le16(DEVICE_POWER_FLAGS_NO_SLEEP_TILL_D3_MSK);
|
||||
|
||||
IWL_DEBUG_POWER(mvm,
|
||||
"Sending device power command with flags = 0x%X\n",
|
||||
cmd.flags);
|
||||
|
|
@ -808,8 +821,7 @@ iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
|
|||
|
||||
static int _iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_beacon_filter_cmd *cmd,
|
||||
u32 cmd_flags)
|
||||
struct iwl_beacon_filter_cmd *cmd)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
int ret;
|
||||
|
|
@ -820,29 +832,27 @@ static int _iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
|
|||
|
||||
iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, cmd);
|
||||
iwl_mvm_beacon_filter_debugfs_parameters(vif, cmd);
|
||||
ret = iwl_mvm_beacon_filter_send_cmd(mvm, cmd, cmd_flags);
|
||||
ret = iwl_mvm_beacon_filter_send_cmd(mvm, cmd);
|
||||
|
||||
if (!ret)
|
||||
mvmvif->bf_data.bf_enabled = true;
|
||||
mvmvif->bf_enabled = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 flags)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_beacon_filter_cmd cmd = {
|
||||
IWL_BF_CMD_CONFIG_DEFAULTS,
|
||||
.bf_enable_beacon_filter = cpu_to_le32(1),
|
||||
};
|
||||
|
||||
return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, flags);
|
||||
return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd);
|
||||
}
|
||||
|
||||
static int _iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 flags)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_beacon_filter_cmd cmd = {};
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
|
@ -851,19 +861,18 @@ static int _iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
|
|||
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
|
||||
return 0;
|
||||
|
||||
ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, flags);
|
||||
ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
|
||||
|
||||
if (!ret)
|
||||
mvmvif->bf_data.bf_enabled = false;
|
||||
mvmvif->bf_enabled = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 flags)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
return _iwl_mvm_disable_beacon_filter(mvm, vif, flags);
|
||||
return _iwl_mvm_disable_beacon_filter(mvm, vif);
|
||||
}
|
||||
|
||||
static int iwl_mvm_power_set_ps(struct iwl_mvm *mvm)
|
||||
|
|
@ -903,18 +912,18 @@ static int iwl_mvm_power_set_ba(struct iwl_mvm *mvm,
|
|||
.bf_enable_beacon_filter = cpu_to_le32(1),
|
||||
};
|
||||
|
||||
if (!mvmvif->bf_data.bf_enabled)
|
||||
if (!mvmvif->bf_enabled)
|
||||
return 0;
|
||||
|
||||
if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))
|
||||
cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3);
|
||||
|
||||
mvmvif->bf_data.ba_enabled = !(!mvmvif->pm_enabled ||
|
||||
mvm->ps_disabled ||
|
||||
!vif->cfg.ps ||
|
||||
iwl_mvm_vif_low_latency(mvmvif));
|
||||
mvmvif->ba_enabled = !(!mvmvif->pm_enabled ||
|
||||
mvm->ps_disabled ||
|
||||
!vif->cfg.ps ||
|
||||
iwl_mvm_vif_low_latency(mvmvif));
|
||||
|
||||
return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0);
|
||||
return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd);
|
||||
}
|
||||
|
||||
int iwl_mvm_power_update_ps(struct iwl_mvm *mvm)
|
||||
|
|
|
|||
|
|
@ -132,14 +132,18 @@ struct iwl_rfi_freq_table_resp_cmd *iwl_rfi_get_freq_table(struct iwl_mvm *mvm)
|
|||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
if (WARN_ON_ONCE(iwl_rx_packet_payload_len(cmd.resp_pkt) != resp_size))
|
||||
if (WARN_ON_ONCE(iwl_rx_packet_payload_len(cmd.resp_pkt) !=
|
||||
resp_size)) {
|
||||
iwl_free_resp(&cmd);
|
||||
return ERR_PTR(-EIO);
|
||||
}
|
||||
|
||||
resp = kmemdup(cmd.resp_pkt->data, resp_size, GFP_KERNEL);
|
||||
iwl_free_resp(&cmd);
|
||||
|
||||
if (!resp)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
iwl_free_resp(&cmd);
|
||||
return resp;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2018-2024 Intel Corporation
|
||||
*/
|
||||
#include "rs.h"
|
||||
#include "fw-api.h"
|
||||
|
|
@ -479,9 +479,15 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
|
|||
}
|
||||
|
||||
if (flags & IWL_TLC_NOTIF_FLAG_AMSDU && !mvm_link_sta->orig_amsdu_len) {
|
||||
u32 enabled = le32_to_cpu(notif->amsdu_enabled);
|
||||
u16 size = le32_to_cpu(notif->amsdu_size);
|
||||
int i;
|
||||
|
||||
if (size < 2000) {
|
||||
size = 0;
|
||||
enabled = 0;
|
||||
}
|
||||
|
||||
if (link_sta->agg.max_amsdu_len < size) {
|
||||
/*
|
||||
* In debug link_sta->agg.max_amsdu_len < size
|
||||
|
|
@ -492,7 +498,7 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
|
|||
goto out;
|
||||
}
|
||||
|
||||
mvmsta->amsdu_enabled = le32_to_cpu(notif->amsdu_enabled);
|
||||
mvmsta->amsdu_enabled = enabled;
|
||||
mvmsta->max_amsdu_len = size;
|
||||
link_sta->agg.max_rc_amsdu_len = mvmsta->max_amsdu_len;
|
||||
|
||||
|
|
@ -508,6 +514,8 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
|
|||
link_sta->agg.max_tid_amsdu_len[i] = 1;
|
||||
}
|
||||
|
||||
ieee80211_sta_recalc_aggregates(sta);
|
||||
|
||||
IWL_DEBUG_RATE(mvm,
|
||||
"AMSDU update. AMSDU size: %d, AMSDU selected size: %d, AMSDU TID bitmap 0x%X\n",
|
||||
le32_to_cpu(notif->amsdu_size), size,
|
||||
|
|
@ -528,10 +536,10 @@ u16 rs_fw_get_max_amsdu_len(struct ieee80211_sta *sta,
|
|||
const struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap;
|
||||
const struct ieee80211_sta_eht_cap *eht_cap = &link_sta->eht_cap;
|
||||
|
||||
if (WARN_ON_ONCE(!link_conf->chandef.chan))
|
||||
if (WARN_ON_ONCE(!link_conf->chanreq.oper.chan))
|
||||
return IEEE80211_MAX_MPDU_LEN_VHT_3895;
|
||||
|
||||
if (link_conf->chandef.chan->band == NL80211_BAND_6GHZ) {
|
||||
if (link_conf->chanreq.oper.chan->band == NL80211_BAND_6GHZ) {
|
||||
switch (le16_get_bits(link_sta->he_6ghz_capa.capa,
|
||||
IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN)) {
|
||||
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
|
||||
|
|
@ -541,7 +549,7 @@ u16 rs_fw_get_max_amsdu_len(struct ieee80211_sta *sta,
|
|||
default:
|
||||
return IEEE80211_MAX_MPDU_LEN_VHT_3895;
|
||||
}
|
||||
} else if (link_conf->chandef.chan->band == NL80211_BAND_2GHZ &&
|
||||
} else if (link_conf->chanreq.oper.chan->band == NL80211_BAND_2GHZ &&
|
||||
eht_cap->has_eht) {
|
||||
switch (u8_get_bits(eht_cap->eht_cap_elem.mac_cap_info[0],
|
||||
IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK)) {
|
||||
|
|
@ -606,6 +614,7 @@ void iwl_mvm_rs_fw_rate_init(struct iwl_mvm *mvm,
|
|||
cpu_to_le16(max_amsdu_len) : 0,
|
||||
};
|
||||
unsigned int link_id = link_conf->link_id;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
|
||||
int cmd_ver;
|
||||
int ret;
|
||||
|
||||
|
|
@ -649,12 +658,12 @@ void iwl_mvm_rs_fw_rate_init(struct iwl_mvm *mvm,
|
|||
* since TLC offload works with one mode we can assume
|
||||
* that only vht/ht is used and also set it as station max amsdu
|
||||
*/
|
||||
sta->deflink.agg.max_amsdu_len = max_amsdu_len;
|
||||
link_sta->agg.max_amsdu_len = max_amsdu_len;
|
||||
ieee80211_sta_recalc_aggregates(sta);
|
||||
|
||||
cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
|
||||
WIDE_ID(DATA_PATH_GROUP,
|
||||
TLC_MNG_CONFIG_CMD),
|
||||
0);
|
||||
cfg_cmd.max_tx_op = cpu_to_le16(mvmvif->max_tx_op);
|
||||
|
||||
cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 0);
|
||||
IWL_DEBUG_RATE(mvm, "TLC CONFIG CMD, sta_id=%d, max_ch_width=%d, mode=%d\n",
|
||||
cfg_cmd.sta_id, cfg_cmd.max_ch_width, cfg_cmd.mode);
|
||||
IWL_DEBUG_RATE(mvm, "TLC CONFIG CMD, chains=0x%X, ch_wid_supp=%d, flags=0x%X\n",
|
||||
|
|
@ -690,9 +699,7 @@ void iwl_mvm_rs_fw_rate_init(struct iwl_mvm *mvm,
|
|||
u16 cmd_size = sizeof(cfg_cmd_v3);
|
||||
|
||||
/* In old versions of the API the struct is 4 bytes smaller */
|
||||
if (iwl_fw_lookup_cmd_ver(mvm->fw,
|
||||
WIDE_ID(DATA_PATH_GROUP,
|
||||
TLC_MNG_CONFIG_CMD), 0) < 3)
|
||||
if (iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 0) < 3)
|
||||
cmd_size -= 4;
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, CMD_ASYNC, cmd_size,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -562,39 +562,41 @@ struct iwl_mvm_stat_data {
|
|||
struct iwl_mvm_stat_data_all_macs {
|
||||
struct iwl_mvm *mvm;
|
||||
__le32 flags;
|
||||
struct iwl_statistics_ntfy_per_mac *per_mac_stats;
|
||||
struct iwl_stats_ntfy_per_mac *per_mac;
|
||||
};
|
||||
|
||||
static void iwl_mvm_update_vif_sig(struct ieee80211_vif *vif, int sig)
|
||||
static void iwl_mvm_update_link_sig(struct ieee80211_vif *vif, int sig,
|
||||
struct iwl_mvm_vif_link_info *link_info,
|
||||
struct ieee80211_bss_conf *bss_conf)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = mvmvif->mvm;
|
||||
int thold = vif->bss_conf.cqm_rssi_thold;
|
||||
int hyst = vif->bss_conf.cqm_rssi_hyst;
|
||||
struct iwl_mvm *mvm = iwl_mvm_vif_from_mac80211(vif)->mvm;
|
||||
int thold = bss_conf->cqm_rssi_thold;
|
||||
int hyst = bss_conf->cqm_rssi_hyst;
|
||||
int last_event;
|
||||
s8 exit_esr_thresh;
|
||||
|
||||
if (sig == 0) {
|
||||
IWL_DEBUG_RX(mvm, "RSSI is 0 - skip signal based decision\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mvmvif->bf_data.ave_beacon_signal = sig;
|
||||
link_info->bf_data.ave_beacon_signal = sig;
|
||||
|
||||
/* BT Coex */
|
||||
if (mvmvif->bf_data.bt_coex_min_thold !=
|
||||
mvmvif->bf_data.bt_coex_max_thold) {
|
||||
last_event = mvmvif->bf_data.last_bt_coex_event;
|
||||
if (sig > mvmvif->bf_data.bt_coex_max_thold &&
|
||||
(last_event <= mvmvif->bf_data.bt_coex_min_thold ||
|
||||
if (link_info->bf_data.bt_coex_min_thold !=
|
||||
link_info->bf_data.bt_coex_max_thold) {
|
||||
last_event = link_info->bf_data.last_bt_coex_event;
|
||||
if (sig > link_info->bf_data.bt_coex_max_thold &&
|
||||
(last_event <= link_info->bf_data.bt_coex_min_thold ||
|
||||
last_event == 0)) {
|
||||
mvmvif->bf_data.last_bt_coex_event = sig;
|
||||
link_info->bf_data.last_bt_coex_event = sig;
|
||||
IWL_DEBUG_RX(mvm, "cqm_iterator bt coex high %d\n",
|
||||
sig);
|
||||
iwl_mvm_bt_rssi_event(mvm, vif, RSSI_EVENT_HIGH);
|
||||
} else if (sig < mvmvif->bf_data.bt_coex_min_thold &&
|
||||
(last_event >= mvmvif->bf_data.bt_coex_max_thold ||
|
||||
} else if (sig < link_info->bf_data.bt_coex_min_thold &&
|
||||
(last_event >= link_info->bf_data.bt_coex_max_thold ||
|
||||
last_event == 0)) {
|
||||
mvmvif->bf_data.last_bt_coex_event = sig;
|
||||
link_info->bf_data.last_bt_coex_event = sig;
|
||||
IWL_DEBUG_RX(mvm, "cqm_iterator bt coex low %d\n",
|
||||
sig);
|
||||
iwl_mvm_bt_rssi_event(mvm, vif, RSSI_EVENT_LOW);
|
||||
|
|
@ -605,10 +607,10 @@ static void iwl_mvm_update_vif_sig(struct ieee80211_vif *vif, int sig)
|
|||
return;
|
||||
|
||||
/* CQM Notification */
|
||||
last_event = mvmvif->bf_data.last_cqm_event;
|
||||
last_event = link_info->bf_data.last_cqm_event;
|
||||
if (thold && sig < thold && (last_event == 0 ||
|
||||
sig < last_event - hyst)) {
|
||||
mvmvif->bf_data.last_cqm_event = sig;
|
||||
link_info->bf_data.last_cqm_event = sig;
|
||||
IWL_DEBUG_RX(mvm, "cqm_iterator cqm low %d\n",
|
||||
sig);
|
||||
ieee80211_cqm_rssi_notify(
|
||||
|
|
@ -618,7 +620,7 @@ static void iwl_mvm_update_vif_sig(struct ieee80211_vif *vif, int sig)
|
|||
GFP_KERNEL);
|
||||
} else if (sig > thold &&
|
||||
(last_event == 0 || sig > last_event + hyst)) {
|
||||
mvmvif->bf_data.last_cqm_event = sig;
|
||||
link_info->bf_data.last_cqm_event = sig;
|
||||
IWL_DEBUG_RX(mvm, "cqm_iterator cqm high %d\n",
|
||||
sig);
|
||||
ieee80211_cqm_rssi_notify(
|
||||
|
|
@ -627,6 +629,20 @@ static void iwl_mvm_update_vif_sig(struct ieee80211_vif *vif, int sig)
|
|||
sig,
|
||||
GFP_KERNEL);
|
||||
}
|
||||
|
||||
/* ESR recalculation */
|
||||
if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif))
|
||||
return;
|
||||
|
||||
exit_esr_thresh =
|
||||
iwl_mvm_get_esr_rssi_thresh(mvm,
|
||||
&bss_conf->chanreq.oper,
|
||||
true);
|
||||
|
||||
if (sig < exit_esr_thresh)
|
||||
iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_LOW_RSSI,
|
||||
iwl_mvm_get_other_link(vif,
|
||||
bss_conf->link_id));
|
||||
}
|
||||
|
||||
static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
|
||||
|
|
@ -660,14 +676,15 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
|
|||
mvmvif->deflink.beacon_stats.accu_num_beacons +=
|
||||
mvmvif->deflink.beacon_stats.num_beacons;
|
||||
|
||||
iwl_mvm_update_vif_sig(vif, sig);
|
||||
/* This is used in pre-MLO API so use deflink */
|
||||
iwl_mvm_update_link_sig(vif, sig, &mvmvif->deflink, &vif->bss_conf);
|
||||
}
|
||||
|
||||
static void iwl_mvm_stat_iterator_all_macs(void *_data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_stat_data_all_macs *data = _data;
|
||||
struct iwl_statistics_ntfy_per_mac *mac_stats;
|
||||
struct iwl_stats_ntfy_per_mac *mac_stats;
|
||||
int sig;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
u16 vif_id = mvmvif->id;
|
||||
|
|
@ -678,7 +695,7 @@ static void iwl_mvm_stat_iterator_all_macs(void *_data, u8 *mac,
|
|||
if (vif->type != NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
mac_stats = &data->per_mac_stats[vif_id];
|
||||
mac_stats = &data->per_mac[vif_id];
|
||||
|
||||
mvmvif->deflink.beacon_stats.num_beacons =
|
||||
le32_to_cpu(mac_stats->beacon_counter);
|
||||
|
|
@ -693,7 +710,9 @@ static void iwl_mvm_stat_iterator_all_macs(void *_data, u8 *mac,
|
|||
mvmvif->deflink.beacon_stats.num_beacons;
|
||||
|
||||
sig = -le32_to_cpu(mac_stats->beacon_filter_average_energy);
|
||||
iwl_mvm_update_vif_sig(vif, sig);
|
||||
|
||||
/* This is used in pre-MLO API so use deflink */
|
||||
iwl_mvm_update_link_sig(vif, sig, &mvmvif->deflink, &vif->bss_conf);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -765,6 +784,19 @@ iwl_mvm_update_tcm_from_stats(struct iwl_mvm *mvm, __le32 *air_time_le,
|
|||
spin_unlock(&mvm->tcm.lock);
|
||||
}
|
||||
|
||||
static void iwl_mvm_handle_per_phy_stats(struct iwl_mvm *mvm,
|
||||
struct iwl_stats_ntfy_per_phy *per_phy)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_PHY_CTX; i++) {
|
||||
if (!mvm->phy_ctxts[i].ref)
|
||||
continue;
|
||||
mvm->phy_ctxts[i].channel_load_by_us =
|
||||
le32_to_cpu(per_phy[i].channel_load_by_us);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mvm_stats_ver_15(struct iwl_mvm *mvm,
|
||||
struct iwl_statistics_operational_ntfy *stats)
|
||||
|
|
@ -772,13 +804,14 @@ iwl_mvm_stats_ver_15(struct iwl_mvm *mvm,
|
|||
struct iwl_mvm_stat_data_all_macs data = {
|
||||
.mvm = mvm,
|
||||
.flags = stats->flags,
|
||||
.per_mac_stats = stats->per_mac_stats,
|
||||
.per_mac = stats->per_mac,
|
||||
};
|
||||
|
||||
ieee80211_iterate_active_interfaces(mvm->hw,
|
||||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
iwl_mvm_stat_iterator_all_macs,
|
||||
&data);
|
||||
iwl_mvm_handle_per_phy_stats(mvm, stats->per_phy);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -841,6 +874,239 @@ static bool iwl_mvm_verify_stats_len(struct iwl_mvm *mvm,
|
|||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm,
|
||||
struct iwl_stats_ntfy_per_link *per_link)
|
||||
{
|
||||
u32 air_time[MAC_INDEX_AUX] = {};
|
||||
u32 rx_bytes[MAC_INDEX_AUX] = {};
|
||||
int fw_link_id;
|
||||
|
||||
for (fw_link_id = 0; fw_link_id < ARRAY_SIZE(mvm->link_id_to_link_conf);
|
||||
fw_link_id++) {
|
||||
struct iwl_stats_ntfy_per_link *link_stats;
|
||||
struct ieee80211_bss_conf *bss_conf;
|
||||
struct iwl_mvm_vif *mvmvif;
|
||||
struct iwl_mvm_vif_link_info *link_info;
|
||||
int link_id;
|
||||
int sig;
|
||||
|
||||
bss_conf = iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, fw_link_id,
|
||||
false);
|
||||
if (!bss_conf)
|
||||
continue;
|
||||
|
||||
if (bss_conf->vif->type != NL80211_IFTYPE_STATION)
|
||||
continue;
|
||||
|
||||
link_id = bss_conf->link_id;
|
||||
if (link_id >= ARRAY_SIZE(mvmvif->link))
|
||||
continue;
|
||||
|
||||
mvmvif = iwl_mvm_vif_from_mac80211(bss_conf->vif);
|
||||
link_info = mvmvif->link[link_id];
|
||||
if (!link_info)
|
||||
continue;
|
||||
|
||||
link_stats = &per_link[fw_link_id];
|
||||
|
||||
link_info->beacon_stats.num_beacons =
|
||||
le32_to_cpu(link_stats->beacon_counter);
|
||||
|
||||
/* we basically just use the u8 to store 8 bits and then treat
|
||||
* it as a s8 whenever we take it out to a different type.
|
||||
*/
|
||||
link_info->beacon_stats.avg_signal =
|
||||
-le32_to_cpu(link_stats->beacon_average_energy);
|
||||
|
||||
if (link_info->phy_ctxt &&
|
||||
link_info->phy_ctxt->channel->band == NL80211_BAND_2GHZ)
|
||||
iwl_mvm_bt_coex_update_link_esr(mvm, bss_conf->vif,
|
||||
link_id);
|
||||
|
||||
/* make sure that beacon statistics don't go backwards with TCM
|
||||
* request to clear statistics
|
||||
*/
|
||||
if (mvm->statistics_clear)
|
||||
mvmvif->link[link_id]->beacon_stats.accu_num_beacons +=
|
||||
mvmvif->link[link_id]->beacon_stats.num_beacons;
|
||||
|
||||
sig = -le32_to_cpu(link_stats->beacon_filter_average_energy);
|
||||
iwl_mvm_update_link_sig(bss_conf->vif, sig, link_info,
|
||||
bss_conf);
|
||||
|
||||
if (WARN_ONCE(mvmvif->id >= MAC_INDEX_AUX,
|
||||
"invalid mvmvif id: %d", mvmvif->id))
|
||||
continue;
|
||||
|
||||
air_time[mvmvif->id] +=
|
||||
le32_to_cpu(per_link[fw_link_id].air_time);
|
||||
rx_bytes[mvmvif->id] +=
|
||||
le32_to_cpu(per_link[fw_link_id].rx_bytes);
|
||||
}
|
||||
|
||||
/* Don't update in case the statistics are not cleared, since
|
||||
* we will end up counting twice the same airtime, once in TCM
|
||||
* request and once in statistics notification.
|
||||
*/
|
||||
if (mvm->statistics_clear) {
|
||||
__le32 air_time_le[MAC_INDEX_AUX];
|
||||
__le32 rx_bytes_le[MAC_INDEX_AUX];
|
||||
int vif_id;
|
||||
|
||||
for (vif_id = 0; vif_id < ARRAY_SIZE(air_time_le); vif_id++) {
|
||||
air_time_le[vif_id] = cpu_to_le32(air_time[vif_id]);
|
||||
rx_bytes_le[vif_id] = cpu_to_le32(rx_bytes[vif_id]);
|
||||
}
|
||||
|
||||
iwl_mvm_update_tcm_from_stats(mvm, air_time_le, rx_bytes_le);
|
||||
}
|
||||
}
|
||||
|
||||
#define SEC_LINK_MIN_PERC 10
|
||||
#define SEC_LINK_MIN_TX 3000
|
||||
#define SEC_LINK_MIN_RX 400
|
||||
|
||||
static void iwl_mvm_update_esr_mode_tpt(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm);
|
||||
struct iwl_mvm_vif *mvmvif;
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
unsigned long total_tx = 0, total_rx = 0;
|
||||
unsigned long sec_link_tx = 0, sec_link_rx = 0;
|
||||
u8 sec_link_tx_perc, sec_link_rx_perc;
|
||||
u8 sec_link;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (IS_ERR_OR_NULL(bss_vif))
|
||||
return;
|
||||
|
||||
mvmvif = iwl_mvm_vif_from_mac80211(bss_vif);
|
||||
|
||||
if (!mvmvif->esr_active || !mvmvif->ap_sta)
|
||||
return;
|
||||
|
||||
mvmsta = iwl_mvm_sta_from_mac80211(mvmvif->ap_sta);
|
||||
/* We only count for the AP sta in a MLO connection */
|
||||
if (!mvmsta->mpdu_counters)
|
||||
return;
|
||||
|
||||
/* Get the FW ID of the secondary link */
|
||||
sec_link = iwl_mvm_get_other_link(bss_vif,
|
||||
iwl_mvm_get_primary_link(bss_vif));
|
||||
if (WARN_ON(!mvmvif->link[sec_link]))
|
||||
return;
|
||||
sec_link = mvmvif->link[sec_link]->fw_link_id;
|
||||
|
||||
/* Sum up RX and TX MPDUs from the different queues/links */
|
||||
for (int q = 0; q < mvm->trans->num_rx_queues; q++) {
|
||||
spin_lock_bh(&mvmsta->mpdu_counters[q].lock);
|
||||
|
||||
/* The link IDs that doesn't exist will contain 0 */
|
||||
for (int link = 0; link < IWL_MVM_FW_MAX_LINK_ID; link++) {
|
||||
total_tx += mvmsta->mpdu_counters[q].per_link[link].tx;
|
||||
total_rx += mvmsta->mpdu_counters[q].per_link[link].rx;
|
||||
}
|
||||
|
||||
sec_link_tx += mvmsta->mpdu_counters[q].per_link[sec_link].tx;
|
||||
sec_link_rx += mvmsta->mpdu_counters[q].per_link[sec_link].rx;
|
||||
|
||||
/*
|
||||
* In EMLSR we have statistics every 5 seconds, so we can reset
|
||||
* the counters upon every statistics notification.
|
||||
*/
|
||||
memset(mvmsta->mpdu_counters[q].per_link, 0,
|
||||
sizeof(mvmsta->mpdu_counters[q].per_link));
|
||||
|
||||
spin_unlock_bh(&mvmsta->mpdu_counters[q].lock);
|
||||
}
|
||||
|
||||
IWL_DEBUG_STATS(mvm, "total Tx MPDUs: %ld. total Rx MPDUs: %ld\n",
|
||||
total_tx, total_rx);
|
||||
|
||||
/* If we don't have enough MPDUs - exit EMLSR */
|
||||
if (total_tx < IWL_MVM_ENTER_ESR_TPT_THRESH &&
|
||||
total_rx < IWL_MVM_ENTER_ESR_TPT_THRESH) {
|
||||
iwl_mvm_block_esr(mvm, bss_vif, IWL_MVM_ESR_BLOCKED_TPT,
|
||||
iwl_mvm_get_primary_link(bss_vif));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Calculate the percentage of the secondary link TX/RX */
|
||||
sec_link_tx_perc = total_tx ? sec_link_tx * 100 / total_tx : 0;
|
||||
sec_link_rx_perc = total_rx ? sec_link_rx * 100 / total_rx : 0;
|
||||
|
||||
/*
|
||||
* The TX/RX percentage is checked only if it exceeds the required
|
||||
* minimum. In addition, RX is checked only if the TX check failed.
|
||||
*/
|
||||
if ((total_tx > SEC_LINK_MIN_TX &&
|
||||
sec_link_tx_perc < SEC_LINK_MIN_PERC) ||
|
||||
(total_rx > SEC_LINK_MIN_RX &&
|
||||
sec_link_rx_perc < SEC_LINK_MIN_PERC))
|
||||
iwl_mvm_exit_esr(mvm, bss_vif, IWL_MVM_ESR_EXIT_LINK_USAGE,
|
||||
iwl_mvm_get_primary_link(bss_vif));
|
||||
}
|
||||
|
||||
void iwl_mvm_handle_rx_system_oper_stats(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
u8 average_energy[IWL_MVM_STATION_COUNT_MAX];
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_system_statistics_notif_oper *stats;
|
||||
int i;
|
||||
u32 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, STATISTICS_GROUP,
|
||||
STATISTICS_OPER_NOTIF, 0);
|
||||
|
||||
if (notif_ver != 3) {
|
||||
IWL_FW_CHECK_FAILED(mvm,
|
||||
"Oper stats notif ver %d is not supported\n",
|
||||
notif_ver);
|
||||
return;
|
||||
}
|
||||
|
||||
stats = (void *)&pkt->data;
|
||||
iwl_mvm_stat_iterator_all_links(mvm, stats->per_link);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(average_energy); i++)
|
||||
average_energy[i] =
|
||||
le32_to_cpu(stats->per_sta[i].average_energy);
|
||||
|
||||
ieee80211_iterate_stations_atomic(mvm->hw, iwl_mvm_stats_energy_iter,
|
||||
average_energy);
|
||||
iwl_mvm_handle_per_phy_stats(mvm, stats->per_phy);
|
||||
|
||||
iwl_mvm_update_esr_mode_tpt(mvm);
|
||||
}
|
||||
|
||||
void iwl_mvm_handle_rx_system_oper_part1_stats(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_system_statistics_part1_notif_oper *part1_stats;
|
||||
int i;
|
||||
u32 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, STATISTICS_GROUP,
|
||||
STATISTICS_OPER_PART1_NOTIF, 0);
|
||||
|
||||
if (notif_ver != 4) {
|
||||
IWL_FW_CHECK_FAILED(mvm,
|
||||
"Part1 stats notif ver %d is not supported\n",
|
||||
notif_ver);
|
||||
return;
|
||||
}
|
||||
|
||||
part1_stats = (void *)&pkt->data;
|
||||
mvm->radio_stats.rx_time = 0;
|
||||
mvm->radio_stats.tx_time = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(part1_stats->per_link); i++) {
|
||||
mvm->radio_stats.rx_time +=
|
||||
le64_to_cpu(part1_stats->per_link[i].rx_time);
|
||||
mvm->radio_stats.tx_time +=
|
||||
le64_to_cpu(part1_stats->per_link[i].tx_time);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mvm_handle_rx_statistics_tlv(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_packet *pkt)
|
||||
|
|
@ -900,11 +1166,11 @@ iwl_mvm_handle_rx_statistics_tlv(struct iwl_mvm *mvm,
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(average_energy); i++)
|
||||
average_energy[i] =
|
||||
le32_to_cpu(stats->per_sta_stats[i].average_energy);
|
||||
le32_to_cpu(stats->per_sta[i].average_energy);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(air_time); i++) {
|
||||
air_time[i] = stats->per_mac_stats[i].air_time;
|
||||
rx_bytes[i] = stats->per_mac_stats[i].rx_bytes;
|
||||
air_time[i] = stats->per_mac[i].air_time;
|
||||
rx_bytes[i] = stats->per_mac[i].rx_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -930,6 +1196,13 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
|
|||
__le32 *bytes, *air_time, flags;
|
||||
int expected_size;
|
||||
u8 *energy;
|
||||
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
|
||||
WIDE_ID(SYSTEM_GROUP,
|
||||
SYSTEM_STATISTICS_CMD),
|
||||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
|
||||
if (cmd_ver != IWL_FW_CMD_VER_UNKNOWN)
|
||||
return;
|
||||
|
||||
/* From ver 14 and up we use TLV statistics format */
|
||||
if (iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -239,21 +239,13 @@ static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm,
|
|||
static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
|
||||
struct napi_struct *napi,
|
||||
struct sk_buff *skb, int queue,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_link_sta *link_sta)
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
if (unlikely(iwl_mvm_check_pn(mvm, skb, queue, sta))) {
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sta && sta->valid_links && link_sta) {
|
||||
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
|
||||
rx_status->link_valid = 1;
|
||||
rx_status->link_id = link_sta->link_id;
|
||||
}
|
||||
|
||||
ieee80211_rx_napi(mvm->hw, sta, skb, napi);
|
||||
}
|
||||
|
||||
|
|
@ -285,6 +277,7 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
|
|||
u32 status,
|
||||
struct ieee80211_rx_status *stats)
|
||||
{
|
||||
struct wireless_dev *wdev;
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
struct iwl_mvm_vif *mvmvif;
|
||||
u8 keyid;
|
||||
|
|
@ -306,9 +299,15 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
|
|||
if (!ieee80211_is_beacon(hdr->frame_control))
|
||||
return 0;
|
||||
|
||||
if (!sta)
|
||||
return -1;
|
||||
|
||||
mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
|
||||
|
||||
/* key mismatch - will also report !MIC_OK but we shouldn't count it */
|
||||
if (!(status & IWL_RX_MPDU_STATUS_KEY_VALID))
|
||||
return -1;
|
||||
goto report;
|
||||
|
||||
/* good cases */
|
||||
if (likely(status & IWL_RX_MPDU_STATUS_MIC_OK &&
|
||||
|
|
@ -317,13 +316,6 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!sta)
|
||||
return -1;
|
||||
|
||||
mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
|
||||
mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
|
||||
|
||||
/*
|
||||
* both keys will have the same cipher and MIC length, use
|
||||
* whichever one is available
|
||||
|
|
@ -332,11 +324,11 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
|
|||
if (!key) {
|
||||
key = rcu_dereference(mvmvif->bcn_prot.keys[1]);
|
||||
if (!key)
|
||||
return -1;
|
||||
goto report;
|
||||
}
|
||||
|
||||
if (len < key->icv_len + IEEE80211_GMAC_PN_LEN + 2)
|
||||
return -1;
|
||||
goto report;
|
||||
|
||||
/* get the real key ID */
|
||||
keyid = frame[len - key->icv_len - IEEE80211_GMAC_PN_LEN - 2];
|
||||
|
|
@ -350,7 +342,7 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
|
|||
return -1;
|
||||
key = rcu_dereference(mvmvif->bcn_prot.keys[keyid - 6]);
|
||||
if (!key)
|
||||
return -1;
|
||||
goto report;
|
||||
}
|
||||
|
||||
/* Report status to mac80211 */
|
||||
|
|
@ -358,6 +350,10 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
|
|||
ieee80211_key_mic_failure(key);
|
||||
else if (status & IWL_RX_MPDU_STATUS_REPLAY_ERROR)
|
||||
ieee80211_key_replay(key);
|
||||
report:
|
||||
wdev = ieee80211_vif_to_wdev(mvmsta->vif);
|
||||
if (wdev->netdev)
|
||||
cfg80211_rx_unprot_mlme_mgmt(wdev->netdev, (void *)hdr, len);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -379,8 +375,10 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|||
*/
|
||||
if (phy_info & IWL_RX_MPDU_PHY_AMPDU &&
|
||||
(status & IWL_RX_MPDU_STATUS_SEC_MASK) ==
|
||||
IWL_RX_MPDU_STATUS_SEC_UNKNOWN && !mvm->monitor_on)
|
||||
IWL_RX_MPDU_STATUS_SEC_UNKNOWN && !mvm->monitor_on) {
|
||||
IWL_DEBUG_DROP(mvm, "Dropping packets, bad enc status\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (unlikely(ieee80211_is_mgmt(hdr->frame_control) &&
|
||||
!ieee80211_has_protected(hdr->frame_control)))
|
||||
|
|
@ -404,8 +402,11 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|||
case IWL_RX_MPDU_STATUS_SEC_GCM:
|
||||
BUILD_BUG_ON(IEEE80211_CCMP_PN_LEN != IEEE80211_GCMP_PN_LEN);
|
||||
/* alg is CCM: check MIC only */
|
||||
if (!(status & IWL_RX_MPDU_STATUS_MIC_OK))
|
||||
if (!(status & IWL_RX_MPDU_STATUS_MIC_OK)) {
|
||||
IWL_DEBUG_DROP(mvm,
|
||||
"Dropping packet, bad MIC (CCM/GCM)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
stats->flag |= RX_FLAG_DECRYPTED | RX_FLAG_MIC_STRIPPED;
|
||||
*crypt_len = IEEE80211_CCMP_HDR_LEN;
|
||||
|
|
@ -516,10 +517,10 @@ static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue,
|
|||
return false;
|
||||
|
||||
mvm_sta = iwl_mvm_sta_from_mac80211(sta);
|
||||
#if defined(__FreeBSD__)
|
||||
if (WARN_ON(mvm_sta->dup_data == NULL))
|
||||
|
||||
if (WARN_ON_ONCE(!mvm_sta->dup_data))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
dup_data = &mvm_sta->dup_data[queue];
|
||||
|
||||
/*
|
||||
|
|
@ -527,11 +528,9 @@ static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue,
|
|||
* (IEEE 802.11-2012: 9.3.2.10 "Duplicate detection and recovery")
|
||||
*/
|
||||
if (ieee80211_is_ctl(hdr->frame_control) ||
|
||||
ieee80211_is_qos_nullfunc(hdr->frame_control) ||
|
||||
is_multicast_ether_addr(hdr->addr1)) {
|
||||
rx_status->flag |= RX_FLAG_DUP_VALIDATED;
|
||||
ieee80211_is_any_nullfunc(hdr->frame_control) ||
|
||||
is_multicast_ether_addr(hdr->addr1))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
/* frame has qos control */
|
||||
|
|
@ -565,44 +564,12 @@ static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue,
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if sn2 - buffer_size < sn1 < sn2.
|
||||
* To be used only in order to compare reorder buffer head with NSSN.
|
||||
* We fully trust NSSN unless it is behind us due to reorder timeout.
|
||||
* Reorder timeout can only bring us up to buffer_size SNs ahead of NSSN.
|
||||
*/
|
||||
static bool iwl_mvm_is_sn_less(u16 sn1, u16 sn2, u16 buffer_size)
|
||||
{
|
||||
return ieee80211_sn_less(sn1, sn2) &&
|
||||
!ieee80211_sn_less(sn1, sn2 - buffer_size);
|
||||
}
|
||||
|
||||
static void iwl_mvm_sync_nssn(struct iwl_mvm *mvm, u8 baid, u16 nssn)
|
||||
{
|
||||
if (IWL_MVM_USE_NSSN_SYNC) {
|
||||
struct iwl_mvm_nssn_sync_data notif = {
|
||||
.baid = baid,
|
||||
.nssn = nssn,
|
||||
};
|
||||
|
||||
iwl_mvm_sync_rx_queues_internal(mvm, IWL_MVM_RXQ_NSSN_SYNC, false,
|
||||
¬if, sizeof(notif));
|
||||
}
|
||||
}
|
||||
|
||||
#define RX_REORDER_BUF_TIMEOUT_MQ (HZ / 10)
|
||||
|
||||
enum iwl_mvm_release_flags {
|
||||
IWL_MVM_RELEASE_SEND_RSS_SYNC = BIT(0),
|
||||
IWL_MVM_RELEASE_FROM_RSS_SYNC = BIT(1),
|
||||
};
|
||||
|
||||
static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
|
||||
struct ieee80211_sta *sta,
|
||||
struct napi_struct *napi,
|
||||
struct iwl_mvm_baid_data *baid_data,
|
||||
struct iwl_mvm_reorder_buffer *reorder_buf,
|
||||
u16 nssn, u32 flags)
|
||||
u16 nssn)
|
||||
{
|
||||
struct iwl_mvm_reorder_buf_entry *entries =
|
||||
&baid_data->entries[reorder_buf->queue *
|
||||
|
|
@ -611,31 +578,12 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
|
|||
|
||||
lockdep_assert_held(&reorder_buf->lock);
|
||||
|
||||
/*
|
||||
* We keep the NSSN not too far behind, if we are sync'ing it and it
|
||||
* is more than 2048 ahead of us, it must be behind us. Discard it.
|
||||
* This can happen if the queue that hit the 0 / 2048 seqno was lagging
|
||||
* behind and this queue already processed packets. The next if
|
||||
* would have caught cases where this queue would have processed less
|
||||
* than 64 packets, but it may have processed more than 64 packets.
|
||||
*/
|
||||
if ((flags & IWL_MVM_RELEASE_FROM_RSS_SYNC) &&
|
||||
ieee80211_sn_less(nssn, ssn))
|
||||
goto set_timer;
|
||||
|
||||
/* ignore nssn smaller than head sn - this can happen due to timeout */
|
||||
if (iwl_mvm_is_sn_less(nssn, ssn, reorder_buf->buf_size))
|
||||
goto set_timer;
|
||||
|
||||
while (iwl_mvm_is_sn_less(ssn, nssn, reorder_buf->buf_size)) {
|
||||
int index = ssn % reorder_buf->buf_size;
|
||||
struct sk_buff_head *skb_list = &entries[index].e.frames;
|
||||
while (ieee80211_sn_less(ssn, nssn)) {
|
||||
int index = ssn % baid_data->buf_size;
|
||||
struct sk_buff_head *skb_list = &entries[index].frames;
|
||||
struct sk_buff *skb;
|
||||
|
||||
ssn = ieee80211_sn_inc(ssn);
|
||||
if ((flags & IWL_MVM_RELEASE_SEND_RSS_SYNC) &&
|
||||
(ssn == 2048 || ssn == 0))
|
||||
iwl_mvm_sync_nssn(mvm, baid_data->baid, ssn);
|
||||
|
||||
/*
|
||||
* Empty the list. Will have more than one frame for A-MSDU.
|
||||
|
|
@ -645,104 +593,11 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
|
|||
while ((skb = __skb_dequeue(skb_list))) {
|
||||
iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb,
|
||||
reorder_buf->queue,
|
||||
sta, NULL /* FIXME */);
|
||||
sta);
|
||||
reorder_buf->num_stored--;
|
||||
}
|
||||
}
|
||||
reorder_buf->head_sn = nssn;
|
||||
|
||||
set_timer:
|
||||
if (reorder_buf->num_stored && !reorder_buf->removed) {
|
||||
u16 index = reorder_buf->head_sn % reorder_buf->buf_size;
|
||||
|
||||
while (skb_queue_empty(&entries[index].e.frames))
|
||||
index = (index + 1) % reorder_buf->buf_size;
|
||||
/* modify timer to match next frame's expiration time */
|
||||
mod_timer(&reorder_buf->reorder_timer,
|
||||
entries[index].e.reorder_time + 1 +
|
||||
RX_REORDER_BUF_TIMEOUT_MQ);
|
||||
} else {
|
||||
del_timer(&reorder_buf->reorder_timer);
|
||||
}
|
||||
}
|
||||
|
||||
void iwl_mvm_reorder_timer_expired(struct timer_list *t)
|
||||
{
|
||||
struct iwl_mvm_reorder_buffer *buf = from_timer(buf, t, reorder_timer);
|
||||
struct iwl_mvm_baid_data *baid_data =
|
||||
iwl_mvm_baid_data_from_reorder_buf(buf);
|
||||
struct iwl_mvm_reorder_buf_entry *entries =
|
||||
&baid_data->entries[buf->queue * baid_data->entries_per_queue];
|
||||
int i;
|
||||
u16 sn = 0, index = 0;
|
||||
bool expired = false;
|
||||
bool cont = false;
|
||||
|
||||
spin_lock(&buf->lock);
|
||||
|
||||
if (!buf->num_stored || buf->removed) {
|
||||
spin_unlock(&buf->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < buf->buf_size ; i++) {
|
||||
index = (buf->head_sn + i) % buf->buf_size;
|
||||
|
||||
if (skb_queue_empty(&entries[index].e.frames)) {
|
||||
/*
|
||||
* If there is a hole and the next frame didn't expire
|
||||
* we want to break and not advance SN
|
||||
*/
|
||||
cont = false;
|
||||
continue;
|
||||
}
|
||||
if (!cont &&
|
||||
!time_after(jiffies, entries[index].e.reorder_time +
|
||||
RX_REORDER_BUF_TIMEOUT_MQ))
|
||||
break;
|
||||
|
||||
expired = true;
|
||||
/* continue until next hole after this expired frames */
|
||||
cont = true;
|
||||
sn = ieee80211_sn_add(buf->head_sn, i + 1);
|
||||
}
|
||||
|
||||
if (expired) {
|
||||
struct ieee80211_sta *sta;
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
u8 sta_id = ffs(baid_data->sta_mask) - 1;
|
||||
|
||||
rcu_read_lock();
|
||||
sta = rcu_dereference(buf->mvm->fw_id_to_mac_id[sta_id]);
|
||||
if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta))) {
|
||||
rcu_read_unlock();
|
||||
goto out;
|
||||
}
|
||||
|
||||
mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
|
||||
/* SN is set to the last expired frame + 1 */
|
||||
IWL_DEBUG_HT(buf->mvm,
|
||||
"Releasing expired frames for sta %u, sn %d\n",
|
||||
sta_id, sn);
|
||||
iwl_mvm_event_frame_timeout_callback(buf->mvm, mvmsta->vif,
|
||||
sta, baid_data->tid);
|
||||
iwl_mvm_release_frames(buf->mvm, sta, NULL, baid_data,
|
||||
buf, sn, IWL_MVM_RELEASE_SEND_RSS_SYNC);
|
||||
rcu_read_unlock();
|
||||
} else {
|
||||
/*
|
||||
* If no frame expired and there are stored frames, index is now
|
||||
* pointing to the first unexpired frame - modify timer
|
||||
* accordingly to this frame.
|
||||
*/
|
||||
mod_timer(&buf->reorder_timer,
|
||||
entries[index].e.reorder_time +
|
||||
1 + RX_REORDER_BUF_TIMEOUT_MQ);
|
||||
}
|
||||
|
||||
out:
|
||||
spin_unlock(&buf->lock);
|
||||
}
|
||||
|
||||
static void iwl_mvm_del_ba(struct iwl_mvm *mvm, int queue,
|
||||
|
|
@ -775,10 +630,8 @@ static void iwl_mvm_del_ba(struct iwl_mvm *mvm, int queue,
|
|||
spin_lock_bh(&reorder_buf->lock);
|
||||
iwl_mvm_release_frames(mvm, sta, NULL, ba_data, reorder_buf,
|
||||
ieee80211_sn_add(reorder_buf->head_sn,
|
||||
reorder_buf->buf_size),
|
||||
0);
|
||||
ba_data->buf_size));
|
||||
spin_unlock_bh(&reorder_buf->lock);
|
||||
del_timer_sync(&reorder_buf->reorder_timer);
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
|
|
@ -786,8 +639,7 @@ out:
|
|||
|
||||
static void iwl_mvm_release_frames_from_notif(struct iwl_mvm *mvm,
|
||||
struct napi_struct *napi,
|
||||
u8 baid, u16 nssn, int queue,
|
||||
u32 flags)
|
||||
u8 baid, u16 nssn, int queue)
|
||||
{
|
||||
struct ieee80211_sta *sta;
|
||||
struct iwl_mvm_reorder_buffer *reorder_buf;
|
||||
|
|
@ -804,11 +656,8 @@ static void iwl_mvm_release_frames_from_notif(struct iwl_mvm *mvm,
|
|||
rcu_read_lock();
|
||||
|
||||
ba_data = rcu_dereference(mvm->baid_map[baid]);
|
||||
if (!ba_data) {
|
||||
WARN(!(flags & IWL_MVM_RELEASE_FROM_RSS_SYNC),
|
||||
"BAID %d not found in map\n", baid);
|
||||
if (WARN(!ba_data, "BAID %d not found in map\n", baid))
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* pick any STA ID to find the pointer */
|
||||
sta_id = ffs(ba_data->sta_mask) - 1;
|
||||
|
|
@ -820,22 +669,13 @@ static void iwl_mvm_release_frames_from_notif(struct iwl_mvm *mvm,
|
|||
|
||||
spin_lock_bh(&reorder_buf->lock);
|
||||
iwl_mvm_release_frames(mvm, sta, napi, ba_data,
|
||||
reorder_buf, nssn, flags);
|
||||
reorder_buf, nssn);
|
||||
spin_unlock_bh(&reorder_buf->lock);
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void iwl_mvm_nssn_sync(struct iwl_mvm *mvm,
|
||||
struct napi_struct *napi, int queue,
|
||||
const struct iwl_mvm_nssn_sync_data *data)
|
||||
{
|
||||
iwl_mvm_release_frames_from_notif(mvm, napi, data->baid,
|
||||
data->nssn, queue,
|
||||
IWL_MVM_RELEASE_FROM_RSS_SYNC);
|
||||
}
|
||||
|
||||
void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||
struct iwl_rx_cmd_buffer *rxb, int queue)
|
||||
{
|
||||
|
|
@ -853,11 +693,11 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
return;
|
||||
len -= sizeof(*notif) + sizeof(*internal_notif);
|
||||
|
||||
if (internal_notif->sync &&
|
||||
mvm->queue_sync_cookie != internal_notif->cookie) {
|
||||
WARN_ONCE(1, "Received expired RX queue sync message\n");
|
||||
if (WARN_ONCE(internal_notif->sync &&
|
||||
mvm->queue_sync_cookie != internal_notif->cookie,
|
||||
"Received expired RX queue sync message (cookie %d but wanted %d, queue %d)\n",
|
||||
internal_notif->cookie, mvm->queue_sync_cookie, queue))
|
||||
return;
|
||||
}
|
||||
|
||||
switch (internal_notif->type) {
|
||||
case IWL_MVM_RXQ_EMPTY:
|
||||
|
|
@ -870,14 +710,6 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
break;
|
||||
iwl_mvm_del_ba(mvm, queue, (void *)internal_notif->data);
|
||||
break;
|
||||
case IWL_MVM_RXQ_NSSN_SYNC:
|
||||
if (WARN_ONCE(len != sizeof(struct iwl_mvm_nssn_sync_data),
|
||||
"invalid nssn sync notification size %d (%d)",
|
||||
len, (int)sizeof(struct iwl_mvm_nssn_sync_data)))
|
||||
break;
|
||||
iwl_mvm_nssn_sync(mvm, napi, queue,
|
||||
(void *)internal_notif->data);
|
||||
break;
|
||||
default:
|
||||
WARN_ONCE(1, "Invalid identifier %d", internal_notif->type);
|
||||
}
|
||||
|
|
@ -891,55 +723,6 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_oldsn_workaround(struct iwl_mvm *mvm,
|
||||
struct ieee80211_sta *sta, int tid,
|
||||
struct iwl_mvm_reorder_buffer *buffer,
|
||||
u32 reorder, u32 gp2, int queue)
|
||||
{
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
|
||||
if (gp2 != buffer->consec_oldsn_ampdu_gp2) {
|
||||
/* we have a new (A-)MPDU ... */
|
||||
|
||||
/*
|
||||
* reset counter to 0 if we didn't have any oldsn in
|
||||
* the last A-MPDU (as detected by GP2 being identical)
|
||||
*/
|
||||
if (!buffer->consec_oldsn_prev_drop)
|
||||
buffer->consec_oldsn_drops = 0;
|
||||
|
||||
/* either way, update our tracking state */
|
||||
buffer->consec_oldsn_ampdu_gp2 = gp2;
|
||||
} else if (buffer->consec_oldsn_prev_drop) {
|
||||
/*
|
||||
* tracking state didn't change, and we had an old SN
|
||||
* indication before - do nothing in this case, we
|
||||
* already noted this one down and are waiting for the
|
||||
* next A-MPDU (by GP2)
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
/* return unless this MPDU has old SN */
|
||||
if (!(reorder & IWL_RX_MPDU_REORDER_BA_OLD_SN))
|
||||
return;
|
||||
|
||||
/* update state */
|
||||
buffer->consec_oldsn_prev_drop = 1;
|
||||
buffer->consec_oldsn_drops++;
|
||||
|
||||
/* if limit is reached, send del BA and reset state */
|
||||
if (buffer->consec_oldsn_drops == IWL_MVM_AMPDU_CONSEC_DROPS_DELBA) {
|
||||
IWL_WARN(mvm,
|
||||
"reached %d old SN frames from %pM on queue %d, stopping BA session on TID %d\n",
|
||||
IWL_MVM_AMPDU_CONSEC_DROPS_DELBA,
|
||||
sta->addr, queue, tid);
|
||||
ieee80211_stop_rx_ba_session(mvmsta->vif, BIT(tid), sta->addr);
|
||||
buffer->consec_oldsn_prev_drop = 0;
|
||||
buffer->consec_oldsn_drops = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the MPDU was buffered\dropped, false if it should be passed
|
||||
* to upper layer.
|
||||
|
|
@ -951,11 +734,9 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
|||
struct sk_buff *skb,
|
||||
struct iwl_rx_mpdu_desc *desc)
|
||||
{
|
||||
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
struct ieee80211_hdr *hdr = (void *)skb_mac_header(skb);
|
||||
struct iwl_mvm_baid_data *baid_data;
|
||||
struct iwl_mvm_reorder_buffer *buffer;
|
||||
struct sk_buff *tail;
|
||||
u32 reorder = le32_to_cpu(desc->reorder_data);
|
||||
bool amsdu = desc->mac_flags2 & IWL_RX_MPDU_MFLG2_AMSDU;
|
||||
bool last_subframe =
|
||||
|
|
@ -976,6 +757,9 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
|||
baid = (reorder & IWL_RX_MPDU_REORDER_BAID_MASK) >>
|
||||
IWL_RX_MPDU_REORDER_BAID_SHIFT;
|
||||
|
||||
if (mvm->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_9000)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* This also covers the case of receiving a Block Ack Request
|
||||
* outside a BA session; we'll pass it to mac80211 and that
|
||||
|
|
@ -1040,59 +824,18 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
|||
buffer->valid = true;
|
||||
}
|
||||
|
||||
if (ieee80211_is_back_req(hdr->frame_control)) {
|
||||
iwl_mvm_release_frames(mvm, sta, napi, baid_data,
|
||||
buffer, nssn, 0);
|
||||
/* drop any duplicated packets */
|
||||
if (desc->status & cpu_to_le32(IWL_RX_MPDU_STATUS_DUPLICATE))
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there was a significant jump in the nssn - adjust.
|
||||
* If the SN is smaller than the NSSN it might need to first go into
|
||||
* the reorder buffer, in which case we just release up to it and the
|
||||
* rest of the function will take care of storing it and releasing up to
|
||||
* the nssn.
|
||||
* This should not happen. This queue has been lagging and it should
|
||||
* have been updated by a IWL_MVM_RXQ_NSSN_SYNC notification. Be nice
|
||||
* and update the other queues.
|
||||
*/
|
||||
if (!iwl_mvm_is_sn_less(nssn, buffer->head_sn + buffer->buf_size,
|
||||
buffer->buf_size) ||
|
||||
!ieee80211_sn_less(sn, buffer->head_sn + buffer->buf_size)) {
|
||||
u16 min_sn = ieee80211_sn_less(sn, nssn) ? sn : nssn;
|
||||
|
||||
iwl_mvm_release_frames(mvm, sta, napi, baid_data, buffer,
|
||||
min_sn, IWL_MVM_RELEASE_SEND_RSS_SYNC);
|
||||
}
|
||||
|
||||
iwl_mvm_oldsn_workaround(mvm, sta, tid, buffer, reorder,
|
||||
rx_status->device_timestamp, queue);
|
||||
|
||||
/* drop any oudated packets */
|
||||
if (ieee80211_sn_less(sn, buffer->head_sn))
|
||||
if (reorder & IWL_RX_MPDU_REORDER_BA_OLD_SN)
|
||||
goto drop;
|
||||
|
||||
/* release immediately if allowed by nssn and no stored frames */
|
||||
if (!buffer->num_stored && ieee80211_sn_less(sn, nssn)) {
|
||||
if (iwl_mvm_is_sn_less(buffer->head_sn, nssn,
|
||||
buffer->buf_size) &&
|
||||
(!amsdu || last_subframe)) {
|
||||
/*
|
||||
* If we crossed the 2048 or 0 SN, notify all the
|
||||
* queues. This is done in order to avoid having a
|
||||
* head_sn that lags behind for too long. When that
|
||||
* happens, we can get to a situation where the head_sn
|
||||
* is within the interval [nssn - buf_size : nssn]
|
||||
* which will make us think that the nssn is a packet
|
||||
* that we already freed because of the reordering
|
||||
* buffer and we will ignore it. So maintain the
|
||||
* head_sn somewhat updated across all the queues:
|
||||
* when it crosses 0 and 2048.
|
||||
*/
|
||||
if (sn == 2048 || sn == 0)
|
||||
iwl_mvm_sync_nssn(mvm, baid, sn);
|
||||
if (!amsdu || last_subframe)
|
||||
buffer->head_sn = nssn;
|
||||
}
|
||||
/* No need to update AMSDU last SN - we are moving the head */
|
||||
spin_unlock_bh(&buffer->lock);
|
||||
return false;
|
||||
|
|
@ -1107,37 +850,18 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
|||
* while technically there is no hole and we can move forward.
|
||||
*/
|
||||
if (!buffer->num_stored && sn == buffer->head_sn) {
|
||||
if (!amsdu || last_subframe) {
|
||||
if (sn == 2048 || sn == 0)
|
||||
iwl_mvm_sync_nssn(mvm, baid, sn);
|
||||
if (!amsdu || last_subframe)
|
||||
buffer->head_sn = ieee80211_sn_inc(buffer->head_sn);
|
||||
}
|
||||
|
||||
/* No need to update AMSDU last SN - we are moving the head */
|
||||
spin_unlock_bh(&buffer->lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
index = sn % buffer->buf_size;
|
||||
|
||||
/*
|
||||
* Check if we already stored this frame
|
||||
* As AMSDU is either received or not as whole, logic is simple:
|
||||
* If we have frames in that position in the buffer and the last frame
|
||||
* originated from AMSDU had a different SN then it is a retransmission.
|
||||
* If it is the same SN then if the subframe index is incrementing it
|
||||
* is the same AMSDU - otherwise it is a retransmission.
|
||||
*/
|
||||
tail = skb_peek_tail(&entries[index].e.frames);
|
||||
if (tail && !amsdu)
|
||||
goto drop;
|
||||
else if (tail && (sn != buffer->last_amsdu ||
|
||||
buffer->last_sub_index >= sub_frame_idx))
|
||||
goto drop;
|
||||
|
||||
/* put in reorder buffer */
|
||||
__skb_queue_tail(&entries[index].e.frames, skb);
|
||||
index = sn % baid_data->buf_size;
|
||||
__skb_queue_tail(&entries[index].frames, skb);
|
||||
buffer->num_stored++;
|
||||
entries[index].e.reorder_time = jiffies;
|
||||
|
||||
if (amsdu) {
|
||||
buffer->last_amsdu = sn;
|
||||
|
|
@ -1157,8 +881,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
|||
*/
|
||||
if (!amsdu || last_subframe)
|
||||
iwl_mvm_release_frames(mvm, sta, napi, baid_data,
|
||||
buffer, nssn,
|
||||
IWL_MVM_RELEASE_SEND_RSS_SYNC);
|
||||
buffer, nssn);
|
||||
|
||||
spin_unlock_bh(&buffer->lock);
|
||||
return true;
|
||||
|
|
@ -1531,7 +1254,7 @@ static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm,
|
|||
#define IWL_RX_RU_DATA_A1 2
|
||||
#define IWL_RX_RU_DATA_A2 2
|
||||
#define IWL_RX_RU_DATA_B1 2
|
||||
#define IWL_RX_RU_DATA_B2 3
|
||||
#define IWL_RX_RU_DATA_B2 4
|
||||
#define IWL_RX_RU_DATA_C1 3
|
||||
#define IWL_RX_RU_DATA_C2 3
|
||||
#define IWL_RX_RU_DATA_D1 4
|
||||
|
|
@ -2187,21 +1910,6 @@ static void iwl_mvm_decode_lsig(struct sk_buff *skb,
|
|||
}
|
||||
}
|
||||
|
||||
static inline u8 iwl_mvm_nl80211_band_from_rx_msdu(u8 phy_band)
|
||||
{
|
||||
switch (phy_band) {
|
||||
case PHY_BAND_24:
|
||||
return NL80211_BAND_2GHZ;
|
||||
case PHY_BAND_5:
|
||||
return NL80211_BAND_5GHZ;
|
||||
case PHY_BAND_6:
|
||||
return NL80211_BAND_6GHZ;
|
||||
default:
|
||||
WARN_ONCE(1, "Unsupported phy band (%u)\n", phy_band);
|
||||
return NL80211_BAND_5GHZ;
|
||||
}
|
||||
}
|
||||
|
||||
struct iwl_rx_sta_csa {
|
||||
bool all_sta_unblocked;
|
||||
struct ieee80211_vif *vif;
|
||||
|
|
@ -2266,6 +1974,16 @@ static void iwl_mvm_rx_fill_status(struct iwl_mvm *mvm,
|
|||
iwl_mvm_decode_lsig(skb, phy_data);
|
||||
|
||||
rx_status->device_timestamp = phy_data->gp2_on_air_rise;
|
||||
|
||||
if (mvm->rx_ts_ptp && mvm->monitor_on) {
|
||||
u64 adj_time =
|
||||
iwl_mvm_ptp_get_adj_time(mvm, phy_data->gp2_on_air_rise * NSEC_PER_USEC);
|
||||
|
||||
rx_status->mactime = div64_u64(adj_time, NSEC_PER_USEC);
|
||||
rx_status->flag |= RX_FLAG_MACTIME_IS_RTAP_TS64;
|
||||
rx_status->flag &= ~RX_FLAG_MACTIME;
|
||||
}
|
||||
|
||||
rx_status->freq = ieee80211_channel_to_frequency(phy_data->channel,
|
||||
rx_status->band);
|
||||
iwl_mvm_get_signal_strength(mvm, rx_status, rate_n_flags,
|
||||
|
|
@ -2344,9 +2062,9 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
u32 len;
|
||||
u32 pkt_len = iwl_rx_packet_payload_len(pkt);
|
||||
struct ieee80211_sta *sta = NULL;
|
||||
struct ieee80211_link_sta *link_sta = NULL;
|
||||
struct sk_buff *skb;
|
||||
u8 crypt_len = 0;
|
||||
u8 sta_id = le32_get_bits(desc->status, IWL_RX_MPDU_STATUS_STA_ID);
|
||||
size_t desc_size;
|
||||
struct iwl_mvm_rx_phy_data phy_data = {};
|
||||
u32 format;
|
||||
|
|
@ -2465,7 +2183,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
if (iwl_mvm_is_band_in_rx_supported(mvm)) {
|
||||
u8 band = BAND_IN_RX_STATUS(desc->mac_phy_idx);
|
||||
|
||||
rx_status->band = iwl_mvm_nl80211_band_from_rx_msdu(band);
|
||||
rx_status->band = iwl_mvm_nl80211_band_from_phy(band);
|
||||
} else {
|
||||
rx_status->band = phy_data.channel > 14 ? NL80211_BAND_5GHZ :
|
||||
NL80211_BAND_2GHZ;
|
||||
|
|
@ -2495,13 +2213,18 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
rcu_read_lock();
|
||||
|
||||
if (desc->status & cpu_to_le32(IWL_RX_MPDU_STATUS_SRC_STA_FOUND)) {
|
||||
u8 id = le32_get_bits(desc->status, IWL_RX_MPDU_STATUS_STA_ID);
|
||||
if (!WARN_ON_ONCE(sta_id >= mvm->fw->ucode_capa.num_stations)) {
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
|
||||
if (!WARN_ON_ONCE(id >= mvm->fw->ucode_capa.num_stations)) {
|
||||
sta = rcu_dereference(mvm->fw_id_to_mac_id[id]);
|
||||
sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
|
||||
if (IS_ERR(sta))
|
||||
sta = NULL;
|
||||
link_sta = rcu_dereference(mvm->fw_id_to_link_sta[id]);
|
||||
link_sta = rcu_dereference(mvm->fw_id_to_link_sta[sta_id]);
|
||||
|
||||
if (sta && sta->valid_links && link_sta) {
|
||||
rx_status->link_valid = 1;
|
||||
rx_status->link_id = link_sta->link_id;
|
||||
}
|
||||
}
|
||||
} else if (!is_multicast_ether_addr(hdr->addr2)) {
|
||||
/*
|
||||
|
|
@ -2590,6 +2313,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
iwl_mvm_rx_csum(mvm, sta, skb, pkt);
|
||||
|
||||
if (iwl_mvm_is_dup(sta, queue, rx_status, hdr, desc)) {
|
||||
IWL_DEBUG_DROP(mvm, "Dropping duplicate packet 0x%x\n",
|
||||
le16_to_cpu(hdr->seq_ctrl));
|
||||
kfree_skb(skb);
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -2619,6 +2344,16 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
|
||||
iwl_mvm_agg_rx_received(mvm, reorder_data, baid);
|
||||
}
|
||||
|
||||
if (ieee80211_is_data(hdr->frame_control)) {
|
||||
u8 sub_frame_idx = desc->amsdu_info &
|
||||
IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK;
|
||||
|
||||
/* 0 means not an A-MSDU, and 1 means a new A-MSDU */
|
||||
if (!sub_frame_idx || sub_frame_idx == 1)
|
||||
iwl_mvm_count_mpdu(mvmsta, sta_id, 1, false,
|
||||
queue);
|
||||
}
|
||||
}
|
||||
|
||||
/* management stuff on default queue */
|
||||
|
|
@ -2641,9 +2376,14 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
|
||||
if (!iwl_mvm_reorder(mvm, napi, queue, sta, skb, desc) &&
|
||||
likely(!iwl_mvm_time_sync_frame(mvm, skb, hdr->addr2)) &&
|
||||
likely(!iwl_mvm_mei_filter_scan(mvm, skb)))
|
||||
iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta,
|
||||
link_sta);
|
||||
likely(!iwl_mvm_mei_filter_scan(mvm, skb))) {
|
||||
if (mvm->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_9000 &&
|
||||
(desc->mac_flags2 & IWL_RX_MPDU_MFLG2_AMSDU) &&
|
||||
!(desc->amsdu_info & IWL_RX_MPDU_AMSDU_LAST_SUBFRAME))
|
||||
rx_status->flag |= RX_FLAG_AMSDU_MORE;
|
||||
|
||||
iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta);
|
||||
}
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
|
@ -2655,7 +2395,6 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_rx_no_data_ver_3 *desc = (void *)pkt->data;
|
||||
u32 rssi;
|
||||
u32 info_type;
|
||||
struct ieee80211_sta *sta = NULL;
|
||||
struct sk_buff *skb;
|
||||
struct iwl_mvm_rx_phy_data phy_data;
|
||||
|
|
@ -2668,7 +2407,6 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
return;
|
||||
|
||||
rssi = le32_to_cpu(desc->rssi);
|
||||
info_type = le32_to_cpu(desc->info) & RX_NO_DATA_INFO_TYPE_MSK;
|
||||
phy_data.d0 = desc->phy_info[0];
|
||||
phy_data.d1 = desc->phy_info[1];
|
||||
phy_data.phy_info = IWL_RX_MPDU_PHY_TSF_OVERLOAD;
|
||||
|
|
@ -2720,7 +2458,12 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
/* 0-length PSDU */
|
||||
rx_status->flag |= RX_FLAG_NO_PSDU;
|
||||
|
||||
switch (info_type) {
|
||||
/* mark as failed PLCP on any errors to skip checks in mac80211 */
|
||||
if (le32_get_bits(desc->info, RX_NO_DATA_INFO_ERR_MSK) !=
|
||||
RX_NO_DATA_INFO_ERR_NONE)
|
||||
rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC;
|
||||
|
||||
switch (le32_get_bits(desc->info, RX_NO_DATA_INFO_TYPE_MSK)) {
|
||||
case RX_NO_DATA_INFO_TYPE_NDP:
|
||||
rx_status->zero_length_psdu_type =
|
||||
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_SOUNDING;
|
||||
|
|
@ -2745,8 +2488,11 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
*
|
||||
* We mark it as mac header, for upper layers to know where
|
||||
* all radio tap header ends.
|
||||
*
|
||||
* Since data doesn't move data while putting data on skb and that is
|
||||
* the only way we use, data + len is the next place that hdr would be put
|
||||
*/
|
||||
skb_reset_mac_header(skb);
|
||||
skb_set_mac_header(skb, skb->len);
|
||||
|
||||
/*
|
||||
* Override the nss from the rx_vec since the rate_n_flags has
|
||||
|
|
@ -2786,7 +2532,7 @@ void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
|
||||
iwl_mvm_release_frames_from_notif(mvm, napi, release->baid,
|
||||
le16_to_cpu(release->nssn),
|
||||
queue, 0);
|
||||
queue);
|
||||
}
|
||||
|
||||
void iwl_mvm_rx_bar_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||
|
|
@ -2827,7 +2573,10 @@ void iwl_mvm_rx_bar_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
tid))
|
||||
goto out;
|
||||
|
||||
iwl_mvm_release_frames_from_notif(mvm, napi, baid, nssn, queue, 0);
|
||||
IWL_DEBUG_DROP(mvm, "Received a BAR, expect packet loss: nssn %d\n",
|
||||
nssn);
|
||||
|
||||
iwl_mvm_release_frames_from_notif(mvm, napi, baid, nssn, queue);
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue