device_reg_t __iomem *reg;
        uint8_t         abort_active;
        uint8_t         io_lock_on;
-       uint16_t        command;
+       uint16_t        command = 0;
        uint16_t        *iptr;
        uint16_t __iomem *optr;
        uint32_t        cnt;
                return QLA_FUNCTION_TIMEOUT;
        }
 
+       if (IS_QLA82XX(ha) && ha->flags.fw_hung) {
+               /* Setting Link-Down error */
+               mcp->mb[0] = MBS_LINK_DOWN_ERROR;
+               rval = QLA_FUNCTION_FAILED;
+               goto premature_exit;
+       }
+
        ha->flags.mbox_busy = 1;
        /* Save mailbox command for debug */
        ha->mcp = mcp;
                                DEBUG2_3_11(printk(KERN_INFO
                                    "%s(%ld): Pending Mailbox timeout. "
                                    "Exiting.\n", __func__, base_vha->host_no));
-                               return QLA_FUNCTION_TIMEOUT;
+                               rval = QLA_FUNCTION_TIMEOUT;
+                               goto premature_exit;
                        }
                        WRT_REG_DWORD(®->isp82.hint, HINT_MBX_INT_PENDING);
                } else if (IS_FWI2_CAPABLE(ha))
                                DEBUG2_3_11(printk(KERN_INFO
                                    "%s(%ld): Pending Mailbox timeout. "
                                    "Exiting.\n", __func__, base_vha->host_no));
-                               return QLA_FUNCTION_TIMEOUT;
+                               rval = QLA_FUNCTION_TIMEOUT;
+                               goto premature_exit;
                        }
                        WRT_REG_DWORD(®->isp82.hint, HINT_MBX_INT_PENDING);
                } else if (IS_FWI2_CAPABLE(ha))
                ha->flags.mbox_int = 0;
                clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
 
+               if (IS_QLA82XX(ha) && ha->flags.fw_hung) {
+                       ha->flags.mbox_busy = 0;
+                       /* Setting Link-Down error */
+                       mcp->mb[0] = MBS_LINK_DOWN_ERROR;
+                       ha->mcp = NULL;
+                       rval = QLA_FUNCTION_FAILED;
+                       goto premature_exit;
+               }
+
                if (ha->mailbox_out[0] != MBS_COMMAND_COMPLETE)
                        rval = QLA_FUNCTION_FAILED;
 
                        DEBUG2_3_11(printk("%s(%ld): timeout schedule "
                        "isp_abort_needed.\n", __func__,
                        base_vha->host_no));
-                       qla_printk(KERN_WARNING, ha,
-                           "Mailbox command timeout occurred. Scheduling ISP "
-                           "abort. eeh_busy: 0x%x\n", ha->flags.eeh_busy);
-                       set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);
-                       qla2xxx_wake_dpc(vha);
+
+                       if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) &&
+                           !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) &&
+                           !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
+
+                               qla_printk(KERN_WARNING, ha,
+                                   "Mailbox command timeout occured. "
+                                   "Scheduling ISP " "abort. eeh_busy: 0x%x\n",
+                                   ha->flags.eeh_busy);
+                               set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+                               qla2xxx_wake_dpc(vha);
+                       }
                } else if (!abort_active) {
                        /* call abort directly since we are in the DPC thread */
                        DEBUG(printk("%s(%ld): timeout calling abort_isp\n",
                            __func__, base_vha->host_no));
                        DEBUG2_3_11(printk("%s(%ld): timeout calling "
                            "abort_isp\n", __func__, base_vha->host_no));
-                       qla_printk(KERN_WARNING, ha,
-                           "Mailbox command timeout occurred. Issuing ISP "
-                           "abort.\n");
-
-                       set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
-                       clear_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);
-                       if (ha->isp_ops->abort_isp(base_vha)) {
-                               /* Failed. retry later. */
-                               set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);
+
+                       if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) &&
+                           !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) &&
+                           !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
+
+                               qla_printk(KERN_WARNING, ha,
+                                   "Mailbox command timeout occured. "
+                                   "Issuing ISP abort.\n");
+
+                               set_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
+                               clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+                               if (ha->isp_ops->abort_isp(vha)) {
+                                       /* Failed. retry later. */
+                                       set_bit(ISP_ABORT_NEEDED,
+                                           &vha->dpc_flags);
+                               }
+                               clear_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
+                               DEBUG(printk("%s(%ld): finished abort_isp\n",
+                                   __func__, vha->host_no));
+                               DEBUG2_3_11(printk(
+                                   "%s(%ld): finished abort_isp\n",
+                                   __func__, vha->host_no));
                        }
-                       clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
-                       DEBUG(printk("%s(%ld): finished abort_isp\n", __func__,
-                           base_vha->host_no));
-                       DEBUG2_3_11(printk("%s(%ld): finished abort_isp\n",
-                           __func__, base_vha->host_no));
                }
        }
 
+premature_exit:
        /* Allow next mbx cmd to come in. */
        complete(&ha->mbx_cmd_comp);
 
 
                                set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
                        }
                        qla2xxx_wake_dpc(vha);
+                       if (ha->flags.mbox_busy) {
+                               ha->flags.fw_hung = 1;
+                               ha->flags.mbox_int = 1;
+                               DEBUG2(qla_printk(KERN_ERR, ha,
+                                   "Due to fw hung, doing premature "
+                                   "completion of mbx command\n"));
+                               complete(&ha->mbx_intr_comp);
+                       }
                }
        }
        vha->fw_heartbeat_counter = fw_heartbeat_counter;
                                "%s(): Adapter reset needed!\n", __func__);
                        set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
                        qla2xxx_wake_dpc(vha);
+                       if (ha->flags.mbox_busy) {
+                               ha->flags.fw_hung = 1;
+                               ha->flags.mbox_int = 1;
+                               DEBUG2(qla_printk(KERN_ERR, ha,
+                                   "Need reset, doing premature "
+                                   "completion of mbx command\n"));
+                               complete(&ha->mbx_intr_comp);
+                       }
                } else {
                        qla82xx_check_fw_alive(vha);
                }
        qla82xx_clear_rst_ready(ha);
        qla82xx_idc_unlock(ha);
 
-       if (rval == QLA_SUCCESS)
+       if (rval == QLA_SUCCESS) {
+               ha->flags.fw_hung = 0;
                qla82xx_restart_isp(vha);
+       }
 
        if (rval) {
                vha->flags.online = 1;