diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi')
101 files changed, 2774 insertions, 1181 deletions
| diff --git a/drivers/net/wireless/intel/iwlwifi/Makefile b/drivers/net/wireless/intel/iwlwifi/Makefile index d86918d162aa..0d4656efe908 100644 --- a/drivers/net/wireless/intel/iwlwifi/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/Makefile @@ -15,7 +15,7 @@ iwlwifi-objs		+= iwl-dbg-tlv.o  iwlwifi-objs		+= iwl-trans.o  iwlwifi-objs		+= queue/tx.o -iwlwifi-objs		+= fw/img.o fw/notif-wait.o +iwlwifi-objs		+= fw/img.o fw/notif-wait.o fw/rs.o  iwlwifi-objs		+= fw/dbg.o fw/pnvm.o fw/dump.o  iwlwifi-$(CONFIG_IWLMVM) += fw/paging.o fw/smem.o fw/init.o  iwlwifi-$(CONFIG_ACPI) += fw/acpi.o diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/1000.c b/drivers/net/wireless/intel/iwlwifi/cfg/1000.c index 44c4fe975390..116defb15afb 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/1000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/1000.c @@ -3,11 +3,6 @@   *   * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.   * Copyright(c) 2018 - 2020 Intel Corporation - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #include <linux/module.h> diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/2000.c b/drivers/net/wireless/intel/iwlwifi/cfg/2000.c index df6ac00340b2..ab2038a3fbe2 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/2000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/2000.c @@ -3,11 +3,6 @@   *   * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.   * Copyright(c) 2018 - 2020 Intel Corporation - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #include <linux/module.h> diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index d8231cc821ae..1572097bccf1 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -9,7 +9,7 @@  #include "iwl-prph.h"  /* Highest firmware API version supported */ -#define IWL_22000_UCODE_API_MAX	66 +#define IWL_22000_UCODE_API_MAX	67  /* Lowest firmware API version supported */  #define IWL_22000_UCODE_API_MIN	39 @@ -53,6 +53,9 @@  #define IWL_BZ_A_GF_A_FW_PRE		"iwlwifi-bz-a0-gf-a0-"  #define IWL_BZ_A_GF4_A_FW_PRE		"iwlwifi-bz-a0-gf4-a0-"  #define IWL_BZ_A_MR_A_FW_PRE		"iwlwifi-bz-a0-mr-a0-" +#define IWL_BZ_A_FM_A_FW_PRE		"iwlwifi-bz-a0-fm-a0-" +#define IWL_GL_A_FM_A_FW_PRE		"iwlwifi-gl-a0-fm7-a0-" +  #define IWL_QU_B_HR_B_MODULE_FIRMWARE(api) \  	IWL_QU_B_HR_B_FW_PRE __stringify(api) ".ucode" @@ -106,6 +109,10 @@  	IWL_BZ_A_GF4_A_FW_PRE __stringify(api) ".ucode"  #define IWL_BZ_A_MR_A_MODULE_FIRMWARE(api) \  	IWL_BZ_A_MR_A_FW_PRE __stringify(api) ".ucode" +#define IWL_BZ_A_FM_A_MODULE_FIRMWARE(api) \ +		IWL_BZ_A_FM_A_FW_PRE __stringify(api) ".ucode" +#define IWL_GL_A_FM_A_MODULE_FIRMWARE(api) \ +		IWL_GL_A_FM_A_FW_PRE __stringify(api) ".ucode"  static const struct iwl_base_params iwl_22000_base_params = {  	.eeprom_size = OTP_LOW_IMAGE_SIZE_32K, @@ -355,7 +362,7 @@ const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg = {  	.base_params = &iwl_ax210_base_params,  	.umac_prph_offset = 0x300000,  	.integrated = true, -	/* TODO: the following values need to be checked */ +	.low_latency_xtal = true,  	.xtal_latency = 12000,  	.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,  }; @@ -469,6 +476,14 @@ const char iwl_ax210_killer_1675w_name[] =  	"Killer(R) Wi-Fi 6E AX1675w 160MHz Wireless Network Adapter (210D2W)";  const char iwl_ax210_killer_1675x_name[] =  	"Killer(R) Wi-Fi 6E AX1675x 160MHz Wireless Network Adapter (210NGW)"; +const char iwl_ax211_killer_1675s_name[] = +	"Killer(R) Wi-Fi 6E AX1675s 160MHz Wireless Network Adapter (211NGW)"; +const char iwl_ax211_killer_1675i_name[] = +	"Killer(R) Wi-Fi 6E AX1675i 160MHz Wireless Network Adapter (211NGW)"; +const char iwl_ax411_killer_1690s_name[] = +	"Killer(R) Wi-Fi 6E AX1690s 160MHz Wireless Network Adapter (411D2W)"; +const char iwl_ax411_killer_1690i_name[] = +	"Killer(R) Wi-Fi 6E AX1690i 160MHz Wireless Network Adapter (411NGW)";  const struct iwl_cfg iwl_qu_b0_hr1_b0 = {  	.fw_name_pre = IWL_QU_B_HR_B_FW_PRE, @@ -850,6 +865,20 @@ const struct iwl_cfg iwl_cfg_bz_a0_mr_a0 = {  	.num_rbds = IWL_NUM_RBDS_AX210_HE,  }; +const struct iwl_cfg iwl_cfg_bz_a0_fm_a0 = { +	.fw_name_pre = IWL_BZ_A_FM_A_FW_PRE, +	.uhb_supported = true, +	IWL_DEVICE_BZ, +	.num_rbds = IWL_NUM_RBDS_AX210_HE, +}; + +const struct iwl_cfg iwl_cfg_gl_a0_fm_a0 = { +	.fw_name_pre = IWL_GL_A_FM_A_FW_PRE, +	.uhb_supported = true, +	IWL_DEVICE_BZ, +	.num_rbds = IWL_NUM_RBDS_AX210_HE, +}; +  MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));  MODULE_FIRMWARE(IWL_QNJ_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));  MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); @@ -876,3 +905,5 @@ MODULE_FIRMWARE(IWL_BZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));  MODULE_FIRMWARE(IWL_BZ_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));  MODULE_FIRMWARE(IWL_BZ_A_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));  MODULE_FIRMWARE(IWL_BZ_A_MR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_BZ_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_GL_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/5000.c b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c index 6cdd7d983bda..e2e23d2bc1fe 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/5000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c @@ -3,11 +3,6 @@   *   * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.   * Copyright(c) 2018 - 2020 Intel Corporation - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #include <linux/module.h> diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/6000.c b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c index 541a3ec85777..20929e59c2f4 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/6000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c @@ -3,11 +3,6 @@   *   * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.   * Copyright(c) 2018 - 2020 Intel Corporation - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #include <linux/module.h> diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/agn.h b/drivers/net/wireless/intel/iwlwifi/dvm/agn.h index 1276df1c7a55..abb8696ba294 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/agn.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/agn.h @@ -1,6 +1,6 @@  /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */  /* - * Copyright (C) 2005-2014 Intel Corporation + * Copyright (C) 2005-2014, 2021 Intel Corporation   */  #ifndef __iwl_agn_h__  #define __iwl_agn_h__ @@ -398,8 +398,10 @@ do {									\  	if (!iwl_is_rfkill((m)))					\  		IWL_ERR(m, fmt, ##args);				\  	else								\ -		__iwl_err((m)->dev, true,				\ -			  !iwl_have_debug_level(IWL_DL_RADIO),		\ +		__iwl_err((m)->dev,					\ +			  iwl_have_debug_level(IWL_DL_RADIO) ?		\ +				IWL_ERR_MODE_RFKILL :			\ +				IWL_ERR_MODE_TRACE_ONLY,		\  			  fmt, ##args);					\  } while (0)  #else @@ -408,7 +410,8 @@ do {									\  	if (!iwl_is_rfkill((m)))					\  		IWL_ERR(m, fmt, ##args);				\  	else								\ -		__iwl_err((m)->dev, true, true, fmt, ##args);	\ +		__iwl_err((m)->dev, IWL_ERR_MODE_TRACE_ONLY,		\ +			  fmt, ##args);					\  } while (0)  #endif				/* CONFIG_IWLWIFI_DEBUG */ diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/commands.h b/drivers/net/wireless/intel/iwlwifi/dvm/commands.h index 235c7a2e3483..75a4b8e26232 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/commands.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/commands.h @@ -1251,8 +1251,10 @@ struct iwl_tx_cmd {  	 * MAC header goes here, followed by 2 bytes padding if MAC header  	 * length is 26 or 30 bytes, followed by payload data  	 */ -	u8 payload[0]; -	struct ieee80211_hdr hdr[]; +	union { +		DECLARE_FLEX_ARRAY(u8, payload); +		DECLARE_FLEX_ARRAY(struct ieee80211_hdr, hdr); +	};  } __packed;  /* diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c index 911049201838..b246dbd371b3 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c @@ -3,10 +3,6 @@   *   * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.   * Copyright (C) 2018 Intel Corporation - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497   *****************************************************************************/  #include <linux/slab.h> diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/dev.h b/drivers/net/wireless/intel/iwlwifi/dvm/dev.h index 4bd792c06ff6..bbd574091201 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/dev.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/dev.h @@ -2,11 +2,6 @@  /******************************************************************************   *   * Copyright(c) 2003 - 2014, 2020 Intel Corporation. All rights reserved. - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  /*   * Please use this file (dev.h) for driver implementation definitions. diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/devices.c b/drivers/net/wireless/intel/iwlwifi/dvm/devices.c index c3e25885d194..39e40901fa46 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/devices.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/devices.c @@ -3,11 +3,6 @@   *   * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.   * Copyright (C) 2019 Intel Corporation - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #include <linux/units.h> diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/led.c b/drivers/net/wireless/intel/iwlwifi/dvm/led.c index e8a4d604b910..71f67a019cf6 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/led.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/led.c @@ -3,11 +3,6 @@   *   * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.   * Copyright (C) 2019 Intel Corporation - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/ diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/led.h b/drivers/net/wireless/intel/iwlwifi/dvm/led.h index 6fe20180dc87..5038fc378a1f 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/led.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/led.h @@ -2,11 +2,6 @@  /******************************************************************************   *   * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #ifndef __iwl_leds_h__ diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/lib.c b/drivers/net/wireless/intel/iwlwifi/dvm/lib.c index 3b937a7dd403..40d790b36d85 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/lib.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/lib.c @@ -2,11 +2,6 @@  /******************************************************************************   *   * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #include <linux/etherdevice.h>  #include <linux/kernel.h> diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c index 75e7665773c5..754876cd27ce 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c @@ -6,11 +6,6 @@   *   * Portions of this file are derived from the ipw3945 project, as well   * as portions of the ieee80211 subsystem header files. - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #include <linux/kernel.h>  #include <linux/module.h> diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/main.c b/drivers/net/wireless/intel/iwlwifi/dvm/main.c index cc7b69fd14d3..fbd57a2b2bd5 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/main.c @@ -6,11 +6,6 @@   *   * Portions of this file are derived from the ipw3945 project, as well   * as portions of the ieee80211 subsystem header files. - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -52,7 +47,6 @@  #define DRV_DESCRIPTION	"Intel(R) Wireless WiFi Link AGN driver for Linux"  MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_AUTHOR);  MODULE_LICENSE("GPL");  /* Please keep this array *SORTED* by hex value. @@ -1525,7 +1519,6 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)  	kfree(priv->nvm_data);  	/*netif_stop_queue(dev); */ -	flush_workqueue(priv->workqueue);  	/* ieee80211_unregister_hw calls iwlagn_mac_stop, which flushes  	 * priv->workqueue... so we can't take down the workqueue diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/power.c b/drivers/net/wireless/intel/iwlwifi/dvm/power.c index 93ef023905c9..6d16a7105656 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/power.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/power.c @@ -6,10 +6,6 @@   *   * Portions of this file are derived from the ipw3945 project, as well   * as portions of the ieee80211 subsystem header files. - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497   *****************************************************************************/ diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/power.h b/drivers/net/wireless/intel/iwlwifi/dvm/power.h index 3f8db1fc4b59..f38201ce1e99 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/power.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/power.h @@ -5,10 +5,6 @@   *   * Portions of this file are derived from the ipw3945 project, as well   * as portions of the ieee80211 subsystem header files. - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497   *****************************************************************************/  #ifndef __iwl_power_setting_h__  #define __iwl_power_setting_h__ diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c index 548540dd0c0f..b7c8b209bfea 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c @@ -3,11 +3,6 @@   *   * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.   * Copyright (C) 2019 - 2020 Intel Corporation - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #include <linux/kernel.h>  #include <linux/skbuff.h> diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rs.h b/drivers/net/wireless/intel/iwlwifi/dvm/rs.h index 68a840d739e8..0b47f1993c5d 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rs.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rs.h @@ -2,11 +2,6 @@  /******************************************************************************   *   * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #ifndef __iwl_agn_rs_h__ diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c index 3cd7b423c588..db0c41bbeb0e 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c @@ -7,11 +7,6 @@   *   * Portions of this file are derived from the ipw3945 project, as well   * as portionhelp of the ieee80211 subsystem header files. - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #include <linux/etherdevice.h> diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c b/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c index 12a3d464ae64..70338bc7bb54 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c @@ -3,11 +3,6 @@   *   * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.   * Copyright(c) 2015 Intel Deutschland GmbH - * - * Contact Information: - * Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #include <linux/etherdevice.h> diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/scan.c b/drivers/net/wireless/intel/iwlwifi/dvm/scan.c index c4ecf6ed2186..2d38227dfdd2 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/scan.c @@ -3,10 +3,6 @@   *   * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.   * Copyright(c) 2018        Intel Corporation - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497   *****************************************************************************/  #include <linux/slab.h>  #include <linux/types.h> diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/sta.c b/drivers/net/wireless/intel/iwlwifi/dvm/sta.c index ddc14059b07d..8f7a0f36c276 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/sta.c @@ -5,11 +5,6 @@   *   * Portions of this file are derived from the ipw3945 project, as well   * as portions of the ieee80211 subsystem header files. - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #include <linux/etherdevice.h>  #include <net/mac80211.h> diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tt.c b/drivers/net/wireless/intel/iwlwifi/dvm/tt.c index 2684a924ba57..43e8d04d5a8b 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/tt.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/tt.c @@ -6,10 +6,6 @@   *   * Portions of this file are derived from the ipw3945 project, as well   * as portions of the ieee80211 subsystem header files. - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497   *****************************************************************************/ diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tt.h b/drivers/net/wireless/intel/iwlwifi/dvm/tt.h index 3b0ff458a158..7ace052fc78a 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/tt.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/tt.h @@ -5,10 +5,6 @@   *   * Portions of this file are derived from the ipw3945 project, as well   * as portions of the ieee80211 subsystem header files. - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497   *****************************************************************************/  #ifndef __iwl_tt_setting_h__  #define __iwl_tt_setting_h__ diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c index 847b8e07f81c..60a7b61d59aa 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c @@ -3,11 +3,6 @@   *   * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.   * Copyright (C) 2019 Intel Corporation - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #include <linux/kernel.h> diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c b/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c index 24194c791218..4b27a53d0bb4 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c @@ -3,11 +3,6 @@   *   * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.   * Copyright(c) 2015 Intel Deutschland GmbH - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #include <linux/kernel.h> diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c index 1efac0b2a94d..bf431fa4fe81 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c @@ -184,9 +184,11 @@ int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func,  }  IWL_EXPORT_SYMBOL(iwl_acpi_get_dsm_u32); -union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev, -					 union acpi_object *data, -					 int data_size, int *tbl_rev) +union acpi_object *iwl_acpi_get_wifi_pkg_range(struct device *dev, +					       union acpi_object *data, +					       int min_data_size, +					       int max_data_size, +					       int *tbl_rev)  {  	int i;  	union acpi_object *wifi_pkg; @@ -196,7 +198,7 @@ union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,  	 * describes the domain, and one more entry, otherwise there's  	 * no point in reading it.  	 */ -	if (WARN_ON_ONCE(data_size < 2)) +	if (WARN_ON_ONCE(min_data_size < 2 || min_data_size > max_data_size))  		return ERR_PTR(-EINVAL);  	/* @@ -222,7 +224,8 @@ union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,  		/* skip entries that are not a package with the right size */  		if (wifi_pkg->type != ACPI_TYPE_PACKAGE || -		    wifi_pkg->package.count != data_size) +		    wifi_pkg->package.count < min_data_size || +		    wifi_pkg->package.count > max_data_size)  			continue;  		domain = &wifi_pkg->package.elements[0]; @@ -236,7 +239,7 @@ union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,  found:  	return wifi_pkg;  } -IWL_EXPORT_SYMBOL(iwl_acpi_get_wifi_pkg); +IWL_EXPORT_SYMBOL(iwl_acpi_get_wifi_pkg_range);  int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt,  		     __le32 *block_list_array, @@ -707,49 +710,103 @@ int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt)  {  	union acpi_object *wifi_pkg, *data;  	int i, j, k, ret, tbl_rev; -	int idx = 1; /* start from one to skip the domain */ -	u8 num_bands; +	u8 num_bands, num_profiles; +	static const struct { +		u8 revisions; +		u8 bands; +		u8 profiles; +		u8 min_profiles; +	} rev_data[] = { +		{ +			.revisions = BIT(3), +			.bands = ACPI_GEO_NUM_BANDS_REV2, +			.profiles = ACPI_NUM_GEO_PROFILES_REV3, +			.min_profiles = 3, +		}, +		{ +			.revisions = BIT(2), +			.bands = ACPI_GEO_NUM_BANDS_REV2, +			.profiles = ACPI_NUM_GEO_PROFILES, +		}, +		{ +			.revisions = BIT(0) | BIT(1), +			.bands = ACPI_GEO_NUM_BANDS_REV0, +			.profiles = ACPI_NUM_GEO_PROFILES, +		}, +	}; +	int idx; +	/* start from one to skip the domain */ +	int entry_idx = 1; + +	BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES_REV3 != IWL_NUM_GEO_PROFILES_V3); +	BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES != IWL_NUM_GEO_PROFILES);  	data = iwl_acpi_get_object(fwrt->dev, ACPI_WGDS_METHOD);  	if (IS_ERR(data))  		return PTR_ERR(data); -	/* start by trying to read revision 2 */ -	wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data, -					 ACPI_WGDS_WIFI_DATA_SIZE_REV2, -					 &tbl_rev); -	if (!IS_ERR(wifi_pkg)) { -		if (tbl_rev != 2) { -			ret = PTR_ERR(wifi_pkg); -			goto out_free; -		} - -		num_bands = ACPI_GEO_NUM_BANDS_REV2; - -		goto read_table; -	} - -	/* then try revision 0 (which is the same as 1) */ -	wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data, -					 ACPI_WGDS_WIFI_DATA_SIZE_REV0, -					 &tbl_rev); -	if (!IS_ERR(wifi_pkg)) { -		if (tbl_rev != 0 && tbl_rev != 1) { -			ret = PTR_ERR(wifi_pkg); -			goto out_free; +	/* read the highest revision we understand first */ +	for (idx = 0; idx < ARRAY_SIZE(rev_data); idx++) { +		/* min_profiles != 0 requires num_profiles header */ +		u32 hdr_size = 1 + !!rev_data[idx].min_profiles; +		u32 profile_size = ACPI_GEO_PER_CHAIN_SIZE * +				   rev_data[idx].bands; +		u32 max_size = hdr_size + profile_size * rev_data[idx].profiles; +		u32 min_size; + +		if (!rev_data[idx].min_profiles) +			min_size = max_size; +		else +			min_size = hdr_size + +				   profile_size * rev_data[idx].min_profiles; + +		wifi_pkg = iwl_acpi_get_wifi_pkg_range(fwrt->dev, data, +						       min_size, max_size, +						       &tbl_rev); +		if (!IS_ERR(wifi_pkg)) { +			if (!(BIT(tbl_rev) & rev_data[idx].revisions)) +				continue; + +			num_bands = rev_data[idx].bands; +			num_profiles = rev_data[idx].profiles; + +			if (rev_data[idx].min_profiles) { +				/* read header that says # of profiles */ +				union acpi_object *entry; + +				entry = &wifi_pkg->package.elements[entry_idx]; +				entry_idx++; +				if (entry->type != ACPI_TYPE_INTEGER || +				    entry->integer.value > num_profiles) { +					ret = -EINVAL; +					goto out_free; +				} +				num_profiles = entry->integer.value; + +				/* +				 * this also validates >= min_profiles since we +				 * otherwise wouldn't have gotten the data when +				 * looking up in ACPI +				 */ +				if (wifi_pkg->package.count != +				    min_size + profile_size * num_profiles) { +					ret = -EINVAL; +					goto out_free; +				} +			} +			goto read_table;  		} - -		num_bands = ACPI_GEO_NUM_BANDS_REV0; - -		goto read_table;  	} -	ret = PTR_ERR(wifi_pkg); +	if (idx < ARRAY_SIZE(rev_data)) +		ret = PTR_ERR(wifi_pkg); +	else +		ret = -ENOENT;  	goto out_free;  read_table:  	fwrt->geo_rev = tbl_rev; -	for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) { +	for (i = 0; i < num_profiles; i++) {  		for (j = 0; j < ACPI_GEO_NUM_BANDS_REV2; j++) {  			union acpi_object *entry; @@ -762,7 +819,8 @@ read_table:  				fwrt->geo_profiles[i].bands[j].max =  					fwrt->geo_profiles[i].bands[1].max;  			} else { -				entry = &wifi_pkg->package.elements[idx++]; +				entry = &wifi_pkg->package.elements[entry_idx]; +				entry_idx++;  				if (entry->type != ACPI_TYPE_INTEGER ||  				    entry->integer.value > U8_MAX) {  					ret = -EINVAL; @@ -779,7 +837,8 @@ read_table:  					fwrt->geo_profiles[i].bands[j].chains[k] =  						fwrt->geo_profiles[i].bands[1].chains[k];  				} else { -					entry = &wifi_pkg->package.elements[idx++]; +					entry = &wifi_pkg->package.elements[entry_idx]; +					entry_idx++;  					if (entry->type != ACPI_TYPE_INTEGER ||  					    entry->integer.value > U8_MAX) {  						ret = -EINVAL; @@ -803,10 +862,10 @@ IWL_EXPORT_SYMBOL(iwl_sar_get_wgds_table);  bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt)  {  	/* -	 * The GEO_TX_POWER_LIMIT 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 +	 * 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 @@ -822,14 +881,15 @@ bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt)  IWL_EXPORT_SYMBOL(iwl_sar_geo_support);  int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt, -		     struct iwl_per_chain_offset *table, u32 n_bands) +		     struct iwl_per_chain_offset *table, +		     u32 n_bands, u32 n_profiles)  {  	int i, j;  	if (!iwl_sar_geo_support(fwrt))  		return -EOPNOTSUPP; -	for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) { +	for (i = 0; i < n_profiles; i++) {  		for (j = 0; j < n_bands; j++) {  			struct iwl_per_chain_offset *chain =  				&table[i * n_bands + j]; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h index 16ed0995b51e..4aaa8a6b071b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h @@ -29,6 +29,7 @@  #define ACPI_SAR_PROFILE_NUM		4  #define ACPI_NUM_GEO_PROFILES		3 +#define ACPI_NUM_GEO_PROFILES_REV3	8  #define ACPI_GEO_PER_CHAIN_SIZE		3  #define ACPI_SAR_NUM_CHAINS_REV0	2 @@ -59,13 +60,6 @@  #define ACPI_GEO_NUM_BANDS_REV2		3  #define ACPI_GEO_NUM_CHAINS		2 -#define ACPI_WGDS_WIFI_DATA_SIZE_REV0	(ACPI_NUM_GEO_PROFILES *   \ -					 ACPI_GEO_NUM_BANDS_REV0 * \ -					 ACPI_GEO_PER_CHAIN_SIZE + 1) -#define ACPI_WGDS_WIFI_DATA_SIZE_REV2	(ACPI_NUM_GEO_PROFILES *   \ -					 ACPI_GEO_NUM_BANDS_REV2 * \ -					 ACPI_GEO_PER_CHAIN_SIZE + 1) -  #define ACPI_WRDD_WIFI_DATA_SIZE	2  #define ACPI_SPLC_WIFI_DATA_SIZE	2  #define ACPI_ECKV_WIFI_DATA_SIZE	2 @@ -115,8 +109,10 @@ enum iwl_dsm_funcs_rev_0 {  	DSM_FUNC_QUERY = 0,  	DSM_FUNC_DISABLE_SRD = 1,  	DSM_FUNC_ENABLE_INDONESIA_5G2 = 2, +	DSM_FUNC_ENABLE_6E = 3,  	DSM_FUNC_11AX_ENABLEMENT = 6, -	DSM_FUNC_ENABLE_UNII4_CHAN = 7 +	DSM_FUNC_ENABLE_UNII4_CHAN = 7, +	DSM_FUNC_ACTIVATE_CHANNEL = 8  };  enum iwl_dsm_values_srd { @@ -158,10 +154,11 @@ int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func,  int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func,  			 const guid_t *guid, u32 *value); -union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev, -					 union acpi_object *data, -					 int data_size, int *tbl_rev); - +union acpi_object *iwl_acpi_get_wifi_pkg_range(struct device *dev, +					       union acpi_object *data, +					       int min_data_size, +					       int max_data_size, +					       int *tbl_rev);  /**   * iwl_acpi_get_mcc - read MCC from ACPI, if available   * @@ -198,7 +195,8 @@ int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt);  bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt);  int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt, -		     struct iwl_per_chain_offset *table, u32 n_bands); +		     struct iwl_per_chain_offset *table, +		     u32 n_bands, u32 n_profiles);  int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt, __le32 *block_list_array,  		     int *block_list_size); @@ -230,10 +228,11 @@ static inline int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func,  	return -ENOENT;  } -static inline union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev, -						       union acpi_object *data, -						       int data_size, -						       int *tbl_rev) +static inline union acpi_object * +iwl_acpi_get_wifi_pkg_range(struct device *dev, +			    union acpi_object *data, +			    int min_data_size, int max_data_size, +			    int *tbl_rev)  {  	return ERR_PTR(-ENOENT);  } @@ -293,4 +292,14 @@ static inline __le32 iwl_acpi_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt  }  #endif /* CONFIG_ACPI */ + +static inline union acpi_object * +iwl_acpi_get_wifi_pkg(struct device *dev, +		      union acpi_object *data, +		      int data_size, int *tbl_rev) +{ +	return iwl_acpi_get_wifi_pkg_range(dev, data, data_size, data_size, +					   tbl_rev); +} +  #endif /* __iwl_fw_acpi__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h index 3ec82cae3981..1503119ea910 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h @@ -624,7 +624,7 @@ struct iwl_wowlan_status_v6 {  } __packed; /* WOWLAN_STATUSES_API_S_VER_6 */  /** - * struct iwl_wowlan_status - WoWLAN status + * struct iwl_wowlan_status_v7 - WoWLAN status   * @gtk: GTK data   * @igtk: IGTK data   * @replay_ctr: GTK rekey replay counter @@ -693,49 +693,6 @@ struct iwl_wowlan_status_v9 {  	u8 wake_packet[]; /* can be truncated from _length to _bufsize */  } __packed; /* WOWLAN_STATUSES_RSP_API_S_VER_9 */ -/** - * struct iwl_wowlan_status - WoWLAN status - * @gtk: GTK data - * @igtk: IGTK data - * @bigtk: BIGTK 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 - * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason - * @num_of_gtk_rekeys: number of GTK rekeys - * @tid_tear_down: bitmap of TIDs torn down - * @reserved: reserved - * @received_beacons: number of received beacons - * @wake_packet_length: wakeup packet length - * @wake_packet_bufsize: wakeup packet buffer size - * @tid_tear_down: bit mask of tids whose BA sessions were closed - *		   in suspend state - * @wake_packet: wakeup packet - */ -struct iwl_wowlan_status { -	struct iwl_wowlan_gtk_status gtk[1]; -	struct iwl_wowlan_igtk_status igtk[1]; -	struct iwl_wowlan_igtk_status bigtk[WOWLAN_IGTK_KEYS_NUM]; -	__le64 replay_ctr; -	__le16 pattern_number; -	__le16 non_qos_seq_ctr; -	__le16 qos_seq_ctr[8]; -	__le32 wakeup_reasons; -	__le32 num_of_gtk_rekeys; -	u8 tid_tear_down; -	u8 reserved[3]; -	__le32 received_beacons; -	__le32 wake_packet_length; -	__le32 wake_packet_bufsize; -	u8 wake_packet[]; /* can be truncated from _length to _bufsize */ -} __packed; /* WOWLAN_STATUSES_API_S_VER_11 */ - -static inline u8 iwlmvm_wowlan_gtk_idx(struct iwl_wowlan_gtk_status *gtk) -{ -	return gtk->key_flags & IWL_WOWLAN_GTK_IDX_MASK; -} -  /* TODO: NetDetect API */  #endif /* __iwl_fw_api_d3_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h index d8b5870d6e9a..3988f5fea33a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h @@ -7,6 +7,7 @@  #include <linux/bitops.h> +#define IWL_FW_INI_HW_SMEM_REGION_ID		15  #define IWL_FW_INI_MAX_REGION_ID		64  #define IWL_FW_INI_MAX_NAME			32  #define IWL_FW_INI_MAX_CFG_NAME			64 @@ -243,6 +244,62 @@ struct iwl_fw_ini_hcmd_tlv {  } __packed; /* FW_TLV_DEBUG_HCMD_API_S_VER_1 */  /** +* struct iwl_fw_ini_conf_tlv - preset configuration TLV +* +* @address: the base address +* @value: value to set at address + +*/ +struct iwl_fw_ini_addr_val { +	__le32 address; +	__le32 value; +} __packed; /* FW_TLV_DEBUG_ADDR_VALUE_VER_1 */ + +/** + * struct iwl_fw_ini_conf_tlv - configuration TLV to set register/memory. + * + * @hdr: debug header + * @time_point: time point to apply config. One of &enum iwl_fw_ini_time_point + * @set_type: write access type preset token for time point. + *  one of &enum iwl_fw_ini_config_set_type + * @addr_offset: the offset to add to any item in address[0] field + * @addr_val: address value pair + */ +struct iwl_fw_ini_conf_set_tlv { +	struct iwl_fw_ini_header hdr; +	__le32 time_point; +	__le32 set_type; +	__le32 addr_offset; +	struct iwl_fw_ini_addr_val addr_val[0]; +} __packed; /* FW_TLV_DEBUG_CONFIG_SET_API_S_VER_1 */ + +/** + * enum iwl_fw_ini_config_set_type + * + * @IWL_FW_INI_CONFIG_SET_TYPE_INVALID: invalid config set + * @IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_MAC: for PERIPHERY MAC configuration + * @IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_PHY: for PERIPHERY PHY configuration + * @IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_AUX: for PERIPHERY AUX configuration + * @IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_MEMORY: for DEVICE MEMORY configuration + * @IWL_FW_INI_CONFIG_SET_TYPE_CSR: for CSR configuration + * @IWL_FW_INI_CONFIG_SET_TYPE_DBGC_DRAM_ADDR: for DBGC_DRAM_ADDR configuration + * @IWL_FW_INI_CONFIG_SET_TYPE_PERIPH_SCRATCH_HWM: for PERIPH SCRATCH HWM configuration + * @IWL_FW_INI_ALLOCATION_NUM: max number of configuration supported +*/ + +enum iwl_fw_ini_config_set_type { +	IWL_FW_INI_CONFIG_SET_TYPE_INVALID = 0, +	IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_MAC, +	IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_PHY, +	IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_AUX, +	IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_MEMORY, +	IWL_FW_INI_CONFIG_SET_TYPE_CSR, +	IWL_FW_INI_CONFIG_SET_TYPE_DBGC_DRAM_ADDR, +	IWL_FW_INI_CONFIG_SET_TYPE_PERIPH_SCRATCH_HWM, +	IWL_FW_INI_CONFIG_SET_TYPE_MAX_NUM, +} __packed; + +/**   * enum iwl_fw_ini_allocation_id   *   * @IWL_FW_INI_ALLOCATION_INVALID: invalid diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h b/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h index 8adccd5da095..029ae64bf2b2 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h @@ -361,6 +361,41 @@ struct iwl_buf_alloc_cmd {  	struct iwl_buf_alloc_frag frags[BUF_ALLOC_MAX_NUM_FRAGS];  } __packed; /* BUFFER_ALLOCATION_CMD_API_S_VER_2 */ +#define DRAM_INFO_FIRST_MAGIC_WORD 0x76543210 +#define DRAM_INFO_SECOND_MAGIC_WORD 0x89ABCDEF + +/** + * struct iwL_dram_info - DRAM fragments allocation struct + * + * Driver will fill in the first 1K(+) of the pointed DRAM fragment + * + * @first_word: magic word value + * @second_word: magic word value + * @framfrags: DRAM fragmentaion detail +*/ +struct iwl_dram_info { +	__le32 first_word; +	__le32 second_word; +	struct iwl_buf_alloc_cmd dram_frags[IWL_FW_INI_ALLOCATION_NUM - 1]; +} __packed; /* INIT_DRAM_FRAGS_ALLOCATIONS_S_VER_1 */ + +/** + * struct iwl_dbgc1_info - DBGC1 address and size + * + * Driver will fill the dbcg1 address and size at address based on config TLV. + * + * @first_word: all 0 set as identifier + * @dbgc1_add_lsb: LSB bits of DBGC1 physical address + * @dbgc1_add_msb: MSB bits of DBGC1 physical address + * @dbgc1_size: DBGC1 size +*/ +struct iwl_dbgc1_info { +	__le32 first_word; +	__le32 dbgc1_add_lsb; +	__le32 dbgc1_add_msb; +	__le32 dbgc1_size; +} __packed; /* INIT_DRAM_FRAGS_ALLOCATIONS_S_VER_1 */ +  /**   * struct iwl_dbg_host_event_cfg_cmd   * @enabled_severities: enabled severities diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h index 6bbb8b8c91cd..12af94e166ed 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h @@ -206,7 +206,7 @@ enum iwl_tof_responder_cfg_flags {  	IWL_TOF_RESPONDER_FLAGS_SPECIFIC_CALIB_MODE = BIT(8),  	IWL_TOF_RESPONDER_FLAGS_FAST_ALGO_SUPPORT = BIT(9),  	IWL_TOF_RESPONDER_FLAGS_RETRY_ON_ALGO_FAIL = BIT(10), -	IWL_TOF_RESPONDER_FLAGS_FTM_TX_ANT = RATE_MCS_ANT_ABC_MSK, +	IWL_TOF_RESPONDER_FLAGS_FTM_TX_ANT = RATE_MCS_ANT_AB_MSK,  	IWL_TOF_RESPONDER_FLAGS_NDP_SUPPORT = BIT(24),  	IWL_TOF_RESPONDER_FLAGS_LMR_FEEDBACK = BIT(25),  	IWL_TOF_RESPONDER_FLAGS_SESSION_ID = BIT(27), @@ -629,6 +629,7 @@ enum iwl_location_bw {  	IWL_LOCATION_BW_20MHZ,  	IWL_LOCATION_BW_40MHZ,  	IWL_LOCATION_BW_80MHZ, +	IWL_LOCATION_BW_160MHZ,  };  #define TK_11AZ_LEN	32 @@ -1500,7 +1501,9 @@ struct iwl_tof_range_rsp_ap_entry_ntfy_v6 {  	u8 reserved[3];  	u8 rx_pn[IEEE80211_CCMP_PN_LEN];  	u8 tx_pn[IEEE80211_CCMP_PN_LEN]; -} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_6 */ +} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_6, +	       LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_7 */ +  /**   * enum iwl_tof_response_status - tof response status @@ -1581,7 +1584,8 @@ struct iwl_tof_range_rsp_ntfy_v8 {  	u8 last_report;  	u8 reserved;  	struct iwl_tof_range_rsp_ap_entry_ntfy_v6 ap[IWL_MVM_TOF_MAX_APS]; -} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_8 */ +} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_8, +	       LOCATION_RANGE_RSP_NTFY_API_S_VER_9 */  #define IWL_MVM_TOF_MCSI_BUF_SIZE  (245)  /** diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h index 6610d1234f74..d088c820b1a9 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h @@ -1,6 +1,6 @@  /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */  /* - * Copyright (C) 2012-2014, 2018-2019 Intel Corporation + * Copyright (C) 2012-2014, 2018-2019, 2021 Intel Corporation   * Copyright (C) 2013-2015 Intel Mobile Communications GmbH   * Copyright (C) 2016-2017 Intel Deutschland GmbH   */ @@ -39,9 +39,9 @@ enum iwl_mac_conf_subcmd_ids {  	PROBE_RESPONSE_DATA_NOTIF = 0xFC,  	/** -	 * @CHANNEL_SWITCH_NOA_NOTIF: &struct iwl_channel_switch_noa_notif +	 * @CHANNEL_SWITCH_START_NOTIF: &struct iwl_channel_switch_start_notif  	 */ -	CHANNEL_SWITCH_NOA_NOTIF = 0xFF, +	CHANNEL_SWITCH_START_NOTIF = 0xFF,  };  #define IWL_P2P_NOA_DESC_COUNT	(2) @@ -102,11 +102,11 @@ struct iwl_missed_vap_notif {  } __packed; /* MISSED_VAP_NTFY_API_S_VER_1 */  /** - * struct iwl_channel_switch_noa_notif - Channel switch NOA notification + * struct iwl_channel_switch_start_notif - Channel switch start notification   *   * @id_and_color: ID and color of the MAC   */ -struct iwl_channel_switch_noa_notif { +struct iwl_channel_switch_start_notif {  	__le32 id_and_color;  } __packed; /* CHANNEL_SWITCH_START_NTFY_API_S_VER_1 */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h index 7be7715b431d..11f0bd283e49 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h @@ -138,6 +138,8 @@ struct iwl_mac_data_ibss {   * @FLEXIBLE_TWT_SUPPORTED: AP supports flexible TWT schedule   * @PROTECTED_TWT_SUPPORTED: AP supports protected TWT frames (with 11w)   * @BROADCAST_TWT_SUPPORTED: AP and STA support broadcast TWT + * @COEX_HIGH_PRIORITY_ENABLE: high priority mode for BT coex, to be used + *	during 802.1X negotiation (and allowed during 4-way-HS)   */  enum iwl_mac_data_policy {  	TWT_SUPPORTED = BIT(0), @@ -145,6 +147,7 @@ enum iwl_mac_data_policy {  	FLEXIBLE_TWT_SUPPORTED = BIT(2),  	PROTECTED_TWT_SUPPORTED = BIT(3),  	BROADCAST_TWT_SUPPORTED = BIT(4), +	COEX_HIGH_PRIORITY_ENABLE = BIT(5),  };  /** diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h index cf48c6fa8f65..3551a3f1c1aa 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h @@ -472,6 +472,29 @@ struct iwl_lari_config_change_cmd_v4 {  } __packed; /* LARI_CHANGE_CONF_CMD_S_VER_4 */  /** + * struct iwl_lari_config_change_cmd_v5 - change LARI configuration + * @config_bitmap: Bitmap of the config commands. Each bit will trigger a + *     different predefined FW config operation. + * @oem_uhb_allow_bitmap: Bitmap of UHB enabled MCC sets. + * @oem_11ax_allow_bitmap: Bitmap of 11ax allowed MCCs. There are two bits + *     per country, one to indicate whether to override and the other to + *     indicate the value to use. + * @oem_unii4_allow_bitmap: Bitmap of unii4 allowed MCCs.There are two bits + *     per country, one to indicate whether to override and the other to + *     indicate allow/disallow unii4 channels. + * @chan_state_active_bitmap: Bitmap for overriding channel state to active. + *     Each bit represents a country or region to activate, according to the BIOS + *     definitions. + */ +struct iwl_lari_config_change_cmd_v5 { +	__le32 config_bitmap; +	__le32 oem_uhb_allow_bitmap; +	__le32 oem_11ax_allow_bitmap; +	__le32 oem_unii4_allow_bitmap; +	__le32 chan_state_active_bitmap; +} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_5 */ + +/**   * struct iwl_pnvm_init_complete_ntfy - PNVM initialization complete   * @status: PNVM image loading status   */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/phy.h b/drivers/net/wireless/intel/iwlwifi/fw/api/phy.h index d07a632f1af7..c04f2521fcb3 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/phy.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/phy.h @@ -1,6 +1,6 @@  /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */  /* - * Copyright (C) 2012-2014, 2019-2020 Intel Corporation + * Copyright (C) 2012-2014, 2019-2021 Intel Corporation   * Copyright (C) 2013-2015 Intel Mobile Communications GmbH   * Copyright (C) 2016-2017 Intel Deutschland GmbH   */ @@ -29,9 +29,9 @@ enum iwl_phy_ops_subcmd_ids {  	TEMP_REPORTING_THRESHOLDS_CMD = 0x04,  	/** -	 * @GEO_TX_POWER_LIMIT: &struct iwl_geo_tx_power_profiles_cmd +	 * @PER_CHAIN_LIMIT_OFFSET_CMD: &struct iwl_geo_tx_power_profiles_cmd  	 */ -	GEO_TX_POWER_LIMIT = 0x05, +	PER_CHAIN_LIMIT_OFFSET_CMD = 0x05,  	/**  	 * @PER_PLATFORM_ANT_GAIN_CMD: &struct iwl_ppag_table_cmd diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h index 86445385f072..4d671c878bb7 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h @@ -1,6 +1,6 @@  /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */  /* - * Copyright (C) 2012-2014, 2018-2020 Intel Corporation + * Copyright (C) 2012-2014, 2018-2021 Intel Corporation   * Copyright (C) 2013-2014 Intel Mobile Communications GmbH   * Copyright (C) 2015-2017 Intel Deutschland GmbH   */ @@ -378,9 +378,10 @@ struct iwl_dev_tx_power_cmd {  	};  }; -#define IWL_NUM_GEO_PROFILES   3 -#define IWL_NUM_BANDS_PER_CHAIN_V1 2 -#define IWL_NUM_BANDS_PER_CHAIN_V2 3 +#define IWL_NUM_GEO_PROFILES		3 +#define IWL_NUM_GEO_PROFILES_V3		8 +#define IWL_NUM_BANDS_PER_CHAIN_V1	2 +#define IWL_NUM_BANDS_PER_CHAIN_V2	3  /**   * enum iwl_geo_per_chain_offset_operation - type of operation @@ -390,10 +391,10 @@ struct iwl_dev_tx_power_cmd {  enum iwl_geo_per_chain_offset_operation {  	IWL_PER_CHAIN_OFFSET_SET_TABLES,  	IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE, -};  /* GEO_TX_POWER_LIMIT FLAGS TYPE */ +};  /* PER_CHAIN_OFFSET_OPERATION_E */  /** - * struct iwl_per_chain_offset - embedded struct for GEO_TX_POWER_LIMIT. + * struct iwl_per_chain_offset - embedded struct for PER_CHAIN_LIMIT_OFFSET_CMD.   * @max_tx_power: maximum allowed tx power.   * @chain_a: tx power offset for chain a.   * @chain_b: tx power offset for chain b. @@ -405,17 +406,17 @@ struct iwl_per_chain_offset {  } __packed; /* PER_CHAIN_LIMIT_OFFSET_PER_CHAIN_S_VER_1 */  /** - * struct iwl_geo_tx_power_profile_cmd_v1 - struct for GEO_TX_POWER_LIMIT cmd. + * struct iwl_geo_tx_power_profile_cmd_v1 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.   * @ops: operations, value from &enum iwl_geo_per_chain_offset_operation   * @table: offset profile per band.   */  struct iwl_geo_tx_power_profiles_cmd_v1 {  	__le32 ops;  	struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES][IWL_NUM_BANDS_PER_CHAIN_V1]; -} __packed; /* GEO_TX_POWER_LIMIT_VER_1 */ +} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_1 */  /** - * struct iwl_geo_tx_power_profile_cmd_v2 - struct for GEO_TX_POWER_LIMIT cmd. + * struct iwl_geo_tx_power_profile_cmd_v2 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.   * @ops: operations, value from &enum iwl_geo_per_chain_offset_operation   * @table: offset profile per band.   * @table_revision: BIOS table revision. @@ -424,10 +425,10 @@ struct iwl_geo_tx_power_profiles_cmd_v2 {  	__le32 ops;  	struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES][IWL_NUM_BANDS_PER_CHAIN_V1];  	__le32 table_revision; -} __packed; /* GEO_TX_POWER_LIMIT_VER_2 */ +} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_2 */  /** - * struct iwl_geo_tx_power_profile_cmd_v3 - struct for GEO_TX_POWER_LIMIT cmd. + * struct iwl_geo_tx_power_profile_cmd_v3 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.   * @ops: operations, value from &enum iwl_geo_per_chain_offset_operation   * @table: offset profile per band.   * @table_revision: BIOS table revision. @@ -436,21 +437,47 @@ struct iwl_geo_tx_power_profiles_cmd_v3 {  	__le32 ops;  	struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES][IWL_NUM_BANDS_PER_CHAIN_V2];  	__le32 table_revision; -} __packed; /* GEO_TX_POWER_LIMIT_VER_3 */ +} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_3 */ + +/** + * struct iwl_geo_tx_power_profile_cmd_v4 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd. + * @ops: operations, value from &enum iwl_geo_per_chain_offset_operation + * @table: offset profile per band. + * @table_revision: BIOS table revision. + */ +struct iwl_geo_tx_power_profiles_cmd_v4 { +	__le32 ops; +	struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES_V3][IWL_NUM_BANDS_PER_CHAIN_V1]; +	__le32 table_revision; +} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_4 */ + +/** + * struct iwl_geo_tx_power_profile_cmd_v5 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd. + * @ops: operations, value from &enum iwl_geo_per_chain_offset_operation + * @table: offset profile per band. + * @table_revision: BIOS table revision. + */ +struct iwl_geo_tx_power_profiles_cmd_v5 { +	__le32 ops; +	struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES_V3][IWL_NUM_BANDS_PER_CHAIN_V2]; +	__le32 table_revision; +} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_5 */  union iwl_geo_tx_power_profiles_cmd {  	struct iwl_geo_tx_power_profiles_cmd_v1 v1;  	struct iwl_geo_tx_power_profiles_cmd_v2 v2;  	struct iwl_geo_tx_power_profiles_cmd_v3 v3; +	struct iwl_geo_tx_power_profiles_cmd_v4 v4; +	struct iwl_geo_tx_power_profiles_cmd_v5 v5;  };  /** - * struct iwl_geo_tx_power_profiles_resp -  response to GEO_TX_POWER_LIMIT cmd + * struct iwl_geo_tx_power_profiles_resp -  response to PER_CHAIN_LIMIT_OFFSET_CMD cmd   * @profile_idx: current geo profile in use   */  struct iwl_geo_tx_power_profiles_resp {  	__le32 profile_idx; -} __packed; /* GEO_TX_POWER_LIMIT_RESP */ +} __packed; /* PER_CHAIN_LIMIT_OFFSET_RSP */  /**   * union iwl_ppag_table_cmd - union for all versions of PPAG command diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h index fc2fa49e9825..a09081d7ed45 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h @@ -184,6 +184,14 @@ struct iwl_tlc_update_notif {  	__le32 amsdu_enabled;  } __packed; /* TLC_MNG_UPDATE_NTFY_API_S_VER_2 */ + +#define IWL_MAX_MCS_DISPLAY_SIZE        12 + +struct iwl_rate_mcs_info { +	char    mbps[IWL_MAX_MCS_DISPLAY_SIZE]; +	char    mcs[IWL_MAX_MCS_DISPLAY_SIZE]; +}; +  /*   * These serve as indexes into   * struct iwl_rate_info fw_rate_idx_to_plcp[IWL_RATE_COUNT]; @@ -226,6 +234,8 @@ enum {  	IWL_LAST_HE_RATE = IWL_RATE_MCS_11_INDEX,  	IWL_RATE_COUNT_LEGACY = IWL_LAST_NON_HT_RATE + 1,  	IWL_RATE_COUNT = IWL_LAST_HE_RATE + 1, +	IWL_RATE_INVM_INDEX = IWL_RATE_COUNT, +	IWL_RATE_INVALID = IWL_RATE_COUNT,  };  #define IWL_RATE_BIT_MSK(r) BIT(IWL_RATE_##r##M_INDEX) @@ -248,7 +258,7 @@ enum {  };  /* - * rate_n_flags bit fields + * rate_n_flags bit fields version 1   *   * The 32-bit value has different layouts in the low 8 bites depending on the   * format. There are three formats, HT, VHT and legacy (11abg, with subformats @@ -266,15 +276,15 @@ enum {  /* Bit 8: (1) HT format, (0) legacy or VHT format */  #define RATE_MCS_HT_POS 8 -#define RATE_MCS_HT_MSK (1 << RATE_MCS_HT_POS) +#define RATE_MCS_HT_MSK_V1 BIT(RATE_MCS_HT_POS)  /* Bit 9: (1) CCK, (0) OFDM.  HT (bit 8) must be "0" for this bit to be valid */ -#define RATE_MCS_CCK_POS 9 -#define RATE_MCS_CCK_MSK (1 << RATE_MCS_CCK_POS) +#define RATE_MCS_CCK_POS_V1 9 +#define RATE_MCS_CCK_MSK_V1 BIT(RATE_MCS_CCK_POS_V1)  /* Bit 26: (1) VHT format, (0) legacy format in bits 8:0 */ -#define RATE_MCS_VHT_POS 26 -#define RATE_MCS_VHT_MSK (1 << RATE_MCS_VHT_POS) +#define RATE_MCS_VHT_POS_V1 26 +#define RATE_MCS_VHT_MSK_V1 BIT(RATE_MCS_VHT_POS_V1)  /* @@ -300,15 +310,16 @@ enum {   * streams and 16-23 have three streams. We could also support MCS 32   * which is the duplicate 20 MHz MCS (bit 5 set, all others zero.)   */ -#define RATE_HT_MCS_RATE_CODE_MSK	0x7 -#define RATE_HT_MCS_NSS_POS             3 -#define RATE_HT_MCS_NSS_MSK             (3 << RATE_HT_MCS_NSS_POS) +#define RATE_HT_MCS_RATE_CODE_MSK_V1	0x7 +#define RATE_HT_MCS_NSS_POS_V1          3 +#define RATE_HT_MCS_NSS_MSK_V1          (3 << RATE_HT_MCS_NSS_POS_V1) +#define RATE_HT_MCS_MIMO2_MSK		BIT(RATE_HT_MCS_NSS_POS_V1)  /* Bit 10: (1) Use Green Field preamble */  #define RATE_HT_MCS_GF_POS		10  #define RATE_HT_MCS_GF_MSK		(1 << RATE_HT_MCS_GF_POS) -#define RATE_HT_MCS_INDEX_MSK		0x3f +#define RATE_HT_MCS_INDEX_MSK_V1	0x3f  /*   * Very High-throughput (VHT) rate format for bits 7:0 @@ -324,6 +335,7 @@ enum {  #define RATE_VHT_MCS_RATE_CODE_MSK	0xf  #define RATE_VHT_MCS_NSS_POS		4  #define RATE_VHT_MCS_NSS_MSK		(3 << RATE_VHT_MCS_NSS_POS) +#define RATE_VHT_MCS_MIMO2_MSK		BIT(RATE_VHT_MCS_NSS_POS)  /*   * Legacy OFDM rate format for bits 7:0 @@ -347,37 +359,30 @@ enum {   *        110)  11 Mbps   * (bit 7 is 0)   */ -#define RATE_LEGACY_RATE_MSK 0xff +#define RATE_LEGACY_RATE_MSK_V1 0xff  /* Bit 10 - OFDM HE */ -#define RATE_MCS_HE_POS		10 -#define RATE_MCS_HE_MSK		BIT(RATE_MCS_HE_POS) +#define RATE_MCS_HE_POS_V1	10 +#define RATE_MCS_HE_MSK_V1	BIT(RATE_MCS_HE_POS_V1)  /*   * Bit 11-12: (0) 20MHz, (1) 40MHz, (2) 80MHz, (3) 160MHz   * 0 and 1 are valid for HT and VHT, 2 and 3 only for VHT   */  #define RATE_MCS_CHAN_WIDTH_POS		11 -#define RATE_MCS_CHAN_WIDTH_MSK		(3 << RATE_MCS_CHAN_WIDTH_POS) -#define RATE_MCS_CHAN_WIDTH_20		(0 << RATE_MCS_CHAN_WIDTH_POS) -#define RATE_MCS_CHAN_WIDTH_40		(1 << RATE_MCS_CHAN_WIDTH_POS) -#define RATE_MCS_CHAN_WIDTH_80		(2 << RATE_MCS_CHAN_WIDTH_POS) -#define RATE_MCS_CHAN_WIDTH_160		(3 << RATE_MCS_CHAN_WIDTH_POS) +#define RATE_MCS_CHAN_WIDTH_MSK_V1	(3 << RATE_MCS_CHAN_WIDTH_POS)  /* Bit 13: (1) Short guard interval (0.4 usec), (0) normal GI (0.8 usec) */ -#define RATE_MCS_SGI_POS		13 -#define RATE_MCS_SGI_MSK		(1 << RATE_MCS_SGI_POS) +#define RATE_MCS_SGI_POS_V1		13 +#define RATE_MCS_SGI_MSK_V1		BIT(RATE_MCS_SGI_POS_V1)  /* Bit 14-16: Antenna selection (1) Ant A, (2) Ant B, (4) Ant C */  #define RATE_MCS_ANT_POS		14  #define RATE_MCS_ANT_A_MSK		(1 << RATE_MCS_ANT_POS)  #define RATE_MCS_ANT_B_MSK		(2 << RATE_MCS_ANT_POS) -#define RATE_MCS_ANT_C_MSK		(4 << RATE_MCS_ANT_POS)  #define RATE_MCS_ANT_AB_MSK		(RATE_MCS_ANT_A_MSK | \  					 RATE_MCS_ANT_B_MSK) -#define RATE_MCS_ANT_ABC_MSK		(RATE_MCS_ANT_AB_MSK | \ -					 RATE_MCS_ANT_C_MSK) -#define RATE_MCS_ANT_MSK		RATE_MCS_ANT_ABC_MSK +#define RATE_MCS_ANT_MSK		RATE_MCS_ANT_AB_MSK  /* Bit 17: (0) SS, (1) SS*2 */  #define RATE_MCS_STBC_POS		17 @@ -411,27 +416,27 @@ enum {   *	3			(does not occur)   */  #define RATE_MCS_HE_GI_LTF_POS		20 -#define RATE_MCS_HE_GI_LTF_MSK		(3 << RATE_MCS_HE_GI_LTF_POS) +#define RATE_MCS_HE_GI_LTF_MSK_V1		(3 << RATE_MCS_HE_GI_LTF_POS)  /* Bit 22-23: HE type. (0) SU, (1) SU_EXT, (2) MU, (3) trigger based */ -#define RATE_MCS_HE_TYPE_POS		22 -#define RATE_MCS_HE_TYPE_SU		(0 << RATE_MCS_HE_TYPE_POS) -#define RATE_MCS_HE_TYPE_EXT_SU		(1 << RATE_MCS_HE_TYPE_POS) -#define RATE_MCS_HE_TYPE_MU		(2 << RATE_MCS_HE_TYPE_POS) -#define RATE_MCS_HE_TYPE_TRIG		(3 << RATE_MCS_HE_TYPE_POS) -#define RATE_MCS_HE_TYPE_MSK		(3 << RATE_MCS_HE_TYPE_POS) +#define RATE_MCS_HE_TYPE_POS_V1		22 +#define RATE_MCS_HE_TYPE_SU_V1		(0 << RATE_MCS_HE_TYPE_POS_V1) +#define RATE_MCS_HE_TYPE_EXT_SU_V1		BIT(RATE_MCS_HE_TYPE_POS_V1) +#define RATE_MCS_HE_TYPE_MU_V1		(2 << RATE_MCS_HE_TYPE_POS_V1) +#define RATE_MCS_HE_TYPE_TRIG_V1	(3 << RATE_MCS_HE_TYPE_POS_V1) +#define RATE_MCS_HE_TYPE_MSK_V1		(3 << RATE_MCS_HE_TYPE_POS_V1)  /* Bit 24-25: (0) 20MHz (no dup), (1) 2x20MHz, (2) 4x20MHz, 3 8x20MHz */ -#define RATE_MCS_DUP_POS		24 -#define RATE_MCS_DUP_MSK		(3 << RATE_MCS_DUP_POS) +#define RATE_MCS_DUP_POS_V1		24 +#define RATE_MCS_DUP_MSK_V1		(3 << RATE_MCS_DUP_POS_V1)  /* Bit 27: (1) LDPC enabled, (0) LDPC disabled */ -#define RATE_MCS_LDPC_POS		27 -#define RATE_MCS_LDPC_MSK		(1 << RATE_MCS_LDPC_POS) +#define RATE_MCS_LDPC_POS_V1		27 +#define RATE_MCS_LDPC_MSK_V1		BIT(RATE_MCS_LDPC_POS_V1)  /* Bit 28: (1) 106-tone RX (8 MHz RU), (0) normal bandwidth */ -#define RATE_MCS_HE_106T_POS		28 -#define RATE_MCS_HE_106T_MSK		(1 << RATE_MCS_HE_106T_POS) +#define RATE_MCS_HE_106T_POS_V1		28 +#define RATE_MCS_HE_106T_MSK_V1		BIT(RATE_MCS_HE_106T_POS_V1)  /* Bit 30-31: (1) RTS, (2) CTS */  #define RATE_MCS_RTS_REQUIRED_POS  (30) @@ -440,6 +445,152 @@ enum {  #define RATE_MCS_CTS_REQUIRED_POS  (31)  #define RATE_MCS_CTS_REQUIRED_MSK  (0x1 << RATE_MCS_CTS_REQUIRED_POS) +/* rate_n_flags bit field version 2 + * + * The 32-bit value has different layouts in the low 8 bits depending on the + * format. There are three formats, HT, VHT and legacy (11abg, with subformats + * for CCK and OFDM). + * + */ + +/* Bits 10-8: rate format + * (0) Legacy CCK (1) Legacy OFDM (2) High-throughput (HT) + * (3) Very High-throughput (VHT) (4) High-efficiency (HE) + * (5) Extremely High-throughput (EHT) + */ +#define RATE_MCS_MOD_TYPE_POS		8 +#define RATE_MCS_MOD_TYPE_MSK		(0x7 << RATE_MCS_MOD_TYPE_POS) +#define RATE_MCS_CCK_MSK		(0 << RATE_MCS_MOD_TYPE_POS) +#define RATE_MCS_LEGACY_OFDM_MSK	(1 << RATE_MCS_MOD_TYPE_POS) +#define RATE_MCS_HT_MSK			(2 << RATE_MCS_MOD_TYPE_POS) +#define RATE_MCS_VHT_MSK		(3 << RATE_MCS_MOD_TYPE_POS) +#define RATE_MCS_HE_MSK			(4 << RATE_MCS_MOD_TYPE_POS) +#define RATE_MCS_EHT_MSK		(5 << RATE_MCS_MOD_TYPE_POS) + +/* + * Legacy CCK rate format for bits 0:3: + * + * (0) 0xa - 1 Mbps + * (1) 0x14 - 2 Mbps + * (2) 0x37 - 5.5 Mbps + * (3) 0x6e - 11 nbps + * + * Legacy OFDM rate format for bis 3:0: + * + * (0) 6 Mbps + * (1) 9 Mbps + * (2) 12 Mbps + * (3) 18 Mbps + * (4) 24 Mbps + * (5) 36 Mbps + * (6) 48 Mbps + * (7) 54 Mbps + * + */ +#define RATE_LEGACY_RATE_MSK		0x7 + +/* + * HT, VHT, HE, EHT rate format for bits 3:0 + * 3-0: MCS + * + */ +#define RATE_HT_MCS_CODE_MSK		0x7 +#define RATE_MCS_NSS_POS		4 +#define RATE_MCS_NSS_MSK		(1 << RATE_MCS_NSS_POS) +#define RATE_MCS_CODE_MSK		0xf +#define RATE_HT_MCS_INDEX(r)		((((r) & RATE_MCS_NSS_MSK) >> 1) | \ +					 ((r) & RATE_HT_MCS_CODE_MSK)) + +/* Bits 7-5: reserved */ + +/* + * Bits 13-11: (0) 20MHz, (1) 40MHz, (2) 80MHz, (3) 160MHz, (4) 320MHz + */ +#define RATE_MCS_CHAN_WIDTH_MSK			(0x7 << RATE_MCS_CHAN_WIDTH_POS) +#define RATE_MCS_CHAN_WIDTH_20			(0 << RATE_MCS_CHAN_WIDTH_POS) +#define RATE_MCS_CHAN_WIDTH_40			(1 << RATE_MCS_CHAN_WIDTH_POS) +#define RATE_MCS_CHAN_WIDTH_80			(2 << RATE_MCS_CHAN_WIDTH_POS) +#define RATE_MCS_CHAN_WIDTH_160			(3 << RATE_MCS_CHAN_WIDTH_POS) +#define RATE_MCS_CHAN_WIDTH_320			(4 << RATE_MCS_CHAN_WIDTH_POS) + +/* Bit 15-14: Antenna selection: + * Bit 14: Ant A active + * Bit 15: Ant B active + * + * All relevant definitions are same as in v1 + */ + +/* Bit 16 (1) LDPC enables, (0) LDPC disabled */ +#define RATE_MCS_LDPC_POS	16 +#define RATE_MCS_LDPC_MSK	(1 << RATE_MCS_LDPC_POS) + +/* Bit 17: (0) SS, (1) SS*2 (same as v1) */ + +/* Bit 18: OFDM-HE dual carrier mode (same as v1) */ + +/* Bit 19: (0) Beamforming is off, (1) Beamforming is on (same as v1) */ + +/* + * Bit 22-20: HE LTF type and guard interval + * CCK: + *	0			long preamble + *	1			short preamble + * HT/VHT: + *	0			0.8us + *	1			0.4us + * HE (ext) SU: + *	0			1xLTF+0.8us + *	1			2xLTF+0.8us + *	2			2xLTF+1.6us + *	3			4xLTF+3.2us + *	4			4xLTF+0.8us + * HE MU: + *	0			4xLTF+0.8us + *	1			2xLTF+0.8us + *	2			2xLTF+1.6us + *	3			4xLTF+3.2us + * HE TRIG: + *	0			1xLTF+1.6us + *	1			2xLTF+1.6us + *	2			4xLTF+3.2us + * */ +#define RATE_MCS_HE_GI_LTF_MSK		(0x7 << RATE_MCS_HE_GI_LTF_POS) +#define RATE_MCS_SGI_POS		RATE_MCS_HE_GI_LTF_POS +#define RATE_MCS_SGI_MSK		(1 << RATE_MCS_SGI_POS) +#define RATE_MCS_HE_SU_4_LTF		3 +#define RATE_MCS_HE_SU_4_LTF_08_GI	4 + +/* Bit 24-23: HE type. (0) SU, (1) SU_EXT, (2) MU, (3) trigger based */ +#define RATE_MCS_HE_TYPE_POS		23 +#define RATE_MCS_HE_TYPE_SU		(0 << RATE_MCS_HE_TYPE_POS) +#define RATE_MCS_HE_TYPE_EXT_SU		(1 << RATE_MCS_HE_TYPE_POS) +#define RATE_MCS_HE_TYPE_MU		(2 << RATE_MCS_HE_TYPE_POS) +#define RATE_MCS_HE_TYPE_TRIG		(3 << RATE_MCS_HE_TYPE_POS) +#define RATE_MCS_HE_TYPE_MSK		(3 << RATE_MCS_HE_TYPE_POS) + +/* Bit 25: duplicate channel enabled + * + * if this bit is set, duplicate is according to BW (bits 11-13): + * + * CCK:  2x 20MHz + * OFDM Legacy: N x 20Mhz, (N = BW \ 2 , either 2, 4, 8, 16) + * EHT: 2 x BW/2, (80 - 2x40, 160 - 2x80, 320 - 2x160) + * */ +#define RATE_MCS_DUP_POS		25 +#define RATE_MCS_DUP_MSK		(1 << RATE_MCS_DUP_POS) + +/* Bit 26: (1) 106-tone RX (8 MHz RU), (0) normal bandwidth */ +#define RATE_MCS_HE_106T_POS		26 +#define RATE_MCS_HE_106T_MSK		(1 << RATE_MCS_HE_106T_POS) + +/* Bit 27: EHT extra LTF: + * instead of 1 LTF for SISO use 2 LTFs, + * instead of 2 LTFs for NSTS=2 use 4 LTFs*/ +#define RATE_MCS_EHT_EXTRA_LTF_POS	27 +#define RATE_MCS_EHT_EXTRA_LTF_MSK	(1 << RATE_MCS_EHT_EXTRA_LTF_POS) + +/* Bit 31-28: reserved */ +  /* Link Quality definitions */  /* # entries in rate scale table to support Tx retries */ @@ -557,4 +708,13 @@ struct iwl_lq_cmd {  	__le32 ss_params;  }; /* LINK_QUALITY_CMD_API_S_VER_1 */ +u8 iwl_fw_rate_idx_to_plcp(int idx); +u32 iwl_new_rate_from_v1(u32 rate_v1); +u32 iwl_legacy_rate_to_fw_idx(u32 rate_n_flags); +const struct iwl_rate_mcs_info *iwl_rate_mcs(int idx); +const char *iwl_rs_pretty_ant(u8 ant); +const char *iwl_rs_pretty_bw(int bw); +int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate); +bool iwl_he_is_sgi(u32 rate_n_flags); +  #endif /* __iwl_fw_api_rs_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h index 3f13b572915a..1989b270862b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h @@ -1,6 +1,6 @@  /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */  /* - * Copyright (C) 2012-2014, 2018-2020 Intel Corporation + * Copyright (C) 2012-2014, 2018-2021 Intel Corporation   * Copyright (C) 2013-2015 Intel Mobile Communications GmbH   * Copyright (C) 2015-2017 Intel Deutschland GmbH   */ @@ -13,7 +13,6 @@  #define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1  #define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff  #define IWL_RX_INFO_ENERGY_ANT_B_MSK 0x0000ff00 -#define IWL_RX_INFO_ENERGY_ANT_C_MSK 0x00ff0000  #define IWL_RX_INFO_ENERGY_ANT_A_POS 0  #define IWL_RX_INFO_ENERGY_ANT_B_POS 8  #define IWL_RX_INFO_ENERGY_ANT_C_POS 16 @@ -126,14 +125,12 @@ enum iwl_rx_phy_flags {   * @RX_MPDU_RES_STATUS_OVERRUN_OK: there was no RXE overflow   * @RX_MPDU_RES_STATUS_SRC_STA_FOUND: station was found   * @RX_MPDU_RES_STATUS_KEY_VALID: key was valid - * @RX_MPDU_RES_STATUS_KEY_PARAM_OK: key parameters were usable   * @RX_MPDU_RES_STATUS_ICV_OK: ICV is fine, if not, the packet is destroyed   * @RX_MPDU_RES_STATUS_MIC_OK: used for CCM alg only. TKIP MIC is checked   *	in the driver.   * @RX_MPDU_RES_STATUS_TTAK_OK: TTAK is fine   * @RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR:  valid for alg = CCM_CMAC or - *	alg = CCM only. Checks replay attack for 11w frames. Relevant only if - *	%RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME is set. + *	alg = CCM only. Checks replay attack for 11w frames.   * @RX_MPDU_RES_STATUS_SEC_NO_ENC: this frame is not encrypted   * @RX_MPDU_RES_STATUS_SEC_WEP_ENC: this frame is encrypted using WEP   * @RX_MPDU_RES_STATUS_SEC_CCM_ENC: this frame is encrypted using CCM @@ -145,9 +142,6 @@ enum iwl_rx_phy_flags {   * @RX_MPDU_RES_STATUS_SEC_ENC_ERR: this frame couldn't be decrypted   * @RX_MPDU_RES_STATUS_SEC_ENC_MSK: bitmask of the encryption algorithm   * @RX_MPDU_RES_STATUS_DEC_DONE: this frame has been successfully decrypted - * @RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP: extended IV (set with TKIP) - * @RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT: key ID comparison done - * @RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME: this frame is an 11w management frame   * @RX_MPDU_RES_STATUS_CSUM_DONE: checksum was done by the hw   * @RX_MPDU_RES_STATUS_CSUM_OK: checksum found no errors   * @RX_MPDU_RES_STATUS_STA_ID_MSK: station ID mask @@ -158,7 +152,6 @@ enum iwl_mvm_rx_status {  	RX_MPDU_RES_STATUS_OVERRUN_OK			= BIT(1),  	RX_MPDU_RES_STATUS_SRC_STA_FOUND		= BIT(2),  	RX_MPDU_RES_STATUS_KEY_VALID			= BIT(3), -	RX_MPDU_RES_STATUS_KEY_PARAM_OK			= BIT(4),  	RX_MPDU_RES_STATUS_ICV_OK			= BIT(5),  	RX_MPDU_RES_STATUS_MIC_OK			= BIT(6),  	RX_MPDU_RES_STATUS_TTAK_OK			= BIT(7), @@ -172,9 +165,6 @@ enum iwl_mvm_rx_status {  	RX_MPDU_RES_STATUS_SEC_ENC_ERR			= (7 << 8),  	RX_MPDU_RES_STATUS_SEC_ENC_MSK			= (7 << 8),  	RX_MPDU_RES_STATUS_DEC_DONE			= BIT(11), -	RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP		= BIT(13), -	RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT		= BIT(14), -	RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME		= BIT(15),  	RX_MPDU_RES_STATUS_CSUM_DONE			= BIT(16),  	RX_MPDU_RES_STATUS_CSUM_OK			= BIT(17),  	RX_MDPU_RES_STATUS_STA_ID_SHIFT			= 24, @@ -236,7 +226,6 @@ enum iwl_rx_mpdu_status {  	IWL_RX_MPDU_STATUS_OVERRUN_OK		= BIT(1),  	IWL_RX_MPDU_STATUS_SRC_STA_FOUND	= BIT(2),  	IWL_RX_MPDU_STATUS_KEY_VALID		= BIT(3), -	IWL_RX_MPDU_STATUS_KEY_PARAM_OK		= BIT(4),  	IWL_RX_MPDU_STATUS_ICV_OK		= BIT(5),  	IWL_RX_MPDU_STATUS_MIC_OK		= BIT(6),  	IWL_RX_MPDU_RES_STATUS_TTAK_OK		= BIT(7), @@ -251,12 +240,8 @@ enum iwl_rx_mpdu_status {  	IWL_RX_MPDU_STATUS_SEC_EXT_ENC		= 0x4 << 8,  	IWL_RX_MPDU_STATUS_SEC_GCM		= 0x5 << 8,  	IWL_RX_MPDU_STATUS_DECRYPTED		= BIT(11), -	IWL_RX_MPDU_STATUS_WEP_MATCH		= BIT(12), -	IWL_RX_MPDU_STATUS_EXT_IV_MATCH		= BIT(13), -	IWL_RX_MPDU_STATUS_KEY_ID_MATCH		= BIT(14),  	IWL_RX_MPDU_STATUS_ROBUST_MNG_FRAME	= BIT(15), -	IWL_RX_MPDU_STATUS_KEY			= 0x3f0000,  	IWL_RX_MPDU_STATUS_DUPLICATE		= BIT(22),  	IWL_RX_MPDU_STATUS_STA_ID		= 0x1f000000, @@ -460,7 +445,7 @@ struct iwl_rx_mpdu_desc_v1 {  			__le32 phy_data1;  		};  	}; -} __packed; +} __packed; /* RX_MPDU_RES_START_API_S_VER_4 */  /**   * struct iwl_rx_mpdu_desc_v3 - RX MPDU descriptor @@ -560,7 +545,8 @@ struct iwl_rx_mpdu_desc_v3 {  	 * @reserved: reserved  	 */  	__le32 reserved[2]; -} __packed; /* RX_MPDU_RES_START_API_S_VER_3 */ +} __packed; /* RX_MPDU_RES_START_API_S_VER_3, +	       RX_MPDU_RES_START_API_S_VER_5 */  /**   * struct iwl_rx_mpdu_desc - RX MPDU descriptor @@ -625,7 +611,9 @@ struct iwl_rx_mpdu_desc {  		struct iwl_rx_mpdu_desc_v1 v1;  		struct iwl_rx_mpdu_desc_v3 v3;  	}; -} __packed; /* RX_MPDU_RES_START_API_S_VER_3 */ +} __packed; /* RX_MPDU_RES_START_API_S_VER_3, +	       RX_MPDU_RES_START_API_S_VER_4, +	       RX_MPDU_RES_START_API_S_VER_5 */  #define IWL_RX_DESC_SIZE_V1 offsetofend(struct iwl_rx_mpdu_desc, v1) @@ -679,7 +667,8 @@ struct iwl_rx_no_data {  	__le32 rate;  	__le32 phy_info[2];  	__le32 rx_vec[2]; -} __packed; /* RX_NO_DATA_NTFY_API_S_VER_1 */ +} __packed; /* RX_NO_DATA_NTFY_API_S_VER_1, +	       TX_NO_DATA_NTFY_API_S_VER_2 */  struct iwl_frame_release {  	u8 baid; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/sta.h b/drivers/net/wireless/intel/iwlwifi/fw/api/sta.h index f1a3e14880e7..5edbe27c0922 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/sta.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/sta.h @@ -28,6 +28,8 @@   * @STA_FLG_MAX_AGG_SIZE_256K: maximal size for A-MPDU (256k supported)   * @STA_FLG_MAX_AGG_SIZE_512K: maximal size for A-MPDU (512k supported)   * @STA_FLG_MAX_AGG_SIZE_1024K: maximal size for A-MPDU (1024k supported) + * @STA_FLG_MAX_AGG_SIZE_2M: maximal size for A-MPDU (2M supported) + * @STA_FLG_MAX_AGG_SIZE_4M: maximal size for A-MPDU (4M supported)   * @STA_FLG_AGG_MPDU_DENS_MSK: maximal MPDU density for Tx aggregation   * @STA_FLG_FAT_EN_MSK: support for channel width (for Tx). This flag is   *	initialised by driver and can be updated by fw upon reception of diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h index 24e4a82a55da..4a74c0ea0f31 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h @@ -1,6 +1,6 @@  /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */  /* - * Copyright (C) 2012-2014, 2018-2020 Intel Corporation + * Copyright (C) 2012-2014, 2018-2021 Intel Corporation   * Copyright (C) 2016-2017 Intel Deutschland GmbH   */  #ifndef __iwl_fw_api_tx_h__ @@ -81,6 +81,10 @@ enum iwl_tx_cmd_flags {  	IWL_TX_FLAGS_CMD_RATE		= BIT(0),  	IWL_TX_FLAGS_ENCRYPT_DIS	= BIT(1),  	IWL_TX_FLAGS_HIGH_PRI		= BIT(2), +	/* Use these flags only from +	 * TX_FLAGS_BITS_API_S_VER_4 and above */ +	IWL_TX_FLAGS_RTS		= BIT(3), +	IWL_TX_FLAGS_CTS		= BIT(4),  }; /* TX_FLAGS_BITS_API_S_VER_3 */  /** @@ -239,8 +243,10 @@ struct iwl_tx_cmd {  	u8 tid_tspec;  	__le16 pm_frame_timeout;  	__le16 reserved4; -	u8 payload[0]; -	struct ieee80211_hdr hdr[0]; +	union { +		DECLARE_FLEX_ARRAY(u8, payload); +		DECLARE_FLEX_ARRAY(struct ieee80211_hdr, hdr); +	};  } __packed; /* TX_CMD_API_S_VER_6 */  struct iwl_dram_sec_info { @@ -267,7 +273,8 @@ struct iwl_tx_cmd_gen2 {  	struct iwl_dram_sec_info dram_info;  	__le32 rate_n_flags;  	struct ieee80211_hdr hdr[]; -} __packed; /* TX_CMD_API_S_VER_7 */ +} __packed; /* TX_CMD_API_S_VER_7, +	       TX_CMD_API_S_VER_9 */  /**   * struct iwl_tx_cmd_gen3 - TX command struct to FW for AX210+ devices @@ -290,7 +297,8 @@ struct iwl_tx_cmd_gen3 {  	__le32 rate_n_flags;  	__le64 ttl;  	struct ieee80211_hdr hdr[]; -} __packed; /* TX_CMD_API_S_VER_8 */ +} __packed; /* TX_CMD_API_S_VER_8, +	       TX_CMD_API_S_VER_10 */  /*   * TX response related data @@ -591,7 +599,8 @@ struct iwl_mvm_tx_resp {  	__le16 tx_queue;  	__le16 reserved2;  	struct agg_tx_status status; -} __packed; /* TX_RSP_API_S_VER_6 */ +} __packed; /* TX_RSP_API_S_VER_6, +	       TX_RSP_API_S_VER_7 */  /**   * struct iwl_mvm_ba_notif - notifies about reception of BA @@ -713,9 +722,12 @@ struct iwl_mvm_compressed_ba_notif {  	__le32 tx_rate;  	__le16 tfd_cnt;  	__le16 ra_tid_cnt; -	struct iwl_mvm_compressed_ba_ratid ra_tid[0]; -	struct iwl_mvm_compressed_ba_tfd tfd[]; -} __packed; /* COMPRESSED_BA_RES_API_S_VER_4 */ +	union { +		DECLARE_FLEX_ARRAY(struct iwl_mvm_compressed_ba_ratid, ra_tid); +		DECLARE_FLEX_ARRAY(struct iwl_mvm_compressed_ba_tfd, tfd); +	}; +} __packed; /* COMPRESSED_BA_RES_API_S_VER_4, +	       COMPRESSED_BA_RES_API_S_VER_5 */  /**   * struct iwl_mac_beacon_cmd_v6 - beacon template command @@ -755,12 +767,20 @@ struct iwl_mac_beacon_cmd_v7 {  	struct ieee80211_hdr frame[];  } __packed; /* BEACON_TEMPLATE_CMD_API_S_VER_7 */ +/* Bit flags for BEACON_TEMPLATE_CMD_API until version 10 */ +enum iwl_mac_beacon_flags_v1 { +	IWL_MAC_BEACON_CCK_V1	= BIT(8), +	IWL_MAC_BEACON_ANT_A_V1 = BIT(9), +	IWL_MAC_BEACON_ANT_B_V1 = BIT(10), +	IWL_MAC_BEACON_FILS_V1	= BIT(12), +}; + +/* Bit flags for BEACON_TEMPLATE_CMD_API version 11 and above */  enum iwl_mac_beacon_flags { -	IWL_MAC_BEACON_CCK	= BIT(8), -	IWL_MAC_BEACON_ANT_A	= BIT(9), -	IWL_MAC_BEACON_ANT_B	= BIT(10), -	IWL_MAC_BEACON_ANT_C	= BIT(11), -	IWL_MAC_BEACON_FILS	= BIT(12), +	IWL_MAC_BEACON_CCK	= BIT(5), +	IWL_MAC_BEACON_ANT_A	= BIT(6), +	IWL_MAC_BEACON_ANT_B	= BIT(7), +	IWL_MAC_BEACON_FILS	= BIT(8),  };  /** @@ -788,7 +808,9 @@ struct iwl_mac_beacon_cmd {  	__le32 ecsa_offset;  	__le32 csa_offset;  	struct ieee80211_hdr frame[]; -} __packed; /* BEACON_TEMPLATE_CMD_API_S_VER_10 */ +} __packed; /* BEACON_TEMPLATE_CMD_API_S_VER_10, +	       BEACON_TEMPLATE_CMD_API_S_VER_11, +	       BEACON_TEMPLATE_CMD_API_S_VER_12 */  struct iwl_beacon_notif {  	struct iwl_mvm_tx_resp beacon_notify_hdr; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 6dcafd0a3d4b..a39013c401c9 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -159,11 +159,15 @@ static void iwl_fwrt_dump_txf(struct iwl_fw_runtime *fwrt,  	iwl_trans_read_prph(fwrt->trans, TXF_READ_MODIFY_DATA + offset);  	/* Read FIFO */ -	fifo_len /= sizeof(u32); /* Size in DWORDS */ -	for (i = 0; i < fifo_len; i++) +	for (i = 0; i < fifo_len / sizeof(u32); i++)  		fifo_data[i] = iwl_trans_read_prph(fwrt->trans,  						  TXF_READ_MODIFY_DATA +  						  offset); + +	if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf) +		fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx, +					     fifo_data, fifo_len); +  	*dump_data = iwl_fw_error_next_data(*dump_data);  } @@ -659,6 +663,10 @@ static void iwl_fw_dump_mem(struct iwl_fw_runtime *fwrt,  	iwl_trans_read_mem_bytes(fwrt->trans, ofs, dump_mem->data, len);  	*dump_data = iwl_fw_error_next_data(*dump_data); +	if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem) +		fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx, ofs, +					     dump_mem->data, len); +  	IWL_DEBUG_INFO(fwrt, "WRT memory dump. Type=%u\n", dump_mem->type);  } @@ -752,6 +760,12 @@ static void iwl_dump_paging(struct iwl_fw_runtime *fwrt,  					   PAGING_BLOCK_SIZE,  					   DMA_BIDIRECTIONAL);  		(*data) = iwl_fw_error_next_data(*data); + +		if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem) +			fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx, +						     fwrt->fw_paging_db[i].fw_offs, +						     paging->data, +						     PAGING_BLOCK_SIZE);  	}  } @@ -980,6 +994,11 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,  					 dump_data->data + data_size,  					 data_size); +		if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem) +			fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx, addr, +						     dump_data->data + data_size, +						     data_size); +  		dump_data = iwl_fw_error_next_data(dump_data);  	} @@ -1146,6 +1165,13 @@ static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt,  	iwl_trans_read_mem_bytes(fwrt->trans, addr, range->data,  				 le32_to_cpu(reg->dev_addr.size)); +	if ((le32_to_cpu(reg->id) & IWL_FW_INI_REGION_V2_MASK) == +		IWL_FW_INI_HW_SMEM_REGION_ID && +	    fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf) +		fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx, +					     range->data, +					     le32_to_cpu(reg->dev_addr.size)); +  	return sizeof(*range) + le32_to_cpu(range->range_data_size);  } @@ -1338,6 +1364,10 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt,  	for (i = 0; i < iter->fifo_size; i += sizeof(*data))  		*data++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr)); +	if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf) +		fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx, +					     reg_dump, iter->fifo_size); +  out:  	iwl_trans_release_nic_access(fwrt->trans); @@ -2077,7 +2107,7 @@ static u32 iwl_dump_ini_info(struct iwl_fw_runtime *fwrt,  	 */  	hw_type = CSR_HW_REV_TYPE(fwrt->trans->hw_rev);  	if (hw_type == IWL_AX210_HW_TYPE) { -		u32 prph_val = iwl_read_prph(fwrt->trans, WFPM_OTP_CFG1_ADDR); +		u32 prph_val = iwl_read_prph(fwrt->trans, WFPM_OTP_CFG1_ADDR_GEN2);  		u32 is_jacket = !!(prph_val & WFPM_OTP_CFG1_IS_JACKET_BIT);  		u32 is_cdb = !!(prph_val & WFPM_OTP_CFG1_IS_CDB_BIT);  		u32 masked_bits = is_jacket | (is_cdb << 1); @@ -2360,7 +2390,9 @@ static void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt,  	if (dump_data->monitor_only)  		dump_mask &= BIT(IWL_FW_ERROR_DUMP_FW_MONITOR); -	fw_error_dump.trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask); +	fw_error_dump.trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask, +						      fwrt->sanitize_ops, +						      fwrt->sanitize_ctx);  	file_len = le32_to_cpu(dump_file->file_len);  	fw_error_dump.fwrt_len = file_len; @@ -2788,6 +2820,12 @@ void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt)  	iwl_trans_read_mem_bytes(fwrt->trans, cfg->d3_debug_data_base_addr,  				 fwrt->dump.d3_debug_data,  				 cfg->d3_debug_data_length); + +	if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem) +		fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx, +					     cfg->d3_debug_data_base_addr, +					     fwrt->dump.d3_debug_data, +					     cfg->d3_debug_data_length);  }  IWL_EXPORT_SYMBOL(iwl_fw_dbg_read_d3_debug_data); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dump.c b/drivers/net/wireless/intel/iwlwifi/fw/dump.c index a1842205e86a..016b3a4c5f51 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dump.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dump.c @@ -214,7 +214,7 @@ static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_nu  		/* reset the device */  		iwl_trans_sw_reset(trans); -		err = iwl_finish_nic_init(trans, trans->trans_cfg); +		err = iwl_finish_nic_init(trans);  		if (err)  			return;  	} @@ -328,6 +328,13 @@ static void iwl_fwrt_dump_tcm_error_log(struct iwl_fw_runtime *fwrt)  	for (i = 0; i < ARRAY_SIZE(table.sw_status); i++)  		IWL_ERR(fwrt, "0x%08X | tcm SW status[%d]\n",  			table.sw_status[i], i); + +	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { +		u32 scratch = iwl_read32(trans, CSR_FUNC_SCRATCH); + +		IWL_ERR(fwrt, "Function Scratch status:\n"); +		IWL_ERR(fwrt, "0x%08X | Func Scratch\n", scratch); +	}  }  static void iwl_fwrt_dump_iml_error_log(struct iwl_fw_runtime *fwrt) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h index 521ca2bb0e92..9036b32ec765 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h @@ -342,10 +342,6 @@ struct iwl_fw_ini_dump_cfg_name {  #define IWL_AX210_HW_TYPE 0x42  /* How many bits to roll when adding to the HW type of AX210 HW */  #define IWL_AX210_HW_TYPE_ADDITION_SHIFT 12 -/* This prph is used to tell apart HW_TYPE == 0x42 NICs */ -#define WFPM_OTP_CFG1_ADDR 0xd03098 -#define WFPM_OTP_CFG1_IS_JACKET_BIT BIT(4) -#define WFPM_OTP_CFG1_IS_CDB_BIT BIT(5)  /* struct iwl_fw_ini_dump_info - ini dump information   * @version: dump version diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index 6c8e9f3a6af2..3d572f5024bb 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -100,6 +100,9 @@ enum iwl_ucode_tlv_type {  	IWL_UCODE_TLV_PNVM_SKU			= 64,  	IWL_UCODE_TLV_TCM_DEBUG_ADDRS		= 65, +	IWL_UCODE_TLV_SEC_TABLE_ADDR		= 66, +	IWL_UCODE_TLV_D3_KEK_KCK_ADDR		= 67, +  	IWL_UCODE_TLV_FW_NUM_STATIONS		= IWL_UCODE_TLV_CONST_BASE + 0,  	IWL_UCODE_TLV_TYPE_DEBUG_INFO		= IWL_UCODE_TLV_DEBUG_BASE + 0, @@ -107,6 +110,7 @@ enum iwl_ucode_tlv_type {  	IWL_UCODE_TLV_TYPE_HCMD			= IWL_UCODE_TLV_DEBUG_BASE + 2,  	IWL_UCODE_TLV_TYPE_REGIONS		= IWL_UCODE_TLV_DEBUG_BASE + 3,  	IWL_UCODE_TLV_TYPE_TRIGGERS		= IWL_UCODE_TLV_DEBUG_BASE + 4, +	IWL_UCODE_TLV_TYPE_CONF_SET		= IWL_UCODE_TLV_DEBUG_BASE + 5,  	IWL_UCODE_TLV_DEBUG_MAX = IWL_UCODE_TLV_TYPE_TRIGGERS,  	/* TLVs 0x1000-0x2000 are for internal driver usage */ @@ -416,6 +420,8 @@ enum iwl_ucode_tlv_capa {  	IWL_UCODE_TLV_CAPA_PASSIVE_6GHZ_SCAN		= (__force iwl_ucode_tlv_capa_t)58,  	IWL_UCODE_TLV_CAPA_HIDDEN_6GHZ_SCAN		= (__force iwl_ucode_tlv_capa_t)59,  	IWL_UCODE_TLV_CAPA_BROADCAST_TWT		= (__force iwl_ucode_tlv_capa_t)60, +	IWL_UCODE_TLV_CAPA_COEX_HIGH_PRIO		= (__force iwl_ucode_tlv_capa_t)61, +	IWL_UCODE_TLV_CAPA_RFIM_SUPPORT			= (__force iwl_ucode_tlv_capa_t)62,  	/* set 2 */  	IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE		= (__force iwl_ucode_tlv_capa_t)64, @@ -449,7 +455,7 @@ enum iwl_ucode_tlv_capa {  	IWL_UCODE_TLV_CAPA_PSC_CHAN_SUPPORT		= (__force iwl_ucode_tlv_capa_t)98,  	IWL_UCODE_TLV_CAPA_BIGTK_SUPPORT		= (__force iwl_ucode_tlv_capa_t)100, -	IWL_UCODE_TLV_CAPA_RFIM_SUPPORT			= (__force iwl_ucode_tlv_capa_t)102, +	IWL_UCODE_TLV_CAPA_DRAM_FRAG_SUPPORT		= (__force iwl_ucode_tlv_capa_t)104,  #ifdef __CHECKER__  	/* sparse says it cannot increment the previous enum member */ @@ -956,6 +962,10 @@ struct iwl_fw_tcm_error_addr {  	__le32 addr;  }; /* FW_TLV_TCM_ERROR_INFO_ADDRS_S */ +struct iwl_fw_dump_exclude { +	__le32 addr, size; +}; +  static inline size_t _iwl_tlv_array_len(const struct iwl_ucode_tlv *tlv,  					size_t fixed_size, size_t var_size)  { diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.c b/drivers/net/wireless/intel/iwlwifi/fw/img.c index c2a4e60518bc..24a966673691 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/img.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/img.c @@ -1,59 +1,7 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license.  When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/*   * Copyright(c) 2019 - 2020 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * General Public License for more details. - * - * The full GNU General Public License is included in this distribution - * in the file called COPYING. - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2019 - 2020 Intel Corporation - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - *  * Redistributions of source code must retain the above copyright - *    notice, this list of conditions and the following disclaimer. - *  * Redistributions in binary form must reproduce the above copyright - *    notice, this list of conditions and the following disclaimer in - *    the documentation and/or other materials provided with the - *    distribution. - *  * Neither the name Intel Corporation nor the names of its - *    contributors may be used to endorse or promote products derived - *    from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ + */  #include "img.h" diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.h b/drivers/net/wireless/intel/iwlwifi/fw/img.h index 153a3529e77a..993bda17fa30 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/img.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/img.h @@ -124,11 +124,13 @@ struct fw_img {   * @fw_paging_phys: page phy pointer   * @fw_paging_block: pointer to the allocated block   * @fw_paging_size: page size + * @fw_offs: offset in the device   */  struct iwl_fw_paging {  	dma_addr_t fw_paging_phys;  	struct page *fw_paging_block;  	u32 fw_paging_size; +	u32 fw_offs;  };  /** @@ -174,6 +176,10 @@ struct iwl_fw_dbg {  	u32 dump_mask;  }; +struct iwl_dump_exclude { +	u32 addr, size; +}; +  /**   * struct iwl_fw - variables associated with the firmware   * @@ -194,6 +200,10 @@ struct iwl_fw_dbg {   * @cipher_scheme: optional external cipher scheme.   * @human_readable: human readable version   *	we get the ALIVE from the uCode + * @phy_integration_ver: PHY integration version string + * @phy_integration_ver_len: length of @phy_integration_ver + * @dump_excl: image dump exclusion areas for RT image + * @dump_excl_wowlan: image dump exclusion areas for WoWLAN image   */  struct iwl_fw {  	u32 ucode_ver; @@ -225,6 +235,8 @@ struct iwl_fw {  	u8 *phy_integration_ver;  	u32 phy_integration_ver_len; + +	struct iwl_dump_exclude dump_excl[2], dump_excl_wowlan[2];  };  static inline const char *get_fw_dbg_mode_string(int mode) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/init.c b/drivers/net/wireless/intel/iwlwifi/fw/init.c index 2ecec00db9da..566957ac4539 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/init.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/init.c @@ -1,7 +1,7 @@  // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause  /*   * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2019-2020 Intel Corporation + * Copyright (C) 2019-2021 Intel Corporation   */  #include "iwl-drv.h"  #include "runtime.h" @@ -16,6 +16,8 @@  void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,  			const struct iwl_fw *fw,  			const struct iwl_fw_runtime_ops *ops, void *ops_ctx, +			const struct iwl_dump_sanitize_ops *sanitize_ops, +			void *sanitize_ctx,  			struct dentry *dbgfs_dir)  {  	int i; @@ -26,6 +28,8 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,  	fwrt->dev = trans->dev;  	fwrt->dump.conf = FW_DBG_INVALID;  	fwrt->ops = ops; +	fwrt->sanitize_ops = sanitize_ops; +	fwrt->sanitize_ctx = sanitize_ctx;  	fwrt->ops_ctx = ops_ctx;  	for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++) {  		fwrt->dump.wks[i].idx = i; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/paging.c b/drivers/net/wireless/intel/iwlwifi/fw/paging.c index 4a8fe9641a32..58ca3849d1f3 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/paging.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/paging.c @@ -1,6 +1,6 @@  // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause  /* - * Copyright (C) 2012-2014, 2018-2019 Intel Corporation + * Copyright (C) 2012-2014, 2018-2019, 2021 Intel Corporation   * Copyright (C) 2013-2015 Intel Mobile Communications GmbH   * Copyright (C) 2016-2017 Intel Deutschland GmbH   */ @@ -152,6 +152,7 @@ static int iwl_fill_paging_mem(struct iwl_fw_runtime *fwrt,  	memcpy(page_address(fwrt->fw_paging_db[0].fw_paging_block),  	       image->sec[sec_idx].data,  	       image->sec[sec_idx].len); +	fwrt->fw_paging_db[0].fw_offs = image->sec[sec_idx].offset;  	dma_sync_single_for_device(fwrt->trans->dev,  				   fwrt->fw_paging_db[0].fw_paging_phys,  				   fwrt->fw_paging_db[0].fw_paging_size, @@ -197,6 +198,7 @@ static int iwl_fill_paging_mem(struct iwl_fw_runtime *fwrt,  		memcpy(page_address(block->fw_paging_block),  		       image->sec[sec_idx].data + offset, len); +		block->fw_offs = image->sec[sec_idx].offset + offset;  		dma_sync_single_for_device(fwrt->trans->dev,  					   block->fw_paging_phys,  					   block->fw_paging_size, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c index dde22bdc8703..7d4aa398729a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c @@ -162,7 +162,7 @@ done:  		goto out;  	} -	IWL_INFO(trans, "loaded PNVM version 0x%0x\n", sha1); +	IWL_INFO(trans, "loaded PNVM version %08x\n", sha1);  	ret = iwl_trans_set_pnvm(trans, pnvm_data, size);  out: @@ -284,16 +284,19 @@ int iwl_pnvm_load(struct iwl_trans *trans,  	/* First attempt to get the PNVM from BIOS */  	package = iwl_uefi_get_pnvm(trans, &len);  	if (!IS_ERR_OR_NULL(package)) { -		data = kmemdup(package->data, len, GFP_KERNEL); +		if (len >= sizeof(*package)) { +			/* we need only the data */ +			len -= sizeof(*package); +			data = kmemdup(package->data, len, GFP_KERNEL); +		} else { +			data = NULL; +		}  		/* free package regardless of whether kmemdup succeeded */  		kfree(package); -		if (data) { -			/* we need only the data size */ -			len -= sizeof(*package); +		if (data)  			goto parse; -		}  	}  	/* If it's not available, try from the filesystem */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/rs.c b/drivers/net/wireless/intel/iwlwifi/fw/rs.c new file mode 100644 index 000000000000..a21c3befd93b --- /dev/null +++ b/drivers/net/wireless/intel/iwlwifi/fw/rs.c @@ -0,0 +1,252 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* + * Copyright (C) 2021 Intel Corporation + */ + +#include <net/mac80211.h> +#include "fw/api/rs.h" +#include "iwl-drv.h" +#include "iwl-config.h" + +#define IWL_DECLARE_RATE_INFO(r) \ +	[IWL_RATE_##r##M_INDEX] = IWL_RATE_##r##M_PLCP + +/* + * Translate from fw_rate_index (IWL_RATE_XXM_INDEX) to PLCP + * */ +static const u8 fw_rate_idx_to_plcp[IWL_RATE_COUNT] = { +	IWL_DECLARE_RATE_INFO(1), +	IWL_DECLARE_RATE_INFO(2), +	IWL_DECLARE_RATE_INFO(5), +	IWL_DECLARE_RATE_INFO(11), +	IWL_DECLARE_RATE_INFO(6), +	IWL_DECLARE_RATE_INFO(9), +	IWL_DECLARE_RATE_INFO(12), +	IWL_DECLARE_RATE_INFO(18), +	IWL_DECLARE_RATE_INFO(24), +	IWL_DECLARE_RATE_INFO(36), +	IWL_DECLARE_RATE_INFO(48), +	IWL_DECLARE_RATE_INFO(54), +}; + +/* mbps, mcs */ +static const struct iwl_rate_mcs_info rate_mcs[IWL_RATE_COUNT] = { +	{  "1", "BPSK DSSS"}, +	{  "2", "QPSK DSSS"}, +	{"5.5", "BPSK CCK"}, +	{ "11", "QPSK CCK"}, +	{  "6", "BPSK 1/2"}, +	{  "9", "BPSK 1/2"}, +	{ "12", "QPSK 1/2"}, +	{ "18", "QPSK 3/4"}, +	{ "24", "16QAM 1/2"}, +	{ "36", "16QAM 3/4"}, +	{ "48", "64QAM 2/3"}, +	{ "54", "64QAM 3/4"}, +	{ "60", "64QAM 5/6"}, +}; + +static const char * const ant_name[] = { +	[ANT_NONE] = "None", +	[ANT_A]    = "A", +	[ANT_B]    = "B", +	[ANT_AB]   = "AB", +}; + +static const char * const pretty_bw[] = { +	"20Mhz", +	"40Mhz", +	"80Mhz", +	"160 Mhz", +	"320Mhz", +}; + +u8 iwl_fw_rate_idx_to_plcp(int idx) +{ +	return fw_rate_idx_to_plcp[idx]; +} +IWL_EXPORT_SYMBOL(iwl_fw_rate_idx_to_plcp); + +const struct iwl_rate_mcs_info *iwl_rate_mcs(int idx) +{ +	return &rate_mcs[idx]; +} +IWL_EXPORT_SYMBOL(iwl_rate_mcs); + +const char *iwl_rs_pretty_ant(u8 ant) +{ +	if (ant >= ARRAY_SIZE(ant_name)) +		return "UNKNOWN"; + +	return ant_name[ant]; +} +IWL_EXPORT_SYMBOL(iwl_rs_pretty_ant); + +const char *iwl_rs_pretty_bw(int bw) +{ +	if (bw >= ARRAY_SIZE(pretty_bw)) +		return "unknown bw"; + +	return pretty_bw[bw]; +} +IWL_EXPORT_SYMBOL(iwl_rs_pretty_bw); + +u32 iwl_new_rate_from_v1(u32 rate_v1) +{ +	u32 rate_v2 = 0; +	u32 dup = 0; + +	if (rate_v1 == 0) +		return rate_v1; +	/* convert rate */ +	if (rate_v1 & RATE_MCS_HT_MSK_V1) { +		u32 nss = 0; + +		rate_v2 |= RATE_MCS_HT_MSK; +		rate_v2 |= +			rate_v1 & RATE_HT_MCS_RATE_CODE_MSK_V1; +		nss = (rate_v1 & RATE_HT_MCS_MIMO2_MSK) >> +			RATE_HT_MCS_NSS_POS_V1; +		rate_v2 |= nss << RATE_MCS_NSS_POS; +	} else if (rate_v1 & RATE_MCS_VHT_MSK_V1 || +		   rate_v1 & RATE_MCS_HE_MSK_V1) { +		rate_v2 |= rate_v1 & RATE_VHT_MCS_RATE_CODE_MSK; + +		rate_v2 |= rate_v1 & RATE_VHT_MCS_MIMO2_MSK; + +		if (rate_v1 & RATE_MCS_HE_MSK_V1) { +			u32 he_type_bits = rate_v1 & RATE_MCS_HE_TYPE_MSK_V1; +			u32 he_type = he_type_bits >> RATE_MCS_HE_TYPE_POS_V1; +			u32 he_106t = (rate_v1 & RATE_MCS_HE_106T_MSK_V1) >> +				RATE_MCS_HE_106T_POS_V1; +			u32 he_gi_ltf = (rate_v1 & RATE_MCS_HE_GI_LTF_MSK_V1) >> +				RATE_MCS_HE_GI_LTF_POS; + +			if ((he_type_bits == RATE_MCS_HE_TYPE_SU || +			     he_type_bits == RATE_MCS_HE_TYPE_EXT_SU) && +			    he_gi_ltf == RATE_MCS_HE_SU_4_LTF) +				/* the new rate have an additional bit to +				 * represent the value 4 rather then using SGI +				 * bit for this purpose - as it was done in the old +				 * rate */ +				he_gi_ltf += (rate_v1 & RATE_MCS_SGI_MSK_V1) >> +					RATE_MCS_SGI_POS_V1; + +			rate_v2 |= he_gi_ltf << RATE_MCS_HE_GI_LTF_POS; +			rate_v2 |= he_type << RATE_MCS_HE_TYPE_POS; +			rate_v2 |= he_106t << RATE_MCS_HE_106T_POS; +			rate_v2 |= rate_v1 & RATE_HE_DUAL_CARRIER_MODE_MSK; +			rate_v2 |= RATE_MCS_HE_MSK; +		} else { +			rate_v2 |= RATE_MCS_VHT_MSK; +		} +	/* if legacy format */ +	} else { +		u32 legacy_rate = iwl_legacy_rate_to_fw_idx(rate_v1); + +		WARN_ON(legacy_rate < 0); +		rate_v2 |= legacy_rate; +		if (!(rate_v1 & RATE_MCS_CCK_MSK_V1)) +			rate_v2 |= RATE_MCS_LEGACY_OFDM_MSK; +	} + +	/* convert flags */ +	if (rate_v1 & RATE_MCS_LDPC_MSK_V1) +		rate_v2 |= RATE_MCS_LDPC_MSK; +	rate_v2 |= (rate_v1 & RATE_MCS_CHAN_WIDTH_MSK_V1) | +		(rate_v1 & RATE_MCS_ANT_AB_MSK) | +		(rate_v1 & RATE_MCS_STBC_MSK) | +		(rate_v1 & RATE_MCS_BF_MSK); + +	dup = (rate_v1 & RATE_MCS_DUP_MSK_V1) >> RATE_MCS_DUP_POS_V1; +	if (dup) { +		rate_v2 |= RATE_MCS_DUP_MSK; +		rate_v2 |= dup << RATE_MCS_CHAN_WIDTH_POS; +	} + +	if ((!(rate_v1 & RATE_MCS_HE_MSK_V1)) && +	    (rate_v1 & RATE_MCS_SGI_MSK_V1)) +		rate_v2 |= RATE_MCS_SGI_MSK; + +	return rate_v2; +} +IWL_EXPORT_SYMBOL(iwl_new_rate_from_v1); + +u32 iwl_legacy_rate_to_fw_idx(u32 rate_n_flags) +{ +	int rate = rate_n_flags & RATE_LEGACY_RATE_MSK_V1; +	int idx; +	bool ofdm = !(rate_n_flags & RATE_MCS_CCK_MSK_V1); +	int offset = ofdm ? IWL_FIRST_OFDM_RATE : 0; +	int last = ofdm ? IWL_RATE_COUNT_LEGACY : IWL_FIRST_OFDM_RATE; + +	for (idx = offset; idx < last; idx++) +		if (iwl_fw_rate_idx_to_plcp(idx) == rate) +			return idx - offset; +	return -1; +} + +int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate) +{ +	char *type; +	u8 mcs = 0, nss = 0; +	u8 ant = (rate & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS; +	u32 bw = (rate & RATE_MCS_CHAN_WIDTH_MSK) >> +		RATE_MCS_CHAN_WIDTH_POS; +	u32 format = rate & RATE_MCS_MOD_TYPE_MSK; +	bool sgi; + +	if (format == RATE_MCS_CCK_MSK || +	    format == RATE_MCS_LEGACY_OFDM_MSK) { +		int legacy_rate = rate & RATE_LEGACY_RATE_MSK; +		int index = format == RATE_MCS_CCK_MSK ? +			legacy_rate : +			legacy_rate + IWL_FIRST_OFDM_RATE; + +		return scnprintf(buf, bufsz, "Legacy | ANT: %s Rate: %s Mbps", +				 iwl_rs_pretty_ant(ant), +				 index == IWL_RATE_INVALID ? "BAD" : +				 iwl_rate_mcs(index)->mbps); +	} + +	if (format ==  RATE_MCS_VHT_MSK) +		type = "VHT"; +	else if (format ==  RATE_MCS_HT_MSK) +		type = "HT"; +	else if (format == RATE_MCS_HE_MSK) +		type = "HE"; +	else +		type = "Unknown"; /* shouldn't happen */ + +	mcs = format == RATE_MCS_HT_MSK ? +		RATE_HT_MCS_INDEX(rate) : +		rate & RATE_MCS_CODE_MSK; +	nss = ((rate & RATE_MCS_NSS_MSK) +	       >> RATE_MCS_NSS_POS) + 1; +	sgi = format == RATE_MCS_HE_MSK ? +		iwl_he_is_sgi(rate) : +		rate & RATE_MCS_SGI_MSK; + +	return scnprintf(buf, bufsz, +			 "0x%x: %s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s", +			 rate, type, iwl_rs_pretty_ant(ant), iwl_rs_pretty_bw(bw), mcs, nss, +			 (sgi) ? "SGI " : "NGI ", +			 (rate & RATE_MCS_STBC_MSK) ? "STBC " : "", +			 (rate & RATE_MCS_LDPC_MSK) ? "LDPC " : "", +			 (rate & RATE_HE_DUAL_CARRIER_MODE_MSK) ? "DCM " : "", +			 (rate & RATE_MCS_BF_MSK) ? "BF " : ""); +} +IWL_EXPORT_SYMBOL(rs_pretty_print_rate); + +bool iwl_he_is_sgi(u32 rate_n_flags) +{ +	u32 type = rate_n_flags & RATE_MCS_HE_TYPE_MSK; +	u32 ltf_gi = rate_n_flags & RATE_MCS_HE_GI_LTF_MSK; + +	if (type == RATE_MCS_HE_TYPE_SU || +	    type == RATE_MCS_HE_TYPE_EXT_SU) +		return ltf_gi == RATE_MCS_HE_SU_4_LTF_08_GI; +	return false; +} +IWL_EXPORT_SYMBOL(iwl_he_is_sgi); + diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index 35af85a5430b..69799f1ed2c4 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -105,6 +105,9 @@ struct iwl_fw_runtime {  	const struct iwl_fw_runtime_ops *ops;  	void *ops_ctx; +	const struct iwl_dump_sanitize_ops *sanitize_ops; +	void *sanitize_ctx; +  	/* Paging */  	struct iwl_fw_paging fw_paging_db[NUM_OF_FW_PAGING_BLOCKS];  	u16 num_of_paging_blk; @@ -151,7 +154,7 @@ struct iwl_fw_runtime {  	struct iwl_sar_profile sar_profiles[ACPI_SAR_PROFILE_NUM];  	u8 sar_chain_a_profile;  	u8 sar_chain_b_profile; -	struct iwl_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES]; +	struct iwl_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES_REV3];  	u32 geo_rev;  	union iwl_ppag_table_cmd ppag_table;  	u32 ppag_ver; @@ -161,6 +164,8 @@ struct iwl_fw_runtime {  void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,  			const struct iwl_fw *fw,  			const struct iwl_fw_runtime_ops *ops, void *ops_ctx, +			const struct iwl_dump_sanitize_ops *sanitize_ops, +			void *sanitize_ctx,  			struct dentry *dbgfs_dir);  static inline void iwl_fw_runtime_free(struct iwl_fw_runtime *fwrt) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h index 45d0b36d79b5..d552c656ac9f 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h @@ -2,7 +2,8 @@  /*   * Copyright(c) 2021 Intel Corporation   */ - +#ifndef __iwl_fw_uefi__ +#define __iwl_fw_uefi__  #define IWL_UEFI_OEM_PNVM_NAME		L"UefiCnvWlanOemSignedPnvm"  #define IWL_UEFI_REDUCED_POWER_NAME	L"UefiCnvWlanReducedPower" @@ -40,3 +41,5 @@ void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)  	return ERR_PTR(-EOPNOTSUPP);  }  #endif /* CONFIG_EFI */ + +#endif /* __iwl_fw_uefi__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 7eb534df5331..665167a223f6 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -95,7 +95,6 @@ enum iwl_nvm_type {  #define	ANT_AC		(ANT_A | ANT_C)  #define ANT_BC		(ANT_B | ANT_C)  #define ANT_ABC		(ANT_A | ANT_B | ANT_C) -#define MAX_ANT_NUM 3  static inline u8 num_of_ant(u8 mask) @@ -420,6 +419,7 @@ struct iwl_cfg {  #define IWL_CFG_MAC_TYPE_SOF		0x43  #define IWL_CFG_MAC_TYPE_MA		0x44  #define IWL_CFG_MAC_TYPE_BZ		0x46 +#define IWL_CFG_MAC_TYPE_GL		0x47  #define IWL_CFG_RF_TYPE_TH		0x105  #define IWL_CFG_RF_TYPE_TH1		0x108 @@ -511,6 +511,10 @@ extern const char iwl_ax210_killer_1675w_name[];  extern const char iwl_ax210_killer_1675x_name[];  extern const char iwl9560_killer_1550i_160_name[];  extern const char iwl9560_killer_1550s_160_name[]; +extern const char iwl_ax211_killer_1675s_name[]; +extern const char iwl_ax211_killer_1675i_name[]; +extern const char iwl_ax411_killer_1690s_name[]; +extern const char iwl_ax411_killer_1690i_name[];  extern const char iwl_ax211_name[];  extern const char iwl_ax221_name[];  extern const char iwl_ax231_name[]; @@ -628,6 +632,8 @@ extern const struct iwl_cfg iwl_cfg_bz_a0_hr_b0;  extern const struct iwl_cfg iwl_cfg_bz_a0_gf_a0;  extern const struct iwl_cfg iwl_cfg_bz_a0_gf4_a0;  extern const struct iwl_cfg iwl_cfg_bz_a0_mr_a0; +extern const struct iwl_cfg iwl_cfg_bz_a0_fm_a0; +extern const struct iwl_cfg iwl_cfg_gl_a0_fm_a0;  #endif /* CONFIG_IWLMVM */  #endif /* __IWL_CONFIG_H__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h index e1fec23ac07f..5adf485db38e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h @@ -109,12 +109,12 @@ struct iwl_prph_scratch_pnvm_cfg {   * struct iwl_prph_scratch_hwm_cfg - hwm config   * @hwm_base_addr: hwm start address   * @hwm_size: hwm size in DWs - * @reserved: reserved + * @debug_token_config: debug preset   */  struct iwl_prph_scratch_hwm_cfg {  	__le64 hwm_base_addr;  	__le32 hwm_size; -	__le32 reserved; +	__le32 debug_token_config;  } __packed; /* PERIPH_SCRATCH_HWM_CFG_S */  /* diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h index cf796403c45c..ff79a2ecb242 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h @@ -34,6 +34,7 @@  #define CSR_GPIO_IN             (CSR_BASE+0x018) /* read external chip pins */  #define CSR_RESET               (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/  #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()! */  #define CSR_INT_PERIODIC_REG	(CSR_BASE+0x005) @@ -135,6 +136,12 @@  #define CSR_DBG_HPET_MEM_REG		(CSR_BASE+0x240)  #define CSR_DBG_LINK_PWR_MGMT_REG	(CSR_BASE+0x250) +/* + * Scratch register initial configuration - this is set on init, and read + * during a error FW error. + */ +#define CSR_FUNC_SCRATCH_INIT_VALUE		(0x01010101) +  /* Bits for CSR_HW_IF_CONFIG_REG */  #define CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH	(0x00000003)  #define CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP	(0x0000000C) @@ -598,6 +605,7 @@ enum msix_hw_int_causes {  	MSIX_HW_INT_CAUSES_REG_WAKEUP		= BIT(1),  	MSIX_HW_INT_CAUSES_REG_IML              = BIT(1),  	MSIX_HW_INT_CAUSES_REG_RESET_DONE	= BIT(2), +	MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ	= BIT(5),  	MSIX_HW_INT_CAUSES_REG_CT_KILL		= BIT(6),  	MSIX_HW_INT_CAUSES_REG_RF_KILL		= BIT(7),  	MSIX_HW_INT_CAUSES_REG_PERIODIC		= BIT(8), diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index 125479b5c0d6..7ab98b419cc1 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c @@ -16,6 +16,7 @@   * @IWL_DBG_TLV_TYPE_HCMD: host command TLV   * @IWL_DBG_TLV_TYPE_REGION: region TLV   * @IWL_DBG_TLV_TYPE_TRIGGER: trigger TLV + * @IWL_DBG_TLV_TYPE_CONF_SET: conf set TLV   * @IWL_DBG_TLV_TYPE_NUM: number of debug TLVs   */  enum iwl_dbg_tlv_type { @@ -25,6 +26,7 @@ enum iwl_dbg_tlv_type {  	IWL_DBG_TLV_TYPE_HCMD,  	IWL_DBG_TLV_TYPE_REGION,  	IWL_DBG_TLV_TYPE_TRIGGER, +	IWL_DBG_TLV_TYPE_CONF_SET,  	IWL_DBG_TLV_TYPE_NUM,  }; @@ -59,6 +61,7 @@ dbg_ver_table[IWL_DBG_TLV_TYPE_NUM] = {  	[IWL_DBG_TLV_TYPE_HCMD]		= {.min_ver = 1, .max_ver = 1,},  	[IWL_DBG_TLV_TYPE_REGION]	= {.min_ver = 1, .max_ver = 2,},  	[IWL_DBG_TLV_TYPE_TRIGGER]	= {.min_ver = 1, .max_ver = 1,}, +	[IWL_DBG_TLV_TYPE_CONF_SET]	= {.min_ver = 1, .max_ver = 1,},  };  static int iwl_dbg_tlv_add(const struct iwl_ucode_tlv *tlv, @@ -260,6 +263,30 @@ static int iwl_dbg_tlv_alloc_trigger(struct iwl_trans *trans,  	return ret;  } +static int iwl_dbg_tlv_config_set(struct iwl_trans *trans, +				  const struct iwl_ucode_tlv *tlv) +{ +	struct iwl_fw_ini_conf_set_tlv *conf_set = (void *)tlv->data; +	u32 tp = le32_to_cpu(conf_set->time_point); +	u32 type = le32_to_cpu(conf_set->set_type); + +	if (tp <= IWL_FW_INI_TIME_POINT_INVALID || +	    tp >= IWL_FW_INI_TIME_POINT_NUM) { +		IWL_DEBUG_FW(trans, +			     "WRT: Invalid time point %u for config set TLV\n", tp); +		return -EINVAL; +	} + +	if (type <= IWL_FW_INI_CONFIG_SET_TYPE_INVALID || +	    type >= IWL_FW_INI_CONFIG_SET_TYPE_MAX_NUM) { +		IWL_DEBUG_FW(trans, +			     "WRT: Invalid config set type %u for config set TLV\n", type); +		return -EINVAL; +	} + +	return iwl_dbg_tlv_add(tlv, &trans->dbg.time_point[tp].config_list); +} +  static int (*dbg_tlv_alloc[])(struct iwl_trans *trans,  			      const struct iwl_ucode_tlv *tlv) = {  	[IWL_DBG_TLV_TYPE_DEBUG_INFO]	= iwl_dbg_tlv_alloc_debug_info, @@ -267,6 +294,7 @@ static int (*dbg_tlv_alloc[])(struct iwl_trans *trans,  	[IWL_DBG_TLV_TYPE_HCMD]		= iwl_dbg_tlv_alloc_hcmd,  	[IWL_DBG_TLV_TYPE_REGION]	= iwl_dbg_tlv_alloc_region,  	[IWL_DBG_TLV_TYPE_TRIGGER]	= iwl_dbg_tlv_alloc_trigger, +	[IWL_DBG_TLV_TYPE_CONF_SET]	= iwl_dbg_tlv_config_set,  };  void iwl_dbg_tlv_alloc(struct iwl_trans *trans, const struct iwl_ucode_tlv *tlv, @@ -399,6 +427,13 @@ void iwl_dbg_tlv_free(struct iwl_trans *trans)  			list_del(&tlv_node->list);  			kfree(tlv_node);  		} + +		list_for_each_entry_safe(tlv_node, tlv_node_tmp, +					 &tp->config_list, list) { +			list_del(&tlv_node->list); +			kfree(tlv_node); +		} +  	}  	for (i = 0; i < ARRAY_SIZE(trans->dbg.fw_mon_ini); i++) @@ -466,6 +501,7 @@ void iwl_dbg_tlv_init(struct iwl_trans *trans)  		INIT_LIST_HEAD(&tp->trig_list);  		INIT_LIST_HEAD(&tp->hcmd_list);  		INIT_LIST_HEAD(&tp->active_trig_list); +		INIT_LIST_HEAD(&tp->config_list);  	}  } @@ -649,6 +685,10 @@ static void iwl_dbg_tlv_apply_buffers(struct iwl_fw_runtime *fwrt)  {  	int ret, i; +	if (fw_has_capa(&fwrt->fw->ucode_capa, +			IWL_UCODE_TLV_CAPA_DRAM_FRAG_SUPPORT)) +		return; +  	for (i = 0; i < IWL_FW_INI_ALLOCATION_NUM; i++) {  		ret = iwl_dbg_tlv_apply_buffer(fwrt, i);  		if (ret) @@ -658,6 +698,87 @@ static void iwl_dbg_tlv_apply_buffers(struct iwl_fw_runtime *fwrt)  	}  } +static int iwl_dbg_tlv_update_dram(struct iwl_fw_runtime *fwrt, +				   enum iwl_fw_ini_allocation_id alloc_id, +				   struct iwl_dram_info *dram_info) +{ +	struct iwl_fw_mon *fw_mon; +	u32 remain_frags, num_frags; +	int j, fw_mon_idx = 0; +	struct iwl_buf_alloc_cmd *data; + +	if (le32_to_cpu(fwrt->trans->dbg.fw_mon_cfg[alloc_id].buf_location) != +			IWL_FW_INI_LOCATION_DRAM_PATH) { +		IWL_DEBUG_FW(fwrt, "DRAM_PATH is not supported alloc_id %u\n", alloc_id); +		return -1; +	} + +	fw_mon = &fwrt->trans->dbg.fw_mon_ini[alloc_id]; + +	/* the first fragment of DBGC1 is given to the FW via register +	 * or context info +	 */ +	if (alloc_id == IWL_FW_INI_ALLOCATION_ID_DBGC1) +		fw_mon_idx++; + +	remain_frags = fw_mon->num_frags - fw_mon_idx; +	if (!remain_frags) +		return -1; + +	num_frags = min_t(u32, remain_frags, BUF_ALLOC_MAX_NUM_FRAGS); +	data = &dram_info->dram_frags[alloc_id - 1]; +	data->alloc_id = cpu_to_le32(alloc_id); +	data->num_frags = cpu_to_le32(num_frags); +	data->buf_location = cpu_to_le32(IWL_FW_INI_LOCATION_DRAM_PATH); + +	IWL_DEBUG_FW(fwrt, "WRT: DRAM buffer details alloc_id=%u, num_frags=%u\n", +		     cpu_to_le32(alloc_id), cpu_to_le32(num_frags)); + +	for (j = 0; j < num_frags; j++) { +		struct iwl_buf_alloc_frag *frag = &data->frags[j]; +		struct iwl_dram_data *fw_mon_frag = &fw_mon->frags[fw_mon_idx++]; + +		frag->addr = cpu_to_le64(fw_mon_frag->physical); +		frag->size = cpu_to_le32(fw_mon_frag->size); +		IWL_DEBUG_FW(fwrt, "WRT: DRAM fragment details\n"); +		IWL_DEBUG_FW(fwrt, "frag=%u, addr=0x%016llx, size=0x%x)\n", +			     j, cpu_to_le64(fw_mon_frag->physical), +			     cpu_to_le32(fw_mon_frag->size)); +	} +	return 0; +} + +static void iwl_dbg_tlv_update_drams(struct iwl_fw_runtime *fwrt) +{ +	int ret, i, dram_alloc = 0; +	struct iwl_dram_info dram_info; +	struct iwl_dram_data *frags = +		&fwrt->trans->dbg.fw_mon_ini[IWL_FW_INI_ALLOCATION_ID_DBGC1].frags[0]; + +	if (!fw_has_capa(&fwrt->fw->ucode_capa, +			 IWL_UCODE_TLV_CAPA_DRAM_FRAG_SUPPORT)) +		return; + +	dram_info.first_word = cpu_to_le32(DRAM_INFO_FIRST_MAGIC_WORD); +	dram_info.second_word = cpu_to_le32(DRAM_INFO_SECOND_MAGIC_WORD); + +	for (i = IWL_FW_INI_ALLOCATION_ID_DBGC1; +	     i <= IWL_FW_INI_ALLOCATION_ID_DBGC3; i++) { +		ret = iwl_dbg_tlv_update_dram(fwrt, i, &dram_info); +		if (!ret) +			dram_alloc++; +		else +			IWL_WARN(fwrt, +				 "WRT: Failed to set DRAM buffer for alloc id %d, ret=%d\n", +				 i, ret); +	} +	if (dram_alloc) { +		memcpy(frags->block, &dram_info, sizeof(dram_info)); +		IWL_DEBUG_FW(fwrt, "block data after  %016x\n", +			     *((int *)fwrt->trans->dbg.fw_mon_ini[1].frags[0].block)); +	} +} +  static void iwl_dbg_tlv_send_hcmds(struct iwl_fw_runtime *fwrt,  				   struct list_head *hcmd_list)  { @@ -677,6 +798,97 @@ static void iwl_dbg_tlv_send_hcmds(struct iwl_fw_runtime *fwrt,  	}  } +static void iwl_dbg_tlv_apply_config(struct iwl_fw_runtime *fwrt, +				     struct list_head *config_list) +{ +	struct iwl_dbg_tlv_node *node; + +	list_for_each_entry(node, config_list, list) { +		struct iwl_fw_ini_conf_set_tlv *config_list = (void *)node->tlv.data; +		u32 count, address, value; +		u32 len = (le32_to_cpu(node->tlv.length) - sizeof(*config_list)) / 8; +		u32 type = le32_to_cpu(config_list->set_type); +		u32 offset = le32_to_cpu(config_list->addr_offset); + +		switch (type) { +		case IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_MAC: { +			if (!iwl_trans_grab_nic_access(fwrt->trans)) { +				IWL_DEBUG_FW(fwrt, "WRT: failed to get nic access\n"); +				IWL_DEBUG_FW(fwrt, "WRT: skipping MAC PERIPHERY config\n"); +				continue; +			} +			IWL_DEBUG_FW(fwrt, "WRT:  MAC PERIPHERY config len: len %u\n", len); +			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_release_nic_access(fwrt->trans); +		break; +		} +		case IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_MEMORY: { +			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_mem32(fwrt->trans, address + offset, value); +				IWL_DEBUG_FW(fwrt, "WRT: DEV_MEM: count %u, add: %u val: %u\n", +					     count, address, value); +			} +		break; +		} +		case IWL_FW_INI_CONFIG_SET_TYPE_CSR: { +			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_DEBUG_FW(fwrt, "WRT: CSR: count %u, add: %u val: %u\n", +					     count, address, value); +			} +		break; +		} +		case IWL_FW_INI_CONFIG_SET_TYPE_DBGC_DRAM_ADDR: { +			struct iwl_dbgc1_info dram_info = {}; +			struct iwl_dram_data *frags = &fwrt->trans->dbg.fw_mon_ini[1].frags[0]; +			__le64 dram_base_addr = cpu_to_le64(frags->physical); +			__le32 dram_size = cpu_to_le32(frags->size); +			u64  dram_addr = le64_to_cpu(dram_base_addr); +			u32 ret; + +			IWL_DEBUG_FW(fwrt, "WRT: dram_base_addr 0x%016llx, dram_size 0x%x\n", +				     dram_base_addr, dram_size); +			IWL_DEBUG_FW(fwrt, "WRT: config_list->addr_offset: %u\n", +				     le32_to_cpu(config_list->addr_offset)); +			for (count = 0; count < len; count++) { +				address = le32_to_cpu(config_list->addr_val[count].address); +				dram_info.dbgc1_add_lsb = +					cpu_to_le32((dram_addr & 0x00000000FFFFFFFFULL) + 0x400); +				dram_info.dbgc1_add_msb = +					cpu_to_le32((dram_addr & 0xFFFFFFFF00000000ULL) >> 32); +				dram_info.dbgc1_size = cpu_to_le32(le32_to_cpu(dram_size) - 0x400); +				ret = iwl_trans_write_mem(fwrt->trans, +							  address + offset, &dram_info, 4); +				if (ret) { +					IWL_ERR(fwrt, "Failed to write dram_info to HW_SMEM\n"); +					break; +				} +			} +			break; +		} +		case IWL_FW_INI_CONFIG_SET_TYPE_PERIPH_SCRATCH_HWM: { +			u32 debug_token_config = +				le32_to_cpu(config_list->addr_val[0].value); + +			IWL_DEBUG_FW(fwrt, "WRT: Setting HWM debug token config: %u\n", +				     debug_token_config); +			fwrt->trans->dbg.ucode_preset = debug_token_config; +			break; +		} +		default: +			break; +		} +	} +} +  static void iwl_dbg_tlv_periodic_trig_handler(struct timer_list *t)  {  	struct iwl_dbg_tlv_timer_node *timer_node = @@ -996,8 +1208,10 @@ static void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt)  			&fwrt->trans->dbg.fw_mon_cfg[i];  		u32 dest = le32_to_cpu(fw_mon_cfg->buf_location); -		if (dest == IWL_FW_INI_LOCATION_INVALID) +		if (dest == IWL_FW_INI_LOCATION_INVALID) { +			failed_alloc |= BIT(i);  			continue; +		}  		if (*ini_dest == IWL_FW_INI_LOCATION_INVALID)  			*ini_dest = dest; @@ -1024,8 +1238,10 @@ static void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt)  			&fwrt->trans->dbg.active_regions[i];  		u32 reg_type; -		if (!*active_reg) +		if (!*active_reg) { +			fwrt->trans->dbg.unsupported_region_msk |= BIT(i);  			continue; +		}  		reg = (void *)(*active_reg)->data;  		reg_type = le32_to_cpu(reg->type); @@ -1051,7 +1267,7 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,  			     union iwl_dbg_tlv_tp_data *tp_data,  			     bool sync)  { -	struct list_head *hcmd_list, *trig_list; +	struct list_head *hcmd_list, *trig_list, *conf_list;  	if (!iwl_trans_dbg_ini_valid(fwrt->trans) ||  	    tp_id == IWL_FW_INI_TIME_POINT_INVALID || @@ -1060,15 +1276,19 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,  	hcmd_list = &fwrt->trans->dbg.time_point[tp_id].hcmd_list;  	trig_list = &fwrt->trans->dbg.time_point[tp_id].active_trig_list; +	conf_list = &fwrt->trans->dbg.time_point[tp_id].config_list;  	switch (tp_id) {  	case IWL_FW_INI_TIME_POINT_EARLY:  		iwl_dbg_tlv_init_cfg(fwrt); +		iwl_dbg_tlv_apply_config(fwrt, conf_list); +		iwl_dbg_tlv_update_drams(fwrt);  		iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, NULL);  		break;  	case IWL_FW_INI_TIME_POINT_AFTER_ALIVE:  		iwl_dbg_tlv_apply_buffers(fwrt);  		iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list); +		iwl_dbg_tlv_apply_config(fwrt, conf_list);  		iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, NULL);  		break;  	case IWL_FW_INI_TIME_POINT_PERIODIC: @@ -1079,11 +1299,13 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,  	case IWL_FW_INI_TIME_POINT_MISSED_BEACONS:  	case IWL_FW_INI_TIME_POINT_FW_DHC_NOTIFICATION:  		iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list); +		iwl_dbg_tlv_apply_config(fwrt, conf_list);  		iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data,  				       iwl_dbg_tlv_check_fw_pkt);  		break;  	default:  		iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list); +		iwl_dbg_tlv_apply_config(fwrt, conf_list);  		iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, NULL);  		break;  	} diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h index c12b1fd3f479..79287708bd6e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h @@ -33,11 +33,13 @@ union iwl_dbg_tlv_tp_data {   * @trig_list: list of triggers   * @active_trig_list: list of active triggers   * @hcmd_list: list of host commands + * @config_list: list of configuration   */  struct iwl_dbg_tlv_time_point_data {  	struct list_head trig_list;  	struct list_head active_trig_list;  	struct list_head hcmd_list; +	struct list_head config_list;  };  struct iwl_trans; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-debug.c b/drivers/net/wireless/intel/iwlwifi/iwl-debug.c index f6ca2fc37c40..ae4c2a3d63d5 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-debug.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-debug.c @@ -1,6 +1,6 @@  // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause  /* - * Copyright (C) 2005-2011 Intel Corporation + * Copyright (C) 2005-2011, 2021 Intel Corporation   */  #include <linux/device.h>  #include <linux/interrupt.h> @@ -31,21 +31,31 @@ IWL_EXPORT_SYMBOL(__iwl_info);  __iwl_fn(crit)  IWL_EXPORT_SYMBOL(__iwl_crit); -void __iwl_err(struct device *dev, bool rfkill_prefix, bool trace_only, -		const char *fmt, ...) +void __iwl_err(struct device *dev, enum iwl_err_mode mode, const char *fmt, ...)  {  	struct va_format vaf = {  		.fmt = fmt,  	}; -	va_list args; +	va_list args, args2;  	va_start(args, fmt); -	vaf.va = &args; -	if (!trace_only) { -		if (rfkill_prefix) +	switch (mode) { +	case IWL_ERR_MODE_RATELIMIT: +		if (net_ratelimit()) +			break; +		fallthrough; +	case IWL_ERR_MODE_REGULAR: +	case IWL_ERR_MODE_RFKILL: +		va_copy(args2, args); +		vaf.va = &args2; +		if (mode == IWL_ERR_MODE_RFKILL)  			dev_err(dev, "(RFKILL) %pV", &vaf);  		else  			dev_err(dev, "%pV", &vaf); +		va_end(args2); +		break; +	default: +		break;  	}  	trace_iwlwifi_err(&vaf);  	va_end(args); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-debug.h b/drivers/net/wireless/intel/iwlwifi/iwl-debug.h index 528eba441926..1b9f16a31b54 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-debug.h @@ -2,14 +2,9 @@  /******************************************************************************   *   * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2018 - 2020 Intel Corporation + * Copyright(c) 2018 - 2021 Intel Corporation   *   * Portions of this file are derived from the ipw3945 project. - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #ifndef __iwl_debug_h__ @@ -27,9 +22,16 @@ static inline bool iwl_have_debug_level(u32 level)  #endif  } +enum iwl_err_mode { +	IWL_ERR_MODE_REGULAR, +	IWL_ERR_MODE_RFKILL, +	IWL_ERR_MODE_TRACE_ONLY, +	IWL_ERR_MODE_RATELIMIT, +}; +  struct device; -void __iwl_err(struct device *dev, bool rfkill_prefix, bool only_trace, -		const char *fmt, ...) __printf(4, 5); +void __iwl_err(struct device *dev, enum iwl_err_mode mode, const char *fmt, ...) +	__printf(3, 4);  void __iwl_warn(struct device *dev, const char *fmt, ...) __printf(2, 3);  void __iwl_info(struct device *dev, const char *fmt, ...) __printf(2, 3);  void __iwl_crit(struct device *dev, const char *fmt, ...) __printf(2, 3); @@ -38,13 +40,17 @@ void __iwl_crit(struct device *dev, const char *fmt, ...) __printf(2, 3);  #define CHECK_FOR_NEWLINE(f) BUILD_BUG_ON(f[sizeof(f) - 2] != '\n')  /* No matter what is m (priv, bus, trans), this will work */ -#define IWL_ERR_DEV(d, f, a...)						\ +#define __IWL_ERR_DEV(d, mode, f, a...)					\  	do {								\  		CHECK_FOR_NEWLINE(f);					\ -		__iwl_err((d), false, false, f, ## a);			\ +		__iwl_err((d), mode, f, ## a);				\  	} while (0) +#define IWL_ERR_DEV(d, f, a...)						\ +	__IWL_ERR_DEV(d, IWL_ERR_MODE_REGULAR, f, ## a)  #define IWL_ERR(m, f, a...)						\  	IWL_ERR_DEV((m)->dev, f, ## a) +#define IWL_ERR_LIMIT(m, f, a...)					\ +	__IWL_ERR_DEV((m)->dev, IWL_ERR_MODE_RATELIMIT, f, ## a)  #define IWL_WARN(m, f, a...)						\  	do {								\  		CHECK_FOR_NEWLINE(f);					\ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h index 1bc6ecc32140..347fd95c4e3a 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h @@ -4,11 +4,6 @@   * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.   * Copyright(c) 2015        Intel Deutschland GmbH   * Copyright(c) 2018 - 2019 Intel Corporation - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #if !defined(__IWLWIFI_DEVICE_TRACE_DATA) || defined(TRACE_HEADER_MULTI_READ) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h index a57019241a78..0af9d8362c5b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h @@ -3,11 +3,6 @@   *   * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.   * Copyright(c) 2016-2017 Intel Deutschland GmbH - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #if !defined(__IWLWIFI_DEVICE_TRACE_IO) || defined(TRACE_HEADER_MULTI_READ) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h index 72ca882daed5..46ed723f138a 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h @@ -5,11 +5,6 @@   * Copyright(c) 2015 Intel Mobile Communications GmbH   * Copyright(c) 2016 - 2017 Intel Deutschland GmbH   * Copyright(c) 2018        Intel Corporation - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #if !defined(__IWLWIFI_DEVICE_TRACE_IWLWIFI) || defined(TRACE_HEADER_MULTI_READ) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h index d0467da5af03..7dd70011fd1e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h @@ -2,11 +2,6 @@  /******************************************************************************   *   * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved. - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #if !defined(__IWLWIFI_DEVICE_TRACE_MSG) || defined(TRACE_HEADER_MULTI_READ) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-ucode.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-ucode.h index 2228faefffbc..3ec0205ac9f9 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-ucode.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-ucode.h @@ -2,11 +2,6 @@  /******************************************************************************   *   * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved. - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #if !defined(__IWLWIFI_DEVICE_TRACE_UCODE) || defined(TRACE_HEADER_MULTI_READ) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.c b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.c index b5037db0c381..999b7c652289 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.c @@ -3,11 +3,6 @@   *   * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.   * Copyright (C) 2018 Intel Corporation - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #include <linux/module.h> diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h index fc8bc212ee84..1455b578358b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h @@ -4,11 +4,6 @@   * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.   * Copyright(C) 2016        Intel Deutschland GmbH   * Copyright(c) 2018        Intel Corporation - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #ifndef __IWLWIFI_DEVICE_TRACE diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 77124b8b235e..36196e07b1a0 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -31,7 +31,6 @@  #define DRV_DESCRIPTION	"Intel(R) Wireless WiFi driver for Linux"  MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_AUTHOR);  MODULE_LICENSE("GPL");  #ifdef CONFIG_IWLWIFI_DEBUGFS @@ -550,6 +549,43 @@ static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv,  	return 0;  } +static void iwl_drv_set_dump_exclude(struct iwl_drv *drv, +				     enum iwl_ucode_tlv_type tlv_type, +				     const void *tlv_data, u32 tlv_len) +{ +	const struct iwl_fw_dump_exclude *fw = tlv_data; +	struct iwl_dump_exclude *excl; + +	if (tlv_len < sizeof(*fw)) +		return; + +	if (tlv_type == IWL_UCODE_TLV_SEC_TABLE_ADDR) { +		excl = &drv->fw.dump_excl[0]; + +		/* second time we find this, it's for WoWLAN */ +		if (excl->addr) +			excl = &drv->fw.dump_excl_wowlan[0]; +	} else if (fw_has_capa(&drv->fw.ucode_capa, +			       IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG)) { +		/* IWL_UCODE_TLV_D3_KEK_KCK_ADDR is regular image */ +		excl = &drv->fw.dump_excl[0]; +	} else { +		/* IWL_UCODE_TLV_D3_KEK_KCK_ADDR is WoWLAN image */ +		excl = &drv->fw.dump_excl_wowlan[0]; +	} + +	if (excl->addr) +		excl++; + +	if (excl->addr) { +		IWL_DEBUG_FW_INFO(drv, "found too many excludes in fw file\n"); +		return; +	} + +	excl->addr = le32_to_cpu(fw->addr) & ~FW_ADDR_CACHE_CONTROL; +	excl->size = le32_to_cpu(fw->size); +} +  static int iwl_parse_tlv_firmware(struct iwl_drv *drv,  				const struct firmware *ucode_raw,  				struct iwl_firmware_pieces *pieces, @@ -1133,6 +1169,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,  		case IWL_UCODE_TLV_TYPE_HCMD:  		case IWL_UCODE_TLV_TYPE_REGIONS:  		case IWL_UCODE_TLV_TYPE_TRIGGERS: +		case IWL_UCODE_TLV_TYPE_CONF_SET:  			if (iwlwifi_mod_params.enable_ini)  				iwl_dbg_tlv_alloc(drv->trans, tlv, false);  			break; @@ -1166,6 +1203,11 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,  				return -ENOMEM;  			drv->fw.phy_integration_ver_len = tlv_len;  			break; +		case IWL_UCODE_TLV_SEC_TABLE_ADDR: +		case IWL_UCODE_TLV_D3_KEK_KCK_ADDR: +			iwl_drv_set_dump_exclude(drv, tlv_type, +						 tlv_data, tlv_len); +			break;  		default:  			IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);  			break; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h index b6442df0c643..2e2d60a58692 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h @@ -1,6 +1,6 @@  /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */  /* - * Copyright (C) 2005-2014, 2020 Intel Corporation + * Copyright (C) 2005-2014, 2020-2021 Intel Corporation   * Copyright (C) 2013-2014 Intel Mobile Communications GmbH   */  #ifndef __iwl_drv_h__ @@ -9,7 +9,6 @@  /* for all modules */  #define DRV_NAME        "iwlwifi" -#define DRV_AUTHOR	"Intel Corporation <linuxwifi@intel.com>"  /* radio config bits (actual values from NVM definition) */  #define NVM_RF_CFG_DASH_MSK(x)   (x & 0x3)         /* bits 0-1   */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c index dbab2f10d750..b9e86bf972e5 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c @@ -1,6 +1,6 @@  // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause  /* - * Copyright (C) 2005-2014, 2018-2019 Intel Corporation + * Copyright (C) 2005-2014, 2018-2019, 2021 Intel Corporation   */  #include <linux/types.h>  #include <linux/slab.h> @@ -139,7 +139,7 @@ static int iwl_init_otp_access(struct iwl_trans *trans)  {  	int ret; -	ret = iwl_finish_nic_init(trans, trans->trans_cfg); +	ret = iwl_finish_nic_init(trans);  	if (ret)  		return ret; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c index 2517c4ae07ab..46917b4216b3 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c @@ -398,9 +398,50 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf)  	return 0;  } -int iwl_finish_nic_init(struct iwl_trans *trans, -			const struct iwl_cfg_trans_params *cfg_trans) +#define IWL_HOST_MON_BLOCK_PEMON	0x00 +#define IWL_HOST_MON_BLOCK_HIPM		0x22 + +#define IWL_HOST_MON_BLOCK_PEMON_VEC0	0x00 +#define IWL_HOST_MON_BLOCK_PEMON_VEC1	0x01 +#define IWL_HOST_MON_BLOCK_PEMON_WFPM	0x06 + +static void iwl_dump_host_monitor_block(struct iwl_trans *trans, +					u32 block, u32 vec, u32 iter) +{ +	int i; + +	IWL_ERR(trans, "Host monitor block 0x%x vector 0x%x\n", block, vec); +	iwl_write32(trans, CSR_MONITOR_CFG_REG, (block << 8) | vec); +	for (i = 0; i < iter; i++) +		IWL_ERR(trans, "    value [iter %d]: 0x%08x\n", +			i, iwl_read32(trans, CSR_MONITOR_STATUS_REG)); +} + +static void iwl_dump_host_monitor(struct iwl_trans *trans)  { +	switch (trans->trans_cfg->device_family) { +	case IWL_DEVICE_FAMILY_22000: +	case IWL_DEVICE_FAMILY_AX210: +		IWL_ERR(trans, "CSR_RESET = 0x%x\n", +			iwl_read32(trans, CSR_RESET)); +		iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON, +					    IWL_HOST_MON_BLOCK_PEMON_VEC0, 15); +		iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON, +					    IWL_HOST_MON_BLOCK_PEMON_VEC1, 15); +		iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON, +					    IWL_HOST_MON_BLOCK_PEMON_WFPM, 15); +		iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_HIPM, +					    IWL_HOST_MON_BLOCK_PEMON_VEC0, 1); +		break; +	default: +		/* not supported yet */ +		return; +	} +} + +int iwl_finish_nic_init(struct iwl_trans *trans) +{ +	const struct iwl_cfg_trans_params *cfg_trans = trans->trans_cfg;  	u32 poll_ready;  	int err; @@ -433,9 +474,12 @@ int iwl_finish_nic_init(struct iwl_trans *trans,  	 * and accesses to uCode SRAM.  	 */  	err = iwl_poll_bit(trans, CSR_GP_CNTRL, poll_ready, poll_ready, 25000); -	if (err < 0) +	if (err < 0) {  		IWL_DEBUG_INFO(trans, "Failed to wake NIC\n"); +		iwl_dump_host_monitor(trans); +	} +  	if (cfg_trans->bisr_workaround) {  		/* ensure BISR shift has finished */  		udelay(200); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-io.h index 3c21c0e081f8..37b3bd62897e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.h @@ -1,6 +1,6 @@  /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */  /* - * Copyright (C) 2018-2020 Intel Corporation + * Copyright (C) 2018-2021 Intel Corporation   */  #ifndef __iwl_io_h__  #define __iwl_io_h__ @@ -52,8 +52,7 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,  void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);  void iwl_force_nmi(struct iwl_trans *trans); -int iwl_finish_nic_init(struct iwl_trans *trans, -			const struct iwl_cfg_trans_params *cfg_trans); +int iwl_finish_nic_init(struct iwl_trans *trans);  /* Error handling */  int iwl_dump_fh(struct iwl_trans *trans, char **buf); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 475f951d4b1e..f470f9aea50f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -534,6 +534,17 @@ static void iwl_init_vht_hw_capab(struct iwl_trans *trans,  		cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE);  } +static const u8 iwl_vendor_caps[] = { +	0xdd,			/* vendor element */ +	0x06,			/* length */ +	0x00, 0x17, 0x35,	/* Intel OUI */ +	0x08,			/* type (Intel Capabilities) */ +	/* followed by 16 bits of capabilities */ +#define IWL_VENDOR_CAP_IMPROVED_BF_FDBK_HE	BIT(0) +	IWL_VENDOR_CAP_IMPROVED_BF_FDBK_HE, +	0x00 +}; +  static const struct ieee80211_sband_iftype_data iwl_he_capa[] = {  	{  		.types_mask = BIT(NL80211_IFTYPE_STATION), @@ -781,6 +792,12 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,  	if (fw_has_capa(&fw->ucode_capa, IWL_UCODE_TLV_CAPA_BROADCAST_TWT))  		iftype_data->he_cap.he_cap_elem.mac_cap_info[2] |=  			IEEE80211_HE_MAC_CAP2_BCAST_TWT; + +	if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000 && +	    !is_ap) { +		iftype_data->vendor_elems.data = iwl_vendor_caps; +		iftype_data->vendor_elems.len = ARRAY_SIZE(iwl_vendor_caps); +	}  }  static void iwl_init_he_hw_capab(struct iwl_trans *trans, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h index d0a7d58336a9..a84ab02cf9d7 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h @@ -347,6 +347,12 @@  #define RADIO_REG_SYS_MANUAL_DFT_0	0xAD4078  #define RFIC_REG_RD			0xAD0470  #define WFPM_CTRL_REG			0xA03030 +#define WFPM_CTRL_REG_GEN2		0xd03030 +#define WFPM_OTP_CFG1_ADDR		0x00a03098 +#define WFPM_OTP_CFG1_ADDR_GEN2		0x00d03098 +#define WFPM_OTP_CFG1_IS_JACKET_BIT	BIT(4) +#define WFPM_OTP_CFG1_IS_CDB_BIT	BIT(5) +  #define WFPM_GP2			0xA030B4  /* DBGI SRAM Register details */ @@ -399,10 +405,40 @@ enum {  	LMPM_PAGE_PASS_NOTIF_POS = BIT(20),  }; +/* + * CRF ID register + * + * type: bits 0-11 + * reserved: bits 12-18 + * slave_exist: bit 19 + * dash: bits 20-23 + * step: bits 24-26 + * flavor: bits 27-31 + */ +#define REG_CRF_ID_TYPE(val)		(((val) & 0x00000FFF) >> 0) +#define REG_CRF_ID_SLAVE(val)		(((val) & 0x00080000) >> 19) +#define REG_CRF_ID_DASH(val)		(((val) & 0x00F00000) >> 20) +#define REG_CRF_ID_STEP(val)		(((val) & 0x07000000) >> 24) +#define REG_CRF_ID_FLAVOR(val)		(((val) & 0xF8000000) >> 27) +  #define UREG_CHICK		(0xA05C00)  #define UREG_CHICK_MSI_ENABLE	BIT(24)  #define UREG_CHICK_MSIX_ENABLE	BIT(25) +#define SD_REG_VER		0xa29600 +#define SD_REG_VER_GEN2		0x00a2b800 + +#define REG_CRF_ID_TYPE_JF_1			0x201 +#define REG_CRF_ID_TYPE_JF_2			0x202 +#define REG_CRF_ID_TYPE_HR_CDB			0x503 +#define REG_CRF_ID_TYPE_HR_NONE_CDB		0x504 +#define REG_CRF_ID_TYPE_HR_NONE_CDB_1X1	0x501 +#define REG_CRF_ID_TYPE_HR_NONE_CDB_CCP	0x532 +#define REG_CRF_ID_TYPE_GF			0x410 +#define REG_CRF_ID_TYPE_GF_TC			0xF08 +#define REG_CRF_ID_TYPE_MR			0x810 +#define REG_CRF_ID_TYPE_FM			0x910 +  #define HPM_DEBUG			0xA03440  #define PERSISTENCE_BIT			BIT(12)  #define PREG_WFPM_ACCESS		BIT(12) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 8f0ff540f439..4ebb1871bd1f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -363,6 +363,20 @@ struct iwl_hcmd_arr {  	{ .arr = x, .size = ARRAY_SIZE(x) }  /** + * struct iwl_dump_sanitize_ops - dump sanitization operations + * @frob_txf: Scrub the TX FIFO data + * @frob_hcmd: Scrub a host command, the %hcmd pointer is to the header + *	but that might be short or long (&struct iwl_cmd_header or + *	&struct iwl_cmd_header_wide) + * @frob_mem: Scrub memory data + */ +struct iwl_dump_sanitize_ops { +	void (*frob_txf)(void *ctx, void *buf, size_t buflen); +	void (*frob_hcmd)(void *ctx, void *hcmd, size_t buflen); +	void (*frob_mem)(void *ctx, u32 mem_addr, void *mem, size_t buflen); +}; + +/**   * struct iwl_trans_config - transport configuration   *   * @op_mode: pointer to the upper layer. @@ -586,7 +600,9 @@ struct iwl_trans_ops {  			      u32 value);  	struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans, -						 u32 dump_mask); +						 u32 dump_mask, +						 const struct iwl_dump_sanitize_ops *sanitize_ops, +						 void *sanitize_ctx);  	void (*debugfs_cleanup)(struct iwl_trans *trans);  	void (*sync_nmi)(struct iwl_trans *trans);  	int (*set_pnvm)(struct iwl_trans *trans, const void *data, u32 len); @@ -723,8 +739,8 @@ struct iwl_self_init_dram {   * @debug_info_tlv_list: list of debug info TLVs   * @time_point: array of debug time points   * @periodic_trig_list: periodic triggers list - * @domains_bitmap: bitmap of active domains other than - *	&IWL_FW_INI_DOMAIN_ALWAYS_ON + * @domains_bitmap: bitmap of active domains other than &IWL_FW_INI_DOMAIN_ALWAYS_ON + * @ucode_preset: preset based on ucode   */  struct iwl_trans_debug {  	u8 n_dest_reg; @@ -758,6 +774,7 @@ struct iwl_trans_debug {  	struct list_head periodic_trig_list;  	u32 domains_bitmap; +	u32 ucode_preset;  };  struct iwl_dma_ptr { @@ -1086,11 +1103,14 @@ static inline int iwl_trans_d3_resume(struct iwl_trans *trans,  }  static inline struct iwl_trans_dump_data * -iwl_trans_dump_data(struct iwl_trans *trans, u32 dump_mask) +iwl_trans_dump_data(struct iwl_trans *trans, u32 dump_mask, +		    const struct iwl_dump_sanitize_ops *sanitize_ops, +		    void *sanitize_ctx)  {  	if (!trans->ops->dump_data)  		return NULL; -	return trans->ops->dump_data(trans, dump_mask); +	return trans->ops->dump_data(trans, dump_mask, +				     sanitize_ops, sanitize_ctx);  }  static inline struct iwl_device_tx_cmd * diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 9f706fffb592..a19f646a324f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -1379,12 +1379,49 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)  /* converted data from the different status responses */  struct iwl_wowlan_status_data { -	u16 pattern_number; -	u16 qos_seq_ctr[8]; +	u64 replay_ctr; +	u32 num_of_gtk_rekeys; +	u32 received_beacons;  	u32 wakeup_reasons;  	u32 wake_packet_length;  	u32 wake_packet_bufsize; -	const u8 *wake_packet; +	u16 pattern_number; +	u16 non_qos_seq_ctr; +	u16 qos_seq_ctr[8]; +	u8 tid_tear_down; + +	struct { +		/* +		 * We store both the TKIP and AES representations +		 * coming from the firmware because we decode the +		 * data from there before we iterate the keys and +		 * know which one we need. +		 */ +		struct { +			struct ieee80211_key_seq seq[IWL_MAX_TID_COUNT]; +		} tkip, aes; +		/* including RX MIC key for TKIP */ +		u8 key[WOWLAN_KEY_MAX_SIZE]; +		u8 len; +		u8 flags; +	} gtk; + +	struct { +		/* Same as above */ +		struct { +			struct ieee80211_key_seq seq[IWL_MAX_TID_COUNT]; +			u64 tx_pn; +		} tkip, aes; +	} ptk; + +	struct { +		u64 ipn; +		u8 key[WOWLAN_KEY_MAX_SIZE]; +		u8 len; +		u8 flags; +	} igtk; + +	u8 wake_packet[];  };  static void iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm, @@ -1540,77 +1577,90 @@ static void iwl_mvm_tkip_sc_to_seq(struct tkip_sc *sc,  	seq->tkip.iv16 = le16_to_cpu(sc->iv16);  } -static void iwl_mvm_set_aes_rx_seq(struct iwl_mvm *mvm, struct aes_sc *scs, -				   struct ieee80211_sta *sta, -				   struct ieee80211_key_conf *key) +static void iwl_mvm_set_key_rx_seq_tids(struct ieee80211_key_conf *key, +					struct ieee80211_key_seq *seq)  {  	int tid; -	BUILD_BUG_ON(IWL_NUM_RSC != IEEE80211_NUM_TIDS); +	for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) +		ieee80211_set_key_rx_seq(key, tid, &seq[tid]); +} -	if (sta && iwl_mvm_has_new_rx_api(mvm)) { -		struct iwl_mvm_sta *mvmsta; -		struct iwl_mvm_key_pn *ptk_pn; +static void iwl_mvm_set_aes_ptk_rx_seq(struct iwl_mvm *mvm, +				       struct iwl_wowlan_status_data *status, +				       struct ieee80211_sta *sta, +				       struct ieee80211_key_conf *key) +{ +	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); +	struct iwl_mvm_key_pn *ptk_pn; +	int tid; -		mvmsta = iwl_mvm_sta_from_mac80211(sta); +	iwl_mvm_set_key_rx_seq_tids(key, status->ptk.aes.seq); -		rcu_read_lock(); -		ptk_pn = rcu_dereference(mvmsta->ptk_pn[key->keyidx]); -		if (WARN_ON(!ptk_pn)) { -			rcu_read_unlock(); -			return; -		} +	if (!iwl_mvm_has_new_rx_api(mvm)) +		return; -		for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) { -			struct ieee80211_key_seq seq = {}; -			int i; -			iwl_mvm_aes_sc_to_seq(&scs[tid], &seq); -			ieee80211_set_key_rx_seq(key, tid, &seq); -			for (i = 1; i < mvm->trans->num_rx_queues; i++) -				memcpy(ptk_pn->q[i].pn[tid], -				       seq.ccmp.pn, IEEE80211_CCMP_PN_LEN); -		} +	rcu_read_lock(); +	ptk_pn = rcu_dereference(mvmsta->ptk_pn[key->keyidx]); +	if (WARN_ON(!ptk_pn)) {  		rcu_read_unlock(); -	} else { -		for (tid = 0; tid < IWL_NUM_RSC; tid++) { -			struct ieee80211_key_seq seq = {}; +		return; +	} -			iwl_mvm_aes_sc_to_seq(&scs[tid], &seq); -			ieee80211_set_key_rx_seq(key, tid, &seq); -		} +	for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) { +		int i; + +		for (i = 1; i < mvm->trans->num_rx_queues; i++) +			memcpy(ptk_pn->q[i].pn[tid], +			       status->ptk.aes.seq[tid].ccmp.pn, +			       IEEE80211_CCMP_PN_LEN);  	} +	rcu_read_unlock();  } -static void iwl_mvm_set_tkip_rx_seq(struct tkip_sc *scs, -				    struct ieee80211_key_conf *key) +static void iwl_mvm_convert_key_counters(struct iwl_wowlan_status_data *status, +					 union iwl_all_tsc_rsc *sc)  { -	int tid; +	int i; + +	BUILD_BUG_ON(IWL_MAX_TID_COUNT > IWL_MAX_TID_COUNT); +	BUILD_BUG_ON(IWL_MAX_TID_COUNT > IWL_NUM_RSC); -	BUILD_BUG_ON(IWL_NUM_RSC != IEEE80211_NUM_TIDS); +	/* GTK RX counters */ +	for (i = 0; i < IWL_MAX_TID_COUNT; i++) { +		iwl_mvm_tkip_sc_to_seq(&sc->tkip.multicast_rsc[i], +				       &status->gtk.tkip.seq[i]); +		iwl_mvm_aes_sc_to_seq(&sc->aes.multicast_rsc[i], +				      &status->gtk.aes.seq[i]); +	} -	for (tid = 0; tid < IWL_NUM_RSC; tid++) { -		struct ieee80211_key_seq seq = {}; +	/* PTK TX counter */ +	status->ptk.tkip.tx_pn = (u64)le16_to_cpu(sc->tkip.tsc.iv16) | +				 ((u64)le32_to_cpu(sc->tkip.tsc.iv32) << 16); +	status->ptk.aes.tx_pn = le64_to_cpu(sc->aes.tsc.pn); -		iwl_mvm_tkip_sc_to_seq(&scs[tid], &seq); -		ieee80211_set_key_rx_seq(key, tid, &seq); +	/* PTK RX counters */ +	for (i = 0; i < IWL_MAX_TID_COUNT; i++) { +		iwl_mvm_tkip_sc_to_seq(&sc->tkip.unicast_rsc[i], +				       &status->ptk.tkip.seq[i]); +		iwl_mvm_aes_sc_to_seq(&sc->aes.unicast_rsc[i], +				      &status->ptk.aes.seq[i]);  	}  }  static void iwl_mvm_set_key_rx_seq(struct iwl_mvm *mvm,  				   struct ieee80211_key_conf *key, -				   struct iwl_wowlan_status *status) +				   struct iwl_wowlan_status_data *status)  { -	union iwl_all_tsc_rsc *rsc = &status->gtk[0].rsc.all_tsc_rsc; -  	switch (key->cipher) {  	case WLAN_CIPHER_SUITE_CCMP:  	case WLAN_CIPHER_SUITE_GCMP:  	case WLAN_CIPHER_SUITE_GCMP_256: -		iwl_mvm_set_aes_rx_seq(mvm, rsc->aes.multicast_rsc, NULL, key); +		iwl_mvm_set_key_rx_seq_tids(key, status->gtk.aes.seq);  		break;  	case WLAN_CIPHER_SUITE_TKIP: -		iwl_mvm_set_tkip_rx_seq(rsc->tkip.multicast_rsc, key); +		iwl_mvm_set_key_rx_seq_tids(key, status->gtk.tkip.seq);  		break;  	default:  		WARN_ON(1); @@ -1619,7 +1669,7 @@ static void iwl_mvm_set_key_rx_seq(struct iwl_mvm *mvm,  struct iwl_mvm_d3_gtk_iter_data {  	struct iwl_mvm *mvm; -	struct iwl_wowlan_status *status; +	struct iwl_wowlan_status_data *status;  	void *last_gtk;  	u32 cipher;  	bool find_phase, unhandled_cipher; @@ -1633,6 +1683,7 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,  				   void *_data)  {  	struct iwl_mvm_d3_gtk_iter_data *data = _data; +	struct iwl_wowlan_status_data *status = data->status;  	if (data->unhandled_cipher)  		return; @@ -1661,10 +1712,6 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,  	 * note that this assumes no TDLS sessions are active  	 */  	if (sta) { -		struct ieee80211_key_seq seq = {}; -		union iwl_all_tsc_rsc *sc = -			&data->status->gtk[0].rsc.all_tsc_rsc; -  		if (data->find_phase)  			return; @@ -1672,16 +1719,12 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,  		case WLAN_CIPHER_SUITE_CCMP:  		case WLAN_CIPHER_SUITE_GCMP:  		case WLAN_CIPHER_SUITE_GCMP_256: -			iwl_mvm_set_aes_rx_seq(data->mvm, sc->aes.unicast_rsc, -					       sta, key); -			atomic64_set(&key->tx_pn, le64_to_cpu(sc->aes.tsc.pn)); +			atomic64_set(&key->tx_pn, status->ptk.aes.tx_pn); +			iwl_mvm_set_aes_ptk_rx_seq(data->mvm, status, sta, key);  			break;  		case WLAN_CIPHER_SUITE_TKIP: -			iwl_mvm_tkip_sc_to_seq(&sc->tkip.tsc, &seq); -			iwl_mvm_set_tkip_rx_seq(sc->tkip.unicast_rsc, key); -			atomic64_set(&key->tx_pn, -				     (u64)seq.tkip.iv16 | -				     ((u64)seq.tkip.iv32 << 16)); +			atomic64_set(&key->tx_pn, status->ptk.tkip.tx_pn); +			iwl_mvm_set_key_rx_seq_tids(key, status->ptk.tkip.seq);  			break;  		} @@ -1703,7 +1746,7 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,  static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,  					  struct ieee80211_vif *vif, -					  struct iwl_wowlan_status *status) +					  struct iwl_wowlan_status_data *status)  {  	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);  	struct iwl_mvm_d3_gtk_iter_data gtkdata = { @@ -1717,7 +1760,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,  	if (!status || !vif->bss_conf.bssid)  		return false; -	if (le32_to_cpu(status->wakeup_reasons) & disconnection_reasons) +	if (status->wakeup_reasons & disconnection_reasons)  		return false;  	/* find last GTK that we used initially, if any */ @@ -1741,7 +1784,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,  			    iwl_mvm_d3_update_keys, >kdata);  	IWL_DEBUG_WOWLAN(mvm, "num of GTK rekeying %d\n", -			 le32_to_cpu(status->num_of_gtk_rekeys)); +			 status->num_of_gtk_rekeys);  	if (status->num_of_gtk_rekeys) {  		struct ieee80211_key_conf *key;  		struct { @@ -1750,36 +1793,32 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,  		} conf = {  			.conf.cipher = gtkdata.cipher,  			.conf.keyidx = -				iwlmvm_wowlan_gtk_idx(&status->gtk[0]), +				status->gtk.flags & IWL_WOWLAN_GTK_IDX_MASK,  		};  		__be64 replay_ctr;  		IWL_DEBUG_WOWLAN(mvm,  				 "Received from FW GTK cipher %d, key index %d\n",  				 conf.conf.cipher, conf.conf.keyidx); + +		BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP); +		BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_CCMP); +		BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_GCMP_256); +		BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_TKIP); +		BUILD_BUG_ON(sizeof(conf.key) < sizeof(status->gtk.key)); + +		memcpy(conf.conf.key, status->gtk.key, sizeof(status->gtk.key)); +  		switch (gtkdata.cipher) {  		case WLAN_CIPHER_SUITE_CCMP:  		case WLAN_CIPHER_SUITE_GCMP: -			BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP); -			BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_CCMP);  			conf.conf.keylen = WLAN_KEY_LEN_CCMP; -			memcpy(conf.conf.key, status->gtk[0].key, -			       WLAN_KEY_LEN_CCMP);  			break;  		case WLAN_CIPHER_SUITE_GCMP_256: -			BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_GCMP_256);  			conf.conf.keylen = WLAN_KEY_LEN_GCMP_256; -			memcpy(conf.conf.key, status->gtk[0].key, -			       WLAN_KEY_LEN_GCMP_256);  			break;  		case WLAN_CIPHER_SUITE_TKIP: -			BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_TKIP);  			conf.conf.keylen = WLAN_KEY_LEN_TKIP; -			memcpy(conf.conf.key, status->gtk[0].key, 16); -			/* leave TX MIC key zeroed, we don't use it anyway */ -			memcpy(conf.conf.key + -			       NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY, -			       status->gtk[0].tkip_mic_key, 8);  			break;  		} @@ -1788,8 +1827,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,  			return false;  		iwl_mvm_set_key_rx_seq(mvm, key, status); -		replay_ctr = -			cpu_to_be64(le64_to_cpu(status->replay_ctr)); +		replay_ctr = cpu_to_be64(status->replay_ctr);  		ieee80211_gtk_rekey_notify(vif, vif->bss_conf.bssid,  					   (void *)&replay_ctr, GFP_KERNEL); @@ -1800,7 +1838,7 @@ out:  				    WOWLAN_GET_STATUSES, 0) < 10) {  		mvmvif->seqno_valid = true;  		/* +0x10 because the set API expects next-to-use, not last-used */ -		mvmvif->seqno = le16_to_cpu(status->non_qos_seq_ctr) + 0x10; +		mvmvif->seqno = status->non_qos_seq_ctr + 0x10;  	}  	return true; @@ -1808,13 +1846,13 @@ out:  /* Occasionally, templates would be nice. This is one of those times ... */  #define iwl_mvm_parse_wowlan_status_common(_ver)			\ -static struct iwl_wowlan_status *					\ +static struct iwl_wowlan_status_data *					\  iwl_mvm_parse_wowlan_status_common_ ## _ver(struct iwl_mvm *mvm,	\ -					    void *_data, int len)	\ +					    struct iwl_wowlan_status_ ##_ver *data,\ +					    int len)			\  {									\ -	struct iwl_wowlan_status *status;				\ -	struct iwl_wowlan_status_ ##_ver *data = _data;			\ -	int data_size;							\ +	struct iwl_wowlan_status_data *status;				\ +	int data_size, i;						\  									\  	if (len < sizeof(*data)) {					\  		IWL_ERR(mvm, "Invalid WoWLAN status response!\n");	\ @@ -1832,18 +1870,22 @@ iwl_mvm_parse_wowlan_status_common_ ## _ver(struct iwl_mvm *mvm,	\  		return ERR_PTR(-ENOMEM);				\  									\  	/* copy all the common fields */				\ -	status->replay_ctr = data->replay_ctr;				\ -	status->pattern_number = data->pattern_number;			\ -	status->non_qos_seq_ctr = data->non_qos_seq_ctr;		\ -	memcpy(status->qos_seq_ctr, data->qos_seq_ctr,			\ -	       sizeof(status->qos_seq_ctr));				\ -	status->wakeup_reasons = data->wakeup_reasons;			\ -	status->num_of_gtk_rekeys = data->num_of_gtk_rekeys;		\ -	status->received_beacons = data->received_beacons;		\ -	status->wake_packet_length = data->wake_packet_length;		\ -	status->wake_packet_bufsize = data->wake_packet_bufsize;	\ +	status->replay_ctr = le64_to_cpu(data->replay_ctr);		\ +	status->pattern_number = le16_to_cpu(data->pattern_number);	\ +	status->non_qos_seq_ctr = le16_to_cpu(data->non_qos_seq_ctr);	\ +	for (i = 0; i < 8; i++)						\ +		status->qos_seq_ctr[i] =				\ +			le16_to_cpu(data->qos_seq_ctr[i]);		\ +	status->wakeup_reasons = le32_to_cpu(data->wakeup_reasons);	\ +	status->num_of_gtk_rekeys =					\ +		le32_to_cpu(data->num_of_gtk_rekeys);			\ +	status->received_beacons = le32_to_cpu(data->received_beacons);	\ +	status->wake_packet_length =					\ +		le32_to_cpu(data->wake_packet_length);			\ +	status->wake_packet_bufsize =					\ +		le32_to_cpu(data->wake_packet_bufsize);			\  	memcpy(status->wake_packet, data->wake_packet,			\ -	       le32_to_cpu(status->wake_packet_bufsize));		\ +	       status->wake_packet_bufsize);				\  									\  	return status;							\  } @@ -1852,10 +1894,49 @@ iwl_mvm_parse_wowlan_status_common(v6)  iwl_mvm_parse_wowlan_status_common(v7)  iwl_mvm_parse_wowlan_status_common(v9) -static struct iwl_wowlan_status * +static void iwl_mvm_convert_gtk(struct iwl_wowlan_status_data *status, +				struct iwl_wowlan_gtk_status *data) +{ +	BUILD_BUG_ON(sizeof(status->gtk.key) < sizeof(data->key)); +	BUILD_BUG_ON(NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY + +		     sizeof(data->tkip_mic_key) > +		     sizeof(status->gtk.key)); + +	status->gtk.len = data->key_len; +	status->gtk.flags = data->key_flags; + +	memcpy(status->gtk.key, data->key, sizeof(data->key)); + +	/* if it's as long as the TKIP encryption key, copy MIC key */ +	if (status->gtk.len == NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY) +		memcpy(status->gtk.key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY, +		       data->tkip_mic_key, sizeof(data->tkip_mic_key)); +} + +static void iwl_mvm_convert_igtk(struct iwl_wowlan_status_data *status, +				 struct iwl_wowlan_igtk_status *data) +{ +	const u8 *ipn = data->ipn; + +	BUILD_BUG_ON(sizeof(status->igtk.key) < sizeof(data->key)); + +	status->igtk.len = data->key_len; +	status->igtk.flags = data->key_flags; + +	memcpy(status->igtk.key, data->key, sizeof(data->key)); + +	status->igtk.ipn = ((u64)ipn[5] <<  0) | +			   ((u64)ipn[4] <<  8) | +			   ((u64)ipn[3] << 16) | +			   ((u64)ipn[2] << 24) | +			   ((u64)ipn[1] << 32) | +			   ((u64)ipn[0] << 40); +} + +static struct iwl_wowlan_status_data *  iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)  { -	struct iwl_wowlan_status *status; +	struct iwl_wowlan_status_data *status;  	struct iwl_wowlan_get_status_cmd get_status_cmd = {  		.sta_id = cpu_to_le32(sta_id),  	}; @@ -1895,59 +1976,57 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)  			IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL)) {  		struct iwl_wowlan_status_v6 *v6 = (void *)cmd.resp_pkt->data; -		status = iwl_mvm_parse_wowlan_status_common_v6(mvm, -							       cmd.resp_pkt->data, -							       len); +		status = iwl_mvm_parse_wowlan_status_common_v6(mvm, v6, len);  		if (IS_ERR(status))  			goto out_free_resp;  		BUILD_BUG_ON(sizeof(v6->gtk.decrypt_key) > -			     sizeof(status->gtk[0].key)); -		BUILD_BUG_ON(sizeof(v6->gtk.tkip_mic_key) > -			     sizeof(status->gtk[0].tkip_mic_key)); +			     sizeof(status->gtk.key)); +		BUILD_BUG_ON(NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY + +			     sizeof(v6->gtk.tkip_mic_key) > +			     sizeof(status->gtk.key));  		/* copy GTK info to the right place */ -		memcpy(status->gtk[0].key, v6->gtk.decrypt_key, +		memcpy(status->gtk.key, v6->gtk.decrypt_key,  		       sizeof(v6->gtk.decrypt_key)); -		memcpy(status->gtk[0].tkip_mic_key, v6->gtk.tkip_mic_key, +		memcpy(status->gtk.key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY, +		       v6->gtk.tkip_mic_key,  		       sizeof(v6->gtk.tkip_mic_key)); -		memcpy(&status->gtk[0].rsc, &v6->gtk.rsc, -		       sizeof(status->gtk[0].rsc)); + +		iwl_mvm_convert_key_counters(status, &v6->gtk.rsc.all_tsc_rsc);  		/* hardcode the key length to 16 since v6 only supports 16 */ -		status->gtk[0].key_len = 16; +		status->gtk.len = 16;  		/*  		 * The key index only uses 2 bits (values 0 to 3) and  		 * we always set bit 7 which means this is the  		 * currently used key.  		 */ -		status->gtk[0].key_flags = v6->gtk.key_index | BIT(7); +		status->gtk.flags = v6->gtk.key_index | BIT(7);  	} else if (notif_ver == 7) {  		struct iwl_wowlan_status_v7 *v7 = (void *)cmd.resp_pkt->data; -		status = iwl_mvm_parse_wowlan_status_common_v7(mvm, -							       cmd.resp_pkt->data, -							       len); +		status = iwl_mvm_parse_wowlan_status_common_v7(mvm, v7, len);  		if (IS_ERR(status))  			goto out_free_resp; -		status->gtk[0] = v7->gtk[0]; -		status->igtk[0] = v7->igtk[0]; +		iwl_mvm_convert_key_counters(status, &v7->gtk[0].rsc.all_tsc_rsc); +		iwl_mvm_convert_gtk(status, &v7->gtk[0]); +		iwl_mvm_convert_igtk(status, &v7->igtk[0]);  	} else if (notif_ver == 9 || notif_ver == 10 || notif_ver == 11) {  		struct iwl_wowlan_status_v9 *v9 = (void *)cmd.resp_pkt->data;  		/* these three command versions have same layout and size, the  		 * difference is only in a few not used (reserved) fields.  		 */ -		status = iwl_mvm_parse_wowlan_status_common_v9(mvm, -							       cmd.resp_pkt->data, -							       len); +		status = iwl_mvm_parse_wowlan_status_common_v9(mvm, v9, len);  		if (IS_ERR(status))  			goto out_free_resp; -		status->gtk[0] = v9->gtk[0]; -		status->igtk[0] = v9->igtk[0]; +		iwl_mvm_convert_key_counters(status, &v9->gtk[0].rsc.all_tsc_rsc); +		iwl_mvm_convert_gtk(status, &v9->gtk[0]); +		iwl_mvm_convert_igtk(status, &v9->igtk[0]);  		status->tid_tear_down = v9->tid_tear_down;  	} else { @@ -1962,7 +2041,7 @@ out_free_resp:  	return status;  } -static struct iwl_wowlan_status * +static struct iwl_wowlan_status_data *  iwl_mvm_get_wakeup_status(struct iwl_mvm *mvm, u8 sta_id)  {  	u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP, @@ -1987,29 +2066,17 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,  					 struct ieee80211_vif *vif)  {  	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); -	struct iwl_wowlan_status_data status; -	struct iwl_wowlan_status *fw_status; +	struct iwl_wowlan_status_data *status;  	int i;  	bool keep;  	struct iwl_mvm_sta *mvm_ap_sta; -	fw_status = iwl_mvm_get_wakeup_status(mvm, mvmvif->ap_sta_id); -	if (IS_ERR_OR_NULL(fw_status)) +	status = iwl_mvm_get_wakeup_status(mvm, mvmvif->ap_sta_id); +	if (IS_ERR(status))  		goto out_unlock;  	IWL_DEBUG_WOWLAN(mvm, "wakeup reason 0x%x\n", -			 le32_to_cpu(fw_status->wakeup_reasons)); - -	status.pattern_number = le16_to_cpu(fw_status->pattern_number); -	for (i = 0; i < 8; i++) -		status.qos_seq_ctr[i] = -			le16_to_cpu(fw_status->qos_seq_ctr[i]); -	status.wakeup_reasons = le32_to_cpu(fw_status->wakeup_reasons); -	status.wake_packet_length = -		le32_to_cpu(fw_status->wake_packet_length); -	status.wake_packet_bufsize = -		le32_to_cpu(fw_status->wake_packet_bufsize); -	status.wake_packet = fw_status->wake_packet; +			 status->wakeup_reasons);  	/* still at hard-coded place 0 for D3 image */  	mvm_ap_sta = iwl_mvm_sta_from_staid_protected(mvm, 0); @@ -2017,7 +2084,7 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,  		goto out_free;  	for (i = 0; i < IWL_MAX_TID_COUNT; i++) { -		u16 seq = status.qos_seq_ctr[i]; +		u16 seq = status->qos_seq_ctr[i];  		/* firmware stores last-used value, we store next value */  		seq += 0x10;  		mvm_ap_sta->tid_data[i].seq_number = seq; @@ -2033,15 +2100,15 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,  	/* now we have all the data we need, unlock to avoid mac80211 issues */  	mutex_unlock(&mvm->mutex); -	iwl_mvm_report_wakeup_reasons(mvm, vif, &status); +	iwl_mvm_report_wakeup_reasons(mvm, vif, status); -	keep = iwl_mvm_setup_connection_keep(mvm, vif, fw_status); +	keep = iwl_mvm_setup_connection_keep(mvm, vif, status); -	kfree(fw_status); +	kfree(status);  	return keep;  out_free: -	kfree(fw_status); +	kfree(status);  out_unlock:  	mutex_unlock(&mvm->mutex);  	return false; @@ -2165,16 +2232,16 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,  		.pattern_idx = -1,  	};  	struct cfg80211_wowlan_wakeup *wakeup_report = &wakeup; +	struct iwl_wowlan_status_data *status;  	struct iwl_mvm_nd_query_results query; -	struct iwl_wowlan_status *fw_status;  	unsigned long matched_profiles;  	u32 reasons = 0;  	int i, n_matches, ret; -	fw_status = iwl_mvm_get_wakeup_status(mvm, IWL_MVM_INVALID_STA); -	if (!IS_ERR_OR_NULL(fw_status)) { -		reasons = le32_to_cpu(fw_status->wakeup_reasons); -		kfree(fw_status); +	status = iwl_mvm_get_wakeup_status(mvm, IWL_MVM_INVALID_STA); +	if (!IS_ERR(status)) { +		reasons = status->wakeup_reasons; +		kfree(status);  	}  	if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED) @@ -2336,7 +2403,6 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)  		iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert,  					false, 0);  		ret = 1; -		mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;  		goto err;  	} @@ -2385,6 +2451,7 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)  		}  	} +	/* after the successful handshake, we're out of D3 */  	mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;  	/* @@ -2455,6 +2522,9 @@ out:  	 */  	set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status); +	/* regardless of what happened, we're now out of D3 */ +	mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED; +  	return 1;  } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 5dc39fbb74d6..ff66001d507e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -395,10 +395,9 @@ static ssize_t iwl_dbgfs_rs_data_read(struct file *file, char __user *user_buf,  			  "A-MPDU size limit %d\n",  			  lq_sta->pers.dbg_agg_frame_count_lim);  	desc += scnprintf(buff + desc, bufsz - desc, -			  "valid_tx_ant %s%s%s\n", +			  "valid_tx_ant %s%s\n",  		(iwl_mvm_get_valid_tx_ant(mvm) & ANT_A) ? "ANT_A," : "", -		(iwl_mvm_get_valid_tx_ant(mvm) & ANT_B) ? "ANT_B," : "", -		(iwl_mvm_get_valid_tx_ant(mvm) & ANT_C) ? "ANT_C" : ""); +		(iwl_mvm_get_valid_tx_ant(mvm) & ANT_B) ? "ANT_B," : "");  	desc += scnprintf(buff + desc, bufsz - desc,  			  "last tx rate=0x%X ",  			  lq_sta->last_rate_n_flags); @@ -986,8 +985,8 @@ static ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm,  			continue;  		pos += scnprintf(pos, endpos - pos, "Rate[%d]: ",  				 (int)(ARRAY_SIZE(stats->last_rates) - i)); -		pos += rs_pretty_print_rate(pos, endpos - pos, -					    stats->last_rates[idx]); +		pos += rs_pretty_print_rate_v1(pos, endpos - pos, +					       stats->last_rates[idx]);  		if (pos < endpos - 1)  			*pos++ = '\n';  	} @@ -1060,8 +1059,6 @@ iwl_dbgfs_scan_ant_rxchain_read(struct file *file,  		pos += scnprintf(buf + pos, bufsz - pos, "A");  	if (mvm->scan_rx_ant & ANT_B)  		pos += scnprintf(buf + pos, bufsz - pos, "B"); -	if (mvm->scan_rx_ant & ANT_C) -		pos += scnprintf(buf + pos, bufsz - pos, "C");  	pos += scnprintf(buf + pos, bufsz - pos, " (%hhx)\n", mvm->scan_rx_ant);  	return simple_read_from_buffer(user_buf, count, ppos, buf, pos); @@ -1196,7 +1193,6 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)  	struct ieee80211_tx_info *info;  	struct iwl_mac_beacon_cmd beacon_cmd = {};  	u8 rate; -	u16 flags;  	int i;  	len /= 2; @@ -1243,12 +1239,9 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)  	mvmvif = iwl_mvm_vif_from_mac80211(vif);  	info = IEEE80211_SKB_CB(beacon);  	rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif); -	flags = iwl_mvm_mac80211_idx_to_hwrate(rate); -	if (rate == IWL_FIRST_CCK_RATE) -		flags |= IWL_MAC_BEACON_CCK; - -	beacon_cmd.flags = cpu_to_le16(flags); +	beacon_cmd.flags = +		cpu_to_le16(iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw, rate));  	beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);  	beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c index 03e5bf5cb909..949fb790f8fb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c @@ -324,6 +324,7 @@ iwl_mvm_ftm_target_chandef_v2(struct iwl_mvm *mvm,  			      u8 *ctrl_ch_position)  {  	u32 freq = peer->chandef.chan->center_freq; +	u8 cmd_ver;  	*channel = ieee80211_frequency_to_channel(freq); @@ -344,6 +345,17 @@ iwl_mvm_ftm_target_chandef_v2(struct iwl_mvm *mvm,  		*format_bw = IWL_LOCATION_FRAME_FORMAT_VHT;  		*format_bw |= IWL_LOCATION_BW_80MHZ << LOCATION_BW_POS;  		break; +	case NL80211_CHAN_WIDTH_160: +		cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, LOCATION_GROUP, +						TOF_RANGE_REQ_CMD, +						IWL_FW_CMD_VER_UNKNOWN); + +		if (cmd_ver >= 13) { +			*format_bw = IWL_LOCATION_FRAME_FORMAT_HE; +			*format_bw |= IWL_LOCATION_BW_160MHZ << LOCATION_BW_POS; +			break; +		} +		fallthrough;  	default:  		IWL_ERR(mvm, "Unsupported BW in FTM request (%d)\n",  			peer->chandef.width); @@ -1142,6 +1154,7 @@ static u8 iwl_mvm_ftm_get_range_resp_ver(struct iwl_mvm *mvm)  static bool iwl_mvm_ftm_resp_size_validation(u8 ver, unsigned int pkt_len)  {  	switch (ver) { +	case 9:  	case 8:  		return pkt_len == sizeof(struct iwl_tof_range_rsp_ntfy_v8);  	case 7: @@ -1205,7 +1218,7 @@ void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)  		int peer_idx;  		if (new_api) { -			if (notif_ver == 8) { +			if (notif_ver >= 8) {  				fw_ap = &fw_resp_v8->ap[i];  				iwl_mvm_ftm_pasn_update_pn(mvm, fw_ap);  			} else if (notif_ver == 7) { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c index eba5433c2626..bda6da7d988e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c @@ -46,8 +46,8 @@ static int iwl_mvm_ftm_responder_set_bw_v1(struct cfg80211_chan_def *chandef,  }  static int iwl_mvm_ftm_responder_set_bw_v2(struct cfg80211_chan_def *chandef, -					   u8 *format_bw, -					   u8 *ctrl_ch_position) +					   u8 *format_bw, u8 *ctrl_ch_position, +					   u8 cmd_ver)  {  	switch (chandef->width) {  	case NL80211_CHAN_WIDTH_20_NOHT: @@ -68,6 +68,14 @@ static int iwl_mvm_ftm_responder_set_bw_v2(struct cfg80211_chan_def *chandef,  		*format_bw |= IWL_LOCATION_BW_80MHZ << LOCATION_BW_POS;  		*ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef);  		break; +	case NL80211_CHAN_WIDTH_160: +		if (cmd_ver >= 9) { +			*format_bw = IWL_LOCATION_FRAME_FORMAT_HE; +			*format_bw |= IWL_LOCATION_BW_160MHZ << LOCATION_BW_POS; +			*ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef); +			break; +		} +		fallthrough;  	default:  		return -ENOTSUPP;  	} @@ -140,7 +148,8 @@ iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,  	if (cmd_ver >= 7)  		err = iwl_mvm_ftm_responder_set_bw_v2(chandef, &cmd.format_bw, -						      &cmd.ctrl_ch_position); +						      &cmd.ctrl_ch_position, +						      cmd_ver);  	else  		err = iwl_mvm_ftm_responder_set_bw_v1(chandef, &cmd.format_bw,  						      &cmd.ctrl_ch_position); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 74404c96063b..863fec150e53 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -295,6 +295,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,  	if (ret) {  		struct iwl_trans *trans = mvm->trans; +		/* SecBoot info */  		if (trans->trans_cfg->device_family >=  					IWL_DEVICE_FAMILY_22000) {  			IWL_ERR(mvm, @@ -302,6 +303,17 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,  				iwl_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS),  				iwl_read_umac_prph(trans,  						   UMAG_SB_CPU_2_STATUS)); +		} else if (trans->trans_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)); +		} + +		/* LMAC/UMAC PC info */ +		if (trans->trans_cfg->device_family >= +					IWL_DEVICE_FAMILY_9000) {  			IWL_ERR(mvm, "UMAC PC: 0x%x\n",  				iwl_read_umac_prph(trans,  						   UREG_UMAC_CURRENT_PC)); @@ -312,12 +324,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,  				IWL_ERR(mvm, "LMAC2 PC: 0x%x\n",  					iwl_read_umac_prph(trans,  						UREG_LMAC2_CURRENT_PC)); -		} else if (trans->trans_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));  		}  		if (ret == -ETIMEDOUT) @@ -763,14 +769,18 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)  	int ret;  	struct iwl_host_cmd cmd;  	u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, PHY_OPS_GROUP, -					   GEO_TX_POWER_LIMIT, +					   PER_CHAIN_LIMIT_OFFSET_CMD,  					   IWL_FW_CMD_VER_UNKNOWN);  	/* the ops field is at the same spot for all versions, so set in v1 */  	geo_tx_cmd.v1.ops =  		cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE); -	if (cmd_ver == 3) +	if (cmd_ver == 5) +		len = sizeof(geo_tx_cmd.v5); +	else if (cmd_ver == 4) +		len = sizeof(geo_tx_cmd.v4); +	else if (cmd_ver == 3)  		len = sizeof(geo_tx_cmd.v3);  	else if (fw_has_api(&mvm->fwrt.fw->ucode_capa,  			    IWL_UCODE_TLV_API_SAR_TABLE_VER)) @@ -782,7 +792,7 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)  		return -EOPNOTSUPP;  	cmd = (struct iwl_host_cmd){ -		.id =  WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT), +		.id =  WIDE_ID(PHY_OPS_GROUP, PER_CHAIN_LIMIT_OFFSET_CMD),  		.len = { len, },  		.flags = CMD_WANT_SKB,  		.data = { &geo_tx_cmd }, @@ -797,7 +807,7 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)  	resp = (void *)cmd.resp_pkt->data;  	ret = le32_to_cpu(resp->profile_idx); -	if (WARN_ON(ret > ACPI_NUM_GEO_PROFILES)) +	if (WARN_ON(ret > ACPI_NUM_GEO_PROFILES_REV3))  		ret = -EIO;  	iwl_free_resp(&cmd); @@ -809,36 +819,58 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)  	union iwl_geo_tx_power_profiles_cmd cmd;  	u16 len;  	u32 n_bands; +	u32 n_profiles;  	int ret;  	u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, PHY_OPS_GROUP, -					   GEO_TX_POWER_LIMIT, +					   PER_CHAIN_LIMIT_OFFSET_CMD,  					   IWL_FW_CMD_VER_UNKNOWN);  	BUILD_BUG_ON(offsetof(struct iwl_geo_tx_power_profiles_cmd_v1, ops) !=  		     offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, ops) ||  		     offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, ops) != -		     offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, ops)); +		     offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, ops) || +		     offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, ops) != +		     offsetof(struct iwl_geo_tx_power_profiles_cmd_v4, ops) || +		     offsetof(struct iwl_geo_tx_power_profiles_cmd_v4, ops) != +		     offsetof(struct iwl_geo_tx_power_profiles_cmd_v5, ops)); +  	/* the ops field is at the same spot for all versions, so set in v1 */  	cmd.v1.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES); -	if (cmd_ver == 3) { +	if (cmd_ver == 5) { +		len = sizeof(cmd.v5); +		n_bands = ARRAY_SIZE(cmd.v5.table[0]); +		n_profiles = ACPI_NUM_GEO_PROFILES_REV3; +	} else if (cmd_ver == 4) { +		len = sizeof(cmd.v4); +		n_bands = ARRAY_SIZE(cmd.v4.table[0]); +		n_profiles = ACPI_NUM_GEO_PROFILES_REV3; +	} else if (cmd_ver == 3) {  		len = sizeof(cmd.v3);  		n_bands = ARRAY_SIZE(cmd.v3.table[0]); +		n_profiles = ACPI_NUM_GEO_PROFILES;  	} else if (fw_has_api(&mvm->fwrt.fw->ucode_capa,  			      IWL_UCODE_TLV_API_SAR_TABLE_VER)) {  		len = sizeof(cmd.v2);  		n_bands = ARRAY_SIZE(cmd.v2.table[0]); +		n_profiles = ACPI_NUM_GEO_PROFILES;  	} else {  		len = sizeof(cmd.v1);  		n_bands = ARRAY_SIZE(cmd.v1.table[0]); +		n_profiles = ACPI_NUM_GEO_PROFILES;  	}  	BUILD_BUG_ON(offsetof(struct iwl_geo_tx_power_profiles_cmd_v1, table) !=  		     offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, table) ||  		     offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, table) != -		     offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, table)); +		     offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, table) || +		     offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, table) != +		     offsetof(struct iwl_geo_tx_power_profiles_cmd_v4, table) || +		     offsetof(struct iwl_geo_tx_power_profiles_cmd_v4, table) != +		     offsetof(struct iwl_geo_tx_power_profiles_cmd_v5, table));  	/* the table is at the same position for all versions, so set use v1 */ -	ret = iwl_sar_geo_init(&mvm->fwrt, &cmd.v1.table[0][0], n_bands); +	ret = iwl_sar_geo_init(&mvm->fwrt, &cmd.v1.table[0][0], +			       n_bands, n_profiles);  	/*  	 * It is a valid scenario to not support SAR, or miss wgds table, @@ -851,14 +883,19 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)  	 * Set the revision on versions that contain it.  	 * This must be done after calling iwl_sar_geo_init().  	 */ -	if (cmd_ver == 3) +	if (cmd_ver == 5) +		cmd.v5.table_revision = cpu_to_le32(mvm->fwrt.geo_rev); +	else if (cmd_ver == 4) +		cmd.v4.table_revision = cpu_to_le32(mvm->fwrt.geo_rev); +	else if (cmd_ver == 3)  		cmd.v3.table_revision = cpu_to_le32(mvm->fwrt.geo_rev);  	else if (fw_has_api(&mvm->fwrt.fw->ucode_capa,  			    IWL_UCODE_TLV_API_SAR_TABLE_VER))  		cmd.v2.table_revision = cpu_to_le32(mvm->fwrt.geo_rev);  	return iwl_mvm_send_cmd_pdu(mvm, -				    WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT), +				    WIDE_ID(PHY_OPS_GROUP, +					    PER_CHAIN_LIMIT_OFFSET_CMD),  				    0, len, &cmd);  } @@ -1108,7 +1145,7 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm)  static u8 iwl_mvm_eval_dsm_rfi(struct iwl_mvm *mvm)  {  	u8 value; -	int ret = iwl_acpi_get_dsm_u8((&mvm->fwrt)->dev, 0, DSM_RFI_FUNC_ENABLE, +	int ret = iwl_acpi_get_dsm_u8(mvm->fwrt.dev, 0, DSM_RFI_FUNC_ENABLE,  				      &iwl_rfi_guid, &value);  	if (ret < 0) { @@ -1133,30 +1170,45 @@ static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)  {  	int ret;  	u32 value; -	struct iwl_lari_config_change_cmd_v4 cmd = {}; +	struct iwl_lari_config_change_cmd_v5 cmd = {};  	cmd.config_bitmap = iwl_acpi_get_lari_config_bitmap(&mvm->fwrt); -	ret = iwl_acpi_get_dsm_u32((&mvm->fwrt)->dev, 0, DSM_FUNC_11AX_ENABLEMENT, +	ret = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0, DSM_FUNC_11AX_ENABLEMENT,  				   &iwl_guid, &value);  	if (!ret)  		cmd.oem_11ax_allow_bitmap = cpu_to_le32(value); -	/* apply more config masks here */ -	ret = iwl_acpi_get_dsm_u32((&mvm->fwrt)->dev, 0, +	ret = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0,  				   DSM_FUNC_ENABLE_UNII4_CHAN,  				   &iwl_guid, &value);  	if (!ret)  		cmd.oem_unii4_allow_bitmap = cpu_to_le32(value); +	ret = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0, +				   DSM_FUNC_ACTIVATE_CHANNEL, +				   &iwl_guid, &value); +	if (!ret) +		cmd.chan_state_active_bitmap = cpu_to_le32(value); + +	ret = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0, +				   DSM_FUNC_ENABLE_6E, +				   &iwl_guid, &value); +	if (!ret) +		cmd.oem_uhb_allow_bitmap = cpu_to_le32(value); +  	if (cmd.config_bitmap || +	    cmd.oem_uhb_allow_bitmap ||  	    cmd.oem_11ax_allow_bitmap || -	    cmd.oem_unii4_allow_bitmap) { +	    cmd.oem_unii4_allow_bitmap || +	    cmd.chan_state_active_bitmap) {  		size_t cmd_size;  		u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,  						   REGULATORY_AND_NVM_GROUP,  						   LARI_CONFIG_CHANGE, 1); -		if (cmd_ver == 4) +		if (cmd_ver == 5) +			cmd_size = sizeof(struct iwl_lari_config_change_cmd_v5); +		else if (cmd_ver == 4)  			cmd_size = sizeof(struct iwl_lari_config_change_cmd_v4);  		else if (cmd_ver == 3)  			cmd_size = sizeof(struct iwl_lari_config_change_cmd_v3); @@ -1170,9 +1222,13 @@ static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)  				le32_to_cpu(cmd.config_bitmap),  				le32_to_cpu(cmd.oem_11ax_allow_bitmap));  		IWL_DEBUG_RADIO(mvm, -				"sending LARI_CONFIG_CHANGE, oem_unii4_allow_bitmap=0x%x, cmd_ver=%d\n", +				"sending LARI_CONFIG_CHANGE, oem_unii4_allow_bitmap=0x%x, chan_state_active_bitmap=0x%x, cmd_ver=%d\n",  				le32_to_cpu(cmd.oem_unii4_allow_bitmap), +				le32_to_cpu(cmd.chan_state_active_bitmap),  				cmd_ver); +		IWL_DEBUG_RADIO(mvm, +				"sending LARI_CONFIG_CHANGE, oem_uhb_allow_bitmap=0x%x\n", +				le32_to_cpu(cmd.oem_uhb_allow_bitmap));  		ret = iwl_mvm_send_cmd_pdu(mvm,  					   WIDE_ID(REGULATORY_AND_NVM_GROUP,  						   LARI_CONFIG_CHANGE), diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index fd352b2624a6..fd7d4abfb454 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -604,6 +604,12 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,  		ctxt_sta->is_assoc = cpu_to_le32(1); +		if (!mvmvif->authorized && +		    fw_has_capa(&mvm->fw->ucode_capa, +				IWL_UCODE_TLV_CAPA_COEX_HIGH_PRIO)) +			ctxt_sta->data_policy |= +				cpu_to_le32(COEX_HIGH_PRIORITY_ENABLE); +  		/*  		 * allow multicast data frames only as long as the station is  		 * authorized, i.e., GTK keys are already installed (if needed) @@ -812,6 +818,21 @@ u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info,  	return rate;  } +u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw, u8 rate_idx) +{ +	u16 flags = iwl_mvm_mac80211_idx_to_hwrate(fw, rate_idx); +	bool is_new_rate = iwl_fw_lookup_cmd_ver(fw, +						 LONG_GROUP, +						 BEACON_TEMPLATE_CMD, +						 0) > 10; + +	if (rate_idx <= IWL_FIRST_CCK_RATE) +		flags |= is_new_rate ? IWL_MAC_BEACON_CCK +			  : IWL_MAC_BEACON_CCK_V1; + +	return flags; +} +  static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,  				    struct ieee80211_vif *vif,  				    struct sk_buff *beacon, @@ -844,9 +865,10 @@ static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,  	rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif); -	tx->rate_n_flags |= cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(rate)); +	tx->rate_n_flags |= +		cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(mvm->fw, rate));  	if (rate == IWL_FIRST_CCK_RATE) -		tx->rate_n_flags |= cpu_to_le32(RATE_MCS_CCK_MSK); +		tx->rate_n_flags |= cpu_to_le32(RATE_MCS_CCK_MSK_V1);  } @@ -929,11 +951,7 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,  	u16 flags;  	struct ieee80211_chanctx_conf *ctx;  	int channel; - -	flags = iwl_mvm_mac80211_idx_to_hwrate(rate); - -	if (rate == IWL_FIRST_CCK_RATE) -		flags |= IWL_MAC_BEACON_CCK; +	flags = iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw, rate);  	/* Enable FILS on PSC channels only */  	rcu_read_lock(); @@ -942,7 +960,11 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,  	WARN_ON(channel == 0);  	if (cfg80211_channel_is_psc(ctx->def.chan) &&  	    !IWL_MVM_DISABLE_AP_FILS) { -		flags |= IWL_MAC_BEACON_FILS; +		flags |= iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP, +					       BEACON_TEMPLATE_CMD, +					       0) > 10 ? +			IWL_MAC_BEACON_FILS : +			IWL_MAC_BEACON_FILS_V1;  		beacon_cmd.short_ssid =  			cpu_to_le32(~crc32_le(~0, vif->bss_conf.ssid,  					      vif->bss_conf.ssid_len)); @@ -1535,11 +1557,11 @@ void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm,  		ieee80211_beacon_set_cntdwn(vif, notif->csa_counter);  } -void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm, -				      struct iwl_rx_cmd_buffer *rxb) +void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm, +					struct iwl_rx_cmd_buffer *rxb)  {  	struct iwl_rx_packet *pkt = rxb_addr(rxb); -	struct iwl_channel_switch_noa_notif *notif = (void *)pkt->data; +	struct iwl_channel_switch_start_notif *notif = (void *)pkt->data;  	struct ieee80211_vif *csa_vif, *vif;  	struct iwl_mvm_vif *mvmvif;  	u32 id_n_color, csa_id, mac_id; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 3a4585222d6d..9fb9c7dad314 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -145,7 +145,8 @@ static const struct cfg80211_pmsr_capabilities iwl_mvm_pmsr_capa = {  		.bandwidths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |  			      BIT(NL80211_CHAN_WIDTH_20) |  			      BIT(NL80211_CHAN_WIDTH_40) | -			      BIT(NL80211_CHAN_WIDTH_80), +			      BIT(NL80211_CHAN_WIDTH_80) | +			      BIT(NL80211_CHAN_WIDTH_160),  		.preambles = BIT(NL80211_PREAMBLE_LEGACY) |  			     BIT(NL80211_PREAMBLE_HT) |  			     BIT(NL80211_PREAMBLE_VHT) | @@ -2022,7 +2023,8 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,  	}  	sband = mvm->hw->wiphy->bands[chanctx_conf->def.chan->band]; -	own_he_cap = ieee80211_get_he_iftype_cap(sband, vif->type); +	own_he_cap = ieee80211_get_he_iftype_cap(sband, +						 ieee80211_vif_type_p2p(vif));  	sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_ctxt_cmd.sta_id]);  	if (IS_ERR_OR_NULL(sta)) { @@ -2234,6 +2236,34 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,  		IWL_ERR(mvm, "Failed to config FW to work HE!\n");  } +static void iwl_mvm_protect_assoc(struct iwl_mvm *mvm, +				  struct ieee80211_vif *vif, +				  u32 duration_override) +{ +	u32 duration = IWL_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS; +	u32 min_duration = IWL_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS; + +	if (duration_override > duration) +		duration = duration_override; + +	/* Try really hard to protect the session and hear a beacon +	 * The new session protection command allows us to protect the +	 * session for a much longer time since the firmware will internally +	 * create two events: a 300TU one with a very high priority that +	 * won't be fragmented which should be enough for 99% of the cases, +	 * and another one (which we configure here to be 900TU long) which +	 * will have a slightly lower priority, but more importantly, can be +	 * fragmented so that it'll allow other activities to run. +	 */ +	if (fw_has_capa(&mvm->fw->ucode_capa, +			IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD)) +		iwl_mvm_schedule_session_protection(mvm, vif, 900, +						    min_duration, false); +	else +		iwl_mvm_protect_session(mvm, vif, duration, +					min_duration, 500, false); +} +  static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,  					     struct ieee80211_vif *vif,  					     struct ieee80211_bss_conf *bss_conf, @@ -2317,6 +2347,20 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,  				u32 dur = (11 * vif->bss_conf.beacon_int) / 10;  				iwl_mvm_protect_session(mvm, vif, dur, dur,  							5 * dur, false); +			} else if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, +					     &mvm->status) && +				   !vif->bss_conf.dtim_period) { +				/* +				 * If we're not restarting and still haven't +				 * heard a beacon (dtim period unknown) then +				 * make sure we still have enough minimum time +				 * remaining in the time event, since the auth +				 * might actually have taken quite a while +				 * (especially for SAE) and so the remaining +				 * time could be small without us having heard +				 * a beacon yet. +				 */ +				iwl_mvm_protect_assoc(mvm, vif, 0);  			}  			iwl_mvm_sf_update(mvm, vif, false); @@ -3192,38 +3236,52 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,  		if (iwl_mvm_phy_ctx_count(mvm) > 1)  			iwl_mvm_teardown_tdls_peers(mvm); -		if (sta->tdls) +		if (sta->tdls) {  			iwl_mvm_tdls_check_trigger(mvm, vif, sta->addr,  						   NL80211_TDLS_ENABLE_LINK); +		} else { +			/* enable beacon filtering */ +			WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0)); -		/* enable beacon filtering */ -		WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0)); +			mvmvif->authorized = 1; -		/* -		 * Now that the station is authorized, i.e., keys were already -		 * installed, need to indicate to the FW that -		 * multicast data frames can be forwarded to the driver -		 */ -		iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); +			/* +			 * Now that the station is authorized, i.e., keys were already +			 * installed, need to indicate to the FW that +			 * multicast data frames can be forwarded to the driver +			 */ +			iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); +		}  		iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,  				     true);  	} else if (old_state == IEEE80211_STA_AUTHORIZED &&  		   new_state == IEEE80211_STA_ASSOC) { -		/* Multicast data frames are no longer allowed */ -		iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); +		if (!sta->tdls) { +			/* Multicast data frames are no longer allowed */ +			iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); + +			/* +			 * Set this after the above iwl_mvm_mac_ctxt_changed() +			 * to avoid sending high prio again for a little time. +			 */ +			mvmvif->authorized = 0; -		/* disable beacon filtering */ -		ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0); -		WARN_ON(ret && -			!test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, -				  &mvm->status)); +			/* disable beacon filtering */ +			ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0); +			WARN_ON(ret && +				!test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, +					  &mvm->status)); +		}  		ret = 0;  	} else if (old_state == IEEE80211_STA_ASSOC &&  		   new_state == IEEE80211_STA_AUTH) {  		if (vif->type == NL80211_IFTYPE_AP) {  			mvmvif->ap_assoc_sta_count--;  			iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); +		} else if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { +			/* remove session protection if still running */ +			iwl_mvm_stop_session_protection(mvm, vif);  		}  		ret = 0;  	} else if (old_state == IEEE80211_STA_AUTH && @@ -3316,29 +3374,24 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,  				       struct ieee80211_prep_tx_info *info)  {  	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); -	u32 duration = IWL_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS; -	u32 min_duration = IWL_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS; -	if (info->duration > duration) -		duration = info->duration; +	mutex_lock(&mvm->mutex); +	iwl_mvm_protect_assoc(mvm, vif, info->duration); +	mutex_unlock(&mvm->mutex); +} + +static void iwl_mvm_mac_mgd_complete_tx(struct ieee80211_hw *hw, +					struct ieee80211_vif *vif, +					struct ieee80211_prep_tx_info *info) +{ +	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + +	/* for successful cases (auth/assoc), don't cancel session protection */ +	if (info->success) +		return;  	mutex_lock(&mvm->mutex); -	/* Try really hard to protect the session and hear a beacon -	 * The new session protection command allows us to protect the -	 * session for a much longer time since the firmware will internally -	 * create two events: a 300TU one with a very high priority that -	 * won't be fragmented which should be enough for 99% of the cases, -	 * and another one (which we configure here to be 900TU long) which -	 * will have a slightly lower priority, but more importantly, can be -	 * fragmented so that it'll allow other activities to run. -	 */ -	if (fw_has_capa(&mvm->fw->ucode_capa, -			IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD)) -		iwl_mvm_schedule_session_protection(mvm, vif, 900, -						    min_duration, false); -	else -		iwl_mvm_protect_session(mvm, vif, duration, -					min_duration, 500, false); +	iwl_mvm_stop_session_protection(mvm, vif);  	mutex_unlock(&mvm->mutex);  } @@ -4704,6 +4757,9 @@ static void iwl_mvm_channel_switch_rx_beacon(struct ieee80211_hw *hw,  	if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_CS_MODIFY))  		return; +	IWL_DEBUG_MAC80211(mvm, "Modify CSA on mac %d count = %d (old %d) mode = %d\n", +			   mvmvif->id, chsw->count, mvmvif->csa_count, chsw->block_tx); +  	if (chsw->count >= mvmvif->csa_count && chsw->block_tx) {  		if (mvmvif->csa_misbehave) {  			/* Second time, give up on this AP*/ @@ -4720,8 +4776,6 @@ static void iwl_mvm_channel_switch_rx_beacon(struct ieee80211_hw *hw,  	if (mvmvif->csa_failed)  		goto out_unlock; -	IWL_DEBUG_MAC80211(mvm, "Modify CSA on mac %d count = %d mode = %d\n", -			   mvmvif->id, chsw->count, chsw->block_tx);  	WARN_ON(iwl_mvm_send_cmd_pdu(mvm,  				     WIDE_ID(MAC_CONF_GROUP,  					     CHANNEL_SWITCH_TIME_EVENT_CMD), @@ -4873,6 +4927,8 @@ static int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,  static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo)  { +	u32 format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK; +  	switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) {  	case RATE_MCS_CHAN_WIDTH_20:  		rinfo->bw = RATE_INFO_BW_20; @@ -4888,30 +4944,65 @@ static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo)  		break;  	} -	if (rate_n_flags & RATE_MCS_HT_MSK) { -		rinfo->flags |= RATE_INFO_FLAGS_MCS; -		rinfo->mcs = u32_get_bits(rate_n_flags, RATE_HT_MCS_INDEX_MSK); -		rinfo->nss = u32_get_bits(rate_n_flags, -					  RATE_HT_MCS_NSS_MSK) + 1; -		if (rate_n_flags & RATE_MCS_SGI_MSK) -			rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; -	} else if (rate_n_flags & RATE_MCS_VHT_MSK) { -		rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS; -		rinfo->mcs = u32_get_bits(rate_n_flags, -					  RATE_VHT_MCS_RATE_CODE_MSK); -		rinfo->nss = u32_get_bits(rate_n_flags, -					  RATE_VHT_MCS_NSS_MSK) + 1; -		if (rate_n_flags & RATE_MCS_SGI_MSK) -			rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; -	} else if (rate_n_flags & RATE_MCS_HE_MSK) { +	if (format == RATE_MCS_CCK_MSK || +	    format == RATE_MCS_LEGACY_OFDM_MSK) { +		int rate = u32_get_bits(rate_n_flags, RATE_LEGACY_RATE_MSK); + +		/* add the offset needed to get to the legacy ofdm indices */ +		if (format == RATE_MCS_LEGACY_OFDM_MSK) +			rate += IWL_FIRST_OFDM_RATE; + +		switch (rate) { +		case IWL_RATE_1M_INDEX: +			rinfo->legacy = 10; +			break; +		case IWL_RATE_2M_INDEX: +			rinfo->legacy = 20; +			break; +		case IWL_RATE_5M_INDEX: +			rinfo->legacy = 55; +			break; +		case IWL_RATE_11M_INDEX: +			rinfo->legacy = 110; +			break; +		case IWL_RATE_6M_INDEX: +			rinfo->legacy = 60; +			break; +		case IWL_RATE_9M_INDEX: +			rinfo->legacy = 90; +			break; +		case IWL_RATE_12M_INDEX: +			rinfo->legacy = 120; +			break; +		case IWL_RATE_18M_INDEX: +			rinfo->legacy = 180; +			break; +		case IWL_RATE_24M_INDEX: +			rinfo->legacy = 240; +			break; +		case IWL_RATE_36M_INDEX: +			rinfo->legacy = 360; +			break; +		case IWL_RATE_48M_INDEX: +			rinfo->legacy = 480; +			break; +		case IWL_RATE_54M_INDEX: +			rinfo->legacy = 540; +		} +		return; +	} + +	rinfo->nss = u32_get_bits(rate_n_flags, +				  RATE_MCS_NSS_MSK) + 1; +	rinfo->mcs = format == RATE_MCS_HT_MSK ? +		RATE_HT_MCS_INDEX(rate_n_flags) : +		u32_get_bits(rate_n_flags, RATE_MCS_CODE_MSK); + +	if (format == RATE_MCS_HE_MSK) {  		u32 gi_ltf = u32_get_bits(rate_n_flags,  					  RATE_MCS_HE_GI_LTF_MSK);  		rinfo->flags |= RATE_INFO_FLAGS_HE_MCS; -		rinfo->mcs = u32_get_bits(rate_n_flags, -					  RATE_VHT_MCS_RATE_CODE_MSK); -		rinfo->nss = u32_get_bits(rate_n_flags, -					  RATE_VHT_MCS_NSS_MSK) + 1;  		if (rate_n_flags & RATE_MCS_HE_106T_MSK) {  			rinfo->bw = RATE_INFO_BW_HE_RU; @@ -4925,10 +5016,10 @@ static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo)  				rinfo->he_gi = NL80211_RATE_INFO_HE_GI_0_8;  			else if (gi_ltf == 2)  				rinfo->he_gi = NL80211_RATE_INFO_HE_GI_1_6; -			else if (rate_n_flags & RATE_MCS_SGI_MSK) -				rinfo->he_gi = NL80211_RATE_INFO_HE_GI_0_8; -			else +			else if (gi_ltf == 3)  				rinfo->he_gi = NL80211_RATE_INFO_HE_GI_3_2; +			else +				rinfo->he_gi = NL80211_RATE_INFO_HE_GI_0_8;  			break;  		case RATE_MCS_HE_TYPE_MU:  			if (gi_ltf == 0 || gi_ltf == 1) @@ -4948,46 +5039,19 @@ static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo)  		if (rate_n_flags & RATE_HE_DUAL_CARRIER_MODE_MSK)  			rinfo->he_dcm = 1; -	} else { -		switch (u32_get_bits(rate_n_flags, RATE_LEGACY_RATE_MSK)) { -		case IWL_RATE_1M_PLCP: -			rinfo->legacy = 10; -			break; -		case IWL_RATE_2M_PLCP: -			rinfo->legacy = 20; -			break; -		case IWL_RATE_5M_PLCP: -			rinfo->legacy = 55; -			break; -		case IWL_RATE_11M_PLCP: -			rinfo->legacy = 110; -			break; -		case IWL_RATE_6M_PLCP: -			rinfo->legacy = 60; -			break; -		case IWL_RATE_9M_PLCP: -			rinfo->legacy = 90; -			break; -		case IWL_RATE_12M_PLCP: -			rinfo->legacy = 120; -			break; -		case IWL_RATE_18M_PLCP: -			rinfo->legacy = 180; -			break; -		case IWL_RATE_24M_PLCP: -			rinfo->legacy = 240; -			break; -		case IWL_RATE_36M_PLCP: -			rinfo->legacy = 360; -			break; -		case IWL_RATE_48M_PLCP: -			rinfo->legacy = 480; -			break; -		case IWL_RATE_54M_PLCP: -			rinfo->legacy = 540; -			break; -		} +		return; +	} + +	if (rate_n_flags & RATE_MCS_SGI_MSK) +		rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; + +	if (format == RATE_MCS_HT_MSK) { +		rinfo->flags |= RATE_INFO_FLAGS_MCS; + +	} else if (format == RATE_MCS_VHT_MSK) { +		rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS;  	} +  }  static void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw, @@ -5332,6 +5396,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {  	.sta_rc_update = iwl_mvm_sta_rc_update,  	.conf_tx = iwl_mvm_mac_conf_tx,  	.mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx, +	.mgd_complete_tx = iwl_mvm_mac_mgd_complete_tx,  	.mgd_protect_tdls_discover = iwl_mvm_mac_mgd_protect_tdls_discover,  	.flush = iwl_mvm_mac_flush,  	.sched_scan_start = iwl_mvm_mac_sched_scan_start, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index f877d86b038e..2b1dcd60e00f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -297,6 +297,7 @@ struct iwl_probe_resp_data {   *	see enum &iwl_mvm_low_latency_cause for causes.   * @low_latency_actual: boolean, indicates low latency is set,   *	as a result from low_latency bit flags and takes force into account. + * @authorized: indicates the AP station was set to authorized   * @ps_disabled: indicates that this interface requires PS to be disabled   * @queue_params: QoS params for this MAC   * @bcast_sta: station used for broadcast packets. Used by the following @@ -330,6 +331,7 @@ struct iwl_mvm_vif {  	bool monitor_active;  	u8 low_latency: 6;  	u8 low_latency_actual: 1; +	u8 authorized:1;  	bool ps_disabled;  	struct iwl_mvm_vif_bf_data bf_data; @@ -1443,12 +1445,17 @@ int __iwl_mvm_mac_start(struct iwl_mvm *mvm);  int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm);  /* Utils */ +int iwl_mvm_legacy_hw_idx_to_mac80211_idx(u32 rate_n_flags, +					  enum nl80211_band band);  int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,  					enum nl80211_band band);  void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,  			       enum nl80211_band band,  			       struct ieee80211_tx_rate *r); -u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx); +void iwl_mvm_hwrate_to_tx_rate_v1(u32 rate_n_flags, +				  enum nl80211_band band, +				  struct ieee80211_tx_rate *r); +u8 iwl_mvm_mac80211_idx_to_hwrate(const struct iwl_fw *fw, int rate_idx);  u8 iwl_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_ac_numbers ac);  static inline void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) @@ -1629,6 +1636,8 @@ int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm,  				     void *data, int len);  u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info,  				    struct ieee80211_vif *vif); +u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw, +				      u8 rate_idx);  void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm,  			      __le32 *tim_index, __le32 *tim_size,  			      u8 *beacon, u32 frame_size); @@ -1649,8 +1658,8 @@ void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm,  				   struct iwl_rx_cmd_buffer *rxb);  void iwl_mvm_rx_missed_vap_notif(struct iwl_mvm *mvm,  				 struct iwl_rx_cmd_buffer *rxb); -void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm, -				      struct iwl_rx_cmd_buffer *rxb); +void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm, +					struct iwl_rx_cmd_buffer *rxb);  /* Bindings */  int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);  int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); @@ -1732,7 +1741,7 @@ iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)  /* rate scaling */  int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq);  void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg); -int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate); +int rs_pretty_print_rate_v1(char *buf, int bufsz, const u32 rate);  void rs_update_last_rssi(struct iwl_mvm *mvm,  			 struct iwl_mvm_sta *mvmsta,  			 struct ieee80211_rx_status *rx_status); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c index da705fcaf0fc..6d18a1fd649b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c @@ -583,8 +583,9 @@ void iwl_mvm_rx_chub_update_mcc(struct iwl_mvm *mvm,  		return;  	wgds_tbl_idx = iwl_mvm_get_sar_geo_profile(mvm); -	if (wgds_tbl_idx < 0) -		IWL_DEBUG_INFO(mvm, "SAR WGDS is disabled (%d)\n", +	if (wgds_tbl_idx < 1) +		IWL_DEBUG_INFO(mvm, +			       "SAR WGDS is disabled or error received (%d)\n",  			       wgds_tbl_idx);  	else  		IWL_DEBUG_INFO(mvm, "SAR WGDS: geo profile %d is configured\n", diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 77ea2d0a3091..232ad531d612 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -29,7 +29,6 @@  #define DRV_DESCRIPTION	"The new Intel(R) wireless AGN driver for Linux"  MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_AUTHOR);  MODULE_LICENSE("GPL");  static const struct iwl_op_mode_ops iwl_mvm_ops; @@ -384,9 +383,9 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {  		       iwl_mvm_probe_resp_data_notif,  		       RX_HANDLER_ASYNC_LOCKED,  		       struct iwl_probe_resp_data_notif), -	RX_HANDLER_GRP(MAC_CONF_GROUP, CHANNEL_SWITCH_NOA_NOTIF, -		       iwl_mvm_channel_switch_noa_notif, -		       RX_HANDLER_SYNC, struct iwl_channel_switch_noa_notif), +	RX_HANDLER_GRP(MAC_CONF_GROUP, CHANNEL_SWITCH_START_NOTIF, +		       iwl_mvm_channel_switch_start_notif, +		       RX_HANDLER_SYNC, struct iwl_channel_switch_start_notif),  	RX_HANDLER_GRP(DATA_PATH_GROUP, MONITOR_NOTIF,  		       iwl_mvm_rx_monitor_notif, RX_HANDLER_ASYNC_LOCKED,  		       struct iwl_datapath_monitor_notif), @@ -512,7 +511,7 @@ static const struct iwl_hcmd_names iwl_mvm_mac_conf_names[] = {  	HCMD_NAME(CHANNEL_SWITCH_TIME_EVENT_CMD),  	HCMD_NAME(SESSION_PROTECTION_CMD),  	HCMD_NAME(SESSION_PROTECTION_NOTIF), -	HCMD_NAME(CHANNEL_SWITCH_NOA_NOTIF), +	HCMD_NAME(CHANNEL_SWITCH_START_NOTIF),  };  /* Please keep this array *SORTED* by hex value. @@ -522,7 +521,7 @@ static const struct iwl_hcmd_names iwl_mvm_phy_names[] = {  	HCMD_NAME(CMD_DTS_MEASUREMENT_TRIGGER_WIDE),  	HCMD_NAME(CTDP_CONFIG_CMD),  	HCMD_NAME(TEMP_REPORTING_THRESHOLDS_CMD), -	HCMD_NAME(GEO_TX_POWER_LIMIT), +	HCMD_NAME(PER_CHAIN_LIMIT_OFFSET_CMD),  	HCMD_NAME(CT_KILL_NOTIFICATION),  	HCMD_NAME(DTS_MEASUREMENT_NOTIF_WIDE),  }; @@ -726,6 +725,183 @@ static int iwl_mvm_start_post_nvm(struct iwl_mvm *mvm)  	return 0;  } +struct iwl_mvm_frob_txf_data { +	u8 *buf; +	size_t buflen; +}; + +static void iwl_mvm_frob_txf_key_iter(struct ieee80211_hw *hw, +				      struct ieee80211_vif *vif, +				      struct ieee80211_sta *sta, +				      struct ieee80211_key_conf *key, +				      void *data) +{ +	struct iwl_mvm_frob_txf_data *txf = data; +	u8 keylen, match, matchend; +	u8 *keydata; +	size_t i; + +	switch (key->cipher) { +	case WLAN_CIPHER_SUITE_CCMP: +		keydata = key->key; +		keylen = key->keylen; +		break; +	case WLAN_CIPHER_SUITE_WEP40: +	case WLAN_CIPHER_SUITE_WEP104: +	case WLAN_CIPHER_SUITE_TKIP: +		/* +		 * WEP has short keys which might show up in the payload, +		 * and then you can deduce the key, so in this case just +		 * remove all FIFO data. +		 * For TKIP, we don't know the phase 2 keys here, so same. +		 */ +		memset(txf->buf, 0xBB, txf->buflen); +		return; +	default: +		return; +	} + +	/* scan for key material and clear it out */ +	match = 0; +	for (i = 0; i < txf->buflen; i++) { +		if (txf->buf[i] != keydata[match]) { +			match = 0; +			continue; +		} +		match++; +		if (match == keylen) { +			memset(txf->buf + i - keylen, 0xAA, keylen); +			match = 0; +		} +	} + +	/* we're dealing with a FIFO, so check wrapped around data */ +	matchend = match; +	for (i = 0; match && i < keylen - match; i++) { +		if (txf->buf[i] != keydata[match]) +			break; +		match++; +		if (match == keylen) { +			memset(txf->buf, 0xAA, i + 1); +			memset(txf->buf + txf->buflen - matchend, 0xAA, +			       matchend); +			break; +		} +	} +} + +static void iwl_mvm_frob_txf(void *ctx, void *buf, size_t buflen) +{ +	struct iwl_mvm_frob_txf_data txf = { +		.buf = buf, +		.buflen = buflen, +	}; +	struct iwl_mvm *mvm = ctx; + +	/* embedded key material exists only on old API */ +	if (iwl_mvm_has_new_tx_api(mvm)) +		return; + +	rcu_read_lock(); +	ieee80211_iter_keys_rcu(mvm->hw, NULL, iwl_mvm_frob_txf_key_iter, &txf); +	rcu_read_unlock(); +} + +static void iwl_mvm_frob_hcmd(void *ctx, void *hcmd, size_t len) +{ +	/* we only use wide headers for commands */ +	struct iwl_cmd_header_wide *hdr = hcmd; +	unsigned int frob_start = sizeof(*hdr), frob_end = 0; + +	if (len < sizeof(hdr)) +		return; + +	/* all the commands we care about are in LONG_GROUP */ +	if (hdr->group_id != LONG_GROUP) +		return; + +	switch (hdr->cmd) { +	case WEP_KEY: +	case WOWLAN_TKIP_PARAM: +	case WOWLAN_KEK_KCK_MATERIAL: +	case ADD_STA_KEY: +		/* +		 * blank out everything here, easier than dealing +		 * with the various versions of the command +		 */ +		frob_end = INT_MAX; +		break; +	case MGMT_MCAST_KEY: +		frob_start = offsetof(struct iwl_mvm_mgmt_mcast_key_cmd, igtk); +		BUILD_BUG_ON(offsetof(struct iwl_mvm_mgmt_mcast_key_cmd, igtk) != +			     offsetof(struct iwl_mvm_mgmt_mcast_key_cmd_v1, igtk)); + +		frob_end = offsetofend(struct iwl_mvm_mgmt_mcast_key_cmd, igtk); +		BUILD_BUG_ON(offsetof(struct iwl_mvm_mgmt_mcast_key_cmd, igtk) < +			     offsetof(struct iwl_mvm_mgmt_mcast_key_cmd_v1, igtk)); +		break; +	} + +	if (frob_start >= frob_end) +		return; + +	if (frob_end > len) +		frob_end = len; + +	memset((u8 *)hcmd + frob_start, 0xAA, frob_end - frob_start); +} + +static void iwl_mvm_frob_mem(void *ctx, u32 mem_addr, void *mem, size_t buflen) +{ +	const struct iwl_dump_exclude *excl; +	struct iwl_mvm *mvm = ctx; +	int i; + +	switch (mvm->fwrt.cur_fw_img) { +	case IWL_UCODE_INIT: +	default: +		/* not relevant */ +		return; +	case IWL_UCODE_REGULAR: +	case IWL_UCODE_REGULAR_USNIFFER: +		excl = mvm->fw->dump_excl; +		break; +	case IWL_UCODE_WOWLAN: +		excl = mvm->fw->dump_excl_wowlan; +		break; +	} + +	BUILD_BUG_ON(sizeof(mvm->fw->dump_excl) != +		     sizeof(mvm->fw->dump_excl_wowlan)); + +	for (i = 0; i < ARRAY_SIZE(mvm->fw->dump_excl); i++) { +		u32 start, end; + +		if (!excl[i].addr || !excl[i].size) +			continue; + +		start = excl[i].addr; +		end = start + excl[i].size; + +		if (end <= mem_addr || start >= mem_addr + buflen) +			continue; + +		if (start < mem_addr) +			start = mem_addr; + +		if (end > mem_addr + buflen) +			end = mem_addr + buflen; + +		memset((u8 *)mem + start - mem_addr, 0xAA, end - start); +	} +} + +static const struct iwl_dump_sanitize_ops iwl_mvm_sanitize_ops = { +	.frob_txf = iwl_mvm_frob_txf, +	.frob_hcmd = iwl_mvm_frob_hcmd, +	.frob_mem = iwl_mvm_frob_mem, +}; +  static struct iwl_op_mode *  iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,  		      const struct iwl_fw *fw, struct dentry *dbgfs_dir) @@ -775,7 +951,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,  	mvm->hw = hw;  	iwl_fw_runtime_init(&mvm->fwrt, trans, fw, &iwl_mvm_fwrt_ops, mvm, -			    dbgfs_dir); +			    &iwl_mvm_sanitize_ops, mvm, dbgfs_dir);  	iwl_mvm_get_acpi_tables(mvm); @@ -868,8 +1044,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,  	mvm->cmd_ver.range_resp =  		iwl_fw_lookup_notif_ver(mvm->fw, LOCATION_GROUP,  					TOF_RANGE_RESPONSE_NOTIF, 5); -	/* we only support up to version 8 */ -	if (WARN_ON_ONCE(mvm->cmd_ver.range_resp > 8)) +	/* we only support up to version 9 */ +	if (WARN_ON_ONCE(mvm->cmd_ver.range_resp > 9))  		goto out_free;  	/* diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c index f2b090be3898..b2ea2fca5376 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c @@ -1,6 +1,6 @@  // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause  /* - * Copyright (C) 2012-2014, 2018-2019 Intel Corporation + * Copyright (C) 2012-2014, 2018-2019, 2021 Intel Corporation   * Copyright (C) 2013-2014 Intel Mobile Communications GmbH   * Copyright (C) 2015-2017 Intel Deutschland GmbH   */ @@ -128,6 +128,19 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,  	enum ieee80211_ac_numbers ac;  	bool tid_found = false; +	if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) || +	    cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) { +		cmd->rx_data_timeout_uapsd = +			cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT); +		cmd->tx_data_timeout_uapsd = +			cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); +	} else { +		cmd->rx_data_timeout_uapsd = +			cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT); +		cmd->tx_data_timeout_uapsd = +			cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT); +	} +  #ifdef CONFIG_IWLWIFI_DEBUGFS  	/* set advanced pm flag with no uapsd ACs to enable ps-poll */  	if (mvmvif->dbgfs_pm.use_ps_poll) { @@ -182,19 +195,6 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,  	cmd->uapsd_max_sp = mvm->hw->uapsd_max_sp_len; -	if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) || -	    cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) { -		cmd->rx_data_timeout_uapsd = -			cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT); -		cmd->tx_data_timeout_uapsd = -			cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); -	} else { -		cmd->rx_data_timeout_uapsd = -			cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT); -		cmd->tx_data_timeout_uapsd = -			cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT); -	} -  	if (cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {  		cmd->heavy_tx_thld_packets =  			IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c index 2d58cb969918..958702403a45 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c @@ -32,10 +32,6 @@ static u8 rs_fw_set_active_chains(u8 chains)  		fw_chains |= IWL_TLC_MNG_CHAIN_A_MSK;  	if (chains & ANT_B)  		fw_chains |= IWL_TLC_MNG_CHAIN_B_MSK; -	if (chains & ANT_C) -		WARN(false, -		     "tlc offload doesn't support antenna C. chains: 0x%x\n", -		     chains);  	return fw_chains;  } @@ -314,7 +310,19 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,  	if (flags & IWL_TLC_NOTIF_FLAG_RATE) {  		char pretty_rate[100]; + +	if (iwl_fw_lookup_notif_ver(mvm->fw, DATA_PATH_GROUP, +				    TLC_MNG_UPDATE_NOTIF, 0) < 3) { +		rs_pretty_print_rate_v1(pretty_rate, sizeof(pretty_rate), +					le32_to_cpu(notif->rate)); +		IWL_DEBUG_RATE(mvm, +			       "Got rate in old format. Rate: %s. Converting.\n", +			       pretty_rate); +		lq_sta->last_rate_n_flags = +			iwl_new_rate_from_v1(le32_to_cpu(notif->rate)); +	} else {  		lq_sta->last_rate_n_flags = le32_to_cpu(notif->rate); +	}  		rs_pretty_print_rate(pretty_rate, sizeof(pretty_rate),  				     lq_sta->last_rate_n_flags);  		IWL_DEBUG_RATE(mvm, "new rate: %s\n", pretty_rate); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index b97708cb869d..f4d02f9fe16d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -4,11 +4,6 @@   * Copyright(c) 2005 - 2014, 2018 - 2021 Intel Corporation. All rights reserved.   * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH   * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #include <linux/kernel.h>  #include <linux/skbuff.h> @@ -335,15 +330,15 @@ static const struct rs_tx_column rs_tx_columns[] = {  static inline u8 rs_extract_rate(u32 rate_n_flags)  {  	/* also works for HT because bits 7:6 are zero there */ -	return (u8)(rate_n_flags & RATE_LEGACY_RATE_MSK); +	return (u8)(rate_n_flags & RATE_LEGACY_RATE_MSK_V1);  }  static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)  {  	int idx = 0; -	if (rate_n_flags & RATE_MCS_HT_MSK) { -		idx = rate_n_flags & RATE_HT_MCS_RATE_CODE_MSK; +	if (rate_n_flags & RATE_MCS_HT_MSK_V1) { +		idx = rate_n_flags & RATE_HT_MCS_RATE_CODE_MSK_V1;  		idx += IWL_RATE_MCS_0_INDEX;  		/* skip 9M not supported in HT*/ @@ -351,8 +346,8 @@ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)  			idx += 1;  		if ((idx >= IWL_FIRST_HT_RATE) && (idx <= IWL_LAST_HT_RATE))  			return idx; -	} else if (rate_n_flags & RATE_MCS_VHT_MSK || -		   rate_n_flags & RATE_MCS_HE_MSK) { +	} else if (rate_n_flags & RATE_MCS_VHT_MSK_V1 || +		   rate_n_flags & RATE_MCS_HE_MSK_V1) {  		idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;  		idx += IWL_RATE_MCS_0_INDEX; @@ -361,8 +356,8 @@ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)  			idx++;  		if ((idx >= IWL_FIRST_VHT_RATE) && (idx <= IWL_LAST_VHT_RATE))  			return idx; -		if ((rate_n_flags & RATE_MCS_HE_MSK) && -		    (idx <= IWL_LAST_HE_RATE)) +		if ((rate_n_flags & RATE_MCS_HE_MSK_V1) && +		    idx <= IWL_LAST_HE_RATE)  			return idx;  	} else {  		/* legacy rate format, search for match in table */ @@ -459,44 +454,8 @@ static const u16 expected_tpt_mimo2_160MHz[4][IWL_RATE_COUNT] = {  	{0, 0, 0, 0, 971, 0, 1925, 2861, 3779, 5574, 7304, 8147, 8976, 10592, 11640},  }; -/* mbps, mcs */ -static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { -	{  "1", "BPSK DSSS"}, -	{  "2", "QPSK DSSS"}, -	{"5.5", "BPSK CCK"}, -	{ "11", "QPSK CCK"}, -	{  "6", "BPSK 1/2"}, -	{  "9", "BPSK 1/2"}, -	{ "12", "QPSK 1/2"}, -	{ "18", "QPSK 3/4"}, -	{ "24", "16QAM 1/2"}, -	{ "36", "16QAM 3/4"}, -	{ "48", "64QAM 2/3"}, -	{ "54", "64QAM 3/4"}, -	{ "60", "64QAM 5/6"}, -}; -  #define MCS_INDEX_PER_STREAM	(8) -static const char *rs_pretty_ant(u8 ant) -{ -	static const char * const ant_name[] = { -		[ANT_NONE] = "None", -		[ANT_A]    = "A", -		[ANT_B]    = "B", -		[ANT_AB]   = "AB", -		[ANT_C]    = "C", -		[ANT_AC]   = "AC", -		[ANT_BC]   = "BC", -		[ANT_ABC]  = "ABC", -	}; - -	if (ant > ANT_ABC) -		return "UNKNOWN"; - -	return ant_name[ant]; -} -  static const char *rs_pretty_lq_type(enum iwl_table_type type)  {  	static const char * const lq_types[] = { @@ -558,7 +517,7 @@ static char *rs_pretty_rate(const struct rs_rate *rate)  		rate_str = "BAD_RATE";  	sprintf(buf, "(%s|%s|%s)", rs_pretty_lq_type(rate->type), -		rs_pretty_ant(rate->ant), rate_str); +		iwl_rs_pretty_ant(rate->ant), rate_str);  	return buf;  } @@ -654,8 +613,7 @@ static void rs_tl_turn_on_agg(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,  static inline int get_num_of_ant_from_rate(u32 rate_n_flags)  {  	return !!(rate_n_flags & RATE_MCS_ANT_A_MSK) + -	       !!(rate_n_flags & RATE_MCS_ANT_B_MSK) + -	       !!(rate_n_flags & RATE_MCS_ANT_C_MSK); +	       !!(rate_n_flags & RATE_MCS_ANT_B_MSK);  }  /* @@ -820,12 +778,12 @@ static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm,  	int index = rate->index;  	ucode_rate |= ((rate->ant << RATE_MCS_ANT_POS) & -			 RATE_MCS_ANT_ABC_MSK); +			 RATE_MCS_ANT_AB_MSK);  	if (is_legacy(rate)) {  		ucode_rate |= iwl_rates[index].plcp;  		if (index >= IWL_FIRST_CCK_RATE && index <= IWL_LAST_CCK_RATE) -			ucode_rate |= RATE_MCS_CCK_MSK; +			ucode_rate |= RATE_MCS_CCK_MSK_V1;  		return ucode_rate;  	} @@ -840,7 +798,7 @@ static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm,  			IWL_ERR(mvm, "Invalid HT rate index %d\n", index);  			index = IWL_LAST_HT_RATE;  		} -		ucode_rate |= RATE_MCS_HT_MSK; +		ucode_rate |= RATE_MCS_HT_MSK_V1;  		if (is_ht_siso(rate))  			ucode_rate |= iwl_rates[index].plcp_ht_siso; @@ -853,7 +811,7 @@ static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm,  			IWL_ERR(mvm, "Invalid VHT rate index %d\n", index);  			index = IWL_LAST_VHT_RATE;  		} -		ucode_rate |= RATE_MCS_VHT_MSK; +		ucode_rate |= RATE_MCS_VHT_MSK_V1;  		if (is_vht_siso(rate))  			ucode_rate |= iwl_rates[index].plcp_vht_siso;  		else if (is_vht_mimo2(rate)) @@ -873,9 +831,9 @@ static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm,  	ucode_rate |= rate->bw;  	if (rate->sgi) -		ucode_rate |= RATE_MCS_SGI_MSK; +		ucode_rate |= RATE_MCS_SGI_MSK_V1;  	if (rate->ldpc) -		ucode_rate |= RATE_MCS_LDPC_MSK; +		ucode_rate |= RATE_MCS_LDPC_MSK_V1;  	return ucode_rate;  } @@ -885,7 +843,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,  				   enum nl80211_band band,  				   struct rs_rate *rate)  { -	u32 ant_msk = ucode_rate & RATE_MCS_ANT_ABC_MSK; +	u32 ant_msk = ucode_rate & RATE_MCS_ANT_AB_MSK;  	u8 num_of_ant = get_num_of_ant_from_rate(ucode_rate);  	u8 nss; @@ -898,9 +856,9 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,  	rate->ant = (ant_msk >> RATE_MCS_ANT_POS);  	/* Legacy */ -	if (!(ucode_rate & RATE_MCS_HT_MSK) && -	    !(ucode_rate & RATE_MCS_VHT_MSK) && -	    !(ucode_rate & RATE_MCS_HE_MSK)) { +	if (!(ucode_rate & RATE_MCS_HT_MSK_V1) && +	    !(ucode_rate & RATE_MCS_VHT_MSK_V1) && +	    !(ucode_rate & RATE_MCS_HE_MSK_V1)) {  		if (num_of_ant == 1) {  			if (band == NL80211_BAND_5GHZ)  				rate->type = LQ_LEGACY_A; @@ -912,20 +870,20 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,  	}  	/* HT, VHT or HE */ -	if (ucode_rate & RATE_MCS_SGI_MSK) +	if (ucode_rate & RATE_MCS_SGI_MSK_V1)  		rate->sgi = true; -	if (ucode_rate & RATE_MCS_LDPC_MSK) +	if (ucode_rate & RATE_MCS_LDPC_MSK_V1)  		rate->ldpc = true;  	if (ucode_rate & RATE_MCS_STBC_MSK)  		rate->stbc = true;  	if (ucode_rate & RATE_MCS_BF_MSK)  		rate->bfer = true; -	rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK; +	rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK_V1; -	if (ucode_rate & RATE_MCS_HT_MSK) { -		nss = ((ucode_rate & RATE_HT_MCS_NSS_MSK) >> -		       RATE_HT_MCS_NSS_POS) + 1; +	if (ucode_rate & RATE_MCS_HT_MSK_V1) { +		nss = ((ucode_rate & RATE_HT_MCS_NSS_MSK_V1) >> +		       RATE_HT_MCS_NSS_POS_V1) + 1;  		if (nss == 1) {  			rate->type = LQ_HT_SISO; @@ -938,7 +896,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,  		} else {  			WARN_ON_ONCE(1);  		} -	} else if (ucode_rate & RATE_MCS_VHT_MSK) { +	} else if (ucode_rate & RATE_MCS_VHT_MSK_V1) {  		nss = ((ucode_rate & RATE_VHT_MCS_NSS_MSK) >>  		       RATE_VHT_MCS_NSS_POS) + 1; @@ -953,7 +911,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,  		} else {  			WARN_ON_ONCE(1);  		} -	} else if (ucode_rate & RATE_MCS_HE_MSK) { +	} else if (ucode_rate & RATE_MCS_HE_MSK_V1) {  		nss = ((ucode_rate & RATE_VHT_MCS_NSS_MSK) >>  		      RATE_VHT_MCS_NSS_POS) + 1; @@ -981,9 +939,6 @@ static int rs_toggle_antenna(u32 valid_ant, struct rs_rate *rate)  {  	u8 new_ant_type; -	if (!rate->ant || WARN_ON_ONCE(rate->ant & ANT_C)) -		return 0; -  	if (!rs_is_valid_ant(valid_ant, rate->ant))  		return 0; @@ -2552,7 +2507,7 @@ static void rs_get_initial_rate(struct iwl_mvm *mvm,  	}  	IWL_DEBUG_RATE(mvm, "Best ANT: %s Best RSSI: %d\n", -		       rs_pretty_ant(best_ant), best_rssi); +		       iwl_rs_pretty_ant(best_ant), best_rssi);  	if (best_ant != ANT_A && best_ant != ANT_B)  		rate->ant = first_antenna(valid_tx_ant); @@ -2652,7 +2607,6 @@ void rs_update_last_rssi(struct iwl_mvm *mvm,  	lq_sta->pers.chains = rx_status->chains;  	lq_sta->pers.chain_signal[0] = rx_status->chain_signal[0];  	lq_sta->pers.chain_signal[1] = rx_status->chain_signal[1]; -	lq_sta->pers.chain_signal[2] = rx_status->chain_signal[2];  	lq_sta->pers.last_rssi = S8_MIN;  	for (i = 0; i < ARRAY_SIZE(lq_sta->pers.chain_signal); i++) { @@ -2738,8 +2692,8 @@ static void rs_drv_get_rate(void *mvm_r, struct ieee80211_sta *sta,  		return;  	lq_sta = mvm_sta; -	iwl_mvm_hwrate_to_tx_rate(lq_sta->last_rate_n_flags, -				  info->band, &info->control.rates[0]); +	iwl_mvm_hwrate_to_tx_rate_v1(lq_sta->last_rate_n_flags, +				     info->band, &info->control.rates[0]);  	info->control.rates[0].count = 1;  	/* Report the optimal rate based on rssi and STA caps if we haven't @@ -2749,8 +2703,8 @@ static void rs_drv_get_rate(void *mvm_r, struct ieee80211_sta *sta,  		optimal_rate = rs_get_optimal_rate(mvm, lq_sta);  		last_ucode_rate = ucode_rate_from_rs_rate(mvm,  							  optimal_rate); -		iwl_mvm_hwrate_to_tx_rate(last_ucode_rate, info->band, -					  &txrc->reported_rate); +		iwl_mvm_hwrate_to_tx_rate_v1(last_ucode_rate, info->band, +					     &txrc->reported_rate);  	}  } @@ -2909,7 +2863,7 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg)  	mvm->drv_rx_stats.success_frames++; -	switch (rate & RATE_MCS_CHAN_WIDTH_MSK) { +	switch (rate & RATE_MCS_CHAN_WIDTH_MSK_V1) {  	case RATE_MCS_CHAN_WIDTH_20:  		mvm->drv_rx_stats.bw_20_frames++;  		break; @@ -2926,10 +2880,10 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg)  		WARN_ONCE(1, "bad BW. rate 0x%x", rate);  	} -	if (rate & RATE_MCS_HT_MSK) { +	if (rate & RATE_MCS_HT_MSK_V1) {  		mvm->drv_rx_stats.ht_frames++; -		nss = ((rate & RATE_HT_MCS_NSS_MSK) >> RATE_HT_MCS_NSS_POS) + 1; -	} else if (rate & RATE_MCS_VHT_MSK) { +		nss = ((rate & RATE_HT_MCS_NSS_MSK_V1) >> RATE_HT_MCS_NSS_POS_V1) + 1; +	} else if (rate & RATE_MCS_VHT_MSK_V1) {  		mvm->drv_rx_stats.vht_frames++;  		nss = ((rate & RATE_VHT_MCS_NSS_MSK) >>  		       RATE_VHT_MCS_NSS_POS) + 1; @@ -2942,7 +2896,7 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg)  	else if (nss == 2)  		mvm->drv_rx_stats.mimo2_frames++; -	if (rate & RATE_MCS_SGI_MSK) +	if (rate & RATE_MCS_SGI_MSK_V1)  		mvm->drv_rx_stats.sgi_frames++;  	else  		mvm->drv_rx_stats.ngi_frames++; @@ -3323,7 +3277,7 @@ static void rs_build_rates_table_from_fixed(struct iwl_mvm *mvm,  	int i;  	int num_rates = ARRAY_SIZE(lq_cmd->rs_table);  	__le32 ucode_rate_le32 = cpu_to_le32(ucode_rate); -	u8 ant = (ucode_rate & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS; +	u8 ant = (ucode_rate & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS;  	for (i = 0; i < num_rates; i++)  		lq_cmd->rs_table[i] = ucode_rate_le32; @@ -3688,35 +3642,37 @@ static void rs_free_sta(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta)  	IWL_DEBUG_RATE(mvm, "leave\n");  } -int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate) +int rs_pretty_print_rate_v1(char *buf, int bufsz, const u32 rate)  { -	char *type, *bw; +	char *type;  	u8 mcs = 0, nss = 0; -	u8 ant = (rate & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS; +	u8 ant = (rate & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS; +	u32 bw = (rate & RATE_MCS_CHAN_WIDTH_MSK_V1) >> +		RATE_MCS_CHAN_WIDTH_POS; -	if (!(rate & RATE_MCS_HT_MSK) && -	    !(rate & RATE_MCS_VHT_MSK) && -	    !(rate & RATE_MCS_HE_MSK)) { +	if (!(rate & RATE_MCS_HT_MSK_V1) && +	    !(rate & RATE_MCS_VHT_MSK_V1) && +	    !(rate & RATE_MCS_HE_MSK_V1)) {  		int index = iwl_hwrate_to_plcp_idx(rate);  		return scnprintf(buf, bufsz, "Legacy | ANT: %s Rate: %s Mbps", -				 rs_pretty_ant(ant), +				 iwl_rs_pretty_ant(ant),  				 index == IWL_RATE_INVALID ? "BAD" : -				 iwl_rate_mcs[index].mbps); +				 iwl_rate_mcs(index)->mbps);  	} -	if (rate & RATE_MCS_VHT_MSK) { +	if (rate & RATE_MCS_VHT_MSK_V1) {  		type = "VHT";  		mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK;  		nss = ((rate & RATE_VHT_MCS_NSS_MSK)  		       >> RATE_VHT_MCS_NSS_POS) + 1; -	} else if (rate & RATE_MCS_HT_MSK) { +	} else if (rate & RATE_MCS_HT_MSK_V1) {  		type = "HT"; -		mcs = rate & RATE_HT_MCS_INDEX_MSK; -		nss = ((rate & RATE_HT_MCS_NSS_MSK) -		       >> RATE_HT_MCS_NSS_POS) + 1; -	} else if (rate & RATE_MCS_HE_MSK) { +		mcs = rate & RATE_HT_MCS_INDEX_MSK_V1; +		nss = ((rate & RATE_HT_MCS_NSS_MSK_V1) +		       >> RATE_HT_MCS_NSS_POS_V1) + 1; +	} else if (rate & RATE_MCS_HE_MSK_V1) {  		type = "HE";  		mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK;  		nss = ((rate & RATE_VHT_MCS_NSS_MSK) @@ -3725,29 +3681,12 @@ int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate)  		type = "Unknown"; /* shouldn't happen */  	} -	switch (rate & RATE_MCS_CHAN_WIDTH_MSK) { -	case RATE_MCS_CHAN_WIDTH_20: -		bw = "20Mhz"; -		break; -	case RATE_MCS_CHAN_WIDTH_40: -		bw = "40Mhz"; -		break; -	case RATE_MCS_CHAN_WIDTH_80: -		bw = "80Mhz"; -		break; -	case RATE_MCS_CHAN_WIDTH_160: -		bw = "160Mhz"; -		break; -	default: -		bw = "BAD BW"; -	} -  	return scnprintf(buf, bufsz,  			 "0x%x: %s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s", -			 rate, type, rs_pretty_ant(ant), bw, mcs, nss, -			 (rate & RATE_MCS_SGI_MSK) ? "SGI " : "NGI ", +			 rate, type, iwl_rs_pretty_ant(ant), iwl_rs_pretty_bw(bw), mcs, nss, +			 (rate & RATE_MCS_SGI_MSK_V1) ? "SGI " : "NGI ",  			 (rate & RATE_MCS_STBC_MSK) ? "STBC " : "", -			 (rate & RATE_MCS_LDPC_MSK) ? "LDPC " : "", +			 (rate & RATE_MCS_LDPC_MSK_V1) ? "LDPC " : "",  			 (rate & RATE_HE_DUAL_CARRIER_MODE_MSK) ? "DCM " : "",  			 (rate & RATE_MCS_BF_MSK) ? "BF " : "");  } @@ -3830,10 +3769,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,  			  lq_sta->active_legacy_rate);  	desc += scnprintf(buff + desc, bufsz - desc, "fixed rate 0x%X\n",  			  lq_sta->pers.dbg_fixed_rate); -	desc += scnprintf(buff + desc, bufsz - desc, "valid_tx_ant %s%s%s\n", +	desc += scnprintf(buff + desc, bufsz - desc, "valid_tx_ant %s%s\n",  	    (iwl_mvm_get_valid_tx_ant(mvm) & ANT_A) ? "ANT_A," : "", -	    (iwl_mvm_get_valid_tx_ant(mvm) & ANT_B) ? "ANT_B," : "", -	    (iwl_mvm_get_valid_tx_ant(mvm) & ANT_C) ? "ANT_C" : ""); +	    (iwl_mvm_get_valid_tx_ant(mvm) & ANT_B) ? "ANT_B," : "");  	desc += scnprintf(buff + desc, bufsz - desc, "lq type %s\n",  			  (is_legacy(rate)) ? "legacy" :  			  is_vht(rate) ? "VHT" : "HT"); @@ -3891,7 +3829,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,  		desc += scnprintf(buff + desc, bufsz - desc,  				  " rate[%d] 0x%X ", i, r); -		desc += rs_pretty_print_rate(buff + desc, bufsz - desc, r); +		desc += rs_pretty_print_rate_v1(buff + desc, bufsz - desc, r);  		if (desc < bufsz - 1)  			buff[desc++] = '\n';  	} diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h index 32104c9f8f5e..b7bc8c1b2dda 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h @@ -5,11 +5,6 @@   * Copyright(c) 2015 Intel Mobile Communications GmbH   * Copyright(c) 2017 Intel Deutschland GmbH   * Copyright(c) 2018 - 2019 Intel Corporation - * - * Contact Information: - *  Intel Linux Wireless <linuxwifi@intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *   *****************************************************************************/  #ifndef __rs_h__ @@ -36,11 +31,6 @@ struct iwl_rs_rate_info {  #define IWL_RATE_60M_PLCP 3 -enum { -	IWL_RATE_INVM_INDEX = IWL_RATE_COUNT, -	IWL_RATE_INVALID = IWL_RATE_COUNT, -}; -  #define LINK_QUAL_MAX_RETRY_NUM 16  enum { @@ -211,13 +201,6 @@ struct rs_rate {  #define is_ht80(rate)         ((rate)->bw == RATE_MCS_CHAN_WIDTH_80)  #define is_ht160(rate)        ((rate)->bw == RATE_MCS_CHAN_WIDTH_160) -#define IWL_MAX_MCS_DISPLAY_SIZE	12 - -struct iwl_rate_mcs_info { -	char	mbps[IWL_MAX_MCS_DISPLAY_SIZE]; -	char	mcs[IWL_MAX_MCS_DISPLAY_SIZE]; -}; -  /**   * struct iwl_lq_sta_rs_fw - rate and related statistics for RS in FW   * @last_rate_n_flags: last rate reported by FW diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c index 8ef5399ad9be..d22f40a5354d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c @@ -1,6 +1,6 @@  // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause  /* - * Copyright (C) 2012-2014, 2018-2020 Intel Corporation + * Copyright (C) 2012-2014, 2018-2021 Intel Corporation   * Copyright (C) 2013-2015 Intel Mobile Communications GmbH   * Copyright (C) 2016-2017 Intel Deutschland GmbH   */ @@ -103,7 +103,7 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,  					struct iwl_rx_phy_info *phy_info,  					struct ieee80211_rx_status *rx_status)  { -	int energy_a, energy_b, energy_c, max_energy; +	int energy_a, energy_b, max_energy;  	u32 val;  	val = @@ -114,14 +114,10 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,  	energy_b = (val & IWL_RX_INFO_ENERGY_ANT_B_MSK) >>  						IWL_RX_INFO_ENERGY_ANT_B_POS;  	energy_b = energy_b ? -energy_b : S8_MIN; -	energy_c = (val & IWL_RX_INFO_ENERGY_ANT_C_MSK) >> -						IWL_RX_INFO_ENERGY_ANT_C_POS; -	energy_c = energy_c ? -energy_c : S8_MIN;  	max_energy = max(energy_a, energy_b); -	max_energy = max(max_energy, energy_c); -	IWL_DEBUG_STATS(mvm, "energy In A %d B %d C %d , and max %d\n", -			energy_a, energy_b, energy_c, max_energy); +	IWL_DEBUG_STATS(mvm, "energy In A %d B %d  , and max %d\n", +			energy_a, energy_b, max_energy);  	rx_status->signal = max_energy;  	rx_status->chains = (le16_to_cpu(phy_info->phy_flags) & @@ -129,7 +125,6 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,  					>> RX_RES_PHY_FLAGS_ANTENNA_POS;  	rx_status->chain_signal[0] = energy_a;  	rx_status->chain_signal[1] = energy_b; -	rx_status->chain_signal[2] = energy_c;  }  /* @@ -235,7 +230,7 @@ static void iwl_mvm_rx_handle_tcm(struct iwl_mvm *mvm,  		mdata->rx.airtime += le16_to_cpu(phy_info->frame_time);  	} -	if (!(rate_n_flags & (RATE_MCS_HT_MSK | RATE_MCS_VHT_MSK))) +	if (!(rate_n_flags & (RATE_MCS_HT_MSK_V1 | RATE_MCS_VHT_MSK_V1)))  		return;  	mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif); @@ -249,10 +244,10 @@ static void iwl_mvm_rx_handle_tcm(struct iwl_mvm *mvm,  	    mvmsta->sta_id != mvmvif->ap_sta_id)  		return; -	if (rate_n_flags & RATE_MCS_HT_MSK) { -		thr = thresh_tpt[rate_n_flags & RATE_HT_MCS_RATE_CODE_MSK]; -		thr *= 1 + ((rate_n_flags & RATE_HT_MCS_NSS_MSK) >> -					RATE_HT_MCS_NSS_POS); +	if (rate_n_flags & RATE_MCS_HT_MSK_V1) { +		thr = thresh_tpt[rate_n_flags & RATE_HT_MCS_RATE_CODE_MSK_V1]; +		thr *= 1 + ((rate_n_flags & RATE_HT_MCS_NSS_MSK_V1) >> +					RATE_HT_MCS_NSS_POS_V1);  	} else {  		if (WARN_ON((rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK) >=  				ARRAY_SIZE(thresh_tpt))) @@ -262,7 +257,7 @@ static void iwl_mvm_rx_handle_tcm(struct iwl_mvm *mvm,  					RATE_VHT_MCS_NSS_POS);  	} -	thr <<= ((rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) >> +	thr <<= ((rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK_V1) >>  				RATE_MCS_CHAN_WIDTH_POS);  	mdata->uapsd_nonagg_detect.rx_bytes += len; @@ -455,7 +450,7 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,  	}  	/* Set up the HT phy flags */ -	switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) { +	switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK_V1) {  	case RATE_MCS_CHAN_WIDTH_20:  		break;  	case RATE_MCS_CHAN_WIDTH_40: @@ -468,20 +463,20 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,  		rx_status->bw = RATE_INFO_BW_160;  		break;  	} -	if (!(rate_n_flags & RATE_MCS_CCK_MSK) && -	    rate_n_flags & RATE_MCS_SGI_MSK) +	if (!(rate_n_flags & RATE_MCS_CCK_MSK_V1) && +	    rate_n_flags & RATE_MCS_SGI_MSK_V1)  		rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;  	if (rate_n_flags & RATE_HT_MCS_GF_MSK)  		rx_status->enc_flags |= RX_ENC_FLAG_HT_GF; -	if (rate_n_flags & RATE_MCS_LDPC_MSK) +	if (rate_n_flags & RATE_MCS_LDPC_MSK_V1)  		rx_status->enc_flags |= RX_ENC_FLAG_LDPC; -	if (rate_n_flags & RATE_MCS_HT_MSK) { +	if (rate_n_flags & RATE_MCS_HT_MSK_V1) {  		u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >>  				RATE_MCS_STBC_POS;  		rx_status->encoding = RX_ENC_HT; -		rx_status->rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK; +		rx_status->rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK_V1;  		rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT; -	} else if (rate_n_flags & RATE_MCS_VHT_MSK) { +	} else if (rate_n_flags & RATE_MCS_VHT_MSK_V1) {  		u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >>  				RATE_MCS_STBC_POS;  		rx_status->nss = diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index c12f303cf652..e0601f802628 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -240,8 +240,7 @@ static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm,  static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,  					    struct napi_struct *napi,  					    struct sk_buff *skb, int queue, -					    struct ieee80211_sta *sta, -					    bool csi) +					    struct ieee80211_sta *sta)  {  	if (iwl_mvm_check_pn(mvm, skb, queue, sta))  		kfree_skb(skb); @@ -269,7 +268,6 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,  		(rate_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS;  	rx_status->chain_signal[0] = energy_a;  	rx_status->chain_signal[1] = energy_b; -	rx_status->chain_signal[2] = S8_MIN;  }  static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta, @@ -620,7 +618,7 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,  		while ((skb = __skb_dequeue(skb_list))) {  			iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb,  							reorder_buf->queue, -							sta, false); +							sta);  			reorder_buf->num_stored--;  		}  	} @@ -1198,7 +1196,7 @@ static void iwl_mvm_decode_he_mu_ext(struct iwl_mvm *mvm,  	}  	if (FIELD_GET(IWL_RX_PHY_DATA4_HE_MU_EXT_CH2_CRC_OK, phy_data4) && -	    (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) != RATE_MCS_CHAN_WIDTH_20) { +	    (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK_V1) != RATE_MCS_CHAN_WIDTH_20) {  		he_mu->flags1 |=  			cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_RU_KNOWN |  				    IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_CTR_26T_RU_KNOWN); @@ -1235,7 +1233,7 @@ iwl_mvm_decode_he_phy_ru_alloc(struct iwl_mvm_rx_phy_data *phy_data,  	 * the TSF/timers are not be transmitted in HE-MU.  	 */  	u8 ru = le32_get_bits(phy_data->d1, IWL_RX_PHY_DATA1_HE_RU_ALLOC_MASK); -	u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK; +	u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK_V1;  	u8 offs = 0;  	rx_status->bw = RATE_INFO_BW_HE_RU; @@ -1290,13 +1288,13 @@ iwl_mvm_decode_he_phy_ru_alloc(struct iwl_mvm_rx_phy_data *phy_data,  	if (he_mu)  		he_mu->flags2 |= -			le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK, +			le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK_V1,  						   rate_n_flags),  					 IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW); -	else if (he_type == RATE_MCS_HE_TYPE_TRIG) +	else if (he_type == RATE_MCS_HE_TYPE_TRIG_V1)  		he->data6 |=  			cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_KNOWN) | -			le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK, +			le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK_V1,  						   rate_n_flags),  					 IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW);  } @@ -1508,9 +1506,9 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,  	stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >> RATE_MCS_STBC_POS;  	rx_status->nss = -		((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >> -					RATE_VHT_MCS_NSS_POS) + 1; -	rx_status->rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK; +		((rate_n_flags & RATE_MCS_NSS_MSK) >> +		 RATE_MCS_NSS_POS) + 1; +	rx_status->rate_idx = rate_n_flags & RATE_MCS_CODE_MSK;  	rx_status->encoding = RX_ENC_HE;  	rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;  	if (rate_n_flags & RATE_MCS_BF_MSK) @@ -1562,14 +1560,15 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,  		}  		break;  	case 3: -		if ((he_type == RATE_MCS_HE_TYPE_SU || -		     he_type == RATE_MCS_HE_TYPE_EXT_SU) && -		    rate_n_flags & RATE_MCS_SGI_MSK) -			rx_status->he_gi = NL80211_RATE_INFO_HE_GI_0_8; -		else -			rx_status->he_gi = NL80211_RATE_INFO_HE_GI_3_2; +		rx_status->he_gi = NL80211_RATE_INFO_HE_GI_3_2;  		ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X;  		break; +	case 4: +		rx_status->he_gi = NL80211_RATE_INFO_HE_GI_0_8; +		ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X; +		break; +	default: +		ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN;  	}  	he->data5 |= le16_encode_bits(ltf, @@ -1653,7 +1652,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,  	struct iwl_mvm_rx_phy_data phy_data = {  		.info_type = IWL_RX_PHY_INFO_TYPE_NONE,  	}; -	bool csi = false; +	u32 format; +	bool is_sgi;  	if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))  		return; @@ -1691,6 +1691,13 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,  		phy_data.d2 = desc->v1.phy_data2;  		phy_data.d3 = desc->v1.phy_data3;  	} +	if (iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP, +				    REPLY_RX_MPDU_CMD, 0) < 4) { +		rate_n_flags = iwl_new_rate_from_v1(rate_n_flags); +		IWL_DEBUG_DROP(mvm, "Got old format rate, converting. New rate: 0x%x\n", +			       rate_n_flags); +	} +	format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK;  	len = le16_to_cpu(desc->mpdu_len); @@ -1744,7 +1751,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,  		break;  	} -	if (rate_n_flags & RATE_MCS_HE_MSK) +	if (format == RATE_MCS_HE_MSK)  		iwl_mvm_rx_he(mvm, skb, &phy_data, rate_n_flags,  			      phy_info, queue); @@ -1761,7 +1768,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,  		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;  	}  	/* set the preamble flag if appropriate */ -	if (rate_n_flags & RATE_MCS_CCK_MSK && +	if (format == RATE_MCS_CCK_MSK &&  	    phy_info & IWL_RX_MPDU_PHY_SHORT_PREAMBLE)  		rx_status->enc_flags |= RX_ENC_FLAG_SHORTPRE; @@ -1937,33 +1944,34 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,  		}  	} -	if (!(rate_n_flags & RATE_MCS_CCK_MSK) && -	    rate_n_flags & RATE_MCS_SGI_MSK) +	is_sgi = format == RATE_MCS_HE_MSK ? +		iwl_he_is_sgi(rate_n_flags) : +		rate_n_flags & RATE_MCS_SGI_MSK; + +	if (!(format == RATE_MCS_CCK_MSK) && is_sgi)  		rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI; -	if (rate_n_flags & RATE_HT_MCS_GF_MSK) -		rx_status->enc_flags |= RX_ENC_FLAG_HT_GF;  	if (rate_n_flags & RATE_MCS_LDPC_MSK)  		rx_status->enc_flags |= RX_ENC_FLAG_LDPC; -	if (rate_n_flags & RATE_MCS_HT_MSK) { +	if (format == RATE_MCS_HT_MSK) {  		u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >> -				RATE_MCS_STBC_POS; +			RATE_MCS_STBC_POS;  		rx_status->encoding = RX_ENC_HT; -		rx_status->rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK; +		rx_status->rate_idx = RATE_HT_MCS_INDEX(rate_n_flags);  		rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT; -	} else if (rate_n_flags & RATE_MCS_VHT_MSK) { +	} else if (format == RATE_MCS_VHT_MSK) {  		u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >> -				RATE_MCS_STBC_POS; -		rx_status->nss = -			((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >> -						RATE_VHT_MCS_NSS_POS) + 1; -		rx_status->rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK; +			RATE_MCS_STBC_POS; +			rx_status->nss = +			((rate_n_flags & RATE_MCS_NSS_MSK) >> +			RATE_MCS_NSS_POS) + 1; +		rx_status->rate_idx = rate_n_flags & RATE_MCS_CODE_MSK;  		rx_status->encoding = RX_ENC_VHT;  		rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;  		if (rate_n_flags & RATE_MCS_BF_MSK)  			rx_status->enc_flags |= RX_ENC_FLAG_BF; -	} else if (!(rate_n_flags & RATE_MCS_HE_MSK)) { -		int rate = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags, -							       rx_status->band); +	} else if (!(format == RATE_MCS_HE_MSK)) { +		int rate = iwl_mvm_legacy_hw_idx_to_mac80211_idx(rate_n_flags, +								 rx_status->band);  		if (WARN(rate < 0 || rate > 0xFF,  			 "Invalid rate flags 0x%x, band %d,\n", @@ -1994,7 +2002,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,  	if (!iwl_mvm_reorder(mvm, napi, queue, sta, skb, desc))  		iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, -						sta, csi); +						sta);  out:  	rcu_read_unlock();  } @@ -2013,12 +2021,24 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,  	struct ieee80211_sta *sta = NULL;  	struct sk_buff *skb;  	u8 channel, energy_a, energy_b; +	u32 format;  	struct iwl_mvm_rx_phy_data phy_data = {  		.info_type = le32_get_bits(desc->phy_info[1],  					   IWL_RX_PHY_DATA1_INFO_TYPE_MASK),  		.d0 = desc->phy_info[0],  		.d1 = desc->phy_info[1],  	}; +	bool is_sgi; + +	if (iwl_fw_lookup_notif_ver(mvm->fw, DATA_PATH_GROUP, +				    RX_NO_DATA_NOTIF, 0) < 2) { +		IWL_DEBUG_DROP(mvm, "Got an old rate format. Old rate: 0x%x\n", +			       rate_n_flags); +		rate_n_flags = iwl_new_rate_from_v1(rate_n_flags); +		IWL_DEBUG_DROP(mvm, " Rate after conversion to the new format: 0x%x\n", +			       rate_n_flags); +	} +	format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK;  	if (unlikely(iwl_rx_packet_payload_len(pkt) < sizeof(*desc)))  		return; @@ -2075,7 +2095,7 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,  		break;  	} -	if (rate_n_flags & RATE_MCS_HE_MSK) +	if (format == RATE_MCS_HE_MSK)  		iwl_mvm_rx_he(mvm, skb, &phy_data, rate_n_flags,  			      phy_info, queue); @@ -2091,23 +2111,24 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,  	rcu_read_lock(); -	if (!(rate_n_flags & RATE_MCS_CCK_MSK) && -	    rate_n_flags & RATE_MCS_SGI_MSK) +	is_sgi = format == RATE_MCS_HE_MSK ? +		iwl_he_is_sgi(rate_n_flags) : +		rate_n_flags & RATE_MCS_SGI_MSK; + +	if (!(format == RATE_MCS_CCK_MSK) && is_sgi)  		rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI; -	if (rate_n_flags & RATE_HT_MCS_GF_MSK) -		rx_status->enc_flags |= RX_ENC_FLAG_HT_GF;  	if (rate_n_flags & RATE_MCS_LDPC_MSK)  		rx_status->enc_flags |= RX_ENC_FLAG_LDPC; -	if (rate_n_flags & RATE_MCS_HT_MSK) { +	if (format == RATE_MCS_HT_MSK) {  		u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >>  				RATE_MCS_STBC_POS;  		rx_status->encoding = RX_ENC_HT; -		rx_status->rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK; +		rx_status->rate_idx = RATE_HT_MCS_INDEX(rate_n_flags);  		rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT; -	} else if (rate_n_flags & RATE_MCS_VHT_MSK) { +	} else if (format == RATE_MCS_VHT_MSK) {  		u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >>  				RATE_MCS_STBC_POS; -		rx_status->rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK; +		rx_status->rate_idx = rate_n_flags & RATE_MCS_CODE_MSK;  		rx_status->encoding = RX_ENC_VHT;  		rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;  		if (rate_n_flags & RATE_MCS_BF_MSK) @@ -2120,12 +2141,12 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,  		rx_status->nss =  			le32_get_bits(desc->rx_vec[0],  				      RX_NO_DATA_RX_VEC0_VHT_NSTS_MSK) + 1; -	} else if (rate_n_flags & RATE_MCS_HE_MSK) { +	} else if (format == RATE_MCS_HE_MSK) {  		rx_status->nss =  			le32_get_bits(desc->rx_vec[0],  				      RX_NO_DATA_RX_VEC0_HE_NSTS_MSK) + 1;  	} else { -		int rate = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags, +		int rate = iwl_mvm_legacy_hw_idx_to_mac80211_idx(rate_n_flags,  							       rx_status->band);  		if (WARN(rate < 0 || rate > 0xFF, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index d78e436fa8b5..a138b5c4cce8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -163,7 +163,7 @@ iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum nl80211_band band,  	tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS;  	if (band == NL80211_BAND_2GHZ && !no_cck) -		return cpu_to_le32(IWL_RATE_1M_PLCP | RATE_MCS_CCK_MSK | +		return cpu_to_le32(IWL_RATE_1M_PLCP | RATE_MCS_CCK_MSK_V1 |  				   tx_ant);  	else  		return cpu_to_le32(IWL_RATE_6M_PLCP | tx_ant); @@ -1995,8 +1995,16 @@ static u16 iwl_mvm_scan_umac_flags_v2(struct iwl_mvm *mvm,  {  	u16 flags = 0; +	/* +	 * If no direct SSIDs are provided perform a passive scan. Otherwise, +	 * if there is a single SSID which is not the broadcast SSID, assume +	 * that the scan is intended for roaming purposes and thus enable Rx on +	 * all chains to improve chances of hearing the beacons/probe responses. +	 */  	if (params->n_ssids == 0)  		flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_FORCE_PASSIVE; +	else if (params->n_ssids == 1 && params->ssids[0].ssid_len) +		flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_USE_ALL_RX_CHAINS;  	if (iwl_mvm_is_scan_fragmented(params->type))  		flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC1; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 0a13c2bda2ee..bdd4ee432548 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -268,6 +268,7 @@ static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm,  	int rate_idx = -1;  	u8 rate_plcp;  	u32 rate_flags = 0; +	bool is_cck;  	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);  	/* info->control is only relevant for non HW rate control */ @@ -299,11 +300,18 @@ static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm,  	BUILD_BUG_ON(IWL_FIRST_CCK_RATE != 0);  	/* Get PLCP rate for tx_cmd->rate_n_flags */ -	rate_plcp = iwl_mvm_mac80211_idx_to_hwrate(rate_idx); +	rate_plcp = iwl_mvm_mac80211_idx_to_hwrate(mvm->fw, rate_idx); +	is_cck = (rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE); -	/* Set CCK flag as needed */ -	if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) -		rate_flags |= RATE_MCS_CCK_MSK; +	/* Set CCK or OFDM flag */ +	if (iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP, TX_CMD, 0) > 8) { +		if (!is_cck) +			rate_flags |= RATE_MCS_LEGACY_OFDM_MSK; +		else +			rate_flags |= RATE_MCS_CCK_MSK; +	} else if (is_cck) { +		rate_flags |= RATE_MCS_CCK_MSK_V1; +	}  	return (u32)rate_plcp | rate_flags;  } @@ -1284,31 +1292,72 @@ const char *iwl_mvm_get_tx_fail_reason(u32 status)  }  #endif /* CONFIG_IWLWIFI_DEBUG */ -void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags, -			       enum nl80211_band band, -			       struct ieee80211_tx_rate *r) +static int iwl_mvm_get_hwrate_chan_width(u32 chan_width)  { -	if (rate_n_flags & RATE_HT_MCS_GF_MSK) -		r->flags |= IEEE80211_TX_RC_GREEN_FIELD; -	switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) { +	switch (chan_width) {  	case RATE_MCS_CHAN_WIDTH_20: -		break; +		return 0;  	case RATE_MCS_CHAN_WIDTH_40: -		r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; -		break; +		return IEEE80211_TX_RC_40_MHZ_WIDTH;  	case RATE_MCS_CHAN_WIDTH_80: -		r->flags |= IEEE80211_TX_RC_80_MHZ_WIDTH; -		break; +		return IEEE80211_TX_RC_80_MHZ_WIDTH;  	case RATE_MCS_CHAN_WIDTH_160: -		r->flags |= IEEE80211_TX_RC_160_MHZ_WIDTH; -		break; +		return IEEE80211_TX_RC_160_MHZ_WIDTH; +	default: +		return 0;  	} +} + +void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags, +			       enum nl80211_band band, +			       struct ieee80211_tx_rate *r) +{ +	u32 format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK; +	u32 rate = format == RATE_MCS_HT_MSK ? +		RATE_HT_MCS_INDEX(rate_n_flags) : +		rate_n_flags & RATE_MCS_CODE_MSK; + +	r->flags |= +		iwl_mvm_get_hwrate_chan_width(rate_n_flags & +					      RATE_MCS_CHAN_WIDTH_MSK); +  	if (rate_n_flags & RATE_MCS_SGI_MSK)  		r->flags |= IEEE80211_TX_RC_SHORT_GI; -	if (rate_n_flags & RATE_MCS_HT_MSK) { +	if (format ==  RATE_MCS_HT_MSK) {  		r->flags |= IEEE80211_TX_RC_MCS; -		r->idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK; -	} else if (rate_n_flags & RATE_MCS_VHT_MSK) { +		r->idx = rate; +	} else if (format ==  RATE_MCS_VHT_MSK) { +		ieee80211_rate_set_vht(r, rate, +				       ((rate_n_flags & RATE_MCS_NSS_MSK) >> +					RATE_MCS_NSS_POS) + 1); +		r->flags |= IEEE80211_TX_RC_VHT_MCS; +	} else if (format == RATE_MCS_HE_MSK) { +		/* mac80211 cannot do this without ieee80211_tx_status_ext() +		 * but it only matters for radiotap */ +		r->idx = 0; +	} else { +		r->idx = iwl_mvm_legacy_hw_idx_to_mac80211_idx(rate_n_flags, +							       band); +	} +} + +void iwl_mvm_hwrate_to_tx_rate_v1(u32 rate_n_flags, +				  enum nl80211_band band, +				  struct ieee80211_tx_rate *r) +{ +	if (rate_n_flags & RATE_HT_MCS_GF_MSK) +		r->flags |= IEEE80211_TX_RC_GREEN_FIELD; + +	r->flags |= +		iwl_mvm_get_hwrate_chan_width(rate_n_flags & +					      RATE_MCS_CHAN_WIDTH_MSK_V1); + +	if (rate_n_flags & RATE_MCS_SGI_MSK_V1) +		r->flags |= IEEE80211_TX_RC_SHORT_GI; +	if (rate_n_flags & RATE_MCS_HT_MSK_V1) { +		r->flags |= IEEE80211_TX_RC_MCS; +		r->idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK_V1; +	} else if (rate_n_flags & RATE_MCS_VHT_MSK_V1) {  		ieee80211_rate_set_vht(  			r, rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK,  			((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >> @@ -1323,14 +1372,20 @@ void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,  /*   * translate ucode response to mac80211 tx status control values   */ -static void iwl_mvm_hwrate_to_tx_status(u32 rate_n_flags, +static void iwl_mvm_hwrate_to_tx_status(const struct iwl_fw *fw, +					u32 rate_n_flags,  					struct ieee80211_tx_info *info)  {  	struct ieee80211_tx_rate *r = &info->status.rates[0]; +	if (iwl_fw_lookup_notif_ver(fw, LONG_GROUP, +				    TX_CMD, 0) > 6) +		rate_n_flags = iwl_new_rate_from_v1(rate_n_flags); +  	info->status.antenna = -		((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); -	iwl_mvm_hwrate_to_tx_rate(rate_n_flags, info->band, r); +		((rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS); +	iwl_mvm_hwrate_to_tx_rate(rate_n_flags, +				  info->band, r);  }  static void iwl_mvm_tx_status_check_trigger(struct iwl_mvm *mvm, @@ -1450,7 +1505,9 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,  			/* the FW should have stopped the queue and not  			 * return this status  			 */ -			WARN_ON(1); +			IWL_ERR_LIMIT(mvm, +				      "FW reported TX filtered, status=0x%x, FC=0x%x\n", +				      status, le16_to_cpu(hdr->frame_control));  			info->flags |= IEEE80211_TX_STAT_TX_FILTERED;  			break;  		default: @@ -1472,8 +1529,14 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,  		iwl_mvm_tx_status_check_trigger(mvm, status, hdr->frame_control);  		info->status.rates[0].count = tx_resp->failure_frame + 1; -		iwl_mvm_hwrate_to_tx_status(le32_to_cpu(tx_resp->initial_rate), + +		iwl_mvm_hwrate_to_tx_status(mvm->fw, +					    le32_to_cpu(tx_resp->initial_rate),  					    info); + +		/* Don't assign the converted initial_rate, because driver +		 * TLC uses this and doesn't support the new FW rate +		 */  		info->status.status_driver_data[1] =  			(void *)(uintptr_t)le32_to_cpu(tx_resp->initial_rate); @@ -1835,7 +1898,7 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,  			info->flags |= IEEE80211_TX_STAT_AMPDU;  			memcpy(&info->status, &tx_info->status,  			       sizeof(tx_info->status)); -			iwl_mvm_hwrate_to_tx_status(rate, info); +			iwl_mvm_hwrate_to_tx_status(mvm->fw, rate, info);  		}  	} @@ -1856,7 +1919,7 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,  			goto out;  		tx_info->band = chanctx_conf->def.chan->band; -		iwl_mvm_hwrate_to_tx_status(rate, tx_info); +		iwl_mvm_hwrate_to_tx_status(mvm->fw, rate, tx_info);  		if (!iwl_mvm_has_tlc_offload(mvm)) {  			IWL_DEBUG_TX_REPLY(mvm, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index 4a3d2971a98b..caf1dcf48888 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -135,31 +135,25 @@ int iwl_mvm_send_cmd_pdu_status(struct iwl_mvm *mvm, u32 id, u16 len,  	return iwl_mvm_send_cmd_status(mvm, &cmd, status);  } -#define IWL_DECLARE_RATE_INFO(r) \ -	[IWL_RATE_##r##M_INDEX] = IWL_RATE_##r##M_PLCP +int iwl_mvm_legacy_hw_idx_to_mac80211_idx(u32 rate_n_flags, +					  enum nl80211_band band) +{ +	int format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK; +	int rate = rate_n_flags & RATE_LEGACY_RATE_MSK; +	bool is_LB = band == NL80211_BAND_2GHZ; -/* - * Translate from fw_rate_index (IWL_RATE_XXM_INDEX) to PLCP - */ -static const u8 fw_rate_idx_to_plcp[IWL_RATE_COUNT] = { -	IWL_DECLARE_RATE_INFO(1), -	IWL_DECLARE_RATE_INFO(2), -	IWL_DECLARE_RATE_INFO(5), -	IWL_DECLARE_RATE_INFO(11), -	IWL_DECLARE_RATE_INFO(6), -	IWL_DECLARE_RATE_INFO(9), -	IWL_DECLARE_RATE_INFO(12), -	IWL_DECLARE_RATE_INFO(18), -	IWL_DECLARE_RATE_INFO(24), -	IWL_DECLARE_RATE_INFO(36), -	IWL_DECLARE_RATE_INFO(48), -	IWL_DECLARE_RATE_INFO(54), -}; +	if (format == RATE_MCS_LEGACY_OFDM_MSK) +		return is_LB ? rate + IWL_FIRST_OFDM_RATE : +			rate; + +	/* CCK is not allowed in HB */ +	return is_LB ? rate : -1; +}  int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,  					enum nl80211_band band)  { -	int rate = rate_n_flags & RATE_LEGACY_RATE_MSK; +	int rate = rate_n_flags & RATE_LEGACY_RATE_MSK_V1;  	int idx;  	int band_offset = 0; @@ -167,16 +161,24 @@ int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,  	if (band != NL80211_BAND_2GHZ)  		band_offset = IWL_FIRST_OFDM_RATE;  	for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++) -		if (fw_rate_idx_to_plcp[idx] == rate) +		if (iwl_fw_rate_idx_to_plcp(idx) == rate)  			return idx - band_offset;  	return -1;  } -u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx) +u8 iwl_mvm_mac80211_idx_to_hwrate(const struct iwl_fw *fw, int rate_idx)  { -	/* Get PLCP rate for tx_cmd->rate_n_flags */ -	return fw_rate_idx_to_plcp[rate_idx]; +	if (iwl_fw_lookup_cmd_ver(fw, LONG_GROUP, +				  TX_CMD, 0) > 8) +		/* In the new rate legacy rates are indexed: +		 * 0 - 3 for CCK and 0 - 7 for OFDM. +		 */ +		return (rate_idx >= IWL_FIRST_OFDM_RATE ? +			rate_idx - IWL_FIRST_OFDM_RATE : +			rate_idx); + +	return iwl_fw_rate_idx_to_plcp(rate_idx);  }  u8 iwl_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_ac_numbers ac) @@ -217,6 +219,7 @@ u8 first_antenna(u8 mask)  	return BIT(ffs(mask) - 1);  } +#define MAX_ANT_NUM 2  /*   * Toggles between TX antennas to send the probe request on.   * Receives the bitmask of valid TX antennas and the *index* used @@ -405,6 +408,9 @@ bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm,  	lockdep_assert_held(&mvm->mutex); +	if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM) +		return false; +  	if (num_of_ant(iwl_mvm_get_valid_rx_ant(mvm)) == 1)  		return false; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index 239a722cd79d..85a6da70ca78 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -57,6 +57,10 @@ iwl_pcie_ctxt_info_dbg_enable(struct iwl_trans *trans,  			dbg_flags |= IWL_PRPH_SCRATCH_EDBG_DEST_DRAM;  			dbg_cfg->hwm_base_addr = cpu_to_le64(frag->physical);  			dbg_cfg->hwm_size = cpu_to_le32(frag->size); +			dbg_cfg->debug_token_config = cpu_to_le32(trans->dbg.ucode_preset); +			IWL_DEBUG_FW(trans, +				     "WRT: Applying DRAM destination (debug_token_config=%u)\n", +				     dbg_cfg->debug_token_config);  			IWL_DEBUG_FW(trans,  				     "WRT: Applying DRAM destination (alloc_id=%u, num_frags=%u)\n",  				     alloc_id, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index e3996ff99bad..c574f041f096 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -499,6 +499,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = {  /* Ma devices */  	{IWL_PCI_DEVICE(0x2729, PCI_ANY_ID, iwl_ma_trans_cfg)},  	{IWL_PCI_DEVICE(0x7E40, PCI_ANY_ID, iwl_ma_trans_cfg)}, +	{IWL_PCI_DEVICE(0x7F70, PCI_ANY_ID, iwl_ma_trans_cfg)},  /* Bz devices */  	{IWL_PCI_DEVICE(0x2727, PCI_ANY_ID, iwl_bz_trans_cfg)}, @@ -518,7 +519,7 @@ MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);  #define IWL_DEV_INFO(_device, _subdevice, _cfg, _name) \  	_IWL_DEV_INFO(_device, _subdevice, IWL_CFG_ANY, IWL_CFG_ANY,	   \  		      IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,  \ -		      IWL_CFG_NO_CDB, _cfg, _name) +		      IWL_CFG_ANY, _cfg, _name)  static const struct iwl_dev_info iwl_dev_info_table[] = {  #if IS_ENABLED(CONFIG_IWLMVM) @@ -532,15 +533,25 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {  	IWL_DEV_INFO(0x31DC, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_name),  	IWL_DEV_INFO(0xA370, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_name),  	IWL_DEV_INFO(0xA370, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_name), +	IWL_DEV_INFO(0x54F0, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_160_name), +	IWL_DEV_INFO(0x54F0, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_name),  	IWL_DEV_INFO(0x51F0, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_160_name),  	IWL_DEV_INFO(0x51F0, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_160_name), +	IWL_DEV_INFO(0x51F0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name), +	IWL_DEV_INFO(0x51F0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name), +	IWL_DEV_INFO(0x54F0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name), +	IWL_DEV_INFO(0x54F0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name), +	IWL_DEV_INFO(0x7A70, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name), +	IWL_DEV_INFO(0x7A70, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),  	IWL_DEV_INFO(0x271C, 0x0214, iwl9260_2ac_cfg, iwl9260_1_name), +	IWL_DEV_INFO(0x7E40, 0x1691, iwl_cfg_ma_a0_gf4_a0, iwl_ax411_killer_1690s_name), +	IWL_DEV_INFO(0x7E40, 0x1692, iwl_cfg_ma_a0_gf4_a0, iwl_ax411_killer_1690i_name),  /* AX200 */ +	IWL_DEV_INFO(0x2723, IWL_CFG_ANY, iwl_ax200_cfg_cc, iwl_ax200_name),  	IWL_DEV_INFO(0x2723, 0x1653, iwl_ax200_cfg_cc, iwl_ax200_killer_1650w_name),  	IWL_DEV_INFO(0x2723, 0x1654, iwl_ax200_cfg_cc, iwl_ax200_killer_1650x_name), -	IWL_DEV_INFO(0x2723, IWL_CFG_ANY, iwl_ax200_cfg_cc, iwl_ax200_name),  	/* Qu with Hr */  	IWL_DEV_INFO(0x43F0, 0x0070, iwl_ax201_cfg_qu_hr, NULL), @@ -639,6 +650,12 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {  	IWL_DEV_INFO(0x7AF0, 0x0510, iwlax211_2ax_cfg_so_gf_a0, NULL),  	IWL_DEV_INFO(0x7AF0, 0x0A10, iwlax211_2ax_cfg_so_gf_a0, NULL), +	/* So with JF */ +	IWL_DEV_INFO(0x7A70, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_160_name), +	IWL_DEV_INFO(0x7A70, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_160_name), +	IWL_DEV_INFO(0x7AF0, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_160_name), +	IWL_DEV_INFO(0x7AF0, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_160_name), +  	/* SnJ with HR */  	IWL_DEV_INFO(0x2725, 0x00B0, iwlax411_2ax_cfg_sosnj_gf4_a0, NULL),  	IWL_DEV_INFO(0x2726, 0x0090, iwlax211_cfg_snj_gf_a0, NULL), @@ -648,6 +665,12 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {  	IWL_DEV_INFO(0x2726, 0x0510, iwlax211_cfg_snj_gf_a0, NULL),  	IWL_DEV_INFO(0x2726, 0x1651, iwl_cfg_snj_hr_b0, iwl_ax201_killer_1650s_name),  	IWL_DEV_INFO(0x2726, 0x1652, iwl_cfg_snj_hr_b0, iwl_ax201_killer_1650i_name), +	IWL_DEV_INFO(0x2726, 0x1671, iwlax211_cfg_snj_gf_a0, iwl_ax211_killer_1675s_name), +	IWL_DEV_INFO(0x2726, 0x1672, iwlax211_cfg_snj_gf_a0, iwl_ax211_killer_1675i_name), +	IWL_DEV_INFO(0x2726, 0x1691, iwlax411_2ax_cfg_sosnj_gf4_a0, iwl_ax411_killer_1690s_name), +	IWL_DEV_INFO(0x2726, 0x1692, iwlax411_2ax_cfg_sosnj_gf4_a0, iwl_ax411_killer_1690i_name), +	IWL_DEV_INFO(0x7F70, 0x1691, iwlax411_2ax_cfg_sosnj_gf4_a0, iwl_ax411_killer_1690s_name), +	IWL_DEV_INFO(0x7F70, 0x1692, iwlax411_2ax_cfg_sosnj_gf4_a0, iwl_ax411_killer_1690i_name),  	_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,  		      IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY, @@ -703,17 +726,6 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {  		      iwl9260_2ac_cfg, iwl9462_name),  	_IWL_DEV_INFO(0x2526, IWL_CFG_ANY, -		      IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_ANY, -		      IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, -		      IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, -		      iwl9260_2ac_cfg, iwl9560_160_name), -	_IWL_DEV_INFO(0x2526, IWL_CFG_ANY, -		      IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_ANY, -		      IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, -		      IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, -		      iwl9260_2ac_cfg, iwl9560_name), - -	_IWL_DEV_INFO(0x2526, IWL_CFG_ANY,  		      IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,  		      IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY,  		      IWL_CFG_160, IWL_CFG_CORES_BT_GNSS, IWL_CFG_NO_CDB, @@ -931,9 +943,9 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {  		      IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,  		      iwl_qu_b0_hr1_b0, iwl_ax101_name),  	_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, -		      IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP, +		      IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,  		      IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, -		      IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, +		      IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,  		      iwl_qu_b0_hr_b0, iwl_ax203_name),  	/* Qu C step */ @@ -945,7 +957,7 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {  	_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,  		      IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,  		      IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, -		      IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, +		      IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,  		      iwl_qu_c0_hr_b0, iwl_ax203_name),  	/* QuZ */ @@ -1053,11 +1065,6 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {  		      iwl_cfg_so_a0_hr_a0, iwl_ax203_name),  	_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,  		      IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY, -		      IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, -		      IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, -		      iwl_cfg_so_a0_hr_a0, iwl_ax203_name), -	_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, -		      IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,  		      IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY,  		      IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,  		      iwl_cfg_so_a0_hr_a0, iwl_ax101_name), @@ -1112,6 +1119,50 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {  		      IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY,  		      IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,  		      iwl_cfg_bz_a0_mr_a0, iwl_bz_name), +	_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, +		      IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY, +		      IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, +		      IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, +		      iwl_cfg_bz_a0_fm_a0, iwl_bz_name), +	_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, +		      IWL_CFG_MAC_TYPE_GL, IWL_CFG_ANY, +		      IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, +		      IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, +		      iwl_cfg_gl_a0_fm_a0, iwl_bz_name), + +/* SoF with JF2 */ +	_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, +		      IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, +		      IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, +		      IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, +		      iwlax210_2ax_cfg_so_jf_b0, iwl9560_160_name), +	_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, +		      IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, +		      IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, +		      IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, +		      iwlax210_2ax_cfg_so_jf_b0, iwl9560_name), + +/* SoF with JF */ +	_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, +		      IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, +		      IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, +		      IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, +		      iwlax210_2ax_cfg_so_jf_b0, iwl9461_160_name), +	_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, +		      IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, +		      IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, +		      IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, +		      iwlax210_2ax_cfg_so_jf_b0, iwl9462_160_name), +	_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, +		      IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, +		      IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, +		      IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, +		      iwlax210_2ax_cfg_so_jf_b0, iwl9461_name), +	_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, +		      IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, +		      IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, +		      IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, +		      iwlax210_2ax_cfg_so_jf_b0, iwl9462_name),  /* SoF with JF2 */  	_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, @@ -1191,16 +1242,158 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {  #endif /* CONFIG_IWLMVM */  }; +/* + * In case that there is no OTP on the NIC, get the rf id and cdb info + * from the prph registers. + */ +static int get_crf_id(struct iwl_trans *iwl_trans) +{ +	int ret = 0; +	u32 wfpm_ctrl_addr; +	u32 wfpm_otp_cfg_addr; +	u32 sd_reg_ver_addr; +	u32 cdb = 0; +	u32 val; + +	if (iwl_trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { +		wfpm_ctrl_addr = WFPM_CTRL_REG_GEN2; +		wfpm_otp_cfg_addr = WFPM_OTP_CFG1_ADDR_GEN2; +		sd_reg_ver_addr = SD_REG_VER_GEN2; +	/* Qu/Pu families have other addresses */ +	} else { +		wfpm_ctrl_addr = WFPM_CTRL_REG; +		wfpm_otp_cfg_addr = WFPM_OTP_CFG1_ADDR; +		sd_reg_ver_addr = SD_REG_VER; +	} + +	if (!iwl_trans_grab_nic_access(iwl_trans)) { +		IWL_ERR(iwl_trans, "Failed to grab nic access before reading crf id\n"); +		ret = -EIO; +		goto out; +	} + +	/* Enable access to peripheral registers */ +	val = iwl_read_umac_prph_no_grab(iwl_trans, wfpm_ctrl_addr); +	val |= ENABLE_WFPM; +	iwl_write_umac_prph_no_grab(iwl_trans, wfpm_ctrl_addr, val); + +	/* Read crf info */ +	val = iwl_read_prph_no_grab(iwl_trans, sd_reg_ver_addr); + +	/* Read cdb info (also contains the jacket info if needed in the future */ +	cdb = iwl_read_umac_prph_no_grab(iwl_trans, wfpm_otp_cfg_addr); + +	/* Map between crf id to rf id */ +	switch (REG_CRF_ID_TYPE(val)) { +	case REG_CRF_ID_TYPE_JF_1: +		iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_JF1 << 12); +		break; +	case REG_CRF_ID_TYPE_JF_2: +		iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_JF2 << 12); +		break; +	case REG_CRF_ID_TYPE_HR_NONE_CDB: +		iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_HR1 << 12); +		break; +	case REG_CRF_ID_TYPE_HR_CDB: +		iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_HR2 << 12); +		break; +	case REG_CRF_ID_TYPE_GF: +		iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_GF << 12); +		break; +	case REG_CRF_ID_TYPE_MR: +		iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_MR << 12); +		break; +		case REG_CRF_ID_TYPE_FM: +			iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_FM << 12); +			break; +	default: +		ret = -EIO; +		IWL_ERR(iwl_trans, +			"Can find a correct rfid for crf id 0x%x\n", +			REG_CRF_ID_TYPE(val)); +		goto out_release; + +	} + +	/* Set CDB capabilities */ +	if (cdb & BIT(4)) { +		iwl_trans->hw_rf_id += BIT(28); +		IWL_INFO(iwl_trans, "Adding cdb to rf id\n"); +	} + +	IWL_INFO(iwl_trans, "Detected RF 0x%x from crf id 0x%x\n", +		 iwl_trans->hw_rf_id, REG_CRF_ID_TYPE(val)); + +out_release: +	iwl_trans_release_nic_access(iwl_trans); + +out: +	return ret; +} +  /* PCI registers */  #define PCI_CFG_RETRY_TIMEOUT	0x041 +static const struct iwl_dev_info * +iwl_pci_find_dev_info(u16 device, u16 subsystem_device, +		      u16 mac_type, u8 mac_step, +		      u16 rf_type, u8 cdb, u8 rf_id, u8 no_160, u8 cores) +{ +	int i; + +	for (i = ARRAY_SIZE(iwl_dev_info_table) - 1; i >= 0; i--) { +		const struct iwl_dev_info *dev_info = &iwl_dev_info_table[i]; + +		if (dev_info->device != (u16)IWL_CFG_ANY && +		    dev_info->device != device) +			continue; + +		if (dev_info->subdevice != (u16)IWL_CFG_ANY && +		    dev_info->subdevice != subsystem_device) +			continue; + +		if (dev_info->mac_type != (u16)IWL_CFG_ANY && +		    dev_info->mac_type != mac_type) +			continue; + +		if (dev_info->mac_step != (u8)IWL_CFG_ANY && +		    dev_info->mac_step != mac_step) +			continue; + +		if (dev_info->rf_type != (u16)IWL_CFG_ANY && +		    dev_info->rf_type != rf_type) +			continue; + +		if (dev_info->cdb != (u8)IWL_CFG_ANY && +		    dev_info->cdb != cdb) +			continue; + +		if (dev_info->rf_id != (u8)IWL_CFG_ANY && +		    dev_info->rf_id != rf_id) +			continue; + +		if (dev_info->no_160 != (u8)IWL_CFG_ANY && +		    dev_info->no_160 != no_160) +			continue; + +		if (dev_info->cores != (u8)IWL_CFG_ANY && +		    dev_info->cores != cores) +			continue; + +		return dev_info; +	} + +	return NULL; +} +  static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  {  	const struct iwl_cfg_trans_params *trans;  	const struct iwl_cfg *cfg_7265d __maybe_unused = NULL; +	const struct iwl_dev_info *dev_info;  	struct iwl_trans *iwl_trans;  	struct iwl_trans_pcie *trans_pcie; -	int i, ret; +	int ret;  	const struct iwl_cfg *cfg;  	trans = (void *)(ent->driver_data & ~TRANS_CFG_MARKER); @@ -1222,37 +1415,48 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	trans_pcie = IWL_TRANS_GET_PCIE_TRANS(iwl_trans); +	/* +	 * Let's try to grab NIC access early here. Sometimes, NICs may +	 * fail to initialize, and if that happens it's better if we see +	 * issues early on (and can reprobe, per the logic inside), than +	 * first trying to load the firmware etc. and potentially only +	 * detecting any problems when the first interface is brought up. +	 */ +	ret = iwl_finish_nic_init(iwl_trans); +	if (ret) +		goto out_free_trans; +	if (iwl_trans_grab_nic_access(iwl_trans)) { +		/* all good */ +		iwl_trans_release_nic_access(iwl_trans); +	} else { +		ret = -EIO; +		goto out_free_trans; +	} +  	iwl_trans->hw_rf_id = iwl_read32(iwl_trans, CSR_HW_RF_ID); -	for (i = 0; i < ARRAY_SIZE(iwl_dev_info_table); i++) { -		const struct iwl_dev_info *dev_info = &iwl_dev_info_table[i]; -		if ((dev_info->device == (u16)IWL_CFG_ANY || -		     dev_info->device == pdev->device) && -		    (dev_info->subdevice == (u16)IWL_CFG_ANY || -		     dev_info->subdevice == pdev->subsystem_device) && -		    (dev_info->mac_type == (u16)IWL_CFG_ANY || -		     dev_info->mac_type == -		     CSR_HW_REV_TYPE(iwl_trans->hw_rev)) && -		    (dev_info->mac_step == (u8)IWL_CFG_ANY || -		     dev_info->mac_step == -		     CSR_HW_REV_STEP(iwl_trans->hw_rev)) && -		    (dev_info->rf_type == (u16)IWL_CFG_ANY || -		     dev_info->rf_type == -		     CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id)) && -		    (dev_info->cdb == IWL_CFG_NO_CDB || -		     CSR_HW_RFID_IS_CDB(iwl_trans->hw_rf_id)) && -		    (dev_info->rf_id == (u8)IWL_CFG_ANY || -		     dev_info->rf_id == -		     IWL_SUBDEVICE_RF_ID(pdev->subsystem_device)) && -		    (dev_info->no_160 == (u8)IWL_CFG_ANY || -		     dev_info->no_160 == -		     IWL_SUBDEVICE_NO_160(pdev->subsystem_device)) && -		    (dev_info->cores == (u8)IWL_CFG_ANY || -		     dev_info->cores == -		     IWL_SUBDEVICE_CORES(pdev->subsystem_device))) { -			iwl_trans->cfg = dev_info->cfg; -			iwl_trans->name = dev_info->name; -		} +	/* +	 * The RF_ID is set to zero in blank OTP so read version to +	 * extract the RF_ID. +	 * This is relevant only for family 9000 and up. +	 */ +	if (iwl_trans->trans_cfg->rf_id && +	    iwl_trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_9000 && +	    !CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id) && get_crf_id(iwl_trans)) +		goto out_free_trans; + +	dev_info = iwl_pci_find_dev_info(pdev->device, pdev->subsystem_device, +					 CSR_HW_REV_TYPE(iwl_trans->hw_rev), +					 CSR_HW_REV_STEP(iwl_trans->hw_rev), +					 CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id), +					 CSR_HW_RFID_IS_CDB(iwl_trans->hw_rf_id), +					 IWL_SUBDEVICE_RF_ID(pdev->subsystem_device), +					 IWL_SUBDEVICE_NO_160(pdev->subsystem_device), +					 IWL_SUBDEVICE_CORES(pdev->subsystem_device)); + +	if (dev_info) { +		iwl_trans->cfg = dev_info->cfg; +		iwl_trans->name = dev_info->name;  	}  #if IS_ENABLED(CONFIG_IWLMVM) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 8e45eb38304b..14602d6d6699 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -2149,6 +2149,7 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)  	u32 inta_fh_msk = ~MSIX_FH_INT_CAUSES_DATA_QUEUE;  	u32 inta_fh, inta_hw;  	bool polling = false; +	bool sw_err;  	if (trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_NON_RX)  		inta_fh_msk |= MSIX_FH_INT_CAUSES_Q0; @@ -2221,9 +2222,13 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)  		wake_up(&trans_pcie->ucode_write_waitq);  	} +	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) +		sw_err = inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ; +	else +		sw_err = inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR; +  	/* Error detected by uCode */ -	if ((inta_fh & MSIX_FH_INT_CAUSES_FH_ERR) || -	    (inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR)) { +	if ((inta_fh & MSIX_FH_INT_CAUSES_FH_ERR) || sw_err) {  		IWL_ERR(trans,  			"Microcode SW error detected. Restarting 0x%X.\n",  			inta_fh); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c index bf0c32a74ca4..645cb4dd4e5a 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c @@ -47,7 +47,7 @@ int iwl_pcie_gen2_apm_init(struct iwl_trans *trans)  	iwl_pcie_apm_config(trans); -	ret = iwl_finish_nic_init(trans, trans->trans_cfg); +	ret = iwl_finish_nic_init(trans);  	if (ret)  		return ret; @@ -131,21 +131,9 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)  	if (trans_pcie->is_down)  		return; -	if (trans->state >= IWL_TRANS_FW_STARTED) { -		if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { -			iwl_set_bit(trans, CSR_GP_CNTRL, -				    CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_REQ); -			iwl_poll_bit(trans, CSR_GP_CNTRL, -				     CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS, -				     CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS, -				     5000); -			msleep(100); -			iwl_set_bit(trans, CSR_GP_CNTRL, -				    CSR_GP_CNTRL_REG_FLAG_SW_RESET); -		} else if (trans_pcie->fw_reset_handshake) { +	if (trans->state >= IWL_TRANS_FW_STARTED) +		if (trans_pcie->fw_reset_handshake)  			iwl_trans_pcie_fw_reset_handshake(trans); -		} -	}  	trans_pcie->is_down = true; @@ -175,18 +163,6 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)  	else  		iwl_pcie_ctxt_info_free(trans); -	/* Make sure (redundant) we've released our request to stay awake */ -	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) -		iwl_clear_bit(trans, CSR_GP_CNTRL, -			      CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ); -	else -		iwl_clear_bit(trans, CSR_GP_CNTRL, -			      CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - -	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { -		iwl_set_bit(trans, CSR_GP_CNTRL, -			    CSR_GP_CNTRL_REG_FLAG_SW_RESET); -	}  	/* Stop the device, and put it in low power state */  	iwl_pcie_gen2_apm_stop(trans, false); @@ -466,13 +442,15 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,  	iwl_pcie_set_ltr(trans); -	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) +	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { +		iwl_write32(trans, CSR_FUNC_SCRATCH, CSR_FUNC_SCRATCH_INIT_VALUE);  		iwl_set_bit(trans, CSR_GP_CNTRL,  			    CSR_GP_CNTRL_REG_FLAG_ROM_START); -	else if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) +	} else if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {  		iwl_write_umac_prph(trans, UREG_CPU_INIT_RUN, 1); -	else +	} else {  		iwl_write_prph(trans, UREG_CPU_INIT_RUN, 1); +	}  	/* re-check RF-Kill state since we may have missed the interrupt */  	hw_rfkill = iwl_pcie_check_hw_rf_kill(trans); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index f252680f18e8..1efb53f78a62 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -129,7 +129,12 @@ out:  static void iwl_trans_pcie_sw_reset(struct iwl_trans *trans)  {  	/* Reset entire device - do controller reset (results in SHRD_HW_RST) */ -	iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); +	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) +		iwl_set_bit(trans, CSR_GP_CNTRL, +			    CSR_GP_CNTRL_REG_FLAG_SW_RESET); +	else +		iwl_set_bit(trans, CSR_RESET, +			    CSR_RESET_REG_FLAG_SW_RESET);  	usleep_range(5000, 6000);  } @@ -306,7 +311,7 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans)  	if (trans->trans_cfg->base_params->pll_cfg)  		iwl_set_bit(trans, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); -	ret = iwl_finish_nic_init(trans, trans->trans_cfg); +	ret = iwl_finish_nic_init(trans);  	if (ret)  		return ret; @@ -378,7 +383,7 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans)  	iwl_trans_pcie_sw_reset(trans); -	ret = iwl_finish_nic_init(trans, trans->trans_cfg); +	ret = iwl_finish_nic_init(trans);  	if (WARN_ON(ret)) {  		/* Release XTAL ON request */  		__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, @@ -458,6 +463,7 @@ void iwl_pcie_apm_stop_master(struct iwl_trans *trans)  				   CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS,  				   CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS,  				   100); +		msleep(100);  	} else {  		iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); @@ -1056,7 +1062,7 @@ struct iwl_causes_list {  	u8 addr;  }; -static struct iwl_causes_list causes_list[] = { +static const struct iwl_causes_list causes_list_common[] = {  	{MSIX_FH_INT_CAUSES_D2S_CH0_NUM,	CSR_MSIX_FH_INT_MASK_AD, 0},  	{MSIX_FH_INT_CAUSES_D2S_CH1_NUM,	CSR_MSIX_FH_INT_MASK_AD, 0x1},  	{MSIX_FH_INT_CAUSES_S2D,		CSR_MSIX_FH_INT_MASK_AD, 0x3}, @@ -1067,30 +1073,50 @@ static struct iwl_causes_list causes_list[] = {  	{MSIX_HW_INT_CAUSES_REG_CT_KILL,	CSR_MSIX_HW_INT_MASK_AD, 0x16},  	{MSIX_HW_INT_CAUSES_REG_RF_KILL,	CSR_MSIX_HW_INT_MASK_AD, 0x17},  	{MSIX_HW_INT_CAUSES_REG_PERIODIC,	CSR_MSIX_HW_INT_MASK_AD, 0x18}, -	{MSIX_HW_INT_CAUSES_REG_SW_ERR,		CSR_MSIX_HW_INT_MASK_AD, 0x29},  	{MSIX_HW_INT_CAUSES_REG_SCD,		CSR_MSIX_HW_INT_MASK_AD, 0x2A},  	{MSIX_HW_INT_CAUSES_REG_FH_TX,		CSR_MSIX_HW_INT_MASK_AD, 0x2B},  	{MSIX_HW_INT_CAUSES_REG_HW_ERR,		CSR_MSIX_HW_INT_MASK_AD, 0x2D},  	{MSIX_HW_INT_CAUSES_REG_HAP,		CSR_MSIX_HW_INT_MASK_AD, 0x2E},  }; +static const struct iwl_causes_list causes_list_pre_bz[] = { +	{MSIX_HW_INT_CAUSES_REG_SW_ERR,		CSR_MSIX_HW_INT_MASK_AD, 0x29}, +}; + +static const struct iwl_causes_list causes_list_bz[] = { +	{MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ,	CSR_MSIX_HW_INT_MASK_AD, 0x29}, +}; + +static void iwl_pcie_map_list(struct iwl_trans *trans, +			      const struct iwl_causes_list *causes, +			      int arr_size, int val) +{ +	int i; + +	for (i = 0; i < arr_size; i++) { +		iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val); +		iwl_clear_bit(trans, causes[i].mask_reg, +			      causes[i].cause_num); +	} +} +  static void iwl_pcie_map_non_rx_causes(struct iwl_trans *trans)  {  	struct iwl_trans_pcie *trans_pcie =  IWL_TRANS_GET_PCIE_TRANS(trans);  	int val = trans_pcie->def_irq | MSIX_NON_AUTO_CLEAR_CAUSE; -	int i, arr_size = ARRAY_SIZE(causes_list); -	struct iwl_causes_list *causes = causes_list; -  	/*  	 * Access all non RX causes and map them to the default irq.  	 * In case we are missing at least one interrupt vector,  	 * the first interrupt vector will serve non-RX and FBQ causes.  	 */ -	for (i = 0; i < arr_size; i++) { -		iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val); -		iwl_clear_bit(trans, causes[i].mask_reg, -			      causes[i].cause_num); -	} +	iwl_pcie_map_list(trans, causes_list_common, +			  ARRAY_SIZE(causes_list_common), val); +	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) +		iwl_pcie_map_list(trans, causes_list_bz, +				  ARRAY_SIZE(causes_list_bz), val); +	else +		iwl_pcie_map_list(trans, causes_list_pre_bz, +				  ARRAY_SIZE(causes_list_pre_bz), val);  }  static void iwl_pcie_map_rx_causes(struct iwl_trans *trans) @@ -1208,8 +1234,12 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans)  	}  	/* Make sure (redundant) we've released our request to stay awake */ -	iwl_clear_bit(trans, CSR_GP_CNTRL, -		      CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); +	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) +		iwl_clear_bit(trans, CSR_GP_CNTRL, +			      CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ); +	else +		iwl_clear_bit(trans, CSR_GP_CNTRL, +			      CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);  	/* Stop the device, and put it in low power state */  	iwl_pcie_apm_stop(trans, false); @@ -1501,7 +1531,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,  	iwl_set_bit(trans, CSR_GP_CNTRL,  		    CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); -	ret = iwl_finish_nic_init(trans, trans->trans_cfg); +	ret = iwl_finish_nic_init(trans);  	if (ret)  		return ret; @@ -1734,7 +1764,7 @@ static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans)  {  	int ret; -	ret = iwl_finish_nic_init(trans, trans->trans_cfg); +	ret = iwl_finish_nic_init(trans);  	if (ret < 0)  		return ret; @@ -2140,9 +2170,12 @@ static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans)  	if (trans_pcie->cmd_hold_nic_awake)  		goto out; - -	__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, -				   CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); +	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) +		__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, +					   CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ); +	else +		__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, +					   CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);  	/*  	 * Above we read the CSR_GP_CNTRL register, which will flush  	 * any previous writes, but we need the write that clears the @@ -3203,9 +3236,11 @@ static int iwl_trans_get_fw_monitor_len(struct iwl_trans *trans, u32 *len)  	return 0;  } -static struct iwl_trans_dump_data -*iwl_trans_pcie_dump_data(struct iwl_trans *trans, -			  u32 dump_mask) +static struct iwl_trans_dump_data * +iwl_trans_pcie_dump_data(struct iwl_trans *trans, +			 u32 dump_mask, +			 const struct iwl_dump_sanitize_ops *sanitize_ops, +			 void *sanitize_ctx)  {  	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);  	struct iwl_fw_error_dump_data *data; @@ -3305,6 +3340,10 @@ static struct iwl_trans_dump_data  				txcmd->caplen = cpu_to_le32(caplen);  				memcpy(txcmd->data, cmdq->entries[idx].cmd,  				       caplen); +				if (sanitize_ops && sanitize_ops->frob_hcmd) +					sanitize_ops->frob_hcmd(sanitize_ctx, +								txcmd->data, +								caplen);  				txcmd = (void *)((u8 *)txcmd->data + caplen);  			} @@ -3365,7 +3404,10 @@ static void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans)  	if (trans_pcie->msix_enabled) {  		inta_addr = CSR_MSIX_HW_INT_CAUSES_AD; -		sw_err_bit = MSIX_HW_INT_CAUSES_REG_SW_ERR; +		if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) +			sw_err_bit = MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ; +		else +			sw_err_bit = MSIX_HW_INT_CAUSES_REG_SW_ERR;  	} else {  		inta_addr = CSR_INT;  		sw_err_bit = CSR_INT_BIT_SW_ERR; | 
