Commit 4cbfea88 authored by Adam Radford's avatar Adam Radford Committed by Christoph Hellwig

megaraid_sas: Fix LD/VF affiliation parsing

The following patch for megaraid_sas fixes the LD/VF affiliation policy parsing
code to account for LD targetId's and Hidden LD's (not yet affiliated with any
Virtual Functions).  This also breaks megasas_get_ld_vf_affiliation() into 2
separate functions:  megasas_get_ld_vf_affiliation_111() and
megasas_get_ld_Vf_affiliation_12() to reduce indentation levels.
Signed-off-by: default avatarAdam Radford <aradford@gmail.com>
Reviewed-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent e46b0344
...@@ -1661,6 +1661,7 @@ struct MR_LD_VF_AFFILIATION { ...@@ -1661,6 +1661,7 @@ struct MR_LD_VF_AFFILIATION {
/* Plasma 1.11 FW backward compatibility structures */ /* Plasma 1.11 FW backward compatibility structures */
#define IOV_111_OFFSET 0x7CE #define IOV_111_OFFSET 0x7CE
#define MAX_VIRTUAL_FUNCTIONS 8 #define MAX_VIRTUAL_FUNCTIONS 8
#define MR_LD_ACCESS_HIDDEN 15
struct IOV_111 { struct IOV_111 {
u8 maxVFsSupported; u8 maxVFsSupported;
......
...@@ -1825,16 +1825,12 @@ void megasas_do_ocr(struct megasas_instance *instance) ...@@ -1825,16 +1825,12 @@ void megasas_do_ocr(struct megasas_instance *instance)
process_fw_state_change_wq(&instance->work_init); 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_111(struct megasas_instance *instance,
static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance,
int initial) int initial)
{ {
struct megasas_cmd *cmd; struct megasas_cmd *cmd;
struct megasas_dcmd_frame *dcmd; 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_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; dma_addr_t new_affiliation_111_h;
int ld, retval = 0; int ld, retval = 0;
u8 thisVf; u8 thisVf;
...@@ -1842,15 +1838,15 @@ static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance, ...@@ -1842,15 +1838,15 @@ static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance,
cmd = megasas_get_cmd(instance); cmd = megasas_get_cmd(instance);
if (!cmd) { if (!cmd) {
printk(KERN_DEBUG "megasas: megasas_get_ld_vf_" printk(KERN_DEBUG "megasas: megasas_get_ld_vf_affiliation_111:"
"affiliation: Failed to get cmd for scsi%d.\n", "Failed to get cmd for scsi%d.\n",
instance->host->host_no); instance->host->host_no);
return -ENOMEM; return -ENOMEM;
} }
dcmd = &cmd->frame->dcmd; dcmd = &cmd->frame->dcmd;
if (!instance->vf_affiliation && !instance->vf_affiliation_111) { if (!instance->vf_affiliation_111) {
printk(KERN_WARNING "megasas: SR-IOV: Couldn't get LD/VF " printk(KERN_WARNING "megasas: SR-IOV: Couldn't get LD/VF "
"affiliation for scsi%d.\n", instance->host->host_no); "affiliation for scsi%d.\n", instance->host->host_no);
megasas_return_cmd(instance, cmd); megasas_return_cmd(instance, cmd);
...@@ -1858,38 +1854,22 @@ static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance, ...@@ -1858,38 +1854,22 @@ static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance,
} }
if (initial) if (initial)
if (instance->PlasmaFW111)
memset(instance->vf_affiliation_111, 0, memset(instance->vf_affiliation_111, 0,
sizeof(struct MR_LD_VF_AFFILIATION_111)); sizeof(struct MR_LD_VF_AFFILIATION_111));
else
memset(instance->vf_affiliation, 0,
(MAX_LOGICAL_DRIVES + 1) *
sizeof(struct MR_LD_VF_AFFILIATION));
else { else {
if (instance->PlasmaFW111)
new_affiliation_111 = new_affiliation_111 =
pci_alloc_consistent(instance->pdev, pci_alloc_consistent(instance->pdev,
sizeof(struct MR_LD_VF_AFFILIATION_111), sizeof(struct MR_LD_VF_AFFILIATION_111),
&new_affiliation_111_h); &new_affiliation_111_h);
else if (!new_affiliation_111) {
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 " printk(KERN_DEBUG "megasas: SR-IOV: Couldn't allocate "
"memory for new affiliation for scsi%d.\n", "memory for new affiliation for scsi%d.\n",
instance->host->host_no); instance->host->host_no);
megasas_return_cmd(instance, cmd); megasas_return_cmd(instance, cmd);
return -ENOMEM; return -ENOMEM;
} }
if (instance->PlasmaFW111)
memset(new_affiliation_111, 0, memset(new_affiliation_111, 0,
sizeof(struct MR_LD_VF_AFFILIATION_111)); 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); memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
...@@ -1900,34 +1880,17 @@ static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance, ...@@ -1900,34 +1880,17 @@ static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance,
dcmd->flags = MFI_FRAME_DIR_BOTH; dcmd->flags = MFI_FRAME_DIR_BOTH;
dcmd->timeout = 0; dcmd->timeout = 0;
dcmd->pad_0 = 0; dcmd->pad_0 = 0;
if (instance->PlasmaFW111) {
dcmd->data_xfer_len = sizeof(struct MR_LD_VF_AFFILIATION_111); dcmd->data_xfer_len = sizeof(struct MR_LD_VF_AFFILIATION_111);
dcmd->opcode = MR_DCMD_LD_VF_MAP_GET_ALL_LDS_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 (initial)
if (instance->PlasmaFW111)
dcmd->sgl.sge32[0].phys_addr = dcmd->sgl.sge32[0].phys_addr =
instance->vf_affiliation_111_h; instance->vf_affiliation_111_h;
else 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; 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 = dcmd->sgl.sge32[0].length =
sizeof(struct MR_LD_VF_AFFILIATION_111); 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 " printk(KERN_WARNING "megasas: SR-IOV: Getting LD/VF affiliation for "
"scsi%d\n", instance->host->host_no); "scsi%d\n", instance->host->host_no);
...@@ -1943,18 +1906,10 @@ static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance, ...@@ -1943,18 +1906,10 @@ static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance,
} }
if (!initial) { 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; thisVf = new_affiliation_111->thisVf;
for (ld = 0 ; ld < new_affiliation_111->vdCount; ld++) 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]) { if (instance->vf_affiliation_111->map[ld].policy[thisVf] !=
new_affiliation_111->map[ld].policy[thisVf]) {
printk(KERN_WARNING "megasas: SR-IOV: " printk(KERN_WARNING "megasas: SR-IOV: "
"Got new LD/VF affiliation " "Got new LD/VF affiliation "
"for scsi%d.\n", "for scsi%d.\n",
...@@ -1965,11 +1920,105 @@ static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance, ...@@ -1965,11 +1920,105 @@ static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance,
retval = 1; retval = 1;
goto out; goto out;
} }
} else { }
out:
if (new_affiliation_111) {
pci_free_consistent(instance->pdev,
sizeof(struct MR_LD_VF_AFFILIATION_111),
new_affiliation_111,
new_affiliation_111_h);
}
megasas_return_cmd(instance, cmd);
return retval;
}
static int megasas_get_ld_vf_affiliation_12(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_MAP *newmap = NULL, *savedmap = NULL;
dma_addr_t new_affiliation_h;
int i, j, retval = 0, found = 0, doscan = 0;
u8 thisVf;
cmd = megasas_get_cmd(instance);
if (!cmd) {
printk(KERN_DEBUG "megasas: megasas_get_ld_vf_affiliation12: "
"Failed to get cmd for scsi%d.\n",
instance->host->host_no);
return -ENOMEM;
}
dcmd = &cmd->frame->dcmd;
if (!instance->vf_affiliation) {
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)
memset(instance->vf_affiliation, 0, (MAX_LOGICAL_DRIVES + 1) *
sizeof(struct MR_LD_VF_AFFILIATION));
else {
new_affiliation =
pci_alloc_consistent(instance->pdev,
(MAX_LOGICAL_DRIVES + 1) *
sizeof(struct MR_LD_VF_AFFILIATION),
&new_affiliation_h);
if (!new_affiliation) {
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;
}
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;
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)
dcmd->sgl.sge32[0].phys_addr = instance->vf_affiliation_h;
else
dcmd->sgl.sge32[0].phys_addr = new_affiliation_h;
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 (!new_affiliation->ldCount) { if (!new_affiliation->ldCount) {
printk(KERN_WARNING "megasas: SR-IOV: Got new " printk(KERN_WARNING "megasas: SR-IOV: Got new LD/VF "
"LD/VF affiliation for passive " "affiliation for passive path for scsi%d.\n",
"path for scsi%d.\n",
instance->host->host_no); instance->host->host_no);
retval = 1; retval = 1;
goto out; goto out;
...@@ -1977,46 +2026,93 @@ static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance, ...@@ -1977,46 +2026,93 @@ static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance,
newmap = new_affiliation->map; newmap = new_affiliation->map;
savedmap = instance->vf_affiliation->map; savedmap = instance->vf_affiliation->map;
thisVf = new_affiliation->thisVf; thisVf = new_affiliation->thisVf;
for (ld = 0 ; ld < new_affiliation->ldCount; ld++) { for (i = 0 ; i < new_affiliation->ldCount; i++) {
if (savedmap->policy[thisVf] != found = 0;
newmap->policy[thisVf]) { for (j = 0; j < instance->vf_affiliation->ldCount;
printk(KERN_WARNING "megasas: SR-IOV: " j++) {
"Got new LD/VF affiliation " if (newmap->ref.targetId ==
"for scsi%d.\n", savedmap->ref.targetId) {
instance->host->host_no); found = 1;
memcpy(instance->vf_affiliation, if (newmap->policy[thisVf] !=
new_affiliation, savedmap->policy[thisVf]) {
new_affiliation->size); doscan = 1;
retval = 1;
goto out; goto out;
} }
}
savedmap = (struct MR_LD_VF_MAP *) savedmap = (struct MR_LD_VF_MAP *)
((unsigned char *)savedmap + ((unsigned char *)savedmap +
savedmap->size); savedmap->size);
}
if (!found && newmap->policy[thisVf] !=
MR_LD_ACCESS_HIDDEN) {
doscan = 1;
goto out;
}
newmap = (struct MR_LD_VF_MAP *)
((unsigned char *)newmap + newmap->size);
}
newmap = new_affiliation->map;
savedmap = instance->vf_affiliation->map;
for (i = 0 ; i < instance->vf_affiliation->ldCount; i++) {
found = 0;
for (j = 0 ; j < new_affiliation->ldCount; j++) {
if (savedmap->ref.targetId ==
newmap->ref.targetId) {
found = 1;
if (savedmap->policy[thisVf] !=
newmap->policy[thisVf]) {
doscan = 1;
goto out;
}
}
newmap = (struct MR_LD_VF_MAP *) newmap = (struct MR_LD_VF_MAP *)
((unsigned char *)newmap + ((unsigned char *)newmap +
newmap->size); newmap->size);
} }
if (!found && savedmap->policy[thisVf] !=
MR_LD_ACCESS_HIDDEN) {
doscan = 1;
goto out;
}
savedmap = (struct MR_LD_VF_MAP *)
((unsigned char *)savedmap +
savedmap->size);
} }
} }
out: out:
if (new_affiliation) { if (doscan) {
if (instance->PlasmaFW111) printk(KERN_WARNING "megasas: SR-IOV: Got new LD/VF "
pci_free_consistent(instance->pdev, "affiliation for scsi%d.\n", instance->host->host_no);
sizeof(struct MR_LD_VF_AFFILIATION_111), memcpy(instance->vf_affiliation, new_affiliation,
new_affiliation_111, new_affiliation->size);
new_affiliation_111_h); retval = 1;
else }
if (new_affiliation)
pci_free_consistent(instance->pdev, pci_free_consistent(instance->pdev,
(MAX_LOGICAL_DRIVES + 1) * (MAX_LOGICAL_DRIVES + 1) *
sizeof(struct MR_LD_VF_AFFILIATION), sizeof(struct MR_LD_VF_AFFILIATION),
new_affiliation, new_affiliation_h); new_affiliation, new_affiliation_h);
}
megasas_return_cmd(instance, cmd); megasas_return_cmd(instance, cmd);
return retval; return retval;
} }
/* This function will get the current SR-IOV LD/VF affiliation */
static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance,
int initial)
{
int retval;
if (instance->PlasmaFW111)
retval = megasas_get_ld_vf_affiliation_111(instance, initial);
else
retval = megasas_get_ld_vf_affiliation_12(instance, initial);
return retval;
}
/* This function will tell FW to start the SR-IOV heartbeat */ /* This function will tell FW to start the SR-IOV heartbeat */
int megasas_sriov_start_heartbeat(struct megasas_instance *instance, int megasas_sriov_start_heartbeat(struct megasas_instance *instance,
int initial) int initial)
......
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