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