mrsas_fp.c revision 272744
1265555Sambrisko/* 2272744Skadesai * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy 3265555Sambrisko * Support: freebsdraid@lsi.com 4265555Sambrisko * 5265555Sambrisko * Redistribution and use in source and binary forms, with or without 6272744Skadesai * modification, are permitted provided that the following conditions are 7272744Skadesai * met: 8265555Sambrisko * 9272744Skadesai * 1. Redistributions of source code must retain the above copyright notice, 10272744Skadesai * this list of conditions and the following disclaimer. 2. Redistributions 11272744Skadesai * in binary form must reproduce the above copyright notice, this list of 12272744Skadesai * conditions and the following disclaimer in the documentation and/or other 13272744Skadesai * materials provided with the distribution. 3. Neither the name of the 14272744Skadesai * <ORGANIZATION> nor the names of its contributors may be used to endorse or 15272744Skadesai * promote products derived from this software without specific prior written 16272744Skadesai * permission. 17265555Sambrisko * 18272744Skadesai * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19272744Skadesai * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20272744Skadesai * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21272744Skadesai * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22272744Skadesai * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23272744Skadesai * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24272744Skadesai * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25272744Skadesai * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26272744Skadesai * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27272744Skadesai * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28265555Sambrisko * POSSIBILITY OF SUCH DAMAGE. 29265555Sambrisko * 30272744Skadesai * The views and conclusions contained in the software and documentation are 31272744Skadesai * those of the authors and should not be interpreted as representing 32265555Sambrisko * official policies,either expressed or implied, of the FreeBSD Project. 33265555Sambrisko * 34272744Skadesai * Send feedback to: <megaraidfbsd@lsi.com> Mail to: LSI Corporation, 1621 35272744Skadesai * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD 36265555Sambrisko * 37265555Sambrisko */ 38265555Sambrisko 39265555Sambrisko#include <sys/cdefs.h> 40265555Sambrisko__FBSDID("$FreeBSD: head/sys/dev/mrsas/mrsas_fp.c 272744 2014-10-08 10:14:37Z kadesai $"); 41265555Sambrisko 42265555Sambrisko#include <dev/mrsas/mrsas.h> 43265555Sambrisko 44265555Sambrisko#include <cam/cam.h> 45265555Sambrisko#include <cam/cam_ccb.h> 46265555Sambrisko#include <cam/cam_sim.h> 47265555Sambrisko#include <cam/cam_xpt_sim.h> 48265555Sambrisko#include <cam/cam_debug.h> 49265555Sambrisko#include <cam/cam_periph.h> 50265555Sambrisko#include <cam/cam_xpt_periph.h> 51265555Sambrisko 52265555Sambrisko 53265555Sambrisko/* 54265555Sambrisko * Function prototypes 55265555Sambrisko */ 56265555Sambriskou_int8_t MR_ValidateMapInfo(struct mrsas_softc *sc); 57272744Skadesaiu_int8_t 58272744Skadesaimrsas_get_best_arm(PLD_LOAD_BALANCE_INFO lbInfo, u_int8_t arm, 59272744Skadesai u_int64_t block, u_int32_t count); 60272744Skadesaiu_int8_t 61272744SkadesaiMR_BuildRaidContext(struct mrsas_softc *sc, 62272744Skadesai struct IO_REQUEST_INFO *io_info, 63272744Skadesai RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map); 64272744Skadesaiu_int8_t 65272744SkadesaiMR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld, 66272744Skadesai u_int64_t stripRow, u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 67272744Skadesai RAID_CONTEXT * pRAID_Context, 68272744Skadesai MR_DRV_RAID_MAP_ALL * map); 69272744Skadesaiu_int16_t MR_TargetIdToLdGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map); 70272744Skadesaiu_int32_t MR_LdBlockSizeGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map); 71272744Skadesaiu_int16_t MR_GetLDTgtId(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map); 72272744Skadesaiu_int16_t 73272744Skadesaimrsas_get_updated_dev_handle(PLD_LOAD_BALANCE_INFO lbInfo, 74272744Skadesai struct IO_REQUEST_INFO *io_info); 75265555Sambriskou_int32_t mega_mod64(u_int64_t dividend, u_int32_t divisor); 76272744Skadesaiu_int32_t 77272744SkadesaiMR_GetSpanBlock(u_int32_t ld, u_int64_t row, u_int64_t *span_blk, 78272744Skadesai MR_DRV_RAID_MAP_ALL * map, int *div_error); 79265555Sambriskou_int64_t mega_div64_32(u_int64_t dividend, u_int32_t divisor); 80272744Skadesaivoid 81272744Skadesaimrsas_update_load_balance_params(MR_DRV_RAID_MAP_ALL * map, 82272744Skadesai PLD_LOAD_BALANCE_INFO lbInfo); 83272744Skadesaivoid 84272744Skadesaimrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request, 85272744Skadesai u_int8_t cdb_len, struct IO_REQUEST_INFO *io_info, union ccb *ccb, 86272744Skadesai MR_DRV_RAID_MAP_ALL * local_map_ptr, u_int32_t ref_tag, 87272744Skadesai u_int32_t ld_block_size); 88272744Skadesaistatic u_int16_t 89272744SkadesaiMR_LdSpanArrayGet(u_int32_t ld, u_int32_t span, 90272744Skadesai MR_DRV_RAID_MAP_ALL * map); 91272744Skadesaistatic u_int16_t MR_PdDevHandleGet(u_int32_t pd, MR_DRV_RAID_MAP_ALL * map); 92272744Skadesaistatic u_int16_t 93272744SkadesaiMR_ArPdGet(u_int32_t ar, u_int32_t arm, 94272744Skadesai MR_DRV_RAID_MAP_ALL * map); 95272744Skadesaistatic MR_LD_SPAN * 96272744SkadesaiMR_LdSpanPtrGet(u_int32_t ld, u_int32_t span, 97272744Skadesai MR_DRV_RAID_MAP_ALL * map); 98272744Skadesaistatic u_int8_t 99272744SkadesaiMR_LdDataArmGet(u_int32_t ld, u_int32_t armIdx, 100272744Skadesai MR_DRV_RAID_MAP_ALL * map); 101272744Skadesaistatic MR_SPAN_BLOCK_INFO * 102272744SkadesaiMR_LdSpanInfoGet(u_int32_t ld, 103272744Skadesai MR_DRV_RAID_MAP_ALL * map); 104272744SkadesaiMR_LD_RAID *MR_LdRaidGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map); 105272744Skadesaivoid MR_PopulateDrvRaidMap(struct mrsas_softc *sc); 106265555Sambrisko 107272735Skadesai 108265555Sambrisko/* 109272744Skadesai * Spanset related function prototypes Added for PRL11 configuration (Uneven 110272744Skadesai * span support) 111265555Sambrisko */ 112272744Skadesaivoid mr_update_span_set(MR_DRV_RAID_MAP_ALL * map, PLD_SPAN_INFO ldSpanInfo); 113272744Skadesaistatic u_int8_t 114272744Skadesaimr_spanset_get_phy_params(struct mrsas_softc *sc, u_int32_t ld, 115272744Skadesai u_int64_t stripRow, u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 116272744Skadesai RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map); 117272744Skadesaistatic u_int64_t 118272744Skadesaiget_row_from_strip(struct mrsas_softc *sc, u_int32_t ld, 119272744Skadesai u_int64_t strip, MR_DRV_RAID_MAP_ALL * map); 120272744Skadesaistatic u_int32_t 121272744Skadesaimr_spanset_get_span_block(struct mrsas_softc *sc, 122272744Skadesai u_int32_t ld, u_int64_t row, u_int64_t *span_blk, 123272744Skadesai MR_DRV_RAID_MAP_ALL * map, int *div_error); 124272744Skadesaistatic u_int8_t 125272744Skadesaiget_arm(struct mrsas_softc *sc, u_int32_t ld, u_int8_t span, 126272744Skadesai u_int64_t stripe, MR_DRV_RAID_MAP_ALL * map); 127265555Sambrisko 128265555Sambrisko 129265555Sambrisko/* 130272744Skadesai * Spanset related defines Added for PRL11 configuration(Uneven span support) 131265555Sambrisko */ 132272744Skadesai#define SPAN_ROW_SIZE(map, ld, index_) MR_LdSpanPtrGet(ld, index_, map)->spanRowSize 133272744Skadesai#define SPAN_ROW_DATA_SIZE(map_, ld, index_) \ 134272744Skadesai MR_LdSpanPtrGet(ld, index_, map)->spanRowDataSize 135272744Skadesai#define SPAN_INVALID 0xff 136272744Skadesai#define SPAN_DEBUG 0 137265555Sambrisko 138265555Sambrisko/* 139265555Sambrisko * Related Defines 140265555Sambrisko */ 141265555Sambrisko 142272744Skadesaitypedef u_int64_t REGION_KEY; 143272744Skadesaitypedef u_int32_t REGION_LEN; 144265555Sambrisko 145272744Skadesai#define MR_LD_STATE_OPTIMAL 3 146272744Skadesai#define FALSE 0 147272744Skadesai#define TRUE 1 148265555Sambrisko 149265555Sambrisko 150265555Sambrisko/* 151265555Sambrisko * Related Macros 152265555Sambrisko */ 153265555Sambrisko 154272744Skadesai#define ABS_DIFF(a,b) ( ((a) > (b)) ? ((a) - (b)) : ((b) - (a)) ) 155265555Sambrisko 156272744Skadesai#define swap32(x) \ 157265555Sambrisko ((unsigned int)( \ 158265555Sambrisko (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \ 159265555Sambrisko (((unsigned int)(x) & (unsigned int)0x0000ff00UL) << 8) | \ 160265555Sambrisko (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >> 8) | \ 161265555Sambrisko (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) )) 162265555Sambrisko 163265555Sambrisko 164265555Sambrisko/* 165272744Skadesai * In-line functions for mod and divide of 64-bit dividend and 32-bit 166272744Skadesai * divisor. Assumes a check for a divisor of zero is not possible. 167272744Skadesai * 168272744Skadesai * @param dividend: Dividend 169272744Skadesai * @param divisor: Divisor 170272744Skadesai * @return remainder 171265555Sambrisko */ 172265555Sambrisko 173272744Skadesai#define mega_mod64(dividend, divisor) ({ \ 174265555Sambriskoint remainder; \ 175265555Sambriskoremainder = ((u_int64_t) (dividend)) % (u_int32_t) (divisor); \ 176265555Sambriskoremainder;}) 177265555Sambrisko 178272744Skadesai#define mega_div64_32(dividend, divisor) ({ \ 179265555Sambriskoint quotient; \ 180265555Sambriskoquotient = ((u_int64_t) (dividend)) / (u_int32_t) (divisor); \ 181265555Sambriskoquotient;}) 182265555Sambrisko 183265555Sambrisko 184265555Sambrisko/* 185265555Sambrisko * Various RAID map access functions. These functions access the various 186272744Skadesai * parts of the RAID map and returns the appropriate parameters. 187265555Sambrisko */ 188265555Sambrisko 189272744SkadesaiMR_LD_RAID * 190272744SkadesaiMR_LdRaidGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map) 191265555Sambrisko{ 192272744Skadesai return (&map->raidMap.ldSpanMap[ld].ldRaid); 193265555Sambrisko} 194265555Sambrisko 195272744Skadesaiu_int16_t 196272744SkadesaiMR_GetLDTgtId(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map) 197265555Sambrisko{ 198272744Skadesai return (map->raidMap.ldSpanMap[ld].ldRaid.targetId); 199265555Sambrisko} 200265555Sambrisko 201272744Skadesaistatic u_int16_t 202272744SkadesaiMR_LdSpanArrayGet(u_int32_t ld, u_int32_t span, MR_DRV_RAID_MAP_ALL * map) 203265555Sambrisko{ 204272744Skadesai return map->raidMap.ldSpanMap[ld].spanBlock[span].span.arrayRef; 205265555Sambrisko} 206265555Sambrisko 207272744Skadesaistatic u_int8_t 208272744SkadesaiMR_LdDataArmGet(u_int32_t ld, u_int32_t armIdx, MR_DRV_RAID_MAP_ALL * map) 209265555Sambrisko{ 210272744Skadesai return map->raidMap.ldSpanMap[ld].dataArmMap[armIdx]; 211265555Sambrisko} 212265555Sambrisko 213272744Skadesaistatic u_int16_t 214272744SkadesaiMR_PdDevHandleGet(u_int32_t pd, MR_DRV_RAID_MAP_ALL * map) 215265555Sambrisko{ 216272744Skadesai return map->raidMap.devHndlInfo[pd].curDevHdl; 217265555Sambrisko} 218265555Sambrisko 219272744Skadesaistatic u_int16_t 220272744SkadesaiMR_ArPdGet(u_int32_t ar, u_int32_t arm, MR_DRV_RAID_MAP_ALL * map) 221265555Sambrisko{ 222272744Skadesai return map->raidMap.arMapInfo[ar].pd[arm]; 223265555Sambrisko} 224265555Sambrisko 225272744Skadesaistatic MR_LD_SPAN * 226272744SkadesaiMR_LdSpanPtrGet(u_int32_t ld, u_int32_t span, MR_DRV_RAID_MAP_ALL * map) 227265555Sambrisko{ 228272744Skadesai return &map->raidMap.ldSpanMap[ld].spanBlock[span].span; 229265555Sambrisko} 230265555Sambrisko 231272744Skadesaistatic MR_SPAN_BLOCK_INFO * 232272744SkadesaiMR_LdSpanInfoGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map) 233265555Sambrisko{ 234272744Skadesai return &map->raidMap.ldSpanMap[ld].spanBlock[0]; 235265555Sambrisko} 236265555Sambrisko 237272744Skadesaiu_int16_t 238272744SkadesaiMR_TargetIdToLdGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map) 239265555Sambrisko{ 240272744Skadesai return map->raidMap.ldTgtIdToLd[ldTgtId]; 241265555Sambrisko} 242265555Sambrisko 243272744Skadesaiu_int32_t 244272744SkadesaiMR_LdBlockSizeGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map) 245265555Sambrisko{ 246272744Skadesai MR_LD_RAID *raid; 247272744Skadesai u_int32_t ld, ldBlockSize = MRSAS_SCSIBLOCKSIZE; 248265555Sambrisko 249272744Skadesai ld = MR_TargetIdToLdGet(ldTgtId, map); 250265555Sambrisko 251272744Skadesai /* 252272744Skadesai * Check if logical drive was removed. 253272744Skadesai */ 254272744Skadesai if (ld >= MAX_LOGICAL_DRIVES) 255272744Skadesai return ldBlockSize; 256265555Sambrisko 257272744Skadesai raid = MR_LdRaidGet(ld, map); 258272744Skadesai ldBlockSize = raid->logicalBlockLength; 259272744Skadesai if (!ldBlockSize) 260272744Skadesai ldBlockSize = MRSAS_SCSIBLOCKSIZE; 261265555Sambrisko 262272744Skadesai return ldBlockSize; 263265555Sambrisko} 264265555Sambrisko 265272735Skadesai/* 266272735Skadesai * This function will Populate Driver Map using firmware raid map 267272735Skadesai */ 268272744Skadesaivoid 269272744SkadesaiMR_PopulateDrvRaidMap(struct mrsas_softc *sc) 270272735Skadesai{ 271272744Skadesai MR_FW_RAID_MAP_ALL *fw_map_old = NULL; 272272744Skadesai MR_FW_RAID_MAP *pFwRaidMap = NULL; 273272735Skadesai unsigned int i; 274272735Skadesai 275272735Skadesai MR_DRV_RAID_MAP_ALL *drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 276272735Skadesai MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap; 277272735Skadesai 278272744Skadesai if (sc->max256vdSupport) { 279272735Skadesai memcpy(sc->ld_drv_map[sc->map_id & 1], 280272744Skadesai sc->raidmap_mem[sc->map_id & 1], 281272744Skadesai sc->current_map_sz); 282272744Skadesai /* 283272744Skadesai * New Raid map will not set totalSize, so keep expected 284272744Skadesai * value for legacy code in ValidateMapInfo 285272735Skadesai */ 286272744Skadesai pDrvRaidMap->totalSize = sizeof(MR_FW_RAID_MAP_EXT); 287272735Skadesai } else { 288272744Skadesai fw_map_old = (MR_FW_RAID_MAP_ALL *) sc->raidmap_mem[(sc->map_id & 1)]; 289272735Skadesai pFwRaidMap = &fw_map_old->raidMap; 290272735Skadesai 291272735Skadesai#if VD_EXT_DEBUG 292272735Skadesai for (i = 0; i < pFwRaidMap->ldCount; i++) { 293272735Skadesai device_printf(sc->mrsas_dev, 294272744Skadesai "Index 0x%x Target Id 0x%x Seq Num 0x%x Size 0/%lx\n", i, 295272744Skadesai fw_map_old->raidMap.ldSpanMap[i].ldRaid.targetId, 296272744Skadesai fw_map_old->raidMap.ldSpanMap[i].ldRaid.seqNum, 297272744Skadesai fw_map_old->raidMap.ldSpanMap[i].ldRaid.size); 298272735Skadesai } 299272735Skadesai#endif 300272735Skadesai 301272735Skadesai memset(drv_map, 0, sc->drv_map_sz); 302272735Skadesai pDrvRaidMap->totalSize = pFwRaidMap->totalSize; 303272735Skadesai pDrvRaidMap->ldCount = pFwRaidMap->ldCount; 304272735Skadesai pDrvRaidMap->fpPdIoTimeoutSec = 305272744Skadesai pFwRaidMap->fpPdIoTimeoutSec; 306272735Skadesai 307272744Skadesai for (i = 0; i < MAX_RAIDMAP_LOGICAL_DRIVES + MAX_RAIDMAP_VIEWS; i++) { 308272735Skadesai pDrvRaidMap->ldTgtIdToLd[i] = 309272744Skadesai (u_int8_t)pFwRaidMap->ldTgtIdToLd[i]; 310272735Skadesai } 311272735Skadesai 312272744Skadesai for (i = 0; i < pDrvRaidMap->ldCount; i++) { 313272735Skadesai pDrvRaidMap->ldSpanMap[i] = 314272744Skadesai pFwRaidMap->ldSpanMap[i]; 315272735Skadesai 316272735Skadesai#if VD_EXT_DEBUG 317272744Skadesai device_printf(sc->mrsas_dev, "pFwRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x " 318272744Skadesai "pFwRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x size 0x%x\n", 319272744Skadesai i, i, pFwRaidMap->ldSpanMap[i].ldRaid.targetId, 320272744Skadesai pFwRaidMap->ldSpanMap[i].ldRaid.seqNum, 321272744Skadesai (u_int32_t)pFwRaidMap->ldSpanMap[i].ldRaid.rowSize); 322272744Skadesai device_printf(sc->mrsas_dev, "pDrvRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x" 323272744Skadesai "pDrvRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x size 0x%x\n", i, i, 324272744Skadesai pDrvRaidMap->ldSpanMap[i].ldRaid.targetId, 325272744Skadesai pDrvRaidMap->ldSpanMap[i].ldRaid.seqNum, 326272744Skadesai (u_int32_t)pDrvRaidMap->ldSpanMap[i].ldRaid.rowSize); 327272744Skadesai device_printf(sc->mrsas_dev, "drv raid map all %p raid map %p LD RAID MAP %p/%p\n", 328272744Skadesai drv_map, pDrvRaidMap, 329272744Skadesai &pFwRaidMap->ldSpanMap[i].ldRaid, &pDrvRaidMap->ldSpanMap[i].ldRaid); 330272735Skadesai#endif 331272735Skadesai } 332272735Skadesai 333272735Skadesai memcpy(pDrvRaidMap->arMapInfo, pFwRaidMap->arMapInfo, 334272744Skadesai sizeof(MR_ARRAY_INFO) * MAX_RAIDMAP_ARRAYS); 335272735Skadesai memcpy(pDrvRaidMap->devHndlInfo, pFwRaidMap->devHndlInfo, 336272744Skadesai sizeof(MR_DEV_HANDLE_INFO) * 337272744Skadesai MAX_RAIDMAP_PHYSICAL_DEVICES); 338272735Skadesai } 339272735Skadesai} 340272735Skadesai 341272744Skadesai/* 342272744Skadesai * MR_ValidateMapInfo: Validate RAID map 343272744Skadesai * input: Adapter instance soft state 344265555Sambrisko * 345272744Skadesai * This function checks and validates the loaded RAID map. It returns 0 if 346265555Sambrisko * successful, and 1 otherwise. 347265555Sambrisko */ 348272744Skadesaiu_int8_t 349272744SkadesaiMR_ValidateMapInfo(struct mrsas_softc *sc) 350265555Sambrisko{ 351265555Sambrisko if (!sc) { 352265555Sambrisko return 1; 353265555Sambrisko } 354272744Skadesai MR_PopulateDrvRaidMap(sc); 355272735Skadesai 356272744Skadesai MR_DRV_RAID_MAP_ALL *drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 357272744Skadesai MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap; 358272735Skadesai 359272744Skadesai u_int32_t expected_map_size; 360272735Skadesai 361272744Skadesai drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 362272744Skadesai pDrvRaidMap = &drv_map->raidMap; 363272744Skadesai PLD_SPAN_INFO ldSpanInfo = (PLD_SPAN_INFO) & sc->log_to_span; 364265555Sambrisko 365272744Skadesai if (sc->max256vdSupport) 366272744Skadesai expected_map_size = sizeof(MR_FW_RAID_MAP_EXT); 367272744Skadesai else 368272744Skadesai expected_map_size = 369272744Skadesai (sizeof(MR_FW_RAID_MAP) - sizeof(MR_LD_SPAN_MAP)) + 370272744Skadesai (sizeof(MR_LD_SPAN_MAP) * pDrvRaidMap->ldCount); 371265555Sambrisko 372272744Skadesai if (pDrvRaidMap->totalSize != expected_map_size) { 373272744Skadesai device_printf(sc->mrsas_dev, "map size %x not matching ld count\n", expected_map_size); 374272744Skadesai device_printf(sc->mrsas_dev, "span map= %x\n", (unsigned int)sizeof(MR_LD_SPAN_MAP)); 375272744Skadesai device_printf(sc->mrsas_dev, "pDrvRaidMap->totalSize=%x\n", pDrvRaidMap->totalSize); 376272744Skadesai return 1; 377265555Sambrisko } 378272744Skadesai if (sc->UnevenSpanSupport) { 379272744Skadesai printf("Updating span set\n\n"); 380272744Skadesai mr_update_span_set(drv_map, ldSpanInfo); 381272744Skadesai } 382272744Skadesai mrsas_update_load_balance_params(drv_map, sc->load_balance_info); 383265555Sambrisko 384272744Skadesai return 0; 385265555Sambrisko} 386265555Sambrisko 387265555Sambrisko/* 388272744Skadesai * 389272744Skadesai * Function to print info about span set created in driver from FW raid map 390272744Skadesai * 391272744Skadesai * Inputs: map 392272744Skadesai * ldSpanInfo: ld map span info per HBA instance 393272744Skadesai * 394272744Skadesai * 395272744Skadesai */ 396265555Sambrisko#if SPAN_DEBUG 397272744Skadesaistatic int 398272744SkadesaigetSpanInfo(MR_DRV_RAID_MAP_ALL * map, PLD_SPAN_INFO ldSpanInfo) 399265555Sambrisko{ 400265555Sambrisko 401272744Skadesai u_int8_t span; 402272744Skadesai u_int32_t element; 403272744Skadesai MR_LD_RAID *raid; 404272744Skadesai LD_SPAN_SET *span_set; 405272744Skadesai MR_QUAD_ELEMENT *quad; 406272744Skadesai int ldCount; 407272744Skadesai u_int16_t ld; 408265555Sambrisko 409272744Skadesai for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) { 410272744Skadesai ld = MR_TargetIdToLdGet(ldCount, map); 411272744Skadesai if (ld >= MAX_LOGICAL_DRIVES) { 412272744Skadesai continue; 413272744Skadesai } 414272744Skadesai raid = MR_LdRaidGet(ld, map); 415272744Skadesai printf("LD %x: span_depth=%x\n", ld, raid->spanDepth); 416272744Skadesai for (span = 0; span < raid->spanDepth; span++) 417272744Skadesai printf("Span=%x, number of quads=%x\n", span, 418272744Skadesai map->raidMap.ldSpanMap[ld].spanBlock[span]. 419272744Skadesai block_span_info.noElements); 420272744Skadesai for (element = 0; element < MAX_QUAD_DEPTH; element++) { 421272744Skadesai span_set = &(ldSpanInfo[ld].span_set[element]); 422272744Skadesai if (span_set->span_row_data_width == 0) 423272744Skadesai break; 424265555Sambrisko 425272744Skadesai printf("Span Set %x: width=%x, diff=%x\n", element, 426272744Skadesai (unsigned int)span_set->span_row_data_width, 427272744Skadesai (unsigned int)span_set->diff); 428272744Skadesai printf("logical LBA start=0x%08lx, end=0x%08lx\n", 429272744Skadesai (long unsigned int)span_set->log_start_lba, 430272744Skadesai (long unsigned int)span_set->log_end_lba); 431272744Skadesai printf("span row start=0x%08lx, end=0x%08lx\n", 432272744Skadesai (long unsigned int)span_set->span_row_start, 433272744Skadesai (long unsigned int)span_set->span_row_end); 434272744Skadesai printf("data row start=0x%08lx, end=0x%08lx\n", 435272744Skadesai (long unsigned int)span_set->data_row_start, 436272744Skadesai (long unsigned int)span_set->data_row_end); 437272744Skadesai printf("data strip start=0x%08lx, end=0x%08lx\n", 438272744Skadesai (long unsigned int)span_set->data_strip_start, 439272744Skadesai (long unsigned int)span_set->data_strip_end); 440272744Skadesai 441272744Skadesai for (span = 0; span < raid->spanDepth; span++) { 442272744Skadesai if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 443272744Skadesai block_span_info.noElements >= element + 1) { 444272744Skadesai quad = &map->raidMap.ldSpanMap[ld]. 445272744Skadesai spanBlock[span].block_span_info. 446272744Skadesai quad[element]; 447272744Skadesai printf("Span=%x, Quad=%x, diff=%x\n", span, 448272744Skadesai element, quad->diff); 449272744Skadesai printf("offset_in_span=0x%08lx\n", 450272744Skadesai (long unsigned int)quad->offsetInSpan); 451272744Skadesai printf("logical start=0x%08lx, end=0x%08lx\n", 452272744Skadesai (long unsigned int)quad->logStart, 453272744Skadesai (long unsigned int)quad->logEnd); 454272744Skadesai } 455272744Skadesai } 456272744Skadesai } 457272744Skadesai } 458272744Skadesai return 0; 459265555Sambrisko} 460272744Skadesai 461265555Sambrisko#endif 462265555Sambrisko/* 463272744Skadesai * 464272744Skadesai * This routine calculates the Span block for given row using spanset. 465272744Skadesai * 466272744Skadesai * Inputs : HBA instance 467272744Skadesai * ld: Logical drive number 468272744Skadesai * row: Row number 469272744Skadesai * map: LD map 470272744Skadesai * 471272744Skadesai * Outputs : span - Span number block 472272744Skadesai * - Absolute Block number in the physical disk 473272744Skadesai * div_error - Devide error code. 474272744Skadesai */ 475265555Sambrisko 476272744Skadesaiu_int32_t 477272744Skadesaimr_spanset_get_span_block(struct mrsas_softc *sc, u_int32_t ld, u_int64_t row, 478272744Skadesai u_int64_t *span_blk, MR_DRV_RAID_MAP_ALL * map, int *div_error) 479265555Sambrisko{ 480272744Skadesai MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 481272744Skadesai LD_SPAN_SET *span_set; 482272744Skadesai MR_QUAD_ELEMENT *quad; 483272744Skadesai u_int32_t span, info; 484272744Skadesai PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 485265555Sambrisko 486272744Skadesai for (info = 0; info < MAX_QUAD_DEPTH; info++) { 487272744Skadesai span_set = &(ldSpanInfo[ld].span_set[info]); 488265555Sambrisko 489272744Skadesai if (span_set->span_row_data_width == 0) 490272744Skadesai break; 491272744Skadesai if (row > span_set->data_row_end) 492272744Skadesai continue; 493265555Sambrisko 494272744Skadesai for (span = 0; span < raid->spanDepth; span++) 495272744Skadesai if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 496272744Skadesai block_span_info.noElements >= info + 1) { 497272744Skadesai quad = &map->raidMap.ldSpanMap[ld]. 498272744Skadesai spanBlock[span]. 499272744Skadesai block_span_info.quad[info]; 500272744Skadesai if (quad->diff == 0) { 501272744Skadesai *div_error = 1; 502272744Skadesai return span; 503272744Skadesai } 504272744Skadesai if (quad->logStart <= row && 505272744Skadesai row <= quad->logEnd && 506272744Skadesai (mega_mod64(row - quad->logStart, 507272744Skadesai quad->diff)) == 0) { 508272744Skadesai if (span_blk != NULL) { 509272744Skadesai u_int64_t blk; 510272744Skadesai 511272744Skadesai blk = mega_div64_32 512272744Skadesai ((row - quad->logStart), 513272744Skadesai quad->diff); 514272744Skadesai blk = (blk + quad->offsetInSpan) 515272744Skadesai << raid->stripeShift; 516272744Skadesai *span_blk = blk; 517272744Skadesai } 518272744Skadesai return span; 519272744Skadesai } 520272744Skadesai } 521272744Skadesai } 522272744Skadesai return SPAN_INVALID; 523265555Sambrisko} 524265555Sambrisko 525265555Sambrisko/* 526272744Skadesai * 527272744Skadesai * This routine calculates the row for given strip using spanset. 528272744Skadesai * 529272744Skadesai * Inputs : HBA instance 530272744Skadesai * ld: Logical drive number 531272744Skadesai * Strip: Strip 532272744Skadesai * map: LD map 533272744Skadesai * 534272744Skadesai * Outputs : row - row associated with strip 535272744Skadesai */ 536265555Sambrisko 537272744Skadesaistatic u_int64_t 538272744Skadesaiget_row_from_strip(struct mrsas_softc *sc, 539272744Skadesai u_int32_t ld, u_int64_t strip, MR_DRV_RAID_MAP_ALL * map) 540265555Sambrisko{ 541272744Skadesai MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 542272744Skadesai LD_SPAN_SET *span_set; 543272744Skadesai PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 544272744Skadesai u_int32_t info, strip_offset, span, span_offset; 545272744Skadesai u_int64_t span_set_Strip, span_set_Row; 546265555Sambrisko 547272744Skadesai for (info = 0; info < MAX_QUAD_DEPTH; info++) { 548272744Skadesai span_set = &(ldSpanInfo[ld].span_set[info]); 549265555Sambrisko 550272744Skadesai if (span_set->span_row_data_width == 0) 551272744Skadesai break; 552272744Skadesai if (strip > span_set->data_strip_end) 553272744Skadesai continue; 554265555Sambrisko 555272744Skadesai span_set_Strip = strip - span_set->data_strip_start; 556272744Skadesai strip_offset = mega_mod64(span_set_Strip, 557272744Skadesai span_set->span_row_data_width); 558272744Skadesai span_set_Row = mega_div64_32(span_set_Strip, 559272744Skadesai span_set->span_row_data_width) * span_set->diff; 560272744Skadesai for (span = 0, span_offset = 0; span < raid->spanDepth; span++) 561272744Skadesai if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 562272744Skadesai block_span_info.noElements >= info + 1) { 563272744Skadesai if (strip_offset >= 564272744Skadesai span_set->strip_offset[span]) 565272744Skadesai span_offset++; 566272744Skadesai else 567272744Skadesai break; 568272744Skadesai } 569272744Skadesai mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : Strip 0x%llx, span_set_Strip 0x%llx, span_set_Row 0x%llx " 570272744Skadesai "data width 0x%llx span offset 0x%llx\n", (unsigned long long)strip, 571272744Skadesai (unsigned long long)span_set_Strip, 572272744Skadesai (unsigned long long)span_set_Row, 573272744Skadesai (unsigned long long)span_set->span_row_data_width, (unsigned long long)span_offset); 574272744Skadesai mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : For strip 0x%llx row is 0x%llx\n", (unsigned long long)strip, 575272744Skadesai (unsigned long long)span_set->data_row_start + 576272744Skadesai (unsigned long long)span_set_Row + (span_offset - 1)); 577272744Skadesai return (span_set->data_row_start + span_set_Row + (span_offset - 1)); 578272744Skadesai } 579272744Skadesai return -1LLU; 580265555Sambrisko} 581265555Sambrisko 582265555Sambrisko 583265555Sambrisko/* 584272744Skadesai * 585272744Skadesai * This routine calculates the Start Strip for given row using spanset. 586272744Skadesai * 587272744Skadesai * Inputs: HBA instance 588272744Skadesai * ld: Logical drive number 589272744Skadesai * row: Row number 590272744Skadesai * map: LD map 591272744Skadesai * 592272744Skadesai * Outputs : Strip - Start strip associated with row 593272744Skadesai */ 594265555Sambrisko 595272744Skadesaistatic u_int64_t 596272744Skadesaiget_strip_from_row(struct mrsas_softc *sc, 597272744Skadesai u_int32_t ld, u_int64_t row, MR_DRV_RAID_MAP_ALL * map) 598265555Sambrisko{ 599272744Skadesai MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 600272744Skadesai LD_SPAN_SET *span_set; 601272744Skadesai MR_QUAD_ELEMENT *quad; 602272744Skadesai PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 603272744Skadesai u_int32_t span, info; 604272744Skadesai u_int64_t strip; 605265555Sambrisko 606272744Skadesai for (info = 0; info < MAX_QUAD_DEPTH; info++) { 607272744Skadesai span_set = &(ldSpanInfo[ld].span_set[info]); 608265555Sambrisko 609272744Skadesai if (span_set->span_row_data_width == 0) 610272744Skadesai break; 611272744Skadesai if (row > span_set->data_row_end) 612272744Skadesai continue; 613265555Sambrisko 614272744Skadesai for (span = 0; span < raid->spanDepth; span++) 615272744Skadesai if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 616272744Skadesai block_span_info.noElements >= info + 1) { 617272744Skadesai quad = &map->raidMap.ldSpanMap[ld]. 618272744Skadesai spanBlock[span].block_span_info.quad[info]; 619272744Skadesai if (quad->logStart <= row && 620272744Skadesai row <= quad->logEnd && 621272744Skadesai mega_mod64((row - quad->logStart), 622272744Skadesai quad->diff) == 0) { 623272744Skadesai strip = mega_div64_32 624272744Skadesai (((row - span_set->data_row_start) 625272744Skadesai - quad->logStart), 626272744Skadesai quad->diff); 627272744Skadesai strip *= span_set->span_row_data_width; 628272744Skadesai strip += span_set->data_strip_start; 629272744Skadesai strip += span_set->strip_offset[span]; 630272744Skadesai return strip; 631272744Skadesai } 632272744Skadesai } 633272744Skadesai } 634272744Skadesai mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug - get_strip_from_row: returns invalid " 635272744Skadesai "strip for ld=%x, row=%lx\n", ld, (long unsigned int)row); 636272744Skadesai return -1; 637265555Sambrisko} 638265555Sambrisko 639265555Sambrisko/* 640272744Skadesai * ***************************************************************************** 641272744Skadesai * 642272744Skadesai * 643272744Skadesai * This routine calculates the Physical Arm for given strip using spanset. 644272744Skadesai * 645272744Skadesai * Inputs : HBA instance 646272744Skadesai * Logical drive number 647272744Skadesai * Strip 648272744Skadesai * LD map 649272744Skadesai * 650272744Skadesai * Outputs : Phys Arm - Phys Arm associated with strip 651272744Skadesai */ 652265555Sambrisko 653272744Skadesaistatic u_int32_t 654272744Skadesaiget_arm_from_strip(struct mrsas_softc *sc, 655272744Skadesai u_int32_t ld, u_int64_t strip, MR_DRV_RAID_MAP_ALL * map) 656265555Sambrisko{ 657272744Skadesai MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 658272744Skadesai LD_SPAN_SET *span_set; 659272744Skadesai PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 660272744Skadesai u_int32_t info, strip_offset, span, span_offset; 661265555Sambrisko 662272744Skadesai for (info = 0; info < MAX_QUAD_DEPTH; info++) { 663272744Skadesai span_set = &(ldSpanInfo[ld].span_set[info]); 664265555Sambrisko 665272744Skadesai if (span_set->span_row_data_width == 0) 666272744Skadesai break; 667272744Skadesai if (strip > span_set->data_strip_end) 668272744Skadesai continue; 669265555Sambrisko 670272744Skadesai strip_offset = (u_int32_t)mega_mod64 671272744Skadesai ((strip - span_set->data_strip_start), 672272744Skadesai span_set->span_row_data_width); 673265555Sambrisko 674272744Skadesai for (span = 0, span_offset = 0; span < raid->spanDepth; span++) 675272744Skadesai if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 676272744Skadesai block_span_info.noElements >= info + 1) { 677272744Skadesai if (strip_offset >= span_set->strip_offset[span]) 678272744Skadesai span_offset = span_set->strip_offset[span]; 679272744Skadesai else 680272744Skadesai break; 681272744Skadesai } 682272744Skadesai mrsas_dprint(sc, MRSAS_PRL11, "LSI PRL11: get_arm_from_strip: " 683272744Skadesai "for ld=0x%x strip=0x%lx arm is 0x%x\n", ld, 684272744Skadesai (long unsigned int)strip, (strip_offset - span_offset)); 685272744Skadesai return (strip_offset - span_offset); 686272744Skadesai } 687265555Sambrisko 688272744Skadesai mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: - get_arm_from_strip: returns invalid arm" 689272744Skadesai " for ld=%x strip=%lx\n", ld, (long unsigned int)strip); 690265555Sambrisko 691272744Skadesai return -1; 692265555Sambrisko} 693265555Sambrisko 694265555Sambrisko 695265555Sambrisko/* This Function will return Phys arm */ 696272744Skadesaiu_int8_t 697272744Skadesaiget_arm(struct mrsas_softc *sc, u_int32_t ld, u_int8_t span, u_int64_t stripe, 698272744Skadesai MR_DRV_RAID_MAP_ALL * map) 699265555Sambrisko{ 700272744Skadesai MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 701265555Sambrisko 702272744Skadesai /* Need to check correct default value */ 703272744Skadesai u_int32_t arm = 0; 704265555Sambrisko 705272744Skadesai switch (raid->level) { 706272744Skadesai case 0: 707272744Skadesai case 5: 708272744Skadesai case 6: 709272744Skadesai arm = mega_mod64(stripe, SPAN_ROW_SIZE(map, ld, span)); 710272744Skadesai break; 711272744Skadesai case 1: 712272744Skadesai /* start with logical arm */ 713272744Skadesai arm = get_arm_from_strip(sc, ld, stripe, map); 714272744Skadesai arm *= 2; 715272744Skadesai break; 716272744Skadesai } 717265555Sambrisko 718272744Skadesai return arm; 719265555Sambrisko} 720265555Sambrisko 721265555Sambrisko/* 722272744Skadesai * 723272744Skadesai * This routine calculates the arm, span and block for the specified stripe and 724272744Skadesai * reference in stripe using spanset 725272744Skadesai * 726272744Skadesai * Inputs : Logical drive number 727272744Skadesai * stripRow: Stripe number 728272744Skadesai * stripRef: Reference in stripe 729272744Skadesai * 730272744Skadesai * Outputs : span - Span number block - Absolute Block 731272744Skadesai * number in the physical disk 732272744Skadesai */ 733272744Skadesaistatic u_int8_t 734272744Skadesaimr_spanset_get_phy_params(struct mrsas_softc *sc, u_int32_t ld, u_int64_t stripRow, 735272744Skadesai u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 736272744Skadesai RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map) 737265555Sambrisko{ 738272744Skadesai MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 739272744Skadesai u_int32_t pd, arRef; 740272744Skadesai u_int8_t physArm, span; 741272744Skadesai u_int64_t row; 742272744Skadesai u_int8_t retval = TRUE; 743272744Skadesai u_int64_t *pdBlock = &io_info->pdBlock; 744272744Skadesai u_int16_t *pDevHandle = &io_info->devHandle; 745272744Skadesai u_int32_t logArm, rowMod, armQ, arm; 746272744Skadesai u_int8_t do_invader = 0; 747265555Sambrisko 748272744Skadesai if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) 749272744Skadesai do_invader = 1; 750265555Sambrisko 751272744Skadesai /* Get row and span from io_info for Uneven Span IO. */ 752272744Skadesai row = io_info->start_row; 753272744Skadesai span = io_info->start_span; 754265555Sambrisko 755265555Sambrisko 756272744Skadesai if (raid->level == 6) { 757272744Skadesai logArm = get_arm_from_strip(sc, ld, stripRow, map); 758272744Skadesai rowMod = mega_mod64(row, SPAN_ROW_SIZE(map, ld, span)); 759272744Skadesai armQ = SPAN_ROW_SIZE(map, ld, span) - 1 - rowMod; 760272744Skadesai arm = armQ + 1 + logArm; 761272744Skadesai if (arm >= SPAN_ROW_SIZE(map, ld, span)) 762272744Skadesai arm -= SPAN_ROW_SIZE(map, ld, span); 763272744Skadesai physArm = (u_int8_t)arm; 764272744Skadesai } else 765272744Skadesai /* Calculate the arm */ 766272744Skadesai physArm = get_arm(sc, ld, span, stripRow, map); 767265555Sambrisko 768265555Sambrisko 769272744Skadesai arRef = MR_LdSpanArrayGet(ld, span, map); 770272744Skadesai pd = MR_ArPdGet(arRef, physArm, map); 771265555Sambrisko 772272744Skadesai if (pd != MR_PD_INVALID) 773272744Skadesai *pDevHandle = MR_PdDevHandleGet(pd, map); 774272744Skadesai else { 775272744Skadesai *pDevHandle = MR_PD_INVALID; 776272744Skadesai if ((raid->level >= 5) && ((!do_invader) || (do_invader && 777272744Skadesai raid->regTypeReqOnRead != REGION_TYPE_UNUSED))) 778272744Skadesai pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; 779272744Skadesai else if (raid->level == 1) { 780272744Skadesai pd = MR_ArPdGet(arRef, physArm + 1, map); 781272744Skadesai if (pd != MR_PD_INVALID) 782272744Skadesai *pDevHandle = MR_PdDevHandleGet(pd, map); 783272744Skadesai } 784272744Skadesai } 785272744Skadesai 786272744Skadesai *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk; 787272744Skadesai pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; 788272744Skadesai return retval; 789265555Sambrisko} 790265555Sambrisko 791272744Skadesai/* 792272744Skadesai * MR_BuildRaidContext: Set up Fast path RAID context 793272744Skadesai * 794272744Skadesai * This function will initiate command processing. The start/end row and strip 795272744Skadesai * information is calculated then the lock is acquired. This function will 796272744Skadesai * return 0 if region lock was acquired OR return num strips. 797272744Skadesai */ 798272744Skadesaiu_int8_t 799265555SambriskoMR_BuildRaidContext(struct mrsas_softc *sc, struct IO_REQUEST_INFO *io_info, 800272744Skadesai RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map) 801265555Sambrisko{ 802272744Skadesai MR_LD_RAID *raid; 803272744Skadesai u_int32_t ld, stripSize, stripe_mask; 804272744Skadesai u_int64_t endLba, endStrip, endRow, start_row, start_strip; 805272744Skadesai REGION_KEY regStart; 806272744Skadesai REGION_LEN regSize; 807272744Skadesai u_int8_t num_strips, numRows; 808272744Skadesai u_int16_t ref_in_start_stripe, ref_in_end_stripe; 809272744Skadesai u_int64_t ldStartBlock; 810272744Skadesai u_int32_t numBlocks, ldTgtId; 811272744Skadesai u_int8_t isRead, stripIdx; 812272744Skadesai u_int8_t retval = 0; 813265555Sambrisko u_int8_t startlba_span = SPAN_INVALID; 814272744Skadesai u_int64_t *pdBlock = &io_info->pdBlock; 815272744Skadesai int error_code = 0; 816265555Sambrisko 817272744Skadesai ldStartBlock = io_info->ldStartBlock; 818272744Skadesai numBlocks = io_info->numBlocks; 819272744Skadesai ldTgtId = io_info->ldTgtId; 820272744Skadesai isRead = io_info->isRead; 821272744Skadesai 822265555Sambrisko io_info->IoforUnevenSpan = 0; 823272744Skadesai io_info->start_span = SPAN_INVALID; 824265555Sambrisko 825272744Skadesai ld = MR_TargetIdToLdGet(ldTgtId, map); 826272744Skadesai raid = MR_LdRaidGet(ld, map); 827265555Sambrisko 828272744Skadesai if (raid->rowDataSize == 0) { 829272744Skadesai if (MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize == 0) 830272744Skadesai return FALSE; 831272744Skadesai else if (sc->UnevenSpanSupport) { 832272744Skadesai io_info->IoforUnevenSpan = 1; 833272744Skadesai } else { 834272744Skadesai mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: raid->rowDataSize is 0, but has SPAN[0] rowDataSize = 0x%0x," 835272744Skadesai " but there is _NO_ UnevenSpanSupport\n", 836272744Skadesai MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize); 837272744Skadesai return FALSE; 838272744Skadesai } 839265555Sambrisko } 840272744Skadesai stripSize = 1 << raid->stripeShift; 841272744Skadesai stripe_mask = stripSize - 1; 842272744Skadesai /* 843272744Skadesai * calculate starting row and stripe, and number of strips and rows 844272744Skadesai */ 845272744Skadesai start_strip = ldStartBlock >> raid->stripeShift; 846272744Skadesai ref_in_start_stripe = (u_int16_t)(ldStartBlock & stripe_mask); 847272744Skadesai endLba = ldStartBlock + numBlocks - 1; 848272744Skadesai ref_in_end_stripe = (u_int16_t)(endLba & stripe_mask); 849272744Skadesai endStrip = endLba >> raid->stripeShift; 850272744Skadesai num_strips = (u_int8_t)(endStrip - start_strip + 1); /* End strip */ 851272744Skadesai if (io_info->IoforUnevenSpan) { 852272744Skadesai start_row = get_row_from_strip(sc, ld, start_strip, map); 853272744Skadesai endRow = get_row_from_strip(sc, ld, endStrip, map); 854272744Skadesai if (raid->spanDepth == 1) { 855272744Skadesai startlba_span = 0; 856272744Skadesai *pdBlock = start_row << raid->stripeShift; 857272744Skadesai } else { 858272744Skadesai startlba_span = (u_int8_t)mr_spanset_get_span_block(sc, ld, start_row, 859272744Skadesai pdBlock, map, &error_code); 860272744Skadesai if (error_code == 1) { 861272744Skadesai mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: return from %s %d. Send IO w/o region lock.\n", 862272744Skadesai __func__, __LINE__); 863272744Skadesai return FALSE; 864272744Skadesai } 865272744Skadesai } 866272744Skadesai if (startlba_span == SPAN_INVALID) { 867272744Skadesai mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: return from %s %d for row 0x%llx," 868272744Skadesai "start strip %llx endSrip %llx\n", __func__, 869272744Skadesai __LINE__, (unsigned long long)start_row, 870272744Skadesai (unsigned long long)start_strip, 871272744Skadesai (unsigned long long)endStrip); 872272744Skadesai return FALSE; 873272744Skadesai } 874272744Skadesai io_info->start_span = startlba_span; 875272744Skadesai io_info->start_row = start_row; 876272744Skadesai mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: Check Span number from %s %d for row 0x%llx, " 877272744Skadesai " start strip 0x%llx endSrip 0x%llx span 0x%x\n", 878272744Skadesai __func__, __LINE__, (unsigned long long)start_row, 879272744Skadesai (unsigned long long)start_strip, 880272744Skadesai (unsigned long long)endStrip, startlba_span); 881272744Skadesai mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : 1. start_row 0x%llx endRow 0x%llx Start span 0x%x\n", 882272744Skadesai (unsigned long long)start_row, (unsigned long long)endRow, startlba_span); 883272744Skadesai } else { 884272744Skadesai start_row = mega_div64_32(start_strip, raid->rowDataSize); 885272744Skadesai endRow = mega_div64_32(endStrip, raid->rowDataSize); 886272744Skadesai } 887265555Sambrisko 888272744Skadesai numRows = (u_int8_t)(endRow - start_row + 1); /* get the row count */ 889265555Sambrisko 890272744Skadesai /* 891272744Skadesai * Calculate region info. (Assume region at start of first row, and 892272744Skadesai * assume this IO needs the full row - will adjust if not true.) 893272744Skadesai */ 894272744Skadesai regStart = start_row << raid->stripeShift; 895272744Skadesai regSize = stripSize; 896265555Sambrisko 897272744Skadesai /* Check if we can send this I/O via FastPath */ 898272744Skadesai if (raid->capability.fpCapable) { 899272744Skadesai if (isRead) 900272744Skadesai io_info->fpOkForIo = (raid->capability.fpReadCapable && 901272744Skadesai ((num_strips == 1) || 902272744Skadesai raid->capability.fpReadAcrossStripe)); 903272744Skadesai else 904272744Skadesai io_info->fpOkForIo = (raid->capability.fpWriteCapable && 905272744Skadesai ((num_strips == 1) || 906272744Skadesai raid->capability.fpWriteAcrossStripe)); 907272744Skadesai } else 908272744Skadesai io_info->fpOkForIo = FALSE; 909265555Sambrisko 910272744Skadesai if (numRows == 1) { 911272744Skadesai if (num_strips == 1) { 912272744Skadesai regStart += ref_in_start_stripe; 913272744Skadesai regSize = numBlocks; 914272744Skadesai } 915272744Skadesai } else if (io_info->IoforUnevenSpan == 0) { 916272744Skadesai /* 917272744Skadesai * For Even span region lock optimization. If the start strip 918272744Skadesai * is the last in the start row 919272744Skadesai */ 920272744Skadesai if (start_strip == (start_row + 1) * raid->rowDataSize - 1) { 921272744Skadesai regStart += ref_in_start_stripe; 922272744Skadesai /* 923272744Skadesai * initialize count to sectors from startRef to end 924272744Skadesai * of strip 925272744Skadesai */ 926272744Skadesai regSize = stripSize - ref_in_start_stripe; 927272744Skadesai } 928272744Skadesai /* add complete rows in the middle of the transfer */ 929265555Sambrisko if (numRows > 2) 930272744Skadesai regSize += (numRows - 2) << raid->stripeShift; 931265555Sambrisko 932272744Skadesai /* if IO ends within first strip of last row */ 933272744Skadesai if (endStrip == endRow * raid->rowDataSize) 934272744Skadesai regSize += ref_in_end_stripe + 1; 935272744Skadesai else 936272744Skadesai regSize += stripSize; 937272744Skadesai } else { 938272744Skadesai if (start_strip == (get_strip_from_row(sc, ld, start_row, map) + 939272744Skadesai SPAN_ROW_DATA_SIZE(map, ld, startlba_span) - 1)) { 940272744Skadesai regStart += ref_in_start_stripe; 941272744Skadesai /* 942272744Skadesai * initialize count to sectors from startRef to end 943272744Skadesai * of strip 944272744Skadesai */ 945265555Sambrisko regSize = stripSize - ref_in_start_stripe; 946272744Skadesai } 947272744Skadesai /* add complete rows in the middle of the transfer */ 948272744Skadesai if (numRows > 2) 949272744Skadesai regSize += (numRows - 2) << raid->stripeShift; 950265555Sambrisko 951272744Skadesai /* if IO ends within first strip of last row */ 952272744Skadesai if (endStrip == get_strip_from_row(sc, ld, endRow, map)) 953272744Skadesai regSize += ref_in_end_stripe + 1; 954272744Skadesai else 955272744Skadesai regSize += stripSize; 956272744Skadesai } 957272744Skadesai pRAID_Context->timeoutValue = map->raidMap.fpPdIoTimeoutSec; 958272744Skadesai if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) 959272744Skadesai pRAID_Context->regLockFlags = (isRead) ? raid->regTypeReqOnRead : raid->regTypeReqOnWrite; 960272744Skadesai else 961272744Skadesai pRAID_Context->regLockFlags = (isRead) ? REGION_TYPE_SHARED_READ : raid->regTypeReqOnWrite; 962272744Skadesai pRAID_Context->VirtualDiskTgtId = raid->targetId; 963272744Skadesai pRAID_Context->regLockRowLBA = regStart; 964272744Skadesai pRAID_Context->regLockLength = regSize; 965272744Skadesai pRAID_Context->configSeqNum = raid->seqNum; 966265555Sambrisko 967272744Skadesai /* 968272744Skadesai * Get Phy Params only if FP capable, or else leave it to MR firmware 969272744Skadesai * to do the calculation. 970272744Skadesai */ 971272744Skadesai if (io_info->fpOkForIo) { 972272744Skadesai retval = io_info->IoforUnevenSpan ? 973272744Skadesai mr_spanset_get_phy_params(sc, ld, start_strip, 974272744Skadesai ref_in_start_stripe, io_info, pRAID_Context, map) : 975272744Skadesai MR_GetPhyParams(sc, ld, start_strip, 976272744Skadesai ref_in_start_stripe, io_info, pRAID_Context, map); 977272744Skadesai /* If IO on an invalid Pd, then FP is not possible */ 978272744Skadesai if (io_info->devHandle == MR_PD_INVALID) 979272744Skadesai io_info->fpOkForIo = FALSE; 980272744Skadesai return retval; 981272744Skadesai } else if (isRead) { 982272744Skadesai for (stripIdx = 0; stripIdx < num_strips; stripIdx++) { 983272744Skadesai retval = io_info->IoforUnevenSpan ? 984272744Skadesai mr_spanset_get_phy_params(sc, ld, start_strip + stripIdx, 985272744Skadesai ref_in_start_stripe, io_info, pRAID_Context, map) : 986272744Skadesai MR_GetPhyParams(sc, ld, start_strip + stripIdx, 987272744Skadesai ref_in_start_stripe, io_info, pRAID_Context, map); 988272744Skadesai if (!retval) 989272744Skadesai return TRUE; 990272744Skadesai } 991272744Skadesai } 992265555Sambrisko#if SPAN_DEBUG 993272744Skadesai /* Just for testing what arm we get for strip. */ 994272744Skadesai get_arm_from_strip(sc, ld, start_strip, map); 995265555Sambrisko#endif 996272744Skadesai return TRUE; 997265555Sambrisko} 998265555Sambrisko 999265555Sambrisko/* 1000272744Skadesai * 1001272744Skadesai * This routine pepare spanset info from Valid Raid map and store it into local 1002272744Skadesai * copy of ldSpanInfo per instance data structure. 1003272744Skadesai * 1004272744Skadesai * Inputs : LD map 1005272744Skadesai * ldSpanInfo per HBA instance 1006272744Skadesai * 1007272744Skadesai */ 1008272744Skadesaivoid 1009272744Skadesaimr_update_span_set(MR_DRV_RAID_MAP_ALL * map, PLD_SPAN_INFO ldSpanInfo) 1010265555Sambrisko{ 1011272744Skadesai u_int8_t span, count; 1012272744Skadesai u_int32_t element, span_row_width; 1013272744Skadesai u_int64_t span_row; 1014272744Skadesai MR_LD_RAID *raid; 1015272744Skadesai LD_SPAN_SET *span_set, *span_set_prev; 1016272744Skadesai MR_QUAD_ELEMENT *quad; 1017272744Skadesai int ldCount; 1018272744Skadesai u_int16_t ld; 1019272735Skadesai 1020272744Skadesai for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) { 1021272744Skadesai ld = MR_TargetIdToLdGet(ldCount, map); 1022272744Skadesai if (ld >= MAX_LOGICAL_DRIVES) 1023272744Skadesai continue; 1024272744Skadesai raid = MR_LdRaidGet(ld, map); 1025272744Skadesai for (element = 0; element < MAX_QUAD_DEPTH; element++) { 1026272744Skadesai for (span = 0; span < raid->spanDepth; span++) { 1027272744Skadesai if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 1028272744Skadesai block_span_info.noElements < element + 1) 1029272744Skadesai continue; 1030272744Skadesai /* TO-DO */ 1031272744Skadesai span_set = &(ldSpanInfo[ld].span_set[element]); 1032272744Skadesai quad = &map->raidMap.ldSpanMap[ld]. 1033272744Skadesai spanBlock[span].block_span_info.quad[element]; 1034265555Sambrisko 1035272744Skadesai span_set->diff = quad->diff; 1036265555Sambrisko 1037272744Skadesai for (count = 0, span_row_width = 0; 1038272744Skadesai count < raid->spanDepth; count++) { 1039272744Skadesai if (map->raidMap.ldSpanMap[ld].spanBlock[count]. 1040272744Skadesai block_span_info.noElements >= element + 1) { 1041272744Skadesai span_set->strip_offset[count] = span_row_width; 1042272744Skadesai span_row_width += 1043272744Skadesai MR_LdSpanPtrGet(ld, count, map)->spanRowDataSize; 1044265555Sambrisko#if SPAN_DEBUG 1045272744Skadesai printf("LSI Debug span %x rowDataSize %x\n", count, 1046272744Skadesai MR_LdSpanPtrGet(ld, count, map)->spanRowDataSize); 1047265555Sambrisko#endif 1048272744Skadesai } 1049272744Skadesai } 1050265555Sambrisko 1051272744Skadesai span_set->span_row_data_width = span_row_width; 1052272744Skadesai span_row = mega_div64_32(((quad->logEnd - 1053272744Skadesai quad->logStart) + quad->diff), quad->diff); 1054265555Sambrisko 1055272744Skadesai if (element == 0) { 1056272744Skadesai span_set->log_start_lba = 0; 1057272744Skadesai span_set->log_end_lba = 1058272744Skadesai ((span_row << raid->stripeShift) * span_row_width) - 1; 1059265555Sambrisko 1060272744Skadesai span_set->span_row_start = 0; 1061272744Skadesai span_set->span_row_end = span_row - 1; 1062265555Sambrisko 1063272744Skadesai span_set->data_strip_start = 0; 1064272744Skadesai span_set->data_strip_end = (span_row * span_row_width) - 1; 1065265555Sambrisko 1066272744Skadesai span_set->data_row_start = 0; 1067272744Skadesai span_set->data_row_end = (span_row * quad->diff) - 1; 1068272744Skadesai } else { 1069272744Skadesai span_set_prev = &(ldSpanInfo[ld].span_set[element - 1]); 1070272744Skadesai span_set->log_start_lba = span_set_prev->log_end_lba + 1; 1071272744Skadesai span_set->log_end_lba = span_set->log_start_lba + 1072272744Skadesai ((span_row << raid->stripeShift) * span_row_width) - 1; 1073265555Sambrisko 1074272744Skadesai span_set->span_row_start = span_set_prev->span_row_end + 1; 1075272744Skadesai span_set->span_row_end = 1076272744Skadesai span_set->span_row_start + span_row - 1; 1077272744Skadesai 1078272744Skadesai span_set->data_strip_start = 1079272744Skadesai span_set_prev->data_strip_end + 1; 1080272744Skadesai span_set->data_strip_end = span_set->data_strip_start + 1081272744Skadesai (span_row * span_row_width) - 1; 1082272744Skadesai 1083272744Skadesai span_set->data_row_start = span_set_prev->data_row_end + 1; 1084272744Skadesai span_set->data_row_end = span_set->data_row_start + 1085272744Skadesai (span_row * quad->diff) - 1; 1086272744Skadesai } 1087272744Skadesai break; 1088272744Skadesai } 1089272744Skadesai if (span == raid->spanDepth) 1090272744Skadesai break; /* no quads remain */ 1091272744Skadesai } 1092272744Skadesai } 1093265555Sambrisko#if SPAN_DEBUG 1094272744Skadesai getSpanInfo(map, ldSpanInfo); /* to get span set info */ 1095265555Sambrisko#endif 1096265555Sambrisko} 1097265555Sambrisko 1098272744Skadesai/* 1099272744Skadesai * mrsas_update_load_balance_params: Update load balance parmas 1100272744Skadesai * Inputs: map pointer 1101272744Skadesai * Load balance info 1102265555Sambrisko * 1103272744Skadesai * This function updates the load balance parameters for the LD config of a two 1104272744Skadesai * drive optimal RAID-1. 1105265555Sambrisko */ 1106272744Skadesaivoid 1107272744Skadesaimrsas_update_load_balance_params(MR_DRV_RAID_MAP_ALL * map, 1108272744Skadesai PLD_LOAD_BALANCE_INFO lbInfo) 1109265555Sambrisko{ 1110272744Skadesai int ldCount; 1111272744Skadesai u_int16_t ld; 1112272744Skadesai u_int32_t pd, arRef; 1113272744Skadesai MR_LD_RAID *raid; 1114265555Sambrisko 1115272744Skadesai for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) { 1116272744Skadesai ld = MR_TargetIdToLdGet(ldCount, map); 1117272744Skadesai if (ld >= MAX_LOGICAL_DRIVES) { 1118272744Skadesai lbInfo[ldCount].loadBalanceFlag = 0; 1119272744Skadesai continue; 1120272744Skadesai } 1121272744Skadesai raid = MR_LdRaidGet(ld, map); 1122265555Sambrisko 1123272744Skadesai /* Two drive Optimal RAID 1 */ 1124272744Skadesai if ((raid->level == 1) && (raid->rowSize == 2) && 1125272744Skadesai (raid->spanDepth == 1) 1126272744Skadesai && raid->ldState == MR_LD_STATE_OPTIMAL) { 1127272744Skadesai lbInfo[ldCount].loadBalanceFlag = 1; 1128265555Sambrisko 1129272744Skadesai /* Get the array on which this span is present */ 1130272744Skadesai arRef = MR_LdSpanArrayGet(ld, 0, map); 1131265555Sambrisko 1132272744Skadesai /* Get the PD */ 1133272744Skadesai pd = MR_ArPdGet(arRef, 0, map); 1134272744Skadesai /* Get dev handle from PD */ 1135272744Skadesai lbInfo[ldCount].raid1DevHandle[0] = MR_PdDevHandleGet(pd, map); 1136272744Skadesai pd = MR_ArPdGet(arRef, 1, map); 1137272744Skadesai lbInfo[ldCount].raid1DevHandle[1] = MR_PdDevHandleGet(pd, map); 1138272744Skadesai } else 1139272744Skadesai lbInfo[ldCount].loadBalanceFlag = 0; 1140272744Skadesai } 1141265555Sambrisko} 1142265555Sambrisko 1143265555Sambrisko 1144272744Skadesai/* 1145272744Skadesai * mrsas_set_pd_lba: Sets PD LBA 1146272744Skadesai * input: io_request pointer 1147272744Skadesai * CDB length 1148272744Skadesai * io_info pointer 1149272744Skadesai * Pointer to CCB 1150272744Skadesai * Local RAID map pointer 1151272744Skadesai * Start block of IO Block Size 1152265555Sambrisko * 1153265555Sambrisko * Used to set the PD logical block address in CDB for FP IOs. 1154265555Sambrisko */ 1155272744Skadesaivoid 1156272744Skadesaimrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request, u_int8_t cdb_len, 1157265555Sambrisko struct IO_REQUEST_INFO *io_info, union ccb *ccb, 1158272744Skadesai MR_DRV_RAID_MAP_ALL * local_map_ptr, u_int32_t ref_tag, 1159265555Sambrisko u_int32_t ld_block_size) 1160265555Sambrisko{ 1161272744Skadesai MR_LD_RAID *raid; 1162272744Skadesai u_int32_t ld; 1163272744Skadesai u_int64_t start_blk = io_info->pdBlock; 1164272744Skadesai u_int8_t *cdb = io_request->CDB.CDB32; 1165272744Skadesai u_int32_t num_blocks = io_info->numBlocks; 1166272744Skadesai u_int8_t opcode = 0, flagvals = 0, groupnum = 0, control = 0; 1167272744Skadesai struct ccb_hdr *ccb_h = &(ccb->ccb_h); 1168265555Sambrisko 1169272744Skadesai /* Check if T10 PI (DIF) is enabled for this LD */ 1170272744Skadesai ld = MR_TargetIdToLdGet(io_info->ldTgtId, local_map_ptr); 1171272744Skadesai raid = MR_LdRaidGet(ld, local_map_ptr); 1172272744Skadesai if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER) { 1173272744Skadesai memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1174272744Skadesai cdb[0] = MRSAS_SCSI_VARIABLE_LENGTH_CMD; 1175272744Skadesai cdb[7] = MRSAS_SCSI_ADDL_CDB_LEN; 1176265555Sambrisko 1177272744Skadesai if (ccb_h->flags == CAM_DIR_OUT) 1178272744Skadesai cdb[9] = MRSAS_SCSI_SERVICE_ACTION_READ32; 1179272744Skadesai else 1180272744Skadesai cdb[9] = MRSAS_SCSI_SERVICE_ACTION_WRITE32; 1181272744Skadesai cdb[10] = MRSAS_RD_WR_PROTECT_CHECK_ALL; 1182265555Sambrisko 1183272744Skadesai /* LBA */ 1184272744Skadesai cdb[12] = (u_int8_t)((start_blk >> 56) & 0xff); 1185272744Skadesai cdb[13] = (u_int8_t)((start_blk >> 48) & 0xff); 1186272744Skadesai cdb[14] = (u_int8_t)((start_blk >> 40) & 0xff); 1187272744Skadesai cdb[15] = (u_int8_t)((start_blk >> 32) & 0xff); 1188272744Skadesai cdb[16] = (u_int8_t)((start_blk >> 24) & 0xff); 1189272744Skadesai cdb[17] = (u_int8_t)((start_blk >> 16) & 0xff); 1190272744Skadesai cdb[18] = (u_int8_t)((start_blk >> 8) & 0xff); 1191272744Skadesai cdb[19] = (u_int8_t)(start_blk & 0xff); 1192265555Sambrisko 1193272744Skadesai /* Logical block reference tag */ 1194272744Skadesai io_request->CDB.EEDP32.PrimaryReferenceTag = swap32(ref_tag); 1195272744Skadesai io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0xffff; 1196272744Skadesai io_request->IoFlags = 32; /* Specify 32-byte cdb */ 1197265555Sambrisko 1198272744Skadesai /* Transfer length */ 1199272744Skadesai cdb[28] = (u_int8_t)((num_blocks >> 24) & 0xff); 1200272744Skadesai cdb[29] = (u_int8_t)((num_blocks >> 16) & 0xff); 1201272744Skadesai cdb[30] = (u_int8_t)((num_blocks >> 8) & 0xff); 1202272744Skadesai cdb[31] = (u_int8_t)(num_blocks & 0xff); 1203265555Sambrisko 1204272744Skadesai /* set SCSI IO EEDP Flags */ 1205272744Skadesai if (ccb_h->flags == CAM_DIR_OUT) { 1206272744Skadesai io_request->EEDPFlags = 1207272744Skadesai MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | 1208272744Skadesai MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | 1209272744Skadesai MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP | 1210272744Skadesai MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG | 1211272744Skadesai MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; 1212272744Skadesai } else { 1213272744Skadesai io_request->EEDPFlags = 1214272744Skadesai MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | 1215272744Skadesai MPI2_SCSIIO_EEDPFLAGS_INSERT_OP; 1216272744Skadesai } 1217272744Skadesai io_request->Control |= (0x4 << 26); 1218272744Skadesai io_request->EEDPBlockSize = ld_block_size; 1219272744Skadesai } else { 1220272744Skadesai /* Some drives don't support 16/12 byte CDB's, convert to 10 */ 1221272744Skadesai if (((cdb_len == 12) || (cdb_len == 16)) && 1222272744Skadesai (start_blk <= 0xffffffff)) { 1223272744Skadesai if (cdb_len == 16) { 1224272744Skadesai opcode = cdb[0] == READ_16 ? READ_10 : WRITE_10; 1225272744Skadesai flagvals = cdb[1]; 1226272744Skadesai groupnum = cdb[14]; 1227272744Skadesai control = cdb[15]; 1228272744Skadesai } else { 1229272744Skadesai opcode = cdb[0] == READ_12 ? READ_10 : WRITE_10; 1230272744Skadesai flagvals = cdb[1]; 1231272744Skadesai groupnum = cdb[10]; 1232272744Skadesai control = cdb[11]; 1233272744Skadesai } 1234265555Sambrisko 1235272744Skadesai memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1236265555Sambrisko 1237272744Skadesai cdb[0] = opcode; 1238272744Skadesai cdb[1] = flagvals; 1239272744Skadesai cdb[6] = groupnum; 1240272744Skadesai cdb[9] = control; 1241265555Sambrisko 1242272744Skadesai /* Transfer length */ 1243272744Skadesai cdb[8] = (u_int8_t)(num_blocks & 0xff); 1244272744Skadesai cdb[7] = (u_int8_t)((num_blocks >> 8) & 0xff); 1245265555Sambrisko 1246272744Skadesai io_request->IoFlags = 10; /* Specify 10-byte cdb */ 1247272744Skadesai cdb_len = 10; 1248272744Skadesai } else if ((cdb_len < 16) && (start_blk > 0xffffffff)) { 1249272744Skadesai /* Convert to 16 byte CDB for large LBA's */ 1250272744Skadesai switch (cdb_len) { 1251272744Skadesai case 6: 1252272744Skadesai opcode = cdb[0] == READ_6 ? READ_16 : WRITE_16; 1253272744Skadesai control = cdb[5]; 1254272744Skadesai break; 1255272744Skadesai case 10: 1256272744Skadesai opcode = cdb[0] == READ_10 ? READ_16 : WRITE_16; 1257272744Skadesai flagvals = cdb[1]; 1258272744Skadesai groupnum = cdb[6]; 1259272744Skadesai control = cdb[9]; 1260272744Skadesai break; 1261272744Skadesai case 12: 1262272744Skadesai opcode = cdb[0] == READ_12 ? READ_16 : WRITE_16; 1263272744Skadesai flagvals = cdb[1]; 1264272744Skadesai groupnum = cdb[10]; 1265272744Skadesai control = cdb[11]; 1266272744Skadesai break; 1267272744Skadesai } 1268265555Sambrisko 1269272744Skadesai memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1270265555Sambrisko 1271272744Skadesai cdb[0] = opcode; 1272272744Skadesai cdb[1] = flagvals; 1273272744Skadesai cdb[14] = groupnum; 1274272744Skadesai cdb[15] = control; 1275265555Sambrisko 1276272744Skadesai /* Transfer length */ 1277272744Skadesai cdb[13] = (u_int8_t)(num_blocks & 0xff); 1278272744Skadesai cdb[12] = (u_int8_t)((num_blocks >> 8) & 0xff); 1279272744Skadesai cdb[11] = (u_int8_t)((num_blocks >> 16) & 0xff); 1280272744Skadesai cdb[10] = (u_int8_t)((num_blocks >> 24) & 0xff); 1281265555Sambrisko 1282272744Skadesai io_request->IoFlags = 16; /* Specify 16-byte cdb */ 1283272744Skadesai cdb_len = 16; 1284272744Skadesai } else if ((cdb_len == 6) && (start_blk > 0x1fffff)) { 1285272744Skadesai /* convert to 10 byte CDB */ 1286272744Skadesai opcode = cdb[0] == READ_6 ? READ_10 : WRITE_10; 1287272744Skadesai control = cdb[5]; 1288265555Sambrisko 1289272744Skadesai memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1290272744Skadesai cdb[0] = opcode; 1291272744Skadesai cdb[9] = control; 1292265555Sambrisko 1293272744Skadesai /* Set transfer length */ 1294272744Skadesai cdb[8] = (u_int8_t)(num_blocks & 0xff); 1295272744Skadesai cdb[7] = (u_int8_t)((num_blocks >> 8) & 0xff); 1296272744Skadesai 1297272744Skadesai /* Specify 10-byte cdb */ 1298272744Skadesai cdb_len = 10; 1299272744Skadesai } 1300272744Skadesai /* Fall through normal case, just load LBA here */ 1301272744Skadesai u_int8_t val = cdb[1] & 0xE0; 1302272744Skadesai switch (cdb_len) { 1303272744Skadesai case 6: 1304272744Skadesai cdb[3] = (u_int8_t)(start_blk & 0xff); 1305272744Skadesai cdb[2] = (u_int8_t)((start_blk >> 8) & 0xff); 1306272744Skadesai cdb[1] = val | ((u_int8_t)(start_blk >> 16) & 0x1f); 1307272744Skadesai break; 1308272744Skadesai case 10: 1309272744Skadesai cdb[5] = (u_int8_t)(start_blk & 0xff); 1310272744Skadesai cdb[4] = (u_int8_t)((start_blk >> 8) & 0xff); 1311272744Skadesai cdb[3] = (u_int8_t)((start_blk >> 16) & 0xff); 1312272744Skadesai cdb[2] = (u_int8_t)((start_blk >> 24) & 0xff); 1313272744Skadesai break; 1314272744Skadesai case 12: 1315272744Skadesai cdb[5] = (u_int8_t)(start_blk & 0xff); 1316272744Skadesai cdb[4] = (u_int8_t)((start_blk >> 8) & 0xff); 1317272744Skadesai cdb[3] = (u_int8_t)((start_blk >> 16) & 0xff); 1318272744Skadesai cdb[2] = (u_int8_t)((start_blk >> 24) & 0xff); 1319272744Skadesai break; 1320272744Skadesai case 16: 1321272744Skadesai cdb[9] = (u_int8_t)(start_blk & 0xff); 1322272744Skadesai cdb[8] = (u_int8_t)((start_blk >> 8) & 0xff); 1323272744Skadesai cdb[7] = (u_int8_t)((start_blk >> 16) & 0xff); 1324272744Skadesai cdb[6] = (u_int8_t)((start_blk >> 24) & 0xff); 1325272744Skadesai cdb[5] = (u_int8_t)((start_blk >> 32) & 0xff); 1326272744Skadesai cdb[4] = (u_int8_t)((start_blk >> 40) & 0xff); 1327272744Skadesai cdb[3] = (u_int8_t)((start_blk >> 48) & 0xff); 1328272744Skadesai cdb[2] = (u_int8_t)((start_blk >> 56) & 0xff); 1329272744Skadesai break; 1330272744Skadesai } 1331265555Sambrisko } 1332265555Sambrisko} 1333265555Sambrisko 1334272744Skadesai/* 1335272744Skadesai * mrsas_get_best_arm: Determine the best spindle arm 1336272744Skadesai * Inputs: Load balance info 1337265555Sambrisko * 1338265555Sambrisko * This function determines and returns the best arm by looking at the 1339265555Sambrisko * parameters of the last PD access. 1340265555Sambrisko */ 1341272744Skadesaiu_int8_t 1342272744Skadesaimrsas_get_best_arm(PLD_LOAD_BALANCE_INFO lbInfo, u_int8_t arm, 1343272744Skadesai u_int64_t block, u_int32_t count) 1344265555Sambrisko{ 1345272744Skadesai u_int16_t pend0, pend1; 1346272744Skadesai u_int64_t diff0, diff1; 1347272744Skadesai u_int8_t bestArm; 1348265555Sambrisko 1349272744Skadesai /* get the pending cmds for the data and mirror arms */ 1350272744Skadesai pend0 = atomic_read(&lbInfo->scsi_pending_cmds[0]); 1351272744Skadesai pend1 = atomic_read(&lbInfo->scsi_pending_cmds[1]); 1352265555Sambrisko 1353272744Skadesai /* Determine the disk whose head is nearer to the req. block */ 1354272744Skadesai diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[0]); 1355272744Skadesai diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[1]); 1356272744Skadesai bestArm = (diff0 <= diff1 ? 0 : 1); 1357265555Sambrisko 1358272744Skadesai if ((bestArm == arm && pend0 > pend1 + 16) || (bestArm != arm && pend1 > pend0 + 16)) 1359272744Skadesai bestArm ^= 1; 1360265555Sambrisko 1361272744Skadesai /* Update the last accessed block on the correct pd */ 1362272744Skadesai lbInfo->last_accessed_block[bestArm] = block + count - 1; 1363265555Sambrisko 1364272744Skadesai return bestArm; 1365265555Sambrisko} 1366265555Sambrisko 1367272744Skadesai/* 1368272744Skadesai * mrsas_get_updated_dev_handle: Get the update dev handle 1369272744Skadesai * Inputs: Load balance info io_info pointer 1370265555Sambrisko * 1371265555Sambrisko * This function determines and returns the updated dev handle. 1372265555Sambrisko */ 1373272744Skadesaiu_int16_t 1374272744Skadesaimrsas_get_updated_dev_handle(PLD_LOAD_BALANCE_INFO lbInfo, 1375272744Skadesai struct IO_REQUEST_INFO *io_info) 1376265555Sambrisko{ 1377272744Skadesai u_int8_t arm, old_arm; 1378272744Skadesai u_int16_t devHandle; 1379265555Sambrisko 1380272744Skadesai old_arm = lbInfo->raid1DevHandle[0] == io_info->devHandle ? 0 : 1; 1381265555Sambrisko 1382272744Skadesai /* get best new arm */ 1383272744Skadesai arm = mrsas_get_best_arm(lbInfo, old_arm, io_info->ldStartBlock, io_info->numBlocks); 1384272744Skadesai devHandle = lbInfo->raid1DevHandle[arm]; 1385272744Skadesai atomic_inc(&lbInfo->scsi_pending_cmds[arm]); 1386265555Sambrisko 1387272744Skadesai return devHandle; 1388265555Sambrisko} 1389265555Sambrisko 1390272744Skadesai/* 1391272744Skadesai * MR_GetPhyParams: Calculates arm, span, and block 1392272744Skadesai * Inputs: Adapter soft state 1393272744Skadesai * Logical drive number (LD) 1394272744Skadesai * Stripe number(stripRow) 1395272744Skadesai * Reference in stripe (stripRef) 1396265555Sambrisko * 1397272744Skadesai * Outputs: Absolute Block number in the physical disk 1398272744Skadesai * 1399272744Skadesai * This routine calculates the arm, span and block for the specified stripe and 1400272744Skadesai * reference in stripe. 1401265555Sambrisko */ 1402272744Skadesaiu_int8_t 1403272744SkadesaiMR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld, 1404272744Skadesai u_int64_t stripRow, 1405272744Skadesai u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 1406272744Skadesai RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map) 1407265555Sambrisko{ 1408272744Skadesai MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 1409272744Skadesai u_int32_t pd, arRef; 1410272744Skadesai u_int8_t physArm, span; 1411272744Skadesai u_int64_t row; 1412272744Skadesai u_int8_t retval = TRUE; 1413272744Skadesai int error_code = 0; 1414265555Sambrisko u_int64_t *pdBlock = &io_info->pdBlock; 1415272744Skadesai u_int16_t *pDevHandle = &io_info->devHandle; 1416272744Skadesai u_int32_t rowMod, armQ, arm, logArm; 1417265555Sambrisko u_int8_t do_invader = 0; 1418265555Sambrisko 1419265555Sambrisko if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) 1420265555Sambrisko do_invader = 1; 1421265555Sambrisko 1422272744Skadesai row = mega_div64_32(stripRow, raid->rowDataSize); 1423265555Sambrisko 1424272744Skadesai if (raid->level == 6) { 1425272744Skadesai /* logical arm within row */ 1426272744Skadesai logArm = mega_mod64(stripRow, raid->rowDataSize); 1427272744Skadesai if (raid->rowSize == 0) 1428272744Skadesai return FALSE; 1429272744Skadesai rowMod = mega_mod64(row, raid->rowSize); /* get logical row mod */ 1430272744Skadesai armQ = raid->rowSize - 1 - rowMod; /* index of Q drive */ 1431272744Skadesai arm = armQ + 1 + logArm;/* data always logically follows Q */ 1432272744Skadesai if (arm >= raid->rowSize) /* handle wrap condition */ 1433272744Skadesai arm -= raid->rowSize; 1434272744Skadesai physArm = (u_int8_t)arm; 1435272744Skadesai } else { 1436272744Skadesai if (raid->modFactor == 0) 1437272744Skadesai return FALSE; 1438272744Skadesai physArm = MR_LdDataArmGet(ld, mega_mod64(stripRow, raid->modFactor), map); 1439272744Skadesai } 1440265555Sambrisko 1441272744Skadesai if (raid->spanDepth == 1) { 1442272744Skadesai span = 0; 1443272744Skadesai *pdBlock = row << raid->stripeShift; 1444272744Skadesai } else { 1445272744Skadesai span = (u_int8_t)MR_GetSpanBlock(ld, row, pdBlock, map, &error_code); 1446272744Skadesai if (error_code == 1) 1447272744Skadesai return FALSE; 1448272744Skadesai } 1449265555Sambrisko 1450272744Skadesai /* Get the array on which this span is present */ 1451272744Skadesai arRef = MR_LdSpanArrayGet(ld, span, map); 1452265555Sambrisko 1453272744Skadesai pd = MR_ArPdGet(arRef, physArm, map); /* Get the Pd. */ 1454265555Sambrisko 1455272744Skadesai if (pd != MR_PD_INVALID) 1456272744Skadesai /* Get dev handle from Pd */ 1457272744Skadesai *pDevHandle = MR_PdDevHandleGet(pd, map); 1458272744Skadesai else { 1459272744Skadesai *pDevHandle = MR_PD_INVALID; /* set dev handle as invalid. */ 1460272744Skadesai if ((raid->level >= 5) && ((!do_invader) || (do_invader && 1461272744Skadesai raid->regTypeReqOnRead != REGION_TYPE_UNUSED))) 1462272744Skadesai pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; 1463272744Skadesai else if (raid->level == 1) { 1464272744Skadesai /* Get Alternate Pd. */ 1465272744Skadesai pd = MR_ArPdGet(arRef, physArm + 1, map); 1466272744Skadesai if (pd != MR_PD_INVALID) 1467272744Skadesai /* Get dev handle from Pd. */ 1468272744Skadesai *pDevHandle = MR_PdDevHandleGet(pd, map); 1469272744Skadesai } 1470272744Skadesai } 1471265555Sambrisko 1472272744Skadesai *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk; 1473272744Skadesai pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; 1474272744Skadesai return retval; 1475265555Sambrisko} 1476265555Sambrisko 1477272744Skadesai/* 1478272744Skadesai * MR_GetSpanBlock: Calculates span block 1479272744Skadesai * Inputs: LD 1480272744Skadesai * row PD 1481272744Skadesai * span block 1482272744Skadesai * RAID map pointer 1483265555Sambrisko * 1484272744Skadesai * Outputs: Span number Error code 1485272744Skadesai * 1486272744Skadesai * This routine calculates the span from the span block info. 1487265555Sambrisko */ 1488272744Skadesaiu_int32_t 1489272744SkadesaiMR_GetSpanBlock(u_int32_t ld, u_int64_t row, u_int64_t *span_blk, 1490272744Skadesai MR_DRV_RAID_MAP_ALL * map, int *div_error) 1491265555Sambrisko{ 1492272744Skadesai MR_SPAN_BLOCK_INFO *pSpanBlock = MR_LdSpanInfoGet(ld, map); 1493272744Skadesai MR_QUAD_ELEMENT *quad; 1494272744Skadesai MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 1495272744Skadesai u_int32_t span, j; 1496272744Skadesai u_int64_t blk, debugBlk; 1497265555Sambrisko 1498272744Skadesai for (span = 0; span < raid->spanDepth; span++, pSpanBlock++) { 1499272744Skadesai for (j = 0; j < pSpanBlock->block_span_info.noElements; j++) { 1500272744Skadesai quad = &pSpanBlock->block_span_info.quad[j]; 1501272744Skadesai if (quad->diff == 0) { 1502272744Skadesai *div_error = 1; 1503272744Skadesai return span; 1504272744Skadesai } 1505272744Skadesai if (quad->logStart <= row && row <= quad->logEnd && 1506272744Skadesai (mega_mod64(row - quad->logStart, quad->diff)) == 0) { 1507272744Skadesai if (span_blk != NULL) { 1508272744Skadesai blk = mega_div64_32((row - quad->logStart), quad->diff); 1509272744Skadesai debugBlk = blk; 1510272744Skadesai blk = (blk + quad->offsetInSpan) << raid->stripeShift; 1511272744Skadesai *span_blk = blk; 1512272744Skadesai } 1513272744Skadesai return span; 1514272744Skadesai } 1515272744Skadesai } 1516272744Skadesai } 1517272744Skadesai return span; 1518265555Sambrisko} 1519