1230592Sken/*- 2237876Sken * Copyright (c) 2011, 2012 LSI Corp. 3230592Sken * All rights reserved. 4230592Sken * 5230592Sken * Redistribution and use in source and binary forms, with or without 6230592Sken * modification, are permitted provided that the following conditions 7230592Sken * are met: 8230592Sken * 1. Redistributions of source code must retain the above copyright 9230592Sken * notice, this list of conditions and the following disclaimer. 10230592Sken * 2. Redistributions in binary form must reproduce the above copyright 11230592Sken * notice, this list of conditions and the following disclaimer in the 12230592Sken * documentation and/or other materials provided with the distribution. 13230592Sken * 14230592Sken * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15230592Sken * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16230592Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17230592Sken * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18230592Sken * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19230592Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20230592Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21230592Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22230592Sken * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23230592Sken * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24230592Sken * SUCH DAMAGE. 25230592Sken * 26230592Sken * LSI MPT-Fusion Host Adapter FreeBSD 27230592Sken */ 28230592Sken 29230592Sken#include <sys/cdefs.h> 30230592Sken__FBSDID("$FreeBSD$"); 31230592Sken 32230592Sken/* TODO Move headers to mpsvar */ 33230592Sken#include <sys/types.h> 34230592Sken#include <sys/param.h> 35230592Sken#include <sys/lock.h> 36230592Sken#include <sys/mutex.h> 37230592Sken#include <sys/systm.h> 38230592Sken#include <sys/kernel.h> 39230592Sken#include <sys/malloc.h> 40230592Sken#include <sys/kthread.h> 41230592Sken#include <sys/taskqueue.h> 42230592Sken#include <sys/bus.h> 43230592Sken#include <sys/endian.h> 44230592Sken#include <sys/sysctl.h> 45230592Sken#include <sys/eventhandler.h> 46230592Sken#include <sys/uio.h> 47230592Sken#include <machine/bus.h> 48230592Sken#include <machine/resource.h> 49230592Sken#include <dev/mps/mpi/mpi2_type.h> 50230592Sken#include <dev/mps/mpi/mpi2.h> 51230592Sken#include <dev/mps/mpi/mpi2_ioc.h> 52230592Sken#include <dev/mps/mpi/mpi2_sas.h> 53230592Sken#include <dev/mps/mpi/mpi2_cnfg.h> 54230592Sken#include <dev/mps/mpi/mpi2_init.h> 55230592Sken#include <dev/mps/mpi/mpi2_tool.h> 56230592Sken#include <dev/mps/mps_ioctl.h> 57230592Sken#include <dev/mps/mpsvar.h> 58230592Sken#include <dev/mps/mps_mapping.h> 59230592Sken 60230592Sken/** 61230592Sken * _mapping_clear_entry - Clear a particular mapping entry. 62230592Sken * @map_entry: map table entry 63230592Sken * 64230592Sken * Returns nothing. 65230592Sken */ 66230592Skenstatic inline void 67230592Sken_mapping_clear_map_entry(struct dev_mapping_table *map_entry) 68230592Sken{ 69230592Sken map_entry->physical_id = 0; 70230592Sken map_entry->device_info = 0; 71230592Sken map_entry->phy_bits = 0; 72230592Sken map_entry->dpm_entry_num = MPS_DPM_BAD_IDX; 73230592Sken map_entry->dev_handle = 0; 74230592Sken map_entry->channel = -1; 75230592Sken map_entry->id = -1; 76230592Sken map_entry->missing_count = 0; 77230592Sken map_entry->init_complete = 0; 78230592Sken map_entry->TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR; 79230592Sken} 80230592Sken 81230592Sken/** 82230592Sken * _mapping_clear_enc_entry - Clear a particular enclosure table entry. 83230592Sken * @enc_entry: enclosure table entry 84230592Sken * 85230592Sken * Returns nothing. 86230592Sken */ 87230592Skenstatic inline void 88230592Sken_mapping_clear_enc_entry(struct enc_mapping_table *enc_entry) 89230592Sken{ 90230592Sken enc_entry->enclosure_id = 0; 91230592Sken enc_entry->start_index = MPS_MAPTABLE_BAD_IDX; 92230592Sken enc_entry->phy_bits = 0; 93230592Sken enc_entry->dpm_entry_num = MPS_DPM_BAD_IDX; 94230592Sken enc_entry->enc_handle = 0; 95230592Sken enc_entry->num_slots = 0; 96230592Sken enc_entry->start_slot = 0; 97230592Sken enc_entry->missing_count = 0; 98230592Sken enc_entry->removal_flag = 0; 99230592Sken enc_entry->skip_search = 0; 100230592Sken enc_entry->init_complete = 0; 101230592Sken} 102230592Sken 103230592Sken/** 104230592Sken * _mapping_commit_enc_entry - write a particular enc entry in DPM page0. 105230592Sken * @sc: per adapter object 106230592Sken * @enc_entry: enclosure table entry 107230592Sken * 108230592Sken * Returns 0 for success, non-zero for failure. 109230592Sken */ 110230592Skenstatic int 111230592Sken_mapping_commit_enc_entry(struct mps_softc *sc, 112230592Sken struct enc_mapping_table *et_entry) 113230592Sken{ 114230592Sken Mpi2DriverMap0Entry_t *dpm_entry; 115230592Sken struct dev_mapping_table *mt_entry; 116230592Sken Mpi2ConfigReply_t mpi_reply; 117230592Sken Mpi2DriverMappingPage0_t config_page; 118230592Sken 119230592Sken if (!sc->is_dpm_enable) 120230592Sken return 0; 121230592Sken 122230592Sken memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t)); 123230592Sken memcpy(&config_page.Header, (u8 *) sc->dpm_pg0, 124230592Sken sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 125230592Sken dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 + 126230592Sken sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 127230592Sken dpm_entry += et_entry->dpm_entry_num; 128230592Sken dpm_entry->PhysicalIdentifier.Low = 129230592Sken ( 0xFFFFFFFF & et_entry->enclosure_id); 130230592Sken dpm_entry->PhysicalIdentifier.High = 131230592Sken ( et_entry->enclosure_id >> 32); 132230592Sken mt_entry = &sc->mapping_table[et_entry->start_index]; 133230592Sken dpm_entry->DeviceIndex = htole16(mt_entry->id); 134230592Sken dpm_entry->MappingInformation = et_entry->num_slots; 135230592Sken dpm_entry->MappingInformation <<= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT; 136230592Sken dpm_entry->MappingInformation |= et_entry->missing_count; 137230592Sken dpm_entry->MappingInformation = htole16(dpm_entry->MappingInformation); 138230592Sken dpm_entry->PhysicalBitsMapping = htole32(et_entry->phy_bits); 139230592Sken dpm_entry->Reserved1 = 0; 140230592Sken 141230592Sken memcpy(&config_page.Entry, (u8 *)dpm_entry, 142230592Sken sizeof(Mpi2DriverMap0Entry_t)); 143230592Sken if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page, 144230592Sken et_entry->dpm_entry_num)) { 145230592Sken printf("%s: write of dpm entry %d for enclosure failed\n", 146230592Sken __func__, et_entry->dpm_entry_num); 147230592Sken dpm_entry->MappingInformation = le16toh(dpm_entry-> 148230592Sken MappingInformation); 149230592Sken dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex); 150230592Sken dpm_entry->PhysicalBitsMapping = 151230592Sken le32toh(dpm_entry->PhysicalBitsMapping); 152230592Sken return -1; 153230592Sken } 154230592Sken dpm_entry->MappingInformation = le16toh(dpm_entry-> 155230592Sken MappingInformation); 156230592Sken dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex); 157230592Sken dpm_entry->PhysicalBitsMapping = 158230592Sken le32toh(dpm_entry->PhysicalBitsMapping); 159230592Sken return 0; 160230592Sken} 161230592Sken 162230592Sken/** 163230592Sken * _mapping_commit_map_entry - write a particular map table entry in DPM page0. 164230592Sken * @sc: per adapter object 165230592Sken * @enc_entry: enclosure table entry 166230592Sken * 167230592Sken * Returns 0 for success, non-zero for failure. 168230592Sken */ 169230592Sken 170230592Skenstatic int 171230592Sken_mapping_commit_map_entry(struct mps_softc *sc, 172230592Sken struct dev_mapping_table *mt_entry) 173230592Sken{ 174230592Sken Mpi2DriverMap0Entry_t *dpm_entry; 175230592Sken Mpi2ConfigReply_t mpi_reply; 176230592Sken Mpi2DriverMappingPage0_t config_page; 177230592Sken 178230592Sken if (!sc->is_dpm_enable) 179230592Sken return 0; 180230592Sken 181230592Sken memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t)); 182230592Sken memcpy(&config_page.Header, (u8 *)sc->dpm_pg0, 183230592Sken sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 184230592Sken dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *) sc->dpm_pg0 + 185230592Sken sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 186230592Sken dpm_entry = dpm_entry + mt_entry->dpm_entry_num; 187230592Sken dpm_entry->PhysicalIdentifier.Low = (0xFFFFFFFF & 188230592Sken mt_entry->physical_id); 189230592Sken dpm_entry->PhysicalIdentifier.High = (mt_entry->physical_id >> 32); 190230592Sken dpm_entry->DeviceIndex = htole16(mt_entry->id); 191230592Sken dpm_entry->MappingInformation = htole16(mt_entry->missing_count); 192230592Sken dpm_entry->PhysicalBitsMapping = 0; 193230592Sken dpm_entry->Reserved1 = 0; 194230592Sken dpm_entry->MappingInformation = htole16(dpm_entry->MappingInformation); 195230592Sken memcpy(&config_page.Entry, (u8 *)dpm_entry, 196230592Sken sizeof(Mpi2DriverMap0Entry_t)); 197230592Sken if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page, 198230592Sken mt_entry->dpm_entry_num)) { 199230592Sken printf("%s: write of dpm entry %d for device failed\n", 200230592Sken __func__, mt_entry->dpm_entry_num); 201230592Sken dpm_entry->MappingInformation = le16toh(dpm_entry-> 202230592Sken MappingInformation); 203230592Sken dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex); 204230592Sken return -1; 205230592Sken } 206230592Sken 207230592Sken dpm_entry->MappingInformation = le16toh(dpm_entry->MappingInformation); 208230592Sken dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex); 209230592Sken return 0; 210230592Sken} 211230592Sken 212230592Sken/** 213230592Sken * _mapping_get_ir_maprange - get start and end index for IR map range. 214230592Sken * @sc: per adapter object 215230592Sken * @start_idx: place holder for start index 216230592Sken * @end_idx: place holder for end index 217230592Sken * 218230592Sken * The IR volumes can be mapped either at start or end of the mapping table 219230592Sken * this function gets the detail of where IR volume mapping starts and ends 220230592Sken * in the device mapping table 221230592Sken * 222230592Sken * Returns nothing. 223230592Sken */ 224230592Skenstatic void 225230592Sken_mapping_get_ir_maprange(struct mps_softc *sc, u32 *start_idx, u32 *end_idx) 226230592Sken{ 227230592Sken u16 volume_mapping_flags; 228230592Sken u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 229230592Sken 230230592Sken volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) & 231230592Sken MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; 232230592Sken if (volume_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) { 233230592Sken *start_idx = 0; 234230592Sken if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0) 235230592Sken *start_idx = 1; 236230592Sken } else 237230592Sken *start_idx = sc->max_devices - sc->max_volumes; 238230592Sken *end_idx = *start_idx + sc->max_volumes - 1; 239230592Sken} 240230592Sken 241230592Sken/** 242230592Sken * _mapping_get_enc_idx_from_id - get enclosure index from enclosure ID 243230592Sken * @sc: per adapter object 244230592Sken * @enc_id: enclosure logical identifier 245230592Sken * 246230592Sken * Returns the index of enclosure entry on success or bad index. 247230592Sken */ 248230592Skenstatic u8 249230592Sken_mapping_get_enc_idx_from_id(struct mps_softc *sc, u64 enc_id, 250230592Sken u64 phy_bits) 251230592Sken{ 252230592Sken struct enc_mapping_table *et_entry; 253230592Sken u8 enc_idx = 0; 254230592Sken 255230592Sken for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) { 256230592Sken et_entry = &sc->enclosure_table[enc_idx]; 257230592Sken if ((et_entry->enclosure_id == le64toh(enc_id)) && 258230592Sken (!et_entry->phy_bits || (et_entry->phy_bits & 259230592Sken le32toh(phy_bits)))) 260230592Sken return enc_idx; 261230592Sken } 262230592Sken return MPS_ENCTABLE_BAD_IDX; 263230592Sken} 264230592Sken 265230592Sken/** 266230592Sken * _mapping_get_enc_idx_from_handle - get enclosure index from handle 267230592Sken * @sc: per adapter object 268230592Sken * @enc_id: enclosure handle 269230592Sken * 270230592Sken * Returns the index of enclosure entry on success or bad index. 271230592Sken */ 272230592Skenstatic u8 273230592Sken_mapping_get_enc_idx_from_handle(struct mps_softc *sc, u16 handle) 274230592Sken{ 275230592Sken struct enc_mapping_table *et_entry; 276230592Sken u8 enc_idx = 0; 277230592Sken 278230592Sken for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) { 279230592Sken et_entry = &sc->enclosure_table[enc_idx]; 280230592Sken if (et_entry->missing_count) 281230592Sken continue; 282230592Sken if (et_entry->enc_handle == handle) 283230592Sken return enc_idx; 284230592Sken } 285230592Sken return MPS_ENCTABLE_BAD_IDX; 286230592Sken} 287230592Sken 288230592Sken/** 289230592Sken * _mapping_get_high_missing_et_idx - get missing enclosure index 290230592Sken * @sc: per adapter object 291230592Sken * 292230592Sken * Search through the enclosure table and identifies the enclosure entry 293230592Sken * with high missing count and returns it's index 294230592Sken * 295230592Sken * Returns the index of enclosure entry on success or bad index. 296230592Sken */ 297230592Skenstatic u8 298230592Sken_mapping_get_high_missing_et_idx(struct mps_softc *sc) 299230592Sken{ 300230592Sken struct enc_mapping_table *et_entry; 301230592Sken u8 high_missing_count = 0; 302230592Sken u8 enc_idx, high_idx = MPS_ENCTABLE_BAD_IDX; 303230592Sken 304230592Sken for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) { 305230592Sken et_entry = &sc->enclosure_table[enc_idx]; 306230592Sken if ((et_entry->missing_count > high_missing_count) && 307230592Sken !et_entry->skip_search) { 308230592Sken high_missing_count = et_entry->missing_count; 309230592Sken high_idx = enc_idx; 310230592Sken } 311230592Sken } 312230592Sken return high_idx; 313230592Sken} 314230592Sken 315230592Sken/** 316230592Sken * _mapping_get_high_missing_mt_idx - get missing map table index 317230592Sken * @sc: per adapter object 318230592Sken * 319230592Sken * Search through the map table and identifies the device entry 320230592Sken * with high missing count and returns it's index 321230592Sken * 322230592Sken * Returns the index of map table entry on success or bad index. 323230592Sken */ 324230592Skenstatic u32 325230592Sken_mapping_get_high_missing_mt_idx(struct mps_softc *sc) 326230592Sken{ 327230592Sken u32 map_idx, high_idx = MPS_ENCTABLE_BAD_IDX; 328230592Sken u8 high_missing_count = 0; 329230592Sken u32 start_idx, end_idx, start_idx_ir, end_idx_ir; 330230592Sken struct dev_mapping_table *mt_entry; 331230592Sken u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 332230592Sken 333230592Sken start_idx = 0; 334251414Ssmh start_idx_ir = 0; 335251414Ssmh end_idx_ir = 0; 336230592Sken end_idx = sc->max_devices; 337230592Sken if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0) 338230592Sken start_idx = 1; 339230592Sken if (sc->ir_firmware) 340230592Sken _mapping_get_ir_maprange(sc, &start_idx_ir, &end_idx_ir); 341230592Sken if (start_idx == start_idx_ir) 342230592Sken start_idx = end_idx_ir + 1; 343230592Sken else 344230592Sken end_idx = start_idx_ir; 345230592Sken mt_entry = &sc->mapping_table[start_idx]; 346230592Sken for (map_idx = start_idx; map_idx < end_idx; map_idx++, mt_entry++) { 347230592Sken if (mt_entry->missing_count > high_missing_count) { 348230592Sken high_missing_count = mt_entry->missing_count; 349230592Sken high_idx = map_idx; 350230592Sken } 351230592Sken } 352230592Sken return high_idx; 353230592Sken} 354230592Sken 355230592Sken/** 356230592Sken * _mapping_get_ir_mt_idx_from_wwid - get map table index from volume WWID 357230592Sken * @sc: per adapter object 358230592Sken * @wwid: world wide unique ID of the volume 359230592Sken * 360230592Sken * Returns the index of map table entry on success or bad index. 361230592Sken */ 362230592Skenstatic u32 363230592Sken_mapping_get_ir_mt_idx_from_wwid(struct mps_softc *sc, u64 wwid) 364230592Sken{ 365230592Sken u32 start_idx, end_idx, map_idx; 366230592Sken struct dev_mapping_table *mt_entry; 367230592Sken 368230592Sken _mapping_get_ir_maprange(sc, &start_idx, &end_idx); 369230592Sken mt_entry = &sc->mapping_table[start_idx]; 370230592Sken for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) 371230592Sken if (mt_entry->physical_id == wwid) 372230592Sken return map_idx; 373230592Sken 374230592Sken return MPS_MAPTABLE_BAD_IDX; 375230592Sken} 376230592Sken 377230592Sken/** 378230592Sken * _mapping_get_mt_idx_from_id - get map table index from a device ID 379230592Sken * @sc: per adapter object 380230592Sken * @dev_id: device identifer (SAS Address) 381230592Sken * 382230592Sken * Returns the index of map table entry on success or bad index. 383230592Sken */ 384230592Skenstatic u32 385230592Sken_mapping_get_mt_idx_from_id(struct mps_softc *sc, u64 dev_id) 386230592Sken{ 387230592Sken u32 map_idx; 388230592Sken struct dev_mapping_table *mt_entry; 389230592Sken 390230592Sken for (map_idx = 0; map_idx < sc->max_devices; map_idx++) { 391230592Sken mt_entry = &sc->mapping_table[map_idx]; 392230592Sken if (mt_entry->physical_id == dev_id) 393230592Sken return map_idx; 394230592Sken } 395230592Sken return MPS_MAPTABLE_BAD_IDX; 396230592Sken} 397230592Sken 398230592Sken/** 399230592Sken * _mapping_get_ir_mt_idx_from_handle - get map table index from volume handle 400230592Sken * @sc: per adapter object 401230592Sken * @wwid: volume device handle 402230592Sken * 403230592Sken * Returns the index of map table entry on success or bad index. 404230592Sken */ 405230592Skenstatic u32 406230592Sken_mapping_get_ir_mt_idx_from_handle(struct mps_softc *sc, u16 volHandle) 407230592Sken{ 408230592Sken u32 start_idx, end_idx, map_idx; 409230592Sken struct dev_mapping_table *mt_entry; 410230592Sken 411230592Sken _mapping_get_ir_maprange(sc, &start_idx, &end_idx); 412230592Sken mt_entry = &sc->mapping_table[start_idx]; 413230592Sken for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) 414230592Sken if (mt_entry->dev_handle == volHandle) 415230592Sken return map_idx; 416230592Sken 417230592Sken return MPS_MAPTABLE_BAD_IDX; 418230592Sken} 419230592Sken 420230592Sken/** 421230592Sken * _mapping_get_mt_idx_from_handle - get map table index from handle 422230592Sken * @sc: per adapter object 423230592Sken * @dev_id: device handle 424230592Sken * 425230592Sken * Returns the index of map table entry on success or bad index. 426230592Sken */ 427230592Skenstatic u32 428230592Sken_mapping_get_mt_idx_from_handle(struct mps_softc *sc, u16 handle) 429230592Sken{ 430230592Sken u32 map_idx; 431230592Sken struct dev_mapping_table *mt_entry; 432230592Sken 433230592Sken for (map_idx = 0; map_idx < sc->max_devices; map_idx++) { 434230592Sken mt_entry = &sc->mapping_table[map_idx]; 435230592Sken if (mt_entry->dev_handle == handle) 436230592Sken return map_idx; 437230592Sken } 438230592Sken return MPS_MAPTABLE_BAD_IDX; 439230592Sken} 440230592Sken 441230592Sken/** 442230592Sken * _mapping_get_free_ir_mt_idx - get first free index for a volume 443230592Sken * @sc: per adapter object 444230592Sken * 445230592Sken * Search through mapping table for free index for a volume and if no free 446230592Sken * index then looks for a volume with high mapping index 447230592Sken * 448230592Sken * Returns the index of map table entry on success or bad index. 449230592Sken */ 450230592Skenstatic u32 451230592Sken_mapping_get_free_ir_mt_idx(struct mps_softc *sc) 452230592Sken{ 453230592Sken u8 high_missing_count = 0; 454230592Sken u32 start_idx, end_idx, map_idx; 455230592Sken u32 high_idx = MPS_MAPTABLE_BAD_IDX; 456230592Sken struct dev_mapping_table *mt_entry; 457230592Sken 458230592Sken _mapping_get_ir_maprange(sc, &start_idx, &end_idx); 459230592Sken 460230592Sken mt_entry = &sc->mapping_table[start_idx]; 461230592Sken for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) 462230592Sken if (!(mt_entry->device_info & MPS_MAP_IN_USE)) 463230592Sken return map_idx; 464230592Sken 465230592Sken mt_entry = &sc->mapping_table[start_idx]; 466230592Sken for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) { 467230592Sken if (mt_entry->missing_count > high_missing_count) { 468230592Sken high_missing_count = mt_entry->missing_count; 469230592Sken high_idx = map_idx; 470230592Sken } 471230592Sken } 472230592Sken return high_idx; 473230592Sken} 474230592Sken 475230592Sken/** 476230592Sken * _mapping_get_free_mt_idx - get first free index for a device 477230592Sken * @sc: per adapter object 478230592Sken * @start_idx: offset in the table to start search 479230592Sken * 480230592Sken * Returns the index of map table entry on success or bad index. 481230592Sken */ 482230592Skenstatic u32 483230592Sken_mapping_get_free_mt_idx(struct mps_softc *sc, u32 start_idx) 484230592Sken{ 485230592Sken u32 map_idx, max_idx = sc->max_devices; 486230592Sken struct dev_mapping_table *mt_entry = &sc->mapping_table[start_idx]; 487230592Sken u16 volume_mapping_flags; 488230592Sken 489230592Sken volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) & 490230592Sken MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; 491230592Sken if (sc->ir_firmware && (volume_mapping_flags == 492230592Sken MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING)) 493230592Sken max_idx -= sc->max_volumes; 494230592Sken for (map_idx = start_idx; map_idx < max_idx; map_idx++, mt_entry++) 495230592Sken if (!(mt_entry->device_info & (MPS_MAP_IN_USE | 496230592Sken MPS_DEV_RESERVED))) 497230592Sken return map_idx; 498230592Sken 499230592Sken return MPS_MAPTABLE_BAD_IDX; 500230592Sken} 501230592Sken 502230592Sken/** 503230592Sken * _mapping_get_dpm_idx_from_id - get DPM index from ID 504230592Sken * @sc: per adapter object 505230592Sken * @id: volume WWID or enclosure ID or device ID 506230592Sken * 507230592Sken * Returns the index of DPM entry on success or bad index. 508230592Sken */ 509230592Skenstatic u16 510230592Sken_mapping_get_dpm_idx_from_id(struct mps_softc *sc, u64 id, u32 phy_bits) 511230592Sken{ 512230592Sken u16 entry_num; 513230592Sken uint64_t PhysicalIdentifier; 514230592Sken Mpi2DriverMap0Entry_t *dpm_entry; 515230592Sken 516230592Sken dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 + 517230592Sken sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 518230592Sken PhysicalIdentifier = dpm_entry->PhysicalIdentifier.High; 519230592Sken PhysicalIdentifier = (PhysicalIdentifier << 32) | 520230592Sken dpm_entry->PhysicalIdentifier.Low; 521230592Sken for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++, 522230592Sken dpm_entry++) 523230592Sken if ((id == PhysicalIdentifier) && 524230592Sken (!phy_bits || !dpm_entry->PhysicalBitsMapping || 525230592Sken (phy_bits & dpm_entry->PhysicalBitsMapping))) 526230592Sken return entry_num; 527230592Sken 528230592Sken return MPS_DPM_BAD_IDX; 529230592Sken} 530230592Sken 531230592Sken 532230592Sken/** 533230592Sken * _mapping_get_free_dpm_idx - get first available DPM index 534230592Sken * @sc: per adapter object 535230592Sken * 536230592Sken * Returns the index of DPM entry on success or bad index. 537230592Sken */ 538230592Skenstatic u32 539230592Sken_mapping_get_free_dpm_idx(struct mps_softc *sc) 540230592Sken{ 541230592Sken u16 entry_num; 542230592Sken 543230592Sken for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) { 544230592Sken if (!sc->dpm_entry_used[entry_num]) 545230592Sken return entry_num; 546230592Sken } 547230592Sken return MPS_DPM_BAD_IDX; 548230592Sken} 549230592Sken 550230592Sken/** 551230592Sken * _mapping_update_ir_missing_cnt - Updates missing count for a volume 552230592Sken * @sc: per adapter object 553230592Sken * @map_idx: map table index of the volume 554230592Sken * @element: IR configuration change element 555230592Sken * @wwid: IR volume ID. 556230592Sken * 557230592Sken * Updates the missing count in the map table and in the DPM entry for a volume 558230592Sken * 559230592Sken * Returns nothing. 560230592Sken */ 561230592Skenstatic void 562230592Sken_mapping_update_ir_missing_cnt(struct mps_softc *sc, u32 map_idx, 563230592Sken Mpi2EventIrConfigElement_t *element, u64 wwid) 564230592Sken{ 565230592Sken struct dev_mapping_table *mt_entry; 566230592Sken u8 missing_cnt, reason = element->ReasonCode; 567230592Sken u16 dpm_idx; 568230592Sken Mpi2DriverMap0Entry_t *dpm_entry; 569230592Sken 570230592Sken if (!sc->is_dpm_enable) 571230592Sken return; 572230592Sken mt_entry = &sc->mapping_table[map_idx]; 573230592Sken if (reason == MPI2_EVENT_IR_CHANGE_RC_ADDED) { 574230592Sken mt_entry->missing_count = 0; 575230592Sken } else if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) { 576230592Sken mt_entry->missing_count = 0; 577230592Sken mt_entry->init_complete = 0; 578230592Sken } else if ((reason == MPI2_EVENT_IR_CHANGE_RC_REMOVED) || 579230592Sken (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED)) { 580230592Sken if (!mt_entry->init_complete) { 581230592Sken if (mt_entry->missing_count < MPS_MAX_MISSING_COUNT) 582230592Sken mt_entry->missing_count++; 583230592Sken else 584230592Sken mt_entry->init_complete = 1; 585230592Sken } 586230592Sken if (!mt_entry->missing_count) 587230592Sken mt_entry->missing_count++; 588230592Sken mt_entry->dev_handle = 0; 589230592Sken } 590230592Sken 591230592Sken dpm_idx = mt_entry->dpm_entry_num; 592230592Sken if (dpm_idx == MPS_DPM_BAD_IDX) { 593230592Sken if ((reason == MPI2_EVENT_IR_CHANGE_RC_ADDED) || 594230592Sken (reason == MPI2_EVENT_IR_CHANGE_RC_REMOVED)) 595230592Sken dpm_idx = _mapping_get_dpm_idx_from_id(sc, 596230592Sken mt_entry->physical_id, 0); 597230592Sken else if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED) 598230592Sken return; 599230592Sken } 600230592Sken if (dpm_idx != MPS_DPM_BAD_IDX) { 601230592Sken dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 + 602230592Sken sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 603230592Sken dpm_entry += dpm_idx; 604230592Sken missing_cnt = dpm_entry->MappingInformation & 605230592Sken MPI2_DRVMAP0_MAPINFO_MISSING_MASK; 606230592Sken if ((mt_entry->physical_id == 607230592Sken le64toh((u64)dpm_entry->PhysicalIdentifier.High | 608230592Sken dpm_entry->PhysicalIdentifier.Low)) && (missing_cnt == 609230592Sken mt_entry->missing_count)) 610230592Sken mt_entry->init_complete = 1; 611230592Sken } else { 612230592Sken dpm_idx = _mapping_get_free_dpm_idx(sc); 613230592Sken mt_entry->init_complete = 0; 614230592Sken } 615230592Sken 616230592Sken if ((dpm_idx != MPS_DPM_BAD_IDX) && !mt_entry->init_complete) { 617230592Sken mt_entry->init_complete = 1; 618230592Sken mt_entry->dpm_entry_num = dpm_idx; 619230592Sken dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 + 620230592Sken sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 621230592Sken dpm_entry += dpm_idx; 622230592Sken dpm_entry->PhysicalIdentifier.Low = 623230592Sken (0xFFFFFFFF & mt_entry->physical_id); 624230592Sken dpm_entry->PhysicalIdentifier.High = 625230592Sken (mt_entry->physical_id >> 32); 626230592Sken dpm_entry->DeviceIndex = map_idx; 627230592Sken dpm_entry->MappingInformation = mt_entry->missing_count; 628230592Sken dpm_entry->PhysicalBitsMapping = 0; 629230592Sken dpm_entry->Reserved1 = 0; 630230592Sken sc->dpm_flush_entry[dpm_idx] = 1; 631230592Sken sc->dpm_entry_used[dpm_idx] = 1; 632230592Sken } else if (dpm_idx == MPS_DPM_BAD_IDX) { 633230592Sken printf("%s: no space to add entry in DPM table\n", __func__); 634230592Sken mt_entry->init_complete = 1; 635230592Sken } 636230592Sken} 637230592Sken 638230592Sken/** 639230592Sken * _mapping_add_to_removal_table - mark an entry for removal 640230592Sken * @sc: per adapter object 641230592Sken * @handle: Handle of enclosures/device/volume 642230592Sken * 643230592Sken * Adds the handle or DPM entry number in removal table. 644230592Sken * 645230592Sken * Returns nothing. 646230592Sken */ 647230592Skenstatic void 648230592Sken_mapping_add_to_removal_table(struct mps_softc *sc, u16 handle, 649230592Sken u16 dpm_idx) 650230592Sken{ 651230592Sken struct map_removal_table *remove_entry; 652230592Sken u32 i; 653230592Sken u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 654230592Sken 655230592Sken remove_entry = sc->removal_table; 656230592Sken 657230592Sken for (i = 0; i < sc->max_devices; i++, remove_entry++) { 658230592Sken if (remove_entry->dev_handle || remove_entry->dpm_entry_num != 659230592Sken MPS_DPM_BAD_IDX) 660230592Sken continue; 661230592Sken if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 662230592Sken MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 663230592Sken if (dpm_idx) 664230592Sken remove_entry->dpm_entry_num = dpm_idx; 665230592Sken if (remove_entry->dpm_entry_num == MPS_DPM_BAD_IDX) 666230592Sken remove_entry->dev_handle = handle; 667230592Sken } else if ((ioc_pg8_flags & 668230592Sken MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 669230592Sken MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) 670230592Sken remove_entry->dev_handle = handle; 671230592Sken break; 672230592Sken } 673230592Sken 674230592Sken} 675230592Sken 676230592Sken/** 677230592Sken * _mapping_update_missing_count - Update missing count for a device 678230592Sken * @sc: per adapter object 679230592Sken * @topo_change: Topology change event entry 680230592Sken * 681230592Sken * Search through the topology change list and if any device is found not 682230592Sken * responding it's associated map table entry and DPM entry is updated 683230592Sken * 684230592Sken * Returns nothing. 685230592Sken */ 686230592Skenstatic void 687230592Sken_mapping_update_missing_count(struct mps_softc *sc, 688230592Sken struct _map_topology_change *topo_change) 689230592Sken{ 690230592Sken u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 691230592Sken u8 entry; 692230592Sken struct _map_phy_change *phy_change; 693230592Sken u32 map_idx; 694230592Sken struct dev_mapping_table *mt_entry; 695230592Sken Mpi2DriverMap0Entry_t *dpm_entry; 696230592Sken 697230592Sken for (entry = 0; entry < topo_change->num_entries; entry++) { 698230592Sken phy_change = &topo_change->phy_details[entry]; 699230592Sken if (!phy_change->dev_handle || (phy_change->reason != 700230592Sken MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)) 701230592Sken continue; 702230592Sken map_idx = _mapping_get_mt_idx_from_handle(sc, phy_change-> 703230592Sken dev_handle); 704230592Sken phy_change->is_processed = 1; 705230592Sken if (map_idx == MPS_MAPTABLE_BAD_IDX) { 706230592Sken printf("%s: device is already removed from mapping " 707230592Sken "table\n", __func__); 708230592Sken continue; 709230592Sken } 710230592Sken mt_entry = &sc->mapping_table[map_idx]; 711230592Sken if (!mt_entry->init_complete) { 712230592Sken if (mt_entry->missing_count < MPS_MAX_MISSING_COUNT) 713230592Sken mt_entry->missing_count++; 714230592Sken else 715230592Sken mt_entry->init_complete = 1; 716230592Sken } 717230592Sken if (!mt_entry->missing_count) 718230592Sken mt_entry->missing_count++; 719230592Sken _mapping_add_to_removal_table(sc, mt_entry->dev_handle, 0); 720230592Sken mt_entry->dev_handle = 0; 721230592Sken 722230592Sken if (((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 723230592Sken MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) && 724230592Sken sc->is_dpm_enable && !mt_entry->init_complete && 725230592Sken mt_entry->dpm_entry_num != MPS_DPM_BAD_IDX) { 726230592Sken dpm_entry = 727230592Sken (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 + 728230592Sken sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 729230592Sken dpm_entry += mt_entry->dpm_entry_num; 730230592Sken dpm_entry->MappingInformation = mt_entry->missing_count; 731230592Sken sc->dpm_flush_entry[mt_entry->dpm_entry_num] = 1; 732230592Sken } 733230592Sken mt_entry->init_complete = 1; 734230592Sken } 735230592Sken} 736230592Sken 737230592Sken/** 738230592Sken * _mapping_find_enc_map_space -find map table entries for enclosure 739230592Sken * @sc: per adapter object 740230592Sken * @et_entry: enclosure entry 741230592Sken * 742230592Sken * Search through the mapping table defragment it and provide contiguous 743230592Sken * space in map table for a particular enclosure entry 744230592Sken * 745230592Sken * Returns start index in map table or bad index. 746230592Sken */ 747230592Skenstatic u32 748230592Sken_mapping_find_enc_map_space(struct mps_softc *sc, 749230592Sken struct enc_mapping_table *et_entry) 750230592Sken{ 751230592Sken u16 vol_mapping_flags; 752230592Sken u32 skip_count, end_of_table, map_idx, enc_idx; 753230592Sken u16 num_found; 754230592Sken u32 start_idx = MPS_MAPTABLE_BAD_IDX; 755230592Sken struct dev_mapping_table *mt_entry; 756230592Sken struct enc_mapping_table *enc_entry; 757230592Sken unsigned char done_flag = 0, found_space; 758230592Sken u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs); 759230592Sken 760230592Sken skip_count = sc->num_rsvd_entries; 761230592Sken num_found = 0; 762230592Sken 763230592Sken vol_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) & 764230592Sken MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; 765230592Sken 766230592Sken if (!sc->ir_firmware) 767230592Sken end_of_table = sc->max_devices; 768230592Sken else if (vol_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) 769230592Sken end_of_table = sc->max_devices; 770230592Sken else 771230592Sken end_of_table = sc->max_devices - sc->max_volumes; 772230592Sken 773230592Sken for (map_idx = (max_num_phy_ids + skip_count); 774230592Sken map_idx < end_of_table; map_idx++) { 775230592Sken mt_entry = &sc->mapping_table[map_idx]; 776230592Sken if ((et_entry->enclosure_id == mt_entry->physical_id) && 777230592Sken (!mt_entry->phy_bits || (mt_entry->phy_bits & 778230592Sken et_entry->phy_bits))) { 779230592Sken num_found += 1; 780230592Sken if (num_found == et_entry->num_slots) { 781230592Sken start_idx = (map_idx - num_found) + 1; 782230592Sken return start_idx; 783230592Sken } 784230592Sken } else 785230592Sken num_found = 0; 786230592Sken } 787230592Sken for (map_idx = (max_num_phy_ids + skip_count); 788230592Sken map_idx < end_of_table; map_idx++) { 789230592Sken mt_entry = &sc->mapping_table[map_idx]; 790230592Sken if (!(mt_entry->device_info & MPS_DEV_RESERVED)) { 791230592Sken num_found += 1; 792230592Sken if (num_found == et_entry->num_slots) { 793230592Sken start_idx = (map_idx - num_found) + 1; 794230592Sken return start_idx; 795230592Sken } 796230592Sken } else 797230592Sken num_found = 0; 798230592Sken } 799230592Sken 800230592Sken while (!done_flag) { 801230592Sken enc_idx = _mapping_get_high_missing_et_idx(sc); 802230592Sken if (enc_idx == MPS_ENCTABLE_BAD_IDX) 803230592Sken return MPS_MAPTABLE_BAD_IDX; 804230592Sken enc_entry = &sc->enclosure_table[enc_idx]; 805230592Sken /*VSP FIXME*/ 806230592Sken enc_entry->skip_search = 1; 807230592Sken mt_entry = &sc->mapping_table[enc_entry->start_index]; 808230592Sken for (map_idx = enc_entry->start_index; map_idx < 809230592Sken (enc_entry->start_index + enc_entry->num_slots); map_idx++, 810230592Sken mt_entry++) 811230592Sken mt_entry->device_info &= ~MPS_DEV_RESERVED; 812230592Sken found_space = 0; 813230592Sken for (map_idx = (max_num_phy_ids + 814230592Sken skip_count); map_idx < end_of_table; map_idx++) { 815230592Sken mt_entry = &sc->mapping_table[map_idx]; 816230592Sken if (!(mt_entry->device_info & MPS_DEV_RESERVED)) { 817230592Sken num_found += 1; 818230592Sken if (num_found == et_entry->num_slots) { 819230592Sken start_idx = (map_idx - num_found) + 1; 820230592Sken found_space = 1; 821230592Sken } 822230592Sken } else 823230592Sken num_found = 0; 824230592Sken } 825230592Sken 826230592Sken if (!found_space) 827230592Sken continue; 828230592Sken for (map_idx = start_idx; map_idx < (start_idx + num_found); 829230592Sken map_idx++) { 830230592Sken enc_entry = sc->enclosure_table; 831230592Sken for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; 832230592Sken enc_idx++, enc_entry++) { 833230592Sken if (map_idx < enc_entry->start_index || 834230592Sken map_idx > (enc_entry->start_index + 835230592Sken enc_entry->num_slots)) 836230592Sken continue; 837230592Sken if (!enc_entry->removal_flag) { 838230592Sken enc_entry->removal_flag = 1; 839230592Sken _mapping_add_to_removal_table(sc, 0, 840230592Sken enc_entry->dpm_entry_num); 841230592Sken } 842230592Sken mt_entry = &sc->mapping_table[map_idx]; 843230592Sken if (mt_entry->device_info & 844230592Sken MPS_MAP_IN_USE) { 845230592Sken _mapping_add_to_removal_table(sc, 846230592Sken mt_entry->dev_handle, 0); 847230592Sken _mapping_clear_map_entry(mt_entry); 848230592Sken } 849230592Sken if (map_idx == (enc_entry->start_index + 850230592Sken enc_entry->num_slots - 1)) 851230592Sken _mapping_clear_enc_entry(et_entry); 852230592Sken } 853230592Sken } 854230592Sken enc_entry = sc->enclosure_table; 855230592Sken for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; 856230592Sken enc_idx++, enc_entry++) { 857230592Sken if (!enc_entry->removal_flag) { 858230592Sken mt_entry = &sc->mapping_table[enc_entry-> 859230592Sken start_index]; 860230592Sken for (map_idx = enc_entry->start_index; map_idx < 861230592Sken (enc_entry->start_index + 862230592Sken enc_entry->num_slots); map_idx++, 863230592Sken mt_entry++) 864230592Sken mt_entry->device_info |= 865230592Sken MPS_DEV_RESERVED; 866230592Sken et_entry->skip_search = 0; 867230592Sken } 868230592Sken } 869230592Sken done_flag = 1; 870230592Sken } 871230592Sken return start_idx; 872230592Sken} 873230592Sken 874230592Sken/** 875230592Sken * _mapping_get_dev_info -get information about newly added devices 876230592Sken * @sc: per adapter object 877230592Sken * @topo_change: Topology change event entry 878230592Sken * 879230592Sken * Search through the topology change event list and issues sas device pg0 880230592Sken * requests for the newly added device and reserved entries in tables 881230592Sken * 882230592Sken * Returns nothing 883230592Sken */ 884230592Skenstatic void 885230592Sken_mapping_get_dev_info(struct mps_softc *sc, 886230592Sken struct _map_topology_change *topo_change) 887230592Sken{ 888230592Sken u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 889230592Sken Mpi2ConfigReply_t mpi_reply; 890230592Sken Mpi2SasDevicePage0_t sas_device_pg0; 891230592Sken u8 entry, enc_idx, phy_idx; 892230592Sken u32 map_idx, index, device_info; 893230592Sken struct _map_phy_change *phy_change, *tmp_phy_change; 894230592Sken uint64_t sas_address; 895230592Sken struct enc_mapping_table *et_entry; 896230592Sken struct dev_mapping_table *mt_entry; 897230592Sken u8 add_code = MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED; 898230592Sken int rc; 899230592Sken 900230592Sken for (entry = 0; entry < topo_change->num_entries; entry++) { 901230592Sken phy_change = &topo_change->phy_details[entry]; 902230592Sken if (phy_change->is_processed || !phy_change->dev_handle || 903230592Sken phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED) 904230592Sken continue; 905230592Sken if (mps_config_get_sas_device_pg0(sc, &mpi_reply, 906230592Sken &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, 907230592Sken phy_change->dev_handle)) { 908230592Sken phy_change->is_processed = 1; 909230592Sken continue; 910230592Sken } 911230592Sken 912230592Sken device_info = le32toh(sas_device_pg0.DeviceInfo); 913230592Sken if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 914230592Sken MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { 915230592Sken if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) && 916230592Sken (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) { 917230592Sken rc = mpssas_get_sas_address_for_sata_disk(sc, 918230592Sken &sas_address, phy_change->dev_handle, 919230592Sken device_info); 920230592Sken if (rc) { 921230592Sken printf("%s: failed to compute the " 922230592Sken "hashed SAS Address for SATA " 923230592Sken "device with handle 0x%04x\n", 924230592Sken __func__, phy_change->dev_handle); 925230592Sken sas_address = 926230592Sken sas_device_pg0.SASAddress.High; 927230592Sken sas_address = (sas_address << 32) | 928230592Sken sas_device_pg0.SASAddress.Low; 929230592Sken } 930254938Sken mps_dprint(sc, MPS_MAPPING, 931254938Sken "SAS Address for SATA device = %jx\n", 932254938Sken sas_address); 933230592Sken } else { 934230592Sken sas_address = 935230592Sken sas_device_pg0.SASAddress.High; 936230592Sken sas_address = (sas_address << 32) | 937230592Sken sas_device_pg0.SASAddress.Low; 938230592Sken } 939230592Sken } else { 940230592Sken sas_address = sas_device_pg0.SASAddress.High; 941230592Sken sas_address = (sas_address << 32) | 942230592Sken sas_device_pg0.SASAddress.Low; 943230592Sken } 944230592Sken phy_change->physical_id = sas_address; 945230592Sken phy_change->slot = le16toh(sas_device_pg0.Slot); 946230592Sken phy_change->device_info = 947230592Sken le32toh(sas_device_pg0.DeviceInfo); 948230592Sken 949230592Sken if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 950230592Sken MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 951230592Sken enc_idx = _mapping_get_enc_idx_from_handle(sc, 952230592Sken topo_change->enc_handle); 953230592Sken if (enc_idx == MPS_ENCTABLE_BAD_IDX) { 954230592Sken phy_change->is_processed = 1; 955230592Sken printf("%s: failed to add the device with " 956230592Sken "handle 0x%04x because the enclosure is " 957230592Sken "not in the mapping table\n", __func__, 958230592Sken phy_change->dev_handle); 959230592Sken continue; 960230592Sken } 961230592Sken if (!((phy_change->device_info & 962230592Sken MPI2_SAS_DEVICE_INFO_END_DEVICE) && 963230592Sken (phy_change->device_info & 964230592Sken (MPI2_SAS_DEVICE_INFO_SSP_TARGET | 965230592Sken MPI2_SAS_DEVICE_INFO_STP_TARGET | 966230592Sken MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))) { 967230592Sken phy_change->is_processed = 1; 968230592Sken continue; 969230592Sken } 970230592Sken et_entry = &sc->enclosure_table[enc_idx]; 971230592Sken if (et_entry->start_index != MPS_MAPTABLE_BAD_IDX) 972230592Sken continue; 973230592Sken if (!topo_change->exp_handle) { 974230592Sken map_idx = sc->num_rsvd_entries; 975230592Sken et_entry->start_index = map_idx; 976230592Sken } else { 977230592Sken map_idx = _mapping_find_enc_map_space(sc, 978230592Sken et_entry); 979230592Sken et_entry->start_index = map_idx; 980230592Sken if (et_entry->start_index == 981230592Sken MPS_MAPTABLE_BAD_IDX) { 982230592Sken phy_change->is_processed = 1; 983230592Sken for (phy_idx = 0; phy_idx < 984230592Sken topo_change->num_entries; 985230592Sken phy_idx++) { 986230592Sken tmp_phy_change = 987230592Sken &topo_change->phy_details 988230592Sken [phy_idx]; 989230592Sken if (tmp_phy_change->reason == 990230592Sken add_code) 991230592Sken tmp_phy_change-> 992230592Sken is_processed = 1; 993230592Sken } 994230592Sken break; 995230592Sken } 996230592Sken } 997230592Sken mt_entry = &sc->mapping_table[map_idx]; 998230592Sken for (index = map_idx; index < (et_entry->num_slots 999230592Sken + map_idx); index++, mt_entry++) { 1000230592Sken mt_entry->device_info = MPS_DEV_RESERVED; 1001230592Sken mt_entry->physical_id = et_entry->enclosure_id; 1002230592Sken mt_entry->phy_bits = et_entry->phy_bits; 1003230592Sken } 1004230592Sken } 1005230592Sken } 1006230592Sken} 1007230592Sken 1008230592Sken/** 1009230592Sken * _mapping_set_mid_to_eid -set map table data from enclosure table 1010230592Sken * @sc: per adapter object 1011230592Sken * @et_entry: enclosure entry 1012230592Sken * 1013230592Sken * Returns nothing 1014230592Sken */ 1015230592Skenstatic inline void 1016230592Sken_mapping_set_mid_to_eid(struct mps_softc *sc, 1017230592Sken struct enc_mapping_table *et_entry) 1018230592Sken{ 1019230592Sken struct dev_mapping_table *mt_entry; 1020230592Sken u16 slots = et_entry->num_slots, map_idx; 1021230592Sken u32 start_idx = et_entry->start_index; 1022230592Sken if (start_idx != MPS_MAPTABLE_BAD_IDX) { 1023230592Sken mt_entry = &sc->mapping_table[start_idx]; 1024230592Sken for (map_idx = 0; map_idx < slots; map_idx++, mt_entry++) 1025230592Sken mt_entry->physical_id = et_entry->enclosure_id; 1026230592Sken } 1027230592Sken} 1028230592Sken 1029230592Sken/** 1030230592Sken * _mapping_clear_removed_entries - mark the entries to be cleared 1031230592Sken * @sc: per adapter object 1032230592Sken * 1033230592Sken * Search through the removal table and mark the entries which needs to be 1034230592Sken * flushed to DPM and also updates the map table and enclosure table by 1035230592Sken * clearing the corresponding entries. 1036230592Sken * 1037230592Sken * Returns nothing 1038230592Sken */ 1039230592Skenstatic void 1040230592Sken_mapping_clear_removed_entries(struct mps_softc *sc) 1041230592Sken{ 1042230592Sken u32 remove_idx; 1043230592Sken struct map_removal_table *remove_entry; 1044230592Sken Mpi2DriverMap0Entry_t *dpm_entry; 1045230592Sken u8 done_flag = 0, num_entries, m, i; 1046230592Sken struct enc_mapping_table *et_entry, *from, *to; 1047230592Sken u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1048230592Sken 1049230592Sken if (sc->is_dpm_enable) { 1050230592Sken remove_entry = sc->removal_table; 1051230592Sken for (remove_idx = 0; remove_idx < sc->max_devices; 1052230592Sken remove_idx++, remove_entry++) { 1053230592Sken if (remove_entry->dpm_entry_num != MPS_DPM_BAD_IDX) { 1054230592Sken dpm_entry = (Mpi2DriverMap0Entry_t *) 1055230592Sken ((u8 *) sc->dpm_pg0 + 1056230592Sken sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 1057230592Sken dpm_entry += remove_entry->dpm_entry_num; 1058230592Sken dpm_entry->PhysicalIdentifier.Low = 0; 1059230592Sken dpm_entry->PhysicalIdentifier.High = 0; 1060230592Sken dpm_entry->DeviceIndex = 0; 1061230592Sken dpm_entry->MappingInformation = 0; 1062230592Sken dpm_entry->PhysicalBitsMapping = 0; 1063230592Sken sc->dpm_flush_entry[remove_entry-> 1064230592Sken dpm_entry_num] = 1; 1065230592Sken sc->dpm_entry_used[remove_entry->dpm_entry_num] 1066230592Sken = 0; 1067230592Sken remove_entry->dpm_entry_num = MPS_DPM_BAD_IDX; 1068230592Sken } 1069230592Sken } 1070230592Sken } 1071230592Sken if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1072230592Sken MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 1073230592Sken num_entries = sc->num_enc_table_entries; 1074230592Sken while (!done_flag) { 1075230592Sken done_flag = 1; 1076230592Sken et_entry = sc->enclosure_table; 1077230592Sken for (i = 0; i < num_entries; i++, et_entry++) { 1078230592Sken if (!et_entry->enc_handle && et_entry-> 1079230592Sken init_complete) { 1080230592Sken done_flag = 0; 1081230592Sken if (i != (num_entries - 1)) { 1082230592Sken from = &sc->enclosure_table 1083230592Sken [i+1]; 1084230592Sken to = &sc->enclosure_table[i]; 1085230592Sken for (m = i; m < (num_entries - 1086230592Sken 1); m++, from++, to++) { 1087230592Sken _mapping_set_mid_to_eid 1088230592Sken (sc, to); 1089230592Sken *to = *from; 1090230592Sken } 1091230592Sken _mapping_clear_enc_entry(to); 1092230592Sken sc->num_enc_table_entries--; 1093230592Sken num_entries = 1094230592Sken sc->num_enc_table_entries; 1095230592Sken } else { 1096230592Sken _mapping_clear_enc_entry 1097230592Sken (et_entry); 1098230592Sken sc->num_enc_table_entries--; 1099230592Sken num_entries = 1100230592Sken sc->num_enc_table_entries; 1101230592Sken } 1102230592Sken } 1103230592Sken } 1104230592Sken } 1105230592Sken } 1106230592Sken} 1107230592Sken 1108230592Sken/** 1109230592Sken * _mapping_add_new_device -Add the new device into mapping table 1110230592Sken * @sc: per adapter object 1111230592Sken * @topo_change: Topology change event entry 1112230592Sken * 1113230592Sken * Search through the topology change event list and updates map table, 1114230592Sken * enclosure table and DPM pages for for the newly added devices. 1115230592Sken * 1116230592Sken * Returns nothing 1117230592Sken */ 1118230592Skenstatic void 1119230592Sken_mapping_add_new_device(struct mps_softc *sc, 1120230592Sken struct _map_topology_change *topo_change) 1121230592Sken{ 1122230592Sken u8 enc_idx, missing_cnt, is_removed = 0; 1123230592Sken u16 dpm_idx; 1124230592Sken u32 search_idx, map_idx; 1125230592Sken u32 entry; 1126230592Sken struct dev_mapping_table *mt_entry; 1127230592Sken struct enc_mapping_table *et_entry; 1128230592Sken struct _map_phy_change *phy_change; 1129230592Sken u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1130230592Sken Mpi2DriverMap0Entry_t *dpm_entry; 1131230592Sken uint64_t temp64_var; 1132230592Sken u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT; 1133230592Sken u8 hdr_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER); 1134230592Sken u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs); 1135230592Sken 1136230592Sken for (entry = 0; entry < topo_change->num_entries; entry++) { 1137230592Sken phy_change = &topo_change->phy_details[entry]; 1138230592Sken if (phy_change->is_processed) 1139230592Sken continue; 1140230592Sken if (phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED || 1141230592Sken !phy_change->dev_handle) { 1142230592Sken phy_change->is_processed = 1; 1143230592Sken continue; 1144230592Sken } 1145230592Sken if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1146230592Sken MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 1147230592Sken enc_idx = _mapping_get_enc_idx_from_handle 1148230592Sken (sc, topo_change->enc_handle); 1149230592Sken if (enc_idx == MPS_ENCTABLE_BAD_IDX) { 1150230592Sken phy_change->is_processed = 1; 1151230592Sken printf("%s: failed to add the device with " 1152230592Sken "handle 0x%04x because the enclosure is " 1153230592Sken "not in the mapping table\n", __func__, 1154230592Sken phy_change->dev_handle); 1155230592Sken continue; 1156230592Sken } 1157230592Sken et_entry = &sc->enclosure_table[enc_idx]; 1158230592Sken if (et_entry->start_index == MPS_MAPTABLE_BAD_IDX) { 1159230592Sken phy_change->is_processed = 1; 1160230592Sken if (!sc->mt_full_retry) { 1161230592Sken sc->mt_add_device_failed = 1; 1162230592Sken continue; 1163230592Sken } 1164230592Sken printf("%s: failed to add the device with " 1165230592Sken "handle 0x%04x because there is no free " 1166230592Sken "space available in the mapping table\n", 1167230592Sken __func__, phy_change->dev_handle); 1168230592Sken continue; 1169230592Sken } 1170230592Sken map_idx = et_entry->start_index + phy_change->slot - 1171230592Sken et_entry->start_slot; 1172230592Sken mt_entry = &sc->mapping_table[map_idx]; 1173230592Sken mt_entry->physical_id = phy_change->physical_id; 1174230592Sken mt_entry->channel = 0; 1175230592Sken mt_entry->id = map_idx; 1176230592Sken mt_entry->dev_handle = phy_change->dev_handle; 1177230592Sken mt_entry->missing_count = 0; 1178230592Sken mt_entry->dpm_entry_num = et_entry->dpm_entry_num; 1179230592Sken mt_entry->device_info = phy_change->device_info | 1180230592Sken (MPS_DEV_RESERVED | MPS_MAP_IN_USE); 1181230592Sken if (sc->is_dpm_enable) { 1182230592Sken dpm_idx = et_entry->dpm_entry_num; 1183230592Sken if (dpm_idx == MPS_DPM_BAD_IDX) 1184230592Sken dpm_idx = _mapping_get_dpm_idx_from_id 1185230592Sken (sc, et_entry->enclosure_id, 1186230592Sken et_entry->phy_bits); 1187230592Sken if (dpm_idx == MPS_DPM_BAD_IDX) { 1188230592Sken dpm_idx = _mapping_get_free_dpm_idx(sc); 1189230592Sken if (dpm_idx != MPS_DPM_BAD_IDX) { 1190230592Sken dpm_entry = 1191230592Sken (Mpi2DriverMap0Entry_t *) 1192230592Sken ((u8 *) sc->dpm_pg0 + 1193230592Sken hdr_sz); 1194230592Sken dpm_entry += dpm_idx; 1195230592Sken dpm_entry-> 1196230592Sken PhysicalIdentifier.Low = 1197230592Sken (0xFFFFFFFF & 1198230592Sken et_entry->enclosure_id); 1199230592Sken dpm_entry-> 1200230592Sken PhysicalIdentifier.High = 1201230592Sken ( et_entry->enclosure_id 1202230592Sken >> 32); 1203230592Sken dpm_entry->DeviceIndex = 1204230592Sken (U16)et_entry->start_index; 1205230592Sken dpm_entry->MappingInformation = 1206230592Sken et_entry->num_slots; 1207230592Sken dpm_entry->MappingInformation 1208230592Sken <<= map_shift; 1209230592Sken dpm_entry->PhysicalBitsMapping 1210230592Sken = et_entry->phy_bits; 1211230592Sken et_entry->dpm_entry_num = 1212230592Sken dpm_idx; 1213230592Sken /* FIXME Do I need to set the dpm_idxin mt_entry too */ 1214230592Sken sc->dpm_entry_used[dpm_idx] = 1; 1215230592Sken sc->dpm_flush_entry[dpm_idx] = 1216230592Sken 1; 1217230592Sken phy_change->is_processed = 1; 1218230592Sken } else { 1219230592Sken phy_change->is_processed = 1; 1220254938Sken mps_dprint(sc, MPS_INFO, "%s: " 1221254938Sken "failed to add the device " 1222254938Sken "with handle 0x%04x to " 1223254938Sken "persistent table because " 1224254938Sken "there is no free space " 1225254938Sken "available\n", __func__, 1226230592Sken phy_change->dev_handle); 1227230592Sken } 1228230592Sken } else { 1229230592Sken et_entry->dpm_entry_num = dpm_idx; 1230230592Sken mt_entry->dpm_entry_num = dpm_idx; 1231230592Sken } 1232230592Sken } 1233230592Sken /* FIXME Why not mt_entry too? */ 1234230592Sken et_entry->init_complete = 1; 1235230592Sken } else if ((ioc_pg8_flags & 1236230592Sken MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1237230592Sken MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { 1238230592Sken map_idx = _mapping_get_mt_idx_from_id 1239230592Sken (sc, phy_change->physical_id); 1240230592Sken if (map_idx == MPS_MAPTABLE_BAD_IDX) { 1241230592Sken search_idx = sc->num_rsvd_entries; 1242230592Sken if (topo_change->exp_handle) 1243230592Sken search_idx += max_num_phy_ids; 1244230592Sken map_idx = _mapping_get_free_mt_idx(sc, 1245230592Sken search_idx); 1246230592Sken } 1247230592Sken if (map_idx == MPS_MAPTABLE_BAD_IDX) { 1248230592Sken map_idx = _mapping_get_high_missing_mt_idx(sc); 1249230592Sken if (map_idx != MPS_MAPTABLE_BAD_IDX) { 1250230592Sken mt_entry = &sc->mapping_table[map_idx]; 1251230592Sken if (mt_entry->dev_handle) { 1252230592Sken _mapping_add_to_removal_table 1253230592Sken (sc, mt_entry->dev_handle, 1254230592Sken 0); 1255230592Sken is_removed = 1; 1256230592Sken } 1257230592Sken mt_entry->init_complete = 0; 1258230592Sken } 1259230592Sken } 1260230592Sken if (map_idx != MPS_MAPTABLE_BAD_IDX) { 1261230592Sken mt_entry = &sc->mapping_table[map_idx]; 1262230592Sken mt_entry->physical_id = phy_change->physical_id; 1263230592Sken mt_entry->channel = 0; 1264230592Sken mt_entry->id = map_idx; 1265230592Sken mt_entry->dev_handle = phy_change->dev_handle; 1266230592Sken mt_entry->missing_count = 0; 1267230592Sken mt_entry->device_info = phy_change->device_info 1268230592Sken | (MPS_DEV_RESERVED | MPS_MAP_IN_USE); 1269230592Sken } else { 1270230592Sken phy_change->is_processed = 1; 1271230592Sken if (!sc->mt_full_retry) { 1272230592Sken sc->mt_add_device_failed = 1; 1273230592Sken continue; 1274230592Sken } 1275230592Sken printf("%s: failed to add the device with " 1276230592Sken "handle 0x%04x because there is no free " 1277230592Sken "space available in the mapping table\n", 1278230592Sken __func__, phy_change->dev_handle); 1279230592Sken continue; 1280230592Sken } 1281230592Sken if (sc->is_dpm_enable) { 1282230592Sken if (mt_entry->dpm_entry_num != 1283230592Sken MPS_DPM_BAD_IDX) { 1284230592Sken dpm_idx = mt_entry->dpm_entry_num; 1285230592Sken dpm_entry = (Mpi2DriverMap0Entry_t *) 1286230592Sken ((u8 *)sc->dpm_pg0 + hdr_sz); 1287230592Sken dpm_entry += dpm_idx; 1288230592Sken missing_cnt = dpm_entry-> 1289230592Sken MappingInformation & 1290230592Sken MPI2_DRVMAP0_MAPINFO_MISSING_MASK; 1291230592Sken temp64_var = dpm_entry-> 1292230592Sken PhysicalIdentifier.High; 1293230592Sken temp64_var = (temp64_var << 32) | 1294230592Sken dpm_entry->PhysicalIdentifier.Low; 1295230592Sken if ((mt_entry->physical_id == 1296230592Sken temp64_var) && !missing_cnt) 1297230592Sken mt_entry->init_complete = 1; 1298230592Sken } else { 1299230592Sken dpm_idx = _mapping_get_free_dpm_idx(sc); 1300230592Sken mt_entry->init_complete = 0; 1301230592Sken } 1302230592Sken if (dpm_idx != MPS_DPM_BAD_IDX && 1303230592Sken !mt_entry->init_complete) { 1304230592Sken mt_entry->init_complete = 1; 1305230592Sken mt_entry->dpm_entry_num = dpm_idx; 1306230592Sken dpm_entry = (Mpi2DriverMap0Entry_t *) 1307230592Sken ((u8 *)sc->dpm_pg0 + hdr_sz); 1308230592Sken dpm_entry += dpm_idx; 1309230592Sken dpm_entry->PhysicalIdentifier.Low = 1310230592Sken (0xFFFFFFFF & 1311230592Sken mt_entry->physical_id); 1312230592Sken dpm_entry->PhysicalIdentifier.High = 1313230592Sken (mt_entry->physical_id >> 32); 1314230592Sken dpm_entry->DeviceIndex = (U16) map_idx; 1315230592Sken dpm_entry->MappingInformation = 0; 1316230592Sken dpm_entry->PhysicalBitsMapping = 0; 1317230592Sken sc->dpm_entry_used[dpm_idx] = 1; 1318230592Sken sc->dpm_flush_entry[dpm_idx] = 1; 1319230592Sken phy_change->is_processed = 1; 1320230592Sken } else if (dpm_idx == MPS_DPM_BAD_IDX) { 1321230592Sken phy_change->is_processed = 1; 1322254938Sken mps_dprint(sc, MPS_INFO, "%s: " 1323254938Sken "failed to add the device " 1324254938Sken "with handle 0x%04x to " 1325254938Sken "persistent table because " 1326254938Sken "there is no free space " 1327254938Sken "available\n", __func__, 1328230592Sken phy_change->dev_handle); 1329230592Sken } 1330230592Sken } 1331230592Sken mt_entry->init_complete = 1; 1332230592Sken } 1333230592Sken 1334230592Sken phy_change->is_processed = 1; 1335230592Sken } 1336230592Sken if (is_removed) 1337230592Sken _mapping_clear_removed_entries(sc); 1338230592Sken} 1339230592Sken 1340230592Sken/** 1341230592Sken * _mapping_flush_dpm_pages -Flush the DPM pages to NVRAM 1342230592Sken * @sc: per adapter object 1343230592Sken * 1344230592Sken * Returns nothing 1345230592Sken */ 1346230592Skenstatic void 1347230592Sken_mapping_flush_dpm_pages(struct mps_softc *sc) 1348230592Sken{ 1349230592Sken Mpi2DriverMap0Entry_t *dpm_entry; 1350230592Sken Mpi2ConfigReply_t mpi_reply; 1351230592Sken Mpi2DriverMappingPage0_t config_page; 1352230592Sken u16 entry_num; 1353230592Sken 1354230592Sken for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) { 1355230592Sken if (!sc->dpm_flush_entry[entry_num]) 1356230592Sken continue; 1357230592Sken memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t)); 1358230592Sken memcpy(&config_page.Header, (u8 *)sc->dpm_pg0, 1359230592Sken sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 1360230592Sken dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 + 1361230592Sken sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 1362230592Sken dpm_entry += entry_num; 1363230592Sken dpm_entry->MappingInformation = htole16(dpm_entry-> 1364230592Sken MappingInformation); 1365230592Sken dpm_entry->DeviceIndex = htole16(dpm_entry->DeviceIndex); 1366230592Sken dpm_entry->PhysicalBitsMapping = htole32(dpm_entry-> 1367230592Sken PhysicalBitsMapping); 1368230592Sken memcpy(&config_page.Entry, (u8 *)dpm_entry, 1369230592Sken sizeof(Mpi2DriverMap0Entry_t)); 1370230592Sken /* TODO-How to handle failed writes? */ 1371230592Sken if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page, 1372230592Sken entry_num)) { 1373230592Sken printf("%s: write of dpm entry %d for device failed\n", 1374230592Sken __func__, entry_num); 1375230592Sken } else 1376230592Sken sc->dpm_flush_entry[entry_num] = 0; 1377230592Sken dpm_entry->MappingInformation = le16toh(dpm_entry-> 1378230592Sken MappingInformation); 1379230592Sken dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex); 1380230592Sken dpm_entry->PhysicalBitsMapping = le32toh(dpm_entry-> 1381230592Sken PhysicalBitsMapping); 1382230592Sken } 1383230592Sken} 1384230592Sken 1385230592Sken/** 1386230592Sken * _mapping_allocate_memory- allocates the memory required for mapping tables 1387230592Sken * @sc: per adapter object 1388230592Sken * 1389230592Sken * Allocates the memory for all the tables required for host mapping 1390230592Sken * 1391230592Sken * Return 0 on success or non-zero on failure. 1392230592Sken */ 1393230592Skenint 1394230592Skenmps_mapping_allocate_memory(struct mps_softc *sc) 1395230592Sken{ 1396230592Sken uint32_t dpm_pg0_sz; 1397230592Sken 1398230592Sken sc->mapping_table = malloc((sizeof(struct dev_mapping_table) * 1399230592Sken sc->max_devices), M_MPT2, M_ZERO|M_NOWAIT); 1400230592Sken if (!sc->mapping_table) 1401230592Sken goto free_resources; 1402230592Sken 1403230592Sken sc->removal_table = malloc((sizeof(struct map_removal_table) * 1404230592Sken sc->max_devices), M_MPT2, M_ZERO|M_NOWAIT); 1405230592Sken if (!sc->removal_table) 1406230592Sken goto free_resources; 1407230592Sken 1408230592Sken sc->enclosure_table = malloc((sizeof(struct enc_mapping_table) * 1409230592Sken sc->max_enclosures), M_MPT2, M_ZERO|M_NOWAIT); 1410230592Sken if (!sc->enclosure_table) 1411230592Sken goto free_resources; 1412230592Sken 1413230592Sken sc->dpm_entry_used = malloc((sizeof(u8) * sc->max_dpm_entries), 1414230592Sken M_MPT2, M_ZERO|M_NOWAIT); 1415230592Sken if (!sc->dpm_entry_used) 1416230592Sken goto free_resources; 1417230592Sken 1418230592Sken sc->dpm_flush_entry = malloc((sizeof(u8) * sc->max_dpm_entries), 1419230592Sken M_MPT2, M_ZERO|M_NOWAIT); 1420230592Sken if (!sc->dpm_flush_entry) 1421230592Sken goto free_resources; 1422230592Sken 1423230592Sken dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) + 1424230592Sken (sc->max_dpm_entries * sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY)); 1425230592Sken 1426230592Sken sc->dpm_pg0 = malloc(dpm_pg0_sz, M_MPT2, M_ZERO|M_NOWAIT); 1427230592Sken if (!sc->dpm_pg0) { 1428230592Sken printf("%s: memory alloc failed for dpm page; disabling dpm\n", 1429230592Sken __func__); 1430230592Sken sc->is_dpm_enable = 0; 1431230592Sken } 1432230592Sken 1433230592Sken return 0; 1434230592Sken 1435230592Skenfree_resources: 1436230592Sken free(sc->mapping_table, M_MPT2); 1437230592Sken free(sc->removal_table, M_MPT2); 1438230592Sken free(sc->enclosure_table, M_MPT2); 1439230592Sken free(sc->dpm_entry_used, M_MPT2); 1440230592Sken free(sc->dpm_flush_entry, M_MPT2); 1441230592Sken free(sc->dpm_pg0, M_MPT2); 1442230592Sken printf("%s: device initialization failed due to failure in mapping " 1443230592Sken "table memory allocation\n", __func__); 1444230592Sken return -1; 1445230592Sken} 1446230592Sken 1447230592Sken/** 1448230592Sken * mps_mapping_free_memory- frees the memory allocated for mapping tables 1449230592Sken * @sc: per adapter object 1450230592Sken * 1451230592Sken * Returns nothing. 1452230592Sken */ 1453230592Skenvoid 1454230592Skenmps_mapping_free_memory(struct mps_softc *sc) 1455230592Sken{ 1456230592Sken free(sc->mapping_table, M_MPT2); 1457230592Sken free(sc->removal_table, M_MPT2); 1458230592Sken free(sc->enclosure_table, M_MPT2); 1459230592Sken free(sc->dpm_entry_used, M_MPT2); 1460230592Sken free(sc->dpm_flush_entry, M_MPT2); 1461230592Sken free(sc->dpm_pg0, M_MPT2); 1462230592Sken} 1463230592Sken 1464230592Sken 1465230592Skenstatic void 1466230592Sken_mapping_process_dpm_pg0(struct mps_softc *sc) 1467230592Sken{ 1468230592Sken u8 missing_cnt, enc_idx; 1469230592Sken u16 slot_id, entry_num, num_slots; 1470230592Sken u32 map_idx, dev_idx, start_idx, end_idx; 1471230592Sken struct dev_mapping_table *mt_entry; 1472230592Sken Mpi2DriverMap0Entry_t *dpm_entry; 1473230592Sken u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1474230592Sken u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs); 1475230592Sken struct enc_mapping_table *et_entry; 1476230592Sken u64 physical_id; 1477230592Sken u32 phy_bits = 0; 1478230592Sken 1479230592Sken if (sc->ir_firmware) 1480230592Sken _mapping_get_ir_maprange(sc, &start_idx, &end_idx); 1481230592Sken 1482230592Sken dpm_entry = (Mpi2DriverMap0Entry_t *) ((uint8_t *) sc->dpm_pg0 + 1483230592Sken sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 1484230592Sken for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++, 1485230592Sken dpm_entry++) { 1486230592Sken physical_id = dpm_entry->PhysicalIdentifier.High; 1487230592Sken physical_id = (physical_id << 32) | 1488230592Sken dpm_entry->PhysicalIdentifier.Low; 1489230592Sken if (!physical_id) { 1490230592Sken sc->dpm_entry_used[entry_num] = 0; 1491230592Sken continue; 1492230592Sken } 1493230592Sken sc->dpm_entry_used[entry_num] = 1; 1494230592Sken dpm_entry->MappingInformation = le16toh(dpm_entry-> 1495230592Sken MappingInformation); 1496230592Sken missing_cnt = dpm_entry->MappingInformation & 1497230592Sken MPI2_DRVMAP0_MAPINFO_MISSING_MASK; 1498230592Sken dev_idx = le16toh(dpm_entry->DeviceIndex); 1499230592Sken phy_bits = le32toh(dpm_entry->PhysicalBitsMapping); 1500230592Sken if (sc->ir_firmware && (dev_idx >= start_idx) && 1501230592Sken (dev_idx <= end_idx)) { 1502230592Sken mt_entry = &sc->mapping_table[dev_idx]; 1503230592Sken mt_entry->physical_id = dpm_entry->PhysicalIdentifier.High; 1504230592Sken mt_entry->physical_id = (mt_entry->physical_id << 32) | 1505230592Sken dpm_entry->PhysicalIdentifier.Low; 1506230592Sken mt_entry->channel = MPS_RAID_CHANNEL; 1507230592Sken mt_entry->id = dev_idx; 1508230592Sken mt_entry->missing_count = missing_cnt; 1509230592Sken mt_entry->dpm_entry_num = entry_num; 1510230592Sken mt_entry->device_info = MPS_DEV_RESERVED; 1511230592Sken continue; 1512230592Sken } 1513230592Sken if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1514230592Sken MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 1515230592Sken if (dev_idx < (sc->num_rsvd_entries + 1516230592Sken max_num_phy_ids)) { 1517230592Sken slot_id = 0; 1518230592Sken if (ioc_pg8_flags & 1519230592Sken MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1) 1520230592Sken slot_id = 1; 1521230592Sken num_slots = max_num_phy_ids; 1522230592Sken } else { 1523230592Sken slot_id = 0; 1524230592Sken num_slots = dpm_entry->MappingInformation & 1525230592Sken MPI2_DRVMAP0_MAPINFO_SLOT_MASK; 1526230592Sken num_slots >>= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT; 1527230592Sken } 1528230592Sken enc_idx = sc->num_enc_table_entries; 1529230592Sken if (enc_idx >= sc->max_enclosures) { 1530230592Sken printf("%s: enclosure entries exceed max " 1531230592Sken "enclosures of %d\n", __func__, 1532230592Sken sc->max_enclosures); 1533230592Sken break; 1534230592Sken } 1535230592Sken sc->num_enc_table_entries++; 1536230592Sken et_entry = &sc->enclosure_table[enc_idx]; 1537230592Sken physical_id = dpm_entry->PhysicalIdentifier.High; 1538230592Sken et_entry->enclosure_id = (physical_id << 32) | 1539230592Sken dpm_entry->PhysicalIdentifier.Low; 1540230592Sken et_entry->start_index = dev_idx; 1541230592Sken et_entry->dpm_entry_num = entry_num; 1542230592Sken et_entry->num_slots = num_slots; 1543230592Sken et_entry->start_slot = slot_id; 1544230592Sken et_entry->missing_count = missing_cnt; 1545230592Sken et_entry->phy_bits = phy_bits; 1546230592Sken 1547230592Sken mt_entry = &sc->mapping_table[dev_idx]; 1548230592Sken for (map_idx = dev_idx; map_idx < (dev_idx + num_slots); 1549230592Sken map_idx++, mt_entry++) { 1550230592Sken if (mt_entry->dpm_entry_num != 1551230592Sken MPS_DPM_BAD_IDX) { 1552230592Sken printf("%s: conflict in mapping table " 1553230592Sken "for enclosure %d\n", __func__, 1554230592Sken enc_idx); 1555230592Sken break; 1556230592Sken } 1557230592Sken physical_id = dpm_entry->PhysicalIdentifier.High; 1558230592Sken mt_entry->physical_id = (physical_id << 32) | 1559230592Sken dpm_entry->PhysicalIdentifier.Low; 1560230592Sken mt_entry->phy_bits = phy_bits; 1561230592Sken mt_entry->channel = 0; 1562230592Sken mt_entry->id = dev_idx; 1563230592Sken mt_entry->dpm_entry_num = entry_num; 1564230592Sken mt_entry->missing_count = missing_cnt; 1565230592Sken mt_entry->device_info = MPS_DEV_RESERVED; 1566230592Sken } 1567230592Sken } else if ((ioc_pg8_flags & 1568230592Sken MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1569230592Sken MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { 1570230592Sken map_idx = dev_idx; 1571230592Sken mt_entry = &sc->mapping_table[map_idx]; 1572230592Sken if (mt_entry->dpm_entry_num != MPS_DPM_BAD_IDX) { 1573230592Sken printf("%s: conflict in mapping table for " 1574230592Sken "device %d\n", __func__, map_idx); 1575230592Sken break; 1576230592Sken } 1577230592Sken physical_id = dpm_entry->PhysicalIdentifier.High; 1578230592Sken mt_entry->physical_id = (physical_id << 32) | 1579230592Sken dpm_entry->PhysicalIdentifier.Low; 1580230592Sken mt_entry->phy_bits = phy_bits; 1581230592Sken mt_entry->channel = 0; 1582230592Sken mt_entry->id = dev_idx; 1583230592Sken mt_entry->missing_count = missing_cnt; 1584230592Sken mt_entry->dpm_entry_num = entry_num; 1585230592Sken mt_entry->device_info = MPS_DEV_RESERVED; 1586230592Sken } 1587230592Sken } /*close the loop for DPM table */ 1588230592Sken} 1589230592Sken 1590230592Sken/* 1591230592Sken * mps_mapping_check_devices - start of the day check for device availabilty 1592230592Sken * @sc: per adapter object 1593230592Sken * @sleep_flag: Flag indicating whether this function can sleep or not 1594230592Sken * 1595230592Sken * Returns nothing. 1596230592Sken */ 1597230592Skenvoid 1598230592Skenmps_mapping_check_devices(struct mps_softc *sc, int sleep_flag) 1599230592Sken{ 1600230592Sken u32 i; 1601230592Sken/* u32 cntdn, i; 1602230592Sken u32 timeout = 60;*/ 1603230592Sken struct dev_mapping_table *mt_entry; 1604230592Sken u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1605230592Sken struct enc_mapping_table *et_entry; 1606230592Sken u32 start_idx, end_idx; 1607230592Sken 1608230592Sken /* We need to ucomment this when this function is called 1609230592Sken * from the port enable complete */ 1610230592Sken#if 0 1611230592Sken sc->track_mapping_events = 0; 1612230592Sken cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; 1613230592Sken do { 1614230592Sken if (!sc->pending_map_events) 1615230592Sken break; 1616230592Sken if (sleep_flag == CAN_SLEEP) 1617230592Sken pause("mps_pause", (hz/1000));/* 1msec sleep */ 1618230592Sken else 1619230592Sken DELAY(500); /* 500 useconds delay */ 1620230592Sken } while (--cntdn); 1621230592Sken 1622230592Sken 1623230592Sken if (!cntdn) 1624230592Sken printf("%s: there are %d" 1625230592Sken " pending events after %d seconds of delay\n", 1626230592Sken __func__, sc->pending_map_events, timeout); 1627230592Sken#endif 1628230592Sken sc->pending_map_events = 0; 1629230592Sken 1630230592Sken if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1631230592Sken MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { 1632230592Sken et_entry = sc->enclosure_table; 1633230592Sken for (i = 0; i < sc->num_enc_table_entries; i++, et_entry++) { 1634230592Sken if (!et_entry->init_complete) { 1635230592Sken if (et_entry->missing_count < 1636230592Sken MPS_MAX_MISSING_COUNT) { 1637230592Sken et_entry->missing_count++; 1638230592Sken if (et_entry->dpm_entry_num != 1639230592Sken MPS_DPM_BAD_IDX) 1640230592Sken _mapping_commit_enc_entry(sc, 1641230592Sken et_entry); 1642230592Sken } 1643230592Sken et_entry->init_complete = 1; 1644230592Sken } 1645230592Sken } 1646230592Sken if (!sc->ir_firmware) 1647230592Sken return; 1648230592Sken _mapping_get_ir_maprange(sc, &start_idx, &end_idx); 1649230592Sken mt_entry = &sc->mapping_table[start_idx]; 1650230592Sken for (i = start_idx; i < (end_idx + 1); i++, mt_entry++) { 1651230592Sken if (mt_entry->device_info & MPS_DEV_RESERVED 1652230592Sken && !mt_entry->physical_id) 1653230592Sken mt_entry->init_complete = 1; 1654230592Sken else if (mt_entry->device_info & MPS_DEV_RESERVED) { 1655230592Sken if (!mt_entry->init_complete) { 1656230592Sken if (mt_entry->missing_count < 1657230592Sken MPS_MAX_MISSING_COUNT) { 1658230592Sken mt_entry->missing_count++; 1659230592Sken if (mt_entry->dpm_entry_num != 1660230592Sken MPS_DPM_BAD_IDX) 1661230592Sken _mapping_commit_map_entry(sc, 1662230592Sken mt_entry); 1663230592Sken } 1664230592Sken mt_entry->init_complete = 1; 1665230592Sken } 1666230592Sken } 1667230592Sken } 1668230592Sken } else if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == 1669230592Sken MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { 1670230592Sken mt_entry = sc->mapping_table; 1671230592Sken for (i = 0; i < sc->max_devices; i++, mt_entry++) { 1672230592Sken if (mt_entry->device_info & MPS_DEV_RESERVED 1673230592Sken && !mt_entry->physical_id) 1674230592Sken mt_entry->init_complete = 1; 1675230592Sken else if (mt_entry->device_info & MPS_DEV_RESERVED) { 1676230592Sken if (!mt_entry->init_complete) { 1677230592Sken if (mt_entry->missing_count < 1678230592Sken MPS_MAX_MISSING_COUNT) { 1679230592Sken mt_entry->missing_count++; 1680230592Sken if (mt_entry->dpm_entry_num != 1681230592Sken MPS_DPM_BAD_IDX) 1682230592Sken _mapping_commit_map_entry(sc, 1683230592Sken mt_entry); 1684230592Sken } 1685230592Sken mt_entry->init_complete = 1; 1686230592Sken } 1687230592Sken } 1688230592Sken } 1689230592Sken } 1690230592Sken} 1691230592Sken 1692230592Sken 1693230592Sken/** 1694230592Sken * mps_mapping_is_reinit_required - check whether event replay required 1695230592Sken * @sc: per adapter object 1696230592Sken * 1697230592Sken * Checks the per ioc flags and decide whether reinit of events required 1698230592Sken * 1699230592Sken * Returns 1 for reinit of ioc 0 for not. 1700230592Sken */ 1701230592Skenint mps_mapping_is_reinit_required(struct mps_softc *sc) 1702230592Sken{ 1703230592Sken if (!sc->mt_full_retry && sc->mt_add_device_failed) { 1704230592Sken sc->mt_full_retry = 1; 1705230592Sken sc->mt_add_device_failed = 0; 1706230592Sken _mapping_flush_dpm_pages(sc); 1707230592Sken return 1; 1708230592Sken } 1709230592Sken sc->mt_full_retry = 1; 1710230592Sken return 0; 1711230592Sken} 1712230592Sken 1713230592Sken/** 1714230592Sken * mps_mapping_initialize - initialize mapping tables 1715230592Sken * @sc: per adapter object 1716230592Sken * 1717230592Sken * Read controller persitant mapping tables into internal data area. 1718230592Sken * 1719230592Sken * Return 0 for success or non-zero for failure. 1720230592Sken */ 1721230592Skenint 1722230592Skenmps_mapping_initialize(struct mps_softc *sc) 1723230592Sken{ 1724230592Sken uint16_t volume_mapping_flags, dpm_pg0_sz; 1725230592Sken uint32_t i; 1726230592Sken Mpi2ConfigReply_t mpi_reply; 1727230592Sken int error; 1728230592Sken uint8_t retry_count; 1729230592Sken uint16_t ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1730230592Sken 1731230592Sken /* The additional 1 accounts for the virtual enclosure 1732230592Sken * created for the controller 1733230592Sken */ 1734230592Sken sc->max_enclosures = sc->facts->MaxEnclosures + 1; 1735230592Sken sc->max_expanders = sc->facts->MaxSasExpanders; 1736230592Sken sc->max_volumes = sc->facts->MaxVolumes; 1737230592Sken sc->max_devices = sc->facts->MaxTargets + sc->max_volumes; 1738230592Sken sc->pending_map_events = 0; 1739230592Sken sc->num_enc_table_entries = 0; 1740230592Sken sc->num_rsvd_entries = 0; 1741230592Sken sc->num_channels = 1; 1742230592Sken sc->max_dpm_entries = sc->ioc_pg8.MaxPersistentEntries; 1743230592Sken sc->is_dpm_enable = (sc->max_dpm_entries) ? 1 : 0; 1744230592Sken sc->track_mapping_events = 0; 1745230592Sken 1746230592Sken if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING) 1747230592Sken sc->is_dpm_enable = 0; 1748230592Sken 1749230592Sken if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0) 1750230592Sken sc->num_rsvd_entries = 1; 1751230592Sken 1752230592Sken volume_mapping_flags = sc->ioc_pg8.IRVolumeMappingFlags & 1753230592Sken MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; 1754230592Sken if (sc->ir_firmware && (volume_mapping_flags == 1755230592Sken MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING)) 1756230592Sken sc->num_rsvd_entries += sc->max_volumes; 1757230592Sken 1758230592Sken error = mps_mapping_allocate_memory(sc); 1759230592Sken if (error) 1760230592Sken return (error); 1761230592Sken 1762230592Sken for (i = 0; i < sc->max_devices; i++) 1763230592Sken _mapping_clear_map_entry(sc->mapping_table + i); 1764230592Sken 1765230592Sken for (i = 0; i < sc->max_enclosures; i++) 1766230592Sken _mapping_clear_enc_entry(sc->enclosure_table + i); 1767230592Sken 1768230592Sken for (i = 0; i < sc->max_devices; i++) { 1769230592Sken sc->removal_table[i].dev_handle = 0; 1770230592Sken sc->removal_table[i].dpm_entry_num = MPS_DPM_BAD_IDX; 1771230592Sken } 1772230592Sken 1773230592Sken memset(sc->dpm_entry_used, 0, sc->max_dpm_entries); 1774230592Sken memset(sc->dpm_flush_entry, 0, sc->max_dpm_entries); 1775230592Sken 1776230592Sken if (sc->is_dpm_enable) { 1777230592Sken dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) + 1778230592Sken (sc->max_dpm_entries * 1779230592Sken sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY)); 1780230592Sken retry_count = 0; 1781230592Sken 1782230592Skenretry_read_dpm: 1783230592Sken if (mps_config_get_dpm_pg0(sc, &mpi_reply, sc->dpm_pg0, 1784230592Sken dpm_pg0_sz)) { 1785230592Sken printf("%s: dpm page read failed; disabling dpm\n", 1786230592Sken __func__); 1787230592Sken if (retry_count < 3) { 1788230592Sken retry_count++; 1789230592Sken goto retry_read_dpm; 1790230592Sken } 1791230592Sken sc->is_dpm_enable = 0; 1792230592Sken } 1793230592Sken } 1794230592Sken 1795230592Sken if (sc->is_dpm_enable) 1796230592Sken _mapping_process_dpm_pg0(sc); 1797230592Sken 1798230592Sken sc->track_mapping_events = 1; 1799230592Sken return 0; 1800230592Sken} 1801230592Sken 1802230592Sken/** 1803230592Sken * mps_mapping_exit - clear mapping table and associated memory 1804230592Sken * @sc: per adapter object 1805230592Sken * 1806230592Sken * Returns nothing. 1807230592Sken */ 1808230592Skenvoid 1809230592Skenmps_mapping_exit(struct mps_softc *sc) 1810230592Sken{ 1811230592Sken _mapping_flush_dpm_pages(sc); 1812230592Sken mps_mapping_free_memory(sc); 1813230592Sken} 1814230592Sken 1815230592Sken/** 1816230592Sken * mps_mapping_get_sas_id - assign a target id for sas device 1817230592Sken * @sc: per adapter object 1818230592Sken * @sas_address: sas address of the device 1819230592Sken * @handle: device handle 1820230592Sken * 1821230592Sken * Returns valid ID on success or BAD_ID. 1822230592Sken */ 1823230592Skenunsigned int 1824230592Skenmps_mapping_get_sas_id(struct mps_softc *sc, uint64_t sas_address, u16 handle) 1825230592Sken{ 1826230592Sken u32 map_idx; 1827230592Sken struct dev_mapping_table *mt_entry; 1828230592Sken 1829230592Sken for (map_idx = 0; map_idx < sc->max_devices; map_idx++) { 1830230592Sken mt_entry = &sc->mapping_table[map_idx]; 1831230592Sken if (mt_entry->dev_handle == handle && mt_entry->physical_id == 1832230592Sken sas_address) 1833230592Sken return mt_entry->id; 1834230592Sken } 1835230592Sken 1836230592Sken return MPS_MAP_BAD_ID; 1837230592Sken} 1838230592Sken 1839230592Sken/** 1840230592Sken * mps_mapping_get_sas_id_from_handle - find a target id in mapping table using 1841230592Sken * only the dev handle. This is just a wrapper function for the local function 1842230592Sken * _mapping_get_mt_idx_from_handle. 1843230592Sken * @sc: per adapter object 1844230592Sken * @handle: device handle 1845230592Sken * 1846230592Sken * Returns valid ID on success or BAD_ID. 1847230592Sken */ 1848230592Skenunsigned int 1849230592Skenmps_mapping_get_sas_id_from_handle(struct mps_softc *sc, u16 handle) 1850230592Sken{ 1851230592Sken return (_mapping_get_mt_idx_from_handle(sc, handle)); 1852230592Sken} 1853230592Sken 1854230592Sken/** 1855230592Sken * mps_mapping_get_raid_id - assign a target id for raid device 1856230592Sken * @sc: per adapter object 1857230592Sken * @wwid: world wide identifier for raid volume 1858230592Sken * @handle: device handle 1859230592Sken * 1860230592Sken * Returns valid ID on success or BAD_ID. 1861230592Sken */ 1862230592Skenunsigned int 1863230592Skenmps_mapping_get_raid_id(struct mps_softc *sc, u64 wwid, u16 handle) 1864230592Sken{ 1865230592Sken u32 map_idx; 1866230592Sken struct dev_mapping_table *mt_entry; 1867230592Sken 1868230592Sken for (map_idx = 0; map_idx < sc->max_devices; map_idx++) { 1869230592Sken mt_entry = &sc->mapping_table[map_idx]; 1870230592Sken if (mt_entry->dev_handle == handle && mt_entry->physical_id == 1871230592Sken wwid) 1872230592Sken return mt_entry->id; 1873230592Sken } 1874230592Sken 1875230592Sken return MPS_MAP_BAD_ID; 1876230592Sken} 1877230592Sken 1878230592Sken/** 1879230592Sken * mps_mapping_get_raid_id_from_handle - find raid device in mapping table 1880230592Sken * using only the volume dev handle. This is just a wrapper function for the 1881230592Sken * local function _mapping_get_ir_mt_idx_from_handle. 1882230592Sken * @sc: per adapter object 1883230592Sken * @volHandle: volume device handle 1884230592Sken * 1885230592Sken * Returns valid ID on success or BAD_ID. 1886230592Sken */ 1887230592Skenunsigned int 1888230592Skenmps_mapping_get_raid_id_from_handle(struct mps_softc *sc, u16 volHandle) 1889230592Sken{ 1890230592Sken return (_mapping_get_ir_mt_idx_from_handle(sc, volHandle)); 1891230592Sken} 1892230592Sken 1893230592Sken/** 1894230592Sken * mps_mapping_enclosure_dev_status_change_event - handle enclosure events 1895230592Sken * @sc: per adapter object 1896230592Sken * @event_data: event data payload 1897230592Sken * 1898230592Sken * Return nothing. 1899230592Sken */ 1900230592Skenvoid 1901230592Skenmps_mapping_enclosure_dev_status_change_event(struct mps_softc *sc, 1902230592Sken Mpi2EventDataSasEnclDevStatusChange_t *event_data) 1903230592Sken{ 1904230592Sken u8 enc_idx, missing_count; 1905230592Sken struct enc_mapping_table *et_entry; 1906230592Sken Mpi2DriverMap0Entry_t *dpm_entry; 1907230592Sken u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1908230592Sken u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT; 1909230592Sken u8 update_phy_bits = 0; 1910230592Sken u32 saved_phy_bits; 1911230592Sken uint64_t temp64_var; 1912230592Sken 1913230592Sken if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) != 1914230592Sken MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) 1915230592Sken goto out; 1916230592Sken 1917230592Sken dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 + 1918230592Sken sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 1919230592Sken 1920230592Sken if (event_data->ReasonCode == MPI2_EVENT_SAS_ENCL_RC_ADDED) { 1921230592Sken if (!event_data->NumSlots) { 1922230592Sken printf("%s: enclosure with handle = 0x%x reported 0 " 1923230592Sken "slots\n", __func__, 1924230592Sken le16toh(event_data->EnclosureHandle)); 1925230592Sken goto out; 1926230592Sken } 1927230592Sken temp64_var = event_data->EnclosureLogicalID.High; 1928230592Sken temp64_var = (temp64_var << 32) | 1929230592Sken event_data->EnclosureLogicalID.Low; 1930230592Sken enc_idx = _mapping_get_enc_idx_from_id(sc, temp64_var, 1931230592Sken event_data->PhyBits); 1932230592Sken if (enc_idx != MPS_ENCTABLE_BAD_IDX) { 1933230592Sken et_entry = &sc->enclosure_table[enc_idx]; 1934230592Sken if (et_entry->init_complete && 1935230592Sken !et_entry->missing_count) { 1936230592Sken printf("%s: enclosure %d is already present " 1937230592Sken "with handle = 0x%x\n",__func__, enc_idx, 1938230592Sken et_entry->enc_handle); 1939230592Sken goto out; 1940230592Sken } 1941230592Sken et_entry->enc_handle = le16toh(event_data-> 1942230592Sken EnclosureHandle); 1943230592Sken et_entry->start_slot = le16toh(event_data->StartSlot); 1944230592Sken saved_phy_bits = et_entry->phy_bits; 1945230592Sken et_entry->phy_bits |= le32toh(event_data->PhyBits); 1946230592Sken if (saved_phy_bits != et_entry->phy_bits) 1947230592Sken update_phy_bits = 1; 1948230592Sken if (et_entry->missing_count || update_phy_bits) { 1949230592Sken et_entry->missing_count = 0; 1950230592Sken if (sc->is_dpm_enable && 1951230592Sken et_entry->dpm_entry_num != 1952230592Sken MPS_DPM_BAD_IDX) { 1953230592Sken dpm_entry += et_entry->dpm_entry_num; 1954230592Sken missing_count = 1955230592Sken (u8)(dpm_entry->MappingInformation & 1956230592Sken MPI2_DRVMAP0_MAPINFO_MISSING_MASK); 1957230592Sken if (!et_entry->init_complete && ( 1958230592Sken missing_count || update_phy_bits)) { 1959230592Sken dpm_entry->MappingInformation 1960230592Sken = et_entry->num_slots; 1961230592Sken dpm_entry->MappingInformation 1962230592Sken <<= map_shift; 1963230592Sken dpm_entry->PhysicalBitsMapping 1964230592Sken = et_entry->phy_bits; 1965230592Sken sc->dpm_flush_entry[et_entry-> 1966230592Sken dpm_entry_num] = 1; 1967230592Sken } 1968230592Sken } 1969230592Sken } 1970230592Sken } else { 1971230592Sken enc_idx = sc->num_enc_table_entries; 1972230592Sken if (enc_idx >= sc->max_enclosures) { 1973230592Sken printf("%s: enclosure can not be added; " 1974230592Sken "mapping table is full\n", __func__); 1975230592Sken goto out; 1976230592Sken } 1977230592Sken sc->num_enc_table_entries++; 1978230592Sken et_entry = &sc->enclosure_table[enc_idx]; 1979230592Sken et_entry->enc_handle = le16toh(event_data-> 1980230592Sken EnclosureHandle); 1981230592Sken et_entry->enclosure_id = event_data-> 1982230592Sken EnclosureLogicalID.High; 1983230592Sken et_entry->enclosure_id = ( et_entry->enclosure_id << 1984230592Sken 32) | event_data->EnclosureLogicalID.Low; 1985230592Sken et_entry->start_index = MPS_MAPTABLE_BAD_IDX; 1986230592Sken et_entry->dpm_entry_num = MPS_DPM_BAD_IDX; 1987230592Sken et_entry->num_slots = le16toh(event_data->NumSlots); 1988230592Sken et_entry->start_slot = le16toh(event_data->StartSlot); 1989230592Sken et_entry->phy_bits = le32toh(event_data->PhyBits); 1990230592Sken } 1991230592Sken et_entry->init_complete = 1; 1992230592Sken } else if (event_data->ReasonCode == 1993230592Sken MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING) { 1994230592Sken enc_idx = _mapping_get_enc_idx_from_handle(sc, 1995230592Sken le16toh(event_data->EnclosureHandle)); 1996230592Sken if (enc_idx == MPS_ENCTABLE_BAD_IDX) { 1997230592Sken printf("%s: cannot unmap enclosure %d because it has " 1998230592Sken "already been deleted", __func__, enc_idx); 1999230592Sken goto out; 2000230592Sken } 2001230592Sken et_entry = &sc->enclosure_table[enc_idx]; 2002230592Sken if (!et_entry->init_complete) { 2003230592Sken if (et_entry->missing_count < MPS_MAX_MISSING_COUNT) 2004230592Sken et_entry->missing_count++; 2005230592Sken else 2006230592Sken et_entry->init_complete = 1; 2007230592Sken } 2008230592Sken if (!et_entry->missing_count) 2009230592Sken et_entry->missing_count++; 2010230592Sken if (sc->is_dpm_enable && !et_entry->init_complete && 2011230592Sken et_entry->dpm_entry_num != MPS_DPM_BAD_IDX) { 2012230592Sken dpm_entry += et_entry->dpm_entry_num; 2013230592Sken dpm_entry->MappingInformation = et_entry->num_slots; 2014230592Sken dpm_entry->MappingInformation <<= map_shift; 2015230592Sken dpm_entry->MappingInformation |= 2016230592Sken et_entry->missing_count; 2017230592Sken sc->dpm_flush_entry[et_entry->dpm_entry_num] = 1; 2018230592Sken } 2019230592Sken et_entry->init_complete = 1; 2020230592Sken } 2021230592Sken 2022230592Skenout: 2023230592Sken _mapping_flush_dpm_pages(sc); 2024230592Sken if (sc->pending_map_events) 2025230592Sken sc->pending_map_events--; 2026230592Sken} 2027230592Sken 2028230592Sken/** 2029230592Sken * mps_mapping_topology_change_event - handle topology change events 2030230592Sken * @sc: per adapter object 2031230592Sken * @event_data: event data payload 2032230592Sken * 2033230592Sken * Returns nothing. 2034230592Sken */ 2035230592Skenvoid 2036230592Skenmps_mapping_topology_change_event(struct mps_softc *sc, 2037230592Sken Mpi2EventDataSasTopologyChangeList_t *event_data) 2038230592Sken{ 2039230592Sken struct _map_topology_change topo_change; 2040230592Sken struct _map_phy_change *phy_change; 2041230592Sken Mpi2EventSasTopoPhyEntry_t *event_phy_change; 2042230592Sken u8 i, num_entries; 2043230592Sken 2044230592Sken topo_change.enc_handle = le16toh(event_data->EnclosureHandle); 2045230592Sken topo_change.exp_handle = le16toh(event_data->ExpanderDevHandle); 2046230592Sken num_entries = event_data->NumEntries; 2047230592Sken topo_change.num_entries = num_entries; 2048230592Sken topo_change.start_phy_num = event_data->StartPhyNum; 2049230592Sken topo_change.num_phys = event_data->NumPhys; 2050230592Sken topo_change.exp_status = event_data->ExpStatus; 2051230592Sken event_phy_change = event_data->PHY; 2052230592Sken topo_change.phy_details = NULL; 2053230592Sken 2054230592Sken if (!num_entries) 2055230592Sken goto out; 2056230592Sken phy_change = malloc(sizeof(struct _map_phy_change) * num_entries, 2057230592Sken M_MPT2, M_NOWAIT|M_ZERO); 2058230592Sken topo_change.phy_details = phy_change; 2059230592Sken if (!phy_change) 2060230592Sken goto out; 2061230592Sken for (i = 0; i < num_entries; i++, event_phy_change++, phy_change++) { 2062230592Sken phy_change->dev_handle = le16toh(event_phy_change-> 2063230592Sken AttachedDevHandle); 2064230592Sken phy_change->reason = event_phy_change->PhyStatus & 2065230592Sken MPI2_EVENT_SAS_TOPO_RC_MASK; 2066230592Sken } 2067230592Sken _mapping_update_missing_count(sc, &topo_change); 2068230592Sken _mapping_get_dev_info(sc, &topo_change); 2069230592Sken _mapping_clear_removed_entries(sc); 2070230592Sken _mapping_add_new_device(sc, &topo_change); 2071230592Sken 2072230592Skenout: 2073230592Sken free(topo_change.phy_details, M_MPT2); 2074230592Sken _mapping_flush_dpm_pages(sc); 2075230592Sken if (sc->pending_map_events) 2076230592Sken sc->pending_map_events--; 2077230592Sken} 2078230592Sken 2079230592Sken/** 2080230592Sken * _mapping_check_update_ir_mt_idx - Check and update IR map table index 2081230592Sken * @sc: per adapter object 2082230592Sken * @event_data: event data payload 2083230592Sken * @evt_idx: current event index 2084230592Sken * @map_idx: current index and the place holder for new map table index 2085230592Sken * @wwid_table: world wide name for volumes in the element table 2086230592Sken * 2087230592Sken * pass through IR events and find whether any events matches and if so 2088230592Sken * tries to find new index if not returns failure 2089230592Sken * 2090230592Sken * Returns 0 on success and 1 on failure 2091230592Sken */ 2092230592Skenstatic int 2093230592Sken_mapping_check_update_ir_mt_idx(struct mps_softc *sc, 2094230592Sken Mpi2EventDataIrConfigChangeList_t *event_data, int evt_idx, u32 *map_idx, 2095230592Sken u64 *wwid_table) 2096230592Sken{ 2097230592Sken struct dev_mapping_table *mt_entry; 2098230592Sken u32 st_idx, end_idx, mt_idx = *map_idx; 2099230592Sken u8 match = 0; 2100230592Sken Mpi2EventIrConfigElement_t *element; 2101230592Sken u16 element_flags; 2102230592Sken int i; 2103230592Sken 2104230592Sken mt_entry = &sc->mapping_table[mt_idx]; 2105230592Sken _mapping_get_ir_maprange(sc, &st_idx, &end_idx); 2106230592Skensearch_again: 2107230592Sken match = 0; 2108230592Sken for (i = evt_idx + 1; i < event_data->NumElements; i++) { 2109230592Sken element = (Mpi2EventIrConfigElement_t *) 2110230592Sken &event_data->ConfigElement[i]; 2111230592Sken element_flags = le16toh(element->ElementFlags); 2112230592Sken if ((element_flags & 2113230592Sken MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK) != 2114230592Sken MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT) 2115230592Sken continue; 2116230592Sken if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_ADDED || 2117230592Sken element->ReasonCode == 2118230592Sken MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) { 2119230592Sken if (mt_entry->physical_id == wwid_table[i]) { 2120230592Sken match = 1; 2121230592Sken break; 2122230592Sken } 2123230592Sken } 2124230592Sken } 2125230592Sken 2126230592Sken if (match) { 2127230592Sken do { 2128230592Sken mt_idx++; 2129230592Sken if (mt_idx > end_idx) 2130230592Sken return 1; 2131230592Sken mt_entry = &sc->mapping_table[mt_idx]; 2132230592Sken } while (mt_entry->device_info & MPS_MAP_IN_USE); 2133230592Sken goto search_again; 2134230592Sken } 2135230592Sken *map_idx = mt_idx; 2136230592Sken return 0; 2137230592Sken} 2138230592Sken 2139230592Sken/** 2140230592Sken * mps_mapping_ir_config_change_event - handle IR config change list events 2141230592Sken * @sc: per adapter object 2142230592Sken * @event_data: event data payload 2143230592Sken * 2144230592Sken * Returns nothing. 2145230592Sken */ 2146230592Skenvoid 2147230592Skenmps_mapping_ir_config_change_event(struct mps_softc *sc, 2148230592Sken Mpi2EventDataIrConfigChangeList_t *event_data) 2149230592Sken{ 2150230592Sken Mpi2EventIrConfigElement_t *element; 2151230592Sken int i; 2152230592Sken u64 *wwid_table; 2153230592Sken u32 map_idx, flags; 2154230592Sken struct dev_mapping_table *mt_entry; 2155230592Sken u16 element_flags; 2156230592Sken u8 log_full_error = 0; 2157230592Sken 2158230592Sken wwid_table = malloc(sizeof(u64) * event_data->NumElements, M_MPT2, 2159230592Sken M_NOWAIT | M_ZERO); 2160230592Sken if (!wwid_table) 2161230592Sken goto out; 2162230592Sken element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; 2163230592Sken flags = le32toh(event_data->Flags); 2164230592Sken for (i = 0; i < event_data->NumElements; i++, element++) { 2165230592Sken element_flags = le16toh(element->ElementFlags); 2166230592Sken if ((element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_ADDED) && 2167230592Sken (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_REMOVED) && 2168230592Sken (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE) 2169230592Sken && (element->ReasonCode != 2170230592Sken MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED)) 2171230592Sken continue; 2172230592Sken if ((element_flags & 2173230592Sken MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK) == 2174230592Sken MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT) { 2175230592Sken mps_config_get_volume_wwid(sc, 2176230592Sken le16toh(element->VolDevHandle), &wwid_table[i]); 2177230592Sken map_idx = _mapping_get_ir_mt_idx_from_wwid(sc, 2178230592Sken wwid_table[i]); 2179230592Sken if (map_idx != MPS_MAPTABLE_BAD_IDX) { 2180230592Sken mt_entry = &sc->mapping_table[map_idx]; 2181230592Sken mt_entry->device_info |= MPS_MAP_IN_USE; 2182230592Sken } 2183230592Sken } 2184230592Sken } 2185230592Sken if (flags == MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) 2186230592Sken goto out; 2187230592Sken else { 2188230592Sken element = (Mpi2EventIrConfigElement_t *)&event_data-> 2189230592Sken ConfigElement[0]; 2190230592Sken for (i = 0; i < event_data->NumElements; i++, element++) { 2191230592Sken if (element->ReasonCode == 2192230592Sken MPI2_EVENT_IR_CHANGE_RC_ADDED || 2193230592Sken element->ReasonCode == 2194230592Sken MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) { 2195230592Sken map_idx = _mapping_get_ir_mt_idx_from_wwid 2196230592Sken (sc, wwid_table[i]); 2197230592Sken if (map_idx != MPS_MAPTABLE_BAD_IDX) { 2198230592Sken mt_entry = &sc->mapping_table[map_idx]; 2199230592Sken mt_entry->channel = MPS_RAID_CHANNEL; 2200230592Sken mt_entry->id = map_idx; 2201230592Sken mt_entry->dev_handle = le16toh 2202230592Sken (element->VolDevHandle); 2203230592Sken mt_entry->device_info = 2204230592Sken MPS_DEV_RESERVED | MPS_MAP_IN_USE; 2205230592Sken _mapping_update_ir_missing_cnt(sc, 2206230592Sken map_idx, element, wwid_table[i]); 2207230592Sken continue; 2208230592Sken } 2209230592Sken map_idx = _mapping_get_free_ir_mt_idx(sc); 2210230592Sken if (map_idx == MPS_MAPTABLE_BAD_IDX) 2211230592Sken log_full_error = 1; 2212230592Sken else if (i < (event_data->NumElements - 1)) { 2213230592Sken log_full_error = 2214230592Sken _mapping_check_update_ir_mt_idx 2215230592Sken (sc, event_data, i, &map_idx, 2216230592Sken wwid_table); 2217230592Sken } 2218230592Sken if (log_full_error) { 2219230592Sken printf("%s: no space to add the RAID " 2220230592Sken "volume with handle 0x%04x in " 2221230592Sken "mapping table\n", __func__, le16toh 2222230592Sken (element->VolDevHandle)); 2223230592Sken continue; 2224230592Sken } 2225230592Sken mt_entry = &sc->mapping_table[map_idx]; 2226230592Sken mt_entry->physical_id = wwid_table[i]; 2227230592Sken mt_entry->channel = MPS_RAID_CHANNEL; 2228230592Sken mt_entry->id = map_idx; 2229230592Sken mt_entry->dev_handle = le16toh(element-> 2230230592Sken VolDevHandle); 2231230592Sken mt_entry->device_info = MPS_DEV_RESERVED | 2232230592Sken MPS_MAP_IN_USE; 2233230592Sken mt_entry->init_complete = 0; 2234230592Sken _mapping_update_ir_missing_cnt(sc, map_idx, 2235230592Sken element, wwid_table[i]); 2236230592Sken } else if (element->ReasonCode == 2237230592Sken MPI2_EVENT_IR_CHANGE_RC_REMOVED) { 2238230592Sken map_idx = _mapping_get_ir_mt_idx_from_wwid(sc, 2239230592Sken wwid_table[i]); 2240230592Sken if (map_idx == MPS_MAPTABLE_BAD_IDX) { 2241230592Sken printf("%s: failed to remove a volume " 2242230592Sken "because it has already been " 2243230592Sken "removed\n", __func__); 2244230592Sken continue; 2245230592Sken } 2246230592Sken _mapping_update_ir_missing_cnt(sc, map_idx, 2247230592Sken element, wwid_table[i]); 2248230592Sken } else if (element->ReasonCode == 2249230592Sken MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED) { 2250230592Sken map_idx = _mapping_get_mt_idx_from_handle(sc, 2251230592Sken le16toh(element->VolDevHandle)); 2252230592Sken if (map_idx == MPS_MAPTABLE_BAD_IDX) { 2253230592Sken printf("%s: failed to remove volume " 2254230592Sken "with handle 0x%04x because it has " 2255230592Sken "already been removed\n", __func__, 2256230592Sken le16toh(element->VolDevHandle)); 2257230592Sken continue; 2258230592Sken } 2259230592Sken mt_entry = &sc->mapping_table[map_idx]; 2260230592Sken _mapping_update_ir_missing_cnt(sc, map_idx, 2261230592Sken element, mt_entry->physical_id); 2262230592Sken } 2263230592Sken } 2264230592Sken } 2265230592Sken 2266230592Skenout: 2267230592Sken _mapping_flush_dpm_pages(sc); 2268230592Sken free(wwid_table, M_MPT2); 2269230592Sken if (sc->pending_map_events) 2270230592Sken sc->pending_map_events--; 2271230592Sken} 2272