xref: /freebsd/sys/dev/mps/mps_mapping.c (revision b652778e426d00b6a1df29bbd86869db86f36e25)
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