[BUGFIX] iwlwifi: fw: add a workaround to secure boot failures

Add a workaround for secure boot failures which enables the driver
to retry loading the firmware 3 times before failure.

type=bugfix
bug=cq:MWG100247686
fixes=unknown

Change-Id: I982984420cc8d6845964f1c3f9f07f43d9049b0c
Signed-off-by: Oren Givon <oren.givon@intel.com>
Reviewed-on: https://git-amr-3.devtools.intel.com/gerrit/6990
Tested-by: ec ger unix iil jenkins <EC.GER.UNIX.IIL.JENKINS@INTEL.COM>
Reviewed-by: Grumbach, Emmanuel <emmanuel.grumbach@intel.com>
(cherry picked from commit 19d5831e69a539ee86548e50bab0d5efc9556a9f)
Reviewed-on: https://git-amr-3.devtools.intel.com/gerrit/7939
x-iwlwifi-stack-dev: 38a59b3f94710597fd57e4dcbbf08203f399aed7
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index 2cec40c..2c309b6 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -531,6 +531,7 @@
 	enum iwl_ucode_type old_type = mvm->cur_ucode;
 	static const u16 alive_cmd[] = { MVM_ALIVE };
 	struct iwl_sf_region st_fwrd_space;
+	unsigned int retries = 3;
 
 	if (ucode_type == IWL_UCODE_REGULAR &&
 	    iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_START_FROM_ALIVE))
@@ -542,29 +543,51 @@
 	mvm->cur_ucode = ucode_type;
 	mvm->ucode_loaded = false;
 
-	iwl_init_notification_wait(&mvm->notif_wait, &alive_wait,
-				   alive_cmd, ARRAY_SIZE(alive_cmd),
-				   iwl_alive_fn, &alive_data);
-
-	ret = iwl_trans_start_fw(mvm->trans, fw, ucode_type == IWL_UCODE_INIT);
-	if (ret) {
-		mvm->cur_ucode = old_type;
-		iwl_remove_notification(&mvm->notif_wait, &alive_wait);
-		return ret;
-	}
-
 	/*
-	 * Some things may run in the background now, but we
-	 * just wait for the ALIVE notification here.
+	 * A temporary workaround to a SecBoot issue:
+	 * If we fail to load the firmware due to a SecBoot issue,
+	 * retry to load the firmware. This workaround should be
+	 * removed once the SecBoot issue is fixed.
 	 */
-	ret = iwl_wait_notification(&mvm->notif_wait, &alive_wait,
-				    MVM_UCODE_ALIVE_TIMEOUT);
-	if (ret) {
-		if (mvm->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+	while (retries > 0) {
+		iwl_init_notification_wait(&mvm->notif_wait, &alive_wait,
+					   alive_cmd, ARRAY_SIZE(alive_cmd),
+					   iwl_alive_fn, &alive_data);
+
+		ret = iwl_trans_start_fw(mvm->trans, fw,
+					 ucode_type == IWL_UCODE_INIT);
+		if (ret) {
+			mvm->cur_ucode = old_type;
+			iwl_remove_notification(&mvm->notif_wait, &alive_wait);
+			return ret;
+		}
+
+		/*
+		 * Some things may run in the background now, but we
+		 * just wait for the ALIVE notification here.
+		 */
+		ret = iwl_wait_notification(&mvm->notif_wait, &alive_wait,
+					    MVM_UCODE_ALIVE_TIMEOUT);
+		if (!ret)
+			break;
+
+		if (mvm->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
 			IWL_ERR(mvm,
 				"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
 				iwl_read_prph(mvm->trans, SB_CPU_1_STATUS),
 				iwl_read_prph(mvm->trans, SB_CPU_2_STATUS));
+			retries--;
+			if (retries > 0) {
+				_iwl_trans_stop_device(mvm->trans, false);
+				ret = _iwl_trans_start_hw(mvm->trans, false);
+				if (ret) {
+					IWL_ERR(mvm,
+						"Failed to start hardware.\n");
+					return ret;
+				}
+				continue; /* retry to load the fw */
+			}
+		}
 		mvm->cur_ucode = old_type;
 		return ret;
 	}
diff --git a/versions b/versions
index 78ee3ce..bcae27e 100644
--- a/versions
+++ b/versions
@@ -2,5 +2,5 @@
 BACKPORTED_KERNEL_VERSION="(see git)"
 BACKPORTED_KERNEL_NAME="iwlwifi"
 BACKPORTS_BUILD_TSTAMP=__DATE__ \" \" __TIME__
-BACKPORTS_GIT_TRACKED="iwlwifi-stack-public:release/LinuxCore14:4627:a8d9a08b"
+BACKPORTS_GIT_TRACKED="iwlwifi-stack-public:release/LinuxCore14:4628:38a59b3f"
 BACKPORTS_BRANCH_TSTAMP="Aug 26 2015 10:38:56"