1265555Sambrisko/* 2284267Skadesai * Copyright (c) 2015, AVAGO Tech. All rights reserved. Author: Marian Choy 3275976Ssmh * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy 4284267Skadesai * Support: freebsdraid@avagotech.com 5265555Sambrisko * 6265555Sambrisko * Redistribution and use in source and binary forms, with or without 7275976Ssmh * modification, are permitted provided that the following conditions are 8275976Ssmh * met: 9265555Sambrisko * 10275976Ssmh * 1. Redistributions of source code must retain the above copyright notice, 11275976Ssmh * this list of conditions and the following disclaimer. 2. Redistributions 12275976Ssmh * in binary form must reproduce the above copyright notice, this list of 13275976Ssmh * conditions and the following disclaimer in the documentation and/or other 14275976Ssmh * materials provided with the distribution. 3. Neither the name of the 15275976Ssmh * <ORGANIZATION> nor the names of its contributors may be used to endorse or 16275976Ssmh * promote products derived from this software without specific prior written 17275976Ssmh * permission. 18265555Sambrisko * 19275976Ssmh * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20275976Ssmh * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21275976Ssmh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22275976Ssmh * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23275976Ssmh * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24275976Ssmh * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25275976Ssmh * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26275976Ssmh * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27275976Ssmh * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28275976Ssmh * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29265555Sambrisko * POSSIBILITY OF SUCH DAMAGE. 30265555Sambrisko * 31275976Ssmh * The views and conclusions contained in the software and documentation are 32275976Ssmh * those of the authors and should not be interpreted as representing 33265555Sambrisko * official policies,either expressed or implied, of the FreeBSD Project. 34265555Sambrisko * 35284267Skadesai * Send feedback to: <megaraidfbsd@avagotech.com> Mail to: AVAGO TECHNOLOGIES, 1621 36275976Ssmh * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD 37265555Sambrisko * 38265555Sambrisko */ 39265555Sambrisko 40265555Sambrisko#include <sys/cdefs.h> 41265555Sambrisko__FBSDID("$FreeBSD: stable/10/sys/dev/mrsas/mrsas_fp.c 310264 2016-12-19 13:14:39Z kadesai $"); 42265555Sambrisko 43265555Sambrisko#include <dev/mrsas/mrsas.h> 44265555Sambrisko 45265555Sambrisko#include <cam/cam.h> 46265555Sambrisko#include <cam/cam_ccb.h> 47265555Sambrisko#include <cam/cam_sim.h> 48265555Sambrisko#include <cam/cam_xpt_sim.h> 49265555Sambrisko#include <cam/cam_debug.h> 50265555Sambrisko#include <cam/cam_periph.h> 51265555Sambrisko#include <cam/cam_xpt_periph.h> 52265555Sambrisko 53265555Sambrisko 54265555Sambrisko/* 55265555Sambrisko * Function prototypes 56265555Sambrisko */ 57265555Sambriskou_int8_t MR_ValidateMapInfo(struct mrsas_softc *sc); 58275976Ssmhu_int8_t 59284267Skadesaimrsas_get_best_arm_pd(struct mrsas_softc *sc, 60284267Skadesai PLD_LOAD_BALANCE_INFO lbInfo, struct IO_REQUEST_INFO *io_info); 61284267Skadesaiu_int8_t 62275976SsmhMR_BuildRaidContext(struct mrsas_softc *sc, 63275976Ssmh struct IO_REQUEST_INFO *io_info, 64275976Ssmh RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map); 65284267Skadesaiu_int8_t 66275976SsmhMR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld, 67275976Ssmh u_int64_t stripRow, u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 68275976Ssmh RAID_CONTEXT * pRAID_Context, 69275976Ssmh MR_DRV_RAID_MAP_ALL * map); 70275976Ssmhu_int16_t MR_TargetIdToLdGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map); 71275976Ssmhu_int32_t MR_LdBlockSizeGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map); 72275976Ssmhu_int16_t MR_GetLDTgtId(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map); 73275976Ssmhu_int16_t 74284267Skadesaimrsas_get_updated_dev_handle(struct mrsas_softc *sc, 75284267Skadesai PLD_LOAD_BALANCE_INFO lbInfo, struct IO_REQUEST_INFO *io_info); 76265555Sambriskou_int32_t mega_mod64(u_int64_t dividend, u_int32_t divisor); 77284267Skadesaiu_int32_t 78275976SsmhMR_GetSpanBlock(u_int32_t ld, u_int64_t row, u_int64_t *span_blk, 79275976Ssmh MR_DRV_RAID_MAP_ALL * map, int *div_error); 80265555Sambriskou_int64_t mega_div64_32(u_int64_t dividend, u_int32_t divisor); 81275976Ssmhvoid 82284267Skadesaimrsas_update_load_balance_params(struct mrsas_softc *sc, 83284267Skadesai MR_DRV_RAID_MAP_ALL * map, PLD_LOAD_BALANCE_INFO lbInfo); 84284267Skadesaivoid 85275976Ssmhmrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request, 86275976Ssmh u_int8_t cdb_len, struct IO_REQUEST_INFO *io_info, union ccb *ccb, 87275976Ssmh MR_DRV_RAID_MAP_ALL * local_map_ptr, u_int32_t ref_tag, 88275976Ssmh u_int32_t ld_block_size); 89284267Skadesaistatic u_int16_t 90275976SsmhMR_LdSpanArrayGet(u_int32_t ld, u_int32_t span, 91275976Ssmh MR_DRV_RAID_MAP_ALL * map); 92275976Ssmhstatic u_int16_t MR_PdDevHandleGet(u_int32_t pd, MR_DRV_RAID_MAP_ALL * map); 93284267Skadesaistatic u_int16_t 94275976SsmhMR_ArPdGet(u_int32_t ar, u_int32_t arm, 95275976Ssmh MR_DRV_RAID_MAP_ALL * map); 96275976Ssmhstatic MR_LD_SPAN * 97275976SsmhMR_LdSpanPtrGet(u_int32_t ld, u_int32_t span, 98275976Ssmh MR_DRV_RAID_MAP_ALL * map); 99284267Skadesaistatic u_int8_t 100275976SsmhMR_LdDataArmGet(u_int32_t ld, u_int32_t armIdx, 101275976Ssmh MR_DRV_RAID_MAP_ALL * map); 102275976Ssmhstatic MR_SPAN_BLOCK_INFO * 103275976SsmhMR_LdSpanInfoGet(u_int32_t ld, 104275976Ssmh MR_DRV_RAID_MAP_ALL * map); 105275976SsmhMR_LD_RAID *MR_LdRaidGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map); 106275976Ssmhvoid MR_PopulateDrvRaidMap(struct mrsas_softc *sc); 107265555Sambrisko 108275976Ssmh 109265555Sambrisko/* 110275976Ssmh * Spanset related function prototypes Added for PRL11 configuration (Uneven 111275976Ssmh * span support) 112265555Sambrisko */ 113275976Ssmhvoid mr_update_span_set(MR_DRV_RAID_MAP_ALL * map, PLD_SPAN_INFO ldSpanInfo); 114275976Ssmhstatic u_int8_t 115275976Ssmhmr_spanset_get_phy_params(struct mrsas_softc *sc, u_int32_t ld, 116275976Ssmh u_int64_t stripRow, u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 117275976Ssmh RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map); 118275976Ssmhstatic u_int64_t 119275976Ssmhget_row_from_strip(struct mrsas_softc *sc, u_int32_t ld, 120275976Ssmh u_int64_t strip, MR_DRV_RAID_MAP_ALL * map); 121275976Ssmhstatic u_int32_t 122275976Ssmhmr_spanset_get_span_block(struct mrsas_softc *sc, 123275976Ssmh u_int32_t ld, u_int64_t row, u_int64_t *span_blk, 124275976Ssmh MR_DRV_RAID_MAP_ALL * map, int *div_error); 125275976Ssmhstatic u_int8_t 126275976Ssmhget_arm(struct mrsas_softc *sc, u_int32_t ld, u_int8_t span, 127275976Ssmh u_int64_t stripe, MR_DRV_RAID_MAP_ALL * map); 128265555Sambrisko 129265555Sambrisko 130265555Sambrisko/* 131275976Ssmh * Spanset related defines Added for PRL11 configuration(Uneven span support) 132265555Sambrisko */ 133275976Ssmh#define SPAN_ROW_SIZE(map, ld, index_) MR_LdSpanPtrGet(ld, index_, map)->spanRowSize 134275976Ssmh#define SPAN_ROW_DATA_SIZE(map_, ld, index_) \ 135275976Ssmh MR_LdSpanPtrGet(ld, index_, map)->spanRowDataSize 136275976Ssmh#define SPAN_INVALID 0xff 137275976Ssmh#define SPAN_DEBUG 0 138265555Sambrisko 139265555Sambrisko/* 140265555Sambrisko * Related Defines 141265555Sambrisko */ 142265555Sambrisko 143275976Ssmhtypedef u_int64_t REGION_KEY; 144275976Ssmhtypedef u_int32_t REGION_LEN; 145265555Sambrisko 146275976Ssmh#define MR_LD_STATE_OPTIMAL 3 147275976Ssmh#define FALSE 0 148275976Ssmh#define TRUE 1 149265555Sambrisko 150284267Skadesai#define LB_PENDING_CMDS_DEFAULT 4 151265555Sambrisko 152284267Skadesai 153265555Sambrisko/* 154265555Sambrisko * Related Macros 155265555Sambrisko */ 156265555Sambrisko 157275976Ssmh#define ABS_DIFF(a,b) ( ((a) > (b)) ? ((a) - (b)) : ((b) - (a)) ) 158265555Sambrisko 159275976Ssmh#define swap32(x) \ 160265555Sambrisko ((unsigned int)( \ 161265555Sambrisko (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \ 162265555Sambrisko (((unsigned int)(x) & (unsigned int)0x0000ff00UL) << 8) | \ 163265555Sambrisko (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >> 8) | \ 164265555Sambrisko (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) )) 165265555Sambrisko 166265555Sambrisko 167265555Sambrisko/* 168275976Ssmh * In-line functions for mod and divide of 64-bit dividend and 32-bit 169275976Ssmh * divisor. Assumes a check for a divisor of zero is not possible. 170275976Ssmh * 171275976Ssmh * @param dividend: Dividend 172275976Ssmh * @param divisor: Divisor 173275976Ssmh * @return remainder 174265555Sambrisko */ 175265555Sambrisko 176275976Ssmh#define mega_mod64(dividend, divisor) ({ \ 177265555Sambriskoint remainder; \ 178265555Sambriskoremainder = ((u_int64_t) (dividend)) % (u_int32_t) (divisor); \ 179265555Sambriskoremainder;}) 180265555Sambrisko 181275976Ssmh#define mega_div64_32(dividend, divisor) ({ \ 182265555Sambriskoint quotient; \ 183265555Sambriskoquotient = ((u_int64_t) (dividend)) / (u_int32_t) (divisor); \ 184265555Sambriskoquotient;}) 185265555Sambrisko 186265555Sambrisko 187265555Sambrisko/* 188265555Sambrisko * Various RAID map access functions. These functions access the various 189275976Ssmh * parts of the RAID map and returns the appropriate parameters. 190265555Sambrisko */ 191265555Sambrisko 192275976SsmhMR_LD_RAID * 193275976SsmhMR_LdRaidGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map) 194265555Sambrisko{ 195275976Ssmh return (&map->raidMap.ldSpanMap[ld].ldRaid); 196265555Sambrisko} 197265555Sambrisko 198275976Ssmhu_int16_t 199275976SsmhMR_GetLDTgtId(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map) 200265555Sambrisko{ 201275976Ssmh return (map->raidMap.ldSpanMap[ld].ldRaid.targetId); 202265555Sambrisko} 203265555Sambrisko 204275976Ssmhstatic u_int16_t 205275976SsmhMR_LdSpanArrayGet(u_int32_t ld, u_int32_t span, MR_DRV_RAID_MAP_ALL * map) 206265555Sambrisko{ 207275976Ssmh return map->raidMap.ldSpanMap[ld].spanBlock[span].span.arrayRef; 208265555Sambrisko} 209265555Sambrisko 210275976Ssmhstatic u_int8_t 211275976SsmhMR_LdDataArmGet(u_int32_t ld, u_int32_t armIdx, MR_DRV_RAID_MAP_ALL * map) 212265555Sambrisko{ 213275976Ssmh return map->raidMap.ldSpanMap[ld].dataArmMap[armIdx]; 214265555Sambrisko} 215265555Sambrisko 216275976Ssmhstatic u_int16_t 217275976SsmhMR_PdDevHandleGet(u_int32_t pd, MR_DRV_RAID_MAP_ALL * map) 218265555Sambrisko{ 219275976Ssmh return map->raidMap.devHndlInfo[pd].curDevHdl; 220265555Sambrisko} 221265555Sambrisko 222275976Ssmhstatic u_int16_t 223275976SsmhMR_ArPdGet(u_int32_t ar, u_int32_t arm, MR_DRV_RAID_MAP_ALL * map) 224265555Sambrisko{ 225275976Ssmh return map->raidMap.arMapInfo[ar].pd[arm]; 226265555Sambrisko} 227265555Sambrisko 228275976Ssmhstatic MR_LD_SPAN * 229275976SsmhMR_LdSpanPtrGet(u_int32_t ld, u_int32_t span, MR_DRV_RAID_MAP_ALL * map) 230265555Sambrisko{ 231275976Ssmh return &map->raidMap.ldSpanMap[ld].spanBlock[span].span; 232265555Sambrisko} 233265555Sambrisko 234275976Ssmhstatic MR_SPAN_BLOCK_INFO * 235275976SsmhMR_LdSpanInfoGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map) 236265555Sambrisko{ 237275976Ssmh return &map->raidMap.ldSpanMap[ld].spanBlock[0]; 238265555Sambrisko} 239265555Sambrisko 240275976Ssmhu_int16_t 241275976SsmhMR_TargetIdToLdGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map) 242265555Sambrisko{ 243275976Ssmh return map->raidMap.ldTgtIdToLd[ldTgtId]; 244265555Sambrisko} 245265555Sambrisko 246275976Ssmhu_int32_t 247275976SsmhMR_LdBlockSizeGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map) 248265555Sambrisko{ 249275976Ssmh MR_LD_RAID *raid; 250275976Ssmh u_int32_t ld, ldBlockSize = MRSAS_SCSIBLOCKSIZE; 251265555Sambrisko 252275976Ssmh ld = MR_TargetIdToLdGet(ldTgtId, map); 253265555Sambrisko 254275976Ssmh /* 255275976Ssmh * Check if logical drive was removed. 256275976Ssmh */ 257275976Ssmh if (ld >= MAX_LOGICAL_DRIVES) 258275976Ssmh return ldBlockSize; 259265555Sambrisko 260275976Ssmh raid = MR_LdRaidGet(ld, map); 261275976Ssmh ldBlockSize = raid->logicalBlockLength; 262275976Ssmh if (!ldBlockSize) 263275976Ssmh ldBlockSize = MRSAS_SCSIBLOCKSIZE; 264265555Sambrisko 265275976Ssmh return ldBlockSize; 266265555Sambrisko} 267265555Sambrisko 268275976Ssmh/* 269275976Ssmh * This function will Populate Driver Map using firmware raid map 270275976Ssmh */ 271275976Ssmhvoid 272275976SsmhMR_PopulateDrvRaidMap(struct mrsas_softc *sc) 273275976Ssmh{ 274275976Ssmh MR_FW_RAID_MAP_ALL *fw_map_old = NULL; 275275976Ssmh MR_FW_RAID_MAP *pFwRaidMap = NULL; 276275976Ssmh unsigned int i; 277275976Ssmh 278275976Ssmh MR_DRV_RAID_MAP_ALL *drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 279275976Ssmh MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap; 280275976Ssmh 281275976Ssmh if (sc->max256vdSupport) { 282275976Ssmh memcpy(sc->ld_drv_map[sc->map_id & 1], 283275976Ssmh sc->raidmap_mem[sc->map_id & 1], 284275976Ssmh sc->current_map_sz); 285275976Ssmh /* 286275976Ssmh * New Raid map will not set totalSize, so keep expected 287275976Ssmh * value for legacy code in ValidateMapInfo 288275976Ssmh */ 289275976Ssmh pDrvRaidMap->totalSize = sizeof(MR_FW_RAID_MAP_EXT); 290275976Ssmh } else { 291275976Ssmh fw_map_old = (MR_FW_RAID_MAP_ALL *) sc->raidmap_mem[(sc->map_id & 1)]; 292275976Ssmh pFwRaidMap = &fw_map_old->raidMap; 293275976Ssmh 294275976Ssmh#if VD_EXT_DEBUG 295275976Ssmh for (i = 0; i < pFwRaidMap->ldCount; i++) { 296275976Ssmh device_printf(sc->mrsas_dev, 297275976Ssmh "Index 0x%x Target Id 0x%x Seq Num 0x%x Size 0/%lx\n", i, 298275976Ssmh fw_map_old->raidMap.ldSpanMap[i].ldRaid.targetId, 299275976Ssmh fw_map_old->raidMap.ldSpanMap[i].ldRaid.seqNum, 300275976Ssmh fw_map_old->raidMap.ldSpanMap[i].ldRaid.size); 301275976Ssmh } 302275976Ssmh#endif 303275976Ssmh 304275976Ssmh memset(drv_map, 0, sc->drv_map_sz); 305275976Ssmh pDrvRaidMap->totalSize = pFwRaidMap->totalSize; 306275976Ssmh pDrvRaidMap->ldCount = pFwRaidMap->ldCount; 307275976Ssmh pDrvRaidMap->fpPdIoTimeoutSec = 308275976Ssmh pFwRaidMap->fpPdIoTimeoutSec; 309275976Ssmh 310275976Ssmh for (i = 0; i < MAX_RAIDMAP_LOGICAL_DRIVES + MAX_RAIDMAP_VIEWS; i++) { 311275976Ssmh pDrvRaidMap->ldTgtIdToLd[i] = 312275976Ssmh (u_int8_t)pFwRaidMap->ldTgtIdToLd[i]; 313275976Ssmh } 314275976Ssmh 315275976Ssmh for (i = 0; i < pDrvRaidMap->ldCount; i++) { 316275976Ssmh pDrvRaidMap->ldSpanMap[i] = 317275976Ssmh pFwRaidMap->ldSpanMap[i]; 318275976Ssmh 319275976Ssmh#if VD_EXT_DEBUG 320275976Ssmh device_printf(sc->mrsas_dev, "pFwRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x " 321275976Ssmh "pFwRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x size 0x%x\n", 322275976Ssmh i, i, pFwRaidMap->ldSpanMap[i].ldRaid.targetId, 323275976Ssmh pFwRaidMap->ldSpanMap[i].ldRaid.seqNum, 324275976Ssmh (u_int32_t)pFwRaidMap->ldSpanMap[i].ldRaid.rowSize); 325275976Ssmh device_printf(sc->mrsas_dev, "pDrvRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x" 326275976Ssmh "pDrvRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x size 0x%x\n", i, i, 327275976Ssmh pDrvRaidMap->ldSpanMap[i].ldRaid.targetId, 328275976Ssmh pDrvRaidMap->ldSpanMap[i].ldRaid.seqNum, 329275976Ssmh (u_int32_t)pDrvRaidMap->ldSpanMap[i].ldRaid.rowSize); 330275976Ssmh device_printf(sc->mrsas_dev, "drv raid map all %p raid map %p LD RAID MAP %p/%p\n", 331275976Ssmh drv_map, pDrvRaidMap, 332275976Ssmh &pFwRaidMap->ldSpanMap[i].ldRaid, &pDrvRaidMap->ldSpanMap[i].ldRaid); 333275976Ssmh#endif 334275976Ssmh } 335275976Ssmh 336275976Ssmh memcpy(pDrvRaidMap->arMapInfo, pFwRaidMap->arMapInfo, 337275976Ssmh sizeof(MR_ARRAY_INFO) * MAX_RAIDMAP_ARRAYS); 338275976Ssmh memcpy(pDrvRaidMap->devHndlInfo, pFwRaidMap->devHndlInfo, 339275976Ssmh sizeof(MR_DEV_HANDLE_INFO) * 340275976Ssmh MAX_RAIDMAP_PHYSICAL_DEVICES); 341275976Ssmh } 342275976Ssmh} 343275976Ssmh 344275976Ssmh/* 345275976Ssmh * MR_ValidateMapInfo: Validate RAID map 346275976Ssmh * input: Adapter instance soft state 347265555Sambrisko * 348275976Ssmh * This function checks and validates the loaded RAID map. It returns 0 if 349265555Sambrisko * successful, and 1 otherwise. 350265555Sambrisko */ 351275976Ssmhu_int8_t 352275976SsmhMR_ValidateMapInfo(struct mrsas_softc *sc) 353265555Sambrisko{ 354265555Sambrisko if (!sc) { 355265555Sambrisko return 1; 356265555Sambrisko } 357275976Ssmh MR_PopulateDrvRaidMap(sc); 358265555Sambrisko 359275976Ssmh MR_DRV_RAID_MAP_ALL *drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 360275976Ssmh MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap; 361265555Sambrisko 362275976Ssmh u_int32_t expected_map_size; 363265555Sambrisko 364275976Ssmh drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 365275976Ssmh pDrvRaidMap = &drv_map->raidMap; 366275976Ssmh PLD_SPAN_INFO ldSpanInfo = (PLD_SPAN_INFO) & sc->log_to_span; 367275976Ssmh 368275976Ssmh if (sc->max256vdSupport) 369275976Ssmh expected_map_size = sizeof(MR_FW_RAID_MAP_EXT); 370275976Ssmh else 371275976Ssmh expected_map_size = 372275976Ssmh (sizeof(MR_FW_RAID_MAP) - sizeof(MR_LD_SPAN_MAP)) + 373275976Ssmh (sizeof(MR_LD_SPAN_MAP) * pDrvRaidMap->ldCount); 374275976Ssmh 375275976Ssmh if (pDrvRaidMap->totalSize != expected_map_size) { 376275976Ssmh device_printf(sc->mrsas_dev, "map size %x not matching ld count\n", expected_map_size); 377275976Ssmh device_printf(sc->mrsas_dev, "span map= %x\n", (unsigned int)sizeof(MR_LD_SPAN_MAP)); 378275976Ssmh device_printf(sc->mrsas_dev, "pDrvRaidMap->totalSize=%x\n", pDrvRaidMap->totalSize); 379275976Ssmh return 1; 380265555Sambrisko } 381275976Ssmh if (sc->UnevenSpanSupport) { 382275976Ssmh mr_update_span_set(drv_map, ldSpanInfo); 383275976Ssmh } 384284267Skadesai mrsas_update_load_balance_params(sc, drv_map, sc->load_balance_info); 385265555Sambrisko 386275976Ssmh return 0; 387265555Sambrisko} 388265555Sambrisko 389265555Sambrisko/* 390275976Ssmh * 391275976Ssmh * Function to print info about span set created in driver from FW raid map 392275976Ssmh * 393275976Ssmh * Inputs: map 394275976Ssmh * ldSpanInfo: ld map span info per HBA instance 395275976Ssmh * 396275976Ssmh * 397275976Ssmh */ 398265555Sambrisko#if SPAN_DEBUG 399275976Ssmhstatic int 400275976SsmhgetSpanInfo(MR_DRV_RAID_MAP_ALL * map, PLD_SPAN_INFO ldSpanInfo) 401265555Sambrisko{ 402265555Sambrisko 403275976Ssmh u_int8_t span; 404275976Ssmh u_int32_t element; 405275976Ssmh MR_LD_RAID *raid; 406275976Ssmh LD_SPAN_SET *span_set; 407275976Ssmh MR_QUAD_ELEMENT *quad; 408275976Ssmh int ldCount; 409275976Ssmh u_int16_t ld; 410265555Sambrisko 411275976Ssmh for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) { 412275976Ssmh ld = MR_TargetIdToLdGet(ldCount, map); 413275976Ssmh if (ld >= MAX_LOGICAL_DRIVES) { 414275976Ssmh continue; 415275976Ssmh } 416275976Ssmh raid = MR_LdRaidGet(ld, map); 417275976Ssmh printf("LD %x: span_depth=%x\n", ld, raid->spanDepth); 418275976Ssmh for (span = 0; span < raid->spanDepth; span++) 419275976Ssmh printf("Span=%x, number of quads=%x\n", span, 420275976Ssmh map->raidMap.ldSpanMap[ld].spanBlock[span]. 421275976Ssmh block_span_info.noElements); 422275976Ssmh for (element = 0; element < MAX_QUAD_DEPTH; element++) { 423275976Ssmh span_set = &(ldSpanInfo[ld].span_set[element]); 424275976Ssmh if (span_set->span_row_data_width == 0) 425275976Ssmh break; 426265555Sambrisko 427275976Ssmh printf("Span Set %x: width=%x, diff=%x\n", element, 428275976Ssmh (unsigned int)span_set->span_row_data_width, 429275976Ssmh (unsigned int)span_set->diff); 430275976Ssmh printf("logical LBA start=0x%08lx, end=0x%08lx\n", 431275976Ssmh (long unsigned int)span_set->log_start_lba, 432275976Ssmh (long unsigned int)span_set->log_end_lba); 433275976Ssmh printf("span row start=0x%08lx, end=0x%08lx\n", 434275976Ssmh (long unsigned int)span_set->span_row_start, 435275976Ssmh (long unsigned int)span_set->span_row_end); 436275976Ssmh printf("data row start=0x%08lx, end=0x%08lx\n", 437275976Ssmh (long unsigned int)span_set->data_row_start, 438275976Ssmh (long unsigned int)span_set->data_row_end); 439275976Ssmh printf("data strip start=0x%08lx, end=0x%08lx\n", 440275976Ssmh (long unsigned int)span_set->data_strip_start, 441275976Ssmh (long unsigned int)span_set->data_strip_end); 442275976Ssmh 443275976Ssmh for (span = 0; span < raid->spanDepth; span++) { 444275976Ssmh if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 445275976Ssmh block_span_info.noElements >= element + 1) { 446275976Ssmh quad = &map->raidMap.ldSpanMap[ld]. 447275976Ssmh spanBlock[span].block_span_info. 448275976Ssmh quad[element]; 449275976Ssmh printf("Span=%x, Quad=%x, diff=%x\n", span, 450275976Ssmh element, quad->diff); 451275976Ssmh printf("offset_in_span=0x%08lx\n", 452275976Ssmh (long unsigned int)quad->offsetInSpan); 453275976Ssmh printf("logical start=0x%08lx, end=0x%08lx\n", 454275976Ssmh (long unsigned int)quad->logStart, 455275976Ssmh (long unsigned int)quad->logEnd); 456275976Ssmh } 457275976Ssmh } 458275976Ssmh } 459275976Ssmh } 460275976Ssmh return 0; 461265555Sambrisko} 462275976Ssmh 463265555Sambrisko#endif 464265555Sambrisko/* 465275976Ssmh * 466275976Ssmh * This routine calculates the Span block for given row using spanset. 467275976Ssmh * 468275976Ssmh * Inputs : HBA instance 469275976Ssmh * ld: Logical drive number 470275976Ssmh * row: Row number 471275976Ssmh * map: LD map 472275976Ssmh * 473275976Ssmh * Outputs : span - Span number block 474275976Ssmh * - Absolute Block number in the physical disk 475275976Ssmh * div_error - Devide error code. 476275976Ssmh */ 477265555Sambrisko 478275976Ssmhu_int32_t 479275976Ssmhmr_spanset_get_span_block(struct mrsas_softc *sc, u_int32_t ld, u_int64_t row, 480275976Ssmh u_int64_t *span_blk, MR_DRV_RAID_MAP_ALL * map, int *div_error) 481265555Sambrisko{ 482275976Ssmh MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 483275976Ssmh LD_SPAN_SET *span_set; 484275976Ssmh MR_QUAD_ELEMENT *quad; 485275976Ssmh u_int32_t span, info; 486275976Ssmh PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 487265555Sambrisko 488275976Ssmh for (info = 0; info < MAX_QUAD_DEPTH; info++) { 489275976Ssmh span_set = &(ldSpanInfo[ld].span_set[info]); 490265555Sambrisko 491275976Ssmh if (span_set->span_row_data_width == 0) 492275976Ssmh break; 493275976Ssmh if (row > span_set->data_row_end) 494275976Ssmh continue; 495265555Sambrisko 496275976Ssmh for (span = 0; span < raid->spanDepth; span++) 497275976Ssmh if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 498275976Ssmh block_span_info.noElements >= info + 1) { 499275976Ssmh quad = &map->raidMap.ldSpanMap[ld]. 500275976Ssmh spanBlock[span]. 501275976Ssmh block_span_info.quad[info]; 502275976Ssmh if (quad->diff == 0) { 503275976Ssmh *div_error = 1; 504275976Ssmh return span; 505275976Ssmh } 506275976Ssmh if (quad->logStart <= row && 507275976Ssmh row <= quad->logEnd && 508275976Ssmh (mega_mod64(row - quad->logStart, 509275976Ssmh quad->diff)) == 0) { 510275976Ssmh if (span_blk != NULL) { 511275976Ssmh u_int64_t blk; 512275976Ssmh 513275976Ssmh blk = mega_div64_32 514275976Ssmh ((row - quad->logStart), 515275976Ssmh quad->diff); 516275976Ssmh blk = (blk + quad->offsetInSpan) 517275976Ssmh << raid->stripeShift; 518275976Ssmh *span_blk = blk; 519275976Ssmh } 520275976Ssmh return span; 521275976Ssmh } 522275976Ssmh } 523275976Ssmh } 524275976Ssmh return SPAN_INVALID; 525265555Sambrisko} 526265555Sambrisko 527265555Sambrisko/* 528275976Ssmh * 529275976Ssmh * This routine calculates the row for given strip using spanset. 530275976Ssmh * 531275976Ssmh * Inputs : HBA instance 532275976Ssmh * ld: Logical drive number 533275976Ssmh * Strip: Strip 534275976Ssmh * map: LD map 535275976Ssmh * 536275976Ssmh * Outputs : row - row associated with strip 537275976Ssmh */ 538265555Sambrisko 539275976Ssmhstatic u_int64_t 540275976Ssmhget_row_from_strip(struct mrsas_softc *sc, 541275976Ssmh u_int32_t ld, u_int64_t strip, MR_DRV_RAID_MAP_ALL * map) 542265555Sambrisko{ 543275976Ssmh MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 544275976Ssmh LD_SPAN_SET *span_set; 545275976Ssmh PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 546275976Ssmh u_int32_t info, strip_offset, span, span_offset; 547275976Ssmh u_int64_t span_set_Strip, span_set_Row; 548265555Sambrisko 549275976Ssmh for (info = 0; info < MAX_QUAD_DEPTH; info++) { 550275976Ssmh span_set = &(ldSpanInfo[ld].span_set[info]); 551265555Sambrisko 552275976Ssmh if (span_set->span_row_data_width == 0) 553275976Ssmh break; 554275976Ssmh if (strip > span_set->data_strip_end) 555275976Ssmh continue; 556265555Sambrisko 557275976Ssmh span_set_Strip = strip - span_set->data_strip_start; 558275976Ssmh strip_offset = mega_mod64(span_set_Strip, 559275976Ssmh span_set->span_row_data_width); 560275976Ssmh span_set_Row = mega_div64_32(span_set_Strip, 561275976Ssmh span_set->span_row_data_width) * span_set->diff; 562275976Ssmh for (span = 0, span_offset = 0; span < raid->spanDepth; span++) 563275976Ssmh if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 564275976Ssmh block_span_info.noElements >= info + 1) { 565275976Ssmh if (strip_offset >= 566275976Ssmh span_set->strip_offset[span]) 567275976Ssmh span_offset++; 568275976Ssmh else 569275976Ssmh break; 570275976Ssmh } 571284267Skadesai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug : Strip 0x%llx, span_set_Strip 0x%llx, span_set_Row 0x%llx " 572275976Ssmh "data width 0x%llx span offset 0x%llx\n", (unsigned long long)strip, 573275976Ssmh (unsigned long long)span_set_Strip, 574275976Ssmh (unsigned long long)span_set_Row, 575275976Ssmh (unsigned long long)span_set->span_row_data_width, (unsigned long long)span_offset); 576284267Skadesai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug : For strip 0x%llx row is 0x%llx\n", (unsigned long long)strip, 577275976Ssmh (unsigned long long)span_set->data_row_start + 578275976Ssmh (unsigned long long)span_set_Row + (span_offset - 1)); 579275976Ssmh return (span_set->data_row_start + span_set_Row + (span_offset - 1)); 580275976Ssmh } 581275976Ssmh return -1LLU; 582265555Sambrisko} 583265555Sambrisko 584265555Sambrisko 585265555Sambrisko/* 586275976Ssmh * 587275976Ssmh * This routine calculates the Start Strip for given row using spanset. 588275976Ssmh * 589275976Ssmh * Inputs: HBA instance 590275976Ssmh * ld: Logical drive number 591275976Ssmh * row: Row number 592275976Ssmh * map: LD map 593275976Ssmh * 594275976Ssmh * Outputs : Strip - Start strip associated with row 595275976Ssmh */ 596265555Sambrisko 597275976Ssmhstatic u_int64_t 598275976Ssmhget_strip_from_row(struct mrsas_softc *sc, 599275976Ssmh u_int32_t ld, u_int64_t row, MR_DRV_RAID_MAP_ALL * map) 600265555Sambrisko{ 601275976Ssmh MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 602275976Ssmh LD_SPAN_SET *span_set; 603275976Ssmh MR_QUAD_ELEMENT *quad; 604275976Ssmh PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 605275976Ssmh u_int32_t span, info; 606275976Ssmh u_int64_t strip; 607265555Sambrisko 608275976Ssmh for (info = 0; info < MAX_QUAD_DEPTH; info++) { 609275976Ssmh span_set = &(ldSpanInfo[ld].span_set[info]); 610265555Sambrisko 611275976Ssmh if (span_set->span_row_data_width == 0) 612275976Ssmh break; 613275976Ssmh if (row > span_set->data_row_end) 614275976Ssmh continue; 615265555Sambrisko 616275976Ssmh for (span = 0; span < raid->spanDepth; span++) 617275976Ssmh if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 618275976Ssmh block_span_info.noElements >= info + 1) { 619275976Ssmh quad = &map->raidMap.ldSpanMap[ld]. 620275976Ssmh spanBlock[span].block_span_info.quad[info]; 621275976Ssmh if (quad->logStart <= row && 622275976Ssmh row <= quad->logEnd && 623275976Ssmh mega_mod64((row - quad->logStart), 624275976Ssmh quad->diff) == 0) { 625275976Ssmh strip = mega_div64_32 626275976Ssmh (((row - span_set->data_row_start) 627275976Ssmh - quad->logStart), 628275976Ssmh quad->diff); 629275976Ssmh strip *= span_set->span_row_data_width; 630275976Ssmh strip += span_set->data_strip_start; 631275976Ssmh strip += span_set->strip_offset[span]; 632275976Ssmh return strip; 633275976Ssmh } 634275976Ssmh } 635275976Ssmh } 636284267Skadesai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug - get_strip_from_row: returns invalid " 637275976Ssmh "strip for ld=%x, row=%lx\n", ld, (long unsigned int)row); 638275976Ssmh return -1; 639265555Sambrisko} 640265555Sambrisko 641265555Sambrisko/* 642275976Ssmh * ***************************************************************************** 643275976Ssmh * 644275976Ssmh * 645275976Ssmh * This routine calculates the Physical Arm for given strip using spanset. 646275976Ssmh * 647275976Ssmh * Inputs : HBA instance 648275976Ssmh * Logical drive number 649275976Ssmh * Strip 650275976Ssmh * LD map 651275976Ssmh * 652275976Ssmh * Outputs : Phys Arm - Phys Arm associated with strip 653275976Ssmh */ 654265555Sambrisko 655275976Ssmhstatic u_int32_t 656275976Ssmhget_arm_from_strip(struct mrsas_softc *sc, 657275976Ssmh u_int32_t ld, u_int64_t strip, MR_DRV_RAID_MAP_ALL * map) 658265555Sambrisko{ 659275976Ssmh MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 660275976Ssmh LD_SPAN_SET *span_set; 661275976Ssmh PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 662275976Ssmh u_int32_t info, strip_offset, span, span_offset; 663265555Sambrisko 664275976Ssmh for (info = 0; info < MAX_QUAD_DEPTH; info++) { 665275976Ssmh span_set = &(ldSpanInfo[ld].span_set[info]); 666265555Sambrisko 667275976Ssmh if (span_set->span_row_data_width == 0) 668275976Ssmh break; 669275976Ssmh if (strip > span_set->data_strip_end) 670275976Ssmh continue; 671265555Sambrisko 672275976Ssmh strip_offset = (u_int32_t)mega_mod64 673275976Ssmh ((strip - span_set->data_strip_start), 674275976Ssmh span_set->span_row_data_width); 675265555Sambrisko 676275976Ssmh for (span = 0, span_offset = 0; span < raid->spanDepth; span++) 677275976Ssmh if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 678275976Ssmh block_span_info.noElements >= info + 1) { 679275976Ssmh if (strip_offset >= span_set->strip_offset[span]) 680275976Ssmh span_offset = span_set->strip_offset[span]; 681275976Ssmh else 682275976Ssmh break; 683275976Ssmh } 684284267Skadesai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO PRL11: get_arm_from_strip: " 685275976Ssmh "for ld=0x%x strip=0x%lx arm is 0x%x\n", ld, 686275976Ssmh (long unsigned int)strip, (strip_offset - span_offset)); 687275976Ssmh return (strip_offset - span_offset); 688275976Ssmh } 689265555Sambrisko 690284267Skadesai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: - get_arm_from_strip: returns invalid arm" 691275976Ssmh " for ld=%x strip=%lx\n", ld, (long unsigned int)strip); 692265555Sambrisko 693275976Ssmh return -1; 694265555Sambrisko} 695265555Sambrisko 696265555Sambrisko 697265555Sambrisko/* This Function will return Phys arm */ 698275976Ssmhu_int8_t 699275976Ssmhget_arm(struct mrsas_softc *sc, u_int32_t ld, u_int8_t span, u_int64_t stripe, 700275976Ssmh MR_DRV_RAID_MAP_ALL * map) 701265555Sambrisko{ 702275976Ssmh MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 703265555Sambrisko 704275976Ssmh /* Need to check correct default value */ 705275976Ssmh u_int32_t arm = 0; 706265555Sambrisko 707275976Ssmh switch (raid->level) { 708275976Ssmh case 0: 709275976Ssmh case 5: 710275976Ssmh case 6: 711275976Ssmh arm = mega_mod64(stripe, SPAN_ROW_SIZE(map, ld, span)); 712275976Ssmh break; 713275976Ssmh case 1: 714275976Ssmh /* start with logical arm */ 715275976Ssmh arm = get_arm_from_strip(sc, ld, stripe, map); 716275976Ssmh arm *= 2; 717275976Ssmh break; 718275976Ssmh } 719265555Sambrisko 720275976Ssmh return arm; 721265555Sambrisko} 722265555Sambrisko 723265555Sambrisko/* 724275976Ssmh * 725275976Ssmh * This routine calculates the arm, span and block for the specified stripe and 726275976Ssmh * reference in stripe using spanset 727275976Ssmh * 728284267Skadesai * Inputs : 729284267Skadesai * sc - HBA instance 730284267Skadesai * ld - Logical drive number 731284267Skadesai * stripRow: Stripe number 732284267Skadesai * stripRef: Reference in stripe 733275976Ssmh * 734275976Ssmh * Outputs : span - Span number block - Absolute Block 735275976Ssmh * number in the physical disk 736275976Ssmh */ 737275976Ssmhstatic u_int8_t 738275976Ssmhmr_spanset_get_phy_params(struct mrsas_softc *sc, u_int32_t ld, u_int64_t stripRow, 739275976Ssmh u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 740275976Ssmh RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map) 741265555Sambrisko{ 742275976Ssmh MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 743275976Ssmh u_int32_t pd, arRef; 744275976Ssmh u_int8_t physArm, span; 745275976Ssmh u_int64_t row; 746275976Ssmh u_int8_t retval = TRUE; 747275976Ssmh u_int64_t *pdBlock = &io_info->pdBlock; 748275976Ssmh u_int16_t *pDevHandle = &io_info->devHandle; 749275976Ssmh u_int32_t logArm, rowMod, armQ, arm; 750265555Sambrisko 751275976Ssmh /* Get row and span from io_info for Uneven Span IO. */ 752275976Ssmh row = io_info->start_row; 753275976Ssmh span = io_info->start_span; 754265555Sambrisko 755265555Sambrisko 756275976Ssmh if (raid->level == 6) { 757275976Ssmh logArm = get_arm_from_strip(sc, ld, stripRow, map); 758275976Ssmh rowMod = mega_mod64(row, SPAN_ROW_SIZE(map, ld, span)); 759275976Ssmh armQ = SPAN_ROW_SIZE(map, ld, span) - 1 - rowMod; 760275976Ssmh arm = armQ + 1 + logArm; 761275976Ssmh if (arm >= SPAN_ROW_SIZE(map, ld, span)) 762275976Ssmh arm -= SPAN_ROW_SIZE(map, ld, span); 763275976Ssmh physArm = (u_int8_t)arm; 764275976Ssmh } else 765275976Ssmh /* Calculate the arm */ 766275976Ssmh physArm = get_arm(sc, ld, span, stripRow, map); 767265555Sambrisko 768265555Sambrisko 769275976Ssmh arRef = MR_LdSpanArrayGet(ld, span, map); 770275976Ssmh pd = MR_ArPdGet(arRef, physArm, map); 771265555Sambrisko 772275976Ssmh if (pd != MR_PD_INVALID) 773275976Ssmh *pDevHandle = MR_PdDevHandleGet(pd, map); 774275976Ssmh else { 775275976Ssmh *pDevHandle = MR_PD_INVALID; 776310264Skadesai if ((raid->level >= 5) && ((!sc->mrsas_gen3_ctrl) || (sc->mrsas_gen3_ctrl && 777275976Ssmh raid->regTypeReqOnRead != REGION_TYPE_UNUSED))) 778275976Ssmh pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; 779275976Ssmh else if (raid->level == 1) { 780275976Ssmh pd = MR_ArPdGet(arRef, physArm + 1, map); 781275976Ssmh if (pd != MR_PD_INVALID) 782275976Ssmh *pDevHandle = MR_PdDevHandleGet(pd, map); 783275976Ssmh } 784275976Ssmh } 785275976Ssmh 786275976Ssmh *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk; 787275976Ssmh pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; 788284267Skadesai io_info->span_arm = pRAID_Context->spanArm; 789275976Ssmh return retval; 790265555Sambrisko} 791265555Sambrisko 792275976Ssmh/* 793275976Ssmh * MR_BuildRaidContext: Set up Fast path RAID context 794275976Ssmh * 795275976Ssmh * This function will initiate command processing. The start/end row and strip 796275976Ssmh * information is calculated then the lock is acquired. This function will 797275976Ssmh * return 0 if region lock was acquired OR return num strips. 798275976Ssmh */ 799275976Ssmhu_int8_t 800265555SambriskoMR_BuildRaidContext(struct mrsas_softc *sc, struct IO_REQUEST_INFO *io_info, 801275976Ssmh RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map) 802265555Sambrisko{ 803275976Ssmh MR_LD_RAID *raid; 804275976Ssmh u_int32_t ld, stripSize, stripe_mask; 805275976Ssmh u_int64_t endLba, endStrip, endRow, start_row, start_strip; 806275976Ssmh REGION_KEY regStart; 807275976Ssmh REGION_LEN regSize; 808275976Ssmh u_int8_t num_strips, numRows; 809275976Ssmh u_int16_t ref_in_start_stripe, ref_in_end_stripe; 810275976Ssmh u_int64_t ldStartBlock; 811275976Ssmh u_int32_t numBlocks, ldTgtId; 812275976Ssmh u_int8_t isRead, stripIdx; 813275976Ssmh u_int8_t retval = 0; 814265555Sambrisko u_int8_t startlba_span = SPAN_INVALID; 815275976Ssmh u_int64_t *pdBlock = &io_info->pdBlock; 816275976Ssmh int error_code = 0; 817265555Sambrisko 818275976Ssmh ldStartBlock = io_info->ldStartBlock; 819275976Ssmh numBlocks = io_info->numBlocks; 820275976Ssmh ldTgtId = io_info->ldTgtId; 821275976Ssmh isRead = io_info->isRead; 822275976Ssmh 823265555Sambrisko io_info->IoforUnevenSpan = 0; 824275976Ssmh io_info->start_span = SPAN_INVALID; 825265555Sambrisko 826275976Ssmh ld = MR_TargetIdToLdGet(ldTgtId, map); 827275976Ssmh raid = MR_LdRaidGet(ld, map); 828265555Sambrisko 829275976Ssmh if (raid->rowDataSize == 0) { 830275976Ssmh if (MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize == 0) 831275976Ssmh return FALSE; 832275976Ssmh else if (sc->UnevenSpanSupport) { 833275976Ssmh io_info->IoforUnevenSpan = 1; 834275976Ssmh } else { 835284267Skadesai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: raid->rowDataSize is 0, but has SPAN[0] rowDataSize = 0x%0x," 836275976Ssmh " but there is _NO_ UnevenSpanSupport\n", 837275976Ssmh MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize); 838275976Ssmh return FALSE; 839275976Ssmh } 840265555Sambrisko } 841275976Ssmh stripSize = 1 << raid->stripeShift; 842275976Ssmh stripe_mask = stripSize - 1; 843275976Ssmh /* 844275976Ssmh * calculate starting row and stripe, and number of strips and rows 845275976Ssmh */ 846275976Ssmh start_strip = ldStartBlock >> raid->stripeShift; 847275976Ssmh ref_in_start_stripe = (u_int16_t)(ldStartBlock & stripe_mask); 848275976Ssmh endLba = ldStartBlock + numBlocks - 1; 849275976Ssmh ref_in_end_stripe = (u_int16_t)(endLba & stripe_mask); 850275976Ssmh endStrip = endLba >> raid->stripeShift; 851275976Ssmh num_strips = (u_int8_t)(endStrip - start_strip + 1); /* End strip */ 852275976Ssmh if (io_info->IoforUnevenSpan) { 853275976Ssmh start_row = get_row_from_strip(sc, ld, start_strip, map); 854275976Ssmh endRow = get_row_from_strip(sc, ld, endStrip, map); 855275976Ssmh if (raid->spanDepth == 1) { 856275976Ssmh startlba_span = 0; 857275976Ssmh *pdBlock = start_row << raid->stripeShift; 858275976Ssmh } else { 859275976Ssmh startlba_span = (u_int8_t)mr_spanset_get_span_block(sc, ld, start_row, 860275976Ssmh pdBlock, map, &error_code); 861275976Ssmh if (error_code == 1) { 862284267Skadesai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: return from %s %d. Send IO w/o region lock.\n", 863275976Ssmh __func__, __LINE__); 864275976Ssmh return FALSE; 865275976Ssmh } 866275976Ssmh } 867275976Ssmh if (startlba_span == SPAN_INVALID) { 868284267Skadesai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: return from %s %d for row 0x%llx," 869275976Ssmh "start strip %llx endSrip %llx\n", __func__, 870275976Ssmh __LINE__, (unsigned long long)start_row, 871275976Ssmh (unsigned long long)start_strip, 872275976Ssmh (unsigned long long)endStrip); 873275976Ssmh return FALSE; 874275976Ssmh } 875275976Ssmh io_info->start_span = startlba_span; 876275976Ssmh io_info->start_row = start_row; 877284267Skadesai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: Check Span number from %s %d for row 0x%llx, " 878275976Ssmh " start strip 0x%llx endSrip 0x%llx span 0x%x\n", 879275976Ssmh __func__, __LINE__, (unsigned long long)start_row, 880275976Ssmh (unsigned long long)start_strip, 881275976Ssmh (unsigned long long)endStrip, startlba_span); 882284267Skadesai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug : 1. start_row 0x%llx endRow 0x%llx Start span 0x%x\n", 883275976Ssmh (unsigned long long)start_row, (unsigned long long)endRow, startlba_span); 884275976Ssmh } else { 885275976Ssmh start_row = mega_div64_32(start_strip, raid->rowDataSize); 886275976Ssmh endRow = mega_div64_32(endStrip, raid->rowDataSize); 887275976Ssmh } 888265555Sambrisko 889275976Ssmh numRows = (u_int8_t)(endRow - start_row + 1); /* get the row count */ 890265555Sambrisko 891275976Ssmh /* 892275976Ssmh * Calculate region info. (Assume region at start of first row, and 893275976Ssmh * assume this IO needs the full row - will adjust if not true.) 894275976Ssmh */ 895275976Ssmh regStart = start_row << raid->stripeShift; 896275976Ssmh regSize = stripSize; 897265555Sambrisko 898275976Ssmh /* Check if we can send this I/O via FastPath */ 899275976Ssmh if (raid->capability.fpCapable) { 900275976Ssmh if (isRead) 901275976Ssmh io_info->fpOkForIo = (raid->capability.fpReadCapable && 902275976Ssmh ((num_strips == 1) || 903275976Ssmh raid->capability.fpReadAcrossStripe)); 904275976Ssmh else 905275976Ssmh io_info->fpOkForIo = (raid->capability.fpWriteCapable && 906275976Ssmh ((num_strips == 1) || 907275976Ssmh raid->capability.fpWriteAcrossStripe)); 908275976Ssmh } else 909275976Ssmh io_info->fpOkForIo = FALSE; 910265555Sambrisko 911275976Ssmh if (numRows == 1) { 912275976Ssmh if (num_strips == 1) { 913275976Ssmh regStart += ref_in_start_stripe; 914275976Ssmh regSize = numBlocks; 915275976Ssmh } 916275976Ssmh } else if (io_info->IoforUnevenSpan == 0) { 917275976Ssmh /* 918275976Ssmh * For Even span region lock optimization. If the start strip 919275976Ssmh * is the last in the start row 920275976Ssmh */ 921275976Ssmh if (start_strip == (start_row + 1) * raid->rowDataSize - 1) { 922275976Ssmh regStart += ref_in_start_stripe; 923275976Ssmh /* 924275976Ssmh * initialize count to sectors from startRef to end 925275976Ssmh * of strip 926275976Ssmh */ 927275976Ssmh regSize = stripSize - ref_in_start_stripe; 928275976Ssmh } 929275976Ssmh /* add complete rows in the middle of the transfer */ 930265555Sambrisko if (numRows > 2) 931275976Ssmh regSize += (numRows - 2) << raid->stripeShift; 932265555Sambrisko 933275976Ssmh /* if IO ends within first strip of last row */ 934275976Ssmh if (endStrip == endRow * raid->rowDataSize) 935275976Ssmh regSize += ref_in_end_stripe + 1; 936275976Ssmh else 937275976Ssmh regSize += stripSize; 938275976Ssmh } else { 939275976Ssmh if (start_strip == (get_strip_from_row(sc, ld, start_row, map) + 940275976Ssmh SPAN_ROW_DATA_SIZE(map, ld, startlba_span) - 1)) { 941275976Ssmh regStart += ref_in_start_stripe; 942275976Ssmh /* 943275976Ssmh * initialize count to sectors from startRef to end 944275976Ssmh * of strip 945275976Ssmh */ 946265555Sambrisko regSize = stripSize - ref_in_start_stripe; 947275976Ssmh } 948275976Ssmh /* add complete rows in the middle of the transfer */ 949275976Ssmh if (numRows > 2) 950275976Ssmh regSize += (numRows - 2) << raid->stripeShift; 951265555Sambrisko 952275976Ssmh /* if IO ends within first strip of last row */ 953275976Ssmh if (endStrip == get_strip_from_row(sc, ld, endRow, map)) 954275976Ssmh regSize += ref_in_end_stripe + 1; 955275976Ssmh else 956275976Ssmh regSize += stripSize; 957275976Ssmh } 958275976Ssmh pRAID_Context->timeoutValue = map->raidMap.fpPdIoTimeoutSec; 959310264Skadesai if (sc->mrsas_gen3_ctrl) 960275976Ssmh pRAID_Context->regLockFlags = (isRead) ? raid->regTypeReqOnRead : raid->regTypeReqOnWrite; 961275976Ssmh else 962275976Ssmh pRAID_Context->regLockFlags = (isRead) ? REGION_TYPE_SHARED_READ : raid->regTypeReqOnWrite; 963275976Ssmh pRAID_Context->VirtualDiskTgtId = raid->targetId; 964275976Ssmh pRAID_Context->regLockRowLBA = regStart; 965275976Ssmh pRAID_Context->regLockLength = regSize; 966275976Ssmh pRAID_Context->configSeqNum = raid->seqNum; 967265555Sambrisko 968275976Ssmh /* 969275976Ssmh * Get Phy Params only if FP capable, or else leave it to MR firmware 970275976Ssmh * to do the calculation. 971275976Ssmh */ 972275976Ssmh if (io_info->fpOkForIo) { 973275976Ssmh retval = io_info->IoforUnevenSpan ? 974275976Ssmh mr_spanset_get_phy_params(sc, ld, start_strip, 975275976Ssmh ref_in_start_stripe, io_info, pRAID_Context, map) : 976275976Ssmh MR_GetPhyParams(sc, ld, start_strip, 977275976Ssmh ref_in_start_stripe, io_info, pRAID_Context, map); 978275976Ssmh /* If IO on an invalid Pd, then FP is not possible */ 979275976Ssmh if (io_info->devHandle == MR_PD_INVALID) 980275976Ssmh io_info->fpOkForIo = FALSE; 981275976Ssmh return retval; 982275976Ssmh } else if (isRead) { 983275976Ssmh for (stripIdx = 0; stripIdx < num_strips; stripIdx++) { 984275976Ssmh retval = io_info->IoforUnevenSpan ? 985275976Ssmh mr_spanset_get_phy_params(sc, ld, start_strip + stripIdx, 986275976Ssmh ref_in_start_stripe, io_info, pRAID_Context, map) : 987275976Ssmh MR_GetPhyParams(sc, ld, start_strip + stripIdx, 988275976Ssmh ref_in_start_stripe, io_info, pRAID_Context, map); 989275976Ssmh if (!retval) 990275976Ssmh return TRUE; 991275976Ssmh } 992275976Ssmh } 993265555Sambrisko#if SPAN_DEBUG 994275976Ssmh /* Just for testing what arm we get for strip. */ 995275976Ssmh get_arm_from_strip(sc, ld, start_strip, map); 996265555Sambrisko#endif 997275976Ssmh return TRUE; 998265555Sambrisko} 999265555Sambrisko 1000265555Sambrisko/* 1001275976Ssmh * 1002275976Ssmh * This routine pepare spanset info from Valid Raid map and store it into local 1003275976Ssmh * copy of ldSpanInfo per instance data structure. 1004275976Ssmh * 1005275976Ssmh * Inputs : LD map 1006275976Ssmh * ldSpanInfo per HBA instance 1007275976Ssmh * 1008275976Ssmh */ 1009275976Ssmhvoid 1010275976Ssmhmr_update_span_set(MR_DRV_RAID_MAP_ALL * map, PLD_SPAN_INFO ldSpanInfo) 1011265555Sambrisko{ 1012275976Ssmh u_int8_t span, count; 1013275976Ssmh u_int32_t element, span_row_width; 1014275976Ssmh u_int64_t span_row; 1015275976Ssmh MR_LD_RAID *raid; 1016275976Ssmh LD_SPAN_SET *span_set, *span_set_prev; 1017275976Ssmh MR_QUAD_ELEMENT *quad; 1018275976Ssmh int ldCount; 1019275976Ssmh u_int16_t ld; 1020265555Sambrisko 1021275976Ssmh for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) { 1022275976Ssmh ld = MR_TargetIdToLdGet(ldCount, map); 1023275976Ssmh if (ld >= MAX_LOGICAL_DRIVES) 1024275976Ssmh continue; 1025275976Ssmh raid = MR_LdRaidGet(ld, map); 1026275976Ssmh for (element = 0; element < MAX_QUAD_DEPTH; element++) { 1027275976Ssmh for (span = 0; span < raid->spanDepth; span++) { 1028275976Ssmh if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 1029275976Ssmh block_span_info.noElements < element + 1) 1030275976Ssmh continue; 1031275976Ssmh /* TO-DO */ 1032275976Ssmh span_set = &(ldSpanInfo[ld].span_set[element]); 1033275976Ssmh quad = &map->raidMap.ldSpanMap[ld]. 1034275976Ssmh spanBlock[span].block_span_info.quad[element]; 1035265555Sambrisko 1036275976Ssmh span_set->diff = quad->diff; 1037275976Ssmh 1038275976Ssmh for (count = 0, span_row_width = 0; 1039275976Ssmh count < raid->spanDepth; count++) { 1040275976Ssmh if (map->raidMap.ldSpanMap[ld].spanBlock[count]. 1041275976Ssmh block_span_info.noElements >= element + 1) { 1042275976Ssmh span_set->strip_offset[count] = span_row_width; 1043275976Ssmh span_row_width += 1044275976Ssmh MR_LdSpanPtrGet(ld, count, map)->spanRowDataSize; 1045265555Sambrisko#if SPAN_DEBUG 1046284267Skadesai printf("AVAGO Debug span %x rowDataSize %x\n", count, 1047275976Ssmh MR_LdSpanPtrGet(ld, count, map)->spanRowDataSize); 1048265555Sambrisko#endif 1049275976Ssmh } 1050275976Ssmh } 1051265555Sambrisko 1052275976Ssmh span_set->span_row_data_width = span_row_width; 1053275976Ssmh span_row = mega_div64_32(((quad->logEnd - 1054275976Ssmh quad->logStart) + quad->diff), quad->diff); 1055265555Sambrisko 1056275976Ssmh if (element == 0) { 1057275976Ssmh span_set->log_start_lba = 0; 1058275976Ssmh span_set->log_end_lba = 1059275976Ssmh ((span_row << raid->stripeShift) * span_row_width) - 1; 1060265555Sambrisko 1061275976Ssmh span_set->span_row_start = 0; 1062275976Ssmh span_set->span_row_end = span_row - 1; 1063265555Sambrisko 1064275976Ssmh span_set->data_strip_start = 0; 1065275976Ssmh span_set->data_strip_end = (span_row * span_row_width) - 1; 1066265555Sambrisko 1067275976Ssmh span_set->data_row_start = 0; 1068275976Ssmh span_set->data_row_end = (span_row * quad->diff) - 1; 1069275976Ssmh } else { 1070275976Ssmh span_set_prev = &(ldSpanInfo[ld].span_set[element - 1]); 1071275976Ssmh span_set->log_start_lba = span_set_prev->log_end_lba + 1; 1072275976Ssmh span_set->log_end_lba = span_set->log_start_lba + 1073275976Ssmh ((span_row << raid->stripeShift) * span_row_width) - 1; 1074265555Sambrisko 1075275976Ssmh span_set->span_row_start = span_set_prev->span_row_end + 1; 1076275976Ssmh span_set->span_row_end = 1077275976Ssmh span_set->span_row_start + span_row - 1; 1078275976Ssmh 1079275976Ssmh span_set->data_strip_start = 1080275976Ssmh span_set_prev->data_strip_end + 1; 1081275976Ssmh span_set->data_strip_end = span_set->data_strip_start + 1082275976Ssmh (span_row * span_row_width) - 1; 1083275976Ssmh 1084275976Ssmh span_set->data_row_start = span_set_prev->data_row_end + 1; 1085275976Ssmh span_set->data_row_end = span_set->data_row_start + 1086275976Ssmh (span_row * quad->diff) - 1; 1087275976Ssmh } 1088275976Ssmh break; 1089275976Ssmh } 1090275976Ssmh if (span == raid->spanDepth) 1091275976Ssmh break; /* no quads remain */ 1092275976Ssmh } 1093275976Ssmh } 1094265555Sambrisko#if SPAN_DEBUG 1095275976Ssmh getSpanInfo(map, ldSpanInfo); /* to get span set info */ 1096265555Sambrisko#endif 1097265555Sambrisko} 1098265555Sambrisko 1099275976Ssmh/* 1100275976Ssmh * mrsas_update_load_balance_params: Update load balance parmas 1101284267Skadesai * Inputs: 1102284267Skadesai * sc - driver softc instance 1103284267Skadesai * drv_map - driver RAID map 1104284267Skadesai * lbInfo - Load balance info 1105265555Sambrisko * 1106275976Ssmh * This function updates the load balance parameters for the LD config of a two 1107275976Ssmh * drive optimal RAID-1. 1108265555Sambrisko */ 1109284267Skadesaivoid 1110284267Skadesaimrsas_update_load_balance_params(struct mrsas_softc *sc, 1111284267Skadesai MR_DRV_RAID_MAP_ALL * drv_map, PLD_LOAD_BALANCE_INFO lbInfo) 1112265555Sambrisko{ 1113275976Ssmh int ldCount; 1114275976Ssmh u_int16_t ld; 1115275976Ssmh MR_LD_RAID *raid; 1116265555Sambrisko 1117284267Skadesai if (sc->lb_pending_cmds > 128 || sc->lb_pending_cmds < 1) 1118284267Skadesai sc->lb_pending_cmds = LB_PENDING_CMDS_DEFAULT; 1119284267Skadesai 1120284267Skadesai for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES_EXT; ldCount++) { 1121284267Skadesai ld = MR_TargetIdToLdGet(ldCount, drv_map); 1122284267Skadesai if (ld >= MAX_LOGICAL_DRIVES_EXT) { 1123275976Ssmh lbInfo[ldCount].loadBalanceFlag = 0; 1124275976Ssmh continue; 1125275976Ssmh } 1126284267Skadesai raid = MR_LdRaidGet(ld, drv_map); 1127284267Skadesai if ((raid->level != 1) || 1128284267Skadesai (raid->ldState != MR_LD_STATE_OPTIMAL)) { 1129275976Ssmh lbInfo[ldCount].loadBalanceFlag = 0; 1130284267Skadesai continue; 1131284267Skadesai } 1132284267Skadesai lbInfo[ldCount].loadBalanceFlag = 1; 1133275976Ssmh } 1134265555Sambrisko} 1135265555Sambrisko 1136265555Sambrisko 1137275976Ssmh/* 1138275976Ssmh * mrsas_set_pd_lba: Sets PD LBA 1139275976Ssmh * input: io_request pointer 1140275976Ssmh * CDB length 1141275976Ssmh * io_info pointer 1142275976Ssmh * Pointer to CCB 1143275976Ssmh * Local RAID map pointer 1144275976Ssmh * Start block of IO Block Size 1145265555Sambrisko * 1146265555Sambrisko * Used to set the PD logical block address in CDB for FP IOs. 1147265555Sambrisko */ 1148284267Skadesaivoid 1149275976Ssmhmrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request, u_int8_t cdb_len, 1150265555Sambrisko struct IO_REQUEST_INFO *io_info, union ccb *ccb, 1151275976Ssmh MR_DRV_RAID_MAP_ALL * local_map_ptr, u_int32_t ref_tag, 1152265555Sambrisko u_int32_t ld_block_size) 1153265555Sambrisko{ 1154275976Ssmh MR_LD_RAID *raid; 1155275976Ssmh u_int32_t ld; 1156275976Ssmh u_int64_t start_blk = io_info->pdBlock; 1157275976Ssmh u_int8_t *cdb = io_request->CDB.CDB32; 1158275976Ssmh u_int32_t num_blocks = io_info->numBlocks; 1159275976Ssmh u_int8_t opcode = 0, flagvals = 0, groupnum = 0, control = 0; 1160275976Ssmh struct ccb_hdr *ccb_h = &(ccb->ccb_h); 1161265555Sambrisko 1162275976Ssmh /* Check if T10 PI (DIF) is enabled for this LD */ 1163275976Ssmh ld = MR_TargetIdToLdGet(io_info->ldTgtId, local_map_ptr); 1164275976Ssmh raid = MR_LdRaidGet(ld, local_map_ptr); 1165275976Ssmh if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER) { 1166275976Ssmh memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1167275976Ssmh cdb[0] = MRSAS_SCSI_VARIABLE_LENGTH_CMD; 1168275976Ssmh cdb[7] = MRSAS_SCSI_ADDL_CDB_LEN; 1169265555Sambrisko 1170275976Ssmh if (ccb_h->flags == CAM_DIR_OUT) 1171275976Ssmh cdb[9] = MRSAS_SCSI_SERVICE_ACTION_READ32; 1172275976Ssmh else 1173275976Ssmh cdb[9] = MRSAS_SCSI_SERVICE_ACTION_WRITE32; 1174275976Ssmh cdb[10] = MRSAS_RD_WR_PROTECT_CHECK_ALL; 1175265555Sambrisko 1176275976Ssmh /* LBA */ 1177275976Ssmh cdb[12] = (u_int8_t)((start_blk >> 56) & 0xff); 1178275976Ssmh cdb[13] = (u_int8_t)((start_blk >> 48) & 0xff); 1179275976Ssmh cdb[14] = (u_int8_t)((start_blk >> 40) & 0xff); 1180275976Ssmh cdb[15] = (u_int8_t)((start_blk >> 32) & 0xff); 1181275976Ssmh cdb[16] = (u_int8_t)((start_blk >> 24) & 0xff); 1182275976Ssmh cdb[17] = (u_int8_t)((start_blk >> 16) & 0xff); 1183275976Ssmh cdb[18] = (u_int8_t)((start_blk >> 8) & 0xff); 1184275976Ssmh cdb[19] = (u_int8_t)(start_blk & 0xff); 1185265555Sambrisko 1186275976Ssmh /* Logical block reference tag */ 1187275976Ssmh io_request->CDB.EEDP32.PrimaryReferenceTag = swap32(ref_tag); 1188275976Ssmh io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0xffff; 1189275976Ssmh io_request->IoFlags = 32; /* Specify 32-byte cdb */ 1190265555Sambrisko 1191275976Ssmh /* Transfer length */ 1192275976Ssmh cdb[28] = (u_int8_t)((num_blocks >> 24) & 0xff); 1193275976Ssmh cdb[29] = (u_int8_t)((num_blocks >> 16) & 0xff); 1194275976Ssmh cdb[30] = (u_int8_t)((num_blocks >> 8) & 0xff); 1195275976Ssmh cdb[31] = (u_int8_t)(num_blocks & 0xff); 1196265555Sambrisko 1197275976Ssmh /* set SCSI IO EEDP Flags */ 1198275976Ssmh if (ccb_h->flags == CAM_DIR_OUT) { 1199275976Ssmh io_request->EEDPFlags = 1200275976Ssmh MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | 1201275976Ssmh MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | 1202275976Ssmh MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP | 1203275976Ssmh MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG | 1204275976Ssmh MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; 1205275976Ssmh } else { 1206275976Ssmh io_request->EEDPFlags = 1207275976Ssmh MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | 1208275976Ssmh MPI2_SCSIIO_EEDPFLAGS_INSERT_OP; 1209275976Ssmh } 1210275976Ssmh io_request->Control |= (0x4 << 26); 1211275976Ssmh io_request->EEDPBlockSize = ld_block_size; 1212275976Ssmh } else { 1213275976Ssmh /* Some drives don't support 16/12 byte CDB's, convert to 10 */ 1214275976Ssmh if (((cdb_len == 12) || (cdb_len == 16)) && 1215275976Ssmh (start_blk <= 0xffffffff)) { 1216275976Ssmh if (cdb_len == 16) { 1217275976Ssmh opcode = cdb[0] == READ_16 ? READ_10 : WRITE_10; 1218275976Ssmh flagvals = cdb[1]; 1219275976Ssmh groupnum = cdb[14]; 1220275976Ssmh control = cdb[15]; 1221275976Ssmh } else { 1222275976Ssmh opcode = cdb[0] == READ_12 ? READ_10 : WRITE_10; 1223275976Ssmh flagvals = cdb[1]; 1224275976Ssmh groupnum = cdb[10]; 1225275976Ssmh control = cdb[11]; 1226275976Ssmh } 1227265555Sambrisko 1228275976Ssmh memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1229265555Sambrisko 1230275976Ssmh cdb[0] = opcode; 1231275976Ssmh cdb[1] = flagvals; 1232275976Ssmh cdb[6] = groupnum; 1233275976Ssmh cdb[9] = control; 1234265555Sambrisko 1235275976Ssmh /* Transfer length */ 1236275976Ssmh cdb[8] = (u_int8_t)(num_blocks & 0xff); 1237275976Ssmh cdb[7] = (u_int8_t)((num_blocks >> 8) & 0xff); 1238265555Sambrisko 1239275976Ssmh io_request->IoFlags = 10; /* Specify 10-byte cdb */ 1240275976Ssmh cdb_len = 10; 1241275976Ssmh } else if ((cdb_len < 16) && (start_blk > 0xffffffff)) { 1242275976Ssmh /* Convert to 16 byte CDB for large LBA's */ 1243275976Ssmh switch (cdb_len) { 1244275976Ssmh case 6: 1245275976Ssmh opcode = cdb[0] == READ_6 ? READ_16 : WRITE_16; 1246275976Ssmh control = cdb[5]; 1247275976Ssmh break; 1248275976Ssmh case 10: 1249275976Ssmh opcode = cdb[0] == READ_10 ? READ_16 : WRITE_16; 1250275976Ssmh flagvals = cdb[1]; 1251275976Ssmh groupnum = cdb[6]; 1252275976Ssmh control = cdb[9]; 1253275976Ssmh break; 1254275976Ssmh case 12: 1255275976Ssmh opcode = cdb[0] == READ_12 ? READ_16 : WRITE_16; 1256275976Ssmh flagvals = cdb[1]; 1257275976Ssmh groupnum = cdb[10]; 1258275976Ssmh control = cdb[11]; 1259275976Ssmh break; 1260275976Ssmh } 1261265555Sambrisko 1262275976Ssmh memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1263265555Sambrisko 1264275976Ssmh cdb[0] = opcode; 1265275976Ssmh cdb[1] = flagvals; 1266275976Ssmh cdb[14] = groupnum; 1267275976Ssmh cdb[15] = control; 1268265555Sambrisko 1269275976Ssmh /* Transfer length */ 1270275976Ssmh cdb[13] = (u_int8_t)(num_blocks & 0xff); 1271275976Ssmh cdb[12] = (u_int8_t)((num_blocks >> 8) & 0xff); 1272275976Ssmh cdb[11] = (u_int8_t)((num_blocks >> 16) & 0xff); 1273275976Ssmh cdb[10] = (u_int8_t)((num_blocks >> 24) & 0xff); 1274265555Sambrisko 1275275976Ssmh io_request->IoFlags = 16; /* Specify 16-byte cdb */ 1276275976Ssmh cdb_len = 16; 1277275976Ssmh } else if ((cdb_len == 6) && (start_blk > 0x1fffff)) { 1278275976Ssmh /* convert to 10 byte CDB */ 1279275976Ssmh opcode = cdb[0] == READ_6 ? READ_10 : WRITE_10; 1280275976Ssmh control = cdb[5]; 1281265555Sambrisko 1282275976Ssmh memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1283275976Ssmh cdb[0] = opcode; 1284275976Ssmh cdb[9] = control; 1285265555Sambrisko 1286275976Ssmh /* Set transfer length */ 1287275976Ssmh cdb[8] = (u_int8_t)(num_blocks & 0xff); 1288275976Ssmh cdb[7] = (u_int8_t)((num_blocks >> 8) & 0xff); 1289275976Ssmh 1290275976Ssmh /* Specify 10-byte cdb */ 1291275976Ssmh cdb_len = 10; 1292275976Ssmh } 1293275976Ssmh /* Fall through normal case, just load LBA here */ 1294275976Ssmh u_int8_t val = cdb[1] & 0xE0; 1295284267Skadesai 1296275976Ssmh switch (cdb_len) { 1297275976Ssmh case 6: 1298275976Ssmh cdb[3] = (u_int8_t)(start_blk & 0xff); 1299275976Ssmh cdb[2] = (u_int8_t)((start_blk >> 8) & 0xff); 1300275976Ssmh cdb[1] = val | ((u_int8_t)(start_blk >> 16) & 0x1f); 1301275976Ssmh break; 1302275976Ssmh case 10: 1303275976Ssmh cdb[5] = (u_int8_t)(start_blk & 0xff); 1304275976Ssmh cdb[4] = (u_int8_t)((start_blk >> 8) & 0xff); 1305275976Ssmh cdb[3] = (u_int8_t)((start_blk >> 16) & 0xff); 1306275976Ssmh cdb[2] = (u_int8_t)((start_blk >> 24) & 0xff); 1307275976Ssmh break; 1308275976Ssmh case 16: 1309275976Ssmh cdb[9] = (u_int8_t)(start_blk & 0xff); 1310275976Ssmh cdb[8] = (u_int8_t)((start_blk >> 8) & 0xff); 1311275976Ssmh cdb[7] = (u_int8_t)((start_blk >> 16) & 0xff); 1312275976Ssmh cdb[6] = (u_int8_t)((start_blk >> 24) & 0xff); 1313275976Ssmh cdb[5] = (u_int8_t)((start_blk >> 32) & 0xff); 1314275976Ssmh cdb[4] = (u_int8_t)((start_blk >> 40) & 0xff); 1315275976Ssmh cdb[3] = (u_int8_t)((start_blk >> 48) & 0xff); 1316275976Ssmh cdb[2] = (u_int8_t)((start_blk >> 56) & 0xff); 1317275976Ssmh break; 1318275976Ssmh } 1319265555Sambrisko } 1320265555Sambrisko} 1321265555Sambrisko 1322275976Ssmh/* 1323284267Skadesai * mrsas_get_best_arm_pd: Determine the best spindle arm 1324284267Skadesai * Inputs: 1325284267Skadesai * sc - HBA instance 1326284267Skadesai * lbInfo - Load balance info 1327284267Skadesai * io_info - IO request info 1328265555Sambrisko * 1329265555Sambrisko * This function determines and returns the best arm by looking at the 1330265555Sambrisko * parameters of the last PD access. 1331265555Sambrisko */ 1332284267Skadesaiu_int8_t 1333284267Skadesaimrsas_get_best_arm_pd(struct mrsas_softc *sc, 1334284267Skadesai PLD_LOAD_BALANCE_INFO lbInfo, struct IO_REQUEST_INFO *io_info) 1335265555Sambrisko{ 1336284267Skadesai MR_LD_RAID *raid; 1337284267Skadesai MR_DRV_RAID_MAP_ALL *drv_map; 1338284267Skadesai u_int16_t pend0, pend1, ld; 1339275976Ssmh u_int64_t diff0, diff1; 1340284267Skadesai u_int8_t bestArm, pd0, pd1, span, arm; 1341284267Skadesai u_int32_t arRef, span_row_size; 1342265555Sambrisko 1343284267Skadesai u_int64_t block = io_info->ldStartBlock; 1344284267Skadesai u_int32_t count = io_info->numBlocks; 1345284267Skadesai 1346284267Skadesai span = ((io_info->span_arm & RAID_CTX_SPANARM_SPAN_MASK) 1347284267Skadesai >> RAID_CTX_SPANARM_SPAN_SHIFT); 1348284267Skadesai arm = (io_info->span_arm & RAID_CTX_SPANARM_ARM_MASK); 1349284267Skadesai 1350284267Skadesai drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 1351284267Skadesai ld = MR_TargetIdToLdGet(io_info->ldTgtId, drv_map); 1352284267Skadesai raid = MR_LdRaidGet(ld, drv_map); 1353284267Skadesai span_row_size = sc->UnevenSpanSupport ? 1354284267Skadesai SPAN_ROW_SIZE(drv_map, ld, span) : raid->rowSize; 1355284267Skadesai 1356284267Skadesai arRef = MR_LdSpanArrayGet(ld, span, drv_map); 1357284267Skadesai pd0 = MR_ArPdGet(arRef, arm, drv_map); 1358284267Skadesai pd1 = MR_ArPdGet(arRef, (arm + 1) >= span_row_size ? 1359284267Skadesai (arm + 1 - span_row_size) : arm + 1, drv_map); 1360284267Skadesai 1361275976Ssmh /* get the pending cmds for the data and mirror arms */ 1362284267Skadesai pend0 = mrsas_atomic_read(&lbInfo->scsi_pending_cmds[pd0]); 1363284267Skadesai pend1 = mrsas_atomic_read(&lbInfo->scsi_pending_cmds[pd1]); 1364265555Sambrisko 1365275976Ssmh /* Determine the disk whose head is nearer to the req. block */ 1366284267Skadesai diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[pd0]); 1367284267Skadesai diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[pd1]); 1368284267Skadesai bestArm = (diff0 <= diff1 ? arm : arm ^ 1); 1369265555Sambrisko 1370284267Skadesai if ((bestArm == arm && pend0 > pend1 + sc->lb_pending_cmds) || 1371284267Skadesai (bestArm != arm && pend1 > pend0 + sc->lb_pending_cmds)) 1372275976Ssmh bestArm ^= 1; 1373265555Sambrisko 1374275976Ssmh /* Update the last accessed block on the correct pd */ 1375284267Skadesai lbInfo->last_accessed_block[bestArm == arm ? pd0 : pd1] = block + count - 1; 1376284267Skadesai io_info->span_arm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | bestArm; 1377284267Skadesai io_info->pd_after_lb = (bestArm == arm) ? pd0 : pd1; 1378284267Skadesai#if SPAN_DEBUG 1379284267Skadesai if (arm != bestArm) 1380284267Skadesai printf("AVAGO Debug R1 Load balance occur - span 0x%x arm 0x%x bestArm 0x%x " 1381284267Skadesai "io_info->span_arm 0x%x\n", 1382284267Skadesai span, arm, bestArm, io_info->span_arm); 1383284267Skadesai#endif 1384265555Sambrisko 1385284267Skadesai return io_info->pd_after_lb; 1386265555Sambrisko} 1387265555Sambrisko 1388275976Ssmh/* 1389275976Ssmh * mrsas_get_updated_dev_handle: Get the update dev handle 1390284267Skadesai * Inputs: 1391284267Skadesai * sc - Adapter instance soft state 1392284267Skadesai * lbInfo - Load balance info 1393284267Skadesai * io_info - io_info pointer 1394265555Sambrisko * 1395265555Sambrisko * This function determines and returns the updated dev handle. 1396265555Sambrisko */ 1397284267Skadesaiu_int16_t 1398284267Skadesaimrsas_get_updated_dev_handle(struct mrsas_softc *sc, 1399284267Skadesai PLD_LOAD_BALANCE_INFO lbInfo, struct IO_REQUEST_INFO *io_info) 1400265555Sambrisko{ 1401284267Skadesai u_int8_t arm_pd; 1402275976Ssmh u_int16_t devHandle; 1403284267Skadesai MR_DRV_RAID_MAP_ALL *drv_map; 1404265555Sambrisko 1405284267Skadesai drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 1406265555Sambrisko 1407275976Ssmh /* get best new arm */ 1408284267Skadesai arm_pd = mrsas_get_best_arm_pd(sc, lbInfo, io_info); 1409284267Skadesai devHandle = MR_PdDevHandleGet(arm_pd, drv_map); 1410284267Skadesai mrsas_atomic_inc(&lbInfo->scsi_pending_cmds[arm_pd]); 1411265555Sambrisko 1412275976Ssmh return devHandle; 1413265555Sambrisko} 1414265555Sambrisko 1415275976Ssmh/* 1416275976Ssmh * MR_GetPhyParams: Calculates arm, span, and block 1417275976Ssmh * Inputs: Adapter soft state 1418275976Ssmh * Logical drive number (LD) 1419275976Ssmh * Stripe number(stripRow) 1420275976Ssmh * Reference in stripe (stripRef) 1421265555Sambrisko * 1422275976Ssmh * Outputs: Absolute Block number in the physical disk 1423275976Ssmh * 1424275976Ssmh * This routine calculates the arm, span and block for the specified stripe and 1425275976Ssmh * reference in stripe. 1426265555Sambrisko */ 1427275976Ssmhu_int8_t 1428275976SsmhMR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld, 1429275976Ssmh u_int64_t stripRow, 1430275976Ssmh u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 1431275976Ssmh RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map) 1432265555Sambrisko{ 1433275976Ssmh MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 1434275976Ssmh u_int32_t pd, arRef; 1435275976Ssmh u_int8_t physArm, span; 1436275976Ssmh u_int64_t row; 1437275976Ssmh u_int8_t retval = TRUE; 1438275976Ssmh int error_code = 0; 1439265555Sambrisko u_int64_t *pdBlock = &io_info->pdBlock; 1440275976Ssmh u_int16_t *pDevHandle = &io_info->devHandle; 1441275976Ssmh u_int32_t rowMod, armQ, arm, logArm; 1442265555Sambrisko 1443275976Ssmh row = mega_div64_32(stripRow, raid->rowDataSize); 1444265555Sambrisko 1445275976Ssmh if (raid->level == 6) { 1446275976Ssmh /* logical arm within row */ 1447275976Ssmh logArm = mega_mod64(stripRow, raid->rowDataSize); 1448275976Ssmh if (raid->rowSize == 0) 1449275976Ssmh return FALSE; 1450275976Ssmh rowMod = mega_mod64(row, raid->rowSize); /* get logical row mod */ 1451275976Ssmh armQ = raid->rowSize - 1 - rowMod; /* index of Q drive */ 1452275976Ssmh arm = armQ + 1 + logArm;/* data always logically follows Q */ 1453275976Ssmh if (arm >= raid->rowSize) /* handle wrap condition */ 1454275976Ssmh arm -= raid->rowSize; 1455275976Ssmh physArm = (u_int8_t)arm; 1456275976Ssmh } else { 1457275976Ssmh if (raid->modFactor == 0) 1458275976Ssmh return FALSE; 1459275976Ssmh physArm = MR_LdDataArmGet(ld, mega_mod64(stripRow, raid->modFactor), map); 1460275976Ssmh } 1461265555Sambrisko 1462275976Ssmh if (raid->spanDepth == 1) { 1463275976Ssmh span = 0; 1464275976Ssmh *pdBlock = row << raid->stripeShift; 1465275976Ssmh } else { 1466275976Ssmh span = (u_int8_t)MR_GetSpanBlock(ld, row, pdBlock, map, &error_code); 1467275976Ssmh if (error_code == 1) 1468275976Ssmh return FALSE; 1469275976Ssmh } 1470265555Sambrisko 1471275976Ssmh /* Get the array on which this span is present */ 1472275976Ssmh arRef = MR_LdSpanArrayGet(ld, span, map); 1473265555Sambrisko 1474275976Ssmh pd = MR_ArPdGet(arRef, physArm, map); /* Get the Pd. */ 1475265555Sambrisko 1476275976Ssmh if (pd != MR_PD_INVALID) 1477275976Ssmh /* Get dev handle from Pd */ 1478275976Ssmh *pDevHandle = MR_PdDevHandleGet(pd, map); 1479275976Ssmh else { 1480275976Ssmh *pDevHandle = MR_PD_INVALID; /* set dev handle as invalid. */ 1481310264Skadesai if ((raid->level >= 5) && ((!sc->mrsas_gen3_ctrl) || (sc->mrsas_gen3_ctrl && 1482275976Ssmh raid->regTypeReqOnRead != REGION_TYPE_UNUSED))) 1483275976Ssmh pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; 1484275976Ssmh else if (raid->level == 1) { 1485275976Ssmh /* Get Alternate Pd. */ 1486275976Ssmh pd = MR_ArPdGet(arRef, physArm + 1, map); 1487275976Ssmh if (pd != MR_PD_INVALID) 1488275976Ssmh /* Get dev handle from Pd. */ 1489275976Ssmh *pDevHandle = MR_PdDevHandleGet(pd, map); 1490275976Ssmh } 1491275976Ssmh } 1492265555Sambrisko 1493275976Ssmh *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk; 1494275976Ssmh pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; 1495284267Skadesai io_info->span_arm = pRAID_Context->spanArm; 1496275976Ssmh return retval; 1497265555Sambrisko} 1498265555Sambrisko 1499275976Ssmh/* 1500275976Ssmh * MR_GetSpanBlock: Calculates span block 1501275976Ssmh * Inputs: LD 1502275976Ssmh * row PD 1503275976Ssmh * span block 1504275976Ssmh * RAID map pointer 1505265555Sambrisko * 1506275976Ssmh * Outputs: Span number Error code 1507275976Ssmh * 1508275976Ssmh * This routine calculates the span from the span block info. 1509265555Sambrisko */ 1510275976Ssmhu_int32_t 1511275976SsmhMR_GetSpanBlock(u_int32_t ld, u_int64_t row, u_int64_t *span_blk, 1512275976Ssmh MR_DRV_RAID_MAP_ALL * map, int *div_error) 1513265555Sambrisko{ 1514275976Ssmh MR_SPAN_BLOCK_INFO *pSpanBlock = MR_LdSpanInfoGet(ld, map); 1515275976Ssmh MR_QUAD_ELEMENT *quad; 1516275976Ssmh MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 1517275976Ssmh u_int32_t span, j; 1518275976Ssmh u_int64_t blk, debugBlk; 1519265555Sambrisko 1520275976Ssmh for (span = 0; span < raid->spanDepth; span++, pSpanBlock++) { 1521275976Ssmh for (j = 0; j < pSpanBlock->block_span_info.noElements; j++) { 1522275976Ssmh quad = &pSpanBlock->block_span_info.quad[j]; 1523275976Ssmh if (quad->diff == 0) { 1524275976Ssmh *div_error = 1; 1525275976Ssmh return span; 1526275976Ssmh } 1527275976Ssmh if (quad->logStart <= row && row <= quad->logEnd && 1528275976Ssmh (mega_mod64(row - quad->logStart, quad->diff)) == 0) { 1529275976Ssmh if (span_blk != NULL) { 1530275976Ssmh blk = mega_div64_32((row - quad->logStart), quad->diff); 1531275976Ssmh debugBlk = blk; 1532275976Ssmh blk = (blk + quad->offsetInSpan) << raid->stripeShift; 1533275976Ssmh *span_blk = blk; 1534275976Ssmh } 1535275976Ssmh return span; 1536275976Ssmh } 1537275976Ssmh } 1538275976Ssmh } 1539275976Ssmh return span; 1540265555Sambrisko} 1541