diff options
Diffstat (limited to 'drivers/scsi/megaraid/megaraid_sas_base.c')
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_base.c | 1025 |
1 files changed, 631 insertions, 394 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index a36e18156e49..cc54bdb5c712 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -161,6 +161,7 @@ static struct pci_device_id megasas_pci_table[] = { {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_CUTLASS_53)}, /* VENTURA */ {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VENTURA)}, + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_CRUSADER)}, {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_HARPOON)}, {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_TOMCAT)}, {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VENTURA_4PORT)}, @@ -205,6 +206,43 @@ wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd, void megasas_fusion_ocr_wq(struct work_struct *work); static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance, int initial); +static int +megasas_set_dma_mask(struct megasas_instance *instance); +static int +megasas_alloc_ctrl_mem(struct megasas_instance *instance); +static inline void +megasas_free_ctrl_mem(struct megasas_instance *instance); +static inline int +megasas_alloc_ctrl_dma_buffers(struct megasas_instance *instance); +static inline void +megasas_free_ctrl_dma_buffers(struct megasas_instance *instance); +static inline void +megasas_init_ctrl_params(struct megasas_instance *instance); + +/** + * megasas_set_dma_settings - Populate DMA address, length and flags for DCMDs + * @instance: Adapter soft state + * @dcmd: DCMD frame inside MFI command + * @dma_addr: DMA address of buffer to be passed to FW + * @dma_len: Length of DMA buffer to be passed to FW + * @return: void + */ +void megasas_set_dma_settings(struct megasas_instance *instance, + struct megasas_dcmd_frame *dcmd, + dma_addr_t dma_addr, u32 dma_len) +{ + if (instance->consistent_mask_64bit) { + dcmd->sgl.sge64[0].phys_addr = cpu_to_le64(dma_addr); + dcmd->sgl.sge64[0].length = cpu_to_le32(dma_len); + dcmd->flags = cpu_to_le16(dcmd->flags | MFI_FRAME_SGL64); + + } else { + dcmd->sgl.sge32[0].phys_addr = + cpu_to_le32(lower_32_bits(dma_addr)); + dcmd->sgl.sge32[0].length = cpu_to_le32(dma_len); + dcmd->flags = cpu_to_le16(dcmd->flags); + } +} void megasas_issue_dcmd(struct megasas_instance *instance, struct megasas_cmd *cmd) @@ -2023,7 +2061,7 @@ void megaraid_sas_kill_hba(struct megasas_instance *instance) msleep(1000); if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) || - (instance->ctrl_context)) { + (instance->adapter_type != MFI_SERIES)) { writel(MFI_STOP_ADP, &instance->reg_set->doorbell); /* Flush */ readl(&instance->reg_set->doorbell); @@ -2485,13 +2523,15 @@ int megasas_sriov_start_heartbeat(struct megasas_instance *instance, dcmd->pad_0 = 0; dcmd->data_xfer_len = cpu_to_le32(sizeof(struct MR_CTRL_HB_HOST_MEM)); dcmd->opcode = cpu_to_le32(MR_DCMD_CTRL_SHARED_HOST_MEM_ALLOC); - dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(instance->hb_host_mem_h); - dcmd->sgl.sge32[0].length = cpu_to_le32(sizeof(struct MR_CTRL_HB_HOST_MEM)); + + megasas_set_dma_settings(instance, dcmd, instance->hb_host_mem_h, + sizeof(struct MR_CTRL_HB_HOST_MEM)); dev_warn(&instance->pdev->dev, "SR-IOV: Starting heartbeat for scsi%d\n", instance->host->host_no); - if (instance->ctrl_context && !instance->mask_interrupts) + if ((instance->adapter_type != MFI_SERIES) && + !instance->mask_interrupts) retval = megasas_issue_blocked_cmd(instance, cmd, MEGASAS_ROUTINE_WAIT_TIME_VF); else @@ -2787,7 +2827,9 @@ static int megasas_reset_bus_host(struct scsi_cmnd *scmd) /* * First wait for all commands to complete */ - if (instance->ctrl_context) { + if (instance->adapter_type == MFI_SERIES) { + ret = megasas_generic_reset(scmd); + } else { struct megasas_cmd_fusion *cmd; cmd = (struct megasas_cmd_fusion *)scmd->SCp.ptr; if (cmd) @@ -2795,8 +2837,7 @@ static int megasas_reset_bus_host(struct scsi_cmnd *scmd) MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE); ret = megasas_reset_fusion(scmd->device->host, SCSIIO_TIMEOUT_OCR); - } else - ret = megasas_generic_reset(scmd); + } return ret; } @@ -2813,7 +2854,7 @@ static int megasas_task_abort(struct scsi_cmnd *scmd) instance = (struct megasas_instance *)scmd->device->host->hostdata; - if (instance->ctrl_context) + if (instance->adapter_type != MFI_SERIES) ret = megasas_task_abort_fusion(scmd); else { sdev_printk(KERN_NOTICE, scmd->device, "TASK ABORT not supported\n"); @@ -2835,7 +2876,7 @@ static int megasas_reset_target(struct scsi_cmnd *scmd) instance = (struct megasas_instance *)scmd->device->host->hostdata; - if (instance->ctrl_context) + if (instance->adapter_type != MFI_SERIES) ret = megasas_reset_target_fusion(scmd); else { sdev_printk(KERN_NOTICE, scmd->device, "TARGET RESET not supported\n"); @@ -3280,6 +3321,9 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, case MFI_CMD_SMP: case MFI_CMD_STP: + megasas_complete_int_cmd(instance, cmd); + break; + case MFI_CMD_DCMD: opcode = le32_to_cpu(cmd->frame->dcmd.opcode); /* Check for LD map update */ @@ -3366,6 +3410,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, default: dev_info(&instance->pdev->dev, "Unknown command completed! [0x%X]\n", hdr->cmd); + megasas_complete_int_cmd(instance, cmd); break; } } @@ -3712,7 +3757,7 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr) PCI_DEVICE_ID_LSI_SAS0073SKINNY) || (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) || - (instance->ctrl_context)) + (instance->adapter_type != MFI_SERIES)) writel( MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, &instance->reg_set->doorbell); @@ -3730,7 +3775,7 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr) PCI_DEVICE_ID_LSI_SAS0073SKINNY) || (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) || - (instance->ctrl_context)) + (instance->adapter_type != MFI_SERIES)) writel(MFI_INIT_HOTPLUG, &instance->reg_set->doorbell); else @@ -3750,11 +3795,11 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr) PCI_DEVICE_ID_LSI_SAS0073SKINNY) || (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) || - (instance->ctrl_context)) { + (instance->adapter_type != MFI_SERIES)) { writel(MFI_RESET_FLAGS, &instance->reg_set->doorbell); - if (instance->ctrl_context) { + if (instance->adapter_type != MFI_SERIES) { for (i = 0; i < (10 * 1000); i += 20) { if (readl( &instance-> @@ -3921,7 +3966,8 @@ static int megasas_create_frame_pool(struct megasas_instance *instance) * max_sge_sz = 12 byte (sizeof megasas_sge64) * Total 192 byte (3 MFI frame of 64 byte) */ - frame_count = instance->ctrl_context ? (3 + 1) : (15 + 1); + frame_count = (instance->adapter_type == MFI_SERIES) ? + (15 + 1) : (3 + 1); instance->mfi_frame_size = MEGAMFI_FRAME_SIZE * frame_count; /* * Use DMA pool facility provided by PCI layer @@ -3976,7 +4022,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance) memset(cmd->frame, 0, instance->mfi_frame_size); cmd->frame->io.context = cpu_to_le32(cmd->index); cmd->frame->io.pad_0 = 0; - if (!instance->ctrl_context && reset_devices) + if ((instance->adapter_type == MFI_SERIES) && reset_devices) cmd->frame->hdr.cmd = MFI_CMD_INVALID; } @@ -4030,9 +4076,7 @@ int megasas_alloc_cmds(struct megasas_instance *instance) int j; u16 max_cmd; struct megasas_cmd *cmd; - struct fusion_context *fusion; - fusion = instance->ctrl_context; max_cmd = instance->max_mfi_cmds; /* @@ -4096,7 +4140,7 @@ int megasas_alloc_cmds(struct megasas_instance *instance) inline int dcmd_timeout_ocr_possible(struct megasas_instance *instance) { - if (!instance->ctrl_context) + if (instance->adapter_type == MFI_SERIES) return KILL_ADAPTER; else if (instance->unload || test_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags)) @@ -4132,15 +4176,17 @@ megasas_get_pd_info(struct megasas_instance *instance, struct scsi_device *sdev) dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd_status = 0xFF; dcmd->sge_count = 1; - dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ); + dcmd->flags = MFI_FRAME_DIR_READ; dcmd->timeout = 0; dcmd->pad_0 = 0; dcmd->data_xfer_len = cpu_to_le32(sizeof(struct MR_PD_INFO)); dcmd->opcode = cpu_to_le32(MR_DCMD_PD_GET_INFO); - dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(instance->pd_info_h); - dcmd->sgl.sge32[0].length = cpu_to_le32(sizeof(struct MR_PD_INFO)); - if (instance->ctrl_context && !instance->mask_interrupts) + megasas_set_dma_settings(instance, dcmd, instance->pd_info_h, + sizeof(struct MR_PD_INFO)); + + if ((instance->adapter_type != MFI_SERIES) && + !instance->mask_interrupts) ret = megasas_issue_blocked_cmd(instance, cmd, MFI_IO_TIMEOUT_SECS); else ret = megasas_issue_polled(instance, cmd); @@ -4203,6 +4249,9 @@ megasas_get_pd_list(struct megasas_instance *instance) return ret; } + ci = instance->pd_list_buf; + ci_h = instance->pd_list_buf_h; + cmd = megasas_get_cmd(instance); if (!cmd) { @@ -4212,15 +4261,6 @@ megasas_get_pd_list(struct megasas_instance *instance) dcmd = &cmd->frame->dcmd; - ci = pci_alloc_consistent(instance->pdev, - MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), &ci_h); - - if (!ci) { - dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to alloc mem for pd_list\n"); - megasas_return_cmd(instance, cmd); - return -ENOMEM; - } - memset(ci, 0, sizeof(*ci)); memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); @@ -4229,15 +4269,17 @@ megasas_get_pd_list(struct megasas_instance *instance) dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd_status = MFI_STAT_INVALID_STATUS; dcmd->sge_count = 1; - dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ); + dcmd->flags = MFI_FRAME_DIR_READ; dcmd->timeout = 0; dcmd->pad_0 = 0; dcmd->data_xfer_len = cpu_to_le32(MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST)); dcmd->opcode = cpu_to_le32(MR_DCMD_PD_LIST_QUERY); - dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(ci_h); - dcmd->sgl.sge32[0].length = cpu_to_le32(MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST)); - if (instance->ctrl_context && !instance->mask_interrupts) + megasas_set_dma_settings(instance, dcmd, instance->pd_list_buf_h, + (MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST))); + + if ((instance->adapter_type != MFI_SERIES) && + !instance->mask_interrupts) ret = megasas_issue_blocked_cmd(instance, cmd, MFI_IO_TIMEOUT_SECS); else @@ -4248,7 +4290,7 @@ megasas_get_pd_list(struct megasas_instance *instance) dev_info(&instance->pdev->dev, "MR_DCMD_PD_LIST_QUERY " "failed/not supported by firmware\n"); - if (instance->ctrl_context) + if (instance->adapter_type != MFI_SERIES) megaraid_sas_kill_hba(instance); else instance->pd_list_not_supported = 1; @@ -4305,10 +4347,6 @@ megasas_get_pd_list(struct megasas_instance *instance) } - pci_free_consistent(instance->pdev, - MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), - ci, ci_h); - if (ret != DCMD_TIMEOUT) megasas_return_cmd(instance, cmd); @@ -4334,6 +4372,9 @@ megasas_get_ld_list(struct megasas_instance *instance) dma_addr_t ci_h = 0; u32 ld_count; + ci = instance->ld_list_buf; + ci_h = instance->ld_list_buf_h; + cmd = megasas_get_cmd(instance); if (!cmd) { @@ -4343,16 +4384,6 @@ megasas_get_ld_list(struct megasas_instance *instance) dcmd = &cmd->frame->dcmd; - ci = pci_alloc_consistent(instance->pdev, - sizeof(struct MR_LD_LIST), - &ci_h); - - if (!ci) { - dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to alloc mem in get_ld_list\n"); - megasas_return_cmd(instance, cmd); - return -ENOMEM; - } - memset(ci, 0, sizeof(*ci)); memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); @@ -4361,15 +4392,17 @@ megasas_get_ld_list(struct megasas_instance *instance) dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd_status = MFI_STAT_INVALID_STATUS; dcmd->sge_count = 1; - dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ); + dcmd->flags = MFI_FRAME_DIR_READ; dcmd->timeout = 0; dcmd->data_xfer_len = cpu_to_le32(sizeof(struct MR_LD_LIST)); dcmd->opcode = cpu_to_le32(MR_DCMD_LD_GET_LIST); - dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(ci_h); - dcmd->sgl.sge32[0].length = cpu_to_le32(sizeof(struct MR_LD_LIST)); dcmd->pad_0 = 0; - if (instance->ctrl_context && !instance->mask_interrupts) + megasas_set_dma_settings(instance, dcmd, ci_h, + sizeof(struct MR_LD_LIST)); + + if ((instance->adapter_type != MFI_SERIES) && + !instance->mask_interrupts) ret = megasas_issue_blocked_cmd(instance, cmd, MFI_IO_TIMEOUT_SECS); else @@ -4423,8 +4456,6 @@ megasas_get_ld_list(struct megasas_instance *instance) break; } - pci_free_consistent(instance->pdev, sizeof(struct MR_LD_LIST), ci, ci_h); - if (ret != DCMD_TIMEOUT) megasas_return_cmd(instance, cmd); @@ -4450,6 +4481,9 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type) dma_addr_t ci_h = 0; u32 tgtid_count; + ci = instance->ld_targetid_list_buf; + ci_h = instance->ld_targetid_list_buf_h; + cmd = megasas_get_cmd(instance); if (!cmd) { @@ -4460,16 +4494,6 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type) dcmd = &cmd->frame->dcmd; - ci = pci_alloc_consistent(instance->pdev, - sizeof(struct MR_LD_TARGETID_LIST), &ci_h); - - if (!ci) { - dev_warn(&instance->pdev->dev, - "Failed to alloc mem for ld_list_query\n"); - megasas_return_cmd(instance, cmd); - return -ENOMEM; - } - memset(ci, 0, sizeof(*ci)); memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); @@ -4480,15 +4504,17 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type) dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd_status = MFI_STAT_INVALID_STATUS; dcmd->sge_count = 1; - dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ); + dcmd->flags = MFI_FRAME_DIR_READ; dcmd->timeout = 0; dcmd->data_xfer_len = cpu_to_le32(sizeof(struct MR_LD_TARGETID_LIST)); dcmd->opcode = cpu_to_le32(MR_DCMD_LD_LIST_QUERY); - dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(ci_h); - dcmd->sgl.sge32[0].length = cpu_to_le32(sizeof(struct MR_LD_TARGETID_LIST)); dcmd->pad_0 = 0; - if (instance->ctrl_context && !instance->mask_interrupts) + megasas_set_dma_settings(instance, dcmd, ci_h, + sizeof(struct MR_LD_TARGETID_LIST)); + + if ((instance->adapter_type != MFI_SERIES) && + !instance->mask_interrupts) ret = megasas_issue_blocked_cmd(instance, cmd, MFI_IO_TIMEOUT_SECS); else ret = megasas_issue_polled(instance, cmd); @@ -4539,9 +4565,6 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type) break; } - pci_free_consistent(instance->pdev, sizeof(struct MR_LD_TARGETID_LIST), - ci, ci_h); - if (ret != DCMD_TIMEOUT) megasas_return_cmd(instance, cmd); @@ -4563,9 +4586,9 @@ static void megasas_update_ext_vd_details(struct megasas_instance *instance) return; instance->supportmax256vd = - instance->ctrl_info->adapterOperations3.supportMaxExtLDs; + instance->ctrl_info_buf->adapterOperations3.supportMaxExtLDs; /* Below is additional check to address future FW enhancement */ - if (instance->ctrl_info->max_lds > 64) + if (instance->ctrl_info_buf->max_lds > 64) instance->supportmax256vd = 1; instance->drv_supported_vd_count = MEGASAS_MAX_LD_CHANNELS @@ -4623,10 +4646,10 @@ megasas_get_ctrl_info(struct megasas_instance *instance) struct megasas_cmd *cmd; struct megasas_dcmd_frame *dcmd; struct megasas_ctrl_info *ci; - struct megasas_ctrl_info *ctrl_info; dma_addr_t ci_h = 0; - ctrl_info = instance->ctrl_info; + ci = instance->ctrl_info_buf; + ci_h = instance->ctrl_info_buf_h; cmd = megasas_get_cmd(instance); @@ -4637,45 +4660,37 @@ megasas_get_ctrl_info(struct megasas_instance *instance) dcmd = &cmd->frame->dcmd; - ci = pci_alloc_consistent(instance->pdev, - sizeof(struct megasas_ctrl_info), &ci_h); - - if (!ci) { - dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to alloc mem for ctrl info\n"); - megasas_return_cmd(instance, cmd); - return -ENOMEM; - } - memset(ci, 0, sizeof(*ci)); memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd_status = MFI_STAT_INVALID_STATUS; dcmd->sge_count = 1; - dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ); + dcmd->flags = MFI_FRAME_DIR_READ; dcmd->timeout = 0; dcmd->pad_0 = 0; dcmd->data_xfer_len = cpu_to_le32(sizeof(struct megasas_ctrl_info)); dcmd->opcode = cpu_to_le32(MR_DCMD_CTRL_GET_INFO); - dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(ci_h); - dcmd->sgl.sge32[0].length = cpu_to_le32(sizeof(struct megasas_ctrl_info)); dcmd->mbox.b[0] = 1; - if (instance->ctrl_context && !instance->mask_interrupts) + megasas_set_dma_settings(instance, dcmd, ci_h, + sizeof(struct megasas_ctrl_info)); + + if ((instance->adapter_type != MFI_SERIES) && + !instance->mask_interrupts) ret = megasas_issue_blocked_cmd(instance, cmd, MFI_IO_TIMEOUT_SECS); else ret = megasas_issue_polled(instance, cmd); switch (ret) { case DCMD_SUCCESS: - memcpy(ctrl_info, ci, sizeof(struct megasas_ctrl_info)); /* Save required controller information in * CPU endianness format. */ - le32_to_cpus((u32 *)&ctrl_info->properties.OnOffProperties); - le32_to_cpus((u32 *)&ctrl_info->adapterOperations2); - le32_to_cpus((u32 *)&ctrl_info->adapterOperations3); - le16_to_cpus((u16 *)&ctrl_info->adapter_operations4); + le32_to_cpus((u32 *)&ci->properties.OnOffProperties); + le32_to_cpus((u32 *)&ci->adapterOperations2); + le32_to_cpus((u32 *)&ci->adapterOperations3); + le16_to_cpus((u16 *)&ci->adapter_operations4); /* Update the latest Ext VD info. * From Init path, store current firmware details. @@ -4684,21 +4699,21 @@ megasas_get_ctrl_info(struct megasas_instance *instance) */ megasas_update_ext_vd_details(instance); instance->use_seqnum_jbod_fp = - ctrl_info->adapterOperations3.useSeqNumJbodFP; + ci->adapterOperations3.useSeqNumJbodFP; instance->support_morethan256jbod = - ctrl_info->adapter_operations4.support_pd_map_target_id; + ci->adapter_operations4.support_pd_map_target_id; /*Check whether controller is iMR or MR */ - instance->is_imr = (ctrl_info->memory_size ? 0 : 1); + instance->is_imr = (ci->memory_size ? 0 : 1); dev_info(&instance->pdev->dev, "controller type\t: %s(%dMB)\n", instance->is_imr ? "iMR" : "MR", - le16_to_cpu(ctrl_info->memory_size)); + le16_to_cpu(ci->memory_size)); instance->disableOnlineCtrlReset = - ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset; + ci->properties.OnOffProperties.disableOnlineCtrlReset; instance->secure_jbod_support = - ctrl_info->adapterOperations3.supportSecurityonJBOD; + ci->adapterOperations3.supportSecurityonJBOD; dev_info(&instance->pdev->dev, "Online Controller Reset(OCR)\t: %s\n", instance->disableOnlineCtrlReset ? "Disabled" : "Enabled"); dev_info(&instance->pdev->dev, "Secure JBOD support\t: %s\n", @@ -4726,9 +4741,6 @@ megasas_get_ctrl_info(struct megasas_instance *instance) } - pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info), - ci, ci_h); - megasas_return_cmd(instance, cmd); @@ -4772,15 +4784,17 @@ int megasas_set_crash_dump_params(struct megasas_instance *instance, dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd_status = MFI_STAT_INVALID_STATUS; dcmd->sge_count = 1; - dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_NONE); + dcmd->flags = MFI_FRAME_DIR_NONE; dcmd->timeout = 0; dcmd->pad_0 = 0; dcmd->data_xfer_len = cpu_to_le32(CRASH_DMA_BUF_SIZE); dcmd->opcode = cpu_to_le32(MR_DCMD_CTRL_SET_CRASH_DUMP_PARAMS); - dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(instance->crash_dump_h); - dcmd->sgl.sge32[0].length = cpu_to_le32(CRASH_DMA_BUF_SIZE); - if (instance->ctrl_context && !instance->mask_interrupts) + megasas_set_dma_settings(instance, dcmd, instance->crash_dump_h, + CRASH_DMA_BUF_SIZE); + + if ((instance->adapter_type != MFI_SERIES) && + !instance->mask_interrupts) ret = megasas_issue_blocked_cmd(instance, cmd, MFI_IO_TIMEOUT_SECS); else ret = megasas_issue_polled(instance, cmd); @@ -5088,7 +5102,7 @@ megasas_setup_jbod_map(struct megasas_instance *instance) (sizeof(struct MR_PD_CFG_SEQ) * (MAX_PHYSICAL_DEVICES - 1)); if (reset_devices || !fusion || - !instance->ctrl_info->adapterOperations3.useSeqNumJbodFP) { + !instance->ctrl_info_buf->adapterOperations3.useSeqNumJbodFP) { dev_info(&instance->pdev->dev, "Jbod map is not supported %s %d\n", __func__, __LINE__); @@ -5167,7 +5181,7 @@ static int megasas_init_fw(struct megasas_instance *instance) reg_set = instance->reg_set; - if (fusion) + if (instance->adapter_type != MFI_SERIES) instance->instancet = &megasas_instance_template_fusion; else { switch (instance->pdev->device) { @@ -5208,7 +5222,20 @@ static int megasas_init_fw(struct megasas_instance *instance) goto fail_ready_state; } - if (instance->is_ventura) { + megasas_init_ctrl_params(instance); + + if (megasas_set_dma_mask(instance)) + goto fail_ready_state; + + if (megasas_alloc_ctrl_mem(instance)) + goto fail_alloc_dma_buf; + + if (megasas_alloc_ctrl_dma_buffers(instance)) + goto fail_alloc_dma_buf; + + fusion = instance->ctrl_context; + + if (instance->adapter_type == VENTURA_SERIES) { scratch_pad_3 = readl(&instance->reg_set->outbound_scratch_pad_3); instance->max_raid_mapsize = ((scratch_pad_3 >> @@ -5226,7 +5253,8 @@ static int megasas_init_fw(struct megasas_instance *instance) (&instance->reg_set->outbound_scratch_pad_2); /* Check max MSI-X vectors */ if (fusion) { - if (fusion->adapter_type == THUNDERBOLT_SERIES) { /* Thunderbolt Series*/ + if (instance->adapter_type == THUNDERBOLT_SERIES) { + /* Thunderbolt Series*/ instance->msix_vectors = (scratch_pad_2 & MR_MAX_REPLY_QUEUES_OFFSET) + 1; fw_msix_count = instance->msix_vectors; @@ -5301,11 +5329,6 @@ static int megasas_init_fw(struct megasas_instance *instance) tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet, (unsigned long)instance); - instance->ctrl_info = kzalloc(sizeof(struct megasas_ctrl_info), - GFP_KERNEL); - if (instance->ctrl_info == NULL) - goto fail_init_adapter; - /* * Below are default value for legacy Firmware. * non-fusion based controllers @@ -5316,7 +5339,7 @@ static int megasas_init_fw(struct megasas_instance *instance) if (instance->instancet->init_adapter(instance)) goto fail_init_adapter; - if (instance->is_ventura) { + if (instance->adapter_type == VENTURA_SERIES) { scratch_pad_4 = readl(&instance->reg_set->outbound_scratch_pad_4); if ((scratch_pad_4 & MR_NVME_PAGE_SIZE_MASK) >= @@ -5352,7 +5375,7 @@ static int megasas_init_fw(struct megasas_instance *instance) memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); /* stream detection initialization */ - if (instance->is_ventura && fusion) { + if (instance->adapter_type == VENTURA_SERIES) { fusion->stream_detect_by_ld = kzalloc(sizeof(struct LD_STREAM_DETECT *) * MAX_LOGICAL_DRIVES_EXT, @@ -5394,7 +5417,7 @@ static int megasas_init_fw(struct megasas_instance *instance) * to calculate max_sectors_1. So the number ended up as zero always. */ tmp_sectors = 0; - ctrl_info = instance->ctrl_info; + ctrl_info = instance->ctrl_info_buf; max_sectors_1 = (1 << ctrl_info->stripe_sz_ops.min) * le16_to_cpu(ctrl_info->max_strips_per_io); @@ -5505,9 +5528,10 @@ fail_setup_irqs: if (instance->msix_vectors) pci_free_irq_vectors(instance->pdev); instance->msix_vectors = 0; +fail_alloc_dma_buf: + megasas_free_ctrl_dma_buffers(instance); + megasas_free_ctrl_mem(instance); fail_ready_state: - kfree(instance->ctrl_info); - instance->ctrl_info = NULL; iounmap(instance->reg_set); fail_ioremap: @@ -5580,13 +5604,14 @@ megasas_get_seq_num(struct megasas_instance *instance, dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd_status = 0x0; dcmd->sge_count = 1; - dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ); + dcmd->flags = MFI_FRAME_DIR_READ; dcmd->timeout = 0; dcmd->pad_0 = 0; dcmd->data_xfer_len = cpu_to_le32(sizeof(struct megasas_evt_log_info)); dcmd->opcode = cpu_to_le32(MR_DCMD_CTRL_EVENT_GET_INFO); - 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_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) { @@ -5711,7 +5736,7 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num, dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd_status = 0x0; dcmd->sge_count = 1; - dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ); + dcmd->flags = MFI_FRAME_DIR_READ; dcmd->timeout = 0; dcmd->pad_0 = 0; dcmd->data_xfer_len = cpu_to_le32(sizeof(struct megasas_evt_detail)); @@ -5719,8 +5744,9 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num, dcmd->mbox.w[0] = cpu_to_le32(seq_num); instance->last_seq_num = seq_num; dcmd->mbox.w[1] = cpu_to_le32(curr_aen.word); - dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(instance->evt_detail_h); - dcmd->sgl.sge32[0].length = cpu_to_le32(sizeof(struct megasas_evt_detail)); + + megasas_set_dma_settings(instance, dcmd, instance->evt_detail_h, + sizeof(struct megasas_evt_detail)); if (instance->aen_cmd != NULL) { megasas_return_cmd(instance, cmd); @@ -5787,18 +5813,18 @@ megasas_get_target_prop(struct megasas_instance *instance, dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd_status = 0xFF; dcmd->sge_count = 1; - dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ); + dcmd->flags = MFI_FRAME_DIR_READ; dcmd->timeout = 0; dcmd->pad_0 = 0; dcmd->data_xfer_len = cpu_to_le32(sizeof(struct MR_TARGET_PROPERTIES)); dcmd->opcode = cpu_to_le32(MR_DCMD_DRV_GET_TARGET_PROP); - dcmd->sgl.sge32[0].phys_addr = - cpu_to_le32(instance->tgt_prop_h); - dcmd->sgl.sge32[0].length = - cpu_to_le32(sizeof(struct MR_TARGET_PROPERTIES)); - if (instance->ctrl_context && !instance->mask_interrupts) + megasas_set_dma_settings(instance, dcmd, instance->tgt_prop_h, + sizeof(struct MR_TARGET_PROPERTIES)); + + if ((instance->adapter_type != MFI_SERIES) && + !instance->mask_interrupts) ret = megasas_issue_blocked_cmd(instance, cmd, MFI_IO_TIMEOUT_SECS); else @@ -5923,234 +5949,408 @@ static int megasas_io_attach(struct megasas_instance *instance) return 0; } +/** + * megasas_set_dma_mask - Set DMA mask for supported controllers + * + * @instance: Adapter soft state + * Description: + * + * For Ventura, driver/FW will operate in 64bit DMA addresses. + * + * For invader- + * By default, driver/FW will operate in 32bit DMA addresses + * for consistent DMA mapping but if 32 bit consistent + * DMA mask fails, driver will try with 64 bit consistent + * mask provided FW is true 64bit DMA capable + * + * For older controllers(Thunderbolt and MFI based adapters)- + * driver/FW will operate in 32 bit consistent DMA addresses. + */ static int -megasas_set_dma_mask(struct pci_dev *pdev) +megasas_set_dma_mask(struct megasas_instance *instance) { - /* - * All our controllers are capable of performing 64-bit DMA - */ + u64 consistent_mask; + struct pci_dev *pdev; + u32 scratch_pad_2; + + pdev = instance->pdev; + consistent_mask = (instance->adapter_type == VENTURA_SERIES) ? + DMA_BIT_MASK(64) : DMA_BIT_MASK(32); + if (IS_DMA64) { - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) { + if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)) && + dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) + goto fail_set_dma_mask; + + if ((*pdev->dev.dma_mask == DMA_BIT_MASK(64)) && + (dma_set_coherent_mask(&pdev->dev, consistent_mask) && + dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)))) { + /* + * If 32 bit DMA mask fails, then try for 64 bit mask + * for FW capable of handling 64 bit DMA. + */ + scratch_pad_2 = readl + (&instance->reg_set->outbound_scratch_pad_2); - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) + if (!(scratch_pad_2 & MR_CAN_HANDLE_64_BIT_DMA_OFFSET)) + goto fail_set_dma_mask; + else if (dma_set_mask_and_coherent(&pdev->dev, + DMA_BIT_MASK(64))) goto fail_set_dma_mask; } - } else { - 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; - } + } else if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) + goto fail_set_dma_mask; + + if (pdev->dev.coherent_dma_mask == DMA_BIT_MASK(32)) + instance->consistent_mask_64bit = false; + else + instance->consistent_mask_64bit = true; + + dev_info(&pdev->dev, "%s bit DMA mask and %s bit consistent mask\n", + ((*pdev->dev.dma_mask == DMA_BIT_MASK(64)) ? "64" : "32"), + (instance->consistent_mask_64bit ? "64" : "32")); return 0; fail_set_dma_mask: - return 1; + dev_err(&pdev->dev, "Failed to set DMA mask\n"); + return -1; + } -/** - * megasas_probe_one - PCI hotplug entry point - * @pdev: PCI device structure - * @id: PCI ids of supported hotplugged adapter +/* + * megasas_set_adapter_type - Set adapter type. + * Supported controllers can be divided in + * 4 categories- enum MR_ADAPTER_TYPE { + * MFI_SERIES = 1, + * THUNDERBOLT_SERIES = 2, + * INVADER_SERIES = 3, + * VENTURA_SERIES = 4, + * }; + * @instance: Adapter soft state + * return: void */ -static int megasas_probe_one(struct pci_dev *pdev, - const struct pci_device_id *id) +static inline void megasas_set_adapter_type(struct megasas_instance *instance) { - int rval, pos; - struct Scsi_Host *host; - struct megasas_instance *instance; - u16 control = 0; - struct fusion_context *fusion = NULL; - - /* Reset MSI-X in the kdump kernel */ - if (reset_devices) { - pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX); - if (pos) { - pci_read_config_word(pdev, pos + PCI_MSIX_FLAGS, - &control); - if (control & PCI_MSIX_FLAGS_ENABLE) { - dev_info(&pdev->dev, "resetting MSI-X\n"); - pci_write_config_word(pdev, - pos + PCI_MSIX_FLAGS, - control & - ~PCI_MSIX_FLAGS_ENABLE); - } + if ((instance->pdev->vendor == PCI_VENDOR_ID_DELL) && + (instance->pdev->device == PCI_DEVICE_ID_DELL_PERC5)) { + instance->adapter_type = MFI_SERIES; + } else { + switch (instance->pdev->device) { + case PCI_DEVICE_ID_LSI_VENTURA: + case PCI_DEVICE_ID_LSI_CRUSADER: + case PCI_DEVICE_ID_LSI_HARPOON: + case PCI_DEVICE_ID_LSI_TOMCAT: + case PCI_DEVICE_ID_LSI_VENTURA_4PORT: + case PCI_DEVICE_ID_LSI_CRUSADER_4PORT: + instance->adapter_type = VENTURA_SERIES; + break; + case PCI_DEVICE_ID_LSI_FUSION: + case PCI_DEVICE_ID_LSI_PLASMA: + instance->adapter_type = THUNDERBOLT_SERIES; + break; + case PCI_DEVICE_ID_LSI_INVADER: + case PCI_DEVICE_ID_LSI_INTRUDER: + case PCI_DEVICE_ID_LSI_INTRUDER_24: + case PCI_DEVICE_ID_LSI_CUTLASS_52: + case PCI_DEVICE_ID_LSI_CUTLASS_53: + case PCI_DEVICE_ID_LSI_FURY: + instance->adapter_type = INVADER_SERIES; + break; + default: /* For all other supported controllers */ + instance->adapter_type = MFI_SERIES; + break; } } +} - /* - * PCI prepping: enable device set bus mastering and dma mask - */ - rval = pci_enable_device_mem(pdev); +static inline int megasas_alloc_mfi_ctrl_mem(struct megasas_instance *instance) +{ + instance->producer = pci_alloc_consistent(instance->pdev, sizeof(u32), + &instance->producer_h); + instance->consumer = pci_alloc_consistent(instance->pdev, sizeof(u32), + &instance->consumer_h); - if (rval) { - return rval; + if (!instance->producer || !instance->consumer) { + dev_err(&instance->pdev->dev, + "Failed to allocate memory for producer, consumer\n"); + return -1; } - pci_set_master(pdev); + *instance->producer = 0; + *instance->consumer = 0; + return 0; +} - if (megasas_set_dma_mask(pdev)) - goto fail_set_dma_mask; +/** + * megasas_alloc_ctrl_mem - Allocate per controller memory for core data + * structures which are not common across MFI + * adapters and fusion adapters. + * For MFI based adapters, allocate producer and + * consumer buffers. For fusion adapters, allocate + * memory for fusion context. + * @instance: Adapter soft state + * return: 0 for SUCCESS + */ +static int megasas_alloc_ctrl_mem(struct megasas_instance *instance) +{ + switch (instance->adapter_type) { + case MFI_SERIES: + if (megasas_alloc_mfi_ctrl_mem(instance)) + return -ENOMEM; + break; + case VENTURA_SERIES: + case THUNDERBOLT_SERIES: + case INVADER_SERIES: + if (megasas_alloc_fusion_context(instance)) + return -ENOMEM; + break; + } - host = scsi_host_alloc(&megasas_template, - sizeof(struct megasas_instance)); + return 0; +} - if (!host) { - dev_printk(KERN_DEBUG, &pdev->dev, "scsi_host_alloc failed\n"); - goto fail_alloc_instance; +/* + * megasas_free_ctrl_mem - Free fusion context for fusion adapters and + * producer, consumer buffers for MFI adapters + * + * @instance - Adapter soft instance + * + */ +static inline void megasas_free_ctrl_mem(struct megasas_instance *instance) +{ + if (instance->adapter_type == MFI_SERIES) { + if (instance->producer) + pci_free_consistent(instance->pdev, sizeof(u32), + instance->producer, + instance->producer_h); + if (instance->consumer) + pci_free_consistent(instance->pdev, sizeof(u32), + instance->consumer, + instance->consumer_h); + } else { + megasas_free_fusion_context(instance); } +} - instance = (struct megasas_instance *)host->hostdata; - memset(instance, 0, sizeof(*instance)); - atomic_set(&instance->fw_reset_no_pci_access, 0); - instance->pdev = pdev; +/** + * megasas_alloc_ctrl_dma_buffers - Allocate consistent DMA buffers during + * driver load time + * + * @instance- Adapter soft instance + * @return- O for SUCCESS + */ +static inline +int megasas_alloc_ctrl_dma_buffers(struct megasas_instance *instance) +{ + struct pci_dev *pdev = instance->pdev; + struct fusion_context *fusion = instance->ctrl_context; - switch (instance->pdev->device) { - case PCI_DEVICE_ID_LSI_VENTURA: - case PCI_DEVICE_ID_LSI_HARPOON: - case PCI_DEVICE_ID_LSI_TOMCAT: - case PCI_DEVICE_ID_LSI_VENTURA_4PORT: - case PCI_DEVICE_ID_LSI_CRUSADER_4PORT: - instance->is_ventura = true; - case PCI_DEVICE_ID_LSI_FUSION: - case PCI_DEVICE_ID_LSI_PLASMA: - case PCI_DEVICE_ID_LSI_INVADER: - case PCI_DEVICE_ID_LSI_FURY: - case PCI_DEVICE_ID_LSI_INTRUDER: - case PCI_DEVICE_ID_LSI_INTRUDER_24: - case PCI_DEVICE_ID_LSI_CUTLASS_52: - case PCI_DEVICE_ID_LSI_CUTLASS_53: - { - if (megasas_alloc_fusion_context(instance)) { - megasas_free_fusion_context(instance); - goto fail_alloc_dma_buf; - } - fusion = instance->ctrl_context; + instance->evt_detail = + pci_alloc_consistent(pdev, + sizeof(struct megasas_evt_detail), + &instance->evt_detail_h); - if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || - (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA)) - fusion->adapter_type = THUNDERBOLT_SERIES; - else if (instance->is_ventura) - fusion->adapter_type = VENTURA_SERIES; - else - fusion->adapter_type = INVADER_SERIES; - } - break; - default: /* For all other supported controllers */ - - instance->producer = - pci_alloc_consistent(pdev, sizeof(u32), - &instance->producer_h); - instance->consumer = - pci_alloc_consistent(pdev, sizeof(u32), - &instance->consumer_h); - - if (!instance->producer || !instance->consumer) { - dev_printk(KERN_DEBUG, &pdev->dev, "Failed to allocate " - "memory for producer, consumer\n"); - goto fail_alloc_dma_buf; + if (!instance->evt_detail) { + dev_err(&instance->pdev->dev, + "Failed to allocate event detail buffer\n"); + return -ENOMEM; + } + + if (fusion) { + fusion->ioc_init_request = + dma_alloc_coherent(&pdev->dev, + sizeof(struct MPI2_IOC_INIT_REQUEST), + &fusion->ioc_init_request_phys, + GFP_KERNEL); + + if (!fusion->ioc_init_request) { + dev_err(&pdev->dev, + "Failed to allocate PD list buffer\n"); + return -ENOMEM; } + } - *instance->producer = 0; - *instance->consumer = 0; - break; + instance->pd_list_buf = + pci_alloc_consistent(pdev, + MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), + &instance->pd_list_buf_h); + + if (!instance->pd_list_buf) { + dev_err(&pdev->dev, "Failed to allocate PD list buffer\n"); + return -ENOMEM; } - /* Crash dump feature related initialisation*/ - instance->drv_buf_index = 0; - instance->drv_buf_alloc = 0; - instance->crash_dump_fw_support = 0; - instance->crash_dump_app_support = 0; - instance->fw_crash_state = UNAVAILABLE; - spin_lock_init(&instance->crashdump_lock); - instance->crash_dump_buf = NULL; + instance->ctrl_info_buf = + pci_alloc_consistent(pdev, + sizeof(struct megasas_ctrl_info), + &instance->ctrl_info_buf_h); - megasas_poll_wait_aen = 0; - instance->flag_ieee = 0; - instance->ev = NULL; - instance->issuepend_done = 1; - atomic_set(&instance->adprecovery, MEGASAS_HBA_OPERATIONAL); - instance->is_imr = 0; + if (!instance->ctrl_info_buf) { + dev_err(&pdev->dev, + "Failed to allocate controller info buffer\n"); + return -ENOMEM; + } - instance->evt_detail = pci_alloc_consistent(pdev, - sizeof(struct - megasas_evt_detail), - &instance->evt_detail_h); + instance->ld_list_buf = + pci_alloc_consistent(pdev, + sizeof(struct MR_LD_LIST), + &instance->ld_list_buf_h); - if (!instance->evt_detail) { - dev_printk(KERN_DEBUG, &pdev->dev, "Failed to allocate memory for " - "event detail structure\n"); - goto fail_alloc_dma_buf; + if (!instance->ld_list_buf) { + dev_err(&pdev->dev, "Failed to allocate LD list buffer\n"); + return -ENOMEM; + } + + instance->ld_targetid_list_buf = + pci_alloc_consistent(pdev, + sizeof(struct MR_LD_TARGETID_LIST), + &instance->ld_targetid_list_buf_h); + + if (!instance->ld_targetid_list_buf) { + dev_err(&pdev->dev, + "Failed to allocate LD targetid list buffer\n"); + return -ENOMEM; } if (!reset_devices) { - instance->system_info_buf = pci_zalloc_consistent(pdev, - sizeof(struct MR_DRV_SYSTEM_INFO), - &instance->system_info_h); - if (!instance->system_info_buf) - dev_info(&instance->pdev->dev, "Can't allocate system info buffer\n"); + instance->system_info_buf = + pci_alloc_consistent(pdev, + sizeof(struct MR_DRV_SYSTEM_INFO), + &instance->system_info_h); + instance->pd_info = + pci_alloc_consistent(pdev, + sizeof(struct MR_PD_INFO), + &instance->pd_info_h); + instance->tgt_prop = + pci_alloc_consistent(pdev, + sizeof(struct MR_TARGET_PROPERTIES), + &instance->tgt_prop_h); + instance->crash_dump_buf = + pci_alloc_consistent(pdev, + CRASH_DMA_BUF_SIZE, + &instance->crash_dump_h); - instance->pd_info = pci_alloc_consistent(pdev, - sizeof(struct MR_PD_INFO), &instance->pd_info_h); + if (!instance->system_info_buf) + dev_err(&instance->pdev->dev, + "Failed to allocate system info buffer\n"); if (!instance->pd_info) - dev_err(&instance->pdev->dev, "Failed to alloc mem for pd_info\n"); - - instance->tgt_prop = pci_alloc_consistent(pdev, - sizeof(struct MR_TARGET_PROPERTIES), &instance->tgt_prop_h); + dev_err(&instance->pdev->dev, + "Failed to allocate pd_info buffer\n"); if (!instance->tgt_prop) - dev_err(&instance->pdev->dev, "Failed to alloc mem for tgt_prop\n"); + dev_err(&instance->pdev->dev, + "Failed to allocate tgt_prop buffer\n"); - instance->crash_dump_buf = pci_alloc_consistent(pdev, - CRASH_DMA_BUF_SIZE, - &instance->crash_dump_h); if (!instance->crash_dump_buf) - dev_err(&pdev->dev, "Can't allocate Firmware " - "crash dump DMA buffer\n"); + dev_err(&instance->pdev->dev, + "Failed to allocate crash dump buffer\n"); } + return 0; +} + +/* + * megasas_free_ctrl_dma_buffers - Free consistent DMA buffers allocated + * during driver load time + * + * @instance- Adapter soft instance + * + */ +static inline +void megasas_free_ctrl_dma_buffers(struct megasas_instance *instance) +{ + struct pci_dev *pdev = instance->pdev; + struct fusion_context *fusion = instance->ctrl_context; + + if (instance->evt_detail) + pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), + instance->evt_detail, + instance->evt_detail_h); + + if (fusion && fusion->ioc_init_request) + dma_free_coherent(&pdev->dev, + sizeof(struct MPI2_IOC_INIT_REQUEST), + fusion->ioc_init_request, + fusion->ioc_init_request_phys); + + if (instance->pd_list_buf) + pci_free_consistent(pdev, + MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), + instance->pd_list_buf, + instance->pd_list_buf_h); + + if (instance->ld_list_buf) + pci_free_consistent(pdev, sizeof(struct MR_LD_LIST), + instance->ld_list_buf, + instance->ld_list_buf_h); + + if (instance->ld_targetid_list_buf) + pci_free_consistent(pdev, sizeof(struct MR_LD_TARGETID_LIST), + instance->ld_targetid_list_buf, + instance->ld_targetid_list_buf_h); + + if (instance->ctrl_info_buf) + pci_free_consistent(pdev, sizeof(struct megasas_ctrl_info), + instance->ctrl_info_buf, + instance->ctrl_info_buf_h); + + if (instance->system_info_buf) + pci_free_consistent(pdev, sizeof(struct MR_DRV_SYSTEM_INFO), + instance->system_info_buf, + instance->system_info_h); + + if (instance->pd_info) + pci_free_consistent(pdev, sizeof(struct MR_PD_INFO), + instance->pd_info, instance->pd_info_h); + + if (instance->tgt_prop) + pci_free_consistent(pdev, sizeof(struct MR_TARGET_PROPERTIES), + instance->tgt_prop, instance->tgt_prop_h); + + if (instance->crash_dump_buf) + pci_free_consistent(pdev, CRASH_DMA_BUF_SIZE, + instance->crash_dump_buf, + instance->crash_dump_h); +} + +/* + * megasas_init_ctrl_params - Initialize controller's instance + * parameters before FW init + * @instance - Adapter soft instance + * @return - void + */ +static inline void megasas_init_ctrl_params(struct megasas_instance *instance) +{ + instance->fw_crash_state = UNAVAILABLE; + + megasas_poll_wait_aen = 0; + instance->issuepend_done = 1; + atomic_set(&instance->adprecovery, MEGASAS_HBA_OPERATIONAL); + /* * Initialize locks and queues */ INIT_LIST_HEAD(&instance->cmd_pool); INIT_LIST_HEAD(&instance->internal_reset_pending_q); - atomic_set(&instance->fw_outstanding,0); + atomic_set(&instance->fw_outstanding, 0); init_waitqueue_head(&instance->int_cmd_wait_q); init_waitqueue_head(&instance->abort_cmd_wait_q); + spin_lock_init(&instance->crashdump_lock); spin_lock_init(&instance->mfi_pool_lock); spin_lock_init(&instance->hba_lock); spin_lock_init(&instance->stream_lock); spin_lock_init(&instance->completion_lock); - mutex_init(&instance->reset_mutex); mutex_init(&instance->hba_mutex); - - /* - * Initialize PCI related and misc parameters - */ - instance->host = host; - instance->unique_id = pdev->bus->number << 8 | pdev->devfn; - instance->init_id = MEGASAS_DEFAULT_INIT_ID; - instance->ctrl_info = NULL; - + mutex_init(&instance->reset_mutex); if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || - (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) + (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) instance->flag_ieee = 1; megasas_dbg_lvl = 0; @@ -6160,11 +6360,75 @@ static int megasas_probe_one(struct pci_dev *pdev, instance->disableOnlineCtrlReset = 1; instance->UnevenSpanSupport = 0; - if (instance->ctrl_context) { + if (instance->adapter_type != MFI_SERIES) { INIT_WORK(&instance->work_init, megasas_fusion_ocr_wq); INIT_WORK(&instance->crash_init, megasas_fusion_crash_dump_wq); - } else + } else { INIT_WORK(&instance->work_init, process_fw_state_change_wq); + } +} + +/** + * megasas_probe_one - PCI hotplug entry point + * @pdev: PCI device structure + * @id: PCI ids of supported hotplugged adapter + */ +static int megasas_probe_one(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + int rval, pos; + struct Scsi_Host *host; + struct megasas_instance *instance; + u16 control = 0; + + /* Reset MSI-X in the kdump kernel */ + if (reset_devices) { + pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX); + if (pos) { + pci_read_config_word(pdev, pos + PCI_MSIX_FLAGS, + &control); + if (control & PCI_MSIX_FLAGS_ENABLE) { + dev_info(&pdev->dev, "resetting MSI-X\n"); + pci_write_config_word(pdev, + pos + PCI_MSIX_FLAGS, + control & + ~PCI_MSIX_FLAGS_ENABLE); + } + } + } + + /* + * PCI prepping: enable device set bus mastering and dma mask + */ + rval = pci_enable_device_mem(pdev); + + if (rval) { + return rval; + } + + pci_set_master(pdev); + + host = scsi_host_alloc(&megasas_template, + sizeof(struct megasas_instance)); + + if (!host) { + dev_printk(KERN_DEBUG, &pdev->dev, "scsi_host_alloc failed\n"); + goto fail_alloc_instance; + } + + instance = (struct megasas_instance *)host->hostdata; + memset(instance, 0, sizeof(*instance)); + atomic_set(&instance->fw_reset_no_pci_access, 0); + + /* + * Initialize PCI related and misc parameters + */ + instance->pdev = pdev; + instance->host = host; + instance->unique_id = pdev->bus->number << 8 | pdev->devfn; + instance->init_id = MEGASAS_DEFAULT_INIT_ID; + + megasas_set_adapter_type(instance); /* * Initialize MFI Firmware @@ -6240,37 +6504,16 @@ fail_io_attach: instance->instancet->disable_intr(instance); megasas_destroy_irqs(instance); - if (instance->ctrl_context) + if (instance->adapter_type != MFI_SERIES) megasas_release_fusion(instance); else megasas_release_mfi(instance); if (instance->msix_vectors) pci_free_irq_vectors(instance->pdev); fail_init_mfi: -fail_alloc_dma_buf: - if (instance->evt_detail) - pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), - instance->evt_detail, - instance->evt_detail_h); - - if (instance->pd_info) - pci_free_consistent(pdev, sizeof(struct MR_PD_INFO), - instance->pd_info, - instance->pd_info_h); - if (instance->tgt_prop) - pci_free_consistent(pdev, sizeof(struct MR_TARGET_PROPERTIES), - instance->tgt_prop, - instance->tgt_prop_h); - if (instance->producer) - pci_free_consistent(pdev, sizeof(u32), instance->producer, - instance->producer_h); - if (instance->consumer) - pci_free_consistent(pdev, sizeof(u32), instance->consumer, - instance->consumer_h); scsi_host_put(host); fail_alloc_instance: -fail_set_dma_mask: pci_disable_device(pdev); return -ENODEV; @@ -6447,7 +6690,13 @@ megasas_resume(struct pci_dev *pdev) pci_set_master(pdev); - if (megasas_set_dma_mask(pdev)) + /* + * We expect the FW state to be READY + */ + if (megasas_transition_to_ready(instance, 0)) + goto fail_ready_state; + + if (megasas_set_dma_mask(instance)) goto fail_set_dma_mask; /* @@ -6456,12 +6705,6 @@ megasas_resume(struct pci_dev *pdev) atomic_set(&instance->fw_outstanding, 0); - /* - * We expect the FW state to be READY - */ - if (megasas_transition_to_ready(instance, 0)) - goto fail_ready_state; - /* Now re-enable MSI-X */ if (instance->msix_vectors) { irq_flags = PCI_IRQ_MSIX; @@ -6474,7 +6717,7 @@ megasas_resume(struct pci_dev *pdev) if (rval < 0) goto fail_reenable_msix; - if (instance->ctrl_context) { + if (instance->adapter_type != MFI_SERIES) { megasas_reset_reply_desc(instance); if (megasas_ioc_init_fusion(instance)) { megasas_free_cmds(instance); @@ -6521,30 +6764,13 @@ megasas_resume(struct pci_dev *pdev) return 0; fail_init_mfi: - if (instance->evt_detail) - pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), - instance->evt_detail, - instance->evt_detail_h); - - if (instance->pd_info) - pci_free_consistent(pdev, sizeof(struct MR_PD_INFO), - instance->pd_info, - instance->pd_info_h); - if (instance->tgt_prop) - pci_free_consistent(pdev, sizeof(struct MR_TARGET_PROPERTIES), - instance->tgt_prop, - instance->tgt_prop_h); - if (instance->producer) - pci_free_consistent(pdev, sizeof(u32), instance->producer, - instance->producer_h); - if (instance->consumer) - pci_free_consistent(pdev, sizeof(u32), instance->consumer, - instance->consumer_h); + megasas_free_ctrl_dma_buffers(instance); + megasas_free_ctrl_mem(instance); scsi_host_put(host); +fail_reenable_msix: fail_set_dma_mask: fail_ready_state: -fail_reenable_msix: pci_disable_device(pdev); @@ -6647,7 +6873,7 @@ skip_firing_dcmds: if (instance->msix_vectors) pci_free_irq_vectors(instance->pdev); - if (instance->is_ventura) { + if (instance->adapter_type == VENTURA_SERIES) { for (i = 0; i < MAX_LOGICAL_DRIVES_EXT; ++i) kfree(fusion->stream_detect_by_ld[i]); kfree(fusion->stream_detect_by_ld); @@ -6655,7 +6881,7 @@ skip_firing_dcmds: } - if (instance->ctrl_context) { + if (instance->adapter_type != MFI_SERIES) { megasas_release_fusion(instance); pd_seq_map_sz = sizeof(struct MR_PD_CFG_SEQ_NUM_SYNC) + (sizeof(struct MR_PD_CFG_SEQ) * @@ -6680,30 +6906,10 @@ skip_firing_dcmds: fusion->pd_seq_sync[i], fusion->pd_seq_phys[i]); } - megasas_free_fusion_context(instance); } else { megasas_release_mfi(instance); - pci_free_consistent(pdev, sizeof(u32), - instance->producer, - instance->producer_h); - pci_free_consistent(pdev, sizeof(u32), - instance->consumer, - instance->consumer_h); } - kfree(instance->ctrl_info); - - if (instance->evt_detail) - pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), - instance->evt_detail, instance->evt_detail_h); - if (instance->pd_info) - pci_free_consistent(pdev, sizeof(struct MR_PD_INFO), - instance->pd_info, - instance->pd_info_h); - if (instance->tgt_prop) - pci_free_consistent(pdev, sizeof(struct MR_TARGET_PROPERTIES), - instance->tgt_prop, - instance->tgt_prop_h); if (instance->vf_affiliation) pci_free_consistent(pdev, (MAX_LOGICAL_DRIVES + 1) * sizeof(struct MR_LD_VF_AFFILIATION), @@ -6721,13 +6927,9 @@ skip_firing_dcmds: instance->hb_host_mem, instance->hb_host_mem_h); - if (instance->crash_dump_buf) - pci_free_consistent(pdev, CRASH_DMA_BUF_SIZE, - instance->crash_dump_buf, instance->crash_dump_h); + megasas_free_ctrl_dma_buffers(instance); - if (instance->system_info_buf) - pci_free_consistent(pdev, sizeof(struct MR_DRV_SYSTEM_INFO), - instance->system_info_buf, instance->system_info_h); + megasas_free_ctrl_mem(instance); scsi_host_put(host); @@ -6866,7 +7068,8 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, struct megasas_iocpacket __user * user_ioc, struct megasas_iocpacket *ioc) { - struct megasas_sge32 *kern_sge32; + struct megasas_sge64 *kern_sge64 = NULL; + struct megasas_sge32 *kern_sge32 = NULL; struct megasas_cmd *cmd; void *kbuff_arr[MAX_IOCTL_SGE]; dma_addr_t buf_handle = 0; @@ -6874,7 +7077,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, void *sense = NULL; dma_addr_t sense_handle; unsigned long *sense_ptr; - u32 opcode; + u32 opcode = 0; memset(kbuff_arr, 0, sizeof(kbuff_arr)); @@ -6884,6 +7087,13 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, return -EINVAL; } + if (ioc->frame.hdr.cmd >= MFI_CMD_OP_COUNT) { + dev_err(&instance->pdev->dev, + "Received invalid ioctl command 0x%x\n", + ioc->frame.hdr.cmd); + return -ENOTSUPP; + } + cmd = megasas_get_cmd(instance); if (!cmd) { dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to get a cmd packet\n"); @@ -6899,10 +7109,18 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE); cmd->frame->hdr.context = cpu_to_le32(cmd->index); cmd->frame->hdr.pad_0 = 0; - cmd->frame->hdr.flags &= cpu_to_le16(~(MFI_FRAME_IEEE | - MFI_FRAME_SGL64 | + + cmd->frame->hdr.flags &= (~MFI_FRAME_IEEE); + + if (instance->consistent_mask_64bit) + cmd->frame->hdr.flags |= cpu_to_le16((MFI_FRAME_SGL64 | + MFI_FRAME_SENSE64)); + else + cmd->frame->hdr.flags &= cpu_to_le16(~(MFI_FRAME_SGL64 | MFI_FRAME_SENSE64)); - opcode = le32_to_cpu(cmd->frame->dcmd.opcode); + + if (cmd->frame->hdr.cmd == MFI_CMD_DCMD) + opcode = le32_to_cpu(cmd->frame->dcmd.opcode); if (opcode == MR_DCMD_CTRL_SHUTDOWN) { if (megasas_get_ctrl_info(instance) != DCMD_SUCCESS) { @@ -6925,8 +7143,12 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, * kernel buffers in SGLs. The location of SGL is embedded in the * struct iocpacket itself. */ - kern_sge32 = (struct megasas_sge32 *) - ((unsigned long)cmd->frame + ioc->sgl_off); + if (instance->consistent_mask_64bit) + kern_sge64 = (struct megasas_sge64 *) + ((unsigned long)cmd->frame + ioc->sgl_off); + else + kern_sge32 = (struct megasas_sge32 *) + ((unsigned long)cmd->frame + ioc->sgl_off); /* * For each user buffer, create a mirror buffer and copy in @@ -6949,8 +7171,13 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, * We don't change the dma_coherent_mask, so * pci_alloc_consistent only returns 32bit addresses */ - kern_sge32[i].phys_addr = cpu_to_le32(buf_handle); - kern_sge32[i].length = cpu_to_le32(ioc->sgl[i].iov_len); + if (instance->consistent_mask_64bit) { + kern_sge64[i].phys_addr = cpu_to_le64(buf_handle); + kern_sge64[i].length = cpu_to_le32(ioc->sgl[i].iov_len); + } else { + kern_sge32[i].phys_addr = cpu_to_le32(buf_handle); + kern_sge32[i].length = cpu_to_le32(ioc->sgl[i].iov_len); + } /* * We created a kernel buffer corresponding to the @@ -6973,7 +7200,10 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, sense_ptr = (unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off); - *sense_ptr = cpu_to_le32(sense_handle); + if (instance->consistent_mask_64bit) + *sense_ptr = cpu_to_le64(sense_handle); + else + *sense_ptr = cpu_to_le32(sense_handle); } /* @@ -6984,8 +7214,9 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, if (megasas_issue_blocked_cmd(instance, cmd, 0) == DCMD_NOT_FIRED) { cmd->sync_cmd = 0; dev_err(&instance->pdev->dev, - "return -EBUSY from %s %d opcode 0x%x cmd->cmd_status_drv 0x%x\n", - __func__, __LINE__, opcode, cmd->cmd_status_drv); + "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; } @@ -7045,10 +7276,16 @@ out: for (i = 0; i < ioc->sge_count; i++) { if (kbuff_arr[i]) { - dma_free_coherent(&instance->pdev->dev, - le32_to_cpu(kern_sge32[i].length), - kbuff_arr[i], - le32_to_cpu(kern_sge32[i].phys_addr)); + if (instance->consistent_mask_64bit) + dma_free_coherent(&instance->pdev->dev, + le32_to_cpu(kern_sge64[i].length), + kbuff_arr[i], + le64_to_cpu(kern_sge64[i].phys_addr)); + else + dma_free_coherent(&instance->pdev->dev, + le32_to_cpu(kern_sge32[i].length), + kbuff_arr[i], + le32_to_cpu(kern_sge32[i].phys_addr)); kbuff_arr[i] = NULL; } } |