pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_size);
        pm8001_mw32(address, MAIN_PCS_EVENT_LOG_OPTION,
                pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity);
+       /* Update Fatal error interrupt vector */
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt |=
+                                       ((pm8001_ha->number_of_intr - 1) << 8);
        pm8001_mw32(address, MAIN_FATAL_ERROR_INTERRUPT,
                pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt);
        pm8001_mw32(address, MAIN_EVENT_CRC_CHECK,
                return -EBUSY;
        }
 
+       /* Initialize the controller fatal error flag */
+       pm8001_ha->controller_fatal_error = false;
+
        /* Initialize pci space address eg: mpi offset */
        init_pci_device_addresses(pm8001_ha);
        init_default_table_values(pm8001_ha);
        u32 bootloader_state;
        u32 ibutton0, ibutton1;
 
-       /* Check if MPI is in ready state to reset */
-       if (mpi_uninit_check(pm8001_ha) != 0) {
-               PM8001_FAIL_DBG(pm8001_ha,
-                       pm8001_printk("MPI state is not ready\n"));
-               return -1;
+       /* Process MPI table uninitialization only if FW is ready */
+       if (!pm8001_ha->controller_fatal_error) {
+               /* Check if MPI is in ready state to reset */
+               if (mpi_uninit_check(pm8001_ha) != 0) {
+                       regval = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
+                       PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+                               "MPI state is not ready scratch1 :0x%x\n",
+                               regval));
+                       return -1;
+               }
        }
-
        /* checked for reset register normal state; 0x0 */
        regval = pm8001_cr32(pm8001_ha, 0, SPC_REG_SOFT_RESET);
        PM8001_INIT_DBG(pm8001_ha,
        }
 }
 
+static void print_scratchpad_registers(struct pm8001_hba_info *pm8001_ha)
+{
+       PM8001_FAIL_DBG(pm8001_ha,
+               pm8001_printk("MSGU_SCRATCH_PAD_0: 0x%x\n",
+                       pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0)));
+       PM8001_FAIL_DBG(pm8001_ha,
+               pm8001_printk("MSGU_SCRATCH_PAD_1:0x%x\n",
+                       pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1)));
+       PM8001_FAIL_DBG(pm8001_ha,
+               pm8001_printk("MSGU_SCRATCH_PAD_2: 0x%x\n",
+                       pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2)));
+       PM8001_FAIL_DBG(pm8001_ha,
+               pm8001_printk("MSGU_SCRATCH_PAD_3: 0x%x\n",
+                       pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3)));
+       PM8001_FAIL_DBG(pm8001_ha,
+               pm8001_printk("MSGU_HOST_SCRATCH_PAD_0: 0x%x\n",
+                       pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_0)));
+       PM8001_FAIL_DBG(pm8001_ha,
+               pm8001_printk("MSGU_HOST_SCRATCH_PAD_1: 0x%x\n",
+                       pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_1)));
+       PM8001_FAIL_DBG(pm8001_ha,
+               pm8001_printk("MSGU_HOST_SCRATCH_PAD_2: 0x%x\n",
+                       pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_2)));
+       PM8001_FAIL_DBG(pm8001_ha,
+               pm8001_printk("MSGU_HOST_SCRATCH_PAD_3: 0x%x\n",
+                       pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_3)));
+       PM8001_FAIL_DBG(pm8001_ha,
+               pm8001_printk("MSGU_HOST_SCRATCH_PAD_4: 0x%x\n",
+                       pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_4)));
+       PM8001_FAIL_DBG(pm8001_ha,
+               pm8001_printk("MSGU_HOST_SCRATCH_PAD_5: 0x%x\n",
+                       pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_5)));
+       PM8001_FAIL_DBG(pm8001_ha,
+               pm8001_printk("MSGU_RSVD_SCRATCH_PAD_0: 0x%x\n",
+                       pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_6)));
+       PM8001_FAIL_DBG(pm8001_ha,
+               pm8001_printk("MSGU_RSVD_SCRATCH_PAD_1: 0x%x\n",
+                       pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_7)));
+}
+
 static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec)
 {
        struct outbound_queue_table *circularQ;
        u8 uninitialized_var(bc);
        u32 ret = MPI_IO_STATUS_FAIL;
        unsigned long flags;
+       u32 regval;
 
+       if (vec == (pm8001_ha->number_of_intr - 1)) {
+               regval = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
+               if ((regval & SCRATCH_PAD_MIPSALL_READY) !=
+                                       SCRATCH_PAD_MIPSALL_READY) {
+                       pm8001_ha->controller_fatal_error = true;
+                       PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+                               "Firmware Fatal error! Regval:0x%x\n", regval));
+                       print_scratchpad_registers(pm8001_ha);
+                       return ret;
+               }
+       }
        spin_lock_irqsave(&pm8001_ha->lock, flags);
        circularQ = &pm8001_ha->outbnd_q_tbl[vec];
        do {
+               /* spurious interrupt during setup if kexec-ing and
+                * driver doing a doorbell access w/ the pre-kexec oq
+                * interrupt setup.
+                */
+               if (!circularQ->pi_virt)
+                       break;
                ret = pm8001_mpi_msg_consume(pm8001_ha, circularQ, &pMsg1, &bc);
                if (MPI_IO_STATUS_SUCCESS == ret) {
                        /* process the outbound message */