1230592Sken/*-
2237876Sken * Copyright (c) 2011, 2012 LSI Corp.
3230592Sken * All rights reserved.
4230592Sken *
5230592Sken * Redistribution and use in source and binary forms, with or without
6230592Sken * modification, are permitted provided that the following conditions
7230592Sken * are met:
8230592Sken * 1. Redistributions of source code must retain the above copyright
9230592Sken *    notice, this list of conditions and the following disclaimer.
10230592Sken * 2. Redistributions in binary form must reproduce the above copyright
11230592Sken *    notice, this list of conditions and the following disclaimer in the
12230592Sken *    documentation and/or other materials provided with the distribution.
13230592Sken *
14230592Sken * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15230592Sken * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16230592Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17230592Sken * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18230592Sken * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19230592Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20230592Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21230592Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22230592Sken * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23230592Sken * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24230592Sken * SUCH DAMAGE.
25230592Sken *
26230592Sken * LSI MPT-Fusion Host Adapter FreeBSD
27230592Sken */
28230592Sken
29230592Sken#include <sys/cdefs.h>
30230592Sken__FBSDID("$FreeBSD$");
31230592Sken
32230592Sken/* TODO Move headers to mpsvar */
33230592Sken#include <sys/types.h>
34230592Sken#include <sys/param.h>
35230592Sken#include <sys/lock.h>
36230592Sken#include <sys/mutex.h>
37230592Sken#include <sys/systm.h>
38230592Sken#include <sys/kernel.h>
39230592Sken#include <sys/malloc.h>
40230592Sken#include <sys/kthread.h>
41230592Sken#include <sys/taskqueue.h>
42230592Sken#include <sys/bus.h>
43230592Sken#include <sys/endian.h>
44230592Sken#include <sys/sysctl.h>
45230592Sken#include <sys/eventhandler.h>
46230592Sken#include <sys/uio.h>
47230592Sken#include <machine/bus.h>
48230592Sken#include <machine/resource.h>
49230592Sken#include <dev/mps/mpi/mpi2_type.h>
50230592Sken#include <dev/mps/mpi/mpi2.h>
51230592Sken#include <dev/mps/mpi/mpi2_ioc.h>
52230592Sken#include <dev/mps/mpi/mpi2_sas.h>
53230592Sken#include <dev/mps/mpi/mpi2_cnfg.h>
54230592Sken#include <dev/mps/mpi/mpi2_init.h>
55230592Sken#include <dev/mps/mpi/mpi2_tool.h>
56230592Sken#include <dev/mps/mps_ioctl.h>
57230592Sken#include <dev/mps/mpsvar.h>
58230592Sken#include <dev/mps/mps_mapping.h>
59230592Sken
60230592Sken/**
61230592Sken * _mapping_clear_entry - Clear a particular mapping entry.
62230592Sken * @map_entry: map table entry
63230592Sken *
64230592Sken * Returns nothing.
65230592Sken */
66230592Skenstatic inline void
67230592Sken_mapping_clear_map_entry(struct dev_mapping_table *map_entry)
68230592Sken{
69230592Sken	map_entry->physical_id = 0;
70230592Sken	map_entry->device_info = 0;
71230592Sken	map_entry->phy_bits = 0;
72230592Sken	map_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
73230592Sken	map_entry->dev_handle = 0;
74230592Sken	map_entry->channel = -1;
75230592Sken	map_entry->id = -1;
76230592Sken	map_entry->missing_count = 0;
77230592Sken	map_entry->init_complete = 0;
78230592Sken	map_entry->TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR;
79230592Sken}
80230592Sken
81230592Sken/**
82230592Sken * _mapping_clear_enc_entry - Clear a particular enclosure table entry.
83230592Sken * @enc_entry: enclosure table entry
84230592Sken *
85230592Sken * Returns nothing.
86230592Sken */
87230592Skenstatic inline void
88230592Sken_mapping_clear_enc_entry(struct enc_mapping_table *enc_entry)
89230592Sken{
90230592Sken	enc_entry->enclosure_id = 0;
91230592Sken	enc_entry->start_index = MPS_MAPTABLE_BAD_IDX;
92230592Sken	enc_entry->phy_bits = 0;
93230592Sken	enc_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
94230592Sken	enc_entry->enc_handle = 0;
95230592Sken	enc_entry->num_slots = 0;
96230592Sken	enc_entry->start_slot = 0;
97230592Sken	enc_entry->missing_count = 0;
98230592Sken	enc_entry->removal_flag = 0;
99230592Sken	enc_entry->skip_search = 0;
100230592Sken	enc_entry->init_complete = 0;
101230592Sken}
102230592Sken
103230592Sken/**
104230592Sken * _mapping_commit_enc_entry - write a particular enc entry in DPM page0.
105230592Sken * @sc: per adapter object
106230592Sken * @enc_entry: enclosure table entry
107230592Sken *
108230592Sken * Returns 0 for success, non-zero for failure.
109230592Sken */
110230592Skenstatic int
111230592Sken_mapping_commit_enc_entry(struct mps_softc *sc,
112230592Sken    struct enc_mapping_table *et_entry)
113230592Sken{
114230592Sken	Mpi2DriverMap0Entry_t *dpm_entry;
115230592Sken	struct dev_mapping_table *mt_entry;
116230592Sken	Mpi2ConfigReply_t mpi_reply;
117230592Sken	Mpi2DriverMappingPage0_t config_page;
118230592Sken
119230592Sken	if (!sc->is_dpm_enable)
120230592Sken		return 0;
121230592Sken
122230592Sken	memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
123230592Sken	memcpy(&config_page.Header, (u8 *) sc->dpm_pg0,
124230592Sken	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
125230592Sken	dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
126230592Sken	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
127230592Sken	dpm_entry += et_entry->dpm_entry_num;
128230592Sken	dpm_entry->PhysicalIdentifier.Low =
129230592Sken	    ( 0xFFFFFFFF & et_entry->enclosure_id);
130230592Sken	dpm_entry->PhysicalIdentifier.High =
131230592Sken	    ( et_entry->enclosure_id >> 32);
132230592Sken	mt_entry = &sc->mapping_table[et_entry->start_index];
133230592Sken	dpm_entry->DeviceIndex = htole16(mt_entry->id);
134230592Sken	dpm_entry->MappingInformation = et_entry->num_slots;
135230592Sken	dpm_entry->MappingInformation <<= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
136230592Sken	dpm_entry->MappingInformation |= et_entry->missing_count;
137230592Sken	dpm_entry->MappingInformation = htole16(dpm_entry->MappingInformation);
138230592Sken	dpm_entry->PhysicalBitsMapping = htole32(et_entry->phy_bits);
139230592Sken	dpm_entry->Reserved1 = 0;
140230592Sken
141230592Sken	memcpy(&config_page.Entry, (u8 *)dpm_entry,
142230592Sken	    sizeof(Mpi2DriverMap0Entry_t));
143230592Sken	if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
144230592Sken	    et_entry->dpm_entry_num)) {
145230592Sken		printf("%s: write of dpm entry %d for enclosure failed\n",
146230592Sken		    __func__, et_entry->dpm_entry_num);
147230592Sken		dpm_entry->MappingInformation = le16toh(dpm_entry->
148230592Sken		    MappingInformation);
149230592Sken		dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
150230592Sken		dpm_entry->PhysicalBitsMapping =
151230592Sken		    le32toh(dpm_entry->PhysicalBitsMapping);
152230592Sken		return -1;
153230592Sken	}
154230592Sken	dpm_entry->MappingInformation = le16toh(dpm_entry->
155230592Sken	    MappingInformation);
156230592Sken	dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
157230592Sken	dpm_entry->PhysicalBitsMapping =
158230592Sken	    le32toh(dpm_entry->PhysicalBitsMapping);
159230592Sken	return 0;
160230592Sken}
161230592Sken
162230592Sken/**
163230592Sken * _mapping_commit_map_entry - write a particular map table entry in DPM page0.
164230592Sken * @sc: per adapter object
165230592Sken * @enc_entry: enclosure table entry
166230592Sken *
167230592Sken * Returns 0 for success, non-zero for failure.
168230592Sken */
169230592Sken
170230592Skenstatic int
171230592Sken_mapping_commit_map_entry(struct mps_softc *sc,
172230592Sken    struct dev_mapping_table *mt_entry)
173230592Sken{
174230592Sken	Mpi2DriverMap0Entry_t *dpm_entry;
175230592Sken	Mpi2ConfigReply_t mpi_reply;
176230592Sken	Mpi2DriverMappingPage0_t config_page;
177230592Sken
178230592Sken	if (!sc->is_dpm_enable)
179230592Sken		return 0;
180230592Sken
181230592Sken	memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
182230592Sken	memcpy(&config_page.Header, (u8 *)sc->dpm_pg0,
183230592Sken	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
184230592Sken	dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *) sc->dpm_pg0 +
185230592Sken	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
186230592Sken	dpm_entry = dpm_entry + mt_entry->dpm_entry_num;
187230592Sken	dpm_entry->PhysicalIdentifier.Low = (0xFFFFFFFF &
188230592Sken	    mt_entry->physical_id);
189230592Sken	dpm_entry->PhysicalIdentifier.High = (mt_entry->physical_id >> 32);
190230592Sken	dpm_entry->DeviceIndex = htole16(mt_entry->id);
191230592Sken	dpm_entry->MappingInformation = htole16(mt_entry->missing_count);
192230592Sken	dpm_entry->PhysicalBitsMapping = 0;
193230592Sken	dpm_entry->Reserved1 = 0;
194230592Sken	dpm_entry->MappingInformation = htole16(dpm_entry->MappingInformation);
195230592Sken	memcpy(&config_page.Entry, (u8 *)dpm_entry,
196230592Sken	    sizeof(Mpi2DriverMap0Entry_t));
197230592Sken	if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
198230592Sken	    mt_entry->dpm_entry_num)) {
199230592Sken		printf("%s: write of dpm entry %d for device failed\n",
200230592Sken		    __func__, mt_entry->dpm_entry_num);
201230592Sken		dpm_entry->MappingInformation = le16toh(dpm_entry->
202230592Sken		    MappingInformation);
203230592Sken		dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
204230592Sken		return -1;
205230592Sken	}
206230592Sken
207230592Sken	dpm_entry->MappingInformation = le16toh(dpm_entry->MappingInformation);
208230592Sken	dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
209230592Sken	return 0;
210230592Sken}
211230592Sken
212230592Sken/**
213230592Sken * _mapping_get_ir_maprange - get start and end index for IR map range.
214230592Sken * @sc: per adapter object
215230592Sken * @start_idx: place holder for start index
216230592Sken * @end_idx: place holder for end index
217230592Sken *
218230592Sken * The IR volumes can be mapped either at start or end of the mapping table
219230592Sken * this function gets the detail of where IR volume mapping starts and ends
220230592Sken * in the device mapping table
221230592Sken *
222230592Sken * Returns nothing.
223230592Sken */
224230592Skenstatic void
225230592Sken_mapping_get_ir_maprange(struct mps_softc *sc, u32 *start_idx, u32 *end_idx)
226230592Sken{
227230592Sken	u16 volume_mapping_flags;
228230592Sken	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
229230592Sken
230230592Sken	volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
231230592Sken	    MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
232230592Sken	if (volume_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
233230592Sken		*start_idx = 0;
234230592Sken		if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
235230592Sken			*start_idx = 1;
236230592Sken	} else
237230592Sken		*start_idx = sc->max_devices - sc->max_volumes;
238230592Sken	*end_idx = *start_idx + sc->max_volumes - 1;
239230592Sken}
240230592Sken
241230592Sken/**
242230592Sken * _mapping_get_enc_idx_from_id - get enclosure index from enclosure ID
243230592Sken * @sc: per adapter object
244230592Sken * @enc_id: enclosure logical identifier
245230592Sken *
246230592Sken * Returns the index of enclosure entry on success or bad index.
247230592Sken */
248230592Skenstatic u8
249230592Sken_mapping_get_enc_idx_from_id(struct mps_softc *sc, u64 enc_id,
250230592Sken    u64 phy_bits)
251230592Sken{
252230592Sken	struct enc_mapping_table *et_entry;
253230592Sken	u8 enc_idx = 0;
254230592Sken
255230592Sken	for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
256230592Sken		et_entry = &sc->enclosure_table[enc_idx];
257230592Sken		if ((et_entry->enclosure_id == le64toh(enc_id)) &&
258230592Sken		    (!et_entry->phy_bits || (et_entry->phy_bits &
259230592Sken		    le32toh(phy_bits))))
260230592Sken			return enc_idx;
261230592Sken	}
262230592Sken	return MPS_ENCTABLE_BAD_IDX;
263230592Sken}
264230592Sken
265230592Sken/**
266230592Sken * _mapping_get_enc_idx_from_handle - get enclosure index from handle
267230592Sken * @sc: per adapter object
268230592Sken * @enc_id: enclosure handle
269230592Sken *
270230592Sken * Returns the index of enclosure entry on success or bad index.
271230592Sken */
272230592Skenstatic u8
273230592Sken_mapping_get_enc_idx_from_handle(struct mps_softc *sc, u16 handle)
274230592Sken{
275230592Sken	struct enc_mapping_table *et_entry;
276230592Sken	u8 enc_idx = 0;
277230592Sken
278230592Sken	for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
279230592Sken		et_entry = &sc->enclosure_table[enc_idx];
280230592Sken		if (et_entry->missing_count)
281230592Sken			continue;
282230592Sken		if (et_entry->enc_handle == handle)
283230592Sken			return enc_idx;
284230592Sken	}
285230592Sken	return MPS_ENCTABLE_BAD_IDX;
286230592Sken}
287230592Sken
288230592Sken/**
289230592Sken * _mapping_get_high_missing_et_idx - get missing enclosure index
290230592Sken * @sc: per adapter object
291230592Sken *
292230592Sken * Search through the enclosure table and identifies the enclosure entry
293230592Sken * with high missing count and returns it's index
294230592Sken *
295230592Sken * Returns the index of enclosure entry on success or bad index.
296230592Sken */
297230592Skenstatic u8
298230592Sken_mapping_get_high_missing_et_idx(struct mps_softc *sc)
299230592Sken{
300230592Sken	struct enc_mapping_table *et_entry;
301230592Sken	u8 high_missing_count = 0;
302230592Sken	u8 enc_idx, high_idx = MPS_ENCTABLE_BAD_IDX;
303230592Sken
304230592Sken	for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
305230592Sken		et_entry = &sc->enclosure_table[enc_idx];
306230592Sken		if ((et_entry->missing_count > high_missing_count) &&
307230592Sken		    !et_entry->skip_search) {
308230592Sken			high_missing_count =  et_entry->missing_count;
309230592Sken			high_idx = enc_idx;
310230592Sken		}
311230592Sken	}
312230592Sken	return high_idx;
313230592Sken}
314230592Sken
315230592Sken/**
316230592Sken * _mapping_get_high_missing_mt_idx - get missing map table index
317230592Sken * @sc: per adapter object
318230592Sken *
319230592Sken * Search through the map table and identifies the device entry
320230592Sken * with high missing count and returns it's index
321230592Sken *
322230592Sken * Returns the index of map table entry on success or bad index.
323230592Sken */
324230592Skenstatic u32
325230592Sken_mapping_get_high_missing_mt_idx(struct mps_softc *sc)
326230592Sken{
327230592Sken	u32 map_idx, high_idx = MPS_ENCTABLE_BAD_IDX;
328230592Sken	u8 high_missing_count = 0;
329230592Sken	u32 start_idx, end_idx, start_idx_ir, end_idx_ir;
330230592Sken	struct dev_mapping_table *mt_entry;
331230592Sken	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
332230592Sken
333230592Sken	start_idx = 0;
334251414Ssmh	start_idx_ir = 0;
335251414Ssmh	end_idx_ir = 0;
336230592Sken	end_idx = sc->max_devices;
337230592Sken	if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
338230592Sken		start_idx = 1;
339230592Sken	if (sc->ir_firmware)
340230592Sken		_mapping_get_ir_maprange(sc, &start_idx_ir, &end_idx_ir);
341230592Sken	if (start_idx == start_idx_ir)
342230592Sken		start_idx = end_idx_ir + 1;
343230592Sken	else
344230592Sken		end_idx = start_idx_ir;
345230592Sken	mt_entry = &sc->mapping_table[start_idx];
346230592Sken	for (map_idx = start_idx; map_idx < end_idx; map_idx++, mt_entry++) {
347230592Sken		if (mt_entry->missing_count > high_missing_count) {
348230592Sken			high_missing_count =  mt_entry->missing_count;
349230592Sken			high_idx = map_idx;
350230592Sken		}
351230592Sken	}
352230592Sken	return high_idx;
353230592Sken}
354230592Sken
355230592Sken/**
356230592Sken * _mapping_get_ir_mt_idx_from_wwid - get map table index from volume WWID
357230592Sken * @sc: per adapter object
358230592Sken * @wwid: world wide unique ID of the volume
359230592Sken *
360230592Sken * Returns the index of map table entry on success or bad index.
361230592Sken */
362230592Skenstatic u32
363230592Sken_mapping_get_ir_mt_idx_from_wwid(struct mps_softc *sc, u64 wwid)
364230592Sken{
365230592Sken	u32 start_idx, end_idx, map_idx;
366230592Sken	struct dev_mapping_table *mt_entry;
367230592Sken
368230592Sken	_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
369230592Sken	mt_entry = &sc->mapping_table[start_idx];
370230592Sken	for (map_idx  = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
371230592Sken		if (mt_entry->physical_id == wwid)
372230592Sken			return map_idx;
373230592Sken
374230592Sken	return MPS_MAPTABLE_BAD_IDX;
375230592Sken}
376230592Sken
377230592Sken/**
378230592Sken * _mapping_get_mt_idx_from_id - get map table index from a device ID
379230592Sken * @sc: per adapter object
380230592Sken * @dev_id: device identifer (SAS Address)
381230592Sken *
382230592Sken * Returns the index of map table entry on success or bad index.
383230592Sken */
384230592Skenstatic u32
385230592Sken_mapping_get_mt_idx_from_id(struct mps_softc *sc, u64 dev_id)
386230592Sken{
387230592Sken	u32 map_idx;
388230592Sken	struct dev_mapping_table *mt_entry;
389230592Sken
390230592Sken	for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
391230592Sken		mt_entry = &sc->mapping_table[map_idx];
392230592Sken		if (mt_entry->physical_id == dev_id)
393230592Sken			return map_idx;
394230592Sken	}
395230592Sken	return MPS_MAPTABLE_BAD_IDX;
396230592Sken}
397230592Sken
398230592Sken/**
399230592Sken * _mapping_get_ir_mt_idx_from_handle - get map table index from volume handle
400230592Sken * @sc: per adapter object
401230592Sken * @wwid: volume device handle
402230592Sken *
403230592Sken * Returns the index of map table entry on success or bad index.
404230592Sken */
405230592Skenstatic u32
406230592Sken_mapping_get_ir_mt_idx_from_handle(struct mps_softc *sc, u16 volHandle)
407230592Sken{
408230592Sken	u32 start_idx, end_idx, map_idx;
409230592Sken	struct dev_mapping_table *mt_entry;
410230592Sken
411230592Sken	_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
412230592Sken	mt_entry = &sc->mapping_table[start_idx];
413230592Sken	for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
414230592Sken		if (mt_entry->dev_handle == volHandle)
415230592Sken			return map_idx;
416230592Sken
417230592Sken	return MPS_MAPTABLE_BAD_IDX;
418230592Sken}
419230592Sken
420230592Sken/**
421230592Sken * _mapping_get_mt_idx_from_handle - get map table index from handle
422230592Sken * @sc: per adapter object
423230592Sken * @dev_id: device handle
424230592Sken *
425230592Sken * Returns the index of map table entry on success or bad index.
426230592Sken */
427230592Skenstatic u32
428230592Sken_mapping_get_mt_idx_from_handle(struct mps_softc *sc, u16 handle)
429230592Sken{
430230592Sken	u32 map_idx;
431230592Sken	struct dev_mapping_table *mt_entry;
432230592Sken
433230592Sken	for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
434230592Sken		mt_entry = &sc->mapping_table[map_idx];
435230592Sken		if (mt_entry->dev_handle == handle)
436230592Sken			return map_idx;
437230592Sken	}
438230592Sken	return MPS_MAPTABLE_BAD_IDX;
439230592Sken}
440230592Sken
441230592Sken/**
442230592Sken * _mapping_get_free_ir_mt_idx - get first free index for a volume
443230592Sken * @sc: per adapter object
444230592Sken *
445230592Sken * Search through mapping table for free index for a volume and if no free
446230592Sken * index then looks for a volume with high mapping index
447230592Sken *
448230592Sken * Returns the index of map table entry on success or bad index.
449230592Sken */
450230592Skenstatic u32
451230592Sken_mapping_get_free_ir_mt_idx(struct mps_softc *sc)
452230592Sken{
453230592Sken	u8 high_missing_count = 0;
454230592Sken	u32 start_idx, end_idx, map_idx;
455230592Sken	u32 high_idx = MPS_MAPTABLE_BAD_IDX;
456230592Sken	struct dev_mapping_table *mt_entry;
457230592Sken
458230592Sken	_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
459230592Sken
460230592Sken	mt_entry = &sc->mapping_table[start_idx];
461230592Sken	for (map_idx  = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
462230592Sken		if (!(mt_entry->device_info & MPS_MAP_IN_USE))
463230592Sken			return map_idx;
464230592Sken
465230592Sken	mt_entry = &sc->mapping_table[start_idx];
466230592Sken	for (map_idx  = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) {
467230592Sken		if (mt_entry->missing_count > high_missing_count) {
468230592Sken			high_missing_count = mt_entry->missing_count;
469230592Sken			high_idx = map_idx;
470230592Sken		}
471230592Sken	}
472230592Sken	return high_idx;
473230592Sken}
474230592Sken
475230592Sken/**
476230592Sken * _mapping_get_free_mt_idx - get first free index for a device
477230592Sken * @sc: per adapter object
478230592Sken * @start_idx: offset in the table to start search
479230592Sken *
480230592Sken * Returns the index of map table entry on success or bad index.
481230592Sken */
482230592Skenstatic u32
483230592Sken_mapping_get_free_mt_idx(struct mps_softc *sc, u32 start_idx)
484230592Sken{
485230592Sken	u32 map_idx, max_idx = sc->max_devices;
486230592Sken	struct dev_mapping_table *mt_entry = &sc->mapping_table[start_idx];
487230592Sken	u16 volume_mapping_flags;
488230592Sken
489230592Sken	volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
490230592Sken	    MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
491230592Sken	if (sc->ir_firmware && (volume_mapping_flags ==
492230592Sken	    MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING))
493230592Sken		max_idx -= sc->max_volumes;
494230592Sken	for (map_idx  = start_idx; map_idx < max_idx; map_idx++, mt_entry++)
495230592Sken		if (!(mt_entry->device_info & (MPS_MAP_IN_USE |
496230592Sken		    MPS_DEV_RESERVED)))
497230592Sken			return map_idx;
498230592Sken
499230592Sken	return MPS_MAPTABLE_BAD_IDX;
500230592Sken}
501230592Sken
502230592Sken/**
503230592Sken * _mapping_get_dpm_idx_from_id - get DPM index from ID
504230592Sken * @sc: per adapter object
505230592Sken * @id: volume WWID or enclosure ID or device ID
506230592Sken *
507230592Sken * Returns the index of DPM entry on success or bad index.
508230592Sken */
509230592Skenstatic u16
510230592Sken_mapping_get_dpm_idx_from_id(struct mps_softc *sc, u64 id, u32 phy_bits)
511230592Sken{
512230592Sken	u16 entry_num;
513230592Sken	uint64_t PhysicalIdentifier;
514230592Sken	Mpi2DriverMap0Entry_t *dpm_entry;
515230592Sken
516230592Sken	dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
517230592Sken	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
518230592Sken	PhysicalIdentifier = dpm_entry->PhysicalIdentifier.High;
519230592Sken	PhysicalIdentifier = (PhysicalIdentifier << 32) |
520230592Sken	    dpm_entry->PhysicalIdentifier.Low;
521230592Sken	for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++,
522230592Sken	    dpm_entry++)
523230592Sken		if ((id == PhysicalIdentifier) &&
524230592Sken		    (!phy_bits || !dpm_entry->PhysicalBitsMapping ||
525230592Sken		    (phy_bits & dpm_entry->PhysicalBitsMapping)))
526230592Sken			return entry_num;
527230592Sken
528230592Sken	return MPS_DPM_BAD_IDX;
529230592Sken}
530230592Sken
531230592Sken
532230592Sken/**
533230592Sken * _mapping_get_free_dpm_idx - get first available DPM index
534230592Sken * @sc: per adapter object
535230592Sken *
536230592Sken * Returns the index of DPM entry on success or bad index.
537230592Sken */
538230592Skenstatic u32
539230592Sken_mapping_get_free_dpm_idx(struct mps_softc *sc)
540230592Sken{
541230592Sken	u16 entry_num;
542230592Sken
543230592Sken	for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) {
544230592Sken		if (!sc->dpm_entry_used[entry_num])
545230592Sken			return entry_num;
546230592Sken	}
547230592Sken	return MPS_DPM_BAD_IDX;
548230592Sken}
549230592Sken
550230592Sken/**
551230592Sken * _mapping_update_ir_missing_cnt - Updates missing count for a volume
552230592Sken * @sc: per adapter object
553230592Sken * @map_idx: map table index of the volume
554230592Sken * @element: IR configuration change element
555230592Sken * @wwid: IR volume ID.
556230592Sken *
557230592Sken * Updates the missing count in the map table and in the DPM entry for a volume
558230592Sken *
559230592Sken * Returns nothing.
560230592Sken */
561230592Skenstatic void
562230592Sken_mapping_update_ir_missing_cnt(struct mps_softc *sc, u32 map_idx,
563230592Sken    Mpi2EventIrConfigElement_t *element, u64 wwid)
564230592Sken{
565230592Sken	struct dev_mapping_table *mt_entry;
566230592Sken	u8 missing_cnt, reason = element->ReasonCode;
567230592Sken	u16 dpm_idx;
568230592Sken	Mpi2DriverMap0Entry_t *dpm_entry;
569230592Sken
570230592Sken	if (!sc->is_dpm_enable)
571230592Sken		return;
572230592Sken	mt_entry = &sc->mapping_table[map_idx];
573230592Sken	if (reason == MPI2_EVENT_IR_CHANGE_RC_ADDED) {
574230592Sken		mt_entry->missing_count = 0;
575230592Sken	} else if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) {
576230592Sken		mt_entry->missing_count = 0;
577230592Sken		mt_entry->init_complete = 0;
578230592Sken	} else if ((reason == MPI2_EVENT_IR_CHANGE_RC_REMOVED) ||
579230592Sken	    (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED)) {
580230592Sken		if (!mt_entry->init_complete) {
581230592Sken			if (mt_entry->missing_count < MPS_MAX_MISSING_COUNT)
582230592Sken				mt_entry->missing_count++;
583230592Sken			else
584230592Sken				mt_entry->init_complete = 1;
585230592Sken		}
586230592Sken		if (!mt_entry->missing_count)
587230592Sken			mt_entry->missing_count++;
588230592Sken		mt_entry->dev_handle = 0;
589230592Sken	}
590230592Sken
591230592Sken	dpm_idx = mt_entry->dpm_entry_num;
592230592Sken	if (dpm_idx == MPS_DPM_BAD_IDX) {
593230592Sken		if ((reason == MPI2_EVENT_IR_CHANGE_RC_ADDED) ||
594230592Sken		    (reason == MPI2_EVENT_IR_CHANGE_RC_REMOVED))
595230592Sken			dpm_idx = _mapping_get_dpm_idx_from_id(sc,
596230592Sken			    mt_entry->physical_id, 0);
597230592Sken		else if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED)
598230592Sken			return;
599230592Sken	}
600230592Sken	if (dpm_idx != MPS_DPM_BAD_IDX) {
601230592Sken		dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
602230592Sken		    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
603230592Sken		dpm_entry += dpm_idx;
604230592Sken		missing_cnt = dpm_entry->MappingInformation &
605230592Sken		    MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
606230592Sken		if ((mt_entry->physical_id ==
607230592Sken		    le64toh((u64)dpm_entry->PhysicalIdentifier.High |
608230592Sken		    dpm_entry->PhysicalIdentifier.Low)) && (missing_cnt ==
609230592Sken		    mt_entry->missing_count))
610230592Sken			mt_entry->init_complete = 1;
611230592Sken	} else {
612230592Sken		dpm_idx = _mapping_get_free_dpm_idx(sc);
613230592Sken		mt_entry->init_complete = 0;
614230592Sken	}
615230592Sken
616230592Sken	if ((dpm_idx != MPS_DPM_BAD_IDX) && !mt_entry->init_complete) {
617230592Sken		mt_entry->init_complete = 1;
618230592Sken		mt_entry->dpm_entry_num = dpm_idx;
619230592Sken		dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
620230592Sken		    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
621230592Sken		dpm_entry += dpm_idx;
622230592Sken		dpm_entry->PhysicalIdentifier.Low =
623230592Sken		    (0xFFFFFFFF & mt_entry->physical_id);
624230592Sken		dpm_entry->PhysicalIdentifier.High =
625230592Sken		    (mt_entry->physical_id >> 32);
626230592Sken		dpm_entry->DeviceIndex = map_idx;
627230592Sken		dpm_entry->MappingInformation = mt_entry->missing_count;
628230592Sken		dpm_entry->PhysicalBitsMapping = 0;
629230592Sken		dpm_entry->Reserved1 = 0;
630230592Sken		sc->dpm_flush_entry[dpm_idx] = 1;
631230592Sken		sc->dpm_entry_used[dpm_idx] = 1;
632230592Sken	} else if (dpm_idx == MPS_DPM_BAD_IDX) {
633230592Sken		printf("%s: no space to add entry in DPM table\n", __func__);
634230592Sken		mt_entry->init_complete = 1;
635230592Sken	}
636230592Sken}
637230592Sken
638230592Sken/**
639230592Sken * _mapping_add_to_removal_table - mark an entry for removal
640230592Sken * @sc: per adapter object
641230592Sken * @handle: Handle of enclosures/device/volume
642230592Sken *
643230592Sken * Adds the handle or DPM entry number in removal table.
644230592Sken *
645230592Sken * Returns nothing.
646230592Sken */
647230592Skenstatic void
648230592Sken_mapping_add_to_removal_table(struct mps_softc *sc, u16 handle,
649230592Sken    u16 dpm_idx)
650230592Sken{
651230592Sken	struct map_removal_table *remove_entry;
652230592Sken	u32 i;
653230592Sken	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
654230592Sken
655230592Sken	remove_entry = sc->removal_table;
656230592Sken
657230592Sken	for (i = 0; i < sc->max_devices; i++, remove_entry++) {
658230592Sken		if (remove_entry->dev_handle || remove_entry->dpm_entry_num !=
659230592Sken		    MPS_DPM_BAD_IDX)
660230592Sken			continue;
661230592Sken		if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
662230592Sken		    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
663230592Sken			if (dpm_idx)
664230592Sken				remove_entry->dpm_entry_num = dpm_idx;
665230592Sken			if (remove_entry->dpm_entry_num == MPS_DPM_BAD_IDX)
666230592Sken				remove_entry->dev_handle = handle;
667230592Sken		} else if ((ioc_pg8_flags &
668230592Sken		    MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
669230592Sken		    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING)
670230592Sken			remove_entry->dev_handle = handle;
671230592Sken		break;
672230592Sken	}
673230592Sken
674230592Sken}
675230592Sken
676230592Sken/**
677230592Sken * _mapping_update_missing_count - Update missing count for a device
678230592Sken * @sc: per adapter object
679230592Sken * @topo_change: Topology change event entry
680230592Sken *
681230592Sken * Search through the topology change list and if any device is found not
682230592Sken * responding it's associated map table entry and DPM entry is updated
683230592Sken *
684230592Sken * Returns nothing.
685230592Sken */
686230592Skenstatic void
687230592Sken_mapping_update_missing_count(struct mps_softc *sc,
688230592Sken    struct _map_topology_change *topo_change)
689230592Sken{
690230592Sken	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
691230592Sken	u8 entry;
692230592Sken	struct _map_phy_change *phy_change;
693230592Sken	u32 map_idx;
694230592Sken	struct dev_mapping_table *mt_entry;
695230592Sken	Mpi2DriverMap0Entry_t *dpm_entry;
696230592Sken
697230592Sken	for (entry = 0; entry < topo_change->num_entries; entry++) {
698230592Sken		phy_change = &topo_change->phy_details[entry];
699230592Sken		if (!phy_change->dev_handle || (phy_change->reason !=
700230592Sken		    MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING))
701230592Sken			continue;
702230592Sken		map_idx = _mapping_get_mt_idx_from_handle(sc, phy_change->
703230592Sken		    dev_handle);
704230592Sken		phy_change->is_processed = 1;
705230592Sken		if (map_idx == MPS_MAPTABLE_BAD_IDX) {
706230592Sken			printf("%s: device is already removed from mapping "
707230592Sken			    "table\n", __func__);
708230592Sken			continue;
709230592Sken		}
710230592Sken		mt_entry = &sc->mapping_table[map_idx];
711230592Sken		if (!mt_entry->init_complete) {
712230592Sken			if (mt_entry->missing_count < MPS_MAX_MISSING_COUNT)
713230592Sken				mt_entry->missing_count++;
714230592Sken			else
715230592Sken				mt_entry->init_complete = 1;
716230592Sken		}
717230592Sken		if (!mt_entry->missing_count)
718230592Sken			mt_entry->missing_count++;
719230592Sken		_mapping_add_to_removal_table(sc, mt_entry->dev_handle, 0);
720230592Sken		mt_entry->dev_handle = 0;
721230592Sken
722230592Sken		if (((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
723230592Sken		    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) &&
724230592Sken		    sc->is_dpm_enable && !mt_entry->init_complete &&
725230592Sken		    mt_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
726230592Sken			dpm_entry =
727230592Sken			    (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
728230592Sken			    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
729230592Sken			dpm_entry += mt_entry->dpm_entry_num;
730230592Sken			dpm_entry->MappingInformation = mt_entry->missing_count;
731230592Sken			sc->dpm_flush_entry[mt_entry->dpm_entry_num] = 1;
732230592Sken		}
733230592Sken		mt_entry->init_complete = 1;
734230592Sken	}
735230592Sken}
736230592Sken
737230592Sken/**
738230592Sken * _mapping_find_enc_map_space -find map table entries for enclosure
739230592Sken * @sc: per adapter object
740230592Sken * @et_entry: enclosure entry
741230592Sken *
742230592Sken * Search through the mapping table defragment it and provide contiguous
743230592Sken * space in map table for a particular enclosure entry
744230592Sken *
745230592Sken * Returns start index in map table or bad index.
746230592Sken */
747230592Skenstatic u32
748230592Sken_mapping_find_enc_map_space(struct mps_softc *sc,
749230592Sken    struct enc_mapping_table *et_entry)
750230592Sken{
751230592Sken	u16 vol_mapping_flags;
752230592Sken	u32 skip_count, end_of_table, map_idx, enc_idx;
753230592Sken	u16 num_found;
754230592Sken	u32 start_idx = MPS_MAPTABLE_BAD_IDX;
755230592Sken	struct dev_mapping_table *mt_entry;
756230592Sken	struct enc_mapping_table *enc_entry;
757230592Sken	unsigned char done_flag = 0, found_space;
758230592Sken	u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
759230592Sken
760230592Sken	skip_count = sc->num_rsvd_entries;
761230592Sken	num_found = 0;
762230592Sken
763230592Sken	vol_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
764230592Sken	    MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
765230592Sken
766230592Sken	if (!sc->ir_firmware)
767230592Sken		end_of_table = sc->max_devices;
768230592Sken	else if (vol_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING)
769230592Sken		end_of_table = sc->max_devices;
770230592Sken	else
771230592Sken		end_of_table = sc->max_devices - sc->max_volumes;
772230592Sken
773230592Sken	for (map_idx = (max_num_phy_ids + skip_count);
774230592Sken	    map_idx < end_of_table; map_idx++) {
775230592Sken		mt_entry = &sc->mapping_table[map_idx];
776230592Sken		if ((et_entry->enclosure_id == mt_entry->physical_id) &&
777230592Sken		    (!mt_entry->phy_bits || (mt_entry->phy_bits &
778230592Sken		    et_entry->phy_bits))) {
779230592Sken			num_found += 1;
780230592Sken			if (num_found == et_entry->num_slots) {
781230592Sken				start_idx = (map_idx - num_found) + 1;
782230592Sken				return start_idx;
783230592Sken			}
784230592Sken		} else
785230592Sken			num_found = 0;
786230592Sken	}
787230592Sken	for (map_idx = (max_num_phy_ids + skip_count);
788230592Sken	    map_idx < end_of_table; map_idx++) {
789230592Sken		mt_entry = &sc->mapping_table[map_idx];
790230592Sken		if (!(mt_entry->device_info & MPS_DEV_RESERVED)) {
791230592Sken			num_found += 1;
792230592Sken			if (num_found == et_entry->num_slots) {
793230592Sken				start_idx = (map_idx - num_found) + 1;
794230592Sken				return start_idx;
795230592Sken			}
796230592Sken		} else
797230592Sken			num_found = 0;
798230592Sken	}
799230592Sken
800230592Sken	while (!done_flag) {
801230592Sken		enc_idx = _mapping_get_high_missing_et_idx(sc);
802230592Sken		if (enc_idx == MPS_ENCTABLE_BAD_IDX)
803230592Sken			return MPS_MAPTABLE_BAD_IDX;
804230592Sken		enc_entry = &sc->enclosure_table[enc_idx];
805230592Sken		/*VSP FIXME*/
806230592Sken		enc_entry->skip_search = 1;
807230592Sken		mt_entry = &sc->mapping_table[enc_entry->start_index];
808230592Sken		for (map_idx = enc_entry->start_index; map_idx <
809230592Sken		    (enc_entry->start_index + enc_entry->num_slots); map_idx++,
810230592Sken		    mt_entry++)
811230592Sken			mt_entry->device_info  &= ~MPS_DEV_RESERVED;
812230592Sken		found_space = 0;
813230592Sken		for (map_idx = (max_num_phy_ids +
814230592Sken		    skip_count); map_idx < end_of_table; map_idx++) {
815230592Sken			mt_entry = &sc->mapping_table[map_idx];
816230592Sken			if (!(mt_entry->device_info & MPS_DEV_RESERVED)) {
817230592Sken				num_found += 1;
818230592Sken				if (num_found == et_entry->num_slots) {
819230592Sken					start_idx = (map_idx - num_found) + 1;
820230592Sken					found_space = 1;
821230592Sken				}
822230592Sken			} else
823230592Sken				num_found = 0;
824230592Sken		}
825230592Sken
826230592Sken		if (!found_space)
827230592Sken			continue;
828230592Sken		for (map_idx = start_idx; map_idx < (start_idx + num_found);
829230592Sken		    map_idx++) {
830230592Sken			enc_entry = sc->enclosure_table;
831230592Sken			for (enc_idx = 0; enc_idx < sc->num_enc_table_entries;
832230592Sken			    enc_idx++, enc_entry++) {
833230592Sken				if (map_idx < enc_entry->start_index ||
834230592Sken				    map_idx > (enc_entry->start_index +
835230592Sken				    enc_entry->num_slots))
836230592Sken					continue;
837230592Sken				if (!enc_entry->removal_flag) {
838230592Sken					enc_entry->removal_flag = 1;
839230592Sken					_mapping_add_to_removal_table(sc, 0,
840230592Sken					    enc_entry->dpm_entry_num);
841230592Sken				}
842230592Sken				mt_entry = &sc->mapping_table[map_idx];
843230592Sken				if (mt_entry->device_info &
844230592Sken				    MPS_MAP_IN_USE) {
845230592Sken					_mapping_add_to_removal_table(sc,
846230592Sken					    mt_entry->dev_handle, 0);
847230592Sken					_mapping_clear_map_entry(mt_entry);
848230592Sken				}
849230592Sken				if (map_idx == (enc_entry->start_index +
850230592Sken				    enc_entry->num_slots - 1))
851230592Sken					_mapping_clear_enc_entry(et_entry);
852230592Sken			}
853230592Sken		}
854230592Sken		enc_entry = sc->enclosure_table;
855230592Sken		for (enc_idx = 0; enc_idx < sc->num_enc_table_entries;
856230592Sken		    enc_idx++, enc_entry++) {
857230592Sken			if (!enc_entry->removal_flag) {
858230592Sken				mt_entry = &sc->mapping_table[enc_entry->
859230592Sken				    start_index];
860230592Sken				for (map_idx = enc_entry->start_index; map_idx <
861230592Sken				    (enc_entry->start_index +
862230592Sken				    enc_entry->num_slots); map_idx++,
863230592Sken				    mt_entry++)
864230592Sken					mt_entry->device_info |=
865230592Sken					    MPS_DEV_RESERVED;
866230592Sken				et_entry->skip_search = 0;
867230592Sken			}
868230592Sken		}
869230592Sken		done_flag = 1;
870230592Sken	}
871230592Sken	return start_idx;
872230592Sken}
873230592Sken
874230592Sken/**
875230592Sken * _mapping_get_dev_info -get information about newly added devices
876230592Sken * @sc: per adapter object
877230592Sken * @topo_change: Topology change event entry
878230592Sken *
879230592Sken * Search through the topology change event list and issues sas device pg0
880230592Sken * requests for the newly added device and reserved entries in tables
881230592Sken *
882230592Sken * Returns nothing
883230592Sken */
884230592Skenstatic void
885230592Sken_mapping_get_dev_info(struct mps_softc *sc,
886230592Sken    struct _map_topology_change *topo_change)
887230592Sken{
888230592Sken	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
889230592Sken	Mpi2ConfigReply_t mpi_reply;
890230592Sken	Mpi2SasDevicePage0_t sas_device_pg0;
891230592Sken	u8 entry, enc_idx, phy_idx;
892230592Sken	u32 map_idx, index, device_info;
893230592Sken	struct _map_phy_change *phy_change, *tmp_phy_change;
894230592Sken	uint64_t sas_address;
895230592Sken	struct enc_mapping_table *et_entry;
896230592Sken	struct dev_mapping_table *mt_entry;
897230592Sken	u8 add_code = MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED;
898230592Sken	int rc;
899230592Sken
900230592Sken	for (entry = 0; entry < topo_change->num_entries; entry++) {
901230592Sken		phy_change = &topo_change->phy_details[entry];
902230592Sken		if (phy_change->is_processed || !phy_change->dev_handle ||
903230592Sken		    phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED)
904230592Sken			continue;
905230592Sken		if (mps_config_get_sas_device_pg0(sc, &mpi_reply,
906230592Sken		    &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
907230592Sken		    phy_change->dev_handle)) {
908230592Sken			phy_change->is_processed = 1;
909230592Sken			continue;
910230592Sken		}
911230592Sken
912230592Sken		device_info = le32toh(sas_device_pg0.DeviceInfo);
913230592Sken		if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
914230592Sken		    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
915230592Sken			if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) &&
916230592Sken			    (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) {
917230592Sken				rc = mpssas_get_sas_address_for_sata_disk(sc,
918230592Sken				    &sas_address, phy_change->dev_handle,
919230592Sken				    device_info);
920230592Sken				if (rc) {
921230592Sken					printf("%s: failed to compute the "
922230592Sken					    "hashed SAS Address for SATA "
923230592Sken					    "device with handle 0x%04x\n",
924230592Sken					    __func__, phy_change->dev_handle);
925230592Sken					sas_address =
926230592Sken					    sas_device_pg0.SASAddress.High;
927230592Sken					sas_address = (sas_address << 32) |
928230592Sken					    sas_device_pg0.SASAddress.Low;
929230592Sken				}
930254938Sken				mps_dprint(sc, MPS_MAPPING,
931254938Sken				    "SAS Address for SATA device = %jx\n",
932254938Sken				    sas_address);
933230592Sken			} else {
934230592Sken				sas_address =
935230592Sken					sas_device_pg0.SASAddress.High;
936230592Sken				sas_address = (sas_address << 32) |
937230592Sken					sas_device_pg0.SASAddress.Low;
938230592Sken			}
939230592Sken		} else {
940230592Sken			sas_address = sas_device_pg0.SASAddress.High;
941230592Sken			sas_address = (sas_address << 32) |
942230592Sken			   sas_device_pg0.SASAddress.Low;
943230592Sken		}
944230592Sken		phy_change->physical_id = sas_address;
945230592Sken		phy_change->slot = le16toh(sas_device_pg0.Slot);
946230592Sken		phy_change->device_info =
947230592Sken		    le32toh(sas_device_pg0.DeviceInfo);
948230592Sken
949230592Sken		if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
950230592Sken		    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
951230592Sken			enc_idx = _mapping_get_enc_idx_from_handle(sc,
952230592Sken			    topo_change->enc_handle);
953230592Sken			if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
954230592Sken				phy_change->is_processed = 1;
955230592Sken				printf("%s: failed to add the device with "
956230592Sken				    "handle 0x%04x because the enclosure is "
957230592Sken				    "not in the mapping table\n", __func__,
958230592Sken				    phy_change->dev_handle);
959230592Sken				continue;
960230592Sken			}
961230592Sken			if (!((phy_change->device_info &
962230592Sken			    MPI2_SAS_DEVICE_INFO_END_DEVICE) &&
963230592Sken			    (phy_change->device_info &
964230592Sken			    (MPI2_SAS_DEVICE_INFO_SSP_TARGET |
965230592Sken			    MPI2_SAS_DEVICE_INFO_STP_TARGET |
966230592Sken			    MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))) {
967230592Sken				phy_change->is_processed = 1;
968230592Sken				continue;
969230592Sken			}
970230592Sken			et_entry = &sc->enclosure_table[enc_idx];
971230592Sken			if (et_entry->start_index != MPS_MAPTABLE_BAD_IDX)
972230592Sken				continue;
973230592Sken			if (!topo_change->exp_handle) {
974230592Sken				map_idx	= sc->num_rsvd_entries;
975230592Sken				et_entry->start_index = map_idx;
976230592Sken			} else {
977230592Sken				map_idx = _mapping_find_enc_map_space(sc,
978230592Sken				    et_entry);
979230592Sken				et_entry->start_index = map_idx;
980230592Sken				if (et_entry->start_index ==
981230592Sken				    MPS_MAPTABLE_BAD_IDX) {
982230592Sken					phy_change->is_processed = 1;
983230592Sken					for (phy_idx = 0; phy_idx <
984230592Sken					    topo_change->num_entries;
985230592Sken					    phy_idx++) {
986230592Sken						tmp_phy_change =
987230592Sken						    &topo_change->phy_details
988230592Sken						    [phy_idx];
989230592Sken						if (tmp_phy_change->reason ==
990230592Sken						    add_code)
991230592Sken							tmp_phy_change->
992230592Sken							    is_processed = 1;
993230592Sken					}
994230592Sken					break;
995230592Sken				}
996230592Sken			}
997230592Sken			mt_entry = &sc->mapping_table[map_idx];
998230592Sken			for (index = map_idx; index < (et_entry->num_slots
999230592Sken			    + map_idx); index++, mt_entry++) {
1000230592Sken				mt_entry->device_info = MPS_DEV_RESERVED;
1001230592Sken				mt_entry->physical_id = et_entry->enclosure_id;
1002230592Sken				mt_entry->phy_bits = et_entry->phy_bits;
1003230592Sken			}
1004230592Sken		}
1005230592Sken	}
1006230592Sken}
1007230592Sken
1008230592Sken/**
1009230592Sken * _mapping_set_mid_to_eid -set map table data from enclosure table
1010230592Sken * @sc: per adapter object
1011230592Sken * @et_entry: enclosure entry
1012230592Sken *
1013230592Sken * Returns nothing
1014230592Sken */
1015230592Skenstatic inline void
1016230592Sken_mapping_set_mid_to_eid(struct mps_softc *sc,
1017230592Sken    struct enc_mapping_table *et_entry)
1018230592Sken{
1019230592Sken	struct dev_mapping_table *mt_entry;
1020230592Sken	u16 slots = et_entry->num_slots, map_idx;
1021230592Sken	u32 start_idx = et_entry->start_index;
1022230592Sken	if (start_idx != MPS_MAPTABLE_BAD_IDX) {
1023230592Sken		mt_entry = &sc->mapping_table[start_idx];
1024230592Sken		for (map_idx = 0; map_idx < slots; map_idx++, mt_entry++)
1025230592Sken			mt_entry->physical_id = et_entry->enclosure_id;
1026230592Sken	}
1027230592Sken}
1028230592Sken
1029230592Sken/**
1030230592Sken * _mapping_clear_removed_entries - mark the entries to be cleared
1031230592Sken * @sc: per adapter object
1032230592Sken *
1033230592Sken * Search through the removal table and mark the entries which needs to be
1034230592Sken * flushed to DPM and also updates the map table and enclosure table by
1035230592Sken * clearing the corresponding entries.
1036230592Sken *
1037230592Sken * Returns nothing
1038230592Sken */
1039230592Skenstatic void
1040230592Sken_mapping_clear_removed_entries(struct mps_softc *sc)
1041230592Sken{
1042230592Sken	u32 remove_idx;
1043230592Sken	struct map_removal_table *remove_entry;
1044230592Sken	Mpi2DriverMap0Entry_t *dpm_entry;
1045230592Sken	u8 done_flag = 0, num_entries, m, i;
1046230592Sken	struct enc_mapping_table *et_entry, *from, *to;
1047230592Sken	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1048230592Sken
1049230592Sken	if (sc->is_dpm_enable) {
1050230592Sken		remove_entry = sc->removal_table;
1051230592Sken		for (remove_idx = 0; remove_idx < sc->max_devices;
1052230592Sken		    remove_idx++, remove_entry++) {
1053230592Sken			if (remove_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
1054230592Sken				dpm_entry = (Mpi2DriverMap0Entry_t *)
1055230592Sken				    ((u8 *) sc->dpm_pg0 +
1056230592Sken				    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1057230592Sken				dpm_entry += remove_entry->dpm_entry_num;
1058230592Sken				dpm_entry->PhysicalIdentifier.Low = 0;
1059230592Sken				dpm_entry->PhysicalIdentifier.High = 0;
1060230592Sken				dpm_entry->DeviceIndex = 0;
1061230592Sken				dpm_entry->MappingInformation = 0;
1062230592Sken				dpm_entry->PhysicalBitsMapping = 0;
1063230592Sken				sc->dpm_flush_entry[remove_entry->
1064230592Sken				    dpm_entry_num] = 1;
1065230592Sken				sc->dpm_entry_used[remove_entry->dpm_entry_num]
1066230592Sken				    = 0;
1067230592Sken				remove_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
1068230592Sken			}
1069230592Sken		}
1070230592Sken	}
1071230592Sken	if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1072230592Sken	    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1073230592Sken		num_entries = sc->num_enc_table_entries;
1074230592Sken		while (!done_flag) {
1075230592Sken			done_flag = 1;
1076230592Sken			et_entry = sc->enclosure_table;
1077230592Sken			for (i = 0; i < num_entries; i++, et_entry++) {
1078230592Sken				if (!et_entry->enc_handle && et_entry->
1079230592Sken				    init_complete) {
1080230592Sken					done_flag = 0;
1081230592Sken					if (i != (num_entries - 1)) {
1082230592Sken						from = &sc->enclosure_table
1083230592Sken						    [i+1];
1084230592Sken						to = &sc->enclosure_table[i];
1085230592Sken						for (m = i; m < (num_entries -
1086230592Sken						    1); m++, from++, to++) {
1087230592Sken							_mapping_set_mid_to_eid
1088230592Sken							    (sc, to);
1089230592Sken							*to = *from;
1090230592Sken						}
1091230592Sken						_mapping_clear_enc_entry(to);
1092230592Sken						sc->num_enc_table_entries--;
1093230592Sken						num_entries =
1094230592Sken						    sc->num_enc_table_entries;
1095230592Sken					} else {
1096230592Sken						_mapping_clear_enc_entry
1097230592Sken						    (et_entry);
1098230592Sken						sc->num_enc_table_entries--;
1099230592Sken						num_entries =
1100230592Sken						    sc->num_enc_table_entries;
1101230592Sken					}
1102230592Sken				}
1103230592Sken			}
1104230592Sken		}
1105230592Sken	}
1106230592Sken}
1107230592Sken
1108230592Sken/**
1109230592Sken * _mapping_add_new_device -Add the new device into mapping table
1110230592Sken * @sc: per adapter object
1111230592Sken * @topo_change: Topology change event entry
1112230592Sken *
1113230592Sken * Search through the topology change event list and updates map table,
1114230592Sken * enclosure table and DPM pages for for the newly added devices.
1115230592Sken *
1116230592Sken * Returns nothing
1117230592Sken */
1118230592Skenstatic void
1119230592Sken_mapping_add_new_device(struct mps_softc *sc,
1120230592Sken    struct _map_topology_change *topo_change)
1121230592Sken{
1122230592Sken	u8 enc_idx, missing_cnt, is_removed = 0;
1123230592Sken	u16 dpm_idx;
1124230592Sken	u32 search_idx, map_idx;
1125230592Sken	u32 entry;
1126230592Sken	struct dev_mapping_table *mt_entry;
1127230592Sken	struct enc_mapping_table *et_entry;
1128230592Sken	struct _map_phy_change *phy_change;
1129230592Sken	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1130230592Sken	Mpi2DriverMap0Entry_t *dpm_entry;
1131230592Sken	uint64_t temp64_var;
1132230592Sken	u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
1133230592Sken	u8 hdr_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER);
1134230592Sken	u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
1135230592Sken
1136230592Sken	for (entry = 0; entry < topo_change->num_entries; entry++) {
1137230592Sken		phy_change = &topo_change->phy_details[entry];
1138230592Sken		if (phy_change->is_processed)
1139230592Sken			continue;
1140230592Sken		if (phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED ||
1141230592Sken		    !phy_change->dev_handle) {
1142230592Sken			phy_change->is_processed = 1;
1143230592Sken			continue;
1144230592Sken		}
1145230592Sken		if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1146230592Sken		    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1147230592Sken			enc_idx = _mapping_get_enc_idx_from_handle
1148230592Sken			    (sc, topo_change->enc_handle);
1149230592Sken			if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
1150230592Sken				phy_change->is_processed = 1;
1151230592Sken				printf("%s: failed to add the device with "
1152230592Sken				    "handle 0x%04x because the enclosure is "
1153230592Sken				    "not in the mapping table\n", __func__,
1154230592Sken				    phy_change->dev_handle);
1155230592Sken				continue;
1156230592Sken			}
1157230592Sken			et_entry = &sc->enclosure_table[enc_idx];
1158230592Sken			if (et_entry->start_index == MPS_MAPTABLE_BAD_IDX) {
1159230592Sken				phy_change->is_processed = 1;
1160230592Sken				if (!sc->mt_full_retry) {
1161230592Sken					sc->mt_add_device_failed = 1;
1162230592Sken					continue;
1163230592Sken				}
1164230592Sken				printf("%s: failed to add the device with "
1165230592Sken				    "handle 0x%04x because there is no free "
1166230592Sken				    "space available in the mapping table\n",
1167230592Sken				    __func__, phy_change->dev_handle);
1168230592Sken				continue;
1169230592Sken			}
1170230592Sken			map_idx = et_entry->start_index + phy_change->slot -
1171230592Sken			    et_entry->start_slot;
1172230592Sken			mt_entry = &sc->mapping_table[map_idx];
1173230592Sken			mt_entry->physical_id = phy_change->physical_id;
1174230592Sken			mt_entry->channel = 0;
1175230592Sken			mt_entry->id = map_idx;
1176230592Sken			mt_entry->dev_handle = phy_change->dev_handle;
1177230592Sken			mt_entry->missing_count = 0;
1178230592Sken			mt_entry->dpm_entry_num = et_entry->dpm_entry_num;
1179230592Sken			mt_entry->device_info = phy_change->device_info |
1180230592Sken			    (MPS_DEV_RESERVED | MPS_MAP_IN_USE);
1181230592Sken			if (sc->is_dpm_enable) {
1182230592Sken				dpm_idx = et_entry->dpm_entry_num;
1183230592Sken				if (dpm_idx == MPS_DPM_BAD_IDX)
1184230592Sken					dpm_idx = _mapping_get_dpm_idx_from_id
1185230592Sken					    (sc, et_entry->enclosure_id,
1186230592Sken					     et_entry->phy_bits);
1187230592Sken				if (dpm_idx == MPS_DPM_BAD_IDX) {
1188230592Sken					dpm_idx = _mapping_get_free_dpm_idx(sc);
1189230592Sken					if (dpm_idx != MPS_DPM_BAD_IDX) {
1190230592Sken						dpm_entry =
1191230592Sken						    (Mpi2DriverMap0Entry_t *)
1192230592Sken						    ((u8 *) sc->dpm_pg0 +
1193230592Sken						     hdr_sz);
1194230592Sken						dpm_entry += dpm_idx;
1195230592Sken						dpm_entry->
1196230592Sken						    PhysicalIdentifier.Low =
1197230592Sken						    (0xFFFFFFFF &
1198230592Sken						    et_entry->enclosure_id);
1199230592Sken						dpm_entry->
1200230592Sken						    PhysicalIdentifier.High =
1201230592Sken						    ( et_entry->enclosure_id
1202230592Sken						     >> 32);
1203230592Sken						dpm_entry->DeviceIndex =
1204230592Sken						    (U16)et_entry->start_index;
1205230592Sken						dpm_entry->MappingInformation =
1206230592Sken							et_entry->num_slots;
1207230592Sken						dpm_entry->MappingInformation
1208230592Sken						    <<= map_shift;
1209230592Sken						dpm_entry->PhysicalBitsMapping
1210230592Sken						    = et_entry->phy_bits;
1211230592Sken						et_entry->dpm_entry_num =
1212230592Sken						    dpm_idx;
1213230592Sken		/* FIXME Do I need to set the dpm_idxin mt_entry too */
1214230592Sken						sc->dpm_entry_used[dpm_idx] = 1;
1215230592Sken						sc->dpm_flush_entry[dpm_idx] =
1216230592Sken						    1;
1217230592Sken						phy_change->is_processed = 1;
1218230592Sken					} else {
1219230592Sken						phy_change->is_processed = 1;
1220254938Sken						mps_dprint(sc, MPS_INFO, "%s: "
1221254938Sken						    "failed to add the device "
1222254938Sken						    "with handle 0x%04x to "
1223254938Sken						    "persistent table because "
1224254938Sken						    "there is no free space "
1225254938Sken						    "available\n", __func__,
1226230592Sken						    phy_change->dev_handle);
1227230592Sken					}
1228230592Sken				} else {
1229230592Sken					et_entry->dpm_entry_num = dpm_idx;
1230230592Sken					mt_entry->dpm_entry_num = dpm_idx;
1231230592Sken				}
1232230592Sken			}
1233230592Sken			/* FIXME Why not mt_entry too? */
1234230592Sken			et_entry->init_complete = 1;
1235230592Sken		} else if ((ioc_pg8_flags &
1236230592Sken		    MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1237230592Sken		    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
1238230592Sken			map_idx = _mapping_get_mt_idx_from_id
1239230592Sken			    (sc, phy_change->physical_id);
1240230592Sken			if (map_idx == MPS_MAPTABLE_BAD_IDX) {
1241230592Sken				search_idx = sc->num_rsvd_entries;
1242230592Sken				if (topo_change->exp_handle)
1243230592Sken					search_idx += max_num_phy_ids;
1244230592Sken				map_idx = _mapping_get_free_mt_idx(sc,
1245230592Sken				    search_idx);
1246230592Sken			}
1247230592Sken			if (map_idx == MPS_MAPTABLE_BAD_IDX) {
1248230592Sken				map_idx = _mapping_get_high_missing_mt_idx(sc);
1249230592Sken				if (map_idx != MPS_MAPTABLE_BAD_IDX) {
1250230592Sken					mt_entry = &sc->mapping_table[map_idx];
1251230592Sken					if (mt_entry->dev_handle) {
1252230592Sken						_mapping_add_to_removal_table
1253230592Sken						    (sc, mt_entry->dev_handle,
1254230592Sken						     0);
1255230592Sken						is_removed = 1;
1256230592Sken					}
1257230592Sken					mt_entry->init_complete = 0;
1258230592Sken				}
1259230592Sken			}
1260230592Sken			if (map_idx != MPS_MAPTABLE_BAD_IDX) {
1261230592Sken				mt_entry = &sc->mapping_table[map_idx];
1262230592Sken				mt_entry->physical_id = phy_change->physical_id;
1263230592Sken				mt_entry->channel = 0;
1264230592Sken				mt_entry->id = map_idx;
1265230592Sken				mt_entry->dev_handle = phy_change->dev_handle;
1266230592Sken				mt_entry->missing_count = 0;
1267230592Sken				mt_entry->device_info = phy_change->device_info
1268230592Sken				    | (MPS_DEV_RESERVED | MPS_MAP_IN_USE);
1269230592Sken			} else {
1270230592Sken				phy_change->is_processed = 1;
1271230592Sken				if (!sc->mt_full_retry) {
1272230592Sken					sc->mt_add_device_failed = 1;
1273230592Sken					continue;
1274230592Sken				}
1275230592Sken				printf("%s: failed to add the device with "
1276230592Sken				    "handle 0x%04x because there is no free "
1277230592Sken				    "space available in the mapping table\n",
1278230592Sken				    __func__, phy_change->dev_handle);
1279230592Sken				continue;
1280230592Sken			}
1281230592Sken			if (sc->is_dpm_enable) {
1282230592Sken				if (mt_entry->dpm_entry_num !=
1283230592Sken				    MPS_DPM_BAD_IDX) {
1284230592Sken					dpm_idx = mt_entry->dpm_entry_num;
1285230592Sken					dpm_entry = (Mpi2DriverMap0Entry_t *)
1286230592Sken					    ((u8 *)sc->dpm_pg0 + hdr_sz);
1287230592Sken					dpm_entry += dpm_idx;
1288230592Sken					missing_cnt = dpm_entry->
1289230592Sken					    MappingInformation &
1290230592Sken					    MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
1291230592Sken					temp64_var = dpm_entry->
1292230592Sken					    PhysicalIdentifier.High;
1293230592Sken					temp64_var = (temp64_var << 32) |
1294230592Sken					   dpm_entry->PhysicalIdentifier.Low;
1295230592Sken					if ((mt_entry->physical_id ==
1296230592Sken					    temp64_var) && !missing_cnt)
1297230592Sken						mt_entry->init_complete = 1;
1298230592Sken				} else {
1299230592Sken					dpm_idx = _mapping_get_free_dpm_idx(sc);
1300230592Sken					mt_entry->init_complete = 0;
1301230592Sken				}
1302230592Sken				if (dpm_idx != MPS_DPM_BAD_IDX &&
1303230592Sken				    !mt_entry->init_complete) {
1304230592Sken					mt_entry->init_complete = 1;
1305230592Sken					mt_entry->dpm_entry_num = dpm_idx;
1306230592Sken					dpm_entry = (Mpi2DriverMap0Entry_t *)
1307230592Sken					    ((u8 *)sc->dpm_pg0 + hdr_sz);
1308230592Sken					dpm_entry += dpm_idx;
1309230592Sken					dpm_entry->PhysicalIdentifier.Low =
1310230592Sken					    (0xFFFFFFFF &
1311230592Sken					    mt_entry->physical_id);
1312230592Sken					dpm_entry->PhysicalIdentifier.High =
1313230592Sken					    (mt_entry->physical_id >> 32);
1314230592Sken					dpm_entry->DeviceIndex = (U16) map_idx;
1315230592Sken					dpm_entry->MappingInformation = 0;
1316230592Sken					dpm_entry->PhysicalBitsMapping = 0;
1317230592Sken					sc->dpm_entry_used[dpm_idx] = 1;
1318230592Sken					sc->dpm_flush_entry[dpm_idx] = 1;
1319230592Sken					phy_change->is_processed = 1;
1320230592Sken				} else if (dpm_idx == MPS_DPM_BAD_IDX) {
1321230592Sken						phy_change->is_processed = 1;
1322254938Sken						mps_dprint(sc, MPS_INFO, "%s: "
1323254938Sken						    "failed to add the device "
1324254938Sken						    "with handle 0x%04x to "
1325254938Sken						    "persistent table because "
1326254938Sken						    "there is no free space "
1327254938Sken						    "available\n", __func__,
1328230592Sken						    phy_change->dev_handle);
1329230592Sken				}
1330230592Sken			}
1331230592Sken			mt_entry->init_complete = 1;
1332230592Sken		}
1333230592Sken
1334230592Sken		phy_change->is_processed = 1;
1335230592Sken	}
1336230592Sken	if (is_removed)
1337230592Sken		_mapping_clear_removed_entries(sc);
1338230592Sken}
1339230592Sken
1340230592Sken/**
1341230592Sken * _mapping_flush_dpm_pages -Flush the DPM pages to NVRAM
1342230592Sken * @sc: per adapter object
1343230592Sken *
1344230592Sken * Returns nothing
1345230592Sken */
1346230592Skenstatic void
1347230592Sken_mapping_flush_dpm_pages(struct mps_softc *sc)
1348230592Sken{
1349230592Sken	Mpi2DriverMap0Entry_t *dpm_entry;
1350230592Sken	Mpi2ConfigReply_t mpi_reply;
1351230592Sken	Mpi2DriverMappingPage0_t config_page;
1352230592Sken	u16 entry_num;
1353230592Sken
1354230592Sken	for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) {
1355230592Sken		if (!sc->dpm_flush_entry[entry_num])
1356230592Sken			continue;
1357230592Sken		memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
1358230592Sken		memcpy(&config_page.Header, (u8 *)sc->dpm_pg0,
1359230592Sken		    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1360230592Sken		dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
1361230592Sken		    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1362230592Sken		dpm_entry += entry_num;
1363230592Sken		dpm_entry->MappingInformation = htole16(dpm_entry->
1364230592Sken		    MappingInformation);
1365230592Sken		dpm_entry->DeviceIndex = htole16(dpm_entry->DeviceIndex);
1366230592Sken		dpm_entry->PhysicalBitsMapping = htole32(dpm_entry->
1367230592Sken		    PhysicalBitsMapping);
1368230592Sken		memcpy(&config_page.Entry, (u8 *)dpm_entry,
1369230592Sken		    sizeof(Mpi2DriverMap0Entry_t));
1370230592Sken		/* TODO-How to handle failed writes? */
1371230592Sken		if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
1372230592Sken		    entry_num)) {
1373230592Sken			printf("%s: write of dpm entry %d for device failed\n",
1374230592Sken			     __func__, entry_num);
1375230592Sken		} else
1376230592Sken			sc->dpm_flush_entry[entry_num] = 0;
1377230592Sken		dpm_entry->MappingInformation = le16toh(dpm_entry->
1378230592Sken		    MappingInformation);
1379230592Sken		dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
1380230592Sken		dpm_entry->PhysicalBitsMapping = le32toh(dpm_entry->
1381230592Sken		    PhysicalBitsMapping);
1382230592Sken	}
1383230592Sken}
1384230592Sken
1385230592Sken/**
1386230592Sken * _mapping_allocate_memory- allocates the memory required for mapping tables
1387230592Sken * @sc: per adapter object
1388230592Sken *
1389230592Sken * Allocates the memory for all the tables required for host mapping
1390230592Sken *
1391230592Sken * Return 0 on success or non-zero on failure.
1392230592Sken */
1393230592Skenint
1394230592Skenmps_mapping_allocate_memory(struct mps_softc *sc)
1395230592Sken{
1396230592Sken	uint32_t dpm_pg0_sz;
1397230592Sken
1398230592Sken	sc->mapping_table = malloc((sizeof(struct dev_mapping_table) *
1399230592Sken	    sc->max_devices), M_MPT2, M_ZERO|M_NOWAIT);
1400230592Sken	if (!sc->mapping_table)
1401230592Sken		goto free_resources;
1402230592Sken
1403230592Sken	sc->removal_table = malloc((sizeof(struct map_removal_table) *
1404230592Sken	    sc->max_devices), M_MPT2, M_ZERO|M_NOWAIT);
1405230592Sken	if (!sc->removal_table)
1406230592Sken		goto free_resources;
1407230592Sken
1408230592Sken	sc->enclosure_table = malloc((sizeof(struct enc_mapping_table) *
1409230592Sken	    sc->max_enclosures), M_MPT2, M_ZERO|M_NOWAIT);
1410230592Sken	if (!sc->enclosure_table)
1411230592Sken		goto free_resources;
1412230592Sken
1413230592Sken	sc->dpm_entry_used = malloc((sizeof(u8) * sc->max_dpm_entries),
1414230592Sken	    M_MPT2, M_ZERO|M_NOWAIT);
1415230592Sken	if (!sc->dpm_entry_used)
1416230592Sken		goto free_resources;
1417230592Sken
1418230592Sken	sc->dpm_flush_entry = malloc((sizeof(u8) * sc->max_dpm_entries),
1419230592Sken	    M_MPT2, M_ZERO|M_NOWAIT);
1420230592Sken	if (!sc->dpm_flush_entry)
1421230592Sken		goto free_resources;
1422230592Sken
1423230592Sken	dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) +
1424230592Sken	    (sc->max_dpm_entries * sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY));
1425230592Sken
1426230592Sken	sc->dpm_pg0 = malloc(dpm_pg0_sz, M_MPT2, M_ZERO|M_NOWAIT);
1427230592Sken	if (!sc->dpm_pg0) {
1428230592Sken		printf("%s: memory alloc failed for dpm page; disabling dpm\n",
1429230592Sken		    __func__);
1430230592Sken		sc->is_dpm_enable = 0;
1431230592Sken	}
1432230592Sken
1433230592Sken	return 0;
1434230592Sken
1435230592Skenfree_resources:
1436230592Sken	free(sc->mapping_table, M_MPT2);
1437230592Sken	free(sc->removal_table, M_MPT2);
1438230592Sken	free(sc->enclosure_table, M_MPT2);
1439230592Sken	free(sc->dpm_entry_used, M_MPT2);
1440230592Sken	free(sc->dpm_flush_entry, M_MPT2);
1441230592Sken	free(sc->dpm_pg0, M_MPT2);
1442230592Sken	printf("%s: device initialization failed due to failure in mapping "
1443230592Sken	    "table memory allocation\n", __func__);
1444230592Sken	return -1;
1445230592Sken}
1446230592Sken
1447230592Sken/**
1448230592Sken * mps_mapping_free_memory- frees the memory allocated for mapping tables
1449230592Sken * @sc: per adapter object
1450230592Sken *
1451230592Sken * Returns nothing.
1452230592Sken */
1453230592Skenvoid
1454230592Skenmps_mapping_free_memory(struct mps_softc *sc)
1455230592Sken{
1456230592Sken	free(sc->mapping_table, M_MPT2);
1457230592Sken	free(sc->removal_table, M_MPT2);
1458230592Sken	free(sc->enclosure_table, M_MPT2);
1459230592Sken	free(sc->dpm_entry_used, M_MPT2);
1460230592Sken	free(sc->dpm_flush_entry, M_MPT2);
1461230592Sken	free(sc->dpm_pg0, M_MPT2);
1462230592Sken}
1463230592Sken
1464230592Sken
1465230592Skenstatic void
1466230592Sken_mapping_process_dpm_pg0(struct mps_softc *sc)
1467230592Sken{
1468230592Sken	u8 missing_cnt, enc_idx;
1469230592Sken	u16 slot_id, entry_num, num_slots;
1470230592Sken	u32 map_idx, dev_idx, start_idx, end_idx;
1471230592Sken	struct dev_mapping_table *mt_entry;
1472230592Sken	Mpi2DriverMap0Entry_t *dpm_entry;
1473230592Sken	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1474230592Sken	u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
1475230592Sken	struct enc_mapping_table *et_entry;
1476230592Sken	u64 physical_id;
1477230592Sken	u32 phy_bits = 0;
1478230592Sken
1479230592Sken	if (sc->ir_firmware)
1480230592Sken		_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
1481230592Sken
1482230592Sken	dpm_entry = (Mpi2DriverMap0Entry_t *) ((uint8_t *) sc->dpm_pg0 +
1483230592Sken	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1484230592Sken	for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++,
1485230592Sken	    dpm_entry++) {
1486230592Sken		physical_id = dpm_entry->PhysicalIdentifier.High;
1487230592Sken		physical_id = (physical_id << 32) |
1488230592Sken		    dpm_entry->PhysicalIdentifier.Low;
1489230592Sken		if (!physical_id) {
1490230592Sken			sc->dpm_entry_used[entry_num] = 0;
1491230592Sken			continue;
1492230592Sken		}
1493230592Sken		sc->dpm_entry_used[entry_num] = 1;
1494230592Sken		dpm_entry->MappingInformation = le16toh(dpm_entry->
1495230592Sken		    MappingInformation);
1496230592Sken		missing_cnt = dpm_entry->MappingInformation &
1497230592Sken		    MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
1498230592Sken		dev_idx = le16toh(dpm_entry->DeviceIndex);
1499230592Sken		phy_bits = le32toh(dpm_entry->PhysicalBitsMapping);
1500230592Sken		if (sc->ir_firmware && (dev_idx >= start_idx) &&
1501230592Sken		    (dev_idx <= end_idx)) {
1502230592Sken			mt_entry = &sc->mapping_table[dev_idx];
1503230592Sken			mt_entry->physical_id = dpm_entry->PhysicalIdentifier.High;
1504230592Sken			mt_entry->physical_id = (mt_entry->physical_id << 32) |
1505230592Sken			    dpm_entry->PhysicalIdentifier.Low;
1506230592Sken			mt_entry->channel = MPS_RAID_CHANNEL;
1507230592Sken			mt_entry->id = dev_idx;
1508230592Sken			mt_entry->missing_count = missing_cnt;
1509230592Sken			mt_entry->dpm_entry_num = entry_num;
1510230592Sken			mt_entry->device_info = MPS_DEV_RESERVED;
1511230592Sken			continue;
1512230592Sken		}
1513230592Sken		if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1514230592Sken		    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1515230592Sken			if (dev_idx <  (sc->num_rsvd_entries +
1516230592Sken			    max_num_phy_ids)) {
1517230592Sken				slot_id = 0;
1518230592Sken				if (ioc_pg8_flags &
1519230592Sken				    MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1)
1520230592Sken					slot_id = 1;
1521230592Sken				num_slots = max_num_phy_ids;
1522230592Sken			} else {
1523230592Sken				slot_id = 0;
1524230592Sken				num_slots = dpm_entry->MappingInformation &
1525230592Sken				    MPI2_DRVMAP0_MAPINFO_SLOT_MASK;
1526230592Sken				num_slots >>= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
1527230592Sken			}
1528230592Sken			enc_idx = sc->num_enc_table_entries;
1529230592Sken			if (enc_idx >= sc->max_enclosures) {
1530230592Sken				printf("%s: enclosure entries exceed max "
1531230592Sken				    "enclosures of %d\n", __func__,
1532230592Sken				    sc->max_enclosures);
1533230592Sken				break;
1534230592Sken			}
1535230592Sken			sc->num_enc_table_entries++;
1536230592Sken			et_entry = &sc->enclosure_table[enc_idx];
1537230592Sken			physical_id = dpm_entry->PhysicalIdentifier.High;
1538230592Sken			et_entry->enclosure_id = (physical_id << 32) |
1539230592Sken			    dpm_entry->PhysicalIdentifier.Low;
1540230592Sken			et_entry->start_index = dev_idx;
1541230592Sken			et_entry->dpm_entry_num = entry_num;
1542230592Sken			et_entry->num_slots = num_slots;
1543230592Sken			et_entry->start_slot = slot_id;
1544230592Sken			et_entry->missing_count = missing_cnt;
1545230592Sken			et_entry->phy_bits = phy_bits;
1546230592Sken
1547230592Sken			mt_entry = &sc->mapping_table[dev_idx];
1548230592Sken			for (map_idx = dev_idx; map_idx < (dev_idx + num_slots);
1549230592Sken			    map_idx++, mt_entry++) {
1550230592Sken				if (mt_entry->dpm_entry_num !=
1551230592Sken				    MPS_DPM_BAD_IDX) {
1552230592Sken					printf("%s: conflict in mapping table "
1553230592Sken					    "for enclosure %d\n", __func__,
1554230592Sken					    enc_idx);
1555230592Sken					break;
1556230592Sken				}
1557230592Sken				physical_id = dpm_entry->PhysicalIdentifier.High;
1558230592Sken				mt_entry->physical_id = (physical_id << 32) |
1559230592Sken				    dpm_entry->PhysicalIdentifier.Low;
1560230592Sken				mt_entry->phy_bits = phy_bits;
1561230592Sken				mt_entry->channel = 0;
1562230592Sken				mt_entry->id = dev_idx;
1563230592Sken				mt_entry->dpm_entry_num = entry_num;
1564230592Sken				mt_entry->missing_count = missing_cnt;
1565230592Sken				mt_entry->device_info = MPS_DEV_RESERVED;
1566230592Sken			}
1567230592Sken		} else if ((ioc_pg8_flags &
1568230592Sken		    MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1569230592Sken		    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
1570230592Sken			map_idx = dev_idx;
1571230592Sken			mt_entry = &sc->mapping_table[map_idx];
1572230592Sken			if (mt_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
1573230592Sken				printf("%s: conflict in mapping table for "
1574230592Sken				    "device %d\n", __func__, map_idx);
1575230592Sken				break;
1576230592Sken			}
1577230592Sken			physical_id = dpm_entry->PhysicalIdentifier.High;
1578230592Sken			mt_entry->physical_id = (physical_id << 32) |
1579230592Sken			    dpm_entry->PhysicalIdentifier.Low;
1580230592Sken			mt_entry->phy_bits = phy_bits;
1581230592Sken			mt_entry->channel = 0;
1582230592Sken			mt_entry->id = dev_idx;
1583230592Sken			mt_entry->missing_count = missing_cnt;
1584230592Sken			mt_entry->dpm_entry_num = entry_num;
1585230592Sken			mt_entry->device_info = MPS_DEV_RESERVED;
1586230592Sken		}
1587230592Sken	} /*close the loop for DPM table */
1588230592Sken}
1589230592Sken
1590230592Sken/*
1591230592Sken * mps_mapping_check_devices - start of the day check for device availabilty
1592230592Sken * @sc: per adapter object
1593230592Sken * @sleep_flag: Flag indicating whether this function can sleep or not
1594230592Sken *
1595230592Sken * Returns nothing.
1596230592Sken */
1597230592Skenvoid
1598230592Skenmps_mapping_check_devices(struct mps_softc *sc, int sleep_flag)
1599230592Sken{
1600230592Sken	u32 i;
1601230592Sken/*	u32 cntdn, i;
1602230592Sken	u32 timeout = 60;*/
1603230592Sken	struct dev_mapping_table *mt_entry;
1604230592Sken	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1605230592Sken	struct enc_mapping_table *et_entry;
1606230592Sken	u32 start_idx, end_idx;
1607230592Sken
1608230592Sken	/* We need to ucomment this when this function is called
1609230592Sken	 * from the port enable complete */
1610230592Sken#if 0
1611230592Sken	sc->track_mapping_events = 0;
1612230592Sken	cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
1613230592Sken	do {
1614230592Sken		if (!sc->pending_map_events)
1615230592Sken			break;
1616230592Sken		if (sleep_flag == CAN_SLEEP)
1617230592Sken			pause("mps_pause", (hz/1000));/* 1msec sleep */
1618230592Sken		else
1619230592Sken			DELAY(500); /* 500 useconds delay */
1620230592Sken	} while (--cntdn);
1621230592Sken
1622230592Sken
1623230592Sken	if (!cntdn)
1624230592Sken		printf("%s: there are %d"
1625230592Sken		    " pending events after %d seconds of delay\n",
1626230592Sken		    __func__, sc->pending_map_events, timeout);
1627230592Sken#endif
1628230592Sken	sc->pending_map_events = 0;
1629230592Sken
1630230592Sken	if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1631230592Sken	    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1632230592Sken		et_entry = sc->enclosure_table;
1633230592Sken		for (i = 0; i < sc->num_enc_table_entries; i++, et_entry++) {
1634230592Sken			if (!et_entry->init_complete) {
1635230592Sken				if (et_entry->missing_count <
1636230592Sken				    MPS_MAX_MISSING_COUNT) {
1637230592Sken					et_entry->missing_count++;
1638230592Sken					if (et_entry->dpm_entry_num !=
1639230592Sken					    MPS_DPM_BAD_IDX)
1640230592Sken						_mapping_commit_enc_entry(sc,
1641230592Sken						    et_entry);
1642230592Sken				}
1643230592Sken				et_entry->init_complete = 1;
1644230592Sken			}
1645230592Sken		}
1646230592Sken		if (!sc->ir_firmware)
1647230592Sken			return;
1648230592Sken		_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
1649230592Sken		mt_entry = &sc->mapping_table[start_idx];
1650230592Sken		for (i = start_idx; i < (end_idx + 1); i++, mt_entry++) {
1651230592Sken			if (mt_entry->device_info & MPS_DEV_RESERVED
1652230592Sken			    && !mt_entry->physical_id)
1653230592Sken				mt_entry->init_complete = 1;
1654230592Sken			else if (mt_entry->device_info & MPS_DEV_RESERVED) {
1655230592Sken				if (!mt_entry->init_complete) {
1656230592Sken					if (mt_entry->missing_count <
1657230592Sken					    MPS_MAX_MISSING_COUNT) {
1658230592Sken						mt_entry->missing_count++;
1659230592Sken						if (mt_entry->dpm_entry_num !=
1660230592Sken						    MPS_DPM_BAD_IDX)
1661230592Sken						_mapping_commit_map_entry(sc,
1662230592Sken						    mt_entry);
1663230592Sken					}
1664230592Sken					mt_entry->init_complete = 1;
1665230592Sken				}
1666230592Sken			}
1667230592Sken		}
1668230592Sken	} else if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1669230592Sken	    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
1670230592Sken		mt_entry = sc->mapping_table;
1671230592Sken		for (i = 0; i < sc->max_devices; i++, mt_entry++) {
1672230592Sken			if (mt_entry->device_info & MPS_DEV_RESERVED
1673230592Sken			    && !mt_entry->physical_id)
1674230592Sken				mt_entry->init_complete = 1;
1675230592Sken			else if (mt_entry->device_info & MPS_DEV_RESERVED) {
1676230592Sken				if (!mt_entry->init_complete) {
1677230592Sken					if (mt_entry->missing_count <
1678230592Sken					    MPS_MAX_MISSING_COUNT) {
1679230592Sken						mt_entry->missing_count++;
1680230592Sken						if (mt_entry->dpm_entry_num !=
1681230592Sken						    MPS_DPM_BAD_IDX)
1682230592Sken						_mapping_commit_map_entry(sc,
1683230592Sken						    mt_entry);
1684230592Sken					}
1685230592Sken					mt_entry->init_complete = 1;
1686230592Sken				}
1687230592Sken			}
1688230592Sken		}
1689230592Sken	}
1690230592Sken}
1691230592Sken
1692230592Sken
1693230592Sken/**
1694230592Sken * mps_mapping_is_reinit_required - check whether event replay required
1695230592Sken * @sc: per adapter object
1696230592Sken *
1697230592Sken * Checks the per ioc flags and decide whether reinit of events required
1698230592Sken *
1699230592Sken * Returns 1 for reinit of ioc 0 for not.
1700230592Sken */
1701230592Skenint mps_mapping_is_reinit_required(struct mps_softc *sc)
1702230592Sken{
1703230592Sken	if (!sc->mt_full_retry && sc->mt_add_device_failed) {
1704230592Sken		sc->mt_full_retry = 1;
1705230592Sken		sc->mt_add_device_failed = 0;
1706230592Sken		_mapping_flush_dpm_pages(sc);
1707230592Sken		return 1;
1708230592Sken	}
1709230592Sken	sc->mt_full_retry = 1;
1710230592Sken	return 0;
1711230592Sken}
1712230592Sken
1713230592Sken/**
1714230592Sken * mps_mapping_initialize - initialize mapping tables
1715230592Sken * @sc: per adapter object
1716230592Sken *
1717230592Sken * Read controller persitant mapping tables into internal data area.
1718230592Sken *
1719230592Sken * Return 0 for success or non-zero for failure.
1720230592Sken */
1721230592Skenint
1722230592Skenmps_mapping_initialize(struct mps_softc *sc)
1723230592Sken{
1724230592Sken	uint16_t volume_mapping_flags, dpm_pg0_sz;
1725230592Sken	uint32_t i;
1726230592Sken	Mpi2ConfigReply_t mpi_reply;
1727230592Sken	int error;
1728230592Sken	uint8_t retry_count;
1729230592Sken	uint16_t ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1730230592Sken
1731230592Sken	/* The additional 1 accounts for the virtual enclosure
1732230592Sken	 * created for the controller
1733230592Sken	 */
1734230592Sken	sc->max_enclosures = sc->facts->MaxEnclosures + 1;
1735230592Sken	sc->max_expanders = sc->facts->MaxSasExpanders;
1736230592Sken	sc->max_volumes = sc->facts->MaxVolumes;
1737230592Sken	sc->max_devices = sc->facts->MaxTargets + sc->max_volumes;
1738230592Sken	sc->pending_map_events = 0;
1739230592Sken	sc->num_enc_table_entries = 0;
1740230592Sken	sc->num_rsvd_entries = 0;
1741230592Sken	sc->num_channels = 1;
1742230592Sken	sc->max_dpm_entries = sc->ioc_pg8.MaxPersistentEntries;
1743230592Sken	sc->is_dpm_enable = (sc->max_dpm_entries) ? 1 : 0;
1744230592Sken	sc->track_mapping_events = 0;
1745230592Sken
1746230592Sken	if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING)
1747230592Sken		sc->is_dpm_enable = 0;
1748230592Sken
1749230592Sken	if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
1750230592Sken		sc->num_rsvd_entries = 1;
1751230592Sken
1752230592Sken	volume_mapping_flags = sc->ioc_pg8.IRVolumeMappingFlags &
1753230592Sken	    MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
1754230592Sken	if (sc->ir_firmware && (volume_mapping_flags ==
1755230592Sken	    MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING))
1756230592Sken		sc->num_rsvd_entries += sc->max_volumes;
1757230592Sken
1758230592Sken	error = mps_mapping_allocate_memory(sc);
1759230592Sken	if (error)
1760230592Sken		return (error);
1761230592Sken
1762230592Sken	for (i = 0; i < sc->max_devices; i++)
1763230592Sken		_mapping_clear_map_entry(sc->mapping_table + i);
1764230592Sken
1765230592Sken	for (i = 0; i < sc->max_enclosures; i++)
1766230592Sken		_mapping_clear_enc_entry(sc->enclosure_table + i);
1767230592Sken
1768230592Sken	for (i = 0; i < sc->max_devices; i++) {
1769230592Sken		sc->removal_table[i].dev_handle = 0;
1770230592Sken		sc->removal_table[i].dpm_entry_num = MPS_DPM_BAD_IDX;
1771230592Sken	}
1772230592Sken
1773230592Sken	memset(sc->dpm_entry_used, 0, sc->max_dpm_entries);
1774230592Sken	memset(sc->dpm_flush_entry, 0, sc->max_dpm_entries);
1775230592Sken
1776230592Sken	if (sc->is_dpm_enable) {
1777230592Sken		dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) +
1778230592Sken		    (sc->max_dpm_entries *
1779230592Sken		     sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY));
1780230592Sken		retry_count = 0;
1781230592Sken
1782230592Skenretry_read_dpm:
1783230592Sken		if (mps_config_get_dpm_pg0(sc, &mpi_reply, sc->dpm_pg0,
1784230592Sken		    dpm_pg0_sz)) {
1785230592Sken			printf("%s: dpm page read failed; disabling dpm\n",
1786230592Sken			    __func__);
1787230592Sken			if (retry_count < 3) {
1788230592Sken				retry_count++;
1789230592Sken				goto retry_read_dpm;
1790230592Sken			}
1791230592Sken			sc->is_dpm_enable = 0;
1792230592Sken		}
1793230592Sken	}
1794230592Sken
1795230592Sken	if (sc->is_dpm_enable)
1796230592Sken		_mapping_process_dpm_pg0(sc);
1797230592Sken
1798230592Sken	sc->track_mapping_events = 1;
1799230592Sken	return 0;
1800230592Sken}
1801230592Sken
1802230592Sken/**
1803230592Sken * mps_mapping_exit - clear mapping table and associated memory
1804230592Sken * @sc: per adapter object
1805230592Sken *
1806230592Sken * Returns nothing.
1807230592Sken */
1808230592Skenvoid
1809230592Skenmps_mapping_exit(struct mps_softc *sc)
1810230592Sken{
1811230592Sken	_mapping_flush_dpm_pages(sc);
1812230592Sken	mps_mapping_free_memory(sc);
1813230592Sken}
1814230592Sken
1815230592Sken/**
1816230592Sken * mps_mapping_get_sas_id - assign a target id for sas device
1817230592Sken * @sc: per adapter object
1818230592Sken * @sas_address: sas address of the device
1819230592Sken * @handle: device handle
1820230592Sken *
1821230592Sken * Returns valid ID on success or BAD_ID.
1822230592Sken */
1823230592Skenunsigned int
1824230592Skenmps_mapping_get_sas_id(struct mps_softc *sc, uint64_t sas_address, u16 handle)
1825230592Sken{
1826230592Sken	u32 map_idx;
1827230592Sken	struct dev_mapping_table *mt_entry;
1828230592Sken
1829230592Sken	for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
1830230592Sken		mt_entry = &sc->mapping_table[map_idx];
1831230592Sken		if (mt_entry->dev_handle == handle && mt_entry->physical_id ==
1832230592Sken		    sas_address)
1833230592Sken			return mt_entry->id;
1834230592Sken	}
1835230592Sken
1836230592Sken	return MPS_MAP_BAD_ID;
1837230592Sken}
1838230592Sken
1839230592Sken/**
1840230592Sken * mps_mapping_get_sas_id_from_handle - find a target id in mapping table using
1841230592Sken * only the dev handle.  This is just a wrapper function for the local function
1842230592Sken * _mapping_get_mt_idx_from_handle.
1843230592Sken * @sc: per adapter object
1844230592Sken * @handle: device handle
1845230592Sken *
1846230592Sken * Returns valid ID on success or BAD_ID.
1847230592Sken */
1848230592Skenunsigned int
1849230592Skenmps_mapping_get_sas_id_from_handle(struct mps_softc *sc, u16 handle)
1850230592Sken{
1851230592Sken	return (_mapping_get_mt_idx_from_handle(sc, handle));
1852230592Sken}
1853230592Sken
1854230592Sken/**
1855230592Sken * mps_mapping_get_raid_id - assign a target id for raid device
1856230592Sken * @sc: per adapter object
1857230592Sken * @wwid: world wide identifier for raid volume
1858230592Sken * @handle: device handle
1859230592Sken *
1860230592Sken * Returns valid ID on success or BAD_ID.
1861230592Sken */
1862230592Skenunsigned int
1863230592Skenmps_mapping_get_raid_id(struct mps_softc *sc, u64 wwid, u16 handle)
1864230592Sken{
1865230592Sken	u32 map_idx;
1866230592Sken	struct dev_mapping_table *mt_entry;
1867230592Sken
1868230592Sken	for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
1869230592Sken		mt_entry = &sc->mapping_table[map_idx];
1870230592Sken		if (mt_entry->dev_handle == handle && mt_entry->physical_id ==
1871230592Sken		    wwid)
1872230592Sken			return mt_entry->id;
1873230592Sken	}
1874230592Sken
1875230592Sken	return MPS_MAP_BAD_ID;
1876230592Sken}
1877230592Sken
1878230592Sken/**
1879230592Sken * mps_mapping_get_raid_id_from_handle - find raid device in mapping table
1880230592Sken * using only the volume dev handle.  This is just a wrapper function for the
1881230592Sken * local function _mapping_get_ir_mt_idx_from_handle.
1882230592Sken * @sc: per adapter object
1883230592Sken * @volHandle: volume device handle
1884230592Sken *
1885230592Sken * Returns valid ID on success or BAD_ID.
1886230592Sken */
1887230592Skenunsigned int
1888230592Skenmps_mapping_get_raid_id_from_handle(struct mps_softc *sc, u16 volHandle)
1889230592Sken{
1890230592Sken	return (_mapping_get_ir_mt_idx_from_handle(sc, volHandle));
1891230592Sken}
1892230592Sken
1893230592Sken/**
1894230592Sken * mps_mapping_enclosure_dev_status_change_event - handle enclosure events
1895230592Sken * @sc: per adapter object
1896230592Sken * @event_data: event data payload
1897230592Sken *
1898230592Sken * Return nothing.
1899230592Sken */
1900230592Skenvoid
1901230592Skenmps_mapping_enclosure_dev_status_change_event(struct mps_softc *sc,
1902230592Sken    Mpi2EventDataSasEnclDevStatusChange_t *event_data)
1903230592Sken{
1904230592Sken	u8 enc_idx, missing_count;
1905230592Sken	struct enc_mapping_table *et_entry;
1906230592Sken	Mpi2DriverMap0Entry_t *dpm_entry;
1907230592Sken	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1908230592Sken	u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
1909230592Sken	u8 update_phy_bits = 0;
1910230592Sken	u32 saved_phy_bits;
1911230592Sken	uint64_t temp64_var;
1912230592Sken
1913230592Sken	if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) !=
1914230592Sken	    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING)
1915230592Sken		goto out;
1916230592Sken
1917230592Sken	dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
1918230592Sken	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1919230592Sken
1920230592Sken	if (event_data->ReasonCode == MPI2_EVENT_SAS_ENCL_RC_ADDED) {
1921230592Sken		if (!event_data->NumSlots) {
1922230592Sken			printf("%s: enclosure with handle = 0x%x reported 0 "
1923230592Sken			    "slots\n", __func__,
1924230592Sken			    le16toh(event_data->EnclosureHandle));
1925230592Sken			goto out;
1926230592Sken		}
1927230592Sken		temp64_var = event_data->EnclosureLogicalID.High;
1928230592Sken		temp64_var = (temp64_var << 32) |
1929230592Sken		    event_data->EnclosureLogicalID.Low;
1930230592Sken		enc_idx = _mapping_get_enc_idx_from_id(sc, temp64_var,
1931230592Sken		    event_data->PhyBits);
1932230592Sken		if (enc_idx != MPS_ENCTABLE_BAD_IDX) {
1933230592Sken			et_entry = &sc->enclosure_table[enc_idx];
1934230592Sken			if (et_entry->init_complete &&
1935230592Sken			    !et_entry->missing_count) {
1936230592Sken				printf("%s: enclosure %d is already present "
1937230592Sken				    "with handle = 0x%x\n",__func__, enc_idx,
1938230592Sken				    et_entry->enc_handle);
1939230592Sken				goto out;
1940230592Sken			}
1941230592Sken			et_entry->enc_handle = le16toh(event_data->
1942230592Sken			    EnclosureHandle);
1943230592Sken			et_entry->start_slot = le16toh(event_data->StartSlot);
1944230592Sken			saved_phy_bits = et_entry->phy_bits;
1945230592Sken			et_entry->phy_bits |= le32toh(event_data->PhyBits);
1946230592Sken			if (saved_phy_bits != et_entry->phy_bits)
1947230592Sken				update_phy_bits = 1;
1948230592Sken			if (et_entry->missing_count || update_phy_bits) {
1949230592Sken				et_entry->missing_count = 0;
1950230592Sken				if (sc->is_dpm_enable &&
1951230592Sken				    et_entry->dpm_entry_num !=
1952230592Sken				    MPS_DPM_BAD_IDX) {
1953230592Sken					dpm_entry += et_entry->dpm_entry_num;
1954230592Sken					missing_count =
1955230592Sken					    (u8)(dpm_entry->MappingInformation &
1956230592Sken					    MPI2_DRVMAP0_MAPINFO_MISSING_MASK);
1957230592Sken					if (!et_entry->init_complete && (
1958230592Sken					    missing_count || update_phy_bits)) {
1959230592Sken						dpm_entry->MappingInformation
1960230592Sken						    = et_entry->num_slots;
1961230592Sken						dpm_entry->MappingInformation
1962230592Sken						    <<= map_shift;
1963230592Sken						dpm_entry->PhysicalBitsMapping
1964230592Sken						    = et_entry->phy_bits;
1965230592Sken						sc->dpm_flush_entry[et_entry->
1966230592Sken						    dpm_entry_num] = 1;
1967230592Sken					}
1968230592Sken				}
1969230592Sken			}
1970230592Sken		} else {
1971230592Sken			enc_idx = sc->num_enc_table_entries;
1972230592Sken			if (enc_idx >= sc->max_enclosures) {
1973230592Sken				printf("%s: enclosure can not be added; "
1974230592Sken				    "mapping table is full\n", __func__);
1975230592Sken				goto out;
1976230592Sken			}
1977230592Sken			sc->num_enc_table_entries++;
1978230592Sken			et_entry = &sc->enclosure_table[enc_idx];
1979230592Sken			et_entry->enc_handle = le16toh(event_data->
1980230592Sken			    EnclosureHandle);
1981230592Sken			et_entry->enclosure_id = event_data->
1982230592Sken			    EnclosureLogicalID.High;
1983230592Sken			et_entry->enclosure_id = ( et_entry->enclosure_id <<
1984230592Sken			    32) | event_data->EnclosureLogicalID.Low;
1985230592Sken			et_entry->start_index = MPS_MAPTABLE_BAD_IDX;
1986230592Sken			et_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
1987230592Sken			et_entry->num_slots = le16toh(event_data->NumSlots);
1988230592Sken			et_entry->start_slot = le16toh(event_data->StartSlot);
1989230592Sken			et_entry->phy_bits = le32toh(event_data->PhyBits);
1990230592Sken		}
1991230592Sken		et_entry->init_complete = 1;
1992230592Sken	} else if (event_data->ReasonCode ==
1993230592Sken	    MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING) {
1994230592Sken		enc_idx = _mapping_get_enc_idx_from_handle(sc,
1995230592Sken		    le16toh(event_data->EnclosureHandle));
1996230592Sken		if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
1997230592Sken			printf("%s: cannot unmap enclosure %d because it has "
1998230592Sken			    "already been deleted", __func__, enc_idx);
1999230592Sken			goto out;
2000230592Sken		}
2001230592Sken		et_entry = &sc->enclosure_table[enc_idx];
2002230592Sken		if (!et_entry->init_complete) {
2003230592Sken			if (et_entry->missing_count < MPS_MAX_MISSING_COUNT)
2004230592Sken				et_entry->missing_count++;
2005230592Sken			else
2006230592Sken				et_entry->init_complete = 1;
2007230592Sken		}
2008230592Sken		if (!et_entry->missing_count)
2009230592Sken			et_entry->missing_count++;
2010230592Sken		if (sc->is_dpm_enable && !et_entry->init_complete &&
2011230592Sken		    et_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
2012230592Sken			dpm_entry += et_entry->dpm_entry_num;
2013230592Sken			dpm_entry->MappingInformation = et_entry->num_slots;
2014230592Sken			dpm_entry->MappingInformation <<= map_shift;
2015230592Sken			dpm_entry->MappingInformation |=
2016230592Sken			    et_entry->missing_count;
2017230592Sken			sc->dpm_flush_entry[et_entry->dpm_entry_num] = 1;
2018230592Sken		}
2019230592Sken		et_entry->init_complete = 1;
2020230592Sken	}
2021230592Sken
2022230592Skenout:
2023230592Sken	_mapping_flush_dpm_pages(sc);
2024230592Sken	if (sc->pending_map_events)
2025230592Sken		sc->pending_map_events--;
2026230592Sken}
2027230592Sken
2028230592Sken/**
2029230592Sken * mps_mapping_topology_change_event - handle topology change events
2030230592Sken * @sc: per adapter object
2031230592Sken * @event_data: event data payload
2032230592Sken *
2033230592Sken * Returns nothing.
2034230592Sken */
2035230592Skenvoid
2036230592Skenmps_mapping_topology_change_event(struct mps_softc *sc,
2037230592Sken    Mpi2EventDataSasTopologyChangeList_t *event_data)
2038230592Sken{
2039230592Sken	struct _map_topology_change topo_change;
2040230592Sken	struct _map_phy_change *phy_change;
2041230592Sken	Mpi2EventSasTopoPhyEntry_t *event_phy_change;
2042230592Sken	u8 i, num_entries;
2043230592Sken
2044230592Sken	topo_change.enc_handle = le16toh(event_data->EnclosureHandle);
2045230592Sken	topo_change.exp_handle = le16toh(event_data->ExpanderDevHandle);
2046230592Sken	num_entries = event_data->NumEntries;
2047230592Sken	topo_change.num_entries = num_entries;
2048230592Sken	topo_change.start_phy_num = event_data->StartPhyNum;
2049230592Sken	topo_change.num_phys = event_data->NumPhys;
2050230592Sken	topo_change.exp_status = event_data->ExpStatus;
2051230592Sken	event_phy_change = event_data->PHY;
2052230592Sken	topo_change.phy_details = NULL;
2053230592Sken
2054230592Sken	if (!num_entries)
2055230592Sken		goto out;
2056230592Sken	phy_change = malloc(sizeof(struct _map_phy_change) * num_entries,
2057230592Sken	    M_MPT2, M_NOWAIT|M_ZERO);
2058230592Sken	topo_change.phy_details = phy_change;
2059230592Sken	if (!phy_change)
2060230592Sken		goto out;
2061230592Sken	for (i = 0; i < num_entries; i++, event_phy_change++, phy_change++) {
2062230592Sken		phy_change->dev_handle = le16toh(event_phy_change->
2063230592Sken		    AttachedDevHandle);
2064230592Sken		phy_change->reason = event_phy_change->PhyStatus &
2065230592Sken		    MPI2_EVENT_SAS_TOPO_RC_MASK;
2066230592Sken	}
2067230592Sken	_mapping_update_missing_count(sc, &topo_change);
2068230592Sken	_mapping_get_dev_info(sc, &topo_change);
2069230592Sken	_mapping_clear_removed_entries(sc);
2070230592Sken	_mapping_add_new_device(sc, &topo_change);
2071230592Sken
2072230592Skenout:
2073230592Sken	free(topo_change.phy_details, M_MPT2);
2074230592Sken	_mapping_flush_dpm_pages(sc);
2075230592Sken	if (sc->pending_map_events)
2076230592Sken		sc->pending_map_events--;
2077230592Sken}
2078230592Sken
2079230592Sken/**
2080230592Sken * _mapping_check_update_ir_mt_idx - Check and update IR map table index
2081230592Sken * @sc: per adapter object
2082230592Sken * @event_data: event data payload
2083230592Sken * @evt_idx: current event index
2084230592Sken * @map_idx: current index and the place holder for new map table index
2085230592Sken * @wwid_table: world wide name for volumes in the element table
2086230592Sken *
2087230592Sken * pass through IR events and find whether any events matches and if so
2088230592Sken * tries to find new index if not returns failure
2089230592Sken *
2090230592Sken * Returns 0 on success and 1 on failure
2091230592Sken */
2092230592Skenstatic int
2093230592Sken_mapping_check_update_ir_mt_idx(struct mps_softc *sc,
2094230592Sken    Mpi2EventDataIrConfigChangeList_t *event_data, int evt_idx, u32 *map_idx,
2095230592Sken    u64 *wwid_table)
2096230592Sken{
2097230592Sken	struct dev_mapping_table *mt_entry;
2098230592Sken	u32 st_idx, end_idx, mt_idx = *map_idx;
2099230592Sken	u8 match = 0;
2100230592Sken	Mpi2EventIrConfigElement_t *element;
2101230592Sken	u16 element_flags;
2102230592Sken	int i;
2103230592Sken
2104230592Sken	mt_entry = &sc->mapping_table[mt_idx];
2105230592Sken	_mapping_get_ir_maprange(sc, &st_idx, &end_idx);
2106230592Skensearch_again:
2107230592Sken	match = 0;
2108230592Sken	for (i = evt_idx + 1; i < event_data->NumElements; i++) {
2109230592Sken		element = (Mpi2EventIrConfigElement_t *)
2110230592Sken		    &event_data->ConfigElement[i];
2111230592Sken		element_flags = le16toh(element->ElementFlags);
2112230592Sken		if ((element_flags &
2113230592Sken		    MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK) !=
2114230592Sken		    MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT)
2115230592Sken			continue;
2116230592Sken		if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_ADDED ||
2117230592Sken		    element->ReasonCode ==
2118230592Sken		    MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) {
2119230592Sken			if (mt_entry->physical_id == wwid_table[i]) {
2120230592Sken				match = 1;
2121230592Sken				break;
2122230592Sken			}
2123230592Sken		}
2124230592Sken	}
2125230592Sken
2126230592Sken	if (match) {
2127230592Sken		do {
2128230592Sken			mt_idx++;
2129230592Sken			if (mt_idx > end_idx)
2130230592Sken				return 1;
2131230592Sken			mt_entry = &sc->mapping_table[mt_idx];
2132230592Sken		} while (mt_entry->device_info & MPS_MAP_IN_USE);
2133230592Sken		goto search_again;
2134230592Sken	}
2135230592Sken	*map_idx = mt_idx;
2136230592Sken	return 0;
2137230592Sken}
2138230592Sken
2139230592Sken/**
2140230592Sken * mps_mapping_ir_config_change_event - handle IR config change list events
2141230592Sken * @sc: per adapter object
2142230592Sken * @event_data: event data payload
2143230592Sken *
2144230592Sken * Returns nothing.
2145230592Sken */
2146230592Skenvoid
2147230592Skenmps_mapping_ir_config_change_event(struct mps_softc *sc,
2148230592Sken    Mpi2EventDataIrConfigChangeList_t *event_data)
2149230592Sken{
2150230592Sken	Mpi2EventIrConfigElement_t *element;
2151230592Sken	int i;
2152230592Sken	u64 *wwid_table;
2153230592Sken	u32 map_idx, flags;
2154230592Sken	struct dev_mapping_table *mt_entry;
2155230592Sken	u16 element_flags;
2156230592Sken	u8 log_full_error = 0;
2157230592Sken
2158230592Sken	wwid_table = malloc(sizeof(u64) * event_data->NumElements, M_MPT2,
2159230592Sken	    M_NOWAIT | M_ZERO);
2160230592Sken	if (!wwid_table)
2161230592Sken		goto out;
2162230592Sken	element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
2163230592Sken	flags = le32toh(event_data->Flags);
2164230592Sken	for (i = 0; i < event_data->NumElements; i++, element++) {
2165230592Sken		element_flags = le16toh(element->ElementFlags);
2166230592Sken		if ((element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_ADDED) &&
2167230592Sken		    (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_REMOVED) &&
2168230592Sken		    (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE)
2169230592Sken		    && (element->ReasonCode !=
2170230592Sken			MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED))
2171230592Sken			continue;
2172230592Sken		if ((element_flags &
2173230592Sken		    MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK) ==
2174230592Sken		    MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT) {
2175230592Sken			mps_config_get_volume_wwid(sc,
2176230592Sken			    le16toh(element->VolDevHandle), &wwid_table[i]);
2177230592Sken			map_idx = _mapping_get_ir_mt_idx_from_wwid(sc,
2178230592Sken			    wwid_table[i]);
2179230592Sken			if (map_idx != MPS_MAPTABLE_BAD_IDX) {
2180230592Sken				mt_entry = &sc->mapping_table[map_idx];
2181230592Sken				mt_entry->device_info |= MPS_MAP_IN_USE;
2182230592Sken			}
2183230592Sken		}
2184230592Sken	}
2185230592Sken	if (flags == MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
2186230592Sken		goto out;
2187230592Sken	else {
2188230592Sken		element = (Mpi2EventIrConfigElement_t *)&event_data->
2189230592Sken		    ConfigElement[0];
2190230592Sken		for (i = 0; i < event_data->NumElements; i++, element++) {
2191230592Sken			if (element->ReasonCode ==
2192230592Sken			    MPI2_EVENT_IR_CHANGE_RC_ADDED ||
2193230592Sken			    element->ReasonCode ==
2194230592Sken			    MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) {
2195230592Sken				map_idx = _mapping_get_ir_mt_idx_from_wwid
2196230592Sken				    (sc, wwid_table[i]);
2197230592Sken				if (map_idx != MPS_MAPTABLE_BAD_IDX) {
2198230592Sken					mt_entry = &sc->mapping_table[map_idx];
2199230592Sken					mt_entry->channel = MPS_RAID_CHANNEL;
2200230592Sken					mt_entry->id = map_idx;
2201230592Sken					mt_entry->dev_handle = le16toh
2202230592Sken					    (element->VolDevHandle);
2203230592Sken					mt_entry->device_info =
2204230592Sken					    MPS_DEV_RESERVED | MPS_MAP_IN_USE;
2205230592Sken					_mapping_update_ir_missing_cnt(sc,
2206230592Sken					    map_idx, element, wwid_table[i]);
2207230592Sken					continue;
2208230592Sken				}
2209230592Sken				map_idx = _mapping_get_free_ir_mt_idx(sc);
2210230592Sken				if (map_idx == MPS_MAPTABLE_BAD_IDX)
2211230592Sken					log_full_error = 1;
2212230592Sken				else if (i < (event_data->NumElements - 1)) {
2213230592Sken					log_full_error =
2214230592Sken					    _mapping_check_update_ir_mt_idx
2215230592Sken					    (sc, event_data, i, &map_idx,
2216230592Sken					     wwid_table);
2217230592Sken				}
2218230592Sken				if (log_full_error) {
2219230592Sken					printf("%s: no space to add the RAID "
2220230592Sken					    "volume with handle 0x%04x in "
2221230592Sken					    "mapping table\n", __func__, le16toh
2222230592Sken					    (element->VolDevHandle));
2223230592Sken					continue;
2224230592Sken				}
2225230592Sken				mt_entry = &sc->mapping_table[map_idx];
2226230592Sken				mt_entry->physical_id = wwid_table[i];
2227230592Sken				mt_entry->channel = MPS_RAID_CHANNEL;
2228230592Sken				mt_entry->id = map_idx;
2229230592Sken				mt_entry->dev_handle = le16toh(element->
2230230592Sken				    VolDevHandle);
2231230592Sken				mt_entry->device_info = MPS_DEV_RESERVED |
2232230592Sken				    MPS_MAP_IN_USE;
2233230592Sken				mt_entry->init_complete = 0;
2234230592Sken				_mapping_update_ir_missing_cnt(sc, map_idx,
2235230592Sken				    element, wwid_table[i]);
2236230592Sken			} else if (element->ReasonCode ==
2237230592Sken			    MPI2_EVENT_IR_CHANGE_RC_REMOVED) {
2238230592Sken				map_idx = _mapping_get_ir_mt_idx_from_wwid(sc,
2239230592Sken				    wwid_table[i]);
2240230592Sken				if (map_idx == MPS_MAPTABLE_BAD_IDX) {
2241230592Sken					printf("%s: failed to remove a volume "
2242230592Sken					    "because it has already been "
2243230592Sken					    "removed\n", __func__);
2244230592Sken					continue;
2245230592Sken				}
2246230592Sken				_mapping_update_ir_missing_cnt(sc, map_idx,
2247230592Sken				    element, wwid_table[i]);
2248230592Sken			} else if (element->ReasonCode ==
2249230592Sken			    MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED) {
2250230592Sken				map_idx = _mapping_get_mt_idx_from_handle(sc,
2251230592Sken				    le16toh(element->VolDevHandle));
2252230592Sken				if (map_idx == MPS_MAPTABLE_BAD_IDX) {
2253230592Sken					printf("%s: failed to remove volume "
2254230592Sken					    "with handle 0x%04x because it has "
2255230592Sken					    "already been removed\n", __func__,
2256230592Sken					    le16toh(element->VolDevHandle));
2257230592Sken					continue;
2258230592Sken				}
2259230592Sken				mt_entry = &sc->mapping_table[map_idx];
2260230592Sken				_mapping_update_ir_missing_cnt(sc, map_idx,
2261230592Sken				    element, mt_entry->physical_id);
2262230592Sken			}
2263230592Sken		}
2264230592Sken	}
2265230592Sken
2266230592Skenout:
2267230592Sken	_mapping_flush_dpm_pages(sc);
2268230592Sken	free(wwid_table, M_MPT2);
2269230592Sken	if (sc->pending_map_events)
2270230592Sken		sc->pending_map_events--;
2271230592Sken}
2272