iwlwifi: uCode Alive notification with timeout

Wait for REPLY_ALIVE notification from init and runtime uCode.
based on the type of REPLY_ALIVE, different status bit will be set to
wake up the queue:
STATUS_INIT_UCODE_ALIVE for init uCode
STATUS_RT_UCODE_ALIVE for runtime uCode.

If timeout, attempt to download the failing uCode image again. This can
only be done for the init ucode images of all iwlagn devices and the
runtime ucode image of the 5000 series and up. If there is a problem
with the 4965 runtime ucode coming up we restart the interface and thus
trigger a new download of the init ucode also.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 6b874da..f61f653a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -533,12 +533,16 @@
 
 	if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
 		IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
+		set_bit(STATUS_INIT_UCODE_ALIVE, &priv->status);
+		wake_up_interruptible(&priv->wait_command_queue);
 		memcpy(&priv->card_alive_init,
 		       &pkt->u.alive_frame,
 		       sizeof(struct iwl_init_alive_resp));
 		pwork = &priv->init_alive_start;
 	} else {
 		IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
+		set_bit(STATUS_RT_UCODE_ALIVE, &priv->status);
+		wake_up_interruptible(&priv->wait_command_queue);
 		memcpy(&priv->card_alive, &pkt->u.alive_frame,
 		       sizeof(struct iwl_alive_resp));
 		pwork = &priv->alive_start;
@@ -1782,6 +1786,7 @@
 {
 	int i;
 	int ret;
+	unsigned long status;
 
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
 		IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
@@ -1859,6 +1864,51 @@
 		/* start card; "initialize" will load runtime ucode */
 		iwl_nic_start(priv);
 
+		/* Just finish download Init or Runtime uCode image to device
+		 * now we wait here for uCode send REPLY_ALIVE notification
+		 * to indicate uCode is ready.
+		 * 1) For Init uCode image, all iwlagn devices should wait here
+		 * on STATUS_INIT_UCODE_ALIVE status bit; if timeout before
+		 * receive the REPLY_ALIVE notification, go back and try to
+		 * download the Init uCode image again.
+		 * 2) For Runtime uCode image, all iwlagn devices except 4965
+		 * wait here on STATUS_RT_UCODE_ALIVE status bit; if
+		 * timeout before receive the REPLY_ALIVE notification, go back
+		 * and download the Runtime uCode image again.
+		 * 3) For 4965 Runtime uCode, it will not go through this path,
+		 * need to wait for STATUS_RT_UCODE_ALIVE status bit in
+		 * iwl4965_init_alive_start() function; if timeout, need to
+		 * restart and download Init uCode image.
+		 */
+		if (priv->ucode_type == UCODE_INIT)
+			status = STATUS_INIT_UCODE_ALIVE;
+		else
+			status = STATUS_RT_UCODE_ALIVE;
+		if (test_bit(status, &priv->status)) {
+			IWL_WARN(priv,
+				"%s uCode already alive? "
+				"Waiting for alive anyway\n",
+				(status == STATUS_INIT_UCODE_ALIVE)
+				? "INIT" : "Runtime");
+			clear_bit(status, &priv->status);
+		}
+		ret = wait_event_interruptible_timeout(
+				priv->wait_command_queue,
+				test_bit(status, &priv->status),
+				UCODE_ALIVE_TIMEOUT);
+		if (!ret) {
+			if (!test_bit(status, &priv->status)) {
+				priv->ucode_type =
+					(status == STATUS_INIT_UCODE_ALIVE)
+					? UCODE_NONE : UCODE_INIT;
+				IWL_ERR(priv,
+					"%s timeout after %dms\n",
+					(status == STATUS_INIT_UCODE_ALIVE)
+					? "INIT" : "Runtime",
+					jiffies_to_msecs(UCODE_ALIVE_TIMEOUT));
+				continue;
+			}
+		}
 		IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n");
 
 		return 0;