diff options
author | adam radford <aradford@gmail.com> | 2014-03-10 05:51:56 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2014-03-15 13:19:21 -0400 |
commit | 229fe47cd046ef2d01c13298293cda9693811417 (patch) | |
tree | 5fbc96b8332d466ddc2f1a903314fb3419677f17 /drivers/scsi/megaraid | |
parent | 3d0c24cd9bedf5a0665d60c8219a0a84c05abeb3 (diff) |
[SCSI] megaraid_sas: Add Dell PowerEdge VRTX SR-IOV VF support
The following patch for megaraid_sas adds Dell PowerEdge VRTS SR-IOV VF
support (Device ID 0x002f).
This patch has some > 80 column lines that need to be left in place
for code readability purposes.
Signed-off-by: Adam Radford <aradford@gmail.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/megaraid')
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.h | 100 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_base.c | 634 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_fusion.c | 232 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_fusion.h | 3 |
4 files changed, 851 insertions, 118 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index a80e13ef9ffa..66be91249bfa 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h | |||
@@ -48,6 +48,7 @@ | |||
48 | #define PCI_DEVICE_ID_LSI_SAS0073SKINNY 0x0073 | 48 | #define PCI_DEVICE_ID_LSI_SAS0073SKINNY 0x0073 |
49 | #define PCI_DEVICE_ID_LSI_SAS0071SKINNY 0x0071 | 49 | #define PCI_DEVICE_ID_LSI_SAS0071SKINNY 0x0071 |
50 | #define PCI_DEVICE_ID_LSI_FUSION 0x005b | 50 | #define PCI_DEVICE_ID_LSI_FUSION 0x005b |
51 | #define PCI_DEVICE_ID_LSI_PLASMA 0x002f | ||
51 | #define PCI_DEVICE_ID_LSI_INVADER 0x005d | 52 | #define PCI_DEVICE_ID_LSI_INVADER 0x005d |
52 | #define PCI_DEVICE_ID_LSI_FURY 0x005f | 53 | #define PCI_DEVICE_ID_LSI_FURY 0x005f |
53 | 54 | ||
@@ -559,7 +560,8 @@ struct megasas_ctrl_info { | |||
559 | u8 PCIE:1; | 560 | u8 PCIE:1; |
560 | u8 iSCSI:1; | 561 | u8 iSCSI:1; |
561 | u8 SAS_3G:1; | 562 | u8 SAS_3G:1; |
562 | u8 reserved_0:4; | 563 | u8 SRIOV:1; |
564 | u8 reserved_0:3; | ||
563 | u8 reserved_1[6]; | 565 | u8 reserved_1[6]; |
564 | u8 port_count; | 566 | u8 port_count; |
565 | u64 port_addr[8]; | 567 | u64 port_addr[8]; |
@@ -839,7 +841,12 @@ struct megasas_ctrl_info { | |||
839 | 841 | ||
840 | struct { /*7A4h */ | 842 | struct { /*7A4h */ |
841 | #if defined(__BIG_ENDIAN_BITFIELD) | 843 | #if defined(__BIG_ENDIAN_BITFIELD) |
842 | u32 reserved:11; | 844 | u32 reserved:5; |
845 | u32 activePassive:2; | ||
846 | u32 supportConfigAutoBalance:1; | ||
847 | u32 mpio:1; | ||
848 | u32 supportDataLDonSSCArray:1; | ||
849 | u32 supportPointInTimeProgress:1; | ||
843 | u32 supportUnevenSpans:1; | 850 | u32 supportUnevenSpans:1; |
844 | u32 dedicatedHotSparesLimited:1; | 851 | u32 dedicatedHotSparesLimited:1; |
845 | u32 headlessMode:1; | 852 | u32 headlessMode:1; |
@@ -886,7 +893,12 @@ struct megasas_ctrl_info { | |||
886 | 893 | ||
887 | 894 | ||
888 | u32 supportUnevenSpans:1; | 895 | u32 supportUnevenSpans:1; |
889 | u32 reserved:11; | 896 | u32 supportPointInTimeProgress:1; |
897 | u32 supportDataLDonSSCArray:1; | ||
898 | u32 mpio:1; | ||
899 | u32 supportConfigAutoBalance:1; | ||
900 | u32 activePassive:2; | ||
901 | u32 reserved:5; | ||
890 | #endif | 902 | #endif |
891 | } adapterOperations2; | 903 | } adapterOperations2; |
892 | 904 | ||
@@ -914,8 +926,14 @@ struct megasas_ctrl_info { | |||
914 | } cluster; | 926 | } cluster; |
915 | 927 | ||
916 | char clusterId[16]; /*7D4h */ | 928 | char clusterId[16]; /*7D4h */ |
929 | struct { | ||
930 | u8 maxVFsSupported; /*0x7E4*/ | ||
931 | u8 numVFsEnabled; /*0x7E5*/ | ||
932 | u8 requestorId; /*0x7E6 0:PF, 1:VF1, 2:VF2*/ | ||
933 | u8 reserved; /*0x7E7*/ | ||
934 | } iov; | ||
917 | 935 | ||
918 | u8 pad[0x800-0x7E4]; /*7E4 */ | 936 | u8 pad[0x800-0x7E8]; /*0x7E8 pad to 2k */ |
919 | } __packed; | 937 | } __packed; |
920 | 938 | ||
921 | /* | 939 | /* |
@@ -986,7 +1004,9 @@ struct megasas_ctrl_info { | |||
986 | 1004 | ||
987 | #define MFI_OB_INTR_STATUS_MASK 0x00000002 | 1005 | #define MFI_OB_INTR_STATUS_MASK 0x00000002 |
988 | #define MFI_POLL_TIMEOUT_SECS 60 | 1006 | #define MFI_POLL_TIMEOUT_SECS 60 |
989 | 1007 | #define MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF (5 * HZ) | |
1008 | #define MEGASAS_OCR_SETTLE_TIME_VF (1000 * 30) | ||
1009 | #define MEGASAS_ROUTINE_WAIT_TIME_VF 300 | ||
990 | #define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000 | 1010 | #define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000 |
991 | #define MFI_REPLY_GEN2_MESSAGE_INTERRUPT 0x00000001 | 1011 | #define MFI_REPLY_GEN2_MESSAGE_INTERRUPT 0x00000001 |
992 | #define MFI_GEN2_ENABLE_INTERRUPT_MASK (0x00000001 | 0x00000004) | 1012 | #define MFI_GEN2_ENABLE_INTERRUPT_MASK (0x00000001 | 0x00000004) |
@@ -1529,6 +1549,12 @@ struct megasas_instance { | |||
1529 | dma_addr_t producer_h; | 1549 | dma_addr_t producer_h; |
1530 | u32 *consumer; | 1550 | u32 *consumer; |
1531 | dma_addr_t consumer_h; | 1551 | dma_addr_t consumer_h; |
1552 | struct MR_LD_VF_AFFILIATION *vf_affiliation; | ||
1553 | dma_addr_t vf_affiliation_h; | ||
1554 | struct MR_LD_VF_AFFILIATION_111 *vf_affiliation_111; | ||
1555 | dma_addr_t vf_affiliation_111_h; | ||
1556 | struct MR_CTRL_HB_HOST_MEM *hb_host_mem; | ||
1557 | dma_addr_t hb_host_mem_h; | ||
1532 | 1558 | ||
1533 | u32 *reply_queue; | 1559 | u32 *reply_queue; |
1534 | dma_addr_t reply_queue_h; | 1560 | dma_addr_t reply_queue_h; |
@@ -1604,10 +1630,73 @@ struct megasas_instance { | |||
1604 | unsigned long bar; | 1630 | unsigned long bar; |
1605 | long reset_flags; | 1631 | long reset_flags; |
1606 | struct mutex reset_mutex; | 1632 | struct mutex reset_mutex; |
1633 | struct timer_list sriov_heartbeat_timer; | ||
1634 | char skip_heartbeat_timer_del; | ||
1635 | u8 requestorId; | ||
1636 | u64 initiator_sas_address; | ||
1637 | u64 ld_sas_address[64]; | ||
1638 | char PlasmaFW111; | ||
1639 | char mpio; | ||
1607 | int throttlequeuedepth; | 1640 | int throttlequeuedepth; |
1608 | u8 mask_interrupts; | 1641 | u8 mask_interrupts; |
1609 | u8 is_imr; | 1642 | u8 is_imr; |
1610 | }; | 1643 | }; |
1644 | struct MR_LD_VF_MAP { | ||
1645 | u32 size; | ||
1646 | union MR_LD_REF ref; | ||
1647 | u8 ldVfCount; | ||
1648 | u8 reserved[6]; | ||
1649 | u8 policy[1]; | ||
1650 | }; | ||
1651 | |||
1652 | struct MR_LD_VF_AFFILIATION { | ||
1653 | u32 size; | ||
1654 | u8 ldCount; | ||
1655 | u8 vfCount; | ||
1656 | u8 thisVf; | ||
1657 | u8 reserved[9]; | ||
1658 | struct MR_LD_VF_MAP map[1]; | ||
1659 | }; | ||
1660 | |||
1661 | /* Plasma 1.11 FW backward compatibility structures */ | ||
1662 | #define IOV_111_OFFSET 0x7CE | ||
1663 | #define MAX_VIRTUAL_FUNCTIONS 8 | ||
1664 | |||
1665 | struct IOV_111 { | ||
1666 | u8 maxVFsSupported; | ||
1667 | u8 numVFsEnabled; | ||
1668 | u8 requestorId; | ||
1669 | u8 reserved[5]; | ||
1670 | }; | ||
1671 | |||
1672 | struct MR_LD_VF_MAP_111 { | ||
1673 | u8 targetId; | ||
1674 | u8 reserved[3]; | ||
1675 | u8 policy[MAX_VIRTUAL_FUNCTIONS]; | ||
1676 | }; | ||
1677 | |||
1678 | struct MR_LD_VF_AFFILIATION_111 { | ||
1679 | u8 vdCount; | ||
1680 | u8 vfCount; | ||
1681 | u8 thisVf; | ||
1682 | u8 reserved[5]; | ||
1683 | struct MR_LD_VF_MAP_111 map[MAX_LOGICAL_DRIVES]; | ||
1684 | }; | ||
1685 | |||
1686 | struct MR_CTRL_HB_HOST_MEM { | ||
1687 | struct { | ||
1688 | u32 fwCounter; /* Firmware heart beat counter */ | ||
1689 | struct { | ||
1690 | u32 debugmode:1; /* 1=Firmware is in debug mode. | ||
1691 | Heart beat will not be updated. */ | ||
1692 | u32 reserved:31; | ||
1693 | } debug; | ||
1694 | u32 reserved_fw[6]; | ||
1695 | u32 driverCounter; /* Driver heart beat counter. 0x20 */ | ||
1696 | u32 reserved_driver[7]; | ||
1697 | } HB; | ||
1698 | u8 pad[0x400-0x40]; | ||
1699 | }; | ||
1611 | 1700 | ||
1612 | enum { | 1701 | enum { |
1613 | MEGASAS_HBA_OPERATIONAL = 0, | 1702 | MEGASAS_HBA_OPERATIONAL = 0, |
@@ -1615,6 +1704,7 @@ enum { | |||
1615 | MEGASAS_ADPRESET_SM_FW_RESET_SUCCESS = 2, | 1704 | MEGASAS_ADPRESET_SM_FW_RESET_SUCCESS = 2, |
1616 | MEGASAS_ADPRESET_SM_OPERATIONAL = 3, | 1705 | MEGASAS_ADPRESET_SM_OPERATIONAL = 3, |
1617 | MEGASAS_HW_CRITICAL_ERROR = 4, | 1706 | MEGASAS_HW_CRITICAL_ERROR = 4, |
1707 | MEGASAS_ADPRESET_SM_POLLING = 5, | ||
1618 | MEGASAS_ADPRESET_INPROG_SIGN = 0xDEADDEAD, | 1708 | MEGASAS_ADPRESET_INPROG_SIGN = 0xDEADDEAD, |
1619 | }; | 1709 | }; |
1620 | 1710 | ||
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index c6203e677ab3..1fb7ab6e77bd 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c | |||
@@ -75,6 +75,10 @@ static unsigned int msix_vectors; | |||
75 | module_param(msix_vectors, int, S_IRUGO); | 75 | module_param(msix_vectors, int, S_IRUGO); |
76 | MODULE_PARM_DESC(msix_vectors, "MSI-X max vector count. Default: Set by FW"); | 76 | MODULE_PARM_DESC(msix_vectors, "MSI-X max vector count. Default: Set by FW"); |
77 | 77 | ||
78 | static int allow_vf_ioctls; | ||
79 | module_param(allow_vf_ioctls, int, S_IRUGO); | ||
80 | MODULE_PARM_DESC(allow_vf_ioctls, "Allow ioctls in SR-IOV VF mode. Default: 0"); | ||
81 | |||
78 | static int throttlequeuedepth = MEGASAS_THROTTLE_QUEUE_DEPTH; | 82 | static int throttlequeuedepth = MEGASAS_THROTTLE_QUEUE_DEPTH; |
79 | module_param(throttlequeuedepth, int, S_IRUGO); | 83 | module_param(throttlequeuedepth, int, S_IRUGO); |
80 | MODULE_PARM_DESC(throttlequeuedepth, | 84 | MODULE_PARM_DESC(throttlequeuedepth, |
@@ -122,6 +126,8 @@ static struct pci_device_id megasas_pci_table[] = { | |||
122 | /* xscale IOP */ | 126 | /* xscale IOP */ |
123 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FUSION)}, | 127 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FUSION)}, |
124 | /* Fusion */ | 128 | /* Fusion */ |
129 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_PLASMA)}, | ||
130 | /* Plasma */ | ||
125 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_INVADER)}, | 131 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_INVADER)}, |
126 | /* Invader */ | 132 | /* Invader */ |
127 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FURY)}, | 133 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FURY)}, |
@@ -132,7 +138,7 @@ static struct pci_device_id megasas_pci_table[] = { | |||
132 | MODULE_DEVICE_TABLE(pci, megasas_pci_table); | 138 | MODULE_DEVICE_TABLE(pci, megasas_pci_table); |
133 | 139 | ||
134 | static int megasas_mgmt_majorno; | 140 | static int megasas_mgmt_majorno; |
135 | static struct megasas_mgmt_info megasas_mgmt_info; | 141 | struct megasas_mgmt_info megasas_mgmt_info; |
136 | static struct fasync_struct *megasas_async_queue; | 142 | static struct fasync_struct *megasas_async_queue; |
137 | static DEFINE_MUTEX(megasas_async_queue_mutex); | 143 | static DEFINE_MUTEX(megasas_async_queue_mutex); |
138 | 144 | ||
@@ -171,10 +177,15 @@ megasas_get_map_info(struct megasas_instance *instance); | |||
171 | int | 177 | int |
172 | megasas_sync_map_info(struct megasas_instance *instance); | 178 | megasas_sync_map_info(struct megasas_instance *instance); |
173 | int | 179 | int |
174 | wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd); | 180 | wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd, |
181 | int seconds); | ||
175 | void megasas_reset_reply_desc(struct megasas_instance *instance); | 182 | void megasas_reset_reply_desc(struct megasas_instance *instance); |
176 | int megasas_reset_fusion(struct Scsi_Host *shost); | 183 | int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout); |
177 | void megasas_fusion_ocr_wq(struct work_struct *work); | 184 | void megasas_fusion_ocr_wq(struct work_struct *work); |
185 | static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance, | ||
186 | int initial); | ||
187 | int megasas_check_mpio_paths(struct megasas_instance *instance, | ||
188 | struct scsi_cmnd *scmd); | ||
178 | 189 | ||
179 | void | 190 | void |
180 | megasas_issue_dcmd(struct megasas_instance *instance, struct megasas_cmd *cmd) | 191 | megasas_issue_dcmd(struct megasas_instance *instance, struct megasas_cmd *cmd) |
@@ -224,6 +235,7 @@ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) | |||
224 | cmd->scmd = NULL; | 235 | cmd->scmd = NULL; |
225 | cmd->frame_count = 0; | 236 | cmd->frame_count = 0; |
226 | if ((instance->pdev->device != PCI_DEVICE_ID_LSI_FUSION) && | 237 | if ((instance->pdev->device != PCI_DEVICE_ID_LSI_FUSION) && |
238 | (instance->pdev->device != PCI_DEVICE_ID_LSI_PLASMA) && | ||
227 | (instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER) && | 239 | (instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER) && |
228 | (instance->pdev->device != PCI_DEVICE_ID_LSI_FURY) && | 240 | (instance->pdev->device != PCI_DEVICE_ID_LSI_FURY) && |
229 | (reset_devices)) | 241 | (reset_devices)) |
@@ -877,6 +889,7 @@ extern struct megasas_instance_template megasas_instance_template_fusion; | |||
877 | int | 889 | int |
878 | megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd) | 890 | megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd) |
879 | { | 891 | { |
892 | int seconds; | ||
880 | 893 | ||
881 | struct megasas_header *frame_hdr = &cmd->frame->hdr; | 894 | struct megasas_header *frame_hdr = &cmd->frame->hdr; |
882 | 895 | ||
@@ -891,7 +904,11 @@ megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd) | |||
891 | /* | 904 | /* |
892 | * Wait for cmd_status to change | 905 | * Wait for cmd_status to change |
893 | */ | 906 | */ |
894 | return wait_and_poll(instance, cmd); | 907 | if (instance->requestorId) |
908 | seconds = MEGASAS_ROUTINE_WAIT_TIME_VF; | ||
909 | else | ||
910 | seconds = MFI_POLL_TIMEOUT_SECS; | ||
911 | return wait_and_poll(instance, cmd, seconds); | ||
895 | } | 912 | } |
896 | 913 | ||
897 | /** | 914 | /** |
@@ -1532,9 +1549,23 @@ megasas_queue_command_lck(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd | |||
1532 | 1549 | ||
1533 | spin_lock_irqsave(&instance->hba_lock, flags); | 1550 | spin_lock_irqsave(&instance->hba_lock, flags); |
1534 | 1551 | ||
1552 | /* Check for an mpio path and adjust behavior */ | ||
1553 | if (instance->adprecovery == MEGASAS_ADPRESET_SM_INFAULT) { | ||
1554 | if (megasas_check_mpio_paths(instance, scmd) == | ||
1555 | (DID_RESET << 16)) { | ||
1556 | spin_unlock_irqrestore(&instance->hba_lock, flags); | ||
1557 | return SCSI_MLQUEUE_HOST_BUSY; | ||
1558 | } else { | ||
1559 | spin_unlock_irqrestore(&instance->hba_lock, flags); | ||
1560 | scmd->result = DID_NO_CONNECT << 16; | ||
1561 | done(scmd); | ||
1562 | return 0; | ||
1563 | } | ||
1564 | } | ||
1565 | |||
1535 | if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { | 1566 | if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { |
1536 | spin_unlock_irqrestore(&instance->hba_lock, flags); | 1567 | spin_unlock_irqrestore(&instance->hba_lock, flags); |
1537 | scmd->result = DID_ERROR << 16; | 1568 | scmd->result = DID_NO_CONNECT << 16; |
1538 | done(scmd); | 1569 | done(scmd); |
1539 | return 0; | 1570 | return 0; |
1540 | } | 1571 | } |
@@ -1659,9 +1690,14 @@ void megaraid_sas_kill_hba(struct megasas_instance *instance) | |||
1659 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || | 1690 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || |
1660 | (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) || | 1691 | (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) || |
1661 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || | 1692 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || |
1693 | (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) || | ||
1662 | (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || | 1694 | (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || |
1663 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { | 1695 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { |
1664 | writel(MFI_STOP_ADP, &instance->reg_set->doorbell); | 1696 | writel(MFI_STOP_ADP, &instance->reg_set->doorbell); |
1697 | /* Flush */ | ||
1698 | readl(&instance->reg_set->doorbell); | ||
1699 | if (instance->mpio && instance->requestorId) | ||
1700 | memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); | ||
1665 | } else { | 1701 | } else { |
1666 | writel(MFI_STOP_ADP, &instance->reg_set->inbound_doorbell); | 1702 | writel(MFI_STOP_ADP, &instance->reg_set->inbound_doorbell); |
1667 | } | 1703 | } |
@@ -1748,6 +1784,25 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr) | |||
1748 | megasas_check_and_restore_queue_depth(instance); | 1784 | megasas_check_and_restore_queue_depth(instance); |
1749 | } | 1785 | } |
1750 | 1786 | ||
1787 | /** | ||
1788 | * megasas_start_timer - Initializes a timer object | ||
1789 | * @instance: Adapter soft state | ||
1790 | * @timer: timer object to be initialized | ||
1791 | * @fn: timer function | ||
1792 | * @interval: time interval between timer function call | ||
1793 | * | ||
1794 | */ | ||
1795 | void megasas_start_timer(struct megasas_instance *instance, | ||
1796 | struct timer_list *timer, | ||
1797 | void *fn, unsigned long interval) | ||
1798 | { | ||
1799 | init_timer(timer); | ||
1800 | timer->expires = jiffies + interval; | ||
1801 | timer->data = (unsigned long)instance; | ||
1802 | timer->function = fn; | ||
1803 | add_timer(timer); | ||
1804 | } | ||
1805 | |||
1751 | static void | 1806 | static void |
1752 | megasas_internal_reset_defer_cmds(struct megasas_instance *instance); | 1807 | megasas_internal_reset_defer_cmds(struct megasas_instance *instance); |
1753 | 1808 | ||
@@ -1770,6 +1825,295 @@ void megasas_do_ocr(struct megasas_instance *instance) | |||
1770 | process_fw_state_change_wq(&instance->work_init); | 1825 | process_fw_state_change_wq(&instance->work_init); |
1771 | } | 1826 | } |
1772 | 1827 | ||
1828 | /* This function will get the current SR-IOV LD/VF affiliation */ | ||
1829 | static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance, | ||
1830 | int initial) | ||
1831 | { | ||
1832 | struct megasas_cmd *cmd; | ||
1833 | struct megasas_dcmd_frame *dcmd; | ||
1834 | struct MR_LD_VF_AFFILIATION *new_affiliation = NULL; | ||
1835 | struct MR_LD_VF_AFFILIATION_111 *new_affiliation_111 = NULL; | ||
1836 | struct MR_LD_VF_MAP *newmap = NULL, *savedmap = NULL; | ||
1837 | dma_addr_t new_affiliation_h; | ||
1838 | dma_addr_t new_affiliation_111_h; | ||
1839 | int ld, retval = 0; | ||
1840 | u8 thisVf; | ||
1841 | |||
1842 | cmd = megasas_get_cmd(instance); | ||
1843 | |||
1844 | if (!cmd) { | ||
1845 | printk(KERN_DEBUG "megasas: megasas_get_ld_vf_" | ||
1846 | "affiliation: Failed to get cmd for scsi%d.\n", | ||
1847 | instance->host->host_no); | ||
1848 | return -ENOMEM; | ||
1849 | } | ||
1850 | |||
1851 | dcmd = &cmd->frame->dcmd; | ||
1852 | |||
1853 | if (!instance->vf_affiliation && !instance->vf_affiliation_111) { | ||
1854 | printk(KERN_WARNING "megasas: SR-IOV: Couldn't get LD/VF " | ||
1855 | "affiliation for scsi%d.\n", instance->host->host_no); | ||
1856 | megasas_return_cmd(instance, cmd); | ||
1857 | return -ENOMEM; | ||
1858 | } | ||
1859 | |||
1860 | if (initial) | ||
1861 | if (instance->PlasmaFW111) | ||
1862 | memset(instance->vf_affiliation_111, 0, | ||
1863 | sizeof(struct MR_LD_VF_AFFILIATION_111)); | ||
1864 | else | ||
1865 | memset(instance->vf_affiliation, 0, | ||
1866 | (MAX_LOGICAL_DRIVES + 1) * | ||
1867 | sizeof(struct MR_LD_VF_AFFILIATION)); | ||
1868 | else { | ||
1869 | if (instance->PlasmaFW111) | ||
1870 | new_affiliation_111 = | ||
1871 | pci_alloc_consistent(instance->pdev, | ||
1872 | sizeof(struct MR_LD_VF_AFFILIATION_111), | ||
1873 | &new_affiliation_111_h); | ||
1874 | else | ||
1875 | new_affiliation = | ||
1876 | pci_alloc_consistent(instance->pdev, | ||
1877 | (MAX_LOGICAL_DRIVES + 1) * | ||
1878 | sizeof(struct MR_LD_VF_AFFILIATION), | ||
1879 | &new_affiliation_h); | ||
1880 | if (!new_affiliation && !new_affiliation_111) { | ||
1881 | printk(KERN_DEBUG "megasas: SR-IOV: Couldn't allocate " | ||
1882 | "memory for new affiliation for scsi%d.\n", | ||
1883 | instance->host->host_no); | ||
1884 | megasas_return_cmd(instance, cmd); | ||
1885 | return -ENOMEM; | ||
1886 | } | ||
1887 | if (instance->PlasmaFW111) | ||
1888 | memset(new_affiliation_111, 0, | ||
1889 | sizeof(struct MR_LD_VF_AFFILIATION_111)); | ||
1890 | else | ||
1891 | memset(new_affiliation, 0, (MAX_LOGICAL_DRIVES + 1) * | ||
1892 | sizeof(struct MR_LD_VF_AFFILIATION)); | ||
1893 | } | ||
1894 | |||
1895 | memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); | ||
1896 | |||
1897 | dcmd->cmd = MFI_CMD_DCMD; | ||
1898 | dcmd->cmd_status = 0xFF; | ||
1899 | dcmd->sge_count = 1; | ||
1900 | dcmd->flags = MFI_FRAME_DIR_BOTH; | ||
1901 | dcmd->timeout = 0; | ||
1902 | dcmd->pad_0 = 0; | ||
1903 | if (instance->PlasmaFW111) { | ||
1904 | dcmd->data_xfer_len = sizeof(struct MR_LD_VF_AFFILIATION_111); | ||
1905 | dcmd->opcode = MR_DCMD_LD_VF_MAP_GET_ALL_LDS_111; | ||
1906 | } else { | ||
1907 | dcmd->data_xfer_len = (MAX_LOGICAL_DRIVES + 1) * | ||
1908 | sizeof(struct MR_LD_VF_AFFILIATION); | ||
1909 | dcmd->opcode = MR_DCMD_LD_VF_MAP_GET_ALL_LDS; | ||
1910 | } | ||
1911 | |||
1912 | if (initial) { | ||
1913 | if (instance->PlasmaFW111) | ||
1914 | dcmd->sgl.sge32[0].phys_addr = | ||
1915 | instance->vf_affiliation_111_h; | ||
1916 | else | ||
1917 | dcmd->sgl.sge32[0].phys_addr = | ||
1918 | instance->vf_affiliation_h; | ||
1919 | } else { | ||
1920 | if (instance->PlasmaFW111) | ||
1921 | dcmd->sgl.sge32[0].phys_addr = new_affiliation_111_h; | ||
1922 | else | ||
1923 | dcmd->sgl.sge32[0].phys_addr = new_affiliation_h; | ||
1924 | } | ||
1925 | if (instance->PlasmaFW111) | ||
1926 | dcmd->sgl.sge32[0].length = | ||
1927 | sizeof(struct MR_LD_VF_AFFILIATION_111); | ||
1928 | else | ||
1929 | dcmd->sgl.sge32[0].length = (MAX_LOGICAL_DRIVES + 1) * | ||
1930 | sizeof(struct MR_LD_VF_AFFILIATION); | ||
1931 | |||
1932 | printk(KERN_WARNING "megasas: SR-IOV: Getting LD/VF affiliation for " | ||
1933 | "scsi%d\n", instance->host->host_no); | ||
1934 | |||
1935 | megasas_issue_blocked_cmd(instance, cmd, 0); | ||
1936 | |||
1937 | if (dcmd->cmd_status) { | ||
1938 | printk(KERN_WARNING "megasas: SR-IOV: LD/VF affiliation DCMD" | ||
1939 | " failed with status 0x%x for scsi%d.\n", | ||
1940 | dcmd->cmd_status, instance->host->host_no); | ||
1941 | retval = 1; /* Do a scan if we couldn't get affiliation */ | ||
1942 | goto out; | ||
1943 | } | ||
1944 | |||
1945 | if (!initial) { | ||
1946 | if (instance->PlasmaFW111) { | ||
1947 | if (!new_affiliation_111->vdCount) { | ||
1948 | printk(KERN_WARNING "megasas: SR-IOV: Got new " | ||
1949 | "LD/VF affiliation for passive path " | ||
1950 | "for scsi%d.\n", | ||
1951 | instance->host->host_no); | ||
1952 | retval = 1; | ||
1953 | goto out; | ||
1954 | } | ||
1955 | thisVf = new_affiliation_111->thisVf; | ||
1956 | for (ld = 0 ; ld < new_affiliation_111->vdCount; ld++) | ||
1957 | if (instance->vf_affiliation_111->map[ld].policy[thisVf] != new_affiliation_111->map[ld].policy[thisVf]) { | ||
1958 | printk(KERN_WARNING "megasas: SR-IOV: " | ||
1959 | "Got new LD/VF affiliation " | ||
1960 | "for scsi%d.\n", | ||
1961 | instance->host->host_no); | ||
1962 | memcpy(instance->vf_affiliation_111, | ||
1963 | new_affiliation_111, | ||
1964 | sizeof(struct MR_LD_VF_AFFILIATION_111)); | ||
1965 | retval = 1; | ||
1966 | goto out; | ||
1967 | } | ||
1968 | } else { | ||
1969 | if (!new_affiliation->ldCount) { | ||
1970 | printk(KERN_WARNING "megasas: SR-IOV: Got new " | ||
1971 | "LD/VF affiliation for passive " | ||
1972 | "path for scsi%d.\n", | ||
1973 | instance->host->host_no); | ||
1974 | retval = 1; | ||
1975 | goto out; | ||
1976 | } | ||
1977 | newmap = new_affiliation->map; | ||
1978 | savedmap = instance->vf_affiliation->map; | ||
1979 | thisVf = new_affiliation->thisVf; | ||
1980 | for (ld = 0 ; ld < new_affiliation->ldCount; ld++) { | ||
1981 | if (savedmap->policy[thisVf] != | ||
1982 | newmap->policy[thisVf]) { | ||
1983 | printk(KERN_WARNING "megasas: SR-IOV: " | ||
1984 | "Got new LD/VF affiliation " | ||
1985 | "for scsi%d.\n", | ||
1986 | instance->host->host_no); | ||
1987 | memcpy(instance->vf_affiliation, | ||
1988 | new_affiliation, | ||
1989 | new_affiliation->size); | ||
1990 | retval = 1; | ||
1991 | goto out; | ||
1992 | } | ||
1993 | savedmap = (struct MR_LD_VF_MAP *) | ||
1994 | ((unsigned char *)savedmap + | ||
1995 | savedmap->size); | ||
1996 | newmap = (struct MR_LD_VF_MAP *) | ||
1997 | ((unsigned char *)newmap + | ||
1998 | newmap->size); | ||
1999 | } | ||
2000 | } | ||
2001 | } | ||
2002 | out: | ||
2003 | if (new_affiliation) { | ||
2004 | if (instance->PlasmaFW111) | ||
2005 | pci_free_consistent(instance->pdev, | ||
2006 | sizeof(struct MR_LD_VF_AFFILIATION_111), | ||
2007 | new_affiliation_111, | ||
2008 | new_affiliation_111_h); | ||
2009 | else | ||
2010 | pci_free_consistent(instance->pdev, | ||
2011 | (MAX_LOGICAL_DRIVES + 1) * | ||
2012 | sizeof(struct MR_LD_VF_AFFILIATION), | ||
2013 | new_affiliation, new_affiliation_h); | ||
2014 | } | ||
2015 | megasas_return_cmd(instance, cmd); | ||
2016 | |||
2017 | return retval; | ||
2018 | } | ||
2019 | |||
2020 | /* This function will tell FW to start the SR-IOV heartbeat */ | ||
2021 | int megasas_sriov_start_heartbeat(struct megasas_instance *instance, | ||
2022 | int initial) | ||
2023 | { | ||
2024 | struct megasas_cmd *cmd; | ||
2025 | struct megasas_dcmd_frame *dcmd; | ||
2026 | int retval = 0; | ||
2027 | |||
2028 | cmd = megasas_get_cmd(instance); | ||
2029 | |||
2030 | if (!cmd) { | ||
2031 | printk(KERN_DEBUG "megasas: megasas_sriov_start_heartbeat: " | ||
2032 | "Failed to get cmd for scsi%d.\n", | ||
2033 | instance->host->host_no); | ||
2034 | return -ENOMEM; | ||
2035 | } | ||
2036 | |||
2037 | dcmd = &cmd->frame->dcmd; | ||
2038 | |||
2039 | if (initial) { | ||
2040 | instance->hb_host_mem = | ||
2041 | pci_alloc_consistent(instance->pdev, | ||
2042 | sizeof(struct MR_CTRL_HB_HOST_MEM), | ||
2043 | &instance->hb_host_mem_h); | ||
2044 | if (!instance->hb_host_mem) { | ||
2045 | printk(KERN_DEBUG "megasas: SR-IOV: Couldn't allocate" | ||
2046 | " memory for heartbeat host memory for " | ||
2047 | "scsi%d.\n", instance->host->host_no); | ||
2048 | retval = -ENOMEM; | ||
2049 | goto out; | ||
2050 | } | ||
2051 | memset(instance->hb_host_mem, 0, | ||
2052 | sizeof(struct MR_CTRL_HB_HOST_MEM)); | ||
2053 | } | ||
2054 | |||
2055 | memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); | ||
2056 | |||
2057 | dcmd->mbox.s[0] = sizeof(struct MR_CTRL_HB_HOST_MEM); | ||
2058 | dcmd->cmd = MFI_CMD_DCMD; | ||
2059 | dcmd->cmd_status = 0xFF; | ||
2060 | dcmd->sge_count = 1; | ||
2061 | dcmd->flags = MFI_FRAME_DIR_BOTH; | ||
2062 | dcmd->timeout = 0; | ||
2063 | dcmd->pad_0 = 0; | ||
2064 | dcmd->data_xfer_len = sizeof(struct MR_CTRL_HB_HOST_MEM); | ||
2065 | dcmd->opcode = MR_DCMD_CTRL_SHARED_HOST_MEM_ALLOC; | ||
2066 | dcmd->sgl.sge32[0].phys_addr = instance->hb_host_mem_h; | ||
2067 | dcmd->sgl.sge32[0].length = sizeof(struct MR_CTRL_HB_HOST_MEM); | ||
2068 | |||
2069 | printk(KERN_WARNING "megasas: SR-IOV: Starting heartbeat for scsi%d\n", | ||
2070 | instance->host->host_no); | ||
2071 | |||
2072 | if (!megasas_issue_polled(instance, cmd)) { | ||
2073 | retval = 0; | ||
2074 | } else { | ||
2075 | printk(KERN_WARNING "megasas: SR-IOV: MR_DCMD_CTRL_SHARED_HOST" | ||
2076 | "_MEM_ALLOC DCMD timed out for scsi%d\n", | ||
2077 | instance->host->host_no); | ||
2078 | retval = 1; | ||
2079 | goto out; | ||
2080 | } | ||
2081 | |||
2082 | |||
2083 | if (dcmd->cmd_status) { | ||
2084 | printk(KERN_WARNING "megasas: SR-IOV: MR_DCMD_CTRL_SHARED_HOST" | ||
2085 | "_MEM_ALLOC DCMD failed with status 0x%x for scsi%d\n", | ||
2086 | dcmd->cmd_status, | ||
2087 | instance->host->host_no); | ||
2088 | retval = 1; | ||
2089 | goto out; | ||
2090 | } | ||
2091 | |||
2092 | out: | ||
2093 | megasas_return_cmd(instance, cmd); | ||
2094 | |||
2095 | return retval; | ||
2096 | } | ||
2097 | |||
2098 | /* Handler for SR-IOV heartbeat */ | ||
2099 | void megasas_sriov_heartbeat_handler(unsigned long instance_addr) | ||
2100 | { | ||
2101 | struct megasas_instance *instance = | ||
2102 | (struct megasas_instance *)instance_addr; | ||
2103 | |||
2104 | if (instance->hb_host_mem->HB.fwCounter != | ||
2105 | instance->hb_host_mem->HB.driverCounter) { | ||
2106 | instance->hb_host_mem->HB.driverCounter = | ||
2107 | instance->hb_host_mem->HB.fwCounter; | ||
2108 | mod_timer(&instance->sriov_heartbeat_timer, | ||
2109 | jiffies + MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF); | ||
2110 | } else { | ||
2111 | printk(KERN_WARNING "megasas: SR-IOV: Heartbeat never " | ||
2112 | "completed for scsi%d\n", instance->host->host_no); | ||
2113 | schedule_work(&instance->work_init); | ||
2114 | } | ||
2115 | } | ||
2116 | |||
1773 | /** | 2117 | /** |
1774 | * megasas_wait_for_outstanding - Wait for all outstanding cmds | 2118 | * megasas_wait_for_outstanding - Wait for all outstanding cmds |
1775 | * @instance: Adapter soft state | 2119 | * @instance: Adapter soft state |
@@ -2032,9 +2376,10 @@ static int megasas_reset_bus_host(struct scsi_cmnd *scmd) | |||
2032 | * First wait for all commands to complete | 2376 | * First wait for all commands to complete |
2033 | */ | 2377 | */ |
2034 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || | 2378 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || |
2379 | (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) || | ||
2035 | (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || | 2380 | (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || |
2036 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) | 2381 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) |
2037 | ret = megasas_reset_fusion(scmd->device->host); | 2382 | ret = megasas_reset_fusion(scmd->device->host, 1); |
2038 | else | 2383 | else |
2039 | ret = megasas_generic_reset(scmd); | 2384 | ret = megasas_generic_reset(scmd); |
2040 | 2385 | ||
@@ -2749,6 +3094,8 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr) | |||
2749 | (instance->pdev->device == | 3094 | (instance->pdev->device == |
2750 | PCI_DEVICE_ID_LSI_FUSION) || | 3095 | PCI_DEVICE_ID_LSI_FUSION) || |
2751 | (instance->pdev->device == | 3096 | (instance->pdev->device == |
3097 | PCI_DEVICE_ID_LSI_PLASMA) || | ||
3098 | (instance->pdev->device == | ||
2752 | PCI_DEVICE_ID_LSI_INVADER) || | 3099 | PCI_DEVICE_ID_LSI_INVADER) || |
2753 | (instance->pdev->device == | 3100 | (instance->pdev->device == |
2754 | PCI_DEVICE_ID_LSI_FURY)) { | 3101 | PCI_DEVICE_ID_LSI_FURY)) { |
@@ -2773,6 +3120,8 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr) | |||
2773 | (instance->pdev->device == | 3120 | (instance->pdev->device == |
2774 | PCI_DEVICE_ID_LSI_FUSION) || | 3121 | PCI_DEVICE_ID_LSI_FUSION) || |
2775 | (instance->pdev->device == | 3122 | (instance->pdev->device == |
3123 | PCI_DEVICE_ID_LSI_PLASMA) || | ||
3124 | (instance->pdev->device == | ||
2776 | PCI_DEVICE_ID_LSI_INVADER) || | 3125 | PCI_DEVICE_ID_LSI_INVADER) || |
2777 | (instance->pdev->device == | 3126 | (instance->pdev->device == |
2778 | PCI_DEVICE_ID_LSI_FURY)) { | 3127 | PCI_DEVICE_ID_LSI_FURY)) { |
@@ -2798,6 +3147,8 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr) | |||
2798 | (instance->pdev->device | 3147 | (instance->pdev->device |
2799 | == PCI_DEVICE_ID_LSI_FUSION) || | 3148 | == PCI_DEVICE_ID_LSI_FUSION) || |
2800 | (instance->pdev->device | 3149 | (instance->pdev->device |
3150 | == PCI_DEVICE_ID_LSI_PLASMA) || | ||
3151 | (instance->pdev->device | ||
2801 | == PCI_DEVICE_ID_LSI_INVADER) || | 3152 | == PCI_DEVICE_ID_LSI_INVADER) || |
2802 | (instance->pdev->device | 3153 | (instance->pdev->device |
2803 | == PCI_DEVICE_ID_LSI_FURY)) { | 3154 | == PCI_DEVICE_ID_LSI_FURY)) { |
@@ -2806,6 +3157,8 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr) | |||
2806 | if ((instance->pdev->device == | 3157 | if ((instance->pdev->device == |
2807 | PCI_DEVICE_ID_LSI_FUSION) || | 3158 | PCI_DEVICE_ID_LSI_FUSION) || |
2808 | (instance->pdev->device == | 3159 | (instance->pdev->device == |
3160 | PCI_DEVICE_ID_LSI_PLASMA) || | ||
3161 | (instance->pdev->device == | ||
2809 | PCI_DEVICE_ID_LSI_INVADER) || | 3162 | PCI_DEVICE_ID_LSI_INVADER) || |
2810 | (instance->pdev->device == | 3163 | (instance->pdev->device == |
2811 | PCI_DEVICE_ID_LSI_FURY)) { | 3164 | PCI_DEVICE_ID_LSI_FURY)) { |
@@ -3032,6 +3385,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance) | |||
3032 | cmd->frame->io.context = cpu_to_le32(cmd->index); | 3385 | cmd->frame->io.context = cpu_to_le32(cmd->index); |
3033 | cmd->frame->io.pad_0 = 0; | 3386 | cmd->frame->io.pad_0 = 0; |
3034 | if ((instance->pdev->device != PCI_DEVICE_ID_LSI_FUSION) && | 3387 | if ((instance->pdev->device != PCI_DEVICE_ID_LSI_FUSION) && |
3388 | (instance->pdev->device != PCI_DEVICE_ID_LSI_PLASMA) && | ||
3035 | (instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER) && | 3389 | (instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER) && |
3036 | (instance->pdev->device != PCI_DEVICE_ID_LSI_FURY) && | 3390 | (instance->pdev->device != PCI_DEVICE_ID_LSI_FURY) && |
3037 | (reset_devices)) | 3391 | (reset_devices)) |
@@ -3638,6 +3992,7 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
3638 | struct megasas_ctrl_info *ctrl_info; | 3992 | struct megasas_ctrl_info *ctrl_info; |
3639 | unsigned long bar_list; | 3993 | unsigned long bar_list; |
3640 | int i, loop, fw_msix_count = 0; | 3994 | int i, loop, fw_msix_count = 0; |
3995 | struct IOV_111 *iovPtr; | ||
3641 | 3996 | ||
3642 | /* Find first memory bar */ | 3997 | /* Find first memory bar */ |
3643 | bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM); | 3998 | bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM); |
@@ -3660,6 +4015,7 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
3660 | 4015 | ||
3661 | switch (instance->pdev->device) { | 4016 | switch (instance->pdev->device) { |
3662 | case PCI_DEVICE_ID_LSI_FUSION: | 4017 | case PCI_DEVICE_ID_LSI_FUSION: |
4018 | case PCI_DEVICE_ID_LSI_PLASMA: | ||
3663 | case PCI_DEVICE_ID_LSI_INVADER: | 4019 | case PCI_DEVICE_ID_LSI_INVADER: |
3664 | case PCI_DEVICE_ID_LSI_FURY: | 4020 | case PCI_DEVICE_ID_LSI_FURY: |
3665 | instance->instancet = &megasas_instance_template_fusion; | 4021 | instance->instancet = &megasas_instance_template_fusion; |
@@ -3714,7 +4070,8 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
3714 | scratch_pad_2 = readl | 4070 | scratch_pad_2 = readl |
3715 | (&instance->reg_set->outbound_scratch_pad_2); | 4071 | (&instance->reg_set->outbound_scratch_pad_2); |
3716 | /* Check max MSI-X vectors */ | 4072 | /* Check max MSI-X vectors */ |
3717 | if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) { | 4073 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || |
4074 | (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA)) { | ||
3718 | instance->msix_vectors = (scratch_pad_2 | 4075 | instance->msix_vectors = (scratch_pad_2 |
3719 | & MR_MAX_REPLY_QUEUES_OFFSET) + 1; | 4076 | & MR_MAX_REPLY_QUEUES_OFFSET) + 1; |
3720 | fw_msix_count = instance->msix_vectors; | 4077 | fw_msix_count = instance->msix_vectors; |
@@ -3828,6 +4185,7 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
3828 | ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset; | 4185 | ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset; |
3829 | /* adapterOperations2 are converted into CPU arch*/ | 4186 | /* adapterOperations2 are converted into CPU arch*/ |
3830 | le32_to_cpus((u32 *)&ctrl_info->adapterOperations2); | 4187 | le32_to_cpus((u32 *)&ctrl_info->adapterOperations2); |
4188 | instance->mpio = ctrl_info->adapterOperations2.mpio; | ||
3831 | instance->UnevenSpanSupport = | 4189 | instance->UnevenSpanSupport = |
3832 | ctrl_info->adapterOperations2.supportUnevenSpans; | 4190 | ctrl_info->adapterOperations2.supportUnevenSpans; |
3833 | if (instance->UnevenSpanSupport) { | 4191 | if (instance->UnevenSpanSupport) { |
@@ -3840,6 +4198,20 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
3840 | fusion->fast_path_io = 0; | 4198 | fusion->fast_path_io = 0; |
3841 | 4199 | ||
3842 | } | 4200 | } |
4201 | if (ctrl_info->host_interface.SRIOV) { | ||
4202 | if (!ctrl_info->adapterOperations2.activePassive) | ||
4203 | instance->PlasmaFW111 = 1; | ||
4204 | |||
4205 | if (!instance->PlasmaFW111) | ||
4206 | instance->requestorId = | ||
4207 | ctrl_info->iov.requestorId; | ||
4208 | else { | ||
4209 | iovPtr = (struct IOV_111 *)((unsigned char *)ctrl_info + IOV_111_OFFSET); | ||
4210 | instance->requestorId = iovPtr->requestorId; | ||
4211 | } | ||
4212 | printk(KERN_WARNING "megaraid_sas: I am VF " | ||
4213 | "requestorId %d\n", instance->requestorId); | ||
4214 | } | ||
3843 | } | 4215 | } |
3844 | instance->max_sectors_per_req = instance->max_num_sge * | 4216 | instance->max_sectors_per_req = instance->max_num_sge * |
3845 | PAGE_SIZE / 512; | 4217 | PAGE_SIZE / 512; |
@@ -3872,6 +4244,17 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
3872 | tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet, | 4244 | tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet, |
3873 | (unsigned long)instance); | 4245 | (unsigned long)instance); |
3874 | 4246 | ||
4247 | /* Launch SR-IOV heartbeat timer */ | ||
4248 | if (instance->requestorId) { | ||
4249 | if (!megasas_sriov_start_heartbeat(instance, 1)) | ||
4250 | megasas_start_timer(instance, | ||
4251 | &instance->sriov_heartbeat_timer, | ||
4252 | megasas_sriov_heartbeat_handler, | ||
4253 | MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF); | ||
4254 | else | ||
4255 | instance->skip_heartbeat_timer_del = 1; | ||
4256 | } | ||
4257 | |||
3875 | return 0; | 4258 | return 0; |
3876 | 4259 | ||
3877 | fail_init_adapter: | 4260 | fail_init_adapter: |
@@ -4184,6 +4567,7 @@ static int megasas_io_attach(struct megasas_instance *instance) | |||
4184 | 4567 | ||
4185 | /* Fusion only supports host reset */ | 4568 | /* Fusion only supports host reset */ |
4186 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || | 4569 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || |
4570 | (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) || | ||
4187 | (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || | 4571 | (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || |
4188 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { | 4572 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { |
4189 | host->hostt->eh_device_reset_handler = NULL; | 4573 | host->hostt->eh_device_reset_handler = NULL; |
@@ -4309,6 +4693,7 @@ static int megasas_probe_one(struct pci_dev *pdev, | |||
4309 | 4693 | ||
4310 | switch (instance->pdev->device) { | 4694 | switch (instance->pdev->device) { |
4311 | case PCI_DEVICE_ID_LSI_FUSION: | 4695 | case PCI_DEVICE_ID_LSI_FUSION: |
4696 | case PCI_DEVICE_ID_LSI_PLASMA: | ||
4312 | case PCI_DEVICE_ID_LSI_INVADER: | 4697 | case PCI_DEVICE_ID_LSI_INVADER: |
4313 | case PCI_DEVICE_ID_LSI_FURY: | 4698 | case PCI_DEVICE_ID_LSI_FURY: |
4314 | { | 4699 | { |
@@ -4405,6 +4790,7 @@ static int megasas_probe_one(struct pci_dev *pdev, | |||
4405 | instance->UnevenSpanSupport = 0; | 4790 | instance->UnevenSpanSupport = 0; |
4406 | 4791 | ||
4407 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || | 4792 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || |
4793 | (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) || | ||
4408 | (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || | 4794 | (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || |
4409 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) | 4795 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) |
4410 | INIT_WORK(&instance->work_init, megasas_fusion_ocr_wq); | 4796 | INIT_WORK(&instance->work_init, megasas_fusion_ocr_wq); |
@@ -4417,6 +4803,26 @@ static int megasas_probe_one(struct pci_dev *pdev, | |||
4417 | if (megasas_init_fw(instance)) | 4803 | if (megasas_init_fw(instance)) |
4418 | goto fail_init_mfi; | 4804 | goto fail_init_mfi; |
4419 | 4805 | ||
4806 | if (instance->requestorId) { | ||
4807 | if (instance->PlasmaFW111) { | ||
4808 | instance->vf_affiliation_111 = | ||
4809 | pci_alloc_consistent(pdev, sizeof(struct MR_LD_VF_AFFILIATION_111), | ||
4810 | &instance->vf_affiliation_111_h); | ||
4811 | if (!instance->vf_affiliation_111) | ||
4812 | printk(KERN_WARNING "megasas: Can't allocate " | ||
4813 | "memory for VF affiliation buffer\n"); | ||
4814 | } else { | ||
4815 | instance->vf_affiliation = | ||
4816 | pci_alloc_consistent(pdev, | ||
4817 | (MAX_LOGICAL_DRIVES + 1) * | ||
4818 | sizeof(struct MR_LD_VF_AFFILIATION), | ||
4819 | &instance->vf_affiliation_h); | ||
4820 | if (!instance->vf_affiliation) | ||
4821 | printk(KERN_WARNING "megasas: Can't allocate " | ||
4822 | "memory for VF affiliation buffer\n"); | ||
4823 | } | ||
4824 | } | ||
4825 | |||
4420 | retry_irq_register: | 4826 | retry_irq_register: |
4421 | /* | 4827 | /* |
4422 | * Register IRQ | 4828 | * Register IRQ |
@@ -4511,6 +4917,7 @@ retry_irq_register: | |||
4511 | free_irq(instance->pdev->irq, &instance->irq_context[0]); | 4917 | free_irq(instance->pdev->irq, &instance->irq_context[0]); |
4512 | fail_irq: | 4918 | fail_irq: |
4513 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || | 4919 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || |
4920 | (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) || | ||
4514 | (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || | 4921 | (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || |
4515 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) | 4922 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) |
4516 | megasas_release_fusion(instance); | 4923 | megasas_release_fusion(instance); |
@@ -4644,6 +5051,10 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state) | |||
4644 | host = instance->host; | 5051 | host = instance->host; |
4645 | instance->unload = 1; | 5052 | instance->unload = 1; |
4646 | 5053 | ||
5054 | /* Shutdown SR-IOV heartbeat timer */ | ||
5055 | if (instance->requestorId && !instance->skip_heartbeat_timer_del) | ||
5056 | del_timer_sync(&instance->sriov_heartbeat_timer); | ||
5057 | |||
4647 | megasas_flush_cache(instance); | 5058 | megasas_flush_cache(instance); |
4648 | megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN); | 5059 | megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN); |
4649 | 5060 | ||
@@ -4730,6 +5141,7 @@ megasas_resume(struct pci_dev *pdev) | |||
4730 | 5141 | ||
4731 | switch (instance->pdev->device) { | 5142 | switch (instance->pdev->device) { |
4732 | case PCI_DEVICE_ID_LSI_FUSION: | 5143 | case PCI_DEVICE_ID_LSI_FUSION: |
5144 | case PCI_DEVICE_ID_LSI_PLASMA: | ||
4733 | case PCI_DEVICE_ID_LSI_INVADER: | 5145 | case PCI_DEVICE_ID_LSI_INVADER: |
4734 | case PCI_DEVICE_ID_LSI_FURY: | 5146 | case PCI_DEVICE_ID_LSI_FURY: |
4735 | { | 5147 | { |
@@ -4795,6 +5207,17 @@ megasas_resume(struct pci_dev *pdev) | |||
4795 | } | 5207 | } |
4796 | } | 5208 | } |
4797 | 5209 | ||
5210 | /* Re-launch SR-IOV heartbeat timer */ | ||
5211 | if (instance->requestorId) { | ||
5212 | if (!megasas_sriov_start_heartbeat(instance, 0)) | ||
5213 | megasas_start_timer(instance, | ||
5214 | &instance->sriov_heartbeat_timer, | ||
5215 | megasas_sriov_heartbeat_handler, | ||
5216 | MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF); | ||
5217 | else | ||
5218 | instance->skip_heartbeat_timer_del = 1; | ||
5219 | } | ||
5220 | |||
4798 | instance->instancet->enable_intr(instance); | 5221 | instance->instancet->enable_intr(instance); |
4799 | instance->unload = 0; | 5222 | instance->unload = 0; |
4800 | 5223 | ||
@@ -4849,6 +5272,10 @@ static void megasas_detach_one(struct pci_dev *pdev) | |||
4849 | host = instance->host; | 5272 | host = instance->host; |
4850 | fusion = instance->ctrl_context; | 5273 | fusion = instance->ctrl_context; |
4851 | 5274 | ||
5275 | /* Shutdown SR-IOV heartbeat timer */ | ||
5276 | if (instance->requestorId && !instance->skip_heartbeat_timer_del) | ||
5277 | del_timer_sync(&instance->sriov_heartbeat_timer); | ||
5278 | |||
4852 | scsi_remove_host(instance->host); | 5279 | scsi_remove_host(instance->host); |
4853 | megasas_flush_cache(instance); | 5280 | megasas_flush_cache(instance); |
4854 | megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); | 5281 | megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); |
@@ -4894,6 +5321,7 @@ static void megasas_detach_one(struct pci_dev *pdev) | |||
4894 | 5321 | ||
4895 | switch (instance->pdev->device) { | 5322 | switch (instance->pdev->device) { |
4896 | case PCI_DEVICE_ID_LSI_FUSION: | 5323 | case PCI_DEVICE_ID_LSI_FUSION: |
5324 | case PCI_DEVICE_ID_LSI_PLASMA: | ||
4897 | case PCI_DEVICE_ID_LSI_INVADER: | 5325 | case PCI_DEVICE_ID_LSI_INVADER: |
4898 | case PCI_DEVICE_ID_LSI_FURY: | 5326 | case PCI_DEVICE_ID_LSI_FURY: |
4899 | megasas_release_fusion(instance); | 5327 | megasas_release_fusion(instance); |
@@ -4920,6 +5348,24 @@ static void megasas_detach_one(struct pci_dev *pdev) | |||
4920 | if (instance->evt_detail) | 5348 | if (instance->evt_detail) |
4921 | pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), | 5349 | pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), |
4922 | instance->evt_detail, instance->evt_detail_h); | 5350 | instance->evt_detail, instance->evt_detail_h); |
5351 | |||
5352 | if (instance->vf_affiliation) | ||
5353 | pci_free_consistent(pdev, (MAX_LOGICAL_DRIVES + 1) * | ||
5354 | sizeof(struct MR_LD_VF_AFFILIATION), | ||
5355 | instance->vf_affiliation, | ||
5356 | instance->vf_affiliation_h); | ||
5357 | |||
5358 | if (instance->vf_affiliation_111) | ||
5359 | pci_free_consistent(pdev, | ||
5360 | sizeof(struct MR_LD_VF_AFFILIATION_111), | ||
5361 | instance->vf_affiliation_111, | ||
5362 | instance->vf_affiliation_111_h); | ||
5363 | |||
5364 | if (instance->hb_host_mem) | ||
5365 | pci_free_consistent(pdev, sizeof(struct MR_CTRL_HB_HOST_MEM), | ||
5366 | instance->hb_host_mem, | ||
5367 | instance->hb_host_mem_h); | ||
5368 | |||
4923 | scsi_host_put(host); | 5369 | scsi_host_put(host); |
4924 | 5370 | ||
4925 | pci_disable_device(pdev); | 5371 | pci_disable_device(pdev); |
@@ -5208,6 +5654,16 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) | |||
5208 | goto out_kfree_ioc; | 5654 | goto out_kfree_ioc; |
5209 | } | 5655 | } |
5210 | 5656 | ||
5657 | /* Adjust ioctl wait time for VF mode */ | ||
5658 | if (instance->requestorId) | ||
5659 | wait_time = MEGASAS_ROUTINE_WAIT_TIME_VF; | ||
5660 | |||
5661 | /* Block ioctls in VF mode */ | ||
5662 | if (instance->requestorId && !allow_vf_ioctls) { | ||
5663 | error = -ENODEV; | ||
5664 | goto out_kfree_ioc; | ||
5665 | } | ||
5666 | |||
5211 | if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { | 5667 | if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { |
5212 | printk(KERN_ERR "Controller in crit error\n"); | 5668 | printk(KERN_ERR "Controller in crit error\n"); |
5213 | error = -ENODEV; | 5669 | error = -ENODEV; |
@@ -5517,7 +5973,7 @@ megasas_aen_polling(struct work_struct *work) | |||
5517 | u16 pd_index = 0; | 5973 | u16 pd_index = 0; |
5518 | u16 ld_index = 0; | 5974 | u16 ld_index = 0; |
5519 | int i, j, doscan = 0; | 5975 | int i, j, doscan = 0; |
5520 | u32 seq_num; | 5976 | u32 seq_num, wait_time = MEGASAS_RESET_WAIT_TIME; |
5521 | int error; | 5977 | int error; |
5522 | 5978 | ||
5523 | if (!instance) { | 5979 | if (!instance) { |
@@ -5525,6 +5981,23 @@ megasas_aen_polling(struct work_struct *work) | |||
5525 | kfree(ev); | 5981 | kfree(ev); |
5526 | return; | 5982 | return; |
5527 | } | 5983 | } |
5984 | |||
5985 | /* Adjust event workqueue thread wait time for VF mode */ | ||
5986 | if (instance->requestorId) | ||
5987 | wait_time = MEGASAS_ROUTINE_WAIT_TIME_VF; | ||
5988 | |||
5989 | /* Don't run the event workqueue thread if OCR is running */ | ||
5990 | for (i = 0; i < wait_time; i++) { | ||
5991 | if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) | ||
5992 | break; | ||
5993 | if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { | ||
5994 | printk(KERN_NOTICE "megasas: %s waiting for " | ||
5995 | "controller reset to finish for scsi%d\n", | ||
5996 | __func__, instance->host->host_no); | ||
5997 | } | ||
5998 | msleep(1000); | ||
5999 | } | ||
6000 | |||
5528 | instance->ev = NULL; | 6001 | instance->ev = NULL; |
5529 | host = instance->host; | 6002 | host = instance->host; |
5530 | if (instance->evt_detail) { | 6003 | if (instance->evt_detail) { |
@@ -5591,65 +6064,64 @@ megasas_aen_polling(struct work_struct *work) | |||
5591 | case MR_EVT_LD_OFFLINE: | 6064 | case MR_EVT_LD_OFFLINE: |
5592 | case MR_EVT_CFG_CLEARED: | 6065 | case MR_EVT_CFG_CLEARED: |
5593 | case MR_EVT_LD_DELETED: | 6066 | case MR_EVT_LD_DELETED: |
5594 | if (megasas_ld_list_query(instance, | 6067 | if (!instance->requestorId || |
5595 | MR_LD_QUERY_TYPE_EXPOSED_TO_HOST)) | 6068 | (instance->requestorId && |
5596 | megasas_get_ld_list(instance); | 6069 | megasas_get_ld_vf_affiliation(instance, 0))) { |
5597 | for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { | 6070 | if (megasas_ld_list_query(instance, |
5598 | for (j = 0; | 6071 | MR_LD_QUERY_TYPE_EXPOSED_TO_HOST)) |
5599 | j < MEGASAS_MAX_DEV_PER_CHANNEL; | 6072 | megasas_get_ld_list(instance); |
5600 | j++) { | 6073 | for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { |
5601 | 6074 | for (j = 0; | |
5602 | ld_index = | 6075 | j < MEGASAS_MAX_DEV_PER_CHANNEL; |
5603 | (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; | 6076 | j++) { |
5604 | 6077 | ||
5605 | sdev1 = scsi_device_lookup(host, | 6078 | ld_index = |
5606 | MEGASAS_MAX_PD_CHANNELS + i, | 6079 | (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; |
5607 | j, | 6080 | |
5608 | 0); | 6081 | sdev1 = scsi_device_lookup(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0); |
5609 | 6082 | ||
5610 | if (instance->ld_ids[ld_index] != 0xff) { | 6083 | if (instance->ld_ids[ld_index] |
5611 | if (sdev1) { | 6084 | != 0xff) { |
5612 | scsi_device_put(sdev1); | 6085 | if (sdev1) |
5613 | } | 6086 | scsi_device_put(sdev1); |
5614 | } else { | 6087 | } else { |
5615 | if (sdev1) { | 6088 | if (sdev1) { |
5616 | scsi_remove_device(sdev1); | 6089 | scsi_remove_device(sdev1); |
5617 | scsi_device_put(sdev1); | 6090 | scsi_device_put(sdev1); |
6091 | } | ||
6092 | } | ||
5618 | } | 6093 | } |
5619 | } | 6094 | } |
5620 | } | 6095 | doscan = 0; |
5621 | } | 6096 | } |
5622 | doscan = 0; | ||
5623 | break; | 6097 | break; |
5624 | case MR_EVT_LD_CREATED: | 6098 | case MR_EVT_LD_CREATED: |
5625 | if (megasas_ld_list_query(instance, | 6099 | if (!instance->requestorId || |
5626 | MR_LD_QUERY_TYPE_EXPOSED_TO_HOST)) | 6100 | (instance->requestorId && |
5627 | megasas_get_ld_list(instance); | 6101 | megasas_get_ld_vf_affiliation(instance, 0))) { |
5628 | for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { | 6102 | if (megasas_ld_list_query(instance, |
5629 | for (j = 0; | 6103 | MR_LD_QUERY_TYPE_EXPOSED_TO_HOST)) |
5630 | j < MEGASAS_MAX_DEV_PER_CHANNEL; | 6104 | megasas_get_ld_list(instance); |
5631 | j++) { | 6105 | for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { |
5632 | ld_index = | 6106 | for (j = 0; |
5633 | (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; | 6107 | j < MEGASAS_MAX_DEV_PER_CHANNEL; |
5634 | 6108 | j++) { | |
5635 | sdev1 = scsi_device_lookup(host, | 6109 | ld_index = |
5636 | MEGASAS_MAX_PD_CHANNELS + i, | 6110 | (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; |
5637 | j, 0); | 6111 | |
5638 | 6112 | sdev1 = scsi_device_lookup(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0); | |
5639 | if (instance->ld_ids[ld_index] != | 6113 | |
5640 | 0xff) { | 6114 | if (instance->ld_ids[ld_index] |
5641 | if (!sdev1) { | 6115 | != 0xff) { |
5642 | scsi_add_device(host, | 6116 | if (!sdev1) |
5643 | MEGASAS_MAX_PD_CHANNELS + i, | 6117 | scsi_add_device(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0); |
5644 | j, 0); | ||
5645 | } | 6118 | } |
5646 | } | 6119 | if (sdev1) |
5647 | if (sdev1) { | 6120 | scsi_device_put(sdev1); |
5648 | scsi_device_put(sdev1); | ||
5649 | } | 6121 | } |
5650 | } | 6122 | } |
6123 | doscan = 0; | ||
5651 | } | 6124 | } |
5652 | doscan = 0; | ||
5653 | break; | 6125 | break; |
5654 | case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED: | 6126 | case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED: |
5655 | case MR_EVT_FOREIGN_CFG_IMPORTED: | 6127 | case MR_EVT_FOREIGN_CFG_IMPORTED: |
@@ -5667,7 +6139,8 @@ megasas_aen_polling(struct work_struct *work) | |||
5667 | } | 6139 | } |
5668 | 6140 | ||
5669 | if (doscan) { | 6141 | if (doscan) { |
5670 | printk(KERN_INFO "scanning ...\n"); | 6142 | printk(KERN_INFO "megaraid_sas: scanning for scsi%d...\n", |
6143 | instance->host->host_no); | ||
5671 | if (megasas_get_pd_list(instance) == 0) { | 6144 | if (megasas_get_pd_list(instance) == 0) { |
5672 | for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) { | 6145 | for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) { |
5673 | for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) { | 6146 | for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) { |
@@ -5690,28 +6163,31 @@ megasas_aen_polling(struct work_struct *work) | |||
5690 | } | 6163 | } |
5691 | } | 6164 | } |
5692 | 6165 | ||
5693 | if (megasas_ld_list_query(instance, | 6166 | if (!instance->requestorId || |
5694 | MR_LD_QUERY_TYPE_EXPOSED_TO_HOST)) | 6167 | (instance->requestorId && |
5695 | megasas_get_ld_list(instance); | 6168 | megasas_get_ld_vf_affiliation(instance, 0))) { |
5696 | for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { | 6169 | if (megasas_ld_list_query(instance, |
5697 | for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) { | 6170 | MR_LD_QUERY_TYPE_EXPOSED_TO_HOST)) |
5698 | ld_index = | 6171 | megasas_get_ld_list(instance); |
5699 | (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; | 6172 | for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { |
6173 | for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; | ||
6174 | j++) { | ||
6175 | ld_index = | ||
6176 | (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; | ||
5700 | 6177 | ||
5701 | sdev1 = scsi_device_lookup(host, | 6178 | sdev1 = scsi_device_lookup(host, |
5702 | MEGASAS_MAX_PD_CHANNELS + i, j, 0); | 6179 | MEGASAS_MAX_PD_CHANNELS + i, j, 0); |
5703 | if (instance->ld_ids[ld_index] != 0xff) { | 6180 | if (instance->ld_ids[ld_index] |
5704 | if (!sdev1) { | 6181 | != 0xff) { |
5705 | scsi_add_device(host, | 6182 | if (!sdev1) |
5706 | MEGASAS_MAX_PD_CHANNELS + i, | 6183 | scsi_add_device(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0); |
5707 | j, 0); | 6184 | else |
6185 | scsi_device_put(sdev1); | ||
5708 | } else { | 6186 | } else { |
5709 | scsi_device_put(sdev1); | 6187 | if (sdev1) { |
5710 | } | 6188 | scsi_remove_device(sdev1); |
5711 | } else { | 6189 | scsi_device_put(sdev1); |
5712 | if (sdev1) { | 6190 | } |
5713 | scsi_remove_device(sdev1); | ||
5714 | scsi_device_put(sdev1); | ||
5715 | } | 6191 | } |
5716 | } | 6192 | } |
5717 | } | 6193 | } |
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 99b7bffb36fe..22600419ae9f 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c | |||
@@ -62,7 +62,8 @@ megasas_complete_cmd(struct megasas_instance *instance, | |||
62 | struct megasas_cmd *cmd, u8 alt_status); | 62 | struct megasas_cmd *cmd, u8 alt_status); |
63 | int megasas_is_ldio(struct scsi_cmnd *cmd); | 63 | int megasas_is_ldio(struct scsi_cmnd *cmd); |
64 | int | 64 | int |
65 | wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd); | 65 | wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd, |
66 | int seconds); | ||
66 | 67 | ||
67 | void | 68 | void |
68 | megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd); | 69 | megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd); |
@@ -81,6 +82,13 @@ int megasas_transition_to_ready(struct megasas_instance *instance, int ocr); | |||
81 | void megaraid_sas_kill_hba(struct megasas_instance *instance); | 82 | void megaraid_sas_kill_hba(struct megasas_instance *instance); |
82 | 83 | ||
83 | extern u32 megasas_dbg_lvl; | 84 | extern u32 megasas_dbg_lvl; |
85 | void megasas_sriov_heartbeat_handler(unsigned long instance_addr); | ||
86 | int megasas_sriov_start_heartbeat(struct megasas_instance *instance, | ||
87 | int initial); | ||
88 | void megasas_start_timer(struct megasas_instance *instance, | ||
89 | struct timer_list *timer, | ||
90 | void *fn, unsigned long interval); | ||
91 | extern struct megasas_mgmt_info megasas_mgmt_info; | ||
84 | extern int resetwaittime; | 92 | extern int resetwaittime; |
85 | 93 | ||
86 | /** | 94 | /** |
@@ -549,12 +557,13 @@ fail_req_desc: | |||
549 | * For polling, MFI requires the cmd_status to be set to 0xFF before posting. | 557 | * For polling, MFI requires the cmd_status to be set to 0xFF before posting. |
550 | */ | 558 | */ |
551 | int | 559 | int |
552 | wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd) | 560 | wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd, |
561 | int seconds) | ||
553 | { | 562 | { |
554 | int i; | 563 | int i; |
555 | struct megasas_header *frame_hdr = &cmd->frame->hdr; | 564 | struct megasas_header *frame_hdr = &cmd->frame->hdr; |
556 | 565 | ||
557 | u32 msecs = MFI_POLL_TIMEOUT_SECS * 1000; | 566 | u32 msecs = seconds * 1000; |
558 | 567 | ||
559 | /* | 568 | /* |
560 | * Wait for cmd_status to change | 569 | * Wait for cmd_status to change |
@@ -672,7 +681,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) | |||
672 | instance->instancet->fire_cmd(instance, req_desc.u.low, | 681 | instance->instancet->fire_cmd(instance, req_desc.u.low, |
673 | req_desc.u.high, instance->reg_set); | 682 | req_desc.u.high, instance->reg_set); |
674 | 683 | ||
675 | wait_and_poll(instance, cmd); | 684 | wait_and_poll(instance, cmd, MFI_POLL_TIMEOUT_SECS); |
676 | 685 | ||
677 | frame_hdr = &cmd->frame->hdr; | 686 | frame_hdr = &cmd->frame->hdr; |
678 | if (frame_hdr->cmd_status != 0) { | 687 | if (frame_hdr->cmd_status != 0) { |
@@ -1772,7 +1781,8 @@ megasas_get_request_descriptor(struct megasas_instance *instance, u16 index) | |||
1772 | 1781 | ||
1773 | if (index >= instance->max_fw_cmds) { | 1782 | if (index >= instance->max_fw_cmds) { |
1774 | printk(KERN_ERR "megasas: Invalid SMID (0x%x)request for " | 1783 | printk(KERN_ERR "megasas: Invalid SMID (0x%x)request for " |
1775 | "descriptor\n", index); | 1784 | "descriptor for scsi%d\n", index, |
1785 | instance->host->host_no); | ||
1776 | return NULL; | 1786 | return NULL; |
1777 | } | 1787 | } |
1778 | fusion = instance->ctrl_context; | 1788 | fusion = instance->ctrl_context; |
@@ -2040,8 +2050,11 @@ irqreturn_t megasas_isr_fusion(int irq, void *devp) | |||
2040 | /* If we didn't complete any commands, check for FW fault */ | 2050 | /* If we didn't complete any commands, check for FW fault */ |
2041 | fw_state = instance->instancet->read_fw_status_reg( | 2051 | fw_state = instance->instancet->read_fw_status_reg( |
2042 | instance->reg_set) & MFI_STATE_MASK; | 2052 | instance->reg_set) & MFI_STATE_MASK; |
2043 | if (fw_state == MFI_STATE_FAULT) | 2053 | if (fw_state == MFI_STATE_FAULT) { |
2054 | printk(KERN_WARNING "megaraid_sas: Iop2SysDoorbellInt" | ||
2055 | "for scsi%d\n", instance->host->host_no); | ||
2044 | schedule_work(&instance->work_init); | 2056 | schedule_work(&instance->work_init); |
2057 | } | ||
2045 | } | 2058 | } |
2046 | 2059 | ||
2047 | return IRQ_HANDLED; | 2060 | return IRQ_HANDLED; |
@@ -2212,9 +2225,10 @@ megasas_check_reset_fusion(struct megasas_instance *instance, | |||
2212 | } | 2225 | } |
2213 | 2226 | ||
2214 | /* This function waits for outstanding commands on fusion to complete */ | 2227 | /* This function waits for outstanding commands on fusion to complete */ |
2215 | int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance) | 2228 | int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance, |
2229 | int iotimeout, int *convert) | ||
2216 | { | 2230 | { |
2217 | int i, outstanding, retval = 0; | 2231 | int i, outstanding, retval = 0, hb_seconds_missed = 0; |
2218 | u32 fw_state; | 2232 | u32 fw_state; |
2219 | 2233 | ||
2220 | for (i = 0; i < resetwaittime; i++) { | 2234 | for (i = 0; i < resetwaittime; i++) { |
@@ -2223,18 +2237,49 @@ int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance) | |||
2223 | instance->reg_set) & MFI_STATE_MASK; | 2237 | instance->reg_set) & MFI_STATE_MASK; |
2224 | if (fw_state == MFI_STATE_FAULT) { | 2238 | if (fw_state == MFI_STATE_FAULT) { |
2225 | printk(KERN_WARNING "megasas: Found FW in FAULT state," | 2239 | printk(KERN_WARNING "megasas: Found FW in FAULT state," |
2226 | " will reset adapter.\n"); | 2240 | " will reset adapter scsi%d.\n", |
2241 | instance->host->host_no); | ||
2242 | retval = 1; | ||
2243 | goto out; | ||
2244 | } | ||
2245 | /* If SR-IOV VF mode & heartbeat timeout, don't wait */ | ||
2246 | if (instance->requestorId && !iotimeout) { | ||
2227 | retval = 1; | 2247 | retval = 1; |
2228 | goto out; | 2248 | goto out; |
2229 | } | 2249 | } |
2230 | 2250 | ||
2251 | /* If SR-IOV VF mode & I/O timeout, check for HB timeout */ | ||
2252 | if (instance->requestorId && iotimeout) { | ||
2253 | if (instance->hb_host_mem->HB.fwCounter != | ||
2254 | instance->hb_host_mem->HB.driverCounter) { | ||
2255 | instance->hb_host_mem->HB.driverCounter = | ||
2256 | instance->hb_host_mem->HB.fwCounter; | ||
2257 | hb_seconds_missed = 0; | ||
2258 | } else { | ||
2259 | hb_seconds_missed++; | ||
2260 | if (hb_seconds_missed == | ||
2261 | (MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF/HZ)) { | ||
2262 | printk(KERN_WARNING "megasas: SR-IOV:" | ||
2263 | " Heartbeat never completed " | ||
2264 | " while polling during I/O " | ||
2265 | " timeout handling for " | ||
2266 | "scsi%d.\n", | ||
2267 | instance->host->host_no); | ||
2268 | *convert = 1; | ||
2269 | retval = 1; | ||
2270 | goto out; | ||
2271 | } | ||
2272 | } | ||
2273 | } | ||
2274 | |||
2231 | outstanding = atomic_read(&instance->fw_outstanding); | 2275 | outstanding = atomic_read(&instance->fw_outstanding); |
2232 | if (!outstanding) | 2276 | if (!outstanding) |
2233 | goto out; | 2277 | goto out; |
2234 | 2278 | ||
2235 | if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { | 2279 | if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { |
2236 | printk(KERN_NOTICE "megasas: [%2d]waiting for %d " | 2280 | printk(KERN_NOTICE "megasas: [%2d]waiting for %d " |
2237 | "commands to complete\n", i, outstanding); | 2281 | "commands to complete for scsi%d\n", i, |
2282 | outstanding, instance->host->host_no); | ||
2238 | megasas_complete_cmd_dpc_fusion( | 2283 | megasas_complete_cmd_dpc_fusion( |
2239 | (unsigned long)instance); | 2284 | (unsigned long)instance); |
2240 | } | 2285 | } |
@@ -2243,7 +2288,8 @@ int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance) | |||
2243 | 2288 | ||
2244 | if (atomic_read(&instance->fw_outstanding)) { | 2289 | if (atomic_read(&instance->fw_outstanding)) { |
2245 | printk("megaraid_sas: pending commands remain after waiting, " | 2290 | printk("megaraid_sas: pending commands remain after waiting, " |
2246 | "will reset adapter.\n"); | 2291 | "will reset adapter scsi%d.\n", |
2292 | instance->host->host_no); | ||
2247 | retval = 1; | 2293 | retval = 1; |
2248 | } | 2294 | } |
2249 | out: | 2295 | out: |
@@ -2265,10 +2311,34 @@ void megasas_reset_reply_desc(struct megasas_instance *instance) | |||
2265 | reply_desc->Words = ULLONG_MAX; | 2311 | reply_desc->Words = ULLONG_MAX; |
2266 | } | 2312 | } |
2267 | 2313 | ||
2314 | /* Check for a second path that is currently UP */ | ||
2315 | int megasas_check_mpio_paths(struct megasas_instance *instance, | ||
2316 | struct scsi_cmnd *scmd) | ||
2317 | { | ||
2318 | int i, j, retval = (DID_RESET << 16); | ||
2319 | |||
2320 | if (instance->mpio && instance->requestorId) { | ||
2321 | for (i = 0 ; i < MAX_MGMT_ADAPTERS ; i++) | ||
2322 | for (j = 0 ; j < MAX_LOGICAL_DRIVES; j++) | ||
2323 | if (megasas_mgmt_info.instance[i] && | ||
2324 | (megasas_mgmt_info.instance[i] != instance) && | ||
2325 | megasas_mgmt_info.instance[i]->mpio && | ||
2326 | megasas_mgmt_info.instance[i]->requestorId | ||
2327 | && | ||
2328 | (megasas_mgmt_info.instance[i]->ld_ids[j] | ||
2329 | == scmd->device->id)) { | ||
2330 | retval = (DID_NO_CONNECT << 16); | ||
2331 | goto out; | ||
2332 | } | ||
2333 | } | ||
2334 | out: | ||
2335 | return retval; | ||
2336 | } | ||
2337 | |||
2268 | /* Core fusion reset function */ | 2338 | /* Core fusion reset function */ |
2269 | int megasas_reset_fusion(struct Scsi_Host *shost) | 2339 | int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout) |
2270 | { | 2340 | { |
2271 | int retval = SUCCESS, i, j, retry = 0; | 2341 | int retval = SUCCESS, i, j, retry = 0, convert = 0; |
2272 | struct megasas_instance *instance; | 2342 | struct megasas_instance *instance; |
2273 | struct megasas_cmd_fusion *cmd_fusion; | 2343 | struct megasas_cmd_fusion *cmd_fusion; |
2274 | struct fusion_context *fusion; | 2344 | struct fusion_context *fusion; |
@@ -2279,28 +2349,39 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
2279 | instance = (struct megasas_instance *)shost->hostdata; | 2349 | instance = (struct megasas_instance *)shost->hostdata; |
2280 | fusion = instance->ctrl_context; | 2350 | fusion = instance->ctrl_context; |
2281 | 2351 | ||
2352 | mutex_lock(&instance->reset_mutex); | ||
2353 | |||
2282 | if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { | 2354 | if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { |
2283 | printk(KERN_WARNING "megaraid_sas: Hardware critical error, " | 2355 | printk(KERN_WARNING "megaraid_sas: Hardware critical error, " |
2284 | "returning FAILED.\n"); | 2356 | "returning FAILED for scsi%d.\n", |
2357 | instance->host->host_no); | ||
2285 | return FAILED; | 2358 | return FAILED; |
2286 | } | 2359 | } |
2287 | 2360 | ||
2288 | mutex_lock(&instance->reset_mutex); | 2361 | if (instance->requestorId && !instance->skip_heartbeat_timer_del) |
2362 | del_timer_sync(&instance->sriov_heartbeat_timer); | ||
2289 | set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); | 2363 | set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); |
2290 | instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; | 2364 | instance->adprecovery = MEGASAS_ADPRESET_SM_POLLING; |
2291 | instance->instancet->disable_intr(instance); | 2365 | instance->instancet->disable_intr(instance); |
2292 | msleep(1000); | 2366 | msleep(1000); |
2293 | 2367 | ||
2294 | /* First try waiting for commands to complete */ | 2368 | /* First try waiting for commands to complete */ |
2295 | if (megasas_wait_for_outstanding_fusion(instance)) { | 2369 | if (megasas_wait_for_outstanding_fusion(instance, iotimeout, |
2370 | &convert)) { | ||
2371 | instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; | ||
2296 | printk(KERN_WARNING "megaraid_sas: resetting fusion " | 2372 | printk(KERN_WARNING "megaraid_sas: resetting fusion " |
2297 | "adapter.\n"); | 2373 | "adapter scsi%d.\n", instance->host->host_no); |
2374 | if (convert) | ||
2375 | iotimeout = 0; | ||
2376 | |||
2298 | /* Now return commands back to the OS */ | 2377 | /* Now return commands back to the OS */ |
2299 | for (i = 0 ; i < instance->max_fw_cmds; i++) { | 2378 | for (i = 0 ; i < instance->max_fw_cmds; i++) { |
2300 | cmd_fusion = fusion->cmd_list[i]; | 2379 | cmd_fusion = fusion->cmd_list[i]; |
2301 | if (cmd_fusion->scmd) { | 2380 | if (cmd_fusion->scmd) { |
2302 | scsi_dma_unmap(cmd_fusion->scmd); | 2381 | scsi_dma_unmap(cmd_fusion->scmd); |
2303 | cmd_fusion->scmd->result = (DID_RESET << 16); | 2382 | cmd_fusion->scmd->result = |
2383 | megasas_check_mpio_paths(instance, | ||
2384 | cmd_fusion->scmd); | ||
2304 | cmd_fusion->scmd->scsi_done(cmd_fusion->scmd); | 2385 | cmd_fusion->scmd->scsi_done(cmd_fusion->scmd); |
2305 | megasas_return_cmd_fusion(instance, cmd_fusion); | 2386 | megasas_return_cmd_fusion(instance, cmd_fusion); |
2306 | atomic_dec(&instance->fw_outstanding); | 2387 | atomic_dec(&instance->fw_outstanding); |
@@ -2315,13 +2396,67 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
2315 | (abs_state == MFI_STATE_FAULT && !reset_adapter)) { | 2396 | (abs_state == MFI_STATE_FAULT && !reset_adapter)) { |
2316 | /* Reset not supported, kill adapter */ | 2397 | /* Reset not supported, kill adapter */ |
2317 | printk(KERN_WARNING "megaraid_sas: Reset not supported" | 2398 | printk(KERN_WARNING "megaraid_sas: Reset not supported" |
2318 | ", killing adapter.\n"); | 2399 | ", killing adapter scsi%d.\n", |
2400 | instance->host->host_no); | ||
2319 | megaraid_sas_kill_hba(instance); | 2401 | megaraid_sas_kill_hba(instance); |
2402 | instance->skip_heartbeat_timer_del = 1; | ||
2320 | instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR; | 2403 | instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR; |
2321 | retval = FAILED; | 2404 | retval = FAILED; |
2322 | goto out; | 2405 | goto out; |
2323 | } | 2406 | } |
2324 | 2407 | ||
2408 | /* Let SR-IOV VF & PF sync up if there was a HB failure */ | ||
2409 | if (instance->requestorId && !iotimeout) { | ||
2410 | msleep(MEGASAS_OCR_SETTLE_TIME_VF); | ||
2411 | /* Look for a late HB update after VF settle time */ | ||
2412 | if (abs_state == MFI_STATE_OPERATIONAL && | ||
2413 | (instance->hb_host_mem->HB.fwCounter != | ||
2414 | instance->hb_host_mem->HB.driverCounter)) { | ||
2415 | instance->hb_host_mem->HB.driverCounter = | ||
2416 | instance->hb_host_mem->HB.fwCounter; | ||
2417 | printk(KERN_WARNING "megasas: SR-IOV:" | ||
2418 | "Late FW heartbeat update for " | ||
2419 | "scsi%d.\n", | ||
2420 | instance->host->host_no); | ||
2421 | } else { | ||
2422 | /* In VF mode, first poll for FW ready */ | ||
2423 | for (i = 0; | ||
2424 | i < (MEGASAS_RESET_WAIT_TIME * 1000); | ||
2425 | i += 20) { | ||
2426 | status_reg = | ||
2427 | instance->instancet-> | ||
2428 | read_fw_status_reg( | ||
2429 | instance->reg_set); | ||
2430 | abs_state = status_reg & | ||
2431 | MFI_STATE_MASK; | ||
2432 | if (abs_state == MFI_STATE_READY) { | ||
2433 | printk(KERN_WARNING "megasas" | ||
2434 | ": SR-IOV: FW was found" | ||
2435 | "to be in ready state " | ||
2436 | "for scsi%d.\n", | ||
2437 | instance->host->host_no); | ||
2438 | break; | ||
2439 | } | ||
2440 | msleep(20); | ||
2441 | } | ||
2442 | if (abs_state != MFI_STATE_READY) { | ||
2443 | printk(KERN_WARNING "megasas: SR-IOV: " | ||
2444 | "FW not in ready state after %d" | ||
2445 | " seconds for scsi%d, status_reg = " | ||
2446 | "0x%x.\n", | ||
2447 | MEGASAS_RESET_WAIT_TIME, | ||
2448 | instance->host->host_no, | ||
2449 | status_reg); | ||
2450 | megaraid_sas_kill_hba(instance); | ||
2451 | instance->skip_heartbeat_timer_del = 1; | ||
2452 | instance->adprecovery = | ||
2453 | MEGASAS_HW_CRITICAL_ERROR; | ||
2454 | retval = FAILED; | ||
2455 | goto out; | ||
2456 | } | ||
2457 | } | ||
2458 | } | ||
2459 | |||
2325 | /* Now try to reset the chip */ | 2460 | /* Now try to reset the chip */ |
2326 | for (i = 0; i < MEGASAS_FUSION_MAX_RESET_TRIES; i++) { | 2461 | for (i = 0; i < MEGASAS_FUSION_MAX_RESET_TRIES; i++) { |
2327 | writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, | 2462 | writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, |
@@ -2348,7 +2483,9 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
2348 | readl(&instance->reg_set->fusion_host_diag); | 2483 | readl(&instance->reg_set->fusion_host_diag); |
2349 | if (retry++ == 100) { | 2484 | if (retry++ == 100) { |
2350 | printk(KERN_WARNING "megaraid_sas: " | 2485 | printk(KERN_WARNING "megaraid_sas: " |
2351 | "Host diag unlock failed!\n"); | 2486 | "Host diag unlock failed! " |
2487 | "for scsi%d\n", | ||
2488 | instance->host->host_no); | ||
2352 | break; | 2489 | break; |
2353 | } | 2490 | } |
2354 | } | 2491 | } |
@@ -2370,7 +2507,8 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
2370 | if (retry++ == 1000) { | 2507 | if (retry++ == 1000) { |
2371 | printk(KERN_WARNING "megaraid_sas: " | 2508 | printk(KERN_WARNING "megaraid_sas: " |
2372 | "Diag reset adapter never " | 2509 | "Diag reset adapter never " |
2373 | "cleared!\n"); | 2510 | "cleared for scsi%d!\n", |
2511 | instance->host->host_no); | ||
2374 | break; | 2512 | break; |
2375 | } | 2513 | } |
2376 | } | 2514 | } |
@@ -2392,29 +2530,29 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
2392 | if (abs_state <= MFI_STATE_FW_INIT) { | 2530 | if (abs_state <= MFI_STATE_FW_INIT) { |
2393 | printk(KERN_WARNING "megaraid_sas: firmware " | 2531 | printk(KERN_WARNING "megaraid_sas: firmware " |
2394 | "state < MFI_STATE_FW_INIT, state = " | 2532 | "state < MFI_STATE_FW_INIT, state = " |
2395 | "0x%x\n", abs_state); | 2533 | "0x%x for scsi%d\n", abs_state, |
2534 | instance->host->host_no); | ||
2396 | continue; | 2535 | continue; |
2397 | } | 2536 | } |
2398 | 2537 | ||
2399 | /* Wait for FW to become ready */ | 2538 | /* Wait for FW to become ready */ |
2400 | if (megasas_transition_to_ready(instance, 1)) { | 2539 | if (megasas_transition_to_ready(instance, 1)) { |
2401 | printk(KERN_WARNING "megaraid_sas: Failed to " | 2540 | printk(KERN_WARNING "megaraid_sas: Failed to " |
2402 | "transition controller to ready.\n"); | 2541 | "transition controller to ready " |
2542 | "for scsi%d.\n", | ||
2543 | instance->host->host_no); | ||
2403 | continue; | 2544 | continue; |
2404 | } | 2545 | } |
2405 | 2546 | ||
2406 | megasas_reset_reply_desc(instance); | 2547 | megasas_reset_reply_desc(instance); |
2407 | if (megasas_ioc_init_fusion(instance)) { | 2548 | if (megasas_ioc_init_fusion(instance)) { |
2408 | printk(KERN_WARNING "megaraid_sas: " | 2549 | printk(KERN_WARNING "megaraid_sas: " |
2409 | "megasas_ioc_init_fusion() failed!\n"); | 2550 | "megasas_ioc_init_fusion() failed!" |
2551 | " for scsi%d\n", | ||
2552 | instance->host->host_no); | ||
2410 | continue; | 2553 | continue; |
2411 | } | 2554 | } |
2412 | 2555 | ||
2413 | clear_bit(MEGASAS_FUSION_IN_RESET, | ||
2414 | &instance->reset_flags); | ||
2415 | instance->instancet->enable_intr(instance); | ||
2416 | instance->adprecovery = MEGASAS_HBA_OPERATIONAL; | ||
2417 | |||
2418 | /* Re-fire management commands */ | 2556 | /* Re-fire management commands */ |
2419 | for (j = 0 ; j < instance->max_fw_cmds; j++) { | 2557 | for (j = 0 ; j < instance->max_fw_cmds; j++) { |
2420 | cmd_fusion = fusion->cmd_list[j]; | 2558 | cmd_fusion = fusion->cmd_list[j]; |
@@ -2438,7 +2576,8 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
2438 | if (!req_desc) { | 2576 | if (!req_desc) { |
2439 | printk(KERN_WARNING | 2577 | printk(KERN_WARNING |
2440 | "req_desc NULL" | 2578 | "req_desc NULL" |
2441 | "\n"); | 2579 | " for scsi%d\n", |
2580 | instance->host->host_no); | ||
2442 | /* Return leaked MPT | 2581 | /* Return leaked MPT |
2443 | frame */ | 2582 | frame */ |
2444 | megasas_return_cmd_fusion(instance, cmd_fusion); | 2583 | megasas_return_cmd_fusion(instance, cmd_fusion); |
@@ -2456,6 +2595,11 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
2456 | } | 2595 | } |
2457 | } | 2596 | } |
2458 | 2597 | ||
2598 | clear_bit(MEGASAS_FUSION_IN_RESET, | ||
2599 | &instance->reset_flags); | ||
2600 | instance->instancet->enable_intr(instance); | ||
2601 | instance->adprecovery = MEGASAS_HBA_OPERATIONAL; | ||
2602 | |||
2459 | /* Reset load balance info */ | 2603 | /* Reset load balance info */ |
2460 | memset(fusion->load_balance_info, 0, | 2604 | memset(fusion->load_balance_info, 0, |
2461 | sizeof(struct LD_LOAD_BALANCE_INFO) | 2605 | sizeof(struct LD_LOAD_BALANCE_INFO) |
@@ -2464,19 +2608,39 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
2464 | if (!megasas_get_map_info(instance)) | 2608 | if (!megasas_get_map_info(instance)) |
2465 | megasas_sync_map_info(instance); | 2609 | megasas_sync_map_info(instance); |
2466 | 2610 | ||
2611 | /* Restart SR-IOV heartbeat */ | ||
2612 | if (instance->requestorId) { | ||
2613 | if (!megasas_sriov_start_heartbeat(instance, 0)) | ||
2614 | megasas_start_timer(instance, | ||
2615 | &instance->sriov_heartbeat_timer, | ||
2616 | megasas_sriov_heartbeat_handler, | ||
2617 | MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF); | ||
2618 | else | ||
2619 | instance->skip_heartbeat_timer_del = 1; | ||
2620 | } | ||
2621 | |||
2467 | /* Adapter reset completed successfully */ | 2622 | /* Adapter reset completed successfully */ |
2468 | printk(KERN_WARNING "megaraid_sas: Reset " | 2623 | printk(KERN_WARNING "megaraid_sas: Reset " |
2469 | "successful.\n"); | 2624 | "successful for scsi%d.\n", |
2625 | instance->host->host_no); | ||
2470 | retval = SUCCESS; | 2626 | retval = SUCCESS; |
2471 | goto out; | 2627 | goto out; |
2472 | } | 2628 | } |
2473 | /* Reset failed, kill the adapter */ | 2629 | /* Reset failed, kill the adapter */ |
2474 | printk(KERN_WARNING "megaraid_sas: Reset failed, killing " | 2630 | printk(KERN_WARNING "megaraid_sas: Reset failed, killing " |
2475 | "adapter.\n"); | 2631 | "adapter scsi%d.\n", instance->host->host_no); |
2476 | megaraid_sas_kill_hba(instance); | 2632 | megaraid_sas_kill_hba(instance); |
2633 | instance->skip_heartbeat_timer_del = 1; | ||
2477 | instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR; | 2634 | instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR; |
2478 | retval = FAILED; | 2635 | retval = FAILED; |
2479 | } else { | 2636 | } else { |
2637 | /* For VF: Restart HB timer if we didn't OCR */ | ||
2638 | if (instance->requestorId) { | ||
2639 | megasas_start_timer(instance, | ||
2640 | &instance->sriov_heartbeat_timer, | ||
2641 | megasas_sriov_heartbeat_handler, | ||
2642 | MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF); | ||
2643 | } | ||
2480 | clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); | 2644 | clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); |
2481 | instance->instancet->enable_intr(instance); | 2645 | instance->instancet->enable_intr(instance); |
2482 | instance->adprecovery = MEGASAS_HBA_OPERATIONAL; | 2646 | instance->adprecovery = MEGASAS_HBA_OPERATIONAL; |
@@ -2493,7 +2657,7 @@ void megasas_fusion_ocr_wq(struct work_struct *work) | |||
2493 | struct megasas_instance *instance = | 2657 | struct megasas_instance *instance = |
2494 | container_of(work, struct megasas_instance, work_init); | 2658 | container_of(work, struct megasas_instance, work_init); |
2495 | 2659 | ||
2496 | megasas_reset_fusion(instance->host); | 2660 | megasas_reset_fusion(instance->host, 0); |
2497 | } | 2661 | } |
2498 | 2662 | ||
2499 | struct megasas_instance_template megasas_instance_template_fusion = { | 2663 | struct megasas_instance_template megasas_instance_template_fusion = { |
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h index 35a51397b364..e76af5459a09 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.h +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h | |||
@@ -485,6 +485,9 @@ struct MPI2_IOC_INIT_REQUEST { | |||
485 | #define MAX_PHYSICAL_DEVICES 256 | 485 | #define MAX_PHYSICAL_DEVICES 256 |
486 | #define MAX_RAIDMAP_PHYSICAL_DEVICES (MAX_PHYSICAL_DEVICES) | 486 | #define MAX_RAIDMAP_PHYSICAL_DEVICES (MAX_PHYSICAL_DEVICES) |
487 | #define MR_DCMD_LD_MAP_GET_INFO 0x0300e101 | 487 | #define MR_DCMD_LD_MAP_GET_INFO 0x0300e101 |
488 | #define MR_DCMD_CTRL_SHARED_HOST_MEM_ALLOC 0x010e8485 /* SR-IOV HB alloc*/ | ||
489 | #define MR_DCMD_LD_VF_MAP_GET_ALL_LDS_111 0x03200200 | ||
490 | #define MR_DCMD_LD_VF_MAP_GET_ALL_LDS 0x03150200 | ||
488 | 491 | ||
489 | struct MR_DEV_HANDLE_INFO { | 492 | struct MR_DEV_HANDLE_INFO { |
490 | u16 curDevHdl; | 493 | u16 curDevHdl; |