aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/megaraid
diff options
context:
space:
mode:
authorSumit.Saxena@avagotech.com <Sumit.Saxena@avagotech.com>2014-09-12 09:27:53 -0400
committerChristoph Hellwig <hch@lst.de>2014-09-16 12:14:26 -0400
commitd2552ebe885314d3c8352e35f2fae2a7478ac778 (patch)
treef2ebc6b01009a73b5cd80a833c1f783000b5c713 /drivers/scsi/megaraid
parentac95136ad40fc72c4842fee1ef002390ad96bfa0 (diff)
megaraid_sas : N-drive primary raid level 1 load balancing
Resending the patch. Addressed the review comments from Tomas Henzl. Current driver does fast path read load balancing between arm and mirror disk for two Drive Raid-1 configuration only. Now, Driver support fast path read load balancing for all (any number of disk) Raid-1 configuration. 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>
Diffstat (limited to 'drivers/scsi/megaraid')
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h8
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fp.c134
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.c14
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.h8
4 files changed, 96 insertions, 68 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 5dedf09fc46d..156d4b97d2bd 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -1188,7 +1188,8 @@ union megasas_sgl_frame {
1188typedef union _MFI_CAPABILITIES { 1188typedef union _MFI_CAPABILITIES {
1189 struct { 1189 struct {
1190#if defined(__BIG_ENDIAN_BITFIELD) 1190#if defined(__BIG_ENDIAN_BITFIELD)
1191 u32 reserved:28; 1191 u32 reserved:27;
1192 u32 support_ndrive_r1_lb:1;
1192 u32 support_max_255lds:1; 1193 u32 support_max_255lds:1;
1193 u32 reserved1:1; 1194 u32 reserved1:1;
1194 u32 support_additional_msix:1; 1195 u32 support_additional_msix:1;
@@ -1198,7 +1199,8 @@ typedef union _MFI_CAPABILITIES {
1198 u32 support_additional_msix:1; 1199 u32 support_additional_msix:1;
1199 u32 reserved1:1; 1200 u32 reserved1:1;
1200 u32 support_max_255lds:1; 1201 u32 support_max_255lds:1;
1201 u32 reserved:28; 1202 u32 support_ndrive_r1_lb:1;
1203 u32 reserved:27;
1202#endif 1204#endif
1203 } mfi_capabilities; 1205 } mfi_capabilities;
1204 u32 reg; 1206 u32 reg;
@@ -1914,6 +1916,8 @@ u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_DRV_RAID_MAP_ALL *map);
1914u16 MR_PdDevHandleGet(u32 pd, struct MR_DRV_RAID_MAP_ALL *map); 1916u16 MR_PdDevHandleGet(u32 pd, struct MR_DRV_RAID_MAP_ALL *map);
1915u16 MR_GetLDTgtId(u32 ld, struct MR_DRV_RAID_MAP_ALL *map); 1917u16 MR_GetLDTgtId(u32 ld, struct MR_DRV_RAID_MAP_ALL *map);
1916 1918
1919u16 get_updated_dev_handle(struct megasas_instance *instance,
1920 struct LD_LOAD_BALANCE_INFO *lbInfo, struct IO_REQUEST_INFO *in_info);
1917void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *map, 1921void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *map,
1918 struct LD_LOAD_BALANCE_INFO *lbInfo); 1922 struct LD_LOAD_BALANCE_INFO *lbInfo);
1919int megasas_get_ctrl_info(struct megasas_instance *instance, 1923int megasas_get_ctrl_info(struct megasas_instance *instance,
diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
index c2eaf6ef3d11..685e6f391fe4 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fp.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
@@ -55,6 +55,13 @@
55#include "megaraid_sas.h" 55#include "megaraid_sas.h"
56#include <asm/div64.h> 56#include <asm/div64.h>
57 57
58#define LB_PENDING_CMDS_DEFAULT 4
59static unsigned int lb_pending_cmds = LB_PENDING_CMDS_DEFAULT;
60module_param(lb_pending_cmds, int, S_IRUGO);
61MODULE_PARM_DESC(lb_pending_cmds, "Change raid-1 load balancing outstanding "
62 "threshold. Valid Values are 1-128. Default: 4");
63
64
58#define ABS_DIFF(a, b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a))) 65#define ABS_DIFF(a, b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a)))
59#define MR_LD_STATE_OPTIMAL 3 66#define MR_LD_STATE_OPTIMAL 3
60#define FALSE 0 67#define FALSE 0
@@ -769,6 +776,7 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld,
769 *pdBlock += stripRef + le64_to_cpu(MR_LdSpanPtrGet(ld, span, map)->startBlk); 776 *pdBlock += stripRef + le64_to_cpu(MR_LdSpanPtrGet(ld, span, map)->startBlk);
770 pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | 777 pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) |
771 physArm; 778 physArm;
779 io_info->span_arm = pRAID_Context->spanArm;
772 return retval; 780 return retval;
773} 781}
774 782
@@ -865,6 +873,7 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
865 *pdBlock += stripRef + le64_to_cpu(MR_LdSpanPtrGet(ld, span, map)->startBlk); 873 *pdBlock += stripRef + le64_to_cpu(MR_LdSpanPtrGet(ld, span, map)->startBlk);
866 pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | 874 pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) |
867 physArm; 875 physArm;
876 io_info->span_arm = pRAID_Context->spanArm;
868 return retval; 877 return retval;
869} 878}
870 879
@@ -1131,7 +1140,7 @@ MR_BuildRaidContext(struct megasas_instance *instance,
1131* 1140*
1132*/ 1141*/
1133void mr_update_span_set(struct MR_DRV_RAID_MAP_ALL *map, 1142void mr_update_span_set(struct MR_DRV_RAID_MAP_ALL *map,
1134 PLD_SPAN_INFO ldSpanInfo) 1143 PLD_SPAN_INFO ldSpanInfo)
1135{ 1144{
1136 u8 span, count; 1145 u8 span, count;
1137 u32 element, span_row_width; 1146 u32 element, span_row_width;
@@ -1239,90 +1248,105 @@ void mr_update_span_set(struct MR_DRV_RAID_MAP_ALL *map,
1239 1248
1240} 1249}
1241 1250
1242void 1251void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *drv_map,
1243mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *map, 1252 struct LD_LOAD_BALANCE_INFO *lbInfo)
1244 struct LD_LOAD_BALANCE_INFO *lbInfo)
1245{ 1253{
1246 int ldCount; 1254 int ldCount;
1247 u16 ld; 1255 u16 ld;
1248 struct MR_LD_RAID *raid; 1256 struct MR_LD_RAID *raid;
1249 1257
1258 if (lb_pending_cmds > 128 || lb_pending_cmds < 1)
1259 lb_pending_cmds = LB_PENDING_CMDS_DEFAULT;
1260
1250 for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES_EXT; ldCount++) { 1261 for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES_EXT; ldCount++) {
1251 ld = MR_TargetIdToLdGet(ldCount, map); 1262 ld = MR_TargetIdToLdGet(ldCount, drv_map);
1252 if (ld >= MAX_LOGICAL_DRIVES_EXT) { 1263 if (ld >= MAX_LOGICAL_DRIVES_EXT) {
1253 lbInfo[ldCount].loadBalanceFlag = 0; 1264 lbInfo[ldCount].loadBalanceFlag = 0;
1254 continue; 1265 continue;
1255 } 1266 }
1256 1267
1257 raid = MR_LdRaidGet(ld, map); 1268 raid = MR_LdRaidGet(ld, drv_map);
1258 1269 if ((raid->level != 1) ||
1259 /* Two drive Optimal RAID 1 */ 1270 (raid->ldState != MR_LD_STATE_OPTIMAL)) {
1260 if ((raid->level == 1) && (raid->rowSize == 2) &&
1261 (raid->spanDepth == 1) && raid->ldState ==
1262 MR_LD_STATE_OPTIMAL) {
1263 u32 pd, arRef;
1264
1265 lbInfo[ldCount].loadBalanceFlag = 1;
1266
1267 /* Get the array on which this span is present */
1268 arRef = MR_LdSpanArrayGet(ld, 0, map);
1269
1270 /* Get the Pd */
1271 pd = MR_ArPdGet(arRef, 0, map);
1272 /* Get dev handle from Pd */
1273 lbInfo[ldCount].raid1DevHandle[0] =
1274 MR_PdDevHandleGet(pd, map);
1275 /* Get the Pd */
1276 pd = MR_ArPdGet(arRef, 1, map);
1277
1278 /* Get the dev handle from Pd */
1279 lbInfo[ldCount].raid1DevHandle[1] =
1280 MR_PdDevHandleGet(pd, map);
1281 } else
1282 lbInfo[ldCount].loadBalanceFlag = 0; 1271 lbInfo[ldCount].loadBalanceFlag = 0;
1272 continue;
1273 }
1274 lbInfo[ldCount].loadBalanceFlag = 1;
1283 } 1275 }
1284} 1276}
1285 1277
1286u8 megasas_get_best_arm(struct LD_LOAD_BALANCE_INFO *lbInfo, u8 arm, u64 block, 1278u8 megasas_get_best_arm_pd(struct megasas_instance *instance,
1287 u32 count) 1279 struct LD_LOAD_BALANCE_INFO *lbInfo, struct IO_REQUEST_INFO *io_info)
1288{ 1280{
1289 u16 pend0, pend1; 1281 struct fusion_context *fusion;
1282 struct MR_LD_RAID *raid;
1283 struct MR_DRV_RAID_MAP_ALL *drv_map;
1284 u16 pend0, pend1, ld;
1290 u64 diff0, diff1; 1285 u64 diff0, diff1;
1291 u8 bestArm; 1286 u8 bestArm, pd0, pd1, span, arm;
1287 u32 arRef, span_row_size;
1288
1289 u64 block = io_info->ldStartBlock;
1290 u32 count = io_info->numBlocks;
1291
1292 span = ((io_info->span_arm & RAID_CTX_SPANARM_SPAN_MASK)
1293 >> RAID_CTX_SPANARM_SPAN_SHIFT);
1294 arm = (io_info->span_arm & RAID_CTX_SPANARM_ARM_MASK);
1295
1296
1297 fusion = instance->ctrl_context;
1298 drv_map = fusion->ld_drv_map[(instance->map_id & 1)];
1299 ld = MR_TargetIdToLdGet(io_info->ldTgtId, drv_map);
1300 raid = MR_LdRaidGet(ld, drv_map);
1301 span_row_size = instance->UnevenSpanSupport ?
1302 SPAN_ROW_SIZE(drv_map, ld, span) : raid->rowSize;
1303
1304 arRef = MR_LdSpanArrayGet(ld, span, drv_map);
1305 pd0 = MR_ArPdGet(arRef, arm, drv_map);
1306 pd1 = MR_ArPdGet(arRef, (arm + 1) >= span_row_size ?
1307 (arm + 1 - span_row_size) : arm + 1, drv_map);
1292 1308
1293 /* get the pending cmds for the data and mirror arms */ 1309 /* get the pending cmds for the data and mirror arms */
1294 pend0 = atomic_read(&lbInfo->scsi_pending_cmds[0]); 1310 pend0 = atomic_read(&lbInfo->scsi_pending_cmds[pd0]);
1295 pend1 = atomic_read(&lbInfo->scsi_pending_cmds[1]); 1311 pend1 = atomic_read(&lbInfo->scsi_pending_cmds[pd1]);
1296 1312
1297 /* Determine the disk whose head is nearer to the req. block */ 1313 /* Determine the disk whose head is nearer to the req. block */
1298 diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[0]); 1314 diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[pd0]);
1299 diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[1]); 1315 diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[pd1]);
1300 bestArm = (diff0 <= diff1 ? 0 : 1); 1316 bestArm = (diff0 <= diff1 ? arm : arm ^ 1);
1301 1317
1302 /*Make balance count from 16 to 4 to keep driver in sync with Firmware*/ 1318 if ((bestArm == arm && pend0 > pend1 + lb_pending_cmds) ||
1303 if ((bestArm == arm && pend0 > pend1 + 4) || 1319 (bestArm != arm && pend1 > pend0 + lb_pending_cmds))
1304 (bestArm != arm && pend1 > pend0 + 4))
1305 bestArm ^= 1; 1320 bestArm ^= 1;
1306 1321
1307 /* Update the last accessed block on the correct pd */ 1322 /* Update the last accessed block on the correct pd */
1308 lbInfo->last_accessed_block[bestArm] = block + count - 1; 1323 io_info->pd_after_lb = (bestArm == arm) ? pd0 : pd1;
1309 1324 lbInfo->last_accessed_block[io_info->pd_after_lb] = block + count - 1;
1310 return bestArm; 1325 io_info->span_arm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | bestArm;
1326#if SPAN_DEBUG
1327 if (arm != bestArm)
1328 dev_dbg(&instance->pdev->dev, "LSI Debug R1 Load balance "
1329 "occur - span 0x%x arm 0x%x bestArm 0x%x "
1330 "io_info->span_arm 0x%x\n",
1331 span, arm, bestArm, io_info->span_arm);
1332#endif
1333 return io_info->pd_after_lb;
1311} 1334}
1312 1335
1313u16 get_updated_dev_handle(struct LD_LOAD_BALANCE_INFO *lbInfo, 1336u16 get_updated_dev_handle(struct megasas_instance *instance,
1314 struct IO_REQUEST_INFO *io_info) 1337 struct LD_LOAD_BALANCE_INFO *lbInfo, struct IO_REQUEST_INFO *io_info)
1315{ 1338{
1316 u8 arm, old_arm; 1339 u8 arm_pd;
1317 u16 devHandle; 1340 u16 devHandle;
1341 struct fusion_context *fusion;
1342 struct MR_DRV_RAID_MAP_ALL *drv_map;
1318 1343
1319 old_arm = lbInfo->raid1DevHandle[0] == io_info->devHandle ? 0 : 1; 1344 fusion = instance->ctrl_context;
1320 1345 drv_map = fusion->ld_drv_map[(instance->map_id & 1)];
1321 /* get best new arm */
1322 arm = megasas_get_best_arm(lbInfo, old_arm, io_info->ldStartBlock,
1323 io_info->numBlocks);
1324 devHandle = lbInfo->raid1DevHandle[arm];
1325 atomic_inc(&lbInfo->scsi_pending_cmds[arm]);
1326 1346
1347 /* get best new arm (PD ID) */
1348 arm_pd = megasas_get_best_arm_pd(instance, lbInfo, io_info);
1349 devHandle = MR_PdDevHandleGet(arm_pd, drv_map);
1350 atomic_inc(&lbInfo->scsi_pending_cmds[arm_pd]);
1327 return devHandle; 1351 return devHandle;
1328} 1352}
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index d35ac34ea624..54c720ccb3e6 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -76,8 +76,6 @@ megasas_issue_polled(struct megasas_instance *instance,
76void 76void
77megasas_check_and_restore_queue_depth(struct megasas_instance *instance); 77megasas_check_and_restore_queue_depth(struct megasas_instance *instance);
78 78
79u16 get_updated_dev_handle(struct LD_LOAD_BALANCE_INFO *lbInfo,
80 struct IO_REQUEST_INFO *in_info);
81int megasas_transition_to_ready(struct megasas_instance *instance, int ocr); 79int megasas_transition_to_ready(struct megasas_instance *instance, int ocr);
82void megaraid_sas_kill_hba(struct megasas_instance *instance); 80void megaraid_sas_kill_hba(struct megasas_instance *instance);
83 81
@@ -654,6 +652,8 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
654 = 1; 652 = 1;
655 init_frame->driver_operations.mfi_capabilities.support_max_255lds 653 init_frame->driver_operations.mfi_capabilities.support_max_255lds
656 = 1; 654 = 1;
655 init_frame->driver_operations.mfi_capabilities.support_ndrive_r1_lb
656 = 1;
657 /* Convert capability to LE32 */ 657 /* Convert capability to LE32 */
658 cpu_to_le32s((u32 *)&init_frame->driver_operations.mfi_capabilities); 658 cpu_to_le32s((u32 *)&init_frame->driver_operations.mfi_capabilities);
659 659
@@ -1606,10 +1606,11 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
1606 if ((fusion->load_balance_info[device_id].loadBalanceFlag) && 1606 if ((fusion->load_balance_info[device_id].loadBalanceFlag) &&
1607 (io_info.isRead)) { 1607 (io_info.isRead)) {
1608 io_info.devHandle = 1608 io_info.devHandle =
1609 get_updated_dev_handle( 1609 get_updated_dev_handle(instance,
1610 &fusion->load_balance_info[device_id], 1610 &fusion->load_balance_info[device_id],
1611 &io_info); 1611 &io_info);
1612 scp->SCp.Status |= MEGASAS_LOAD_BALANCE_FLAG; 1612 scp->SCp.Status |= MEGASAS_LOAD_BALANCE_FLAG;
1613 cmd->pd_r1_lb = io_info.pd_after_lb;
1613 } else 1614 } else
1614 scp->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG; 1615 scp->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG;
1615 cmd->request_desc->SCSIIO.DevHandle = io_info.devHandle; 1616 cmd->request_desc->SCSIIO.DevHandle = io_info.devHandle;
@@ -1942,7 +1943,7 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex)
1942 struct megasas_cmd *cmd_mfi; 1943 struct megasas_cmd *cmd_mfi;
1943 struct megasas_cmd_fusion *cmd_fusion; 1944 struct megasas_cmd_fusion *cmd_fusion;
1944 u16 smid, num_completed; 1945 u16 smid, num_completed;
1945 u8 reply_descript_type, arm; 1946 u8 reply_descript_type;
1946 u32 status, extStatus, device_id; 1947 u32 status, extStatus, device_id;
1947 union desc_value d_val; 1948 union desc_value d_val;
1948 struct LD_LOAD_BALANCE_INFO *lbinfo; 1949 struct LD_LOAD_BALANCE_INFO *lbinfo;
@@ -1993,10 +1994,7 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex)
1993 lbinfo = &fusion->load_balance_info[device_id]; 1994 lbinfo = &fusion->load_balance_info[device_id];
1994 if (cmd_fusion->scmd->SCp.Status & 1995 if (cmd_fusion->scmd->SCp.Status &
1995 MEGASAS_LOAD_BALANCE_FLAG) { 1996 MEGASAS_LOAD_BALANCE_FLAG) {
1996 arm = lbinfo->raid1DevHandle[0] == 1997 atomic_dec(&lbinfo->scsi_pending_cmds[cmd_fusion->pd_r1_lb]);
1997 cmd_fusion->io_request->DevHandle ? 0 :
1998 1;
1999 atomic_dec(&lbinfo->scsi_pending_cmds[arm]);
2000 cmd_fusion->scmd->SCp.Status &= 1998 cmd_fusion->scmd->SCp.Status &=
2001 ~MEGASAS_LOAD_BALANCE_FLAG; 1999 ~MEGASAS_LOAD_BALANCE_FLAG;
2002 } 2000 }
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h
index 065c27031c9c..75844260fae9 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.h
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h
@@ -630,6 +630,8 @@ struct IO_REQUEST_INFO {
630 u8 start_span; 630 u8 start_span;
631 u8 reserved; 631 u8 reserved;
632 u64 start_row; 632 u64 start_row;
633 u8 span_arm; /* span[7:5], arm[4:0] */
634 u8 pd_after_lb;
633}; 635};
634 636
635struct MR_LD_TARGET_SYNC { 637struct MR_LD_TARGET_SYNC {
@@ -681,14 +683,14 @@ struct megasas_cmd_fusion {
681 u32 sync_cmd_idx; 683 u32 sync_cmd_idx;
682 u32 index; 684 u32 index;
683 u8 flags; 685 u8 flags;
686 u8 pd_r1_lb;
684}; 687};
685 688
686struct LD_LOAD_BALANCE_INFO { 689struct LD_LOAD_BALANCE_INFO {
687 u8 loadBalanceFlag; 690 u8 loadBalanceFlag;
688 u8 reserved1; 691 u8 reserved1;
689 u16 raid1DevHandle[2]; 692 atomic_t scsi_pending_cmds[MAX_PHYSICAL_DEVICES];
690 atomic_t scsi_pending_cmds[2]; 693 u64 last_accessed_block[MAX_PHYSICAL_DEVICES];
691 u64 last_accessed_block[2];
692}; 694};
693 695
694/* SPAN_SET is info caclulated from span info from Raid map per LD */ 696/* SPAN_SET is info caclulated from span info from Raid map per LD */