aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYang, Bo <Bo.Yang@lsi.com>2010-10-12 09:20:27 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-10-26 12:07:07 -0400
commit707e09bd867cee4cd0e5bff0a67513aa0232fcec (patch)
tree7d36a852947513a5e5eb13662d7d5bc859782011
parent1fd106851698e9a858d20ab0e0f0afd5e9ec9332 (diff)
[SCSI] megaraid_sas: Add three times Online controller reset
If fw didn't raise the interrupt with the fw state change to driver and fw goes to failure state, driver Will check the FW state in driver's timeout routine and issue the reset if need. Driver will do the OCR upto three times until kill adapter. Also driver will issue OCR before driver kill adapter even if fw in operational state. Signed-off-by Bo Yang <bo.yang@lsi.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c70
1 files changed, 69 insertions, 1 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 41ffc205724..a8a2666831d 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -728,6 +728,10 @@ static int
728megasas_check_reset_gen2(struct megasas_instance *instance, 728megasas_check_reset_gen2(struct megasas_instance *instance,
729 struct megasas_register_set __iomem *regs) 729 struct megasas_register_set __iomem *regs)
730{ 730{
731 if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
732 return 1;
733 }
734
731 return 0; 735 return 0;
732} 736}
733 737
@@ -940,6 +944,7 @@ megasas_make_sgl_skinny(struct megasas_instance *instance,
940 mfi_sgl->sge_skinny[i].length = sg_dma_len(os_sgl); 944 mfi_sgl->sge_skinny[i].length = sg_dma_len(os_sgl);
941 mfi_sgl->sge_skinny[i].phys_addr = 945 mfi_sgl->sge_skinny[i].phys_addr =
942 sg_dma_address(os_sgl); 946 sg_dma_address(os_sgl);
947 mfi_sgl->sge_skinny[i].flag = 0;
943 } 948 }
944 } 949 }
945 return sge_count; 950 return sge_count;
@@ -1567,6 +1572,28 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr)
1567 } 1572 }
1568} 1573}
1569 1574
1575static void
1576megasas_internal_reset_defer_cmds(struct megasas_instance *instance);
1577
1578static void
1579process_fw_state_change_wq(struct work_struct *work);
1580
1581void megasas_do_ocr(struct megasas_instance *instance)
1582{
1583 if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1064R) ||
1584 (instance->pdev->device == PCI_DEVICE_ID_DELL_PERC5) ||
1585 (instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR)) {
1586 *instance->consumer = MEGASAS_ADPRESET_INPROG_SIGN;
1587 }
1588 instance->instancet->disable_intr(instance->reg_set);
1589 instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT;
1590 instance->issuepend_done = 0;
1591
1592 atomic_set(&instance->fw_outstanding, 0);
1593 megasas_internal_reset_defer_cmds(instance);
1594 process_fw_state_change_wq(&instance->work_init);
1595}
1596
1570/** 1597/**
1571 * megasas_wait_for_outstanding - Wait for all outstanding cmds 1598 * megasas_wait_for_outstanding - Wait for all outstanding cmds
1572 * @instance: Adapter soft state 1599 * @instance: Adapter soft state
@@ -1584,6 +1611,8 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance)
1584 unsigned long flags; 1611 unsigned long flags;
1585 struct list_head clist_local; 1612 struct list_head clist_local;
1586 struct megasas_cmd *reset_cmd; 1613 struct megasas_cmd *reset_cmd;
1614 u32 fw_state;
1615 u8 kill_adapter_flag;
1587 1616
1588 spin_lock_irqsave(&instance->hba_lock, flags); 1617 spin_lock_irqsave(&instance->hba_lock, flags);
1589 adprecovery = instance->adprecovery; 1618 adprecovery = instance->adprecovery;
@@ -1669,7 +1698,45 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance)
1669 msleep(1000); 1698 msleep(1000);
1670 } 1699 }
1671 1700
1672 if (atomic_read(&instance->fw_outstanding)) { 1701 i = 0;
1702 kill_adapter_flag = 0;
1703 do {
1704 fw_state = instance->instancet->read_fw_status_reg(
1705 instance->reg_set) & MFI_STATE_MASK;
1706 if ((fw_state == MFI_STATE_FAULT) &&
1707 (instance->disableOnlineCtrlReset == 0)) {
1708 if (i == 3) {
1709 kill_adapter_flag = 2;
1710 break;
1711 }
1712 megasas_do_ocr(instance);
1713 kill_adapter_flag = 1;
1714
1715 /* wait for 1 secs to let FW finish the pending cmds */
1716 msleep(1000);
1717 }
1718 i++;
1719 } while (i <= 3);
1720
1721 if (atomic_read(&instance->fw_outstanding) &&
1722 !kill_adapter_flag) {
1723 if (instance->disableOnlineCtrlReset == 0) {
1724
1725 megasas_do_ocr(instance);
1726
1727 /* wait for 5 secs to let FW finish the pending cmds */
1728 for (i = 0; i < wait_time; i++) {
1729 int outstanding =
1730 atomic_read(&instance->fw_outstanding);
1731 if (!outstanding)
1732 return SUCCESS;
1733 msleep(1000);
1734 }
1735 }
1736 }
1737
1738 if (atomic_read(&instance->fw_outstanding) ||
1739 (kill_adapter_flag == 2)) {
1673 printk(KERN_NOTICE "megaraid_sas: pending cmds after reset\n"); 1740 printk(KERN_NOTICE "megaraid_sas: pending cmds after reset\n");
1674 /* 1741 /*
1675 * Send signal to FW to stop processing any pending cmds. 1742 * Send signal to FW to stop processing any pending cmds.
@@ -2679,6 +2746,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
2679 return -ENOMEM; 2746 return -ENOMEM;
2680 } 2747 }
2681 2748
2749 memset(cmd->frame, 0, total_sz);
2682 cmd->frame->io.context = cmd->index; 2750 cmd->frame->io.context = cmd->index;
2683 cmd->frame->io.pad_0 = 0; 2751 cmd->frame->io.pad_0 = 0;
2684 } 2752 }