scsi: megaraid_sas: Update LD map after populating drv_map driver map copy
authorShivasharan S <shivasharan.srikanteshwara@broadcom.com>
Fri, 5 Jan 2018 13:27:44 +0000 (05:27 -0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 11 Jan 2018 04:25:17 +0000 (23:25 -0500)
Issue – There may be some IO accessing incorrect raid map, but driver
has checks in IO path to handle those cases. It is always better to move
to new raid map only once raid map is populated and validated.  No
functional defect. Fix is provided as part of review.  Fix – Update
instance->map_id after driver has populated new driver raid map from
firmware raid map.

Signed-off-by: Sumit Saxena <sumit.saxena@broadcom.com>
Signed-off-by: Shivasharan S <shivasharan.srikanteshwara@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
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

index 0a66935ddf334239a67b7470859fdcfc0df50218..14b82c0b0461606b389604a489998a5306c20313 100644 (file)
@@ -230,7 +230,7 @@ enum MFI_CMD_OP {
 /*
  * Global functions
  */
-extern u8 MR_ValidateMapInfo(struct megasas_instance *instance);
+extern u8 MR_ValidateMapInfo(struct megasas_instance *instance, u64 map_id);
 
 
 /*
index 34d1fb75285ad5d6e4205112c3d5b07c13f8ca80..6da2766694cb9dca97f1feaa3adc9d04b90183c6 100644 (file)
@@ -3331,10 +3331,10 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
                        && (cmd->frame->dcmd.mbox.b[1] == 1)) {
                        fusion->fast_path_io = 0;
                        spin_lock_irqsave(instance->host->host_lock, flags);
+                       status = cmd->frame->hdr.cmd_status;
                        instance->map_update_cmd = NULL;
-                       if (cmd->frame->hdr.cmd_status != 0) {
-                               if (cmd->frame->hdr.cmd_status !=
-                                   MFI_STAT_NOT_FOUND)
+                       if (status != MFI_STAT_OK) {
+                               if (status != MFI_STAT_NOT_FOUND)
                                        dev_warn(&instance->pdev->dev, "map syncfailed, status = 0x%x\n",
                                               cmd->frame->hdr.cmd_status);
                                else {
@@ -3344,8 +3344,8 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
                                                flags);
                                        break;
                                }
-                       } else
-                               instance->map_id++;
+                       }
+
                        megasas_return_cmd(instance, cmd);
 
                        /*
@@ -3353,10 +3353,14 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
                         * Validate Map will set proper value.
                         * Meanwhile all IOs will go as LD IO.
                         */
-                       if (MR_ValidateMapInfo(instance))
+                       if (status == MFI_STAT_OK &&
+                           (MR_ValidateMapInfo(instance, (instance->map_id + 1)))) {
+                               instance->map_id++;
                                fusion->fast_path_io = 1;
-                       else
+                       } else {
                                fusion->fast_path_io = 0;
+                       }
+
                        megasas_sync_map_info(instance);
                        spin_unlock_irqrestore(instance->host->host_lock,
                                               flags);
@@ -5432,7 +5436,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
                ctrl_info->adapterOperations2.supportUnevenSpans;
        if (instance->UnevenSpanSupport) {
                struct fusion_context *fusion = instance->ctrl_context;
-               if (MR_ValidateMapInfo(instance))
+               if (MR_ValidateMapInfo(instance, instance->map_id))
                        fusion->fast_path_io = 1;
                else
                        fusion->fast_path_io = 0;
index f2ffde430ec18d19ad8f47099dbc68722cf39845..59ecbb3b53b52acd3a37a105dc181f7845239c53 100644 (file)
@@ -168,7 +168,7 @@ static struct MR_LD_SPAN *MR_LdSpanPtrGet(u32 ld, u32 span,
 /*
  * This function will Populate Driver Map using firmware raid map
  */
-static int MR_PopulateDrvRaidMap(struct megasas_instance *instance)
+static int MR_PopulateDrvRaidMap(struct megasas_instance *instance, u64 map_id)
 {
        struct fusion_context *fusion = instance->ctrl_context;
        struct MR_FW_RAID_MAP_ALL     *fw_map_old    = NULL;
@@ -181,7 +181,7 @@ static int MR_PopulateDrvRaidMap(struct megasas_instance *instance)
 
 
        struct MR_DRV_RAID_MAP_ALL *drv_map =
-                       fusion->ld_drv_map[(instance->map_id & 1)];
+                       fusion->ld_drv_map[(map_id & 1)];
        struct MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap;
        void *raid_map_data = NULL;
 
@@ -190,7 +190,7 @@ static int MR_PopulateDrvRaidMap(struct megasas_instance *instance)
               0xff, (sizeof(u16) * MAX_LOGICAL_DRIVES_DYN));
 
        if (instance->max_raid_mapsize) {
-               fw_map_dyn = fusion->ld_map[(instance->map_id & 1)];
+               fw_map_dyn = fusion->ld_map[(map_id & 1)];
                desc_table =
                (struct MR_RAID_MAP_DESC_TABLE *)((void *)fw_map_dyn + le32_to_cpu(fw_map_dyn->desc_table_offset));
                if (desc_table != fw_map_dyn->raid_map_desc_table)
@@ -255,7 +255,7 @@ static int MR_PopulateDrvRaidMap(struct megasas_instance *instance)
 
        } else if (instance->supportmax256vd) {
                fw_map_ext =
-                       (struct MR_FW_RAID_MAP_EXT *)fusion->ld_map[(instance->map_id & 1)];
+                       (struct MR_FW_RAID_MAP_EXT *)fusion->ld_map[(map_id & 1)];
                ld_count = (u16)le16_to_cpu(fw_map_ext->ldCount);
                if (ld_count > MAX_LOGICAL_DRIVES_EXT) {
                        dev_dbg(&instance->pdev->dev, "megaraid_sas: LD count exposed in RAID map in not valid\n");
@@ -282,7 +282,7 @@ static int MR_PopulateDrvRaidMap(struct megasas_instance *instance)
                        cpu_to_le32(sizeof(struct MR_FW_RAID_MAP_EXT));
        } else {
                fw_map_old = (struct MR_FW_RAID_MAP_ALL *)
-                       fusion->ld_map[(instance->map_id & 1)];
+                               fusion->ld_map[(map_id & 1)];
                pFwRaidMap = &fw_map_old->raidMap;
                ld_count = (u16)le32_to_cpu(pFwRaidMap->ldCount);
                if (ld_count > MAX_LOGICAL_DRIVES) {
@@ -313,7 +313,7 @@ static int MR_PopulateDrvRaidMap(struct megasas_instance *instance)
 /*
  * This function will validate Map info data provided by FW
  */
-u8 MR_ValidateMapInfo(struct megasas_instance *instance)
+u8 MR_ValidateMapInfo(struct megasas_instance *instance, u64 map_id)
 {
        struct fusion_context *fusion;
        struct MR_DRV_RAID_MAP_ALL *drv_map;
@@ -325,11 +325,11 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance)
        u16 ld;
        u32 expected_size;
 
-       if (MR_PopulateDrvRaidMap(instance))
+       if (MR_PopulateDrvRaidMap(instance, map_id))
                return 0;
 
        fusion = instance->ctrl_context;
-       drv_map = fusion->ld_drv_map[(instance->map_id & 1)];
+       drv_map = fusion->ld_drv_map[(map_id & 1)];
        pDrvRaidMap = &drv_map->raidMap;
 
        lbInfo = fusion->load_balance_info;
index ea3312205a0ee94d37e6b0727b8d38456120c369..74dadd052be4d0567e4820370be121b0558c5b0c 100644 (file)
@@ -1320,7 +1320,7 @@ megasas_get_map_info(struct megasas_instance *instance)
 
        fusion->fast_path_io = 0;
        if (!megasas_get_ld_map_info(instance)) {
-               if (MR_ValidateMapInfo(instance)) {
+               if (MR_ValidateMapInfo(instance, instance->map_id)) {
                        fusion->fast_path_io = 1;
                        return 0;
                }