diff options
Diffstat (limited to 'drivers/scsi/pm8001/pm80xx_hwi.c')
-rw-r--r-- | drivers/scsi/pm8001/pm80xx_hwi.c | 119 |
1 files changed, 94 insertions, 25 deletions
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 42f0405601ad..63e4f7d34d6c 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) 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, @@ -2123,7 +2133,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) sata_resp = &psataPayload->sata_resp[0]; resp = (struct ata_task_resp *)ts->buf; if (t->ata_task.dma_xfer == 0 && - t->data_dir == PCI_DMA_FROMDEVICE) { + t->data_dir == DMA_FROM_DEVICE) { len = sizeof(struct pio_setup_fis); PM8001_IO_DBG(pm8001_ha, pm8001_printk("PIO read len = %d\n", len)); @@ -3118,8 +3128,9 @@ static int mpi_phy_start_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_printk("phy start resp status:0x%x, phyid:0x%x\n", status, phy_id)); if (status == 0) { - phy->phy_state = 1; - if (pm8001_ha->flags == PM8001F_RUN_TIME) + phy->phy_state = PHY_LINK_DOWN; + if (pm8001_ha->flags == PM8001F_RUN_TIME && + phy->enable_completion != NULL) complete(phy->enable_completion); } return 0; @@ -3211,7 +3222,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) return 0; } phy->phy_attached = 0; - phy->phy_state = 0; + phy->phy_state = PHY_LINK_DISABLE; break; case HW_EVENT_PORT_INVALID: PM8001_MSG_DBG(pm8001_ha, @@ -3384,13 +3395,14 @@ static int mpi_phy_stop_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) u32 status = le32_to_cpu(pPayload->status); u32 phyid = - le32_to_cpu(pPayload->phyid); + le32_to_cpu(pPayload->phyid) & 0xFF; struct pm8001_phy *phy = &pm8001_ha->phy[phyid]; PM8001_MSG_DBG(pm8001_ha, pm8001_printk("phy:0x%x status:0x%x\n", phyid, status)); - if (status == 0) - phy->phy_state = 0; + if (status == PHY_STOP_SUCCESS || + status == PHY_STOP_ERR_DEVICE_ATTACHED) + phy->phy_state = PHY_LINK_DISABLE; return 0; } @@ -3752,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; @@ -3759,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 */ @@ -3785,12 +3855,12 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec) return ret; } -/* PCI_DMA_... to our direction translation. */ +/* DMA_... to our direction translation. */ static const u8 data_dir_flags[] = { - [PCI_DMA_BIDIRECTIONAL] = DATA_DIR_BYRECIPIENT,/* UNSPECIFIED */ - [PCI_DMA_TODEVICE] = DATA_DIR_OUT,/* OUTBOUND */ - [PCI_DMA_FROMDEVICE] = DATA_DIR_IN,/* INBOUND */ - [PCI_DMA_NONE] = DATA_DIR_NONE,/* NO TRANSFER */ + [DMA_BIDIRECTIONAL] = DATA_DIR_BYRECIPIENT, /* UNSPECIFIED */ + [DMA_TO_DEVICE] = DATA_DIR_OUT, /* OUTBOUND */ + [DMA_FROM_DEVICE] = DATA_DIR_IN, /* INBOUND */ + [DMA_NONE] = DATA_DIR_NONE, /* NO TRANSFER */ }; static void build_smp_cmd(u32 deviceID, __le32 hTag, @@ -3832,13 +3902,13 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, * DMA-map SMP request, response buffers */ sg_req = &task->smp_task.smp_req; - elem = dma_map_sg(pm8001_ha->dev, sg_req, 1, PCI_DMA_TODEVICE); + elem = dma_map_sg(pm8001_ha->dev, sg_req, 1, DMA_TO_DEVICE); if (!elem) return -ENOMEM; req_len = sg_dma_len(sg_req); sg_resp = &task->smp_task.smp_resp; - elem = dma_map_sg(pm8001_ha->dev, sg_resp, 1, PCI_DMA_FROMDEVICE); + elem = dma_map_sg(pm8001_ha->dev, sg_resp, 1, DMA_FROM_DEVICE); if (!elem) { rc = -ENOMEM; goto err_out; @@ -3929,10 +3999,10 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, err_out_2: dma_unmap_sg(pm8001_ha->dev, &ccb->task->smp_task.smp_resp, 1, - PCI_DMA_FROMDEVICE); + DMA_FROM_DEVICE); err_out: dma_unmap_sg(pm8001_ha->dev, &ccb->task->smp_task.smp_req, 1, - PCI_DMA_TODEVICE); + DMA_TO_DEVICE); return rc; } @@ -4156,7 +4226,7 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, q_index = (u32) (pm8001_ha_dev->id & 0x00ffffff) % PM8001_MAX_INB_NUM; circularQ = &pm8001_ha->inbnd_q_tbl[q_index]; - if (task->data_dir == PCI_DMA_NONE) { + if (task->data_dir == DMA_NONE) { ATAP = 0x04; /* no data*/ PM8001_IO_DBG(pm8001_ha, pm8001_printk("no data\n")); } else if (likely(!task->ata_task.device_control_reg_update)) { @@ -4606,9 +4676,8 @@ void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha, void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha, u32 length, u8 *buf) { - u32 page_code, i; + u32 i; - page_code = SAS_PHY_ANALOG_SETTINGS_PAGE; for (i = 0; i < pm8001_ha->chip->n_phy; i++) { mpi_set_phy_profile_req(pm8001_ha, SAS_PHY_ANALOG_SETTINGS_PAGE, i, length, (u32 *)buf); |