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