1*c12c399aSSascha Wildner /*- 2*c12c399aSSascha Wildner * Copyright (c) 2011 LSI Corp. 3*c12c399aSSascha Wildner * All rights reserved. 4*c12c399aSSascha Wildner * 5*c12c399aSSascha Wildner * Redistribution and use in source and binary forms, with or without 6*c12c399aSSascha Wildner * modification, are permitted provided that the following conditions 7*c12c399aSSascha Wildner * are met: 8*c12c399aSSascha Wildner * 1. Redistributions of source code must retain the above copyright 9*c12c399aSSascha Wildner * notice, this list of conditions and the following disclaimer. 10*c12c399aSSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright 11*c12c399aSSascha Wildner * notice, this list of conditions and the following disclaimer in the 12*c12c399aSSascha Wildner * documentation and/or other materials provided with the distribution. 13*c12c399aSSascha Wildner * 14*c12c399aSSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15*c12c399aSSascha Wildner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*c12c399aSSascha Wildner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*c12c399aSSascha Wildner * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18*c12c399aSSascha Wildner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*c12c399aSSascha Wildner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*c12c399aSSascha Wildner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*c12c399aSSascha Wildner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*c12c399aSSascha Wildner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*c12c399aSSascha Wildner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*c12c399aSSascha Wildner * SUCH DAMAGE. 25*c12c399aSSascha Wildner * 26*c12c399aSSascha Wildner * LSI MPT-Fusion Host Adapter FreeBSD 27*c12c399aSSascha Wildner * 28*c12c399aSSascha Wildner * $FreeBSD: src/sys/dev/mps/mps_mapping.c,v 1.1 2012/01/26 18:17:21 ken Exp $ 29*c12c399aSSascha Wildner */ 30*c12c399aSSascha Wildner 31*c12c399aSSascha Wildner /* TODO Move headers to mpsvar */ 32*c12c399aSSascha Wildner #include <sys/types.h> 33*c12c399aSSascha Wildner #include <sys/param.h> 34*c12c399aSSascha Wildner #include <sys/lock.h> 35*c12c399aSSascha Wildner #include <sys/mutex.h> 36*c12c399aSSascha Wildner #include <sys/systm.h> 37*c12c399aSSascha Wildner #include <sys/kernel.h> 38*c12c399aSSascha Wildner #include <sys/malloc.h> 39*c12c399aSSascha Wildner #include <sys/kthread.h> 40*c12c399aSSascha Wildner #include <sys/taskqueue.h> 41*c12c399aSSascha Wildner #include <sys/bus.h> 42*c12c399aSSascha Wildner #include <sys/endian.h> 43*c12c399aSSascha Wildner #include <sys/sysctl.h> 44*c12c399aSSascha Wildner #include <sys/eventhandler.h> 45*c12c399aSSascha Wildner #include <sys/uio.h> 46*c12c399aSSascha Wildner #include <dev/raid/mps/mpi/mpi2_type.h> 47*c12c399aSSascha Wildner #include <dev/raid/mps/mpi/mpi2.h> 48*c12c399aSSascha Wildner #include <dev/raid/mps/mpi/mpi2_ioc.h> 49*c12c399aSSascha Wildner #include <dev/raid/mps/mpi/mpi2_sas.h> 50*c12c399aSSascha Wildner #include <dev/raid/mps/mpi/mpi2_cnfg.h> 51*c12c399aSSascha Wildner #include <dev/raid/mps/mpi/mpi2_init.h> 52*c12c399aSSascha Wildner #include <dev/raid/mps/mpi/mpi2_tool.h> 53*c12c399aSSascha Wildner #include <dev/raid/mps/mps_ioctl.h> 54*c12c399aSSascha Wildner #include <dev/raid/mps/mpsvar.h> 55*c12c399aSSascha Wildner #include <dev/raid/mps/mps_mapping.h> 56*c12c399aSSascha Wildner 57*c12c399aSSascha Wildner /** 58*c12c399aSSascha Wildner * _mapping_clear_entry - Clear a particular mapping entry. 59*c12c399aSSascha Wildner * @map_entry: map table entry 60*c12c399aSSascha Wildner * 61*c12c399aSSascha Wildner * Returns nothing. 62*c12c399aSSascha Wildner */ 63*c12c399aSSascha Wildner static inline void 64*c12c399aSSascha Wildner _mapping_clear_map_entry(struct dev_mapping_table *map_entry) 65*c12c399aSSascha Wildner { 66*c12c399aSSascha Wildner map_entry->physical_id = 0; 67*c12c399aSSascha Wildner map_entry->device_info = 0; 68*c12c399aSSascha Wildner map_entry->phy_bits = 0; 69*c12c399aSSascha Wildner map_entry->dpm_entry_num = MPS_DPM_BAD_IDX; 70*c12c399aSSascha Wildner map_entry->dev_handle = 0; 71*c12c399aSSascha Wildner map_entry->channel = -1; 72*c12c399aSSascha Wildner map_entry->id = -1; 73*c12c399aSSascha Wildner map_entry->missing_count = 0; 74*c12c399aSSascha Wildner map_entry->init_complete = 0; 75*c12c399aSSascha Wildner map_entry->TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR; 76*c12c399aSSascha Wildner } 77*c12c399aSSascha Wildner 78*c12c399aSSascha Wildner /** 79*c12c399aSSascha Wildner * _mapping_clear_enc_entry - Clear a particular enclosure table entry. 80*c12c399aSSascha Wildner * @enc_entry: enclosure table entry 81*c12c399aSSascha Wildner * 82*c12c399aSSascha Wildner * Returns nothing. 83*c12c399aSSascha Wildner */ 84*c12c399aSSascha Wildner static inline void 85*c12c399aSSascha Wildner _mapping_clear_enc_entry(struct enc_mapping_table *enc_entry) 86*c12c399aSSascha Wildner { 87*c12c399aSSascha Wildner enc_entry->enclosure_id = 0; 88*c12c399aSSascha Wildner enc_entry->start_index = MPS_MAPTABLE_BAD_IDX; 89*c12c399aSSascha Wildner enc_entry->phy_bits = 0; 90*c12c399aSSascha Wildner enc_entry->dpm_entry_num = MPS_DPM_BAD_IDX; 91*c12c399aSSascha Wildner enc_entry->enc_handle = 0; 92*c12c399aSSascha Wildner enc_entry->num_slots = 0; 93*c12c399aSSascha Wildner enc_entry->start_slot = 0; 94*c12c399aSSascha Wildner enc_entry->missing_count = 0; 95*c12c399aSSascha Wildner enc_entry->removal_flag = 0; 96*c12c399aSSascha Wildner enc_entry->skip_search = 0; 97*c12c399aSSascha Wildner enc_entry->init_complete = 0; 98*c12c399aSSascha Wildner } 99*c12c399aSSascha Wildner 100*c12c399aSSascha Wildner /** 101*c12c399aSSascha Wildner * _mapping_commit_enc_entry - write a particular enc entry in DPM page0. 102*c12c399aSSascha Wildner * @sc: per adapter object 103*c12c399aSSascha Wildner * @enc_entry: enclosure table entry 104*c12c399aSSascha Wildner * 105*c12c399aSSascha Wildner * Returns 0 for success, non-zero for failure. 106*c12c399aSSascha Wildner */ 107*c12c399aSSascha Wildner static int 108*c12c399aSSascha Wildner _mapping_commit_enc_entry(struct mps_softc *sc, 109*c12c399aSSascha Wildner struct enc_mapping_table *et_entry) 110*c12c399aSSascha Wildner { 111*c12c399aSSascha Wildner Mpi2DriverMap0Entry_t *dpm_entry; 112*c12c399aSSascha Wildner struct dev_mapping_table *mt_entry; 113*c12c399aSSascha Wildner Mpi2ConfigReply_t mpi_reply; 114*c12c399aSSascha Wildner Mpi2DriverMappingPage0_t config_page; 115*c12c399aSSascha Wildner 116*c12c399aSSascha Wildner if (!sc->is_dpm_enable) 117*c12c399aSSascha Wildner return 0; 118*c12c399aSSascha Wildner 119*c12c399aSSascha Wildner memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t)); 120*c12c399aSSascha Wildner memcpy(&config_page.Header, (u8 *) sc->dpm_pg0, 121*c12c399aSSascha Wildner sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 122*c12c399aSSascha Wildner dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 + 123*c12c399aSSascha Wildner sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 124*c12c399aSSascha Wildner dpm_entry += et_entry->dpm_entry_num; 125*c12c399aSSascha Wildner dpm_entry->PhysicalIdentifier.Low = 126*c12c399aSSascha Wildner ( 0xFFFFFFFF & et_entry->enclosure_id); 127*c12c399aSSascha Wildner dpm_entry->PhysicalIdentifier.High = 128*c12c399aSSascha Wildner ( et_entry->enclosure_id >> 32); 129*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[et_entry->start_index]; 130*c12c399aSSascha Wildner dpm_entry->DeviceIndex = htole16(mt_entry->id); 131*c12c399aSSascha Wildner dpm_entry->MappingInformation = et_entry->num_slots; 132*c12c399aSSascha Wildner dpm_entry->MappingInformation <<= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT; 133*c12c399aSSascha Wildner dpm_entry->MappingInformation |= et_entry->missing_count; 134*c12c399aSSascha Wildner dpm_entry->MappingInformation = htole16(dpm_entry->MappingInformation); 135*c12c399aSSascha Wildner dpm_entry->PhysicalBitsMapping = htole32(et_entry->phy_bits); 136*c12c399aSSascha Wildner dpm_entry->Reserved1 = 0; 137*c12c399aSSascha Wildner 138*c12c399aSSascha Wildner memcpy(&config_page.Entry, (u8 *)dpm_entry, 139*c12c399aSSascha Wildner sizeof(Mpi2DriverMap0Entry_t)); 140*c12c399aSSascha Wildner if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page, 141*c12c399aSSascha Wildner et_entry->dpm_entry_num)) { 142*c12c399aSSascha Wildner kprintf("%s: write of dpm entry %d for enclosure failed\n", 143*c12c399aSSascha Wildner __func__, et_entry->dpm_entry_num); 144*c12c399aSSascha Wildner dpm_entry->MappingInformation = le16toh(dpm_entry-> 145*c12c399aSSascha Wildner MappingInformation); 146*c12c399aSSascha Wildner dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex); 147*c12c399aSSascha Wildner dpm_entry->PhysicalBitsMapping = 148*c12c399aSSascha Wildner le32toh(dpm_entry->PhysicalBitsMapping); 149*c12c399aSSascha Wildner return -1; 150*c12c399aSSascha Wildner } 151*c12c399aSSascha Wildner dpm_entry->MappingInformation = le16toh(dpm_entry-> 152*c12c399aSSascha Wildner MappingInformation); 153*c12c399aSSascha Wildner dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex); 154*c12c399aSSascha Wildner dpm_entry->PhysicalBitsMapping = 155*c12c399aSSascha Wildner le32toh(dpm_entry->PhysicalBitsMapping); 156*c12c399aSSascha Wildner return 0; 157*c12c399aSSascha Wildner } 158*c12c399aSSascha Wildner 159*c12c399aSSascha Wildner /** 160*c12c399aSSascha Wildner * _mapping_commit_map_entry - write a particular map table entry in DPM page0. 161*c12c399aSSascha Wildner * @sc: per adapter object 162*c12c399aSSascha Wildner * @enc_entry: enclosure table entry 163*c12c399aSSascha Wildner * 164*c12c399aSSascha Wildner * Returns 0 for success, non-zero for failure. 165*c12c399aSSascha Wildner */ 166*c12c399aSSascha Wildner 167*c12c399aSSascha Wildner static int 168*c12c399aSSascha Wildner _mapping_commit_map_entry(struct mps_softc *sc, 169*c12c399aSSascha Wildner struct dev_mapping_table *mt_entry) 170*c12c399aSSascha Wildner { 171*c12c399aSSascha Wildner Mpi2DriverMap0Entry_t *dpm_entry; 172*c12c399aSSascha Wildner Mpi2ConfigReply_t mpi_reply; 173*c12c399aSSascha Wildner Mpi2DriverMappingPage0_t config_page; 174*c12c399aSSascha Wildner 175*c12c399aSSascha Wildner if (!sc->is_dpm_enable) 176*c12c399aSSascha Wildner return 0; 177*c12c399aSSascha Wildner 178*c12c399aSSascha Wildner memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t)); 179*c12c399aSSascha Wildner memcpy(&config_page.Header, (u8 *)sc->dpm_pg0, 180*c12c399aSSascha Wildner sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 181*c12c399aSSascha Wildner dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *) sc->dpm_pg0 + 182*c12c399aSSascha Wildner sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 183*c12c399aSSascha Wildner dpm_entry = dpm_entry + mt_entry->dpm_entry_num; 184*c12c399aSSascha Wildner dpm_entry->PhysicalIdentifier.Low = (0xFFFFFFFF & 185*c12c399aSSascha Wildner mt_entry->physical_id); 186*c12c399aSSascha Wildner dpm_entry->PhysicalIdentifier.High = (mt_entry->physical_id >> 32); 187*c12c399aSSascha Wildner dpm_entry->DeviceIndex = htole16(mt_entry->id); 188*c12c399aSSascha Wildner dpm_entry->MappingInformation = htole16(mt_entry->missing_count); 189*c12c399aSSascha Wildner dpm_entry->PhysicalBitsMapping = 0; 190*c12c399aSSascha Wildner dpm_entry->Reserved1 = 0; 191*c12c399aSSascha Wildner dpm_entry->MappingInformation = htole16(dpm_entry->MappingInformation); 192*c12c399aSSascha Wildner memcpy(&config_page.Entry, (u8 *)dpm_entry, 193*c12c399aSSascha Wildner sizeof(Mpi2DriverMap0Entry_t)); 194*c12c399aSSascha Wildner if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page, 195*c12c399aSSascha Wildner mt_entry->dpm_entry_num)) { 196*c12c399aSSascha Wildner kprintf("%s: write of dpm entry %d for device failed\n", 197*c12c399aSSascha Wildner __func__, mt_entry->dpm_entry_num); 198*c12c399aSSascha Wildner dpm_entry->MappingInformation = le16toh(dpm_entry-> 199*c12c399aSSascha Wildner MappingInformation); 200*c12c399aSSascha Wildner dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex); 201*c12c399aSSascha Wildner return -1; 202*c12c399aSSascha Wildner } 203*c12c399aSSascha Wildner 204*c12c399aSSascha Wildner dpm_entry->MappingInformation = le16toh(dpm_entry->MappingInformation); 205*c12c399aSSascha Wildner dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex); 206*c12c399aSSascha Wildner return 0; 207*c12c399aSSascha Wildner } 208*c12c399aSSascha Wildner 209*c12c399aSSascha Wildner /** 210*c12c399aSSascha Wildner * _mapping_get_ir_maprange - get start and end index for IR map range. 211*c12c399aSSascha Wildner * @sc: per adapter object 212*c12c399aSSascha Wildner * @start_idx: place holder for start index 213*c12c399aSSascha Wildner * @end_idx: place holder for end index 214*c12c399aSSascha Wildner * 215*c12c399aSSascha Wildner * The IR volumes can be mapped either at start or end of the mapping table 216*c12c399aSSascha Wildner * this function gets the detail of where IR volume mapping starts and ends 217*c12c399aSSascha Wildner * in the device mapping table 218*c12c399aSSascha Wildner * 219*c12c399aSSascha Wildner * Returns nothing. 220*c12c399aSSascha Wildner */ 221*c12c399aSSascha Wildner static void 222*c12c399aSSascha Wildner _mapping_get_ir_maprange(struct mps_softc *sc, u32 *start_idx, u32 *end_idx) 223*c12c399aSSascha Wildner { 224*c12c399aSSascha Wildner u16 volume_mapping_flags; 225*c12c399aSSascha Wildner u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 226*c12c399aSSascha Wildner 227*c12c399aSSascha Wildner volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) & 228*c12c399aSSascha Wildner MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; 229*c12c399aSSascha Wildner if (volume_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) { 230*c12c399aSSascha Wildner *start_idx = 0; 231*c12c399aSSascha Wildner if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0) 232*c12c399aSSascha Wildner *start_idx = 1; 233*c12c399aSSascha Wildner } else 234*c12c399aSSascha Wildner *start_idx = sc->max_devices - sc->max_volumes; 235*c12c399aSSascha Wildner *end_idx = *start_idx + sc->max_volumes - 1; 236*c12c399aSSascha Wildner } 237*c12c399aSSascha Wildner 238*c12c399aSSascha Wildner /** 239*c12c399aSSascha Wildner * _mapping_get_enc_idx_from_id - get enclosure index from enclosure ID 240*c12c399aSSascha Wildner * @sc: per adapter object 241*c12c399aSSascha Wildner * @enc_id: enclosure logical identifier 242*c12c399aSSascha Wildner * 243*c12c399aSSascha Wildner * Returns the index of enclosure entry on success or bad index. 244*c12c399aSSascha Wildner */ 245*c12c399aSSascha Wildner static u8 246*c12c399aSSascha Wildner _mapping_get_enc_idx_from_id(struct mps_softc *sc, u64 enc_id, 247*c12c399aSSascha Wildner u64 phy_bits) 248*c12c399aSSascha Wildner { 249*c12c399aSSascha Wildner struct enc_mapping_table *et_entry; 250*c12c399aSSascha Wildner u8 enc_idx = 0; 251*c12c399aSSascha Wildner 252*c12c399aSSascha Wildner for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) { 253*c12c399aSSascha Wildner et_entry = &sc->enclosure_table[enc_idx]; 254*c12c399aSSascha Wildner if ((et_entry->enclosure_id == le64toh(enc_id)) && 255*c12c399aSSascha Wildner (!et_entry->phy_bits || (et_entry->phy_bits & 256*c12c399aSSascha Wildner le32toh(phy_bits)))) 257*c12c399aSSascha Wildner return enc_idx; 258*c12c399aSSascha Wildner } 259*c12c399aSSascha Wildner return MPS_ENCTABLE_BAD_IDX; 260*c12c399aSSascha Wildner } 261*c12c399aSSascha Wildner 262*c12c399aSSascha Wildner /** 263*c12c399aSSascha Wildner * _mapping_get_enc_idx_from_handle - get enclosure index from handle 264*c12c399aSSascha Wildner * @sc: per adapter object 265*c12c399aSSascha Wildner * @enc_id: enclosure handle 266*c12c399aSSascha Wildner * 267*c12c399aSSascha Wildner * Returns the index of enclosure entry on success or bad index. 268*c12c399aSSascha Wildner */ 269*c12c399aSSascha Wildner static u8 270*c12c399aSSascha Wildner _mapping_get_enc_idx_from_handle(struct mps_softc *sc, u16 handle) 271*c12c399aSSascha Wildner { 272*c12c399aSSascha Wildner struct enc_mapping_table *et_entry; 273*c12c399aSSascha Wildner u8 enc_idx = 0; 274*c12c399aSSascha Wildner 275*c12c399aSSascha Wildner for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) { 276*c12c399aSSascha Wildner et_entry = &sc->enclosure_table[enc_idx]; 277*c12c399aSSascha Wildner if (et_entry->missing_count) 278*c12c399aSSascha Wildner continue; 279*c12c399aSSascha Wildner if (et_entry->enc_handle == handle) 280*c12c399aSSascha Wildner return enc_idx; 281*c12c399aSSascha Wildner } 282*c12c399aSSascha Wildner return MPS_ENCTABLE_BAD_IDX; 283*c12c399aSSascha Wildner } 284*c12c399aSSascha Wildner 285*c12c399aSSascha Wildner /** 286*c12c399aSSascha Wildner * _mapping_get_high_missing_et_idx - get missing enclosure index 287*c12c399aSSascha Wildner * @sc: per adapter object 288*c12c399aSSascha Wildner * 289*c12c399aSSascha Wildner * Search through the enclosure table and identifies the enclosure entry 290*c12c399aSSascha Wildner * with high missing count and returns it's index 291*c12c399aSSascha Wildner * 292*c12c399aSSascha Wildner * Returns the index of enclosure entry on success or bad index. 293*c12c399aSSascha Wildner */ 294*c12c399aSSascha Wildner static u8 295*c12c399aSSascha Wildner _mapping_get_high_missing_et_idx(struct mps_softc *sc) 296*c12c399aSSascha Wildner { 297*c12c399aSSascha Wildner struct enc_mapping_table *et_entry; 298*c12c399aSSascha Wildner u8 high_missing_count = 0; 299*c12c399aSSascha Wildner u8 enc_idx, high_idx = MPS_ENCTABLE_BAD_IDX; 300*c12c399aSSascha Wildner 301*c12c399aSSascha Wildner for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) { 302*c12c399aSSascha Wildner et_entry = &sc->enclosure_table[enc_idx]; 303*c12c399aSSascha Wildner if ((et_entry->missing_count > high_missing_count) && 304*c12c399aSSascha Wildner !et_entry->skip_search) { 305*c12c399aSSascha Wildner high_missing_count = et_entry->missing_count; 306*c12c399aSSascha Wildner high_idx = enc_idx; 307*c12c399aSSascha Wildner } 308*c12c399aSSascha Wildner } 309*c12c399aSSascha Wildner return high_idx; 310*c12c399aSSascha Wildner } 311*c12c399aSSascha Wildner 312*c12c399aSSascha Wildner /** 313*c12c399aSSascha Wildner * _mapping_get_high_missing_mt_idx - get missing map table index 314*c12c399aSSascha Wildner * @sc: per adapter object 315*c12c399aSSascha Wildner * 316*c12c399aSSascha Wildner * Search through the map table and identifies the device entry 317*c12c399aSSascha Wildner * with high missing count and returns it's index 318*c12c399aSSascha Wildner * 319*c12c399aSSascha Wildner * Returns the index of map table entry on success or bad index. 320*c12c399aSSascha Wildner */ 321*c12c399aSSascha Wildner static u32 322*c12c399aSSascha Wildner _mapping_get_high_missing_mt_idx(struct mps_softc *sc) 323*c12c399aSSascha Wildner { 324*c12c399aSSascha Wildner u32 map_idx, high_idx = MPS_ENCTABLE_BAD_IDX; 325*c12c399aSSascha Wildner u8 high_missing_count = 0; 326*c12c399aSSascha Wildner u32 start_idx, end_idx, start_idx_ir, end_idx_ir; 327*c12c399aSSascha Wildner struct dev_mapping_table *mt_entry; 328*c12c399aSSascha Wildner u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 329*c12c399aSSascha Wildner 330*c12c399aSSascha Wildner start_idx = 0; 331*c12c399aSSascha Wildner end_idx = sc->max_devices; 332*c12c399aSSascha Wildner if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0) 333*c12c399aSSascha Wildner start_idx = 1; 334*c12c399aSSascha Wildner if (sc->ir_firmware) 335*c12c399aSSascha Wildner _mapping_get_ir_maprange(sc, &start_idx_ir, &end_idx_ir); 336*c12c399aSSascha Wildner if (start_idx == start_idx_ir) 337*c12c399aSSascha Wildner start_idx = end_idx_ir + 1; 338*c12c399aSSascha Wildner else 339*c12c399aSSascha Wildner end_idx = start_idx_ir; 340*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[start_idx]; 341*c12c399aSSascha Wildner for (map_idx = start_idx; map_idx < end_idx; map_idx++, mt_entry++) { 342*c12c399aSSascha Wildner if (mt_entry->missing_count > high_missing_count) { 343*c12c399aSSascha Wildner high_missing_count = mt_entry->missing_count; 344*c12c399aSSascha Wildner high_idx = map_idx; 345*c12c399aSSascha Wildner } 346*c12c399aSSascha Wildner } 347*c12c399aSSascha Wildner return high_idx; 348*c12c399aSSascha Wildner } 349*c12c399aSSascha Wildner 350*c12c399aSSascha Wildner /** 351*c12c399aSSascha Wildner * _mapping_get_ir_mt_idx_from_wwid - get map table index from volume WWID 352*c12c399aSSascha Wildner * @sc: per adapter object 353*c12c399aSSascha Wildner * @wwid: world wide unique ID of the volume 354*c12c399aSSascha Wildner * 355*c12c399aSSascha Wildner * Returns the index of map table entry on success or bad index. 356*c12c399aSSascha Wildner */ 357*c12c399aSSascha Wildner static u32 358*c12c399aSSascha Wildner _mapping_get_ir_mt_idx_from_wwid(struct mps_softc *sc, u64 wwid) 359*c12c399aSSascha Wildner { 360*c12c399aSSascha Wildner u32 start_idx, end_idx, map_idx; 361*c12c399aSSascha Wildner struct dev_mapping_table *mt_entry; 362*c12c399aSSascha Wildner 363*c12c399aSSascha Wildner _mapping_get_ir_maprange(sc, &start_idx, &end_idx); 364*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[start_idx]; 365*c12c399aSSascha Wildner for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) 366*c12c399aSSascha Wildner if (mt_entry->physical_id == wwid) 367*c12c399aSSascha Wildner return map_idx; 368*c12c399aSSascha Wildner 369*c12c399aSSascha Wildner return MPS_MAPTABLE_BAD_IDX; 370*c12c399aSSascha Wildner } 371*c12c399aSSascha Wildner 372*c12c399aSSascha Wildner /** 373*c12c399aSSascha Wildner * _mapping_get_mt_idx_from_id - get map table index from a device ID 374*c12c399aSSascha Wildner * @sc: per adapter object 375*c12c399aSSascha Wildner * @dev_id: device identifer (SAS Address) 376*c12c399aSSascha Wildner * 377*c12c399aSSascha Wildner * Returns the index of map table entry on success or bad index. 378*c12c399aSSascha Wildner */ 379*c12c399aSSascha Wildner static u32 380*c12c399aSSascha Wildner _mapping_get_mt_idx_from_id(struct mps_softc *sc, u64 dev_id) 381*c12c399aSSascha Wildner { 382*c12c399aSSascha Wildner u32 map_idx; 383*c12c399aSSascha Wildner struct dev_mapping_table *mt_entry; 384*c12c399aSSascha Wildner 385*c12c399aSSascha Wildner for (map_idx = 0; map_idx < sc->max_devices; map_idx++) { 386*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[map_idx]; 387*c12c399aSSascha Wildner if (mt_entry->physical_id == dev_id) 388*c12c399aSSascha Wildner return map_idx; 389*c12c399aSSascha Wildner } 390*c12c399aSSascha Wildner return MPS_MAPTABLE_BAD_IDX; 391*c12c399aSSascha Wildner } 392*c12c399aSSascha Wildner 393*c12c399aSSascha Wildner /** 394*c12c399aSSascha Wildner * _mapping_get_ir_mt_idx_from_handle - get map table index from volume handle 395*c12c399aSSascha Wildner * @sc: per adapter object 396*c12c399aSSascha Wildner * @wwid: volume device handle 397*c12c399aSSascha Wildner * 398*c12c399aSSascha Wildner * Returns the index of map table entry on success or bad index. 399*c12c399aSSascha Wildner */ 400*c12c399aSSascha Wildner static u32 401*c12c399aSSascha Wildner _mapping_get_ir_mt_idx_from_handle(struct mps_softc *sc, u16 volHandle) 402*c12c399aSSascha Wildner { 403*c12c399aSSascha Wildner u32 start_idx, end_idx, map_idx; 404*c12c399aSSascha Wildner struct dev_mapping_table *mt_entry; 405*c12c399aSSascha Wildner 406*c12c399aSSascha Wildner _mapping_get_ir_maprange(sc, &start_idx, &end_idx); 407*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[start_idx]; 408*c12c399aSSascha Wildner for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) 409*c12c399aSSascha Wildner if (mt_entry->dev_handle == volHandle) 410*c12c399aSSascha Wildner return map_idx; 411*c12c399aSSascha Wildner 412*c12c399aSSascha Wildner return MPS_MAPTABLE_BAD_IDX; 413*c12c399aSSascha Wildner } 414*c12c399aSSascha Wildner 415*c12c399aSSascha Wildner /** 416*c12c399aSSascha Wildner * _mapping_get_mt_idx_from_handle - get map table index from handle 417*c12c399aSSascha Wildner * @sc: per adapter object 418*c12c399aSSascha Wildner * @dev_id: device handle 419*c12c399aSSascha Wildner * 420*c12c399aSSascha Wildner * Returns the index of map table entry on success or bad index. 421*c12c399aSSascha Wildner */ 422*c12c399aSSascha Wildner static u32 423*c12c399aSSascha Wildner _mapping_get_mt_idx_from_handle(struct mps_softc *sc, u16 handle) 424*c12c399aSSascha Wildner { 425*c12c399aSSascha Wildner u32 map_idx; 426*c12c399aSSascha Wildner struct dev_mapping_table *mt_entry; 427*c12c399aSSascha Wildner 428*c12c399aSSascha Wildner for (map_idx = 0; map_idx < sc->max_devices; map_idx++) { 429*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[map_idx]; 430*c12c399aSSascha Wildner if (mt_entry->dev_handle == handle) 431*c12c399aSSascha Wildner return map_idx; 432*c12c399aSSascha Wildner } 433*c12c399aSSascha Wildner return MPS_MAPTABLE_BAD_IDX; 434*c12c399aSSascha Wildner } 435*c12c399aSSascha Wildner 436*c12c399aSSascha Wildner /** 437*c12c399aSSascha Wildner * _mapping_get_free_ir_mt_idx - get first free index for a volume 438*c12c399aSSascha Wildner * @sc: per adapter object 439*c12c399aSSascha Wildner * 440*c12c399aSSascha Wildner * Search through mapping table for free index for a volume and if no free 441*c12c399aSSascha Wildner * index then looks for a volume with high mapping index 442*c12c399aSSascha Wildner * 443*c12c399aSSascha Wildner * Returns the index of map table entry on success or bad index. 444*c12c399aSSascha Wildner */ 445*c12c399aSSascha Wildner static u32 446*c12c399aSSascha Wildner _mapping_get_free_ir_mt_idx(struct mps_softc *sc) 447*c12c399aSSascha Wildner { 448*c12c399aSSascha Wildner u8 high_missing_count = 0; 449*c12c399aSSascha Wildner u32 start_idx, end_idx, map_idx; 450*c12c399aSSascha Wildner u32 high_idx = MPS_MAPTABLE_BAD_IDX; 451*c12c399aSSascha Wildner struct dev_mapping_table *mt_entry; 452*c12c399aSSascha Wildner 453*c12c399aSSascha Wildner _mapping_get_ir_maprange(sc, &start_idx, &end_idx); 454*c12c399aSSascha Wildner 455*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[start_idx]; 456*c12c399aSSascha Wildner for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) 457*c12c399aSSascha Wildner if (!(mt_entry->device_info & MPS_MAP_IN_USE)) 458*c12c399aSSascha Wildner return map_idx; 459*c12c399aSSascha Wildner 460*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[start_idx]; 461*c12c399aSSascha Wildner for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) { 462*c12c399aSSascha Wildner if (mt_entry->missing_count > high_missing_count) { 463*c12c399aSSascha Wildner high_missing_count = mt_entry->missing_count; 464*c12c399aSSascha Wildner high_idx = map_idx; 465*c12c399aSSascha Wildner } 466*c12c399aSSascha Wildner } 467*c12c399aSSascha Wildner return high_idx; 468*c12c399aSSascha Wildner } 469*c12c399aSSascha Wildner 470*c12c399aSSascha Wildner /** 471*c12c399aSSascha Wildner * _mapping_get_free_mt_idx - get first free index for a device 472*c12c399aSSascha Wildner * @sc: per adapter object 473*c12c399aSSascha Wildner * @start_idx: offset in the table to start search 474*c12c399aSSascha Wildner * 475*c12c399aSSascha Wildner * Returns the index of map table entry on success or bad index. 476*c12c399aSSascha Wildner */ 477*c12c399aSSascha Wildner static u32 478*c12c399aSSascha Wildner _mapping_get_free_mt_idx(struct mps_softc *sc, u32 start_idx) 479*c12c399aSSascha Wildner { 480*c12c399aSSascha Wildner u32 map_idx, max_idx = sc->max_devices; 481*c12c399aSSascha Wildner struct dev_mapping_table *mt_entry = &sc->mapping_table[start_idx]; 482*c12c399aSSascha Wildner u16 volume_mapping_flags; 483*c12c399aSSascha Wildner 484*c12c399aSSascha Wildner volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) & 485*c12c399aSSascha Wildner MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; 486*c12c399aSSascha Wildner if (sc->ir_firmware && (volume_mapping_flags == 487*c12c399aSSascha Wildner MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING)) 488*c12c399aSSascha Wildner max_idx -= sc->max_volumes; 489*c12c399aSSascha Wildner for (map_idx = start_idx; map_idx < max_idx; map_idx++, mt_entry++) 490*c12c399aSSascha Wildner if (!(mt_entry->device_info & (MPS_MAP_IN_USE | 491*c12c399aSSascha Wildner MPS_DEV_RESERVED))) 492*c12c399aSSascha Wildner return map_idx; 493*c12c399aSSascha Wildner 494*c12c399aSSascha Wildner return MPS_MAPTABLE_BAD_IDX; 495*c12c399aSSascha Wildner } 496*c12c399aSSascha Wildner 497*c12c399aSSascha Wildner /** 498*c12c399aSSascha Wildner * _mapping_get_dpm_idx_from_id - get DPM index from ID 499*c12c399aSSascha Wildner * @sc: per adapter object 500*c12c399aSSascha Wildner * @id: volume WWID or enclosure ID or device ID 501*c12c399aSSascha Wildner * 502*c12c399aSSascha Wildner * Returns the index of DPM entry on success or bad index. 503*c12c399aSSascha Wildner */ 504*c12c399aSSascha Wildner static u16 505*c12c399aSSascha Wildner _mapping_get_dpm_idx_from_id(struct mps_softc *sc, u64 id, u32 phy_bits) 506*c12c399aSSascha Wildner { 507*c12c399aSSascha Wildner u16 entry_num; 508*c12c399aSSascha Wildner uint64_t PhysicalIdentifier; 509*c12c399aSSascha Wildner Mpi2DriverMap0Entry_t *dpm_entry; 510*c12c399aSSascha Wildner 511*c12c399aSSascha Wildner dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 + 512*c12c399aSSascha Wildner sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 513*c12c399aSSascha Wildner PhysicalIdentifier = dpm_entry->PhysicalIdentifier.High; 514*c12c399aSSascha Wildner PhysicalIdentifier = (PhysicalIdentifier << 32) | 515*c12c399aSSascha Wildner dpm_entry->PhysicalIdentifier.Low; 516*c12c399aSSascha Wildner for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++, 517*c12c399aSSascha Wildner dpm_entry++) 518*c12c399aSSascha Wildner if ((id == PhysicalIdentifier) && 519*c12c399aSSascha Wildner (!phy_bits || !dpm_entry->PhysicalBitsMapping || 520*c12c399aSSascha Wildner (phy_bits & dpm_entry->PhysicalBitsMapping))) 521*c12c399aSSascha Wildner return entry_num; 522*c12c399aSSascha Wildner 523*c12c399aSSascha Wildner return MPS_DPM_BAD_IDX; 524*c12c399aSSascha Wildner } 525*c12c399aSSascha Wildner 526*c12c399aSSascha Wildner 527*c12c399aSSascha Wildner /** 528*c12c399aSSascha Wildner * _mapping_get_free_dpm_idx - get first available DPM index 529*c12c399aSSascha Wildner * @sc: per adapter object 530*c12c399aSSascha Wildner * 531*c12c399aSSascha Wildner * Returns the index of DPM entry on success or bad index. 532*c12c399aSSascha Wildner */ 533*c12c399aSSascha Wildner static u32 534*c12c399aSSascha Wildner _mapping_get_free_dpm_idx(struct mps_softc *sc) 535*c12c399aSSascha Wildner { 536*c12c399aSSascha Wildner u16 entry_num; 537*c12c399aSSascha Wildner 538*c12c399aSSascha Wildner for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) { 539*c12c399aSSascha Wildner if (!sc->dpm_entry_used[entry_num]) 540*c12c399aSSascha Wildner return entry_num; 541*c12c399aSSascha Wildner } 542*c12c399aSSascha Wildner return MPS_DPM_BAD_IDX; 543*c12c399aSSascha Wildner } 544*c12c399aSSascha Wildner 545*c12c399aSSascha Wildner /** 546*c12c399aSSascha Wildner * _mapping_update_ir_missing_cnt - Updates missing count for a volume 547*c12c399aSSascha Wildner * @sc: per adapter object 548*c12c399aSSascha Wildner * @map_idx: map table index of the volume 549*c12c399aSSascha Wildner * @element: IR configuration change element 550*c12c399aSSascha Wildner * @wwid: IR volume ID. 551*c12c399aSSascha Wildner * 552*c12c399aSSascha Wildner * Updates the missing count in the map table and in the DPM entry for a volume 553*c12c399aSSascha Wildner * 554*c12c399aSSascha Wildner * Returns nothing. 555*c12c399aSSascha Wildner */ 556*c12c399aSSascha Wildner static void 557*c12c399aSSascha Wildner _mapping_update_ir_missing_cnt(struct mps_softc *sc, u32 map_idx, 558*c12c399aSSascha Wildner Mpi2EventIrConfigElement_t *element, u64 wwid) 559*c12c399aSSascha Wildner { 560*c12c399aSSascha Wildner struct dev_mapping_table *mt_entry; 561*c12c399aSSascha Wildner u8 missing_cnt, reason = element->ReasonCode; 562*c12c399aSSascha Wildner u16 dpm_idx; 563*c12c399aSSascha Wildner Mpi2DriverMap0Entry_t *dpm_entry; 564*c12c399aSSascha Wildner 565*c12c399aSSascha Wildner if (!sc->is_dpm_enable) 566*c12c399aSSascha Wildner return; 567*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[map_idx]; 568*c12c399aSSascha Wildner if (reason == MPI2_EVENT_IR_CHANGE_RC_ADDED) { 569*c12c399aSSascha Wildner mt_entry->missing_count = 0; 570*c12c399aSSascha Wildner } else if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) { 571*c12c399aSSascha Wildner mt_entry->missing_count = 0; 572*c12c399aSSascha Wildner mt_entry->init_complete = 0; 573*c12c399aSSascha Wildner } else if ((reason == MPI2_EVENT_IR_CHANGE_RC_REMOVED) || 574*c12c399aSSascha Wildner (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED)) { 575*c12c399aSSascha Wildner if (!mt_entry->init_complete) { 576*c12c399aSSascha Wildner if (mt_entry->missing_count < MPS_MAX_MISSING_COUNT) 577*c12c399aSSascha Wildner mt_entry->missing_count++; 578*c12c399aSSascha Wildner else 579*c12c399aSSascha Wildner mt_entry->init_complete = 1; 580*c12c399aSSascha Wildner } 581*c12c399aSSascha Wildner if (!mt_entry->missing_count) 582*c12c399aSSascha Wildner mt_entry->missing_count++; 583*c12c399aSSascha Wildner mt_entry->dev_handle = 0; 584*c12c399aSSascha Wildner } 585*c12c399aSSascha Wildner 586*c12c399aSSascha Wildner dpm_idx = mt_entry->dpm_entry_num; 587*c12c399aSSascha Wildner if (dpm_idx == MPS_DPM_BAD_IDX) { 588*c12c399aSSascha Wildner if ((reason == MPI2_EVENT_IR_CHANGE_RC_ADDED) || 589*c12c399aSSascha Wildner (reason == MPI2_EVENT_IR_CHANGE_RC_REMOVED)) 590*c12c399aSSascha Wildner dpm_idx = _mapping_get_dpm_idx_from_id(sc, 591*c12c399aSSascha Wildner mt_entry->physical_id, 0); 592*c12c399aSSascha Wildner else if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED) 593*c12c399aSSascha Wildner return; 594*c12c399aSSascha Wildner } 595*c12c399aSSascha Wildner if (dpm_idx != MPS_DPM_BAD_IDX) { 596*c12c399aSSascha Wildner dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 + 597*c12c399aSSascha Wildner sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 598*c12c399aSSascha Wildner dpm_entry += dpm_idx; 599*c12c399aSSascha Wildner missing_cnt = dpm_entry->MappingInformation & 600*c12c399aSSascha Wildner MPI2_DRVMAP0_MAPINFO_MISSING_MASK; 601*c12c399aSSascha Wildner if ((mt_entry->physical_id == 602*c12c399aSSascha Wildner le64toh((u64)dpm_entry->PhysicalIdentifier.High | 603*c12c399aSSascha Wildner dpm_entry->PhysicalIdentifier.Low)) && (missing_cnt == 604*c12c399aSSascha Wildner mt_entry->missing_count)) 605*c12c399aSSascha Wildner mt_entry->init_complete = 1; 606*c12c399aSSascha Wildner } else { 607*c12c399aSSascha Wildner dpm_idx = _mapping_get_free_dpm_idx(sc); 608*c12c399aSSascha Wildner mt_entry->init_complete = 0; 609*c12c399aSSascha Wildner } 610*c12c399aSSascha Wildner 611*c12c399aSSascha Wildner if ((dpm_idx != MPS_DPM_BAD_IDX) && !mt_entry->init_complete) { 612*c12c399aSSascha Wildner mt_entry->init_complete = 1; 613*c12c399aSSascha Wildner mt_entry->dpm_entry_num = dpm_idx; 614*c12c399aSSascha Wildner dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 + 615*c12c399aSSascha Wildner sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 616*c12c399aSSascha Wildner dpm_entry += dpm_idx; 617*c12c399aSSascha Wildner dpm_entry->PhysicalIdentifier.Low = 618*c12c399aSSascha Wildner (0xFFFFFFFF & mt_entry->physical_id); 619*c12c399aSSascha Wildner dpm_entry->PhysicalIdentifier.High = 620*c12c399aSSascha Wildner (mt_entry->physical_id >> 32); 621*c12c399aSSascha Wildner dpm_entry->DeviceIndex = map_idx; 622*c12c399aSSascha Wildner dpm_entry->MappingInformation = mt_entry->missing_count; 623*c12c399aSSascha Wildner dpm_entry->PhysicalBitsMapping = 0; 624*c12c399aSSascha Wildner dpm_entry->Reserved1 = 0; 625*c12c399aSSascha Wildner sc->dpm_flush_entry[dpm_idx] = 1; 626*c12c399aSSascha Wildner sc->dpm_entry_used[dpm_idx] = 1; 627*c12c399aSSascha Wildner } else if (dpm_idx == MPS_DPM_BAD_IDX) { 628*c12c399aSSascha Wildner kprintf("%s: no space to add entry in DPM table\n", __func__); 629*c12c399aSSascha Wildner mt_entry->init_complete = 1; 630*c12c399aSSascha Wildner } 631*c12c399aSSascha Wildner } 632*c12c399aSSascha Wildner 633*c12c399aSSascha Wildner /** 634*c12c399aSSascha Wildner * _mapping_add_to_removal_table - mark an entry for removal 635*c12c399aSSascha Wildner * @sc: per adapter object 636*c12c399aSSascha Wildner * @handle: Handle of enclosures/device/volume 637*c12c399aSSascha Wildner * 638*c12c399aSSascha Wildner * Adds the handle or DPM entry number in removal table. 639*c12c399aSSascha Wildner * 640*c12c399aSSascha Wildner * Returns nothing. 641*c12c399aSSascha Wildner */ 642*c12c399aSSascha Wildner static void 643*c12c399aSSascha Wildner _mapping_add_to_removal_table(struct mps_softc *sc, u16 handle, 644*c12c399aSSascha Wildner u16 dpm_idx) 645*c12c399aSSascha Wildner { 646*c12c399aSSascha Wildner struct map_removal_table *remove_entry; 647*c12c399aSSascha Wildner u32 i; 648*c12c399aSSascha Wildner u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 649*c12c399aSSascha Wildner 650*c12c399aSSascha Wildner remove_entry = sc->removal_table; 651*c12c399aSSascha Wildner 652*c12c399aSSascha Wildner for (i = 0; i < sc->max_devices; i++, remove_entry++) { 653*c12c399aSSascha Wildner if (remove_entry->dev_handle || remove_entry->dpm_entry_num != 654*c12c399aSSascha Wildner MPS_DPM_BAD_IDX) 655*c12c399aSSascha Wildner continue; 656*c12c399aSSascha Wildner if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 657*c12c399aSSascha Wildner MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 658*c12c399aSSascha Wildner if (dpm_idx) 659*c12c399aSSascha Wildner remove_entry->dpm_entry_num = dpm_idx; 660*c12c399aSSascha Wildner if (remove_entry->dpm_entry_num == MPS_DPM_BAD_IDX) 661*c12c399aSSascha Wildner remove_entry->dev_handle = handle; 662*c12c399aSSascha Wildner } else if ((ioc_pg8_flags & 663*c12c399aSSascha Wildner MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 664*c12c399aSSascha Wildner MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) 665*c12c399aSSascha Wildner remove_entry->dev_handle = handle; 666*c12c399aSSascha Wildner break; 667*c12c399aSSascha Wildner } 668*c12c399aSSascha Wildner 669*c12c399aSSascha Wildner } 670*c12c399aSSascha Wildner 671*c12c399aSSascha Wildner /** 672*c12c399aSSascha Wildner * _mapping_update_missing_count - Update missing count for a device 673*c12c399aSSascha Wildner * @sc: per adapter object 674*c12c399aSSascha Wildner * @topo_change: Topology change event entry 675*c12c399aSSascha Wildner * 676*c12c399aSSascha Wildner * Search through the topology change list and if any device is found not 677*c12c399aSSascha Wildner * responding it's associated map table entry and DPM entry is updated 678*c12c399aSSascha Wildner * 679*c12c399aSSascha Wildner * Returns nothing. 680*c12c399aSSascha Wildner */ 681*c12c399aSSascha Wildner static void 682*c12c399aSSascha Wildner _mapping_update_missing_count(struct mps_softc *sc, 683*c12c399aSSascha Wildner struct _map_topology_change *topo_change) 684*c12c399aSSascha Wildner { 685*c12c399aSSascha Wildner u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 686*c12c399aSSascha Wildner u8 entry; 687*c12c399aSSascha Wildner struct _map_phy_change *phy_change; 688*c12c399aSSascha Wildner u32 map_idx; 689*c12c399aSSascha Wildner struct dev_mapping_table *mt_entry; 690*c12c399aSSascha Wildner Mpi2DriverMap0Entry_t *dpm_entry; 691*c12c399aSSascha Wildner 692*c12c399aSSascha Wildner for (entry = 0; entry < topo_change->num_entries; entry++) { 693*c12c399aSSascha Wildner phy_change = &topo_change->phy_details[entry]; 694*c12c399aSSascha Wildner if (!phy_change->dev_handle || (phy_change->reason != 695*c12c399aSSascha Wildner MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)) 696*c12c399aSSascha Wildner continue; 697*c12c399aSSascha Wildner map_idx = _mapping_get_mt_idx_from_handle(sc, phy_change-> 698*c12c399aSSascha Wildner dev_handle); 699*c12c399aSSascha Wildner phy_change->is_processed = 1; 700*c12c399aSSascha Wildner if (map_idx == MPS_MAPTABLE_BAD_IDX) { 701*c12c399aSSascha Wildner kprintf("%s: device is already removed from mapping " 702*c12c399aSSascha Wildner "table\n", __func__); 703*c12c399aSSascha Wildner continue; 704*c12c399aSSascha Wildner } 705*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[map_idx]; 706*c12c399aSSascha Wildner if (!mt_entry->init_complete) { 707*c12c399aSSascha Wildner if (mt_entry->missing_count < MPS_MAX_MISSING_COUNT) 708*c12c399aSSascha Wildner mt_entry->missing_count++; 709*c12c399aSSascha Wildner else 710*c12c399aSSascha Wildner mt_entry->init_complete = 1; 711*c12c399aSSascha Wildner } 712*c12c399aSSascha Wildner if (!mt_entry->missing_count) 713*c12c399aSSascha Wildner mt_entry->missing_count++; 714*c12c399aSSascha Wildner _mapping_add_to_removal_table(sc, mt_entry->dev_handle, 0); 715*c12c399aSSascha Wildner mt_entry->dev_handle = 0; 716*c12c399aSSascha Wildner 717*c12c399aSSascha Wildner if (((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 718*c12c399aSSascha Wildner MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) && 719*c12c399aSSascha Wildner sc->is_dpm_enable && !mt_entry->init_complete && 720*c12c399aSSascha Wildner mt_entry->dpm_entry_num != MPS_DPM_BAD_IDX) { 721*c12c399aSSascha Wildner dpm_entry = 722*c12c399aSSascha Wildner (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 + 723*c12c399aSSascha Wildner sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 724*c12c399aSSascha Wildner dpm_entry += mt_entry->dpm_entry_num; 725*c12c399aSSascha Wildner dpm_entry->MappingInformation = mt_entry->missing_count; 726*c12c399aSSascha Wildner sc->dpm_flush_entry[mt_entry->dpm_entry_num] = 1; 727*c12c399aSSascha Wildner } 728*c12c399aSSascha Wildner mt_entry->init_complete = 1; 729*c12c399aSSascha Wildner } 730*c12c399aSSascha Wildner } 731*c12c399aSSascha Wildner 732*c12c399aSSascha Wildner /** 733*c12c399aSSascha Wildner * _mapping_find_enc_map_space -find map table entries for enclosure 734*c12c399aSSascha Wildner * @sc: per adapter object 735*c12c399aSSascha Wildner * @et_entry: enclosure entry 736*c12c399aSSascha Wildner * 737*c12c399aSSascha Wildner * Search through the mapping table defragment it and provide contiguous 738*c12c399aSSascha Wildner * space in map table for a particular enclosure entry 739*c12c399aSSascha Wildner * 740*c12c399aSSascha Wildner * Returns start index in map table or bad index. 741*c12c399aSSascha Wildner */ 742*c12c399aSSascha Wildner static u32 743*c12c399aSSascha Wildner _mapping_find_enc_map_space(struct mps_softc *sc, 744*c12c399aSSascha Wildner struct enc_mapping_table *et_entry) 745*c12c399aSSascha Wildner { 746*c12c399aSSascha Wildner u16 vol_mapping_flags; 747*c12c399aSSascha Wildner u32 skip_count, end_of_table, map_idx, enc_idx; 748*c12c399aSSascha Wildner u16 num_found; 749*c12c399aSSascha Wildner u32 start_idx = MPS_MAPTABLE_BAD_IDX; 750*c12c399aSSascha Wildner struct dev_mapping_table *mt_entry; 751*c12c399aSSascha Wildner struct enc_mapping_table *enc_entry; 752*c12c399aSSascha Wildner unsigned char done_flag = 0, found_space; 753*c12c399aSSascha Wildner u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs); 754*c12c399aSSascha Wildner 755*c12c399aSSascha Wildner skip_count = sc->num_rsvd_entries; 756*c12c399aSSascha Wildner num_found = 0; 757*c12c399aSSascha Wildner 758*c12c399aSSascha Wildner vol_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) & 759*c12c399aSSascha Wildner MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; 760*c12c399aSSascha Wildner 761*c12c399aSSascha Wildner if (!sc->ir_firmware) 762*c12c399aSSascha Wildner end_of_table = sc->max_devices; 763*c12c399aSSascha Wildner else if (vol_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) 764*c12c399aSSascha Wildner end_of_table = sc->max_devices; 765*c12c399aSSascha Wildner else 766*c12c399aSSascha Wildner end_of_table = sc->max_devices - sc->max_volumes; 767*c12c399aSSascha Wildner 768*c12c399aSSascha Wildner for (map_idx = (max_num_phy_ids + skip_count); 769*c12c399aSSascha Wildner map_idx < end_of_table; map_idx++) { 770*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[map_idx]; 771*c12c399aSSascha Wildner if ((et_entry->enclosure_id == mt_entry->physical_id) && 772*c12c399aSSascha Wildner (!mt_entry->phy_bits || (mt_entry->phy_bits & 773*c12c399aSSascha Wildner et_entry->phy_bits))) { 774*c12c399aSSascha Wildner num_found += 1; 775*c12c399aSSascha Wildner if (num_found == et_entry->num_slots) { 776*c12c399aSSascha Wildner start_idx = (map_idx - num_found) + 1; 777*c12c399aSSascha Wildner return start_idx; 778*c12c399aSSascha Wildner } 779*c12c399aSSascha Wildner } else 780*c12c399aSSascha Wildner num_found = 0; 781*c12c399aSSascha Wildner } 782*c12c399aSSascha Wildner for (map_idx = (max_num_phy_ids + skip_count); 783*c12c399aSSascha Wildner map_idx < end_of_table; map_idx++) { 784*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[map_idx]; 785*c12c399aSSascha Wildner if (!(mt_entry->device_info & MPS_DEV_RESERVED)) { 786*c12c399aSSascha Wildner num_found += 1; 787*c12c399aSSascha Wildner if (num_found == et_entry->num_slots) { 788*c12c399aSSascha Wildner start_idx = (map_idx - num_found) + 1; 789*c12c399aSSascha Wildner return start_idx; 790*c12c399aSSascha Wildner } 791*c12c399aSSascha Wildner } else 792*c12c399aSSascha Wildner num_found = 0; 793*c12c399aSSascha Wildner } 794*c12c399aSSascha Wildner 795*c12c399aSSascha Wildner while (!done_flag) { 796*c12c399aSSascha Wildner enc_idx = _mapping_get_high_missing_et_idx(sc); 797*c12c399aSSascha Wildner if (enc_idx == MPS_ENCTABLE_BAD_IDX) 798*c12c399aSSascha Wildner return MPS_MAPTABLE_BAD_IDX; 799*c12c399aSSascha Wildner enc_entry = &sc->enclosure_table[enc_idx]; 800*c12c399aSSascha Wildner /*VSP FIXME*/ 801*c12c399aSSascha Wildner enc_entry->skip_search = 1; 802*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[enc_entry->start_index]; 803*c12c399aSSascha Wildner for (map_idx = enc_entry->start_index; map_idx < 804*c12c399aSSascha Wildner (enc_entry->start_index + enc_entry->num_slots); map_idx++, 805*c12c399aSSascha Wildner mt_entry++) 806*c12c399aSSascha Wildner mt_entry->device_info &= ~MPS_DEV_RESERVED; 807*c12c399aSSascha Wildner found_space = 0; 808*c12c399aSSascha Wildner for (map_idx = (max_num_phy_ids + 809*c12c399aSSascha Wildner skip_count); map_idx < end_of_table; map_idx++) { 810*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[map_idx]; 811*c12c399aSSascha Wildner if (!(mt_entry->device_info & MPS_DEV_RESERVED)) { 812*c12c399aSSascha Wildner num_found += 1; 813*c12c399aSSascha Wildner if (num_found == et_entry->num_slots) { 814*c12c399aSSascha Wildner start_idx = (map_idx - num_found) + 1; 815*c12c399aSSascha Wildner found_space = 1; 816*c12c399aSSascha Wildner } 817*c12c399aSSascha Wildner } else 818*c12c399aSSascha Wildner num_found = 0; 819*c12c399aSSascha Wildner } 820*c12c399aSSascha Wildner 821*c12c399aSSascha Wildner if (!found_space) 822*c12c399aSSascha Wildner continue; 823*c12c399aSSascha Wildner for (map_idx = start_idx; map_idx < (start_idx + num_found); 824*c12c399aSSascha Wildner map_idx++) { 825*c12c399aSSascha Wildner enc_entry = sc->enclosure_table; 826*c12c399aSSascha Wildner for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; 827*c12c399aSSascha Wildner enc_idx++, enc_entry++) { 828*c12c399aSSascha Wildner if (map_idx < enc_entry->start_index || 829*c12c399aSSascha Wildner map_idx > (enc_entry->start_index + 830*c12c399aSSascha Wildner enc_entry->num_slots)) 831*c12c399aSSascha Wildner continue; 832*c12c399aSSascha Wildner if (!enc_entry->removal_flag) { 833*c12c399aSSascha Wildner enc_entry->removal_flag = 1; 834*c12c399aSSascha Wildner _mapping_add_to_removal_table(sc, 0, 835*c12c399aSSascha Wildner enc_entry->dpm_entry_num); 836*c12c399aSSascha Wildner } 837*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[map_idx]; 838*c12c399aSSascha Wildner if (mt_entry->device_info & 839*c12c399aSSascha Wildner MPS_MAP_IN_USE) { 840*c12c399aSSascha Wildner _mapping_add_to_removal_table(sc, 841*c12c399aSSascha Wildner mt_entry->dev_handle, 0); 842*c12c399aSSascha Wildner _mapping_clear_map_entry(mt_entry); 843*c12c399aSSascha Wildner } 844*c12c399aSSascha Wildner if (map_idx == (enc_entry->start_index + 845*c12c399aSSascha Wildner enc_entry->num_slots - 1)) 846*c12c399aSSascha Wildner _mapping_clear_enc_entry(et_entry); 847*c12c399aSSascha Wildner } 848*c12c399aSSascha Wildner } 849*c12c399aSSascha Wildner enc_entry = sc->enclosure_table; 850*c12c399aSSascha Wildner for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; 851*c12c399aSSascha Wildner enc_idx++, enc_entry++) { 852*c12c399aSSascha Wildner if (!enc_entry->removal_flag) { 853*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[enc_entry-> 854*c12c399aSSascha Wildner start_index]; 855*c12c399aSSascha Wildner for (map_idx = enc_entry->start_index; map_idx < 856*c12c399aSSascha Wildner (enc_entry->start_index + 857*c12c399aSSascha Wildner enc_entry->num_slots); map_idx++, 858*c12c399aSSascha Wildner mt_entry++) 859*c12c399aSSascha Wildner mt_entry->device_info |= 860*c12c399aSSascha Wildner MPS_DEV_RESERVED; 861*c12c399aSSascha Wildner et_entry->skip_search = 0; 862*c12c399aSSascha Wildner } 863*c12c399aSSascha Wildner } 864*c12c399aSSascha Wildner done_flag = 1; 865*c12c399aSSascha Wildner } 866*c12c399aSSascha Wildner return start_idx; 867*c12c399aSSascha Wildner } 868*c12c399aSSascha Wildner 869*c12c399aSSascha Wildner /** 870*c12c399aSSascha Wildner * _mapping_get_dev_info -get information about newly added devices 871*c12c399aSSascha Wildner * @sc: per adapter object 872*c12c399aSSascha Wildner * @topo_change: Topology change event entry 873*c12c399aSSascha Wildner * 874*c12c399aSSascha Wildner * Search through the topology change event list and issues sas device pg0 875*c12c399aSSascha Wildner * requests for the newly added device and reserved entries in tables 876*c12c399aSSascha Wildner * 877*c12c399aSSascha Wildner * Returns nothing 878*c12c399aSSascha Wildner */ 879*c12c399aSSascha Wildner static void 880*c12c399aSSascha Wildner _mapping_get_dev_info(struct mps_softc *sc, 881*c12c399aSSascha Wildner struct _map_topology_change *topo_change) 882*c12c399aSSascha Wildner { 883*c12c399aSSascha Wildner u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 884*c12c399aSSascha Wildner Mpi2ConfigReply_t mpi_reply; 885*c12c399aSSascha Wildner Mpi2SasDevicePage0_t sas_device_pg0; 886*c12c399aSSascha Wildner u8 entry, enc_idx, phy_idx; 887*c12c399aSSascha Wildner u32 map_idx, index, device_info; 888*c12c399aSSascha Wildner struct _map_phy_change *phy_change, *tmp_phy_change; 889*c12c399aSSascha Wildner uint64_t sas_address; 890*c12c399aSSascha Wildner struct enc_mapping_table *et_entry; 891*c12c399aSSascha Wildner struct dev_mapping_table *mt_entry; 892*c12c399aSSascha Wildner u8 add_code = MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED; 893*c12c399aSSascha Wildner int rc; 894*c12c399aSSascha Wildner 895*c12c399aSSascha Wildner for (entry = 0; entry < topo_change->num_entries; entry++) { 896*c12c399aSSascha Wildner phy_change = &topo_change->phy_details[entry]; 897*c12c399aSSascha Wildner if (phy_change->is_processed || !phy_change->dev_handle || 898*c12c399aSSascha Wildner phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED) 899*c12c399aSSascha Wildner continue; 900*c12c399aSSascha Wildner if (mps_config_get_sas_device_pg0(sc, &mpi_reply, 901*c12c399aSSascha Wildner &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, 902*c12c399aSSascha Wildner phy_change->dev_handle)) { 903*c12c399aSSascha Wildner phy_change->is_processed = 1; 904*c12c399aSSascha Wildner continue; 905*c12c399aSSascha Wildner } 906*c12c399aSSascha Wildner 907*c12c399aSSascha Wildner device_info = le32toh(sas_device_pg0.DeviceInfo); 908*c12c399aSSascha Wildner if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 909*c12c399aSSascha Wildner MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { 910*c12c399aSSascha Wildner if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) && 911*c12c399aSSascha Wildner (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) { 912*c12c399aSSascha Wildner rc = mpssas_get_sas_address_for_sata_disk(sc, 913*c12c399aSSascha Wildner &sas_address, phy_change->dev_handle, 914*c12c399aSSascha Wildner device_info); 915*c12c399aSSascha Wildner if (rc) { 916*c12c399aSSascha Wildner kprintf("%s: failed to compute the " 917*c12c399aSSascha Wildner "hashed SAS Address for SATA " 918*c12c399aSSascha Wildner "device with handle 0x%04x\n", 919*c12c399aSSascha Wildner __func__, phy_change->dev_handle); 920*c12c399aSSascha Wildner sas_address = 921*c12c399aSSascha Wildner sas_device_pg0.SASAddress.High; 922*c12c399aSSascha Wildner sas_address = (sas_address << 32) | 923*c12c399aSSascha Wildner sas_device_pg0.SASAddress.Low; 924*c12c399aSSascha Wildner } 925*c12c399aSSascha Wildner mps_dprint(sc, MPS_INFO, "SAS Address for SATA " 926*c12c399aSSascha Wildner "device = %jx\n", sas_address); 927*c12c399aSSascha Wildner } else { 928*c12c399aSSascha Wildner sas_address = 929*c12c399aSSascha Wildner sas_device_pg0.SASAddress.High; 930*c12c399aSSascha Wildner sas_address = (sas_address << 32) | 931*c12c399aSSascha Wildner sas_device_pg0.SASAddress.Low; 932*c12c399aSSascha Wildner } 933*c12c399aSSascha Wildner } else { 934*c12c399aSSascha Wildner sas_address = sas_device_pg0.SASAddress.High; 935*c12c399aSSascha Wildner sas_address = (sas_address << 32) | 936*c12c399aSSascha Wildner sas_device_pg0.SASAddress.Low; 937*c12c399aSSascha Wildner } 938*c12c399aSSascha Wildner phy_change->physical_id = sas_address; 939*c12c399aSSascha Wildner phy_change->slot = le16toh(sas_device_pg0.Slot); 940*c12c399aSSascha Wildner phy_change->device_info = 941*c12c399aSSascha Wildner le32toh(sas_device_pg0.DeviceInfo); 942*c12c399aSSascha Wildner 943*c12c399aSSascha Wildner if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 944*c12c399aSSascha Wildner MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 945*c12c399aSSascha Wildner enc_idx = _mapping_get_enc_idx_from_handle(sc, 946*c12c399aSSascha Wildner topo_change->enc_handle); 947*c12c399aSSascha Wildner if (enc_idx == MPS_ENCTABLE_BAD_IDX) { 948*c12c399aSSascha Wildner phy_change->is_processed = 1; 949*c12c399aSSascha Wildner kprintf("%s: failed to add the device with " 950*c12c399aSSascha Wildner "handle 0x%04x because the enclosure is " 951*c12c399aSSascha Wildner "not in the mapping table\n", __func__, 952*c12c399aSSascha Wildner phy_change->dev_handle); 953*c12c399aSSascha Wildner continue; 954*c12c399aSSascha Wildner } 955*c12c399aSSascha Wildner if (!((phy_change->device_info & 956*c12c399aSSascha Wildner MPI2_SAS_DEVICE_INFO_END_DEVICE) && 957*c12c399aSSascha Wildner (phy_change->device_info & 958*c12c399aSSascha Wildner (MPI2_SAS_DEVICE_INFO_SSP_TARGET | 959*c12c399aSSascha Wildner MPI2_SAS_DEVICE_INFO_STP_TARGET | 960*c12c399aSSascha Wildner MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))) { 961*c12c399aSSascha Wildner phy_change->is_processed = 1; 962*c12c399aSSascha Wildner continue; 963*c12c399aSSascha Wildner } 964*c12c399aSSascha Wildner et_entry = &sc->enclosure_table[enc_idx]; 965*c12c399aSSascha Wildner if (et_entry->start_index != MPS_MAPTABLE_BAD_IDX) 966*c12c399aSSascha Wildner continue; 967*c12c399aSSascha Wildner if (!topo_change->exp_handle) { 968*c12c399aSSascha Wildner map_idx = sc->num_rsvd_entries; 969*c12c399aSSascha Wildner et_entry->start_index = map_idx; 970*c12c399aSSascha Wildner } else { 971*c12c399aSSascha Wildner map_idx = _mapping_find_enc_map_space(sc, 972*c12c399aSSascha Wildner et_entry); 973*c12c399aSSascha Wildner et_entry->start_index = map_idx; 974*c12c399aSSascha Wildner if (et_entry->start_index == 975*c12c399aSSascha Wildner MPS_MAPTABLE_BAD_IDX) { 976*c12c399aSSascha Wildner phy_change->is_processed = 1; 977*c12c399aSSascha Wildner for (phy_idx = 0; phy_idx < 978*c12c399aSSascha Wildner topo_change->num_entries; 979*c12c399aSSascha Wildner phy_idx++) { 980*c12c399aSSascha Wildner tmp_phy_change = 981*c12c399aSSascha Wildner &topo_change->phy_details 982*c12c399aSSascha Wildner [phy_idx]; 983*c12c399aSSascha Wildner if (tmp_phy_change->reason == 984*c12c399aSSascha Wildner add_code) 985*c12c399aSSascha Wildner tmp_phy_change-> 986*c12c399aSSascha Wildner is_processed = 1; 987*c12c399aSSascha Wildner } 988*c12c399aSSascha Wildner break; 989*c12c399aSSascha Wildner } 990*c12c399aSSascha Wildner } 991*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[map_idx]; 992*c12c399aSSascha Wildner for (index = map_idx; index < (et_entry->num_slots 993*c12c399aSSascha Wildner + map_idx); index++, mt_entry++) { 994*c12c399aSSascha Wildner mt_entry->device_info = MPS_DEV_RESERVED; 995*c12c399aSSascha Wildner mt_entry->physical_id = et_entry->enclosure_id; 996*c12c399aSSascha Wildner mt_entry->phy_bits = et_entry->phy_bits; 997*c12c399aSSascha Wildner } 998*c12c399aSSascha Wildner } 999*c12c399aSSascha Wildner } 1000*c12c399aSSascha Wildner } 1001*c12c399aSSascha Wildner 1002*c12c399aSSascha Wildner /** 1003*c12c399aSSascha Wildner * _mapping_set_mid_to_eid -set map table data from enclosure table 1004*c12c399aSSascha Wildner * @sc: per adapter object 1005*c12c399aSSascha Wildner * @et_entry: enclosure entry 1006*c12c399aSSascha Wildner * 1007*c12c399aSSascha Wildner * Returns nothing 1008*c12c399aSSascha Wildner */ 1009*c12c399aSSascha Wildner static inline void 1010*c12c399aSSascha Wildner _mapping_set_mid_to_eid(struct mps_softc *sc, 1011*c12c399aSSascha Wildner struct enc_mapping_table *et_entry) 1012*c12c399aSSascha Wildner { 1013*c12c399aSSascha Wildner struct dev_mapping_table *mt_entry; 1014*c12c399aSSascha Wildner u16 slots = et_entry->num_slots, map_idx; 1015*c12c399aSSascha Wildner u32 start_idx = et_entry->start_index; 1016*c12c399aSSascha Wildner if (start_idx != MPS_MAPTABLE_BAD_IDX) { 1017*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[start_idx]; 1018*c12c399aSSascha Wildner for (map_idx = 0; map_idx < slots; map_idx++, mt_entry++) 1019*c12c399aSSascha Wildner mt_entry->physical_id = et_entry->enclosure_id; 1020*c12c399aSSascha Wildner } 1021*c12c399aSSascha Wildner } 1022*c12c399aSSascha Wildner 1023*c12c399aSSascha Wildner /** 1024*c12c399aSSascha Wildner * _mapping_clear_removed_entries - mark the entries to be cleared 1025*c12c399aSSascha Wildner * @sc: per adapter object 1026*c12c399aSSascha Wildner * 1027*c12c399aSSascha Wildner * Search through the removal table and mark the entries which needs to be 1028*c12c399aSSascha Wildner * flushed to DPM and also updates the map table and enclosure table by 1029*c12c399aSSascha Wildner * clearing the corresponding entries. 1030*c12c399aSSascha Wildner * 1031*c12c399aSSascha Wildner * Returns nothing 1032*c12c399aSSascha Wildner */ 1033*c12c399aSSascha Wildner static void 1034*c12c399aSSascha Wildner _mapping_clear_removed_entries(struct mps_softc *sc) 1035*c12c399aSSascha Wildner { 1036*c12c399aSSascha Wildner u32 remove_idx; 1037*c12c399aSSascha Wildner struct map_removal_table *remove_entry; 1038*c12c399aSSascha Wildner Mpi2DriverMap0Entry_t *dpm_entry; 1039*c12c399aSSascha Wildner u8 done_flag = 0, num_entries, m, i; 1040*c12c399aSSascha Wildner struct enc_mapping_table *et_entry, *from, *to; 1041*c12c399aSSascha Wildner u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1042*c12c399aSSascha Wildner 1043*c12c399aSSascha Wildner if (sc->is_dpm_enable) { 1044*c12c399aSSascha Wildner remove_entry = sc->removal_table; 1045*c12c399aSSascha Wildner for (remove_idx = 0; remove_idx < sc->max_devices; 1046*c12c399aSSascha Wildner remove_idx++, remove_entry++) { 1047*c12c399aSSascha Wildner if (remove_entry->dpm_entry_num != MPS_DPM_BAD_IDX) { 1048*c12c399aSSascha Wildner dpm_entry = (Mpi2DriverMap0Entry_t *) 1049*c12c399aSSascha Wildner ((u8 *) sc->dpm_pg0 + 1050*c12c399aSSascha Wildner sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 1051*c12c399aSSascha Wildner dpm_entry += remove_entry->dpm_entry_num; 1052*c12c399aSSascha Wildner dpm_entry->PhysicalIdentifier.Low = 0; 1053*c12c399aSSascha Wildner dpm_entry->PhysicalIdentifier.High = 0; 1054*c12c399aSSascha Wildner dpm_entry->DeviceIndex = 0; 1055*c12c399aSSascha Wildner dpm_entry->MappingInformation = 0; 1056*c12c399aSSascha Wildner dpm_entry->PhysicalBitsMapping = 0; 1057*c12c399aSSascha Wildner sc->dpm_flush_entry[remove_entry-> 1058*c12c399aSSascha Wildner dpm_entry_num] = 1; 1059*c12c399aSSascha Wildner sc->dpm_entry_used[remove_entry->dpm_entry_num] 1060*c12c399aSSascha Wildner = 0; 1061*c12c399aSSascha Wildner remove_entry->dpm_entry_num = MPS_DPM_BAD_IDX; 1062*c12c399aSSascha Wildner } 1063*c12c399aSSascha Wildner } 1064*c12c399aSSascha Wildner } 1065*c12c399aSSascha Wildner if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1066*c12c399aSSascha Wildner MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 1067*c12c399aSSascha Wildner num_entries = sc->num_enc_table_entries; 1068*c12c399aSSascha Wildner while (!done_flag) { 1069*c12c399aSSascha Wildner done_flag = 1; 1070*c12c399aSSascha Wildner et_entry = sc->enclosure_table; 1071*c12c399aSSascha Wildner for (i = 0; i < num_entries; i++, et_entry++) { 1072*c12c399aSSascha Wildner if (!et_entry->enc_handle && et_entry-> 1073*c12c399aSSascha Wildner init_complete) { 1074*c12c399aSSascha Wildner done_flag = 0; 1075*c12c399aSSascha Wildner if (i != (num_entries - 1)) { 1076*c12c399aSSascha Wildner from = &sc->enclosure_table 1077*c12c399aSSascha Wildner [i+1]; 1078*c12c399aSSascha Wildner to = &sc->enclosure_table[i]; 1079*c12c399aSSascha Wildner for (m = i; m < (num_entries - 1080*c12c399aSSascha Wildner 1); m++, from++, to++) { 1081*c12c399aSSascha Wildner _mapping_set_mid_to_eid 1082*c12c399aSSascha Wildner (sc, to); 1083*c12c399aSSascha Wildner *to = *from; 1084*c12c399aSSascha Wildner } 1085*c12c399aSSascha Wildner _mapping_clear_enc_entry(to); 1086*c12c399aSSascha Wildner sc->num_enc_table_entries--; 1087*c12c399aSSascha Wildner num_entries = 1088*c12c399aSSascha Wildner sc->num_enc_table_entries; 1089*c12c399aSSascha Wildner } else { 1090*c12c399aSSascha Wildner _mapping_clear_enc_entry 1091*c12c399aSSascha Wildner (et_entry); 1092*c12c399aSSascha Wildner sc->num_enc_table_entries--; 1093*c12c399aSSascha Wildner num_entries = 1094*c12c399aSSascha Wildner sc->num_enc_table_entries; 1095*c12c399aSSascha Wildner } 1096*c12c399aSSascha Wildner } 1097*c12c399aSSascha Wildner } 1098*c12c399aSSascha Wildner } 1099*c12c399aSSascha Wildner } 1100*c12c399aSSascha Wildner } 1101*c12c399aSSascha Wildner 1102*c12c399aSSascha Wildner /** 1103*c12c399aSSascha Wildner * _mapping_add_new_device -Add the new device into mapping table 1104*c12c399aSSascha Wildner * @sc: per adapter object 1105*c12c399aSSascha Wildner * @topo_change: Topology change event entry 1106*c12c399aSSascha Wildner * 1107*c12c399aSSascha Wildner * Search through the topology change event list and updates map table, 1108*c12c399aSSascha Wildner * enclosure table and DPM pages for for the newly added devices. 1109*c12c399aSSascha Wildner * 1110*c12c399aSSascha Wildner * Returns nothing 1111*c12c399aSSascha Wildner */ 1112*c12c399aSSascha Wildner static void 1113*c12c399aSSascha Wildner _mapping_add_new_device(struct mps_softc *sc, 1114*c12c399aSSascha Wildner struct _map_topology_change *topo_change) 1115*c12c399aSSascha Wildner { 1116*c12c399aSSascha Wildner u8 enc_idx, missing_cnt, is_removed = 0; 1117*c12c399aSSascha Wildner u16 dpm_idx; 1118*c12c399aSSascha Wildner u32 search_idx, map_idx; 1119*c12c399aSSascha Wildner u32 entry; 1120*c12c399aSSascha Wildner struct dev_mapping_table *mt_entry; 1121*c12c399aSSascha Wildner struct enc_mapping_table *et_entry; 1122*c12c399aSSascha Wildner struct _map_phy_change *phy_change; 1123*c12c399aSSascha Wildner u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1124*c12c399aSSascha Wildner Mpi2DriverMap0Entry_t *dpm_entry; 1125*c12c399aSSascha Wildner uint64_t temp64_var; 1126*c12c399aSSascha Wildner u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT; 1127*c12c399aSSascha Wildner u8 hdr_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER); 1128*c12c399aSSascha Wildner u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs); 1129*c12c399aSSascha Wildner 1130*c12c399aSSascha Wildner for (entry = 0; entry < topo_change->num_entries; entry++) { 1131*c12c399aSSascha Wildner phy_change = &topo_change->phy_details[entry]; 1132*c12c399aSSascha Wildner if (phy_change->is_processed) 1133*c12c399aSSascha Wildner continue; 1134*c12c399aSSascha Wildner if (phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED || 1135*c12c399aSSascha Wildner !phy_change->dev_handle) { 1136*c12c399aSSascha Wildner phy_change->is_processed = 1; 1137*c12c399aSSascha Wildner continue; 1138*c12c399aSSascha Wildner } 1139*c12c399aSSascha Wildner if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1140*c12c399aSSascha Wildner MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 1141*c12c399aSSascha Wildner enc_idx = _mapping_get_enc_idx_from_handle 1142*c12c399aSSascha Wildner (sc, topo_change->enc_handle); 1143*c12c399aSSascha Wildner if (enc_idx == MPS_ENCTABLE_BAD_IDX) { 1144*c12c399aSSascha Wildner phy_change->is_processed = 1; 1145*c12c399aSSascha Wildner kprintf("%s: failed to add the device with " 1146*c12c399aSSascha Wildner "handle 0x%04x because the enclosure is " 1147*c12c399aSSascha Wildner "not in the mapping table\n", __func__, 1148*c12c399aSSascha Wildner phy_change->dev_handle); 1149*c12c399aSSascha Wildner continue; 1150*c12c399aSSascha Wildner } 1151*c12c399aSSascha Wildner et_entry = &sc->enclosure_table[enc_idx]; 1152*c12c399aSSascha Wildner if (et_entry->start_index == MPS_MAPTABLE_BAD_IDX) { 1153*c12c399aSSascha Wildner phy_change->is_processed = 1; 1154*c12c399aSSascha Wildner if (!sc->mt_full_retry) { 1155*c12c399aSSascha Wildner sc->mt_add_device_failed = 1; 1156*c12c399aSSascha Wildner continue; 1157*c12c399aSSascha Wildner } 1158*c12c399aSSascha Wildner kprintf("%s: failed to add the device with " 1159*c12c399aSSascha Wildner "handle 0x%04x because there is no free " 1160*c12c399aSSascha Wildner "space available in the mapping table\n", 1161*c12c399aSSascha Wildner __func__, phy_change->dev_handle); 1162*c12c399aSSascha Wildner continue; 1163*c12c399aSSascha Wildner } 1164*c12c399aSSascha Wildner map_idx = et_entry->start_index + phy_change->slot - 1165*c12c399aSSascha Wildner et_entry->start_slot; 1166*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[map_idx]; 1167*c12c399aSSascha Wildner mt_entry->physical_id = phy_change->physical_id; 1168*c12c399aSSascha Wildner mt_entry->channel = 0; 1169*c12c399aSSascha Wildner mt_entry->id = map_idx; 1170*c12c399aSSascha Wildner mt_entry->dev_handle = phy_change->dev_handle; 1171*c12c399aSSascha Wildner mt_entry->missing_count = 0; 1172*c12c399aSSascha Wildner mt_entry->dpm_entry_num = et_entry->dpm_entry_num; 1173*c12c399aSSascha Wildner mt_entry->device_info = phy_change->device_info | 1174*c12c399aSSascha Wildner (MPS_DEV_RESERVED | MPS_MAP_IN_USE); 1175*c12c399aSSascha Wildner if (sc->is_dpm_enable) { 1176*c12c399aSSascha Wildner dpm_idx = et_entry->dpm_entry_num; 1177*c12c399aSSascha Wildner if (dpm_idx == MPS_DPM_BAD_IDX) 1178*c12c399aSSascha Wildner dpm_idx = _mapping_get_dpm_idx_from_id 1179*c12c399aSSascha Wildner (sc, et_entry->enclosure_id, 1180*c12c399aSSascha Wildner et_entry->phy_bits); 1181*c12c399aSSascha Wildner if (dpm_idx == MPS_DPM_BAD_IDX) { 1182*c12c399aSSascha Wildner dpm_idx = _mapping_get_free_dpm_idx(sc); 1183*c12c399aSSascha Wildner if (dpm_idx != MPS_DPM_BAD_IDX) { 1184*c12c399aSSascha Wildner dpm_entry = 1185*c12c399aSSascha Wildner (Mpi2DriverMap0Entry_t *) 1186*c12c399aSSascha Wildner ((u8 *) sc->dpm_pg0 + 1187*c12c399aSSascha Wildner hdr_sz); 1188*c12c399aSSascha Wildner dpm_entry += dpm_idx; 1189*c12c399aSSascha Wildner dpm_entry-> 1190*c12c399aSSascha Wildner PhysicalIdentifier.Low = 1191*c12c399aSSascha Wildner (0xFFFFFFFF & 1192*c12c399aSSascha Wildner et_entry->enclosure_id); 1193*c12c399aSSascha Wildner dpm_entry-> 1194*c12c399aSSascha Wildner PhysicalIdentifier.High = 1195*c12c399aSSascha Wildner ( et_entry->enclosure_id 1196*c12c399aSSascha Wildner >> 32); 1197*c12c399aSSascha Wildner dpm_entry->DeviceIndex = 1198*c12c399aSSascha Wildner (U16)et_entry->start_index; 1199*c12c399aSSascha Wildner dpm_entry->MappingInformation = 1200*c12c399aSSascha Wildner et_entry->num_slots; 1201*c12c399aSSascha Wildner dpm_entry->MappingInformation 1202*c12c399aSSascha Wildner <<= map_shift; 1203*c12c399aSSascha Wildner dpm_entry->PhysicalBitsMapping 1204*c12c399aSSascha Wildner = et_entry->phy_bits; 1205*c12c399aSSascha Wildner et_entry->dpm_entry_num = 1206*c12c399aSSascha Wildner dpm_idx; 1207*c12c399aSSascha Wildner /* FIXME Do I need to set the dpm_idxin mt_entry too */ 1208*c12c399aSSascha Wildner sc->dpm_entry_used[dpm_idx] = 1; 1209*c12c399aSSascha Wildner sc->dpm_flush_entry[dpm_idx] = 1210*c12c399aSSascha Wildner 1; 1211*c12c399aSSascha Wildner phy_change->is_processed = 1; 1212*c12c399aSSascha Wildner } else { 1213*c12c399aSSascha Wildner phy_change->is_processed = 1; 1214*c12c399aSSascha Wildner kprintf("%s: failed to add the " 1215*c12c399aSSascha Wildner "device with handle 0x%04x " 1216*c12c399aSSascha Wildner "to persistent table " 1217*c12c399aSSascha Wildner "because there is no free " 1218*c12c399aSSascha Wildner "space available\n", 1219*c12c399aSSascha Wildner __func__, 1220*c12c399aSSascha Wildner phy_change->dev_handle); 1221*c12c399aSSascha Wildner } 1222*c12c399aSSascha Wildner } else { 1223*c12c399aSSascha Wildner et_entry->dpm_entry_num = dpm_idx; 1224*c12c399aSSascha Wildner mt_entry->dpm_entry_num = dpm_idx; 1225*c12c399aSSascha Wildner } 1226*c12c399aSSascha Wildner } 1227*c12c399aSSascha Wildner /* FIXME Why not mt_entry too? */ 1228*c12c399aSSascha Wildner et_entry->init_complete = 1; 1229*c12c399aSSascha Wildner } else if ((ioc_pg8_flags & 1230*c12c399aSSascha Wildner MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1231*c12c399aSSascha Wildner MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { 1232*c12c399aSSascha Wildner map_idx = _mapping_get_mt_idx_from_id 1233*c12c399aSSascha Wildner (sc, phy_change->physical_id); 1234*c12c399aSSascha Wildner if (map_idx == MPS_MAPTABLE_BAD_IDX) { 1235*c12c399aSSascha Wildner search_idx = sc->num_rsvd_entries; 1236*c12c399aSSascha Wildner if (topo_change->exp_handle) 1237*c12c399aSSascha Wildner search_idx += max_num_phy_ids; 1238*c12c399aSSascha Wildner map_idx = _mapping_get_free_mt_idx(sc, 1239*c12c399aSSascha Wildner search_idx); 1240*c12c399aSSascha Wildner } 1241*c12c399aSSascha Wildner if (map_idx == MPS_MAPTABLE_BAD_IDX) { 1242*c12c399aSSascha Wildner map_idx = _mapping_get_high_missing_mt_idx(sc); 1243*c12c399aSSascha Wildner if (map_idx != MPS_MAPTABLE_BAD_IDX) { 1244*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[map_idx]; 1245*c12c399aSSascha Wildner if (mt_entry->dev_handle) { 1246*c12c399aSSascha Wildner _mapping_add_to_removal_table 1247*c12c399aSSascha Wildner (sc, mt_entry->dev_handle, 1248*c12c399aSSascha Wildner 0); 1249*c12c399aSSascha Wildner is_removed = 1; 1250*c12c399aSSascha Wildner } 1251*c12c399aSSascha Wildner mt_entry->init_complete = 0; 1252*c12c399aSSascha Wildner } 1253*c12c399aSSascha Wildner } 1254*c12c399aSSascha Wildner if (map_idx != MPS_MAPTABLE_BAD_IDX) { 1255*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[map_idx]; 1256*c12c399aSSascha Wildner mt_entry->physical_id = phy_change->physical_id; 1257*c12c399aSSascha Wildner mt_entry->channel = 0; 1258*c12c399aSSascha Wildner mt_entry->id = map_idx; 1259*c12c399aSSascha Wildner mt_entry->dev_handle = phy_change->dev_handle; 1260*c12c399aSSascha Wildner mt_entry->missing_count = 0; 1261*c12c399aSSascha Wildner mt_entry->device_info = phy_change->device_info 1262*c12c399aSSascha Wildner | (MPS_DEV_RESERVED | MPS_MAP_IN_USE); 1263*c12c399aSSascha Wildner } else { 1264*c12c399aSSascha Wildner phy_change->is_processed = 1; 1265*c12c399aSSascha Wildner if (!sc->mt_full_retry) { 1266*c12c399aSSascha Wildner sc->mt_add_device_failed = 1; 1267*c12c399aSSascha Wildner continue; 1268*c12c399aSSascha Wildner } 1269*c12c399aSSascha Wildner kprintf("%s: failed to add the device with " 1270*c12c399aSSascha Wildner "handle 0x%04x because there is no free " 1271*c12c399aSSascha Wildner "space available in the mapping table\n", 1272*c12c399aSSascha Wildner __func__, phy_change->dev_handle); 1273*c12c399aSSascha Wildner continue; 1274*c12c399aSSascha Wildner } 1275*c12c399aSSascha Wildner if (sc->is_dpm_enable) { 1276*c12c399aSSascha Wildner if (mt_entry->dpm_entry_num != 1277*c12c399aSSascha Wildner MPS_DPM_BAD_IDX) { 1278*c12c399aSSascha Wildner dpm_idx = mt_entry->dpm_entry_num; 1279*c12c399aSSascha Wildner dpm_entry = (Mpi2DriverMap0Entry_t *) 1280*c12c399aSSascha Wildner ((u8 *)sc->dpm_pg0 + hdr_sz); 1281*c12c399aSSascha Wildner dpm_entry += dpm_idx; 1282*c12c399aSSascha Wildner missing_cnt = dpm_entry-> 1283*c12c399aSSascha Wildner MappingInformation & 1284*c12c399aSSascha Wildner MPI2_DRVMAP0_MAPINFO_MISSING_MASK; 1285*c12c399aSSascha Wildner temp64_var = dpm_entry-> 1286*c12c399aSSascha Wildner PhysicalIdentifier.High; 1287*c12c399aSSascha Wildner temp64_var = (temp64_var << 32) | 1288*c12c399aSSascha Wildner dpm_entry->PhysicalIdentifier.Low; 1289*c12c399aSSascha Wildner if ((mt_entry->physical_id == 1290*c12c399aSSascha Wildner temp64_var) && !missing_cnt) 1291*c12c399aSSascha Wildner mt_entry->init_complete = 1; 1292*c12c399aSSascha Wildner } else { 1293*c12c399aSSascha Wildner dpm_idx = _mapping_get_free_dpm_idx(sc); 1294*c12c399aSSascha Wildner mt_entry->init_complete = 0; 1295*c12c399aSSascha Wildner } 1296*c12c399aSSascha Wildner if (dpm_idx != MPS_DPM_BAD_IDX && 1297*c12c399aSSascha Wildner !mt_entry->init_complete) { 1298*c12c399aSSascha Wildner mt_entry->init_complete = 1; 1299*c12c399aSSascha Wildner mt_entry->dpm_entry_num = dpm_idx; 1300*c12c399aSSascha Wildner dpm_entry = (Mpi2DriverMap0Entry_t *) 1301*c12c399aSSascha Wildner ((u8 *)sc->dpm_pg0 + hdr_sz); 1302*c12c399aSSascha Wildner dpm_entry += dpm_idx; 1303*c12c399aSSascha Wildner dpm_entry->PhysicalIdentifier.Low = 1304*c12c399aSSascha Wildner (0xFFFFFFFF & 1305*c12c399aSSascha Wildner mt_entry->physical_id); 1306*c12c399aSSascha Wildner dpm_entry->PhysicalIdentifier.High = 1307*c12c399aSSascha Wildner (mt_entry->physical_id >> 32); 1308*c12c399aSSascha Wildner dpm_entry->DeviceIndex = (U16) map_idx; 1309*c12c399aSSascha Wildner dpm_entry->MappingInformation = 0; 1310*c12c399aSSascha Wildner dpm_entry->PhysicalBitsMapping = 0; 1311*c12c399aSSascha Wildner sc->dpm_entry_used[dpm_idx] = 1; 1312*c12c399aSSascha Wildner sc->dpm_flush_entry[dpm_idx] = 1; 1313*c12c399aSSascha Wildner phy_change->is_processed = 1; 1314*c12c399aSSascha Wildner } else if (dpm_idx == MPS_DPM_BAD_IDX) { 1315*c12c399aSSascha Wildner phy_change->is_processed = 1; 1316*c12c399aSSascha Wildner kprintf("%s: failed to add the " 1317*c12c399aSSascha Wildner "device with handle 0x%04x " 1318*c12c399aSSascha Wildner "to persistent table " 1319*c12c399aSSascha Wildner "because there is no free " 1320*c12c399aSSascha Wildner "space available\n", 1321*c12c399aSSascha Wildner __func__, 1322*c12c399aSSascha Wildner phy_change->dev_handle); 1323*c12c399aSSascha Wildner } 1324*c12c399aSSascha Wildner } 1325*c12c399aSSascha Wildner mt_entry->init_complete = 1; 1326*c12c399aSSascha Wildner } 1327*c12c399aSSascha Wildner 1328*c12c399aSSascha Wildner phy_change->is_processed = 1; 1329*c12c399aSSascha Wildner } 1330*c12c399aSSascha Wildner if (is_removed) 1331*c12c399aSSascha Wildner _mapping_clear_removed_entries(sc); 1332*c12c399aSSascha Wildner } 1333*c12c399aSSascha Wildner 1334*c12c399aSSascha Wildner /** 1335*c12c399aSSascha Wildner * _mapping_flush_dpm_pages -Flush the DPM pages to NVRAM 1336*c12c399aSSascha Wildner * @sc: per adapter object 1337*c12c399aSSascha Wildner * 1338*c12c399aSSascha Wildner * Returns nothing 1339*c12c399aSSascha Wildner */ 1340*c12c399aSSascha Wildner static void 1341*c12c399aSSascha Wildner _mapping_flush_dpm_pages(struct mps_softc *sc) 1342*c12c399aSSascha Wildner { 1343*c12c399aSSascha Wildner Mpi2DriverMap0Entry_t *dpm_entry; 1344*c12c399aSSascha Wildner Mpi2ConfigReply_t mpi_reply; 1345*c12c399aSSascha Wildner Mpi2DriverMappingPage0_t config_page; 1346*c12c399aSSascha Wildner u16 entry_num; 1347*c12c399aSSascha Wildner 1348*c12c399aSSascha Wildner for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) { 1349*c12c399aSSascha Wildner if (!sc->dpm_flush_entry[entry_num]) 1350*c12c399aSSascha Wildner continue; 1351*c12c399aSSascha Wildner memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t)); 1352*c12c399aSSascha Wildner memcpy(&config_page.Header, (u8 *)sc->dpm_pg0, 1353*c12c399aSSascha Wildner sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 1354*c12c399aSSascha Wildner dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 + 1355*c12c399aSSascha Wildner sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 1356*c12c399aSSascha Wildner dpm_entry += entry_num; 1357*c12c399aSSascha Wildner dpm_entry->MappingInformation = htole16(dpm_entry-> 1358*c12c399aSSascha Wildner MappingInformation); 1359*c12c399aSSascha Wildner dpm_entry->DeviceIndex = htole16(dpm_entry->DeviceIndex); 1360*c12c399aSSascha Wildner dpm_entry->PhysicalBitsMapping = htole32(dpm_entry-> 1361*c12c399aSSascha Wildner PhysicalBitsMapping); 1362*c12c399aSSascha Wildner memcpy(&config_page.Entry, (u8 *)dpm_entry, 1363*c12c399aSSascha Wildner sizeof(Mpi2DriverMap0Entry_t)); 1364*c12c399aSSascha Wildner /* TODO-How to handle failed writes? */ 1365*c12c399aSSascha Wildner if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page, 1366*c12c399aSSascha Wildner entry_num)) { 1367*c12c399aSSascha Wildner kprintf("%s: write of dpm entry %d for device failed\n", 1368*c12c399aSSascha Wildner __func__, entry_num); 1369*c12c399aSSascha Wildner } else 1370*c12c399aSSascha Wildner sc->dpm_flush_entry[entry_num] = 0; 1371*c12c399aSSascha Wildner dpm_entry->MappingInformation = le16toh(dpm_entry-> 1372*c12c399aSSascha Wildner MappingInformation); 1373*c12c399aSSascha Wildner dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex); 1374*c12c399aSSascha Wildner dpm_entry->PhysicalBitsMapping = le32toh(dpm_entry-> 1375*c12c399aSSascha Wildner PhysicalBitsMapping); 1376*c12c399aSSascha Wildner } 1377*c12c399aSSascha Wildner } 1378*c12c399aSSascha Wildner 1379*c12c399aSSascha Wildner /** 1380*c12c399aSSascha Wildner * _mapping_allocate_memory- allocates the memory required for mapping tables 1381*c12c399aSSascha Wildner * @sc: per adapter object 1382*c12c399aSSascha Wildner * 1383*c12c399aSSascha Wildner * Allocates the memory for all the tables required for host mapping 1384*c12c399aSSascha Wildner * 1385*c12c399aSSascha Wildner * Return 0 on success or non-zero on failure. 1386*c12c399aSSascha Wildner */ 1387*c12c399aSSascha Wildner int 1388*c12c399aSSascha Wildner mps_mapping_allocate_memory(struct mps_softc *sc) 1389*c12c399aSSascha Wildner { 1390*c12c399aSSascha Wildner uint32_t dpm_pg0_sz; 1391*c12c399aSSascha Wildner 1392*c12c399aSSascha Wildner sc->mapping_table = kmalloc((sizeof(struct dev_mapping_table) * 1393*c12c399aSSascha Wildner sc->max_devices), M_MPT2, M_ZERO|M_NOWAIT); 1394*c12c399aSSascha Wildner if (!sc->mapping_table) 1395*c12c399aSSascha Wildner goto free_resources; 1396*c12c399aSSascha Wildner 1397*c12c399aSSascha Wildner sc->removal_table = kmalloc((sizeof(struct map_removal_table) * 1398*c12c399aSSascha Wildner sc->max_devices), M_MPT2, M_ZERO|M_NOWAIT); 1399*c12c399aSSascha Wildner if (!sc->removal_table) 1400*c12c399aSSascha Wildner goto free_resources; 1401*c12c399aSSascha Wildner 1402*c12c399aSSascha Wildner sc->enclosure_table = kmalloc((sizeof(struct enc_mapping_table) * 1403*c12c399aSSascha Wildner sc->max_enclosures), M_MPT2, M_ZERO|M_NOWAIT); 1404*c12c399aSSascha Wildner if (!sc->enclosure_table) 1405*c12c399aSSascha Wildner goto free_resources; 1406*c12c399aSSascha Wildner 1407*c12c399aSSascha Wildner sc->dpm_entry_used = kmalloc((sizeof(u8) * sc->max_dpm_entries), 1408*c12c399aSSascha Wildner M_MPT2, M_ZERO|M_NOWAIT); 1409*c12c399aSSascha Wildner if (!sc->dpm_entry_used) 1410*c12c399aSSascha Wildner goto free_resources; 1411*c12c399aSSascha Wildner 1412*c12c399aSSascha Wildner sc->dpm_flush_entry = kmalloc((sizeof(u8) * sc->max_dpm_entries), 1413*c12c399aSSascha Wildner M_MPT2, M_ZERO|M_NOWAIT); 1414*c12c399aSSascha Wildner if (!sc->dpm_flush_entry) 1415*c12c399aSSascha Wildner goto free_resources; 1416*c12c399aSSascha Wildner 1417*c12c399aSSascha Wildner dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) + 1418*c12c399aSSascha Wildner (sc->max_dpm_entries * sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY)); 1419*c12c399aSSascha Wildner 1420*c12c399aSSascha Wildner sc->dpm_pg0 = kmalloc(dpm_pg0_sz, M_MPT2, M_ZERO|M_NOWAIT); 1421*c12c399aSSascha Wildner if (!sc->dpm_pg0) { 1422*c12c399aSSascha Wildner kprintf("%s: memory alloc failed for dpm page; disabling dpm\n", 1423*c12c399aSSascha Wildner __func__); 1424*c12c399aSSascha Wildner sc->is_dpm_enable = 0; 1425*c12c399aSSascha Wildner } 1426*c12c399aSSascha Wildner 1427*c12c399aSSascha Wildner return 0; 1428*c12c399aSSascha Wildner 1429*c12c399aSSascha Wildner free_resources: 1430*c12c399aSSascha Wildner kfree(sc->mapping_table, M_MPT2); 1431*c12c399aSSascha Wildner kfree(sc->removal_table, M_MPT2); 1432*c12c399aSSascha Wildner kfree(sc->enclosure_table, M_MPT2); 1433*c12c399aSSascha Wildner kfree(sc->dpm_entry_used, M_MPT2); 1434*c12c399aSSascha Wildner kfree(sc->dpm_flush_entry, M_MPT2); 1435*c12c399aSSascha Wildner kfree(sc->dpm_pg0, M_MPT2); 1436*c12c399aSSascha Wildner kprintf("%s: device initialization failed due to failure in mapping " 1437*c12c399aSSascha Wildner "table memory allocation\n", __func__); 1438*c12c399aSSascha Wildner return -1; 1439*c12c399aSSascha Wildner } 1440*c12c399aSSascha Wildner 1441*c12c399aSSascha Wildner /** 1442*c12c399aSSascha Wildner * mps_mapping_free_memory- frees the memory allocated for mapping tables 1443*c12c399aSSascha Wildner * @sc: per adapter object 1444*c12c399aSSascha Wildner * 1445*c12c399aSSascha Wildner * Returns nothing. 1446*c12c399aSSascha Wildner */ 1447*c12c399aSSascha Wildner void 1448*c12c399aSSascha Wildner mps_mapping_free_memory(struct mps_softc *sc) 1449*c12c399aSSascha Wildner { 1450*c12c399aSSascha Wildner kfree(sc->mapping_table, M_MPT2); 1451*c12c399aSSascha Wildner kfree(sc->removal_table, M_MPT2); 1452*c12c399aSSascha Wildner kfree(sc->enclosure_table, M_MPT2); 1453*c12c399aSSascha Wildner kfree(sc->dpm_entry_used, M_MPT2); 1454*c12c399aSSascha Wildner kfree(sc->dpm_flush_entry, M_MPT2); 1455*c12c399aSSascha Wildner kfree(sc->dpm_pg0, M_MPT2); 1456*c12c399aSSascha Wildner } 1457*c12c399aSSascha Wildner 1458*c12c399aSSascha Wildner 1459*c12c399aSSascha Wildner static void 1460*c12c399aSSascha Wildner _mapping_process_dpm_pg0(struct mps_softc *sc) 1461*c12c399aSSascha Wildner { 1462*c12c399aSSascha Wildner u8 missing_cnt, enc_idx; 1463*c12c399aSSascha Wildner u16 slot_id, entry_num, num_slots; 1464*c12c399aSSascha Wildner u32 map_idx, dev_idx, start_idx, end_idx; 1465*c12c399aSSascha Wildner struct dev_mapping_table *mt_entry; 1466*c12c399aSSascha Wildner Mpi2DriverMap0Entry_t *dpm_entry; 1467*c12c399aSSascha Wildner u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1468*c12c399aSSascha Wildner u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs); 1469*c12c399aSSascha Wildner struct enc_mapping_table *et_entry; 1470*c12c399aSSascha Wildner u64 physical_id; 1471*c12c399aSSascha Wildner u32 phy_bits = 0; 1472*c12c399aSSascha Wildner 1473*c12c399aSSascha Wildner if (sc->ir_firmware) 1474*c12c399aSSascha Wildner _mapping_get_ir_maprange(sc, &start_idx, &end_idx); 1475*c12c399aSSascha Wildner 1476*c12c399aSSascha Wildner dpm_entry = (Mpi2DriverMap0Entry_t *) ((uint8_t *) sc->dpm_pg0 + 1477*c12c399aSSascha Wildner sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 1478*c12c399aSSascha Wildner for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++, 1479*c12c399aSSascha Wildner dpm_entry++) { 1480*c12c399aSSascha Wildner physical_id = dpm_entry->PhysicalIdentifier.High; 1481*c12c399aSSascha Wildner physical_id = (physical_id << 32) | 1482*c12c399aSSascha Wildner dpm_entry->PhysicalIdentifier.Low; 1483*c12c399aSSascha Wildner if (!physical_id) { 1484*c12c399aSSascha Wildner sc->dpm_entry_used[entry_num] = 0; 1485*c12c399aSSascha Wildner continue; 1486*c12c399aSSascha Wildner } 1487*c12c399aSSascha Wildner sc->dpm_entry_used[entry_num] = 1; 1488*c12c399aSSascha Wildner dpm_entry->MappingInformation = le16toh(dpm_entry-> 1489*c12c399aSSascha Wildner MappingInformation); 1490*c12c399aSSascha Wildner missing_cnt = dpm_entry->MappingInformation & 1491*c12c399aSSascha Wildner MPI2_DRVMAP0_MAPINFO_MISSING_MASK; 1492*c12c399aSSascha Wildner dev_idx = le16toh(dpm_entry->DeviceIndex); 1493*c12c399aSSascha Wildner phy_bits = le32toh(dpm_entry->PhysicalBitsMapping); 1494*c12c399aSSascha Wildner if (sc->ir_firmware && (dev_idx >= start_idx) && 1495*c12c399aSSascha Wildner (dev_idx <= end_idx)) { 1496*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[dev_idx]; 1497*c12c399aSSascha Wildner mt_entry->physical_id = dpm_entry->PhysicalIdentifier.High; 1498*c12c399aSSascha Wildner mt_entry->physical_id = (mt_entry->physical_id << 32) | 1499*c12c399aSSascha Wildner dpm_entry->PhysicalIdentifier.Low; 1500*c12c399aSSascha Wildner mt_entry->channel = MPS_RAID_CHANNEL; 1501*c12c399aSSascha Wildner mt_entry->id = dev_idx; 1502*c12c399aSSascha Wildner mt_entry->missing_count = missing_cnt; 1503*c12c399aSSascha Wildner mt_entry->dpm_entry_num = entry_num; 1504*c12c399aSSascha Wildner mt_entry->device_info = MPS_DEV_RESERVED; 1505*c12c399aSSascha Wildner continue; 1506*c12c399aSSascha Wildner } 1507*c12c399aSSascha Wildner if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1508*c12c399aSSascha Wildner MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 1509*c12c399aSSascha Wildner if (dev_idx < (sc->num_rsvd_entries + 1510*c12c399aSSascha Wildner max_num_phy_ids)) { 1511*c12c399aSSascha Wildner slot_id = 0; 1512*c12c399aSSascha Wildner if (ioc_pg8_flags & 1513*c12c399aSSascha Wildner MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1) 1514*c12c399aSSascha Wildner slot_id = 1; 1515*c12c399aSSascha Wildner num_slots = max_num_phy_ids; 1516*c12c399aSSascha Wildner } else { 1517*c12c399aSSascha Wildner slot_id = 0; 1518*c12c399aSSascha Wildner num_slots = dpm_entry->MappingInformation & 1519*c12c399aSSascha Wildner MPI2_DRVMAP0_MAPINFO_SLOT_MASK; 1520*c12c399aSSascha Wildner num_slots >>= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT; 1521*c12c399aSSascha Wildner } 1522*c12c399aSSascha Wildner enc_idx = sc->num_enc_table_entries; 1523*c12c399aSSascha Wildner if (enc_idx >= sc->max_enclosures) { 1524*c12c399aSSascha Wildner kprintf("%s: enclosure entries exceed max " 1525*c12c399aSSascha Wildner "enclosures of %d\n", __func__, 1526*c12c399aSSascha Wildner sc->max_enclosures); 1527*c12c399aSSascha Wildner break; 1528*c12c399aSSascha Wildner } 1529*c12c399aSSascha Wildner sc->num_enc_table_entries++; 1530*c12c399aSSascha Wildner et_entry = &sc->enclosure_table[enc_idx]; 1531*c12c399aSSascha Wildner physical_id = dpm_entry->PhysicalIdentifier.High; 1532*c12c399aSSascha Wildner et_entry->enclosure_id = (physical_id << 32) | 1533*c12c399aSSascha Wildner dpm_entry->PhysicalIdentifier.Low; 1534*c12c399aSSascha Wildner et_entry->start_index = dev_idx; 1535*c12c399aSSascha Wildner et_entry->dpm_entry_num = entry_num; 1536*c12c399aSSascha Wildner et_entry->num_slots = num_slots; 1537*c12c399aSSascha Wildner et_entry->start_slot = slot_id; 1538*c12c399aSSascha Wildner et_entry->missing_count = missing_cnt; 1539*c12c399aSSascha Wildner et_entry->phy_bits = phy_bits; 1540*c12c399aSSascha Wildner 1541*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[dev_idx]; 1542*c12c399aSSascha Wildner for (map_idx = dev_idx; map_idx < (dev_idx + num_slots); 1543*c12c399aSSascha Wildner map_idx++, mt_entry++) { 1544*c12c399aSSascha Wildner if (mt_entry->dpm_entry_num != 1545*c12c399aSSascha Wildner MPS_DPM_BAD_IDX) { 1546*c12c399aSSascha Wildner kprintf("%s: conflict in mapping table " 1547*c12c399aSSascha Wildner "for enclosure %d\n", __func__, 1548*c12c399aSSascha Wildner enc_idx); 1549*c12c399aSSascha Wildner break; 1550*c12c399aSSascha Wildner } 1551*c12c399aSSascha Wildner physical_id = dpm_entry->PhysicalIdentifier.High; 1552*c12c399aSSascha Wildner mt_entry->physical_id = (physical_id << 32) | 1553*c12c399aSSascha Wildner dpm_entry->PhysicalIdentifier.Low; 1554*c12c399aSSascha Wildner mt_entry->phy_bits = phy_bits; 1555*c12c399aSSascha Wildner mt_entry->channel = 0; 1556*c12c399aSSascha Wildner mt_entry->id = dev_idx; 1557*c12c399aSSascha Wildner mt_entry->dpm_entry_num = entry_num; 1558*c12c399aSSascha Wildner mt_entry->missing_count = missing_cnt; 1559*c12c399aSSascha Wildner mt_entry->device_info = MPS_DEV_RESERVED; 1560*c12c399aSSascha Wildner } 1561*c12c399aSSascha Wildner } else if ((ioc_pg8_flags & 1562*c12c399aSSascha Wildner MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1563*c12c399aSSascha Wildner MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { 1564*c12c399aSSascha Wildner map_idx = dev_idx; 1565*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[map_idx]; 1566*c12c399aSSascha Wildner if (mt_entry->dpm_entry_num != MPS_DPM_BAD_IDX) { 1567*c12c399aSSascha Wildner kprintf("%s: conflict in mapping table for " 1568*c12c399aSSascha Wildner "device %d\n", __func__, map_idx); 1569*c12c399aSSascha Wildner break; 1570*c12c399aSSascha Wildner } 1571*c12c399aSSascha Wildner physical_id = dpm_entry->PhysicalIdentifier.High; 1572*c12c399aSSascha Wildner mt_entry->physical_id = (physical_id << 32) | 1573*c12c399aSSascha Wildner dpm_entry->PhysicalIdentifier.Low; 1574*c12c399aSSascha Wildner mt_entry->phy_bits = phy_bits; 1575*c12c399aSSascha Wildner mt_entry->channel = 0; 1576*c12c399aSSascha Wildner mt_entry->id = dev_idx; 1577*c12c399aSSascha Wildner mt_entry->missing_count = missing_cnt; 1578*c12c399aSSascha Wildner mt_entry->dpm_entry_num = entry_num; 1579*c12c399aSSascha Wildner mt_entry->device_info = MPS_DEV_RESERVED; 1580*c12c399aSSascha Wildner } 1581*c12c399aSSascha Wildner } /*close the loop for DPM table */ 1582*c12c399aSSascha Wildner } 1583*c12c399aSSascha Wildner 1584*c12c399aSSascha Wildner /* 1585*c12c399aSSascha Wildner * mps_mapping_check_devices - start of the day check for device availabilty 1586*c12c399aSSascha Wildner * @sc: per adapter object 1587*c12c399aSSascha Wildner * @sleep_flag: Flag indicating whether this function can sleep or not 1588*c12c399aSSascha Wildner * 1589*c12c399aSSascha Wildner * Returns nothing. 1590*c12c399aSSascha Wildner */ 1591*c12c399aSSascha Wildner void 1592*c12c399aSSascha Wildner mps_mapping_check_devices(struct mps_softc *sc, int sleep_flag) 1593*c12c399aSSascha Wildner { 1594*c12c399aSSascha Wildner u32 i; 1595*c12c399aSSascha Wildner /* u32 cntdn, i; 1596*c12c399aSSascha Wildner u32 timeout = 60;*/ 1597*c12c399aSSascha Wildner struct dev_mapping_table *mt_entry; 1598*c12c399aSSascha Wildner u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1599*c12c399aSSascha Wildner struct enc_mapping_table *et_entry; 1600*c12c399aSSascha Wildner u32 start_idx, end_idx; 1601*c12c399aSSascha Wildner 1602*c12c399aSSascha Wildner /* We need to ucomment this when this function is called 1603*c12c399aSSascha Wildner * from the port enable complete */ 1604*c12c399aSSascha Wildner #if 0 1605*c12c399aSSascha Wildner sc->track_mapping_events = 0; 1606*c12c399aSSascha Wildner cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; 1607*c12c399aSSascha Wildner do { 1608*c12c399aSSascha Wildner if (!sc->pending_map_events) 1609*c12c399aSSascha Wildner break; 1610*c12c399aSSascha Wildner if (sleep_flag == CAN_SLEEP) 1611*c12c399aSSascha Wildner pause("mps_pause", (hz/1000));/* 1msec sleep */ 1612*c12c399aSSascha Wildner else 1613*c12c399aSSascha Wildner DELAY(500); /* 500 useconds delay */ 1614*c12c399aSSascha Wildner } while (--cntdn); 1615*c12c399aSSascha Wildner 1616*c12c399aSSascha Wildner 1617*c12c399aSSascha Wildner if (!cntdn) 1618*c12c399aSSascha Wildner kprintf("%s: there are %d" 1619*c12c399aSSascha Wildner " pending events after %d seconds of delay\n", 1620*c12c399aSSascha Wildner __func__, sc->pending_map_events, timeout); 1621*c12c399aSSascha Wildner #endif 1622*c12c399aSSascha Wildner sc->pending_map_events = 0; 1623*c12c399aSSascha Wildner 1624*c12c399aSSascha Wildner if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1625*c12c399aSSascha Wildner MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 1626*c12c399aSSascha Wildner et_entry = sc->enclosure_table; 1627*c12c399aSSascha Wildner for (i = 0; i < sc->num_enc_table_entries; i++, et_entry++) { 1628*c12c399aSSascha Wildner if (!et_entry->init_complete) { 1629*c12c399aSSascha Wildner if (et_entry->missing_count < 1630*c12c399aSSascha Wildner MPS_MAX_MISSING_COUNT) { 1631*c12c399aSSascha Wildner et_entry->missing_count++; 1632*c12c399aSSascha Wildner if (et_entry->dpm_entry_num != 1633*c12c399aSSascha Wildner MPS_DPM_BAD_IDX) 1634*c12c399aSSascha Wildner _mapping_commit_enc_entry(sc, 1635*c12c399aSSascha Wildner et_entry); 1636*c12c399aSSascha Wildner } 1637*c12c399aSSascha Wildner et_entry->init_complete = 1; 1638*c12c399aSSascha Wildner } 1639*c12c399aSSascha Wildner } 1640*c12c399aSSascha Wildner if (!sc->ir_firmware) 1641*c12c399aSSascha Wildner return; 1642*c12c399aSSascha Wildner _mapping_get_ir_maprange(sc, &start_idx, &end_idx); 1643*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[start_idx]; 1644*c12c399aSSascha Wildner for (i = start_idx; i < (end_idx + 1); i++, mt_entry++) { 1645*c12c399aSSascha Wildner if (mt_entry->device_info & MPS_DEV_RESERVED 1646*c12c399aSSascha Wildner && !mt_entry->physical_id) 1647*c12c399aSSascha Wildner mt_entry->init_complete = 1; 1648*c12c399aSSascha Wildner else if (mt_entry->device_info & MPS_DEV_RESERVED) { 1649*c12c399aSSascha Wildner if (!mt_entry->init_complete) { 1650*c12c399aSSascha Wildner if (mt_entry->missing_count < 1651*c12c399aSSascha Wildner MPS_MAX_MISSING_COUNT) { 1652*c12c399aSSascha Wildner mt_entry->missing_count++; 1653*c12c399aSSascha Wildner if (mt_entry->dpm_entry_num != 1654*c12c399aSSascha Wildner MPS_DPM_BAD_IDX) 1655*c12c399aSSascha Wildner _mapping_commit_map_entry(sc, 1656*c12c399aSSascha Wildner mt_entry); 1657*c12c399aSSascha Wildner } 1658*c12c399aSSascha Wildner mt_entry->init_complete = 1; 1659*c12c399aSSascha Wildner } 1660*c12c399aSSascha Wildner } 1661*c12c399aSSascha Wildner } 1662*c12c399aSSascha Wildner } else if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1663*c12c399aSSascha Wildner MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { 1664*c12c399aSSascha Wildner mt_entry = sc->mapping_table; 1665*c12c399aSSascha Wildner for (i = 0; i < sc->max_devices; i++, mt_entry++) { 1666*c12c399aSSascha Wildner if (mt_entry->device_info & MPS_DEV_RESERVED 1667*c12c399aSSascha Wildner && !mt_entry->physical_id) 1668*c12c399aSSascha Wildner mt_entry->init_complete = 1; 1669*c12c399aSSascha Wildner else if (mt_entry->device_info & MPS_DEV_RESERVED) { 1670*c12c399aSSascha Wildner if (!mt_entry->init_complete) { 1671*c12c399aSSascha Wildner if (mt_entry->missing_count < 1672*c12c399aSSascha Wildner MPS_MAX_MISSING_COUNT) { 1673*c12c399aSSascha Wildner mt_entry->missing_count++; 1674*c12c399aSSascha Wildner if (mt_entry->dpm_entry_num != 1675*c12c399aSSascha Wildner MPS_DPM_BAD_IDX) 1676*c12c399aSSascha Wildner _mapping_commit_map_entry(sc, 1677*c12c399aSSascha Wildner mt_entry); 1678*c12c399aSSascha Wildner } 1679*c12c399aSSascha Wildner mt_entry->init_complete = 1; 1680*c12c399aSSascha Wildner } 1681*c12c399aSSascha Wildner } 1682*c12c399aSSascha Wildner } 1683*c12c399aSSascha Wildner } 1684*c12c399aSSascha Wildner } 1685*c12c399aSSascha Wildner 1686*c12c399aSSascha Wildner 1687*c12c399aSSascha Wildner /** 1688*c12c399aSSascha Wildner * mps_mapping_is_reinit_required - check whether event replay required 1689*c12c399aSSascha Wildner * @sc: per adapter object 1690*c12c399aSSascha Wildner * 1691*c12c399aSSascha Wildner * Checks the per ioc flags and decide whether reinit of events required 1692*c12c399aSSascha Wildner * 1693*c12c399aSSascha Wildner * Returns 1 for reinit of ioc 0 for not. 1694*c12c399aSSascha Wildner */ 1695*c12c399aSSascha Wildner int mps_mapping_is_reinit_required(struct mps_softc *sc) 1696*c12c399aSSascha Wildner { 1697*c12c399aSSascha Wildner if (!sc->mt_full_retry && sc->mt_add_device_failed) { 1698*c12c399aSSascha Wildner sc->mt_full_retry = 1; 1699*c12c399aSSascha Wildner sc->mt_add_device_failed = 0; 1700*c12c399aSSascha Wildner _mapping_flush_dpm_pages(sc); 1701*c12c399aSSascha Wildner return 1; 1702*c12c399aSSascha Wildner } 1703*c12c399aSSascha Wildner sc->mt_full_retry = 1; 1704*c12c399aSSascha Wildner return 0; 1705*c12c399aSSascha Wildner } 1706*c12c399aSSascha Wildner 1707*c12c399aSSascha Wildner /** 1708*c12c399aSSascha Wildner * mps_mapping_initialize - initialize mapping tables 1709*c12c399aSSascha Wildner * @sc: per adapter object 1710*c12c399aSSascha Wildner * 1711*c12c399aSSascha Wildner * Read controller persitant mapping tables into internal data area. 1712*c12c399aSSascha Wildner * 1713*c12c399aSSascha Wildner * Return 0 for success or non-zero for failure. 1714*c12c399aSSascha Wildner */ 1715*c12c399aSSascha Wildner int 1716*c12c399aSSascha Wildner mps_mapping_initialize(struct mps_softc *sc) 1717*c12c399aSSascha Wildner { 1718*c12c399aSSascha Wildner uint16_t volume_mapping_flags, dpm_pg0_sz; 1719*c12c399aSSascha Wildner uint32_t i; 1720*c12c399aSSascha Wildner Mpi2ConfigReply_t mpi_reply; 1721*c12c399aSSascha Wildner int error; 1722*c12c399aSSascha Wildner uint8_t retry_count; 1723*c12c399aSSascha Wildner uint16_t ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1724*c12c399aSSascha Wildner 1725*c12c399aSSascha Wildner /* The additional 1 accounts for the virtual enclosure 1726*c12c399aSSascha Wildner * created for the controller 1727*c12c399aSSascha Wildner */ 1728*c12c399aSSascha Wildner sc->max_enclosures = sc->facts->MaxEnclosures + 1; 1729*c12c399aSSascha Wildner sc->max_expanders = sc->facts->MaxSasExpanders; 1730*c12c399aSSascha Wildner sc->max_volumes = sc->facts->MaxVolumes; 1731*c12c399aSSascha Wildner sc->max_devices = sc->facts->MaxTargets + sc->max_volumes; 1732*c12c399aSSascha Wildner sc->pending_map_events = 0; 1733*c12c399aSSascha Wildner sc->num_enc_table_entries = 0; 1734*c12c399aSSascha Wildner sc->num_rsvd_entries = 0; 1735*c12c399aSSascha Wildner sc->num_channels = 1; 1736*c12c399aSSascha Wildner sc->max_dpm_entries = sc->ioc_pg8.MaxPersistentEntries; 1737*c12c399aSSascha Wildner sc->is_dpm_enable = (sc->max_dpm_entries) ? 1 : 0; 1738*c12c399aSSascha Wildner sc->track_mapping_events = 0; 1739*c12c399aSSascha Wildner 1740*c12c399aSSascha Wildner if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING) 1741*c12c399aSSascha Wildner sc->is_dpm_enable = 0; 1742*c12c399aSSascha Wildner 1743*c12c399aSSascha Wildner if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0) 1744*c12c399aSSascha Wildner sc->num_rsvd_entries = 1; 1745*c12c399aSSascha Wildner 1746*c12c399aSSascha Wildner volume_mapping_flags = sc->ioc_pg8.IRVolumeMappingFlags & 1747*c12c399aSSascha Wildner MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; 1748*c12c399aSSascha Wildner if (sc->ir_firmware && (volume_mapping_flags == 1749*c12c399aSSascha Wildner MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING)) 1750*c12c399aSSascha Wildner sc->num_rsvd_entries += sc->max_volumes; 1751*c12c399aSSascha Wildner 1752*c12c399aSSascha Wildner error = mps_mapping_allocate_memory(sc); 1753*c12c399aSSascha Wildner if (error) 1754*c12c399aSSascha Wildner return (error); 1755*c12c399aSSascha Wildner 1756*c12c399aSSascha Wildner for (i = 0; i < sc->max_devices; i++) 1757*c12c399aSSascha Wildner _mapping_clear_map_entry(sc->mapping_table + i); 1758*c12c399aSSascha Wildner 1759*c12c399aSSascha Wildner for (i = 0; i < sc->max_enclosures; i++) 1760*c12c399aSSascha Wildner _mapping_clear_enc_entry(sc->enclosure_table + i); 1761*c12c399aSSascha Wildner 1762*c12c399aSSascha Wildner for (i = 0; i < sc->max_devices; i++) { 1763*c12c399aSSascha Wildner sc->removal_table[i].dev_handle = 0; 1764*c12c399aSSascha Wildner sc->removal_table[i].dpm_entry_num = MPS_DPM_BAD_IDX; 1765*c12c399aSSascha Wildner } 1766*c12c399aSSascha Wildner 1767*c12c399aSSascha Wildner memset(sc->dpm_entry_used, 0, sc->max_dpm_entries); 1768*c12c399aSSascha Wildner memset(sc->dpm_flush_entry, 0, sc->max_dpm_entries); 1769*c12c399aSSascha Wildner 1770*c12c399aSSascha Wildner if (sc->is_dpm_enable) { 1771*c12c399aSSascha Wildner dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) + 1772*c12c399aSSascha Wildner (sc->max_dpm_entries * 1773*c12c399aSSascha Wildner sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY)); 1774*c12c399aSSascha Wildner retry_count = 0; 1775*c12c399aSSascha Wildner 1776*c12c399aSSascha Wildner retry_read_dpm: 1777*c12c399aSSascha Wildner if (mps_config_get_dpm_pg0(sc, &mpi_reply, sc->dpm_pg0, 1778*c12c399aSSascha Wildner dpm_pg0_sz)) { 1779*c12c399aSSascha Wildner kprintf("%s: dpm page read failed; disabling dpm\n", 1780*c12c399aSSascha Wildner __func__); 1781*c12c399aSSascha Wildner if (retry_count < 3) { 1782*c12c399aSSascha Wildner retry_count++; 1783*c12c399aSSascha Wildner goto retry_read_dpm; 1784*c12c399aSSascha Wildner } 1785*c12c399aSSascha Wildner sc->is_dpm_enable = 0; 1786*c12c399aSSascha Wildner } 1787*c12c399aSSascha Wildner } 1788*c12c399aSSascha Wildner 1789*c12c399aSSascha Wildner if (sc->is_dpm_enable) 1790*c12c399aSSascha Wildner _mapping_process_dpm_pg0(sc); 1791*c12c399aSSascha Wildner 1792*c12c399aSSascha Wildner sc->track_mapping_events = 1; 1793*c12c399aSSascha Wildner return 0; 1794*c12c399aSSascha Wildner } 1795*c12c399aSSascha Wildner 1796*c12c399aSSascha Wildner /** 1797*c12c399aSSascha Wildner * mps_mapping_exit - clear mapping table and associated memory 1798*c12c399aSSascha Wildner * @sc: per adapter object 1799*c12c399aSSascha Wildner * 1800*c12c399aSSascha Wildner * Returns nothing. 1801*c12c399aSSascha Wildner */ 1802*c12c399aSSascha Wildner void 1803*c12c399aSSascha Wildner mps_mapping_exit(struct mps_softc *sc) 1804*c12c399aSSascha Wildner { 1805*c12c399aSSascha Wildner _mapping_flush_dpm_pages(sc); 1806*c12c399aSSascha Wildner mps_mapping_free_memory(sc); 1807*c12c399aSSascha Wildner } 1808*c12c399aSSascha Wildner 1809*c12c399aSSascha Wildner /** 1810*c12c399aSSascha Wildner * mps_mapping_get_sas_id - assign a target id for sas device 1811*c12c399aSSascha Wildner * @sc: per adapter object 1812*c12c399aSSascha Wildner * @sas_address: sas address of the device 1813*c12c399aSSascha Wildner * @handle: device handle 1814*c12c399aSSascha Wildner * 1815*c12c399aSSascha Wildner * Returns valid ID on success or BAD_ID. 1816*c12c399aSSascha Wildner */ 1817*c12c399aSSascha Wildner unsigned int 1818*c12c399aSSascha Wildner mps_mapping_get_sas_id(struct mps_softc *sc, uint64_t sas_address, u16 handle) 1819*c12c399aSSascha Wildner { 1820*c12c399aSSascha Wildner u32 map_idx; 1821*c12c399aSSascha Wildner struct dev_mapping_table *mt_entry; 1822*c12c399aSSascha Wildner 1823*c12c399aSSascha Wildner for (map_idx = 0; map_idx < sc->max_devices; map_idx++) { 1824*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[map_idx]; 1825*c12c399aSSascha Wildner if (mt_entry->dev_handle == handle && mt_entry->physical_id == 1826*c12c399aSSascha Wildner sas_address) 1827*c12c399aSSascha Wildner return mt_entry->id; 1828*c12c399aSSascha Wildner } 1829*c12c399aSSascha Wildner 1830*c12c399aSSascha Wildner return MPS_MAP_BAD_ID; 1831*c12c399aSSascha Wildner } 1832*c12c399aSSascha Wildner 1833*c12c399aSSascha Wildner /** 1834*c12c399aSSascha Wildner * mps_mapping_get_sas_id_from_handle - find a target id in mapping table using 1835*c12c399aSSascha Wildner * only the dev handle. This is just a wrapper function for the local function 1836*c12c399aSSascha Wildner * _mapping_get_mt_idx_from_handle. 1837*c12c399aSSascha Wildner * @sc: per adapter object 1838*c12c399aSSascha Wildner * @handle: device handle 1839*c12c399aSSascha Wildner * 1840*c12c399aSSascha Wildner * Returns valid ID on success or BAD_ID. 1841*c12c399aSSascha Wildner */ 1842*c12c399aSSascha Wildner unsigned int 1843*c12c399aSSascha Wildner mps_mapping_get_sas_id_from_handle(struct mps_softc *sc, u16 handle) 1844*c12c399aSSascha Wildner { 1845*c12c399aSSascha Wildner return (_mapping_get_mt_idx_from_handle(sc, handle)); 1846*c12c399aSSascha Wildner } 1847*c12c399aSSascha Wildner 1848*c12c399aSSascha Wildner /** 1849*c12c399aSSascha Wildner * mps_mapping_get_raid_id - assign a target id for raid device 1850*c12c399aSSascha Wildner * @sc: per adapter object 1851*c12c399aSSascha Wildner * @wwid: world wide identifier for raid volume 1852*c12c399aSSascha Wildner * @handle: device handle 1853*c12c399aSSascha Wildner * 1854*c12c399aSSascha Wildner * Returns valid ID on success or BAD_ID. 1855*c12c399aSSascha Wildner */ 1856*c12c399aSSascha Wildner unsigned int 1857*c12c399aSSascha Wildner mps_mapping_get_raid_id(struct mps_softc *sc, u64 wwid, u16 handle) 1858*c12c399aSSascha Wildner { 1859*c12c399aSSascha Wildner u32 map_idx; 1860*c12c399aSSascha Wildner struct dev_mapping_table *mt_entry; 1861*c12c399aSSascha Wildner 1862*c12c399aSSascha Wildner for (map_idx = 0; map_idx < sc->max_devices; map_idx++) { 1863*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[map_idx]; 1864*c12c399aSSascha Wildner if (mt_entry->dev_handle == handle && mt_entry->physical_id == 1865*c12c399aSSascha Wildner wwid) 1866*c12c399aSSascha Wildner return mt_entry->id; 1867*c12c399aSSascha Wildner } 1868*c12c399aSSascha Wildner 1869*c12c399aSSascha Wildner return MPS_MAP_BAD_ID; 1870*c12c399aSSascha Wildner } 1871*c12c399aSSascha Wildner 1872*c12c399aSSascha Wildner /** 1873*c12c399aSSascha Wildner * mps_mapping_get_raid_id_from_handle - find raid device in mapping table 1874*c12c399aSSascha Wildner * using only the volume dev handle. This is just a wrapper function for the 1875*c12c399aSSascha Wildner * local function _mapping_get_ir_mt_idx_from_handle. 1876*c12c399aSSascha Wildner * @sc: per adapter object 1877*c12c399aSSascha Wildner * @volHandle: volume device handle 1878*c12c399aSSascha Wildner * 1879*c12c399aSSascha Wildner * Returns valid ID on success or BAD_ID. 1880*c12c399aSSascha Wildner */ 1881*c12c399aSSascha Wildner unsigned int 1882*c12c399aSSascha Wildner mps_mapping_get_raid_id_from_handle(struct mps_softc *sc, u16 volHandle) 1883*c12c399aSSascha Wildner { 1884*c12c399aSSascha Wildner return (_mapping_get_ir_mt_idx_from_handle(sc, volHandle)); 1885*c12c399aSSascha Wildner } 1886*c12c399aSSascha Wildner 1887*c12c399aSSascha Wildner /** 1888*c12c399aSSascha Wildner * mps_mapping_enclosure_dev_status_change_event - handle enclosure events 1889*c12c399aSSascha Wildner * @sc: per adapter object 1890*c12c399aSSascha Wildner * @event_data: event data payload 1891*c12c399aSSascha Wildner * 1892*c12c399aSSascha Wildner * Return nothing. 1893*c12c399aSSascha Wildner */ 1894*c12c399aSSascha Wildner void 1895*c12c399aSSascha Wildner mps_mapping_enclosure_dev_status_change_event(struct mps_softc *sc, 1896*c12c399aSSascha Wildner Mpi2EventDataSasEnclDevStatusChange_t *event_data) 1897*c12c399aSSascha Wildner { 1898*c12c399aSSascha Wildner u8 enc_idx, missing_count; 1899*c12c399aSSascha Wildner struct enc_mapping_table *et_entry; 1900*c12c399aSSascha Wildner Mpi2DriverMap0Entry_t *dpm_entry; 1901*c12c399aSSascha Wildner u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1902*c12c399aSSascha Wildner u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT; 1903*c12c399aSSascha Wildner u8 update_phy_bits = 0; 1904*c12c399aSSascha Wildner u32 saved_phy_bits; 1905*c12c399aSSascha Wildner uint64_t temp64_var; 1906*c12c399aSSascha Wildner 1907*c12c399aSSascha Wildner if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) != 1908*c12c399aSSascha Wildner MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) 1909*c12c399aSSascha Wildner goto out; 1910*c12c399aSSascha Wildner 1911*c12c399aSSascha Wildner dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 + 1912*c12c399aSSascha Wildner sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 1913*c12c399aSSascha Wildner 1914*c12c399aSSascha Wildner if (event_data->ReasonCode == MPI2_EVENT_SAS_ENCL_RC_ADDED) { 1915*c12c399aSSascha Wildner if (!event_data->NumSlots) { 1916*c12c399aSSascha Wildner kprintf("%s: enclosure with handle = 0x%x reported 0 " 1917*c12c399aSSascha Wildner "slots\n", __func__, 1918*c12c399aSSascha Wildner le16toh(event_data->EnclosureHandle)); 1919*c12c399aSSascha Wildner goto out; 1920*c12c399aSSascha Wildner } 1921*c12c399aSSascha Wildner temp64_var = event_data->EnclosureLogicalID.High; 1922*c12c399aSSascha Wildner temp64_var = (temp64_var << 32) | 1923*c12c399aSSascha Wildner event_data->EnclosureLogicalID.Low; 1924*c12c399aSSascha Wildner enc_idx = _mapping_get_enc_idx_from_id(sc, temp64_var, 1925*c12c399aSSascha Wildner event_data->PhyBits); 1926*c12c399aSSascha Wildner if (enc_idx != MPS_ENCTABLE_BAD_IDX) { 1927*c12c399aSSascha Wildner et_entry = &sc->enclosure_table[enc_idx]; 1928*c12c399aSSascha Wildner if (et_entry->init_complete && 1929*c12c399aSSascha Wildner !et_entry->missing_count) { 1930*c12c399aSSascha Wildner kprintf("%s: enclosure %d is already present " 1931*c12c399aSSascha Wildner "with handle = 0x%x\n",__func__, enc_idx, 1932*c12c399aSSascha Wildner et_entry->enc_handle); 1933*c12c399aSSascha Wildner goto out; 1934*c12c399aSSascha Wildner } 1935*c12c399aSSascha Wildner et_entry->enc_handle = le16toh(event_data-> 1936*c12c399aSSascha Wildner EnclosureHandle); 1937*c12c399aSSascha Wildner et_entry->start_slot = le16toh(event_data->StartSlot); 1938*c12c399aSSascha Wildner saved_phy_bits = et_entry->phy_bits; 1939*c12c399aSSascha Wildner et_entry->phy_bits |= le32toh(event_data->PhyBits); 1940*c12c399aSSascha Wildner if (saved_phy_bits != et_entry->phy_bits) 1941*c12c399aSSascha Wildner update_phy_bits = 1; 1942*c12c399aSSascha Wildner if (et_entry->missing_count || update_phy_bits) { 1943*c12c399aSSascha Wildner et_entry->missing_count = 0; 1944*c12c399aSSascha Wildner if (sc->is_dpm_enable && 1945*c12c399aSSascha Wildner et_entry->dpm_entry_num != 1946*c12c399aSSascha Wildner MPS_DPM_BAD_IDX) { 1947*c12c399aSSascha Wildner dpm_entry += et_entry->dpm_entry_num; 1948*c12c399aSSascha Wildner missing_count = 1949*c12c399aSSascha Wildner (u8)(dpm_entry->MappingInformation & 1950*c12c399aSSascha Wildner MPI2_DRVMAP0_MAPINFO_MISSING_MASK); 1951*c12c399aSSascha Wildner if (!et_entry->init_complete && ( 1952*c12c399aSSascha Wildner missing_count || update_phy_bits)) { 1953*c12c399aSSascha Wildner dpm_entry->MappingInformation 1954*c12c399aSSascha Wildner = et_entry->num_slots; 1955*c12c399aSSascha Wildner dpm_entry->MappingInformation 1956*c12c399aSSascha Wildner <<= map_shift; 1957*c12c399aSSascha Wildner dpm_entry->PhysicalBitsMapping 1958*c12c399aSSascha Wildner = et_entry->phy_bits; 1959*c12c399aSSascha Wildner sc->dpm_flush_entry[et_entry-> 1960*c12c399aSSascha Wildner dpm_entry_num] = 1; 1961*c12c399aSSascha Wildner } 1962*c12c399aSSascha Wildner } 1963*c12c399aSSascha Wildner } 1964*c12c399aSSascha Wildner } else { 1965*c12c399aSSascha Wildner enc_idx = sc->num_enc_table_entries; 1966*c12c399aSSascha Wildner if (enc_idx >= sc->max_enclosures) { 1967*c12c399aSSascha Wildner kprintf("%s: enclosure can not be added; " 1968*c12c399aSSascha Wildner "mapping table is full\n", __func__); 1969*c12c399aSSascha Wildner goto out; 1970*c12c399aSSascha Wildner } 1971*c12c399aSSascha Wildner sc->num_enc_table_entries++; 1972*c12c399aSSascha Wildner et_entry = &sc->enclosure_table[enc_idx]; 1973*c12c399aSSascha Wildner et_entry->enc_handle = le16toh(event_data-> 1974*c12c399aSSascha Wildner EnclosureHandle); 1975*c12c399aSSascha Wildner et_entry->enclosure_id = event_data-> 1976*c12c399aSSascha Wildner EnclosureLogicalID.High; 1977*c12c399aSSascha Wildner et_entry->enclosure_id = ( et_entry->enclosure_id << 1978*c12c399aSSascha Wildner 32) | event_data->EnclosureLogicalID.Low; 1979*c12c399aSSascha Wildner et_entry->start_index = MPS_MAPTABLE_BAD_IDX; 1980*c12c399aSSascha Wildner et_entry->dpm_entry_num = MPS_DPM_BAD_IDX; 1981*c12c399aSSascha Wildner et_entry->num_slots = le16toh(event_data->NumSlots); 1982*c12c399aSSascha Wildner et_entry->start_slot = le16toh(event_data->StartSlot); 1983*c12c399aSSascha Wildner et_entry->phy_bits = le32toh(event_data->PhyBits); 1984*c12c399aSSascha Wildner } 1985*c12c399aSSascha Wildner et_entry->init_complete = 1; 1986*c12c399aSSascha Wildner } else if (event_data->ReasonCode == 1987*c12c399aSSascha Wildner MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING) { 1988*c12c399aSSascha Wildner enc_idx = _mapping_get_enc_idx_from_handle(sc, 1989*c12c399aSSascha Wildner le16toh(event_data->EnclosureHandle)); 1990*c12c399aSSascha Wildner if (enc_idx == MPS_ENCTABLE_BAD_IDX) { 1991*c12c399aSSascha Wildner kprintf("%s: cannot unmap enclosure %d because it has " 1992*c12c399aSSascha Wildner "already been deleted", __func__, enc_idx); 1993*c12c399aSSascha Wildner goto out; 1994*c12c399aSSascha Wildner } 1995*c12c399aSSascha Wildner et_entry = &sc->enclosure_table[enc_idx]; 1996*c12c399aSSascha Wildner if (!et_entry->init_complete) { 1997*c12c399aSSascha Wildner if (et_entry->missing_count < MPS_MAX_MISSING_COUNT) 1998*c12c399aSSascha Wildner et_entry->missing_count++; 1999*c12c399aSSascha Wildner else 2000*c12c399aSSascha Wildner et_entry->init_complete = 1; 2001*c12c399aSSascha Wildner } 2002*c12c399aSSascha Wildner if (!et_entry->missing_count) 2003*c12c399aSSascha Wildner et_entry->missing_count++; 2004*c12c399aSSascha Wildner if (sc->is_dpm_enable && !et_entry->init_complete && 2005*c12c399aSSascha Wildner et_entry->dpm_entry_num != MPS_DPM_BAD_IDX) { 2006*c12c399aSSascha Wildner dpm_entry += et_entry->dpm_entry_num; 2007*c12c399aSSascha Wildner dpm_entry->MappingInformation = et_entry->num_slots; 2008*c12c399aSSascha Wildner dpm_entry->MappingInformation <<= map_shift; 2009*c12c399aSSascha Wildner dpm_entry->MappingInformation |= 2010*c12c399aSSascha Wildner et_entry->missing_count; 2011*c12c399aSSascha Wildner sc->dpm_flush_entry[et_entry->dpm_entry_num] = 1; 2012*c12c399aSSascha Wildner } 2013*c12c399aSSascha Wildner et_entry->init_complete = 1; 2014*c12c399aSSascha Wildner } 2015*c12c399aSSascha Wildner 2016*c12c399aSSascha Wildner out: 2017*c12c399aSSascha Wildner _mapping_flush_dpm_pages(sc); 2018*c12c399aSSascha Wildner if (sc->pending_map_events) 2019*c12c399aSSascha Wildner sc->pending_map_events--; 2020*c12c399aSSascha Wildner } 2021*c12c399aSSascha Wildner 2022*c12c399aSSascha Wildner /** 2023*c12c399aSSascha Wildner * mps_mapping_topology_change_event - handle topology change events 2024*c12c399aSSascha Wildner * @sc: per adapter object 2025*c12c399aSSascha Wildner * @event_data: event data payload 2026*c12c399aSSascha Wildner * 2027*c12c399aSSascha Wildner * Returns nothing. 2028*c12c399aSSascha Wildner */ 2029*c12c399aSSascha Wildner void 2030*c12c399aSSascha Wildner mps_mapping_topology_change_event(struct mps_softc *sc, 2031*c12c399aSSascha Wildner Mpi2EventDataSasTopologyChangeList_t *event_data) 2032*c12c399aSSascha Wildner { 2033*c12c399aSSascha Wildner struct _map_topology_change topo_change; 2034*c12c399aSSascha Wildner struct _map_phy_change *phy_change; 2035*c12c399aSSascha Wildner Mpi2EventSasTopoPhyEntry_t *event_phy_change; 2036*c12c399aSSascha Wildner u8 i, num_entries; 2037*c12c399aSSascha Wildner 2038*c12c399aSSascha Wildner topo_change.enc_handle = le16toh(event_data->EnclosureHandle); 2039*c12c399aSSascha Wildner topo_change.exp_handle = le16toh(event_data->ExpanderDevHandle); 2040*c12c399aSSascha Wildner num_entries = event_data->NumEntries; 2041*c12c399aSSascha Wildner topo_change.num_entries = num_entries; 2042*c12c399aSSascha Wildner topo_change.start_phy_num = event_data->StartPhyNum; 2043*c12c399aSSascha Wildner topo_change.num_phys = event_data->NumPhys; 2044*c12c399aSSascha Wildner topo_change.exp_status = event_data->ExpStatus; 2045*c12c399aSSascha Wildner event_phy_change = event_data->PHY; 2046*c12c399aSSascha Wildner topo_change.phy_details = NULL; 2047*c12c399aSSascha Wildner 2048*c12c399aSSascha Wildner if (!num_entries) 2049*c12c399aSSascha Wildner goto out; 2050*c12c399aSSascha Wildner phy_change = kmalloc(sizeof(struct _map_phy_change) * num_entries, 2051*c12c399aSSascha Wildner M_MPT2, M_NOWAIT|M_ZERO); 2052*c12c399aSSascha Wildner topo_change.phy_details = phy_change; 2053*c12c399aSSascha Wildner if (!phy_change) 2054*c12c399aSSascha Wildner goto out; 2055*c12c399aSSascha Wildner for (i = 0; i < num_entries; i++, event_phy_change++, phy_change++) { 2056*c12c399aSSascha Wildner phy_change->dev_handle = le16toh(event_phy_change-> 2057*c12c399aSSascha Wildner AttachedDevHandle); 2058*c12c399aSSascha Wildner phy_change->reason = event_phy_change->PhyStatus & 2059*c12c399aSSascha Wildner MPI2_EVENT_SAS_TOPO_RC_MASK; 2060*c12c399aSSascha Wildner } 2061*c12c399aSSascha Wildner _mapping_update_missing_count(sc, &topo_change); 2062*c12c399aSSascha Wildner _mapping_get_dev_info(sc, &topo_change); 2063*c12c399aSSascha Wildner _mapping_clear_removed_entries(sc); 2064*c12c399aSSascha Wildner _mapping_add_new_device(sc, &topo_change); 2065*c12c399aSSascha Wildner 2066*c12c399aSSascha Wildner out: 2067*c12c399aSSascha Wildner kfree(topo_change.phy_details, M_MPT2); 2068*c12c399aSSascha Wildner _mapping_flush_dpm_pages(sc); 2069*c12c399aSSascha Wildner if (sc->pending_map_events) 2070*c12c399aSSascha Wildner sc->pending_map_events--; 2071*c12c399aSSascha Wildner } 2072*c12c399aSSascha Wildner 2073*c12c399aSSascha Wildner /** 2074*c12c399aSSascha Wildner * _mapping_check_update_ir_mt_idx - Check and update IR map table index 2075*c12c399aSSascha Wildner * @sc: per adapter object 2076*c12c399aSSascha Wildner * @event_data: event data payload 2077*c12c399aSSascha Wildner * @evt_idx: current event index 2078*c12c399aSSascha Wildner * @map_idx: current index and the place holder for new map table index 2079*c12c399aSSascha Wildner * @wwid_table: world wide name for volumes in the element table 2080*c12c399aSSascha Wildner * 2081*c12c399aSSascha Wildner * pass through IR events and find whether any events matches and if so 2082*c12c399aSSascha Wildner * tries to find new index if not returns failure 2083*c12c399aSSascha Wildner * 2084*c12c399aSSascha Wildner * Returns 0 on success and 1 on failure 2085*c12c399aSSascha Wildner */ 2086*c12c399aSSascha Wildner static int 2087*c12c399aSSascha Wildner _mapping_check_update_ir_mt_idx(struct mps_softc *sc, 2088*c12c399aSSascha Wildner Mpi2EventDataIrConfigChangeList_t *event_data, int evt_idx, u32 *map_idx, 2089*c12c399aSSascha Wildner u64 *wwid_table) 2090*c12c399aSSascha Wildner { 2091*c12c399aSSascha Wildner struct dev_mapping_table *mt_entry; 2092*c12c399aSSascha Wildner u32 st_idx, end_idx, mt_idx = *map_idx; 2093*c12c399aSSascha Wildner u8 match = 0; 2094*c12c399aSSascha Wildner Mpi2EventIrConfigElement_t *element; 2095*c12c399aSSascha Wildner u16 element_flags; 2096*c12c399aSSascha Wildner int i; 2097*c12c399aSSascha Wildner 2098*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[mt_idx]; 2099*c12c399aSSascha Wildner _mapping_get_ir_maprange(sc, &st_idx, &end_idx); 2100*c12c399aSSascha Wildner search_again: 2101*c12c399aSSascha Wildner match = 0; 2102*c12c399aSSascha Wildner for (i = evt_idx + 1; i < event_data->NumElements; i++) { 2103*c12c399aSSascha Wildner element = (Mpi2EventIrConfigElement_t *) 2104*c12c399aSSascha Wildner &event_data->ConfigElement[i]; 2105*c12c399aSSascha Wildner element_flags = le16toh(element->ElementFlags); 2106*c12c399aSSascha Wildner if ((element_flags & 2107*c12c399aSSascha Wildner MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK) != 2108*c12c399aSSascha Wildner MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT) 2109*c12c399aSSascha Wildner continue; 2110*c12c399aSSascha Wildner if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_ADDED || 2111*c12c399aSSascha Wildner element->ReasonCode == 2112*c12c399aSSascha Wildner MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) { 2113*c12c399aSSascha Wildner if (mt_entry->physical_id == wwid_table[i]) { 2114*c12c399aSSascha Wildner match = 1; 2115*c12c399aSSascha Wildner break; 2116*c12c399aSSascha Wildner } 2117*c12c399aSSascha Wildner } 2118*c12c399aSSascha Wildner } 2119*c12c399aSSascha Wildner 2120*c12c399aSSascha Wildner if (match) { 2121*c12c399aSSascha Wildner do { 2122*c12c399aSSascha Wildner mt_idx++; 2123*c12c399aSSascha Wildner if (mt_idx > end_idx) 2124*c12c399aSSascha Wildner return 1; 2125*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[mt_idx]; 2126*c12c399aSSascha Wildner } while (mt_entry->device_info & MPS_MAP_IN_USE); 2127*c12c399aSSascha Wildner goto search_again; 2128*c12c399aSSascha Wildner } 2129*c12c399aSSascha Wildner *map_idx = mt_idx; 2130*c12c399aSSascha Wildner return 0; 2131*c12c399aSSascha Wildner } 2132*c12c399aSSascha Wildner 2133*c12c399aSSascha Wildner /** 2134*c12c399aSSascha Wildner * mps_mapping_ir_config_change_event - handle IR config change list events 2135*c12c399aSSascha Wildner * @sc: per adapter object 2136*c12c399aSSascha Wildner * @event_data: event data payload 2137*c12c399aSSascha Wildner * 2138*c12c399aSSascha Wildner * Returns nothing. 2139*c12c399aSSascha Wildner */ 2140*c12c399aSSascha Wildner void 2141*c12c399aSSascha Wildner mps_mapping_ir_config_change_event(struct mps_softc *sc, 2142*c12c399aSSascha Wildner Mpi2EventDataIrConfigChangeList_t *event_data) 2143*c12c399aSSascha Wildner { 2144*c12c399aSSascha Wildner Mpi2EventIrConfigElement_t *element; 2145*c12c399aSSascha Wildner int i; 2146*c12c399aSSascha Wildner u64 *wwid_table; 2147*c12c399aSSascha Wildner u32 map_idx, flags; 2148*c12c399aSSascha Wildner struct dev_mapping_table *mt_entry; 2149*c12c399aSSascha Wildner u16 element_flags; 2150*c12c399aSSascha Wildner u8 log_full_error = 0; 2151*c12c399aSSascha Wildner 2152*c12c399aSSascha Wildner wwid_table = kmalloc(sizeof(u64) * event_data->NumElements, M_MPT2, 2153*c12c399aSSascha Wildner M_NOWAIT | M_ZERO); 2154*c12c399aSSascha Wildner if (!wwid_table) 2155*c12c399aSSascha Wildner goto out; 2156*c12c399aSSascha Wildner element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; 2157*c12c399aSSascha Wildner flags = le32toh(event_data->Flags); 2158*c12c399aSSascha Wildner for (i = 0; i < event_data->NumElements; i++, element++) { 2159*c12c399aSSascha Wildner element_flags = le16toh(element->ElementFlags); 2160*c12c399aSSascha Wildner if ((element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_ADDED) && 2161*c12c399aSSascha Wildner (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_REMOVED) && 2162*c12c399aSSascha Wildner (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE) 2163*c12c399aSSascha Wildner && (element->ReasonCode != 2164*c12c399aSSascha Wildner MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED)) 2165*c12c399aSSascha Wildner continue; 2166*c12c399aSSascha Wildner if ((element_flags & 2167*c12c399aSSascha Wildner MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK) == 2168*c12c399aSSascha Wildner MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT) { 2169*c12c399aSSascha Wildner mps_config_get_volume_wwid(sc, 2170*c12c399aSSascha Wildner le16toh(element->VolDevHandle), &wwid_table[i]); 2171*c12c399aSSascha Wildner map_idx = _mapping_get_ir_mt_idx_from_wwid(sc, 2172*c12c399aSSascha Wildner wwid_table[i]); 2173*c12c399aSSascha Wildner if (map_idx != MPS_MAPTABLE_BAD_IDX) { 2174*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[map_idx]; 2175*c12c399aSSascha Wildner mt_entry->device_info |= MPS_MAP_IN_USE; 2176*c12c399aSSascha Wildner } 2177*c12c399aSSascha Wildner } 2178*c12c399aSSascha Wildner } 2179*c12c399aSSascha Wildner if (flags == MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) 2180*c12c399aSSascha Wildner goto out; 2181*c12c399aSSascha Wildner else { 2182*c12c399aSSascha Wildner element = (Mpi2EventIrConfigElement_t *)&event_data-> 2183*c12c399aSSascha Wildner ConfigElement[0]; 2184*c12c399aSSascha Wildner for (i = 0; i < event_data->NumElements; i++, element++) { 2185*c12c399aSSascha Wildner if (element->ReasonCode == 2186*c12c399aSSascha Wildner MPI2_EVENT_IR_CHANGE_RC_ADDED || 2187*c12c399aSSascha Wildner element->ReasonCode == 2188*c12c399aSSascha Wildner MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) { 2189*c12c399aSSascha Wildner map_idx = _mapping_get_ir_mt_idx_from_wwid 2190*c12c399aSSascha Wildner (sc, wwid_table[i]); 2191*c12c399aSSascha Wildner if (map_idx != MPS_MAPTABLE_BAD_IDX) { 2192*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[map_idx]; 2193*c12c399aSSascha Wildner mt_entry->channel = MPS_RAID_CHANNEL; 2194*c12c399aSSascha Wildner mt_entry->id = map_idx; 2195*c12c399aSSascha Wildner mt_entry->dev_handle = le16toh 2196*c12c399aSSascha Wildner (element->VolDevHandle); 2197*c12c399aSSascha Wildner mt_entry->device_info = 2198*c12c399aSSascha Wildner MPS_DEV_RESERVED | MPS_MAP_IN_USE; 2199*c12c399aSSascha Wildner _mapping_update_ir_missing_cnt(sc, 2200*c12c399aSSascha Wildner map_idx, element, wwid_table[i]); 2201*c12c399aSSascha Wildner continue; 2202*c12c399aSSascha Wildner } 2203*c12c399aSSascha Wildner map_idx = _mapping_get_free_ir_mt_idx(sc); 2204*c12c399aSSascha Wildner if (map_idx == MPS_MAPTABLE_BAD_IDX) 2205*c12c399aSSascha Wildner log_full_error = 1; 2206*c12c399aSSascha Wildner else if (i < (event_data->NumElements - 1)) { 2207*c12c399aSSascha Wildner log_full_error = 2208*c12c399aSSascha Wildner _mapping_check_update_ir_mt_idx 2209*c12c399aSSascha Wildner (sc, event_data, i, &map_idx, 2210*c12c399aSSascha Wildner wwid_table); 2211*c12c399aSSascha Wildner } 2212*c12c399aSSascha Wildner if (log_full_error) { 2213*c12c399aSSascha Wildner kprintf("%s: no space to add the RAID " 2214*c12c399aSSascha Wildner "volume with handle 0x%04x in " 2215*c12c399aSSascha Wildner "mapping table\n", __func__, le16toh 2216*c12c399aSSascha Wildner (element->VolDevHandle)); 2217*c12c399aSSascha Wildner continue; 2218*c12c399aSSascha Wildner } 2219*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[map_idx]; 2220*c12c399aSSascha Wildner mt_entry->physical_id = wwid_table[i]; 2221*c12c399aSSascha Wildner mt_entry->channel = MPS_RAID_CHANNEL; 2222*c12c399aSSascha Wildner mt_entry->id = map_idx; 2223*c12c399aSSascha Wildner mt_entry->dev_handle = le16toh(element-> 2224*c12c399aSSascha Wildner VolDevHandle); 2225*c12c399aSSascha Wildner mt_entry->device_info = MPS_DEV_RESERVED | 2226*c12c399aSSascha Wildner MPS_MAP_IN_USE; 2227*c12c399aSSascha Wildner mt_entry->init_complete = 0; 2228*c12c399aSSascha Wildner _mapping_update_ir_missing_cnt(sc, map_idx, 2229*c12c399aSSascha Wildner element, wwid_table[i]); 2230*c12c399aSSascha Wildner } else if (element->ReasonCode == 2231*c12c399aSSascha Wildner MPI2_EVENT_IR_CHANGE_RC_REMOVED) { 2232*c12c399aSSascha Wildner map_idx = _mapping_get_ir_mt_idx_from_wwid(sc, 2233*c12c399aSSascha Wildner wwid_table[i]); 2234*c12c399aSSascha Wildner if (map_idx == MPS_MAPTABLE_BAD_IDX) { 2235*c12c399aSSascha Wildner kprintf("%s: failed to remove a volume " 2236*c12c399aSSascha Wildner "because it has already been " 2237*c12c399aSSascha Wildner "removed\n", __func__); 2238*c12c399aSSascha Wildner continue; 2239*c12c399aSSascha Wildner } 2240*c12c399aSSascha Wildner _mapping_update_ir_missing_cnt(sc, map_idx, 2241*c12c399aSSascha Wildner element, wwid_table[i]); 2242*c12c399aSSascha Wildner } else if (element->ReasonCode == 2243*c12c399aSSascha Wildner MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED) { 2244*c12c399aSSascha Wildner map_idx = _mapping_get_mt_idx_from_handle(sc, 2245*c12c399aSSascha Wildner le16toh(element->VolDevHandle)); 2246*c12c399aSSascha Wildner if (map_idx == MPS_MAPTABLE_BAD_IDX) { 2247*c12c399aSSascha Wildner kprintf("%s: failed to remove volume " 2248*c12c399aSSascha Wildner "with handle 0x%04x because it has " 2249*c12c399aSSascha Wildner "already been removed\n", __func__, 2250*c12c399aSSascha Wildner le16toh(element->VolDevHandle)); 2251*c12c399aSSascha Wildner continue; 2252*c12c399aSSascha Wildner } 2253*c12c399aSSascha Wildner mt_entry = &sc->mapping_table[map_idx]; 2254*c12c399aSSascha Wildner _mapping_update_ir_missing_cnt(sc, map_idx, 2255*c12c399aSSascha Wildner element, mt_entry->physical_id); 2256*c12c399aSSascha Wildner } 2257*c12c399aSSascha Wildner } 2258*c12c399aSSascha Wildner } 2259*c12c399aSSascha Wildner 2260*c12c399aSSascha Wildner out: 2261*c12c399aSSascha Wildner _mapping_flush_dpm_pages(sc); 2262*c12c399aSSascha Wildner kfree(wwid_table, M_MPT2); 2263*c12c399aSSascha Wildner if (sc->pending_map_events) 2264*c12c399aSSascha Wildner sc->pending_map_events--; 2265*c12c399aSSascha Wildner } 2266