Blob Blame History Raw
Date: Fri, 19 Jul 2019 11:39:45 -0400
From: Jarod Wilson <jarod@redhat.com>
To: rhkernel-list@redhat.com
Cc: Jarod Wilson <jarod@redhat.com>
Subject: [RHEL8 PATCH 18/45] iwlwifi: fix load in rfkill flow for unified
 firmware

Bugzilla: http://bugzilla.redhat.com/1728992

commit b3500b472c880b5abe90ffd5c4a25aa736f906ad
Author: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Date:   Wed May 29 16:39:50 2019 +0300

    iwlwifi: fix load in rfkill flow for unified firmware

    When we have a single image (same firmware image for INIT and
    OPERATIONAL), we couldn't load the driver and register to the
    stack if we had hardware RF-Kill asserted.

    Fix this. This required a few changes:

    1) Run the firmware as part of the INIT phase even if its
       ucode_type is not IWL_UCODE_INIT.
    2) Send the commands that are sent to the unified image in
       INIT flow even in RF-Kill.
    3) Don't ask the transport to stop the hardware upon RF-Kill
       interrupt if the RF-Kill is asserted.
    4) Allow the RF-Kill interrupt to take us out of L1A so that
       the RF-Kill interrupt will be received by the host (to
       enable the radio).

    Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
    Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
    Signed-off-by: Kalle Valo <kvalo@codeaurora.org>

Signed-off-by: Jarod Wilson <jarod@redhat.com>
---
 drivers/net/wireless/intel/iwlwifi/mvm/fw.c   | 23 ++++++++++++++-----
 .../net/wireless/intel/iwlwifi/mvm/mac80211.c |  2 +-
 drivers/net/wireless/intel/iwlwifi/mvm/mvm.h  |  2 +-
 drivers/net/wireless/intel/iwlwifi/mvm/ops.c  | 17 ++++++++++----
 .../wireless/intel/iwlwifi/pcie/internal.h    |  2 +-
 5 files changed, 33 insertions(+), 13 deletions(-)

Index: src/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
===================================================================
--- src.orig/drivers/net/wireless/intel/iwlwifi/mvm/fw.c	2019-09-08 16:05:32.735990145 +0200
+++ src/drivers/net/wireless/intel/iwlwifi/mvm/fw.c	2019-09-11 11:39:11.178977764 +0200
@@ -311,6 +311,8 @@
 	int ret, i;
 	enum iwl_ucode_type old_type = mvm->fwrt.cur_fw_img;
 	static const u16 alive_cmd[] = { MVM_ALIVE };
+	bool run_in_rfkill =
+		ucode_type == IWL_UCODE_INIT || iwl_mvm_has_unified_ucode(mvm);
 
 	if (ucode_type == IWL_UCODE_REGULAR &&
 	    iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_START_FROM_ALIVE) &&
@@ -328,7 +330,12 @@
 				   alive_cmd, ARRAY_SIZE(alive_cmd),
 				   iwl_alive_fn, &alive_data);
 
-	ret = iwl_trans_start_fw(mvm->trans, fw, ucode_type == IWL_UCODE_INIT);
+	/*
+	 * We want to load the INIT firmware even in RFKILL
+	 * For the unified firmware case, the ucode_type is not
+	 * INIT, but we still need to run it.
+	 */
+	ret = iwl_trans_start_fw(mvm->trans, fw, run_in_rfkill);
 	if (ret) {
 		iwl_fw_set_current_image(&mvm->fwrt, old_type);
 		iwl_remove_notification(&mvm->notif_wait, &alive_wait);
@@ -436,7 +443,8 @@
 	 * commands
 	 */
 	ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(SYSTEM_GROUP,
-						INIT_EXTENDED_CFG_CMD), 0,
+						INIT_EXTENDED_CFG_CMD),
+				   CMD_SEND_IN_RFKILL,
 				   sizeof(init_cfg), &init_cfg);
 	if (ret) {
 		IWL_ERR(mvm, "Failed to run init config command: %d\n",
@@ -460,7 +468,8 @@
 	}
 
 	ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(REGULATORY_AND_NVM_GROUP,
-						NVM_ACCESS_COMPLETE), 0,
+						NVM_ACCESS_COMPLETE),
+				   CMD_SEND_IN_RFKILL,
 				   sizeof(nvm_complete), &nvm_complete);
 	if (ret) {
 		IWL_ERR(mvm, "Failed to run complete NVM access: %d\n",
@@ -485,6 +494,8 @@
 		}
 	}
 
+	mvm->rfkill_safe_init_done = true;
+
 	return 0;
 
 error:
@@ -529,7 +540,7 @@
 
 	lockdep_assert_held(&mvm->mutex);
 
-	if (WARN_ON_ONCE(mvm->calibrating))
+	if (WARN_ON_ONCE(mvm->rfkill_safe_init_done))
 		return 0;
 
 	iwl_init_notification_wait(&mvm->notif_wait,
@@ -579,7 +590,7 @@
 		goto remove_notif;
 	}
 
-	mvm->calibrating = true;
+	mvm->rfkill_safe_init_done = true;
 
 	/* Send TX valid antennas before triggering calibrations */
 	ret = iwl_send_tx_ant_cfg(mvm, iwl_mvm_get_valid_tx_ant(mvm));
@@ -615,7 +626,7 @@
 remove_notif:
 	iwl_remove_notification(&mvm->notif_wait, &calib_wait);
 out:
-	mvm->calibrating = false;
+	mvm->rfkill_safe_init_done = false;
 	if (iwlmvm_mod_params.init_dbg && !mvm->nvm_data) {
 		/* we want to debug INIT and we have no NVM - fake */
 		mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) +
Index: src/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
===================================================================
--- src.orig/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c	2019-09-08 16:05:35.487954714 +0200
+++ src/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c	2019-09-11 11:39:11.179977744 +0200
@@ -1048,7 +1048,7 @@
 
 	mvm->scan_status = 0;
 	mvm->ps_disabled = false;
-	mvm->calibrating = false;
+	mvm->rfkill_safe_init_done = false;
 
 	/* just in case one was running */
 	iwl_mvm_cleanup_roc_te(mvm);
Index: src/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
===================================================================
--- src.orig/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h	2019-09-11 11:38:55.198303534 +0200
+++ src/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h	2019-09-11 11:39:11.179977744 +0200
@@ -844,7 +844,7 @@
 	struct iwl_mvm_vif *bf_allowed_vif;
 
 	bool hw_registered;
-	bool calibrating;
+	bool rfkill_safe_init_done;
 	bool support_umac_log;
 
 	u32 ampdu_ref;
Index: src/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
===================================================================
--- src.orig/drivers/net/wireless/intel/iwlwifi/mvm/ops.c	2019-09-11 11:38:55.199303513 +0200
+++ src/drivers/net/wireless/intel/iwlwifi/mvm/ops.c	2019-09-11 11:39:11.180977724 +0200
@@ -1167,7 +1167,8 @@
 static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
 {
 	struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
-	bool calibrating = READ_ONCE(mvm->calibrating);
+	bool rfkill_safe_init_done = READ_ONCE(mvm->rfkill_safe_init_done);
+	bool unified = iwl_mvm_has_unified_ucode(mvm);
 
 	if (state)
 		set_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
@@ -1176,15 +1177,23 @@
 
 	iwl_mvm_set_rfkill_state(mvm);
 
-	/* iwl_run_init_mvm_ucode is waiting for results, abort it */
-	if (calibrating)
+	 /* iwl_run_init_mvm_ucode is waiting for results, abort it. */
+	if (rfkill_safe_init_done)
 		iwl_abort_notification_waits(&mvm->notif_wait);
 
 	/*
+	 * Don't ask the transport to stop the firmware. We'll do it
+	 * after cfg80211 takes us down.
+	 */
+	if (unified)
+		return false;
+
+	/*
 	 * Stop the device if we run OPERATIONAL firmware or if we are in the
 	 * middle of the calibrations.
 	 */
-	return state && (mvm->fwrt.cur_fw_img != IWL_UCODE_INIT || calibrating);
+	return state && (mvm->fwrt.cur_fw_img != IWL_UCODE_INIT ||
+			 rfkill_safe_init_done);
 }
 
 static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
Index: src/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
===================================================================
--- src.orig/drivers/net/wireless/intel/iwlwifi/pcie/internal.h	2019-06-27 14:54:04.143678216 +0200
+++ src/drivers/net/wireless/intel/iwlwifi/pcie/internal.h	2019-09-11 11:39:11.181977703 +0200
@@ -928,7 +928,7 @@
 					   MSIX_HW_INT_CAUSES_REG_RF_KILL);
 	}
 
-	if (trans->cfg->device_family == IWL_DEVICE_FAMILY_9000) {
+	if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_9000) {
 		/*
 		 * On 9000-series devices this bit isn't enabled by default, so
 		 * when we power down the device we need set the bit to allow it