diff options
author | adam radford <aradford@gmail.com> | 2013-09-06 18:27:14 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-09-06 18:54:55 -0400 |
commit | 21c9e160a51383d4cb0b882398534b0c95c0cc3b (patch) | |
tree | f8d0992cb054f39306ea565df149708dd612ac2e | |
parent | 9807b4d94911be4e4efb9a08481b24292a9edf8a (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>
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.h | 32 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_base.c | 106 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_fp.c | 11 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_fusion.c | 77 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_fusion.h | 7 |
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 | ||
349 | enum 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 | ||
448 | struct 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 | ||
1677 | u8 | ||
1678 | MR_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); | ||
1682 | u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map); | ||
1683 | struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_FW_RAID_MAP_ALL *map); | ||
1684 | u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_FW_RAID_MAP_ALL *map); | ||
1685 | u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_FW_RAID_MAP_ALL *map); | ||
1686 | u16 MR_PdDevHandleGet(u32 pd, struct MR_FW_RAID_MAP_ALL *map); | ||
1687 | u16 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 | ||
93 | int megasas_transition_to_ready(struct megasas_instance *instance, int ocr); | 93 | int megasas_transition_to_ready(struct megasas_instance *instance, int ocr); |
94 | static int megasas_get_pd_list(struct megasas_instance *instance); | 94 | static int megasas_get_pd_list(struct megasas_instance *instance); |
95 | static int megasas_ld_list_query(struct megasas_instance *instance, | ||
96 | u8 query_type); | ||
95 | static int megasas_issue_init_mfi(struct megasas_instance *instance); | 97 | static int megasas_issue_init_mfi(struct megasas_instance *instance); |
96 | static int megasas_register_aen(struct megasas_instance *instance, | 98 | static 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 | */ | ||
3284 | static int | ||
3285 | megasas_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 | ||
129 | static u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_FW_RAID_MAP_ALL *map) | 129 | u16 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 | ||
134 | static u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_FW_RAID_MAP_ALL *map) | 134 | u16 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 | ||
139 | static u16 MR_PdDevHandleGet(u32 pd, struct MR_FW_RAID_MAP_ALL *map) | 139 | u16 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 | |||
784 | MR_BuildRaidContext(struct megasas_instance *instance, | 784 | MR_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); | |||
72 | int | 72 | int |
73 | megasas_issue_polled(struct megasas_instance *instance, | 73 | megasas_issue_polled(struct megasas_instance *instance, |
74 | struct megasas_cmd *cmd); | 74 | struct megasas_cmd *cmd); |
75 | |||
76 | u8 | ||
77 | MR_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); | ||
81 | u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map); | ||
82 | struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_FW_RAID_MAP_ALL *map); | ||
83 | |||
84 | u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map); | ||
85 | |||
86 | void | 75 | void |
87 | megasas_check_and_restore_queue_depth(struct megasas_instance *instance); | 76 | megasas_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 | |||
1677 | NonFastPath: | ||
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 | ||
557 | struct MR_LD_SPAN_MAP { | 560 | struct MR_LD_SPAN_MAP { |