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