summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2024-12-27 10:01:11 +0200
committerJohannes Berg <johannes.berg@intel.com>2025-01-13 15:26:39 +0100
commit7391b2a4f7dbb7be7dd763bc87506c10f570a8d3 (patch)
treebf93c69a81695b5d2aa97332c4b790da34f8ab90 /drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h
parent2d15d213e3d83108f1e29a80b230f9adb8b6e0c9 (diff)
wifi: iwlwifi: rework firmware error handling
In order to later add the ability to do deeper resets of the device when it crashes, first restructure the firmware error handling. Instead of having just a single nic_error() method that handles all, split it: - nic_error() just handles and prints the error itself, - dump_error() synchronously creates an error dump, and - sw_reset() will be called to request doing a SW reset. This changes the architecture so that the transport is now responsible for deciding how to do the reset, and therefore the handling of reprobe if error occurs during reconfig moves there, which necessitates adding a method there that notifies the transport that the recovery was completed. Actually introducing the model under which deeper resets can be done will be in future patches. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com> Link: https://patch.msgid.link/20241227095718.6d4f741ae907.I96a9243e7877808ed6d1bff6967c15d6c24882f0@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h53
1 files changed, 51 insertions, 2 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h
index 3b4085d3aad2..34eca1a568ea 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h
@@ -61,6 +61,39 @@ enum iwl_fw_error_type {
};
/**
+ * 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
@@ -93,8 +126,11 @@ enum iwl_fw_error_type {
* 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 type is IWL_ERR_TYPE_RESET_HS_TIMEOUT
+ * @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
@@ -120,6 +156,10 @@ struct iwl_op_mode_ops {
void (*free_skb)(struct iwl_op_mode *op_mode, struct sk_buff *skb);
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,
@@ -197,6 +237,15 @@ static inline void iwl_op_mode_nic_error(struct iwl_op_mode *op_mode,
op_mode->ops->nic_error(op_mode, type);
}
+static inline void iwl_op_mode_dump_error(struct iwl_op_mode *op_mode,
+ struct iwl_fw_error_dump_mode *mode)
+{
+ might_sleep();
+
+ 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)
{
might_sleep();