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