[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:
parent
3d0c24cd9b
commit
229fe47cd0
4 changed files with 853 additions and 120 deletions
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -75,6 +75,10 @@ static unsigned int msix_vectors;
|
|||
module_param(msix_vectors, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(msix_vectors, "MSI-X max vector count. Default: Set by FW");
|
||||
|
||||
static int allow_vf_ioctls;
|
||||
module_param(allow_vf_ioctls, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(allow_vf_ioctls, "Allow ioctls in SR-IOV VF mode. Default: 0");
|
||||
|
||||
static int throttlequeuedepth = MEGASAS_THROTTLE_QUEUE_DEPTH;
|
||||
module_param(throttlequeuedepth, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(throttlequeuedepth,
|
||||
|
@ -122,6 +126,8 @@ static struct pci_device_id megasas_pci_table[] = {
|
|||
/* xscale IOP */
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FUSION)},
|
||||
/* Fusion */
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_PLASMA)},
|
||||
/* Plasma */
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_INVADER)},
|
||||
/* Invader */
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FURY)},
|
||||
|
@ -132,7 +138,7 @@ static struct pci_device_id megasas_pci_table[] = {
|
|||
MODULE_DEVICE_TABLE(pci, megasas_pci_table);
|
||||
|
||||
static int megasas_mgmt_majorno;
|
||||
static struct megasas_mgmt_info megasas_mgmt_info;
|
||||
struct megasas_mgmt_info megasas_mgmt_info;
|
||||
static struct fasync_struct *megasas_async_queue;
|
||||
static DEFINE_MUTEX(megasas_async_queue_mutex);
|
||||
|
||||
|
@ -171,10 +177,15 @@ megasas_get_map_info(struct megasas_instance *instance);
|
|||
int
|
||||
megasas_sync_map_info(struct megasas_instance *instance);
|
||||
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_reset_reply_desc(struct megasas_instance *instance);
|
||||
int megasas_reset_fusion(struct Scsi_Host *shost);
|
||||
int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout);
|
||||
void megasas_fusion_ocr_wq(struct work_struct *work);
|
||||
static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance,
|
||||
int initial);
|
||||
int megasas_check_mpio_paths(struct megasas_instance *instance,
|
||||
struct scsi_cmnd *scmd);
|
||||
|
||||
void
|
||||
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)
|
|||
cmd->scmd = NULL;
|
||||
cmd->frame_count = 0;
|
||||
if ((instance->pdev->device != PCI_DEVICE_ID_LSI_FUSION) &&
|
||||
(instance->pdev->device != PCI_DEVICE_ID_LSI_PLASMA) &&
|
||||
(instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER) &&
|
||||
(instance->pdev->device != PCI_DEVICE_ID_LSI_FURY) &&
|
||||
(reset_devices))
|
||||
|
@ -877,6 +889,7 @@ extern struct megasas_instance_template megasas_instance_template_fusion;
|
|||
int
|
||||
megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd)
|
||||
{
|
||||
int seconds;
|
||||
|
||||
struct megasas_header *frame_hdr = &cmd->frame->hdr;
|
||||
|
||||
|
@ -891,7 +904,11 @@ megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd)
|
|||
/*
|
||||
* Wait for cmd_status to change
|
||||
*/
|
||||
return wait_and_poll(instance, cmd);
|
||||
if (instance->requestorId)
|
||||
seconds = MEGASAS_ROUTINE_WAIT_TIME_VF;
|
||||
else
|
||||
seconds = MFI_POLL_TIMEOUT_SECS;
|
||||
return wait_and_poll(instance, cmd, seconds);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1532,9 +1549,23 @@ megasas_queue_command_lck(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd
|
|||
|
||||
spin_lock_irqsave(&instance->hba_lock, flags);
|
||||
|
||||
/* Check for an mpio path and adjust behavior */
|
||||
if (instance->adprecovery == MEGASAS_ADPRESET_SM_INFAULT) {
|
||||
if (megasas_check_mpio_paths(instance, scmd) ==
|
||||
(DID_RESET << 16)) {
|
||||
spin_unlock_irqrestore(&instance->hba_lock, flags);
|
||||
return SCSI_MLQUEUE_HOST_BUSY;
|
||||
} else {
|
||||
spin_unlock_irqrestore(&instance->hba_lock, flags);
|
||||
scmd->result = DID_NO_CONNECT << 16;
|
||||
done(scmd);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
|
||||
spin_unlock_irqrestore(&instance->hba_lock, flags);
|
||||
scmd->result = DID_ERROR << 16;
|
||||
scmd->result = DID_NO_CONNECT << 16;
|
||||
done(scmd);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1659,9 +1690,14 @@ void megaraid_sas_kill_hba(struct megasas_instance *instance)
|
|||
if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
|
||||
(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
|
||||
(instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
|
||||
(instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) ||
|
||||
(instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
|
||||
(instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
|
||||
writel(MFI_STOP_ADP, &instance->reg_set->doorbell);
|
||||
/* Flush */
|
||||
readl(&instance->reg_set->doorbell);
|
||||
if (instance->mpio && instance->requestorId)
|
||||
memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
|
||||
} else {
|
||||
writel(MFI_STOP_ADP, &instance->reg_set->inbound_doorbell);
|
||||
}
|
||||
|
@ -1748,6 +1784,25 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr)
|
|||
megasas_check_and_restore_queue_depth(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* megasas_start_timer - Initializes a timer object
|
||||
* @instance: Adapter soft state
|
||||
* @timer: timer object to be initialized
|
||||
* @fn: timer function
|
||||
* @interval: time interval between timer function call
|
||||
*
|
||||
*/
|
||||
void megasas_start_timer(struct megasas_instance *instance,
|
||||
struct timer_list *timer,
|
||||
void *fn, unsigned long interval)
|
||||
{
|
||||
init_timer(timer);
|
||||
timer->expires = jiffies + interval;
|
||||
timer->data = (unsigned long)instance;
|
||||
timer->function = fn;
|
||||
add_timer(timer);
|
||||
}
|
||||
|
||||
static void
|
||||
megasas_internal_reset_defer_cmds(struct megasas_instance *instance);
|
||||
|
||||
|
@ -1770,6 +1825,295 @@ void megasas_do_ocr(struct megasas_instance *instance)
|
|||
process_fw_state_change_wq(&instance->work_init);
|
||||
}
|
||||
|
||||
/* This function will get the current SR-IOV LD/VF affiliation */
|
||||
static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance,
|
||||
int initial)
|
||||
{
|
||||
struct megasas_cmd *cmd;
|
||||
struct megasas_dcmd_frame *dcmd;
|
||||
struct MR_LD_VF_AFFILIATION *new_affiliation = NULL;
|
||||
struct MR_LD_VF_AFFILIATION_111 *new_affiliation_111 = NULL;
|
||||
struct MR_LD_VF_MAP *newmap = NULL, *savedmap = NULL;
|
||||
dma_addr_t new_affiliation_h;
|
||||
dma_addr_t new_affiliation_111_h;
|
||||
int ld, retval = 0;
|
||||
u8 thisVf;
|
||||
|
||||
cmd = megasas_get_cmd(instance);
|
||||
|
||||
if (!cmd) {
|
||||
printk(KERN_DEBUG "megasas: megasas_get_ld_vf_"
|
||||
"affiliation: Failed to get cmd for scsi%d.\n",
|
||||
instance->host->host_no);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dcmd = &cmd->frame->dcmd;
|
||||
|
||||
if (!instance->vf_affiliation && !instance->vf_affiliation_111) {
|
||||
printk(KERN_WARNING "megasas: SR-IOV: Couldn't get LD/VF "
|
||||
"affiliation for scsi%d.\n", instance->host->host_no);
|
||||
megasas_return_cmd(instance, cmd);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (initial)
|
||||
if (instance->PlasmaFW111)
|
||||
memset(instance->vf_affiliation_111, 0,
|
||||
sizeof(struct MR_LD_VF_AFFILIATION_111));
|
||||
else
|
||||
memset(instance->vf_affiliation, 0,
|
||||
(MAX_LOGICAL_DRIVES + 1) *
|
||||
sizeof(struct MR_LD_VF_AFFILIATION));
|
||||
else {
|
||||
if (instance->PlasmaFW111)
|
||||
new_affiliation_111 =
|
||||
pci_alloc_consistent(instance->pdev,
|
||||
sizeof(struct MR_LD_VF_AFFILIATION_111),
|
||||
&new_affiliation_111_h);
|
||||
else
|
||||
new_affiliation =
|
||||
pci_alloc_consistent(instance->pdev,
|
||||
(MAX_LOGICAL_DRIVES + 1) *
|
||||
sizeof(struct MR_LD_VF_AFFILIATION),
|
||||
&new_affiliation_h);
|
||||
if (!new_affiliation && !new_affiliation_111) {
|
||||
printk(KERN_DEBUG "megasas: SR-IOV: Couldn't allocate "
|
||||
"memory for new affiliation for scsi%d.\n",
|
||||
instance->host->host_no);
|
||||
megasas_return_cmd(instance, cmd);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (instance->PlasmaFW111)
|
||||
memset(new_affiliation_111, 0,
|
||||
sizeof(struct MR_LD_VF_AFFILIATION_111));
|
||||
else
|
||||
memset(new_affiliation, 0, (MAX_LOGICAL_DRIVES + 1) *
|
||||
sizeof(struct MR_LD_VF_AFFILIATION));
|
||||
}
|
||||
|
||||
memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
|
||||
|
||||
dcmd->cmd = MFI_CMD_DCMD;
|
||||
dcmd->cmd_status = 0xFF;
|
||||
dcmd->sge_count = 1;
|
||||
dcmd->flags = MFI_FRAME_DIR_BOTH;
|
||||
dcmd->timeout = 0;
|
||||
dcmd->pad_0 = 0;
|
||||
if (instance->PlasmaFW111) {
|
||||
dcmd->data_xfer_len = sizeof(struct MR_LD_VF_AFFILIATION_111);
|
||||
dcmd->opcode = MR_DCMD_LD_VF_MAP_GET_ALL_LDS_111;
|
||||
} else {
|
||||
dcmd->data_xfer_len = (MAX_LOGICAL_DRIVES + 1) *
|
||||
sizeof(struct MR_LD_VF_AFFILIATION);
|
||||
dcmd->opcode = MR_DCMD_LD_VF_MAP_GET_ALL_LDS;
|
||||
}
|
||||
|
||||
if (initial) {
|
||||
if (instance->PlasmaFW111)
|
||||
dcmd->sgl.sge32[0].phys_addr =
|
||||
instance->vf_affiliation_111_h;
|
||||
else
|
||||
dcmd->sgl.sge32[0].phys_addr =
|
||||
instance->vf_affiliation_h;
|
||||
} else {
|
||||
if (instance->PlasmaFW111)
|
||||
dcmd->sgl.sge32[0].phys_addr = new_affiliation_111_h;
|
||||
else
|
||||
dcmd->sgl.sge32[0].phys_addr = new_affiliation_h;
|
||||
}
|
||||
if (instance->PlasmaFW111)
|
||||
dcmd->sgl.sge32[0].length =
|
||||
sizeof(struct MR_LD_VF_AFFILIATION_111);
|
||||
else
|
||||
dcmd->sgl.sge32[0].length = (MAX_LOGICAL_DRIVES + 1) *
|
||||
sizeof(struct MR_LD_VF_AFFILIATION);
|
||||
|
||||
printk(KERN_WARNING "megasas: SR-IOV: Getting LD/VF affiliation for "
|
||||
"scsi%d\n", instance->host->host_no);
|
||||
|
||||
megasas_issue_blocked_cmd(instance, cmd, 0);
|
||||
|
||||
if (dcmd->cmd_status) {
|
||||
printk(KERN_WARNING "megasas: SR-IOV: LD/VF affiliation DCMD"
|
||||
" failed with status 0x%x for scsi%d.\n",
|
||||
dcmd->cmd_status, instance->host->host_no);
|
||||
retval = 1; /* Do a scan if we couldn't get affiliation */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!initial) {
|
||||
if (instance->PlasmaFW111) {
|
||||
if (!new_affiliation_111->vdCount) {
|
||||
printk(KERN_WARNING "megasas: SR-IOV: Got new "
|
||||
"LD/VF affiliation for passive path "
|
||||
"for scsi%d.\n",
|
||||
instance->host->host_no);
|
||||
retval = 1;
|
||||
goto out;
|
||||
}
|
||||
thisVf = new_affiliation_111->thisVf;
|
||||
for (ld = 0 ; ld < new_affiliation_111->vdCount; ld++)
|
||||
if (instance->vf_affiliation_111->map[ld].policy[thisVf] != new_affiliation_111->map[ld].policy[thisVf]) {
|
||||
printk(KERN_WARNING "megasas: SR-IOV: "
|
||||
"Got new LD/VF affiliation "
|
||||
"for scsi%d.\n",
|
||||
instance->host->host_no);
|
||||
memcpy(instance->vf_affiliation_111,
|
||||
new_affiliation_111,
|
||||
sizeof(struct MR_LD_VF_AFFILIATION_111));
|
||||
retval = 1;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
if (!new_affiliation->ldCount) {
|
||||
printk(KERN_WARNING "megasas: SR-IOV: Got new "
|
||||
"LD/VF affiliation for passive "
|
||||
"path for scsi%d.\n",
|
||||
instance->host->host_no);
|
||||
retval = 1;
|
||||
goto out;
|
||||
}
|
||||
newmap = new_affiliation->map;
|
||||
savedmap = instance->vf_affiliation->map;
|
||||
thisVf = new_affiliation->thisVf;
|
||||
for (ld = 0 ; ld < new_affiliation->ldCount; ld++) {
|
||||
if (savedmap->policy[thisVf] !=
|
||||
newmap->policy[thisVf]) {
|
||||
printk(KERN_WARNING "megasas: SR-IOV: "
|
||||
"Got new LD/VF affiliation "
|
||||
"for scsi%d.\n",
|
||||
instance->host->host_no);
|
||||
memcpy(instance->vf_affiliation,
|
||||
new_affiliation,
|
||||
new_affiliation->size);
|
||||
retval = 1;
|
||||
goto out;
|
||||
}
|
||||
savedmap = (struct MR_LD_VF_MAP *)
|
||||
((unsigned char *)savedmap +
|
||||
savedmap->size);
|
||||
newmap = (struct MR_LD_VF_MAP *)
|
||||
((unsigned char *)newmap +
|
||||
newmap->size);
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
if (new_affiliation) {
|
||||
if (instance->PlasmaFW111)
|
||||
pci_free_consistent(instance->pdev,
|
||||
sizeof(struct MR_LD_VF_AFFILIATION_111),
|
||||
new_affiliation_111,
|
||||
new_affiliation_111_h);
|
||||
else
|
||||
pci_free_consistent(instance->pdev,
|
||||
(MAX_LOGICAL_DRIVES + 1) *
|
||||
sizeof(struct MR_LD_VF_AFFILIATION),
|
||||
new_affiliation, new_affiliation_h);
|
||||
}
|
||||
megasas_return_cmd(instance, cmd);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* This function will tell FW to start the SR-IOV heartbeat */
|
||||
int megasas_sriov_start_heartbeat(struct megasas_instance *instance,
|
||||
int initial)
|
||||
{
|
||||
struct megasas_cmd *cmd;
|
||||
struct megasas_dcmd_frame *dcmd;
|
||||
int retval = 0;
|
||||
|
||||
cmd = megasas_get_cmd(instance);
|
||||
|
||||
if (!cmd) {
|
||||
printk(KERN_DEBUG "megasas: megasas_sriov_start_heartbeat: "
|
||||
"Failed to get cmd for scsi%d.\n",
|
||||
instance->host->host_no);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dcmd = &cmd->frame->dcmd;
|
||||
|
||||
if (initial) {
|
||||
instance->hb_host_mem =
|
||||
pci_alloc_consistent(instance->pdev,
|
||||
sizeof(struct MR_CTRL_HB_HOST_MEM),
|
||||
&instance->hb_host_mem_h);
|
||||
if (!instance->hb_host_mem) {
|
||||
printk(KERN_DEBUG "megasas: SR-IOV: Couldn't allocate"
|
||||
" memory for heartbeat host memory for "
|
||||
"scsi%d.\n", instance->host->host_no);
|
||||
retval = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
memset(instance->hb_host_mem, 0,
|
||||
sizeof(struct MR_CTRL_HB_HOST_MEM));
|
||||
}
|
||||
|
||||
memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
|
||||
|
||||
dcmd->mbox.s[0] = sizeof(struct MR_CTRL_HB_HOST_MEM);
|
||||
dcmd->cmd = MFI_CMD_DCMD;
|
||||
dcmd->cmd_status = 0xFF;
|
||||
dcmd->sge_count = 1;
|
||||
dcmd->flags = MFI_FRAME_DIR_BOTH;
|
||||
dcmd->timeout = 0;
|
||||
dcmd->pad_0 = 0;
|
||||
dcmd->data_xfer_len = sizeof(struct MR_CTRL_HB_HOST_MEM);
|
||||
dcmd->opcode = MR_DCMD_CTRL_SHARED_HOST_MEM_ALLOC;
|
||||
dcmd->sgl.sge32[0].phys_addr = instance->hb_host_mem_h;
|
||||
dcmd->sgl.sge32[0].length = sizeof(struct MR_CTRL_HB_HOST_MEM);
|
||||
|
||||
printk(KERN_WARNING "megasas: SR-IOV: Starting heartbeat for scsi%d\n",
|
||||
instance->host->host_no);
|
||||
|
||||
if (!megasas_issue_polled(instance, cmd)) {
|
||||
retval = 0;
|
||||
} else {
|
||||
printk(KERN_WARNING "megasas: SR-IOV: MR_DCMD_CTRL_SHARED_HOST"
|
||||
"_MEM_ALLOC DCMD timed out for scsi%d\n",
|
||||
instance->host->host_no);
|
||||
retval = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
if (dcmd->cmd_status) {
|
||||
printk(KERN_WARNING "megasas: SR-IOV: MR_DCMD_CTRL_SHARED_HOST"
|
||||
"_MEM_ALLOC DCMD failed with status 0x%x for scsi%d\n",
|
||||
dcmd->cmd_status,
|
||||
instance->host->host_no);
|
||||
retval = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
megasas_return_cmd(instance, cmd);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Handler for SR-IOV heartbeat */
|
||||
void megasas_sriov_heartbeat_handler(unsigned long instance_addr)
|
||||
{
|
||||
struct megasas_instance *instance =
|
||||
(struct megasas_instance *)instance_addr;
|
||||
|
||||
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;
|
||||
mod_timer(&instance->sriov_heartbeat_timer,
|
||||
jiffies + MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF);
|
||||
} else {
|
||||
printk(KERN_WARNING "megasas: SR-IOV: Heartbeat never "
|
||||
"completed for scsi%d\n", instance->host->host_no);
|
||||
schedule_work(&instance->work_init);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* megasas_wait_for_outstanding - Wait for all outstanding cmds
|
||||
* @instance: Adapter soft state
|
||||
|
@ -2032,9 +2376,10 @@ static int megasas_reset_bus_host(struct scsi_cmnd *scmd)
|
|||
* First wait for all commands to complete
|
||||
*/
|
||||
if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
|
||||
(instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) ||
|
||||
(instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
|
||||
(instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
|
||||
ret = megasas_reset_fusion(scmd->device->host);
|
||||
ret = megasas_reset_fusion(scmd->device->host, 1);
|
||||
else
|
||||
ret = megasas_generic_reset(scmd);
|
||||
|
||||
|
@ -2749,6 +3094,8 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr)
|
|||
(instance->pdev->device ==
|
||||
PCI_DEVICE_ID_LSI_FUSION) ||
|
||||
(instance->pdev->device ==
|
||||
PCI_DEVICE_ID_LSI_PLASMA) ||
|
||||
(instance->pdev->device ==
|
||||
PCI_DEVICE_ID_LSI_INVADER) ||
|
||||
(instance->pdev->device ==
|
||||
PCI_DEVICE_ID_LSI_FURY)) {
|
||||
|
@ -2772,6 +3119,8 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr)
|
|||
PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
|
||||
(instance->pdev->device ==
|
||||
PCI_DEVICE_ID_LSI_FUSION) ||
|
||||
(instance->pdev->device ==
|
||||
PCI_DEVICE_ID_LSI_PLASMA) ||
|
||||
(instance->pdev->device ==
|
||||
PCI_DEVICE_ID_LSI_INVADER) ||
|
||||
(instance->pdev->device ==
|
||||
|
@ -2797,6 +3146,8 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr)
|
|||
PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
|
||||
(instance->pdev->device
|
||||
== PCI_DEVICE_ID_LSI_FUSION) ||
|
||||
(instance->pdev->device
|
||||
== PCI_DEVICE_ID_LSI_PLASMA) ||
|
||||
(instance->pdev->device
|
||||
== PCI_DEVICE_ID_LSI_INVADER) ||
|
||||
(instance->pdev->device
|
||||
|
@ -2806,6 +3157,8 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr)
|
|||
if ((instance->pdev->device ==
|
||||
PCI_DEVICE_ID_LSI_FUSION) ||
|
||||
(instance->pdev->device ==
|
||||
PCI_DEVICE_ID_LSI_PLASMA) ||
|
||||
(instance->pdev->device ==
|
||||
PCI_DEVICE_ID_LSI_INVADER) ||
|
||||
(instance->pdev->device ==
|
||||
PCI_DEVICE_ID_LSI_FURY)) {
|
||||
|
@ -3032,6 +3385,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
|
|||
cmd->frame->io.context = cpu_to_le32(cmd->index);
|
||||
cmd->frame->io.pad_0 = 0;
|
||||
if ((instance->pdev->device != PCI_DEVICE_ID_LSI_FUSION) &&
|
||||
(instance->pdev->device != PCI_DEVICE_ID_LSI_PLASMA) &&
|
||||
(instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER) &&
|
||||
(instance->pdev->device != PCI_DEVICE_ID_LSI_FURY) &&
|
||||
(reset_devices))
|
||||
|
@ -3638,6 +3992,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
|
|||
struct megasas_ctrl_info *ctrl_info;
|
||||
unsigned long bar_list;
|
||||
int i, loop, fw_msix_count = 0;
|
||||
struct IOV_111 *iovPtr;
|
||||
|
||||
/* Find first memory bar */
|
||||
bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM);
|
||||
|
@ -3660,6 +4015,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
|
|||
|
||||
switch (instance->pdev->device) {
|
||||
case PCI_DEVICE_ID_LSI_FUSION:
|
||||
case PCI_DEVICE_ID_LSI_PLASMA:
|
||||
case PCI_DEVICE_ID_LSI_INVADER:
|
||||
case PCI_DEVICE_ID_LSI_FURY:
|
||||
instance->instancet = &megasas_instance_template_fusion;
|
||||
|
@ -3714,7 +4070,8 @@ static int megasas_init_fw(struct megasas_instance *instance)
|
|||
scratch_pad_2 = readl
|
||||
(&instance->reg_set->outbound_scratch_pad_2);
|
||||
/* Check max MSI-X vectors */
|
||||
if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) {
|
||||
if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
|
||||
(instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA)) {
|
||||
instance->msix_vectors = (scratch_pad_2
|
||||
& MR_MAX_REPLY_QUEUES_OFFSET) + 1;
|
||||
fw_msix_count = instance->msix_vectors;
|
||||
|
@ -3828,6 +4185,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
|
|||
ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
|
||||
/* adapterOperations2 are converted into CPU arch*/
|
||||
le32_to_cpus((u32 *)&ctrl_info->adapterOperations2);
|
||||
instance->mpio = ctrl_info->adapterOperations2.mpio;
|
||||
instance->UnevenSpanSupport =
|
||||
ctrl_info->adapterOperations2.supportUnevenSpans;
|
||||
if (instance->UnevenSpanSupport) {
|
||||
|
@ -3840,6 +4198,20 @@ static int megasas_init_fw(struct megasas_instance *instance)
|
|||
fusion->fast_path_io = 0;
|
||||
|
||||
}
|
||||
if (ctrl_info->host_interface.SRIOV) {
|
||||
if (!ctrl_info->adapterOperations2.activePassive)
|
||||
instance->PlasmaFW111 = 1;
|
||||
|
||||
if (!instance->PlasmaFW111)
|
||||
instance->requestorId =
|
||||
ctrl_info->iov.requestorId;
|
||||
else {
|
||||
iovPtr = (struct IOV_111 *)((unsigned char *)ctrl_info + IOV_111_OFFSET);
|
||||
instance->requestorId = iovPtr->requestorId;
|
||||
}
|
||||
printk(KERN_WARNING "megaraid_sas: I am VF "
|
||||
"requestorId %d\n", instance->requestorId);
|
||||
}
|
||||
}
|
||||
instance->max_sectors_per_req = instance->max_num_sge *
|
||||
PAGE_SIZE / 512;
|
||||
|
@ -3872,6 +4244,17 @@ static int megasas_init_fw(struct megasas_instance *instance)
|
|||
tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
|
||||
(unsigned long)instance);
|
||||
|
||||
/* Launch SR-IOV heartbeat timer */
|
||||
if (instance->requestorId) {
|
||||
if (!megasas_sriov_start_heartbeat(instance, 1))
|
||||
megasas_start_timer(instance,
|
||||
&instance->sriov_heartbeat_timer,
|
||||
megasas_sriov_heartbeat_handler,
|
||||
MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF);
|
||||
else
|
||||
instance->skip_heartbeat_timer_del = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail_init_adapter:
|
||||
|
@ -4184,6 +4567,7 @@ static int megasas_io_attach(struct megasas_instance *instance)
|
|||
|
||||
/* Fusion only supports host reset */
|
||||
if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
|
||||
(instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) ||
|
||||
(instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
|
||||
(instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
|
||||
host->hostt->eh_device_reset_handler = NULL;
|
||||
|
@ -4309,6 +4693,7 @@ static int megasas_probe_one(struct pci_dev *pdev,
|
|||
|
||||
switch (instance->pdev->device) {
|
||||
case PCI_DEVICE_ID_LSI_FUSION:
|
||||
case PCI_DEVICE_ID_LSI_PLASMA:
|
||||
case PCI_DEVICE_ID_LSI_INVADER:
|
||||
case PCI_DEVICE_ID_LSI_FURY:
|
||||
{
|
||||
|
@ -4405,6 +4790,7 @@ static int megasas_probe_one(struct pci_dev *pdev,
|
|||
instance->UnevenSpanSupport = 0;
|
||||
|
||||
if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
|
||||
(instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) ||
|
||||
(instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
|
||||
(instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
|
||||
INIT_WORK(&instance->work_init, megasas_fusion_ocr_wq);
|
||||
|
@ -4417,6 +4803,26 @@ static int megasas_probe_one(struct pci_dev *pdev,
|
|||
if (megasas_init_fw(instance))
|
||||
goto fail_init_mfi;
|
||||
|
||||
if (instance->requestorId) {
|
||||
if (instance->PlasmaFW111) {
|
||||
instance->vf_affiliation_111 =
|
||||
pci_alloc_consistent(pdev, sizeof(struct MR_LD_VF_AFFILIATION_111),
|
||||
&instance->vf_affiliation_111_h);
|
||||
if (!instance->vf_affiliation_111)
|
||||
printk(KERN_WARNING "megasas: Can't allocate "
|
||||
"memory for VF affiliation buffer\n");
|
||||
} else {
|
||||
instance->vf_affiliation =
|
||||
pci_alloc_consistent(pdev,
|
||||
(MAX_LOGICAL_DRIVES + 1) *
|
||||
sizeof(struct MR_LD_VF_AFFILIATION),
|
||||
&instance->vf_affiliation_h);
|
||||
if (!instance->vf_affiliation)
|
||||
printk(KERN_WARNING "megasas: Can't allocate "
|
||||
"memory for VF affiliation buffer\n");
|
||||
}
|
||||
}
|
||||
|
||||
retry_irq_register:
|
||||
/*
|
||||
* Register IRQ
|
||||
|
@ -4511,6 +4917,7 @@ static int megasas_probe_one(struct pci_dev *pdev,
|
|||
free_irq(instance->pdev->irq, &instance->irq_context[0]);
|
||||
fail_irq:
|
||||
if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
|
||||
(instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) ||
|
||||
(instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
|
||||
(instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
|
||||
megasas_release_fusion(instance);
|
||||
|
@ -4644,6 +5051,10 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
|
|||
host = instance->host;
|
||||
instance->unload = 1;
|
||||
|
||||
/* Shutdown SR-IOV heartbeat timer */
|
||||
if (instance->requestorId && !instance->skip_heartbeat_timer_del)
|
||||
del_timer_sync(&instance->sriov_heartbeat_timer);
|
||||
|
||||
megasas_flush_cache(instance);
|
||||
megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN);
|
||||
|
||||
|
@ -4730,6 +5141,7 @@ megasas_resume(struct pci_dev *pdev)
|
|||
|
||||
switch (instance->pdev->device) {
|
||||
case PCI_DEVICE_ID_LSI_FUSION:
|
||||
case PCI_DEVICE_ID_LSI_PLASMA:
|
||||
case PCI_DEVICE_ID_LSI_INVADER:
|
||||
case PCI_DEVICE_ID_LSI_FURY:
|
||||
{
|
||||
|
@ -4795,6 +5207,17 @@ megasas_resume(struct pci_dev *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
/* Re-launch SR-IOV heartbeat timer */
|
||||
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;
|
||||
}
|
||||
|
||||
instance->instancet->enable_intr(instance);
|
||||
instance->unload = 0;
|
||||
|
||||
|
@ -4849,6 +5272,10 @@ static void megasas_detach_one(struct pci_dev *pdev)
|
|||
host = instance->host;
|
||||
fusion = instance->ctrl_context;
|
||||
|
||||
/* Shutdown SR-IOV heartbeat timer */
|
||||
if (instance->requestorId && !instance->skip_heartbeat_timer_del)
|
||||
del_timer_sync(&instance->sriov_heartbeat_timer);
|
||||
|
||||
scsi_remove_host(instance->host);
|
||||
megasas_flush_cache(instance);
|
||||
megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
|
||||
|
@ -4894,6 +5321,7 @@ static void megasas_detach_one(struct pci_dev *pdev)
|
|||
|
||||
switch (instance->pdev->device) {
|
||||
case PCI_DEVICE_ID_LSI_FUSION:
|
||||
case PCI_DEVICE_ID_LSI_PLASMA:
|
||||
case PCI_DEVICE_ID_LSI_INVADER:
|
||||
case PCI_DEVICE_ID_LSI_FURY:
|
||||
megasas_release_fusion(instance);
|
||||
|
@ -4920,6 +5348,24 @@ static void megasas_detach_one(struct pci_dev *pdev)
|
|||
if (instance->evt_detail)
|
||||
pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
|
||||
instance->evt_detail, instance->evt_detail_h);
|
||||
|
||||
if (instance->vf_affiliation)
|
||||
pci_free_consistent(pdev, (MAX_LOGICAL_DRIVES + 1) *
|
||||
sizeof(struct MR_LD_VF_AFFILIATION),
|
||||
instance->vf_affiliation,
|
||||
instance->vf_affiliation_h);
|
||||
|
||||
if (instance->vf_affiliation_111)
|
||||
pci_free_consistent(pdev,
|
||||
sizeof(struct MR_LD_VF_AFFILIATION_111),
|
||||
instance->vf_affiliation_111,
|
||||
instance->vf_affiliation_111_h);
|
||||
|
||||
if (instance->hb_host_mem)
|
||||
pci_free_consistent(pdev, sizeof(struct MR_CTRL_HB_HOST_MEM),
|
||||
instance->hb_host_mem,
|
||||
instance->hb_host_mem_h);
|
||||
|
||||
scsi_host_put(host);
|
||||
|
||||
pci_disable_device(pdev);
|
||||
|
@ -5208,6 +5654,16 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
|
|||
goto out_kfree_ioc;
|
||||
}
|
||||
|
||||
/* Adjust ioctl wait time for VF mode */
|
||||
if (instance->requestorId)
|
||||
wait_time = MEGASAS_ROUTINE_WAIT_TIME_VF;
|
||||
|
||||
/* Block ioctls in VF mode */
|
||||
if (instance->requestorId && !allow_vf_ioctls) {
|
||||
error = -ENODEV;
|
||||
goto out_kfree_ioc;
|
||||
}
|
||||
|
||||
if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
|
||||
printk(KERN_ERR "Controller in crit error\n");
|
||||
error = -ENODEV;
|
||||
|
@ -5517,7 +5973,7 @@ megasas_aen_polling(struct work_struct *work)
|
|||
u16 pd_index = 0;
|
||||
u16 ld_index = 0;
|
||||
int i, j, doscan = 0;
|
||||
u32 seq_num;
|
||||
u32 seq_num, wait_time = MEGASAS_RESET_WAIT_TIME;
|
||||
int error;
|
||||
|
||||
if (!instance) {
|
||||
|
@ -5525,6 +5981,23 @@ megasas_aen_polling(struct work_struct *work)
|
|||
kfree(ev);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Adjust event workqueue thread wait time for VF mode */
|
||||
if (instance->requestorId)
|
||||
wait_time = MEGASAS_ROUTINE_WAIT_TIME_VF;
|
||||
|
||||
/* Don't run the event workqueue thread if OCR is running */
|
||||
for (i = 0; i < wait_time; i++) {
|
||||
if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL)
|
||||
break;
|
||||
if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
|
||||
printk(KERN_NOTICE "megasas: %s waiting for "
|
||||
"controller reset to finish for scsi%d\n",
|
||||
__func__, instance->host->host_no);
|
||||
}
|
||||
msleep(1000);
|
||||
}
|
||||
|
||||
instance->ev = NULL;
|
||||
host = instance->host;
|
||||
if (instance->evt_detail) {
|
||||
|
@ -5591,6 +6064,9 @@ megasas_aen_polling(struct work_struct *work)
|
|||
case MR_EVT_LD_OFFLINE:
|
||||
case MR_EVT_CFG_CLEARED:
|
||||
case MR_EVT_LD_DELETED:
|
||||
if (!instance->requestorId ||
|
||||
(instance->requestorId &&
|
||||
megasas_get_ld_vf_affiliation(instance, 0))) {
|
||||
if (megasas_ld_list_query(instance,
|
||||
MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
|
||||
megasas_get_ld_list(instance);
|
||||
|
@ -5602,15 +6078,12 @@ megasas_aen_polling(struct work_struct *work)
|
|||
ld_index =
|
||||
(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
|
||||
|
||||
sdev1 = scsi_device_lookup(host,
|
||||
MEGASAS_MAX_PD_CHANNELS + i,
|
||||
j,
|
||||
0);
|
||||
sdev1 = scsi_device_lookup(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0);
|
||||
|
||||
if (instance->ld_ids[ld_index] != 0xff) {
|
||||
if (sdev1) {
|
||||
if (instance->ld_ids[ld_index]
|
||||
!= 0xff) {
|
||||
if (sdev1)
|
||||
scsi_device_put(sdev1);
|
||||
}
|
||||
} else {
|
||||
if (sdev1) {
|
||||
scsi_remove_device(sdev1);
|
||||
|
@ -5620,8 +6093,12 @@ megasas_aen_polling(struct work_struct *work)
|
|||
}
|
||||
}
|
||||
doscan = 0;
|
||||
}
|
||||
break;
|
||||
case MR_EVT_LD_CREATED:
|
||||
if (!instance->requestorId ||
|
||||
(instance->requestorId &&
|
||||
megasas_get_ld_vf_affiliation(instance, 0))) {
|
||||
if (megasas_ld_list_query(instance,
|
||||
MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
|
||||
megasas_get_ld_list(instance);
|
||||
|
@ -5632,24 +6109,19 @@ megasas_aen_polling(struct work_struct *work)
|
|||
ld_index =
|
||||
(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
|
||||
|
||||
sdev1 = scsi_device_lookup(host,
|
||||
MEGASAS_MAX_PD_CHANNELS + i,
|
||||
j, 0);
|
||||
sdev1 = scsi_device_lookup(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0);
|
||||
|
||||
if (instance->ld_ids[ld_index] !=
|
||||
0xff) {
|
||||
if (!sdev1) {
|
||||
scsi_add_device(host,
|
||||
MEGASAS_MAX_PD_CHANNELS + i,
|
||||
j, 0);
|
||||
if (instance->ld_ids[ld_index]
|
||||
!= 0xff) {
|
||||
if (!sdev1)
|
||||
scsi_add_device(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0);
|
||||
}
|
||||
}
|
||||
if (sdev1) {
|
||||
if (sdev1)
|
||||
scsi_device_put(sdev1);
|
||||
}
|
||||
}
|
||||
}
|
||||
doscan = 0;
|
||||
}
|
||||
break;
|
||||
case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED:
|
||||
case MR_EVT_FOREIGN_CFG_IMPORTED:
|
||||
|
@ -5667,7 +6139,8 @@ megasas_aen_polling(struct work_struct *work)
|
|||
}
|
||||
|
||||
if (doscan) {
|
||||
printk(KERN_INFO "scanning ...\n");
|
||||
printk(KERN_INFO "megaraid_sas: scanning for scsi%d...\n",
|
||||
instance->host->host_no);
|
||||
if (megasas_get_pd_list(instance) == 0) {
|
||||
for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) {
|
||||
for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
|
||||
|
@ -5690,24 +6163,26 @@ megasas_aen_polling(struct work_struct *work)
|
|||
}
|
||||
}
|
||||
|
||||
if (!instance->requestorId ||
|
||||
(instance->requestorId &&
|
||||
megasas_get_ld_vf_affiliation(instance, 0))) {
|
||||
if (megasas_ld_list_query(instance,
|
||||
MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
|
||||
megasas_get_ld_list(instance);
|
||||
for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
|
||||
for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
|
||||
for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL;
|
||||
j++) {
|
||||
ld_index =
|
||||
(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
|
||||
|
||||
sdev1 = scsi_device_lookup(host,
|
||||
MEGASAS_MAX_PD_CHANNELS + i, j, 0);
|
||||
if (instance->ld_ids[ld_index] != 0xff) {
|
||||
if (!sdev1) {
|
||||
scsi_add_device(host,
|
||||
MEGASAS_MAX_PD_CHANNELS + i,
|
||||
j, 0);
|
||||
} else {
|
||||
if (instance->ld_ids[ld_index]
|
||||
!= 0xff) {
|
||||
if (!sdev1)
|
||||
scsi_add_device(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0);
|
||||
else
|
||||
scsi_device_put(sdev1);
|
||||
}
|
||||
} else {
|
||||
if (sdev1) {
|
||||
scsi_remove_device(sdev1);
|
||||
|
@ -5717,6 +6192,7 @@ megasas_aen_polling(struct work_struct *work)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( instance->aen_cmd != NULL ) {
|
||||
kfree(ev);
|
||||
|
|
|
@ -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 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance)
|
|||
* 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,9 +2050,12 @@ 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;
|
||||
|
|
Loading…
Reference in a new issue