提交 69c337c0 编写于 作者: S Sasikumar Chandrasekaran 提交者: Martin K. Petersen

scsi: megaraid_sas: SAS3.5 Generic Megaraid Controllers Fast Path for RAID 1/10 Writes

To improve RAID 1/10 Write performance, OS drivers need to issue the
required Write IOs as Fast Path IOs (after the appropriate checks
allowing Fast Path to be used) to the appropriate physical drives
(translated from the OS logical IO) and wait for all Write IOs to complete.

Design: A write IO on RAID volume will be examined if it can be sent in
Fast Path based on IO size and starting LBA and ending LBA falling on to
a Physical Drive boundary. If the underlying RAID volume is a RAID 1/10,
driver issues two fast path write IOs one for each corresponding physical
drive after computing the corresponding start LBA for each physical drive.
Both write IOs will have the same payload and are posted to HW such that
replies land in the same reply queue.

If there are no resources available for sending two IOs, driver will send
the original IO from SCSI layer to RAID volume through the Firmware.

Based on PCI bandwidth and write payload, every second this feature is
enabled/disabled.

When both IOs are completed by HW, the resources will be released
and SCSI IO completion handler will be called.
Signed-off-by: NSasikumar Chandrasekaran <sasikumar.pc@broadcom.com>
Reviewed-by: NTomas Henzl <thenzl@redhat.com>
Signed-off-by: NMartin K. Petersen <martin.petersen@oracle.com>
上级 fdd84e25
...@@ -2056,6 +2056,7 @@ struct megasas_instance { ...@@ -2056,6 +2056,7 @@ struct megasas_instance {
u16 max_num_sge; u16 max_num_sge;
u16 max_fw_cmds; u16 max_fw_cmds;
u16 max_mpt_cmds;
u16 max_mfi_cmds; u16 max_mfi_cmds;
u16 max_scsi_cmds; u16 max_scsi_cmds;
u16 ldio_threshold; u16 ldio_threshold;
......
...@@ -737,7 +737,7 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld, ...@@ -737,7 +737,7 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld,
struct MR_DRV_RAID_MAP_ALL *map) struct MR_DRV_RAID_MAP_ALL *map)
{ {
struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
u32 pd, arRef; u32 pd, arRef, r1_alt_pd;
u8 physArm, span; u8 physArm, span;
u64 row; u64 row;
u8 retval = TRUE; u8 retval = TRUE;
...@@ -772,9 +772,16 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld, ...@@ -772,9 +772,16 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld,
arRef = MR_LdSpanArrayGet(ld, span, map); arRef = MR_LdSpanArrayGet(ld, span, map);
pd = MR_ArPdGet(arRef, physArm, map); pd = MR_ArPdGet(arRef, physArm, map);
if (pd != MR_PD_INVALID) if (pd != MR_PD_INVALID) {
*pDevHandle = MR_PdDevHandleGet(pd, map); *pDevHandle = MR_PdDevHandleGet(pd, map);
else { /* get second pd also for raid 1/10 fast path writes*/
if (raid->level == 1) {
r1_alt_pd = MR_ArPdGet(arRef, physArm + 1, map);
if (r1_alt_pd != MR_PD_INVALID)
io_info->r1_alt_dev_handle =
MR_PdDevHandleGet(r1_alt_pd, map);
}
} else {
*pDevHandle = cpu_to_le16(MR_PD_INVALID); *pDevHandle = cpu_to_le16(MR_PD_INVALID);
if ((raid->level >= 5) && if ((raid->level >= 5) &&
((fusion->adapter_type == THUNDERBOLT_SERIES) || ((fusion->adapter_type == THUNDERBOLT_SERIES) ||
...@@ -819,7 +826,7 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow, ...@@ -819,7 +826,7 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
struct MR_DRV_RAID_MAP_ALL *map) struct MR_DRV_RAID_MAP_ALL *map)
{ {
struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
u32 pd, arRef; u32 pd, arRef, r1_alt_pd;
u8 physArm, span; u8 physArm, span;
u64 row; u64 row;
u8 retval = TRUE; u8 retval = TRUE;
...@@ -867,10 +874,17 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow, ...@@ -867,10 +874,17 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
arRef = MR_LdSpanArrayGet(ld, span, map); arRef = MR_LdSpanArrayGet(ld, span, map);
pd = MR_ArPdGet(arRef, physArm, map); /* Get the pd */ pd = MR_ArPdGet(arRef, physArm, map); /* Get the pd */
if (pd != MR_PD_INVALID) if (pd != MR_PD_INVALID) {
/* Get dev handle from Pd. */ /* Get dev handle from Pd. */
*pDevHandle = MR_PdDevHandleGet(pd, map); *pDevHandle = MR_PdDevHandleGet(pd, map);
else { /* get second pd also for raid 1/10 fast path writes*/
if (raid->level == 1) {
r1_alt_pd = MR_ArPdGet(arRef, physArm + 1, map);
if (r1_alt_pd != MR_PD_INVALID)
io_info->r1_alt_dev_handle =
MR_PdDevHandleGet(r1_alt_pd, map);
}
} else {
/* set dev handle as invalid. */ /* set dev handle as invalid. */
*pDevHandle = cpu_to_le16(MR_PD_INVALID); *pDevHandle = cpu_to_le16(MR_PD_INVALID);
if ((raid->level >= 5) && if ((raid->level >= 5) &&
...@@ -1126,6 +1140,11 @@ MR_BuildRaidContext(struct megasas_instance *instance, ...@@ -1126,6 +1140,11 @@ MR_BuildRaidContext(struct megasas_instance *instance,
/* If IO on an invalid Pd, then FP is not possible.*/ /* If IO on an invalid Pd, then FP is not possible.*/
if (io_info->devHandle == cpu_to_le16(MR_PD_INVALID)) if (io_info->devHandle == cpu_to_le16(MR_PD_INVALID))
io_info->fpOkForIo = FALSE; io_info->fpOkForIo = FALSE;
/* set raid 1/10 fast path write capable bit in io_info */
if (io_info->fpOkForIo &&
(io_info->r1_alt_dev_handle != MR_PD_INVALID) &&
(raid->level == 1) && !isRead)
io_info->is_raid_1_fp_write = 1;
return retval; return retval;
} else if (isRead) { } else if (isRead) {
uint stripIdx; uint stripIdx;
......
...@@ -94,6 +94,7 @@ enum MR_RAID_FLAGS_IO_SUB_TYPE { ...@@ -94,6 +94,7 @@ enum MR_RAID_FLAGS_IO_SUB_TYPE {
#define MEGASAS_FP_CMD_LEN 16 #define MEGASAS_FP_CMD_LEN 16
#define MEGASAS_FUSION_IN_RESET 0 #define MEGASAS_FUSION_IN_RESET 0
#define THRESHOLD_REPLY_COUNT 50 #define THRESHOLD_REPLY_COUNT 50
#define RAID_1_10_RMW_CMDS 3
#define JBOD_MAPS_COUNT 2 #define JBOD_MAPS_COUNT 2
enum MR_FUSION_ADAPTER_TYPE { enum MR_FUSION_ADAPTER_TYPE {
...@@ -728,7 +729,9 @@ struct MR_SPAN_BLOCK_INFO { ...@@ -728,7 +729,9 @@ struct MR_SPAN_BLOCK_INFO {
struct MR_LD_RAID { struct MR_LD_RAID {
struct { struct {
#if defined(__BIG_ENDIAN_BITFIELD) #if defined(__BIG_ENDIAN_BITFIELD)
u32 reserved4:5; u32 reserved4:3;
u32 fp_cache_bypass_capable:1;
u32 fp_rmw_capable:1;
u32 fpBypassRegionLock:1; u32 fpBypassRegionLock:1;
u32 tmCapable:1; u32 tmCapable:1;
u32 fpNonRWCapable:1; u32 fpNonRWCapable:1;
...@@ -756,7 +759,9 @@ struct MR_LD_RAID { ...@@ -756,7 +759,9 @@ struct MR_LD_RAID {
u32 fpNonRWCapable:1; u32 fpNonRWCapable:1;
u32 tmCapable:1; u32 tmCapable:1;
u32 fpBypassRegionLock:1; u32 fpBypassRegionLock:1;
u32 reserved4:5; u32 fp_rmw_capable:1;
u32 fp_cache_bypass_capable:1;
u32 reserved4:3;
#endif #endif
} capability; } capability;
__le32 reserved6; __le32 reserved6;
...@@ -830,6 +835,8 @@ struct IO_REQUEST_INFO { ...@@ -830,6 +835,8 @@ struct IO_REQUEST_INFO {
u64 start_row; u64 start_row;
u8 span_arm; /* span[7:5], arm[4:0] */ u8 span_arm; /* span[7:5], arm[4:0] */
u8 pd_after_lb; u8 pd_after_lb;
u16 r1_alt_dev_handle; /* raid 1/10 only */
bool is_raid_1_fp_write;
bool ra_capable; bool ra_capable;
}; };
...@@ -883,6 +890,10 @@ struct megasas_cmd_fusion { ...@@ -883,6 +890,10 @@ struct megasas_cmd_fusion {
u32 index; u32 index;
u8 pd_r1_lb; u8 pd_r1_lb;
struct completion done; struct completion done;
bool is_raid_1_fp_write;
u16 r1_alt_dev_handle; /* raid 1/10 only*/
bool cmd_completed; /* raid 1/10 fp writes status holder */
}; };
struct LD_LOAD_BALANCE_INFO { struct LD_LOAD_BALANCE_INFO {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册