1265555Sambrisko/* 2282531Skadesai * Copyright (c) 2015, AVAGO Tech. All rights reserved. Author: Marian Choy 3272744Skadesai * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy 4282531Skadesai * Support: freebsdraid@avagotech.com 5265555Sambrisko * 6265555Sambrisko * Redistribution and use in source and binary forms, with or without 7272744Skadesai * modification, are permitted provided that the following conditions are 8272744Skadesai * met: 9265555Sambrisko * 10272744Skadesai * 1. Redistributions of source code must retain the above copyright notice, 11272744Skadesai * this list of conditions and the following disclaimer. 2. Redistributions 12272744Skadesai * in binary form must reproduce the above copyright notice, this list of 13272744Skadesai * conditions and the following disclaimer in the documentation and/or other 14272744Skadesai * materials provided with the distribution. 3. Neither the name of the 15272744Skadesai * <ORGANIZATION> nor the names of its contributors may be used to endorse or 16272744Skadesai * promote products derived from this software without specific prior written 17272744Skadesai * permission. 18265555Sambrisko * 19272744Skadesai * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20272744Skadesai * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21272744Skadesai * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22272744Skadesai * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23272744Skadesai * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24272744Skadesai * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25272744Skadesai * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26272744Skadesai * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27272744Skadesai * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28272744Skadesai * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29265555Sambrisko * POSSIBILITY OF SUCH DAMAGE. 30265555Sambrisko * 31272744Skadesai * The views and conclusions contained in the software and documentation are 32272744Skadesai * those of the authors and should not be interpreted as representing 33265555Sambrisko * official policies,either expressed or implied, of the FreeBSD Project. 34265555Sambrisko * 35282531Skadesai * Send feedback to: <megaraidfbsd@avagotech.com> Mail to: AVAGO TECHNOLOGIES, 1621 36272744Skadesai * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD 37265555Sambrisko * 38265555Sambrisko */ 39265555Sambrisko 40265555Sambrisko#include <sys/cdefs.h> 41265555Sambrisko__FBSDID("$FreeBSD: stable/11/sys/dev/mrsas/mrsas_fp.c 342720 2019-01-03 08:04:14Z 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); 58272744Skadesaiu_int8_t 59282533Skadesaimrsas_get_best_arm_pd(struct mrsas_softc *sc, 60282533Skadesai PLD_LOAD_BALANCE_INFO lbInfo, struct IO_REQUEST_INFO *io_info); 61282533Skadesaiu_int8_t 62272744SkadesaiMR_BuildRaidContext(struct mrsas_softc *sc, 63272744Skadesai struct IO_REQUEST_INFO *io_info, 64272744Skadesai RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map); 65282533Skadesaiu_int8_t 66272744SkadesaiMR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld, 67272744Skadesai u_int64_t stripRow, u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 68272744Skadesai RAID_CONTEXT * pRAID_Context, 69272744Skadesai MR_DRV_RAID_MAP_ALL * map); 70342716Skadesaiu_int8_t MR_TargetIdToLdGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL *map); 71272744Skadesaiu_int32_t MR_LdBlockSizeGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map); 72272744Skadesaiu_int16_t MR_GetLDTgtId(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map); 73282533Skadesaiu_int16_t 74282533Skadesaimrsas_get_updated_dev_handle(struct mrsas_softc *sc, 75282533Skadesai PLD_LOAD_BALANCE_INFO lbInfo, struct IO_REQUEST_INFO *io_info); 76265555Sambriskou_int32_t mega_mod64(u_int64_t dividend, u_int32_t divisor); 77282533Skadesaiu_int32_t 78272744SkadesaiMR_GetSpanBlock(u_int32_t ld, u_int64_t row, u_int64_t *span_blk, 79272744Skadesai MR_DRV_RAID_MAP_ALL * map, int *div_error); 80265555Sambriskou_int64_t mega_div64_32(u_int64_t dividend, u_int32_t divisor); 81272744Skadesaivoid 82282533Skadesaimrsas_update_load_balance_params(struct mrsas_softc *sc, 83282533Skadesai MR_DRV_RAID_MAP_ALL * map, PLD_LOAD_BALANCE_INFO lbInfo); 84282533Skadesaivoid 85272744Skadesaimrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request, 86272744Skadesai u_int8_t cdb_len, struct IO_REQUEST_INFO *io_info, union ccb *ccb, 87272744Skadesai MR_DRV_RAID_MAP_ALL * local_map_ptr, u_int32_t ref_tag, 88272744Skadesai u_int32_t ld_block_size); 89282533Skadesaistatic u_int16_t 90272744SkadesaiMR_LdSpanArrayGet(u_int32_t ld, u_int32_t span, 91272744Skadesai MR_DRV_RAID_MAP_ALL * map); 92272744Skadesaistatic u_int16_t MR_PdDevHandleGet(u_int32_t pd, MR_DRV_RAID_MAP_ALL * map); 93282533Skadesaistatic u_int16_t 94272744SkadesaiMR_ArPdGet(u_int32_t ar, u_int32_t arm, 95272744Skadesai MR_DRV_RAID_MAP_ALL * map); 96272744Skadesaistatic MR_LD_SPAN * 97272744SkadesaiMR_LdSpanPtrGet(u_int32_t ld, u_int32_t span, 98272744Skadesai MR_DRV_RAID_MAP_ALL * map); 99282533Skadesaistatic u_int8_t 100272744SkadesaiMR_LdDataArmGet(u_int32_t ld, u_int32_t armIdx, 101272744Skadesai MR_DRV_RAID_MAP_ALL * map); 102272744Skadesaistatic MR_SPAN_BLOCK_INFO * 103272744SkadesaiMR_LdSpanInfoGet(u_int32_t ld, 104272744Skadesai MR_DRV_RAID_MAP_ALL * map); 105272744SkadesaiMR_LD_RAID *MR_LdRaidGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map); 106342716Skadesaistatic int MR_PopulateDrvRaidMap(struct mrsas_softc *sc); 107265555Sambrisko 108272735Skadesai 109265555Sambrisko/* 110272744Skadesai * Spanset related function prototypes Added for PRL11 configuration (Uneven 111272744Skadesai * span support) 112265555Sambrisko */ 113272744Skadesaivoid mr_update_span_set(MR_DRV_RAID_MAP_ALL * map, PLD_SPAN_INFO ldSpanInfo); 114272744Skadesaistatic u_int8_t 115272744Skadesaimr_spanset_get_phy_params(struct mrsas_softc *sc, u_int32_t ld, 116272744Skadesai u_int64_t stripRow, u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 117272744Skadesai RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map); 118272744Skadesaistatic u_int64_t 119272744Skadesaiget_row_from_strip(struct mrsas_softc *sc, u_int32_t ld, 120272744Skadesai u_int64_t strip, MR_DRV_RAID_MAP_ALL * map); 121272744Skadesaistatic u_int32_t 122272744Skadesaimr_spanset_get_span_block(struct mrsas_softc *sc, 123272744Skadesai u_int32_t ld, u_int64_t row, u_int64_t *span_blk, 124272744Skadesai MR_DRV_RAID_MAP_ALL * map, int *div_error); 125272744Skadesaistatic u_int8_t 126272744Skadesaiget_arm(struct mrsas_softc *sc, u_int32_t ld, u_int8_t span, 127272744Skadesai u_int64_t stripe, MR_DRV_RAID_MAP_ALL * map); 128265555Sambrisko 129265555Sambrisko 130265555Sambrisko/* 131272744Skadesai * Spanset related defines Added for PRL11 configuration(Uneven span support) 132265555Sambrisko */ 133272744Skadesai#define SPAN_ROW_SIZE(map, ld, index_) MR_LdSpanPtrGet(ld, index_, map)->spanRowSize 134272744Skadesai#define SPAN_ROW_DATA_SIZE(map_, ld, index_) \ 135272744Skadesai MR_LdSpanPtrGet(ld, index_, map)->spanRowDataSize 136272744Skadesai#define SPAN_INVALID 0xff 137272744Skadesai#define SPAN_DEBUG 0 138265555Sambrisko 139265555Sambrisko/* 140265555Sambrisko * Related Defines 141265555Sambrisko */ 142265555Sambrisko 143272744Skadesaitypedef u_int64_t REGION_KEY; 144272744Skadesaitypedef u_int32_t REGION_LEN; 145265555Sambrisko 146272744Skadesai#define MR_LD_STATE_OPTIMAL 3 147272744Skadesai#define FALSE 0 148272744Skadesai#define TRUE 1 149265555Sambrisko 150282533Skadesai#define LB_PENDING_CMDS_DEFAULT 4 151265555Sambrisko 152282527Skadesai 153265555Sambrisko/* 154265555Sambrisko * Related Macros 155265555Sambrisko */ 156265555Sambrisko 157272744Skadesai#define ABS_DIFF(a,b) ( ((a) > (b)) ? ((a) - (b)) : ((b) - (a)) ) 158265555Sambrisko 159272744Skadesai#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/* 168272744Skadesai * In-line functions for mod and divide of 64-bit dividend and 32-bit 169272744Skadesai * divisor. Assumes a check for a divisor of zero is not possible. 170272744Skadesai * 171272744Skadesai * @param dividend: Dividend 172272744Skadesai * @param divisor: Divisor 173272744Skadesai * @return remainder 174265555Sambrisko */ 175265555Sambrisko 176272744Skadesai#define mega_mod64(dividend, divisor) ({ \ 177265555Sambriskoint remainder; \ 178265555Sambriskoremainder = ((u_int64_t) (dividend)) % (u_int32_t) (divisor); \ 179265555Sambriskoremainder;}) 180265555Sambrisko 181272744Skadesai#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 189272744Skadesai * parts of the RAID map and returns the appropriate parameters. 190265555Sambrisko */ 191265555Sambrisko 192272744SkadesaiMR_LD_RAID * 193272744SkadesaiMR_LdRaidGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map) 194265555Sambrisko{ 195272744Skadesai return (&map->raidMap.ldSpanMap[ld].ldRaid); 196265555Sambrisko} 197265555Sambrisko 198272744Skadesaiu_int16_t 199272744SkadesaiMR_GetLDTgtId(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map) 200265555Sambrisko{ 201272744Skadesai return (map->raidMap.ldSpanMap[ld].ldRaid.targetId); 202265555Sambrisko} 203265555Sambrisko 204272744Skadesaistatic u_int16_t 205272744SkadesaiMR_LdSpanArrayGet(u_int32_t ld, u_int32_t span, MR_DRV_RAID_MAP_ALL * map) 206265555Sambrisko{ 207272744Skadesai return map->raidMap.ldSpanMap[ld].spanBlock[span].span.arrayRef; 208265555Sambrisko} 209265555Sambrisko 210272744Skadesaistatic u_int8_t 211272744SkadesaiMR_LdDataArmGet(u_int32_t ld, u_int32_t armIdx, MR_DRV_RAID_MAP_ALL * map) 212265555Sambrisko{ 213272744Skadesai return map->raidMap.ldSpanMap[ld].dataArmMap[armIdx]; 214265555Sambrisko} 215265555Sambrisko 216272744Skadesaistatic u_int16_t 217272744SkadesaiMR_PdDevHandleGet(u_int32_t pd, MR_DRV_RAID_MAP_ALL * map) 218265555Sambrisko{ 219272744Skadesai return map->raidMap.devHndlInfo[pd].curDevHdl; 220265555Sambrisko} 221265555Sambrisko 222342716Skadesaistatic u_int8_t MR_PdInterfaceTypeGet(u_int32_t pd, MR_DRV_RAID_MAP_ALL *map) 223342716Skadesai{ 224342716Skadesai return map->raidMap.devHndlInfo[pd].interfaceType; 225342716Skadesai} 226342716Skadesai 227342716Skadesai 228272744Skadesaistatic u_int16_t 229272744SkadesaiMR_ArPdGet(u_int32_t ar, u_int32_t arm, MR_DRV_RAID_MAP_ALL * map) 230265555Sambrisko{ 231272744Skadesai return map->raidMap.arMapInfo[ar].pd[arm]; 232265555Sambrisko} 233265555Sambrisko 234272744Skadesaistatic MR_LD_SPAN * 235272744SkadesaiMR_LdSpanPtrGet(u_int32_t ld, u_int32_t span, MR_DRV_RAID_MAP_ALL * map) 236265555Sambrisko{ 237272744Skadesai return &map->raidMap.ldSpanMap[ld].spanBlock[span].span; 238265555Sambrisko} 239265555Sambrisko 240272744Skadesaistatic MR_SPAN_BLOCK_INFO * 241272744SkadesaiMR_LdSpanInfoGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map) 242265555Sambrisko{ 243272744Skadesai return &map->raidMap.ldSpanMap[ld].spanBlock[0]; 244265555Sambrisko} 245265555Sambrisko 246342716Skadesaiu_int8_t 247272744SkadesaiMR_TargetIdToLdGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map) 248265555Sambrisko{ 249272744Skadesai return map->raidMap.ldTgtIdToLd[ldTgtId]; 250265555Sambrisko} 251265555Sambrisko 252272744Skadesaiu_int32_t 253272744SkadesaiMR_LdBlockSizeGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map) 254265555Sambrisko{ 255272744Skadesai MR_LD_RAID *raid; 256272744Skadesai u_int32_t ld, ldBlockSize = MRSAS_SCSIBLOCKSIZE; 257265555Sambrisko 258272744Skadesai ld = MR_TargetIdToLdGet(ldTgtId, map); 259265555Sambrisko 260272744Skadesai /* 261272744Skadesai * Check if logical drive was removed. 262272744Skadesai */ 263272744Skadesai if (ld >= MAX_LOGICAL_DRIVES) 264272744Skadesai return ldBlockSize; 265265555Sambrisko 266272744Skadesai raid = MR_LdRaidGet(ld, map); 267272744Skadesai ldBlockSize = raid->logicalBlockLength; 268272744Skadesai if (!ldBlockSize) 269272744Skadesai ldBlockSize = MRSAS_SCSIBLOCKSIZE; 270265555Sambrisko 271272744Skadesai return ldBlockSize; 272265555Sambrisko} 273265555Sambrisko 274272735Skadesai/* 275342716Skadesai * This function will Populate Driver Map using Dynamic firmware raid map 276342716Skadesai */ 277342716Skadesaistatic int 278342716SkadesaiMR_PopulateDrvRaidMapVentura(struct mrsas_softc *sc) 279342716Skadesai{ 280342716Skadesai unsigned int i, j; 281342716Skadesai u_int16_t ld_count; 282342716Skadesai 283342716Skadesai MR_FW_RAID_MAP_DYNAMIC *fw_map_dyn; 284342716Skadesai MR_RAID_MAP_DESC_TABLE *desc_table; 285342716Skadesai MR_DRV_RAID_MAP_ALL *drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 286342716Skadesai MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap; 287342716Skadesai void *raid_map_data = NULL; 288342716Skadesai 289342716Skadesai fw_map_dyn = (MR_FW_RAID_MAP_DYNAMIC *) sc->raidmap_mem[(sc->map_id & 1)]; 290342716Skadesai 291342716Skadesai if (fw_map_dyn == NULL) { 292342716Skadesai device_printf(sc->mrsas_dev, 293342716Skadesai "from %s %d map0 %p map1 %p map size %d \n", __func__, __LINE__, 294342716Skadesai sc->raidmap_mem[0], sc->raidmap_mem[1], sc->maxRaidMapSize); 295342716Skadesai return 1; 296342716Skadesai } 297342716Skadesai#if VD_EXT_DEBUG 298342716Skadesai device_printf(sc->mrsas_dev, 299342716Skadesai " raidMapSize 0x%x, descTableOffset 0x%x, " 300342716Skadesai " descTableSize 0x%x, descTableNumElements 0x%x \n", 301342716Skadesai fw_map_dyn->raidMapSize, fw_map_dyn->descTableOffset, 302342716Skadesai fw_map_dyn->descTableSize, fw_map_dyn->descTableNumElements); 303342716Skadesai#endif 304342716Skadesai desc_table = (MR_RAID_MAP_DESC_TABLE *) ((char *)fw_map_dyn + 305342716Skadesai fw_map_dyn->descTableOffset); 306342716Skadesai if (desc_table != fw_map_dyn->raidMapDescTable) { 307342716Skadesai device_printf(sc->mrsas_dev, 308342716Skadesai "offsets of desc table are not matching returning " 309342716Skadesai " FW raid map has been changed: desc %p original %p\n", 310342716Skadesai desc_table, fw_map_dyn->raidMapDescTable); 311342716Skadesai } 312342716Skadesai memset(drv_map, 0, sc->drv_map_sz); 313342716Skadesai ld_count = fw_map_dyn->ldCount; 314342716Skadesai pDrvRaidMap->ldCount = ld_count; 315342716Skadesai pDrvRaidMap->fpPdIoTimeoutSec = fw_map_dyn->fpPdIoTimeoutSec; 316342716Skadesai pDrvRaidMap->totalSize = sizeof(MR_DRV_RAID_MAP_ALL); 317342716Skadesai /* point to actual data starting point */ 318342716Skadesai raid_map_data = (char *)fw_map_dyn + 319342716Skadesai fw_map_dyn->descTableOffset + fw_map_dyn->descTableSize; 320342716Skadesai 321342716Skadesai for (i = 0; i < fw_map_dyn->descTableNumElements; ++i) { 322342716Skadesai if (!desc_table) { 323342716Skadesai device_printf(sc->mrsas_dev, 324342716Skadesai "desc table is null, coming out %p \n", desc_table); 325342716Skadesai return 1; 326342716Skadesai } 327342716Skadesai#if VD_EXT_DEBUG 328342716Skadesai device_printf(sc->mrsas_dev, "raid_map_data %p \n", raid_map_data); 329342716Skadesai device_printf(sc->mrsas_dev, 330342716Skadesai "desc table %p \n", desc_table); 331342716Skadesai device_printf(sc->mrsas_dev, 332342716Skadesai "raidmap type %d, raidmapOffset 0x%x, " 333342716Skadesai " raid map number of elements 0%x, raidmapsize 0x%x\n", 334342716Skadesai desc_table->raidMapDescType, desc_table->raidMapDescOffset, 335342716Skadesai desc_table->raidMapDescElements, desc_table->raidMapDescBufferSize); 336342716Skadesai#endif 337342716Skadesai switch (desc_table->raidMapDescType) { 338342716Skadesai case RAID_MAP_DESC_TYPE_DEVHDL_INFO: 339342716Skadesai fw_map_dyn->RaidMapDescPtrs.ptrStruct.devHndlInfo = (MR_DEV_HANDLE_INFO *) 340342716Skadesai ((char *)raid_map_data + desc_table->raidMapDescOffset); 341342716Skadesai#if VD_EXT_DEBUG 342342716Skadesai device_printf(sc->mrsas_dev, 343342716Skadesai "devHndlInfo address %p\n", fw_map_dyn->RaidMapDescPtrs.ptrStruct.devHndlInfo); 344342716Skadesai#endif 345342716Skadesai memcpy(pDrvRaidMap->devHndlInfo, fw_map_dyn->RaidMapDescPtrs.ptrStruct.devHndlInfo, 346342716Skadesai sizeof(MR_DEV_HANDLE_INFO) * desc_table->raidMapDescElements); 347342716Skadesai break; 348342716Skadesai case RAID_MAP_DESC_TYPE_TGTID_INFO: 349342716Skadesai fw_map_dyn->RaidMapDescPtrs.ptrStruct.ldTgtIdToLd = (u_int16_t *) 350342716Skadesai ((char *)raid_map_data + desc_table->raidMapDescOffset); 351342716Skadesai#if VD_EXT_DEBUG 352342716Skadesai device_printf(sc->mrsas_dev, 353342716Skadesai "ldTgtIdToLd address %p\n", fw_map_dyn->RaidMapDescPtrs.ptrStruct.ldTgtIdToLd); 354342716Skadesai#endif 355342716Skadesai for (j = 0; j < desc_table->raidMapDescElements; j++) { 356342716Skadesai pDrvRaidMap->ldTgtIdToLd[j] = fw_map_dyn->RaidMapDescPtrs.ptrStruct.ldTgtIdToLd[j]; 357342716Skadesai#if VD_EXT_DEBUG 358342716Skadesai device_printf(sc->mrsas_dev, 359342716Skadesai " %d drv ldTgtIdToLd %d\n", j, pDrvRaidMap->ldTgtIdToLd[j]); 360342716Skadesai#endif 361342716Skadesai } 362342716Skadesai break; 363342716Skadesai case RAID_MAP_DESC_TYPE_ARRAY_INFO: 364342716Skadesai fw_map_dyn->RaidMapDescPtrs.ptrStruct.arMapInfo = (MR_ARRAY_INFO *) ((char *)raid_map_data + 365342716Skadesai desc_table->raidMapDescOffset); 366342716Skadesai#if VD_EXT_DEBUG 367342716Skadesai device_printf(sc->mrsas_dev, 368342716Skadesai "arMapInfo address %p\n", fw_map_dyn->RaidMapDescPtrs.ptrStruct.arMapInfo); 369342716Skadesai#endif 370342716Skadesai memcpy(pDrvRaidMap->arMapInfo, fw_map_dyn->RaidMapDescPtrs.ptrStruct.arMapInfo, 371342716Skadesai sizeof(MR_ARRAY_INFO) * desc_table->raidMapDescElements); 372342716Skadesai break; 373342716Skadesai case RAID_MAP_DESC_TYPE_SPAN_INFO: 374342716Skadesai fw_map_dyn->RaidMapDescPtrs.ptrStruct.ldSpanMap = (MR_LD_SPAN_MAP *) ((char *)raid_map_data + 375342716Skadesai desc_table->raidMapDescOffset); 376342716Skadesai memcpy(pDrvRaidMap->ldSpanMap, fw_map_dyn->RaidMapDescPtrs.ptrStruct.ldSpanMap, 377342716Skadesai sizeof(MR_LD_SPAN_MAP) * desc_table->raidMapDescElements); 378342716Skadesai#if VD_EXT_DEBUG 379342716Skadesai device_printf(sc->mrsas_dev, 380342716Skadesai "ldSpanMap address %p\n", fw_map_dyn->RaidMapDescPtrs.ptrStruct.ldSpanMap); 381342716Skadesai device_printf(sc->mrsas_dev, 382342716Skadesai "MR_LD_SPAN_MAP size 0x%lx\n", sizeof(MR_LD_SPAN_MAP)); 383342716Skadesai for (j = 0; j < ld_count; j++) { 384342716Skadesai printf("mrsas(%d) : fw_map_dyn->ldSpanMap[%d].ldRaid.targetId 0x%x " 385342716Skadesai "fw_map_dyn->ldSpanMap[%d].ldRaid.seqNum 0x%x size 0x%x\n", 386342716Skadesai j, j, fw_map_dyn->RaidMapDescPtrs.ptrStruct.ldSpanMap[j].ldRaid.targetId, j, 387342716Skadesai fw_map_dyn->RaidMapDescPtrs.ptrStruct.ldSpanMap[j].ldRaid.seqNum, 388342716Skadesai (u_int32_t)fw_map_dyn->RaidMapDescPtrs.ptrStruct.ldSpanMap[j].ldRaid.rowSize); 389342716Skadesai printf("mrsas(%d) : pDrvRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x " 390342716Skadesai "pDrvRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x size 0x%x\n", 391342716Skadesai j, j, pDrvRaidMap->ldSpanMap[j].ldRaid.targetId, j, 392342716Skadesai pDrvRaidMap->ldSpanMap[j].ldRaid.seqNum, 393342716Skadesai (u_int32_t)pDrvRaidMap->ldSpanMap[j].ldRaid.rowSize); 394342716Skadesai printf("mrsas : drv raid map all %p raid map %p LD RAID MAP %p/%p\n", 395342716Skadesai drv_map, pDrvRaidMap, &fw_map_dyn->RaidMapDescPtrs.ptrStruct.ldSpanMap[j].ldRaid, 396342716Skadesai &pDrvRaidMap->ldSpanMap[j].ldRaid); 397342716Skadesai } 398342716Skadesai#endif 399342716Skadesai break; 400342716Skadesai default: 401342716Skadesai device_printf(sc->mrsas_dev, 402342716Skadesai "wrong number of desctableElements %d\n", 403342716Skadesai fw_map_dyn->descTableNumElements); 404342716Skadesai } 405342716Skadesai ++desc_table; 406342716Skadesai } 407342716Skadesai return 0; 408342716Skadesai} 409342716Skadesai 410342716Skadesai/* 411272735Skadesai * This function will Populate Driver Map using firmware raid map 412272735Skadesai */ 413342716Skadesaistatic int 414272744SkadesaiMR_PopulateDrvRaidMap(struct mrsas_softc *sc) 415272735Skadesai{ 416272744Skadesai MR_FW_RAID_MAP_ALL *fw_map_old = NULL; 417342716Skadesai MR_FW_RAID_MAP_EXT *fw_map_ext; 418272744Skadesai MR_FW_RAID_MAP *pFwRaidMap = NULL; 419272735Skadesai unsigned int i; 420342716Skadesai u_int16_t ld_count; 421272735Skadesai 422272735Skadesai MR_DRV_RAID_MAP_ALL *drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 423272735Skadesai MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap; 424272735Skadesai 425342716Skadesai if (sc->maxRaidMapSize) { 426342716Skadesai return MR_PopulateDrvRaidMapVentura(sc); 427342716Skadesai } else if (sc->max256vdSupport) { 428342716Skadesai fw_map_ext = (MR_FW_RAID_MAP_EXT *) sc->raidmap_mem[(sc->map_id & 1)]; 429342716Skadesai ld_count = (u_int16_t)(fw_map_ext->ldCount); 430342716Skadesai if (ld_count > MAX_LOGICAL_DRIVES_EXT) { 431342716Skadesai device_printf(sc->mrsas_dev, 432342716Skadesai "mrsas: LD count exposed in RAID map in not valid\n"); 433342716Skadesai return 1; 434342716Skadesai } 435342716Skadesai#if VD_EXT_DEBUG 436342716Skadesai for (i = 0; i < ld_count; i++) { 437342716Skadesai printf("mrsas : Index 0x%x Target Id 0x%x Seq Num 0x%x Size 0/%lx\n", 438342716Skadesai i, fw_map_ext->ldSpanMap[i].ldRaid.targetId, 439342716Skadesai fw_map_ext->ldSpanMap[i].ldRaid.seqNum, 440342716Skadesai fw_map_ext->ldSpanMap[i].ldRaid.size); 441342716Skadesai } 442342716Skadesai#endif 443342716Skadesai memset(drv_map, 0, sc->drv_map_sz); 444342716Skadesai pDrvRaidMap->ldCount = ld_count; 445342716Skadesai pDrvRaidMap->fpPdIoTimeoutSec = fw_map_ext->fpPdIoTimeoutSec; 446342716Skadesai for (i = 0; i < (MAX_LOGICAL_DRIVES_EXT); i++) { 447342716Skadesai pDrvRaidMap->ldTgtIdToLd[i] = (u_int16_t)fw_map_ext->ldTgtIdToLd[i]; 448342716Skadesai } 449342716Skadesai memcpy(pDrvRaidMap->ldSpanMap, fw_map_ext->ldSpanMap, sizeof(MR_LD_SPAN_MAP) * ld_count); 450342716Skadesai#if VD_EXT_DEBUG 451342716Skadesai for (i = 0; i < ld_count; i++) { 452342716Skadesai printf("mrsas(%d) : fw_map_ext->ldSpanMap[%d].ldRaid.targetId 0x%x " 453342716Skadesai "fw_map_ext->ldSpanMap[%d].ldRaid.seqNum 0x%x size 0x%x\n", 454342716Skadesai i, i, fw_map_ext->ldSpanMap[i].ldRaid.targetId, i, 455342716Skadesai fw_map_ext->ldSpanMap[i].ldRaid.seqNum, 456342716Skadesai (u_int32_t)fw_map_ext->ldSpanMap[i].ldRaid.rowSize); 457342716Skadesai printf("mrsas(%d) : pDrvRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x" 458342716Skadesai "pDrvRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x size 0x%x\n", i, i, 459342716Skadesai pDrvRaidMap->ldSpanMap[i].ldRaid.targetId, i, 460342716Skadesai pDrvRaidMap->ldSpanMap[i].ldRaid.seqNum, 461342716Skadesai (u_int32_t)pDrvRaidMap->ldSpanMap[i].ldRaid.rowSize); 462342716Skadesai printf("mrsas : drv raid map all %p raid map %p LD RAID MAP %p/%p\n", 463342716Skadesai drv_map, pDrvRaidMap, &fw_map_ext->ldSpanMap[i].ldRaid, 464342716Skadesai &pDrvRaidMap->ldSpanMap[i].ldRaid); 465342716Skadesai } 466342716Skadesai#endif 467342716Skadesai memcpy(pDrvRaidMap->arMapInfo, fw_map_ext->arMapInfo, 468342716Skadesai sizeof(MR_ARRAY_INFO) * MAX_API_ARRAYS_EXT); 469342716Skadesai memcpy(pDrvRaidMap->devHndlInfo, fw_map_ext->devHndlInfo, 470342716Skadesai sizeof(MR_DEV_HANDLE_INFO) * MAX_RAIDMAP_PHYSICAL_DEVICES); 471342716Skadesai 472272744Skadesai pDrvRaidMap->totalSize = sizeof(MR_FW_RAID_MAP_EXT); 473272735Skadesai } else { 474272744Skadesai fw_map_old = (MR_FW_RAID_MAP_ALL *) sc->raidmap_mem[(sc->map_id & 1)]; 475272735Skadesai pFwRaidMap = &fw_map_old->raidMap; 476272735Skadesai 477272735Skadesai#if VD_EXT_DEBUG 478272735Skadesai for (i = 0; i < pFwRaidMap->ldCount; i++) { 479272735Skadesai device_printf(sc->mrsas_dev, 480272744Skadesai "Index 0x%x Target Id 0x%x Seq Num 0x%x Size 0/%lx\n", i, 481272744Skadesai fw_map_old->raidMap.ldSpanMap[i].ldRaid.targetId, 482272744Skadesai fw_map_old->raidMap.ldSpanMap[i].ldRaid.seqNum, 483272744Skadesai fw_map_old->raidMap.ldSpanMap[i].ldRaid.size); 484272735Skadesai } 485272735Skadesai#endif 486272735Skadesai 487272735Skadesai memset(drv_map, 0, sc->drv_map_sz); 488272735Skadesai pDrvRaidMap->totalSize = pFwRaidMap->totalSize; 489272735Skadesai pDrvRaidMap->ldCount = pFwRaidMap->ldCount; 490272735Skadesai pDrvRaidMap->fpPdIoTimeoutSec = 491272744Skadesai pFwRaidMap->fpPdIoTimeoutSec; 492272735Skadesai 493272744Skadesai for (i = 0; i < MAX_RAIDMAP_LOGICAL_DRIVES + MAX_RAIDMAP_VIEWS; i++) { 494272735Skadesai pDrvRaidMap->ldTgtIdToLd[i] = 495272744Skadesai (u_int8_t)pFwRaidMap->ldTgtIdToLd[i]; 496272735Skadesai } 497272735Skadesai 498272744Skadesai for (i = 0; i < pDrvRaidMap->ldCount; i++) { 499272735Skadesai pDrvRaidMap->ldSpanMap[i] = 500272744Skadesai pFwRaidMap->ldSpanMap[i]; 501272735Skadesai 502272735Skadesai#if VD_EXT_DEBUG 503272744Skadesai device_printf(sc->mrsas_dev, "pFwRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x " 504272744Skadesai "pFwRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x size 0x%x\n", 505272744Skadesai i, i, pFwRaidMap->ldSpanMap[i].ldRaid.targetId, 506272744Skadesai pFwRaidMap->ldSpanMap[i].ldRaid.seqNum, 507272744Skadesai (u_int32_t)pFwRaidMap->ldSpanMap[i].ldRaid.rowSize); 508272744Skadesai device_printf(sc->mrsas_dev, "pDrvRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x" 509272744Skadesai "pDrvRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x size 0x%x\n", i, i, 510272744Skadesai pDrvRaidMap->ldSpanMap[i].ldRaid.targetId, 511272744Skadesai pDrvRaidMap->ldSpanMap[i].ldRaid.seqNum, 512272744Skadesai (u_int32_t)pDrvRaidMap->ldSpanMap[i].ldRaid.rowSize); 513272744Skadesai device_printf(sc->mrsas_dev, "drv raid map all %p raid map %p LD RAID MAP %p/%p\n", 514272744Skadesai drv_map, pDrvRaidMap, 515272744Skadesai &pFwRaidMap->ldSpanMap[i].ldRaid, &pDrvRaidMap->ldSpanMap[i].ldRaid); 516272735Skadesai#endif 517272735Skadesai } 518272735Skadesai 519272735Skadesai memcpy(pDrvRaidMap->arMapInfo, pFwRaidMap->arMapInfo, 520272744Skadesai sizeof(MR_ARRAY_INFO) * MAX_RAIDMAP_ARRAYS); 521272735Skadesai memcpy(pDrvRaidMap->devHndlInfo, pFwRaidMap->devHndlInfo, 522272744Skadesai sizeof(MR_DEV_HANDLE_INFO) * 523272744Skadesai MAX_RAIDMAP_PHYSICAL_DEVICES); 524272735Skadesai } 525342716Skadesai return 0; 526272735Skadesai} 527272735Skadesai 528272744Skadesai/* 529272744Skadesai * MR_ValidateMapInfo: Validate RAID map 530272744Skadesai * input: Adapter instance soft state 531265555Sambrisko * 532272744Skadesai * This function checks and validates the loaded RAID map. It returns 0 if 533265555Sambrisko * successful, and 1 otherwise. 534265555Sambrisko */ 535272744Skadesaiu_int8_t 536272744SkadesaiMR_ValidateMapInfo(struct mrsas_softc *sc) 537265555Sambrisko{ 538265555Sambrisko if (!sc) { 539265555Sambrisko return 1; 540265555Sambrisko } 541342716Skadesai if (MR_PopulateDrvRaidMap(sc)) 542342716Skadesai return 0; 543272735Skadesai 544272744Skadesai MR_DRV_RAID_MAP_ALL *drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 545272744Skadesai MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap; 546272735Skadesai 547272744Skadesai u_int32_t expected_map_size; 548272735Skadesai 549272744Skadesai drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 550272744Skadesai pDrvRaidMap = &drv_map->raidMap; 551272744Skadesai PLD_SPAN_INFO ldSpanInfo = (PLD_SPAN_INFO) & sc->log_to_span; 552265555Sambrisko 553342716Skadesai if (sc->maxRaidMapSize) 554342716Skadesai expected_map_size = sizeof(MR_DRV_RAID_MAP_ALL); 555342716Skadesai else if (sc->max256vdSupport) 556272744Skadesai expected_map_size = sizeof(MR_FW_RAID_MAP_EXT); 557272744Skadesai else 558272744Skadesai expected_map_size = 559272744Skadesai (sizeof(MR_FW_RAID_MAP) - sizeof(MR_LD_SPAN_MAP)) + 560272744Skadesai (sizeof(MR_LD_SPAN_MAP) * pDrvRaidMap->ldCount); 561265555Sambrisko 562272744Skadesai if (pDrvRaidMap->totalSize != expected_map_size) { 563272744Skadesai device_printf(sc->mrsas_dev, "map size %x not matching ld count\n", expected_map_size); 564272744Skadesai device_printf(sc->mrsas_dev, "span map= %x\n", (unsigned int)sizeof(MR_LD_SPAN_MAP)); 565272744Skadesai device_printf(sc->mrsas_dev, "pDrvRaidMap->totalSize=%x\n", pDrvRaidMap->totalSize); 566272744Skadesai return 1; 567265555Sambrisko } 568272744Skadesai if (sc->UnevenSpanSupport) { 569272744Skadesai mr_update_span_set(drv_map, ldSpanInfo); 570272744Skadesai } 571282527Skadesai mrsas_update_load_balance_params(sc, drv_map, sc->load_balance_info); 572265555Sambrisko 573272744Skadesai return 0; 574265555Sambrisko} 575265555Sambrisko 576265555Sambrisko/* 577272744Skadesai * 578272744Skadesai * Function to print info about span set created in driver from FW raid map 579272744Skadesai * 580272744Skadesai * Inputs: map 581272744Skadesai * ldSpanInfo: ld map span info per HBA instance 582272744Skadesai * 583272744Skadesai * 584272744Skadesai */ 585265555Sambrisko#if SPAN_DEBUG 586272744Skadesaistatic int 587272744SkadesaigetSpanInfo(MR_DRV_RAID_MAP_ALL * map, PLD_SPAN_INFO ldSpanInfo) 588265555Sambrisko{ 589265555Sambrisko 590272744Skadesai u_int8_t span; 591272744Skadesai u_int32_t element; 592272744Skadesai MR_LD_RAID *raid; 593272744Skadesai LD_SPAN_SET *span_set; 594272744Skadesai MR_QUAD_ELEMENT *quad; 595272744Skadesai int ldCount; 596272744Skadesai u_int16_t ld; 597265555Sambrisko 598272744Skadesai for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) { 599272744Skadesai ld = MR_TargetIdToLdGet(ldCount, map); 600272744Skadesai if (ld >= MAX_LOGICAL_DRIVES) { 601272744Skadesai continue; 602272744Skadesai } 603272744Skadesai raid = MR_LdRaidGet(ld, map); 604272744Skadesai printf("LD %x: span_depth=%x\n", ld, raid->spanDepth); 605272744Skadesai for (span = 0; span < raid->spanDepth; span++) 606272744Skadesai printf("Span=%x, number of quads=%x\n", span, 607272744Skadesai map->raidMap.ldSpanMap[ld].spanBlock[span]. 608272744Skadesai block_span_info.noElements); 609272744Skadesai for (element = 0; element < MAX_QUAD_DEPTH; element++) { 610272744Skadesai span_set = &(ldSpanInfo[ld].span_set[element]); 611272744Skadesai if (span_set->span_row_data_width == 0) 612272744Skadesai break; 613265555Sambrisko 614272744Skadesai printf("Span Set %x: width=%x, diff=%x\n", element, 615272744Skadesai (unsigned int)span_set->span_row_data_width, 616272744Skadesai (unsigned int)span_set->diff); 617272744Skadesai printf("logical LBA start=0x%08lx, end=0x%08lx\n", 618272744Skadesai (long unsigned int)span_set->log_start_lba, 619272744Skadesai (long unsigned int)span_set->log_end_lba); 620272744Skadesai printf("span row start=0x%08lx, end=0x%08lx\n", 621272744Skadesai (long unsigned int)span_set->span_row_start, 622272744Skadesai (long unsigned int)span_set->span_row_end); 623272744Skadesai printf("data row start=0x%08lx, end=0x%08lx\n", 624272744Skadesai (long unsigned int)span_set->data_row_start, 625272744Skadesai (long unsigned int)span_set->data_row_end); 626272744Skadesai printf("data strip start=0x%08lx, end=0x%08lx\n", 627272744Skadesai (long unsigned int)span_set->data_strip_start, 628272744Skadesai (long unsigned int)span_set->data_strip_end); 629272744Skadesai 630272744Skadesai for (span = 0; span < raid->spanDepth; span++) { 631272744Skadesai if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 632272744Skadesai block_span_info.noElements >= element + 1) { 633272744Skadesai quad = &map->raidMap.ldSpanMap[ld]. 634272744Skadesai spanBlock[span].block_span_info. 635272744Skadesai quad[element]; 636272744Skadesai printf("Span=%x, Quad=%x, diff=%x\n", span, 637272744Skadesai element, quad->diff); 638272744Skadesai printf("offset_in_span=0x%08lx\n", 639272744Skadesai (long unsigned int)quad->offsetInSpan); 640272744Skadesai printf("logical start=0x%08lx, end=0x%08lx\n", 641272744Skadesai (long unsigned int)quad->logStart, 642272744Skadesai (long unsigned int)quad->logEnd); 643272744Skadesai } 644272744Skadesai } 645272744Skadesai } 646272744Skadesai } 647272744Skadesai return 0; 648265555Sambrisko} 649272744Skadesai 650265555Sambrisko#endif 651265555Sambrisko/* 652272744Skadesai * 653272744Skadesai * This routine calculates the Span block for given row using spanset. 654272744Skadesai * 655272744Skadesai * Inputs : HBA instance 656272744Skadesai * ld: Logical drive number 657272744Skadesai * row: Row number 658272744Skadesai * map: LD map 659272744Skadesai * 660272744Skadesai * Outputs : span - Span number block 661272744Skadesai * - Absolute Block number in the physical disk 662272744Skadesai * div_error - Devide error code. 663272744Skadesai */ 664265555Sambrisko 665272744Skadesaiu_int32_t 666272744Skadesaimr_spanset_get_span_block(struct mrsas_softc *sc, u_int32_t ld, u_int64_t row, 667272744Skadesai u_int64_t *span_blk, MR_DRV_RAID_MAP_ALL * map, int *div_error) 668265555Sambrisko{ 669272744Skadesai MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 670272744Skadesai LD_SPAN_SET *span_set; 671272744Skadesai MR_QUAD_ELEMENT *quad; 672272744Skadesai u_int32_t span, info; 673272744Skadesai PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 674265555Sambrisko 675272744Skadesai for (info = 0; info < MAX_QUAD_DEPTH; info++) { 676272744Skadesai span_set = &(ldSpanInfo[ld].span_set[info]); 677265555Sambrisko 678272744Skadesai if (span_set->span_row_data_width == 0) 679272744Skadesai break; 680272744Skadesai if (row > span_set->data_row_end) 681272744Skadesai continue; 682265555Sambrisko 683272744Skadesai for (span = 0; span < raid->spanDepth; span++) 684272744Skadesai if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 685272744Skadesai block_span_info.noElements >= info + 1) { 686272744Skadesai quad = &map->raidMap.ldSpanMap[ld]. 687272744Skadesai spanBlock[span]. 688272744Skadesai block_span_info.quad[info]; 689272744Skadesai if (quad->diff == 0) { 690272744Skadesai *div_error = 1; 691272744Skadesai return span; 692272744Skadesai } 693272744Skadesai if (quad->logStart <= row && 694272744Skadesai row <= quad->logEnd && 695272744Skadesai (mega_mod64(row - quad->logStart, 696272744Skadesai quad->diff)) == 0) { 697272744Skadesai if (span_blk != NULL) { 698272744Skadesai u_int64_t blk; 699272744Skadesai 700272744Skadesai blk = mega_div64_32 701272744Skadesai ((row - quad->logStart), 702272744Skadesai quad->diff); 703272744Skadesai blk = (blk + quad->offsetInSpan) 704272744Skadesai << raid->stripeShift; 705272744Skadesai *span_blk = blk; 706272744Skadesai } 707272744Skadesai return span; 708272744Skadesai } 709272744Skadesai } 710272744Skadesai } 711272744Skadesai return SPAN_INVALID; 712265555Sambrisko} 713265555Sambrisko 714265555Sambrisko/* 715272744Skadesai * 716272744Skadesai * This routine calculates the row for given strip using spanset. 717272744Skadesai * 718272744Skadesai * Inputs : HBA instance 719272744Skadesai * ld: Logical drive number 720272744Skadesai * Strip: Strip 721272744Skadesai * map: LD map 722272744Skadesai * 723272744Skadesai * Outputs : row - row associated with strip 724272744Skadesai */ 725265555Sambrisko 726272744Skadesaistatic u_int64_t 727272744Skadesaiget_row_from_strip(struct mrsas_softc *sc, 728272744Skadesai u_int32_t ld, u_int64_t strip, MR_DRV_RAID_MAP_ALL * map) 729265555Sambrisko{ 730272744Skadesai MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 731272744Skadesai LD_SPAN_SET *span_set; 732272744Skadesai PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 733272744Skadesai u_int32_t info, strip_offset, span, span_offset; 734272744Skadesai u_int64_t span_set_Strip, span_set_Row; 735265555Sambrisko 736272744Skadesai for (info = 0; info < MAX_QUAD_DEPTH; info++) { 737272744Skadesai span_set = &(ldSpanInfo[ld].span_set[info]); 738265555Sambrisko 739272744Skadesai if (span_set->span_row_data_width == 0) 740272744Skadesai break; 741272744Skadesai if (strip > span_set->data_strip_end) 742272744Skadesai continue; 743265555Sambrisko 744272744Skadesai span_set_Strip = strip - span_set->data_strip_start; 745272744Skadesai strip_offset = mega_mod64(span_set_Strip, 746272744Skadesai span_set->span_row_data_width); 747272744Skadesai span_set_Row = mega_div64_32(span_set_Strip, 748272744Skadesai span_set->span_row_data_width) * span_set->diff; 749272744Skadesai for (span = 0, span_offset = 0; span < raid->spanDepth; span++) 750272744Skadesai if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 751272744Skadesai block_span_info.noElements >= info + 1) { 752272744Skadesai if (strip_offset >= 753272744Skadesai span_set->strip_offset[span]) 754272744Skadesai span_offset++; 755272744Skadesai else 756272744Skadesai break; 757272744Skadesai } 758282531Skadesai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug : Strip 0x%llx, span_set_Strip 0x%llx, span_set_Row 0x%llx " 759272744Skadesai "data width 0x%llx span offset 0x%llx\n", (unsigned long long)strip, 760272744Skadesai (unsigned long long)span_set_Strip, 761272744Skadesai (unsigned long long)span_set_Row, 762272744Skadesai (unsigned long long)span_set->span_row_data_width, (unsigned long long)span_offset); 763282531Skadesai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug : For strip 0x%llx row is 0x%llx\n", (unsigned long long)strip, 764272744Skadesai (unsigned long long)span_set->data_row_start + 765272744Skadesai (unsigned long long)span_set_Row + (span_offset - 1)); 766272744Skadesai return (span_set->data_row_start + span_set_Row + (span_offset - 1)); 767272744Skadesai } 768272744Skadesai return -1LLU; 769265555Sambrisko} 770265555Sambrisko 771265555Sambrisko 772265555Sambrisko/* 773272744Skadesai * 774272744Skadesai * This routine calculates the Start Strip for given row using spanset. 775272744Skadesai * 776272744Skadesai * Inputs: HBA instance 777272744Skadesai * ld: Logical drive number 778272744Skadesai * row: Row number 779272744Skadesai * map: LD map 780272744Skadesai * 781272744Skadesai * Outputs : Strip - Start strip associated with row 782272744Skadesai */ 783265555Sambrisko 784272744Skadesaistatic u_int64_t 785272744Skadesaiget_strip_from_row(struct mrsas_softc *sc, 786272744Skadesai u_int32_t ld, u_int64_t row, MR_DRV_RAID_MAP_ALL * map) 787265555Sambrisko{ 788272744Skadesai MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 789272744Skadesai LD_SPAN_SET *span_set; 790272744Skadesai MR_QUAD_ELEMENT *quad; 791272744Skadesai PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 792272744Skadesai u_int32_t span, info; 793272744Skadesai u_int64_t strip; 794265555Sambrisko 795272744Skadesai for (info = 0; info < MAX_QUAD_DEPTH; info++) { 796272744Skadesai span_set = &(ldSpanInfo[ld].span_set[info]); 797265555Sambrisko 798272744Skadesai if (span_set->span_row_data_width == 0) 799272744Skadesai break; 800272744Skadesai if (row > span_set->data_row_end) 801272744Skadesai continue; 802265555Sambrisko 803272744Skadesai for (span = 0; span < raid->spanDepth; span++) 804272744Skadesai if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 805272744Skadesai block_span_info.noElements >= info + 1) { 806272744Skadesai quad = &map->raidMap.ldSpanMap[ld]. 807272744Skadesai spanBlock[span].block_span_info.quad[info]; 808272744Skadesai if (quad->logStart <= row && 809272744Skadesai row <= quad->logEnd && 810272744Skadesai mega_mod64((row - quad->logStart), 811272744Skadesai quad->diff) == 0) { 812272744Skadesai strip = mega_div64_32 813272744Skadesai (((row - span_set->data_row_start) 814272744Skadesai - quad->logStart), 815272744Skadesai quad->diff); 816272744Skadesai strip *= span_set->span_row_data_width; 817272744Skadesai strip += span_set->data_strip_start; 818272744Skadesai strip += span_set->strip_offset[span]; 819272744Skadesai return strip; 820272744Skadesai } 821272744Skadesai } 822272744Skadesai } 823282531Skadesai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug - get_strip_from_row: returns invalid " 824272744Skadesai "strip for ld=%x, row=%lx\n", ld, (long unsigned int)row); 825272744Skadesai return -1; 826265555Sambrisko} 827265555Sambrisko 828265555Sambrisko/* 829272744Skadesai * ***************************************************************************** 830272744Skadesai * 831272744Skadesai * 832272744Skadesai * This routine calculates the Physical Arm for given strip using spanset. 833272744Skadesai * 834272744Skadesai * Inputs : HBA instance 835272744Skadesai * Logical drive number 836272744Skadesai * Strip 837272744Skadesai * LD map 838272744Skadesai * 839272744Skadesai * Outputs : Phys Arm - Phys Arm associated with strip 840272744Skadesai */ 841265555Sambrisko 842272744Skadesaistatic u_int32_t 843272744Skadesaiget_arm_from_strip(struct mrsas_softc *sc, 844272744Skadesai u_int32_t ld, u_int64_t strip, MR_DRV_RAID_MAP_ALL * map) 845265555Sambrisko{ 846272744Skadesai MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 847272744Skadesai LD_SPAN_SET *span_set; 848272744Skadesai PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 849272744Skadesai u_int32_t info, strip_offset, span, span_offset; 850265555Sambrisko 851272744Skadesai for (info = 0; info < MAX_QUAD_DEPTH; info++) { 852272744Skadesai span_set = &(ldSpanInfo[ld].span_set[info]); 853265555Sambrisko 854272744Skadesai if (span_set->span_row_data_width == 0) 855272744Skadesai break; 856272744Skadesai if (strip > span_set->data_strip_end) 857272744Skadesai continue; 858265555Sambrisko 859272744Skadesai strip_offset = (u_int32_t)mega_mod64 860272744Skadesai ((strip - span_set->data_strip_start), 861272744Skadesai span_set->span_row_data_width); 862265555Sambrisko 863272744Skadesai for (span = 0, span_offset = 0; span < raid->spanDepth; span++) 864272744Skadesai if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 865272744Skadesai block_span_info.noElements >= info + 1) { 866272744Skadesai if (strip_offset >= span_set->strip_offset[span]) 867272744Skadesai span_offset = span_set->strip_offset[span]; 868272744Skadesai else 869272744Skadesai break; 870272744Skadesai } 871282531Skadesai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO PRL11: get_arm_from_strip: " 872272744Skadesai "for ld=0x%x strip=0x%lx arm is 0x%x\n", ld, 873272744Skadesai (long unsigned int)strip, (strip_offset - span_offset)); 874272744Skadesai return (strip_offset - span_offset); 875272744Skadesai } 876265555Sambrisko 877282531Skadesai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: - get_arm_from_strip: returns invalid arm" 878272744Skadesai " for ld=%x strip=%lx\n", ld, (long unsigned int)strip); 879265555Sambrisko 880272744Skadesai return -1; 881265555Sambrisko} 882265555Sambrisko 883265555Sambrisko 884265555Sambrisko/* This Function will return Phys arm */ 885272744Skadesaiu_int8_t 886272744Skadesaiget_arm(struct mrsas_softc *sc, u_int32_t ld, u_int8_t span, u_int64_t stripe, 887272744Skadesai MR_DRV_RAID_MAP_ALL * map) 888265555Sambrisko{ 889272744Skadesai MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 890265555Sambrisko 891272744Skadesai /* Need to check correct default value */ 892272744Skadesai u_int32_t arm = 0; 893265555Sambrisko 894272744Skadesai switch (raid->level) { 895272744Skadesai case 0: 896272744Skadesai case 5: 897272744Skadesai case 6: 898272744Skadesai arm = mega_mod64(stripe, SPAN_ROW_SIZE(map, ld, span)); 899272744Skadesai break; 900272744Skadesai case 1: 901272744Skadesai /* start with logical arm */ 902272744Skadesai arm = get_arm_from_strip(sc, ld, stripe, map); 903272744Skadesai arm *= 2; 904272744Skadesai break; 905272744Skadesai } 906265555Sambrisko 907272744Skadesai return arm; 908265555Sambrisko} 909265555Sambrisko 910265555Sambrisko/* 911272744Skadesai * 912272744Skadesai * This routine calculates the arm, span and block for the specified stripe and 913272744Skadesai * reference in stripe using spanset 914272744Skadesai * 915282527Skadesai * Inputs : 916282527Skadesai * sc - HBA instance 917282527Skadesai * ld - Logical drive number 918282527Skadesai * stripRow: Stripe number 919282527Skadesai * stripRef: Reference in stripe 920272744Skadesai * 921272744Skadesai * Outputs : span - Span number block - Absolute Block 922272744Skadesai * number in the physical disk 923272744Skadesai */ 924272744Skadesaistatic u_int8_t 925272744Skadesaimr_spanset_get_phy_params(struct mrsas_softc *sc, u_int32_t ld, u_int64_t stripRow, 926272744Skadesai u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 927272744Skadesai RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map) 928265555Sambrisko{ 929272744Skadesai MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 930342716Skadesai u_int32_t pd, arRef, r1_alt_pd; 931272744Skadesai u_int8_t physArm, span; 932272744Skadesai u_int64_t row; 933272744Skadesai u_int8_t retval = TRUE; 934272744Skadesai u_int64_t *pdBlock = &io_info->pdBlock; 935272744Skadesai u_int16_t *pDevHandle = &io_info->devHandle; 936342716Skadesai u_int8_t *pPdInterface = &io_info->pdInterface; 937342716Skadesai 938272744Skadesai u_int32_t logArm, rowMod, armQ, arm; 939265555Sambrisko 940272744Skadesai /* Get row and span from io_info for Uneven Span IO. */ 941272744Skadesai row = io_info->start_row; 942272744Skadesai span = io_info->start_span; 943265555Sambrisko 944265555Sambrisko 945272744Skadesai if (raid->level == 6) { 946272744Skadesai logArm = get_arm_from_strip(sc, ld, stripRow, map); 947272744Skadesai rowMod = mega_mod64(row, SPAN_ROW_SIZE(map, ld, span)); 948272744Skadesai armQ = SPAN_ROW_SIZE(map, ld, span) - 1 - rowMod; 949272744Skadesai arm = armQ + 1 + logArm; 950272744Skadesai if (arm >= SPAN_ROW_SIZE(map, ld, span)) 951272744Skadesai arm -= SPAN_ROW_SIZE(map, ld, span); 952272744Skadesai physArm = (u_int8_t)arm; 953272744Skadesai } else 954272744Skadesai /* Calculate the arm */ 955272744Skadesai physArm = get_arm(sc, ld, span, stripRow, map); 956265555Sambrisko 957265555Sambrisko 958272744Skadesai arRef = MR_LdSpanArrayGet(ld, span, map); 959272744Skadesai pd = MR_ArPdGet(arRef, physArm, map); 960265555Sambrisko 961342716Skadesai if (pd != MR_PD_INVALID) { 962272744Skadesai *pDevHandle = MR_PdDevHandleGet(pd, map); 963342716Skadesai *pPdInterface = MR_PdInterfaceTypeGet(pd, map); 964342716Skadesai /* get second pd also for raid 1/10 fast path writes */ 965342716Skadesai if ((raid->level == 1) && !io_info->isRead) { 966342716Skadesai r1_alt_pd = MR_ArPdGet(arRef, physArm + 1, map); 967342716Skadesai if (r1_alt_pd != MR_PD_INVALID) 968342716Skadesai io_info->r1_alt_dev_handle = MR_PdDevHandleGet(r1_alt_pd, map); 969342716Skadesai } 970342716Skadesai } else { 971342716Skadesai *pDevHandle = MR_DEVHANDLE_INVALID; 972342716Skadesai if ((raid->level >= 5) && ((sc->device_id == MRSAS_TBOLT) || 973342716Skadesai (sc->mrsas_gen3_ctrl && 974342716Skadesai raid->regTypeReqOnRead != REGION_TYPE_UNUSED))) 975272744Skadesai pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; 976272744Skadesai else if (raid->level == 1) { 977272744Skadesai pd = MR_ArPdGet(arRef, physArm + 1, map); 978342716Skadesai if (pd != MR_PD_INVALID) { 979272744Skadesai *pDevHandle = MR_PdDevHandleGet(pd, map); 980342716Skadesai *pPdInterface = MR_PdInterfaceTypeGet(pd, map); 981342716Skadesai } 982272744Skadesai } 983272744Skadesai } 984272744Skadesai 985272744Skadesai *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk; 986342720Skadesai if (sc->is_ventura || sc->is_aero) { 987342716Skadesai ((RAID_CONTEXT_G35 *) pRAID_Context)->spanArm = 988342716Skadesai (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; 989342716Skadesai io_info->span_arm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; 990342716Skadesai } else { 991342716Skadesai pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; 992342716Skadesai io_info->span_arm = pRAID_Context->spanArm; 993342716Skadesai } 994272744Skadesai return retval; 995265555Sambrisko} 996265555Sambrisko 997272744Skadesai/* 998272744Skadesai * MR_BuildRaidContext: Set up Fast path RAID context 999272744Skadesai * 1000272744Skadesai * This function will initiate command processing. The start/end row and strip 1001272744Skadesai * information is calculated then the lock is acquired. This function will 1002272744Skadesai * return 0 if region lock was acquired OR return num strips. 1003272744Skadesai */ 1004272744Skadesaiu_int8_t 1005265555SambriskoMR_BuildRaidContext(struct mrsas_softc *sc, struct IO_REQUEST_INFO *io_info, 1006272744Skadesai RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map) 1007265555Sambrisko{ 1008272744Skadesai MR_LD_RAID *raid; 1009272744Skadesai u_int32_t ld, stripSize, stripe_mask; 1010272744Skadesai u_int64_t endLba, endStrip, endRow, start_row, start_strip; 1011272744Skadesai REGION_KEY regStart; 1012272744Skadesai REGION_LEN regSize; 1013272744Skadesai u_int8_t num_strips, numRows; 1014272744Skadesai u_int16_t ref_in_start_stripe, ref_in_end_stripe; 1015272744Skadesai u_int64_t ldStartBlock; 1016272744Skadesai u_int32_t numBlocks, ldTgtId; 1017272744Skadesai u_int8_t isRead, stripIdx; 1018272744Skadesai u_int8_t retval = 0; 1019265555Sambrisko u_int8_t startlba_span = SPAN_INVALID; 1020272744Skadesai u_int64_t *pdBlock = &io_info->pdBlock; 1021272744Skadesai int error_code = 0; 1022265555Sambrisko 1023272744Skadesai ldStartBlock = io_info->ldStartBlock; 1024272744Skadesai numBlocks = io_info->numBlocks; 1025272744Skadesai ldTgtId = io_info->ldTgtId; 1026272744Skadesai isRead = io_info->isRead; 1027272744Skadesai 1028265555Sambrisko io_info->IoforUnevenSpan = 0; 1029272744Skadesai io_info->start_span = SPAN_INVALID; 1030265555Sambrisko 1031272744Skadesai ld = MR_TargetIdToLdGet(ldTgtId, map); 1032272744Skadesai raid = MR_LdRaidGet(ld, map); 1033265555Sambrisko 1034342716Skadesai /* check read ahead bit */ 1035342716Skadesai io_info->raCapable = raid->capability.raCapable; 1036342716Skadesai 1037272744Skadesai if (raid->rowDataSize == 0) { 1038272744Skadesai if (MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize == 0) 1039272744Skadesai return FALSE; 1040272744Skadesai else if (sc->UnevenSpanSupport) { 1041272744Skadesai io_info->IoforUnevenSpan = 1; 1042272744Skadesai } else { 1043282531Skadesai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: raid->rowDataSize is 0, but has SPAN[0] rowDataSize = 0x%0x," 1044272744Skadesai " but there is _NO_ UnevenSpanSupport\n", 1045272744Skadesai MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize); 1046272744Skadesai return FALSE; 1047272744Skadesai } 1048265555Sambrisko } 1049272744Skadesai stripSize = 1 << raid->stripeShift; 1050272744Skadesai stripe_mask = stripSize - 1; 1051272744Skadesai /* 1052272744Skadesai * calculate starting row and stripe, and number of strips and rows 1053272744Skadesai */ 1054272744Skadesai start_strip = ldStartBlock >> raid->stripeShift; 1055272744Skadesai ref_in_start_stripe = (u_int16_t)(ldStartBlock & stripe_mask); 1056272744Skadesai endLba = ldStartBlock + numBlocks - 1; 1057272744Skadesai ref_in_end_stripe = (u_int16_t)(endLba & stripe_mask); 1058272744Skadesai endStrip = endLba >> raid->stripeShift; 1059272744Skadesai num_strips = (u_int8_t)(endStrip - start_strip + 1); /* End strip */ 1060272744Skadesai if (io_info->IoforUnevenSpan) { 1061272744Skadesai start_row = get_row_from_strip(sc, ld, start_strip, map); 1062272744Skadesai endRow = get_row_from_strip(sc, ld, endStrip, map); 1063272744Skadesai if (raid->spanDepth == 1) { 1064272744Skadesai startlba_span = 0; 1065272744Skadesai *pdBlock = start_row << raid->stripeShift; 1066272744Skadesai } else { 1067272744Skadesai startlba_span = (u_int8_t)mr_spanset_get_span_block(sc, ld, start_row, 1068272744Skadesai pdBlock, map, &error_code); 1069272744Skadesai if (error_code == 1) { 1070282531Skadesai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: return from %s %d. Send IO w/o region lock.\n", 1071272744Skadesai __func__, __LINE__); 1072272744Skadesai return FALSE; 1073272744Skadesai } 1074272744Skadesai } 1075272744Skadesai if (startlba_span == SPAN_INVALID) { 1076282531Skadesai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: return from %s %d for row 0x%llx," 1077272744Skadesai "start strip %llx endSrip %llx\n", __func__, 1078272744Skadesai __LINE__, (unsigned long long)start_row, 1079272744Skadesai (unsigned long long)start_strip, 1080272744Skadesai (unsigned long long)endStrip); 1081272744Skadesai return FALSE; 1082272744Skadesai } 1083272744Skadesai io_info->start_span = startlba_span; 1084272744Skadesai io_info->start_row = start_row; 1085282531Skadesai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: Check Span number from %s %d for row 0x%llx, " 1086272744Skadesai " start strip 0x%llx endSrip 0x%llx span 0x%x\n", 1087272744Skadesai __func__, __LINE__, (unsigned long long)start_row, 1088272744Skadesai (unsigned long long)start_strip, 1089272744Skadesai (unsigned long long)endStrip, startlba_span); 1090282531Skadesai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug : 1. start_row 0x%llx endRow 0x%llx Start span 0x%x\n", 1091272744Skadesai (unsigned long long)start_row, (unsigned long long)endRow, startlba_span); 1092272744Skadesai } else { 1093272744Skadesai start_row = mega_div64_32(start_strip, raid->rowDataSize); 1094272744Skadesai endRow = mega_div64_32(endStrip, raid->rowDataSize); 1095272744Skadesai } 1096265555Sambrisko 1097272744Skadesai numRows = (u_int8_t)(endRow - start_row + 1); /* get the row count */ 1098265555Sambrisko 1099272744Skadesai /* 1100272744Skadesai * Calculate region info. (Assume region at start of first row, and 1101272744Skadesai * assume this IO needs the full row - will adjust if not true.) 1102272744Skadesai */ 1103272744Skadesai regStart = start_row << raid->stripeShift; 1104272744Skadesai regSize = stripSize; 1105265555Sambrisko 1106272744Skadesai /* Check if we can send this I/O via FastPath */ 1107272744Skadesai if (raid->capability.fpCapable) { 1108272744Skadesai if (isRead) 1109272744Skadesai io_info->fpOkForIo = (raid->capability.fpReadCapable && 1110272744Skadesai ((num_strips == 1) || 1111272744Skadesai raid->capability.fpReadAcrossStripe)); 1112272744Skadesai else 1113272744Skadesai io_info->fpOkForIo = (raid->capability.fpWriteCapable && 1114272744Skadesai ((num_strips == 1) || 1115272744Skadesai raid->capability.fpWriteAcrossStripe)); 1116272744Skadesai } else 1117272744Skadesai io_info->fpOkForIo = FALSE; 1118265555Sambrisko 1119272744Skadesai if (numRows == 1) { 1120272744Skadesai if (num_strips == 1) { 1121272744Skadesai regStart += ref_in_start_stripe; 1122272744Skadesai regSize = numBlocks; 1123272744Skadesai } 1124272744Skadesai } else if (io_info->IoforUnevenSpan == 0) { 1125272744Skadesai /* 1126272744Skadesai * For Even span region lock optimization. If the start strip 1127272744Skadesai * is the last in the start row 1128272744Skadesai */ 1129272744Skadesai if (start_strip == (start_row + 1) * raid->rowDataSize - 1) { 1130272744Skadesai regStart += ref_in_start_stripe; 1131272744Skadesai /* 1132272744Skadesai * initialize count to sectors from startRef to end 1133272744Skadesai * of strip 1134272744Skadesai */ 1135272744Skadesai regSize = stripSize - ref_in_start_stripe; 1136272744Skadesai } 1137272744Skadesai /* add complete rows in the middle of the transfer */ 1138265555Sambrisko if (numRows > 2) 1139272744Skadesai regSize += (numRows - 2) << raid->stripeShift; 1140265555Sambrisko 1141272744Skadesai /* if IO ends within first strip of last row */ 1142272744Skadesai if (endStrip == endRow * raid->rowDataSize) 1143272744Skadesai regSize += ref_in_end_stripe + 1; 1144272744Skadesai else 1145272744Skadesai regSize += stripSize; 1146272744Skadesai } else { 1147272744Skadesai if (start_strip == (get_strip_from_row(sc, ld, start_row, map) + 1148272744Skadesai SPAN_ROW_DATA_SIZE(map, ld, startlba_span) - 1)) { 1149272744Skadesai regStart += ref_in_start_stripe; 1150272744Skadesai /* 1151272744Skadesai * initialize count to sectors from startRef to end 1152272744Skadesai * of strip 1153272744Skadesai */ 1154265555Sambrisko regSize = stripSize - ref_in_start_stripe; 1155272744Skadesai } 1156272744Skadesai /* add complete rows in the middle of the transfer */ 1157272744Skadesai if (numRows > 2) 1158272744Skadesai regSize += (numRows - 2) << raid->stripeShift; 1159265555Sambrisko 1160272744Skadesai /* if IO ends within first strip of last row */ 1161272744Skadesai if (endStrip == get_strip_from_row(sc, ld, endRow, map)) 1162272744Skadesai regSize += ref_in_end_stripe + 1; 1163272744Skadesai else 1164272744Skadesai regSize += stripSize; 1165272744Skadesai } 1166272744Skadesai pRAID_Context->timeoutValue = map->raidMap.fpPdIoTimeoutSec; 1167323819Sjkim if (sc->mrsas_gen3_ctrl) 1168272744Skadesai pRAID_Context->regLockFlags = (isRead) ? raid->regTypeReqOnRead : raid->regTypeReqOnWrite; 1169342716Skadesai else if (sc->device_id == MRSAS_TBOLT) 1170272744Skadesai pRAID_Context->regLockFlags = (isRead) ? REGION_TYPE_SHARED_READ : raid->regTypeReqOnWrite; 1171272744Skadesai pRAID_Context->VirtualDiskTgtId = raid->targetId; 1172272744Skadesai pRAID_Context->regLockRowLBA = regStart; 1173272744Skadesai pRAID_Context->regLockLength = regSize; 1174272744Skadesai pRAID_Context->configSeqNum = raid->seqNum; 1175265555Sambrisko 1176272744Skadesai /* 1177272744Skadesai * Get Phy Params only if FP capable, or else leave it to MR firmware 1178272744Skadesai * to do the calculation. 1179272744Skadesai */ 1180272744Skadesai if (io_info->fpOkForIo) { 1181272744Skadesai retval = io_info->IoforUnevenSpan ? 1182272744Skadesai mr_spanset_get_phy_params(sc, ld, start_strip, 1183272744Skadesai ref_in_start_stripe, io_info, pRAID_Context, map) : 1184272744Skadesai MR_GetPhyParams(sc, ld, start_strip, 1185272744Skadesai ref_in_start_stripe, io_info, pRAID_Context, map); 1186272744Skadesai /* If IO on an invalid Pd, then FP is not possible */ 1187342716Skadesai if (io_info->devHandle == MR_DEVHANDLE_INVALID) 1188272744Skadesai io_info->fpOkForIo = FALSE; 1189342716Skadesai /* 1190342716Skadesai * if FP possible, set the SLUD bit in regLockFlags for 1191342716Skadesai * ventura 1192342716Skadesai */ 1193342720Skadesai else if ((sc->is_ventura || sc->is_aero) && !isRead && 1194342716Skadesai (raid->writeMode == MR_RL_WRITE_BACK_MODE) && (raid->level <= 1) && 1195342716Skadesai raid->capability.fpCacheBypassCapable) { 1196342716Skadesai ((RAID_CONTEXT_G35 *) pRAID_Context)->routingFlags.bits.sld = 1; 1197342716Skadesai } 1198342716Skadesai 1199272744Skadesai return retval; 1200272744Skadesai } else if (isRead) { 1201272744Skadesai for (stripIdx = 0; stripIdx < num_strips; stripIdx++) { 1202272744Skadesai retval = io_info->IoforUnevenSpan ? 1203272744Skadesai mr_spanset_get_phy_params(sc, ld, start_strip + stripIdx, 1204272744Skadesai ref_in_start_stripe, io_info, pRAID_Context, map) : 1205272744Skadesai MR_GetPhyParams(sc, ld, start_strip + stripIdx, 1206272744Skadesai ref_in_start_stripe, io_info, pRAID_Context, map); 1207272744Skadesai if (!retval) 1208272744Skadesai return TRUE; 1209272744Skadesai } 1210272744Skadesai } 1211265555Sambrisko#if SPAN_DEBUG 1212272744Skadesai /* Just for testing what arm we get for strip. */ 1213272744Skadesai get_arm_from_strip(sc, ld, start_strip, map); 1214265555Sambrisko#endif 1215272744Skadesai return TRUE; 1216265555Sambrisko} 1217265555Sambrisko 1218265555Sambrisko/* 1219272744Skadesai * 1220272744Skadesai * This routine pepare spanset info from Valid Raid map and store it into local 1221272744Skadesai * copy of ldSpanInfo per instance data structure. 1222272744Skadesai * 1223272744Skadesai * Inputs : LD map 1224272744Skadesai * ldSpanInfo per HBA instance 1225272744Skadesai * 1226272744Skadesai */ 1227272744Skadesaivoid 1228272744Skadesaimr_update_span_set(MR_DRV_RAID_MAP_ALL * map, PLD_SPAN_INFO ldSpanInfo) 1229265555Sambrisko{ 1230272744Skadesai u_int8_t span, count; 1231272744Skadesai u_int32_t element, span_row_width; 1232272744Skadesai u_int64_t span_row; 1233272744Skadesai MR_LD_RAID *raid; 1234272744Skadesai LD_SPAN_SET *span_set, *span_set_prev; 1235272744Skadesai MR_QUAD_ELEMENT *quad; 1236272744Skadesai int ldCount; 1237272744Skadesai u_int16_t ld; 1238272735Skadesai 1239272744Skadesai for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) { 1240272744Skadesai ld = MR_TargetIdToLdGet(ldCount, map); 1241272744Skadesai if (ld >= MAX_LOGICAL_DRIVES) 1242272744Skadesai continue; 1243272744Skadesai raid = MR_LdRaidGet(ld, map); 1244272744Skadesai for (element = 0; element < MAX_QUAD_DEPTH; element++) { 1245272744Skadesai for (span = 0; span < raid->spanDepth; span++) { 1246272744Skadesai if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 1247272744Skadesai block_span_info.noElements < element + 1) 1248272744Skadesai continue; 1249272744Skadesai /* TO-DO */ 1250272744Skadesai span_set = &(ldSpanInfo[ld].span_set[element]); 1251272744Skadesai quad = &map->raidMap.ldSpanMap[ld]. 1252272744Skadesai spanBlock[span].block_span_info.quad[element]; 1253265555Sambrisko 1254272744Skadesai span_set->diff = quad->diff; 1255265555Sambrisko 1256272744Skadesai for (count = 0, span_row_width = 0; 1257272744Skadesai count < raid->spanDepth; count++) { 1258272744Skadesai if (map->raidMap.ldSpanMap[ld].spanBlock[count]. 1259272744Skadesai block_span_info.noElements >= element + 1) { 1260272744Skadesai span_set->strip_offset[count] = span_row_width; 1261272744Skadesai span_row_width += 1262272744Skadesai MR_LdSpanPtrGet(ld, count, map)->spanRowDataSize; 1263265555Sambrisko#if SPAN_DEBUG 1264282531Skadesai printf("AVAGO Debug span %x rowDataSize %x\n", count, 1265272744Skadesai MR_LdSpanPtrGet(ld, count, map)->spanRowDataSize); 1266265555Sambrisko#endif 1267272744Skadesai } 1268272744Skadesai } 1269265555Sambrisko 1270272744Skadesai span_set->span_row_data_width = span_row_width; 1271272744Skadesai span_row = mega_div64_32(((quad->logEnd - 1272272744Skadesai quad->logStart) + quad->diff), quad->diff); 1273265555Sambrisko 1274272744Skadesai if (element == 0) { 1275272744Skadesai span_set->log_start_lba = 0; 1276272744Skadesai span_set->log_end_lba = 1277272744Skadesai ((span_row << raid->stripeShift) * span_row_width) - 1; 1278265555Sambrisko 1279272744Skadesai span_set->span_row_start = 0; 1280272744Skadesai span_set->span_row_end = span_row - 1; 1281265555Sambrisko 1282272744Skadesai span_set->data_strip_start = 0; 1283272744Skadesai span_set->data_strip_end = (span_row * span_row_width) - 1; 1284265555Sambrisko 1285272744Skadesai span_set->data_row_start = 0; 1286272744Skadesai span_set->data_row_end = (span_row * quad->diff) - 1; 1287272744Skadesai } else { 1288272744Skadesai span_set_prev = &(ldSpanInfo[ld].span_set[element - 1]); 1289272744Skadesai span_set->log_start_lba = span_set_prev->log_end_lba + 1; 1290272744Skadesai span_set->log_end_lba = span_set->log_start_lba + 1291272744Skadesai ((span_row << raid->stripeShift) * span_row_width) - 1; 1292265555Sambrisko 1293272744Skadesai span_set->span_row_start = span_set_prev->span_row_end + 1; 1294272744Skadesai span_set->span_row_end = 1295272744Skadesai span_set->span_row_start + span_row - 1; 1296272744Skadesai 1297272744Skadesai span_set->data_strip_start = 1298272744Skadesai span_set_prev->data_strip_end + 1; 1299272744Skadesai span_set->data_strip_end = span_set->data_strip_start + 1300272744Skadesai (span_row * span_row_width) - 1; 1301272744Skadesai 1302272744Skadesai span_set->data_row_start = span_set_prev->data_row_end + 1; 1303272744Skadesai span_set->data_row_end = span_set->data_row_start + 1304272744Skadesai (span_row * quad->diff) - 1; 1305272744Skadesai } 1306272744Skadesai break; 1307272744Skadesai } 1308272744Skadesai if (span == raid->spanDepth) 1309272744Skadesai break; /* no quads remain */ 1310272744Skadesai } 1311272744Skadesai } 1312265555Sambrisko#if SPAN_DEBUG 1313272744Skadesai getSpanInfo(map, ldSpanInfo); /* to get span set info */ 1314265555Sambrisko#endif 1315265555Sambrisko} 1316265555Sambrisko 1317272744Skadesai/* 1318272744Skadesai * mrsas_update_load_balance_params: Update load balance parmas 1319282527Skadesai * Inputs: 1320282527Skadesai * sc - driver softc instance 1321282527Skadesai * drv_map - driver RAID map 1322282527Skadesai * lbInfo - Load balance info 1323265555Sambrisko * 1324272744Skadesai * This function updates the load balance parameters for the LD config of a two 1325272744Skadesai * drive optimal RAID-1. 1326265555Sambrisko */ 1327282533Skadesaivoid 1328282527Skadesaimrsas_update_load_balance_params(struct mrsas_softc *sc, 1329282533Skadesai MR_DRV_RAID_MAP_ALL * drv_map, PLD_LOAD_BALANCE_INFO lbInfo) 1330265555Sambrisko{ 1331272744Skadesai int ldCount; 1332272744Skadesai u_int16_t ld; 1333272744Skadesai MR_LD_RAID *raid; 1334265555Sambrisko 1335282533Skadesai if (sc->lb_pending_cmds > 128 || sc->lb_pending_cmds < 1) 1336282533Skadesai sc->lb_pending_cmds = LB_PENDING_CMDS_DEFAULT; 1337282527Skadesai 1338282527Skadesai for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES_EXT; ldCount++) { 1339282527Skadesai ld = MR_TargetIdToLdGet(ldCount, drv_map); 1340282527Skadesai if (ld >= MAX_LOGICAL_DRIVES_EXT) { 1341272744Skadesai lbInfo[ldCount].loadBalanceFlag = 0; 1342272744Skadesai continue; 1343272744Skadesai } 1344282527Skadesai raid = MR_LdRaidGet(ld, drv_map); 1345282527Skadesai if ((raid->level != 1) || 1346282533Skadesai (raid->ldState != MR_LD_STATE_OPTIMAL)) { 1347272744Skadesai lbInfo[ldCount].loadBalanceFlag = 0; 1348282527Skadesai continue; 1349282527Skadesai } 1350282527Skadesai lbInfo[ldCount].loadBalanceFlag = 1; 1351272744Skadesai } 1352265555Sambrisko} 1353265555Sambrisko 1354265555Sambrisko 1355272744Skadesai/* 1356272744Skadesai * mrsas_set_pd_lba: Sets PD LBA 1357272744Skadesai * input: io_request pointer 1358272744Skadesai * CDB length 1359272744Skadesai * io_info pointer 1360272744Skadesai * Pointer to CCB 1361272744Skadesai * Local RAID map pointer 1362272744Skadesai * Start block of IO Block Size 1363265555Sambrisko * 1364265555Sambrisko * Used to set the PD logical block address in CDB for FP IOs. 1365265555Sambrisko */ 1366282533Skadesaivoid 1367272744Skadesaimrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request, u_int8_t cdb_len, 1368265555Sambrisko struct IO_REQUEST_INFO *io_info, union ccb *ccb, 1369272744Skadesai MR_DRV_RAID_MAP_ALL * local_map_ptr, u_int32_t ref_tag, 1370265555Sambrisko u_int32_t ld_block_size) 1371265555Sambrisko{ 1372272744Skadesai MR_LD_RAID *raid; 1373272744Skadesai u_int32_t ld; 1374272744Skadesai u_int64_t start_blk = io_info->pdBlock; 1375272744Skadesai u_int8_t *cdb = io_request->CDB.CDB32; 1376272744Skadesai u_int32_t num_blocks = io_info->numBlocks; 1377272744Skadesai u_int8_t opcode = 0, flagvals = 0, groupnum = 0, control = 0; 1378272744Skadesai struct ccb_hdr *ccb_h = &(ccb->ccb_h); 1379265555Sambrisko 1380272744Skadesai /* Check if T10 PI (DIF) is enabled for this LD */ 1381272744Skadesai ld = MR_TargetIdToLdGet(io_info->ldTgtId, local_map_ptr); 1382272744Skadesai raid = MR_LdRaidGet(ld, local_map_ptr); 1383272744Skadesai if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER) { 1384272744Skadesai memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1385272744Skadesai cdb[0] = MRSAS_SCSI_VARIABLE_LENGTH_CMD; 1386272744Skadesai cdb[7] = MRSAS_SCSI_ADDL_CDB_LEN; 1387265555Sambrisko 1388272744Skadesai if (ccb_h->flags == CAM_DIR_OUT) 1389272744Skadesai cdb[9] = MRSAS_SCSI_SERVICE_ACTION_READ32; 1390272744Skadesai else 1391272744Skadesai cdb[9] = MRSAS_SCSI_SERVICE_ACTION_WRITE32; 1392272744Skadesai cdb[10] = MRSAS_RD_WR_PROTECT_CHECK_ALL; 1393265555Sambrisko 1394272744Skadesai /* LBA */ 1395272744Skadesai cdb[12] = (u_int8_t)((start_blk >> 56) & 0xff); 1396272744Skadesai cdb[13] = (u_int8_t)((start_blk >> 48) & 0xff); 1397272744Skadesai cdb[14] = (u_int8_t)((start_blk >> 40) & 0xff); 1398272744Skadesai cdb[15] = (u_int8_t)((start_blk >> 32) & 0xff); 1399272744Skadesai cdb[16] = (u_int8_t)((start_blk >> 24) & 0xff); 1400272744Skadesai cdb[17] = (u_int8_t)((start_blk >> 16) & 0xff); 1401272744Skadesai cdb[18] = (u_int8_t)((start_blk >> 8) & 0xff); 1402272744Skadesai cdb[19] = (u_int8_t)(start_blk & 0xff); 1403265555Sambrisko 1404272744Skadesai /* Logical block reference tag */ 1405272744Skadesai io_request->CDB.EEDP32.PrimaryReferenceTag = swap32(ref_tag); 1406272744Skadesai io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0xffff; 1407272744Skadesai io_request->IoFlags = 32; /* Specify 32-byte cdb */ 1408265555Sambrisko 1409272744Skadesai /* Transfer length */ 1410272744Skadesai cdb[28] = (u_int8_t)((num_blocks >> 24) & 0xff); 1411272744Skadesai cdb[29] = (u_int8_t)((num_blocks >> 16) & 0xff); 1412272744Skadesai cdb[30] = (u_int8_t)((num_blocks >> 8) & 0xff); 1413272744Skadesai cdb[31] = (u_int8_t)(num_blocks & 0xff); 1414265555Sambrisko 1415272744Skadesai /* set SCSI IO EEDP Flags */ 1416272744Skadesai if (ccb_h->flags == CAM_DIR_OUT) { 1417272744Skadesai io_request->EEDPFlags = 1418272744Skadesai MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | 1419272744Skadesai MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | 1420272744Skadesai MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP | 1421272744Skadesai MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG | 1422272744Skadesai MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; 1423272744Skadesai } else { 1424272744Skadesai io_request->EEDPFlags = 1425272744Skadesai MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | 1426272744Skadesai MPI2_SCSIIO_EEDPFLAGS_INSERT_OP; 1427272744Skadesai } 1428272744Skadesai io_request->Control |= (0x4 << 26); 1429272744Skadesai io_request->EEDPBlockSize = ld_block_size; 1430272744Skadesai } else { 1431272744Skadesai /* Some drives don't support 16/12 byte CDB's, convert to 10 */ 1432272744Skadesai if (((cdb_len == 12) || (cdb_len == 16)) && 1433272744Skadesai (start_blk <= 0xffffffff)) { 1434272744Skadesai if (cdb_len == 16) { 1435272744Skadesai opcode = cdb[0] == READ_16 ? READ_10 : WRITE_10; 1436272744Skadesai flagvals = cdb[1]; 1437272744Skadesai groupnum = cdb[14]; 1438272744Skadesai control = cdb[15]; 1439272744Skadesai } else { 1440272744Skadesai opcode = cdb[0] == READ_12 ? READ_10 : WRITE_10; 1441272744Skadesai flagvals = cdb[1]; 1442272744Skadesai groupnum = cdb[10]; 1443272744Skadesai control = cdb[11]; 1444272744Skadesai } 1445265555Sambrisko 1446272744Skadesai memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1447265555Sambrisko 1448272744Skadesai cdb[0] = opcode; 1449272744Skadesai cdb[1] = flagvals; 1450272744Skadesai cdb[6] = groupnum; 1451272744Skadesai cdb[9] = control; 1452265555Sambrisko 1453272744Skadesai /* Transfer length */ 1454272744Skadesai cdb[8] = (u_int8_t)(num_blocks & 0xff); 1455272744Skadesai cdb[7] = (u_int8_t)((num_blocks >> 8) & 0xff); 1456265555Sambrisko 1457272744Skadesai io_request->IoFlags = 10; /* Specify 10-byte cdb */ 1458272744Skadesai cdb_len = 10; 1459272744Skadesai } else if ((cdb_len < 16) && (start_blk > 0xffffffff)) { 1460272744Skadesai /* Convert to 16 byte CDB for large LBA's */ 1461272744Skadesai switch (cdb_len) { 1462272744Skadesai case 6: 1463272744Skadesai opcode = cdb[0] == READ_6 ? READ_16 : WRITE_16; 1464272744Skadesai control = cdb[5]; 1465272744Skadesai break; 1466272744Skadesai case 10: 1467272744Skadesai opcode = cdb[0] == READ_10 ? READ_16 : WRITE_16; 1468272744Skadesai flagvals = cdb[1]; 1469272744Skadesai groupnum = cdb[6]; 1470272744Skadesai control = cdb[9]; 1471272744Skadesai break; 1472272744Skadesai case 12: 1473272744Skadesai opcode = cdb[0] == READ_12 ? READ_16 : WRITE_16; 1474272744Skadesai flagvals = cdb[1]; 1475272744Skadesai groupnum = cdb[10]; 1476272744Skadesai control = cdb[11]; 1477272744Skadesai break; 1478272744Skadesai } 1479265555Sambrisko 1480272744Skadesai memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1481265555Sambrisko 1482272744Skadesai cdb[0] = opcode; 1483272744Skadesai cdb[1] = flagvals; 1484272744Skadesai cdb[14] = groupnum; 1485272744Skadesai cdb[15] = control; 1486265555Sambrisko 1487272744Skadesai /* Transfer length */ 1488272744Skadesai cdb[13] = (u_int8_t)(num_blocks & 0xff); 1489272744Skadesai cdb[12] = (u_int8_t)((num_blocks >> 8) & 0xff); 1490272744Skadesai cdb[11] = (u_int8_t)((num_blocks >> 16) & 0xff); 1491272744Skadesai cdb[10] = (u_int8_t)((num_blocks >> 24) & 0xff); 1492265555Sambrisko 1493272744Skadesai io_request->IoFlags = 16; /* Specify 16-byte cdb */ 1494272744Skadesai cdb_len = 16; 1495272744Skadesai } else if ((cdb_len == 6) && (start_blk > 0x1fffff)) { 1496272744Skadesai /* convert to 10 byte CDB */ 1497272744Skadesai opcode = cdb[0] == READ_6 ? READ_10 : WRITE_10; 1498272744Skadesai control = cdb[5]; 1499265555Sambrisko 1500272744Skadesai memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1501272744Skadesai cdb[0] = opcode; 1502272744Skadesai cdb[9] = control; 1503265555Sambrisko 1504272744Skadesai /* Set transfer length */ 1505272744Skadesai cdb[8] = (u_int8_t)(num_blocks & 0xff); 1506272744Skadesai cdb[7] = (u_int8_t)((num_blocks >> 8) & 0xff); 1507272744Skadesai 1508272744Skadesai /* Specify 10-byte cdb */ 1509272744Skadesai cdb_len = 10; 1510272744Skadesai } 1511272744Skadesai /* Fall through normal case, just load LBA here */ 1512272744Skadesai u_int8_t val = cdb[1] & 0xE0; 1513282533Skadesai 1514272744Skadesai switch (cdb_len) { 1515272744Skadesai case 6: 1516272744Skadesai cdb[3] = (u_int8_t)(start_blk & 0xff); 1517272744Skadesai cdb[2] = (u_int8_t)((start_blk >> 8) & 0xff); 1518272744Skadesai cdb[1] = val | ((u_int8_t)(start_blk >> 16) & 0x1f); 1519272744Skadesai break; 1520272744Skadesai case 10: 1521272744Skadesai cdb[5] = (u_int8_t)(start_blk & 0xff); 1522272744Skadesai cdb[4] = (u_int8_t)((start_blk >> 8) & 0xff); 1523272744Skadesai cdb[3] = (u_int8_t)((start_blk >> 16) & 0xff); 1524272744Skadesai cdb[2] = (u_int8_t)((start_blk >> 24) & 0xff); 1525272744Skadesai break; 1526272744Skadesai case 16: 1527272744Skadesai cdb[9] = (u_int8_t)(start_blk & 0xff); 1528272744Skadesai cdb[8] = (u_int8_t)((start_blk >> 8) & 0xff); 1529272744Skadesai cdb[7] = (u_int8_t)((start_blk >> 16) & 0xff); 1530272744Skadesai cdb[6] = (u_int8_t)((start_blk >> 24) & 0xff); 1531272744Skadesai cdb[5] = (u_int8_t)((start_blk >> 32) & 0xff); 1532272744Skadesai cdb[4] = (u_int8_t)((start_blk >> 40) & 0xff); 1533272744Skadesai cdb[3] = (u_int8_t)((start_blk >> 48) & 0xff); 1534272744Skadesai cdb[2] = (u_int8_t)((start_blk >> 56) & 0xff); 1535272744Skadesai break; 1536272744Skadesai } 1537265555Sambrisko } 1538265555Sambrisko} 1539265555Sambrisko 1540272744Skadesai/* 1541282527Skadesai * mrsas_get_best_arm_pd: Determine the best spindle arm 1542282527Skadesai * Inputs: 1543282527Skadesai * sc - HBA instance 1544282527Skadesai * lbInfo - Load balance info 1545282527Skadesai * io_info - IO request info 1546265555Sambrisko * 1547265555Sambrisko * This function determines and returns the best arm by looking at the 1548265555Sambrisko * parameters of the last PD access. 1549265555Sambrisko */ 1550282533Skadesaiu_int8_t 1551282533Skadesaimrsas_get_best_arm_pd(struct mrsas_softc *sc, 1552282533Skadesai PLD_LOAD_BALANCE_INFO lbInfo, struct IO_REQUEST_INFO *io_info) 1553265555Sambrisko{ 1554282533Skadesai MR_LD_RAID *raid; 1555282527Skadesai MR_DRV_RAID_MAP_ALL *drv_map; 1556342716Skadesai u_int16_t pd1_devHandle; 1557282527Skadesai u_int16_t pend0, pend1, ld; 1558272744Skadesai u_int64_t diff0, diff1; 1559282527Skadesai u_int8_t bestArm, pd0, pd1, span, arm; 1560282527Skadesai u_int32_t arRef, span_row_size; 1561265555Sambrisko 1562282527Skadesai u_int64_t block = io_info->ldStartBlock; 1563282527Skadesai u_int32_t count = io_info->numBlocks; 1564282527Skadesai 1565282527Skadesai span = ((io_info->span_arm & RAID_CTX_SPANARM_SPAN_MASK) 1566282533Skadesai >> RAID_CTX_SPANARM_SPAN_SHIFT); 1567282527Skadesai arm = (io_info->span_arm & RAID_CTX_SPANARM_ARM_MASK); 1568282527Skadesai 1569282527Skadesai drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 1570282527Skadesai ld = MR_TargetIdToLdGet(io_info->ldTgtId, drv_map); 1571282527Skadesai raid = MR_LdRaidGet(ld, drv_map); 1572282527Skadesai span_row_size = sc->UnevenSpanSupport ? 1573282533Skadesai SPAN_ROW_SIZE(drv_map, ld, span) : raid->rowSize; 1574282527Skadesai 1575282533Skadesai arRef = MR_LdSpanArrayGet(ld, span, drv_map); 1576282533Skadesai pd0 = MR_ArPdGet(arRef, arm, drv_map); 1577282533Skadesai pd1 = MR_ArPdGet(arRef, (arm + 1) >= span_row_size ? 1578282533Skadesai (arm + 1 - span_row_size) : arm + 1, drv_map); 1579282527Skadesai 1580342716Skadesai /* Get PD1 Dev Handle */ 1581342716Skadesai pd1_devHandle = MR_PdDevHandleGet(pd1, drv_map); 1582342716Skadesai if (pd1_devHandle == MR_DEVHANDLE_INVALID) { 1583342716Skadesai bestArm = arm; 1584342716Skadesai } else { 1585342716Skadesai /* get the pending cmds for the data and mirror arms */ 1586342716Skadesai pend0 = mrsas_atomic_read(&lbInfo->scsi_pending_cmds[pd0]); 1587342716Skadesai pend1 = mrsas_atomic_read(&lbInfo->scsi_pending_cmds[pd1]); 1588265555Sambrisko 1589342716Skadesai /* Determine the disk whose head is nearer to the req. block */ 1590342716Skadesai diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[pd0]); 1591342716Skadesai diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[pd1]); 1592342716Skadesai bestArm = (diff0 <= diff1 ? arm : arm ^ 1); 1593265555Sambrisko 1594342716Skadesai if ((bestArm == arm && pend0 > pend1 + sc->lb_pending_cmds) || 1595342716Skadesai (bestArm != arm && pend1 > pend0 + sc->lb_pending_cmds)) 1596342716Skadesai bestArm ^= 1; 1597265555Sambrisko 1598342716Skadesai /* Update the last accessed block on the correct pd */ 1599342716Skadesai io_info->span_arm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | bestArm; 1600342716Skadesai io_info->pd_after_lb = (bestArm == arm) ? pd0 : pd1; 1601342716Skadesai } 1602342716Skadesai 1603282533Skadesai lbInfo->last_accessed_block[bestArm == arm ? pd0 : pd1] = block + count - 1; 1604282527Skadesai#if SPAN_DEBUG 1605282533Skadesai if (arm != bestArm) 1606282533Skadesai printf("AVAGO Debug R1 Load balance occur - span 0x%x arm 0x%x bestArm 0x%x " 1607282533Skadesai "io_info->span_arm 0x%x\n", 1608282533Skadesai span, arm, bestArm, io_info->span_arm); 1609282527Skadesai#endif 1610265555Sambrisko 1611282527Skadesai return io_info->pd_after_lb; 1612265555Sambrisko} 1613265555Sambrisko 1614272744Skadesai/* 1615272744Skadesai * mrsas_get_updated_dev_handle: Get the update dev handle 1616282527Skadesai * Inputs: 1617282527Skadesai * sc - Adapter instance soft state 1618282527Skadesai * lbInfo - Load balance info 1619282527Skadesai * io_info - io_info pointer 1620265555Sambrisko * 1621265555Sambrisko * This function determines and returns the updated dev handle. 1622265555Sambrisko */ 1623282533Skadesaiu_int16_t 1624282533Skadesaimrsas_get_updated_dev_handle(struct mrsas_softc *sc, 1625282533Skadesai PLD_LOAD_BALANCE_INFO lbInfo, struct IO_REQUEST_INFO *io_info) 1626265555Sambrisko{ 1627282527Skadesai u_int8_t arm_pd; 1628272744Skadesai u_int16_t devHandle; 1629282527Skadesai MR_DRV_RAID_MAP_ALL *drv_map; 1630265555Sambrisko 1631282527Skadesai drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 1632265555Sambrisko 1633272744Skadesai /* get best new arm */ 1634282533Skadesai arm_pd = mrsas_get_best_arm_pd(sc, lbInfo, io_info); 1635282527Skadesai devHandle = MR_PdDevHandleGet(arm_pd, drv_map); 1636342716Skadesai io_info->pdInterface = MR_PdInterfaceTypeGet(arm_pd, drv_map); 1637282527Skadesai mrsas_atomic_inc(&lbInfo->scsi_pending_cmds[arm_pd]); 1638265555Sambrisko 1639272744Skadesai return devHandle; 1640265555Sambrisko} 1641265555Sambrisko 1642272744Skadesai/* 1643272744Skadesai * MR_GetPhyParams: Calculates arm, span, and block 1644272744Skadesai * Inputs: Adapter soft state 1645272744Skadesai * Logical drive number (LD) 1646272744Skadesai * Stripe number(stripRow) 1647272744Skadesai * Reference in stripe (stripRef) 1648265555Sambrisko * 1649272744Skadesai * Outputs: Absolute Block number in the physical disk 1650272744Skadesai * 1651272744Skadesai * This routine calculates the arm, span and block for the specified stripe and 1652272744Skadesai * reference in stripe. 1653265555Sambrisko */ 1654272744Skadesaiu_int8_t 1655272744SkadesaiMR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld, 1656272744Skadesai u_int64_t stripRow, 1657272744Skadesai u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 1658272744Skadesai RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map) 1659265555Sambrisko{ 1660272744Skadesai MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 1661342716Skadesai u_int32_t pd, arRef, r1_alt_pd; 1662272744Skadesai u_int8_t physArm, span; 1663272744Skadesai u_int64_t row; 1664272744Skadesai u_int8_t retval = TRUE; 1665272744Skadesai int error_code = 0; 1666265555Sambrisko u_int64_t *pdBlock = &io_info->pdBlock; 1667272744Skadesai u_int16_t *pDevHandle = &io_info->devHandle; 1668342716Skadesai u_int8_t *pPdInterface = &io_info->pdInterface; 1669272744Skadesai u_int32_t rowMod, armQ, arm, logArm; 1670265555Sambrisko 1671272744Skadesai row = mega_div64_32(stripRow, raid->rowDataSize); 1672265555Sambrisko 1673272744Skadesai if (raid->level == 6) { 1674272744Skadesai /* logical arm within row */ 1675272744Skadesai logArm = mega_mod64(stripRow, raid->rowDataSize); 1676272744Skadesai if (raid->rowSize == 0) 1677272744Skadesai return FALSE; 1678272744Skadesai rowMod = mega_mod64(row, raid->rowSize); /* get logical row mod */ 1679272744Skadesai armQ = raid->rowSize - 1 - rowMod; /* index of Q drive */ 1680272744Skadesai arm = armQ + 1 + logArm;/* data always logically follows Q */ 1681272744Skadesai if (arm >= raid->rowSize) /* handle wrap condition */ 1682272744Skadesai arm -= raid->rowSize; 1683272744Skadesai physArm = (u_int8_t)arm; 1684272744Skadesai } else { 1685272744Skadesai if (raid->modFactor == 0) 1686272744Skadesai return FALSE; 1687272744Skadesai physArm = MR_LdDataArmGet(ld, mega_mod64(stripRow, raid->modFactor), map); 1688272744Skadesai } 1689265555Sambrisko 1690272744Skadesai if (raid->spanDepth == 1) { 1691272744Skadesai span = 0; 1692272744Skadesai *pdBlock = row << raid->stripeShift; 1693272744Skadesai } else { 1694272744Skadesai span = (u_int8_t)MR_GetSpanBlock(ld, row, pdBlock, map, &error_code); 1695272744Skadesai if (error_code == 1) 1696272744Skadesai return FALSE; 1697272744Skadesai } 1698265555Sambrisko 1699272744Skadesai /* Get the array on which this span is present */ 1700272744Skadesai arRef = MR_LdSpanArrayGet(ld, span, map); 1701265555Sambrisko 1702272744Skadesai pd = MR_ArPdGet(arRef, physArm, map); /* Get the Pd. */ 1703265555Sambrisko 1704342716Skadesai if (pd != MR_PD_INVALID) { 1705272744Skadesai /* Get dev handle from Pd */ 1706272744Skadesai *pDevHandle = MR_PdDevHandleGet(pd, map); 1707342716Skadesai *pPdInterface = MR_PdInterfaceTypeGet(pd, map); 1708342716Skadesai /* get second pd also for raid 1/10 fast path writes */ 1709342716Skadesai if ((raid->level == 1) && !io_info->isRead) { 1710342716Skadesai r1_alt_pd = MR_ArPdGet(arRef, physArm + 1, map); 1711342716Skadesai if (r1_alt_pd != MR_PD_INVALID) 1712342716Skadesai io_info->r1_alt_dev_handle = MR_PdDevHandleGet(r1_alt_pd, map); 1713342716Skadesai } 1714342716Skadesai } else { 1715342716Skadesai *pDevHandle = MR_DEVHANDLE_INVALID; /* set dev handle as invalid. */ 1716342716Skadesai if ((raid->level >= 5) && ((sc->device_id == MRSAS_TBOLT) || 1717342716Skadesai (sc->mrsas_gen3_ctrl && 1718342716Skadesai raid->regTypeReqOnRead != REGION_TYPE_UNUSED))) 1719272744Skadesai pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; 1720272744Skadesai else if (raid->level == 1) { 1721272744Skadesai /* Get Alternate Pd. */ 1722272744Skadesai pd = MR_ArPdGet(arRef, physArm + 1, map); 1723342716Skadesai if (pd != MR_PD_INVALID) { 1724272744Skadesai /* Get dev handle from Pd. */ 1725272744Skadesai *pDevHandle = MR_PdDevHandleGet(pd, map); 1726342716Skadesai *pPdInterface = MR_PdInterfaceTypeGet(pd, map); 1727342716Skadesai } 1728272744Skadesai } 1729272744Skadesai } 1730265555Sambrisko 1731272744Skadesai *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk; 1732342720Skadesai if (sc->is_ventura || sc->is_aero) { 1733342716Skadesai ((RAID_CONTEXT_G35 *) pRAID_Context)->spanArm = 1734342716Skadesai (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; 1735342716Skadesai io_info->span_arm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; 1736342716Skadesai } else { 1737342716Skadesai pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; 1738342716Skadesai io_info->span_arm = pRAID_Context->spanArm; 1739342716Skadesai } 1740272744Skadesai return retval; 1741265555Sambrisko} 1742265555Sambrisko 1743272744Skadesai/* 1744272744Skadesai * MR_GetSpanBlock: Calculates span block 1745272744Skadesai * Inputs: LD 1746272744Skadesai * row PD 1747272744Skadesai * span block 1748272744Skadesai * RAID map pointer 1749265555Sambrisko * 1750272744Skadesai * Outputs: Span number Error code 1751272744Skadesai * 1752272744Skadesai * This routine calculates the span from the span block info. 1753265555Sambrisko */ 1754272744Skadesaiu_int32_t 1755272744SkadesaiMR_GetSpanBlock(u_int32_t ld, u_int64_t row, u_int64_t *span_blk, 1756272744Skadesai MR_DRV_RAID_MAP_ALL * map, int *div_error) 1757265555Sambrisko{ 1758272744Skadesai MR_SPAN_BLOCK_INFO *pSpanBlock = MR_LdSpanInfoGet(ld, map); 1759272744Skadesai MR_QUAD_ELEMENT *quad; 1760272744Skadesai MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 1761272744Skadesai u_int32_t span, j; 1762272744Skadesai u_int64_t blk, debugBlk; 1763265555Sambrisko 1764272744Skadesai for (span = 0; span < raid->spanDepth; span++, pSpanBlock++) { 1765272744Skadesai for (j = 0; j < pSpanBlock->block_span_info.noElements; j++) { 1766272744Skadesai quad = &pSpanBlock->block_span_info.quad[j]; 1767272744Skadesai if (quad->diff == 0) { 1768272744Skadesai *div_error = 1; 1769272744Skadesai return span; 1770272744Skadesai } 1771272744Skadesai if (quad->logStart <= row && row <= quad->logEnd && 1772272744Skadesai (mega_mod64(row - quad->logStart, quad->diff)) == 0) { 1773272744Skadesai if (span_blk != NULL) { 1774272744Skadesai blk = mega_div64_32((row - quad->logStart), quad->diff); 1775272744Skadesai debugBlk = blk; 1776272744Skadesai blk = (blk + quad->offsetInSpan) << raid->stripeShift; 1777272744Skadesai *span_blk = blk; 1778272744Skadesai } 1779272744Skadesai return span; 1780272744Skadesai } 1781272744Skadesai } 1782272744Skadesai } 1783272744Skadesai return span; 1784265555Sambrisko} 1785