From 51087a8617fef1fb15e5b7a8805cfbab3583944d Mon Sep 17 00:00:00 2001 From: "Sumit.Saxena@avagotech.com" Date: Fri, 12 Sep 2014 18:57:33 +0530 Subject: [PATCH] megaraid_sas : Extended VD support Resending the patch. Addressed the review comments from Tomas Henzl. reserved1 field(part of union) of Raid map struct was not required so it is removed. Current MegaRAID firmware and hence the driver only supported 64VDs. E.g: If the user wants to create more than 64VD on a controller, it is not possible on current firmware/driver. New feature and requirement to support upto 256VD, firmware/driver/apps need changes. In addition to that there must be a backward compatibility of the new driver with the older firmware and vice versa. RAID map is the interface between Driver and FW to fetch all required fields(attributes) for each Virtual Drives. In the earlier design driver was using the FW copy of RAID map where as in the new design the Driver will keep the RAID map copy of its own; on which it will operate for any raid map access in fast path. Local driver raid map copy will provide ease of access through out the code and provide generic interface for future FW raid map changes. For the backward compatibility driver will notify FW that it supports 256VD to the FW in driver capability field. Based on the controller properly returned by the FW, the Driver will know whether it supports 256VD or not and will copy the RAID map accordingly. At any given time, driver will always have old or new Raid map. So with this changes, driver can also work in host lock less mode. Please see next patch which enable host lock less mode for megaraid_sas driver. Signed-off-by: Sumit Saxena Signed-off-by: Kashyap Desai Reviewed-by: Tomas Henzl Signed-off-by: Christoph Hellwig --- drivers/scsi/megaraid/megaraid_sas.h | 73 +++++-- drivers/scsi/megaraid/megaraid_sas_base.c | 205 ++++++++++++-------- drivers/scsi/megaraid/megaraid_sas_fp.c | 195 +++++++++++++------ drivers/scsi/megaraid/megaraid_sas_fusion.c | 118 ++++++++--- drivers/scsi/megaraid/megaraid_sas_fusion.h | 94 ++++++++- 5 files changed, 500 insertions(+), 185 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index e0f03e2f6ddf..5dedf09fc46d 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -390,7 +390,6 @@ enum MR_LD_QUERY_TYPE { #define MR_EVT_FOREIGN_CFG_IMPORTED 0x00db #define MR_EVT_LD_OFFLINE 0x00fc #define MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED 0x0152 -#define MAX_LOGICAL_DRIVES 64 enum MR_PD_STATE { MR_PD_STATE_UNCONFIGURED_GOOD = 0x00, @@ -468,14 +467,14 @@ struct MR_LD_LIST { u8 state; u8 reserved[3]; u64 size; - } ldList[MAX_LOGICAL_DRIVES]; + } ldList[MAX_LOGICAL_DRIVES_EXT]; } __packed; struct MR_LD_TARGETID_LIST { u32 size; u32 count; u8 pad[3]; - u8 targetId[MAX_LOGICAL_DRIVES]; + u8 targetId[MAX_LOGICAL_DRIVES_EXT]; }; @@ -941,6 +940,15 @@ struct megasas_ctrl_info { * HA cluster information */ struct { +#if defined(__BIG_ENDIAN_BITFIELD) + u32 reserved:26; + u32 premiumFeatureMismatch:1; + u32 ctrlPropIncompatible:1; + u32 fwVersionMismatch:1; + u32 hwIncompatible:1; + u32 peerIsIncompatible:1; + u32 peerIsPresent:1; +#else u32 peerIsPresent:1; u32 peerIsIncompatible:1; u32 hwIncompatible:1; @@ -948,6 +956,7 @@ struct megasas_ctrl_info { u32 ctrlPropIncompatible:1; u32 premiumFeatureMismatch:1; u32 reserved:26; +#endif } cluster; char clusterId[16]; /*7D4h */ @@ -962,9 +971,17 @@ struct megasas_ctrl_info { #if defined(__BIG_ENDIAN_BITFIELD) u32 reserved:25; u32 supportCrashDump:1; - u32 reserved1:6; + u32 supportMaxExtLDs:1; + u32 supportT10RebuildAssist:1; + u32 supportDisableImmediateIO:1; + u32 supportThermalPollInterval:1; + u32 supportPersonalityChange:2; #else - u32 reserved1:6; + u32 supportPersonalityChange:2; + u32 supportThermalPollInterval:1; + u32 supportDisableImmediateIO:1; + u32 supportT10RebuildAssist:1; + u32 supportMaxExtLDs:1; u32 supportCrashDump:1; u32 reserved:25; #endif @@ -979,13 +996,12 @@ struct megasas_ctrl_info { * =============================== */ #define MEGASAS_MAX_PD_CHANNELS 2 -#define MEGASAS_MAX_LD_CHANNELS 1 +#define MEGASAS_MAX_LD_CHANNELS 2 #define MEGASAS_MAX_CHANNELS (MEGASAS_MAX_PD_CHANNELS + \ MEGASAS_MAX_LD_CHANNELS) #define MEGASAS_MAX_DEV_PER_CHANNEL 128 #define MEGASAS_DEFAULT_INIT_ID -1 #define MEGASAS_MAX_LUN 8 -#define MEGASAS_MAX_LD 64 #define MEGASAS_DEFAULT_CMD_PER_LUN 256 #define MEGASAS_MAX_PD (MEGASAS_MAX_PD_CHANNELS * \ MEGASAS_MAX_DEV_PER_CHANNEL) @@ -998,6 +1014,8 @@ struct megasas_ctrl_info { #define MEGASAS_FW_BUSY 1 +#define VD_EXT_DEBUG 0 + /* Frame Type */ #define IO_FRAME 0 #define PTHRU_FRAME 1 @@ -1170,13 +1188,17 @@ union megasas_sgl_frame { typedef union _MFI_CAPABILITIES { struct { #if defined(__BIG_ENDIAN_BITFIELD) - u32 reserved:30; + u32 reserved:28; + u32 support_max_255lds:1; + u32 reserved1:1; u32 support_additional_msix:1; u32 support_fp_remote_lun:1; #else u32 support_fp_remote_lun:1; u32 support_additional_msix:1; - u32 reserved:30; + u32 reserved1:1; + u32 support_max_255lds:1; + u32 reserved:28; #endif } mfi_capabilities; u32 reg; @@ -1665,6 +1687,14 @@ struct megasas_instance { u8 issuepend_done; u8 disableOnlineCtrlReset; u8 UnevenSpanSupport; + + u8 supportmax256vd; + u16 fw_supported_vd_count; + u16 fw_supported_pd_count; + + u16 drv_supported_vd_count; + u16 drv_supported_pd_count; + u8 adprecovery; unsigned long last_time; u32 mfiStatus; @@ -1674,6 +1704,8 @@ struct megasas_instance { /* Ptr to hba specific information */ void *ctrl_context; + u32 ctrl_context_pages; + struct megasas_ctrl_info *ctrl_info; unsigned int msix_vectors; struct msix_entry msixentry[MEGASAS_MAX_MSIX_QUEUES]; struct megasas_irq_context irq_context[MEGASAS_MAX_MSIX_QUEUES]; @@ -1874,16 +1906,21 @@ u8 MR_BuildRaidContext(struct megasas_instance *instance, struct IO_REQUEST_INFO *io_info, struct RAID_CONTEXT *pRAID_Context, - struct MR_FW_RAID_MAP_ALL *map, u8 **raidLUN); -u8 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map); -struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_FW_RAID_MAP_ALL *map); -u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_FW_RAID_MAP_ALL *map); -u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_FW_RAID_MAP_ALL *map); -u16 MR_PdDevHandleGet(u32 pd, struct MR_FW_RAID_MAP_ALL *map); -u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map); - + struct MR_DRV_RAID_MAP_ALL *map, u8 **raidLUN); +u8 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_DRV_RAID_MAP_ALL *map); +struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_DRV_RAID_MAP_ALL *map); +u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_DRV_RAID_MAP_ALL *map); +u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_DRV_RAID_MAP_ALL *map); +u16 MR_PdDevHandleGet(u32 pd, struct MR_DRV_RAID_MAP_ALL *map); +u16 MR_GetLDTgtId(u32 ld, struct MR_DRV_RAID_MAP_ALL *map); + +void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *map, + struct LD_LOAD_BALANCE_INFO *lbInfo); +int megasas_get_ctrl_info(struct megasas_instance *instance, + struct megasas_ctrl_info *ctrl_info); int megasas_set_crash_dump_params(struct megasas_instance *instance, - u8 crash_buf_state); + u8 crash_buf_state); void megasas_free_host_crash_buffer(struct megasas_instance *instance); void megasas_fusion_crash_dump_wq(struct work_struct *work); + #endif /*LSI_MEGARAID_SAS_H */ diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index ff96e3c58fbf..c7ddb129349d 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -1581,7 +1581,8 @@ megasas_queue_command_lck(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd scmd->result = 0; if (MEGASAS_IS_LOGICAL(scmd) && - (scmd->device->id >= MEGASAS_MAX_LD || scmd->device->lun)) { + (scmd->device->id >= instance->fw_supported_vd_count || + scmd->device->lun)) { scmd->result = DID_BAD_TARGET << 16; goto out_done; } @@ -3846,6 +3847,8 @@ megasas_get_ld_list(struct megasas_instance *instance) memset(ci, 0, sizeof(*ci)); memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + if (instance->supportmax256vd) + dcmd->mbox.b[0] = 1; dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd_status = 0xFF; dcmd->sge_count = 1; @@ -3867,8 +3870,8 @@ megasas_get_ld_list(struct megasas_instance *instance) /* the following function will get the instance PD LIST */ - if ((ret == 0) && (ld_count <= MAX_LOGICAL_DRIVES)) { - memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); + if ((ret == 0) && (ld_count <= instance->fw_supported_vd_count)) { + memset(instance->ld_ids, 0xff, MAX_LOGICAL_DRIVES_EXT); for (ld_index = 0; ld_index < ld_count; ld_index++) { if (ci->ldList[ld_index].state != 0) { @@ -3931,6 +3934,8 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type) memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); dcmd->mbox.b[0] = query_type; + if (instance->supportmax256vd) + dcmd->mbox.b[2] = 1; dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd_status = 0xFF; @@ -3952,7 +3957,7 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type) tgtid_count = le32_to_cpu(ci->count); - if ((ret == 0) && (tgtid_count <= (MAX_LOGICAL_DRIVES))) { + if ((ret == 0) && (tgtid_count <= (instance->fw_supported_vd_count))) { memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); for (ld_index = 0; ld_index < tgtid_count; ld_index++) { ids = ci->targetId[ld_index]; @@ -3978,7 +3983,7 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type) * This information is mainly used to find out the maximum IO transfer per * command supported by the FW. */ -static int +int megasas_get_ctrl_info(struct megasas_instance *instance, struct megasas_ctrl_info *ctrl_info) { @@ -4019,6 +4024,7 @@ megasas_get_ctrl_info(struct megasas_instance *instance, 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 (!megasas_issue_polled(instance, cmd)) { ret = 0; @@ -4217,6 +4223,13 @@ megasas_init_adapter_mfi(struct megasas_instance *instance) if (megasas_issue_init_mfi(instance)) goto fail_fw_init; + if (megasas_get_ctrl_info(instance, instance->ctrl_info)) { + dev_err(&instance->pdev->dev, "(%d): Could get controller info " + "Fail from %s %d\n", instance->unique_id, + __func__, __LINE__); + goto fail_fw_init; + } + instance->fw_support_ieee = 0; instance->fw_support_ieee = (instance->instancet->read_fw_status_reg(reg_set) & @@ -4255,7 +4268,7 @@ static int megasas_init_fw(struct megasas_instance *instance) u32 tmp_sectors, msix_enable, scratch_pad_2; resource_size_t base_addr; struct megasas_register_set __iomem *reg_set; - struct megasas_ctrl_info *ctrl_info; + struct megasas_ctrl_info *ctrl_info = NULL; unsigned long bar_list; int i, loop, fw_msix_count = 0; struct IOV_111 *iovPtr; @@ -4386,6 +4399,17 @@ static int megasas_init_fw(struct megasas_instance *instance) instance->msix_vectors); } + 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 + */ + instance->fw_supported_vd_count = MAX_LOGICAL_DRIVES; + instance->fw_supported_pd_count = MAX_PHYSICAL_DEVICES; /* Get operational params, sge flags, send init cmd to controller */ if (instance->instancet->init_adapter(instance)) goto fail_init_adapter; @@ -4408,8 +4432,6 @@ static int megasas_init_fw(struct megasas_instance *instance) MR_LD_QUERY_TYPE_EXPOSED_TO_HOST)) megasas_get_ld_list(instance); - ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL); - /* * Compute the max allowed sectors per IO: The controller info has two * limits on max sectors. Driver should use the minimum of these two. @@ -4420,79 +4442,79 @@ 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; - if (ctrl_info && !megasas_get_ctrl_info(instance, ctrl_info)) { - - max_sectors_1 = (1 << ctrl_info->stripe_sz_ops.min) * - le16_to_cpu(ctrl_info->max_strips_per_io); - max_sectors_2 = le32_to_cpu(ctrl_info->max_request_size); + ctrl_info = instance->ctrl_info; - tmp_sectors = min_t(u32, max_sectors_1 , max_sectors_2); + max_sectors_1 = (1 << ctrl_info->stripe_sz_ops.min) * + le16_to_cpu(ctrl_info->max_strips_per_io); + max_sectors_2 = le32_to_cpu(ctrl_info->max_request_size); - /*Check whether controller is iMR or MR */ - if (ctrl_info->memory_size) { - instance->is_imr = 0; - dev_info(&instance->pdev->dev, "Controller type: MR," - "Memory size is: %dMB\n", - le16_to_cpu(ctrl_info->memory_size)); - } else { - instance->is_imr = 1; - dev_info(&instance->pdev->dev, - "Controller type: iMR\n"); - } - /* OnOffProperties are converted into CPU arch*/ - le32_to_cpus((u32 *)&ctrl_info->properties.OnOffProperties); - instance->disableOnlineCtrlReset = - ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset; - /* adapterOperations2 are converted into CPU arch*/ - le32_to_cpus((u32 *)&ctrl_info->adapterOperations2); - instance->mpio = ctrl_info->adapterOperations2.mpio; - instance->UnevenSpanSupport = - ctrl_info->adapterOperations2.supportUnevenSpans; - if (instance->UnevenSpanSupport) { - struct fusion_context *fusion = instance->ctrl_context; - dev_info(&instance->pdev->dev, "FW supports: " - "UnevenSpanSupport=%x\n", instance->UnevenSpanSupport); - if (MR_ValidateMapInfo(instance)) - fusion->fast_path_io = 1; - else - fusion->fast_path_io = 0; + tmp_sectors = min_t(u32, max_sectors_1 , max_sectors_2); - } - if (ctrl_info->host_interface.SRIOV) { - if (!ctrl_info->adapterOperations2.activePassive) - instance->PlasmaFW111 = 1; - - if (!instance->PlasmaFW111) - instance->requestorId = - ctrl_info->iov.requestorId; - else { - iovPtr = (struct IOV_111 *)((unsigned char *)ctrl_info + IOV_111_OFFSET); - instance->requestorId = iovPtr->requestorId; - } - printk(KERN_WARNING "megaraid_sas: I am VF " - "requestorId %d\n", instance->requestorId); - } + /*Check whether controller is iMR or MR */ + if (ctrl_info->memory_size) { + instance->is_imr = 0; + dev_info(&instance->pdev->dev, "Controller type: MR," + "Memory size is: %dMB\n", + le16_to_cpu(ctrl_info->memory_size)); + } else { + instance->is_imr = 1; + dev_info(&instance->pdev->dev, + "Controller type: iMR\n"); + } + /* OnOffProperties are converted into CPU arch*/ + le32_to_cpus((u32 *)&ctrl_info->properties.OnOffProperties); + instance->disableOnlineCtrlReset = + ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset; + /* adapterOperations2 are converted into CPU arch*/ + le32_to_cpus((u32 *)&ctrl_info->adapterOperations2); + instance->mpio = ctrl_info->adapterOperations2.mpio; + instance->UnevenSpanSupport = + ctrl_info->adapterOperations2.supportUnevenSpans; + if (instance->UnevenSpanSupport) { + struct fusion_context *fusion = instance->ctrl_context; + + dev_info(&instance->pdev->dev, "FW supports: " + "UnevenSpanSupport=%x\n", instance->UnevenSpanSupport); + if (MR_ValidateMapInfo(instance)) + fusion->fast_path_io = 1; + else + fusion->fast_path_io = 0; - le32_to_cpus((u32 *)&ctrl_info->adapterOperations3); - instance->crash_dump_fw_support = - ctrl_info->adapterOperations3.supportCrashDump; - instance->crash_dump_drv_support = - (instance->crash_dump_fw_support && - instance->crash_dump_buf); - if (instance->crash_dump_drv_support) { - dev_info(&instance->pdev->dev, "Firmware Crash dump " - "feature is supported\n"); - megasas_set_crash_dump_params(instance, - MR_CRASH_BUF_TURN_OFF); + } + if (ctrl_info->host_interface.SRIOV) { + if (!ctrl_info->adapterOperations2.activePassive) + instance->PlasmaFW111 = 1; - } else { - if (instance->crash_dump_buf) - pci_free_consistent(instance->pdev, - CRASH_DMA_BUF_SIZE, - instance->crash_dump_buf, - instance->crash_dump_h); - instance->crash_dump_buf = NULL; + if (!instance->PlasmaFW111) + instance->requestorId = + ctrl_info->iov.requestorId; + else { + iovPtr = (struct IOV_111 *)((unsigned char *)ctrl_info + IOV_111_OFFSET); + instance->requestorId = iovPtr->requestorId; } + dev_warn(&instance->pdev->dev, "I am VF " + "requestorId %d\n", instance->requestorId); + } + + le32_to_cpus((u32 *)&ctrl_info->adapterOperations3); + instance->crash_dump_fw_support = + ctrl_info->adapterOperations3.supportCrashDump; + instance->crash_dump_drv_support = + (instance->crash_dump_fw_support && + instance->crash_dump_buf); + if (instance->crash_dump_drv_support) { + dev_info(&instance->pdev->dev, "Firmware Crash dump " + "feature is supported\n"); + megasas_set_crash_dump_params(instance, + MR_CRASH_BUF_TURN_OFF); + + } else { + if (instance->crash_dump_buf) + pci_free_consistent(instance->pdev, + CRASH_DMA_BUF_SIZE, + instance->crash_dump_buf, + instance->crash_dump_h); + instance->crash_dump_buf = NULL; } instance->max_sectors_per_req = instance->max_num_sge * PAGE_SIZE / 512; @@ -4540,6 +4562,8 @@ static int megasas_init_fw(struct megasas_instance *instance) fail_init_adapter: fail_ready_state: + kfree(instance->ctrl_info); + instance->ctrl_info = NULL; iounmap(instance->reg_set); fail_ioremap: @@ -4918,6 +4942,7 @@ static int megasas_probe_one(struct pci_dev *pdev, 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) { @@ -4978,10 +5003,10 @@ static int megasas_probe_one(struct pci_dev *pdev, case PCI_DEVICE_ID_LSI_INVADER: case PCI_DEVICE_ID_LSI_FURY: { - struct fusion_context *fusion; - - instance->ctrl_context = - kzalloc(sizeof(struct fusion_context), GFP_KERNEL); + instance->ctrl_context_pages = + get_order(sizeof(struct fusion_context)); + instance->ctrl_context = (void *)__get_free_pages(GFP_KERNEL, + instance->ctrl_context_pages); if (!instance->ctrl_context) { printk(KERN_DEBUG "megasas: Failed to allocate " "memory for Fusion context info\n"); @@ -4990,6 +5015,8 @@ static int megasas_probe_one(struct pci_dev *pdev, fusion = instance->ctrl_context; INIT_LIST_HEAD(&fusion->cmd_pool); spin_lock_init(&fusion->cmd_pool_lock); + memset(fusion->load_balance_info, 0, + sizeof(struct LD_LOAD_BALANCE_INFO) * MAX_LOGICAL_DRIVES_EXT); } break; default: /* For all other supported controllers */ @@ -5035,7 +5062,6 @@ static int megasas_probe_one(struct pci_dev *pdev, instance->issuepend_done = 1; instance->adprecovery = MEGASAS_HBA_OPERATIONAL; instance->is_imr = 0; - megasas_poll_wait_aen = 0; instance->evt_detail = pci_alloc_consistent(pdev, sizeof(struct @@ -5072,6 +5098,7 @@ static int megasas_probe_one(struct pci_dev *pdev, instance->host = host; instance->unique_id = pdev->bus->number << 8 | pdev->devfn; instance->init_id = MEGASAS_DEFAULT_INIT_ID; + instance->ctrl_info = NULL; if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { @@ -5632,14 +5659,18 @@ static void megasas_detach_one(struct pci_dev *pdev) case PCI_DEVICE_ID_LSI_INVADER: case PCI_DEVICE_ID_LSI_FURY: megasas_release_fusion(instance); - for (i = 0; i < 2 ; i++) + for (i = 0; i < 2 ; i++) { if (fusion->ld_map[i]) dma_free_coherent(&instance->pdev->dev, - fusion->map_sz, + fusion->max_map_sz, fusion->ld_map[i], - fusion-> - ld_map_phys[i]); - kfree(instance->ctrl_context); + fusion->ld_map_phys[i]); + if (fusion->ld_drv_map[i]) + free_pages((ulong)fusion->ld_drv_map[i], + fusion->drv_map_pages); + } + free_pages((ulong)instance->ctrl_context, + instance->ctrl_context_pages); break; default: megasas_release_mfi(instance); @@ -5652,6 +5683,8 @@ static void megasas_detach_one(struct pci_dev *pdev) break; } + kfree(instance->ctrl_info); + if (instance->evt_detail) pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), instance->evt_detail, instance->evt_detail_h); @@ -5762,8 +5795,10 @@ static unsigned int megasas_mgmt_poll(struct file *file, poll_table *wait) spin_lock_irqsave(&poll_aen_lock, flags); if (megasas_poll_wait_aen) mask = (POLLIN | POLLRDNORM); + else mask = 0; + megasas_poll_wait_aen = 0; spin_unlock_irqrestore(&poll_aen_lock, flags); return mask; } diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c index 081bfff12d00..c2eaf6ef3d11 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fp.c +++ b/drivers/scsi/megaraid/megaraid_sas_fp.c @@ -66,16 +66,13 @@ #define SPAN_INVALID 0xff /* Prototypes */ -void mr_update_load_balance_params(struct MR_FW_RAID_MAP_ALL *map, - struct LD_LOAD_BALANCE_INFO *lbInfo); - -static void mr_update_span_set(struct MR_FW_RAID_MAP_ALL *map, +static void mr_update_span_set(struct MR_DRV_RAID_MAP_ALL *map, PLD_SPAN_INFO ldSpanInfo); static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld, u64 stripRow, u16 stripRef, struct IO_REQUEST_INFO *io_info, - struct RAID_CONTEXT *pRAID_Context, struct MR_FW_RAID_MAP_ALL *map); + struct RAID_CONTEXT *pRAID_Context, struct MR_DRV_RAID_MAP_ALL *map); static u64 get_row_from_strip(struct megasas_instance *instance, u32 ld, - u64 strip, struct MR_FW_RAID_MAP_ALL *map); + u64 strip, struct MR_DRV_RAID_MAP_ALL *map); u32 mega_mod64(u64 dividend, u32 divisor) { @@ -109,94 +106,183 @@ u64 mega_div64_32(uint64_t dividend, uint32_t divisor) return d; } -struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_FW_RAID_MAP_ALL *map) +struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_DRV_RAID_MAP_ALL *map) { return &map->raidMap.ldSpanMap[ld].ldRaid; } static struct MR_SPAN_BLOCK_INFO *MR_LdSpanInfoGet(u32 ld, - struct MR_FW_RAID_MAP_ALL + struct MR_DRV_RAID_MAP_ALL *map) { return &map->raidMap.ldSpanMap[ld].spanBlock[0]; } -static u8 MR_LdDataArmGet(u32 ld, u32 armIdx, struct MR_FW_RAID_MAP_ALL *map) +static u8 MR_LdDataArmGet(u32 ld, u32 armIdx, struct MR_DRV_RAID_MAP_ALL *map) { return map->raidMap.ldSpanMap[ld].dataArmMap[armIdx]; } -u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_FW_RAID_MAP_ALL *map) +u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_DRV_RAID_MAP_ALL *map) { return le16_to_cpu(map->raidMap.arMapInfo[ar].pd[arm]); } -u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_FW_RAID_MAP_ALL *map) +u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_DRV_RAID_MAP_ALL *map) { return le16_to_cpu(map->raidMap.ldSpanMap[ld].spanBlock[span].span.arrayRef); } -u16 MR_PdDevHandleGet(u32 pd, struct MR_FW_RAID_MAP_ALL *map) +u16 MR_PdDevHandleGet(u32 pd, struct MR_DRV_RAID_MAP_ALL *map) { return map->raidMap.devHndlInfo[pd].curDevHdl; } -u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map) +u16 MR_GetLDTgtId(u32 ld, struct MR_DRV_RAID_MAP_ALL *map) { return le16_to_cpu(map->raidMap.ldSpanMap[ld].ldRaid.targetId); } -u8 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map) +u8 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_DRV_RAID_MAP_ALL *map) { return map->raidMap.ldTgtIdToLd[ldTgtId]; } static struct MR_LD_SPAN *MR_LdSpanPtrGet(u32 ld, u32 span, - struct MR_FW_RAID_MAP_ALL *map) + struct MR_DRV_RAID_MAP_ALL *map) { return &map->raidMap.ldSpanMap[ld].spanBlock[span].span; } +/* + * This function will Populate Driver Map using firmware raid map + */ +void MR_PopulateDrvRaidMap(struct megasas_instance *instance) +{ + struct fusion_context *fusion = instance->ctrl_context; + struct MR_FW_RAID_MAP_ALL *fw_map_old = NULL; + struct MR_FW_RAID_MAP *pFwRaidMap = NULL; + int i; + + + struct MR_DRV_RAID_MAP_ALL *drv_map = + fusion->ld_drv_map[(instance->map_id & 1)]; + struct MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap; + + if (instance->supportmax256vd) { + memcpy(fusion->ld_drv_map[instance->map_id & 1], + fusion->ld_map[instance->map_id & 1], + fusion->current_map_sz); + /* New Raid map will not set totalSize, so keep expected value + * for legacy code in ValidateMapInfo + */ + pDrvRaidMap->totalSize = sizeof(struct MR_FW_RAID_MAP_EXT); + } else { + fw_map_old = (struct MR_FW_RAID_MAP_ALL *) + fusion->ld_map[(instance->map_id & 1)]; + pFwRaidMap = &fw_map_old->raidMap; + +#if VD_EXT_DEBUG + for (i = 0; i < pFwRaidMap->ldCount; i++) { + dev_dbg(&instance->pdev->dev, "(%d) :Index 0x%x " + "Target Id 0x%x Seq Num 0x%x Size 0/%llx\n", + instance->unique_id, i, + fw_map_old->raidMap.ldSpanMap[i].ldRaid.targetId, + fw_map_old->raidMap.ldSpanMap[i].ldRaid.seqNum, + fw_map_old->raidMap.ldSpanMap[i].ldRaid.size); + } +#endif + + memset(drv_map, 0, fusion->drv_map_sz); + pDrvRaidMap->totalSize = pFwRaidMap->totalSize; + pDrvRaidMap->ldCount = pFwRaidMap->ldCount; + pDrvRaidMap->fpPdIoTimeoutSec = pFwRaidMap->fpPdIoTimeoutSec; + for (i = 0; i < MAX_RAIDMAP_LOGICAL_DRIVES + MAX_RAIDMAP_VIEWS; i++) + pDrvRaidMap->ldTgtIdToLd[i] = + (u8)pFwRaidMap->ldTgtIdToLd[i]; + for (i = 0; i < pDrvRaidMap->ldCount; i++) { + pDrvRaidMap->ldSpanMap[i] = pFwRaidMap->ldSpanMap[i]; +#if VD_EXT_DEBUG + dev_dbg(&instance->pdev->dev, + "pFwRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x " + "pFwRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x " + "size 0x%x\n", i, i, + pFwRaidMap->ldSpanMap[i].ldRaid.targetId, + pFwRaidMap->ldSpanMap[i].ldRaid.seqNum, + (u32)pFwRaidMap->ldSpanMap[i].ldRaid.rowSize); + dev_dbg(&instance->pdev->dev, + "pDrvRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x " + "pDrvRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x " + "size 0x%x\n", i, i, + pDrvRaidMap->ldSpanMap[i].ldRaid.targetId, + pDrvRaidMap->ldSpanMap[i].ldRaid.seqNum, + (u32)pDrvRaidMap->ldSpanMap[i].ldRaid.rowSize); + dev_dbg(&instance->pdev->dev, "Driver raid map all %p " + "raid map %p LD RAID MAP %p/%p\n", drv_map, + pDrvRaidMap, &pFwRaidMap->ldSpanMap[i].ldRaid, + &pDrvRaidMap->ldSpanMap[i].ldRaid); +#endif + } + memcpy(pDrvRaidMap->arMapInfo, pFwRaidMap->arMapInfo, + sizeof(struct MR_ARRAY_INFO) * MAX_RAIDMAP_ARRAYS); + memcpy(pDrvRaidMap->devHndlInfo, pFwRaidMap->devHndlInfo, + sizeof(struct MR_DEV_HANDLE_INFO) * + MAX_RAIDMAP_PHYSICAL_DEVICES); + } +} + /* * This function will validate Map info data provided by FW */ u8 MR_ValidateMapInfo(struct megasas_instance *instance) { - struct fusion_context *fusion = instance->ctrl_context; - struct MR_FW_RAID_MAP_ALL *map = fusion->ld_map[(instance->map_id & 1)]; - struct LD_LOAD_BALANCE_INFO *lbInfo = fusion->load_balance_info; - PLD_SPAN_INFO ldSpanInfo = fusion->log_to_span; - struct MR_FW_RAID_MAP *pFwRaidMap = &map->raidMap; + struct fusion_context *fusion; + struct MR_DRV_RAID_MAP_ALL *drv_map; + struct MR_DRV_RAID_MAP *pDrvRaidMap; + struct LD_LOAD_BALANCE_INFO *lbInfo; + PLD_SPAN_INFO ldSpanInfo; struct MR_LD_RAID *raid; int ldCount, num_lds; u16 ld; + u32 expected_size; - if (le32_to_cpu(pFwRaidMap->totalSize) != - (sizeof(struct MR_FW_RAID_MAP) -sizeof(struct MR_LD_SPAN_MAP) + - (sizeof(struct MR_LD_SPAN_MAP) * le32_to_cpu(pFwRaidMap->ldCount)))) { - printk(KERN_ERR "megasas: map info structure size 0x%x is not matching with ld count\n", - (unsigned int)((sizeof(struct MR_FW_RAID_MAP) - - sizeof(struct MR_LD_SPAN_MAP)) + - (sizeof(struct MR_LD_SPAN_MAP) * - le32_to_cpu(pFwRaidMap->ldCount)))); - printk(KERN_ERR "megasas: span map %x, pFwRaidMap->totalSize " - ": %x\n", (unsigned int)sizeof(struct MR_LD_SPAN_MAP), - le32_to_cpu(pFwRaidMap->totalSize)); + MR_PopulateDrvRaidMap(instance); + + fusion = instance->ctrl_context; + drv_map = fusion->ld_drv_map[(instance->map_id & 1)]; + pDrvRaidMap = &drv_map->raidMap; + + lbInfo = fusion->load_balance_info; + ldSpanInfo = fusion->log_to_span; + + if (instance->supportmax256vd) + expected_size = sizeof(struct MR_FW_RAID_MAP_EXT); + else + expected_size = + (sizeof(struct MR_FW_RAID_MAP) - sizeof(struct MR_LD_SPAN_MAP) + + (sizeof(struct MR_LD_SPAN_MAP) * le32_to_cpu(pDrvRaidMap->ldCount))); + + if (le32_to_cpu(pDrvRaidMap->totalSize) != expected_size) { + dev_err(&instance->pdev->dev, "map info structure size 0x%x is not matching with ld count\n", + (unsigned int) expected_size); + dev_err(&instance->pdev->dev, "megasas: span map %x, pDrvRaidMap->totalSize : %x\n", + (unsigned int)sizeof(struct MR_LD_SPAN_MAP), + le32_to_cpu(pDrvRaidMap->totalSize)); return 0; } if (instance->UnevenSpanSupport) - mr_update_span_set(map, ldSpanInfo); + mr_update_span_set(drv_map, ldSpanInfo); - mr_update_load_balance_params(map, lbInfo); + mr_update_load_balance_params(drv_map, lbInfo); - num_lds = le32_to_cpu(map->raidMap.ldCount); + num_lds = le32_to_cpu(drv_map->raidMap.ldCount); /*Convert Raid capability values to CPU arch */ for (ldCount = 0; ldCount < num_lds; ldCount++) { - ld = MR_TargetIdToLdGet(ldCount, map); - raid = MR_LdRaidGet(ld, map); + ld = MR_TargetIdToLdGet(ldCount, drv_map); + raid = MR_LdRaidGet(ld, drv_map); le32_to_cpus((u32 *)&raid->capability); } @@ -204,7 +290,7 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance) } u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk, - struct MR_FW_RAID_MAP_ALL *map) + struct MR_DRV_RAID_MAP_ALL *map) { struct MR_SPAN_BLOCK_INFO *pSpanBlock = MR_LdSpanInfoGet(ld, map); struct MR_QUAD_ELEMENT *quad; @@ -246,7 +332,8 @@ u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk, * ldSpanInfo - ldSpanInfo per HBA instance */ #if SPAN_DEBUG -static int getSpanInfo(struct MR_FW_RAID_MAP_ALL *map, PLD_SPAN_INFO ldSpanInfo) +static int getSpanInfo(struct MR_DRV_RAID_MAP_ALL *map, + PLD_SPAN_INFO ldSpanInfo) { u8 span; @@ -257,9 +344,9 @@ static int getSpanInfo(struct MR_FW_RAID_MAP_ALL *map, PLD_SPAN_INFO ldSpanInfo) int ldCount; u16 ld; - for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) { + for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES_EXT; ldCount++) { ld = MR_TargetIdToLdGet(ldCount, map); - if (ld >= MAX_LOGICAL_DRIVES) + if (ld >= MAX_LOGICAL_DRIVES_EXT) continue; raid = MR_LdRaidGet(ld, map); dev_dbg(&instance->pdev->dev, "LD %x: span_depth=%x\n", @@ -339,7 +426,7 @@ static int getSpanInfo(struct MR_FW_RAID_MAP_ALL *map, PLD_SPAN_INFO ldSpanInfo) */ u32 mr_spanset_get_span_block(struct megasas_instance *instance, - u32 ld, u64 row, u64 *span_blk, struct MR_FW_RAID_MAP_ALL *map) + u32 ld, u64 row, u64 *span_blk, struct MR_DRV_RAID_MAP_ALL *map) { struct fusion_context *fusion = instance->ctrl_context; struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); @@ -402,7 +489,7 @@ u32 mr_spanset_get_span_block(struct megasas_instance *instance, */ static u64 get_row_from_strip(struct megasas_instance *instance, - u32 ld, u64 strip, struct MR_FW_RAID_MAP_ALL *map) + u32 ld, u64 strip, struct MR_DRV_RAID_MAP_ALL *map) { struct fusion_context *fusion = instance->ctrl_context; struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); @@ -471,7 +558,7 @@ static u64 get_row_from_strip(struct megasas_instance *instance, */ static u64 get_strip_from_row(struct megasas_instance *instance, - u32 ld, u64 row, struct MR_FW_RAID_MAP_ALL *map) + u32 ld, u64 row, struct MR_DRV_RAID_MAP_ALL *map) { struct fusion_context *fusion = instance->ctrl_context; struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); @@ -532,7 +619,7 @@ static u64 get_strip_from_row(struct megasas_instance *instance, */ static u32 get_arm_from_strip(struct megasas_instance *instance, - u32 ld, u64 strip, struct MR_FW_RAID_MAP_ALL *map) + u32 ld, u64 strip, struct MR_DRV_RAID_MAP_ALL *map) { struct fusion_context *fusion = instance->ctrl_context; struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); @@ -580,7 +667,7 @@ static u32 get_arm_from_strip(struct megasas_instance *instance, /* This Function will return Phys arm */ u8 get_arm(struct megasas_instance *instance, u32 ld, u8 span, u64 stripe, - struct MR_FW_RAID_MAP_ALL *map) + struct MR_DRV_RAID_MAP_ALL *map) { struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); /* Need to check correct default value */ @@ -624,7 +711,7 @@ u8 get_arm(struct megasas_instance *instance, u32 ld, u8 span, u64 stripe, static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld, u64 stripRow, u16 stripRef, struct IO_REQUEST_INFO *io_info, struct RAID_CONTEXT *pRAID_Context, - struct MR_FW_RAID_MAP_ALL *map) + struct MR_DRV_RAID_MAP_ALL *map) { struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); u32 pd, arRef; @@ -705,7 +792,7 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld, u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow, u16 stripRef, struct IO_REQUEST_INFO *io_info, struct RAID_CONTEXT *pRAID_Context, - struct MR_FW_RAID_MAP_ALL *map) + struct MR_DRV_RAID_MAP_ALL *map) { struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); u32 pd, arRef; @@ -794,7 +881,7 @@ u8 MR_BuildRaidContext(struct megasas_instance *instance, struct IO_REQUEST_INFO *io_info, struct RAID_CONTEXT *pRAID_Context, - struct MR_FW_RAID_MAP_ALL *map, u8 **raidLUN) + struct MR_DRV_RAID_MAP_ALL *map, u8 **raidLUN) { struct MR_LD_RAID *raid; u32 ld, stripSize, stripe_mask; @@ -1043,7 +1130,7 @@ MR_BuildRaidContext(struct megasas_instance *instance, * ldSpanInfo - ldSpanInfo per HBA instance * */ -void mr_update_span_set(struct MR_FW_RAID_MAP_ALL *map, +void mr_update_span_set(struct MR_DRV_RAID_MAP_ALL *map, PLD_SPAN_INFO ldSpanInfo) { u8 span, count; @@ -1056,9 +1143,9 @@ void mr_update_span_set(struct MR_FW_RAID_MAP_ALL *map, u16 ld; - for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) { + for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES_EXT; ldCount++) { ld = MR_TargetIdToLdGet(ldCount, map); - if (ld >= MAX_LOGICAL_DRIVES) + if (ld >= MAX_LOGICAL_DRIVES_EXT) continue; raid = MR_LdRaidGet(ld, map); for (element = 0; element < MAX_QUAD_DEPTH; element++) { @@ -1153,16 +1240,16 @@ void mr_update_span_set(struct MR_FW_RAID_MAP_ALL *map, } void -mr_update_load_balance_params(struct MR_FW_RAID_MAP_ALL *map, +mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *map, struct LD_LOAD_BALANCE_INFO *lbInfo) { int ldCount; u16 ld; struct MR_LD_RAID *raid; - for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) { + for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES_EXT; ldCount++) { ld = MR_TargetIdToLdGet(ldCount, map); - if (ld >= MAX_LOGICAL_DRIVES) { + if (ld >= MAX_LOGICAL_DRIVES_EXT) { lbInfo[ldCount].loadBalanceFlag = 0; continue; } diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 913e9fa8fc15..ed24a848df5b 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -652,6 +652,8 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) /* driver supports HA / Remote LUN over Fast Path interface */ init_frame->driver_operations.mfi_capabilities.support_fp_remote_lun = 1; + init_frame->driver_operations.mfi_capabilities.support_max_255lds + = 1; /* Convert capability to LE32 */ cpu_to_le32s((u32 *)&init_frame->driver_operations.mfi_capabilities); @@ -711,6 +713,13 @@ fail_get_cmd: * Issues an internal command (DCMD) to get the FW's controller PD * list structure. This information is mainly used to find out SYSTEM * supported by the FW. + * dcmd.mbox value setting for MR_DCMD_LD_MAP_GET_INFO + * dcmd.mbox.b[0] - number of LDs being sync'd + * dcmd.mbox.b[1] - 0 - complete command immediately. + * - 1 - pend till config change + * dcmd.mbox.b[2] - 0 - supports max 64 lds and uses legacy MR_FW_RAID_MAP + * - 1 - supports max MAX_LOGICAL_DRIVES_EXT lds and + * uses extended struct MR_FW_RAID_MAP_EXT */ static int megasas_get_ld_map_info(struct megasas_instance *instance) @@ -718,7 +727,7 @@ megasas_get_ld_map_info(struct megasas_instance *instance) int ret = 0; struct megasas_cmd *cmd; struct megasas_dcmd_frame *dcmd; - struct MR_FW_RAID_MAP_ALL *ci; + void *ci; dma_addr_t ci_h = 0; u32 size_map_info; struct fusion_context *fusion; @@ -739,10 +748,9 @@ megasas_get_ld_map_info(struct megasas_instance *instance) dcmd = &cmd->frame->dcmd; - size_map_info = sizeof(struct MR_FW_RAID_MAP) + - (sizeof(struct MR_LD_SPAN_MAP) *(MAX_LOGICAL_DRIVES - 1)); + size_map_info = fusion->current_map_sz; - ci = fusion->ld_map[(instance->map_id & 1)]; + ci = (void *) fusion->ld_map[(instance->map_id & 1)]; ci_h = fusion->ld_map_phys[(instance->map_id & 1)]; if (!ci) { @@ -751,9 +759,13 @@ megasas_get_ld_map_info(struct megasas_instance *instance) return -ENOMEM; } - memset(ci, 0, sizeof(*ci)); + memset(ci, 0, fusion->max_map_sz); memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); - +#if VD_EXT_DEBUG + dev_dbg(&instance->pdev->dev, + "%s sending MR_DCMD_LD_MAP_GET_INFO with size %d\n", + __func__, cpu_to_le32(size_map_info)); +#endif dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd_status = 0xFF; dcmd->sge_count = 1; @@ -809,7 +821,7 @@ megasas_sync_map_info(struct megasas_instance *instance) u32 size_sync_info, num_lds; struct fusion_context *fusion; struct MR_LD_TARGET_SYNC *ci = NULL; - struct MR_FW_RAID_MAP_ALL *map; + struct MR_DRV_RAID_MAP_ALL *map; struct MR_LD_RAID *raid; struct MR_LD_TARGET_SYNC *ld_sync; dma_addr_t ci_h = 0; @@ -830,7 +842,7 @@ megasas_sync_map_info(struct megasas_instance *instance) return 1; } - map = fusion->ld_map[instance->map_id & 1]; + map = fusion->ld_drv_map[instance->map_id & 1]; num_lds = le32_to_cpu(map->raidMap.ldCount); @@ -842,7 +854,7 @@ megasas_sync_map_info(struct megasas_instance *instance) ci = (struct MR_LD_TARGET_SYNC *) fusion->ld_map[(instance->map_id - 1) & 1]; - memset(ci, 0, sizeof(struct MR_FW_RAID_MAP_ALL)); + memset(ci, 0, fusion->max_map_sz); ci_h = fusion->ld_map_phys[(instance->map_id - 1) & 1]; @@ -854,8 +866,7 @@ megasas_sync_map_info(struct megasas_instance *instance) ld_sync->seqNum = raid->seqNum; } - size_map_info = sizeof(struct MR_FW_RAID_MAP) + - (sizeof(struct MR_LD_SPAN_MAP) *(MAX_LOGICAL_DRIVES - 1)); + size_map_info = fusion->current_map_sz; dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd_status = 0xFF; @@ -1018,17 +1029,75 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) goto fail_ioc_init; megasas_display_intel_branding(instance); + if (megasas_get_ctrl_info(instance, instance->ctrl_info)) { + dev_err(&instance->pdev->dev, + "Could not get controller info. Fail from %s %d\n", + __func__, __LINE__); + goto fail_ioc_init; + } + + instance->supportmax256vd = + instance->ctrl_info->adapterOperations3.supportMaxExtLDs; + /* Below is additional check to address future FW enhancement */ + if (instance->ctrl_info->max_lds > 64) + instance->supportmax256vd = 1; + instance->drv_supported_vd_count = MEGASAS_MAX_LD_CHANNELS + * MEGASAS_MAX_DEV_PER_CHANNEL; + instance->drv_supported_pd_count = MEGASAS_MAX_PD_CHANNELS + * MEGASAS_MAX_DEV_PER_CHANNEL; + if (instance->supportmax256vd) { + instance->fw_supported_vd_count = MAX_LOGICAL_DRIVES_EXT; + instance->fw_supported_pd_count = MAX_PHYSICAL_DEVICES; + } else { + instance->fw_supported_vd_count = MAX_LOGICAL_DRIVES; + instance->fw_supported_pd_count = MAX_PHYSICAL_DEVICES; + } + dev_info(&instance->pdev->dev, "Firmware supports %d VDs %d PDs\n" + "Driver supports %d VDs %d PDs\n", + instance->fw_supported_vd_count, + instance->fw_supported_pd_count, + instance->drv_supported_vd_count, + instance->drv_supported_pd_count); instance->flag_ieee = 1; + fusion->fast_path_io = 0; - fusion->map_sz = sizeof(struct MR_FW_RAID_MAP) + - (sizeof(struct MR_LD_SPAN_MAP) *(MAX_LOGICAL_DRIVES - 1)); + fusion->old_map_sz = + sizeof(struct MR_FW_RAID_MAP) + (sizeof(struct MR_LD_SPAN_MAP) * + (instance->fw_supported_vd_count - 1)); + fusion->new_map_sz = + sizeof(struct MR_FW_RAID_MAP_EXT); + fusion->drv_map_sz = + sizeof(struct MR_DRV_RAID_MAP) + (sizeof(struct MR_LD_SPAN_MAP) * + (instance->drv_supported_vd_count - 1)); + + fusion->drv_map_pages = get_order(fusion->drv_map_sz); + for (i = 0; i < 2; i++) { + fusion->ld_map[i] = NULL; + fusion->ld_drv_map[i] = (void *)__get_free_pages(GFP_KERNEL, + fusion->drv_map_pages); + if (!fusion->ld_drv_map[i]) { + dev_err(&instance->pdev->dev, "Could not allocate " + "memory for local map info for %d pages\n", + fusion->drv_map_pages); + if (i == 1) + free_pages((ulong)fusion->ld_drv_map[0], + fusion->drv_map_pages); + goto fail_ioc_init; + } + } + + fusion->max_map_sz = max(fusion->old_map_sz, fusion->new_map_sz); + + if (instance->supportmax256vd) + fusion->current_map_sz = fusion->new_map_sz; + else + fusion->current_map_sz = fusion->old_map_sz; - fusion->fast_path_io = 0; for (i = 0; i < 2; i++) { fusion->ld_map[i] = dma_alloc_coherent(&instance->pdev->dev, - fusion->map_sz, + fusion->max_map_sz, &fusion->ld_map_phys[i], GFP_KERNEL); if (!fusion->ld_map[i]) { @@ -1045,7 +1114,7 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) fail_map_info: if (i == 1) - dma_free_coherent(&instance->pdev->dev, fusion->map_sz, + dma_free_coherent(&instance->pdev->dev, fusion->max_map_sz, fusion->ld_map[0], fusion->ld_map_phys[0]); fail_ioc_init: megasas_free_cmds_fusion(instance); @@ -1232,7 +1301,7 @@ megasas_make_sgl_fusion(struct megasas_instance *instance, void megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len, struct IO_REQUEST_INFO *io_info, struct scsi_cmnd *scp, - struct MR_FW_RAID_MAP_ALL *local_map_ptr, u32 ref_tag) + struct MR_DRV_RAID_MAP_ALL *local_map_ptr, u32 ref_tag) { struct MR_LD_RAID *raid; u32 ld; @@ -1417,7 +1486,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; struct IO_REQUEST_INFO io_info; struct fusion_context *fusion; - struct MR_FW_RAID_MAP_ALL *local_map_ptr; + struct MR_DRV_RAID_MAP_ALL *local_map_ptr; u8 *raidLUN; device_id = MEGASAS_DEV_INDEX(instance, scp); @@ -1494,10 +1563,10 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) io_info.isRead = 1; - local_map_ptr = fusion->ld_map[(instance->map_id & 1)]; + local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)]; if ((MR_TargetIdToLdGet(device_id, local_map_ptr) >= - MAX_LOGICAL_DRIVES) || (!fusion->fast_path_io)) { + instance->fw_supported_vd_count) || (!fusion->fast_path_io)) { io_request->RaidContext.regLockFlags = 0; fp_possible = 0; } else { @@ -1587,7 +1656,7 @@ megasas_build_dcdb_fusion(struct megasas_instance *instance, u32 device_id; struct MPI2_RAID_SCSI_IO_REQUEST *io_request; u16 pd_index = 0; - struct MR_FW_RAID_MAP_ALL *local_map_ptr; + struct MR_DRV_RAID_MAP_ALL *local_map_ptr; struct fusion_context *fusion = instance->ctrl_context; u8 span, physArm; u16 devHandle; @@ -1599,7 +1668,7 @@ megasas_build_dcdb_fusion(struct megasas_instance *instance, device_id = MEGASAS_DEV_INDEX(instance, scmd); pd_index = (scmd->device->channel * MEGASAS_MAX_DEV_PER_CHANNEL) +scmd->device->id; - local_map_ptr = fusion->ld_map[(instance->map_id & 1)]; + local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)]; io_request->DataLength = cpu_to_le32(scsi_bufflen(scmd)); @@ -1647,7 +1716,8 @@ megasas_build_dcdb_fusion(struct megasas_instance *instance, goto NonFastPath; ld = MR_TargetIdToLdGet(device_id, local_map_ptr); - if ((ld >= MAX_LOGICAL_DRIVES) || (!fusion->fast_path_io)) + if ((ld >= instance->fw_supported_vd_count) || + (!fusion->fast_path_io)) goto NonFastPath; raid = MR_LdRaidGet(ld, local_map_ptr); @@ -2722,7 +2792,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout) /* Reset load balance info */ memset(fusion->load_balance_info, 0, sizeof(struct LD_LOAD_BALANCE_INFO) - *MAX_LOGICAL_DRIVES); + *MAX_LOGICAL_DRIVES_EXT); if (!megasas_get_map_info(instance)) megasas_sync_map_info(instance); diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h index d660c4df4153..065c27031c9c 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.h +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h @@ -479,10 +479,13 @@ struct MPI2_IOC_INIT_REQUEST { #define MAX_ROW_SIZE 32 #define MAX_RAIDMAP_ROW_SIZE (MAX_ROW_SIZE) #define MAX_LOGICAL_DRIVES 64 +#define MAX_LOGICAL_DRIVES_EXT 256 #define MAX_RAIDMAP_LOGICAL_DRIVES (MAX_LOGICAL_DRIVES) #define MAX_RAIDMAP_VIEWS (MAX_LOGICAL_DRIVES) #define MAX_ARRAYS 128 #define MAX_RAIDMAP_ARRAYS (MAX_ARRAYS) +#define MAX_ARRAYS_EXT 256 +#define MAX_API_ARRAYS_EXT (MAX_ARRAYS_EXT) #define MAX_PHYSICAL_DEVICES 256 #define MAX_RAIDMAP_PHYSICAL_DEVICES (MAX_PHYSICAL_DEVICES) #define MR_DCMD_LD_MAP_GET_INFO 0x0300e101 @@ -602,7 +605,6 @@ struct MR_FW_RAID_MAP { u32 maxArrays; } validationInfo; u32 version[5]; - u32 reserved1[5]; }; u32 ldCount; @@ -714,6 +716,81 @@ struct MR_FW_RAID_MAP_ALL { struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES - 1]; } __attribute__ ((packed)); +struct MR_DRV_RAID_MAP { + /* total size of this structure, including this field. + * This feild will be manupulated by driver for ext raid map, + * else pick the value from firmware raid map. + */ + u32 totalSize; + + union { + struct { + u32 maxLd; + u32 maxSpanDepth; + u32 maxRowSize; + u32 maxPdCount; + u32 maxArrays; + } validationInfo; + u32 version[5]; + }; + + /* timeout value used by driver in FP IOs*/ + u8 fpPdIoTimeoutSec; + u8 reserved2[7]; + + u16 ldCount; + u16 arCount; + u16 spanCount; + u16 reserve3; + + struct MR_DEV_HANDLE_INFO devHndlInfo[MAX_RAIDMAP_PHYSICAL_DEVICES]; + u8 ldTgtIdToLd[MAX_LOGICAL_DRIVES_EXT]; + struct MR_ARRAY_INFO arMapInfo[MAX_API_ARRAYS_EXT]; + struct MR_LD_SPAN_MAP ldSpanMap[1]; + +}; + +/* Driver raid map size is same as raid map ext + * MR_DRV_RAID_MAP_ALL is created to sync with old raid. + * And it is mainly for code re-use purpose. + */ +struct MR_DRV_RAID_MAP_ALL { + + struct MR_DRV_RAID_MAP raidMap; + struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES_EXT - 1]; +} __packed; + + + +struct MR_FW_RAID_MAP_EXT { + /* Not usred in new map */ + u32 reserved; + + union { + struct { + u32 maxLd; + u32 maxSpanDepth; + u32 maxRowSize; + u32 maxPdCount; + u32 maxArrays; + } validationInfo; + u32 version[5]; + }; + + u8 fpPdIoTimeoutSec; + u8 reserved2[7]; + + u16 ldCount; + u16 arCount; + u16 spanCount; + u16 reserve3; + + struct MR_DEV_HANDLE_INFO devHndlInfo[MAX_RAIDMAP_PHYSICAL_DEVICES]; + u8 ldTgtIdToLd[MAX_LOGICAL_DRIVES_EXT]; + struct MR_ARRAY_INFO arMapInfo[MAX_API_ARRAYS_EXT]; + struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES_EXT]; +}; + struct fusion_context { struct megasas_cmd_fusion **cmd_list; struct list_head cmd_pool; @@ -750,10 +827,18 @@ struct fusion_context { struct MR_FW_RAID_MAP_ALL *ld_map[2]; dma_addr_t ld_map_phys[2]; - u32 map_sz; + /*Non dma-able memory. Driver local copy.*/ + struct MR_DRV_RAID_MAP_ALL *ld_drv_map[2]; + + u32 max_map_sz; + u32 current_map_sz; + u32 old_map_sz; + u32 new_map_sz; + u32 drv_map_sz; + u32 drv_map_pages; u8 fast_path_io; - struct LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES]; - LD_SPAN_INFO log_to_span[MAX_LOGICAL_DRIVES]; + struct LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES_EXT]; + LD_SPAN_INFO log_to_span[MAX_LOGICAL_DRIVES_EXT]; }; union desc_value { @@ -764,4 +849,5 @@ union desc_value { } u; }; + #endif /* _MEGARAID_SAS_FUSION_H_ */ -- 2.39.5