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