diff options
Diffstat (limited to 'sys/contrib/dev/iwlwifi/iwl-op-mode.h')
| -rw-r--r-- | sys/contrib/dev/iwlwifi/iwl-op-mode.h | 106 | 
1 files changed, 93 insertions, 13 deletions
| diff --git a/sys/contrib/dev/iwlwifi/iwl-op-mode.h b/sys/contrib/dev/iwlwifi/iwl-op-mode.h index 8ef5ed2db051..a146d0e399f2 100644 --- a/sys/contrib/dev/iwlwifi/iwl-op-mode.h +++ b/sys/contrib/dev/iwlwifi/iwl-op-mode.h @@ -1,6 +1,6 @@  /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */  /* - * Copyright (C) 2005-2014, 2018-2021, 2024 Intel Corporation + * Copyright (C) 2005-2014, 2018-2021, 2024-2025 Intel Corporation   * Copyright (C) 2013-2014 Intel Mobile Communications GmbH   * Copyright (C) 2015 Intel Deutschland GmbH   */ @@ -17,7 +17,7 @@ struct sk_buff;  struct iwl_device_cmd;  struct iwl_rx_cmd_buffer;  struct iwl_fw; -struct iwl_cfg; +struct iwl_rf_cfg;  /**   * DOC: Operational mode - what is it ? @@ -45,6 +45,63 @@ struct iwl_cfg;   */  /** + * enum iwl_fw_error_type - FW error types/sources + * @IWL_ERR_TYPE_IRQ: "normal" FW error through an IRQ + * @IWL_ERR_TYPE_NMI_FORCED: NMI was forced by driver + * @IWL_ERR_TYPE_RESET_HS_TIMEOUT: reset handshake timed out, + *	any debug collection must happen synchronously as + *	the device will be shut down + * @IWL_ERR_TYPE_CMD_QUEUE_FULL: command queue was full + * @IWL_ERR_TYPE_TOP_RESET_BY_BT: TOP reset initiated by BT + * @IWL_ERR_TYPE_TOP_FATAL_ERROR: TOP fatal error + * @IWL_ERR_TYPE_TOP_RESET_FAILED: TOP reset failed + * @IWL_ERR_TYPE_DEBUGFS: error/reset indication from debugfs + */ +enum iwl_fw_error_type { +	IWL_ERR_TYPE_IRQ, +	IWL_ERR_TYPE_NMI_FORCED, +	IWL_ERR_TYPE_RESET_HS_TIMEOUT, +	IWL_ERR_TYPE_CMD_QUEUE_FULL, +	IWL_ERR_TYPE_TOP_RESET_BY_BT, +	IWL_ERR_TYPE_TOP_FATAL_ERROR, +	IWL_ERR_TYPE_TOP_RESET_FAILED, +	IWL_ERR_TYPE_DEBUGFS, +}; + +/** + * enum iwl_fw_error_context - error dump context + * @IWL_ERR_CONTEXT_WORKER: regular from worker context, + *	opmode must acquire locks and must also check + *	for @IWL_ERR_CONTEXT_ABORT after acquiring locks + * @IWL_ERR_CONTEXT_FROM_OPMODE: context is in a call + *	originating from the opmode, e.g. while resetting + *	or stopping the device, so opmode must not acquire + *	any locks + * @IWL_ERR_CONTEXT_ABORT: after lock acquisition, indicates + *	that the dump already happened via another callback + *	(currently only while stopping the device) via the + *	@IWL_ERR_CONTEXT_FROM_OPMODE context, and this call + *	must be aborted + */ +enum iwl_fw_error_context { +	IWL_ERR_CONTEXT_WORKER, +	IWL_ERR_CONTEXT_FROM_OPMODE, +	IWL_ERR_CONTEXT_ABORT, +}; + +/** + * struct iwl_fw_error_dump_mode - error dump mode for callback + * @type: The reason for the dump, per &enum iwl_fw_error_type. + * @context: The context for the dump, may also indicate this + *	call needs to be skipped. This MUST be checked before + *	and after acquiring any locks in the op-mode! + */ +struct iwl_fw_error_dump_mode { +	enum iwl_fw_error_type type; +	enum iwl_fw_error_context context; +}; + +/**   * struct iwl_op_mode_ops - op_mode specific operations   *   * The op_mode exports its ops so that external components can start it and @@ -77,10 +134,11 @@ struct iwl_cfg;   *	reclaimed by the op_mode. This can happen when the driver is freed and   *	there are Tx packets pending in the transport layer.   *	Must be atomic - * @nic_error: error notification. Must be atomic and must be called with BH - *	disabled, unless the sync parameter is true. - * @cmd_queue_full: Called when the command queue gets full. Must be atomic and - *	called with BH disabled. + * @nic_error: error notification. Must be atomic, the op mode should handle + *	the error (e.g. abort notification waiters) and print the error if + *	applicable + * @dump_error: NIC error dump collection (can sleep, synchronous) + * @sw_reset: (maybe) initiate a software reset, return %true if started   * @nic_config: configure NIC, called before firmware is started.   *	May sleep   * @wimax_active: invoked when WiMax becomes active. May sleep @@ -89,10 +147,12 @@ struct iwl_cfg;   *	Op_mode needs to reset its internal state because the device did not   *	survive the system state transition. The firmware is no longer running,   *	etc... + * @dump: Op_mode needs to collect the firmware dump upon this handler + *	being called.   */  struct iwl_op_mode_ops {  	struct iwl_op_mode *(*start)(struct iwl_trans *trans, -				     const struct iwl_cfg *cfg, +				     const struct iwl_rf_cfg *cfg,  				     const struct iwl_fw *fw,  				     struct dentry *dbgfs_dir);  	void (*stop)(struct iwl_op_mode *op_mode); @@ -104,14 +164,19 @@ struct iwl_op_mode_ops {  	void (*queue_not_full)(struct iwl_op_mode *op_mode, int queue);  	bool (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state);  	void (*free_skb)(struct iwl_op_mode *op_mode, struct sk_buff *skb); -	void (*nic_error)(struct iwl_op_mode *op_mode, bool sync); -	void (*cmd_queue_full)(struct iwl_op_mode *op_mode); +	void (*nic_error)(struct iwl_op_mode *op_mode, +			  enum iwl_fw_error_type type); +	void (*dump_error)(struct iwl_op_mode *op_mode, +			   struct iwl_fw_error_dump_mode *mode); +	bool (*sw_reset)(struct iwl_op_mode *op_mode, +			 enum iwl_fw_error_type type);  	void (*nic_config)(struct iwl_op_mode *op_mode);  	void (*wimax_active)(struct iwl_op_mode *op_mode);  	void (*time_point)(struct iwl_op_mode *op_mode,  			   enum iwl_fw_ini_time_point tp_id,  			   union iwl_dbg_tlv_tp_data *tp_data);  	void (*device_powered_off)(struct iwl_op_mode *op_mode); +	void (*dump)(struct iwl_op_mode *op_mode);  };  int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops); @@ -177,14 +242,22 @@ static inline void iwl_op_mode_free_skb(struct iwl_op_mode *op_mode,  	op_mode->ops->free_skb(op_mode, skb);  } -static inline void iwl_op_mode_nic_error(struct iwl_op_mode *op_mode, bool sync) +static inline void iwl_op_mode_nic_error(struct iwl_op_mode *op_mode, +					 enum iwl_fw_error_type type)  { -	op_mode->ops->nic_error(op_mode, sync); +	op_mode->ops->nic_error(op_mode, type);  } -static inline void iwl_op_mode_cmd_queue_full(struct iwl_op_mode *op_mode) +static inline void iwl_op_mode_dump_error(struct iwl_op_mode *op_mode, +					  struct iwl_fw_error_dump_mode *mode)  { -	op_mode->ops->cmd_queue_full(op_mode); +	might_sleep(); + +	if (WARN_ON(mode->type == IWL_ERR_TYPE_TOP_RESET_BY_BT)) +		return; + +	if (op_mode->ops->dump_error) +		op_mode->ops->dump_error(op_mode, mode);  }  static inline void iwl_op_mode_nic_config(struct iwl_op_mode *op_mode) @@ -216,4 +289,11 @@ static inline void iwl_op_mode_device_powered_off(struct iwl_op_mode *op_mode)  	op_mode->ops->device_powered_off(op_mode);  } +static inline void iwl_op_mode_dump(struct iwl_op_mode *op_mode) +{ +	if (!op_mode || !op_mode->ops || !op_mode->ops->dump) +		return; +	op_mode->ops->dump(op_mode); +} +  #endif /* __iwl_op_mode_h__ */ | 
