diff options
Diffstat (limited to 'drivers/scsi/megaraid/megaraid_sas_base.c')
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_base.c | 815 |
1 files changed, 684 insertions, 131 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 3b7ad10497fe..d84d02c2aad9 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * FILE: megaraid_sas_base.c - * Version : 06.700.06.00-rc1 + * Version : 06.803.01.00-rc1 * * Authors: LSI Corporation * Sreenivas Bagalkote @@ -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,13 +904,18 @@ 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); } /** * megasas_issue_blocked_cmd - Synchronous wrapper around regular FW cmds * @instance: Adapter soft state * @cmd: Command to be issued + * @timeout: Timeout in seconds * * This function waits on an event for the command to be returned from ISR. * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs @@ -905,13 +923,20 @@ megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd) */ static int megasas_issue_blocked_cmd(struct megasas_instance *instance, - struct megasas_cmd *cmd) + struct megasas_cmd *cmd, int timeout) { + int ret = 0; cmd->cmd_status = ENODATA; instance->instancet->issue_dcmd(instance, cmd); - - wait_event(instance->int_cmd_wait_q, cmd->cmd_status != ENODATA); + if (timeout) { + ret = wait_event_timeout(instance->int_cmd_wait_q, + cmd->cmd_status != ENODATA, timeout * HZ); + if (!ret) + return 1; + } else + wait_event(instance->int_cmd_wait_q, + cmd->cmd_status != ENODATA); return 0; } @@ -920,18 +945,20 @@ megasas_issue_blocked_cmd(struct megasas_instance *instance, * megasas_issue_blocked_abort_cmd - Aborts previously issued cmd * @instance: Adapter soft state * @cmd_to_abort: Previously issued cmd to be aborted + * @timeout: Timeout in seconds * - * MFI firmware can abort previously issued AEN command (automatic event + * MFI firmware can abort previously issued AEN comamnd (automatic event * notification). The megasas_issue_blocked_abort_cmd() issues such abort * cmd and waits for return status. * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs */ static int megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, - struct megasas_cmd *cmd_to_abort) + struct megasas_cmd *cmd_to_abort, int timeout) { struct megasas_cmd *cmd; struct megasas_abort_frame *abort_fr; + int ret = 0; cmd = megasas_get_cmd(instance); @@ -957,10 +984,18 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, instance->instancet->issue_dcmd(instance, cmd); - /* - * Wait for this cmd to complete - */ - wait_event(instance->abort_cmd_wait_q, cmd->cmd_status != 0xFF); + if (timeout) { + ret = wait_event_timeout(instance->abort_cmd_wait_q, + cmd->cmd_status != ENODATA, timeout * HZ); + if (!ret) { + dev_err(&instance->pdev->dev, "Command timedout" + "from %s\n", __func__); + return 1; + } + } else + wait_event(instance->abort_cmd_wait_q, + cmd->cmd_status != ENODATA); + cmd->sync_cmd = 0; megasas_return_cmd(instance, cmd); @@ -1514,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; } @@ -1641,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); } @@ -1730,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); @@ -1752,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 @@ -2014,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); @@ -2731,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)) { @@ -2755,6 +3120,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)) { @@ -2780,6 +3147,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)) { @@ -2788,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)) { @@ -3014,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)) @@ -3620,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); @@ -3642,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; @@ -3696,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; @@ -3763,7 +4138,10 @@ static int megasas_init_fw(struct megasas_instance *instance) memset(instance->pd_list, 0 , (MEGASAS_MAX_PD * sizeof(struct megasas_pd_list))); - megasas_get_pd_list(instance); + if (megasas_get_pd_list(instance) < 0) { + printk(KERN_ERR "megasas: failed to get PD list\n"); + goto fail_init_adapter; + } memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); if (megasas_ld_list_query(instance, @@ -3807,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) { @@ -3819,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; @@ -3851,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: @@ -3933,16 +4337,19 @@ megasas_get_seq_num(struct megasas_instance *instance, dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(el_info_h); dcmd->sgl.sge32[0].length = cpu_to_le32(sizeof(struct megasas_evt_log_info)); - megasas_issue_blocked_cmd(instance, cmd); - - /* - * Copy the data back into callers buffer - */ - eli->newest_seq_num = le32_to_cpu(el_info->newest_seq_num); - eli->oldest_seq_num = le32_to_cpu(el_info->oldest_seq_num); - eli->clear_seq_num = le32_to_cpu(el_info->clear_seq_num); - eli->shutdown_seq_num = le32_to_cpu(el_info->shutdown_seq_num); - eli->boot_seq_num = le32_to_cpu(el_info->boot_seq_num); + if (megasas_issue_blocked_cmd(instance, cmd, 30)) + dev_err(&instance->pdev->dev, "Command timedout" + "from %s\n", __func__); + else { + /* + * Copy the data back into callers buffer + */ + eli->newest_seq_num = le32_to_cpu(el_info->newest_seq_num); + eli->oldest_seq_num = le32_to_cpu(el_info->oldest_seq_num); + eli->clear_seq_num = le32_to_cpu(el_info->clear_seq_num); + eli->shutdown_seq_num = le32_to_cpu(el_info->shutdown_seq_num); + eli->boot_seq_num = le32_to_cpu(el_info->boot_seq_num); + } pci_free_consistent(instance->pdev, sizeof(struct megasas_evt_log_info), el_info, el_info_h); @@ -4018,7 +4425,7 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num, instance->aen_cmd->abort_aen = 1; ret_val = megasas_issue_blocked_abort_cmd(instance, instance-> - aen_cmd); + aen_cmd, 30); if (ret_val) { printk(KERN_DEBUG "megasas: Failed to abort " @@ -4160,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; @@ -4197,6 +4605,19 @@ megasas_set_dma_mask(struct pci_dev *pdev) if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) goto fail_set_dma_mask; } + /* + * Ensure that all data structures are allocated in 32-bit + * memory. + */ + if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) { + /* Try 32bit DMA mask and 32 bit Consistent dma mask */ + if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) + && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) + dev_info(&pdev->dev, "set 32bit DMA mask" + "and 32 bit consistent mask\n"); + else + goto fail_set_dma_mask; + } return 0; @@ -4212,7 +4633,7 @@ fail_set_dma_mask: static int megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) { - int rval, pos, i, j; + int rval, pos, i, j, cpu; struct Scsi_Host *host; struct megasas_instance *instance; u16 control = 0; @@ -4272,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: { @@ -4368,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); @@ -4380,12 +4803,33 @@ 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 */ if (instance->msix_vectors) { - for (i = 0 ; i < instance->msix_vectors; i++) { + cpu = cpumask_first(cpu_online_mask); + for (i = 0; i < instance->msix_vectors; i++) { instance->irq_context[i].instance = instance; instance->irq_context[i].MSIxIndex = i; if (request_irq(instance->msixentry[i].vector, @@ -4394,14 +4838,22 @@ retry_irq_register: &instance->irq_context[i])) { printk(KERN_DEBUG "megasas: Failed to " "register IRQ for vector %d.\n", i); - for (j = 0 ; j < i ; j++) + for (j = 0; j < i; j++) { + irq_set_affinity_hint( + instance->msixentry[j].vector, NULL); free_irq( instance->msixentry[j].vector, &instance->irq_context[j]); + } /* Retry irq register for IO_APIC */ instance->msix_vectors = 0; goto retry_irq_register; } + if (irq_set_affinity_hint(instance->msixentry[i].vector, + get_cpu_mask(cpu))) + dev_err(&instance->pdev->dev, "Error setting" + "affinity hint for cpu %d\n", cpu); + cpu = cpumask_next(cpu, cpu_online_mask); } } else { instance->irq_context[0].instance = instance; @@ -4455,13 +4907,17 @@ retry_irq_register: instance->instancet->disable_intr(instance); if (instance->msix_vectors) - for (i = 0 ; i < instance->msix_vectors; i++) + for (i = 0; i < instance->msix_vectors; i++) { + irq_set_affinity_hint( + instance->msixentry[i].vector, NULL); free_irq(instance->msixentry[i].vector, &instance->irq_context[i]); + } else 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); @@ -4522,7 +4978,9 @@ static void megasas_flush_cache(struct megasas_instance *instance) dcmd->opcode = cpu_to_le32(MR_DCMD_CTRL_CACHE_FLUSH); dcmd->mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE; - megasas_issue_blocked_cmd(instance, cmd); + if (megasas_issue_blocked_cmd(instance, cmd, 30)) + dev_err(&instance->pdev->dev, "Command timedout" + " from %s\n", __func__); megasas_return_cmd(instance, cmd); @@ -4549,10 +5007,11 @@ static void megasas_shutdown_controller(struct megasas_instance *instance, return; if (instance->aen_cmd) - megasas_issue_blocked_abort_cmd(instance, instance->aen_cmd); + megasas_issue_blocked_abort_cmd(instance, + instance->aen_cmd, 30); if (instance->map_update_cmd) megasas_issue_blocked_abort_cmd(instance, - instance->map_update_cmd); + instance->map_update_cmd, 30); dcmd = &cmd->frame->dcmd; memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); @@ -4566,7 +5025,9 @@ static void megasas_shutdown_controller(struct megasas_instance *instance, dcmd->data_xfer_len = 0; dcmd->opcode = cpu_to_le32(opcode); - megasas_issue_blocked_cmd(instance, cmd); + if (megasas_issue_blocked_cmd(instance, cmd, 30)) + dev_err(&instance->pdev->dev, "Command timedout" + "from %s\n", __func__); megasas_return_cmd(instance, cmd); @@ -4590,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); @@ -4606,9 +5071,12 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state) instance->instancet->disable_intr(instance); if (instance->msix_vectors) - for (i = 0 ; i < instance->msix_vectors; i++) + for (i = 0; i < instance->msix_vectors; i++) { + irq_set_affinity_hint( + instance->msixentry[i].vector, NULL); free_irq(instance->msixentry[i].vector, &instance->irq_context[i]); + } else free_irq(instance->pdev->irq, &instance->irq_context[0]); if (instance->msix_vectors) @@ -4629,7 +5097,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state) static int megasas_resume(struct pci_dev *pdev) { - int rval, i, j; + int rval, i, j, cpu; struct Scsi_Host *host; struct megasas_instance *instance; @@ -4673,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: { @@ -4701,6 +5170,7 @@ megasas_resume(struct pci_dev *pdev) * Register IRQ */ if (instance->msix_vectors) { + cpu = cpumask_first(cpu_online_mask); for (i = 0 ; i < instance->msix_vectors; i++) { instance->irq_context[i].instance = instance; instance->irq_context[i].MSIxIndex = i; @@ -4710,12 +5180,21 @@ megasas_resume(struct pci_dev *pdev) &instance->irq_context[i])) { printk(KERN_DEBUG "megasas: Failed to " "register IRQ for vector %d.\n", i); - for (j = 0 ; j < i ; j++) + for (j = 0; j < i; j++) { + irq_set_affinity_hint( + instance->msixentry[j].vector, NULL); free_irq( instance->msixentry[j].vector, &instance->irq_context[j]); + } goto fail_irq; } + + if (irq_set_affinity_hint(instance->msixentry[i].vector, + get_cpu_mask(cpu))) + dev_err(&instance->pdev->dev, "Error setting" + "affinity hint for cpu %d\n", cpu); + cpu = cpumask_next(cpu, cpu_online_mask); } } else { instance->irq_context[0].instance = instance; @@ -4728,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; @@ -4782,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); @@ -4793,6 +5287,9 @@ static void megasas_detach_one(struct pci_dev *pdev) instance->ev = NULL; } + /* cancel all wait events */ + wake_up_all(&instance->int_cmd_wait_q); + tasklet_kill(&instance->isr_tasklet); /* @@ -4811,9 +5308,12 @@ static void megasas_detach_one(struct pci_dev *pdev) instance->instancet->disable_intr(instance); if (instance->msix_vectors) - for (i = 0 ; i < instance->msix_vectors; i++) + for (i = 0; i < instance->msix_vectors; i++) { + irq_set_affinity_hint( + instance->msixentry[i].vector, NULL); free_irq(instance->msixentry[i].vector, &instance->irq_context[i]); + } else free_irq(instance->pdev->irq, &instance->irq_context[0]); if (instance->msix_vectors) @@ -4821,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); @@ -4847,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); @@ -4868,9 +5387,12 @@ static void megasas_shutdown(struct pci_dev *pdev) megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); instance->instancet->disable_intr(instance); if (instance->msix_vectors) - for (i = 0 ; i < instance->msix_vectors; i++) + for (i = 0; i < instance->msix_vectors; i++) { + irq_set_affinity_hint( + instance->msixentry[i].vector, NULL); free_irq(instance->msixentry[i].vector, &instance->irq_context[i]); + } else free_irq(instance->pdev->irq, &instance->irq_context[0]); if (instance->msix_vectors) @@ -5045,7 +5567,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, * cmd to the SCSI mid-layer */ cmd->sync_cmd = 1; - megasas_issue_blocked_cmd(instance, cmd); + megasas_issue_blocked_cmd(instance, cmd, 0); cmd->sync_cmd = 0; /* @@ -5132,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; @@ -5441,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) { @@ -5449,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) { @@ -5515,65 +6064,64 @@ megasas_aen_polling(struct work_struct *work) case MR_EVT_LD_OFFLINE: case MR_EVT_CFG_CLEARED: case MR_EVT_LD_DELETED: - 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++) { - - 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_device_put(sdev1); - } - } else { - if (sdev1) { - scsi_remove_device(sdev1); - scsi_device_put(sdev1); + 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++) { + + 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_device_put(sdev1); + } else { + if (sdev1) { + scsi_remove_device(sdev1); + scsi_device_put(sdev1); + } + } } } - } + doscan = 0; } - doscan = 0; break; case MR_EVT_LD_CREATED: - 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++) { - 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); + 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++) { + 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); } - } - if (sdev1) { - scsi_device_put(sdev1); + if (sdev1) + scsi_device_put(sdev1); } } + doscan = 0; } - doscan = 0; break; case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED: case MR_EVT_FOREIGN_CFG_IMPORTED: @@ -5591,50 +6139,55 @@ megasas_aen_polling(struct work_struct *work) } if (doscan) { - printk(KERN_INFO "scanning ...\n"); - megasas_get_pd_list(instance); - for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) { - for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) { - pd_index = i*MEGASAS_MAX_DEV_PER_CHANNEL + j; - sdev1 = scsi_device_lookup(host, i, j, 0); - if (instance->pd_list[pd_index].driveState == - MR_PD_STATE_SYSTEM) { - if (!sdev1) { - scsi_add_device(host, i, j, 0); - } - if (sdev1) - scsi_device_put(sdev1); - } else { - if (sdev1) { - scsi_remove_device(sdev1); - scsi_device_put(sdev1); + 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++) { + pd_index = i*MEGASAS_MAX_DEV_PER_CHANNEL + j; + sdev1 = scsi_device_lookup(host, i, j, 0); + if (instance->pd_list[pd_index].driveState == + MR_PD_STATE_SYSTEM) { + if (!sdev1) { + scsi_add_device(host, i, j, 0); + } + if (sdev1) + scsi_device_put(sdev1); + } else { + if (sdev1) { + scsi_remove_device(sdev1); + scsi_device_put(sdev1); + } } } } } - 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++) { - ld_index = - (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; + 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++) { + 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); + 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 + scsi_device_put(sdev1); } else { - scsi_device_put(sdev1); - } - } else { - if (sdev1) { - scsi_remove_device(sdev1); - scsi_device_put(sdev1); + if (sdev1) { + scsi_remove_device(sdev1); + scsi_device_put(sdev1); + } } } } |