aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authoradam radford <aradford@gmail.com>2013-09-06 18:27:14 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-09-06 18:54:55 -0400
commit21c9e160a51383d4cb0b882398534b0c95c0cc3b (patch)
treef8d0992cb054f39306ea565df149708dd612ac2e /drivers/scsi
parent9807b4d94911be4e4efb9a08481b24292a9edf8a (diff)
[SCSI] megaraid_sas: Add High Availability clustering support using shared Logical Disks
Signed-off-by: Adam Radford <aradford@gmail.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h32
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c106
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fp.c11
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.c77
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.h7
5 files changed, 204 insertions, 29 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 04a42a505852..a6d80f70e2fc 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -170,6 +170,7 @@
170 170
171#define MR_DCMD_CTRL_GET_INFO 0x01010000 171#define MR_DCMD_CTRL_GET_INFO 0x01010000
172#define MR_DCMD_LD_GET_LIST 0x03010000 172#define MR_DCMD_LD_GET_LIST 0x03010000
173#define MR_DCMD_LD_LIST_QUERY 0x03010100
173 174
174#define MR_DCMD_CTRL_CACHE_FLUSH 0x01101000 175#define MR_DCMD_CTRL_CACHE_FLUSH 0x01101000
175#define MR_FLUSH_CTRL_CACHE 0x01 176#define MR_FLUSH_CTRL_CACHE 0x01
@@ -345,6 +346,15 @@ enum MR_PD_QUERY_TYPE {
345 MR_PD_QUERY_TYPE_EXPOSED_TO_HOST = 5, 346 MR_PD_QUERY_TYPE_EXPOSED_TO_HOST = 5,
346}; 347};
347 348
349enum MR_LD_QUERY_TYPE {
350 MR_LD_QUERY_TYPE_ALL = 0,
351 MR_LD_QUERY_TYPE_EXPOSED_TO_HOST = 1,
352 MR_LD_QUERY_TYPE_USED_TGT_IDS = 2,
353 MR_LD_QUERY_TYPE_CLUSTER_ACCESS = 3,
354 MR_LD_QUERY_TYPE_CLUSTER_LOCALE = 4,
355};
356
357
348#define MR_EVT_CFG_CLEARED 0x0004 358#define MR_EVT_CFG_CLEARED 0x0004
349#define MR_EVT_LD_STATE_CHANGE 0x0051 359#define MR_EVT_LD_STATE_CHANGE 0x0051
350#define MR_EVT_PD_INSERTED 0x005b 360#define MR_EVT_PD_INSERTED 0x005b
@@ -435,6 +445,14 @@ struct MR_LD_LIST {
435 } ldList[MAX_LOGICAL_DRIVES]; 445 } ldList[MAX_LOGICAL_DRIVES];
436} __packed; 446} __packed;
437 447
448struct MR_LD_TARGETID_LIST {
449 u32 size;
450 u32 count;
451 u8 pad[3];
452 u8 targetId[MAX_LOGICAL_DRIVES];
453};
454
455
438/* 456/*
439 * SAS controller properties 457 * SAS controller properties
440 */ 458 */
@@ -863,7 +881,7 @@ struct megasas_ctrl_info {
863 * =============================== 881 * ===============================
864 */ 882 */
865#define MEGASAS_MAX_PD_CHANNELS 2 883#define MEGASAS_MAX_PD_CHANNELS 2
866#define MEGASAS_MAX_LD_CHANNELS 2 884#define MEGASAS_MAX_LD_CHANNELS 1
867#define MEGASAS_MAX_CHANNELS (MEGASAS_MAX_PD_CHANNELS + \ 885#define MEGASAS_MAX_CHANNELS (MEGASAS_MAX_PD_CHANNELS + \
868 MEGASAS_MAX_LD_CHANNELS) 886 MEGASAS_MAX_LD_CHANNELS)
869#define MEGASAS_MAX_DEV_PER_CHANNEL 128 887#define MEGASAS_MAX_DEV_PER_CHANNEL 128
@@ -1656,4 +1674,16 @@ struct megasas_mgmt_info {
1656 int max_index; 1674 int max_index;
1657}; 1675};
1658 1676
1677u8
1678MR_BuildRaidContext(struct megasas_instance *instance,
1679 struct IO_REQUEST_INFO *io_info,
1680 struct RAID_CONTEXT *pRAID_Context,
1681 struct MR_FW_RAID_MAP_ALL *map, u8 **raidLUN);
1682u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map);
1683struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_FW_RAID_MAP_ALL *map);
1684u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_FW_RAID_MAP_ALL *map);
1685u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_FW_RAID_MAP_ALL *map);
1686u16 MR_PdDevHandleGet(u32 pd, struct MR_FW_RAID_MAP_ALL *map);
1687u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map);
1688
1659#endif /*LSI_MEGARAID_SAS_H */ 1689#endif /*LSI_MEGARAID_SAS_H */
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index 1f0ca68409d4..9f7c4a169222 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -92,6 +92,8 @@ MODULE_DESCRIPTION("LSI MegaRAID SAS Driver");
92 92
93int megasas_transition_to_ready(struct megasas_instance *instance, int ocr); 93int megasas_transition_to_ready(struct megasas_instance *instance, int ocr);
94static int megasas_get_pd_list(struct megasas_instance *instance); 94static int megasas_get_pd_list(struct megasas_instance *instance);
95static int megasas_ld_list_query(struct megasas_instance *instance,
96 u8 query_type);
95static int megasas_issue_init_mfi(struct megasas_instance *instance); 97static int megasas_issue_init_mfi(struct megasas_instance *instance);
96static int megasas_register_aen(struct megasas_instance *instance, 98static int megasas_register_aen(struct megasas_instance *instance,
97 u32 seq_num, u32 class_locale_word); 99 u32 seq_num, u32 class_locale_word);
@@ -3271,6 +3273,84 @@ megasas_get_ld_list(struct megasas_instance *instance)
3271} 3273}
3272 3274
3273/** 3275/**
3276 * megasas_ld_list_query - Returns FW's ld_list structure
3277 * @instance: Adapter soft state
3278 * @ld_list: ld_list structure
3279 *
3280 * Issues an internal command (DCMD) to get the FW's controller PD
3281 * list structure. This information is mainly used to find out SYSTEM
3282 * supported by the FW.
3283 */
3284static int
3285megasas_ld_list_query(struct megasas_instance *instance, u8 query_type)
3286{
3287 int ret = 0, ld_index = 0, ids = 0;
3288 struct megasas_cmd *cmd;
3289 struct megasas_dcmd_frame *dcmd;
3290 struct MR_LD_TARGETID_LIST *ci;
3291 dma_addr_t ci_h = 0;
3292
3293 cmd = megasas_get_cmd(instance);
3294
3295 if (!cmd) {
3296 printk(KERN_WARNING
3297 "megasas:(megasas_ld_list_query): Failed to get cmd\n");
3298 return -ENOMEM;
3299 }
3300
3301 dcmd = &cmd->frame->dcmd;
3302
3303 ci = pci_alloc_consistent(instance->pdev,
3304 sizeof(struct MR_LD_TARGETID_LIST), &ci_h);
3305
3306 if (!ci) {
3307 printk(KERN_WARNING
3308 "megasas: Failed to alloc mem for ld_list_query\n");
3309 megasas_return_cmd(instance, cmd);
3310 return -ENOMEM;
3311 }
3312
3313 memset(ci, 0, sizeof(*ci));
3314 memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
3315
3316 dcmd->mbox.b[0] = query_type;
3317
3318 dcmd->cmd = MFI_CMD_DCMD;
3319 dcmd->cmd_status = 0xFF;
3320 dcmd->sge_count = 1;
3321 dcmd->flags = MFI_FRAME_DIR_READ;
3322 dcmd->timeout = 0;
3323 dcmd->data_xfer_len = sizeof(struct MR_LD_TARGETID_LIST);
3324 dcmd->opcode = MR_DCMD_LD_LIST_QUERY;
3325 dcmd->sgl.sge32[0].phys_addr = ci_h;
3326 dcmd->sgl.sge32[0].length = sizeof(struct MR_LD_TARGETID_LIST);
3327 dcmd->pad_0 = 0;
3328
3329 if (!megasas_issue_polled(instance, cmd) && !dcmd->cmd_status) {
3330 ret = 0;
3331 } else {
3332 /* On failure, call older LD list DCMD */
3333 ret = 1;
3334 }
3335
3336 if ((ret == 0) && (ci->count <= (MAX_LOGICAL_DRIVES))) {
3337 memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
3338 for (ld_index = 0; ld_index < ci->count; ld_index++) {
3339 ids = ci->targetId[ld_index];
3340 instance->ld_ids[ids] = ci->targetId[ld_index];
3341 }
3342
3343 }
3344
3345 pci_free_consistent(instance->pdev, sizeof(struct MR_LD_TARGETID_LIST),
3346 ci, ci_h);
3347
3348 megasas_return_cmd(instance, cmd);
3349
3350 return ret;
3351}
3352
3353/**
3274 * megasas_get_controller_info - Returns FW's controller structure 3354 * megasas_get_controller_info - Returns FW's controller structure
3275 * @instance: Adapter soft state 3355 * @instance: Adapter soft state
3276 * @ctrl_info: Controller information structure 3356 * @ctrl_info: Controller information structure
@@ -3648,7 +3728,9 @@ static int megasas_init_fw(struct megasas_instance *instance)
3648 megasas_get_pd_list(instance); 3728 megasas_get_pd_list(instance);
3649 3729
3650 memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); 3730 memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
3651 megasas_get_ld_list(instance); 3731 if (megasas_ld_list_query(instance,
3732 MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
3733 megasas_get_ld_list(instance);
3652 3734
3653 ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL); 3735 ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL);
3654 3736
@@ -5389,7 +5471,9 @@ megasas_aen_polling(struct work_struct *work)
5389 case MR_EVT_LD_OFFLINE: 5471 case MR_EVT_LD_OFFLINE:
5390 case MR_EVT_CFG_CLEARED: 5472 case MR_EVT_CFG_CLEARED:
5391 case MR_EVT_LD_DELETED: 5473 case MR_EVT_LD_DELETED:
5392 megasas_get_ld_list(instance); 5474 if (megasas_ld_list_query(instance,
5475 MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
5476 megasas_get_ld_list(instance);
5393 for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { 5477 for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
5394 for (j = 0; 5478 for (j = 0;
5395 j < MEGASAS_MAX_DEV_PER_CHANNEL; 5479 j < MEGASAS_MAX_DEV_PER_CHANNEL;
@@ -5399,7 +5483,7 @@ megasas_aen_polling(struct work_struct *work)
5399 (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; 5483 (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
5400 5484
5401 sdev1 = scsi_device_lookup(host, 5485 sdev1 = scsi_device_lookup(host,
5402 i + MEGASAS_MAX_LD_CHANNELS, 5486 MEGASAS_MAX_PD_CHANNELS + i,
5403 j, 5487 j,
5404 0); 5488 0);
5405 5489
@@ -5418,7 +5502,9 @@ megasas_aen_polling(struct work_struct *work)
5418 doscan = 0; 5502 doscan = 0;
5419 break; 5503 break;
5420 case MR_EVT_LD_CREATED: 5504 case MR_EVT_LD_CREATED:
5421 megasas_get_ld_list(instance); 5505 if (megasas_ld_list_query(instance,
5506 MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
5507 megasas_get_ld_list(instance);
5422 for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { 5508 for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
5423 for (j = 0; 5509 for (j = 0;
5424 j < MEGASAS_MAX_DEV_PER_CHANNEL; 5510 j < MEGASAS_MAX_DEV_PER_CHANNEL;
@@ -5427,14 +5513,14 @@ megasas_aen_polling(struct work_struct *work)
5427 (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; 5513 (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
5428 5514
5429 sdev1 = scsi_device_lookup(host, 5515 sdev1 = scsi_device_lookup(host,
5430 i+MEGASAS_MAX_LD_CHANNELS, 5516 MEGASAS_MAX_PD_CHANNELS + i,
5431 j, 0); 5517 j, 0);
5432 5518
5433 if (instance->ld_ids[ld_index] != 5519 if (instance->ld_ids[ld_index] !=
5434 0xff) { 5520 0xff) {
5435 if (!sdev1) { 5521 if (!sdev1) {
5436 scsi_add_device(host, 5522 scsi_add_device(host,
5437 i + 2, 5523 MEGASAS_MAX_PD_CHANNELS + i,
5438 j, 0); 5524 j, 0);
5439 } 5525 }
5440 } 5526 }
@@ -5483,18 +5569,20 @@ megasas_aen_polling(struct work_struct *work)
5483 } 5569 }
5484 } 5570 }
5485 5571
5486 megasas_get_ld_list(instance); 5572 if (megasas_ld_list_query(instance,
5573 MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
5574 megasas_get_ld_list(instance);
5487 for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { 5575 for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
5488 for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) { 5576 for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
5489 ld_index = 5577 ld_index =
5490 (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; 5578 (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
5491 5579
5492 sdev1 = scsi_device_lookup(host, 5580 sdev1 = scsi_device_lookup(host,
5493 i+MEGASAS_MAX_LD_CHANNELS, j, 0); 5581 MEGASAS_MAX_PD_CHANNELS + i, j, 0);
5494 if (instance->ld_ids[ld_index] != 0xff) { 5582 if (instance->ld_ids[ld_index] != 0xff) {
5495 if (!sdev1) { 5583 if (!sdev1) {
5496 scsi_add_device(host, 5584 scsi_add_device(host,
5497 i+2, 5585 MEGASAS_MAX_PD_CHANNELS + i,
5498 j, 0); 5586 j, 0);
5499 } else { 5587 } else {
5500 scsi_device_put(sdev1); 5588 scsi_device_put(sdev1);
diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
index 4f401f753f8e..75e811810d0b 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fp.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
@@ -126,17 +126,17 @@ static u8 MR_LdDataArmGet(u32 ld, u32 armIdx, struct MR_FW_RAID_MAP_ALL *map)
126 return map->raidMap.ldSpanMap[ld].dataArmMap[armIdx]; 126 return map->raidMap.ldSpanMap[ld].dataArmMap[armIdx];
127} 127}
128 128
129static u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_FW_RAID_MAP_ALL *map) 129u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_FW_RAID_MAP_ALL *map)
130{ 130{
131 return map->raidMap.arMapInfo[ar].pd[arm]; 131 return map->raidMap.arMapInfo[ar].pd[arm];
132} 132}
133 133
134static u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_FW_RAID_MAP_ALL *map) 134u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_FW_RAID_MAP_ALL *map)
135{ 135{
136 return map->raidMap.ldSpanMap[ld].spanBlock[span].span.arrayRef; 136 return map->raidMap.ldSpanMap[ld].spanBlock[span].span.arrayRef;
137} 137}
138 138
139static u16 MR_PdDevHandleGet(u32 pd, struct MR_FW_RAID_MAP_ALL *map) 139u16 MR_PdDevHandleGet(u32 pd, struct MR_FW_RAID_MAP_ALL *map)
140{ 140{
141 return map->raidMap.devHndlInfo[pd].curDevHdl; 141 return map->raidMap.devHndlInfo[pd].curDevHdl;
142} 142}
@@ -784,7 +784,7 @@ u8
784MR_BuildRaidContext(struct megasas_instance *instance, 784MR_BuildRaidContext(struct megasas_instance *instance,
785 struct IO_REQUEST_INFO *io_info, 785 struct IO_REQUEST_INFO *io_info,
786 struct RAID_CONTEXT *pRAID_Context, 786 struct RAID_CONTEXT *pRAID_Context,
787 struct MR_FW_RAID_MAP_ALL *map) 787 struct MR_FW_RAID_MAP_ALL *map, u8 **raidLUN)
788{ 788{
789 struct MR_LD_RAID *raid; 789 struct MR_LD_RAID *raid;
790 u32 ld, stripSize, stripe_mask; 790 u32 ld, stripSize, stripe_mask;
@@ -977,6 +977,9 @@ MR_BuildRaidContext(struct megasas_instance *instance,
977 pRAID_Context->regLockRowLBA = regStart; 977 pRAID_Context->regLockRowLBA = regStart;
978 pRAID_Context->regLockLength = regSize; 978 pRAID_Context->regLockLength = regSize;
979 pRAID_Context->configSeqNum = raid->seqNum; 979 pRAID_Context->configSeqNum = raid->seqNum;
980 /* save pointer to raid->LUN array */
981 *raidLUN = raid->LUN;
982
980 983
981 /*Get Phy Params only if FP capable, or else leave it to MR firmware 984 /*Get Phy Params only if FP capable, or else leave it to MR firmware
982 to do the calculation.*/ 985 to do the calculation.*/
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index 417d5f167aa2..10b19a87050b 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -72,17 +72,6 @@ megasas_clear_intr_fusion(struct megasas_register_set __iomem *regs);
72int 72int
73megasas_issue_polled(struct megasas_instance *instance, 73megasas_issue_polled(struct megasas_instance *instance,
74 struct megasas_cmd *cmd); 74 struct megasas_cmd *cmd);
75
76u8
77MR_BuildRaidContext(struct megasas_instance *instance,
78 struct IO_REQUEST_INFO *io_info,
79 struct RAID_CONTEXT *pRAID_Context,
80 struct MR_FW_RAID_MAP_ALL *map);
81u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map);
82struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_FW_RAID_MAP_ALL *map);
83
84u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map);
85
86void 75void
87megasas_check_and_restore_queue_depth(struct megasas_instance *instance); 76megasas_check_and_restore_queue_depth(struct megasas_instance *instance);
88 77
@@ -652,6 +641,10 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
652 (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) 641 (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
653 init_frame->driver_operations. 642 init_frame->driver_operations.
654 mfi_capabilities.support_additional_msix = 1; 643 mfi_capabilities.support_additional_msix = 1;
644 /* driver supports HA / Remote LUN over Fast Path interface */
645 init_frame->driver_operations.mfi_capabilities.support_fp_remote_lun
646 = 1;
647
655 648
656 init_frame->queue_info_new_phys_addr_lo = ioc_init_handle; 649 init_frame->queue_info_new_phys_addr_lo = ioc_init_handle;
657 init_frame->data_xfer_len = sizeof(struct MPI2_IOC_INIT_REQUEST); 650 init_frame->data_xfer_len = sizeof(struct MPI2_IOC_INIT_REQUEST);
@@ -1410,6 +1403,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
1410 struct IO_REQUEST_INFO io_info; 1403 struct IO_REQUEST_INFO io_info;
1411 struct fusion_context *fusion; 1404 struct fusion_context *fusion;
1412 struct MR_FW_RAID_MAP_ALL *local_map_ptr; 1405 struct MR_FW_RAID_MAP_ALL *local_map_ptr;
1406 u8 *raidLUN;
1413 1407
1414 device_id = MEGASAS_DEV_INDEX(instance, scp); 1408 device_id = MEGASAS_DEV_INDEX(instance, scp);
1415 1409
@@ -1494,7 +1488,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
1494 } else { 1488 } else {
1495 if (MR_BuildRaidContext(instance, &io_info, 1489 if (MR_BuildRaidContext(instance, &io_info,
1496 &io_request->RaidContext, 1490 &io_request->RaidContext,
1497 local_map_ptr)) 1491 local_map_ptr, &raidLUN))
1498 fp_possible = io_info.fpOkForIo; 1492 fp_possible = io_info.fpOkForIo;
1499 } 1493 }
1500 1494
@@ -1537,6 +1531,8 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
1537 scp->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG; 1531 scp->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG;
1538 cmd->request_desc->SCSIIO.DevHandle = io_info.devHandle; 1532 cmd->request_desc->SCSIIO.DevHandle = io_info.devHandle;
1539 io_request->DevHandle = io_info.devHandle; 1533 io_request->DevHandle = io_info.devHandle;
1534 /* populate the LUN field */
1535 memcpy(io_request->LUN, raidLUN, 8);
1540 } else { 1536 } else {
1541 io_request->RaidContext.timeoutValue = 1537 io_request->RaidContext.timeoutValue =
1542 local_map_ptr->raidMap.fpPdIoTimeoutSec; 1538 local_map_ptr->raidMap.fpPdIoTimeoutSec;
@@ -1579,6 +1575,11 @@ megasas_build_dcdb_fusion(struct megasas_instance *instance,
1579 u16 pd_index = 0; 1575 u16 pd_index = 0;
1580 struct MR_FW_RAID_MAP_ALL *local_map_ptr; 1576 struct MR_FW_RAID_MAP_ALL *local_map_ptr;
1581 struct fusion_context *fusion = instance->ctrl_context; 1577 struct fusion_context *fusion = instance->ctrl_context;
1578 u8 span, physArm;
1579 u16 devHandle;
1580 u32 ld, arRef, pd;
1581 struct MR_LD_RAID *raid;
1582 struct RAID_CONTEXT *pRAID_Context;
1582 1583
1583 io_request = cmd->io_request; 1584 io_request = cmd->io_request;
1584 device_id = MEGASAS_DEV_INDEX(instance, scmd); 1585 device_id = MEGASAS_DEV_INDEX(instance, scmd);
@@ -1586,6 +1587,9 @@ megasas_build_dcdb_fusion(struct megasas_instance *instance,
1586 +scmd->device->id; 1587 +scmd->device->id;
1587 local_map_ptr = fusion->ld_map[(instance->map_id & 1)]; 1588 local_map_ptr = fusion->ld_map[(instance->map_id & 1)];
1588 1589
1590 io_request->DataLength = scsi_bufflen(scmd);
1591
1592
1589 /* Check if this is a system PD I/O */ 1593 /* Check if this is a system PD I/O */
1590 if (scmd->device->channel < MEGASAS_MAX_PD_CHANNELS && 1594 if (scmd->device->channel < MEGASAS_MAX_PD_CHANNELS &&
1591 instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) { 1595 instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) {
@@ -1623,6 +1627,54 @@ megasas_build_dcdb_fusion(struct megasas_instance *instance,
1623 scmd->request->timeout / HZ; 1627 scmd->request->timeout / HZ;
1624 } 1628 }
1625 } else { 1629 } else {
1630 if (scmd->device->channel < MEGASAS_MAX_PD_CHANNELS)
1631 goto NonFastPath;
1632
1633 ld = MR_TargetIdToLdGet(device_id, local_map_ptr);
1634 if ((ld >= MAX_LOGICAL_DRIVES) || (!fusion->fast_path_io))
1635 goto NonFastPath;
1636
1637 raid = MR_LdRaidGet(ld, local_map_ptr);
1638
1639 /* check if this LD is FP capable */
1640 if (!(raid->capability.fpNonRWCapable))
1641 /* not FP capable, send as non-FP */
1642 goto NonFastPath;
1643
1644 /* get RAID_Context pointer */
1645 pRAID_Context = &io_request->RaidContext;
1646
1647 /* set RAID context values */
1648 pRAID_Context->regLockFlags = REGION_TYPE_SHARED_READ;
1649 pRAID_Context->timeoutValue = raid->fpIoTimeoutForLd;
1650 pRAID_Context->VirtualDiskTgtId = device_id;
1651 pRAID_Context->regLockRowLBA = 0;
1652 pRAID_Context->regLockLength = 0;
1653 pRAID_Context->configSeqNum = raid->seqNum;
1654
1655 /* get the DevHandle for the PD (since this is
1656 fpNonRWCapable, this is a single disk RAID0) */
1657 span = physArm = 0;
1658 arRef = MR_LdSpanArrayGet(ld, span, local_map_ptr);
1659 pd = MR_ArPdGet(arRef, physArm, local_map_ptr);
1660 devHandle = MR_PdDevHandleGet(pd, local_map_ptr);
1661
1662 /* build request descriptor */
1663 cmd->request_desc->SCSIIO.RequestFlags =
1664 (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY <<
1665 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
1666 cmd->request_desc->SCSIIO.DevHandle = devHandle;
1667
1668 /* populate the LUN field */
1669 memcpy(io_request->LUN, raid->LUN, 8);
1670
1671 /* build the raidScsiIO structure */
1672 io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
1673 io_request->DevHandle = devHandle;
1674
1675 return;
1676
1677NonFastPath:
1626 io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST; 1678 io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
1627 io_request->DevHandle = device_id; 1679 io_request->DevHandle = device_id;
1628 cmd->request_desc->SCSIIO.RequestFlags = 1680 cmd->request_desc->SCSIIO.RequestFlags =
@@ -1631,7 +1683,6 @@ megasas_build_dcdb_fusion(struct megasas_instance *instance,
1631 } 1683 }
1632 io_request->RaidContext.VirtualDiskTgtId = device_id; 1684 io_request->RaidContext.VirtualDiskTgtId = device_id;
1633 io_request->LUN[1] = scmd->device->lun; 1685 io_request->LUN[1] = scmd->device->lun;
1634 io_request->DataLength = scsi_bufflen(scmd);
1635} 1686}
1636 1687
1637/** 1688/**
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h
index 12ff01cf6799..92b4daa172b6 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.h
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h
@@ -527,7 +527,8 @@ struct MR_LD_RAID {
527 u32 fpReadCapable:1; 527 u32 fpReadCapable:1;
528 u32 fpWriteAcrossStripe:1; 528 u32 fpWriteAcrossStripe:1;
529 u32 fpReadAcrossStripe:1; 529 u32 fpReadAcrossStripe:1;
530 u32 reserved4:8; 530 u32 fpNonRWCapable:1;
531 u32 reserved4:7;
531 } capability; 532 } capability;
532 u32 reserved6; 533 u32 reserved6;
533 u64 size; 534 u64 size;
@@ -551,7 +552,9 @@ struct MR_LD_RAID {
551 u32 reserved:31; 552 u32 reserved:31;
552 } flags; 553 } flags;
553 554
554 u8 reserved3[0x5C]; 555 u8 LUN[8]; /* 0x24 8 byte LUN field used for SCSI IO's */
556 u8 fpIoTimeoutForLd;/*0x2C timeout value used by driver in FP IO*/
557 u8 reserved3[0x80-0x2D]; /* 0x2D */
555}; 558};
556 559
557struct MR_LD_SPAN_MAP { 560struct MR_LD_SPAN_MAP {