1*665484d8SDoug Ambrisko /* 2*665484d8SDoug Ambrisko * Copyright (c) 2014, LSI Corp. 3*665484d8SDoug Ambrisko * All rights reserved. 4*665484d8SDoug Ambrisko * Author: Marian Choy 5*665484d8SDoug Ambrisko * Support: freebsdraid@lsi.com 6*665484d8SDoug Ambrisko * 7*665484d8SDoug Ambrisko * Redistribution and use in source and binary forms, with or without 8*665484d8SDoug Ambrisko * modification, are permitted provided that the following conditions 9*665484d8SDoug Ambrisko * are met: 10*665484d8SDoug Ambrisko * 11*665484d8SDoug Ambrisko * 1. Redistributions of source code must retain the above copyright 12*665484d8SDoug Ambrisko * notice, this list of conditions and the following disclaimer. 13*665484d8SDoug Ambrisko * 2. Redistributions in binary form must reproduce the above copyright 14*665484d8SDoug Ambrisko * notice, this list of conditions and the following disclaimer in 15*665484d8SDoug Ambrisko * the documentation and/or other materials provided with the 16*665484d8SDoug Ambrisko * distribution. 17*665484d8SDoug Ambrisko * 3. Neither the name of the <ORGANIZATION> nor the names of its 18*665484d8SDoug Ambrisko * contributors may be used to endorse or promote products derived 19*665484d8SDoug Ambrisko * from this software without specific prior written permission. 20*665484d8SDoug Ambrisko * 21*665484d8SDoug Ambrisko * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22*665484d8SDoug Ambrisko * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23*665484d8SDoug Ambrisko * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24*665484d8SDoug Ambrisko * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25*665484d8SDoug Ambrisko * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26*665484d8SDoug Ambrisko * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27*665484d8SDoug Ambrisko * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28*665484d8SDoug Ambrisko * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29*665484d8SDoug Ambrisko * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30*665484d8SDoug Ambrisko * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31*665484d8SDoug Ambrisko * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32*665484d8SDoug Ambrisko * POSSIBILITY OF SUCH DAMAGE. 33*665484d8SDoug Ambrisko * 34*665484d8SDoug Ambrisko * The views and conclusions contained in the software and documentation 35*665484d8SDoug Ambrisko * are those of the authors and should not be interpreted as representing 36*665484d8SDoug Ambrisko * official policies,either expressed or implied, of the FreeBSD Project. 37*665484d8SDoug Ambrisko * 38*665484d8SDoug Ambrisko * Send feedback to: <megaraidfbsd@lsi.com> 39*665484d8SDoug Ambrisko * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035 40*665484d8SDoug Ambrisko * ATTN: MegaRaid FreeBSD 41*665484d8SDoug Ambrisko * 42*665484d8SDoug Ambrisko */ 43*665484d8SDoug Ambrisko 44*665484d8SDoug Ambrisko #include <sys/cdefs.h> 45*665484d8SDoug Ambrisko __FBSDID("$FreeBSD$"); 46*665484d8SDoug Ambrisko 47*665484d8SDoug Ambrisko #include <dev/mrsas/mrsas.h> 48*665484d8SDoug Ambrisko 49*665484d8SDoug Ambrisko #include <cam/cam.h> 50*665484d8SDoug Ambrisko #include <cam/cam_ccb.h> 51*665484d8SDoug Ambrisko #include <cam/cam_sim.h> 52*665484d8SDoug Ambrisko #include <cam/cam_xpt_sim.h> 53*665484d8SDoug Ambrisko #include <cam/cam_debug.h> 54*665484d8SDoug Ambrisko #include <cam/cam_periph.h> 55*665484d8SDoug Ambrisko #include <cam/cam_xpt_periph.h> 56*665484d8SDoug Ambrisko 57*665484d8SDoug Ambrisko 58*665484d8SDoug Ambrisko /* 59*665484d8SDoug Ambrisko * Function prototypes 60*665484d8SDoug Ambrisko */ 61*665484d8SDoug Ambrisko u_int8_t MR_ValidateMapInfo(struct mrsas_softc *sc); 62*665484d8SDoug Ambrisko u_int8_t mrsas_get_best_arm(PLD_LOAD_BALANCE_INFO lbInfo, u_int8_t arm, 63*665484d8SDoug Ambrisko u_int64_t block, u_int32_t count); 64*665484d8SDoug Ambrisko u_int8_t MR_BuildRaidContext(struct mrsas_softc *sc, 65*665484d8SDoug Ambrisko struct IO_REQUEST_INFO *io_info, 66*665484d8SDoug Ambrisko RAID_CONTEXT *pRAID_Context, MR_FW_RAID_MAP_ALL *map); 67*665484d8SDoug Ambrisko u_int8_t MR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld, 68*665484d8SDoug Ambrisko u_int64_t stripRow, u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 69*665484d8SDoug Ambrisko RAID_CONTEXT *pRAID_Context, 70*665484d8SDoug Ambrisko MR_FW_RAID_MAP_ALL *map); 71*665484d8SDoug Ambrisko u_int16_t MR_TargetIdToLdGet(u_int32_t ldTgtId, MR_FW_RAID_MAP_ALL *map); 72*665484d8SDoug Ambrisko u_int32_t MR_LdBlockSizeGet(u_int32_t ldTgtId, MR_FW_RAID_MAP_ALL *map); 73*665484d8SDoug Ambrisko u_int16_t MR_GetLDTgtId(u_int32_t ld, MR_FW_RAID_MAP_ALL *map); 74*665484d8SDoug Ambrisko u_int16_t mrsas_get_updated_dev_handle(PLD_LOAD_BALANCE_INFO lbInfo, 75*665484d8SDoug Ambrisko struct IO_REQUEST_INFO *io_info); 76*665484d8SDoug Ambrisko u_int32_t mega_mod64(u_int64_t dividend, u_int32_t divisor); 77*665484d8SDoug Ambrisko u_int32_t MR_GetSpanBlock(u_int32_t ld, u_int64_t row, u_int64_t *span_blk, 78*665484d8SDoug Ambrisko MR_FW_RAID_MAP_ALL *map, int *div_error); 79*665484d8SDoug Ambrisko u_int64_t mega_div64_32(u_int64_t dividend, u_int32_t divisor); 80*665484d8SDoug Ambrisko void mrsas_update_load_balance_params(MR_FW_RAID_MAP_ALL *map, 81*665484d8SDoug Ambrisko PLD_LOAD_BALANCE_INFO lbInfo); 82*665484d8SDoug Ambrisko void mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST *io_request, 83*665484d8SDoug Ambrisko u_int8_t cdb_len, struct IO_REQUEST_INFO *io_info, union ccb *ccb, 84*665484d8SDoug Ambrisko MR_FW_RAID_MAP_ALL *local_map_ptr, u_int32_t ref_tag, 85*665484d8SDoug Ambrisko u_int32_t ld_block_size); 86*665484d8SDoug Ambrisko static u_int16_t MR_LdSpanArrayGet(u_int32_t ld, u_int32_t span, 87*665484d8SDoug Ambrisko MR_FW_RAID_MAP_ALL *map); 88*665484d8SDoug Ambrisko static u_int16_t MR_PdDevHandleGet(u_int32_t pd, MR_FW_RAID_MAP_ALL *map); 89*665484d8SDoug Ambrisko static u_int16_t MR_ArPdGet(u_int32_t ar, u_int32_t arm, 90*665484d8SDoug Ambrisko MR_FW_RAID_MAP_ALL *map); 91*665484d8SDoug Ambrisko static MR_LD_SPAN *MR_LdSpanPtrGet(u_int32_t ld, u_int32_t span, 92*665484d8SDoug Ambrisko MR_FW_RAID_MAP_ALL *map); 93*665484d8SDoug Ambrisko static u_int8_t MR_LdDataArmGet(u_int32_t ld, u_int32_t armIdx, 94*665484d8SDoug Ambrisko MR_FW_RAID_MAP_ALL *map); 95*665484d8SDoug Ambrisko static MR_SPAN_BLOCK_INFO *MR_LdSpanInfoGet(u_int32_t ld, 96*665484d8SDoug Ambrisko MR_FW_RAID_MAP_ALL *map); 97*665484d8SDoug Ambrisko MR_LD_RAID *MR_LdRaidGet(u_int32_t ld, MR_FW_RAID_MAP_ALL *map); 98*665484d8SDoug Ambrisko 99*665484d8SDoug Ambrisko /* 100*665484d8SDoug Ambrisko * Spanset related function prototypes 101*665484d8SDoug Ambrisko * Added for PRL11 configuration (Uneven span support) 102*665484d8SDoug Ambrisko */ 103*665484d8SDoug Ambrisko void mr_update_span_set(MR_FW_RAID_MAP_ALL *map, PLD_SPAN_INFO ldSpanInfo); 104*665484d8SDoug Ambrisko static u_int8_t mr_spanset_get_phy_params(struct mrsas_softc *sc, u_int32_t ld, 105*665484d8SDoug Ambrisko u_int64_t stripRow, u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 106*665484d8SDoug Ambrisko RAID_CONTEXT *pRAID_Context, MR_FW_RAID_MAP_ALL *map); 107*665484d8SDoug Ambrisko static u_int64_t get_row_from_strip(struct mrsas_softc *sc, u_int32_t ld, 108*665484d8SDoug Ambrisko u_int64_t strip, MR_FW_RAID_MAP_ALL *map); 109*665484d8SDoug Ambrisko static u_int32_t mr_spanset_get_span_block(struct mrsas_softc *sc, 110*665484d8SDoug Ambrisko u_int32_t ld, u_int64_t row, u_int64_t *span_blk, 111*665484d8SDoug Ambrisko MR_FW_RAID_MAP_ALL *map, int *div_error); 112*665484d8SDoug Ambrisko static u_int8_t get_arm(struct mrsas_softc *sc, u_int32_t ld, u_int8_t span, 113*665484d8SDoug Ambrisko u_int64_t stripe, MR_FW_RAID_MAP_ALL *map); 114*665484d8SDoug Ambrisko 115*665484d8SDoug Ambrisko 116*665484d8SDoug Ambrisko /* 117*665484d8SDoug Ambrisko * Spanset related defines 118*665484d8SDoug Ambrisko * Added for PRL11 configuration(Uneven span support) 119*665484d8SDoug Ambrisko */ 120*665484d8SDoug Ambrisko #define SPAN_ROW_SIZE(map, ld, index_) MR_LdSpanPtrGet(ld, index_, map)->spanRowSize 121*665484d8SDoug Ambrisko #define SPAN_ROW_DATA_SIZE(map_, ld, index_) MR_LdSpanPtrGet(ld, index_, map)->spanRowDataSize 122*665484d8SDoug Ambrisko #define SPAN_INVALID 0xff 123*665484d8SDoug Ambrisko #define SPAN_DEBUG 0 124*665484d8SDoug Ambrisko 125*665484d8SDoug Ambrisko /* 126*665484d8SDoug Ambrisko * Related Defines 127*665484d8SDoug Ambrisko */ 128*665484d8SDoug Ambrisko 129*665484d8SDoug Ambrisko typedef u_int64_t REGION_KEY; 130*665484d8SDoug Ambrisko typedef u_int32_t REGION_LEN; 131*665484d8SDoug Ambrisko 132*665484d8SDoug Ambrisko #define MR_LD_STATE_OPTIMAL 3 133*665484d8SDoug Ambrisko #define FALSE 0 134*665484d8SDoug Ambrisko #define TRUE 1 135*665484d8SDoug Ambrisko 136*665484d8SDoug Ambrisko 137*665484d8SDoug Ambrisko /* 138*665484d8SDoug Ambrisko * Related Macros 139*665484d8SDoug Ambrisko */ 140*665484d8SDoug Ambrisko 141*665484d8SDoug Ambrisko #define ABS_DIFF(a,b) ( ((a) > (b)) ? ((a) - (b)) : ((b) - (a)) ) 142*665484d8SDoug Ambrisko 143*665484d8SDoug Ambrisko #define swap32(x) \ 144*665484d8SDoug Ambrisko ((unsigned int)( \ 145*665484d8SDoug Ambrisko (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \ 146*665484d8SDoug Ambrisko (((unsigned int)(x) & (unsigned int)0x0000ff00UL) << 8) | \ 147*665484d8SDoug Ambrisko (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >> 8) | \ 148*665484d8SDoug Ambrisko (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) )) 149*665484d8SDoug Ambrisko 150*665484d8SDoug Ambrisko 151*665484d8SDoug Ambrisko /* 152*665484d8SDoug Ambrisko * In-line functions for mod and divide of 64-bit dividend and 32-bit divisor. 153*665484d8SDoug Ambrisko * Assumes a check for a divisor of zero is not possible. 154*665484d8SDoug Ambrisko * 155*665484d8SDoug Ambrisko * @param dividend : Dividend 156*665484d8SDoug Ambrisko * @param divisor : Divisor 157*665484d8SDoug Ambrisko * @return remainder 158*665484d8SDoug Ambrisko */ 159*665484d8SDoug Ambrisko 160*665484d8SDoug Ambrisko #define mega_mod64(dividend, divisor) ({ \ 161*665484d8SDoug Ambrisko int remainder; \ 162*665484d8SDoug Ambrisko remainder = ((u_int64_t) (dividend)) % (u_int32_t) (divisor); \ 163*665484d8SDoug Ambrisko remainder;}) 164*665484d8SDoug Ambrisko 165*665484d8SDoug Ambrisko #define mega_div64_32(dividend, divisor) ({ \ 166*665484d8SDoug Ambrisko int quotient; \ 167*665484d8SDoug Ambrisko quotient = ((u_int64_t) (dividend)) / (u_int32_t) (divisor); \ 168*665484d8SDoug Ambrisko quotient;}) 169*665484d8SDoug Ambrisko 170*665484d8SDoug Ambrisko 171*665484d8SDoug Ambrisko /* 172*665484d8SDoug Ambrisko * Various RAID map access functions. These functions access the various 173*665484d8SDoug Ambrisko * parts of the RAID map and returns the appropriate parameters. 174*665484d8SDoug Ambrisko */ 175*665484d8SDoug Ambrisko 176*665484d8SDoug Ambrisko MR_LD_RAID *MR_LdRaidGet(u_int32_t ld, MR_FW_RAID_MAP_ALL *map) 177*665484d8SDoug Ambrisko { 178*665484d8SDoug Ambrisko return (&map->raidMap.ldSpanMap[ld].ldRaid); 179*665484d8SDoug Ambrisko } 180*665484d8SDoug Ambrisko 181*665484d8SDoug Ambrisko u_int16_t MR_GetLDTgtId(u_int32_t ld, MR_FW_RAID_MAP_ALL *map) 182*665484d8SDoug Ambrisko { 183*665484d8SDoug Ambrisko return (map->raidMap.ldSpanMap[ld].ldRaid.targetId); 184*665484d8SDoug Ambrisko } 185*665484d8SDoug Ambrisko 186*665484d8SDoug Ambrisko static u_int16_t MR_LdSpanArrayGet(u_int32_t ld, u_int32_t span, MR_FW_RAID_MAP_ALL *map) 187*665484d8SDoug Ambrisko { 188*665484d8SDoug Ambrisko return map->raidMap.ldSpanMap[ld].spanBlock[span].span.arrayRef; 189*665484d8SDoug Ambrisko } 190*665484d8SDoug Ambrisko 191*665484d8SDoug Ambrisko static u_int8_t MR_LdDataArmGet(u_int32_t ld, u_int32_t armIdx, MR_FW_RAID_MAP_ALL *map) 192*665484d8SDoug Ambrisko { 193*665484d8SDoug Ambrisko return map->raidMap.ldSpanMap[ld].dataArmMap[armIdx]; 194*665484d8SDoug Ambrisko } 195*665484d8SDoug Ambrisko 196*665484d8SDoug Ambrisko static u_int16_t MR_PdDevHandleGet(u_int32_t pd, MR_FW_RAID_MAP_ALL *map) 197*665484d8SDoug Ambrisko { 198*665484d8SDoug Ambrisko return map->raidMap.devHndlInfo[pd].curDevHdl; 199*665484d8SDoug Ambrisko } 200*665484d8SDoug Ambrisko 201*665484d8SDoug Ambrisko static u_int16_t MR_ArPdGet(u_int32_t ar, u_int32_t arm, MR_FW_RAID_MAP_ALL *map) 202*665484d8SDoug Ambrisko { 203*665484d8SDoug Ambrisko return map->raidMap.arMapInfo[ar].pd[arm]; 204*665484d8SDoug Ambrisko } 205*665484d8SDoug Ambrisko 206*665484d8SDoug Ambrisko static MR_LD_SPAN *MR_LdSpanPtrGet(u_int32_t ld, u_int32_t span, MR_FW_RAID_MAP_ALL *map) 207*665484d8SDoug Ambrisko { 208*665484d8SDoug Ambrisko return &map->raidMap.ldSpanMap[ld].spanBlock[span].span; 209*665484d8SDoug Ambrisko } 210*665484d8SDoug Ambrisko 211*665484d8SDoug Ambrisko static MR_SPAN_BLOCK_INFO *MR_LdSpanInfoGet(u_int32_t ld, MR_FW_RAID_MAP_ALL *map) 212*665484d8SDoug Ambrisko { 213*665484d8SDoug Ambrisko return &map->raidMap.ldSpanMap[ld].spanBlock[0]; 214*665484d8SDoug Ambrisko } 215*665484d8SDoug Ambrisko 216*665484d8SDoug Ambrisko u_int16_t MR_TargetIdToLdGet(u_int32_t ldTgtId, MR_FW_RAID_MAP_ALL *map) 217*665484d8SDoug Ambrisko { 218*665484d8SDoug Ambrisko return map->raidMap.ldTgtIdToLd[ldTgtId]; 219*665484d8SDoug Ambrisko } 220*665484d8SDoug Ambrisko 221*665484d8SDoug Ambrisko u_int32_t MR_LdBlockSizeGet(u_int32_t ldTgtId, MR_FW_RAID_MAP_ALL *map) 222*665484d8SDoug Ambrisko { 223*665484d8SDoug Ambrisko MR_LD_RAID *raid; 224*665484d8SDoug Ambrisko u_int32_t ld, ldBlockSize = MRSAS_SCSIBLOCKSIZE; 225*665484d8SDoug Ambrisko 226*665484d8SDoug Ambrisko ld = MR_TargetIdToLdGet(ldTgtId, map); 227*665484d8SDoug Ambrisko 228*665484d8SDoug Ambrisko /* 229*665484d8SDoug Ambrisko * Check if logical drive was removed. 230*665484d8SDoug Ambrisko */ 231*665484d8SDoug Ambrisko if (ld >= MAX_LOGICAL_DRIVES) 232*665484d8SDoug Ambrisko return ldBlockSize; 233*665484d8SDoug Ambrisko 234*665484d8SDoug Ambrisko raid = MR_LdRaidGet(ld, map); 235*665484d8SDoug Ambrisko ldBlockSize = raid->logicalBlockLength; 236*665484d8SDoug Ambrisko if (!ldBlockSize) 237*665484d8SDoug Ambrisko ldBlockSize = MRSAS_SCSIBLOCKSIZE; 238*665484d8SDoug Ambrisko 239*665484d8SDoug Ambrisko return ldBlockSize; 240*665484d8SDoug Ambrisko } 241*665484d8SDoug Ambrisko 242*665484d8SDoug Ambrisko /** 243*665484d8SDoug Ambrisko * MR_ValidateMapInfo: Validate RAID map 244*665484d8SDoug Ambrisko * input: Adapter instance soft state 245*665484d8SDoug Ambrisko * 246*665484d8SDoug Ambrisko * This function checks and validates the loaded RAID map. It returns 0 if 247*665484d8SDoug Ambrisko * successful, and 1 otherwise. 248*665484d8SDoug Ambrisko */ 249*665484d8SDoug Ambrisko u_int8_t MR_ValidateMapInfo(struct mrsas_softc *sc) 250*665484d8SDoug Ambrisko { 251*665484d8SDoug Ambrisko if (!sc) { 252*665484d8SDoug Ambrisko return 1; 253*665484d8SDoug Ambrisko } 254*665484d8SDoug Ambrisko uint32_t total_map_sz; 255*665484d8SDoug Ambrisko MR_FW_RAID_MAP_ALL *map = sc->raidmap_mem[(sc->map_id & 1)]; 256*665484d8SDoug Ambrisko MR_FW_RAID_MAP *pFwRaidMap = &map->raidMap; 257*665484d8SDoug Ambrisko PLD_SPAN_INFO ldSpanInfo = (PLD_SPAN_INFO) &sc->log_to_span; 258*665484d8SDoug Ambrisko 259*665484d8SDoug Ambrisko total_map_sz = (sizeof(MR_FW_RAID_MAP) - sizeof(MR_LD_SPAN_MAP) + 260*665484d8SDoug Ambrisko (sizeof(MR_LD_SPAN_MAP) * pFwRaidMap->ldCount)); 261*665484d8SDoug Ambrisko 262*665484d8SDoug Ambrisko if (pFwRaidMap->totalSize != total_map_sz) { 263*665484d8SDoug Ambrisko device_printf(sc->mrsas_dev, "map size %x not matching ld count\n", total_map_sz); 264*665484d8SDoug Ambrisko device_printf(sc->mrsas_dev, "span map= %x\n", (unsigned int)sizeof(MR_LD_SPAN_MAP)); 265*665484d8SDoug Ambrisko device_printf(sc->mrsas_dev, "pFwRaidMap->totalSize=%x\n", pFwRaidMap->totalSize); 266*665484d8SDoug Ambrisko return 1; 267*665484d8SDoug Ambrisko } 268*665484d8SDoug Ambrisko 269*665484d8SDoug Ambrisko if (sc->UnevenSpanSupport) { 270*665484d8SDoug Ambrisko mr_update_span_set(map, ldSpanInfo); 271*665484d8SDoug Ambrisko } 272*665484d8SDoug Ambrisko 273*665484d8SDoug Ambrisko mrsas_update_load_balance_params(map, sc->load_balance_info); 274*665484d8SDoug Ambrisko 275*665484d8SDoug Ambrisko return 0; 276*665484d8SDoug Ambrisko } 277*665484d8SDoug Ambrisko 278*665484d8SDoug Ambrisko /* 279*665484d8SDoug Ambrisko * ****************************************************************************** 280*665484d8SDoug Ambrisko * 281*665484d8SDoug Ambrisko * Function to print info about span set created in driver from FW raid map 282*665484d8SDoug Ambrisko * 283*665484d8SDoug Ambrisko * Inputs : 284*665484d8SDoug Ambrisko * map - LD map 285*665484d8SDoug Ambrisko * ldSpanInfo - ldSpanInfo per HBA instance 286*665484d8SDoug Ambrisko * 287*665484d8SDoug Ambrisko * 288*665484d8SDoug Ambrisko * */ 289*665484d8SDoug Ambrisko #if SPAN_DEBUG 290*665484d8SDoug Ambrisko static int getSpanInfo(MR_FW_RAID_MAP_ALL *map, PLD_SPAN_INFO ldSpanInfo) 291*665484d8SDoug Ambrisko { 292*665484d8SDoug Ambrisko 293*665484d8SDoug Ambrisko u_int8_t span; 294*665484d8SDoug Ambrisko u_int32_t element; 295*665484d8SDoug Ambrisko MR_LD_RAID *raid; 296*665484d8SDoug Ambrisko LD_SPAN_SET *span_set; 297*665484d8SDoug Ambrisko MR_QUAD_ELEMENT *quad; 298*665484d8SDoug Ambrisko int ldCount; 299*665484d8SDoug Ambrisko u_int16_t ld; 300*665484d8SDoug Ambrisko 301*665484d8SDoug Ambrisko for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) 302*665484d8SDoug Ambrisko { 303*665484d8SDoug Ambrisko ld = MR_TargetIdToLdGet(ldCount, map); 304*665484d8SDoug Ambrisko if (ld >= MAX_LOGICAL_DRIVES) { 305*665484d8SDoug Ambrisko continue; 306*665484d8SDoug Ambrisko } 307*665484d8SDoug Ambrisko raid = MR_LdRaidGet(ld, map); 308*665484d8SDoug Ambrisko printf("LD %x: span_depth=%x\n", ld, raid->spanDepth); 309*665484d8SDoug Ambrisko for (span=0; span<raid->spanDepth; span++) 310*665484d8SDoug Ambrisko printf("Span=%x, number of quads=%x\n", span, 311*665484d8SDoug Ambrisko map->raidMap.ldSpanMap[ld].spanBlock[span]. 312*665484d8SDoug Ambrisko block_span_info.noElements); 313*665484d8SDoug Ambrisko for (element=0; element < MAX_QUAD_DEPTH; element++) { 314*665484d8SDoug Ambrisko span_set = &(ldSpanInfo[ld].span_set[element]); 315*665484d8SDoug Ambrisko if (span_set->span_row_data_width == 0) break; 316*665484d8SDoug Ambrisko 317*665484d8SDoug Ambrisko printf(" Span Set %x: width=%x, diff=%x\n", element, 318*665484d8SDoug Ambrisko (unsigned int)span_set->span_row_data_width, 319*665484d8SDoug Ambrisko (unsigned int)span_set->diff); 320*665484d8SDoug Ambrisko printf(" logical LBA start=0x%08lx, end=0x%08lx\n", 321*665484d8SDoug Ambrisko (long unsigned int)span_set->log_start_lba, 322*665484d8SDoug Ambrisko (long unsigned int)span_set->log_end_lba); 323*665484d8SDoug Ambrisko printf(" span row start=0x%08lx, end=0x%08lx\n", 324*665484d8SDoug Ambrisko (long unsigned int)span_set->span_row_start, 325*665484d8SDoug Ambrisko (long unsigned int)span_set->span_row_end); 326*665484d8SDoug Ambrisko printf(" data row start=0x%08lx, end=0x%08lx\n", 327*665484d8SDoug Ambrisko (long unsigned int)span_set->data_row_start, 328*665484d8SDoug Ambrisko (long unsigned int)span_set->data_row_end); 329*665484d8SDoug Ambrisko printf(" data strip start=0x%08lx, end=0x%08lx\n", 330*665484d8SDoug Ambrisko (long unsigned int)span_set->data_strip_start, 331*665484d8SDoug Ambrisko (long unsigned int)span_set->data_strip_end); 332*665484d8SDoug Ambrisko 333*665484d8SDoug Ambrisko for (span=0; span<raid->spanDepth; span++) { 334*665484d8SDoug Ambrisko if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 335*665484d8SDoug Ambrisko block_span_info.noElements >=element+1){ 336*665484d8SDoug Ambrisko quad = &map->raidMap.ldSpanMap[ld]. 337*665484d8SDoug Ambrisko spanBlock[span].block_span_info. 338*665484d8SDoug Ambrisko quad[element]; 339*665484d8SDoug Ambrisko printf(" Span=%x, Quad=%x, diff=%x\n", span, 340*665484d8SDoug Ambrisko element, quad->diff); 341*665484d8SDoug Ambrisko printf(" offset_in_span=0x%08lx\n", 342*665484d8SDoug Ambrisko (long unsigned int)quad->offsetInSpan); 343*665484d8SDoug Ambrisko printf(" logical start=0x%08lx, end=0x%08lx\n", 344*665484d8SDoug Ambrisko (long unsigned int)quad->logStart, 345*665484d8SDoug Ambrisko (long unsigned int)quad->logEnd); 346*665484d8SDoug Ambrisko } 347*665484d8SDoug Ambrisko } 348*665484d8SDoug Ambrisko } 349*665484d8SDoug Ambrisko } 350*665484d8SDoug Ambrisko return 0; 351*665484d8SDoug Ambrisko } 352*665484d8SDoug Ambrisko #endif 353*665484d8SDoug Ambrisko /* 354*665484d8SDoug Ambrisko ****************************************************************************** 355*665484d8SDoug Ambrisko * 356*665484d8SDoug Ambrisko * This routine calculates the Span block for given row using spanset. 357*665484d8SDoug Ambrisko * 358*665484d8SDoug Ambrisko * Inputs : 359*665484d8SDoug Ambrisko * instance - HBA instance 360*665484d8SDoug Ambrisko * ld - Logical drive number 361*665484d8SDoug Ambrisko * row - Row number 362*665484d8SDoug Ambrisko * map - LD map 363*665484d8SDoug Ambrisko * 364*665484d8SDoug Ambrisko * Outputs : 365*665484d8SDoug Ambrisko * 366*665484d8SDoug Ambrisko * span - Span number 367*665484d8SDoug Ambrisko * block - Absolute Block number in the physical disk 368*665484d8SDoug Ambrisko * div_error - Devide error code. 369*665484d8SDoug Ambrisko */ 370*665484d8SDoug Ambrisko 371*665484d8SDoug Ambrisko u_int32_t mr_spanset_get_span_block(struct mrsas_softc *sc, u_int32_t ld, u_int64_t row, 372*665484d8SDoug Ambrisko u_int64_t *span_blk, MR_FW_RAID_MAP_ALL *map, int *div_error) 373*665484d8SDoug Ambrisko { 374*665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 375*665484d8SDoug Ambrisko LD_SPAN_SET *span_set; 376*665484d8SDoug Ambrisko MR_QUAD_ELEMENT *quad; 377*665484d8SDoug Ambrisko u_int32_t span, info; 378*665484d8SDoug Ambrisko PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 379*665484d8SDoug Ambrisko 380*665484d8SDoug Ambrisko for (info=0; info < MAX_QUAD_DEPTH; info++) { 381*665484d8SDoug Ambrisko span_set = &(ldSpanInfo[ld].span_set[info]); 382*665484d8SDoug Ambrisko 383*665484d8SDoug Ambrisko if (span_set->span_row_data_width == 0) break; 384*665484d8SDoug Ambrisko if (row > span_set->data_row_end) continue; 385*665484d8SDoug Ambrisko 386*665484d8SDoug Ambrisko for (span=0; span<raid->spanDepth; span++) 387*665484d8SDoug Ambrisko if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 388*665484d8SDoug Ambrisko block_span_info.noElements >= info+1) { 389*665484d8SDoug Ambrisko quad = &map->raidMap.ldSpanMap[ld]. 390*665484d8SDoug Ambrisko spanBlock[span]. 391*665484d8SDoug Ambrisko block_span_info.quad[info]; 392*665484d8SDoug Ambrisko if (quad->diff == 0) { 393*665484d8SDoug Ambrisko *div_error = 1; 394*665484d8SDoug Ambrisko return span; 395*665484d8SDoug Ambrisko } 396*665484d8SDoug Ambrisko if ( quad->logStart <= row && 397*665484d8SDoug Ambrisko row <= quad->logEnd && 398*665484d8SDoug Ambrisko (mega_mod64(row - quad->logStart, 399*665484d8SDoug Ambrisko quad->diff)) == 0 ) { 400*665484d8SDoug Ambrisko if (span_blk != NULL) { 401*665484d8SDoug Ambrisko u_int64_t blk; 402*665484d8SDoug Ambrisko blk = mega_div64_32 403*665484d8SDoug Ambrisko ((row - quad->logStart), 404*665484d8SDoug Ambrisko quad->diff); 405*665484d8SDoug Ambrisko blk = (blk + quad->offsetInSpan) 406*665484d8SDoug Ambrisko << raid->stripeShift; 407*665484d8SDoug Ambrisko *span_blk = blk; 408*665484d8SDoug Ambrisko } 409*665484d8SDoug Ambrisko return span; 410*665484d8SDoug Ambrisko } 411*665484d8SDoug Ambrisko } 412*665484d8SDoug Ambrisko } 413*665484d8SDoug Ambrisko return SPAN_INVALID; 414*665484d8SDoug Ambrisko } 415*665484d8SDoug Ambrisko 416*665484d8SDoug Ambrisko /* 417*665484d8SDoug Ambrisko ****************************************************************************** 418*665484d8SDoug Ambrisko * 419*665484d8SDoug Ambrisko * This routine calculates the row for given strip using spanset. 420*665484d8SDoug Ambrisko * 421*665484d8SDoug Ambrisko * Inputs : 422*665484d8SDoug Ambrisko * instance - HBA instance 423*665484d8SDoug Ambrisko * ld - Logical drive number 424*665484d8SDoug Ambrisko * Strip - Strip 425*665484d8SDoug Ambrisko * map - LD map 426*665484d8SDoug Ambrisko * 427*665484d8SDoug Ambrisko * Outputs : 428*665484d8SDoug Ambrisko * 429*665484d8SDoug Ambrisko * row - row associated with strip 430*665484d8SDoug Ambrisko */ 431*665484d8SDoug Ambrisko 432*665484d8SDoug Ambrisko static u_int64_t get_row_from_strip(struct mrsas_softc *sc, 433*665484d8SDoug Ambrisko u_int32_t ld, u_int64_t strip, MR_FW_RAID_MAP_ALL *map) 434*665484d8SDoug Ambrisko { 435*665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 436*665484d8SDoug Ambrisko LD_SPAN_SET *span_set; 437*665484d8SDoug Ambrisko PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 438*665484d8SDoug Ambrisko u_int32_t info, strip_offset, span, span_offset; 439*665484d8SDoug Ambrisko u_int64_t span_set_Strip, span_set_Row; 440*665484d8SDoug Ambrisko 441*665484d8SDoug Ambrisko for (info=0; info < MAX_QUAD_DEPTH; info++) { 442*665484d8SDoug Ambrisko span_set = &(ldSpanInfo[ld].span_set[info]); 443*665484d8SDoug Ambrisko 444*665484d8SDoug Ambrisko if (span_set->span_row_data_width == 0) break; 445*665484d8SDoug Ambrisko if (strip > span_set->data_strip_end) continue; 446*665484d8SDoug Ambrisko 447*665484d8SDoug Ambrisko span_set_Strip = strip - span_set->data_strip_start; 448*665484d8SDoug Ambrisko strip_offset = mega_mod64(span_set_Strip, 449*665484d8SDoug Ambrisko span_set->span_row_data_width); 450*665484d8SDoug Ambrisko span_set_Row = mega_div64_32(span_set_Strip, 451*665484d8SDoug Ambrisko span_set->span_row_data_width) * span_set->diff; 452*665484d8SDoug Ambrisko for (span=0,span_offset=0; span<raid->spanDepth; span++) 453*665484d8SDoug Ambrisko if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 454*665484d8SDoug Ambrisko block_span_info.noElements >=info+1) { 455*665484d8SDoug Ambrisko if (strip_offset >= 456*665484d8SDoug Ambrisko span_set->strip_offset[span]) 457*665484d8SDoug Ambrisko span_offset++; 458*665484d8SDoug Ambrisko else 459*665484d8SDoug Ambrisko break; 460*665484d8SDoug Ambrisko } 461*665484d8SDoug Ambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : Strip 0x%llx, span_set_Strip 0x%llx, span_set_Row 0x%llx " 462*665484d8SDoug Ambrisko "data width 0x%llx span offset 0x%llx\n", (unsigned long long)strip, 463*665484d8SDoug Ambrisko (unsigned long long)span_set_Strip, 464*665484d8SDoug Ambrisko (unsigned long long)span_set_Row, 465*665484d8SDoug Ambrisko (unsigned long long)span_set->span_row_data_width, (unsigned long long)span_offset); 466*665484d8SDoug Ambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : For strip 0x%llx row is 0x%llx\n", (unsigned long long)strip, 467*665484d8SDoug Ambrisko (unsigned long long) span_set->data_row_start + 468*665484d8SDoug Ambrisko (unsigned long long) span_set_Row + (span_offset - 1)); 469*665484d8SDoug Ambrisko return (span_set->data_row_start + span_set_Row + (span_offset - 1)); 470*665484d8SDoug Ambrisko } 471*665484d8SDoug Ambrisko return -1LLU; 472*665484d8SDoug Ambrisko } 473*665484d8SDoug Ambrisko 474*665484d8SDoug Ambrisko 475*665484d8SDoug Ambrisko /* 476*665484d8SDoug Ambrisko ****************************************************************************** 477*665484d8SDoug Ambrisko * 478*665484d8SDoug Ambrisko * This routine calculates the Start Strip for given row using spanset. 479*665484d8SDoug Ambrisko * 480*665484d8SDoug Ambrisko * Inputs : 481*665484d8SDoug Ambrisko * instance - HBA instance 482*665484d8SDoug Ambrisko * ld - Logical drive number 483*665484d8SDoug Ambrisko * row - Row number 484*665484d8SDoug Ambrisko * map - LD map 485*665484d8SDoug Ambrisko * 486*665484d8SDoug Ambrisko * Outputs : 487*665484d8SDoug Ambrisko * 488*665484d8SDoug Ambrisko * Strip - Start strip associated with row 489*665484d8SDoug Ambrisko */ 490*665484d8SDoug Ambrisko 491*665484d8SDoug Ambrisko static u_int64_t get_strip_from_row(struct mrsas_softc *sc, 492*665484d8SDoug Ambrisko u_int32_t ld, u_int64_t row, MR_FW_RAID_MAP_ALL *map) 493*665484d8SDoug Ambrisko { 494*665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 495*665484d8SDoug Ambrisko LD_SPAN_SET *span_set; 496*665484d8SDoug Ambrisko MR_QUAD_ELEMENT *quad; 497*665484d8SDoug Ambrisko PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 498*665484d8SDoug Ambrisko u_int32_t span, info; 499*665484d8SDoug Ambrisko u_int64_t strip; 500*665484d8SDoug Ambrisko 501*665484d8SDoug Ambrisko for (info=0; info<MAX_QUAD_DEPTH; info++) { 502*665484d8SDoug Ambrisko span_set = &(ldSpanInfo[ld].span_set[info]); 503*665484d8SDoug Ambrisko 504*665484d8SDoug Ambrisko if (span_set->span_row_data_width == 0) break; 505*665484d8SDoug Ambrisko if (row > span_set->data_row_end) continue; 506*665484d8SDoug Ambrisko 507*665484d8SDoug Ambrisko for (span=0; span<raid->spanDepth; span++) 508*665484d8SDoug Ambrisko if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 509*665484d8SDoug Ambrisko block_span_info.noElements >=info+1) { 510*665484d8SDoug Ambrisko quad = &map->raidMap.ldSpanMap[ld]. 511*665484d8SDoug Ambrisko spanBlock[span].block_span_info.quad[info]; 512*665484d8SDoug Ambrisko if ( quad->logStart <= row && 513*665484d8SDoug Ambrisko row <= quad->logEnd && 514*665484d8SDoug Ambrisko mega_mod64((row - quad->logStart), 515*665484d8SDoug Ambrisko quad->diff) == 0 ) { 516*665484d8SDoug Ambrisko strip = mega_div64_32 517*665484d8SDoug Ambrisko (((row - span_set->data_row_start) 518*665484d8SDoug Ambrisko - quad->logStart), 519*665484d8SDoug Ambrisko quad->diff); 520*665484d8SDoug Ambrisko strip *= span_set->span_row_data_width; 521*665484d8SDoug Ambrisko strip += span_set->data_strip_start; 522*665484d8SDoug Ambrisko strip += span_set->strip_offset[span]; 523*665484d8SDoug Ambrisko return strip; 524*665484d8SDoug Ambrisko } 525*665484d8SDoug Ambrisko } 526*665484d8SDoug Ambrisko } 527*665484d8SDoug Ambrisko mrsas_dprint(sc, MRSAS_PRL11,"LSI Debug - get_strip_from_row: returns invalid " 528*665484d8SDoug Ambrisko "strip for ld=%x, row=%lx\n", ld, (long unsigned int)row); 529*665484d8SDoug Ambrisko return -1; 530*665484d8SDoug Ambrisko } 531*665484d8SDoug Ambrisko 532*665484d8SDoug Ambrisko /* 533*665484d8SDoug Ambrisko ****************************************************************************** 534*665484d8SDoug Ambrisko * 535*665484d8SDoug Ambrisko * This routine calculates the Physical Arm for given strip using spanset. 536*665484d8SDoug Ambrisko * 537*665484d8SDoug Ambrisko * Inputs : 538*665484d8SDoug Ambrisko * instance - HBA instance 539*665484d8SDoug Ambrisko * ld - Logical drive number 540*665484d8SDoug Ambrisko * strip - Strip 541*665484d8SDoug Ambrisko * map - LD map 542*665484d8SDoug Ambrisko * 543*665484d8SDoug Ambrisko * Outputs : 544*665484d8SDoug Ambrisko * 545*665484d8SDoug Ambrisko * Phys Arm - Phys Arm associated with strip 546*665484d8SDoug Ambrisko */ 547*665484d8SDoug Ambrisko 548*665484d8SDoug Ambrisko static u_int32_t get_arm_from_strip(struct mrsas_softc *sc, 549*665484d8SDoug Ambrisko u_int32_t ld, u_int64_t strip, MR_FW_RAID_MAP_ALL *map) 550*665484d8SDoug Ambrisko { 551*665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 552*665484d8SDoug Ambrisko LD_SPAN_SET *span_set; 553*665484d8SDoug Ambrisko PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 554*665484d8SDoug Ambrisko u_int32_t info, strip_offset, span, span_offset; 555*665484d8SDoug Ambrisko 556*665484d8SDoug Ambrisko for (info=0; info<MAX_QUAD_DEPTH; info++) { 557*665484d8SDoug Ambrisko span_set = &(ldSpanInfo[ld].span_set[info]); 558*665484d8SDoug Ambrisko 559*665484d8SDoug Ambrisko if (span_set->span_row_data_width == 0) break; 560*665484d8SDoug Ambrisko if (strip > span_set->data_strip_end) continue; 561*665484d8SDoug Ambrisko 562*665484d8SDoug Ambrisko strip_offset = (u_int32_t)mega_mod64 563*665484d8SDoug Ambrisko ((strip - span_set->data_strip_start), 564*665484d8SDoug Ambrisko span_set->span_row_data_width); 565*665484d8SDoug Ambrisko 566*665484d8SDoug Ambrisko for (span=0,span_offset=0; span<raid->spanDepth; span++) 567*665484d8SDoug Ambrisko if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 568*665484d8SDoug Ambrisko block_span_info.noElements >=info+1) { 569*665484d8SDoug Ambrisko if (strip_offset >= 570*665484d8SDoug Ambrisko span_set->strip_offset[span]) 571*665484d8SDoug Ambrisko span_offset = 572*665484d8SDoug Ambrisko span_set->strip_offset[span]; 573*665484d8SDoug Ambrisko else 574*665484d8SDoug Ambrisko break; 575*665484d8SDoug Ambrisko } 576*665484d8SDoug Ambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI PRL11: get_arm_from_strip: " 577*665484d8SDoug Ambrisko " for ld=0x%x strip=0x%lx arm is 0x%x\n", ld, 578*665484d8SDoug Ambrisko (long unsigned int)strip, (strip_offset - span_offset)); 579*665484d8SDoug Ambrisko return (strip_offset - span_offset); 580*665484d8SDoug Ambrisko } 581*665484d8SDoug Ambrisko 582*665484d8SDoug Ambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: - get_arm_from_strip: returns invalid arm" 583*665484d8SDoug Ambrisko " for ld=%x strip=%lx\n", ld, (long unsigned int)strip); 584*665484d8SDoug Ambrisko 585*665484d8SDoug Ambrisko return -1; 586*665484d8SDoug Ambrisko } 587*665484d8SDoug Ambrisko 588*665484d8SDoug Ambrisko 589*665484d8SDoug Ambrisko /* This Function will return Phys arm */ 590*665484d8SDoug Ambrisko u_int8_t get_arm(struct mrsas_softc *sc, u_int32_t ld, u_int8_t span, u_int64_t stripe, 591*665484d8SDoug Ambrisko MR_FW_RAID_MAP_ALL *map) 592*665484d8SDoug Ambrisko { 593*665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 594*665484d8SDoug Ambrisko /* Need to check correct default value */ 595*665484d8SDoug Ambrisko u_int32_t arm = 0; 596*665484d8SDoug Ambrisko 597*665484d8SDoug Ambrisko switch (raid->level) { 598*665484d8SDoug Ambrisko case 0: 599*665484d8SDoug Ambrisko case 5: 600*665484d8SDoug Ambrisko case 6: 601*665484d8SDoug Ambrisko arm = mega_mod64(stripe, SPAN_ROW_SIZE(map, ld, span)); 602*665484d8SDoug Ambrisko break; 603*665484d8SDoug Ambrisko case 1: 604*665484d8SDoug Ambrisko // start with logical arm 605*665484d8SDoug Ambrisko arm = get_arm_from_strip(sc, ld, stripe, map); 606*665484d8SDoug Ambrisko arm *= 2; 607*665484d8SDoug Ambrisko break; 608*665484d8SDoug Ambrisko 609*665484d8SDoug Ambrisko } 610*665484d8SDoug Ambrisko 611*665484d8SDoug Ambrisko return arm; 612*665484d8SDoug Ambrisko } 613*665484d8SDoug Ambrisko 614*665484d8SDoug Ambrisko /* 615*665484d8SDoug Ambrisko ****************************************************************************** 616*665484d8SDoug Ambrisko * 617*665484d8SDoug Ambrisko * This routine calculates the arm, span and block for the specified stripe and 618*665484d8SDoug Ambrisko * reference in stripe using spanset 619*665484d8SDoug Ambrisko * 620*665484d8SDoug Ambrisko * Inputs : 621*665484d8SDoug Ambrisko * 622*665484d8SDoug Ambrisko * ld - Logical drive number 623*665484d8SDoug Ambrisko * stripRow - Stripe number 624*665484d8SDoug Ambrisko * stripRef - Reference in stripe 625*665484d8SDoug Ambrisko * 626*665484d8SDoug Ambrisko * Outputs : 627*665484d8SDoug Ambrisko * 628*665484d8SDoug Ambrisko * span - Span number 629*665484d8SDoug Ambrisko * block - Absolute Block number in the physical disk 630*665484d8SDoug Ambrisko */ 631*665484d8SDoug Ambrisko static u_int8_t mr_spanset_get_phy_params(struct mrsas_softc *sc, u_int32_t ld, u_int64_t stripRow, 632*665484d8SDoug Ambrisko u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 633*665484d8SDoug Ambrisko RAID_CONTEXT *pRAID_Context, MR_FW_RAID_MAP_ALL *map) 634*665484d8SDoug Ambrisko { 635*665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 636*665484d8SDoug Ambrisko u_int32_t pd, arRef; 637*665484d8SDoug Ambrisko u_int8_t physArm, span; 638*665484d8SDoug Ambrisko u_int64_t row; 639*665484d8SDoug Ambrisko u_int8_t retval = TRUE; 640*665484d8SDoug Ambrisko u_int64_t *pdBlock = &io_info->pdBlock; 641*665484d8SDoug Ambrisko u_int16_t *pDevHandle = &io_info->devHandle; 642*665484d8SDoug Ambrisko u_int32_t logArm, rowMod, armQ, arm; 643*665484d8SDoug Ambrisko u_int8_t do_invader = 0; 644*665484d8SDoug Ambrisko 645*665484d8SDoug Ambrisko if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) 646*665484d8SDoug Ambrisko do_invader = 1; 647*665484d8SDoug Ambrisko 648*665484d8SDoug Ambrisko // Get row and span from io_info for Uneven Span IO. 649*665484d8SDoug Ambrisko row = io_info->start_row; 650*665484d8SDoug Ambrisko span = io_info->start_span; 651*665484d8SDoug Ambrisko 652*665484d8SDoug Ambrisko 653*665484d8SDoug Ambrisko if (raid->level == 6) { 654*665484d8SDoug Ambrisko logArm = get_arm_from_strip(sc, ld, stripRow, map); 655*665484d8SDoug Ambrisko rowMod = mega_mod64(row, SPAN_ROW_SIZE(map, ld, span)); 656*665484d8SDoug Ambrisko armQ = SPAN_ROW_SIZE(map,ld,span) - 1 - rowMod; 657*665484d8SDoug Ambrisko arm = armQ + 1 + logArm; 658*665484d8SDoug Ambrisko if (arm >= SPAN_ROW_SIZE(map, ld, span)) 659*665484d8SDoug Ambrisko arm -= SPAN_ROW_SIZE(map ,ld ,span); 660*665484d8SDoug Ambrisko physArm = (u_int8_t)arm; 661*665484d8SDoug Ambrisko } else 662*665484d8SDoug Ambrisko // Calculate the arm 663*665484d8SDoug Ambrisko physArm = get_arm(sc, ld, span, stripRow, map); 664*665484d8SDoug Ambrisko 665*665484d8SDoug Ambrisko 666*665484d8SDoug Ambrisko arRef = MR_LdSpanArrayGet(ld, span, map); 667*665484d8SDoug Ambrisko pd = MR_ArPdGet(arRef, physArm, map); 668*665484d8SDoug Ambrisko 669*665484d8SDoug Ambrisko if (pd != MR_PD_INVALID) 670*665484d8SDoug Ambrisko *pDevHandle = MR_PdDevHandleGet(pd, map); 671*665484d8SDoug Ambrisko else { 672*665484d8SDoug Ambrisko *pDevHandle = MR_PD_INVALID; 673*665484d8SDoug Ambrisko if ((raid->level >= 5) && ((!do_invader) || (do_invader && 674*665484d8SDoug Ambrisko raid->regTypeReqOnRead != REGION_TYPE_UNUSED))) 675*665484d8SDoug Ambrisko pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; 676*665484d8SDoug Ambrisko else if (raid->level == 1) { 677*665484d8SDoug Ambrisko pd = MR_ArPdGet(arRef, physArm + 1, map); 678*665484d8SDoug Ambrisko if (pd != MR_PD_INVALID) 679*665484d8SDoug Ambrisko *pDevHandle = MR_PdDevHandleGet(pd, map); 680*665484d8SDoug Ambrisko } 681*665484d8SDoug Ambrisko } 682*665484d8SDoug Ambrisko 683*665484d8SDoug Ambrisko *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk; 684*665484d8SDoug Ambrisko pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; 685*665484d8SDoug Ambrisko return retval; 686*665484d8SDoug Ambrisko } 687*665484d8SDoug Ambrisko 688*665484d8SDoug Ambrisko /** 689*665484d8SDoug Ambrisko * MR_BuildRaidContext: Set up Fast path RAID context 690*665484d8SDoug Ambrisko * 691*665484d8SDoug Ambrisko * This function will initiate command processing. The start/end row 692*665484d8SDoug Ambrisko * and strip information is calculated then the lock is acquired. 693*665484d8SDoug Ambrisko * This function will return 0 if region lock was acquired OR return 694*665484d8SDoug Ambrisko * num strips. 695*665484d8SDoug Ambrisko */ 696*665484d8SDoug Ambrisko u_int8_t 697*665484d8SDoug Ambrisko MR_BuildRaidContext(struct mrsas_softc *sc, struct IO_REQUEST_INFO *io_info, 698*665484d8SDoug Ambrisko RAID_CONTEXT *pRAID_Context, MR_FW_RAID_MAP_ALL *map) 699*665484d8SDoug Ambrisko { 700*665484d8SDoug Ambrisko MR_LD_RAID *raid; 701*665484d8SDoug Ambrisko u_int32_t ld, stripSize, stripe_mask; 702*665484d8SDoug Ambrisko u_int64_t endLba, endStrip, endRow, start_row, start_strip; 703*665484d8SDoug Ambrisko REGION_KEY regStart; 704*665484d8SDoug Ambrisko REGION_LEN regSize; 705*665484d8SDoug Ambrisko u_int8_t num_strips, numRows; 706*665484d8SDoug Ambrisko u_int16_t ref_in_start_stripe, ref_in_end_stripe; 707*665484d8SDoug Ambrisko u_int64_t ldStartBlock; 708*665484d8SDoug Ambrisko u_int32_t numBlocks, ldTgtId; 709*665484d8SDoug Ambrisko u_int8_t isRead, stripIdx; 710*665484d8SDoug Ambrisko u_int8_t retval = 0; 711*665484d8SDoug Ambrisko u_int8_t startlba_span = SPAN_INVALID; 712*665484d8SDoug Ambrisko u_int64_t *pdBlock = &io_info->pdBlock; 713*665484d8SDoug Ambrisko int error_code = 0; 714*665484d8SDoug Ambrisko 715*665484d8SDoug Ambrisko ldStartBlock = io_info->ldStartBlock; 716*665484d8SDoug Ambrisko numBlocks = io_info->numBlocks; 717*665484d8SDoug Ambrisko ldTgtId = io_info->ldTgtId; 718*665484d8SDoug Ambrisko isRead = io_info->isRead; 719*665484d8SDoug Ambrisko 720*665484d8SDoug Ambrisko io_info->IoforUnevenSpan = 0; 721*665484d8SDoug Ambrisko io_info->start_span = SPAN_INVALID; 722*665484d8SDoug Ambrisko 723*665484d8SDoug Ambrisko ld = MR_TargetIdToLdGet(ldTgtId, map); 724*665484d8SDoug Ambrisko raid = MR_LdRaidGet(ld, map); 725*665484d8SDoug Ambrisko 726*665484d8SDoug Ambrisko /* 727*665484d8SDoug Ambrisko * if rowDataSize @RAID map and spanRowDataSize @SPAN INFO are zero 728*665484d8SDoug Ambrisko * return FALSE 729*665484d8SDoug Ambrisko */ 730*665484d8SDoug Ambrisko if (raid->rowDataSize == 0) { 731*665484d8SDoug Ambrisko if (MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize == 0) 732*665484d8SDoug Ambrisko return FALSE; 733*665484d8SDoug Ambrisko else if (sc->UnevenSpanSupport) { 734*665484d8SDoug Ambrisko io_info->IoforUnevenSpan = 1; 735*665484d8SDoug Ambrisko } 736*665484d8SDoug Ambrisko else { 737*665484d8SDoug Ambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: raid->rowDataSize is 0, but has SPAN[0] rowDataSize = 0x%0x," 738*665484d8SDoug Ambrisko " but there is _NO_ UnevenSpanSupport\n", 739*665484d8SDoug Ambrisko MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize); 740*665484d8SDoug Ambrisko return FALSE; 741*665484d8SDoug Ambrisko } 742*665484d8SDoug Ambrisko } 743*665484d8SDoug Ambrisko stripSize = 1 << raid->stripeShift; 744*665484d8SDoug Ambrisko stripe_mask = stripSize-1; 745*665484d8SDoug Ambrisko /* 746*665484d8SDoug Ambrisko * calculate starting row and stripe, and number of strips and rows 747*665484d8SDoug Ambrisko */ 748*665484d8SDoug Ambrisko start_strip = ldStartBlock >> raid->stripeShift; 749*665484d8SDoug Ambrisko ref_in_start_stripe = (u_int16_t)(ldStartBlock & stripe_mask); 750*665484d8SDoug Ambrisko endLba = ldStartBlock + numBlocks - 1; 751*665484d8SDoug Ambrisko ref_in_end_stripe = (u_int16_t)(endLba & stripe_mask); 752*665484d8SDoug Ambrisko endStrip = endLba >> raid->stripeShift; 753*665484d8SDoug Ambrisko num_strips = (u_int8_t)(endStrip - start_strip + 1); // End strip 754*665484d8SDoug Ambrisko if (io_info->IoforUnevenSpan) { 755*665484d8SDoug Ambrisko start_row = get_row_from_strip(sc, ld, start_strip, map); 756*665484d8SDoug Ambrisko endRow = get_row_from_strip(sc, ld, endStrip, map); 757*665484d8SDoug Ambrisko if (raid->spanDepth == 1) { 758*665484d8SDoug Ambrisko startlba_span = 0; 759*665484d8SDoug Ambrisko *pdBlock = start_row << raid->stripeShift; 760*665484d8SDoug Ambrisko } else { 761*665484d8SDoug Ambrisko startlba_span = (u_int8_t)mr_spanset_get_span_block(sc, ld, start_row, 762*665484d8SDoug Ambrisko pdBlock, map, &error_code); 763*665484d8SDoug Ambrisko if (error_code == 1) { 764*665484d8SDoug Ambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: return from %s %d. Send IO w/o region lock.\n", 765*665484d8SDoug Ambrisko __func__, __LINE__); 766*665484d8SDoug Ambrisko return FALSE; 767*665484d8SDoug Ambrisko } 768*665484d8SDoug Ambrisko } 769*665484d8SDoug Ambrisko if (startlba_span == SPAN_INVALID) { 770*665484d8SDoug Ambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: return from %s %d for row 0x%llx," 771*665484d8SDoug Ambrisko "start strip %llx endSrip %llx\n", __func__, 772*665484d8SDoug Ambrisko __LINE__, (unsigned long long)start_row, 773*665484d8SDoug Ambrisko (unsigned long long)start_strip, 774*665484d8SDoug Ambrisko (unsigned long long)endStrip); 775*665484d8SDoug Ambrisko return FALSE; 776*665484d8SDoug Ambrisko } 777*665484d8SDoug Ambrisko io_info->start_span = startlba_span; 778*665484d8SDoug Ambrisko io_info->start_row = start_row; 779*665484d8SDoug Ambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: Check Span number from %s %d for row 0x%llx, " 780*665484d8SDoug Ambrisko " start strip 0x%llx endSrip 0x%llx span 0x%x\n", 781*665484d8SDoug Ambrisko __func__, __LINE__, (unsigned long long)start_row, 782*665484d8SDoug Ambrisko (unsigned long long)start_strip, 783*665484d8SDoug Ambrisko (unsigned long long)endStrip, startlba_span); 784*665484d8SDoug Ambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : 1. start_row 0x%llx endRow 0x%llx Start span 0x%x\n", 785*665484d8SDoug Ambrisko (unsigned long long)start_row, (unsigned long long)endRow, startlba_span); 786*665484d8SDoug Ambrisko } else { 787*665484d8SDoug Ambrisko start_row = mega_div64_32(start_strip, raid->rowDataSize); // Start Row 788*665484d8SDoug Ambrisko endRow = mega_div64_32(endStrip, raid->rowDataSize); 789*665484d8SDoug Ambrisko } 790*665484d8SDoug Ambrisko 791*665484d8SDoug Ambrisko numRows = (u_int8_t)(endRow - start_row + 1); // get the row count 792*665484d8SDoug Ambrisko 793*665484d8SDoug Ambrisko /* 794*665484d8SDoug Ambrisko * Calculate region info. (Assume region at start of first row, and 795*665484d8SDoug Ambrisko * assume this IO needs the full row - will adjust if not true.) 796*665484d8SDoug Ambrisko */ 797*665484d8SDoug Ambrisko regStart = start_row << raid->stripeShift; 798*665484d8SDoug Ambrisko regSize = stripSize; 799*665484d8SDoug Ambrisko 800*665484d8SDoug Ambrisko /* Check if we can send this I/O via FastPath */ 801*665484d8SDoug Ambrisko if (raid->capability.fpCapable) { 802*665484d8SDoug Ambrisko if (isRead) 803*665484d8SDoug Ambrisko io_info->fpOkForIo = (raid->capability.fpReadCapable && 804*665484d8SDoug Ambrisko ((num_strips == 1) || 805*665484d8SDoug Ambrisko raid->capability. 806*665484d8SDoug Ambrisko fpReadAcrossStripe)); 807*665484d8SDoug Ambrisko else 808*665484d8SDoug Ambrisko io_info->fpOkForIo = (raid->capability.fpWriteCapable && 809*665484d8SDoug Ambrisko ((num_strips == 1) || 810*665484d8SDoug Ambrisko raid->capability. 811*665484d8SDoug Ambrisko fpWriteAcrossStripe)); 812*665484d8SDoug Ambrisko } 813*665484d8SDoug Ambrisko else 814*665484d8SDoug Ambrisko io_info->fpOkForIo = FALSE; 815*665484d8SDoug Ambrisko 816*665484d8SDoug Ambrisko if (numRows == 1) { 817*665484d8SDoug Ambrisko if (num_strips == 1) { 818*665484d8SDoug Ambrisko /* single-strip IOs can always lock only the data needed, 819*665484d8SDoug Ambrisko multi-strip IOs always need to full stripe locked */ 820*665484d8SDoug Ambrisko regStart += ref_in_start_stripe; 821*665484d8SDoug Ambrisko regSize = numBlocks; 822*665484d8SDoug Ambrisko } 823*665484d8SDoug Ambrisko } 824*665484d8SDoug Ambrisko else if (io_info->IoforUnevenSpan == 0){ 825*665484d8SDoug Ambrisko // For Even span region lock optimization. 826*665484d8SDoug Ambrisko // If the start strip is the last in the start row 827*665484d8SDoug Ambrisko if (start_strip == (start_row + 1) * raid->rowDataSize - 1) { 828*665484d8SDoug Ambrisko regStart += ref_in_start_stripe; 829*665484d8SDoug Ambrisko // initialize count to sectors from startRef to end of strip 830*665484d8SDoug Ambrisko regSize = stripSize - ref_in_start_stripe; 831*665484d8SDoug Ambrisko } 832*665484d8SDoug Ambrisko // add complete rows in the middle of the transfer 833*665484d8SDoug Ambrisko if (numRows > 2) 834*665484d8SDoug Ambrisko regSize += (numRows-2) << raid->stripeShift; 835*665484d8SDoug Ambrisko 836*665484d8SDoug Ambrisko // if IO ends within first strip of last row 837*665484d8SDoug Ambrisko if (endStrip == endRow*raid->rowDataSize) 838*665484d8SDoug Ambrisko regSize += ref_in_end_stripe+1; 839*665484d8SDoug Ambrisko else 840*665484d8SDoug Ambrisko regSize += stripSize; 841*665484d8SDoug Ambrisko } else { 842*665484d8SDoug Ambrisko //For Uneven span region lock optimization. 843*665484d8SDoug Ambrisko // If the start strip is the last in the start row 844*665484d8SDoug Ambrisko if (start_strip == (get_strip_from_row(sc, ld, start_row, map) + 845*665484d8SDoug Ambrisko SPAN_ROW_DATA_SIZE(map, ld, startlba_span) - 1)) { 846*665484d8SDoug Ambrisko regStart += ref_in_start_stripe; 847*665484d8SDoug Ambrisko // initialize count to sectors from startRef to end of strip 848*665484d8SDoug Ambrisko regSize = stripSize - ref_in_start_stripe; 849*665484d8SDoug Ambrisko } 850*665484d8SDoug Ambrisko // add complete rows in the middle of the transfer 851*665484d8SDoug Ambrisko if (numRows > 2) 852*665484d8SDoug Ambrisko regSize += (numRows-2) << raid->stripeShift; 853*665484d8SDoug Ambrisko 854*665484d8SDoug Ambrisko // if IO ends within first strip of last row 855*665484d8SDoug Ambrisko if (endStrip == get_strip_from_row(sc, ld, endRow, map)) 856*665484d8SDoug Ambrisko regSize += ref_in_end_stripe+1; 857*665484d8SDoug Ambrisko else 858*665484d8SDoug Ambrisko regSize += stripSize; 859*665484d8SDoug Ambrisko } 860*665484d8SDoug Ambrisko pRAID_Context->timeoutValue = map->raidMap.fpPdIoTimeoutSec; 861*665484d8SDoug Ambrisko if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) 862*665484d8SDoug Ambrisko pRAID_Context->regLockFlags = (isRead)? raid->regTypeReqOnRead : raid->regTypeReqOnWrite; 863*665484d8SDoug Ambrisko else 864*665484d8SDoug Ambrisko pRAID_Context->regLockFlags = (isRead)? REGION_TYPE_SHARED_READ : raid->regTypeReqOnWrite; 865*665484d8SDoug Ambrisko pRAID_Context->VirtualDiskTgtId = raid->targetId; 866*665484d8SDoug Ambrisko pRAID_Context->regLockRowLBA = regStart; 867*665484d8SDoug Ambrisko pRAID_Context->regLockLength = regSize; 868*665484d8SDoug Ambrisko pRAID_Context->configSeqNum = raid->seqNum; 869*665484d8SDoug Ambrisko 870*665484d8SDoug Ambrisko /* 871*665484d8SDoug Ambrisko * Get Phy Params only if FP capable, or else leave it to MR firmware 872*665484d8SDoug Ambrisko * to do the calculation. 873*665484d8SDoug Ambrisko */ 874*665484d8SDoug Ambrisko if (io_info->fpOkForIo) { 875*665484d8SDoug Ambrisko retval = io_info->IoforUnevenSpan ? 876*665484d8SDoug Ambrisko mr_spanset_get_phy_params(sc, ld, 877*665484d8SDoug Ambrisko start_strip, ref_in_start_stripe, io_info, 878*665484d8SDoug Ambrisko pRAID_Context, map) : 879*665484d8SDoug Ambrisko MR_GetPhyParams(sc, ld, start_strip, 880*665484d8SDoug Ambrisko ref_in_start_stripe, io_info, pRAID_Context, map); 881*665484d8SDoug Ambrisko /* If IO on an invalid Pd, then FP is not possible */ 882*665484d8SDoug Ambrisko if (io_info->devHandle == MR_PD_INVALID) 883*665484d8SDoug Ambrisko io_info->fpOkForIo = FALSE; 884*665484d8SDoug Ambrisko return retval; 885*665484d8SDoug Ambrisko } 886*665484d8SDoug Ambrisko else if (isRead) { 887*665484d8SDoug Ambrisko for (stripIdx=0; stripIdx<num_strips; stripIdx++) { 888*665484d8SDoug Ambrisko retval = io_info->IoforUnevenSpan ? 889*665484d8SDoug Ambrisko mr_spanset_get_phy_params(sc, ld, 890*665484d8SDoug Ambrisko start_strip + stripIdx, 891*665484d8SDoug Ambrisko ref_in_start_stripe, io_info, 892*665484d8SDoug Ambrisko pRAID_Context, map) : 893*665484d8SDoug Ambrisko MR_GetPhyParams(sc, ld, 894*665484d8SDoug Ambrisko start_strip + stripIdx, ref_in_start_stripe, 895*665484d8SDoug Ambrisko io_info, pRAID_Context, map); 896*665484d8SDoug Ambrisko if (!retval) 897*665484d8SDoug Ambrisko return TRUE; 898*665484d8SDoug Ambrisko } 899*665484d8SDoug Ambrisko } 900*665484d8SDoug Ambrisko #if SPAN_DEBUG 901*665484d8SDoug Ambrisko // Just for testing what arm we get for strip. 902*665484d8SDoug Ambrisko get_arm_from_strip(sc, ld, start_strip, map); 903*665484d8SDoug Ambrisko #endif 904*665484d8SDoug Ambrisko return TRUE; 905*665484d8SDoug Ambrisko } 906*665484d8SDoug Ambrisko 907*665484d8SDoug Ambrisko /* 908*665484d8SDoug Ambrisko ****************************************************************************** 909*665484d8SDoug Ambrisko * 910*665484d8SDoug Ambrisko * This routine pepare spanset info from Valid Raid map and store it into 911*665484d8SDoug Ambrisko * local copy of ldSpanInfo per instance data structure. 912*665484d8SDoug Ambrisko * 913*665484d8SDoug Ambrisko * Inputs : 914*665484d8SDoug Ambrisko * map - LD map 915*665484d8SDoug Ambrisko * ldSpanInfo - ldSpanInfo per HBA instance 916*665484d8SDoug Ambrisko * 917*665484d8SDoug Ambrisko */ 918*665484d8SDoug Ambrisko void mr_update_span_set(MR_FW_RAID_MAP_ALL *map, PLD_SPAN_INFO ldSpanInfo) 919*665484d8SDoug Ambrisko { 920*665484d8SDoug Ambrisko u_int8_t span,count; 921*665484d8SDoug Ambrisko u_int32_t element,span_row_width; 922*665484d8SDoug Ambrisko u_int64_t span_row; 923*665484d8SDoug Ambrisko MR_LD_RAID *raid; 924*665484d8SDoug Ambrisko LD_SPAN_SET *span_set, *span_set_prev; 925*665484d8SDoug Ambrisko MR_QUAD_ELEMENT *quad; 926*665484d8SDoug Ambrisko int ldCount; 927*665484d8SDoug Ambrisko u_int16_t ld; 928*665484d8SDoug Ambrisko 929*665484d8SDoug Ambrisko if (!ldSpanInfo) 930*665484d8SDoug Ambrisko return; 931*665484d8SDoug Ambrisko 932*665484d8SDoug Ambrisko for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) 933*665484d8SDoug Ambrisko { 934*665484d8SDoug Ambrisko ld = MR_TargetIdToLdGet(ldCount, map); 935*665484d8SDoug Ambrisko if (ld >= MAX_LOGICAL_DRIVES) 936*665484d8SDoug Ambrisko continue; 937*665484d8SDoug Ambrisko raid = MR_LdRaidGet(ld, map); 938*665484d8SDoug Ambrisko for (element=0; element < MAX_QUAD_DEPTH; element++) { 939*665484d8SDoug Ambrisko for (span=0; span < raid->spanDepth; span++) { 940*665484d8SDoug Ambrisko if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 941*665484d8SDoug Ambrisko block_span_info.noElements < element+1) 942*665484d8SDoug Ambrisko continue; 943*665484d8SDoug Ambrisko // TO-DO 944*665484d8SDoug Ambrisko span_set = &(ldSpanInfo[ld].span_set[element]); 945*665484d8SDoug Ambrisko quad = &map->raidMap.ldSpanMap[ld]. 946*665484d8SDoug Ambrisko spanBlock[span].block_span_info. 947*665484d8SDoug Ambrisko quad[element]; 948*665484d8SDoug Ambrisko 949*665484d8SDoug Ambrisko span_set->diff = quad->diff; 950*665484d8SDoug Ambrisko 951*665484d8SDoug Ambrisko for (count=0,span_row_width=0; 952*665484d8SDoug Ambrisko count<raid->spanDepth; count++) { 953*665484d8SDoug Ambrisko if (map->raidMap.ldSpanMap[ld]. 954*665484d8SDoug Ambrisko spanBlock[count]. 955*665484d8SDoug Ambrisko block_span_info. 956*665484d8SDoug Ambrisko noElements >=element+1) { 957*665484d8SDoug Ambrisko span_set->strip_offset[count] = 958*665484d8SDoug Ambrisko span_row_width; 959*665484d8SDoug Ambrisko span_row_width += 960*665484d8SDoug Ambrisko MR_LdSpanPtrGet 961*665484d8SDoug Ambrisko (ld, count, map)->spanRowDataSize; 962*665484d8SDoug Ambrisko #if SPAN_DEBUG 963*665484d8SDoug Ambrisko printf("LSI Debug span %x rowDataSize %x\n", 964*665484d8SDoug Ambrisko count, MR_LdSpanPtrGet 965*665484d8SDoug Ambrisko (ld, count, map)->spanRowDataSize); 966*665484d8SDoug Ambrisko #endif 967*665484d8SDoug Ambrisko } 968*665484d8SDoug Ambrisko } 969*665484d8SDoug Ambrisko 970*665484d8SDoug Ambrisko span_set->span_row_data_width = span_row_width; 971*665484d8SDoug Ambrisko span_row = mega_div64_32(((quad->logEnd - 972*665484d8SDoug Ambrisko quad->logStart) + quad->diff), quad->diff); 973*665484d8SDoug Ambrisko 974*665484d8SDoug Ambrisko if (element == 0) { 975*665484d8SDoug Ambrisko span_set->log_start_lba = 0; 976*665484d8SDoug Ambrisko span_set->log_end_lba = 977*665484d8SDoug Ambrisko ((span_row << raid->stripeShift) * span_row_width) - 1; 978*665484d8SDoug Ambrisko 979*665484d8SDoug Ambrisko span_set->span_row_start = 0; 980*665484d8SDoug Ambrisko span_set->span_row_end = span_row - 1; 981*665484d8SDoug Ambrisko 982*665484d8SDoug Ambrisko span_set->data_strip_start = 0; 983*665484d8SDoug Ambrisko span_set->data_strip_end = 984*665484d8SDoug Ambrisko (span_row * span_row_width) - 1; 985*665484d8SDoug Ambrisko 986*665484d8SDoug Ambrisko span_set->data_row_start = 0; 987*665484d8SDoug Ambrisko span_set->data_row_end = 988*665484d8SDoug Ambrisko (span_row * quad->diff) - 1; 989*665484d8SDoug Ambrisko } else { 990*665484d8SDoug Ambrisko span_set_prev = &(ldSpanInfo[ld]. 991*665484d8SDoug Ambrisko span_set[element - 1]); 992*665484d8SDoug Ambrisko span_set->log_start_lba = 993*665484d8SDoug Ambrisko span_set_prev->log_end_lba + 1; 994*665484d8SDoug Ambrisko span_set->log_end_lba = 995*665484d8SDoug Ambrisko span_set->log_start_lba + 996*665484d8SDoug Ambrisko ((span_row << raid->stripeShift) * span_row_width) - 1; 997*665484d8SDoug Ambrisko 998*665484d8SDoug Ambrisko span_set->span_row_start = 999*665484d8SDoug Ambrisko span_set_prev->span_row_end + 1; 1000*665484d8SDoug Ambrisko span_set->span_row_end = 1001*665484d8SDoug Ambrisko span_set->span_row_start + span_row - 1; 1002*665484d8SDoug Ambrisko 1003*665484d8SDoug Ambrisko span_set->data_strip_start = 1004*665484d8SDoug Ambrisko span_set_prev->data_strip_end + 1; 1005*665484d8SDoug Ambrisko span_set->data_strip_end = 1006*665484d8SDoug Ambrisko span_set->data_strip_start + 1007*665484d8SDoug Ambrisko (span_row * span_row_width) - 1; 1008*665484d8SDoug Ambrisko 1009*665484d8SDoug Ambrisko span_set->data_row_start = 1010*665484d8SDoug Ambrisko span_set_prev->data_row_end + 1; 1011*665484d8SDoug Ambrisko span_set->data_row_end = 1012*665484d8SDoug Ambrisko span_set->data_row_start + 1013*665484d8SDoug Ambrisko (span_row * quad->diff) - 1; 1014*665484d8SDoug Ambrisko } 1015*665484d8SDoug Ambrisko break; 1016*665484d8SDoug Ambrisko } 1017*665484d8SDoug Ambrisko if (span == raid->spanDepth) break; // no quads remain 1018*665484d8SDoug Ambrisko } 1019*665484d8SDoug Ambrisko } 1020*665484d8SDoug Ambrisko #if SPAN_DEBUG 1021*665484d8SDoug Ambrisko getSpanInfo(map, ldSpanInfo); //to get span set info 1022*665484d8SDoug Ambrisko #endif 1023*665484d8SDoug Ambrisko } 1024*665484d8SDoug Ambrisko 1025*665484d8SDoug Ambrisko /** 1026*665484d8SDoug Ambrisko * mrsas_update_load_balance_params: Update load balance parmas 1027*665484d8SDoug Ambrisko * Inputs: map pointer 1028*665484d8SDoug Ambrisko * Load balance info 1029*665484d8SDoug Ambrisko * io_info pointer 1030*665484d8SDoug Ambrisko * 1031*665484d8SDoug Ambrisko * This function updates the load balance parameters for the LD config 1032*665484d8SDoug Ambrisko * of a two drive optimal RAID-1. 1033*665484d8SDoug Ambrisko */ 1034*665484d8SDoug Ambrisko void mrsas_update_load_balance_params(MR_FW_RAID_MAP_ALL *map, 1035*665484d8SDoug Ambrisko PLD_LOAD_BALANCE_INFO lbInfo) 1036*665484d8SDoug Ambrisko { 1037*665484d8SDoug Ambrisko int ldCount; 1038*665484d8SDoug Ambrisko u_int16_t ld; 1039*665484d8SDoug Ambrisko u_int32_t pd, arRef; 1040*665484d8SDoug Ambrisko MR_LD_RAID *raid; 1041*665484d8SDoug Ambrisko 1042*665484d8SDoug Ambrisko for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) 1043*665484d8SDoug Ambrisko { 1044*665484d8SDoug Ambrisko ld = MR_TargetIdToLdGet(ldCount, map); 1045*665484d8SDoug Ambrisko if (ld >= MAX_LOGICAL_DRIVES) { 1046*665484d8SDoug Ambrisko lbInfo[ldCount].loadBalanceFlag = 0; 1047*665484d8SDoug Ambrisko continue; 1048*665484d8SDoug Ambrisko } 1049*665484d8SDoug Ambrisko 1050*665484d8SDoug Ambrisko raid = MR_LdRaidGet(ld, map); 1051*665484d8SDoug Ambrisko 1052*665484d8SDoug Ambrisko /* Two drive Optimal RAID 1 */ 1053*665484d8SDoug Ambrisko if ((raid->level == 1) && (raid->rowSize == 2) && 1054*665484d8SDoug Ambrisko (raid->spanDepth == 1) 1055*665484d8SDoug Ambrisko && raid->ldState == MR_LD_STATE_OPTIMAL) { 1056*665484d8SDoug Ambrisko lbInfo[ldCount].loadBalanceFlag = 1; 1057*665484d8SDoug Ambrisko 1058*665484d8SDoug Ambrisko /* Get the array on which this span is present */ 1059*665484d8SDoug Ambrisko arRef = MR_LdSpanArrayGet(ld, 0, map); 1060*665484d8SDoug Ambrisko 1061*665484d8SDoug Ambrisko /* Get the PD */ 1062*665484d8SDoug Ambrisko pd = MR_ArPdGet(arRef, 0, map); 1063*665484d8SDoug Ambrisko /* Get dev handle from PD */ 1064*665484d8SDoug Ambrisko lbInfo[ldCount].raid1DevHandle[0] = MR_PdDevHandleGet(pd, map); 1065*665484d8SDoug Ambrisko pd = MR_ArPdGet(arRef, 1, map); 1066*665484d8SDoug Ambrisko lbInfo[ldCount].raid1DevHandle[1] = MR_PdDevHandleGet(pd, map); 1067*665484d8SDoug Ambrisko } 1068*665484d8SDoug Ambrisko else 1069*665484d8SDoug Ambrisko lbInfo[ldCount].loadBalanceFlag = 0; 1070*665484d8SDoug Ambrisko } 1071*665484d8SDoug Ambrisko } 1072*665484d8SDoug Ambrisko 1073*665484d8SDoug Ambrisko 1074*665484d8SDoug Ambrisko /** 1075*665484d8SDoug Ambrisko * mrsas_set_pd_lba: Sets PD LBA 1076*665484d8SDoug Ambrisko * input: io_request pointer 1077*665484d8SDoug Ambrisko * CDB length 1078*665484d8SDoug Ambrisko * io_info pointer 1079*665484d8SDoug Ambrisko * Pointer to CCB 1080*665484d8SDoug Ambrisko * Local RAID map pointer 1081*665484d8SDoug Ambrisko * Start block of IO 1082*665484d8SDoug Ambrisko * Block Size 1083*665484d8SDoug Ambrisko * 1084*665484d8SDoug Ambrisko * Used to set the PD logical block address in CDB for FP IOs. 1085*665484d8SDoug Ambrisko */ 1086*665484d8SDoug Ambrisko void mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST *io_request, u_int8_t cdb_len, 1087*665484d8SDoug Ambrisko struct IO_REQUEST_INFO *io_info, union ccb *ccb, 1088*665484d8SDoug Ambrisko MR_FW_RAID_MAP_ALL *local_map_ptr, u_int32_t ref_tag, 1089*665484d8SDoug Ambrisko u_int32_t ld_block_size) 1090*665484d8SDoug Ambrisko { 1091*665484d8SDoug Ambrisko MR_LD_RAID *raid; 1092*665484d8SDoug Ambrisko u_int32_t ld; 1093*665484d8SDoug Ambrisko u_int64_t start_blk = io_info->pdBlock; 1094*665484d8SDoug Ambrisko u_int8_t *cdb = io_request->CDB.CDB32; 1095*665484d8SDoug Ambrisko u_int32_t num_blocks = io_info->numBlocks; 1096*665484d8SDoug Ambrisko u_int8_t opcode = 0, flagvals = 0, groupnum = 0, control = 0; 1097*665484d8SDoug Ambrisko struct ccb_hdr *ccb_h = &(ccb->ccb_h); 1098*665484d8SDoug Ambrisko 1099*665484d8SDoug Ambrisko /* Check if T10 PI (DIF) is enabled for this LD */ 1100*665484d8SDoug Ambrisko ld = MR_TargetIdToLdGet(io_info->ldTgtId, local_map_ptr); 1101*665484d8SDoug Ambrisko raid = MR_LdRaidGet(ld, local_map_ptr); 1102*665484d8SDoug Ambrisko if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER) { 1103*665484d8SDoug Ambrisko memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1104*665484d8SDoug Ambrisko cdb[0] = MRSAS_SCSI_VARIABLE_LENGTH_CMD; 1105*665484d8SDoug Ambrisko cdb[7] = MRSAS_SCSI_ADDL_CDB_LEN; 1106*665484d8SDoug Ambrisko 1107*665484d8SDoug Ambrisko if (ccb_h->flags == CAM_DIR_OUT) 1108*665484d8SDoug Ambrisko cdb[9] = MRSAS_SCSI_SERVICE_ACTION_READ32; 1109*665484d8SDoug Ambrisko else 1110*665484d8SDoug Ambrisko cdb[9] = MRSAS_SCSI_SERVICE_ACTION_WRITE32; 1111*665484d8SDoug Ambrisko cdb[10] = MRSAS_RD_WR_PROTECT_CHECK_ALL; 1112*665484d8SDoug Ambrisko 1113*665484d8SDoug Ambrisko /* LBA */ 1114*665484d8SDoug Ambrisko cdb[12] = (u_int8_t)((start_blk >> 56) & 0xff); 1115*665484d8SDoug Ambrisko cdb[13] = (u_int8_t)((start_blk >> 48) & 0xff); 1116*665484d8SDoug Ambrisko cdb[14] = (u_int8_t)((start_blk >> 40) & 0xff); 1117*665484d8SDoug Ambrisko cdb[15] = (u_int8_t)((start_blk >> 32) & 0xff); 1118*665484d8SDoug Ambrisko cdb[16] = (u_int8_t)((start_blk >> 24) & 0xff); 1119*665484d8SDoug Ambrisko cdb[17] = (u_int8_t)((start_blk >> 16) & 0xff); 1120*665484d8SDoug Ambrisko cdb[18] = (u_int8_t)((start_blk >> 8) & 0xff); 1121*665484d8SDoug Ambrisko cdb[19] = (u_int8_t)(start_blk & 0xff); 1122*665484d8SDoug Ambrisko 1123*665484d8SDoug Ambrisko /* Logical block reference tag */ 1124*665484d8SDoug Ambrisko io_request->CDB.EEDP32.PrimaryReferenceTag = swap32(ref_tag); 1125*665484d8SDoug Ambrisko io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0xffff; 1126*665484d8SDoug Ambrisko io_request->IoFlags = 32; /* Specify 32-byte cdb */ 1127*665484d8SDoug Ambrisko 1128*665484d8SDoug Ambrisko /* Transfer length */ 1129*665484d8SDoug Ambrisko cdb[28] = (u_int8_t)((num_blocks >> 24) & 0xff); 1130*665484d8SDoug Ambrisko cdb[29] = (u_int8_t)((num_blocks >> 16) & 0xff); 1131*665484d8SDoug Ambrisko cdb[30] = (u_int8_t)((num_blocks >> 8) & 0xff); 1132*665484d8SDoug Ambrisko cdb[31] = (u_int8_t)(num_blocks & 0xff); 1133*665484d8SDoug Ambrisko 1134*665484d8SDoug Ambrisko /* set SCSI IO EEDP Flags */ 1135*665484d8SDoug Ambrisko if (ccb_h->flags == CAM_DIR_OUT) { 1136*665484d8SDoug Ambrisko io_request->EEDPFlags = 1137*665484d8SDoug Ambrisko MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | 1138*665484d8SDoug Ambrisko MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | 1139*665484d8SDoug Ambrisko MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP | 1140*665484d8SDoug Ambrisko MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG | 1141*665484d8SDoug Ambrisko MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; 1142*665484d8SDoug Ambrisko } 1143*665484d8SDoug Ambrisko else { 1144*665484d8SDoug Ambrisko io_request->EEDPFlags = 1145*665484d8SDoug Ambrisko MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | 1146*665484d8SDoug Ambrisko MPI2_SCSIIO_EEDPFLAGS_INSERT_OP; 1147*665484d8SDoug Ambrisko } 1148*665484d8SDoug Ambrisko io_request->Control |= (0x4 << 26); 1149*665484d8SDoug Ambrisko io_request->EEDPBlockSize = ld_block_size; 1150*665484d8SDoug Ambrisko } 1151*665484d8SDoug Ambrisko else { 1152*665484d8SDoug Ambrisko /* Some drives don't support 16/12 byte CDB's, convert to 10 */ 1153*665484d8SDoug Ambrisko if (((cdb_len == 12) || (cdb_len == 16)) && 1154*665484d8SDoug Ambrisko (start_blk <= 0xffffffff)) { 1155*665484d8SDoug Ambrisko if (cdb_len == 16) { 1156*665484d8SDoug Ambrisko opcode = cdb[0] == READ_16 ? READ_10 : WRITE_10; 1157*665484d8SDoug Ambrisko flagvals = cdb[1]; 1158*665484d8SDoug Ambrisko groupnum = cdb[14]; 1159*665484d8SDoug Ambrisko control = cdb[15]; 1160*665484d8SDoug Ambrisko } 1161*665484d8SDoug Ambrisko else { 1162*665484d8SDoug Ambrisko opcode = cdb[0] == READ_12 ? READ_10 : WRITE_10; 1163*665484d8SDoug Ambrisko flagvals = cdb[1]; 1164*665484d8SDoug Ambrisko groupnum = cdb[10]; 1165*665484d8SDoug Ambrisko control = cdb[11]; 1166*665484d8SDoug Ambrisko } 1167*665484d8SDoug Ambrisko 1168*665484d8SDoug Ambrisko memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1169*665484d8SDoug Ambrisko 1170*665484d8SDoug Ambrisko cdb[0] = opcode; 1171*665484d8SDoug Ambrisko cdb[1] = flagvals; 1172*665484d8SDoug Ambrisko cdb[6] = groupnum; 1173*665484d8SDoug Ambrisko cdb[9] = control; 1174*665484d8SDoug Ambrisko 1175*665484d8SDoug Ambrisko /* Transfer length */ 1176*665484d8SDoug Ambrisko cdb[8] = (u_int8_t)(num_blocks & 0xff); 1177*665484d8SDoug Ambrisko cdb[7] = (u_int8_t)((num_blocks >> 8) & 0xff); 1178*665484d8SDoug Ambrisko 1179*665484d8SDoug Ambrisko io_request->IoFlags = 10; /* Specify 10-byte cdb */ 1180*665484d8SDoug Ambrisko cdb_len = 10; 1181*665484d8SDoug Ambrisko } else if ((cdb_len < 16) && (start_blk > 0xffffffff)) { 1182*665484d8SDoug Ambrisko /* Convert to 16 byte CDB for large LBA's */ 1183*665484d8SDoug Ambrisko switch (cdb_len) { 1184*665484d8SDoug Ambrisko case 6: 1185*665484d8SDoug Ambrisko opcode = cdb[0] == READ_6 ? READ_16 : WRITE_16; 1186*665484d8SDoug Ambrisko control = cdb[5]; 1187*665484d8SDoug Ambrisko break; 1188*665484d8SDoug Ambrisko case 10: 1189*665484d8SDoug Ambrisko opcode = cdb[0] == READ_10 ? READ_16 : WRITE_16; 1190*665484d8SDoug Ambrisko flagvals = cdb[1]; 1191*665484d8SDoug Ambrisko groupnum = cdb[6]; 1192*665484d8SDoug Ambrisko control = cdb[9]; 1193*665484d8SDoug Ambrisko break; 1194*665484d8SDoug Ambrisko case 12: 1195*665484d8SDoug Ambrisko opcode = cdb[0] == READ_12 ? READ_16 : WRITE_16; 1196*665484d8SDoug Ambrisko flagvals = cdb[1]; 1197*665484d8SDoug Ambrisko groupnum = cdb[10]; 1198*665484d8SDoug Ambrisko control = cdb[11]; 1199*665484d8SDoug Ambrisko break; 1200*665484d8SDoug Ambrisko } 1201*665484d8SDoug Ambrisko 1202*665484d8SDoug Ambrisko memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1203*665484d8SDoug Ambrisko 1204*665484d8SDoug Ambrisko cdb[0] = opcode; 1205*665484d8SDoug Ambrisko cdb[1] = flagvals; 1206*665484d8SDoug Ambrisko cdb[14] = groupnum; 1207*665484d8SDoug Ambrisko cdb[15] = control; 1208*665484d8SDoug Ambrisko 1209*665484d8SDoug Ambrisko /* Transfer length */ 1210*665484d8SDoug Ambrisko cdb[13] = (u_int8_t)(num_blocks & 0xff); 1211*665484d8SDoug Ambrisko cdb[12] = (u_int8_t)((num_blocks >> 8) & 0xff); 1212*665484d8SDoug Ambrisko cdb[11] = (u_int8_t)((num_blocks >> 16) & 0xff); 1213*665484d8SDoug Ambrisko cdb[10] = (u_int8_t)((num_blocks >> 24) & 0xff); 1214*665484d8SDoug Ambrisko 1215*665484d8SDoug Ambrisko io_request->IoFlags = 16; /* Specify 16-byte cdb */ 1216*665484d8SDoug Ambrisko cdb_len = 16; 1217*665484d8SDoug Ambrisko } else if ((cdb_len == 6) && (start_blk > 0x1fffff)) { 1218*665484d8SDoug Ambrisko /* convert to 10 byte CDB */ 1219*665484d8SDoug Ambrisko opcode = cdb[0] == READ_6 ? READ_10 : WRITE_10; 1220*665484d8SDoug Ambrisko control = cdb[5]; 1221*665484d8SDoug Ambrisko 1222*665484d8SDoug Ambrisko memset(cdb, 0, sizeof(cdb)); 1223*665484d8SDoug Ambrisko cdb[0] = opcode; 1224*665484d8SDoug Ambrisko cdb[9] = control; 1225*665484d8SDoug Ambrisko 1226*665484d8SDoug Ambrisko /* Set transfer length */ 1227*665484d8SDoug Ambrisko cdb[8] = (u_int8_t)(num_blocks & 0xff); 1228*665484d8SDoug Ambrisko cdb[7] = (u_int8_t)((num_blocks >> 8) & 0xff); 1229*665484d8SDoug Ambrisko 1230*665484d8SDoug Ambrisko /* Specify 10-byte cdb */ 1231*665484d8SDoug Ambrisko cdb_len = 10; 1232*665484d8SDoug Ambrisko } 1233*665484d8SDoug Ambrisko 1234*665484d8SDoug Ambrisko /* Fall through normal case, just load LBA here */ 1235*665484d8SDoug Ambrisko switch (cdb_len) 1236*665484d8SDoug Ambrisko { 1237*665484d8SDoug Ambrisko case 6: 1238*665484d8SDoug Ambrisko { 1239*665484d8SDoug Ambrisko u_int8_t val = cdb[1] & 0xE0; 1240*665484d8SDoug Ambrisko cdb[3] = (u_int8_t)(start_blk & 0xff); 1241*665484d8SDoug Ambrisko cdb[2] = (u_int8_t)((start_blk >> 8) & 0xff); 1242*665484d8SDoug Ambrisko cdb[1] = val | ((u_int8_t)(start_blk >> 16) & 0x1f); 1243*665484d8SDoug Ambrisko break; 1244*665484d8SDoug Ambrisko } 1245*665484d8SDoug Ambrisko case 10: 1246*665484d8SDoug Ambrisko cdb[5] = (u_int8_t)(start_blk & 0xff); 1247*665484d8SDoug Ambrisko cdb[4] = (u_int8_t)((start_blk >> 8) & 0xff); 1248*665484d8SDoug Ambrisko cdb[3] = (u_int8_t)((start_blk >> 16) & 0xff); 1249*665484d8SDoug Ambrisko cdb[2] = (u_int8_t)((start_blk >> 24) & 0xff); 1250*665484d8SDoug Ambrisko break; 1251*665484d8SDoug Ambrisko case 12: 1252*665484d8SDoug Ambrisko cdb[5] = (u_int8_t)(start_blk & 0xff); 1253*665484d8SDoug Ambrisko cdb[4] = (u_int8_t)((start_blk >> 8) & 0xff); 1254*665484d8SDoug Ambrisko cdb[3] = (u_int8_t)((start_blk >> 16) & 0xff); 1255*665484d8SDoug Ambrisko cdb[2] = (u_int8_t)((start_blk >> 24) & 0xff); 1256*665484d8SDoug Ambrisko break; 1257*665484d8SDoug Ambrisko case 16: 1258*665484d8SDoug Ambrisko cdb[9] = (u_int8_t)(start_blk & 0xff); 1259*665484d8SDoug Ambrisko cdb[8] = (u_int8_t)((start_blk >> 8) & 0xff); 1260*665484d8SDoug Ambrisko cdb[7] = (u_int8_t)((start_blk >> 16) & 0xff); 1261*665484d8SDoug Ambrisko cdb[6] = (u_int8_t)((start_blk >> 24) & 0xff); 1262*665484d8SDoug Ambrisko cdb[5] = (u_int8_t)((start_blk >> 32) & 0xff); 1263*665484d8SDoug Ambrisko cdb[4] = (u_int8_t)((start_blk >> 40) & 0xff); 1264*665484d8SDoug Ambrisko cdb[3] = (u_int8_t)((start_blk >> 48) & 0xff); 1265*665484d8SDoug Ambrisko cdb[2] = (u_int8_t)((start_blk >> 56) & 0xff); 1266*665484d8SDoug Ambrisko break; 1267*665484d8SDoug Ambrisko } 1268*665484d8SDoug Ambrisko } 1269*665484d8SDoug Ambrisko } 1270*665484d8SDoug Ambrisko 1271*665484d8SDoug Ambrisko /** 1272*665484d8SDoug Ambrisko * mrsas_get_best_arm Determine the best spindle arm 1273*665484d8SDoug Ambrisko * Inputs: Load balance info 1274*665484d8SDoug Ambrisko * 1275*665484d8SDoug Ambrisko * This function determines and returns the best arm by looking at the 1276*665484d8SDoug Ambrisko * parameters of the last PD access. 1277*665484d8SDoug Ambrisko */ 1278*665484d8SDoug Ambrisko u_int8_t mrsas_get_best_arm(PLD_LOAD_BALANCE_INFO lbInfo, u_int8_t arm, 1279*665484d8SDoug Ambrisko u_int64_t block, u_int32_t count) 1280*665484d8SDoug Ambrisko { 1281*665484d8SDoug Ambrisko u_int16_t pend0, pend1; 1282*665484d8SDoug Ambrisko u_int64_t diff0, diff1; 1283*665484d8SDoug Ambrisko u_int8_t bestArm; 1284*665484d8SDoug Ambrisko 1285*665484d8SDoug Ambrisko /* get the pending cmds for the data and mirror arms */ 1286*665484d8SDoug Ambrisko pend0 = atomic_read(&lbInfo->scsi_pending_cmds[0]); 1287*665484d8SDoug Ambrisko pend1 = atomic_read(&lbInfo->scsi_pending_cmds[1]); 1288*665484d8SDoug Ambrisko 1289*665484d8SDoug Ambrisko /* Determine the disk whose head is nearer to the req. block */ 1290*665484d8SDoug Ambrisko diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[0]); 1291*665484d8SDoug Ambrisko diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[1]); 1292*665484d8SDoug Ambrisko bestArm = (diff0 <= diff1 ? 0 : 1); 1293*665484d8SDoug Ambrisko 1294*665484d8SDoug Ambrisko if ((bestArm == arm && pend0 > pend1 + 16) || (bestArm != arm && pend1 > pend0 + 16)) 1295*665484d8SDoug Ambrisko bestArm ^= 1; 1296*665484d8SDoug Ambrisko 1297*665484d8SDoug Ambrisko /* Update the last accessed block on the correct pd */ 1298*665484d8SDoug Ambrisko lbInfo->last_accessed_block[bestArm] = block + count - 1; 1299*665484d8SDoug Ambrisko 1300*665484d8SDoug Ambrisko return bestArm; 1301*665484d8SDoug Ambrisko } 1302*665484d8SDoug Ambrisko 1303*665484d8SDoug Ambrisko /** 1304*665484d8SDoug Ambrisko * mrsas_get_updated_dev_handle Get the update dev handle 1305*665484d8SDoug Ambrisko * Inputs: Load balance info 1306*665484d8SDoug Ambrisko * io_info pointer 1307*665484d8SDoug Ambrisko * 1308*665484d8SDoug Ambrisko * This function determines and returns the updated dev handle. 1309*665484d8SDoug Ambrisko */ 1310*665484d8SDoug Ambrisko u_int16_t mrsas_get_updated_dev_handle(PLD_LOAD_BALANCE_INFO lbInfo, 1311*665484d8SDoug Ambrisko struct IO_REQUEST_INFO *io_info) 1312*665484d8SDoug Ambrisko { 1313*665484d8SDoug Ambrisko u_int8_t arm, old_arm; 1314*665484d8SDoug Ambrisko u_int16_t devHandle; 1315*665484d8SDoug Ambrisko 1316*665484d8SDoug Ambrisko old_arm = lbInfo->raid1DevHandle[0] == io_info->devHandle ? 0 : 1; 1317*665484d8SDoug Ambrisko 1318*665484d8SDoug Ambrisko /* get best new arm */ 1319*665484d8SDoug Ambrisko arm = mrsas_get_best_arm(lbInfo, old_arm, io_info->ldStartBlock, io_info->numBlocks); 1320*665484d8SDoug Ambrisko devHandle = lbInfo->raid1DevHandle[arm]; 1321*665484d8SDoug Ambrisko atomic_inc(&lbInfo->scsi_pending_cmds[arm]); 1322*665484d8SDoug Ambrisko 1323*665484d8SDoug Ambrisko return devHandle; 1324*665484d8SDoug Ambrisko } 1325*665484d8SDoug Ambrisko 1326*665484d8SDoug Ambrisko /** 1327*665484d8SDoug Ambrisko * MR_GetPhyParams Calculates arm, span, and block 1328*665484d8SDoug Ambrisko * Inputs: Adapter instance soft state 1329*665484d8SDoug Ambrisko * Logical drive number (LD) 1330*665484d8SDoug Ambrisko * Stripe number (stripRow) 1331*665484d8SDoug Ambrisko * Reference in stripe (stripRef) 1332*665484d8SDoug Ambrisko * Outputs: Span number 1333*665484d8SDoug Ambrisko * Absolute Block number in the physical disk 1334*665484d8SDoug Ambrisko * 1335*665484d8SDoug Ambrisko * This routine calculates the arm, span and block for the specified stripe 1336*665484d8SDoug Ambrisko * and reference in stripe. 1337*665484d8SDoug Ambrisko */ 1338*665484d8SDoug Ambrisko u_int8_t MR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld, 1339*665484d8SDoug Ambrisko u_int64_t stripRow, 1340*665484d8SDoug Ambrisko u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 1341*665484d8SDoug Ambrisko RAID_CONTEXT *pRAID_Context, MR_FW_RAID_MAP_ALL *map) 1342*665484d8SDoug Ambrisko { 1343*665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 1344*665484d8SDoug Ambrisko u_int32_t pd, arRef; 1345*665484d8SDoug Ambrisko u_int8_t physArm, span; 1346*665484d8SDoug Ambrisko u_int64_t row; 1347*665484d8SDoug Ambrisko u_int8_t retval = TRUE; 1348*665484d8SDoug Ambrisko int error_code = 0; 1349*665484d8SDoug Ambrisko u_int64_t *pdBlock = &io_info->pdBlock; 1350*665484d8SDoug Ambrisko u_int16_t *pDevHandle = &io_info->devHandle; 1351*665484d8SDoug Ambrisko u_int32_t rowMod, armQ, arm, logArm; 1352*665484d8SDoug Ambrisko u_int8_t do_invader = 0; 1353*665484d8SDoug Ambrisko 1354*665484d8SDoug Ambrisko if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) 1355*665484d8SDoug Ambrisko do_invader = 1; 1356*665484d8SDoug Ambrisko 1357*665484d8SDoug Ambrisko row = mega_div64_32(stripRow, raid->rowDataSize); 1358*665484d8SDoug Ambrisko 1359*665484d8SDoug Ambrisko if (raid->level == 6) { 1360*665484d8SDoug Ambrisko logArm = mega_mod64(stripRow, raid->rowDataSize); // logical arm within row 1361*665484d8SDoug Ambrisko if (raid->rowSize == 0) 1362*665484d8SDoug Ambrisko return FALSE; 1363*665484d8SDoug Ambrisko rowMod = mega_mod64(row, raid->rowSize); // get logical row mod 1364*665484d8SDoug Ambrisko armQ = raid->rowSize-1-rowMod; // index of Q drive 1365*665484d8SDoug Ambrisko arm = armQ+1+logArm; // data always logically follows Q 1366*665484d8SDoug Ambrisko if (arm >= raid->rowSize) // handle wrap condition 1367*665484d8SDoug Ambrisko arm -= raid->rowSize; 1368*665484d8SDoug Ambrisko physArm = (u_int8_t)arm; 1369*665484d8SDoug Ambrisko } 1370*665484d8SDoug Ambrisko else { 1371*665484d8SDoug Ambrisko if (raid->modFactor == 0) 1372*665484d8SDoug Ambrisko return FALSE; 1373*665484d8SDoug Ambrisko physArm = MR_LdDataArmGet(ld, mega_mod64(stripRow, raid->modFactor), map); 1374*665484d8SDoug Ambrisko } 1375*665484d8SDoug Ambrisko 1376*665484d8SDoug Ambrisko if (raid->spanDepth == 1) { 1377*665484d8SDoug Ambrisko span = 0; 1378*665484d8SDoug Ambrisko *pdBlock = row << raid->stripeShift; 1379*665484d8SDoug Ambrisko } 1380*665484d8SDoug Ambrisko else { 1381*665484d8SDoug Ambrisko span = (u_int8_t)MR_GetSpanBlock(ld, row, pdBlock, map, &error_code); 1382*665484d8SDoug Ambrisko if (error_code == 1) 1383*665484d8SDoug Ambrisko return FALSE; 1384*665484d8SDoug Ambrisko } 1385*665484d8SDoug Ambrisko 1386*665484d8SDoug Ambrisko /* Get the array on which this span is present */ 1387*665484d8SDoug Ambrisko arRef = MR_LdSpanArrayGet(ld, span, map); 1388*665484d8SDoug Ambrisko 1389*665484d8SDoug Ambrisko pd = MR_ArPdGet(arRef, physArm, map); // Get the Pd. 1390*665484d8SDoug Ambrisko 1391*665484d8SDoug Ambrisko if (pd != MR_PD_INVALID) 1392*665484d8SDoug Ambrisko *pDevHandle = MR_PdDevHandleGet(pd, map); // Get dev handle from Pd. 1393*665484d8SDoug Ambrisko else { 1394*665484d8SDoug Ambrisko *pDevHandle = MR_PD_INVALID; // set dev handle as invalid. 1395*665484d8SDoug Ambrisko if ((raid->level >= 5) && ((!do_invader) || (do_invader && 1396*665484d8SDoug Ambrisko raid->regTypeReqOnRead != REGION_TYPE_UNUSED))) 1397*665484d8SDoug Ambrisko pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; 1398*665484d8SDoug Ambrisko else if (raid->level == 1) { 1399*665484d8SDoug Ambrisko pd = MR_ArPdGet(arRef, physArm + 1, map); // Get Alternate Pd. 1400*665484d8SDoug Ambrisko if (pd != MR_PD_INVALID) 1401*665484d8SDoug Ambrisko *pDevHandle = MR_PdDevHandleGet(pd, map);//Get dev handle from Pd. 1402*665484d8SDoug Ambrisko } 1403*665484d8SDoug Ambrisko } 1404*665484d8SDoug Ambrisko 1405*665484d8SDoug Ambrisko *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk; 1406*665484d8SDoug Ambrisko pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; 1407*665484d8SDoug Ambrisko return retval; 1408*665484d8SDoug Ambrisko } 1409*665484d8SDoug Ambrisko 1410*665484d8SDoug Ambrisko /** 1411*665484d8SDoug Ambrisko * MR_GetSpanBlock Calculates span block 1412*665484d8SDoug Ambrisko * Inputs: LD 1413*665484d8SDoug Ambrisko * row 1414*665484d8SDoug Ambrisko * PD span block 1415*665484d8SDoug Ambrisko * RAID map pointer 1416*665484d8SDoug Ambrisko * Outputs: Span number 1417*665484d8SDoug Ambrisko * Error code 1418*665484d8SDoug Ambrisko * 1419*665484d8SDoug Ambrisko * This routine calculates the span from the span block info. 1420*665484d8SDoug Ambrisko */ 1421*665484d8SDoug Ambrisko u_int32_t MR_GetSpanBlock(u_int32_t ld, u_int64_t row, u_int64_t *span_blk, 1422*665484d8SDoug Ambrisko MR_FW_RAID_MAP_ALL *map, int *div_error) 1423*665484d8SDoug Ambrisko { 1424*665484d8SDoug Ambrisko MR_SPAN_BLOCK_INFO *pSpanBlock = MR_LdSpanInfoGet(ld, map); 1425*665484d8SDoug Ambrisko MR_QUAD_ELEMENT *quad; 1426*665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 1427*665484d8SDoug Ambrisko u_int32_t span, j; 1428*665484d8SDoug Ambrisko u_int64_t blk, debugBlk; 1429*665484d8SDoug Ambrisko 1430*665484d8SDoug Ambrisko for (span=0; span < raid->spanDepth; span++, pSpanBlock++) { 1431*665484d8SDoug Ambrisko for (j=0; j < pSpanBlock->block_span_info.noElements; j++) { 1432*665484d8SDoug Ambrisko quad = &pSpanBlock->block_span_info.quad[j]; 1433*665484d8SDoug Ambrisko if (quad->diff == 0) { 1434*665484d8SDoug Ambrisko *div_error = 1; 1435*665484d8SDoug Ambrisko return span; 1436*665484d8SDoug Ambrisko } 1437*665484d8SDoug Ambrisko if (quad->logStart <= row && row <= quad->logEnd && 1438*665484d8SDoug Ambrisko (mega_mod64(row-quad->logStart, quad->diff)) == 0) { 1439*665484d8SDoug Ambrisko if (span_blk != NULL) { 1440*665484d8SDoug Ambrisko blk = mega_div64_32((row-quad->logStart), quad->diff); 1441*665484d8SDoug Ambrisko debugBlk = blk; 1442*665484d8SDoug Ambrisko blk = (blk + quad->offsetInSpan) << raid->stripeShift; 1443*665484d8SDoug Ambrisko *span_blk = blk; 1444*665484d8SDoug Ambrisko } 1445*665484d8SDoug Ambrisko return span; 1446*665484d8SDoug Ambrisko } 1447*665484d8SDoug Ambrisko } 1448*665484d8SDoug Ambrisko } 1449*665484d8SDoug Ambrisko return span; 1450*665484d8SDoug Ambrisko } 1451*665484d8SDoug Ambrisko 1452