diff options
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.c | 70 |
1 files changed, 69 insertions, 1 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 41ffc205724f..a8a2666831d3 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c | |||
@@ -728,6 +728,10 @@ static int | |||
728 | megasas_check_reset_gen2(struct megasas_instance *instance, | 728 | megasas_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 | ||
1575 | static void | ||
1576 | megasas_internal_reset_defer_cmds(struct megasas_instance *instance); | ||
1577 | |||
1578 | static void | ||
1579 | process_fw_state_change_wq(struct work_struct *work); | ||
1580 | |||
1581 | void 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 | } |