On 09/06/2014 03:25 PM, sumit.sax...@avagotech.com wrote:
> 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 <sumit.sax...@avagotech.com>
> Signed-off-by: Kashyap Desai <kashyap.de...@avagotech.com>
> ---
>  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 |  95 ++++++++++++-
>  5 files changed, 502 insertions(+), 184 deletions(-)
>
> diff --git a/drivers/scsi/megaraid/megaraid_sas.h 
> b/drivers/scsi/megaraid/megaraid_sas.h
> index e0f03e2..5dedf09 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 5b58e39d..9dbbd9d 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 */
> @@ -5033,7 +5060,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
> @@ -5070,6 +5096,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)) {
> @@ -5630,14 +5657,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);
> @@ -5650,6 +5681,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);
> @@ -5760,8 +5793,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 081bfff..c2eaf6e 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 aaba2a7..65f617e 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);
> @@ -1234,7 +1303,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;
> @@ -1419,7 +1488,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);
> @@ -1496,10 +1565,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 {
> @@ -1589,7 +1658,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;
> @@ -1601,7 +1670,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));
>  
> @@ -1649,7 +1718,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);
> @@ -2724,7 +2794,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 d660c4d..0a6a430 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
> @@ -714,6 +717,83 @@ 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];
> +     u32             reserved1[5];

What is this 'reserved1' used for? In a union it does not
reserve  additional space, ther already is 'version' with the same size.

> +     };
> +
> +     /* 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];
> +     u32             reserved1[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 +830,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 +852,5 @@ union desc_value {
>       } u;
>  };
>  
> +
>  #endif /* _MEGARAID_SAS_FUSION_H_ */

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to