diff options
Diffstat (limited to 'drivers/scsi/megaraid')
-rw-r--r-- | drivers/scsi/megaraid/megaraid_mbox.c | 2 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_mm.c | 28 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.h | 21 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_base.c | 237 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_fp.c | 7 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_fusion.c | 161 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_fusion.h | 18 |
7 files changed, 324 insertions, 150 deletions
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index f6ac819e6e96..8443f2f35be2 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -731,7 +731,7 @@ megaraid_init_mbox(adapter_t *adapter) goto out_free_raid_dev; } - raid_dev->baseaddr = ioremap_nocache(raid_dev->baseport, 128); + raid_dev->baseaddr = ioremap(raid_dev->baseport, 128); if (!raid_dev->baseaddr) { diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c index 59cca898f088..e83163c66884 100644 --- a/drivers/scsi/megaraid/megaraid_mm.c +++ b/drivers/scsi/megaraid/megaraid_mm.c @@ -41,10 +41,6 @@ static int mraid_mm_setup_dma_pools(mraid_mmadp_t *); static void mraid_mm_free_adp_resources(mraid_mmadp_t *); static void mraid_mm_teardown_dma_pools(mraid_mmadp_t *); -#ifdef CONFIG_COMPAT -static long mraid_mm_compat_ioctl(struct file *, unsigned int, unsigned long); -#endif - MODULE_AUTHOR("LSI Logic Corporation"); MODULE_DESCRIPTION("LSI Logic Management Module"); MODULE_LICENSE("GPL"); @@ -68,9 +64,7 @@ static wait_queue_head_t wait_q; static const struct file_operations lsi_fops = { .open = mraid_mm_open, .unlocked_ioctl = mraid_mm_unlocked_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = mraid_mm_compat_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, .owner = THIS_MODULE, .llseek = noop_llseek, }; @@ -224,7 +218,6 @@ mraid_mm_unlocked_ioctl(struct file *filep, unsigned int cmd, { int err; - /* inconsistent: mraid_mm_compat_ioctl doesn't take the BKL */ mutex_lock(&mraid_mm_mutex); err = mraid_mm_ioctl(filep, cmd, arg); mutex_unlock(&mraid_mm_mutex); @@ -1228,25 +1221,6 @@ mraid_mm_init(void) } -#ifdef CONFIG_COMPAT -/** - * mraid_mm_compat_ioctl - 32bit to 64bit ioctl conversion routine - * @filep : file operations pointer (ignored) - * @cmd : ioctl command - * @arg : user ioctl packet - */ -static long -mraid_mm_compat_ioctl(struct file *filep, unsigned int cmd, - unsigned long arg) -{ - int err; - - err = mraid_mm_ioctl(filep, cmd, arg); - - return err; -} -#endif - /** * mraid_mm_exit - Module exit point */ diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index a14e8344822b..83d8c4cb1ad5 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -21,8 +21,10 @@ /* * MegaRAID SAS Driver meta data */ -#define MEGASAS_VERSION "07.710.50.00-rc1" -#define MEGASAS_RELDATE "June 28, 2019" +#define MEGASAS_VERSION "07.713.01.00-rc1" +#define MEGASAS_RELDATE "Dec 27, 2019" + +#define MEGASAS_MSIX_NAME_LEN 32 /* * Device IDs @@ -2203,6 +2205,7 @@ struct megasas_aen_event { }; struct megasas_irq_context { + char name[MEGASAS_MSIX_NAME_LEN]; struct megasas_instance *instance; u32 MSIxIndex; u32 os_irq; @@ -2230,9 +2233,9 @@ enum MR_PD_TYPE { /* JBOD Queue depth definitions */ #define MEGASAS_SATA_QD 32 -#define MEGASAS_SAS_QD 64 +#define MEGASAS_SAS_QD 256 #define MEGASAS_DEFAULT_PD_QD 64 -#define MEGASAS_NVME_QD 32 +#define MEGASAS_NVME_QD 64 #define MR_DEFAULT_NVME_PAGE_SIZE 4096 #define MR_DEFAULT_NVME_PAGE_SHIFT 12 @@ -2429,6 +2432,7 @@ struct megasas_instance { u8 adapter_type; bool consistent_mask_64bit; bool support_nvme_passthru; + bool enable_sdev_max_qd; u8 task_abort_tmo; u8 max_reset_tmo; u8 snapdump_wait_time; @@ -2636,10 +2640,11 @@ enum MEGASAS_OCR_CAUSE { }; enum DCMD_RETURN_STATUS { - DCMD_SUCCESS = 0, - DCMD_TIMEOUT = 1, - DCMD_FAILED = 2, - DCMD_NOT_FIRED = 3, + DCMD_SUCCESS = 0x00, + DCMD_TIMEOUT = 0x01, + DCMD_FAILED = 0x02, + DCMD_BUSY = 0x03, + DCMD_INIT = 0xff, }; u8 diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index f9f07935556e..fd4b5ac6ac5b 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -109,6 +109,10 @@ int event_log_level = MFI_EVT_CLASS_CRITICAL; module_param(event_log_level, int, 0644); MODULE_PARM_DESC(event_log_level, "Asynchronous event logging level- range is: -2(CLASS_DEBUG) to 4(CLASS_DEAD), Default: 2(CLASS_CRITICAL)"); +unsigned int enable_sdev_max_qd; +module_param(enable_sdev_max_qd, int, 0444); +MODULE_PARM_DESC(enable_sdev_max_qd, "Enable sdev max qd as can_queue. Default: 0"); + MODULE_LICENSE("GPL"); MODULE_VERSION(MEGASAS_VERSION); MODULE_AUTHOR("megaraidlinux.pdl@broadcom.com"); @@ -195,7 +199,7 @@ static bool support_nvme_encapsulation; static bool support_pci_lane_margining; /* define lock for aen poll */ -spinlock_t poll_aen_lock; +static spinlock_t poll_aen_lock; extern struct dentry *megasas_debugfs_root; extern void megasas_init_debugfs(void); @@ -1095,7 +1099,7 @@ megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd) if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) { dev_err(&instance->pdev->dev, "Failed from %s %d\n", __func__, __LINE__); - return DCMD_NOT_FIRED; + return DCMD_INIT; } instance->instancet->issue_dcmd(instance, cmd); @@ -1119,19 +1123,19 @@ megasas_issue_blocked_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, int timeout) { int ret = 0; - cmd->cmd_status_drv = MFI_STAT_INVALID_STATUS; + cmd->cmd_status_drv = DCMD_INIT; if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) { dev_err(&instance->pdev->dev, "Failed from %s %d\n", __func__, __LINE__); - return DCMD_NOT_FIRED; + return DCMD_INIT; } instance->instancet->issue_dcmd(instance, cmd); if (timeout) { ret = wait_event_timeout(instance->int_cmd_wait_q, - cmd->cmd_status_drv != MFI_STAT_INVALID_STATUS, timeout * HZ); + cmd->cmd_status_drv != DCMD_INIT, timeout * HZ); if (!ret) { dev_err(&instance->pdev->dev, "DCMD(opcode: 0x%x) is timed out, func:%s\n", @@ -1140,10 +1144,9 @@ megasas_issue_blocked_cmd(struct megasas_instance *instance, } } else wait_event(instance->int_cmd_wait_q, - cmd->cmd_status_drv != MFI_STAT_INVALID_STATUS); + cmd->cmd_status_drv != DCMD_INIT); - return (cmd->cmd_status_drv == MFI_STAT_OK) ? - DCMD_SUCCESS : DCMD_FAILED; + return cmd->cmd_status_drv; } /** @@ -1186,19 +1189,19 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, cpu_to_le32(upper_32_bits(cmd_to_abort->frame_phys_addr)); cmd->sync_cmd = 1; - cmd->cmd_status_drv = MFI_STAT_INVALID_STATUS; + cmd->cmd_status_drv = DCMD_INIT; if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) { dev_err(&instance->pdev->dev, "Failed from %s %d\n", __func__, __LINE__); - return DCMD_NOT_FIRED; + return DCMD_INIT; } instance->instancet->issue_dcmd(instance, cmd); if (timeout) { ret = wait_event_timeout(instance->abort_cmd_wait_q, - cmd->cmd_status_drv != MFI_STAT_INVALID_STATUS, timeout * HZ); + cmd->cmd_status_drv != DCMD_INIT, timeout * HZ); if (!ret) { opcode = cmd_to_abort->frame->dcmd.opcode; dev_err(&instance->pdev->dev, @@ -1208,13 +1211,12 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, } } else wait_event(instance->abort_cmd_wait_q, - cmd->cmd_status_drv != MFI_STAT_INVALID_STATUS); + cmd->cmd_status_drv != DCMD_INIT); cmd->sync_cmd = 0; megasas_return_cmd(instance, cmd); - return (cmd->cmd_status_drv == MFI_STAT_OK) ? - DCMD_SUCCESS : DCMD_FAILED; + return cmd->cmd_status_drv; } /** @@ -1883,6 +1885,10 @@ void megasas_set_dynamic_target_properties(struct scsi_device *sdev, mr_device_priv_data->is_tm_capable = raid->capability.tmCapable; + + if (!raid->flags.isEPD) + sdev->no_write_same = 1; + } else if (instance->use_seqnum_jbod_fp) { pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + sdev->id; @@ -1941,25 +1947,19 @@ megasas_set_nvme_device_properties(struct scsi_device *sdev, u32 max_io_size) blk_queue_virt_boundary(sdev->request_queue, mr_nvme_pg_size - 1); } - /* - * megasas_set_static_target_properties - - * Device property set by driver are static and it is not required to be - * updated after OCR. - * - * set io timeout - * set device queue depth - * set nvme device properties. see - megasas_set_nvme_device_properties + * megasas_set_fw_assisted_qd - + * set device queue depth to can_queue + * set device queue depth to fw assisted qd * * @sdev: scsi device * @is_target_prop true, if fw provided target properties. */ -static void megasas_set_static_target_properties(struct scsi_device *sdev, +static void megasas_set_fw_assisted_qd(struct scsi_device *sdev, bool is_target_prop) { u8 interface_type; u32 device_qd = MEGASAS_DEFAULT_CMD_PER_LUN; - u32 max_io_size_kb = MR_DEFAULT_NVME_MDTS_KB; u32 tgt_device_qd; struct megasas_instance *instance; struct MR_PRIV_DEVICE *mr_device_priv_data; @@ -1968,11 +1968,6 @@ static void megasas_set_static_target_properties(struct scsi_device *sdev, mr_device_priv_data = sdev->hostdata; interface_type = mr_device_priv_data->interface_type; - /* - * The RAID firmware may require extended timeouts. - */ - blk_queue_rq_timeout(sdev->request_queue, scmd_timeout * HZ); - switch (interface_type) { case SAS_PD: device_qd = MEGASAS_SAS_QD; @@ -1990,18 +1985,49 @@ static void megasas_set_static_target_properties(struct scsi_device *sdev, if (tgt_device_qd && (tgt_device_qd <= instance->host->can_queue)) device_qd = tgt_device_qd; + } - /* max_io_size_kb will be set to non zero for - * nvme based vd and syspd. - */ + if (instance->enable_sdev_max_qd && interface_type != UNKNOWN_DRIVE) + device_qd = instance->host->can_queue; + + scsi_change_queue_depth(sdev, device_qd); +} + +/* + * megasas_set_static_target_properties - + * Device property set by driver are static and it is not required to be + * updated after OCR. + * + * set io timeout + * set device queue depth + * set nvme device properties. see - megasas_set_nvme_device_properties + * + * @sdev: scsi device + * @is_target_prop true, if fw provided target properties. + */ +static void megasas_set_static_target_properties(struct scsi_device *sdev, + bool is_target_prop) +{ + u32 max_io_size_kb = MR_DEFAULT_NVME_MDTS_KB; + struct megasas_instance *instance; + + instance = megasas_lookup_instance(sdev->host->host_no); + + /* + * The RAID firmware may require extended timeouts. + */ + blk_queue_rq_timeout(sdev->request_queue, scmd_timeout * HZ); + + /* max_io_size_kb will be set to non zero for + * nvme based vd and syspd. + */ + if (is_target_prop) max_io_size_kb = le32_to_cpu(instance->tgt_prop->max_io_size_kb); - } if (instance->nvme_page_size && max_io_size_kb) megasas_set_nvme_device_properties(sdev, (max_io_size_kb << 10)); - scsi_change_queue_depth(sdev, device_qd); - + megasas_set_fw_assisted_qd(sdev, is_target_prop); } @@ -2126,6 +2152,12 @@ static void megasas_complete_outstanding_ioctls(struct megasas_instance *instanc void megaraid_sas_kill_hba(struct megasas_instance *instance) { + if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) { + dev_warn(&instance->pdev->dev, + "Adapter already dead, skipping kill HBA\n"); + return; + } + /* Set critical error to block I/O & ioctls in case caller didn't */ atomic_set(&instance->adprecovery, MEGASAS_HW_CRITICAL_ERROR); /* Wait 1 second to ensure IO or ioctls in build have posted */ @@ -2702,7 +2734,7 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) "reset queue\n", reset_cmd); - reset_cmd->cmd_status_drv = MFI_STAT_INVALID_STATUS; + reset_cmd->cmd_status_drv = DCMD_INIT; instance->instancet->fire_cmd(instance, reset_cmd->frame_phys_addr, 0, instance->reg_set); @@ -3285,6 +3317,48 @@ fw_cmds_outstanding_show(struct device *cdev, } static ssize_t +enable_sdev_max_qd_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", instance->enable_sdev_max_qd); +} + +static ssize_t +enable_sdev_max_qd_store(struct device *cdev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct megasas_instance *instance = (struct megasas_instance *)shost->hostdata; + u32 val = 0; + bool is_target_prop; + int ret_target_prop = DCMD_FAILED; + struct scsi_device *sdev; + + if (kstrtou32(buf, 0, &val) != 0) { + pr_err("megasas: could not set enable_sdev_max_qd\n"); + return -EINVAL; + } + + mutex_lock(&instance->reset_mutex); + if (val) + instance->enable_sdev_max_qd = true; + else + instance->enable_sdev_max_qd = false; + + shost_for_each_device(sdev, shost) { + ret_target_prop = megasas_get_target_prop(instance, sdev); + is_target_prop = (ret_target_prop == DCMD_SUCCESS) ? true : false; + megasas_set_fw_assisted_qd(sdev, is_target_prop); + } + mutex_unlock(&instance->reset_mutex); + + return strlen(buf); +} + +static ssize_t dump_system_regs_show(struct device *cdev, struct device_attribute *attr, char *buf) { @@ -3313,6 +3387,7 @@ static DEVICE_ATTR_RW(fw_crash_state); static DEVICE_ATTR_RO(page_size); static DEVICE_ATTR_RO(ldio_outstanding); static DEVICE_ATTR_RO(fw_cmds_outstanding); +static DEVICE_ATTR_RW(enable_sdev_max_qd); static DEVICE_ATTR_RO(dump_system_regs); static DEVICE_ATTR_RO(raid_map_id); @@ -3323,6 +3398,7 @@ static struct device_attribute *megaraid_host_attrs[] = { &dev_attr_page_size, &dev_attr_ldio_outstanding, &dev_attr_fw_cmds_outstanding, + &dev_attr_enable_sdev_max_qd, &dev_attr_dump_system_regs, &dev_attr_raid_map_id, NULL, @@ -3348,7 +3424,6 @@ static struct scsi_host_template megasas_template = { .bios_param = megasas_bios_param, .change_queue_depth = scsi_change_queue_depth, .max_segment_size = 0xffffffff, - .no_write_same = 1, }; /** @@ -3364,7 +3439,11 @@ static void megasas_complete_int_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) { - cmd->cmd_status_drv = cmd->frame->io.cmd_status; + if (cmd->cmd_status_drv == DCMD_INIT) + cmd->cmd_status_drv = + (cmd->frame->io.cmd_status == MFI_STAT_OK) ? + DCMD_SUCCESS : DCMD_FAILED; + wake_up(&instance->int_cmd_wait_q); } @@ -3383,7 +3462,7 @@ megasas_complete_abort(struct megasas_instance *instance, { if (cmd->sync_cmd) { cmd->sync_cmd = 0; - cmd->cmd_status_drv = 0; + cmd->cmd_status_drv = DCMD_SUCCESS; wake_up(&instance->abort_cmd_wait_q); } } @@ -3659,7 +3738,7 @@ megasas_issue_pending_cmds_again(struct megasas_instance *instance) dev_notice(&instance->pdev->dev, "%p synchronous cmd" "on the internal reset queue," "issue it again.\n", cmd); - cmd->cmd_status_drv = MFI_STAT_INVALID_STATUS; + cmd->cmd_status_drv = DCMD_INIT; instance->instancet->fire_cmd(instance, cmd->frame_phys_addr, 0, instance->reg_set); @@ -4324,7 +4403,8 @@ dcmd_timeout_ocr_possible(struct megasas_instance *instance) { if (instance->adapter_type == MFI_SERIES) return KILL_ADAPTER; else if (instance->unload || - test_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags)) + test_bit(MEGASAS_FUSION_OCR_NOT_POSSIBLE, + &instance->reset_flags)) return IGNORE_TIMEOUT; else return INITIATE_OCR; @@ -5478,9 +5558,11 @@ megasas_setup_irqs_ioapic(struct megasas_instance *instance) pdev = instance->pdev; instance->irq_context[0].instance = instance; instance->irq_context[0].MSIxIndex = 0; + snprintf(instance->irq_context->name, MEGASAS_MSIX_NAME_LEN, "%s%u", + "megasas", instance->host->host_no); if (request_irq(pci_irq_vector(pdev, 0), instance->instancet->service_isr, IRQF_SHARED, - "megasas", &instance->irq_context[0])) { + instance->irq_context->name, &instance->irq_context[0])) { dev_err(&instance->pdev->dev, "Failed to register IRQ from %s %d\n", __func__, __LINE__); @@ -5512,8 +5594,10 @@ megasas_setup_irqs_msix(struct megasas_instance *instance, u8 is_probe) for (i = 0; i < instance->msix_vectors; i++) { instance->irq_context[i].instance = instance; instance->irq_context[i].MSIxIndex = i; + snprintf(instance->irq_context[i].name, MEGASAS_MSIX_NAME_LEN, "%s%u-msix%u", + "megasas", instance->host->host_no, i); if (request_irq(pci_irq_vector(pdev, i), - instance->instancet->service_isr, 0, "megasas", + instance->instancet->service_isr, 0, instance->irq_context[i].name, &instance->irq_context[i])) { dev_err(&instance->pdev->dev, "Failed to register IRQ for vector %d.\n", i); @@ -5803,7 +5887,7 @@ static int megasas_init_fw(struct megasas_instance *instance) } base_addr = pci_resource_start(instance->pdev, instance->bar); - instance->reg_set = ioremap_nocache(base_addr, 8192); + instance->reg_set = ioremap(base_addr, 8192); if (!instance->reg_set) { dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to map IO mem\n"); @@ -5894,6 +5978,8 @@ static int megasas_init_fw(struct megasas_instance *instance) MR_MAX_RAID_MAP_SIZE_MASK); } + instance->enable_sdev_max_qd = enable_sdev_max_qd; + switch (instance->adapter_type) { case VENTURA_SERIES: fusion->pcie_bw_limitation = true; @@ -7518,7 +7604,7 @@ megasas_resume(struct pci_dev *pdev) int rval; struct Scsi_Host *host; struct megasas_instance *instance; - int irq_flags = PCI_IRQ_LEGACY; + u32 status_reg; instance = pci_get_drvdata(pdev); @@ -7546,9 +7632,35 @@ megasas_resume(struct pci_dev *pdev) /* * We expect the FW state to be READY */ - if (megasas_transition_to_ready(instance, 0)) - goto fail_ready_state; + if (megasas_transition_to_ready(instance, 0)) { + dev_info(&instance->pdev->dev, + "Failed to transition controller to ready from %s!\n", + __func__); + if (instance->adapter_type != MFI_SERIES) { + status_reg = + instance->instancet->read_fw_status_reg(instance); + if (!(status_reg & MFI_RESET_ADAPTER) || + ((megasas_adp_reset_wait_for_ready + (instance, true, 0)) == FAILED)) + goto fail_ready_state; + } else { + atomic_set(&instance->fw_reset_no_pci_access, 1); + instance->instancet->adp_reset + (instance, instance->reg_set); + atomic_set(&instance->fw_reset_no_pci_access, 0); + + /* waiting for about 30 seconds before retry */ + ssleep(30); + + if (megasas_transition_to_ready(instance, 0)) + goto fail_ready_state; + } + + dev_info(&instance->pdev->dev, + "FW restarted successfully from %s!\n", + __func__); + } if (megasas_set_dma_mask(instance)) goto fail_set_dma_mask; @@ -7560,16 +7672,15 @@ megasas_resume(struct pci_dev *pdev) atomic_set(&instance->ldio_outstanding, 0); /* Now re-enable MSI-X */ - if (instance->msix_vectors) { - irq_flags = PCI_IRQ_MSIX; - if (instance->smp_affinity_enable) - irq_flags |= PCI_IRQ_AFFINITY; + if (instance->msix_vectors) + megasas_alloc_irq_vectors(instance); + + if (!instance->msix_vectors) { + rval = pci_alloc_irq_vectors(instance->pdev, 1, 1, + PCI_IRQ_LEGACY); + if (rval < 0) + goto fail_reenable_msix; } - rval = pci_alloc_irq_vectors(instance->pdev, 1, - instance->msix_vectors ? - instance->msix_vectors : 1, irq_flags); - if (rval < 0) - goto fail_reenable_msix; megasas_setup_reply_map(instance); @@ -7962,6 +8073,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, dma_addr_t sense_handle; unsigned long *sense_ptr; u32 opcode = 0; + int ret = DCMD_SUCCESS; memset(kbuff_arr, 0, sizeof(kbuff_arr)); @@ -8102,13 +8214,18 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, * cmd to the SCSI mid-layer */ cmd->sync_cmd = 1; - if (megasas_issue_blocked_cmd(instance, cmd, 0) == DCMD_NOT_FIRED) { + + ret = megasas_issue_blocked_cmd(instance, cmd, 0); + switch (ret) { + case DCMD_INIT: + case DCMD_BUSY: cmd->sync_cmd = 0; dev_err(&instance->pdev->dev, "return -EBUSY from %s %d cmd 0x%x opcode 0x%x cmd->cmd_status_drv 0x%x\n", - __func__, __LINE__, cmd->frame->hdr.cmd, opcode, - cmd->cmd_status_drv); - return -EBUSY; + __func__, __LINE__, cmd->frame->hdr.cmd, opcode, + cmd->cmd_status_drv); + error = -EBUSY; + goto out; } cmd->sync_cmd = 0; diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c index 50b8c1b12767..89c3685f5163 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fp.c +++ b/drivers/scsi/megaraid/megaraid_sas_fp.c @@ -386,9 +386,8 @@ u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk, le64_to_cpu(quad->logEnd) && (mega_mod64(row - le64_to_cpu(quad->logStart), le32_to_cpu(quad->diff))) == 0) { if (span_blk != NULL) { - u64 blk, debugBlk; + u64 blk; blk = mega_div64_32((row-le64_to_cpu(quad->logStart)), le32_to_cpu(quad->diff)); - debugBlk = blk; blk = (blk + le64_to_cpu(quad->offsetInSpan)) << raid->stripeShift; *span_blk = blk; @@ -699,9 +698,7 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld, __le16 *pDevHandle = &io_info->devHandle; u8 *pPdInterface = &io_info->pd_interface; u32 logArm, rowMod, armQ, arm; - struct fusion_context *fusion; - fusion = instance->ctrl_context; *pDevHandle = cpu_to_le16(MR_DEVHANDLE_INVALID); /*Get row and span from io_info for Uneven Span IO.*/ @@ -801,9 +798,7 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow, u64 *pdBlock = &io_info->pdBlock; __le16 *pDevHandle = &io_info->devHandle; u8 *pPdInterface = &io_info->pd_interface; - struct fusion_context *fusion; - fusion = instance->ctrl_context; *pDevHandle = cpu_to_le16(MR_DEVHANDLE_INVALID); row = mega_div64_32(stripRow, raid->rowDataSize); diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 120e3c4de8c2..f3b36fd0a0eb 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -323,9 +323,6 @@ megasas_fusion_update_can_queue(struct megasas_instance *instance, int fw_boot_c { u16 cur_max_fw_cmds = 0; u16 ldio_threshold = 0; - struct megasas_register_set __iomem *reg_set; - - reg_set = instance->reg_set; /* ventura FW does not fill outbound_scratch_pad_2 with queue depth */ if (instance->adapter_type < VENTURA_SERIES) @@ -367,6 +364,35 @@ megasas_fusion_update_can_queue(struct megasas_instance *instance, int fw_boot_c instance->max_fw_cmds = instance->max_fw_cmds-1; } } + +static inline void +megasas_get_msix_index(struct megasas_instance *instance, + struct scsi_cmnd *scmd, + struct megasas_cmd_fusion *cmd, + u8 data_arms) +{ + int sdev_busy; + + /* nr_hw_queue = 1 for MegaRAID */ + struct blk_mq_hw_ctx *hctx = + scmd->device->request_queue->queue_hw_ctx[0]; + + sdev_busy = atomic_read(&hctx->nr_active); + + if (instance->perf_mode == MR_BALANCED_PERF_MODE && + sdev_busy > (data_arms * MR_DEVICE_HIGH_IOPS_DEPTH)) + cmd->request_desc->SCSIIO.MSIxIndex = + mega_mod64((atomic64_add_return(1, &instance->high_iops_outstanding) / + MR_HIGH_IOPS_BATCH_COUNT), instance->low_latency_index_start); + else if (instance->msix_load_balance) + cmd->request_desc->SCSIIO.MSIxIndex = + (mega_mod64(atomic64_add_return(1, &instance->total_io_count), + instance->msix_vectors)); + else + cmd->request_desc->SCSIIO.MSIxIndex = + instance->reply_map[raw_smp_processor_id()]; +} + /** * megasas_free_cmds_fusion - Free all the cmds in the free cmd pool * @instance: Adapter soft state @@ -1315,7 +1341,9 @@ megasas_sync_pd_seq_num(struct megasas_instance *instance, bool pend) { } if (ret == DCMD_TIMEOUT) - megaraid_sas_kill_hba(instance); + dev_warn(&instance->pdev->dev, + "%s DCMD timed out, continue without JBOD sequence map\n", + __func__); if (ret == DCMD_SUCCESS) instance->pd_seq_map_id++; @@ -1397,7 +1425,9 @@ megasas_get_ld_map_info(struct megasas_instance *instance) ret = megasas_issue_polled(instance, cmd); if (ret == DCMD_TIMEOUT) - megaraid_sas_kill_hba(instance); + dev_warn(&instance->pdev->dev, + "%s DCMD timed out, RAID map is disabled\n", + __func__); megasas_return_cmd(instance, cmd); @@ -2828,19 +2858,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, fp_possible = (io_info.fpOkForIo > 0) ? true : false; } - if ((instance->perf_mode == MR_BALANCED_PERF_MODE) && - atomic_read(&scp->device->device_busy) > - (io_info.data_arms * MR_DEVICE_HIGH_IOPS_DEPTH)) - cmd->request_desc->SCSIIO.MSIxIndex = - mega_mod64((atomic64_add_return(1, &instance->high_iops_outstanding) / - MR_HIGH_IOPS_BATCH_COUNT), instance->low_latency_index_start); - else if (instance->msix_load_balance) - cmd->request_desc->SCSIIO.MSIxIndex = - (mega_mod64(atomic64_add_return(1, &instance->total_io_count), - instance->msix_vectors)); - else - cmd->request_desc->SCSIIO.MSIxIndex = - instance->reply_map[raw_smp_processor_id()]; + megasas_get_msix_index(instance, scp, cmd, io_info.data_arms); if (instance->adapter_type >= VENTURA_SERIES) { /* FP for Optimal raid level 1. @@ -3161,18 +3179,7 @@ megasas_build_syspd_fusion(struct megasas_instance *instance, cmd->request_desc->SCSIIO.DevHandle = io_request->DevHandle; - if ((instance->perf_mode == MR_BALANCED_PERF_MODE) && - atomic_read(&scmd->device->device_busy) > MR_DEVICE_HIGH_IOPS_DEPTH) - cmd->request_desc->SCSIIO.MSIxIndex = - mega_mod64((atomic64_add_return(1, &instance->high_iops_outstanding) / - MR_HIGH_IOPS_BATCH_COUNT), instance->low_latency_index_start); - else if (instance->msix_load_balance) - cmd->request_desc->SCSIIO.MSIxIndex = - (mega_mod64(atomic64_add_return(1, &instance->total_io_count), - instance->msix_vectors)); - else - cmd->request_desc->SCSIIO.MSIxIndex = - instance->reply_map[raw_smp_processor_id()]; + megasas_get_msix_index(instance, scmd, cmd, 1); if (!fp_possible) { /* system pd firmware path */ @@ -3511,7 +3518,7 @@ megasas_complete_r1_command(struct megasas_instance *instance, * @instance: Adapter soft state * Completes all commands that is in reply descriptor queue */ -int +static int complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex, struct megasas_irq_context *irq_context) { @@ -3702,7 +3709,7 @@ static void megasas_enable_irq_poll(struct megasas_instance *instance) * megasas_sync_irqs - Synchronizes all IRQs owned by adapter * @instance: Adapter soft state */ -void megasas_sync_irqs(unsigned long instance_addr) +static void megasas_sync_irqs(unsigned long instance_addr) { u32 count, i; struct megasas_instance *instance = @@ -3760,7 +3767,7 @@ int megasas_irqpoll(struct irq_poll *irqpoll, int budget) * * Tasklet to complete cmds */ -void +static void megasas_complete_cmd_dpc_fusion(unsigned long instance_addr) { struct megasas_instance *instance = @@ -3780,7 +3787,7 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr) /** * megasas_isr_fusion - isr entry point */ -irqreturn_t megasas_isr_fusion(int irq, void *devp) +static irqreturn_t megasas_isr_fusion(int irq, void *devp) { struct megasas_irq_context *irq_context = devp; struct megasas_instance *instance = irq_context->instance; @@ -3816,7 +3823,7 @@ irqreturn_t megasas_isr_fusion(int irq, void *devp) * mfi_cmd: megasas_cmd pointer * */ -void +static void build_mpt_mfi_pass_thru(struct megasas_instance *instance, struct megasas_cmd *mfi_cmd) { @@ -3874,7 +3881,7 @@ build_mpt_mfi_pass_thru(struct megasas_instance *instance, * @cmd: mfi cmd to build * */ -union MEGASAS_REQUEST_DESCRIPTOR_UNION * +static union MEGASAS_REQUEST_DESCRIPTOR_UNION * build_mpt_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) { union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc = NULL; @@ -3900,7 +3907,7 @@ build_mpt_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) * @cmd: mfi cmd pointer * */ -void +static void megasas_issue_dcmd_fusion(struct megasas_instance *instance, struct megasas_cmd *cmd) { @@ -4096,8 +4103,9 @@ static inline void megasas_trigger_snap_dump(struct megasas_instance *instance) } /* This function waits for outstanding commands on fusion to complete */ -int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance, - int reason, int *convert) +static int +megasas_wait_for_outstanding_fusion(struct megasas_instance *instance, + int reason, int *convert) { int i, outstanding, retval = 0, hb_seconds_missed = 0; u32 fw_state, abs_state; @@ -4221,7 +4229,8 @@ void megasas_reset_reply_desc(struct megasas_instance *instance) * megasas_refire_mgmt_cmd : Re-fire management commands * @instance: Controller's soft instance */ -void megasas_refire_mgmt_cmd(struct megasas_instance *instance) +void megasas_refire_mgmt_cmd(struct megasas_instance *instance, + bool return_ioctl) { int j; struct megasas_cmd_fusion *cmd_fusion; @@ -4285,6 +4294,16 @@ void megasas_refire_mgmt_cmd(struct megasas_instance *instance) break; } + if (return_ioctl && cmd_mfi->sync_cmd && + cmd_mfi->frame->hdr.cmd != MFI_CMD_ABORT) { + dev_err(&instance->pdev->dev, + "return -EBUSY from %s %d cmd 0x%x opcode 0x%x\n", + __func__, __LINE__, cmd_mfi->frame->hdr.cmd, + le32_to_cpu(cmd_mfi->frame->dcmd.opcode)); + cmd_mfi->cmd_status_drv = DCMD_BUSY; + result = COMPLETE_CMD; + } + switch (result) { case REFIRE_CMD: megasas_fire_cmd_fusion(instance, req_desc); @@ -4300,6 +4319,37 @@ void megasas_refire_mgmt_cmd(struct megasas_instance *instance) } /* + * megasas_return_polled_cmds: Return polled mode commands back to the pool + * before initiating an OCR. + * @instance: Controller's soft instance + */ +static void +megasas_return_polled_cmds(struct megasas_instance *instance) +{ + int i; + struct megasas_cmd_fusion *cmd_fusion; + struct fusion_context *fusion; + struct megasas_cmd *cmd_mfi; + + fusion = instance->ctrl_context; + + for (i = instance->max_scsi_cmds; i < instance->max_fw_cmds; i++) { + cmd_fusion = fusion->cmd_list[i]; + cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx]; + + if (cmd_mfi->flags & DRV_DCMD_POLLED_MODE) { + if (megasas_dbg_lvl & OCR_DEBUG) + dev_info(&instance->pdev->dev, + "%s %d return cmd 0x%x opcode 0x%x\n", + __func__, __LINE__, cmd_mfi->frame->hdr.cmd, + le32_to_cpu(cmd_mfi->frame->dcmd.opcode)); + cmd_mfi->flags &= ~DRV_DCMD_POLLED_MODE; + megasas_return_cmd(instance, cmd_mfi); + } + } +} + +/* * megasas_track_scsiio : Track SCSI IOs outstanding to a SCSI device * @instance: per adapter struct * @channel: the channel assigned by the OS @@ -4747,7 +4797,8 @@ out: } /*SRIOV get other instance in cluster if any*/ -struct megasas_instance *megasas_get_peer_instance(struct megasas_instance *instance) +static struct +megasas_instance *megasas_get_peer_instance(struct megasas_instance *instance) { int i; @@ -4848,6 +4899,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason) if (instance->requestorId && !instance->skip_heartbeat_timer_del) del_timer_sync(&instance->sriov_heartbeat_timer); set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); + set_bit(MEGASAS_FUSION_OCR_NOT_POSSIBLE, &instance->reset_flags); atomic_set(&instance->adprecovery, MEGASAS_ADPRESET_SM_POLLING); instance->instancet->disable_intr(instance); megasas_sync_irqs((unsigned long)instance); @@ -4952,7 +5004,9 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason) goto kill_hba; } - megasas_refire_mgmt_cmd(instance); + megasas_refire_mgmt_cmd(instance, + (i == (MEGASAS_FUSION_MAX_RESET_TRIES - 1) + ? 1 : 0)); /* Reset load balance info */ if (fusion->load_balance_info) @@ -4960,8 +5014,16 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason) (sizeof(struct LD_LOAD_BALANCE_INFO) * MAX_LOGICAL_DRIVES_EXT)); - if (!megasas_get_map_info(instance)) + if (!megasas_get_map_info(instance)) { megasas_sync_map_info(instance); + } else { + /* + * Return pending polled mode cmds before + * retrying OCR + */ + megasas_return_polled_cmds(instance); + continue; + } megasas_setup_jbod_map(instance); @@ -4988,6 +5050,15 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason) megasas_set_dynamic_target_properties(sdev, is_target_prop); } + status_reg = instance->instancet->read_fw_status_reg + (instance); + abs_state = status_reg & MFI_STATE_MASK; + if (abs_state != MFI_STATE_OPERATIONAL) { + dev_info(&instance->pdev->dev, + "Adapter is not OPERATIONAL, state 0x%x for scsi:%d\n", + abs_state, instance->host->host_no); + goto out; + } atomic_set(&instance->adprecovery, MEGASAS_HBA_OPERATIONAL); dev_info(&instance->pdev->dev, @@ -5047,13 +5118,13 @@ kill_hba: instance->skip_heartbeat_timer_del = 1; retval = FAILED; out: - clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); + clear_bit(MEGASAS_FUSION_OCR_NOT_POSSIBLE, &instance->reset_flags); mutex_unlock(&instance->reset_mutex); return retval; } /* Fusion Crash dump collection */ -void megasas_fusion_crash_dump(struct megasas_instance *instance) +static void megasas_fusion_crash_dump(struct megasas_instance *instance) { u32 status_reg; u8 partial_copy = 0; diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h index c013c80fe4e6..d57ecc7f88d8 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.h +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h @@ -89,6 +89,7 @@ enum MR_RAID_FLAGS_IO_SUB_TYPE { #define MEGASAS_FP_CMD_LEN 16 #define MEGASAS_FUSION_IN_RESET 0 +#define MEGASAS_FUSION_OCR_NOT_POSSIBLE 1 #define RAID_1_PEER_CMDS 2 #define JBOD_MAPS_COUNT 2 #define MEGASAS_REDUCE_QD_COUNT 64 @@ -864,9 +865,20 @@ struct MR_LD_RAID { u8 regTypeReqOnRead; __le16 seqNum; - struct { - u32 ldSyncRequired:1; - u32 reserved:31; +struct { +#ifndef MFI_BIG_ENDIAN + u32 ldSyncRequired:1; + u32 regTypeReqOnReadIsValid:1; + u32 isEPD:1; + u32 enableSLDOnAllRWIOs:1; + u32 reserved:28; +#else + u32 reserved:28; + u32 enableSLDOnAllRWIOs:1; + u32 isEPD:1; + u32 regTypeReqOnReadIsValid:1; + u32 ldSyncRequired:1; +#endif } flags; u8 LUN[8]; /* 0x24 8 byte LUN field used for SCSI IO's */ |