aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSumit.Saxena@lsi.com <Sumit.Saxena@lsi.com>2013-05-22 03:05:04 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-06-24 20:48:12 -0400
commitbc93d425fcb6443ffd6e20efa08f4960a30ab26f (patch)
tree8b91194f92099e1e414db83bec3145870ba0813f
parentd46a3ad679c7232b72b21c6d0ca047dc4a68063f (diff)
[SCSI] megaraid_sas: Add support for Uneven Span PRL11
MegaRAID older Firmware does not support uneven span configuration for PRL11. E.g User wants to create 34 Driver PRL11 config, it was not possible using old firmware, since it was not supported configuration in old firmware Old Firmware expect even number of Drives in each span and same number of physical drives at each span. Considering above design, 17 Drives at Span-0 and 17 drives at span-1 was not possible. Now, using this new feature Firmware and Driver both required changes. New Firmware can allow user to create 16 Drives at span-0 and 18 Drives at span-1. This will allow user to create 34 Drives Uneven span PRL11. RAID map is interface between Driver and FW to fetch all required fields(attributes) for each Virtual Drives. Since legacy RAID map consider Even Span design, there was no place to keep Uneven span information in existing Raid map. Because of this limitation, for Uneven span VD, driver can not use RAID map. This patch address the changes required in Driver to support Uneven span PRL11 support. 1. Driver will find if Firmware has UnevenSpanSupport or not by reading Controller Info. 2. If Firmware has UnvenSpan PRL11 support, then Driver will inform about its capability of handling UnevenSpan PRL11 to the firmware. 3. Driver will update its copy of span info on each time Raid map update is called. 4. Follow different IO path if it is Uneven Span. (For Uneven Span, Driver uses Span Set info to find relavent fields for that particular Virtual Disk) More verbose prints will be available by setting "SPAN_DEBUG" to 1 at compilation time. Signed-off-by: Sumit Saxena <sumit.saxena@lsi.com> Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h127
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c26
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fp.c766
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.c5
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.h30
5 files changed, 904 insertions, 50 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 2371e5ca2a5b..55a08d8ec531 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -190,6 +190,12 @@
190#define MR_DCMD_PD_LIST_QUERY 0x02010100 190#define MR_DCMD_PD_LIST_QUERY 0x02010100
191 191
192/* 192/*
193 * Global functions
194 */
195extern u8 MR_ValidateMapInfo(struct megasas_instance *instance);
196
197
198/*
193 * MFI command completion codes 199 * MFI command completion codes
194 */ 200 */
195enum MFI_STAT { 201enum MFI_STAT {
@@ -729,8 +735,126 @@ struct megasas_ctrl_info {
729 */ 735 */
730 char package_version[0x60]; 736 char package_version[0x60];
731 737
732 u8 pad[0x800 - 0x6a0];
733 738
739 /*
740 * If adapterOperations.supportMoreThan8Phys is set,
741 * and deviceInterface.portCount is greater than 8,
742 * SAS Addrs for first 8 ports shall be populated in
743 * deviceInterface.portAddr, and the rest shall be
744 * populated in deviceInterfacePortAddr2.
745 */
746 u64 deviceInterfacePortAddr2[8]; /*6a0h */
747 u8 reserved3[128]; /*6e0h */
748
749 struct { /*760h */
750 u16 minPdRaidLevel_0:4;
751 u16 maxPdRaidLevel_0:12;
752
753 u16 minPdRaidLevel_1:4;
754 u16 maxPdRaidLevel_1:12;
755
756 u16 minPdRaidLevel_5:4;
757 u16 maxPdRaidLevel_5:12;
758
759 u16 minPdRaidLevel_1E:4;
760 u16 maxPdRaidLevel_1E:12;
761
762 u16 minPdRaidLevel_6:4;
763 u16 maxPdRaidLevel_6:12;
764
765 u16 minPdRaidLevel_10:4;
766 u16 maxPdRaidLevel_10:12;
767
768 u16 minPdRaidLevel_50:4;
769 u16 maxPdRaidLevel_50:12;
770
771 u16 minPdRaidLevel_60:4;
772 u16 maxPdRaidLevel_60:12;
773
774 u16 minPdRaidLevel_1E_RLQ0:4;
775 u16 maxPdRaidLevel_1E_RLQ0:12;
776
777 u16 minPdRaidLevel_1E0_RLQ0:4;
778 u16 maxPdRaidLevel_1E0_RLQ0:12;
779
780 u16 reserved[6];
781 } pdsForRaidLevels;
782
783 u16 maxPds; /*780h */
784 u16 maxDedHSPs; /*782h */
785 u16 maxGlobalHSPs; /*784h */
786 u16 ddfSize; /*786h */
787 u8 maxLdsPerArray; /*788h */
788 u8 partitionsInDDF; /*789h */
789 u8 lockKeyBinding; /*78ah */
790 u8 maxPITsPerLd; /*78bh */
791 u8 maxViewsPerLd; /*78ch */
792 u8 maxTargetId; /*78dh */
793 u16 maxBvlVdSize; /*78eh */
794
795 u16 maxConfigurableSSCSize; /*790h */
796 u16 currentSSCsize; /*792h */
797
798 char expanderFwVersion[12]; /*794h */
799
800 u16 PFKTrialTimeRemaining; /*7A0h */
801
802 u16 cacheMemorySize; /*7A2h */
803
804 struct { /*7A4h */
805 u32 supportPIcontroller:1;
806 u32 supportLdPIType1:1;
807 u32 supportLdPIType2:1;
808 u32 supportLdPIType3:1;
809 u32 supportLdBBMInfo:1;
810 u32 supportShieldState:1;
811 u32 blockSSDWriteCacheChange:1;
812 u32 supportSuspendResumeBGops:1;
813 u32 supportEmergencySpares:1;
814 u32 supportSetLinkSpeed:1;
815 u32 supportBootTimePFKChange:1;
816 u32 supportJBOD:1;
817 u32 disableOnlinePFKChange:1;
818 u32 supportPerfTuning:1;
819 u32 supportSSDPatrolRead:1;
820 u32 realTimeScheduler:1;
821
822 u32 supportResetNow:1;
823 u32 supportEmulatedDrives:1;
824 u32 headlessMode:1;
825 u32 dedicatedHotSparesLimited:1;
826
827
828 u32 supportUnevenSpans:1;
829 u32 reserved:11;
830 } adapterOperations2;
831
832 u8 driverVersion[32]; /*7A8h */
833 u8 maxDAPdCountSpinup60; /*7C8h */
834 u8 temperatureROC; /*7C9h */
835 u8 temperatureCtrl; /*7CAh */
836 u8 reserved4; /*7CBh */
837 u16 maxConfigurablePds; /*7CCh */
838
839
840 u8 reserved5[2]; /*0x7CDh */
841
842 /*
843 * HA cluster information
844 */
845 struct {
846 u32 peerIsPresent:1;
847 u32 peerIsIncompatible:1;
848 u32 hwIncompatible:1;
849 u32 fwVersionMismatch:1;
850 u32 ctrlPropIncompatible:1;
851 u32 premiumFeatureMismatch:1;
852 u32 reserved:26;
853 } cluster;
854
855 char clusterId[16]; /*7D4h */
856
857 u8 pad[0x800-0x7E4]; /*7E4 */
734} __packed; 858} __packed;
735 859
736/* 860/*
@@ -1389,6 +1513,7 @@ struct megasas_instance {
1389 u8 flag_ieee; 1513 u8 flag_ieee;
1390 u8 issuepend_done; 1514 u8 issuepend_done;
1391 u8 disableOnlineCtrlReset; 1515 u8 disableOnlineCtrlReset;
1516 u8 UnevenSpanSupport;
1392 u8 adprecovery; 1517 u8 adprecovery;
1393 unsigned long last_time; 1518 unsigned long last_time;
1394 u32 mfiStatus; 1519 u32 mfiStatus;
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index 11f1c940a2aa..6d7b656bd21b 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -171,8 +171,6 @@ megasas_sync_map_info(struct megasas_instance *instance);
171int 171int
172wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd); 172wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd);
173void megasas_reset_reply_desc(struct megasas_instance *instance); 173void megasas_reset_reply_desc(struct megasas_instance *instance);
174u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map,
175 struct LD_LOAD_BALANCE_INFO *lbInfo);
176int megasas_reset_fusion(struct Scsi_Host *shost); 174int megasas_reset_fusion(struct Scsi_Host *shost);
177void megasas_fusion_ocr_wq(struct work_struct *work); 175void megasas_fusion_ocr_wq(struct work_struct *work);
178 176
@@ -2295,6 +2293,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
2295 /* Check for LD map update */ 2293 /* Check for LD map update */
2296 if ((cmd->frame->dcmd.opcode == MR_DCMD_LD_MAP_GET_INFO) && 2294 if ((cmd->frame->dcmd.opcode == MR_DCMD_LD_MAP_GET_INFO) &&
2297 (cmd->frame->dcmd.mbox.b[1] == 1)) { 2295 (cmd->frame->dcmd.mbox.b[1] == 1)) {
2296 fusion->fast_path_io = 0;
2298 spin_lock_irqsave(instance->host->host_lock, flags); 2297 spin_lock_irqsave(instance->host->host_lock, flags);
2299 if (cmd->frame->hdr.cmd_status != 0) { 2298 if (cmd->frame->hdr.cmd_status != 0) {
2300 if (cmd->frame->hdr.cmd_status != 2299 if (cmd->frame->hdr.cmd_status !=
@@ -2312,9 +2311,13 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
2312 } else 2311 } else
2313 instance->map_id++; 2312 instance->map_id++;
2314 megasas_return_cmd(instance, cmd); 2313 megasas_return_cmd(instance, cmd);
2315 if (MR_ValidateMapInfo( 2314
2316 fusion->ld_map[(instance->map_id & 1)], 2315 /*
2317 fusion->load_balance_info)) 2316 * Set fast path IO to ZERO.
2317 * Validate Map will set proper value.
2318 * Meanwhile all IOs will go as LD IO.
2319 */
2320 if (MR_ValidateMapInfo(instance))
2318 fusion->fast_path_io = 1; 2321 fusion->fast_path_io = 1;
2319 else 2322 else
2320 fusion->fast_path_io = 0; 2323 fusion->fast_path_io = 0;
@@ -3661,6 +3664,18 @@ static int megasas_init_fw(struct megasas_instance *instance)
3661 tmp_sectors = min_t(u32, max_sectors_1 , max_sectors_2); 3664 tmp_sectors = min_t(u32, max_sectors_1 , max_sectors_2);
3662 instance->disableOnlineCtrlReset = 3665 instance->disableOnlineCtrlReset =
3663 ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset; 3666 ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
3667 instance->UnevenSpanSupport =
3668 ctrl_info->adapterOperations2.supportUnevenSpans;
3669 if (instance->UnevenSpanSupport) {
3670 struct fusion_context *fusion = instance->ctrl_context;
3671 dev_info(&instance->pdev->dev, "FW supports: "
3672 "UnevenSpanSupport=%x\n", instance->UnevenSpanSupport);
3673 if (MR_ValidateMapInfo(instance))
3674 fusion->fast_path_io = 1;
3675 else
3676 fusion->fast_path_io = 0;
3677
3678 }
3664 } 3679 }
3665 3680
3666 instance->max_sectors_per_req = instance->max_num_sge * 3681 instance->max_sectors_per_req = instance->max_num_sge *
@@ -4202,6 +4217,7 @@ static int megasas_probe_one(struct pci_dev *pdev,
4202 instance->unload = 1; 4217 instance->unload = 1;
4203 instance->last_time = 0; 4218 instance->last_time = 0;
4204 instance->disableOnlineCtrlReset = 1; 4219 instance->disableOnlineCtrlReset = 1;
4220 instance->UnevenSpanSupport = 0;
4205 4221
4206 if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || 4222 if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
4207 (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || 4223 (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
index 356b684f5355..8056eacba758 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fp.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
@@ -60,10 +60,22 @@
60#define FALSE 0 60#define FALSE 0
61#define TRUE 1 61#define TRUE 1
62 62
63#define SPAN_DEBUG 0
64#define SPAN_ROW_SIZE(map, ld, index_) (MR_LdSpanPtrGet(ld, index_, map)->spanRowSize)
65#define SPAN_ROW_DATA_SIZE(map_, ld, index_) (MR_LdSpanPtrGet(ld, index_, map)->spanRowDataSize)
66#define SPAN_INVALID 0xff
67
63/* Prototypes */ 68/* Prototypes */
64void 69void mr_update_load_balance_params(struct MR_FW_RAID_MAP_ALL *map,
65mr_update_load_balance_params(struct MR_FW_RAID_MAP_ALL *map, 70 struct LD_LOAD_BALANCE_INFO *lbInfo);
66 struct LD_LOAD_BALANCE_INFO *lbInfo); 71
72static void mr_update_span_set(struct MR_FW_RAID_MAP_ALL *map,
73 PLD_SPAN_INFO ldSpanInfo);
74static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld,
75 u64 stripRow, u16 stripRef, struct IO_REQUEST_INFO *io_info,
76 struct RAID_CONTEXT *pRAID_Context, struct MR_FW_RAID_MAP_ALL *map);
77static u64 get_row_from_strip(struct megasas_instance *instance, u32 ld,
78 u64 strip, struct MR_FW_RAID_MAP_ALL *map);
67 79
68u32 mega_mod64(u64 dividend, u32 divisor) 80u32 mega_mod64(u64 dividend, u32 divisor)
69{ 81{
@@ -148,9 +160,12 @@ static struct MR_LD_SPAN *MR_LdSpanPtrGet(u32 ld, u32 span,
148/* 160/*
149 * This function will validate Map info data provided by FW 161 * This function will validate Map info data provided by FW
150 */ 162 */
151u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map, 163u8 MR_ValidateMapInfo(struct megasas_instance *instance)
152 struct LD_LOAD_BALANCE_INFO *lbInfo)
153{ 164{
165 struct fusion_context *fusion = instance->ctrl_context;
166 struct MR_FW_RAID_MAP_ALL *map = fusion->ld_map[(instance->map_id & 1)];
167 struct LD_LOAD_BALANCE_INFO *lbInfo = fusion->load_balance_info;
168 PLD_SPAN_INFO ldSpanInfo = fusion->log_to_span;
154 struct MR_FW_RAID_MAP *pFwRaidMap = &map->raidMap; 169 struct MR_FW_RAID_MAP *pFwRaidMap = &map->raidMap;
155 170
156 if (pFwRaidMap->totalSize != 171 if (pFwRaidMap->totalSize !=
@@ -167,13 +182,16 @@ u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map,
167 return 0; 182 return 0;
168 } 183 }
169 184
185 if (instance->UnevenSpanSupport)
186 mr_update_span_set(map, ldSpanInfo);
187
170 mr_update_load_balance_params(map, lbInfo); 188 mr_update_load_balance_params(map, lbInfo);
171 189
172 return 1; 190 return 1;
173} 191}
174 192
175u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk, 193u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk,
176 struct MR_FW_RAID_MAP_ALL *map, int *div_error) 194 struct MR_FW_RAID_MAP_ALL *map)
177{ 195{
178 struct MR_SPAN_BLOCK_INFO *pSpanBlock = MR_LdSpanInfoGet(ld, map); 196 struct MR_SPAN_BLOCK_INFO *pSpanBlock = MR_LdSpanInfoGet(ld, map);
179 struct MR_QUAD_ELEMENT *quad; 197 struct MR_QUAD_ELEMENT *quad;
@@ -185,10 +203,8 @@ u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk,
185 for (j = 0; j < pSpanBlock->block_span_info.noElements; j++) { 203 for (j = 0; j < pSpanBlock->block_span_info.noElements; j++) {
186 quad = &pSpanBlock->block_span_info.quad[j]; 204 quad = &pSpanBlock->block_span_info.quad[j];
187 205
188 if (quad->diff == 0) { 206 if (quad->diff == 0)
189 *div_error = 1; 207 return SPAN_INVALID;
190 return span;
191 }
192 if (quad->logStart <= row && row <= quad->logEnd && 208 if (quad->logStart <= row && row <= quad->logEnd &&
193 (mega_mod64(row-quad->logStart, quad->diff)) == 0) { 209 (mega_mod64(row-quad->logStart, quad->diff)) == 0) {
194 if (span_blk != NULL) { 210 if (span_blk != NULL) {
@@ -207,7 +223,456 @@ u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk,
207 } 223 }
208 } 224 }
209 } 225 }
210 return span; 226 return SPAN_INVALID;
227}
228
229/*
230******************************************************************************
231*
232* Function to print info about span set created in driver from FW raid map
233*
234* Inputs :
235* map - LD map
236* ldSpanInfo - ldSpanInfo per HBA instance
237*/
238#if SPAN_DEBUG
239static int getSpanInfo(struct MR_FW_RAID_MAP_ALL *map, PLD_SPAN_INFO ldSpanInfo)
240{
241
242 u8 span;
243 u32 element;
244 struct MR_LD_RAID *raid;
245 LD_SPAN_SET *span_set;
246 struct MR_QUAD_ELEMENT *quad;
247 int ldCount;
248 u16 ld;
249
250 for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) {
251 ld = MR_TargetIdToLdGet(ldCount, map);
252 if (ld >= MAX_LOGICAL_DRIVES)
253 continue;
254 raid = MR_LdRaidGet(ld, map);
255 dev_dbg(&instance->pdev->dev, "LD %x: span_depth=%x\n",
256 ld, raid->spanDepth);
257 for (span = 0; span < raid->spanDepth; span++)
258 dev_dbg(&instance->pdev->dev, "Span=%x,"
259 " number of quads=%x\n", span,
260 map->raidMap.ldSpanMap[ld].spanBlock[span].
261 block_span_info.noElements);
262 for (element = 0; element < MAX_QUAD_DEPTH; element++) {
263 span_set = &(ldSpanInfo[ld].span_set[element]);
264 if (span_set->span_row_data_width == 0)
265 break;
266
267 dev_dbg(&instance->pdev->dev, "Span Set %x:"
268 "width=%x, diff=%x\n", element,
269 (unsigned int)span_set->span_row_data_width,
270 (unsigned int)span_set->diff);
271 dev_dbg(&instance->pdev->dev, "logical LBA"
272 "start=0x%08lx, end=0x%08lx\n",
273 (long unsigned int)span_set->log_start_lba,
274 (long unsigned int)span_set->log_end_lba);
275 dev_dbg(&instance->pdev->dev, "span row start=0x%08lx,"
276 " end=0x%08lx\n",
277 (long unsigned int)span_set->span_row_start,
278 (long unsigned int)span_set->span_row_end);
279 dev_dbg(&instance->pdev->dev, "data row start=0x%08lx,"
280 " end=0x%08lx\n",
281 (long unsigned int)span_set->data_row_start,
282 (long unsigned int)span_set->data_row_end);
283 dev_dbg(&instance->pdev->dev, "data strip start=0x%08lx,"
284 " end=0x%08lx\n",
285 (long unsigned int)span_set->data_strip_start,
286 (long unsigned int)span_set->data_strip_end);
287
288 for (span = 0; span < raid->spanDepth; span++) {
289 if (map->raidMap.ldSpanMap[ld].spanBlock[span].
290 block_span_info.noElements >=
291 element + 1) {
292 quad = &map->raidMap.ldSpanMap[ld].
293 spanBlock[span].block_span_info.
294 quad[element];
295 dev_dbg(&instance->pdev->dev, "Span=%x,"
296 "Quad=%x, diff=%x\n", span,
297 element, quad->diff);
298 dev_dbg(&instance->pdev->dev,
299 "offset_in_span=0x%08lx\n",
300 (long unsigned int)quad->offsetInSpan);
301 dev_dbg(&instance->pdev->dev,
302 "logical start=0x%08lx, end=0x%08lx\n",
303 (long unsigned int)quad->logStart,
304 (long unsigned int)quad->logEnd);
305 }
306 }
307 }
308 }
309 return 0;
310}
311#endif
312
313/*
314******************************************************************************
315*
316* This routine calculates the Span block for given row using spanset.
317*
318* Inputs :
319* instance - HBA instance
320* ld - Logical drive number
321* row - Row number
322* map - LD map
323*
324* Outputs :
325*
326* span - Span number
327* block - Absolute Block number in the physical disk
328* div_error - Devide error code.
329*/
330
331u32 mr_spanset_get_span_block(struct megasas_instance *instance,
332 u32 ld, u64 row, u64 *span_blk, struct MR_FW_RAID_MAP_ALL *map)
333{
334 struct fusion_context *fusion = instance->ctrl_context;
335 struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
336 LD_SPAN_SET *span_set;
337 struct MR_QUAD_ELEMENT *quad;
338 u32 span, info;
339 PLD_SPAN_INFO ldSpanInfo = fusion->log_to_span;
340
341 for (info = 0; info < MAX_QUAD_DEPTH; info++) {
342 span_set = &(ldSpanInfo[ld].span_set[info]);
343
344 if (span_set->span_row_data_width == 0)
345 break;
346
347 if (row > span_set->data_row_end)
348 continue;
349
350 for (span = 0; span < raid->spanDepth; span++)
351 if (map->raidMap.ldSpanMap[ld].spanBlock[span].
352 block_span_info.noElements >= info+1) {
353 quad = &map->raidMap.ldSpanMap[ld].
354 spanBlock[span].
355 block_span_info.quad[info];
356 if (quad->diff == 0)
357 return SPAN_INVALID;
358 if (quad->logStart <= row &&
359 row <= quad->logEnd &&
360 (mega_mod64(row - quad->logStart,
361 quad->diff)) == 0) {
362 if (span_blk != NULL) {
363 u64 blk;
364 blk = mega_div64_32
365 ((row - quad->logStart),
366 quad->diff);
367 blk = (blk + quad->offsetInSpan)
368 << raid->stripeShift;
369 *span_blk = blk;
370 }
371 return span;
372 }
373 }
374 }
375 return SPAN_INVALID;
376}
377
378/*
379******************************************************************************
380*
381* This routine calculates the row for given strip using spanset.
382*
383* Inputs :
384* instance - HBA instance
385* ld - Logical drive number
386* Strip - Strip
387* map - LD map
388*
389* Outputs :
390*
391* row - row associated with strip
392*/
393
394static u64 get_row_from_strip(struct megasas_instance *instance,
395 u32 ld, u64 strip, struct MR_FW_RAID_MAP_ALL *map)
396{
397 struct fusion_context *fusion = instance->ctrl_context;
398 struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
399 LD_SPAN_SET *span_set;
400 PLD_SPAN_INFO ldSpanInfo = fusion->log_to_span;
401 u32 info, strip_offset, span, span_offset;
402 u64 span_set_Strip, span_set_Row, retval;
403
404 for (info = 0; info < MAX_QUAD_DEPTH; info++) {
405 span_set = &(ldSpanInfo[ld].span_set[info]);
406
407 if (span_set->span_row_data_width == 0)
408 break;
409 if (strip > span_set->data_strip_end)
410 continue;
411
412 span_set_Strip = strip - span_set->data_strip_start;
413 strip_offset = mega_mod64(span_set_Strip,
414 span_set->span_row_data_width);
415 span_set_Row = mega_div64_32(span_set_Strip,
416 span_set->span_row_data_width) * span_set->diff;
417 for (span = 0, span_offset = 0; span < raid->spanDepth; span++)
418 if (map->raidMap.ldSpanMap[ld].spanBlock[span].
419 block_span_info.noElements >= info+1) {
420 if (strip_offset >=
421 span_set->strip_offset[span])
422 span_offset++;
423 else
424 break;
425 }
426#if SPAN_DEBUG
427 dev_info(&instance->pdev->dev, "Strip 0x%llx,"
428 "span_set_Strip 0x%llx, span_set_Row 0x%llx"
429 "data width 0x%llx span offset 0x%x\n", strip,
430 (unsigned long long)span_set_Strip,
431 (unsigned long long)span_set_Row,
432 (unsigned long long)span_set->span_row_data_width,
433 span_offset);
434 dev_info(&instance->pdev->dev, "For strip 0x%llx"
435 "row is 0x%llx\n", strip,
436 (unsigned long long) span_set->data_row_start +
437 (unsigned long long) span_set_Row + (span_offset - 1));
438#endif
439 retval = (span_set->data_row_start + span_set_Row +
440 (span_offset - 1));
441 return retval;
442 }
443 return -1LLU;
444}
445
446
447/*
448******************************************************************************
449*
450* This routine calculates the Start Strip for given row using spanset.
451*
452* Inputs :
453* instance - HBA instance
454* ld - Logical drive number
455* row - Row number
456* map - LD map
457*
458* Outputs :
459*
460* Strip - Start strip associated with row
461*/
462
463static u64 get_strip_from_row(struct megasas_instance *instance,
464 u32 ld, u64 row, struct MR_FW_RAID_MAP_ALL *map)
465{
466 struct fusion_context *fusion = instance->ctrl_context;
467 struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
468 LD_SPAN_SET *span_set;
469 struct MR_QUAD_ELEMENT *quad;
470 PLD_SPAN_INFO ldSpanInfo = fusion->log_to_span;
471 u32 span, info;
472 u64 strip;
473
474 for (info = 0; info < MAX_QUAD_DEPTH; info++) {
475 span_set = &(ldSpanInfo[ld].span_set[info]);
476
477 if (span_set->span_row_data_width == 0)
478 break;
479 if (row > span_set->data_row_end)
480 continue;
481
482 for (span = 0; span < raid->spanDepth; span++)
483 if (map->raidMap.ldSpanMap[ld].spanBlock[span].
484 block_span_info.noElements >= info+1) {
485 quad = &map->raidMap.ldSpanMap[ld].
486 spanBlock[span].block_span_info.quad[info];
487 if (quad->logStart <= row &&
488 row <= quad->logEnd &&
489 mega_mod64((row - quad->logStart),
490 quad->diff) == 0) {
491 strip = mega_div64_32
492 (((row - span_set->data_row_start)
493 - quad->logStart),
494 quad->diff);
495 strip *= span_set->span_row_data_width;
496 strip += span_set->data_strip_start;
497 strip += span_set->strip_offset[span];
498 return strip;
499 }
500 }
501 }
502 dev_err(&instance->pdev->dev, "get_strip_from_row"
503 "returns invalid strip for ld=%x, row=%lx\n",
504 ld, (long unsigned int)row);
505 return -1;
506}
507
508/*
509******************************************************************************
510*
511* This routine calculates the Physical Arm for given strip using spanset.
512*
513* Inputs :
514* instance - HBA instance
515* ld - Logical drive number
516* strip - Strip
517* map - LD map
518*
519* Outputs :
520*
521* Phys Arm - Phys Arm associated with strip
522*/
523
524static u32 get_arm_from_strip(struct megasas_instance *instance,
525 u32 ld, u64 strip, struct MR_FW_RAID_MAP_ALL *map)
526{
527 struct fusion_context *fusion = instance->ctrl_context;
528 struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
529 LD_SPAN_SET *span_set;
530 PLD_SPAN_INFO ldSpanInfo = fusion->log_to_span;
531 u32 info, strip_offset, span, span_offset, retval;
532
533 for (info = 0 ; info < MAX_QUAD_DEPTH; info++) {
534 span_set = &(ldSpanInfo[ld].span_set[info]);
535
536 if (span_set->span_row_data_width == 0)
537 break;
538 if (strip > span_set->data_strip_end)
539 continue;
540
541 strip_offset = (uint)mega_mod64
542 ((strip - span_set->data_strip_start),
543 span_set->span_row_data_width);
544
545 for (span = 0, span_offset = 0; span < raid->spanDepth; span++)
546 if (map->raidMap.ldSpanMap[ld].spanBlock[span].
547 block_span_info.noElements >= info+1) {
548 if (strip_offset >=
549 span_set->strip_offset[span])
550 span_offset =
551 span_set->strip_offset[span];
552 else
553 break;
554 }
555#if SPAN_DEBUG
556 dev_info(&instance->pdev->dev, "get_arm_from_strip:"
557 "for ld=0x%x strip=0x%lx arm is 0x%x\n", ld,
558 (long unsigned int)strip, (strip_offset - span_offset));
559#endif
560 retval = (strip_offset - span_offset);
561 return retval;
562 }
563
564 dev_err(&instance->pdev->dev, "get_arm_from_strip"
565 "returns invalid arm for ld=%x strip=%lx\n",
566 ld, (long unsigned int)strip);
567
568 return -1;
569}
570
571/* This Function will return Phys arm */
572u8 get_arm(struct megasas_instance *instance, u32 ld, u8 span, u64 stripe,
573 struct MR_FW_RAID_MAP_ALL *map)
574{
575 struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
576 /* Need to check correct default value */
577 u32 arm = 0;
578
579 switch (raid->level) {
580 case 0:
581 case 5:
582 case 6:
583 arm = mega_mod64(stripe, SPAN_ROW_SIZE(map, ld, span));
584 break;
585 case 1:
586 /* start with logical arm */
587 arm = get_arm_from_strip(instance, ld, stripe, map);
588 if (arm != -1UL)
589 arm *= 2;
590 break;
591 }
592
593 return arm;
594}
595
596
597/*
598******************************************************************************
599*
600* This routine calculates the arm, span and block for the specified stripe and
601* reference in stripe using spanset
602*
603* Inputs :
604*
605* ld - Logical drive number
606* stripRow - Stripe number
607* stripRef - Reference in stripe
608*
609* Outputs :
610*
611* span - Span number
612* block - Absolute Block number in the physical disk
613*/
614static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld,
615 u64 stripRow, u16 stripRef, struct IO_REQUEST_INFO *io_info,
616 struct RAID_CONTEXT *pRAID_Context,
617 struct MR_FW_RAID_MAP_ALL *map)
618{
619 struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
620 u32 pd, arRef;
621 u8 physArm, span;
622 u64 row;
623 u8 retval = TRUE;
624 u8 do_invader = 0;
625 u64 *pdBlock = &io_info->pdBlock;
626 u16 *pDevHandle = &io_info->devHandle;
627 u32 logArm, rowMod, armQ, arm;
628
629 if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER ||
630 instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
631 do_invader = 1;
632
633 /*Get row and span from io_info for Uneven Span IO.*/
634 row = io_info->start_row;
635 span = io_info->start_span;
636
637
638 if (raid->level == 6) {
639 logArm = get_arm_from_strip(instance, ld, stripRow, map);
640 if (logArm == -1UL)
641 return FALSE;
642 rowMod = mega_mod64(row, SPAN_ROW_SIZE(map, ld, span));
643 armQ = SPAN_ROW_SIZE(map, ld, span) - 1 - rowMod;
644 arm = armQ + 1 + logArm;
645 if (arm >= SPAN_ROW_SIZE(map, ld, span))
646 arm -= SPAN_ROW_SIZE(map, ld, span);
647 physArm = (u8)arm;
648 } else
649 /* Calculate the arm */
650 physArm = get_arm(instance, ld, span, stripRow, map);
651 if (physArm == 0xFF)
652 return FALSE;
653
654 arRef = MR_LdSpanArrayGet(ld, span, map);
655 pd = MR_ArPdGet(arRef, physArm, map);
656
657 if (pd != MR_PD_INVALID)
658 *pDevHandle = MR_PdDevHandleGet(pd, map);
659 else {
660 *pDevHandle = MR_PD_INVALID;
661 if ((raid->level >= 5) &&
662 (!do_invader || (do_invader &&
663 (raid->regTypeReqOnRead != REGION_TYPE_UNUSED))))
664 pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE;
665 else if (raid->level == 1) {
666 pd = MR_ArPdGet(arRef, physArm + 1, map);
667 if (pd != MR_PD_INVALID)
668 *pDevHandle = MR_PdDevHandleGet(pd, map);
669 }
670 }
671
672 *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk;
673 pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) |
674 physArm;
675 return retval;
211} 676}
212 677
213/* 678/*
@@ -228,17 +693,18 @@ u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk,
228* block - Absolute Block number in the physical disk 693* block - Absolute Block number in the physical disk
229*/ 694*/
230u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow, 695u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
231 u16 stripRef, u64 *pdBlock, u16 *pDevHandle, 696 u16 stripRef, struct IO_REQUEST_INFO *io_info,
232 struct RAID_CONTEXT *pRAID_Context, 697 struct RAID_CONTEXT *pRAID_Context,
233 struct MR_FW_RAID_MAP_ALL *map) 698 struct MR_FW_RAID_MAP_ALL *map)
234{ 699{
235 struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 700 struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
236 u32 pd, arRef; 701 u32 pd, arRef;
237 u8 physArm, span; 702 u8 physArm, span;
238 u64 row; 703 u64 row;
239 u8 retval = TRUE; 704 u8 retval = TRUE;
240 int error_code = 0;
241 u8 do_invader = 0; 705 u8 do_invader = 0;
706 u64 *pdBlock = &io_info->pdBlock;
707 u16 *pDevHandle = &io_info->devHandle;
242 708
243 if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER || 709 if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER ||
244 instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) 710 instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
@@ -272,8 +738,8 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
272 span = 0; 738 span = 0;
273 *pdBlock = row << raid->stripeShift; 739 *pdBlock = row << raid->stripeShift;
274 } else { 740 } else {
275 span = (u8)MR_GetSpanBlock(ld, row, pdBlock, map, &error_code); 741 span = (u8)MR_GetSpanBlock(ld, row, pdBlock, map);
276 if (error_code == 1) 742 if (span == SPAN_INVALID)
277 return FALSE; 743 return FALSE;
278 } 744 }
279 745
@@ -331,17 +797,42 @@ MR_BuildRaidContext(struct megasas_instance *instance,
331 u32 numBlocks, ldTgtId; 797 u32 numBlocks, ldTgtId;
332 u8 isRead; 798 u8 isRead;
333 u8 retval = 0; 799 u8 retval = 0;
800 u8 startlba_span = SPAN_INVALID;
801 u64 *pdBlock = &io_info->pdBlock;
334 802
335 ldStartBlock = io_info->ldStartBlock; 803 ldStartBlock = io_info->ldStartBlock;
336 numBlocks = io_info->numBlocks; 804 numBlocks = io_info->numBlocks;
337 ldTgtId = io_info->ldTgtId; 805 ldTgtId = io_info->ldTgtId;
338 isRead = io_info->isRead; 806 isRead = io_info->isRead;
807 io_info->IoforUnevenSpan = 0;
808 io_info->start_span = SPAN_INVALID;
339 809
340 ld = MR_TargetIdToLdGet(ldTgtId, map); 810 ld = MR_TargetIdToLdGet(ldTgtId, map);
341 raid = MR_LdRaidGet(ld, map); 811 raid = MR_LdRaidGet(ld, map);
342 812
813 /*
814 * if rowDataSize @RAID map and spanRowDataSize @SPAN INFO are zero
815 * return FALSE
816 */
817 if (raid->rowDataSize == 0) {
818 if (MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize == 0)
819 return FALSE;
820 else if (instance->UnevenSpanSupport) {
821 io_info->IoforUnevenSpan = 1;
822 } else {
823 dev_info(&instance->pdev->dev,
824 "raid->rowDataSize is 0, but has SPAN[0]"
825 "rowDataSize = 0x%0x,"
826 "but there is _NO_ UnevenSpanSupport\n",
827 MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize);
828 return FALSE;
829 }
830 }
831
343 stripSize = 1 << raid->stripeShift; 832 stripSize = 1 << raid->stripeShift;
344 stripe_mask = stripSize-1; 833 stripe_mask = stripSize-1;
834
835
345 /* 836 /*
346 * calculate starting row and stripe, and number of strips and rows 837 * calculate starting row and stripe, and number of strips and rows
347 */ 838 */
@@ -351,11 +842,50 @@ MR_BuildRaidContext(struct megasas_instance *instance,
351 ref_in_end_stripe = (u16)(endLba & stripe_mask); 842 ref_in_end_stripe = (u16)(endLba & stripe_mask);
352 endStrip = endLba >> raid->stripeShift; 843 endStrip = endLba >> raid->stripeShift;
353 num_strips = (u8)(endStrip - start_strip + 1); /* End strip */ 844 num_strips = (u8)(endStrip - start_strip + 1); /* End strip */
354 if (raid->rowDataSize == 0) 845
355 return FALSE; 846 if (io_info->IoforUnevenSpan) {
356 start_row = mega_div64_32(start_strip, raid->rowDataSize); 847 start_row = get_row_from_strip(instance, ld, start_strip, map);
357 endRow = mega_div64_32(endStrip, raid->rowDataSize); 848 endRow = get_row_from_strip(instance, ld, endStrip, map);
358 numRows = (u8)(endRow - start_row + 1); 849 if (start_row == -1ULL || endRow == -1ULL) {
850 dev_info(&instance->pdev->dev, "return from %s %d."
851 "Send IO w/o region lock.\n",
852 __func__, __LINE__);
853 return FALSE;
854 }
855
856 if (raid->spanDepth == 1) {
857 startlba_span = 0;
858 *pdBlock = start_row << raid->stripeShift;
859 } else
860 startlba_span = (u8)mr_spanset_get_span_block(instance,
861 ld, start_row, pdBlock, map);
862 if (startlba_span == SPAN_INVALID) {
863 dev_info(&instance->pdev->dev, "return from %s %d"
864 "for row 0x%llx,start strip %llx"
865 "endSrip %llx\n", __func__, __LINE__,
866 (unsigned long long)start_row,
867 (unsigned long long)start_strip,
868 (unsigned long long)endStrip);
869 return FALSE;
870 }
871 io_info->start_span = startlba_span;
872 io_info->start_row = start_row;
873#if SPAN_DEBUG
874 dev_dbg(&instance->pdev->dev, "Check Span number from %s %d"
875 "for row 0x%llx, start strip 0x%llx end strip 0x%llx"
876 " span 0x%x\n", __func__, __LINE__,
877 (unsigned long long)start_row,
878 (unsigned long long)start_strip,
879 (unsigned long long)endStrip, startlba_span);
880 dev_dbg(&instance->pdev->dev, "start_row 0x%llx endRow 0x%llx"
881 "Start span 0x%x\n", (unsigned long long)start_row,
882 (unsigned long long)endRow, startlba_span);
883#endif
884 } else {
885 start_row = mega_div64_32(start_strip, raid->rowDataSize);
886 endRow = mega_div64_32(endStrip, raid->rowDataSize);
887 }
888 numRows = (u8)(endRow - start_row + 1);
359 889
360 /* 890 /*
361 * calculate region info. 891 * calculate region info.
@@ -388,24 +918,51 @@ MR_BuildRaidContext(struct megasas_instance *instance,
388 regSize = numBlocks; 918 regSize = numBlocks;
389 } 919 }
390 /* multi-strip IOs always need to full stripe locked */ 920 /* multi-strip IOs always need to full stripe locked */
391 } else { 921 } else if (io_info->IoforUnevenSpan == 0) {
922 /*
923 * For Even span region lock optimization.
924 * If the start strip is the last in the start row
925 */
392 if (start_strip == (start_row + 1) * raid->rowDataSize - 1) { 926 if (start_strip == (start_row + 1) * raid->rowDataSize - 1) {
393 /* If the start strip is the last in the start row */
394 regStart += ref_in_start_stripe; 927 regStart += ref_in_start_stripe;
395 regSize = stripSize - ref_in_start_stripe;
396 /* initialize count to sectors from startref to end 928 /* initialize count to sectors from startref to end
397 of strip */ 929 of strip */
930 regSize = stripSize - ref_in_start_stripe;
398 } 931 }
399 932
933 /* add complete rows in the middle of the transfer */
400 if (numRows > 2) 934 if (numRows > 2)
401 /* Add complete rows in the middle of the transfer */
402 regSize += (numRows-2) << raid->stripeShift; 935 regSize += (numRows-2) << raid->stripeShift;
403 936
404 /* if IO ends within first strip of last row */ 937 /* if IO ends within first strip of last row*/
405 if (endStrip == endRow*raid->rowDataSize) 938 if (endStrip == endRow*raid->rowDataSize)
406 regSize += ref_in_end_stripe+1; 939 regSize += ref_in_end_stripe+1;
407 else 940 else
408 regSize += stripSize; 941 regSize += stripSize;
942 } else {
943 /*
944 * For Uneven span region lock optimization.
945 * If the start strip is the last in the start row
946 */
947 if (start_strip == (get_strip_from_row(instance, ld, start_row, map) +
948 SPAN_ROW_DATA_SIZE(map, ld, startlba_span) - 1)) {
949 regStart += ref_in_start_stripe;
950 /* initialize count to sectors from
951 * startRef to end of strip
952 */
953 regSize = stripSize - ref_in_start_stripe;
954 }
955 /* Add complete rows in the middle of the transfer*/
956
957 if (numRows > 2)
958 /* Add complete rows in the middle of the transfer*/
959 regSize += (numRows-2) << raid->stripeShift;
960
961 /* if IO ends within first strip of last row */
962 if (endStrip == get_strip_from_row(instance, ld, endRow, map))
963 regSize += ref_in_end_stripe + 1;
964 else
965 regSize += stripSize;
409 } 966 }
410 967
411 pRAID_Context->timeoutValue = map->raidMap.fpPdIoTimeoutSec; 968 pRAID_Context->timeoutValue = map->raidMap.fpPdIoTimeoutSec;
@@ -424,30 +981,161 @@ MR_BuildRaidContext(struct megasas_instance *instance,
424 /*Get Phy Params only if FP capable, or else leave it to MR firmware 981 /*Get Phy Params only if FP capable, or else leave it to MR firmware
425 to do the calculation.*/ 982 to do the calculation.*/
426 if (io_info->fpOkForIo) { 983 if (io_info->fpOkForIo) {
427 retval = MR_GetPhyParams(instance, ld, start_strip, 984 retval = io_info->IoforUnevenSpan ?
428 ref_in_start_stripe, 985 mr_spanset_get_phy_params(instance, ld,
429 &io_info->pdBlock, 986 start_strip, ref_in_start_stripe,
430 &io_info->devHandle, pRAID_Context, 987 io_info, pRAID_Context, map) :
431 map); 988 MR_GetPhyParams(instance, ld, start_strip,
432 /* If IO on an invalid Pd, then FP i snot possible */ 989 ref_in_start_stripe, io_info,
990 pRAID_Context, map);
991 /* If IO on an invalid Pd, then FP is not possible.*/
433 if (io_info->devHandle == MR_PD_INVALID) 992 if (io_info->devHandle == MR_PD_INVALID)
434 io_info->fpOkForIo = FALSE; 993 io_info->fpOkForIo = FALSE;
435 return retval; 994 return retval;
436 } else if (isRead) { 995 } else if (isRead) {
437 uint stripIdx; 996 uint stripIdx;
438 for (stripIdx = 0; stripIdx < num_strips; stripIdx++) { 997 for (stripIdx = 0; stripIdx < num_strips; stripIdx++) {
439 if (!MR_GetPhyParams(instance, ld, 998 retval = io_info->IoforUnevenSpan ?
440 start_strip + stripIdx, 999 mr_spanset_get_phy_params(instance, ld,
441 ref_in_start_stripe, 1000 start_strip + stripIdx,
442 &io_info->pdBlock, 1001 ref_in_start_stripe, io_info,
443 &io_info->devHandle, 1002 pRAID_Context, map) :
444 pRAID_Context, map)) 1003 MR_GetPhyParams(instance, ld,
1004 start_strip + stripIdx, ref_in_start_stripe,
1005 io_info, pRAID_Context, map);
1006 if (!retval)
445 return TRUE; 1007 return TRUE;
446 } 1008 }
447 } 1009 }
1010
1011#if SPAN_DEBUG
1012 /* Just for testing what arm we get for strip.*/
1013 if (io_info->IoforUnevenSpan)
1014 get_arm_from_strip(instance, ld, start_strip, map);
1015#endif
448 return TRUE; 1016 return TRUE;
449} 1017}
450 1018
1019/*
1020******************************************************************************
1021*
1022* This routine pepare spanset info from Valid Raid map and store it into
1023* local copy of ldSpanInfo per instance data structure.
1024*
1025* Inputs :
1026* map - LD map
1027* ldSpanInfo - ldSpanInfo per HBA instance
1028*
1029*/
1030void mr_update_span_set(struct MR_FW_RAID_MAP_ALL *map,
1031 PLD_SPAN_INFO ldSpanInfo)
1032{
1033 u8 span, count;
1034 u32 element, span_row_width;
1035 u64 span_row;
1036 struct MR_LD_RAID *raid;
1037 LD_SPAN_SET *span_set, *span_set_prev;
1038 struct MR_QUAD_ELEMENT *quad;
1039 int ldCount;
1040 u16 ld;
1041
1042
1043 for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) {
1044 ld = MR_TargetIdToLdGet(ldCount, map);
1045 if (ld >= MAX_LOGICAL_DRIVES)
1046 continue;
1047 raid = MR_LdRaidGet(ld, map);
1048 for (element = 0; element < MAX_QUAD_DEPTH; element++) {
1049 for (span = 0; span < raid->spanDepth; span++) {
1050 if (map->raidMap.ldSpanMap[ld].spanBlock[span].
1051 block_span_info.noElements <
1052 element + 1)
1053 continue;
1054 span_set = &(ldSpanInfo[ld].span_set[element]);
1055 quad = &map->raidMap.ldSpanMap[ld].
1056 spanBlock[span].block_span_info.
1057 quad[element];
1058
1059 span_set->diff = quad->diff;
1060
1061 for (count = 0, span_row_width = 0;
1062 count < raid->spanDepth; count++) {
1063 if (map->raidMap.ldSpanMap[ld].
1064 spanBlock[count].
1065 block_span_info.
1066 noElements >= element + 1) {
1067 span_set->strip_offset[count] =
1068 span_row_width;
1069 span_row_width +=
1070 MR_LdSpanPtrGet
1071 (ld, count, map)->spanRowDataSize;
1072 printk(KERN_INFO "megasas:"
1073 "span %x rowDataSize %x\n",
1074 count, MR_LdSpanPtrGet
1075 (ld, count, map)->spanRowDataSize);
1076 }
1077 }
1078
1079 span_set->span_row_data_width = span_row_width;
1080 span_row = mega_div64_32(((quad->logEnd -
1081 quad->logStart) + quad->diff),
1082 quad->diff);
1083
1084 if (element == 0) {
1085 span_set->log_start_lba = 0;
1086 span_set->log_end_lba =
1087 ((span_row << raid->stripeShift)
1088 * span_row_width) - 1;
1089
1090 span_set->span_row_start = 0;
1091 span_set->span_row_end = span_row - 1;
1092
1093 span_set->data_strip_start = 0;
1094 span_set->data_strip_end =
1095 (span_row * span_row_width) - 1;
1096
1097 span_set->data_row_start = 0;
1098 span_set->data_row_end =
1099 (span_row * quad->diff) - 1;
1100 } else {
1101 span_set_prev = &(ldSpanInfo[ld].
1102 span_set[element - 1]);
1103 span_set->log_start_lba =
1104 span_set_prev->log_end_lba + 1;
1105 span_set->log_end_lba =
1106 span_set->log_start_lba +
1107 ((span_row << raid->stripeShift)
1108 * span_row_width) - 1;
1109
1110 span_set->span_row_start =
1111 span_set_prev->span_row_end + 1;
1112 span_set->span_row_end =
1113 span_set->span_row_start + span_row - 1;
1114
1115 span_set->data_strip_start =
1116 span_set_prev->data_strip_end + 1;
1117 span_set->data_strip_end =
1118 span_set->data_strip_start +
1119 (span_row * span_row_width) - 1;
1120
1121 span_set->data_row_start =
1122 span_set_prev->data_row_end + 1;
1123 span_set->data_row_end =
1124 span_set->data_row_start +
1125 (span_row * quad->diff) - 1;
1126 }
1127 break;
1128 }
1129 if (span == raid->spanDepth)
1130 break;
1131 }
1132 }
1133#if SPAN_DEBUG
1134 getSpanInfo(map, ldSpanInfo);
1135#endif
1136
1137}
1138
451void 1139void
452mr_update_load_balance_params(struct MR_FW_RAID_MAP_ALL *map, 1140mr_update_load_balance_params(struct MR_FW_RAID_MAP_ALL *map,
453 struct LD_LOAD_BALANCE_INFO *lbInfo) 1141 struct LD_LOAD_BALANCE_INFO *lbInfo)
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index 748b8ac5e1c3..417d5f167aa2 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -86,8 +86,6 @@ u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map);
86void 86void
87megasas_check_and_restore_queue_depth(struct megasas_instance *instance); 87megasas_check_and_restore_queue_depth(struct megasas_instance *instance);
88 88
89u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map,
90 struct LD_LOAD_BALANCE_INFO *lbInfo);
91u16 get_updated_dev_handle(struct LD_LOAD_BALANCE_INFO *lbInfo, 89u16 get_updated_dev_handle(struct LD_LOAD_BALANCE_INFO *lbInfo,
92 struct IO_REQUEST_INFO *in_info); 90 struct IO_REQUEST_INFO *in_info);
93int megasas_transition_to_ready(struct megasas_instance *instance, int ocr); 91int megasas_transition_to_ready(struct megasas_instance *instance, int ocr);
@@ -782,8 +780,7 @@ megasas_get_map_info(struct megasas_instance *instance)
782 780
783 fusion->fast_path_io = 0; 781 fusion->fast_path_io = 0;
784 if (!megasas_get_ld_map_info(instance)) { 782 if (!megasas_get_ld_map_info(instance)) {
785 if (MR_ValidateMapInfo(fusion->ld_map[(instance->map_id & 1)], 783 if (MR_ValidateMapInfo(instance)) {
786 fusion->load_balance_info)) {
787 fusion->fast_path_io = 1; 784 fusion->fast_path_io = 1;
788 return 0; 785 return 0;
789 } 786 }
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h
index 004c18e408c1..12ff01cf6799 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.h
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h
@@ -463,6 +463,7 @@ struct MPI2_IOC_INIT_REQUEST {
463/* mrpriv defines */ 463/* mrpriv defines */
464#define MR_PD_INVALID 0xFFFF 464#define MR_PD_INVALID 0xFFFF
465#define MAX_SPAN_DEPTH 8 465#define MAX_SPAN_DEPTH 8
466#define MAX_QUAD_DEPTH MAX_SPAN_DEPTH
466#define MAX_RAIDMAP_SPAN_DEPTH (MAX_SPAN_DEPTH) 467#define MAX_RAIDMAP_SPAN_DEPTH (MAX_SPAN_DEPTH)
467#define MAX_ROW_SIZE 32 468#define MAX_ROW_SIZE 32
468#define MAX_RAIDMAP_ROW_SIZE (MAX_ROW_SIZE) 469#define MAX_RAIDMAP_ROW_SIZE (MAX_ROW_SIZE)
@@ -504,7 +505,9 @@ struct MR_LD_SPAN {
504 u64 startBlk; 505 u64 startBlk;
505 u64 numBlks; 506 u64 numBlks;
506 u16 arrayRef; 507 u16 arrayRef;
507 u8 reserved[6]; 508 u8 spanRowSize;
509 u8 spanRowDataSize;
510 u8 reserved[4];
508}; 511};
509 512
510struct MR_SPAN_BLOCK_INFO { 513struct MR_SPAN_BLOCK_INFO {
@@ -590,6 +593,10 @@ struct IO_REQUEST_INFO {
590 u16 devHandle; 593 u16 devHandle;
591 u64 pdBlock; 594 u64 pdBlock;
592 u8 fpOkForIo; 595 u8 fpOkForIo;
596 u8 IoforUnevenSpan;
597 u8 start_span;
598 u8 reserved;
599 u64 start_row;
593}; 600};
594 601
595struct MR_LD_TARGET_SYNC { 602struct MR_LD_TARGET_SYNC {
@@ -651,6 +658,26 @@ struct LD_LOAD_BALANCE_INFO {
651 u64 last_accessed_block[2]; 658 u64 last_accessed_block[2];
652}; 659};
653 660
661/* SPAN_SET is info caclulated from span info from Raid map per LD */
662typedef struct _LD_SPAN_SET {
663 u64 log_start_lba;
664 u64 log_end_lba;
665 u64 span_row_start;
666 u64 span_row_end;
667 u64 data_strip_start;
668 u64 data_strip_end;
669 u64 data_row_start;
670 u64 data_row_end;
671 u8 strip_offset[MAX_SPAN_DEPTH];
672 u32 span_row_data_width;
673 u32 diff;
674 u32 reserved[2];
675} LD_SPAN_SET, *PLD_SPAN_SET;
676
677typedef struct LOG_BLOCK_SPAN_INFO {
678 LD_SPAN_SET span_set[MAX_SPAN_DEPTH];
679} LD_SPAN_INFO, *PLD_SPAN_INFO;
680
654struct MR_FW_RAID_MAP_ALL { 681struct MR_FW_RAID_MAP_ALL {
655 struct MR_FW_RAID_MAP raidMap; 682 struct MR_FW_RAID_MAP raidMap;
656 struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES - 1]; 683 struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES - 1];
@@ -695,6 +722,7 @@ struct fusion_context {
695 u32 map_sz; 722 u32 map_sz;
696 u8 fast_path_io; 723 u8 fast_path_io;
697 struct LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES]; 724 struct LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES];
725 LD_SPAN_INFO log_to_span[MAX_LOGICAL_DRIVES];
698}; 726};
699 727
700union desc_value { 728union desc_value {