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