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 | } |
