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