| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/09/26 16:31 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"KMSANReasoning": "",
"NeedsKMSAN": false,
"Reasoning": "The patch series exclusively modifies the Intel Wi-Fi driver (`drivers/net/wireless/intel/iwlwifi`), including PCIe transport handling, firmware interaction, power/SAR regulatory management, and MVM/MLD operations. This driver requires physical Intel PCIe Wi-Fi hardware that is not emulated in standard virtualized fuzzing environments (QEMU/GCE), making the modified code structurally unreachable.",
"WorthFuzzing": false
} |
| 1/1 | 2026/09/26 16:31 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 4d6d8f627d2307e510beb8f5bc1dc4bffd96cf51\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Sat Sep 26 16:31:13 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/wireless/intel/iwlwifi/Makefile b/drivers/net/wireless/intel/iwlwifi/Makefile\nindex 2a74efe09cf01..6746281350e0e 100644\n--- a/drivers/net/wireless/intel/iwlwifi/Makefile\n+++ b/drivers/net/wireless/intel/iwlwifi/Makefile\n@@ -9,9 +9,9 @@ iwlwifi-objs\t\t+= iwl-utils.o\n iwlwifi-objs\t\t+= iwl-phy-db.o iwl-nvm-parse.o\n \n # Bus\n-iwlwifi-objs\t\t+= pcie/ctxt-info.o pcie/ctxt-info-v2.o pcie/drv.o pcie/utils.o\n-iwlwifi-objs\t\t+= pcie/gen1_2/rx.o pcie/gen1_2/tx.o pcie/gen1_2/trans.o\n-iwlwifi-objs\t\t+= pcie/gen1_2/trans-gen2.o pcie/gen1_2/tx-gen2.o\n+iwlwifi-objs\t\t+= pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o\n+iwlwifi-objs\t\t+= pcie/ctxt-info.o pcie/ctxt-info-v2.o pcie/trans-gen2.o pcie/tx-gen2.o\n+iwlwifi-objs\t\t+= pcie/utils.o\n \n CFLAGS_pcie/drv.o += -Wno-override-init\n \ndiff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h\nindex b17babef71c01..3fbcb2e4bfe06 100644\n--- a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h\n+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h\n@@ -522,17 +522,34 @@ struct iwl_rx_baid_cfg_cmd_alloc {\n } __packed; /* RX_BAID_ALLOCATION_ADD_CMD_API_S_VER_1 */\n \n /**\n- * struct iwl_rx_baid_cfg_cmd_modify - BAID modification data\n+ * struct iwl_rx_baid_cfg_cmd_modify_v2 - BAID modification data\n * @old_sta_id_mask: old station ID mask\n * @new_sta_id_mask: new station ID mask\n * @tid: TID of the BAID\n */\n-struct iwl_rx_baid_cfg_cmd_modify {\n+struct iwl_rx_baid_cfg_cmd_modify_v2 {\n \t__le32 old_sta_id_mask;\n \t__le32 new_sta_id_mask;\n \t__le32 tid;\n } __packed; /* RX_BAID_ALLOCATION_MODIFY_CMD_API_S_VER_2 */\n \n+/**\n+ * struct iwl_rx_baid_cfg_cmd_modify - BAID modification data\n+ * @old_sta_id_mask: old station ID mask\n+ * @new_sta_id_mask: new station ID mask\n+ * @tid: TID of the BAID\n+ * @reserved: reserved\n+ * @win_size: RX BA session window size to apply to the modified BAID,\n+ *\t0 means keep the current one\n+ */\n+struct iwl_rx_baid_cfg_cmd_modify {\n+\t__le32 old_sta_id_mask;\n+\t__le32 new_sta_id_mask;\n+\tu8 tid;\n+\tu8 reserved;\n+\t__le16 win_size;\n+} __packed; /* RX_BAID_ALLOCATION_MODIFY_CMD_API_S_VER_3 */\n+\n /**\n * struct iwl_rx_baid_cfg_cmd_remove_v1 - BAID removal data\n * @baid: the BAID to remove\n@@ -555,7 +572,8 @@ struct iwl_rx_baid_cfg_cmd_remove {\n * struct iwl_rx_baid_cfg_cmd - BAID allocation/config command\n * @action: the action, from \u0026enum iwl_rx_baid_action\n * @alloc: allocation data\n- * @modify: modify data\n+ * @modify_v2: modify data (version 2)\n+ * @modify: modify data (version 3)\n * @remove_v1: remove data (version 1)\n * @remove: remove data\n */\n@@ -563,11 +581,12 @@ struct iwl_rx_baid_cfg_cmd {\n \t__le32 action;\n \tunion {\n \t\tstruct iwl_rx_baid_cfg_cmd_alloc alloc;\n+\t\tstruct iwl_rx_baid_cfg_cmd_modify_v2 modify_v2;\n \t\tstruct iwl_rx_baid_cfg_cmd_modify modify;\n \t\tstruct iwl_rx_baid_cfg_cmd_remove_v1 remove_v1;\n \t\tstruct iwl_rx_baid_cfg_cmd_remove remove;\n-\t}; /* RX_BAID_ALLOCATION_OPERATION_API_U_VER_2 */\n-} __packed; /* RX_BAID_ALLOCATION_CONFIG_CMD_API_S_VER_2 */\n+\t}; /* RX_BAID_ALLOCATION_OPERATION_API_U_VER_3 */\n+} __packed; /* RX_BAID_ALLOCATION_CONFIG_CMD_API_S_VER_3 */\n \n /**\n * struct iwl_rx_baid_cfg_resp - BAID allocation response\ndiff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h\nindex 115e65ba19f8c..4d54a95b98ca6 100644\n--- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h\n+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h\n@@ -300,7 +300,8 @@ enum iwl_dev_tx_power_cmd_mode {\n \tIWL_TX_POWER_MODE_SET_ACK = 3,\n \tIWL_TX_POWER_MODE_SET_SAR_TIMER = 4,\n \tIWL_TX_POWER_MODE_SET_SAR_TIMER_DEFAULT_TABLE = 5,\n-}; /* TX_POWER_REDUCED_FLAGS_TYPE_API_E_VER_5 */;\n+\tIWL_TX_POWER_MODE_SET_STANDALONE_CHAINS = 8, /* cmd ver 12+ */\n+}; /* TX_POWER_REDUCED_FLAGS_TYPE_API_E_VER_2 */;\n \n #define IWL_NUM_CHAIN_TABLES\t1\n #define IWL_NUM_CHAIN_TABLES_V2\t2\n@@ -464,31 +465,34 @@ struct iwl_dev_tx_power_cmd_v10 {\n \t__le32 flags;\n } __packed; /* TX_REDUCED_POWER_API_S_VER_10 */\n \n-struct iwl_dev_tx_power_cmd_v11 {\n+struct iwl_dev_tx_power_cmd_v12 {\n \t__le16 per_chain[IWL_NUM_CHAIN_TABLES_V2][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V3];\n \tu8 per_chain_restriction_changed;\n \tu8 reserved;\n \t__le32 timer_period;\n \t__le32 flags;\n-} __packed; /* TX_REDUCED_POWER_API_S_VER_11 */\n+} __packed; /* TX_REDUCED_POWER_API_S_VER_11\n+\t * TX_REDUCED_POWER_API_S_VER_12\n+\t */\n \n /*\n * struct iwl_dev_tx_power_cmd - TX power reduction command (multiversion)\n * @common: common part of the command\n * @v9: version 9 part of the command\n * @v10: version 10 part of the command\n- * @v11: version 11 part of the command\n+ * @v12: version 12 part of the command (also covers v11)\n */\n struct iwl_dev_tx_power_cmd {\n \tstruct iwl_dev_tx_power_common common;\n \tunion {\n \t\tstruct iwl_dev_tx_power_cmd_v9 v9;\n \t\tstruct iwl_dev_tx_power_cmd_v10 v10;\n-\t\tstruct iwl_dev_tx_power_cmd_v11 v11;\n+\t\tstruct iwl_dev_tx_power_cmd_v12 v12;\n \t};\n } __packed; /* TX_REDUCED_POWER_API_S_VER_9\n \t * TX_REDUCED_POWER_API_S_VER_10\n \t * TX_REDUCED_POWER_API_S_VER_11\n+\t * TX_REDUCED_POWER_API_S_VER_12\n \t */\n \n #define IWL_NUM_GEO_PROFILES\t\t3\ndiff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h\nindex a8f1edf19bbef..20460534fc99d 100644\n--- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h\n+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h\n@@ -583,7 +583,11 @@ struct iwl_rx_mpdu_desc_v3 {\n \t/**\n \t * @reserved_xsum: reserved high bits in the raw checksum\n \t */\n-\t__le16 reserved_xsum;\n+\tu8 reserved_xsum;\n+\t/**\n+\t * @mac_context: MAC context mask, in this DW only from API version 10\n+\t */\n+\tu8 mac_context;\n \t/* DW11 */\n \t/**\n \t * @rate_n_flags: RX rate/flags encoding\n@@ -603,9 +607,10 @@ struct iwl_rx_mpdu_desc_v3 {\n \t */\n \tu8 channel;\n \t/**\n-\t * @mac_context: MAC context mask\n+\t * @ru: RU/MRU/DRU used for the frame, in trigger-like format;\n+\t *\tonly from API version 10, this byte held @mac_context before\n \t */\n-\tu8 mac_context;\n+\tu8 ru;\n \t/* DW13 */\n \t/**\n \t * @gp2_on_air_rise: GP2 timer value on air rise (INA)\n@@ -647,7 +652,11 @@ struct iwl_rx_mpdu_desc_v3 {\n \t__le32 reserved[1];\n } __packed; /* RX_MPDU_RES_START_API_S_VER_3,\n \t * RX_MPDU_RES_START_API_S_VER_5,\n-\t * RX_MPDU_RES_START_API_S_VER_6\n+\t * RX_MPDU_RES_START_API_S_VER_6,\n+\t * RX_MPDU_RES_START_API_S_VER_7,\n+\t * RX_MPDU_RES_START_API_S_VER_8,\n+\t * RX_MPDU_RES_START_API_S_VER_9,\n+\t * RX_MPDU_RES_START_API_S_VER_10\n \t */\n \n /**\n@@ -737,6 +746,8 @@ struct iwl_rx_mpdu_desc {\n \t * RX_MPDU_RES_START_API_S_VER_6\n \t * RX_MPDU_RES_START_API_S_VER_7\n \t * RX_MPDU_RES_START_API_S_VER_8\n+\t * RX_MPDU_RES_START_API_S_VER_9\n+\t * RX_MPDU_RES_START_API_S_VER_10\n \t */\n \n #define IWL_RX_DESC_SIZE_V1 offsetofend(struct iwl_rx_mpdu_desc, v1)\ndiff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c\nindex 8c8d15ac71ac0..897538066b7de 100644\n--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c\n+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c\n@@ -2055,7 +2055,7 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,\n \t\tif (trigger-\u003eflags \u0026 IWL_FW_DBG_FORCE_RESTART) {\n \t\t\tIWL_WARN(fwrt, \"Force restart: trigger %d fired.\\n\",\n \t\t\t\t trig);\n-\t\t\tiwl_force_nmi(fwrt-\u003etrans);\n+\t\t\tiwl_trans_force_nmi(fwrt-\u003etrans);\n \t\t\treturn 0;\n \t\t}\n \n@@ -2233,7 +2233,8 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx)\n \t}\n \n \tif (fwrt-\u003etrans-\u003edbg.last_tp_resetfw == IWL_FW_INI_RESET_FW_MODE_STOP_FW_ONLY)\n-\t\tiwl_force_nmi(fwrt-\u003etrans);\n+\t\tiwl_trans_force_nmi(fwrt-\u003etrans);\n+\n out:\n \tif (iwl_trans_dbg_ini_valid(fwrt-\u003etrans)) {\n \t\tiwl_fw_error_dump_data_free(dump_data);\ndiff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c\nindex 137303e4a29bc..c7de45323935e 100644\n--- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c\n+++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c\n@@ -49,11 +49,16 @@ static const struct dmi_system_id dmi_ppag_approved_list[] = {\n \t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"HP\"),\n \t\t},\n \t},\n-\t{ .ident = \"SAMSUNG\",\n+\t{ .ident = \"SAMSUNG_ELECTRONICS\",\n \t .matches = {\n \t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"SAMSUNG ELECTRONICS CO., LTD\"),\n \t\t},\n \t},\n+\t{ .ident = \"SAMSUNG\",\n+\t .matches = {\n+\t\t\tDMI_EXACT_MATCH(DMI_SYS_VENDOR, \"Samsung\"),\n+\t\t},\n+\t},\n \t{ .ident = \"MSFT\",\n \t .matches = {\n \t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Microsoft Corporation\"),\n@@ -126,10 +131,15 @@ static const struct dmi_system_id dmi_tas_approved_list[] = {\n \t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"HP\"),\n \t\t},\n \t},\n-\t{ .ident = \"SAMSUNG\",\n+\t{ .ident = \"SAMSUNG_ELECTRONICS\",\n \t .matches = {\n \t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"SAMSUNG ELECTRONICS CO., LTD\"),\n \t\t},\n+\t},\n+\t{ .ident = \"SAMSUNG\",\n+\t .matches = {\n+\t\t\tDMI_EXACT_MATCH(DMI_SYS_VENDOR, \"Samsung\"),\n+\t\t},\n \t},\n \t\t{ .ident = \"LENOVO\",\n \t .matches = {\n@@ -247,17 +257,22 @@ IWL_EXPORT_SYMBOL(iwl_sar_geo_fill_table);\n \n static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt,\n \t\t\t __le16 *per_chain, u32 n_subbands,\n-\t\t\t int prof_a, int prof_b)\n+\t\t\t int prof_a, int prof_b,\n+\t\t\t const struct iwl_sar_profile *profiles,\n+\t\t\t bool is_standalone)\n {\n \tint profs[BIOS_SAR_NUM_CHAINS] = { prof_a, prof_b };\n \tint i, j;\n \n+\tBUILD_BUG_ON(ARRAY_SIZE(fwrt-\u003esar_standalone_profiles[0].chains[0].subbands) !=\n+\t\t ARRAY_SIZE(fwrt-\u003esar_profiles[0].chains[0].subbands));\n+\n \tif (WARN_ON_ONCE(n_subbands \u003e\n \t\t\t ARRAY_SIZE(fwrt-\u003esar_profiles[0].chains[0].subbands)))\n \t\treturn -EINVAL;\n \n \tfor (i = 0; i \u003c BIOS_SAR_NUM_CHAINS; i++) {\n-\t\tstruct iwl_sar_profile *prof;\n+\t\tconst struct iwl_sar_profile *prof;\n \n \t\t/* don't allow SAR to be disabled (profile 0 means disable) */\n \t\tif (profs[i] == 0)\n@@ -268,11 +283,13 @@ static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt,\n \t\t\treturn -EINVAL;\n \n \t\t/* profiles go from 1 to 4, so decrement to access the array */\n-\t\tprof = \u0026fwrt-\u003esar_profiles[profs[i] - 1];\n+\t\tprof = \u0026profiles[profs[i] - 1];\n \n \t\t/* if the profile is disabled, do nothing */\n \t\tif (!prof-\u003eenabled) {\n-\t\t\tIWL_DEBUG_RADIO(fwrt, \"SAR profile %d is disabled.\\n\",\n+\t\t\tIWL_DEBUG_RADIO(fwrt,\n+\t\t\t\t\t\"SAR %sprofile %d is disabled.\\n\",\n+\t\t\t\t\tis_standalone ? \"standalone \" : \"\",\n \t\t\t\t\tprofs[i]);\n \t\t\t/*\n \t\t\t * if one of the profiles is disabled, we\n@@ -282,8 +299,8 @@ static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt,\n \t\t\treturn 1;\n \t\t}\n \n-\t\tIWL_DEBUG_INFO(fwrt,\n-\t\t\t \"SAR EWRD: chain %d profile index %d\\n\",\n+\t\tIWL_DEBUG_INFO(fwrt, \"SAR %s: chain %d profile index %d\\n\",\n+\t\t\t is_standalone ? \"standalone\" : \"EWRD\",\n \t\t\t i, profs[i]);\n \t\tIWL_DEBUG_RADIO(fwrt, \" Chain[%d]:\\n\", i);\n \t\tfor (j = 0; j \u003c n_subbands; j++) {\n@@ -299,14 +316,17 @@ static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt,\n \n int iwl_sar_fill_profile(struct iwl_fw_runtime *fwrt,\n \t\t\t __le16 *per_chain, u32 n_tables, u32 n_subbands,\n-\t\t\t int prof_a, int prof_b)\n+\t\t\t int prof_a, int prof_b,\n+\t\t\t const struct iwl_sar_profile *profiles,\n+\t\t\t bool is_standalone)\n {\n \tint i, ret = 0;\n \n \tfor (i = 0; i \u003c n_tables; i++) {\n \t\tret = iwl_sar_fill_table(fwrt,\n \t\t\t\u0026per_chain[i * n_subbands * BIOS_SAR_NUM_CHAINS],\n-\t\t\tn_subbands, prof_a, prof_b);\n+\t\t\tn_subbands, prof_a, prof_b, profiles,\n+\t\t\tis_standalone);\n \t\tif (ret)\n \t\t\tbreak;\n \t}\ndiff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h\nindex bd7ea0ff3d19b..e32e107812b1a 100644\n--- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h\n+++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h\n@@ -210,7 +210,9 @@ int iwl_sar_geo_fill_table(struct iwl_fw_runtime *fwrt,\n \n int iwl_sar_fill_profile(struct iwl_fw_runtime *fwrt,\n \t\t\t __le16 *per_chain, u32 n_tables, u32 n_subbands,\n-\t\t\t int prof_a, int prof_b);\n+\t\t\t int prof_a, int prof_b,\n+\t\t\t const struct iwl_sar_profile *profiles,\n+\t\t\t bool is_standalone);\n \n bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt);\n \ndiff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c\nindex 79fd95d08732b..dffd5e68f41da 100644\n--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c\n+++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c\n@@ -251,15 +251,24 @@ static int iwl_uefi_reduce_power_section(struct iwl_trans *trans,\n \tmemset(pnvm_data, 0, sizeof(*pnvm_data));\n \n \twhile (len \u003e= sizeof(*tlv)) {\n-\t\tu32 tlv_len, tlv_type;\n+\t\tu32 tlv_len, tlv_type, tlv_len_aligned;\n \n \t\tlen -= sizeof(*tlv);\n \t\ttlv = (const void *)data;\n \n \t\ttlv_len = le32_to_cpu(tlv-\u003elength);\n \t\ttlv_type = le32_to_cpu(tlv-\u003etype);\n+\t\ttlv_len_aligned = ALIGN(tlv_len, 4);\n \n-\t\tif (len \u003c tlv_len) {\n+\t\t/* Make sure ALIGN() did not overflow for a malformed TLV length. */\n+\t\tif (tlv_len_aligned \u003c tlv_len) {\n+\t\t\tIWL_ERR(trans,\n+\t\t\t\t\"TLV len overflows on alignment: %u\\n\",\n+\t\t\t\ttlv_len);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tif (len \u003c tlv_len_aligned) {\n \t\t\tIWL_ERR(trans, \"invalid TLV len: %zd/%u\\n\",\n \t\t\t\tlen, tlv_len);\n \t\t\treturn -EINVAL;\n@@ -278,13 +287,13 @@ static int iwl_uefi_reduce_power_section(struct iwl_trans *trans,\n \t\t\t\t \"New REDUCE_POWER section started, stop parsing.\\n\");\n \t\t\tgoto done;\n \t\tdefault:\n-\t\t\tIWL_DEBUG_FW(trans, \"Found TLV 0x%0x, len %d\\n\",\n+\t\t\tIWL_DEBUG_FW(trans, \"Found TLV 0x%0x, len %u\\n\",\n \t\t\t\t tlv_type, tlv_len);\n \t\t\tbreak;\n \t\t}\n \n-\t\tlen -= ALIGN(tlv_len, 4);\n-\t\tdata += ALIGN(tlv_len, 4);\n+\t\tlen -= tlv_len_aligned;\n+\t\tdata += tlv_len_aligned;\n \t}\n \n done:\n@@ -305,15 +314,24 @@ int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,\n \tIWL_DEBUG_FW(trans, \"Parsing REDUCE_POWER data\\n\");\n \n \twhile (len \u003e= sizeof(*tlv)) {\n-\t\tu32 tlv_len, tlv_type;\n+\t\tu32 tlv_len, tlv_type, tlv_len_aligned;\n \n \t\tlen -= sizeof(*tlv);\n \t\ttlv = (const void *)data;\n \n \t\ttlv_len = le32_to_cpu(tlv-\u003elength);\n \t\ttlv_type = le32_to_cpu(tlv-\u003etype);\n+\t\ttlv_len_aligned = ALIGN(tlv_len, 4);\n+\n+\t\t/* Make sure ALIGN() did not overflow for a malformed TLV length. */\n+\t\tif (tlv_len_aligned \u003c tlv_len) {\n+\t\t\tIWL_ERR(trans,\n+\t\t\t\t\"TLV len overflows on alignment: %u\\n\",\n+\t\t\t\ttlv_len);\n+\t\t\treturn -EINVAL;\n+\t\t}\n \n-\t\tif (len \u003c tlv_len) {\n+\t\tif (len \u003c tlv_len_aligned) {\n \t\t\tIWL_ERR(trans, \"invalid TLV len: %zd/%u\\n\",\n \t\t\t\tlen, tlv_len);\n \t\t\treturn -EINVAL;\n@@ -323,8 +341,15 @@ int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,\n \t\t\tconst struct iwl_sku_id *tlv_sku_id =\n \t\t\t\t(const void *)(data + sizeof(*tlv));\n \n+\t\t\tif (tlv_len \u003c sizeof(*tlv_sku_id)) {\n+\t\t\t\tIWL_ERR(trans,\n+\t\t\t\t\t\"Invalid IWL_UCODE_TLV_PNVM_SKU len %u\\n\",\n+\t\t\t\t\ttlv_len);\n+\t\t\t\treturn -EINVAL;\n+\t\t\t}\n+\n \t\t\tIWL_DEBUG_FW(trans,\n-\t\t\t\t \"Got IWL_UCODE_TLV_PNVM_SKU len %d\\n\",\n+\t\t\t\t \"Got IWL_UCODE_TLV_PNVM_SKU len %u\\n\",\n \t\t\t\t tlv_len);\n \t\t\tif (tlv_len \u003c sizeof(*tlv_sku_id)) {\n \t\t\t\tIWL_ERR(trans, \"invalid PNVM SKU TLV len: %u\\n\",\n@@ -337,8 +362,8 @@ int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,\n \t\t\t\t le32_to_cpu(tlv_sku_id-\u003edata[1]),\n \t\t\t\t le32_to_cpu(tlv_sku_id-\u003edata[2]));\n \n-\t\t\tdata += sizeof(*tlv) + ALIGN(tlv_len, 4);\n-\t\t\tlen -= ALIGN(tlv_len, 4);\n+\t\t\tdata += sizeof(*tlv) + tlv_len_aligned;\n+\t\t\tlen -= tlv_len_aligned;\n \n \t\t\tif (sku_id[0] == tlv_sku_id-\u003edata[0] \u0026\u0026\n \t\t\t sku_id[1] == tlv_sku_id-\u003edata[1] \u0026\u0026\n@@ -352,8 +377,8 @@ int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,\n \t\t\t\tIWL_DEBUG_FW(trans, \"SKU ID didn't match!\\n\");\n \t\t\t}\n \t\t} else {\n-\t\t\tdata += sizeof(*tlv) + ALIGN(tlv_len, 4);\n-\t\t\tlen -= ALIGN(tlv_len, 4);\n+\t\t\tdata += sizeof(*tlv) + tlv_len_aligned;\n+\t\t\tlen -= tlv_len_aligned;\n \t\t}\n \t}\n \n@@ -549,7 +574,7 @@ IWL_EXPORT_SYMBOL(iwl_uefi_get_uneb_table);\n \n static void iwl_uefi_set_sar_profile(struct iwl_sar_profile *profiles,\n \t\t\t\t const u8 *vals, u8 prof_index,\n-\t\t\t\t u8 num_subbands, bool enabled)\n+\t\t\t\t u8 num_subbands, u32 mode)\n {\n \tstruct iwl_sar_profile *sar_prof = \u0026profiles[prof_index];\n \n@@ -573,7 +598,7 @@ static void iwl_uefi_set_sar_profile(struct iwl_sar_profile *profiles,\n \t\t\t\tvals[chain * num_subbands + subband];\n \t}\n \n-\tsar_prof-\u003eenabled = enabled \u0026 IWL_SAR_ENABLE_MSK;\n+\tsar_prof-\u003eenabled = mode \u0026 IWL_SAR_ENABLE_MSK;\n }\n \n int iwl_uefi_get_wrds_table(struct iwl_fw_runtime *fwrt)\ndiff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c\nindex bb746112ddadf..cc6bf4ea5055d 100644\n--- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c\n+++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c\n@@ -10,8 +10,6 @@\n #include \"iwl-io.h\"\n #include \"iwl-csr.h\"\n #include \"iwl-debug.h\"\n-#include \"iwl-prph.h\"\n-#include \"iwl-fh.h\"\n \n void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val)\n {\n@@ -217,232 +215,3 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)\n \t}\n }\n IWL_EXPORT_SYMBOL(iwl_clear_bits_prph);\n-\n-void iwl_force_nmi(struct iwl_trans *trans)\n-{\n-\tif (trans-\u003emac_cfg-\u003edevice_family \u003c IWL_DEVICE_FAMILY_9000)\n-\t\tiwl_write_prph_delay(trans, DEVICE_SET_NMI_REG,\n-\t\t\t\t DEVICE_SET_NMI_VAL_DRV, 1);\n-\telse if (trans-\u003emac_cfg-\u003edevice_family \u003c IWL_DEVICE_FAMILY_AX210)\n-\t\tiwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER,\n-\t\t\t\tUREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER);\n-\telse if (trans-\u003emac_cfg-\u003edevice_family \u003c IWL_DEVICE_FAMILY_BZ)\n-\t\tiwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,\n-\t\t\t\t UREG_DOORBELL_TO_ISR6_NMI_BIT);\n-\telse\n-\t\tiwl_write32(trans, CSR_DOORBELL_VECTOR,\n-\t\t\t UREG_DOORBELL_TO_ISR6_NMI_BIT);\n-}\n-IWL_EXPORT_SYMBOL(iwl_force_nmi);\n-\n-static const char *get_rfh_string(int cmd)\n-{\n-#define IWL_CMD(x) case x: return #x\n-#define IWL_CMD_MQ(arg, reg, q) { if (arg == reg(q)) return #reg; }\n-\n-\tint i;\n-\n-\tfor (i = 0; i \u003c IWL_MAX_RX_HW_QUEUES; i++) {\n-\t\tIWL_CMD_MQ(cmd, RFH_Q_FRBDCB_BA_LSB, i);\n-\t\tIWL_CMD_MQ(cmd, RFH_Q_FRBDCB_WIDX, i);\n-\t\tIWL_CMD_MQ(cmd, RFH_Q_FRBDCB_RIDX, i);\n-\t\tIWL_CMD_MQ(cmd, RFH_Q_URBD_STTS_WPTR_LSB, i);\n-\t}\n-\n-\tswitch (cmd) {\n-\tIWL_CMD(RFH_RXF_DMA_CFG);\n-\tIWL_CMD(RFH_GEN_CFG);\n-\tIWL_CMD(RFH_GEN_STATUS);\n-\tIWL_CMD(FH_TSSR_TX_STATUS_REG);\n-\tIWL_CMD(FH_TSSR_TX_ERROR_REG);\n-\tdefault:\n-\t\treturn \"UNKNOWN\";\n-\t}\n-#undef IWL_CMD_MQ\n-}\n-\n-struct reg {\n-\tu32 addr;\n-\tbool is64;\n-};\n-\n-static int iwl_dump_rfh(struct iwl_trans *trans, char **buf)\n-{\n-\tint i, q;\n-\tint num_q = trans-\u003einfo.num_rxqs;\n-\tstatic const u32 rfh_tbl[] = {\n-\t\tRFH_RXF_DMA_CFG,\n-\t\tRFH_GEN_CFG,\n-\t\tRFH_GEN_STATUS,\n-\t\tFH_TSSR_TX_STATUS_REG,\n-\t\tFH_TSSR_TX_ERROR_REG,\n-\t};\n-\tstatic const struct reg rfh_mq_tbl[] = {\n-\t\t{ RFH_Q0_FRBDCB_BA_LSB, true },\n-\t\t{ RFH_Q0_FRBDCB_WIDX, false },\n-\t\t{ RFH_Q0_FRBDCB_RIDX, false },\n-\t\t{ RFH_Q0_URBD_STTS_WPTR_LSB, true },\n-\t};\n-\n-#ifdef CONFIG_IWLWIFI_DEBUGFS\n-\tif (buf) {\n-\t\tint pos = 0;\n-\t\t/*\n-\t\t * Register (up to 34 for name + 8 blank/q for MQ): 40 chars\n-\t\t * Colon + space: 2 characters\n-\t\t * 0X%08x: 10 characters\n-\t\t * New line: 1 character\n-\t\t * Total of 53 characters\n-\t\t */\n-\t\tsize_t bufsz = ARRAY_SIZE(rfh_tbl) * 53 +\n-\t\t\t ARRAY_SIZE(rfh_mq_tbl) * 53 * num_q + 40;\n-\n-\t\t*buf = kmalloc(bufsz, GFP_KERNEL);\n-\t\tif (!*buf)\n-\t\t\treturn -ENOMEM;\n-\n-\t\tpos += scnprintf(*buf + pos, bufsz - pos,\n-\t\t\t\t\"RFH register values:\\n\");\n-\n-\t\tfor (i = 0; i \u003c ARRAY_SIZE(rfh_tbl); i++)\n-\t\t\tpos += scnprintf(*buf + pos, bufsz - pos,\n-\t\t\t\t\"%40s: 0X%08x\\n\",\n-\t\t\t\tget_rfh_string(rfh_tbl[i]),\n-\t\t\t\tiwl_read_prph(trans, rfh_tbl[i]));\n-\n-\t\tfor (i = 0; i \u003c ARRAY_SIZE(rfh_mq_tbl); i++)\n-\t\t\tfor (q = 0; q \u003c num_q; q++) {\n-\t\t\t\tu32 addr = rfh_mq_tbl[i].addr;\n-\n-\t\t\t\taddr += q * (rfh_mq_tbl[i].is64 ? 8 : 4);\n-\t\t\t\tpos += scnprintf(*buf + pos, bufsz - pos,\n-\t\t\t\t\t\"%34s(q %2d): 0X%08x\\n\",\n-\t\t\t\t\tget_rfh_string(addr), q,\n-\t\t\t\t\tiwl_read_prph(trans, addr));\n-\t\t\t}\n-\n-\t\treturn pos;\n-\t}\n-#endif\n-\n-\tIWL_ERR(trans, \"RFH register values:\\n\");\n-\tfor (i = 0; i \u003c ARRAY_SIZE(rfh_tbl); i++)\n-\t\tIWL_ERR(trans, \" %34s: 0X%08x\\n\",\n-\t\t\tget_rfh_string(rfh_tbl[i]),\n-\t\t\tiwl_read_prph(trans, rfh_tbl[i]));\n-\n-\tfor (i = 0; i \u003c ARRAY_SIZE(rfh_mq_tbl); i++)\n-\t\tfor (q = 0; q \u003c num_q; q++) {\n-\t\t\tu32 addr = rfh_mq_tbl[i].addr;\n-\n-\t\t\taddr += q * (rfh_mq_tbl[i].is64 ? 8 : 4);\n-\t\t\tIWL_ERR(trans, \" %34s(q %d): 0X%08x\\n\",\n-\t\t\t\tget_rfh_string(addr), q,\n-\t\t\t\tiwl_read_prph(trans, addr));\n-\t\t}\n-\n-\treturn 0;\n-}\n-\n-static const char *get_fh_string(int cmd)\n-{\n-\tswitch (cmd) {\n-\tIWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);\n-\tIWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);\n-\tIWL_CMD(FH_RSCSR_CHNL0_WPTR);\n-\tIWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);\n-\tIWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);\n-\tIWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);\n-\tIWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);\n-\tIWL_CMD(FH_TSSR_TX_STATUS_REG);\n-\tIWL_CMD(FH_TSSR_TX_ERROR_REG);\n-\tdefault:\n-\t\treturn \"UNKNOWN\";\n-\t}\n-#undef IWL_CMD\n-}\n-\n-int iwl_dump_fh(struct iwl_trans *trans, char **buf)\n-{\n-\tint i;\n-\tstatic const u32 fh_tbl[] = {\n-\t\tFH_RSCSR_CHNL0_STTS_WPTR_REG,\n-\t\tFH_RSCSR_CHNL0_RBDCB_BASE_REG,\n-\t\tFH_RSCSR_CHNL0_WPTR,\n-\t\tFH_MEM_RCSR_CHNL0_CONFIG_REG,\n-\t\tFH_MEM_RSSR_SHARED_CTRL_REG,\n-\t\tFH_MEM_RSSR_RX_STATUS_REG,\n-\t\tFH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,\n-\t\tFH_TSSR_TX_STATUS_REG,\n-\t\tFH_TSSR_TX_ERROR_REG\n-\t};\n-\n-\tif (trans-\u003emac_cfg-\u003emq_rx_supported)\n-\t\treturn iwl_dump_rfh(trans, buf);\n-\n-#ifdef CONFIG_IWLWIFI_DEBUGFS\n-\tif (buf) {\n-\t\tint pos = 0;\n-\t\tsize_t bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;\n-\n-\t\t*buf = kmalloc(bufsz, GFP_KERNEL);\n-\t\tif (!*buf)\n-\t\t\treturn -ENOMEM;\n-\n-\t\tpos += scnprintf(*buf + pos, bufsz - pos,\n-\t\t\t\t\"FH register values:\\n\");\n-\n-\t\tfor (i = 0; i \u003c ARRAY_SIZE(fh_tbl); i++)\n-\t\t\tpos += scnprintf(*buf + pos, bufsz - pos,\n-\t\t\t\t\" %34s: 0X%08x\\n\",\n-\t\t\t\tget_fh_string(fh_tbl[i]),\n-\t\t\t\tiwl_read_direct32(trans, fh_tbl[i]));\n-\n-\t\treturn pos;\n-\t}\n-#endif\n-\n-\tIWL_ERR(trans, \"FH register values:\\n\");\n-\tfor (i = 0; i \u003c ARRAY_SIZE(fh_tbl); i++)\n-\t\tIWL_ERR(trans, \" %34s: 0X%08x\\n\",\n-\t\t\tget_fh_string(fh_tbl[i]),\n-\t\t\tiwl_read_direct32(trans, fh_tbl[i]));\n-\n-\treturn 0;\n-}\n-\n-void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr,\n-\t\t\t\t u32 sw_err_bit)\n-{\n-\tunsigned long timeout = jiffies + IWL_TRANS_NMI_TIMEOUT;\n-\tbool interrupts_enabled = test_bit(STATUS_INT_ENABLED, \u0026trans-\u003estatus);\n-\n-\t/* if the interrupts were already disabled, there is no point in\n-\t * calling iwl_disable_interrupts\n-\t */\n-\tif (interrupts_enabled)\n-\t\tiwl_trans_interrupts(trans, false);\n-\n-\tiwl_force_nmi(trans);\n-\twhile (time_after(timeout, jiffies)) {\n-\t\tu32 inta_hw = iwl_read32(trans, inta_addr);\n-\n-\t\t/* Error detected by uCode */\n-\t\tif (inta_hw \u0026 sw_err_bit) {\n-\t\t\t/* Clear causes register */\n-\t\t\tiwl_write32(trans, inta_addr, inta_hw \u0026 sw_err_bit);\n-\t\t\tbreak;\n-\t\t}\n-\n-\t\tmdelay(1);\n-\t}\n-\n-\t/* enable interrupts only if there were already enabled before this\n-\t * function to avoid a case were the driver enable interrupts before\n-\t * proper configurations were made\n-\t */\n-\tif (interrupts_enabled)\n-\t\tiwl_trans_interrupts(trans, true);\n-\n-\tiwl_trans_fw_error(trans, IWL_ERR_TYPE_NMI_FORCED);\n-}\ndiff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-io.h\nindex 6dce2e5267a64..e4a9f2ba0de93 100644\n--- a/drivers/net/wireless/intel/iwlwifi/iwl-io.h\n+++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.h\n@@ -57,10 +57,6 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);\n void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,\n \t\t\t u32 bits, u32 mask);\n void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);\n-void iwl_force_nmi(struct iwl_trans *trans);\n-\n-/* Error handling */\n-int iwl_dump_fh(struct iwl_trans *trans, char **buf);\n \n /*\n * UMAC periphery address space changed from 0xA00000 to 0xD00000 starting from\ndiff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c\nindex 6bb27d7f1166e..413dd55115f8f 100644\n--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c\n+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c\n@@ -612,7 +612,6 @@ static const struct ieee80211_sband_iftype_data iwl_iftype_cap[] = {\n \t\t\t\t\tIEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP |\n \t\t\t\t\tIEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI,\n \t\t\t\t.phy_cap_info[8] =\n-\t\t\t\t\tIEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI |\n \t\t\t\t\tIEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |\n \t\t\t\t\tIEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |\n \t\t\t\t\tIEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU |\n@@ -747,7 +746,6 @@ static const struct ieee80211_sband_iftype_data iwl_iftype_cap[] = {\n \t\t\t\t.phy_cap_info[7] =\n \t\t\t\t\tIEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI,\n \t\t\t\t.phy_cap_info[8] =\n-\t\t\t\t\tIEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI |\n \t\t\t\t\tIEEE80211_HE_PHY_CAP8_DCM_MAX_RU_242,\n \t\t\t\t.phy_cap_info[9] =\n \t\t\t\t\tIEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |\ndiff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c\nindex a1545e9d2cd84..0a6b7b264aa23 100644\n--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c\n+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c\n@@ -10,9 +10,10 @@\n \n #include \"iwl-trans.h\"\n #include \"iwl-drv.h\"\n+#include \"iwl-prph.h\"\n #include \u003clinux/dmapool.h\u003e\n #include \"fw/api/commands.h\"\n-#include \"pcie/gen1_2/internal.h\"\n+#include \"pcie/internal.h\"\n #include \"pcie/iwl-context-info-v2.h\"\n \n struct iwl_trans_dev_restart_data {\n@@ -333,14 +334,14 @@ IWL_EXPORT_SYMBOL(iwl_trans_send_cmd);\n \n struct iwl_device_tx_cmd *iwl_trans_alloc_tx_cmd(struct iwl_trans *trans)\n {\n-\treturn iwl_pcie_gen1_2_alloc_tx_cmd(trans);\n+\treturn iwl_pcie_alloc_tx_cmd(trans);\n }\n IWL_EXPORT_SYMBOL(iwl_trans_alloc_tx_cmd);\n \n void iwl_trans_free_tx_cmd(struct iwl_trans *trans,\n \t\t\t struct iwl_device_tx_cmd *dev_cmd)\n {\n-\tiwl_pcie_gen1_2_free_tx_cmd(trans, dev_cmd);\n+\tiwl_pcie_free_tx_cmd(trans, dev_cmd);\n }\n IWL_EXPORT_SYMBOL(iwl_trans_free_tx_cmd);\n \n@@ -395,7 +396,7 @@ void iwl_trans_op_mode_enter(struct iwl_trans *trans,\n \n \tWARN_ON_ONCE(!trans-\u003econf.rx_mpdu_cmd);\n \n-\tiwl_pcie_gen1_2_op_mode_enter(trans);\n+\tiwl_trans_pcie_op_mode_enter(trans);\n }\n IWL_EXPORT_SYMBOL(iwl_trans_op_mode_enter);\n \n@@ -452,6 +453,23 @@ void iwl_trans_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)\n \treturn iwl_trans_pcie_write_prph(trans, ofs, val);\n }\n \n+void iwl_trans_force_nmi(struct iwl_trans *trans)\n+{\n+\tif (trans-\u003emac_cfg-\u003edevice_family \u003c IWL_DEVICE_FAMILY_9000)\n+\t\tiwl_write_prph_delay(trans, DEVICE_SET_NMI_REG,\n+\t\t\t\t DEVICE_SET_NMI_VAL_DRV, 1);\n+\telse if (trans-\u003emac_cfg-\u003edevice_family \u003c IWL_DEVICE_FAMILY_AX210)\n+\t\tiwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER,\n+\t\t\t\t UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER);\n+\telse if (trans-\u003emac_cfg-\u003edevice_family \u003c IWL_DEVICE_FAMILY_BZ)\n+\t\tiwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,\n+\t\t\t\t UREG_DOORBELL_TO_ISR6_NMI_BIT);\n+\telse\n+\t\tiwl_write32(trans, CSR_DOORBELL_VECTOR,\n+\t\t\t UREG_DOORBELL_TO_ISR6_NMI_BIT);\n+}\n+IWL_EXPORT_SYMBOL(iwl_trans_force_nmi);\n+\n int iwl_trans_read_mem(struct iwl_trans *trans, u32 addr,\n \t\t void *buf, int dwords)\n {\n@@ -523,11 +541,6 @@ int iwl_trans_d3_resume(struct iwl_trans *trans, bool reset)\n }\n IWL_EXPORT_SYMBOL(iwl_trans_d3_resume);\n \n-void iwl_trans_interrupts(struct iwl_trans *trans, bool enable)\n-{\n-\tiwl_trans_pci_interrupts(trans, enable);\n-}\n-\n void iwl_trans_sync_nmi(struct iwl_trans *trans)\n {\n \tiwl_trans_pcie_sync_nmi(trans);\n@@ -563,8 +576,7 @@ void iwl_trans_resched_with_nic_access(struct iwl_trans *trans)\n \tiwl_trans_pcie_resched_with_nic_access(trans);\n }\n \n-void __releases(nic_access)\n-iwl_trans_release_nic_access(struct iwl_trans *trans)\n+void iwl_trans_release_nic_access(struct iwl_trans *trans)\n {\n \tiwl_trans_pcie_release_nic_access(trans);\n }\n@@ -821,13 +833,13 @@ IWL_EXPORT_SYMBOL(iwl_trans_is_pm_supported);\n \n bool iwl_trans_is_ltr_enabled(struct iwl_trans *trans)\n {\n-\treturn iwl_pcie_gen1_2_is_ltr_enabled(trans);\n+\treturn iwl_pcie_is_ltr_enabled(trans);\n }\n IWL_EXPORT_SYMBOL(iwl_trans_is_ltr_enabled);\n \n int iwl_trans_activate_nic(struct iwl_trans *trans)\n {\n-\treturn iwl_pcie_gen1_2_activate_nic(trans);\n+\treturn iwl_pcie_activate_nic(trans);\n }\n IWL_EXPORT_SYMBOL(iwl_trans_activate_nic);\n \ndiff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h\nindex dfad839dd2e69..56c5e61b614ad 100644\n--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h\n+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h\n@@ -992,8 +992,7 @@ bool iwl_trans_grab_nic_access(struct iwl_trans *trans);\n */\n void iwl_trans_resched_with_nic_access(struct iwl_trans *trans);\n \n-void __releases(nic_access)\n-iwl_trans_release_nic_access(struct iwl_trans *trans);\n+void iwl_trans_release_nic_access(struct iwl_trans *trans);\n \n static inline void iwl_trans_schedule_reset(struct iwl_trans *trans,\n \t\t\t\t\t enum iwl_fw_error_type type)\n@@ -1055,8 +1054,7 @@ static inline bool iwl_trans_fw_running(struct iwl_trans *trans)\n \n void iwl_trans_sync_nmi(struct iwl_trans *trans);\n \n-void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr,\n-\t\t\t\t u32 sw_err_bit);\n+void iwl_trans_force_nmi(struct iwl_trans *trans);\n \n int iwl_trans_load_pnvm(struct iwl_trans *trans,\n \t\t\tconst struct iwl_pnvm_image *pnvm_data,\n@@ -1078,8 +1076,6 @@ static inline bool iwl_trans_dbg_ini_valid(struct iwl_trans *trans)\n \t\ttrans-\u003edbg.external_ini_cfg != IWL_INI_CFG_STATE_NOT_LOADED;\n }\n \n-void iwl_trans_interrupts(struct iwl_trans *trans, bool enable);\n-\n int iwl_trans_activate_nic(struct iwl_trans *trans);\n \n static inline void iwl_trans_finish_sw_reset(struct iwl_trans *trans)\ndiff --git a/drivers/net/wireless/intel/iwlwifi/mld/agg.c b/drivers/net/wireless/intel/iwlwifi/mld/agg.c\nindex c45c47337509e..ea1f02380ad4e 100644\n--- a/drivers/net/wireless/intel/iwlwifi/mld/agg.c\n+++ b/drivers/net/wireless/intel/iwlwifi/mld/agg.c\n@@ -660,6 +660,7 @@ int iwl_mld_update_sta_baids(struct iwl_mld *mld,\n \t\t.modify.new_sta_id_mask = cpu_to_le32(new_sta_mask),\n \t};\n \tu32 cmd_id = WIDE_ID(DATA_PATH_GROUP, RX_BAID_ALLOCATION_CONFIG_CMD);\n+\tu8 cmd_ver = iwl_fw_lookup_cmd_ver(mld-\u003efw, cmd_id, 2);\n \tint baid;\n \n \t/* mac80211 will remove sessions later, but we ignore all that */\n@@ -667,6 +668,7 @@ int iwl_mld_update_sta_baids(struct iwl_mld *mld,\n \t\treturn 0;\n \n \tBUILD_BUG_ON(sizeof(struct iwl_rx_baid_cfg_resp) != sizeof(baid));\n+\tBUILD_BUG_ON(sizeof(cmd.modify) != sizeof(cmd.modify_v2));\n \n \tfor (baid = 0; baid \u003c ARRAY_SIZE(mld-\u003efw_id_to_ba); baid++) {\n \t\tstruct iwl_mld_baid_data *data;\n@@ -683,7 +685,10 @@ int iwl_mld_update_sta_baids(struct iwl_mld *mld,\n \t\t\t \"BAID data for %d corrupted - expected 0x%x found 0x%x\\n\",\n \t\t\t baid, old_sta_mask, data-\u003esta_mask);\n \n-\t\tcmd.modify.tid = cpu_to_le32(data-\u003etid);\n+\t\tif (cmd_ver \u003e= 3)\n+\t\t\tcmd.modify.tid = data-\u003etid;\n+\t\telse\n+\t\t\tcmd.modify_v2.tid = cpu_to_le32(data-\u003etid);\n \n \t\tret = iwl_mld_send_cmd_pdu(mld, cmd_id, \u0026cmd);\n \t\tif (ret)\ndiff --git a/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c\nindex 351a4f177e920..dd4bf7cb6a791 100644\n--- a/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c\n+++ b/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c\n@@ -69,7 +69,7 @@ static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mld *mld, char *buf,\n \tif (count == 6 \u0026\u0026 !strcmp(buf, \"nolog\\n\"))\n \t\tmld-\u003efw_status.do_not_dump_once = true;\n \n-\tiwl_force_nmi(mld-\u003etrans);\n+\tiwl_trans_force_nmi(mld-\u003etrans);\n \n \treturn count;\n }\ndiff --git a/drivers/net/wireless/intel/iwlwifi/mld/power.c b/drivers/net/wireless/intel/iwlwifi/mld/power.c\nindex 2387f3da5185a..6fcbb1a2e8a8f 100644\n--- a/drivers/net/wireless/intel/iwlwifi/mld/power.c\n+++ b/drivers/net/wireless/intel/iwlwifi/mld/power.c\n@@ -525,7 +525,7 @@ int iwl_mld_set_tx_power(struct iwl_mld *mld,\n \t\t.common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_LINK),\n \t\t.common.pwr_restriction = cpu_to_le16(u_tx_power),\n \t};\n-\tint len = sizeof(cmd.common) + sizeof(cmd.v11);\n+\tint len = sizeof(cmd.common) + sizeof(cmd.v12);\n \n \tif (iwl_fw_lookup_cmd_ver(mld-\u003efw, cmd_id, 10) == 10)\n \t\tlen = sizeof(cmd.common) + sizeof(cmd.v10);\ndiff --git a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c\nindex 9f395a1fd12ae..8a20d7622329c 100644\n--- a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c\n+++ b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c\n@@ -74,6 +74,21 @@ void iwl_mld_get_bios_tables(struct iwl_mld *mld)\n \t\t\t\t\t\"EWRD SAR BIOS table invalid or unavailable. (%d)\\n\",\n \t\t\t\t\tret);\n \n+\t\tret = iwl_bios_get_wsss_table(\u0026mld-\u003efwrt);\n+\t\tif (ret \u003c 0)\n+\t\t\tIWL_DEBUG_RADIO(mld,\n+\t\t\t\t\t\"WSSS (WRDS Standalone) SAR BIOS table invalid or unavailable. (%d)\\n\",\n+\t\t\t\t\tret);\n+\n+\t\tif (!ret) {\n+\t\t\t/* EWSS only extends the standalone SAR profiles from WSSS. */\n+\t\t\tret = iwl_bios_get_ewss_table(\u0026mld-\u003efwrt);\n+\t\t\tif (ret \u003c 0)\n+\t\t\t\tIWL_DEBUG_RADIO(mld,\n+\t\t\t\t\t\t\"EWSS (EWRD Standalone) SAR BIOS table invalid or unavailable. (%d)\\n\",\n+\t\t\t\t\t\tret);\n+\t\t}\n+\n \t\tret = iwl_bios_get_wgds_table(\u0026mld-\u003efwrt);\n \t\tif (ret \u003c 0)\n \t\t\tIWL_DEBUG_RADIO(mld,\n@@ -135,7 +150,9 @@ static int iwl_mld_geo_sar_init(struct iwl_mld *mld)\n \treturn iwl_mld_send_cmd_pdu(mld, cmd_id, \u0026cmd, cmd_size);\n }\n \n-int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b)\n+static int\n+iwl_mld_config_sar_concurrent_profile(struct iwl_mld *mld, int prof_a,\n+\t\t\t\t int prof_b)\n {\n \tstruct iwl_dev_tx_power_cmd cmd = {\n \t\t.common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS),\n@@ -152,8 +169,9 @@ int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b)\n \t\tnum_subbands = IWL_NUM_SUB_BANDS_V2;\n \t\tbreak;\n \tcase 11:\n-\t\tcmd.v11.flags = cpu_to_le32(mld-\u003efwrt.reduced_power_flags);\n-\t\tcmd_size = sizeof(cmd.common) + sizeof(cmd.v11);\n+\tcase 12:\n+\t\tcmd.v12.flags = cpu_to_le32(mld-\u003efwrt.reduced_power_flags);\n+\t\tcmd_size = sizeof(cmd.common) + sizeof(cmd.v12);\n \t\tnum_subbands = IWL_NUM_SUB_BANDS_V3;\n \t\tbreak;\n \tdefault:\n@@ -163,12 +181,13 @@ int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b)\n \t}\n \n \t/* TODO: CDB - support IWL_NUM_CHAIN_TABLES_V2 */\n-\t/* v10 and v11 have the same position for per_chain */\n-\tBUILD_BUG_ON(offsetof(typeof(cmd), v11.per_chain) !=\n+\t/* v10 and v12 have the same position for per_chain */\n+\tBUILD_BUG_ON(offsetof(typeof(cmd), v12.per_chain) !=\n \t\t offsetof(typeof(cmd), v10.per_chain));\n-\tret = iwl_sar_fill_profile(\u0026mld-\u003efwrt, \u0026cmd.v11.per_chain[0][0][0],\n+\tret = iwl_sar_fill_profile(\u0026mld-\u003efwrt, \u0026cmd.v12.per_chain[0][0][0],\n \t\t\t\t IWL_NUM_CHAIN_TABLES, num_subbands,\n-\t\t\t\t prof_a, prof_b);\n+\t\t\t\t prof_a, prof_b,\n+\t\t\t\t mld-\u003efwrt.sar_profiles, false);\n \t/* return on error or if the profile is disabled (positive number) */\n \tif (ret)\n \t\treturn ret;\n@@ -176,6 +195,51 @@ int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b)\n \treturn iwl_mld_send_cmd_pdu(mld, REDUCE_TX_POWER_CMD, \u0026cmd, cmd_size);\n }\n \n+static int iwl_mld_config_sar_standalone_profile(struct iwl_mld *mld,\n+\t\t\t\t\t\t int prof_a, int prof_b)\n+{\n+\tstruct iwl_dev_tx_power_cmd cmd = {\n+\t\t.common.set_mode =\n+\t\t\tcpu_to_le32(IWL_TX_POWER_MODE_SET_STANDALONE_CHAINS),\n+\t};\n+\tint ret;\n+\n+\t/* standalone per-chain SAR limits require cmd version 12 */\n+\tif (iwl_fw_lookup_cmd_ver(mld-\u003efw, REDUCE_TX_POWER_CMD, 10) != 12)\n+\t\treturn 0;\n+\n+\tret = iwl_sar_fill_profile(\u0026mld-\u003efwrt,\n+\t\t\t\t \u0026cmd.v12.per_chain[0][0][0],\n+\t\t\t\t IWL_NUM_CHAIN_TABLES,\n+\t\t\t\t IWL_NUM_SUB_BANDS_V3,\n+\t\t\t\t prof_a, prof_b,\n+\t\t\t\t mld-\u003efwrt.sar_standalone_profiles,\n+\t\t\t\t true);\n+\t/* return on error or if the standalone profile is disabled */\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn iwl_mld_send_cmd_pdu(mld, REDUCE_TX_POWER_CMD, \u0026cmd,\n+\t\t\t\t sizeof(cmd.common) + sizeof(cmd.v12));\n+}\n+\n+int iwl_mld_config_sar_profiles(struct iwl_mld *mld, int prof_a, int prof_b)\n+{\n+\tint ret;\n+\n+\tret = iwl_mld_config_sar_concurrent_profile(mld, prof_a, prof_b);\n+\t/* return on error or if the profile is disabled (positive number) */\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = iwl_mld_config_sar_standalone_profile(mld, prof_a, prof_b);\n+\t/* standalone profile is optional and may be disabled (positive number) */\n+\tif (ret \u003c 0)\n+\t\treturn ret;\n+\n+\treturn 0;\n+}\n+\n int iwl_mld_init_sar(struct iwl_mld *mld)\n {\n \tint chain_a_prof = 1;\n@@ -190,7 +254,7 @@ int iwl_mld_init_sar(struct iwl_mld *mld)\n \t\tchain_b_prof = mld-\u003efwrt.sar_chain_b_profile;\n \t}\n \n-\tret = iwl_mld_config_sar_profile(mld, chain_a_prof, chain_b_prof);\n+\tret = iwl_mld_config_sar_profiles(mld, chain_a_prof, chain_b_prof);\n \tif (ret \u003c 0)\n \t\treturn ret;\n \ndiff --git a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.h b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.h\nindex 5498c19789f4e..0877b951f2e27 100644\n--- a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.h\n+++ b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.h\n@@ -1,6 +1,6 @@\n /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */\n /*\n- * Copyright (C) 2024-2025 Intel Corporation\n+ * Copyright (C) 2024-2026 Intel Corporation\n */\n #ifndef __iwl_mld_regulatory_h__\n #define __iwl_mld_regulatory_h__\n@@ -18,6 +18,6 @@ int iwl_mld_init_sgom(struct iwl_mld *mld);\n \n int iwl_mld_init_sar(struct iwl_mld *mld);\n \n-int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b);\n+int iwl_mld_config_sar_profiles(struct iwl_mld *mld, int prof_a, int prof_b);\n \n #endif /* __iwl_mld_regulatory_h__ */\ndiff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c\nindex 4db0f29dd21af..06502f57e823e 100644\n--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c\n+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c\n@@ -1102,7 +1102,7 @@ static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,\n \tif (count == 6 \u0026\u0026 !strcmp(buf, \"nolog\\n\"))\n \t\tset_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, \u0026mvm-\u003estatus);\n \n-\tiwl_force_nmi(mvm-\u003etrans);\n+\tiwl_trans_force_nmi(mvm-\u003etrans);\n \n \treturn count;\n }\ndiff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c\nindex 0b5b41223a8a7..c3402f5e47a03 100644\n--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c\n+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c\n@@ -911,7 +911,8 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)\n \n \tret = iwl_sar_fill_profile(\u0026mvm-\u003efwrt, per_chain,\n \t\t\t\t IWL_NUM_CHAIN_TABLES,\n-\t\t\t\t n_subbands, prof_a, prof_b);\n+\t\t\t\t n_subbands, prof_a, prof_b,\n+\t\t\t\t mvm-\u003efwrt.sar_profiles, false);\n \n \t/* return on error or if the profile is disabled (positive number) */\n \tif (ret)\ndiff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c\nindex 5bd246e379432..a4f3d3c2bd350 100644\n--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c\n+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c\n@@ -5258,7 +5258,7 @@ iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm,\n \n out_restart:\n \t/* things keep failing, better restart the hw */\n-\tiwl_force_nmi(mvm-\u003etrans);\n+\tiwl_trans_force_nmi(mvm-\u003etrans);\n \treturn ret;\n }\n \n@@ -5294,7 +5294,7 @@ iwl_mvm_switch_vif_chanctx_reassign(struct iwl_mvm *mvm,\n \n out_restart:\n \t/* things keep failing, better restart the hw */\n-\tiwl_force_nmi(mvm-\u003etrans);\n+\tiwl_trans_force_nmi(mvm-\u003etrans);\n \treturn ret;\n }\n \ndiff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c\nindex 817c6dacfaccd..a94eaca0b3ed5 100644\n--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c\n+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c\n@@ -2703,7 +2703,7 @@ void iwl_mvm_scan_timeout_wk(struct work_struct *work)\n \n \tIWL_ERR(mvm, \"regular scan timed out\\n\");\n \n-\tiwl_force_nmi(mvm-\u003etrans);\n+\tiwl_trans_force_nmi(mvm-\u003etrans);\n }\n \n static void iwl_mvm_fill_scan_type(struct iwl_mvm *mvm,\ndiff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c\nindex 1ea23d297713a..c75210829ec94 100644\n--- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c\n+++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c\n@@ -6,7 +6,7 @@\n #include \"iwl-trans.h\"\n #include \"iwl-fh.h\"\n #include \"iwl-context-info-v2.h\"\n-#include \"gen1_2/internal.h\"\n+#include \"internal.h\"\n #include \"iwl-prph.h\"\n \n static const struct dmi_system_id dmi_force_scu_active_approved_list[] = {\ndiff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c\nindex 7f886200d6933..23ec968577bd9 100644\n--- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c\n+++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c\n@@ -6,7 +6,7 @@\n #include \"iwl-trans.h\"\n #include \"iwl-fh.h\"\n #include \"iwl-context-info.h\"\n-#include \"gen1_2/internal.h\"\n+#include \"internal.h\"\n #include \"iwl-prph.h\"\n \n static void *_iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans,\ndiff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c\nindex a117c378b1f1e..905482419a9af 100644\n--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c\n+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c\n@@ -15,7 +15,7 @@\n #include \"iwl-trans.h\"\n #include \"iwl-drv.h\"\n #include \"iwl-prph.h\"\n-#include \"gen1_2/internal.h\"\n+#include \"internal.h\"\n \n #define _IS_A(cfg, _struct) __builtin_types_compatible_p(typeof(cfg),\t\\\n \t\t\t\t\t\t\t struct _struct)\n@@ -1188,17 +1188,22 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)\n \t\treturn -EIO;\n \t}\n \n-\treturn iwl_pci_gen1_2_probe(pdev, ent, mac_cfg, hw_base, hw_rev);\n+\treturn _iwl_pci_probe(pdev, ent, mac_cfg, hw_base, hw_rev);\n }\n \n static void iwl_pci_remove(struct pci_dev *pdev)\n {\n \tstruct iwl_trans *trans = pci_get_drvdata(pdev);\n+\tstruct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);\n \n \tif (!trans)\n \t\treturn;\n \n-\tiwl_pcie_gen1_2_remove(trans);\n+\tcancel_delayed_work_sync(\u0026trans_pcie-\u003eme_recheck_wk);\n+\n+\tiwl_drv_stop(trans-\u003edrv);\n+\n+\tiwl_trans_pcie_free(trans);\n }\n \n #ifdef CONFIG_PM_SLEEP\ndiff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h\nsimilarity index 98%\nrename from drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h\nrename to drivers/net/wireless/intel/iwlwifi/pcie/internal.h\nindex f0e70b0fedfe7..e6b1cb559a0a6 100644\n--- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h\n+++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h\n@@ -22,7 +22,7 @@\n #include \"iwl-io.h\"\n #include \"iwl-op-mode.h\"\n #include \"iwl-drv.h\"\n-#include \"pcie/iwl-context-info.h\"\n+#include \"iwl-context-info.h\"\n \n /*\n * RX related structures and functions\n@@ -850,7 +850,7 @@ static inline u16 iwl_txq_gen1_tfd_tb_get_len(struct iwl_trans *trans,\n }\n \n static inline struct iwl_device_tx_cmd *\n-iwl_pcie_gen1_2_alloc_tx_cmd(struct iwl_trans *trans)\n+iwl_pcie_alloc_tx_cmd(struct iwl_trans *trans)\n {\n \tstruct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);\n \n@@ -858,8 +858,8 @@ iwl_pcie_gen1_2_alloc_tx_cmd(struct iwl_trans *trans)\n }\n \n static inline void\n-iwl_pcie_gen1_2_free_tx_cmd(struct iwl_trans *trans,\n-\t\t\t struct iwl_device_tx_cmd *dev_cmd)\n+iwl_pcie_free_tx_cmd(struct iwl_trans *trans,\n+\t\t struct iwl_device_tx_cmd *dev_cmd)\n {\n \tstruct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);\n \n@@ -1132,7 +1132,7 @@ static inline void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans) { }\n void iwl_pcie_rx_allocator_work(struct work_struct *data);\n \n /* common trans ops for all generations transports */\n-void iwl_pcie_gen1_2_op_mode_enter(struct iwl_trans *trans);\n+void iwl_trans_pcie_op_mode_enter(struct iwl_trans *trans);\n int _iwl_trans_pcie_start_hw(struct iwl_trans *trans);\n int iwl_trans_pcie_start_hw(struct iwl_trans *trans);\n void iwl_trans_pcie_op_mode_leave(struct iwl_trans *trans);\n@@ -1161,14 +1161,11 @@ int iwl_trans_pcie_read_config32(struct iwl_trans *trans, u32 ofs,\n \t\t\t\t u32 *val);\n bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans);\n void iwl_trans_pcie_resched_with_nic_access(struct iwl_trans *trans);\n-void __releases(nic_access_nobh)\n-iwl_trans_pcie_release_nic_access(struct iwl_trans *trans);\n+void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans);\n void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power);\n-int iwl_pci_gen1_2_probe(struct pci_dev *pdev,\n-\t\t\t const struct pci_device_id *ent,\n-\t\t\t const struct iwl_mac_cfg *mac_cfg,\n-\t\t\t u8 __iomem *hw_base, u32 hw_rev);\n-void iwl_pcie_gen1_2_remove(struct iwl_trans *trans);\n+int _iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent,\n+\t\t const struct iwl_mac_cfg *mac_cfg,\n+\t\t u8 __iomem *hw_base, u32 hw_rev);\n \n /* transport gen 1 exported functions */\n void iwl_trans_pcie_fw_alive(struct iwl_trans *trans);\n@@ -1193,7 +1190,7 @@ int iwl_pcie_alloc_dma_ptr(struct iwl_trans *trans,\n \t\t\t struct iwl_dma_ptr *ptr, size_t size);\n void iwl_pcie_free_dma_ptr(struct iwl_trans *trans, struct iwl_dma_ptr *ptr);\n void iwl_pcie_apply_destination(struct iwl_trans *trans);\n-int iwl_pcie_gen1_2_activate_nic(struct iwl_trans *trans);\n+int iwl_pcie_activate_nic(struct iwl_trans *trans);\n \n /* transport gen 2 exported functions */\n int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,\n@@ -1223,7 +1220,7 @@ static inline bool iwl_pcie_gen1_is_pm_supported(struct iwl_trans *trans)\n \treturn trans_pcie-\u003epm_support;\n }\n \n-static inline bool iwl_pcie_gen1_2_is_ltr_enabled(struct iwl_trans *trans)\n+static inline bool iwl_pcie_is_ltr_enabled(struct iwl_trans *trans)\n {\n \tstruct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);\n \ndiff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c\nsimilarity index 99%\nrename from drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c\nrename to drivers/net/wireless/intel/iwlwifi/pcie/rx.c\nindex 4631e11f2a964..db3933b0d1979 100644\n--- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c\n+++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c\n@@ -12,7 +12,7 @@\n #include \"iwl-io.h\"\n #include \"internal.h\"\n #include \"iwl-op-mode.h\"\n-#include \"pcie/iwl-context-info-v2.h\"\n+#include \"iwl-context-info-v2.h\"\n #include \"fw/dbg.h\"\n \n /******************************************************************************\n@@ -1493,7 +1493,7 @@ static struct iwl_rx_mem_buffer *iwl_pcie_get_rxb(struct iwl_trans *trans,\n \n out_err:\n \tWARN(1, \"Invalid rxb from HW %u\\n\", (u32)vid);\n-\tiwl_force_nmi(trans);\n+\tiwl_trans_force_nmi(trans);\n \treturn NULL;\n }\n \n@@ -1519,6 +1519,11 @@ static int iwl_pcie_rx_handle(struct iwl_trans *trans, int queue, int budget)\n \tr = iwl_get_closed_rb_stts(trans, rxq);\n \ti = rxq-\u003eread;\n \n+\t/* Order the read of the write pointer before any read of the\n+\t * completion descriptors and of the RB contents it makes visible.\n+\t */\n+\tdma_rmb();\n+\n \t/* W/A 9000 device step A0 wrap-around bug */\n \tr \u0026= (rxq-\u003equeue_size - 1);\n \ndiff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c\nsimilarity index 99%\nrename from drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c\nrename to drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c\nindex f41cbe62e7aa5..39dd963920b31 100644\n--- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c\n+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c\n@@ -5,8 +5,8 @@\n */\n #include \"iwl-trans.h\"\n #include \"iwl-prph.h\"\n-#include \"pcie/iwl-context-info.h\"\n-#include \"pcie/iwl-context-info-v2.h\"\n+#include \"iwl-context-info.h\"\n+#include \"iwl-context-info-v2.h\"\n #include \"internal.h\"\n #include \"fw/dbg.h\"\n \ndiff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c\nsimilarity index 98%\nrename from drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c\nrename to drivers/net/wireless/intel/iwlwifi/pcie/trans.c\nindex 71c4746c61a6b..bda069a6f7ebf 100644\n--- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c\n+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c\n@@ -28,7 +28,7 @@\n #include \"mei/iwl-mei.h\"\n #include \"internal.h\"\n #include \"iwl-fh.h\"\n-#include \"pcie/iwl-context-info-v2.h\"\n+#include \"iwl-context-info-v2.h\"\n #include \"pcie/utils.h\"\n \n #define IWL_HOST_MON_BLOCK_PEMON\t0x00\n@@ -1903,7 +1903,7 @@ void iwl_trans_pcie_write_prph(struct iwl_trans *trans, u32 addr, u32 val)\n \tiwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WDAT, val);\n }\n \n-void iwl_pcie_gen1_2_op_mode_enter(struct iwl_trans *trans)\n+void iwl_trans_pcie_op_mode_enter(struct iwl_trans *trans)\n {\n \tstruct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);\n \n@@ -2402,10 +2402,10 @@ bool _iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent)\n \n out:\n \t/*\n-\t * Fool sparse by faking we release the lock - sparse will\n-\t * track nic_access anyway.\n+\t * Deliberately return with reg_lock held; the caller must drop it via\n+\t * iwl_trans_pcie_release_nic_access(), or explicitly if it wants to\n+\t * keep the NIC awake past the critical section (cmd_hold_nic_awake).\n \t */\n-\t__release(\u0026trans_pcie-\u003ereg_lock);\n \treturn true;\n }\n \n@@ -2427,24 +2427,19 @@ void iwl_trans_pcie_resched_with_nic_access(struct iwl_trans *trans)\n {\n \tstruct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);\n \n+\tlockdep_assert_held(\u0026trans_pcie-\u003ereg_lock);\n+\n \tspin_unlock_bh(\u0026trans_pcie-\u003ereg_lock);\n \tcond_resched();\n \tspin_lock_bh(\u0026trans_pcie-\u003ereg_lock);\n }\n \n-void __releases(nic_access_nobh)\n-iwl_trans_pcie_release_nic_access(struct iwl_trans *trans)\n+void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans)\n {\n \tstruct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);\n \n \tlockdep_assert_held(\u0026trans_pcie-\u003ereg_lock);\n \n-\t/*\n-\t * Fool sparse by faking we acquiring the lock - sparse will\n-\t * track nic_access anyway.\n-\t */\n-\t__acquire(\u0026trans_pcie-\u003ereg_lock);\n-\n \tif (trans_pcie-\u003ecmd_hold_nic_awake)\n \t\tgoto out;\n \tif (trans-\u003emac_cfg-\u003edevice_family \u003e= IWL_DEVICE_FAMILY_BZ)\n@@ -2460,7 +2455,6 @@ iwl_trans_pcie_release_nic_access(struct iwl_trans *trans)\n \t * scheduled on different CPUs (after we drop reg_lock).\n \t */\n out:\n-\t__release(nic_access_nobh);\n \tspin_unlock_bh(\u0026trans_pcie-\u003ereg_lock);\n }\n \n@@ -3016,24 +3010,6 @@ static ssize_t iwl_dbgfs_csr_write(struct file *file,\n \treturn count;\n }\n \n-static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,\n-\t\t\t\t char __user *user_buf,\n-\t\t\t\t size_t count, loff_t *ppos)\n-{\n-\tstruct iwl_trans *trans = file-\u003eprivate_data;\n-\tchar *buf = NULL;\n-\tssize_t ret;\n-\n-\tret = iwl_dump_fh(trans, \u0026buf);\n-\tif (ret \u003c 0)\n-\t\treturn ret;\n-\tif (!buf)\n-\t\treturn -EINVAL;\n-\tret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);\n-\tkfree(buf);\n-\treturn ret;\n-}\n-\n static ssize_t iwl_dbgfs_rfkill_read(struct file *file,\n \t\t\t\t char __user *user_buf,\n \t\t\t\t size_t count, loff_t *ppos)\n@@ -3133,7 +3109,6 @@ static ssize_t iwl_dbgfs_reset_write(struct file *file,\n }\n \n DEBUGFS_READ_WRITE_FILE_OPS(interrupt);\n-DEBUGFS_READ_FILE_OPS(fh_reg);\n DEBUGFS_READ_FILE_OPS(rx_queue);\n DEBUGFS_WRITE_FILE_OPS(csr);\n DEBUGFS_READ_WRITE_FILE_OPS(rfkill);\n@@ -3157,7 +3132,6 @@ void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans)\n \tDEBUGFS_ADD_FILE(tx_queue, dir, 0400);\n \tDEBUGFS_ADD_FILE(interrupt, dir, 0600);\n \tDEBUGFS_ADD_FILE(csr, dir, 0200);\n-\tDEBUGFS_ADD_FILE(fh_reg, dir, 0400);\n \tDEBUGFS_ADD_FILE(rfkill, dir, 0600);\n \tDEBUGFS_ADD_FILE(rf, dir, 0400);\n \tDEBUGFS_ADD_FILE(reset, dir, 0200);\n@@ -3594,8 +3568,10 @@ void iwl_trans_pci_interrupts(struct iwl_trans *trans, bool enable)\n \n void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans)\n {\n-\tu32 inta_addr, sw_err_bit;\n+\tbool interrupts_enabled = test_bit(STATUS_INT_ENABLED, \u0026trans-\u003estatus);\n \tstruct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);\n+\tunsigned long timeout = jiffies + IWL_TRANS_NMI_TIMEOUT;\n+\tu32 inta_addr, sw_err_bit;\n \n \tif (trans_pcie-\u003emsix_enabled) {\n \t\tinta_addr = CSR_MSIX_HW_INT_CAUSES_AD;\n@@ -3608,7 +3584,34 @@ void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans)\n \t\tsw_err_bit = CSR_INT_BIT_SW_ERR;\n \t}\n \n-\tiwl_trans_sync_nmi_with_addr(trans, inta_addr, sw_err_bit);\n+\t/* if the interrupts were already disabled, there is no point in\n+\t * calling iwl_disable_interrupts\n+\t */\n+\tif (interrupts_enabled)\n+\t\tiwl_trans_pci_interrupts(trans, false);\n+\n+\tiwl_trans_force_nmi(trans);\n+\twhile (time_after(timeout, jiffies)) {\n+\t\tu32 inta_hw = iwl_read32(trans, inta_addr);\n+\n+\t\t/* Error detected by uCode */\n+\t\tif (inta_hw \u0026 sw_err_bit) {\n+\t\t\t/* Clear causes register */\n+\t\t\tiwl_write32(trans, inta_addr, inta_hw \u0026 sw_err_bit);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tmdelay(1);\n+\t}\n+\n+\t/* enable interrupts only if there were already enabled before this\n+\t * function to avoid a case were the driver enable interrupts before\n+\t * proper configurations were made\n+\t */\n+\tif (interrupts_enabled)\n+\t\tiwl_trans_pci_interrupts(trans, true);\n+\n+\tiwl_trans_fw_error(trans, IWL_ERR_TYPE_NMI_FORCED);\n }\n \n static int iwl_trans_pcie_alloc_txcmd_pool(struct iwl_trans *trans)\n@@ -4076,10 +4079,9 @@ static void iwl_pcie_check_me_status(struct iwl_trans *trans)\n \tschedule_delayed_work(\u0026trans_pcie-\u003eme_recheck_wk, HZ);\n }\n \n-int iwl_pci_gen1_2_probe(struct pci_dev *pdev,\n-\t\t\t const struct pci_device_id *ent,\n-\t\t\t const struct iwl_mac_cfg *mac_cfg,\n-\t\t\t u8 __iomem *hw_base, u32 hw_rev)\n+int _iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent,\n+\t\t const struct iwl_mac_cfg *mac_cfg,\n+\t\t u8 __iomem *hw_base, u32 hw_rev)\n {\n \tconst struct iwl_dev_info *dev_info;\n \tstruct iwl_trans_info info = {\n@@ -4229,18 +4231,7 @@ int iwl_pci_gen1_2_probe(struct pci_dev *pdev,\n \treturn ret;\n }\n \n-void iwl_pcie_gen1_2_remove(struct iwl_trans *trans)\n-{\n-\tstruct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);\n-\n-\tcancel_delayed_work_sync(\u0026trans_pcie-\u003eme_recheck_wk);\n-\n-\tiwl_drv_stop(trans-\u003edrv);\n-\n-\tiwl_trans_pcie_free(trans);\n-}\n-\n-int iwl_pcie_gen1_2_activate_nic(struct iwl_trans *trans)\n+int iwl_pcie_activate_nic(struct iwl_trans *trans)\n {\n \tconst struct iwl_mac_cfg *mac_cfg = trans-\u003emac_cfg;\n \tu32 poll_ready;\ndiff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c\nsimilarity index 100%\nrename from drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx-gen2.c\nrename to drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c\ndiff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c\nsimilarity index 99%\nrename from drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c\nrename to drivers/net/wireless/intel/iwlwifi/pcie/tx.c\nindex 26d1530cfa373..496435ea93ee8 100644\n--- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c\n+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c\n@@ -715,7 +715,7 @@ static void iwl_txq_stuck_timer(struct timer_list *t)\n \n \tiwl_txq_log_scd_error(trans, txq);\n \n-\tiwl_force_nmi(trans);\n+\tiwl_trans_force_nmi(trans);\n }\n \n int iwl_pcie_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq,\n@@ -1105,7 +1105,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)\n \t\tif (nfreed++ \u003e 0) {\n \t\t\tIWL_ERR(trans, \"HCMD skipped: index (%d) %d %d\\n\",\n \t\t\t\tidx, txq-\u003ewrite_ptr, r);\n-\t\t\tiwl_force_nmi(trans);\n+\t\t\tiwl_trans_force_nmi(trans);\n \t\t}\n \t}\n \n"
} |
| 2/1 | 2026/09/26 16:31 | agent | patch-evaluator |
0mModel:core Args: null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch series exclusively modifies the Intel Wi-Fi driver (`drivers/net/wireless/intel/iwlwifi`), including PCIe transport handling, firmware interaction, power/SAR regulatory management, and MVM/MLD operations. This driver requires physical Intel PCIe Wi-Fi hardware that is not emulated in standard virtualized fuzzing environments (QEMU/GCE), making the modified code structurally unreachable.",
"WorthFuzzing": false
}Instruction: You are an expert Linux kernel maintainer and security engineer.
Your job is to review a provided patch series and evaluate whether it warrants fuzzing with syzkaller.
IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on internal assumptions. You must actively use your code access
tools to inspect the actual source code, callers, and surrounding context.
================================================================================
1. CORE TRIAGE PHILOSOPHY
================================================================================
The goal of patch fuzzing is to discover crashes, regressions, exposed latent bugs,
and newly triggered assertions introduced by the patch series.
- REACHABILITY IS THE PRIMARY GATE:
Fuzzing can only discover bugs in code that can actually execute in standard virtualized
environments (GCE or QEMU, utilizing software-emulated devices like USB gadgets, netdev, tun/tap).
If the modified code is structurally unreachable (see Section 2), it MUST NOT be fuzzed,
regardless of whether it adds assertions or complex logic.
- DO NOT BLINDLY TRUST "NO FUNCTIONAL CHANGE" (NFCI) OR "REFACTORING" CLAIMS:
Patch authors routinely label changes as "cleanups", "refactorings", or state
"No functional change intended". Do NOT take these claims at face value.
Code refactorings that rearrange logic, introduce helper functions, or alter state management
in core subsystems frequently introduce subtle semantic shifts or uncover latent kernel bugs.
If reachable executable code is modified or refactored, it MUST be fuzzed.
- NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED:
When a patch introduces or modifies runtime checks or assertions (e.g., WARN_ON*, VM_WARN_ON*,
BUG_ON*, lockdep_assert*) in reachable code paths, it enforces new or stricter invariants.
Even if the author believes the invariant always holds, fuzzing is essential to verify whether
an unusual sequence of operations can violate it.
================================================================================
2. WHEN TO RETURN WorthFuzzing=false (NEGATIVE CRITERIA)
================================================================================
Return WorthFuzzing=false ONLY IF all modified code falls strictly into one or more of these categories:
- Non-kernel and non-executable changes:
* Modifications to Documentation/, comments, or spelling fixes.
* User-space directories, self-tests, samples, or scripts (e.g., tools/, samples/, scripts/, usr/)
that do not affect the compiled kernel image (vmlinux) or kernel modules.
* Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints
that do not alter control flow or data structures.
* Build system or Kconfig changes that do not alter compiled C logic.
- Structurally unreachable hardware:
* Vendor-specific PCIe switches, SmartNICs, or GPU drivers (e.g., mlxsw, pds_core, qed,
ionic, amdgpu) requiring physical ASIC/PCIe cards not emulated in standard QEMU.
- Unreachable execution paths:
* Driver teardown callbacks (.remove, .shutdown, pci_unregister_driver) executed only during
physical PCI hot-unplug or manual sysfs driver unbinding.
* Code paths exclusive to architectures other than the target architecture.
================================================================================
3. WHEN TO RETURN WorthFuzzing=true (POSITIVE CRITERIA)
================================================================================
Return WorthFuzzing=true whenever the patch touches reachable executable code, including:
- Core Subsystems:
* Any logic modifications in memory management (mm/), synchronization/locking (kernel/locking/),
BPF, scheduler, core networking, VFS, or syscall handling.
- Refactorings and Code Cleanups:
* Any restructuring of reachable data structures, helper abstractions, or algorithm flows.
- Runtime Assertions and Defensive Checks:
* Any introduction or alteration of assertions (WARN_ON*, VM_WARN_ON*, BUG_ON*, etc.) in reachable paths.
- Reachable Drivers and Protocols:
* Drivers accessible via virtual buses (virtio, USB gadget, loopback, netlink, binder, sockets, etc.).
================================================================================
4. EXTRACTING FocusSymbols (PREVENTING DILUTION)
================================================================================
When WorthFuzzing=true, you must extract specific kernel functions into FocusSymbols to guide the fuzzer:
- AVOID UBIQUITOUS LIFECYCLE HOT-PATHS:
Do NOT list generic, ubiquitous functions called by almost every program in the corpus
(including, but not limited to: general memory allocators and deallocators, page fault
and trap handlers, or core synchronization primitives; this is not an exhaustive list).
Listing ubiquitous functions causes the fuzzer to classify thousands of unrelated tests as "focused",
which severely dilutes fuzzing effort away from the actual changes.
- TARGET SPECIFIC FEATURE LOGIC AND ENTRYPOINTS:
List functions that specifically implement the logic being added or altered, or direct API entrypoints
for the subsystem feature under review.
- HANDLING STATIC INLINE FUNCTIONS IN HEADERS (.h):
Compiler-inlined static functions (such as static inlines in mm/*.h or include/linux/*.h) lack
distinct symbol addresses in vmlinux and cannot be targeted directly by symbol coverage filters.
If the changes are primarily in static inline helpers, identify non-static, feature-specific caller
functions in .c files that exercise them (avoiding ubiquitous lifecycle wrappers).
================================================================================
5. IDENTIFYING EnableConfigs
================================================================================
Identify any specific CONFIG_ options required to properly compile and reach the modified code:
- Inspect Kconfig files and #ifdef guards; do not make assumptions.
- Check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed.
- Strip any 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.
Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.
Prompt: Target architecture: amd64
For your convenience, here is the diff of the changes:
commit 4d6d8f627d2307e510beb8f5bc1dc4bffd96cf51
Author: syz-cluster <triage@syzkaller.com>
Date: Sat Sep 26 16:31:13 2026 +0000
syz-cluster: applied patch under review
diff --git a/drivers/net/wireless/intel/iwlwifi/Makefile b/drivers/net/wireless/intel/iwlwifi/Makefile
index 2a74efe09cf01..6746281350e0e 100644
--- a/drivers/net/wireless/intel/iwlwifi/Makefile
+++ b/drivers/net/wireless/intel/iwlwifi/Makefile
@@ -9,9 +9,9 @@ iwlwifi-objs += iwl-utils.o
iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o
# Bus
-iwlwifi-objs += pcie/ctxt-info.o pcie/ctxt-info-v2.o pcie/drv.o pcie/utils.o
-iwlwifi-objs += pcie/gen1_2/rx.o pcie/gen1_2/tx.o pcie/gen1_2/trans.o
-iwlwifi-objs += pcie/gen1_2/trans-gen2.o pcie/gen1_2/tx-gen2.o
+iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o
+iwlwifi-objs += pcie/ctxt-info.o pcie/ctxt-info-v2.o pcie/trans-gen2.o pcie/tx-gen2.o
+iwlwifi-objs += pcie/utils.o
CFLAGS_pcie/drv.o += -Wno-override-init
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h
index b17babef71c01..3fbcb2e4bfe06 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h
@@ -522,17 +522,34 @@ struct iwl_rx_baid_cfg_cmd_alloc {
} __packed; /* RX_BAID_ALLOCATION_ADD_CMD_API_S_VER_1 */
/**
- * struct iwl_rx_baid_cfg_cmd_modify - BAID modification data
+ * struct iwl_rx_baid_cfg_cmd_modify_v2 - BAID modification data
* @old_sta_id_mask: old station ID mask
* @new_sta_id_mask: new station ID mask
* @tid: TID of the BAID
*/
-struct iwl_rx_baid_cfg_cmd_modify {
+struct iwl_rx_baid_cfg_cmd_modify_v2 {
__le32 old_sta_id_mask;
__le32 new_sta_id_mask;
__le32 tid;
} __packed; /* RX_BAID_ALLOCATION_MODIFY_CMD_API_S_VER_2 */
+/**
+ * struct iwl_rx_baid_cfg_cmd_modify - BAID modification data
+ * @old_sta_id_mask: old station ID mask
+ * @new_sta_id_mask: new station ID mask
+ * @tid: TID of the BAID
+ * @reserved: reserved
+ * @win_size: RX BA session window size to apply to the modified BAID,
+ * 0 means keep the current one
+ */
+struct iwl_rx_baid_cfg_cmd_modify {
+ __le32 old_sta_id_mask;
+ __le32 new_sta_id_mask;
+ u8 tid;
+ u8 reserved;
+ __le16 win_size;
+} __packed; /* RX_BAID_ALLOCATION_MODIFY_CMD_API_S_VER_3 */
+
/**
* struct iwl_rx_baid_cfg_cmd_remove_v1 - BAID removal data
* @baid: the BAID to remove
@@ -555,7 +572,8 @@ struct iwl_rx_baid_cfg_cmd_remove {
* struct iwl_rx_baid_cfg_cmd - BAID allocation/config command
* @action: the action, from &enum iwl_rx_baid_action
* @alloc: allocation data
- * @modify: modify data
+ * @modify_v2: modify data (version 2)
+ * @modify: modify data (version 3)
* @remove_v1: remove data (version 1)
* @remove: remove data
*/
@@ -563,11 +581,12 @@ struct iwl_rx_baid_cfg_cmd {
__le32 action;
union {
struct iwl_rx_baid_cfg_cmd_alloc alloc;
+ struct iwl_rx_baid_cfg_cmd_modify_v2 modify_v2;
struct iwl_rx_baid_cfg_cmd_modify modify;
struct iwl_rx_baid_cfg_cmd_remove_v1 remove_v1;
struct iwl_rx_baid_cfg_cmd_remove remove;
- }; /* RX_BAID_ALLOCATION_OPERATION_API_U_VER_2 */
-} __packed; /* RX_BAID_ALLOCATION_CONFIG_CMD_API_S_VER_2 */
+ }; /* RX_BAID_ALLOCATION_OPERATION_API_U_VER_3 */
+} __packed; /* RX_BAID_ALLOCATION_CONFIG_CMD_API_S_VER_3 */
/**
* struct iwl_rx_baid_cfg_resp - BAID allocation response
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h
index 115e65ba19f8c..4d54a95b98ca6 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h
@@ -300,7 +300,8 @@ enum iwl_dev_tx_power_cmd_mode {
IWL_TX_POWER_MODE_SET_ACK = 3,
IWL_TX_POWER_MODE_SET_SAR_TIMER = 4,
IWL_TX_POWER_MODE_SET_SAR_TIMER_DEFAULT_TABLE = 5,
-}; /* TX_POWER_REDUCED_FLAGS_TYPE_API_E_VER_5 */;
+ IWL_TX_POWER_MODE_SET_STANDALONE_CHAINS = 8, /* cmd ver 12+ */
+}; /* TX_POWER_REDUCED_FLAGS_TYPE_API_E_VER_2 */;
#define IWL_NUM_CHAIN_TABLES 1
#define IWL_NUM_CHAIN_TABLES_V2 2
@@ -464,31 +465,34 @@ struct iwl_dev_tx_power_cmd_v10 {
__le32 flags;
} __packed; /* TX_REDUCED_POWER_API_S_VER_10 */
-struct iwl_dev_tx_power_cmd_v11 {
+struct iwl_dev_tx_power_cmd_v12 {
__le16 per_chain[IWL_NUM_CHAIN_TABLES_V2][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V3];
u8 per_chain_restriction_changed;
u8 reserved;
__le32 timer_period;
__le32 flags;
-} __packed; /* TX_REDUCED_POWER_API_S_VER_11 */
+} __packed; /* TX_REDUCED_POWER_API_S_VER_11
+ * TX_REDUCED_POWER_API_S_VER_12
+ */
/*
* struct iwl_dev_tx_power_cmd - TX power reduction command (multiversion)
* @common: common part of the command
* @v9: version 9 part of the command
* @v10: version 10 part of the command
- * @v11: version 11 part of the command
+ * @v12: version 12 part of the command (also covers v11)
*/
struct iwl_dev_tx_power_cmd {
struct iwl_dev_tx_power_common common;
union {
struct iwl_dev_tx_power_cmd_v9 v9;
struct iwl_dev_tx_power_cmd_v10 v10;
- struct iwl_dev_tx_power_cmd_v11 v11;
+ struct iwl_dev_tx_power_cmd_v12 v12;
};
} __packed; /* TX_REDUCED_POWER_API_S_VER_9
* TX_REDUCED_POWER_API_S_VER_10
* TX_REDUCED_POWER_API_S_VER_11
+ * TX_REDUCED_POWER_API_S_VER_12
*/
#define IWL_NUM_GEO_PROFILES 3
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
index a8f1edf19bbef..20460534fc99d 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
@@ -583,7 +583,11 @@ struct iwl_rx_mpdu_desc_v3 {
/**
* @reserved_xsum: reserved high bits in the raw checksum
*/
- __le16 reserved_xsum;
+ u8 reserved_xsum;
+ /**
+ * @mac_context: MAC context mask, in this DW only from API version 10
+ */
+ u8 mac_context;
/* DW11 */
/**
* @rate_n_flags: RX rate/flags encoding
@@ -603,9 +607,10 @@ struct iwl_rx_mpdu_desc_v3 {
*/
u8 channel;
/**
- * @mac_context: MAC context mask
+ * @ru: RU/MRU/DRU used for the frame, in trigger-like format;
+ * only from API version 10, this byte held @mac_context before
*/
- u8 mac_context;
+ u8 ru;
/* DW13 */
/**
* @gp2_on_air_rise: GP2 timer value on air rise (INA)
@@ -647,7 +652,11 @@ struct iwl_rx_mpdu_desc_v3 {
__le32 reserved[1];
} __packed; /* RX_MPDU_RES_START_API_S_VER_3,
* RX_MPDU_RES_START_API_S_VER_5,
- * RX_MPDU_RES_START_API_S_VER_6
+ * RX_MPDU_RES_START_API_S_VER_6,
+ * RX_MPDU_RES_START_API_S_VER_7,
+ * RX_MPDU_RES_START_API_S_VER_8,
+ * RX_MPDU_RES_START_API_S_VER_9,
+ * RX_MPDU_RES_START_API_S_VER_10
*/
/**
@@ -737,6 +746,8 @@ struct iwl_rx_mpdu_desc {
* RX_MPDU_RES_START_API_S_VER_6
* RX_MPDU_RES_START_API_S_VER_7
* RX_MPDU_RES_START_API_S_VER_8
+ * RX_MPDU_RES_START_API_S_VER_9
+ * RX_MPDU_RES_START_API_S_VER_10
*/
#define IWL_RX_DESC_SIZE_V1 offsetofend(struct iwl_rx_mpdu_desc, v1)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index 8c8d15ac71ac0..897538066b7de 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -2055,7 +2055,7 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
if (trigger->flags & IWL_FW_DBG_FORCE_RESTART) {
IWL_WARN(fwrt, "Force restart: trigger %d fired.\n",
trig);
- iwl_force_nmi(fwrt->trans);
+ iwl_trans_force_nmi(fwrt->trans);
return 0;
}
@@ -2233,7 +2233,8 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx)
}
if (fwrt->trans->dbg.last_tp_resetfw == IWL_FW_INI_RESET_FW_MODE_STOP_FW_ONLY)
- iwl_force_nmi(fwrt->trans);
+ iwl_trans_force_nmi(fwrt->trans);
+
out:
if (iwl_trans_dbg_ini_valid(fwrt->trans)) {
iwl_fw_error_dump_data_free(dump_data);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c
index 137303e4a29bc..c7de45323935e 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c
@@ -49,11 +49,16 @@ static const struct dmi_system_id dmi_ppag_approved_list[] = {
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
},
},
- { .ident = "SAMSUNG",
+ { .ident = "SAMSUNG_ELECTRONICS",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"),
},
},
+ { .ident = "SAMSUNG",
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Samsung"),
+ },
+ },
{ .ident = "MSFT",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
@@ -126,10 +131,15 @@ static const struct dmi_system_id dmi_tas_approved_list[] = {
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
},
},
- { .ident = "SAMSUNG",
+ { .ident = "SAMSUNG_ELECTRONICS",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"),
},
+ },
+ { .ident = "SAMSUNG",
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Samsung"),
+ },
},
{ .ident = "LENOVO",
.matches = {
@@ -247,17 +257,22 @@ IWL_EXPORT_SYMBOL(iwl_sar_geo_fill_table);
static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt,
__le16 *per_chain, u32 n_subbands,
- int prof_a, int prof_b)
+ int prof_a, int prof_b,
+ const struct iwl_sar_profile *profiles,
+ bool is_standalone)
{
int profs[BIOS_SAR_NUM_CHAINS] = { prof_a, prof_b };
int i, j;
+ BUILD_BUG_ON(ARRAY_SIZE(fwrt->sar_standalone_profiles[0].chains[0].subbands) !=
+ ARRAY_SIZE(fwrt->sar_profiles[0].chains[0].subbands));
+
if (WARN_ON_ONCE(n_subbands >
ARRAY_SIZE(fwrt->sar_profiles[0].chains[0].subbands)))
return -EINVAL;
for (i = 0; i < BIOS_SAR_NUM_CHAINS; i++) {
- struct iwl_sar_profile *prof;
+ const struct iwl_sar_profile *prof;
/* don't allow SAR to be disabled (profile 0 means disable) */
if (profs[i] == 0)
@@ -268,11 +283,13 @@ static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt,
return -EINVAL;
/* profiles go from 1 to 4, so decrement to access the array */
- prof = &fwrt->sar_profiles[profs[i] - 1];
+ prof = &profiles[profs[i] - 1];
/* if the profile is disabled, do nothing */
if (!prof->enabled) {
- IWL_DEBUG_RADIO(fwrt, "SAR profile %d is disabled.\n",
+ IWL_DEBUG_RADIO(fwrt,
+ "SAR %sprofile %d is disabled.\n",
+ is_standalone ? "standalone " : "",
profs[i]);
/*
* if one of the profiles is disabled, we
@@ -282,8 +299,8 @@ static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt,
return 1;
}
- IWL_DEBUG_INFO(fwrt,
- "SAR EWRD: chain %d profile index %d\n",
+ IWL_DEBUG_INFO(fwrt, "SAR %s: chain %d profile index %d\n",
+ is_standalone ? "standalone" : "EWRD",
i, profs[i]);
IWL_DEBUG_RADIO(fwrt, " Chain[%d]:\n", i);
for (j = 0; j < n_subbands; j++) {
@@ -299,14 +316,17 @@ static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt,
int iwl_sar_fill_profile(struct iwl_fw_runtime *fwrt,
__le16 *per_chain, u32 n_tables, u32 n_subbands,
- int prof_a, int prof_b)
+ int prof_a, int prof_b,
+ const struct iwl_sar_profile *profiles,
+ bool is_standalone)
{
int i, ret = 0;
for (i = 0; i < n_tables; i++) {
ret = iwl_sar_fill_table(fwrt,
&per_chain[i * n_subbands * BIOS_SAR_NUM_CHAINS],
- n_subbands, prof_a, prof_b);
+ n_subbands, prof_a, prof_b, profiles,
+ is_standalone);
if (ret)
break;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h
index bd7ea0ff3d19b..e32e107812b1a 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h
@@ -210,7 +210,9 @@ int iwl_sar_geo_fill_table(struct iwl_fw_runtime *fwrt,
int iwl_sar_fill_profile(struct iwl_fw_runtime *fwrt,
__le16 *per_chain, u32 n_tables, u32 n_subbands,
- int prof_a, int prof_b);
+ int prof_a, int prof_b,
+ const struct iwl_sar_profile *profiles,
+ bool is_standalone);
bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
index 79fd95d08732b..dffd5e68f41da 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
@@ -251,15 +251,24 @@ static int iwl_uefi_reduce_power_section(struct iwl_trans *trans,
memset(pnvm_data, 0, sizeof(*pnvm_data));
while (len >= sizeof(*tlv)) {
- u32 tlv_len, tlv_type;
+ u32 tlv_len, tlv_type, tlv_len_aligned;
len -= sizeof(*tlv);
tlv = (const void *)data;
tlv_len = le32_to_cpu(tlv->length);
tlv_type = le32_to_cpu(tlv->type);
+ tlv_len_aligned = ALIGN(tlv_len, 4);
- if (len < tlv_len) {
+ /* Make sure ALIGN() did not overflow for a malformed TLV length. */
+ if (tlv_len_aligned < tlv_len) {
+ IWL_ERR(trans,
+ "TLV len overflows on alignment: %u\n",
+ tlv_len);
+ return -EINVAL;
+ }
+
+ if (len < tlv_len_aligned) {
IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
len, tlv_len);
return -EINVAL;
@@ -278,13 +287,13 @@ static int iwl_uefi_reduce_power_section(struct iwl_trans *trans,
"New REDUCE_POWER section started, stop parsing.\n");
goto done;
default:
- IWL_DEBUG_FW(trans, "Found TLV 0x%0x, len %d\n",
+ IWL_DEBUG_FW(trans, "Found TLV 0x%0x, len %u\n",
tlv_type, tlv_len);
break;
}
- len -= ALIGN(tlv_len, 4);
- data += ALIGN(tlv_len, 4);
+ len -= tlv_len_aligned;
+ data += tlv_len_aligned;
}
done:
@@ -305,15 +314,24 @@ int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
IWL_DEBUG_FW(trans, "Parsing REDUCE_POWER data\n");
while (len >= sizeof(*tlv)) {
- u32 tlv_len, tlv_type;
+ u32 tlv_len, tlv_type, tlv_len_aligned;
len -= sizeof(*tlv);
tlv = (const void *)data;
tlv_len = le32_to_cpu(tlv->length);
tlv_type = le32_to_cpu(tlv->type);
+ tlv_len_aligned = ALIGN(tlv_len, 4);
+
+ /* Make sure ALIGN() did not overflow for a malformed TLV length. */
+ if (tlv_len_aligned < tlv_len) {
+ IWL_ERR(trans,
+ "TLV len overflows on alignment: %u\n",
+ tlv_len);
+ return -EINVAL;
+ }
- if (len < tlv_len) {
+ if (len < tlv_len_aligned) {
IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
len, tlv_len);
return -EINVAL;
@@ -323,8 +341,15 @@ int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
const struct iwl_sku_id *tlv_sku_id =
(const void *)(data + sizeof(*tlv));
+ if (tlv_len < sizeof(*tlv_sku_id)) {
+ IWL_ERR(trans,
+ "Invalid IWL_UCODE_TLV_PNVM_SKU len %u\n",
+ tlv_len);
+ return -EINVAL;
+ }
+
IWL_DEBUG_FW(trans,
- "Got IWL_UCODE_TLV_PNVM_SKU len %d\n",
+ "Got IWL_UCODE_TLV_PNVM_SKU len %u\n",
tlv_len);
if (tlv_len < sizeof(*tlv_sku_id)) {
IWL_ERR(trans, "invalid PNVM SKU TLV len: %u\n",
@@ -337,8 +362,8 @@ int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
le32_to_cpu(tlv_sku_id->data[1]),
le32_to_cpu(tlv_sku_id->data[2]));
- data += sizeof(*tlv) + ALIGN(tlv_len, 4);
- len -= ALIGN(tlv_len, 4);
+ data += sizeof(*tlv) + tlv_len_aligned;
+ len -= tlv_len_aligned;
if (sku_id[0] == tlv_sku_id->data[0] &&
sku_id[1] == tlv_sku_id->data[1] &&
@@ -352,8 +377,8 @@ int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
IWL_DEBUG_FW(trans, "SKU ID didn't match!\n");
}
} else {
- data += sizeof(*tlv) + ALIGN(tlv_len, 4);
- len -= ALIGN(tlv_len, 4);
+ data += sizeof(*tlv) + tlv_len_aligned;
+ len -= tlv_len_aligned;
}
}
@@ -549,7 +574,7 @@ IWL_EXPORT_SYMBOL(iwl_uefi_get_uneb_table);
static void iwl_uefi_set_sar_profile(struct iwl_sar_profile *profiles,
const u8 *vals, u8 prof_index,
- u8 num_subbands, bool enabled)
+ u8 num_subbands, u32 mode)
{
struct iwl_sar_profile *sar_prof = &profiles[prof_index];
@@ -573,7 +598,7 @@ static void iwl_uefi_set_sar_profile(struct iwl_sar_profile *profiles,
vals[chain * num_subbands + subband];
}
- sar_prof->enabled = enabled & IWL_SAR_ENABLE_MSK;
+ sar_prof->enabled = mode & IWL_SAR_ENABLE_MSK;
}
int iwl_uefi_get_wrds_table(struct iwl_fw_runtime *fwrt)
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c
index bb746112ddadf..cc6bf4ea5055d 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c
@@ -10,8 +10,6 @@
#include "iwl-io.h"
#include "iwl-csr.h"
#include "iwl-debug.h"
-#include "iwl-prph.h"
-#include "iwl-fh.h"
void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val)
{
@@ -217,232 +215,3 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
}
}
IWL_EXPORT_SYMBOL(iwl_clear_bits_prph);
-
-void iwl_force_nmi(struct iwl_trans *trans)
-{
- if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_9000)
- iwl_write_prph_delay(trans, DEVICE_SET_NMI_REG,
- DEVICE_SET_NMI_VAL_DRV, 1);
- else if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
- iwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER,
- UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER);
- else if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
- iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
- UREG_DOORBELL_TO_ISR6_NMI_BIT);
- else
- iwl_write32(trans, CSR_DOORBELL_VECTOR,
- UREG_DOORBELL_TO_ISR6_NMI_BIT);
-}
-IWL_EXPORT_SYMBOL(iwl_force_nmi);
-
-static const char *get_rfh_string(int cmd)
-{
-#define IWL_CMD(x) case x: return #x
-#define IWL_CMD_MQ(arg, reg, q) { if (arg == reg(q)) return #reg; }
-
- int i;
-
- for (i = 0; i < IWL_MAX_RX_HW_QUEUES; i++) {
- IWL_CMD_MQ(cmd, RFH_Q_FRBDCB_BA_LSB, i);
- IWL_CMD_MQ(cmd, RFH_Q_FRBDCB_WIDX, i);
- IWL_CMD_MQ(cmd, RFH_Q_FRBDCB_RIDX, i);
- IWL_CMD_MQ(cmd, RFH_Q_URBD_STTS_WPTR_LSB, i);
- }
-
- switch (cmd) {
- IWL_CMD(RFH_RXF_DMA_CFG);
- IWL_CMD(RFH_GEN_CFG);
- IWL_CMD(RFH_GEN_STATUS);
- IWL_CMD(FH_TSSR_TX_STATUS_REG);
- IWL_CMD(FH_TSSR_TX_ERROR_REG);
- default:
- return "UNKNOWN";
- }
-#undef IWL_CMD_MQ
-}
-
-struct reg {
- u32 addr;
- bool is64;
-};
-
-static int iwl_dump_rfh(struct iwl_trans *trans, char **buf)
-{
- int i, q;
- int num_q = trans->info.num_rxqs;
- static const u32 rfh_tbl[] = {
- RFH_RXF_DMA_CFG,
- RFH_GEN_CFG,
- RFH_GEN_STATUS,
- FH_TSSR_TX_STATUS_REG,
- FH_TSSR_TX_ERROR_REG,
- };
- static const struct reg rfh_mq_tbl[] = {
- { RFH_Q0_FRBDCB_BA_LSB, true },
- { RFH_Q0_FRBDCB_WIDX, false },
- { RFH_Q0_FRBDCB_RIDX, false },
- { RFH_Q0_URBD_STTS_WPTR_LSB, true },
- };
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
- if (buf) {
- int pos = 0;
- /*
- * Register (up to 34 for name + 8 blank/q for MQ): 40 chars
- * Colon + space: 2 characters
- * 0X%08x: 10 characters
- * New line: 1 character
- * Total of 53 characters
- */
- size_t bufsz = ARRAY_SIZE(rfh_tbl) * 53 +
- ARRAY_SIZE(rfh_mq_tbl) * 53 * num_q + 40;
-
- *buf = kmalloc(bufsz, GFP_KERNEL);
- if (!*buf)
- return -ENOMEM;
-
- pos += scnprintf(*buf + pos, bufsz - pos,
- "RFH register values:\n");
-
- for (i = 0; i < ARRAY_SIZE(rfh_tbl); i++)
- pos += scnprintf(*buf + pos, bufsz - pos,
- "%40s: 0X%08x\n",
- get_rfh_string(rfh_tbl[i]),
- iwl_read_prph(trans, rfh_tbl[i]));
-
- for (i = 0; i < ARRAY_SIZE(rfh_mq_tbl); i++)
- for (q = 0; q < num_q; q++) {
- u32 addr = rfh_mq_tbl[i].addr;
-
- addr += q * (rfh_mq_tbl[i].is64 ? 8 : 4);
- pos += scnprintf(*buf + pos, bufsz - pos,
- "%34s(q %2d): 0X%08x\n",
- get_rfh_string(addr), q,
- iwl_read_prph(trans, addr));
- }
-
- return pos;
- }
-#endif
-
- IWL_ERR(trans, "RFH register values:\n");
- for (i = 0; i < ARRAY_SIZE(rfh_tbl); i++)
- IWL_ERR(trans, " %34s: 0X%08x\n",
- get_rfh_string(rfh_tbl[i]),
- iwl_read_prph(trans, rfh_tbl[i]));
-
- for (i = 0; i < ARRAY_SIZE(rfh_mq_tbl); i++)
- for (q = 0; q < num_q; q++) {
- u32 addr = rfh_mq_tbl[i].addr;
-
- addr += q * (rfh_mq_tbl[i].is64 ? 8 : 4);
- IWL_ERR(trans, " %34s(q %d): 0X%08x\n",
- get_rfh_string(addr), q,
- iwl_read_prph(trans, addr));
- }
-
- return 0;
-}
-
-static const char *get_fh_string(int cmd)
-{
- switch (cmd) {
- IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
- IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
- IWL_CMD(FH_RSCSR_CHNL0_WPTR);
- IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
- IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
- IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
- IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
- IWL_CMD(FH_TSSR_TX_STATUS_REG);
- IWL_CMD(FH_TSSR_TX_ERROR_REG);
- default:
- return "UNKNOWN";
- }
-#undef IWL_CMD
-}
-
-int iwl_dump_fh(struct iwl_trans *trans, char **buf)
-{
- int i;
- static const u32 fh_tbl[] = {
- FH_RSCSR_CHNL0_STTS_WPTR_REG,
- FH_RSCSR_CHNL0_RBDCB_BASE_REG,
- FH_RSCSR_CHNL0_WPTR,
- FH_MEM_RCSR_CHNL0_CONFIG_REG,
- FH_MEM_RSSR_SHARED_CTRL_REG,
- FH_MEM_RSSR_RX_STATUS_REG,
- FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
- FH_TSSR_TX_STATUS_REG,
- FH_TSSR_TX_ERROR_REG
- };
-
- if (trans->mac_cfg->mq_rx_supported)
- return iwl_dump_rfh(trans, buf);
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
- if (buf) {
- int pos = 0;
- size_t bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
-
- *buf = kmalloc(bufsz, GFP_KERNEL);
- if (!*buf)
- return -ENOMEM;
-
- pos += scnprintf(*buf + pos, bufsz - pos,
- "FH register values:\n");
-
- for (i = 0; i < ARRAY_SIZE(fh_tbl); i++)
- pos += scnprintf(*buf + pos, bufsz - pos,
- " %34s: 0X%08x\n",
- get_fh_string(fh_tbl[i]),
- iwl_read_direct32(trans, fh_tbl[i]));
-
- return pos;
- }
-#endif
-
- IWL_ERR(trans, "FH register values:\n");
- for (i = 0; i < ARRAY_SIZE(fh_tbl); i++)
- IWL_ERR(trans, " %34s: 0X%08x\n",
- get_fh_string(fh_tbl[i]),
- iwl_read_direct32(trans, fh_tbl[i]));
-
- return 0;
-}
-
-void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr,
- u32 sw_err_bit)
-{
- unsigned long timeout = jiffies + IWL_TRANS_NMI_TIMEOUT;
- bool interrupts_enabled = test_bit(STATUS_INT_ENABLED, &trans->status);
-
- /* if the interrupts were already disabled, there is no point in
- * calling iwl_disable_interrupts
- */
- if (interrupts_enabled)
- iwl_trans_interrupts(trans, false);
-
- iwl_force_nmi(trans);
- while (time_after(timeout, jiffies)) {
- u32 inta_hw = iwl_read32(trans, inta_addr);
-
- /* Error detected by uCode */
- if (inta_hw & sw_err_bit) {
- /* Clear causes register */
- iwl_write32(trans, inta_addr, inta_hw & sw_err_bit);
- break;
- }
-
- mdelay(1);
- }
-
- /* enable interrupts only if there were already enabled before this
- * function to avoid a case were the driver enable interrupts before
- * proper configurations were made
- */
- if (interrupts_enabled)
- iwl_trans_interrupts(trans, true);
-
- iwl_trans_fw_error(trans, IWL_ERR_TYPE_NMI_FORCED);
-}
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-io.h
index 6dce2e5267a64..e4a9f2ba0de93 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.h
@@ -57,10 +57,6 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);
void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
u32 bits, u32 mask);
void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);
-void iwl_force_nmi(struct iwl_trans *trans);
-
-/* Error handling */
-int iwl_dump_fh(struct iwl_trans *trans, char **buf);
/*
* UMAC periphery address space changed from 0xA00000 to 0xD00000 starting from
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
index 6bb27d7f1166e..413dd55115f8f 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
@@ -612,7 +612,6 @@ static const struct ieee80211_sband_iftype_data iwl_iftype_cap[] = {
IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP |
IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI,
.phy_cap_info[8] =
- IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI |
IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |
IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |
IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU |
@@ -747,7 +746,6 @@ static const struct ieee80211_sband_iftype_data iwl_iftype_cap[] = {
.phy_cap_info[7] =
IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI,
.phy_cap_info[8] =
- IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI |
IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_242,
.phy_cap_info[9] =
IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
index a1545e9d2cd84..0a6b7b264aa23 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
@@ -10,9 +10,10 @@
#include "iwl-trans.h"
#include "iwl-drv.h"
+#include "iwl-prph.h"
#include <linux/dmapool.h>
#include "fw/api/commands.h"
-#include "pcie/gen1_2/internal.h"
+#include "pcie/internal.h"
#include "pcie/iwl-context-info-v2.h"
struct iwl_trans_dev_restart_data {
@@ -333,14 +334,14 @@ IWL_EXPORT_SYMBOL(iwl_trans_send_cmd);
struct iwl_device_tx_cmd *iwl_trans_alloc_tx_cmd(struct iwl_trans *trans)
{
- return iwl_pcie_gen1_2_alloc_tx_cmd(trans);
+ return iwl_pcie_alloc_tx_cmd(trans);
}
IWL_EXPORT_SYMBOL(iwl_trans_alloc_tx_cmd);
void iwl_trans_free_tx_cmd(struct iwl_trans *trans,
struct iwl_device_tx_cmd *dev_cmd)
{
- iwl_pcie_gen1_2_free_tx_cmd(trans, dev_cmd);
+ iwl_pcie_free_tx_cmd(trans, dev_cmd);
}
IWL_EXPORT_SYMBOL(iwl_trans_free_tx_cmd);
@@ -395,7 +396,7 @@ void iwl_trans_op_mode_enter(struct iwl_trans *trans,
WARN_ON_ONCE(!trans->conf.rx_mpdu_cmd);
- iwl_pcie_gen1_2_op_mode_enter(trans);
+ iwl_trans_pcie_op_mode_enter(trans);
}
IWL_EXPORT_SYMBOL(iwl_trans_op_mode_enter);
@@ -452,6 +453,23 @@ void iwl_trans_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
return iwl_trans_pcie_write_prph(trans, ofs, val);
}
+void iwl_trans_force_nmi(struct iwl_trans *trans)
+{
+ if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_9000)
+ iwl_write_prph_delay(trans, DEVICE_SET_NMI_REG,
+ DEVICE_SET_NMI_VAL_DRV, 1);
+ else if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
+ iwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER,
+ UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER);
+ else if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
+ iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
+ UREG_DOORBELL_TO_ISR6_NMI_BIT);
+ else
+ iwl_write32(trans, CSR_DOORBELL_VECTOR,
+ UREG_DOORBELL_TO_ISR6_NMI_BIT);
+}
+IWL_EXPORT_SYMBOL(iwl_trans_force_nmi);
+
int iwl_trans_read_mem(struct iwl_trans *trans, u32 addr,
void *buf, int dwords)
{
@@ -523,11 +541,6 @@ int iwl_trans_d3_resume(struct iwl_trans *trans, bool reset)
}
IWL_EXPORT_SYMBOL(iwl_trans_d3_resume);
-void iwl_trans_interrupts(struct iwl_trans *trans, bool enable)
-{
- iwl_trans_pci_interrupts(trans, enable);
-}
-
void iwl_trans_sync_nmi(struct iwl_trans *trans)
{
iwl_trans_pcie_sync_nmi(trans);
@@ -563,8 +576,7 @@ void iwl_trans_resched_with_nic_access(struct iwl_trans *trans)
iwl_trans_pcie_resched_with_nic_access(trans);
}
-void __releases(nic_access)
-iwl_trans_release_nic_access(struct iwl_trans *trans)
+void iwl_trans_release_nic_access(struct iwl_trans *trans)
{
iwl_trans_pcie_release_nic_access(trans);
}
@@ -821,13 +833,13 @@ IWL_EXPORT_SYMBOL(iwl_trans_is_pm_supported);
bool iwl_trans_is_ltr_enabled(struct iwl_trans *trans)
{
- return iwl_pcie_gen1_2_is_ltr_enabled(trans);
+ return iwl_pcie_is_ltr_enabled(trans);
}
IWL_EXPORT_SYMBOL(iwl_trans_is_ltr_enabled);
int iwl_trans_activate_nic(struct iwl_trans *trans)
{
- return iwl_pcie_gen1_2_activate_nic(trans);
+ return iwl_pcie_activate_nic(trans);
}
IWL_EXPORT_SYMBOL(iwl_trans_activate_nic);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
index dfad839dd2e69..56c5e61b614ad 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
@@ -992,8 +992,7 @@ bool iwl_trans_grab_nic_access(struct iwl_trans *trans);
*/
void iwl_trans_resched_with_nic_access(struct iwl_trans *trans);
-void __releases(nic_access)
-iwl_trans_release_nic_access(struct iwl_trans *trans);
+void iwl_trans_release_nic_access(struct iwl_trans *trans);
static inline void iwl_trans_schedule_reset(struct iwl_trans *trans,
enum iwl_fw_error_type type)
@@ -1055,8 +1054,7 @@ static inline bool iwl_trans_fw_running(struct iwl_trans *trans)
void iwl_trans_sync_nmi(struct iwl_trans *trans);
-void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr,
- u32 sw_err_bit);
+void iwl_trans_force_nmi(struct iwl_trans *trans);
int iwl_trans_load_pnvm(struct iwl_trans *trans,
const struct iwl_pnvm_image *pnvm_data,
@@ -1078,8 +1076,6 @@ static inline bool iwl_trans_dbg_ini_valid(struct iwl_trans *trans)
trans->dbg.external_ini_cfg != IWL_INI_CFG_STATE_NOT_LOADED;
}
-void iwl_trans_interrupts(struct iwl_trans *trans, bool enable);
-
int iwl_trans_activate_nic(struct iwl_trans *trans);
static inline void iwl_trans_finish_sw_reset(struct iwl_trans *trans)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/agg.c b/drivers/net/wireless/intel/iwlwifi/mld/agg.c
index c45c47337509e..ea1f02380ad4e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/agg.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/agg.c
@@ -660,6 +660,7 @@ int iwl_mld_update_sta_baids(struct iwl_mld *mld,
.modify.new_sta_id_mask = cpu_to_le32(new_sta_mask),
};
u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, RX_BAID_ALLOCATION_CONFIG_CMD);
+ u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 2);
int baid;
/* mac80211 will remove sessions later, but we ignore all that */
@@ -667,6 +668,7 @@ int iwl_mld_update_sta_baids(struct iwl_mld *mld,
return 0;
BUILD_BUG_ON(sizeof(struct iwl_rx_baid_cfg_resp) != sizeof(baid));
+ BUILD_BUG_ON(sizeof(cmd.modify) != sizeof(cmd.modify_v2));
for (baid = 0; baid < ARRAY_SIZE(mld->fw_id_to_ba); baid++) {
struct iwl_mld_baid_data *data;
@@ -683,7 +685,10 @@ int iwl_mld_update_sta_baids(struct iwl_mld *mld,
"BAID data for %d corrupted - expected 0x%x found 0x%x\n",
baid, old_sta_mask, data->sta_mask);
- cmd.modify.tid = cpu_to_le32(data->tid);
+ if (cmd_ver >= 3)
+ cmd.modify.tid = data->tid;
+ else
+ cmd.modify_v2.tid = cpu_to_le32(data->tid);
ret = iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd);
if (ret)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c
index 351a4f177e920..dd4bf7cb6a791 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c
@@ -69,7 +69,7 @@ static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mld *mld, char *buf,
if (count == 6 && !strcmp(buf, "nolog\n"))
mld->fw_status.do_not_dump_once = true;
- iwl_force_nmi(mld->trans);
+ iwl_trans_force_nmi(mld->trans);
return count;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/power.c b/drivers/net/wireless/intel/iwlwifi/mld/power.c
index 2387f3da5185a..6fcbb1a2e8a8f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/power.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/power.c
@@ -525,7 +525,7 @@ int iwl_mld_set_tx_power(struct iwl_mld *mld,
.common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_LINK),
.common.pwr_restriction = cpu_to_le16(u_tx_power),
};
- int len = sizeof(cmd.common) + sizeof(cmd.v11);
+ int len = sizeof(cmd.common) + sizeof(cmd.v12);
if (iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 10) == 10)
len = sizeof(cmd.common) + sizeof(cmd.v10);
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c
index 9f395a1fd12ae..8a20d7622329c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c
@@ -74,6 +74,21 @@ void iwl_mld_get_bios_tables(struct iwl_mld *mld)
"EWRD SAR BIOS table invalid or unavailable. (%d)\n",
ret);
+ ret = iwl_bios_get_wsss_table(&mld->fwrt);
+ if (ret < 0)
+ IWL_DEBUG_RADIO(mld,
+ "WSSS (WRDS Standalone) SAR BIOS table invalid or unavailable. (%d)\n",
+ ret);
+
+ if (!ret) {
+ /* EWSS only extends the standalone SAR profiles from WSSS. */
+ ret = iwl_bios_get_ewss_table(&mld->fwrt);
+ if (ret < 0)
+ IWL_DEBUG_RADIO(mld,
+ "EWSS (EWRD Standalone) SAR BIOS table invalid or unavailable. (%d)\n",
+ ret);
+ }
+
ret = iwl_bios_get_wgds_table(&mld->fwrt);
if (ret < 0)
IWL_DEBUG_RADIO(mld,
@@ -135,7 +150,9 @@ static int iwl_mld_geo_sar_init(struct iwl_mld *mld)
return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, cmd_size);
}
-int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b)
+static int
+iwl_mld_config_sar_concurrent_profile(struct iwl_mld *mld, int prof_a,
+ int prof_b)
{
struct iwl_dev_tx_power_cmd cmd = {
.common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS),
@@ -152,8 +169,9 @@ int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b)
num_subbands = IWL_NUM_SUB_BANDS_V2;
break;
case 11:
- cmd.v11.flags = cpu_to_le32(mld->fwrt.reduced_power_flags);
- cmd_size = sizeof(cmd.common) + sizeof(cmd.v11);
+ case 12:
+ cmd.v12.flags = cpu_to_le32(mld->fwrt.reduced_power_flags);
+ cmd_size = sizeof(cmd.common) + sizeof(cmd.v12);
num_subbands = IWL_NUM_SUB_BANDS_V3;
break;
default:
@@ -163,12 +181,13 @@ int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b)
}
/* TODO: CDB - support IWL_NUM_CHAIN_TABLES_V2 */
- /* v10 and v11 have the same position for per_chain */
- BUILD_BUG_ON(offsetof(typeof(cmd), v11.per_chain) !=
+ /* v10 and v12 have the same position for per_chain */
+ BUILD_BUG_ON(offsetof(typeof(cmd), v12.per_chain) !=
offsetof(typeof(cmd), v10.per_chain));
- ret = iwl_sar_fill_profile(&mld->fwrt, &cmd.v11.per_chain[0][0][0],
+ ret = iwl_sar_fill_profile(&mld->fwrt, &cmd.v12.per_chain[0][0][0],
IWL_NUM_CHAIN_TABLES, num_subbands,
- prof_a, prof_b);
+ prof_a, prof_b,
+ mld->fwrt.sar_profiles, false);
/* return on error or if the profile is disabled (positive number) */
if (ret)
return ret;
@@ -176,6 +195,51 @@ int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b)
return iwl_mld_send_cmd_pdu(mld, REDUCE_TX_POWER_CMD, &cmd, cmd_size);
}
+static int iwl_mld_config_sar_standalone_profile(struct iwl_mld *mld,
+ int prof_a, int prof_b)
+{
+ struct iwl_dev_tx_power_cmd cmd = {
+ .common.set_mode =
+ cpu_to_le32(IWL_TX_POWER_MODE_SET_STANDALONE_CHAINS),
+ };
+ int ret;
+
+ /* standalone per-chain SAR limits require cmd version 12 */
+ if (iwl_fw_lookup_cmd_ver(mld->fw, REDUCE_TX_POWER_CMD, 10) != 12)
+ return 0;
+
+ ret = iwl_sar_fill_profile(&mld->fwrt,
+ &cmd.v12.per_chain[0][0][0],
+ IWL_NUM_CHAIN_TABLES,
+ IWL_NUM_SUB_BANDS_V3,
+ prof_a, prof_b,
+ mld->fwrt.sar_standalone_profiles,
+ true);
+ /* return on error or if the standalone profile is disabled */
+ if (ret)
+ return ret;
+
+ return iwl_mld_send_cmd_pdu(mld, REDUCE_TX_POWER_CMD, &cmd,
+ sizeof(cmd.common) + sizeof(cmd.v12));
+}
+
+int iwl_mld_config_sar_profiles(struct iwl_mld *mld, int prof_a, int prof_b)
+{
+ int ret;
+
+ ret = iwl_mld_config_sar_concurrent_profile(mld, prof_a, prof_b);
+ /* return on error or if the profile is disabled (positive number) */
+ if (ret)
+ return ret;
+
+ ret = iwl_mld_config_sar_standalone_profile(mld, prof_a, prof_b);
+ /* standalone profile is optional and may be disabled (positive number) */
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
int iwl_mld_init_sar(struct iwl_mld *mld)
{
int chain_a_prof = 1;
@@ -190,7 +254,7 @@ int iwl_mld_init_sar(struct iwl_mld *mld)
chain_b_prof = mld->fwrt.sar_chain_b_profile;
}
- ret = iwl_mld_config_sar_profile(mld, chain_a_prof, chain_b_prof);
+ ret = iwl_mld_config_sar_profiles(mld, chain_a_prof, chain_b_prof);
if (ret < 0)
return ret;
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.h b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.h
index 5498c19789f4e..0877b951f2e27 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2024-2025 Intel Corporation
+ * Copyright (C) 2024-2026 Intel Corporation
*/
#ifndef __iwl_mld_regulatory_h__
#define __iwl_mld_regulatory_h__
@@ -18,6 +18,6 @@ int iwl_mld_init_sgom(struct iwl_mld *mld);
int iwl_mld_init_sar(struct iwl_mld *mld);
-int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b);
+int iwl_mld_config_sar_profiles(struct iwl_mld *mld, int prof_a, int prof_b);
#endif /* __iwl_mld_regulatory_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index 4db0f29dd21af..06502f57e823e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -1102,7 +1102,7 @@ static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
if (count == 6 && !strcmp(buf, "nolog\n"))
set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status);
- iwl_force_nmi(mvm->trans);
+ iwl_trans_force_nmi(mvm->trans);
return count;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 0b5b41223a8a7..c3402f5e47a03 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -911,7 +911,8 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
ret = iwl_sar_fill_profile(&mvm->fwrt, per_chain,
IWL_NUM_CHAIN_TABLES,
- n_subbands, prof_a, prof_b);
+ n_subbands, prof_a, prof_b,
+ mvm->fwrt.sar_profiles, false);
/* return on error or if the profile is disabled (positive number) */
if (ret)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 5bd246e379432..a4f3d3c2bd350 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -5258,7 +5258,7 @@ iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm,
out_restart:
/* things keep failing, better restart the hw */
- iwl_force_nmi(mvm->trans);
+ iwl_trans_force_nmi(mvm->trans);
return ret;
}
@@ -5294,7 +5294,7 @@ iwl_mvm_switch_vif_chanctx_reassign(struct iwl_mvm *mvm,
out_restart:
/* things keep failing, better restart the hw */
- iwl_force_nmi(mvm->trans);
+ iwl_trans_force_nmi(mvm->trans);
return ret;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index 817c6dacfaccd..a94eaca0b3ed5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -2703,7 +2703,7 @@ void iwl_mvm_scan_timeout_wk(struct work_struct *work)
IWL_ERR(mvm, "regular scan timed out\n");
- iwl_force_nmi(mvm->trans);
+ iwl_trans_force_nmi(mvm->trans);
}
static void iwl_mvm_fill_scan_type(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c
index 1ea23d297713a..c75210829ec94 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c
@@ -6,7 +6,7 @@
#include "iwl-trans.h"
#include "iwl-fh.h"
#include "iwl-context-info-v2.h"
-#include "gen1_2/internal.h"
+#include "internal.h"
#include "iwl-prph.h"
static const struct dmi_system_id dmi_force_scu_active_approved_list[] = {
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
index 7f886200d6933..23ec968577bd9 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
@@ -6,7 +6,7 @@
#include "iwl-trans.h"
#include "iwl-fh.h"
#include "iwl-context-info.h"
-#include "gen1_2/internal.h"
+#include "internal.h"
#include "iwl-prph.h"
static void *_iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans,
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index a117c378b1f1e..905482419a9af 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -15,7 +15,7 @@
#include "iwl-trans.h"
#include "iwl-drv.h"
#include "iwl-prph.h"
-#include "gen1_2/internal.h"
+#include "internal.h"
#define _IS_A(cfg, _struct) __builtin_types_compatible_p(typeof(cfg), \
struct _struct)
@@ -1188,17 +1188,22 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return -EIO;
}
- return iwl_pci_gen1_2_probe(pdev, ent, mac_cfg, hw_base, hw_rev);
+ return _iwl_pci_probe(pdev, ent, mac_cfg, hw_base, hw_rev);
}
static void iwl_pci_remove(struct pci_dev *pdev)
{
struct iwl_trans *trans = pci_get_drvdata(pdev);
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
if (!trans)
return;
- iwl_pcie_gen1_2_remove(trans);
+ cancel_delayed_work_sync(&trans_pcie->me_recheck_wk);
+
+ iwl_drv_stop(trans->drv);
+
+ iwl_trans_pcie_free(trans);
}
#ifdef CONFIG_PM_SLEEP
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
similarity index 98%
rename from drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h
rename to drivers/net/wireless/intel/iwlwifi/pcie/internal.h
index f0e70b0fedfe7..e6b1cb559a0a6 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
@@ -22,7 +22,7 @@
#include "iwl-io.h"
#include "iwl-op-mode.h"
#include "iwl-drv.h"
-#include "pcie/iwl-context-info.h"
+#include "iwl-context-info.h"
/*
* RX related structures and functions
@@ -850,7 +850,7 @@ static inline u16 iwl_txq_gen1_tfd_tb_get_len(struct iwl_trans *trans,
}
static inline struct iwl_device_tx_cmd *
-iwl_pcie_gen1_2_alloc_tx_cmd(struct iwl_trans *trans)
+iwl_pcie_alloc_tx_cmd(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -858,8 +858,8 @@ iwl_pcie_gen1_2_alloc_tx_cmd(struct iwl_trans *trans)
}
static inline void
-iwl_pcie_gen1_2_free_tx_cmd(struct iwl_trans *trans,
- struct iwl_device_tx_cmd *dev_cmd)
+iwl_pcie_free_tx_cmd(struct iwl_trans *trans,
+ struct iwl_device_tx_cmd *dev_cmd)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -1132,7 +1132,7 @@ static inline void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans) { }
void iwl_pcie_rx_allocator_work(struct work_struct *data);
/* common trans ops for all generations transports */
-void iwl_pcie_gen1_2_op_mode_enter(struct iwl_trans *trans);
+void iwl_trans_pcie_op_mode_enter(struct iwl_trans *trans);
int _iwl_trans_pcie_start_hw(struct iwl_trans *trans);
int iwl_trans_pcie_start_hw(struct iwl_trans *trans);
void iwl_trans_pcie_op_mode_leave(struct iwl_trans *trans);
@@ -1161,14 +1161,11 @@ int iwl_trans_pcie_read_config32(struct iwl_trans *trans, u32 ofs,
u32 *val);
bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans);
void iwl_trans_pcie_resched_with_nic_access(struct iwl_trans *trans);
-void __releases(nic_access_nobh)
-iwl_trans_pcie_release_nic_access(struct iwl_trans *trans);
+void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans);
void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power);
-int iwl_pci_gen1_2_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent,
- const struct iwl_mac_cfg *mac_cfg,
- u8 __iomem *hw_base, u32 hw_rev);
-void iwl_pcie_gen1_2_remove(struct iwl_trans *trans);
+int _iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent,
+ const struct iwl_mac_cfg *mac_cfg,
+ u8 __iomem *hw_base, u32 hw_rev);
/* transport gen 1 exported functions */
void iwl_trans_pcie_fw_alive(struct iwl_trans *trans);
@@ -1193,7 +1190,7 @@ int iwl_pcie_alloc_dma_ptr(struct iwl_trans *trans,
struct iwl_dma_ptr *ptr, size_t size);
void iwl_pcie_free_dma_ptr(struct iwl_trans *trans, struct iwl_dma_ptr *ptr);
void iwl_pcie_apply_destination(struct iwl_trans *trans);
-int iwl_pcie_gen1_2_activate_nic(struct iwl_trans *trans);
+int iwl_pcie_activate_nic(struct iwl_trans *trans);
/* transport gen 2 exported functions */
int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
@@ -1223,7 +1220,7 @@ static inline bool iwl_pcie_gen1_is_pm_supported(struct iwl_trans *trans)
return trans_pcie->pm_support;
}
-static inline bool iwl_pcie_gen1_2_is_ltr_enabled(struct iwl_trans *trans)
+static inline bool iwl_pcie_is_ltr_enabled(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
similarity index 99%
rename from drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c
rename to drivers/net/wireless/intel/iwlwifi/pcie/rx.c
index 4631e11f2a964..db3933b0d1979 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
@@ -12,7 +12,7 @@
#include "iwl-io.h"
#include "internal.h"
#include "iwl-op-mode.h"
-#include "pcie/iwl-context-info-v2.h"
+#include "iwl-context-info-v2.h"
#include "fw/dbg.h"
/******************************************************************************
@@ -1493,7 +1493,7 @@ static struct iwl_rx_mem_buffer *iwl_pcie_get_rxb(struct iwl_trans *trans,
out_err:
WARN(1, "Invalid rxb from HW %u\n", (u32)vid);
- iwl_force_nmi(trans);
+ iwl_trans_force_nmi(trans);
return NULL;
}
@@ -1519,6 +1519,11 @@ static int iwl_pcie_rx_handle(struct iwl_trans *trans, int queue, int budget)
r = iwl_get_closed_rb_stts(trans, rxq);
i = rxq->read;
+ /* Order the read of the write pointer before any read of the
+ * completion descriptors and of the RB contents it makes visible.
+ */
+ dma_rmb();
+
/* W/A 9000 device step A0 wrap-around bug */
r &= (rxq->queue_size - 1);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
similarity index 99%
rename from drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c
rename to drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
index f41cbe62e7aa5..39dd963920b31 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
@@ -5,8 +5,8 @@
*/
#include "iwl-trans.h"
#include "iwl-prph.h"
-#include "pcie/iwl-context-info.h"
-#include "pcie/iwl-context-info-v2.h"
+#include "iwl-context-info.h"
+#include "iwl-context-info-v2.h"
#include "internal.h"
#include "fw/dbg.h"
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
similarity index 98%
rename from drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c
rename to drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index 71c4746c61a6b..bda069a6f7ebf 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -28,7 +28,7 @@
#include "mei/iwl-mei.h"
#include "internal.h"
#include "iwl-fh.h"
-#include "pcie/iwl-context-info-v2.h"
+#include "iwl-context-info-v2.h"
#include "pcie/utils.h"
#define IWL_HOST_MON_BLOCK_PEMON 0x00
@@ -1903,7 +1903,7 @@ void iwl_trans_pcie_write_prph(struct iwl_trans *trans, u32 addr, u32 val)
iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WDAT, val);
}
-void iwl_pcie_gen1_2_op_mode_enter(struct iwl_trans *trans)
+void iwl_trans_pcie_op_mode_enter(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -2402,10 +2402,10 @@ bool _iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent)
out:
/*
- * Fool sparse by faking we release the lock - sparse will
- * track nic_access anyway.
+ * Deliberately return with reg_lock held; the caller must drop it via
+ * iwl_trans_pcie_release_nic_access(), or explicitly if it wants to
+ * keep the NIC awake past the critical section (cmd_hold_nic_awake).
*/
- __release(&trans_pcie->reg_lock);
return true;
}
@@ -2427,24 +2427,19 @@ void iwl_trans_pcie_resched_with_nic_access(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ lockdep_assert_held(&trans_pcie->reg_lock);
+
spin_unlock_bh(&trans_pcie->reg_lock);
cond_resched();
spin_lock_bh(&trans_pcie->reg_lock);
}
-void __releases(nic_access_nobh)
-iwl_trans_pcie_release_nic_access(struct iwl_trans *trans)
+void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
lockdep_assert_held(&trans_pcie->reg_lock);
- /*
- * Fool sparse by faking we acquiring the lock - sparse will
- * track nic_access anyway.
- */
- __acquire(&trans_pcie->reg_lock);
-
if (trans_pcie->cmd_hold_nic_awake)
goto out;
if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
@@ -2460,7 +2455,6 @@ iwl_trans_pcie_release_nic_access(struct iwl_trans *trans)
* scheduled on different CPUs (after we drop reg_lock).
*/
out:
- __release(nic_access_nobh);
spin_unlock_bh(&trans_pcie->reg_lock);
}
@@ -3016,24 +3010,6 @@ static ssize_t iwl_dbgfs_csr_write(struct file *file,
return count;
}
-static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_trans *trans = file->private_data;
- char *buf = NULL;
- ssize_t ret;
-
- ret = iwl_dump_fh(trans, &buf);
- if (ret < 0)
- return ret;
- if (!buf)
- return -EINVAL;
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
- kfree(buf);
- return ret;
-}
-
static ssize_t iwl_dbgfs_rfkill_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
@@ -3133,7 +3109,6 @@ static ssize_t iwl_dbgfs_reset_write(struct file *file,
}
DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
-DEBUGFS_READ_FILE_OPS(fh_reg);
DEBUGFS_READ_FILE_OPS(rx_queue);
DEBUGFS_WRITE_FILE_OPS(csr);
DEBUGFS_READ_WRITE_FILE_OPS(rfkill);
@@ -3157,7 +3132,6 @@ void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans)
DEBUGFS_ADD_FILE(tx_queue, dir, 0400);
DEBUGFS_ADD_FILE(interrupt, dir, 0600);
DEBUGFS_ADD_FILE(csr, dir, 0200);
- DEBUGFS_ADD_FILE(fh_reg, dir, 0400);
DEBUGFS_ADD_FILE(rfkill, dir, 0600);
DEBUGFS_ADD_FILE(rf, dir, 0400);
DEBUGFS_ADD_FILE(reset, dir, 0200);
@@ -3594,8 +3568,10 @@ void iwl_trans_pci_interrupts(struct iwl_trans *trans, bool enable)
void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans)
{
- u32 inta_addr, sw_err_bit;
+ bool interrupts_enabled = test_bit(STATUS_INT_ENABLED, &trans->status);
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ unsigned long timeout = jiffies + IWL_TRANS_NMI_TIMEOUT;
+ u32 inta_addr, sw_err_bit;
if (trans_pcie->msix_enabled) {
inta_addr = CSR_MSIX_HW_INT_CAUSES_AD;
@@ -3608,7 +3584,34 @@ void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans)
sw_err_bit = CSR_INT_BIT_SW_ERR;
}
- iwl_trans_sync_nmi_with_addr(trans, inta_addr, sw_err_bit);
+ /* if the interrupts were already disabled, there is no point in
+ * calling iwl_disable_interrupts
+ */
+ if (interrupts_enabled)
+ iwl_trans_pci_interrupts(trans, false);
+
+ iwl_trans_force_nmi(trans);
+ while (time_after(timeout, jiffies)) {
+ u32 inta_hw = iwl_read32(trans, inta_addr);
+
+ /* Error detected by uCode */
+ if (inta_hw & sw_err_bit) {
+ /* Clear causes register */
+ iwl_write32(trans, inta_addr, inta_hw & sw_err_bit);
+ break;
+ }
+
+ mdelay(1);
+ }
+
+ /* enable interrupts only if there were already enabled before this
+ * function to avoid a case were the driver enable interrupts before
+ * proper configurations were made
+ */
+ if (interrupts_enabled)
+ iwl_trans_pci_interrupts(trans, true);
+
+ iwl_trans_fw_error(trans, IWL_ERR_TYPE_NMI_FORCED);
}
static int iwl_trans_pcie_alloc_txcmd_pool(struct iwl_trans *trans)
@@ -4076,10 +4079,9 @@ static void iwl_pcie_check_me_status(struct iwl_trans *trans)
schedule_delayed_work(&trans_pcie->me_recheck_wk, HZ);
}
-int iwl_pci_gen1_2_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent,
- const struct iwl_mac_cfg *mac_cfg,
- u8 __iomem *hw_base, u32 hw_rev)
+int _iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent,
+ const struct iwl_mac_cfg *mac_cfg,
+ u8 __iomem *hw_base, u32 hw_rev)
{
const struct iwl_dev_info *dev_info;
struct iwl_trans_info info = {
@@ -4229,18 +4231,7 @@ int iwl_pci_gen1_2_probe(struct pci_dev *pdev,
return ret;
}
-void iwl_pcie_gen1_2_remove(struct iwl_trans *trans)
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
- cancel_delayed_work_sync(&trans_pcie->me_recheck_wk);
-
- iwl_drv_stop(trans->drv);
-
- iwl_trans_pcie_free(trans);
-}
-
-int iwl_pcie_gen1_2_activate_nic(struct iwl_trans *trans)
+int iwl_pcie_activate_nic(struct iwl_trans *trans)
{
const struct iwl_mac_cfg *mac_cfg = trans->mac_cfg;
u32 poll_ready;
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
similarity index 100%
rename from drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx-gen2.c
rename to drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
similarity index 99%
rename from drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c
rename to drivers/net/wireless/intel/iwlwifi/pcie/tx.c
index 26d1530cfa373..496435ea93ee8 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
@@ -715,7 +715,7 @@ static void iwl_txq_stuck_timer(struct timer_list *t)
iwl_txq_log_scd_error(trans, txq);
- iwl_force_nmi(trans);
+ iwl_trans_force_nmi(trans);
}
int iwl_pcie_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq,
@@ -1105,7 +1105,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
if (nfreed++ > 0) {
IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n",
idx, txq->write_ptr, r);
- iwl_force_nmi(trans);
+ iwl_trans_force_nmi(trans);
}
}
|
| 3/2 | 2026/09/26 16:31 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 27968 output: 37 thoughts: 1140 Thoughts: **Analyzing the iwlwifi Patch: Worth Fuzzing?** Okay, let's break down this patch for the `iwlwifi` driver. My initial assessment is focused on determining if it's "worth fuzzing," and that means figuring out if the changes are accessible within a standard QEMU/syzkaller environment. Let's see what we've got. It appears the patch has changes across various files in the `drivers/net/wireless/intel/iwlwifi` directory. I see: 1. **`Makefile`:** Path renaming, that's straightforward. 2. **`fw/api/*`:** Modifications to data structures (`struct iwl_rx_baid_cfg_cmd_modify`, `struct iwl_dev_tx_power_cmd_v12`, etc.) and the like. This suggests some API or firmware interaction changes. 3. **`fw/*`:** Changes in firmware-related code: `fw/dbg.c` (NMI handling), `fw/regulatory.c` (regulatory tables, SAR), `fw/uefi.c` (UEFI power control), and header changes. Firmware is usually a target for fuzzing, but accessibility is the key. 4. **`iwl-io.c`, `iwl-io.h`:** Removal of some NMI-related functions. Interesting, but let's see why. 5. **`iwl-nvm-parse.c`:** A flag has been removed. 6. **`iwl-trans.c`, `iwl-trans.h`:** Function moves and renames related to the transport layer. This could be significant if it involves changes to how the driver interacts with the hardware. 7. **`mld/*`:** Changes in MLD (Multi-Link Device) code: BAID updates, debugfs entries, power setting, regulatory configuration. MLD is another potentially interesting area. 8. **`mvm/*`:** Changes within the MVM (Mesh Virtual Machine) subtree, touching debugfs, firmware, mac80211 integration, and scanning. This is potentially interesting. 9. **`pcie/*`:** A significant chunk, including files moved from `pcie/gen1_2/` to `pcie/`, function renames, DMA read memory barrier addition and lockdep assertions, and sparse annotations removed. This screams "low-level hardware interaction". This is definitely a red flag for standard QEMU. Now, I recall the "NEGATIVE CRITERIA" for deeming a patch unworthy of fuzzing. *Structurally unreachable hardware* is the one I need to focus on. Specifically, anything that requires physical hardware not emulated in standard QEMU. Wait, is iwlwifi reachable in standard QEMU/syzkaller without actual Intel WiFi hardware? That's the million-dollar question. Let me recall. It's an Intel Wireless WiFi driver for Intel *PCIe* cards... Okay, so it's a PCIe wireless driver. That means it interacts directly with PCIe hardware. And QEMU doesn't emulate the `iwlwifi` driver itself, it only emulates other network interfaces such as e1000, rtl8139, and virtio-net. It's definitely not the target of any mac80211 based software simulation. Okay, let's verify. I see `iwl_pci_probe` in `drivers/net/wireless/intel/iwlwifi/pcie/drv.c`. That confirms it, it's a PCI driver and requires physical hardware or a highly specific emulation. So, this patch probably isn't "WorthFuzzing=true" in a standard QEMU/syzkaller setup. The changes are largely focused on low-level interaction, firmware, and PCIe, which is exactly the kind of thing QEMU doesn't emulate for this driver. I'd need a specific emulation setup to make any progress here. |
| 4/2 | 2026/09/26 16:31 | tool | grepper |
0mArgs:{
"Expression": "pci_register_driver",
"PathPrefix": "drivers/net/wireless/intel/iwlwifi"
}Results: {
"Output": "drivers/net/wireless/intel/iwlwifi/iwl-drv.c=2114=static int __init iwl_drv_init(void)\n--\ndrivers/net/wireless/intel/iwlwifi/iwl-drv.c-2125-\ndrivers/net/wireless/intel/iwlwifi/iwl-drv.c:2126:\terr = iwl_pci_register_driver();\ndrivers/net/wireless/intel/iwlwifi/iwl-drv.c-2127-\tif (err)\n--\ndrivers/net/wireless/intel/iwlwifi/iwl-trans.h=1133=static inline void iwl_trans_notify_fw_error(struct iwl_trans *trans)\n--\ndrivers/net/wireless/intel/iwlwifi/iwl-trans.h-1140- *****************************************************/\ndrivers/net/wireless/intel/iwlwifi/iwl-trans.h:1141:int __must_check iwl_pci_register_driver(void);\ndrivers/net/wireless/intel/iwlwifi/iwl-trans.h-1142-void iwl_pci_unregister_driver(void);\n--\ndrivers/net/wireless/intel/iwlwifi/pcie/drv.c=1345=static struct pci_driver iwl_pci_driver = {\n--\ndrivers/net/wireless/intel/iwlwifi/pcie/drv.c-1353-\ndrivers/net/wireless/intel/iwlwifi/pcie/drv.c:1354:int __must_check iwl_pci_register_driver(void)\ndrivers/net/wireless/intel/iwlwifi/pcie/drv.c-1355-{\ndrivers/net/wireless/intel/iwlwifi/pcie/drv.c-1356-\tint ret;\ndrivers/net/wireless/intel/iwlwifi/pcie/drv.c:1357:\tret = pci_register_driver(\u0026iwl_pci_driver);\ndrivers/net/wireless/intel/iwlwifi/pcie/drv.c-1358-\tif (ret)\n"
} |
| 5/2 | 2026/09/26 16:31 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 30577 output: 34 thoughts: 24 Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience and presented in the first person: **Investigating Alternative Bus and Register Mechanisms in iwlwifi** Alright, let's dive in. I need to make sure I haven't missed anything with `iwlwifi`. My initial focus is on the standard PCI bus, and that's been my starting point, but experience has taught me to be thorough. I need to take a step back and methodically consider if there are *any* other potential hardware access methods in play here. Is it solely PCI, or are there hidden dependencies or alternate access methods at play that I haven't accounted for? I'm thinking about platform buses, that should include ACPI tables if they apply to the platform. Are there any other device drivers that might be involved? Is there anything that could be happening in a System Integrated Module(SIM) that I need to be aware of? I need to methodically check for any indication of those, or any other, potential alternate bus or register mechanisms. The goal is a complete picture of the potential hardware access pathways. Let's see what we can find. |
| 6/2 | 2026/09/26 16:31 | tool | grepper |
0mArgs:{
"Expression": "module_init",
"PathPrefix": "drivers/net/wireless/intel/iwlwifi"
}Results: {
"Output": "drivers/net/wireless/intel/iwlwifi/dvm/main.c=2157=static int __init iwl_init(void)\n--\ndrivers/net/wireless/intel/iwlwifi/dvm/main.c-2175-}\ndrivers/net/wireless/intel/iwlwifi/dvm/main.c:2176:module_init(iwl_init);\ndrivers/net/wireless/intel/iwlwifi/dvm/main.c-2177-\n--\ndrivers/net/wireless/intel/iwlwifi/iwl-drv.c=2114=static int __init iwl_drv_init(void)\n--\ndrivers/net/wireless/intel/iwlwifi/iwl-drv.c-2137-}\ndrivers/net/wireless/intel/iwlwifi/iwl-drv.c:2138:module_init(iwl_drv_init);\ndrivers/net/wireless/intel/iwlwifi/iwl-drv.c-2139-\n--\ndrivers/net/wireless/intel/iwlwifi/iwl-drv.h-42- * The init flow wrt to the drv component looks like this:\ndrivers/net/wireless/intel/iwlwifi/iwl-drv.h:43: * 1) The bus specific component is called from module_init\ndrivers/net/wireless/intel/iwlwifi/iwl-drv.h-44- * 2) The bus specific component registers the bus driver\n--\ndrivers/net/wireless/intel/iwlwifi/mld/mld.c=38=static int __init iwl_mld_init(void)\n--\ndrivers/net/wireless/intel/iwlwifi/mld/mld.c-46-}\ndrivers/net/wireless/intel/iwlwifi/mld/mld.c:47:module_init(iwl_mld_init);\ndrivers/net/wireless/intel/iwlwifi/mld/mld.c-48-\n--\ndrivers/net/wireless/intel/iwlwifi/mvm/ops.c=53=static int __init iwl_mvm_init(void)\n--\ndrivers/net/wireless/intel/iwlwifi/mvm/ops.c-70-}\ndrivers/net/wireless/intel/iwlwifi/mvm/ops.c:71:module_init(iwl_mvm_init);\ndrivers/net/wireless/intel/iwlwifi/mvm/ops.c-72-\n"
} |
| 7/2 | 2026/09/26 16:31 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 31500 output: 47 thoughts: 12 Thoughts: Okay, let's dive into this. Here's how I'd approach summarizing the "Thoughts" based on my expertise: **Checking `iwl_drv_init`** Alright, let's take a look at `iwl_drv_init`. I immediately know this is the initialization function for the Intel Wireless driver – the core of the thing. I'm going to want to understand its role within the larger driver framework, and how it sets things up for the hardware interaction. I'll need to remember the architectural layers: the HAL (Hardware Abstraction Layer), the core driver functionality, and any associated firmware loading. This function *has* to be responsible for registering the driver with the kernel, probing for compatible hardware, allocating necessary data structures, and probably initiating the firmware loading process. I'll be particularly interested in how it handles initialization failures and what error reporting mechanisms are in place. Does it gracefully handle the absence of Intel hardware? What about situations where firmware loading fails? I'll also be expecting to see some initializations of locks or mutexes to ensure thread safety. Let's see if those assumptions are correct. |
| 8/2 | 2026/09/26 16:31 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/intel/iwlwifi/iwl-drv.c",
"FirstLine": 2110,
"LineCount": 35
}Results: {
"Contents": "2110:\t\tmutex_unlock(\u0026iwlwifi_opmode_table_mtx);\n2111:\t}\n2112:\tIWL_EXPORT_SYMBOL(iwl_opmode_deregister);\n2113:\t\n2114:\tstatic int __init iwl_drv_init(void)\n2115:\t{\n2116:\t\tint i, err;\n2117:\t\n2118:\t\tfor (i = 0; i \u003c ARRAY_SIZE(iwlwifi_opmode_table); i++)\n2119:\t\t\tINIT_LIST_HEAD(\u0026iwlwifi_opmode_table[i].drv);\n2120:\t\n2121:\t#ifdef CONFIG_IWLWIFI_DEBUGFS\n2122:\t\t/* Create the root of iwlwifi debugfs subsystem. */\n2123:\t\tiwl_dbgfs_root = debugfs_create_dir(DRV_NAME, NULL);\n2124:\t#endif\n2125:\t\n2126:\t\terr = iwl_pci_register_driver();\n2127:\t\tif (err)\n2128:\t\t\tgoto cleanup_debugfs;\n2129:\t\n2130:\t\treturn 0;\n2131:\t\n2132:\tcleanup_debugfs:\n2133:\t#ifdef CONFIG_IWLWIFI_DEBUGFS\n2134:\t\tdebugfs_remove_recursive(iwl_dbgfs_root);\n2135:\t#endif\n2136:\t\treturn err;\n2137:\t}\n2138:\tmodule_init(iwl_drv_init);\n2139:\t\n2140:\tstatic void __exit iwl_drv_exit(void)\n2141:\t{\n2142:\t\tiwl_pci_unregister_driver();\n2143:\t\tiwl_trans_free_restart_list();\n2144:\t\n"
} |
| 9/2 | 2026/09/26 16:31 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 32305 output: 45 thoughts: 47 Thoughts: Okay, here's my take on those snippets, as if I were processing them myself: **Initial Assessment: Driver Initialization** Right, `iwl_drv_init()`. Okay, this one's straightforward, it seems. All it does is set up that debugfs directory, and then it calls `iwl_pci_register_driver()`. Nothing too fancy there. Standard driver setup, at least at this initial level. It's laying the groundwork. Now, `iwl_mvm_init()`... hmm, that's where the real meat of the multi-VIF (Virtual Interface Function) magic begins, I suspect. Let's dig into that one. I want to see how it's expanding upon what was just established by `iwl_drv_init()`. What are the core components it's initializing, how does it handle the multiple virtual interfaces, and what are the key data structures involved. I need to get a better handle on how the MVM structure integrates into the base driver. |
| 10/2 | 2026/09/26 16:31 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/intel/iwlwifi/mvm/ops.c",
"FirstLine": 50,
"LineCount": 25
}Results: {
"Contents": " 50:\t/*\n 51:\t * module init and exit functions\n 52:\t */\n 53:\tstatic int __init iwl_mvm_init(void)\n 54:\t{\n 55:\t\tint ret;\n 56:\t\n 57:\t\tret = iwl_mvm_rate_control_register();\n 58:\t\tif (ret) {\n 59:\t\t\tpr_err(\"Unable to register rate control algorithm: %d\\n\", ret);\n 60:\t\t\treturn ret;\n 61:\t\t}\n 62:\t\n 63:\t\tret = iwl_opmode_register(\"iwlmvm\", \u0026iwl_mvm_ops);\n 64:\t\tif (ret) {\n 65:\t\t\tpr_err(\"Unable to register MVM op_mode: %d\\n\", ret);\n 66:\t\t\tiwl_mvm_rate_control_unregister();\n 67:\t\t}\n 68:\t\n 69:\t\treturn ret;\n 70:\t}\n 71:\tmodule_init(iwl_mvm_init);\n 72:\t\n 73:\tstatic void __exit iwl_mvm_exit(void)\n 74:\t{\n"
} |
| 11/2 | 2026/09/26 16:31 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 32938 output: 46 thoughts: 14 Thoughts: Okay, here's my understanding, assuming I'm an expert in this field, based on your prompt: **Decoding `iwl_mld_init`** Alright, so I'm thinking about `iwl_mld_init` right now. It's that critical initialization function related to the Intel Wireless LAN driver's Multicast Listener Discovery (MLD) functionality, isn't it? My mind automatically jumps to the nuances of multicast group management and how the driver interfaces with the network stack for IPv6 multicast. I'm wondering if it's responsible for setting up the necessary MLD sockets and binding them, maybe configuring the kernel's IGMPv3/MLDv2 membership reports. Does it handle any specific hardware-level configuration related to multicast filtering on the NIC? I need to think through if it sets up any specific multicast related parameters for the firmware to handle. I'm imagining it deals with the driver registering with the kernel's network stack to receive MLD reports, and possibly setting up the timer that keeps the groups up to date. I am also considering how any of this impacts the performance, perhaps it has some optimization to avoid flooding the link with unnecessary packets. Gotta keep all the potential race conditions in mind too. I will check. |
| 12/2 | 2026/09/26 16:31 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/intel/iwlwifi/mld/mld.c",
"FirstLine": 35,
"LineCount": 20
}Results: {
"Contents": " 35:\t\n 36:\tstatic const struct iwl_op_mode_ops iwl_mld_ops;\n 37:\t\n 38:\tstatic int __init iwl_mld_init(void)\n 39:\t{\n 40:\t\tint ret = iwl_opmode_register(\"iwlmld\", \u0026iwl_mld_ops);\n 41:\t\n 42:\t\tif (ret)\n 43:\t\t\tpr_err(\"Unable to register MLD op_mode: %d\\n\", ret);\n 44:\t\n 45:\t\treturn ret;\n 46:\t}\n 47:\tmodule_init(iwl_mld_init);\n 48:\t\n 49:\tstatic void __exit iwl_mld_exit(void)\n 50:\t{\n 51:\t\tiwl_opmode_deregister(\"iwlmld\");\n 52:\t}\n 53:\tmodule_exit(iwl_mld_exit);\n 54:\t\n"
} |
| 13/2 | 2026/09/26 16:31 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 33537 output: 114 thoughts: 1222 Thoughts: **Fuzzing Verdict: WorthFuzzing=false for Intel iwlwifi Driver** Okay, let's break this down. My initial observation is that `iwl_opmode_register` is the key. It's registering an op_mode within `iwlwifi_opmode_table`, but the crucial point is that this whole op_mode business *only* kicks off during PCI device probe. That's the entry point, via `_iwl_pci_probe`, which eventually leads to `iwl_drv_start` and then the op_mode initialization. So, the question is, can we trigger that probe in a standard fuzzing environment? First, I looked at the modified files: it's a deep dive into the iwlwifi codebase. Every single change is within the `drivers/net/wireless/intel/iwlwifi/` directory. That's a pretty strong indicator. It touches on firmware APIs, power management, regulatory features, various I/O and transport mechanisms, and also the MLD and MVM op_mode implementations. Now, let's apply the *negative* criteria from the instructions. It explicitly states to return `WorthFuzzing=false` if the changes fall into certain categories of unreachable code. One of these categories is "Structurally unreachable hardware: * Vendor-specific PCIe switches, SmartNICs, or GPU drivers... requiring physical ASIC/PCIe cards not emulated in standard QEMU". That's exactly where I think we are. I immediately considered: can syzkaller or QEMU help here? Syzkaller often handles mac80211 through mac80211_hwsim, or it can fuzz USB Wi-Fi drivers like the rtl8xxxu or ath9k_htc. But `iwlwifi`? This is a *PCIe* device driver for Intel WiFi NICs. QEMU does *not* emulate Intel WiFi PCIe devices in a way that would trigger a probe. There's no virtual iwlwifi device in standard environments like GCE or QEMU. Therefore, without that physical Intel WiFi PCIe hardware, the probe is never called. The driver doesn't attach to anything, no netdev or mac80211 wiphy is created, and *none* of this code gets executed. It's unreachable. So, it all points to `drivers/net/wireless/intel/iwlwifi`, a vendor-specific PCIe wireless driver that depends on physical Intel wireless hardware that is *not* emulated in standard virtualized environments. That firmly puts us in the "structurally unreachable hardware" category. Therefore, `WorthFuzzing=false`. I am very confident of this. Now, let's verify all the parameters for `set-results`. - WorthFuzzing: `false` - EnableConfigs: `[]` (empty list) - FocusSymbols: `[]` (empty list) And finally, my *Reasoning*: "The patch exclusively modifies the Intel wireless driver (`drivers/net/wireless/intel/iwlwifi/`), including PCIe transport, firmware interaction, power/regulatory management, and op_mode implementations (MLD/MVM). This driver requires specific Intel PCIe Wi-Fi hardware that is not emulated in standard virtualized environments (QEMU/GCE), making the modified code structurally unreachable for fuzzing." Now I'll call `set-results`. |
| 14/2 | 2026/09/26 16:31 | tool | set-results |
0mArgs:{
"EnableConfigs": [],
"FocusSymbols": [],
"Reasoning": "The patch series exclusively modifies the Intel Wi-Fi driver (`drivers/net/wireless/intel/iwlwifi`), including PCIe transport handling, firmware interaction, power/SAR regulatory management, and MVM/MLD operations. This driver requires physical Intel PCIe Wi-Fi hardware that is not emulated in standard virtualized fuzzing environments (QEMU/GCE), making the modified code structurally unreachable.",
"WorthFuzzing": false
}Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch series exclusively modifies the Intel Wi-Fi driver (`drivers/net/wireless/intel/iwlwifi`), including PCIe transport handling, firmware interaction, power/SAR regulatory management, and MVM/MLD operations. This driver requires physical Intel PCIe Wi-Fi hardware that is not emulated in standard virtualized fuzzing environments (QEMU/GCE), making the modified code structurally unreachable.",
"WorthFuzzing": false
} |
| 15/1 | 2026/09/26 16:31 | action | If |
0mArgs:{
"WorthFuzzing": false
}Results: null |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|