1665484d8SDoug Ambrisko /* 2*8e727371SKashyap D Desai * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy 3665484d8SDoug Ambrisko * Support: freebsdraid@lsi.com 4665484d8SDoug Ambrisko * 5665484d8SDoug Ambrisko * Redistribution and use in source and binary forms, with or without 6*8e727371SKashyap D Desai * modification, are permitted provided that the following conditions are 7*8e727371SKashyap D Desai * met: 8665484d8SDoug Ambrisko * 9*8e727371SKashyap D Desai * 1. Redistributions of source code must retain the above copyright notice, 10*8e727371SKashyap D Desai * this list of conditions and the following disclaimer. 2. Redistributions 11*8e727371SKashyap D Desai * in binary form must reproduce the above copyright notice, this list of 12*8e727371SKashyap D Desai * conditions and the following disclaimer in the documentation and/or other 13*8e727371SKashyap D Desai * materials provided with the distribution. 3. Neither the name of the 14*8e727371SKashyap D Desai * <ORGANIZATION> nor the names of its contributors may be used to endorse or 15*8e727371SKashyap D Desai * promote products derived from this software without specific prior written 16*8e727371SKashyap D Desai * permission. 17665484d8SDoug Ambrisko * 18*8e727371SKashyap D Desai * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19*8e727371SKashyap D Desai * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20*8e727371SKashyap D Desai * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21*8e727371SKashyap D Desai * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22*8e727371SKashyap D Desai * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23*8e727371SKashyap D Desai * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24*8e727371SKashyap D Desai * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25*8e727371SKashyap D Desai * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26*8e727371SKashyap D Desai * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27*8e727371SKashyap D Desai * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28665484d8SDoug Ambrisko * POSSIBILITY OF SUCH DAMAGE. 29665484d8SDoug Ambrisko * 30*8e727371SKashyap D Desai * The views and conclusions contained in the software and documentation are 31*8e727371SKashyap D Desai * those of the authors and should not be interpreted as representing 32665484d8SDoug Ambrisko * official policies,either expressed or implied, of the FreeBSD Project. 33665484d8SDoug Ambrisko * 34*8e727371SKashyap D Desai * Send feedback to: <megaraidfbsd@lsi.com> Mail to: LSI Corporation, 1621 35*8e727371SKashyap D Desai * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD 36665484d8SDoug Ambrisko * 37665484d8SDoug Ambrisko */ 38665484d8SDoug Ambrisko 39665484d8SDoug Ambrisko #include <sys/cdefs.h> 40665484d8SDoug Ambrisko __FBSDID("$FreeBSD$"); 41665484d8SDoug Ambrisko 42665484d8SDoug Ambrisko #include <dev/mrsas/mrsas.h> 43665484d8SDoug Ambrisko 44665484d8SDoug Ambrisko #include <cam/cam.h> 45665484d8SDoug Ambrisko #include <cam/cam_ccb.h> 46665484d8SDoug Ambrisko #include <cam/cam_sim.h> 47665484d8SDoug Ambrisko #include <cam/cam_xpt_sim.h> 48665484d8SDoug Ambrisko #include <cam/cam_debug.h> 49665484d8SDoug Ambrisko #include <cam/cam_periph.h> 50665484d8SDoug Ambrisko #include <cam/cam_xpt_periph.h> 51665484d8SDoug Ambrisko 52665484d8SDoug Ambrisko 53665484d8SDoug Ambrisko /* 54665484d8SDoug Ambrisko * Function prototypes 55665484d8SDoug Ambrisko */ 56665484d8SDoug Ambrisko u_int8_t MR_ValidateMapInfo(struct mrsas_softc *sc); 57*8e727371SKashyap D Desai u_int8_t 58*8e727371SKashyap D Desai mrsas_get_best_arm(PLD_LOAD_BALANCE_INFO lbInfo, u_int8_t arm, 59665484d8SDoug Ambrisko u_int64_t block, u_int32_t count); 60*8e727371SKashyap D Desai u_int8_t 61*8e727371SKashyap D Desai MR_BuildRaidContext(struct mrsas_softc *sc, 62665484d8SDoug Ambrisko struct IO_REQUEST_INFO *io_info, 634799d485SKashyap D Desai RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map); 64*8e727371SKashyap D Desai u_int8_t 65*8e727371SKashyap D Desai MR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld, 66665484d8SDoug Ambrisko u_int64_t stripRow, u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 67665484d8SDoug Ambrisko RAID_CONTEXT * pRAID_Context, 684799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * map); 694799d485SKashyap D Desai u_int16_t MR_TargetIdToLdGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map); 704799d485SKashyap D Desai u_int32_t MR_LdBlockSizeGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map); 714799d485SKashyap D Desai u_int16_t MR_GetLDTgtId(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map); 72*8e727371SKashyap D Desai u_int16_t 73*8e727371SKashyap D Desai mrsas_get_updated_dev_handle(PLD_LOAD_BALANCE_INFO lbInfo, 74665484d8SDoug Ambrisko struct IO_REQUEST_INFO *io_info); 75665484d8SDoug Ambrisko u_int32_t mega_mod64(u_int64_t dividend, u_int32_t divisor); 76*8e727371SKashyap D Desai u_int32_t 77*8e727371SKashyap D Desai MR_GetSpanBlock(u_int32_t ld, u_int64_t row, u_int64_t *span_blk, 784799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * map, int *div_error); 79665484d8SDoug Ambrisko u_int64_t mega_div64_32(u_int64_t dividend, u_int32_t divisor); 80*8e727371SKashyap D Desai void 81*8e727371SKashyap D Desai mrsas_update_load_balance_params(MR_DRV_RAID_MAP_ALL * map, 82665484d8SDoug Ambrisko PLD_LOAD_BALANCE_INFO lbInfo); 83*8e727371SKashyap D Desai void 84*8e727371SKashyap D Desai mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request, 85665484d8SDoug Ambrisko u_int8_t cdb_len, struct IO_REQUEST_INFO *io_info, union ccb *ccb, 864799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * local_map_ptr, u_int32_t ref_tag, 87665484d8SDoug Ambrisko u_int32_t ld_block_size); 88*8e727371SKashyap D Desai static u_int16_t 89*8e727371SKashyap D Desai MR_LdSpanArrayGet(u_int32_t ld, u_int32_t span, 904799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * map); 914799d485SKashyap D Desai static u_int16_t MR_PdDevHandleGet(u_int32_t pd, MR_DRV_RAID_MAP_ALL * map); 92*8e727371SKashyap D Desai static u_int16_t 93*8e727371SKashyap D Desai MR_ArPdGet(u_int32_t ar, u_int32_t arm, 944799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * map); 95*8e727371SKashyap D Desai static MR_LD_SPAN * 96*8e727371SKashyap D Desai MR_LdSpanPtrGet(u_int32_t ld, u_int32_t span, 974799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * map); 98*8e727371SKashyap D Desai static u_int8_t 99*8e727371SKashyap D Desai MR_LdDataArmGet(u_int32_t ld, u_int32_t armIdx, 1004799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * map); 101*8e727371SKashyap D Desai static MR_SPAN_BLOCK_INFO * 102*8e727371SKashyap D Desai MR_LdSpanInfoGet(u_int32_t ld, 1034799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * map); 1044799d485SKashyap D Desai MR_LD_RAID *MR_LdRaidGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map); 1054799d485SKashyap D Desai void MR_PopulateDrvRaidMap(struct mrsas_softc *sc); 1064799d485SKashyap D Desai 107665484d8SDoug Ambrisko 108665484d8SDoug Ambrisko /* 109*8e727371SKashyap D Desai * Spanset related function prototypes Added for PRL11 configuration (Uneven 110*8e727371SKashyap D Desai * span support) 111665484d8SDoug Ambrisko */ 1124799d485SKashyap D Desai void mr_update_span_set(MR_DRV_RAID_MAP_ALL * map, PLD_SPAN_INFO ldSpanInfo); 113*8e727371SKashyap D Desai static u_int8_t 114*8e727371SKashyap D Desai mr_spanset_get_phy_params(struct mrsas_softc *sc, u_int32_t ld, 115665484d8SDoug Ambrisko u_int64_t stripRow, u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 1164799d485SKashyap D Desai RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map); 117*8e727371SKashyap D Desai static u_int64_t 118*8e727371SKashyap D Desai get_row_from_strip(struct mrsas_softc *sc, u_int32_t ld, 1194799d485SKashyap D Desai u_int64_t strip, MR_DRV_RAID_MAP_ALL * map); 120*8e727371SKashyap D Desai static u_int32_t 121*8e727371SKashyap D Desai mr_spanset_get_span_block(struct mrsas_softc *sc, 122665484d8SDoug Ambrisko u_int32_t ld, u_int64_t row, u_int64_t *span_blk, 1234799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * map, int *div_error); 124*8e727371SKashyap D Desai static u_int8_t 125*8e727371SKashyap D Desai get_arm(struct mrsas_softc *sc, u_int32_t ld, u_int8_t span, 1264799d485SKashyap D Desai u_int64_t stripe, MR_DRV_RAID_MAP_ALL * map); 127665484d8SDoug Ambrisko 128665484d8SDoug Ambrisko 129665484d8SDoug Ambrisko /* 130*8e727371SKashyap D Desai * Spanset related defines Added for PRL11 configuration(Uneven span support) 131665484d8SDoug Ambrisko */ 132665484d8SDoug Ambrisko #define SPAN_ROW_SIZE(map, ld, index_) MR_LdSpanPtrGet(ld, index_, map)->spanRowSize 133*8e727371SKashyap D Desai #define SPAN_ROW_DATA_SIZE(map_, ld, index_) \ 134*8e727371SKashyap D Desai MR_LdSpanPtrGet(ld, index_, map)->spanRowDataSize 135665484d8SDoug Ambrisko #define SPAN_INVALID 0xff 136665484d8SDoug Ambrisko #define SPAN_DEBUG 0 137665484d8SDoug Ambrisko 138665484d8SDoug Ambrisko /* 139665484d8SDoug Ambrisko * Related Defines 140665484d8SDoug Ambrisko */ 141665484d8SDoug Ambrisko 142665484d8SDoug Ambrisko typedef u_int64_t REGION_KEY; 143665484d8SDoug Ambrisko typedef u_int32_t REGION_LEN; 144665484d8SDoug Ambrisko 145665484d8SDoug Ambrisko #define MR_LD_STATE_OPTIMAL 3 146665484d8SDoug Ambrisko #define FALSE 0 147665484d8SDoug Ambrisko #define TRUE 1 148665484d8SDoug Ambrisko 149665484d8SDoug Ambrisko 150665484d8SDoug Ambrisko /* 151665484d8SDoug Ambrisko * Related Macros 152665484d8SDoug Ambrisko */ 153665484d8SDoug Ambrisko 154665484d8SDoug Ambrisko #define ABS_DIFF(a,b) ( ((a) > (b)) ? ((a) - (b)) : ((b) - (a)) ) 155665484d8SDoug Ambrisko 156665484d8SDoug Ambrisko #define swap32(x) \ 157665484d8SDoug Ambrisko ((unsigned int)( \ 158665484d8SDoug Ambrisko (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \ 159665484d8SDoug Ambrisko (((unsigned int)(x) & (unsigned int)0x0000ff00UL) << 8) | \ 160665484d8SDoug Ambrisko (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >> 8) | \ 161665484d8SDoug Ambrisko (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) )) 162665484d8SDoug Ambrisko 163665484d8SDoug Ambrisko 164665484d8SDoug Ambrisko /* 165*8e727371SKashyap D Desai * In-line functions for mod and divide of 64-bit dividend and 32-bit 166*8e727371SKashyap D Desai * divisor. Assumes a check for a divisor of zero is not possible. 167665484d8SDoug Ambrisko * 168665484d8SDoug Ambrisko * @param dividend: Dividend 169665484d8SDoug Ambrisko * @param divisor: Divisor 170665484d8SDoug Ambrisko * @return remainder 171665484d8SDoug Ambrisko */ 172665484d8SDoug Ambrisko 173665484d8SDoug Ambrisko #define mega_mod64(dividend, divisor) ({ \ 174665484d8SDoug Ambrisko int remainder; \ 175665484d8SDoug Ambrisko remainder = ((u_int64_t) (dividend)) % (u_int32_t) (divisor); \ 176665484d8SDoug Ambrisko remainder;}) 177665484d8SDoug Ambrisko 178665484d8SDoug Ambrisko #define mega_div64_32(dividend, divisor) ({ \ 179665484d8SDoug Ambrisko int quotient; \ 180665484d8SDoug Ambrisko quotient = ((u_int64_t) (dividend)) / (u_int32_t) (divisor); \ 181665484d8SDoug Ambrisko quotient;}) 182665484d8SDoug Ambrisko 183665484d8SDoug Ambrisko 184665484d8SDoug Ambrisko /* 185665484d8SDoug Ambrisko * Various RAID map access functions. These functions access the various 186665484d8SDoug Ambrisko * parts of the RAID map and returns the appropriate parameters. 187665484d8SDoug Ambrisko */ 188665484d8SDoug Ambrisko 189*8e727371SKashyap D Desai MR_LD_RAID * 190*8e727371SKashyap D Desai MR_LdRaidGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map) 191665484d8SDoug Ambrisko { 192665484d8SDoug Ambrisko return (&map->raidMap.ldSpanMap[ld].ldRaid); 193665484d8SDoug Ambrisko } 194665484d8SDoug Ambrisko 195*8e727371SKashyap D Desai u_int16_t 196*8e727371SKashyap D Desai MR_GetLDTgtId(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map) 197665484d8SDoug Ambrisko { 198665484d8SDoug Ambrisko return (map->raidMap.ldSpanMap[ld].ldRaid.targetId); 199665484d8SDoug Ambrisko } 200665484d8SDoug Ambrisko 201*8e727371SKashyap D Desai static u_int16_t 202*8e727371SKashyap D Desai MR_LdSpanArrayGet(u_int32_t ld, u_int32_t span, MR_DRV_RAID_MAP_ALL * map) 203665484d8SDoug Ambrisko { 204665484d8SDoug Ambrisko return map->raidMap.ldSpanMap[ld].spanBlock[span].span.arrayRef; 205665484d8SDoug Ambrisko } 206665484d8SDoug Ambrisko 207*8e727371SKashyap D Desai static u_int8_t 208*8e727371SKashyap D Desai MR_LdDataArmGet(u_int32_t ld, u_int32_t armIdx, MR_DRV_RAID_MAP_ALL * map) 209665484d8SDoug Ambrisko { 210665484d8SDoug Ambrisko return map->raidMap.ldSpanMap[ld].dataArmMap[armIdx]; 211665484d8SDoug Ambrisko } 212665484d8SDoug Ambrisko 213*8e727371SKashyap D Desai static u_int16_t 214*8e727371SKashyap D Desai MR_PdDevHandleGet(u_int32_t pd, MR_DRV_RAID_MAP_ALL * map) 215665484d8SDoug Ambrisko { 216665484d8SDoug Ambrisko return map->raidMap.devHndlInfo[pd].curDevHdl; 217665484d8SDoug Ambrisko } 218665484d8SDoug Ambrisko 219*8e727371SKashyap D Desai static u_int16_t 220*8e727371SKashyap D Desai MR_ArPdGet(u_int32_t ar, u_int32_t arm, MR_DRV_RAID_MAP_ALL * map) 221665484d8SDoug Ambrisko { 222665484d8SDoug Ambrisko return map->raidMap.arMapInfo[ar].pd[arm]; 223665484d8SDoug Ambrisko } 224665484d8SDoug Ambrisko 225*8e727371SKashyap D Desai static MR_LD_SPAN * 226*8e727371SKashyap D Desai MR_LdSpanPtrGet(u_int32_t ld, u_int32_t span, MR_DRV_RAID_MAP_ALL * map) 227665484d8SDoug Ambrisko { 228665484d8SDoug Ambrisko return &map->raidMap.ldSpanMap[ld].spanBlock[span].span; 229665484d8SDoug Ambrisko } 230665484d8SDoug Ambrisko 231*8e727371SKashyap D Desai static MR_SPAN_BLOCK_INFO * 232*8e727371SKashyap D Desai MR_LdSpanInfoGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map) 233665484d8SDoug Ambrisko { 234665484d8SDoug Ambrisko return &map->raidMap.ldSpanMap[ld].spanBlock[0]; 235665484d8SDoug Ambrisko } 236665484d8SDoug Ambrisko 237*8e727371SKashyap D Desai u_int16_t 238*8e727371SKashyap D Desai MR_TargetIdToLdGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map) 239665484d8SDoug Ambrisko { 240665484d8SDoug Ambrisko return map->raidMap.ldTgtIdToLd[ldTgtId]; 241665484d8SDoug Ambrisko } 242665484d8SDoug Ambrisko 243*8e727371SKashyap D Desai u_int32_t 244*8e727371SKashyap D Desai MR_LdBlockSizeGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map) 245665484d8SDoug Ambrisko { 246665484d8SDoug Ambrisko MR_LD_RAID *raid; 247665484d8SDoug Ambrisko u_int32_t ld, ldBlockSize = MRSAS_SCSIBLOCKSIZE; 248665484d8SDoug Ambrisko 249665484d8SDoug Ambrisko ld = MR_TargetIdToLdGet(ldTgtId, map); 250665484d8SDoug Ambrisko 251665484d8SDoug Ambrisko /* 252665484d8SDoug Ambrisko * Check if logical drive was removed. 253665484d8SDoug Ambrisko */ 254665484d8SDoug Ambrisko if (ld >= MAX_LOGICAL_DRIVES) 255665484d8SDoug Ambrisko return ldBlockSize; 256665484d8SDoug Ambrisko 257665484d8SDoug Ambrisko raid = MR_LdRaidGet(ld, map); 258665484d8SDoug Ambrisko ldBlockSize = raid->logicalBlockLength; 259665484d8SDoug Ambrisko if (!ldBlockSize) 260665484d8SDoug Ambrisko ldBlockSize = MRSAS_SCSIBLOCKSIZE; 261665484d8SDoug Ambrisko 262665484d8SDoug Ambrisko return ldBlockSize; 263665484d8SDoug Ambrisko } 264665484d8SDoug Ambrisko 2654799d485SKashyap D Desai /* 2664799d485SKashyap D Desai * This function will Populate Driver Map using firmware raid map 2674799d485SKashyap D Desai */ 268*8e727371SKashyap D Desai void 269*8e727371SKashyap D Desai MR_PopulateDrvRaidMap(struct mrsas_softc *sc) 2704799d485SKashyap D Desai { 2714799d485SKashyap D Desai MR_FW_RAID_MAP_ALL *fw_map_old = NULL; 2724799d485SKashyap D Desai MR_FW_RAID_MAP *pFwRaidMap = NULL; 2734799d485SKashyap D Desai unsigned int i; 2744799d485SKashyap D Desai 2754799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL *drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 2764799d485SKashyap D Desai MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap; 2774799d485SKashyap D Desai 2784799d485SKashyap D Desai if (sc->max256vdSupport) { 2794799d485SKashyap D Desai memcpy(sc->ld_drv_map[sc->map_id & 1], 2804799d485SKashyap D Desai sc->raidmap_mem[sc->map_id & 1], 2814799d485SKashyap D Desai sc->current_map_sz); 282*8e727371SKashyap D Desai /* 283*8e727371SKashyap D Desai * New Raid map will not set totalSize, so keep expected 284*8e727371SKashyap D Desai * value for legacy code in ValidateMapInfo 2854799d485SKashyap D Desai */ 2864799d485SKashyap D Desai pDrvRaidMap->totalSize = sizeof(MR_FW_RAID_MAP_EXT); 2874799d485SKashyap D Desai } else { 2884799d485SKashyap D Desai fw_map_old = (MR_FW_RAID_MAP_ALL *) sc->raidmap_mem[(sc->map_id & 1)]; 2894799d485SKashyap D Desai pFwRaidMap = &fw_map_old->raidMap; 2904799d485SKashyap D Desai 2914799d485SKashyap D Desai #if VD_EXT_DEBUG 2924799d485SKashyap D Desai for (i = 0; i < pFwRaidMap->ldCount; i++) { 2934799d485SKashyap D Desai device_printf(sc->mrsas_dev, 2944799d485SKashyap D Desai "Index 0x%x Target Id 0x%x Seq Num 0x%x Size 0/%lx\n", i, 2954799d485SKashyap D Desai fw_map_old->raidMap.ldSpanMap[i].ldRaid.targetId, 2964799d485SKashyap D Desai fw_map_old->raidMap.ldSpanMap[i].ldRaid.seqNum, 2974799d485SKashyap D Desai fw_map_old->raidMap.ldSpanMap[i].ldRaid.size); 2984799d485SKashyap D Desai } 2994799d485SKashyap D Desai #endif 3004799d485SKashyap D Desai 3014799d485SKashyap D Desai memset(drv_map, 0, sc->drv_map_sz); 3024799d485SKashyap D Desai pDrvRaidMap->totalSize = pFwRaidMap->totalSize; 3034799d485SKashyap D Desai pDrvRaidMap->ldCount = pFwRaidMap->ldCount; 3044799d485SKashyap D Desai pDrvRaidMap->fpPdIoTimeoutSec = 3054799d485SKashyap D Desai pFwRaidMap->fpPdIoTimeoutSec; 3064799d485SKashyap D Desai 3074799d485SKashyap D Desai for (i = 0; i < MAX_RAIDMAP_LOGICAL_DRIVES + MAX_RAIDMAP_VIEWS; i++) { 3084799d485SKashyap D Desai pDrvRaidMap->ldTgtIdToLd[i] = 3094799d485SKashyap D Desai (u_int8_t)pFwRaidMap->ldTgtIdToLd[i]; 3104799d485SKashyap D Desai } 3114799d485SKashyap D Desai 3124799d485SKashyap D Desai for (i = 0; i < pDrvRaidMap->ldCount; i++) { 3134799d485SKashyap D Desai pDrvRaidMap->ldSpanMap[i] = 3144799d485SKashyap D Desai pFwRaidMap->ldSpanMap[i]; 3154799d485SKashyap D Desai 3164799d485SKashyap D Desai #if VD_EXT_DEBUG 3174799d485SKashyap D Desai device_printf(sc->mrsas_dev, "pFwRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x " 3184799d485SKashyap D Desai "pFwRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x size 0x%x\n", 3194799d485SKashyap D Desai i, i, pFwRaidMap->ldSpanMap[i].ldRaid.targetId, 3204799d485SKashyap D Desai pFwRaidMap->ldSpanMap[i].ldRaid.seqNum, 3214799d485SKashyap D Desai (u_int32_t)pFwRaidMap->ldSpanMap[i].ldRaid.rowSize); 3224799d485SKashyap D Desai device_printf(sc->mrsas_dev, "pDrvRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x" 3234799d485SKashyap D Desai "pDrvRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x size 0x%x\n", i, i, 3244799d485SKashyap D Desai pDrvRaidMap->ldSpanMap[i].ldRaid.targetId, 3254799d485SKashyap D Desai pDrvRaidMap->ldSpanMap[i].ldRaid.seqNum, 3264799d485SKashyap D Desai (u_int32_t)pDrvRaidMap->ldSpanMap[i].ldRaid.rowSize); 3274799d485SKashyap D Desai device_printf(sc->mrsas_dev, "drv raid map all %p raid map %p LD RAID MAP %p/%p\n", 3284799d485SKashyap D Desai drv_map, pDrvRaidMap, 3294799d485SKashyap D Desai &pFwRaidMap->ldSpanMap[i].ldRaid, &pDrvRaidMap->ldSpanMap[i].ldRaid); 3304799d485SKashyap D Desai #endif 3314799d485SKashyap D Desai } 3324799d485SKashyap D Desai 3334799d485SKashyap D Desai memcpy(pDrvRaidMap->arMapInfo, pFwRaidMap->arMapInfo, 3344799d485SKashyap D Desai sizeof(MR_ARRAY_INFO) * MAX_RAIDMAP_ARRAYS); 3354799d485SKashyap D Desai memcpy(pDrvRaidMap->devHndlInfo, pFwRaidMap->devHndlInfo, 3364799d485SKashyap D Desai sizeof(MR_DEV_HANDLE_INFO) * 3374799d485SKashyap D Desai MAX_RAIDMAP_PHYSICAL_DEVICES); 3384799d485SKashyap D Desai } 3394799d485SKashyap D Desai } 3404799d485SKashyap D Desai 341*8e727371SKashyap D Desai /* 342665484d8SDoug Ambrisko * MR_ValidateMapInfo: Validate RAID map 343665484d8SDoug Ambrisko * input: Adapter instance soft state 344665484d8SDoug Ambrisko * 345665484d8SDoug Ambrisko * This function checks and validates the loaded RAID map. It returns 0 if 346665484d8SDoug Ambrisko * successful, and 1 otherwise. 347665484d8SDoug Ambrisko */ 348*8e727371SKashyap D Desai u_int8_t 349*8e727371SKashyap D Desai MR_ValidateMapInfo(struct mrsas_softc *sc) 350665484d8SDoug Ambrisko { 351665484d8SDoug Ambrisko if (!sc) { 352665484d8SDoug Ambrisko return 1; 353665484d8SDoug Ambrisko } 3544799d485SKashyap D Desai MR_PopulateDrvRaidMap(sc); 3554799d485SKashyap D Desai 3564799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL *drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 3574799d485SKashyap D Desai MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap; 3584799d485SKashyap D Desai 3594799d485SKashyap D Desai u_int32_t expected_map_size; 360*8e727371SKashyap D Desai 3614799d485SKashyap D Desai drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 3624799d485SKashyap D Desai pDrvRaidMap = &drv_map->raidMap; 363665484d8SDoug Ambrisko PLD_SPAN_INFO ldSpanInfo = (PLD_SPAN_INFO) & sc->log_to_span; 364665484d8SDoug Ambrisko 3654799d485SKashyap D Desai if (sc->max256vdSupport) 3664799d485SKashyap D Desai expected_map_size = sizeof(MR_FW_RAID_MAP_EXT); 3674799d485SKashyap D Desai else 3684799d485SKashyap D Desai expected_map_size = 3694799d485SKashyap D Desai (sizeof(MR_FW_RAID_MAP) - sizeof(MR_LD_SPAN_MAP)) + 3704799d485SKashyap D Desai (sizeof(MR_LD_SPAN_MAP) * pDrvRaidMap->ldCount); 371665484d8SDoug Ambrisko 3724799d485SKashyap D Desai if (pDrvRaidMap->totalSize != expected_map_size) { 3734799d485SKashyap D Desai device_printf(sc->mrsas_dev, "map size %x not matching ld count\n", expected_map_size); 374665484d8SDoug Ambrisko device_printf(sc->mrsas_dev, "span map= %x\n", (unsigned int)sizeof(MR_LD_SPAN_MAP)); 3754799d485SKashyap D Desai device_printf(sc->mrsas_dev, "pDrvRaidMap->totalSize=%x\n", pDrvRaidMap->totalSize); 376665484d8SDoug Ambrisko return 1; 377665484d8SDoug Ambrisko } 378665484d8SDoug Ambrisko if (sc->UnevenSpanSupport) { 3794799d485SKashyap D Desai printf("Updating span set\n\n"); 3804799d485SKashyap D Desai mr_update_span_set(drv_map, ldSpanInfo); 381665484d8SDoug Ambrisko } 3824799d485SKashyap D Desai mrsas_update_load_balance_params(drv_map, sc->load_balance_info); 383665484d8SDoug Ambrisko 384665484d8SDoug Ambrisko return 0; 385665484d8SDoug Ambrisko } 386665484d8SDoug Ambrisko 387665484d8SDoug Ambrisko /* 388665484d8SDoug Ambrisko * 389665484d8SDoug Ambrisko * Function to print info about span set created in driver from FW raid map 390665484d8SDoug Ambrisko * 391*8e727371SKashyap D Desai * Inputs: map 392*8e727371SKashyap D Desai * ldSpanInfo: ld map span info per HBA instance 393665484d8SDoug Ambrisko * 394665484d8SDoug Ambrisko * 395*8e727371SKashyap D Desai */ 396665484d8SDoug Ambrisko #if SPAN_DEBUG 397*8e727371SKashyap D Desai static int 398*8e727371SKashyap D Desai getSpanInfo(MR_DRV_RAID_MAP_ALL * map, PLD_SPAN_INFO ldSpanInfo) 399665484d8SDoug Ambrisko { 400665484d8SDoug Ambrisko 401665484d8SDoug Ambrisko u_int8_t span; 402665484d8SDoug Ambrisko u_int32_t element; 403665484d8SDoug Ambrisko MR_LD_RAID *raid; 404665484d8SDoug Ambrisko LD_SPAN_SET *span_set; 405665484d8SDoug Ambrisko MR_QUAD_ELEMENT *quad; 406665484d8SDoug Ambrisko int ldCount; 407665484d8SDoug Ambrisko u_int16_t ld; 408665484d8SDoug Ambrisko 409*8e727371SKashyap D Desai for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) { 410665484d8SDoug Ambrisko ld = MR_TargetIdToLdGet(ldCount, map); 411665484d8SDoug Ambrisko if (ld >= MAX_LOGICAL_DRIVES) { 412665484d8SDoug Ambrisko continue; 413665484d8SDoug Ambrisko } 414665484d8SDoug Ambrisko raid = MR_LdRaidGet(ld, map); 415665484d8SDoug Ambrisko printf("LD %x: span_depth=%x\n", ld, raid->spanDepth); 416665484d8SDoug Ambrisko for (span = 0; span < raid->spanDepth; span++) 417665484d8SDoug Ambrisko printf("Span=%x, number of quads=%x\n", span, 418665484d8SDoug Ambrisko map->raidMap.ldSpanMap[ld].spanBlock[span]. 419665484d8SDoug Ambrisko block_span_info.noElements); 420665484d8SDoug Ambrisko for (element = 0; element < MAX_QUAD_DEPTH; element++) { 421665484d8SDoug Ambrisko span_set = &(ldSpanInfo[ld].span_set[element]); 422*8e727371SKashyap D Desai if (span_set->span_row_data_width == 0) 423*8e727371SKashyap D Desai break; 424665484d8SDoug Ambrisko 425665484d8SDoug Ambrisko printf("Span Set %x: width=%x, diff=%x\n", element, 426665484d8SDoug Ambrisko (unsigned int)span_set->span_row_data_width, 427665484d8SDoug Ambrisko (unsigned int)span_set->diff); 428665484d8SDoug Ambrisko printf("logical LBA start=0x%08lx, end=0x%08lx\n", 429665484d8SDoug Ambrisko (long unsigned int)span_set->log_start_lba, 430665484d8SDoug Ambrisko (long unsigned int)span_set->log_end_lba); 431665484d8SDoug Ambrisko printf("span row start=0x%08lx, end=0x%08lx\n", 432665484d8SDoug Ambrisko (long unsigned int)span_set->span_row_start, 433665484d8SDoug Ambrisko (long unsigned int)span_set->span_row_end); 434665484d8SDoug Ambrisko printf("data row start=0x%08lx, end=0x%08lx\n", 435665484d8SDoug Ambrisko (long unsigned int)span_set->data_row_start, 436665484d8SDoug Ambrisko (long unsigned int)span_set->data_row_end); 437665484d8SDoug Ambrisko printf("data strip start=0x%08lx, end=0x%08lx\n", 438665484d8SDoug Ambrisko (long unsigned int)span_set->data_strip_start, 439665484d8SDoug Ambrisko (long unsigned int)span_set->data_strip_end); 440665484d8SDoug Ambrisko 441665484d8SDoug Ambrisko for (span = 0; span < raid->spanDepth; span++) { 442665484d8SDoug Ambrisko if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 443665484d8SDoug Ambrisko block_span_info.noElements >= element + 1) { 444665484d8SDoug Ambrisko quad = &map->raidMap.ldSpanMap[ld]. 445665484d8SDoug Ambrisko spanBlock[span].block_span_info. 446665484d8SDoug Ambrisko quad[element]; 447665484d8SDoug Ambrisko printf("Span=%x, Quad=%x, diff=%x\n", span, 448665484d8SDoug Ambrisko element, quad->diff); 449665484d8SDoug Ambrisko printf("offset_in_span=0x%08lx\n", 450665484d8SDoug Ambrisko (long unsigned int)quad->offsetInSpan); 451665484d8SDoug Ambrisko printf("logical start=0x%08lx, end=0x%08lx\n", 452665484d8SDoug Ambrisko (long unsigned int)quad->logStart, 453665484d8SDoug Ambrisko (long unsigned int)quad->logEnd); 454665484d8SDoug Ambrisko } 455665484d8SDoug Ambrisko } 456665484d8SDoug Ambrisko } 457665484d8SDoug Ambrisko } 458665484d8SDoug Ambrisko return 0; 459665484d8SDoug Ambrisko } 460*8e727371SKashyap D Desai 461665484d8SDoug Ambrisko #endif 462665484d8SDoug Ambrisko /* 463665484d8SDoug Ambrisko * 464665484d8SDoug Ambrisko * This routine calculates the Span block for given row using spanset. 465665484d8SDoug Ambrisko * 466*8e727371SKashyap D Desai * Inputs : HBA instance 467*8e727371SKashyap D Desai * ld: Logical drive number 468*8e727371SKashyap D Desai * row: Row number 469*8e727371SKashyap D Desai * map: LD map 470665484d8SDoug Ambrisko * 471*8e727371SKashyap D Desai * Outputs : span - Span number block 472*8e727371SKashyap D Desai * - Absolute Block number in the physical disk 473665484d8SDoug Ambrisko * div_error - Devide error code. 474665484d8SDoug Ambrisko */ 475665484d8SDoug Ambrisko 476*8e727371SKashyap D Desai u_int32_t 477*8e727371SKashyap D Desai mr_spanset_get_span_block(struct mrsas_softc *sc, u_int32_t ld, u_int64_t row, 4784799d485SKashyap D Desai u_int64_t *span_blk, MR_DRV_RAID_MAP_ALL * map, int *div_error) 479665484d8SDoug Ambrisko { 480665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 481665484d8SDoug Ambrisko LD_SPAN_SET *span_set; 482665484d8SDoug Ambrisko MR_QUAD_ELEMENT *quad; 483665484d8SDoug Ambrisko u_int32_t span, info; 484665484d8SDoug Ambrisko PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 485665484d8SDoug Ambrisko 486665484d8SDoug Ambrisko for (info = 0; info < MAX_QUAD_DEPTH; info++) { 487665484d8SDoug Ambrisko span_set = &(ldSpanInfo[ld].span_set[info]); 488665484d8SDoug Ambrisko 489*8e727371SKashyap D Desai if (span_set->span_row_data_width == 0) 490*8e727371SKashyap D Desai break; 491*8e727371SKashyap D Desai if (row > span_set->data_row_end) 492*8e727371SKashyap D Desai continue; 493665484d8SDoug Ambrisko 494665484d8SDoug Ambrisko for (span = 0; span < raid->spanDepth; span++) 495665484d8SDoug Ambrisko if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 496665484d8SDoug Ambrisko block_span_info.noElements >= info + 1) { 497665484d8SDoug Ambrisko quad = &map->raidMap.ldSpanMap[ld]. 498665484d8SDoug Ambrisko spanBlock[span]. 499665484d8SDoug Ambrisko block_span_info.quad[info]; 500665484d8SDoug Ambrisko if (quad->diff == 0) { 501665484d8SDoug Ambrisko *div_error = 1; 502665484d8SDoug Ambrisko return span; 503665484d8SDoug Ambrisko } 504665484d8SDoug Ambrisko if (quad->logStart <= row && 505665484d8SDoug Ambrisko row <= quad->logEnd && 506665484d8SDoug Ambrisko (mega_mod64(row - quad->logStart, 507665484d8SDoug Ambrisko quad->diff)) == 0) { 508665484d8SDoug Ambrisko if (span_blk != NULL) { 509665484d8SDoug Ambrisko u_int64_t blk; 510*8e727371SKashyap D Desai 511665484d8SDoug Ambrisko blk = mega_div64_32 512665484d8SDoug Ambrisko ((row - quad->logStart), 513665484d8SDoug Ambrisko quad->diff); 514665484d8SDoug Ambrisko blk = (blk + quad->offsetInSpan) 515665484d8SDoug Ambrisko << raid->stripeShift; 516665484d8SDoug Ambrisko *span_blk = blk; 517665484d8SDoug Ambrisko } 518665484d8SDoug Ambrisko return span; 519665484d8SDoug Ambrisko } 520665484d8SDoug Ambrisko } 521665484d8SDoug Ambrisko } 522665484d8SDoug Ambrisko return SPAN_INVALID; 523665484d8SDoug Ambrisko } 524665484d8SDoug Ambrisko 525665484d8SDoug Ambrisko /* 526665484d8SDoug Ambrisko * 527665484d8SDoug Ambrisko * This routine calculates the row for given strip using spanset. 528665484d8SDoug Ambrisko * 529*8e727371SKashyap D Desai * Inputs : HBA instance 530*8e727371SKashyap D Desai * ld: Logical drive number 531*8e727371SKashyap D Desai * Strip: Strip 532*8e727371SKashyap D Desai * map: LD map 533665484d8SDoug Ambrisko * 534*8e727371SKashyap D Desai * Outputs : row - row associated with strip 535665484d8SDoug Ambrisko */ 536665484d8SDoug Ambrisko 537*8e727371SKashyap D Desai static u_int64_t 538*8e727371SKashyap D Desai get_row_from_strip(struct mrsas_softc *sc, 5394799d485SKashyap D Desai u_int32_t ld, u_int64_t strip, MR_DRV_RAID_MAP_ALL * map) 540665484d8SDoug Ambrisko { 541665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 542665484d8SDoug Ambrisko LD_SPAN_SET *span_set; 543665484d8SDoug Ambrisko PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 544665484d8SDoug Ambrisko u_int32_t info, strip_offset, span, span_offset; 545665484d8SDoug Ambrisko u_int64_t span_set_Strip, span_set_Row; 546665484d8SDoug Ambrisko 547665484d8SDoug Ambrisko for (info = 0; info < MAX_QUAD_DEPTH; info++) { 548665484d8SDoug Ambrisko span_set = &(ldSpanInfo[ld].span_set[info]); 549665484d8SDoug Ambrisko 550*8e727371SKashyap D Desai if (span_set->span_row_data_width == 0) 551*8e727371SKashyap D Desai break; 552*8e727371SKashyap D Desai if (strip > span_set->data_strip_end) 553*8e727371SKashyap D Desai continue; 554665484d8SDoug Ambrisko 555665484d8SDoug Ambrisko span_set_Strip = strip - span_set->data_strip_start; 556665484d8SDoug Ambrisko strip_offset = mega_mod64(span_set_Strip, 557665484d8SDoug Ambrisko span_set->span_row_data_width); 558665484d8SDoug Ambrisko span_set_Row = mega_div64_32(span_set_Strip, 559665484d8SDoug Ambrisko span_set->span_row_data_width) * span_set->diff; 560665484d8SDoug Ambrisko for (span = 0, span_offset = 0; span < raid->spanDepth; span++) 561665484d8SDoug Ambrisko if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 562665484d8SDoug Ambrisko block_span_info.noElements >= info + 1) { 563665484d8SDoug Ambrisko if (strip_offset >= 564665484d8SDoug Ambrisko span_set->strip_offset[span]) 565665484d8SDoug Ambrisko span_offset++; 566665484d8SDoug Ambrisko else 567665484d8SDoug Ambrisko break; 568665484d8SDoug Ambrisko } 569665484d8SDoug Ambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : Strip 0x%llx, span_set_Strip 0x%llx, span_set_Row 0x%llx " 570665484d8SDoug Ambrisko "data width 0x%llx span offset 0x%llx\n", (unsigned long long)strip, 571665484d8SDoug Ambrisko (unsigned long long)span_set_Strip, 572665484d8SDoug Ambrisko (unsigned long long)span_set_Row, 573665484d8SDoug Ambrisko (unsigned long long)span_set->span_row_data_width, (unsigned long long)span_offset); 574665484d8SDoug Ambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : For strip 0x%llx row is 0x%llx\n", (unsigned long long)strip, 575665484d8SDoug Ambrisko (unsigned long long)span_set->data_row_start + 576665484d8SDoug Ambrisko (unsigned long long)span_set_Row + (span_offset - 1)); 577665484d8SDoug Ambrisko return (span_set->data_row_start + span_set_Row + (span_offset - 1)); 578665484d8SDoug Ambrisko } 579665484d8SDoug Ambrisko return -1LLU; 580665484d8SDoug Ambrisko } 581665484d8SDoug Ambrisko 582665484d8SDoug Ambrisko 583665484d8SDoug Ambrisko /* 584665484d8SDoug Ambrisko * 585665484d8SDoug Ambrisko * This routine calculates the Start Strip for given row using spanset. 586665484d8SDoug Ambrisko * 587*8e727371SKashyap D Desai * Inputs: HBA instance 588*8e727371SKashyap D Desai * ld: Logical drive number 589*8e727371SKashyap D Desai * row: Row number 590*8e727371SKashyap D Desai * map: LD map 591665484d8SDoug Ambrisko * 592*8e727371SKashyap D Desai * Outputs : Strip - Start strip associated with row 593665484d8SDoug Ambrisko */ 594665484d8SDoug Ambrisko 595*8e727371SKashyap D Desai static u_int64_t 596*8e727371SKashyap D Desai get_strip_from_row(struct mrsas_softc *sc, 5974799d485SKashyap D Desai u_int32_t ld, u_int64_t row, MR_DRV_RAID_MAP_ALL * map) 598665484d8SDoug Ambrisko { 599665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 600665484d8SDoug Ambrisko LD_SPAN_SET *span_set; 601665484d8SDoug Ambrisko MR_QUAD_ELEMENT *quad; 602665484d8SDoug Ambrisko PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 603665484d8SDoug Ambrisko u_int32_t span, info; 604665484d8SDoug Ambrisko u_int64_t strip; 605665484d8SDoug Ambrisko 606665484d8SDoug Ambrisko for (info = 0; info < MAX_QUAD_DEPTH; info++) { 607665484d8SDoug Ambrisko span_set = &(ldSpanInfo[ld].span_set[info]); 608665484d8SDoug Ambrisko 609*8e727371SKashyap D Desai if (span_set->span_row_data_width == 0) 610*8e727371SKashyap D Desai break; 611*8e727371SKashyap D Desai if (row > span_set->data_row_end) 612*8e727371SKashyap D Desai continue; 613665484d8SDoug Ambrisko 614665484d8SDoug Ambrisko for (span = 0; span < raid->spanDepth; span++) 615665484d8SDoug Ambrisko if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 616665484d8SDoug Ambrisko block_span_info.noElements >= info + 1) { 617665484d8SDoug Ambrisko quad = &map->raidMap.ldSpanMap[ld]. 618665484d8SDoug Ambrisko spanBlock[span].block_span_info.quad[info]; 619665484d8SDoug Ambrisko if (quad->logStart <= row && 620665484d8SDoug Ambrisko row <= quad->logEnd && 621665484d8SDoug Ambrisko mega_mod64((row - quad->logStart), 622665484d8SDoug Ambrisko quad->diff) == 0) { 623665484d8SDoug Ambrisko strip = mega_div64_32 624665484d8SDoug Ambrisko (((row - span_set->data_row_start) 625665484d8SDoug Ambrisko - quad->logStart), 626665484d8SDoug Ambrisko quad->diff); 627665484d8SDoug Ambrisko strip *= span_set->span_row_data_width; 628665484d8SDoug Ambrisko strip += span_set->data_strip_start; 629665484d8SDoug Ambrisko strip += span_set->strip_offset[span]; 630665484d8SDoug Ambrisko return strip; 631665484d8SDoug Ambrisko } 632665484d8SDoug Ambrisko } 633665484d8SDoug Ambrisko } 634665484d8SDoug Ambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug - get_strip_from_row: returns invalid " 635665484d8SDoug Ambrisko "strip for ld=%x, row=%lx\n", ld, (long unsigned int)row); 636665484d8SDoug Ambrisko return -1; 637665484d8SDoug Ambrisko } 638665484d8SDoug Ambrisko 639665484d8SDoug Ambrisko /* 640665484d8SDoug Ambrisko * ***************************************************************************** 641665484d8SDoug Ambrisko * 642*8e727371SKashyap D Desai * 643665484d8SDoug Ambrisko * This routine calculates the Physical Arm for given strip using spanset. 644665484d8SDoug Ambrisko * 645*8e727371SKashyap D Desai * Inputs : HBA instance 646*8e727371SKashyap D Desai * Logical drive number 647*8e727371SKashyap D Desai * Strip 648*8e727371SKashyap D Desai * LD map 649665484d8SDoug Ambrisko * 650*8e727371SKashyap D Desai * Outputs : Phys Arm - Phys Arm associated with strip 651665484d8SDoug Ambrisko */ 652665484d8SDoug Ambrisko 653*8e727371SKashyap D Desai static u_int32_t 654*8e727371SKashyap D Desai get_arm_from_strip(struct mrsas_softc *sc, 6554799d485SKashyap D Desai u_int32_t ld, u_int64_t strip, MR_DRV_RAID_MAP_ALL * map) 656665484d8SDoug Ambrisko { 657665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 658665484d8SDoug Ambrisko LD_SPAN_SET *span_set; 659665484d8SDoug Ambrisko PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 660665484d8SDoug Ambrisko u_int32_t info, strip_offset, span, span_offset; 661665484d8SDoug Ambrisko 662665484d8SDoug Ambrisko for (info = 0; info < MAX_QUAD_DEPTH; info++) { 663665484d8SDoug Ambrisko span_set = &(ldSpanInfo[ld].span_set[info]); 664665484d8SDoug Ambrisko 665*8e727371SKashyap D Desai if (span_set->span_row_data_width == 0) 666*8e727371SKashyap D Desai break; 667*8e727371SKashyap D Desai if (strip > span_set->data_strip_end) 668*8e727371SKashyap D Desai continue; 669665484d8SDoug Ambrisko 670665484d8SDoug Ambrisko strip_offset = (u_int32_t)mega_mod64 671665484d8SDoug Ambrisko ((strip - span_set->data_strip_start), 672665484d8SDoug Ambrisko span_set->span_row_data_width); 673665484d8SDoug Ambrisko 674665484d8SDoug Ambrisko for (span = 0, span_offset = 0; span < raid->spanDepth; span++) 675665484d8SDoug Ambrisko if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 676665484d8SDoug Ambrisko block_span_info.noElements >= info + 1) { 677*8e727371SKashyap D Desai if (strip_offset >= span_set->strip_offset[span]) 678*8e727371SKashyap D Desai span_offset = span_set->strip_offset[span]; 679665484d8SDoug Ambrisko else 680665484d8SDoug Ambrisko break; 681665484d8SDoug Ambrisko } 682665484d8SDoug Ambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI PRL11: get_arm_from_strip: " 683665484d8SDoug Ambrisko "for ld=0x%x strip=0x%lx arm is 0x%x\n", ld, 684665484d8SDoug Ambrisko (long unsigned int)strip, (strip_offset - span_offset)); 685665484d8SDoug Ambrisko return (strip_offset - span_offset); 686665484d8SDoug Ambrisko } 687665484d8SDoug Ambrisko 688665484d8SDoug Ambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: - get_arm_from_strip: returns invalid arm" 689665484d8SDoug Ambrisko " for ld=%x strip=%lx\n", ld, (long unsigned int)strip); 690665484d8SDoug Ambrisko 691665484d8SDoug Ambrisko return -1; 692665484d8SDoug Ambrisko } 693665484d8SDoug Ambrisko 694665484d8SDoug Ambrisko 695665484d8SDoug Ambrisko /* This Function will return Phys arm */ 696*8e727371SKashyap D Desai u_int8_t 697*8e727371SKashyap D Desai get_arm(struct mrsas_softc *sc, u_int32_t ld, u_int8_t span, u_int64_t stripe, 6984799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * map) 699665484d8SDoug Ambrisko { 700665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 701*8e727371SKashyap D Desai 702665484d8SDoug Ambrisko /* Need to check correct default value */ 703665484d8SDoug Ambrisko u_int32_t arm = 0; 704665484d8SDoug Ambrisko 705665484d8SDoug Ambrisko switch (raid->level) { 706665484d8SDoug Ambrisko case 0: 707665484d8SDoug Ambrisko case 5: 708665484d8SDoug Ambrisko case 6: 709665484d8SDoug Ambrisko arm = mega_mod64(stripe, SPAN_ROW_SIZE(map, ld, span)); 710665484d8SDoug Ambrisko break; 711665484d8SDoug Ambrisko case 1: 712*8e727371SKashyap D Desai /* start with logical arm */ 713665484d8SDoug Ambrisko arm = get_arm_from_strip(sc, ld, stripe, map); 714665484d8SDoug Ambrisko arm *= 2; 715665484d8SDoug Ambrisko break; 716665484d8SDoug Ambrisko } 717665484d8SDoug Ambrisko 718665484d8SDoug Ambrisko return arm; 719665484d8SDoug Ambrisko } 720665484d8SDoug Ambrisko 721665484d8SDoug Ambrisko /* 722665484d8SDoug Ambrisko * 723665484d8SDoug Ambrisko * This routine calculates the arm, span and block for the specified stripe and 724665484d8SDoug Ambrisko * reference in stripe using spanset 725665484d8SDoug Ambrisko * 726*8e727371SKashyap D Desai * Inputs : Logical drive number 727*8e727371SKashyap D Desai * stripRow: Stripe number 728*8e727371SKashyap D Desai * stripRef: Reference in stripe 729665484d8SDoug Ambrisko * 730*8e727371SKashyap D Desai * Outputs : span - Span number block - Absolute Block 731*8e727371SKashyap D Desai * number in the physical disk 732665484d8SDoug Ambrisko */ 733*8e727371SKashyap D Desai static u_int8_t 734*8e727371SKashyap D Desai mr_spanset_get_phy_params(struct mrsas_softc *sc, u_int32_t ld, u_int64_t stripRow, 735665484d8SDoug Ambrisko u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 7364799d485SKashyap D Desai RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map) 737665484d8SDoug Ambrisko { 738665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 739665484d8SDoug Ambrisko u_int32_t pd, arRef; 740665484d8SDoug Ambrisko u_int8_t physArm, span; 741665484d8SDoug Ambrisko u_int64_t row; 742665484d8SDoug Ambrisko u_int8_t retval = TRUE; 743665484d8SDoug Ambrisko u_int64_t *pdBlock = &io_info->pdBlock; 744665484d8SDoug Ambrisko u_int16_t *pDevHandle = &io_info->devHandle; 745665484d8SDoug Ambrisko u_int32_t logArm, rowMod, armQ, arm; 746665484d8SDoug Ambrisko u_int8_t do_invader = 0; 747665484d8SDoug Ambrisko 748665484d8SDoug Ambrisko if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) 749665484d8SDoug Ambrisko do_invader = 1; 750665484d8SDoug Ambrisko 751*8e727371SKashyap D Desai /* Get row and span from io_info for Uneven Span IO. */ 752665484d8SDoug Ambrisko row = io_info->start_row; 753665484d8SDoug Ambrisko span = io_info->start_span; 754665484d8SDoug Ambrisko 755665484d8SDoug Ambrisko 756665484d8SDoug Ambrisko if (raid->level == 6) { 757665484d8SDoug Ambrisko logArm = get_arm_from_strip(sc, ld, stripRow, map); 758665484d8SDoug Ambrisko rowMod = mega_mod64(row, SPAN_ROW_SIZE(map, ld, span)); 759665484d8SDoug Ambrisko armQ = SPAN_ROW_SIZE(map, ld, span) - 1 - rowMod; 760665484d8SDoug Ambrisko arm = armQ + 1 + logArm; 761665484d8SDoug Ambrisko if (arm >= SPAN_ROW_SIZE(map, ld, span)) 762665484d8SDoug Ambrisko arm -= SPAN_ROW_SIZE(map, ld, span); 763665484d8SDoug Ambrisko physArm = (u_int8_t)arm; 764665484d8SDoug Ambrisko } else 765*8e727371SKashyap D Desai /* Calculate the arm */ 766665484d8SDoug Ambrisko physArm = get_arm(sc, ld, span, stripRow, map); 767665484d8SDoug Ambrisko 768665484d8SDoug Ambrisko 769665484d8SDoug Ambrisko arRef = MR_LdSpanArrayGet(ld, span, map); 770665484d8SDoug Ambrisko pd = MR_ArPdGet(arRef, physArm, map); 771665484d8SDoug Ambrisko 772665484d8SDoug Ambrisko if (pd != MR_PD_INVALID) 773665484d8SDoug Ambrisko *pDevHandle = MR_PdDevHandleGet(pd, map); 774665484d8SDoug Ambrisko else { 775665484d8SDoug Ambrisko *pDevHandle = MR_PD_INVALID; 776665484d8SDoug Ambrisko if ((raid->level >= 5) && ((!do_invader) || (do_invader && 777665484d8SDoug Ambrisko raid->regTypeReqOnRead != REGION_TYPE_UNUSED))) 778665484d8SDoug Ambrisko pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; 779665484d8SDoug Ambrisko else if (raid->level == 1) { 780665484d8SDoug Ambrisko pd = MR_ArPdGet(arRef, physArm + 1, map); 781665484d8SDoug Ambrisko if (pd != MR_PD_INVALID) 782665484d8SDoug Ambrisko *pDevHandle = MR_PdDevHandleGet(pd, map); 783665484d8SDoug Ambrisko } 784665484d8SDoug Ambrisko } 785665484d8SDoug Ambrisko 786665484d8SDoug Ambrisko *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk; 787665484d8SDoug Ambrisko pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; 788665484d8SDoug Ambrisko return retval; 789665484d8SDoug Ambrisko } 790665484d8SDoug Ambrisko 791*8e727371SKashyap D Desai /* 792665484d8SDoug Ambrisko * MR_BuildRaidContext: Set up Fast path RAID context 793665484d8SDoug Ambrisko * 794*8e727371SKashyap D Desai * This function will initiate command processing. The start/end row and strip 795*8e727371SKashyap D Desai * information is calculated then the lock is acquired. This function will 796*8e727371SKashyap D Desai * return 0 if region lock was acquired OR return num strips. 797665484d8SDoug Ambrisko */ 798665484d8SDoug Ambrisko u_int8_t 799665484d8SDoug Ambrisko MR_BuildRaidContext(struct mrsas_softc *sc, struct IO_REQUEST_INFO *io_info, 8004799d485SKashyap D Desai RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map) 801665484d8SDoug Ambrisko { 802665484d8SDoug Ambrisko MR_LD_RAID *raid; 803665484d8SDoug Ambrisko u_int32_t ld, stripSize, stripe_mask; 804665484d8SDoug Ambrisko u_int64_t endLba, endStrip, endRow, start_row, start_strip; 805665484d8SDoug Ambrisko REGION_KEY regStart; 806665484d8SDoug Ambrisko REGION_LEN regSize; 807665484d8SDoug Ambrisko u_int8_t num_strips, numRows; 808665484d8SDoug Ambrisko u_int16_t ref_in_start_stripe, ref_in_end_stripe; 809665484d8SDoug Ambrisko u_int64_t ldStartBlock; 810665484d8SDoug Ambrisko u_int32_t numBlocks, ldTgtId; 811665484d8SDoug Ambrisko u_int8_t isRead, stripIdx; 812665484d8SDoug Ambrisko u_int8_t retval = 0; 813665484d8SDoug Ambrisko u_int8_t startlba_span = SPAN_INVALID; 814665484d8SDoug Ambrisko u_int64_t *pdBlock = &io_info->pdBlock; 815665484d8SDoug Ambrisko int error_code = 0; 816665484d8SDoug Ambrisko 817665484d8SDoug Ambrisko ldStartBlock = io_info->ldStartBlock; 818665484d8SDoug Ambrisko numBlocks = io_info->numBlocks; 819665484d8SDoug Ambrisko ldTgtId = io_info->ldTgtId; 820665484d8SDoug Ambrisko isRead = io_info->isRead; 821665484d8SDoug Ambrisko 822665484d8SDoug Ambrisko io_info->IoforUnevenSpan = 0; 823665484d8SDoug Ambrisko io_info->start_span = SPAN_INVALID; 824665484d8SDoug Ambrisko 825665484d8SDoug Ambrisko ld = MR_TargetIdToLdGet(ldTgtId, map); 826665484d8SDoug Ambrisko raid = MR_LdRaidGet(ld, map); 827665484d8SDoug Ambrisko 828665484d8SDoug Ambrisko if (raid->rowDataSize == 0) { 829665484d8SDoug Ambrisko if (MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize == 0) 830665484d8SDoug Ambrisko return FALSE; 831665484d8SDoug Ambrisko else if (sc->UnevenSpanSupport) { 832665484d8SDoug Ambrisko io_info->IoforUnevenSpan = 1; 833*8e727371SKashyap D Desai } else { 834665484d8SDoug Ambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: raid->rowDataSize is 0, but has SPAN[0] rowDataSize = 0x%0x," 835665484d8SDoug Ambrisko " but there is _NO_ UnevenSpanSupport\n", 836665484d8SDoug Ambrisko MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize); 837665484d8SDoug Ambrisko return FALSE; 838665484d8SDoug Ambrisko } 839665484d8SDoug Ambrisko } 840665484d8SDoug Ambrisko stripSize = 1 << raid->stripeShift; 841665484d8SDoug Ambrisko stripe_mask = stripSize - 1; 842665484d8SDoug Ambrisko /* 843665484d8SDoug Ambrisko * calculate starting row and stripe, and number of strips and rows 844665484d8SDoug Ambrisko */ 845665484d8SDoug Ambrisko start_strip = ldStartBlock >> raid->stripeShift; 846665484d8SDoug Ambrisko ref_in_start_stripe = (u_int16_t)(ldStartBlock & stripe_mask); 847665484d8SDoug Ambrisko endLba = ldStartBlock + numBlocks - 1; 848665484d8SDoug Ambrisko ref_in_end_stripe = (u_int16_t)(endLba & stripe_mask); 849665484d8SDoug Ambrisko endStrip = endLba >> raid->stripeShift; 850*8e727371SKashyap D Desai num_strips = (u_int8_t)(endStrip - start_strip + 1); /* End strip */ 851665484d8SDoug Ambrisko if (io_info->IoforUnevenSpan) { 852665484d8SDoug Ambrisko start_row = get_row_from_strip(sc, ld, start_strip, map); 853665484d8SDoug Ambrisko endRow = get_row_from_strip(sc, ld, endStrip, map); 854665484d8SDoug Ambrisko if (raid->spanDepth == 1) { 855665484d8SDoug Ambrisko startlba_span = 0; 856665484d8SDoug Ambrisko *pdBlock = start_row << raid->stripeShift; 857665484d8SDoug Ambrisko } else { 858665484d8SDoug Ambrisko startlba_span = (u_int8_t)mr_spanset_get_span_block(sc, ld, start_row, 859665484d8SDoug Ambrisko pdBlock, map, &error_code); 860665484d8SDoug Ambrisko if (error_code == 1) { 861665484d8SDoug Ambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: return from %s %d. Send IO w/o region lock.\n", 862665484d8SDoug Ambrisko __func__, __LINE__); 863665484d8SDoug Ambrisko return FALSE; 864665484d8SDoug Ambrisko } 865665484d8SDoug Ambrisko } 866665484d8SDoug Ambrisko if (startlba_span == SPAN_INVALID) { 867665484d8SDoug Ambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: return from %s %d for row 0x%llx," 868665484d8SDoug Ambrisko "start strip %llx endSrip %llx\n", __func__, 869665484d8SDoug Ambrisko __LINE__, (unsigned long long)start_row, 870665484d8SDoug Ambrisko (unsigned long long)start_strip, 871665484d8SDoug Ambrisko (unsigned long long)endStrip); 872665484d8SDoug Ambrisko return FALSE; 873665484d8SDoug Ambrisko } 874665484d8SDoug Ambrisko io_info->start_span = startlba_span; 875665484d8SDoug Ambrisko io_info->start_row = start_row; 876665484d8SDoug Ambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: Check Span number from %s %d for row 0x%llx, " 877665484d8SDoug Ambrisko " start strip 0x%llx endSrip 0x%llx span 0x%x\n", 878665484d8SDoug Ambrisko __func__, __LINE__, (unsigned long long)start_row, 879665484d8SDoug Ambrisko (unsigned long long)start_strip, 880665484d8SDoug Ambrisko (unsigned long long)endStrip, startlba_span); 881665484d8SDoug Ambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : 1. start_row 0x%llx endRow 0x%llx Start span 0x%x\n", 882665484d8SDoug Ambrisko (unsigned long long)start_row, (unsigned long long)endRow, startlba_span); 883665484d8SDoug Ambrisko } else { 884*8e727371SKashyap D Desai start_row = mega_div64_32(start_strip, raid->rowDataSize); 885665484d8SDoug Ambrisko endRow = mega_div64_32(endStrip, raid->rowDataSize); 886665484d8SDoug Ambrisko } 887665484d8SDoug Ambrisko 888*8e727371SKashyap D Desai numRows = (u_int8_t)(endRow - start_row + 1); /* get the row count */ 889665484d8SDoug Ambrisko 890665484d8SDoug Ambrisko /* 891665484d8SDoug Ambrisko * Calculate region info. (Assume region at start of first row, and 892665484d8SDoug Ambrisko * assume this IO needs the full row - will adjust if not true.) 893665484d8SDoug Ambrisko */ 894665484d8SDoug Ambrisko regStart = start_row << raid->stripeShift; 895665484d8SDoug Ambrisko regSize = stripSize; 896665484d8SDoug Ambrisko 897665484d8SDoug Ambrisko /* Check if we can send this I/O via FastPath */ 898665484d8SDoug Ambrisko if (raid->capability.fpCapable) { 899665484d8SDoug Ambrisko if (isRead) 900665484d8SDoug Ambrisko io_info->fpOkForIo = (raid->capability.fpReadCapable && 901665484d8SDoug Ambrisko ((num_strips == 1) || 902*8e727371SKashyap D Desai raid->capability.fpReadAcrossStripe)); 903665484d8SDoug Ambrisko else 904665484d8SDoug Ambrisko io_info->fpOkForIo = (raid->capability.fpWriteCapable && 905665484d8SDoug Ambrisko ((num_strips == 1) || 906*8e727371SKashyap D Desai raid->capability.fpWriteAcrossStripe)); 907*8e727371SKashyap D Desai } else 908665484d8SDoug Ambrisko io_info->fpOkForIo = FALSE; 909665484d8SDoug Ambrisko 910665484d8SDoug Ambrisko if (numRows == 1) { 911665484d8SDoug Ambrisko if (num_strips == 1) { 912665484d8SDoug Ambrisko regStart += ref_in_start_stripe; 913665484d8SDoug Ambrisko regSize = numBlocks; 914665484d8SDoug Ambrisko } 915*8e727371SKashyap D Desai } else if (io_info->IoforUnevenSpan == 0) { 916*8e727371SKashyap D Desai /* 917*8e727371SKashyap D Desai * For Even span region lock optimization. If the start strip 918*8e727371SKashyap D Desai * is the last in the start row 919*8e727371SKashyap D Desai */ 920665484d8SDoug Ambrisko if (start_strip == (start_row + 1) * raid->rowDataSize - 1) { 921665484d8SDoug Ambrisko regStart += ref_in_start_stripe; 922*8e727371SKashyap D Desai /* 923*8e727371SKashyap D Desai * initialize count to sectors from startRef to end 924*8e727371SKashyap D Desai * of strip 925*8e727371SKashyap D Desai */ 926665484d8SDoug Ambrisko regSize = stripSize - ref_in_start_stripe; 927665484d8SDoug Ambrisko } 928*8e727371SKashyap D Desai /* add complete rows in the middle of the transfer */ 929665484d8SDoug Ambrisko if (numRows > 2) 930665484d8SDoug Ambrisko regSize += (numRows - 2) << raid->stripeShift; 931665484d8SDoug Ambrisko 932*8e727371SKashyap D Desai /* if IO ends within first strip of last row */ 933665484d8SDoug Ambrisko if (endStrip == endRow * raid->rowDataSize) 934665484d8SDoug Ambrisko regSize += ref_in_end_stripe + 1; 935665484d8SDoug Ambrisko else 936665484d8SDoug Ambrisko regSize += stripSize; 937665484d8SDoug Ambrisko } else { 938665484d8SDoug Ambrisko if (start_strip == (get_strip_from_row(sc, ld, start_row, map) + 939665484d8SDoug Ambrisko SPAN_ROW_DATA_SIZE(map, ld, startlba_span) - 1)) { 940665484d8SDoug Ambrisko regStart += ref_in_start_stripe; 941*8e727371SKashyap D Desai /* 942*8e727371SKashyap D Desai * initialize count to sectors from startRef to end 943*8e727371SKashyap D Desai * of strip 944*8e727371SKashyap D Desai */ 945665484d8SDoug Ambrisko regSize = stripSize - ref_in_start_stripe; 946665484d8SDoug Ambrisko } 947*8e727371SKashyap D Desai /* add complete rows in the middle of the transfer */ 948665484d8SDoug Ambrisko if (numRows > 2) 949665484d8SDoug Ambrisko regSize += (numRows - 2) << raid->stripeShift; 950665484d8SDoug Ambrisko 951*8e727371SKashyap D Desai /* if IO ends within first strip of last row */ 952665484d8SDoug Ambrisko if (endStrip == get_strip_from_row(sc, ld, endRow, map)) 953665484d8SDoug Ambrisko regSize += ref_in_end_stripe + 1; 954665484d8SDoug Ambrisko else 955665484d8SDoug Ambrisko regSize += stripSize; 956665484d8SDoug Ambrisko } 957665484d8SDoug Ambrisko pRAID_Context->timeoutValue = map->raidMap.fpPdIoTimeoutSec; 958665484d8SDoug Ambrisko if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) 959665484d8SDoug Ambrisko pRAID_Context->regLockFlags = (isRead) ? raid->regTypeReqOnRead : raid->regTypeReqOnWrite; 960665484d8SDoug Ambrisko else 961665484d8SDoug Ambrisko pRAID_Context->regLockFlags = (isRead) ? REGION_TYPE_SHARED_READ : raid->regTypeReqOnWrite; 962665484d8SDoug Ambrisko pRAID_Context->VirtualDiskTgtId = raid->targetId; 963665484d8SDoug Ambrisko pRAID_Context->regLockRowLBA = regStart; 964665484d8SDoug Ambrisko pRAID_Context->regLockLength = regSize; 965665484d8SDoug Ambrisko pRAID_Context->configSeqNum = raid->seqNum; 966665484d8SDoug Ambrisko 967665484d8SDoug Ambrisko /* 968665484d8SDoug Ambrisko * Get Phy Params only if FP capable, or else leave it to MR firmware 969665484d8SDoug Ambrisko * to do the calculation. 970665484d8SDoug Ambrisko */ 971665484d8SDoug Ambrisko if (io_info->fpOkForIo) { 972665484d8SDoug Ambrisko retval = io_info->IoforUnevenSpan ? 973*8e727371SKashyap D Desai mr_spanset_get_phy_params(sc, ld, start_strip, 974*8e727371SKashyap D Desai ref_in_start_stripe, io_info, pRAID_Context, map) : 975665484d8SDoug Ambrisko MR_GetPhyParams(sc, ld, start_strip, 976665484d8SDoug Ambrisko ref_in_start_stripe, io_info, pRAID_Context, map); 977665484d8SDoug Ambrisko /* If IO on an invalid Pd, then FP is not possible */ 978665484d8SDoug Ambrisko if (io_info->devHandle == MR_PD_INVALID) 979665484d8SDoug Ambrisko io_info->fpOkForIo = FALSE; 980665484d8SDoug Ambrisko return retval; 981*8e727371SKashyap D Desai } else if (isRead) { 982665484d8SDoug Ambrisko for (stripIdx = 0; stripIdx < num_strips; stripIdx++) { 983665484d8SDoug Ambrisko retval = io_info->IoforUnevenSpan ? 984*8e727371SKashyap D Desai mr_spanset_get_phy_params(sc, ld, start_strip + stripIdx, 985*8e727371SKashyap D Desai ref_in_start_stripe, io_info, pRAID_Context, map) : 986*8e727371SKashyap D Desai MR_GetPhyParams(sc, ld, start_strip + stripIdx, 987*8e727371SKashyap D Desai ref_in_start_stripe, io_info, pRAID_Context, map); 988665484d8SDoug Ambrisko if (!retval) 989665484d8SDoug Ambrisko return TRUE; 990665484d8SDoug Ambrisko } 991665484d8SDoug Ambrisko } 992665484d8SDoug Ambrisko #if SPAN_DEBUG 993*8e727371SKashyap D Desai /* Just for testing what arm we get for strip. */ 994665484d8SDoug Ambrisko get_arm_from_strip(sc, ld, start_strip, map); 995665484d8SDoug Ambrisko #endif 996665484d8SDoug Ambrisko return TRUE; 997665484d8SDoug Ambrisko } 998665484d8SDoug Ambrisko 999665484d8SDoug Ambrisko /* 1000665484d8SDoug Ambrisko * 1001*8e727371SKashyap D Desai * This routine pepare spanset info from Valid Raid map and store it into local 1002*8e727371SKashyap D Desai * copy of ldSpanInfo per instance data structure. 1003665484d8SDoug Ambrisko * 1004*8e727371SKashyap D Desai * Inputs : LD map 1005*8e727371SKashyap D Desai * ldSpanInfo per HBA instance 1006665484d8SDoug Ambrisko * 1007665484d8SDoug Ambrisko */ 1008*8e727371SKashyap D Desai void 1009*8e727371SKashyap D Desai mr_update_span_set(MR_DRV_RAID_MAP_ALL * map, PLD_SPAN_INFO ldSpanInfo) 1010665484d8SDoug Ambrisko { 1011665484d8SDoug Ambrisko u_int8_t span, count; 1012665484d8SDoug Ambrisko u_int32_t element, span_row_width; 1013665484d8SDoug Ambrisko u_int64_t span_row; 1014665484d8SDoug Ambrisko MR_LD_RAID *raid; 1015665484d8SDoug Ambrisko LD_SPAN_SET *span_set, *span_set_prev; 1016665484d8SDoug Ambrisko MR_QUAD_ELEMENT *quad; 1017665484d8SDoug Ambrisko int ldCount; 1018665484d8SDoug Ambrisko u_int16_t ld; 1019665484d8SDoug Ambrisko 1020*8e727371SKashyap D Desai for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) { 1021665484d8SDoug Ambrisko ld = MR_TargetIdToLdGet(ldCount, map); 1022665484d8SDoug Ambrisko if (ld >= MAX_LOGICAL_DRIVES) 1023665484d8SDoug Ambrisko continue; 1024665484d8SDoug Ambrisko raid = MR_LdRaidGet(ld, map); 1025665484d8SDoug Ambrisko for (element = 0; element < MAX_QUAD_DEPTH; element++) { 1026665484d8SDoug Ambrisko for (span = 0; span < raid->spanDepth; span++) { 1027665484d8SDoug Ambrisko if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 1028665484d8SDoug Ambrisko block_span_info.noElements < element + 1) 1029665484d8SDoug Ambrisko continue; 1030*8e727371SKashyap D Desai /* TO-DO */ 1031665484d8SDoug Ambrisko span_set = &(ldSpanInfo[ld].span_set[element]); 1032665484d8SDoug Ambrisko quad = &map->raidMap.ldSpanMap[ld]. 1033*8e727371SKashyap D Desai spanBlock[span].block_span_info.quad[element]; 1034665484d8SDoug Ambrisko 1035665484d8SDoug Ambrisko span_set->diff = quad->diff; 1036665484d8SDoug Ambrisko 1037665484d8SDoug Ambrisko for (count = 0, span_row_width = 0; 1038665484d8SDoug Ambrisko count < raid->spanDepth; count++) { 1039*8e727371SKashyap D Desai if (map->raidMap.ldSpanMap[ld].spanBlock[count]. 1040*8e727371SKashyap D Desai block_span_info.noElements >= element + 1) { 1041*8e727371SKashyap D Desai span_set->strip_offset[count] = span_row_width; 1042665484d8SDoug Ambrisko span_row_width += 1043*8e727371SKashyap D Desai MR_LdSpanPtrGet(ld, count, map)->spanRowDataSize; 1044665484d8SDoug Ambrisko #if SPAN_DEBUG 1045*8e727371SKashyap D Desai printf("LSI Debug span %x rowDataSize %x\n", count, 1046*8e727371SKashyap D Desai MR_LdSpanPtrGet(ld, count, map)->spanRowDataSize); 1047665484d8SDoug Ambrisko #endif 1048665484d8SDoug Ambrisko } 1049665484d8SDoug Ambrisko } 1050665484d8SDoug Ambrisko 1051665484d8SDoug Ambrisko span_set->span_row_data_width = span_row_width; 1052665484d8SDoug Ambrisko span_row = mega_div64_32(((quad->logEnd - 1053665484d8SDoug Ambrisko quad->logStart) + quad->diff), quad->diff); 1054665484d8SDoug Ambrisko 1055665484d8SDoug Ambrisko if (element == 0) { 1056665484d8SDoug Ambrisko span_set->log_start_lba = 0; 1057665484d8SDoug Ambrisko span_set->log_end_lba = 1058665484d8SDoug Ambrisko ((span_row << raid->stripeShift) * span_row_width) - 1; 1059665484d8SDoug Ambrisko 1060665484d8SDoug Ambrisko span_set->span_row_start = 0; 1061665484d8SDoug Ambrisko span_set->span_row_end = span_row - 1; 1062665484d8SDoug Ambrisko 1063665484d8SDoug Ambrisko span_set->data_strip_start = 0; 1064*8e727371SKashyap D Desai span_set->data_strip_end = (span_row * span_row_width) - 1; 1065665484d8SDoug Ambrisko 1066665484d8SDoug Ambrisko span_set->data_row_start = 0; 1067*8e727371SKashyap D Desai span_set->data_row_end = (span_row * quad->diff) - 1; 1068665484d8SDoug Ambrisko } else { 1069*8e727371SKashyap D Desai span_set_prev = &(ldSpanInfo[ld].span_set[element - 1]); 1070*8e727371SKashyap D Desai span_set->log_start_lba = span_set_prev->log_end_lba + 1; 1071*8e727371SKashyap D Desai span_set->log_end_lba = span_set->log_start_lba + 1072665484d8SDoug Ambrisko ((span_row << raid->stripeShift) * span_row_width) - 1; 1073665484d8SDoug Ambrisko 1074*8e727371SKashyap D Desai span_set->span_row_start = span_set_prev->span_row_end + 1; 1075665484d8SDoug Ambrisko span_set->span_row_end = 1076665484d8SDoug Ambrisko span_set->span_row_start + span_row - 1; 1077665484d8SDoug Ambrisko 1078665484d8SDoug Ambrisko span_set->data_strip_start = 1079665484d8SDoug Ambrisko span_set_prev->data_strip_end + 1; 1080*8e727371SKashyap D Desai span_set->data_strip_end = span_set->data_strip_start + 1081665484d8SDoug Ambrisko (span_row * span_row_width) - 1; 1082665484d8SDoug Ambrisko 1083*8e727371SKashyap D Desai span_set->data_row_start = span_set_prev->data_row_end + 1; 1084*8e727371SKashyap D Desai span_set->data_row_end = span_set->data_row_start + 1085665484d8SDoug Ambrisko (span_row * quad->diff) - 1; 1086665484d8SDoug Ambrisko } 1087665484d8SDoug Ambrisko break; 1088665484d8SDoug Ambrisko } 1089*8e727371SKashyap D Desai if (span == raid->spanDepth) 1090*8e727371SKashyap D Desai break; /* no quads remain */ 1091665484d8SDoug Ambrisko } 1092665484d8SDoug Ambrisko } 1093665484d8SDoug Ambrisko #if SPAN_DEBUG 1094*8e727371SKashyap D Desai getSpanInfo(map, ldSpanInfo); /* to get span set info */ 1095665484d8SDoug Ambrisko #endif 1096665484d8SDoug Ambrisko } 1097665484d8SDoug Ambrisko 1098*8e727371SKashyap D Desai /* 1099665484d8SDoug Ambrisko * mrsas_update_load_balance_params: Update load balance parmas 1100665484d8SDoug Ambrisko * Inputs: map pointer 1101665484d8SDoug Ambrisko * Load balance info 1102665484d8SDoug Ambrisko * 1103*8e727371SKashyap D Desai * This function updates the load balance parameters for the LD config of a two 1104*8e727371SKashyap D Desai * drive optimal RAID-1. 1105665484d8SDoug Ambrisko */ 1106*8e727371SKashyap D Desai void 1107*8e727371SKashyap D Desai mrsas_update_load_balance_params(MR_DRV_RAID_MAP_ALL * map, 1108665484d8SDoug Ambrisko PLD_LOAD_BALANCE_INFO lbInfo) 1109665484d8SDoug Ambrisko { 1110665484d8SDoug Ambrisko int ldCount; 1111665484d8SDoug Ambrisko u_int16_t ld; 1112665484d8SDoug Ambrisko u_int32_t pd, arRef; 1113665484d8SDoug Ambrisko MR_LD_RAID *raid; 1114665484d8SDoug Ambrisko 1115*8e727371SKashyap D Desai for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) { 1116665484d8SDoug Ambrisko ld = MR_TargetIdToLdGet(ldCount, map); 1117665484d8SDoug Ambrisko if (ld >= MAX_LOGICAL_DRIVES) { 1118665484d8SDoug Ambrisko lbInfo[ldCount].loadBalanceFlag = 0; 1119665484d8SDoug Ambrisko continue; 1120665484d8SDoug Ambrisko } 1121665484d8SDoug Ambrisko raid = MR_LdRaidGet(ld, map); 1122665484d8SDoug Ambrisko 1123665484d8SDoug Ambrisko /* Two drive Optimal RAID 1 */ 1124665484d8SDoug Ambrisko if ((raid->level == 1) && (raid->rowSize == 2) && 1125665484d8SDoug Ambrisko (raid->spanDepth == 1) 1126665484d8SDoug Ambrisko && raid->ldState == MR_LD_STATE_OPTIMAL) { 1127665484d8SDoug Ambrisko lbInfo[ldCount].loadBalanceFlag = 1; 1128665484d8SDoug Ambrisko 1129665484d8SDoug Ambrisko /* Get the array on which this span is present */ 1130665484d8SDoug Ambrisko arRef = MR_LdSpanArrayGet(ld, 0, map); 1131665484d8SDoug Ambrisko 1132665484d8SDoug Ambrisko /* Get the PD */ 1133665484d8SDoug Ambrisko pd = MR_ArPdGet(arRef, 0, map); 1134665484d8SDoug Ambrisko /* Get dev handle from PD */ 1135665484d8SDoug Ambrisko lbInfo[ldCount].raid1DevHandle[0] = MR_PdDevHandleGet(pd, map); 1136665484d8SDoug Ambrisko pd = MR_ArPdGet(arRef, 1, map); 1137665484d8SDoug Ambrisko lbInfo[ldCount].raid1DevHandle[1] = MR_PdDevHandleGet(pd, map); 1138*8e727371SKashyap D Desai } else 1139665484d8SDoug Ambrisko lbInfo[ldCount].loadBalanceFlag = 0; 1140665484d8SDoug Ambrisko } 1141665484d8SDoug Ambrisko } 1142665484d8SDoug Ambrisko 1143665484d8SDoug Ambrisko 1144*8e727371SKashyap D Desai /* 1145665484d8SDoug Ambrisko * mrsas_set_pd_lba: Sets PD LBA 1146665484d8SDoug Ambrisko * input: io_request pointer 1147665484d8SDoug Ambrisko * CDB length 1148665484d8SDoug Ambrisko * io_info pointer 1149665484d8SDoug Ambrisko * Pointer to CCB 1150665484d8SDoug Ambrisko * Local RAID map pointer 1151*8e727371SKashyap D Desai * Start block of IO Block Size 1152665484d8SDoug Ambrisko * 1153665484d8SDoug Ambrisko * Used to set the PD logical block address in CDB for FP IOs. 1154665484d8SDoug Ambrisko */ 1155*8e727371SKashyap D Desai void 1156*8e727371SKashyap D Desai mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request, u_int8_t cdb_len, 1157665484d8SDoug Ambrisko struct IO_REQUEST_INFO *io_info, union ccb *ccb, 11584799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * local_map_ptr, u_int32_t ref_tag, 1159665484d8SDoug Ambrisko u_int32_t ld_block_size) 1160665484d8SDoug Ambrisko { 1161665484d8SDoug Ambrisko MR_LD_RAID *raid; 1162665484d8SDoug Ambrisko u_int32_t ld; 1163665484d8SDoug Ambrisko u_int64_t start_blk = io_info->pdBlock; 1164665484d8SDoug Ambrisko u_int8_t *cdb = io_request->CDB.CDB32; 1165665484d8SDoug Ambrisko u_int32_t num_blocks = io_info->numBlocks; 1166665484d8SDoug Ambrisko u_int8_t opcode = 0, flagvals = 0, groupnum = 0, control = 0; 1167665484d8SDoug Ambrisko struct ccb_hdr *ccb_h = &(ccb->ccb_h); 1168665484d8SDoug Ambrisko 1169665484d8SDoug Ambrisko /* Check if T10 PI (DIF) is enabled for this LD */ 1170665484d8SDoug Ambrisko ld = MR_TargetIdToLdGet(io_info->ldTgtId, local_map_ptr); 1171665484d8SDoug Ambrisko raid = MR_LdRaidGet(ld, local_map_ptr); 1172665484d8SDoug Ambrisko if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER) { 1173665484d8SDoug Ambrisko memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1174665484d8SDoug Ambrisko cdb[0] = MRSAS_SCSI_VARIABLE_LENGTH_CMD; 1175665484d8SDoug Ambrisko cdb[7] = MRSAS_SCSI_ADDL_CDB_LEN; 1176665484d8SDoug Ambrisko 1177665484d8SDoug Ambrisko if (ccb_h->flags == CAM_DIR_OUT) 1178665484d8SDoug Ambrisko cdb[9] = MRSAS_SCSI_SERVICE_ACTION_READ32; 1179665484d8SDoug Ambrisko else 1180665484d8SDoug Ambrisko cdb[9] = MRSAS_SCSI_SERVICE_ACTION_WRITE32; 1181665484d8SDoug Ambrisko cdb[10] = MRSAS_RD_WR_PROTECT_CHECK_ALL; 1182665484d8SDoug Ambrisko 1183665484d8SDoug Ambrisko /* LBA */ 1184665484d8SDoug Ambrisko cdb[12] = (u_int8_t)((start_blk >> 56) & 0xff); 1185665484d8SDoug Ambrisko cdb[13] = (u_int8_t)((start_blk >> 48) & 0xff); 1186665484d8SDoug Ambrisko cdb[14] = (u_int8_t)((start_blk >> 40) & 0xff); 1187665484d8SDoug Ambrisko cdb[15] = (u_int8_t)((start_blk >> 32) & 0xff); 1188665484d8SDoug Ambrisko cdb[16] = (u_int8_t)((start_blk >> 24) & 0xff); 1189665484d8SDoug Ambrisko cdb[17] = (u_int8_t)((start_blk >> 16) & 0xff); 1190665484d8SDoug Ambrisko cdb[18] = (u_int8_t)((start_blk >> 8) & 0xff); 1191665484d8SDoug Ambrisko cdb[19] = (u_int8_t)(start_blk & 0xff); 1192665484d8SDoug Ambrisko 1193665484d8SDoug Ambrisko /* Logical block reference tag */ 1194665484d8SDoug Ambrisko io_request->CDB.EEDP32.PrimaryReferenceTag = swap32(ref_tag); 1195665484d8SDoug Ambrisko io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0xffff; 1196665484d8SDoug Ambrisko io_request->IoFlags = 32; /* Specify 32-byte cdb */ 1197665484d8SDoug Ambrisko 1198665484d8SDoug Ambrisko /* Transfer length */ 1199665484d8SDoug Ambrisko cdb[28] = (u_int8_t)((num_blocks >> 24) & 0xff); 1200665484d8SDoug Ambrisko cdb[29] = (u_int8_t)((num_blocks >> 16) & 0xff); 1201665484d8SDoug Ambrisko cdb[30] = (u_int8_t)((num_blocks >> 8) & 0xff); 1202665484d8SDoug Ambrisko cdb[31] = (u_int8_t)(num_blocks & 0xff); 1203665484d8SDoug Ambrisko 1204665484d8SDoug Ambrisko /* set SCSI IO EEDP Flags */ 1205665484d8SDoug Ambrisko if (ccb_h->flags == CAM_DIR_OUT) { 1206665484d8SDoug Ambrisko io_request->EEDPFlags = 1207665484d8SDoug Ambrisko MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | 1208665484d8SDoug Ambrisko MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | 1209665484d8SDoug Ambrisko MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP | 1210665484d8SDoug Ambrisko MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG | 1211665484d8SDoug Ambrisko MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; 1212*8e727371SKashyap D Desai } else { 1213665484d8SDoug Ambrisko io_request->EEDPFlags = 1214665484d8SDoug Ambrisko MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | 1215665484d8SDoug Ambrisko MPI2_SCSIIO_EEDPFLAGS_INSERT_OP; 1216665484d8SDoug Ambrisko } 1217665484d8SDoug Ambrisko io_request->Control |= (0x4 << 26); 1218665484d8SDoug Ambrisko io_request->EEDPBlockSize = ld_block_size; 1219*8e727371SKashyap D Desai } else { 1220665484d8SDoug Ambrisko /* Some drives don't support 16/12 byte CDB's, convert to 10 */ 1221665484d8SDoug Ambrisko if (((cdb_len == 12) || (cdb_len == 16)) && 1222665484d8SDoug Ambrisko (start_blk <= 0xffffffff)) { 1223665484d8SDoug Ambrisko if (cdb_len == 16) { 1224665484d8SDoug Ambrisko opcode = cdb[0] == READ_16 ? READ_10 : WRITE_10; 1225665484d8SDoug Ambrisko flagvals = cdb[1]; 1226665484d8SDoug Ambrisko groupnum = cdb[14]; 1227665484d8SDoug Ambrisko control = cdb[15]; 1228*8e727371SKashyap D Desai } else { 1229665484d8SDoug Ambrisko opcode = cdb[0] == READ_12 ? READ_10 : WRITE_10; 1230665484d8SDoug Ambrisko flagvals = cdb[1]; 1231665484d8SDoug Ambrisko groupnum = cdb[10]; 1232665484d8SDoug Ambrisko control = cdb[11]; 1233665484d8SDoug Ambrisko } 1234665484d8SDoug Ambrisko 1235665484d8SDoug Ambrisko memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1236665484d8SDoug Ambrisko 1237665484d8SDoug Ambrisko cdb[0] = opcode; 1238665484d8SDoug Ambrisko cdb[1] = flagvals; 1239665484d8SDoug Ambrisko cdb[6] = groupnum; 1240665484d8SDoug Ambrisko cdb[9] = control; 1241665484d8SDoug Ambrisko 1242665484d8SDoug Ambrisko /* Transfer length */ 1243665484d8SDoug Ambrisko cdb[8] = (u_int8_t)(num_blocks & 0xff); 1244665484d8SDoug Ambrisko cdb[7] = (u_int8_t)((num_blocks >> 8) & 0xff); 1245665484d8SDoug Ambrisko 1246665484d8SDoug Ambrisko io_request->IoFlags = 10; /* Specify 10-byte cdb */ 1247665484d8SDoug Ambrisko cdb_len = 10; 1248665484d8SDoug Ambrisko } else if ((cdb_len < 16) && (start_blk > 0xffffffff)) { 1249665484d8SDoug Ambrisko /* Convert to 16 byte CDB for large LBA's */ 1250665484d8SDoug Ambrisko switch (cdb_len) { 1251665484d8SDoug Ambrisko case 6: 1252665484d8SDoug Ambrisko opcode = cdb[0] == READ_6 ? READ_16 : WRITE_16; 1253665484d8SDoug Ambrisko control = cdb[5]; 1254665484d8SDoug Ambrisko break; 1255665484d8SDoug Ambrisko case 10: 1256665484d8SDoug Ambrisko opcode = cdb[0] == READ_10 ? READ_16 : WRITE_16; 1257665484d8SDoug Ambrisko flagvals = cdb[1]; 1258665484d8SDoug Ambrisko groupnum = cdb[6]; 1259665484d8SDoug Ambrisko control = cdb[9]; 1260665484d8SDoug Ambrisko break; 1261665484d8SDoug Ambrisko case 12: 1262665484d8SDoug Ambrisko opcode = cdb[0] == READ_12 ? READ_16 : WRITE_16; 1263665484d8SDoug Ambrisko flagvals = cdb[1]; 1264665484d8SDoug Ambrisko groupnum = cdb[10]; 1265665484d8SDoug Ambrisko control = cdb[11]; 1266665484d8SDoug Ambrisko break; 1267665484d8SDoug Ambrisko } 1268665484d8SDoug Ambrisko 1269665484d8SDoug Ambrisko memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1270665484d8SDoug Ambrisko 1271665484d8SDoug Ambrisko cdb[0] = opcode; 1272665484d8SDoug Ambrisko cdb[1] = flagvals; 1273665484d8SDoug Ambrisko cdb[14] = groupnum; 1274665484d8SDoug Ambrisko cdb[15] = control; 1275665484d8SDoug Ambrisko 1276665484d8SDoug Ambrisko /* Transfer length */ 1277665484d8SDoug Ambrisko cdb[13] = (u_int8_t)(num_blocks & 0xff); 1278665484d8SDoug Ambrisko cdb[12] = (u_int8_t)((num_blocks >> 8) & 0xff); 1279665484d8SDoug Ambrisko cdb[11] = (u_int8_t)((num_blocks >> 16) & 0xff); 1280665484d8SDoug Ambrisko cdb[10] = (u_int8_t)((num_blocks >> 24) & 0xff); 1281665484d8SDoug Ambrisko 1282665484d8SDoug Ambrisko io_request->IoFlags = 16; /* Specify 16-byte cdb */ 1283665484d8SDoug Ambrisko cdb_len = 16; 1284665484d8SDoug Ambrisko } else if ((cdb_len == 6) && (start_blk > 0x1fffff)) { 1285665484d8SDoug Ambrisko /* convert to 10 byte CDB */ 1286665484d8SDoug Ambrisko opcode = cdb[0] == READ_6 ? READ_10 : WRITE_10; 1287665484d8SDoug Ambrisko control = cdb[5]; 1288665484d8SDoug Ambrisko 128902190a56SXin LI memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1290665484d8SDoug Ambrisko cdb[0] = opcode; 1291665484d8SDoug Ambrisko cdb[9] = control; 1292665484d8SDoug Ambrisko 1293665484d8SDoug Ambrisko /* Set transfer length */ 1294665484d8SDoug Ambrisko cdb[8] = (u_int8_t)(num_blocks & 0xff); 1295665484d8SDoug Ambrisko cdb[7] = (u_int8_t)((num_blocks >> 8) & 0xff); 1296665484d8SDoug Ambrisko 1297665484d8SDoug Ambrisko /* Specify 10-byte cdb */ 1298665484d8SDoug Ambrisko cdb_len = 10; 1299665484d8SDoug Ambrisko } 1300665484d8SDoug Ambrisko /* Fall through normal case, just load LBA here */ 1301665484d8SDoug Ambrisko u_int8_t val = cdb[1] & 0xE0; 1302*8e727371SKashyap D Desai switch (cdb_len) { 1303*8e727371SKashyap D Desai case 6: 1304665484d8SDoug Ambrisko cdb[3] = (u_int8_t)(start_blk & 0xff); 1305665484d8SDoug Ambrisko cdb[2] = (u_int8_t)((start_blk >> 8) & 0xff); 1306665484d8SDoug Ambrisko cdb[1] = val | ((u_int8_t)(start_blk >> 16) & 0x1f); 1307665484d8SDoug Ambrisko break; 1308665484d8SDoug Ambrisko case 10: 1309665484d8SDoug Ambrisko cdb[5] = (u_int8_t)(start_blk & 0xff); 1310665484d8SDoug Ambrisko cdb[4] = (u_int8_t)((start_blk >> 8) & 0xff); 1311665484d8SDoug Ambrisko cdb[3] = (u_int8_t)((start_blk >> 16) & 0xff); 1312665484d8SDoug Ambrisko cdb[2] = (u_int8_t)((start_blk >> 24) & 0xff); 1313665484d8SDoug Ambrisko break; 1314665484d8SDoug Ambrisko case 12: 1315665484d8SDoug Ambrisko cdb[5] = (u_int8_t)(start_blk & 0xff); 1316665484d8SDoug Ambrisko cdb[4] = (u_int8_t)((start_blk >> 8) & 0xff); 1317665484d8SDoug Ambrisko cdb[3] = (u_int8_t)((start_blk >> 16) & 0xff); 1318665484d8SDoug Ambrisko cdb[2] = (u_int8_t)((start_blk >> 24) & 0xff); 1319665484d8SDoug Ambrisko break; 1320665484d8SDoug Ambrisko case 16: 1321665484d8SDoug Ambrisko cdb[9] = (u_int8_t)(start_blk & 0xff); 1322665484d8SDoug Ambrisko cdb[8] = (u_int8_t)((start_blk >> 8) & 0xff); 1323665484d8SDoug Ambrisko cdb[7] = (u_int8_t)((start_blk >> 16) & 0xff); 1324665484d8SDoug Ambrisko cdb[6] = (u_int8_t)((start_blk >> 24) & 0xff); 1325665484d8SDoug Ambrisko cdb[5] = (u_int8_t)((start_blk >> 32) & 0xff); 1326665484d8SDoug Ambrisko cdb[4] = (u_int8_t)((start_blk >> 40) & 0xff); 1327665484d8SDoug Ambrisko cdb[3] = (u_int8_t)((start_blk >> 48) & 0xff); 1328665484d8SDoug Ambrisko cdb[2] = (u_int8_t)((start_blk >> 56) & 0xff); 1329665484d8SDoug Ambrisko break; 1330665484d8SDoug Ambrisko } 1331665484d8SDoug Ambrisko } 1332665484d8SDoug Ambrisko } 1333665484d8SDoug Ambrisko 1334*8e727371SKashyap D Desai /* 1335*8e727371SKashyap D Desai * mrsas_get_best_arm: Determine the best spindle arm 1336665484d8SDoug Ambrisko * Inputs: Load balance info 1337665484d8SDoug Ambrisko * 1338665484d8SDoug Ambrisko * This function determines and returns the best arm by looking at the 1339665484d8SDoug Ambrisko * parameters of the last PD access. 1340665484d8SDoug Ambrisko */ 1341*8e727371SKashyap D Desai u_int8_t 1342*8e727371SKashyap D Desai mrsas_get_best_arm(PLD_LOAD_BALANCE_INFO lbInfo, u_int8_t arm, 1343665484d8SDoug Ambrisko u_int64_t block, u_int32_t count) 1344665484d8SDoug Ambrisko { 1345665484d8SDoug Ambrisko u_int16_t pend0, pend1; 1346665484d8SDoug Ambrisko u_int64_t diff0, diff1; 1347665484d8SDoug Ambrisko u_int8_t bestArm; 1348665484d8SDoug Ambrisko 1349665484d8SDoug Ambrisko /* get the pending cmds for the data and mirror arms */ 1350665484d8SDoug Ambrisko pend0 = atomic_read(&lbInfo->scsi_pending_cmds[0]); 1351665484d8SDoug Ambrisko pend1 = atomic_read(&lbInfo->scsi_pending_cmds[1]); 1352665484d8SDoug Ambrisko 1353665484d8SDoug Ambrisko /* Determine the disk whose head is nearer to the req. block */ 1354665484d8SDoug Ambrisko diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[0]); 1355665484d8SDoug Ambrisko diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[1]); 1356665484d8SDoug Ambrisko bestArm = (diff0 <= diff1 ? 0 : 1); 1357665484d8SDoug Ambrisko 1358665484d8SDoug Ambrisko if ((bestArm == arm && pend0 > pend1 + 16) || (bestArm != arm && pend1 > pend0 + 16)) 1359665484d8SDoug Ambrisko bestArm ^= 1; 1360665484d8SDoug Ambrisko 1361665484d8SDoug Ambrisko /* Update the last accessed block on the correct pd */ 1362665484d8SDoug Ambrisko lbInfo->last_accessed_block[bestArm] = block + count - 1; 1363665484d8SDoug Ambrisko 1364665484d8SDoug Ambrisko return bestArm; 1365665484d8SDoug Ambrisko } 1366665484d8SDoug Ambrisko 1367*8e727371SKashyap D Desai /* 1368*8e727371SKashyap D Desai * mrsas_get_updated_dev_handle: Get the update dev handle 1369*8e727371SKashyap D Desai * Inputs: Load balance info io_info pointer 1370665484d8SDoug Ambrisko * 1371665484d8SDoug Ambrisko * This function determines and returns the updated dev handle. 1372665484d8SDoug Ambrisko */ 1373*8e727371SKashyap D Desai u_int16_t 1374*8e727371SKashyap D Desai mrsas_get_updated_dev_handle(PLD_LOAD_BALANCE_INFO lbInfo, 1375665484d8SDoug Ambrisko struct IO_REQUEST_INFO *io_info) 1376665484d8SDoug Ambrisko { 1377665484d8SDoug Ambrisko u_int8_t arm, old_arm; 1378665484d8SDoug Ambrisko u_int16_t devHandle; 1379665484d8SDoug Ambrisko 1380665484d8SDoug Ambrisko old_arm = lbInfo->raid1DevHandle[0] == io_info->devHandle ? 0 : 1; 1381665484d8SDoug Ambrisko 1382665484d8SDoug Ambrisko /* get best new arm */ 1383665484d8SDoug Ambrisko arm = mrsas_get_best_arm(lbInfo, old_arm, io_info->ldStartBlock, io_info->numBlocks); 1384665484d8SDoug Ambrisko devHandle = lbInfo->raid1DevHandle[arm]; 1385665484d8SDoug Ambrisko atomic_inc(&lbInfo->scsi_pending_cmds[arm]); 1386665484d8SDoug Ambrisko 1387665484d8SDoug Ambrisko return devHandle; 1388665484d8SDoug Ambrisko } 1389665484d8SDoug Ambrisko 1390*8e727371SKashyap D Desai /* 1391*8e727371SKashyap D Desai * MR_GetPhyParams: Calculates arm, span, and block 1392*8e727371SKashyap D Desai * Inputs: Adapter soft state 1393665484d8SDoug Ambrisko * Logical drive number (LD) 1394665484d8SDoug Ambrisko * Stripe number(stripRow) 1395665484d8SDoug Ambrisko * Reference in stripe (stripRef) 1396665484d8SDoug Ambrisko * 1397*8e727371SKashyap D Desai * Outputs: Absolute Block number in the physical disk 1398*8e727371SKashyap D Desai * 1399*8e727371SKashyap D Desai * This routine calculates the arm, span and block for the specified stripe and 1400*8e727371SKashyap D Desai * reference in stripe. 1401665484d8SDoug Ambrisko */ 1402*8e727371SKashyap D Desai u_int8_t 1403*8e727371SKashyap D Desai MR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld, 1404665484d8SDoug Ambrisko u_int64_t stripRow, 1405665484d8SDoug Ambrisko u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 14064799d485SKashyap D Desai RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map) 1407665484d8SDoug Ambrisko { 1408665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 1409665484d8SDoug Ambrisko u_int32_t pd, arRef; 1410665484d8SDoug Ambrisko u_int8_t physArm, span; 1411665484d8SDoug Ambrisko u_int64_t row; 1412665484d8SDoug Ambrisko u_int8_t retval = TRUE; 1413665484d8SDoug Ambrisko int error_code = 0; 1414665484d8SDoug Ambrisko u_int64_t *pdBlock = &io_info->pdBlock; 1415665484d8SDoug Ambrisko u_int16_t *pDevHandle = &io_info->devHandle; 1416665484d8SDoug Ambrisko u_int32_t rowMod, armQ, arm, logArm; 1417665484d8SDoug Ambrisko u_int8_t do_invader = 0; 1418665484d8SDoug Ambrisko 1419665484d8SDoug Ambrisko if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) 1420665484d8SDoug Ambrisko do_invader = 1; 1421665484d8SDoug Ambrisko 1422665484d8SDoug Ambrisko row = mega_div64_32(stripRow, raid->rowDataSize); 1423665484d8SDoug Ambrisko 1424665484d8SDoug Ambrisko if (raid->level == 6) { 1425*8e727371SKashyap D Desai /* logical arm within row */ 1426*8e727371SKashyap D Desai logArm = mega_mod64(stripRow, raid->rowDataSize); 1427665484d8SDoug Ambrisko if (raid->rowSize == 0) 1428665484d8SDoug Ambrisko return FALSE; 1429*8e727371SKashyap D Desai rowMod = mega_mod64(row, raid->rowSize); /* get logical row mod */ 1430*8e727371SKashyap D Desai armQ = raid->rowSize - 1 - rowMod; /* index of Q drive */ 1431*8e727371SKashyap D Desai arm = armQ + 1 + logArm;/* data always logically follows Q */ 1432*8e727371SKashyap D Desai if (arm >= raid->rowSize) /* handle wrap condition */ 1433665484d8SDoug Ambrisko arm -= raid->rowSize; 1434665484d8SDoug Ambrisko physArm = (u_int8_t)arm; 1435*8e727371SKashyap D Desai } else { 1436665484d8SDoug Ambrisko if (raid->modFactor == 0) 1437665484d8SDoug Ambrisko return FALSE; 1438665484d8SDoug Ambrisko physArm = MR_LdDataArmGet(ld, mega_mod64(stripRow, raid->modFactor), map); 1439665484d8SDoug Ambrisko } 1440665484d8SDoug Ambrisko 1441665484d8SDoug Ambrisko if (raid->spanDepth == 1) { 1442665484d8SDoug Ambrisko span = 0; 1443665484d8SDoug Ambrisko *pdBlock = row << raid->stripeShift; 1444*8e727371SKashyap D Desai } else { 1445665484d8SDoug Ambrisko span = (u_int8_t)MR_GetSpanBlock(ld, row, pdBlock, map, &error_code); 1446665484d8SDoug Ambrisko if (error_code == 1) 1447665484d8SDoug Ambrisko return FALSE; 1448665484d8SDoug Ambrisko } 1449665484d8SDoug Ambrisko 1450665484d8SDoug Ambrisko /* Get the array on which this span is present */ 1451665484d8SDoug Ambrisko arRef = MR_LdSpanArrayGet(ld, span, map); 1452665484d8SDoug Ambrisko 1453*8e727371SKashyap D Desai pd = MR_ArPdGet(arRef, physArm, map); /* Get the Pd. */ 1454665484d8SDoug Ambrisko 1455665484d8SDoug Ambrisko if (pd != MR_PD_INVALID) 1456*8e727371SKashyap D Desai /* Get dev handle from Pd */ 1457*8e727371SKashyap D Desai *pDevHandle = MR_PdDevHandleGet(pd, map); 1458665484d8SDoug Ambrisko else { 1459*8e727371SKashyap D Desai *pDevHandle = MR_PD_INVALID; /* set dev handle as invalid. */ 1460665484d8SDoug Ambrisko if ((raid->level >= 5) && ((!do_invader) || (do_invader && 1461665484d8SDoug Ambrisko raid->regTypeReqOnRead != REGION_TYPE_UNUSED))) 1462665484d8SDoug Ambrisko pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; 1463665484d8SDoug Ambrisko else if (raid->level == 1) { 1464*8e727371SKashyap D Desai /* Get Alternate Pd. */ 1465*8e727371SKashyap D Desai pd = MR_ArPdGet(arRef, physArm + 1, map); 1466665484d8SDoug Ambrisko if (pd != MR_PD_INVALID) 1467*8e727371SKashyap D Desai /* Get dev handle from Pd. */ 1468*8e727371SKashyap D Desai *pDevHandle = MR_PdDevHandleGet(pd, map); 1469665484d8SDoug Ambrisko } 1470665484d8SDoug Ambrisko } 1471665484d8SDoug Ambrisko 1472665484d8SDoug Ambrisko *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk; 1473665484d8SDoug Ambrisko pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; 1474665484d8SDoug Ambrisko return retval; 1475665484d8SDoug Ambrisko } 1476665484d8SDoug Ambrisko 1477*8e727371SKashyap D Desai /* 1478*8e727371SKashyap D Desai * MR_GetSpanBlock: Calculates span block 1479665484d8SDoug Ambrisko * Inputs: LD 1480*8e727371SKashyap D Desai * row PD 1481*8e727371SKashyap D Desai * span block 1482665484d8SDoug Ambrisko * RAID map pointer 1483*8e727371SKashyap D Desai * 1484*8e727371SKashyap D Desai * Outputs: Span number Error code 1485665484d8SDoug Ambrisko * 1486665484d8SDoug Ambrisko * This routine calculates the span from the span block info. 1487665484d8SDoug Ambrisko */ 1488*8e727371SKashyap D Desai u_int32_t 1489*8e727371SKashyap D Desai MR_GetSpanBlock(u_int32_t ld, u_int64_t row, u_int64_t *span_blk, 14904799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * map, int *div_error) 1491665484d8SDoug Ambrisko { 1492665484d8SDoug Ambrisko MR_SPAN_BLOCK_INFO *pSpanBlock = MR_LdSpanInfoGet(ld, map); 1493665484d8SDoug Ambrisko MR_QUAD_ELEMENT *quad; 1494665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 1495665484d8SDoug Ambrisko u_int32_t span, j; 1496665484d8SDoug Ambrisko u_int64_t blk, debugBlk; 1497665484d8SDoug Ambrisko 1498665484d8SDoug Ambrisko for (span = 0; span < raid->spanDepth; span++, pSpanBlock++) { 1499665484d8SDoug Ambrisko for (j = 0; j < pSpanBlock->block_span_info.noElements; j++) { 1500665484d8SDoug Ambrisko quad = &pSpanBlock->block_span_info.quad[j]; 1501665484d8SDoug Ambrisko if (quad->diff == 0) { 1502665484d8SDoug Ambrisko *div_error = 1; 1503665484d8SDoug Ambrisko return span; 1504665484d8SDoug Ambrisko } 1505665484d8SDoug Ambrisko if (quad->logStart <= row && row <= quad->logEnd && 1506665484d8SDoug Ambrisko (mega_mod64(row - quad->logStart, quad->diff)) == 0) { 1507665484d8SDoug Ambrisko if (span_blk != NULL) { 1508665484d8SDoug Ambrisko blk = mega_div64_32((row - quad->logStart), quad->diff); 1509665484d8SDoug Ambrisko debugBlk = blk; 1510665484d8SDoug Ambrisko blk = (blk + quad->offsetInSpan) << raid->stripeShift; 1511665484d8SDoug Ambrisko *span_blk = blk; 1512665484d8SDoug Ambrisko } 1513665484d8SDoug Ambrisko return span; 1514665484d8SDoug Ambrisko } 1515665484d8SDoug Ambrisko } 1516665484d8SDoug Ambrisko } 1517665484d8SDoug Ambrisko return span; 1518665484d8SDoug Ambrisko } 1519