You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
[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>
This commit is contained in:
committed by
James Bottomley
parent
3d0c24cd9b
commit
229fe47cd0
@@ -48,6 +48,7 @@
|
||||
#define PCI_DEVICE_ID_LSI_SAS0073SKINNY 0x0073
|
||||
#define PCI_DEVICE_ID_LSI_SAS0071SKINNY 0x0071
|
||||
#define PCI_DEVICE_ID_LSI_FUSION 0x005b
|
||||
#define PCI_DEVICE_ID_LSI_PLASMA 0x002f
|
||||
#define PCI_DEVICE_ID_LSI_INVADER 0x005d
|
||||
#define PCI_DEVICE_ID_LSI_FURY 0x005f
|
||||
|
||||
@@ -559,7 +560,8 @@ struct megasas_ctrl_info {
|
||||
u8 PCIE:1;
|
||||
u8 iSCSI:1;
|
||||
u8 SAS_3G:1;
|
||||
u8 reserved_0:4;
|
||||
u8 SRIOV:1;
|
||||
u8 reserved_0:3;
|
||||
u8 reserved_1[6];
|
||||
u8 port_count;
|
||||
u64 port_addr[8];
|
||||
@@ -839,7 +841,12 @@ struct megasas_ctrl_info {
|
||||
|
||||
struct { /*7A4h */
|
||||
#if defined(__BIG_ENDIAN_BITFIELD)
|
||||
u32 reserved:11;
|
||||
u32 reserved:5;
|
||||
u32 activePassive:2;
|
||||
u32 supportConfigAutoBalance:1;
|
||||
u32 mpio:1;
|
||||
u32 supportDataLDonSSCArray:1;
|
||||
u32 supportPointInTimeProgress:1;
|
||||
u32 supportUnevenSpans:1;
|
||||
u32 dedicatedHotSparesLimited:1;
|
||||
u32 headlessMode:1;
|
||||
@@ -886,7 +893,12 @@ struct megasas_ctrl_info {
|
||||
|
||||
|
||||
u32 supportUnevenSpans:1;
|
||||
u32 reserved:11;
|
||||
u32 supportPointInTimeProgress:1;
|
||||
u32 supportDataLDonSSCArray:1;
|
||||
u32 mpio:1;
|
||||
u32 supportConfigAutoBalance:1;
|
||||
u32 activePassive:2;
|
||||
u32 reserved:5;
|
||||
#endif
|
||||
} adapterOperations2;
|
||||
|
||||
@@ -914,8 +926,14 @@ struct megasas_ctrl_info {
|
||||
} cluster;
|
||||
|
||||
char clusterId[16]; /*7D4h */
|
||||
struct {
|
||||
u8 maxVFsSupported; /*0x7E4*/
|
||||
u8 numVFsEnabled; /*0x7E5*/
|
||||
u8 requestorId; /*0x7E6 0:PF, 1:VF1, 2:VF2*/
|
||||
u8 reserved; /*0x7E7*/
|
||||
} iov;
|
||||
|
||||
u8 pad[0x800-0x7E4]; /*7E4 */
|
||||
u8 pad[0x800-0x7E8]; /*0x7E8 pad to 2k */
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
@@ -986,7 +1004,9 @@ struct megasas_ctrl_info {
|
||||
|
||||
#define MFI_OB_INTR_STATUS_MASK 0x00000002
|
||||
#define MFI_POLL_TIMEOUT_SECS 60
|
||||
|
||||
#define MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF (5 * HZ)
|
||||
#define MEGASAS_OCR_SETTLE_TIME_VF (1000 * 30)
|
||||
#define MEGASAS_ROUTINE_WAIT_TIME_VF 300
|
||||
#define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000
|
||||
#define MFI_REPLY_GEN2_MESSAGE_INTERRUPT 0x00000001
|
||||
#define MFI_GEN2_ENABLE_INTERRUPT_MASK (0x00000001 | 0x00000004)
|
||||
@@ -1529,6 +1549,12 @@ struct megasas_instance {
|
||||
dma_addr_t producer_h;
|
||||
u32 *consumer;
|
||||
dma_addr_t consumer_h;
|
||||
struct MR_LD_VF_AFFILIATION *vf_affiliation;
|
||||
dma_addr_t vf_affiliation_h;
|
||||
struct MR_LD_VF_AFFILIATION_111 *vf_affiliation_111;
|
||||
dma_addr_t vf_affiliation_111_h;
|
||||
struct MR_CTRL_HB_HOST_MEM *hb_host_mem;
|
||||
dma_addr_t hb_host_mem_h;
|
||||
|
||||
u32 *reply_queue;
|
||||
dma_addr_t reply_queue_h;
|
||||
@@ -1604,10 +1630,73 @@ struct megasas_instance {
|
||||
unsigned long bar;
|
||||
long reset_flags;
|
||||
struct mutex reset_mutex;
|
||||
struct timer_list sriov_heartbeat_timer;
|
||||
char skip_heartbeat_timer_del;
|
||||
u8 requestorId;
|
||||
u64 initiator_sas_address;
|
||||
u64 ld_sas_address[64];
|
||||
char PlasmaFW111;
|
||||
char mpio;
|
||||
int throttlequeuedepth;
|
||||
u8 mask_interrupts;
|
||||
u8 is_imr;
|
||||
};
|
||||
struct MR_LD_VF_MAP {
|
||||
u32 size;
|
||||
union MR_LD_REF ref;
|
||||
u8 ldVfCount;
|
||||
u8 reserved[6];
|
||||
u8 policy[1];
|
||||
};
|
||||
|
||||
struct MR_LD_VF_AFFILIATION {
|
||||
u32 size;
|
||||
u8 ldCount;
|
||||
u8 vfCount;
|
||||
u8 thisVf;
|
||||
u8 reserved[9];
|
||||
struct MR_LD_VF_MAP map[1];
|
||||
};
|
||||
|
||||
/* Plasma 1.11 FW backward compatibility structures */
|
||||
#define IOV_111_OFFSET 0x7CE
|
||||
#define MAX_VIRTUAL_FUNCTIONS 8
|
||||
|
||||
struct IOV_111 {
|
||||
u8 maxVFsSupported;
|
||||
u8 numVFsEnabled;
|
||||
u8 requestorId;
|
||||
u8 reserved[5];
|
||||
};
|
||||
|
||||
struct MR_LD_VF_MAP_111 {
|
||||
u8 targetId;
|
||||
u8 reserved[3];
|
||||
u8 policy[MAX_VIRTUAL_FUNCTIONS];
|
||||
};
|
||||
|
||||
struct MR_LD_VF_AFFILIATION_111 {
|
||||
u8 vdCount;
|
||||
u8 vfCount;
|
||||
u8 thisVf;
|
||||
u8 reserved[5];
|
||||
struct MR_LD_VF_MAP_111 map[MAX_LOGICAL_DRIVES];
|
||||
};
|
||||
|
||||
struct MR_CTRL_HB_HOST_MEM {
|
||||
struct {
|
||||
u32 fwCounter; /* Firmware heart beat counter */
|
||||
struct {
|
||||
u32 debugmode:1; /* 1=Firmware is in debug mode.
|
||||
Heart beat will not be updated. */
|
||||
u32 reserved:31;
|
||||
} debug;
|
||||
u32 reserved_fw[6];
|
||||
u32 driverCounter; /* Driver heart beat counter. 0x20 */
|
||||
u32 reserved_driver[7];
|
||||
} HB;
|
||||
u8 pad[0x400-0x40];
|
||||
};
|
||||
|
||||
enum {
|
||||
MEGASAS_HBA_OPERATIONAL = 0,
|
||||
@@ -1615,6 +1704,7 @@ enum {
|
||||
MEGASAS_ADPRESET_SM_FW_RESET_SUCCESS = 2,
|
||||
MEGASAS_ADPRESET_SM_OPERATIONAL = 3,
|
||||
MEGASAS_HW_CRITICAL_ERROR = 4,
|
||||
MEGASAS_ADPRESET_SM_POLLING = 5,
|
||||
MEGASAS_ADPRESET_INPROG_SIGN = 0xDEADDEAD,
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -62,7 +62,8 @@ megasas_complete_cmd(struct megasas_instance *instance,
|
||||
struct megasas_cmd *cmd, u8 alt_status);
|
||||
int megasas_is_ldio(struct scsi_cmnd *cmd);
|
||||
int
|
||||
wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd);
|
||||
wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd,
|
||||
int seconds);
|
||||
|
||||
void
|
||||
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);
|
||||
void megaraid_sas_kill_hba(struct megasas_instance *instance);
|
||||
|
||||
extern u32 megasas_dbg_lvl;
|
||||
void megasas_sriov_heartbeat_handler(unsigned long instance_addr);
|
||||
int megasas_sriov_start_heartbeat(struct megasas_instance *instance,
|
||||
int initial);
|
||||
void megasas_start_timer(struct megasas_instance *instance,
|
||||
struct timer_list *timer,
|
||||
void *fn, unsigned long interval);
|
||||
extern struct megasas_mgmt_info megasas_mgmt_info;
|
||||
extern int resetwaittime;
|
||||
|
||||
/**
|
||||
@@ -549,12 +557,13 @@ fail_req_desc:
|
||||
* For polling, MFI requires the cmd_status to be set to 0xFF before posting.
|
||||
*/
|
||||
int
|
||||
wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd)
|
||||
wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd,
|
||||
int seconds)
|
||||
{
|
||||
int i;
|
||||
struct megasas_header *frame_hdr = &cmd->frame->hdr;
|
||||
|
||||
u32 msecs = MFI_POLL_TIMEOUT_SECS * 1000;
|
||||
u32 msecs = seconds * 1000;
|
||||
|
||||
/*
|
||||
* Wait for cmd_status to change
|
||||
@@ -672,7 +681,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
|
||||
instance->instancet->fire_cmd(instance, req_desc.u.low,
|
||||
req_desc.u.high, instance->reg_set);
|
||||
|
||||
wait_and_poll(instance, cmd);
|
||||
wait_and_poll(instance, cmd, MFI_POLL_TIMEOUT_SECS);
|
||||
|
||||
frame_hdr = &cmd->frame->hdr;
|
||||
if (frame_hdr->cmd_status != 0) {
|
||||
@@ -1772,7 +1781,8 @@ megasas_get_request_descriptor(struct megasas_instance *instance, u16 index)
|
||||
|
||||
if (index >= instance->max_fw_cmds) {
|
||||
printk(KERN_ERR "megasas: Invalid SMID (0x%x)request for "
|
||||
"descriptor\n", index);
|
||||
"descriptor for scsi%d\n", index,
|
||||
instance->host->host_no);
|
||||
return NULL;
|
||||
}
|
||||
fusion = instance->ctrl_context;
|
||||
@@ -2040,8 +2050,11 @@ irqreturn_t megasas_isr_fusion(int irq, void *devp)
|
||||
/* If we didn't complete any commands, check for FW fault */
|
||||
fw_state = instance->instancet->read_fw_status_reg(
|
||||
instance->reg_set) & MFI_STATE_MASK;
|
||||
if (fw_state == MFI_STATE_FAULT)
|
||||
if (fw_state == MFI_STATE_FAULT) {
|
||||
printk(KERN_WARNING "megaraid_sas: Iop2SysDoorbellInt"
|
||||
"for scsi%d\n", instance->host->host_no);
|
||||
schedule_work(&instance->work_init);
|
||||
}
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
@@ -2212,9 +2225,10 @@ megasas_check_reset_fusion(struct megasas_instance *instance,
|
||||
}
|
||||
|
||||
/* This function waits for outstanding commands on fusion to complete */
|
||||
int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance)
|
||||
int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance,
|
||||
int iotimeout, int *convert)
|
||||
{
|
||||
int i, outstanding, retval = 0;
|
||||
int i, outstanding, retval = 0, hb_seconds_missed = 0;
|
||||
u32 fw_state;
|
||||
|
||||
for (i = 0; i < resetwaittime; i++) {
|
||||
@@ -2223,10 +2237,40 @@ int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance)
|
||||
instance->reg_set) & MFI_STATE_MASK;
|
||||
if (fw_state == MFI_STATE_FAULT) {
|
||||
printk(KERN_WARNING "megasas: Found FW in FAULT state,"
|
||||
" will reset adapter.\n");
|
||||
" will reset adapter scsi%d.\n",
|
||||
instance->host->host_no);
|
||||
retval = 1;
|
||||
goto out;
|
||||
}
|
||||
/* If SR-IOV VF mode & heartbeat timeout, don't wait */
|
||||
if (instance->requestorId && !iotimeout) {
|
||||
retval = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* If SR-IOV VF mode & I/O timeout, check for HB timeout */
|
||||
if (instance->requestorId && iotimeout) {
|
||||
if (instance->hb_host_mem->HB.fwCounter !=
|
||||
instance->hb_host_mem->HB.driverCounter) {
|
||||
instance->hb_host_mem->HB.driverCounter =
|
||||
instance->hb_host_mem->HB.fwCounter;
|
||||
hb_seconds_missed = 0;
|
||||
} else {
|
||||
hb_seconds_missed++;
|
||||
if (hb_seconds_missed ==
|
||||
(MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF/HZ)) {
|
||||
printk(KERN_WARNING "megasas: SR-IOV:"
|
||||
" Heartbeat never completed "
|
||||
" while polling during I/O "
|
||||
" timeout handling for "
|
||||
"scsi%d.\n",
|
||||
instance->host->host_no);
|
||||
*convert = 1;
|
||||
retval = 1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
outstanding = atomic_read(&instance->fw_outstanding);
|
||||
if (!outstanding)
|
||||
@@ -2234,7 +2278,8 @@ int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance)
|
||||
|
||||
if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
|
||||
printk(KERN_NOTICE "megasas: [%2d]waiting for %d "
|
||||
"commands to complete\n", i, outstanding);
|
||||
"commands to complete for scsi%d\n", i,
|
||||
outstanding, instance->host->host_no);
|
||||
megasas_complete_cmd_dpc_fusion(
|
||||
(unsigned long)instance);
|
||||
}
|
||||
@@ -2243,7 +2288,8 @@ int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance)
|
||||
|
||||
if (atomic_read(&instance->fw_outstanding)) {
|
||||
printk("megaraid_sas: pending commands remain after waiting, "
|
||||
"will reset adapter.\n");
|
||||
"will reset adapter scsi%d.\n",
|
||||
instance->host->host_no);
|
||||
retval = 1;
|
||||
}
|
||||
out:
|
||||
@@ -2265,10 +2311,34 @@ void megasas_reset_reply_desc(struct megasas_instance *instance)
|
||||
reply_desc->Words = ULLONG_MAX;
|
||||
}
|
||||
|
||||
/* Core fusion reset function */
|
||||
int megasas_reset_fusion(struct Scsi_Host *shost)
|
||||
/* Check for a second path that is currently UP */
|
||||
int megasas_check_mpio_paths(struct megasas_instance *instance,
|
||||
struct scsi_cmnd *scmd)
|
||||
{
|
||||
int retval = SUCCESS, i, j, retry = 0;
|
||||
int i, j, retval = (DID_RESET << 16);
|
||||
|
||||
if (instance->mpio && instance->requestorId) {
|
||||
for (i = 0 ; i < MAX_MGMT_ADAPTERS ; i++)
|
||||
for (j = 0 ; j < MAX_LOGICAL_DRIVES; j++)
|
||||
if (megasas_mgmt_info.instance[i] &&
|
||||
(megasas_mgmt_info.instance[i] != instance) &&
|
||||
megasas_mgmt_info.instance[i]->mpio &&
|
||||
megasas_mgmt_info.instance[i]->requestorId
|
||||
&&
|
||||
(megasas_mgmt_info.instance[i]->ld_ids[j]
|
||||
== scmd->device->id)) {
|
||||
retval = (DID_NO_CONNECT << 16);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
out:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Core fusion reset function */
|
||||
int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
|
||||
{
|
||||
int retval = SUCCESS, i, j, retry = 0, convert = 0;
|
||||
struct megasas_instance *instance;
|
||||
struct megasas_cmd_fusion *cmd_fusion;
|
||||
struct fusion_context *fusion;
|
||||
@@ -2279,28 +2349,39 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
|
||||
instance = (struct megasas_instance *)shost->hostdata;
|
||||
fusion = instance->ctrl_context;
|
||||
|
||||
mutex_lock(&instance->reset_mutex);
|
||||
|
||||
if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
|
||||
printk(KERN_WARNING "megaraid_sas: Hardware critical error, "
|
||||
"returning FAILED.\n");
|
||||
"returning FAILED for scsi%d.\n",
|
||||
instance->host->host_no);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
mutex_lock(&instance->reset_mutex);
|
||||
if (instance->requestorId && !instance->skip_heartbeat_timer_del)
|
||||
del_timer_sync(&instance->sriov_heartbeat_timer);
|
||||
set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
|
||||
instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT;
|
||||
instance->adprecovery = MEGASAS_ADPRESET_SM_POLLING;
|
||||
instance->instancet->disable_intr(instance);
|
||||
msleep(1000);
|
||||
|
||||
/* First try waiting for commands to complete */
|
||||
if (megasas_wait_for_outstanding_fusion(instance)) {
|
||||
if (megasas_wait_for_outstanding_fusion(instance, iotimeout,
|
||||
&convert)) {
|
||||
instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT;
|
||||
printk(KERN_WARNING "megaraid_sas: resetting fusion "
|
||||
"adapter.\n");
|
||||
"adapter scsi%d.\n", instance->host->host_no);
|
||||
if (convert)
|
||||
iotimeout = 0;
|
||||
|
||||
/* Now return commands back to the OS */
|
||||
for (i = 0 ; i < instance->max_fw_cmds; i++) {
|
||||
cmd_fusion = fusion->cmd_list[i];
|
||||
if (cmd_fusion->scmd) {
|
||||
scsi_dma_unmap(cmd_fusion->scmd);
|
||||
cmd_fusion->scmd->result = (DID_RESET << 16);
|
||||
cmd_fusion->scmd->result =
|
||||
megasas_check_mpio_paths(instance,
|
||||
cmd_fusion->scmd);
|
||||
cmd_fusion->scmd->scsi_done(cmd_fusion->scmd);
|
||||
megasas_return_cmd_fusion(instance, cmd_fusion);
|
||||
atomic_dec(&instance->fw_outstanding);
|
||||
@@ -2315,13 +2396,67 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
|
||||
(abs_state == MFI_STATE_FAULT && !reset_adapter)) {
|
||||
/* Reset not supported, kill adapter */
|
||||
printk(KERN_WARNING "megaraid_sas: Reset not supported"
|
||||
", killing adapter.\n");
|
||||
", killing adapter scsi%d.\n",
|
||||
instance->host->host_no);
|
||||
megaraid_sas_kill_hba(instance);
|
||||
instance->skip_heartbeat_timer_del = 1;
|
||||
instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR;
|
||||
retval = FAILED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Let SR-IOV VF & PF sync up if there was a HB failure */
|
||||
if (instance->requestorId && !iotimeout) {
|
||||
msleep(MEGASAS_OCR_SETTLE_TIME_VF);
|
||||
/* Look for a late HB update after VF settle time */
|
||||
if (abs_state == MFI_STATE_OPERATIONAL &&
|
||||
(instance->hb_host_mem->HB.fwCounter !=
|
||||
instance->hb_host_mem->HB.driverCounter)) {
|
||||
instance->hb_host_mem->HB.driverCounter =
|
||||
instance->hb_host_mem->HB.fwCounter;
|
||||
printk(KERN_WARNING "megasas: SR-IOV:"
|
||||
"Late FW heartbeat update for "
|
||||
"scsi%d.\n",
|
||||
instance->host->host_no);
|
||||
} else {
|
||||
/* In VF mode, first poll for FW ready */
|
||||
for (i = 0;
|
||||
i < (MEGASAS_RESET_WAIT_TIME * 1000);
|
||||
i += 20) {
|
||||
status_reg =
|
||||
instance->instancet->
|
||||
read_fw_status_reg(
|
||||
instance->reg_set);
|
||||
abs_state = status_reg &
|
||||
MFI_STATE_MASK;
|
||||
if (abs_state == MFI_STATE_READY) {
|
||||
printk(KERN_WARNING "megasas"
|
||||
": SR-IOV: FW was found"
|
||||
"to be in ready state "
|
||||
"for scsi%d.\n",
|
||||
instance->host->host_no);
|
||||
break;
|
||||
}
|
||||
msleep(20);
|
||||
}
|
||||
if (abs_state != MFI_STATE_READY) {
|
||||
printk(KERN_WARNING "megasas: SR-IOV: "
|
||||
"FW not in ready state after %d"
|
||||
" seconds for scsi%d, status_reg = "
|
||||
"0x%x.\n",
|
||||
MEGASAS_RESET_WAIT_TIME,
|
||||
instance->host->host_no,
|
||||
status_reg);
|
||||
megaraid_sas_kill_hba(instance);
|
||||
instance->skip_heartbeat_timer_del = 1;
|
||||
instance->adprecovery =
|
||||
MEGASAS_HW_CRITICAL_ERROR;
|
||||
retval = FAILED;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now try to reset the chip */
|
||||
for (i = 0; i < MEGASAS_FUSION_MAX_RESET_TRIES; i++) {
|
||||
writel(MPI2_WRSEQ_FLUSH_KEY_VALUE,
|
||||
@@ -2348,7 +2483,9 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
|
||||
readl(&instance->reg_set->fusion_host_diag);
|
||||
if (retry++ == 100) {
|
||||
printk(KERN_WARNING "megaraid_sas: "
|
||||
"Host diag unlock failed!\n");
|
||||
"Host diag unlock failed! "
|
||||
"for scsi%d\n",
|
||||
instance->host->host_no);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2370,7 +2507,8 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
|
||||
if (retry++ == 1000) {
|
||||
printk(KERN_WARNING "megaraid_sas: "
|
||||
"Diag reset adapter never "
|
||||
"cleared!\n");
|
||||
"cleared for scsi%d!\n",
|
||||
instance->host->host_no);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2392,29 +2530,29 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
|
||||
if (abs_state <= MFI_STATE_FW_INIT) {
|
||||
printk(KERN_WARNING "megaraid_sas: firmware "
|
||||
"state < MFI_STATE_FW_INIT, state = "
|
||||
"0x%x\n", abs_state);
|
||||
"0x%x for scsi%d\n", abs_state,
|
||||
instance->host->host_no);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Wait for FW to become ready */
|
||||
if (megasas_transition_to_ready(instance, 1)) {
|
||||
printk(KERN_WARNING "megaraid_sas: Failed to "
|
||||
"transition controller to ready.\n");
|
||||
"transition controller to ready "
|
||||
"for scsi%d.\n",
|
||||
instance->host->host_no);
|
||||
continue;
|
||||
}
|
||||
|
||||
megasas_reset_reply_desc(instance);
|
||||
if (megasas_ioc_init_fusion(instance)) {
|
||||
printk(KERN_WARNING "megaraid_sas: "
|
||||
"megasas_ioc_init_fusion() failed!\n");
|
||||
"megasas_ioc_init_fusion() failed!"
|
||||
" for scsi%d\n",
|
||||
instance->host->host_no);
|
||||
continue;
|
||||
}
|
||||
|
||||
clear_bit(MEGASAS_FUSION_IN_RESET,
|
||||
&instance->reset_flags);
|
||||
instance->instancet->enable_intr(instance);
|
||||
instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
|
||||
|
||||
/* Re-fire management commands */
|
||||
for (j = 0 ; j < instance->max_fw_cmds; j++) {
|
||||
cmd_fusion = fusion->cmd_list[j];
|
||||
@@ -2438,7 +2576,8 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
|
||||
if (!req_desc) {
|
||||
printk(KERN_WARNING
|
||||
"req_desc NULL"
|
||||
"\n");
|
||||
" for scsi%d\n",
|
||||
instance->host->host_no);
|
||||
/* Return leaked MPT
|
||||
frame */
|
||||
megasas_return_cmd_fusion(instance, cmd_fusion);
|
||||
@@ -2456,6 +2595,11 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
|
||||
}
|
||||
}
|
||||
|
||||
clear_bit(MEGASAS_FUSION_IN_RESET,
|
||||
&instance->reset_flags);
|
||||
instance->instancet->enable_intr(instance);
|
||||
instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
|
||||
|
||||
/* Reset load balance info */
|
||||
memset(fusion->load_balance_info, 0,
|
||||
sizeof(struct LD_LOAD_BALANCE_INFO)
|
||||
@@ -2464,19 +2608,39 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
|
||||
if (!megasas_get_map_info(instance))
|
||||
megasas_sync_map_info(instance);
|
||||
|
||||
/* Restart SR-IOV heartbeat */
|
||||
if (instance->requestorId) {
|
||||
if (!megasas_sriov_start_heartbeat(instance, 0))
|
||||
megasas_start_timer(instance,
|
||||
&instance->sriov_heartbeat_timer,
|
||||
megasas_sriov_heartbeat_handler,
|
||||
MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF);
|
||||
else
|
||||
instance->skip_heartbeat_timer_del = 1;
|
||||
}
|
||||
|
||||
/* Adapter reset completed successfully */
|
||||
printk(KERN_WARNING "megaraid_sas: Reset "
|
||||
"successful.\n");
|
||||
"successful for scsi%d.\n",
|
||||
instance->host->host_no);
|
||||
retval = SUCCESS;
|
||||
goto out;
|
||||
}
|
||||
/* Reset failed, kill the adapter */
|
||||
printk(KERN_WARNING "megaraid_sas: Reset failed, killing "
|
||||
"adapter.\n");
|
||||
"adapter scsi%d.\n", instance->host->host_no);
|
||||
megaraid_sas_kill_hba(instance);
|
||||
instance->skip_heartbeat_timer_del = 1;
|
||||
instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR;
|
||||
retval = FAILED;
|
||||
} else {
|
||||
/* For VF: Restart HB timer if we didn't OCR */
|
||||
if (instance->requestorId) {
|
||||
megasas_start_timer(instance,
|
||||
&instance->sriov_heartbeat_timer,
|
||||
megasas_sriov_heartbeat_handler,
|
||||
MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF);
|
||||
}
|
||||
clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
|
||||
instance->instancet->enable_intr(instance);
|
||||
instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
|
||||
@@ -2493,7 +2657,7 @@ void megasas_fusion_ocr_wq(struct work_struct *work)
|
||||
struct megasas_instance *instance =
|
||||
container_of(work, struct megasas_instance, work_init);
|
||||
|
||||
megasas_reset_fusion(instance->host);
|
||||
megasas_reset_fusion(instance->host, 0);
|
||||
}
|
||||
|
||||
struct megasas_instance_template megasas_instance_template_fusion = {
|
||||
|
||||
@@ -485,6 +485,9 @@ struct MPI2_IOC_INIT_REQUEST {
|
||||
#define MAX_PHYSICAL_DEVICES 256
|
||||
#define MAX_RAIDMAP_PHYSICAL_DEVICES (MAX_PHYSICAL_DEVICES)
|
||||
#define MR_DCMD_LD_MAP_GET_INFO 0x0300e101
|
||||
#define MR_DCMD_CTRL_SHARED_HOST_MEM_ALLOC 0x010e8485 /* SR-IOV HB alloc*/
|
||||
#define MR_DCMD_LD_VF_MAP_GET_ALL_LDS_111 0x03200200
|
||||
#define MR_DCMD_LD_VF_MAP_GET_ALL_LDS 0x03150200
|
||||
|
||||
struct MR_DEV_HANDLE_INFO {
|
||||
u16 curDevHdl;
|
||||
|
||||
Reference in New Issue
Block a user