diff options
Diffstat (limited to 'drivers/scsi/megaraid/megaraid_sas_base.c')
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_base.c | 171 |
1 files changed, 83 insertions, 88 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 2c8cfa27909d..2791141bd035 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -181,6 +181,7 @@ static DECLARE_WAIT_QUEUE_HEAD(megasas_poll_wait); static u32 support_poll_for_event; u32 megasas_dbg_lvl; static u32 support_device_change; +static bool support_nvme_encapsulation; /* define lock for aen poll */ spinlock_t poll_aen_lock; @@ -1952,7 +1953,7 @@ static int megasas_slave_configure(struct scsi_device *sdev) } } - mutex_lock(&instance->hba_mutex); + mutex_lock(&instance->reset_mutex); /* Send DCMD to Firmware and cache the information */ if ((instance->pd_info) && !MEGASAS_IS_LOGICAL(sdev)) megasas_get_pd_info(instance, sdev); @@ -1966,7 +1967,7 @@ static int megasas_slave_configure(struct scsi_device *sdev) is_target_prop = (ret_target_prop == DCMD_SUCCESS) ? true : false; megasas_set_static_target_properties(sdev, is_target_prop); - mutex_unlock(&instance->hba_mutex); + mutex_unlock(&instance->reset_mutex); /* This sdev property may change post OCR */ megasas_set_dynamic_target_properties(sdev); @@ -3122,6 +3123,16 @@ megasas_ldio_outstanding_show(struct device *cdev, struct device_attribute *attr return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&instance->ldio_outstanding)); } +static ssize_t +megasas_fw_cmds_outstanding_show(struct device *cdev, + struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct megasas_instance *instance = (struct megasas_instance *)shost->hostdata; + + return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&instance->fw_outstanding)); +} + static DEVICE_ATTR(fw_crash_buffer, S_IRUGO | S_IWUSR, megasas_fw_crash_buffer_show, megasas_fw_crash_buffer_store); static DEVICE_ATTR(fw_crash_buffer_size, S_IRUGO, @@ -3132,6 +3143,8 @@ static DEVICE_ATTR(page_size, S_IRUGO, megasas_page_size_show, NULL); static DEVICE_ATTR(ldio_outstanding, S_IRUGO, megasas_ldio_outstanding_show, NULL); +static DEVICE_ATTR(fw_cmds_outstanding, S_IRUGO, + megasas_fw_cmds_outstanding_show, NULL); struct device_attribute *megaraid_host_attrs[] = { &dev_attr_fw_crash_buffer_size, @@ -3139,6 +3152,7 @@ struct device_attribute *megaraid_host_attrs[] = { &dev_attr_fw_crash_state, &dev_attr_page_size, &dev_attr_ldio_outstanding, + &dev_attr_fw_cmds_outstanding, NULL, }; @@ -3321,6 +3335,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, case MFI_CMD_SMP: case MFI_CMD_STP: + case MFI_CMD_NVME: megasas_complete_int_cmd(instance, cmd); break; @@ -3331,10 +3346,10 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, && (cmd->frame->dcmd.mbox.b[1] == 1)) { fusion->fast_path_io = 0; spin_lock_irqsave(instance->host->host_lock, flags); + status = cmd->frame->hdr.cmd_status; instance->map_update_cmd = NULL; - if (cmd->frame->hdr.cmd_status != 0) { - if (cmd->frame->hdr.cmd_status != - MFI_STAT_NOT_FOUND) + if (status != MFI_STAT_OK) { + if (status != MFI_STAT_NOT_FOUND) dev_warn(&instance->pdev->dev, "map syncfailed, status = 0x%x\n", cmd->frame->hdr.cmd_status); else { @@ -3344,8 +3359,8 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, flags); break; } - } else - instance->map_id++; + } + megasas_return_cmd(instance, cmd); /* @@ -3353,10 +3368,14 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, * Validate Map will set proper value. * Meanwhile all IOs will go as LD IO. */ - if (MR_ValidateMapInfo(instance)) + if (status == MFI_STAT_OK && + (MR_ValidateMapInfo(instance, (instance->map_id + 1)))) { + instance->map_id++; fusion->fast_path_io = 1; - else + } else { fusion->fast_path_io = 0; + } + megasas_sync_map_info(instance); spin_unlock_irqrestore(instance->host->host_lock, flags); @@ -4677,10 +4696,12 @@ megasas_get_ctrl_info(struct megasas_instance *instance) sizeof(struct megasas_ctrl_info)); if ((instance->adapter_type != MFI_SERIES) && - !instance->mask_interrupts) + !instance->mask_interrupts) { ret = megasas_issue_blocked_cmd(instance, cmd, MFI_IO_TIMEOUT_SECS); - else + } else { ret = megasas_issue_polled(instance, cmd); + cmd->flags |= DRV_DCMD_SKIP_REFIRE; + } switch (ret) { case DCMD_SUCCESS: @@ -4702,6 +4723,8 @@ megasas_get_ctrl_info(struct megasas_instance *instance) ci->adapterOperations3.useSeqNumJbodFP; instance->support_morethan256jbod = ci->adapter_operations4.support_pd_map_target_id; + instance->support_nvme_passthru = + ci->adapter_operations4.support_nvme_passthru; /*Check whether controller is iMR or MR */ instance->is_imr = (ci->memory_size ? 0 : 1); @@ -4718,6 +4741,8 @@ megasas_get_ctrl_info(struct megasas_instance *instance) instance->disableOnlineCtrlReset ? "Disabled" : "Enabled"); dev_info(&instance->pdev->dev, "Secure JBOD support\t: %s\n", instance->secure_jbod_support ? "Yes" : "No"); + dev_info(&instance->pdev->dev, "NVMe passthru support\t: %s\n", + instance->support_nvme_passthru ? "Yes" : "No"); break; case DCMD_TIMEOUT: @@ -5387,7 +5412,7 @@ static int megasas_init_fw(struct megasas_instance *instance) } for (i = 0; i < MAX_LOGICAL_DRIVES_EXT; ++i) { fusion->stream_detect_by_ld[i] = - kmalloc(sizeof(struct LD_STREAM_DETECT), + kzalloc(sizeof(struct LD_STREAM_DETECT), GFP_KERNEL); if (!fusion->stream_detect_by_ld[i]) { dev_err(&instance->pdev->dev, @@ -5432,7 +5457,7 @@ static int megasas_init_fw(struct megasas_instance *instance) ctrl_info->adapterOperations2.supportUnevenSpans; if (instance->UnevenSpanSupport) { struct fusion_context *fusion = instance->ctrl_context; - if (MR_ValidateMapInfo(instance)) + if (MR_ValidateMapInfo(instance, instance->map_id)) fusion->fast_path_io = 1; else fusion->fast_path_io = 0; @@ -5581,6 +5606,7 @@ megasas_get_seq_num(struct megasas_instance *instance, struct megasas_dcmd_frame *dcmd; struct megasas_evt_log_info *el_info; dma_addr_t el_info_h = 0; + int ret; cmd = megasas_get_cmd(instance); @@ -5613,26 +5639,29 @@ megasas_get_seq_num(struct megasas_instance *instance, megasas_set_dma_settings(instance, dcmd, el_info_h, sizeof(struct megasas_evt_log_info)); - if (megasas_issue_blocked_cmd(instance, cmd, MFI_IO_TIMEOUT_SECS) == - DCMD_SUCCESS) { - /* - * Copy the data back into callers buffer - */ - eli->newest_seq_num = el_info->newest_seq_num; - eli->oldest_seq_num = el_info->oldest_seq_num; - eli->clear_seq_num = el_info->clear_seq_num; - eli->shutdown_seq_num = el_info->shutdown_seq_num; - eli->boot_seq_num = el_info->boot_seq_num; - } else - dev_err(&instance->pdev->dev, "DCMD failed " - "from %s\n", __func__); + ret = megasas_issue_blocked_cmd(instance, cmd, MFI_IO_TIMEOUT_SECS); + if (ret != DCMD_SUCCESS) { + dev_err(&instance->pdev->dev, "Failed from %s %d\n", + __func__, __LINE__); + goto dcmd_failed; + } + /* + * Copy the data back into callers buffer + */ + eli->newest_seq_num = el_info->newest_seq_num; + eli->oldest_seq_num = el_info->oldest_seq_num; + eli->clear_seq_num = el_info->clear_seq_num; + eli->shutdown_seq_num = el_info->shutdown_seq_num; + eli->boot_seq_num = el_info->boot_seq_num; + +dcmd_failed: pci_free_consistent(instance->pdev, sizeof(struct megasas_evt_log_info), el_info, el_info_h); megasas_return_cmd(instance, cmd); - return 0; + return ret; } /** @@ -6346,7 +6375,6 @@ static inline void megasas_init_ctrl_params(struct megasas_instance *instance) spin_lock_init(&instance->stream_lock); spin_lock_init(&instance->completion_lock); - mutex_init(&instance->hba_mutex); mutex_init(&instance->reset_mutex); if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || @@ -6704,6 +6732,7 @@ megasas_resume(struct pci_dev *pdev) */ atomic_set(&instance->fw_outstanding, 0); + atomic_set(&instance->ldio_outstanding, 0); /* Now re-enable MSI-X */ if (instance->msix_vectors) { @@ -6822,7 +6851,6 @@ static void megasas_detach_one(struct pci_dev *pdev) u32 pd_seq_map_sz; instance = pci_get_drvdata(pdev); - instance->unload = 1; host = instance->host; fusion = instance->ctrl_context; @@ -6833,6 +6861,7 @@ static void megasas_detach_one(struct pci_dev *pdev) if (instance->fw_crash_state != UNAVAILABLE) megasas_free_host_crash_buffer(instance); scsi_remove_host(instance->host); + instance->unload = 1; if (megasas_wait_for_adapter_operational(instance)) goto skip_firing_dcmds; @@ -7087,7 +7116,9 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, return -EINVAL; } - if (ioc->frame.hdr.cmd >= MFI_CMD_OP_COUNT) { + if ((ioc->frame.hdr.cmd >= MFI_CMD_OP_COUNT) || + ((ioc->frame.hdr.cmd == MFI_CMD_NVME) && + !instance->support_nvme_passthru)) { dev_err(&instance->pdev->dev, "Received invalid ioctl command 0x%x\n", ioc->frame.hdr.cmd); @@ -7301,9 +7332,6 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) struct megasas_iocpacket *ioc; struct megasas_instance *instance; int error; - int i; - unsigned long flags; - u32 wait_time = MEGASAS_RESET_WAIT_TIME; ioc = memdup_user(user_ioc, sizeof(*ioc)); if (IS_ERR(ioc)) @@ -7315,10 +7343,6 @@ 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; @@ -7341,32 +7365,10 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) goto out_kfree_ioc; } - for (i = 0; i < wait_time; i++) { - - spin_lock_irqsave(&instance->hba_lock, flags); - if (atomic_read(&instance->adprecovery) == MEGASAS_HBA_OPERATIONAL) { - spin_unlock_irqrestore(&instance->hba_lock, flags); - break; - } - spin_unlock_irqrestore(&instance->hba_lock, flags); - - if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { - dev_notice(&instance->pdev->dev, "waiting" - "for controller reset to finish\n"); - } - - msleep(1000); - } - - spin_lock_irqsave(&instance->hba_lock, flags); - if (atomic_read(&instance->adprecovery) != MEGASAS_HBA_OPERATIONAL) { - spin_unlock_irqrestore(&instance->hba_lock, flags); - - dev_err(&instance->pdev->dev, "timed out while waiting for HBA to recover\n"); + if (megasas_wait_for_adapter_operational(instance)) { error = -ENODEV; goto out_up; } - spin_unlock_irqrestore(&instance->hba_lock, flags); error = megasas_mgmt_fw_ioctl(instance, user_ioc, ioc); out_up: @@ -7382,9 +7384,6 @@ static int megasas_mgmt_ioctl_aen(struct file *file, unsigned long arg) struct megasas_instance *instance; struct megasas_aen aen; int error; - int i; - unsigned long flags; - u32 wait_time = MEGASAS_RESET_WAIT_TIME; if (file->private_data != file) { printk(KERN_DEBUG "megasas: fasync_helper was not " @@ -7408,32 +7407,8 @@ static int megasas_mgmt_ioctl_aen(struct file *file, unsigned long arg) return -ENODEV; } - for (i = 0; i < wait_time; i++) { - - spin_lock_irqsave(&instance->hba_lock, flags); - if (atomic_read(&instance->adprecovery) == MEGASAS_HBA_OPERATIONAL) { - spin_unlock_irqrestore(&instance->hba_lock, - flags); - break; - } - - spin_unlock_irqrestore(&instance->hba_lock, flags); - - if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { - dev_notice(&instance->pdev->dev, "waiting for" - "controller reset to finish\n"); - } - - msleep(1000); - } - - spin_lock_irqsave(&instance->hba_lock, flags); - if (atomic_read(&instance->adprecovery) != MEGASAS_HBA_OPERATIONAL) { - spin_unlock_irqrestore(&instance->hba_lock, flags); - dev_err(&instance->pdev->dev, "timed out while waiting for HBA to recover\n"); + if (megasas_wait_for_adapter_operational(instance)) return -ENODEV; - } - spin_unlock_irqrestore(&instance->hba_lock, flags); mutex_lock(&instance->reset_mutex); error = megasas_register_aen(instance, aen.seq_num, @@ -7613,6 +7588,14 @@ static ssize_t dbg_lvl_store(struct device_driver *dd, const char *buf, } static DRIVER_ATTR_RW(dbg_lvl); +static ssize_t +support_nvme_encapsulation_show(struct device_driver *dd, char *buf) +{ + return sprintf(buf, "%u\n", support_nvme_encapsulation); +} + +static DRIVER_ATTR_RO(support_nvme_encapsulation); + static inline void megasas_remove_scsi_device(struct scsi_device *sdev) { sdev_printk(KERN_INFO, sdev, "SCSI device is removed\n"); @@ -7801,6 +7784,7 @@ static int __init megasas_init(void) support_poll_for_event = 2; support_device_change = 1; + support_nvme_encapsulation = true; memset(&megasas_mgmt_info, 0, sizeof(megasas_mgmt_info)); @@ -7850,8 +7834,17 @@ static int __init megasas_init(void) if (rval) goto err_dcf_support_device_change; + rval = driver_create_file(&megasas_pci_driver.driver, + &driver_attr_support_nvme_encapsulation); + if (rval) + goto err_dcf_support_nvme_encapsulation; + return rval; +err_dcf_support_nvme_encapsulation: + driver_remove_file(&megasas_pci_driver.driver, + &driver_attr_support_device_change); + err_dcf_support_device_change: driver_remove_file(&megasas_pci_driver.driver, &driver_attr_dbg_lvl); @@ -7884,6 +7877,8 @@ static void __exit megasas_exit(void) driver_remove_file(&megasas_pci_driver.driver, &driver_attr_release_date); driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version); + driver_remove_file(&megasas_pci_driver.driver, + &driver_attr_support_nvme_encapsulation); pci_unregister_driver(&megasas_pci_driver); unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl"); |