mrsas_fp.c revision 272735
1265555Sambrisko/* 2265555Sambrisko * Copyright (c) 2014, LSI Corp. 3265555Sambrisko * All rights reserved. 4265555Sambrisko * Author: Marian Choy 5265555Sambrisko * Support: freebsdraid@lsi.com 6265555Sambrisko * 7265555Sambrisko * Redistribution and use in source and binary forms, with or without 8265555Sambrisko * modification, are permitted provided that the following conditions 9265555Sambrisko * are met: 10265555Sambrisko * 11265555Sambrisko * 1. Redistributions of source code must retain the above copyright 12265555Sambrisko * notice, this list of conditions and the following disclaimer. 13265555Sambrisko * 2. Redistributions in binary form must reproduce the above copyright 14265555Sambrisko * notice, this list of conditions and the following disclaimer in 15265555Sambrisko * the documentation and/or other materials provided with the 16265555Sambrisko * distribution. 17265555Sambrisko * 3. Neither the name of the <ORGANIZATION> nor the names of its 18265555Sambrisko * contributors may be used to endorse or promote products derived 19265555Sambrisko * from this software without specific prior written permission. 20265555Sambrisko * 21265555Sambrisko * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22265555Sambrisko * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23265555Sambrisko * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24265555Sambrisko * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25265555Sambrisko * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26265555Sambrisko * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27265555Sambrisko * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28265555Sambrisko * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29265555Sambrisko * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30265555Sambrisko * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31265555Sambrisko * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32265555Sambrisko * POSSIBILITY OF SUCH DAMAGE. 33265555Sambrisko * 34265555Sambrisko * The views and conclusions contained in the software and documentation 35265555Sambrisko * are those of the authors and should not be interpreted as representing 36265555Sambrisko * official policies,either expressed or implied, of the FreeBSD Project. 37265555Sambrisko * 38265555Sambrisko * Send feedback to: <megaraidfbsd@lsi.com> 39265555Sambrisko * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035 40265555Sambrisko * ATTN: MegaRaid FreeBSD 41265555Sambrisko * 42265555Sambrisko */ 43265555Sambrisko 44265555Sambrisko#include <sys/cdefs.h> 45265555Sambrisko__FBSDID("$FreeBSD: head/sys/dev/mrsas/mrsas_fp.c 272735 2014-10-08 08:48:18Z kadesai $"); 46265555Sambrisko 47265555Sambrisko#include <dev/mrsas/mrsas.h> 48265555Sambrisko 49265555Sambrisko#include <cam/cam.h> 50265555Sambrisko#include <cam/cam_ccb.h> 51265555Sambrisko#include <cam/cam_sim.h> 52265555Sambrisko#include <cam/cam_xpt_sim.h> 53265555Sambrisko#include <cam/cam_debug.h> 54265555Sambrisko#include <cam/cam_periph.h> 55265555Sambrisko#include <cam/cam_xpt_periph.h> 56265555Sambrisko 57265555Sambrisko 58265555Sambrisko/* 59265555Sambrisko * Function prototypes 60265555Sambrisko */ 61265555Sambriskou_int8_t MR_ValidateMapInfo(struct mrsas_softc *sc); 62265555Sambriskou_int8_t mrsas_get_best_arm(PLD_LOAD_BALANCE_INFO lbInfo, u_int8_t arm, 63265555Sambrisko u_int64_t block, u_int32_t count); 64265555Sambriskou_int8_t MR_BuildRaidContext(struct mrsas_softc *sc, 65265555Sambrisko struct IO_REQUEST_INFO *io_info, 66272735Skadesai RAID_CONTEXT *pRAID_Context, MR_DRV_RAID_MAP_ALL *map); 67265555Sambriskou_int8_t MR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld, 68265555Sambrisko u_int64_t stripRow, u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 69265555Sambrisko RAID_CONTEXT *pRAID_Context, 70272735Skadesai MR_DRV_RAID_MAP_ALL *map); 71272735Skadesaiu_int16_t MR_TargetIdToLdGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL *map); 72272735Skadesaiu_int32_t MR_LdBlockSizeGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL *map); 73272735Skadesaiu_int16_t MR_GetLDTgtId(u_int32_t ld, MR_DRV_RAID_MAP_ALL *map); 74265555Sambriskou_int16_t mrsas_get_updated_dev_handle(PLD_LOAD_BALANCE_INFO lbInfo, 75265555Sambrisko struct IO_REQUEST_INFO *io_info); 76265555Sambriskou_int32_t mega_mod64(u_int64_t dividend, u_int32_t divisor); 77265555Sambriskou_int32_t MR_GetSpanBlock(u_int32_t ld, u_int64_t row, u_int64_t *span_blk, 78272735Skadesai MR_DRV_RAID_MAP_ALL *map, int *div_error); 79265555Sambriskou_int64_t mega_div64_32(u_int64_t dividend, u_int32_t divisor); 80272735Skadesaivoid mrsas_update_load_balance_params(MR_DRV_RAID_MAP_ALL *map, 81265555Sambrisko PLD_LOAD_BALANCE_INFO lbInfo); 82265555Sambriskovoid mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST *io_request, 83265555Sambrisko u_int8_t cdb_len, struct IO_REQUEST_INFO *io_info, union ccb *ccb, 84272735Skadesai MR_DRV_RAID_MAP_ALL *local_map_ptr, u_int32_t ref_tag, 85265555Sambrisko u_int32_t ld_block_size); 86265555Sambriskostatic u_int16_t MR_LdSpanArrayGet(u_int32_t ld, u_int32_t span, 87272735Skadesai MR_DRV_RAID_MAP_ALL *map); 88272735Skadesaistatic u_int16_t MR_PdDevHandleGet(u_int32_t pd, MR_DRV_RAID_MAP_ALL *map); 89265555Sambriskostatic u_int16_t MR_ArPdGet(u_int32_t ar, u_int32_t arm, 90272735Skadesai MR_DRV_RAID_MAP_ALL *map); 91265555Sambriskostatic MR_LD_SPAN *MR_LdSpanPtrGet(u_int32_t ld, u_int32_t span, 92272735Skadesai MR_DRV_RAID_MAP_ALL *map); 93265555Sambriskostatic u_int8_t MR_LdDataArmGet(u_int32_t ld, u_int32_t armIdx, 94272735Skadesai MR_DRV_RAID_MAP_ALL *map); 95265555Sambriskostatic MR_SPAN_BLOCK_INFO *MR_LdSpanInfoGet(u_int32_t ld, 96272735Skadesai MR_DRV_RAID_MAP_ALL *map); 97272735SkadesaiMR_LD_RAID *MR_LdRaidGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL *map); 98272735Skadesaivoid MR_PopulateDrvRaidMap (struct mrsas_softc *sc); 99265555Sambrisko 100272735Skadesai 101265555Sambrisko/* 102265555Sambrisko * Spanset related function prototypes 103265555Sambrisko * Added for PRL11 configuration (Uneven span support) 104265555Sambrisko */ 105272735Skadesaivoid mr_update_span_set(MR_DRV_RAID_MAP_ALL *map, PLD_SPAN_INFO ldSpanInfo); 106265555Sambriskostatic u_int8_t mr_spanset_get_phy_params(struct mrsas_softc *sc, u_int32_t ld, 107265555Sambrisko u_int64_t stripRow, u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 108272735Skadesai RAID_CONTEXT *pRAID_Context, MR_DRV_RAID_MAP_ALL *map); 109265555Sambriskostatic u_int64_t get_row_from_strip(struct mrsas_softc *sc, u_int32_t ld, 110272735Skadesai u_int64_t strip, MR_DRV_RAID_MAP_ALL *map); 111265555Sambriskostatic u_int32_t mr_spanset_get_span_block(struct mrsas_softc *sc, 112265555Sambrisko u_int32_t ld, u_int64_t row, u_int64_t *span_blk, 113272735Skadesai MR_DRV_RAID_MAP_ALL *map, int *div_error); 114265555Sambriskostatic u_int8_t get_arm(struct mrsas_softc *sc, u_int32_t ld, u_int8_t span, 115272735Skadesai u_int64_t stripe, MR_DRV_RAID_MAP_ALL *map); 116265555Sambrisko 117265555Sambrisko 118265555Sambrisko/* 119265555Sambrisko * Spanset related defines 120265555Sambrisko * Added for PRL11 configuration(Uneven span support) 121265555Sambrisko */ 122265555Sambrisko#define SPAN_ROW_SIZE(map, ld, index_) MR_LdSpanPtrGet(ld, index_, map)->spanRowSize 123265555Sambrisko#define SPAN_ROW_DATA_SIZE(map_, ld, index_) MR_LdSpanPtrGet(ld, index_, map)->spanRowDataSize 124265555Sambrisko#define SPAN_INVALID 0xff 125265555Sambrisko#define SPAN_DEBUG 0 126265555Sambrisko 127265555Sambrisko/* 128265555Sambrisko * Related Defines 129265555Sambrisko */ 130265555Sambrisko 131265555Sambriskotypedef u_int64_t REGION_KEY; 132265555Sambriskotypedef u_int32_t REGION_LEN; 133265555Sambrisko 134265555Sambrisko#define MR_LD_STATE_OPTIMAL 3 135265555Sambrisko#define FALSE 0 136265555Sambrisko#define TRUE 1 137265555Sambrisko 138265555Sambrisko 139265555Sambrisko/* 140265555Sambrisko * Related Macros 141265555Sambrisko */ 142265555Sambrisko 143265555Sambrisko#define ABS_DIFF(a,b) ( ((a) > (b)) ? ((a) - (b)) : ((b) - (a)) ) 144265555Sambrisko 145265555Sambrisko#define swap32(x) \ 146265555Sambrisko ((unsigned int)( \ 147265555Sambrisko (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \ 148265555Sambrisko (((unsigned int)(x) & (unsigned int)0x0000ff00UL) << 8) | \ 149265555Sambrisko (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >> 8) | \ 150265555Sambrisko (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) )) 151265555Sambrisko 152265555Sambrisko 153265555Sambrisko/* 154265555Sambrisko * In-line functions for mod and divide of 64-bit dividend and 32-bit divisor. 155265555Sambrisko * Assumes a check for a divisor of zero is not possible. 156265555Sambrisko * 157265555Sambrisko * @param dividend : Dividend 158265555Sambrisko * @param divisor : Divisor 159265555Sambrisko * @return remainder 160265555Sambrisko */ 161265555Sambrisko 162265555Sambrisko#define mega_mod64(dividend, divisor) ({ \ 163265555Sambriskoint remainder; \ 164265555Sambriskoremainder = ((u_int64_t) (dividend)) % (u_int32_t) (divisor); \ 165265555Sambriskoremainder;}) 166265555Sambrisko 167265555Sambrisko#define mega_div64_32(dividend, divisor) ({ \ 168265555Sambriskoint quotient; \ 169265555Sambriskoquotient = ((u_int64_t) (dividend)) / (u_int32_t) (divisor); \ 170265555Sambriskoquotient;}) 171265555Sambrisko 172265555Sambrisko 173265555Sambrisko/* 174265555Sambrisko * Various RAID map access functions. These functions access the various 175265555Sambrisko * parts of the RAID map and returns the appropriate parameters. 176265555Sambrisko */ 177265555Sambrisko 178272735SkadesaiMR_LD_RAID *MR_LdRaidGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL *map) 179265555Sambrisko{ 180265555Sambrisko return (&map->raidMap.ldSpanMap[ld].ldRaid); 181265555Sambrisko} 182265555Sambrisko 183272735Skadesaiu_int16_t MR_GetLDTgtId(u_int32_t ld, MR_DRV_RAID_MAP_ALL *map) 184265555Sambrisko{ 185265555Sambrisko return (map->raidMap.ldSpanMap[ld].ldRaid.targetId); 186265555Sambrisko} 187265555Sambrisko 188272735Skadesaistatic u_int16_t MR_LdSpanArrayGet(u_int32_t ld, u_int32_t span, MR_DRV_RAID_MAP_ALL *map) 189265555Sambrisko{ 190265555Sambrisko return map->raidMap.ldSpanMap[ld].spanBlock[span].span.arrayRef; 191265555Sambrisko} 192265555Sambrisko 193272735Skadesaistatic u_int8_t MR_LdDataArmGet(u_int32_t ld, u_int32_t armIdx, MR_DRV_RAID_MAP_ALL *map) 194265555Sambrisko{ 195265555Sambrisko return map->raidMap.ldSpanMap[ld].dataArmMap[armIdx]; 196265555Sambrisko} 197265555Sambrisko 198272735Skadesaistatic u_int16_t MR_PdDevHandleGet(u_int32_t pd, MR_DRV_RAID_MAP_ALL *map) 199265555Sambrisko{ 200265555Sambrisko return map->raidMap.devHndlInfo[pd].curDevHdl; 201265555Sambrisko} 202265555Sambrisko 203272735Skadesaistatic u_int16_t MR_ArPdGet(u_int32_t ar, u_int32_t arm, MR_DRV_RAID_MAP_ALL *map) 204265555Sambrisko{ 205265555Sambrisko return map->raidMap.arMapInfo[ar].pd[arm]; 206265555Sambrisko} 207265555Sambrisko 208272735Skadesaistatic MR_LD_SPAN *MR_LdSpanPtrGet(u_int32_t ld, u_int32_t span, MR_DRV_RAID_MAP_ALL *map) 209265555Sambrisko{ 210265555Sambrisko return &map->raidMap.ldSpanMap[ld].spanBlock[span].span; 211265555Sambrisko} 212265555Sambrisko 213272735Skadesaistatic MR_SPAN_BLOCK_INFO *MR_LdSpanInfoGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL *map) 214265555Sambrisko{ 215265555Sambrisko return &map->raidMap.ldSpanMap[ld].spanBlock[0]; 216265555Sambrisko} 217265555Sambrisko 218272735Skadesaiu_int16_t MR_TargetIdToLdGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL *map) 219265555Sambrisko{ 220265555Sambrisko return map->raidMap.ldTgtIdToLd[ldTgtId]; 221265555Sambrisko} 222265555Sambrisko 223272735Skadesaiu_int32_t MR_LdBlockSizeGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL *map) 224265555Sambrisko{ 225265555Sambrisko MR_LD_RAID *raid; 226265555Sambrisko u_int32_t ld, ldBlockSize = MRSAS_SCSIBLOCKSIZE; 227265555Sambrisko 228265555Sambrisko ld = MR_TargetIdToLdGet(ldTgtId, map); 229265555Sambrisko 230265555Sambrisko /* 231265555Sambrisko * Check if logical drive was removed. 232265555Sambrisko */ 233265555Sambrisko if (ld >= MAX_LOGICAL_DRIVES) 234265555Sambrisko return ldBlockSize; 235265555Sambrisko 236265555Sambrisko raid = MR_LdRaidGet(ld, map); 237265555Sambrisko ldBlockSize = raid->logicalBlockLength; 238265555Sambrisko if (!ldBlockSize) 239265555Sambrisko ldBlockSize = MRSAS_SCSIBLOCKSIZE; 240265555Sambrisko 241265555Sambrisko return ldBlockSize; 242265555Sambrisko} 243265555Sambrisko 244272735Skadesai/* 245272735Skadesai * This function will Populate Driver Map using firmware raid map 246272735Skadesai */ 247272735Skadesaivoid MR_PopulateDrvRaidMap(struct mrsas_softc *sc) 248272735Skadesai{ 249272735Skadesai MR_FW_RAID_MAP_ALL *fw_map_old = NULL; 250272735Skadesai MR_FW_RAID_MAP *pFwRaidMap = NULL; 251272735Skadesai unsigned int i; 252272735Skadesai 253272735Skadesai MR_DRV_RAID_MAP_ALL *drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 254272735Skadesai MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap; 255272735Skadesai 256272735Skadesai if(sc->max256vdSupport) { 257272735Skadesai memcpy(sc->ld_drv_map[sc->map_id & 1], 258272735Skadesai sc->raidmap_mem[sc->map_id & 1], 259272735Skadesai sc->current_map_sz); 260272735Skadesai /* New Raid map will not set totalSize, so keep expected value 261272735Skadesai * for legacy code in ValidateMapInfo 262272735Skadesai */ 263272735Skadesai pDrvRaidMap->totalSize = sizeof (MR_FW_RAID_MAP_EXT); 264272735Skadesai } else { 265272735Skadesai fw_map_old =(MR_FW_RAID_MAP_ALL *) sc->raidmap_mem[(sc->map_id & 1)]; 266272735Skadesai pFwRaidMap = &fw_map_old->raidMap; 267272735Skadesai 268272735Skadesai#if VD_EXT_DEBUG 269272735Skadesai for (i = 0; i < pFwRaidMap->ldCount; i++) { 270272735Skadesai device_printf(sc->mrsas_dev, 271272735Skadesai "Index 0x%x Target Id 0x%x Seq Num 0x%x Size 0/%lx\n", i, 272272735Skadesai fw_map_old->raidMap.ldSpanMap[i].ldRaid.targetId, 273272735Skadesai fw_map_old->raidMap.ldSpanMap[i].ldRaid.seqNum, 274272735Skadesai fw_map_old->raidMap.ldSpanMap[i].ldRaid.size ); 275272735Skadesai } 276272735Skadesai#endif 277272735Skadesai 278272735Skadesai memset(drv_map, 0, sc->drv_map_sz); 279272735Skadesai pDrvRaidMap->totalSize = pFwRaidMap->totalSize; 280272735Skadesai pDrvRaidMap->ldCount = pFwRaidMap->ldCount; 281272735Skadesai pDrvRaidMap->fpPdIoTimeoutSec = 282272735Skadesai pFwRaidMap->fpPdIoTimeoutSec; 283272735Skadesai 284272735Skadesai for(i=0; i < MAX_RAIDMAP_LOGICAL_DRIVES+MAX_RAIDMAP_VIEWS; i++) { 285272735Skadesai pDrvRaidMap->ldTgtIdToLd[i] = 286272735Skadesai (u_int8_t)pFwRaidMap->ldTgtIdToLd[i]; 287272735Skadesai } 288272735Skadesai 289272735Skadesai for(i=0; i < pDrvRaidMap->ldCount; i++) { 290272735Skadesai pDrvRaidMap->ldSpanMap[i] = 291272735Skadesai pFwRaidMap->ldSpanMap[i]; 292272735Skadesai 293272735Skadesai#if VD_EXT_DEBUG 294272735Skadesai device_printf(sc->mrsas_dev, "pFwRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x " 295272735Skadesai "pFwRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x size 0x%x\n", 296272735Skadesai i, i, pFwRaidMap->ldSpanMap[i].ldRaid.targetId, 297272735Skadesai pFwRaidMap->ldSpanMap[i].ldRaid.seqNum, 298272735Skadesai (u_int32_t)pFwRaidMap->ldSpanMap[i].ldRaid.rowSize); 299272735Skadesai device_printf(sc->mrsas_dev, "pDrvRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x" 300272735Skadesai "pDrvRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x size 0x%x\n",i, i, 301272735Skadesai pDrvRaidMap->ldSpanMap[i].ldRaid.targetId, 302272735Skadesai pDrvRaidMap->ldSpanMap[i].ldRaid.seqNum, 303272735Skadesai (u_int32_t)pDrvRaidMap->ldSpanMap[i].ldRaid.rowSize); 304272735Skadesai device_printf(sc->mrsas_dev, "drv raid map all %p raid map %p LD RAID MAP %p/%p\n", 305272735Skadesai drv_map, pDrvRaidMap, 306272735Skadesai &pFwRaidMap->ldSpanMap[i].ldRaid, &pDrvRaidMap->ldSpanMap[i].ldRaid); 307272735Skadesai#endif 308272735Skadesai } 309272735Skadesai 310272735Skadesai memcpy(pDrvRaidMap->arMapInfo, pFwRaidMap->arMapInfo, 311272735Skadesai sizeof(MR_ARRAY_INFO) * MAX_RAIDMAP_ARRAYS); 312272735Skadesai memcpy(pDrvRaidMap->devHndlInfo, pFwRaidMap->devHndlInfo, 313272735Skadesai sizeof(MR_DEV_HANDLE_INFO) * 314272735Skadesai MAX_RAIDMAP_PHYSICAL_DEVICES); 315272735Skadesai } 316272735Skadesai} 317272735Skadesai 318265555Sambrisko/** 319265555Sambrisko * MR_ValidateMapInfo: Validate RAID map 320265555Sambrisko * input: Adapter instance soft state 321265555Sambrisko * 322265555Sambrisko * This function checks and validates the loaded RAID map. It returns 0 if 323265555Sambrisko * successful, and 1 otherwise. 324265555Sambrisko */ 325265555Sambriskou_int8_t MR_ValidateMapInfo(struct mrsas_softc *sc) 326265555Sambrisko{ 327265555Sambrisko if (!sc) { 328265555Sambrisko return 1; 329265555Sambrisko } 330272735Skadesai 331272735Skadesai MR_PopulateDrvRaidMap (sc); 332272735Skadesai 333272735Skadesai MR_DRV_RAID_MAP_ALL *drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 334272735Skadesai MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap; 335272735Skadesai 336272735Skadesai u_int32_t expected_map_size; 337272735Skadesai drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 338272735Skadesai pDrvRaidMap = &drv_map->raidMap; 339265555Sambrisko PLD_SPAN_INFO ldSpanInfo = (PLD_SPAN_INFO) &sc->log_to_span; 340265555Sambrisko 341272735Skadesai if(sc->max256vdSupport) 342272735Skadesai expected_map_size = sizeof (MR_FW_RAID_MAP_EXT); 343272735Skadesai else 344272735Skadesai expected_map_size = 345272735Skadesai (sizeof (MR_FW_RAID_MAP) - sizeof(MR_LD_SPAN_MAP)) + 346272735Skadesai (sizeof(MR_LD_SPAN_MAP) * pDrvRaidMap->ldCount); 347265555Sambrisko 348272735Skadesai if (pDrvRaidMap->totalSize != expected_map_size) { 349272735Skadesai device_printf(sc->mrsas_dev, "map size %x not matching ld count\n", expected_map_size); 350265555Sambrisko device_printf(sc->mrsas_dev, "span map= %x\n", (unsigned int)sizeof(MR_LD_SPAN_MAP)); 351272735Skadesai device_printf(sc->mrsas_dev, "pDrvRaidMap->totalSize=%x\n", pDrvRaidMap->totalSize); 352265555Sambrisko return 1; 353265555Sambrisko } 354265555Sambrisko 355265555Sambrisko if (sc->UnevenSpanSupport) { 356272735Skadesai printf ("Updating span set\n\n"); 357272735Skadesai mr_update_span_set(drv_map, ldSpanInfo); 358265555Sambrisko } 359265555Sambrisko 360272735Skadesai mrsas_update_load_balance_params(drv_map, sc->load_balance_info); 361265555Sambrisko 362265555Sambrisko return 0; 363265555Sambrisko} 364265555Sambrisko 365265555Sambrisko/* 366265555Sambrisko * ****************************************************************************** 367265555Sambrisko * 368265555Sambrisko * Function to print info about span set created in driver from FW raid map 369265555Sambrisko * 370265555Sambrisko * Inputs : 371265555Sambrisko * map - LD map 372265555Sambrisko * ldSpanInfo - ldSpanInfo per HBA instance 373265555Sambrisko * 374265555Sambrisko * 375265555Sambrisko * */ 376265555Sambrisko#if SPAN_DEBUG 377272735Skadesaistatic int getSpanInfo(MR_DRV_RAID_MAP_ALL *map, PLD_SPAN_INFO ldSpanInfo) 378265555Sambrisko{ 379265555Sambrisko 380265555Sambrisko u_int8_t span; 381265555Sambrisko u_int32_t element; 382265555Sambrisko MR_LD_RAID *raid; 383265555Sambrisko LD_SPAN_SET *span_set; 384265555Sambrisko MR_QUAD_ELEMENT *quad; 385265555Sambrisko int ldCount; 386265555Sambrisko u_int16_t ld; 387265555Sambrisko 388265555Sambrisko for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) 389265555Sambrisko { 390265555Sambrisko ld = MR_TargetIdToLdGet(ldCount, map); 391265555Sambrisko if (ld >= MAX_LOGICAL_DRIVES) { 392265555Sambrisko continue; 393265555Sambrisko } 394265555Sambrisko raid = MR_LdRaidGet(ld, map); 395265555Sambrisko printf("LD %x: span_depth=%x\n", ld, raid->spanDepth); 396265555Sambrisko for (span=0; span<raid->spanDepth; span++) 397265555Sambrisko printf("Span=%x, number of quads=%x\n", span, 398265555Sambrisko map->raidMap.ldSpanMap[ld].spanBlock[span]. 399265555Sambrisko block_span_info.noElements); 400265555Sambrisko for (element=0; element < MAX_QUAD_DEPTH; element++) { 401265555Sambrisko span_set = &(ldSpanInfo[ld].span_set[element]); 402265555Sambrisko if (span_set->span_row_data_width == 0) break; 403265555Sambrisko 404265555Sambrisko printf(" Span Set %x: width=%x, diff=%x\n", element, 405265555Sambrisko (unsigned int)span_set->span_row_data_width, 406265555Sambrisko (unsigned int)span_set->diff); 407265555Sambrisko printf(" logical LBA start=0x%08lx, end=0x%08lx\n", 408265555Sambrisko (long unsigned int)span_set->log_start_lba, 409265555Sambrisko (long unsigned int)span_set->log_end_lba); 410265555Sambrisko printf(" span row start=0x%08lx, end=0x%08lx\n", 411265555Sambrisko (long unsigned int)span_set->span_row_start, 412265555Sambrisko (long unsigned int)span_set->span_row_end); 413265555Sambrisko printf(" data row start=0x%08lx, end=0x%08lx\n", 414265555Sambrisko (long unsigned int)span_set->data_row_start, 415265555Sambrisko (long unsigned int)span_set->data_row_end); 416265555Sambrisko printf(" data strip start=0x%08lx, end=0x%08lx\n", 417265555Sambrisko (long unsigned int)span_set->data_strip_start, 418265555Sambrisko (long unsigned int)span_set->data_strip_end); 419265555Sambrisko 420265555Sambrisko for (span=0; span<raid->spanDepth; span++) { 421265555Sambrisko if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 422265555Sambrisko block_span_info.noElements >=element+1){ 423265555Sambrisko quad = &map->raidMap.ldSpanMap[ld]. 424265555Sambrisko spanBlock[span].block_span_info. 425265555Sambrisko quad[element]; 426265555Sambrisko printf(" Span=%x, Quad=%x, diff=%x\n", span, 427265555Sambrisko element, quad->diff); 428265555Sambrisko printf(" offset_in_span=0x%08lx\n", 429265555Sambrisko (long unsigned int)quad->offsetInSpan); 430265555Sambrisko printf(" logical start=0x%08lx, end=0x%08lx\n", 431265555Sambrisko (long unsigned int)quad->logStart, 432265555Sambrisko (long unsigned int)quad->logEnd); 433265555Sambrisko } 434265555Sambrisko } 435265555Sambrisko } 436265555Sambrisko } 437265555Sambrisko return 0; 438265555Sambrisko} 439265555Sambrisko#endif 440265555Sambrisko/* 441265555Sambrisko****************************************************************************** 442265555Sambrisko* 443265555Sambrisko* This routine calculates the Span block for given row using spanset. 444265555Sambrisko* 445265555Sambrisko* Inputs : 446265555Sambrisko* instance - HBA instance 447265555Sambrisko* ld - Logical drive number 448265555Sambrisko* row - Row number 449265555Sambrisko* map - LD map 450265555Sambrisko* 451265555Sambrisko* Outputs : 452265555Sambrisko* 453265555Sambrisko* span - Span number 454265555Sambrisko* block - Absolute Block number in the physical disk 455265555Sambrisko* div_error - Devide error code. 456265555Sambrisko*/ 457265555Sambrisko 458265555Sambriskou_int32_t mr_spanset_get_span_block(struct mrsas_softc *sc, u_int32_t ld, u_int64_t row, 459272735Skadesai u_int64_t *span_blk, MR_DRV_RAID_MAP_ALL *map, int *div_error) 460265555Sambrisko{ 461265555Sambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 462265555Sambrisko LD_SPAN_SET *span_set; 463265555Sambrisko MR_QUAD_ELEMENT *quad; 464265555Sambrisko u_int32_t span, info; 465265555Sambrisko PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 466265555Sambrisko 467265555Sambrisko for (info=0; info < MAX_QUAD_DEPTH; info++) { 468265555Sambrisko span_set = &(ldSpanInfo[ld].span_set[info]); 469265555Sambrisko 470265555Sambrisko if (span_set->span_row_data_width == 0) break; 471265555Sambrisko if (row > span_set->data_row_end) continue; 472265555Sambrisko 473265555Sambrisko for (span=0; span<raid->spanDepth; span++) 474265555Sambrisko if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 475265555Sambrisko block_span_info.noElements >= info+1) { 476265555Sambrisko quad = &map->raidMap.ldSpanMap[ld]. 477265555Sambrisko spanBlock[span]. 478265555Sambrisko block_span_info.quad[info]; 479265555Sambrisko if (quad->diff == 0) { 480265555Sambrisko *div_error = 1; 481265555Sambrisko return span; 482265555Sambrisko } 483265555Sambrisko if ( quad->logStart <= row && 484265555Sambrisko row <= quad->logEnd && 485265555Sambrisko (mega_mod64(row - quad->logStart, 486265555Sambrisko quad->diff)) == 0 ) { 487265555Sambrisko if (span_blk != NULL) { 488265555Sambrisko u_int64_t blk; 489265555Sambrisko blk = mega_div64_32 490265555Sambrisko ((row - quad->logStart), 491265555Sambrisko quad->diff); 492265555Sambrisko blk = (blk + quad->offsetInSpan) 493265555Sambrisko << raid->stripeShift; 494265555Sambrisko *span_blk = blk; 495265555Sambrisko } 496265555Sambrisko return span; 497265555Sambrisko } 498265555Sambrisko } 499265555Sambrisko } 500265555Sambrisko return SPAN_INVALID; 501265555Sambrisko} 502265555Sambrisko 503265555Sambrisko/* 504265555Sambrisko****************************************************************************** 505265555Sambrisko* 506265555Sambrisko* This routine calculates the row for given strip using spanset. 507265555Sambrisko* 508265555Sambrisko* Inputs : 509265555Sambrisko* instance - HBA instance 510265555Sambrisko* ld - Logical drive number 511265555Sambrisko* Strip - Strip 512265555Sambrisko* map - LD map 513265555Sambrisko* 514265555Sambrisko* Outputs : 515265555Sambrisko* 516265555Sambrisko* row - row associated with strip 517265555Sambrisko*/ 518265555Sambrisko 519265555Sambriskostatic u_int64_t get_row_from_strip(struct mrsas_softc *sc, 520272735Skadesai u_int32_t ld, u_int64_t strip, MR_DRV_RAID_MAP_ALL *map) 521265555Sambrisko{ 522265555Sambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 523265555Sambrisko LD_SPAN_SET *span_set; 524265555Sambrisko PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 525265555Sambrisko u_int32_t info, strip_offset, span, span_offset; 526265555Sambrisko u_int64_t span_set_Strip, span_set_Row; 527265555Sambrisko 528265555Sambrisko for (info=0; info < MAX_QUAD_DEPTH; info++) { 529265555Sambrisko span_set = &(ldSpanInfo[ld].span_set[info]); 530265555Sambrisko 531265555Sambrisko if (span_set->span_row_data_width == 0) break; 532265555Sambrisko if (strip > span_set->data_strip_end) continue; 533265555Sambrisko 534265555Sambrisko span_set_Strip = strip - span_set->data_strip_start; 535265555Sambrisko strip_offset = mega_mod64(span_set_Strip, 536265555Sambrisko span_set->span_row_data_width); 537265555Sambrisko span_set_Row = mega_div64_32(span_set_Strip, 538265555Sambrisko span_set->span_row_data_width) * span_set->diff; 539265555Sambrisko for (span=0,span_offset=0; span<raid->spanDepth; span++) 540265555Sambrisko if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 541265555Sambrisko block_span_info.noElements >=info+1) { 542265555Sambrisko if (strip_offset >= 543265555Sambrisko span_set->strip_offset[span]) 544265555Sambrisko span_offset++; 545265555Sambrisko else 546265555Sambrisko break; 547265555Sambrisko } 548265555Sambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : Strip 0x%llx, span_set_Strip 0x%llx, span_set_Row 0x%llx " 549265555Sambrisko "data width 0x%llx span offset 0x%llx\n", (unsigned long long)strip, 550265555Sambrisko (unsigned long long)span_set_Strip, 551265555Sambrisko (unsigned long long)span_set_Row, 552265555Sambrisko (unsigned long long)span_set->span_row_data_width, (unsigned long long)span_offset); 553265555Sambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : For strip 0x%llx row is 0x%llx\n", (unsigned long long)strip, 554265555Sambrisko (unsigned long long) span_set->data_row_start + 555265555Sambrisko (unsigned long long) span_set_Row + (span_offset - 1)); 556265555Sambrisko return (span_set->data_row_start + span_set_Row + (span_offset - 1)); 557265555Sambrisko } 558265555Sambrisko return -1LLU; 559265555Sambrisko} 560265555Sambrisko 561265555Sambrisko 562265555Sambrisko/* 563265555Sambrisko****************************************************************************** 564265555Sambrisko* 565265555Sambrisko* This routine calculates the Start Strip for given row using spanset. 566265555Sambrisko* 567265555Sambrisko* Inputs : 568265555Sambrisko* instance - HBA instance 569265555Sambrisko* ld - Logical drive number 570265555Sambrisko* row - Row number 571265555Sambrisko* map - LD map 572265555Sambrisko* 573265555Sambrisko* Outputs : 574265555Sambrisko* 575265555Sambrisko* Strip - Start strip associated with row 576265555Sambrisko*/ 577265555Sambrisko 578265555Sambriskostatic u_int64_t get_strip_from_row(struct mrsas_softc *sc, 579272735Skadesai u_int32_t ld, u_int64_t row, MR_DRV_RAID_MAP_ALL *map) 580265555Sambrisko{ 581265555Sambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 582265555Sambrisko LD_SPAN_SET *span_set; 583265555Sambrisko MR_QUAD_ELEMENT *quad; 584265555Sambrisko PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 585265555Sambrisko u_int32_t span, info; 586265555Sambrisko u_int64_t strip; 587265555Sambrisko 588265555Sambrisko for (info=0; info<MAX_QUAD_DEPTH; info++) { 589265555Sambrisko span_set = &(ldSpanInfo[ld].span_set[info]); 590265555Sambrisko 591265555Sambrisko if (span_set->span_row_data_width == 0) break; 592265555Sambrisko if (row > span_set->data_row_end) continue; 593265555Sambrisko 594265555Sambrisko for (span=0; span<raid->spanDepth; span++) 595265555Sambrisko if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 596265555Sambrisko block_span_info.noElements >=info+1) { 597265555Sambrisko quad = &map->raidMap.ldSpanMap[ld]. 598265555Sambrisko spanBlock[span].block_span_info.quad[info]; 599265555Sambrisko if ( quad->logStart <= row && 600265555Sambrisko row <= quad->logEnd && 601265555Sambrisko mega_mod64((row - quad->logStart), 602265555Sambrisko quad->diff) == 0 ) { 603265555Sambrisko strip = mega_div64_32 604265555Sambrisko (((row - span_set->data_row_start) 605265555Sambrisko - quad->logStart), 606265555Sambrisko quad->diff); 607265555Sambrisko strip *= span_set->span_row_data_width; 608265555Sambrisko strip += span_set->data_strip_start; 609265555Sambrisko strip += span_set->strip_offset[span]; 610265555Sambrisko return strip; 611265555Sambrisko } 612265555Sambrisko } 613265555Sambrisko } 614265555Sambrisko mrsas_dprint(sc, MRSAS_PRL11,"LSI Debug - get_strip_from_row: returns invalid " 615265555Sambrisko "strip for ld=%x, row=%lx\n", ld, (long unsigned int)row); 616265555Sambrisko return -1; 617265555Sambrisko} 618265555Sambrisko 619265555Sambrisko/* 620265555Sambrisko****************************************************************************** 621265555Sambrisko* 622265555Sambrisko* This routine calculates the Physical Arm for given strip using spanset. 623265555Sambrisko* 624265555Sambrisko* Inputs : 625265555Sambrisko* instance - HBA instance 626265555Sambrisko* ld - Logical drive number 627265555Sambrisko* strip - Strip 628265555Sambrisko* map - LD map 629265555Sambrisko* 630265555Sambrisko* Outputs : 631265555Sambrisko* 632265555Sambrisko* Phys Arm - Phys Arm associated with strip 633265555Sambrisko*/ 634265555Sambrisko 635265555Sambriskostatic u_int32_t get_arm_from_strip(struct mrsas_softc *sc, 636272735Skadesai u_int32_t ld, u_int64_t strip, MR_DRV_RAID_MAP_ALL *map) 637265555Sambrisko{ 638265555Sambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 639265555Sambrisko LD_SPAN_SET *span_set; 640265555Sambrisko PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 641265555Sambrisko u_int32_t info, strip_offset, span, span_offset; 642265555Sambrisko 643265555Sambrisko for (info=0; info<MAX_QUAD_DEPTH; info++) { 644265555Sambrisko span_set = &(ldSpanInfo[ld].span_set[info]); 645265555Sambrisko 646265555Sambrisko if (span_set->span_row_data_width == 0) break; 647265555Sambrisko if (strip > span_set->data_strip_end) continue; 648265555Sambrisko 649265555Sambrisko strip_offset = (u_int32_t)mega_mod64 650265555Sambrisko ((strip - span_set->data_strip_start), 651265555Sambrisko span_set->span_row_data_width); 652265555Sambrisko 653265555Sambrisko for (span=0,span_offset=0; span<raid->spanDepth; span++) 654265555Sambrisko if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 655265555Sambrisko block_span_info.noElements >=info+1) { 656265555Sambrisko if (strip_offset >= 657265555Sambrisko span_set->strip_offset[span]) 658265555Sambrisko span_offset = 659265555Sambrisko span_set->strip_offset[span]; 660265555Sambrisko else 661265555Sambrisko break; 662265555Sambrisko } 663265555Sambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI PRL11: get_arm_from_strip: " 664265555Sambrisko " for ld=0x%x strip=0x%lx arm is 0x%x\n", ld, 665265555Sambrisko (long unsigned int)strip, (strip_offset - span_offset)); 666265555Sambrisko return (strip_offset - span_offset); 667265555Sambrisko } 668265555Sambrisko 669265555Sambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: - get_arm_from_strip: returns invalid arm" 670265555Sambrisko " for ld=%x strip=%lx\n", ld, (long unsigned int)strip); 671265555Sambrisko 672265555Sambrisko return -1; 673265555Sambrisko} 674265555Sambrisko 675265555Sambrisko 676265555Sambrisko/* This Function will return Phys arm */ 677265555Sambriskou_int8_t get_arm(struct mrsas_softc *sc, u_int32_t ld, u_int8_t span, u_int64_t stripe, 678272735Skadesai MR_DRV_RAID_MAP_ALL *map) 679265555Sambrisko{ 680265555Sambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 681265555Sambrisko /* Need to check correct default value */ 682265555Sambrisko u_int32_t arm = 0; 683265555Sambrisko 684265555Sambrisko switch (raid->level) { 685265555Sambrisko case 0: 686265555Sambrisko case 5: 687265555Sambrisko case 6: 688265555Sambrisko arm = mega_mod64(stripe, SPAN_ROW_SIZE(map, ld, span)); 689265555Sambrisko break; 690265555Sambrisko case 1: 691265555Sambrisko // start with logical arm 692265555Sambrisko arm = get_arm_from_strip(sc, ld, stripe, map); 693265555Sambrisko arm *= 2; 694265555Sambrisko break; 695265555Sambrisko 696265555Sambrisko } 697265555Sambrisko 698265555Sambrisko return arm; 699265555Sambrisko} 700265555Sambrisko 701265555Sambrisko/* 702265555Sambrisko****************************************************************************** 703265555Sambrisko* 704265555Sambrisko* This routine calculates the arm, span and block for the specified stripe and 705265555Sambrisko* reference in stripe using spanset 706265555Sambrisko* 707265555Sambrisko* Inputs : 708265555Sambrisko* 709265555Sambrisko* ld - Logical drive number 710265555Sambrisko* stripRow - Stripe number 711265555Sambrisko* stripRef - Reference in stripe 712265555Sambrisko* 713265555Sambrisko* Outputs : 714265555Sambrisko* 715265555Sambrisko* span - Span number 716265555Sambrisko* block - Absolute Block number in the physical disk 717265555Sambrisko*/ 718265555Sambriskostatic u_int8_t mr_spanset_get_phy_params(struct mrsas_softc *sc, u_int32_t ld, u_int64_t stripRow, 719265555Sambrisko u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 720272735Skadesai RAID_CONTEXT *pRAID_Context, MR_DRV_RAID_MAP_ALL *map) 721265555Sambrisko{ 722265555Sambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 723265555Sambrisko u_int32_t pd, arRef; 724265555Sambrisko u_int8_t physArm, span; 725265555Sambrisko u_int64_t row; 726265555Sambrisko u_int8_t retval = TRUE; 727265555Sambrisko u_int64_t *pdBlock = &io_info->pdBlock; 728265555Sambrisko u_int16_t *pDevHandle = &io_info->devHandle; 729265555Sambrisko u_int32_t logArm, rowMod, armQ, arm; 730265555Sambrisko u_int8_t do_invader = 0; 731265555Sambrisko 732265555Sambrisko if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) 733265555Sambrisko do_invader = 1; 734265555Sambrisko 735265555Sambrisko // Get row and span from io_info for Uneven Span IO. 736265555Sambrisko row = io_info->start_row; 737265555Sambrisko span = io_info->start_span; 738265555Sambrisko 739265555Sambrisko 740265555Sambrisko if (raid->level == 6) { 741265555Sambrisko logArm = get_arm_from_strip(sc, ld, stripRow, map); 742265555Sambrisko rowMod = mega_mod64(row, SPAN_ROW_SIZE(map, ld, span)); 743265555Sambrisko armQ = SPAN_ROW_SIZE(map,ld,span) - 1 - rowMod; 744265555Sambrisko arm = armQ + 1 + logArm; 745265555Sambrisko if (arm >= SPAN_ROW_SIZE(map, ld, span)) 746265555Sambrisko arm -= SPAN_ROW_SIZE(map ,ld ,span); 747265555Sambrisko physArm = (u_int8_t)arm; 748265555Sambrisko } else 749265555Sambrisko // Calculate the arm 750265555Sambrisko physArm = get_arm(sc, ld, span, stripRow, map); 751265555Sambrisko 752265555Sambrisko 753265555Sambrisko arRef = MR_LdSpanArrayGet(ld, span, map); 754265555Sambrisko pd = MR_ArPdGet(arRef, physArm, map); 755265555Sambrisko 756265555Sambrisko if (pd != MR_PD_INVALID) 757265555Sambrisko *pDevHandle = MR_PdDevHandleGet(pd, map); 758265555Sambrisko else { 759265555Sambrisko *pDevHandle = MR_PD_INVALID; 760265555Sambrisko if ((raid->level >= 5) && ((!do_invader) || (do_invader && 761265555Sambrisko raid->regTypeReqOnRead != REGION_TYPE_UNUSED))) 762265555Sambrisko pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; 763265555Sambrisko else if (raid->level == 1) { 764265555Sambrisko pd = MR_ArPdGet(arRef, physArm + 1, map); 765265555Sambrisko if (pd != MR_PD_INVALID) 766265555Sambrisko *pDevHandle = MR_PdDevHandleGet(pd, map); 767265555Sambrisko } 768265555Sambrisko } 769265555Sambrisko 770265555Sambrisko *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk; 771265555Sambrisko pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; 772265555Sambrisko return retval; 773265555Sambrisko} 774265555Sambrisko 775265555Sambrisko/** 776265555Sambrisko* MR_BuildRaidContext: Set up Fast path RAID context 777265555Sambrisko* 778265555Sambrisko* This function will initiate command processing. The start/end row 779265555Sambrisko* and strip information is calculated then the lock is acquired. 780265555Sambrisko* This function will return 0 if region lock was acquired OR return 781265555Sambrisko* num strips. 782265555Sambrisko*/ 783265555Sambriskou_int8_t 784265555SambriskoMR_BuildRaidContext(struct mrsas_softc *sc, struct IO_REQUEST_INFO *io_info, 785272735Skadesai RAID_CONTEXT *pRAID_Context, MR_DRV_RAID_MAP_ALL *map) 786265555Sambrisko{ 787265555Sambrisko MR_LD_RAID *raid; 788265555Sambrisko u_int32_t ld, stripSize, stripe_mask; 789265555Sambrisko u_int64_t endLba, endStrip, endRow, start_row, start_strip; 790265555Sambrisko REGION_KEY regStart; 791265555Sambrisko REGION_LEN regSize; 792265555Sambrisko u_int8_t num_strips, numRows; 793265555Sambrisko u_int16_t ref_in_start_stripe, ref_in_end_stripe; 794265555Sambrisko u_int64_t ldStartBlock; 795265555Sambrisko u_int32_t numBlocks, ldTgtId; 796265555Sambrisko u_int8_t isRead, stripIdx; 797265555Sambrisko u_int8_t retval = 0; 798265555Sambrisko u_int8_t startlba_span = SPAN_INVALID; 799265555Sambrisko u_int64_t *pdBlock = &io_info->pdBlock; 800265555Sambrisko int error_code = 0; 801265555Sambrisko 802265555Sambrisko ldStartBlock = io_info->ldStartBlock; 803265555Sambrisko numBlocks = io_info->numBlocks; 804265555Sambrisko ldTgtId = io_info->ldTgtId; 805265555Sambrisko isRead = io_info->isRead; 806265555Sambrisko 807265555Sambrisko io_info->IoforUnevenSpan = 0; 808265555Sambrisko io_info->start_span = SPAN_INVALID; 809265555Sambrisko 810265555Sambrisko ld = MR_TargetIdToLdGet(ldTgtId, map); 811265555Sambrisko raid = MR_LdRaidGet(ld, map); 812265555Sambrisko 813265555Sambrisko /* 814265555Sambrisko * if rowDataSize @RAID map and spanRowDataSize @SPAN INFO are zero 815265555Sambrisko * return FALSE 816265555Sambrisko */ 817265555Sambrisko if (raid->rowDataSize == 0) { 818265555Sambrisko if (MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize == 0) 819265555Sambrisko return FALSE; 820265555Sambrisko else if (sc->UnevenSpanSupport) { 821265555Sambrisko io_info->IoforUnevenSpan = 1; 822265555Sambrisko } 823265555Sambrisko else { 824265555Sambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: raid->rowDataSize is 0, but has SPAN[0] rowDataSize = 0x%0x," 825265555Sambrisko " but there is _NO_ UnevenSpanSupport\n", 826265555Sambrisko MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize); 827265555Sambrisko return FALSE; 828265555Sambrisko } 829265555Sambrisko } 830265555Sambrisko stripSize = 1 << raid->stripeShift; 831265555Sambrisko stripe_mask = stripSize-1; 832265555Sambrisko /* 833265555Sambrisko * calculate starting row and stripe, and number of strips and rows 834265555Sambrisko */ 835265555Sambrisko start_strip = ldStartBlock >> raid->stripeShift; 836265555Sambrisko ref_in_start_stripe = (u_int16_t)(ldStartBlock & stripe_mask); 837265555Sambrisko endLba = ldStartBlock + numBlocks - 1; 838265555Sambrisko ref_in_end_stripe = (u_int16_t)(endLba & stripe_mask); 839265555Sambrisko endStrip = endLba >> raid->stripeShift; 840265555Sambrisko num_strips = (u_int8_t)(endStrip - start_strip + 1); // End strip 841265555Sambrisko if (io_info->IoforUnevenSpan) { 842265555Sambrisko start_row = get_row_from_strip(sc, ld, start_strip, map); 843265555Sambrisko endRow = get_row_from_strip(sc, ld, endStrip, map); 844265555Sambrisko if (raid->spanDepth == 1) { 845265555Sambrisko startlba_span = 0; 846265555Sambrisko *pdBlock = start_row << raid->stripeShift; 847265555Sambrisko } else { 848265555Sambrisko startlba_span = (u_int8_t)mr_spanset_get_span_block(sc, ld, start_row, 849265555Sambrisko pdBlock, map, &error_code); 850265555Sambrisko if (error_code == 1) { 851265555Sambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: return from %s %d. Send IO w/o region lock.\n", 852265555Sambrisko __func__, __LINE__); 853265555Sambrisko return FALSE; 854265555Sambrisko } 855265555Sambrisko } 856265555Sambrisko if (startlba_span == SPAN_INVALID) { 857265555Sambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: return from %s %d for row 0x%llx," 858265555Sambrisko "start strip %llx endSrip %llx\n", __func__, 859265555Sambrisko __LINE__, (unsigned long long)start_row, 860265555Sambrisko (unsigned long long)start_strip, 861265555Sambrisko (unsigned long long)endStrip); 862265555Sambrisko return FALSE; 863265555Sambrisko } 864265555Sambrisko io_info->start_span = startlba_span; 865265555Sambrisko io_info->start_row = start_row; 866265555Sambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: Check Span number from %s %d for row 0x%llx, " 867265555Sambrisko " start strip 0x%llx endSrip 0x%llx span 0x%x\n", 868265555Sambrisko __func__, __LINE__, (unsigned long long)start_row, 869265555Sambrisko (unsigned long long)start_strip, 870265555Sambrisko (unsigned long long)endStrip, startlba_span); 871265555Sambrisko mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : 1. start_row 0x%llx endRow 0x%llx Start span 0x%x\n", 872265555Sambrisko (unsigned long long)start_row, (unsigned long long)endRow, startlba_span); 873265555Sambrisko } else { 874265555Sambrisko start_row = mega_div64_32(start_strip, raid->rowDataSize); // Start Row 875265555Sambrisko endRow = mega_div64_32(endStrip, raid->rowDataSize); 876265555Sambrisko } 877265555Sambrisko 878265555Sambrisko numRows = (u_int8_t)(endRow - start_row + 1); // get the row count 879265555Sambrisko 880265555Sambrisko /* 881265555Sambrisko * Calculate region info. (Assume region at start of first row, and 882265555Sambrisko * assume this IO needs the full row - will adjust if not true.) 883265555Sambrisko */ 884265555Sambrisko regStart = start_row << raid->stripeShift; 885265555Sambrisko regSize = stripSize; 886265555Sambrisko 887265555Sambrisko /* Check if we can send this I/O via FastPath */ 888265555Sambrisko if (raid->capability.fpCapable) { 889265555Sambrisko if (isRead) 890265555Sambrisko io_info->fpOkForIo = (raid->capability.fpReadCapable && 891265555Sambrisko ((num_strips == 1) || 892265555Sambrisko raid->capability. 893265555Sambrisko fpReadAcrossStripe)); 894265555Sambrisko else 895265555Sambrisko io_info->fpOkForIo = (raid->capability.fpWriteCapable && 896265555Sambrisko ((num_strips == 1) || 897265555Sambrisko raid->capability. 898265555Sambrisko fpWriteAcrossStripe)); 899265555Sambrisko } 900265555Sambrisko else 901265555Sambrisko io_info->fpOkForIo = FALSE; 902265555Sambrisko 903265555Sambrisko if (numRows == 1) { 904265555Sambrisko if (num_strips == 1) { 905265555Sambrisko /* single-strip IOs can always lock only the data needed, 906265555Sambrisko multi-strip IOs always need to full stripe locked */ 907265555Sambrisko regStart += ref_in_start_stripe; 908265555Sambrisko regSize = numBlocks; 909265555Sambrisko } 910265555Sambrisko } 911265555Sambrisko else if (io_info->IoforUnevenSpan == 0){ 912265555Sambrisko // For Even span region lock optimization. 913265555Sambrisko // If the start strip is the last in the start row 914265555Sambrisko if (start_strip == (start_row + 1) * raid->rowDataSize - 1) { 915265555Sambrisko regStart += ref_in_start_stripe; 916265555Sambrisko // initialize count to sectors from startRef to end of strip 917265555Sambrisko regSize = stripSize - ref_in_start_stripe; 918265555Sambrisko } 919265555Sambrisko // add complete rows in the middle of the transfer 920265555Sambrisko if (numRows > 2) 921265555Sambrisko regSize += (numRows-2) << raid->stripeShift; 922265555Sambrisko 923265555Sambrisko // if IO ends within first strip of last row 924265555Sambrisko if (endStrip == endRow*raid->rowDataSize) 925265555Sambrisko regSize += ref_in_end_stripe+1; 926265555Sambrisko else 927265555Sambrisko regSize += stripSize; 928265555Sambrisko } else { 929265555Sambrisko //For Uneven span region lock optimization. 930265555Sambrisko // If the start strip is the last in the start row 931265555Sambrisko if (start_strip == (get_strip_from_row(sc, ld, start_row, map) + 932265555Sambrisko SPAN_ROW_DATA_SIZE(map, ld, startlba_span) - 1)) { 933265555Sambrisko regStart += ref_in_start_stripe; 934265555Sambrisko // initialize count to sectors from startRef to end of strip 935265555Sambrisko regSize = stripSize - ref_in_start_stripe; 936265555Sambrisko } 937265555Sambrisko // add complete rows in the middle of the transfer 938265555Sambrisko if (numRows > 2) 939265555Sambrisko regSize += (numRows-2) << raid->stripeShift; 940265555Sambrisko 941265555Sambrisko // if IO ends within first strip of last row 942265555Sambrisko if (endStrip == get_strip_from_row(sc, ld, endRow, map)) 943265555Sambrisko regSize += ref_in_end_stripe+1; 944265555Sambrisko else 945265555Sambrisko regSize += stripSize; 946265555Sambrisko } 947265555Sambrisko pRAID_Context->timeoutValue = map->raidMap.fpPdIoTimeoutSec; 948265555Sambrisko if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) 949265555Sambrisko pRAID_Context->regLockFlags = (isRead)? raid->regTypeReqOnRead : raid->regTypeReqOnWrite; 950265555Sambrisko else 951265555Sambrisko pRAID_Context->regLockFlags = (isRead)? REGION_TYPE_SHARED_READ : raid->regTypeReqOnWrite; 952265555Sambrisko pRAID_Context->VirtualDiskTgtId = raid->targetId; 953265555Sambrisko pRAID_Context->regLockRowLBA = regStart; 954265555Sambrisko pRAID_Context->regLockLength = regSize; 955265555Sambrisko pRAID_Context->configSeqNum = raid->seqNum; 956265555Sambrisko 957265555Sambrisko /* 958265555Sambrisko * Get Phy Params only if FP capable, or else leave it to MR firmware 959265555Sambrisko * to do the calculation. 960265555Sambrisko */ 961265555Sambrisko if (io_info->fpOkForIo) { 962265555Sambrisko retval = io_info->IoforUnevenSpan ? 963265555Sambrisko mr_spanset_get_phy_params(sc, ld, 964265555Sambrisko start_strip, ref_in_start_stripe, io_info, 965265555Sambrisko pRAID_Context, map) : 966265555Sambrisko MR_GetPhyParams(sc, ld, start_strip, 967265555Sambrisko ref_in_start_stripe, io_info, pRAID_Context, map); 968265555Sambrisko /* If IO on an invalid Pd, then FP is not possible */ 969265555Sambrisko if (io_info->devHandle == MR_PD_INVALID) 970265555Sambrisko io_info->fpOkForIo = FALSE; 971265555Sambrisko return retval; 972265555Sambrisko } 973265555Sambrisko else if (isRead) { 974265555Sambrisko for (stripIdx=0; stripIdx<num_strips; stripIdx++) { 975265555Sambrisko retval = io_info->IoforUnevenSpan ? 976265555Sambrisko mr_spanset_get_phy_params(sc, ld, 977265555Sambrisko start_strip + stripIdx, 978265555Sambrisko ref_in_start_stripe, io_info, 979265555Sambrisko pRAID_Context, map) : 980265555Sambrisko MR_GetPhyParams(sc, ld, 981265555Sambrisko start_strip + stripIdx, ref_in_start_stripe, 982265555Sambrisko io_info, pRAID_Context, map); 983265555Sambrisko if (!retval) 984265555Sambrisko return TRUE; 985265555Sambrisko } 986265555Sambrisko } 987265555Sambrisko#if SPAN_DEBUG 988265555Sambrisko // Just for testing what arm we get for strip. 989265555Sambrisko get_arm_from_strip(sc, ld, start_strip, map); 990265555Sambrisko#endif 991265555Sambrisko return TRUE; 992265555Sambrisko} 993265555Sambrisko 994265555Sambrisko/* 995265555Sambrisko****************************************************************************** 996265555Sambrisko* 997265555Sambrisko* This routine pepare spanset info from Valid Raid map and store it into 998265555Sambrisko* local copy of ldSpanInfo per instance data structure. 999265555Sambrisko* 1000265555Sambrisko* Inputs : 1001265555Sambrisko* map - LD map 1002265555Sambrisko* ldSpanInfo - ldSpanInfo per HBA instance 1003265555Sambrisko* 1004265555Sambrisko*/ 1005272735Skadesaivoid mr_update_span_set(MR_DRV_RAID_MAP_ALL *map, PLD_SPAN_INFO ldSpanInfo) 1006265555Sambrisko{ 1007265555Sambrisko u_int8_t span,count; 1008265555Sambrisko u_int32_t element,span_row_width; 1009265555Sambrisko u_int64_t span_row; 1010265555Sambrisko MR_LD_RAID *raid; 1011265555Sambrisko LD_SPAN_SET *span_set, *span_set_prev; 1012265555Sambrisko MR_QUAD_ELEMENT *quad; 1013265555Sambrisko int ldCount; 1014265555Sambrisko u_int16_t ld; 1015272735Skadesai 1016265555Sambrisko for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) 1017265555Sambrisko { 1018265555Sambrisko ld = MR_TargetIdToLdGet(ldCount, map); 1019272735Skadesai printf ("ld = %d\n\n", ld); 1020265555Sambrisko if (ld >= MAX_LOGICAL_DRIVES) 1021265555Sambrisko continue; 1022265555Sambrisko raid = MR_LdRaidGet(ld, map); 1023265555Sambrisko for (element=0; element < MAX_QUAD_DEPTH; element++) { 1024265555Sambrisko for (span=0; span < raid->spanDepth; span++) { 1025265555Sambrisko if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 1026265555Sambrisko block_span_info.noElements < element+1) 1027265555Sambrisko continue; 1028265555Sambrisko // TO-DO 1029265555Sambrisko span_set = &(ldSpanInfo[ld].span_set[element]); 1030265555Sambrisko quad = &map->raidMap.ldSpanMap[ld]. 1031265555Sambrisko spanBlock[span].block_span_info. 1032265555Sambrisko quad[element]; 1033265555Sambrisko 1034265555Sambrisko span_set->diff = quad->diff; 1035265555Sambrisko 1036265555Sambrisko for (count=0,span_row_width=0; 1037265555Sambrisko count<raid->spanDepth; count++) { 1038265555Sambrisko if (map->raidMap.ldSpanMap[ld]. 1039265555Sambrisko spanBlock[count]. 1040265555Sambrisko block_span_info. 1041265555Sambrisko noElements >=element+1) { 1042265555Sambrisko span_set->strip_offset[count] = 1043265555Sambrisko span_row_width; 1044265555Sambrisko span_row_width += 1045265555Sambrisko MR_LdSpanPtrGet 1046265555Sambrisko (ld, count, map)->spanRowDataSize; 1047265555Sambrisko#if SPAN_DEBUG 1048265555Sambrisko printf("LSI Debug span %x rowDataSize %x\n", 1049265555Sambrisko count, MR_LdSpanPtrGet 1050265555Sambrisko (ld, count, map)->spanRowDataSize); 1051265555Sambrisko#endif 1052265555Sambrisko } 1053265555Sambrisko } 1054265555Sambrisko 1055265555Sambrisko span_set->span_row_data_width = span_row_width; 1056265555Sambrisko span_row = mega_div64_32(((quad->logEnd - 1057265555Sambrisko quad->logStart) + quad->diff), quad->diff); 1058265555Sambrisko 1059265555Sambrisko if (element == 0) { 1060265555Sambrisko span_set->log_start_lba = 0; 1061265555Sambrisko span_set->log_end_lba = 1062265555Sambrisko ((span_row << raid->stripeShift) * span_row_width) - 1; 1063265555Sambrisko 1064265555Sambrisko span_set->span_row_start = 0; 1065265555Sambrisko span_set->span_row_end = span_row - 1; 1066265555Sambrisko 1067265555Sambrisko span_set->data_strip_start = 0; 1068265555Sambrisko span_set->data_strip_end = 1069265555Sambrisko (span_row * span_row_width) - 1; 1070265555Sambrisko 1071265555Sambrisko span_set->data_row_start = 0; 1072265555Sambrisko span_set->data_row_end = 1073265555Sambrisko (span_row * quad->diff) - 1; 1074265555Sambrisko } else { 1075265555Sambrisko span_set_prev = &(ldSpanInfo[ld]. 1076265555Sambrisko span_set[element - 1]); 1077265555Sambrisko span_set->log_start_lba = 1078265555Sambrisko span_set_prev->log_end_lba + 1; 1079265555Sambrisko span_set->log_end_lba = 1080265555Sambrisko span_set->log_start_lba + 1081265555Sambrisko ((span_row << raid->stripeShift) * span_row_width) - 1; 1082265555Sambrisko 1083265555Sambrisko span_set->span_row_start = 1084265555Sambrisko span_set_prev->span_row_end + 1; 1085265555Sambrisko span_set->span_row_end = 1086265555Sambrisko span_set->span_row_start + span_row - 1; 1087265555Sambrisko 1088265555Sambrisko span_set->data_strip_start = 1089265555Sambrisko span_set_prev->data_strip_end + 1; 1090265555Sambrisko span_set->data_strip_end = 1091265555Sambrisko span_set->data_strip_start + 1092265555Sambrisko (span_row * span_row_width) - 1; 1093265555Sambrisko 1094265555Sambrisko span_set->data_row_start = 1095265555Sambrisko span_set_prev->data_row_end + 1; 1096265555Sambrisko span_set->data_row_end = 1097265555Sambrisko span_set->data_row_start + 1098265555Sambrisko (span_row * quad->diff) - 1; 1099265555Sambrisko } 1100265555Sambrisko break; 1101265555Sambrisko } 1102265555Sambrisko if (span == raid->spanDepth) break; // no quads remain 1103265555Sambrisko } 1104265555Sambrisko } 1105265555Sambrisko#if SPAN_DEBUG 1106265555Sambrisko getSpanInfo(map, ldSpanInfo); //to get span set info 1107265555Sambrisko#endif 1108265555Sambrisko} 1109265555Sambrisko 1110265555Sambrisko/** 1111265555Sambrisko * mrsas_update_load_balance_params: Update load balance parmas 1112265555Sambrisko * Inputs: map pointer 1113265555Sambrisko * Load balance info 1114265555Sambrisko * io_info pointer 1115265555Sambrisko * 1116265555Sambrisko * This function updates the load balance parameters for the LD config 1117265555Sambrisko * of a two drive optimal RAID-1. 1118265555Sambrisko */ 1119272735Skadesaivoid mrsas_update_load_balance_params(MR_DRV_RAID_MAP_ALL *map, 1120265555Sambrisko PLD_LOAD_BALANCE_INFO lbInfo) 1121265555Sambrisko{ 1122265555Sambrisko int ldCount; 1123265555Sambrisko u_int16_t ld; 1124265555Sambrisko u_int32_t pd, arRef; 1125265555Sambrisko MR_LD_RAID *raid; 1126265555Sambrisko 1127265555Sambrisko for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) 1128265555Sambrisko { 1129265555Sambrisko ld = MR_TargetIdToLdGet(ldCount, map); 1130265555Sambrisko if (ld >= MAX_LOGICAL_DRIVES) { 1131265555Sambrisko lbInfo[ldCount].loadBalanceFlag = 0; 1132265555Sambrisko continue; 1133265555Sambrisko } 1134265555Sambrisko 1135265555Sambrisko raid = MR_LdRaidGet(ld, map); 1136265555Sambrisko 1137265555Sambrisko /* Two drive Optimal RAID 1 */ 1138265555Sambrisko if ((raid->level == 1) && (raid->rowSize == 2) && 1139265555Sambrisko (raid->spanDepth == 1) 1140265555Sambrisko && raid->ldState == MR_LD_STATE_OPTIMAL) { 1141265555Sambrisko lbInfo[ldCount].loadBalanceFlag = 1; 1142265555Sambrisko 1143265555Sambrisko /* Get the array on which this span is present */ 1144265555Sambrisko arRef = MR_LdSpanArrayGet(ld, 0, map); 1145265555Sambrisko 1146265555Sambrisko /* Get the PD */ 1147265555Sambrisko pd = MR_ArPdGet(arRef, 0, map); 1148265555Sambrisko /* Get dev handle from PD */ 1149265555Sambrisko lbInfo[ldCount].raid1DevHandle[0] = MR_PdDevHandleGet(pd, map); 1150265555Sambrisko pd = MR_ArPdGet(arRef, 1, map); 1151265555Sambrisko lbInfo[ldCount].raid1DevHandle[1] = MR_PdDevHandleGet(pd, map); 1152265555Sambrisko } 1153265555Sambrisko else 1154265555Sambrisko lbInfo[ldCount].loadBalanceFlag = 0; 1155265555Sambrisko } 1156265555Sambrisko} 1157265555Sambrisko 1158265555Sambrisko 1159265555Sambrisko/** 1160265555Sambrisko * mrsas_set_pd_lba: Sets PD LBA 1161265555Sambrisko * input: io_request pointer 1162265555Sambrisko * CDB length 1163265555Sambrisko * io_info pointer 1164265555Sambrisko * Pointer to CCB 1165265555Sambrisko * Local RAID map pointer 1166265555Sambrisko * Start block of IO 1167265555Sambrisko * Block Size 1168265555Sambrisko * 1169265555Sambrisko * Used to set the PD logical block address in CDB for FP IOs. 1170265555Sambrisko */ 1171265555Sambriskovoid mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST *io_request, u_int8_t cdb_len, 1172265555Sambrisko struct IO_REQUEST_INFO *io_info, union ccb *ccb, 1173272735Skadesai MR_DRV_RAID_MAP_ALL *local_map_ptr, u_int32_t ref_tag, 1174265555Sambrisko u_int32_t ld_block_size) 1175265555Sambrisko{ 1176265555Sambrisko MR_LD_RAID *raid; 1177265555Sambrisko u_int32_t ld; 1178265555Sambrisko u_int64_t start_blk = io_info->pdBlock; 1179265555Sambrisko u_int8_t *cdb = io_request->CDB.CDB32; 1180265555Sambrisko u_int32_t num_blocks = io_info->numBlocks; 1181265555Sambrisko u_int8_t opcode = 0, flagvals = 0, groupnum = 0, control = 0; 1182265555Sambrisko struct ccb_hdr *ccb_h = &(ccb->ccb_h); 1183265555Sambrisko 1184265555Sambrisko /* Check if T10 PI (DIF) is enabled for this LD */ 1185265555Sambrisko ld = MR_TargetIdToLdGet(io_info->ldTgtId, local_map_ptr); 1186265555Sambrisko raid = MR_LdRaidGet(ld, local_map_ptr); 1187265555Sambrisko if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER) { 1188265555Sambrisko memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1189265555Sambrisko cdb[0] = MRSAS_SCSI_VARIABLE_LENGTH_CMD; 1190265555Sambrisko cdb[7] = MRSAS_SCSI_ADDL_CDB_LEN; 1191265555Sambrisko 1192265555Sambrisko if (ccb_h->flags == CAM_DIR_OUT) 1193265555Sambrisko cdb[9] = MRSAS_SCSI_SERVICE_ACTION_READ32; 1194265555Sambrisko else 1195265555Sambrisko cdb[9] = MRSAS_SCSI_SERVICE_ACTION_WRITE32; 1196265555Sambrisko cdb[10] = MRSAS_RD_WR_PROTECT_CHECK_ALL; 1197265555Sambrisko 1198265555Sambrisko /* LBA */ 1199265555Sambrisko cdb[12] = (u_int8_t)((start_blk >> 56) & 0xff); 1200265555Sambrisko cdb[13] = (u_int8_t)((start_blk >> 48) & 0xff); 1201265555Sambrisko cdb[14] = (u_int8_t)((start_blk >> 40) & 0xff); 1202265555Sambrisko cdb[15] = (u_int8_t)((start_blk >> 32) & 0xff); 1203265555Sambrisko cdb[16] = (u_int8_t)((start_blk >> 24) & 0xff); 1204265555Sambrisko cdb[17] = (u_int8_t)((start_blk >> 16) & 0xff); 1205265555Sambrisko cdb[18] = (u_int8_t)((start_blk >> 8) & 0xff); 1206265555Sambrisko cdb[19] = (u_int8_t)(start_blk & 0xff); 1207265555Sambrisko 1208265555Sambrisko /* Logical block reference tag */ 1209265555Sambrisko io_request->CDB.EEDP32.PrimaryReferenceTag = swap32(ref_tag); 1210265555Sambrisko io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0xffff; 1211265555Sambrisko io_request->IoFlags = 32; /* Specify 32-byte cdb */ 1212265555Sambrisko 1213265555Sambrisko /* Transfer length */ 1214265555Sambrisko cdb[28] = (u_int8_t)((num_blocks >> 24) & 0xff); 1215265555Sambrisko cdb[29] = (u_int8_t)((num_blocks >> 16) & 0xff); 1216265555Sambrisko cdb[30] = (u_int8_t)((num_blocks >> 8) & 0xff); 1217265555Sambrisko cdb[31] = (u_int8_t)(num_blocks & 0xff); 1218265555Sambrisko 1219265555Sambrisko /* set SCSI IO EEDP Flags */ 1220265555Sambrisko if (ccb_h->flags == CAM_DIR_OUT) { 1221265555Sambrisko io_request->EEDPFlags = 1222265555Sambrisko MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | 1223265555Sambrisko MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | 1224265555Sambrisko MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP | 1225265555Sambrisko MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG | 1226265555Sambrisko MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; 1227265555Sambrisko } 1228265555Sambrisko else { 1229265555Sambrisko io_request->EEDPFlags = 1230265555Sambrisko MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | 1231265555Sambrisko MPI2_SCSIIO_EEDPFLAGS_INSERT_OP; 1232265555Sambrisko } 1233265555Sambrisko io_request->Control |= (0x4 << 26); 1234265555Sambrisko io_request->EEDPBlockSize = ld_block_size; 1235265555Sambrisko } 1236265555Sambrisko else { 1237265555Sambrisko /* Some drives don't support 16/12 byte CDB's, convert to 10 */ 1238265555Sambrisko if (((cdb_len == 12) || (cdb_len == 16)) && 1239265555Sambrisko (start_blk <= 0xffffffff)) { 1240265555Sambrisko if (cdb_len == 16) { 1241265555Sambrisko opcode = cdb[0] == READ_16 ? READ_10 : WRITE_10; 1242265555Sambrisko flagvals = cdb[1]; 1243265555Sambrisko groupnum = cdb[14]; 1244265555Sambrisko control = cdb[15]; 1245265555Sambrisko } 1246265555Sambrisko else { 1247265555Sambrisko opcode = cdb[0] == READ_12 ? READ_10 : WRITE_10; 1248265555Sambrisko flagvals = cdb[1]; 1249265555Sambrisko groupnum = cdb[10]; 1250265555Sambrisko control = cdb[11]; 1251265555Sambrisko } 1252265555Sambrisko 1253265555Sambrisko memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1254265555Sambrisko 1255265555Sambrisko cdb[0] = opcode; 1256265555Sambrisko cdb[1] = flagvals; 1257265555Sambrisko cdb[6] = groupnum; 1258265555Sambrisko cdb[9] = control; 1259265555Sambrisko 1260265555Sambrisko /* Transfer length */ 1261265555Sambrisko cdb[8] = (u_int8_t)(num_blocks & 0xff); 1262265555Sambrisko cdb[7] = (u_int8_t)((num_blocks >> 8) & 0xff); 1263265555Sambrisko 1264265555Sambrisko io_request->IoFlags = 10; /* Specify 10-byte cdb */ 1265265555Sambrisko cdb_len = 10; 1266265555Sambrisko } else if ((cdb_len < 16) && (start_blk > 0xffffffff)) { 1267265555Sambrisko /* Convert to 16 byte CDB for large LBA's */ 1268265555Sambrisko switch (cdb_len) { 1269265555Sambrisko case 6: 1270265555Sambrisko opcode = cdb[0] == READ_6 ? READ_16 : WRITE_16; 1271265555Sambrisko control = cdb[5]; 1272265555Sambrisko break; 1273265555Sambrisko case 10: 1274265555Sambrisko opcode = cdb[0] == READ_10 ? READ_16 : WRITE_16; 1275265555Sambrisko flagvals = cdb[1]; 1276265555Sambrisko groupnum = cdb[6]; 1277265555Sambrisko control = cdb[9]; 1278265555Sambrisko break; 1279265555Sambrisko case 12: 1280265555Sambrisko opcode = cdb[0] == READ_12 ? READ_16 : WRITE_16; 1281265555Sambrisko flagvals = cdb[1]; 1282265555Sambrisko groupnum = cdb[10]; 1283265555Sambrisko control = cdb[11]; 1284265555Sambrisko break; 1285265555Sambrisko } 1286265555Sambrisko 1287265555Sambrisko memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1288265555Sambrisko 1289265555Sambrisko cdb[0] = opcode; 1290265555Sambrisko cdb[1] = flagvals; 1291265555Sambrisko cdb[14] = groupnum; 1292265555Sambrisko cdb[15] = control; 1293265555Sambrisko 1294265555Sambrisko /* Transfer length */ 1295265555Sambrisko cdb[13] = (u_int8_t)(num_blocks & 0xff); 1296265555Sambrisko cdb[12] = (u_int8_t)((num_blocks >> 8) & 0xff); 1297265555Sambrisko cdb[11] = (u_int8_t)((num_blocks >> 16) & 0xff); 1298265555Sambrisko cdb[10] = (u_int8_t)((num_blocks >> 24) & 0xff); 1299265555Sambrisko 1300265555Sambrisko io_request->IoFlags = 16; /* Specify 16-byte cdb */ 1301265555Sambrisko cdb_len = 16; 1302265555Sambrisko } else if ((cdb_len == 6) && (start_blk > 0x1fffff)) { 1303265555Sambrisko /* convert to 10 byte CDB */ 1304265555Sambrisko opcode = cdb[0] == READ_6 ? READ_10 : WRITE_10; 1305265555Sambrisko control = cdb[5]; 1306265555Sambrisko 1307267838Sdelphij memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1308265555Sambrisko cdb[0] = opcode; 1309265555Sambrisko cdb[9] = control; 1310265555Sambrisko 1311265555Sambrisko /* Set transfer length */ 1312265555Sambrisko cdb[8] = (u_int8_t)(num_blocks & 0xff); 1313265555Sambrisko cdb[7] = (u_int8_t)((num_blocks >> 8) & 0xff); 1314265555Sambrisko 1315265555Sambrisko /* Specify 10-byte cdb */ 1316265555Sambrisko cdb_len = 10; 1317265555Sambrisko } 1318265555Sambrisko 1319265555Sambrisko /* Fall through normal case, just load LBA here */ 1320265555Sambrisko switch (cdb_len) 1321265555Sambrisko { 1322265555Sambrisko case 6: 1323265555Sambrisko { 1324265555Sambrisko u_int8_t val = cdb[1] & 0xE0; 1325265555Sambrisko cdb[3] = (u_int8_t)(start_blk & 0xff); 1326265555Sambrisko cdb[2] = (u_int8_t)((start_blk >> 8) & 0xff); 1327265555Sambrisko cdb[1] = val | ((u_int8_t)(start_blk >> 16) & 0x1f); 1328265555Sambrisko break; 1329265555Sambrisko } 1330265555Sambrisko case 10: 1331265555Sambrisko cdb[5] = (u_int8_t)(start_blk & 0xff); 1332265555Sambrisko cdb[4] = (u_int8_t)((start_blk >> 8) & 0xff); 1333265555Sambrisko cdb[3] = (u_int8_t)((start_blk >> 16) & 0xff); 1334265555Sambrisko cdb[2] = (u_int8_t)((start_blk >> 24) & 0xff); 1335265555Sambrisko break; 1336265555Sambrisko case 12: 1337265555Sambrisko cdb[5] = (u_int8_t)(start_blk & 0xff); 1338265555Sambrisko cdb[4] = (u_int8_t)((start_blk >> 8) & 0xff); 1339265555Sambrisko cdb[3] = (u_int8_t)((start_blk >> 16) & 0xff); 1340265555Sambrisko cdb[2] = (u_int8_t)((start_blk >> 24) & 0xff); 1341265555Sambrisko break; 1342265555Sambrisko case 16: 1343265555Sambrisko cdb[9] = (u_int8_t)(start_blk & 0xff); 1344265555Sambrisko cdb[8] = (u_int8_t)((start_blk >> 8) & 0xff); 1345265555Sambrisko cdb[7] = (u_int8_t)((start_blk >> 16) & 0xff); 1346265555Sambrisko cdb[6] = (u_int8_t)((start_blk >> 24) & 0xff); 1347265555Sambrisko cdb[5] = (u_int8_t)((start_blk >> 32) & 0xff); 1348265555Sambrisko cdb[4] = (u_int8_t)((start_blk >> 40) & 0xff); 1349265555Sambrisko cdb[3] = (u_int8_t)((start_blk >> 48) & 0xff); 1350265555Sambrisko cdb[2] = (u_int8_t)((start_blk >> 56) & 0xff); 1351265555Sambrisko break; 1352265555Sambrisko } 1353265555Sambrisko } 1354265555Sambrisko} 1355265555Sambrisko 1356265555Sambrisko/** 1357265555Sambrisko * mrsas_get_best_arm Determine the best spindle arm 1358265555Sambrisko * Inputs: Load balance info 1359265555Sambrisko * 1360265555Sambrisko * This function determines and returns the best arm by looking at the 1361265555Sambrisko * parameters of the last PD access. 1362265555Sambrisko */ 1363265555Sambriskou_int8_t mrsas_get_best_arm(PLD_LOAD_BALANCE_INFO lbInfo, u_int8_t arm, 1364265555Sambrisko u_int64_t block, u_int32_t count) 1365265555Sambrisko{ 1366265555Sambrisko u_int16_t pend0, pend1; 1367265555Sambrisko u_int64_t diff0, diff1; 1368265555Sambrisko u_int8_t bestArm; 1369265555Sambrisko 1370265555Sambrisko /* get the pending cmds for the data and mirror arms */ 1371265555Sambrisko pend0 = atomic_read(&lbInfo->scsi_pending_cmds[0]); 1372265555Sambrisko pend1 = atomic_read(&lbInfo->scsi_pending_cmds[1]); 1373265555Sambrisko 1374265555Sambrisko /* Determine the disk whose head is nearer to the req. block */ 1375265555Sambrisko diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[0]); 1376265555Sambrisko diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[1]); 1377265555Sambrisko bestArm = (diff0 <= diff1 ? 0 : 1); 1378265555Sambrisko 1379265555Sambrisko if ((bestArm == arm && pend0 > pend1 + 16) || (bestArm != arm && pend1 > pend0 + 16)) 1380265555Sambrisko bestArm ^= 1; 1381265555Sambrisko 1382265555Sambrisko /* Update the last accessed block on the correct pd */ 1383265555Sambrisko lbInfo->last_accessed_block[bestArm] = block + count - 1; 1384265555Sambrisko 1385265555Sambrisko return bestArm; 1386265555Sambrisko} 1387265555Sambrisko 1388265555Sambrisko/** 1389265555Sambrisko * mrsas_get_updated_dev_handle Get the update dev handle 1390265555Sambrisko * Inputs: Load balance info 1391265555Sambrisko * io_info pointer 1392265555Sambrisko * 1393265555Sambrisko * This function determines and returns the updated dev handle. 1394265555Sambrisko */ 1395265555Sambriskou_int16_t mrsas_get_updated_dev_handle(PLD_LOAD_BALANCE_INFO lbInfo, 1396265555Sambrisko struct IO_REQUEST_INFO *io_info) 1397265555Sambrisko{ 1398265555Sambrisko u_int8_t arm, old_arm; 1399265555Sambrisko u_int16_t devHandle; 1400265555Sambrisko 1401265555Sambrisko old_arm = lbInfo->raid1DevHandle[0] == io_info->devHandle ? 0 : 1; 1402265555Sambrisko 1403265555Sambrisko /* get best new arm */ 1404265555Sambrisko arm = mrsas_get_best_arm(lbInfo, old_arm, io_info->ldStartBlock, io_info->numBlocks); 1405265555Sambrisko devHandle = lbInfo->raid1DevHandle[arm]; 1406265555Sambrisko atomic_inc(&lbInfo->scsi_pending_cmds[arm]); 1407265555Sambrisko 1408265555Sambrisko return devHandle; 1409265555Sambrisko} 1410265555Sambrisko 1411265555Sambrisko/** 1412265555Sambrisko * MR_GetPhyParams Calculates arm, span, and block 1413265555Sambrisko * Inputs: Adapter instance soft state 1414265555Sambrisko * Logical drive number (LD) 1415265555Sambrisko * Stripe number (stripRow) 1416265555Sambrisko * Reference in stripe (stripRef) 1417265555Sambrisko * Outputs: Span number 1418265555Sambrisko * Absolute Block number in the physical disk 1419265555Sambrisko * 1420265555Sambrisko * This routine calculates the arm, span and block for the specified stripe 1421265555Sambrisko * and reference in stripe. 1422265555Sambrisko */ 1423265555Sambriskou_int8_t MR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld, 1424265555Sambrisko u_int64_t stripRow, 1425265555Sambrisko u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 1426272735Skadesai RAID_CONTEXT *pRAID_Context, MR_DRV_RAID_MAP_ALL *map) 1427265555Sambrisko{ 1428265555Sambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 1429265555Sambrisko u_int32_t pd, arRef; 1430265555Sambrisko u_int8_t physArm, span; 1431265555Sambrisko u_int64_t row; 1432265555Sambrisko u_int8_t retval = TRUE; 1433265555Sambrisko int error_code = 0; 1434265555Sambrisko u_int64_t *pdBlock = &io_info->pdBlock; 1435265555Sambrisko u_int16_t *pDevHandle = &io_info->devHandle; 1436265555Sambrisko u_int32_t rowMod, armQ, arm, logArm; 1437265555Sambrisko u_int8_t do_invader = 0; 1438265555Sambrisko 1439265555Sambrisko if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) 1440265555Sambrisko do_invader = 1; 1441265555Sambrisko 1442265555Sambrisko row = mega_div64_32(stripRow, raid->rowDataSize); 1443265555Sambrisko 1444265555Sambrisko if (raid->level == 6) { 1445265555Sambrisko logArm = mega_mod64(stripRow, raid->rowDataSize); // logical arm within row 1446265555Sambrisko if (raid->rowSize == 0) 1447265555Sambrisko return FALSE; 1448265555Sambrisko rowMod = mega_mod64(row, raid->rowSize); // get logical row mod 1449265555Sambrisko armQ = raid->rowSize-1-rowMod; // index of Q drive 1450265555Sambrisko arm = armQ+1+logArm; // data always logically follows Q 1451265555Sambrisko if (arm >= raid->rowSize) // handle wrap condition 1452265555Sambrisko arm -= raid->rowSize; 1453265555Sambrisko physArm = (u_int8_t)arm; 1454265555Sambrisko } 1455265555Sambrisko else { 1456265555Sambrisko if (raid->modFactor == 0) 1457265555Sambrisko return FALSE; 1458265555Sambrisko physArm = MR_LdDataArmGet(ld, mega_mod64(stripRow, raid->modFactor), map); 1459265555Sambrisko } 1460265555Sambrisko 1461265555Sambrisko if (raid->spanDepth == 1) { 1462265555Sambrisko span = 0; 1463265555Sambrisko *pdBlock = row << raid->stripeShift; 1464265555Sambrisko } 1465265555Sambrisko else { 1466265555Sambrisko span = (u_int8_t)MR_GetSpanBlock(ld, row, pdBlock, map, &error_code); 1467265555Sambrisko if (error_code == 1) 1468265555Sambrisko return FALSE; 1469265555Sambrisko } 1470265555Sambrisko 1471265555Sambrisko /* Get the array on which this span is present */ 1472265555Sambrisko arRef = MR_LdSpanArrayGet(ld, span, map); 1473265555Sambrisko 1474265555Sambrisko pd = MR_ArPdGet(arRef, physArm, map); // Get the Pd. 1475265555Sambrisko 1476265555Sambrisko if (pd != MR_PD_INVALID) 1477265555Sambrisko *pDevHandle = MR_PdDevHandleGet(pd, map); // Get dev handle from Pd. 1478265555Sambrisko else { 1479265555Sambrisko *pDevHandle = MR_PD_INVALID; // set dev handle as invalid. 1480265555Sambrisko if ((raid->level >= 5) && ((!do_invader) || (do_invader && 1481265555Sambrisko raid->regTypeReqOnRead != REGION_TYPE_UNUSED))) 1482265555Sambrisko pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; 1483265555Sambrisko else if (raid->level == 1) { 1484265555Sambrisko pd = MR_ArPdGet(arRef, physArm + 1, map); // Get Alternate Pd. 1485265555Sambrisko if (pd != MR_PD_INVALID) 1486265555Sambrisko *pDevHandle = MR_PdDevHandleGet(pd, map);//Get dev handle from Pd. 1487265555Sambrisko } 1488265555Sambrisko } 1489265555Sambrisko 1490265555Sambrisko *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk; 1491265555Sambrisko pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; 1492265555Sambrisko return retval; 1493265555Sambrisko} 1494265555Sambrisko 1495265555Sambrisko/** 1496265555Sambrisko * MR_GetSpanBlock Calculates span block 1497265555Sambrisko * Inputs: LD 1498265555Sambrisko * row 1499265555Sambrisko * PD span block 1500265555Sambrisko * RAID map pointer 1501265555Sambrisko * Outputs: Span number 1502265555Sambrisko * Error code 1503265555Sambrisko * 1504265555Sambrisko * This routine calculates the span from the span block info. 1505265555Sambrisko */ 1506265555Sambriskou_int32_t MR_GetSpanBlock(u_int32_t ld, u_int64_t row, u_int64_t *span_blk, 1507272735Skadesai MR_DRV_RAID_MAP_ALL *map, int *div_error) 1508265555Sambrisko{ 1509265555Sambrisko MR_SPAN_BLOCK_INFO *pSpanBlock = MR_LdSpanInfoGet(ld, map); 1510265555Sambrisko MR_QUAD_ELEMENT *quad; 1511265555Sambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 1512265555Sambrisko u_int32_t span, j; 1513265555Sambrisko u_int64_t blk, debugBlk; 1514265555Sambrisko 1515265555Sambrisko for (span=0; span < raid->spanDepth; span++, pSpanBlock++) { 1516265555Sambrisko for (j=0; j < pSpanBlock->block_span_info.noElements; j++) { 1517265555Sambrisko quad = &pSpanBlock->block_span_info.quad[j]; 1518265555Sambrisko if (quad->diff == 0) { 1519265555Sambrisko *div_error = 1; 1520265555Sambrisko return span; 1521265555Sambrisko } 1522265555Sambrisko if (quad->logStart <= row && row <= quad->logEnd && 1523265555Sambrisko (mega_mod64(row-quad->logStart, quad->diff)) == 0) { 1524265555Sambrisko if (span_blk != NULL) { 1525265555Sambrisko blk = mega_div64_32((row-quad->logStart), quad->diff); 1526265555Sambrisko debugBlk = blk; 1527265555Sambrisko blk = (blk + quad->offsetInSpan) << raid->stripeShift; 1528265555Sambrisko *span_blk = blk; 1529265555Sambrisko } 1530265555Sambrisko return span; 1531265555Sambrisko } 1532265555Sambrisko } 1533265555Sambrisko } 1534265555Sambrisko return span; 1535265555Sambrisko} 1536265555Sambrisko 1537