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