Commit f81f2e3a authored by Sumit Saxena's avatar Sumit Saxena Committed by Tim Gardner

megaraid_sas: Fix for IO failing post OCR in SRIOV environment

BugLink: http://bugs.launchpad.net/bugs/1544679

Driver assumes that VFs always have peers present whenever they have
same LD IDs. But this is not the case.  This patch handles the above
mentioned by explicitly checking for a peer before making HA/non-HA path
decision.
Signed-off-by: default avatarUday Lingala <uday.lingala@avagotech.com>
Signed-off-by: default avatarSumit Saxena <sumit.saxena@avagotech.com>
Reviewed-by: default avatarTomas Henzl <thenzl@redhat.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
(cherry picked from linux-next commit 07d6c5aa4d4128cadb7ff0557576f70085f2cae1)
Signed-off-by: default avatarTim Gardner <tim.gardner@canonical.com>
parent 92befa41
......@@ -393,6 +393,7 @@ enum MR_EVT_ARGS {
#define SGE_BUFFER_SIZE 4096
#define MEGASAS_CLUSTER_ID_SIZE 16
/*
* define constants for device list query options
*/
......@@ -1227,7 +1228,8 @@ struct megasas_ctrl_info {
*/
struct {
#if defined(__BIG_ENDIAN_BITFIELD)
u32 reserved:26;
u32 reserved:25;
u32 passive:1;
u32 premiumFeatureMismatch:1;
u32 ctrlPropIncompatible:1;
u32 fwVersionMismatch:1;
......@@ -1241,11 +1243,12 @@ struct megasas_ctrl_info {
u32 fwVersionMismatch:1;
u32 ctrlPropIncompatible:1;
u32 premiumFeatureMismatch:1;
u32 reserved:26;
u32 passive:1;
u32 reserved:25;
#endif
} cluster;
char clusterId[16]; /*7D4h */
char clusterId[MEGASAS_CLUSTER_ID_SIZE]; /*0x7D4 */
struct {
u8 maxVFsSupported; /*0x7E4*/
u8 numVFsEnabled; /*0x7E5*/
......@@ -2126,7 +2129,9 @@ struct megasas_instance {
char skip_heartbeat_timer_del;
u8 requestorId;
char PlasmaFW111;
char mpio;
char clusterId[MEGASAS_CLUSTER_ID_SIZE];
u8 peerIsPresent;
u8 passive;
u16 throttlequeuedepth;
u8 mask_interrupts;
u16 max_chain_frame_sz;
......
......@@ -1943,7 +1943,7 @@ void megaraid_sas_kill_hba(struct megasas_instance *instance)
writel(MFI_STOP_ADP, &instance->reg_set->doorbell);
/* Flush */
readl(&instance->reg_set->doorbell);
if (instance->mpio && instance->requestorId)
if (instance->requestorId && instance->peerIsPresent)
memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
} else {
writel(MFI_STOP_ADP,
......@@ -5182,7 +5182,9 @@ static int megasas_init_fw(struct megasas_instance *instance)
tmp_sectors = min_t(u32, max_sectors_1, max_sectors_2);
instance->mpio = ctrl_info->adapterOperations2.mpio;
instance->peerIsPresent = ctrl_info->cluster.peerIsPresent;
instance->passive = ctrl_info->cluster.passive;
memcpy(instance->clusterId, ctrl_info->clusterId, sizeof(instance->clusterId));
instance->UnevenSpanSupport =
ctrl_info->adapterOperations2.supportUnevenSpans;
if (instance->UnevenSpanSupport) {
......
......@@ -3325,27 +3325,37 @@ int megasas_reset_target_fusion(struct scsi_cmnd *scmd)
return ret;
}
/*SRIOV get other instance in cluster if any*/
struct megasas_instance *megasas_get_peer_instance(struct megasas_instance *instance)
{
int i;
for (i = 0; i < MAX_MGMT_ADAPTERS; i++) {
if (megasas_mgmt_info.instance[i] &&
(megasas_mgmt_info.instance[i] != instance) &&
megasas_mgmt_info.instance[i]->requestorId &&
megasas_mgmt_info.instance[i]->peerIsPresent &&
(memcmp((megasas_mgmt_info.instance[i]->clusterId),
instance->clusterId, MEGASAS_CLUSTER_ID_SIZE) == 0))
return megasas_mgmt_info.instance[i];
}
return NULL;
}
/* Check for a second path that is currently UP */
int megasas_check_mpio_paths(struct megasas_instance *instance,
struct scsi_cmnd *scmd)
{
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;
}
struct megasas_instance *peer_instance = NULL;
int retval = (DID_RESET << 16);
if (instance->peerIsPresent) {
peer_instance = megasas_get_peer_instance(instance);
if ((peer_instance) &&
(atomic_read(&peer_instance->adprecovery) ==
MEGASAS_HBA_OPERATIONAL))
retval = (DID_NO_CONNECT << 16);
}
out:
return retval;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment