Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'iwlwifi-next-for-kalle-2018-11-23' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next

second batch of iwlwifi patches intended for v4.21

* New FW debugging infrastructure;
* Some more work on 802.11ax;
* Improve support for multiple RF modules with 22000 devices;
* Remove an unused FW parameter;
* Other debugging improvements;

+1374 -77
+1
drivers/net/wireless/intel/iwlwifi/Makefile
··· 11 11 iwlwifi-objs += pcie/trans-gen2.o pcie/tx-gen2.o 12 12 iwlwifi-$(CONFIG_IWLDVM) += cfg/1000.o cfg/2000.o cfg/5000.o cfg/6000.o 13 13 iwlwifi-$(CONFIG_IWLMVM) += cfg/7000.o cfg/8000.o cfg/9000.o cfg/22000.o 14 + iwlwifi-objs += iwl-dbg-tlv.o 14 15 iwlwifi-objs += iwl-trans.o 15 16 iwlwifi-objs += fw/notif-wait.o 16 17 iwlwifi-$(CONFIG_IWLMVM) += fw/paging.o fw/smem.o fw/init.o fw/dbg.o
-1
drivers/net/wireless/intel/iwlwifi/cfg/22000.c
··· 323 323 MODULE_FIRMWARE(IWL_22000_JF_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); 324 324 MODULE_FIRMWARE(IWL_22000_HR_A_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); 325 325 MODULE_FIRMWARE(IWL_22000_HR_B_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); 326 - MODULE_FIRMWARE(IWL_22000_QU_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); 327 326 MODULE_FIRMWARE(IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); 328 327 MODULE_FIRMWARE(IWL_22000_JF_B0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); 329 328 MODULE_FIRMWARE(IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
+401
drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h
··· 1 + /****************************************************************************** 2 + * 3 + * This file is provided under a dual BSD/GPLv2 license. When using or 4 + * redistributing this file, you may do so under either license. 5 + * 6 + * GPL LICENSE SUMMARY 7 + * 8 + * Copyright (C) 2018 Intel Corporation 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of version 2 of the GNU General Public License as 12 + * published by the Free Software Foundation. 13 + * 14 + * This program is distributed in the hope that it will be useful, but 15 + * WITHOUT ANY WARRANTY; without even the implied warranty of 16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 + * General Public License for more details. 18 + * 19 + * The full GNU General Public License is included in this distribution 20 + * in the file called COPYING. 21 + * 22 + * Contact Information: 23 + * Intel Linux Wireless <linuxwifi@intel.com> 24 + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 25 + * 26 + * BSD LICENSE 27 + * 28 + * Copyright (C) 2018 Intel Corporation 29 + * All rights reserved. 30 + * 31 + * Redistribution and use in source and binary forms, with or without 32 + * modification, are permitted provided that the following conditions 33 + * are met: 34 + * 35 + * * Redistributions of source code must retain the above copyright 36 + * notice, this list of conditions and the following disclaimer. 37 + * * Redistributions in binary form must reproduce the above copyright 38 + * notice, this list of conditions and the following disclaimer in 39 + * the documentation and/or other materials provided with the 40 + * distribution. 41 + * * Neither the name Intel Corporation nor the names of its 42 + * contributors may be used to endorse or promote products derived 43 + * from this software without specific prior written permission. 44 + * 45 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 46 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 47 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 48 + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 49 + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 50 + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 51 + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 52 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 53 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 54 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 55 + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 + * 57 + *****************************************************************************/ 58 + #ifndef __iwl_fw_dbg_tlv_h__ 59 + #define __iwl_fw_dbg_tlv_h__ 60 + 61 + #include <linux/bitops.h> 62 + 63 + /* 64 + * struct iwl_fw_ini_header: Common Header for all debug group TLV's structures 65 + * @tlv_version: version info 66 + * @apply_point: &enum iwl_fw_ini_apply_point 67 + * @data: TLV data followed 68 + **/ 69 + struct iwl_fw_ini_header { 70 + __le32 tlv_version; 71 + __le32 apply_point; 72 + u8 data[]; 73 + } __packed; /* FW_INI_HEADER_TLV_S */ 74 + 75 + /** 76 + * struct iwl_fw_ini_allocation_tlv - (IWL_FW_INI_TLV_TYPE_BUFFER_ALLOCATION) 77 + * buffer allocation TLV - for debug 78 + * 79 + * @iwl_fw_ini_header: header 80 + * @allocation_id: &enum iwl_fw_ini_allocation_id - to bind allocation and hcmd 81 + * if needed (DBGC1/DBGC2/SDFX/...) 82 + * @buffer_location: type of iwl_fw_ini_buffer_location 83 + * @size: size in bytes 84 + * @max_fragments: the maximum allowed fragmentation in the desired memory 85 + * allocation above 86 + * @min_frag_size: the minimum allowed fragmentation size in bytes 87 + */ 88 + struct iwl_fw_ini_allocation_tlv { 89 + struct iwl_fw_ini_header header; 90 + __le32 allocation_id; 91 + __le32 buffer_location; 92 + __le32 size; 93 + __le32 max_fragments; 94 + __le32 min_frag_size; 95 + } __packed; /* FW_INI_BUFFER_ALLOCATION_TLV_S_VER_1 */ 96 + 97 + /** 98 + * struct iwl_fw_ini_hcmd (IWL_FW_INI_TLV_TYPE_HCMD) 99 + * Generic Host command pass through TLV 100 + * 101 + * @id: the debug configuration command type for instance: 0xf6 / 0xf5 / DHC 102 + * @group: the desired cmd group 103 + * @padding: all zeros for dword alignment 104 + * @data: all of the relevant command (0xf6/0xf5) to be sent 105 + */ 106 + struct iwl_fw_ini_hcmd { 107 + u8 id; 108 + u8 group; 109 + __le16 padding; 110 + u8 data[0]; 111 + } __packed; /* FW_INI_HCMD_S */ 112 + 113 + /** 114 + * struct iwl_fw_ini_hcmd_tlv 115 + * @header: header 116 + * @hcmd: a variable length host-command to be sent to apply the configuration. 117 + */ 118 + struct iwl_fw_ini_hcmd_tlv { 119 + struct iwl_fw_ini_header header; 120 + struct iwl_fw_ini_hcmd hcmd; 121 + } __packed; /* FW_INI_HCMD_TLV_S_VER_1 */ 122 + 123 + /* 124 + * struct iwl_fw_ini_debug_flow_tlv (IWL_FW_INI_TLV_TYPE_DEBUG_FLOW) 125 + * 126 + * @header: header 127 + * @debug_flow_cfg: &enum iwl_fw_ini_debug_flow 128 + */ 129 + struct iwl_fw_ini_debug_flow_tlv { 130 + struct iwl_fw_ini_header header; 131 + __le32 debug_flow_cfg; 132 + } __packed; /* FW_INI_DEBUG_FLOW_TLV_S_VER_1 */ 133 + 134 + #define IWL_FW_INI_MAX_REGION_ID 20 135 + #define IWL_FW_INI_MAX_NAME 32 136 + /** 137 + * struct iwl_fw_ini_region_cfg 138 + * @region_id: ID of this dump configuration 139 + * @region_type: &enum iwl_fw_ini_region_type 140 + * @num_regions: amount of regions in the address array. 141 + * @allocation_id: For DRAM type field substitutes for allocation_id. 142 + * @name_len: name length 143 + * @name: file name to use for this region 144 + * @size: size of the data, in bytes.(unused for IWL_FW_INI_REGION_DRAM_BUFFER) 145 + * @start_addr: array of addresses. (unused for IWL_FW_INI_REGION_DRAM_BUFFER) 146 + */ 147 + struct iwl_fw_ini_region_cfg { 148 + __le32 region_id; 149 + __le32 region_type; 150 + __le32 name_len; 151 + u8 name[IWL_FW_INI_MAX_NAME]; 152 + union { 153 + __le32 num_regions; 154 + __le32 allocation_id; 155 + }; 156 + __le32 size; 157 + __le32 start_addr[]; 158 + } __packed; /* FW_INI_REGION_CONFIG_S */ 159 + 160 + /** 161 + * struct iwl_fw_ini_region_tlv - (IWL_FW_INI_TLV_TYPE_REGION_CFG) 162 + * DUMP sections define IDs and triggers that use those IDs TLV 163 + * @header: header 164 + * @num_regions: how many different region section and IDs are coming next 165 + * @iwl_fw_ini_dump dump_config: list of dump configurations 166 + */ 167 + struct iwl_fw_ini_region_tlv { 168 + struct iwl_fw_ini_header header; 169 + __le32 num_regions; 170 + struct iwl_fw_ini_region_cfg region_config[]; 171 + } __packed; /* FW_INI_REGION_CFG_S */ 172 + 173 + /** 174 + * struct iwl_fw_ini_trigger - (IWL_FW_INI_TLV_TYPE_DUMP_CFG) 175 + * Region sections define IDs and triggers that use those IDs TLV 176 + * 177 + * @trigger_id: enum &iwl_fw_ini_tigger_id 178 + * @ignore_default: override FW TLV with binary TLV 179 + * @dump_delay: delay from trigger fire to dump, in usec 180 + * @occurrences: max amount of times to be fired 181 + * @ignore_consec: ignore consecutive triggers, in usec 182 + * @force_restart: force FW restart 183 + * @multi_dut: initiate debug dump data on several DUTs 184 + * @trigger_data: generic data to be utilized per trigger 185 + * @num_regions: number of dump regions defined for this trigger 186 + * @data: region IDs 187 + */ 188 + struct iwl_fw_ini_trigger { 189 + __le32 trigger_id; 190 + __le32 ignore_default; 191 + __le32 dump_delay; 192 + __le32 occurrences; 193 + __le32 ignore_consec; 194 + __le32 force_restart; 195 + __le32 multi_dut; 196 + __le32 trigger_data; 197 + __le32 num_regions; 198 + __le32 data[]; 199 + } __packed; /* FW_INI_TRIGGER_CONFIG_S */ 200 + 201 + /** 202 + * struct iwl_fw_ini_trigger_tlv - (IWL_FW_INI_TLV_TYPE_TRIGGERS_CFG) 203 + * DUMP sections define IDs and triggers that use those IDs TLV 204 + * 205 + * @header: header 206 + * @num_triggers: how many different triggers section and IDs are coming next 207 + * @trigger_config: list of trigger configurations 208 + */ 209 + struct iwl_fw_ini_trigger_tlv { 210 + struct iwl_fw_ini_header header; 211 + __le32 num_triggers; 212 + struct iwl_fw_ini_trigger trigger_config[]; 213 + } __packed; /* FW_INI_TRIGGER_CFG_S */ 214 + 215 + /** 216 + * enum iwl_fw_ini_trigger_id 217 + * @IWL_FW_TRIGGER_ID_FW_ASSERT: FW assert 218 + * @IWL_FW_TRIGGER_ID_FW_TFD_Q_HANG: TFD queue hang 219 + * @IWL_FW_TRIGGER_ID_FW_HW_ERROR: HW assert 220 + * @IWL_FW_TRIGGER_ID_FW_TRIGGER_ERROR: FW error notification 221 + * @IWL_FW_TRIGGER_ID_FW_TRIGGER_WARNING: FW warning notification 222 + * @IWL_FW_TRIGGER_ID_FW_TRIGGER_INFO: FW info notification 223 + * @IWL_FW_TRIGGER_ID_FW_TRIGGER_DEBUG: FW debug notification 224 + * @IWL_FW_TRIGGER_ID_USER_TRIGGER: User trigger 225 + * @IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY: peer inactivity 226 + * @FW_DEBUG_TLV_TRIGGER_ID_HOST_DID_INITIATED_EVENT: undefined 227 + * @IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED: TX latency 228 + * threshold was crossed 229 + * @IWL_FW_TRIGGER_ID_HOST_TX_RESPONSE_STATUS_FAILED: TX failed 230 + * @IWL_FW_TRIGGER_ID_HOST_OS_REQ_DEAUTH_PEER: Deauth initiated by host 231 + * @IWL_FW_TRIGGER_ID_HOST_STOP_GO_REQUEST: stop GO request 232 + * @IWL_FW_TRIGGER_ID_HOST_START_GO_REQUEST: start GO request 233 + * @IWL_FW_TRIGGER_ID_HOST_JOIN_GROUP_REQUEST: join P2P group request 234 + * @IWL_FW_TRIGGER_ID_HOST_SCAN_START: scan started event 235 + * @IWL_FW_TRIGGER_ID_HOST_SCAN_SUBMITTED: undefined 236 + * @IWL_FW_TRIGGER_ID_HOST_SCAN_PARAMS: undefined 237 + * @IWL_FW_TRIGGER_ID_HOST_CHECK_FOR_HANG: undefined 238 + * @IWL_FW_TRIGGER_ID_HOST_BAR_RECEIVED: BAR frame was received 239 + * @IWL_FW_TRIGGER_ID_HOST_AGG_TX_RESPONSE_STATUS_FAILED: agg TX failed 240 + * @IWL_FW_TRIGGER_ID_HOST_EAPOL_TX_RESPONSE_FAILED: EAPOL TX failed 241 + * @IWL_FW_TRIGGER_ID_HOST_FAKE_TX_RESPONSE_SUSPECTED: suspicious TX response 242 + * @IWL_FW_TRIGGER_ID_HOST_AUTH_REQ_FROM_ASSOC_CLIENT: received suspicious auth 243 + * @IWL_FW_TRIGGER_ID_HOST_ROAM_COMPLETE: roaming was completed 244 + * @IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAST_FAILED: fast assoc failed 245 + * @IWL_FW_TRIGGER_ID_HOST_D3_START: D3 start 246 + * @IWL_FW_TRIGGER_ID_HOST_D3_END: D3 end 247 + * @IWL_FW_TRIGGER_ID_HOST_BSS_MISSED_BEACONS: missed beacon events 248 + * @IWL_FW_TRIGGER_ID_HOST_P2P_CLIENT_MISSED_BEACONS: P2P missed beacon events 249 + * @IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_TX_FAILURES: undefined 250 + * @IWL_FW_TRIGGER_ID_HOST_TX_WFD_ACTION_FRAME_FAILED: undefined 251 + * @IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAILED: authentication / association 252 + * failed 253 + * @IWL_FW_TRIGGER_ID_HOST_SCAN_COMPLETE: scan complete event 254 + * @IWL_FW_TRIGGER_ID_HOST_SCAN_ABORT: scan abort complete 255 + * @IWL_FW_TRIGGER_ID_HOST_NIC_ALIVE: nic alive message was received 256 + * @IWL_FW_TRIGGER_ID_HOST_CHANNEL_SWITCH_COMPLETE: CSA was completed 257 + * @IWL_FW_TRIGGER_ID_NUM: number of trigger IDs 258 + */ 259 + enum iwl_fw_ini_trigger_id { 260 + /* Errors triggers */ 261 + IWL_FW_TRIGGER_ID_FW_ASSERT = 1, 262 + IWL_FW_TRIGGER_ID_FW_TFD_Q_HANG = 2, 263 + IWL_FW_TRIGGER_ID_FW_HW_ERROR = 3, 264 + /* Generic triggers */ 265 + IWL_FW_TRIGGER_ID_FW_TRIGGER_ERROR = 4, 266 + IWL_FW_TRIGGER_ID_FW_TRIGGER_WARNING = 5, 267 + IWL_FW_TRIGGER_ID_FW_TRIGGER_INFO = 6, 268 + IWL_FW_TRIGGER_ID_FW_TRIGGER_DEBUG = 7, 269 + /* User Trigger */ 270 + IWL_FW_TRIGGER_ID_USER_TRIGGER = 8, 271 + /* Host triggers */ 272 + IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY = 9, 273 + IWL_FW_TRIGGER_ID_HOST_DID_INITIATED_EVENT = 10, 274 + IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED = 11, 275 + IWL_FW_TRIGGER_ID_HOST_TX_RESPONSE_STATUS_FAILED = 12, 276 + IWL_FW_TRIGGER_ID_HOST_OS_REQ_DEAUTH_PEER = 13, 277 + IWL_FW_TRIGGER_ID_HOST_STOP_GO_REQUEST = 14, 278 + IWL_FW_TRIGGER_ID_HOST_START_GO_REQUEST = 15, 279 + IWL_FW_TRIGGER_ID_HOST_JOIN_GROUP_REQUEST = 16, 280 + IWL_FW_TRIGGER_ID_HOST_SCAN_START = 17, 281 + IWL_FW_TRIGGER_ID_HOST_SCAN_SUBITTED = 18, 282 + IWL_FW_TRIGGER_ID_HOST_SCAN_PARAMS = 19, 283 + IWL_FW_TRIGGER_ID_HOST_CHECK_FOR_HANG = 20, 284 + IWL_FW_TRIGGER_ID_HOST_BAR_RECEIVED = 21, 285 + IWL_FW_TRIGGER_ID_HOST_AGG_TX_RESPONSE_STATUS_FAILED = 22, 286 + IWL_FW_TRIGGER_ID_HOST_EAPOL_TX_RESPONSE_FAILED = 23, 287 + IWL_FW_TRIGGER_ID_HOST_FAKE_TX_RESPONSE_SUSPECTED = 24, 288 + IWL_FW_TRIGGER_ID_HOST_AUTH_REQ_FROM_ASSOC_CLIENT = 25, 289 + IWL_FW_TRIGGER_ID_HOST_ROAM_COMPLETE = 26, 290 + IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAST_FAILED = 27, 291 + IWL_FW_TRIGGER_ID_HOST_D3_START = 28, 292 + IWL_FW_TRIGGER_ID_HOST_D3_END = 29, 293 + IWL_FW_TRIGGER_ID_HOST_BSS_MISSED_BEACONS = 30, 294 + IWL_FW_TRIGGER_ID_HOST_P2P_CLIENT_MISSED_BEACONS = 31, 295 + IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_TX_FAILURES = 32, 296 + IWL_FW_TRIGGER_ID_HOST_TX_WFD_ACTION_FRAME_FAILED = 33, 297 + IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAILED = 34, 298 + IWL_FW_TRIGGER_ID_HOST_SCAN_COMPLETE = 35, 299 + IWL_FW_TRIGGER_ID_HOST_SCAN_ABORT = 36, 300 + IWL_FW_TRIGGER_ID_HOST_NIC_ALIVE = 37, 301 + IWL_FW_TRIGGER_ID_HOST_CHANNEL_SWITCH_COMPLETE = 38, 302 + IWL_FW_TRIGGER_ID_NUM, 303 + }; /* FW_INI_TRIGGER_ID_E_VER_1 */ 304 + 305 + /** 306 + * enum iwl_fw_ini_apply_point 307 + * @IWL_FW_INI_APPLY_INVALID: invalid 308 + * @IWL_FW_INI_APPLY_EARLY: pre loading FW 309 + * @IWL_FW_INI_APPLY_AFTER_ALIVE: first cmd from host after alive 310 + * @IWL_FW_INI_APPLY_POST_INIT: last cmd in initialization sequence 311 + * @IWL_FW_INI_APPLY_MISSED_BEACONS: missed beacons notification 312 + * @IWL_FW_INI_APPLY_SCAN_COMPLETE: scan completed 313 + * @IWL_FW_INI_APPLY_NUM: number of apply points 314 + */ 315 + enum iwl_fw_ini_apply_point { 316 + IWL_FW_INI_APPLY_INVALID, 317 + IWL_FW_INI_APPLY_EARLY, 318 + IWL_FW_INI_APPLY_AFTER_ALIVE, 319 + IWL_FW_INI_APPLY_POST_INIT, 320 + IWL_FW_INI_APPLY_MISSED_BEACONS, 321 + IWL_FW_INI_APPLY_SCAN_COMPLETE, 322 + IWL_FW_INI_APPLY_NUM, 323 + }; /* FW_INI_APPLY_POINT_E_VER_1 */ 324 + 325 + /** 326 + * enum iwl_fw_ini_allocation_id 327 + * @IWL_FW_INI_ALLOCATION_INVALID: invalid 328 + * @IWL_FW_INI_ALLOCATION_ID_DBGC1: allocation meant for DBGC1 configuration 329 + * @IWL_FW_INI_ALLOCATION_ID_DBGC2: allocation meant for DBGC2 configuration 330 + * @IWL_FW_INI_ALLOCATION_ID_DBGC3: allocation meant for DBGC3 configuration 331 + * @IWL_FW_INI_ALLOCATION_ID_SDFX: for SDFX module 332 + * @IWL_FW_INI_ALLOCATION_ID_FW_DUMP: used for crash and runtime dumps 333 + * @IWL_FW_INI_ALLOCATION_ID_USER_DEFINED: for future user scenarios 334 + */ 335 + enum iwl_fw_ini_allocation_id { 336 + IWL_FW_INI_ALLOCATION_INVALID, 337 + IWL_FW_INI_ALLOCATION_ID_DBGC1, 338 + IWL_FW_INI_ALLOCATION_ID_DBGC2, 339 + IWL_FW_INI_ALLOCATION_ID_DBGC3, 340 + IWL_FW_INI_ALLOCATION_ID_SDFX, 341 + IWL_FW_INI_ALLOCATION_ID_FW_DUMP, 342 + IWL_FW_INI_ALLOCATION_ID_USER_DEFINED, 343 + }; /* FW_INI_ALLOCATION_ID_E_VER_1 */ 344 + 345 + /** 346 + * enum iwl_fw_ini_buffer_location 347 + * @IWL_FW_INI_LOCATION_INVALID: invalid 348 + * @IWL_FW_INI_LOCATION_SRAM_PATH: SRAM location 349 + * @IWL_FW_INI_LOCATION_DRAM_PATH: DRAM location 350 + */ 351 + enum iwl_fw_ini_buffer_location { 352 + IWL_FW_INI_LOCATION_SRAM_INVALID, 353 + IWL_FW_INI_LOCATION_SRAM_PATH, 354 + IWL_FW_INI_LOCATION_DRAM_PATH, 355 + }; /* FW_INI_BUFFER_LOCATION_E_VER_1 */ 356 + 357 + /** 358 + * enum iwl_fw_ini_debug_flow 359 + * @IWL_FW_INI_DEBUG_INVALID: invalid 360 + * @IWL_FW_INI_DEBUG_DBTR_FLOW: undefined 361 + * @IWL_FW_INI_DEBUG_TB2DTF_FLOW: undefined 362 + */ 363 + enum iwl_fw_ini_debug_flow { 364 + IWL_FW_INI_DEBUG_INVALID, 365 + IWL_FW_INI_DEBUG_DBTR_FLOW, 366 + IWL_FW_INI_DEBUG_TB2DTF_FLOW, 367 + }; /* FW_INI_DEBUG_FLOW_E_VER_1 */ 368 + 369 + /** 370 + * enum iwl_fw_ini_region_type 371 + * @IWL_FW_INI_REGION_INVALID: invalid 372 + * @IWL_FW_INI_REGION_DEVICE_MEMORY: device internal memory 373 + * @IWL_FW_INI_REGION_PERIPHERY_MAC: periphery registers of MAC 374 + * @IWL_FW_INI_REGION_PERIPHERY_PHY: periphery registers of PHY 375 + * @IWL_FW_INI_REGION_PERIPHERY_AUX: periphery registers of AUX 376 + * @IWL_FW_INI_REGION_DRAM_BUFFER: DRAM buffer 377 + * @IWL_FW_INI_REGION_DRAM_IMR: IMR memory 378 + * @IWL_FW_INI_REGION_INTERNAL_BUFFER: undefined 379 + * @IWL_FW_INI_REGION_TXF: TX fifos 380 + * @IWL_FW_INI_REGION_RXF: RX fifo 381 + * @IWL_FW_INI_REGION_PAGING: paging memory 382 + * @IWL_FW_INI_REGION_CSR: CSR registers 383 + * @IWL_FW_INI_REGION_NUM: number of region types 384 + */ 385 + enum iwl_fw_ini_region_type { 386 + IWL_FW_INI_REGION_INVALID, 387 + IWL_FW_INI_REGION_DEVICE_MEMORY, 388 + IWL_FW_INI_REGION_PERIPHERY_MAC, 389 + IWL_FW_INI_REGION_PERIPHERY_PHY, 390 + IWL_FW_INI_REGION_PERIPHERY_AUX, 391 + IWL_FW_INI_REGION_DRAM_BUFFER, 392 + IWL_FW_INI_REGION_DRAM_IMR, 393 + IWL_FW_INI_REGION_INTERNAL_BUFFER, 394 + IWL_FW_INI_REGION_TXF, 395 + IWL_FW_INI_REGION_RXF, 396 + IWL_FW_INI_REGION_PAGING, 397 + IWL_FW_INI_REGION_CSR, 398 + IWL_FW_INI_REGION_NUM 399 + }; /* FW_INI_REGION_TYPE_E_VER_1*/ 400 + 401 + #endif
+20 -19
drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
··· 151 151 * @beacon_time: beacon transmit time in system time 152 152 * @beacon_tsf: beacon transmit time in TSF 153 153 * @bi: beacon interval in TU 154 - * @bi_reciprocal: 2^32 / bi 154 + * @reserved1: reserved 155 155 * @dtim_interval: dtim transmit time in TU 156 - * @dtim_reciprocal: 2^32 / dtim_interval 156 + * @reserved2: reserved 157 157 * @mcast_qid: queue ID for multicast traffic. 158 158 * NOTE: obsolete from VER2 and on 159 159 * @beacon_template: beacon template ID ··· 162 162 __le32 beacon_time; 163 163 __le64 beacon_tsf; 164 164 __le32 bi; 165 - __le32 bi_reciprocal; 165 + __le32 reserved1; 166 166 __le32 dtim_interval; 167 - __le32 dtim_reciprocal; 167 + __le32 reserved2; 168 168 __le32 mcast_qid; 169 169 __le32 beacon_template; 170 170 } __packed; /* AP_MAC_DATA_API_S_VER_2 */ ··· 174 174 * @beacon_time: beacon transmit time in system time 175 175 * @beacon_tsf: beacon transmit time in TSF 176 176 * @bi: beacon interval in TU 177 - * @bi_reciprocal: 2^32 / bi 177 + * @reserved: reserved 178 178 * @beacon_template: beacon template ID 179 179 */ 180 180 struct iwl_mac_data_ibss { 181 181 __le32 beacon_time; 182 182 __le64 beacon_tsf; 183 183 __le32 bi; 184 - __le32 bi_reciprocal; 184 + __le32 reserved; 185 185 __le32 beacon_template; 186 186 } __packed; /* IBSS_MAC_DATA_API_S_VER_1 */ 187 + 188 + /** 189 + * enum iwl_mac_data_policy - policy of the data path for this MAC 190 + * @TWT_SUPPORTED: twt is supported 191 + */ 192 + enum iwl_mac_data_policy { 193 + TWT_SUPPORTED = BIT(0), 194 + }; 187 195 188 196 /** 189 197 * struct iwl_mac_data_sta - configuration data for station MAC context ··· 199 191 * @dtim_time: DTIM arrival time in system time 200 192 * @dtim_tsf: DTIM arrival time in TSF 201 193 * @bi: beacon interval in TU, applicable only when associated 202 - * @bi_reciprocal: 2^32 / bi , applicable only when associated 194 + * @reserved1: reserved 203 195 * @dtim_interval: DTIM interval in TU, applicable only when associated 204 - * @dtim_reciprocal: 2^32 / dtim_interval , applicable only when associated 196 + * @data_policy: see &enum iwl_mac_data_policy 205 197 * @listen_interval: in beacon intervals, applicable only when associated 206 198 * @assoc_id: unique ID assigned by the AP during association 207 199 * @assoc_beacon_arrive_time: TSF of first beacon after association ··· 211 203 __le32 dtim_time; 212 204 __le64 dtim_tsf; 213 205 __le32 bi; 214 - __le32 bi_reciprocal; 206 + __le32 reserved1; 215 207 __le32 dtim_interval; 216 - __le32 dtim_reciprocal; 208 + __le32 data_policy; 217 209 __le32 listen_interval; 218 210 __le32 assoc_id; 219 211 __le32 assoc_beacon_arrive_time; 220 - } __packed; /* STA_MAC_DATA_API_S_VER_1 */ 212 + } __packed; /* STA_MAC_DATA_API_S_VER_2 */ 221 213 222 214 /** 223 215 * struct iwl_mac_data_go - configuration data for P2P GO MAC context ··· 241 233 struct iwl_mac_data_p2p_sta { 242 234 struct iwl_mac_data_sta sta; 243 235 __le32 ctwin; 244 - } __packed; /* P2P_STA_MAC_DATA_API_S_VER_1 */ 236 + } __packed; /* P2P_STA_MAC_DATA_API_S_VER_2 */ 245 237 246 238 /** 247 239 * struct iwl_mac_data_pibss - Pseudo IBSS config data ··· 385 377 struct iwl_mac_data_ibss ibss; 386 378 }; 387 379 } __packed; /* MAC_CONTEXT_CMD_API_S_VER_1 */ 388 - 389 - static inline u32 iwl_mvm_reciprocal(u32 v) 390 - { 391 - if (!v) 392 - return 0; 393 - return 0xFFFFFFFF / v; 394 - } 395 380 396 381 #define IWL_NONQOS_SEQ_GET 0x1 397 382 #define IWL_NONQOS_SEQ_SET 0x2
+262 -15
drivers/net/wireless/intel/iwlwifi/fw/dbg.c
··· 225 225 *dump_data = iwl_fw_error_next_data(*dump_data); 226 226 } 227 227 228 - static void iwl_fw_dump_fifos(struct iwl_fw_runtime *fwrt, 229 - struct iwl_fw_error_dump_data **dump_data) 228 + static void iwl_fw_dump_rxf(struct iwl_fw_runtime *fwrt, 229 + struct iwl_fw_error_dump_data **dump_data) 230 230 { 231 - struct iwl_fw_error_dump_fifo *fifo_hdr; 232 231 struct iwl_fwrt_shared_mem_cfg *cfg = &fwrt->smem_cfg; 233 - u32 *fifo_data; 234 - u32 fifo_len; 235 232 unsigned long flags; 236 - int i, j; 237 233 238 - IWL_DEBUG_INFO(fwrt, "WRT FIFO dump\n"); 234 + IWL_DEBUG_INFO(fwrt, "WRT RX FIFO dump\n"); 239 235 240 236 if (!iwl_trans_grab_nic_access(fwrt->trans, &flags)) 241 237 return; ··· 249 253 cfg->lmac[1].rxfifo1_size, 250 254 LMAC2_PRPH_OFFSET, 2); 251 255 } 256 + 257 + iwl_trans_release_nic_access(fwrt->trans, &flags); 258 + } 259 + 260 + static void iwl_fw_dump_txf(struct iwl_fw_runtime *fwrt, 261 + struct iwl_fw_error_dump_data **dump_data) 262 + { 263 + struct iwl_fw_error_dump_fifo *fifo_hdr; 264 + struct iwl_fwrt_shared_mem_cfg *cfg = &fwrt->smem_cfg; 265 + u32 *fifo_data; 266 + u32 fifo_len; 267 + unsigned long flags; 268 + int i, j; 269 + 270 + IWL_DEBUG_INFO(fwrt, "WRT TX FIFO dump\n"); 271 + 272 + if (!iwl_trans_grab_nic_access(fwrt->trans, &flags)) 273 + return; 252 274 253 275 if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_TXF)) { 254 276 /* Pull TXF data from LMAC1 */ ··· 609 595 do {size_t item = item_len; len += (!!item) * const_len + item; } \ 610 596 while (0) 611 597 612 - static int iwl_fw_fifo_len(struct iwl_fw_runtime *fwrt, 613 - struct iwl_fwrt_shared_mem_cfg *mem_cfg) 598 + static int iwl_fw_rxf_len(struct iwl_fw_runtime *fwrt, 599 + struct iwl_fwrt_shared_mem_cfg *mem_cfg) 614 600 { 615 601 size_t hdr_len = sizeof(struct iwl_fw_error_dump_data) + 616 602 sizeof(struct iwl_fw_error_dump_fifo); ··· 618 604 int i; 619 605 620 606 if (!iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_RXF)) 621 - goto dump_txf; 607 + return 0; 622 608 623 609 /* Count RXF2 size */ 624 610 ADD_LEN(fifo_len, mem_cfg->rxfifo2_size, hdr_len); ··· 627 613 for (i = 0; i < mem_cfg->num_lmacs; i++) 628 614 ADD_LEN(fifo_len, mem_cfg->lmac[i].rxfifo1_size, hdr_len); 629 615 630 - dump_txf: 616 + return fifo_len; 617 + } 618 + 619 + static int iwl_fw_txf_len(struct iwl_fw_runtime *fwrt, 620 + struct iwl_fwrt_shared_mem_cfg *mem_cfg) 621 + { 622 + size_t hdr_len = sizeof(struct iwl_fw_error_dump_data) + 623 + sizeof(struct iwl_fw_error_dump_fifo); 624 + u32 fifo_len = 0; 625 + int i; 626 + 631 627 if (!iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_TXF)) 632 628 goto dump_internal_txf; 633 629 ··· 721 697 722 698 /* reading RXF/TXF sizes */ 723 699 if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status)) { 724 - fifo_len = iwl_fw_fifo_len(fwrt, mem_cfg); 700 + fifo_len = iwl_fw_rxf_len(fwrt, mem_cfg); 701 + fifo_len += iwl_fw_txf_len(fwrt, mem_cfg); 725 702 726 703 /* Make room for PRPH registers */ 727 704 if (!fwrt->trans->cfg->gen2 && ··· 842 817 843 818 /* We only dump the FIFOs if the FW is in error state */ 844 819 if (fifo_len) { 845 - iwl_fw_dump_fifos(fwrt, &dump_data); 820 + iwl_fw_dump_rxf(fwrt, &dump_data); 821 + iwl_fw_dump_txf(fwrt, &dump_data); 846 822 if (radio_len) 847 823 iwl_read_radio_regs(fwrt, &dump_data); 848 824 } ··· 934 908 struct iwl_fw_error_dump_file *dump_file; 935 909 struct scatterlist *sg_dump_data; 936 910 u32 file_len; 911 + u32 dump_mask = fwrt->fw->dbg.dump_mask; 937 912 938 913 IWL_DEBUG_INFO(fwrt, "WRT dump start\n"); 939 914 ··· 954 927 goto out; 955 928 } 956 929 957 - fw_error_dump->trans_ptr = iwl_trans_dump_data(fwrt->trans, 958 - fwrt->dump.monitor_only); 930 + if (fwrt->dump.monitor_only) 931 + dump_mask &= IWL_FW_ERROR_DUMP_FW_MONITOR; 932 + 933 + fw_error_dump->trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask); 959 934 file_len = le32_to_cpu(dump_file->file_len); 960 935 fw_error_dump->fwrt_len = file_len; 961 936 if (fw_error_dump->trans_ptr) { ··· 997 968 }, 998 969 }; 999 970 IWL_EXPORT_SYMBOL(iwl_dump_desc_assert); 971 + 972 + void iwl_fw_assert_error_dump(struct iwl_fw_runtime *fwrt) 973 + { 974 + IWL_INFO(fwrt, "error dump due to fw assert\n"); 975 + fwrt->dump.desc = &iwl_dump_desc_assert; 976 + iwl_fw_error_dump(fwrt); 977 + } 978 + IWL_EXPORT_SYMBOL(iwl_fw_assert_error_dump); 1000 979 1001 980 void iwl_fw_alive_error_dump(struct iwl_fw_runtime *fwrt) 1002 981 { ··· 1116 1079 { 1117 1080 int ret, len = 0; 1118 1081 char buf[64]; 1082 + 1083 + if (fwrt->trans->ini_valid) 1084 + return 0; 1119 1085 1120 1086 if (fmt) { 1121 1087 va_list ap; ··· 1263 1223 cfg->d3_debug_data_length); 1264 1224 } 1265 1225 IWL_EXPORT_SYMBOL(iwl_fw_dbg_read_d3_debug_data); 1226 + 1227 + static void 1228 + iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt, 1229 + struct iwl_fw_ini_allocation_tlv *alloc) 1230 + { 1231 + struct iwl_trans *trans = fwrt->trans; 1232 + struct iwl_continuous_record_cmd cont_rec = {}; 1233 + struct iwl_buffer_allocation_cmd *cmd = (void *)&cont_rec.pad[0]; 1234 + struct iwl_host_cmd hcmd = { 1235 + .id = LDBG_CONFIG_CMD, 1236 + .flags = CMD_ASYNC, 1237 + .data[0] = &cont_rec, 1238 + .len[0] = sizeof(cont_rec), 1239 + }; 1240 + void *virtual_addr = NULL; 1241 + u32 size = le32_to_cpu(alloc->size); 1242 + dma_addr_t phys_addr; 1243 + 1244 + cont_rec.record_mode.enable_recording = cpu_to_le16(BUFFER_ALLOCATION); 1245 + 1246 + if (!trans->num_blocks && 1247 + le32_to_cpu(alloc->buffer_location) != 1248 + IWL_FW_INI_LOCATION_DRAM_PATH) 1249 + return; 1250 + 1251 + virtual_addr = dma_alloc_coherent(fwrt->trans->dev, size, 1252 + &phys_addr, GFP_KERNEL); 1253 + 1254 + /* TODO: alloc fragments if needed */ 1255 + if (!virtual_addr) 1256 + IWL_ERR(fwrt, "Failed to allocate debug memory\n"); 1257 + 1258 + if (WARN_ON_ONCE(trans->num_blocks == ARRAY_SIZE(trans->fw_mon))) 1259 + return; 1260 + 1261 + trans->fw_mon[trans->num_blocks].block = virtual_addr; 1262 + trans->fw_mon[trans->num_blocks].physical = phys_addr; 1263 + trans->fw_mon[trans->num_blocks].size = size; 1264 + trans->num_blocks++; 1265 + 1266 + IWL_DEBUG_FW(trans, "Allocated debug block of size %d\n", size); 1267 + 1268 + /* First block is assigned via registers / context info */ 1269 + if (trans->num_blocks == 1) 1270 + return; 1271 + 1272 + cmd->num_frags = cpu_to_le32(1); 1273 + cmd->fragments[0].address = cpu_to_le64(phys_addr); 1274 + cmd->fragments[0].size = alloc->size; 1275 + cmd->allocation_id = alloc->allocation_id; 1276 + cmd->buffer_location = alloc->buffer_location; 1277 + 1278 + iwl_trans_send_cmd(trans, &hcmd); 1279 + } 1280 + 1281 + static void iwl_fw_dbg_send_hcmd(struct iwl_fw_runtime *fwrt, 1282 + struct iwl_ucode_tlv *tlv) 1283 + { 1284 + struct iwl_fw_ini_hcmd_tlv *hcmd_tlv = (void *)&tlv->data[0]; 1285 + struct iwl_fw_ini_hcmd *data = &hcmd_tlv->hcmd; 1286 + u16 len = le32_to_cpu(tlv->length) - sizeof(*hcmd_tlv); 1287 + 1288 + struct iwl_host_cmd hcmd = { 1289 + .id = WIDE_ID(data->group, data->id), 1290 + .len = { len, }, 1291 + .data = { data->data, }, 1292 + }; 1293 + 1294 + iwl_trans_send_cmd(fwrt->trans, &hcmd); 1295 + } 1296 + 1297 + static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt, 1298 + struct iwl_fw_ini_region_tlv *tlv, 1299 + bool ext, enum iwl_fw_ini_apply_point pnt) 1300 + { 1301 + void *iter = (void *)tlv->region_config; 1302 + int i, size = le32_to_cpu(tlv->num_regions); 1303 + 1304 + for (i = 0; i < size; i++) { 1305 + struct iwl_fw_ini_region_cfg *reg = iter; 1306 + int id = le32_to_cpu(reg->region_id); 1307 + struct iwl_fw_ini_active_regs *active; 1308 + 1309 + if (WARN_ON(id >= ARRAY_SIZE(fwrt->dump.active_regs))) 1310 + break; 1311 + 1312 + active = &fwrt->dump.active_regs[id]; 1313 + 1314 + if (ext && active->apply_point == pnt) 1315 + IWL_WARN(fwrt->trans, 1316 + "External region TLV overrides FW default %x\n", 1317 + id); 1318 + 1319 + IWL_DEBUG_FW(fwrt, 1320 + "%s: apply point %d, activating region ID %d\n", 1321 + __func__, pnt, id); 1322 + 1323 + active->reg = reg; 1324 + active->apply_point = pnt; 1325 + 1326 + if (le32_to_cpu(reg->region_type) != 1327 + IWL_FW_INI_REGION_DRAM_BUFFER) 1328 + iter += le32_to_cpu(reg->num_regions) * sizeof(__le32); 1329 + 1330 + iter += sizeof(*reg); 1331 + } 1332 + } 1333 + 1334 + static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt, 1335 + struct iwl_fw_ini_trigger_tlv *tlv, 1336 + bool ext, 1337 + enum iwl_fw_ini_apply_point apply_point) 1338 + { 1339 + int i, size = le32_to_cpu(tlv->num_triggers); 1340 + void *iter = (void *)tlv->trigger_config; 1341 + 1342 + for (i = 0; i < size; i++) { 1343 + struct iwl_fw_ini_trigger *trig = iter; 1344 + struct iwl_fw_ini_active_triggers *active; 1345 + int id = le32_to_cpu(trig->trigger_id); 1346 + u32 num; 1347 + 1348 + if (WARN_ON(id >= ARRAY_SIZE(fwrt->dump.active_trigs))) 1349 + break; 1350 + 1351 + active = &fwrt->dump.active_trigs[id]; 1352 + 1353 + if (active->apply_point != apply_point) { 1354 + active->conf = NULL; 1355 + active->conf_ext = NULL; 1356 + } 1357 + 1358 + num = le32_to_cpu(trig->num_regions); 1359 + 1360 + if (ext && active->apply_point == apply_point) { 1361 + num += le32_to_cpu(active->conf->num_regions); 1362 + if (trig->ignore_default) { 1363 + active->conf_ext = active->conf; 1364 + active->conf = trig; 1365 + } else { 1366 + active->conf_ext = trig; 1367 + } 1368 + } else { 1369 + active->conf = trig; 1370 + } 1371 + 1372 + iter += sizeof(*trig) + 1373 + le32_to_cpu(trig->num_regions) * sizeof(__le32); 1374 + 1375 + active->active = num; 1376 + active->apply_point = apply_point; 1377 + } 1378 + } 1379 + 1380 + static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, 1381 + struct iwl_apply_point_data *data, 1382 + enum iwl_fw_ini_apply_point pnt, 1383 + bool ext) 1384 + { 1385 + void *iter = data->data; 1386 + 1387 + while (iter && iter < data->data + data->size) { 1388 + struct iwl_ucode_tlv *tlv = iter; 1389 + void *ini_tlv = (void *)tlv->data; 1390 + u32 type = le32_to_cpu(tlv->type); 1391 + 1392 + switch (type) { 1393 + case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION: 1394 + iwl_fw_dbg_buffer_allocation(fwrt, ini_tlv); 1395 + break; 1396 + case IWL_UCODE_TLV_TYPE_HCMD: 1397 + if (pnt < IWL_FW_INI_APPLY_AFTER_ALIVE) { 1398 + IWL_ERR(fwrt, 1399 + "Invalid apply point %x for host command\n", 1400 + pnt); 1401 + goto next; 1402 + } 1403 + iwl_fw_dbg_send_hcmd(fwrt, tlv); 1404 + break; 1405 + case IWL_UCODE_TLV_TYPE_REGIONS: 1406 + iwl_fw_dbg_update_regions(fwrt, ini_tlv, ext, pnt); 1407 + break; 1408 + case IWL_UCODE_TLV_TYPE_TRIGGERS: 1409 + iwl_fw_dbg_update_triggers(fwrt, ini_tlv, ext, pnt); 1410 + break; 1411 + case IWL_UCODE_TLV_TYPE_DEBUG_FLOW: 1412 + break; 1413 + default: 1414 + WARN_ONCE(1, "Invalid TLV %x for apply point\n", type); 1415 + break; 1416 + } 1417 + next: 1418 + iter += sizeof(*tlv) + le32_to_cpu(tlv->length); 1419 + } 1420 + } 1421 + 1422 + void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, 1423 + enum iwl_fw_ini_apply_point apply_point) 1424 + { 1425 + void *data = &fwrt->trans->apply_points[apply_point]; 1426 + 1427 + _iwl_fw_dbg_apply_point(fwrt, data, apply_point, false); 1428 + 1429 + data = &fwrt->trans->apply_points_ext[apply_point]; 1430 + _iwl_fw_dbg_apply_point(fwrt, data, apply_point, true); 1431 + } 1432 + IWL_EXPORT_SYMBOL(iwl_fw_dbg_apply_point);
+22
drivers/net/wireless/intel/iwlwifi/fw/dbg.h
··· 72 72 #include "file.h" 73 73 #include "error-dump.h" 74 74 #include "api/commands.h" 75 + #include "api/dbg-tlv.h" 75 76 76 77 /** 77 78 * struct iwl_fw_dump_desc - describes the dump ··· 193 192 { 194 193 struct iwl_fw_dbg_trigger_tlv *trig; 195 194 195 + if (fwrt->trans->ini_valid) 196 + return NULL; 197 + 196 198 if (!iwl_fw_dbg_trigger_enabled(fwrt->fw, id)) 197 199 return NULL; 198 200 ··· 266 262 iwl_write_prph(trans, DBGC_IN_SAMPLE, 0); 267 263 udelay(100); 268 264 iwl_write_prph(trans, DBGC_OUT_CTRL, 0); 265 + #ifdef CONFIG_IWLWIFI_DEBUGFS 266 + trans->dbg_rec_on = false; 267 + #endif 269 268 } 270 269 271 270 static inline void ··· 299 292 } 300 293 } 301 294 295 + #ifdef CONFIG_IWLWIFI_DEBUGFS 296 + static inline void iwl_fw_set_dbg_rec_on(struct iwl_fw_runtime *fwrt) 297 + { 298 + if (fwrt->fw->dbg.dest_tlv && fwrt->cur_fw_img == IWL_UCODE_REGULAR) 299 + fwrt->trans->dbg_rec_on = true; 300 + } 301 + #endif 302 + 302 303 static inline void 303 304 iwl_fw_dbg_restart_recording(struct iwl_fw_runtime *fwrt, 304 305 struct iwl_fw_dbg_params *params) ··· 315 300 _iwl_fw_dbg_restart_recording(fwrt->trans, params); 316 301 else 317 302 iwl_fw_dbg_start_stop_hcmd(fwrt, true); 303 + #ifdef CONFIG_IWLWIFI_DEBUGFS 304 + iwl_fw_set_dbg_rec_on(fwrt); 305 + #endif 318 306 } 319 307 320 308 static inline void iwl_fw_dump_conf_clear(struct iwl_fw_runtime *fwrt) ··· 396 378 397 379 #endif /* CONFIG_IWLWIFI_DEBUGFS */ 398 380 381 + void iwl_fw_assert_error_dump(struct iwl_fw_runtime *fwrt); 399 382 void iwl_fw_alive_error_dump(struct iwl_fw_runtime *fwrt); 400 383 void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt); 384 + void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, 385 + enum iwl_fw_ini_apply_point apply_point); 386 + 401 387 #endif /* __iwl_fw_dbg_h__ */
+7
drivers/net/wireless/intel/iwlwifi/fw/file.h
··· 91 91 } u; 92 92 }; 93 93 94 + #define IWL_UCODE_INI_TLV_GROUP BIT(24) 95 + 94 96 /* 95 97 * new TLV uCode file layout 96 98 * ··· 143 141 IWL_UCODE_TLV_FW_GSCAN_CAPA = 50, 144 142 IWL_UCODE_TLV_FW_MEM_SEG = 51, 145 143 IWL_UCODE_TLV_IML = 52, 144 + IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION = IWL_UCODE_INI_TLV_GROUP | 0x1, 145 + IWL_UCODE_TLV_TYPE_HCMD = IWL_UCODE_INI_TLV_GROUP | 0x2, 146 + IWL_UCODE_TLV_TYPE_REGIONS = IWL_UCODE_INI_TLV_GROUP | 0x3, 147 + IWL_UCODE_TLV_TYPE_TRIGGERS = IWL_UCODE_INI_TLV_GROUP | 0x4, 148 + IWL_UCODE_TLV_TYPE_DEBUG_FLOW = IWL_UCODE_INI_TLV_GROUP | 0x5, 146 149 147 150 /* TLVs 0x1000-0x2000 are for internal driver usage */ 148 151 IWL_UCODE_TLV_FW_DBG_DUMP_LST = 0x1000,
+26
drivers/net/wireless/intel/iwlwifi/fw/img.h
··· 65 65 #define __iwl_fw_img_h__ 66 66 #include <linux/types.h> 67 67 68 + #include "api/dbg-tlv.h" 69 + 68 70 #include "file.h" 69 71 #include "error-dump.h" 70 72 ··· 220 218 struct iwl_fw_dbg_mem_seg_tlv *mem_tlv; 221 219 size_t n_mem_tlv; 222 220 u32 dump_mask; 221 + }; 222 + 223 + /** 224 + * struct iwl_fw_ini_active_triggers 225 + * @active: is this trigger active 226 + * @apply_point: last apply point that updated this trigger 227 + * @conf: active trigger 228 + * @conf_ext: second trigger, contains extra regions to dump 229 + */ 230 + struct iwl_fw_ini_active_triggers { 231 + bool active; 232 + enum iwl_fw_ini_apply_point apply_point; 233 + struct iwl_fw_ini_trigger *conf; 234 + struct iwl_fw_ini_trigger *conf_ext; 235 + }; 236 + 237 + /** 238 + * struct iwl_fw_ini_active_regs 239 + * @reg: active region from TLV 240 + * @apply_point: apply point where it became active 241 + */ 242 + struct iwl_fw_ini_active_regs { 243 + struct iwl_fw_ini_region_cfg *reg; 244 + enum iwl_fw_ini_apply_point apply_point; 223 245 }; 224 246 225 247 /**
+3
drivers/net/wireless/intel/iwlwifi/fw/runtime.h
··· 64 64 #include "iwl-trans.h" 65 65 #include "img.h" 66 66 #include "fw/api/debug.h" 67 + #include "fw/api/dbg-tlv.h" 67 68 #include "fw/api/paging.h" 68 69 #include "iwl-eeprom-parse.h" 69 70 ··· 140 139 /* ts of the beginning of a non-collect fw dbg data period */ 141 140 unsigned long non_collect_ts_start[FW_DBG_TRIGGER_MAX - 1]; 142 141 u32 *d3_debug_data; 142 + struct iwl_fw_ini_active_regs active_regs[IWL_FW_INI_MAX_REGION_ID]; 143 + struct iwl_fw_ini_active_triggers active_trigs[IWL_FW_TRIGGER_ID_NUM]; 143 144 } dump; 144 145 #ifdef CONFIG_IWLWIFI_DEBUGFS 145 146 struct {
+230
drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
··· 1 + /****************************************************************************** 2 + * 3 + * This file is provided under a dual BSD/GPLv2 license. When using or 4 + * redistributing this file, you may do so under either license. 5 + * 6 + * GPL LICENSE SUMMARY 7 + * 8 + * Copyright (C) 2018 Intel Corporation 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of version 2 of the GNU General Public License as 12 + * published by the Free Software Foundation. 13 + * 14 + * This program is distributed in the hope that it will be useful, but 15 + * WITHOUT ANY WARRANTY; without even the implied warranty of 16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 + * General Public License for more details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this program. 21 + * 22 + * The full GNU General Public License is included in this distribution 23 + * in the file called COPYING. 24 + * 25 + * Contact Information: 26 + * Intel Linux Wireless <linuxwifi@intel.com> 27 + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 28 + * 29 + * BSD LICENSE 30 + * 31 + * Copyright (C) 2018 Intel Corporation 32 + * All rights reserved. 33 + * 34 + * Redistribution and use in source and binary forms, with or without 35 + * modification, are permitted provided that the following conditions 36 + * are met: 37 + * 38 + * * Redistributions of source code must retain the above copyright 39 + * notice, this list of conditions and the following disclaimer. 40 + * * Redistributions in binary form must reproduce the above copyright 41 + * notice, this list of conditions and the following disclaimer in 42 + * the documentation and/or other materials provided with the 43 + * distribution. 44 + * * Neither the name Intel Corporation nor the names of its 45 + * contributors may be used to endorse or promote products derived 46 + * from this software without specific prior written permission. 47 + * 48 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 49 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 50 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 51 + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 52 + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 53 + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 54 + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 55 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 56 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 57 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 58 + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 59 + * 60 + *****************************************************************************/ 61 + 62 + #include <linux/firmware.h> 63 + #include "iwl-trans.h" 64 + #include "iwl-dbg-tlv.h" 65 + 66 + void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv, 67 + bool ext) 68 + { 69 + struct iwl_apply_point_data *data; 70 + struct iwl_fw_ini_header *header = (void *)&tlv->data[0]; 71 + u32 apply_point = le32_to_cpu(header->apply_point); 72 + 73 + int copy_size = le32_to_cpu(tlv->length) + sizeof(*tlv); 74 + 75 + if (WARN_ONCE(apply_point >= IWL_FW_INI_APPLY_NUM, 76 + "Invalid apply point id %d\n", apply_point)) 77 + return; 78 + 79 + if (ext) 80 + data = &trans->apply_points_ext[apply_point]; 81 + else 82 + data = &trans->apply_points[apply_point]; 83 + 84 + /* 85 + * Make sure we still have room to copy this TLV. Offset points to the 86 + * location the last copy ended. 87 + */ 88 + if (WARN_ONCE(data->offset + copy_size > data->size, 89 + "Not enough memory for apply point %d\n", 90 + apply_point)) 91 + return; 92 + 93 + memcpy(data->data + data->offset, (void *)tlv, copy_size); 94 + data->offset += copy_size; 95 + } 96 + 97 + void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data, 98 + bool ext) 99 + { 100 + struct iwl_ucode_tlv *tlv; 101 + u32 size[IWL_FW_INI_APPLY_NUM] = {0}; 102 + int i; 103 + 104 + while (len >= sizeof(*tlv)) { 105 + u32 tlv_len, tlv_type, apply; 106 + struct iwl_fw_ini_header *hdr; 107 + 108 + len -= sizeof(*tlv); 109 + tlv = (void *)data; 110 + 111 + tlv_len = le32_to_cpu(tlv->length); 112 + tlv_type = le32_to_cpu(tlv->type); 113 + 114 + if (len < tlv_len) 115 + return; 116 + 117 + len -= ALIGN(tlv_len, 4); 118 + data += sizeof(*tlv) + ALIGN(tlv_len, 4); 119 + 120 + if (!(tlv_type & IWL_UCODE_INI_TLV_GROUP)) 121 + continue; 122 + 123 + hdr = (void *)&tlv->data[0]; 124 + apply = le32_to_cpu(hdr->apply_point); 125 + 126 + IWL_DEBUG_FW(trans, "Read TLV %x, apply point %d\n", 127 + le32_to_cpu(tlv->type), apply); 128 + 129 + if (WARN_ON(apply >= IWL_FW_INI_APPLY_NUM)) 130 + continue; 131 + 132 + size[apply] += sizeof(*tlv) + tlv_len; 133 + } 134 + 135 + for (i = 0; i < ARRAY_SIZE(size); i++) { 136 + void *mem; 137 + 138 + if (!size[i]) 139 + continue; 140 + 141 + mem = kzalloc(size[i], GFP_KERNEL); 142 + 143 + if (!mem) { 144 + IWL_ERR(trans, "No memory for apply point %d\n", i); 145 + return; 146 + } 147 + 148 + if (ext) { 149 + trans->apply_points_ext[i].data = mem; 150 + trans->apply_points_ext[i].size = size[i]; 151 + } else { 152 + trans->apply_points[i].data = mem; 153 + trans->apply_points[i].size = size[i]; 154 + } 155 + 156 + trans->ini_valid = true; 157 + } 158 + } 159 + 160 + void iwl_fw_dbg_free(struct iwl_trans *trans) 161 + { 162 + int i; 163 + 164 + for (i = 0; i < ARRAY_SIZE(trans->apply_points); i++) { 165 + kfree(trans->apply_points[i].data); 166 + trans->apply_points[i].size = 0; 167 + trans->apply_points[i].offset = 0; 168 + 169 + kfree(trans->apply_points_ext[i].data); 170 + trans->apply_points_ext[i].size = 0; 171 + trans->apply_points_ext[i].offset = 0; 172 + } 173 + } 174 + 175 + static int iwl_parse_fw_dbg_tlv(struct iwl_trans *trans, const u8 *data, 176 + size_t len) 177 + { 178 + struct iwl_ucode_tlv *tlv; 179 + enum iwl_ucode_tlv_type tlv_type; 180 + u32 tlv_len; 181 + 182 + while (len >= sizeof(*tlv)) { 183 + len -= sizeof(*tlv); 184 + tlv = (void *)data; 185 + 186 + tlv_len = le32_to_cpu(tlv->length); 187 + tlv_type = le32_to_cpu(tlv->type); 188 + 189 + if (len < tlv_len) { 190 + IWL_ERR(trans, "invalid TLV len: %zd/%u\n", 191 + len, tlv_len); 192 + return -EINVAL; 193 + } 194 + len -= ALIGN(tlv_len, 4); 195 + data += sizeof(*tlv) + ALIGN(tlv_len, 4); 196 + 197 + switch (tlv_type) { 198 + case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION: 199 + case IWL_UCODE_TLV_TYPE_HCMD: 200 + case IWL_UCODE_TLV_TYPE_REGIONS: 201 + case IWL_UCODE_TLV_TYPE_TRIGGERS: 202 + case IWL_UCODE_TLV_TYPE_DEBUG_FLOW: 203 + iwl_fw_dbg_copy_tlv(trans, tlv, true); 204 + default: 205 + WARN_ONCE(1, "Invalid TLV %x\n", tlv_type); 206 + break; 207 + } 208 + } 209 + 210 + return 0; 211 + } 212 + 213 + void iwl_load_fw_dbg_tlv(struct device *dev, struct iwl_trans *trans) 214 + { 215 + const struct firmware *fw; 216 + int res; 217 + 218 + if (trans->external_ini_loaded || !iwlwifi_mod_params.enable_ini) 219 + return; 220 + 221 + res = request_firmware(&fw, "iwl-dbg-tlv.ini", dev); 222 + if (res) 223 + return; 224 + 225 + iwl_alloc_dbg_tlv(trans, fw->size, fw->data, true); 226 + iwl_parse_fw_dbg_tlv(trans, fw->data, fw->size); 227 + 228 + trans->external_ini_loaded = true; 229 + release_firmware(fw); 230 + }
+87
drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h
··· 1 + /****************************************************************************** 2 + * 3 + * This file is provided under a dual BSD/GPLv2 license. When using or 4 + * redistributing this file, you may do so under either license. 5 + * 6 + * GPL LICENSE SUMMARY 7 + * 8 + * Copyright (C) 2018 Intel Corporation 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of version 2 of the GNU General Public License as 12 + * published by the Free Software Foundation. 13 + * 14 + * This program is distributed in the hope that it will be useful, but 15 + * WITHOUT ANY WARRANTY; without even the implied warranty of 16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 + * General Public License for more details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this program. 21 + * 22 + * The full GNU General Public License is included in this distribution 23 + * in the file called COPYING. 24 + * 25 + * Contact Information: 26 + * Intel Linux Wireless <linuxwifi@intel.com> 27 + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 28 + * 29 + * BSD LICENSE 30 + * 31 + * Copyright (C) 2018 Intel Corporation 32 + * All rights reserved. 33 + * 34 + * Redistribution and use in source and binary forms, with or without 35 + * modification, are permitted provided that the following conditions 36 + * are met: 37 + * 38 + * * Redistributions of source code must retain the above copyright 39 + * notice, this list of conditions and the following disclaimer. 40 + * * Redistributions in binary form must reproduce the above copyright 41 + * notice, this list of conditions and the following disclaimer in 42 + * the documentation and/or other materials provided with the 43 + * distribution. 44 + * * Neither the name Intel Corporation nor the names of its 45 + * contributors may be used to endorse or promote products derived 46 + * from this software without specific prior written permission. 47 + * 48 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 49 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 50 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 51 + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 52 + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 53 + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 54 + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 55 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 56 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 57 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 58 + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 59 + * 60 + *****************************************************************************/ 61 + #ifndef __iwl_dbg_tlv_h__ 62 + #define __iwl_dbg_tlv_h__ 63 + 64 + #include <linux/device.h> 65 + #include <linux/types.h> 66 + 67 + /** 68 + * struct iwl_apply_point_data 69 + * @data: start address of this apply point data 70 + * @size total size of the data 71 + * @offset: current offset of the copied data 72 + */ 73 + struct iwl_apply_point_data { 74 + void *data; 75 + int size; 76 + int offset; 77 + }; 78 + 79 + struct iwl_trans; 80 + void iwl_load_fw_dbg_tlv(struct device *dev, struct iwl_trans *trans); 81 + void iwl_fw_dbg_free(struct iwl_trans *trans); 82 + void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv, 83 + bool ext); 84 + void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data, 85 + bool ext); 86 + 87 + #endif /* __iwl_dbg_tlv_h__*/
+22 -2
drivers/net/wireless/intel/iwlwifi/iwl-drv.c
··· 72 72 #include "iwl-op-mode.h" 73 73 #include "iwl-agn-hw.h" 74 74 #include "fw/img.h" 75 + #include "iwl-dbg-tlv.h" 75 76 #include "iwl-config.h" 76 77 #include "iwl-modparams.h" 77 78 ··· 646 645 647 646 len -= sizeof(*ucode); 648 647 648 + if (iwlwifi_mod_params.enable_ini) 649 + iwl_alloc_dbg_tlv(drv->trans, len, data, false); 650 + 649 651 while (len >= sizeof(*tlv)) { 650 652 len -= sizeof(*tlv); 651 653 tlv = (void *)data; ··· 1090 1086 return -ENOMEM; 1091 1087 break; 1092 1088 } 1089 + case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION: 1090 + case IWL_UCODE_TLV_TYPE_HCMD: 1091 + case IWL_UCODE_TLV_TYPE_REGIONS: 1092 + case IWL_UCODE_TLV_TYPE_TRIGGERS: 1093 + case IWL_UCODE_TLV_TYPE_DEBUG_FLOW: 1094 + if (iwlwifi_mod_params.enable_ini) 1095 + iwl_fw_dbg_copy_tlv(drv->trans, tlv, false); 1093 1096 default: 1094 1097 IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type); 1095 1098 break; ··· 1576 1565 if (!drv->dbgfs_drv) { 1577 1566 IWL_ERR(drv, "failed to create debugfs directory\n"); 1578 1567 ret = -ENOMEM; 1579 - goto err_free_drv; 1568 + goto err_free_tlv; 1580 1569 } 1581 1570 1582 1571 /* Create transport layer debugfs dir */ ··· 1601 1590 #ifdef CONFIG_IWLWIFI_DEBUGFS 1602 1591 err_free_dbgfs: 1603 1592 debugfs_remove_recursive(drv->dbgfs_drv); 1604 - err_free_drv: 1593 + err_free_tlv: 1594 + iwl_fw_dbg_free(drv->trans); 1605 1595 #endif 1606 1596 kfree(drv); 1607 1597 err: ··· 1628 1616 mutex_unlock(&iwlwifi_opmode_table_mtx); 1629 1617 1630 1618 #ifdef CONFIG_IWLWIFI_DEBUGFS 1619 + drv->trans->ops->debugfs_cleanup(drv->trans); 1620 + 1631 1621 debugfs_remove_recursive(drv->dbgfs_drv); 1632 1622 #endif 1623 + 1624 + iwl_fw_dbg_free(drv->trans); 1633 1625 1634 1626 kfree(drv); 1635 1627 } ··· 1765 1749 module_param_named(uapsd_disable, iwlwifi_mod_params.uapsd_disable, uint, 0644); 1766 1750 MODULE_PARM_DESC(uapsd_disable, 1767 1751 "disable U-APSD functionality bitmap 1: BSS 2: P2P Client (default: 3)"); 1752 + module_param_named(enable_ini, iwlwifi_mod_params.enable_ini, 1753 + bool, S_IRUGO | S_IWUSR); 1754 + MODULE_PARM_DESC(enable_ini, 1755 + "Enable debug INI TLV FW debug infrastructure (default: 0"); 1768 1756 1769 1757 /* 1770 1758 * set bt_coex_active to true, uCode will do kill/defer
+2
drivers/net/wireless/intel/iwlwifi/iwl-modparams.h
··· 122 122 * @fw_monitor: allow to use firmware monitor 123 123 * @disable_11ac: disable VHT capabilities, default = false. 124 124 * @remove_when_gone: remove an inaccessible device from the PCIe bus. 125 + * @enable_ini: enable new FW debug infratructure (INI TLVs) 125 126 */ 126 127 struct iwl_mod_params { 127 128 int swcrypto; ··· 149 148 */ 150 149 bool disable_11ax; 151 150 bool remove_when_gone; 151 + bool enable_ini; 152 152 }; 153 153 154 154 #endif /* #__iwl_modparams_h__ */
+17 -6
drivers/net/wireless/intel/iwlwifi/iwl-trans.h
··· 73 73 #include "iwl-op-mode.h" 74 74 #include "fw/api/cmdhdr.h" 75 75 #include "fw/api/txq.h" 76 + #include "fw/api/dbg-tlv.h" 77 + #include "iwl-dbg-tlv.h" 76 78 77 79 /** 78 80 * DOC: Transport layer - what is it ? ··· 536 534 * @dump_data: return a vmalloc'ed buffer with debug data, maybe containing last 537 535 * TX'ed commands and similar. The buffer will be vfree'd by the caller. 538 536 * Note that the transport must fill in the proper file headers. 537 + * @debugfs_cleanup: used in the driver unload flow to make a proper cleanup 538 + * of the trans debugfs 539 539 */ 540 540 struct iwl_trans_ops { 541 541 ··· 606 602 void (*resume)(struct iwl_trans *trans); 607 603 608 604 struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans, 609 - bool monitor_only); 605 + u32 dump_mask); 606 + void (*debugfs_cleanup)(struct iwl_trans *trans); 610 607 }; 611 608 612 609 /** ··· 683 678 * enter/exit (in msecs). 684 679 */ 685 680 #define IWL_TRANS_IDLE_TIMEOUT 2000 686 - #define IWL_MAX_DEBUG_ALLOCATIONS 1 687 681 688 682 /** 689 683 * struct iwl_dram_data ··· 737 733 * @runtime_pm_mode: the runtime power management mode in use. This 738 734 * mode is set during the initialization phase and is not 739 735 * supposed to change during runtime. 736 + * @dbg_rec_on: true iff there is a fw debug recording currently active 740 737 */ 741 738 struct iwl_trans { 742 739 const struct iwl_trans_ops *ops; ··· 778 773 struct lockdep_map sync_cmd_lockdep_map; 779 774 #endif 780 775 776 + struct iwl_apply_point_data apply_points[IWL_FW_INI_APPLY_NUM]; 777 + struct iwl_apply_point_data apply_points_ext[IWL_FW_INI_APPLY_NUM]; 778 + 779 + bool external_ini_loaded; 780 + bool ini_valid; 781 + 781 782 const struct iwl_fw_dbg_dest_tlv_v1 *dbg_dest_tlv; 782 783 const struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX]; 783 784 struct iwl_fw_dbg_trigger_tlv * const *dbg_trigger_tlv; 784 - u32 dbg_dump_mask; 785 785 u8 dbg_n_dest_reg; 786 786 int num_blocks; 787 - struct iwl_dram_data fw_mon[IWL_MAX_DEBUG_ALLOCATIONS]; 787 + struct iwl_dram_data fw_mon[IWL_FW_INI_APPLY_NUM]; 788 788 789 789 enum iwl_plat_pm_mode system_pm_mode; 790 790 enum iwl_plat_pm_mode runtime_pm_mode; 791 791 bool suspending; 792 + bool dbg_rec_on; 792 793 793 794 /* pointer to trans specific struct */ 794 795 /*Ensure that this pointer will always be aligned to sizeof pointer */ ··· 907 896 } 908 897 909 898 static inline struct iwl_trans_dump_data * 910 - iwl_trans_dump_data(struct iwl_trans *trans, bool monitor_only) 899 + iwl_trans_dump_data(struct iwl_trans *trans, u32 dump_mask) 911 900 { 912 901 if (!trans->ops->dump_data) 913 902 return NULL; 914 - return trans->ops->dump_data(trans, monitor_only); 903 + return trans->ops->dump_data(trans, dump_mask); 915 904 } 916 905 917 906 static inline struct iwl_device_cmd *
+5
drivers/net/wireless/intel/iwlwifi/mvm/fw.c
··· 377 377 atomic_set(&mvm->mac80211_queue_stop_count[i], 0); 378 378 379 379 set_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status); 380 + #ifdef CONFIG_IWLWIFI_DEBUGFS 381 + iwl_fw_set_dbg_rec_on(&mvm->fwrt); 382 + #endif 380 383 clear_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &mvm->fwrt.status); 381 384 382 385 return 0; ··· 410 407 ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR); 411 408 if (ret) { 412 409 IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret); 410 + iwl_fw_assert_error_dump(&mvm->fwrt); 413 411 goto error; 414 412 } 415 413 ··· 1028 1024 ret = iwl_mvm_load_rt_fw(mvm); 1029 1025 if (ret) { 1030 1026 IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret); 1027 + iwl_fw_assert_error_dump(&mvm->fwrt); 1031 1028 goto error; 1032 1029 } 1033 1030
+26 -13
drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
··· 767 767 } 768 768 769 769 ctxt_sta->bi = cpu_to_le32(vif->bss_conf.beacon_int); 770 - ctxt_sta->bi_reciprocal = 771 - cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int)); 772 770 ctxt_sta->dtim_interval = cpu_to_le32(vif->bss_conf.beacon_int * 773 771 vif->bss_conf.dtim_period); 774 - ctxt_sta->dtim_reciprocal = 775 - cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int * 776 - vif->bss_conf.dtim_period)); 777 772 778 773 ctxt_sta->listen_interval = cpu_to_le32(mvm->hw->conf.listen_interval); 779 774 ctxt_sta->assoc_id = cpu_to_le32(vif->bss_conf.aid); ··· 777 782 cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); 778 783 779 784 if (vif->bss_conf.assoc && vif->bss_conf.he_support && 780 - !iwlwifi_mod_params.disable_11ax) 785 + !iwlwifi_mod_params.disable_11ax) { 786 + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 787 + u8 sta_id = mvmvif->ap_sta_id; 788 + 781 789 cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_11AX); 790 + if (sta_id != IWL_MVM_INVALID_STA) { 791 + struct ieee80211_sta *sta; 792 + 793 + sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id], 794 + lockdep_is_held(&mvm->mutex)); 795 + 796 + /* 797 + * TODO: we should check the ext cap IE but it is 798 + * unclear why the spec requires two bits (one in HE 799 + * cap IE, and one in the ext cap IE). In the meantime 800 + * rely on the HE cap IE only. 801 + */ 802 + if (sta && (sta->he_cap.he_cap_elem.mac_cap_info[0] & 803 + IEEE80211_HE_MAC_CAP0_TWT_RES)) 804 + ctxt_sta->data_policy |= 805 + cpu_to_le32(TWT_SUPPORTED); 806 + } 807 + } 808 + 782 809 783 810 return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); 784 811 } ··· 849 832 850 833 /* cmd.ibss.beacon_time/cmd.ibss.beacon_tsf are curently ignored */ 851 834 cmd.ibss.bi = cpu_to_le32(vif->bss_conf.beacon_int); 852 - cmd.ibss.bi_reciprocal = 853 - cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int)); 854 835 855 836 /* TODO: Assumes that the beacon id == mac context id */ 856 837 cmd.ibss.beacon_template = cpu_to_le32(mvmvif->id); ··· 1194 1179 IWL_DEBUG_HC(mvm, "No need to receive beacons\n"); 1195 1180 } 1196 1181 1182 + if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax) 1183 + cmd->filter_flags |= cpu_to_le32(MAC_FILTER_IN_11AX); 1184 + 1197 1185 ctxt_ap->bi = cpu_to_le32(vif->bss_conf.beacon_int); 1198 - ctxt_ap->bi_reciprocal = 1199 - cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int)); 1200 1186 ctxt_ap->dtim_interval = cpu_to_le32(vif->bss_conf.beacon_int * 1201 1187 vif->bss_conf.dtim_period); 1202 - ctxt_ap->dtim_reciprocal = 1203 - cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int * 1204 - vif->bss_conf.dtim_period)); 1205 1188 1206 1189 if (!fw_has_api(&mvm->fw->ucode_capa, 1207 1190 IWL_UCODE_TLV_API_STA_TYPE))
+4
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
··· 419 419 ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); 420 420 ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR); 421 421 ieee80211_hw_set(hw, DEAUTH_NEED_MGD_TX_PREP); 422 + ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); 422 423 423 424 if (iwl_mvm_has_tlc_offload(mvm)) { 424 425 ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW); ··· 2969 2968 if (vif->type == NL80211_IFTYPE_AP) { 2970 2969 mvmvif->ap_assoc_sta_count++; 2971 2970 iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); 2971 + if (vif->bss_conf.he_support && 2972 + !iwlwifi_mod_params.disable_11ax) 2973 + iwl_mvm_cfg_he_sta(mvm, vif, mvm_sta->sta_id); 2972 2974 } 2973 2975 2974 2976 iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,
-1
drivers/net/wireless/intel/iwlwifi/mvm/ops.c
··· 769 769 memcpy(trans->dbg_conf_tlv, mvm->fw->dbg.conf_tlv, 770 770 sizeof(trans->dbg_conf_tlv)); 771 771 trans->dbg_trigger_tlv = mvm->fw->dbg.trigger_tlv; 772 - trans->dbg_dump_mask = mvm->fw->dbg.dump_mask; 773 772 774 773 trans->iml = mvm->fw->iml; 775 774 trans->iml_len = mvm->fw->iml_len;
+1 -1
drivers/net/wireless/intel/iwlwifi/pcie/drv.c
··· 882 882 {IWL_PCI_DEVICE(0x34F0, 0x0040, iwl22000_2ax_cfg_hr)}, 883 883 {IWL_PCI_DEVICE(0x34F0, 0x0070, iwl22000_2ax_cfg_hr)}, 884 884 {IWL_PCI_DEVICE(0x34F0, 0x0078, iwl22000_2ax_cfg_hr)}, 885 - {IWL_PCI_DEVICE(0x34F0, 0x0310, iwl22000_2ac_cfg_jf)}, 885 + {IWL_PCI_DEVICE(0x34F0, 0x0310, iwl22000_2ax_cfg_hr)}, 886 886 {IWL_PCI_DEVICE(0x40C0, 0x0000, iwl22560_2ax_cfg_su_cdb)}, 887 887 {IWL_PCI_DEVICE(0x40C0, 0x0010, iwl22560_2ax_cfg_su_cdb)}, 888 888 {IWL_PCI_DEVICE(0x40c0, 0x0090, iwl22560_2ax_cfg_su_cdb)},
+44
drivers/net/wireless/intel/iwlwifi/pcie/internal.h
··· 378 378 u8 *pos; 379 379 }; 380 380 381 + #ifdef CONFIG_IWLWIFI_DEBUGFS 382 + /** 383 + * enum iwl_fw_mon_dbgfs_state - the different states of the monitor_data 384 + * debugfs file 385 + * 386 + * @IWL_FW_MON_DBGFS_STATE_CLOSED: the file is closed. 387 + * @IWL_FW_MON_DBGFS_STATE_OPEN: the file is open. 388 + * @IWL_FW_MON_DBGFS_STATE_DISABLED: the file is disabled, once this state is 389 + * set the file can no longer be used. 390 + */ 391 + enum iwl_fw_mon_dbgfs_state { 392 + IWL_FW_MON_DBGFS_STATE_CLOSED, 393 + IWL_FW_MON_DBGFS_STATE_OPEN, 394 + IWL_FW_MON_DBGFS_STATE_DISABLED, 395 + }; 396 + #endif 397 + 381 398 /** 382 399 * enum iwl_shared_irq_flags - level of sharing for irq 383 400 * @IWL_SHARED_IRQ_NON_RX: interrupt vector serves non rx causes. ··· 430 413 struct iwl_dram_data *paging; 431 414 int paging_cnt; 432 415 }; 416 + 417 + /** 418 + * struct cont_rec: continuous recording data structure 419 + * @prev_wr_ptr: the last address that was read in monitor_data 420 + * debugfs file 421 + * @prev_wrap_cnt: the wrap count that was used during the last read in 422 + * monitor_data debugfs file 423 + * @state: the state of monitor_data debugfs file as described 424 + * in &iwl_fw_mon_dbgfs_state enum 425 + * @mutex: locked while reading from monitor_data debugfs file 426 + */ 427 + #ifdef CONFIG_IWLWIFI_DEBUGFS 428 + struct cont_rec { 429 + u32 prev_wr_ptr; 430 + u32 prev_wrap_cnt; 431 + u8 state; 432 + /* Used to sync monitor_data debugfs file with driver unload flow */ 433 + struct mutex mutex; 434 + }; 435 + #endif 433 436 434 437 /** 435 438 * struct iwl_trans_pcie - PCIe transport specific data ··· 488 451 * @reg_lock: protect hw register access 489 452 * @mutex: to protect stop_device / start_fw / start_hw 490 453 * @cmd_in_flight: true when we have a host command in flight 454 + #ifdef CONFIG_IWLWIFI_DEBUGFS 455 + * @fw_mon_data: fw continuous recording data 456 + #endif 491 457 * @msix_entries: array of MSI-X entries 492 458 * @msix_enabled: true if managed to enable MSI-X 493 459 * @shared_vec_mask: the type of causes the shared vector handles ··· 577 537 spinlock_t reg_lock; 578 538 bool cmd_hold_nic_awake; 579 539 bool ref_cmd_in_flight; 540 + 541 + #ifdef CONFIG_IWLWIFI_DEBUGFS 542 + struct cont_rec fw_mon_data; 543 + #endif 580 544 581 545 struct msix_entry msix_entries[IWL_MAX_RX_HW_QUEUES]; 582 546 bool msix_enabled;
+194 -19
drivers/net/wireless/intel/iwlwifi/pcie/trans.c
··· 71 71 #include <linux/vmalloc.h> 72 72 #include <linux/pm_runtime.h> 73 73 #include <linux/module.h> 74 + #include <linux/wait.h> 74 75 75 76 #include "iwl-drv.h" 76 77 #include "iwl-trans.h" ··· 2710 2709 return count; 2711 2710 } 2712 2711 2712 + static int iwl_dbgfs_monitor_data_open(struct inode *inode, 2713 + struct file *file) 2714 + { 2715 + struct iwl_trans *trans = inode->i_private; 2716 + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 2717 + 2718 + if (!trans->dbg_dest_tlv || 2719 + trans->dbg_dest_tlv->monitor_mode != EXTERNAL_MODE) { 2720 + IWL_ERR(trans, "Debug destination is not set to DRAM\n"); 2721 + return -ENOENT; 2722 + } 2723 + 2724 + if (trans_pcie->fw_mon_data.state != IWL_FW_MON_DBGFS_STATE_CLOSED) 2725 + return -EBUSY; 2726 + 2727 + trans_pcie->fw_mon_data.state = IWL_FW_MON_DBGFS_STATE_OPEN; 2728 + return simple_open(inode, file); 2729 + } 2730 + 2731 + static int iwl_dbgfs_monitor_data_release(struct inode *inode, 2732 + struct file *file) 2733 + { 2734 + struct iwl_trans_pcie *trans_pcie = 2735 + IWL_TRANS_GET_PCIE_TRANS(inode->i_private); 2736 + 2737 + if (trans_pcie->fw_mon_data.state == IWL_FW_MON_DBGFS_STATE_OPEN) 2738 + trans_pcie->fw_mon_data.state = IWL_FW_MON_DBGFS_STATE_CLOSED; 2739 + return 0; 2740 + } 2741 + 2742 + static bool iwl_write_to_user_buf(char __user *user_buf, ssize_t count, 2743 + void *buf, ssize_t *size, 2744 + ssize_t *bytes_copied) 2745 + { 2746 + int buf_size_left = count - *bytes_copied; 2747 + 2748 + buf_size_left = buf_size_left - (buf_size_left % sizeof(u32)); 2749 + if (*size > buf_size_left) 2750 + *size = buf_size_left; 2751 + 2752 + *size -= copy_to_user(user_buf, buf, *size); 2753 + *bytes_copied += *size; 2754 + 2755 + if (buf_size_left == *size) 2756 + return true; 2757 + return false; 2758 + } 2759 + 2760 + static ssize_t iwl_dbgfs_monitor_data_read(struct file *file, 2761 + char __user *user_buf, 2762 + size_t count, loff_t *ppos) 2763 + { 2764 + struct iwl_trans *trans = file->private_data; 2765 + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 2766 + void *cpu_addr = (void *)trans->fw_mon[0].block, *curr_buf; 2767 + struct cont_rec *data = &trans_pcie->fw_mon_data; 2768 + u32 write_ptr_addr, wrap_cnt_addr, write_ptr, wrap_cnt; 2769 + ssize_t size, bytes_copied = 0; 2770 + bool b_full; 2771 + 2772 + if (trans->dbg_dest_tlv) { 2773 + write_ptr_addr = 2774 + le32_to_cpu(trans->dbg_dest_tlv->write_ptr_reg); 2775 + wrap_cnt_addr = le32_to_cpu(trans->dbg_dest_tlv->wrap_count); 2776 + } else { 2777 + write_ptr_addr = MON_BUFF_WRPTR; 2778 + wrap_cnt_addr = MON_BUFF_CYCLE_CNT; 2779 + } 2780 + 2781 + if (unlikely(!trans->dbg_rec_on)) 2782 + return 0; 2783 + 2784 + mutex_lock(&data->mutex); 2785 + if (data->state == 2786 + IWL_FW_MON_DBGFS_STATE_DISABLED) { 2787 + mutex_unlock(&data->mutex); 2788 + return 0; 2789 + } 2790 + 2791 + /* write_ptr position in bytes rather then DW */ 2792 + write_ptr = iwl_read_prph(trans, write_ptr_addr) * sizeof(u32); 2793 + wrap_cnt = iwl_read_prph(trans, wrap_cnt_addr); 2794 + 2795 + if (data->prev_wrap_cnt == wrap_cnt) { 2796 + size = write_ptr - data->prev_wr_ptr; 2797 + curr_buf = cpu_addr + data->prev_wr_ptr; 2798 + b_full = iwl_write_to_user_buf(user_buf, count, 2799 + curr_buf, &size, 2800 + &bytes_copied); 2801 + data->prev_wr_ptr += size; 2802 + 2803 + } else if (data->prev_wrap_cnt == wrap_cnt - 1 && 2804 + write_ptr < data->prev_wr_ptr) { 2805 + size = trans->fw_mon[0].size - data->prev_wr_ptr; 2806 + curr_buf = cpu_addr + data->prev_wr_ptr; 2807 + b_full = iwl_write_to_user_buf(user_buf, count, 2808 + curr_buf, &size, 2809 + &bytes_copied); 2810 + data->prev_wr_ptr += size; 2811 + 2812 + if (!b_full) { 2813 + size = write_ptr; 2814 + b_full = iwl_write_to_user_buf(user_buf, count, 2815 + cpu_addr, &size, 2816 + &bytes_copied); 2817 + data->prev_wr_ptr = size; 2818 + data->prev_wrap_cnt++; 2819 + } 2820 + } else { 2821 + if (data->prev_wrap_cnt == wrap_cnt - 1 && 2822 + write_ptr > data->prev_wr_ptr) 2823 + IWL_WARN(trans, 2824 + "write pointer passed previous write pointer, start copying from the beginning\n"); 2825 + else if (!unlikely(data->prev_wrap_cnt == 0 && 2826 + data->prev_wr_ptr == 0)) 2827 + IWL_WARN(trans, 2828 + "monitor data is out of sync, start copying from the beginning\n"); 2829 + 2830 + size = write_ptr; 2831 + b_full = iwl_write_to_user_buf(user_buf, count, 2832 + cpu_addr, &size, 2833 + &bytes_copied); 2834 + data->prev_wr_ptr = size; 2835 + data->prev_wrap_cnt = wrap_cnt; 2836 + } 2837 + 2838 + mutex_unlock(&data->mutex); 2839 + 2840 + return bytes_copied; 2841 + } 2842 + 2713 2843 DEBUGFS_READ_WRITE_FILE_OPS(interrupt); 2714 2844 DEBUGFS_READ_FILE_OPS(fh_reg); 2715 2845 DEBUGFS_READ_FILE_OPS(rx_queue); 2716 2846 DEBUGFS_READ_FILE_OPS(tx_queue); 2717 2847 DEBUGFS_WRITE_FILE_OPS(csr); 2718 2848 DEBUGFS_READ_WRITE_FILE_OPS(rfkill); 2849 + 2850 + static const struct file_operations iwl_dbgfs_monitor_data_ops = { 2851 + .read = iwl_dbgfs_monitor_data_read, 2852 + .open = iwl_dbgfs_monitor_data_open, 2853 + .release = iwl_dbgfs_monitor_data_release, 2854 + }; 2719 2855 2720 2856 /* Create the debugfs files and directories */ 2721 2857 int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans) ··· 2865 2727 DEBUGFS_ADD_FILE(csr, dir, 0200); 2866 2728 DEBUGFS_ADD_FILE(fh_reg, dir, 0400); 2867 2729 DEBUGFS_ADD_FILE(rfkill, dir, 0600); 2730 + DEBUGFS_ADD_FILE(monitor_data, dir, 0400); 2868 2731 return 0; 2869 2732 2870 2733 err: 2871 2734 IWL_ERR(trans, "failed to create the trans debugfs entry\n"); 2872 2735 return -ENOMEM; 2736 + } 2737 + 2738 + static void iwl_trans_pcie_debugfs_cleanup(struct iwl_trans *trans) 2739 + { 2740 + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 2741 + struct cont_rec *data = &trans_pcie->fw_mon_data; 2742 + 2743 + mutex_lock(&data->mutex); 2744 + data->state = IWL_FW_MON_DBGFS_STATE_DISABLED; 2745 + mutex_unlock(&data->mutex); 2873 2746 } 2874 2747 #endif /*CONFIG_IWLWIFI_DEBUGFS */ 2875 2748 ··· 3139 2990 3140 2991 static struct iwl_trans_dump_data 3141 2992 *iwl_trans_pcie_dump_data(struct iwl_trans *trans, 3142 - bool monitor_only) 2993 + u32 dump_mask) 3143 2994 { 3144 2995 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 3145 2996 struct iwl_fw_error_dump_data *data; ··· 3151 3002 int i, ptr; 3152 3003 bool dump_rbs = test_bit(STATUS_FW_ERROR, &trans->status) && 3153 3004 !trans->cfg->mq_rx_supported && 3154 - trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_RB); 3005 + dump_mask & BIT(IWL_FW_ERROR_DUMP_RB); 3006 + 3007 + if (!dump_mask) 3008 + return NULL; 3155 3009 3156 3010 /* transport dump header */ 3157 3011 len = sizeof(*dump_data); ··· 3166 3014 /* FW monitor */ 3167 3015 monitor_len = iwl_trans_get_fw_monitor_len(trans, &len); 3168 3016 3169 - if (monitor_only) { 3170 - if (!(trans->dbg_dump_mask & 3171 - BIT(IWL_FW_ERROR_DUMP_FW_MONITOR))) 3172 - return NULL; 3173 - 3017 + if (dump_mask == BIT(IWL_FW_ERROR_DUMP_FW_MONITOR)) { 3174 3018 dump_data = vzalloc(len); 3175 3019 if (!dump_data) 3176 3020 return NULL; ··· 3179 3031 } 3180 3032 3181 3033 /* CSR registers */ 3182 - if (trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_CSR)) 3034 + if (dump_mask & BIT(IWL_FW_ERROR_DUMP_CSR)) 3183 3035 len += sizeof(*data) + IWL_CSR_TO_DUMP; 3184 3036 3185 3037 /* FH registers */ 3186 - if (trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_FH_REGS)) { 3038 + if (dump_mask & BIT(IWL_FW_ERROR_DUMP_FH_REGS)) { 3187 3039 if (trans->cfg->gen2) 3188 3040 len += sizeof(*data) + 3189 3041 (FH_MEM_UPPER_BOUND_GEN2 - ··· 3208 3060 } 3209 3061 3210 3062 /* Paged memory for gen2 HW */ 3211 - if (trans->cfg->gen2 && 3212 - trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING)) 3063 + if (trans->cfg->gen2 && dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING)) 3213 3064 for (i = 0; i < trans_pcie->init_dram.paging_cnt; i++) 3214 3065 len += sizeof(*data) + 3215 3066 sizeof(struct iwl_fw_error_dump_paging) + ··· 3221 3074 len = 0; 3222 3075 data = (void *)dump_data->data; 3223 3076 3224 - if (trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_TXCMD)) { 3077 + if (dump_mask & BIT(IWL_FW_ERROR_DUMP_TXCMD)) { 3225 3078 u16 tfd_size = trans_pcie->tfd_size; 3226 3079 3227 3080 data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD); ··· 3255 3108 data = iwl_fw_error_next_data(data); 3256 3109 } 3257 3110 3258 - if (trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_CSR)) 3111 + if (dump_mask & BIT(IWL_FW_ERROR_DUMP_CSR)) 3259 3112 len += iwl_trans_pcie_dump_csr(trans, &data); 3260 - if (trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_FH_REGS)) 3113 + if (dump_mask & BIT(IWL_FW_ERROR_DUMP_FH_REGS)) 3261 3114 len += iwl_trans_pcie_fh_regs_dump(trans, &data); 3262 3115 if (dump_rbs) 3263 3116 len += iwl_trans_pcie_dump_rbs(trans, &data, num_rbs); 3264 3117 3265 3118 /* Paged memory for gen2 HW */ 3266 - if (trans->cfg->gen2 && 3267 - trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING)) { 3119 + if (trans->cfg->gen2 && dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING)) { 3268 3120 for (i = 0; i < trans_pcie->init_dram.paging_cnt; i++) { 3269 3121 struct iwl_fw_error_dump_paging *paging; 3270 3122 dma_addr_t addr = ··· 3283 3137 len += sizeof(*data) + sizeof(*paging) + page_len; 3284 3138 } 3285 3139 } 3286 - if (trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_FW_MONITOR)) 3140 + if (dump_mask & BIT(IWL_FW_ERROR_DUMP_FW_MONITOR)) 3287 3141 len += iwl_trans_pcie_dump_monitor(trans, &data, monitor_len); 3288 3142 3289 3143 dump_data->len = len; ··· 3360 3214 3361 3215 .freeze_txq_timer = iwl_trans_pcie_freeze_txq_timer, 3362 3216 .block_txq_ptrs = iwl_trans_pcie_block_txq_ptrs, 3217 + #ifdef CONFIG_IWLWIFI_DEBUGFS 3218 + .debugfs_cleanup = iwl_trans_pcie_debugfs_cleanup, 3219 + #endif 3363 3220 }; 3364 3221 3365 3222 static const struct iwl_trans_ops trans_ops_pcie_gen2 = { ··· 3382 3233 .txq_free = iwl_trans_pcie_dyn_txq_free, 3383 3234 .wait_txq_empty = iwl_trans_pcie_wait_txq_empty, 3384 3235 .rxq_dma_data = iwl_trans_pcie_rxq_dma_data, 3236 + #ifdef CONFIG_IWLWIFI_DEBUGFS 3237 + .debugfs_cleanup = iwl_trans_pcie_debugfs_cleanup, 3238 + #endif 3385 3239 }; 3386 3240 3387 3241 struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, ··· 3556 3404 #if IS_ENABLED(CONFIG_IWLMVM) 3557 3405 trans->hw_rf_id = iwl_read32(trans, CSR_HW_RF_ID); 3558 3406 3559 - if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == 3560 - CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) { 3407 + if (cfg == &iwl22000_2ax_cfg_hr) { 3408 + if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == 3409 + CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) { 3410 + trans->cfg = &iwl22000_2ax_cfg_hr; 3411 + } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == 3412 + CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF)) { 3413 + trans->cfg = &iwl22000_2ax_cfg_jf; 3414 + } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == 3415 + CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HRCDB)) { 3416 + IWL_ERR(trans, "RF ID HRCDB is not supported\n"); 3417 + ret = -EINVAL; 3418 + goto out_no_pci; 3419 + } else { 3420 + IWL_ERR(trans, "Unrecognized RF ID 0x%08x\n", 3421 + CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id)); 3422 + ret = -EINVAL; 3423 + goto out_no_pci; 3424 + } 3425 + } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == 3426 + CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) { 3561 3427 u32 hw_status; 3562 3428 3563 3429 hw_status = iwl_read_prph(trans, UMAG_GEN_HW_STATUS); ··· 3635 3465 #else 3636 3466 trans->runtime_pm_mode = IWL_PLAT_PM_MODE_DISABLED; 3637 3467 #endif /* CONFIG_IWLWIFI_PCIE_RTPM */ 3468 + 3469 + #ifdef CONFIG_IWLWIFI_DEBUGFS 3470 + trans_pcie->fw_mon_data.state = IWL_FW_MON_DBGFS_STATE_CLOSED; 3471 + mutex_init(&trans_pcie->fw_mon_data.mutex); 3472 + #endif 3638 3473 3639 3474 return trans; 3640 3475