1665484d8SDoug Ambrisko /* 2ecea5be4SKashyap D Desai * Copyright (c) 2015, AVAGO Tech. All rights reserved. Author: Marian Choy 38e727371SKashyap D Desai * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy 4ecea5be4SKashyap D Desai * Support: freebsdraid@avagotech.com 5665484d8SDoug Ambrisko * 6665484d8SDoug Ambrisko * Redistribution and use in source and binary forms, with or without 78e727371SKashyap D Desai * modification, are permitted provided that the following conditions are 88e727371SKashyap D Desai * met: 9665484d8SDoug Ambrisko * 108e727371SKashyap D Desai * 1. Redistributions of source code must retain the above copyright notice, 118e727371SKashyap D Desai * this list of conditions and the following disclaimer. 2. Redistributions 128e727371SKashyap D Desai * in binary form must reproduce the above copyright notice, this list of 138e727371SKashyap D Desai * conditions and the following disclaimer in the documentation and/or other 148e727371SKashyap D Desai * materials provided with the distribution. 3. Neither the name of the 158e727371SKashyap D Desai * <ORGANIZATION> nor the names of its contributors may be used to endorse or 168e727371SKashyap D Desai * promote products derived from this software without specific prior written 178e727371SKashyap D Desai * permission. 18665484d8SDoug Ambrisko * 198e727371SKashyap D Desai * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 208e727371SKashyap D Desai * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 218e727371SKashyap D Desai * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 228e727371SKashyap D Desai * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 238e727371SKashyap D Desai * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 248e727371SKashyap D Desai * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 258e727371SKashyap D Desai * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 268e727371SKashyap D Desai * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 278e727371SKashyap D Desai * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 288e727371SKashyap D Desai * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29665484d8SDoug Ambrisko * POSSIBILITY OF SUCH DAMAGE. 30665484d8SDoug Ambrisko * 318e727371SKashyap D Desai * The views and conclusions contained in the software and documentation are 328e727371SKashyap D Desai * those of the authors and should not be interpreted as representing 33665484d8SDoug Ambrisko * official policies,either expressed or implied, of the FreeBSD Project. 34665484d8SDoug Ambrisko * 35ecea5be4SKashyap D Desai * Send feedback to: <megaraidfbsd@avagotech.com> Mail to: AVAGO TECHNOLOGIES, 1621 368e727371SKashyap D Desai * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD 37665484d8SDoug Ambrisko * 38665484d8SDoug Ambrisko */ 39665484d8SDoug Ambrisko 40665484d8SDoug Ambrisko #include <sys/cdefs.h> 41665484d8SDoug Ambrisko __FBSDID("$FreeBSD$"); 42665484d8SDoug Ambrisko 43665484d8SDoug Ambrisko #include <dev/mrsas/mrsas.h> 44665484d8SDoug Ambrisko 45665484d8SDoug Ambrisko #include <cam/cam.h> 46665484d8SDoug Ambrisko #include <cam/cam_ccb.h> 47665484d8SDoug Ambrisko #include <cam/cam_sim.h> 48665484d8SDoug Ambrisko #include <cam/cam_xpt_sim.h> 49665484d8SDoug Ambrisko #include <cam/cam_debug.h> 50665484d8SDoug Ambrisko #include <cam/cam_periph.h> 51665484d8SDoug Ambrisko #include <cam/cam_xpt_periph.h> 52665484d8SDoug Ambrisko 53665484d8SDoug Ambrisko /* 54665484d8SDoug Ambrisko * Function prototypes 55665484d8SDoug Ambrisko */ 56665484d8SDoug Ambrisko u_int8_t MR_ValidateMapInfo(struct mrsas_softc *sc); 57dbcc81dfSKashyap D Desai u_int8_t 58dbcc81dfSKashyap D Desai mrsas_get_best_arm_pd(struct mrsas_softc *sc, 5916dc2814SKashyap D Desai PLD_LOAD_BALANCE_INFO lbInfo, struct IO_REQUEST_INFO *io_info); 608e727371SKashyap D Desai u_int8_t 618e727371SKashyap D Desai MR_BuildRaidContext(struct mrsas_softc *sc, 62665484d8SDoug Ambrisko struct IO_REQUEST_INFO *io_info, 634799d485SKashyap D Desai RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map); 648e727371SKashyap D Desai u_int8_t 658e727371SKashyap D Desai MR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld, 66665484d8SDoug Ambrisko u_int64_t stripRow, u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 67665484d8SDoug Ambrisko RAID_CONTEXT * pRAID_Context, 684799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * map); 694ad83576SKashyap D Desai u_int8_t MR_TargetIdToLdGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL *map); 704799d485SKashyap D Desai u_int32_t MR_LdBlockSizeGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map); 714799d485SKashyap D Desai u_int16_t MR_GetLDTgtId(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map); 72dbcc81dfSKashyap D Desai u_int16_t 73dbcc81dfSKashyap D Desai mrsas_get_updated_dev_handle(struct mrsas_softc *sc, 7416dc2814SKashyap D Desai PLD_LOAD_BALANCE_INFO lbInfo, struct IO_REQUEST_INFO *io_info); 75665484d8SDoug Ambrisko u_int32_t mega_mod64(u_int64_t dividend, u_int32_t divisor); 768e727371SKashyap D Desai u_int32_t 778e727371SKashyap D Desai MR_GetSpanBlock(u_int32_t ld, u_int64_t row, u_int64_t *span_blk, 784799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * map, int *div_error); 79665484d8SDoug Ambrisko u_int64_t mega_div64_32(u_int64_t dividend, u_int32_t divisor); 80dbcc81dfSKashyap D Desai void 81dbcc81dfSKashyap D Desai mrsas_update_load_balance_params(struct mrsas_softc *sc, 8216dc2814SKashyap D Desai MR_DRV_RAID_MAP_ALL * map, PLD_LOAD_BALANCE_INFO lbInfo); 838e727371SKashyap D Desai void 848e727371SKashyap D Desai mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request, 85665484d8SDoug Ambrisko u_int8_t cdb_len, struct IO_REQUEST_INFO *io_info, union ccb *ccb, 864799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * local_map_ptr, u_int32_t ref_tag, 87665484d8SDoug Ambrisko u_int32_t ld_block_size); 888e727371SKashyap D Desai static u_int16_t 898e727371SKashyap D Desai MR_LdSpanArrayGet(u_int32_t ld, u_int32_t span, 904799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * map); 914799d485SKashyap D Desai static u_int16_t MR_PdDevHandleGet(u_int32_t pd, MR_DRV_RAID_MAP_ALL * map); 928e727371SKashyap D Desai static u_int16_t 938e727371SKashyap D Desai MR_ArPdGet(u_int32_t ar, u_int32_t arm, 944799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * map); 958e727371SKashyap D Desai static MR_LD_SPAN * 968e727371SKashyap D Desai MR_LdSpanPtrGet(u_int32_t ld, u_int32_t span, 974799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * map); 988e727371SKashyap D Desai static u_int8_t 998e727371SKashyap D Desai MR_LdDataArmGet(u_int32_t ld, u_int32_t armIdx, 1004799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * map); 1018e727371SKashyap D Desai static MR_SPAN_BLOCK_INFO * 1028e727371SKashyap D Desai MR_LdSpanInfoGet(u_int32_t ld, 1034799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * map); 1044799d485SKashyap D Desai MR_LD_RAID *MR_LdRaidGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map); 1054ad83576SKashyap D Desai static int MR_PopulateDrvRaidMap(struct mrsas_softc *sc); 1064799d485SKashyap D Desai 107665484d8SDoug Ambrisko /* 1088e727371SKashyap D Desai * Spanset related function prototypes Added for PRL11 configuration (Uneven 1098e727371SKashyap D Desai * span support) 110665484d8SDoug Ambrisko */ 1114799d485SKashyap D Desai void mr_update_span_set(MR_DRV_RAID_MAP_ALL * map, PLD_SPAN_INFO ldSpanInfo); 1128e727371SKashyap D Desai static u_int8_t 1138e727371SKashyap D Desai mr_spanset_get_phy_params(struct mrsas_softc *sc, u_int32_t ld, 114665484d8SDoug Ambrisko u_int64_t stripRow, u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 1154799d485SKashyap D Desai RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map); 1168e727371SKashyap D Desai static u_int64_t 1178e727371SKashyap D Desai get_row_from_strip(struct mrsas_softc *sc, u_int32_t ld, 1184799d485SKashyap D Desai u_int64_t strip, MR_DRV_RAID_MAP_ALL * map); 1198e727371SKashyap D Desai static u_int32_t 1208e727371SKashyap D Desai mr_spanset_get_span_block(struct mrsas_softc *sc, 121665484d8SDoug Ambrisko u_int32_t ld, u_int64_t row, u_int64_t *span_blk, 1224799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * map, int *div_error); 1238e727371SKashyap D Desai static u_int8_t 1248e727371SKashyap D Desai get_arm(struct mrsas_softc *sc, u_int32_t ld, u_int8_t span, 1254799d485SKashyap D Desai u_int64_t stripe, MR_DRV_RAID_MAP_ALL * map); 126665484d8SDoug Ambrisko 127665484d8SDoug Ambrisko /* 1288e727371SKashyap D Desai * Spanset related defines Added for PRL11 configuration(Uneven span support) 129665484d8SDoug Ambrisko */ 130665484d8SDoug Ambrisko #define SPAN_ROW_SIZE(map, ld, index_) MR_LdSpanPtrGet(ld, index_, map)->spanRowSize 1318e727371SKashyap D Desai #define SPAN_ROW_DATA_SIZE(map_, ld, index_) \ 1328e727371SKashyap D Desai MR_LdSpanPtrGet(ld, index_, map)->spanRowDataSize 133665484d8SDoug Ambrisko #define SPAN_INVALID 0xff 134665484d8SDoug Ambrisko #define SPAN_DEBUG 0 135665484d8SDoug Ambrisko 136665484d8SDoug Ambrisko /* 137665484d8SDoug Ambrisko * Related Defines 138665484d8SDoug Ambrisko */ 139665484d8SDoug Ambrisko 140665484d8SDoug Ambrisko typedef u_int64_t REGION_KEY; 141665484d8SDoug Ambrisko typedef u_int32_t REGION_LEN; 142665484d8SDoug Ambrisko 143665484d8SDoug Ambrisko #define MR_LD_STATE_OPTIMAL 3 144665484d8SDoug Ambrisko #define FALSE 0 145665484d8SDoug Ambrisko #define TRUE 1 146665484d8SDoug Ambrisko 14716dc2814SKashyap D Desai #define LB_PENDING_CMDS_DEFAULT 4 14816dc2814SKashyap D Desai 149665484d8SDoug Ambrisko /* 150665484d8SDoug Ambrisko * Related Macros 151665484d8SDoug Ambrisko */ 152665484d8SDoug Ambrisko 153665484d8SDoug Ambrisko #define ABS_DIFF(a,b) ( ((a) > (b)) ? ((a) - (b)) : ((b) - (a)) ) 154665484d8SDoug Ambrisko 155665484d8SDoug Ambrisko #define swap32(x) \ 156665484d8SDoug Ambrisko ((unsigned int)( \ 157665484d8SDoug Ambrisko (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \ 158665484d8SDoug Ambrisko (((unsigned int)(x) & (unsigned int)0x0000ff00UL) << 8) | \ 159665484d8SDoug Ambrisko (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >> 8) | \ 160665484d8SDoug Ambrisko (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) )) 161665484d8SDoug Ambrisko 162665484d8SDoug Ambrisko /* 1638e727371SKashyap D Desai * In-line functions for mod and divide of 64-bit dividend and 32-bit 1648e727371SKashyap D Desai * divisor. Assumes a check for a divisor of zero is not possible. 165665484d8SDoug Ambrisko * 166665484d8SDoug Ambrisko * @param dividend: Dividend 167665484d8SDoug Ambrisko * @param divisor: Divisor 168665484d8SDoug Ambrisko * @return remainder 169665484d8SDoug Ambrisko */ 170665484d8SDoug Ambrisko 171665484d8SDoug Ambrisko #define mega_mod64(dividend, divisor) ({ \ 172665484d8SDoug Ambrisko int remainder; \ 173665484d8SDoug Ambrisko remainder = ((u_int64_t) (dividend)) % (u_int32_t) (divisor); \ 174665484d8SDoug Ambrisko remainder;}) 175665484d8SDoug Ambrisko 176665484d8SDoug Ambrisko #define mega_div64_32(dividend, divisor) ({ \ 177665484d8SDoug Ambrisko int quotient; \ 178665484d8SDoug Ambrisko quotient = ((u_int64_t) (dividend)) / (u_int32_t) (divisor); \ 179665484d8SDoug Ambrisko quotient;}) 180665484d8SDoug Ambrisko 181665484d8SDoug Ambrisko /* 182665484d8SDoug Ambrisko * Various RAID map access functions. These functions access the various 183665484d8SDoug Ambrisko * parts of the RAID map and returns the appropriate parameters. 184665484d8SDoug Ambrisko */ 185665484d8SDoug Ambrisko 1868e727371SKashyap D Desai MR_LD_RAID * 1878e727371SKashyap D Desai MR_LdRaidGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map) 188665484d8SDoug Ambrisko { 189665484d8SDoug Ambrisko return (&map->raidMap.ldSpanMap[ld].ldRaid); 190665484d8SDoug Ambrisko } 191665484d8SDoug Ambrisko 1928e727371SKashyap D Desai u_int16_t 1938e727371SKashyap D Desai MR_GetLDTgtId(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map) 194665484d8SDoug Ambrisko { 195*e34a057cSAlfredo Dal'Ava Junior return le16toh(map->raidMap.ldSpanMap[ld].ldRaid.targetId); 196665484d8SDoug Ambrisko } 197665484d8SDoug Ambrisko 1988e727371SKashyap D Desai static u_int16_t 1998e727371SKashyap D Desai MR_LdSpanArrayGet(u_int32_t ld, u_int32_t span, MR_DRV_RAID_MAP_ALL * map) 200665484d8SDoug Ambrisko { 201*e34a057cSAlfredo Dal'Ava Junior return le16toh(map->raidMap.ldSpanMap[ld].spanBlock[span].span.arrayRef); 202665484d8SDoug Ambrisko } 203665484d8SDoug Ambrisko 2048e727371SKashyap D Desai static u_int8_t 2058e727371SKashyap D Desai MR_LdDataArmGet(u_int32_t ld, u_int32_t armIdx, MR_DRV_RAID_MAP_ALL * map) 206665484d8SDoug Ambrisko { 207665484d8SDoug Ambrisko return map->raidMap.ldSpanMap[ld].dataArmMap[armIdx]; 208665484d8SDoug Ambrisko } 209665484d8SDoug Ambrisko 2108e727371SKashyap D Desai static u_int16_t 2118e727371SKashyap D Desai MR_PdDevHandleGet(u_int32_t pd, MR_DRV_RAID_MAP_ALL * map) 212665484d8SDoug Ambrisko { 213665484d8SDoug Ambrisko return map->raidMap.devHndlInfo[pd].curDevHdl; 214665484d8SDoug Ambrisko } 215665484d8SDoug Ambrisko 2163d273176SKashyap D Desai static u_int8_t MR_PdInterfaceTypeGet(u_int32_t pd, MR_DRV_RAID_MAP_ALL *map) 2173d273176SKashyap D Desai { 2183d273176SKashyap D Desai return map->raidMap.devHndlInfo[pd].interfaceType; 2193d273176SKashyap D Desai } 2203d273176SKashyap D Desai 2218e727371SKashyap D Desai static u_int16_t 2228e727371SKashyap D Desai MR_ArPdGet(u_int32_t ar, u_int32_t arm, MR_DRV_RAID_MAP_ALL * map) 223665484d8SDoug Ambrisko { 224*e34a057cSAlfredo Dal'Ava Junior return le16toh(map->raidMap.arMapInfo[ar].pd[arm]); 225665484d8SDoug Ambrisko } 226665484d8SDoug Ambrisko 2278e727371SKashyap D Desai static MR_LD_SPAN * 2288e727371SKashyap D Desai MR_LdSpanPtrGet(u_int32_t ld, u_int32_t span, MR_DRV_RAID_MAP_ALL * map) 229665484d8SDoug Ambrisko { 230665484d8SDoug Ambrisko return &map->raidMap.ldSpanMap[ld].spanBlock[span].span; 231665484d8SDoug Ambrisko } 232665484d8SDoug Ambrisko 2338e727371SKashyap D Desai static MR_SPAN_BLOCK_INFO * 2348e727371SKashyap D Desai MR_LdSpanInfoGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map) 235665484d8SDoug Ambrisko { 236665484d8SDoug Ambrisko return &map->raidMap.ldSpanMap[ld].spanBlock[0]; 237665484d8SDoug Ambrisko } 238665484d8SDoug Ambrisko 2394ad83576SKashyap D Desai u_int8_t 2408e727371SKashyap D Desai MR_TargetIdToLdGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map) 241665484d8SDoug Ambrisko { 242665484d8SDoug Ambrisko return map->raidMap.ldTgtIdToLd[ldTgtId]; 243665484d8SDoug Ambrisko } 244665484d8SDoug Ambrisko 2458e727371SKashyap D Desai u_int32_t 2468e727371SKashyap D Desai MR_LdBlockSizeGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map) 247665484d8SDoug Ambrisko { 248665484d8SDoug Ambrisko MR_LD_RAID *raid; 249665484d8SDoug Ambrisko u_int32_t ld, ldBlockSize = MRSAS_SCSIBLOCKSIZE; 250665484d8SDoug Ambrisko 251665484d8SDoug Ambrisko ld = MR_TargetIdToLdGet(ldTgtId, map); 252665484d8SDoug Ambrisko 253665484d8SDoug Ambrisko /* 254665484d8SDoug Ambrisko * Check if logical drive was removed. 255665484d8SDoug Ambrisko */ 256665484d8SDoug Ambrisko if (ld >= MAX_LOGICAL_DRIVES) 257665484d8SDoug Ambrisko return ldBlockSize; 258665484d8SDoug Ambrisko 259665484d8SDoug Ambrisko raid = MR_LdRaidGet(ld, map); 260665484d8SDoug Ambrisko ldBlockSize = raid->logicalBlockLength; 261665484d8SDoug Ambrisko if (!ldBlockSize) 262665484d8SDoug Ambrisko ldBlockSize = MRSAS_SCSIBLOCKSIZE; 263665484d8SDoug Ambrisko 264665484d8SDoug Ambrisko return ldBlockSize; 265665484d8SDoug Ambrisko } 266665484d8SDoug Ambrisko 2674799d485SKashyap D Desai /* 2684ad83576SKashyap D Desai * This function will Populate Driver Map using Dynamic firmware raid map 2694ad83576SKashyap D Desai */ 2704ad83576SKashyap D Desai static int 2714ad83576SKashyap D Desai MR_PopulateDrvRaidMapVentura(struct mrsas_softc *sc) 2724ad83576SKashyap D Desai { 2734ad83576SKashyap D Desai unsigned int i, j; 2744ad83576SKashyap D Desai u_int16_t ld_count; 2754ad83576SKashyap D Desai 2764ad83576SKashyap D Desai MR_FW_RAID_MAP_DYNAMIC *fw_map_dyn; 2774ad83576SKashyap D Desai MR_RAID_MAP_DESC_TABLE *desc_table; 2784ad83576SKashyap D Desai MR_DRV_RAID_MAP_ALL *drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 2794ad83576SKashyap D Desai MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap; 2804ad83576SKashyap D Desai void *raid_map_data = NULL; 2814ad83576SKashyap D Desai 2824ad83576SKashyap D Desai fw_map_dyn = (MR_FW_RAID_MAP_DYNAMIC *) sc->raidmap_mem[(sc->map_id & 1)]; 2834ad83576SKashyap D Desai 2844ad83576SKashyap D Desai if (fw_map_dyn == NULL) { 2854ad83576SKashyap D Desai device_printf(sc->mrsas_dev, 2864ad83576SKashyap D Desai "from %s %d map0 %p map1 %p map size %d \n", __func__, __LINE__, 2874ad83576SKashyap D Desai sc->raidmap_mem[0], sc->raidmap_mem[1], sc->maxRaidMapSize); 2884ad83576SKashyap D Desai return 1; 2894ad83576SKashyap D Desai } 2904ad83576SKashyap D Desai #if VD_EXT_DEBUG 2914ad83576SKashyap D Desai device_printf(sc->mrsas_dev, 2924ad83576SKashyap D Desai " raidMapSize 0x%x, descTableOffset 0x%x, " 2934ad83576SKashyap D Desai " descTableSize 0x%x, descTableNumElements 0x%x \n", 294*e34a057cSAlfredo Dal'Ava Junior fw_map_dyn->raidMapSize, le32toh(fw_map_dyn->descTableOffset), 2954ad83576SKashyap D Desai fw_map_dyn->descTableSize, fw_map_dyn->descTableNumElements); 2964ad83576SKashyap D Desai #endif 2974ad83576SKashyap D Desai desc_table = (MR_RAID_MAP_DESC_TABLE *) ((char *)fw_map_dyn + 298*e34a057cSAlfredo Dal'Ava Junior le32toh(fw_map_dyn->descTableOffset)); 2994ad83576SKashyap D Desai if (desc_table != fw_map_dyn->raidMapDescTable) { 3004ad83576SKashyap D Desai device_printf(sc->mrsas_dev, 3014ad83576SKashyap D Desai "offsets of desc table are not matching returning " 3024ad83576SKashyap D Desai " FW raid map has been changed: desc %p original %p\n", 3034ad83576SKashyap D Desai desc_table, fw_map_dyn->raidMapDescTable); 3044ad83576SKashyap D Desai } 3054ad83576SKashyap D Desai memset(drv_map, 0, sc->drv_map_sz); 306*e34a057cSAlfredo Dal'Ava Junior ld_count = le16toh(fw_map_dyn->ldCount); 307*e34a057cSAlfredo Dal'Ava Junior pDrvRaidMap->ldCount = htole16(ld_count); 3084ad83576SKashyap D Desai pDrvRaidMap->fpPdIoTimeoutSec = fw_map_dyn->fpPdIoTimeoutSec; 309*e34a057cSAlfredo Dal'Ava Junior pDrvRaidMap->totalSize = htole32(sizeof(MR_DRV_RAID_MAP_ALL)); 3104ad83576SKashyap D Desai /* point to actual data starting point */ 3114ad83576SKashyap D Desai raid_map_data = (char *)fw_map_dyn + 312*e34a057cSAlfredo Dal'Ava Junior le32toh(fw_map_dyn->descTableOffset) + 313*e34a057cSAlfredo Dal'Ava Junior le32toh(fw_map_dyn->descTableSize); 3144ad83576SKashyap D Desai 315*e34a057cSAlfredo Dal'Ava Junior for (i = 0; i < le32toh(fw_map_dyn->descTableNumElements); ++i) { 3164ad83576SKashyap D Desai if (!desc_table) { 3174ad83576SKashyap D Desai device_printf(sc->mrsas_dev, 3184ad83576SKashyap D Desai "desc table is null, coming out %p \n", desc_table); 3194ad83576SKashyap D Desai return 1; 3204ad83576SKashyap D Desai } 3214ad83576SKashyap D Desai #if VD_EXT_DEBUG 3224ad83576SKashyap D Desai device_printf(sc->mrsas_dev, "raid_map_data %p \n", raid_map_data); 3234ad83576SKashyap D Desai device_printf(sc->mrsas_dev, 3244ad83576SKashyap D Desai "desc table %p \n", desc_table); 3254ad83576SKashyap D Desai device_printf(sc->mrsas_dev, 3264ad83576SKashyap D Desai "raidmap type %d, raidmapOffset 0x%x, " 3274ad83576SKashyap D Desai " raid map number of elements 0%x, raidmapsize 0x%x\n", 328*e34a057cSAlfredo Dal'Ava Junior le32toh(desc_table->raidMapDescType), desc_table->raidMapDescOffset, 329*e34a057cSAlfredo Dal'Ava Junior le32toh(desc_table->raidMapDescElements), desc_table->raidMapDescBufferSize); 3304ad83576SKashyap D Desai #endif 331*e34a057cSAlfredo Dal'Ava Junior switch (le32toh(desc_table->raidMapDescType)) { 3324ad83576SKashyap D Desai case RAID_MAP_DESC_TYPE_DEVHDL_INFO: 3334ad83576SKashyap D Desai fw_map_dyn->RaidMapDescPtrs.ptrStruct.devHndlInfo = (MR_DEV_HANDLE_INFO *) 334*e34a057cSAlfredo Dal'Ava Junior ((char *)raid_map_data + le32toh(desc_table->raidMapDescOffset)); 3354ad83576SKashyap D Desai #if VD_EXT_DEBUG 3364ad83576SKashyap D Desai device_printf(sc->mrsas_dev, 3374ad83576SKashyap D Desai "devHndlInfo address %p\n", fw_map_dyn->RaidMapDescPtrs.ptrStruct.devHndlInfo); 3384ad83576SKashyap D Desai #endif 3394ad83576SKashyap D Desai memcpy(pDrvRaidMap->devHndlInfo, fw_map_dyn->RaidMapDescPtrs.ptrStruct.devHndlInfo, 340*e34a057cSAlfredo Dal'Ava Junior sizeof(MR_DEV_HANDLE_INFO) * le32toh(desc_table->raidMapDescElements)); 3414ad83576SKashyap D Desai break; 3424ad83576SKashyap D Desai case RAID_MAP_DESC_TYPE_TGTID_INFO: 3434ad83576SKashyap D Desai fw_map_dyn->RaidMapDescPtrs.ptrStruct.ldTgtIdToLd = (u_int16_t *) 344*e34a057cSAlfredo Dal'Ava Junior ((char *)raid_map_data + 345*e34a057cSAlfredo Dal'Ava Junior le32toh(desc_table->raidMapDescOffset)); 3464ad83576SKashyap D Desai #if VD_EXT_DEBUG 3474ad83576SKashyap D Desai device_printf(sc->mrsas_dev, 3484ad83576SKashyap D Desai "ldTgtIdToLd address %p\n", fw_map_dyn->RaidMapDescPtrs.ptrStruct.ldTgtIdToLd); 3494ad83576SKashyap D Desai #endif 350*e34a057cSAlfredo Dal'Ava Junior for (j = 0; j < le32toh(desc_table->raidMapDescElements); j++) { 3514ad83576SKashyap D Desai pDrvRaidMap->ldTgtIdToLd[j] = fw_map_dyn->RaidMapDescPtrs.ptrStruct.ldTgtIdToLd[j]; 3524ad83576SKashyap D Desai #if VD_EXT_DEBUG 3534ad83576SKashyap D Desai device_printf(sc->mrsas_dev, 3544ad83576SKashyap D Desai " %d drv ldTgtIdToLd %d\n", j, pDrvRaidMap->ldTgtIdToLd[j]); 3554ad83576SKashyap D Desai #endif 3564ad83576SKashyap D Desai } 3574ad83576SKashyap D Desai break; 3584ad83576SKashyap D Desai case RAID_MAP_DESC_TYPE_ARRAY_INFO: 3594ad83576SKashyap D Desai fw_map_dyn->RaidMapDescPtrs.ptrStruct.arMapInfo = (MR_ARRAY_INFO *) ((char *)raid_map_data + 360*e34a057cSAlfredo Dal'Ava Junior le32toh(desc_table->raidMapDescOffset)); 3614ad83576SKashyap D Desai #if VD_EXT_DEBUG 3624ad83576SKashyap D Desai device_printf(sc->mrsas_dev, 3634ad83576SKashyap D Desai "arMapInfo address %p\n", fw_map_dyn->RaidMapDescPtrs.ptrStruct.arMapInfo); 3644ad83576SKashyap D Desai #endif 3654ad83576SKashyap D Desai memcpy(pDrvRaidMap->arMapInfo, fw_map_dyn->RaidMapDescPtrs.ptrStruct.arMapInfo, 366*e34a057cSAlfredo Dal'Ava Junior sizeof(MR_ARRAY_INFO) * le32toh(desc_table->raidMapDescElements)); 3674ad83576SKashyap D Desai break; 3684ad83576SKashyap D Desai case RAID_MAP_DESC_TYPE_SPAN_INFO: 3694ad83576SKashyap D Desai fw_map_dyn->RaidMapDescPtrs.ptrStruct.ldSpanMap = (MR_LD_SPAN_MAP *) ((char *)raid_map_data + 370*e34a057cSAlfredo Dal'Ava Junior le32toh(desc_table->raidMapDescOffset)); 3714ad83576SKashyap D Desai memcpy(pDrvRaidMap->ldSpanMap, fw_map_dyn->RaidMapDescPtrs.ptrStruct.ldSpanMap, 372*e34a057cSAlfredo Dal'Ava Junior sizeof(MR_LD_SPAN_MAP) * 373*e34a057cSAlfredo Dal'Ava Junior le32toh(desc_table->raidMapDescElements)); 3744ad83576SKashyap D Desai #if VD_EXT_DEBUG 3754ad83576SKashyap D Desai device_printf(sc->mrsas_dev, 3764ad83576SKashyap D Desai "ldSpanMap address %p\n", fw_map_dyn->RaidMapDescPtrs.ptrStruct.ldSpanMap); 3774ad83576SKashyap D Desai device_printf(sc->mrsas_dev, 3784ad83576SKashyap D Desai "MR_LD_SPAN_MAP size 0x%lx\n", sizeof(MR_LD_SPAN_MAP)); 3794ad83576SKashyap D Desai for (j = 0; j < ld_count; j++) { 3804ad83576SKashyap D Desai printf("mrsas(%d) : fw_map_dyn->ldSpanMap[%d].ldRaid.targetId 0x%x " 3814ad83576SKashyap D Desai "fw_map_dyn->ldSpanMap[%d].ldRaid.seqNum 0x%x size 0x%x\n", 3824ad83576SKashyap D Desai j, j, fw_map_dyn->RaidMapDescPtrs.ptrStruct.ldSpanMap[j].ldRaid.targetId, j, 3834ad83576SKashyap D Desai fw_map_dyn->RaidMapDescPtrs.ptrStruct.ldSpanMap[j].ldRaid.seqNum, 3844ad83576SKashyap D Desai (u_int32_t)fw_map_dyn->RaidMapDescPtrs.ptrStruct.ldSpanMap[j].ldRaid.rowSize); 3854ad83576SKashyap D Desai printf("mrsas(%d) : pDrvRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x " 3864ad83576SKashyap D Desai "pDrvRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x size 0x%x\n", 3874ad83576SKashyap D Desai j, j, pDrvRaidMap->ldSpanMap[j].ldRaid.targetId, j, 3884ad83576SKashyap D Desai pDrvRaidMap->ldSpanMap[j].ldRaid.seqNum, 3894ad83576SKashyap D Desai (u_int32_t)pDrvRaidMap->ldSpanMap[j].ldRaid.rowSize); 3904ad83576SKashyap D Desai printf("mrsas : drv raid map all %p raid map %p LD RAID MAP %p/%p\n", 3914ad83576SKashyap D Desai drv_map, pDrvRaidMap, &fw_map_dyn->RaidMapDescPtrs.ptrStruct.ldSpanMap[j].ldRaid, 3924ad83576SKashyap D Desai &pDrvRaidMap->ldSpanMap[j].ldRaid); 3934ad83576SKashyap D Desai } 3944ad83576SKashyap D Desai #endif 3954ad83576SKashyap D Desai break; 3964ad83576SKashyap D Desai default: 3974ad83576SKashyap D Desai device_printf(sc->mrsas_dev, 3984ad83576SKashyap D Desai "wrong number of desctableElements %d\n", 3994ad83576SKashyap D Desai fw_map_dyn->descTableNumElements); 4004ad83576SKashyap D Desai } 4014ad83576SKashyap D Desai ++desc_table; 4024ad83576SKashyap D Desai } 4034ad83576SKashyap D Desai return 0; 4044ad83576SKashyap D Desai } 4054ad83576SKashyap D Desai 4064ad83576SKashyap D Desai /* 4074799d485SKashyap D Desai * This function will Populate Driver Map using firmware raid map 4084799d485SKashyap D Desai */ 4094ad83576SKashyap D Desai static int 4108e727371SKashyap D Desai MR_PopulateDrvRaidMap(struct mrsas_softc *sc) 4114799d485SKashyap D Desai { 4124799d485SKashyap D Desai MR_FW_RAID_MAP_ALL *fw_map_old = NULL; 4134ad83576SKashyap D Desai MR_FW_RAID_MAP_EXT *fw_map_ext; 4144799d485SKashyap D Desai MR_FW_RAID_MAP *pFwRaidMap = NULL; 4154799d485SKashyap D Desai unsigned int i; 4164ad83576SKashyap D Desai u_int16_t ld_count; 4174799d485SKashyap D Desai 4184799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL *drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 4194799d485SKashyap D Desai MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap; 4204799d485SKashyap D Desai 4214ad83576SKashyap D Desai if (sc->maxRaidMapSize) { 4224ad83576SKashyap D Desai return MR_PopulateDrvRaidMapVentura(sc); 4234ad83576SKashyap D Desai } else if (sc->max256vdSupport) { 4244ad83576SKashyap D Desai fw_map_ext = (MR_FW_RAID_MAP_EXT *) sc->raidmap_mem[(sc->map_id & 1)]; 425*e34a057cSAlfredo Dal'Ava Junior ld_count = (u_int16_t)le16toh(fw_map_ext->ldCount); 4264ad83576SKashyap D Desai if (ld_count > MAX_LOGICAL_DRIVES_EXT) { 4274ad83576SKashyap D Desai device_printf(sc->mrsas_dev, 4284ad83576SKashyap D Desai "mrsas: LD count exposed in RAID map in not valid\n"); 4294ad83576SKashyap D Desai return 1; 4304ad83576SKashyap D Desai } 4314ad83576SKashyap D Desai #if VD_EXT_DEBUG 4324ad83576SKashyap D Desai for (i = 0; i < ld_count; i++) { 4334ad83576SKashyap D Desai printf("mrsas : Index 0x%x Target Id 0x%x Seq Num 0x%x Size 0/%lx\n", 4344ad83576SKashyap D Desai i, fw_map_ext->ldSpanMap[i].ldRaid.targetId, 4354ad83576SKashyap D Desai fw_map_ext->ldSpanMap[i].ldRaid.seqNum, 4364ad83576SKashyap D Desai fw_map_ext->ldSpanMap[i].ldRaid.size); 4374ad83576SKashyap D Desai } 4384ad83576SKashyap D Desai #endif 4394ad83576SKashyap D Desai memset(drv_map, 0, sc->drv_map_sz); 440*e34a057cSAlfredo Dal'Ava Junior pDrvRaidMap->ldCount = htole16(ld_count); 4414ad83576SKashyap D Desai pDrvRaidMap->fpPdIoTimeoutSec = fw_map_ext->fpPdIoTimeoutSec; 4424ad83576SKashyap D Desai for (i = 0; i < (MAX_LOGICAL_DRIVES_EXT); i++) { 4434ad83576SKashyap D Desai pDrvRaidMap->ldTgtIdToLd[i] = (u_int16_t)fw_map_ext->ldTgtIdToLd[i]; 4444ad83576SKashyap D Desai } 4454ad83576SKashyap D Desai memcpy(pDrvRaidMap->ldSpanMap, fw_map_ext->ldSpanMap, sizeof(MR_LD_SPAN_MAP) * ld_count); 4464ad83576SKashyap D Desai #if VD_EXT_DEBUG 4474ad83576SKashyap D Desai for (i = 0; i < ld_count; i++) { 4484ad83576SKashyap D Desai printf("mrsas(%d) : fw_map_ext->ldSpanMap[%d].ldRaid.targetId 0x%x " 4494ad83576SKashyap D Desai "fw_map_ext->ldSpanMap[%d].ldRaid.seqNum 0x%x size 0x%x\n", 4504ad83576SKashyap D Desai i, i, fw_map_ext->ldSpanMap[i].ldRaid.targetId, i, 4514ad83576SKashyap D Desai fw_map_ext->ldSpanMap[i].ldRaid.seqNum, 4524ad83576SKashyap D Desai (u_int32_t)fw_map_ext->ldSpanMap[i].ldRaid.rowSize); 4534ad83576SKashyap D Desai printf("mrsas(%d) : pDrvRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x" 4544ad83576SKashyap D Desai "pDrvRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x size 0x%x\n", i, i, 4554ad83576SKashyap D Desai pDrvRaidMap->ldSpanMap[i].ldRaid.targetId, i, 4564ad83576SKashyap D Desai pDrvRaidMap->ldSpanMap[i].ldRaid.seqNum, 4574ad83576SKashyap D Desai (u_int32_t)pDrvRaidMap->ldSpanMap[i].ldRaid.rowSize); 4584ad83576SKashyap D Desai printf("mrsas : drv raid map all %p raid map %p LD RAID MAP %p/%p\n", 4594ad83576SKashyap D Desai drv_map, pDrvRaidMap, &fw_map_ext->ldSpanMap[i].ldRaid, 4604ad83576SKashyap D Desai &pDrvRaidMap->ldSpanMap[i].ldRaid); 4614ad83576SKashyap D Desai } 4624ad83576SKashyap D Desai #endif 4634ad83576SKashyap D Desai memcpy(pDrvRaidMap->arMapInfo, fw_map_ext->arMapInfo, 4644ad83576SKashyap D Desai sizeof(MR_ARRAY_INFO) * MAX_API_ARRAYS_EXT); 4654ad83576SKashyap D Desai memcpy(pDrvRaidMap->devHndlInfo, fw_map_ext->devHndlInfo, 4664ad83576SKashyap D Desai sizeof(MR_DEV_HANDLE_INFO) * MAX_RAIDMAP_PHYSICAL_DEVICES); 4674ad83576SKashyap D Desai 468*e34a057cSAlfredo Dal'Ava Junior pDrvRaidMap->totalSize = htole32(sizeof(MR_FW_RAID_MAP_EXT)); 4694799d485SKashyap D Desai } else { 4704799d485SKashyap D Desai fw_map_old = (MR_FW_RAID_MAP_ALL *) sc->raidmap_mem[(sc->map_id & 1)]; 4714799d485SKashyap D Desai pFwRaidMap = &fw_map_old->raidMap; 4724799d485SKashyap D Desai 4734799d485SKashyap D Desai #if VD_EXT_DEBUG 474*e34a057cSAlfredo Dal'Ava Junior for (i = 0; i < le32toh(pFwRaidMap->ldCount); i++) { 4754799d485SKashyap D Desai device_printf(sc->mrsas_dev, 4764799d485SKashyap D Desai "Index 0x%x Target Id 0x%x Seq Num 0x%x Size 0/%lx\n", i, 4774799d485SKashyap D Desai fw_map_old->raidMap.ldSpanMap[i].ldRaid.targetId, 4784799d485SKashyap D Desai fw_map_old->raidMap.ldSpanMap[i].ldRaid.seqNum, 4794799d485SKashyap D Desai fw_map_old->raidMap.ldSpanMap[i].ldRaid.size); 4804799d485SKashyap D Desai } 4814799d485SKashyap D Desai #endif 4824799d485SKashyap D Desai 4834799d485SKashyap D Desai memset(drv_map, 0, sc->drv_map_sz); 4844799d485SKashyap D Desai pDrvRaidMap->totalSize = pFwRaidMap->totalSize; 4854799d485SKashyap D Desai pDrvRaidMap->ldCount = pFwRaidMap->ldCount; 4864799d485SKashyap D Desai pDrvRaidMap->fpPdIoTimeoutSec = 4874799d485SKashyap D Desai pFwRaidMap->fpPdIoTimeoutSec; 4884799d485SKashyap D Desai 4894799d485SKashyap D Desai for (i = 0; i < MAX_RAIDMAP_LOGICAL_DRIVES + MAX_RAIDMAP_VIEWS; i++) { 4904799d485SKashyap D Desai pDrvRaidMap->ldTgtIdToLd[i] = 4914799d485SKashyap D Desai (u_int8_t)pFwRaidMap->ldTgtIdToLd[i]; 4924799d485SKashyap D Desai } 4934799d485SKashyap D Desai 4944799d485SKashyap D Desai for (i = 0; i < pDrvRaidMap->ldCount; i++) { 4954799d485SKashyap D Desai pDrvRaidMap->ldSpanMap[i] = 4964799d485SKashyap D Desai pFwRaidMap->ldSpanMap[i]; 4974799d485SKashyap D Desai 4984799d485SKashyap D Desai #if VD_EXT_DEBUG 4994799d485SKashyap D Desai device_printf(sc->mrsas_dev, "pFwRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x " 5004799d485SKashyap D Desai "pFwRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x size 0x%x\n", 5014799d485SKashyap D Desai i, i, pFwRaidMap->ldSpanMap[i].ldRaid.targetId, 5024799d485SKashyap D Desai pFwRaidMap->ldSpanMap[i].ldRaid.seqNum, 5034799d485SKashyap D Desai (u_int32_t)pFwRaidMap->ldSpanMap[i].ldRaid.rowSize); 5044799d485SKashyap D Desai device_printf(sc->mrsas_dev, "pDrvRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x" 5054799d485SKashyap D Desai "pDrvRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x size 0x%x\n", i, i, 5064799d485SKashyap D Desai pDrvRaidMap->ldSpanMap[i].ldRaid.targetId, 5074799d485SKashyap D Desai pDrvRaidMap->ldSpanMap[i].ldRaid.seqNum, 5084799d485SKashyap D Desai (u_int32_t)pDrvRaidMap->ldSpanMap[i].ldRaid.rowSize); 5094799d485SKashyap D Desai device_printf(sc->mrsas_dev, "drv raid map all %p raid map %p LD RAID MAP %p/%p\n", 5104799d485SKashyap D Desai drv_map, pDrvRaidMap, 5114799d485SKashyap D Desai &pFwRaidMap->ldSpanMap[i].ldRaid, &pDrvRaidMap->ldSpanMap[i].ldRaid); 5124799d485SKashyap D Desai #endif 5134799d485SKashyap D Desai } 5144799d485SKashyap D Desai 5154799d485SKashyap D Desai memcpy(pDrvRaidMap->arMapInfo, pFwRaidMap->arMapInfo, 5164799d485SKashyap D Desai sizeof(MR_ARRAY_INFO) * MAX_RAIDMAP_ARRAYS); 5174799d485SKashyap D Desai memcpy(pDrvRaidMap->devHndlInfo, pFwRaidMap->devHndlInfo, 5184799d485SKashyap D Desai sizeof(MR_DEV_HANDLE_INFO) * 5194799d485SKashyap D Desai MAX_RAIDMAP_PHYSICAL_DEVICES); 5204799d485SKashyap D Desai } 5214ad83576SKashyap D Desai return 0; 5224799d485SKashyap D Desai } 5234799d485SKashyap D Desai 5248e727371SKashyap D Desai /* 525665484d8SDoug Ambrisko * MR_ValidateMapInfo: Validate RAID map 526665484d8SDoug Ambrisko * input: Adapter instance soft state 527665484d8SDoug Ambrisko * 528665484d8SDoug Ambrisko * This function checks and validates the loaded RAID map. It returns 0 if 529665484d8SDoug Ambrisko * successful, and 1 otherwise. 530665484d8SDoug Ambrisko */ 5318e727371SKashyap D Desai u_int8_t 5328e727371SKashyap D Desai MR_ValidateMapInfo(struct mrsas_softc *sc) 533665484d8SDoug Ambrisko { 534665484d8SDoug Ambrisko if (!sc) { 535665484d8SDoug Ambrisko return 1; 536665484d8SDoug Ambrisko } 5374ad83576SKashyap D Desai if (MR_PopulateDrvRaidMap(sc)) 5384ad83576SKashyap D Desai return 0; 5394799d485SKashyap D Desai 5404799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL *drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 5414799d485SKashyap D Desai MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap; 5424799d485SKashyap D Desai 5434799d485SKashyap D Desai u_int32_t expected_map_size; 5448e727371SKashyap D Desai 5454799d485SKashyap D Desai drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 5464799d485SKashyap D Desai pDrvRaidMap = &drv_map->raidMap; 547665484d8SDoug Ambrisko PLD_SPAN_INFO ldSpanInfo = (PLD_SPAN_INFO) & sc->log_to_span; 548665484d8SDoug Ambrisko 5494ad83576SKashyap D Desai if (sc->maxRaidMapSize) 5504ad83576SKashyap D Desai expected_map_size = sizeof(MR_DRV_RAID_MAP_ALL); 5514ad83576SKashyap D Desai else if (sc->max256vdSupport) 5524799d485SKashyap D Desai expected_map_size = sizeof(MR_FW_RAID_MAP_EXT); 5534799d485SKashyap D Desai else 5544799d485SKashyap D Desai expected_map_size = 5554799d485SKashyap D Desai (sizeof(MR_FW_RAID_MAP) - sizeof(MR_LD_SPAN_MAP)) + 556*e34a057cSAlfredo Dal'Ava Junior (sizeof(MR_LD_SPAN_MAP) * le16toh(pDrvRaidMap->ldCount)); 557665484d8SDoug Ambrisko 558*e34a057cSAlfredo Dal'Ava Junior if (le32toh(pDrvRaidMap->totalSize) != expected_map_size) { 5594799d485SKashyap D Desai device_printf(sc->mrsas_dev, "map size %x not matching ld count\n", expected_map_size); 560665484d8SDoug Ambrisko device_printf(sc->mrsas_dev, "span map= %x\n", (unsigned int)sizeof(MR_LD_SPAN_MAP)); 561*e34a057cSAlfredo Dal'Ava Junior device_printf(sc->mrsas_dev, "pDrvRaidMap->totalSize=%x\n", le32toh(pDrvRaidMap->totalSize)); 562665484d8SDoug Ambrisko return 1; 563665484d8SDoug Ambrisko } 564665484d8SDoug Ambrisko if (sc->UnevenSpanSupport) { 5654799d485SKashyap D Desai mr_update_span_set(drv_map, ldSpanInfo); 566665484d8SDoug Ambrisko } 56716dc2814SKashyap D Desai mrsas_update_load_balance_params(sc, drv_map, sc->load_balance_info); 568665484d8SDoug Ambrisko 569665484d8SDoug Ambrisko return 0; 570665484d8SDoug Ambrisko } 571665484d8SDoug Ambrisko 572665484d8SDoug Ambrisko /* 573665484d8SDoug Ambrisko * 574665484d8SDoug Ambrisko * Function to print info about span set created in driver from FW raid map 575665484d8SDoug Ambrisko * 5768e727371SKashyap D Desai * Inputs: map 5778e727371SKashyap D Desai * ldSpanInfo: ld map span info per HBA instance 578665484d8SDoug Ambrisko * 579665484d8SDoug Ambrisko * 5808e727371SKashyap D Desai */ 581665484d8SDoug Ambrisko #if SPAN_DEBUG 5828e727371SKashyap D Desai static int 5838e727371SKashyap D Desai getSpanInfo(MR_DRV_RAID_MAP_ALL * map, PLD_SPAN_INFO ldSpanInfo) 584665484d8SDoug Ambrisko { 585665484d8SDoug Ambrisko 586665484d8SDoug Ambrisko u_int8_t span; 587665484d8SDoug Ambrisko u_int32_t element; 588665484d8SDoug Ambrisko MR_LD_RAID *raid; 589665484d8SDoug Ambrisko LD_SPAN_SET *span_set; 590665484d8SDoug Ambrisko MR_QUAD_ELEMENT *quad; 591665484d8SDoug Ambrisko int ldCount; 592665484d8SDoug Ambrisko u_int16_t ld; 593665484d8SDoug Ambrisko 5948e727371SKashyap D Desai for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) { 595665484d8SDoug Ambrisko ld = MR_TargetIdToLdGet(ldCount, map); 596665484d8SDoug Ambrisko if (ld >= MAX_LOGICAL_DRIVES) { 597665484d8SDoug Ambrisko continue; 598665484d8SDoug Ambrisko } 599665484d8SDoug Ambrisko raid = MR_LdRaidGet(ld, map); 600665484d8SDoug Ambrisko printf("LD %x: span_depth=%x\n", ld, raid->spanDepth); 601665484d8SDoug Ambrisko for (span = 0; span < raid->spanDepth; span++) 602665484d8SDoug Ambrisko printf("Span=%x, number of quads=%x\n", span, 603*e34a057cSAlfredo Dal'Ava Junior le32toh(map->raidMap.ldSpanMap[ld].spanBlock[span]. 604*e34a057cSAlfredo Dal'Ava Junior block_span_info.noElements)); 605665484d8SDoug Ambrisko for (element = 0; element < MAX_QUAD_DEPTH; element++) { 606665484d8SDoug Ambrisko span_set = &(ldSpanInfo[ld].span_set[element]); 6078e727371SKashyap D Desai if (span_set->span_row_data_width == 0) 6088e727371SKashyap D Desai break; 609665484d8SDoug Ambrisko 610665484d8SDoug Ambrisko printf("Span Set %x: width=%x, diff=%x\n", element, 611665484d8SDoug Ambrisko (unsigned int)span_set->span_row_data_width, 612665484d8SDoug Ambrisko (unsigned int)span_set->diff); 613665484d8SDoug Ambrisko printf("logical LBA start=0x%08lx, end=0x%08lx\n", 614665484d8SDoug Ambrisko (long unsigned int)span_set->log_start_lba, 615665484d8SDoug Ambrisko (long unsigned int)span_set->log_end_lba); 616665484d8SDoug Ambrisko printf("span row start=0x%08lx, end=0x%08lx\n", 617665484d8SDoug Ambrisko (long unsigned int)span_set->span_row_start, 618665484d8SDoug Ambrisko (long unsigned int)span_set->span_row_end); 619665484d8SDoug Ambrisko printf("data row start=0x%08lx, end=0x%08lx\n", 620665484d8SDoug Ambrisko (long unsigned int)span_set->data_row_start, 621665484d8SDoug Ambrisko (long unsigned int)span_set->data_row_end); 622665484d8SDoug Ambrisko printf("data strip start=0x%08lx, end=0x%08lx\n", 623665484d8SDoug Ambrisko (long unsigned int)span_set->data_strip_start, 624665484d8SDoug Ambrisko (long unsigned int)span_set->data_strip_end); 625665484d8SDoug Ambrisko 626665484d8SDoug Ambrisko for (span = 0; span < raid->spanDepth; span++) { 627665484d8SDoug Ambrisko if (map->raidMap.ldSpanMap[ld].spanBlock[span]. 628665484d8SDoug Ambrisko block_span_info.noElements >= element + 1) { 629665484d8SDoug Ambrisko quad = &map->raidMap.ldSpanMap[ld]. 630665484d8SDoug Ambrisko spanBlock[span].block_span_info. 631665484d8SDoug Ambrisko quad[element]; 632665484d8SDoug Ambrisko printf("Span=%x, Quad=%x, diff=%x\n", span, 633*e34a057cSAlfredo Dal'Ava Junior element, le32toh(quad->diff)); 634665484d8SDoug Ambrisko printf("offset_in_span=0x%08lx\n", 635*e34a057cSAlfredo Dal'Ava Junior (long unsigned int)le64toh(quad->offsetInSpan)); 636665484d8SDoug Ambrisko printf("logical start=0x%08lx, end=0x%08lx\n", 637*e34a057cSAlfredo Dal'Ava Junior (long unsigned int)le64toh(quad->logStart), 638*e34a057cSAlfredo Dal'Ava Junior (long unsigned int)le64toh(quad->logEnd)); 639665484d8SDoug Ambrisko } 640665484d8SDoug Ambrisko } 641665484d8SDoug Ambrisko } 642665484d8SDoug Ambrisko } 643665484d8SDoug Ambrisko return 0; 644665484d8SDoug Ambrisko } 6458e727371SKashyap D Desai 646665484d8SDoug Ambrisko #endif 647665484d8SDoug Ambrisko /* 648665484d8SDoug Ambrisko * 649665484d8SDoug Ambrisko * This routine calculates the Span block for given row using spanset. 650665484d8SDoug Ambrisko * 6518e727371SKashyap D Desai * Inputs : HBA instance 6528e727371SKashyap D Desai * ld: Logical drive number 6538e727371SKashyap D Desai * row: Row number 6548e727371SKashyap D Desai * map: LD map 655665484d8SDoug Ambrisko * 6568e727371SKashyap D Desai * Outputs : span - Span number block 6578e727371SKashyap D Desai * - Absolute Block number in the physical disk 658665484d8SDoug Ambrisko * div_error - Devide error code. 659665484d8SDoug Ambrisko */ 660665484d8SDoug Ambrisko 6618e727371SKashyap D Desai u_int32_t 6628e727371SKashyap D Desai mr_spanset_get_span_block(struct mrsas_softc *sc, u_int32_t ld, u_int64_t row, 6634799d485SKashyap D Desai u_int64_t *span_blk, MR_DRV_RAID_MAP_ALL * map, int *div_error) 664665484d8SDoug Ambrisko { 665665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 666665484d8SDoug Ambrisko LD_SPAN_SET *span_set; 667665484d8SDoug Ambrisko MR_QUAD_ELEMENT *quad; 668665484d8SDoug Ambrisko u_int32_t span, info; 669665484d8SDoug Ambrisko PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 670665484d8SDoug Ambrisko 671665484d8SDoug Ambrisko for (info = 0; info < MAX_QUAD_DEPTH; info++) { 672665484d8SDoug Ambrisko span_set = &(ldSpanInfo[ld].span_set[info]); 673665484d8SDoug Ambrisko 6748e727371SKashyap D Desai if (span_set->span_row_data_width == 0) 6758e727371SKashyap D Desai break; 6768e727371SKashyap D Desai if (row > span_set->data_row_end) 6778e727371SKashyap D Desai continue; 678665484d8SDoug Ambrisko 679665484d8SDoug Ambrisko for (span = 0; span < raid->spanDepth; span++) 680*e34a057cSAlfredo Dal'Ava Junior if (le32toh(map->raidMap.ldSpanMap[ld].spanBlock[span]. 681*e34a057cSAlfredo Dal'Ava Junior block_span_info.noElements) >= info + 1) { 682665484d8SDoug Ambrisko quad = &map->raidMap.ldSpanMap[ld]. 683665484d8SDoug Ambrisko spanBlock[span]. 684665484d8SDoug Ambrisko block_span_info.quad[info]; 685665484d8SDoug Ambrisko if (quad->diff == 0) { 686665484d8SDoug Ambrisko *div_error = 1; 687665484d8SDoug Ambrisko return span; 688665484d8SDoug Ambrisko } 689*e34a057cSAlfredo Dal'Ava Junior if (le64toh(quad->logStart) <= row && 690*e34a057cSAlfredo Dal'Ava Junior row <= le64toh(quad->logEnd) && 691*e34a057cSAlfredo Dal'Ava Junior (mega_mod64(row - le64toh(quad->logStart), 692*e34a057cSAlfredo Dal'Ava Junior le32toh(quad->diff))) == 0) { 693665484d8SDoug Ambrisko if (span_blk != NULL) { 694665484d8SDoug Ambrisko u_int64_t blk; 6958e727371SKashyap D Desai 696665484d8SDoug Ambrisko blk = mega_div64_32 697*e34a057cSAlfredo Dal'Ava Junior ((row - le64toh(quad->logStart)), 698*e34a057cSAlfredo Dal'Ava Junior le32toh(quad->diff)); 699*e34a057cSAlfredo Dal'Ava Junior blk = (blk + le64toh(quad->offsetInSpan)) 700665484d8SDoug Ambrisko << raid->stripeShift; 701665484d8SDoug Ambrisko *span_blk = blk; 702665484d8SDoug Ambrisko } 703665484d8SDoug Ambrisko return span; 704665484d8SDoug Ambrisko } 705665484d8SDoug Ambrisko } 706665484d8SDoug Ambrisko } 707665484d8SDoug Ambrisko return SPAN_INVALID; 708665484d8SDoug Ambrisko } 709665484d8SDoug Ambrisko 710665484d8SDoug Ambrisko /* 711665484d8SDoug Ambrisko * 712665484d8SDoug Ambrisko * This routine calculates the row for given strip using spanset. 713665484d8SDoug Ambrisko * 7148e727371SKashyap D Desai * Inputs : HBA instance 7158e727371SKashyap D Desai * ld: Logical drive number 7168e727371SKashyap D Desai * Strip: Strip 7178e727371SKashyap D Desai * map: LD map 718665484d8SDoug Ambrisko * 7198e727371SKashyap D Desai * Outputs : row - row associated with strip 720665484d8SDoug Ambrisko */ 721665484d8SDoug Ambrisko 7228e727371SKashyap D Desai static u_int64_t 7238e727371SKashyap D Desai get_row_from_strip(struct mrsas_softc *sc, 7244799d485SKashyap D Desai u_int32_t ld, u_int64_t strip, MR_DRV_RAID_MAP_ALL * map) 725665484d8SDoug Ambrisko { 726665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 727665484d8SDoug Ambrisko LD_SPAN_SET *span_set; 728665484d8SDoug Ambrisko PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 729665484d8SDoug Ambrisko u_int32_t info, strip_offset, span, span_offset; 730665484d8SDoug Ambrisko u_int64_t span_set_Strip, span_set_Row; 731665484d8SDoug Ambrisko 732665484d8SDoug Ambrisko for (info = 0; info < MAX_QUAD_DEPTH; info++) { 733665484d8SDoug Ambrisko span_set = &(ldSpanInfo[ld].span_set[info]); 734665484d8SDoug Ambrisko 7358e727371SKashyap D Desai if (span_set->span_row_data_width == 0) 7368e727371SKashyap D Desai break; 7378e727371SKashyap D Desai if (strip > span_set->data_strip_end) 7388e727371SKashyap D Desai continue; 739665484d8SDoug Ambrisko 740665484d8SDoug Ambrisko span_set_Strip = strip - span_set->data_strip_start; 741665484d8SDoug Ambrisko strip_offset = mega_mod64(span_set_Strip, 742665484d8SDoug Ambrisko span_set->span_row_data_width); 743665484d8SDoug Ambrisko span_set_Row = mega_div64_32(span_set_Strip, 744665484d8SDoug Ambrisko span_set->span_row_data_width) * span_set->diff; 745665484d8SDoug Ambrisko for (span = 0, span_offset = 0; span < raid->spanDepth; span++) 746*e34a057cSAlfredo Dal'Ava Junior if (le32toh(map->raidMap.ldSpanMap[ld].spanBlock[span]. 747*e34a057cSAlfredo Dal'Ava Junior block_span_info.noElements) >= info + 1) { 748665484d8SDoug Ambrisko if (strip_offset >= 749665484d8SDoug Ambrisko span_set->strip_offset[span]) 750665484d8SDoug Ambrisko span_offset++; 751665484d8SDoug Ambrisko else 752665484d8SDoug Ambrisko break; 753665484d8SDoug Ambrisko } 754ecea5be4SKashyap D Desai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug : Strip 0x%llx, span_set_Strip 0x%llx, span_set_Row 0x%llx " 755665484d8SDoug Ambrisko "data width 0x%llx span offset 0x%llx\n", (unsigned long long)strip, 756665484d8SDoug Ambrisko (unsigned long long)span_set_Strip, 757665484d8SDoug Ambrisko (unsigned long long)span_set_Row, 758665484d8SDoug Ambrisko (unsigned long long)span_set->span_row_data_width, (unsigned long long)span_offset); 759ecea5be4SKashyap D Desai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug : For strip 0x%llx row is 0x%llx\n", (unsigned long long)strip, 760665484d8SDoug Ambrisko (unsigned long long)span_set->data_row_start + 761665484d8SDoug Ambrisko (unsigned long long)span_set_Row + (span_offset - 1)); 762665484d8SDoug Ambrisko return (span_set->data_row_start + span_set_Row + (span_offset - 1)); 763665484d8SDoug Ambrisko } 764665484d8SDoug Ambrisko return -1LLU; 765665484d8SDoug Ambrisko } 766665484d8SDoug Ambrisko 767665484d8SDoug Ambrisko /* 768665484d8SDoug Ambrisko * 769665484d8SDoug Ambrisko * This routine calculates the Start Strip for given row using spanset. 770665484d8SDoug Ambrisko * 7718e727371SKashyap D Desai * Inputs: HBA instance 7728e727371SKashyap D Desai * ld: Logical drive number 7738e727371SKashyap D Desai * row: Row number 7748e727371SKashyap D Desai * map: LD map 775665484d8SDoug Ambrisko * 7768e727371SKashyap D Desai * Outputs : Strip - Start strip associated with row 777665484d8SDoug Ambrisko */ 778665484d8SDoug Ambrisko 7798e727371SKashyap D Desai static u_int64_t 7808e727371SKashyap D Desai get_strip_from_row(struct mrsas_softc *sc, 7814799d485SKashyap D Desai u_int32_t ld, u_int64_t row, MR_DRV_RAID_MAP_ALL * map) 782665484d8SDoug Ambrisko { 783665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 784665484d8SDoug Ambrisko LD_SPAN_SET *span_set; 785665484d8SDoug Ambrisko MR_QUAD_ELEMENT *quad; 786665484d8SDoug Ambrisko PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 787665484d8SDoug Ambrisko u_int32_t span, info; 788665484d8SDoug Ambrisko u_int64_t strip; 789665484d8SDoug Ambrisko 790665484d8SDoug Ambrisko for (info = 0; info < MAX_QUAD_DEPTH; info++) { 791665484d8SDoug Ambrisko span_set = &(ldSpanInfo[ld].span_set[info]); 792665484d8SDoug Ambrisko 7938e727371SKashyap D Desai if (span_set->span_row_data_width == 0) 7948e727371SKashyap D Desai break; 7958e727371SKashyap D Desai if (row > span_set->data_row_end) 7968e727371SKashyap D Desai continue; 797665484d8SDoug Ambrisko 798665484d8SDoug Ambrisko for (span = 0; span < raid->spanDepth; span++) 799*e34a057cSAlfredo Dal'Ava Junior if (le32toh(map->raidMap.ldSpanMap[ld].spanBlock[span]. 800*e34a057cSAlfredo Dal'Ava Junior block_span_info.noElements) >= info + 1) { 801665484d8SDoug Ambrisko quad = &map->raidMap.ldSpanMap[ld]. 802665484d8SDoug Ambrisko spanBlock[span].block_span_info.quad[info]; 803*e34a057cSAlfredo Dal'Ava Junior if (le64toh(quad->logStart) <= row && 804*e34a057cSAlfredo Dal'Ava Junior row <= le64toh(quad->logEnd) && 805*e34a057cSAlfredo Dal'Ava Junior mega_mod64((row - le64toh(quad->logStart)), 806*e34a057cSAlfredo Dal'Ava Junior le32toh(quad->diff)) == 0) { 807665484d8SDoug Ambrisko strip = mega_div64_32 808665484d8SDoug Ambrisko (((row - span_set->data_row_start) 809*e34a057cSAlfredo Dal'Ava Junior - le64toh(quad->logStart)), 810*e34a057cSAlfredo Dal'Ava Junior le32toh(quad->diff)); 811665484d8SDoug Ambrisko strip *= span_set->span_row_data_width; 812665484d8SDoug Ambrisko strip += span_set->data_strip_start; 813665484d8SDoug Ambrisko strip += span_set->strip_offset[span]; 814665484d8SDoug Ambrisko return strip; 815665484d8SDoug Ambrisko } 816665484d8SDoug Ambrisko } 817665484d8SDoug Ambrisko } 818ecea5be4SKashyap D Desai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug - get_strip_from_row: returns invalid " 819665484d8SDoug Ambrisko "strip for ld=%x, row=%lx\n", ld, (long unsigned int)row); 820665484d8SDoug Ambrisko return -1; 821665484d8SDoug Ambrisko } 822665484d8SDoug Ambrisko 823665484d8SDoug Ambrisko /* 824665484d8SDoug Ambrisko * ***************************************************************************** 825665484d8SDoug Ambrisko * 8268e727371SKashyap D Desai * 827665484d8SDoug Ambrisko * This routine calculates the Physical Arm for given strip using spanset. 828665484d8SDoug Ambrisko * 8298e727371SKashyap D Desai * Inputs : HBA instance 8308e727371SKashyap D Desai * Logical drive number 8318e727371SKashyap D Desai * Strip 8328e727371SKashyap D Desai * LD map 833665484d8SDoug Ambrisko * 8348e727371SKashyap D Desai * Outputs : Phys Arm - Phys Arm associated with strip 835665484d8SDoug Ambrisko */ 836665484d8SDoug Ambrisko 8378e727371SKashyap D Desai static u_int32_t 8388e727371SKashyap D Desai get_arm_from_strip(struct mrsas_softc *sc, 8394799d485SKashyap D Desai u_int32_t ld, u_int64_t strip, MR_DRV_RAID_MAP_ALL * map) 840665484d8SDoug Ambrisko { 841665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 842665484d8SDoug Ambrisko LD_SPAN_SET *span_set; 843665484d8SDoug Ambrisko PLD_SPAN_INFO ldSpanInfo = sc->log_to_span; 844665484d8SDoug Ambrisko u_int32_t info, strip_offset, span, span_offset; 845665484d8SDoug Ambrisko 846665484d8SDoug Ambrisko for (info = 0; info < MAX_QUAD_DEPTH; info++) { 847665484d8SDoug Ambrisko span_set = &(ldSpanInfo[ld].span_set[info]); 848665484d8SDoug Ambrisko 8498e727371SKashyap D Desai if (span_set->span_row_data_width == 0) 8508e727371SKashyap D Desai break; 8518e727371SKashyap D Desai if (strip > span_set->data_strip_end) 8528e727371SKashyap D Desai continue; 853665484d8SDoug Ambrisko 854665484d8SDoug Ambrisko strip_offset = (u_int32_t)mega_mod64 855665484d8SDoug Ambrisko ((strip - span_set->data_strip_start), 856665484d8SDoug Ambrisko span_set->span_row_data_width); 857665484d8SDoug Ambrisko 858665484d8SDoug Ambrisko for (span = 0, span_offset = 0; span < raid->spanDepth; span++) 859*e34a057cSAlfredo Dal'Ava Junior if (le32toh(map->raidMap.ldSpanMap[ld].spanBlock[span]. 860*e34a057cSAlfredo Dal'Ava Junior block_span_info.noElements) >= info + 1) { 8618e727371SKashyap D Desai if (strip_offset >= span_set->strip_offset[span]) 8628e727371SKashyap D Desai span_offset = span_set->strip_offset[span]; 863665484d8SDoug Ambrisko else 864665484d8SDoug Ambrisko break; 865665484d8SDoug Ambrisko } 866ecea5be4SKashyap D Desai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO PRL11: get_arm_from_strip: " 867665484d8SDoug Ambrisko "for ld=0x%x strip=0x%lx arm is 0x%x\n", ld, 868665484d8SDoug Ambrisko (long unsigned int)strip, (strip_offset - span_offset)); 869665484d8SDoug Ambrisko return (strip_offset - span_offset); 870665484d8SDoug Ambrisko } 871665484d8SDoug Ambrisko 872ecea5be4SKashyap D Desai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: - get_arm_from_strip: returns invalid arm" 873665484d8SDoug Ambrisko " for ld=%x strip=%lx\n", ld, (long unsigned int)strip); 874665484d8SDoug Ambrisko 875665484d8SDoug Ambrisko return -1; 876665484d8SDoug Ambrisko } 877665484d8SDoug Ambrisko 878665484d8SDoug Ambrisko /* This Function will return Phys arm */ 8798e727371SKashyap D Desai u_int8_t 8808e727371SKashyap D Desai get_arm(struct mrsas_softc *sc, u_int32_t ld, u_int8_t span, u_int64_t stripe, 8814799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * map) 882665484d8SDoug Ambrisko { 883665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 8848e727371SKashyap D Desai 885665484d8SDoug Ambrisko /* Need to check correct default value */ 886665484d8SDoug Ambrisko u_int32_t arm = 0; 887665484d8SDoug Ambrisko 888665484d8SDoug Ambrisko switch (raid->level) { 889665484d8SDoug Ambrisko case 0: 890665484d8SDoug Ambrisko case 5: 891665484d8SDoug Ambrisko case 6: 892665484d8SDoug Ambrisko arm = mega_mod64(stripe, SPAN_ROW_SIZE(map, ld, span)); 893665484d8SDoug Ambrisko break; 894665484d8SDoug Ambrisko case 1: 8958e727371SKashyap D Desai /* start with logical arm */ 896665484d8SDoug Ambrisko arm = get_arm_from_strip(sc, ld, stripe, map); 897665484d8SDoug Ambrisko arm *= 2; 898665484d8SDoug Ambrisko break; 899665484d8SDoug Ambrisko } 900665484d8SDoug Ambrisko 901665484d8SDoug Ambrisko return arm; 902665484d8SDoug Ambrisko } 903665484d8SDoug Ambrisko 904665484d8SDoug Ambrisko /* 905665484d8SDoug Ambrisko * 906665484d8SDoug Ambrisko * This routine calculates the arm, span and block for the specified stripe and 907665484d8SDoug Ambrisko * reference in stripe using spanset 908665484d8SDoug Ambrisko * 90916dc2814SKashyap D Desai * Inputs : 91016dc2814SKashyap D Desai * sc - HBA instance 91116dc2814SKashyap D Desai * ld - Logical drive number 9128e727371SKashyap D Desai * stripRow: Stripe number 9138e727371SKashyap D Desai * stripRef: Reference in stripe 914665484d8SDoug Ambrisko * 9158e727371SKashyap D Desai * Outputs : span - Span number block - Absolute Block 9168e727371SKashyap D Desai * number in the physical disk 917665484d8SDoug Ambrisko */ 9188e727371SKashyap D Desai static u_int8_t 9198e727371SKashyap D Desai mr_spanset_get_phy_params(struct mrsas_softc *sc, u_int32_t ld, u_int64_t stripRow, 920665484d8SDoug Ambrisko u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 9214799d485SKashyap D Desai RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map) 922665484d8SDoug Ambrisko { 923665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 9242a1d3bcdSKashyap D Desai u_int32_t pd, arRef, r1_alt_pd; 925665484d8SDoug Ambrisko u_int8_t physArm, span; 926665484d8SDoug Ambrisko u_int64_t row; 927665484d8SDoug Ambrisko u_int8_t retval = TRUE; 928665484d8SDoug Ambrisko u_int64_t *pdBlock = &io_info->pdBlock; 929665484d8SDoug Ambrisko u_int16_t *pDevHandle = &io_info->devHandle; 9303d273176SKashyap D Desai u_int8_t *pPdInterface = &io_info->pdInterface; 9313d273176SKashyap D Desai 932665484d8SDoug Ambrisko u_int32_t logArm, rowMod, armQ, arm; 933665484d8SDoug Ambrisko 9348e727371SKashyap D Desai /* Get row and span from io_info for Uneven Span IO. */ 935665484d8SDoug Ambrisko row = io_info->start_row; 936665484d8SDoug Ambrisko span = io_info->start_span; 937665484d8SDoug Ambrisko 938665484d8SDoug Ambrisko if (raid->level == 6) { 939665484d8SDoug Ambrisko logArm = get_arm_from_strip(sc, ld, stripRow, map); 940665484d8SDoug Ambrisko rowMod = mega_mod64(row, SPAN_ROW_SIZE(map, ld, span)); 941665484d8SDoug Ambrisko armQ = SPAN_ROW_SIZE(map, ld, span) - 1 - rowMod; 942665484d8SDoug Ambrisko arm = armQ + 1 + logArm; 943665484d8SDoug Ambrisko if (arm >= SPAN_ROW_SIZE(map, ld, span)) 944665484d8SDoug Ambrisko arm -= SPAN_ROW_SIZE(map, ld, span); 945665484d8SDoug Ambrisko physArm = (u_int8_t)arm; 946665484d8SDoug Ambrisko } else 9478e727371SKashyap D Desai /* Calculate the arm */ 948665484d8SDoug Ambrisko physArm = get_arm(sc, ld, span, stripRow, map); 949665484d8SDoug Ambrisko 950665484d8SDoug Ambrisko arRef = MR_LdSpanArrayGet(ld, span, map); 951665484d8SDoug Ambrisko pd = MR_ArPdGet(arRef, physArm, map); 952665484d8SDoug Ambrisko 9532a1d3bcdSKashyap D Desai if (pd != MR_PD_INVALID) { 954665484d8SDoug Ambrisko *pDevHandle = MR_PdDevHandleGet(pd, map); 9553d273176SKashyap D Desai *pPdInterface = MR_PdInterfaceTypeGet(pd, map); 9562a1d3bcdSKashyap D Desai /* get second pd also for raid 1/10 fast path writes */ 9572a1d3bcdSKashyap D Desai if ((raid->level == 1) && !io_info->isRead) { 9582a1d3bcdSKashyap D Desai r1_alt_pd = MR_ArPdGet(arRef, physArm + 1, map); 9592a1d3bcdSKashyap D Desai if (r1_alt_pd != MR_PD_INVALID) 9602a1d3bcdSKashyap D Desai io_info->r1_alt_dev_handle = MR_PdDevHandleGet(r1_alt_pd, map); 9612a1d3bcdSKashyap D Desai } 9622a1d3bcdSKashyap D Desai } else { 963*e34a057cSAlfredo Dal'Ava Junior *pDevHandle = htole16(MR_DEVHANDLE_INVALID); 9647aade8bfSKashyap D Desai if ((raid->level >= 5) && ((sc->device_id == MRSAS_TBOLT) || 9657aade8bfSKashyap D Desai (sc->mrsas_gen3_ctrl && 966665484d8SDoug Ambrisko raid->regTypeReqOnRead != REGION_TYPE_UNUSED))) 967665484d8SDoug Ambrisko pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; 968665484d8SDoug Ambrisko else if (raid->level == 1) { 969665484d8SDoug Ambrisko pd = MR_ArPdGet(arRef, physArm + 1, map); 9703d273176SKashyap D Desai if (pd != MR_PD_INVALID) { 971665484d8SDoug Ambrisko *pDevHandle = MR_PdDevHandleGet(pd, map); 9723d273176SKashyap D Desai *pPdInterface = MR_PdInterfaceTypeGet(pd, map); 9733d273176SKashyap D Desai } 974665484d8SDoug Ambrisko } 975665484d8SDoug Ambrisko } 976665484d8SDoug Ambrisko 977*e34a057cSAlfredo Dal'Ava Junior *pdBlock += stripRef + le64toh(MR_LdSpanPtrGet(ld, span, map)->startBlk); 9782909aab4SKashyap D Desai if (sc->is_ventura || sc->is_aero) { 979503c4f8dSKashyap D Desai ((RAID_CONTEXT_G35 *) pRAID_Context)->spanArm = 980503c4f8dSKashyap D Desai (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; 981503c4f8dSKashyap D Desai io_info->span_arm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; 982503c4f8dSKashyap D Desai } else { 983665484d8SDoug Ambrisko pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; 98416dc2814SKashyap D Desai io_info->span_arm = pRAID_Context->spanArm; 985503c4f8dSKashyap D Desai } 986665484d8SDoug Ambrisko return retval; 987665484d8SDoug Ambrisko } 988665484d8SDoug Ambrisko 9898e727371SKashyap D Desai /* 990665484d8SDoug Ambrisko * MR_BuildRaidContext: Set up Fast path RAID context 991665484d8SDoug Ambrisko * 9928e727371SKashyap D Desai * This function will initiate command processing. The start/end row and strip 9938e727371SKashyap D Desai * information is calculated then the lock is acquired. This function will 9948e727371SKashyap D Desai * return 0 if region lock was acquired OR return num strips. 995665484d8SDoug Ambrisko */ 996665484d8SDoug Ambrisko u_int8_t 997665484d8SDoug Ambrisko MR_BuildRaidContext(struct mrsas_softc *sc, struct IO_REQUEST_INFO *io_info, 9984799d485SKashyap D Desai RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map) 999665484d8SDoug Ambrisko { 1000665484d8SDoug Ambrisko MR_LD_RAID *raid; 1001665484d8SDoug Ambrisko u_int32_t ld, stripSize, stripe_mask; 1002665484d8SDoug Ambrisko u_int64_t endLba, endStrip, endRow, start_row, start_strip; 1003665484d8SDoug Ambrisko REGION_KEY regStart; 1004665484d8SDoug Ambrisko REGION_LEN regSize; 1005665484d8SDoug Ambrisko u_int8_t num_strips, numRows; 1006665484d8SDoug Ambrisko u_int16_t ref_in_start_stripe, ref_in_end_stripe; 1007665484d8SDoug Ambrisko u_int64_t ldStartBlock; 1008665484d8SDoug Ambrisko u_int32_t numBlocks, ldTgtId; 1009665484d8SDoug Ambrisko u_int8_t isRead, stripIdx; 1010665484d8SDoug Ambrisko u_int8_t retval = 0; 1011665484d8SDoug Ambrisko u_int8_t startlba_span = SPAN_INVALID; 1012665484d8SDoug Ambrisko u_int64_t *pdBlock = &io_info->pdBlock; 1013665484d8SDoug Ambrisko int error_code = 0; 1014665484d8SDoug Ambrisko 1015665484d8SDoug Ambrisko ldStartBlock = io_info->ldStartBlock; 1016665484d8SDoug Ambrisko numBlocks = io_info->numBlocks; 1017665484d8SDoug Ambrisko ldTgtId = io_info->ldTgtId; 1018665484d8SDoug Ambrisko isRead = io_info->isRead; 1019665484d8SDoug Ambrisko 1020665484d8SDoug Ambrisko io_info->IoforUnevenSpan = 0; 1021665484d8SDoug Ambrisko io_info->start_span = SPAN_INVALID; 1022665484d8SDoug Ambrisko 1023665484d8SDoug Ambrisko ld = MR_TargetIdToLdGet(ldTgtId, map); 1024665484d8SDoug Ambrisko raid = MR_LdRaidGet(ld, map); 1025665484d8SDoug Ambrisko 1026821df4b9SKashyap D Desai /* check read ahead bit */ 1027821df4b9SKashyap D Desai io_info->raCapable = raid->capability.raCapable; 1028821df4b9SKashyap D Desai 1029665484d8SDoug Ambrisko if (raid->rowDataSize == 0) { 1030665484d8SDoug Ambrisko if (MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize == 0) 1031665484d8SDoug Ambrisko return FALSE; 1032665484d8SDoug Ambrisko else if (sc->UnevenSpanSupport) { 1033665484d8SDoug Ambrisko io_info->IoforUnevenSpan = 1; 10348e727371SKashyap D Desai } else { 1035ecea5be4SKashyap D Desai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: raid->rowDataSize is 0, but has SPAN[0] rowDataSize = 0x%0x," 1036665484d8SDoug Ambrisko " but there is _NO_ UnevenSpanSupport\n", 1037665484d8SDoug Ambrisko MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize); 1038665484d8SDoug Ambrisko return FALSE; 1039665484d8SDoug Ambrisko } 1040665484d8SDoug Ambrisko } 1041665484d8SDoug Ambrisko stripSize = 1 << raid->stripeShift; 1042665484d8SDoug Ambrisko stripe_mask = stripSize - 1; 1043665484d8SDoug Ambrisko /* 1044665484d8SDoug Ambrisko * calculate starting row and stripe, and number of strips and rows 1045665484d8SDoug Ambrisko */ 1046665484d8SDoug Ambrisko start_strip = ldStartBlock >> raid->stripeShift; 1047665484d8SDoug Ambrisko ref_in_start_stripe = (u_int16_t)(ldStartBlock & stripe_mask); 1048665484d8SDoug Ambrisko endLba = ldStartBlock + numBlocks - 1; 1049665484d8SDoug Ambrisko ref_in_end_stripe = (u_int16_t)(endLba & stripe_mask); 1050665484d8SDoug Ambrisko endStrip = endLba >> raid->stripeShift; 10518e727371SKashyap D Desai num_strips = (u_int8_t)(endStrip - start_strip + 1); /* End strip */ 1052665484d8SDoug Ambrisko if (io_info->IoforUnevenSpan) { 1053665484d8SDoug Ambrisko start_row = get_row_from_strip(sc, ld, start_strip, map); 1054665484d8SDoug Ambrisko endRow = get_row_from_strip(sc, ld, endStrip, map); 1055665484d8SDoug Ambrisko if (raid->spanDepth == 1) { 1056665484d8SDoug Ambrisko startlba_span = 0; 1057665484d8SDoug Ambrisko *pdBlock = start_row << raid->stripeShift; 1058665484d8SDoug Ambrisko } else { 1059665484d8SDoug Ambrisko startlba_span = (u_int8_t)mr_spanset_get_span_block(sc, ld, start_row, 1060665484d8SDoug Ambrisko pdBlock, map, &error_code); 1061665484d8SDoug Ambrisko if (error_code == 1) { 1062ecea5be4SKashyap D Desai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: return from %s %d. Send IO w/o region lock.\n", 1063665484d8SDoug Ambrisko __func__, __LINE__); 1064665484d8SDoug Ambrisko return FALSE; 1065665484d8SDoug Ambrisko } 1066665484d8SDoug Ambrisko } 1067665484d8SDoug Ambrisko if (startlba_span == SPAN_INVALID) { 1068ecea5be4SKashyap D Desai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: return from %s %d for row 0x%llx," 1069665484d8SDoug Ambrisko "start strip %llx endSrip %llx\n", __func__, 1070665484d8SDoug Ambrisko __LINE__, (unsigned long long)start_row, 1071665484d8SDoug Ambrisko (unsigned long long)start_strip, 1072665484d8SDoug Ambrisko (unsigned long long)endStrip); 1073665484d8SDoug Ambrisko return FALSE; 1074665484d8SDoug Ambrisko } 1075665484d8SDoug Ambrisko io_info->start_span = startlba_span; 1076665484d8SDoug Ambrisko io_info->start_row = start_row; 1077ecea5be4SKashyap D Desai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: Check Span number from %s %d for row 0x%llx, " 1078665484d8SDoug Ambrisko " start strip 0x%llx endSrip 0x%llx span 0x%x\n", 1079665484d8SDoug Ambrisko __func__, __LINE__, (unsigned long long)start_row, 1080665484d8SDoug Ambrisko (unsigned long long)start_strip, 1081665484d8SDoug Ambrisko (unsigned long long)endStrip, startlba_span); 1082ecea5be4SKashyap D Desai mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug : 1. start_row 0x%llx endRow 0x%llx Start span 0x%x\n", 1083665484d8SDoug Ambrisko (unsigned long long)start_row, (unsigned long long)endRow, startlba_span); 1084665484d8SDoug Ambrisko } else { 10858e727371SKashyap D Desai start_row = mega_div64_32(start_strip, raid->rowDataSize); 1086665484d8SDoug Ambrisko endRow = mega_div64_32(endStrip, raid->rowDataSize); 1087665484d8SDoug Ambrisko } 1088665484d8SDoug Ambrisko 10898e727371SKashyap D Desai numRows = (u_int8_t)(endRow - start_row + 1); /* get the row count */ 1090665484d8SDoug Ambrisko 1091665484d8SDoug Ambrisko /* 1092665484d8SDoug Ambrisko * Calculate region info. (Assume region at start of first row, and 1093665484d8SDoug Ambrisko * assume this IO needs the full row - will adjust if not true.) 1094665484d8SDoug Ambrisko */ 1095665484d8SDoug Ambrisko regStart = start_row << raid->stripeShift; 1096665484d8SDoug Ambrisko regSize = stripSize; 1097665484d8SDoug Ambrisko 1098665484d8SDoug Ambrisko /* Check if we can send this I/O via FastPath */ 1099665484d8SDoug Ambrisko if (raid->capability.fpCapable) { 1100665484d8SDoug Ambrisko if (isRead) 1101665484d8SDoug Ambrisko io_info->fpOkForIo = (raid->capability.fpReadCapable && 1102665484d8SDoug Ambrisko ((num_strips == 1) || 11038e727371SKashyap D Desai raid->capability.fpReadAcrossStripe)); 1104665484d8SDoug Ambrisko else 1105665484d8SDoug Ambrisko io_info->fpOkForIo = (raid->capability.fpWriteCapable && 1106665484d8SDoug Ambrisko ((num_strips == 1) || 11078e727371SKashyap D Desai raid->capability.fpWriteAcrossStripe)); 11088e727371SKashyap D Desai } else 1109665484d8SDoug Ambrisko io_info->fpOkForIo = FALSE; 1110665484d8SDoug Ambrisko 1111665484d8SDoug Ambrisko if (numRows == 1) { 1112665484d8SDoug Ambrisko if (num_strips == 1) { 1113665484d8SDoug Ambrisko regStart += ref_in_start_stripe; 1114665484d8SDoug Ambrisko regSize = numBlocks; 1115665484d8SDoug Ambrisko } 11168e727371SKashyap D Desai } else if (io_info->IoforUnevenSpan == 0) { 11178e727371SKashyap D Desai /* 11188e727371SKashyap D Desai * For Even span region lock optimization. If the start strip 11198e727371SKashyap D Desai * is the last in the start row 11208e727371SKashyap D Desai */ 1121665484d8SDoug Ambrisko if (start_strip == (start_row + 1) * raid->rowDataSize - 1) { 1122665484d8SDoug Ambrisko regStart += ref_in_start_stripe; 11238e727371SKashyap D Desai /* 11248e727371SKashyap D Desai * initialize count to sectors from startRef to end 11258e727371SKashyap D Desai * of strip 11268e727371SKashyap D Desai */ 1127665484d8SDoug Ambrisko regSize = stripSize - ref_in_start_stripe; 1128665484d8SDoug Ambrisko } 11298e727371SKashyap D Desai /* add complete rows in the middle of the transfer */ 1130665484d8SDoug Ambrisko if (numRows > 2) 1131665484d8SDoug Ambrisko regSize += (numRows - 2) << raid->stripeShift; 1132665484d8SDoug Ambrisko 11338e727371SKashyap D Desai /* if IO ends within first strip of last row */ 1134665484d8SDoug Ambrisko if (endStrip == endRow * raid->rowDataSize) 1135665484d8SDoug Ambrisko regSize += ref_in_end_stripe + 1; 1136665484d8SDoug Ambrisko else 1137665484d8SDoug Ambrisko regSize += stripSize; 1138665484d8SDoug Ambrisko } else { 1139665484d8SDoug Ambrisko if (start_strip == (get_strip_from_row(sc, ld, start_row, map) + 1140665484d8SDoug Ambrisko SPAN_ROW_DATA_SIZE(map, ld, startlba_span) - 1)) { 1141665484d8SDoug Ambrisko regStart += ref_in_start_stripe; 11428e727371SKashyap D Desai /* 11438e727371SKashyap D Desai * initialize count to sectors from startRef to end 11448e727371SKashyap D Desai * of strip 11458e727371SKashyap D Desai */ 1146665484d8SDoug Ambrisko regSize = stripSize - ref_in_start_stripe; 1147665484d8SDoug Ambrisko } 11488e727371SKashyap D Desai /* add complete rows in the middle of the transfer */ 1149665484d8SDoug Ambrisko if (numRows > 2) 1150665484d8SDoug Ambrisko regSize += (numRows - 2) << raid->stripeShift; 1151665484d8SDoug Ambrisko 11528e727371SKashyap D Desai /* if IO ends within first strip of last row */ 1153665484d8SDoug Ambrisko if (endStrip == get_strip_from_row(sc, ld, endRow, map)) 1154665484d8SDoug Ambrisko regSize += ref_in_end_stripe + 1; 1155665484d8SDoug Ambrisko else 1156665484d8SDoug Ambrisko regSize += stripSize; 1157665484d8SDoug Ambrisko } 1158*e34a057cSAlfredo Dal'Ava Junior pRAID_Context->timeoutValue = htole16(map->raidMap.fpPdIoTimeoutSec); 1159f9c63081SKashyap D Desai if (sc->mrsas_gen3_ctrl) 1160665484d8SDoug Ambrisko pRAID_Context->regLockFlags = (isRead) ? raid->regTypeReqOnRead : raid->regTypeReqOnWrite; 11617aade8bfSKashyap D Desai else if (sc->device_id == MRSAS_TBOLT) 1162665484d8SDoug Ambrisko pRAID_Context->regLockFlags = (isRead) ? REGION_TYPE_SHARED_READ : raid->regTypeReqOnWrite; 1163665484d8SDoug Ambrisko pRAID_Context->VirtualDiskTgtId = raid->targetId; 1164*e34a057cSAlfredo Dal'Ava Junior pRAID_Context->regLockRowLBA = htole64(regStart); 1165*e34a057cSAlfredo Dal'Ava Junior pRAID_Context->regLockLength = htole32(regSize); 1166665484d8SDoug Ambrisko pRAID_Context->configSeqNum = raid->seqNum; 1167665484d8SDoug Ambrisko 1168665484d8SDoug Ambrisko /* 1169665484d8SDoug Ambrisko * Get Phy Params only if FP capable, or else leave it to MR firmware 1170665484d8SDoug Ambrisko * to do the calculation. 1171665484d8SDoug Ambrisko */ 1172665484d8SDoug Ambrisko if (io_info->fpOkForIo) { 1173665484d8SDoug Ambrisko retval = io_info->IoforUnevenSpan ? 11748e727371SKashyap D Desai mr_spanset_get_phy_params(sc, ld, start_strip, 11758e727371SKashyap D Desai ref_in_start_stripe, io_info, pRAID_Context, map) : 1176665484d8SDoug Ambrisko MR_GetPhyParams(sc, ld, start_strip, 1177665484d8SDoug Ambrisko ref_in_start_stripe, io_info, pRAID_Context, map); 1178665484d8SDoug Ambrisko /* If IO on an invalid Pd, then FP is not possible */ 11792a1d3bcdSKashyap D Desai if (io_info->devHandle == MR_DEVHANDLE_INVALID) 1180665484d8SDoug Ambrisko io_info->fpOkForIo = FALSE; 1181503c4f8dSKashyap D Desai /* 1182503c4f8dSKashyap D Desai * if FP possible, set the SLUD bit in regLockFlags for 1183503c4f8dSKashyap D Desai * ventura 1184503c4f8dSKashyap D Desai */ 11852909aab4SKashyap D Desai else if ((sc->is_ventura || sc->is_aero) && !isRead && 1186503c4f8dSKashyap D Desai (raid->writeMode == MR_RL_WRITE_BACK_MODE) && (raid->level <= 1) && 1187503c4f8dSKashyap D Desai raid->capability.fpCacheBypassCapable) { 1188503c4f8dSKashyap D Desai ((RAID_CONTEXT_G35 *) pRAID_Context)->routingFlags.bits.sld = 1; 1189503c4f8dSKashyap D Desai } 11902a1d3bcdSKashyap D Desai 1191665484d8SDoug Ambrisko return retval; 11928e727371SKashyap D Desai } else if (isRead) { 1193665484d8SDoug Ambrisko for (stripIdx = 0; stripIdx < num_strips; stripIdx++) { 1194665484d8SDoug Ambrisko retval = io_info->IoforUnevenSpan ? 11958e727371SKashyap D Desai mr_spanset_get_phy_params(sc, ld, start_strip + stripIdx, 11968e727371SKashyap D Desai ref_in_start_stripe, io_info, pRAID_Context, map) : 11978e727371SKashyap D Desai MR_GetPhyParams(sc, ld, start_strip + stripIdx, 11988e727371SKashyap D Desai ref_in_start_stripe, io_info, pRAID_Context, map); 1199665484d8SDoug Ambrisko if (!retval) 1200665484d8SDoug Ambrisko return TRUE; 1201665484d8SDoug Ambrisko } 1202665484d8SDoug Ambrisko } 1203665484d8SDoug Ambrisko #if SPAN_DEBUG 12048e727371SKashyap D Desai /* Just for testing what arm we get for strip. */ 1205665484d8SDoug Ambrisko get_arm_from_strip(sc, ld, start_strip, map); 1206665484d8SDoug Ambrisko #endif 1207665484d8SDoug Ambrisko return TRUE; 1208665484d8SDoug Ambrisko } 1209665484d8SDoug Ambrisko 1210665484d8SDoug Ambrisko /* 1211665484d8SDoug Ambrisko * 12128e727371SKashyap D Desai * This routine pepare spanset info from Valid Raid map and store it into local 12138e727371SKashyap D Desai * copy of ldSpanInfo per instance data structure. 1214665484d8SDoug Ambrisko * 12158e727371SKashyap D Desai * Inputs : LD map 12168e727371SKashyap D Desai * ldSpanInfo per HBA instance 1217665484d8SDoug Ambrisko * 1218665484d8SDoug Ambrisko */ 12198e727371SKashyap D Desai void 12208e727371SKashyap D Desai mr_update_span_set(MR_DRV_RAID_MAP_ALL * map, PLD_SPAN_INFO ldSpanInfo) 1221665484d8SDoug Ambrisko { 1222665484d8SDoug Ambrisko u_int8_t span, count; 1223665484d8SDoug Ambrisko u_int32_t element, span_row_width; 1224665484d8SDoug Ambrisko u_int64_t span_row; 1225665484d8SDoug Ambrisko MR_LD_RAID *raid; 1226665484d8SDoug Ambrisko LD_SPAN_SET *span_set, *span_set_prev; 1227665484d8SDoug Ambrisko MR_QUAD_ELEMENT *quad; 1228665484d8SDoug Ambrisko int ldCount; 1229665484d8SDoug Ambrisko u_int16_t ld; 1230665484d8SDoug Ambrisko 12318e727371SKashyap D Desai for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) { 1232665484d8SDoug Ambrisko ld = MR_TargetIdToLdGet(ldCount, map); 1233665484d8SDoug Ambrisko if (ld >= MAX_LOGICAL_DRIVES) 1234665484d8SDoug Ambrisko continue; 1235665484d8SDoug Ambrisko raid = MR_LdRaidGet(ld, map); 1236665484d8SDoug Ambrisko for (element = 0; element < MAX_QUAD_DEPTH; element++) { 1237665484d8SDoug Ambrisko for (span = 0; span < raid->spanDepth; span++) { 1238*e34a057cSAlfredo Dal'Ava Junior if (le32toh(map->raidMap.ldSpanMap[ld].spanBlock[span]. 1239*e34a057cSAlfredo Dal'Ava Junior block_span_info.noElements) < element + 1) 1240665484d8SDoug Ambrisko continue; 12418e727371SKashyap D Desai /* TO-DO */ 1242665484d8SDoug Ambrisko span_set = &(ldSpanInfo[ld].span_set[element]); 1243665484d8SDoug Ambrisko quad = &map->raidMap.ldSpanMap[ld]. 12448e727371SKashyap D Desai spanBlock[span].block_span_info.quad[element]; 1245665484d8SDoug Ambrisko 1246*e34a057cSAlfredo Dal'Ava Junior span_set->diff = le32toh(quad->diff); 1247665484d8SDoug Ambrisko 1248665484d8SDoug Ambrisko for (count = 0, span_row_width = 0; 1249665484d8SDoug Ambrisko count < raid->spanDepth; count++) { 1250*e34a057cSAlfredo Dal'Ava Junior if (le32toh(map->raidMap.ldSpanMap[ld].spanBlock[count]. 1251*e34a057cSAlfredo Dal'Ava Junior block_span_info.noElements) >= element + 1) { 12528e727371SKashyap D Desai span_set->strip_offset[count] = span_row_width; 1253665484d8SDoug Ambrisko span_row_width += 12548e727371SKashyap D Desai MR_LdSpanPtrGet(ld, count, map)->spanRowDataSize; 1255665484d8SDoug Ambrisko #if SPAN_DEBUG 1256ecea5be4SKashyap D Desai printf("AVAGO Debug span %x rowDataSize %x\n", count, 12578e727371SKashyap D Desai MR_LdSpanPtrGet(ld, count, map)->spanRowDataSize); 1258665484d8SDoug Ambrisko #endif 1259665484d8SDoug Ambrisko } 1260665484d8SDoug Ambrisko } 1261665484d8SDoug Ambrisko 1262665484d8SDoug Ambrisko span_set->span_row_data_width = span_row_width; 1263*e34a057cSAlfredo Dal'Ava Junior span_row = mega_div64_32(((le64toh(quad->logEnd) - 1264*e34a057cSAlfredo Dal'Ava Junior le64toh(quad->logStart)) + le32toh(quad->diff)), 1265*e34a057cSAlfredo Dal'Ava Junior le32toh(quad->diff)); 1266665484d8SDoug Ambrisko 1267665484d8SDoug Ambrisko if (element == 0) { 1268665484d8SDoug Ambrisko span_set->log_start_lba = 0; 1269665484d8SDoug Ambrisko span_set->log_end_lba = 1270665484d8SDoug Ambrisko ((span_row << raid->stripeShift) * span_row_width) - 1; 1271665484d8SDoug Ambrisko 1272665484d8SDoug Ambrisko span_set->span_row_start = 0; 1273665484d8SDoug Ambrisko span_set->span_row_end = span_row - 1; 1274665484d8SDoug Ambrisko 1275665484d8SDoug Ambrisko span_set->data_strip_start = 0; 12768e727371SKashyap D Desai span_set->data_strip_end = (span_row * span_row_width) - 1; 1277665484d8SDoug Ambrisko 1278665484d8SDoug Ambrisko span_set->data_row_start = 0; 1279*e34a057cSAlfredo Dal'Ava Junior span_set->data_row_end = 1280*e34a057cSAlfredo Dal'Ava Junior (span_row * le32toh(quad->diff)) - 1; 1281665484d8SDoug Ambrisko } else { 12828e727371SKashyap D Desai span_set_prev = &(ldSpanInfo[ld].span_set[element - 1]); 12838e727371SKashyap D Desai span_set->log_start_lba = span_set_prev->log_end_lba + 1; 12848e727371SKashyap D Desai span_set->log_end_lba = span_set->log_start_lba + 1285665484d8SDoug Ambrisko ((span_row << raid->stripeShift) * span_row_width) - 1; 1286665484d8SDoug Ambrisko 12878e727371SKashyap D Desai span_set->span_row_start = span_set_prev->span_row_end + 1; 1288665484d8SDoug Ambrisko span_set->span_row_end = 1289665484d8SDoug Ambrisko span_set->span_row_start + span_row - 1; 1290665484d8SDoug Ambrisko 1291665484d8SDoug Ambrisko span_set->data_strip_start = 1292665484d8SDoug Ambrisko span_set_prev->data_strip_end + 1; 12938e727371SKashyap D Desai span_set->data_strip_end = span_set->data_strip_start + 1294665484d8SDoug Ambrisko (span_row * span_row_width) - 1; 1295665484d8SDoug Ambrisko 12968e727371SKashyap D Desai span_set->data_row_start = span_set_prev->data_row_end + 1; 12978e727371SKashyap D Desai span_set->data_row_end = span_set->data_row_start + 1298*e34a057cSAlfredo Dal'Ava Junior (span_row * le32toh(quad->diff)) - 1; 1299665484d8SDoug Ambrisko } 1300665484d8SDoug Ambrisko break; 1301665484d8SDoug Ambrisko } 13028e727371SKashyap D Desai if (span == raid->spanDepth) 13038e727371SKashyap D Desai break; /* no quads remain */ 1304665484d8SDoug Ambrisko } 1305665484d8SDoug Ambrisko } 1306665484d8SDoug Ambrisko #if SPAN_DEBUG 13078e727371SKashyap D Desai getSpanInfo(map, ldSpanInfo); /* to get span set info */ 1308665484d8SDoug Ambrisko #endif 1309665484d8SDoug Ambrisko } 1310665484d8SDoug Ambrisko 13118e727371SKashyap D Desai /* 1312665484d8SDoug Ambrisko * mrsas_update_load_balance_params: Update load balance parmas 131316dc2814SKashyap D Desai * Inputs: 131416dc2814SKashyap D Desai * sc - driver softc instance 131516dc2814SKashyap D Desai * drv_map - driver RAID map 131616dc2814SKashyap D Desai * lbInfo - Load balance info 1317665484d8SDoug Ambrisko * 13188e727371SKashyap D Desai * This function updates the load balance parameters for the LD config of a two 13198e727371SKashyap D Desai * drive optimal RAID-1. 1320665484d8SDoug Ambrisko */ 13218e727371SKashyap D Desai void 132216dc2814SKashyap D Desai mrsas_update_load_balance_params(struct mrsas_softc *sc, 132316dc2814SKashyap D Desai MR_DRV_RAID_MAP_ALL * drv_map, PLD_LOAD_BALANCE_INFO lbInfo) 1324665484d8SDoug Ambrisko { 1325665484d8SDoug Ambrisko int ldCount; 1326665484d8SDoug Ambrisko u_int16_t ld; 1327665484d8SDoug Ambrisko MR_LD_RAID *raid; 1328665484d8SDoug Ambrisko 132916dc2814SKashyap D Desai if (sc->lb_pending_cmds > 128 || sc->lb_pending_cmds < 1) 133016dc2814SKashyap D Desai sc->lb_pending_cmds = LB_PENDING_CMDS_DEFAULT; 133116dc2814SKashyap D Desai 133216dc2814SKashyap D Desai for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES_EXT; ldCount++) { 133316dc2814SKashyap D Desai ld = MR_TargetIdToLdGet(ldCount, drv_map); 133416dc2814SKashyap D Desai if (ld >= MAX_LOGICAL_DRIVES_EXT) { 1335665484d8SDoug Ambrisko lbInfo[ldCount].loadBalanceFlag = 0; 1336665484d8SDoug Ambrisko continue; 1337665484d8SDoug Ambrisko } 133816dc2814SKashyap D Desai raid = MR_LdRaidGet(ld, drv_map); 1339*e34a057cSAlfredo Dal'Ava Junior le32_to_cpus(&raid->capability); 134016dc2814SKashyap D Desai if ((raid->level != 1) || 134116dc2814SKashyap D Desai (raid->ldState != MR_LD_STATE_OPTIMAL)) { 1342665484d8SDoug Ambrisko lbInfo[ldCount].loadBalanceFlag = 0; 134316dc2814SKashyap D Desai continue; 134416dc2814SKashyap D Desai } 134516dc2814SKashyap D Desai lbInfo[ldCount].loadBalanceFlag = 1; 1346665484d8SDoug Ambrisko } 1347665484d8SDoug Ambrisko } 1348665484d8SDoug Ambrisko 13498e727371SKashyap D Desai /* 1350665484d8SDoug Ambrisko * mrsas_set_pd_lba: Sets PD LBA 1351665484d8SDoug Ambrisko * input: io_request pointer 1352665484d8SDoug Ambrisko * CDB length 1353665484d8SDoug Ambrisko * io_info pointer 1354665484d8SDoug Ambrisko * Pointer to CCB 1355665484d8SDoug Ambrisko * Local RAID map pointer 13568e727371SKashyap D Desai * Start block of IO Block Size 1357665484d8SDoug Ambrisko * 1358665484d8SDoug Ambrisko * Used to set the PD logical block address in CDB for FP IOs. 1359665484d8SDoug Ambrisko */ 13608e727371SKashyap D Desai void 13618e727371SKashyap D Desai mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request, u_int8_t cdb_len, 1362665484d8SDoug Ambrisko struct IO_REQUEST_INFO *io_info, union ccb *ccb, 13634799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * local_map_ptr, u_int32_t ref_tag, 1364665484d8SDoug Ambrisko u_int32_t ld_block_size) 1365665484d8SDoug Ambrisko { 1366665484d8SDoug Ambrisko MR_LD_RAID *raid; 1367665484d8SDoug Ambrisko u_int32_t ld; 1368665484d8SDoug Ambrisko u_int64_t start_blk = io_info->pdBlock; 1369665484d8SDoug Ambrisko u_int8_t *cdb = io_request->CDB.CDB32; 1370665484d8SDoug Ambrisko u_int32_t num_blocks = io_info->numBlocks; 1371665484d8SDoug Ambrisko u_int8_t opcode = 0, flagvals = 0, groupnum = 0, control = 0; 1372665484d8SDoug Ambrisko struct ccb_hdr *ccb_h = &(ccb->ccb_h); 1373665484d8SDoug Ambrisko 1374665484d8SDoug Ambrisko /* Check if T10 PI (DIF) is enabled for this LD */ 1375665484d8SDoug Ambrisko ld = MR_TargetIdToLdGet(io_info->ldTgtId, local_map_ptr); 1376665484d8SDoug Ambrisko raid = MR_LdRaidGet(ld, local_map_ptr); 1377665484d8SDoug Ambrisko if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER) { 1378665484d8SDoug Ambrisko memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1379665484d8SDoug Ambrisko cdb[0] = MRSAS_SCSI_VARIABLE_LENGTH_CMD; 1380665484d8SDoug Ambrisko cdb[7] = MRSAS_SCSI_ADDL_CDB_LEN; 1381665484d8SDoug Ambrisko 1382665484d8SDoug Ambrisko if (ccb_h->flags == CAM_DIR_OUT) 1383665484d8SDoug Ambrisko cdb[9] = MRSAS_SCSI_SERVICE_ACTION_READ32; 1384665484d8SDoug Ambrisko else 1385665484d8SDoug Ambrisko cdb[9] = MRSAS_SCSI_SERVICE_ACTION_WRITE32; 1386665484d8SDoug Ambrisko cdb[10] = MRSAS_RD_WR_PROTECT_CHECK_ALL; 1387665484d8SDoug Ambrisko 1388665484d8SDoug Ambrisko /* LBA */ 1389665484d8SDoug Ambrisko cdb[12] = (u_int8_t)((start_blk >> 56) & 0xff); 1390665484d8SDoug Ambrisko cdb[13] = (u_int8_t)((start_blk >> 48) & 0xff); 1391665484d8SDoug Ambrisko cdb[14] = (u_int8_t)((start_blk >> 40) & 0xff); 1392665484d8SDoug Ambrisko cdb[15] = (u_int8_t)((start_blk >> 32) & 0xff); 1393665484d8SDoug Ambrisko cdb[16] = (u_int8_t)((start_blk >> 24) & 0xff); 1394665484d8SDoug Ambrisko cdb[17] = (u_int8_t)((start_blk >> 16) & 0xff); 1395665484d8SDoug Ambrisko cdb[18] = (u_int8_t)((start_blk >> 8) & 0xff); 1396665484d8SDoug Ambrisko cdb[19] = (u_int8_t)(start_blk & 0xff); 1397665484d8SDoug Ambrisko 1398665484d8SDoug Ambrisko /* Logical block reference tag */ 1399*e34a057cSAlfredo Dal'Ava Junior io_request->CDB.EEDP32.PrimaryReferenceTag = htobe32(ref_tag); 1400*e34a057cSAlfredo Dal'Ava Junior io_request->CDB.EEDP32.PrimaryApplicationTagMask = htobe16(0xffff); 1401*e34a057cSAlfredo Dal'Ava Junior io_request->IoFlags = htole16(32); /* Specify 32-byte cdb */ 1402665484d8SDoug Ambrisko 1403665484d8SDoug Ambrisko /* Transfer length */ 1404665484d8SDoug Ambrisko cdb[28] = (u_int8_t)((num_blocks >> 24) & 0xff); 1405665484d8SDoug Ambrisko cdb[29] = (u_int8_t)((num_blocks >> 16) & 0xff); 1406665484d8SDoug Ambrisko cdb[30] = (u_int8_t)((num_blocks >> 8) & 0xff); 1407665484d8SDoug Ambrisko cdb[31] = (u_int8_t)(num_blocks & 0xff); 1408665484d8SDoug Ambrisko 1409665484d8SDoug Ambrisko /* set SCSI IO EEDP Flags */ 1410665484d8SDoug Ambrisko if (ccb_h->flags == CAM_DIR_OUT) { 1411*e34a057cSAlfredo Dal'Ava Junior io_request->EEDPFlags = htole16( 1412665484d8SDoug Ambrisko MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | 1413665484d8SDoug Ambrisko MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | 1414665484d8SDoug Ambrisko MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP | 1415665484d8SDoug Ambrisko MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG | 1416*e34a057cSAlfredo Dal'Ava Junior MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD); 14178e727371SKashyap D Desai } else { 1418*e34a057cSAlfredo Dal'Ava Junior io_request->EEDPFlags = htole16( 1419665484d8SDoug Ambrisko MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | 1420*e34a057cSAlfredo Dal'Ava Junior MPI2_SCSIIO_EEDPFLAGS_INSERT_OP); 1421665484d8SDoug Ambrisko } 1422*e34a057cSAlfredo Dal'Ava Junior io_request->Control |= htole32(0x4 << 26); 1423*e34a057cSAlfredo Dal'Ava Junior io_request->EEDPBlockSize = htole32(ld_block_size); 14248e727371SKashyap D Desai } else { 1425665484d8SDoug Ambrisko /* Some drives don't support 16/12 byte CDB's, convert to 10 */ 1426665484d8SDoug Ambrisko if (((cdb_len == 12) || (cdb_len == 16)) && 1427665484d8SDoug Ambrisko (start_blk <= 0xffffffff)) { 1428665484d8SDoug Ambrisko if (cdb_len == 16) { 1429665484d8SDoug Ambrisko opcode = cdb[0] == READ_16 ? READ_10 : WRITE_10; 1430665484d8SDoug Ambrisko flagvals = cdb[1]; 1431665484d8SDoug Ambrisko groupnum = cdb[14]; 1432665484d8SDoug Ambrisko control = cdb[15]; 14338e727371SKashyap D Desai } else { 1434665484d8SDoug Ambrisko opcode = cdb[0] == READ_12 ? READ_10 : WRITE_10; 1435665484d8SDoug Ambrisko flagvals = cdb[1]; 1436665484d8SDoug Ambrisko groupnum = cdb[10]; 1437665484d8SDoug Ambrisko control = cdb[11]; 1438665484d8SDoug Ambrisko } 1439665484d8SDoug Ambrisko 1440665484d8SDoug Ambrisko memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1441665484d8SDoug Ambrisko 1442665484d8SDoug Ambrisko cdb[0] = opcode; 1443665484d8SDoug Ambrisko cdb[1] = flagvals; 1444665484d8SDoug Ambrisko cdb[6] = groupnum; 1445665484d8SDoug Ambrisko cdb[9] = control; 1446665484d8SDoug Ambrisko 1447665484d8SDoug Ambrisko /* Transfer length */ 1448665484d8SDoug Ambrisko cdb[8] = (u_int8_t)(num_blocks & 0xff); 1449665484d8SDoug Ambrisko cdb[7] = (u_int8_t)((num_blocks >> 8) & 0xff); 1450665484d8SDoug Ambrisko 1451*e34a057cSAlfredo Dal'Ava Junior io_request->IoFlags = htole16(10); /* Specify 10-byte cdb */ 1452665484d8SDoug Ambrisko cdb_len = 10; 1453665484d8SDoug Ambrisko } else if ((cdb_len < 16) && (start_blk > 0xffffffff)) { 1454665484d8SDoug Ambrisko /* Convert to 16 byte CDB for large LBA's */ 1455665484d8SDoug Ambrisko switch (cdb_len) { 1456665484d8SDoug Ambrisko case 6: 1457665484d8SDoug Ambrisko opcode = cdb[0] == READ_6 ? READ_16 : WRITE_16; 1458665484d8SDoug Ambrisko control = cdb[5]; 1459665484d8SDoug Ambrisko break; 1460665484d8SDoug Ambrisko case 10: 1461665484d8SDoug Ambrisko opcode = cdb[0] == READ_10 ? READ_16 : WRITE_16; 1462665484d8SDoug Ambrisko flagvals = cdb[1]; 1463665484d8SDoug Ambrisko groupnum = cdb[6]; 1464665484d8SDoug Ambrisko control = cdb[9]; 1465665484d8SDoug Ambrisko break; 1466665484d8SDoug Ambrisko case 12: 1467665484d8SDoug Ambrisko opcode = cdb[0] == READ_12 ? READ_16 : WRITE_16; 1468665484d8SDoug Ambrisko flagvals = cdb[1]; 1469665484d8SDoug Ambrisko groupnum = cdb[10]; 1470665484d8SDoug Ambrisko control = cdb[11]; 1471665484d8SDoug Ambrisko break; 1472665484d8SDoug Ambrisko } 1473665484d8SDoug Ambrisko 1474665484d8SDoug Ambrisko memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1475665484d8SDoug Ambrisko 1476665484d8SDoug Ambrisko cdb[0] = opcode; 1477665484d8SDoug Ambrisko cdb[1] = flagvals; 1478665484d8SDoug Ambrisko cdb[14] = groupnum; 1479665484d8SDoug Ambrisko cdb[15] = control; 1480665484d8SDoug Ambrisko 1481665484d8SDoug Ambrisko /* Transfer length */ 1482665484d8SDoug Ambrisko cdb[13] = (u_int8_t)(num_blocks & 0xff); 1483665484d8SDoug Ambrisko cdb[12] = (u_int8_t)((num_blocks >> 8) & 0xff); 1484665484d8SDoug Ambrisko cdb[11] = (u_int8_t)((num_blocks >> 16) & 0xff); 1485665484d8SDoug Ambrisko cdb[10] = (u_int8_t)((num_blocks >> 24) & 0xff); 1486665484d8SDoug Ambrisko 1487*e34a057cSAlfredo Dal'Ava Junior io_request->IoFlags = htole16(16); /* Specify 16-byte cdb */ 1488665484d8SDoug Ambrisko cdb_len = 16; 1489665484d8SDoug Ambrisko } else if ((cdb_len == 6) && (start_blk > 0x1fffff)) { 1490665484d8SDoug Ambrisko /* convert to 10 byte CDB */ 1491665484d8SDoug Ambrisko opcode = cdb[0] == READ_6 ? READ_10 : WRITE_10; 1492665484d8SDoug Ambrisko control = cdb[5]; 1493665484d8SDoug Ambrisko 149402190a56SXin LI memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1495665484d8SDoug Ambrisko cdb[0] = opcode; 1496665484d8SDoug Ambrisko cdb[9] = control; 1497665484d8SDoug Ambrisko 1498665484d8SDoug Ambrisko /* Set transfer length */ 1499665484d8SDoug Ambrisko cdb[8] = (u_int8_t)(num_blocks & 0xff); 1500665484d8SDoug Ambrisko cdb[7] = (u_int8_t)((num_blocks >> 8) & 0xff); 1501665484d8SDoug Ambrisko 1502665484d8SDoug Ambrisko /* Specify 10-byte cdb */ 1503665484d8SDoug Ambrisko cdb_len = 10; 1504665484d8SDoug Ambrisko } 1505665484d8SDoug Ambrisko /* Fall through normal case, just load LBA here */ 1506665484d8SDoug Ambrisko u_int8_t val = cdb[1] & 0xE0; 1507dbcc81dfSKashyap D Desai 15088e727371SKashyap D Desai switch (cdb_len) { 15098e727371SKashyap D Desai case 6: 1510665484d8SDoug Ambrisko cdb[3] = (u_int8_t)(start_blk & 0xff); 1511665484d8SDoug Ambrisko cdb[2] = (u_int8_t)((start_blk >> 8) & 0xff); 1512665484d8SDoug Ambrisko cdb[1] = val | ((u_int8_t)(start_blk >> 16) & 0x1f); 1513665484d8SDoug Ambrisko break; 1514665484d8SDoug Ambrisko case 10: 1515665484d8SDoug Ambrisko cdb[5] = (u_int8_t)(start_blk & 0xff); 1516665484d8SDoug Ambrisko cdb[4] = (u_int8_t)((start_blk >> 8) & 0xff); 1517665484d8SDoug Ambrisko cdb[3] = (u_int8_t)((start_blk >> 16) & 0xff); 1518665484d8SDoug Ambrisko cdb[2] = (u_int8_t)((start_blk >> 24) & 0xff); 1519665484d8SDoug Ambrisko break; 1520665484d8SDoug Ambrisko case 16: 1521665484d8SDoug Ambrisko cdb[9] = (u_int8_t)(start_blk & 0xff); 1522665484d8SDoug Ambrisko cdb[8] = (u_int8_t)((start_blk >> 8) & 0xff); 1523665484d8SDoug Ambrisko cdb[7] = (u_int8_t)((start_blk >> 16) & 0xff); 1524665484d8SDoug Ambrisko cdb[6] = (u_int8_t)((start_blk >> 24) & 0xff); 1525665484d8SDoug Ambrisko cdb[5] = (u_int8_t)((start_blk >> 32) & 0xff); 1526665484d8SDoug Ambrisko cdb[4] = (u_int8_t)((start_blk >> 40) & 0xff); 1527665484d8SDoug Ambrisko cdb[3] = (u_int8_t)((start_blk >> 48) & 0xff); 1528665484d8SDoug Ambrisko cdb[2] = (u_int8_t)((start_blk >> 56) & 0xff); 1529665484d8SDoug Ambrisko break; 1530665484d8SDoug Ambrisko } 1531665484d8SDoug Ambrisko } 1532665484d8SDoug Ambrisko } 1533665484d8SDoug Ambrisko 15348e727371SKashyap D Desai /* 153516dc2814SKashyap D Desai * mrsas_get_best_arm_pd: Determine the best spindle arm 153616dc2814SKashyap D Desai * Inputs: 153716dc2814SKashyap D Desai * sc - HBA instance 153816dc2814SKashyap D Desai * lbInfo - Load balance info 153916dc2814SKashyap D Desai * io_info - IO request info 1540665484d8SDoug Ambrisko * 1541665484d8SDoug Ambrisko * This function determines and returns the best arm by looking at the 1542665484d8SDoug Ambrisko * parameters of the last PD access. 1543665484d8SDoug Ambrisko */ 1544dbcc81dfSKashyap D Desai u_int8_t 1545dbcc81dfSKashyap D Desai mrsas_get_best_arm_pd(struct mrsas_softc *sc, 154616dc2814SKashyap D Desai PLD_LOAD_BALANCE_INFO lbInfo, struct IO_REQUEST_INFO *io_info) 1547665484d8SDoug Ambrisko { 154816dc2814SKashyap D Desai MR_LD_RAID *raid; 154916dc2814SKashyap D Desai MR_DRV_RAID_MAP_ALL *drv_map; 15502a1d3bcdSKashyap D Desai u_int16_t pd1_devHandle; 155116dc2814SKashyap D Desai u_int16_t pend0, pend1, ld; 1552665484d8SDoug Ambrisko u_int64_t diff0, diff1; 155316dc2814SKashyap D Desai u_int8_t bestArm, pd0, pd1, span, arm; 155416dc2814SKashyap D Desai u_int32_t arRef, span_row_size; 155516dc2814SKashyap D Desai 155616dc2814SKashyap D Desai u_int64_t block = io_info->ldStartBlock; 155716dc2814SKashyap D Desai u_int32_t count = io_info->numBlocks; 155816dc2814SKashyap D Desai 155916dc2814SKashyap D Desai span = ((io_info->span_arm & RAID_CTX_SPANARM_SPAN_MASK) 156016dc2814SKashyap D Desai >> RAID_CTX_SPANARM_SPAN_SHIFT); 156116dc2814SKashyap D Desai arm = (io_info->span_arm & RAID_CTX_SPANARM_ARM_MASK); 156216dc2814SKashyap D Desai 156316dc2814SKashyap D Desai drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 156416dc2814SKashyap D Desai ld = MR_TargetIdToLdGet(io_info->ldTgtId, drv_map); 156516dc2814SKashyap D Desai raid = MR_LdRaidGet(ld, drv_map); 156616dc2814SKashyap D Desai span_row_size = sc->UnevenSpanSupport ? 156716dc2814SKashyap D Desai SPAN_ROW_SIZE(drv_map, ld, span) : raid->rowSize; 156816dc2814SKashyap D Desai 156916dc2814SKashyap D Desai arRef = MR_LdSpanArrayGet(ld, span, drv_map); 157016dc2814SKashyap D Desai pd0 = MR_ArPdGet(arRef, arm, drv_map); 157116dc2814SKashyap D Desai pd1 = MR_ArPdGet(arRef, (arm + 1) >= span_row_size ? 157216dc2814SKashyap D Desai (arm + 1 - span_row_size) : arm + 1, drv_map); 1573665484d8SDoug Ambrisko 15742a1d3bcdSKashyap D Desai /* Get PD1 Dev Handle */ 15752a1d3bcdSKashyap D Desai pd1_devHandle = MR_PdDevHandleGet(pd1, drv_map); 15762a1d3bcdSKashyap D Desai if (pd1_devHandle == MR_DEVHANDLE_INVALID) { 15772a1d3bcdSKashyap D Desai bestArm = arm; 15782a1d3bcdSKashyap D Desai } else { 1579665484d8SDoug Ambrisko /* get the pending cmds for the data and mirror arms */ 158016dc2814SKashyap D Desai pend0 = mrsas_atomic_read(&lbInfo->scsi_pending_cmds[pd0]); 158116dc2814SKashyap D Desai pend1 = mrsas_atomic_read(&lbInfo->scsi_pending_cmds[pd1]); 1582665484d8SDoug Ambrisko 1583665484d8SDoug Ambrisko /* Determine the disk whose head is nearer to the req. block */ 158416dc2814SKashyap D Desai diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[pd0]); 158516dc2814SKashyap D Desai diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[pd1]); 158616dc2814SKashyap D Desai bestArm = (diff0 <= diff1 ? arm : arm ^ 1); 1587665484d8SDoug Ambrisko 158816dc2814SKashyap D Desai if ((bestArm == arm && pend0 > pend1 + sc->lb_pending_cmds) || 158916dc2814SKashyap D Desai (bestArm != arm && pend1 > pend0 + sc->lb_pending_cmds)) 1590665484d8SDoug Ambrisko bestArm ^= 1; 1591665484d8SDoug Ambrisko 1592665484d8SDoug Ambrisko /* Update the last accessed block on the correct pd */ 159316dc2814SKashyap D Desai io_info->span_arm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | bestArm; 159416dc2814SKashyap D Desai io_info->pd_after_lb = (bestArm == arm) ? pd0 : pd1; 15952a1d3bcdSKashyap D Desai } 15962a1d3bcdSKashyap D Desai 15972a1d3bcdSKashyap D Desai lbInfo->last_accessed_block[bestArm == arm ? pd0 : pd1] = block + count - 1; 159816dc2814SKashyap D Desai #if SPAN_DEBUG 159916dc2814SKashyap D Desai if (arm != bestArm) 1600ecea5be4SKashyap D Desai printf("AVAGO Debug R1 Load balance occur - span 0x%x arm 0x%x bestArm 0x%x " 160116dc2814SKashyap D Desai "io_info->span_arm 0x%x\n", 160216dc2814SKashyap D Desai span, arm, bestArm, io_info->span_arm); 160316dc2814SKashyap D Desai #endif 1604665484d8SDoug Ambrisko 160516dc2814SKashyap D Desai return io_info->pd_after_lb; 1606665484d8SDoug Ambrisko } 1607665484d8SDoug Ambrisko 16088e727371SKashyap D Desai /* 16098e727371SKashyap D Desai * mrsas_get_updated_dev_handle: Get the update dev handle 161016dc2814SKashyap D Desai * Inputs: 161116dc2814SKashyap D Desai * sc - Adapter instance soft state 161216dc2814SKashyap D Desai * lbInfo - Load balance info 161316dc2814SKashyap D Desai * io_info - io_info pointer 1614665484d8SDoug Ambrisko * 1615665484d8SDoug Ambrisko * This function determines and returns the updated dev handle. 1616665484d8SDoug Ambrisko */ 1617dbcc81dfSKashyap D Desai u_int16_t 1618dbcc81dfSKashyap D Desai mrsas_get_updated_dev_handle(struct mrsas_softc *sc, 161916dc2814SKashyap D Desai PLD_LOAD_BALANCE_INFO lbInfo, struct IO_REQUEST_INFO *io_info) 1620665484d8SDoug Ambrisko { 162116dc2814SKashyap D Desai u_int8_t arm_pd; 1622665484d8SDoug Ambrisko u_int16_t devHandle; 162316dc2814SKashyap D Desai MR_DRV_RAID_MAP_ALL *drv_map; 1624665484d8SDoug Ambrisko 162516dc2814SKashyap D Desai drv_map = sc->ld_drv_map[(sc->map_id & 1)]; 1626665484d8SDoug Ambrisko 1627665484d8SDoug Ambrisko /* get best new arm */ 162816dc2814SKashyap D Desai arm_pd = mrsas_get_best_arm_pd(sc, lbInfo, io_info); 162916dc2814SKashyap D Desai devHandle = MR_PdDevHandleGet(arm_pd, drv_map); 16303d273176SKashyap D Desai io_info->pdInterface = MR_PdInterfaceTypeGet(arm_pd, drv_map); 163116dc2814SKashyap D Desai mrsas_atomic_inc(&lbInfo->scsi_pending_cmds[arm_pd]); 1632665484d8SDoug Ambrisko 1633665484d8SDoug Ambrisko return devHandle; 1634665484d8SDoug Ambrisko } 1635665484d8SDoug Ambrisko 16368e727371SKashyap D Desai /* 16378e727371SKashyap D Desai * MR_GetPhyParams: Calculates arm, span, and block 16388e727371SKashyap D Desai * Inputs: Adapter soft state 1639665484d8SDoug Ambrisko * Logical drive number (LD) 1640665484d8SDoug Ambrisko * Stripe number(stripRow) 1641665484d8SDoug Ambrisko * Reference in stripe (stripRef) 1642665484d8SDoug Ambrisko * 16438e727371SKashyap D Desai * Outputs: Absolute Block number in the physical disk 16448e727371SKashyap D Desai * 16458e727371SKashyap D Desai * This routine calculates the arm, span and block for the specified stripe and 16468e727371SKashyap D Desai * reference in stripe. 1647665484d8SDoug Ambrisko */ 16488e727371SKashyap D Desai u_int8_t 16498e727371SKashyap D Desai MR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld, 1650665484d8SDoug Ambrisko u_int64_t stripRow, 1651665484d8SDoug Ambrisko u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, 16524799d485SKashyap D Desai RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map) 1653665484d8SDoug Ambrisko { 1654665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 16552a1d3bcdSKashyap D Desai u_int32_t pd, arRef, r1_alt_pd; 1656665484d8SDoug Ambrisko u_int8_t physArm, span; 1657665484d8SDoug Ambrisko u_int64_t row; 1658665484d8SDoug Ambrisko u_int8_t retval = TRUE; 1659665484d8SDoug Ambrisko int error_code = 0; 1660665484d8SDoug Ambrisko u_int64_t *pdBlock = &io_info->pdBlock; 1661665484d8SDoug Ambrisko u_int16_t *pDevHandle = &io_info->devHandle; 16623d273176SKashyap D Desai u_int8_t *pPdInterface = &io_info->pdInterface; 1663665484d8SDoug Ambrisko u_int32_t rowMod, armQ, arm, logArm; 1664665484d8SDoug Ambrisko 1665665484d8SDoug Ambrisko row = mega_div64_32(stripRow, raid->rowDataSize); 1666665484d8SDoug Ambrisko 1667665484d8SDoug Ambrisko if (raid->level == 6) { 16688e727371SKashyap D Desai /* logical arm within row */ 16698e727371SKashyap D Desai logArm = mega_mod64(stripRow, raid->rowDataSize); 1670665484d8SDoug Ambrisko if (raid->rowSize == 0) 1671665484d8SDoug Ambrisko return FALSE; 16728e727371SKashyap D Desai rowMod = mega_mod64(row, raid->rowSize); /* get logical row mod */ 16738e727371SKashyap D Desai armQ = raid->rowSize - 1 - rowMod; /* index of Q drive */ 16748e727371SKashyap D Desai arm = armQ + 1 + logArm;/* data always logically follows Q */ 16758e727371SKashyap D Desai if (arm >= raid->rowSize) /* handle wrap condition */ 1676665484d8SDoug Ambrisko arm -= raid->rowSize; 1677665484d8SDoug Ambrisko physArm = (u_int8_t)arm; 16788e727371SKashyap D Desai } else { 1679665484d8SDoug Ambrisko if (raid->modFactor == 0) 1680665484d8SDoug Ambrisko return FALSE; 1681665484d8SDoug Ambrisko physArm = MR_LdDataArmGet(ld, mega_mod64(stripRow, raid->modFactor), map); 1682665484d8SDoug Ambrisko } 1683665484d8SDoug Ambrisko 1684665484d8SDoug Ambrisko if (raid->spanDepth == 1) { 1685665484d8SDoug Ambrisko span = 0; 1686665484d8SDoug Ambrisko *pdBlock = row << raid->stripeShift; 16878e727371SKashyap D Desai } else { 1688665484d8SDoug Ambrisko span = (u_int8_t)MR_GetSpanBlock(ld, row, pdBlock, map, &error_code); 1689665484d8SDoug Ambrisko if (error_code == 1) 1690665484d8SDoug Ambrisko return FALSE; 1691665484d8SDoug Ambrisko } 1692665484d8SDoug Ambrisko 1693665484d8SDoug Ambrisko /* Get the array on which this span is present */ 1694665484d8SDoug Ambrisko arRef = MR_LdSpanArrayGet(ld, span, map); 1695665484d8SDoug Ambrisko 16968e727371SKashyap D Desai pd = MR_ArPdGet(arRef, physArm, map); /* Get the Pd. */ 1697665484d8SDoug Ambrisko 16982a1d3bcdSKashyap D Desai if (pd != MR_PD_INVALID) { 16998e727371SKashyap D Desai /* Get dev handle from Pd */ 17008e727371SKashyap D Desai *pDevHandle = MR_PdDevHandleGet(pd, map); 17013d273176SKashyap D Desai *pPdInterface = MR_PdInterfaceTypeGet(pd, map); 17022a1d3bcdSKashyap D Desai /* get second pd also for raid 1/10 fast path writes */ 17032a1d3bcdSKashyap D Desai if ((raid->level == 1) && !io_info->isRead) { 17042a1d3bcdSKashyap D Desai r1_alt_pd = MR_ArPdGet(arRef, physArm + 1, map); 17052a1d3bcdSKashyap D Desai if (r1_alt_pd != MR_PD_INVALID) 17062a1d3bcdSKashyap D Desai io_info->r1_alt_dev_handle = MR_PdDevHandleGet(r1_alt_pd, map); 17072a1d3bcdSKashyap D Desai } 17082a1d3bcdSKashyap D Desai } else { 1709*e34a057cSAlfredo Dal'Ava Junior *pDevHandle = htole16(MR_DEVHANDLE_INVALID); /* set dev handle as invalid. */ 17107aade8bfSKashyap D Desai if ((raid->level >= 5) && ((sc->device_id == MRSAS_TBOLT) || 17117aade8bfSKashyap D Desai (sc->mrsas_gen3_ctrl && 1712665484d8SDoug Ambrisko raid->regTypeReqOnRead != REGION_TYPE_UNUSED))) 1713665484d8SDoug Ambrisko pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; 1714665484d8SDoug Ambrisko else if (raid->level == 1) { 17158e727371SKashyap D Desai /* Get Alternate Pd. */ 17168e727371SKashyap D Desai pd = MR_ArPdGet(arRef, physArm + 1, map); 17173d273176SKashyap D Desai if (pd != MR_PD_INVALID) { 17188e727371SKashyap D Desai /* Get dev handle from Pd. */ 17198e727371SKashyap D Desai *pDevHandle = MR_PdDevHandleGet(pd, map); 17203d273176SKashyap D Desai *pPdInterface = MR_PdInterfaceTypeGet(pd, map); 17213d273176SKashyap D Desai } 1722665484d8SDoug Ambrisko } 1723665484d8SDoug Ambrisko } 1724665484d8SDoug Ambrisko 1725*e34a057cSAlfredo Dal'Ava Junior *pdBlock += stripRef + le64toh(MR_LdSpanPtrGet(ld, span, map)->startBlk); 17262909aab4SKashyap D Desai if (sc->is_ventura || sc->is_aero) { 1727503c4f8dSKashyap D Desai ((RAID_CONTEXT_G35 *) pRAID_Context)->spanArm = 1728503c4f8dSKashyap D Desai (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; 1729503c4f8dSKashyap D Desai io_info->span_arm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; 1730503c4f8dSKashyap D Desai } else { 1731665484d8SDoug Ambrisko pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; 173216dc2814SKashyap D Desai io_info->span_arm = pRAID_Context->spanArm; 1733503c4f8dSKashyap D Desai } 1734665484d8SDoug Ambrisko return retval; 1735665484d8SDoug Ambrisko } 1736665484d8SDoug Ambrisko 17378e727371SKashyap D Desai /* 17388e727371SKashyap D Desai * MR_GetSpanBlock: Calculates span block 1739665484d8SDoug Ambrisko * Inputs: LD 17408e727371SKashyap D Desai * row PD 17418e727371SKashyap D Desai * span block 1742665484d8SDoug Ambrisko * RAID map pointer 17438e727371SKashyap D Desai * 17448e727371SKashyap D Desai * Outputs: Span number Error code 1745665484d8SDoug Ambrisko * 1746665484d8SDoug Ambrisko * This routine calculates the span from the span block info. 1747665484d8SDoug Ambrisko */ 17488e727371SKashyap D Desai u_int32_t 17498e727371SKashyap D Desai MR_GetSpanBlock(u_int32_t ld, u_int64_t row, u_int64_t *span_blk, 17504799d485SKashyap D Desai MR_DRV_RAID_MAP_ALL * map, int *div_error) 1751665484d8SDoug Ambrisko { 1752665484d8SDoug Ambrisko MR_SPAN_BLOCK_INFO *pSpanBlock = MR_LdSpanInfoGet(ld, map); 1753665484d8SDoug Ambrisko MR_QUAD_ELEMENT *quad; 1754665484d8SDoug Ambrisko MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 1755665484d8SDoug Ambrisko u_int32_t span, j; 1756665484d8SDoug Ambrisko u_int64_t blk, debugBlk; 1757665484d8SDoug Ambrisko 1758665484d8SDoug Ambrisko for (span = 0; span < raid->spanDepth; span++, pSpanBlock++) { 1759665484d8SDoug Ambrisko for (j = 0; j < pSpanBlock->block_span_info.noElements; j++) { 1760665484d8SDoug Ambrisko quad = &pSpanBlock->block_span_info.quad[j]; 1761665484d8SDoug Ambrisko if (quad->diff == 0) { 1762665484d8SDoug Ambrisko *div_error = 1; 1763665484d8SDoug Ambrisko return span; 1764665484d8SDoug Ambrisko } 1765665484d8SDoug Ambrisko if (quad->logStart <= row && row <= quad->logEnd && 1766665484d8SDoug Ambrisko (mega_mod64(row - quad->logStart, quad->diff)) == 0) { 1767665484d8SDoug Ambrisko if (span_blk != NULL) { 1768665484d8SDoug Ambrisko blk = mega_div64_32((row - quad->logStart), quad->diff); 1769665484d8SDoug Ambrisko debugBlk = blk; 1770665484d8SDoug Ambrisko blk = (blk + quad->offsetInSpan) << raid->stripeShift; 1771665484d8SDoug Ambrisko *span_blk = blk; 1772665484d8SDoug Ambrisko } 1773665484d8SDoug Ambrisko return span; 1774665484d8SDoug Ambrisko } 1775665484d8SDoug Ambrisko } 1776665484d8SDoug Ambrisko } 1777665484d8SDoug Ambrisko return span; 1778665484d8SDoug Ambrisko } 1779