]> git.karo-electronics.de Git - linux-beck.git/commitdiff
megaraid_sas : Extended VD support
authorSumit.Saxena@avagotech.com <Sumit.Saxena@avagotech.com>
Fri, 12 Sep 2014 13:27:33 +0000 (18:57 +0530)
committerChristoph Hellwig <hch@lst.de>
Tue, 16 Sep 2014 16:14:24 +0000 (09:14 -0700)
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 <sumit.saxena@avagotech.com>
Signed-off-by: Kashyap Desai <kashyap.desai@avagotech.com>
Reviewed-by: Tomas Henzl <thenzl@redhat.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
drivers/scsi/megaraid/megaraid_sas.h
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/megaraid/megaraid_sas_fp.c
drivers/scsi/megaraid/megaraid_sas_fusion.c
drivers/scsi/megaraid/megaraid_sas_fusion.h

index e0f03e2f6ddf63fc076513df3031ba0f1ae2131c..5dedf09fc46d063065c33c24533e7894abce81a3 100644 (file)
@@ -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 */
index ff96e3c58fbf31e4e7f66f3a32abf9dfb5a1742c..c7ddb129349dd1953521dfbd5c4e7d7944b9ecd3 100644 (file)
@@ -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;
 }
index 081bfff12d004bf338dba0c1a62491043d49cd7b..c2eaf6ef3d1157d159ce757327a513ea4cf705e1 100644 (file)
 #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;
                }
index 913e9fa8fc15910adbd006720b6da09d2f021106..ed24a848df5be3ec39d3e0d678a1d5edefa41477 100644 (file)
@@ -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);
index d660c4df4153e29ef831f087b448fd6ecd506a9f..065c27031c9c3326a5e41642848cf2dcf02f2295 100644 (file)
@@ -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_ */