Commit 7fc55700 authored by Chandrakanth Patil's avatar Chandrakanth Patil Committed by Martin K. Petersen

scsi: megaraid_sas: Offload Aero RAID5/6 division calculations to driver

For RAID5/RAID6 volumes configured behind Aero, driver will be doing 64bit
division operations on behalf of firmware as controller's ARM CPU is very
slow in this division. Later, driver calculates Q-ARM, P-ARM and Log-ARM and
passes those values to firmware by writing these values to RAID_CONTEXT.
Signed-off-by: default avatarSumit Saxena <sumit.saxena@broadcom.com>
Signed-off-by: default avatarChandrakanth Patil <chandrakanth.patil@broadcom.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 49f2bf10
......@@ -5777,8 +5777,16 @@ static int megasas_init_fw(struct megasas_instance *instance)
MR_MAX_RAID_MAP_SIZE_MASK);
}
if (instance->adapter_type == VENTURA_SERIES)
switch (instance->adapter_type) {
case VENTURA_SERIES:
fusion->pcie_bw_limitation = true;
break;
case AERO_SERIES:
fusion->r56_div_offload = true;
break;
default:
break;
}
/* Check if MSI-X is supported while in ready state */
msix_enable = (instance->instancet->read_fw_status_reg(instance) &
......
......@@ -901,6 +901,77 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
return retval;
}
/*
* mr_get_phy_params_r56_rmw - Calculate parameters for R56 CTIO write operation
* @instance: Adapter soft state
* @ld: LD index
* @stripNo: Strip Number
* @io_info: IO info structure pointer
* pRAID_Context: RAID context pointer
* map: RAID map pointer
*
* This routine calculates the logical arm, data Arm, row number and parity arm
* for R56 CTIO write operation.
*/
static void mr_get_phy_params_r56_rmw(struct megasas_instance *instance,
u32 ld, u64 stripNo,
struct IO_REQUEST_INFO *io_info,
struct RAID_CONTEXT_G35 *pRAID_Context,
struct MR_DRV_RAID_MAP_ALL *map)
{
struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
u8 span, dataArms, arms, dataArm, logArm;
s8 rightmostParityArm, PParityArm;
u64 rowNum;
u64 *pdBlock = &io_info->pdBlock;
dataArms = raid->rowDataSize;
arms = raid->rowSize;
rowNum = mega_div64_32(stripNo, dataArms);
/* parity disk arm, first arm is 0 */
rightmostParityArm = (arms - 1) - mega_mod64(rowNum, arms);
/* logical arm within row */
logArm = mega_mod64(stripNo, dataArms);
/* physical arm for data */
dataArm = mega_mod64((rightmostParityArm + 1 + logArm), arms);
if (raid->spanDepth == 1) {
span = 0;
} else {
span = (u8)MR_GetSpanBlock(ld, rowNum, pdBlock, map);
if (span == SPAN_INVALID)
return;
}
if (raid->level == 6) {
/* P Parity arm, note this can go negative adjust if negative */
PParityArm = (arms - 2) - mega_mod64(rowNum, arms);
if (PParityArm < 0)
PParityArm += arms;
/* rightmostParityArm is P-Parity for RAID 5 and Q-Parity for RAID */
pRAID_Context->flow_specific.r56_arm_map = rightmostParityArm;
pRAID_Context->flow_specific.r56_arm_map |=
(u16)(PParityArm << RAID_CTX_R56_P_ARM_SHIFT);
} else {
pRAID_Context->flow_specific.r56_arm_map |=
(u16)(rightmostParityArm << RAID_CTX_R56_P_ARM_SHIFT);
}
pRAID_Context->reg_lock_row_lba = cpu_to_le64(rowNum);
pRAID_Context->flow_specific.r56_arm_map |=
(u16)(logArm << RAID_CTX_R56_LOG_ARM_SHIFT);
cpu_to_le16s(&pRAID_Context->flow_specific.r56_arm_map);
pRAID_Context->span_arm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | dataArm;
pRAID_Context->raid_flags = (MR_RAID_FLAGS_IO_SUB_TYPE_R56_DIV_OFFLOAD <<
MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT);
return;
}
/*
******************************************************************************
*
......@@ -1108,6 +1179,13 @@ MR_BuildRaidContext(struct megasas_instance *instance,
/* save pointer to raid->LUN array */
*raidLUN = raid->LUN;
/* Aero R5/6 Division Offload for WRITE */
if (fusion->r56_div_offload && (raid->level >= 5) && !isRead) {
mr_get_phy_params_r56_rmw(instance, ld, start_strip, io_info,
(struct RAID_CONTEXT_G35 *)pRAID_Context,
map);
return true;
}
/*Get Phy Params only if FP capable, or else leave it to MR firmware
to do the calculation.*/
......
......@@ -3324,9 +3324,9 @@ void megasas_prepare_secondRaid1_IO(struct megasas_instance *instance,
r1_cmd->request_desc->SCSIIO.DevHandle = cmd->r1_alt_dev_handle;
r1_cmd->io_request->DevHandle = cmd->r1_alt_dev_handle;
r1_cmd->r1_alt_dev_handle = cmd->io_request->DevHandle;
cmd->io_request->RaidContext.raid_context_g35.smid.peer_smid =
cmd->io_request->RaidContext.raid_context_g35.flow_specific.peer_smid =
cpu_to_le16(r1_cmd->index);
r1_cmd->io_request->RaidContext.raid_context_g35.smid.peer_smid =
r1_cmd->io_request->RaidContext.raid_context_g35.flow_specific.peer_smid =
cpu_to_le16(cmd->index);
/*MSIxIndex of both commands request descriptors should be same*/
r1_cmd->request_desc->SCSIIO.MSIxIndex =
......@@ -3444,7 +3444,7 @@ megasas_complete_r1_command(struct megasas_instance *instance,
rctx_g35 = &cmd->io_request->RaidContext.raid_context_g35;
fusion = instance->ctrl_context;
peer_smid = le16_to_cpu(rctx_g35->smid.peer_smid);
peer_smid = le16_to_cpu(rctx_g35->flow_specific.peer_smid);
r1_cmd = fusion->cmd_list[peer_smid - 1];
scmd_local = cmd->scmd;
......
......@@ -87,7 +87,8 @@ enum MR_RAID_FLAGS_IO_SUB_TYPE {
MR_RAID_FLAGS_IO_SUB_TYPE_RMW_P = 3,
MR_RAID_FLAGS_IO_SUB_TYPE_RMW_Q = 4,
MR_RAID_FLAGS_IO_SUB_TYPE_CACHE_BYPASS = 6,
MR_RAID_FLAGS_IO_SUB_TYPE_LDIO_BW_LIMIT = 7
MR_RAID_FLAGS_IO_SUB_TYPE_LDIO_BW_LIMIT = 7,
MR_RAID_FLAGS_IO_SUB_TYPE_R56_DIV_OFFLOAD = 8
};
/*
......@@ -151,12 +152,15 @@ struct RAID_CONTEXT_G35 {
u16 timeout_value; /* 0x02 -0x03 */
u16 routing_flags; // 0x04 -0x05 routing flags
u16 virtual_disk_tgt_id; /* 0x06 -0x07 */
u64 reg_lock_row_lba; /* 0x08 - 0x0F */
__le64 reg_lock_row_lba; /* 0x08 - 0x0F */
u32 reg_lock_length; /* 0x10 - 0x13 */
union {
u16 next_lmid; /* 0x14 - 0x15 */
u16 peer_smid; /* used for the raid 1/10 fp writes */
} smid;
union { // flow specific
u16 rmw_op_index; /* 0x14 - 0x15, R5/6 RMW: rmw operation index*/
u16 peer_smid; /* 0x14 - 0x15, R1 Write: peer smid*/
u16 r56_arm_map; /* 0x14 - 0x15, Unused [15], LogArm[14:10], P-Arm[9:5], Q-Arm[4:0] */
} flow_specific;
u8 ex_status; /* 0x16 : OUT */
u8 status; /* 0x17 status */
u8 raid_flags; /* 0x18 resvd[7:6], ioSubType[5:4],
......@@ -247,6 +251,13 @@ union RAID_CONTEXT_UNION {
#define RAID_CTX_SPANARM_SPAN_SHIFT (5)
#define RAID_CTX_SPANARM_SPAN_MASK (0xE0)
/* LogArm[14:10], P-Arm[9:5], Q-Arm[4:0] */
#define RAID_CTX_R56_Q_ARM_MASK (0x1F)
#define RAID_CTX_R56_P_ARM_SHIFT (5)
#define RAID_CTX_R56_P_ARM_MASK (0x3E0)
#define RAID_CTX_R56_LOG_ARM_SHIFT (10)
#define RAID_CTX_R56_LOG_ARM_MASK (0x7C00)
/* number of bits per index in U32 TrackStream */
#define BITS_PER_INDEX_STREAM 4
#define INVALID_STREAM_NUM 16
......@@ -1336,6 +1347,7 @@ struct fusion_context {
struct MPI2_IOC_INIT_REQUEST *ioc_init_request;
struct megasas_cmd *ioc_init_cmd;
bool pcie_bw_limitation;
bool r56_div_offload;
};
union desc_value {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment