mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
wifi: iwlwifi: updates - 2026-10-14
This contains our usual development commits, notably: - UHR sniffer support - Transport refactor: avoid indirection, bring virtualization back - A UEFI lock for UEFI tables security - New BIOS tables support -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQQM3A3Pv7vbm9vtjWbacY7uyt+OfQUCas9IlgAKCRDacY7uyt+O fUibAP0V/fsGHLVVrYd8qbBi25Vmul2ozWvwr31Lj2gb8asXdwEAlBSc4mw2xwSu /IOdQQkLVl0fR1P5HyB5QMBvj/CwCww= =lSVE -----END PGP SIGNATURE----- Merge tag 'iwlwifi-next-2026-10-14' of https://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next Miri Korenblit says: ==================== wifi: iwlwifi: updates - 2026-10-14 This contains our usual development commits, notably: - UHR sniffer support - Transport refactor: avoid indirection, bring virtualization back - A UEFI lock for UEFI tables security - New BIOS tables support ==================== Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
commit
313f802d6f
|
|
@ -1,7 +1,6 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
# common
|
||||
obj-$(CONFIG_IWLWIFI) += iwlwifi.o
|
||||
iwlwifi-objs += iwl-io.o
|
||||
iwlwifi-objs += iwl-drv.o
|
||||
iwlwifi-objs += iwl-debug.o
|
||||
iwlwifi-objs += iwl-nvm-utils.o
|
||||
|
|
@ -9,9 +8,9 @@ iwlwifi-objs += iwl-utils.o
|
|||
iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o
|
||||
|
||||
# Bus
|
||||
iwlwifi-objs += pcie/ctxt-info.o pcie/ctxt-info-v2.o pcie/drv.o pcie/utils.o
|
||||
iwlwifi-objs += pcie/gen1_2/rx.o pcie/gen1_2/tx.o pcie/gen1_2/trans.o
|
||||
iwlwifi-objs += pcie/gen1_2/trans-gen2.o pcie/gen1_2/tx-gen2.o
|
||||
iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o
|
||||
iwlwifi-objs += pcie/ctxt-info.o pcie/ctxt-info-v2.o pcie/trans-gen2.o pcie/tx-gen2.o
|
||||
iwlwifi-objs += pcie/utils.o
|
||||
|
||||
CFLAGS_pcie/drv.o += -Wno-override-init
|
||||
|
||||
|
|
|
|||
|
|
@ -10,14 +10,11 @@
|
|||
#include "fw/api/txq.h"
|
||||
|
||||
/* Highest firmware core release supported */
|
||||
#define IWL_BZ_UCODE_CORE_MAX 107
|
||||
#define IWL_BZ_UCODE_CORE_MAX 109
|
||||
|
||||
/* Lowest firmware core release supported */
|
||||
#define IWL_BZ_UCODE_CORE_MIN 102
|
||||
|
||||
#define IWL_BZ_A_FM_B_FW_PRE "iwlwifi-bz-a0-fm-b0"
|
||||
#define IWL_BZ_A_FM_C_FW_PRE "iwlwifi-bz-a0-fm-c0"
|
||||
#define IWL_BZ_A_FM4_B_FW_PRE "iwlwifi-bz-a0-fm4-b0"
|
||||
#define IWL_GL_B_FM_B_FW_PRE "iwlwifi-gl-b0-fm-b0"
|
||||
#define IWL_GL_C_FM_C_FW_PRE "iwlwifi-gl-c0-fm-c0"
|
||||
|
||||
|
|
@ -92,8 +89,5 @@ const struct iwl_mac_cfg iwl_gl_mac_cfg = {
|
|||
.low_latency_xtal = true,
|
||||
};
|
||||
|
||||
IWL_CORE_FW(IWL_BZ_A_FM_B_FW_PRE, IWL_BZ_UCODE_CORE_MAX);
|
||||
IWL_CORE_FW(IWL_BZ_A_FM_C_FW_PRE, IWL_BZ_UCODE_CORE_MAX);
|
||||
IWL_CORE_FW(IWL_BZ_A_FM4_B_FW_PRE, IWL_BZ_UCODE_CORE_MAX);
|
||||
IWL_CORE_FW(IWL_GL_B_FM_B_FW_PRE, IWL_BZ_UCODE_CORE_MAX);
|
||||
IWL_CORE_FW(IWL_GL_C_FM_C_FW_PRE, IWL_BZ_UCODE_CORE_MAX);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#include "fw/api/txq.h"
|
||||
|
||||
/* Highest firmware core release supported */
|
||||
#define IWL_DR_UCODE_CORE_MAX 107
|
||||
#define IWL_DR_UCODE_CORE_MAX 109
|
||||
|
||||
/* Lowest firmware core release supported */
|
||||
#define IWL_DR_UCODE_CORE_MIN 102
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
*/
|
||||
#include "iwl-config.h"
|
||||
|
||||
#define IWL_BZ_A_FM_C_FW_PRE "iwlwifi-bz-a0-fm-c0"
|
||||
|
||||
#define IWL_DEVICE_FM \
|
||||
.ht_params = { \
|
||||
.stbc = true, \
|
||||
|
|
@ -48,3 +50,5 @@ const char iwl_be201_name[] = "Intel(R) Wi-Fi 7 BE201 320MHz";
|
|||
const char iwl_be200_name[] = "Intel(R) Wi-Fi 7 BE200 320MHz";
|
||||
const char iwl_be202_name[] = "Intel(R) Wi-Fi 7 BE202 160MHz";
|
||||
const char iwl_be401_name[] = "Intel(R) Wi-Fi 7 BE401 320MHz";
|
||||
|
||||
IWL_CORE_FW(IWL_BZ_A_FM_C_FW_PRE, 107);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#include "fw/api/txq.h"
|
||||
|
||||
/* Highest firmware core release supported */
|
||||
#define IWL_SC_UCODE_CORE_MAX 107
|
||||
#define IWL_SC_UCODE_CORE_MAX 109
|
||||
|
||||
/* Lowest firmware core release supported */
|
||||
#define IWL_SC_UCODE_CORE_MIN 102
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2018, 2025 Intel Corporation
|
||||
* Copyright (C) 2018, 2025-2026 Intel Corporation
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-io.h"
|
||||
#include "dev.h"
|
||||
#include "agn.h"
|
||||
|
||||
|
|
@ -1788,7 +1787,7 @@ static ssize_t iwl_dbgfs_power_save_status_read(struct file *file,
|
|||
const size_t bufsz = sizeof(buf);
|
||||
u32 pwrsave_status;
|
||||
|
||||
pwrsave_status = iwl_read32(priv->trans, CSR_GP_CNTRL) &
|
||||
pwrsave_status = iwl_trans_read32(priv->trans, CSR_GP_CNTRL) &
|
||||
CSR_GP_REG_POWER_SAVE_STATUS_MSK;
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2019, 2025 Intel Corporation
|
||||
* Copyright (C) 2019, 2025-2026 Intel Corporation
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/units.h>
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
/*
|
||||
* DVM device-specific data & functions
|
||||
*/
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "iwl-nvm-utils.h"
|
||||
|
||||
|
|
@ -45,10 +45,10 @@ static void iwl1000_set_ct_threshold(struct iwl_priv *priv)
|
|||
static void iwl1000_nic_config(struct iwl_priv *priv)
|
||||
{
|
||||
/* Setting digital SVR for 1000 card to 1.32V */
|
||||
/* locking is acquired in iwl_set_bits_mask_prph() function */
|
||||
iwl_set_bits_mask_prph(priv->trans, APMG_DIGITAL_SVR_REG,
|
||||
APMG_SVR_DIGITAL_VOLTAGE_1_32,
|
||||
~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK);
|
||||
/* locking is acquired in iwl_trans_set_bits_mask_prph() function */
|
||||
iwl_trans_set_bits_mask_prph(priv->trans, APMG_DIGITAL_SVR_REG,
|
||||
APMG_SVR_DIGITAL_VOLTAGE_1_32,
|
||||
~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -184,8 +184,8 @@ static void iwl2000_set_ct_threshold(struct iwl_priv *priv)
|
|||
/* NIC configuration for 2000 series */
|
||||
static void iwl2000_nic_config(struct iwl_priv *priv)
|
||||
{
|
||||
iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG,
|
||||
CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER);
|
||||
iwl_trans_set_bit(priv->trans, CSR_GP_DRIVER_REG,
|
||||
CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER);
|
||||
}
|
||||
|
||||
static const struct iwl_sensitivity_ranges iwl2000_sensitivity = {
|
||||
|
|
@ -490,22 +490,22 @@ static void iwl6000_nic_config(struct iwl_priv *priv)
|
|||
break;
|
||||
case IWL_DEVICE_FAMILY_6000i:
|
||||
/* 2x2 IPA phy type */
|
||||
iwl_write32(priv->trans, CSR_GP_DRIVER_REG,
|
||||
CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
|
||||
iwl_trans_write32(priv->trans, CSR_GP_DRIVER_REG,
|
||||
CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
|
||||
break;
|
||||
case IWL_DEVICE_FAMILY_6050:
|
||||
/* Indicate calibration version to uCode. */
|
||||
if (priv->nvm_data->calib_version >= 6)
|
||||
iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG,
|
||||
CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
|
||||
iwl_trans_set_bit(priv->trans, CSR_GP_DRIVER_REG,
|
||||
CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
|
||||
break;
|
||||
case IWL_DEVICE_FAMILY_6150:
|
||||
/* Indicate calibration version to uCode. */
|
||||
if (priv->nvm_data->calib_version >= 6)
|
||||
iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG,
|
||||
CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
|
||||
iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG,
|
||||
CSR_GP_DRIVER_REG_BIT_6050_1x2);
|
||||
iwl_trans_set_bit(priv->trans, CSR_GP_DRIVER_REG,
|
||||
CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
|
||||
iwl_trans_set_bit(priv->trans, CSR_GP_DRIVER_REG,
|
||||
CSR_GP_DRIVER_REG_BIT_6050_1x2);
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2019, 2021, 2024-2025 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2019, 2021, 2024-2026 Intel Corporation
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "agn.h"
|
||||
|
|
@ -672,13 +672,13 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_trans *trans)
|
|||
|
||||
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_EEPROM_OWN_SEM);
|
||||
iwl_trans_set_bit(trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_EEPROM_OWN_SEM);
|
||||
|
||||
/* See if we got it */
|
||||
ret = iwl_poll_bits(trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_EEPROM_OWN_SEM,
|
||||
IWL_EEPROM_SEM_TIMEOUT);
|
||||
ret = iwl_trans_poll_bits(trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_EEPROM_OWN_SEM,
|
||||
IWL_EEPROM_SEM_TIMEOUT);
|
||||
if (!ret) {
|
||||
IWL_DEBUG_EEPROM(trans->dev,
|
||||
"Acquired semaphore after %d tries.\n",
|
||||
|
|
@ -692,13 +692,13 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_trans *trans)
|
|||
|
||||
static void iwl_eeprom_release_semaphore(struct iwl_trans *trans)
|
||||
{
|
||||
iwl_clear_bit(trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_EEPROM_OWN_SEM);
|
||||
iwl_trans_clear_bit(trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_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;
|
||||
u32 gp = iwl_trans_read32(trans, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK;
|
||||
|
||||
IWL_DEBUG_EEPROM(trans->dev, "EEPROM signature=0x%08x\n", gp);
|
||||
|
||||
|
|
@ -734,10 +734,10 @@ static int iwl_eeprom_verify_signature(struct iwl_trans *trans, bool nvm_is_otp)
|
|||
|
||||
static void iwl_set_otp_access_absolute(struct iwl_trans *trans)
|
||||
{
|
||||
iwl_read32(trans, CSR_OTP_GP_REG);
|
||||
iwl_trans_read32(trans, CSR_OTP_GP_REG);
|
||||
|
||||
iwl_clear_bit(trans, CSR_OTP_GP_REG,
|
||||
CSR_OTP_GP_REG_OTP_ACCESS_MODE);
|
||||
iwl_trans_clear_bit(trans, CSR_OTP_GP_REG,
|
||||
CSR_OTP_GP_REG_OTP_ACCESS_MODE);
|
||||
}
|
||||
|
||||
static int iwl_nvm_is_otp(struct iwl_trans *trans)
|
||||
|
|
@ -755,7 +755,7 @@ static int iwl_nvm_is_otp(struct iwl_trans *trans)
|
|||
case CSR_HW_REV_TYPE_5150:
|
||||
return 0;
|
||||
default:
|
||||
otpgp = iwl_read32(trans, CSR_OTP_GP_REG);
|
||||
otpgp = iwl_trans_read32(trans, CSR_OTP_GP_REG);
|
||||
if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT)
|
||||
return 1;
|
||||
return 0;
|
||||
|
|
@ -770,19 +770,19 @@ static int iwl_init_otp_access(struct iwl_trans *trans)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
iwl_set_bits_prph(trans, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_VAL_RESET_REQ);
|
||||
iwl_trans_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);
|
||||
iwl_trans_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->mac_cfg->base->shadow_ram_support)
|
||||
iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
|
||||
CSR_RESET_LINK_PWR_MGMT_DISABLED);
|
||||
iwl_trans_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
|
||||
CSR_RESET_LINK_PWR_MGMT_DISABLED);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -794,31 +794,31 @@ static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr,
|
|||
u32 r;
|
||||
u32 otpgp;
|
||||
|
||||
iwl_write32(trans, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
|
||||
ret = iwl_poll_bits(trans, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_READ_VALID_MSK,
|
||||
IWL_EEPROM_ACCESS_TIMEOUT);
|
||||
iwl_trans_write32(trans, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
|
||||
ret = iwl_trans_poll_bits(trans, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_READ_VALID_MSK,
|
||||
IWL_EEPROM_ACCESS_TIMEOUT);
|
||||
if (ret) {
|
||||
IWL_ERR(trans, "Time out reading OTP[%d]\n", addr);
|
||||
return ret;
|
||||
}
|
||||
r = iwl_read32(trans, CSR_EEPROM_REG);
|
||||
r = iwl_trans_read32(trans, CSR_EEPROM_REG);
|
||||
/* check for ECC errors: */
|
||||
otpgp = iwl_read32(trans, CSR_OTP_GP_REG);
|
||||
otpgp = iwl_trans_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_trans_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_trans_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);
|
||||
|
|
@ -918,7 +918,7 @@ static int iwl_find_otp_image(struct iwl_trans *trans,
|
|||
int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size)
|
||||
{
|
||||
__le16 *e;
|
||||
u32 gp = iwl_read32(trans, CSR_EEPROM_GP);
|
||||
u32 gp = iwl_trans_read32(trans, CSR_EEPROM_GP);
|
||||
int sz;
|
||||
int ret;
|
||||
u16 addr;
|
||||
|
|
@ -960,13 +960,13 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size)
|
|||
goto err_unlock;
|
||||
}
|
||||
|
||||
iwl_write32(trans, CSR_EEPROM_GP,
|
||||
iwl_read32(trans, CSR_EEPROM_GP) &
|
||||
~CSR_EEPROM_GP_IF_OWNER_MSK);
|
||||
iwl_trans_write32(trans, CSR_EEPROM_GP,
|
||||
iwl_trans_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);
|
||||
iwl_trans_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->mac_cfg->base->shadow_ram_support) {
|
||||
ret = iwl_find_otp_image(trans, &validblockaddr);
|
||||
|
|
@ -988,18 +988,18 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size)
|
|||
for (addr = 0; addr < sz; addr += sizeof(u16)) {
|
||||
u32 r;
|
||||
|
||||
iwl_write32(trans, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
|
||||
iwl_trans_write32(trans, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
|
||||
|
||||
ret = iwl_poll_bits(trans, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_READ_VALID_MSK,
|
||||
IWL_EEPROM_ACCESS_TIMEOUT);
|
||||
ret = iwl_trans_poll_bits(trans, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_READ_VALID_MSK,
|
||||
IWL_EEPROM_ACCESS_TIMEOUT);
|
||||
if (ret) {
|
||||
IWL_ERR(trans,
|
||||
"Time out reading EEPROM[%d]\n", addr);
|
||||
goto err_unlock;
|
||||
}
|
||||
r = iwl_read32(trans, CSR_EEPROM_REG);
|
||||
r = iwl_trans_read32(trans, CSR_EEPROM_REG);
|
||||
e[addr / 2] = cpu_to_le16(r >> 16);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2019, 2025 Intel Corporation
|
||||
* Copyright (C) 2019, 2025-2026 Intel Corporation
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
|
|
@ -14,7 +14,6 @@
|
|||
#include <net/mac80211.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-modparams.h"
|
||||
#include "dev.h"
|
||||
|
|
@ -49,7 +48,7 @@ static const struct ieee80211_tpt_blink iwl_blink[] = {
|
|||
/* Set led register off */
|
||||
void iwlagn_led_enable(struct iwl_priv *priv)
|
||||
{
|
||||
iwl_write32(priv->trans, CSR_LED_REG, CSR_LED_REG_TURN_ON);
|
||||
iwl_trans_write32(priv->trans, CSR_LED_REG, CSR_LED_REG_TURN_ON);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -85,10 +84,10 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
|
|||
};
|
||||
u32 reg;
|
||||
|
||||
reg = iwl_read32(priv->trans, CSR_LED_REG);
|
||||
reg = iwl_trans_read32(priv->trans, CSR_LED_REG);
|
||||
if (reg != (reg & CSR_LED_BSM_CTRL_MSK))
|
||||
iwl_write32(priv->trans, CSR_LED_REG,
|
||||
reg & CSR_LED_BSM_CTRL_MSK);
|
||||
iwl_trans_write32(priv->trans, CSR_LED_REG,
|
||||
reg & CSR_LED_BSM_CTRL_MSK);
|
||||
|
||||
return iwl_dvm_send_cmd(priv, &cmd);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2008 - 2014, 2022 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2026 Intel Corporation
|
||||
*****************************************************************************/
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/kernel.h>
|
||||
|
|
@ -9,7 +10,6 @@
|
|||
#include <linux/sched.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-modparams.h"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(C) 2018 - 2019, 2022 - 2025 Intel Corporation
|
||||
* Copyright(C) 2018 - 2019, 2022 - 2026 Intel Corporation
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
|
|
@ -23,7 +23,6 @@
|
|||
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-op-mode.h"
|
||||
#include "iwl-modparams.h"
|
||||
|
|
@ -375,8 +374,8 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
|
|||
goto error;
|
||||
|
||||
/* let the ucode operate on its own */
|
||||
iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET,
|
||||
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
|
||||
iwl_trans_write32(priv->trans, CSR_UCODE_DRV_GP1_SET,
|
||||
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
|
||||
|
||||
iwl_trans_d3_suspend(priv->trans, true);
|
||||
|
||||
|
|
@ -455,8 +454,8 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
|
|||
goto out_unlock;
|
||||
|
||||
/* uCode is no longer operating by itself */
|
||||
iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR,
|
||||
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
|
||||
iwl_trans_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR,
|
||||
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
|
||||
|
||||
base = priv->device_pointers.error_event_table;
|
||||
if (!iwlagn_hw_valid_rtc_data_addr(base)) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2014, 2018 - 2022 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2024-2025 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2024-2026 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2015 Intel Deutschland GmbH
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
|
|
@ -27,8 +27,8 @@
|
|||
#include <asm/div64.h>
|
||||
|
||||
#include "iwl-nvm-utils.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-devtrace.h"
|
||||
#include "iwl-op-mode.h"
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-modparams.h"
|
||||
|
|
@ -413,7 +413,7 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
|
|||
return;
|
||||
|
||||
/* Set starting address; reads will auto-increment */
|
||||
iwl_write32(priv->trans, HBUS_TARG_MEM_RADDR, ptr);
|
||||
iwl_trans_write32(priv->trans, HBUS_TARG_MEM_RADDR, ptr);
|
||||
|
||||
/*
|
||||
* Refuse to read more than would have fit into the log from
|
||||
|
|
@ -429,13 +429,13 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
|
|||
* place event id # at far right for easier visual parsing.
|
||||
*/
|
||||
for (i = 0; i < num_events; i++) {
|
||||
ev = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT);
|
||||
time = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT);
|
||||
ev = iwl_trans_read32(priv->trans, HBUS_TARG_MEM_RDAT);
|
||||
time = iwl_trans_read32(priv->trans, HBUS_TARG_MEM_RDAT);
|
||||
if (mode == 0) {
|
||||
trace_iwlwifi_dev_ucode_cont_event(
|
||||
priv->trans->dev, 0, time, ev);
|
||||
} else {
|
||||
data = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT);
|
||||
data = iwl_trans_read32(priv->trans, HBUS_TARG_MEM_RDAT);
|
||||
trace_iwlwifi_dev_ucode_cont_event(
|
||||
priv->trans->dev, time, data, ev);
|
||||
}
|
||||
|
|
@ -661,8 +661,8 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
|
|||
struct iwl_ct_kill_throttling_config adv_cmd;
|
||||
int ret = 0;
|
||||
|
||||
iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR,
|
||||
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
|
||||
iwl_trans_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR,
|
||||
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
|
||||
|
||||
priv->thermal_throttle.ct_kill_toggle = false;
|
||||
|
||||
|
|
@ -1731,13 +1731,13 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
|
|||
return pos;
|
||||
|
||||
/* Set starting address; reads will auto-increment */
|
||||
iwl_write32(trans, HBUS_TARG_MEM_RADDR, ptr);
|
||||
iwl_trans_write32(trans, HBUS_TARG_MEM_RADDR, ptr);
|
||||
|
||||
/* "time" is actually "data" for mode 0 (no timestamp).
|
||||
* place event id # at far right for easier visual parsing. */
|
||||
for (i = 0; i < num_events; i++) {
|
||||
ev = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
|
||||
time = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
|
||||
ev = iwl_trans_read32(trans, HBUS_TARG_MEM_RDAT);
|
||||
time = iwl_trans_read32(trans, HBUS_TARG_MEM_RDAT);
|
||||
if (mode == 0) {
|
||||
/* data, ev */
|
||||
if (bufsz) {
|
||||
|
|
@ -1751,7 +1751,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
|
|||
time, ev);
|
||||
}
|
||||
} else {
|
||||
data = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
|
||||
data = iwl_trans_read32(trans, HBUS_TARG_MEM_RDAT);
|
||||
if (bufsz) {
|
||||
pos += scnprintf(*buf + pos, bufsz - pos,
|
||||
"EVT_LOGT:%010u:0x%08x:%04u\n",
|
||||
|
|
@ -2028,17 +2028,17 @@ static void iwl_nic_config(struct iwl_op_mode *op_mode)
|
|||
}
|
||||
|
||||
/* set CSR_HW_CONFIG_REG for uCode use */
|
||||
iwl_set_bit(priv->trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
|
||||
CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
|
||||
iwl_trans_set_bit(priv->trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
|
||||
CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
|
||||
|
||||
/* W/A : NIC is stuck in a reset state after Early PCIe power off
|
||||
* (PCIe power is lost before PERST# is asserted),
|
||||
* causing ME FW to lose ownership and not being able to obtain it back.
|
||||
*/
|
||||
iwl_set_bits_mask_prph(priv->trans, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
|
||||
~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
|
||||
iwl_trans_set_bits_mask_prph(priv->trans, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
|
||||
~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
|
||||
|
||||
if (priv->lib->nic_config)
|
||||
priv->lib->nic_config(priv);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2019, 2025 Intel Corporation
|
||||
* Copyright (C) 2019, 2025-2026 Intel Corporation
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
|
|
@ -13,7 +13,6 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <net/mac80211.h>
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-modparams.h"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2015 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018, 2020-2021, 2025 Intel Corporation
|
||||
* Copyright(c) 2018, 2020-2021, 2025-2026 Intel Corporation
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portionhelp of the ieee80211 subsystem header files.
|
||||
|
|
@ -16,7 +16,6 @@
|
|||
#include <linux/unaligned.h>
|
||||
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-io.h"
|
||||
#include "dev.h"
|
||||
#include "calib.h"
|
||||
#include "agn.h"
|
||||
|
|
@ -482,17 +481,17 @@ static void iwlagn_rx_card_state_notif(struct iwl_priv *priv,
|
|||
if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED |
|
||||
CT_CARD_DISABLED)) {
|
||||
|
||||
iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET,
|
||||
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
|
||||
iwl_trans_write32(priv->trans, CSR_UCODE_DRV_GP1_SET,
|
||||
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
|
||||
|
||||
iwl_write_direct32(priv->trans, HBUS_TARG_MBX_C,
|
||||
HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
|
||||
iwl_trans_write_direct32(priv->trans, HBUS_TARG_MBX_C,
|
||||
HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
|
||||
|
||||
if (!(flags & RXON_CARD_DISABLED)) {
|
||||
iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR,
|
||||
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
|
||||
iwl_write_direct32(priv->trans, HBUS_TARG_MBX_C,
|
||||
HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
|
||||
iwl_trans_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR,
|
||||
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
|
||||
iwl_trans_write_direct32(priv->trans, HBUS_TARG_MBX_C,
|
||||
HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
|
||||
}
|
||||
if (flags & CT_CARD_DISABLED)
|
||||
iwl_tt_enter_ct_kill(priv);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2018, 2020 Intel Corporation
|
||||
* Copyright (C) 2018, 2020, 2026 Intel Corporation
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <net/mac80211.h>
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-modparams.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "agn.h"
|
||||
|
|
@ -146,15 +146,15 @@ static void iwl_tt_check_exit_ct_kill(struct timer_list *t)
|
|||
|
||||
if (tt->state == IWL_TI_CT_KILL) {
|
||||
if (priv->thermal_throttle.ct_kill_toggle) {
|
||||
iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR,
|
||||
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
|
||||
iwl_trans_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR,
|
||||
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
|
||||
priv->thermal_throttle.ct_kill_toggle = false;
|
||||
} else {
|
||||
iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET,
|
||||
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
|
||||
iwl_trans_write32(priv->trans, CSR_UCODE_DRV_GP1_SET,
|
||||
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
|
||||
priv->thermal_throttle.ct_kill_toggle = true;
|
||||
}
|
||||
iwl_read32(priv->trans, CSR_UCODE_DRV_GP1);
|
||||
iwl_trans_read32(priv->trans, CSR_UCODE_DRV_GP1);
|
||||
if (iwl_trans_grab_nic_access(priv->trans))
|
||||
iwl_trans_release_nic_access(priv->trans);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,14 +3,13 @@
|
|||
*
|
||||
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2019 Intel Corporation
|
||||
* Copyright (C) 2023, 2025 Intel Corporation
|
||||
* Copyright (C) 2023, 2025-2026 Intel Corporation
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ieee80211.h>
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "dev.h"
|
||||
|
|
|
|||
|
|
@ -3,12 +3,11 @@
|
|||
*
|
||||
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2015 Intel Deutschland GmbH
|
||||
* Copyright (C) 2025 Intel Corporation
|
||||
* Copyright (C) 2025-2026 Intel Corporation
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-fh.h"
|
||||
|
|
|
|||
|
|
@ -525,6 +525,83 @@ iwl_acpi_parse_chains_table(union acpi_object *table,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_acpi_parse_extended_sar_profiles(union acpi_object *wifi_pkg,
|
||||
struct iwl_sar_profile *sar_profiles,
|
||||
u8 num_sub_bands, bool has_cdb)
|
||||
{
|
||||
int n_profiles, pos, ret;
|
||||
bool enabled;
|
||||
|
||||
if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER ||
|
||||
wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER)
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON(ACPI_SAR_NUM_CHAINS_REV0 * num_sub_bands >
|
||||
ARRAY_SIZE(sar_profiles[0].chains) *
|
||||
ARRAY_SIZE(sar_profiles[0].chains[0].subbands)))
|
||||
return -EINVAL;
|
||||
|
||||
enabled = !!(wifi_pkg->package.elements[1].integer.value);
|
||||
n_profiles = wifi_pkg->package.elements[2].integer.value;
|
||||
|
||||
if (n_profiles >= BIOS_SAR_MAX_PROFILE_NUM)
|
||||
return -EINVAL;
|
||||
|
||||
/* the tables start at element 3 */
|
||||
pos = 3;
|
||||
|
||||
BUILD_BUG_ON(ACPI_SAR_NUM_CHAINS_REV0 != ACPI_SAR_NUM_CHAINS_REV1);
|
||||
BUILD_BUG_ON(ACPI_SAR_NUM_CHAINS_REV2 != 2 * ACPI_SAR_NUM_CHAINS_REV0);
|
||||
|
||||
/* parse non-cdb chains for all profiles */
|
||||
for (int i = 0; i < n_profiles; i++) {
|
||||
union acpi_object *table = &wifi_pkg->package.elements[pos];
|
||||
|
||||
ret = iwl_acpi_parse_chains_table(table,
|
||||
sar_profiles[i + 1].chains,
|
||||
ACPI_SAR_NUM_CHAINS_REV0,
|
||||
num_sub_bands);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* go to the next table */
|
||||
pos += ACPI_SAR_NUM_CHAINS_REV0 * num_sub_bands;
|
||||
}
|
||||
|
||||
if (!has_cdb)
|
||||
goto set_enabled;
|
||||
|
||||
if (WARN_ON(ACPI_SAR_NUM_CHAINS_REV0 * 2 * num_sub_bands >
|
||||
ARRAY_SIZE(sar_profiles[0].chains) *
|
||||
ARRAY_SIZE(sar_profiles[0].chains[0].subbands)))
|
||||
return -EINVAL;
|
||||
|
||||
/* parse cdb chains for all profiles */
|
||||
for (int i = 0; i < n_profiles; i++) {
|
||||
struct iwl_sar_profile_chain *chains;
|
||||
union acpi_object *table;
|
||||
|
||||
table = &wifi_pkg->package.elements[pos];
|
||||
chains = &sar_profiles[i + 1].chains[ACPI_SAR_NUM_CHAINS_REV0];
|
||||
ret = iwl_acpi_parse_chains_table(table,
|
||||
chains,
|
||||
ACPI_SAR_NUM_CHAINS_REV0,
|
||||
num_sub_bands);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* go to the next table */
|
||||
pos += ACPI_SAR_NUM_CHAINS_REV0 * num_sub_bands;
|
||||
}
|
||||
|
||||
set_enabled:
|
||||
for (int i = 0; i < n_profiles; i++)
|
||||
sar_profiles[i + 1].enabled = enabled;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_acpi_get_wrds_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
union acpi_object *wifi_pkg, *table, *data;
|
||||
|
|
@ -629,8 +706,12 @@ int iwl_acpi_get_wrds_table(struct iwl_fw_runtime *fwrt)
|
|||
*/
|
||||
ret = iwl_acpi_parse_chains_table(table, fwrt->sar_profiles[0].chains,
|
||||
num_chains, num_sub_bands);
|
||||
if (!ret && flags & IWL_SAR_ENABLE_MSK)
|
||||
if (ret)
|
||||
goto out_free;
|
||||
|
||||
if (flags & IWL_SAR_ENABLE_MSK)
|
||||
fwrt->sar_profiles[0].enabled = true;
|
||||
fwrt->wrds_table_revision = tbl_rev;
|
||||
|
||||
out_free:
|
||||
kfree(data);
|
||||
|
|
@ -640,8 +721,7 @@ int iwl_acpi_get_wrds_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;
|
||||
int i, n_profiles, tbl_rev, pos;
|
||||
int tbl_rev;
|
||||
int ret = 0;
|
||||
u8 num_sub_bands;
|
||||
|
||||
|
|
@ -713,95 +793,149 @@ int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
|
|||
goto out_free;
|
||||
|
||||
read_table:
|
||||
if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER ||
|
||||
wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER) {
|
||||
ret = -EINVAL;
|
||||
ret = iwl_acpi_parse_extended_sar_profiles(wifi_pkg,
|
||||
fwrt->sar_profiles,
|
||||
num_sub_bands,
|
||||
tbl_rev >= 2);
|
||||
if (ret)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (WARN_ON(ACPI_SAR_NUM_CHAINS_REV0 * num_sub_bands >
|
||||
ARRAY_SIZE(fwrt->sar_profiles[0].chains) *
|
||||
ARRAY_SIZE(fwrt->sar_profiles[0].chains[0].subbands))) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
enabled = !!(wifi_pkg->package.elements[1].integer.value);
|
||||
n_profiles = wifi_pkg->package.elements[2].integer.value;
|
||||
|
||||
/*
|
||||
* Check the validity of n_profiles. The EWRD profiles start
|
||||
* from index 1, so the maximum value allowed here is
|
||||
* ACPI_SAR_PROFILES_NUM - 1.
|
||||
*/
|
||||
if (n_profiles >= BIOS_SAR_MAX_PROFILE_NUM) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* the tables start at element 3 */
|
||||
pos = 3;
|
||||
|
||||
BUILD_BUG_ON(ACPI_SAR_NUM_CHAINS_REV0 != ACPI_SAR_NUM_CHAINS_REV1);
|
||||
BUILD_BUG_ON(ACPI_SAR_NUM_CHAINS_REV2 != 2 * ACPI_SAR_NUM_CHAINS_REV0);
|
||||
|
||||
/* parse non-cdb chains for all profiles */
|
||||
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_acpi_parse_chains_table(table,
|
||||
fwrt->sar_profiles[i + 1].chains,
|
||||
ACPI_SAR_NUM_CHAINS_REV0,
|
||||
num_sub_bands);
|
||||
if (ret < 0)
|
||||
goto out_free;
|
||||
|
||||
/* go to the next table */
|
||||
pos += ACPI_SAR_NUM_CHAINS_REV0 * num_sub_bands;
|
||||
}
|
||||
|
||||
/* non-cdb table revisions */
|
||||
if (tbl_rev < 2)
|
||||
goto set_enabled;
|
||||
|
||||
if (WARN_ON(ACPI_SAR_NUM_CHAINS_REV0 * 2 * num_sub_bands >
|
||||
ARRAY_SIZE(fwrt->sar_profiles[0].chains) *
|
||||
ARRAY_SIZE(fwrt->sar_profiles[0].chains[0].subbands))) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* parse cdb chains for all profiles */
|
||||
for (i = 0; i < n_profiles; i++) {
|
||||
struct iwl_sar_profile_chain *chains;
|
||||
union acpi_object *table;
|
||||
|
||||
table = &wifi_pkg->package.elements[pos];
|
||||
chains = &fwrt->sar_profiles[i + 1].chains[ACPI_SAR_NUM_CHAINS_REV0];
|
||||
ret = iwl_acpi_parse_chains_table(table,
|
||||
chains,
|
||||
ACPI_SAR_NUM_CHAINS_REV0,
|
||||
num_sub_bands);
|
||||
if (ret < 0)
|
||||
goto out_free;
|
||||
|
||||
/* go to the next table */
|
||||
pos += ACPI_SAR_NUM_CHAINS_REV0 * num_sub_bands;
|
||||
}
|
||||
|
||||
set_enabled:
|
||||
for (i = 0; i < n_profiles; i++)
|
||||
fwrt->sar_profiles[i + 1].enabled = enabled;
|
||||
fwrt->ewrd_table_revision = tbl_rev;
|
||||
|
||||
out_free:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_acpi_get_wsss_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
union acpi_object *data __free(kfree) = NULL;
|
||||
union acpi_object *wifi_pkg, *table;
|
||||
u8 num_chains, num_sub_bands;
|
||||
int ret, tbl_rev;
|
||||
u32 flags;
|
||||
|
||||
if (fwrt->wrds_table_revision == IWL_BIOS_REVISION_UNSET) {
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"Skipping standalone SAR: WRDS table was not read\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
data = iwl_acpi_get_object(fwrt->dev, ACPI_WSSS_METHOD);
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
switch (fwrt->wrds_table_revision) {
|
||||
case 3:
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
|
||||
ACPI_WRDS_WIFI_DATA_SIZE_REV3,
|
||||
&tbl_rev);
|
||||
num_chains = ACPI_SAR_NUM_CHAINS_REV2;
|
||||
num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV3;
|
||||
break;
|
||||
case 2:
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
|
||||
ACPI_WRDS_WIFI_DATA_SIZE_REV2,
|
||||
&tbl_rev);
|
||||
num_chains = ACPI_SAR_NUM_CHAINS_REV2;
|
||||
num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV2;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (IS_ERR(wifi_pkg))
|
||||
return PTR_ERR(wifi_pkg);
|
||||
|
||||
if (fwrt->wrds_table_revision != tbl_rev) {
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"Skipping standalone SAR: WRDS/WSSS revision mismatch (WRDS rev %d, WSSS rev %d)\n",
|
||||
fwrt->wrds_table_revision,
|
||||
tbl_rev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER)
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON(num_chains * num_sub_bands >
|
||||
ARRAY_SIZE(fwrt->sar_standalone_profiles[0].chains) *
|
||||
ARRAY_SIZE(fwrt->sar_standalone_profiles[0].chains[0].subbands)))
|
||||
return -EINVAL;
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "Reading WSSS (WRDS Standalone) tbl_rev=%d\n",
|
||||
tbl_rev);
|
||||
|
||||
flags = wifi_pkg->package.elements[1].integer.value;
|
||||
|
||||
/* position of the actual table */
|
||||
table = &wifi_pkg->package.elements[2];
|
||||
|
||||
ret = iwl_acpi_parse_chains_table(table,
|
||||
fwrt->sar_standalone_profiles[0].chains,
|
||||
num_chains, num_sub_bands);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (flags & IWL_SAR_ENABLE_MSK)
|
||||
fwrt->sar_standalone_profiles[0].enabled = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_acpi_get_ewss_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
union acpi_object *data __free(kfree) = NULL;
|
||||
union acpi_object *wifi_pkg;
|
||||
u8 num_sub_bands;
|
||||
int tbl_rev;
|
||||
|
||||
if (fwrt->ewrd_table_revision == IWL_BIOS_REVISION_UNSET) {
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"Skipping standalone SAR: EWRD table was not read\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
data = iwl_acpi_get_object(fwrt->dev, ACPI_EWSS_METHOD);
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
switch (fwrt->ewrd_table_revision) {
|
||||
case 3:
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
|
||||
ACPI_EWRD_WIFI_DATA_SIZE_REV3,
|
||||
&tbl_rev);
|
||||
num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV3;
|
||||
break;
|
||||
case 2:
|
||||
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
|
||||
ACPI_EWRD_WIFI_DATA_SIZE_REV2,
|
||||
&tbl_rev);
|
||||
num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV2;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (IS_ERR(wifi_pkg))
|
||||
return PTR_ERR(wifi_pkg);
|
||||
|
||||
if (fwrt->ewrd_table_revision != tbl_rev) {
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"Skipping standalone SAR: EWRD/EWSS revision mismatch (EWRD rev %d, EWSS rev %d)\n",
|
||||
fwrt->ewrd_table_revision, tbl_rev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "Reading EWSS (EWRD Standalone) tbl_rev=%d\n",
|
||||
tbl_rev);
|
||||
|
||||
return iwl_acpi_parse_extended_sar_profiles(wifi_pkg,
|
||||
fwrt->sar_standalone_profiles,
|
||||
num_sub_bands,
|
||||
fwrt->ewrd_table_revision >= 2);
|
||||
}
|
||||
|
||||
int iwl_acpi_get_wgds_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
union acpi_object *wifi_pkg, *data;
|
||||
|
|
@ -1153,7 +1287,8 @@ void iwl_acpi_get_guid_lock_status(struct iwl_fw_runtime *fwrt)
|
|||
}
|
||||
|
||||
if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER ||
|
||||
wifi_pkg->package.elements[1].integer.value > ACPI_GLAI_MAX_STATUS)
|
||||
wifi_pkg->package.elements[1].integer.value >
|
||||
UEFI_CNV_GUID_TEST_MODE)
|
||||
goto out_free;
|
||||
|
||||
fwrt->uefi_tables_lock_status =
|
||||
|
|
@ -1165,7 +1300,6 @@ void iwl_acpi_get_guid_lock_status(struct iwl_fw_runtime *fwrt)
|
|||
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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#define ACPI_WRDS_METHOD "WRDS"
|
||||
#define ACPI_EWRD_METHOD "EWRD"
|
||||
#define ACPI_WSSS_METHOD "WSSS"
|
||||
#define ACPI_EWSS_METHOD "EWSS"
|
||||
#define ACPI_WGDS_METHOD "WGDS"
|
||||
#define ACPI_WRDD_METHOD "WRDD"
|
||||
#define ACPI_SPLC_METHOD "SPLC"
|
||||
|
|
@ -89,7 +91,6 @@
|
|||
* 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,
|
||||
|
|
@ -111,9 +112,6 @@
|
|||
#define ACPI_PPAG_WIFI_DATA_SIZE_V3 ((ACPI_PPAG_NUM_CHAINS * \
|
||||
ACPI_PPAG_NUM_BANDS_V3) + 2)
|
||||
|
||||
/* The Inidcator whether UEFI WIFI GUID tables are locked is read from ACPI */
|
||||
#define UEFI_WIFI_GUID_UNLOCKED 0
|
||||
|
||||
#define ACPI_DSM_REV 0
|
||||
|
||||
#define DSM_INTERNAL_FUNC_GET_PLAT_INFO 1
|
||||
|
|
@ -179,6 +177,10 @@ int iwl_acpi_get_wrds_table(struct iwl_fw_runtime *fwrt);
|
|||
|
||||
int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
int iwl_acpi_get_wsss_table(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
int iwl_acpi_get_ewss_table(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
int iwl_acpi_get_wgds_table(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
int iwl_acpi_get_tas_table(struct iwl_fw_runtime *fwrt,
|
||||
|
|
@ -233,6 +235,16 @@ static inline int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_acpi_get_wsss_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_acpi_get_ewss_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_acpi_get_wgds_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -569,8 +569,9 @@ enum iwl_legacy_cmds {
|
|||
|
||||
/**
|
||||
* @WOWLAN_KEK_KCK_MATERIAL: &struct iwl_wowlan_kek_kck_material_cmd_v2,
|
||||
* &struct iwl_wowlan_kek_kck_material_cmd_v3 or
|
||||
* &struct iwl_wowlan_kek_kck_material_cmd_v4
|
||||
* &struct iwl_wowlan_kek_kck_material_cmd_v3,
|
||||
* &struct iwl_wowlan_kek_kck_material_cmd_v4 or
|
||||
* &struct iwl_wowlan_kek_kck_material_cmd
|
||||
*/
|
||||
WOWLAN_KEK_KCK_MATERIAL = 0xe4,
|
||||
|
||||
|
|
|
|||
328
drivers/net/wireless/intel/iwlwifi/fw/api/ctxt-info-v2.h
Normal file
328
drivers/net/wireless/intel/iwlwifi/fw/api/ctxt-info-v2.h
Normal file
|
|
@ -0,0 +1,328 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2026 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_fw_api_context_info_v2_h__
|
||||
#define __iwl_fw_api_context_info_v2_h__
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/bits.h>
|
||||
#include "ctxt-info.h"
|
||||
|
||||
/* CSR addresses used by context info v2 */
|
||||
#define CSR_CTXT_INFO_BOOT_CTRL 0x0
|
||||
#define CSR_CTXT_INFO_ADDR 0x118
|
||||
#define CSR_IML_DATA_ADDR 0x120
|
||||
#define CSR_IML_SIZE_ADDR 0x128
|
||||
#define CSR_IML_RESP_ADDR 0x12c
|
||||
|
||||
#define UNFRAGMENTED_PNVM_PAYLOADS_NUMBER 2
|
||||
|
||||
/* Set bit for enabling automatic function boot */
|
||||
#define CSR_AUTO_FUNC_BOOT_ENA BIT(1)
|
||||
/* Set bit for initiating function boot */
|
||||
#define CSR_AUTO_FUNC_INIT BIT(7)
|
||||
|
||||
/**
|
||||
* enum iwl_prph_scratch_mtr_format - tfd size configuration
|
||||
* @IWL_PRPH_MTR_FORMAT_16B: 16 bit tfd
|
||||
* @IWL_PRPH_MTR_FORMAT_32B: 32 bit tfd
|
||||
* @IWL_PRPH_MTR_FORMAT_64B: 64 bit tfd
|
||||
* @IWL_PRPH_MTR_FORMAT_256B: 256 bit tfd
|
||||
*/
|
||||
enum iwl_prph_scratch_mtr_format {
|
||||
IWL_PRPH_MTR_FORMAT_16B = 0x0,
|
||||
IWL_PRPH_MTR_FORMAT_32B = 0x40000,
|
||||
IWL_PRPH_MTR_FORMAT_64B = 0x80000,
|
||||
IWL_PRPH_MTR_FORMAT_256B = 0xC0000,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_prph_scratch_flags - PRPH scratch control flags
|
||||
* @IWL_PRPH_SCRATCH_IMR_DEBUG_EN: IMR support for debug
|
||||
* @IWL_PRPH_SCRATCH_EARLY_DEBUG_EN: enable early debug conf
|
||||
* @IWL_PRPH_SCRATCH_EDBG_DEST_DRAM: use DRAM, with size allocated
|
||||
* in hwm config.
|
||||
* @IWL_PRPH_SCRATCH_EDBG_DEST_INTERNAL: use buffer on SRAM
|
||||
* @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_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.
|
||||
* There are 4 optional values: 0: 16 bit, 1: 32 bit, 2: 64 bit,
|
||||
* 3: 256 bit.
|
||||
* @IWL_PRPH_SCRATCH_RB_SIZE_EXT_MASK: RB size full information, ignored
|
||||
* by older firmware versions, so set IWL_PRPH_SCRATCH_RB_SIZE_4K
|
||||
* appropriately; use the below values for this.
|
||||
* @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.
|
||||
* @IWL_PRPH_SCRATCH_TOP_RESET: request TOP reset
|
||||
*/
|
||||
enum iwl_prph_scratch_flags {
|
||||
IWL_PRPH_SCRATCH_IMR_DEBUG_EN = BIT(1),
|
||||
IWL_PRPH_SCRATCH_EARLY_DEBUG_EN = BIT(4),
|
||||
IWL_PRPH_SCRATCH_EDBG_DEST_DRAM = BIT(8),
|
||||
IWL_PRPH_SCRATCH_EDBG_DEST_INTERNAL = BIT(9),
|
||||
IWL_PRPH_SCRATCH_EDBG_DEST_ST_ARBITER = BIT(10),
|
||||
IWL_PRPH_SCRATCH_EDBG_DEST_TB22DTF = BIT(11),
|
||||
IWL_PRPH_SCRATCH_RB_SIZE_4K = BIT(16),
|
||||
IWL_PRPH_SCRATCH_MTR_MODE = BIT(17),
|
||||
IWL_PRPH_SCRATCH_MTR_FORMAT = BIT(18) | BIT(19),
|
||||
IWL_PRPH_SCRATCH_RB_SIZE_EXT_MASK = 0xf << 20,
|
||||
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),
|
||||
IWL_PRPH_SCRATCH_TOP_RESET = BIT(30),
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_prph_scratch_ext_flags - PRPH scratch control ext flags
|
||||
* @IWL_PRPH_SCRATCH_EXT_EXT_FSEQ: external FSEQ image provided
|
||||
* @IWL_PRPH_SCRATCH_EXT_URM_FW: switch to URM mode based on fw setting
|
||||
* @IWL_PRPH_SCRATCH_EXT_URM_PERM: switch to permanent URM mode
|
||||
* @IWL_PRPH_SCRATCH_EXT_32KHZ_CLK_VALID: use external 32 KHz clock
|
||||
*/
|
||||
enum iwl_prph_scratch_ext_flags {
|
||||
IWL_PRPH_SCRATCH_EXT_EXT_FSEQ = BIT(0),
|
||||
IWL_PRPH_SCRATCH_EXT_URM_FW = BIT(4),
|
||||
IWL_PRPH_SCRATCH_EXT_URM_PERM = BIT(5),
|
||||
IWL_PRPH_SCRATCH_EXT_32KHZ_CLK_VALID = BIT(8),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_prph_scratch_version - version structure
|
||||
* @mac_id: SKU and revision id
|
||||
* @version: prph scratch information version id
|
||||
* @size: the size of the context information in DWs
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_prph_scratch_version {
|
||||
__le16 mac_id;
|
||||
__le16 version;
|
||||
__le16 size;
|
||||
__le16 reserved;
|
||||
} __packed; /* PERIPH_SCRATCH_VERSION_S */
|
||||
|
||||
/**
|
||||
* struct iwl_prph_scratch_control - control structure
|
||||
* @control_flags: context information flags see &enum iwl_prph_scratch_flags
|
||||
* @control_flags_ext: context information for extended flags,
|
||||
* see &enum iwl_prph_scratch_ext_flags
|
||||
*/
|
||||
struct iwl_prph_scratch_control {
|
||||
__le32 control_flags;
|
||||
__le32 control_flags_ext;
|
||||
} __packed; /* PERIPH_SCRATCH_CONTROL_S */
|
||||
|
||||
/**
|
||||
* struct iwl_prph_scratch_pnvm_cfg - PNVM scratch
|
||||
* @pnvm_base_addr: PNVM start address
|
||||
* @pnvm_size: the size of the PNVM image in bytes
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_prph_scratch_pnvm_cfg {
|
||||
__le64 pnvm_base_addr;
|
||||
__le32 pnvm_size;
|
||||
__le32 reserved;
|
||||
} __packed; /* PERIPH_SCRATCH_PNVM_CFG_S */
|
||||
|
||||
/**
|
||||
* struct iwl_prph_scratch_mem_desc_addr_array - DRAM
|
||||
* @mem_descs: array of dram addresses.
|
||||
* Each address is the beginning of a PNVM payload.
|
||||
*/
|
||||
struct iwl_prph_scratch_mem_desc_addr_array {
|
||||
__le64 mem_descs[IPC_DRAM_MAP_ENTRY_NUM_MAX];
|
||||
} __packed; /* PERIPH_SCRATCH_MEM_DESC_ADDR_ARRAY_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_prph_scratch_hwm_cfg - hwm config
|
||||
* @hwm_base_addr: hwm start address
|
||||
* @hwm_size: hwm size in DWs
|
||||
* @debug_token_config: debug preset
|
||||
*/
|
||||
struct iwl_prph_scratch_hwm_cfg {
|
||||
__le64 hwm_base_addr;
|
||||
__le32 hwm_size;
|
||||
__le32 debug_token_config;
|
||||
} __packed; /* PERIPH_SCRATCH_HWM_CFG_S */
|
||||
|
||||
/**
|
||||
* struct iwl_prph_scratch_rbd_cfg - RBDs configuration
|
||||
* @free_rbd_addr: default queue free RB CB base address
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_prph_scratch_rbd_cfg {
|
||||
__le64 free_rbd_addr;
|
||||
__le32 reserved;
|
||||
} __packed; /* PERIPH_SCRATCH_RBD_CFG_S */
|
||||
|
||||
/**
|
||||
* struct iwl_prph_scratch_uefi_cfg - prph scratch reduce power table
|
||||
* @base_addr: reduce power table address
|
||||
* @size: the size of the entire power table image
|
||||
* @reserved: (reserved)
|
||||
*/
|
||||
struct iwl_prph_scratch_uefi_cfg {
|
||||
__le64 base_addr;
|
||||
__le32 size;
|
||||
__le32 reserved;
|
||||
} __packed; /* PERIPH_SCRATCH_UEFI_CFG_S */
|
||||
|
||||
/**
|
||||
* struct iwl_prph_scratch_step_cfg - prph scratch step configuration
|
||||
* @mbx_addr_0: [0:7] revision,
|
||||
* [8:15] cnvi_to_cnvr length,
|
||||
* [16:23] cnvr_to_cnvi channel length,
|
||||
* [24:31] radio1 reserved
|
||||
* @mbx_addr_1: [0:7] radio2 reserved
|
||||
*/
|
||||
struct iwl_prph_scratch_step_cfg {
|
||||
__le32 mbx_addr_0;
|
||||
__le32 mbx_addr_1;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_prph_scratch_ctrl_cfg - prph scratch ctrl and config
|
||||
* @version: version information of context info and HW
|
||||
* @control: control flags of FH configurations
|
||||
* @pnvm_cfg: ror configuration
|
||||
* @hwm_cfg: hwm configuration
|
||||
* @rbd_cfg: default RX queue configuration
|
||||
* @reduce_power_cfg: UEFI power reduction table
|
||||
* @step_cfg: step configuration
|
||||
*/
|
||||
struct iwl_prph_scratch_ctrl_cfg {
|
||||
struct iwl_prph_scratch_version version;
|
||||
struct iwl_prph_scratch_control control;
|
||||
struct iwl_prph_scratch_pnvm_cfg pnvm_cfg;
|
||||
struct iwl_prph_scratch_hwm_cfg hwm_cfg;
|
||||
struct iwl_prph_scratch_rbd_cfg rbd_cfg;
|
||||
struct iwl_prph_scratch_uefi_cfg reduce_power_cfg;
|
||||
struct iwl_prph_scratch_step_cfg step_cfg;
|
||||
} __packed; /* PERIPH_SCRATCH_CTRL_CFG_S */
|
||||
|
||||
/**
|
||||
* struct iwl_context_info_v2 - device INIT configuration
|
||||
* @version: version of the context information
|
||||
* @size: size of context information in DWs
|
||||
* @config: context in which the peripheral would execute - a subset of
|
||||
* capability csr register published by the peripheral
|
||||
* @prph_info_base_addr: the peripheral information structure start address
|
||||
* @cr_head_idx_arr_base_addr: the completion ring head index array
|
||||
* start address
|
||||
* @tr_tail_idx_arr_base_addr: the transfer ring tail index array
|
||||
* start address
|
||||
* @cr_tail_idx_arr_base_addr: the completion ring tail index array
|
||||
* start address
|
||||
* @tr_head_idx_arr_base_addr: the transfer ring head index array
|
||||
* start address
|
||||
* @cr_idx_arr_size: number of entries in the completion ring index array
|
||||
* @tr_idx_arr_size: number of entries in the transfer ring index array
|
||||
* @mtr_base_addr: the message transfer ring start address
|
||||
* @mcr_base_addr: the message completion ring start address
|
||||
* @mtr_size: number of entries which the message transfer ring can hold
|
||||
* @mcr_size: number of entries which the message completion ring can hold
|
||||
* @mtr_doorbell_vec: the doorbell vector associated with the message
|
||||
* transfer ring
|
||||
* @mcr_doorbell_vec: the doorbell vector associated with the message
|
||||
* completion ring
|
||||
* @mtr_msi_vec: the MSI which shall be generated by the peripheral after
|
||||
* completing a transfer descriptor in the message transfer ring
|
||||
* @mcr_msi_vec: the MSI which shall be generated by the peripheral after
|
||||
* completing a completion descriptor in the message completion ring
|
||||
* @mtr_opt_header_size: the size of the optional header in the transfer
|
||||
* descriptor associated with the message transfer ring in DWs
|
||||
* @mtr_opt_footer_size: the size of the optional footer in the transfer
|
||||
* descriptor associated with the message transfer ring in DWs
|
||||
* @mcr_opt_header_size: the size of the optional header in the completion
|
||||
* descriptor associated with the message completion ring in DWs
|
||||
* @mcr_opt_footer_size: the size of the optional footer in the completion
|
||||
* descriptor associated with the message completion ring in DWs
|
||||
* @msg_rings_ctrl_flags: message rings control flags
|
||||
* @prph_info_msi_vec: the MSI which shall be generated by the peripheral
|
||||
* after updating the Peripheral Information structure
|
||||
* @prph_scratch_base_addr: the peripheral scratch structure start address
|
||||
* @prph_scratch_size: the size of the peripheral scratch structure in DWs
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_context_info_v2 {
|
||||
__le16 version;
|
||||
__le16 size;
|
||||
__le32 config;
|
||||
__le64 prph_info_base_addr;
|
||||
__le64 cr_head_idx_arr_base_addr;
|
||||
__le64 tr_tail_idx_arr_base_addr;
|
||||
__le64 cr_tail_idx_arr_base_addr;
|
||||
__le64 tr_head_idx_arr_base_addr;
|
||||
__le16 cr_idx_arr_size;
|
||||
__le16 tr_idx_arr_size;
|
||||
__le64 mtr_base_addr;
|
||||
__le64 mcr_base_addr;
|
||||
__le16 mtr_size;
|
||||
__le16 mcr_size;
|
||||
__le16 mtr_doorbell_vec;
|
||||
__le16 mcr_doorbell_vec;
|
||||
__le16 mtr_msi_vec;
|
||||
__le16 mcr_msi_vec;
|
||||
u8 mtr_opt_header_size;
|
||||
u8 mtr_opt_footer_size;
|
||||
u8 mcr_opt_header_size;
|
||||
u8 mcr_opt_footer_size;
|
||||
__le16 msg_rings_ctrl_flags;
|
||||
__le16 prph_info_msi_vec;
|
||||
__le64 prph_scratch_base_addr;
|
||||
__le32 prph_scratch_size;
|
||||
__le32 reserved;
|
||||
} __packed; /* IPC_CONTEXT_INFO_S */
|
||||
|
||||
#define IWL_NUM_DRAM_FSEQ_ENTRIES 8
|
||||
|
||||
/**
|
||||
* struct iwl_context_info_dram_fseq - images DRAM map (with fseq)
|
||||
* each entry in the map represents a DRAM chunk of up to 32 KB
|
||||
* @common: UMAC/LMAC/virtual images
|
||||
* @fseq_img: FSEQ image DRAM map
|
||||
*/
|
||||
struct iwl_context_info_dram_fseq {
|
||||
struct iwl_context_info_dram_nonfseq common;
|
||||
__le64 fseq_img[IWL_NUM_DRAM_FSEQ_ENTRIES];
|
||||
} __packed; /* PERIPH_SCRATCH_DRAM_MAP_S */
|
||||
|
||||
/**
|
||||
* 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 fseq_override;
|
||||
__le32 step_analog_params;
|
||||
__le32 reserved[8];
|
||||
struct iwl_context_info_dram_fseq dram;
|
||||
} __packed; /* PERIPH_SCRATCH_S */
|
||||
|
||||
/**
|
||||
* struct iwl_prph_info - peripheral information
|
||||
* @boot_stage_mirror: reflects the value in the Boot Stage CSR register
|
||||
* @ipc_status_mirror: reflects the value in the IPC Status CSR register
|
||||
* @sleep_notif: indicates the peripheral sleep status
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_prph_info {
|
||||
__le32 boot_stage_mirror;
|
||||
__le32 ipc_status_mirror;
|
||||
__le32 sleep_notif;
|
||||
__le32 reserved;
|
||||
} __packed; /* PERIPH_INFO_S */
|
||||
|
||||
#endif /* __iwl_fw_api_context_info_v2_h__ */
|
||||
185
drivers/net/wireless/intel/iwlwifi/fw/api/ctxt-info.h
Normal file
185
drivers/net/wireless/intel/iwlwifi/fw/api/ctxt-info.h
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2026 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_fw_api_context_info_h__
|
||||
#define __iwl_fw_api_context_info_h__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* maximum number of DRAM map entries supported by FW */
|
||||
#define IWL_MAX_DRAM_ENTRY 64
|
||||
#define CSR_CTXT_INFO_BA 0x40
|
||||
|
||||
/**
|
||||
* enum iwl_context_info_flags - Context information control flags
|
||||
* @IWL_CTXT_INFO_AUTO_FUNC_INIT: If set, FW will not wait before interrupting
|
||||
* the init done for driver command that configures several system modes
|
||||
* @IWL_CTXT_INFO_EARLY_DEBUG: enable early debug
|
||||
* @IWL_CTXT_INFO_ENABLE_CDMP: enable core dump
|
||||
* @IWL_CTXT_INFO_RB_CB_SIZE: mask of the RBD Cyclic Buffer Size
|
||||
* exponent, the actual size is 2**value, valid sizes are 8-2048.
|
||||
* The value is four bits long. Maximum valid exponent is 12
|
||||
* @IWL_CTXT_INFO_TFD_FORMAT_LONG: use long TFD Format (the
|
||||
* default is short format - not supported by the driver)
|
||||
* @IWL_CTXT_INFO_RB_SIZE: RB size mask
|
||||
* (values are IWL_CTXT_INFO_RB_SIZE_*K)
|
||||
* @IWL_CTXT_INFO_RB_SIZE_1K: Value for 1K RB size
|
||||
* @IWL_CTXT_INFO_RB_SIZE_2K: Value for 2K RB size
|
||||
* @IWL_CTXT_INFO_RB_SIZE_4K: Value for 4K RB size
|
||||
* @IWL_CTXT_INFO_RB_SIZE_8K: Value for 8K RB size
|
||||
* @IWL_CTXT_INFO_RB_SIZE_12K: Value for 12K RB size
|
||||
* @IWL_CTXT_INFO_RB_SIZE_16K: Value for 16K RB size
|
||||
* @IWL_CTXT_INFO_RB_SIZE_20K: Value for 20K RB size
|
||||
* @IWL_CTXT_INFO_RB_SIZE_24K: Value for 24K RB size
|
||||
* @IWL_CTXT_INFO_RB_SIZE_28K: Value for 28K RB size
|
||||
* @IWL_CTXT_INFO_RB_SIZE_32K: Value for 32K RB size
|
||||
*/
|
||||
enum iwl_context_info_flags {
|
||||
IWL_CTXT_INFO_AUTO_FUNC_INIT = 0x0001,
|
||||
IWL_CTXT_INFO_EARLY_DEBUG = 0x0002,
|
||||
IWL_CTXT_INFO_ENABLE_CDMP = 0x0004,
|
||||
IWL_CTXT_INFO_RB_CB_SIZE = 0x00f0,
|
||||
IWL_CTXT_INFO_TFD_FORMAT_LONG = 0x0100,
|
||||
IWL_CTXT_INFO_RB_SIZE = 0x1e00,
|
||||
IWL_CTXT_INFO_RB_SIZE_1K = 0x1,
|
||||
IWL_CTXT_INFO_RB_SIZE_2K = 0x2,
|
||||
IWL_CTXT_INFO_RB_SIZE_4K = 0x4,
|
||||
IWL_CTXT_INFO_RB_SIZE_8K = 0x8,
|
||||
IWL_CTXT_INFO_RB_SIZE_12K = 0x9,
|
||||
IWL_CTXT_INFO_RB_SIZE_16K = 0xa,
|
||||
IWL_CTXT_INFO_RB_SIZE_20K = 0xb,
|
||||
IWL_CTXT_INFO_RB_SIZE_24K = 0xc,
|
||||
IWL_CTXT_INFO_RB_SIZE_28K = 0xd,
|
||||
IWL_CTXT_INFO_RB_SIZE_32K = 0xe,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_context_info_version - version structure
|
||||
* @mac_id: SKU and revision id
|
||||
* @version: context information version id
|
||||
* @size: the size of the context information in DWs
|
||||
* @reserved: (reserved)
|
||||
*/
|
||||
struct iwl_context_info_version {
|
||||
__le16 mac_id;
|
||||
__le16 version;
|
||||
__le16 size;
|
||||
__le16 reserved;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_context_info_control - version structure
|
||||
* @control_flags: context information flags see &enum iwl_context_info_flags
|
||||
* @reserved: (reserved)
|
||||
*/
|
||||
struct iwl_context_info_control {
|
||||
__le32 control_flags;
|
||||
__le32 reserved;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_context_info_dram_nonfseq - images DRAM map
|
||||
* each entry in the map represents a DRAM chunk of up to 32 KB
|
||||
* @umac_img: UMAC image DRAM map
|
||||
* @lmac_img: LMAC image DRAM map
|
||||
* @virtual_img: paged image DRAM map
|
||||
*/
|
||||
struct iwl_context_info_dram_nonfseq {
|
||||
__le64 umac_img[IWL_MAX_DRAM_ENTRY];
|
||||
__le64 lmac_img[IWL_MAX_DRAM_ENTRY];
|
||||
__le64 virtual_img[IWL_MAX_DRAM_ENTRY];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_context_info_rbd_cfg - RBDs configuration
|
||||
* @free_rbd_addr: default queue free RB CB base address
|
||||
* @used_rbd_addr: default queue used RB CB base address
|
||||
* @status_wr_ptr: default queue used RB status write pointer
|
||||
*/
|
||||
struct iwl_context_info_rbd_cfg {
|
||||
__le64 free_rbd_addr;
|
||||
__le64 used_rbd_addr;
|
||||
__le64 status_wr_ptr;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_context_info_hcmd_cfg - command queue configuration
|
||||
* @cmd_queue_addr: address of command queue
|
||||
* @cmd_queue_size: number of entries
|
||||
* @reserved: (reserved)
|
||||
*/
|
||||
struct iwl_context_info_hcmd_cfg {
|
||||
__le64 cmd_queue_addr;
|
||||
u8 cmd_queue_size;
|
||||
u8 reserved[7];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_context_info_dump_cfg - Core Dump configuration
|
||||
* @core_dump_addr: core dump (debug DRAM address) start address
|
||||
* @core_dump_size: size, in DWs
|
||||
* @reserved: (reserved)
|
||||
*/
|
||||
struct iwl_context_info_dump_cfg {
|
||||
__le64 core_dump_addr;
|
||||
__le32 core_dump_size;
|
||||
__le32 reserved;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_context_info_pnvm_cfg - platform NVM data configuration
|
||||
* @platform_nvm_addr: Platform NVM data start address
|
||||
* @platform_nvm_size: size in DWs
|
||||
* @reserved: (reserved)
|
||||
*/
|
||||
struct iwl_context_info_pnvm_cfg {
|
||||
__le64 platform_nvm_addr;
|
||||
__le32 platform_nvm_size;
|
||||
__le32 reserved;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_context_info_early_dbg_cfg - early debug configuration for
|
||||
* dumping DRAM addresses
|
||||
* @early_debug_addr: early debug start address
|
||||
* @early_debug_size: size in DWs
|
||||
* @reserved: (reserved)
|
||||
*/
|
||||
struct iwl_context_info_early_dbg_cfg {
|
||||
__le64 early_debug_addr;
|
||||
__le32 early_debug_size;
|
||||
__le32 reserved;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_context_info - device INIT configuration
|
||||
* @version: version information of context info and HW
|
||||
* @control: control flags of FH configurations
|
||||
* @reserved0: (reserved)
|
||||
* @rbd_cfg: default RX queue configuration
|
||||
* @hcmd_cfg: command queue configuration
|
||||
* @reserved1: (reserved)
|
||||
* @dump_cfg: core dump data
|
||||
* @edbg_cfg: early debug configuration
|
||||
* @pnvm_cfg: platform nvm configuration
|
||||
* @reserved2: (reserved)
|
||||
* @dram: firmware image addresses in DRAM
|
||||
* @reserved3: (reserved)
|
||||
*/
|
||||
struct iwl_context_info {
|
||||
struct iwl_context_info_version version;
|
||||
struct iwl_context_info_control control;
|
||||
__le64 reserved0;
|
||||
struct iwl_context_info_rbd_cfg rbd_cfg;
|
||||
struct iwl_context_info_hcmd_cfg hcmd_cfg;
|
||||
__le32 reserved1[4];
|
||||
struct iwl_context_info_dump_cfg dump_cfg;
|
||||
struct iwl_context_info_early_dbg_cfg edbg_cfg;
|
||||
struct iwl_context_info_pnvm_cfg pnvm_cfg;
|
||||
__le32 reserved2[16];
|
||||
struct iwl_context_info_dram_nonfseq dram;
|
||||
__le32 reserved3[16];
|
||||
} __packed; /* BOOT_LOADER_CONTEXT_INFO_S */
|
||||
|
||||
#endif /* __iwl_fw_api_context_info_h__ */
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2025 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2026 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -366,16 +366,16 @@ enum iwl_wowlan_flags {
|
|||
ENABLE_L3_FILTERING = BIT(1),
|
||||
ENABLE_NBNS_FILTERING = BIT(2),
|
||||
ENABLE_DHCP_FILTERING = BIT(3),
|
||||
ENABLE_STORE_BEACON = BIT(4),
|
||||
EPP_ROBUST_CONNECTION = BIT(4),
|
||||
HAS_BEACON_PROTECTION = BIT(5),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_config_cmd_v6 - WoWLAN configuration (versions 5 and 6)
|
||||
* @wakeup_filter: filter from &enum iwl_wowlan_wakeup_filters
|
||||
* @non_qos_seq: non-QoS sequence counter to use next.
|
||||
* @non_qos_seq: last used non-QoS sequence counter.
|
||||
* Reserved if the struct has version >= 6.
|
||||
* @qos_seq: QoS sequence counters to use next
|
||||
* @qos_seq: last used QoS sequence counters
|
||||
* @wowlan_ba_teardown_tids: bitmap of BA sessions to tear down
|
||||
* @is_11n_connection: indicates HT connection
|
||||
* @offloading_tid: TID reserved for firmware use
|
||||
|
|
@ -422,6 +422,7 @@ struct iwl_wowlan_config_cmd {
|
|||
#define WOWLAN_IGTK_MIN_INDEX 4
|
||||
#define WOWLAN_BIGTK_KEYS_NUM 2
|
||||
#define WOWLAN_BIGTK_MIN_INDEX 6
|
||||
#define WOWLAN_CIGTK_KEYS_NUM 2
|
||||
|
||||
/*
|
||||
* WOWLAN_TSC_RSC_PARAMS
|
||||
|
|
@ -531,6 +532,20 @@ struct iwl_wowlan_kek_kck_material_cmd_v4 {
|
|||
__le32 bigtk_cipher;
|
||||
} __packed; /* KEK_KCK_MATERIAL_API_S_VER_4 */
|
||||
|
||||
struct iwl_wowlan_kek_kck_material_cmd {
|
||||
__le32 sta_id;
|
||||
u8 kck[IWL_KCK_MAX_SIZE];
|
||||
u8 kek[IWL_KEK_MAX_SIZE];
|
||||
__le16 kck_len;
|
||||
__le16 kek_len;
|
||||
__le64 replay_ctr;
|
||||
__le32 akm;
|
||||
__le32 gtk_cipher;
|
||||
__le32 igtk_cipher;
|
||||
__le32 bigtk_cipher;
|
||||
__le32 cigtk_cipher;
|
||||
} __packed; /* KEK_KCK_MATERIAL_API_S_VER_5 */
|
||||
|
||||
struct iwl_wowlan_get_status_cmd {
|
||||
__le32 sta_id;
|
||||
} __packed; /* WOWLAN_GET_STATUSES_CMD_API_S_VER_1 */
|
||||
|
|
@ -717,8 +732,8 @@ struct iwl_wowlan_igtk_status {
|
|||
* @gtk: GTK data
|
||||
* @replay_ctr: GTK rekey replay counter
|
||||
* @pattern_number: number of the matched pattern
|
||||
* @non_qos_seq_ctr: non-QoS sequence counter to use next
|
||||
* @qos_seq_ctr: QoS sequence counters to use next
|
||||
* @non_qos_seq_ctr: last used non-QoS sequence counter
|
||||
* @qos_seq_ctr: last used QoS sequence counters
|
||||
* @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
|
||||
|
|
@ -748,8 +763,8 @@ struct iwl_wowlan_status_v6 {
|
|||
* @igtk: IGTK data
|
||||
* @replay_ctr: GTK rekey replay counter
|
||||
* @pattern_number: number of the matched pattern
|
||||
* @non_qos_seq_ctr: non-QoS sequence counter to use next
|
||||
* @qos_seq_ctr: QoS sequence counters to use next
|
||||
* @non_qos_seq_ctr: last used non-QoS sequence counter
|
||||
* @qos_seq_ctr: last used QoS sequence counters
|
||||
* @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
|
||||
|
|
@ -781,7 +796,7 @@ struct iwl_wowlan_status_v7 {
|
|||
* @replay_ctr: GTK rekey replay counter
|
||||
* @pattern_number: number of the matched patterns
|
||||
* @reserved1: reserved
|
||||
* @qos_seq_ctr: QoS sequence counters to use next
|
||||
* @qos_seq_ctr: last used QoS sequence counters
|
||||
* @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
|
||||
|
|
@ -812,19 +827,21 @@ struct iwl_wowlan_info_notif_v1 {
|
|||
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_1 */
|
||||
|
||||
/* MAX MLO keys of non-active links that can arrive in the notification */
|
||||
#define WOWLAN_MAX_MLO_KEYS 18
|
||||
#define WOWLAN_MAX_MLO_KEYS 24
|
||||
|
||||
/**
|
||||
* 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_TYPE_CIGTK: CIGTK
|
||||
* @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_TYPE_CIGTK,
|
||||
WOWLAN_MLO_GTK_KEY_NUM_TYPES
|
||||
}; /* WOWLAN_MLO_GTK_KEY_TYPE_API_E_VER_1 */
|
||||
|
||||
|
|
@ -865,7 +882,7 @@ struct iwl_wowlan_mlo_gtk {
|
|||
* @replay_ctr: GTK rekey replay counter
|
||||
* @pattern_number: number of the matched patterns
|
||||
* @reserved1: reserved
|
||||
* @qos_seq_ctr: QoS sequence counters to use next
|
||||
* @qos_seq_ctr: last used QoS sequence counters
|
||||
* @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
|
||||
|
|
@ -899,7 +916,7 @@ struct iwl_wowlan_info_notif_v3 {
|
|||
* @bigtk: BIGTK data
|
||||
* @replay_ctr: GTK rekey replay counter
|
||||
* @pattern_number: number of the matched patterns
|
||||
* @qos_seq_ctr: QoS sequence counters to use next
|
||||
* @qos_seq_ctr: last used QoS sequence counter for @tid_offloaded_tx
|
||||
* @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
|
||||
|
|
@ -932,13 +949,53 @@ struct iwl_wowlan_info_notif_v5 {
|
|||
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_5 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_info_notif - WoWLAN information notification
|
||||
* struct iwl_wowlan_info_notif_v6 - 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
|
||||
* @qos_seq_ctr: QoS sequence counters to use next
|
||||
* @qos_seq_ctr: last used QoS sequence counter for @tid_offloaded_tx
|
||||
* @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
|
||||
* @tid_offloaded_tx: tid used by the firmware to transmit data packets
|
||||
* while in wowlan
|
||||
* @mlo_gtks: array of GTKs of size num_mlo_link_keys
|
||||
*/
|
||||
struct iwl_wowlan_info_notif_v6 {
|
||||
struct iwl_wowlan_gtk_status 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 qos_seq_ctr;
|
||||
__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 tid_offloaded_tx;
|
||||
struct iwl_wowlan_mlo_gtk mlo_gtks[];
|
||||
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_6 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_info_notif - WoWLAN information notification
|
||||
* @gtk: GTK data
|
||||
* @igtk: IGTK data
|
||||
* @bigtk: BIGTK data
|
||||
* @cigtk: CIGTK data
|
||||
* @replay_ctr: GTK rekey replay counter
|
||||
* @pattern_number: number of the matched patterns
|
||||
* @qos_seq_ctr: last used QoS sequence counter for @tid_offloaded_tx
|
||||
* @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
|
||||
|
|
@ -956,6 +1013,7 @@ struct iwl_wowlan_info_notif {
|
|||
struct iwl_wowlan_gtk_status 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];
|
||||
struct iwl_wowlan_igtk_status cigtk[WOWLAN_CIGTK_KEYS_NUM];
|
||||
__le64 replay_ctr;
|
||||
__le16 pattern_number;
|
||||
__le16 qos_seq_ctr;
|
||||
|
|
@ -968,7 +1026,7 @@ struct iwl_wowlan_info_notif {
|
|||
u8 num_mlo_link_keys;
|
||||
u8 tid_offloaded_tx;
|
||||
struct iwl_wowlan_mlo_gtk mlo_gtks[];
|
||||
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_6 */
|
||||
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_7 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_wake_pkt_notif - WoWLAN wake packet notification
|
||||
|
|
|
|||
|
|
@ -522,17 +522,34 @@ struct iwl_rx_baid_cfg_cmd_alloc {
|
|||
} __packed; /* RX_BAID_ALLOCATION_ADD_CMD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_rx_baid_cfg_cmd_modify - BAID modification data
|
||||
* struct iwl_rx_baid_cfg_cmd_modify_v2 - BAID modification data
|
||||
* @old_sta_id_mask: old station ID mask
|
||||
* @new_sta_id_mask: new station ID mask
|
||||
* @tid: TID of the BAID
|
||||
*/
|
||||
struct iwl_rx_baid_cfg_cmd_modify {
|
||||
struct iwl_rx_baid_cfg_cmd_modify_v2 {
|
||||
__le32 old_sta_id_mask;
|
||||
__le32 new_sta_id_mask;
|
||||
__le32 tid;
|
||||
} __packed; /* RX_BAID_ALLOCATION_MODIFY_CMD_API_S_VER_2 */
|
||||
|
||||
/**
|
||||
* struct iwl_rx_baid_cfg_cmd_modify - BAID modification data
|
||||
* @old_sta_id_mask: old station ID mask
|
||||
* @new_sta_id_mask: new station ID mask
|
||||
* @tid: TID of the BAID
|
||||
* @reserved: reserved
|
||||
* @win_size: RX BA session window size to apply to the modified BAID,
|
||||
* 0 means keep the current one
|
||||
*/
|
||||
struct iwl_rx_baid_cfg_cmd_modify {
|
||||
__le32 old_sta_id_mask;
|
||||
__le32 new_sta_id_mask;
|
||||
u8 tid;
|
||||
u8 reserved;
|
||||
__le16 win_size;
|
||||
} __packed; /* RX_BAID_ALLOCATION_MODIFY_CMD_API_S_VER_3 */
|
||||
|
||||
/**
|
||||
* struct iwl_rx_baid_cfg_cmd_remove_v1 - BAID removal data
|
||||
* @baid: the BAID to remove
|
||||
|
|
@ -555,7 +572,8 @@ 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
|
||||
* @modify_v2: modify data (version 2)
|
||||
* @modify: modify data (version 3)
|
||||
* @remove_v1: remove data (version 1)
|
||||
* @remove: remove data
|
||||
*/
|
||||
|
|
@ -563,11 +581,12 @@ struct iwl_rx_baid_cfg_cmd {
|
|||
__le32 action;
|
||||
union {
|
||||
struct iwl_rx_baid_cfg_cmd_alloc alloc;
|
||||
struct iwl_rx_baid_cfg_cmd_modify_v2 modify_v2;
|
||||
struct iwl_rx_baid_cfg_cmd_modify modify;
|
||||
struct iwl_rx_baid_cfg_cmd_remove_v1 remove_v1;
|
||||
struct iwl_rx_baid_cfg_cmd_remove remove;
|
||||
}; /* RX_BAID_ALLOCATION_OPERATION_API_U_VER_2 */
|
||||
} __packed; /* RX_BAID_ALLOCATION_CONFIG_CMD_API_S_VER_2 */
|
||||
}; /* RX_BAID_ALLOCATION_OPERATION_API_U_VER_3 */
|
||||
} __packed; /* RX_BAID_ALLOCATION_CONFIG_CMD_API_S_VER_3 */
|
||||
|
||||
/**
|
||||
* struct iwl_rx_baid_cfg_resp - BAID allocation response
|
||||
|
|
@ -589,6 +608,16 @@ enum iwl_scd_queue_cfg_operation {
|
|||
IWL_SCD_QUEUE_MODIFY = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_scd_queue_modify_flags - scheduler queue modify flags
|
||||
* @IWL_SCD_QUEUE_MODIFY_FLAG_RD_PTR: update the read pointer
|
||||
* @IWL_SCD_QUEUE_MODIFY_FLAG_STA_MSK: update the station mask
|
||||
*/
|
||||
enum iwl_scd_queue_modify_flags {
|
||||
IWL_SCD_QUEUE_MODIFY_FLAG_RD_PTR = BIT(0),
|
||||
IWL_SCD_QUEUE_MODIFY_FLAG_STA_MSK = BIT(1),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_scd_queue_cfg_cmd - scheduler queue allocation command
|
||||
* @operation: the operation, see &enum iwl_scd_queue_cfg_operation
|
||||
|
|
@ -606,6 +635,8 @@ enum iwl_scd_queue_cfg_operation {
|
|||
* @u.modify.old_sta_mask: old station mask for modify
|
||||
* @u.modify.tid: TID of queue to modify
|
||||
* @u.modify.new_sta_mask: new station mask for modify
|
||||
* @u.modify.rd_ptr: new read pointer to set for the queue (version 4)
|
||||
* @u.modify.flags: &enum iwl_scd_queue_modify_flags (version 4)
|
||||
*/
|
||||
struct iwl_scd_queue_cfg_cmd {
|
||||
__le32 operation;
|
||||
|
|
@ -627,9 +658,11 @@ struct iwl_scd_queue_cfg_cmd {
|
|||
__le32 old_sta_mask;
|
||||
__le32 tid;
|
||||
__le32 new_sta_mask;
|
||||
} __packed modify; /* TX_QUEUE_CFG_CMD_MODIFY_API_S_VER_1 */
|
||||
} __packed u; /* TX_QUEUE_CFG_CMD_OPERATION_API_U_VER_1 */
|
||||
} __packed; /* TX_QUEUE_CFG_CMD_API_S_VER_3 */
|
||||
__le16 rd_ptr;
|
||||
__le16 flags;
|
||||
} __packed modify; /* TX_QUEUE_CFG_CMD_MODIFY_API_S_VER_1, _VER_2 */
|
||||
} __packed u; /* TX_QUEUE_CFG_CMD_OPERATION_API_U_VER_1, _VER_2 */
|
||||
} __packed; /* TX_QUEUE_CFG_CMD_API_S_VER_3, _VER_4 */
|
||||
|
||||
/**
|
||||
* enum iwl_sec_key_flags - security key command key flags
|
||||
|
|
@ -643,6 +676,7 @@ struct iwl_scd_queue_cfg_cmd {
|
|||
* @IWL_SEC_KEY_FLAG_MFP: MFP is in used for this key
|
||||
* @IWL_SEC_KEY_FLAG_MCAST_KEY: this is a multicast key
|
||||
* @IWL_SEC_KEY_FLAG_SPP_AMSDU: SPP A-MSDU should be used
|
||||
* @IWL_SEC_KEY_FLAG_ASSOC_ENC: use this key for (Re)Assoc Req/Resp encryption
|
||||
*/
|
||||
enum iwl_sec_key_flags {
|
||||
IWL_SEC_KEY_FLAG_CIPHER_MASK = 0x07,
|
||||
|
|
@ -655,6 +689,7 @@ enum iwl_sec_key_flags {
|
|||
IWL_SEC_KEY_FLAG_MFP = 0x20,
|
||||
IWL_SEC_KEY_FLAG_MCAST_KEY = 0x40,
|
||||
IWL_SEC_KEY_FLAG_SPP_AMSDU = 0x80,
|
||||
IWL_SEC_KEY_FLAG_ASSOC_ENC = 0x200,
|
||||
};
|
||||
|
||||
#define IWL_SEC_WEP_KEY_OFFSET 3
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
#ifndef __iwl_fw_api_mac_cfg_h__
|
||||
#define __iwl_fw_api_mac_cfg_h__
|
||||
|
||||
#include <linux/ieee80211-p2p.h>
|
||||
|
||||
#include "mac.h"
|
||||
#include "phy-ctxt.h"
|
||||
|
||||
|
|
@ -663,7 +665,13 @@ struct iwl_npca_params {
|
|||
* @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
|
||||
* @flags_mask: what of %flags have changed. Also &enum iwl_link_ctx_flags.
|
||||
* Removed in _VER_6, reused as @reserved4 / @max_bssid_indicator
|
||||
* in _VER_9.
|
||||
* @reserved4: reserved
|
||||
* @max_bssid_indicator: N where 2**N is the max number of BSSIDs the physical
|
||||
* AP can support (multi-BSS or EMCCA set). 0 disables the feature.
|
||||
* Since _VER_9.
|
||||
* Below fields are for multi-bssid:
|
||||
* @ref_bssid_addr: reference BSSID used by the AP
|
||||
* @reserved_for_ref_bssid_addr: reserved
|
||||
|
|
@ -704,17 +712,23 @@ struct iwl_link_config_cmd {
|
|||
/* MAC_QOS_PARAM_API_S_VER_1 */
|
||||
__le32 qos_flags;
|
||||
struct iwl_ac_qos ac[AC_NUM + 1];
|
||||
u8 htc_trig_based_pkt_ext;
|
||||
u8 rand_alloc_ecwmin;
|
||||
u8 rand_alloc_ecwmax;
|
||||
u8 htc_trig_based_pkt_ext; /* removed in _VER_9 */
|
||||
u8 rand_alloc_ecwmin; /* removed in _VER_9 */
|
||||
u8 rand_alloc_ecwmax; /* removed in _VER_9 */
|
||||
u8 ndp_fdbk_buff_th_exp;
|
||||
struct iwl_he_backoff_conf trig_based_txf[AC_NUM];
|
||||
__le32 bi;
|
||||
__le32 dtim_interval;
|
||||
__le16 puncture_mask; /* removed in _VER_3 */
|
||||
__le16 frame_time_rts_th;
|
||||
__le16 frame_time_rts_th; /* removed in _VER_9 */
|
||||
__le32 flags;
|
||||
__le32 flags_mask; /* removed in _VER_6 */
|
||||
union {
|
||||
__le32 flags_mask; /* removed in _VER_6 */
|
||||
struct {
|
||||
u8 reserved4[3];
|
||||
u8 max_bssid_indicator; /* since _VER_9 */
|
||||
};
|
||||
};
|
||||
/* The below fields are for multi-bssid */
|
||||
u8 ref_bssid_addr[6];
|
||||
__le16 reserved_for_ref_bssid_addr;
|
||||
|
|
@ -728,7 +742,9 @@ struct iwl_link_config_cmd {
|
|||
struct iwl_ac_qos prio_edca_params; /* since _VER_7 */
|
||||
__le32 reserved3[4];
|
||||
} __packed; /* LINK_CONTEXT_CONFIG_CMD_API_S_VER_1, _VER_2, _VER_3, _VER_4,
|
||||
* _VER_5, _VER_6, _VER_7, _VER_8 */
|
||||
* _VER_5, _VER_6, _VER_7, _VER_8,
|
||||
* _VER_9
|
||||
*/
|
||||
|
||||
/* Currently FW supports link ids in the range 0-3 and can have
|
||||
* at most two active links for each vif.
|
||||
|
|
@ -868,8 +884,8 @@ struct iwl_sta_cfg_cmd_v1 {
|
|||
* @dps_pad_time: DPS (Dynamic Power Save) padding delay resolution to ensure
|
||||
* proper timing alignment
|
||||
* @dps_trans_delay: DPS minimal time that takes the peer to return to low power
|
||||
* @mic_prep_pad_delay: MIC prep time padding
|
||||
* @mic_compute_pad_delay: MIC compute time padding
|
||||
* @mic_prep_pad_delay: MIC prep time padding (4 us resolution)
|
||||
* @mic_compute_pad_delay: MIC compute time padding (4 us resolution)
|
||||
* @reserved: Reserved for alignment
|
||||
*/
|
||||
struct iwl_sta_cfg_cmd_v2 {
|
||||
|
|
@ -924,8 +940,13 @@ struct iwl_sta_cfg_cmd_v2 {
|
|||
* @mimo_protection: indicates whether the sta uses mimo protection or not
|
||||
* @ack_enabled: indicates that the AP supports receiving ACK-
|
||||
* enabled AGG, i.e. both BACK and non-BACK frames in a single AGG
|
||||
* @trig_rnd_alloc: indicates that trigger based random allocation
|
||||
* is enabled according to UORA element existence
|
||||
* @cip_defer: delay the usage of the unicast control frame protection until
|
||||
* after association.
|
||||
* Only supported from command version 4, must be left cleared otherwise.
|
||||
* @epp_robust: indicates that EPP robust individually addressed management
|
||||
* frame support was negotiated during association.
|
||||
* Only supported from command version 4, must be left cleared otherwise.
|
||||
* @reserved1: Reserved for alignment
|
||||
* @tx_ampdu_spacing: minimum A-MPDU spacing:
|
||||
* 4 - 2us density, 5 - 4us density, 6 - 8us density, 7 - 16us density
|
||||
* @tx_ampdu_max_size: maximum A-MPDU length: 0 - 8K, 1 - 16K, 2 - 32K,
|
||||
|
|
@ -942,8 +963,8 @@ struct iwl_sta_cfg_cmd_v2 {
|
|||
* proper timing alignment
|
||||
* @dps_trans_delay: DPS minimal time that takes the peer to return to low power
|
||||
* @dps_enabled: flag indicating whether or not DPS is enabled
|
||||
* @mic_prep_pad_delay: MIC prep time padding
|
||||
* @mic_compute_pad_delay: MIC compute time padding
|
||||
* @mic_prep_pad_delay: MIC prep time padding (4 us resolution)
|
||||
* @mic_compute_pad_delay: MIC compute time padding (4 us resolution)
|
||||
* @nmi_sta_id: for an NDI peer STA, the NMI peer STA ID it relates to
|
||||
* @ndi_local_addr: for an NDI peer STA or NAN multicast data station,
|
||||
* the local NDI interface MAC address
|
||||
|
|
@ -963,7 +984,9 @@ struct iwl_sta_cfg_cmd {
|
|||
__le32 mimo;
|
||||
__le32 mimo_protection;
|
||||
__le32 ack_enabled;
|
||||
__le32 trig_rnd_alloc;
|
||||
u8 cip_defer;
|
||||
u8 epp_robust;
|
||||
__le16 reserved1;
|
||||
__le32 tx_ampdu_spacing;
|
||||
__le32 tx_ampdu_max_size;
|
||||
__le32 sp_length;
|
||||
|
|
@ -980,7 +1003,7 @@ struct iwl_sta_cfg_cmd {
|
|||
u8 nmi_sta_id;
|
||||
u8 ndi_local_addr[ETH_ALEN];
|
||||
u8 reserved[2];
|
||||
} __packed; /* STA_CMD_API_S_VER_3 */
|
||||
} __packed; /* STA_CMD_API_S_VER_3, STA_CMD_API_S_VER_4 */
|
||||
|
||||
/**
|
||||
* struct iwl_aux_sta_cmd - command for AUX STA configuration
|
||||
|
|
|
|||
|
|
@ -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-2025 Intel Corporation
|
||||
* Copyright (C) 2021-2026 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_fw_api_offload_h__
|
||||
#define __iwl_fw_api_offload_h__
|
||||
|
|
@ -20,7 +20,8 @@ enum iwl_prot_offload_subcmd_ids {
|
|||
/**
|
||||
* @WOWLAN_INFO_NOTIFICATION: Notification in
|
||||
* &struct iwl_wowlan_info_notif_v1, iwl_wowlan_info_notif_v3,
|
||||
* &struct iwl_wowlan_info_notif_v5 or &struct iwl_wowlan_info_notif
|
||||
* &struct iwl_wowlan_info_notif_v5, &struct iwl_wowlan_info_notif_v6
|
||||
* or &struct iwl_wowlan_info_notif
|
||||
*/
|
||||
WOWLAN_INFO_NOTIFICATION = 0xFD,
|
||||
|
||||
|
|
|
|||
|
|
@ -300,7 +300,8 @@ enum iwl_dev_tx_power_cmd_mode {
|
|||
IWL_TX_POWER_MODE_SET_ACK = 3,
|
||||
IWL_TX_POWER_MODE_SET_SAR_TIMER = 4,
|
||||
IWL_TX_POWER_MODE_SET_SAR_TIMER_DEFAULT_TABLE = 5,
|
||||
}; /* TX_POWER_REDUCED_FLAGS_TYPE_API_E_VER_5 */;
|
||||
IWL_TX_POWER_MODE_SET_STANDALONE_CHAINS = 8, /* cmd ver 12+ */
|
||||
}; /* TX_POWER_REDUCED_FLAGS_TYPE_API_E_VER_2 */;
|
||||
|
||||
#define IWL_NUM_CHAIN_TABLES 1
|
||||
#define IWL_NUM_CHAIN_TABLES_V2 2
|
||||
|
|
@ -464,31 +465,34 @@ struct iwl_dev_tx_power_cmd_v10 {
|
|||
__le32 flags;
|
||||
} __packed; /* TX_REDUCED_POWER_API_S_VER_10 */
|
||||
|
||||
struct iwl_dev_tx_power_cmd_v11 {
|
||||
struct iwl_dev_tx_power_cmd_v12 {
|
||||
__le16 per_chain[IWL_NUM_CHAIN_TABLES_V2][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V3];
|
||||
u8 per_chain_restriction_changed;
|
||||
u8 reserved;
|
||||
__le32 timer_period;
|
||||
__le32 flags;
|
||||
} __packed; /* TX_REDUCED_POWER_API_S_VER_11 */
|
||||
} __packed; /* TX_REDUCED_POWER_API_S_VER_11
|
||||
* TX_REDUCED_POWER_API_S_VER_12
|
||||
*/
|
||||
|
||||
/*
|
||||
* struct iwl_dev_tx_power_cmd - TX power reduction command (multiversion)
|
||||
* @common: common part of the command
|
||||
* @v9: version 9 part of the command
|
||||
* @v10: version 10 part of the command
|
||||
* @v11: version 11 part of the command
|
||||
* @v12: version 12 part of the command (also covers v11)
|
||||
*/
|
||||
struct iwl_dev_tx_power_cmd {
|
||||
struct iwl_dev_tx_power_common common;
|
||||
union {
|
||||
struct iwl_dev_tx_power_cmd_v9 v9;
|
||||
struct iwl_dev_tx_power_cmd_v10 v10;
|
||||
struct iwl_dev_tx_power_cmd_v11 v11;
|
||||
struct iwl_dev_tx_power_cmd_v12 v12;
|
||||
};
|
||||
} __packed; /* TX_REDUCED_POWER_API_S_VER_9
|
||||
* TX_REDUCED_POWER_API_S_VER_10
|
||||
* TX_REDUCED_POWER_API_S_VER_11
|
||||
* TX_REDUCED_POWER_API_S_VER_12
|
||||
*/
|
||||
|
||||
#define IWL_NUM_GEO_PROFILES 3
|
||||
|
|
|
|||
|
|
@ -583,7 +583,11 @@ struct iwl_rx_mpdu_desc_v3 {
|
|||
/**
|
||||
* @reserved_xsum: reserved high bits in the raw checksum
|
||||
*/
|
||||
__le16 reserved_xsum;
|
||||
u8 reserved_xsum;
|
||||
/**
|
||||
* @mac_context: MAC context mask, in this DW only from API version 10
|
||||
*/
|
||||
u8 mac_context;
|
||||
/* DW11 */
|
||||
/**
|
||||
* @rate_n_flags: RX rate/flags encoding
|
||||
|
|
@ -603,9 +607,10 @@ struct iwl_rx_mpdu_desc_v3 {
|
|||
*/
|
||||
u8 channel;
|
||||
/**
|
||||
* @mac_context: MAC context mask
|
||||
* @ru: RU/MRU/DRU used for the frame, in trigger-like format;
|
||||
* only from API version 10, this byte held @mac_context before
|
||||
*/
|
||||
u8 mac_context;
|
||||
u8 ru;
|
||||
/* DW13 */
|
||||
/**
|
||||
* @gp2_on_air_rise: GP2 timer value on air rise (INA)
|
||||
|
|
@ -647,7 +652,11 @@ struct iwl_rx_mpdu_desc_v3 {
|
|||
__le32 reserved[1];
|
||||
} __packed; /* RX_MPDU_RES_START_API_S_VER_3,
|
||||
* RX_MPDU_RES_START_API_S_VER_5,
|
||||
* RX_MPDU_RES_START_API_S_VER_6
|
||||
* RX_MPDU_RES_START_API_S_VER_6,
|
||||
* RX_MPDU_RES_START_API_S_VER_7,
|
||||
* RX_MPDU_RES_START_API_S_VER_8,
|
||||
* RX_MPDU_RES_START_API_S_VER_9,
|
||||
* RX_MPDU_RES_START_API_S_VER_10
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
@ -737,6 +746,8 @@ struct iwl_rx_mpdu_desc {
|
|||
* RX_MPDU_RES_START_API_S_VER_6
|
||||
* RX_MPDU_RES_START_API_S_VER_7
|
||||
* RX_MPDU_RES_START_API_S_VER_8
|
||||
* RX_MPDU_RES_START_API_S_VER_9
|
||||
* RX_MPDU_RES_START_API_S_VER_10
|
||||
*/
|
||||
|
||||
#define IWL_RX_DESC_SIZE_V1 offsetofend(struct iwl_rx_mpdu_desc, v1)
|
||||
|
|
@ -1347,7 +1358,7 @@ struct iwl_uhr_elr_sigs {
|
|||
#define OFDM_RX_VECTOR_UHR_ELR_PPDU_TYPE 0x00000003
|
||||
#define OFDM_RX_VECTOR_UHR_ELR_USIG_STA_ID 0x00001ffc
|
||||
#define OFDM_RX_VECTOR_UHR_ELR_VALIDATE 0x0000e000
|
||||
#define OFDM_RX_VECTOR_UHR_ELR_CRC_OK 0x00010000
|
||||
#define OFDM_RX_VECTOR_UHR_ELR_CRC_OK 0x40000000
|
||||
__le32 usig_a2_uhr_elr;
|
||||
#define OFDM_RX_VECTOR_UHR_ELR_VER_ID 0x00000007
|
||||
#define OFDM_RX_VECTOR_UHR_ELR_UPLINK_FLAG 0x00000008
|
||||
|
|
@ -1363,7 +1374,7 @@ struct iwl_uhr_elr_sigs {
|
|||
#define OFDM_RX_VECTOR_UHR_ELR_SIG_ID_INDX 0x00000e00
|
||||
#define OFDM_RX_VECTOR_UHR_ELR_STA_RU 0x000ff000
|
||||
#define OFDM_RX_VECTOR_UHR_ELR_STA_RU_PS160 0x00100000
|
||||
#define OFDM_RX_VECTOR_UHR_ELR_SIG2_CRC_OK 0x00200000
|
||||
#define OFDM_RX_VECTOR_UHR_ELR_SIG2_CRC_OK 0x40000000
|
||||
__le32 uhr_sig_elr2;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -987,6 +987,8 @@ struct iwl_scan_probe_params_v4 {
|
|||
#define SCAN_MAX_NUM_CHANS_V3 67
|
||||
#define SCAN_MAX_NUM_CHANS_V4 68
|
||||
|
||||
#define SCAN_MAX_NUM_NOTIF_RESULTS 112
|
||||
|
||||
/**
|
||||
* struct iwl_scan_channel_params_v4 - channel params
|
||||
* @flags: channel flags &enum iwl_scan_channel_flags
|
||||
|
|
@ -1232,7 +1234,8 @@ struct iwl_umac_scan_complete {
|
|||
} __packed; /* SCAN_COMPLETE_NTF_UMAC_API_S_VER_1 */
|
||||
|
||||
#define SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1 5
|
||||
#define SCAN_OFFLOAD_MATCHING_CHANNELS_LEN 7
|
||||
#define SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V2 7
|
||||
#define SCAN_OFFLOAD_MATCHING_CHANNELS_LEN 16
|
||||
|
||||
/**
|
||||
* struct iwl_scan_offload_profile_match_v1 - match information
|
||||
|
|
@ -1278,11 +1281,31 @@ struct iwl_scan_offload_profiles_query_v1 {
|
|||
struct iwl_scan_offload_profile_match_v1 matches[];
|
||||
} __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_2 */
|
||||
|
||||
/**
|
||||
* struct iwl_scan_offload_profile_match_v2 - match information
|
||||
* @bssid: matched bssid
|
||||
* @reserved: reserved
|
||||
* @channel: channel where the match occurred
|
||||
* @energy: energy
|
||||
* @matching_feature: feature matches
|
||||
* @matching_channels: bitmap of channels that matched, referencing
|
||||
* the channels passed in the scan offload request.
|
||||
*/
|
||||
struct iwl_scan_offload_profile_match_v2 {
|
||||
u8 bssid[ETH_ALEN];
|
||||
__le16 reserved;
|
||||
u8 channel;
|
||||
u8 energy;
|
||||
u8 matching_feature;
|
||||
u8 matching_channels[SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V2];
|
||||
} __packed; /* SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S_VER_2 */
|
||||
|
||||
/**
|
||||
* struct iwl_scan_offload_profile_match - match information
|
||||
* @bssid: matched bssid
|
||||
* @reserved: reserved
|
||||
* @channel: channel where the match occurred
|
||||
* @band: band where the match occurred
|
||||
* @energy: energy
|
||||
* @matching_feature: feature matches
|
||||
* @matching_channels: bitmap of channels that matched, referencing
|
||||
|
|
@ -1292,10 +1315,11 @@ struct iwl_scan_offload_profile_match {
|
|||
u8 bssid[ETH_ALEN];
|
||||
__le16 reserved;
|
||||
u8 channel;
|
||||
u8 band;
|
||||
u8 energy;
|
||||
u8 matching_feature;
|
||||
u8 matching_channels[SCAN_OFFLOAD_MATCHING_CHANNELS_LEN];
|
||||
} __packed; /* SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S_VER_2 */
|
||||
} __packed; /* SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S_VER_3 */
|
||||
|
||||
/**
|
||||
* struct iwl_scan_offload_match_info - match results information
|
||||
|
|
@ -1320,12 +1344,13 @@ struct iwl_scan_offload_match_info {
|
|||
u8 self_recovery;
|
||||
__le16 reserved;
|
||||
struct iwl_scan_offload_profile_match matches[IWL_SCAN_MAX_PROFILES_V2];
|
||||
} __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_3 and
|
||||
} __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_5 and
|
||||
* SCAN_OFFLOAD_MATCH_INFO_NOTIFICATION_S_VER_1
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct iwl_umac_scan_iter_complete_notif - notifies end of scanning iteration
|
||||
* struct iwl_umac_scan_iter_complete_notif_v2 - notifies end of scanning
|
||||
* iteration
|
||||
* @uid: scan id, &enum iwl_umac_scan_uid_offsets
|
||||
* @scanned_channels: number of channels scanned and number of valid elements in
|
||||
* results array
|
||||
|
|
@ -1336,7 +1361,7 @@ struct iwl_scan_offload_match_info {
|
|||
* in &struct iwl_scan_req_umac.
|
||||
* @results: array of scan results, length in @scanned_channels
|
||||
*/
|
||||
struct iwl_umac_scan_iter_complete_notif {
|
||||
struct iwl_umac_scan_iter_complete_notif_v2 {
|
||||
__le32 uid;
|
||||
u8 scanned_channels;
|
||||
u8 status;
|
||||
|
|
@ -1346,6 +1371,39 @@ 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_iter_complete_notif - notifies end of scanning
|
||||
* iteration
|
||||
* @uid: scan id, &enum iwl_umac_scan_uid_offsets
|
||||
* @scanned_channels: number of channels scanned and number of valid elements in
|
||||
* results array
|
||||
* @status: one of SCAN_COMP_STATUS_*
|
||||
* @bt_status: BT on/off status
|
||||
* @last_channel: last channel that was scanned
|
||||
* @start_tsf: TSF timer in usecs of the scan start time for the mac specified
|
||||
* in &struct iwl_scan_req_umac.
|
||||
* @results: array of scan results, only @scanned_channels of them are valid
|
||||
* @ebs_status: EBS completion status, &enum iwl_scan_ebs_status
|
||||
* @reserved: reserved for alignment
|
||||
* @ebs_channel_status: only valid when @ebs_status is %IWL_SCAN_EBS_SUCCESS.
|
||||
* Bitmap of the 5 GHz channels on which EBS found energy:
|
||||
* bit i in [0..27]: channel = 36 + 4 * i (channels 36 - 144)
|
||||
* bit i in [28..35]: channel = 37 + 4 * i (channels 149 - 177)
|
||||
* bit 36: channel 181 (reserved, not currently covered by EBS)
|
||||
*/
|
||||
struct iwl_umac_scan_iter_complete_notif {
|
||||
__le32 uid;
|
||||
u8 scanned_channels;
|
||||
u8 status;
|
||||
u8 bt_status;
|
||||
u8 last_channel;
|
||||
__le64 start_tsf;
|
||||
struct iwl_scan_results_notif results[SCAN_MAX_NUM_NOTIF_RESULTS];
|
||||
u8 ebs_status;
|
||||
u8 reserved[3];
|
||||
__le64 ebs_channel_status;
|
||||
} __packed; /* SCAN_ITER_COMPLETE_NTF_UMAC_API_S_VER_3 */
|
||||
|
||||
/**
|
||||
* struct iwl_umac_scan_channel_survey_notif - data for survey
|
||||
* @channel: the channel scanned
|
||||
|
|
|
|||
|
|
@ -616,7 +616,7 @@ struct iwl_stats_ntfy_coex {
|
|||
} __packed; /* STATISTICS_FW_NTFY_COEX_TELEMETRY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_stats_ntfy_per_phy - per PHY statistics
|
||||
* struct iwl_stats_ntfy_per_phy_v2 - per PHY statistics
|
||||
* @channel_load: channel load
|
||||
* @channel_load_by_us: device contribution to MCLM
|
||||
* @channel_load_not_by_us: other devices' contribution to MCLM
|
||||
|
|
@ -632,7 +632,7 @@ struct iwl_stats_ntfy_coex {
|
|||
* @last_tx_ch_width_indx: last txed frame channel width index
|
||||
* @coex: coex related data
|
||||
*/
|
||||
struct iwl_stats_ntfy_per_phy {
|
||||
struct iwl_stats_ntfy_per_phy_v2 {
|
||||
__le32 channel_load;
|
||||
__le32 channel_load_by_us;
|
||||
__le32 channel_load_not_by_us;
|
||||
|
|
@ -646,6 +646,43 @@ struct iwl_stats_ntfy_per_phy {
|
|||
struct iwl_stats_ntfy_coex coex;
|
||||
} __packed; /* STATISTICS_NTFY_PER_PHY_API_S_VER_2 */
|
||||
|
||||
/**
|
||||
* struct iwl_stats_ntfy_per_phy - per PHY statistics
|
||||
* @channel_load: channel load
|
||||
* @channel_load_by_us: device contribution to MCLM
|
||||
* @channel_load_not_by_us: other devices' contribution to MCLM
|
||||
* @clt: CLT HW timer (TIM_CH_LOAD2)
|
||||
* @act: active accumulator SW
|
||||
* @elp: elapsed time accumulator SW
|
||||
* @rx_detected_per_ch_width: number of deferred TX per channel width,
|
||||
* 0 - 20, 1/2/3 - 40/80/160
|
||||
* @success_per_ch_width: number of frames that got ACK/BACK/CTS
|
||||
* per channel BW. note, BACK counted as 1
|
||||
* @fail_per_ch_width: number of frames that didn't get ACK/BACK/CTS
|
||||
* per channel BW. note BACK counted as 1
|
||||
* @last_tx_ch_width_indx: last txed frame channel width index
|
||||
* @coex: coex related data
|
||||
* @channel_load_npca_by_us: device NPCA contribution to MCLM
|
||||
* @channel_load_npca_obss: the time FW identified for NPCA, not necessarily
|
||||
* entered to NPCA state, but can be used as an indication for NPCA
|
||||
* opportunities in the environment
|
||||
*/
|
||||
struct iwl_stats_ntfy_per_phy {
|
||||
__le32 channel_load;
|
||||
__le32 channel_load_by_us;
|
||||
__le32 channel_load_not_by_us;
|
||||
__le32 clt;
|
||||
__le32 act;
|
||||
__le32 elp;
|
||||
__le32 rx_detected_per_ch_width[IWL_STATS_MAX_BW_INDEX];
|
||||
__le32 success_per_ch_width[IWL_STATS_MAX_BW_INDEX];
|
||||
__le32 fail_per_ch_width[IWL_STATS_MAX_BW_INDEX];
|
||||
__le32 last_tx_ch_width_indx;
|
||||
struct iwl_stats_ntfy_coex coex;
|
||||
__le32 channel_load_npca_by_us;
|
||||
__le32 channel_load_npca_obss;
|
||||
} __packed; /* STATISTICS_NTFY_PER_PHY_API_S_VER_3 */
|
||||
|
||||
/* unknown channel load (due to not being active on channel) */
|
||||
#define IWL_STATS_UNKNOWN_CHANNEL_LOAD 0xffffffff
|
||||
|
||||
|
|
@ -675,12 +712,27 @@ struct iwl_system_statistics_notif_oper_v3 {
|
|||
struct iwl_stats_ntfy_per_sta per_sta[IWL_STATION_COUNT_MAX];
|
||||
} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_API_S_VER_3 */
|
||||
|
||||
/**
|
||||
* struct iwl_system_statistics_notif_oper_v4 - statistics notification
|
||||
*
|
||||
* @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_v2
|
||||
* @per_sta: per sta statistics, &struct iwl_stats_ntfy_per_sta
|
||||
*/
|
||||
struct iwl_system_statistics_notif_oper_v4 {
|
||||
__le32 time_stamp;
|
||||
struct iwl_stats_ntfy_per_link per_link[IWL_FW_MAX_LINKS];
|
||||
struct iwl_stats_ntfy_per_phy_v2 per_phy[IWL_STATS_MAX_PHY_OPERATIONAL];
|
||||
struct iwl_stats_ntfy_per_sta per_sta[IWL_STATION_COUNT_MAX];
|
||||
} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_API_S_VER_4 */
|
||||
|
||||
/**
|
||||
* struct iwl_system_statistics_notif_oper - statistics notification
|
||||
*
|
||||
* @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_v1
|
||||
* @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 {
|
||||
|
|
@ -688,7 +740,7 @@ struct iwl_system_statistics_notif_oper {
|
|||
struct iwl_stats_ntfy_per_link per_link[IWL_FW_MAX_LINKS];
|
||||
struct iwl_stats_ntfy_per_phy per_phy[IWL_STATS_MAX_PHY_OPERATIONAL];
|
||||
struct iwl_stats_ntfy_per_sta per_sta[IWL_STATION_COUNT_MAX];
|
||||
} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_API_S_VER_4 */
|
||||
} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_API_S_VER_5 */
|
||||
|
||||
/**
|
||||
* struct iwl_system_statistics_part1_notif_oper - part1 stats notification
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2025 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2026 Intel Corporation
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
#ifndef __iwl_fw_api_tx_h__
|
||||
|
|
@ -292,6 +292,9 @@ struct iwl_tx_cmd_v9 {
|
|||
* @dram_info: FW internal DRAM storage
|
||||
* @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is
|
||||
* cleared. Combination of RATE_MCS_*; format depends on version
|
||||
* @driver_timestamp: gp2 time, in microseconds, assigned before queueing the
|
||||
* MPDU. Firmware uses it to detect frames blocked for too long.
|
||||
* Zero means no timestamp. Used from TX_CMD_API_S_VER_12.
|
||||
* @reserved: reserved
|
||||
* @hdr: 802.11 header
|
||||
*/
|
||||
|
|
@ -301,10 +304,12 @@ struct iwl_tx_cmd {
|
|||
__le32 offload_assist;
|
||||
struct iwl_dram_sec_info dram_info;
|
||||
__le32 rate_n_flags;
|
||||
u8 reserved[8];
|
||||
__le32 driver_timestamp;
|
||||
u8 reserved[4];
|
||||
struct ieee80211_hdr hdr[];
|
||||
} __packed; /* TX_CMD_API_S_VER_10,
|
||||
* TX_CMD_API_S_VER_11
|
||||
* TX_CMD_API_S_VER_11,
|
||||
* TX_CMD_API_S_VER_12
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#include "runtime.h"
|
||||
#include "dbg.h"
|
||||
#include "debugfs.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "iwl-fh.h"
|
||||
|
|
@ -47,8 +47,8 @@ static void iwl_read_radio_regs(struct iwl_fw_runtime *fwrt,
|
|||
u32 rd_cmd = RADIO_RSP_RD_CMD;
|
||||
|
||||
rd_cmd |= i << RADIO_RSP_ADDR_POS;
|
||||
iwl_trans_write_prph(fwrt->trans, RSP_RADIO_CMD, rd_cmd);
|
||||
*pos = (u8)iwl_trans_read_prph(fwrt->trans, RSP_RADIO_RDDAT);
|
||||
iwl_trans_write_prph_no_grab(fwrt->trans, RSP_RADIO_CMD, rd_cmd);
|
||||
*pos = (u8)iwl_trans_read_prph_no_grab(fwrt->trans, RSP_RADIO_RDDAT);
|
||||
|
||||
pos++;
|
||||
}
|
||||
|
|
@ -81,35 +81,35 @@ static void iwl_fwrt_dump_rxf(struct iwl_fw_runtime *fwrt,
|
|||
|
||||
fifo_hdr->fifo_num = cpu_to_le32(fifo_num);
|
||||
fifo_hdr->available_bytes =
|
||||
cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
|
||||
RXF_RD_D_SPACE + offset));
|
||||
cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
RXF_RD_D_SPACE + offset));
|
||||
fifo_hdr->wr_ptr =
|
||||
cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
|
||||
RXF_RD_WR_PTR + offset));
|
||||
cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
RXF_RD_WR_PTR + offset));
|
||||
fifo_hdr->rd_ptr =
|
||||
cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
|
||||
RXF_RD_RD_PTR + offset));
|
||||
cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
RXF_RD_RD_PTR + offset));
|
||||
fifo_hdr->fence_ptr =
|
||||
cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
|
||||
RXF_RD_FENCE_PTR + offset));
|
||||
cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
RXF_RD_FENCE_PTR + offset));
|
||||
fifo_hdr->fence_mode =
|
||||
cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
|
||||
RXF_SET_FENCE_MODE + offset));
|
||||
cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
RXF_SET_FENCE_MODE + offset));
|
||||
|
||||
/* Lock fence */
|
||||
iwl_trans_write_prph(fwrt->trans, RXF_SET_FENCE_MODE + offset, 0x1);
|
||||
iwl_trans_write_prph_no_grab(fwrt->trans, RXF_SET_FENCE_MODE + offset, 0x1);
|
||||
/* Set fence pointer to the same place like WR pointer */
|
||||
iwl_trans_write_prph(fwrt->trans, RXF_LD_WR2FENCE + offset, 0x1);
|
||||
iwl_trans_write_prph_no_grab(fwrt->trans, RXF_LD_WR2FENCE + offset, 0x1);
|
||||
/* Set fence offset */
|
||||
iwl_trans_write_prph(fwrt->trans,
|
||||
RXF_LD_FENCE_OFFSET_ADDR + offset, 0x0);
|
||||
iwl_trans_write_prph_no_grab(fwrt->trans,
|
||||
RXF_LD_FENCE_OFFSET_ADDR + offset, 0x0);
|
||||
|
||||
/* Read FIFO */
|
||||
fifo_len /= sizeof(u32); /* Size in DWORDS */
|
||||
for (i = 0; i < fifo_len; i++)
|
||||
fifo_data[i] = iwl_trans_read_prph(fwrt->trans,
|
||||
RXF_FIFO_RD_FENCE_INC +
|
||||
offset);
|
||||
fifo_data[i] = iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
RXF_FIFO_RD_FENCE_INC +
|
||||
offset);
|
||||
*dump_data = iwl_fw_error_next_data(*dump_data);
|
||||
}
|
||||
|
||||
|
|
@ -136,33 +136,33 @@ static void iwl_fwrt_dump_txf(struct iwl_fw_runtime *fwrt,
|
|||
|
||||
fifo_hdr->fifo_num = cpu_to_le32(fifo_num);
|
||||
fifo_hdr->available_bytes =
|
||||
cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
|
||||
TXF_FIFO_ITEM_CNT + offset));
|
||||
cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
TXF_FIFO_ITEM_CNT + offset));
|
||||
fifo_hdr->wr_ptr =
|
||||
cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
|
||||
TXF_WR_PTR + offset));
|
||||
cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
TXF_WR_PTR + offset));
|
||||
fifo_hdr->rd_ptr =
|
||||
cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
|
||||
TXF_RD_PTR + offset));
|
||||
cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
TXF_RD_PTR + offset));
|
||||
fifo_hdr->fence_ptr =
|
||||
cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
|
||||
TXF_FENCE_PTR + offset));
|
||||
cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
TXF_FENCE_PTR + offset));
|
||||
fifo_hdr->fence_mode =
|
||||
cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
|
||||
TXF_LOCK_FENCE + offset));
|
||||
cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
TXF_LOCK_FENCE + offset));
|
||||
|
||||
/* Set the TXF_READ_MODIFY_ADDR to TXF_WR_PTR */
|
||||
iwl_trans_write_prph(fwrt->trans, TXF_READ_MODIFY_ADDR + offset,
|
||||
TXF_WR_PTR + offset);
|
||||
iwl_trans_write_prph_no_grab(fwrt->trans, TXF_READ_MODIFY_ADDR + offset,
|
||||
TXF_WR_PTR + offset);
|
||||
|
||||
/* Dummy-read to advance the read pointer to the head */
|
||||
iwl_trans_read_prph(fwrt->trans, TXF_READ_MODIFY_DATA + offset);
|
||||
iwl_trans_read_prph_no_grab(fwrt->trans, TXF_READ_MODIFY_DATA + offset);
|
||||
|
||||
/* Read FIFO */
|
||||
for (i = 0; i < fifo_len / sizeof(u32); i++)
|
||||
fifo_data[i] = iwl_trans_read_prph(fwrt->trans,
|
||||
TXF_READ_MODIFY_DATA +
|
||||
offset);
|
||||
fifo_data[i] = iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
TXF_READ_MODIFY_DATA +
|
||||
offset);
|
||||
|
||||
if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf)
|
||||
fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx,
|
||||
|
|
@ -217,7 +217,7 @@ static void iwl_fw_dump_txf(struct iwl_fw_runtime *fwrt,
|
|||
/* Pull TXF data from LMAC1 */
|
||||
for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries; i++) {
|
||||
/* Mark the number of TXF we're pulling now */
|
||||
iwl_trans_write_prph(fwrt->trans, TXF_LARC_NUM, i);
|
||||
iwl_trans_write_prph_no_grab(fwrt->trans, TXF_LARC_NUM, i);
|
||||
iwl_fwrt_dump_txf(fwrt, dump_data,
|
||||
cfg->lmac[0].txfifo_size[i], 0, i);
|
||||
}
|
||||
|
|
@ -227,9 +227,9 @@ static void iwl_fw_dump_txf(struct iwl_fw_runtime *fwrt,
|
|||
for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries;
|
||||
i++) {
|
||||
/* Mark the number of TXF we're pulling now */
|
||||
iwl_trans_write_prph(fwrt->trans,
|
||||
TXF_LARC_NUM +
|
||||
LMAC2_PRPH_OFFSET, i);
|
||||
iwl_trans_write_prph_no_grab(fwrt->trans,
|
||||
TXF_LARC_NUM +
|
||||
LMAC2_PRPH_OFFSET, i);
|
||||
iwl_fwrt_dump_txf(fwrt, dump_data,
|
||||
cfg->lmac[1].txfifo_size[i],
|
||||
LMAC2_PRPH_OFFSET,
|
||||
|
|
@ -262,40 +262,40 @@ static void iwl_fw_dump_txf(struct iwl_fw_runtime *fwrt,
|
|||
fifo_hdr->fifo_num = cpu_to_le32(i);
|
||||
|
||||
/* Mark the number of TXF we're pulling now */
|
||||
iwl_trans_write_prph(fwrt->trans, TXF_CPU2_NUM, i +
|
||||
fwrt->smem_cfg.num_txfifo_entries);
|
||||
iwl_trans_write_prph_no_grab(fwrt->trans, TXF_CPU2_NUM, i +
|
||||
fwrt->smem_cfg.num_txfifo_entries);
|
||||
|
||||
fifo_hdr->available_bytes =
|
||||
cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
|
||||
TXF_CPU2_FIFO_ITEM_CNT));
|
||||
cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
TXF_CPU2_FIFO_ITEM_CNT));
|
||||
fifo_hdr->wr_ptr =
|
||||
cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
|
||||
TXF_CPU2_WR_PTR));
|
||||
cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
TXF_CPU2_WR_PTR));
|
||||
fifo_hdr->rd_ptr =
|
||||
cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
|
||||
TXF_CPU2_RD_PTR));
|
||||
cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
TXF_CPU2_RD_PTR));
|
||||
fifo_hdr->fence_ptr =
|
||||
cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
|
||||
TXF_CPU2_FENCE_PTR));
|
||||
cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
TXF_CPU2_FENCE_PTR));
|
||||
fifo_hdr->fence_mode =
|
||||
cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
|
||||
TXF_CPU2_LOCK_FENCE));
|
||||
cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
TXF_CPU2_LOCK_FENCE));
|
||||
|
||||
/* Set TXF_CPU2_READ_MODIFY_ADDR to TXF_CPU2_WR_PTR */
|
||||
iwl_trans_write_prph(fwrt->trans,
|
||||
TXF_CPU2_READ_MODIFY_ADDR,
|
||||
TXF_CPU2_WR_PTR);
|
||||
iwl_trans_write_prph_no_grab(fwrt->trans,
|
||||
TXF_CPU2_READ_MODIFY_ADDR,
|
||||
TXF_CPU2_WR_PTR);
|
||||
|
||||
/* Dummy-read to advance the read pointer to head */
|
||||
iwl_trans_read_prph(fwrt->trans,
|
||||
TXF_CPU2_READ_MODIFY_DATA);
|
||||
iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
TXF_CPU2_READ_MODIFY_DATA);
|
||||
|
||||
/* Read FIFO */
|
||||
fifo_len /= sizeof(u32); /* Size in DWORDS */
|
||||
for (j = 0; j < fifo_len; j++)
|
||||
fifo_data[j] =
|
||||
iwl_trans_read_prph(fwrt->trans,
|
||||
TXF_CPU2_READ_MODIFY_DATA);
|
||||
iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
TXF_CPU2_READ_MODIFY_DATA);
|
||||
*dump_data = iwl_fw_error_next_data(*dump_data);
|
||||
}
|
||||
}
|
||||
|
|
@ -514,7 +514,7 @@ static void iwl_read_prph_block(struct iwl_trans *trans, u32 start,
|
|||
u32 i;
|
||||
|
||||
for (i = 0; i < len_bytes; i += 4)
|
||||
*data++ = cpu_to_le32(iwl_trans_read_prph(trans, start + i));
|
||||
*data++ = cpu_to_le32(iwl_trans_read_prph_no_grab(trans, start + i));
|
||||
}
|
||||
|
||||
static void iwl_dump_prph(struct iwl_fw_runtime *fwrt,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#include "runtime.h"
|
||||
#include "dbg.h"
|
||||
#include "debugfs.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "iwl-fh.h"
|
||||
|
|
@ -103,7 +103,7 @@ static int iwl_dump_ini_prph_mac_iter_common(struct iwl_fw_runtime *fwrt,
|
|||
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_trans_read_prph(fwrt->trans, addr + i));
|
||||
*val++ = cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, addr + i));
|
||||
|
||||
return sizeof(*range) + le32_to_cpu(range->range_data_size);
|
||||
}
|
||||
|
|
@ -159,7 +159,7 @@ static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt,
|
|||
indirect_rd_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);
|
||||
dphy_state = iwl_trans_read_umac_prph_no_grab(fwrt->trans, dphy_addr);
|
||||
|
||||
for (i = 0; i < le32_to_cpu(size); i += 4) {
|
||||
if (dphy_state == HBUS_TIMEOUT ||
|
||||
|
|
@ -169,16 +169,16 @@ static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt,
|
|||
continue;
|
||||
}
|
||||
|
||||
iwl_trans_write_prph(fwrt->trans, indirect_wr_addr,
|
||||
WMAL_INDRCT_CMD(addr + i));
|
||||
iwl_trans_write_prph_no_grab(fwrt->trans, indirect_wr_addr,
|
||||
WMAL_INDRCT_CMD(addr + i));
|
||||
|
||||
if (fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_JF1 &&
|
||||
fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_JF2 &&
|
||||
fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_HR1 &&
|
||||
fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_HR2) {
|
||||
udelay(2);
|
||||
prph_stts = iwl_trans_read_prph(fwrt->trans,
|
||||
WMAL_MRSPF_STTS);
|
||||
prph_stts = iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
WMAL_MRSPF_STTS);
|
||||
|
||||
/* Abort dump if status is 0xA5A5A5A2 or FIFO1 empty */
|
||||
if (prph_stts == WMAL_TIMEOUT_VAL ||
|
||||
|
|
@ -186,8 +186,8 @@ static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt,
|
|||
break;
|
||||
}
|
||||
|
||||
prph_val = iwl_trans_read_prph(fwrt->trans,
|
||||
indirect_rd_addr);
|
||||
prph_val = iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
indirect_rd_addr);
|
||||
*val++ = cpu_to_le32(prph_val);
|
||||
}
|
||||
|
||||
|
|
@ -344,6 +344,9 @@ iwl_dump_ini_mon_dram_iter(struct iwl_fw_runtime *fwrt,
|
|||
struct iwl_dram_data *frag;
|
||||
u32 alloc_id = le32_to_cpu(reg->dram_alloc_id);
|
||||
|
||||
if (WARN_ON_ONCE(alloc_id >= ARRAY_SIZE(fwrt->trans->dbg.fw_mon_ini)))
|
||||
return -EINVAL;
|
||||
|
||||
frag = &fwrt->trans->dbg.fw_mon_ini[alloc_id].frags[idx];
|
||||
|
||||
range->dram_base_addr = cpu_to_le64(frag->physical);
|
||||
|
|
@ -443,7 +446,7 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt,
|
|||
range->fifo_hdr.num_of_registers = cpu_to_le32(registers_num);
|
||||
range->range_data_size = cpu_to_le32(iter->fifo_size + registers_size);
|
||||
|
||||
iwl_trans_write_prph(fwrt->trans, TXF_LARC_NUM + offs, iter->fifo);
|
||||
iwl_trans_write_prph_no_grab(fwrt->trans, TXF_LARC_NUM + offs, iter->fifo);
|
||||
|
||||
/*
|
||||
* read txf registers. for each register, write to the dump the
|
||||
|
|
@ -453,8 +456,8 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt,
|
|||
addr = le32_to_cpu(reg->addrs[i]) + offs;
|
||||
|
||||
reg_dump->addr = cpu_to_le32(addr);
|
||||
reg_dump->data = cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
|
||||
addr));
|
||||
reg_dump->data = cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
addr));
|
||||
|
||||
reg_dump++;
|
||||
}
|
||||
|
|
@ -465,17 +468,17 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt,
|
|||
}
|
||||
|
||||
/* Set the TXF_READ_MODIFY_ADDR to TXF_WR_PTR */
|
||||
iwl_trans_write_prph(fwrt->trans, TXF_READ_MODIFY_ADDR + offs,
|
||||
TXF_WR_PTR + offs);
|
||||
iwl_trans_write_prph_no_grab(fwrt->trans, TXF_READ_MODIFY_ADDR + offs,
|
||||
TXF_WR_PTR + offs);
|
||||
|
||||
/* Dummy-read to advance the read pointer to the head */
|
||||
iwl_trans_read_prph(fwrt->trans, TXF_READ_MODIFY_DATA + offs);
|
||||
iwl_trans_read_prph_no_grab(fwrt->trans, TXF_READ_MODIFY_DATA + offs);
|
||||
|
||||
/* Read FIFO */
|
||||
addr = TXF_READ_MODIFY_DATA + offs;
|
||||
data = (void *)reg_dump;
|
||||
for (i = 0; i < iter->fifo_size; i += sizeof(*data))
|
||||
*data++ = cpu_to_le32(iwl_trans_read_prph(fwrt->trans, addr));
|
||||
*data++ = cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, addr));
|
||||
|
||||
if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf)
|
||||
fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx,
|
||||
|
|
@ -505,7 +508,7 @@ iwl_dump_ini_prph_snps_dphyip_iter(struct iwl_fw_runtime *fwrt,
|
|||
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);
|
||||
dphy_state = iwl_trans_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 ||
|
||||
|
|
@ -515,12 +518,12 @@ iwl_dump_ini_prph_snps_dphyip_iter(struct iwl_fw_runtime *fwrt,
|
|||
continue;
|
||||
}
|
||||
|
||||
iwl_trans_write_prph(fwrt->trans, indirect_rd_wr_addr,
|
||||
addr + i);
|
||||
iwl_trans_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_trans_read_prph(fwrt->trans,
|
||||
indirect_rd_wr_addr);
|
||||
prph_val = iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
indirect_rd_wr_addr);
|
||||
*val++ = cpu_to_le32((prph_val & DPHYIP_INDIRECT_RD_MSK) >>
|
||||
DPHYIP_INDIRECT_RD_SHIFT);
|
||||
}
|
||||
|
|
@ -583,13 +586,13 @@ static void iwl_ini_get_rxf_data(struct iwl_fw_runtime *fwrt,
|
|||
switch (fifo_idx) {
|
||||
case 0:
|
||||
data->size = fwrt->smem_cfg.rxfifo2_size;
|
||||
data->offset = iwl_umac_prph(fwrt->trans,
|
||||
RXF_DIFF_FROM_PREV);
|
||||
data->offset = iwl_trans_umac_prph(fwrt->trans,
|
||||
RXF_DIFF_FROM_PREV);
|
||||
break;
|
||||
case 1:
|
||||
data->size = fwrt->smem_cfg.rxfifo2_control_size;
|
||||
data->offset = iwl_umac_prph(fwrt->trans,
|
||||
RXF2C_DIFF_FROM_PREV);
|
||||
data->offset = iwl_trans_umac_prph(fwrt->trans,
|
||||
RXF2C_DIFF_FROM_PREV);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -625,8 +628,8 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt,
|
|||
addr = le32_to_cpu(reg->addrs[i]) + offs;
|
||||
|
||||
reg_dump->addr = cpu_to_le32(addr);
|
||||
reg_dump->data = cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
|
||||
addr));
|
||||
reg_dump->data = cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
addr));
|
||||
|
||||
reg_dump++;
|
||||
}
|
||||
|
|
@ -639,17 +642,17 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt,
|
|||
offs = rxf_data.offset;
|
||||
|
||||
/* Lock fence */
|
||||
iwl_trans_write_prph(fwrt->trans, RXF_SET_FENCE_MODE + offs, 0x1);
|
||||
iwl_trans_write_prph_no_grab(fwrt->trans, RXF_SET_FENCE_MODE + offs, 0x1);
|
||||
/* Set fence pointer to the same place like WR pointer */
|
||||
iwl_trans_write_prph(fwrt->trans, RXF_LD_WR2FENCE + offs, 0x1);
|
||||
iwl_trans_write_prph_no_grab(fwrt->trans, RXF_LD_WR2FENCE + offs, 0x1);
|
||||
/* Set fence offset */
|
||||
iwl_trans_write_prph(fwrt->trans, RXF_LD_FENCE_OFFSET_ADDR + offs, 0x0);
|
||||
iwl_trans_write_prph_no_grab(fwrt->trans, RXF_LD_FENCE_OFFSET_ADDR + offs, 0x0);
|
||||
|
||||
/* Read FIFO */
|
||||
addr = RXF_FIFO_RD_FENCE_INC + offs;
|
||||
data = (void *)reg_dump;
|
||||
for (i = 0; i < rxf_data.size; i += sizeof(*data))
|
||||
*data++ = cpu_to_le32(iwl_trans_read_prph(fwrt->trans, addr));
|
||||
*data++ = cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, addr));
|
||||
|
||||
out:
|
||||
return sizeof(*range) + le32_to_cpu(range->range_data_size);
|
||||
|
|
@ -709,10 +712,10 @@ iwl_dump_ini_dbgi_sram_iter(struct iwl_fw_runtime *fwrt,
|
|||
range->range_data_size = reg->dev_addr.size;
|
||||
for (i = 0; i < (le32_to_cpu(reg->dev_addr.size) / 4); i++) {
|
||||
prph_data =
|
||||
iwl_trans_read_prph(fwrt->trans,
|
||||
(i % 2) ?
|
||||
DBGI_SRAM_TARGET_ACCESS_RDATA_MSB :
|
||||
DBGI_SRAM_TARGET_ACCESS_RDATA_LSB);
|
||||
iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
(i % 2) ?
|
||||
DBGI_SRAM_TARGET_ACCESS_RDATA_MSB :
|
||||
DBGI_SRAM_TARGET_ACCESS_RDATA_LSB);
|
||||
if (iwl_trans_is_hw_error_value(prph_data))
|
||||
return -EBUSY;
|
||||
*val++ = cpu_to_le32(prph_data);
|
||||
|
|
@ -809,7 +812,7 @@ static __le32 iwl_get_mon_reg(struct iwl_fw_runtime *fwrt, u32 alloc_id,
|
|||
if (!reg_info || !reg_info->addr || !reg_info->mask)
|
||||
return 0;
|
||||
|
||||
val = iwl_trans_read_prph(fwrt->trans, reg_info->addr + offs);
|
||||
val = iwl_trans_read_prph_no_grab(fwrt->trans, reg_info->addr + offs);
|
||||
|
||||
return cpu_to_le32(mask_apply_and_normalize(val, reg_info->mask));
|
||||
}
|
||||
|
|
@ -957,6 +960,9 @@ iwl_dump_ini_mon_dram_ranges(struct iwl_fw_runtime *fwrt,
|
|||
u32 ranges = 0, alloc_id = le32_to_cpu(reg->dram_alloc_id);
|
||||
int i;
|
||||
|
||||
if (WARN_ON_ONCE(alloc_id >= ARRAY_SIZE(fwrt->trans->dbg.fw_mon_ini)))
|
||||
return 0;
|
||||
|
||||
fw_mon = &fwrt->trans->dbg.fw_mon_ini[alloc_id];
|
||||
|
||||
for (i = 0; i < fw_mon->num_frags; i++) {
|
||||
|
|
@ -1016,8 +1022,16 @@ static u32 iwl_dump_ini_mem_get_size(struct iwl_fw_runtime *fwrt,
|
|||
if (!size || !ranges)
|
||||
return 0;
|
||||
|
||||
return sizeof(struct iwl_fw_ini_error_dump) + ranges *
|
||||
(size + sizeof(struct iwl_fw_ini_error_dump_range));
|
||||
if (check_add_overflow(size,
|
||||
(u32)sizeof(struct iwl_fw_ini_error_dump_range),
|
||||
&size) ||
|
||||
check_mul_overflow(ranges, size, &size) ||
|
||||
check_add_overflow(size,
|
||||
(u32)sizeof(struct iwl_fw_ini_error_dump),
|
||||
&size))
|
||||
return 0;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32
|
||||
|
|
@ -1028,15 +1042,24 @@ iwl_dump_ini_mem_block_get_size(struct iwl_fw_runtime *fwrt,
|
|||
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);
|
||||
u32 range_hdrs;
|
||||
int range;
|
||||
|
||||
if (!ranges)
|
||||
return 0;
|
||||
|
||||
for (range = 0; range < ranges; range++)
|
||||
size += le32_to_cpu(pairs[range].size);
|
||||
if (check_add_overflow(size, le32_to_cpu(pairs[range].size),
|
||||
&size))
|
||||
return 0;
|
||||
|
||||
return size + ranges * sizeof(struct iwl_fw_ini_error_dump_range);
|
||||
if (check_mul_overflow(ranges,
|
||||
(u32)sizeof(struct iwl_fw_ini_error_dump_range),
|
||||
&range_hdrs) ||
|
||||
check_add_overflow(size, range_hdrs, &size))
|
||||
return 0;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32
|
||||
|
|
@ -1068,6 +1091,9 @@ iwl_dump_ini_mon_dram_get_size(struct iwl_fw_runtime *fwrt,
|
|||
u32 size = 0, alloc_id = le32_to_cpu(reg->dram_alloc_id);
|
||||
int i;
|
||||
|
||||
if (WARN_ON_ONCE(alloc_id >= ARRAY_SIZE(fwrt->trans->dbg.fw_mon_ini)))
|
||||
return 0;
|
||||
|
||||
fw_mon = &fwrt->trans->dbg.fw_mon_ini[alloc_id];
|
||||
|
||||
for (i = 0; i < fw_mon->num_frags; i++) {
|
||||
|
|
@ -1112,8 +1138,16 @@ static u32 iwl_dump_ini_mon_dbgi_get_size(struct iwl_fw_runtime *fwrt,
|
|||
if (!size || !ranges)
|
||||
return 0;
|
||||
|
||||
return sizeof(struct iwl_fw_ini_monitor_dump) + ranges *
|
||||
(size + sizeof(struct iwl_fw_ini_error_dump_range));
|
||||
if (check_add_overflow(size,
|
||||
(u32)sizeof(struct iwl_fw_ini_error_dump_range),
|
||||
&size) ||
|
||||
check_mul_overflow(ranges, size, &size) ||
|
||||
check_add_overflow(size,
|
||||
(u32)sizeof(struct iwl_fw_ini_monitor_dump),
|
||||
&size))
|
||||
return 0;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 iwl_dump_ini_txf_get_size(struct iwl_fw_runtime *fwrt,
|
||||
|
|
@ -1786,14 +1820,14 @@ static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt,
|
|||
cpu_to_le32(IWL_FW_INI_APPLY_POLICY_SPLIT_DUMP_RESET)) {
|
||||
size += iwl_dump_ini_dump_entries(fwrt, list,
|
||||
IWL_INI_DUMP_EARLY_REGIONS);
|
||||
iwl_trans_pcie_fw_reset_handshake(fwrt->trans);
|
||||
iwl_trans_fw_reset_handshake(fwrt->trans);
|
||||
size += iwl_dump_ini_dump_entries(fwrt, list,
|
||||
IWL_INI_DUMP_LATE_REGIONS);
|
||||
} else {
|
||||
if (fw_has_capa(&fwrt->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_RESET_DURING_ASSERT) &&
|
||||
iwl_dump_due_to_error(tp_id))
|
||||
iwl_trans_pcie_fw_reset_handshake(fwrt->trans);
|
||||
iwl_trans_fw_reset_handshake(fwrt->trans);
|
||||
size += iwl_dump_ini_dump_entries(fwrt, list,
|
||||
IWL_INI_DUMP_ALL_REGIONS);
|
||||
}
|
||||
|
|
@ -2021,7 +2055,7 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
|
|||
if (trigger->flags & IWL_FW_DBG_FORCE_RESTART) {
|
||||
IWL_WARN(fwrt, "Force restart: trigger %d fired.\n",
|
||||
trig);
|
||||
iwl_force_nmi(fwrt->trans);
|
||||
iwl_trans_force_nmi(fwrt->trans);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2199,7 +2233,8 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx)
|
|||
}
|
||||
|
||||
if (fwrt->trans->dbg.last_tp_resetfw == IWL_FW_INI_RESET_FW_MODE_STOP_FW_ONLY)
|
||||
iwl_force_nmi(fwrt->trans);
|
||||
iwl_trans_force_nmi(fwrt->trans);
|
||||
|
||||
out:
|
||||
if (iwl_trans_dbg_ini_valid(fwrt->trans)) {
|
||||
iwl_fw_error_dump_data_free(dump_data);
|
||||
|
|
@ -2269,8 +2304,13 @@ void iwl_fw_error_dump_wk(struct work_struct *work)
|
|||
{
|
||||
struct iwl_fwrt_wk_data *wks =
|
||||
container_of(work, typeof(*wks), wk.work);
|
||||
struct iwl_fw_runtime *fwrt =
|
||||
container_of(wks, typeof(*fwrt), dump.wks[wks->idx]);
|
||||
struct iwl_fw_runtime *fwrt;
|
||||
|
||||
if (WARN_ONCE(wks->idx >= IWL_FW_RUNTIME_DUMP_WK_NUM,
|
||||
"invalid worker index %d\n", wks->idx))
|
||||
return;
|
||||
|
||||
fwrt = container_of(wks, typeof(*fwrt), dump.wks[wks->idx]);
|
||||
|
||||
/* assumes the op mode mutex is locked in dump_start since
|
||||
* iwl_fw_dbg_collect_sync can't run in parallel
|
||||
|
|
@ -2346,21 +2386,21 @@ static void iwl_fw_dbg_stop_recording(struct iwl_trans *trans,
|
|||
struct iwl_fw_dbg_params *params)
|
||||
{
|
||||
if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_7000) {
|
||||
iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100);
|
||||
iwl_trans_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100);
|
||||
return;
|
||||
}
|
||||
|
||||
if (params) {
|
||||
params->in_sample = iwl_read_umac_prph(trans, DBGC_IN_SAMPLE);
|
||||
params->out_ctrl = iwl_read_umac_prph(trans, DBGC_OUT_CTRL);
|
||||
params->in_sample = iwl_trans_read_umac_prph(trans, DBGC_IN_SAMPLE);
|
||||
params->out_ctrl = iwl_trans_read_umac_prph(trans, DBGC_OUT_CTRL);
|
||||
}
|
||||
|
||||
iwl_write_umac_prph(trans, DBGC_IN_SAMPLE, 0);
|
||||
iwl_trans_write_umac_prph(trans, DBGC_IN_SAMPLE, 0);
|
||||
/* wait for the DBGC to finish writing the internal buffer to DRAM to
|
||||
* avoid halting the HW while writing
|
||||
*/
|
||||
usleep_range(700, 1000);
|
||||
iwl_write_umac_prph(trans, DBGC_OUT_CTRL, 0);
|
||||
iwl_trans_write_umac_prph(trans, DBGC_OUT_CTRL, 0);
|
||||
}
|
||||
|
||||
static int iwl_fw_dbg_restart_recording(struct iwl_trans *trans,
|
||||
|
|
@ -2370,12 +2410,12 @@ static int iwl_fw_dbg_restart_recording(struct iwl_trans *trans,
|
|||
return -EIO;
|
||||
|
||||
if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_7000) {
|
||||
iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100);
|
||||
iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1);
|
||||
iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1);
|
||||
iwl_trans_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100);
|
||||
iwl_trans_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1);
|
||||
iwl_trans_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1);
|
||||
} else {
|
||||
iwl_write_umac_prph(trans, DBGC_IN_SAMPLE, params->in_sample);
|
||||
iwl_write_umac_prph(trans, DBGC_OUT_CTRL, params->out_ctrl);
|
||||
iwl_trans_write_umac_prph(trans, DBGC_IN_SAMPLE, params->in_sample);
|
||||
iwl_trans_write_umac_prph(trans, DBGC_OUT_CTRL, params->out_ctrl);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#include <net/cfg80211.h>
|
||||
#include "runtime.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "file.h"
|
||||
#include "error-dump.h"
|
||||
#include "api/commands.h"
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#include "runtime.h"
|
||||
#include "dbg.h"
|
||||
#include "debugfs.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "pnvm.h"
|
||||
|
|
@ -309,7 +309,7 @@ static void iwl_fwrt_dump_iml_error_log(struct iwl_fw_runtime *fwrt)
|
|||
return;
|
||||
}
|
||||
|
||||
error = iwl_read_umac_prph(trans, error);
|
||||
error = iwl_trans_read_umac_prph(trans, error);
|
||||
|
||||
IWL_ERR(trans, "IML/ROM dump:\n");
|
||||
|
||||
|
|
@ -318,11 +318,11 @@ static void iwl_fwrt_dump_iml_error_log(struct iwl_fw_runtime *fwrt)
|
|||
|
||||
IWL_ERR(fwrt, "0x%08X | IML/ROM error/state\n", error);
|
||||
IWL_ERR(fwrt, "0x%08X | IML/ROM data1\n",
|
||||
iwl_read_umac_prph(trans, data1));
|
||||
iwl_trans_read_umac_prph(trans, data1));
|
||||
|
||||
if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_22000)
|
||||
IWL_ERR(fwrt, "0x%08X | IML/ROM WFPM_AUTH_KEY_0\n",
|
||||
iwl_read_umac_prph(trans, SB_MODIFY_CFG_FLAG));
|
||||
iwl_trans_read_umac_prph(trans, SB_MODIFY_CFG_FLAG));
|
||||
}
|
||||
|
||||
#define FSEQ_REG(x) { .addr = (x), .str = #x, }
|
||||
|
|
@ -360,7 +360,7 @@ static void iwl_fwrt_dump_fseq_regs(struct iwl_fw_runtime *fwrt)
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(fseq_regs); i++)
|
||||
IWL_ERR(fwrt, "0x%08X | %s\n",
|
||||
iwl_read_prph_no_grab(trans, fseq_regs[i].addr),
|
||||
iwl_trans_read_prph_no_grab(trans, fseq_regs[i].addr),
|
||||
fseq_regs[i].str);
|
||||
|
||||
iwl_trans_release_nic_access(trans);
|
||||
|
|
@ -398,13 +398,13 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt)
|
|||
count++, pc_data++)
|
||||
IWL_ERR(fwrt, "%s: 0x%x\n",
|
||||
pc_data->pc_name,
|
||||
iwl_read_prph_no_grab(fwrt->trans,
|
||||
pc_data->pc_address));
|
||||
iwl_trans_read_prph_no_grab(fwrt->trans,
|
||||
pc_data->pc_address));
|
||||
iwl_trans_release_nic_access(fwrt->trans);
|
||||
}
|
||||
|
||||
if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
|
||||
u32 scratch = iwl_read32(fwrt->trans, CSR_FUNC_SCRATCH);
|
||||
u32 scratch = iwl_trans_read32(fwrt->trans, CSR_FUNC_SCRATCH);
|
||||
|
||||
IWL_ERR(fwrt, "Function Scratch status:\n");
|
||||
IWL_ERR(fwrt, "0x%08X | Func Scratch\n", scratch);
|
||||
|
|
|
|||
|
|
@ -452,6 +452,7 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
|
|||
* table data. For LARI_CONFIG_CHANGE command version 13 and above, this
|
||||
* capability is obsolete since raw DSM values are accepted by default.
|
||||
* @IWL_UCODE_TLV_CAPA_NAN_SYNC_SUPPORT: Supports NAN synchronization
|
||||
* @IWL_UCODE_TLV_CAPA_ASSOC_ENC_SUPPORT: firmware supports association frame encryption
|
||||
*
|
||||
* @NUM_IWL_UCODE_TLV_CAPA: number of bits used
|
||||
*/
|
||||
|
|
@ -556,6 +557,7 @@ enum iwl_ucode_tlv_capa {
|
|||
IWL_UCODE_TLV_CAPA_RESET_DURING_ASSERT = (__force iwl_ucode_tlv_capa_t)(4 * 32 + 0),
|
||||
IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE = (__force iwl_ucode_tlv_capa_t)(4 * 32 + 1),
|
||||
IWL_UCODE_TLV_CAPA_NAN_SYNC_SUPPORT = (__force iwl_ucode_tlv_capa_t)(4 * 32 + 2),
|
||||
IWL_UCODE_TLV_CAPA_ASSOC_ENC_SUPPORT = (__force iwl_ucode_tlv_capa_t)(4 * 32 + 4),
|
||||
NUM_IWL_UCODE_TLV_CAPA
|
||||
/*
|
||||
* This construction make both sparse (which cannot increment the previous
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2019-2021, 2024-2025 Intel Corporation
|
||||
* Copyright (C) 2019-2021, 2024-2026 Intel Corporation
|
||||
*/
|
||||
#include "iwl-drv.h"
|
||||
#include "runtime.h"
|
||||
|
|
@ -23,6 +23,8 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
|
|||
int i;
|
||||
|
||||
memset(fwrt, 0, sizeof(*fwrt));
|
||||
fwrt->wrds_table_revision = IWL_BIOS_REVISION_UNSET;
|
||||
fwrt->ewrd_table_revision = IWL_BIOS_REVISION_UNSET;
|
||||
fwrt->trans = trans;
|
||||
fwrt->fw = fw;
|
||||
fwrt->dev = trans->dev;
|
||||
|
|
@ -31,6 +33,8 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
|
|||
fwrt->sanitize_ops = sanitize_ops;
|
||||
fwrt->sanitize_ctx = sanitize_ctx;
|
||||
fwrt->ops_ctx = ops_ctx;
|
||||
/* default until the connectivity GUID lock status is resolved */
|
||||
fwrt->uefi_tables_lock_status = UEFI_CNV_GUID_UNKNOWN;
|
||||
for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++) {
|
||||
fwrt->dump.wks[i].idx = i;
|
||||
INIT_DELAYED_WORK(&fwrt->dump.wks[i].wk, iwl_fw_error_dump_wk);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#include "iwl-drv.h"
|
||||
#include "pnvm.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "fw/api/commands.h"
|
||||
#include "fw/api/nvm-reg.h"
|
||||
#include "fw/api/alive.h"
|
||||
|
|
@ -485,8 +485,8 @@ int iwl_pnvm_load(struct iwl_trans *trans,
|
|||
iwl_pnvm_complete_fn, trans);
|
||||
|
||||
/* kick the doorbell */
|
||||
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
|
||||
UREG_DOORBELL_TO_ISR6_PNVM);
|
||||
iwl_trans_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
|
||||
UREG_DOORBELL_TO_ISR6_PNVM);
|
||||
|
||||
return iwl_wait_notification(notif_wait, &pnvm_wait,
|
||||
MVM_UCODE_PNVM_TIMEOUT);
|
||||
|
|
|
|||
|
|
@ -11,9 +11,7 @@
|
|||
|
||||
#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__); \
|
||||
int ret = iwl_uefi_get_ ## __name(__VA_ARGS__); \
|
||||
if (ret < 0) \
|
||||
ret = iwl_acpi_get_ ## __name(__VA_ARGS__); \
|
||||
return ret; \
|
||||
|
|
@ -32,6 +30,8 @@ IWL_EXPORT_SYMBOL(iwl_bios_get_ ## __name)
|
|||
|
||||
IWL_BIOS_TABLE_LOADER(wrds_table);
|
||||
IWL_BIOS_TABLE_LOADER(ewrd_table);
|
||||
IWL_BIOS_TABLE_LOADER(wsss_table);
|
||||
IWL_BIOS_TABLE_LOADER(ewss_table);
|
||||
IWL_BIOS_TABLE_LOADER(wgds_table);
|
||||
IWL_BIOS_TABLE_LOADER(ppag_table);
|
||||
IWL_BIOS_TABLE_LOADER(phy_filters);
|
||||
|
|
@ -49,11 +49,16 @@ static const struct dmi_system_id dmi_ppag_approved_list[] = {
|
|||
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
||||
},
|
||||
},
|
||||
{ .ident = "SAMSUNG",
|
||||
{ .ident = "SAMSUNG_ELECTRONICS",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"),
|
||||
},
|
||||
},
|
||||
{ .ident = "SAMSUNG",
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Samsung"),
|
||||
},
|
||||
},
|
||||
{ .ident = "MSFT",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
|
||||
|
|
@ -126,10 +131,15 @@ static const struct dmi_system_id dmi_tas_approved_list[] = {
|
|||
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
||||
},
|
||||
},
|
||||
{ .ident = "SAMSUNG",
|
||||
{ .ident = "SAMSUNG_ELECTRONICS",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"),
|
||||
},
|
||||
},
|
||||
{ .ident = "SAMSUNG",
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Samsung"),
|
||||
},
|
||||
},
|
||||
{ .ident = "LENOVO",
|
||||
.matches = {
|
||||
|
|
@ -167,6 +177,12 @@ static const struct dmi_system_id dmi_tas_approved_list[] = {
|
|||
DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
|
||||
},
|
||||
},
|
||||
{ .ident = "GOOGLE-ASUS",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "ASUS"),
|
||||
},
|
||||
},
|
||||
{ .ident = "MSI",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."),
|
||||
|
|
@ -183,21 +199,22 @@ static const struct dmi_system_id dmi_tas_approved_list[] = {
|
|||
|
||||
bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
u32 ucode_ver = fwrt->fw->ucode_ver;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* TLV API flag to rely on, so rely on the ucode version. 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 &&
|
||||
return ucode_ver >= 38 ||
|
||||
(ucode_ver == 17 &&
|
||||
fwrt->trans->info.hw_rev != CSR_HW_REV_TYPE_3160) ||
|
||||
(IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 29 &&
|
||||
(ucode_ver == 29 &&
|
||||
((fwrt->trans->info.hw_rev & CSR_HW_REV_TYPE_MSK) ==
|
||||
CSR_HW_REV_TYPE_7265D));
|
||||
}
|
||||
|
|
@ -241,17 +258,22 @@ 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 prof_a, int prof_b,
|
||||
const struct iwl_sar_profile *profiles,
|
||||
bool is_standalone)
|
||||
{
|
||||
int profs[BIOS_SAR_NUM_CHAINS] = { prof_a, prof_b };
|
||||
int i, j;
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(fwrt->sar_standalone_profiles[0].chains[0].subbands) !=
|
||||
ARRAY_SIZE(fwrt->sar_profiles[0].chains[0].subbands));
|
||||
|
||||
if (WARN_ON_ONCE(n_subbands >
|
||||
ARRAY_SIZE(fwrt->sar_profiles[0].chains[0].subbands)))
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < BIOS_SAR_NUM_CHAINS; i++) {
|
||||
struct iwl_sar_profile *prof;
|
||||
const struct iwl_sar_profile *prof;
|
||||
|
||||
/* don't allow SAR to be disabled (profile 0 means disable) */
|
||||
if (profs[i] == 0)
|
||||
|
|
@ -262,11 +284,13 @@ static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt,
|
|||
return -EINVAL;
|
||||
|
||||
/* profiles go from 1 to 4, so decrement to access the array */
|
||||
prof = &fwrt->sar_profiles[profs[i] - 1];
|
||||
prof = &profiles[profs[i] - 1];
|
||||
|
||||
/* if the profile is disabled, do nothing */
|
||||
if (!prof->enabled) {
|
||||
IWL_DEBUG_RADIO(fwrt, "SAR profile %d is disabled.\n",
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"SAR %sprofile %d is disabled.\n",
|
||||
is_standalone ? "standalone " : "",
|
||||
profs[i]);
|
||||
/*
|
||||
* if one of the profiles is disabled, we
|
||||
|
|
@ -276,8 +300,8 @@ static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt,
|
|||
return 1;
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(fwrt,
|
||||
"SAR EWRD: chain %d profile index %d\n",
|
||||
IWL_DEBUG_INFO(fwrt, "SAR %s: chain %d profile index %d\n",
|
||||
is_standalone ? "standalone" : "EWRD",
|
||||
i, profs[i]);
|
||||
IWL_DEBUG_RADIO(fwrt, " Chain[%d]:\n", i);
|
||||
for (j = 0; j < n_subbands; j++) {
|
||||
|
|
@ -293,14 +317,17 @@ static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt,
|
|||
|
||||
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 prof_a, int prof_b,
|
||||
const struct iwl_sar_profile *profiles,
|
||||
bool is_standalone)
|
||||
{
|
||||
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);
|
||||
n_subbands, prof_a, prof_b, profiles,
|
||||
is_standalone);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
|
@ -447,3 +474,27 @@ bool iwl_rfi_is_enabled_in_bios(struct iwl_fw_runtime *fwrt)
|
|||
return false;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_rfi_is_enabled_in_bios);
|
||||
|
||||
/**
|
||||
* iwl_bios_get_guid_lock_status - resolve connectivity variables lock status
|
||||
* @fwrt: the firmware runtime context
|
||||
*
|
||||
* Determine the root-of-trust for the connectivity UEFI variables. The UEFI
|
||||
* GUID Lock Indicator (GLUI) is preferred: if it attests the tables as locked
|
||||
* or in test mode, that result is used. Otherwise (GLUI is missing, invalid or
|
||||
* reports unlocked) the ACPI GUID Lock Indicator is consulted and can override
|
||||
* the GLUI result.
|
||||
*
|
||||
* This only caches the result in &fwrt->uefi_tables_lock_status
|
||||
* (see &enum iwl_uefi_cnv_guid_status).
|
||||
*/
|
||||
void iwl_bios_get_guid_lock_status(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
iwl_uefi_get_guid_lock_status(fwrt);
|
||||
if (fwrt->uefi_tables_lock_status == UEFI_CNV_GUID_LOCKED ||
|
||||
fwrt->uefi_tables_lock_status == UEFI_CNV_GUID_TEST_MODE)
|
||||
return;
|
||||
|
||||
iwl_acpi_get_guid_lock_status(fwrt);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_bios_get_guid_lock_status);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#define IWL_SAR_ENABLE_MSK BIT(0)
|
||||
#define IWL_REDUCE_POWER_FLAGS_POS 1
|
||||
#define IWL_BIOS_REVISION_UNSET 0xFF
|
||||
|
||||
/* PPAG gain value bounds in 1/8 dBm */
|
||||
#define IWL_PPAG_MIN_LB -16
|
||||
|
|
@ -47,6 +48,22 @@
|
|||
#define IWL_WTAS_CANADA_UHB_MSK BIT(15)
|
||||
#define IWL_WTAS_USA_UHB_MSK BIT(16)
|
||||
|
||||
/**
|
||||
* enum iwl_uefi_cnv_guid_status - lock status of the connectivity
|
||||
* UEFI tables
|
||||
* @UEFI_CNV_GUID_UNLOCKED: the tables are unlocked
|
||||
* @UEFI_CNV_GUID_LOCKED: the tables are locked
|
||||
* @UEFI_CNV_GUID_TEST_MODE: the tables are locked in test mode
|
||||
* @UEFI_CNV_GUID_UNKNOWN: the lock status could not be determined.
|
||||
* This value is a driver internal, not a possible BIOS reported one
|
||||
*/
|
||||
enum iwl_uefi_cnv_guid_status {
|
||||
UEFI_CNV_GUID_UNLOCKED = 0,
|
||||
UEFI_CNV_GUID_LOCKED = 1,
|
||||
UEFI_CNV_GUID_TEST_MODE = 2,
|
||||
UEFI_CNV_GUID_UNKNOWN = 3,
|
||||
};
|
||||
|
||||
struct iwl_tas_selection_data {
|
||||
u8 override_tas_iec:1,
|
||||
enable_tas_iec:1,
|
||||
|
|
@ -193,7 +210,9 @@ int iwl_sar_geo_fill_table(struct iwl_fw_runtime *fwrt,
|
|||
|
||||
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 prof_a, int prof_b,
|
||||
const struct iwl_sar_profile *profiles,
|
||||
bool is_standalone);
|
||||
|
||||
bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
|
|
@ -207,6 +226,10 @@ 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_wsss_table(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
int iwl_bios_get_ewss_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);
|
||||
|
|
@ -242,6 +265,7 @@ bool iwl_puncturing_is_allowed_in_bios(u32 puncturing, u16 mcc);
|
|||
|
||||
int iwl_bios_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value);
|
||||
int iwl_bios_get_phy_filters(struct iwl_fw_runtime *fwrt);
|
||||
void iwl_bios_get_guid_lock_status(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
static inline void iwl_bios_setup_step(struct iwl_trans *trans,
|
||||
struct iwl_fw_runtime *fwrt)
|
||||
|
|
|
|||
|
|
@ -108,10 +108,14 @@ struct iwl_txf_iter_data {
|
|||
* @dump: debug dump data
|
||||
* @ap_type_cmd: AP type tables (for enablement on 6 GHz)
|
||||
* @ap_type_cmd_valid: if &ap_type_cmd is valid
|
||||
* @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.
|
||||
* @uefi_tables_lock_status: the status of the WIFI GUID UEFI variables lock,
|
||||
* see &enum iwl_uefi_cnv_guid_status.
|
||||
* Trust the UEFI variables if locked or in test mode.
|
||||
* @sar_profiles: sar profiles as read from WRDS/EWRD BIOS tables
|
||||
* @sar_standalone_profiles: standalone sar profiles as read from
|
||||
* WSSS/EWSS BIOS tables (for Wi-Fi HB/UHB without concurrent BT)
|
||||
* @wrds_table_revision: revision of WRDS BIOS table
|
||||
* @ewrd_table_revision: revision of EWRD BIOS table
|
||||
* @geo_profiles: geographic profiles as read from WGDS BIOS table
|
||||
* @geo_bios_source: see &enum bios_source
|
||||
* @phy_filters: specific phy filters as read from WPFC BIOS table
|
||||
|
|
@ -206,6 +210,9 @@ struct iwl_fw_runtime {
|
|||
bool tpc_enabled;
|
||||
#endif /* CONFIG_IWLWIFI_DEBUGFS */
|
||||
struct iwl_sar_profile sar_profiles[BIOS_SAR_MAX_PROFILE_NUM];
|
||||
struct iwl_sar_profile sar_standalone_profiles[BIOS_SAR_MAX_PROFILE_NUM];
|
||||
u8 wrds_table_revision;
|
||||
u8 ewrd_table_revision;
|
||||
u8 sar_chain_a_profile;
|
||||
u8 sar_chain_b_profile;
|
||||
u8 reduced_power_flags;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#include "iwl-drv.h"
|
||||
#include "pnvm.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
|
||||
#include "fw/uefi.h"
|
||||
#include "fw/api/alive.h"
|
||||
|
|
@ -20,6 +20,10 @@
|
|||
0x8d, 0x03, 0x77, 0x2e, \
|
||||
0xcc, 0x3d, 0xa5, 0x31)
|
||||
|
||||
#define IWL_EFI_GLUI_GUID EFI_GUID(0x6c5bed75, 0x0ee8, 0x4d45, \
|
||||
0x98, 0x0b, 0x4d, 0x81, \
|
||||
0x31, 0xba, 0x84, 0xb5)
|
||||
|
||||
struct iwl_uefi_pnvm_mem_desc {
|
||||
__le32 addr;
|
||||
__le32 size;
|
||||
|
|
@ -27,9 +31,10 @@ struct iwl_uefi_pnvm_mem_desc {
|
|||
} __packed;
|
||||
|
||||
static void *iwl_uefi_get_variable(efi_char16_t *name, efi_guid_t *guid,
|
||||
unsigned long *data_size)
|
||||
u32 *attributes, unsigned long *data_size)
|
||||
{
|
||||
efi_status_t status;
|
||||
u32 attr = 0;
|
||||
void *data;
|
||||
|
||||
if (!data_size)
|
||||
|
|
@ -48,15 +53,28 @@ static void *iwl_uefi_get_variable(efi_char16_t *name, efi_guid_t *guid,
|
|||
if (!data)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
status = efi.get_variable(name, guid, NULL, data_size, data);
|
||||
status = efi.get_variable(name, guid, &attr, data_size, data);
|
||||
if (status != EFI_SUCCESS) {
|
||||
kfree(data);
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
||||
if (attributes)
|
||||
*attributes = attr;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static efi_status_t iwl_uefi_set_variable(efi_char16_t *name, efi_guid_t *guid,
|
||||
u32 attributes, void *data,
|
||||
unsigned long data_size)
|
||||
{
|
||||
if (!efi_rt_services_supported(EFI_RT_SUPPORTED_SET_VARIABLE))
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
return efi.set_variable(name, guid, attributes, data_size, data);
|
||||
}
|
||||
|
||||
void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
|
||||
{
|
||||
unsigned long package_size;
|
||||
|
|
@ -65,7 +83,7 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
|
|||
*len = 0;
|
||||
|
||||
data = iwl_uefi_get_variable(IWL_UEFI_OEM_PNVM_NAME, &IWL_EFI_WIFI_GUID,
|
||||
&package_size);
|
||||
NULL, &package_size);
|
||||
if (IS_ERR(data)) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
"PNVM UEFI variable not found 0x%lx (len %lu)\n",
|
||||
|
|
@ -80,17 +98,18 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
|
|||
}
|
||||
|
||||
static void *
|
||||
iwl_uefi_get_verified_variable_guid(struct iwl_trans *trans,
|
||||
efi_guid_t *guid,
|
||||
efi_char16_t *uefi_var_name,
|
||||
char *var_name,
|
||||
unsigned int expected_size,
|
||||
unsigned long *size)
|
||||
iwl_uefi_get_variable_guid(struct iwl_trans *trans,
|
||||
efi_guid_t *guid,
|
||||
efi_char16_t *uefi_var_name,
|
||||
char *var_name,
|
||||
unsigned int expected_size,
|
||||
unsigned long *size,
|
||||
u32 *attributes)
|
||||
{
|
||||
void *var;
|
||||
unsigned long var_size;
|
||||
|
||||
var = iwl_uefi_get_variable(uefi_var_name, guid, &var_size);
|
||||
var = iwl_uefi_get_variable(uefi_var_name, guid, attributes, &var_size);
|
||||
|
||||
if (IS_ERR(var)) {
|
||||
IWL_DEBUG_RADIO(trans,
|
||||
|
|
@ -116,13 +135,72 @@ iwl_uefi_get_verified_variable_guid(struct iwl_trans *trans,
|
|||
}
|
||||
|
||||
static void *
|
||||
iwl_uefi_get_verified_variable(struct iwl_trans *trans,
|
||||
iwl_uefi_get_verified_variable_guid(struct iwl_fw_runtime *fwrt,
|
||||
efi_guid_t *guid,
|
||||
efi_char16_t *uefi_var_name,
|
||||
char *var_name,
|
||||
unsigned int expected_size,
|
||||
unsigned long *size)
|
||||
{
|
||||
unsigned long var_size;
|
||||
u32 attributes = 0;
|
||||
void *var;
|
||||
|
||||
if (fwrt->uefi_tables_lock_status == UEFI_CNV_GUID_UNLOCKED)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* In x86 either GLUI or GLAI should exist */
|
||||
if ((IS_ENABLED(CONFIG_X86) || IS_ENABLED(CONFIG_X86_64) ||
|
||||
IS_ENABLED(CONFIG_X86_32)) &&
|
||||
fwrt->uefi_tables_lock_status == UEFI_CNV_GUID_UNKNOWN)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
var = iwl_uefi_get_variable_guid(fwrt->trans,
|
||||
guid,
|
||||
uefi_var_name, var_name,
|
||||
expected_size, &var_size,
|
||||
&attributes);
|
||||
if (IS_ERR(var))
|
||||
return var;
|
||||
|
||||
if (fwrt->uefi_tables_lock_status != UEFI_CNV_GUID_UNKNOWN)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* The lock status is unknown, so probe it: rewrite the variable
|
||||
* with the data just read and trust it only if the firmware
|
||||
* refuses the write. Treat a zero attributes value as untrusted,
|
||||
* since a SetVariable() with no attributes would delete it.
|
||||
*/
|
||||
if (attributes) {
|
||||
efi_status_t status;
|
||||
|
||||
status = iwl_uefi_set_variable(uefi_var_name, guid, attributes,
|
||||
var, var_size);
|
||||
if (status == EFI_WRITE_PROTECTED ||
|
||||
status == EFI_SECURITY_VIOLATION ||
|
||||
status == EFI_ACCESS_DENIED)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* unprobeable (e.g. EFI_UNSUPPORTED) or writable: not trusted */
|
||||
kfree(var);
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
out:
|
||||
if (size)
|
||||
*size = var_size;
|
||||
return var;
|
||||
}
|
||||
|
||||
static void *
|
||||
iwl_uefi_get_verified_wifi_var(struct iwl_fw_runtime *fwrt,
|
||||
efi_char16_t *uefi_var_name,
|
||||
char *var_name,
|
||||
unsigned int expected_size,
|
||||
unsigned long *size)
|
||||
{
|
||||
return iwl_uefi_get_verified_variable_guid(trans, &IWL_EFI_WIFI_GUID,
|
||||
return iwl_uefi_get_verified_variable_guid(fwrt, &IWL_EFI_WIFI_GUID,
|
||||
uefi_var_name, var_name,
|
||||
expected_size, size);
|
||||
}
|
||||
|
|
@ -173,15 +251,24 @@ static int iwl_uefi_reduce_power_section(struct iwl_trans *trans,
|
|||
memset(pnvm_data, 0, sizeof(*pnvm_data));
|
||||
|
||||
while (len >= sizeof(*tlv)) {
|
||||
u32 tlv_len, tlv_type;
|
||||
u32 tlv_len, tlv_type, tlv_len_aligned;
|
||||
|
||||
len -= sizeof(*tlv);
|
||||
tlv = (const void *)data;
|
||||
|
||||
tlv_len = le32_to_cpu(tlv->length);
|
||||
tlv_type = le32_to_cpu(tlv->type);
|
||||
tlv_len_aligned = ALIGN(tlv_len, 4);
|
||||
|
||||
if (len < tlv_len) {
|
||||
/* Make sure ALIGN() did not overflow for a malformed TLV length. */
|
||||
if (tlv_len_aligned < tlv_len) {
|
||||
IWL_ERR(trans,
|
||||
"TLV len overflows on alignment: %u\n",
|
||||
tlv_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (len < tlv_len_aligned) {
|
||||
IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
|
||||
len, tlv_len);
|
||||
return -EINVAL;
|
||||
|
|
@ -200,13 +287,13 @@ static int iwl_uefi_reduce_power_section(struct iwl_trans *trans,
|
|||
"New REDUCE_POWER section started, stop parsing.\n");
|
||||
goto done;
|
||||
default:
|
||||
IWL_DEBUG_FW(trans, "Found TLV 0x%0x, len %d\n",
|
||||
IWL_DEBUG_FW(trans, "Found TLV 0x%0x, len %u\n",
|
||||
tlv_type, tlv_len);
|
||||
break;
|
||||
}
|
||||
|
||||
len -= ALIGN(tlv_len, 4);
|
||||
data += ALIGN(tlv_len, 4);
|
||||
len -= tlv_len_aligned;
|
||||
data += tlv_len_aligned;
|
||||
}
|
||||
|
||||
done:
|
||||
|
|
@ -227,15 +314,24 @@ int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
|
|||
IWL_DEBUG_FW(trans, "Parsing REDUCE_POWER data\n");
|
||||
|
||||
while (len >= sizeof(*tlv)) {
|
||||
u32 tlv_len, tlv_type;
|
||||
u32 tlv_len, tlv_type, tlv_len_aligned;
|
||||
|
||||
len -= sizeof(*tlv);
|
||||
tlv = (const void *)data;
|
||||
|
||||
tlv_len = le32_to_cpu(tlv->length);
|
||||
tlv_type = le32_to_cpu(tlv->type);
|
||||
tlv_len_aligned = ALIGN(tlv_len, 4);
|
||||
|
||||
if (len < tlv_len) {
|
||||
/* Make sure ALIGN() did not overflow for a malformed TLV length. */
|
||||
if (tlv_len_aligned < tlv_len) {
|
||||
IWL_ERR(trans,
|
||||
"TLV len overflows on alignment: %u\n",
|
||||
tlv_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (len < tlv_len_aligned) {
|
||||
IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
|
||||
len, tlv_len);
|
||||
return -EINVAL;
|
||||
|
|
@ -245,22 +341,23 @@ int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
|
|||
const struct iwl_sku_id *tlv_sku_id =
|
||||
(const void *)(data + sizeof(*tlv));
|
||||
|
||||
IWL_DEBUG_FW(trans,
|
||||
"Got IWL_UCODE_TLV_PNVM_SKU len %d\n",
|
||||
tlv_len);
|
||||
if (tlv_len < sizeof(*tlv_sku_id)) {
|
||||
IWL_ERR(trans, "invalid PNVM SKU TLV len: %u\n",
|
||||
tlv_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
IWL_DEBUG_FW(trans,
|
||||
"Got IWL_UCODE_TLV_PNVM_SKU len %u\n",
|
||||
tlv_len);
|
||||
|
||||
IWL_DEBUG_FW(trans, "sku_id 0x%0x 0x%0x 0x%0x\n",
|
||||
le32_to_cpu(tlv_sku_id->data[0]),
|
||||
le32_to_cpu(tlv_sku_id->data[1]),
|
||||
le32_to_cpu(tlv_sku_id->data[2]));
|
||||
|
||||
data += sizeof(*tlv) + ALIGN(tlv_len, 4);
|
||||
len -= ALIGN(tlv_len, 4);
|
||||
data += sizeof(*tlv) + tlv_len_aligned;
|
||||
len -= tlv_len_aligned;
|
||||
|
||||
if (sku_id[0] == tlv_sku_id->data[0] &&
|
||||
sku_id[1] == tlv_sku_id->data[1] &&
|
||||
|
|
@ -274,8 +371,8 @@ int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
|
|||
IWL_DEBUG_FW(trans, "SKU ID didn't match!\n");
|
||||
}
|
||||
} else {
|
||||
data += sizeof(*tlv) + ALIGN(tlv_len, 4);
|
||||
len -= ALIGN(tlv_len, 4);
|
||||
data += sizeof(*tlv) + tlv_len_aligned;
|
||||
len -= tlv_len_aligned;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -288,11 +385,12 @@ u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
|
|||
unsigned long package_size;
|
||||
u8 *data;
|
||||
|
||||
package = iwl_uefi_get_verified_variable(trans,
|
||||
IWL_UEFI_REDUCED_POWER_NAME,
|
||||
"Reduced Power",
|
||||
sizeof(*package),
|
||||
&package_size);
|
||||
package =
|
||||
iwl_uefi_get_variable_guid(trans, &IWL_EFI_WIFI_GUID,
|
||||
IWL_UEFI_REDUCED_POWER_NAME,
|
||||
"Reduced Power",
|
||||
sizeof(*package),
|
||||
&package_size, NULL);
|
||||
if (IS_ERR(package))
|
||||
return ERR_CAST(package);
|
||||
|
||||
|
|
@ -334,9 +432,9 @@ void iwl_uefi_get_step_table(struct iwl_trans *trans)
|
|||
if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
|
||||
return;
|
||||
|
||||
data = iwl_uefi_get_verified_variable_guid(trans, &IWL_EFI_WIFI_BT_GUID,
|
||||
IWL_UEFI_STEP_NAME,
|
||||
"STEP", sizeof(*data), NULL);
|
||||
data = iwl_uefi_get_variable_guid(trans, &IWL_EFI_WIFI_BT_GUID,
|
||||
IWL_UEFI_STEP_NAME, "STEP",
|
||||
sizeof(*data), NULL, NULL);
|
||||
if (IS_ERR(data))
|
||||
return;
|
||||
|
||||
|
|
@ -389,8 +487,9 @@ void iwl_uefi_get_sgom_table(struct iwl_trans *trans,
|
|||
if (!fwrt->geo_enabled)
|
||||
return;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(trans, IWL_UEFI_SGOM_NAME,
|
||||
"SGOM", sizeof(*data), NULL);
|
||||
data = iwl_uefi_get_variable_guid(trans, &IWL_EFI_WIFI_GUID,
|
||||
IWL_UEFI_SGOM_NAME, "SGOM",
|
||||
sizeof(*data), NULL, NULL);
|
||||
if (IS_ERR(data))
|
||||
return;
|
||||
|
||||
|
|
@ -423,8 +522,9 @@ void iwl_uefi_get_uats_table(struct iwl_trans *trans,
|
|||
struct uefi_cnv_wlan_uats_data *data;
|
||||
int ret;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(trans, IWL_UEFI_UATS_NAME,
|
||||
"UATS", sizeof(*data), NULL);
|
||||
data = iwl_uefi_get_variable_guid(trans, &IWL_EFI_WIFI_GUID,
|
||||
IWL_UEFI_UATS_NAME, "UATS",
|
||||
sizeof(*data), NULL, NULL);
|
||||
if (IS_ERR(data))
|
||||
return;
|
||||
|
||||
|
|
@ -440,8 +540,9 @@ void iwl_uefi_get_uneb_table(struct iwl_trans *trans,
|
|||
{
|
||||
struct uefi_cnv_wlan_uneb_data *data;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(trans, IWL_UEFI_UNEB_NAME,
|
||||
"UNEB", sizeof(*data), NULL);
|
||||
data = iwl_uefi_get_variable_guid(trans, &IWL_EFI_WIFI_GUID,
|
||||
IWL_UEFI_UNEB_NAME, "UNEB",
|
||||
sizeof(*data), NULL, NULL);
|
||||
if (IS_ERR(data))
|
||||
return;
|
||||
|
||||
|
|
@ -465,11 +566,11 @@ void iwl_uefi_get_uneb_table(struct iwl_trans *trans,
|
|||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_uefi_get_uneb_table);
|
||||
|
||||
static void iwl_uefi_set_sar_profile(struct iwl_fw_runtime *fwrt,
|
||||
static void iwl_uefi_set_sar_profile(struct iwl_sar_profile *profiles,
|
||||
const u8 *vals, u8 prof_index,
|
||||
u8 num_subbands, bool enabled)
|
||||
u8 num_subbands, u32 mode)
|
||||
{
|
||||
struct iwl_sar_profile *sar_prof = &fwrt->sar_profiles[prof_index];
|
||||
struct iwl_sar_profile *sar_prof = &profiles[prof_index];
|
||||
|
||||
/*
|
||||
* Make sure fwrt has enough room to hold the data
|
||||
|
|
@ -491,7 +592,7 @@ static void iwl_uefi_set_sar_profile(struct iwl_fw_runtime *fwrt,
|
|||
vals[chain * num_subbands + subband];
|
||||
}
|
||||
|
||||
fwrt->sar_profiles[prof_index].enabled = enabled & IWL_SAR_ENABLE_MSK;
|
||||
sar_prof->enabled = mode & IWL_SAR_ENABLE_MSK;
|
||||
}
|
||||
|
||||
int iwl_uefi_get_wrds_table(struct iwl_fw_runtime *fwrt)
|
||||
|
|
@ -502,8 +603,8 @@ int iwl_uefi_get_wrds_table(struct iwl_fw_runtime *fwrt)
|
|||
int num_subbands;
|
||||
int ret = 0;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WRDS_NAME,
|
||||
"WRDS",
|
||||
data = iwl_uefi_get_verified_wifi_var(fwrt,
|
||||
IWL_UEFI_WRDS_NAME, "WRDS",
|
||||
UEFI_SAR_WRDS_TABLE_SIZE_REV2,
|
||||
&size);
|
||||
|
||||
|
|
@ -535,8 +636,9 @@ int iwl_uefi_get_wrds_table(struct iwl_fw_runtime *fwrt)
|
|||
/* 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->vals, 0,
|
||||
iwl_uefi_set_sar_profile(fwrt->sar_profiles, data->vals, 0,
|
||||
num_subbands, data->mode);
|
||||
fwrt->wrds_table_revision = data->revision;
|
||||
out:
|
||||
kfree(data);
|
||||
return ret;
|
||||
|
|
@ -551,8 +653,8 @@ int iwl_uefi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
|
|||
int num_subbands;
|
||||
int profile_size;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_EWRD_NAME,
|
||||
"EWRD",
|
||||
data = iwl_uefi_get_verified_wifi_var(fwrt,
|
||||
IWL_UEFI_EWRD_NAME, "EWRD",
|
||||
UEFI_SAR_EWRD_TABLE_SIZE_REV2,
|
||||
&size);
|
||||
if (IS_ERR(data))
|
||||
|
|
@ -588,14 +690,136 @@ int iwl_uefi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
|
|||
* 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->vals[i * profile_size],
|
||||
iwl_uefi_set_sar_profile(fwrt->sar_profiles,
|
||||
&data->vals[i * profile_size],
|
||||
i + 1, num_subbands, data->mode);
|
||||
|
||||
fwrt->ewrd_table_revision = data->revision;
|
||||
|
||||
out:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_uefi_get_wsss_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct uefi_cnv_var_wrds *data __free(kfree) = NULL;
|
||||
unsigned long expected_size;
|
||||
unsigned long size;
|
||||
int num_subbands;
|
||||
|
||||
if (fwrt->wrds_table_revision == IWL_BIOS_REVISION_UNSET) {
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"Skipping standalone SAR: WRDS table was not read\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
data = iwl_uefi_get_verified_wifi_var(fwrt,
|
||||
IWL_UEFI_WSSS_NAME,
|
||||
"WSSS",
|
||||
UEFI_SAR_WRDS_TABLE_SIZE_REV2,
|
||||
&size);
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
switch (data->revision) {
|
||||
case 2:
|
||||
expected_size = UEFI_SAR_WRDS_TABLE_SIZE_REV2;
|
||||
num_subbands = UEFI_SAR_SUB_BANDS_NUM_REV2;
|
||||
break;
|
||||
case 3:
|
||||
expected_size = UEFI_SAR_WRDS_TABLE_SIZE_REV3;
|
||||
num_subbands = UEFI_SAR_SUB_BANDS_NUM_REV3;
|
||||
break;
|
||||
default:
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"Unsupported UEFI WSSS revision:%d\n",
|
||||
data->revision);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (size != expected_size)
|
||||
return -EINVAL;
|
||||
|
||||
if (fwrt->wrds_table_revision != data->revision) {
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"Skipping standalone SAR: WRDS/WSSS revision mismatch (WRDS rev %d, WSSS rev %d)\n",
|
||||
fwrt->wrds_table_revision,
|
||||
data->revision);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "Reading WSSS (WRDS Standalone) tbl_rev=%d\n",
|
||||
data->revision);
|
||||
iwl_uefi_set_sar_profile(fwrt->sar_standalone_profiles,
|
||||
data->vals, 0,
|
||||
num_subbands,
|
||||
data->mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_uefi_get_ewss_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct uefi_cnv_var_ewrd *data __free(kfree) = NULL;
|
||||
unsigned long expected_size;
|
||||
unsigned long size;
|
||||
int num_subbands;
|
||||
int profile_size;
|
||||
int i;
|
||||
|
||||
if (fwrt->ewrd_table_revision == IWL_BIOS_REVISION_UNSET) {
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"Skipping standalone SAR: EWRD table was not read\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
data = iwl_uefi_get_verified_wifi_var(fwrt,
|
||||
IWL_UEFI_EWSS_NAME,
|
||||
"EWSS",
|
||||
UEFI_SAR_EWRD_TABLE_SIZE_REV2,
|
||||
&size);
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
switch (data->revision) {
|
||||
case 3:
|
||||
expected_size = UEFI_SAR_EWRD_TABLE_SIZE_REV3;
|
||||
num_subbands = UEFI_SAR_SUB_BANDS_NUM_REV3;
|
||||
profile_size = UEFI_SAR_PROFILE_SIZE_REV3;
|
||||
break;
|
||||
case 2:
|
||||
expected_size = UEFI_SAR_EWRD_TABLE_SIZE_REV2;
|
||||
num_subbands = UEFI_SAR_SUB_BANDS_NUM_REV2;
|
||||
profile_size = UEFI_SAR_PROFILE_SIZE_REV2;
|
||||
break;
|
||||
default:
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"Unsupported UEFI EWSS revision:%d\n",
|
||||
data->revision);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (size != expected_size ||
|
||||
data->num_profiles >= BIOS_SAR_MAX_PROFILE_NUM)
|
||||
return -EINVAL;
|
||||
|
||||
if (fwrt->ewrd_table_revision != data->revision) {
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"Skipping standalone SAR: EWRD/EWSS revision mismatch (EWRD rev %d, EWSS rev %d)\n",
|
||||
fwrt->ewrd_table_revision,
|
||||
data->revision);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < data->num_profiles; i++)
|
||||
iwl_uefi_set_sar_profile(fwrt->sar_standalone_profiles,
|
||||
&data->vals[i * profile_size],
|
||||
i + 1, num_subbands,
|
||||
data->mode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct uefi_cnv_var_wgds *data;
|
||||
|
|
@ -605,9 +829,9 @@ int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt)
|
|||
int n_subbands;
|
||||
int ret = 0;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WGDS_NAME,
|
||||
"WGDS", UEFI_WGDS_TABLE_SIZE_REV3,
|
||||
&size);
|
||||
data = iwl_uefi_get_verified_wifi_var(fwrt,
|
||||
IWL_UEFI_WGDS_NAME, "WGDS",
|
||||
UEFI_WGDS_TABLE_SIZE_REV3, &size);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
||||
|
|
@ -680,9 +904,9 @@ int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt)
|
|||
u32 valid_rev;
|
||||
int ret = 0;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_PPAG_NAME,
|
||||
"PPAG", UEFI_PPAG_DATA_SIZE_V5,
|
||||
NULL);
|
||||
data = iwl_uefi_get_verified_wifi_var(fwrt,
|
||||
IWL_UEFI_PPAG_NAME, "PPAG",
|
||||
UEFI_PPAG_DATA_SIZE_V5, NULL);
|
||||
if (!IS_ERR(data)) {
|
||||
n_subbands = UEFI_PPAG_SUB_BANDS_NUM_REV5;
|
||||
valid_rev = BIT(5);
|
||||
|
|
@ -690,7 +914,7 @@ int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt)
|
|||
goto parse_table;
|
||||
}
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans,
|
||||
data = iwl_uefi_get_verified_wifi_var(fwrt,
|
||||
IWL_UEFI_PPAG_NAME,
|
||||
"PPAG",
|
||||
UEFI_PPAG_DATA_SIZE_V4,
|
||||
|
|
@ -748,8 +972,9 @@ int iwl_uefi_get_tas_table(struct iwl_fw_runtime *fwrt,
|
|||
struct uefi_cnv_var_wtas *uefi_tas;
|
||||
int ret, enabled;
|
||||
|
||||
uefi_tas = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WTAS_NAME,
|
||||
"WTAS", sizeof(*uefi_tas), NULL);
|
||||
uefi_tas = iwl_uefi_get_verified_wifi_var(fwrt,
|
||||
IWL_UEFI_WTAS_NAME, "WTAS",
|
||||
sizeof(*uefi_tas), NULL);
|
||||
if (IS_ERR(uefi_tas))
|
||||
return -EINVAL;
|
||||
|
||||
|
|
@ -801,7 +1026,7 @@ int iwl_uefi_get_pwr_limit(struct iwl_fw_runtime *fwrt,
|
|||
struct uefi_cnv_var_splc *data;
|
||||
int ret = 0;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_SPLC_NAME,
|
||||
data = iwl_uefi_get_verified_wifi_var(fwrt, IWL_UEFI_SPLC_NAME,
|
||||
"SPLC", sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
|
@ -823,8 +1048,9 @@ 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);
|
||||
data = iwl_uefi_get_verified_wifi_var(fwrt,
|
||||
IWL_UEFI_WRDD_NAME, "WRDD",
|
||||
sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
||||
|
|
@ -854,7 +1080,7 @@ 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_guid(fwrt->trans,
|
||||
data = iwl_uefi_get_verified_variable_guid(fwrt,
|
||||
&IWL_EFI_WIFI_BT_GUID,
|
||||
IWL_UEFI_ECKV_NAME,
|
||||
"ECKV", sizeof(*data), NULL);
|
||||
|
|
@ -878,8 +1104,9 @@ 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);
|
||||
data = iwl_uefi_get_verified_wifi_var(fwrt,
|
||||
IWL_UEFI_WBEM_NAME, "WBEM",
|
||||
sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
||||
|
|
@ -905,7 +1132,7 @@ static int iwl_uefi_load_dsm_values(struct iwl_fw_runtime *fwrt)
|
|||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(data->functions) < ARRAY_SIZE(fwrt->dsm_values));
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_DSM_NAME,
|
||||
data = iwl_uefi_get_verified_wifi_var(fwrt, IWL_UEFI_DSM_NAME,
|
||||
"DSM", sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
|
@ -915,6 +1142,12 @@ static int iwl_uefi_load_dsm_values(struct iwl_fw_runtime *fwrt)
|
|||
data->revision);
|
||||
goto out;
|
||||
}
|
||||
if (!data->functions[DSM_FUNC_QUERY]) {
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
"UEFI DSM query bitmap is empty, revision:%d\n",
|
||||
data->revision);
|
||||
goto out;
|
||||
}
|
||||
fwrt->dsm_revision = data->revision;
|
||||
fwrt->dsm_source = BIOS_SOURCE_UEFI;
|
||||
|
||||
|
|
@ -980,10 +1213,10 @@ int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt)
|
|||
struct uefi_cnv_var_puncturing_data *data;
|
||||
int ret = 0;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans,
|
||||
IWL_UEFI_PUNCTURING_NAME,
|
||||
"UefiCnvWlanPuncturing",
|
||||
sizeof(*data), NULL);
|
||||
data = iwl_uefi_get_variable_guid(fwrt->trans, &IWL_EFI_WIFI_GUID,
|
||||
IWL_UEFI_PUNCTURING_NAME,
|
||||
"UefiCnvWlanPuncturing",
|
||||
sizeof(*data), NULL, NULL);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
||||
|
|
@ -1009,7 +1242,7 @@ int iwl_uefi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value)
|
|||
struct uefi_cnv_wlan_dsbr_data *data;
|
||||
int ret = 0;
|
||||
|
||||
data = iwl_uefi_get_verified_variable_guid(fwrt->trans,
|
||||
data = iwl_uefi_get_verified_variable_guid(fwrt,
|
||||
&IWL_EFI_WIFI_BT_GUID,
|
||||
IWL_UEFI_DSBR_NAME, "DSBR",
|
||||
sizeof(*data), NULL);
|
||||
|
|
@ -1035,8 +1268,9 @@ int iwl_uefi_get_phy_filters(struct iwl_fw_runtime *fwrt)
|
|||
struct uefi_cnv_wpfc_data *data __free(kfree);
|
||||
struct iwl_phy_specific_cfg *filters = &fwrt->phy_filters;
|
||||
|
||||
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WPFC_NAME,
|
||||
"WPFC", sizeof(*data), NULL);
|
||||
data = iwl_uefi_get_verified_wifi_var(fwrt,
|
||||
IWL_UEFI_WPFC_NAME, "WPFC",
|
||||
sizeof(*data), NULL);
|
||||
if (IS_ERR(data))
|
||||
return -EINVAL;
|
||||
|
||||
|
|
@ -1057,3 +1291,33 @@ int iwl_uefi_get_phy_filters(struct iwl_fw_runtime *fwrt)
|
|||
IWL_DEBUG_RADIO(fwrt, "Loaded WPFC config from UEFI\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void iwl_uefi_get_guid_lock_status(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct uefi_cnv_var_glui *data __free(kfree) =
|
||||
iwl_uefi_get_variable_guid(fwrt->trans,
|
||||
&IWL_EFI_GLUI_GUID,
|
||||
IWL_UEFI_GLUI_NAME, "GLUI",
|
||||
sizeof(*data), NULL, NULL);
|
||||
|
||||
if (IS_ERR(data))
|
||||
return;
|
||||
|
||||
if (data->revision != IWL_UEFI_GLUI_REVISION) {
|
||||
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI GLUI revision:%d\n",
|
||||
data->revision);
|
||||
return;
|
||||
}
|
||||
|
||||
/* UEFI_CNV_GUID_TEST_MODE is the max value the BIOS can report */
|
||||
if (data->guid_lock_status > UEFI_CNV_GUID_TEST_MODE) {
|
||||
IWL_DEBUG_RADIO(fwrt, "Invalid UEFI GUID lock status:%d\n",
|
||||
data->guid_lock_status);
|
||||
return;
|
||||
}
|
||||
|
||||
fwrt->uefi_tables_lock_status = data->guid_lock_status;
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "Loaded UEFI WIFI GUID lock status: %d\n",
|
||||
fwrt->uefi_tables_lock_status);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,10 @@
|
|||
#define IWL_UEFI_STEP_NAME L"UefiCnvCommonSTEP"
|
||||
#define IWL_UEFI_UATS_NAME L"CnvUefiWlanUATS"
|
||||
#define IWL_UEFI_WRDS_NAME L"UefiCnvWlanWRDS"
|
||||
#define IWL_UEFI_GLUI_NAME L"UefiCnvCommonGLUI"
|
||||
#define IWL_UEFI_EWRD_NAME L"UefiCnvWlanEWRD"
|
||||
#define IWL_UEFI_WSSS_NAME L"UefiCnvWlanWSSS"
|
||||
#define IWL_UEFI_EWSS_NAME L"UefiCnvWlanEWSS"
|
||||
#define IWL_UEFI_WGDS_NAME L"UefiCnvWlanWGDS"
|
||||
#define IWL_UEFI_PPAG_NAME L"UefiCnvWlanPPAG"
|
||||
#define IWL_UEFI_WTAS_NAME L"UefiCnvWlanWTAS"
|
||||
|
|
@ -40,6 +43,7 @@
|
|||
#define IWL_UEFI_DSM_REVISION 4
|
||||
#define IWL_UEFI_PUNCTURING_REVISION 0
|
||||
#define IWL_UEFI_DSBR_REVISION 1
|
||||
#define IWL_UEFI_GLUI_REVISION 0
|
||||
|
||||
struct pnvm_sku_package {
|
||||
u8 rev;
|
||||
|
|
@ -54,6 +58,11 @@ struct uefi_cnv_wlan_sgom_data {
|
|||
u8 offset_map[IWL_SGOM_MAP_SIZE - 1];
|
||||
} __packed;
|
||||
|
||||
struct uefi_cnv_var_glui {
|
||||
u8 revision;
|
||||
u8 guid_lock_status;
|
||||
} __packed;
|
||||
|
||||
struct uefi_cnv_wlan_uats_data {
|
||||
u8 revision;
|
||||
u8 mcc_to_ap_type_map[IWL_UATS_MAP_SIZE - 1];
|
||||
|
|
@ -330,6 +339,8 @@ 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_wsss_table(struct iwl_fw_runtime *fwrt);
|
||||
int iwl_uefi_get_ewss_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,
|
||||
|
|
@ -349,6 +360,7 @@ void iwl_uefi_get_uneb_table(struct iwl_trans *trans,
|
|||
int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt);
|
||||
int iwl_uefi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value);
|
||||
int iwl_uefi_get_phy_filters(struct iwl_fw_runtime *fwrt);
|
||||
void iwl_uefi_get_guid_lock_status(struct iwl_fw_runtime *fwrt);
|
||||
#else /* CONFIG_EFI */
|
||||
static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
|
||||
{
|
||||
|
|
@ -391,6 +403,16 @@ static inline int iwl_uefi_get_ewrd_table(struct iwl_fw_runtime *fwrt)
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_uefi_get_wsss_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_uefi_get_ewss_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return -ENOENT;
|
||||
|
|
@ -466,5 +488,9 @@ static inline int iwl_uefi_get_phy_filters(struct iwl_fw_runtime *fwrt)
|
|||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline void iwl_uefi_get_guid_lock_status(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_EFI */
|
||||
#endif /* __iwl_fw_uefi__ */
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@
|
|||
* low power states due to driver-invoked device resets
|
||||
* (e.g. CSR_RESET_REG_FLAG_SW_RESET) or uCode-driven power-saving modes.
|
||||
*
|
||||
* Use iwl_write32() and iwl_read32() family to access these registers;
|
||||
* Use iwl_trans_write32() and iwl_trans_read32() family to access these registers;
|
||||
* these provide simple PCI bus access, without waking up the MAC.
|
||||
* Do not use iwl_write_direct32() family for these registers;
|
||||
* Do not use iwl_trans_write_direct32() family for these registers;
|
||||
* no need to "grab nic access" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ.
|
||||
* The MAC (uCode processor, etc.) does not need to be powered up for accessing
|
||||
* the CSR registers.
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
#define CSR_GP_CNTRL (CSR_BASE+0x024)
|
||||
#define CSR_FUNC_SCRATCH (CSR_BASE+0x02c) /* Scratch register - used for FW dbg */
|
||||
|
||||
/* 2nd byte of CSR_INT_COALESCING, not accessible via iwl_write32()! */
|
||||
/* 2nd byte of CSR_INT_COALESCING, not accessible via iwl_trans_write32()! */
|
||||
#define CSR_INT_PERIODIC_REG (CSR_BASE+0x005)
|
||||
|
||||
/*
|
||||
|
|
@ -474,7 +474,7 @@ enum {
|
|||
* indirect read/write via HEEP_CTRL_WRD_PCIEX_CTRL (0xEC) and
|
||||
* HEEP_CTRL_WRD_PCIEX_DATA (0xF4) registers.
|
||||
*
|
||||
* Use iwl_write32()/iwl_read32() family to access these registers. The MAC HW
|
||||
* Use iwl_trans_write32()/iwl_trans_read32() family to access these registers. The MAC HW
|
||||
* need not be powered up so no "grab inc access" is required.
|
||||
*/
|
||||
|
||||
|
|
@ -501,12 +501,13 @@ enum {
|
|||
* to indirectly access device's internal memory or registers that
|
||||
* may be powered-down.
|
||||
*
|
||||
* Use iwl_write_direct32()/iwl_read_direct32() family for these registers;
|
||||
* Use iwl_trans_write_direct32() family for writing to these registers;
|
||||
* A read operation doesn't exist, can be added if needed.
|
||||
* host must "grab nic access" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ
|
||||
* to make sure the MAC (uCode processor, etc.) is powered up for accessing
|
||||
* internal resources.
|
||||
*
|
||||
* Do not use iwl_write32()/iwl_read32() family to access these registers;
|
||||
* Do not use iwl_trans_write32()/iwl_trans_read32() family to access these registers;
|
||||
* these provide only simple PCI bus access, without waking up the MAC.
|
||||
*/
|
||||
#define HBUS_BASE (0x400)
|
||||
|
|
|
|||
|
|
@ -167,11 +167,13 @@ static int iwl_dbg_tlv_alloc_hcmd(struct iwl_trans *trans,
|
|||
const struct iwl_ucode_tlv *tlv)
|
||||
{
|
||||
const struct iwl_fw_ini_hcmd_tlv *hcmd = (const void *)tlv->data;
|
||||
u32 tp = le32_to_cpu(hcmd->time_point);
|
||||
u32 tp;
|
||||
|
||||
if (le32_to_cpu(tlv->length) <= sizeof(*hcmd))
|
||||
return -EINVAL;
|
||||
|
||||
tp = le32_to_cpu(hcmd->time_point);
|
||||
|
||||
/* Host commands can not be sent in early time point since the FW
|
||||
* is not ready
|
||||
*/
|
||||
|
|
@ -194,9 +196,14 @@ static int iwl_dbg_tlv_alloc_region(struct iwl_trans *trans,
|
|||
{
|
||||
const struct iwl_fw_ini_region_tlv *reg = (const void *)tlv->data;
|
||||
struct iwl_ucode_tlv **active_reg;
|
||||
u32 id = le32_to_cpu(reg->id);
|
||||
u8 type = reg->type;
|
||||
u32 tlv_len = sizeof(*tlv) + le32_to_cpu(tlv->length);
|
||||
u32 id;
|
||||
u8 type;
|
||||
|
||||
if (le32_to_cpu(tlv->length) < sizeof(*reg))
|
||||
return -EINVAL;
|
||||
|
||||
id = le32_to_cpu(reg->id);
|
||||
|
||||
/*
|
||||
* The higher part of the ID from version 2 is debug policy.
|
||||
|
|
@ -205,9 +212,6 @@ static int iwl_dbg_tlv_alloc_region(struct iwl_trans *trans,
|
|||
if (le32_to_cpu(reg->hdr.version) >= 2)
|
||||
id &= IWL_FW_INI_REGION_ID_MASK;
|
||||
|
||||
if (le32_to_cpu(tlv->length) < sizeof(*reg))
|
||||
return -EINVAL;
|
||||
|
||||
/* for safe use of a string from FW, limit it to IWL_FW_INI_MAX_NAME */
|
||||
IWL_DEBUG_FW(trans, "WRT: parsing region: %.*s\n",
|
||||
IWL_FW_INI_MAX_NAME, reg->name);
|
||||
|
|
@ -217,12 +221,26 @@ static int iwl_dbg_tlv_alloc_region(struct iwl_trans *trans,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
type = reg->type;
|
||||
|
||||
if (type <= IWL_FW_INI_REGION_INVALID ||
|
||||
type >= IWL_FW_INI_REGION_NUM) {
|
||||
IWL_ERR(trans, "WRT: Invalid region type %u\n", type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (type == IWL_FW_INI_REGION_DRAM_BUFFER) {
|
||||
u32 alloc_id = le32_to_cpu(reg->dram_alloc_id);
|
||||
|
||||
if (alloc_id <= IWL_FW_INI_ALLOCATION_INVALID ||
|
||||
alloc_id >= ARRAY_SIZE(trans->dbg.fw_mon_ini)) {
|
||||
IWL_ERR(trans,
|
||||
"WRT: Invalid dram_alloc_id %u for region %u\n",
|
||||
alloc_id, id);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == IWL_FW_INI_REGION_INTERNAL_BUFFER) {
|
||||
trans->dbg.imr_data.sram_addr =
|
||||
le32_to_cpu(reg->internal_buffer.base_addr);
|
||||
|
|
@ -251,13 +269,14 @@ 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;
|
||||
u32 tp = le32_to_cpu(trig->time_point);
|
||||
u32 rf = le32_to_cpu(trig->reset_fw);
|
||||
u32 tp, rf;
|
||||
struct iwl_ucode_tlv *new_tlv;
|
||||
|
||||
if (le32_to_cpu(tlv->length) < sizeof(*trig))
|
||||
return -EINVAL;
|
||||
|
||||
tp = le32_to_cpu(trig->time_point);
|
||||
|
||||
if (tp <= IWL_FW_INI_TIME_POINT_INVALID ||
|
||||
tp >= IWL_FW_INI_TIME_POINT_NUM) {
|
||||
IWL_ERR(trans,
|
||||
|
|
@ -266,6 +285,8 @@ static int iwl_dbg_tlv_alloc_trigger(struct iwl_trans *trans,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
rf = le32_to_cpu(trig->reset_fw);
|
||||
|
||||
IWL_DEBUG_FW(trans,
|
||||
"WRT: time point %u for trigger TLV with reset_fw %u\n",
|
||||
tp, rf);
|
||||
|
|
@ -288,8 +309,13 @@ static int iwl_dbg_tlv_config_set(struct iwl_trans *trans,
|
|||
const struct iwl_ucode_tlv *tlv)
|
||||
{
|
||||
const struct iwl_fw_ini_conf_set_tlv *conf_set = (const void *)tlv->data;
|
||||
u32 tp = le32_to_cpu(conf_set->time_point);
|
||||
u32 type = le32_to_cpu(conf_set->set_type);
|
||||
u32 tp, type;
|
||||
|
||||
if (le32_to_cpu(tlv->length) < sizeof(*conf_set))
|
||||
return -EINVAL;
|
||||
|
||||
tp = le32_to_cpu(conf_set->time_point);
|
||||
type = le32_to_cpu(conf_set->set_type);
|
||||
|
||||
if (tp <= IWL_FW_INI_TIME_POINT_INVALID ||
|
||||
tp >= IWL_FW_INI_TIME_POINT_NUM) {
|
||||
|
|
@ -593,7 +619,7 @@ static int iwl_dbg_tlv_alloc_fragments(struct iwl_fw_runtime *fwrt,
|
|||
u32 num_frags, remain_pages, frag_pages;
|
||||
int i;
|
||||
|
||||
if (alloc_id < IWL_FW_INI_ALLOCATION_INVALID ||
|
||||
if (alloc_id <= IWL_FW_INI_ALLOCATION_INVALID ||
|
||||
alloc_id >= IWL_FW_INI_ALLOCATION_NUM)
|
||||
return -EIO;
|
||||
|
||||
|
|
@ -676,7 +702,7 @@ static int iwl_dbg_tlv_apply_buffer(struct iwl_fw_runtime *fwrt,
|
|||
IWL_UCODE_TLV_CAPA_DBG_BUF_ALLOC_CMD_SUPP))
|
||||
return 0;
|
||||
|
||||
if (alloc_id < IWL_FW_INI_ALLOCATION_INVALID ||
|
||||
if (alloc_id <= IWL_FW_INI_ALLOCATION_INVALID ||
|
||||
alloc_id >= IWL_FW_INI_ALLOCATION_NUM)
|
||||
return -EIO;
|
||||
|
||||
|
|
@ -886,7 +912,7 @@ static void iwl_dbg_tlv_apply_config(struct iwl_fw_runtime *fwrt,
|
|||
for (count = 0; count < len; count++) {
|
||||
address = le32_to_cpu(config_list->addr_val[count].address);
|
||||
value = le32_to_cpu(config_list->addr_val[count].value);
|
||||
iwl_trans_write_prph(fwrt->trans, address + offset, value);
|
||||
iwl_trans_write_prph_no_grab(fwrt->trans, address + offset, value);
|
||||
}
|
||||
iwl_trans_release_nic_access(fwrt->trans);
|
||||
break;
|
||||
|
|
@ -905,7 +931,7 @@ static void iwl_dbg_tlv_apply_config(struct iwl_fw_runtime *fwrt,
|
|||
for (count = 0; count < len; count++) {
|
||||
address = le32_to_cpu(config_list->addr_val[count].address);
|
||||
value = le32_to_cpu(config_list->addr_val[count].value);
|
||||
iwl_write32(fwrt->trans, address + offset, value);
|
||||
iwl_trans_write32(fwrt->trans, address + offset, value);
|
||||
IWL_DEBUG_FW(fwrt, "WRT: CSR: count %u, add: %u val: %u\n",
|
||||
count, address, value);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2016-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2026 Intel Corporation
|
||||
*****************************************************************************/
|
||||
|
||||
#if !defined(__IWLWIFI_DEVICE_TRACE_IO) || defined(TRACE_HEADER_MULTI_READ)
|
||||
|
|
@ -65,23 +66,6 @@ TRACE_EVENT(iwlwifi_dev_iowrite32,
|
|||
__get_str(dev), __entry->offs, __entry->val)
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwlwifi_dev_iowrite64,
|
||||
TP_PROTO(const struct device *dev, u64 offs, u64 val),
|
||||
TP_ARGS(dev, offs, val),
|
||||
TP_STRUCT__entry(
|
||||
DEV_ENTRY
|
||||
__field(u64, offs)
|
||||
__field(u64, val)
|
||||
),
|
||||
TP_fast_assign(
|
||||
DEV_ASSIGN;
|
||||
__entry->offs = offs;
|
||||
__entry->val = val;
|
||||
),
|
||||
TP_printk("[%s] write io[%llu] = %llu)",
|
||||
__get_str(dev), __entry->offs, __entry->val)
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwlwifi_dev_iowrite_prph32,
|
||||
TP_PROTO(const struct device *dev, u32 offs, u32 val),
|
||||
TP_ARGS(dev, offs, val),
|
||||
|
|
|
|||
|
|
@ -1103,10 +1103,17 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
|||
const struct iwl_fw_dbg_dest_tlv_v1 *dest_v1 = NULL;
|
||||
u8 mon_mode;
|
||||
|
||||
if (tlv_len < sizeof(*pieces->dbg_dest_ver))
|
||||
goto invalid_tlv_len;
|
||||
|
||||
pieces->dbg_dest_ver = (const u8 *)tlv_data;
|
||||
if (*pieces->dbg_dest_ver == 1) {
|
||||
if (tlv_len < sizeof(*dest))
|
||||
goto invalid_tlv_len;
|
||||
dest = (const void *)tlv_data;
|
||||
} else if (*pieces->dbg_dest_ver == 0) {
|
||||
if (tlv_len < sizeof(*dest_v1))
|
||||
goto invalid_tlv_len;
|
||||
dest_v1 = (const void *)tlv_data;
|
||||
} else {
|
||||
IWL_ERR(drv,
|
||||
|
|
@ -2039,8 +2046,6 @@ void iwl_drv_stop(struct iwl_drv *drv)
|
|||
mutex_unlock(&iwlwifi_opmode_table_mtx);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
iwl_trans_debugfs_cleanup(drv->trans);
|
||||
|
||||
debugfs_remove_recursive(drv->dbgfs_drv);
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -1,448 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2003-2014, 2018-2022, 2024-2026 Intel Corporation
|
||||
* Copyright (C) 2015-2016 Intel Deutschland GmbH
|
||||
*/
|
||||
#include <linux/device.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "iwl-fh.h"
|
||||
|
||||
void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val)
|
||||
{
|
||||
trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val);
|
||||
iwl_trans_write8(trans, ofs, val);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_write8);
|
||||
|
||||
void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val)
|
||||
{
|
||||
trace_iwlwifi_dev_iowrite32(trans->dev, ofs, val);
|
||||
iwl_trans_write32(trans, ofs, val);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_write32);
|
||||
|
||||
void iwl_write64(struct iwl_trans *trans, u64 ofs, u64 val)
|
||||
{
|
||||
trace_iwlwifi_dev_iowrite64(trans->dev, ofs, val);
|
||||
iwl_trans_write32(trans, ofs, lower_32_bits(val));
|
||||
iwl_trans_write32(trans, ofs + 4, upper_32_bits(val));
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_write64);
|
||||
|
||||
u32 iwl_read32(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
u32 val = iwl_trans_read32(trans, ofs);
|
||||
|
||||
trace_iwlwifi_dev_ioread32(trans->dev, ofs, val);
|
||||
return val;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_read32);
|
||||
|
||||
#define IWL_POLL_INTERVAL 10 /* microseconds */
|
||||
|
||||
int iwl_poll_bits_mask(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout)
|
||||
{
|
||||
int t = 0;
|
||||
|
||||
do {
|
||||
if ((iwl_read32(trans, addr) & mask) == (bits & mask))
|
||||
return 0;
|
||||
udelay(IWL_POLL_INTERVAL);
|
||||
t += IWL_POLL_INTERVAL;
|
||||
} while (t < timeout);
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_poll_bits_mask);
|
||||
|
||||
u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
|
||||
{
|
||||
if (iwl_trans_grab_nic_access(trans)) {
|
||||
u32 value = iwl_read32(trans, reg);
|
||||
|
||||
iwl_trans_release_nic_access(trans);
|
||||
return value;
|
||||
}
|
||||
|
||||
/* return as if we have a HW timeout/failure */
|
||||
return 0x5a5a5a5a;
|
||||
}
|
||||
|
||||
void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value)
|
||||
{
|
||||
if (iwl_trans_grab_nic_access(trans)) {
|
||||
iwl_write32(trans, reg, value);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
}
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_write_direct32);
|
||||
|
||||
void iwl_write_direct64(struct iwl_trans *trans, u64 reg, u64 value)
|
||||
{
|
||||
if (iwl_trans_grab_nic_access(trans)) {
|
||||
iwl_write64(trans, reg, value);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
}
|
||||
}
|
||||
|
||||
int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
|
||||
int timeout)
|
||||
{
|
||||
int t = 0;
|
||||
|
||||
do {
|
||||
if ((iwl_read_direct32(trans, addr) & mask) == mask)
|
||||
return t;
|
||||
udelay(IWL_POLL_INTERVAL);
|
||||
t += IWL_POLL_INTERVAL;
|
||||
} while (t < timeout);
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
u32 val = iwl_trans_read_prph(trans, ofs);
|
||||
trace_iwlwifi_dev_ioread_prph32(trans->dev, ofs, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
void iwl_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val)
|
||||
{
|
||||
trace_iwlwifi_dev_iowrite_prph32(trans->dev, ofs, val);
|
||||
iwl_trans_write_prph(trans, ofs, val);
|
||||
}
|
||||
|
||||
void iwl_write_prph64_no_grab(struct iwl_trans *trans, u64 ofs, u64 val)
|
||||
{
|
||||
trace_iwlwifi_dev_iowrite_prph64(trans->dev, ofs, val);
|
||||
iwl_write_prph_no_grab(trans, ofs, val & 0xffffffff);
|
||||
iwl_write_prph_no_grab(trans, ofs + 4, val >> 32);
|
||||
}
|
||||
|
||||
u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
if (iwl_trans_grab_nic_access(trans)) {
|
||||
u32 val = iwl_read_prph_no_grab(trans, ofs);
|
||||
|
||||
iwl_trans_release_nic_access(trans);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/* return as if we have a HW timeout/failure */
|
||||
return 0x5a5a5a5a;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_read_prph);
|
||||
|
||||
void iwl_write_prph_delay(struct iwl_trans *trans, u32 ofs, u32 val, u32 delay_ms)
|
||||
{
|
||||
if (iwl_trans_grab_nic_access(trans)) {
|
||||
mdelay(delay_ms);
|
||||
iwl_write_prph_no_grab(trans, ofs, val);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
}
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_write_prph_delay);
|
||||
|
||||
int iwl_poll_prph_bit(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout)
|
||||
{
|
||||
int t = 0;
|
||||
|
||||
do {
|
||||
if ((iwl_read_prph(trans, addr) & mask) == (bits & mask))
|
||||
return 0;
|
||||
udelay(IWL_POLL_INTERVAL);
|
||||
t += IWL_POLL_INTERVAL;
|
||||
} while (t < timeout);
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
int iwl_poll_umac_prph_bits_no_grab(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout)
|
||||
{
|
||||
int t = 0;
|
||||
|
||||
do {
|
||||
if ((iwl_read_umac_prph_no_grab(trans, addr) & mask) ==
|
||||
(bits & mask))
|
||||
return 0;
|
||||
udelay(IWL_POLL_INTERVAL);
|
||||
t += IWL_POLL_INTERVAL;
|
||||
} while (t < timeout);
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
|
||||
{
|
||||
if (iwl_trans_grab_nic_access(trans)) {
|
||||
iwl_write_prph_no_grab(trans, ofs,
|
||||
iwl_read_prph_no_grab(trans, ofs) |
|
||||
mask);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
}
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_set_bits_prph);
|
||||
|
||||
void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
|
||||
u32 bits, u32 mask)
|
||||
{
|
||||
if (iwl_trans_grab_nic_access(trans)) {
|
||||
iwl_write_prph_no_grab(trans, ofs,
|
||||
(iwl_read_prph_no_grab(trans, ofs) &
|
||||
mask) | bits);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
}
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_set_bits_mask_prph);
|
||||
|
||||
void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (iwl_trans_grab_nic_access(trans)) {
|
||||
val = iwl_read_prph_no_grab(trans, ofs);
|
||||
iwl_write_prph_no_grab(trans, ofs, (val & ~mask));
|
||||
iwl_trans_release_nic_access(trans);
|
||||
}
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_clear_bits_prph);
|
||||
|
||||
void iwl_force_nmi(struct iwl_trans *trans)
|
||||
{
|
||||
if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_9000)
|
||||
iwl_write_prph_delay(trans, DEVICE_SET_NMI_REG,
|
||||
DEVICE_SET_NMI_VAL_DRV, 1);
|
||||
else if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
|
||||
iwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER,
|
||||
UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER);
|
||||
else if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
|
||||
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
|
||||
UREG_DOORBELL_TO_ISR6_NMI_BIT);
|
||||
else
|
||||
iwl_write32(trans, CSR_DOORBELL_VECTOR,
|
||||
UREG_DOORBELL_TO_ISR6_NMI_BIT);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_force_nmi);
|
||||
|
||||
static const char *get_rfh_string(int cmd)
|
||||
{
|
||||
#define IWL_CMD(x) case x: return #x
|
||||
#define IWL_CMD_MQ(arg, reg, q) { if (arg == reg(q)) return #reg; }
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < IWL_MAX_RX_HW_QUEUES; i++) {
|
||||
IWL_CMD_MQ(cmd, RFH_Q_FRBDCB_BA_LSB, i);
|
||||
IWL_CMD_MQ(cmd, RFH_Q_FRBDCB_WIDX, i);
|
||||
IWL_CMD_MQ(cmd, RFH_Q_FRBDCB_RIDX, i);
|
||||
IWL_CMD_MQ(cmd, RFH_Q_URBD_STTS_WPTR_LSB, i);
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
IWL_CMD(RFH_RXF_DMA_CFG);
|
||||
IWL_CMD(RFH_GEN_CFG);
|
||||
IWL_CMD(RFH_GEN_STATUS);
|
||||
IWL_CMD(FH_TSSR_TX_STATUS_REG);
|
||||
IWL_CMD(FH_TSSR_TX_ERROR_REG);
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
#undef IWL_CMD_MQ
|
||||
}
|
||||
|
||||
struct reg {
|
||||
u32 addr;
|
||||
bool is64;
|
||||
};
|
||||
|
||||
static int iwl_dump_rfh(struct iwl_trans *trans, char **buf)
|
||||
{
|
||||
int i, q;
|
||||
int num_q = trans->info.num_rxqs;
|
||||
static const u32 rfh_tbl[] = {
|
||||
RFH_RXF_DMA_CFG,
|
||||
RFH_GEN_CFG,
|
||||
RFH_GEN_STATUS,
|
||||
FH_TSSR_TX_STATUS_REG,
|
||||
FH_TSSR_TX_ERROR_REG,
|
||||
};
|
||||
static const struct reg rfh_mq_tbl[] = {
|
||||
{ RFH_Q0_FRBDCB_BA_LSB, true },
|
||||
{ RFH_Q0_FRBDCB_WIDX, false },
|
||||
{ RFH_Q0_FRBDCB_RIDX, false },
|
||||
{ RFH_Q0_URBD_STTS_WPTR_LSB, true },
|
||||
};
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (buf) {
|
||||
int pos = 0;
|
||||
/*
|
||||
* Register (up to 34 for name + 8 blank/q for MQ): 40 chars
|
||||
* Colon + space: 2 characters
|
||||
* 0X%08x: 10 characters
|
||||
* New line: 1 character
|
||||
* Total of 53 characters
|
||||
*/
|
||||
size_t bufsz = ARRAY_SIZE(rfh_tbl) * 53 +
|
||||
ARRAY_SIZE(rfh_mq_tbl) * 53 * num_q + 40;
|
||||
|
||||
*buf = kmalloc(bufsz, GFP_KERNEL);
|
||||
if (!*buf)
|
||||
return -ENOMEM;
|
||||
|
||||
pos += scnprintf(*buf + pos, bufsz - pos,
|
||||
"RFH register values:\n");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rfh_tbl); i++)
|
||||
pos += scnprintf(*buf + pos, bufsz - pos,
|
||||
"%40s: 0X%08x\n",
|
||||
get_rfh_string(rfh_tbl[i]),
|
||||
iwl_read_prph(trans, rfh_tbl[i]));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rfh_mq_tbl); i++)
|
||||
for (q = 0; q < num_q; q++) {
|
||||
u32 addr = rfh_mq_tbl[i].addr;
|
||||
|
||||
addr += q * (rfh_mq_tbl[i].is64 ? 8 : 4);
|
||||
pos += scnprintf(*buf + pos, bufsz - pos,
|
||||
"%34s(q %2d): 0X%08x\n",
|
||||
get_rfh_string(addr), q,
|
||||
iwl_read_prph(trans, addr));
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
#endif
|
||||
|
||||
IWL_ERR(trans, "RFH register values:\n");
|
||||
for (i = 0; i < ARRAY_SIZE(rfh_tbl); i++)
|
||||
IWL_ERR(trans, " %34s: 0X%08x\n",
|
||||
get_rfh_string(rfh_tbl[i]),
|
||||
iwl_read_prph(trans, rfh_tbl[i]));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rfh_mq_tbl); i++)
|
||||
for (q = 0; q < num_q; q++) {
|
||||
u32 addr = rfh_mq_tbl[i].addr;
|
||||
|
||||
addr += q * (rfh_mq_tbl[i].is64 ? 8 : 4);
|
||||
IWL_ERR(trans, " %34s(q %d): 0X%08x\n",
|
||||
get_rfh_string(addr), q,
|
||||
iwl_read_prph(trans, addr));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *get_fh_string(int cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
|
||||
IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
|
||||
IWL_CMD(FH_RSCSR_CHNL0_WPTR);
|
||||
IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
|
||||
IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
|
||||
IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
|
||||
IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
|
||||
IWL_CMD(FH_TSSR_TX_STATUS_REG);
|
||||
IWL_CMD(FH_TSSR_TX_ERROR_REG);
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
#undef IWL_CMD
|
||||
}
|
||||
|
||||
int iwl_dump_fh(struct iwl_trans *trans, char **buf)
|
||||
{
|
||||
int i;
|
||||
static const u32 fh_tbl[] = {
|
||||
FH_RSCSR_CHNL0_STTS_WPTR_REG,
|
||||
FH_RSCSR_CHNL0_RBDCB_BASE_REG,
|
||||
FH_RSCSR_CHNL0_WPTR,
|
||||
FH_MEM_RCSR_CHNL0_CONFIG_REG,
|
||||
FH_MEM_RSSR_SHARED_CTRL_REG,
|
||||
FH_MEM_RSSR_RX_STATUS_REG,
|
||||
FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
|
||||
FH_TSSR_TX_STATUS_REG,
|
||||
FH_TSSR_TX_ERROR_REG
|
||||
};
|
||||
|
||||
if (trans->mac_cfg->mq_rx_supported)
|
||||
return iwl_dump_rfh(trans, buf);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (buf) {
|
||||
int pos = 0;
|
||||
size_t bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
|
||||
|
||||
*buf = kmalloc(bufsz, GFP_KERNEL);
|
||||
if (!*buf)
|
||||
return -ENOMEM;
|
||||
|
||||
pos += scnprintf(*buf + pos, bufsz - pos,
|
||||
"FH register values:\n");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fh_tbl); i++)
|
||||
pos += scnprintf(*buf + pos, bufsz - pos,
|
||||
" %34s: 0X%08x\n",
|
||||
get_fh_string(fh_tbl[i]),
|
||||
iwl_read_direct32(trans, fh_tbl[i]));
|
||||
|
||||
return pos;
|
||||
}
|
||||
#endif
|
||||
|
||||
IWL_ERR(trans, "FH register values:\n");
|
||||
for (i = 0; i < ARRAY_SIZE(fh_tbl); i++)
|
||||
IWL_ERR(trans, " %34s: 0X%08x\n",
|
||||
get_fh_string(fh_tbl[i]),
|
||||
iwl_read_direct32(trans, fh_tbl[i]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr,
|
||||
u32 sw_err_bit)
|
||||
{
|
||||
unsigned long timeout = jiffies + IWL_TRANS_NMI_TIMEOUT;
|
||||
bool interrupts_enabled = test_bit(STATUS_INT_ENABLED, &trans->status);
|
||||
|
||||
/* if the interrupts were already disabled, there is no point in
|
||||
* calling iwl_disable_interrupts
|
||||
*/
|
||||
if (interrupts_enabled)
|
||||
iwl_trans_interrupts(trans, false);
|
||||
|
||||
iwl_force_nmi(trans);
|
||||
while (time_after(timeout, jiffies)) {
|
||||
u32 inta_hw = iwl_read32(trans, inta_addr);
|
||||
|
||||
/* Error detected by uCode */
|
||||
if (inta_hw & sw_err_bit) {
|
||||
/* Clear causes register */
|
||||
iwl_write32(trans, inta_addr, inta_hw & sw_err_bit);
|
||||
break;
|
||||
}
|
||||
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
/* enable interrupts only if there were already enabled before this
|
||||
* function to avoid a case were the driver enable interrupts before
|
||||
* proper configurations were made
|
||||
*/
|
||||
if (interrupts_enabled)
|
||||
iwl_trans_interrupts(trans, true);
|
||||
|
||||
iwl_trans_fw_error(trans, IWL_ERR_TYPE_NMI_FORCED);
|
||||
}
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2018-2021, 2025-2026 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_io_h__
|
||||
#define __iwl_io_h__
|
||||
|
||||
#include "iwl-devtrace.h"
|
||||
#include "iwl-trans.h"
|
||||
|
||||
void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val);
|
||||
void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val);
|
||||
void iwl_write64(struct iwl_trans *trans, u64 ofs, u64 val);
|
||||
u32 iwl_read32(struct iwl_trans *trans, u32 ofs);
|
||||
|
||||
static inline void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
{
|
||||
iwl_trans_set_bits_mask(trans, reg, mask, mask);
|
||||
}
|
||||
|
||||
static inline void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
{
|
||||
iwl_trans_set_bits_mask(trans, reg, mask, 0);
|
||||
}
|
||||
|
||||
int iwl_poll_bits_mask(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout);
|
||||
static inline int iwl_poll_bits(struct iwl_trans *trans, u32 addr, u32 bits,
|
||||
int timeout)
|
||||
{
|
||||
return iwl_poll_bits_mask(trans, addr, bits, bits, timeout);
|
||||
}
|
||||
int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
|
||||
int timeout);
|
||||
|
||||
u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg);
|
||||
void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value);
|
||||
void iwl_write_direct64(struct iwl_trans *trans, u64 reg, u64 value);
|
||||
|
||||
|
||||
u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs);
|
||||
u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs);
|
||||
void iwl_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val);
|
||||
void iwl_write_prph64_no_grab(struct iwl_trans *trans, u64 ofs, u64 val);
|
||||
void iwl_write_prph_delay(struct iwl_trans *trans, u32 ofs,
|
||||
u32 val, u32 delay_ms);
|
||||
static inline void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
|
||||
{
|
||||
iwl_write_prph_delay(trans, ofs, val, 0);
|
||||
}
|
||||
|
||||
int iwl_poll_prph_bit(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout);
|
||||
int iwl_poll_umac_prph_bits_no_grab(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout);
|
||||
void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);
|
||||
void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
|
||||
u32 bits, u32 mask);
|
||||
void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);
|
||||
void iwl_force_nmi(struct iwl_trans *trans);
|
||||
|
||||
/* Error handling */
|
||||
int iwl_dump_fh(struct iwl_trans *trans, char **buf);
|
||||
|
||||
/*
|
||||
* UMAC periphery address space changed from 0xA00000 to 0xD00000 starting from
|
||||
* device family AX200. So peripheries used in families above and below AX200
|
||||
* should go through iwl_..._umac_..._prph.
|
||||
*/
|
||||
static inline u32 iwl_umac_prph(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
return ofs + trans->mac_cfg->umac_prph_offset;
|
||||
}
|
||||
|
||||
static inline u32 iwl_read_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
return iwl_read_prph_no_grab(trans, ofs +
|
||||
trans->mac_cfg->umac_prph_offset);
|
||||
}
|
||||
|
||||
static inline u32 iwl_read_umac_prph(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
return iwl_read_prph(trans, ofs + trans->mac_cfg->umac_prph_offset);
|
||||
}
|
||||
|
||||
static inline void iwl_write_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs,
|
||||
u32 val)
|
||||
{
|
||||
iwl_write_prph_no_grab(trans, ofs + trans->mac_cfg->umac_prph_offset,
|
||||
val);
|
||||
}
|
||||
|
||||
static inline void iwl_write_umac_prph(struct iwl_trans *trans, u32 ofs,
|
||||
u32 val)
|
||||
{
|
||||
iwl_write_prph(trans, ofs + trans->mac_cfg->umac_prph_offset, val);
|
||||
}
|
||||
|
||||
static inline int iwl_poll_umac_prph_bit(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout)
|
||||
{
|
||||
return iwl_poll_prph_bit(trans, addr +
|
||||
trans->mac_cfg->umac_prph_offset,
|
||||
bits, mask, timeout);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
#include "iwl-modparams.h"
|
||||
#include "iwl-nvm-parse.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "fw/api/nvm-reg.h"
|
||||
#include "fw/api/commands.h"
|
||||
|
|
@ -612,7 +612,6 @@ static const struct ieee80211_sband_iftype_data iwl_iftype_cap[] = {
|
|||
IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP |
|
||||
IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI,
|
||||
.phy_cap_info[8] =
|
||||
IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI |
|
||||
IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |
|
||||
IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |
|
||||
IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU |
|
||||
|
|
@ -710,12 +709,14 @@ static const struct ieee80211_sband_iftype_data iwl_iftype_cap[] = {
|
|||
.has_uhr = true,
|
||||
/* Note: asymmetry is fixed later */
|
||||
.phy.cap = cpu_to_le32(IEEE80211_UHR_PHY_CAP_ELR_RX |
|
||||
IEEE80211_UHR_PHY_CAP_ELR_TX),
|
||||
IEEE80211_UHR_PHY_CAP_ELR_TX |
|
||||
IEEE80211_UHR_PHY_CAP_2XLDPC_RX),
|
||||
.mac.mac_cap = {
|
||||
[0] = IEEE80211_UHR_MAC_CAP0_NPCA_SUPP |
|
||||
IEEE80211_UHR_MAC_CAP0_DPS_SUPP,
|
||||
[1] = IEEE80211_UHR_MAC_CAP1_DUO_SUPP |
|
||||
IEEE80211_UHR_MAC_CAP1_DBE_SUPP,
|
||||
[4] = IEEE80211_UHR_MAC_CAP4_CO_BF_SUPP,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -746,7 +747,6 @@ static const struct ieee80211_sband_iftype_data iwl_iftype_cap[] = {
|
|||
.phy_cap_info[7] =
|
||||
IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI,
|
||||
.phy_cap_info[8] =
|
||||
IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI |
|
||||
IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_242,
|
||||
.phy_cap_info[9] =
|
||||
IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
|
||||
|
|
@ -820,7 +820,8 @@ static const struct ieee80211_sband_iftype_data iwl_iftype_cap[] = {
|
|||
.has_uhr = true,
|
||||
/* Note: asymmetry is fixed later */
|
||||
.phy.cap = cpu_to_le32(IEEE80211_UHR_PHY_CAP_ELR_RX |
|
||||
IEEE80211_UHR_PHY_CAP_ELR_TX),
|
||||
IEEE80211_UHR_PHY_CAP_ELR_TX |
|
||||
IEEE80211_UHR_PHY_CAP_2XLDPC_RX),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -1312,10 +1313,10 @@ static void iwl_flip_hw_address(__le32 mac_addr0, __le32 mac_addr1, u8 *dest)
|
|||
static void iwl_set_hw_address_from_csr(struct iwl_trans *trans,
|
||||
struct iwl_nvm_data *data)
|
||||
{
|
||||
__le32 mac_addr0 = cpu_to_le32(iwl_read32(trans,
|
||||
CSR_MAC_ADDR0_STRAP(trans)));
|
||||
__le32 mac_addr1 = cpu_to_le32(iwl_read32(trans,
|
||||
CSR_MAC_ADDR1_STRAP(trans)));
|
||||
__le32 mac_addr0 = cpu_to_le32(iwl_trans_read32(trans,
|
||||
CSR_MAC_ADDR0_STRAP(trans)));
|
||||
__le32 mac_addr1 = cpu_to_le32(iwl_trans_read32(trans,
|
||||
CSR_MAC_ADDR1_STRAP(trans)));
|
||||
|
||||
iwl_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr);
|
||||
/*
|
||||
|
|
@ -1325,8 +1326,8 @@ static void iwl_set_hw_address_from_csr(struct iwl_trans *trans,
|
|||
if (is_valid_ether_addr(data->hw_addr))
|
||||
return;
|
||||
|
||||
mac_addr0 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR0_OTP(trans)));
|
||||
mac_addr1 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR1_OTP(trans)));
|
||||
mac_addr0 = cpu_to_le32(iwl_trans_read32(trans, CSR_MAC_ADDR0_OTP(trans)));
|
||||
mac_addr1 = cpu_to_le32(iwl_trans_read32(trans, CSR_MAC_ADDR1_OTP(trans)));
|
||||
|
||||
iwl_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr);
|
||||
}
|
||||
|
|
@ -1367,10 +1368,10 @@ static void iwl_set_hw_address_family_8000(struct iwl_trans *trans,
|
|||
|
||||
if (nvm_hw) {
|
||||
/* read the mac address from WFMP registers */
|
||||
__le32 mac_addr0 = cpu_to_le32(iwl_trans_read_prph(trans,
|
||||
WFMP_MAC_ADDR_0));
|
||||
__le32 mac_addr1 = cpu_to_le32(iwl_trans_read_prph(trans,
|
||||
WFMP_MAC_ADDR_1));
|
||||
__le32 mac_addr0 = cpu_to_le32(iwl_trans_read_prph_no_grab(trans,
|
||||
WFMP_MAC_ADDR_0));
|
||||
__le32 mac_addr1 = cpu_to_le32(iwl_trans_read_prph_no_grab(trans,
|
||||
WFMP_MAC_ADDR_1));
|
||||
|
||||
iwl_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr);
|
||||
|
||||
|
|
@ -1410,7 +1411,7 @@ static int iwl_set_hw_address(struct iwl_trans *trans,
|
|||
|
||||
if (!trans->csme_own)
|
||||
IWL_INFO(trans, "base HW address: %pM, OTP minor version: 0x%x\n",
|
||||
data->hw_addr, iwl_read_prph(trans, REG_OTP_MINOR));
|
||||
data->hw_addr, iwl_trans_read_prph(trans, REG_OTP_MINOR));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,52 +1,52 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2026 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_scd_h__
|
||||
#define __iwl_scd_h__
|
||||
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-prph.h"
|
||||
|
||||
|
||||
static inline void iwl_scd_txq_set_chain(struct iwl_trans *trans,
|
||||
u16 txq_id)
|
||||
{
|
||||
iwl_set_bits_prph(trans, SCD_QUEUECHAIN_SEL, BIT(txq_id));
|
||||
iwl_trans_set_bits_prph(trans, SCD_QUEUECHAIN_SEL, BIT(txq_id));
|
||||
}
|
||||
|
||||
static inline void iwl_scd_txq_enable_agg(struct iwl_trans *trans,
|
||||
u16 txq_id)
|
||||
{
|
||||
iwl_set_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id));
|
||||
iwl_trans_set_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id));
|
||||
}
|
||||
|
||||
static inline void iwl_scd_txq_disable_agg(struct iwl_trans *trans,
|
||||
u16 txq_id)
|
||||
{
|
||||
iwl_clear_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id));
|
||||
iwl_trans_clear_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id));
|
||||
}
|
||||
|
||||
static inline void iwl_scd_disable_agg(struct iwl_trans *trans)
|
||||
{
|
||||
iwl_set_bits_prph(trans, SCD_AGGR_SEL, 0);
|
||||
iwl_trans_set_bits_prph(trans, SCD_AGGR_SEL, 0);
|
||||
}
|
||||
|
||||
static inline void iwl_scd_activate_fifos(struct iwl_trans *trans)
|
||||
{
|
||||
iwl_write_prph(trans, SCD_TXFACT, IWL_MASK(0, 7));
|
||||
iwl_trans_write_prph(trans, SCD_TXFACT, IWL_MASK(0, 7));
|
||||
}
|
||||
|
||||
static inline void iwl_scd_deactivate_fifos(struct iwl_trans *trans)
|
||||
{
|
||||
iwl_write_prph(trans, SCD_TXFACT, 0);
|
||||
iwl_trans_write_prph(trans, SCD_TXFACT, 0);
|
||||
}
|
||||
|
||||
static inline void iwl_scd_enable_set_active(struct iwl_trans *trans,
|
||||
u32 value)
|
||||
{
|
||||
iwl_write_prph(trans, SCD_EN_CTRL, value);
|
||||
iwl_trans_write_prph(trans, SCD_EN_CTRL, value);
|
||||
}
|
||||
|
||||
static inline unsigned int SCD_QUEUE_WRPTR(unsigned int chnl)
|
||||
|
|
@ -76,9 +76,9 @@ static inline unsigned int SCD_QUEUE_STATUS_BITS(unsigned int chnl)
|
|||
static inline void iwl_scd_txq_set_inactive(struct iwl_trans *trans,
|
||||
u16 txq_id)
|
||||
{
|
||||
iwl_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id),
|
||||
(0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)|
|
||||
(1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
|
||||
iwl_trans_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id),
|
||||
(0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)|
|
||||
(1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@
|
|||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/bsearch.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-prph.h"
|
||||
#include <linux/dmapool.h>
|
||||
#include "fw/api/commands.h"
|
||||
#include "pcie/gen1_2/internal.h"
|
||||
#include "pcie/iwl-context-info-v2.h"
|
||||
|
||||
struct iwl_trans_dev_restart_data {
|
||||
struct list_head list;
|
||||
|
|
@ -259,13 +259,14 @@ static void iwl_trans_restart_wk(struct work_struct *wk)
|
|||
iwl_trans_schedule_reprobe(trans, 0);
|
||||
break;
|
||||
default:
|
||||
iwl_trans_pcie_reset(trans, mode);
|
||||
iwl_trans_reset(trans, mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
|
||||
struct device *dev,
|
||||
const struct iwl_trans_ops *ops,
|
||||
const struct iwl_mac_cfg *mac_cfg)
|
||||
{
|
||||
struct iwl_trans *trans;
|
||||
|
|
@ -277,6 +278,7 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
|
|||
if (!trans)
|
||||
return NULL;
|
||||
|
||||
trans->ops = ops;
|
||||
trans->mac_cfg = mac_cfg;
|
||||
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
|
|
@ -300,6 +302,9 @@ int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (WARN_ON_ONCE(!trans->ops->send_cmd))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (unlikely(!(cmd->flags & CMD_SEND_IN_RFKILL) &&
|
||||
test_bit(STATUS_RFKILL_OPMODE, &trans->status)))
|
||||
return -ERFKILL;
|
||||
|
|
@ -319,7 +324,7 @@ int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
|||
cmd->id = DEF_ID(cmd->id);
|
||||
}
|
||||
|
||||
ret = iwl_trans_pcie_send_hcmd(trans, cmd);
|
||||
ret = trans->ops->send_cmd(trans, cmd);
|
||||
|
||||
if (!(cmd->flags & CMD_ASYNC))
|
||||
lock_map_release(&trans->sync_cmd_lockdep_map);
|
||||
|
|
@ -333,14 +338,18 @@ IWL_EXPORT_SYMBOL(iwl_trans_send_cmd);
|
|||
|
||||
struct iwl_device_tx_cmd *iwl_trans_alloc_tx_cmd(struct iwl_trans *trans)
|
||||
{
|
||||
return iwl_pcie_gen1_2_alloc_tx_cmd(trans);
|
||||
if (WARN_ON_ONCE(!trans->ops->alloc_tx_cmd))
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
return trans->ops->alloc_tx_cmd(trans);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_alloc_tx_cmd);
|
||||
|
||||
void iwl_trans_free_tx_cmd(struct iwl_trans *trans,
|
||||
struct iwl_device_tx_cmd *dev_cmd)
|
||||
{
|
||||
iwl_pcie_gen1_2_free_tx_cmd(trans, dev_cmd);
|
||||
if (WARN_ON_ONCE(!trans->ops->free_tx_cmd))
|
||||
return;
|
||||
trans->ops->free_tx_cmd(trans, dev_cmd);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_free_tx_cmd);
|
||||
|
||||
|
|
@ -395,7 +404,9 @@ void iwl_trans_op_mode_enter(struct iwl_trans *trans,
|
|||
|
||||
WARN_ON_ONCE(!trans->conf.rx_mpdu_cmd);
|
||||
|
||||
iwl_pcie_gen1_2_op_mode_enter(trans);
|
||||
if (WARN_ON_ONCE(!trans->ops->op_mode_enter))
|
||||
return;
|
||||
trans->ops->op_mode_enter(trans);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_op_mode_enter);
|
||||
|
||||
|
|
@ -405,7 +416,9 @@ int iwl_trans_start_hw(struct iwl_trans *trans)
|
|||
|
||||
clear_bit(STATUS_TRANS_RESET_IN_PROGRESS, &trans->status);
|
||||
|
||||
return iwl_trans_pcie_start_hw(trans);
|
||||
if (WARN_ON_ONCE(!trans->ops->start_hw))
|
||||
return -EOPNOTSUPP;
|
||||
return trans->ops->start_hw(trans);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_start_hw);
|
||||
|
||||
|
|
@ -413,10 +426,8 @@ void iwl_trans_op_mode_leave(struct iwl_trans *trans)
|
|||
{
|
||||
might_sleep();
|
||||
|
||||
if (trans->mac_cfg->gen2)
|
||||
iwl_trans_pcie_gen2_op_mode_leave(trans);
|
||||
else
|
||||
iwl_trans_pcie_op_mode_leave(trans);
|
||||
if (!WARN_ON_ONCE(!trans->ops->op_mode_leave))
|
||||
trans->ops->op_mode_leave(trans);
|
||||
|
||||
cancel_delayed_work_sync(&trans->restart.wk);
|
||||
|
||||
|
|
@ -427,42 +438,147 @@ void iwl_trans_op_mode_leave(struct iwl_trans *trans)
|
|||
}
|
||||
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);
|
||||
}
|
||||
|
||||
void iwl_trans_write32(struct iwl_trans *trans, u32 ofs, u32 val)
|
||||
{
|
||||
iwl_trans_pcie_write32(trans, ofs, val);
|
||||
if (WARN_ON_ONCE(!trans->ops->write32))
|
||||
return;
|
||||
trans->ops->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);
|
||||
if (WARN_ON_ONCE(!trans->ops->read32))
|
||||
return 0;
|
||||
return trans->ops->read32(trans, ofs);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_read32);
|
||||
|
||||
u32 iwl_trans_read_prph_no_grab(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
if (WARN_ON_ONCE(!trans->ops->read_prph))
|
||||
return 0;
|
||||
return trans->ops->read_prph(trans, ofs);
|
||||
}
|
||||
|
||||
void iwl_trans_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val)
|
||||
{
|
||||
if (WARN_ON_ONCE(!trans->ops->write_prph))
|
||||
return;
|
||||
trans->ops->write_prph(trans, ofs, val);
|
||||
}
|
||||
|
||||
int iwl_trans_poll_bits_mask(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout)
|
||||
{
|
||||
if (WARN_ON_ONCE(!trans->ops->poll_bits_mask))
|
||||
return -EOPNOTSUPP;
|
||||
return trans->ops->poll_bits_mask(trans, addr, bits, mask, timeout);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_poll_bits_mask);
|
||||
|
||||
void iwl_trans_write_direct32(struct iwl_trans *trans, u32 reg, u32 value)
|
||||
{
|
||||
if (iwl_trans_grab_nic_access(trans)) {
|
||||
iwl_trans_write32(trans, reg, value);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
}
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_write_direct32);
|
||||
|
||||
u32 iwl_trans_read_prph(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
return iwl_trans_pcie_read_prph(trans, ofs);
|
||||
}
|
||||
if (iwl_trans_grab_nic_access(trans)) {
|
||||
u32 val = iwl_trans_read_prph_no_grab(trans, ofs);
|
||||
|
||||
void iwl_trans_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
|
||||
{
|
||||
return iwl_trans_pcie_write_prph(trans, ofs, val);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/* return as if we have a HW timeout/failure */
|
||||
return 0x5a5a5a5a;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_read_prph);
|
||||
|
||||
void iwl_trans_write_prph_delay(struct iwl_trans *trans, u32 ofs, u32 val,
|
||||
u32 delay_ms)
|
||||
{
|
||||
if (iwl_trans_grab_nic_access(trans)) {
|
||||
mdelay(delay_ms);
|
||||
iwl_trans_write_prph_no_grab(trans, ofs, val);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
}
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_write_prph_delay);
|
||||
|
||||
void iwl_trans_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
|
||||
{
|
||||
if (iwl_trans_grab_nic_access(trans)) {
|
||||
iwl_trans_write_prph_no_grab(trans, ofs,
|
||||
iwl_trans_read_prph_no_grab(trans, ofs) |
|
||||
mask);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
}
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_set_bits_prph);
|
||||
|
||||
void iwl_trans_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
|
||||
u32 bits, u32 mask)
|
||||
{
|
||||
if (iwl_trans_grab_nic_access(trans)) {
|
||||
iwl_trans_write_prph_no_grab(trans, ofs,
|
||||
(iwl_trans_read_prph_no_grab(trans, ofs) &
|
||||
mask) | bits);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
}
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_set_bits_mask_prph);
|
||||
|
||||
void iwl_trans_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (iwl_trans_grab_nic_access(trans)) {
|
||||
val = iwl_trans_read_prph_no_grab(trans, ofs);
|
||||
iwl_trans_write_prph_no_grab(trans, ofs, (val & ~mask));
|
||||
iwl_trans_release_nic_access(trans);
|
||||
}
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_clear_bits_prph);
|
||||
|
||||
void iwl_trans_force_nmi(struct iwl_trans *trans)
|
||||
{
|
||||
if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_9000)
|
||||
iwl_trans_write_prph_delay(trans, DEVICE_SET_NMI_REG,
|
||||
DEVICE_SET_NMI_VAL_DRV, 1);
|
||||
else if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
|
||||
iwl_trans_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER,
|
||||
UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER);
|
||||
else if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
|
||||
iwl_trans_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
|
||||
UREG_DOORBELL_TO_ISR6_NMI_BIT);
|
||||
else
|
||||
iwl_trans_write32(trans, CSR_DOORBELL_VECTOR,
|
||||
UREG_DOORBELL_TO_ISR6_NMI_BIT);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_force_nmi);
|
||||
|
||||
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);
|
||||
if (WARN_ON_ONCE(!trans->ops->read_mem))
|
||||
return -EOPNOTSUPP;
|
||||
return trans->ops->read_mem(trans, addr, buf, dwords);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_read_mem);
|
||||
|
||||
int iwl_trans_read_mem_no_grab(struct iwl_trans *trans, u32 addr,
|
||||
void *buf, u32 dwords)
|
||||
{
|
||||
return iwl_trans_pcie_read_mem_no_grab(trans, addr, buf, dwords);
|
||||
if (WARN_ON_ONCE(!trans->ops->read_mem_no_grab))
|
||||
return -EOPNOTSUPP;
|
||||
return trans->ops->read_mem_no_grab(trans, addr, buf, dwords);
|
||||
}
|
||||
|
||||
int iwl_trans_write_mem(struct iwl_trans *trans, u32 addr,
|
||||
|
|
@ -472,10 +588,10 @@ int iwl_trans_write_mem(struct iwl_trans *trans, u32 addr,
|
|||
const u32 *vals = buf;
|
||||
|
||||
if (iwl_trans_grab_nic_access(trans)) {
|
||||
iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr);
|
||||
iwl_trans_write32(trans, HBUS_TARG_MEM_WADDR, addr);
|
||||
for (offs = 0; offs < dwords; offs++)
|
||||
iwl_write32(trans, HBUS_TARG_MEM_WDAT,
|
||||
vals ? vals[offs] : 0);
|
||||
iwl_trans_write32(trans, HBUS_TARG_MEM_WDAT,
|
||||
vals ? vals[offs] : 0);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
} else {
|
||||
ret = -EBUSY;
|
||||
|
|
@ -495,7 +611,9 @@ IWL_EXPORT_SYMBOL(iwl_trans_set_pmi);
|
|||
|
||||
int iwl_trans_sw_reset(struct iwl_trans *trans)
|
||||
{
|
||||
return iwl_trans_pcie_sw_reset(trans, true);
|
||||
if (WARN_ON_ONCE(!trans->ops->sw_reset))
|
||||
return -EOPNOTSUPP;
|
||||
return trans->ops->sw_reset(trans, true);
|
||||
}
|
||||
|
||||
struct iwl_trans_dump_data *
|
||||
|
|
@ -503,15 +621,19 @@ 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);
|
||||
if (WARN_ON_ONCE(!trans->ops->dump_data))
|
||||
return NULL;
|
||||
return trans->ops->dump_data(trans, dump_mask,
|
||||
sanitize_ops, sanitize_ctx);
|
||||
}
|
||||
|
||||
int iwl_trans_d3_suspend(struct iwl_trans *trans, bool reset)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
return iwl_trans_pcie_d3_suspend(trans, reset);
|
||||
if (WARN_ON_ONCE(!trans->ops->d3_suspend))
|
||||
return -EOPNOTSUPP;
|
||||
return trans->ops->d3_suspend(trans, reset);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_d3_suspend);
|
||||
|
||||
|
|
@ -519,54 +641,64 @@ int iwl_trans_d3_resume(struct iwl_trans *trans, bool reset)
|
|||
{
|
||||
might_sleep();
|
||||
|
||||
return iwl_trans_pcie_d3_resume(trans, reset);
|
||||
if (WARN_ON_ONCE(!trans->ops->d3_resume))
|
||||
return -EOPNOTSUPP;
|
||||
return trans->ops->d3_resume(trans, reset);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_d3_resume);
|
||||
|
||||
void iwl_trans_interrupts(struct iwl_trans *trans, bool enable)
|
||||
{
|
||||
iwl_trans_pci_interrupts(trans, enable);
|
||||
}
|
||||
|
||||
void iwl_trans_sync_nmi(struct iwl_trans *trans)
|
||||
{
|
||||
iwl_trans_pcie_sync_nmi(trans);
|
||||
if (WARN_ON_ONCE(!trans->ops->sync_nmi))
|
||||
return;
|
||||
trans->ops->sync_nmi(trans);
|
||||
}
|
||||
|
||||
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);
|
||||
if (WARN_ON_ONCE(!trans->ops->write_imr_mem))
|
||||
return -EOPNOTSUPP;
|
||||
return trans->ops->write_imr_mem(trans, dst_addr, src_addr, byte_cnt);
|
||||
}
|
||||
|
||||
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);
|
||||
if (WARN_ON_ONCE(!trans->ops->set_bits_mask))
|
||||
return;
|
||||
trans->ops->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);
|
||||
if (WARN_ON_ONCE(!trans->ops->read_config32))
|
||||
return -EOPNOTSUPP;
|
||||
return trans->ops->read_config32(trans, ofs, val);
|
||||
}
|
||||
|
||||
bool iwl_trans_grab_nic_access(struct iwl_trans *trans)
|
||||
{
|
||||
return iwl_trans_pcie_grab_nic_access(trans);
|
||||
if (WARN_ON_ONCE(!trans->ops->grab_nic_access))
|
||||
return false;
|
||||
return trans->ops->grab_nic_access(trans);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_grab_nic_access);
|
||||
|
||||
void iwl_trans_resched_with_nic_access(struct iwl_trans *trans)
|
||||
{
|
||||
iwl_trans_pcie_resched_with_nic_access(trans);
|
||||
if (WARN_ON_ONCE(!trans->ops->resched_with_nic_access))
|
||||
return;
|
||||
trans->ops->resched_with_nic_access(trans);
|
||||
}
|
||||
|
||||
void __releases(nic_access)
|
||||
iwl_trans_release_nic_access(struct iwl_trans *trans)
|
||||
void iwl_trans_release_nic_access(struct iwl_trans *trans)
|
||||
{
|
||||
iwl_trans_pcie_release_nic_access(trans);
|
||||
if (WARN_ON_ONCE(!trans->ops->release_nic_access))
|
||||
return;
|
||||
trans->ops->release_nic_access(trans);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_release_nic_access);
|
||||
|
||||
|
|
@ -576,10 +708,8 @@ void iwl_trans_fw_alive(struct iwl_trans *trans)
|
|||
|
||||
trans->state = IWL_TRANS_FW_ALIVE;
|
||||
|
||||
if (trans->mac_cfg->gen2)
|
||||
iwl_trans_pcie_gen2_fw_alive(trans);
|
||||
else
|
||||
iwl_trans_pcie_fw_alive(trans);
|
||||
if (!WARN_ON_ONCE(!trans->ops->fw_alive))
|
||||
trans->ops->fw_alive(trans);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_fw_alive);
|
||||
|
||||
|
|
@ -597,12 +727,10 @@ int iwl_trans_start_fw(struct iwl_trans *trans, const struct iwl_fw *fw,
|
|||
|
||||
clear_bit(STATUS_FW_ERROR, &trans->status);
|
||||
|
||||
if (trans->mac_cfg->gen2)
|
||||
ret = iwl_trans_pcie_gen2_start_fw(trans, fw, img,
|
||||
run_in_rfkill);
|
||||
else
|
||||
ret = iwl_trans_pcie_start_fw(trans, fw, img,
|
||||
run_in_rfkill);
|
||||
if (WARN_ON_ONCE(!trans->ops->start_fw))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ret = trans->ops->start_fw(trans, fw, img, run_in_rfkill);
|
||||
|
||||
if (ret == 0)
|
||||
trans->state = IWL_TRANS_FW_STARTED;
|
||||
|
|
@ -643,10 +771,8 @@ void iwl_trans_stop_device(struct iwl_trans *trans)
|
|||
iwl_op_mode_dump_error(trans->op_mode, &mode);
|
||||
}
|
||||
|
||||
if (trans->mac_cfg->gen2)
|
||||
iwl_trans_pcie_gen2_stop_device(trans);
|
||||
else
|
||||
iwl_trans_pcie_stop_device(trans);
|
||||
if (!WARN_ON_ONCE(!trans->ops->stop_device))
|
||||
trans->ops->stop_device(trans);
|
||||
|
||||
trans->state = IWL_TRANS_NO_FW;
|
||||
}
|
||||
|
|
@ -662,10 +788,10 @@ int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
|||
"bad state = %d\n", trans->state))
|
||||
return -EIO;
|
||||
|
||||
if (trans->mac_cfg->gen2)
|
||||
return iwl_txq_gen2_tx(trans, skb, dev_cmd, queue);
|
||||
if (WARN_ON_ONCE(!trans->ops->tx))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return iwl_trans_pcie_tx(trans, skb, dev_cmd, queue);
|
||||
return trans->ops->tx(trans, skb, dev_cmd, queue);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_tx);
|
||||
|
||||
|
|
@ -679,14 +805,18 @@ void iwl_trans_reclaim(struct iwl_trans *trans, int queue, int ssn,
|
|||
"bad state = %d\n", trans->state))
|
||||
return;
|
||||
|
||||
iwl_pcie_reclaim(trans, queue, ssn, skbs, is_flush);
|
||||
if (WARN_ON_ONCE(!trans->ops->reclaim))
|
||||
return;
|
||||
trans->ops->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);
|
||||
if (WARN_ON_ONCE(!trans->ops->txq_disable))
|
||||
return;
|
||||
trans->ops->txq_disable(trans, queue, configure_scd);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_txq_disable);
|
||||
|
||||
|
|
@ -700,8 +830,10 @@ bool iwl_trans_txq_enable_cfg(struct iwl_trans *trans, int queue, u16 ssn,
|
|||
"bad state = %d\n", trans->state))
|
||||
return false;
|
||||
|
||||
return iwl_trans_pcie_txq_enable(trans, queue, ssn,
|
||||
cfg, queue_wdg_timeout);
|
||||
if (WARN_ON_ONCE(!trans->ops->txq_enable))
|
||||
return false;
|
||||
return trans->ops->txq_enable(trans, queue, ssn,
|
||||
cfg, queue_wdg_timeout);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_txq_enable_cfg);
|
||||
|
||||
|
|
@ -714,7 +846,9 @@ int iwl_trans_wait_txq_empty(struct iwl_trans *trans, int queue)
|
|||
"bad state = %d\n", trans->state))
|
||||
return -EIO;
|
||||
|
||||
return iwl_trans_pcie_wait_txq_empty(trans, queue);
|
||||
if (WARN_ON_ONCE(!trans->ops->wait_txq_empty))
|
||||
return -EOPNOTSUPP;
|
||||
return trans->ops->wait_txq_empty(trans, queue);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_wait_txq_empty);
|
||||
|
||||
|
|
@ -724,7 +858,9 @@ int iwl_trans_wait_tx_queues_empty(struct iwl_trans *trans, u32 txqs)
|
|||
"bad state = %d\n", trans->state))
|
||||
return -EIO;
|
||||
|
||||
return iwl_trans_pcie_wait_txqs_empty(trans, txqs);
|
||||
if (WARN_ON_ONCE(!trans->ops->wait_txqs_empty))
|
||||
return -EOPNOTSUPP;
|
||||
return trans->ops->wait_txqs_empty(trans, txqs);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_wait_tx_queues_empty);
|
||||
|
||||
|
|
@ -735,31 +871,30 @@ void iwl_trans_freeze_txq_timer(struct iwl_trans *trans,
|
|||
"bad state = %d\n", trans->state))
|
||||
return;
|
||||
|
||||
iwl_pcie_freeze_txq_timer(trans, txqs, freeze);
|
||||
if (WARN_ON_ONCE(!trans->ops->freeze_txq_timer))
|
||||
return;
|
||||
trans->ops->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);
|
||||
if (WARN_ON_ONCE(!trans->ops->txq_set_shared_mode))
|
||||
return;
|
||||
trans->ops->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);
|
||||
}
|
||||
#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);
|
||||
if (WARN_ON_ONCE(!trans->ops->set_q_ptrs))
|
||||
return;
|
||||
trans->ops->set_q_ptrs(trans, queue, ptr);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_set_q_ptrs);
|
||||
|
||||
|
|
@ -772,49 +907,62 @@ int iwl_trans_txq_alloc(struct iwl_trans *trans, u32 flags, u32 sta_mask,
|
|||
"bad state = %d\n", trans->state))
|
||||
return -EIO;
|
||||
|
||||
return iwl_txq_dyn_alloc(trans, flags, sta_mask, tid,
|
||||
size, wdg_timeout);
|
||||
if (WARN_ON_ONCE(!trans->ops->txq_alloc))
|
||||
return -EOPNOTSUPP;
|
||||
return trans->ops->txq_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);
|
||||
if (WARN_ON_ONCE(!trans->ops->txq_free))
|
||||
return;
|
||||
trans->ops->txq_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);
|
||||
if (WARN_ON_ONCE(!trans->ops->rxq_dma_data))
|
||||
return -EOPNOTSUPP;
|
||||
return trans->ops->rxq_dma_data(trans, queue, 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_v2_load_pnvm(trans, pnvm_data, capa);
|
||||
if (WARN_ON_ONCE(!trans->ops->load_pnvm))
|
||||
return -EOPNOTSUPP;
|
||||
return trans->ops->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_v2_set_pnvm(trans, capa);
|
||||
if (WARN_ON_ONCE(!trans->ops->set_pnvm))
|
||||
return;
|
||||
trans->ops->set_pnvm(trans, capa);
|
||||
}
|
||||
|
||||
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_v2_load_reduce_power(trans, payloads,
|
||||
capa);
|
||||
if (WARN_ON_ONCE(!trans->ops->load_reduce_power))
|
||||
return -EOPNOTSUPP;
|
||||
return trans->ops->load_reduce_power(trans, payloads, capa);
|
||||
}
|
||||
|
||||
void iwl_trans_set_reduce_power(struct iwl_trans *trans,
|
||||
const struct iwl_ucode_capabilities *capa)
|
||||
{
|
||||
iwl_trans_pcie_ctx_info_v2_set_reduce_power(trans, capa);
|
||||
if (WARN_ON_ONCE(!trans->ops->set_reduce_power))
|
||||
return;
|
||||
trans->ops->set_reduce_power(trans, capa);
|
||||
}
|
||||
|
||||
bool iwl_trans_is_pm_supported(struct iwl_trans *trans)
|
||||
|
|
@ -822,19 +970,39 @@ bool iwl_trans_is_pm_supported(struct iwl_trans *trans)
|
|||
if (WARN_ON(trans->mac_cfg->gen2))
|
||||
return false;
|
||||
|
||||
return iwl_pcie_gen1_is_pm_supported(trans);
|
||||
if (WARN_ON_ONCE(!trans->ops->is_pm_supported))
|
||||
return false;
|
||||
return trans->ops->is_pm_supported(trans);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_is_pm_supported);
|
||||
|
||||
bool iwl_trans_is_ltr_enabled(struct iwl_trans *trans)
|
||||
{
|
||||
return iwl_pcie_gen1_2_is_ltr_enabled(trans);
|
||||
if (WARN_ON_ONCE(!trans->ops->is_ltr_enabled))
|
||||
return false;
|
||||
return trans->ops->is_ltr_enabled(trans);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_is_ltr_enabled);
|
||||
|
||||
int iwl_trans_activate_nic(struct iwl_trans *trans)
|
||||
{
|
||||
return iwl_pcie_gen1_2_activate_nic(trans);
|
||||
if (WARN_ON_ONCE(!trans->ops->activate_nic))
|
||||
return -EOPNOTSUPP;
|
||||
return trans->ops->activate_nic(trans);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_activate_nic);
|
||||
|
||||
|
||||
void iwl_trans_reset(struct iwl_trans *trans, enum iwl_reset_mode mode)
|
||||
{
|
||||
if (!WARN_ON_ONCE(!trans->ops->reset))
|
||||
trans->ops->reset(trans, mode);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_trans_reset);
|
||||
|
||||
void iwl_trans_fw_reset_handshake(struct iwl_trans *trans)
|
||||
{
|
||||
if (!WARN_ON_ONCE(!trans->ops->fw_reset_handshake))
|
||||
trans->ops->fw_reset_handshake(trans);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -734,12 +734,15 @@ struct iwl_trans_info {
|
|||
u8 num_rxqs;
|
||||
};
|
||||
|
||||
struct iwl_trans_ops;
|
||||
|
||||
/**
|
||||
* struct iwl_trans - transport common data
|
||||
*
|
||||
* @csme_own: true if we couldn't get ownership on the device
|
||||
* @op_mode: pointer to the op_mode
|
||||
* @mac_cfg: the trans-specific configuration part
|
||||
* @ops: bus-specific transport operations, see &struct iwl_trans_ops
|
||||
* @cfg: pointer to the configuration
|
||||
* @drv: pointer to iwl_drv
|
||||
* @conf: configuration set by the opmode before enter
|
||||
|
|
@ -773,6 +776,7 @@ struct iwl_trans {
|
|||
bool csme_own;
|
||||
struct iwl_op_mode *op_mode;
|
||||
const struct iwl_mac_cfg *mac_cfg;
|
||||
const struct iwl_trans_ops *ops;
|
||||
const struct iwl_rf_cfg *cfg;
|
||||
struct iwl_drv *drv;
|
||||
struct iwl_trans_config conf;
|
||||
|
|
@ -910,15 +914,13 @@ int iwl_trans_wait_tx_queues_empty(struct iwl_trans *trans, u32 txqs);
|
|||
|
||||
int iwl_trans_wait_txq_empty(struct iwl_trans *trans, int queue);
|
||||
|
||||
void iwl_trans_write8(struct iwl_trans *trans, u32 ofs, u8 val);
|
||||
|
||||
void iwl_trans_write32(struct iwl_trans *trans, u32 ofs, u32 val);
|
||||
|
||||
u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs);
|
||||
|
||||
u32 iwl_trans_read_prph(struct iwl_trans *trans, u32 ofs);
|
||||
u32 iwl_trans_read_prph_no_grab(struct iwl_trans *trans, u32 ofs);
|
||||
|
||||
void iwl_trans_write_prph(struct iwl_trans *trans, u32 ofs, u32 val);
|
||||
void iwl_trans_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val);
|
||||
|
||||
int iwl_trans_read_mem(struct iwl_trans *trans, u32 addr,
|
||||
void *buf, int dwords);
|
||||
|
|
@ -934,10 +936,6 @@ int iwl_trans_read_mem_no_grab(struct iwl_trans *trans, u32 addr,
|
|||
int iwl_trans_read_config32(struct iwl_trans *trans, u32 ofs,
|
||||
u32 *val);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
void iwl_trans_debugfs_cleanup(struct iwl_trans *trans);
|
||||
#endif
|
||||
|
||||
#define iwl_trans_read_mem_bytes(trans, addr, buf, bufsize) \
|
||||
({ \
|
||||
if (__builtin_constant_p(bufsize)) \
|
||||
|
|
@ -983,6 +981,66 @@ int iwl_trans_sw_reset(struct iwl_trans *trans);
|
|||
void iwl_trans_set_bits_mask(struct iwl_trans *trans, u32 reg,
|
||||
u32 mask, u32 value);
|
||||
|
||||
static inline void iwl_trans_set_bit(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
{
|
||||
iwl_trans_set_bits_mask(trans, reg, mask, mask);
|
||||
}
|
||||
|
||||
static inline void iwl_trans_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
{
|
||||
iwl_trans_set_bits_mask(trans, reg, mask, 0);
|
||||
}
|
||||
|
||||
int iwl_trans_poll_bits_mask(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout);
|
||||
static inline int iwl_trans_poll_bits(struct iwl_trans *trans, u32 addr, u32 bits,
|
||||
int timeout)
|
||||
{
|
||||
return iwl_trans_poll_bits_mask(trans, addr, bits, bits, timeout);
|
||||
}
|
||||
|
||||
void iwl_trans_write_direct32(struct iwl_trans *trans, u32 reg, u32 value);
|
||||
|
||||
u32 iwl_trans_read_prph(struct iwl_trans *trans, u32 ofs);
|
||||
void iwl_trans_write_prph_delay(struct iwl_trans *trans, u32 ofs,
|
||||
u32 val, u32 delay_ms);
|
||||
static inline void iwl_trans_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
|
||||
{
|
||||
iwl_trans_write_prph_delay(trans, ofs, val, 0);
|
||||
}
|
||||
|
||||
void iwl_trans_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);
|
||||
void iwl_trans_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
|
||||
u32 bits, u32 mask);
|
||||
void iwl_trans_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);
|
||||
|
||||
/*
|
||||
* UMAC periphery address space changed from 0xA00000 to 0xD00000 starting from
|
||||
* device family AX200. So peripheries used in families above and below AX200
|
||||
* should go through iwl_trans_..._umac_..._prph.
|
||||
*/
|
||||
static inline u32 iwl_trans_umac_prph(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
return ofs + trans->mac_cfg->umac_prph_offset;
|
||||
}
|
||||
|
||||
static inline u32 iwl_trans_read_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
return iwl_trans_read_prph_no_grab(trans, ofs +
|
||||
trans->mac_cfg->umac_prph_offset);
|
||||
}
|
||||
|
||||
static inline u32 iwl_trans_read_umac_prph(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
return iwl_trans_read_prph(trans, ofs + trans->mac_cfg->umac_prph_offset);
|
||||
}
|
||||
|
||||
static inline void iwl_trans_write_umac_prph(struct iwl_trans *trans, u32 ofs,
|
||||
u32 val)
|
||||
{
|
||||
iwl_trans_write_prph(trans, ofs + trans->mac_cfg->umac_prph_offset, val);
|
||||
}
|
||||
|
||||
bool iwl_trans_grab_nic_access(struct iwl_trans *trans);
|
||||
|
||||
/**
|
||||
|
|
@ -996,8 +1054,7 @@ bool iwl_trans_grab_nic_access(struct iwl_trans *trans);
|
|||
*/
|
||||
void iwl_trans_resched_with_nic_access(struct iwl_trans *trans);
|
||||
|
||||
void __releases(nic_access)
|
||||
iwl_trans_release_nic_access(struct iwl_trans *trans);
|
||||
void iwl_trans_release_nic_access(struct iwl_trans *trans);
|
||||
|
||||
static inline void iwl_trans_schedule_reset(struct iwl_trans *trans,
|
||||
enum iwl_fw_error_type type)
|
||||
|
|
@ -1059,8 +1116,7 @@ static inline bool iwl_trans_fw_running(struct iwl_trans *trans)
|
|||
|
||||
void iwl_trans_sync_nmi(struct iwl_trans *trans);
|
||||
|
||||
void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr,
|
||||
u32 sw_err_bit);
|
||||
void iwl_trans_force_nmi(struct iwl_trans *trans);
|
||||
|
||||
int iwl_trans_load_pnvm(struct iwl_trans *trans,
|
||||
const struct iwl_pnvm_image *pnvm_data,
|
||||
|
|
@ -1082,8 +1138,6 @@ static inline bool iwl_trans_dbg_ini_valid(struct iwl_trans *trans)
|
|||
trans->dbg.external_ini_cfg != IWL_INI_CFG_STATE_NOT_LOADED;
|
||||
}
|
||||
|
||||
void iwl_trans_interrupts(struct iwl_trans *trans, bool enable);
|
||||
|
||||
int iwl_trans_activate_nic(struct iwl_trans *trans);
|
||||
|
||||
static inline void iwl_trans_finish_sw_reset(struct iwl_trans *trans)
|
||||
|
|
@ -1096,6 +1150,7 @@ static inline void iwl_trans_finish_sw_reset(struct iwl_trans *trans)
|
|||
*****************************************************/
|
||||
struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
|
||||
struct device *dev,
|
||||
const struct iwl_trans_ops *ops,
|
||||
const struct iwl_mac_cfg *mac_cfg);
|
||||
void iwl_trans_free(struct iwl_trans *trans);
|
||||
|
||||
|
|
@ -1166,8 +1221,149 @@ enum iwl_reset_mode {
|
|||
IWL_RESET_MODE_BACKOFF,
|
||||
};
|
||||
|
||||
void iwl_trans_pcie_reset(struct iwl_trans *trans, enum iwl_reset_mode mode);
|
||||
void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans);
|
||||
void iwl_trans_reset(struct iwl_trans *trans, enum iwl_reset_mode mode);
|
||||
void iwl_trans_fw_reset_handshake(struct iwl_trans *trans);
|
||||
|
||||
/**
|
||||
* struct iwl_trans_ops - bus-specific transport operations
|
||||
*
|
||||
* Function-pointer table filled in by the bus implementation. Unless noted
|
||||
* otherwise, each callback implements the identically named iwl_trans_*()
|
||||
* API, see its documentation.
|
||||
*
|
||||
* @op_mode_enter: the op_mode took ownership of the transport
|
||||
* @start_hw: start the hardware
|
||||
* @op_mode_leave: the op_mode released the transport
|
||||
* @send_cmd: send a host command to the firmware
|
||||
* @alloc_tx_cmd: allocate a device TX command
|
||||
* @free_tx_cmd: free a device TX command
|
||||
* @write32: write a dword to a device register
|
||||
* @read32: read a dword from a device register
|
||||
* @read_prph: read a peripheral register
|
||||
* @write_prph: write a peripheral register
|
||||
* @read_mem: read device memory, taking NIC access
|
||||
* @read_mem_no_grab: read device memory, NIC access already taken
|
||||
* @set_bits_mask: read-modify-write a device register
|
||||
* @poll_bits_mask: poll a device register until the masked bits match
|
||||
* @read_config32: read a dword from the bus configuration space
|
||||
* @grab_nic_access: keep the NIC awake for register access
|
||||
* @release_nic_access: release the NIC access taken by @grab_nic_access
|
||||
* @resched_with_nic_access: reschedule while holding NIC access
|
||||
* @sw_reset: perform a software reset of the device
|
||||
* @reset: reset the device, see &enum iwl_reset_mode
|
||||
* @fw_reset_handshake: do a firmware reset handshake.
|
||||
* @dump_data: collect a firmware error dump
|
||||
* @d3_suspend: prepare the device for D3 (WoWLAN)
|
||||
* @d3_resume: resume the device from D3 (WoWLAN)
|
||||
* @sync_nmi: trigger an NMI and wait for it to be handled
|
||||
* @write_imr_mem: write to the IMR memory region
|
||||
* @fw_alive: Notify trans that the firmware sent the ALIVE notification
|
||||
* @start_fw: download firmware code to the device and and start the firmware
|
||||
* @stop_device: stop the device and the firmware
|
||||
* @tx: transmit an MPDU
|
||||
* @reclaim: free TX MPDUs up to the given sequence number
|
||||
* @txq_disable: disable a TX queue (gen1)
|
||||
* @txq_enable: enable a TX queue (gen1)
|
||||
* @wait_txq_empty: wait for a single TX queue to become empty
|
||||
* @wait_txqs_empty: wait for the given TX queues to become empty
|
||||
* @freeze_txq_timer: freeze/unfreeze the watchdog of the given TX queues
|
||||
* @txq_set_shared_mode: mark a TX queue as shared between TIDs
|
||||
* @set_q_ptrs: set the write pointer of a TX queue
|
||||
* @txq_alloc: allocate a TX queue (gen2)
|
||||
* @txq_free: free a TX queue allocated by @txq_alloc
|
||||
* @rxq_dma_data: get the DMA addresses of an RX queue
|
||||
* @load_pnvm: load the PNVM image
|
||||
* @set_pnvm: tell the firmware to use the loaded PNVM
|
||||
* @load_reduce_power: load the reduced power table
|
||||
* @set_reduce_power: tell the firmware to use the reduced power table
|
||||
* @is_pm_supported: whether bus power management is supported
|
||||
* @is_ltr_enabled: whether LTR is enabled on the bus
|
||||
* @activate_nic: bring the NIC out of low power and make it accessible
|
||||
*/
|
||||
struct iwl_trans_ops {
|
||||
void (*op_mode_enter)(struct iwl_trans *trans);
|
||||
int (*start_hw)(struct iwl_trans *trans);
|
||||
void (*op_mode_leave)(struct iwl_trans *trans);
|
||||
|
||||
int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
|
||||
struct iwl_device_tx_cmd *(*alloc_tx_cmd)(struct iwl_trans *trans);
|
||||
void (*free_tx_cmd)(struct iwl_trans *trans,
|
||||
struct iwl_device_tx_cmd *dev_cmd);
|
||||
|
||||
void (*write32)(struct iwl_trans *trans, u32 ofs, u32 val);
|
||||
u32 (*read32)(struct iwl_trans *trans, u32 ofs);
|
||||
u32 (*read_prph)(struct iwl_trans *trans, u32 ofs);
|
||||
void (*write_prph)(struct iwl_trans *trans, u32 ofs, u32 val);
|
||||
int (*read_mem)(struct iwl_trans *trans, u32 addr,
|
||||
void *buf, int dwords);
|
||||
int (*read_mem_no_grab)(struct iwl_trans *trans, u32 addr,
|
||||
void *buf, u32 dwords);
|
||||
void (*set_bits_mask)(struct iwl_trans *trans, u32 reg,
|
||||
u32 mask, u32 value);
|
||||
int (*poll_bits_mask)(struct iwl_trans *trans, u32 addr,
|
||||
u32 bits, u32 mask, int timeout);
|
||||
int (*read_config32)(struct iwl_trans *trans, u32 ofs, u32 *val);
|
||||
bool (*grab_nic_access)(struct iwl_trans *trans);
|
||||
void (*release_nic_access)(struct iwl_trans *trans);
|
||||
void (*resched_with_nic_access)(struct iwl_trans *trans);
|
||||
|
||||
int (*sw_reset)(struct iwl_trans *trans, bool retake_ownership);
|
||||
void (*reset)(struct iwl_trans *trans, enum iwl_reset_mode mode);
|
||||
void (*fw_reset_handshake)(struct iwl_trans *trans);
|
||||
|
||||
struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans,
|
||||
u32 dump_mask,
|
||||
const struct iwl_dump_sanitize_ops *sanitize_ops,
|
||||
void *sanitize_ctx);
|
||||
int (*d3_suspend)(struct iwl_trans *trans, bool reset);
|
||||
int (*d3_resume)(struct iwl_trans *trans, bool reset);
|
||||
|
||||
void (*sync_nmi)(struct iwl_trans *trans);
|
||||
int (*write_imr_mem)(struct iwl_trans *trans, u32 dst_addr,
|
||||
u64 src_addr, u32 byte_cnt);
|
||||
|
||||
void (*fw_alive)(struct iwl_trans *trans);
|
||||
int (*start_fw)(struct iwl_trans *trans, const struct iwl_fw *fw,
|
||||
const struct fw_img *img, bool run_in_rfkill);
|
||||
void (*stop_device)(struct iwl_trans *trans);
|
||||
|
||||
int (*tx)(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
struct iwl_device_tx_cmd *dev_cmd, int queue);
|
||||
void (*reclaim)(struct iwl_trans *trans, int queue, int ssn,
|
||||
struct sk_buff_head *skbs, bool is_flush);
|
||||
void (*txq_disable)(struct iwl_trans *trans, int queue,
|
||||
bool configure_scd);
|
||||
bool (*txq_enable)(struct iwl_trans *trans, int queue, u16 ssn,
|
||||
const struct iwl_trans_txq_scd_cfg *cfg,
|
||||
unsigned int queue_wdg_timeout);
|
||||
int (*wait_txq_empty)(struct iwl_trans *trans, int queue);
|
||||
int (*wait_txqs_empty)(struct iwl_trans *trans, u32 txqs);
|
||||
void (*freeze_txq_timer)(struct iwl_trans *trans,
|
||||
unsigned long txqs, bool freeze);
|
||||
void (*txq_set_shared_mode)(struct iwl_trans *trans, u32 txq_id,
|
||||
bool shared_mode);
|
||||
void (*set_q_ptrs)(struct iwl_trans *trans, int queue, int ptr);
|
||||
int (*txq_alloc)(struct iwl_trans *trans, u32 flags, u32 sta_mask,
|
||||
u8 tid, int size, unsigned int wdg_timeout);
|
||||
void (*txq_free)(struct iwl_trans *trans, int queue);
|
||||
int (*rxq_dma_data)(struct iwl_trans *trans, int queue,
|
||||
struct iwl_trans_rxq_dma_data *data);
|
||||
|
||||
int (*load_pnvm)(struct iwl_trans *trans,
|
||||
const struct iwl_pnvm_image *pnvm_data,
|
||||
const struct iwl_ucode_capabilities *capa);
|
||||
void (*set_pnvm)(struct iwl_trans *trans,
|
||||
const struct iwl_ucode_capabilities *capa);
|
||||
int (*load_reduce_power)(struct iwl_trans *trans,
|
||||
const struct iwl_pnvm_image *payloads,
|
||||
const struct iwl_ucode_capabilities *capa);
|
||||
void (*set_reduce_power)(struct iwl_trans *trans,
|
||||
const struct iwl_ucode_capabilities *capa);
|
||||
|
||||
bool (*is_pm_supported)(struct iwl_trans *trans);
|
||||
bool (*is_ltr_enabled)(struct iwl_trans *trans);
|
||||
int (*activate_nic)(struct iwl_trans *trans);
|
||||
};
|
||||
|
||||
/* Internal helper */
|
||||
static inline void iwl_trans_set_info(struct iwl_trans *trans,
|
||||
|
|
|
|||
|
|
@ -660,6 +660,7 @@ int iwl_mld_update_sta_baids(struct iwl_mld *mld,
|
|||
.modify.new_sta_id_mask = cpu_to_le32(new_sta_mask),
|
||||
};
|
||||
u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, RX_BAID_ALLOCATION_CONFIG_CMD);
|
||||
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 2);
|
||||
int baid;
|
||||
|
||||
/* mac80211 will remove sessions later, but we ignore all that */
|
||||
|
|
@ -667,6 +668,7 @@ int iwl_mld_update_sta_baids(struct iwl_mld *mld,
|
|||
return 0;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct iwl_rx_baid_cfg_resp) != sizeof(baid));
|
||||
BUILD_BUG_ON(sizeof(cmd.modify) != sizeof(cmd.modify_v2));
|
||||
|
||||
for (baid = 0; baid < ARRAY_SIZE(mld->fw_id_to_ba); baid++) {
|
||||
struct iwl_mld_baid_data *data;
|
||||
|
|
@ -683,7 +685,10 @@ int iwl_mld_update_sta_baids(struct iwl_mld *mld,
|
|||
"BAID data for %d corrupted - expected 0x%x found 0x%x\n",
|
||||
baid, old_sta_mask, data->sta_mask);
|
||||
|
||||
cmd.modify.tid = cpu_to_le32(data->tid);
|
||||
if (cmd_ver >= 3)
|
||||
cmd.modify.tid = data->tid;
|
||||
else
|
||||
cmd.modify_v2.tid = cpu_to_le32(data->tid);
|
||||
|
||||
ret = iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd);
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -39,6 +39,10 @@
|
|||
|
||||
#define IWL_MLD_TPT_COUNT_WINDOW (5 * HZ)
|
||||
|
||||
#define IWL_MLD_TX_GP2_VALID_PERIOD (10 * HZ)
|
||||
#define IWL_MLD_TX_GP2_REFRESH_MARGIN (5 * HZ)
|
||||
#define IWL_MLD_TX_GP2_RETRY_PERIOD HZ
|
||||
|
||||
#define IWL_MLD_DIS_RANDOM_FW_ID false
|
||||
#define IWL_MLD_D3_DEBUG false
|
||||
#define IWL_MLD_NON_TRANSMITTING_AP false
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "mld.h"
|
||||
|
||||
#include "d3.h"
|
||||
#include "tx.h"
|
||||
#include "power.h"
|
||||
#include "hcmd.h"
|
||||
#include "iface.h"
|
||||
|
|
@ -597,6 +598,37 @@ iwl_mld_convert_wowlan_notif_v5(const struct iwl_wowlan_info_notif_v5 *notif_v5,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mld_convert_wowlan_notif_v6(const struct iwl_wowlan_info_notif_v6 *notif_v6,
|
||||
struct iwl_wowlan_info_notif *notif)
|
||||
{
|
||||
/* v6 is identical to the new format, except that it has no CIGTK */
|
||||
BUILD_BUG_ON(sizeof(notif->gtk) != sizeof(notif_v6->gtk));
|
||||
BUILD_BUG_ON(sizeof(notif->igtk) != sizeof(notif_v6->igtk));
|
||||
BUILD_BUG_ON(sizeof(notif->bigtk) != sizeof(notif_v6->bigtk));
|
||||
|
||||
memcpy(notif->gtk, notif_v6->gtk, sizeof(notif_v6->gtk));
|
||||
memcpy(notif->igtk, notif_v6->igtk, sizeof(notif_v6->igtk));
|
||||
memcpy(notif->bigtk, notif_v6->bigtk, sizeof(notif_v6->bigtk));
|
||||
|
||||
notif->replay_ctr = notif_v6->replay_ctr;
|
||||
notif->pattern_number = notif_v6->pattern_number;
|
||||
notif->qos_seq_ctr = notif_v6->qos_seq_ctr;
|
||||
notif->wakeup_reasons = notif_v6->wakeup_reasons;
|
||||
notif->num_of_gtk_rekeys = notif_v6->num_of_gtk_rekeys;
|
||||
notif->transmitted_ndps = notif_v6->transmitted_ndps;
|
||||
notif->received_beacons = notif_v6->received_beacons;
|
||||
notif->tid_tear_down = notif_v6->tid_tear_down;
|
||||
notif->station_id = notif_v6->station_id;
|
||||
notif->num_mlo_link_keys = notif_v6->num_mlo_link_keys;
|
||||
notif->tid_offloaded_tx = notif_v6->tid_offloaded_tx;
|
||||
|
||||
if (notif_v6->num_mlo_link_keys)
|
||||
memcpy(notif->mlo_gtks, notif_v6->mlo_gtks,
|
||||
notif_v6->num_mlo_link_keys *
|
||||
sizeof(struct iwl_wowlan_mlo_gtk));
|
||||
}
|
||||
|
||||
static bool iwl_mld_validate_wowlan_notif_size(struct iwl_mld *mld, u32 len,
|
||||
const void *notif_data,
|
||||
int version)
|
||||
|
|
@ -618,12 +650,23 @@ static bool iwl_mld_validate_wowlan_notif_size(struct iwl_mld *mld, u32 len,
|
|||
|
||||
num_mlo_keys = notif_v5->num_mlo_link_keys;
|
||||
} else if (version == 6) {
|
||||
const struct iwl_wowlan_info_notif_v6 *notif_v6 = notif_data;
|
||||
|
||||
expected_len = sizeof(*notif_v6);
|
||||
|
||||
if (IWL_FW_CHECK(mld, len < expected_len,
|
||||
"Invalid wowlan_info_notif v6 (expected=%u got=%u)\n",
|
||||
expected_len, len))
|
||||
return false;
|
||||
|
||||
num_mlo_keys = notif_v6->num_mlo_link_keys;
|
||||
} else if (version == 7) {
|
||||
const struct iwl_wowlan_info_notif *notif = notif_data;
|
||||
|
||||
expected_len = sizeof(*notif);
|
||||
|
||||
if (IWL_FW_CHECK(mld, len < expected_len,
|
||||
"Invalid wowlan_info_notif v6 (expected=%u got=%u)\n",
|
||||
"Invalid wowlan_info_notif v7 (expected=%u got=%u)\n",
|
||||
expected_len, len))
|
||||
return false;
|
||||
|
||||
|
|
@ -682,9 +725,27 @@ iwl_mld_handle_wowlan_info_notif(struct iwl_mld *mld,
|
|||
iwl_mld_convert_wowlan_notif_v5(_notif, converted_notif);
|
||||
notif = converted_notif;
|
||||
} else if (wowlan_info_ver == 6) {
|
||||
const struct iwl_wowlan_info_notif_v6 *_notif =
|
||||
(void *)pkt->data;
|
||||
|
||||
if (!iwl_mld_validate_wowlan_notif_size(mld, len, _notif, 6))
|
||||
return true;
|
||||
|
||||
converted_notif = kzalloc_flex(*converted_notif, mlo_gtks,
|
||||
_notif->num_mlo_link_keys,
|
||||
GFP_ATOMIC);
|
||||
if (!converted_notif) {
|
||||
IWL_ERR(mld,
|
||||
"Failed to allocate memory for converted wowlan_info_notif\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
iwl_mld_convert_wowlan_notif_v6(_notif, converted_notif);
|
||||
notif = converted_notif;
|
||||
} else if (wowlan_info_ver == 7) {
|
||||
notif = (void *)pkt->data;
|
||||
|
||||
if (!iwl_mld_validate_wowlan_notif_size(mld, len, notif, 6))
|
||||
if (!iwl_mld_validate_wowlan_notif_size(mld, len, notif, 7))
|
||||
return true;
|
||||
} else {
|
||||
/* smaller versions are not supported */
|
||||
|
|
@ -1610,6 +1671,8 @@ int iwl_mld_no_wowlan_suspend(struct iwl_mld *mld)
|
|||
|
||||
iwl_mld_low_latency_stop(mld);
|
||||
|
||||
iwl_mld_tx_gp2_stop(mld);
|
||||
|
||||
ret = iwl_mld_update_device_power(mld, true);
|
||||
if (ret) {
|
||||
IWL_ERR(mld,
|
||||
|
|
@ -1663,6 +1726,8 @@ int iwl_mld_no_wowlan_resume(struct iwl_mld *mld)
|
|||
|
||||
iwl_mld_low_latency_restart(mld);
|
||||
|
||||
iwl_mld_tx_gp2_start(mld);
|
||||
|
||||
return iwl_mld_update_device_power(mld, false);
|
||||
}
|
||||
|
||||
|
|
@ -1829,9 +1894,12 @@ iwl_mld_send_kek_kck_cmd(struct iwl_mld *mld,
|
|||
struct iwl_mld_suspend_key_iter_data data,
|
||||
int ap_sta_id)
|
||||
{
|
||||
struct iwl_wowlan_kek_kck_material_cmd_v4 kek_kck_cmd = {};
|
||||
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, WOWLAN_KEK_KCK_MATERIAL, 4);
|
||||
struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {};
|
||||
struct iwl_mld_rekey_data *rekey_data =
|
||||
&mld_vif->wowlan_data.rekey_data;
|
||||
u32 cmd_size = cmd_ver == 5 ? sizeof(kek_kck_cmd) :
|
||||
sizeof(struct iwl_wowlan_kek_kck_material_cmd_v4);
|
||||
|
||||
memcpy(kek_kck_cmd.kck, rekey_data->kck,
|
||||
rekey_data->kck_len);
|
||||
|
|
@ -1850,7 +1918,7 @@ iwl_mld_send_kek_kck_cmd(struct iwl_mld *mld,
|
|||
rekey_data->akm);
|
||||
|
||||
return iwl_mld_send_cmd_pdu(mld, WOWLAN_KEK_KCK_MATERIAL,
|
||||
&kek_kck_cmd);
|
||||
&kek_kck_cmd, cmd_size);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#include "mld.h"
|
||||
#include "debugfs.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "hcmd.h"
|
||||
#include "iface.h"
|
||||
#include "sta.h"
|
||||
|
|
@ -69,7 +69,7 @@ static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mld *mld, char *buf,
|
|||
if (count == 6 && !strcmp(buf, "nolog\n"))
|
||||
mld->fw_status.do_not_dump_once = true;
|
||||
|
||||
iwl_force_nmi(mld->trans);
|
||||
iwl_trans_force_nmi(mld->trans);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include "mld.h"
|
||||
#include "iface.h"
|
||||
#include "phy.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "constants.h"
|
||||
#include "fw/api/location.h"
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
* Copyright (C) 2024-2026 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "mld.h"
|
||||
#include "tx.h"
|
||||
|
||||
#include "fw/api/alive.h"
|
||||
#include "fw/api/scan.h"
|
||||
|
|
@ -46,6 +47,9 @@ static int iwl_mld_send_rss_cfg_cmd(struct iwl_mld *mld)
|
|||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
if (mld->trans->info.num_rxqs == 1)
|
||||
return 0;
|
||||
|
||||
/* Do not direct RSS traffic to Q 0 which is our fallback queue */
|
||||
for (int i = 0; i < ARRAY_SIZE(cmd.indirection_table); i++)
|
||||
cmd.indirection_table[i] =
|
||||
|
|
@ -206,11 +210,11 @@ static void iwl_mld_print_alive_notif_timeout(struct iwl_mld *mld)
|
|||
|
||||
IWL_ERR(mld,
|
||||
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
|
||||
iwl_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS),
|
||||
iwl_read_umac_prph(trans,
|
||||
UMAG_SB_CPU_2_STATUS));
|
||||
iwl_trans_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS),
|
||||
iwl_trans_read_umac_prph(trans,
|
||||
UMAG_SB_CPU_2_STATUS));
|
||||
#define IWL_FW_PRINT_REG_INFO(reg_name) \
|
||||
IWL_ERR(mld, #reg_name ": 0x%x\n", iwl_read_umac_prph(trans, reg_name))
|
||||
IWL_ERR(mld, #reg_name ": 0x%x\n", iwl_trans_read_umac_prph(trans, reg_name))
|
||||
|
||||
IWL_FW_PRINT_REG_INFO(WFPM_LMAC1_PD_NOTIFICATION);
|
||||
|
||||
|
|
@ -355,6 +359,8 @@ void iwl_mld_stop_fw(struct iwl_mld *mld)
|
|||
{
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
iwl_mld_tx_gp2_stop(mld);
|
||||
|
||||
iwl_abort_notification_waits(&mld->notif_wait);
|
||||
|
||||
iwl_fw_dbg_stop_sync(&mld->fwrt);
|
||||
|
|
@ -396,8 +402,10 @@ void iwl_mld_send_recovery_cmd(struct iwl_mld *mld, u32 flags)
|
|||
|
||||
if (flags & ERROR_RECOVERY_UPDATE_DB) {
|
||||
/* no buf was allocated upon NIC error */
|
||||
if (!mld->error_recovery_buf)
|
||||
if (!mld->error_recovery_buf) {
|
||||
IWL_ERR(mld, "Recovering without recovery buffer. Expect bugs\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cmd.data[1] = mld->error_recovery_buf;
|
||||
cmd.len[1] = error_log_size;
|
||||
|
|
@ -540,6 +548,8 @@ int iwl_mld_start_fw(struct iwl_mld *mld)
|
|||
if (ret)
|
||||
goto error;
|
||||
|
||||
iwl_mld_tx_gp2_start(mld);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
#ifndef __iwl_mld_hcmd_h__
|
||||
#define __iwl_mld_hcmd_h__
|
||||
|
||||
#include "mld.h"
|
||||
|
||||
static inline int iwl_mld_send_cmd(struct iwl_mld *mld, struct iwl_host_cmd *cmd)
|
||||
{
|
||||
/* No commands, including the d3 related commands, should be sent
|
||||
|
|
|
|||
|
|
@ -37,6 +37,12 @@ static u32 iwl_mld_get_key_flags(struct iwl_mld *mld,
|
|||
break;
|
||||
}
|
||||
|
||||
/* Note that sta->mfp might not be set yet, as it is set only
|
||||
* after association.
|
||||
*/
|
||||
if (sta && pairwise && sta->epp_peer)
|
||||
flags |= IWL_SEC_KEY_FLAG_ASSOC_ENC | IWL_SEC_KEY_FLAG_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.
|
||||
|
|
|
|||
|
|
@ -361,13 +361,6 @@ iwl_mld_change_link_in_fw(struct iwl_mld *mld, struct ieee80211_bss_conf *link,
|
|||
flags |= LINK_FLG_MLPM;
|
||||
}
|
||||
|
||||
cmd.htc_trig_based_pkt_ext = link->htc_trig_based_pkt_ext;
|
||||
|
||||
if (link->uora_exists) {
|
||||
cmd.rand_alloc_ecwmin = link->uora_ocw_range & 0x7;
|
||||
cmd.rand_alloc_ecwmax = (link->uora_ocw_range >> 3) & 0x7;
|
||||
}
|
||||
|
||||
if (iwl_mld_fill_mu_edca(mld, mld_link, cmd.trig_based_txf))
|
||||
flags |= LINK_FLG_MU_EDCA_CW;
|
||||
|
||||
|
|
@ -376,8 +369,6 @@ iwl_mld_change_link_in_fw(struct iwl_mld *mld, struct ieee80211_bss_conf *link,
|
|||
if (!link->he_bss_color.enabled)
|
||||
flags |= LINK_FLG_BSS_COLOR_DIS;
|
||||
|
||||
cmd.frame_time_rts_th = cpu_to_le16(link->frame_time_rts_th);
|
||||
|
||||
/* Block 26-tone RU OFDMA transmissions */
|
||||
if (mld_link->he_ru_2mhz_block)
|
||||
flags |= LINK_FLG_RU_2MHZ_BLOCK;
|
||||
|
|
@ -387,6 +378,11 @@ iwl_mld_change_link_in_fw(struct iwl_mld *mld, struct ieee80211_bss_conf *link,
|
|||
cmd.bssid_index = link->bssid_index;
|
||||
}
|
||||
|
||||
if (iwl_fw_lookup_cmd_ver(mld->fw,
|
||||
WIDE_ID(MAC_CONF_GROUP, LINK_CONFIG_CMD),
|
||||
0) >= 9)
|
||||
cmd.max_bssid_indicator = link->bssid_indicator;
|
||||
|
||||
/* The only EHT parameter is puncturing, and starting from PHY cmd
|
||||
* version 6 - it is sent there. For older versions of the PHY cmd,
|
||||
* puncturing is not needed at all.
|
||||
|
|
|
|||
|
|
@ -257,7 +257,8 @@ static bool iwl_mld_is_vo_vi_pkt(struct ieee80211_hdr *hdr)
|
|||
if (tid >= IWL_MAX_TID_COUNT)
|
||||
return false;
|
||||
|
||||
return tid_to_mac80211_ac[tid] < IEEE80211_AC_VI;
|
||||
return tid_to_mac80211_ac[tid] == IEEE80211_AC_VI ||
|
||||
tid_to_mac80211_ac[tid] == IEEE80211_AC_VO;
|
||||
}
|
||||
|
||||
void iwl_mld_low_latency_update_counters(struct iwl_mld *mld,
|
||||
|
|
|
|||
|
|
@ -395,6 +395,10 @@ static void iwl_mac_hw_set_wiphy(struct iwl_mld *mld)
|
|||
if (fw_has_capa(ucode_capa, IWL_UCODE_TLV_CAPA_PROTECTED_TWT))
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_PROTECTED_TWT);
|
||||
|
||||
if (fw_has_capa(ucode_capa, IWL_UCODE_TLV_CAPA_ASSOC_ENC_SUPPORT))
|
||||
wiphy_ext_feature_set(wiphy,
|
||||
NL80211_EXT_FEATURE_ASSOC_FRAME_ENCRYPTION);
|
||||
|
||||
if (iwlmld_mod_params.power_scheme != IWL_POWER_SCHEME_CAM)
|
||||
wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||
else
|
||||
|
|
@ -2164,6 +2168,8 @@ static int iwl_mld_resume(struct ieee80211_hw *hw)
|
|||
|
||||
iwl_mld_low_latency_restart(mld);
|
||||
|
||||
iwl_mld_tx_gp2_start(mld);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -35,6 +35,17 @@ MODULE_IMPORT_NS("IWLWIFI");
|
|||
|
||||
static const struct iwl_op_mode_ops iwl_mld_ops;
|
||||
|
||||
int iwl_mld_get_systime(struct iwl_mld *mld, u32 *gp2)
|
||||
{
|
||||
*gp2 = iwl_trans_read_prph(mld->trans,
|
||||
mld->trans->mac_cfg->base->gp2_reg_addr);
|
||||
|
||||
if (*gp2 == 0x5a5a5a5a)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init iwl_mld_init(void)
|
||||
{
|
||||
int ret = iwl_opmode_register("iwlmld", &iwl_mld_ops);
|
||||
|
|
@ -425,6 +436,8 @@ iwl_op_mode_mld_start(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
|
|||
/* Configure transport layer with the opmode specific params */
|
||||
iwl_mld_configure_trans(op_mode);
|
||||
|
||||
iwl_mld_tx_gp2_init(mld);
|
||||
|
||||
/* needed for regulatory init */
|
||||
rtnl_lock();
|
||||
/* Needed for sending commands */
|
||||
|
|
@ -621,6 +634,13 @@ static void iwl_mld_read_error_recovery_buffer(struct iwl_mld *mld)
|
|||
if (!src_size)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If we have a the recovery buffer from a previous (failing) recovery -
|
||||
* free it here
|
||||
*/
|
||||
kfree(mld->error_recovery_buf);
|
||||
mld->error_recovery_buf = NULL;
|
||||
|
||||
recovery_buf = kzalloc(src_size, GFP_ATOMIC);
|
||||
if (!recovery_buf)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "notif.h"
|
||||
#include "scan.h"
|
||||
#include "rx.h"
|
||||
#include "tx.h"
|
||||
#include "thermal.h"
|
||||
#include "low_latency.h"
|
||||
#include "constants.h"
|
||||
|
|
@ -196,6 +197,7 @@
|
|||
* being IBSS manager for that time and needing to respond to probe
|
||||
* requests
|
||||
* @ptp_data: data of the PTP clock
|
||||
* @tx_gp2: gp2 timestamping state for TX commands
|
||||
* @time_sync: time sync data.
|
||||
* @ftm_initiator: FTM initiator data
|
||||
* @nan_device_vif: points to the NAN device vif if exists
|
||||
|
|
@ -306,6 +308,8 @@ struct iwl_mld {
|
|||
|
||||
struct ptp_data ptp_data;
|
||||
|
||||
struct iwl_mld_tx_gp2 tx_gp2;
|
||||
|
||||
struct iwl_mld_time_sync_data __rcu *time_sync;
|
||||
|
||||
struct ftm_initiator_data ftm_initiator;
|
||||
|
|
@ -572,6 +576,8 @@ iwl_mld_fw_id_to_link_conf(struct iwl_mld *mld, u8 fw_link_id)
|
|||
|
||||
#define MSEC_TO_TU(_msec) ((_msec) * 1000 / 1024)
|
||||
|
||||
int iwl_mld_get_systime(struct iwl_mld *mld, u32 *gp2);
|
||||
|
||||
void iwl_mld_add_vif_debugfs(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
void iwl_mld_add_link_debugfs(struct ieee80211_hw *hw,
|
||||
|
|
|
|||
|
|
@ -1076,9 +1076,9 @@ static void iwl_mld_chan_load_update_iter(void *_data, u8 *mac,
|
|||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mld_chan_load_data *data = _data;
|
||||
const struct iwl_mld_phy *phy = data->phy;
|
||||
struct iwl_mld_phy *phy = data->phy;
|
||||
struct ieee80211_chanctx_conf *chanctx =
|
||||
container_of((const void *)phy, struct ieee80211_chanctx_conf,
|
||||
container_of((void *)phy, struct ieee80211_chanctx_conf,
|
||||
drv_priv);
|
||||
struct iwl_mld *mld = iwl_mld_vif_from_mac80211(vif)->mld;
|
||||
u32 new_chan_load = phy->avg_channel_load_not_by_us;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "mld.h"
|
||||
#include "iface.h"
|
||||
#include "key.h"
|
||||
#include "link.h"
|
||||
#include "mlo.h"
|
||||
#include "tlc.h"
|
||||
|
|
@ -107,6 +108,20 @@ static void iwl_mld_nan_flush(struct iwl_mld *mld, struct ieee80211_vif *vif)
|
|||
iwl_mld_flush_link_sta_txqs(mld, sta->sta_id);
|
||||
}
|
||||
|
||||
static void iwl_mld_remove_nan_keys_iter(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key,
|
||||
void *data)
|
||||
{
|
||||
struct iwl_mld *mld = data;
|
||||
|
||||
if (sta || key->hw_key_idx == STA_KEY_IDX_INVALID)
|
||||
return;
|
||||
|
||||
iwl_mld_remove_key(mld, vif, NULL, key);
|
||||
}
|
||||
|
||||
static void iwl_mld_nan_remove_stations(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
|
|
@ -296,6 +311,8 @@ int iwl_mld_stop_nan(struct ieee80211_hw *hw,
|
|||
if (ret)
|
||||
IWL_ERR(mld, "NAN: Failed to stop NAN. ret=%d\n", ret);
|
||||
|
||||
ieee80211_iter_keys(mld->hw, vif, iwl_mld_remove_nan_keys_iter, mld);
|
||||
|
||||
/* assume that higher layer guarantees that no additional frames are
|
||||
* added before calling this callback
|
||||
*/
|
||||
|
|
@ -576,21 +593,11 @@ static int iwl_mld_nan_link_set_active(struct iwl_mld *mld,
|
|||
bool active)
|
||||
{
|
||||
struct iwl_link_config_cmd cmd;
|
||||
struct ieee80211_sta *sta;
|
||||
int ret;
|
||||
|
||||
if (nan_link->active == active)
|
||||
return 0;
|
||||
|
||||
if (active) {
|
||||
for_each_station(sta, mld->hw) {
|
||||
struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta);
|
||||
|
||||
if (mld_sta->sta_type == STATION_TYPE_NAN_PEER_NDI)
|
||||
iwl_mld_config_tlc(mld, mld_sta->vif, sta);
|
||||
}
|
||||
}
|
||||
|
||||
nan_link->active = active;
|
||||
|
||||
iwl_mld_nan_link_prep_cmd(mld, nan_link, &cmd,
|
||||
|
|
@ -602,10 +609,8 @@ static int iwl_mld_nan_link_set_active(struct iwl_mld *mld,
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (!active) {
|
||||
if (!active)
|
||||
nan_link->chanctx = NULL;
|
||||
/* TODO: when FW is ready, Update phy in TLC to invalid after */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -847,6 +852,10 @@ void iwl_mld_nan_vif_cfg_changed(struct iwl_mld *mld,
|
|||
if (mld_sta->sta_type == STATION_TYPE_NAN_PEER_NMI ||
|
||||
mld_sta->sta_type == STATION_TYPE_NAN_PEER_NDI)
|
||||
iwl_mld_add_modify_sta_cmd(mld, &sta->deflink);
|
||||
|
||||
if (added_links &&
|
||||
mld_sta->sta_type == STATION_TYPE_NAN_PEER_NDI)
|
||||
iwl_mld_config_tlc(mld, mld_sta->vif, sta);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -159,8 +159,8 @@ static void iwl_mld_mu_mimo_iface_iterator(void *_data, u8 *mac,
|
|||
* action frame, so no conversion is needed.
|
||||
*/
|
||||
ieee80211_update_mu_groups(vif, link_id,
|
||||
(u8 *)¬if->membership_status,
|
||||
(u8 *)¬if->user_position);
|
||||
(const u8 *)¬if->membership_status,
|
||||
(const u8 *)¬if->user_position);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -292,7 +292,8 @@ CMD_VERSIONS(scan_start_notif,
|
|||
CMD_VERSIONS(scan_complete_notif,
|
||||
CMD_VER_ENTRY(1, iwl_umac_scan_complete))
|
||||
CMD_VERSIONS(scan_iter_complete_notif,
|
||||
CMD_VER_ENTRY(2, iwl_umac_scan_iter_complete_notif))
|
||||
CMD_VER_ENTRY(2, iwl_umac_scan_iter_complete_notif_v2)
|
||||
CMD_VER_ENTRY(3, iwl_umac_scan_iter_complete_notif))
|
||||
CMD_VERSIONS(channel_survey_notif,
|
||||
CMD_VER_ENTRY(1, iwl_umac_scan_channel_survey_notif))
|
||||
CMD_VERSIONS(mfuart_notif,
|
||||
|
|
@ -329,7 +330,8 @@ CMD_VERSIONS(datapath_monitor_notif,
|
|||
CMD_VER_ENTRY(1, iwl_datapath_monitor_notif))
|
||||
CMD_VERSIONS(stats_oper_notif,
|
||||
CMD_VER_ENTRY(3, iwl_system_statistics_notif_oper_v3)
|
||||
CMD_VER_ENTRY(4, iwl_system_statistics_notif_oper))
|
||||
CMD_VER_ENTRY(4, iwl_system_statistics_notif_oper_v4)
|
||||
CMD_VER_ENTRY(5, iwl_system_statistics_notif_oper))
|
||||
CMD_VERSIONS(stats_oper_part1_notif,
|
||||
CMD_VER_ENTRY(4, iwl_system_statistics_part1_notif_oper))
|
||||
CMD_VERSIONS(bt_coex_notif,
|
||||
|
|
|
|||
|
|
@ -525,7 +525,7 @@ int iwl_mld_set_tx_power(struct iwl_mld *mld,
|
|||
.common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_LINK),
|
||||
.common.pwr_restriction = cpu_to_le16(u_tx_power),
|
||||
};
|
||||
int len = sizeof(cmd.common) + sizeof(cmd.v11);
|
||||
int len = sizeof(cmd.common) + sizeof(cmd.v12);
|
||||
|
||||
if (iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 10) == 10)
|
||||
len = sizeof(cmd.common) + sizeof(cmd.v10);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2025 Intel Corporation
|
||||
* Copyright (C) 2025 - 2026 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "mld.h"
|
||||
|
|
@ -19,16 +19,6 @@
|
|||
#define IWL_PTP_WRAP_TIME (3600 * HZ)
|
||||
#define IWL_PTP_WRAP_THRESHOLD_USEC (5000)
|
||||
|
||||
static int iwl_mld_get_systime(struct iwl_mld *mld, u32 *gp2)
|
||||
{
|
||||
*gp2 = iwl_read_prph(mld->trans, mld->trans->mac_cfg->base->gp2_reg_addr);
|
||||
|
||||
if (*gp2 == 0x5a5a5a5a)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_mld_ptp_update_new_read(struct iwl_mld *mld, u32 gp2)
|
||||
{
|
||||
IWL_DEBUG_PTP(mld, "PTP: last_gp2=%u, new gp2 read=%u\n",
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
#include <linux/dmi.h>
|
||||
|
||||
#include "fw/regulatory.h"
|
||||
#include "fw/acpi.h"
|
||||
#include "fw/uefi.h"
|
||||
|
||||
#include "regulatory.h"
|
||||
|
|
@ -37,7 +36,7 @@ void iwl_mld_get_bios_tables(struct iwl_mld *mld)
|
|||
{
|
||||
int ret;
|
||||
|
||||
iwl_acpi_get_guid_lock_status(&mld->fwrt);
|
||||
iwl_bios_get_guid_lock_status(&mld->fwrt);
|
||||
|
||||
ret = iwl_bios_get_ppag_table(&mld->fwrt);
|
||||
if (ret < 0) {
|
||||
|
|
@ -75,6 +74,21 @@ void iwl_mld_get_bios_tables(struct iwl_mld *mld)
|
|||
"EWRD SAR BIOS table invalid or unavailable. (%d)\n",
|
||||
ret);
|
||||
|
||||
ret = iwl_bios_get_wsss_table(&mld->fwrt);
|
||||
if (ret < 0)
|
||||
IWL_DEBUG_RADIO(mld,
|
||||
"WSSS (WRDS Standalone) SAR BIOS table invalid or unavailable. (%d)\n",
|
||||
ret);
|
||||
|
||||
if (!ret) {
|
||||
/* EWSS only extends the standalone SAR profiles from WSSS. */
|
||||
ret = iwl_bios_get_ewss_table(&mld->fwrt);
|
||||
if (ret < 0)
|
||||
IWL_DEBUG_RADIO(mld,
|
||||
"EWSS (EWRD Standalone) SAR BIOS table invalid or unavailable. (%d)\n",
|
||||
ret);
|
||||
}
|
||||
|
||||
ret = iwl_bios_get_wgds_table(&mld->fwrt);
|
||||
if (ret < 0)
|
||||
IWL_DEBUG_RADIO(mld,
|
||||
|
|
@ -136,7 +150,9 @@ static int iwl_mld_geo_sar_init(struct iwl_mld *mld)
|
|||
return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, cmd_size);
|
||||
}
|
||||
|
||||
int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b)
|
||||
static int
|
||||
iwl_mld_config_sar_concurrent_profile(struct iwl_mld *mld, int prof_a,
|
||||
int prof_b)
|
||||
{
|
||||
struct iwl_dev_tx_power_cmd cmd = {
|
||||
.common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS),
|
||||
|
|
@ -153,8 +169,9 @@ int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b)
|
|||
num_subbands = IWL_NUM_SUB_BANDS_V2;
|
||||
break;
|
||||
case 11:
|
||||
cmd.v11.flags = cpu_to_le32(mld->fwrt.reduced_power_flags);
|
||||
cmd_size = sizeof(cmd.common) + sizeof(cmd.v11);
|
||||
case 12:
|
||||
cmd.v12.flags = cpu_to_le32(mld->fwrt.reduced_power_flags);
|
||||
cmd_size = sizeof(cmd.common) + sizeof(cmd.v12);
|
||||
num_subbands = IWL_NUM_SUB_BANDS_V3;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -164,12 +181,13 @@ int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b)
|
|||
}
|
||||
|
||||
/* TODO: CDB - support IWL_NUM_CHAIN_TABLES_V2 */
|
||||
/* v10 and v11 have the same position for per_chain */
|
||||
BUILD_BUG_ON(offsetof(typeof(cmd), v11.per_chain) !=
|
||||
/* v10 and v12 have the same position for per_chain */
|
||||
BUILD_BUG_ON(offsetof(typeof(cmd), v12.per_chain) !=
|
||||
offsetof(typeof(cmd), v10.per_chain));
|
||||
ret = iwl_sar_fill_profile(&mld->fwrt, &cmd.v11.per_chain[0][0][0],
|
||||
ret = iwl_sar_fill_profile(&mld->fwrt, &cmd.v12.per_chain[0][0][0],
|
||||
IWL_NUM_CHAIN_TABLES, num_subbands,
|
||||
prof_a, prof_b);
|
||||
prof_a, prof_b,
|
||||
mld->fwrt.sar_profiles, false);
|
||||
/* return on error or if the profile is disabled (positive number) */
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -177,6 +195,51 @@ int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b)
|
|||
return iwl_mld_send_cmd_pdu(mld, REDUCE_TX_POWER_CMD, &cmd, cmd_size);
|
||||
}
|
||||
|
||||
static int iwl_mld_config_sar_standalone_profile(struct iwl_mld *mld,
|
||||
int prof_a, int prof_b)
|
||||
{
|
||||
struct iwl_dev_tx_power_cmd cmd = {
|
||||
.common.set_mode =
|
||||
cpu_to_le32(IWL_TX_POWER_MODE_SET_STANDALONE_CHAINS),
|
||||
};
|
||||
int ret;
|
||||
|
||||
/* standalone per-chain SAR limits require cmd version 12 */
|
||||
if (iwl_fw_lookup_cmd_ver(mld->fw, REDUCE_TX_POWER_CMD, 10) != 12)
|
||||
return 0;
|
||||
|
||||
ret = iwl_sar_fill_profile(&mld->fwrt,
|
||||
&cmd.v12.per_chain[0][0][0],
|
||||
IWL_NUM_CHAIN_TABLES,
|
||||
IWL_NUM_SUB_BANDS_V3,
|
||||
prof_a, prof_b,
|
||||
mld->fwrt.sar_standalone_profiles,
|
||||
true);
|
||||
/* return on error or if the standalone profile is disabled */
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return iwl_mld_send_cmd_pdu(mld, REDUCE_TX_POWER_CMD, &cmd,
|
||||
sizeof(cmd.common) + sizeof(cmd.v12));
|
||||
}
|
||||
|
||||
int iwl_mld_config_sar_profiles(struct iwl_mld *mld, int prof_a, int prof_b)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = iwl_mld_config_sar_concurrent_profile(mld, prof_a, prof_b);
|
||||
/* return on error or if the profile is disabled (positive number) */
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iwl_mld_config_sar_standalone_profile(mld, prof_a, prof_b);
|
||||
/* standalone profile is optional and may be disabled (positive number) */
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_mld_init_sar(struct iwl_mld *mld)
|
||||
{
|
||||
int chain_a_prof = 1;
|
||||
|
|
@ -191,7 +254,7 @@ int iwl_mld_init_sar(struct iwl_mld *mld)
|
|||
chain_b_prof = mld->fwrt.sar_chain_b_profile;
|
||||
}
|
||||
|
||||
ret = iwl_mld_config_sar_profile(mld, chain_a_prof, chain_b_prof);
|
||||
ret = iwl_mld_config_sar_profiles(mld, chain_a_prof, chain_b_prof);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
* Copyright (C) 2024-2026 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_mld_regulatory_h__
|
||||
#define __iwl_mld_regulatory_h__
|
||||
|
|
@ -18,6 +18,6 @@ int iwl_mld_init_sgom(struct iwl_mld *mld);
|
|||
|
||||
int iwl_mld_init_sar(struct iwl_mld *mld);
|
||||
|
||||
int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b);
|
||||
int iwl_mld_config_sar_profiles(struct iwl_mld *mld, int prof_a, int prof_b);
|
||||
|
||||
#endif /* __iwl_mld_regulatory_h__ */
|
||||
|
|
|
|||
|
|
@ -553,7 +553,10 @@ iwl_mld_decode_he_tb_phy_data(struct iwl_mld_rx_phy_data *phy_data,
|
|||
|
||||
nsts = le32_get_bits(phy_data->ntfy->sigs.he_tb.tb_rx1,
|
||||
OFDM_UCODE_TRIG_BASE_RX_NSTS) + 1;
|
||||
rx_status->nss = nsts >> !!(rate_n_flags & RATE_MCS_STBC_MSK);
|
||||
|
||||
rx_status->nss = nsts;
|
||||
if (rate_n_flags & RATE_MCS_STBC_MSK)
|
||||
rx_status->nss = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -589,7 +592,9 @@ iwl_mld_decode_he_phy_data(struct iwl_mld_rx_phy_data *phy_data,
|
|||
break;
|
||||
}
|
||||
|
||||
rx_status->nss = nsts >> !!(rate_n_flags & RATE_MCS_STBC_MSK);
|
||||
rx_status->nss = nsts;
|
||||
if (rate_n_flags & RATE_MCS_STBC_MSK)
|
||||
rx_status->nss = 1;
|
||||
|
||||
he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN |
|
||||
IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN);
|
||||
|
|
@ -811,6 +816,14 @@ iwl_mld_radiotap_put_tlv(struct sk_buff *skb, u16 type, u16 len)
|
|||
(_usig)->value |= LE32_DEC_ENC(in_value, dec_bits, _enc_bits); \
|
||||
} while (0)
|
||||
|
||||
static void
|
||||
iwl_mld_check_bad_usig_crc(struct ieee80211_rx_status *rx_status,
|
||||
struct ieee80211_radiotap_eht_usig *usig)
|
||||
{
|
||||
if (usig->common & cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BAD_USIG_CRC))
|
||||
rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC;
|
||||
}
|
||||
|
||||
static void iwl_mld_decode_eht_usig_tb(struct iwl_mld_rx_phy_data *phy_data,
|
||||
struct ieee80211_radiotap_eht_usig *usig)
|
||||
{
|
||||
|
|
@ -818,7 +831,8 @@ static void iwl_mld_decode_eht_usig_tb(struct iwl_mld_rx_phy_data *phy_data,
|
|||
__le32 usig_a2 = phy_data->ntfy->sigs.eht_tb.usig_a2_eht;
|
||||
|
||||
IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a1,
|
||||
OFDM_RX_FRAME_EHT_USIG1_DISREGARD,
|
||||
OFDM_RX_FRAME_EHT_USIG1_DISREGARD |
|
||||
OFDM_RX_FRAME_EHT_USIG1_VALIDATE,
|
||||
IEEE80211_RADIOTAP_EHT_USIG1_TB_B20_B25_DISREGARD);
|
||||
IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
OFDM_RX_FRAME_EHT_PPDU_TYPE,
|
||||
|
|
@ -872,6 +886,7 @@ static void iwl_mld_decode_eht_usig_non_tb(struct iwl_mld_rx_phy_data *phy_data,
|
|||
static void iwl_mld_decode_eht_usig(struct iwl_mld_rx_phy_data *phy_data,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
u32 he_type = phy_data->rate_n_flags & RATE_MCS_HE_TYPE_MSK;
|
||||
__le32 usig_a1 = phy_data->ntfy->sigs.eht.usig_a1;
|
||||
__le32 usig_a2 = phy_data->ntfy->sigs.eht.usig_a2_eht;
|
||||
|
|
@ -935,11 +950,13 @@ static void iwl_mld_decode_eht_usig(struct iwl_mld_rx_phy_data *phy_data,
|
|||
iwl_mld_decode_eht_usig_tb(phy_data, usig);
|
||||
else
|
||||
iwl_mld_decode_eht_usig_non_tb(phy_data, usig);
|
||||
|
||||
iwl_mld_check_bad_usig_crc(rx_status, usig);
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mld_eht_set_ru_alloc(struct ieee80211_rx_status *rx_status,
|
||||
u32 ru_with_p80)
|
||||
iwl_mld_eht_uhr_set_ru_alloc(struct ieee80211_rx_status *rx_status,
|
||||
u32 ru_with_p80, bool uhr)
|
||||
{
|
||||
enum nl80211_eht_ru_alloc nl_ru;
|
||||
u32 ru = ru_with_p80 >> 1;
|
||||
|
|
@ -1005,7 +1022,15 @@ iwl_mld_eht_set_ru_alloc(struct ieee80211_rx_status *rx_status,
|
|||
}
|
||||
|
||||
rx_status->bw = RATE_INFO_BW_EHT_RU;
|
||||
rx_status->eht.ru = nl_ru;
|
||||
|
||||
/*
|
||||
* This should get optimised away, but since it's bitfields,
|
||||
* we can't ensure uhr.ru and eht.ru overlap in the union.
|
||||
*/
|
||||
if (uhr)
|
||||
rx_status->uhr.ru = nl_ru;
|
||||
else
|
||||
rx_status->eht.ru = nl_ru;
|
||||
}
|
||||
|
||||
static void iwl_mld_decode_eht_tb(struct iwl_mld_rx_phy_data *phy_data,
|
||||
|
|
@ -1045,9 +1070,10 @@ static void iwl_mld_decode_eht_tb(struct iwl_mld_rx_phy_data *phy_data,
|
|||
OFDM_UCODE_TRIG_BASE_RX_RU_P80,
|
||||
IEEE80211_RADIOTAP_EHT_DATA1_PRIMARY_80);
|
||||
|
||||
iwl_mld_eht_set_ru_alloc(rx_status,
|
||||
le32_get_bits(phy_data->ntfy->sigs.eht_tb.tb_rx1,
|
||||
OFDM_UCODE_TRIG_BASE_RX_RU));
|
||||
iwl_mld_eht_uhr_set_ru_alloc(rx_status,
|
||||
le32_get_bits(phy_data->ntfy->sigs.eht_tb.tb_rx1,
|
||||
OFDM_UCODE_TRIG_BASE_RX_RU),
|
||||
false);
|
||||
}
|
||||
|
||||
static void iwl_mld_eht_decode_user_ru(struct iwl_mld_rx_phy_data *phy_data,
|
||||
|
|
@ -1203,9 +1229,10 @@ static void iwl_mld_decode_eht_non_tb(struct iwl_mld_rx_phy_data *phy_data,
|
|||
|
||||
iwl_mld_eht_decode_user_ru(phy_data, eht);
|
||||
|
||||
iwl_mld_eht_set_ru_alloc(rx_status,
|
||||
le32_get_bits(phy_data->ntfy->sigs.eht.b2,
|
||||
OFDM_RX_FRAME_EHT_STA_RU));
|
||||
iwl_mld_eht_uhr_set_ru_alloc(rx_status,
|
||||
le32_get_bits(phy_data->ntfy->sigs.eht.b2,
|
||||
OFDM_RX_FRAME_EHT_STA_RU),
|
||||
false);
|
||||
|
||||
if (phy_data->with_data)
|
||||
eht->user_info[0] |=
|
||||
|
|
@ -1227,48 +1254,30 @@ static void iwl_mld_decode_eht_phy_data(struct iwl_mld_rx_phy_data *phy_data,
|
|||
iwl_mld_decode_eht_non_tb(phy_data, rx_status, eht);
|
||||
}
|
||||
|
||||
static void iwl_mld_rx_eht(struct iwl_mld *mld, struct sk_buff *skb,
|
||||
struct iwl_mld_rx_phy_data *phy_data)
|
||||
static u8 iwl_mld_decode_eht_uhr_gi_ltf(u32 rate_n_flags, u8 *gi)
|
||||
{
|
||||
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
struct ieee80211_radiotap_eht *eht;
|
||||
size_t eht_len = sizeof(*eht);
|
||||
u32 rate_n_flags = phy_data->rate_n_flags;
|
||||
u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
|
||||
/* EHT and HE have the same values for LTF */
|
||||
u8 ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN;
|
||||
|
||||
/* u32 for 1 user_info */
|
||||
if (phy_data->with_data)
|
||||
eht_len += sizeof(u32);
|
||||
|
||||
eht = iwl_mld_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_EHT, eht_len);
|
||||
*gi = NL80211_RATE_INFO_EHT_GI_0_8;
|
||||
|
||||
switch (u32_get_bits(rate_n_flags, RATE_MCS_HE_GI_LTF_MSK)) {
|
||||
case 0:
|
||||
if (he_type == RATE_MCS_HE_TYPE_TRIG) {
|
||||
rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_1_6;
|
||||
ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X;
|
||||
} else {
|
||||
rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_0_8;
|
||||
ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X;
|
||||
*gi = NL80211_RATE_INFO_EHT_GI_1_6;
|
||||
return IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X;
|
||||
}
|
||||
break;
|
||||
return IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X;
|
||||
case 1:
|
||||
rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_1_6;
|
||||
ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X;
|
||||
break;
|
||||
*gi = NL80211_RATE_INFO_EHT_GI_1_6;
|
||||
return IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X;
|
||||
case 2:
|
||||
ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X;
|
||||
if (he_type == RATE_MCS_HE_TYPE_TRIG)
|
||||
rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_3_2;
|
||||
else
|
||||
rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_0_8;
|
||||
break;
|
||||
*gi = NL80211_RATE_INFO_EHT_GI_3_2;
|
||||
return IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X;
|
||||
case 3:
|
||||
if (he_type != RATE_MCS_HE_TYPE_TRIG) {
|
||||
ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X;
|
||||
rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_3_2;
|
||||
*gi = NL80211_RATE_INFO_EHT_GI_3_2;
|
||||
return IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
@ -1276,7 +1285,29 @@ static void iwl_mld_rx_eht(struct iwl_mld *mld, struct sk_buff *skb,
|
|||
break;
|
||||
}
|
||||
|
||||
return IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN;
|
||||
}
|
||||
|
||||
static void iwl_mld_rx_eht(struct iwl_mld *mld, struct sk_buff *skb,
|
||||
struct iwl_mld_rx_phy_data *phy_data)
|
||||
{
|
||||
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
struct ieee80211_radiotap_eht *eht;
|
||||
size_t eht_len = sizeof(*eht);
|
||||
u32 rate_n_flags = phy_data->rate_n_flags;
|
||||
u8 gi, ltf;
|
||||
|
||||
/* u32 for 1 user_info */
|
||||
if (phy_data->with_data)
|
||||
eht_len += sizeof(u32);
|
||||
|
||||
eht = iwl_mld_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_EHT, eht_len);
|
||||
|
||||
ltf = iwl_mld_decode_eht_uhr_gi_ltf(rate_n_flags, &gi);
|
||||
|
||||
if (ltf != IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN) {
|
||||
rx_status->eht.gi = gi;
|
||||
|
||||
eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_GI);
|
||||
eht->data[0] |= le32_encode_bits(ltf,
|
||||
IEEE80211_RADIOTAP_EHT_DATA0_LTF) |
|
||||
|
|
@ -1311,7 +1342,7 @@ static void iwl_mld_rx_eht(struct iwl_mld *mld, struct sk_buff *skb,
|
|||
|
||||
eht->user_info[0] |=
|
||||
le32_encode_bits(u32_get_bits(rate_n_flags,
|
||||
RATE_VHT_MCS_RATE_CODE_MSK),
|
||||
RATE_MCS_CODE_MSK),
|
||||
IEEE80211_RADIOTAP_EHT_USER_INFO_MCS) |
|
||||
le32_encode_bits(u32_get_bits(rate_n_flags,
|
||||
RATE_MCS_NSS_MSK),
|
||||
|
|
@ -1325,6 +1356,558 @@ static void iwl_mld_rx_eht(struct iwl_mld *mld, struct sk_buff *skb,
|
|||
iwl_mld_decode_eht_phy_data(phy_data, rx_status, eht);
|
||||
}
|
||||
|
||||
static void iwl_mld_decode_uhr_usig_tb(struct iwl_mld_rx_phy_data *phy_data,
|
||||
struct ieee80211_radiotap_eht_usig *usig)
|
||||
{
|
||||
__le32 usig_a1 = phy_data->ntfy->sigs.uhr_tb.usig_a1;
|
||||
__le32 usig_a2 = phy_data->ntfy->sigs.uhr_tb.usig_a2_uhr;
|
||||
|
||||
IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a1,
|
||||
OFDM_RX_FRAME_EHT_USIG1_DISREGARD |
|
||||
OFDM_RX_FRAME_EHT_USIG1_VALIDATE,
|
||||
IEEE80211_RADIOTAP_UHR_USIG1_TB_B20_B25_DISREGARD);
|
||||
IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
OFDM_RX_FRAME_UHR_PPDU_TYPE,
|
||||
IEEE80211_RADIOTAP_UHR_USIG2_TB_B0_B1_PPDU_TYPE);
|
||||
IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
OFDM_RX_FRAME_UHR_TRIG_SPATIAL_REUSE_1,
|
||||
IEEE80211_RADIOTAP_UHR_USIG2_TB_B3_B6_SPATIAL_REUSE_1);
|
||||
IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
OFDM_RX_FRAME_UHR_TRIG_SPATIAL_REUSE_2,
|
||||
IEEE80211_RADIOTAP_UHR_USIG2_TB_B7_B10_SPATIAL_REUSE_2);
|
||||
IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
OFDM_RX_FRAME_UHR_TRIG_USIG2_DISREGARD,
|
||||
IEEE80211_RADIOTAP_UHR_USIG2_TB_B11_B15_DISREGARD);
|
||||
|
||||
if (le32_get_bits(usig_a1, OFDM_RX_FRAME_EHT_USIG1_VALIDATE) &&
|
||||
le32_get_bits(usig_a2, OFDM_RX_FRAME_UHR_USIG2_VALIDATE_B8))
|
||||
usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_VALIDATE_BITS_OK);
|
||||
|
||||
if (!le32_get_bits(usig_a2, OFDM_RX_FRAME_UHR_USIG_CRC_OK))
|
||||
usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BAD_USIG_CRC);
|
||||
}
|
||||
|
||||
static void iwl_mld_decode_uhr_usig_elr(struct iwl_mld_rx_phy_data *phy_data,
|
||||
struct ieee80211_radiotap_eht_usig *usig)
|
||||
{
|
||||
__le32 usig_a1 = phy_data->ntfy->sigs.uhr_elr.usig_a1;
|
||||
__le32 usig_a2 = phy_data->ntfy->sigs.uhr_elr.usig_a2_uhr_elr;
|
||||
|
||||
IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a1,
|
||||
OFDM_RX_FRAME_EHT_USIG1_DISREGARD,
|
||||
IEEE80211_RADIOTAP_UHR_USIG1_ELR_B20_B24_DISREGARD);
|
||||
IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a1,
|
||||
OFDM_RX_FRAME_EHT_USIG1_VALIDATE,
|
||||
IEEE80211_RADIOTAP_UHR_USIG1_ELR_B25_VALIDATE);
|
||||
IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
OFDM_RX_VECTOR_UHR_ELR_PPDU_TYPE,
|
||||
IEEE80211_RADIOTAP_UHR_USIG2_ELR_B0_B1_PPDU_TYPE);
|
||||
IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
OFDM_RX_VECTOR_UHR_ELR_USIG_STA_ID,
|
||||
IEEE80211_RADIOTAP_UHR_USIG2_ELR_B2_B12_STA_ID);
|
||||
IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
OFDM_RX_VECTOR_UHR_ELR_VALIDATE,
|
||||
IEEE80211_RADIOTAP_UHR_USIG2_ELR_B13_B15_VALIDATE);
|
||||
|
||||
if (le32_get_bits(usig_a1, OFDM_RX_FRAME_EHT_USIG1_VALIDATE) &&
|
||||
le32_get_bits(usig_a2, OFDM_RX_VECTOR_UHR_ELR_VALIDATE) == 0xe)
|
||||
usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_VALIDATE_BITS_OK);
|
||||
|
||||
if (!le32_get_bits(usig_a2, OFDM_RX_VECTOR_UHR_ELR_CRC_OK))
|
||||
usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BAD_USIG_CRC);
|
||||
}
|
||||
|
||||
static void iwl_mld_decode_uhr_usig_non_tb(struct iwl_mld_rx_phy_data *phy_data,
|
||||
struct ieee80211_radiotap_eht_usig *usig)
|
||||
{
|
||||
__le32 usig_a1 = phy_data->ntfy->sigs.uhr.usig_a1;
|
||||
__le32 usig_a2 = phy_data->ntfy->sigs.uhr.usig_a2_uhr;
|
||||
|
||||
IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a1,
|
||||
OFDM_RX_FRAME_EHT_USIG1_DISREGARD,
|
||||
IEEE80211_RADIOTAP_UHR_USIG1_MU_B20_B24_DISREGARD);
|
||||
IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a1,
|
||||
OFDM_RX_FRAME_EHT_USIG1_VALIDATE,
|
||||
IEEE80211_RADIOTAP_UHR_USIG1_MU_B25_VALIDATE);
|
||||
IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
OFDM_RX_FRAME_UHR_PPDU_TYPE,
|
||||
IEEE80211_RADIOTAP_UHR_USIG2_MU_B0_B1_PPDU_TYPE);
|
||||
IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
OFDM_RX_FRAME_UHR_COBF_CSR_DISABLE,
|
||||
IEEE80211_RADIOTAP_UHR_USIG2_MU_B2_COBF_COSR);
|
||||
IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
OFDM_RX_FRAME_UHR_PUNC_CHANNEL,
|
||||
IEEE80211_RADIOTAP_UHR_USIG2_MU_B3_B7_PUNCTURED_INFO);
|
||||
IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
OFDM_RX_FRAME_UHR_USIG2_VALIDATE_B8,
|
||||
IEEE80211_RADIOTAP_UHR_USIG2_MU_B8_VALIDATE);
|
||||
IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
OFDM_RX_FRAME_UHR_SIG_MCS,
|
||||
IEEE80211_RADIOTAP_UHR_USIG2_MU_B9_B10_SIG_MCS);
|
||||
IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
OFDM_RX_FRAME_UHR_SIG_SYM_NUM,
|
||||
IEEE80211_RADIOTAP_UHR_USIG2_MU_B11_B15_UHR_SIG_SYMBOLS);
|
||||
|
||||
if (le32_get_bits(usig_a1, OFDM_RX_FRAME_EHT_USIG1_VALIDATE) &&
|
||||
le32_get_bits(usig_a2, OFDM_RX_FRAME_UHR_USIG2_VALIDATE_B8))
|
||||
usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_VALIDATE_BITS_OK);
|
||||
|
||||
if (!le32_get_bits(usig_a2, OFDM_RX_FRAME_UHR_USIG_CRC_OK))
|
||||
usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BAD_USIG_CRC);
|
||||
}
|
||||
|
||||
static void iwl_mld_decode_uhr_usig(struct iwl_mld_rx_phy_data *phy_data,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
u32 he_type = phy_data->rate_n_flags & RATE_MCS_HE_TYPE_MSK;
|
||||
struct ieee80211_radiotap_eht_usig *usig;
|
||||
__le32 usig_a1 = phy_data->ntfy->sigs.uhr.usig_a1;
|
||||
u32 bw;
|
||||
|
||||
usig = iwl_mld_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_EHT_USIG,
|
||||
sizeof(*usig));
|
||||
|
||||
BUILD_BUG_ON(offsetof(typeof(phy_data->ntfy->sigs.uhr), usig_a1) !=
|
||||
offsetof(typeof(phy_data->ntfy->sigs.uhr_elr), usig_a1));
|
||||
BUILD_BUG_ON(offsetof(typeof(phy_data->ntfy->sigs.uhr), usig_a1) !=
|
||||
offsetof(typeof(phy_data->ntfy->sigs.uhr_tb), usig_a1));
|
||||
|
||||
usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL_KNOWN |
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR_KNOWN |
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_VALIDATE_BITS_CHECKED |
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_KNOWN |
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP_KNOWN |
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER_KNOWN);
|
||||
|
||||
#define CHECK_BW(bw) \
|
||||
BUILD_BUG_ON(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_ ## bw ## MHZ != \
|
||||
RATE_MCS_CHAN_WIDTH_ ## bw ## _VAL)
|
||||
CHECK_BW(20);
|
||||
CHECK_BW(40);
|
||||
CHECK_BW(80);
|
||||
CHECK_BW(160);
|
||||
#undef CHECK_BW
|
||||
BUILD_BUG_ON(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_320MHZ_1 !=
|
||||
RATE_MCS_CHAN_WIDTH_320_VAL);
|
||||
bw = u32_get_bits(phy_data->rate_n_flags, RATE_MCS_CHAN_WIDTH_MSK);
|
||||
/* specific handling for 320MHz-1/320MHz-2 */
|
||||
if (bw == RATE_MCS_CHAN_WIDTH_320_VAL)
|
||||
bw += le32_get_bits(usig_a1, OFDM_RX_FRAME_EHT_BW320_SLOT);
|
||||
usig->common |= le32_encode_bits(bw,
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW);
|
||||
|
||||
usig->common |= LE32_DEC_ENC(usig_a1, OFDM_RX_FRAME_ENHANCED_WIFI_UL_FLAG,
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL);
|
||||
usig->common |= LE32_DEC_ENC(usig_a1, OFDM_RX_FRAME_ENHANCED_WIFI_BSS_COLOR,
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR);
|
||||
usig->common |= LE32_DEC_ENC(usig_a1,
|
||||
OFDM_RX_FRAME_ENHANCED_WIFI_TXOP_DURATION,
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP);
|
||||
usig->common |= LE32_DEC_ENC(usig_a1,
|
||||
OFDM_RX_FRAME_ENHANCED_WIFI_VER_ID,
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER);
|
||||
|
||||
switch (he_type) {
|
||||
case RATE_MCS_HE_TYPE_TRIG:
|
||||
iwl_mld_decode_uhr_usig_tb(phy_data, usig);
|
||||
break;
|
||||
case RATE_MCS_HE_TYPE_UHR_ELR:
|
||||
iwl_mld_decode_uhr_usig_elr(phy_data, usig);
|
||||
break;
|
||||
default:
|
||||
iwl_mld_decode_uhr_usig_non_tb(phy_data, usig);
|
||||
break;
|
||||
}
|
||||
|
||||
iwl_mld_check_bad_usig_crc(rx_status, usig);
|
||||
}
|
||||
|
||||
static void iwl_mld_decode_uhr_tb(struct iwl_mld_rx_phy_data *phy_data,
|
||||
struct ieee80211_rx_status *rx_status,
|
||||
struct ieee80211_radiotap_uhr *uhr)
|
||||
{
|
||||
if (!(phy_data->ntfy->flags & IWL_SNIF_FLAG_VALID_TB_RX))
|
||||
return;
|
||||
|
||||
uhr->known |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_KNOWN_DRU_RRU_ALLOC_TB_FMT |
|
||||
IEEE80211_RADIOTAP_UHR_KNOWN_LDPC_EXTRA_SYMBOL_SEGMENT |
|
||||
IEEE80211_RADIOTAP_UHR_KNOWN_PRE_FEC_PADDING_FACTOR |
|
||||
IEEE80211_RADIOTAP_UHR_KNOWN_PE_DISAMBIGUITY |
|
||||
IEEE80211_RADIOTAP_UHR_KNOWN_NUMBER_OF_UHR_LTF_SYMBOLS |
|
||||
IEEE80211_RADIOTAP_UHR_KNOWN_PRI80_CHAN_POS);
|
||||
|
||||
uhr->data[8] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr_tb.tb_rx0,
|
||||
OFDM_UCODE_TRIG_BASE_PS160,
|
||||
IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_ALLOC_TB_FMT_PS_160);
|
||||
uhr->data[8] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr_tb.tb_rx1,
|
||||
OFDM_UCODE_TRIG_BASE_RX_RU,
|
||||
IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_ALLOC_TB_FMT_B0 |
|
||||
IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_ALLOC_TB_FMT_B7_B1);
|
||||
uhr->data[8] |= le32_encode_bits(!le32_get_bits(phy_data->ntfy->sigs.uhr_tb.tb_rx0,
|
||||
OFDM_UCODE_RX_IS_DRU),
|
||||
IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_INDICATION);
|
||||
|
||||
uhr->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr_tb.tb_rx1,
|
||||
OFDM_UCODE_TRIG_BASE_RX_CODING_EXTRA_SYM,
|
||||
IEEE80211_RADIOTAP_UHR_DATA0_LDPC_EXTRA_SYMBOL_SEGMENT);
|
||||
uhr->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr_tb.tb_rx1,
|
||||
OFDM_UCODE_TRIG_BASE_RX_PRE_FEC_PAD_FACTOR,
|
||||
IEEE80211_RADIOTAP_UHR_DATA0_PRE_FEC_PADDING_FACTOR);
|
||||
uhr->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr_tb.tb_rx1,
|
||||
OFDM_UCODE_TRIG_BASE_RX_PE_DISAMBIG,
|
||||
IEEE80211_RADIOTAP_UHR_DATA0_PE_DISAMBIGUITY);
|
||||
uhr->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr_tb.tb_rx1,
|
||||
OFDM_UCODE_TRIG_BASE_RX_NUM_OF_LTF_SYM,
|
||||
IEEE80211_RADIOTAP_UHR_DATA0_NUMBER_OF_LTF_SYMBOLS);
|
||||
uhr->data[1] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr_tb.tb_rx0,
|
||||
OFDM_UCODE_TRIG_BASE_RX_RU_P80,
|
||||
IEEE80211_RADIOTAP_UHR_DATA1_PRI80_CHAN_POS);
|
||||
|
||||
iwl_mld_eht_uhr_set_ru_alloc(rx_status,
|
||||
le32_get_bits(phy_data->ntfy->sigs.uhr_tb.tb_rx1,
|
||||
OFDM_UCODE_TRIG_BASE_RX_RU),
|
||||
true);
|
||||
}
|
||||
|
||||
static void iwl_mld_uhr_decode_user_ru(struct iwl_mld_rx_phy_data *phy_data,
|
||||
struct ieee80211_radiotap_uhr *uhr)
|
||||
{
|
||||
u32 phy_bw = phy_data->rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK;
|
||||
|
||||
if (!(phy_data->ntfy->flags & IWL_SNIF_FLAG_VALID_RU))
|
||||
return;
|
||||
|
||||
#define __IWL_MLD_ENC_UHR_RU(rt_data, rt_ru, fw_data, fw_ru) \
|
||||
uhr->data[(rt_data)] |= \
|
||||
(cpu_to_le32(IEEE80211_RADIOTAP_UHR_DATA ## rt_data ## _RU_ALLOC_CC_ ## rt_ru ## _KNOWN) | \
|
||||
LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.cmn[fw_data], \
|
||||
OFDM_RX_FRAME_EHT_RU_ALLOC_ ## fw_data ## _ ## fw_ru, \
|
||||
IEEE80211_RADIOTAP_UHR_DATA ## rt_data ## _RU_ALLOC_CC_ ## rt_ru))
|
||||
|
||||
#define _IWL_MLD_ENC_UHR_RU(rt_data, rt_ru, fw_data, fw_ru) \
|
||||
__IWL_MLD_ENC_UHR_RU(rt_data, rt_ru, fw_data, fw_ru)
|
||||
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_1_1_1 1
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_2_1_1 2
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_1_1_2 2
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_2_1_2 2
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_1_2_1 3
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_2_2_1 3
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_1_2_2 3
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_2_2_2 4
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_1_2_3 4
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_2_2_3 4
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_1_2_4 5
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_2_2_4 5
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_1_2_5 5
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_2_2_5 6
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_1_2_6 6
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_2_2_6 6
|
||||
|
||||
#define IWL_RX_RU_DATA_A1 0
|
||||
#define IWL_RX_RU_DATA_A2 0
|
||||
#define IWL_RX_RU_DATA_A3 0
|
||||
#define IWL_RX_RU_DATA_A4 4
|
||||
#define IWL_RX_RU_DATA_B1 1
|
||||
#define IWL_RX_RU_DATA_B2 1
|
||||
#define IWL_RX_RU_DATA_B3 1
|
||||
#define IWL_RX_RU_DATA_B4 4
|
||||
#define IWL_RX_RU_DATA_C1 2
|
||||
#define IWL_RX_RU_DATA_C2 2
|
||||
#define IWL_RX_RU_DATA_C3 2
|
||||
#define IWL_RX_RU_DATA_C4 5
|
||||
#define IWL_RX_RU_DATA_D1 3
|
||||
#define IWL_RX_RU_DATA_D2 3
|
||||
#define IWL_RX_RU_DATA_D3 3
|
||||
#define IWL_RX_RU_DATA_D4 5
|
||||
|
||||
#define IWL_MLD_ENC_UHR_RU(rt_ru, fw_ru) \
|
||||
_IWL_MLD_ENC_UHR_RU(IEEE80211_RADIOTAP_RU_DATA_ ## rt_ru, \
|
||||
rt_ru, \
|
||||
IWL_RX_RU_DATA_ ## fw_ru, \
|
||||
fw_ru)
|
||||
|
||||
/*
|
||||
* Hardware labels the content channels/RU allocation values
|
||||
* as follows:
|
||||
*
|
||||
* Content Channel 1 Content Channel 2
|
||||
* 20 MHz: A1
|
||||
* 40 MHz: A1 B1
|
||||
* 80 MHz: A1 C1 B1 D1
|
||||
* 160 MHz: A1 C1 A2 C2 B1 D1 B2 D2
|
||||
* 320 MHz: A1 C1 A2 C2 A3 C3 A4 C4 B1 D1 B2 D2 B3 D3 B4 D4
|
||||
*/
|
||||
|
||||
switch (phy_bw) {
|
||||
case RATE_MCS_CHAN_WIDTH_320:
|
||||
/* content channel 1 */
|
||||
IWL_MLD_ENC_UHR_RU(1_2_3, A3);
|
||||
IWL_MLD_ENC_UHR_RU(1_2_4, C3);
|
||||
IWL_MLD_ENC_UHR_RU(1_2_5, A4);
|
||||
IWL_MLD_ENC_UHR_RU(1_2_6, C4);
|
||||
/* content channel 2 */
|
||||
IWL_MLD_ENC_UHR_RU(2_2_3, B3);
|
||||
IWL_MLD_ENC_UHR_RU(2_2_4, D3);
|
||||
IWL_MLD_ENC_UHR_RU(2_2_5, B4);
|
||||
IWL_MLD_ENC_UHR_RU(2_2_6, D4);
|
||||
fallthrough;
|
||||
case RATE_MCS_CHAN_WIDTH_160:
|
||||
/* content channel 1 */
|
||||
IWL_MLD_ENC_UHR_RU(1_2_1, A2);
|
||||
IWL_MLD_ENC_UHR_RU(1_2_2, C2);
|
||||
/* content channel 2 */
|
||||
IWL_MLD_ENC_UHR_RU(2_2_1, B2);
|
||||
IWL_MLD_ENC_UHR_RU(2_2_2, D2);
|
||||
fallthrough;
|
||||
case RATE_MCS_CHAN_WIDTH_80:
|
||||
/* content channel 1 */
|
||||
IWL_MLD_ENC_UHR_RU(1_1_2, C1);
|
||||
/* content channel 2 */
|
||||
IWL_MLD_ENC_UHR_RU(2_1_2, D1);
|
||||
fallthrough;
|
||||
case RATE_MCS_CHAN_WIDTH_40:
|
||||
/* content channel 2 */
|
||||
IWL_MLD_ENC_UHR_RU(2_1_1, B1);
|
||||
fallthrough;
|
||||
case RATE_MCS_CHAN_WIDTH_20:
|
||||
/* content channel 1 */
|
||||
IWL_MLD_ENC_UHR_RU(1_1_1, A1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mld_decode_uhr_non_tb(struct iwl_mld_rx_phy_data *phy_data,
|
||||
struct ieee80211_rx_status *rx_status,
|
||||
struct ieee80211_radiotap_uhr *uhr)
|
||||
{
|
||||
__le32 usig_a1 = phy_data->ntfy->sigs.uhr.usig_a1;
|
||||
__le32 usig_a2 = phy_data->ntfy->sigs.uhr.usig_a2_uhr;
|
||||
bool ofdma;
|
||||
|
||||
uhr->known |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_KNOWN_SPATIAL_REUSE |
|
||||
IEEE80211_RADIOTAP_UHR_KNOWN_NUMBER_OF_UHR_LTF_SYMBOLS |
|
||||
IEEE80211_RADIOTAP_UHR_KNOWN_LDPC_EXTRA_SYMBOL_SEGMENT |
|
||||
IEEE80211_RADIOTAP_UHR_KNOWN_PRE_FEC_PADDING_FACTOR |
|
||||
IEEE80211_RADIOTAP_UHR_KNOWN_PE_DISAMBIGUITY |
|
||||
IEEE80211_RADIOTAP_UHR_KNOWN_PRI80_CHAN_POS);
|
||||
|
||||
/*
|
||||
* TB isn't handled here, so uplink can't be OFDMA.
|
||||
* Downlink OFDMA is PPDU type 0.
|
||||
*/
|
||||
ofdma = !(usig_a1 & cpu_to_le32(OFDM_RX_FRAME_ENHANCED_WIFI_UL_FLAG)) &&
|
||||
le32_get_bits(usig_a2, OFDM_RX_FRAME_UHR_PPDU_TYPE) == 0;
|
||||
|
||||
if (ofdma) {
|
||||
/* All RU allocation size/index is in TB format */
|
||||
uhr->known |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_KNOWN_DRU_RRU_ALLOC_TB_FMT);
|
||||
/* downlink is never DRU */
|
||||
uhr->data[8] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b2,
|
||||
OFDM_RX_FRAME_UHR_STA_RU_PS160,
|
||||
IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_ALLOC_TB_FMT_PS_160);
|
||||
uhr->data[8] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b2,
|
||||
OFDM_RX_FRAME_UHR_STA_RU,
|
||||
IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_ALLOC_TB_FMT_B0 |
|
||||
IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_ALLOC_TB_FMT_B7_B1);
|
||||
uhr->data[8] |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_INDICATION);
|
||||
} else {
|
||||
uhr->known |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_KNOWN_NUMBER_OF_NON_OFDMA_USERS |
|
||||
IEEE80211_RADIOTAP_UHR_KNOWN_INTERFERENCE_MITIGATION);
|
||||
uhr->data[7] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b1,
|
||||
OFDM_RX_FRAME_UHR_NUM_OF_USERS,
|
||||
IEEE80211_RADIOTAP_UHR_DATA7_NUMBER_OF_NON_OFDMA_USERS);
|
||||
if (!(phy_data->ntfy->sigs.uhr.b1 & cpu_to_le32(OFDM_RX_FRAME_UHR_IM_DISABLE)))
|
||||
uhr->data[7] |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_DATA7_INTERFERENCE_MITIGATION);
|
||||
}
|
||||
|
||||
uhr->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b1,
|
||||
OFDM_RX_FRAME_UHR_SPATIAL_REUSE,
|
||||
IEEE80211_RADIOTAP_UHR_DATA0_SPATIAL_REUSE);
|
||||
uhr->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b1,
|
||||
OFDM_RX_FRAME_UHR_NUM_OF_LTF_SYM,
|
||||
IEEE80211_RADIOTAP_UHR_DATA0_NUMBER_OF_LTF_SYMBOLS);
|
||||
|
||||
uhr->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b1,
|
||||
OFDM_RX_FRAME_UHR_CODING_EXTRA_SYM,
|
||||
IEEE80211_RADIOTAP_UHR_DATA0_LDPC_EXTRA_SYMBOL_SEGMENT);
|
||||
uhr->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b1,
|
||||
OFDM_RX_FRAME_UHR_PE_A_FACTOR,
|
||||
IEEE80211_RADIOTAP_UHR_DATA0_PRE_FEC_PADDING_FACTOR);
|
||||
uhr->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b1,
|
||||
OFDM_RX_FRAME_UHR_PE_DISAMBIGUITY,
|
||||
IEEE80211_RADIOTAP_UHR_DATA0_PE_DISAMBIGUITY);
|
||||
uhr->data[1] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b2,
|
||||
OFDM_RX_FRAME_UHR_STA_RU_P80,
|
||||
IEEE80211_RADIOTAP_UHR_DATA1_PRI80_CHAN_POS);
|
||||
|
||||
iwl_mld_uhr_decode_user_ru(phy_data, uhr);
|
||||
|
||||
iwl_mld_eht_uhr_set_ru_alloc(rx_status,
|
||||
le32_get_bits(phy_data->ntfy->sigs.uhr.b2,
|
||||
OFDM_RX_FRAME_UHR_STA_RU),
|
||||
true);
|
||||
|
||||
if (!phy_data->with_data)
|
||||
return;
|
||||
|
||||
uhr->user[0].known |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_USER_KNOWN_STA_ID);
|
||||
uhr->user[0].info |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.user_id,
|
||||
OFDM_RX_FRAME_UHR_USER_FIELD_ID,
|
||||
IEEE80211_RADIOTAP_UHR_USER_INFO_STA_ID);
|
||||
|
||||
/* don't report UEQM for downlink non-OFDMA MU-MIMO allocations */
|
||||
if (!(usig_a1 & cpu_to_le32(OFDM_RX_FRAME_ENHANCED_WIFI_UL_FLAG)) &&
|
||||
le32_get_bits(usig_a2, OFDM_RX_FRAME_UHR_PPDU_TYPE) == 2)
|
||||
return;
|
||||
|
||||
uhr->user[0].known |=
|
||||
cpu_to_le32(IEEE80211_RADIOTAP_UHR_USER_KNOWN_UEQM);
|
||||
uhr->user[0].info |=
|
||||
LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b2,
|
||||
OFDM_RX_FRAME_UHR_UEQM,
|
||||
IEEE80211_RADIOTAP_UHR_USER_INFO_UEQM);
|
||||
|
||||
if (uhr->user[0].info & cpu_to_le32(IEEE80211_RADIOTAP_UHR_USER_INFO_UEQM)) {
|
||||
uhr->user[0].known |=
|
||||
cpu_to_le32(IEEE80211_RADIOTAP_UHR_USER_KNOWN_UEQM_PATTERN);
|
||||
uhr->user[0].info |=
|
||||
LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b2,
|
||||
OFDM_RX_FRAME_UHR_UEQM_PATTERN,
|
||||
IEEE80211_RADIOTAP_UHR_USER_INFO_UEQM_PATTERN);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mld_decode_uhr_elr_phy_data(struct iwl_mld_rx_phy_data *phy_data,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_rx_status *rx_status)
|
||||
{
|
||||
struct ieee80211_radiotap_uhr_elr *elr;
|
||||
__le32 elr1 = phy_data->ntfy->sigs.uhr_elr.uhr_sig_elr1;
|
||||
__le32 elr2 = phy_data->ntfy->sigs.uhr_elr.uhr_sig_elr2;
|
||||
|
||||
elr = iwl_mld_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_UHR_ELR,
|
||||
sizeof(*elr));
|
||||
|
||||
elr->known |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_ELR_KNOWN_VERSION_ID |
|
||||
IEEE80211_RADIOTAP_UHR_ELR_KNOWN_UL_DL |
|
||||
IEEE80211_RADIOTAP_UHR_ELR_KNOWN_MCS |
|
||||
IEEE80211_RADIOTAP_UHR_ELR_KNOWN_CODING |
|
||||
IEEE80211_RADIOTAP_UHR_ELR_KNOWN_LENGTH |
|
||||
IEEE80211_RADIOTAP_UHR_ELR_KNOWN_LDPC_EXTRA_OFDM_SYM |
|
||||
IEEE80211_RADIOTAP_UHR_ELR_KNOWN_STA_ID |
|
||||
IEEE80211_RADIOTAP_UHR_ELR_KNOWN_DISREGARD |
|
||||
IEEE80211_RADIOTAP_UHR_ELR_KNOWN_SIG_1_CRC_CHECKED |
|
||||
IEEE80211_RADIOTAP_UHR_ELR_KNOWN_SIG_2_CRC_CHECKED |
|
||||
IEEE80211_RADIOTAP_UHR_ELR_KNOWN_MARK_BSS_COLOR);
|
||||
elr->sig1 |= LE32_DEC_ENC(elr1, OFDM_RX_VECTOR_UHR_ELR_VER_ID,
|
||||
IEEE80211_RADIOTAP_UHR_ELR_SIG1_VERSION_ID);
|
||||
elr->sig1 |= LE32_DEC_ENC(elr1, OFDM_RX_VECTOR_UHR_ELR_UPLINK_FLAG,
|
||||
IEEE80211_RADIOTAP_UHR_ELR_SIG1_UL_DL);
|
||||
elr->sig1 |= LE32_DEC_ENC(elr1, OFDM_RX_VECTOR_UHR_ELR_MCS,
|
||||
IEEE80211_RADIOTAP_UHR_ELR_SIG1_MCS);
|
||||
elr->sig1 |= LE32_DEC_ENC(elr1, OFDM_RX_VECTOR_UHR_ELR_CODING,
|
||||
IEEE80211_RADIOTAP_UHR_ELR_SIG1_CODING);
|
||||
elr->sig1 |= LE32_DEC_ENC(elr1, OFDM_RX_VECTOR_UHR_ELR_LENGTH_IN_SYM,
|
||||
IEEE80211_RADIOTAP_UHR_ELR_SIG1_LENGTH);
|
||||
elr->sig1 |= LE32_DEC_ENC(elr1, OFDM_RX_VECTOR_UHR_ELR_CODING_EXTRA_SYM,
|
||||
IEEE80211_RADIOTAP_UHR_ELR_SIG1_LDPC_EXTRA_OFDM_SYM);
|
||||
elr->sig1 |= LE32_DEC_ENC(elr1, OFDM_RX_VECTOR_UHR_ELR_SIG1_CRC_OK,
|
||||
IEEE80211_RADIOTAP_UHR_ELR_SIG1_CRC_VALID);
|
||||
|
||||
elr->sig2 |= LE32_DEC_ENC(elr1, OFDM_RX_VECTOR_UHR_ELR_STA_ID,
|
||||
IEEE80211_RADIOTAP_UHR_ELR_SIG2_STA_ID);
|
||||
elr->sig2 |= LE32_DEC_ENC(elr1, OFDM_RX_VECTOR_UHR_ELR_DISREGARD,
|
||||
IEEE80211_RADIOTAP_UHR_ELR_SIG2_DISREGARD);
|
||||
|
||||
elr->sig2 |= LE32_DEC_ENC(elr2, OFDM_RX_VECTOR_UHR_ELR_SIG2_CRC_OK,
|
||||
IEEE80211_RADIOTAP_UHR_ELR_SIG2_CRC_VALID);
|
||||
|
||||
elr->mark |= LE32_DEC_ENC(elr2, OFDM_RX_VECTOR_UHR_ELR_MARK_BSS_COLOR,
|
||||
IEEE80211_RADIOTAP_UHR_ELR_MARK_BSS_COLOR);
|
||||
}
|
||||
|
||||
static void iwl_mld_decode_uhr_phy_data(struct iwl_mld_rx_phy_data *phy_data,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
u32 rate_n_flags = phy_data->rate_n_flags;
|
||||
u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
|
||||
struct ieee80211_radiotap_uhr *uhr;
|
||||
size_t uhr_len;
|
||||
|
||||
if (he_type == RATE_MCS_HE_TYPE_UHR_ELR) {
|
||||
iwl_mld_decode_uhr_elr_phy_data(phy_data, skb, rx_status);
|
||||
return;
|
||||
}
|
||||
|
||||
/* space for one user_info if we captured data */
|
||||
uhr_len = struct_size(uhr, user, (phy_data->with_data ? 1 : 0));
|
||||
|
||||
uhr = iwl_mld_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_UHR, uhr_len);
|
||||
|
||||
uhr->known |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_KNOWN_GI_LTF_SIZE);
|
||||
uhr->data[0] |= le32_encode_bits(u32_get_bits(rate_n_flags,
|
||||
RATE_MCS_HE_GI_LTF_MSK),
|
||||
IEEE80211_RADIOTAP_UHR_DATA0_GI_LTF_SIZE);
|
||||
|
||||
if (phy_data->with_data) {
|
||||
uhr->user[0].known |=
|
||||
cpu_to_le32(IEEE80211_RADIOTAP_UHR_USER_KNOWN_MCS |
|
||||
IEEE80211_RADIOTAP_UHR_USER_KNOWN_NSS |
|
||||
IEEE80211_RADIOTAP_UHR_USER_KNOWN_BF |
|
||||
IEEE80211_RADIOTAP_UHR_USER_KNOWN_2X_LDPC |
|
||||
IEEE80211_RADIOTAP_UHR_USER_KNOWN_CODING |
|
||||
IEEE80211_RADIOTAP_UHR_USER_KNOWN_USER_CAPTURED);
|
||||
|
||||
uhr->user[0].info |=
|
||||
le32_encode_bits(u32_get_bits(rate_n_flags,
|
||||
RATE_MCS_CODE_MSK),
|
||||
IEEE80211_RADIOTAP_UHR_USER_INFO_MCS);
|
||||
uhr->user[0].info |=
|
||||
le32_encode_bits(u32_get_bits(rate_n_flags,
|
||||
RATE_MCS_NSS_MSK),
|
||||
IEEE80211_RADIOTAP_UHR_USER_INFO_NSS);
|
||||
|
||||
if (phy_data->phy_info & IWL_RX_MPDU_PHY_2X_LDPC)
|
||||
uhr->user[0].info |=
|
||||
cpu_to_le32(IEEE80211_RADIOTAP_UHR_USER_INFO_2X_LDPC);
|
||||
|
||||
if (rate_n_flags & RATE_MCS_BF_MSK)
|
||||
uhr->user[0].info |=
|
||||
cpu_to_le32(IEEE80211_RADIOTAP_UHR_USER_INFO_BF);
|
||||
|
||||
if (rate_n_flags & RATE_MCS_LDPC_MSK)
|
||||
uhr->user[0].info |=
|
||||
cpu_to_le32(IEEE80211_RADIOTAP_UHR_USER_INFO_CODING);
|
||||
}
|
||||
|
||||
if (he_type == RATE_MCS_HE_TYPE_TRIG)
|
||||
iwl_mld_decode_uhr_tb(phy_data, rx_status, uhr);
|
||||
else
|
||||
iwl_mld_decode_uhr_non_tb(phy_data, rx_status, uhr);
|
||||
}
|
||||
|
||||
static void iwl_mld_rx_uhr(struct iwl_mld *mld, struct sk_buff *skb,
|
||||
struct iwl_mld_rx_phy_data *phy_data)
|
||||
{
|
||||
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
u8 gi, ltf;
|
||||
|
||||
/* the LTF size is reported from the PHY data, only the GI is needed */
|
||||
ltf = iwl_mld_decode_eht_uhr_gi_ltf(phy_data->rate_n_flags, &gi);
|
||||
if (ltf != IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN)
|
||||
rx_status->uhr.gi = gi;
|
||||
|
||||
if (likely(!phy_data->ntfy))
|
||||
return;
|
||||
|
||||
iwl_mld_decode_uhr_usig(phy_data, skb);
|
||||
iwl_mld_decode_uhr_phy_data(phy_data, skb);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
static void iwl_mld_add_rtap_sniffer_config(struct iwl_mld *mld,
|
||||
struct sk_buff *skb)
|
||||
|
|
@ -1506,19 +2089,42 @@ static void iwl_mld_rx_fill_status(struct iwl_mld *mld, int link_id,
|
|||
|
||||
iwl_mld_set_rx_rate(mld, phy_data, rx_status);
|
||||
|
||||
/* must be before HE data (radiotap field order) */
|
||||
if (format == RATE_MCS_MOD_TYPE_VHT)
|
||||
switch (format) {
|
||||
case RATE_MCS_MOD_TYPE_CCK:
|
||||
/* nothing to see here, see note below */
|
||||
break;
|
||||
case RATE_MCS_MOD_TYPE_LEGACY_OFDM:
|
||||
/*
|
||||
* Technically legacy CCK/OFDM frames don't have an L-SIG
|
||||
* since that's the compat format for HT (non-greenfield)
|
||||
* and up. However, it's meant to be compatible with the
|
||||
* LENGTH and RATE fields in Clause 17 and 18 OFDM frames
|
||||
* so include the field for any non-CCK frame. For CCK it
|
||||
* cannot work, since the LENGTH field for them is 16-bit
|
||||
* and the radiotap field only has 12 bits.
|
||||
*/
|
||||
iwl_mld_decode_lsig(skb, phy_data);
|
||||
break;
|
||||
case RATE_MCS_MOD_TYPE_HT:
|
||||
iwl_mld_decode_lsig(skb, phy_data);
|
||||
break;
|
||||
case RATE_MCS_MOD_TYPE_VHT:
|
||||
iwl_mld_rx_vht(skb, phy_data);
|
||||
|
||||
/* must be before L-SIG data (radiotap field order) */
|
||||
if (format == RATE_MCS_MOD_TYPE_HE)
|
||||
iwl_mld_decode_lsig(skb, phy_data);
|
||||
break;
|
||||
case RATE_MCS_MOD_TYPE_HE:
|
||||
iwl_mld_rx_he(skb, phy_data);
|
||||
|
||||
iwl_mld_decode_lsig(skb, phy_data);
|
||||
|
||||
/* TLVs - must be after radiotap fixed fields */
|
||||
if (format == RATE_MCS_MOD_TYPE_EHT)
|
||||
iwl_mld_decode_lsig(skb, phy_data);
|
||||
break;
|
||||
case RATE_MCS_MOD_TYPE_EHT:
|
||||
iwl_mld_decode_lsig(skb, phy_data);
|
||||
iwl_mld_rx_eht(mld, skb, phy_data);
|
||||
break;
|
||||
case RATE_MCS_MOD_TYPE_UHR:
|
||||
iwl_mld_decode_lsig(skb, phy_data);
|
||||
iwl_mld_rx_uhr(mld, skb, phy_data);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (unlikely(mld->monitor.on)) {
|
||||
|
|
@ -2281,7 +2887,7 @@ void iwl_mld_handle_rsc_notif(struct iwl_mld *mld,
|
|||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
static void iwl_mld_no_data_rx(struct iwl_mld *mld,
|
||||
struct napi_struct *napi,
|
||||
struct napi_struct *napi, bool no_mpdu,
|
||||
struct iwl_rx_phy_air_sniffer_ntfy *ntfy)
|
||||
{
|
||||
struct ieee80211_rx_status *rx_status;
|
||||
|
|
@ -2308,9 +2914,24 @@ static void iwl_mld_no_data_rx(struct iwl_mld *mld,
|
|||
|
||||
switch (ntfy->status) {
|
||||
case IWL_SNIF_STAT_PLCP_RX_OK:
|
||||
/* we only get here with sounding PPDUs */
|
||||
rx_status->zero_length_psdu_type =
|
||||
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_SOUNDING;
|
||||
/*
|
||||
* For trigger-based PPDUs, the firmware decodes the PHY header
|
||||
* and releases with a good status only if the frame was for the
|
||||
* configured AID (the bad status depends on the version), and
|
||||
* also only sets IWL_SNIF_FLAG_VALID_TB_RX if receiving for the
|
||||
* configured AID.
|
||||
*
|
||||
* So trigger-based PHY notifications without MPDU are sounding
|
||||
* PPDUs, while other releases without MPDU are some kind of
|
||||
* error after a good PHY header - don't flag failed PLCP in
|
||||
* this case, but release as unspecified zero-len reason.
|
||||
*/
|
||||
if (no_mpdu && !(ntfy->flags & IWL_SNIF_FLAG_VALID_TB_RX))
|
||||
rx_status->zero_length_psdu_type =
|
||||
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_VENDOR;
|
||||
else
|
||||
rx_status->zero_length_psdu_type =
|
||||
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_SOUNDING;
|
||||
break;
|
||||
case IWL_SNIF_STAT_AID_NOT_FOR_US:
|
||||
rx_status->zero_length_psdu_type =
|
||||
|
|
@ -2321,6 +2942,7 @@ static void iwl_mld_no_data_rx(struct iwl_mld *mld,
|
|||
case IWL_SNIF_STAT_PLCP_RX_SIGB_ERR:
|
||||
case IWL_SNIF_STAT_UNKNOWN_ERROR:
|
||||
default:
|
||||
/* some kind of PLCP error - no details from FW */
|
||||
rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC;
|
||||
fallthrough;
|
||||
case IWL_SNIF_STAT_UNEXPECTED_TB:
|
||||
|
|
@ -2364,12 +2986,9 @@ void iwl_mld_handle_phy_air_sniffer_notif(struct iwl_mld *mld,
|
|||
"invalid air sniffer notification size\n"))
|
||||
return;
|
||||
|
||||
/* check if there's an old one to release as errored */
|
||||
if (mld->monitor.phy.valid && !mld->monitor.phy.used) {
|
||||
/* didn't capture data, so override status */
|
||||
mld->monitor.phy.data.status = IWL_SNIF_STAT_AID_NOT_FOR_US;
|
||||
iwl_mld_no_data_rx(mld, napi, &mld->monitor.phy.data);
|
||||
}
|
||||
/* check if there's an old one to release */
|
||||
if (mld->monitor.phy.valid && !mld->monitor.phy.used)
|
||||
iwl_mld_no_data_rx(mld, napi, true, &mld->monitor.phy.data);
|
||||
|
||||
/* old data is no longer valid now */
|
||||
mld->monitor.phy.valid = false;
|
||||
|
|
@ -2403,10 +3022,17 @@ void iwl_mld_handle_phy_air_sniffer_notif(struct iwl_mld *mld,
|
|||
!le32_get_bits(ntfy->sigs.eht.sig2,
|
||||
OFDM_RX_FRAME_EHT_NUM_OF_DATA_SYM);
|
||||
break;
|
||||
case RATE_MCS_MOD_TYPE_UHR:
|
||||
if (he_type == RATE_MCS_HE_TYPE_TRIG ||
|
||||
he_type == RATE_MCS_HE_TYPE_UHR_ELR)
|
||||
break;
|
||||
is_ndp = !le32_get_bits(ntfy->sigs.uhr.sig2,
|
||||
OFDM_RX_UHR_NUM_OF_DATA_SYM);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ntfy->status != IWL_SNIF_STAT_PLCP_RX_OK || is_ndp) {
|
||||
iwl_mld_no_data_rx(mld, napi, ntfy);
|
||||
iwl_mld_no_data_rx(mld, napi, false, ntfy);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1992,7 +1992,14 @@ void iwl_mld_int_mlo_scan(struct iwl_mld *mld, struct ieee80211_vif *vif)
|
|||
void iwl_mld_handle_scan_iter_complete_notif(struct iwl_mld *mld,
|
||||
struct iwl_rx_packet *pkt)
|
||||
{
|
||||
struct iwl_umac_scan_iter_complete_notif *notif = (void *)pkt->data;
|
||||
/*
|
||||
* The v3 notification is a superset of v2, so the fields that are
|
||||
* common to both versions can always be read from the v3 layout.
|
||||
*/
|
||||
const struct iwl_umac_scan_iter_complete_notif *notif =
|
||||
(const void *)pkt->data;
|
||||
u8 notif_ver = iwl_fw_lookup_notif_ver(mld->fw, LEGACY_GROUP,
|
||||
SCAN_ITERATION_COMPLETE_UMAC, 2);
|
||||
u32 uid = __le32_to_cpu(notif->uid);
|
||||
|
||||
if (IWL_FW_CHECK(mld, uid >= ARRAY_SIZE(mld->scan.uid_status),
|
||||
|
|
@ -2006,6 +2013,12 @@ void iwl_mld_handle_scan_iter_complete_notif(struct iwl_mld *mld,
|
|||
"UMAC Scan iteration complete: status=0x%x scanned_channels=%d\n",
|
||||
notif->status, notif->scanned_channels);
|
||||
|
||||
if (notif_ver >= 3)
|
||||
IWL_DEBUG_SCAN(mld,
|
||||
"UMAC Scan iteration complete: EBS=%s, EBS channel status=0x%llx\n",
|
||||
iwl_mld_scan_ebs_status_str(notif->ebs_status),
|
||||
le64_to_cpu(notif->ebs_channel_status));
|
||||
|
||||
if (mld->scan.pass_all_sched_res == SCHED_SCAN_PASS_ALL_STATE_FOUND) {
|
||||
IWL_DEBUG_SCAN(mld, "Pass all scheduled scan results found\n");
|
||||
ieee80211_sched_scan_results(mld->hw);
|
||||
|
|
@ -2260,6 +2273,7 @@ void iwl_mld_handle_channel_survey_notif(struct iwl_mld *mld,
|
|||
/* Times are all in ms */
|
||||
info->time = le32_to_cpu(notif->active_time);
|
||||
info->time_busy = le32_to_cpu(notif->busy_time);
|
||||
info->time_rx = le32_to_cpu(notif->rx_time);
|
||||
info->noise =
|
||||
iwl_average_neg_dbm(notif->noise, ARRAY_SIZE(notif->noise));
|
||||
}
|
||||
|
|
@ -2308,9 +2322,11 @@ int iwl_mld_mac80211_get_survey(struct ieee80211_hw *hw, int idx,
|
|||
/* Found (the next) channel to report */
|
||||
survey->channel = &sband->channels[per_band_idx];
|
||||
survey->filled = SURVEY_INFO_TIME |
|
||||
SURVEY_INFO_TIME_BUSY;
|
||||
SURVEY_INFO_TIME_BUSY |
|
||||
SURVEY_INFO_TIME_RX;
|
||||
survey->time = info->time;
|
||||
survey->time_busy = info->time_busy;
|
||||
survey->time_rx = info->time_rx;
|
||||
survey->noise = info->noise;
|
||||
if (survey->noise < 0)
|
||||
survey->filled |= SURVEY_INFO_NOISE_DBM;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
* Copyright (C) 2024-2026 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_mld_scan_h__
|
||||
#define __iwl_mld_scan_h__
|
||||
|
|
@ -151,11 +151,13 @@ struct iwl_mld_scan {
|
|||
*
|
||||
* @time: time in ms the radio was on the channel
|
||||
* @time_busy: time in ms the channel was sensed busy
|
||||
* @time_rx: time in ms the channel was sensed to carry Wi-Fi frames
|
||||
* @noise: channel noise in dBm
|
||||
*/
|
||||
struct iwl_mld_survey_channel {
|
||||
u32 time;
|
||||
u32 time_busy;
|
||||
u32 time_rx;
|
||||
s8 noise;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -465,8 +465,8 @@ int iwl_mld_add_modify_sta_cmd(struct iwl_mld *mld,
|
|||
struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta);
|
||||
struct iwl_sta_cfg_cmd cmd = {};
|
||||
int fw_id = iwl_mld_fw_sta_id_from_link_sta(mld, link_sta);
|
||||
bool is_6ghz, uora_exists;
|
||||
u32 link_mask;
|
||||
bool is_6ghz;
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
|
|
@ -479,7 +479,6 @@ int iwl_mld_add_modify_sta_cmd(struct iwl_mld *mld,
|
|||
return -EINVAL;
|
||||
|
||||
is_6ghz = false;
|
||||
uora_exists = false;
|
||||
|
||||
link_mask = iwl_mld_get_nan_link_mask(mld);
|
||||
} else {
|
||||
|
|
@ -495,7 +494,6 @@ int iwl_mld_add_modify_sta_cmd(struct iwl_mld *mld,
|
|||
|
||||
link_mask = BIT(mld_link->fw_id);
|
||||
is_6ghz = link->chanreq.oper.chan->band == NL80211_BAND_6GHZ;
|
||||
uora_exists = link->uora_exists;
|
||||
}
|
||||
|
||||
cmd.sta_id = cpu_to_le32(fw_id);
|
||||
|
|
@ -554,9 +552,6 @@ int iwl_mld_add_modify_sta_cmd(struct iwl_mld *mld,
|
|||
}
|
||||
|
||||
if (link_sta->he_cap.has_he) {
|
||||
cmd.trig_rnd_alloc =
|
||||
cpu_to_le32(uora_exists ? 1 : 0);
|
||||
|
||||
/* PPE Thresholds */
|
||||
iwl_mld_fill_pkt_ext(mld, link_sta, &cmd.pkt_ext);
|
||||
|
||||
|
|
|
|||
|
|
@ -43,12 +43,17 @@ iwl_mld_fill_stats_from_oper_notif(struct iwl_mld *mld,
|
|||
const struct iwl_stats_ntfy_per_sta *per_sta;
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
struct iwl_mld_link_sta *mld_link_sta;
|
||||
u8 notif_ver = iwl_fw_lookup_notif_ver(mld->fw, STATISTICS_GROUP,
|
||||
STATISTICS_OPER_NOTIF, 3);
|
||||
|
||||
if (iwl_fw_lookup_notif_ver(mld->fw, STATISTICS_GROUP,
|
||||
STATISTICS_OPER_NOTIF, 3) >= 4) {
|
||||
if (notif_ver >= 5) {
|
||||
const struct iwl_system_statistics_notif_oper *notif =
|
||||
(void *)&pkt->data;
|
||||
per_sta = ¬if->per_sta[fw_sta_id];
|
||||
} else if (notif_ver == 4) {
|
||||
const struct iwl_system_statistics_notif_oper_v4 *notif =
|
||||
(void *)&pkt->data;
|
||||
per_sta = ¬if->per_sta[fw_sta_id];
|
||||
} else {
|
||||
const struct iwl_system_statistics_notif_oper_v3 *notif =
|
||||
(void *)&pkt->data;
|
||||
|
|
@ -581,17 +586,39 @@ void iwl_mld_handle_stats_oper_notif(struct iwl_mld *mld,
|
|||
struct iwl_system_statistics_notif_oper *_notif __free(kfree) = NULL;
|
||||
const struct iwl_system_statistics_notif_oper *notif =
|
||||
(void *)&pkt->data;
|
||||
u8 notif_ver = iwl_fw_lookup_notif_ver(mld->fw, STATISTICS_GROUP,
|
||||
STATISTICS_OPER_NOTIF, 3);
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(notif->per_sta) != IWL_STATION_COUNT_MAX);
|
||||
BUILD_BUG_ON(ARRAY_SIZE(notif->per_link) <
|
||||
ARRAY_SIZE(mld->fw_id_to_bss_conf));
|
||||
|
||||
if (iwl_fw_lookup_notif_ver(mld->fw, STATISTICS_GROUP,
|
||||
STATISTICS_OPER_NOTIF, 3) == 3) {
|
||||
if (notif_ver == 3) {
|
||||
const struct iwl_system_statistics_notif_oper_v3 *stats =
|
||||
(void *)&pkt->data;
|
||||
_notif = kzalloc_obj(*_notif);
|
||||
|
||||
if (!_notif)
|
||||
return;
|
||||
|
||||
_notif->time_stamp = stats->time_stamp;
|
||||
for (int i = 0; i < ARRAY_SIZE(_notif->per_link); i++)
|
||||
_notif->per_link[i] = stats->per_link[i];
|
||||
|
||||
BUILD_BUG_ON(sizeof(_notif->per_phy[0]) <
|
||||
sizeof(stats->per_phy[0]));
|
||||
for (int i = 0; i < ARRAY_SIZE(_notif->per_phy); i++)
|
||||
memcpy(&_notif->per_phy[i], &stats->per_phy[i],
|
||||
sizeof(stats->per_phy[i]));
|
||||
for (int i = 0; i < ARRAY_SIZE(_notif->per_sta); i++)
|
||||
_notif->per_sta[i] = stats->per_sta[i];
|
||||
|
||||
notif = _notif;
|
||||
} else if (notif_ver == 4) {
|
||||
const struct iwl_system_statistics_notif_oper_v4 *stats =
|
||||
(void *)&pkt->data;
|
||||
_notif = kzalloc_obj(*_notif);
|
||||
|
||||
if (!_notif)
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
iwlmld-tests-y += module.o hcmd.o utils.o link.o rx.o agg.o link-selection.o
|
||||
iwlmld-tests-y += chan_load_thresh.o
|
||||
iwlmld-tests-y += chan_load_thresh.o tx-gp2.o
|
||||
|
||||
ccflags-y += -I$(src)/../
|
||||
obj-$(CONFIG_IWLWIFI_KUNIT_TESTS) += iwlmld-tests.o
|
||||
|
|
|
|||
154
drivers/net/wireless/intel/iwlwifi/mld/tests/tx-gp2.c
Normal file
154
drivers/net/wireless/intel/iwlwifi/mld/tests/tx-gp2.c
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* KUnit tests for TX gp2 timestamp handling
|
||||
*
|
||||
* Copyright (C) 2026 Intel Corporation
|
||||
*/
|
||||
#include <kunit/test.h>
|
||||
|
||||
#include "mld.h"
|
||||
#include "tx.h"
|
||||
|
||||
MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
|
||||
|
||||
static const struct tx_gp2_case {
|
||||
const char *desc;
|
||||
u32 est_gp2_us;
|
||||
u32 est_host_us;
|
||||
u32 tx_host_us;
|
||||
long valid_for;
|
||||
u32 expected_gp2_us;
|
||||
bool expected_refresh;
|
||||
} tx_gp2_cases[] = {
|
||||
{
|
||||
.desc = "zero offset is valid",
|
||||
.est_gp2_us = 2000,
|
||||
.est_host_us = 2000,
|
||||
.tx_host_us = 3500,
|
||||
.valid_for = IWL_MLD_TX_GP2_VALID_PERIOD,
|
||||
.expected_gp2_us = 3500,
|
||||
},
|
||||
{
|
||||
.desc = "gp2 behind host",
|
||||
.est_gp2_us = 2000,
|
||||
.est_host_us = 10000,
|
||||
.tx_host_us = 11500,
|
||||
.valid_for = IWL_MLD_TX_GP2_VALID_PERIOD,
|
||||
.expected_gp2_us = 3500,
|
||||
},
|
||||
{
|
||||
.desc = "gp2 ahead of host",
|
||||
.est_gp2_us = 10000,
|
||||
.est_host_us = 2000,
|
||||
.tx_host_us = 3500,
|
||||
.valid_for = IWL_MLD_TX_GP2_VALID_PERIOD,
|
||||
.expected_gp2_us = 11500,
|
||||
},
|
||||
{
|
||||
.desc = "gp2 wraps after the estimate",
|
||||
.est_gp2_us = U32_MAX - 999,
|
||||
.est_host_us = 1000,
|
||||
.tx_host_us = 2500,
|
||||
.valid_for = IWL_MLD_TX_GP2_VALID_PERIOD,
|
||||
.expected_gp2_us = 500,
|
||||
},
|
||||
{
|
||||
.desc = "host time wraps after the estimate",
|
||||
.est_gp2_us = 5000,
|
||||
.est_host_us = U32_MAX - 999,
|
||||
.tx_host_us = 500,
|
||||
.valid_for = IWL_MLD_TX_GP2_VALID_PERIOD,
|
||||
.expected_gp2_us = 6500,
|
||||
},
|
||||
{
|
||||
.desc = "gp2 landing on 0 is reported as 1",
|
||||
.est_gp2_us = U32_MAX - 1499,
|
||||
.est_host_us = 1000,
|
||||
.tx_host_us = 2500,
|
||||
.valid_for = IWL_MLD_TX_GP2_VALID_PERIOD,
|
||||
.expected_gp2_us = 1,
|
||||
},
|
||||
{
|
||||
.desc = "within the refresh margin: still timestamped",
|
||||
.est_gp2_us = 2000,
|
||||
.est_host_us = 10000,
|
||||
.tx_host_us = 11500,
|
||||
.valid_for = IWL_MLD_TX_GP2_REFRESH_MARGIN - 1,
|
||||
.expected_gp2_us = 3500,
|
||||
.expected_refresh = true,
|
||||
},
|
||||
{
|
||||
.desc = "outside the refresh margin: no refresh",
|
||||
.est_gp2_us = 2000,
|
||||
.est_host_us = 10000,
|
||||
.tx_host_us = 11500,
|
||||
.valid_for = IWL_MLD_TX_GP2_REFRESH_MARGIN + 1,
|
||||
.expected_gp2_us = 3500,
|
||||
},
|
||||
{
|
||||
.desc = "at the refresh threshold",
|
||||
.est_gp2_us = 2000,
|
||||
.est_host_us = 10000,
|
||||
.tx_host_us = 11500,
|
||||
.valid_for = IWL_MLD_TX_GP2_REFRESH_MARGIN,
|
||||
.expected_gp2_us = 3500,
|
||||
.expected_refresh = true,
|
||||
},
|
||||
{
|
||||
.desc = "last valid tick",
|
||||
.est_gp2_us = 2000,
|
||||
.est_host_us = 10000,
|
||||
.tx_host_us = 11500,
|
||||
.valid_for = 1,
|
||||
.expected_gp2_us = 3500,
|
||||
.expected_refresh = true,
|
||||
},
|
||||
{
|
||||
.desc = "validity reached: leave the frame unstamped",
|
||||
.est_gp2_us = 2000,
|
||||
.est_host_us = 10000,
|
||||
.tx_host_us = 11500,
|
||||
.valid_for = 0,
|
||||
.expected_refresh = true,
|
||||
},
|
||||
{
|
||||
.desc = "validity passed: leave the frame unstamped",
|
||||
.est_gp2_us = 2000,
|
||||
.est_host_us = 10000,
|
||||
.tx_host_us = 11500,
|
||||
.valid_for = -1,
|
||||
.expected_refresh = true,
|
||||
},
|
||||
};
|
||||
|
||||
KUNIT_ARRAY_PARAM_DESC(tx_gp2, tx_gp2_cases, desc);
|
||||
|
||||
static void test_tx_gp2(struct kunit *test)
|
||||
{
|
||||
/* Pin time near wraparound to exercise wrapped validity deadlines. */
|
||||
const unsigned long now =
|
||||
ULONG_MAX - IWL_MLD_TX_GP2_REFRESH_MARGIN - 1;
|
||||
const struct tx_gp2_case *test_case = test->param_value;
|
||||
u32 delta_us = test_case->est_gp2_us - test_case->est_host_us;
|
||||
unsigned long valid_until = now + test_case->valid_for;
|
||||
bool refresh = !test_case->expected_refresh;
|
||||
u32 timestamp;
|
||||
|
||||
timestamp = iwl_mld_tx_gp2_from_est(delta_us, valid_until,
|
||||
test_case->tx_host_us, now,
|
||||
&refresh);
|
||||
KUNIT_EXPECT_EQ(test, timestamp, test_case->expected_gp2_us);
|
||||
KUNIT_EXPECT_EQ(test, refresh, test_case->expected_refresh);
|
||||
}
|
||||
|
||||
static struct kunit_case tx_gp2_test_cases[] = {
|
||||
KUNIT_CASE_PARAM(test_tx_gp2, tx_gp2_gen_params),
|
||||
{}
|
||||
};
|
||||
|
||||
static struct kunit_suite tx_gp2_test_suite = {
|
||||
.name = "iwl_mld_tx_gp2",
|
||||
.test_cases = tx_gp2_test_cases,
|
||||
};
|
||||
|
||||
kunit_test_suite(tx_gp2_test_suite);
|
||||
|
|
@ -49,9 +49,60 @@ struct iwl_mld_tlc_sta_capa {
|
|||
const struct ieee80211_sta_uhr_cap *own_uhr_cap;
|
||||
};
|
||||
|
||||
static bool iwl_mld_eht_ldpc_support(const struct ieee80211_sta_he_cap *he_cap,
|
||||
const struct ieee80211_sta_eht_cap *eht_cap,
|
||||
bool from_ap)
|
||||
{
|
||||
u8 nss;
|
||||
|
||||
/* higher bandwidth implies LDPC */
|
||||
if (he_cap->he_cap_elem.phy_cap_info[0] &
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G)
|
||||
return true;
|
||||
if (he_cap->he_cap_elem.phy_cap_info[0] &
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G)
|
||||
return true;
|
||||
if (he_cap->he_cap_elem.phy_cap_info[0] &
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
|
||||
return true;
|
||||
if (eht_cap->eht_cap_elem.phy_cap_info[0] &
|
||||
IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ)
|
||||
return true;
|
||||
|
||||
/* MCS 10-14 imply LDPC support, we only check 10-13 here */
|
||||
if (!from_ap) {
|
||||
const struct ieee80211_eht_mcs_nss_supp_20mhz_only *mcs_nss;
|
||||
|
||||
mcs_nss = &eht_cap->eht_mcs_nss_supp.only_20mhz;
|
||||
|
||||
if (mcs_nss->rx_tx_mcs11_max_nss ||
|
||||
mcs_nss->rx_tx_mcs13_max_nss)
|
||||
return true;
|
||||
|
||||
nss = mcs_nss->rx_tx_mcs7_max_nss;
|
||||
} else {
|
||||
const struct ieee80211_eht_mcs_nss_supp_bw *mcs_nss;
|
||||
|
||||
mcs_nss = &eht_cap->eht_mcs_nss_supp.bw._80;
|
||||
|
||||
if (mcs_nss->rx_tx_mcs11_max_nss ||
|
||||
mcs_nss->rx_tx_mcs13_max_nss)
|
||||
return true;
|
||||
|
||||
nss = mcs_nss->rx_tx_mcs9_max_nss;
|
||||
}
|
||||
|
||||
/* NSS > 4 implies LDPC support */
|
||||
return u8_get_bits(nss, IEEE80211_EHT_MCS_NSS_RX) > 4 ||
|
||||
u8_get_bits(nss, IEEE80211_EHT_MCS_NSS_TX) > 4;
|
||||
}
|
||||
|
||||
static __le16
|
||||
iwl_mld_get_tlc_cmd_flags(struct iwl_mld *mld,
|
||||
struct iwl_mld_tlc_sta_capa *capa)
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mld_tlc_sta_capa *capa,
|
||||
enum iwl_tlc_mng_cfg_mode mode,
|
||||
enum iwl_tlc_mng_cfg_cw max_bw)
|
||||
{
|
||||
const struct ieee80211_sta_ht_cap *ht_cap = capa->ht_cap;
|
||||
const struct ieee80211_sta_vht_cap *vht_cap = capa->vht_cap;
|
||||
|
|
@ -61,64 +112,79 @@ iwl_mld_get_tlc_cmd_flags(struct iwl_mld *mld,
|
|||
const struct ieee80211_sta_he_cap *own_he_cap = capa->own_he_cap;
|
||||
const struct ieee80211_sta_eht_cap *own_eht_cap = capa->own_eht_cap;
|
||||
const struct ieee80211_sta_uhr_cap *own_uhr_cap = capa->own_uhr_cap;
|
||||
bool has_vht = vht_cap && vht_cap->vht_supported;
|
||||
bool stbc_possible = mld->cfg->ht_params.stbc &&
|
||||
hweight8(iwl_mld_get_valid_tx_ant(mld)) > 1;
|
||||
u16 flags = 0;
|
||||
|
||||
/* STBC flags */
|
||||
if (mld->cfg->ht_params.stbc &&
|
||||
(hweight8(iwl_mld_get_valid_tx_ant(mld)) > 1)) {
|
||||
if (he_cap && he_cap->has_he &&
|
||||
switch (mode) {
|
||||
case IWL_TLC_MNG_MODE_NON_HT:
|
||||
break;
|
||||
case IWL_TLC_MNG_MODE_HT:
|
||||
if (WARN_ON(!ht_cap || !ht_cap->ht_supported))
|
||||
return 0;
|
||||
if (stbc_possible &&
|
||||
ht_cap->cap & IEEE80211_HT_CAP_RX_STBC)
|
||||
flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
|
||||
if (mld->cfg->ht_params.ldpc &&
|
||||
ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)
|
||||
flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
|
||||
break;
|
||||
case IWL_TLC_MNG_MODE_VHT:
|
||||
if (WARN_ON(!vht_cap || !vht_cap->vht_supported))
|
||||
return 0;
|
||||
if (stbc_possible &&
|
||||
vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK)
|
||||
flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
|
||||
if (mld->cfg->ht_params.ldpc &&
|
||||
vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC)
|
||||
flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
|
||||
break;
|
||||
case IWL_TLC_MNG_MODE_HE:
|
||||
if (WARN_ON(!he_cap || !he_cap->has_he || !own_he_cap))
|
||||
return 0;
|
||||
if (stbc_possible &&
|
||||
he_cap->he_cap_elem.phy_cap_info[2] &
|
||||
IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ)
|
||||
flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
|
||||
else if (vht_cap &&
|
||||
vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK)
|
||||
flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
|
||||
else if (ht_cap && ht_cap->cap & IEEE80211_HT_CAP_RX_STBC)
|
||||
IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ &&
|
||||
(max_bw <= IWL_TLC_MNG_CH_WIDTH_80MHZ ||
|
||||
he_cap->he_cap_elem.phy_cap_info[7] &
|
||||
IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ))
|
||||
flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
|
||||
if (he_cap->he_cap_elem.phy_cap_info[1] &
|
||||
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD &&
|
||||
own_he_cap->he_cap_elem.phy_cap_info[1] &
|
||||
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)
|
||||
flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
|
||||
if (he_cap->he_cap_elem.phy_cap_info[3] &
|
||||
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK &&
|
||||
own_he_cap->he_cap_elem.phy_cap_info[3] &
|
||||
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK)
|
||||
flags |= IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK;
|
||||
break;
|
||||
case IWL_TLC_MNG_MODE_UHR:
|
||||
if (WARN_ON(!uhr_cap || !uhr_cap->has_uhr || !own_uhr_cap))
|
||||
return 0;
|
||||
if (uhr_cap->phy.cap & cpu_to_le32(IEEE80211_UHR_PHY_CAP_ELR_RX) &&
|
||||
own_uhr_cap->phy.cap & cpu_to_le32(IEEE80211_UHR_PHY_CAP_ELR_TX))
|
||||
flags |= IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_1_5_MBPS_MSK |
|
||||
IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_3_MBPS_MSK;
|
||||
/* uses most config from EHT */
|
||||
fallthrough;
|
||||
case IWL_TLC_MNG_MODE_EHT:
|
||||
if (WARN_ON(!own_he_cap || !he_cap || !he_cap->has_he ||
|
||||
!own_eht_cap || !eht_cap || !eht_cap->has_eht))
|
||||
return 0;
|
||||
if (own_eht_cap->eht_cap_elem.phy_cap_info[5] &
|
||||
IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF &&
|
||||
eht_cap->eht_cap_elem.phy_cap_info[5] &
|
||||
IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF)
|
||||
flags |= IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK;
|
||||
/* no STBC in EHT */
|
||||
if (iwl_mld_eht_ldpc_support(he_cap, eht_cap,
|
||||
vif->type == NL80211_IFTYPE_STATION))
|
||||
flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
|
||||
break;
|
||||
}
|
||||
|
||||
/* LDPC */
|
||||
if (mld->cfg->ht_params.ldpc &&
|
||||
((ht_cap && ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING) ||
|
||||
(has_vht && (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC))))
|
||||
flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
|
||||
|
||||
if (he_cap && he_cap->has_he &&
|
||||
(he_cap->he_cap_elem.phy_cap_info[1] &
|
||||
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
|
||||
flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
|
||||
|
||||
if (own_he_cap &&
|
||||
!(own_he_cap->he_cap_elem.phy_cap_info[1] &
|
||||
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
|
||||
flags &= ~IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
|
||||
|
||||
/* DCM */
|
||||
if (he_cap && he_cap->has_he &&
|
||||
(he_cap->he_cap_elem.phy_cap_info[3] &
|
||||
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK &&
|
||||
own_he_cap &&
|
||||
own_he_cap->he_cap_elem.phy_cap_info[3] &
|
||||
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK))
|
||||
flags |= IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK;
|
||||
|
||||
/* Extra EHT LTF */
|
||||
if (own_eht_cap &&
|
||||
own_eht_cap->eht_cap_elem.phy_cap_info[5] &
|
||||
IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF &&
|
||||
eht_cap && eht_cap->has_eht &&
|
||||
eht_cap->eht_cap_elem.phy_cap_info[5] &
|
||||
IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF) {
|
||||
flags |= IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK;
|
||||
}
|
||||
|
||||
if (uhr_cap && uhr_cap->has_uhr && own_uhr_cap &&
|
||||
uhr_cap->phy.cap & cpu_to_le32(IEEE80211_UHR_PHY_CAP_ELR_RX) &&
|
||||
own_uhr_cap->phy.cap & cpu_to_le32(IEEE80211_UHR_PHY_CAP_ELR_TX))
|
||||
flags |= IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_1_5_MBPS_MSK |
|
||||
IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_3_MBPS_MSK;
|
||||
|
||||
return cpu_to_le16(flags);
|
||||
}
|
||||
|
||||
|
|
@ -478,7 +544,6 @@ static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld,
|
|||
.max_ch_width = mld_sta->sta_state > IEEE80211_STA_ASSOC ?
|
||||
iwl_mld_fw_bw_from_sta_bw(capa->bandwidth) :
|
||||
IWL_TLC_MNG_CH_WIDTH_20MHZ,
|
||||
.flags = iwl_mld_get_tlc_cmd_flags(mld, capa),
|
||||
.chains = iwl_mld_get_fw_chains(mld),
|
||||
.sgi_ch_width_supp = iwl_mld_get_fw_sgi(capa),
|
||||
.max_mpdu_len = cpu_to_le16(capa->max_amsdu_len),
|
||||
|
|
@ -493,6 +558,8 @@ static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld,
|
|||
cmd.phy_id = cpu_to_le32(phy_id);
|
||||
|
||||
iwl_mld_fill_supp_rates(mld, vif, capa, &cmd);
|
||||
cmd.flags = iwl_mld_get_tlc_cmd_flags(mld, vif, capa, cmd.mode,
|
||||
cmd.max_ch_width);
|
||||
|
||||
if (cmd_ver == 6) {
|
||||
cmd_ptr = &cmd;
|
||||
|
|
@ -824,8 +891,13 @@ iwl_mld_get_amsdu_size_of_tid(struct iwl_mld *mld,
|
|||
|
||||
txf = iwl_mld_mac80211_ac_to_fw_tx_fifo(ac);
|
||||
|
||||
/* Only one link: take the lmac according to the band */
|
||||
if (hweight16(sta->valid_links) <= 1) {
|
||||
/*
|
||||
* Only one link: take the lmac according to the band
|
||||
* In NAN, we don't have a link_conf.
|
||||
* TODO: once we have a TLC object, we can know better the band.
|
||||
*/
|
||||
if (hweight16(sta->valid_links) <= 1 &&
|
||||
vif->type != NL80211_IFTYPE_NAN_DATA) {
|
||||
enum nl80211_band band;
|
||||
struct ieee80211_bss_conf *link =
|
||||
wiphy_dereference(mld->wiphy,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
/*
|
||||
* Copyright (C) 2024 - 2026 Intel Corporation
|
||||
*/
|
||||
#include <linux/timekeeping.h>
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "tx.h"
|
||||
|
|
@ -20,6 +21,133 @@
|
|||
|
||||
#define MAX_ANT_NUM 2
|
||||
|
||||
static u32 iwl_mld_tx_gp2_host_us(void)
|
||||
{
|
||||
return div_u64(ktime_get_boottime_ns(), NSEC_PER_USEC);
|
||||
}
|
||||
|
||||
/* Returns the gp2 for the TX command, or 0 to leave the frame unstamped.
|
||||
* Sets @refresh when the estimate expired or is about to.
|
||||
*/
|
||||
VISIBLE_IF_IWLWIFI_KUNIT u32
|
||||
iwl_mld_tx_gp2_from_est(u32 delta_us, unsigned long valid_until, u32 host_us,
|
||||
unsigned long now, bool *refresh)
|
||||
{
|
||||
u32 gp2;
|
||||
|
||||
*refresh = time_after_eq(now, valid_until -
|
||||
IWL_MLD_TX_GP2_REFRESH_MARGIN);
|
||||
|
||||
if (time_after_eq(now, valid_until))
|
||||
return 0;
|
||||
|
||||
gp2 = host_us + delta_us;
|
||||
|
||||
/* 0 means no timestamp; use 1 for a valid wrapped value. */
|
||||
return gp2 ?: 1;
|
||||
}
|
||||
EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_tx_gp2_from_est);
|
||||
|
||||
static u32
|
||||
iwl_mld_tx_gp2_timestamp(struct iwl_mld *mld)
|
||||
{
|
||||
unsigned long valid_until =
|
||||
atomic_long_read_acquire(&mld->tx_gp2.valid_until);
|
||||
bool refresh = false;
|
||||
u32 gp2;
|
||||
|
||||
if (!valid_until)
|
||||
return 0;
|
||||
|
||||
gp2 = iwl_mld_tx_gp2_from_est(atomic_read(&mld->tx_gp2.delta_us),
|
||||
valid_until, iwl_mld_tx_gp2_host_us(),
|
||||
jiffies, &refresh);
|
||||
|
||||
if (refresh)
|
||||
wiphy_delayed_work_queue(mld->wiphy, &mld->tx_gp2.wk, 0);
|
||||
|
||||
return gp2;
|
||||
}
|
||||
|
||||
static void iwl_mld_tx_gp2_refresh(struct iwl_mld *mld)
|
||||
{
|
||||
unsigned long valid_until, delay;
|
||||
u32 gp2, host_us;
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
if (!mld->fw_status.running)
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
if (mld->fw_status.in_d3)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (iwl_mld_get_systime(mld, &gp2))
|
||||
goto retry;
|
||||
|
||||
host_us = iwl_mld_tx_gp2_host_us();
|
||||
valid_until = jiffies + IWL_MLD_TX_GP2_VALID_PERIOD;
|
||||
|
||||
/* Keep arithmetic in u32 to match firmware wraparound semantics. */
|
||||
atomic_set(&mld->tx_gp2.delta_us, gp2 - host_us);
|
||||
atomic_long_set_release(&mld->tx_gp2.valid_until, valid_until ?: 1);
|
||||
|
||||
IWL_DEBUG_TX(mld, "gp2 sync: gp2=%u host_us=%u delta_us=%u\n",
|
||||
gp2, host_us, gp2 - host_us);
|
||||
return;
|
||||
|
||||
retry:
|
||||
/* Stop new TX readers from requesting immediate retries. */
|
||||
atomic_long_set(&mld->tx_gp2.valid_until, 0);
|
||||
delay = round_jiffies_relative(IWL_MLD_TX_GP2_RETRY_PERIOD);
|
||||
wiphy_delayed_work_queue(mld->wiphy, &mld->tx_gp2.wk, delay);
|
||||
}
|
||||
|
||||
static void iwl_mld_tx_gp2_wk(struct wiphy *wiphy, struct wiphy_work *wk)
|
||||
{
|
||||
struct iwl_mld *mld = container_of(wk, struct iwl_mld, tx_gp2.wk.work);
|
||||
unsigned long valid_until = atomic_long_read(&mld->tx_gp2.valid_until);
|
||||
|
||||
/* TX may have queued this work using an older estimate. */
|
||||
if (valid_until &&
|
||||
time_before(jiffies, valid_until - IWL_MLD_TX_GP2_REFRESH_MARGIN))
|
||||
return;
|
||||
|
||||
iwl_mld_tx_gp2_refresh(mld);
|
||||
}
|
||||
|
||||
void iwl_mld_tx_gp2_init(struct iwl_mld *mld)
|
||||
{
|
||||
atomic_set(&mld->tx_gp2.delta_us, 0);
|
||||
atomic_long_set(&mld->tx_gp2.valid_until, 0);
|
||||
wiphy_delayed_work_init(&mld->tx_gp2.wk, iwl_mld_tx_gp2_wk);
|
||||
}
|
||||
|
||||
void iwl_mld_tx_gp2_start(struct iwl_mld *mld)
|
||||
{
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
if (iwl_fw_lookup_cmd_ver(mld->fw, TX_CMD, 0) < 12)
|
||||
return;
|
||||
|
||||
iwl_mld_tx_gp2_refresh(mld);
|
||||
}
|
||||
|
||||
/* TX is quiesced before stopping the refresh work. */
|
||||
void iwl_mld_tx_gp2_stop(struct iwl_mld *mld)
|
||||
{
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
if (iwl_fw_lookup_cmd_ver(mld->fw, TX_CMD, 0) < 12)
|
||||
return;
|
||||
|
||||
wiphy_delayed_work_cancel(mld->wiphy, &mld->tx_gp2.wk);
|
||||
|
||||
atomic_long_set(&mld->tx_gp2.valid_until, 0);
|
||||
}
|
||||
|
||||
/* Toggles between TX antennas. Receives the bitmask of valid TX antennas and
|
||||
* the *index* used for the last TX, and returns the next valid *index* to use.
|
||||
* In order to set it in the tx_cmd, must do BIT(idx).
|
||||
|
|
@ -588,6 +716,9 @@ iwl_mld_fill_tx_cmd(struct iwl_mld *mld, struct sk_buff *skb,
|
|||
tx_cmd->flags = cpu_to_le16(flags);
|
||||
|
||||
tx_cmd->rate_n_flags = rate_n_flags;
|
||||
|
||||
tx_cmd->driver_timestamp =
|
||||
cpu_to_le32(iwl_mld_tx_gp2_timestamp(mld));
|
||||
}
|
||||
|
||||
/* Caller of this need to check that info->control.vif is not NULL */
|
||||
|
|
@ -1353,6 +1484,10 @@ int iwl_mld_update_sta_txqs(struct iwl_mld *mld,
|
|||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
if (mld->trans->conf.queue_alloc_cmd_ver >= 4)
|
||||
cmd.u.modify.flags =
|
||||
cpu_to_le16(IWL_SCD_QUEUE_MODIFY_FLAG_STA_MSK);
|
||||
|
||||
for (int tid = 0; tid <= IWL_MAX_TID_COUNT; tid++) {
|
||||
struct ieee80211_txq *txq =
|
||||
sta->txq[tid != IWL_MAX_TID_COUNT ?
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024 Intel Corporation
|
||||
* Copyright (C) 2024, 2026 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_mld_tx_h__
|
||||
#define __iwl_mld_tx_h__
|
||||
|
||||
#include "mld.h"
|
||||
#include <linux/atomic.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
struct iwl_mld;
|
||||
struct iwl_rx_packet;
|
||||
|
||||
#define IWL_MLD_INVALID_QUEUE 0xFFFF
|
||||
#define IWL_MLD_INVALID_DROP_TX 0xFFFE
|
||||
|
|
@ -74,4 +78,37 @@ u8 iwl_mld_get_lowest_rate(struct iwl_mld *mld,
|
|||
void iwl_mld_tx_skb(struct iwl_mld *mld, struct sk_buff *skb,
|
||||
struct ieee80211_txq *txq);
|
||||
|
||||
/**
|
||||
* struct iwl_mld_tx_gp2 - gp2 timestamping state for TX commands
|
||||
*
|
||||
* Reading gp2 directly in the TX path is too costly. Instead, TX lazily
|
||||
* schedules @wk to refresh gp2 in process context and adds @delta_us to the
|
||||
* host clock to timestamp queued frames.
|
||||
*
|
||||
* A zero @valid_until leaves frames unstamped, including on older firmware
|
||||
* without TX_CMD v12. A deadline that wraps to zero is published as one.
|
||||
* Failed refreshes clear @valid_until, leaving @delta_us for old readers, and
|
||||
* schedule a retry with %IWL_MLD_TX_GP2_RETRY_PERIOD rounded for timer
|
||||
* coalescing, even without further TX traffic. Old readers may retry sooner.
|
||||
*
|
||||
* @delta_us: gp2 minus host time, in microseconds, modulo 2^32;
|
||||
* valid while @valid_until is nonzero and has not expired
|
||||
* @valid_until: jiffies deadline for the offset, or zero when disabled
|
||||
* @wk: worker that refreshes the offset and retries failures
|
||||
*/
|
||||
struct iwl_mld_tx_gp2 {
|
||||
atomic_t delta_us;
|
||||
atomic_long_t valid_until;
|
||||
struct wiphy_delayed_work wk;
|
||||
};
|
||||
|
||||
void iwl_mld_tx_gp2_init(struct iwl_mld *mld);
|
||||
void iwl_mld_tx_gp2_start(struct iwl_mld *mld);
|
||||
void iwl_mld_tx_gp2_stop(struct iwl_mld *mld);
|
||||
|
||||
#if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS)
|
||||
u32 iwl_mld_tx_gp2_from_est(u32 delta_us, unsigned long valid_until,
|
||||
u32 host_us, unsigned long now, bool *refresh);
|
||||
#endif
|
||||
|
||||
#endif /* __iwl_mld_tx_h__ */
|
||||
|
|
|
|||
|
|
@ -2440,6 +2440,12 @@ struct iwl_mvm_nd_results {
|
|||
u8 matches[ND_QUERY_BUF_LEN];
|
||||
};
|
||||
|
||||
static bool iwl_mvm_nd_match_info_v3(struct iwl_mvm *mvm)
|
||||
{
|
||||
return iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
|
||||
SCAN_OFFLOAD_PROFILES_QUERY_CMD, 0) >= 4;
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_nd_results *results)
|
||||
|
|
@ -2459,12 +2465,17 @@ iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm,
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) {
|
||||
if (iwl_mvm_nd_match_info_v3(mvm)) {
|
||||
matches_len = sizeof(struct iwl_scan_offload_profile_match) *
|
||||
max_profiles;
|
||||
query_len = offsetof(struct iwl_scan_offload_match_info,
|
||||
matches) + matches_len;
|
||||
} else if (fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) {
|
||||
matches_len = sizeof(struct iwl_scan_offload_profile_match_v2) *
|
||||
max_profiles;
|
||||
query_len = offsetof(struct iwl_scan_offload_match_info,
|
||||
matches) + matches_len;
|
||||
} else {
|
||||
matches_len = sizeof(struct iwl_scan_offload_profile_match_v1) *
|
||||
max_profiles;
|
||||
|
|
@ -2499,13 +2510,19 @@ static int iwl_mvm_query_num_match_chans(struct iwl_mvm *mvm,
|
|||
{
|
||||
int n_chans = 0, i;
|
||||
|
||||
if (fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) {
|
||||
if (iwl_mvm_nd_match_info_v3(mvm)) {
|
||||
struct iwl_scan_offload_profile_match *matches =
|
||||
(void *)results->matches;
|
||||
|
||||
for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN; i++)
|
||||
n_chans += hweight8(matches[idx].matching_channels[i]);
|
||||
} else if (fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) {
|
||||
struct iwl_scan_offload_profile_match_v2 *matches =
|
||||
(void *)results->matches;
|
||||
|
||||
for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V2; i++)
|
||||
n_chans += hweight8(matches[idx].matching_channels[i]);
|
||||
} else {
|
||||
struct iwl_scan_offload_profile_match_v1 *matches =
|
||||
(void *)results->matches;
|
||||
|
|
@ -2517,34 +2534,58 @@ static int iwl_mvm_query_num_match_chans(struct iwl_mvm *mvm,
|
|||
return n_chans;
|
||||
}
|
||||
|
||||
static void iwl_mvm_set_matching_freqs(struct iwl_mvm *mvm,
|
||||
const u8 *matching_channels,
|
||||
size_t num_bytes,
|
||||
struct cfg80211_wowlan_nd_match *match)
|
||||
{
|
||||
int n_channels = 0;
|
||||
|
||||
for (int i = 0; i < num_bytes * 8; i++) {
|
||||
if (!(matching_channels[i / 8] & BIT(i % 8)))
|
||||
continue;
|
||||
if (IWL_FW_CHECK(mvm, i >= mvm->n_nd_channels,
|
||||
"FW matched channel bit %d beyond n_nd_channels %d\n",
|
||||
i, mvm->n_nd_channels))
|
||||
break;
|
||||
match->channels[n_channels++] =
|
||||
mvm->nd_channels[i]->center_freq;
|
||||
}
|
||||
/* We may have ended up with fewer channels than we allocated. */
|
||||
match->n_channels = n_channels;
|
||||
}
|
||||
|
||||
static void iwl_mvm_query_set_freqs(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_nd_results *results,
|
||||
struct cfg80211_wowlan_nd_match *match,
|
||||
int idx)
|
||||
{
|
||||
int i;
|
||||
int n_channels = 0;
|
||||
|
||||
if (fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) {
|
||||
if (iwl_mvm_nd_match_info_v3(mvm)) {
|
||||
struct iwl_scan_offload_profile_match *matches =
|
||||
(void *)results->matches;
|
||||
|
||||
for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN * 8; i++)
|
||||
if (matches[idx].matching_channels[i / 8] & (BIT(i % 8)))
|
||||
match->channels[n_channels++] =
|
||||
mvm->nd_channels[i]->center_freq;
|
||||
iwl_mvm_set_matching_freqs(mvm,
|
||||
matches[idx].matching_channels,
|
||||
sizeof(matches[idx].matching_channels),
|
||||
match);
|
||||
} else if (fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) {
|
||||
struct iwl_scan_offload_profile_match_v2 *matches =
|
||||
(void *)results->matches;
|
||||
|
||||
iwl_mvm_set_matching_freqs(mvm,
|
||||
matches[idx].matching_channels,
|
||||
sizeof(matches[idx].matching_channels),
|
||||
match);
|
||||
} else {
|
||||
struct iwl_scan_offload_profile_match_v1 *matches =
|
||||
(void *)results->matches;
|
||||
|
||||
for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1 * 8; i++)
|
||||
if (matches[idx].matching_channels[i / 8] & (BIT(i % 8)))
|
||||
match->channels[n_channels++] =
|
||||
mvm->nd_channels[i]->center_freq;
|
||||
iwl_mvm_set_matching_freqs(mvm,
|
||||
matches[idx].matching_channels,
|
||||
sizeof(matches[idx].matching_channels),
|
||||
match);
|
||||
}
|
||||
/* We may have ended up with fewer channels than we allocated. */
|
||||
match->n_channels = n_channels;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2817,8 +2858,14 @@ static void iwl_mvm_nd_match_info_handler(struct iwl_mvm *mvm,
|
|||
struct iwl_wowlan_status_data *status = d3_data->status;
|
||||
struct ieee80211_vif *vif = iwl_mvm_get_bss_vif(mvm);
|
||||
struct iwl_mvm_nd_results *results = d3_data->nd_results;
|
||||
size_t i, matches_len = sizeof(struct iwl_scan_offload_profile_match) *
|
||||
iwl_umac_scan_get_max_profiles(mvm->fw);
|
||||
size_t i, matches_len;
|
||||
|
||||
if (iwl_mvm_nd_match_info_v3(mvm))
|
||||
matches_len = sizeof(struct iwl_scan_offload_profile_match) *
|
||||
iwl_umac_scan_get_max_profiles(mvm->fw);
|
||||
else
|
||||
matches_len = sizeof(struct iwl_scan_offload_profile_match_v2) *
|
||||
iwl_umac_scan_get_max_profiles(mvm->fw);
|
||||
|
||||
if (IS_ERR_OR_NULL(vif))
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include "mvm.h"
|
||||
#include "sta.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "debugfs.h"
|
||||
#include "iwl-modparams.h"
|
||||
#include "iwl-drv.h"
|
||||
|
|
@ -153,72 +153,6 @@ static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
const struct fw_img *img;
|
||||
unsigned int ofs, len;
|
||||
size_t ret;
|
||||
u8 *ptr;
|
||||
|
||||
if (!iwl_mvm_firmware_running(mvm))
|
||||
return -EINVAL;
|
||||
|
||||
/* default is to dump the entire data segment */
|
||||
img = &mvm->fw->img[mvm->fwrt.cur_fw_img];
|
||||
ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
|
||||
len = img->sec[IWL_UCODE_SECTION_DATA].len;
|
||||
|
||||
if (mvm->dbgfs_sram_len) {
|
||||
ofs = mvm->dbgfs_sram_offset;
|
||||
len = mvm->dbgfs_sram_len;
|
||||
}
|
||||
|
||||
ptr = kzalloc(len, GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return -ENOMEM;
|
||||
|
||||
iwl_trans_read_mem_bytes(mvm->trans, ofs, ptr, len);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, ptr, len);
|
||||
|
||||
kfree(ptr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_sram_write(struct iwl_mvm *mvm, char *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
const struct fw_img *img;
|
||||
u32 offset, len;
|
||||
u32 img_offset, img_len;
|
||||
|
||||
if (!iwl_mvm_firmware_running(mvm))
|
||||
return -EINVAL;
|
||||
|
||||
img = &mvm->fw->img[mvm->fwrt.cur_fw_img];
|
||||
img_offset = img->sec[IWL_UCODE_SECTION_DATA].offset;
|
||||
img_len = img->sec[IWL_UCODE_SECTION_DATA].len;
|
||||
|
||||
if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
|
||||
if ((offset & 0x3) || (len & 0x3))
|
||||
return -EINVAL;
|
||||
|
||||
if (offset + len > img_offset + img_len)
|
||||
return -EINVAL;
|
||||
|
||||
mvm->dbgfs_sram_offset = offset;
|
||||
mvm->dbgfs_sram_len = len;
|
||||
} else {
|
||||
mvm->dbgfs_sram_offset = 0;
|
||||
mvm->dbgfs_sram_len = 0;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_set_nic_temperature_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
|
|
@ -591,16 +525,24 @@ static ssize_t iwl_dbgfs_tas_get_status_read(struct file *file,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (iwl_rx_packet_payload_len(hcmd.resp_pkt) != sizeof(*rsp)) {
|
||||
iwl_free_resp(&hcmd);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
buff = kzalloc(bufsz, GFP_KERNEL);
|
||||
if (!buff)
|
||||
if (!buff) {
|
||||
iwl_free_resp(&hcmd);
|
||||
return -ENOMEM;
|
||||
}
|
||||
pos = buff;
|
||||
endpos = pos + bufsz;
|
||||
|
||||
rsp = (void *)hcmd.resp_pkt->data;
|
||||
|
||||
pos += scnprintf(pos, endpos - pos, "TAS Conclusion:\n");
|
||||
for (i = 0; i < rsp->in_dual_radio + 1; i++) {
|
||||
for (i = 0; i < min_t(int, rsp->in_dual_radio + 1,
|
||||
ARRAY_SIZE(rsp->tas_status_mac)); i++) {
|
||||
if (rsp->tas_status_mac[i].dynamic_status &
|
||||
BIT(TAS_DYNA_ACTIVE)) {
|
||||
pos += scnprintf(pos, endpos - pos, "\tON for ");
|
||||
|
|
@ -655,7 +597,8 @@ static ssize_t iwl_dbgfs_tas_get_status_read(struct file *file,
|
|||
"\tDo TAS Support Dual Radio?: %s\n",
|
||||
rsp->in_dual_radio ? "TRUE" : "FALSE");
|
||||
|
||||
for (i = 0; i < rsp->in_dual_radio + 1; i++) {
|
||||
for (i = 0; i < min_t(int, rsp->in_dual_radio + 1,
|
||||
ARRAY_SIZE(rsp->tas_status_mac)); i++) {
|
||||
if (rsp->tas_status_mac[i].static_status == 0) {
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"Static status: disabled\n");
|
||||
|
|
@ -1159,7 +1102,7 @@ static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
|
|||
if (count == 6 && !strcmp(buf, "nolog\n"))
|
||||
set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status);
|
||||
|
||||
iwl_force_nmi(mvm->trans);
|
||||
iwl_trans_force_nmi(mvm->trans);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
|
@ -1211,53 +1154,6 @@ iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf,
|
|||
return count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_indirection_tbl_write(struct iwl_mvm *mvm,
|
||||
char *buf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct iwl_rss_config_cmd cmd = {
|
||||
.flags = cpu_to_le32(IWL_RSS_ENABLE),
|
||||
.hash_mask = IWL_RSS_HASH_TYPE_IPV4_TCP |
|
||||
IWL_RSS_HASH_TYPE_IPV4_UDP |
|
||||
IWL_RSS_HASH_TYPE_IPV4_PAYLOAD |
|
||||
IWL_RSS_HASH_TYPE_IPV6_TCP |
|
||||
IWL_RSS_HASH_TYPE_IPV6_UDP |
|
||||
IWL_RSS_HASH_TYPE_IPV6_PAYLOAD,
|
||||
};
|
||||
int ret, i, num_repeats, nbytes = count / 2;
|
||||
|
||||
ret = hex2bin(cmd.indirection_table, buf, nbytes);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* The input is the redirection table, partial or full.
|
||||
* Repeat the pattern if needed.
|
||||
* For example, input of 01020F will be repeated 42 times,
|
||||
* indirecting RSS hash results to queues 1, 2, 15 (skipping
|
||||
* queues 3 - 14).
|
||||
*/
|
||||
num_repeats = ARRAY_SIZE(cmd.indirection_table) / nbytes;
|
||||
for (i = 1; i < num_repeats; i++)
|
||||
memcpy(&cmd.indirection_table[i * nbytes],
|
||||
cmd.indirection_table, nbytes);
|
||||
/* handle cut in the middle pattern for the last places */
|
||||
memcpy(&cmd.indirection_table[i * nbytes], cmd.indirection_table,
|
||||
ARRAY_SIZE(cmd.indirection_table) % nbytes);
|
||||
|
||||
netdev_rss_key_fill(cmd.secret_key, sizeof(cmd.secret_key));
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
if (iwl_mvm_firmware_running(mvm))
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0,
|
||||
sizeof(cmd), &cmd);
|
||||
else
|
||||
ret = 0;
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return ret ?: count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm,
|
||||
char *buf, size_t count,
|
||||
loff_t *ppos)
|
||||
|
|
@ -1652,7 +1548,7 @@ iwl_dbgfs_prph_reg_read(struct file *file,
|
|||
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n",
|
||||
mvm->dbgfs_prph_reg_addr,
|
||||
iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr));
|
||||
iwl_trans_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr));
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
|
@ -1673,7 +1569,7 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
|
|||
if (args != 2)
|
||||
return -EINVAL;
|
||||
|
||||
iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value);
|
||||
iwl_trans_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value);
|
||||
|
||||
out:
|
||||
return count;
|
||||
|
|
@ -1916,7 +1812,6 @@ 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(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);
|
||||
|
|
@ -1933,8 +1828,6 @@ 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_clear, 64);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(dbg_time_point, 64);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl,
|
||||
(IWL_RSS_INDIRECTION_TABLE_SIZE * 2));
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(inject_packet, 512);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie, 512);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie_restore, 512);
|
||||
|
|
@ -2114,7 +2007,6 @@ 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(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);
|
||||
|
|
@ -2134,7 +2026,6 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm)
|
|||
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);
|
||||
MVM_DEBUGFS_ADD_FILE(inject_packet, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(inject_beacon_ie, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(inject_beacon_ie_restore, mvm->debugfs_dir, 0200);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#include <linux/math64.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include "mvm.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "constants.h"
|
||||
|
||||
|
|
@ -519,8 +519,9 @@ static int iwl_mvm_ftm_send_cmd(struct iwl_mvm *mvm, struct iwl_host_cmd *hcmd)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int iwl_mvm_ftm_start_v5(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request *req)
|
||||
static int noinline_for_stack
|
||||
iwl_mvm_ftm_start_v5(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request *req)
|
||||
{
|
||||
struct iwl_tof_range_req_cmd_v5 cmd_v5;
|
||||
struct iwl_host_cmd hcmd = {
|
||||
|
|
@ -545,8 +546,9 @@ static int iwl_mvm_ftm_start_v5(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
return iwl_mvm_ftm_send_cmd(mvm, &hcmd);
|
||||
}
|
||||
|
||||
static int iwl_mvm_ftm_start_v7(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request *req)
|
||||
static int noinline_for_stack
|
||||
iwl_mvm_ftm_start_v7(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request *req)
|
||||
{
|
||||
struct iwl_tof_range_req_cmd_v7 cmd_v7;
|
||||
struct iwl_host_cmd hcmd = {
|
||||
|
|
@ -575,8 +577,9 @@ static int iwl_mvm_ftm_start_v7(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
return iwl_mvm_ftm_send_cmd(mvm, &hcmd);
|
||||
}
|
||||
|
||||
static int iwl_mvm_ftm_start_v8(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request *req)
|
||||
static int noinline_for_stack
|
||||
iwl_mvm_ftm_start_v8(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request *req)
|
||||
{
|
||||
struct iwl_tof_range_req_cmd_v8 cmd;
|
||||
struct iwl_host_cmd hcmd = {
|
||||
|
|
@ -601,8 +604,10 @@ static int iwl_mvm_ftm_start_v8(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
return iwl_mvm_ftm_send_cmd(mvm, &hcmd);
|
||||
}
|
||||
|
||||
static int iwl_mvm_ftm_start_v9(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request *req)
|
||||
|
||||
static int noinline_for_stack
|
||||
iwl_mvm_ftm_start_v9(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request *req)
|
||||
{
|
||||
struct iwl_tof_range_req_cmd_v9 cmd;
|
||||
struct iwl_host_cmd hcmd = {
|
||||
|
|
@ -735,9 +740,10 @@ iwl_mvm_ftm_put_target_v7(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
&target->initiator_ap_flags);
|
||||
}
|
||||
|
||||
static int iwl_mvm_ftm_start_v11(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request *req)
|
||||
static int noinline_for_stack
|
||||
iwl_mvm_ftm_start_v11(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request *req)
|
||||
{
|
||||
struct iwl_tof_range_req_cmd_v11 cmd;
|
||||
struct iwl_host_cmd hcmd = {
|
||||
|
|
@ -807,9 +813,10 @@ iwl_mvm_ftm_put_target_v8(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_mvm_ftm_start_v12(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request *req)
|
||||
static int noinline_for_stack
|
||||
iwl_mvm_ftm_start_v12(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request *req)
|
||||
{
|
||||
struct iwl_tof_range_req_cmd_v12 cmd;
|
||||
struct iwl_host_cmd hcmd = {
|
||||
|
|
@ -835,9 +842,10 @@ static int iwl_mvm_ftm_start_v12(struct iwl_mvm *mvm,
|
|||
return iwl_mvm_ftm_send_cmd(mvm, &hcmd);
|
||||
}
|
||||
|
||||
static int iwl_mvm_ftm_start_v13(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request *req)
|
||||
static int noinline_for_stack
|
||||
iwl_mvm_ftm_start_v13(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request *req)
|
||||
{
|
||||
struct iwl_tof_range_req_cmd_v13 cmd;
|
||||
struct iwl_host_cmd hcmd = {
|
||||
|
|
@ -951,9 +959,10 @@ iwl_mvm_ftm_put_target_v10(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_mvm_ftm_start_v14(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request *req)
|
||||
static int noinline_for_stack
|
||||
iwl_mvm_ftm_start_v14(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request *req)
|
||||
{
|
||||
struct iwl_tof_range_req_cmd cmd;
|
||||
struct iwl_host_cmd hcmd = {
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ static bool iwl_wait_phy_db_entry(struct iwl_notif_wait_data *notif_wait,
|
|||
static void iwl_mvm_print_pd_notification(struct iwl_mvm *mvm)
|
||||
{
|
||||
#define IWL_FW_PRINT_REG_INFO(reg_name) \
|
||||
IWL_ERR(mvm, #reg_name ": 0x%x\n", iwl_read_umac_prph(trans, reg_name))
|
||||
IWL_ERR(mvm, #reg_name ": 0x%x\n", iwl_trans_read_umac_prph(trans, reg_name))
|
||||
|
||||
struct iwl_trans *trans = mvm->trans;
|
||||
enum iwl_device_family device_family = trans->mac_cfg->device_family;
|
||||
|
|
@ -332,13 +332,13 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
|
|||
IWL_DEVICE_FAMILY_AX210) {
|
||||
/* print these registers regardless of alive fail/success */
|
||||
IWL_INFO(mvm, "WFPM_UMAC_PD_NOTIFICATION: 0x%x\n",
|
||||
iwl_read_umac_prph(mvm->trans, WFPM_ARC1_PD_NOTIFICATION));
|
||||
iwl_trans_read_umac_prph(mvm->trans, WFPM_ARC1_PD_NOTIFICATION));
|
||||
IWL_INFO(mvm, "WFPM_LMAC2_PD_NOTIFICATION: 0x%x\n",
|
||||
iwl_read_umac_prph(mvm->trans, WFPM_LMAC2_PD_NOTIFICATION));
|
||||
iwl_trans_read_umac_prph(mvm->trans, WFPM_LMAC2_PD_NOTIFICATION));
|
||||
IWL_INFO(mvm, "WFPM_AUTH_KEY_0: 0x%x\n",
|
||||
iwl_read_umac_prph(mvm->trans, SB_MODIFY_CFG_FLAG));
|
||||
iwl_trans_read_umac_prph(mvm->trans, SB_MODIFY_CFG_FLAG));
|
||||
IWL_INFO(mvm, "CNVI_SCU_SEQ_DATA_DW9: 0x%x\n",
|
||||
iwl_read_prph(mvm->trans, CNVI_SCU_SEQ_DATA_DW9));
|
||||
iwl_trans_read_prph(mvm->trans, CNVI_SCU_SEQ_DATA_DW9));
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
|
|
@ -349,15 +349,15 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
|
|||
IWL_DEVICE_FAMILY_22000) {
|
||||
IWL_ERR(mvm,
|
||||
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
|
||||
iwl_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS),
|
||||
iwl_read_umac_prph(trans,
|
||||
UMAG_SB_CPU_2_STATUS));
|
||||
iwl_trans_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS),
|
||||
iwl_trans_read_umac_prph(trans,
|
||||
UMAG_SB_CPU_2_STATUS));
|
||||
} else if (trans->mac_cfg->device_family >=
|
||||
IWL_DEVICE_FAMILY_8000) {
|
||||
IWL_ERR(mvm,
|
||||
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
|
||||
iwl_read_prph(trans, SB_CPU_1_STATUS),
|
||||
iwl_read_prph(trans, SB_CPU_2_STATUS));
|
||||
iwl_trans_read_prph(trans, SB_CPU_1_STATUS),
|
||||
iwl_trans_read_prph(trans, SB_CPU_2_STATUS));
|
||||
}
|
||||
|
||||
iwl_mvm_print_pd_notification(mvm);
|
||||
|
|
@ -374,15 +374,15 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
|
|||
} else if (trans->mac_cfg->device_family >=
|
||||
IWL_DEVICE_FAMILY_9000) {
|
||||
IWL_ERR(mvm, "UMAC PC: 0x%x\n",
|
||||
iwl_read_umac_prph(trans,
|
||||
UREG_UMAC_CURRENT_PC));
|
||||
iwl_trans_read_umac_prph(trans,
|
||||
UREG_UMAC_CURRENT_PC));
|
||||
IWL_ERR(mvm, "LMAC PC: 0x%x\n",
|
||||
iwl_read_umac_prph(trans,
|
||||
UREG_LMAC1_CURRENT_PC));
|
||||
iwl_trans_read_umac_prph(trans,
|
||||
UREG_LMAC1_CURRENT_PC));
|
||||
if (iwl_mvm_is_cdb_supported(mvm))
|
||||
IWL_ERR(mvm, "LMAC2 PC: 0x%x\n",
|
||||
iwl_read_umac_prph(trans,
|
||||
UREG_LMAC2_CURRENT_PC));
|
||||
iwl_trans_read_umac_prph(trans,
|
||||
UREG_LMAC2_CURRENT_PC));
|
||||
}
|
||||
|
||||
if (ret == -ETIMEDOUT && !mvm->fw_product_reset)
|
||||
|
|
@ -616,7 +616,7 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm)
|
|||
mvm->rfkill_safe_init_done = false;
|
||||
|
||||
if (mvm->trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_AX210) {
|
||||
sb_cfg = iwl_read_umac_prph(mvm->trans, SB_MODIFY_CFG_FLAG);
|
||||
sb_cfg = iwl_trans_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())
|
||||
|
|
@ -640,8 +640,7 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm)
|
|||
/* if we needed reset then fail here, but notify and remove */
|
||||
if (mvm->fw_product_reset) {
|
||||
iwl_mei_alive_notif(false);
|
||||
iwl_trans_pcie_reset(mvm->trans,
|
||||
IWL_RESET_MODE_RESCAN);
|
||||
iwl_trans_reset(mvm->trans, IWL_RESET_MODE_RESCAN);
|
||||
}
|
||||
|
||||
goto error;
|
||||
|
|
@ -911,7 +910,8 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
|
|||
|
||||
ret = iwl_sar_fill_profile(&mvm->fwrt, per_chain,
|
||||
IWL_NUM_CHAIN_TABLES,
|
||||
n_subbands, prof_a, prof_b);
|
||||
n_subbands, prof_a, prof_b,
|
||||
mvm->fwrt.sar_profiles, false);
|
||||
|
||||
/* return on error or if the profile is disabled (positive number) */
|
||||
if (ret)
|
||||
|
|
@ -1526,7 +1526,7 @@ static void iwl_mvm_send_lari_cfg_extension(struct iwl_mvm *mvm)
|
|||
u32 value;
|
||||
int ret;
|
||||
|
||||
if (iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 0) < 1)
|
||||
if (iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 0) != 1)
|
||||
return;
|
||||
|
||||
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_REGULATORY_CONFIG, &value);
|
||||
|
|
@ -1576,7 +1576,7 @@ void iwl_mvm_get_bios_tables(struct iwl_mvm *mvm)
|
|||
{
|
||||
int ret;
|
||||
|
||||
iwl_acpi_get_guid_lock_status(&mvm->fwrt);
|
||||
iwl_bios_get_guid_lock_status(&mvm->fwrt);
|
||||
|
||||
/* read PPAG table */
|
||||
ret = iwl_bios_get_ppag_table(&mvm->fwrt);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2019, 2025 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2019, 2025-2026 Intel Corporation
|
||||
* Copyright (C) 2017 Intel Deutschland GmbH
|
||||
*/
|
||||
#include <linux/leds.h>
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "mvm.h"
|
||||
|
||||
|
|
@ -38,8 +38,8 @@ static void iwl_mvm_led_set(struct iwl_mvm *mvm, bool on)
|
|||
return;
|
||||
}
|
||||
|
||||
iwl_write32(mvm->trans, CSR_LED_REG,
|
||||
on ? CSR_LED_REG_TURN_ON : CSR_LED_REG_TURN_OFF);
|
||||
iwl_trans_write32(mvm->trans, CSR_LED_REG,
|
||||
on ? CSR_LED_REG_TURN_ON : CSR_LED_REG_TURN_OFF);
|
||||
}
|
||||
|
||||
static void iwl_led_brightness_set(struct led_classdev *led_cdev,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#include <linux/etherdevice.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <net/mac80211.h>
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "fw-api.h"
|
||||
#include "mvm.h"
|
||||
|
|
@ -932,8 +932,8 @@ u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw, u8 rate_idx)
|
|||
u16 flags = 0;
|
||||
|
||||
if (rate_idx <= IWL_LAST_CCK_RATE)
|
||||
flags |= is_new_rate ? IWL_MAC_BEACON_CCK
|
||||
: IWL_MAC_BEACON_CCK_V1;
|
||||
flags |= is_new_rate ? (u16)IWL_MAC_BEACON_CCK
|
||||
: (u16)IWL_MAC_BEACON_CCK_V1;
|
||||
|
||||
if (iwl_fw_lookup_cmd_ver(fw, TX_CMD, 0) > 8)
|
||||
flags |= iwl_mvm_rate_idx_to_fw_idx(fw, rate_idx);
|
||||
|
|
@ -1109,8 +1109,8 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
|
|||
if (iwl_mvm_enable_fils(mvm, vif, ctx)) {
|
||||
flags |= iwl_fw_lookup_cmd_ver(mvm->fw, BEACON_TEMPLATE_CMD,
|
||||
0) > 10 ?
|
||||
IWL_MAC_BEACON_FILS :
|
||||
IWL_MAC_BEACON_FILS_V1;
|
||||
(u16)IWL_MAC_BEACON_FILS :
|
||||
(u16)IWL_MAC_BEACON_FILS_V1;
|
||||
beacon_cmd.short_ssid =
|
||||
cpu_to_le32(~crc32_le(~0, vif->cfg.ssid,
|
||||
vif->cfg.ssid_len));
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-op-mode.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "mvm.h"
|
||||
#include "sta.h"
|
||||
#include "time-event.h"
|
||||
|
|
@ -5258,7 +5258,7 @@ iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm,
|
|||
|
||||
out_restart:
|
||||
/* things keep failing, better restart the hw */
|
||||
iwl_force_nmi(mvm->trans);
|
||||
iwl_trans_force_nmi(mvm->trans);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -5294,7 +5294,7 @@ iwl_mvm_switch_vif_chanctx_reassign(struct iwl_mvm *mvm,
|
|||
|
||||
out_restart:
|
||||
/* things keep failing, better restart the hw */
|
||||
iwl_force_nmi(mvm->trans);
|
||||
iwl_trans_force_nmi(mvm->trans);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
#define IWL_MVM_MAX_ADDRESSES 5
|
||||
/* RSSI offset for WkP */
|
||||
#define IWL_RSSI_OFFSET 50
|
||||
#define IWL_MVM_MISSED_BEACONS_SINCE_RX_THOLD 4
|
||||
#define IWL_MVM_MISSED_BEACONS_SINCE_RX_THOLD 6
|
||||
#define IWL_MVM_MISSED_BEACONS_THRESHOLD 8
|
||||
#define IWL_MVM_MISSED_BEACONS_THRESHOLD_LONG 19
|
||||
|
||||
|
|
@ -1053,7 +1053,6 @@ struct iwl_mvm {
|
|||
*/
|
||||
struct dentry *debugfs_dir;
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
u32 dbgfs_sram_offset, dbgfs_sram_len;
|
||||
u32 dbgfs_prph_reg_addr;
|
||||
bool disable_power_off;
|
||||
bool disable_power_off_d3;
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
|
|||
.data = { &nvm_access_cmd, },
|
||||
};
|
||||
int ret, bytes_read, offset_read;
|
||||
unsigned int pkt_len;
|
||||
u8 *resp_data;
|
||||
|
||||
cmd.len[0] = sizeof(struct iwl_nvm_access_cmd);
|
||||
|
|
@ -95,6 +96,12 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
|
|||
return ret;
|
||||
|
||||
pkt = cmd.resp_pkt;
|
||||
pkt_len = iwl_rx_packet_payload_len(pkt);
|
||||
if (pkt_len < sizeof(*nvm_resp)) {
|
||||
IWL_ERR(mvm, "NVM ACCESS response too short: %u\n", pkt_len);
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Extract NVM response */
|
||||
nvm_resp = (void *)pkt->data;
|
||||
|
|
@ -133,6 +140,14 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
|
|||
goto exit;
|
||||
}
|
||||
|
||||
if (bytes_read > length ||
|
||||
pkt_len < struct_size(nvm_resp, data, bytes_read)) {
|
||||
IWL_ERR(mvm, "NVM ACCESS response with invalid length %d\n",
|
||||
bytes_read);
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Write data to NVM */
|
||||
memcpy(data + offset, resp_data, bytes_read);
|
||||
ret = bytes_read;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@
|
|||
#include "iwl-phy-db.h"
|
||||
#include "iwl-nvm-utils.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "rs.h"
|
||||
#include "fw/api/scan.h"
|
||||
|
|
@ -138,9 +137,9 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
|
|||
* to lose ownership and not being able to obtain it back.
|
||||
*/
|
||||
if (!mvm->trans->mac_cfg->base->apmg_not_supported)
|
||||
iwl_set_bits_mask_prph(mvm->trans, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
|
||||
~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
|
||||
iwl_trans_set_bits_mask_prph(mvm->trans, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
|
||||
~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
|
||||
}
|
||||
|
||||
static void iwl_mvm_rx_monitor_notif(struct iwl_mvm *mvm,
|
||||
|
|
@ -374,7 +373,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
|
|||
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),
|
||||
struct iwl_umac_scan_iter_complete_notif_v2),
|
||||
|
||||
RX_HANDLER(MISSED_BEACONS_NOTIFICATION,
|
||||
iwl_mvm_rx_missed_beacons_notif_legacy,
|
||||
|
|
|
|||
|
|
@ -99,10 +99,14 @@ static int iwl_mvm_create_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
|
|||
u8 mic_crc_len = u8_get_bits(desc->mac_flags1,
|
||||
IWL_RX_MPDU_MFLG1_MIC_CRC_LEN_MASK) << 1;
|
||||
|
||||
if (desc->mac_flags2 & IWL_RX_MPDU_MFLG2_PAD) {
|
||||
len -= 2;
|
||||
pad_len = 2;
|
||||
}
|
||||
pad_len = desc->mac_flags2 & IWL_RX_MPDU_MFLG2_PAD ? 2 : 0;
|
||||
|
||||
if (IWL_FW_CHECK(mvm, len < hdrlen + crypt_len + pad_len + mic_crc_len,
|
||||
"invalid len (%d): hdrlen=%u, crypt_len=%u, pad_len=%u, mic_crc_len=%u\n",
|
||||
len, hdrlen, crypt_len, pad_len, mic_crc_len))
|
||||
return -EINVAL;
|
||||
|
||||
len -= pad_len;
|
||||
|
||||
/*
|
||||
* For non monitor interface strip the bytes the RADA might not have
|
||||
|
|
@ -110,7 +114,7 @@ static int iwl_mvm_create_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
|
|||
* interface cannot exist with other interfaces, this removal is safe
|
||||
* and sufficient, in monitor mode there's no decryption being done.
|
||||
*/
|
||||
if (len > mic_crc_len && !ieee80211_hw_check(mvm->hw, RX_INCLUDES_FCS))
|
||||
if (!ieee80211_hw_check(mvm->hw, RX_INCLUDES_FCS))
|
||||
len -= mic_crc_len;
|
||||
|
||||
/* If frame is small enough to fit in skb->head, pull it completely.
|
||||
|
|
@ -2164,7 +2168,17 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
phy_data.phy_info = le16_to_cpu(desc->phy_info);
|
||||
phy_data.d4 = desc->phy_data4;
|
||||
|
||||
if (IWL_FW_CHECK(mvm, len < sizeof(hdr->frame_control),
|
||||
"MPDU len (%u) is smaller than frame control\n",
|
||||
len))
|
||||
return;
|
||||
|
||||
hdr = (void *)(pkt->data + desc_size);
|
||||
if (IWL_FW_CHECK(mvm, len < ieee80211_hdrlen(hdr->frame_control),
|
||||
"MPDU len (%u) is smaller than header length (%u)\n",
|
||||
len, ieee80211_hdrlen(hdr->frame_control)))
|
||||
return;
|
||||
|
||||
/* Dont use dev_alloc_skb(), we'll have enough headroom once
|
||||
* ieee80211_hdr pulled.
|
||||
*/
|
||||
|
|
@ -2285,7 +2299,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
struct iwl_fw_dbg_trigger_tlv *trig;
|
||||
struct ieee80211_vif *vif = mvmsta->vif;
|
||||
|
||||
if (!mvm->tcm.paused && len >= sizeof(*hdr) &&
|
||||
if (!mvm->tcm.paused &&
|
||||
!is_multicast_ether_addr(hdr->addr1) &&
|
||||
ieee80211_is_data(hdr->frame_control) &&
|
||||
time_after(jiffies, mvm->tcm.ts + MVM_TCM_PERIOD))
|
||||
|
|
@ -2413,7 +2427,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;
|
||||
struct ieee80211_sta *sta = NULL;
|
||||
struct sk_buff *skb;
|
||||
struct iwl_mvm_rx_phy_data phy_data;
|
||||
u32 format;
|
||||
|
|
@ -2527,9 +2540,7 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
RX_NO_DATA_RX_VEC2_EHT_NSTS_MSK) + 1;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
ieee80211_rx_napi(mvm->hw, sta ? &sta->deflink : NULL, skb, napi);
|
||||
rcu_read_unlock();
|
||||
ieee80211_rx_napi(mvm->hw, NULL, skb, napi);
|
||||
}
|
||||
|
||||
void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#include "mvm.h"
|
||||
#include "fw/api/scan.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-utils.h"
|
||||
|
||||
#define IWL_DENSE_EBS_SCAN_RATIO 5
|
||||
|
|
@ -2703,7 +2703,7 @@ void iwl_mvm_scan_timeout_wk(struct work_struct *work)
|
|||
|
||||
IWL_ERR(mvm, "regular scan timed out\n");
|
||||
|
||||
iwl_force_nmi(mvm->trans);
|
||||
iwl_trans_force_nmi(mvm->trans);
|
||||
}
|
||||
|
||||
static void iwl_mvm_fill_scan_type(struct iwl_mvm *mvm,
|
||||
|
|
@ -3282,7 +3282,7 @@ void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm,
|
|||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_umac_scan_iter_complete_notif *notif = (void *)pkt->data;
|
||||
struct iwl_umac_scan_iter_complete_notif_v2 *notif = (void *)pkt->data;
|
||||
|
||||
mvm->scan_start = le64_to_cpu(notif->start_tsf);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2015, 2018-2025 Intel Corporation
|
||||
* Copyright (C) 2012-2015, 2018-2026 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -2792,7 +2792,11 @@ static int iwl_mvm_fw_baid_op_sta(struct iwl_mvm *mvm,
|
|||
if (WARN_ON(start && iwl_mvm_has_new_rx_api(mvm) &&
|
||||
!(status & IWL_ADD_STA_BAID_VALID_MASK)))
|
||||
return -EINVAL;
|
||||
return u32_get_bits(status, IWL_ADD_STA_BAID_MASK);
|
||||
ret = u32_get_bits(status, IWL_ADD_STA_BAID_MASK);
|
||||
if (IWL_FW_CHECK(mvm, start && ret >= ARRAY_SIZE(mvm->baid_map),
|
||||
"invalid BAID %d from FW\n", ret))
|
||||
return -EINVAL;
|
||||
return ret;
|
||||
case ADD_STA_IMMEDIATE_BA_FAILURE:
|
||||
IWL_WARN(mvm, "RX BA Session refused by fw\n");
|
||||
return -ENOSPC;
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2020, 2022-2025 Intel Corporation
|
||||
* Copyright (C) 2018-2020, 2022-2026 Intel Corporation
|
||||
*/
|
||||
#include <linux/etherdevice.h>
|
||||
#include "mvm.h"
|
||||
#include "time-event.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-prph.h"
|
||||
|
||||
#define TU_TO_US(x) (x * 1024)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
#include "fw-api.h"
|
||||
#include "time-event.h"
|
||||
#include "mvm.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-prph.h"
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "mvm.h"
|
||||
|
|
@ -1159,7 +1159,7 @@ u32 iwl_mvm_get_systime(struct iwl_mvm *mvm)
|
|||
mvm->trans->mac_cfg->base->gp2_reg_addr)
|
||||
reg_addr = mvm->trans->mac_cfg->base->gp2_reg_addr;
|
||||
|
||||
return iwl_read_prph(mvm->trans, reg_addr);
|
||||
return iwl_trans_read_prph(mvm->trans, reg_addr);
|
||||
}
|
||||
|
||||
void iwl_mvm_get_sync_time(struct iwl_mvm *mvm, int clock_type,
|
||||
|
|
@ -1356,8 +1356,8 @@ __le32 iwl_mvm_v3_rate_to_fw(u32 rate, u8 rate_ver)
|
|||
case RATE_MCS_MOD_TYPE_VHT:
|
||||
result = RATE_MCS_VHT_MSK_V1;
|
||||
result |= u32_encode_bits(u32_get_bits(rate,
|
||||
RATE_VHT_MCS_NSS_MSK),
|
||||
RATE_MCS_CODE_MSK);
|
||||
RATE_MCS_CODE_MSK),
|
||||
RATE_VHT_MCS_RATE_CODE_MSK);
|
||||
result |= u32_encode_bits(u32_get_bits(rate, RATE_MCS_NSS_MSK),
|
||||
RATE_VHT_MCS_NSS_MSK);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2018-2025 Intel Corporation
|
||||
* Copyright (C) 2018-2026 Intel Corporation
|
||||
*/
|
||||
#include <linux/dmi.h>
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-fh.h"
|
||||
#include "iwl-context-info-v2.h"
|
||||
#include "gen1_2/internal.h"
|
||||
#include "internal.h"
|
||||
#include "pcie/utils.h"
|
||||
#include "iwl-prph.h"
|
||||
|
||||
static const struct dmi_system_id dmi_force_scu_active_approved_list[] = {
|
||||
|
|
@ -112,6 +113,14 @@ int iwl_pcie_ctxt_info_v2_alloc(struct iwl_trans *trans,
|
|||
int cmdq_size = max_t(u32, IWL_CMD_QUEUE_SIZE,
|
||||
trans->mac_cfg->base->min_txq_size);
|
||||
|
||||
if (WARN_ON_ONCE(trans_pcie->ctxt_info_v2 || trans_pcie->prph_info ||
|
||||
trans_pcie->prph_scratch || trans_pcie->iml ||
|
||||
trans_pcie->ctxt_info_dma_addr ||
|
||||
trans_pcie->prph_info_dma_addr ||
|
||||
trans_pcie->prph_scratch_dma_addr ||
|
||||
trans_pcie->iml_dma_addr || trans_pcie->iml_len))
|
||||
return -EBUSY;
|
||||
|
||||
switch (trans->conf.rx_buf_size) {
|
||||
case IWL_AMSDU_DEF:
|
||||
return -EINVAL;
|
||||
|
|
@ -263,7 +272,6 @@ int iwl_pcie_ctxt_info_v2_alloc(struct iwl_trans *trans,
|
|||
trans_pcie->prph_scratch = prph_scratch;
|
||||
|
||||
/* Allocate IML */
|
||||
trans_pcie->iml_len = fw->iml_len;
|
||||
trans_pcie->iml = dma_alloc_coherent(trans->dev, fw->iml_len,
|
||||
&trans_pcie->iml_dma_addr,
|
||||
GFP_KERNEL);
|
||||
|
|
@ -271,6 +279,7 @@ int iwl_pcie_ctxt_info_v2_alloc(struct iwl_trans *trans,
|
|||
ret = -ENOMEM;
|
||||
goto err_free_ctxt_info;
|
||||
}
|
||||
trans_pcie->iml_len = fw->iml_len;
|
||||
|
||||
memcpy(trans_pcie->iml, fw->iml, fw->iml_len);
|
||||
|
||||
|
|
@ -280,16 +289,21 @@ int iwl_pcie_ctxt_info_v2_alloc(struct iwl_trans *trans,
|
|||
dma_free_coherent(trans->dev, sizeof(*trans_pcie->ctxt_info_v2),
|
||||
trans_pcie->ctxt_info_v2,
|
||||
trans_pcie->ctxt_info_dma_addr);
|
||||
trans_pcie->ctxt_info_dma_addr = 0;
|
||||
trans_pcie->ctxt_info_v2 = NULL;
|
||||
err_free_prph_info:
|
||||
dma_free_coherent(trans->dev, PAGE_SIZE, prph_info,
|
||||
trans_pcie->prph_info_dma_addr);
|
||||
trans_pcie->prph_info_dma_addr = 0;
|
||||
trans_pcie->prph_info = NULL;
|
||||
|
||||
err_free_prph_scratch:
|
||||
dma_free_coherent(trans->dev,
|
||||
sizeof(*prph_scratch),
|
||||
prph_scratch,
|
||||
trans_pcie->prph_scratch_dma_addr);
|
||||
trans_pcie->prph_scratch_dma_addr = 0;
|
||||
trans_pcie->prph_scratch = NULL;
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
|
@ -301,12 +315,12 @@ void iwl_pcie_ctxt_info_v2_kick(struct iwl_trans *trans)
|
|||
iwl_enable_fw_load_int_ctx_info(trans, trans->do_top_reset);
|
||||
|
||||
/* kick FW self load */
|
||||
iwl_write64(trans, CSR_CTXT_INFO_ADDR, trans_pcie->ctxt_info_dma_addr);
|
||||
iwl_write64(trans, CSR_IML_DATA_ADDR, trans_pcie->iml_dma_addr);
|
||||
iwl_write32(trans, CSR_IML_SIZE_ADDR, trans_pcie->iml_len);
|
||||
iwl_pcie_write64(trans, CSR_CTXT_INFO_ADDR, trans_pcie->ctxt_info_dma_addr);
|
||||
iwl_pcie_write64(trans, CSR_IML_DATA_ADDR, trans_pcie->iml_dma_addr);
|
||||
iwl_trans_pcie_write32(trans, CSR_IML_SIZE_ADDR, trans_pcie->iml_len);
|
||||
|
||||
iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL,
|
||||
CSR_AUTO_FUNC_BOOT_ENA);
|
||||
iwl_trans_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL,
|
||||
CSR_AUTO_FUNC_BOOT_ENA);
|
||||
}
|
||||
|
||||
void iwl_pcie_ctxt_info_v2_free(struct iwl_trans *trans, bool alive)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user