1d043c564SKenneth D. Merry /*- 2718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3718cf2ccSPedro F. Giffuni * 4ef065d89SStephen McConnell * Copyright (c) 2011-2015 LSI Corp. 5ef065d89SStephen McConnell * Copyright (c) 2013-2015 Avago Technologies 6d043c564SKenneth D. Merry * All rights reserved. 7d043c564SKenneth D. Merry * 8d043c564SKenneth D. Merry * Redistribution and use in source and binary forms, with or without 9d043c564SKenneth D. Merry * modification, are permitted provided that the following conditions 10d043c564SKenneth D. Merry * are met: 11d043c564SKenneth D. Merry * 1. Redistributions of source code must retain the above copyright 12d043c564SKenneth D. Merry * notice, this list of conditions and the following disclaimer. 13d043c564SKenneth D. Merry * 2. Redistributions in binary form must reproduce the above copyright 14d043c564SKenneth D. Merry * notice, this list of conditions and the following disclaimer in the 15d043c564SKenneth D. Merry * documentation and/or other materials provided with the distribution. 16d043c564SKenneth D. Merry * 17d043c564SKenneth D. Merry * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18d043c564SKenneth D. Merry * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19d043c564SKenneth D. Merry * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20d043c564SKenneth D. Merry * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21d043c564SKenneth D. Merry * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22d043c564SKenneth D. Merry * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23d043c564SKenneth D. Merry * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24d043c564SKenneth D. Merry * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25d043c564SKenneth D. Merry * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26d043c564SKenneth D. Merry * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27d043c564SKenneth D. Merry * SUCH DAMAGE. 28d043c564SKenneth D. Merry * 29ef065d89SStephen McConnell * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD 30d043c564SKenneth D. Merry */ 31d043c564SKenneth D. Merry 32d043c564SKenneth D. Merry #include <sys/cdefs.h> 33d043c564SKenneth D. Merry __FBSDID("$FreeBSD$"); 34d043c564SKenneth D. Merry 35d043c564SKenneth D. Merry /* TODO Move headers to mpsvar */ 36d043c564SKenneth D. Merry #include <sys/types.h> 37d043c564SKenneth D. Merry #include <sys/param.h> 38d043c564SKenneth D. Merry #include <sys/lock.h> 39d043c564SKenneth D. Merry #include <sys/mutex.h> 40d043c564SKenneth D. Merry #include <sys/systm.h> 41d043c564SKenneth D. Merry #include <sys/kernel.h> 42d043c564SKenneth D. Merry #include <sys/malloc.h> 43d043c564SKenneth D. Merry #include <sys/kthread.h> 44d043c564SKenneth D. Merry #include <sys/taskqueue.h> 45d043c564SKenneth D. Merry #include <sys/bus.h> 46d043c564SKenneth D. Merry #include <sys/endian.h> 47d043c564SKenneth D. Merry #include <sys/sysctl.h> 48ee5c196bSScott Long #include <sys/sbuf.h> 49d043c564SKenneth D. Merry #include <sys/eventhandler.h> 50d043c564SKenneth D. Merry #include <sys/uio.h> 51d043c564SKenneth D. Merry #include <machine/bus.h> 52d043c564SKenneth D. Merry #include <machine/resource.h> 53d043c564SKenneth D. Merry #include <dev/mps/mpi/mpi2_type.h> 54d043c564SKenneth D. Merry #include <dev/mps/mpi/mpi2.h> 55d043c564SKenneth D. Merry #include <dev/mps/mpi/mpi2_ioc.h> 56d043c564SKenneth D. Merry #include <dev/mps/mpi/mpi2_sas.h> 57d043c564SKenneth D. Merry #include <dev/mps/mpi/mpi2_cnfg.h> 58d043c564SKenneth D. Merry #include <dev/mps/mpi/mpi2_init.h> 59d043c564SKenneth D. Merry #include <dev/mps/mpi/mpi2_tool.h> 60d043c564SKenneth D. Merry #include <dev/mps/mps_ioctl.h> 61d043c564SKenneth D. Merry #include <dev/mps/mpsvar.h> 62d043c564SKenneth D. Merry #include <dev/mps/mps_mapping.h> 63d043c564SKenneth D. Merry 64d043c564SKenneth D. Merry /** 65635e58c7SStephen McConnell * _mapping_clear_map_entry - Clear a particular mapping entry. 66d043c564SKenneth D. Merry * @map_entry: map table entry 67d043c564SKenneth D. Merry * 68d043c564SKenneth D. Merry * Returns nothing. 69d043c564SKenneth D. Merry */ 70d043c564SKenneth D. Merry static inline void 71d043c564SKenneth D. Merry _mapping_clear_map_entry(struct dev_mapping_table *map_entry) 72d043c564SKenneth D. Merry { 73d043c564SKenneth D. Merry map_entry->physical_id = 0; 74d043c564SKenneth D. Merry map_entry->device_info = 0; 75d043c564SKenneth D. Merry map_entry->phy_bits = 0; 76d043c564SKenneth D. Merry map_entry->dpm_entry_num = MPS_DPM_BAD_IDX; 77d043c564SKenneth D. Merry map_entry->dev_handle = 0; 78d043c564SKenneth D. Merry map_entry->id = -1; 79d043c564SKenneth D. Merry map_entry->missing_count = 0; 80d043c564SKenneth D. Merry map_entry->init_complete = 0; 81d043c564SKenneth D. Merry map_entry->TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR; 82d043c564SKenneth D. Merry } 83d043c564SKenneth D. Merry 84d043c564SKenneth D. Merry /** 85d043c564SKenneth D. Merry * _mapping_clear_enc_entry - Clear a particular enclosure table entry. 86d043c564SKenneth D. Merry * @enc_entry: enclosure table entry 87d043c564SKenneth D. Merry * 88d043c564SKenneth D. Merry * Returns nothing. 89d043c564SKenneth D. Merry */ 90d043c564SKenneth D. Merry static inline void 91d043c564SKenneth D. Merry _mapping_clear_enc_entry(struct enc_mapping_table *enc_entry) 92d043c564SKenneth D. Merry { 93d043c564SKenneth D. Merry enc_entry->enclosure_id = 0; 94d043c564SKenneth D. Merry enc_entry->start_index = MPS_MAPTABLE_BAD_IDX; 95d043c564SKenneth D. Merry enc_entry->phy_bits = 0; 96d043c564SKenneth D. Merry enc_entry->dpm_entry_num = MPS_DPM_BAD_IDX; 97d043c564SKenneth D. Merry enc_entry->enc_handle = 0; 98d043c564SKenneth D. Merry enc_entry->num_slots = 0; 99d043c564SKenneth D. Merry enc_entry->start_slot = 0; 100d043c564SKenneth D. Merry enc_entry->missing_count = 0; 101d043c564SKenneth D. Merry enc_entry->removal_flag = 0; 102d043c564SKenneth D. Merry enc_entry->skip_search = 0; 103d043c564SKenneth D. Merry enc_entry->init_complete = 0; 104d043c564SKenneth D. Merry } 105d043c564SKenneth D. Merry 106d043c564SKenneth D. Merry /** 107d043c564SKenneth D. Merry * _mapping_commit_enc_entry - write a particular enc entry in DPM page0. 108d043c564SKenneth D. Merry * @sc: per adapter object 109d043c564SKenneth D. Merry * @enc_entry: enclosure table entry 110d043c564SKenneth D. Merry * 111d043c564SKenneth D. Merry * Returns 0 for success, non-zero for failure. 112d043c564SKenneth D. Merry */ 113d043c564SKenneth D. Merry static int 114d043c564SKenneth D. Merry _mapping_commit_enc_entry(struct mps_softc *sc, 115d043c564SKenneth D. Merry struct enc_mapping_table *et_entry) 116d043c564SKenneth D. Merry { 117d043c564SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry; 118d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry; 119d043c564SKenneth D. Merry Mpi2ConfigReply_t mpi_reply; 120d043c564SKenneth D. Merry Mpi2DriverMappingPage0_t config_page; 121d043c564SKenneth D. Merry 122d043c564SKenneth D. Merry if (!sc->is_dpm_enable) 123d043c564SKenneth D. Merry return 0; 124d043c564SKenneth D. Merry 125d043c564SKenneth D. Merry memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t)); 126d043c564SKenneth D. Merry memcpy(&config_page.Header, (u8 *) sc->dpm_pg0, 127d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 128d043c564SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 + 129d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 130d043c564SKenneth D. Merry dpm_entry += et_entry->dpm_entry_num; 131d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low = 132d043c564SKenneth D. Merry ( 0xFFFFFFFF & et_entry->enclosure_id); 133d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.High = 134d043c564SKenneth D. Merry ( et_entry->enclosure_id >> 32); 135d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[et_entry->start_index]; 136d043c564SKenneth D. Merry dpm_entry->DeviceIndex = htole16(mt_entry->id); 137d043c564SKenneth D. Merry dpm_entry->MappingInformation = et_entry->num_slots; 138d043c564SKenneth D. Merry dpm_entry->MappingInformation <<= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT; 139d043c564SKenneth D. Merry dpm_entry->MappingInformation |= et_entry->missing_count; 140d043c564SKenneth D. Merry dpm_entry->MappingInformation = htole16(dpm_entry->MappingInformation); 141d043c564SKenneth D. Merry dpm_entry->PhysicalBitsMapping = htole32(et_entry->phy_bits); 142d043c564SKenneth D. Merry dpm_entry->Reserved1 = 0; 143d043c564SKenneth D. Merry 144635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Writing DPM entry %d for enclosure.\n", 145635e58c7SStephen McConnell __func__, et_entry->dpm_entry_num); 146d043c564SKenneth D. Merry memcpy(&config_page.Entry, (u8 *)dpm_entry, 147d043c564SKenneth D. Merry sizeof(Mpi2DriverMap0Entry_t)); 148d043c564SKenneth D. Merry if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page, 149d043c564SKenneth D. Merry et_entry->dpm_entry_num)) { 150635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Write of DPM " 151635e58c7SStephen McConnell "entry %d for enclosure failed.\n", __func__, 152635e58c7SStephen McConnell et_entry->dpm_entry_num); 153d043c564SKenneth D. Merry dpm_entry->MappingInformation = le16toh(dpm_entry-> 154d043c564SKenneth D. Merry MappingInformation); 155d043c564SKenneth D. Merry dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex); 156d043c564SKenneth D. Merry dpm_entry->PhysicalBitsMapping = 157d043c564SKenneth D. Merry le32toh(dpm_entry->PhysicalBitsMapping); 158d043c564SKenneth D. Merry return -1; 159d043c564SKenneth D. Merry } 160d043c564SKenneth D. Merry dpm_entry->MappingInformation = le16toh(dpm_entry-> 161d043c564SKenneth D. Merry MappingInformation); 162d043c564SKenneth D. Merry dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex); 163d043c564SKenneth D. Merry dpm_entry->PhysicalBitsMapping = 164d043c564SKenneth D. Merry le32toh(dpm_entry->PhysicalBitsMapping); 165d043c564SKenneth D. Merry return 0; 166d043c564SKenneth D. Merry } 167d043c564SKenneth D. Merry 168d043c564SKenneth D. Merry /** 169d043c564SKenneth D. Merry * _mapping_commit_map_entry - write a particular map table entry in DPM page0. 170d043c564SKenneth D. Merry * @sc: per adapter object 171635e58c7SStephen McConnell * @mt_entry: mapping table entry 172d043c564SKenneth D. Merry * 173d043c564SKenneth D. Merry * Returns 0 for success, non-zero for failure. 174d043c564SKenneth D. Merry */ 175d043c564SKenneth D. Merry 176d043c564SKenneth D. Merry static int 177d043c564SKenneth D. Merry _mapping_commit_map_entry(struct mps_softc *sc, 178d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry) 179d043c564SKenneth D. Merry { 180d043c564SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry; 181d043c564SKenneth D. Merry Mpi2ConfigReply_t mpi_reply; 182d043c564SKenneth D. Merry Mpi2DriverMappingPage0_t config_page; 183d043c564SKenneth D. Merry 184d043c564SKenneth D. Merry if (!sc->is_dpm_enable) 185d043c564SKenneth D. Merry return 0; 186d043c564SKenneth D. Merry 187635e58c7SStephen McConnell /* 188635e58c7SStephen McConnell * It's possible that this Map Entry points to a BAD DPM index. This 189635e58c7SStephen McConnell * can happen if the Map Entry is a for a missing device and the DPM 190635e58c7SStephen McConnell * entry that was being used by this device is now being used by some 191635e58c7SStephen McConnell * new device. So, check for a BAD DPM index and just return if so. 192635e58c7SStephen McConnell */ 193635e58c7SStephen McConnell if (mt_entry->dpm_entry_num == MPS_DPM_BAD_IDX) { 194635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: DPM entry location for target " 195635e58c7SStephen McConnell "%d is invalid. DPM will not be written.\n", __func__, 196635e58c7SStephen McConnell mt_entry->id); 197635e58c7SStephen McConnell return 0; 198635e58c7SStephen McConnell } 199635e58c7SStephen McConnell 200d043c564SKenneth D. Merry memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t)); 201d043c564SKenneth D. Merry memcpy(&config_page.Header, (u8 *)sc->dpm_pg0, 202d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 203d043c564SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *) sc->dpm_pg0 + 204d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 205d043c564SKenneth D. Merry dpm_entry = dpm_entry + mt_entry->dpm_entry_num; 206d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low = (0xFFFFFFFF & 207d043c564SKenneth D. Merry mt_entry->physical_id); 208d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.High = (mt_entry->physical_id >> 32); 209d043c564SKenneth D. Merry dpm_entry->DeviceIndex = htole16(mt_entry->id); 210d043c564SKenneth D. Merry dpm_entry->MappingInformation = htole16(mt_entry->missing_count); 211d043c564SKenneth D. Merry dpm_entry->PhysicalBitsMapping = 0; 212d043c564SKenneth D. Merry dpm_entry->Reserved1 = 0; 213d043c564SKenneth D. Merry memcpy(&config_page.Entry, (u8 *)dpm_entry, 214d043c564SKenneth D. Merry sizeof(Mpi2DriverMap0Entry_t)); 215635e58c7SStephen McConnell 216635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Writing DPM entry %d for target %d.\n", 217635e58c7SStephen McConnell __func__, mt_entry->dpm_entry_num, mt_entry->id); 218d043c564SKenneth D. Merry if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page, 219d043c564SKenneth D. Merry mt_entry->dpm_entry_num)) { 220635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Write of DPM " 221635e58c7SStephen McConnell "entry %d for target %d failed.\n", __func__, 222635e58c7SStephen McConnell mt_entry->dpm_entry_num, mt_entry->id); 223d043c564SKenneth D. Merry dpm_entry->MappingInformation = le16toh(dpm_entry-> 224d043c564SKenneth D. Merry MappingInformation); 225d043c564SKenneth D. Merry dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex); 226d043c564SKenneth D. Merry return -1; 227d043c564SKenneth D. Merry } 228d043c564SKenneth D. Merry 229d043c564SKenneth D. Merry dpm_entry->MappingInformation = le16toh(dpm_entry->MappingInformation); 230d043c564SKenneth D. Merry dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex); 231d043c564SKenneth D. Merry return 0; 232d043c564SKenneth D. Merry } 233d043c564SKenneth D. Merry 234d043c564SKenneth D. Merry /** 235d043c564SKenneth D. Merry * _mapping_get_ir_maprange - get start and end index for IR map range. 236d043c564SKenneth D. Merry * @sc: per adapter object 237d043c564SKenneth D. Merry * @start_idx: place holder for start index 238d043c564SKenneth D. Merry * @end_idx: place holder for end index 239d043c564SKenneth D. Merry * 240d043c564SKenneth D. Merry * The IR volumes can be mapped either at start or end of the mapping table 241d043c564SKenneth D. Merry * this function gets the detail of where IR volume mapping starts and ends 242d043c564SKenneth D. Merry * in the device mapping table 243d043c564SKenneth D. Merry * 244d043c564SKenneth D. Merry * Returns nothing. 245d043c564SKenneth D. Merry */ 246d043c564SKenneth D. Merry static void 247d043c564SKenneth D. Merry _mapping_get_ir_maprange(struct mps_softc *sc, u32 *start_idx, u32 *end_idx) 248d043c564SKenneth D. Merry { 249d043c564SKenneth D. Merry u16 volume_mapping_flags; 250d043c564SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 251d043c564SKenneth D. Merry 252d043c564SKenneth D. Merry volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) & 253d043c564SKenneth D. Merry MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; 254d043c564SKenneth D. Merry if (volume_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) { 255d043c564SKenneth D. Merry *start_idx = 0; 256d043c564SKenneth D. Merry if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0) 257d043c564SKenneth D. Merry *start_idx = 1; 258d043c564SKenneth D. Merry } else 259d043c564SKenneth D. Merry *start_idx = sc->max_devices - sc->max_volumes; 260d043c564SKenneth D. Merry *end_idx = *start_idx + sc->max_volumes - 1; 261d043c564SKenneth D. Merry } 262d043c564SKenneth D. Merry 263d043c564SKenneth D. Merry /** 264d043c564SKenneth D. Merry * _mapping_get_enc_idx_from_id - get enclosure index from enclosure ID 265d043c564SKenneth D. Merry * @sc: per adapter object 266d043c564SKenneth D. Merry * @enc_id: enclosure logical identifier 267d043c564SKenneth D. Merry * 268d043c564SKenneth D. Merry * Returns the index of enclosure entry on success or bad index. 269d043c564SKenneth D. Merry */ 270d043c564SKenneth D. Merry static u8 271d043c564SKenneth D. Merry _mapping_get_enc_idx_from_id(struct mps_softc *sc, u64 enc_id, 272d043c564SKenneth D. Merry u64 phy_bits) 273d043c564SKenneth D. Merry { 274d043c564SKenneth D. Merry struct enc_mapping_table *et_entry; 275d043c564SKenneth D. Merry u8 enc_idx = 0; 276d043c564SKenneth D. Merry 277d043c564SKenneth D. Merry for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) { 278d043c564SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx]; 279d043c564SKenneth D. Merry if ((et_entry->enclosure_id == le64toh(enc_id)) && 280d043c564SKenneth D. Merry (!et_entry->phy_bits || (et_entry->phy_bits & 281d043c564SKenneth D. Merry le32toh(phy_bits)))) 282d043c564SKenneth D. Merry return enc_idx; 283d043c564SKenneth D. Merry } 284d043c564SKenneth D. Merry return MPS_ENCTABLE_BAD_IDX; 285d043c564SKenneth D. Merry } 286d043c564SKenneth D. Merry 287d043c564SKenneth D. Merry /** 288d043c564SKenneth D. Merry * _mapping_get_enc_idx_from_handle - get enclosure index from handle 289d043c564SKenneth D. Merry * @sc: per adapter object 290d043c564SKenneth D. Merry * @enc_id: enclosure handle 291d043c564SKenneth D. Merry * 292d043c564SKenneth D. Merry * Returns the index of enclosure entry on success or bad index. 293d043c564SKenneth D. Merry */ 294d043c564SKenneth D. Merry static u8 295d043c564SKenneth D. Merry _mapping_get_enc_idx_from_handle(struct mps_softc *sc, u16 handle) 296d043c564SKenneth D. Merry { 297d043c564SKenneth D. Merry struct enc_mapping_table *et_entry; 298d043c564SKenneth D. Merry u8 enc_idx = 0; 299d043c564SKenneth D. Merry 300d043c564SKenneth D. Merry for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) { 301d043c564SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx]; 302d043c564SKenneth D. Merry if (et_entry->missing_count) 303d043c564SKenneth D. Merry continue; 304d043c564SKenneth D. Merry if (et_entry->enc_handle == handle) 305d043c564SKenneth D. Merry return enc_idx; 306d043c564SKenneth D. Merry } 307d043c564SKenneth D. Merry return MPS_ENCTABLE_BAD_IDX; 308d043c564SKenneth D. Merry } 309d043c564SKenneth D. Merry 310d043c564SKenneth D. Merry /** 311d043c564SKenneth D. Merry * _mapping_get_high_missing_et_idx - get missing enclosure index 312d043c564SKenneth D. Merry * @sc: per adapter object 313d043c564SKenneth D. Merry * 314d043c564SKenneth D. Merry * Search through the enclosure table and identifies the enclosure entry 315d043c564SKenneth D. Merry * with high missing count and returns it's index 316d043c564SKenneth D. Merry * 317d043c564SKenneth D. Merry * Returns the index of enclosure entry on success or bad index. 318d043c564SKenneth D. Merry */ 319d043c564SKenneth D. Merry static u8 320d043c564SKenneth D. Merry _mapping_get_high_missing_et_idx(struct mps_softc *sc) 321d043c564SKenneth D. Merry { 322d043c564SKenneth D. Merry struct enc_mapping_table *et_entry; 323d043c564SKenneth D. Merry u8 high_missing_count = 0; 324d043c564SKenneth D. Merry u8 enc_idx, high_idx = MPS_ENCTABLE_BAD_IDX; 325d043c564SKenneth D. Merry 326d043c564SKenneth D. Merry for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) { 327d043c564SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx]; 328d043c564SKenneth D. Merry if ((et_entry->missing_count > high_missing_count) && 329d043c564SKenneth D. Merry !et_entry->skip_search) { 330d043c564SKenneth D. Merry high_missing_count = et_entry->missing_count; 331d043c564SKenneth D. Merry high_idx = enc_idx; 332d043c564SKenneth D. Merry } 333d043c564SKenneth D. Merry } 334d043c564SKenneth D. Merry return high_idx; 335d043c564SKenneth D. Merry } 336d043c564SKenneth D. Merry 337d043c564SKenneth D. Merry /** 338d043c564SKenneth D. Merry * _mapping_get_high_missing_mt_idx - get missing map table index 339d043c564SKenneth D. Merry * @sc: per adapter object 340d043c564SKenneth D. Merry * 341d043c564SKenneth D. Merry * Search through the map table and identifies the device entry 342d043c564SKenneth D. Merry * with high missing count and returns it's index 343d043c564SKenneth D. Merry * 344d043c564SKenneth D. Merry * Returns the index of map table entry on success or bad index. 345d043c564SKenneth D. Merry */ 346d043c564SKenneth D. Merry static u32 347d043c564SKenneth D. Merry _mapping_get_high_missing_mt_idx(struct mps_softc *sc) 348d043c564SKenneth D. Merry { 349635e58c7SStephen McConnell u32 map_idx, high_idx = MPS_MAPTABLE_BAD_IDX; 350d043c564SKenneth D. Merry u8 high_missing_count = 0; 351d043c564SKenneth D. Merry u32 start_idx, end_idx, start_idx_ir, end_idx_ir; 352d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry; 353d043c564SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 354d043c564SKenneth D. Merry 355d043c564SKenneth D. Merry start_idx = 0; 3565d0b98f2SSteven Hartland start_idx_ir = 0; 3575d0b98f2SSteven Hartland end_idx_ir = 0; 358d043c564SKenneth D. Merry end_idx = sc->max_devices; 359d043c564SKenneth D. Merry if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0) 360d043c564SKenneth D. Merry start_idx = 1; 361e248a3d1SSteven Hartland if (sc->ir_firmware) { 362d043c564SKenneth D. Merry _mapping_get_ir_maprange(sc, &start_idx_ir, &end_idx_ir); 363d043c564SKenneth D. Merry if (start_idx == start_idx_ir) 364d043c564SKenneth D. Merry start_idx = end_idx_ir + 1; 365d043c564SKenneth D. Merry else 366d043c564SKenneth D. Merry end_idx = start_idx_ir; 367e248a3d1SSteven Hartland } 368d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[start_idx]; 369d043c564SKenneth D. Merry for (map_idx = start_idx; map_idx < end_idx; map_idx++, mt_entry++) { 370d043c564SKenneth D. Merry if (mt_entry->missing_count > high_missing_count) { 371d043c564SKenneth D. Merry high_missing_count = mt_entry->missing_count; 372d043c564SKenneth D. Merry high_idx = map_idx; 373d043c564SKenneth D. Merry } 374d043c564SKenneth D. Merry } 375d043c564SKenneth D. Merry return high_idx; 376d043c564SKenneth D. Merry } 377d043c564SKenneth D. Merry 378d043c564SKenneth D. Merry /** 379d043c564SKenneth D. Merry * _mapping_get_ir_mt_idx_from_wwid - get map table index from volume WWID 380d043c564SKenneth D. Merry * @sc: per adapter object 381d043c564SKenneth D. Merry * @wwid: world wide unique ID of the volume 382d043c564SKenneth D. Merry * 383d043c564SKenneth D. Merry * Returns the index of map table entry on success or bad index. 384d043c564SKenneth D. Merry */ 385d043c564SKenneth D. Merry static u32 386d043c564SKenneth D. Merry _mapping_get_ir_mt_idx_from_wwid(struct mps_softc *sc, u64 wwid) 387d043c564SKenneth D. Merry { 388d043c564SKenneth D. Merry u32 start_idx, end_idx, map_idx; 389d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry; 390d043c564SKenneth D. Merry 391d043c564SKenneth D. Merry _mapping_get_ir_maprange(sc, &start_idx, &end_idx); 392d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[start_idx]; 393d043c564SKenneth D. Merry for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) 394d043c564SKenneth D. Merry if (mt_entry->physical_id == wwid) 395d043c564SKenneth D. Merry return map_idx; 396d043c564SKenneth D. Merry 397d043c564SKenneth D. Merry return MPS_MAPTABLE_BAD_IDX; 398d043c564SKenneth D. Merry } 399d043c564SKenneth D. Merry 400d043c564SKenneth D. Merry /** 401d043c564SKenneth D. Merry * _mapping_get_mt_idx_from_id - get map table index from a device ID 402d043c564SKenneth D. Merry * @sc: per adapter object 403d043c564SKenneth D. Merry * @dev_id: device identifer (SAS Address) 404d043c564SKenneth D. Merry * 405d043c564SKenneth D. Merry * Returns the index of map table entry on success or bad index. 406d043c564SKenneth D. Merry */ 407d043c564SKenneth D. Merry static u32 408d043c564SKenneth D. Merry _mapping_get_mt_idx_from_id(struct mps_softc *sc, u64 dev_id) 409d043c564SKenneth D. Merry { 410d043c564SKenneth D. Merry u32 map_idx; 411d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry; 412d043c564SKenneth D. Merry 413d043c564SKenneth D. Merry for (map_idx = 0; map_idx < sc->max_devices; map_idx++) { 414d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 415d043c564SKenneth D. Merry if (mt_entry->physical_id == dev_id) 416d043c564SKenneth D. Merry return map_idx; 417d043c564SKenneth D. Merry } 418d043c564SKenneth D. Merry return MPS_MAPTABLE_BAD_IDX; 419d043c564SKenneth D. Merry } 420d043c564SKenneth D. Merry 421d043c564SKenneth D. Merry /** 422d043c564SKenneth D. Merry * _mapping_get_ir_mt_idx_from_handle - get map table index from volume handle 423d043c564SKenneth D. Merry * @sc: per adapter object 424d043c564SKenneth D. Merry * @wwid: volume device handle 425d043c564SKenneth D. Merry * 426d043c564SKenneth D. Merry * Returns the index of map table entry on success or bad index. 427d043c564SKenneth D. Merry */ 428d043c564SKenneth D. Merry static u32 429d043c564SKenneth D. Merry _mapping_get_ir_mt_idx_from_handle(struct mps_softc *sc, u16 volHandle) 430d043c564SKenneth D. Merry { 431d043c564SKenneth D. Merry u32 start_idx, end_idx, map_idx; 432d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry; 433d043c564SKenneth D. Merry 434d043c564SKenneth D. Merry _mapping_get_ir_maprange(sc, &start_idx, &end_idx); 435d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[start_idx]; 436d043c564SKenneth D. Merry for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) 437d043c564SKenneth D. Merry if (mt_entry->dev_handle == volHandle) 438d043c564SKenneth D. Merry return map_idx; 439d043c564SKenneth D. Merry 440d043c564SKenneth D. Merry return MPS_MAPTABLE_BAD_IDX; 441d043c564SKenneth D. Merry } 442d043c564SKenneth D. Merry 443d043c564SKenneth D. Merry /** 444d043c564SKenneth D. Merry * _mapping_get_mt_idx_from_handle - get map table index from handle 445d043c564SKenneth D. Merry * @sc: per adapter object 446d043c564SKenneth D. Merry * @dev_id: device handle 447d043c564SKenneth D. Merry * 448d043c564SKenneth D. Merry * Returns the index of map table entry on success or bad index. 449d043c564SKenneth D. Merry */ 450d043c564SKenneth D. Merry static u32 451d043c564SKenneth D. Merry _mapping_get_mt_idx_from_handle(struct mps_softc *sc, u16 handle) 452d043c564SKenneth D. Merry { 453d043c564SKenneth D. Merry u32 map_idx; 454d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry; 455d043c564SKenneth D. Merry 456d043c564SKenneth D. Merry for (map_idx = 0; map_idx < sc->max_devices; map_idx++) { 457d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 458d043c564SKenneth D. Merry if (mt_entry->dev_handle == handle) 459d043c564SKenneth D. Merry return map_idx; 460d043c564SKenneth D. Merry } 461d043c564SKenneth D. Merry return MPS_MAPTABLE_BAD_IDX; 462d043c564SKenneth D. Merry } 463d043c564SKenneth D. Merry 464d043c564SKenneth D. Merry /** 465d043c564SKenneth D. Merry * _mapping_get_free_ir_mt_idx - get first free index for a volume 466d043c564SKenneth D. Merry * @sc: per adapter object 467d043c564SKenneth D. Merry * 468d043c564SKenneth D. Merry * Search through mapping table for free index for a volume and if no free 469d043c564SKenneth D. Merry * index then looks for a volume with high mapping index 470d043c564SKenneth D. Merry * 471d043c564SKenneth D. Merry * Returns the index of map table entry on success or bad index. 472d043c564SKenneth D. Merry */ 473d043c564SKenneth D. Merry static u32 474d043c564SKenneth D. Merry _mapping_get_free_ir_mt_idx(struct mps_softc *sc) 475d043c564SKenneth D. Merry { 476d043c564SKenneth D. Merry u8 high_missing_count = 0; 477d043c564SKenneth D. Merry u32 start_idx, end_idx, map_idx; 478d043c564SKenneth D. Merry u32 high_idx = MPS_MAPTABLE_BAD_IDX; 479d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry; 480d043c564SKenneth D. Merry 481635e58c7SStephen McConnell /* 482635e58c7SStephen McConnell * The IN_USE flag should be clear if the entry is available to use. 483635e58c7SStephen McConnell * This flag is cleared on initialization and and when a volume is 484635e58c7SStephen McConnell * deleted. All other times this flag should be set. If, for some 485635e58c7SStephen McConnell * reason, a free entry cannot be found, look for the entry with the 486635e58c7SStephen McConnell * highest missing count just in case there is one. 487635e58c7SStephen McConnell */ 488d043c564SKenneth D. Merry _mapping_get_ir_maprange(sc, &start_idx, &end_idx); 489d043c564SKenneth D. Merry 490d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[start_idx]; 491635e58c7SStephen McConnell for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) { 492d043c564SKenneth D. Merry if (!(mt_entry->device_info & MPS_MAP_IN_USE)) 493d043c564SKenneth D. Merry return map_idx; 494d043c564SKenneth D. Merry 495d043c564SKenneth D. Merry if (mt_entry->missing_count > high_missing_count) { 496d043c564SKenneth D. Merry high_missing_count = mt_entry->missing_count; 497d043c564SKenneth D. Merry high_idx = map_idx; 498d043c564SKenneth D. Merry } 499d043c564SKenneth D. Merry } 500635e58c7SStephen McConnell 501635e58c7SStephen McConnell if (high_idx == MPS_MAPTABLE_BAD_IDX) { 502635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Could not find a " 503635e58c7SStephen McConnell "free entry in the mapping table for a Volume. The mapping " 504635e58c7SStephen McConnell "table is probably corrupt.\n", __func__); 505635e58c7SStephen McConnell } 506635e58c7SStephen McConnell 507d043c564SKenneth D. Merry return high_idx; 508d043c564SKenneth D. Merry } 509d043c564SKenneth D. Merry 510d043c564SKenneth D. Merry /** 511d043c564SKenneth D. Merry * _mapping_get_free_mt_idx - get first free index for a device 512d043c564SKenneth D. Merry * @sc: per adapter object 513d043c564SKenneth D. Merry * @start_idx: offset in the table to start search 514d043c564SKenneth D. Merry * 515d043c564SKenneth D. Merry * Returns the index of map table entry on success or bad index. 516d043c564SKenneth D. Merry */ 517d043c564SKenneth D. Merry static u32 518d043c564SKenneth D. Merry _mapping_get_free_mt_idx(struct mps_softc *sc, u32 start_idx) 519d043c564SKenneth D. Merry { 520d043c564SKenneth D. Merry u32 map_idx, max_idx = sc->max_devices; 521d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry = &sc->mapping_table[start_idx]; 522d043c564SKenneth D. Merry u16 volume_mapping_flags; 523d043c564SKenneth D. Merry 524d043c564SKenneth D. Merry volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) & 525d043c564SKenneth D. Merry MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; 526d043c564SKenneth D. Merry if (sc->ir_firmware && (volume_mapping_flags == 527d043c564SKenneth D. Merry MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING)) 528d043c564SKenneth D. Merry max_idx -= sc->max_volumes; 529635e58c7SStephen McConnell 530d043c564SKenneth D. Merry for (map_idx = start_idx; map_idx < max_idx; map_idx++, mt_entry++) 531d043c564SKenneth D. Merry if (!(mt_entry->device_info & (MPS_MAP_IN_USE | 532d043c564SKenneth D. Merry MPS_DEV_RESERVED))) 533d043c564SKenneth D. Merry return map_idx; 534d043c564SKenneth D. Merry 535d043c564SKenneth D. Merry return MPS_MAPTABLE_BAD_IDX; 536d043c564SKenneth D. Merry } 537d043c564SKenneth D. Merry 538d043c564SKenneth D. Merry /** 539d043c564SKenneth D. Merry * _mapping_get_dpm_idx_from_id - get DPM index from ID 540d043c564SKenneth D. Merry * @sc: per adapter object 541d043c564SKenneth D. Merry * @id: volume WWID or enclosure ID or device ID 542d043c564SKenneth D. Merry * 543d043c564SKenneth D. Merry * Returns the index of DPM entry on success or bad index. 544d043c564SKenneth D. Merry */ 545d043c564SKenneth D. Merry static u16 546d043c564SKenneth D. Merry _mapping_get_dpm_idx_from_id(struct mps_softc *sc, u64 id, u32 phy_bits) 547d043c564SKenneth D. Merry { 548d043c564SKenneth D. Merry u16 entry_num; 549d043c564SKenneth D. Merry uint64_t PhysicalIdentifier; 550d043c564SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry; 551d043c564SKenneth D. Merry 552d043c564SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 + 553d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 554d043c564SKenneth D. Merry PhysicalIdentifier = dpm_entry->PhysicalIdentifier.High; 555d043c564SKenneth D. Merry PhysicalIdentifier = (PhysicalIdentifier << 32) | 556d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low; 557d043c564SKenneth D. Merry for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++, 558d043c564SKenneth D. Merry dpm_entry++) 559d043c564SKenneth D. Merry if ((id == PhysicalIdentifier) && 560d043c564SKenneth D. Merry (!phy_bits || !dpm_entry->PhysicalBitsMapping || 561d043c564SKenneth D. Merry (phy_bits & dpm_entry->PhysicalBitsMapping))) 562d043c564SKenneth D. Merry return entry_num; 563d043c564SKenneth D. Merry 564d043c564SKenneth D. Merry return MPS_DPM_BAD_IDX; 565d043c564SKenneth D. Merry } 566d043c564SKenneth D. Merry 567d043c564SKenneth D. Merry /** 568d043c564SKenneth D. Merry * _mapping_get_free_dpm_idx - get first available DPM index 569d043c564SKenneth D. Merry * @sc: per adapter object 570d043c564SKenneth D. Merry * 571d043c564SKenneth D. Merry * Returns the index of DPM entry on success or bad index. 572d043c564SKenneth D. Merry */ 573d043c564SKenneth D. Merry static u32 574d043c564SKenneth D. Merry _mapping_get_free_dpm_idx(struct mps_softc *sc) 575d043c564SKenneth D. Merry { 576d043c564SKenneth D. Merry u16 entry_num; 577635e58c7SStephen McConnell Mpi2DriverMap0Entry_t *dpm_entry; 578635e58c7SStephen McConnell u16 current_entry = MPS_DPM_BAD_IDX, missing_cnt, high_missing_cnt = 0; 579635e58c7SStephen McConnell u64 physical_id; 580635e58c7SStephen McConnell struct dev_mapping_table *mt_entry; 581635e58c7SStephen McConnell u32 map_idx; 582d043c564SKenneth D. Merry 583d043c564SKenneth D. Merry for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) { 584635e58c7SStephen McConnell dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 + 585635e58c7SStephen McConnell sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 586635e58c7SStephen McConnell dpm_entry += entry_num; 587635e58c7SStephen McConnell missing_cnt = dpm_entry->MappingInformation & 588635e58c7SStephen McConnell MPI2_DRVMAP0_MAPINFO_MISSING_MASK; 589635e58c7SStephen McConnell 590635e58c7SStephen McConnell /* 591635e58c7SStephen McConnell * If entry is used and not missing, then this entry can't be 592635e58c7SStephen McConnell * used. Look at next one. 593635e58c7SStephen McConnell */ 594635e58c7SStephen McConnell if (sc->dpm_entry_used[entry_num] && !missing_cnt) 595635e58c7SStephen McConnell continue; 596635e58c7SStephen McConnell 597635e58c7SStephen McConnell /* 598635e58c7SStephen McConnell * If this entry is not used at all, then the missing count 599635e58c7SStephen McConnell * doesn't matter. Just use this one. Otherwise, keep looking 600635e58c7SStephen McConnell * and make sure the entry with the highest missing count is 601635e58c7SStephen McConnell * used. 602635e58c7SStephen McConnell */ 603635e58c7SStephen McConnell if (!sc->dpm_entry_used[entry_num]) { 604635e58c7SStephen McConnell current_entry = entry_num; 605635e58c7SStephen McConnell break; 606d043c564SKenneth D. Merry } 607635e58c7SStephen McConnell if ((current_entry == MPS_DPM_BAD_IDX) || 608635e58c7SStephen McConnell (missing_cnt > high_missing_cnt)) { 609635e58c7SStephen McConnell current_entry = entry_num; 610635e58c7SStephen McConnell high_missing_cnt = missing_cnt; 611635e58c7SStephen McConnell } 612635e58c7SStephen McConnell } 613635e58c7SStephen McConnell 614635e58c7SStephen McConnell /* 615635e58c7SStephen McConnell * If an entry has been found to use and it's already marked as used 616635e58c7SStephen McConnell * it means that some device was already using this entry but it's 617635e58c7SStephen McConnell * missing, and that means that the connection between the missing 618635e58c7SStephen McConnell * device's DPM entry and the mapping table needs to be cleared. To do 619635e58c7SStephen McConnell * this, use the Physical ID of the old device still in the DPM entry 620635e58c7SStephen McConnell * to find its mapping table entry, then mark its DPM entry as BAD. 621635e58c7SStephen McConnell */ 622635e58c7SStephen McConnell if ((current_entry != MPS_DPM_BAD_IDX) && 623635e58c7SStephen McConnell sc->dpm_entry_used[current_entry]) { 624635e58c7SStephen McConnell dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 + 625635e58c7SStephen McConnell sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 626635e58c7SStephen McConnell dpm_entry += current_entry; 627635e58c7SStephen McConnell physical_id = dpm_entry->PhysicalIdentifier.High; 628635e58c7SStephen McConnell physical_id = (physical_id << 32) | 629635e58c7SStephen McConnell dpm_entry->PhysicalIdentifier.Low; 630635e58c7SStephen McConnell map_idx = _mapping_get_mt_idx_from_id(sc, physical_id); 631635e58c7SStephen McConnell if (map_idx != MPS_MAPTABLE_BAD_IDX) { 632635e58c7SStephen McConnell mt_entry = &sc->mapping_table[map_idx]; 633635e58c7SStephen McConnell mt_entry->dpm_entry_num = MPS_DPM_BAD_IDX; 634635e58c7SStephen McConnell } 635635e58c7SStephen McConnell } 636635e58c7SStephen McConnell return current_entry; 637d043c564SKenneth D. Merry } 638d043c564SKenneth D. Merry 639d043c564SKenneth D. Merry /** 640d043c564SKenneth D. Merry * _mapping_update_ir_missing_cnt - Updates missing count for a volume 641d043c564SKenneth D. Merry * @sc: per adapter object 642d043c564SKenneth D. Merry * @map_idx: map table index of the volume 643d043c564SKenneth D. Merry * @element: IR configuration change element 644d043c564SKenneth D. Merry * @wwid: IR volume ID. 645d043c564SKenneth D. Merry * 646d043c564SKenneth D. Merry * Updates the missing count in the map table and in the DPM entry for a volume 647d043c564SKenneth D. Merry * 648d043c564SKenneth D. Merry * Returns nothing. 649d043c564SKenneth D. Merry */ 650d043c564SKenneth D. Merry static void 651d043c564SKenneth D. Merry _mapping_update_ir_missing_cnt(struct mps_softc *sc, u32 map_idx, 652d043c564SKenneth D. Merry Mpi2EventIrConfigElement_t *element, u64 wwid) 653d043c564SKenneth D. Merry { 654d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry; 655635e58c7SStephen McConnell u8 missing_cnt, reason = element->ReasonCode, update_dpm = 1; 656d043c564SKenneth D. Merry u16 dpm_idx; 657d043c564SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry; 658d043c564SKenneth D. Merry 659635e58c7SStephen McConnell /* 660635e58c7SStephen McConnell * Depending on the reason code, update the missing count. Always set 661635e58c7SStephen McConnell * the init_complete flag when here, so just do it first. That flag is 662635e58c7SStephen McConnell * used for volumes to make sure that the DPM entry has been updated. 663635e58c7SStephen McConnell * When a volume is deleted, clear the map entry's IN_USE flag so that 664635e58c7SStephen McConnell * the entry can be used again if another volume is created. Also clear 665635e58c7SStephen McConnell * its dev_handle entry so that other functions can't find this volume 666635e58c7SStephen McConnell * by the handle, since it's not defined any longer. 667635e58c7SStephen McConnell */ 668d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 669635e58c7SStephen McConnell mt_entry->init_complete = 1; 670635e58c7SStephen McConnell if ((reason == MPI2_EVENT_IR_CHANGE_RC_ADDED) || 671635e58c7SStephen McConnell (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED)) { 672d043c564SKenneth D. Merry mt_entry->missing_count = 0; 673635e58c7SStephen McConnell } else if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED) { 674d043c564SKenneth D. Merry if (mt_entry->missing_count < MPS_MAX_MISSING_COUNT) 675d043c564SKenneth D. Merry mt_entry->missing_count++; 676635e58c7SStephen McConnell 677635e58c7SStephen McConnell mt_entry->device_info &= ~MPS_MAP_IN_USE; 678d043c564SKenneth D. Merry mt_entry->dev_handle = 0; 679d043c564SKenneth D. Merry } 680d043c564SKenneth D. Merry 681635e58c7SStephen McConnell /* 682635e58c7SStephen McConnell * If persistent mapping is enabled, update the DPM with the new missing 683635e58c7SStephen McConnell * count for the volume. If the DPM index is bad, get a free one. If 684635e58c7SStephen McConnell * it's bad for a volume that's being deleted do nothing because that 685635e58c7SStephen McConnell * volume doesn't have a DPM entry. 686635e58c7SStephen McConnell */ 687635e58c7SStephen McConnell if (!sc->is_dpm_enable) 688635e58c7SStephen McConnell return; 689d043c564SKenneth D. Merry dpm_idx = mt_entry->dpm_entry_num; 690d043c564SKenneth D. Merry if (dpm_idx == MPS_DPM_BAD_IDX) { 691635e58c7SStephen McConnell if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED) 692635e58c7SStephen McConnell { 693635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Volume being deleted " 694635e58c7SStephen McConnell "is not in DPM so DPM missing count will not be " 695635e58c7SStephen McConnell "updated.\n", __func__); 696d043c564SKenneth D. Merry return; 697d043c564SKenneth D. Merry } 698635e58c7SStephen McConnell } 699635e58c7SStephen McConnell if (dpm_idx == MPS_DPM_BAD_IDX) 700635e58c7SStephen McConnell dpm_idx = _mapping_get_free_dpm_idx(sc); 701635e58c7SStephen McConnell 702635e58c7SStephen McConnell /* 703635e58c7SStephen McConnell * Got the DPM entry for the volume or found a free DPM entry if this is 704635e58c7SStephen McConnell * a new volume. Check if the current information is outdated. 705635e58c7SStephen McConnell */ 706d043c564SKenneth D. Merry if (dpm_idx != MPS_DPM_BAD_IDX) { 707d043c564SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 + 708d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 709d043c564SKenneth D. Merry dpm_entry += dpm_idx; 710d043c564SKenneth D. Merry missing_cnt = dpm_entry->MappingInformation & 711d043c564SKenneth D. Merry MPI2_DRVMAP0_MAPINFO_MISSING_MASK; 712d043c564SKenneth D. Merry if ((mt_entry->physical_id == 713635e58c7SStephen McConnell le64toh(((u64)dpm_entry->PhysicalIdentifier.High << 32) | 714635e58c7SStephen McConnell (u64)dpm_entry->PhysicalIdentifier.Low)) && (missing_cnt == 715635e58c7SStephen McConnell mt_entry->missing_count)) { 716635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: DPM entry for volume " 717635e58c7SStephen McConnell "with target ID %d does not require an update.\n", 718635e58c7SStephen McConnell __func__, mt_entry->id); 719635e58c7SStephen McConnell update_dpm = 0; 720635e58c7SStephen McConnell } 721d043c564SKenneth D. Merry } 722d043c564SKenneth D. Merry 723635e58c7SStephen McConnell /* 724635e58c7SStephen McConnell * Update the volume's persistent info if it's new or the ID or missing 725635e58c7SStephen McConnell * count has changed. If a good DPM index has not been found by now, 726635e58c7SStephen McConnell * there is no space left in the DPM table. 727635e58c7SStephen McConnell */ 728635e58c7SStephen McConnell if ((dpm_idx != MPS_DPM_BAD_IDX) && update_dpm) { 729635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Update DPM entry for volume " 730635e58c7SStephen McConnell "with target ID %d.\n", __func__, mt_entry->id); 731635e58c7SStephen McConnell 732d043c564SKenneth D. Merry mt_entry->dpm_entry_num = dpm_idx; 733d043c564SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 + 734d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 735d043c564SKenneth D. Merry dpm_entry += dpm_idx; 736d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low = 737d043c564SKenneth D. Merry (0xFFFFFFFF & mt_entry->physical_id); 738d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.High = 739d043c564SKenneth D. Merry (mt_entry->physical_id >> 32); 740d043c564SKenneth D. Merry dpm_entry->DeviceIndex = map_idx; 741d043c564SKenneth D. Merry dpm_entry->MappingInformation = mt_entry->missing_count; 742d043c564SKenneth D. Merry dpm_entry->PhysicalBitsMapping = 0; 743d043c564SKenneth D. Merry dpm_entry->Reserved1 = 0; 744d043c564SKenneth D. Merry sc->dpm_flush_entry[dpm_idx] = 1; 745d043c564SKenneth D. Merry sc->dpm_entry_used[dpm_idx] = 1; 746d043c564SKenneth D. Merry } else if (dpm_idx == MPS_DPM_BAD_IDX) { 747635e58c7SStephen McConnell mps_dprint(sc, MPS_INFO | MPS_MAPPING, "%s: No space to add an " 748635e58c7SStephen McConnell "entry in the DPM table for volume with target ID %d.\n", 749635e58c7SStephen McConnell __func__, mt_entry->id); 750d043c564SKenneth D. Merry } 751d043c564SKenneth D. Merry } 752d043c564SKenneth D. Merry 753d043c564SKenneth D. Merry /** 754635e58c7SStephen McConnell * _mapping_add_to_removal_table - add DPM index to the removal table 755d043c564SKenneth D. Merry * @sc: per adapter object 756635e58c7SStephen McConnell * @dpm_idx: Index of DPM entry to remove 757d043c564SKenneth D. Merry * 758635e58c7SStephen McConnell * Adds a DPM entry number to the removal table. 759d043c564SKenneth D. Merry * 760d043c564SKenneth D. Merry * Returns nothing. 761d043c564SKenneth D. Merry */ 762d043c564SKenneth D. Merry static void 763635e58c7SStephen McConnell _mapping_add_to_removal_table(struct mps_softc *sc, u16 dpm_idx) 764d043c564SKenneth D. Merry { 765d043c564SKenneth D. Merry struct map_removal_table *remove_entry; 766d043c564SKenneth D. Merry u32 i; 767d043c564SKenneth D. Merry 768635e58c7SStephen McConnell /* 769635e58c7SStephen McConnell * This is only used to remove entries from the DPM in the controller. 770635e58c7SStephen McConnell * If DPM is not enabled, just return. 771635e58c7SStephen McConnell */ 772635e58c7SStephen McConnell if (!sc->is_dpm_enable) 773635e58c7SStephen McConnell return; 774635e58c7SStephen McConnell 775635e58c7SStephen McConnell /* 776635e58c7SStephen McConnell * Find the first available removal_table entry and add the new entry 777635e58c7SStephen McConnell * there. 778635e58c7SStephen McConnell */ 779d043c564SKenneth D. Merry remove_entry = sc->removal_table; 780d043c564SKenneth D. Merry 781d043c564SKenneth D. Merry for (i = 0; i < sc->max_devices; i++, remove_entry++) { 782635e58c7SStephen McConnell if (remove_entry->dpm_entry_num != MPS_DPM_BAD_IDX) 783d043c564SKenneth D. Merry continue; 784635e58c7SStephen McConnell 785635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Adding DPM entry %d to table " 786635e58c7SStephen McConnell "for removal.\n", __func__, dpm_idx); 787d043c564SKenneth D. Merry remove_entry->dpm_entry_num = dpm_idx; 788d043c564SKenneth D. Merry break; 789d043c564SKenneth D. Merry } 790d043c564SKenneth D. Merry 791d043c564SKenneth D. Merry } 792d043c564SKenneth D. Merry 793d043c564SKenneth D. Merry /** 794d043c564SKenneth D. Merry * _mapping_update_missing_count - Update missing count for a device 795d043c564SKenneth D. Merry * @sc: per adapter object 796d043c564SKenneth D. Merry * @topo_change: Topology change event entry 797d043c564SKenneth D. Merry * 798635e58c7SStephen McConnell * Increment the missing count in the mapping table for a device that is not 799635e58c7SStephen McConnell * responding. If Persitent Mapping is used, increment the DPM entry as well. 800635e58c7SStephen McConnell * Currently, this function only increments the missing count if the device 801635e58c7SStephen McConnell * goes missing, so after initialization has completed. This means that the 802635e58c7SStephen McConnell * missing count can only go from 0 to 1 here. The missing count is incremented 803635e58c7SStephen McConnell * during initialization as well, so that's where a target's missing count can 804635e58c7SStephen McConnell * go past 1. 805d043c564SKenneth D. Merry * 806d043c564SKenneth D. Merry * Returns nothing. 807d043c564SKenneth D. Merry */ 808d043c564SKenneth D. Merry static void 809d043c564SKenneth D. Merry _mapping_update_missing_count(struct mps_softc *sc, 810d043c564SKenneth D. Merry struct _map_topology_change *topo_change) 811d043c564SKenneth D. Merry { 812d043c564SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 813d043c564SKenneth D. Merry u8 entry; 814d043c564SKenneth D. Merry struct _map_phy_change *phy_change; 815d043c564SKenneth D. Merry u32 map_idx; 816d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry; 817d043c564SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry; 818d043c564SKenneth D. Merry 819d043c564SKenneth D. Merry for (entry = 0; entry < topo_change->num_entries; entry++) { 820d043c564SKenneth D. Merry phy_change = &topo_change->phy_details[entry]; 821d043c564SKenneth D. Merry if (!phy_change->dev_handle || (phy_change->reason != 822d043c564SKenneth D. Merry MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)) 823d043c564SKenneth D. Merry continue; 824d043c564SKenneth D. Merry map_idx = _mapping_get_mt_idx_from_handle(sc, phy_change-> 825d043c564SKenneth D. Merry dev_handle); 826d043c564SKenneth D. Merry phy_change->is_processed = 1; 827d043c564SKenneth D. Merry if (map_idx == MPS_MAPTABLE_BAD_IDX) { 828635e58c7SStephen McConnell mps_dprint(sc, MPS_INFO | MPS_MAPPING, "%s: device is " 829635e58c7SStephen McConnell "already removed from mapping table\n", __func__); 830d043c564SKenneth D. Merry continue; 831d043c564SKenneth D. Merry } 832d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 833d043c564SKenneth D. Merry if (mt_entry->missing_count < MPS_MAX_MISSING_COUNT) 834d043c564SKenneth D. Merry mt_entry->missing_count++; 835d043c564SKenneth D. Merry 836635e58c7SStephen McConnell /* 837635e58c7SStephen McConnell * When using Enc/Slot mapping, when a device is removed, it's 838635e58c7SStephen McConnell * mapping table information should be cleared. Otherwise, the 839635e58c7SStephen McConnell * target ID will be incorrect if this same device is re-added 840635e58c7SStephen McConnell * to a different slot. 841635e58c7SStephen McConnell */ 842635e58c7SStephen McConnell if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 843635e58c7SStephen McConnell MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 844635e58c7SStephen McConnell _mapping_clear_map_entry(mt_entry); 845635e58c7SStephen McConnell } 846635e58c7SStephen McConnell 847635e58c7SStephen McConnell /* 848635e58c7SStephen McConnell * When using device mapping, update the missing count in the 849635e58c7SStephen McConnell * DPM entry, but only if the missing count has changed. 850635e58c7SStephen McConnell */ 851d043c564SKenneth D. Merry if (((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 852d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) && 853635e58c7SStephen McConnell sc->is_dpm_enable && 854d043c564SKenneth D. Merry mt_entry->dpm_entry_num != MPS_DPM_BAD_IDX) { 855d043c564SKenneth D. Merry dpm_entry = 856d043c564SKenneth D. Merry (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 + 857d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 858d043c564SKenneth D. Merry dpm_entry += mt_entry->dpm_entry_num; 859635e58c7SStephen McConnell if (dpm_entry->MappingInformation != 860635e58c7SStephen McConnell mt_entry->missing_count) { 861635e58c7SStephen McConnell dpm_entry->MappingInformation = 862635e58c7SStephen McConnell mt_entry->missing_count; 863635e58c7SStephen McConnell sc->dpm_flush_entry[mt_entry->dpm_entry_num] = 864635e58c7SStephen McConnell 1; 865d043c564SKenneth D. Merry } 866635e58c7SStephen McConnell } 867d043c564SKenneth D. Merry } 868d043c564SKenneth D. Merry } 869d043c564SKenneth D. Merry 870d043c564SKenneth D. Merry /** 871d043c564SKenneth D. Merry * _mapping_find_enc_map_space -find map table entries for enclosure 872d043c564SKenneth D. Merry * @sc: per adapter object 873d043c564SKenneth D. Merry * @et_entry: enclosure entry 874d043c564SKenneth D. Merry * 875d043c564SKenneth D. Merry * Search through the mapping table defragment it and provide contiguous 876d043c564SKenneth D. Merry * space in map table for a particular enclosure entry 877d043c564SKenneth D. Merry * 878d043c564SKenneth D. Merry * Returns start index in map table or bad index. 879d043c564SKenneth D. Merry */ 880d043c564SKenneth D. Merry static u32 881d043c564SKenneth D. Merry _mapping_find_enc_map_space(struct mps_softc *sc, 882d043c564SKenneth D. Merry struct enc_mapping_table *et_entry) 883d043c564SKenneth D. Merry { 884d043c564SKenneth D. Merry u16 vol_mapping_flags; 885d043c564SKenneth D. Merry u32 skip_count, end_of_table, map_idx, enc_idx; 886d043c564SKenneth D. Merry u16 num_found; 887d043c564SKenneth D. Merry u32 start_idx = MPS_MAPTABLE_BAD_IDX; 888d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry; 889d043c564SKenneth D. Merry struct enc_mapping_table *enc_entry; 890d043c564SKenneth D. Merry unsigned char done_flag = 0, found_space; 891d043c564SKenneth D. Merry u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs); 892d043c564SKenneth D. Merry 893d043c564SKenneth D. Merry skip_count = sc->num_rsvd_entries; 894d043c564SKenneth D. Merry num_found = 0; 895d043c564SKenneth D. Merry 896d043c564SKenneth D. Merry vol_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) & 897d043c564SKenneth D. Merry MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; 898d043c564SKenneth D. Merry 899635e58c7SStephen McConnell /* 900635e58c7SStephen McConnell * The end of the mapping table depends on where volumes are kept, if 901635e58c7SStephen McConnell * IR is enabled. 902635e58c7SStephen McConnell */ 903d043c564SKenneth D. Merry if (!sc->ir_firmware) 904d043c564SKenneth D. Merry end_of_table = sc->max_devices; 905d043c564SKenneth D. Merry else if (vol_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) 906d043c564SKenneth D. Merry end_of_table = sc->max_devices; 907d043c564SKenneth D. Merry else 908d043c564SKenneth D. Merry end_of_table = sc->max_devices - sc->max_volumes; 909d043c564SKenneth D. Merry 910635e58c7SStephen McConnell /* 911635e58c7SStephen McConnell * The skip_count is the number of entries that are reserved at the 912635e58c7SStephen McConnell * beginning of the mapping table. But, it does not include the number 913635e58c7SStephen McConnell * of Physical IDs that are reserved for direct attached devices. Look 914635e58c7SStephen McConnell * through the mapping table after these reserved entries to see if 915635e58c7SStephen McConnell * the devices for this enclosure are already mapped. The PHY bit check 916635e58c7SStephen McConnell * is used to make sure that at least one PHY bit is common between the 917635e58c7SStephen McConnell * enclosure and the device that is already mapped. 918635e58c7SStephen McConnell */ 919635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Looking for space in the mapping " 920635e58c7SStephen McConnell "table for added enclosure.\n", __func__); 921d043c564SKenneth D. Merry for (map_idx = (max_num_phy_ids + skip_count); 922d043c564SKenneth D. Merry map_idx < end_of_table; map_idx++) { 923d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 924d043c564SKenneth D. Merry if ((et_entry->enclosure_id == mt_entry->physical_id) && 925d043c564SKenneth D. Merry (!mt_entry->phy_bits || (mt_entry->phy_bits & 926d043c564SKenneth D. Merry et_entry->phy_bits))) { 927d043c564SKenneth D. Merry num_found += 1; 928d043c564SKenneth D. Merry if (num_found == et_entry->num_slots) { 929d043c564SKenneth D. Merry start_idx = (map_idx - num_found) + 1; 930635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Found space " 931635e58c7SStephen McConnell "in the mapping for enclosure at map index " 932635e58c7SStephen McConnell "%d.\n", __func__, start_idx); 933d043c564SKenneth D. Merry return start_idx; 934d043c564SKenneth D. Merry } 935d043c564SKenneth D. Merry } else 936d043c564SKenneth D. Merry num_found = 0; 937d043c564SKenneth D. Merry } 938635e58c7SStephen McConnell 939635e58c7SStephen McConnell /* 940635e58c7SStephen McConnell * If the enclosure's devices are not mapped already, look for 941635e58c7SStephen McConnell * contiguous entries in the mapping table that are not reserved. If 942635e58c7SStephen McConnell * enough entries are found, return the starting index for that space. 943635e58c7SStephen McConnell */ 944635e58c7SStephen McConnell num_found = 0; 945d043c564SKenneth D. Merry for (map_idx = (max_num_phy_ids + skip_count); 946d043c564SKenneth D. Merry map_idx < end_of_table; map_idx++) { 947d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 948d043c564SKenneth D. Merry if (!(mt_entry->device_info & MPS_DEV_RESERVED)) { 949d043c564SKenneth D. Merry num_found += 1; 950d043c564SKenneth D. Merry if (num_found == et_entry->num_slots) { 951d043c564SKenneth D. Merry start_idx = (map_idx - num_found) + 1; 952635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Found space " 953635e58c7SStephen McConnell "in the mapping for enclosure at map index " 954635e58c7SStephen McConnell "%d.\n", __func__, start_idx); 955d043c564SKenneth D. Merry return start_idx; 956d043c564SKenneth D. Merry } 957d043c564SKenneth D. Merry } else 958d043c564SKenneth D. Merry num_found = 0; 959d043c564SKenneth D. Merry } 960d043c564SKenneth D. Merry 961635e58c7SStephen McConnell /* 962635e58c7SStephen McConnell * If here, it means that not enough space in the mapping table was 963635e58c7SStephen McConnell * found to support this enclosure, so go through the enclosure table to 964635e58c7SStephen McConnell * see if any enclosure entries have a missing count. If so, get the 965635e58c7SStephen McConnell * enclosure with the highest missing count and check it to see if there 966635e58c7SStephen McConnell * is enough space for the new enclosure. 967635e58c7SStephen McConnell */ 968d043c564SKenneth D. Merry while (!done_flag) { 969d043c564SKenneth D. Merry enc_idx = _mapping_get_high_missing_et_idx(sc); 970635e58c7SStephen McConnell if (enc_idx == MPS_ENCTABLE_BAD_IDX) { 971635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Not enough space was " 972635e58c7SStephen McConnell "found in the mapping for the added enclosure.\n", 973635e58c7SStephen McConnell __func__); 974d043c564SKenneth D. Merry return MPS_MAPTABLE_BAD_IDX; 975635e58c7SStephen McConnell } 976635e58c7SStephen McConnell 977635e58c7SStephen McConnell /* 978635e58c7SStephen McConnell * Found a missing enclosure. Set the skip_search flag so this 979635e58c7SStephen McConnell * enclosure is not checked again for a high missing count if 980635e58c7SStephen McConnell * the loop continues. This way, all missing enclosures can 981635e58c7SStephen McConnell * have their space added together to find enough space in the 982635e58c7SStephen McConnell * mapping table for the added enclosure. The space must be 983635e58c7SStephen McConnell * contiguous. 984635e58c7SStephen McConnell */ 985635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Space from a missing " 986635e58c7SStephen McConnell "enclosure was found.\n", __func__); 987d043c564SKenneth D. Merry enc_entry = &sc->enclosure_table[enc_idx]; 988d043c564SKenneth D. Merry enc_entry->skip_search = 1; 989635e58c7SStephen McConnell 990635e58c7SStephen McConnell /* 991635e58c7SStephen McConnell * Unmark all of the missing enclosure's device's reserved 992635e58c7SStephen McConnell * space. These will be remarked as reserved if this missing 993635e58c7SStephen McConnell * enclosure's space is not used. 994635e58c7SStephen McConnell */ 995635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Clear the reserved flag for " 996635e58c7SStephen McConnell "all of the map entries for the enclosure.\n", __func__); 997d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[enc_entry->start_index]; 998d043c564SKenneth D. Merry for (map_idx = enc_entry->start_index; map_idx < 999d043c564SKenneth D. Merry (enc_entry->start_index + enc_entry->num_slots); map_idx++, 1000d043c564SKenneth D. Merry mt_entry++) 1001d043c564SKenneth D. Merry mt_entry->device_info &= ~MPS_DEV_RESERVED; 1002635e58c7SStephen McConnell 1003635e58c7SStephen McConnell /* 1004635e58c7SStephen McConnell * Now that space has been unreserved, check again to see if 1005635e58c7SStephen McConnell * enough space is available for the new enclosure. 1006635e58c7SStephen McConnell */ 1007635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Check if new mapping space is " 1008635e58c7SStephen McConnell "enough for the new enclosure.\n", __func__); 1009d043c564SKenneth D. Merry found_space = 0; 1010635e58c7SStephen McConnell num_found = 0; 1011635e58c7SStephen McConnell for (map_idx = (max_num_phy_ids + skip_count); 1012635e58c7SStephen McConnell map_idx < end_of_table; map_idx++) { 1013d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 1014d043c564SKenneth D. Merry if (!(mt_entry->device_info & MPS_DEV_RESERVED)) { 1015d043c564SKenneth D. Merry num_found += 1; 1016d043c564SKenneth D. Merry if (num_found == et_entry->num_slots) { 1017d043c564SKenneth D. Merry start_idx = (map_idx - num_found) + 1; 1018d043c564SKenneth D. Merry found_space = 1; 1019635e58c7SStephen McConnell break; 1020d043c564SKenneth D. Merry } 1021d043c564SKenneth D. Merry } else 1022d043c564SKenneth D. Merry num_found = 0; 1023d043c564SKenneth D. Merry } 1024d043c564SKenneth D. Merry if (!found_space) 1025d043c564SKenneth D. Merry continue; 1026635e58c7SStephen McConnell 1027635e58c7SStephen McConnell /* 1028635e58c7SStephen McConnell * If enough space was found, all of the missing enclosures that 1029635e58c7SStephen McConnell * will be used for the new enclosure must be added to the 1030635e58c7SStephen McConnell * removal table. Then all mappings for the enclosure's devices 1031635e58c7SStephen McConnell * and for the enclosure itself need to be cleared. There may be 1032635e58c7SStephen McConnell * more than one enclosure to add to the removal table and 1033635e58c7SStephen McConnell * clear. 1034635e58c7SStephen McConnell */ 1035635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Found space in the mapping " 1036635e58c7SStephen McConnell "for enclosure at map index %d.\n", __func__, start_idx); 1037d043c564SKenneth D. Merry for (map_idx = start_idx; map_idx < (start_idx + num_found); 1038d043c564SKenneth D. Merry map_idx++) { 1039d043c564SKenneth D. Merry enc_entry = sc->enclosure_table; 1040d043c564SKenneth D. Merry for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; 1041d043c564SKenneth D. Merry enc_idx++, enc_entry++) { 1042d043c564SKenneth D. Merry if (map_idx < enc_entry->start_index || 1043d043c564SKenneth D. Merry map_idx > (enc_entry->start_index + 1044d043c564SKenneth D. Merry enc_entry->num_slots)) 1045d043c564SKenneth D. Merry continue; 1046d043c564SKenneth D. Merry if (!enc_entry->removal_flag) { 1047635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: " 1048635e58c7SStephen McConnell "Enclosure %d will be removed from " 1049635e58c7SStephen McConnell "the mapping table.\n", __func__, 1050635e58c7SStephen McConnell enc_idx); 1051d043c564SKenneth D. Merry enc_entry->removal_flag = 1; 1052635e58c7SStephen McConnell _mapping_add_to_removal_table(sc, 1053d043c564SKenneth D. Merry enc_entry->dpm_entry_num); 1054d043c564SKenneth D. Merry } 1055d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 1056d043c564SKenneth D. Merry _mapping_clear_map_entry(mt_entry); 1057d043c564SKenneth D. Merry if (map_idx == (enc_entry->start_index + 1058d043c564SKenneth D. Merry enc_entry->num_slots - 1)) 1059d043c564SKenneth D. Merry _mapping_clear_enc_entry(et_entry); 1060d043c564SKenneth D. Merry } 1061d043c564SKenneth D. Merry } 1062635e58c7SStephen McConnell 1063635e58c7SStephen McConnell /* 1064635e58c7SStephen McConnell * During the search for space for this enclosure, some entries 1065635e58c7SStephen McConnell * in the mapping table may have been unreserved. Go back and 1066635e58c7SStephen McConnell * change all of these to reserved again. Only the enclosures 1067635e58c7SStephen McConnell * with the removal_flag set should be left as unreserved. The 1068635e58c7SStephen McConnell * skip_search flag needs to be cleared as well so that the 1069635e58c7SStephen McConnell * enclosure's space will be looked at the next time space is 1070635e58c7SStephen McConnell * needed. 1071635e58c7SStephen McConnell */ 1072d043c564SKenneth D. Merry enc_entry = sc->enclosure_table; 1073d043c564SKenneth D. Merry for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; 1074d043c564SKenneth D. Merry enc_idx++, enc_entry++) { 1075d043c564SKenneth D. Merry if (!enc_entry->removal_flag) { 1076635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Reset the " 1077635e58c7SStephen McConnell "reserved flag for all of the map entries " 1078635e58c7SStephen McConnell "for enclosure %d.\n", __func__, enc_idx); 1079d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[enc_entry-> 1080d043c564SKenneth D. Merry start_index]; 1081d043c564SKenneth D. Merry for (map_idx = enc_entry->start_index; map_idx < 1082d043c564SKenneth D. Merry (enc_entry->start_index + 1083d043c564SKenneth D. Merry enc_entry->num_slots); map_idx++, 1084d043c564SKenneth D. Merry mt_entry++) 1085d043c564SKenneth D. Merry mt_entry->device_info |= 1086d043c564SKenneth D. Merry MPS_DEV_RESERVED; 1087d043c564SKenneth D. Merry et_entry->skip_search = 0; 1088d043c564SKenneth D. Merry } 1089d043c564SKenneth D. Merry } 1090d043c564SKenneth D. Merry done_flag = 1; 1091d043c564SKenneth D. Merry } 1092d043c564SKenneth D. Merry return start_idx; 1093d043c564SKenneth D. Merry } 1094d043c564SKenneth D. Merry 1095d043c564SKenneth D. Merry /** 1096d043c564SKenneth D. Merry * _mapping_get_dev_info -get information about newly added devices 1097d043c564SKenneth D. Merry * @sc: per adapter object 1098d043c564SKenneth D. Merry * @topo_change: Topology change event entry 1099d043c564SKenneth D. Merry * 1100d043c564SKenneth D. Merry * Search through the topology change event list and issues sas device pg0 1101d043c564SKenneth D. Merry * requests for the newly added device and reserved entries in tables 1102d043c564SKenneth D. Merry * 1103d043c564SKenneth D. Merry * Returns nothing 1104d043c564SKenneth D. Merry */ 1105d043c564SKenneth D. Merry static void 1106d043c564SKenneth D. Merry _mapping_get_dev_info(struct mps_softc *sc, 1107d043c564SKenneth D. Merry struct _map_topology_change *topo_change) 1108d043c564SKenneth D. Merry { 1109d043c564SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1110d043c564SKenneth D. Merry Mpi2ConfigReply_t mpi_reply; 1111d043c564SKenneth D. Merry Mpi2SasDevicePage0_t sas_device_pg0; 1112bfa3cf97SMarcelo Araujo u8 entry, enc_idx, phy_idx; 1113d043c564SKenneth D. Merry u32 map_idx, index, device_info; 1114d043c564SKenneth D. Merry struct _map_phy_change *phy_change, *tmp_phy_change; 1115d043c564SKenneth D. Merry uint64_t sas_address; 1116d043c564SKenneth D. Merry struct enc_mapping_table *et_entry; 1117d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry; 1118d043c564SKenneth D. Merry u8 add_code = MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED; 1119ef065d89SStephen McConnell int rc = 1; 1120d043c564SKenneth D. Merry 1121d043c564SKenneth D. Merry for (entry = 0; entry < topo_change->num_entries; entry++) { 1122d043c564SKenneth D. Merry phy_change = &topo_change->phy_details[entry]; 1123d043c564SKenneth D. Merry if (phy_change->is_processed || !phy_change->dev_handle || 1124d043c564SKenneth D. Merry phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED) 1125d043c564SKenneth D. Merry continue; 1126635e58c7SStephen McConnell 1127d043c564SKenneth D. Merry if (mps_config_get_sas_device_pg0(sc, &mpi_reply, 1128d043c564SKenneth D. Merry &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, 1129d043c564SKenneth D. Merry phy_change->dev_handle)) { 1130d043c564SKenneth D. Merry phy_change->is_processed = 1; 1131d043c564SKenneth D. Merry continue; 1132d043c564SKenneth D. Merry } 1133d043c564SKenneth D. Merry 1134ef065d89SStephen McConnell /* 1135ef065d89SStephen McConnell * Always get SATA Identify information because this is used 1136ef065d89SStephen McConnell * to determine if Start/Stop Unit should be sent to the drive 1137ef065d89SStephen McConnell * when the system is shutdown. 1138ef065d89SStephen McConnell */ 1139d043c564SKenneth D. Merry device_info = le32toh(sas_device_pg0.DeviceInfo); 1140635e58c7SStephen McConnell sas_address = le32toh(sas_device_pg0.SASAddress.High); 1141d043c564SKenneth D. Merry sas_address = (sas_address << 32) | 1142635e58c7SStephen McConnell le32toh(sas_device_pg0.SASAddress.Low); 1143ef065d89SStephen McConnell if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) && 1144ef065d89SStephen McConnell (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) { 1145ef065d89SStephen McConnell rc = mpssas_get_sas_address_for_sata_disk(sc, 1146ef065d89SStephen McConnell &sas_address, phy_change->dev_handle, device_info, 1147ef065d89SStephen McConnell &phy_change->is_SATA_SSD); 1148ef065d89SStephen McConnell if (rc) { 1149ef065d89SStephen McConnell mps_dprint(sc, MPS_ERROR, "%s: failed to get " 1150ef065d89SStephen McConnell "disk type (SSD or HDD) and SAS Address " 1151ef065d89SStephen McConnell "for SATA device with handle 0x%04x\n", 1152ef065d89SStephen McConnell __func__, phy_change->dev_handle); 1153d043c564SKenneth D. Merry } 1154ef065d89SStephen McConnell } 1155ef065d89SStephen McConnell 1156d043c564SKenneth D. Merry phy_change->physical_id = sas_address; 1157d043c564SKenneth D. Merry phy_change->slot = le16toh(sas_device_pg0.Slot); 1158635e58c7SStephen McConnell phy_change->device_info = device_info; 1159d043c564SKenneth D. Merry 1160635e58c7SStephen McConnell /* 1161635e58c7SStephen McConnell * When using Enc/Slot mapping, if this device is an enclosure 1162635e58c7SStephen McConnell * make sure that all of its slots can fit into the mapping 1163635e58c7SStephen McConnell * table. 1164635e58c7SStephen McConnell */ 1165d043c564SKenneth D. Merry if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1166d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 1167635e58c7SStephen McConnell /* 1168635e58c7SStephen McConnell * The enclosure should already be in the enclosure 1169635e58c7SStephen McConnell * table due to the Enclosure Add event. If not, just 1170635e58c7SStephen McConnell * continue, nothing can be done. 1171635e58c7SStephen McConnell */ 1172d043c564SKenneth D. Merry enc_idx = _mapping_get_enc_idx_from_handle(sc, 1173d043c564SKenneth D. Merry topo_change->enc_handle); 1174d043c564SKenneth D. Merry if (enc_idx == MPS_ENCTABLE_BAD_IDX) { 1175d043c564SKenneth D. Merry phy_change->is_processed = 1; 1176635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: " 1177635e58c7SStephen McConnell "failed to add the device with handle " 1178*b99419aeSAlexander Motin "0x%04x because enclosure handle 0x%04x " 1179*b99419aeSAlexander Motin "is not in the mapping table\n", __func__, 1180*b99419aeSAlexander Motin phy_change->dev_handle, 1181*b99419aeSAlexander Motin topo_change->enc_handle); 1182d043c564SKenneth D. Merry continue; 1183d043c564SKenneth D. Merry } 1184d043c564SKenneth D. Merry if (!((phy_change->device_info & 1185d043c564SKenneth D. Merry MPI2_SAS_DEVICE_INFO_END_DEVICE) && 1186d043c564SKenneth D. Merry (phy_change->device_info & 1187d043c564SKenneth D. Merry (MPI2_SAS_DEVICE_INFO_SSP_TARGET | 1188d043c564SKenneth D. Merry MPI2_SAS_DEVICE_INFO_STP_TARGET | 1189d043c564SKenneth D. Merry MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))) { 1190d043c564SKenneth D. Merry phy_change->is_processed = 1; 1191d043c564SKenneth D. Merry continue; 1192d043c564SKenneth D. Merry } 1193d043c564SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx]; 1194635e58c7SStephen McConnell 1195635e58c7SStephen McConnell /* 1196635e58c7SStephen McConnell * If the enclosure already has a start_index, it's been 1197635e58c7SStephen McConnell * mapped, so go to the next Topo change. 1198635e58c7SStephen McConnell */ 1199d043c564SKenneth D. Merry if (et_entry->start_index != MPS_MAPTABLE_BAD_IDX) 1200d043c564SKenneth D. Merry continue; 1201635e58c7SStephen McConnell 1202635e58c7SStephen McConnell /* 1203635e58c7SStephen McConnell * If the Expander Handle is 0, the devices are direct 1204635e58c7SStephen McConnell * attached. In that case, the start_index must be just 1205635e58c7SStephen McConnell * after the reserved entries. Otherwise, find space in 1206635e58c7SStephen McConnell * the mapping table for the enclosure's devices. 1207635e58c7SStephen McConnell */ 1208d043c564SKenneth D. Merry if (!topo_change->exp_handle) { 1209d043c564SKenneth D. Merry map_idx = sc->num_rsvd_entries; 1210d043c564SKenneth D. Merry et_entry->start_index = map_idx; 1211d043c564SKenneth D. Merry } else { 1212d043c564SKenneth D. Merry map_idx = _mapping_find_enc_map_space(sc, 1213d043c564SKenneth D. Merry et_entry); 1214d043c564SKenneth D. Merry et_entry->start_index = map_idx; 1215635e58c7SStephen McConnell 1216635e58c7SStephen McConnell /* 1217635e58c7SStephen McConnell * If space cannot be found to hold all of the 1218635e58c7SStephen McConnell * enclosure's devices in the mapping table, 1219635e58c7SStephen McConnell * there's no need to continue checking the 1220635e58c7SStephen McConnell * other devices in this event. Set all of the 1221635e58c7SStephen McConnell * phy_details for this event (if the change is 1222635e58c7SStephen McConnell * for an add) as already processed because none 1223635e58c7SStephen McConnell * of these devices can be added to the mapping 1224635e58c7SStephen McConnell * table. 1225635e58c7SStephen McConnell */ 1226d043c564SKenneth D. Merry if (et_entry->start_index == 1227d043c564SKenneth D. Merry MPS_MAPTABLE_BAD_IDX) { 1228635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, 1229635e58c7SStephen McConnell "%s: failed to add the enclosure " 1230635e58c7SStephen McConnell "with ID 0x%016jx because there is " 1231635e58c7SStephen McConnell "no free space available in the " 1232635e58c7SStephen McConnell "mapping table for all of the " 1233635e58c7SStephen McConnell "enclosure's devices.\n", __func__, 1234635e58c7SStephen McConnell (uintmax_t)et_entry->enclosure_id); 1235d043c564SKenneth D. Merry phy_change->is_processed = 1; 1236d043c564SKenneth D. Merry for (phy_idx = 0; phy_idx < 1237d043c564SKenneth D. Merry topo_change->num_entries; 1238d043c564SKenneth D. Merry phy_idx++) { 1239d043c564SKenneth D. Merry tmp_phy_change = 1240d043c564SKenneth D. Merry &topo_change->phy_details 1241d043c564SKenneth D. Merry [phy_idx]; 1242d043c564SKenneth D. Merry if (tmp_phy_change->reason == 1243d043c564SKenneth D. Merry add_code) 1244d043c564SKenneth D. Merry tmp_phy_change-> 1245d043c564SKenneth D. Merry is_processed = 1; 1246d043c564SKenneth D. Merry } 1247d043c564SKenneth D. Merry break; 1248d043c564SKenneth D. Merry } 1249d043c564SKenneth D. Merry } 1250635e58c7SStephen McConnell 1251635e58c7SStephen McConnell /* 1252635e58c7SStephen McConnell * Found space in the mapping table for this enclosure. 1253635e58c7SStephen McConnell * Initialize each mapping table entry for the 1254635e58c7SStephen McConnell * enclosure. 1255635e58c7SStephen McConnell */ 1256635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Initialize %d map " 1257635e58c7SStephen McConnell "entries for the enclosure, starting at map index " 1258635e58c7SStephen McConnell " %d.\n", __func__, et_entry->num_slots, map_idx); 1259d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 1260d043c564SKenneth D. Merry for (index = map_idx; index < (et_entry->num_slots 1261d043c564SKenneth D. Merry + map_idx); index++, mt_entry++) { 1262d043c564SKenneth D. Merry mt_entry->device_info = MPS_DEV_RESERVED; 1263d043c564SKenneth D. Merry mt_entry->physical_id = et_entry->enclosure_id; 1264d043c564SKenneth D. Merry mt_entry->phy_bits = et_entry->phy_bits; 1265635e58c7SStephen McConnell mt_entry->missing_count = 0; 1266d043c564SKenneth D. Merry } 1267d043c564SKenneth D. Merry } 1268d043c564SKenneth D. Merry } 1269d043c564SKenneth D. Merry } 1270d043c564SKenneth D. Merry 1271d043c564SKenneth D. Merry /** 1272d043c564SKenneth D. Merry * _mapping_set_mid_to_eid -set map table data from enclosure table 1273d043c564SKenneth D. Merry * @sc: per adapter object 1274d043c564SKenneth D. Merry * @et_entry: enclosure entry 1275d043c564SKenneth D. Merry * 1276d043c564SKenneth D. Merry * Returns nothing 1277d043c564SKenneth D. Merry */ 1278d043c564SKenneth D. Merry static inline void 1279d043c564SKenneth D. Merry _mapping_set_mid_to_eid(struct mps_softc *sc, 1280d043c564SKenneth D. Merry struct enc_mapping_table *et_entry) 1281d043c564SKenneth D. Merry { 1282d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry; 1283d043c564SKenneth D. Merry u16 slots = et_entry->num_slots, map_idx; 1284d043c564SKenneth D. Merry u32 start_idx = et_entry->start_index; 1285635e58c7SStephen McConnell 1286d043c564SKenneth D. Merry if (start_idx != MPS_MAPTABLE_BAD_IDX) { 1287d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[start_idx]; 1288d043c564SKenneth D. Merry for (map_idx = 0; map_idx < slots; map_idx++, mt_entry++) 1289d043c564SKenneth D. Merry mt_entry->physical_id = et_entry->enclosure_id; 1290d043c564SKenneth D. Merry } 1291d043c564SKenneth D. Merry } 1292d043c564SKenneth D. Merry 1293d043c564SKenneth D. Merry /** 1294d043c564SKenneth D. Merry * _mapping_clear_removed_entries - mark the entries to be cleared 1295d043c564SKenneth D. Merry * @sc: per adapter object 1296d043c564SKenneth D. Merry * 1297d043c564SKenneth D. Merry * Search through the removal table and mark the entries which needs to be 1298d043c564SKenneth D. Merry * flushed to DPM and also updates the map table and enclosure table by 1299d043c564SKenneth D. Merry * clearing the corresponding entries. 1300d043c564SKenneth D. Merry * 1301d043c564SKenneth D. Merry * Returns nothing 1302d043c564SKenneth D. Merry */ 1303d043c564SKenneth D. Merry static void 1304d043c564SKenneth D. Merry _mapping_clear_removed_entries(struct mps_softc *sc) 1305d043c564SKenneth D. Merry { 1306d043c564SKenneth D. Merry u32 remove_idx; 1307d043c564SKenneth D. Merry struct map_removal_table *remove_entry; 1308d043c564SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry; 1309d043c564SKenneth D. Merry u8 done_flag = 0, num_entries, m, i; 1310d043c564SKenneth D. Merry struct enc_mapping_table *et_entry, *from, *to; 1311d043c564SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1312d043c564SKenneth D. Merry 1313d043c564SKenneth D. Merry if (sc->is_dpm_enable) { 1314d043c564SKenneth D. Merry remove_entry = sc->removal_table; 1315d043c564SKenneth D. Merry for (remove_idx = 0; remove_idx < sc->max_devices; 1316d043c564SKenneth D. Merry remove_idx++, remove_entry++) { 1317d043c564SKenneth D. Merry if (remove_entry->dpm_entry_num != MPS_DPM_BAD_IDX) { 1318d043c564SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *) 1319d043c564SKenneth D. Merry ((u8 *) sc->dpm_pg0 + 1320d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 1321d043c564SKenneth D. Merry dpm_entry += remove_entry->dpm_entry_num; 1322d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low = 0; 1323d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.High = 0; 1324d043c564SKenneth D. Merry dpm_entry->DeviceIndex = 0; 1325d043c564SKenneth D. Merry dpm_entry->MappingInformation = 0; 1326d043c564SKenneth D. Merry dpm_entry->PhysicalBitsMapping = 0; 1327d043c564SKenneth D. Merry sc->dpm_flush_entry[remove_entry-> 1328d043c564SKenneth D. Merry dpm_entry_num] = 1; 1329d043c564SKenneth D. Merry sc->dpm_entry_used[remove_entry->dpm_entry_num] 1330d043c564SKenneth D. Merry = 0; 1331d043c564SKenneth D. Merry remove_entry->dpm_entry_num = MPS_DPM_BAD_IDX; 1332d043c564SKenneth D. Merry } 1333d043c564SKenneth D. Merry } 1334d043c564SKenneth D. Merry } 1335635e58c7SStephen McConnell 1336635e58c7SStephen McConnell /* 1337635e58c7SStephen McConnell * When using Enc/Slot mapping, if a new enclosure was added and old 1338635e58c7SStephen McConnell * enclosure space was needed, the enclosure table may now have gaps 1339635e58c7SStephen McConnell * that need to be closed. All enclosure mappings need to be contiguous 1340635e58c7SStephen McConnell * so that space can be reused correctly if available. 1341635e58c7SStephen McConnell */ 1342d043c564SKenneth D. Merry if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1343d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 1344d043c564SKenneth D. Merry num_entries = sc->num_enc_table_entries; 1345d043c564SKenneth D. Merry while (!done_flag) { 1346d043c564SKenneth D. Merry done_flag = 1; 1347d043c564SKenneth D. Merry et_entry = sc->enclosure_table; 1348d043c564SKenneth D. Merry for (i = 0; i < num_entries; i++, et_entry++) { 1349d043c564SKenneth D. Merry if (!et_entry->enc_handle && et_entry-> 1350d043c564SKenneth D. Merry init_complete) { 1351d043c564SKenneth D. Merry done_flag = 0; 1352d043c564SKenneth D. Merry if (i != (num_entries - 1)) { 1353d043c564SKenneth D. Merry from = &sc->enclosure_table 1354d043c564SKenneth D. Merry [i+1]; 1355d043c564SKenneth D. Merry to = &sc->enclosure_table[i]; 1356d043c564SKenneth D. Merry for (m = i; m < (num_entries - 1357d043c564SKenneth D. Merry 1); m++, from++, to++) { 1358d043c564SKenneth D. Merry _mapping_set_mid_to_eid 1359d043c564SKenneth D. Merry (sc, to); 1360d043c564SKenneth D. Merry *to = *from; 1361d043c564SKenneth D. Merry } 1362d043c564SKenneth D. Merry _mapping_clear_enc_entry(to); 1363d043c564SKenneth D. Merry sc->num_enc_table_entries--; 1364d043c564SKenneth D. Merry num_entries = 1365d043c564SKenneth D. Merry sc->num_enc_table_entries; 1366d043c564SKenneth D. Merry } else { 1367d043c564SKenneth D. Merry _mapping_clear_enc_entry 1368d043c564SKenneth D. Merry (et_entry); 1369d043c564SKenneth D. Merry sc->num_enc_table_entries--; 1370d043c564SKenneth D. Merry num_entries = 1371d043c564SKenneth D. Merry sc->num_enc_table_entries; 1372d043c564SKenneth D. Merry } 1373d043c564SKenneth D. Merry } 1374d043c564SKenneth D. Merry } 1375d043c564SKenneth D. Merry } 1376d043c564SKenneth D. Merry } 1377d043c564SKenneth D. Merry } 1378d043c564SKenneth D. Merry 1379d043c564SKenneth D. Merry /** 1380d043c564SKenneth D. Merry * _mapping_add_new_device -Add the new device into mapping table 1381d043c564SKenneth D. Merry * @sc: per adapter object 1382d043c564SKenneth D. Merry * @topo_change: Topology change event entry 1383d043c564SKenneth D. Merry * 1384635e58c7SStephen McConnell * Search through the topology change event list and update map table, 1385635e58c7SStephen McConnell * enclosure table and DPM pages for the newly added devices. 1386d043c564SKenneth D. Merry * 1387d043c564SKenneth D. Merry * Returns nothing 1388d043c564SKenneth D. Merry */ 1389d043c564SKenneth D. Merry static void 1390d043c564SKenneth D. Merry _mapping_add_new_device(struct mps_softc *sc, 1391d043c564SKenneth D. Merry struct _map_topology_change *topo_change) 1392d043c564SKenneth D. Merry { 1393d043c564SKenneth D. Merry u8 enc_idx, missing_cnt, is_removed = 0; 1394d043c564SKenneth D. Merry u16 dpm_idx; 1395d043c564SKenneth D. Merry u32 search_idx, map_idx; 1396d043c564SKenneth D. Merry u32 entry; 1397d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry; 1398d043c564SKenneth D. Merry struct enc_mapping_table *et_entry; 1399d043c564SKenneth D. Merry struct _map_phy_change *phy_change; 1400d043c564SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1401d043c564SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry; 1402d043c564SKenneth D. Merry uint64_t temp64_var; 1403d043c564SKenneth D. Merry u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT; 1404d043c564SKenneth D. Merry u8 hdr_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER); 1405d043c564SKenneth D. Merry u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs); 1406d043c564SKenneth D. Merry 1407d043c564SKenneth D. Merry for (entry = 0; entry < topo_change->num_entries; entry++) { 1408d043c564SKenneth D. Merry phy_change = &topo_change->phy_details[entry]; 1409d043c564SKenneth D. Merry if (phy_change->is_processed) 1410d043c564SKenneth D. Merry continue; 1411d043c564SKenneth D. Merry if (phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED || 1412d043c564SKenneth D. Merry !phy_change->dev_handle) { 1413d043c564SKenneth D. Merry phy_change->is_processed = 1; 1414d043c564SKenneth D. Merry continue; 1415d043c564SKenneth D. Merry } 1416d043c564SKenneth D. Merry if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1417d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 1418d043c564SKenneth D. Merry enc_idx = _mapping_get_enc_idx_from_handle 1419d043c564SKenneth D. Merry (sc, topo_change->enc_handle); 1420d043c564SKenneth D. Merry if (enc_idx == MPS_ENCTABLE_BAD_IDX) { 1421d043c564SKenneth D. Merry phy_change->is_processed = 1; 1422635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: " 1423635e58c7SStephen McConnell "failed to add the device with handle " 1424*b99419aeSAlexander Motin "0x%04x because enclosure handle 0x%04x " 1425*b99419aeSAlexander Motin "is not in the mapping table\n", __func__, 1426*b99419aeSAlexander Motin phy_change->dev_handle, 1427*b99419aeSAlexander Motin topo_change->enc_handle); 1428d043c564SKenneth D. Merry continue; 1429d043c564SKenneth D. Merry } 1430635e58c7SStephen McConnell 1431635e58c7SStephen McConnell /* 1432635e58c7SStephen McConnell * If the enclosure's start_index is BAD here, it means 1433635e58c7SStephen McConnell * that there is no room in the mapping table to cover 1434635e58c7SStephen McConnell * all of the devices that could be in the enclosure. 1435635e58c7SStephen McConnell * There's no reason to process any of the devices for 1436635e58c7SStephen McConnell * this enclosure since they can't be mapped. 1437635e58c7SStephen McConnell */ 1438d043c564SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx]; 1439d043c564SKenneth D. Merry if (et_entry->start_index == MPS_MAPTABLE_BAD_IDX) { 1440d043c564SKenneth D. Merry phy_change->is_processed = 1; 1441635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: " 1442635e58c7SStephen McConnell "failed to add the device with handle " 1443635e58c7SStephen McConnell "0x%04x because there is no free space " 1444635e58c7SStephen McConnell "available in the mapping table\n", 1445d043c564SKenneth D. Merry __func__, phy_change->dev_handle); 1446d043c564SKenneth D. Merry continue; 1447d043c564SKenneth D. Merry } 1448635e58c7SStephen McConnell 1449635e58c7SStephen McConnell /* 1450635e58c7SStephen McConnell * Add this device to the mapping table at the correct 1451635e58c7SStephen McConnell * offset where space was found to map the enclosure. 1452635e58c7SStephen McConnell * Then setup the DPM entry information if being used. 1453635e58c7SStephen McConnell */ 1454d043c564SKenneth D. Merry map_idx = et_entry->start_index + phy_change->slot - 1455d043c564SKenneth D. Merry et_entry->start_slot; 1456d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 1457d043c564SKenneth D. Merry mt_entry->physical_id = phy_change->physical_id; 1458d043c564SKenneth D. Merry mt_entry->id = map_idx; 1459d043c564SKenneth D. Merry mt_entry->dev_handle = phy_change->dev_handle; 1460d043c564SKenneth D. Merry mt_entry->missing_count = 0; 1461d043c564SKenneth D. Merry mt_entry->dpm_entry_num = et_entry->dpm_entry_num; 1462d043c564SKenneth D. Merry mt_entry->device_info = phy_change->device_info | 1463d043c564SKenneth D. Merry (MPS_DEV_RESERVED | MPS_MAP_IN_USE); 1464d043c564SKenneth D. Merry if (sc->is_dpm_enable) { 1465d043c564SKenneth D. Merry dpm_idx = et_entry->dpm_entry_num; 1466d043c564SKenneth D. Merry if (dpm_idx == MPS_DPM_BAD_IDX) 1467d043c564SKenneth D. Merry dpm_idx = _mapping_get_dpm_idx_from_id 1468d043c564SKenneth D. Merry (sc, et_entry->enclosure_id, 1469d043c564SKenneth D. Merry et_entry->phy_bits); 1470d043c564SKenneth D. Merry if (dpm_idx == MPS_DPM_BAD_IDX) { 1471d043c564SKenneth D. Merry dpm_idx = _mapping_get_free_dpm_idx(sc); 1472d043c564SKenneth D. Merry if (dpm_idx != MPS_DPM_BAD_IDX) { 1473d043c564SKenneth D. Merry dpm_entry = 1474d043c564SKenneth D. Merry (Mpi2DriverMap0Entry_t *) 1475d043c564SKenneth D. Merry ((u8 *) sc->dpm_pg0 + 1476d043c564SKenneth D. Merry hdr_sz); 1477d043c564SKenneth D. Merry dpm_entry += dpm_idx; 1478d043c564SKenneth D. Merry dpm_entry-> 1479d043c564SKenneth D. Merry PhysicalIdentifier.Low = 1480d043c564SKenneth D. Merry (0xFFFFFFFF & 1481d043c564SKenneth D. Merry et_entry->enclosure_id); 1482d043c564SKenneth D. Merry dpm_entry-> 1483d043c564SKenneth D. Merry PhysicalIdentifier.High = 1484d043c564SKenneth D. Merry (et_entry->enclosure_id 1485d043c564SKenneth D. Merry >> 32); 1486d043c564SKenneth D. Merry dpm_entry->DeviceIndex = 1487d043c564SKenneth D. Merry (U16)et_entry->start_index; 1488d043c564SKenneth D. Merry dpm_entry->MappingInformation = 1489d043c564SKenneth D. Merry et_entry->num_slots; 1490d043c564SKenneth D. Merry dpm_entry->MappingInformation 1491d043c564SKenneth D. Merry <<= map_shift; 1492d043c564SKenneth D. Merry dpm_entry->PhysicalBitsMapping 1493d043c564SKenneth D. Merry = et_entry->phy_bits; 1494d043c564SKenneth D. Merry et_entry->dpm_entry_num = 1495d043c564SKenneth D. Merry dpm_idx; 1496d043c564SKenneth D. Merry sc->dpm_entry_used[dpm_idx] = 1; 1497d043c564SKenneth D. Merry sc->dpm_flush_entry[dpm_idx] = 1498d043c564SKenneth D. Merry 1; 1499d043c564SKenneth D. Merry phy_change->is_processed = 1; 1500d043c564SKenneth D. Merry } else { 1501d043c564SKenneth D. Merry phy_change->is_processed = 1; 1502635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | 1503635e58c7SStephen McConnell MPS_MAPPING, "%s: failed " 1504635e58c7SStephen McConnell "to add the device with " 1505635e58c7SStephen McConnell "handle 0x%04x to " 15069b91b192SKenneth D. Merry "persistent table because " 15079b91b192SKenneth D. Merry "there is no free space " 15089b91b192SKenneth D. Merry "available\n", __func__, 1509d043c564SKenneth D. Merry phy_change->dev_handle); 1510d043c564SKenneth D. Merry } 1511d043c564SKenneth D. Merry } else { 1512d043c564SKenneth D. Merry et_entry->dpm_entry_num = dpm_idx; 1513d043c564SKenneth D. Merry mt_entry->dpm_entry_num = dpm_idx; 1514d043c564SKenneth D. Merry } 1515d043c564SKenneth D. Merry } 1516d043c564SKenneth D. Merry et_entry->init_complete = 1; 1517d043c564SKenneth D. Merry } else if ((ioc_pg8_flags & 1518d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1519d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { 1520635e58c7SStephen McConnell /* 1521635e58c7SStephen McConnell * Get the mapping table index for this device. If it's 1522635e58c7SStephen McConnell * not in the mapping table yet, find a free entry if 1523635e58c7SStephen McConnell * one is available. If there are no free entries, look 1524635e58c7SStephen McConnell * for the entry that has the highest missing count. If 1525635e58c7SStephen McConnell * none of that works to find an entry in the mapping 1526635e58c7SStephen McConnell * table, there is a problem. Log a message and just 1527635e58c7SStephen McConnell * continue on. 1528635e58c7SStephen McConnell */ 1529d043c564SKenneth D. Merry map_idx = _mapping_get_mt_idx_from_id 1530d043c564SKenneth D. Merry (sc, phy_change->physical_id); 1531d043c564SKenneth D. Merry if (map_idx == MPS_MAPTABLE_BAD_IDX) { 1532d043c564SKenneth D. Merry search_idx = sc->num_rsvd_entries; 1533d043c564SKenneth D. Merry if (topo_change->exp_handle) 1534d043c564SKenneth D. Merry search_idx += max_num_phy_ids; 1535d043c564SKenneth D. Merry map_idx = _mapping_get_free_mt_idx(sc, 1536d043c564SKenneth D. Merry search_idx); 1537d043c564SKenneth D. Merry } 1538635e58c7SStephen McConnell 1539635e58c7SStephen McConnell /* 1540635e58c7SStephen McConnell * If an entry will be used that has a missing device, 1541635e58c7SStephen McConnell * clear its entry from the DPM in the controller. 1542635e58c7SStephen McConnell */ 1543d043c564SKenneth D. Merry if (map_idx == MPS_MAPTABLE_BAD_IDX) { 1544d043c564SKenneth D. Merry map_idx = _mapping_get_high_missing_mt_idx(sc); 1545d043c564SKenneth D. Merry if (map_idx != MPS_MAPTABLE_BAD_IDX) { 1546d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 1547635e58c7SStephen McConnell _mapping_add_to_removal_table(sc, 1548635e58c7SStephen McConnell mt_entry->dpm_entry_num); 1549d043c564SKenneth D. Merry is_removed = 1; 1550d043c564SKenneth D. Merry mt_entry->init_complete = 0; 1551d043c564SKenneth D. Merry } 1552d043c564SKenneth D. Merry } 1553d043c564SKenneth D. Merry if (map_idx != MPS_MAPTABLE_BAD_IDX) { 1554d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 1555d043c564SKenneth D. Merry mt_entry->physical_id = phy_change->physical_id; 1556d043c564SKenneth D. Merry mt_entry->id = map_idx; 1557d043c564SKenneth D. Merry mt_entry->dev_handle = phy_change->dev_handle; 1558d043c564SKenneth D. Merry mt_entry->missing_count = 0; 1559d043c564SKenneth D. Merry mt_entry->device_info = phy_change->device_info 1560d043c564SKenneth D. Merry | (MPS_DEV_RESERVED | MPS_MAP_IN_USE); 1561d043c564SKenneth D. Merry } else { 1562d043c564SKenneth D. Merry phy_change->is_processed = 1; 1563635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: " 1564635e58c7SStephen McConnell "failed to add the device with handle " 1565635e58c7SStephen McConnell "0x%04x because there is no free space " 1566635e58c7SStephen McConnell "available in the mapping table\n", 1567d043c564SKenneth D. Merry __func__, phy_change->dev_handle); 1568d043c564SKenneth D. Merry continue; 1569d043c564SKenneth D. Merry } 1570d043c564SKenneth D. Merry if (sc->is_dpm_enable) { 1571d043c564SKenneth D. Merry if (mt_entry->dpm_entry_num != 1572d043c564SKenneth D. Merry MPS_DPM_BAD_IDX) { 1573d043c564SKenneth D. Merry dpm_idx = mt_entry->dpm_entry_num; 1574d043c564SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *) 1575d043c564SKenneth D. Merry ((u8 *)sc->dpm_pg0 + hdr_sz); 1576d043c564SKenneth D. Merry dpm_entry += dpm_idx; 1577d043c564SKenneth D. Merry missing_cnt = dpm_entry-> 1578d043c564SKenneth D. Merry MappingInformation & 1579d043c564SKenneth D. Merry MPI2_DRVMAP0_MAPINFO_MISSING_MASK; 1580d043c564SKenneth D. Merry temp64_var = dpm_entry-> 1581d043c564SKenneth D. Merry PhysicalIdentifier.High; 1582d043c564SKenneth D. Merry temp64_var = (temp64_var << 32) | 1583d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low; 1584635e58c7SStephen McConnell 1585635e58c7SStephen McConnell /* 1586635e58c7SStephen McConnell * If the Mapping Table's info is not 1587635e58c7SStephen McConnell * the same as the DPM entry, clear the 1588635e58c7SStephen McConnell * init_complete flag so that it's 1589635e58c7SStephen McConnell * updated. 1590635e58c7SStephen McConnell */ 1591d043c564SKenneth D. Merry if ((mt_entry->physical_id == 1592d043c564SKenneth D. Merry temp64_var) && !missing_cnt) 1593d043c564SKenneth D. Merry mt_entry->init_complete = 1; 1594635e58c7SStephen McConnell else 1595635e58c7SStephen McConnell mt_entry->init_complete = 0; 1596d043c564SKenneth D. Merry } else { 1597d043c564SKenneth D. Merry dpm_idx = _mapping_get_free_dpm_idx(sc); 1598d043c564SKenneth D. Merry mt_entry->init_complete = 0; 1599d043c564SKenneth D. Merry } 1600d043c564SKenneth D. Merry if (dpm_idx != MPS_DPM_BAD_IDX && 1601d043c564SKenneth D. Merry !mt_entry->init_complete) { 1602d043c564SKenneth D. Merry mt_entry->dpm_entry_num = dpm_idx; 1603d043c564SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *) 1604d043c564SKenneth D. Merry ((u8 *)sc->dpm_pg0 + hdr_sz); 1605d043c564SKenneth D. Merry dpm_entry += dpm_idx; 1606d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low = 1607d043c564SKenneth D. Merry (0xFFFFFFFF & 1608d043c564SKenneth D. Merry mt_entry->physical_id); 1609d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.High = 1610d043c564SKenneth D. Merry (mt_entry->physical_id >> 32); 1611d043c564SKenneth D. Merry dpm_entry->DeviceIndex = (U16) map_idx; 1612d043c564SKenneth D. Merry dpm_entry->MappingInformation = 0; 1613d043c564SKenneth D. Merry dpm_entry->PhysicalBitsMapping = 0; 1614d043c564SKenneth D. Merry sc->dpm_entry_used[dpm_idx] = 1; 1615d043c564SKenneth D. Merry sc->dpm_flush_entry[dpm_idx] = 1; 1616d043c564SKenneth D. Merry phy_change->is_processed = 1; 1617d043c564SKenneth D. Merry } else if (dpm_idx == MPS_DPM_BAD_IDX) { 1618d043c564SKenneth D. Merry phy_change->is_processed = 1; 1619635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, 1620635e58c7SStephen McConnell "%s: failed to add the device with " 1621635e58c7SStephen McConnell "handle 0x%04x to persistent table " 1622635e58c7SStephen McConnell "because there is no free space " 16239b91b192SKenneth D. Merry "available\n", __func__, 1624d043c564SKenneth D. Merry phy_change->dev_handle); 1625d043c564SKenneth D. Merry } 1626d043c564SKenneth D. Merry } 1627d043c564SKenneth D. Merry mt_entry->init_complete = 1; 1628d043c564SKenneth D. Merry } 1629d043c564SKenneth D. Merry 1630d043c564SKenneth D. Merry phy_change->is_processed = 1; 1631d043c564SKenneth D. Merry } 1632d043c564SKenneth D. Merry if (is_removed) 1633d043c564SKenneth D. Merry _mapping_clear_removed_entries(sc); 1634d043c564SKenneth D. Merry } 1635d043c564SKenneth D. Merry 1636d043c564SKenneth D. Merry /** 1637d043c564SKenneth D. Merry * _mapping_flush_dpm_pages -Flush the DPM pages to NVRAM 1638d043c564SKenneth D. Merry * @sc: per adapter object 1639d043c564SKenneth D. Merry * 1640d043c564SKenneth D. Merry * Returns nothing 1641d043c564SKenneth D. Merry */ 1642d043c564SKenneth D. Merry static void 1643d043c564SKenneth D. Merry _mapping_flush_dpm_pages(struct mps_softc *sc) 1644d043c564SKenneth D. Merry { 1645d043c564SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry; 1646d043c564SKenneth D. Merry Mpi2ConfigReply_t mpi_reply; 1647d043c564SKenneth D. Merry Mpi2DriverMappingPage0_t config_page; 1648d043c564SKenneth D. Merry u16 entry_num; 1649d043c564SKenneth D. Merry 1650d043c564SKenneth D. Merry for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) { 1651d043c564SKenneth D. Merry if (!sc->dpm_flush_entry[entry_num]) 1652d043c564SKenneth D. Merry continue; 1653d043c564SKenneth D. Merry memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t)); 1654d043c564SKenneth D. Merry memcpy(&config_page.Header, (u8 *)sc->dpm_pg0, 1655d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 1656d043c564SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 + 1657d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 1658d043c564SKenneth D. Merry dpm_entry += entry_num; 1659d043c564SKenneth D. Merry dpm_entry->MappingInformation = htole16(dpm_entry-> 1660d043c564SKenneth D. Merry MappingInformation); 1661d043c564SKenneth D. Merry dpm_entry->DeviceIndex = htole16(dpm_entry->DeviceIndex); 1662d043c564SKenneth D. Merry dpm_entry->PhysicalBitsMapping = htole32(dpm_entry-> 1663d043c564SKenneth D. Merry PhysicalBitsMapping); 1664d043c564SKenneth D. Merry memcpy(&config_page.Entry, (u8 *)dpm_entry, 1665d043c564SKenneth D. Merry sizeof(Mpi2DriverMap0Entry_t)); 1666d043c564SKenneth D. Merry /* TODO-How to handle failed writes? */ 1667635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Flushing DPM entry %d.\n", 1668635e58c7SStephen McConnell __func__, entry_num); 1669d043c564SKenneth D. Merry if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page, 1670d043c564SKenneth D. Merry entry_num)) { 1671635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Flush of " 1672635e58c7SStephen McConnell "DPM entry %d for device failed\n", __func__, 1673635e58c7SStephen McConnell entry_num); 1674d043c564SKenneth D. Merry } else 1675d043c564SKenneth D. Merry sc->dpm_flush_entry[entry_num] = 0; 1676d043c564SKenneth D. Merry dpm_entry->MappingInformation = le16toh(dpm_entry-> 1677d043c564SKenneth D. Merry MappingInformation); 1678d043c564SKenneth D. Merry dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex); 1679d043c564SKenneth D. Merry dpm_entry->PhysicalBitsMapping = le32toh(dpm_entry-> 1680d043c564SKenneth D. Merry PhysicalBitsMapping); 1681d043c564SKenneth D. Merry } 1682d043c564SKenneth D. Merry } 1683d043c564SKenneth D. Merry 1684d043c564SKenneth D. Merry /** 1685d043c564SKenneth D. Merry * _mapping_allocate_memory- allocates the memory required for mapping tables 1686d043c564SKenneth D. Merry * @sc: per adapter object 1687d043c564SKenneth D. Merry * 1688d043c564SKenneth D. Merry * Allocates the memory for all the tables required for host mapping 1689d043c564SKenneth D. Merry * 1690d043c564SKenneth D. Merry * Return 0 on success or non-zero on failure. 1691d043c564SKenneth D. Merry */ 1692d043c564SKenneth D. Merry int 1693d043c564SKenneth D. Merry mps_mapping_allocate_memory(struct mps_softc *sc) 1694d043c564SKenneth D. Merry { 1695d043c564SKenneth D. Merry uint32_t dpm_pg0_sz; 1696d043c564SKenneth D. Merry 1697ac2fffa4SPedro F. Giffuni sc->mapping_table = malloc((sizeof(struct dev_mapping_table) * 1698ac2fffa4SPedro F. Giffuni sc->max_devices), M_MPT2, M_ZERO|M_NOWAIT); 1699d043c564SKenneth D. Merry if (!sc->mapping_table) 1700d043c564SKenneth D. Merry goto free_resources; 1701d043c564SKenneth D. Merry 1702ac2fffa4SPedro F. Giffuni sc->removal_table = malloc((sizeof(struct map_removal_table) * 1703ac2fffa4SPedro F. Giffuni sc->max_devices), M_MPT2, M_ZERO|M_NOWAIT); 1704d043c564SKenneth D. Merry if (!sc->removal_table) 1705d043c564SKenneth D. Merry goto free_resources; 1706d043c564SKenneth D. Merry 1707ac2fffa4SPedro F. Giffuni sc->enclosure_table = malloc((sizeof(struct enc_mapping_table) * 1708ac2fffa4SPedro F. Giffuni sc->max_enclosures), M_MPT2, M_ZERO|M_NOWAIT); 1709d043c564SKenneth D. Merry if (!sc->enclosure_table) 1710d043c564SKenneth D. Merry goto free_resources; 1711d043c564SKenneth D. Merry 1712ac2fffa4SPedro F. Giffuni sc->dpm_entry_used = malloc((sizeof(u8) * sc->max_dpm_entries), 1713d043c564SKenneth D. Merry M_MPT2, M_ZERO|M_NOWAIT); 1714d043c564SKenneth D. Merry if (!sc->dpm_entry_used) 1715d043c564SKenneth D. Merry goto free_resources; 1716d043c564SKenneth D. Merry 1717ac2fffa4SPedro F. Giffuni sc->dpm_flush_entry = malloc((sizeof(u8) * sc->max_dpm_entries), 1718d043c564SKenneth D. Merry M_MPT2, M_ZERO|M_NOWAIT); 1719d043c564SKenneth D. Merry if (!sc->dpm_flush_entry) 1720d043c564SKenneth D. Merry goto free_resources; 1721d043c564SKenneth D. Merry 1722d043c564SKenneth D. Merry dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) + 1723d043c564SKenneth D. Merry (sc->max_dpm_entries * sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY)); 1724d043c564SKenneth D. Merry 1725d043c564SKenneth D. Merry sc->dpm_pg0 = malloc(dpm_pg0_sz, M_MPT2, M_ZERO|M_NOWAIT); 1726d043c564SKenneth D. Merry if (!sc->dpm_pg0) { 1727d043c564SKenneth D. Merry printf("%s: memory alloc failed for dpm page; disabling dpm\n", 1728d043c564SKenneth D. Merry __func__); 1729d043c564SKenneth D. Merry sc->is_dpm_enable = 0; 1730d043c564SKenneth D. Merry } 1731d043c564SKenneth D. Merry 1732d043c564SKenneth D. Merry return 0; 1733d043c564SKenneth D. Merry 1734d043c564SKenneth D. Merry free_resources: 1735d043c564SKenneth D. Merry free(sc->mapping_table, M_MPT2); 1736d043c564SKenneth D. Merry free(sc->removal_table, M_MPT2); 1737d043c564SKenneth D. Merry free(sc->enclosure_table, M_MPT2); 1738d043c564SKenneth D. Merry free(sc->dpm_entry_used, M_MPT2); 1739d043c564SKenneth D. Merry free(sc->dpm_flush_entry, M_MPT2); 1740d043c564SKenneth D. Merry free(sc->dpm_pg0, M_MPT2); 1741d043c564SKenneth D. Merry printf("%s: device initialization failed due to failure in mapping " 1742d043c564SKenneth D. Merry "table memory allocation\n", __func__); 1743d043c564SKenneth D. Merry return -1; 1744d043c564SKenneth D. Merry } 1745d043c564SKenneth D. Merry 1746d043c564SKenneth D. Merry /** 1747d043c564SKenneth D. Merry * mps_mapping_free_memory- frees the memory allocated for mapping tables 1748d043c564SKenneth D. Merry * @sc: per adapter object 1749d043c564SKenneth D. Merry * 1750d043c564SKenneth D. Merry * Returns nothing. 1751d043c564SKenneth D. Merry */ 1752d043c564SKenneth D. Merry void 1753d043c564SKenneth D. Merry mps_mapping_free_memory(struct mps_softc *sc) 1754d043c564SKenneth D. Merry { 1755d043c564SKenneth D. Merry free(sc->mapping_table, M_MPT2); 1756d043c564SKenneth D. Merry free(sc->removal_table, M_MPT2); 1757d043c564SKenneth D. Merry free(sc->enclosure_table, M_MPT2); 1758d043c564SKenneth D. Merry free(sc->dpm_entry_used, M_MPT2); 1759d043c564SKenneth D. Merry free(sc->dpm_flush_entry, M_MPT2); 1760d043c564SKenneth D. Merry free(sc->dpm_pg0, M_MPT2); 1761d043c564SKenneth D. Merry } 1762d043c564SKenneth D. Merry 1763d043c564SKenneth D. Merry static void 1764d043c564SKenneth D. Merry _mapping_process_dpm_pg0(struct mps_softc *sc) 1765d043c564SKenneth D. Merry { 1766d043c564SKenneth D. Merry u8 missing_cnt, enc_idx; 1767d043c564SKenneth D. Merry u16 slot_id, entry_num, num_slots; 1768d043c564SKenneth D. Merry u32 map_idx, dev_idx, start_idx, end_idx; 1769d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry; 1770d043c564SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry; 1771d043c564SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1772d043c564SKenneth D. Merry u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs); 1773d043c564SKenneth D. Merry struct enc_mapping_table *et_entry; 1774d043c564SKenneth D. Merry u64 physical_id; 1775d043c564SKenneth D. Merry u32 phy_bits = 0; 1776d043c564SKenneth D. Merry 1777635e58c7SStephen McConnell /* 1778635e58c7SStephen McConnell * start_idx and end_idx are only used for IR. 1779635e58c7SStephen McConnell */ 1780d043c564SKenneth D. Merry if (sc->ir_firmware) 1781d043c564SKenneth D. Merry _mapping_get_ir_maprange(sc, &start_idx, &end_idx); 1782d043c564SKenneth D. Merry 1783635e58c7SStephen McConnell /* 1784635e58c7SStephen McConnell * Look through all of the DPM entries that were read from the 1785635e58c7SStephen McConnell * controller and copy them over to the driver's internal table if they 1786635e58c7SStephen McConnell * have a non-zero ID. At this point, any ID with a value of 0 would be 1787635e58c7SStephen McConnell * invalid, so don't copy it. 1788635e58c7SStephen McConnell */ 1789635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Start copy of %d DPM entries into the " 1790635e58c7SStephen McConnell "mapping table.\n", __func__, sc->max_dpm_entries); 1791d043c564SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *) ((uint8_t *) sc->dpm_pg0 + 1792d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 1793d043c564SKenneth D. Merry for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++, 1794d043c564SKenneth D. Merry dpm_entry++) { 1795d043c564SKenneth D. Merry physical_id = dpm_entry->PhysicalIdentifier.High; 1796d043c564SKenneth D. Merry physical_id = (physical_id << 32) | 1797d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low; 1798d043c564SKenneth D. Merry if (!physical_id) { 1799d043c564SKenneth D. Merry sc->dpm_entry_used[entry_num] = 0; 1800d043c564SKenneth D. Merry continue; 1801d043c564SKenneth D. Merry } 1802d043c564SKenneth D. Merry sc->dpm_entry_used[entry_num] = 1; 1803d043c564SKenneth D. Merry dpm_entry->MappingInformation = le16toh(dpm_entry-> 1804d043c564SKenneth D. Merry MappingInformation); 1805d043c564SKenneth D. Merry missing_cnt = dpm_entry->MappingInformation & 1806d043c564SKenneth D. Merry MPI2_DRVMAP0_MAPINFO_MISSING_MASK; 1807d043c564SKenneth D. Merry dev_idx = le16toh(dpm_entry->DeviceIndex); 1808d043c564SKenneth D. Merry phy_bits = le32toh(dpm_entry->PhysicalBitsMapping); 1809635e58c7SStephen McConnell 1810635e58c7SStephen McConnell /* 1811635e58c7SStephen McConnell * Volumes are at special locations in the mapping table so 1812635e58c7SStephen McConnell * account for that. Volume mapping table entries do not depend 1813635e58c7SStephen McConnell * on the type of mapping, so continue the loop after adding 1814635e58c7SStephen McConnell * volumes to the mapping table. 1815635e58c7SStephen McConnell */ 1816d043c564SKenneth D. Merry if (sc->ir_firmware && (dev_idx >= start_idx) && 1817d043c564SKenneth D. Merry (dev_idx <= end_idx)) { 1818d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[dev_idx]; 1819635e58c7SStephen McConnell mt_entry->physical_id = 1820635e58c7SStephen McConnell dpm_entry->PhysicalIdentifier.High; 1821d043c564SKenneth D. Merry mt_entry->physical_id = (mt_entry->physical_id << 32) | 1822d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low; 1823d043c564SKenneth D. Merry mt_entry->id = dev_idx; 1824d043c564SKenneth D. Merry mt_entry->missing_count = missing_cnt; 1825d043c564SKenneth D. Merry mt_entry->dpm_entry_num = entry_num; 1826d043c564SKenneth D. Merry mt_entry->device_info = MPS_DEV_RESERVED; 1827d043c564SKenneth D. Merry continue; 1828d043c564SKenneth D. Merry } 1829d043c564SKenneth D. Merry if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1830d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 1831635e58c7SStephen McConnell /* 1832635e58c7SStephen McConnell * The dev_idx for an enclosure is the start index. If 1833635e58c7SStephen McConnell * the start index is within the controller's default 1834635e58c7SStephen McConnell * enclosure area, set the number of slots for this 1835635e58c7SStephen McConnell * enclosure to the max allowed. Otherwise, it should be 1836635e58c7SStephen McConnell * a normal enclosure and the number of slots is in the 1837635e58c7SStephen McConnell * DPM entry's Mapping Information. 1838635e58c7SStephen McConnell */ 1839d043c564SKenneth D. Merry if (dev_idx < (sc->num_rsvd_entries + 1840d043c564SKenneth D. Merry max_num_phy_ids)) { 1841d043c564SKenneth D. Merry slot_id = 0; 1842d043c564SKenneth D. Merry if (ioc_pg8_flags & 1843d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1) 1844d043c564SKenneth D. Merry slot_id = 1; 1845d043c564SKenneth D. Merry num_slots = max_num_phy_ids; 1846d043c564SKenneth D. Merry } else { 1847d043c564SKenneth D. Merry slot_id = 0; 1848d043c564SKenneth D. Merry num_slots = dpm_entry->MappingInformation & 1849d043c564SKenneth D. Merry MPI2_DRVMAP0_MAPINFO_SLOT_MASK; 1850d043c564SKenneth D. Merry num_slots >>= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT; 1851d043c564SKenneth D. Merry } 1852d043c564SKenneth D. Merry enc_idx = sc->num_enc_table_entries; 1853d043c564SKenneth D. Merry if (enc_idx >= sc->max_enclosures) { 1854635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: " 1855635e58c7SStephen McConnell "Number of enclosure entries in DPM exceed " 1856635e58c7SStephen McConnell "the max allowed of %d.\n", __func__, 1857d043c564SKenneth D. Merry sc->max_enclosures); 1858d043c564SKenneth D. Merry break; 1859d043c564SKenneth D. Merry } 1860d043c564SKenneth D. Merry sc->num_enc_table_entries++; 1861d043c564SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx]; 1862d043c564SKenneth D. Merry physical_id = dpm_entry->PhysicalIdentifier.High; 1863d043c564SKenneth D. Merry et_entry->enclosure_id = (physical_id << 32) | 1864d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low; 1865d043c564SKenneth D. Merry et_entry->start_index = dev_idx; 1866d043c564SKenneth D. Merry et_entry->dpm_entry_num = entry_num; 1867d043c564SKenneth D. Merry et_entry->num_slots = num_slots; 1868d043c564SKenneth D. Merry et_entry->start_slot = slot_id; 1869d043c564SKenneth D. Merry et_entry->missing_count = missing_cnt; 1870d043c564SKenneth D. Merry et_entry->phy_bits = phy_bits; 1871d043c564SKenneth D. Merry 1872635e58c7SStephen McConnell /* 1873635e58c7SStephen McConnell * Initialize all entries for this enclosure in the 1874635e58c7SStephen McConnell * mapping table and mark them as reserved. The actual 1875635e58c7SStephen McConnell * devices have not been processed yet but when they are 1876635e58c7SStephen McConnell * they will use these entries. If an entry is found 1877635e58c7SStephen McConnell * that already has a valid DPM index, the mapping table 1878635e58c7SStephen McConnell * is corrupt. This can happen if the mapping type is 1879635e58c7SStephen McConnell * changed without clearing all of the DPM entries in 1880635e58c7SStephen McConnell * the controller. 1881635e58c7SStephen McConnell */ 1882d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[dev_idx]; 1883d043c564SKenneth D. Merry for (map_idx = dev_idx; map_idx < (dev_idx + num_slots); 1884d043c564SKenneth D. Merry map_idx++, mt_entry++) { 1885d043c564SKenneth D. Merry if (mt_entry->dpm_entry_num != 1886d043c564SKenneth D. Merry MPS_DPM_BAD_IDX) { 1887635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, 1888635e58c7SStephen McConnell "%s: Conflict in mapping table for " 1889*b99419aeSAlexander Motin "enclosure %d device %d\n", 1890*b99419aeSAlexander Motin __func__, enc_idx, map_idx); 1891d043c564SKenneth D. Merry break; 1892d043c564SKenneth D. Merry } 1893635e58c7SStephen McConnell physical_id = 1894635e58c7SStephen McConnell dpm_entry->PhysicalIdentifier.High; 1895d043c564SKenneth D. Merry mt_entry->physical_id = (physical_id << 32) | 1896d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low; 1897d043c564SKenneth D. Merry mt_entry->phy_bits = phy_bits; 1898d043c564SKenneth D. Merry mt_entry->id = dev_idx; 1899d043c564SKenneth D. Merry mt_entry->dpm_entry_num = entry_num; 1900d043c564SKenneth D. Merry mt_entry->missing_count = missing_cnt; 1901d043c564SKenneth D. Merry mt_entry->device_info = MPS_DEV_RESERVED; 1902d043c564SKenneth D. Merry } 1903d043c564SKenneth D. Merry } else if ((ioc_pg8_flags & 1904d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1905d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { 1906635e58c7SStephen McConnell /* 1907635e58c7SStephen McConnell * Device mapping, so simply copy the DPM entries to the 1908635e58c7SStephen McConnell * mapping table, but check for a corrupt mapping table 1909635e58c7SStephen McConnell * (as described above in Enc/Slot mapping). 1910635e58c7SStephen McConnell */ 1911d043c564SKenneth D. Merry map_idx = dev_idx; 1912d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 1913d043c564SKenneth D. Merry if (mt_entry->dpm_entry_num != MPS_DPM_BAD_IDX) { 1914635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: " 1915635e58c7SStephen McConnell "Conflict in mapping table for device %d\n", 1916635e58c7SStephen McConnell __func__, map_idx); 1917d043c564SKenneth D. Merry break; 1918d043c564SKenneth D. Merry } 1919d043c564SKenneth D. Merry physical_id = dpm_entry->PhysicalIdentifier.High; 1920d043c564SKenneth D. Merry mt_entry->physical_id = (physical_id << 32) | 1921d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low; 1922d043c564SKenneth D. Merry mt_entry->phy_bits = phy_bits; 1923d043c564SKenneth D. Merry mt_entry->id = dev_idx; 1924d043c564SKenneth D. Merry mt_entry->missing_count = missing_cnt; 1925d043c564SKenneth D. Merry mt_entry->dpm_entry_num = entry_num; 1926d043c564SKenneth D. Merry mt_entry->device_info = MPS_DEV_RESERVED; 1927d043c564SKenneth D. Merry } 1928d043c564SKenneth D. Merry } /*close the loop for DPM table */ 1929d043c564SKenneth D. Merry } 1930d043c564SKenneth D. Merry 1931d043c564SKenneth D. Merry /* 1932d043c564SKenneth D. Merry * mps_mapping_check_devices - start of the day check for device availabilty 1933d043c564SKenneth D. Merry * @sc: per adapter object 1934d043c564SKenneth D. Merry * 1935d043c564SKenneth D. Merry * Returns nothing. 1936d043c564SKenneth D. Merry */ 1937d043c564SKenneth D. Merry void 1938635e58c7SStephen McConnell mps_mapping_check_devices(void *data) 1939d043c564SKenneth D. Merry { 1940d043c564SKenneth D. Merry u32 i; 1941d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry; 1942635e58c7SStephen McConnell struct mps_softc *sc = (struct mps_softc *)data; 1943d043c564SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1944d043c564SKenneth D. Merry struct enc_mapping_table *et_entry; 1945635e58c7SStephen McConnell u32 start_idx = 0, end_idx = 0; 1946635e58c7SStephen McConnell u8 stop_device_checks = 0; 1947d043c564SKenneth D. Merry 1948635e58c7SStephen McConnell MPS_FUNCTRACE(sc); 1949635e58c7SStephen McConnell 1950635e58c7SStephen McConnell /* 1951635e58c7SStephen McConnell * Clear this flag so that this function is never called again except 1952635e58c7SStephen McConnell * within this function if the check needs to be done again. The 1953635e58c7SStephen McConnell * purpose is to check for missing devices that are currently in the 1954635e58c7SStephen McConnell * mapping table so do this only at driver init after discovery. 1955635e58c7SStephen McConnell */ 1956d043c564SKenneth D. Merry sc->track_mapping_events = 0; 1957635e58c7SStephen McConnell 1958635e58c7SStephen McConnell /* 1959635e58c7SStephen McConnell * callout synchronization 1960635e58c7SStephen McConnell * This is used to prevent race conditions for the callout. 1961635e58c7SStephen McConnell */ 1962635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Start check for missing devices.\n", 1963635e58c7SStephen McConnell __func__); 1964635e58c7SStephen McConnell mtx_assert(&sc->mps_mtx, MA_OWNED); 1965635e58c7SStephen McConnell if ((callout_pending(&sc->device_check_callout)) || 1966635e58c7SStephen McConnell (!callout_active(&sc->device_check_callout))) { 1967635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Device Check Callout is " 1968635e58c7SStephen McConnell "already pending or not active.\n", __func__); 1969635e58c7SStephen McConnell return; 1970635e58c7SStephen McConnell } 1971635e58c7SStephen McConnell callout_deactivate(&sc->device_check_callout); 1972635e58c7SStephen McConnell 1973635e58c7SStephen McConnell /* 1974635e58c7SStephen McConnell * Use callout to check if any devices in the mapping table have been 1975635e58c7SStephen McConnell * processed yet. If ALL devices are marked as not init_complete, no 1976635e58c7SStephen McConnell * devices have been processed and mapped. Until devices are mapped 1977635e58c7SStephen McConnell * there's no reason to mark them as missing. Continue resetting this 1978635e58c7SStephen McConnell * callout until devices have been mapped. 1979635e58c7SStephen McConnell */ 1980635e58c7SStephen McConnell if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1981635e58c7SStephen McConnell MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 1982635e58c7SStephen McConnell et_entry = sc->enclosure_table; 1983635e58c7SStephen McConnell for (i = 0; i < sc->num_enc_table_entries; i++, et_entry++) { 1984635e58c7SStephen McConnell if (et_entry->init_complete) { 1985635e58c7SStephen McConnell stop_device_checks = 1; 1986d043c564SKenneth D. Merry break; 1987635e58c7SStephen McConnell } 1988635e58c7SStephen McConnell } 1989635e58c7SStephen McConnell } else if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1990635e58c7SStephen McConnell MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { 1991635e58c7SStephen McConnell mt_entry = sc->mapping_table; 1992635e58c7SStephen McConnell for (i = 0; i < sc->max_devices; i++, mt_entry++) { 1993635e58c7SStephen McConnell if (mt_entry->init_complete) { 1994635e58c7SStephen McConnell stop_device_checks = 1; 1995635e58c7SStephen McConnell break; 1996635e58c7SStephen McConnell } 1997635e58c7SStephen McConnell } 1998635e58c7SStephen McConnell } 1999d043c564SKenneth D. Merry 2000635e58c7SStephen McConnell /* 2001635e58c7SStephen McConnell * Setup another callout check after a delay. Keep doing this until 2002635e58c7SStephen McConnell * devices are mapped. 2003635e58c7SStephen McConnell */ 2004635e58c7SStephen McConnell if (!stop_device_checks) { 2005635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: No devices have been mapped. " 2006635e58c7SStephen McConnell "Reset callout to check again after a %d second delay.\n", 2007635e58c7SStephen McConnell __func__, MPS_MISSING_CHECK_DELAY); 2008635e58c7SStephen McConnell callout_reset(&sc->device_check_callout, 2009635e58c7SStephen McConnell MPS_MISSING_CHECK_DELAY * hz, mps_mapping_check_devices, 2010635e58c7SStephen McConnell sc); 2011635e58c7SStephen McConnell return; 2012635e58c7SStephen McConnell } 2013635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Device check complete.\n", __func__); 2014d043c564SKenneth D. Merry 2015635e58c7SStephen McConnell /* 2016635e58c7SStephen McConnell * Depending on the mapping type, check if devices have been processed 2017635e58c7SStephen McConnell * and update their missing counts if not processed. 2018635e58c7SStephen McConnell */ 2019d043c564SKenneth D. Merry if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 2020d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 2021d043c564SKenneth D. Merry et_entry = sc->enclosure_table; 2022d043c564SKenneth D. Merry for (i = 0; i < sc->num_enc_table_entries; i++, et_entry++) { 2023d043c564SKenneth D. Merry if (!et_entry->init_complete) { 2024d043c564SKenneth D. Merry if (et_entry->missing_count < 2025d043c564SKenneth D. Merry MPS_MAX_MISSING_COUNT) { 2026635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: " 2027635e58c7SStephen McConnell "Enclosure %d is missing from the " 2028635e58c7SStephen McConnell "topology. Update its missing " 2029635e58c7SStephen McConnell "count.\n", __func__, i); 2030d043c564SKenneth D. Merry et_entry->missing_count++; 2031d043c564SKenneth D. Merry if (et_entry->dpm_entry_num != 2032635e58c7SStephen McConnell MPS_DPM_BAD_IDX) { 2033d043c564SKenneth D. Merry _mapping_commit_enc_entry(sc, 2034d043c564SKenneth D. Merry et_entry); 2035d043c564SKenneth D. Merry } 2036635e58c7SStephen McConnell } 2037d043c564SKenneth D. Merry et_entry->init_complete = 1; 2038d043c564SKenneth D. Merry } 2039d043c564SKenneth D. Merry } 2040d043c564SKenneth D. Merry if (!sc->ir_firmware) 2041d043c564SKenneth D. Merry return; 2042d043c564SKenneth D. Merry _mapping_get_ir_maprange(sc, &start_idx, &end_idx); 2043d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[start_idx]; 2044635e58c7SStephen McConnell } else if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 2045635e58c7SStephen McConnell MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { 2046635e58c7SStephen McConnell start_idx = 0; 2047635e58c7SStephen McConnell end_idx = sc->max_devices - 1; 2048635e58c7SStephen McConnell mt_entry = sc->mapping_table; 2049635e58c7SStephen McConnell } 2050635e58c7SStephen McConnell 2051635e58c7SStephen McConnell /* 2052635e58c7SStephen McConnell * The start and end indices have been set above according to the 2053635e58c7SStephen McConnell * mapping type. Go through these mappings and update any entries that 2054635e58c7SStephen McConnell * do not have the init_complete flag set, which means they are missing. 2055635e58c7SStephen McConnell */ 2056635e58c7SStephen McConnell if (end_idx == 0) 2057635e58c7SStephen McConnell return; 2058d043c564SKenneth D. Merry for (i = start_idx; i < (end_idx + 1); i++, mt_entry++) { 2059d043c564SKenneth D. Merry if (mt_entry->device_info & MPS_DEV_RESERVED 2060d043c564SKenneth D. Merry && !mt_entry->physical_id) 2061d043c564SKenneth D. Merry mt_entry->init_complete = 1; 2062d043c564SKenneth D. Merry else if (mt_entry->device_info & MPS_DEV_RESERVED) { 2063d043c564SKenneth D. Merry if (!mt_entry->init_complete) { 2064635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Device in " 2065635e58c7SStephen McConnell "mapping table at index %d is missing from " 2066635e58c7SStephen McConnell "topology. Update its missing count.\n", 2067635e58c7SStephen McConnell __func__, i); 2068d043c564SKenneth D. Merry if (mt_entry->missing_count < 2069d043c564SKenneth D. Merry MPS_MAX_MISSING_COUNT) { 2070d043c564SKenneth D. Merry mt_entry->missing_count++; 2071d043c564SKenneth D. Merry if (mt_entry->dpm_entry_num != 2072635e58c7SStephen McConnell MPS_DPM_BAD_IDX) { 2073d043c564SKenneth D. Merry _mapping_commit_map_entry(sc, 2074d043c564SKenneth D. Merry mt_entry); 2075d043c564SKenneth D. Merry } 2076d043c564SKenneth D. Merry } 2077d043c564SKenneth D. Merry mt_entry->init_complete = 1; 2078d043c564SKenneth D. Merry } 2079d043c564SKenneth D. Merry } 2080d043c564SKenneth D. Merry } 2081d043c564SKenneth D. Merry } 2082d043c564SKenneth D. Merry 2083d043c564SKenneth D. Merry /** 2084d043c564SKenneth D. Merry * mps_mapping_initialize - initialize mapping tables 2085d043c564SKenneth D. Merry * @sc: per adapter object 2086d043c564SKenneth D. Merry * 2087d043c564SKenneth D. Merry * Read controller persitant mapping tables into internal data area. 2088d043c564SKenneth D. Merry * 2089d043c564SKenneth D. Merry * Return 0 for success or non-zero for failure. 2090d043c564SKenneth D. Merry */ 2091d043c564SKenneth D. Merry int 2092d043c564SKenneth D. Merry mps_mapping_initialize(struct mps_softc *sc) 2093d043c564SKenneth D. Merry { 2094d043c564SKenneth D. Merry uint16_t volume_mapping_flags, dpm_pg0_sz; 2095d043c564SKenneth D. Merry uint32_t i; 2096d043c564SKenneth D. Merry Mpi2ConfigReply_t mpi_reply; 2097d043c564SKenneth D. Merry int error; 2098d043c564SKenneth D. Merry uint8_t retry_count; 2099d043c564SKenneth D. Merry uint16_t ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 2100d043c564SKenneth D. Merry 2101d043c564SKenneth D. Merry /* The additional 1 accounts for the virtual enclosure 2102d043c564SKenneth D. Merry * created for the controller 2103d043c564SKenneth D. Merry */ 2104d043c564SKenneth D. Merry sc->max_enclosures = sc->facts->MaxEnclosures + 1; 2105d043c564SKenneth D. Merry sc->max_expanders = sc->facts->MaxSasExpanders; 2106d043c564SKenneth D. Merry sc->max_volumes = sc->facts->MaxVolumes; 2107d043c564SKenneth D. Merry sc->max_devices = sc->facts->MaxTargets + sc->max_volumes; 2108d043c564SKenneth D. Merry sc->pending_map_events = 0; 2109d043c564SKenneth D. Merry sc->num_enc_table_entries = 0; 2110d043c564SKenneth D. Merry sc->num_rsvd_entries = 0; 2111d043c564SKenneth D. Merry sc->max_dpm_entries = sc->ioc_pg8.MaxPersistentEntries; 2112d043c564SKenneth D. Merry sc->is_dpm_enable = (sc->max_dpm_entries) ? 1 : 0; 2113d043c564SKenneth D. Merry sc->track_mapping_events = 0; 2114d043c564SKenneth D. Merry 2115635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Mapping table has a max of %d entries " 2116635e58c7SStephen McConnell "and DPM has a max of %d entries.\n", __func__, sc->max_devices, 2117635e58c7SStephen McConnell sc->max_dpm_entries); 2118d043c564SKenneth D. Merry if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING) 2119d043c564SKenneth D. Merry sc->is_dpm_enable = 0; 2120d043c564SKenneth D. Merry 2121d043c564SKenneth D. Merry if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0) 2122d043c564SKenneth D. Merry sc->num_rsvd_entries = 1; 2123d043c564SKenneth D. Merry 2124d043c564SKenneth D. Merry volume_mapping_flags = sc->ioc_pg8.IRVolumeMappingFlags & 2125d043c564SKenneth D. Merry MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; 2126d043c564SKenneth D. Merry if (sc->ir_firmware && (volume_mapping_flags == 2127d043c564SKenneth D. Merry MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING)) 2128d043c564SKenneth D. Merry sc->num_rsvd_entries += sc->max_volumes; 2129d043c564SKenneth D. Merry 2130d043c564SKenneth D. Merry error = mps_mapping_allocate_memory(sc); 2131d043c564SKenneth D. Merry if (error) 2132d043c564SKenneth D. Merry return (error); 2133d043c564SKenneth D. Merry 2134d043c564SKenneth D. Merry for (i = 0; i < sc->max_devices; i++) 2135d043c564SKenneth D. Merry _mapping_clear_map_entry(sc->mapping_table + i); 2136d043c564SKenneth D. Merry 2137d043c564SKenneth D. Merry for (i = 0; i < sc->max_enclosures; i++) 2138d043c564SKenneth D. Merry _mapping_clear_enc_entry(sc->enclosure_table + i); 2139d043c564SKenneth D. Merry 2140d043c564SKenneth D. Merry for (i = 0; i < sc->max_devices; i++) { 2141d043c564SKenneth D. Merry sc->removal_table[i].dev_handle = 0; 2142d043c564SKenneth D. Merry sc->removal_table[i].dpm_entry_num = MPS_DPM_BAD_IDX; 2143d043c564SKenneth D. Merry } 2144d043c564SKenneth D. Merry 2145d043c564SKenneth D. Merry memset(sc->dpm_entry_used, 0, sc->max_dpm_entries); 2146d043c564SKenneth D. Merry memset(sc->dpm_flush_entry, 0, sc->max_dpm_entries); 2147d043c564SKenneth D. Merry 2148d043c564SKenneth D. Merry if (sc->is_dpm_enable) { 2149d043c564SKenneth D. Merry dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) + 2150d043c564SKenneth D. Merry (sc->max_dpm_entries * 2151d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY)); 2152d043c564SKenneth D. Merry retry_count = 0; 2153d043c564SKenneth D. Merry 2154d043c564SKenneth D. Merry retry_read_dpm: 2155d043c564SKenneth D. Merry if (mps_config_get_dpm_pg0(sc, &mpi_reply, sc->dpm_pg0, 2156d043c564SKenneth D. Merry dpm_pg0_sz)) { 2157635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: DPM page " 2158635e58c7SStephen McConnell "read failed.\n", __func__); 2159d043c564SKenneth D. Merry if (retry_count < 3) { 2160d043c564SKenneth D. Merry retry_count++; 2161d043c564SKenneth D. Merry goto retry_read_dpm; 2162d043c564SKenneth D. Merry } 2163d043c564SKenneth D. Merry sc->is_dpm_enable = 0; 2164d043c564SKenneth D. Merry } 2165d043c564SKenneth D. Merry } 2166d043c564SKenneth D. Merry 2167d043c564SKenneth D. Merry if (sc->is_dpm_enable) 2168d043c564SKenneth D. Merry _mapping_process_dpm_pg0(sc); 2169635e58c7SStephen McConnell else { 2170635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: DPM processing is disabled. " 2171635e58c7SStephen McConnell "Device mappings will not persist across reboots or " 2172635e58c7SStephen McConnell "resets.\n", __func__); 2173635e58c7SStephen McConnell } 2174d043c564SKenneth D. Merry 2175d043c564SKenneth D. Merry sc->track_mapping_events = 1; 2176d043c564SKenneth D. Merry return 0; 2177d043c564SKenneth D. Merry } 2178d043c564SKenneth D. Merry 2179d043c564SKenneth D. Merry /** 2180d043c564SKenneth D. Merry * mps_mapping_exit - clear mapping table and associated memory 2181d043c564SKenneth D. Merry * @sc: per adapter object 2182d043c564SKenneth D. Merry * 2183d043c564SKenneth D. Merry * Returns nothing. 2184d043c564SKenneth D. Merry */ 2185d043c564SKenneth D. Merry void 2186d043c564SKenneth D. Merry mps_mapping_exit(struct mps_softc *sc) 2187d043c564SKenneth D. Merry { 2188d043c564SKenneth D. Merry _mapping_flush_dpm_pages(sc); 2189d043c564SKenneth D. Merry mps_mapping_free_memory(sc); 2190d043c564SKenneth D. Merry } 2191d043c564SKenneth D. Merry 2192d043c564SKenneth D. Merry /** 2193635e58c7SStephen McConnell * mps_mapping_get_tid - return the target id for sas device and handle 2194d043c564SKenneth D. Merry * @sc: per adapter object 2195d043c564SKenneth D. Merry * @sas_address: sas address of the device 2196d043c564SKenneth D. Merry * @handle: device handle 2197d043c564SKenneth D. Merry * 2198635e58c7SStephen McConnell * Returns valid target ID on success or BAD_ID. 2199d043c564SKenneth D. Merry */ 2200d043c564SKenneth D. Merry unsigned int 2201635e58c7SStephen McConnell mps_mapping_get_tid(struct mps_softc *sc, uint64_t sas_address, u16 handle) 2202d043c564SKenneth D. Merry { 2203d043c564SKenneth D. Merry u32 map_idx; 2204d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry; 2205d043c564SKenneth D. Merry 2206d043c564SKenneth D. Merry for (map_idx = 0; map_idx < sc->max_devices; map_idx++) { 2207d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 2208d043c564SKenneth D. Merry if (mt_entry->dev_handle == handle && mt_entry->physical_id == 2209d043c564SKenneth D. Merry sas_address) 2210d043c564SKenneth D. Merry return mt_entry->id; 2211d043c564SKenneth D. Merry } 2212d043c564SKenneth D. Merry 2213d043c564SKenneth D. Merry return MPS_MAP_BAD_ID; 2214d043c564SKenneth D. Merry } 2215d043c564SKenneth D. Merry 2216d043c564SKenneth D. Merry /** 2217635e58c7SStephen McConnell * mps_mapping_get_tid_from_handle - find a target id in mapping table using 2218d043c564SKenneth D. Merry * only the dev handle. This is just a wrapper function for the local function 2219d043c564SKenneth D. Merry * _mapping_get_mt_idx_from_handle. 2220d043c564SKenneth D. Merry * @sc: per adapter object 2221d043c564SKenneth D. Merry * @handle: device handle 2222d043c564SKenneth D. Merry * 2223635e58c7SStephen McConnell * Returns valid target ID on success or BAD_ID. 2224d043c564SKenneth D. Merry */ 2225d043c564SKenneth D. Merry unsigned int 2226635e58c7SStephen McConnell mps_mapping_get_tid_from_handle(struct mps_softc *sc, u16 handle) 2227d043c564SKenneth D. Merry { 2228d043c564SKenneth D. Merry return (_mapping_get_mt_idx_from_handle(sc, handle)); 2229d043c564SKenneth D. Merry } 2230d043c564SKenneth D. Merry 2231d043c564SKenneth D. Merry /** 2232635e58c7SStephen McConnell * mps_mapping_get_raid_tid - return the target id for raid device 2233d043c564SKenneth D. Merry * @sc: per adapter object 2234d043c564SKenneth D. Merry * @wwid: world wide identifier for raid volume 2235635e58c7SStephen McConnell * @volHandle: volume device handle 2236d043c564SKenneth D. Merry * 2237635e58c7SStephen McConnell * Returns valid target ID on success or BAD_ID. 2238d043c564SKenneth D. Merry */ 2239d043c564SKenneth D. Merry unsigned int 2240635e58c7SStephen McConnell mps_mapping_get_raid_tid(struct mps_softc *sc, u64 wwid, u16 volHandle) 2241d043c564SKenneth D. Merry { 2242635e58c7SStephen McConnell u32 start_idx, end_idx, map_idx; 2243d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry; 2244d043c564SKenneth D. Merry 2245635e58c7SStephen McConnell _mapping_get_ir_maprange(sc, &start_idx, &end_idx); 2246635e58c7SStephen McConnell mt_entry = &sc->mapping_table[start_idx]; 2247635e58c7SStephen McConnell for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) { 2248635e58c7SStephen McConnell if (mt_entry->dev_handle == volHandle && 2249635e58c7SStephen McConnell mt_entry->physical_id == wwid) 2250d043c564SKenneth D. Merry return mt_entry->id; 2251d043c564SKenneth D. Merry } 2252d043c564SKenneth D. Merry 2253d043c564SKenneth D. Merry return MPS_MAP_BAD_ID; 2254d043c564SKenneth D. Merry } 2255d043c564SKenneth D. Merry 2256d043c564SKenneth D. Merry /** 2257635e58c7SStephen McConnell * mps_mapping_get_raid_tid_from_handle - find raid device in mapping table 2258d043c564SKenneth D. Merry * using only the volume dev handle. This is just a wrapper function for the 2259d043c564SKenneth D. Merry * local function _mapping_get_ir_mt_idx_from_handle. 2260d043c564SKenneth D. Merry * @sc: per adapter object 2261d043c564SKenneth D. Merry * @volHandle: volume device handle 2262d043c564SKenneth D. Merry * 2263635e58c7SStephen McConnell * Returns valid target ID on success or BAD_ID. 2264d043c564SKenneth D. Merry */ 2265d043c564SKenneth D. Merry unsigned int 2266635e58c7SStephen McConnell mps_mapping_get_raid_tid_from_handle(struct mps_softc *sc, u16 volHandle) 2267d043c564SKenneth D. Merry { 2268d043c564SKenneth D. Merry return (_mapping_get_ir_mt_idx_from_handle(sc, volHandle)); 2269d043c564SKenneth D. Merry } 2270d043c564SKenneth D. Merry 2271d043c564SKenneth D. Merry /** 2272d043c564SKenneth D. Merry * mps_mapping_enclosure_dev_status_change_event - handle enclosure events 2273d043c564SKenneth D. Merry * @sc: per adapter object 2274d043c564SKenneth D. Merry * @event_data: event data payload 2275d043c564SKenneth D. Merry * 2276d043c564SKenneth D. Merry * Return nothing. 2277d043c564SKenneth D. Merry */ 2278d043c564SKenneth D. Merry void 2279d043c564SKenneth D. Merry mps_mapping_enclosure_dev_status_change_event(struct mps_softc *sc, 2280d043c564SKenneth D. Merry Mpi2EventDataSasEnclDevStatusChange_t *event_data) 2281d043c564SKenneth D. Merry { 2282d043c564SKenneth D. Merry u8 enc_idx, missing_count; 2283d043c564SKenneth D. Merry struct enc_mapping_table *et_entry; 2284d043c564SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry; 2285d043c564SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 2286d043c564SKenneth D. Merry u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT; 2287d043c564SKenneth D. Merry u8 update_phy_bits = 0; 2288d043c564SKenneth D. Merry u32 saved_phy_bits; 2289d043c564SKenneth D. Merry uint64_t temp64_var; 2290d043c564SKenneth D. Merry 2291d043c564SKenneth D. Merry if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) != 2292d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) 2293d043c564SKenneth D. Merry goto out; 2294d043c564SKenneth D. Merry 2295d043c564SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 + 2296d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 2297d043c564SKenneth D. Merry 2298d043c564SKenneth D. Merry if (event_data->ReasonCode == MPI2_EVENT_SAS_ENCL_RC_ADDED) { 2299d043c564SKenneth D. Merry if (!event_data->NumSlots) { 2300635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Enclosure " 2301635e58c7SStephen McConnell "with handle = 0x%x reported 0 slots.\n", __func__, 2302d043c564SKenneth D. Merry le16toh(event_data->EnclosureHandle)); 2303d043c564SKenneth D. Merry goto out; 2304d043c564SKenneth D. Merry } 2305d043c564SKenneth D. Merry temp64_var = event_data->EnclosureLogicalID.High; 2306d043c564SKenneth D. Merry temp64_var = (temp64_var << 32) | 2307d043c564SKenneth D. Merry event_data->EnclosureLogicalID.Low; 2308d043c564SKenneth D. Merry enc_idx = _mapping_get_enc_idx_from_id(sc, temp64_var, 2309d043c564SKenneth D. Merry event_data->PhyBits); 2310635e58c7SStephen McConnell 2311635e58c7SStephen McConnell /* 2312635e58c7SStephen McConnell * If the Added enclosure is already in the Enclosure Table, 2313635e58c7SStephen McConnell * make sure that all the the enclosure info is up to date. If 2314635e58c7SStephen McConnell * the enclosure was missing and has just been added back, or if 2315635e58c7SStephen McConnell * the enclosure's Phy Bits have changed, clear the missing 2316635e58c7SStephen McConnell * count and update the Phy Bits in the mapping table and in the 2317635e58c7SStephen McConnell * DPM, if it's being used. 2318635e58c7SStephen McConnell */ 2319d043c564SKenneth D. Merry if (enc_idx != MPS_ENCTABLE_BAD_IDX) { 2320d043c564SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx]; 2321d043c564SKenneth D. Merry if (et_entry->init_complete && 2322d043c564SKenneth D. Merry !et_entry->missing_count) { 2323635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Enclosure %d " 2324635e58c7SStephen McConnell "is already present with handle = 0x%x\n", 2325635e58c7SStephen McConnell __func__, enc_idx, et_entry->enc_handle); 2326d043c564SKenneth D. Merry goto out; 2327d043c564SKenneth D. Merry } 2328d043c564SKenneth D. Merry et_entry->enc_handle = le16toh(event_data-> 2329d043c564SKenneth D. Merry EnclosureHandle); 2330d043c564SKenneth D. Merry et_entry->start_slot = le16toh(event_data->StartSlot); 2331d043c564SKenneth D. Merry saved_phy_bits = et_entry->phy_bits; 2332d043c564SKenneth D. Merry et_entry->phy_bits |= le32toh(event_data->PhyBits); 2333d043c564SKenneth D. Merry if (saved_phy_bits != et_entry->phy_bits) 2334d043c564SKenneth D. Merry update_phy_bits = 1; 2335d043c564SKenneth D. Merry if (et_entry->missing_count || update_phy_bits) { 2336d043c564SKenneth D. Merry et_entry->missing_count = 0; 2337d043c564SKenneth D. Merry if (sc->is_dpm_enable && 2338d043c564SKenneth D. Merry et_entry->dpm_entry_num != 2339d043c564SKenneth D. Merry MPS_DPM_BAD_IDX) { 2340d043c564SKenneth D. Merry dpm_entry += et_entry->dpm_entry_num; 2341d043c564SKenneth D. Merry missing_count = 2342d043c564SKenneth D. Merry (u8)(dpm_entry->MappingInformation & 2343d043c564SKenneth D. Merry MPI2_DRVMAP0_MAPINFO_MISSING_MASK); 2344635e58c7SStephen McConnell if (missing_count || update_phy_bits) { 2345d043c564SKenneth D. Merry dpm_entry->MappingInformation 2346d043c564SKenneth D. Merry = et_entry->num_slots; 2347d043c564SKenneth D. Merry dpm_entry->MappingInformation 2348d043c564SKenneth D. Merry <<= map_shift; 2349d043c564SKenneth D. Merry dpm_entry->PhysicalBitsMapping 2350d043c564SKenneth D. Merry = et_entry->phy_bits; 2351d043c564SKenneth D. Merry sc->dpm_flush_entry[et_entry-> 2352d043c564SKenneth D. Merry dpm_entry_num] = 1; 2353d043c564SKenneth D. Merry } 2354d043c564SKenneth D. Merry } 2355d043c564SKenneth D. Merry } 2356d043c564SKenneth D. Merry } else { 2357635e58c7SStephen McConnell /* 2358635e58c7SStephen McConnell * This is a new enclosure that is being added. 2359635e58c7SStephen McConnell * Initialize the Enclosure Table entry. It will be 2360635e58c7SStephen McConnell * finalized when a device is added for the enclosure 2361635e58c7SStephen McConnell * and the enclosure has enough space in the Mapping 2362635e58c7SStephen McConnell * Table to map its devices. 2363635e58c7SStephen McConnell */ 2364*b99419aeSAlexander Motin if (sc->num_enc_table_entries < sc->max_enclosures) { 2365d043c564SKenneth D. Merry enc_idx = sc->num_enc_table_entries; 2366*b99419aeSAlexander Motin sc->num_enc_table_entries++; 2367*b99419aeSAlexander Motin } else { 2368*b99419aeSAlexander Motin enc_idx = _mapping_get_high_missing_et_idx(sc); 2369*b99419aeSAlexander Motin if (enc_idx != MPS_ENCTABLE_BAD_IDX) { 2370*b99419aeSAlexander Motin et_entry = &sc->enclosure_table[enc_idx]; 2371*b99419aeSAlexander Motin _mapping_add_to_removal_table(sc, 2372*b99419aeSAlexander Motin et_entry->dpm_entry_num); 2373*b99419aeSAlexander Motin _mapping_clear_enc_entry(et_entry); 2374*b99419aeSAlexander Motin } 2375*b99419aeSAlexander Motin } 2376*b99419aeSAlexander Motin if (enc_idx == MPS_ENCTABLE_BAD_IDX) { 2377635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: " 2378635e58c7SStephen McConnell "Enclosure cannot be added to mapping " 2379635e58c7SStephen McConnell "table because it's full.\n", __func__); 2380d043c564SKenneth D. Merry goto out; 2381d043c564SKenneth D. Merry } 2382d043c564SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx]; 2383d043c564SKenneth D. Merry et_entry->enc_handle = le16toh(event_data-> 2384d043c564SKenneth D. Merry EnclosureHandle); 2385635e58c7SStephen McConnell et_entry->enclosure_id = le64toh(event_data-> 2386635e58c7SStephen McConnell EnclosureLogicalID.High); 2387635e58c7SStephen McConnell et_entry->enclosure_id = 2388635e58c7SStephen McConnell ((et_entry->enclosure_id << 32) | 2389635e58c7SStephen McConnell le64toh(event_data->EnclosureLogicalID.Low)); 2390d043c564SKenneth D. Merry et_entry->start_index = MPS_MAPTABLE_BAD_IDX; 2391d043c564SKenneth D. Merry et_entry->dpm_entry_num = MPS_DPM_BAD_IDX; 2392d043c564SKenneth D. Merry et_entry->num_slots = le16toh(event_data->NumSlots); 2393d043c564SKenneth D. Merry et_entry->start_slot = le16toh(event_data->StartSlot); 2394d043c564SKenneth D. Merry et_entry->phy_bits = le32toh(event_data->PhyBits); 2395d043c564SKenneth D. Merry } 2396d043c564SKenneth D. Merry et_entry->init_complete = 1; 2397d043c564SKenneth D. Merry } else if (event_data->ReasonCode == 2398d043c564SKenneth D. Merry MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING) { 2399635e58c7SStephen McConnell /* 2400635e58c7SStephen McConnell * An enclosure was removed. Update its missing count and then 2401635e58c7SStephen McConnell * update the DPM entry with the new missing count for the 2402635e58c7SStephen McConnell * enclosure. 2403635e58c7SStephen McConnell */ 2404d043c564SKenneth D. Merry enc_idx = _mapping_get_enc_idx_from_handle(sc, 2405d043c564SKenneth D. Merry le16toh(event_data->EnclosureHandle)); 2406d043c564SKenneth D. Merry if (enc_idx == MPS_ENCTABLE_BAD_IDX) { 2407635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Cannot " 2408*b99419aeSAlexander Motin "unmap enclosure with handle 0x%04x because it " 2409*b99419aeSAlexander Motin "has already been deleted.\n", __func__, 2410*b99419aeSAlexander Motin le16toh(event_data->EnclosureHandle)); 2411d043c564SKenneth D. Merry goto out; 2412d043c564SKenneth D. Merry } 2413d043c564SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx]; 2414d043c564SKenneth D. Merry if (et_entry->missing_count < MPS_MAX_MISSING_COUNT) 2415d043c564SKenneth D. Merry et_entry->missing_count++; 2416635e58c7SStephen McConnell if (sc->is_dpm_enable && 2417d043c564SKenneth D. Merry et_entry->dpm_entry_num != MPS_DPM_BAD_IDX) { 2418d043c564SKenneth D. Merry dpm_entry += et_entry->dpm_entry_num; 2419d043c564SKenneth D. Merry dpm_entry->MappingInformation = et_entry->num_slots; 2420d043c564SKenneth D. Merry dpm_entry->MappingInformation <<= map_shift; 2421d043c564SKenneth D. Merry dpm_entry->MappingInformation |= 2422d043c564SKenneth D. Merry et_entry->missing_count; 2423d043c564SKenneth D. Merry sc->dpm_flush_entry[et_entry->dpm_entry_num] = 1; 2424d043c564SKenneth D. Merry } 2425d043c564SKenneth D. Merry et_entry->init_complete = 1; 2426d043c564SKenneth D. Merry } 2427d043c564SKenneth D. Merry 2428d043c564SKenneth D. Merry out: 2429d043c564SKenneth D. Merry _mapping_flush_dpm_pages(sc); 2430d043c564SKenneth D. Merry if (sc->pending_map_events) 2431d043c564SKenneth D. Merry sc->pending_map_events--; 2432d043c564SKenneth D. Merry } 2433d043c564SKenneth D. Merry 2434d043c564SKenneth D. Merry /** 2435d043c564SKenneth D. Merry * mps_mapping_topology_change_event - handle topology change events 2436d043c564SKenneth D. Merry * @sc: per adapter object 2437d043c564SKenneth D. Merry * @event_data: event data payload 2438d043c564SKenneth D. Merry * 2439d043c564SKenneth D. Merry * Returns nothing. 2440d043c564SKenneth D. Merry */ 2441d043c564SKenneth D. Merry void 2442d043c564SKenneth D. Merry mps_mapping_topology_change_event(struct mps_softc *sc, 2443d043c564SKenneth D. Merry Mpi2EventDataSasTopologyChangeList_t *event_data) 2444d043c564SKenneth D. Merry { 2445d043c564SKenneth D. Merry struct _map_topology_change topo_change; 2446d043c564SKenneth D. Merry struct _map_phy_change *phy_change; 2447d043c564SKenneth D. Merry Mpi2EventSasTopoPhyEntry_t *event_phy_change; 2448d043c564SKenneth D. Merry u8 i, num_entries; 2449d043c564SKenneth D. Merry 2450d043c564SKenneth D. Merry topo_change.enc_handle = le16toh(event_data->EnclosureHandle); 2451d043c564SKenneth D. Merry topo_change.exp_handle = le16toh(event_data->ExpanderDevHandle); 2452d043c564SKenneth D. Merry num_entries = event_data->NumEntries; 2453d043c564SKenneth D. Merry topo_change.num_entries = num_entries; 2454d043c564SKenneth D. Merry topo_change.start_phy_num = event_data->StartPhyNum; 2455d043c564SKenneth D. Merry topo_change.num_phys = event_data->NumPhys; 2456d043c564SKenneth D. Merry topo_change.exp_status = event_data->ExpStatus; 2457d043c564SKenneth D. Merry event_phy_change = event_data->PHY; 2458d043c564SKenneth D. Merry topo_change.phy_details = NULL; 2459d043c564SKenneth D. Merry 2460d043c564SKenneth D. Merry if (!num_entries) 2461d043c564SKenneth D. Merry goto out; 2462ac2fffa4SPedro F. Giffuni phy_change = malloc(sizeof(struct _map_phy_change) * num_entries, 2463d043c564SKenneth D. Merry M_MPT2, M_NOWAIT|M_ZERO); 2464d043c564SKenneth D. Merry topo_change.phy_details = phy_change; 2465d043c564SKenneth D. Merry if (!phy_change) 2466d043c564SKenneth D. Merry goto out; 2467d043c564SKenneth D. Merry for (i = 0; i < num_entries; i++, event_phy_change++, phy_change++) { 2468d043c564SKenneth D. Merry phy_change->dev_handle = le16toh(event_phy_change-> 2469d043c564SKenneth D. Merry AttachedDevHandle); 2470d043c564SKenneth D. Merry phy_change->reason = event_phy_change->PhyStatus & 2471d043c564SKenneth D. Merry MPI2_EVENT_SAS_TOPO_RC_MASK; 2472d043c564SKenneth D. Merry } 2473d043c564SKenneth D. Merry _mapping_update_missing_count(sc, &topo_change); 2474d043c564SKenneth D. Merry _mapping_get_dev_info(sc, &topo_change); 2475d043c564SKenneth D. Merry _mapping_clear_removed_entries(sc); 2476d043c564SKenneth D. Merry _mapping_add_new_device(sc, &topo_change); 2477d043c564SKenneth D. Merry 2478d043c564SKenneth D. Merry out: 2479d043c564SKenneth D. Merry free(topo_change.phy_details, M_MPT2); 2480d043c564SKenneth D. Merry _mapping_flush_dpm_pages(sc); 2481d043c564SKenneth D. Merry if (sc->pending_map_events) 2482d043c564SKenneth D. Merry sc->pending_map_events--; 2483d043c564SKenneth D. Merry } 2484d043c564SKenneth D. Merry 2485d043c564SKenneth D. Merry /** 2486d043c564SKenneth D. Merry * mps_mapping_ir_config_change_event - handle IR config change list events 2487d043c564SKenneth D. Merry * @sc: per adapter object 2488d043c564SKenneth D. Merry * @event_data: event data payload 2489d043c564SKenneth D. Merry * 2490d043c564SKenneth D. Merry * Returns nothing. 2491d043c564SKenneth D. Merry */ 2492d043c564SKenneth D. Merry void 2493d043c564SKenneth D. Merry mps_mapping_ir_config_change_event(struct mps_softc *sc, 2494d043c564SKenneth D. Merry Mpi2EventDataIrConfigChangeList_t *event_data) 2495d043c564SKenneth D. Merry { 2496d043c564SKenneth D. Merry Mpi2EventIrConfigElement_t *element; 2497d043c564SKenneth D. Merry int i; 2498d043c564SKenneth D. Merry u64 *wwid_table; 2499d043c564SKenneth D. Merry u32 map_idx, flags; 2500d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry; 2501d043c564SKenneth D. Merry u16 element_flags; 2502d043c564SKenneth D. Merry 2503ac2fffa4SPedro F. Giffuni wwid_table = malloc(sizeof(u64) * event_data->NumElements, M_MPT2, 2504d043c564SKenneth D. Merry M_NOWAIT | M_ZERO); 2505d043c564SKenneth D. Merry if (!wwid_table) 2506d043c564SKenneth D. Merry goto out; 2507d043c564SKenneth D. Merry element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; 2508d043c564SKenneth D. Merry flags = le32toh(event_data->Flags); 2509635e58c7SStephen McConnell 2510635e58c7SStephen McConnell /* 2511635e58c7SStephen McConnell * For volume changes, get the WWID for the volume and put it in a 2512635e58c7SStephen McConnell * table to be used in the processing of the IR change event. 2513635e58c7SStephen McConnell */ 2514d043c564SKenneth D. Merry for (i = 0; i < event_data->NumElements; i++, element++) { 2515d043c564SKenneth D. Merry element_flags = le16toh(element->ElementFlags); 2516d043c564SKenneth D. Merry if ((element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_ADDED) && 2517d043c564SKenneth D. Merry (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_REMOVED) && 2518d043c564SKenneth D. Merry (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE) 2519d043c564SKenneth D. Merry && (element->ReasonCode != 2520d043c564SKenneth D. Merry MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED)) 2521d043c564SKenneth D. Merry continue; 2522d043c564SKenneth D. Merry if ((element_flags & 2523d043c564SKenneth D. Merry MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK) == 2524d043c564SKenneth D. Merry MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT) { 2525d043c564SKenneth D. Merry mps_config_get_volume_wwid(sc, 2526d043c564SKenneth D. Merry le16toh(element->VolDevHandle), &wwid_table[i]); 2527d043c564SKenneth D. Merry } 2528d043c564SKenneth D. Merry } 2529635e58c7SStephen McConnell 2530635e58c7SStephen McConnell /* 2531635e58c7SStephen McConnell * Check the ReasonCode for each element in the IR event and Add/Remove 2532635e58c7SStephen McConnell * Volumes or Physical Disks of Volumes to/from the mapping table. Use 2533635e58c7SStephen McConnell * the WWIDs gotten above in wwid_table. 2534635e58c7SStephen McConnell */ 2535d043c564SKenneth D. Merry if (flags == MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) 2536d043c564SKenneth D. Merry goto out; 2537d043c564SKenneth D. Merry else { 2538d043c564SKenneth D. Merry element = (Mpi2EventIrConfigElement_t *)&event_data-> 2539d043c564SKenneth D. Merry ConfigElement[0]; 2540d043c564SKenneth D. Merry for (i = 0; i < event_data->NumElements; i++, element++) { 2541d043c564SKenneth D. Merry if (element->ReasonCode == 2542d043c564SKenneth D. Merry MPI2_EVENT_IR_CHANGE_RC_ADDED || 2543d043c564SKenneth D. Merry element->ReasonCode == 2544d043c564SKenneth D. Merry MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) { 2545d043c564SKenneth D. Merry map_idx = _mapping_get_ir_mt_idx_from_wwid 2546d043c564SKenneth D. Merry (sc, wwid_table[i]); 2547d043c564SKenneth D. Merry if (map_idx != MPS_MAPTABLE_BAD_IDX) { 2548635e58c7SStephen McConnell /* 2549635e58c7SStephen McConnell * The volume is already in the mapping 2550635e58c7SStephen McConnell * table. Just update it's info. 2551635e58c7SStephen McConnell */ 2552d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 2553d043c564SKenneth D. Merry mt_entry->id = map_idx; 2554d043c564SKenneth D. Merry mt_entry->dev_handle = le16toh 2555d043c564SKenneth D. Merry (element->VolDevHandle); 2556d043c564SKenneth D. Merry mt_entry->device_info = 2557d043c564SKenneth D. Merry MPS_DEV_RESERVED | MPS_MAP_IN_USE; 2558d043c564SKenneth D. Merry _mapping_update_ir_missing_cnt(sc, 2559d043c564SKenneth D. Merry map_idx, element, wwid_table[i]); 2560d043c564SKenneth D. Merry continue; 2561d043c564SKenneth D. Merry } 2562635e58c7SStephen McConnell 2563635e58c7SStephen McConnell /* 2564635e58c7SStephen McConnell * Volume is not in mapping table yet. Find a 2565635e58c7SStephen McConnell * free entry in the mapping table at the 2566635e58c7SStephen McConnell * volume mapping locations. If no entries are 2567635e58c7SStephen McConnell * available, this is an error because it means 2568635e58c7SStephen McConnell * there are more volumes than can be mapped 2569635e58c7SStephen McConnell * and that should never happen for volumes. 2570635e58c7SStephen McConnell */ 2571d043c564SKenneth D. Merry map_idx = _mapping_get_free_ir_mt_idx(sc); 2572d043c564SKenneth D. Merry if (map_idx == MPS_MAPTABLE_BAD_IDX) 2573635e58c7SStephen McConnell { 2574635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, 2575635e58c7SStephen McConnell "%s: failed to add the volume with " 2576635e58c7SStephen McConnell "handle 0x%04x because there is no " 2577635e58c7SStephen McConnell "free space available in the " 2578635e58c7SStephen McConnell "mapping table\n", __func__, 2579635e58c7SStephen McConnell le16toh(element->VolDevHandle)); 2580d043c564SKenneth D. Merry continue; 2581d043c564SKenneth D. Merry } 2582d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 2583d043c564SKenneth D. Merry mt_entry->physical_id = wwid_table[i]; 2584d043c564SKenneth D. Merry mt_entry->id = map_idx; 2585d043c564SKenneth D. Merry mt_entry->dev_handle = le16toh(element-> 2586d043c564SKenneth D. Merry VolDevHandle); 2587d043c564SKenneth D. Merry mt_entry->device_info = MPS_DEV_RESERVED | 2588d043c564SKenneth D. Merry MPS_MAP_IN_USE; 2589d043c564SKenneth D. Merry _mapping_update_ir_missing_cnt(sc, map_idx, 2590d043c564SKenneth D. Merry element, wwid_table[i]); 2591d043c564SKenneth D. Merry } else if (element->ReasonCode == 2592d043c564SKenneth D. Merry MPI2_EVENT_IR_CHANGE_RC_REMOVED) { 2593d043c564SKenneth D. Merry map_idx = _mapping_get_ir_mt_idx_from_wwid(sc, 2594d043c564SKenneth D. Merry wwid_table[i]); 2595d043c564SKenneth D. Merry if (map_idx == MPS_MAPTABLE_BAD_IDX) { 2596635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING,"%s: Failed " 2597635e58c7SStephen McConnell "to remove a volume because it has " 2598635e58c7SStephen McConnell "already been removed.\n", 2599635e58c7SStephen McConnell __func__); 2600d043c564SKenneth D. Merry continue; 2601d043c564SKenneth D. Merry } 2602d043c564SKenneth D. Merry _mapping_update_ir_missing_cnt(sc, map_idx, 2603d043c564SKenneth D. Merry element, wwid_table[i]); 2604d043c564SKenneth D. Merry } else if (element->ReasonCode == 2605d043c564SKenneth D. Merry MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED) { 2606d043c564SKenneth D. Merry map_idx = _mapping_get_mt_idx_from_handle(sc, 2607d043c564SKenneth D. Merry le16toh(element->VolDevHandle)); 2608d043c564SKenneth D. Merry if (map_idx == MPS_MAPTABLE_BAD_IDX) { 2609635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING,"%s: Failed " 2610635e58c7SStephen McConnell "to remove volume with handle " 2611635e58c7SStephen McConnell "0x%04x because it has already " 2612635e58c7SStephen McConnell "been removed.\n", __func__, 2613d043c564SKenneth D. Merry le16toh(element->VolDevHandle)); 2614d043c564SKenneth D. Merry continue; 2615d043c564SKenneth D. Merry } 2616d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx]; 2617d043c564SKenneth D. Merry _mapping_update_ir_missing_cnt(sc, map_idx, 2618d043c564SKenneth D. Merry element, mt_entry->physical_id); 2619d043c564SKenneth D. Merry } 2620d043c564SKenneth D. Merry } 2621d043c564SKenneth D. Merry } 2622d043c564SKenneth D. Merry 2623d043c564SKenneth D. Merry out: 2624d043c564SKenneth D. Merry _mapping_flush_dpm_pages(sc); 2625d043c564SKenneth D. Merry free(wwid_table, M_MPT2); 2626d043c564SKenneth D. Merry if (sc->pending_map_events) 2627d043c564SKenneth D. Merry sc->pending_map_events--; 2628d043c564SKenneth D. Merry } 2629ee5c196bSScott Long 2630ee5c196bSScott Long int 2631ee5c196bSScott Long mps_mapping_dump(SYSCTL_HANDLER_ARGS) 2632ee5c196bSScott Long { 2633ee5c196bSScott Long struct mps_softc *sc; 2634ee5c196bSScott Long struct dev_mapping_table *mt_entry; 2635ee5c196bSScott Long struct sbuf sbuf; 2636ee5c196bSScott Long int i, error; 2637ee5c196bSScott Long 2638ee5c196bSScott Long sc = (struct mps_softc *)arg1; 2639ee5c196bSScott Long 2640ee5c196bSScott Long error = sysctl_wire_old_buffer(req, 0); 2641ee5c196bSScott Long if (error != 0) 2642ee5c196bSScott Long return (error); 2643ee5c196bSScott Long sbuf_new_for_sysctl(&sbuf, NULL, 128, req); 2644ee5c196bSScott Long 2645ee5c196bSScott Long sbuf_printf(&sbuf, "\nindex physical_id handle id\n"); 2646ee5c196bSScott Long for (i = 0; i < sc->max_devices; i++) { 2647ee5c196bSScott Long mt_entry = &sc->mapping_table[i]; 2648ee5c196bSScott Long if (mt_entry->physical_id == 0) 2649ee5c196bSScott Long continue; 2650ee5c196bSScott Long sbuf_printf(&sbuf, "%4d %jx %04x %hd\n", 2651ee5c196bSScott Long i, mt_entry->physical_id, mt_entry->dev_handle, 2652ee5c196bSScott Long mt_entry->id); 2653ee5c196bSScott Long } 2654ee5c196bSScott Long error = sbuf_finish(&sbuf); 2655ee5c196bSScott Long sbuf_delete(&sbuf); 2656ee5c196bSScott Long return (error); 2657ee5c196bSScott Long } 2658ee5c196bSScott Long 2659ee5c196bSScott Long int 2660ee5c196bSScott Long mps_mapping_encl_dump(SYSCTL_HANDLER_ARGS) 2661ee5c196bSScott Long { 2662ee5c196bSScott Long struct mps_softc *sc; 2663ee5c196bSScott Long struct enc_mapping_table *enc_entry; 2664ee5c196bSScott Long struct sbuf sbuf; 2665ee5c196bSScott Long int i, error; 2666ee5c196bSScott Long 2667ee5c196bSScott Long sc = (struct mps_softc *)arg1; 2668ee5c196bSScott Long 2669ee5c196bSScott Long error = sysctl_wire_old_buffer(req, 0); 2670ee5c196bSScott Long if (error != 0) 2671ee5c196bSScott Long return (error); 2672ee5c196bSScott Long sbuf_new_for_sysctl(&sbuf, NULL, 128, req); 2673ee5c196bSScott Long 2674ee5c196bSScott Long sbuf_printf(&sbuf, "\nindex enclosure_id handle map_index\n"); 2675ee5c196bSScott Long for (i = 0; i < sc->max_enclosures; i++) { 2676ee5c196bSScott Long enc_entry = &sc->enclosure_table[i]; 2677ee5c196bSScott Long if (enc_entry->enclosure_id == 0) 2678ee5c196bSScott Long continue; 2679ee5c196bSScott Long sbuf_printf(&sbuf, "%4d %jx %04x %d\n", 2680ee5c196bSScott Long i, enc_entry->enclosure_id, enc_entry->enc_handle, 2681ee5c196bSScott Long enc_entry->start_index); 2682ee5c196bSScott Long } 2683ee5c196bSScott Long error = sbuf_finish(&sbuf); 2684ee5c196bSScott Long sbuf_delete(&sbuf); 2685ee5c196bSScott Long return (error); 2686ee5c196bSScott Long } 2687