aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDeepak Ukey <deepak.ukey@microchip.com>2018-09-11 04:48:04 -0400
committerMartin K. Petersen <martin.petersen@oracle.com>2018-09-11 21:14:38 -0400
commit72349b62a571effd6faadd0600b8e657dd87afbf (patch)
treeebf719ebe39db294f399abefc2cc8272d5795c97
parent76cb25b058034d37244be6aca97a2ad52a5fbcad (diff)
scsi: pm80xx: Fixed system hang issue during kexec boot
When the firmware is not responding, execution of kexec boot causes a system hang. When firmware assertion happened, driver get notified with interrupt vector updated in MPI configuration table. Then, the driver will read scratchpad register and set controller_fatal_error flag to true. Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com> Signed-off-by: Viswas G <Viswas.G@microchip.com> Acked-by: Jack Wang <jinpu.wang@profitbricks.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/pm8001/pm8001_hwi.c6
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.c7
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.h1
-rw-r--r--drivers/scsi/pm8001/pm80xx_hwi.c80
-rw-r--r--drivers/scsi/pm8001/pm80xx_hwi.h3
5 files changed, 91 insertions, 6 deletions
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index a14bf50a76d7..e37ab9789ba6 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1479,6 +1479,12 @@ u32 pm8001_mpi_msg_consume(struct pm8001_hba_info *pm8001_ha,
1479 } else { 1479 } else {
1480 u32 producer_index; 1480 u32 producer_index;
1481 void *pi_virt = circularQ->pi_virt; 1481 void *pi_virt = circularQ->pi_virt;
1482 /* spurious interrupt during setup if
1483 * kexec-ing and driver doing a doorbell access
1484 * with the pre-kexec oq interrupt setup
1485 */
1486 if (!pi_virt)
1487 break;
1482 /* Update the producer index from SPC */ 1488 /* Update the producer index from SPC */
1483 producer_index = pm8001_read_32(pi_virt); 1489 producer_index = pm8001_read_32(pi_virt);
1484 circularQ->producer_index = cpu_to_le32(producer_index); 1490 circularQ->producer_index = cpu_to_le32(producer_index);
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index e063faad66f5..b1e7d2699311 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -396,6 +396,13 @@ static int pm8001_task_exec(struct sas_task *task,
396 return 0; 396 return 0;
397 } 397 }
398 pm8001_ha = pm8001_find_ha_by_dev(task->dev); 398 pm8001_ha = pm8001_find_ha_by_dev(task->dev);
399 if (pm8001_ha->controller_fatal_error) {
400 struct task_status_struct *ts = &t->task_status;
401
402 ts->resp = SAS_TASK_UNDELIVERED;
403 t->task_done(t);
404 return 0;
405 }
399 PM8001_IO_DBG(pm8001_ha, pm8001_printk("pm8001_task_exec device \n ")); 406 PM8001_IO_DBG(pm8001_ha, pm8001_printk("pm8001_task_exec device \n "));
400 spin_lock_irqsave(&pm8001_ha->lock, flags); 407 spin_lock_irqsave(&pm8001_ha->lock, flags);
401 do { 408 do {
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 80b4dd6df0c2..1816e351071f 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -538,6 +538,7 @@ struct pm8001_hba_info {
538 u32 logging_level; 538 u32 logging_level;
539 u32 fw_status; 539 u32 fw_status;
540 u32 smp_exp_mode; 540 u32 smp_exp_mode;
541 bool controller_fatal_error;
541 const struct firmware *fw_image; 542 const struct firmware *fw_image;
542 struct isr_param irq_vector[PM8001_MAX_MSIX_VEC]; 543 struct isr_param irq_vector[PM8001_MAX_MSIX_VEC];
543 u32 reset_in_progress; 544 u32 reset_in_progress;
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 91ff6a44e9d9..b641875b8ad7 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -577,6 +577,9 @@ static void update_main_config_table(struct pm8001_hba_info *pm8001_ha)
577 pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_size); 577 pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_size);
578 pm8001_mw32(address, MAIN_PCS_EVENT_LOG_OPTION, 578 pm8001_mw32(address, MAIN_PCS_EVENT_LOG_OPTION,
579 pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity); 579 pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity);
580 /* Update Fatal error interrupt vector */
581 pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt |=
582 ((pm8001_ha->number_of_intr - 1) << 8);
580 pm8001_mw32(address, MAIN_FATAL_ERROR_INTERRUPT, 583 pm8001_mw32(address, MAIN_FATAL_ERROR_INTERRUPT,
581 pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt); 584 pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt);
582 pm8001_mw32(address, MAIN_EVENT_CRC_CHECK, 585 pm8001_mw32(address, MAIN_EVENT_CRC_CHECK,
@@ -1110,6 +1113,9 @@ static int pm80xx_chip_init(struct pm8001_hba_info *pm8001_ha)
1110 return -EBUSY; 1113 return -EBUSY;
1111 } 1114 }
1112 1115
1116 /* Initialize the controller fatal error flag */
1117 pm8001_ha->controller_fatal_error = false;
1118
1113 /* Initialize pci space address eg: mpi offset */ 1119 /* Initialize pci space address eg: mpi offset */
1114 init_pci_device_addresses(pm8001_ha); 1120 init_pci_device_addresses(pm8001_ha);
1115 init_default_table_values(pm8001_ha); 1121 init_default_table_values(pm8001_ha);
@@ -1218,13 +1224,17 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha)
1218 u32 bootloader_state; 1224 u32 bootloader_state;
1219 u32 ibutton0, ibutton1; 1225 u32 ibutton0, ibutton1;
1220 1226
1221 /* Check if MPI is in ready state to reset */ 1227 /* Process MPI table uninitialization only if FW is ready */
1222 if (mpi_uninit_check(pm8001_ha) != 0) { 1228 if (!pm8001_ha->controller_fatal_error) {
1223 PM8001_FAIL_DBG(pm8001_ha, 1229 /* Check if MPI is in ready state to reset */
1224 pm8001_printk("MPI state is not ready\n")); 1230 if (mpi_uninit_check(pm8001_ha) != 0) {
1225 return -1; 1231 regval = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
1232 PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
1233 "MPI state is not ready scratch1 :0x%x\n",
1234 regval));
1235 return -1;
1236 }
1226 } 1237 }
1227
1228 /* checked for reset register normal state; 0x0 */ 1238 /* checked for reset register normal state; 0x0 */
1229 regval = pm8001_cr32(pm8001_ha, 0, SPC_REG_SOFT_RESET); 1239 regval = pm8001_cr32(pm8001_ha, 0, SPC_REG_SOFT_RESET);
1230 PM8001_INIT_DBG(pm8001_ha, 1240 PM8001_INIT_DBG(pm8001_ha,
@@ -3754,6 +3764,46 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
3754 } 3764 }
3755} 3765}
3756 3766
3767static void print_scratchpad_registers(struct pm8001_hba_info *pm8001_ha)
3768{
3769 PM8001_FAIL_DBG(pm8001_ha,
3770 pm8001_printk("MSGU_SCRATCH_PAD_0: 0x%x\n",
3771 pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0)));
3772 PM8001_FAIL_DBG(pm8001_ha,
3773 pm8001_printk("MSGU_SCRATCH_PAD_1:0x%x\n",
3774 pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1)));
3775 PM8001_FAIL_DBG(pm8001_ha,
3776 pm8001_printk("MSGU_SCRATCH_PAD_2: 0x%x\n",
3777 pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2)));
3778 PM8001_FAIL_DBG(pm8001_ha,
3779 pm8001_printk("MSGU_SCRATCH_PAD_3: 0x%x\n",
3780 pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3)));
3781 PM8001_FAIL_DBG(pm8001_ha,
3782 pm8001_printk("MSGU_HOST_SCRATCH_PAD_0: 0x%x\n",
3783 pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_0)));
3784 PM8001_FAIL_DBG(pm8001_ha,
3785 pm8001_printk("MSGU_HOST_SCRATCH_PAD_1: 0x%x\n",
3786 pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_1)));
3787 PM8001_FAIL_DBG(pm8001_ha,
3788 pm8001_printk("MSGU_HOST_SCRATCH_PAD_2: 0x%x\n",
3789 pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_2)));
3790 PM8001_FAIL_DBG(pm8001_ha,
3791 pm8001_printk("MSGU_HOST_SCRATCH_PAD_3: 0x%x\n",
3792 pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_3)));
3793 PM8001_FAIL_DBG(pm8001_ha,
3794 pm8001_printk("MSGU_HOST_SCRATCH_PAD_4: 0x%x\n",
3795 pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_4)));
3796 PM8001_FAIL_DBG(pm8001_ha,
3797 pm8001_printk("MSGU_HOST_SCRATCH_PAD_5: 0x%x\n",
3798 pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_5)));
3799 PM8001_FAIL_DBG(pm8001_ha,
3800 pm8001_printk("MSGU_RSVD_SCRATCH_PAD_0: 0x%x\n",
3801 pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_6)));
3802 PM8001_FAIL_DBG(pm8001_ha,
3803 pm8001_printk("MSGU_RSVD_SCRATCH_PAD_1: 0x%x\n",
3804 pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_7)));
3805}
3806
3757static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec) 3807static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec)
3758{ 3808{
3759 struct outbound_queue_table *circularQ; 3809 struct outbound_queue_table *circularQ;
@@ -3761,10 +3811,28 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec)
3761 u8 uninitialized_var(bc); 3811 u8 uninitialized_var(bc);
3762 u32 ret = MPI_IO_STATUS_FAIL; 3812 u32 ret = MPI_IO_STATUS_FAIL;
3763 unsigned long flags; 3813 unsigned long flags;
3814 u32 regval;
3764 3815
3816 if (vec == (pm8001_ha->number_of_intr - 1)) {
3817 regval = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
3818 if ((regval & SCRATCH_PAD_MIPSALL_READY) !=
3819 SCRATCH_PAD_MIPSALL_READY) {
3820 pm8001_ha->controller_fatal_error = true;
3821 PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
3822 "Firmware Fatal error! Regval:0x%x\n", regval));
3823 print_scratchpad_registers(pm8001_ha);
3824 return ret;
3825 }
3826 }
3765 spin_lock_irqsave(&pm8001_ha->lock, flags); 3827 spin_lock_irqsave(&pm8001_ha->lock, flags);
3766 circularQ = &pm8001_ha->outbnd_q_tbl[vec]; 3828 circularQ = &pm8001_ha->outbnd_q_tbl[vec];
3767 do { 3829 do {
3830 /* spurious interrupt during setup if kexec-ing and
3831 * driver doing a doorbell access w/ the pre-kexec oq
3832 * interrupt setup.
3833 */
3834 if (!circularQ->pi_virt)
3835 break;
3768 ret = pm8001_mpi_msg_consume(pm8001_ha, circularQ, &pMsg1, &bc); 3836 ret = pm8001_mpi_msg_consume(pm8001_ha, circularQ, &pMsg1, &bc);
3769 if (MPI_IO_STATUS_SUCCESS == ret) { 3837 if (MPI_IO_STATUS_SUCCESS == ret) {
3770 /* process the outbound message */ 3838 /* process the outbound message */
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index dead05a55aab..84d7426441bf 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -1386,6 +1386,9 @@ typedef struct SASProtocolTimerConfig SASProtocolTimerConfig_t;
1386#define SCRATCH_PAD_BOOT_LOAD_SUCCESS 0x0 1386#define SCRATCH_PAD_BOOT_LOAD_SUCCESS 0x0
1387#define SCRATCH_PAD_IOP0_READY 0xC00 1387#define SCRATCH_PAD_IOP0_READY 0xC00
1388#define SCRATCH_PAD_IOP1_READY 0x3000 1388#define SCRATCH_PAD_IOP1_READY 0x3000
1389#define SCRATCH_PAD_MIPSALL_READY (SCRATCH_PAD_IOP1_READY | \
1390 SCRATCH_PAD_IOP0_READY | \
1391 SCRATCH_PAD_RAAE_READY)
1389 1392
1390/* boot loader state */ 1393/* boot loader state */
1391#define SCRATCH_PAD1_BOOTSTATE_MASK 0x70 /* Bit 4-6 */ 1394#define SCRATCH_PAD1_BOOTSTATE_MASK 0x70 /* Bit 4-6 */