1991554f2SKenneth D. Merry /*- 2a2c14879SStephen McConnell * Copyright (c) 2011-2015 LSI Corp. 37a2a6a1aSStephen McConnell * Copyright (c) 2013-2016 Avago Technologies 4991554f2SKenneth D. Merry * All rights reserved. 5991554f2SKenneth D. Merry * 6991554f2SKenneth D. Merry * Redistribution and use in source and binary forms, with or without 7991554f2SKenneth D. Merry * modification, are permitted provided that the following conditions 8991554f2SKenneth D. Merry * are met: 9991554f2SKenneth D. Merry * 1. Redistributions of source code must retain the above copyright 10991554f2SKenneth D. Merry * notice, this list of conditions and the following disclaimer. 11991554f2SKenneth D. Merry * 2. Redistributions in binary form must reproduce the above copyright 12991554f2SKenneth D. Merry * notice, this list of conditions and the following disclaimer in the 13991554f2SKenneth D. Merry * documentation and/or other materials provided with the distribution. 14991554f2SKenneth D. Merry * 15991554f2SKenneth D. Merry * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16991554f2SKenneth D. Merry * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17991554f2SKenneth D. Merry * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18991554f2SKenneth D. Merry * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19991554f2SKenneth D. Merry * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20991554f2SKenneth D. Merry * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21991554f2SKenneth D. Merry * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22991554f2SKenneth D. Merry * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23991554f2SKenneth D. Merry * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24991554f2SKenneth D. Merry * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25991554f2SKenneth D. Merry * SUCH DAMAGE. 26991554f2SKenneth D. Merry * 27a2c14879SStephen McConnell * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD 28991554f2SKenneth D. Merry */ 29991554f2SKenneth D. Merry 30991554f2SKenneth D. Merry #include <sys/cdefs.h> 31991554f2SKenneth D. Merry __FBSDID("$FreeBSD$"); 32991554f2SKenneth D. Merry 33991554f2SKenneth D. Merry /* TODO Move headers to mprvar */ 34991554f2SKenneth D. Merry #include <sys/types.h> 35991554f2SKenneth D. Merry #include <sys/param.h> 36991554f2SKenneth D. Merry #include <sys/lock.h> 37991554f2SKenneth D. Merry #include <sys/mutex.h> 38991554f2SKenneth D. Merry #include <sys/systm.h> 39991554f2SKenneth D. Merry #include <sys/kernel.h> 40991554f2SKenneth D. Merry #include <sys/malloc.h> 41991554f2SKenneth D. Merry #include <sys/kthread.h> 42991554f2SKenneth D. Merry #include <sys/taskqueue.h> 43991554f2SKenneth D. Merry #include <sys/bus.h> 44991554f2SKenneth D. Merry #include <sys/endian.h> 45991554f2SKenneth D. Merry #include <sys/sysctl.h> 46991554f2SKenneth D. Merry #include <sys/eventhandler.h> 47991554f2SKenneth D. Merry #include <sys/uio.h> 48991554f2SKenneth D. Merry #include <machine/bus.h> 49991554f2SKenneth D. Merry #include <machine/resource.h> 50991554f2SKenneth D. Merry #include <dev/mpr/mpi/mpi2_type.h> 51991554f2SKenneth D. Merry #include <dev/mpr/mpi/mpi2.h> 52991554f2SKenneth D. Merry #include <dev/mpr/mpi/mpi2_ioc.h> 53991554f2SKenneth D. Merry #include <dev/mpr/mpi/mpi2_sas.h> 54*67feec50SStephen McConnell #include <dev/mpr/mpi/mpi2_pci.h> 55991554f2SKenneth D. Merry #include <dev/mpr/mpi/mpi2_cnfg.h> 56991554f2SKenneth D. Merry #include <dev/mpr/mpi/mpi2_init.h> 57991554f2SKenneth D. Merry #include <dev/mpr/mpi/mpi2_tool.h> 58991554f2SKenneth D. Merry #include <dev/mpr/mpr_ioctl.h> 59991554f2SKenneth D. Merry #include <dev/mpr/mprvar.h> 60991554f2SKenneth D. Merry #include <dev/mpr/mpr_mapping.h> 61991554f2SKenneth D. Merry 62991554f2SKenneth D. Merry /** 63991554f2SKenneth D. Merry * _mapping_clear_entry - Clear a particular mapping entry. 64991554f2SKenneth D. Merry * @map_entry: map table entry 65991554f2SKenneth D. Merry * 66991554f2SKenneth D. Merry * Returns nothing. 67991554f2SKenneth D. Merry */ 68991554f2SKenneth D. Merry static inline void 69991554f2SKenneth D. Merry _mapping_clear_map_entry(struct dev_mapping_table *map_entry) 70991554f2SKenneth D. Merry { 71991554f2SKenneth D. Merry map_entry->physical_id = 0; 72991554f2SKenneth D. Merry map_entry->device_info = 0; 73991554f2SKenneth D. Merry map_entry->phy_bits = 0; 74991554f2SKenneth D. Merry map_entry->dpm_entry_num = MPR_DPM_BAD_IDX; 75991554f2SKenneth D. Merry map_entry->dev_handle = 0; 76991554f2SKenneth D. Merry map_entry->channel = -1; 77991554f2SKenneth D. Merry map_entry->id = -1; 78991554f2SKenneth D. Merry map_entry->missing_count = 0; 79991554f2SKenneth D. Merry map_entry->init_complete = 0; 80991554f2SKenneth D. Merry map_entry->TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR; 81991554f2SKenneth D. Merry } 82991554f2SKenneth D. Merry 83991554f2SKenneth D. Merry /** 84991554f2SKenneth D. Merry * _mapping_clear_enc_entry - Clear a particular enclosure table entry. 85991554f2SKenneth D. Merry * @enc_entry: enclosure table entry 86991554f2SKenneth D. Merry * 87991554f2SKenneth D. Merry * Returns nothing. 88991554f2SKenneth D. Merry */ 89991554f2SKenneth D. Merry static inline void 90991554f2SKenneth D. Merry _mapping_clear_enc_entry(struct enc_mapping_table *enc_entry) 91991554f2SKenneth D. Merry { 92991554f2SKenneth D. Merry enc_entry->enclosure_id = 0; 93991554f2SKenneth D. Merry enc_entry->start_index = MPR_MAPTABLE_BAD_IDX; 94991554f2SKenneth D. Merry enc_entry->phy_bits = 0; 95991554f2SKenneth D. Merry enc_entry->dpm_entry_num = MPR_DPM_BAD_IDX; 96991554f2SKenneth D. Merry enc_entry->enc_handle = 0; 97991554f2SKenneth D. Merry enc_entry->num_slots = 0; 98991554f2SKenneth D. Merry enc_entry->start_slot = 0; 99991554f2SKenneth D. Merry enc_entry->missing_count = 0; 100991554f2SKenneth D. Merry enc_entry->removal_flag = 0; 101991554f2SKenneth D. Merry enc_entry->skip_search = 0; 102991554f2SKenneth D. Merry enc_entry->init_complete = 0; 103991554f2SKenneth D. Merry } 104991554f2SKenneth D. Merry 105991554f2SKenneth D. Merry /** 106991554f2SKenneth D. Merry * _mapping_commit_enc_entry - write a particular enc entry in DPM page0. 107991554f2SKenneth D. Merry * @sc: per adapter object 108991554f2SKenneth D. Merry * @enc_entry: enclosure table entry 109991554f2SKenneth D. Merry * 110991554f2SKenneth D. Merry * Returns 0 for success, non-zero for failure. 111991554f2SKenneth D. Merry */ 112991554f2SKenneth D. Merry static int 113991554f2SKenneth D. Merry _mapping_commit_enc_entry(struct mpr_softc *sc, 114991554f2SKenneth D. Merry struct enc_mapping_table *et_entry) 115991554f2SKenneth D. Merry { 116991554f2SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry; 117991554f2SKenneth D. Merry struct dev_mapping_table *mt_entry; 118991554f2SKenneth D. Merry Mpi2ConfigReply_t mpi_reply; 119991554f2SKenneth D. Merry Mpi2DriverMappingPage0_t config_page; 120991554f2SKenneth D. Merry 121991554f2SKenneth D. Merry if (!sc->is_dpm_enable) 122991554f2SKenneth D. Merry return 0; 123991554f2SKenneth D. Merry 124991554f2SKenneth D. Merry memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t)); 125991554f2SKenneth D. Merry memcpy(&config_page.Header, (u8 *) sc->dpm_pg0, 126991554f2SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 127991554f2SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 + 128991554f2SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 129991554f2SKenneth D. Merry dpm_entry += et_entry->dpm_entry_num; 130991554f2SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low = 131991554f2SKenneth D. Merry ( 0xFFFFFFFF & et_entry->enclosure_id); 132991554f2SKenneth D. Merry dpm_entry->PhysicalIdentifier.High = 133991554f2SKenneth D. Merry ( et_entry->enclosure_id >> 32); 134991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[et_entry->start_index]; 135991554f2SKenneth D. Merry dpm_entry->DeviceIndex = htole16(mt_entry->id); 136991554f2SKenneth D. Merry dpm_entry->MappingInformation = et_entry->num_slots; 137991554f2SKenneth D. Merry dpm_entry->MappingInformation <<= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT; 138991554f2SKenneth D. Merry dpm_entry->MappingInformation |= et_entry->missing_count; 139991554f2SKenneth D. Merry dpm_entry->MappingInformation = htole16(dpm_entry->MappingInformation); 140991554f2SKenneth D. Merry dpm_entry->PhysicalBitsMapping = htole32(et_entry->phy_bits); 141991554f2SKenneth D. Merry dpm_entry->Reserved1 = 0; 142991554f2SKenneth D. Merry 143991554f2SKenneth D. Merry memcpy(&config_page.Entry, (u8 *)dpm_entry, 144991554f2SKenneth D. Merry sizeof(Mpi2DriverMap0Entry_t)); 145991554f2SKenneth D. Merry if (mpr_config_set_dpm_pg0(sc, &mpi_reply, &config_page, 146991554f2SKenneth D. Merry et_entry->dpm_entry_num)) { 147991554f2SKenneth D. Merry printf("%s: write of dpm entry %d for enclosure failed\n", 148991554f2SKenneth D. Merry __func__, et_entry->dpm_entry_num); 149991554f2SKenneth D. Merry dpm_entry->MappingInformation = le16toh(dpm_entry-> 150991554f2SKenneth D. Merry MappingInformation); 151991554f2SKenneth D. Merry dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex); 152991554f2SKenneth D. Merry dpm_entry->PhysicalBitsMapping = 153991554f2SKenneth D. Merry le32toh(dpm_entry->PhysicalBitsMapping); 154991554f2SKenneth D. Merry return -1; 155991554f2SKenneth D. Merry } 156991554f2SKenneth D. Merry dpm_entry->MappingInformation = le16toh(dpm_entry-> 157991554f2SKenneth D. Merry MappingInformation); 158991554f2SKenneth D. Merry dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex); 159991554f2SKenneth D. Merry dpm_entry->PhysicalBitsMapping = 160991554f2SKenneth D. Merry le32toh(dpm_entry->PhysicalBitsMapping); 161991554f2SKenneth D. Merry return 0; 162991554f2SKenneth D. Merry } 163991554f2SKenneth D. Merry 164991554f2SKenneth D. Merry /** 165991554f2SKenneth D. Merry * _mapping_commit_map_entry - write a particular map table entry in DPM page0. 166991554f2SKenneth D. Merry * @sc: per adapter object 167991554f2SKenneth D. Merry * @enc_entry: enclosure table entry 168991554f2SKenneth D. Merry * 169991554f2SKenneth D. Merry * Returns 0 for success, non-zero for failure. 170991554f2SKenneth D. Merry */ 171991554f2SKenneth D. Merry 172991554f2SKenneth D. Merry static int 173991554f2SKenneth D. Merry _mapping_commit_map_entry(struct mpr_softc *sc, 174991554f2SKenneth D. Merry struct dev_mapping_table *mt_entry) 175991554f2SKenneth D. Merry { 176991554f2SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry; 177991554f2SKenneth D. Merry Mpi2ConfigReply_t mpi_reply; 178991554f2SKenneth D. Merry Mpi2DriverMappingPage0_t config_page; 179991554f2SKenneth D. Merry 180991554f2SKenneth D. Merry if (!sc->is_dpm_enable) 181991554f2SKenneth D. Merry return 0; 182991554f2SKenneth D. Merry 183991554f2SKenneth D. Merry memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t)); 184991554f2SKenneth D. Merry memcpy(&config_page.Header, (u8 *)sc->dpm_pg0, 185991554f2SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 186991554f2SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *) sc->dpm_pg0 + 187991554f2SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 188991554f2SKenneth D. Merry dpm_entry = dpm_entry + mt_entry->dpm_entry_num; 189991554f2SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low = (0xFFFFFFFF & 190991554f2SKenneth D. Merry mt_entry->physical_id); 191991554f2SKenneth D. Merry dpm_entry->PhysicalIdentifier.High = (mt_entry->physical_id >> 32); 192991554f2SKenneth D. Merry dpm_entry->DeviceIndex = htole16(mt_entry->id); 193991554f2SKenneth D. Merry dpm_entry->MappingInformation = htole16(mt_entry->missing_count); 194991554f2SKenneth D. Merry dpm_entry->PhysicalBitsMapping = 0; 195991554f2SKenneth D. Merry dpm_entry->Reserved1 = 0; 196991554f2SKenneth D. Merry dpm_entry->MappingInformation = htole16(dpm_entry->MappingInformation); 197991554f2SKenneth D. Merry memcpy(&config_page.Entry, (u8 *)dpm_entry, 198991554f2SKenneth D. Merry sizeof(Mpi2DriverMap0Entry_t)); 199991554f2SKenneth D. Merry if (mpr_config_set_dpm_pg0(sc, &mpi_reply, &config_page, 200991554f2SKenneth D. Merry mt_entry->dpm_entry_num)) { 201991554f2SKenneth D. Merry printf("%s: write of dpm entry %d for device failed\n", 202991554f2SKenneth D. Merry __func__, mt_entry->dpm_entry_num); 203991554f2SKenneth D. Merry dpm_entry->MappingInformation = le16toh(dpm_entry-> 204991554f2SKenneth D. Merry MappingInformation); 205991554f2SKenneth D. Merry dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex); 206991554f2SKenneth D. Merry return -1; 207991554f2SKenneth D. Merry } 208991554f2SKenneth D. Merry 209991554f2SKenneth D. Merry dpm_entry->MappingInformation = le16toh(dpm_entry->MappingInformation); 210991554f2SKenneth D. Merry dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex); 211991554f2SKenneth D. Merry return 0; 212991554f2SKenneth D. Merry } 213991554f2SKenneth D. Merry 214991554f2SKenneth D. Merry /** 215991554f2SKenneth D. Merry * _mapping_get_ir_maprange - get start and end index for IR map range. 216991554f2SKenneth D. Merry * @sc: per adapter object 217991554f2SKenneth D. Merry * @start_idx: place holder for start index 218991554f2SKenneth D. Merry * @end_idx: place holder for end index 219991554f2SKenneth D. Merry * 220991554f2SKenneth D. Merry * The IR volumes can be mapped either at start or end of the mapping table 221991554f2SKenneth D. Merry * this function gets the detail of where IR volume mapping starts and ends 222991554f2SKenneth D. Merry * in the device mapping table 223991554f2SKenneth D. Merry * 224991554f2SKenneth D. Merry * Returns nothing. 225991554f2SKenneth D. Merry */ 226991554f2SKenneth D. Merry static void 227991554f2SKenneth D. Merry _mapping_get_ir_maprange(struct mpr_softc *sc, u32 *start_idx, u32 *end_idx) 228991554f2SKenneth D. Merry { 229991554f2SKenneth D. Merry u16 volume_mapping_flags; 230991554f2SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 231991554f2SKenneth D. Merry 232991554f2SKenneth D. Merry volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) & 233991554f2SKenneth D. Merry MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; 234991554f2SKenneth D. Merry if (volume_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) { 235991554f2SKenneth D. Merry *start_idx = 0; 236991554f2SKenneth D. Merry if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0) 237991554f2SKenneth D. Merry *start_idx = 1; 238991554f2SKenneth D. Merry } else 239991554f2SKenneth D. Merry *start_idx = sc->max_devices - sc->max_volumes; 240991554f2SKenneth D. Merry *end_idx = *start_idx + sc->max_volumes - 1; 241991554f2SKenneth D. Merry } 242991554f2SKenneth D. Merry 243991554f2SKenneth D. Merry /** 244991554f2SKenneth D. Merry * _mapping_get_enc_idx_from_id - get enclosure index from enclosure ID 245991554f2SKenneth D. Merry * @sc: per adapter object 246991554f2SKenneth D. Merry * @enc_id: enclosure logical identifier 247991554f2SKenneth D. Merry * 248991554f2SKenneth D. Merry * Returns the index of enclosure entry on success or bad index. 249991554f2SKenneth D. Merry */ 250991554f2SKenneth D. Merry static u8 251991554f2SKenneth D. Merry _mapping_get_enc_idx_from_id(struct mpr_softc *sc, u64 enc_id, 252991554f2SKenneth D. Merry u64 phy_bits) 253991554f2SKenneth D. Merry { 254991554f2SKenneth D. Merry struct enc_mapping_table *et_entry; 255991554f2SKenneth D. Merry u8 enc_idx = 0; 256991554f2SKenneth D. Merry 257991554f2SKenneth D. Merry for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) { 258991554f2SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx]; 259991554f2SKenneth D. Merry if ((et_entry->enclosure_id == le64toh(enc_id)) && 260991554f2SKenneth D. Merry (!et_entry->phy_bits || (et_entry->phy_bits & 261991554f2SKenneth D. Merry le32toh(phy_bits)))) 262991554f2SKenneth D. Merry return enc_idx; 263991554f2SKenneth D. Merry } 264991554f2SKenneth D. Merry return MPR_ENCTABLE_BAD_IDX; 265991554f2SKenneth D. Merry } 266991554f2SKenneth D. Merry 267991554f2SKenneth D. Merry /** 268991554f2SKenneth D. Merry * _mapping_get_enc_idx_from_handle - get enclosure index from handle 269991554f2SKenneth D. Merry * @sc: per adapter object 270991554f2SKenneth D. Merry * @enc_id: enclosure handle 271991554f2SKenneth D. Merry * 272991554f2SKenneth D. Merry * Returns the index of enclosure entry on success or bad index. 273991554f2SKenneth D. Merry */ 274991554f2SKenneth D. Merry static u8 275991554f2SKenneth D. Merry _mapping_get_enc_idx_from_handle(struct mpr_softc *sc, u16 handle) 276991554f2SKenneth D. Merry { 277991554f2SKenneth D. Merry struct enc_mapping_table *et_entry; 278991554f2SKenneth D. Merry u8 enc_idx = 0; 279991554f2SKenneth D. Merry 280991554f2SKenneth D. Merry for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) { 281991554f2SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx]; 282991554f2SKenneth D. Merry if (et_entry->missing_count) 283991554f2SKenneth D. Merry continue; 284991554f2SKenneth D. Merry if (et_entry->enc_handle == handle) 285991554f2SKenneth D. Merry return enc_idx; 286991554f2SKenneth D. Merry } 287991554f2SKenneth D. Merry return MPR_ENCTABLE_BAD_IDX; 288991554f2SKenneth D. Merry } 289991554f2SKenneth D. Merry 290991554f2SKenneth D. Merry /** 291991554f2SKenneth D. Merry * _mapping_get_high_missing_et_idx - get missing enclosure index 292991554f2SKenneth D. Merry * @sc: per adapter object 293991554f2SKenneth D. Merry * 294991554f2SKenneth D. Merry * Search through the enclosure table and identifies the enclosure entry 295991554f2SKenneth D. Merry * with high missing count and returns it's index 296991554f2SKenneth D. Merry * 297991554f2SKenneth D. Merry * Returns the index of enclosure entry on success or bad index. 298991554f2SKenneth D. Merry */ 299991554f2SKenneth D. Merry static u8 300991554f2SKenneth D. Merry _mapping_get_high_missing_et_idx(struct mpr_softc *sc) 301991554f2SKenneth D. Merry { 302991554f2SKenneth D. Merry struct enc_mapping_table *et_entry; 303991554f2SKenneth D. Merry u8 high_missing_count = 0; 304991554f2SKenneth D. Merry u8 enc_idx, high_idx = MPR_ENCTABLE_BAD_IDX; 305991554f2SKenneth D. Merry 306991554f2SKenneth D. Merry for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) { 307991554f2SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx]; 308991554f2SKenneth D. Merry if ((et_entry->missing_count > high_missing_count) && 309991554f2SKenneth D. Merry !et_entry->skip_search) { 310991554f2SKenneth D. Merry high_missing_count = et_entry->missing_count; 311991554f2SKenneth D. Merry high_idx = enc_idx; 312991554f2SKenneth D. Merry } 313991554f2SKenneth D. Merry } 314991554f2SKenneth D. Merry return high_idx; 315991554f2SKenneth D. Merry } 316991554f2SKenneth D. Merry 317991554f2SKenneth D. Merry /** 318991554f2SKenneth D. Merry * _mapping_get_high_missing_mt_idx - get missing map table index 319991554f2SKenneth D. Merry * @sc: per adapter object 320991554f2SKenneth D. Merry * 321991554f2SKenneth D. Merry * Search through the map table and identifies the device entry 322991554f2SKenneth D. Merry * with high missing count and returns it's index 323991554f2SKenneth D. Merry * 324991554f2SKenneth D. Merry * Returns the index of map table entry on success or bad index. 325991554f2SKenneth D. Merry */ 326991554f2SKenneth D. Merry static u32 327991554f2SKenneth D. Merry _mapping_get_high_missing_mt_idx(struct mpr_softc *sc) 328991554f2SKenneth D. Merry { 329991554f2SKenneth D. Merry u32 map_idx, high_idx = MPR_ENCTABLE_BAD_IDX; 330991554f2SKenneth D. Merry u8 high_missing_count = 0; 331a2c14879SStephen McConnell u32 start_idx, end_idx, start_idx_ir, end_idx_ir; 332991554f2SKenneth D. Merry struct dev_mapping_table *mt_entry; 333991554f2SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 334991554f2SKenneth D. Merry 335991554f2SKenneth D. Merry start_idx = 0; 336a2c14879SStephen McConnell start_idx_ir = 0; 337a2c14879SStephen McConnell end_idx_ir = 0; 338991554f2SKenneth D. Merry end_idx = sc->max_devices; 339991554f2SKenneth D. Merry if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0) 340991554f2SKenneth D. Merry start_idx = 1; 341991554f2SKenneth D. Merry if (sc->ir_firmware) { 342991554f2SKenneth D. Merry _mapping_get_ir_maprange(sc, &start_idx_ir, &end_idx_ir); 343991554f2SKenneth D. Merry if (start_idx == start_idx_ir) 344991554f2SKenneth D. Merry start_idx = end_idx_ir + 1; 345991554f2SKenneth D. Merry else 346991554f2SKenneth D. Merry end_idx = start_idx_ir; 347991554f2SKenneth D. Merry } 348991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[start_idx]; 349991554f2SKenneth D. Merry for (map_idx = start_idx; map_idx < end_idx; map_idx++, mt_entry++) { 350991554f2SKenneth D. Merry if (mt_entry->missing_count > high_missing_count) { 351991554f2SKenneth D. Merry high_missing_count = mt_entry->missing_count; 352991554f2SKenneth D. Merry high_idx = map_idx; 353991554f2SKenneth D. Merry } 354991554f2SKenneth D. Merry } 355991554f2SKenneth D. Merry return high_idx; 356991554f2SKenneth D. Merry } 357991554f2SKenneth D. Merry 358991554f2SKenneth D. Merry /** 359991554f2SKenneth D. Merry * _mapping_get_ir_mt_idx_from_wwid - get map table index from volume WWID 360991554f2SKenneth D. Merry * @sc: per adapter object 361991554f2SKenneth D. Merry * @wwid: world wide unique ID of the volume 362991554f2SKenneth D. Merry * 363991554f2SKenneth D. Merry * Returns the index of map table entry on success or bad index. 364991554f2SKenneth D. Merry */ 365991554f2SKenneth D. Merry static u32 366991554f2SKenneth D. Merry _mapping_get_ir_mt_idx_from_wwid(struct mpr_softc *sc, u64 wwid) 367991554f2SKenneth D. Merry { 368991554f2SKenneth D. Merry u32 start_idx, end_idx, map_idx; 369991554f2SKenneth D. Merry struct dev_mapping_table *mt_entry; 370991554f2SKenneth D. Merry 371991554f2SKenneth D. Merry _mapping_get_ir_maprange(sc, &start_idx, &end_idx); 372991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[start_idx]; 373991554f2SKenneth D. Merry for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) 374991554f2SKenneth D. Merry if (mt_entry->physical_id == wwid) 375991554f2SKenneth D. Merry return map_idx; 376991554f2SKenneth D. Merry 377991554f2SKenneth D. Merry return MPR_MAPTABLE_BAD_IDX; 378991554f2SKenneth D. Merry } 379991554f2SKenneth D. Merry 380991554f2SKenneth D. Merry /** 381991554f2SKenneth D. Merry * _mapping_get_mt_idx_from_id - get map table index from a device ID 382991554f2SKenneth D. Merry * @sc: per adapter object 383991554f2SKenneth D. Merry * @dev_id: device identifer (SAS Address) 384991554f2SKenneth D. Merry * 385991554f2SKenneth D. Merry * Returns the index of map table entry on success or bad index. 386991554f2SKenneth D. Merry */ 387991554f2SKenneth D. Merry static u32 388991554f2SKenneth D. Merry _mapping_get_mt_idx_from_id(struct mpr_softc *sc, u64 dev_id) 389991554f2SKenneth D. Merry { 390991554f2SKenneth D. Merry u32 map_idx; 391991554f2SKenneth D. Merry struct dev_mapping_table *mt_entry; 392991554f2SKenneth D. Merry 393991554f2SKenneth D. Merry for (map_idx = 0; map_idx < sc->max_devices; map_idx++) { 394991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 395991554f2SKenneth D. Merry if (mt_entry->physical_id == dev_id) 396991554f2SKenneth D. Merry return map_idx; 397991554f2SKenneth D. Merry } 398991554f2SKenneth D. Merry return MPR_MAPTABLE_BAD_IDX; 399991554f2SKenneth D. Merry } 400991554f2SKenneth D. Merry 401991554f2SKenneth D. Merry /** 402991554f2SKenneth D. Merry * _mapping_get_ir_mt_idx_from_handle - get map table index from volume handle 403991554f2SKenneth D. Merry * @sc: per adapter object 404991554f2SKenneth D. Merry * @wwid: volume device handle 405991554f2SKenneth D. Merry * 406991554f2SKenneth D. Merry * Returns the index of map table entry on success or bad index. 407991554f2SKenneth D. Merry */ 408991554f2SKenneth D. Merry static u32 409991554f2SKenneth D. Merry _mapping_get_ir_mt_idx_from_handle(struct mpr_softc *sc, u16 volHandle) 410991554f2SKenneth D. Merry { 411991554f2SKenneth D. Merry u32 start_idx, end_idx, map_idx; 412991554f2SKenneth D. Merry struct dev_mapping_table *mt_entry; 413991554f2SKenneth D. Merry 414991554f2SKenneth D. Merry _mapping_get_ir_maprange(sc, &start_idx, &end_idx); 415991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[start_idx]; 416991554f2SKenneth D. Merry for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) 417991554f2SKenneth D. Merry if (mt_entry->dev_handle == volHandle) 418991554f2SKenneth D. Merry return map_idx; 419991554f2SKenneth D. Merry 420991554f2SKenneth D. Merry return MPR_MAPTABLE_BAD_IDX; 421991554f2SKenneth D. Merry } 422991554f2SKenneth D. Merry 423991554f2SKenneth D. Merry /** 424991554f2SKenneth D. Merry * _mapping_get_mt_idx_from_handle - get map table index from handle 425991554f2SKenneth D. Merry * @sc: per adapter object 426991554f2SKenneth D. Merry * @dev_id: device handle 427991554f2SKenneth D. Merry * 428991554f2SKenneth D. Merry * Returns the index of map table entry on success or bad index. 429991554f2SKenneth D. Merry */ 430991554f2SKenneth D. Merry static u32 431991554f2SKenneth D. Merry _mapping_get_mt_idx_from_handle(struct mpr_softc *sc, u16 handle) 432991554f2SKenneth D. Merry { 433991554f2SKenneth D. Merry u32 map_idx; 434991554f2SKenneth D. Merry struct dev_mapping_table *mt_entry; 435991554f2SKenneth D. Merry 436991554f2SKenneth D. Merry for (map_idx = 0; map_idx < sc->max_devices; map_idx++) { 437991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 438991554f2SKenneth D. Merry if (mt_entry->dev_handle == handle) 439991554f2SKenneth D. Merry return map_idx; 440991554f2SKenneth D. Merry } 441991554f2SKenneth D. Merry return MPR_MAPTABLE_BAD_IDX; 442991554f2SKenneth D. Merry } 443991554f2SKenneth D. Merry 444991554f2SKenneth D. Merry /** 445991554f2SKenneth D. Merry * _mapping_get_free_ir_mt_idx - get first free index for a volume 446991554f2SKenneth D. Merry * @sc: per adapter object 447991554f2SKenneth D. Merry * 448991554f2SKenneth D. Merry * Search through mapping table for free index for a volume and if no free 449991554f2SKenneth D. Merry * index then looks for a volume with high mapping index 450991554f2SKenneth D. Merry * 451991554f2SKenneth D. Merry * Returns the index of map table entry on success or bad index. 452991554f2SKenneth D. Merry */ 453991554f2SKenneth D. Merry static u32 454991554f2SKenneth D. Merry _mapping_get_free_ir_mt_idx(struct mpr_softc *sc) 455991554f2SKenneth D. Merry { 456991554f2SKenneth D. Merry u8 high_missing_count = 0; 457991554f2SKenneth D. Merry u32 start_idx, end_idx, map_idx; 458991554f2SKenneth D. Merry u32 high_idx = MPR_MAPTABLE_BAD_IDX; 459991554f2SKenneth D. Merry struct dev_mapping_table *mt_entry; 460991554f2SKenneth D. Merry 461991554f2SKenneth D. Merry _mapping_get_ir_maprange(sc, &start_idx, &end_idx); 462991554f2SKenneth D. Merry 463991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[start_idx]; 464991554f2SKenneth D. Merry for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) 465991554f2SKenneth D. Merry if (!(mt_entry->device_info & MPR_MAP_IN_USE)) 466991554f2SKenneth D. Merry return map_idx; 467991554f2SKenneth D. Merry 468991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[start_idx]; 469991554f2SKenneth D. Merry for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) { 470991554f2SKenneth D. Merry if (mt_entry->missing_count > high_missing_count) { 471991554f2SKenneth D. Merry high_missing_count = mt_entry->missing_count; 472991554f2SKenneth D. Merry high_idx = map_idx; 473991554f2SKenneth D. Merry } 474991554f2SKenneth D. Merry } 475991554f2SKenneth D. Merry return high_idx; 476991554f2SKenneth D. Merry } 477991554f2SKenneth D. Merry 478991554f2SKenneth D. Merry /** 479991554f2SKenneth D. Merry * _mapping_get_free_mt_idx - get first free index for a device 480991554f2SKenneth D. Merry * @sc: per adapter object 481991554f2SKenneth D. Merry * @start_idx: offset in the table to start search 482991554f2SKenneth D. Merry * 483991554f2SKenneth D. Merry * Returns the index of map table entry on success or bad index. 484991554f2SKenneth D. Merry */ 485991554f2SKenneth D. Merry static u32 486991554f2SKenneth D. Merry _mapping_get_free_mt_idx(struct mpr_softc *sc, u32 start_idx) 487991554f2SKenneth D. Merry { 488991554f2SKenneth D. Merry u32 map_idx, max_idx = sc->max_devices; 489991554f2SKenneth D. Merry struct dev_mapping_table *mt_entry = &sc->mapping_table[start_idx]; 490991554f2SKenneth D. Merry u16 volume_mapping_flags; 491991554f2SKenneth D. Merry 492991554f2SKenneth D. Merry volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) & 493991554f2SKenneth D. Merry MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; 494991554f2SKenneth D. Merry if (sc->ir_firmware && (volume_mapping_flags == 495991554f2SKenneth D. Merry MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING)) 496991554f2SKenneth D. Merry max_idx -= sc->max_volumes; 497991554f2SKenneth D. Merry for (map_idx = start_idx; map_idx < max_idx; map_idx++, mt_entry++) 498991554f2SKenneth D. Merry if (!(mt_entry->device_info & (MPR_MAP_IN_USE | 499991554f2SKenneth D. Merry MPR_DEV_RESERVED))) 500991554f2SKenneth D. Merry return map_idx; 501991554f2SKenneth D. Merry 502991554f2SKenneth D. Merry return MPR_MAPTABLE_BAD_IDX; 503991554f2SKenneth D. Merry } 504991554f2SKenneth D. Merry 505991554f2SKenneth D. Merry /** 506991554f2SKenneth D. Merry * _mapping_get_dpm_idx_from_id - get DPM index from ID 507991554f2SKenneth D. Merry * @sc: per adapter object 508991554f2SKenneth D. Merry * @id: volume WWID or enclosure ID or device ID 509991554f2SKenneth D. Merry * 510991554f2SKenneth D. Merry * Returns the index of DPM entry on success or bad index. 511991554f2SKenneth D. Merry */ 512991554f2SKenneth D. Merry static u16 513991554f2SKenneth D. Merry _mapping_get_dpm_idx_from_id(struct mpr_softc *sc, u64 id, u32 phy_bits) 514991554f2SKenneth D. Merry { 515991554f2SKenneth D. Merry u16 entry_num; 516991554f2SKenneth D. Merry uint64_t PhysicalIdentifier; 517991554f2SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry; 518991554f2SKenneth D. Merry 519991554f2SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 + 520991554f2SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 521991554f2SKenneth D. Merry PhysicalIdentifier = dpm_entry->PhysicalIdentifier.High; 522991554f2SKenneth D. Merry PhysicalIdentifier = (PhysicalIdentifier << 32) | 523991554f2SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low; 524991554f2SKenneth D. Merry for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++, 525991554f2SKenneth D. Merry dpm_entry++) 526991554f2SKenneth D. Merry if ((id == PhysicalIdentifier) && 527991554f2SKenneth D. Merry (!phy_bits || !dpm_entry->PhysicalBitsMapping || 528991554f2SKenneth D. Merry (phy_bits & dpm_entry->PhysicalBitsMapping))) 529991554f2SKenneth D. Merry return entry_num; 530991554f2SKenneth D. Merry 531991554f2SKenneth D. Merry return MPR_DPM_BAD_IDX; 532991554f2SKenneth D. Merry } 533991554f2SKenneth D. Merry 534991554f2SKenneth D. Merry 535991554f2SKenneth D. Merry /** 536991554f2SKenneth D. Merry * _mapping_get_free_dpm_idx - get first available DPM index 537991554f2SKenneth D. Merry * @sc: per adapter object 538991554f2SKenneth D. Merry * 539991554f2SKenneth D. Merry * Returns the index of DPM entry on success or bad index. 540991554f2SKenneth D. Merry */ 541991554f2SKenneth D. Merry static u32 542991554f2SKenneth D. Merry _mapping_get_free_dpm_idx(struct mpr_softc *sc) 543991554f2SKenneth D. Merry { 544991554f2SKenneth D. Merry u16 entry_num; 545991554f2SKenneth D. Merry 546991554f2SKenneth D. Merry for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) { 547991554f2SKenneth D. Merry if (!sc->dpm_entry_used[entry_num]) 548991554f2SKenneth D. Merry return entry_num; 549991554f2SKenneth D. Merry } 550991554f2SKenneth D. Merry return MPR_DPM_BAD_IDX; 551991554f2SKenneth D. Merry } 552991554f2SKenneth D. Merry 553991554f2SKenneth D. Merry /** 554991554f2SKenneth D. Merry * _mapping_update_ir_missing_cnt - Updates missing count for a volume 555991554f2SKenneth D. Merry * @sc: per adapter object 556991554f2SKenneth D. Merry * @map_idx: map table index of the volume 557991554f2SKenneth D. Merry * @element: IR configuration change element 558991554f2SKenneth D. Merry * @wwid: IR volume ID. 559991554f2SKenneth D. Merry * 560991554f2SKenneth D. Merry * Updates the missing count in the map table and in the DPM entry for a volume 561991554f2SKenneth D. Merry * 562991554f2SKenneth D. Merry * Returns nothing. 563991554f2SKenneth D. Merry */ 564991554f2SKenneth D. Merry static void 565991554f2SKenneth D. Merry _mapping_update_ir_missing_cnt(struct mpr_softc *sc, u32 map_idx, 566991554f2SKenneth D. Merry Mpi2EventIrConfigElement_t *element, u64 wwid) 567991554f2SKenneth D. Merry { 568991554f2SKenneth D. Merry struct dev_mapping_table *mt_entry; 569991554f2SKenneth D. Merry u8 missing_cnt, reason = element->ReasonCode; 570991554f2SKenneth D. Merry u16 dpm_idx; 571991554f2SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry; 572991554f2SKenneth D. Merry 573991554f2SKenneth D. Merry if (!sc->is_dpm_enable) 574991554f2SKenneth D. Merry return; 575991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 576991554f2SKenneth D. Merry if (reason == MPI2_EVENT_IR_CHANGE_RC_ADDED) { 577991554f2SKenneth D. Merry mt_entry->missing_count = 0; 578991554f2SKenneth D. Merry } else if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) { 579991554f2SKenneth D. Merry mt_entry->missing_count = 0; 580991554f2SKenneth D. Merry mt_entry->init_complete = 0; 581991554f2SKenneth D. Merry } else if ((reason == MPI2_EVENT_IR_CHANGE_RC_REMOVED) || 582991554f2SKenneth D. Merry (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED)) { 583991554f2SKenneth D. Merry if (!mt_entry->init_complete) { 584991554f2SKenneth D. Merry if (mt_entry->missing_count < MPR_MAX_MISSING_COUNT) 585991554f2SKenneth D. Merry mt_entry->missing_count++; 586991554f2SKenneth D. Merry else 587991554f2SKenneth D. Merry mt_entry->init_complete = 1; 588991554f2SKenneth D. Merry } 589991554f2SKenneth D. Merry if (!mt_entry->missing_count) 590991554f2SKenneth D. Merry mt_entry->missing_count++; 591991554f2SKenneth D. Merry mt_entry->dev_handle = 0; 592991554f2SKenneth D. Merry } 593991554f2SKenneth D. Merry 594991554f2SKenneth D. Merry dpm_idx = mt_entry->dpm_entry_num; 595991554f2SKenneth D. Merry if (dpm_idx == MPR_DPM_BAD_IDX) { 596991554f2SKenneth D. Merry if ((reason == MPI2_EVENT_IR_CHANGE_RC_ADDED) || 597991554f2SKenneth D. Merry (reason == MPI2_EVENT_IR_CHANGE_RC_REMOVED)) 598991554f2SKenneth D. Merry dpm_idx = _mapping_get_dpm_idx_from_id(sc, 599991554f2SKenneth D. Merry mt_entry->physical_id, 0); 600991554f2SKenneth D. Merry else if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED) 601991554f2SKenneth D. Merry return; 602991554f2SKenneth D. Merry } 603991554f2SKenneth D. Merry if (dpm_idx != MPR_DPM_BAD_IDX) { 604991554f2SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 + 605991554f2SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 606991554f2SKenneth D. Merry dpm_entry += dpm_idx; 607991554f2SKenneth D. Merry missing_cnt = dpm_entry->MappingInformation & 608991554f2SKenneth D. Merry MPI2_DRVMAP0_MAPINFO_MISSING_MASK; 609991554f2SKenneth D. Merry if ((mt_entry->physical_id == 610991554f2SKenneth D. Merry le64toh((u64)dpm_entry->PhysicalIdentifier.High | 611991554f2SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low)) && (missing_cnt == 612991554f2SKenneth D. Merry mt_entry->missing_count)) 613991554f2SKenneth D. Merry mt_entry->init_complete = 1; 614991554f2SKenneth D. Merry } else { 615991554f2SKenneth D. Merry dpm_idx = _mapping_get_free_dpm_idx(sc); 616991554f2SKenneth D. Merry mt_entry->init_complete = 0; 617991554f2SKenneth D. Merry } 618991554f2SKenneth D. Merry 619991554f2SKenneth D. Merry if ((dpm_idx != MPR_DPM_BAD_IDX) && !mt_entry->init_complete) { 620991554f2SKenneth D. Merry mt_entry->init_complete = 1; 621991554f2SKenneth D. Merry mt_entry->dpm_entry_num = dpm_idx; 622991554f2SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 + 623991554f2SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 624991554f2SKenneth D. Merry dpm_entry += dpm_idx; 625991554f2SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low = 626991554f2SKenneth D. Merry (0xFFFFFFFF & mt_entry->physical_id); 627991554f2SKenneth D. Merry dpm_entry->PhysicalIdentifier.High = 628991554f2SKenneth D. Merry (mt_entry->physical_id >> 32); 629991554f2SKenneth D. Merry dpm_entry->DeviceIndex = map_idx; 630991554f2SKenneth D. Merry dpm_entry->MappingInformation = mt_entry->missing_count; 631991554f2SKenneth D. Merry dpm_entry->PhysicalBitsMapping = 0; 632991554f2SKenneth D. Merry dpm_entry->Reserved1 = 0; 633991554f2SKenneth D. Merry sc->dpm_flush_entry[dpm_idx] = 1; 634991554f2SKenneth D. Merry sc->dpm_entry_used[dpm_idx] = 1; 635991554f2SKenneth D. Merry } else if (dpm_idx == MPR_DPM_BAD_IDX) { 636991554f2SKenneth D. Merry printf("%s: no space to add entry in DPM table\n", __func__); 637991554f2SKenneth D. Merry mt_entry->init_complete = 1; 638991554f2SKenneth D. Merry } 639991554f2SKenneth D. Merry } 640991554f2SKenneth D. Merry 641991554f2SKenneth D. Merry /** 642991554f2SKenneth D. Merry * _mapping_add_to_removal_table - mark an entry for removal 643991554f2SKenneth D. Merry * @sc: per adapter object 644991554f2SKenneth D. Merry * @handle: Handle of enclosures/device/volume 645991554f2SKenneth D. Merry * 646991554f2SKenneth D. Merry * Adds the handle or DPM entry number in removal table. 647991554f2SKenneth D. Merry * 648991554f2SKenneth D. Merry * Returns nothing. 649991554f2SKenneth D. Merry */ 650991554f2SKenneth D. Merry static void 651991554f2SKenneth D. Merry _mapping_add_to_removal_table(struct mpr_softc *sc, u16 handle, 652991554f2SKenneth D. Merry u16 dpm_idx) 653991554f2SKenneth D. Merry { 654991554f2SKenneth D. Merry struct map_removal_table *remove_entry; 655991554f2SKenneth D. Merry u32 i; 656991554f2SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 657991554f2SKenneth D. Merry 658991554f2SKenneth D. Merry remove_entry = sc->removal_table; 659991554f2SKenneth D. Merry 660991554f2SKenneth D. Merry for (i = 0; i < sc->max_devices; i++, remove_entry++) { 661991554f2SKenneth D. Merry if (remove_entry->dev_handle || remove_entry->dpm_entry_num != 662991554f2SKenneth D. Merry MPR_DPM_BAD_IDX) 663991554f2SKenneth D. Merry continue; 664991554f2SKenneth D. Merry if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 665991554f2SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 666991554f2SKenneth D. Merry if (dpm_idx) 667991554f2SKenneth D. Merry remove_entry->dpm_entry_num = dpm_idx; 668991554f2SKenneth D. Merry if (remove_entry->dpm_entry_num == MPR_DPM_BAD_IDX) 669991554f2SKenneth D. Merry remove_entry->dev_handle = handle; 670991554f2SKenneth D. Merry } else if ((ioc_pg8_flags & 671991554f2SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 672991554f2SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) 673991554f2SKenneth D. Merry remove_entry->dev_handle = handle; 674991554f2SKenneth D. Merry break; 675991554f2SKenneth D. Merry } 676991554f2SKenneth D. Merry 677991554f2SKenneth D. Merry } 678991554f2SKenneth D. Merry 679991554f2SKenneth D. Merry /** 680*67feec50SStephen McConnell * _mapping_inc_missing_count 681991554f2SKenneth D. Merry * @sc: per adapter object 682*67feec50SStephen McConnell * @map_idx: index into the mapping table for the device that is missing 683991554f2SKenneth D. Merry * 684*67feec50SStephen McConnell * Increment the missing count in the mapping table for a SAS, SATA, or PCIe 685*67feec50SStephen McConnell * device that is not responding. If Persitent Mapping is used, increment the 686*67feec50SStephen McConnell * DPM entry as well. Also, add this device to the removal table for possible 687*67feec50SStephen McConnell * removal if a new device is added. 688991554f2SKenneth D. Merry * 689991554f2SKenneth D. Merry * Returns nothing. 690991554f2SKenneth D. Merry */ 691991554f2SKenneth D. Merry static void 692*67feec50SStephen McConnell _mapping_inc_missing_count(struct mpr_softc *sc, u32 map_idx) 693991554f2SKenneth D. Merry { 694991554f2SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 695991554f2SKenneth D. Merry struct dev_mapping_table *mt_entry; 696991554f2SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry; 697991554f2SKenneth D. Merry 698991554f2SKenneth D. Merry if (map_idx == MPR_MAPTABLE_BAD_IDX) { 699*67feec50SStephen McConnell mpr_dprint(sc, MPR_INFO, "%s: device is already removed from " 700*67feec50SStephen McConnell "mapping table\n", __func__); 701*67feec50SStephen McConnell return; 702991554f2SKenneth D. Merry } 703991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 704991554f2SKenneth D. Merry if (!mt_entry->init_complete) { 705991554f2SKenneth D. Merry if (mt_entry->missing_count < MPR_MAX_MISSING_COUNT) 706991554f2SKenneth D. Merry mt_entry->missing_count++; 707991554f2SKenneth D. Merry else 708991554f2SKenneth D. Merry mt_entry->init_complete = 1; 709991554f2SKenneth D. Merry } 710991554f2SKenneth D. Merry if (!mt_entry->missing_count) 711991554f2SKenneth D. Merry mt_entry->missing_count++; 712991554f2SKenneth D. Merry _mapping_add_to_removal_table(sc, mt_entry->dev_handle, 0); 713991554f2SKenneth D. Merry mt_entry->dev_handle = 0; 714991554f2SKenneth D. Merry 715991554f2SKenneth D. Merry if (((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 716991554f2SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) && 717991554f2SKenneth D. Merry sc->is_dpm_enable && !mt_entry->init_complete && 718991554f2SKenneth D. Merry mt_entry->dpm_entry_num != MPR_DPM_BAD_IDX) { 719*67feec50SStephen McConnell dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 + 720991554f2SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 721991554f2SKenneth D. Merry dpm_entry += mt_entry->dpm_entry_num; 722991554f2SKenneth D. Merry dpm_entry->MappingInformation = mt_entry->missing_count; 723991554f2SKenneth D. Merry sc->dpm_flush_entry[mt_entry->dpm_entry_num] = 1; 724991554f2SKenneth D. Merry } 725991554f2SKenneth D. Merry mt_entry->init_complete = 1; 726991554f2SKenneth D. Merry } 727*67feec50SStephen McConnell 728*67feec50SStephen McConnell /** 729*67feec50SStephen McConnell * _mapping_update_missing_count - Update missing count for a device 730*67feec50SStephen McConnell * @sc: per adapter object 731*67feec50SStephen McConnell * @topo_change: Topology change event entry 732*67feec50SStephen McConnell * 733*67feec50SStephen McConnell * Search through the topology change list and if any device is found not 734*67feec50SStephen McConnell * responding it's associated map table entry and DPM entry is updated 735*67feec50SStephen McConnell * 736*67feec50SStephen McConnell * Returns nothing. 737*67feec50SStephen McConnell */ 738*67feec50SStephen McConnell static void 739*67feec50SStephen McConnell _mapping_update_missing_count(struct mpr_softc *sc, 740*67feec50SStephen McConnell struct _map_topology_change *topo_change) 741*67feec50SStephen McConnell { 742*67feec50SStephen McConnell u8 entry; 743*67feec50SStephen McConnell struct _map_phy_change *phy_change; 744*67feec50SStephen McConnell u32 map_idx; 745*67feec50SStephen McConnell 746*67feec50SStephen McConnell for (entry = 0; entry < topo_change->num_entries; entry++) { 747*67feec50SStephen McConnell phy_change = &topo_change->phy_details[entry]; 748*67feec50SStephen McConnell if (!phy_change->dev_handle || (phy_change->reason != 749*67feec50SStephen McConnell MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)) 750*67feec50SStephen McConnell continue; 751*67feec50SStephen McConnell map_idx = _mapping_get_mt_idx_from_handle(sc, phy_change-> 752*67feec50SStephen McConnell dev_handle); 753*67feec50SStephen McConnell phy_change->is_processed = 1; 754*67feec50SStephen McConnell _mapping_inc_missing_count(sc, map_idx); 755*67feec50SStephen McConnell } 756*67feec50SStephen McConnell } 757*67feec50SStephen McConnell 758*67feec50SStephen McConnell /** 759*67feec50SStephen McConnell * _mapping_update_pcie_missing_count - Update missing count for a PCIe device 760*67feec50SStephen McConnell * @sc: per adapter object 761*67feec50SStephen McConnell * @topo_change: Topology change event entry 762*67feec50SStephen McConnell * 763*67feec50SStephen McConnell * Search through the PCIe topology change list and if any device is found not 764*67feec50SStephen McConnell * responding it's associated map table entry and DPM entry is updated 765*67feec50SStephen McConnell * 766*67feec50SStephen McConnell * Returns nothing. 767*67feec50SStephen McConnell */ 768*67feec50SStephen McConnell static void 769*67feec50SStephen McConnell _mapping_update_pcie_missing_count(struct mpr_softc *sc, 770*67feec50SStephen McConnell struct _map_pcie_topology_change *topo_change) 771*67feec50SStephen McConnell { 772*67feec50SStephen McConnell u8 entry; 773*67feec50SStephen McConnell struct _map_port_change *port_change; 774*67feec50SStephen McConnell u32 map_idx; 775*67feec50SStephen McConnell 776*67feec50SStephen McConnell for (entry = 0; entry < topo_change->num_entries; entry++) { 777*67feec50SStephen McConnell port_change = &topo_change->port_details[entry]; 778*67feec50SStephen McConnell if (!port_change->dev_handle || (port_change->reason != 779*67feec50SStephen McConnell MPI26_EVENT_PCIE_TOPO_PS_NOT_RESPONDING)) 780*67feec50SStephen McConnell continue; 781*67feec50SStephen McConnell map_idx = _mapping_get_mt_idx_from_handle(sc, port_change-> 782*67feec50SStephen McConnell dev_handle); 783*67feec50SStephen McConnell port_change->is_processed = 1; 784*67feec50SStephen McConnell _mapping_inc_missing_count(sc, map_idx); 785*67feec50SStephen McConnell } 786991554f2SKenneth D. Merry } 787991554f2SKenneth D. Merry 788991554f2SKenneth D. Merry /** 789991554f2SKenneth D. Merry * _mapping_find_enc_map_space -find map table entries for enclosure 790991554f2SKenneth D. Merry * @sc: per adapter object 791991554f2SKenneth D. Merry * @et_entry: enclosure entry 792991554f2SKenneth D. Merry * 793991554f2SKenneth D. Merry * Search through the mapping table defragment it and provide contiguous 794991554f2SKenneth D. Merry * space in map table for a particular enclosure entry 795991554f2SKenneth D. Merry * 796991554f2SKenneth D. Merry * Returns start index in map table or bad index. 797991554f2SKenneth D. Merry */ 798991554f2SKenneth D. Merry static u32 799991554f2SKenneth D. Merry _mapping_find_enc_map_space(struct mpr_softc *sc, 800991554f2SKenneth D. Merry struct enc_mapping_table *et_entry) 801991554f2SKenneth D. Merry { 802991554f2SKenneth D. Merry u16 vol_mapping_flags; 803991554f2SKenneth D. Merry u32 skip_count, end_of_table, map_idx, enc_idx; 804991554f2SKenneth D. Merry u16 num_found; 805991554f2SKenneth D. Merry u32 start_idx = MPR_MAPTABLE_BAD_IDX; 806991554f2SKenneth D. Merry struct dev_mapping_table *mt_entry; 807991554f2SKenneth D. Merry struct enc_mapping_table *enc_entry; 808991554f2SKenneth D. Merry unsigned char done_flag = 0, found_space; 809991554f2SKenneth D. Merry u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs); 810991554f2SKenneth D. Merry 811991554f2SKenneth D. Merry skip_count = sc->num_rsvd_entries; 812991554f2SKenneth D. Merry num_found = 0; 813991554f2SKenneth D. Merry 814991554f2SKenneth D. Merry vol_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) & 815991554f2SKenneth D. Merry MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; 816991554f2SKenneth D. Merry 817991554f2SKenneth D. Merry if (!sc->ir_firmware) 818991554f2SKenneth D. Merry end_of_table = sc->max_devices; 819991554f2SKenneth D. Merry else if (vol_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) 820991554f2SKenneth D. Merry end_of_table = sc->max_devices; 821991554f2SKenneth D. Merry else 822991554f2SKenneth D. Merry end_of_table = sc->max_devices - sc->max_volumes; 823991554f2SKenneth D. Merry 824991554f2SKenneth D. Merry for (map_idx = (max_num_phy_ids + skip_count); 825991554f2SKenneth D. Merry map_idx < end_of_table; map_idx++) { 826991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 827991554f2SKenneth D. Merry if ((et_entry->enclosure_id == mt_entry->physical_id) && 828991554f2SKenneth D. Merry (!mt_entry->phy_bits || (mt_entry->phy_bits & 829991554f2SKenneth D. Merry et_entry->phy_bits))) { 830991554f2SKenneth D. Merry num_found += 1; 831991554f2SKenneth D. Merry if (num_found == et_entry->num_slots) { 832991554f2SKenneth D. Merry start_idx = (map_idx - num_found) + 1; 833991554f2SKenneth D. Merry return start_idx; 834991554f2SKenneth D. Merry } 835991554f2SKenneth D. Merry } else 836991554f2SKenneth D. Merry num_found = 0; 837991554f2SKenneth D. Merry } 838991554f2SKenneth D. Merry for (map_idx = (max_num_phy_ids + skip_count); 839991554f2SKenneth D. Merry map_idx < end_of_table; map_idx++) { 840991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 841991554f2SKenneth D. Merry if (!(mt_entry->device_info & MPR_DEV_RESERVED)) { 842991554f2SKenneth D. Merry num_found += 1; 843991554f2SKenneth D. Merry if (num_found == et_entry->num_slots) { 844991554f2SKenneth D. Merry start_idx = (map_idx - num_found) + 1; 845991554f2SKenneth D. Merry return start_idx; 846991554f2SKenneth D. Merry } 847991554f2SKenneth D. Merry } else 848991554f2SKenneth D. Merry num_found = 0; 849991554f2SKenneth D. Merry } 850991554f2SKenneth D. Merry 851991554f2SKenneth D. Merry while (!done_flag) { 852991554f2SKenneth D. Merry enc_idx = _mapping_get_high_missing_et_idx(sc); 853991554f2SKenneth D. Merry if (enc_idx == MPR_ENCTABLE_BAD_IDX) 854991554f2SKenneth D. Merry return MPR_MAPTABLE_BAD_IDX; 855991554f2SKenneth D. Merry enc_entry = &sc->enclosure_table[enc_idx]; 856991554f2SKenneth D. Merry /*VSP FIXME*/ 857991554f2SKenneth D. Merry enc_entry->skip_search = 1; 858991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[enc_entry->start_index]; 859991554f2SKenneth D. Merry for (map_idx = enc_entry->start_index; map_idx < 860991554f2SKenneth D. Merry (enc_entry->start_index + enc_entry->num_slots); map_idx++, 861991554f2SKenneth D. Merry mt_entry++) 862991554f2SKenneth D. Merry mt_entry->device_info &= ~MPR_DEV_RESERVED; 863991554f2SKenneth D. Merry found_space = 0; 864991554f2SKenneth D. Merry for (map_idx = (max_num_phy_ids + 865991554f2SKenneth D. Merry skip_count); map_idx < end_of_table; map_idx++) { 866991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 867991554f2SKenneth D. Merry if (!(mt_entry->device_info & MPR_DEV_RESERVED)) { 868991554f2SKenneth D. Merry num_found += 1; 869991554f2SKenneth D. Merry if (num_found == et_entry->num_slots) { 870991554f2SKenneth D. Merry start_idx = (map_idx - num_found) + 1; 871991554f2SKenneth D. Merry found_space = 1; 872991554f2SKenneth D. Merry } 873991554f2SKenneth D. Merry } else 874991554f2SKenneth D. Merry num_found = 0; 875991554f2SKenneth D. Merry } 876991554f2SKenneth D. Merry 877991554f2SKenneth D. Merry if (!found_space) 878991554f2SKenneth D. Merry continue; 879991554f2SKenneth D. Merry for (map_idx = start_idx; map_idx < (start_idx + num_found); 880991554f2SKenneth D. Merry map_idx++) { 881991554f2SKenneth D. Merry enc_entry = sc->enclosure_table; 882991554f2SKenneth D. Merry for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; 883991554f2SKenneth D. Merry enc_idx++, enc_entry++) { 884991554f2SKenneth D. Merry if (map_idx < enc_entry->start_index || 885991554f2SKenneth D. Merry map_idx > (enc_entry->start_index + 886991554f2SKenneth D. Merry enc_entry->num_slots)) 887991554f2SKenneth D. Merry continue; 888991554f2SKenneth D. Merry if (!enc_entry->removal_flag) { 889991554f2SKenneth D. Merry enc_entry->removal_flag = 1; 890991554f2SKenneth D. Merry _mapping_add_to_removal_table(sc, 0, 891991554f2SKenneth D. Merry enc_entry->dpm_entry_num); 892991554f2SKenneth D. Merry } 893991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 894991554f2SKenneth D. Merry if (mt_entry->device_info & 895991554f2SKenneth D. Merry MPR_MAP_IN_USE) { 896991554f2SKenneth D. Merry _mapping_add_to_removal_table(sc, 897991554f2SKenneth D. Merry mt_entry->dev_handle, 0); 898991554f2SKenneth D. Merry _mapping_clear_map_entry(mt_entry); 899991554f2SKenneth D. Merry } 900991554f2SKenneth D. Merry if (map_idx == (enc_entry->start_index + 901991554f2SKenneth D. Merry enc_entry->num_slots - 1)) 902991554f2SKenneth D. Merry _mapping_clear_enc_entry(et_entry); 903991554f2SKenneth D. Merry } 904991554f2SKenneth D. Merry } 905991554f2SKenneth D. Merry enc_entry = sc->enclosure_table; 906991554f2SKenneth D. Merry for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; 907991554f2SKenneth D. Merry enc_idx++, enc_entry++) { 908991554f2SKenneth D. Merry if (!enc_entry->removal_flag) { 909991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[enc_entry-> 910991554f2SKenneth D. Merry start_index]; 911991554f2SKenneth D. Merry for (map_idx = enc_entry->start_index; map_idx < 912991554f2SKenneth D. Merry (enc_entry->start_index + 913991554f2SKenneth D. Merry enc_entry->num_slots); map_idx++, 914991554f2SKenneth D. Merry mt_entry++) 915991554f2SKenneth D. Merry mt_entry->device_info |= 916991554f2SKenneth D. Merry MPR_DEV_RESERVED; 917991554f2SKenneth D. Merry et_entry->skip_search = 0; 918991554f2SKenneth D. Merry } 919991554f2SKenneth D. Merry } 920991554f2SKenneth D. Merry done_flag = 1; 921991554f2SKenneth D. Merry } 922991554f2SKenneth D. Merry return start_idx; 923991554f2SKenneth D. Merry } 924991554f2SKenneth D. Merry 925991554f2SKenneth D. Merry /** 926991554f2SKenneth D. Merry * _mapping_get_dev_info -get information about newly added devices 927991554f2SKenneth D. Merry * @sc: per adapter object 928991554f2SKenneth D. Merry * @topo_change: Topology change event entry 929991554f2SKenneth D. Merry * 930991554f2SKenneth D. Merry * Search through the topology change event list and issues sas device pg0 931991554f2SKenneth D. Merry * requests for the newly added device and reserved entries in tables 932991554f2SKenneth D. Merry * 933991554f2SKenneth D. Merry * Returns nothing 934991554f2SKenneth D. Merry */ 935991554f2SKenneth D. Merry static void 936991554f2SKenneth D. Merry _mapping_get_dev_info(struct mpr_softc *sc, 937991554f2SKenneth D. Merry struct _map_topology_change *topo_change) 938991554f2SKenneth D. Merry { 939991554f2SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 940991554f2SKenneth D. Merry Mpi2ConfigReply_t mpi_reply; 941991554f2SKenneth D. Merry Mpi2SasDevicePage0_t sas_device_pg0; 942a2c14879SStephen McConnell u8 entry, enc_idx, phy_idx, sata_end_device; 943991554f2SKenneth D. Merry u32 map_idx, index, device_info; 944991554f2SKenneth D. Merry struct _map_phy_change *phy_change, *tmp_phy_change; 945991554f2SKenneth D. Merry uint64_t sas_address; 946991554f2SKenneth D. Merry struct enc_mapping_table *et_entry; 947991554f2SKenneth D. Merry struct dev_mapping_table *mt_entry; 948991554f2SKenneth D. Merry u8 add_code = MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED; 949a2c14879SStephen McConnell int rc = 1; 950991554f2SKenneth D. Merry 951991554f2SKenneth D. Merry for (entry = 0; entry < topo_change->num_entries; entry++) { 952991554f2SKenneth D. Merry phy_change = &topo_change->phy_details[entry]; 953991554f2SKenneth D. Merry if (phy_change->is_processed || !phy_change->dev_handle || 954991554f2SKenneth D. Merry phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED) 955991554f2SKenneth D. Merry continue; 956991554f2SKenneth D. Merry if (mpr_config_get_sas_device_pg0(sc, &mpi_reply, 957991554f2SKenneth D. Merry &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, 958991554f2SKenneth D. Merry phy_change->dev_handle)) { 959991554f2SKenneth D. Merry phy_change->is_processed = 1; 960991554f2SKenneth D. Merry continue; 961991554f2SKenneth D. Merry } 962991554f2SKenneth D. Merry 963a2c14879SStephen McConnell /* 964a2c14879SStephen McConnell * Always get SATA Identify information because this is used 965a2c14879SStephen McConnell * to determine if Start/Stop Unit should be sent to the drive 966a2c14879SStephen McConnell * when the system is shutdown. 967a2c14879SStephen McConnell */ 968991554f2SKenneth D. Merry device_info = le32toh(sas_device_pg0.DeviceInfo); 969991554f2SKenneth D. Merry sas_address = sas_device_pg0.SASAddress.High; 970991554f2SKenneth D. Merry sas_address = (sas_address << 32) | 971991554f2SKenneth D. Merry sas_device_pg0.SASAddress.Low; 972a2c14879SStephen McConnell sata_end_device = 0; 973a2c14879SStephen McConnell if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) && 974a2c14879SStephen McConnell (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) { 975a2c14879SStephen McConnell sata_end_device = 1; 976a2c14879SStephen McConnell rc = mprsas_get_sas_address_for_sata_disk(sc, 977a2c14879SStephen McConnell &sas_address, phy_change->dev_handle, device_info, 978a2c14879SStephen McConnell &phy_change->is_SATA_SSD); 979a2c14879SStephen McConnell if (rc) { 980a2c14879SStephen McConnell mpr_dprint(sc, MPR_ERROR, "%s: failed to get " 981a2c14879SStephen McConnell "disk type (SSD or HDD) and SAS Address " 982a2c14879SStephen McConnell "for SATA device with handle 0x%04x\n", 983a2c14879SStephen McConnell __func__, phy_change->dev_handle); 984a2c14879SStephen McConnell } else { 985a2c14879SStephen McConnell mpr_dprint(sc, MPR_INFO, "SAS Address for SATA " 986a2c14879SStephen McConnell "device = %jx\n", sas_address); 987991554f2SKenneth D. Merry } 988a2c14879SStephen McConnell } 989a2c14879SStephen McConnell 990991554f2SKenneth D. Merry phy_change->physical_id = sas_address; 991991554f2SKenneth D. Merry phy_change->slot = le16toh(sas_device_pg0.Slot); 992*67feec50SStephen McConnell phy_change->device_info = device_info; 993991554f2SKenneth D. Merry 994991554f2SKenneth D. Merry if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 995991554f2SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 996991554f2SKenneth D. Merry enc_idx = _mapping_get_enc_idx_from_handle(sc, 997991554f2SKenneth D. Merry topo_change->enc_handle); 998991554f2SKenneth D. Merry if (enc_idx == MPR_ENCTABLE_BAD_IDX) { 999991554f2SKenneth D. Merry phy_change->is_processed = 1; 1000a2c14879SStephen McConnell mpr_dprint(sc, MPR_MAPPING, "%s: failed to add " 1001a2c14879SStephen McConnell "the device with handle 0x%04x because the " 1002a2c14879SStephen McConnell "enclosure is not in the mapping table\n", 1003a2c14879SStephen McConnell __func__, phy_change->dev_handle); 1004991554f2SKenneth D. Merry continue; 1005991554f2SKenneth D. Merry } 1006991554f2SKenneth D. Merry if (!((phy_change->device_info & 1007991554f2SKenneth D. Merry MPI2_SAS_DEVICE_INFO_END_DEVICE) && 1008991554f2SKenneth D. Merry (phy_change->device_info & 1009991554f2SKenneth D. Merry (MPI2_SAS_DEVICE_INFO_SSP_TARGET | 1010991554f2SKenneth D. Merry MPI2_SAS_DEVICE_INFO_STP_TARGET | 1011991554f2SKenneth D. Merry MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))) { 1012991554f2SKenneth D. Merry phy_change->is_processed = 1; 1013991554f2SKenneth D. Merry continue; 1014991554f2SKenneth D. Merry } 1015991554f2SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx]; 1016991554f2SKenneth D. Merry if (et_entry->start_index != MPR_MAPTABLE_BAD_IDX) 1017991554f2SKenneth D. Merry continue; 1018991554f2SKenneth D. Merry if (!topo_change->exp_handle) { 1019991554f2SKenneth D. Merry map_idx = sc->num_rsvd_entries; 1020991554f2SKenneth D. Merry et_entry->start_index = map_idx; 1021991554f2SKenneth D. Merry } else { 1022991554f2SKenneth D. Merry map_idx = _mapping_find_enc_map_space(sc, 1023991554f2SKenneth D. Merry et_entry); 1024991554f2SKenneth D. Merry et_entry->start_index = map_idx; 1025991554f2SKenneth D. Merry if (et_entry->start_index == 1026991554f2SKenneth D. Merry MPR_MAPTABLE_BAD_IDX) { 1027991554f2SKenneth D. Merry phy_change->is_processed = 1; 1028991554f2SKenneth D. Merry for (phy_idx = 0; phy_idx < 1029991554f2SKenneth D. Merry topo_change->num_entries; 1030991554f2SKenneth D. Merry phy_idx++) { 1031991554f2SKenneth D. Merry tmp_phy_change = 1032991554f2SKenneth D. Merry &topo_change->phy_details 1033991554f2SKenneth D. Merry [phy_idx]; 1034991554f2SKenneth D. Merry if (tmp_phy_change->reason == 1035991554f2SKenneth D. Merry add_code) 1036991554f2SKenneth D. Merry tmp_phy_change-> 1037991554f2SKenneth D. Merry is_processed = 1; 1038991554f2SKenneth D. Merry } 1039991554f2SKenneth D. Merry break; 1040991554f2SKenneth D. Merry } 1041991554f2SKenneth D. Merry } 1042*67feec50SStephen McConnell 1043*67feec50SStephen McConnell /* Found space in enclosure for mapping entry */ 1044991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 1045991554f2SKenneth D. Merry for (index = map_idx; index < (et_entry->num_slots 1046991554f2SKenneth D. Merry + map_idx); index++, mt_entry++) { 1047991554f2SKenneth D. Merry mt_entry->device_info = MPR_DEV_RESERVED; 1048991554f2SKenneth D. Merry mt_entry->physical_id = et_entry->enclosure_id; 1049991554f2SKenneth D. Merry mt_entry->phy_bits = et_entry->phy_bits; 1050*67feec50SStephen McConnell mt_entry->missing_count = 0; 1051*67feec50SStephen McConnell } 1052*67feec50SStephen McConnell } 1053*67feec50SStephen McConnell } 1054*67feec50SStephen McConnell } 1055*67feec50SStephen McConnell 1056*67feec50SStephen McConnell /** 1057*67feec50SStephen McConnell * _mapping_get_pcie_dev_info -get information about newly added PCIe devices 1058*67feec50SStephen McConnell * @sc: per adapter object 1059*67feec50SStephen McConnell * @topo_change: Topology change event entry 1060*67feec50SStephen McConnell * 1061*67feec50SStephen McConnell * Searches through the PCIe topology change event list and issues PCIe device 1062*67feec50SStephen McConnell * pg0 requests for the newly added PCIe device. If the device is in an 1063*67feec50SStephen McConnell * enclosure, search for available space in the enclosure mapping table for the 1064*67feec50SStephen McConnell * device and reserve that space. 1065*67feec50SStephen McConnell * 1066*67feec50SStephen McConnell * Returns nothing 1067*67feec50SStephen McConnell */ 1068*67feec50SStephen McConnell static void 1069*67feec50SStephen McConnell _mapping_get_pcie_dev_info(struct mpr_softc *sc, 1070*67feec50SStephen McConnell struct _map_pcie_topology_change *topo_change) 1071*67feec50SStephen McConnell { 1072*67feec50SStephen McConnell u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1073*67feec50SStephen McConnell Mpi2ConfigReply_t mpi_reply; 1074*67feec50SStephen McConnell Mpi26PCIeDevicePage0_t pcie_device_pg0; 1075*67feec50SStephen McConnell u8 entry, enc_idx, port_idx; 1076*67feec50SStephen McConnell u32 map_idx, index; 1077*67feec50SStephen McConnell struct _map_port_change *port_change, *tmp_port_change; 1078*67feec50SStephen McConnell uint64_t pcie_wwid; 1079*67feec50SStephen McConnell struct enc_mapping_table *et_entry; 1080*67feec50SStephen McConnell struct dev_mapping_table *mt_entry; 1081*67feec50SStephen McConnell u8 add_code = MPI26_EVENT_PCIE_TOPO_PS_DEV_ADDED; 1082*67feec50SStephen McConnell 1083*67feec50SStephen McConnell for (entry = 0; entry < topo_change->num_entries; entry++) { 1084*67feec50SStephen McConnell port_change = &topo_change->port_details[entry]; 1085*67feec50SStephen McConnell if (port_change->is_processed || !port_change->dev_handle || 1086*67feec50SStephen McConnell port_change->reason != MPI26_EVENT_PCIE_TOPO_PS_DEV_ADDED) 1087*67feec50SStephen McConnell continue; 1088*67feec50SStephen McConnell if (mpr_config_get_pcie_device_pg0(sc, &mpi_reply, 1089*67feec50SStephen McConnell &pcie_device_pg0, MPI26_PCIE_DEVICE_PGAD_FORM_HANDLE, 1090*67feec50SStephen McConnell port_change->dev_handle)) { 1091*67feec50SStephen McConnell port_change->is_processed = 1; 1092*67feec50SStephen McConnell continue; 1093*67feec50SStephen McConnell } 1094*67feec50SStephen McConnell 1095*67feec50SStephen McConnell pcie_wwid = pcie_device_pg0.WWID.High; 1096*67feec50SStephen McConnell pcie_wwid = (pcie_wwid << 32) | pcie_device_pg0.WWID.Low; 1097*67feec50SStephen McConnell port_change->physical_id = pcie_wwid; 1098*67feec50SStephen McConnell port_change->slot = le16toh(pcie_device_pg0.Slot); 1099*67feec50SStephen McConnell port_change->device_info = le32toh(pcie_device_pg0.DeviceInfo); 1100*67feec50SStephen McConnell 1101*67feec50SStephen McConnell if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1102*67feec50SStephen McConnell MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 1103*67feec50SStephen McConnell enc_idx = _mapping_get_enc_idx_from_handle(sc, 1104*67feec50SStephen McConnell topo_change->enc_handle); 1105*67feec50SStephen McConnell if (enc_idx == MPR_ENCTABLE_BAD_IDX) { 1106*67feec50SStephen McConnell port_change->is_processed = 1; 1107*67feec50SStephen McConnell mpr_dprint(sc, MPR_MAPPING, "%s: failed to add " 1108*67feec50SStephen McConnell "the device with handle 0x%04x because the " 1109*67feec50SStephen McConnell "enclosure is not in the mapping table\n", 1110*67feec50SStephen McConnell __func__, port_change->dev_handle); 1111*67feec50SStephen McConnell continue; 1112*67feec50SStephen McConnell } 1113*67feec50SStephen McConnell if (!(port_change->device_info & 1114*67feec50SStephen McConnell MPI26_PCIE_DEVINFO_NVME)) { 1115*67feec50SStephen McConnell port_change->is_processed = 1; 1116*67feec50SStephen McConnell continue; 1117*67feec50SStephen McConnell } 1118*67feec50SStephen McConnell et_entry = &sc->enclosure_table[enc_idx]; 1119*67feec50SStephen McConnell if (et_entry->start_index != MPR_MAPTABLE_BAD_IDX) 1120*67feec50SStephen McConnell continue; 1121*67feec50SStephen McConnell if (!topo_change->switch_dev_handle) { 1122*67feec50SStephen McConnell map_idx = sc->num_rsvd_entries; 1123*67feec50SStephen McConnell et_entry->start_index = map_idx; 1124*67feec50SStephen McConnell } else { 1125*67feec50SStephen McConnell map_idx = _mapping_find_enc_map_space(sc, 1126*67feec50SStephen McConnell et_entry); 1127*67feec50SStephen McConnell et_entry->start_index = map_idx; 1128*67feec50SStephen McConnell if (et_entry->start_index == 1129*67feec50SStephen McConnell MPR_MAPTABLE_BAD_IDX) { 1130*67feec50SStephen McConnell port_change->is_processed = 1; 1131*67feec50SStephen McConnell for (port_idx = 0; port_idx < 1132*67feec50SStephen McConnell topo_change->num_entries; 1133*67feec50SStephen McConnell port_idx++) { 1134*67feec50SStephen McConnell tmp_port_change = 1135*67feec50SStephen McConnell &topo_change->port_details 1136*67feec50SStephen McConnell [port_idx]; 1137*67feec50SStephen McConnell if (tmp_port_change->reason == 1138*67feec50SStephen McConnell add_code) 1139*67feec50SStephen McConnell tmp_port_change-> 1140*67feec50SStephen McConnell is_processed = 1; 1141*67feec50SStephen McConnell } 1142*67feec50SStephen McConnell break; 1143*67feec50SStephen McConnell } 1144*67feec50SStephen McConnell } 1145*67feec50SStephen McConnell 1146*67feec50SStephen McConnell /* Found space in enclosure for mapping entry */ 1147*67feec50SStephen McConnell mt_entry = &sc->mapping_table[map_idx]; 1148*67feec50SStephen McConnell for (index = map_idx; index < (et_entry->num_slots 1149*67feec50SStephen McConnell + map_idx); index++, mt_entry++) { 1150*67feec50SStephen McConnell mt_entry->device_info = MPR_DEV_RESERVED; 1151*67feec50SStephen McConnell mt_entry->physical_id = et_entry->enclosure_id; 1152*67feec50SStephen McConnell mt_entry->phy_bits = et_entry->phy_bits; 1153*67feec50SStephen McConnell mt_entry->missing_count = 0; 1154991554f2SKenneth D. Merry } 1155991554f2SKenneth D. Merry } 1156991554f2SKenneth D. Merry } 1157991554f2SKenneth D. Merry } 1158991554f2SKenneth D. Merry 1159991554f2SKenneth D. Merry /** 1160991554f2SKenneth D. Merry * _mapping_set_mid_to_eid -set map table data from enclosure table 1161991554f2SKenneth D. Merry * @sc: per adapter object 1162991554f2SKenneth D. Merry * @et_entry: enclosure entry 1163991554f2SKenneth D. Merry * 1164991554f2SKenneth D. Merry * Returns nothing 1165991554f2SKenneth D. Merry */ 1166991554f2SKenneth D. Merry static inline void 1167991554f2SKenneth D. Merry _mapping_set_mid_to_eid(struct mpr_softc *sc, 1168991554f2SKenneth D. Merry struct enc_mapping_table *et_entry) 1169991554f2SKenneth D. Merry { 1170991554f2SKenneth D. Merry struct dev_mapping_table *mt_entry; 1171991554f2SKenneth D. Merry u16 slots = et_entry->num_slots, map_idx; 1172991554f2SKenneth D. Merry u32 start_idx = et_entry->start_index; 1173991554f2SKenneth D. Merry if (start_idx != MPR_MAPTABLE_BAD_IDX) { 1174991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[start_idx]; 1175991554f2SKenneth D. Merry for (map_idx = 0; map_idx < slots; map_idx++, mt_entry++) 1176991554f2SKenneth D. Merry mt_entry->physical_id = et_entry->enclosure_id; 1177991554f2SKenneth D. Merry } 1178991554f2SKenneth D. Merry } 1179991554f2SKenneth D. Merry 1180991554f2SKenneth D. Merry /** 1181991554f2SKenneth D. Merry * _mapping_clear_removed_entries - mark the entries to be cleared 1182991554f2SKenneth D. Merry * @sc: per adapter object 1183991554f2SKenneth D. Merry * 1184991554f2SKenneth D. Merry * Search through the removal table and mark the entries which needs to be 1185991554f2SKenneth D. Merry * flushed to DPM and also updates the map table and enclosure table by 1186991554f2SKenneth D. Merry * clearing the corresponding entries. 1187991554f2SKenneth D. Merry * 1188991554f2SKenneth D. Merry * Returns nothing 1189991554f2SKenneth D. Merry */ 1190991554f2SKenneth D. Merry static void 1191991554f2SKenneth D. Merry _mapping_clear_removed_entries(struct mpr_softc *sc) 1192991554f2SKenneth D. Merry { 1193991554f2SKenneth D. Merry u32 remove_idx; 1194991554f2SKenneth D. Merry struct map_removal_table *remove_entry; 1195991554f2SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry; 1196991554f2SKenneth D. Merry u8 done_flag = 0, num_entries, m, i; 1197991554f2SKenneth D. Merry struct enc_mapping_table *et_entry, *from, *to; 1198991554f2SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1199991554f2SKenneth D. Merry 1200991554f2SKenneth D. Merry if (sc->is_dpm_enable) { 1201991554f2SKenneth D. Merry remove_entry = sc->removal_table; 1202991554f2SKenneth D. Merry for (remove_idx = 0; remove_idx < sc->max_devices; 1203991554f2SKenneth D. Merry remove_idx++, remove_entry++) { 1204991554f2SKenneth D. Merry if (remove_entry->dpm_entry_num != MPR_DPM_BAD_IDX) { 1205991554f2SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *) 1206991554f2SKenneth D. Merry ((u8 *) sc->dpm_pg0 + 1207991554f2SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 1208991554f2SKenneth D. Merry dpm_entry += remove_entry->dpm_entry_num; 1209991554f2SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low = 0; 1210991554f2SKenneth D. Merry dpm_entry->PhysicalIdentifier.High = 0; 1211991554f2SKenneth D. Merry dpm_entry->DeviceIndex = 0; 1212991554f2SKenneth D. Merry dpm_entry->MappingInformation = 0; 1213991554f2SKenneth D. Merry dpm_entry->PhysicalBitsMapping = 0; 1214991554f2SKenneth D. Merry sc->dpm_flush_entry[remove_entry-> 1215991554f2SKenneth D. Merry dpm_entry_num] = 1; 1216991554f2SKenneth D. Merry sc->dpm_entry_used[remove_entry->dpm_entry_num] 1217991554f2SKenneth D. Merry = 0; 1218991554f2SKenneth D. Merry remove_entry->dpm_entry_num = MPR_DPM_BAD_IDX; 1219991554f2SKenneth D. Merry } 1220991554f2SKenneth D. Merry } 1221991554f2SKenneth D. Merry } 1222991554f2SKenneth D. Merry if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1223991554f2SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 1224991554f2SKenneth D. Merry num_entries = sc->num_enc_table_entries; 1225991554f2SKenneth D. Merry while (!done_flag) { 1226991554f2SKenneth D. Merry done_flag = 1; 1227991554f2SKenneth D. Merry et_entry = sc->enclosure_table; 1228991554f2SKenneth D. Merry for (i = 0; i < num_entries; i++, et_entry++) { 1229991554f2SKenneth D. Merry if (!et_entry->enc_handle && et_entry-> 1230991554f2SKenneth D. Merry init_complete) { 1231991554f2SKenneth D. Merry done_flag = 0; 1232991554f2SKenneth D. Merry if (i != (num_entries - 1)) { 1233991554f2SKenneth D. Merry from = &sc->enclosure_table 1234991554f2SKenneth D. Merry [i+1]; 1235991554f2SKenneth D. Merry to = &sc->enclosure_table[i]; 1236991554f2SKenneth D. Merry for (m = i; m < (num_entries - 1237991554f2SKenneth D. Merry 1); m++, from++, to++) { 1238991554f2SKenneth D. Merry _mapping_set_mid_to_eid 1239991554f2SKenneth D. Merry (sc, to); 1240991554f2SKenneth D. Merry *to = *from; 1241991554f2SKenneth D. Merry } 1242991554f2SKenneth D. Merry _mapping_clear_enc_entry(to); 1243991554f2SKenneth D. Merry sc->num_enc_table_entries--; 1244991554f2SKenneth D. Merry num_entries = 1245991554f2SKenneth D. Merry sc->num_enc_table_entries; 1246991554f2SKenneth D. Merry } else { 1247991554f2SKenneth D. Merry _mapping_clear_enc_entry 1248991554f2SKenneth D. Merry (et_entry); 1249991554f2SKenneth D. Merry sc->num_enc_table_entries--; 1250991554f2SKenneth D. Merry num_entries = 1251991554f2SKenneth D. Merry sc->num_enc_table_entries; 1252991554f2SKenneth D. Merry } 1253991554f2SKenneth D. Merry } 1254991554f2SKenneth D. Merry } 1255991554f2SKenneth D. Merry } 1256991554f2SKenneth D. Merry } 1257991554f2SKenneth D. Merry } 1258991554f2SKenneth D. Merry 1259991554f2SKenneth D. Merry /** 1260991554f2SKenneth D. Merry * _mapping_add_new_device -Add the new device into mapping table 1261991554f2SKenneth D. Merry * @sc: per adapter object 1262991554f2SKenneth D. Merry * @topo_change: Topology change event entry 1263991554f2SKenneth D. Merry * 1264*67feec50SStephen McConnell * Search through the topology change event list and update map table, 1265*67feec50SStephen McConnell * enclosure table and DPM pages for the newly added devices. 1266991554f2SKenneth D. Merry * 1267991554f2SKenneth D. Merry * Returns nothing 1268991554f2SKenneth D. Merry */ 1269991554f2SKenneth D. Merry static void 1270991554f2SKenneth D. Merry _mapping_add_new_device(struct mpr_softc *sc, 1271991554f2SKenneth D. Merry struct _map_topology_change *topo_change) 1272991554f2SKenneth D. Merry { 1273991554f2SKenneth D. Merry u8 enc_idx, missing_cnt, is_removed = 0; 1274991554f2SKenneth D. Merry u16 dpm_idx; 1275991554f2SKenneth D. Merry u32 search_idx, map_idx; 1276991554f2SKenneth D. Merry u32 entry; 1277991554f2SKenneth D. Merry struct dev_mapping_table *mt_entry; 1278991554f2SKenneth D. Merry struct enc_mapping_table *et_entry; 1279991554f2SKenneth D. Merry struct _map_phy_change *phy_change; 1280991554f2SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1281991554f2SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry; 1282991554f2SKenneth D. Merry uint64_t temp64_var; 1283991554f2SKenneth D. Merry u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT; 1284991554f2SKenneth D. Merry u8 hdr_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER); 1285991554f2SKenneth D. Merry u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs); 1286991554f2SKenneth D. Merry 1287991554f2SKenneth D. Merry for (entry = 0; entry < topo_change->num_entries; entry++) { 1288991554f2SKenneth D. Merry phy_change = &topo_change->phy_details[entry]; 1289991554f2SKenneth D. Merry if (phy_change->is_processed) 1290991554f2SKenneth D. Merry continue; 1291991554f2SKenneth D. Merry if (phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED || 1292991554f2SKenneth D. Merry !phy_change->dev_handle) { 1293991554f2SKenneth D. Merry phy_change->is_processed = 1; 1294991554f2SKenneth D. Merry continue; 1295991554f2SKenneth D. Merry } 1296991554f2SKenneth D. Merry if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1297991554f2SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 1298991554f2SKenneth D. Merry enc_idx = _mapping_get_enc_idx_from_handle 1299991554f2SKenneth D. Merry (sc, topo_change->enc_handle); 1300991554f2SKenneth D. Merry if (enc_idx == MPR_ENCTABLE_BAD_IDX) { 1301991554f2SKenneth D. Merry phy_change->is_processed = 1; 1302*67feec50SStephen McConnell mpr_dprint(sc, MPR_ERROR, "%s: failed to add " 1303*67feec50SStephen McConnell "the device with handle 0x%04x because the " 1304*67feec50SStephen McConnell "enclosure is not in the mapping table\n", 1305*67feec50SStephen McConnell __func__, phy_change->dev_handle); 1306991554f2SKenneth D. Merry continue; 1307991554f2SKenneth D. Merry } 1308991554f2SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx]; 1309991554f2SKenneth D. Merry if (et_entry->start_index == MPR_MAPTABLE_BAD_IDX) { 1310991554f2SKenneth D. Merry phy_change->is_processed = 1; 1311991554f2SKenneth D. Merry if (!sc->mt_full_retry) { 1312991554f2SKenneth D. Merry sc->mt_add_device_failed = 1; 1313991554f2SKenneth D. Merry continue; 1314991554f2SKenneth D. Merry } 1315*67feec50SStephen McConnell mpr_dprint(sc, MPR_INFO, "%s: failed to add " 1316*67feec50SStephen McConnell "the device with handle 0x%04x because " 1317*67feec50SStephen McConnell "there is no free space available in the " 1318*67feec50SStephen McConnell "mapping table\n", __func__, 1319*67feec50SStephen McConnell phy_change->dev_handle); 1320991554f2SKenneth D. Merry continue; 1321991554f2SKenneth D. Merry } 1322991554f2SKenneth D. Merry map_idx = et_entry->start_index + phy_change->slot - 1323991554f2SKenneth D. Merry et_entry->start_slot; 1324991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 1325991554f2SKenneth D. Merry mt_entry->physical_id = phy_change->physical_id; 1326991554f2SKenneth D. Merry mt_entry->channel = 0; 1327991554f2SKenneth D. Merry mt_entry->id = map_idx; 1328991554f2SKenneth D. Merry mt_entry->dev_handle = phy_change->dev_handle; 1329991554f2SKenneth D. Merry mt_entry->missing_count = 0; 1330991554f2SKenneth D. Merry mt_entry->dpm_entry_num = et_entry->dpm_entry_num; 1331991554f2SKenneth D. Merry mt_entry->device_info = phy_change->device_info | 1332991554f2SKenneth D. Merry (MPR_DEV_RESERVED | MPR_MAP_IN_USE); 1333991554f2SKenneth D. Merry if (sc->is_dpm_enable) { 1334991554f2SKenneth D. Merry dpm_idx = et_entry->dpm_entry_num; 1335991554f2SKenneth D. Merry if (dpm_idx == MPR_DPM_BAD_IDX) 1336991554f2SKenneth D. Merry dpm_idx = _mapping_get_dpm_idx_from_id 1337991554f2SKenneth D. Merry (sc, et_entry->enclosure_id, 1338991554f2SKenneth D. Merry et_entry->phy_bits); 1339991554f2SKenneth D. Merry if (dpm_idx == MPR_DPM_BAD_IDX) { 1340991554f2SKenneth D. Merry dpm_idx = _mapping_get_free_dpm_idx(sc); 1341991554f2SKenneth D. Merry if (dpm_idx != MPR_DPM_BAD_IDX) { 1342991554f2SKenneth D. Merry dpm_entry = 1343991554f2SKenneth D. Merry (Mpi2DriverMap0Entry_t *) 1344991554f2SKenneth D. Merry ((u8 *) sc->dpm_pg0 + 1345991554f2SKenneth D. Merry hdr_sz); 1346991554f2SKenneth D. Merry dpm_entry += dpm_idx; 1347991554f2SKenneth D. Merry dpm_entry-> 1348991554f2SKenneth D. Merry PhysicalIdentifier.Low = 1349991554f2SKenneth D. Merry (0xFFFFFFFF & 1350991554f2SKenneth D. Merry et_entry->enclosure_id); 1351991554f2SKenneth D. Merry dpm_entry-> 1352991554f2SKenneth D. Merry PhysicalIdentifier.High = 1353991554f2SKenneth D. Merry ( et_entry->enclosure_id 1354991554f2SKenneth D. Merry >> 32); 1355991554f2SKenneth D. Merry dpm_entry->DeviceIndex = 1356991554f2SKenneth D. Merry (U16)et_entry->start_index; 1357991554f2SKenneth D. Merry dpm_entry->MappingInformation = 1358991554f2SKenneth D. Merry et_entry->num_slots; 1359991554f2SKenneth D. Merry dpm_entry->MappingInformation 1360991554f2SKenneth D. Merry <<= map_shift; 1361991554f2SKenneth D. Merry dpm_entry->PhysicalBitsMapping 1362991554f2SKenneth D. Merry = et_entry->phy_bits; 1363991554f2SKenneth D. Merry et_entry->dpm_entry_num = 1364991554f2SKenneth D. Merry dpm_idx; 1365991554f2SKenneth D. Merry /* FIXME Do I need to set the dpm_idxin mt_entry too */ 1366991554f2SKenneth D. Merry sc->dpm_entry_used[dpm_idx] = 1; 1367991554f2SKenneth D. Merry sc->dpm_flush_entry[dpm_idx] = 1368991554f2SKenneth D. Merry 1; 1369991554f2SKenneth D. Merry phy_change->is_processed = 1; 1370991554f2SKenneth D. Merry } else { 1371991554f2SKenneth D. Merry phy_change->is_processed = 1; 1372991554f2SKenneth D. Merry mpr_dprint(sc, MPR_INFO, "%s: " 1373991554f2SKenneth D. Merry "failed to add the device " 1374991554f2SKenneth D. Merry "with handle 0x%04x to " 1375991554f2SKenneth D. Merry "persistent table because " 1376991554f2SKenneth D. Merry "there is no free space " 1377991554f2SKenneth D. Merry "available\n", __func__, 1378991554f2SKenneth D. Merry phy_change->dev_handle); 1379991554f2SKenneth D. Merry } 1380991554f2SKenneth D. Merry } else { 1381991554f2SKenneth D. Merry et_entry->dpm_entry_num = dpm_idx; 1382991554f2SKenneth D. Merry mt_entry->dpm_entry_num = dpm_idx; 1383991554f2SKenneth D. Merry } 1384991554f2SKenneth D. Merry } 1385991554f2SKenneth D. Merry /* FIXME Why not mt_entry too? */ 1386991554f2SKenneth D. Merry et_entry->init_complete = 1; 1387991554f2SKenneth D. Merry } else if ((ioc_pg8_flags & 1388991554f2SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1389991554f2SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { 1390991554f2SKenneth D. Merry map_idx = _mapping_get_mt_idx_from_id 1391991554f2SKenneth D. Merry (sc, phy_change->physical_id); 1392991554f2SKenneth D. Merry if (map_idx == MPR_MAPTABLE_BAD_IDX) { 1393991554f2SKenneth D. Merry search_idx = sc->num_rsvd_entries; 1394991554f2SKenneth D. Merry if (topo_change->exp_handle) 1395991554f2SKenneth D. Merry search_idx += max_num_phy_ids; 1396991554f2SKenneth D. Merry map_idx = _mapping_get_free_mt_idx(sc, 1397991554f2SKenneth D. Merry search_idx); 1398991554f2SKenneth D. Merry } 1399991554f2SKenneth D. Merry if (map_idx == MPR_MAPTABLE_BAD_IDX) { 1400991554f2SKenneth D. Merry map_idx = _mapping_get_high_missing_mt_idx(sc); 1401991554f2SKenneth D. Merry if (map_idx != MPR_MAPTABLE_BAD_IDX) { 1402991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 1403991554f2SKenneth D. Merry if (mt_entry->dev_handle) { 1404991554f2SKenneth D. Merry _mapping_add_to_removal_table 1405991554f2SKenneth D. Merry (sc, mt_entry->dev_handle, 1406991554f2SKenneth D. Merry 0); 1407991554f2SKenneth D. Merry is_removed = 1; 1408991554f2SKenneth D. Merry } 1409991554f2SKenneth D. Merry mt_entry->init_complete = 0; 1410991554f2SKenneth D. Merry } 1411991554f2SKenneth D. Merry } 1412991554f2SKenneth D. Merry if (map_idx != MPR_MAPTABLE_BAD_IDX) { 1413991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 1414991554f2SKenneth D. Merry mt_entry->physical_id = phy_change->physical_id; 1415991554f2SKenneth D. Merry mt_entry->channel = 0; 1416991554f2SKenneth D. Merry mt_entry->id = map_idx; 1417991554f2SKenneth D. Merry mt_entry->dev_handle = phy_change->dev_handle; 1418991554f2SKenneth D. Merry mt_entry->missing_count = 0; 1419991554f2SKenneth D. Merry mt_entry->device_info = phy_change->device_info 1420991554f2SKenneth D. Merry | (MPR_DEV_RESERVED | MPR_MAP_IN_USE); 1421991554f2SKenneth D. Merry } else { 1422991554f2SKenneth D. Merry phy_change->is_processed = 1; 1423991554f2SKenneth D. Merry if (!sc->mt_full_retry) { 1424991554f2SKenneth D. Merry sc->mt_add_device_failed = 1; 1425991554f2SKenneth D. Merry continue; 1426991554f2SKenneth D. Merry } 1427*67feec50SStephen McConnell mpr_dprint(sc, MPR_INFO, "%s: failed to add " 1428*67feec50SStephen McConnell "the device with handle 0x%04x because " 1429*67feec50SStephen McConnell "there is no free space available in the " 1430*67feec50SStephen McConnell "mapping table\n", __func__, 1431*67feec50SStephen McConnell phy_change->dev_handle); 1432991554f2SKenneth D. Merry continue; 1433991554f2SKenneth D. Merry } 1434991554f2SKenneth D. Merry if (sc->is_dpm_enable) { 1435991554f2SKenneth D. Merry if (mt_entry->dpm_entry_num != 1436991554f2SKenneth D. Merry MPR_DPM_BAD_IDX) { 1437991554f2SKenneth D. Merry dpm_idx = mt_entry->dpm_entry_num; 1438991554f2SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *) 1439991554f2SKenneth D. Merry ((u8 *)sc->dpm_pg0 + hdr_sz); 1440991554f2SKenneth D. Merry dpm_entry += dpm_idx; 1441991554f2SKenneth D. Merry missing_cnt = dpm_entry-> 1442991554f2SKenneth D. Merry MappingInformation & 1443991554f2SKenneth D. Merry MPI2_DRVMAP0_MAPINFO_MISSING_MASK; 1444991554f2SKenneth D. Merry temp64_var = dpm_entry-> 1445991554f2SKenneth D. Merry PhysicalIdentifier.High; 1446991554f2SKenneth D. Merry temp64_var = (temp64_var << 32) | 1447991554f2SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low; 1448991554f2SKenneth D. Merry if ((mt_entry->physical_id == 1449991554f2SKenneth D. Merry temp64_var) && !missing_cnt) 1450991554f2SKenneth D. Merry mt_entry->init_complete = 1; 1451991554f2SKenneth D. Merry } else { 1452991554f2SKenneth D. Merry dpm_idx = _mapping_get_free_dpm_idx(sc); 1453991554f2SKenneth D. Merry mt_entry->init_complete = 0; 1454991554f2SKenneth D. Merry } 1455991554f2SKenneth D. Merry if (dpm_idx != MPR_DPM_BAD_IDX && 1456991554f2SKenneth D. Merry !mt_entry->init_complete) { 1457991554f2SKenneth D. Merry mt_entry->init_complete = 1; 1458991554f2SKenneth D. Merry mt_entry->dpm_entry_num = dpm_idx; 1459991554f2SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *) 1460991554f2SKenneth D. Merry ((u8 *)sc->dpm_pg0 + hdr_sz); 1461991554f2SKenneth D. Merry dpm_entry += dpm_idx; 1462991554f2SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low = 1463991554f2SKenneth D. Merry (0xFFFFFFFF & 1464991554f2SKenneth D. Merry mt_entry->physical_id); 1465991554f2SKenneth D. Merry dpm_entry->PhysicalIdentifier.High = 1466991554f2SKenneth D. Merry (mt_entry->physical_id >> 32); 1467991554f2SKenneth D. Merry dpm_entry->DeviceIndex = (U16) map_idx; 1468991554f2SKenneth D. Merry dpm_entry->MappingInformation = 0; 1469991554f2SKenneth D. Merry dpm_entry->PhysicalBitsMapping = 0; 1470991554f2SKenneth D. Merry sc->dpm_entry_used[dpm_idx] = 1; 1471991554f2SKenneth D. Merry sc->dpm_flush_entry[dpm_idx] = 1; 1472991554f2SKenneth D. Merry phy_change->is_processed = 1; 1473991554f2SKenneth D. Merry } else if (dpm_idx == MPR_DPM_BAD_IDX) { 1474991554f2SKenneth D. Merry phy_change->is_processed = 1; 1475*67feec50SStephen McConnell mpr_dprint(sc, MPR_INFO, "%s: failed " 1476*67feec50SStephen McConnell "to add the device with handle " 1477*67feec50SStephen McConnell "0x%04x to persistent table " 1478*67feec50SStephen McConnell "because there is no free space " 1479991554f2SKenneth D. Merry "available\n", __func__, 1480991554f2SKenneth D. Merry phy_change->dev_handle); 1481991554f2SKenneth D. Merry } 1482991554f2SKenneth D. Merry } 1483991554f2SKenneth D. Merry mt_entry->init_complete = 1; 1484991554f2SKenneth D. Merry } 1485991554f2SKenneth D. Merry 1486991554f2SKenneth D. Merry phy_change->is_processed = 1; 1487991554f2SKenneth D. Merry } 1488991554f2SKenneth D. Merry if (is_removed) 1489991554f2SKenneth D. Merry _mapping_clear_removed_entries(sc); 1490991554f2SKenneth D. Merry } 1491991554f2SKenneth D. Merry 1492991554f2SKenneth D. Merry /** 1493*67feec50SStephen McConnell * _mapping_add_new_pcie_device -Add the new PCIe device into mapping table 1494*67feec50SStephen McConnell * @sc: per adapter object 1495*67feec50SStephen McConnell * @topo_change: Topology change event entry 1496*67feec50SStephen McConnell * 1497*67feec50SStephen McConnell * Search through the PCIe topology change event list and update map table, 1498*67feec50SStephen McConnell * enclosure table and DPM pages for the newly added devices. 1499*67feec50SStephen McConnell * 1500*67feec50SStephen McConnell * Returns nothing 1501*67feec50SStephen McConnell */ 1502*67feec50SStephen McConnell static void 1503*67feec50SStephen McConnell _mapping_add_new_pcie_device(struct mpr_softc *sc, 1504*67feec50SStephen McConnell struct _map_pcie_topology_change *topo_change) 1505*67feec50SStephen McConnell { 1506*67feec50SStephen McConnell u8 enc_idx, missing_cnt, is_removed = 0; 1507*67feec50SStephen McConnell u16 dpm_idx; 1508*67feec50SStephen McConnell u32 search_idx, map_idx; 1509*67feec50SStephen McConnell u32 entry; 1510*67feec50SStephen McConnell struct dev_mapping_table *mt_entry; 1511*67feec50SStephen McConnell struct enc_mapping_table *et_entry; 1512*67feec50SStephen McConnell struct _map_port_change *port_change; 1513*67feec50SStephen McConnell u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1514*67feec50SStephen McConnell Mpi2DriverMap0Entry_t *dpm_entry; 1515*67feec50SStephen McConnell uint64_t temp64_var; 1516*67feec50SStephen McConnell u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT; 1517*67feec50SStephen McConnell u8 hdr_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER); 1518*67feec50SStephen McConnell u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs); 1519*67feec50SStephen McConnell 1520*67feec50SStephen McConnell for (entry = 0; entry < topo_change->num_entries; entry++) { 1521*67feec50SStephen McConnell port_change = &topo_change->port_details[entry]; 1522*67feec50SStephen McConnell if (port_change->is_processed) 1523*67feec50SStephen McConnell continue; 1524*67feec50SStephen McConnell if (port_change->reason != MPI26_EVENT_PCIE_TOPO_PS_DEV_ADDED || 1525*67feec50SStephen McConnell !port_change->dev_handle) { 1526*67feec50SStephen McConnell port_change->is_processed = 1; 1527*67feec50SStephen McConnell continue; 1528*67feec50SStephen McConnell } 1529*67feec50SStephen McConnell if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1530*67feec50SStephen McConnell MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 1531*67feec50SStephen McConnell enc_idx = _mapping_get_enc_idx_from_handle 1532*67feec50SStephen McConnell (sc, topo_change->enc_handle); 1533*67feec50SStephen McConnell if (enc_idx == MPR_ENCTABLE_BAD_IDX) { 1534*67feec50SStephen McConnell port_change->is_processed = 1; 1535*67feec50SStephen McConnell mpr_dprint(sc, MPR_ERROR, "%s: failed to add " 1536*67feec50SStephen McConnell "the device with handle 0x%04x because the " 1537*67feec50SStephen McConnell "enclosure is not in the mapping table\n", 1538*67feec50SStephen McConnell __func__, port_change->dev_handle); 1539*67feec50SStephen McConnell continue; 1540*67feec50SStephen McConnell } 1541*67feec50SStephen McConnell et_entry = &sc->enclosure_table[enc_idx]; 1542*67feec50SStephen McConnell if (et_entry->start_index == MPR_MAPTABLE_BAD_IDX) { 1543*67feec50SStephen McConnell port_change->is_processed = 1; 1544*67feec50SStephen McConnell if (!sc->mt_full_retry) { 1545*67feec50SStephen McConnell sc->mt_add_device_failed = 1; 1546*67feec50SStephen McConnell continue; 1547*67feec50SStephen McConnell } 1548*67feec50SStephen McConnell mpr_dprint(sc, MPR_INFO, "%s: failed to add " 1549*67feec50SStephen McConnell "the device with handle 0x%04x because " 1550*67feec50SStephen McConnell "there is no free space available in the " 1551*67feec50SStephen McConnell "mapping table\n", __func__, 1552*67feec50SStephen McConnell port_change->dev_handle); 1553*67feec50SStephen McConnell continue; 1554*67feec50SStephen McConnell } 1555*67feec50SStephen McConnell map_idx = et_entry->start_index + port_change->slot - 1556*67feec50SStephen McConnell et_entry->start_slot; 1557*67feec50SStephen McConnell mt_entry = &sc->mapping_table[map_idx]; 1558*67feec50SStephen McConnell mt_entry->physical_id = port_change->physical_id; 1559*67feec50SStephen McConnell mt_entry->channel = 0; 1560*67feec50SStephen McConnell mt_entry->id = map_idx; 1561*67feec50SStephen McConnell mt_entry->dev_handle = port_change->dev_handle; 1562*67feec50SStephen McConnell mt_entry->missing_count = 0; 1563*67feec50SStephen McConnell mt_entry->dpm_entry_num = et_entry->dpm_entry_num; 1564*67feec50SStephen McConnell mt_entry->device_info = port_change->device_info | 1565*67feec50SStephen McConnell (MPR_DEV_RESERVED | MPR_MAP_IN_USE); 1566*67feec50SStephen McConnell if (sc->is_dpm_enable) { 1567*67feec50SStephen McConnell dpm_idx = et_entry->dpm_entry_num; 1568*67feec50SStephen McConnell if (dpm_idx == MPR_DPM_BAD_IDX) 1569*67feec50SStephen McConnell dpm_idx = _mapping_get_dpm_idx_from_id 1570*67feec50SStephen McConnell (sc, et_entry->enclosure_id, 1571*67feec50SStephen McConnell et_entry->phy_bits); 1572*67feec50SStephen McConnell if (dpm_idx == MPR_DPM_BAD_IDX) { 1573*67feec50SStephen McConnell dpm_idx = _mapping_get_free_dpm_idx(sc); 1574*67feec50SStephen McConnell if (dpm_idx != MPR_DPM_BAD_IDX) { 1575*67feec50SStephen McConnell dpm_entry = 1576*67feec50SStephen McConnell (Mpi2DriverMap0Entry_t *) 1577*67feec50SStephen McConnell ((u8 *) sc->dpm_pg0 + 1578*67feec50SStephen McConnell hdr_sz); 1579*67feec50SStephen McConnell dpm_entry += dpm_idx; 1580*67feec50SStephen McConnell dpm_entry-> 1581*67feec50SStephen McConnell PhysicalIdentifier.Low = 1582*67feec50SStephen McConnell (0xFFFFFFFF & 1583*67feec50SStephen McConnell et_entry->enclosure_id); 1584*67feec50SStephen McConnell dpm_entry-> 1585*67feec50SStephen McConnell PhysicalIdentifier.High = 1586*67feec50SStephen McConnell ( et_entry->enclosure_id 1587*67feec50SStephen McConnell >> 32); 1588*67feec50SStephen McConnell dpm_entry->DeviceIndex = 1589*67feec50SStephen McConnell (U16)et_entry->start_index; 1590*67feec50SStephen McConnell dpm_entry->MappingInformation = 1591*67feec50SStephen McConnell et_entry->num_slots; 1592*67feec50SStephen McConnell dpm_entry->MappingInformation 1593*67feec50SStephen McConnell <<= map_shift; 1594*67feec50SStephen McConnell dpm_entry->PhysicalBitsMapping 1595*67feec50SStephen McConnell = et_entry->phy_bits; 1596*67feec50SStephen McConnell et_entry->dpm_entry_num = 1597*67feec50SStephen McConnell dpm_idx; 1598*67feec50SStephen McConnell /* FIXME Do I need to set the dpm_idxin mt_entry too */ 1599*67feec50SStephen McConnell sc->dpm_entry_used[dpm_idx] = 1; 1600*67feec50SStephen McConnell sc->dpm_flush_entry[dpm_idx] = 1601*67feec50SStephen McConnell 1; 1602*67feec50SStephen McConnell port_change->is_processed = 1; 1603*67feec50SStephen McConnell } else { 1604*67feec50SStephen McConnell port_change->is_processed = 1; 1605*67feec50SStephen McConnell mpr_dprint(sc, MPR_INFO, "%s: " 1606*67feec50SStephen McConnell "failed to add the device " 1607*67feec50SStephen McConnell "with handle 0x%04x to " 1608*67feec50SStephen McConnell "persistent table because " 1609*67feec50SStephen McConnell "there is no free space " 1610*67feec50SStephen McConnell "available\n", __func__, 1611*67feec50SStephen McConnell port_change->dev_handle); 1612*67feec50SStephen McConnell } 1613*67feec50SStephen McConnell } else { 1614*67feec50SStephen McConnell et_entry->dpm_entry_num = dpm_idx; 1615*67feec50SStephen McConnell mt_entry->dpm_entry_num = dpm_idx; 1616*67feec50SStephen McConnell } 1617*67feec50SStephen McConnell } 1618*67feec50SStephen McConnell /* FIXME Why not mt_entry too? */ 1619*67feec50SStephen McConnell et_entry->init_complete = 1; 1620*67feec50SStephen McConnell } else if ((ioc_pg8_flags & 1621*67feec50SStephen McConnell MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1622*67feec50SStephen McConnell MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { 1623*67feec50SStephen McConnell map_idx = _mapping_get_mt_idx_from_id 1624*67feec50SStephen McConnell (sc, port_change->physical_id); 1625*67feec50SStephen McConnell if (map_idx == MPR_MAPTABLE_BAD_IDX) { 1626*67feec50SStephen McConnell search_idx = sc->num_rsvd_entries; 1627*67feec50SStephen McConnell if (topo_change->switch_dev_handle) 1628*67feec50SStephen McConnell search_idx += max_num_phy_ids; 1629*67feec50SStephen McConnell map_idx = _mapping_get_free_mt_idx(sc, 1630*67feec50SStephen McConnell search_idx); 1631*67feec50SStephen McConnell } 1632*67feec50SStephen McConnell if (map_idx == MPR_MAPTABLE_BAD_IDX) { 1633*67feec50SStephen McConnell map_idx = _mapping_get_high_missing_mt_idx(sc); 1634*67feec50SStephen McConnell if (map_idx != MPR_MAPTABLE_BAD_IDX) { 1635*67feec50SStephen McConnell mt_entry = &sc->mapping_table[map_idx]; 1636*67feec50SStephen McConnell if (mt_entry->dev_handle) { 1637*67feec50SStephen McConnell _mapping_add_to_removal_table 1638*67feec50SStephen McConnell (sc, mt_entry->dev_handle, 1639*67feec50SStephen McConnell 0); 1640*67feec50SStephen McConnell is_removed = 1; 1641*67feec50SStephen McConnell } 1642*67feec50SStephen McConnell mt_entry->init_complete = 0; 1643*67feec50SStephen McConnell } 1644*67feec50SStephen McConnell } 1645*67feec50SStephen McConnell if (map_idx != MPR_MAPTABLE_BAD_IDX) { 1646*67feec50SStephen McConnell mt_entry = &sc->mapping_table[map_idx]; 1647*67feec50SStephen McConnell mt_entry->physical_id = 1648*67feec50SStephen McConnell port_change->physical_id; 1649*67feec50SStephen McConnell mt_entry->channel = 0; 1650*67feec50SStephen McConnell mt_entry->id = map_idx; 1651*67feec50SStephen McConnell mt_entry->dev_handle = port_change->dev_handle; 1652*67feec50SStephen McConnell mt_entry->missing_count = 0; 1653*67feec50SStephen McConnell mt_entry->device_info = 1654*67feec50SStephen McConnell port_change->device_info | 1655*67feec50SStephen McConnell (MPR_DEV_RESERVED | MPR_MAP_IN_USE); 1656*67feec50SStephen McConnell } else { 1657*67feec50SStephen McConnell port_change->is_processed = 1; 1658*67feec50SStephen McConnell if (!sc->mt_full_retry) { 1659*67feec50SStephen McConnell sc->mt_add_device_failed = 1; 1660*67feec50SStephen McConnell continue; 1661*67feec50SStephen McConnell } 1662*67feec50SStephen McConnell mpr_dprint(sc, MPR_INFO, "%s: failed to add " 1663*67feec50SStephen McConnell "the device with handle 0x%04x because " 1664*67feec50SStephen McConnell "there is no free space available in the " 1665*67feec50SStephen McConnell "mapping table\n", __func__, 1666*67feec50SStephen McConnell port_change->dev_handle); 1667*67feec50SStephen McConnell continue; 1668*67feec50SStephen McConnell } 1669*67feec50SStephen McConnell if (sc->is_dpm_enable) { 1670*67feec50SStephen McConnell if (mt_entry->dpm_entry_num != 1671*67feec50SStephen McConnell MPR_DPM_BAD_IDX) { 1672*67feec50SStephen McConnell dpm_idx = mt_entry->dpm_entry_num; 1673*67feec50SStephen McConnell dpm_entry = (Mpi2DriverMap0Entry_t *) 1674*67feec50SStephen McConnell ((u8 *)sc->dpm_pg0 + hdr_sz); 1675*67feec50SStephen McConnell dpm_entry += dpm_idx; 1676*67feec50SStephen McConnell missing_cnt = dpm_entry-> 1677*67feec50SStephen McConnell MappingInformation & 1678*67feec50SStephen McConnell MPI2_DRVMAP0_MAPINFO_MISSING_MASK; 1679*67feec50SStephen McConnell temp64_var = dpm_entry-> 1680*67feec50SStephen McConnell PhysicalIdentifier.High; 1681*67feec50SStephen McConnell temp64_var = (temp64_var << 32) | 1682*67feec50SStephen McConnell dpm_entry->PhysicalIdentifier.Low; 1683*67feec50SStephen McConnell if ((mt_entry->physical_id == 1684*67feec50SStephen McConnell temp64_var) && !missing_cnt) 1685*67feec50SStephen McConnell mt_entry->init_complete = 1; 1686*67feec50SStephen McConnell } else { 1687*67feec50SStephen McConnell dpm_idx = _mapping_get_free_dpm_idx(sc); 1688*67feec50SStephen McConnell mt_entry->init_complete = 0; 1689*67feec50SStephen McConnell } 1690*67feec50SStephen McConnell if (dpm_idx != MPR_DPM_BAD_IDX && 1691*67feec50SStephen McConnell !mt_entry->init_complete) { 1692*67feec50SStephen McConnell mt_entry->init_complete = 1; 1693*67feec50SStephen McConnell mt_entry->dpm_entry_num = dpm_idx; 1694*67feec50SStephen McConnell dpm_entry = (Mpi2DriverMap0Entry_t *) 1695*67feec50SStephen McConnell ((u8 *)sc->dpm_pg0 + hdr_sz); 1696*67feec50SStephen McConnell dpm_entry += dpm_idx; 1697*67feec50SStephen McConnell dpm_entry->PhysicalIdentifier.Low = 1698*67feec50SStephen McConnell (0xFFFFFFFF & 1699*67feec50SStephen McConnell mt_entry->physical_id); 1700*67feec50SStephen McConnell dpm_entry->PhysicalIdentifier.High = 1701*67feec50SStephen McConnell (mt_entry->physical_id >> 32); 1702*67feec50SStephen McConnell dpm_entry->DeviceIndex = (U16) map_idx; 1703*67feec50SStephen McConnell dpm_entry->MappingInformation = 0; 1704*67feec50SStephen McConnell dpm_entry->PhysicalBitsMapping = 0; 1705*67feec50SStephen McConnell sc->dpm_entry_used[dpm_idx] = 1; 1706*67feec50SStephen McConnell sc->dpm_flush_entry[dpm_idx] = 1; 1707*67feec50SStephen McConnell port_change->is_processed = 1; 1708*67feec50SStephen McConnell } else if (dpm_idx == MPR_DPM_BAD_IDX) { 1709*67feec50SStephen McConnell port_change->is_processed = 1; 1710*67feec50SStephen McConnell mpr_dprint(sc, MPR_INFO, "%s: failed " 1711*67feec50SStephen McConnell "to add the device with handle " 1712*67feec50SStephen McConnell "0x%04x to persistent table " 1713*67feec50SStephen McConnell "because there is no free space " 1714*67feec50SStephen McConnell "available\n", __func__, 1715*67feec50SStephen McConnell port_change->dev_handle); 1716*67feec50SStephen McConnell } 1717*67feec50SStephen McConnell } 1718*67feec50SStephen McConnell mt_entry->init_complete = 1; 1719*67feec50SStephen McConnell } 1720*67feec50SStephen McConnell 1721*67feec50SStephen McConnell port_change->is_processed = 1; 1722*67feec50SStephen McConnell } 1723*67feec50SStephen McConnell if (is_removed) 1724*67feec50SStephen McConnell _mapping_clear_removed_entries(sc); 1725*67feec50SStephen McConnell } 1726*67feec50SStephen McConnell 1727*67feec50SStephen McConnell /** 1728991554f2SKenneth D. Merry * _mapping_flush_dpm_pages -Flush the DPM pages to NVRAM 1729991554f2SKenneth D. Merry * @sc: per adapter object 1730991554f2SKenneth D. Merry * 1731991554f2SKenneth D. Merry * Returns nothing 1732991554f2SKenneth D. Merry */ 1733991554f2SKenneth D. Merry static void 1734991554f2SKenneth D. Merry _mapping_flush_dpm_pages(struct mpr_softc *sc) 1735991554f2SKenneth D. Merry { 1736991554f2SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry; 1737991554f2SKenneth D. Merry Mpi2ConfigReply_t mpi_reply; 1738991554f2SKenneth D. Merry Mpi2DriverMappingPage0_t config_page; 1739991554f2SKenneth D. Merry u16 entry_num; 1740991554f2SKenneth D. Merry 1741991554f2SKenneth D. Merry for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) { 1742991554f2SKenneth D. Merry if (!sc->dpm_flush_entry[entry_num]) 1743991554f2SKenneth D. Merry continue; 1744991554f2SKenneth D. Merry memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t)); 1745991554f2SKenneth D. Merry memcpy(&config_page.Header, (u8 *)sc->dpm_pg0, 1746991554f2SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 1747991554f2SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 + 1748991554f2SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 1749991554f2SKenneth D. Merry dpm_entry += entry_num; 1750991554f2SKenneth D. Merry dpm_entry->MappingInformation = htole16(dpm_entry-> 1751991554f2SKenneth D. Merry MappingInformation); 1752991554f2SKenneth D. Merry dpm_entry->DeviceIndex = htole16(dpm_entry->DeviceIndex); 1753991554f2SKenneth D. Merry dpm_entry->PhysicalBitsMapping = htole32(dpm_entry-> 1754991554f2SKenneth D. Merry PhysicalBitsMapping); 1755991554f2SKenneth D. Merry memcpy(&config_page.Entry, (u8 *)dpm_entry, 1756991554f2SKenneth D. Merry sizeof(Mpi2DriverMap0Entry_t)); 1757991554f2SKenneth D. Merry /* TODO-How to handle failed writes? */ 1758991554f2SKenneth D. Merry if (mpr_config_set_dpm_pg0(sc, &mpi_reply, &config_page, 1759991554f2SKenneth D. Merry entry_num)) { 1760991554f2SKenneth D. Merry printf("%s: write of dpm entry %d for device failed\n", 1761991554f2SKenneth D. Merry __func__, entry_num); 1762991554f2SKenneth D. Merry } else 1763991554f2SKenneth D. Merry sc->dpm_flush_entry[entry_num] = 0; 1764991554f2SKenneth D. Merry dpm_entry->MappingInformation = le16toh(dpm_entry-> 1765991554f2SKenneth D. Merry MappingInformation); 1766991554f2SKenneth D. Merry dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex); 1767991554f2SKenneth D. Merry dpm_entry->PhysicalBitsMapping = le32toh(dpm_entry-> 1768991554f2SKenneth D. Merry PhysicalBitsMapping); 1769991554f2SKenneth D. Merry } 1770991554f2SKenneth D. Merry } 1771991554f2SKenneth D. Merry 1772991554f2SKenneth D. Merry /** 1773991554f2SKenneth D. Merry * _mapping_allocate_memory- allocates the memory required for mapping tables 1774991554f2SKenneth D. Merry * @sc: per adapter object 1775991554f2SKenneth D. Merry * 1776991554f2SKenneth D. Merry * Allocates the memory for all the tables required for host mapping 1777991554f2SKenneth D. Merry * 1778991554f2SKenneth D. Merry * Return 0 on success or non-zero on failure. 1779991554f2SKenneth D. Merry */ 1780991554f2SKenneth D. Merry int 1781991554f2SKenneth D. Merry mpr_mapping_allocate_memory(struct mpr_softc *sc) 1782991554f2SKenneth D. Merry { 1783991554f2SKenneth D. Merry uint32_t dpm_pg0_sz; 1784991554f2SKenneth D. Merry 1785991554f2SKenneth D. Merry sc->mapping_table = malloc((sizeof(struct dev_mapping_table) * 1786991554f2SKenneth D. Merry sc->max_devices), M_MPR, M_ZERO|M_NOWAIT); 1787991554f2SKenneth D. Merry if (!sc->mapping_table) 1788991554f2SKenneth D. Merry goto free_resources; 1789991554f2SKenneth D. Merry 1790991554f2SKenneth D. Merry sc->removal_table = malloc((sizeof(struct map_removal_table) * 1791991554f2SKenneth D. Merry sc->max_devices), M_MPR, M_ZERO|M_NOWAIT); 1792991554f2SKenneth D. Merry if (!sc->removal_table) 1793991554f2SKenneth D. Merry goto free_resources; 1794991554f2SKenneth D. Merry 1795991554f2SKenneth D. Merry sc->enclosure_table = malloc((sizeof(struct enc_mapping_table) * 1796991554f2SKenneth D. Merry sc->max_enclosures), M_MPR, M_ZERO|M_NOWAIT); 1797991554f2SKenneth D. Merry if (!sc->enclosure_table) 1798991554f2SKenneth D. Merry goto free_resources; 1799991554f2SKenneth D. Merry 1800991554f2SKenneth D. Merry sc->dpm_entry_used = malloc((sizeof(u8) * sc->max_dpm_entries), 1801991554f2SKenneth D. Merry M_MPR, M_ZERO|M_NOWAIT); 1802991554f2SKenneth D. Merry if (!sc->dpm_entry_used) 1803991554f2SKenneth D. Merry goto free_resources; 1804991554f2SKenneth D. Merry 1805991554f2SKenneth D. Merry sc->dpm_flush_entry = malloc((sizeof(u8) * sc->max_dpm_entries), 1806991554f2SKenneth D. Merry M_MPR, M_ZERO|M_NOWAIT); 1807991554f2SKenneth D. Merry if (!sc->dpm_flush_entry) 1808991554f2SKenneth D. Merry goto free_resources; 1809991554f2SKenneth D. Merry 1810991554f2SKenneth D. Merry dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) + 1811991554f2SKenneth D. Merry (sc->max_dpm_entries * sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY)); 1812991554f2SKenneth D. Merry 1813991554f2SKenneth D. Merry sc->dpm_pg0 = malloc(dpm_pg0_sz, M_MPR, M_ZERO|M_NOWAIT); 1814991554f2SKenneth D. Merry if (!sc->dpm_pg0) { 1815991554f2SKenneth D. Merry printf("%s: memory alloc failed for dpm page; disabling dpm\n", 1816991554f2SKenneth D. Merry __func__); 1817991554f2SKenneth D. Merry sc->is_dpm_enable = 0; 1818991554f2SKenneth D. Merry } 1819991554f2SKenneth D. Merry 1820991554f2SKenneth D. Merry return 0; 1821991554f2SKenneth D. Merry 1822991554f2SKenneth D. Merry free_resources: 1823991554f2SKenneth D. Merry free(sc->mapping_table, M_MPR); 1824991554f2SKenneth D. Merry free(sc->removal_table, M_MPR); 1825991554f2SKenneth D. Merry free(sc->enclosure_table, M_MPR); 1826991554f2SKenneth D. Merry free(sc->dpm_entry_used, M_MPR); 1827991554f2SKenneth D. Merry free(sc->dpm_flush_entry, M_MPR); 1828991554f2SKenneth D. Merry free(sc->dpm_pg0, M_MPR); 1829991554f2SKenneth D. Merry printf("%s: device initialization failed due to failure in mapping " 1830991554f2SKenneth D. Merry "table memory allocation\n", __func__); 1831991554f2SKenneth D. Merry return -1; 1832991554f2SKenneth D. Merry } 1833991554f2SKenneth D. Merry 1834991554f2SKenneth D. Merry /** 1835991554f2SKenneth D. Merry * mpr_mapping_free_memory- frees the memory allocated for mapping tables 1836991554f2SKenneth D. Merry * @sc: per adapter object 1837991554f2SKenneth D. Merry * 1838991554f2SKenneth D. Merry * Returns nothing. 1839991554f2SKenneth D. Merry */ 1840991554f2SKenneth D. Merry void 1841991554f2SKenneth D. Merry mpr_mapping_free_memory(struct mpr_softc *sc) 1842991554f2SKenneth D. Merry { 1843991554f2SKenneth D. Merry free(sc->mapping_table, M_MPR); 1844991554f2SKenneth D. Merry free(sc->removal_table, M_MPR); 1845991554f2SKenneth D. Merry free(sc->enclosure_table, M_MPR); 1846991554f2SKenneth D. Merry free(sc->dpm_entry_used, M_MPR); 1847991554f2SKenneth D. Merry free(sc->dpm_flush_entry, M_MPR); 1848991554f2SKenneth D. Merry free(sc->dpm_pg0, M_MPR); 1849991554f2SKenneth D. Merry } 1850991554f2SKenneth D. Merry 1851991554f2SKenneth D. Merry 1852991554f2SKenneth D. Merry static void 1853991554f2SKenneth D. Merry _mapping_process_dpm_pg0(struct mpr_softc *sc) 1854991554f2SKenneth D. Merry { 1855991554f2SKenneth D. Merry u8 missing_cnt, enc_idx; 1856991554f2SKenneth D. Merry u16 slot_id, entry_num, num_slots; 1857991554f2SKenneth D. Merry u32 map_idx, dev_idx, start_idx, end_idx; 1858991554f2SKenneth D. Merry struct dev_mapping_table *mt_entry; 1859991554f2SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry; 1860991554f2SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1861991554f2SKenneth D. Merry u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs); 1862991554f2SKenneth D. Merry struct enc_mapping_table *et_entry; 1863991554f2SKenneth D. Merry u64 physical_id; 1864991554f2SKenneth D. Merry u32 phy_bits = 0; 1865991554f2SKenneth D. Merry 1866991554f2SKenneth D. Merry if (sc->ir_firmware) 1867991554f2SKenneth D. Merry _mapping_get_ir_maprange(sc, &start_idx, &end_idx); 1868991554f2SKenneth D. Merry 1869991554f2SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *) ((uint8_t *) sc->dpm_pg0 + 1870991554f2SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 1871991554f2SKenneth D. Merry for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++, 1872991554f2SKenneth D. Merry dpm_entry++) { 1873991554f2SKenneth D. Merry physical_id = dpm_entry->PhysicalIdentifier.High; 1874991554f2SKenneth D. Merry physical_id = (physical_id << 32) | 1875991554f2SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low; 1876991554f2SKenneth D. Merry if (!physical_id) { 1877991554f2SKenneth D. Merry sc->dpm_entry_used[entry_num] = 0; 1878991554f2SKenneth D. Merry continue; 1879991554f2SKenneth D. Merry } 1880991554f2SKenneth D. Merry sc->dpm_entry_used[entry_num] = 1; 1881991554f2SKenneth D. Merry dpm_entry->MappingInformation = le16toh(dpm_entry-> 1882991554f2SKenneth D. Merry MappingInformation); 1883991554f2SKenneth D. Merry missing_cnt = dpm_entry->MappingInformation & 1884991554f2SKenneth D. Merry MPI2_DRVMAP0_MAPINFO_MISSING_MASK; 1885991554f2SKenneth D. Merry dev_idx = le16toh(dpm_entry->DeviceIndex); 1886991554f2SKenneth D. Merry phy_bits = le32toh(dpm_entry->PhysicalBitsMapping); 1887991554f2SKenneth D. Merry if (sc->ir_firmware && (dev_idx >= start_idx) && 1888991554f2SKenneth D. Merry (dev_idx <= end_idx)) { 1889991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[dev_idx]; 1890991554f2SKenneth D. Merry mt_entry->physical_id = dpm_entry->PhysicalIdentifier.High; 1891991554f2SKenneth D. Merry mt_entry->physical_id = (mt_entry->physical_id << 32) | 1892991554f2SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low; 1893991554f2SKenneth D. Merry mt_entry->channel = MPR_RAID_CHANNEL; 1894991554f2SKenneth D. Merry mt_entry->id = dev_idx; 1895991554f2SKenneth D. Merry mt_entry->missing_count = missing_cnt; 1896991554f2SKenneth D. Merry mt_entry->dpm_entry_num = entry_num; 1897991554f2SKenneth D. Merry mt_entry->device_info = MPR_DEV_RESERVED; 1898991554f2SKenneth D. Merry continue; 1899991554f2SKenneth D. Merry } 1900991554f2SKenneth D. Merry if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1901991554f2SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 1902991554f2SKenneth D. Merry if (dev_idx < (sc->num_rsvd_entries + 1903991554f2SKenneth D. Merry max_num_phy_ids)) { 1904991554f2SKenneth D. Merry slot_id = 0; 1905991554f2SKenneth D. Merry if (ioc_pg8_flags & 1906991554f2SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1) 1907991554f2SKenneth D. Merry slot_id = 1; 1908991554f2SKenneth D. Merry num_slots = max_num_phy_ids; 1909991554f2SKenneth D. Merry } else { 1910991554f2SKenneth D. Merry slot_id = 0; 1911991554f2SKenneth D. Merry num_slots = dpm_entry->MappingInformation & 1912991554f2SKenneth D. Merry MPI2_DRVMAP0_MAPINFO_SLOT_MASK; 1913991554f2SKenneth D. Merry num_slots >>= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT; 1914991554f2SKenneth D. Merry } 1915991554f2SKenneth D. Merry enc_idx = sc->num_enc_table_entries; 1916991554f2SKenneth D. Merry if (enc_idx >= sc->max_enclosures) { 1917991554f2SKenneth D. Merry printf("%s: enclosure entries exceed max " 1918991554f2SKenneth D. Merry "enclosures of %d\n", __func__, 1919991554f2SKenneth D. Merry sc->max_enclosures); 1920991554f2SKenneth D. Merry break; 1921991554f2SKenneth D. Merry } 1922991554f2SKenneth D. Merry sc->num_enc_table_entries++; 1923991554f2SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx]; 1924991554f2SKenneth D. Merry physical_id = dpm_entry->PhysicalIdentifier.High; 1925991554f2SKenneth D. Merry et_entry->enclosure_id = (physical_id << 32) | 1926991554f2SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low; 1927991554f2SKenneth D. Merry et_entry->start_index = dev_idx; 1928991554f2SKenneth D. Merry et_entry->dpm_entry_num = entry_num; 1929991554f2SKenneth D. Merry et_entry->num_slots = num_slots; 1930991554f2SKenneth D. Merry et_entry->start_slot = slot_id; 1931991554f2SKenneth D. Merry et_entry->missing_count = missing_cnt; 1932991554f2SKenneth D. Merry et_entry->phy_bits = phy_bits; 1933991554f2SKenneth D. Merry 1934991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[dev_idx]; 1935991554f2SKenneth D. Merry for (map_idx = dev_idx; map_idx < (dev_idx + num_slots); 1936991554f2SKenneth D. Merry map_idx++, mt_entry++) { 1937991554f2SKenneth D. Merry if (mt_entry->dpm_entry_num != 1938991554f2SKenneth D. Merry MPR_DPM_BAD_IDX) { 1939991554f2SKenneth D. Merry printf("%s: conflict in mapping table " 1940991554f2SKenneth D. Merry "for enclosure %d\n", __func__, 1941991554f2SKenneth D. Merry enc_idx); 1942991554f2SKenneth D. Merry break; 1943991554f2SKenneth D. Merry } 1944991554f2SKenneth D. Merry physical_id = dpm_entry->PhysicalIdentifier.High; 1945991554f2SKenneth D. Merry mt_entry->physical_id = (physical_id << 32) | 1946991554f2SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low; 1947991554f2SKenneth D. Merry mt_entry->phy_bits = phy_bits; 1948991554f2SKenneth D. Merry mt_entry->channel = 0; 1949991554f2SKenneth D. Merry mt_entry->id = dev_idx; 1950991554f2SKenneth D. Merry mt_entry->dpm_entry_num = entry_num; 1951991554f2SKenneth D. Merry mt_entry->missing_count = missing_cnt; 1952991554f2SKenneth D. Merry mt_entry->device_info = MPR_DEV_RESERVED; 1953991554f2SKenneth D. Merry } 1954991554f2SKenneth D. Merry } else if ((ioc_pg8_flags & 1955991554f2SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1956991554f2SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { 1957991554f2SKenneth D. Merry map_idx = dev_idx; 1958991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 1959991554f2SKenneth D. Merry if (mt_entry->dpm_entry_num != MPR_DPM_BAD_IDX) { 1960991554f2SKenneth D. Merry printf("%s: conflict in mapping table for " 1961991554f2SKenneth D. Merry "device %d\n", __func__, map_idx); 1962991554f2SKenneth D. Merry break; 1963991554f2SKenneth D. Merry } 1964991554f2SKenneth D. Merry physical_id = dpm_entry->PhysicalIdentifier.High; 1965991554f2SKenneth D. Merry mt_entry->physical_id = (physical_id << 32) | 1966991554f2SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low; 1967991554f2SKenneth D. Merry mt_entry->phy_bits = phy_bits; 1968991554f2SKenneth D. Merry mt_entry->channel = 0; 1969991554f2SKenneth D. Merry mt_entry->id = dev_idx; 1970991554f2SKenneth D. Merry mt_entry->missing_count = missing_cnt; 1971991554f2SKenneth D. Merry mt_entry->dpm_entry_num = entry_num; 1972991554f2SKenneth D. Merry mt_entry->device_info = MPR_DEV_RESERVED; 1973991554f2SKenneth D. Merry } 1974991554f2SKenneth D. Merry } /*close the loop for DPM table */ 1975991554f2SKenneth D. Merry } 1976991554f2SKenneth D. Merry 1977991554f2SKenneth D. Merry /* 1978991554f2SKenneth D. Merry * mpr_mapping_check_devices - start of the day check for device availabilty 1979991554f2SKenneth D. Merry * @sc: per adapter object 1980991554f2SKenneth D. Merry * @sleep_flag: Flag indicating whether this function can sleep or not 1981991554f2SKenneth D. Merry * 1982991554f2SKenneth D. Merry * Returns nothing. 1983991554f2SKenneth D. Merry */ 1984991554f2SKenneth D. Merry void 1985991554f2SKenneth D. Merry mpr_mapping_check_devices(struct mpr_softc *sc, int sleep_flag) 1986991554f2SKenneth D. Merry { 1987991554f2SKenneth D. Merry u32 i; 1988991554f2SKenneth D. Merry /* u32 cntdn, i; 1989991554f2SKenneth D. Merry u32 timeout = 60;*/ 1990991554f2SKenneth D. Merry struct dev_mapping_table *mt_entry; 1991991554f2SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1992991554f2SKenneth D. Merry struct enc_mapping_table *et_entry; 1993991554f2SKenneth D. Merry u32 start_idx, end_idx; 1994991554f2SKenneth D. Merry 1995991554f2SKenneth D. Merry /* We need to ucomment this when this function is called 1996991554f2SKenneth D. Merry * from the port enable complete */ 1997991554f2SKenneth D. Merry #if 0 1998991554f2SKenneth D. Merry sc->track_mapping_events = 0; 1999991554f2SKenneth D. Merry cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; 2000991554f2SKenneth D. Merry do { 2001991554f2SKenneth D. Merry if (!sc->pending_map_events) 2002991554f2SKenneth D. Merry break; 2003991554f2SKenneth D. Merry if (sleep_flag == CAN_SLEEP) 2004991554f2SKenneth D. Merry pause("mpr_pause", (hz/1000));/* 1msec sleep */ 2005991554f2SKenneth D. Merry else 2006991554f2SKenneth D. Merry DELAY(500); /* 500 useconds delay */ 2007991554f2SKenneth D. Merry } while (--cntdn); 2008991554f2SKenneth D. Merry 2009991554f2SKenneth D. Merry 2010991554f2SKenneth D. Merry if (!cntdn) 2011991554f2SKenneth D. Merry printf("%s: there are %d" 2012991554f2SKenneth D. Merry " pending events after %d seconds of delay\n", 2013991554f2SKenneth D. Merry __func__, sc->pending_map_events, timeout); 2014991554f2SKenneth D. Merry #endif 2015991554f2SKenneth D. Merry sc->pending_map_events = 0; 2016991554f2SKenneth D. Merry 2017991554f2SKenneth D. Merry if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 2018991554f2SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 2019991554f2SKenneth D. Merry et_entry = sc->enclosure_table; 2020991554f2SKenneth D. Merry for (i = 0; i < sc->num_enc_table_entries; i++, et_entry++) { 2021991554f2SKenneth D. Merry if (!et_entry->init_complete) { 2022991554f2SKenneth D. Merry if (et_entry->missing_count < 2023991554f2SKenneth D. Merry MPR_MAX_MISSING_COUNT) { 2024991554f2SKenneth D. Merry et_entry->missing_count++; 2025991554f2SKenneth D. Merry if (et_entry->dpm_entry_num != 2026991554f2SKenneth D. Merry MPR_DPM_BAD_IDX) 2027991554f2SKenneth D. Merry _mapping_commit_enc_entry(sc, 2028991554f2SKenneth D. Merry et_entry); 2029991554f2SKenneth D. Merry } 2030991554f2SKenneth D. Merry et_entry->init_complete = 1; 2031991554f2SKenneth D. Merry } 2032991554f2SKenneth D. Merry } 2033991554f2SKenneth D. Merry if (!sc->ir_firmware) 2034991554f2SKenneth D. Merry return; 2035991554f2SKenneth D. Merry _mapping_get_ir_maprange(sc, &start_idx, &end_idx); 2036991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[start_idx]; 2037991554f2SKenneth D. Merry for (i = start_idx; i < (end_idx + 1); i++, mt_entry++) { 2038991554f2SKenneth D. Merry if (mt_entry->device_info & MPR_DEV_RESERVED 2039991554f2SKenneth D. Merry && !mt_entry->physical_id) 2040991554f2SKenneth D. Merry mt_entry->init_complete = 1; 2041991554f2SKenneth D. Merry else if (mt_entry->device_info & MPR_DEV_RESERVED) { 2042991554f2SKenneth D. Merry if (!mt_entry->init_complete) { 2043991554f2SKenneth D. Merry if (mt_entry->missing_count < 2044991554f2SKenneth D. Merry MPR_MAX_MISSING_COUNT) { 2045991554f2SKenneth D. Merry mt_entry->missing_count++; 2046991554f2SKenneth D. Merry if (mt_entry->dpm_entry_num != 2047991554f2SKenneth D. Merry MPR_DPM_BAD_IDX) 2048991554f2SKenneth D. Merry _mapping_commit_map_entry(sc, 2049991554f2SKenneth D. Merry mt_entry); 2050991554f2SKenneth D. Merry } 2051991554f2SKenneth D. Merry mt_entry->init_complete = 1; 2052991554f2SKenneth D. Merry } 2053991554f2SKenneth D. Merry } 2054991554f2SKenneth D. Merry } 2055991554f2SKenneth D. Merry } else if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 2056991554f2SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { 2057991554f2SKenneth D. Merry mt_entry = sc->mapping_table; 2058991554f2SKenneth D. Merry for (i = 0; i < sc->max_devices; i++, mt_entry++) { 2059991554f2SKenneth D. Merry if (mt_entry->device_info & MPR_DEV_RESERVED 2060991554f2SKenneth D. Merry && !mt_entry->physical_id) 2061991554f2SKenneth D. Merry mt_entry->init_complete = 1; 2062991554f2SKenneth D. Merry else if (mt_entry->device_info & MPR_DEV_RESERVED) { 2063991554f2SKenneth D. Merry if (!mt_entry->init_complete) { 2064991554f2SKenneth D. Merry if (mt_entry->missing_count < 2065991554f2SKenneth D. Merry MPR_MAX_MISSING_COUNT) { 2066991554f2SKenneth D. Merry mt_entry->missing_count++; 2067991554f2SKenneth D. Merry if (mt_entry->dpm_entry_num != 2068991554f2SKenneth D. Merry MPR_DPM_BAD_IDX) 2069991554f2SKenneth D. Merry _mapping_commit_map_entry(sc, 2070991554f2SKenneth D. Merry mt_entry); 2071991554f2SKenneth D. Merry } 2072991554f2SKenneth D. Merry mt_entry->init_complete = 1; 2073991554f2SKenneth D. Merry } 2074991554f2SKenneth D. Merry } 2075991554f2SKenneth D. Merry } 2076991554f2SKenneth D. Merry } 2077991554f2SKenneth D. Merry } 2078991554f2SKenneth D. Merry 2079991554f2SKenneth D. Merry 2080991554f2SKenneth D. Merry /** 2081991554f2SKenneth D. Merry * mpr_mapping_is_reinit_required - check whether event replay required 2082991554f2SKenneth D. Merry * @sc: per adapter object 2083991554f2SKenneth D. Merry * 2084991554f2SKenneth D. Merry * Checks the per ioc flags and decide whether reinit of events required 2085991554f2SKenneth D. Merry * 2086991554f2SKenneth D. Merry * Returns 1 for reinit of ioc 0 for not. 2087991554f2SKenneth D. Merry */ 2088991554f2SKenneth D. Merry int mpr_mapping_is_reinit_required(struct mpr_softc *sc) 2089991554f2SKenneth D. Merry { 2090991554f2SKenneth D. Merry if (!sc->mt_full_retry && sc->mt_add_device_failed) { 2091991554f2SKenneth D. Merry sc->mt_full_retry = 1; 2092991554f2SKenneth D. Merry sc->mt_add_device_failed = 0; 2093991554f2SKenneth D. Merry _mapping_flush_dpm_pages(sc); 2094991554f2SKenneth D. Merry return 1; 2095991554f2SKenneth D. Merry } 2096991554f2SKenneth D. Merry sc->mt_full_retry = 1; 2097991554f2SKenneth D. Merry return 0; 2098991554f2SKenneth D. Merry } 2099991554f2SKenneth D. Merry 2100991554f2SKenneth D. Merry /** 2101991554f2SKenneth D. Merry * mpr_mapping_initialize - initialize mapping tables 2102991554f2SKenneth D. Merry * @sc: per adapter object 2103991554f2SKenneth D. Merry * 2104991554f2SKenneth D. Merry * Read controller persitant mapping tables into internal data area. 2105991554f2SKenneth D. Merry * 2106991554f2SKenneth D. Merry * Return 0 for success or non-zero for failure. 2107991554f2SKenneth D. Merry */ 2108991554f2SKenneth D. Merry int 2109991554f2SKenneth D. Merry mpr_mapping_initialize(struct mpr_softc *sc) 2110991554f2SKenneth D. Merry { 2111991554f2SKenneth D. Merry uint16_t volume_mapping_flags, dpm_pg0_sz; 2112991554f2SKenneth D. Merry uint32_t i; 2113991554f2SKenneth D. Merry Mpi2ConfigReply_t mpi_reply; 2114991554f2SKenneth D. Merry int error; 2115991554f2SKenneth D. Merry uint8_t retry_count; 2116991554f2SKenneth D. Merry uint16_t ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 2117991554f2SKenneth D. Merry 2118991554f2SKenneth D. Merry /* The additional 1 accounts for the virtual enclosure 2119991554f2SKenneth D. Merry * created for the controller 2120991554f2SKenneth D. Merry */ 2121991554f2SKenneth D. Merry sc->max_enclosures = sc->facts->MaxEnclosures + 1; 2122991554f2SKenneth D. Merry sc->max_expanders = sc->facts->MaxSasExpanders; 2123991554f2SKenneth D. Merry sc->max_volumes = sc->facts->MaxVolumes; 2124991554f2SKenneth D. Merry sc->max_devices = sc->facts->MaxTargets + sc->max_volumes; 2125991554f2SKenneth D. Merry sc->pending_map_events = 0; 2126991554f2SKenneth D. Merry sc->num_enc_table_entries = 0; 2127991554f2SKenneth D. Merry sc->num_rsvd_entries = 0; 2128991554f2SKenneth D. Merry sc->num_channels = 1; 2129991554f2SKenneth D. Merry sc->max_dpm_entries = sc->ioc_pg8.MaxPersistentEntries; 2130991554f2SKenneth D. Merry sc->is_dpm_enable = (sc->max_dpm_entries) ? 1 : 0; 2131991554f2SKenneth D. Merry sc->track_mapping_events = 0; 2132991554f2SKenneth D. Merry 2133991554f2SKenneth D. Merry if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING) 2134991554f2SKenneth D. Merry sc->is_dpm_enable = 0; 2135991554f2SKenneth D. Merry 2136991554f2SKenneth D. Merry if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0) 2137991554f2SKenneth D. Merry sc->num_rsvd_entries = 1; 2138991554f2SKenneth D. Merry 2139991554f2SKenneth D. Merry volume_mapping_flags = sc->ioc_pg8.IRVolumeMappingFlags & 2140991554f2SKenneth D. Merry MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; 2141991554f2SKenneth D. Merry if (sc->ir_firmware && (volume_mapping_flags == 2142991554f2SKenneth D. Merry MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING)) 2143991554f2SKenneth D. Merry sc->num_rsvd_entries += sc->max_volumes; 2144991554f2SKenneth D. Merry 2145991554f2SKenneth D. Merry error = mpr_mapping_allocate_memory(sc); 2146991554f2SKenneth D. Merry if (error) 2147991554f2SKenneth D. Merry return (error); 2148991554f2SKenneth D. Merry 2149991554f2SKenneth D. Merry for (i = 0; i < sc->max_devices; i++) 2150991554f2SKenneth D. Merry _mapping_clear_map_entry(sc->mapping_table + i); 2151991554f2SKenneth D. Merry 2152991554f2SKenneth D. Merry for (i = 0; i < sc->max_enclosures; i++) 2153991554f2SKenneth D. Merry _mapping_clear_enc_entry(sc->enclosure_table + i); 2154991554f2SKenneth D. Merry 2155991554f2SKenneth D. Merry for (i = 0; i < sc->max_devices; i++) { 2156991554f2SKenneth D. Merry sc->removal_table[i].dev_handle = 0; 2157991554f2SKenneth D. Merry sc->removal_table[i].dpm_entry_num = MPR_DPM_BAD_IDX; 2158991554f2SKenneth D. Merry } 2159991554f2SKenneth D. Merry 2160991554f2SKenneth D. Merry memset(sc->dpm_entry_used, 0, sc->max_dpm_entries); 2161991554f2SKenneth D. Merry memset(sc->dpm_flush_entry, 0, sc->max_dpm_entries); 2162991554f2SKenneth D. Merry 2163991554f2SKenneth D. Merry if (sc->is_dpm_enable) { 2164991554f2SKenneth D. Merry dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) + 2165991554f2SKenneth D. Merry (sc->max_dpm_entries * 2166991554f2SKenneth D. Merry sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY)); 2167991554f2SKenneth D. Merry retry_count = 0; 2168991554f2SKenneth D. Merry 2169991554f2SKenneth D. Merry retry_read_dpm: 2170991554f2SKenneth D. Merry if (mpr_config_get_dpm_pg0(sc, &mpi_reply, sc->dpm_pg0, 2171991554f2SKenneth D. Merry dpm_pg0_sz)) { 2172991554f2SKenneth D. Merry printf("%s: dpm page read failed; disabling dpm\n", 2173991554f2SKenneth D. Merry __func__); 2174991554f2SKenneth D. Merry if (retry_count < 3) { 2175991554f2SKenneth D. Merry retry_count++; 2176991554f2SKenneth D. Merry goto retry_read_dpm; 2177991554f2SKenneth D. Merry } 2178991554f2SKenneth D. Merry sc->is_dpm_enable = 0; 2179991554f2SKenneth D. Merry } 2180991554f2SKenneth D. Merry } 2181991554f2SKenneth D. Merry 2182991554f2SKenneth D. Merry if (sc->is_dpm_enable) 2183991554f2SKenneth D. Merry _mapping_process_dpm_pg0(sc); 2184991554f2SKenneth D. Merry 2185991554f2SKenneth D. Merry sc->track_mapping_events = 1; 2186991554f2SKenneth D. Merry return 0; 2187991554f2SKenneth D. Merry } 2188991554f2SKenneth D. Merry 2189991554f2SKenneth D. Merry /** 2190991554f2SKenneth D. Merry * mpr_mapping_exit - clear mapping table and associated memory 2191991554f2SKenneth D. Merry * @sc: per adapter object 2192991554f2SKenneth D. Merry * 2193991554f2SKenneth D. Merry * Returns nothing. 2194991554f2SKenneth D. Merry */ 2195991554f2SKenneth D. Merry void 2196991554f2SKenneth D. Merry mpr_mapping_exit(struct mpr_softc *sc) 2197991554f2SKenneth D. Merry { 2198991554f2SKenneth D. Merry _mapping_flush_dpm_pages(sc); 2199991554f2SKenneth D. Merry mpr_mapping_free_memory(sc); 2200991554f2SKenneth D. Merry } 2201991554f2SKenneth D. Merry 2202991554f2SKenneth D. Merry /** 2203991554f2SKenneth D. Merry * mpr_mapping_get_sas_id - assign a target id for sas device 2204991554f2SKenneth D. Merry * @sc: per adapter object 2205991554f2SKenneth D. Merry * @sas_address: sas address of the device 2206991554f2SKenneth D. Merry * @handle: device handle 2207991554f2SKenneth D. Merry * 2208991554f2SKenneth D. Merry * Returns valid ID on success or BAD_ID. 2209991554f2SKenneth D. Merry */ 2210991554f2SKenneth D. Merry unsigned int 2211991554f2SKenneth D. Merry mpr_mapping_get_sas_id(struct mpr_softc *sc, uint64_t sas_address, u16 handle) 2212991554f2SKenneth D. Merry { 2213991554f2SKenneth D. Merry u32 map_idx; 2214991554f2SKenneth D. Merry struct dev_mapping_table *mt_entry; 2215991554f2SKenneth D. Merry 2216991554f2SKenneth D. Merry for (map_idx = 0; map_idx < sc->max_devices; map_idx++) { 2217991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 2218991554f2SKenneth D. Merry if (mt_entry->dev_handle == handle && mt_entry->physical_id == 2219991554f2SKenneth D. Merry sas_address) 2220991554f2SKenneth D. Merry return mt_entry->id; 2221991554f2SKenneth D. Merry } 2222991554f2SKenneth D. Merry 2223991554f2SKenneth D. Merry return MPR_MAP_BAD_ID; 2224991554f2SKenneth D. Merry } 2225991554f2SKenneth D. Merry 2226991554f2SKenneth D. Merry /** 2227991554f2SKenneth D. Merry * mpr_mapping_get_sas_id_from_handle - find a target id in mapping table using 2228991554f2SKenneth D. Merry * only the dev handle. This is just a wrapper function for the local function 2229991554f2SKenneth D. Merry * _mapping_get_mt_idx_from_handle. 2230991554f2SKenneth D. Merry * @sc: per adapter object 2231991554f2SKenneth D. Merry * @handle: device handle 2232991554f2SKenneth D. Merry * 2233991554f2SKenneth D. Merry * Returns valid ID on success or BAD_ID. 2234991554f2SKenneth D. Merry */ 2235991554f2SKenneth D. Merry unsigned int 2236991554f2SKenneth D. Merry mpr_mapping_get_sas_id_from_handle(struct mpr_softc *sc, u16 handle) 2237991554f2SKenneth D. Merry { 2238991554f2SKenneth D. Merry return (_mapping_get_mt_idx_from_handle(sc, handle)); 2239991554f2SKenneth D. Merry } 2240991554f2SKenneth D. Merry 2241991554f2SKenneth D. Merry /** 2242991554f2SKenneth D. Merry * mpr_mapping_get_raid_id - assign a target id for raid device 2243991554f2SKenneth D. Merry * @sc: per adapter object 2244991554f2SKenneth D. Merry * @wwid: world wide identifier for raid volume 2245991554f2SKenneth D. Merry * @handle: device handle 2246991554f2SKenneth D. Merry * 2247991554f2SKenneth D. Merry * Returns valid ID on success or BAD_ID. 2248991554f2SKenneth D. Merry */ 2249991554f2SKenneth D. Merry unsigned int 2250991554f2SKenneth D. Merry mpr_mapping_get_raid_id(struct mpr_softc *sc, u64 wwid, u16 handle) 2251991554f2SKenneth D. Merry { 2252991554f2SKenneth D. Merry u32 map_idx; 2253991554f2SKenneth D. Merry struct dev_mapping_table *mt_entry; 2254991554f2SKenneth D. Merry 2255991554f2SKenneth D. Merry for (map_idx = 0; map_idx < sc->max_devices; map_idx++) { 2256991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 2257991554f2SKenneth D. Merry if (mt_entry->dev_handle == handle && mt_entry->physical_id == 2258991554f2SKenneth D. Merry wwid) 2259991554f2SKenneth D. Merry return mt_entry->id; 2260991554f2SKenneth D. Merry } 2261991554f2SKenneth D. Merry 2262991554f2SKenneth D. Merry return MPR_MAP_BAD_ID; 2263991554f2SKenneth D. Merry } 2264991554f2SKenneth D. Merry 2265991554f2SKenneth D. Merry /** 2266991554f2SKenneth D. Merry * mpr_mapping_get_raid_id_from_handle - find raid device in mapping table 2267991554f2SKenneth D. Merry * using only the volume dev handle. This is just a wrapper function for the 2268991554f2SKenneth D. Merry * local function _mapping_get_ir_mt_idx_from_handle. 2269991554f2SKenneth D. Merry * @sc: per adapter object 2270991554f2SKenneth D. Merry * @volHandle: volume device handle 2271991554f2SKenneth D. Merry * 2272991554f2SKenneth D. Merry * Returns valid ID on success or BAD_ID. 2273991554f2SKenneth D. Merry */ 2274991554f2SKenneth D. Merry unsigned int 2275991554f2SKenneth D. Merry mpr_mapping_get_raid_id_from_handle(struct mpr_softc *sc, u16 volHandle) 2276991554f2SKenneth D. Merry { 2277991554f2SKenneth D. Merry return (_mapping_get_ir_mt_idx_from_handle(sc, volHandle)); 2278991554f2SKenneth D. Merry } 2279991554f2SKenneth D. Merry 2280991554f2SKenneth D. Merry /** 2281991554f2SKenneth D. Merry * mpr_mapping_enclosure_dev_status_change_event - handle enclosure events 2282991554f2SKenneth D. Merry * @sc: per adapter object 2283991554f2SKenneth D. Merry * @event_data: event data payload 2284991554f2SKenneth D. Merry * 2285991554f2SKenneth D. Merry * Return nothing. 2286991554f2SKenneth D. Merry */ 2287991554f2SKenneth D. Merry void 2288991554f2SKenneth D. Merry mpr_mapping_enclosure_dev_status_change_event(struct mpr_softc *sc, 2289991554f2SKenneth D. Merry Mpi2EventDataSasEnclDevStatusChange_t *event_data) 2290991554f2SKenneth D. Merry { 2291991554f2SKenneth D. Merry u8 enc_idx, missing_count; 2292991554f2SKenneth D. Merry struct enc_mapping_table *et_entry; 2293991554f2SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry; 2294991554f2SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 2295991554f2SKenneth D. Merry u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT; 2296991554f2SKenneth D. Merry u8 update_phy_bits = 0; 2297991554f2SKenneth D. Merry u32 saved_phy_bits; 2298991554f2SKenneth D. Merry uint64_t temp64_var; 2299991554f2SKenneth D. Merry 2300991554f2SKenneth D. Merry if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) != 2301991554f2SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) 2302991554f2SKenneth D. Merry goto out; 2303991554f2SKenneth D. Merry 2304991554f2SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 + 2305991554f2SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 2306991554f2SKenneth D. Merry 2307991554f2SKenneth D. Merry if (event_data->ReasonCode == MPI2_EVENT_SAS_ENCL_RC_ADDED) { 2308991554f2SKenneth D. Merry if (!event_data->NumSlots) { 2309991554f2SKenneth D. Merry printf("%s: enclosure with handle = 0x%x reported 0 " 2310991554f2SKenneth D. Merry "slots\n", __func__, 2311991554f2SKenneth D. Merry le16toh(event_data->EnclosureHandle)); 2312991554f2SKenneth D. Merry goto out; 2313991554f2SKenneth D. Merry } 2314991554f2SKenneth D. Merry temp64_var = event_data->EnclosureLogicalID.High; 2315991554f2SKenneth D. Merry temp64_var = (temp64_var << 32) | 2316991554f2SKenneth D. Merry event_data->EnclosureLogicalID.Low; 2317991554f2SKenneth D. Merry enc_idx = _mapping_get_enc_idx_from_id(sc, temp64_var, 2318991554f2SKenneth D. Merry event_data->PhyBits); 2319991554f2SKenneth D. Merry if (enc_idx != MPR_ENCTABLE_BAD_IDX) { 2320991554f2SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx]; 2321991554f2SKenneth D. Merry if (et_entry->init_complete && 2322991554f2SKenneth D. Merry !et_entry->missing_count) { 2323991554f2SKenneth D. Merry printf("%s: enclosure %d is already present " 2324991554f2SKenneth D. Merry "with handle = 0x%x\n",__func__, enc_idx, 2325991554f2SKenneth D. Merry et_entry->enc_handle); 2326991554f2SKenneth D. Merry goto out; 2327991554f2SKenneth D. Merry } 2328991554f2SKenneth D. Merry et_entry->enc_handle = le16toh(event_data-> 2329991554f2SKenneth D. Merry EnclosureHandle); 2330991554f2SKenneth D. Merry et_entry->start_slot = le16toh(event_data->StartSlot); 2331991554f2SKenneth D. Merry saved_phy_bits = et_entry->phy_bits; 2332991554f2SKenneth D. Merry et_entry->phy_bits |= le32toh(event_data->PhyBits); 2333991554f2SKenneth D. Merry if (saved_phy_bits != et_entry->phy_bits) 2334991554f2SKenneth D. Merry update_phy_bits = 1; 2335991554f2SKenneth D. Merry if (et_entry->missing_count || update_phy_bits) { 2336991554f2SKenneth D. Merry et_entry->missing_count = 0; 2337991554f2SKenneth D. Merry if (sc->is_dpm_enable && 2338991554f2SKenneth D. Merry et_entry->dpm_entry_num != 2339991554f2SKenneth D. Merry MPR_DPM_BAD_IDX) { 2340991554f2SKenneth D. Merry dpm_entry += et_entry->dpm_entry_num; 2341991554f2SKenneth D. Merry missing_count = 2342991554f2SKenneth D. Merry (u8)(dpm_entry->MappingInformation & 2343991554f2SKenneth D. Merry MPI2_DRVMAP0_MAPINFO_MISSING_MASK); 2344991554f2SKenneth D. Merry if (!et_entry->init_complete && ( 2345991554f2SKenneth D. Merry missing_count || update_phy_bits)) { 2346991554f2SKenneth D. Merry dpm_entry->MappingInformation 2347991554f2SKenneth D. Merry = et_entry->num_slots; 2348991554f2SKenneth D. Merry dpm_entry->MappingInformation 2349991554f2SKenneth D. Merry <<= map_shift; 2350991554f2SKenneth D. Merry dpm_entry->PhysicalBitsMapping 2351991554f2SKenneth D. Merry = et_entry->phy_bits; 2352991554f2SKenneth D. Merry sc->dpm_flush_entry[et_entry-> 2353991554f2SKenneth D. Merry dpm_entry_num] = 1; 2354991554f2SKenneth D. Merry } 2355991554f2SKenneth D. Merry } 2356991554f2SKenneth D. Merry } 2357991554f2SKenneth D. Merry } else { 2358991554f2SKenneth D. Merry enc_idx = sc->num_enc_table_entries; 2359991554f2SKenneth D. Merry if (enc_idx >= sc->max_enclosures) { 2360991554f2SKenneth D. Merry printf("%s: enclosure can not be added; " 2361991554f2SKenneth D. Merry "mapping table is full\n", __func__); 2362991554f2SKenneth D. Merry goto out; 2363991554f2SKenneth D. Merry } 2364991554f2SKenneth D. Merry sc->num_enc_table_entries++; 2365991554f2SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx]; 2366991554f2SKenneth D. Merry et_entry->enc_handle = le16toh(event_data-> 2367991554f2SKenneth D. Merry EnclosureHandle); 2368991554f2SKenneth D. Merry et_entry->enclosure_id = event_data-> 2369991554f2SKenneth D. Merry EnclosureLogicalID.High; 2370991554f2SKenneth D. Merry et_entry->enclosure_id = ( et_entry->enclosure_id << 2371991554f2SKenneth D. Merry 32) | event_data->EnclosureLogicalID.Low; 2372991554f2SKenneth D. Merry et_entry->start_index = MPR_MAPTABLE_BAD_IDX; 2373991554f2SKenneth D. Merry et_entry->dpm_entry_num = MPR_DPM_BAD_IDX; 2374991554f2SKenneth D. Merry et_entry->num_slots = le16toh(event_data->NumSlots); 2375991554f2SKenneth D. Merry et_entry->start_slot = le16toh(event_data->StartSlot); 2376991554f2SKenneth D. Merry et_entry->phy_bits = le32toh(event_data->PhyBits); 2377991554f2SKenneth D. Merry } 2378991554f2SKenneth D. Merry et_entry->init_complete = 1; 2379991554f2SKenneth D. Merry } else if (event_data->ReasonCode == 2380991554f2SKenneth D. Merry MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING) { 2381991554f2SKenneth D. Merry enc_idx = _mapping_get_enc_idx_from_handle(sc, 2382991554f2SKenneth D. Merry le16toh(event_data->EnclosureHandle)); 2383991554f2SKenneth D. Merry if (enc_idx == MPR_ENCTABLE_BAD_IDX) { 2384991554f2SKenneth D. Merry printf("%s: cannot unmap enclosure %d because it has " 2385991554f2SKenneth D. Merry "already been deleted", __func__, enc_idx); 2386991554f2SKenneth D. Merry goto out; 2387991554f2SKenneth D. Merry } 2388991554f2SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx]; 2389991554f2SKenneth D. Merry if (!et_entry->init_complete) { 2390991554f2SKenneth D. Merry if (et_entry->missing_count < MPR_MAX_MISSING_COUNT) 2391991554f2SKenneth D. Merry et_entry->missing_count++; 2392991554f2SKenneth D. Merry else 2393991554f2SKenneth D. Merry et_entry->init_complete = 1; 2394991554f2SKenneth D. Merry } 2395991554f2SKenneth D. Merry if (!et_entry->missing_count) 2396991554f2SKenneth D. Merry et_entry->missing_count++; 2397991554f2SKenneth D. Merry if (sc->is_dpm_enable && !et_entry->init_complete && 2398991554f2SKenneth D. Merry et_entry->dpm_entry_num != MPR_DPM_BAD_IDX) { 2399991554f2SKenneth D. Merry dpm_entry += et_entry->dpm_entry_num; 2400991554f2SKenneth D. Merry dpm_entry->MappingInformation = et_entry->num_slots; 2401991554f2SKenneth D. Merry dpm_entry->MappingInformation <<= map_shift; 2402991554f2SKenneth D. Merry dpm_entry->MappingInformation |= 2403991554f2SKenneth D. Merry et_entry->missing_count; 2404991554f2SKenneth D. Merry sc->dpm_flush_entry[et_entry->dpm_entry_num] = 1; 2405991554f2SKenneth D. Merry } 2406991554f2SKenneth D. Merry et_entry->init_complete = 1; 2407991554f2SKenneth D. Merry } 2408991554f2SKenneth D. Merry 2409991554f2SKenneth D. Merry out: 2410991554f2SKenneth D. Merry _mapping_flush_dpm_pages(sc); 2411991554f2SKenneth D. Merry if (sc->pending_map_events) 2412991554f2SKenneth D. Merry sc->pending_map_events--; 2413991554f2SKenneth D. Merry } 2414991554f2SKenneth D. Merry 2415991554f2SKenneth D. Merry /** 2416991554f2SKenneth D. Merry * mpr_mapping_topology_change_event - handle topology change events 2417991554f2SKenneth D. Merry * @sc: per adapter object 2418991554f2SKenneth D. Merry * @event_data: event data payload 2419991554f2SKenneth D. Merry * 2420991554f2SKenneth D. Merry * Returns nothing. 2421991554f2SKenneth D. Merry */ 2422991554f2SKenneth D. Merry void 2423991554f2SKenneth D. Merry mpr_mapping_topology_change_event(struct mpr_softc *sc, 2424991554f2SKenneth D. Merry Mpi2EventDataSasTopologyChangeList_t *event_data) 2425991554f2SKenneth D. Merry { 2426991554f2SKenneth D. Merry struct _map_topology_change topo_change; 2427991554f2SKenneth D. Merry struct _map_phy_change *phy_change; 2428991554f2SKenneth D. Merry Mpi2EventSasTopoPhyEntry_t *event_phy_change; 2429991554f2SKenneth D. Merry u8 i, num_entries; 2430991554f2SKenneth D. Merry 2431991554f2SKenneth D. Merry topo_change.enc_handle = le16toh(event_data->EnclosureHandle); 2432991554f2SKenneth D. Merry topo_change.exp_handle = le16toh(event_data->ExpanderDevHandle); 2433991554f2SKenneth D. Merry num_entries = event_data->NumEntries; 2434991554f2SKenneth D. Merry topo_change.num_entries = num_entries; 2435991554f2SKenneth D. Merry topo_change.start_phy_num = event_data->StartPhyNum; 2436991554f2SKenneth D. Merry topo_change.num_phys = event_data->NumPhys; 2437991554f2SKenneth D. Merry topo_change.exp_status = event_data->ExpStatus; 2438991554f2SKenneth D. Merry event_phy_change = event_data->PHY; 2439991554f2SKenneth D. Merry topo_change.phy_details = NULL; 2440991554f2SKenneth D. Merry 2441991554f2SKenneth D. Merry if (!num_entries) 2442991554f2SKenneth D. Merry goto out; 2443991554f2SKenneth D. Merry phy_change = malloc(sizeof(struct _map_phy_change) * num_entries, 2444991554f2SKenneth D. Merry M_MPR, M_NOWAIT|M_ZERO); 2445991554f2SKenneth D. Merry topo_change.phy_details = phy_change; 2446991554f2SKenneth D. Merry if (!phy_change) 2447991554f2SKenneth D. Merry goto out; 2448991554f2SKenneth D. Merry for (i = 0; i < num_entries; i++, event_phy_change++, phy_change++) { 2449991554f2SKenneth D. Merry phy_change->dev_handle = le16toh(event_phy_change-> 2450991554f2SKenneth D. Merry AttachedDevHandle); 2451991554f2SKenneth D. Merry phy_change->reason = event_phy_change->PhyStatus & 2452991554f2SKenneth D. Merry MPI2_EVENT_SAS_TOPO_RC_MASK; 2453991554f2SKenneth D. Merry } 2454991554f2SKenneth D. Merry _mapping_update_missing_count(sc, &topo_change); 2455991554f2SKenneth D. Merry _mapping_get_dev_info(sc, &topo_change); 2456991554f2SKenneth D. Merry _mapping_clear_removed_entries(sc); 2457991554f2SKenneth D. Merry _mapping_add_new_device(sc, &topo_change); 2458991554f2SKenneth D. Merry 2459991554f2SKenneth D. Merry out: 2460991554f2SKenneth D. Merry free(topo_change.phy_details, M_MPR); 2461991554f2SKenneth D. Merry _mapping_flush_dpm_pages(sc); 2462991554f2SKenneth D. Merry if (sc->pending_map_events) 2463991554f2SKenneth D. Merry sc->pending_map_events--; 2464991554f2SKenneth D. Merry } 2465991554f2SKenneth D. Merry 2466991554f2SKenneth D. Merry /** 2467*67feec50SStephen McConnell * mpr_mapping_pcie_topology_change_event - handle PCIe topology change events 2468*67feec50SStephen McConnell * @sc: per adapter object 2469*67feec50SStephen McConnell * @event_data: event data payload 2470*67feec50SStephen McConnell * 2471*67feec50SStephen McConnell * Returns nothing. 2472*67feec50SStephen McConnell */ 2473*67feec50SStephen McConnell void 2474*67feec50SStephen McConnell mpr_mapping_pcie_topology_change_event(struct mpr_softc *sc, 2475*67feec50SStephen McConnell Mpi26EventDataPCIeTopologyChangeList_t *event_data) 2476*67feec50SStephen McConnell { 2477*67feec50SStephen McConnell struct _map_pcie_topology_change topo_change; 2478*67feec50SStephen McConnell struct _map_port_change *port_change; 2479*67feec50SStephen McConnell Mpi26EventPCIeTopoPortEntry_t *event_port_change; 2480*67feec50SStephen McConnell u8 i, num_entries; 2481*67feec50SStephen McConnell 2482*67feec50SStephen McConnell topo_change.switch_dev_handle = le16toh(event_data->SwitchDevHandle); 2483*67feec50SStephen McConnell topo_change.enc_handle = le16toh(event_data->EnclosureHandle); 2484*67feec50SStephen McConnell num_entries = event_data->NumEntries; 2485*67feec50SStephen McConnell topo_change.num_entries = num_entries; 2486*67feec50SStephen McConnell topo_change.start_port_num = event_data->StartPortNum; 2487*67feec50SStephen McConnell topo_change.num_ports = event_data->NumPorts; 2488*67feec50SStephen McConnell topo_change.switch_status = event_data->SwitchStatus; 2489*67feec50SStephen McConnell event_port_change = event_data->PortEntry; 2490*67feec50SStephen McConnell topo_change.port_details = NULL; 2491*67feec50SStephen McConnell 2492*67feec50SStephen McConnell if (!num_entries) 2493*67feec50SStephen McConnell goto out; 2494*67feec50SStephen McConnell port_change = malloc(sizeof(struct _map_port_change) * num_entries, 2495*67feec50SStephen McConnell M_MPR, M_NOWAIT|M_ZERO); 2496*67feec50SStephen McConnell topo_change.port_details = port_change; 2497*67feec50SStephen McConnell if (!port_change) 2498*67feec50SStephen McConnell goto out; 2499*67feec50SStephen McConnell for (i = 0; i < num_entries; i++, event_port_change++, port_change++) { 2500*67feec50SStephen McConnell port_change->dev_handle = le16toh(event_port_change-> 2501*67feec50SStephen McConnell AttachedDevHandle); 2502*67feec50SStephen McConnell port_change->reason = event_port_change->PortStatus; 2503*67feec50SStephen McConnell } 2504*67feec50SStephen McConnell _mapping_update_pcie_missing_count(sc, &topo_change); 2505*67feec50SStephen McConnell _mapping_get_pcie_dev_info(sc, &topo_change); 2506*67feec50SStephen McConnell _mapping_clear_removed_entries(sc); 2507*67feec50SStephen McConnell _mapping_add_new_pcie_device(sc, &topo_change); 2508*67feec50SStephen McConnell 2509*67feec50SStephen McConnell out: 2510*67feec50SStephen McConnell free(topo_change.port_details, M_MPR); 2511*67feec50SStephen McConnell _mapping_flush_dpm_pages(sc); 2512*67feec50SStephen McConnell if (sc->pending_map_events) 2513*67feec50SStephen McConnell sc->pending_map_events--; 2514*67feec50SStephen McConnell } 2515*67feec50SStephen McConnell 2516*67feec50SStephen McConnell /** 2517991554f2SKenneth D. Merry * _mapping_check_update_ir_mt_idx - Check and update IR map table index 2518991554f2SKenneth D. Merry * @sc: per adapter object 2519991554f2SKenneth D. Merry * @event_data: event data payload 2520991554f2SKenneth D. Merry * @evt_idx: current event index 2521991554f2SKenneth D. Merry * @map_idx: current index and the place holder for new map table index 2522991554f2SKenneth D. Merry * @wwid_table: world wide name for volumes in the element table 2523991554f2SKenneth D. Merry * 2524991554f2SKenneth D. Merry * pass through IR events and find whether any events matches and if so 2525991554f2SKenneth D. Merry * tries to find new index if not returns failure 2526991554f2SKenneth D. Merry * 2527991554f2SKenneth D. Merry * Returns 0 on success and 1 on failure 2528991554f2SKenneth D. Merry */ 2529991554f2SKenneth D. Merry static int 2530991554f2SKenneth D. Merry _mapping_check_update_ir_mt_idx(struct mpr_softc *sc, 2531991554f2SKenneth D. Merry Mpi2EventDataIrConfigChangeList_t *event_data, int evt_idx, u32 *map_idx, 2532991554f2SKenneth D. Merry u64 *wwid_table) 2533991554f2SKenneth D. Merry { 2534991554f2SKenneth D. Merry struct dev_mapping_table *mt_entry; 2535991554f2SKenneth D. Merry u32 st_idx, end_idx, mt_idx = *map_idx; 2536991554f2SKenneth D. Merry u8 match = 0; 2537991554f2SKenneth D. Merry Mpi2EventIrConfigElement_t *element; 2538991554f2SKenneth D. Merry u16 element_flags; 2539991554f2SKenneth D. Merry int i; 2540991554f2SKenneth D. Merry 2541991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[mt_idx]; 2542991554f2SKenneth D. Merry _mapping_get_ir_maprange(sc, &st_idx, &end_idx); 2543991554f2SKenneth D. Merry search_again: 2544991554f2SKenneth D. Merry match = 0; 2545991554f2SKenneth D. Merry for (i = evt_idx + 1; i < event_data->NumElements; i++) { 2546991554f2SKenneth D. Merry element = (Mpi2EventIrConfigElement_t *) 2547991554f2SKenneth D. Merry &event_data->ConfigElement[i]; 2548991554f2SKenneth D. Merry element_flags = le16toh(element->ElementFlags); 2549991554f2SKenneth D. Merry if ((element_flags & 2550991554f2SKenneth D. Merry MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK) != 2551991554f2SKenneth D. Merry MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT) 2552991554f2SKenneth D. Merry continue; 2553991554f2SKenneth D. Merry if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_ADDED || 2554991554f2SKenneth D. Merry element->ReasonCode == 2555991554f2SKenneth D. Merry MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) { 2556991554f2SKenneth D. Merry if (mt_entry->physical_id == wwid_table[i]) { 2557991554f2SKenneth D. Merry match = 1; 2558991554f2SKenneth D. Merry break; 2559991554f2SKenneth D. Merry } 2560991554f2SKenneth D. Merry } 2561991554f2SKenneth D. Merry } 2562991554f2SKenneth D. Merry 2563991554f2SKenneth D. Merry if (match) { 2564991554f2SKenneth D. Merry do { 2565991554f2SKenneth D. Merry mt_idx++; 2566991554f2SKenneth D. Merry if (mt_idx > end_idx) 2567991554f2SKenneth D. Merry return 1; 2568991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[mt_idx]; 2569991554f2SKenneth D. Merry } while (mt_entry->device_info & MPR_MAP_IN_USE); 2570991554f2SKenneth D. Merry goto search_again; 2571991554f2SKenneth D. Merry } 2572991554f2SKenneth D. Merry *map_idx = mt_idx; 2573991554f2SKenneth D. Merry return 0; 2574991554f2SKenneth D. Merry } 2575991554f2SKenneth D. Merry 2576991554f2SKenneth D. Merry /** 2577991554f2SKenneth D. Merry * mpr_mapping_ir_config_change_event - handle IR config change list events 2578991554f2SKenneth D. Merry * @sc: per adapter object 2579991554f2SKenneth D. Merry * @event_data: event data payload 2580991554f2SKenneth D. Merry * 2581991554f2SKenneth D. Merry * Returns nothing. 2582991554f2SKenneth D. Merry */ 2583991554f2SKenneth D. Merry void 2584991554f2SKenneth D. Merry mpr_mapping_ir_config_change_event(struct mpr_softc *sc, 2585991554f2SKenneth D. Merry Mpi2EventDataIrConfigChangeList_t *event_data) 2586991554f2SKenneth D. Merry { 2587991554f2SKenneth D. Merry Mpi2EventIrConfigElement_t *element; 2588991554f2SKenneth D. Merry int i; 2589991554f2SKenneth D. Merry u64 *wwid_table; 2590991554f2SKenneth D. Merry u32 map_idx, flags; 2591991554f2SKenneth D. Merry struct dev_mapping_table *mt_entry; 2592991554f2SKenneth D. Merry u16 element_flags; 2593991554f2SKenneth D. Merry u8 log_full_error = 0; 2594991554f2SKenneth D. Merry 2595991554f2SKenneth D. Merry wwid_table = malloc(sizeof(u64) * event_data->NumElements, M_MPR, 2596991554f2SKenneth D. Merry M_NOWAIT | M_ZERO); 2597991554f2SKenneth D. Merry if (!wwid_table) 2598991554f2SKenneth D. Merry goto out; 2599991554f2SKenneth D. Merry element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; 2600991554f2SKenneth D. Merry flags = le32toh(event_data->Flags); 2601991554f2SKenneth D. Merry for (i = 0; i < event_data->NumElements; i++, element++) { 2602991554f2SKenneth D. Merry element_flags = le16toh(element->ElementFlags); 2603991554f2SKenneth D. Merry if ((element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_ADDED) && 2604991554f2SKenneth D. Merry (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_REMOVED) && 2605991554f2SKenneth D. Merry (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE) 2606991554f2SKenneth D. Merry && (element->ReasonCode != 2607991554f2SKenneth D. Merry MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED)) 2608991554f2SKenneth D. Merry continue; 2609991554f2SKenneth D. Merry if ((element_flags & 2610991554f2SKenneth D. Merry MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK) == 2611991554f2SKenneth D. Merry MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT) { 2612991554f2SKenneth D. Merry mpr_config_get_volume_wwid(sc, 2613991554f2SKenneth D. Merry le16toh(element->VolDevHandle), &wwid_table[i]); 2614991554f2SKenneth D. Merry map_idx = _mapping_get_ir_mt_idx_from_wwid(sc, 2615991554f2SKenneth D. Merry wwid_table[i]); 2616991554f2SKenneth D. Merry if (map_idx != MPR_MAPTABLE_BAD_IDX) { 2617991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 2618991554f2SKenneth D. Merry mt_entry->device_info |= MPR_MAP_IN_USE; 2619991554f2SKenneth D. Merry } 2620991554f2SKenneth D. Merry } 2621991554f2SKenneth D. Merry } 2622991554f2SKenneth D. Merry if (flags == MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) 2623991554f2SKenneth D. Merry goto out; 2624991554f2SKenneth D. Merry else { 2625991554f2SKenneth D. Merry element = (Mpi2EventIrConfigElement_t *)&event_data-> 2626991554f2SKenneth D. Merry ConfigElement[0]; 2627991554f2SKenneth D. Merry for (i = 0; i < event_data->NumElements; i++, element++) { 2628991554f2SKenneth D. Merry if (element->ReasonCode == 2629991554f2SKenneth D. Merry MPI2_EVENT_IR_CHANGE_RC_ADDED || 2630991554f2SKenneth D. Merry element->ReasonCode == 2631991554f2SKenneth D. Merry MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) { 2632991554f2SKenneth D. Merry map_idx = _mapping_get_ir_mt_idx_from_wwid 2633991554f2SKenneth D. Merry (sc, wwid_table[i]); 2634991554f2SKenneth D. Merry if (map_idx != MPR_MAPTABLE_BAD_IDX) { 2635991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 2636991554f2SKenneth D. Merry mt_entry->channel = MPR_RAID_CHANNEL; 2637991554f2SKenneth D. Merry mt_entry->id = map_idx; 2638991554f2SKenneth D. Merry mt_entry->dev_handle = le16toh 2639991554f2SKenneth D. Merry (element->VolDevHandle); 2640991554f2SKenneth D. Merry mt_entry->device_info = 2641991554f2SKenneth D. Merry MPR_DEV_RESERVED | MPR_MAP_IN_USE; 2642991554f2SKenneth D. Merry _mapping_update_ir_missing_cnt(sc, 2643991554f2SKenneth D. Merry map_idx, element, wwid_table[i]); 2644991554f2SKenneth D. Merry continue; 2645991554f2SKenneth D. Merry } 2646991554f2SKenneth D. Merry map_idx = _mapping_get_free_ir_mt_idx(sc); 2647991554f2SKenneth D. Merry if (map_idx == MPR_MAPTABLE_BAD_IDX) 2648991554f2SKenneth D. Merry log_full_error = 1; 2649991554f2SKenneth D. Merry else if (i < (event_data->NumElements - 1)) { 2650991554f2SKenneth D. Merry log_full_error = 2651991554f2SKenneth D. Merry _mapping_check_update_ir_mt_idx 2652991554f2SKenneth D. Merry (sc, event_data, i, &map_idx, 2653991554f2SKenneth D. Merry wwid_table); 2654991554f2SKenneth D. Merry } 2655991554f2SKenneth D. Merry if (log_full_error) { 2656991554f2SKenneth D. Merry printf("%s: no space to add the RAID " 2657991554f2SKenneth D. Merry "volume with handle 0x%04x in " 2658991554f2SKenneth D. Merry "mapping table\n", __func__, le16toh 2659991554f2SKenneth D. Merry (element->VolDevHandle)); 2660991554f2SKenneth D. Merry continue; 2661991554f2SKenneth D. Merry } 2662991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 2663991554f2SKenneth D. Merry mt_entry->physical_id = wwid_table[i]; 2664991554f2SKenneth D. Merry mt_entry->channel = MPR_RAID_CHANNEL; 2665991554f2SKenneth D. Merry mt_entry->id = map_idx; 2666991554f2SKenneth D. Merry mt_entry->dev_handle = le16toh(element-> 2667991554f2SKenneth D. Merry VolDevHandle); 2668991554f2SKenneth D. Merry mt_entry->device_info = MPR_DEV_RESERVED | 2669991554f2SKenneth D. Merry MPR_MAP_IN_USE; 2670991554f2SKenneth D. Merry mt_entry->init_complete = 0; 2671991554f2SKenneth D. Merry _mapping_update_ir_missing_cnt(sc, map_idx, 2672991554f2SKenneth D. Merry element, wwid_table[i]); 2673991554f2SKenneth D. Merry } else if (element->ReasonCode == 2674991554f2SKenneth D. Merry MPI2_EVENT_IR_CHANGE_RC_REMOVED) { 2675991554f2SKenneth D. Merry map_idx = _mapping_get_ir_mt_idx_from_wwid(sc, 2676991554f2SKenneth D. Merry wwid_table[i]); 2677991554f2SKenneth D. Merry if (map_idx == MPR_MAPTABLE_BAD_IDX) { 2678991554f2SKenneth D. Merry printf("%s: failed to remove a volume " 2679991554f2SKenneth D. Merry "because it has already been " 2680991554f2SKenneth D. Merry "removed\n", __func__); 2681991554f2SKenneth D. Merry continue; 2682991554f2SKenneth D. Merry } 2683991554f2SKenneth D. Merry _mapping_update_ir_missing_cnt(sc, map_idx, 2684991554f2SKenneth D. Merry element, wwid_table[i]); 2685991554f2SKenneth D. Merry } else if (element->ReasonCode == 2686991554f2SKenneth D. Merry MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED) { 2687991554f2SKenneth D. Merry map_idx = _mapping_get_mt_idx_from_handle(sc, 2688991554f2SKenneth D. Merry le16toh(element->VolDevHandle)); 2689991554f2SKenneth D. Merry if (map_idx == MPR_MAPTABLE_BAD_IDX) { 2690991554f2SKenneth D. Merry printf("%s: failed to remove volume " 2691991554f2SKenneth D. Merry "with handle 0x%04x because it has " 2692991554f2SKenneth D. Merry "already been removed\n", __func__, 2693991554f2SKenneth D. Merry le16toh(element->VolDevHandle)); 2694991554f2SKenneth D. Merry continue; 2695991554f2SKenneth D. Merry } 2696991554f2SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 2697991554f2SKenneth D. Merry _mapping_update_ir_missing_cnt(sc, map_idx, 2698991554f2SKenneth D. Merry element, mt_entry->physical_id); 2699991554f2SKenneth D. Merry } 2700991554f2SKenneth D. Merry } 2701991554f2SKenneth D. Merry } 2702991554f2SKenneth D. Merry 2703991554f2SKenneth D. Merry out: 2704991554f2SKenneth D. Merry _mapping_flush_dpm_pages(sc); 2705991554f2SKenneth D. Merry free(wwid_table, M_MPR); 2706991554f2SKenneth D. Merry if (sc->pending_map_events) 2707991554f2SKenneth D. Merry sc->pending_map_events--; 2708991554f2SKenneth D. Merry } 2709