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