|
@@ -577,6 +577,9 @@ static void update_main_config_table(struct pm8001_hba_info *pm8001_ha)
|
|
|
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,
|
|
@@ -1110,6 +1113,9 @@ static int pm80xx_chip_init(struct pm8001_hba_info *pm8001_ha)
|
|
|
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);
|
|
@@ -1218,13 +1224,17 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *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,
|
|
@@ -3754,6 +3764,46 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+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;
|
|
@@ -3761,10 +3811,28 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec)
|
|
|
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 */
|