diff options
Diffstat (limited to 'drivers/scsi/megaraid')
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.h | 37 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_base.c | 171 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_fp.c | 28 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_fusion.c | 99 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_fusion.h | 6 |
5 files changed, 201 insertions, 140 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index f5a36ccb8606..ba6503f37756 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -35,8 +35,8 @@ /* * MegaRAID SAS Driver meta data */ -#define MEGASAS_VERSION "07.703.05.00-rc1" -#define MEGASAS_RELDATE "October 5, 2017" +#define MEGASAS_VERSION "07.704.04.00-rc1" +#define MEGASAS_RELDATE "December 7, 2017" /* * Device IDs @@ -197,6 +197,7 @@ enum MFI_CMD_OP { MFI_CMD_ABORT = 0x6, MFI_CMD_SMP = 0x7, MFI_CMD_STP = 0x8, + MFI_CMD_NVME = 0x9, MFI_CMD_OP_COUNT, MFI_CMD_INVALID = 0xff }; @@ -230,7 +231,7 @@ enum MFI_CMD_OP { /* * Global functions */ -extern u8 MR_ValidateMapInfo(struct megasas_instance *instance); +extern u8 MR_ValidateMapInfo(struct megasas_instance *instance, u64 map_id); /* @@ -1352,7 +1353,13 @@ struct megasas_ctrl_info { struct { #if defined(__BIG_ENDIAN_BITFIELD) - u16 reserved:8; + u16 reserved:2; + u16 support_nvme_passthru:1; + u16 support_pl_debug_info:1; + u16 support_flash_comp_info:1; + u16 support_host_info:1; + u16 support_dual_fw_update:1; + u16 support_ssc_rev3:1; u16 fw_swaps_bbu_vpd_info:1; u16 support_pd_map_target_id:1; u16 support_ses_ctrl_in_multipathcfg:1; @@ -1377,7 +1384,19 @@ struct megasas_ctrl_info { * provide the data in little endian order */ u16 fw_swaps_bbu_vpd_info:1; - u16 reserved:8; + u16 support_ssc_rev3:1; + /* FW supports CacheCade 3.0, only one SSCD creation allowed */ + u16 support_dual_fw_update:1; + /* FW supports dual firmware update feature */ + u16 support_host_info:1; + /* FW supports MR_DCMD_CTRL_HOST_INFO_SET/GET */ + u16 support_flash_comp_info:1; + /* FW supports MR_DCMD_CTRL_FLASH_COMP_INFO_GET */ + u16 support_pl_debug_info:1; + /* FW supports retrieval of PL debug information through apps */ + u16 support_nvme_passthru:1; + /* FW supports NVMe passthru commands */ + u16 reserved:2; #endif } adapter_operations4; u8 pad[0x800 - 0x7FE]; /* 0x7FE pad to 2K for expansion */ @@ -1630,7 +1649,8 @@ union megasas_sgl_frame { typedef union _MFI_CAPABILITIES { struct { #if defined(__BIG_ENDIAN_BITFIELD) - u32 reserved:18; + u32 reserved:17; + u32 support_nvme_passthru:1; u32 support_64bit_mode:1; u32 support_pd_map_target_id:1; u32 support_qd_throttling:1; @@ -1660,7 +1680,8 @@ typedef union _MFI_CAPABILITIES { u32 support_qd_throttling:1; u32 support_pd_map_target_id:1; u32 support_64bit_mode:1; - u32 reserved:18; + u32 support_nvme_passthru:1; + u32 reserved:17; #endif } mfi_capabilities; __le32 reg; @@ -2188,7 +2209,6 @@ struct megasas_instance { struct megasas_evt_detail *evt_detail; dma_addr_t evt_detail_h; struct megasas_cmd *aen_cmd; - struct mutex hba_mutex; struct semaphore ioctl_sem; struct Scsi_Host *host; @@ -2269,6 +2289,7 @@ struct megasas_instance { u32 nvme_page_size; u8 adapter_type; bool consistent_mask_64bit; + bool support_nvme_passthru; }; struct MR_LD_VF_MAP { u32 size; 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"); diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c index bfad9bfc313f..59ecbb3b53b5 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fp.c +++ b/drivers/scsi/megaraid/megaraid_sas_fp.c @@ -168,7 +168,7 @@ static struct MR_LD_SPAN *MR_LdSpanPtrGet(u32 ld, u32 span, /* * This function will Populate Driver Map using firmware raid map */ -void MR_PopulateDrvRaidMap(struct megasas_instance *instance) +static int MR_PopulateDrvRaidMap(struct megasas_instance *instance, u64 map_id) { struct fusion_context *fusion = instance->ctrl_context; struct MR_FW_RAID_MAP_ALL *fw_map_old = NULL; @@ -181,7 +181,7 @@ void MR_PopulateDrvRaidMap(struct megasas_instance *instance) struct MR_DRV_RAID_MAP_ALL *drv_map = - fusion->ld_drv_map[(instance->map_id & 1)]; + fusion->ld_drv_map[(map_id & 1)]; struct MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap; void *raid_map_data = NULL; @@ -190,7 +190,7 @@ void MR_PopulateDrvRaidMap(struct megasas_instance *instance) 0xff, (sizeof(u16) * MAX_LOGICAL_DRIVES_DYN)); if (instance->max_raid_mapsize) { - fw_map_dyn = fusion->ld_map[(instance->map_id & 1)]; + fw_map_dyn = fusion->ld_map[(map_id & 1)]; desc_table = (struct MR_RAID_MAP_DESC_TABLE *)((void *)fw_map_dyn + le32_to_cpu(fw_map_dyn->desc_table_offset)); if (desc_table != fw_map_dyn->raid_map_desc_table) @@ -255,11 +255,11 @@ void MR_PopulateDrvRaidMap(struct megasas_instance *instance) } else if (instance->supportmax256vd) { fw_map_ext = - (struct MR_FW_RAID_MAP_EXT *)fusion->ld_map[(instance->map_id & 1)]; + (struct MR_FW_RAID_MAP_EXT *)fusion->ld_map[(map_id & 1)]; ld_count = (u16)le16_to_cpu(fw_map_ext->ldCount); if (ld_count > MAX_LOGICAL_DRIVES_EXT) { dev_dbg(&instance->pdev->dev, "megaraid_sas: LD count exposed in RAID map in not valid\n"); - return; + return 1; } pDrvRaidMap->ldCount = (__le16)cpu_to_le16(ld_count); @@ -282,9 +282,15 @@ void MR_PopulateDrvRaidMap(struct megasas_instance *instance) cpu_to_le32(sizeof(struct MR_FW_RAID_MAP_EXT)); } else { fw_map_old = (struct MR_FW_RAID_MAP_ALL *) - fusion->ld_map[(instance->map_id & 1)]; + fusion->ld_map[(map_id & 1)]; pFwRaidMap = &fw_map_old->raidMap; ld_count = (u16)le32_to_cpu(pFwRaidMap->ldCount); + if (ld_count > MAX_LOGICAL_DRIVES) { + dev_dbg(&instance->pdev->dev, + "LD count exposed in RAID map in not valid\n"); + return 1; + } + pDrvRaidMap->totalSize = pFwRaidMap->totalSize; pDrvRaidMap->ldCount = (__le16)cpu_to_le16(ld_count); pDrvRaidMap->fpPdIoTimeoutSec = pFwRaidMap->fpPdIoTimeoutSec; @@ -300,12 +306,14 @@ void MR_PopulateDrvRaidMap(struct megasas_instance *instance) sizeof(struct MR_DEV_HANDLE_INFO) * MAX_RAIDMAP_PHYSICAL_DEVICES); } + + return 0; } /* * This function will validate Map info data provided by FW */ -u8 MR_ValidateMapInfo(struct megasas_instance *instance) +u8 MR_ValidateMapInfo(struct megasas_instance *instance, u64 map_id) { struct fusion_context *fusion; struct MR_DRV_RAID_MAP_ALL *drv_map; @@ -317,11 +325,11 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance) u16 ld; u32 expected_size; - - MR_PopulateDrvRaidMap(instance); + if (MR_PopulateDrvRaidMap(instance, map_id)) + return 0; fusion = instance->ctrl_context; - drv_map = fusion->ld_drv_map[(instance->map_id & 1)]; + drv_map = fusion->ld_drv_map[(map_id & 1)]; pDrvRaidMap = &drv_map->raidMap; lbInfo = fusion->load_balance_info; diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 65dc4fea6352..073ced07e662 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -983,7 +983,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) MFI_CAPABILITIES *drv_ops; u32 scratch_pad_2; unsigned long flags; - struct timeval tv; + ktime_t time; bool cur_fw_64bit_dma_capable; fusion = instance->ctrl_context; @@ -1042,13 +1042,12 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) IOCInitMessage->HostMSIxVectors = instance->msix_vectors; IOCInitMessage->HostPageSize = MR_DEFAULT_NVME_PAGE_SHIFT; - do_gettimeofday(&tv); + time = ktime_get_real(); /* Convert to milliseconds as per FW requirement */ - IOCInitMessage->TimeStamp = cpu_to_le64((tv.tv_sec * 1000) + - (tv.tv_usec / 1000)); + IOCInitMessage->TimeStamp = cpu_to_le64(ktime_to_ms(time)); init_frame = (struct megasas_init_frame *)cmd->frame; - memset(init_frame, 0, MEGAMFI_FRAME_SIZE); + memset(init_frame, 0, IOC_INIT_FRAME_SIZE); frame_hdr = &cmd->frame->hdr; frame_hdr->cmd_status = 0xFF; @@ -1080,6 +1079,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) drv_ops->mfi_capabilities.support_qd_throttling = 1; drv_ops->mfi_capabilities.support_pd_map_target_id = 1; + drv_ops->mfi_capabilities.support_nvme_passthru = 1; if (instance->consistent_mask_64bit) drv_ops->mfi_capabilities.support_64bit_mode = 1; @@ -1320,7 +1320,7 @@ megasas_get_map_info(struct megasas_instance *instance) fusion->fast_path_io = 0; if (!megasas_get_ld_map_info(instance)) { - if (MR_ValidateMapInfo(instance)) { + if (MR_ValidateMapInfo(instance, instance->map_id)) { fusion->fast_path_io = 1; return 0; } @@ -1603,7 +1603,7 @@ static int megasas_alloc_ioc_init_frame(struct megasas_instance *instance) fusion = instance->ctrl_context; - cmd = kmalloc(sizeof(struct megasas_cmd), GFP_KERNEL); + cmd = kzalloc(sizeof(struct megasas_cmd), GFP_KERNEL); if (!cmd) { dev_err(&instance->pdev->dev, "Failed from func: %s line: %d\n", @@ -2664,16 +2664,6 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, praid_context = &io_request->RaidContext; if (instance->adapter_type == VENTURA_SERIES) { - spin_lock_irqsave(&instance->stream_lock, spinlock_flags); - megasas_stream_detect(instance, cmd, &io_info); - spin_unlock_irqrestore(&instance->stream_lock, spinlock_flags); - /* In ventura if stream detected for a read and it is read ahead - * capable make this IO as LDIO - */ - if (is_stream_detected(&io_request->RaidContext.raid_context_g35) && - io_info.isRead && io_info.ra_capable) - fp_possible = false; - /* FP for Optimal raid level 1. * All large RAID-1 writes (> 32 KiB, both WT and WB modes) * are built by the driver as LD I/Os. @@ -2699,6 +2689,20 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, } } + if (!fp_possible || + (io_info.isRead && io_info.ra_capable)) { + spin_lock_irqsave(&instance->stream_lock, + spinlock_flags); + megasas_stream_detect(instance, cmd, &io_info); + spin_unlock_irqrestore(&instance->stream_lock, + spinlock_flags); + /* In ventura if stream detected for a read and it is + * read ahead capable make this IO as LDIO + */ + if (is_stream_detected(&io_request->RaidContext.raid_context_g35)) + fp_possible = false; + } + /* If raid is NULL, set CPU affinity to default CPU0 */ if (raid) megasas_set_raidflag_cpu_affinity(praid_context, @@ -3953,6 +3957,8 @@ void megasas_refire_mgmt_cmd(struct megasas_instance *instance) union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; u16 smid; bool refire_cmd = 0; + u8 result; + u32 opcode = 0; fusion = instance->ctrl_context; @@ -3963,29 +3969,53 @@ void megasas_refire_mgmt_cmd(struct megasas_instance *instance) cmd_fusion = fusion->cmd_list[j]; cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx]; smid = le16_to_cpu(cmd_mfi->context.smid); + result = REFIRE_CMD; if (!smid) continue; - /* Do not refire shutdown command */ - if (le32_to_cpu(cmd_mfi->frame->dcmd.opcode) == - MR_DCMD_CTRL_SHUTDOWN) { - cmd_mfi->frame->dcmd.cmd_status = MFI_STAT_OK; - megasas_complete_cmd(instance, cmd_mfi, DID_OK); - continue; + req_desc = megasas_get_request_descriptor(instance, smid - 1); + + switch (cmd_mfi->frame->hdr.cmd) { + case MFI_CMD_DCMD: + opcode = le32_to_cpu(cmd_mfi->frame->dcmd.opcode); + /* Do not refire shutdown command */ + if (opcode == MR_DCMD_CTRL_SHUTDOWN) { + cmd_mfi->frame->dcmd.cmd_status = MFI_STAT_OK; + result = COMPLETE_CMD; + break; + } + + refire_cmd = ((opcode != MR_DCMD_LD_MAP_GET_INFO)) && + (opcode != MR_DCMD_SYSTEM_PD_MAP_GET_INFO) && + !(cmd_mfi->flags & DRV_DCMD_SKIP_REFIRE); + + if (!refire_cmd) + result = RETURN_CMD; + + break; + case MFI_CMD_NVME: + if (!instance->support_nvme_passthru) { + cmd_mfi->frame->hdr.cmd_status = MFI_STAT_INVALID_CMD; + result = COMPLETE_CMD; + } + + break; + default: + break; } - req_desc = megasas_get_request_descriptor - (instance, smid - 1); - refire_cmd = req_desc && ((cmd_mfi->frame->dcmd.opcode != - cpu_to_le32(MR_DCMD_LD_MAP_GET_INFO)) && - (cmd_mfi->frame->dcmd.opcode != - cpu_to_le32(MR_DCMD_SYSTEM_PD_MAP_GET_INFO))) - && !(cmd_mfi->flags & DRV_DCMD_SKIP_REFIRE); - if (refire_cmd) + switch (result) { + case REFIRE_CMD: megasas_fire_cmd_fusion(instance, req_desc); - else + break; + case RETURN_CMD: megasas_return_cmd(instance, cmd_mfi); + break; + case COMPLETE_CMD: + megasas_complete_cmd(instance, cmd_mfi, DID_OK); + break; + } } } @@ -4625,8 +4655,6 @@ transition_to_ready: continue; } - megasas_refire_mgmt_cmd(instance); - if (megasas_get_ctrl_info(instance)) { dev_info(&instance->pdev->dev, "Failed from %s %d\n", @@ -4635,6 +4663,9 @@ transition_to_ready: retval = FAILED; goto out; } + + megasas_refire_mgmt_cmd(instance); + /* Reset load balance info */ if (fusion->load_balance_info) memset(fusion->load_balance_info, 0, diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h index 1814d79cb98d..8e5ebee6517f 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.h +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h @@ -1344,6 +1344,12 @@ union desc_value { } u; }; +enum CMD_RET_VALUES { + REFIRE_CMD = 1, + COMPLETE_CMD = 2, + RETURN_CMD = 3, +}; + void megasas_free_cmds_fusion(struct megasas_instance *instance); int megasas_ioc_init_fusion(struct megasas_instance *instance); u8 megasas_get_map_info(struct megasas_instance *instance); |