1/*-
2 * Copyright (c) 2011-2015 LSI Corp.
3 * Copyright (c) 2013-2016 Avago Technologies
4 * Copyright 2000-2020 Broadcom Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * Broadcom Inc. (LSI) MPT-Fusion Host Adapter FreeBSD
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD$");
33
34/* TODO Move headers to mprvar */
35#include <sys/types.h>
36#include <sys/param.h>
37#include <sys/lock.h>
38#include <sys/mutex.h>
39#include <sys/systm.h>
40#include <sys/kernel.h>
41#include <sys/malloc.h>
42#include <sys/kthread.h>
43#include <sys/taskqueue.h>
44#include <sys/bus.h>
45#include <sys/endian.h>
46#include <sys/sysctl.h>
47#include <sys/eventhandler.h>
48#include <sys/uio.h>
49#include <machine/bus.h>
50#include <machine/resource.h>
51#include <dev/mpr/mpi/mpi2_type.h>
52#include <dev/mpr/mpi/mpi2.h>
53#include <dev/mpr/mpi/mpi2_ioc.h>
54#include <dev/mpr/mpi/mpi2_sas.h>
55#include <dev/mpr/mpi/mpi2_pci.h>
56#include <dev/mpr/mpi/mpi2_cnfg.h>
57#include <dev/mpr/mpi/mpi2_init.h>
58#include <dev/mpr/mpi/mpi2_tool.h>
59#include <dev/mpr/mpr_ioctl.h>
60#include <dev/mpr/mprvar.h>
61#include <dev/mpr/mpr_mapping.h>
62
63/**
64 * _mapping_clear_map_entry - Clear a particular mapping entry.
65 * @map_entry: map table entry
66 *
67 * Returns nothing.
68 */
69static inline void
70_mapping_clear_map_entry(struct dev_mapping_table *map_entry)
71{
72	map_entry->physical_id = 0;
73	map_entry->device_info = 0;
74	map_entry->phy_bits = 0;
75	map_entry->dpm_entry_num = MPR_DPM_BAD_IDX;
76	map_entry->dev_handle = 0;
77	map_entry->id = -1;
78	map_entry->missing_count = 0;
79	map_entry->init_complete = 0;
80	map_entry->TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR;
81}
82
83/**
84 * _mapping_clear_enc_entry - Clear a particular enclosure table entry.
85 * @enc_entry: enclosure table entry
86 *
87 * Returns nothing.
88 */
89static inline void
90_mapping_clear_enc_entry(struct enc_mapping_table *enc_entry)
91{
92	enc_entry->enclosure_id = 0;
93	enc_entry->start_index = MPR_MAPTABLE_BAD_IDX;
94	enc_entry->phy_bits = 0;
95	enc_entry->dpm_entry_num = MPR_DPM_BAD_IDX;
96	enc_entry->enc_handle = 0;
97	enc_entry->num_slots = 0;
98	enc_entry->start_slot = 0;
99	enc_entry->missing_count = 0;
100	enc_entry->removal_flag = 0;
101	enc_entry->skip_search = 0;
102	enc_entry->init_complete = 0;
103}
104
105/**
106 * _mapping_commit_enc_entry - write a particular enc entry in DPM page0.
107 * @sc: per adapter object
108 * @enc_entry: enclosure table entry
109 *
110 * Returns 0 for success, non-zero for failure.
111 */
112static int
113_mapping_commit_enc_entry(struct mpr_softc *sc,
114    struct enc_mapping_table *et_entry)
115{
116	Mpi2DriverMap0Entry_t *dpm_entry;
117	struct dev_mapping_table *mt_entry;
118	Mpi2ConfigReply_t mpi_reply;
119	Mpi2DriverMappingPage0_t config_page;
120
121	if (!sc->is_dpm_enable)
122		return 0;
123
124	memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
125	memcpy(&config_page.Header, (u8 *) sc->dpm_pg0,
126	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
127	dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
128	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
129	dpm_entry += et_entry->dpm_entry_num;
130	dpm_entry->PhysicalIdentifier.Low =
131	    ( 0xFFFFFFFF & et_entry->enclosure_id);
132	dpm_entry->PhysicalIdentifier.High =
133	    ( et_entry->enclosure_id >> 32);
134	mt_entry = &sc->mapping_table[et_entry->start_index];
135	dpm_entry->DeviceIndex = htole16(mt_entry->id);
136	dpm_entry->MappingInformation = et_entry->num_slots;
137	dpm_entry->MappingInformation <<= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
138	dpm_entry->MappingInformation |= et_entry->missing_count;
139	dpm_entry->MappingInformation = htole16(dpm_entry->MappingInformation);
140	dpm_entry->PhysicalBitsMapping = htole32(et_entry->phy_bits);
141	dpm_entry->Reserved1 = 0;
142
143	mpr_dprint(sc, MPR_MAPPING, "%s: Writing DPM entry %d for enclosure.\n",
144	    __func__, et_entry->dpm_entry_num);
145	memcpy(&config_page.Entry, (u8 *)dpm_entry,
146	    sizeof(Mpi2DriverMap0Entry_t));
147	if (mpr_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
148	    et_entry->dpm_entry_num)) {
149		mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: Write of DPM "
150		    "entry %d for enclosure failed.\n", __func__,
151		    et_entry->dpm_entry_num);
152		dpm_entry->MappingInformation = le16toh(dpm_entry->
153		    MappingInformation);
154		dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
155		dpm_entry->PhysicalBitsMapping =
156		    le32toh(dpm_entry->PhysicalBitsMapping);
157		return -1;
158	}
159	dpm_entry->MappingInformation = le16toh(dpm_entry->
160	    MappingInformation);
161	dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
162	dpm_entry->PhysicalBitsMapping =
163	    le32toh(dpm_entry->PhysicalBitsMapping);
164	return 0;
165}
166
167/**
168 * _mapping_commit_map_entry - write a particular map table entry in DPM page0.
169 * @sc: per adapter object
170 * @mt_entry: mapping table entry
171 *
172 * Returns 0 for success, non-zero for failure.
173 */
174
175static int
176_mapping_commit_map_entry(struct mpr_softc *sc,
177    struct dev_mapping_table *mt_entry)
178{
179	Mpi2DriverMap0Entry_t *dpm_entry;
180	Mpi2ConfigReply_t mpi_reply;
181	Mpi2DriverMappingPage0_t config_page;
182
183	if (!sc->is_dpm_enable)
184		return 0;
185
186	/*
187	 * It's possible that this Map Entry points to a BAD DPM index. This
188	 * can happen if the Map Entry is a for a missing device and the DPM
189	 * entry that was being used by this device is now being used by some
190	 * new device. So, check for a BAD DPM index and just return if so.
191	 */
192	if (mt_entry->dpm_entry_num == MPR_DPM_BAD_IDX) {
193		mpr_dprint(sc, MPR_MAPPING, "%s: DPM entry location for target "
194		    "%d is invalid. DPM will not be written.\n", __func__,
195		    mt_entry->id);
196		return 0;
197	}
198
199	memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
200	memcpy(&config_page.Header, (u8 *)sc->dpm_pg0,
201	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
202	dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *) sc->dpm_pg0 +
203	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
204	dpm_entry = dpm_entry + mt_entry->dpm_entry_num;
205	dpm_entry->PhysicalIdentifier.Low = (0xFFFFFFFF &
206	    mt_entry->physical_id);
207	dpm_entry->PhysicalIdentifier.High = (mt_entry->physical_id >> 32);
208	dpm_entry->DeviceIndex = htole16(mt_entry->id);
209	dpm_entry->MappingInformation = htole16(mt_entry->missing_count);
210	dpm_entry->PhysicalBitsMapping = 0;
211	dpm_entry->Reserved1 = 0;
212	memcpy(&config_page.Entry, (u8 *)dpm_entry,
213	    sizeof(Mpi2DriverMap0Entry_t));
214
215	mpr_dprint(sc, MPR_MAPPING, "%s: Writing DPM entry %d for target %d.\n",
216	    __func__, mt_entry->dpm_entry_num, mt_entry->id);
217	if (mpr_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
218	    mt_entry->dpm_entry_num)) {
219		mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: Write of DPM "
220		    "entry %d for target %d failed.\n", __func__,
221		    mt_entry->dpm_entry_num, mt_entry->id);
222		dpm_entry->MappingInformation = le16toh(dpm_entry->
223		    MappingInformation);
224		dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
225		return -1;
226	}
227
228	dpm_entry->MappingInformation = le16toh(dpm_entry->MappingInformation);
229	dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
230	return 0;
231}
232
233/**
234 * _mapping_get_ir_maprange - get start and end index for IR map range.
235 * @sc: per adapter object
236 * @start_idx: place holder for start index
237 * @end_idx: place holder for end index
238 *
239 * The IR volumes can be mapped either at start or end of the mapping table
240 * this function gets the detail of where IR volume mapping starts and ends
241 * in the device mapping table
242 *
243 * Returns nothing.
244 */
245static void
246_mapping_get_ir_maprange(struct mpr_softc *sc, u32 *start_idx, u32 *end_idx)
247{
248	u16 volume_mapping_flags;
249	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
250
251	volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
252	    MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
253	if (volume_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
254		*start_idx = 0;
255		if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
256			*start_idx = 1;
257	} else
258		*start_idx = sc->max_devices - sc->max_volumes;
259	*end_idx = *start_idx + sc->max_volumes - 1;
260}
261
262/**
263 * _mapping_get_enc_idx_from_id - get enclosure index from enclosure ID
264 * @sc: per adapter object
265 * @enc_id: enclosure logical identifier
266 *
267 * Returns the index of enclosure entry on success or bad index.
268 */
269static u8
270_mapping_get_enc_idx_from_id(struct mpr_softc *sc, u64 enc_id,
271    u64 phy_bits)
272{
273	struct enc_mapping_table *et_entry;
274	u8 enc_idx = 0;
275
276	for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
277		et_entry = &sc->enclosure_table[enc_idx];
278		if ((et_entry->enclosure_id == le64toh(enc_id)) &&
279		    (!et_entry->phy_bits || (et_entry->phy_bits &
280		    le32toh(phy_bits))))
281			return enc_idx;
282	}
283	return MPR_ENCTABLE_BAD_IDX;
284}
285
286/**
287 * _mapping_get_enc_idx_from_handle - get enclosure index from handle
288 * @sc: per adapter object
289 * @enc_id: enclosure handle
290 *
291 * Returns the index of enclosure entry on success or bad index.
292 */
293static u8
294_mapping_get_enc_idx_from_handle(struct mpr_softc *sc, u16 handle)
295{
296	struct enc_mapping_table *et_entry;
297	u8 enc_idx = 0;
298
299	for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
300		et_entry = &sc->enclosure_table[enc_idx];
301		if (et_entry->missing_count)
302			continue;
303		if (et_entry->enc_handle == handle)
304			return enc_idx;
305	}
306	return MPR_ENCTABLE_BAD_IDX;
307}
308
309/**
310 * _mapping_get_high_missing_et_idx - get missing enclosure index
311 * @sc: per adapter object
312 *
313 * Search through the enclosure table and identifies the enclosure entry
314 * with high missing count and returns it's index
315 *
316 * Returns the index of enclosure entry on success or bad index.
317 */
318static u8
319_mapping_get_high_missing_et_idx(struct mpr_softc *sc)
320{
321	struct enc_mapping_table *et_entry;
322	u8 high_missing_count = 0;
323	u8 enc_idx, high_idx = MPR_ENCTABLE_BAD_IDX;
324
325	for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
326		et_entry = &sc->enclosure_table[enc_idx];
327		if ((et_entry->missing_count > high_missing_count) &&
328		    !et_entry->skip_search) {
329			high_missing_count = et_entry->missing_count;
330			high_idx = enc_idx;
331		}
332	}
333	return high_idx;
334}
335
336/**
337 * _mapping_get_high_missing_mt_idx - get missing map table index
338 * @sc: per adapter object
339 *
340 * Search through the map table and identifies the device entry
341 * with high missing count and returns it's index
342 *
343 * Returns the index of map table entry on success or bad index.
344 */
345static u32
346_mapping_get_high_missing_mt_idx(struct mpr_softc *sc)
347{
348	u32 map_idx, high_idx = MPR_MAPTABLE_BAD_IDX;
349	u8 high_missing_count = 0;
350	u32 start_idx, end_idx, start_idx_ir, end_idx_ir;
351	struct dev_mapping_table *mt_entry;
352	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
353
354	start_idx = 0;
355	start_idx_ir = 0;
356	end_idx_ir = 0;
357	end_idx = sc->max_devices;
358	if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
359		start_idx = 1;
360	if (sc->ir_firmware) {
361		_mapping_get_ir_maprange(sc, &start_idx_ir, &end_idx_ir);
362		if (start_idx == start_idx_ir)
363			start_idx = end_idx_ir + 1;
364		else
365			end_idx = start_idx_ir;
366	}
367	mt_entry = &sc->mapping_table[start_idx];
368	for (map_idx = start_idx; map_idx < end_idx; map_idx++, mt_entry++) {
369		if (mt_entry->missing_count > high_missing_count) {
370			high_missing_count =  mt_entry->missing_count;
371			high_idx = map_idx;
372		}
373	}
374	return high_idx;
375}
376
377/**
378 * _mapping_get_ir_mt_idx_from_wwid - get map table index from volume WWID
379 * @sc: per adapter object
380 * @wwid: world wide unique ID of the volume
381 *
382 * Returns the index of map table entry on success or bad index.
383 */
384static u32
385_mapping_get_ir_mt_idx_from_wwid(struct mpr_softc *sc, u64 wwid)
386{
387	u32 start_idx, end_idx, map_idx;
388	struct dev_mapping_table *mt_entry;
389
390	_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
391	mt_entry = &sc->mapping_table[start_idx];
392	for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
393		if (mt_entry->physical_id == wwid)
394			return map_idx;
395
396	return MPR_MAPTABLE_BAD_IDX;
397}
398
399/**
400 * _mapping_get_mt_idx_from_id - get map table index from a device ID
401 * @sc: per adapter object
402 * @dev_id: device identifer (SAS Address)
403 *
404 * Returns the index of map table entry on success or bad index.
405 */
406static u32
407_mapping_get_mt_idx_from_id(struct mpr_softc *sc, u64 dev_id)
408{
409	u32 map_idx;
410	struct dev_mapping_table *mt_entry;
411
412	for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
413		mt_entry = &sc->mapping_table[map_idx];
414		if (mt_entry->physical_id == dev_id)
415			return map_idx;
416	}
417	return MPR_MAPTABLE_BAD_IDX;
418}
419
420/**
421 * _mapping_get_ir_mt_idx_from_handle - get map table index from volume handle
422 * @sc: per adapter object
423 * @wwid: volume device handle
424 *
425 * Returns the index of map table entry on success or bad index.
426 */
427static u32
428_mapping_get_ir_mt_idx_from_handle(struct mpr_softc *sc, u16 volHandle)
429{
430	u32 start_idx, end_idx, map_idx;
431	struct dev_mapping_table *mt_entry;
432
433	_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
434	mt_entry = &sc->mapping_table[start_idx];
435	for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
436		if (mt_entry->dev_handle == volHandle)
437			return map_idx;
438
439	return MPR_MAPTABLE_BAD_IDX;
440}
441
442/**
443 * _mapping_get_mt_idx_from_handle - get map table index from handle
444 * @sc: per adapter object
445 * @dev_id: device handle
446 *
447 * Returns the index of map table entry on success or bad index.
448 */
449static u32
450_mapping_get_mt_idx_from_handle(struct mpr_softc *sc, u16 handle)
451{
452	u32 map_idx;
453	struct dev_mapping_table *mt_entry;
454
455	for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
456		mt_entry = &sc->mapping_table[map_idx];
457		if (mt_entry->dev_handle == handle)
458			return map_idx;
459	}
460	return MPR_MAPTABLE_BAD_IDX;
461}
462
463/**
464 * _mapping_get_free_ir_mt_idx - get first free index for a volume
465 * @sc: per adapter object
466 *
467 * Search through mapping table for free index for a volume and if no free
468 * index then looks for a volume with high mapping index
469 *
470 * Returns the index of map table entry on success or bad index.
471 */
472static u32
473_mapping_get_free_ir_mt_idx(struct mpr_softc *sc)
474{
475	u8 high_missing_count = 0;
476	u32 start_idx, end_idx, map_idx;
477	u32 high_idx = MPR_MAPTABLE_BAD_IDX;
478	struct dev_mapping_table *mt_entry;
479
480	/*
481	 * The IN_USE flag should be clear if the entry is available to use.
482	 * This flag is cleared on initialization and and when a volume is
483	 * deleted. All other times this flag should be set. If, for some
484	 * reason, a free entry cannot be found, look for the entry with the
485	 * highest missing count just in case there is one.
486	 */
487	_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
488	mt_entry = &sc->mapping_table[start_idx];
489	for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) {
490		if (!(mt_entry->device_info & MPR_MAP_IN_USE))
491			return map_idx;
492
493		if (mt_entry->missing_count > high_missing_count) {
494			high_missing_count = mt_entry->missing_count;
495			high_idx = map_idx;
496		}
497	}
498
499	if (high_idx == MPR_MAPTABLE_BAD_IDX) {
500		mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: Could not find a "
501		    "free entry in the mapping table for a Volume. The mapping "
502		    "table is probably corrupt.\n", __func__);
503	}
504
505	return high_idx;
506}
507
508/**
509 * _mapping_get_free_mt_idx - get first free index for a device
510 * @sc: per adapter object
511 * @start_idx: offset in the table to start search
512 *
513 * Returns the index of map table entry on success or bad index.
514 */
515static u32
516_mapping_get_free_mt_idx(struct mpr_softc *sc, u32 start_idx)
517{
518	u32 map_idx, max_idx = sc->max_devices;
519	struct dev_mapping_table *mt_entry = &sc->mapping_table[start_idx];
520	u16 volume_mapping_flags;
521
522	volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
523	    MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
524	if (sc->ir_firmware && (volume_mapping_flags ==
525	    MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING))
526		max_idx -= sc->max_volumes;
527
528	for (map_idx  = start_idx; map_idx < max_idx; map_idx++, mt_entry++)
529		if (!(mt_entry->device_info & (MPR_MAP_IN_USE |
530		    MPR_DEV_RESERVED)))
531			return map_idx;
532
533	return MPR_MAPTABLE_BAD_IDX;
534}
535
536/**
537 * _mapping_get_dpm_idx_from_id - get DPM index from ID
538 * @sc: per adapter object
539 * @id: volume WWID or enclosure ID or device ID
540 *
541 * Returns the index of DPM entry on success or bad index.
542 */
543static u16
544_mapping_get_dpm_idx_from_id(struct mpr_softc *sc, u64 id, u32 phy_bits)
545{
546	u16 entry_num;
547	uint64_t PhysicalIdentifier;
548	Mpi2DriverMap0Entry_t *dpm_entry;
549
550	dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
551	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
552	PhysicalIdentifier = dpm_entry->PhysicalIdentifier.High;
553	PhysicalIdentifier = (PhysicalIdentifier << 32) |
554	    dpm_entry->PhysicalIdentifier.Low;
555	for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++,
556	    dpm_entry++)
557		if ((id == PhysicalIdentifier) &&
558		    (!phy_bits || !dpm_entry->PhysicalBitsMapping ||
559		    (phy_bits & dpm_entry->PhysicalBitsMapping)))
560			return entry_num;
561
562	return MPR_DPM_BAD_IDX;
563}
564
565
566/**
567 * _mapping_get_free_dpm_idx - get first available DPM index
568 * @sc: per adapter object
569 *
570 * Returns the index of DPM entry on success or bad index.
571 */
572static u32
573_mapping_get_free_dpm_idx(struct mpr_softc *sc)
574{
575	u16 entry_num;
576	Mpi2DriverMap0Entry_t *dpm_entry;
577	u16 current_entry = MPR_DPM_BAD_IDX, missing_cnt, high_missing_cnt = 0;
578	u64 physical_id;
579	struct dev_mapping_table *mt_entry;
580	u32 map_idx;
581
582	for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) {
583		dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
584		    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
585		dpm_entry += entry_num;
586		missing_cnt = dpm_entry->MappingInformation &
587		    MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
588
589		/*
590		 * If entry is used and not missing, then this entry can't be
591		 * used. Look at next one.
592		 */
593		if (sc->dpm_entry_used[entry_num] && !missing_cnt)
594			continue;
595
596		/*
597		 * If this entry is not used at all, then the missing count
598		 * doesn't matter. Just use this one. Otherwise, keep looking
599		 * and make sure the entry with the highest missing count is
600		 * used.
601		 */
602		if (!sc->dpm_entry_used[entry_num]) {
603			current_entry = entry_num;
604			break;
605		}
606		if ((current_entry == MPR_DPM_BAD_IDX) ||
607		    (missing_cnt > high_missing_cnt)) {
608			current_entry = entry_num;
609			high_missing_cnt = missing_cnt;
610		}
611	}
612
613	/*
614	 * If an entry has been found to use and it's already marked as used
615	 * it means that some device was already using this entry but it's
616	 * missing, and that means that the connection between the missing
617	 * device's DPM entry and the mapping table needs to be cleared. To do
618	 * this, use the Physical ID of the old device still in the DPM entry
619	 * to find its mapping table entry, then mark its DPM entry as BAD.
620	 */
621	if ((current_entry != MPR_DPM_BAD_IDX) &&
622	    sc->dpm_entry_used[current_entry]) {
623		dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
624		    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
625		dpm_entry += current_entry;
626		physical_id = dpm_entry->PhysicalIdentifier.High;
627		physical_id = (physical_id << 32) |
628		    dpm_entry->PhysicalIdentifier.Low;
629		map_idx = _mapping_get_mt_idx_from_id(sc, physical_id);
630		if (map_idx != MPR_MAPTABLE_BAD_IDX) {
631			mt_entry = &sc->mapping_table[map_idx];
632			mt_entry->dpm_entry_num = MPR_DPM_BAD_IDX;
633		}
634	}
635	return current_entry;
636}
637
638/**
639 * _mapping_update_ir_missing_cnt - Updates missing count for a volume
640 * @sc: per adapter object
641 * @map_idx: map table index of the volume
642 * @element: IR configuration change element
643 * @wwid: IR volume ID.
644 *
645 * Updates the missing count in the map table and in the DPM entry for a volume
646 *
647 * Returns nothing.
648 */
649static void
650_mapping_update_ir_missing_cnt(struct mpr_softc *sc, u32 map_idx,
651    Mpi2EventIrConfigElement_t *element, u64 wwid)
652{
653	struct dev_mapping_table *mt_entry;
654	u8 missing_cnt, reason = element->ReasonCode, update_dpm = 1;
655	u16 dpm_idx;
656	Mpi2DriverMap0Entry_t *dpm_entry;
657
658	/*
659	 * Depending on the reason code, update the missing count. Always set
660	 * the init_complete flag when here, so just do it first. That flag is
661	 * used for volumes to make sure that the DPM entry has been updated.
662	 * When a volume is deleted, clear the map entry's IN_USE flag so that
663	 * the entry can be used again if another volume is created. Also clear
664	 * its dev_handle entry so that other functions can't find this volume
665	 * by the handle, since it's not defined any longer.
666	 */
667	mt_entry = &sc->mapping_table[map_idx];
668	mt_entry->init_complete = 1;
669	if ((reason == MPI2_EVENT_IR_CHANGE_RC_ADDED) ||
670	    (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED)) {
671		mt_entry->missing_count = 0;
672	} else if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED) {
673		if (mt_entry->missing_count < MPR_MAX_MISSING_COUNT)
674			mt_entry->missing_count++;
675
676		mt_entry->device_info &= ~MPR_MAP_IN_USE;
677		mt_entry->dev_handle = 0;
678	}
679
680	/*
681	 * If persistent mapping is enabled, update the DPM with the new missing
682	 * count for the volume. If the DPM index is bad, get a free one. If
683	 * it's bad for a volume that's being deleted do nothing because that
684	 * volume doesn't have a DPM entry.
685	 */
686	if (!sc->is_dpm_enable)
687		return;
688	dpm_idx = mt_entry->dpm_entry_num;
689	if (dpm_idx == MPR_DPM_BAD_IDX) {
690		if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED)
691		{
692			mpr_dprint(sc, MPR_MAPPING, "%s: Volume being deleted "
693			    "is not in DPM so DPM missing count will not be "
694			    "updated.\n", __func__);
695			return;
696		}
697	}
698	if (dpm_idx == MPR_DPM_BAD_IDX)
699		dpm_idx = _mapping_get_free_dpm_idx(sc);
700
701	/*
702	 * Got the DPM entry for the volume or found a free DPM entry if this is
703	 * a new volume. Check if the current information is outdated.
704	 */
705	if (dpm_idx != MPR_DPM_BAD_IDX) {
706		dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
707		    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
708		dpm_entry += dpm_idx;
709		missing_cnt = dpm_entry->MappingInformation &
710		    MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
711		if ((mt_entry->physical_id ==
712		    le64toh(((u64)dpm_entry->PhysicalIdentifier.High << 32) |
713		    (u64)dpm_entry->PhysicalIdentifier.Low)) && (missing_cnt ==
714		    mt_entry->missing_count)) {
715			mpr_dprint(sc, MPR_MAPPING, "%s: DPM entry for volume "
716			   "with target ID %d does not require an update.\n",
717			    __func__, mt_entry->id);
718			update_dpm = 0;
719		}
720	}
721
722	/*
723	 * Update the volume's persistent info if it's new or the ID or missing
724	 * count has changed. If a good DPM index has not been found by now,
725	 * there is no space left in the DPM table.
726	 */
727	if ((dpm_idx != MPR_DPM_BAD_IDX) && update_dpm) {
728		mpr_dprint(sc, MPR_MAPPING, "%s: Update DPM entry for volume "
729		    "with target ID %d.\n", __func__, mt_entry->id);
730		mt_entry->dpm_entry_num = dpm_idx;
731		dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
732		    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
733		dpm_entry += dpm_idx;
734		dpm_entry->PhysicalIdentifier.Low =
735		    (0xFFFFFFFF & mt_entry->physical_id);
736		dpm_entry->PhysicalIdentifier.High =
737		    (mt_entry->physical_id >> 32);
738		dpm_entry->DeviceIndex = map_idx;
739		dpm_entry->MappingInformation = mt_entry->missing_count;
740		dpm_entry->PhysicalBitsMapping = 0;
741		dpm_entry->Reserved1 = 0;
742		sc->dpm_flush_entry[dpm_idx] = 1;
743		sc->dpm_entry_used[dpm_idx] = 1;
744	} else if (dpm_idx == MPR_DPM_BAD_IDX) {
745		mpr_dprint(sc, MPR_INFO | MPR_MAPPING, "%s: No space to add an "
746		    "entry in the DPM table for volume with target ID %d.\n",
747		    __func__, mt_entry->id);
748	}
749}
750
751/**
752 * _mapping_add_to_removal_table - add DPM index to the removal table
753 * @sc: per adapter object
754 * @dpm_idx: Index of DPM entry to remove
755 *
756 * Adds a DPM entry number to the removal table.
757 *
758 * Returns nothing.
759 */
760static void
761_mapping_add_to_removal_table(struct mpr_softc *sc, u16 dpm_idx)
762{
763	struct map_removal_table *remove_entry;
764	u32 i;
765
766	/*
767	 * This is only used to remove entries from the DPM in the controller.
768	 * If DPM is not enabled, just return.
769	 */
770	if (!sc->is_dpm_enable)
771		return;
772
773	/*
774	 * Find the first available removal_table entry and add the new entry
775	 * there.
776	 */
777	remove_entry = sc->removal_table;
778	for (i = 0; i < sc->max_devices; i++, remove_entry++) {
779		if (remove_entry->dpm_entry_num != MPR_DPM_BAD_IDX)
780			continue;
781
782		mpr_dprint(sc, MPR_MAPPING, "%s: Adding DPM entry %d to table "
783		    "for removal.\n", __func__, dpm_idx);
784		remove_entry->dpm_entry_num = dpm_idx;
785		break;
786	}
787
788}
789
790/**
791 * _mapping_inc_missing_count
792 * @sc: per adapter object
793 * @map_idx: index into the mapping table for the device that is missing
794 *
795 * Increment the missing count in the mapping table for a SAS, SATA, or PCIe
796 * device that is not responding. If Persitent Mapping is used, increment the
797 * DPM entry as well. Currently, this function is only called if the target
798 * goes missing, so after initialization has completed. This means that the
799 * missing count can only go from 0 to 1 here. The missing count is incremented
800 * during initialization as well, so that's where a target's missing count can
801 * go past 1.
802 *
803 * Returns nothing.
804 */
805static void
806_mapping_inc_missing_count(struct mpr_softc *sc, u32 map_idx)
807{
808	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
809	struct dev_mapping_table *mt_entry;
810	Mpi2DriverMap0Entry_t *dpm_entry;
811
812	if (map_idx == MPR_MAPTABLE_BAD_IDX) {
813		mpr_dprint(sc, MPR_INFO | MPR_MAPPING, "%s: device is already "
814		    "removed from mapping table\n", __func__);
815		return;
816	}
817	mt_entry = &sc->mapping_table[map_idx];
818	if (mt_entry->missing_count < MPR_MAX_MISSING_COUNT)
819		mt_entry->missing_count++;
820
821	/*
822	 * When using Enc/Slot mapping, when a device is removed, it's mapping
823	 * table information should be cleared. Otherwise, the target ID will
824	 * be incorrect if this same device is re-added to a different slot.
825	 */
826	if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
827	    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
828		_mapping_clear_map_entry(mt_entry);
829	}
830
831	/*
832	 * When using device mapping, update the missing count in the DPM entry,
833	 * but only if the missing count has changed.
834	 */
835	if (((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
836	    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) &&
837	    sc->is_dpm_enable &&
838	    mt_entry->dpm_entry_num != MPR_DPM_BAD_IDX) {
839		dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
840		    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
841		dpm_entry += mt_entry->dpm_entry_num;
842		if (dpm_entry->MappingInformation != mt_entry->missing_count) {
843			dpm_entry->MappingInformation = mt_entry->missing_count;
844			sc->dpm_flush_entry[mt_entry->dpm_entry_num] = 1;
845		}
846	}
847}
848
849/**
850 * _mapping_update_missing_count - Update missing count for a device
851 * @sc: per adapter object
852 * @topo_change: Topology change event entry
853 *
854 * Search through the topology change list and if any device is found not
855 * responding it's associated map table entry and DPM entry is updated
856 *
857 * Returns nothing.
858 */
859static void
860_mapping_update_missing_count(struct mpr_softc *sc,
861    struct _map_topology_change *topo_change)
862{
863	u8 entry;
864	struct _map_phy_change *phy_change;
865	u32 map_idx;
866
867	for (entry = 0; entry < topo_change->num_entries; entry++) {
868		phy_change = &topo_change->phy_details[entry];
869		if (!phy_change->dev_handle || (phy_change->reason !=
870		    MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING))
871			continue;
872		map_idx = _mapping_get_mt_idx_from_handle(sc, phy_change->
873		    dev_handle);
874		phy_change->is_processed = 1;
875		_mapping_inc_missing_count(sc, map_idx);
876	}
877}
878
879/**
880 * _mapping_update_pcie_missing_count - Update missing count for a PCIe device
881 * @sc: per adapter object
882 * @topo_change: Topology change event entry
883 *
884 * Search through the PCIe topology change list and if any device is found not
885 * responding it's associated map table entry and DPM entry is updated
886 *
887 * Returns nothing.
888 */
889static void
890_mapping_update_pcie_missing_count(struct mpr_softc *sc,
891    struct _map_pcie_topology_change *topo_change)
892{
893	u8 entry;
894	struct _map_port_change *port_change;
895	u32 map_idx;
896
897	for (entry = 0; entry < topo_change->num_entries; entry++) {
898		port_change = &topo_change->port_details[entry];
899		if (!port_change->dev_handle || (port_change->reason !=
900		    MPI26_EVENT_PCIE_TOPO_PS_NOT_RESPONDING))
901			continue;
902		map_idx = _mapping_get_mt_idx_from_handle(sc, port_change->
903		    dev_handle);
904		port_change->is_processed = 1;
905		_mapping_inc_missing_count(sc, map_idx);
906	}
907}
908
909/**
910 * _mapping_find_enc_map_space -find map table entries for enclosure
911 * @sc: per adapter object
912 * @et_entry: enclosure entry
913 *
914 * Search through the mapping table defragment it and provide contiguous
915 * space in map table for a particular enclosure entry
916 *
917 * Returns start index in map table or bad index.
918 */
919static u32
920_mapping_find_enc_map_space(struct mpr_softc *sc,
921    struct enc_mapping_table *et_entry)
922{
923	u16 vol_mapping_flags;
924	u32 skip_count, end_of_table, map_idx, enc_idx;
925	u16 num_found;
926	u32 start_idx = MPR_MAPTABLE_BAD_IDX;
927	struct dev_mapping_table *mt_entry;
928	struct enc_mapping_table *enc_entry;
929	unsigned char done_flag = 0, found_space;
930	u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
931
932	skip_count = sc->num_rsvd_entries;
933	num_found = 0;
934
935	vol_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
936	    MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
937
938	/*
939	 * The end of the mapping table depends on where volumes are kept, if
940	 * IR is enabled.
941	 */
942	if (!sc->ir_firmware)
943		end_of_table = sc->max_devices;
944	else if (vol_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING)
945		end_of_table = sc->max_devices;
946	else
947		end_of_table = sc->max_devices - sc->max_volumes;
948
949	/*
950	 * The skip_count is the number of entries that are reserved at the
951	 * beginning of the mapping table. But, it does not include the number
952	 * of Physical IDs that are reserved for direct attached devices. Look
953	 * through the mapping table after these reserved entries to see if
954	 * the devices for this enclosure are already mapped. The PHY bit check
955	 * is used to make sure that at least one PHY bit is common between the
956	 * enclosure and the device that is already mapped.
957	 */
958	mpr_dprint(sc, MPR_MAPPING, "%s: Looking for space in the mapping "
959	    "table for added enclosure.\n", __func__);
960	for (map_idx = (max_num_phy_ids + skip_count);
961	    map_idx < end_of_table; map_idx++) {
962		mt_entry = &sc->mapping_table[map_idx];
963		if ((et_entry->enclosure_id == mt_entry->physical_id) &&
964		    (!mt_entry->phy_bits || (mt_entry->phy_bits &
965		    et_entry->phy_bits))) {
966			num_found += 1;
967			if (num_found == et_entry->num_slots) {
968				start_idx = (map_idx - num_found) + 1;
969				mpr_dprint(sc, MPR_MAPPING, "%s: Found space "
970				    "in the mapping for enclosure at map index "
971				    "%d.\n", __func__, start_idx);
972				return start_idx;
973			}
974		} else
975			num_found = 0;
976	}
977
978	/*
979	 * If the enclosure's devices are not mapped already, look for
980	 * contiguous entries in the mapping table that are not reserved. If
981	 * enough entries are found, return the starting index for that space.
982	 */
983	num_found = 0;
984	for (map_idx = (max_num_phy_ids + skip_count);
985	    map_idx < end_of_table; map_idx++) {
986		mt_entry = &sc->mapping_table[map_idx];
987		if (!(mt_entry->device_info & MPR_DEV_RESERVED)) {
988			num_found += 1;
989			if (num_found == et_entry->num_slots) {
990				start_idx = (map_idx - num_found) + 1;
991				mpr_dprint(sc, MPR_MAPPING, "%s: Found space "
992				    "in the mapping for enclosure at map index "
993				    "%d.\n", __func__, start_idx);
994				return start_idx;
995			}
996		} else
997			num_found = 0;
998	}
999
1000	/*
1001	 * If here, it means that not enough space in the mapping table was
1002	 * found to support this enclosure, so go through the enclosure table to
1003	 * see if any enclosure entries have a missing count. If so, get the
1004	 * enclosure with the highest missing count and check it to see if there
1005	 * is enough space for the new enclosure.
1006	 */
1007	while (!done_flag) {
1008		enc_idx = _mapping_get_high_missing_et_idx(sc);
1009		if (enc_idx == MPR_ENCTABLE_BAD_IDX) {
1010			mpr_dprint(sc, MPR_MAPPING, "%s: Not enough space was "
1011			    "found in the mapping for the added enclosure.\n",
1012			    __func__);
1013			return MPR_MAPTABLE_BAD_IDX;
1014		}
1015
1016		/*
1017		 * Found a missing enclosure. Set the skip_search flag so this
1018		 * enclosure is not checked again for a high missing count if
1019		 * the loop continues. This way, all missing enclosures can
1020		 * have their space added together to find enough space in the
1021		 * mapping table for the added enclosure. The space must be
1022		 * contiguous.
1023		 */
1024		mpr_dprint(sc, MPR_MAPPING, "%s: Space from a missing "
1025		    "enclosure was found.\n", __func__);
1026		enc_entry = &sc->enclosure_table[enc_idx];
1027		enc_entry->skip_search = 1;
1028
1029		/*
1030		 * Unmark all of the missing enclosure's device's reserved
1031		 * space. These will be remarked as reserved if this missing
1032		 * enclosure's space is not used.
1033		 */
1034		mpr_dprint(sc, MPR_MAPPING, "%s: Clear the reserved flag for "
1035		    "all of the map entries for the enclosure.\n", __func__);
1036		mt_entry = &sc->mapping_table[enc_entry->start_index];
1037		for (map_idx = enc_entry->start_index; map_idx <
1038		    (enc_entry->start_index + enc_entry->num_slots); map_idx++,
1039		    mt_entry++)
1040			mt_entry->device_info &= ~MPR_DEV_RESERVED;
1041
1042		/*
1043		 * Now that space has been unreserved, check again to see if
1044		 * enough space is available for the new enclosure.
1045		 */
1046		mpr_dprint(sc, MPR_MAPPING, "%s: Check if new mapping space is "
1047		    "enough for the new enclosure.\n", __func__);
1048		found_space = 0;
1049		num_found = 0;
1050		for (map_idx = (max_num_phy_ids + skip_count);
1051		    map_idx < end_of_table; map_idx++) {
1052			mt_entry = &sc->mapping_table[map_idx];
1053			if (!(mt_entry->device_info & MPR_DEV_RESERVED)) {
1054				num_found += 1;
1055				if (num_found == et_entry->num_slots) {
1056					start_idx = (map_idx - num_found) + 1;
1057					found_space = 1;
1058					break;
1059				}
1060			} else
1061				num_found = 0;
1062		}
1063		if (!found_space)
1064			continue;
1065
1066		/*
1067		 * If enough space was found, all of the missing enclosures that
1068		 * will be used for the new enclosure must be added to the
1069		 * removal table. Then all mappings for the enclosure's devices
1070		 * and for the enclosure itself need to be cleared. There may be
1071		 * more than one enclosure to add to the removal table and
1072		 * clear.
1073		 */
1074		mpr_dprint(sc, MPR_MAPPING, "%s: Found space in the mapping "
1075		    "for enclosure at map index %d.\n", __func__, start_idx);
1076		for (map_idx = start_idx; map_idx < (start_idx + num_found);
1077		    map_idx++) {
1078			enc_entry = sc->enclosure_table;
1079			for (enc_idx = 0; enc_idx < sc->num_enc_table_entries;
1080			    enc_idx++, enc_entry++) {
1081				if (map_idx < enc_entry->start_index ||
1082				    map_idx > (enc_entry->start_index +
1083				    enc_entry->num_slots))
1084					continue;
1085				if (!enc_entry->removal_flag) {
1086					mpr_dprint(sc, MPR_MAPPING, "%s: "
1087					    "Enclosure %d will be removed from "
1088					    "the mapping table.\n", __func__,
1089					    enc_idx);
1090					enc_entry->removal_flag = 1;
1091					_mapping_add_to_removal_table(sc,
1092					    enc_entry->dpm_entry_num);
1093				}
1094				mt_entry = &sc->mapping_table[map_idx];
1095				_mapping_clear_map_entry(mt_entry);
1096				if (map_idx == (enc_entry->start_index +
1097				    enc_entry->num_slots - 1))
1098					_mapping_clear_enc_entry(et_entry);
1099			}
1100		}
1101
1102		/*
1103		 * During the search for space for this enclosure, some entries
1104		 * in the mapping table may have been unreserved. Go back and
1105		 * change all of these to reserved again. Only the enclosures
1106		 * with the removal_flag set should be left as unreserved. The
1107		 * skip_search flag needs to be cleared as well so that the
1108		 * enclosure's space will be looked at the next time space is
1109		 * needed.
1110		 */
1111		enc_entry = sc->enclosure_table;
1112		for (enc_idx = 0; enc_idx < sc->num_enc_table_entries;
1113		    enc_idx++, enc_entry++) {
1114			if (!enc_entry->removal_flag) {
1115				mpr_dprint(sc, MPR_MAPPING, "%s: Reset the "
1116				    "reserved flag for all of the map entries "
1117				    "for enclosure %d.\n", __func__, enc_idx);
1118				mt_entry = &sc->mapping_table[enc_entry->
1119				    start_index];
1120				for (map_idx = enc_entry->start_index; map_idx <
1121				    (enc_entry->start_index +
1122				    enc_entry->num_slots); map_idx++,
1123				    mt_entry++)
1124					mt_entry->device_info |=
1125					    MPR_DEV_RESERVED;
1126				et_entry->skip_search = 0;
1127			}
1128		}
1129		done_flag = 1;
1130	}
1131	return start_idx;
1132}
1133
1134/**
1135 * _mapping_get_dev_info -get information about newly added devices
1136 * @sc: per adapter object
1137 * @topo_change: Topology change event entry
1138 *
1139 * Search through the topology change event list and issues sas device pg0
1140 * requests for the newly added device and reserved entries in tables
1141 *
1142 * Returns nothing
1143 */
1144static void
1145_mapping_get_dev_info(struct mpr_softc *sc,
1146    struct _map_topology_change *topo_change)
1147{
1148	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1149	Mpi2ConfigReply_t mpi_reply;
1150	Mpi2SasDevicePage0_t sas_device_pg0;
1151	u8 entry, enc_idx, phy_idx;
1152	u32 map_idx, index, device_info;
1153	struct _map_phy_change *phy_change, *tmp_phy_change;
1154	uint64_t sas_address;
1155	struct enc_mapping_table *et_entry;
1156	struct dev_mapping_table *mt_entry;
1157	u8 add_code = MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED;
1158	int rc = 1;
1159
1160	for (entry = 0; entry < topo_change->num_entries; entry++) {
1161		phy_change = &topo_change->phy_details[entry];
1162		if (phy_change->is_processed || !phy_change->dev_handle ||
1163		    phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED)
1164			continue;
1165
1166		if (mpr_config_get_sas_device_pg0(sc, &mpi_reply,
1167		    &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
1168		    phy_change->dev_handle)) {
1169			phy_change->is_processed = 1;
1170			continue;
1171		}
1172
1173		/*
1174		 * Always get SATA Identify information because this is used
1175		 * to determine if Start/Stop Unit should be sent to the drive
1176		 * when the system is shutdown.
1177		 */
1178		device_info = le32toh(sas_device_pg0.DeviceInfo);
1179		sas_address = le32toh(sas_device_pg0.SASAddress.High);
1180		sas_address = (sas_address << 32) |
1181		    le32toh(sas_device_pg0.SASAddress.Low);
1182		if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) &&
1183		    (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) {
1184			rc = mprsas_get_sas_address_for_sata_disk(sc,
1185			    &sas_address, phy_change->dev_handle, device_info,
1186			    &phy_change->is_SATA_SSD);
1187			if (rc) {
1188				mpr_dprint(sc, MPR_ERROR, "%s: failed to get "
1189				    "disk type (SSD or HDD) and SAS Address "
1190				    "for SATA device with handle 0x%04x\n",
1191				    __func__, phy_change->dev_handle);
1192			}
1193		}
1194
1195		phy_change->physical_id = sas_address;
1196		phy_change->slot = le16toh(sas_device_pg0.Slot);
1197		phy_change->device_info = device_info;
1198
1199		/*
1200		 * When using Enc/Slot mapping, if this device is an enclosure
1201		 * make sure that all of its slots can fit into the mapping
1202		 * table.
1203		 */
1204		if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1205		    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1206			/*
1207			 * The enclosure should already be in the enclosure
1208			 * table due to the Enclosure Add event. If not, just
1209			 * continue, nothing can be done.
1210			 */
1211			enc_idx = _mapping_get_enc_idx_from_handle(sc,
1212			    topo_change->enc_handle);
1213			if (enc_idx == MPR_ENCTABLE_BAD_IDX) {
1214				phy_change->is_processed = 1;
1215				mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: "
1216				    "failed to add the device with handle "
1217				    "0x%04x because the enclosure is not in "
1218				    "the mapping table\n", __func__,
1219				    phy_change->dev_handle);
1220				continue;
1221			}
1222			if (!((phy_change->device_info &
1223			    MPI2_SAS_DEVICE_INFO_END_DEVICE) &&
1224			    (phy_change->device_info &
1225			    (MPI2_SAS_DEVICE_INFO_SSP_TARGET |
1226			    MPI2_SAS_DEVICE_INFO_STP_TARGET |
1227			    MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))) {
1228				phy_change->is_processed = 1;
1229				continue;
1230			}
1231			et_entry = &sc->enclosure_table[enc_idx];
1232
1233			/*
1234			 * If the enclosure already has a start_index, it's been
1235			 * mapped, so go to the next Topo change.
1236			 */
1237			if (et_entry->start_index != MPR_MAPTABLE_BAD_IDX)
1238				continue;
1239
1240			/*
1241			 * If the Expander Handle is 0, the devices are direct
1242			 * attached. In that case, the start_index must be just
1243			 * after the reserved entries. Otherwise, find space in
1244			 * the mapping table for the enclosure's devices.
1245			 */
1246			if (!topo_change->exp_handle) {
1247				map_idx	= sc->num_rsvd_entries;
1248				et_entry->start_index = map_idx;
1249			} else {
1250				map_idx = _mapping_find_enc_map_space(sc,
1251				    et_entry);
1252				et_entry->start_index = map_idx;
1253
1254				/*
1255				 * If space cannot be found to hold all of the
1256				 * enclosure's devices in the mapping table,
1257				 * there's no need to continue checking the
1258				 * other devices in this event. Set all of the
1259				 * phy_details for this event (if the change is
1260				 * for an add) as already processed because none
1261				 * of these devices can be added to the mapping
1262				 * table.
1263				 */
1264				if (et_entry->start_index ==
1265				    MPR_MAPTABLE_BAD_IDX) {
1266					mpr_dprint(sc, MPR_ERROR | MPR_MAPPING,
1267					    "%s: failed to add the enclosure "
1268					    "with ID 0x%016jx because there is "
1269					    "no free space available in the "
1270					    "mapping table for all of the "
1271					    "enclosure's devices.\n", __func__,
1272					    (uintmax_t)et_entry->enclosure_id);
1273					phy_change->is_processed = 1;
1274					for (phy_idx = 0; phy_idx <
1275					    topo_change->num_entries;
1276					    phy_idx++) {
1277						tmp_phy_change =
1278						    &topo_change->phy_details
1279						    [phy_idx];
1280						if (tmp_phy_change->reason ==
1281						    add_code)
1282							tmp_phy_change->
1283							    is_processed = 1;
1284					}
1285					break;
1286				}
1287			}
1288
1289			/*
1290			 * Found space in the mapping table for this enclosure.
1291			 * Initialize each mapping table entry for the
1292			 * enclosure.
1293			 */
1294			mpr_dprint(sc, MPR_MAPPING, "%s: Initialize %d map "
1295			    "entries for the enclosure, starting at map index "
1296			    " %d.\n", __func__, et_entry->num_slots, map_idx);
1297			mt_entry = &sc->mapping_table[map_idx];
1298			for (index = map_idx; index < (et_entry->num_slots
1299			    + map_idx); index++, mt_entry++) {
1300				mt_entry->device_info = MPR_DEV_RESERVED;
1301				mt_entry->physical_id = et_entry->enclosure_id;
1302				mt_entry->phy_bits = et_entry->phy_bits;
1303				mt_entry->missing_count = 0;
1304			}
1305		}
1306	}
1307}
1308
1309/**
1310 * _mapping_get_pcie_dev_info -get information about newly added PCIe devices
1311 * @sc: per adapter object
1312 * @topo_change: Topology change event entry
1313 *
1314 * Searches through the PCIe topology change event list and issues PCIe device
1315 * pg0 requests for the newly added PCIe device. If the device is in an
1316 * enclosure, search for available space in the enclosure mapping table for the
1317 * device and reserve that space.
1318 *
1319 * Returns nothing
1320 */
1321static void
1322_mapping_get_pcie_dev_info(struct mpr_softc *sc,
1323    struct _map_pcie_topology_change *topo_change)
1324{
1325	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1326	Mpi2ConfigReply_t mpi_reply;
1327	Mpi26PCIeDevicePage0_t pcie_device_pg0;
1328	u8 entry, enc_idx, port_idx;
1329	u32 map_idx, index;
1330	struct _map_port_change *port_change, *tmp_port_change;
1331	uint64_t pcie_wwid;
1332	struct enc_mapping_table *et_entry;
1333	struct dev_mapping_table *mt_entry;
1334	u8 add_code = MPI26_EVENT_PCIE_TOPO_PS_DEV_ADDED;
1335
1336	for (entry = 0; entry < topo_change->num_entries; entry++) {
1337		port_change = &topo_change->port_details[entry];
1338		if (port_change->is_processed || !port_change->dev_handle ||
1339		    port_change->reason != MPI26_EVENT_PCIE_TOPO_PS_DEV_ADDED)
1340			continue;
1341		if (mpr_config_get_pcie_device_pg0(sc, &mpi_reply,
1342		    &pcie_device_pg0, MPI26_PCIE_DEVICE_PGAD_FORM_HANDLE,
1343		    port_change->dev_handle)) {
1344			port_change->is_processed = 1;
1345			continue;
1346		}
1347
1348		pcie_wwid = pcie_device_pg0.WWID.High;
1349		pcie_wwid = (pcie_wwid << 32) | pcie_device_pg0.WWID.Low;
1350		port_change->physical_id = pcie_wwid;
1351		port_change->slot = le16toh(pcie_device_pg0.Slot);
1352		port_change->device_info = le32toh(pcie_device_pg0.DeviceInfo);
1353
1354		/*
1355		 * When using Enc/Slot mapping, if this device is an enclosure
1356		 * make sure that all of its slots can fit into the mapping
1357		 * table.
1358		 */
1359		if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1360		    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1361			/*
1362			 * The enclosure should already be in the enclosure
1363			 * table due to the Enclosure Add event. If not, just
1364			 * continue, nothing can be done.
1365			 */
1366			enc_idx = _mapping_get_enc_idx_from_handle(sc,
1367			    topo_change->enc_handle);
1368			if (enc_idx == MPR_ENCTABLE_BAD_IDX) {
1369				port_change->is_processed = 1;
1370				mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: "
1371				    "failed to add the device with handle "
1372				    "0x%04x because the enclosure is not in "
1373				    "the mapping table\n", __func__,
1374				    port_change->dev_handle);
1375				continue;
1376			}
1377			if (!(port_change->device_info &
1378			    MPI26_PCIE_DEVINFO_NVME)) {
1379				port_change->is_processed = 1;
1380				continue;
1381			}
1382			et_entry = &sc->enclosure_table[enc_idx];
1383
1384			/*
1385			 * If the enclosure already has a start_index, it's been
1386			 * mapped, so go to the next Topo change.
1387			 */
1388			if (et_entry->start_index != MPR_MAPTABLE_BAD_IDX)
1389				continue;
1390
1391			/*
1392			 * If the Switch Handle is 0, the devices are direct
1393			 * attached. In that case, the start_index must be just
1394			 * after the reserved entries. Otherwise, find space in
1395			 * the mapping table for the enclosure's devices.
1396			 */
1397			if (!topo_change->switch_dev_handle) {
1398				map_idx	= sc->num_rsvd_entries;
1399				et_entry->start_index = map_idx;
1400			} else {
1401				map_idx = _mapping_find_enc_map_space(sc,
1402				    et_entry);
1403				et_entry->start_index = map_idx;
1404
1405				/*
1406				 * If space cannot be found to hold all of the
1407				 * enclosure's devices in the mapping table,
1408				 * there's no need to continue checking the
1409				 * other devices in this event. Set all of the
1410				 * port_details for this event (if the change is
1411				 * for an add) as already processed because none
1412				 * of these devices can be added to the mapping
1413				 * table.
1414				 */
1415				if (et_entry->start_index ==
1416				    MPR_MAPTABLE_BAD_IDX) {
1417					mpr_dprint(sc, MPR_ERROR | MPR_MAPPING,
1418					    "%s: failed to add the enclosure "
1419					    "with ID 0x%016jx because there is "
1420					    "no free space available in the "
1421					    "mapping table for all of the "
1422					    "enclosure's devices.\n", __func__,
1423					    (uintmax_t)et_entry->enclosure_id);
1424					port_change->is_processed = 1;
1425					for (port_idx = 0; port_idx <
1426					    topo_change->num_entries;
1427					    port_idx++) {
1428						tmp_port_change =
1429						    &topo_change->port_details
1430						    [port_idx];
1431						if (tmp_port_change->reason ==
1432						    add_code)
1433							tmp_port_change->
1434							    is_processed = 1;
1435					}
1436					break;
1437				}
1438			}
1439
1440			/*
1441			 * Found space in the mapping table for this enclosure.
1442			 * Initialize each mapping table entry for the
1443			 * enclosure.
1444			 */
1445			mpr_dprint(sc, MPR_MAPPING, "%s: Initialize %d map "
1446			    "entries for the enclosure, starting at map index "
1447			    " %d.\n", __func__, et_entry->num_slots, map_idx);
1448			mt_entry = &sc->mapping_table[map_idx];
1449			for (index = map_idx; index < (et_entry->num_slots
1450			    + map_idx); index++, mt_entry++) {
1451				mt_entry->device_info = MPR_DEV_RESERVED;
1452				mt_entry->physical_id = et_entry->enclosure_id;
1453				mt_entry->phy_bits = et_entry->phy_bits;
1454				mt_entry->missing_count = 0;
1455			}
1456		}
1457	}
1458}
1459
1460/**
1461 * _mapping_set_mid_to_eid -set map table data from enclosure table
1462 * @sc: per adapter object
1463 * @et_entry: enclosure entry
1464 *
1465 * Returns nothing
1466 */
1467static inline void
1468_mapping_set_mid_to_eid(struct mpr_softc *sc,
1469    struct enc_mapping_table *et_entry)
1470{
1471	struct dev_mapping_table *mt_entry;
1472	u16 slots = et_entry->num_slots, map_idx;
1473	u32 start_idx = et_entry->start_index;
1474
1475	if (start_idx != MPR_MAPTABLE_BAD_IDX) {
1476		mt_entry = &sc->mapping_table[start_idx];
1477		for (map_idx = 0; map_idx < slots; map_idx++, mt_entry++)
1478			mt_entry->physical_id = et_entry->enclosure_id;
1479	}
1480}
1481
1482/**
1483 * _mapping_clear_removed_entries - mark the entries to be cleared
1484 * @sc: per adapter object
1485 *
1486 * Search through the removal table and mark the entries which needs to be
1487 * flushed to DPM and also updates the map table and enclosure table by
1488 * clearing the corresponding entries.
1489 *
1490 * Returns nothing
1491 */
1492static void
1493_mapping_clear_removed_entries(struct mpr_softc *sc)
1494{
1495	u32 remove_idx;
1496	struct map_removal_table *remove_entry;
1497	Mpi2DriverMap0Entry_t *dpm_entry;
1498	u8 done_flag = 0, num_entries, m, i;
1499	struct enc_mapping_table *et_entry, *from, *to;
1500	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1501
1502	if (sc->is_dpm_enable) {
1503		remove_entry = sc->removal_table;
1504		for (remove_idx = 0; remove_idx < sc->max_devices;
1505		    remove_idx++, remove_entry++) {
1506			if (remove_entry->dpm_entry_num != MPR_DPM_BAD_IDX) {
1507				dpm_entry = (Mpi2DriverMap0Entry_t *)
1508				    ((u8 *) sc->dpm_pg0 +
1509				    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1510				dpm_entry += remove_entry->dpm_entry_num;
1511				dpm_entry->PhysicalIdentifier.Low = 0;
1512				dpm_entry->PhysicalIdentifier.High = 0;
1513				dpm_entry->DeviceIndex = 0;
1514				dpm_entry->MappingInformation = 0;
1515				dpm_entry->PhysicalBitsMapping = 0;
1516				sc->dpm_flush_entry[remove_entry->
1517				    dpm_entry_num] = 1;
1518				sc->dpm_entry_used[remove_entry->dpm_entry_num]
1519				    = 0;
1520				remove_entry->dpm_entry_num = MPR_DPM_BAD_IDX;
1521			}
1522		}
1523	}
1524
1525	/*
1526	 * When using Enc/Slot mapping, if a new enclosure was added and old
1527	 * enclosure space was needed, the enclosure table may now have gaps
1528	 * that need to be closed. All enclosure mappings need to be contiguous
1529	 * so that space can be reused correctly if available.
1530	 */
1531	if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1532	    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1533		num_entries = sc->num_enc_table_entries;
1534		while (!done_flag) {
1535			done_flag = 1;
1536			et_entry = sc->enclosure_table;
1537			for (i = 0; i < num_entries; i++, et_entry++) {
1538				if (!et_entry->enc_handle && et_entry->
1539				    init_complete) {
1540					done_flag = 0;
1541					if (i != (num_entries - 1)) {
1542						from = &sc->enclosure_table
1543						    [i+1];
1544						to = &sc->enclosure_table[i];
1545						for (m = i; m < (num_entries -
1546						    1); m++, from++, to++) {
1547							_mapping_set_mid_to_eid
1548							    (sc, to);
1549							*to = *from;
1550						}
1551						_mapping_clear_enc_entry(to);
1552						sc->num_enc_table_entries--;
1553						num_entries =
1554						    sc->num_enc_table_entries;
1555					} else {
1556						_mapping_clear_enc_entry
1557						    (et_entry);
1558						sc->num_enc_table_entries--;
1559						num_entries =
1560						    sc->num_enc_table_entries;
1561					}
1562				}
1563			}
1564		}
1565	}
1566}
1567
1568/**
1569 * _mapping_add_new_device -Add the new device into mapping table
1570 * @sc: per adapter object
1571 * @topo_change: Topology change event entry
1572 *
1573 * Search through the topology change event list and update map table,
1574 * enclosure table and DPM pages for the newly added devices.
1575 *
1576 * Returns nothing
1577 */
1578static void
1579_mapping_add_new_device(struct mpr_softc *sc,
1580    struct _map_topology_change *topo_change)
1581{
1582	u8 enc_idx, missing_cnt, is_removed = 0;
1583	u16 dpm_idx;
1584	u32 search_idx, map_idx;
1585	u32 entry;
1586	struct dev_mapping_table *mt_entry;
1587	struct enc_mapping_table *et_entry;
1588	struct _map_phy_change *phy_change;
1589	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1590	Mpi2DriverMap0Entry_t *dpm_entry;
1591	uint64_t temp64_var;
1592	u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
1593	u8 hdr_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER);
1594	u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
1595
1596	for (entry = 0; entry < topo_change->num_entries; entry++) {
1597		phy_change = &topo_change->phy_details[entry];
1598		if (phy_change->is_processed)
1599			continue;
1600		if (phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED ||
1601		    !phy_change->dev_handle) {
1602			phy_change->is_processed = 1;
1603			continue;
1604		}
1605		if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1606		    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1607			enc_idx = _mapping_get_enc_idx_from_handle
1608			    (sc, topo_change->enc_handle);
1609			if (enc_idx == MPR_ENCTABLE_BAD_IDX) {
1610				phy_change->is_processed = 1;
1611				mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: "
1612				    "failed to add the device with handle "
1613				    "0x%04x because the enclosure is not in "
1614				    "the mapping table\n", __func__,
1615				    phy_change->dev_handle);
1616				continue;
1617			}
1618
1619			/*
1620			 * If the enclosure's start_index is BAD here, it means
1621			 * that there is no room in the mapping table to cover
1622			 * all of the devices that could be in the enclosure.
1623			 * There's no reason to process any of the devices for
1624			 * this enclosure since they can't be mapped.
1625			 */
1626			et_entry = &sc->enclosure_table[enc_idx];
1627			if (et_entry->start_index == MPR_MAPTABLE_BAD_IDX) {
1628				phy_change->is_processed = 1;
1629				mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: "
1630				    "failed to add the device with handle "
1631				    "0x%04x because there is no free space "
1632				    "available in the mapping table\n",
1633				    __func__, phy_change->dev_handle);
1634				continue;
1635			}
1636
1637			/*
1638			 * Add this device to the mapping table at the correct
1639			 * offset where space was found to map the enclosure.
1640			 * Then setup the DPM entry information if being used.
1641			 */
1642			map_idx = et_entry->start_index + phy_change->slot -
1643			    et_entry->start_slot;
1644			mt_entry = &sc->mapping_table[map_idx];
1645			mt_entry->physical_id = phy_change->physical_id;
1646			mt_entry->id = map_idx;
1647			mt_entry->dev_handle = phy_change->dev_handle;
1648			mt_entry->missing_count = 0;
1649			mt_entry->dpm_entry_num = et_entry->dpm_entry_num;
1650			mt_entry->device_info = phy_change->device_info |
1651			    (MPR_DEV_RESERVED | MPR_MAP_IN_USE);
1652			if (sc->is_dpm_enable) {
1653				dpm_idx = et_entry->dpm_entry_num;
1654				if (dpm_idx == MPR_DPM_BAD_IDX)
1655					dpm_idx = _mapping_get_dpm_idx_from_id
1656					    (sc, et_entry->enclosure_id,
1657					     et_entry->phy_bits);
1658				if (dpm_idx == MPR_DPM_BAD_IDX) {
1659					dpm_idx = _mapping_get_free_dpm_idx(sc);
1660					if (dpm_idx != MPR_DPM_BAD_IDX) {
1661						dpm_entry =
1662						    (Mpi2DriverMap0Entry_t *)
1663						    ((u8 *) sc->dpm_pg0 +
1664						     hdr_sz);
1665						dpm_entry += dpm_idx;
1666						dpm_entry->
1667						    PhysicalIdentifier.Low =
1668						    (0xFFFFFFFF &
1669						    et_entry->enclosure_id);
1670						dpm_entry->
1671						    PhysicalIdentifier.High =
1672						    (et_entry->enclosure_id
1673						     >> 32);
1674						dpm_entry->DeviceIndex =
1675						    (U16)et_entry->start_index;
1676						dpm_entry->MappingInformation =
1677						    et_entry->num_slots;
1678						dpm_entry->MappingInformation
1679						    <<= map_shift;
1680						dpm_entry->PhysicalBitsMapping
1681						    = et_entry->phy_bits;
1682						et_entry->dpm_entry_num =
1683						    dpm_idx;
1684						sc->dpm_entry_used[dpm_idx] = 1;
1685						sc->dpm_flush_entry[dpm_idx] =
1686						    1;
1687						phy_change->is_processed = 1;
1688					} else {
1689						phy_change->is_processed = 1;
1690						mpr_dprint(sc, MPR_ERROR |
1691						    MPR_MAPPING, "%s: failed "
1692						    "to add the device with "
1693						    "handle 0x%04x to "
1694						    "persistent table because "
1695						    "there is no free space "
1696						    "available\n", __func__,
1697						    phy_change->dev_handle);
1698					}
1699				} else {
1700					et_entry->dpm_entry_num = dpm_idx;
1701					mt_entry->dpm_entry_num = dpm_idx;
1702				}
1703			}
1704			et_entry->init_complete = 1;
1705		} else if ((ioc_pg8_flags &
1706		    MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1707		    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
1708
1709			/*
1710			 * Get the mapping table index for this device. If it's
1711			 * not in the mapping table yet, find a free entry if
1712			 * one is available. If there are no free entries, look
1713			 * for the entry that has the highest missing count. If
1714			 * none of that works to find an entry in the mapping
1715			 * table, there is a problem. Log a message and just
1716			 * continue on.
1717			 */
1718			map_idx = _mapping_get_mt_idx_from_id
1719			    (sc, phy_change->physical_id);
1720			if (map_idx == MPR_MAPTABLE_BAD_IDX) {
1721				search_idx = sc->num_rsvd_entries;
1722				if (topo_change->exp_handle)
1723					search_idx += max_num_phy_ids;
1724				map_idx = _mapping_get_free_mt_idx(sc,
1725				    search_idx);
1726			}
1727
1728			/*
1729			 * If an entry will be used that has a missing device,
1730			 * clear its entry from  the DPM in the controller.
1731			 */
1732			if (map_idx == MPR_MAPTABLE_BAD_IDX) {
1733				map_idx = _mapping_get_high_missing_mt_idx(sc);
1734				if (map_idx != MPR_MAPTABLE_BAD_IDX) {
1735					mt_entry = &sc->mapping_table[map_idx];
1736					_mapping_add_to_removal_table(sc,
1737					    mt_entry->dpm_entry_num);
1738					is_removed = 1;
1739					mt_entry->init_complete = 0;
1740				}
1741			}
1742			if (map_idx != MPR_MAPTABLE_BAD_IDX) {
1743				mt_entry = &sc->mapping_table[map_idx];
1744				mt_entry->physical_id = phy_change->physical_id;
1745				mt_entry->id = map_idx;
1746				mt_entry->dev_handle = phy_change->dev_handle;
1747				mt_entry->missing_count = 0;
1748				mt_entry->device_info = phy_change->device_info
1749				    | (MPR_DEV_RESERVED | MPR_MAP_IN_USE);
1750			} else {
1751				phy_change->is_processed = 1;
1752				mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: "
1753				    "failed to add the device with handle "
1754				    "0x%04x because there is no free space "
1755				    "available in the mapping table\n",
1756				    __func__, phy_change->dev_handle);
1757				continue;
1758			}
1759			if (sc->is_dpm_enable) {
1760				if (mt_entry->dpm_entry_num !=
1761				    MPR_DPM_BAD_IDX) {
1762					dpm_idx = mt_entry->dpm_entry_num;
1763					dpm_entry = (Mpi2DriverMap0Entry_t *)
1764					    ((u8 *)sc->dpm_pg0 + hdr_sz);
1765					dpm_entry += dpm_idx;
1766					missing_cnt = dpm_entry->
1767					    MappingInformation &
1768					    MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
1769					temp64_var = dpm_entry->
1770					    PhysicalIdentifier.High;
1771					temp64_var = (temp64_var << 32) |
1772					   dpm_entry->PhysicalIdentifier.Low;
1773
1774					/*
1775					 * If the Mapping Table's info is not
1776					 * the same as the DPM entry, clear the
1777					 * init_complete flag so that it's
1778					 * updated.
1779					 */
1780					if ((mt_entry->physical_id ==
1781					    temp64_var) && !missing_cnt)
1782						mt_entry->init_complete = 1;
1783					else
1784						mt_entry->init_complete = 0;
1785				} else {
1786					dpm_idx = _mapping_get_free_dpm_idx(sc);
1787					mt_entry->init_complete = 0;
1788				}
1789				if (dpm_idx != MPR_DPM_BAD_IDX &&
1790				    !mt_entry->init_complete) {
1791					mt_entry->dpm_entry_num = dpm_idx;
1792					dpm_entry = (Mpi2DriverMap0Entry_t *)
1793					    ((u8 *)sc->dpm_pg0 + hdr_sz);
1794					dpm_entry += dpm_idx;
1795					dpm_entry->PhysicalIdentifier.Low =
1796					    (0xFFFFFFFF &
1797					    mt_entry->physical_id);
1798					dpm_entry->PhysicalIdentifier.High =
1799					    (mt_entry->physical_id >> 32);
1800					dpm_entry->DeviceIndex = (U16) map_idx;
1801					dpm_entry->MappingInformation = 0;
1802					dpm_entry->PhysicalBitsMapping = 0;
1803					sc->dpm_entry_used[dpm_idx] = 1;
1804					sc->dpm_flush_entry[dpm_idx] = 1;
1805					phy_change->is_processed = 1;
1806				} else if (dpm_idx == MPR_DPM_BAD_IDX) {
1807					phy_change->is_processed = 1;
1808					mpr_dprint(sc, MPR_ERROR | MPR_MAPPING,
1809					    "%s: failed to add the device with "
1810					    "handle 0x%04x to persistent table "
1811					    "because there is no free space "
1812					    "available\n", __func__,
1813					    phy_change->dev_handle);
1814				}
1815			}
1816			mt_entry->init_complete = 1;
1817		}
1818
1819		phy_change->is_processed = 1;
1820	}
1821	if (is_removed)
1822		_mapping_clear_removed_entries(sc);
1823}
1824
1825/**
1826 * _mapping_add_new_pcie_device -Add the new PCIe device into mapping table
1827 * @sc: per adapter object
1828 * @topo_change: Topology change event entry
1829 *
1830 * Search through the PCIe topology change event list and update map table,
1831 * enclosure table and DPM pages for the newly added devices.
1832 *
1833 * Returns nothing
1834 */
1835static void
1836_mapping_add_new_pcie_device(struct mpr_softc *sc,
1837    struct _map_pcie_topology_change *topo_change)
1838{
1839	u8 enc_idx, missing_cnt, is_removed = 0;
1840	u16 dpm_idx;
1841	u32 search_idx, map_idx;
1842	u32 entry;
1843	struct dev_mapping_table *mt_entry;
1844	struct enc_mapping_table *et_entry;
1845	struct _map_port_change *port_change;
1846	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1847	Mpi2DriverMap0Entry_t *dpm_entry;
1848	uint64_t temp64_var;
1849	u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
1850	u8 hdr_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER);
1851	u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
1852
1853	for (entry = 0; entry < topo_change->num_entries; entry++) {
1854		port_change = &topo_change->port_details[entry];
1855		if (port_change->is_processed)
1856			continue;
1857		if (port_change->reason != MPI26_EVENT_PCIE_TOPO_PS_DEV_ADDED ||
1858		    !port_change->dev_handle) {
1859			port_change->is_processed = 1;
1860			continue;
1861		}
1862		if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1863		    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1864			enc_idx = _mapping_get_enc_idx_from_handle
1865			    (sc, topo_change->enc_handle);
1866			if (enc_idx == MPR_ENCTABLE_BAD_IDX) {
1867				port_change->is_processed = 1;
1868				mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: "
1869				    "failed to add the device with handle "
1870				    "0x%04x because the enclosure is not in "
1871				    "the mapping table\n", __func__,
1872				    port_change->dev_handle);
1873				continue;
1874			}
1875
1876			/*
1877			 * If the enclosure's start_index is BAD here, it means
1878			 * that there is no room in the mapping table to cover
1879			 * all of the devices that could be in the enclosure.
1880			 * There's no reason to process any of the devices for
1881			 * this enclosure since they can't be mapped.
1882			 */
1883			et_entry = &sc->enclosure_table[enc_idx];
1884			if (et_entry->start_index == MPR_MAPTABLE_BAD_IDX) {
1885				port_change->is_processed = 1;
1886				mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: "
1887				    "failed to add the device with handle "
1888				    "0x%04x because there is no free space "
1889				    "available in the mapping table\n",
1890				    __func__, port_change->dev_handle);
1891				continue;
1892			}
1893
1894			/*
1895			 * Add this device to the mapping table at the correct
1896			 * offset where space was found to map the enclosure.
1897			 * Then setup the DPM entry information if being used.
1898			 */
1899			map_idx = et_entry->start_index + port_change->slot -
1900			    et_entry->start_slot;
1901			mt_entry = &sc->mapping_table[map_idx];
1902			mt_entry->physical_id = port_change->physical_id;
1903			mt_entry->id = map_idx;
1904			mt_entry->dev_handle = port_change->dev_handle;
1905			mt_entry->missing_count = 0;
1906			mt_entry->dpm_entry_num = et_entry->dpm_entry_num;
1907			mt_entry->device_info = port_change->device_info |
1908			    (MPR_DEV_RESERVED | MPR_MAP_IN_USE);
1909			if (sc->is_dpm_enable) {
1910				dpm_idx = et_entry->dpm_entry_num;
1911				if (dpm_idx == MPR_DPM_BAD_IDX)
1912					dpm_idx = _mapping_get_dpm_idx_from_id
1913					    (sc, et_entry->enclosure_id,
1914					     et_entry->phy_bits);
1915				if (dpm_idx == MPR_DPM_BAD_IDX) {
1916					dpm_idx = _mapping_get_free_dpm_idx(sc);
1917					if (dpm_idx != MPR_DPM_BAD_IDX) {
1918						dpm_entry =
1919						    (Mpi2DriverMap0Entry_t *)
1920						    ((u8 *) sc->dpm_pg0 +
1921						     hdr_sz);
1922						dpm_entry += dpm_idx;
1923						dpm_entry->
1924						    PhysicalIdentifier.Low =
1925						    (0xFFFFFFFF &
1926						    et_entry->enclosure_id);
1927						dpm_entry->
1928						    PhysicalIdentifier.High =
1929						    (et_entry->enclosure_id
1930						     >> 32);
1931						dpm_entry->DeviceIndex =
1932						    (U16)et_entry->start_index;
1933						dpm_entry->MappingInformation =
1934						    et_entry->num_slots;
1935						dpm_entry->MappingInformation
1936						    <<= map_shift;
1937						dpm_entry->PhysicalBitsMapping
1938						    = et_entry->phy_bits;
1939						et_entry->dpm_entry_num =
1940						    dpm_idx;
1941						sc->dpm_entry_used[dpm_idx] = 1;
1942						sc->dpm_flush_entry[dpm_idx] =
1943						    1;
1944						port_change->is_processed = 1;
1945					} else {
1946						port_change->is_processed = 1;
1947						mpr_dprint(sc, MPR_ERROR |
1948						    MPR_MAPPING, "%s: failed "
1949						    "to add the device with "
1950						    "handle 0x%04x to "
1951						    "persistent table because "
1952						    "there is no free space "
1953						    "available\n", __func__,
1954						    port_change->dev_handle);
1955					}
1956				} else {
1957					et_entry->dpm_entry_num = dpm_idx;
1958					mt_entry->dpm_entry_num = dpm_idx;
1959				}
1960			}
1961			et_entry->init_complete = 1;
1962		} else if ((ioc_pg8_flags &
1963		    MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1964		    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
1965
1966			/*
1967			 * Get the mapping table index for this device. If it's
1968			 * not in the mapping table yet, find a free entry if
1969			 * one is available. If there are no free entries, look
1970			 * for the entry that has the highest missing count. If
1971			 * none of that works to find an entry in the mapping
1972			 * table, there is a problem. Log a message and just
1973			 * continue on.
1974			 */
1975			map_idx = _mapping_get_mt_idx_from_id
1976			    (sc, port_change->physical_id);
1977			if (map_idx == MPR_MAPTABLE_BAD_IDX) {
1978				search_idx = sc->num_rsvd_entries;
1979				if (topo_change->switch_dev_handle)
1980					search_idx += max_num_phy_ids;
1981				map_idx = _mapping_get_free_mt_idx(sc,
1982				    search_idx);
1983			}
1984
1985			/*
1986			 * If an entry will be used that has a missing device,
1987			 * clear its entry from  the DPM in the controller.
1988			 */
1989			if (map_idx == MPR_MAPTABLE_BAD_IDX) {
1990				map_idx = _mapping_get_high_missing_mt_idx(sc);
1991				if (map_idx != MPR_MAPTABLE_BAD_IDX) {
1992					mt_entry = &sc->mapping_table[map_idx];
1993					_mapping_add_to_removal_table(sc,
1994					    mt_entry->dpm_entry_num);
1995					is_removed = 1;
1996					mt_entry->init_complete = 0;
1997				}
1998			}
1999			if (map_idx != MPR_MAPTABLE_BAD_IDX) {
2000				mt_entry = &sc->mapping_table[map_idx];
2001				mt_entry->physical_id =
2002				    port_change->physical_id;
2003				mt_entry->id = map_idx;
2004				mt_entry->dev_handle = port_change->dev_handle;
2005				mt_entry->missing_count = 0;
2006				mt_entry->device_info =
2007				    port_change->device_info |
2008				    (MPR_DEV_RESERVED | MPR_MAP_IN_USE);
2009			} else {
2010				port_change->is_processed = 1;
2011				mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: "
2012				    "failed to add the device with handle "
2013				    "0x%04x because there is no free space "
2014				    "available in the mapping table\n",
2015				    __func__, port_change->dev_handle);
2016				continue;
2017			}
2018			if (sc->is_dpm_enable) {
2019				if (mt_entry->dpm_entry_num !=
2020				    MPR_DPM_BAD_IDX) {
2021					dpm_idx = mt_entry->dpm_entry_num;
2022					dpm_entry = (Mpi2DriverMap0Entry_t *)
2023					    ((u8 *)sc->dpm_pg0 + hdr_sz);
2024					dpm_entry += dpm_idx;
2025					missing_cnt = dpm_entry->
2026					    MappingInformation &
2027					    MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
2028					temp64_var = dpm_entry->
2029					    PhysicalIdentifier.High;
2030					temp64_var = (temp64_var << 32) |
2031					   dpm_entry->PhysicalIdentifier.Low;
2032
2033					/*
2034					 * If the Mapping Table's info is not
2035					 * the same as the DPM entry, clear the
2036					 * init_complete flag so that it's
2037					 * updated.
2038					 */
2039					if ((mt_entry->physical_id ==
2040					    temp64_var) && !missing_cnt)
2041						mt_entry->init_complete = 1;
2042					else
2043						mt_entry->init_complete = 0;
2044				} else {
2045					dpm_idx = _mapping_get_free_dpm_idx(sc);
2046					mt_entry->init_complete = 0;
2047				}
2048				if (dpm_idx != MPR_DPM_BAD_IDX &&
2049				    !mt_entry->init_complete) {
2050					mt_entry->dpm_entry_num = dpm_idx;
2051					dpm_entry = (Mpi2DriverMap0Entry_t *)
2052					    ((u8 *)sc->dpm_pg0 + hdr_sz);
2053					dpm_entry += dpm_idx;
2054					dpm_entry->PhysicalIdentifier.Low =
2055					    (0xFFFFFFFF &
2056					    mt_entry->physical_id);
2057					dpm_entry->PhysicalIdentifier.High =
2058					    (mt_entry->physical_id >> 32);
2059					dpm_entry->DeviceIndex = (U16) map_idx;
2060					dpm_entry->MappingInformation = 0;
2061					dpm_entry->PhysicalBitsMapping = 0;
2062					sc->dpm_entry_used[dpm_idx] = 1;
2063					sc->dpm_flush_entry[dpm_idx] = 1;
2064					port_change->is_processed = 1;
2065				} else if (dpm_idx == MPR_DPM_BAD_IDX) {
2066					port_change->is_processed = 1;
2067					mpr_dprint(sc, MPR_ERROR | MPR_MAPPING,
2068					    "%s: failed to add the device with "
2069					    "handle 0x%04x to persistent table "
2070					    "because there is no free space "
2071					    "available\n", __func__,
2072					    port_change->dev_handle);
2073				}
2074			}
2075			mt_entry->init_complete = 1;
2076		}
2077
2078		port_change->is_processed = 1;
2079	}
2080	if (is_removed)
2081		_mapping_clear_removed_entries(sc);
2082}
2083
2084/**
2085 * _mapping_flush_dpm_pages -Flush the DPM pages to NVRAM
2086 * @sc: per adapter object
2087 *
2088 * Returns nothing
2089 */
2090static void
2091_mapping_flush_dpm_pages(struct mpr_softc *sc)
2092{
2093	Mpi2DriverMap0Entry_t *dpm_entry;
2094	Mpi2ConfigReply_t mpi_reply;
2095	Mpi2DriverMappingPage0_t config_page;
2096	u16 entry_num;
2097
2098	for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) {
2099		if (!sc->dpm_flush_entry[entry_num])
2100			continue;
2101		memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
2102		memcpy(&config_page.Header, (u8 *)sc->dpm_pg0,
2103		    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
2104		dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
2105		    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
2106		dpm_entry += entry_num;
2107		dpm_entry->MappingInformation = htole16(dpm_entry->
2108		    MappingInformation);
2109		dpm_entry->DeviceIndex = htole16(dpm_entry->DeviceIndex);
2110		dpm_entry->PhysicalBitsMapping = htole32(dpm_entry->
2111		    PhysicalBitsMapping);
2112		memcpy(&config_page.Entry, (u8 *)dpm_entry,
2113		    sizeof(Mpi2DriverMap0Entry_t));
2114		/* TODO-How to handle failed writes? */
2115		mpr_dprint(sc, MPR_MAPPING, "%s: Flushing DPM entry %d.\n",
2116		    __func__, entry_num);
2117		if (mpr_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
2118		    entry_num)) {
2119			mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: Flush of "
2120			    "DPM entry %d for device failed\n", __func__,
2121			    entry_num);
2122		} else
2123			sc->dpm_flush_entry[entry_num] = 0;
2124		dpm_entry->MappingInformation = le16toh(dpm_entry->
2125		    MappingInformation);
2126		dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
2127		dpm_entry->PhysicalBitsMapping = le32toh(dpm_entry->
2128		    PhysicalBitsMapping);
2129	}
2130}
2131
2132/**
2133 * _mapping_allocate_memory- allocates the memory required for mapping tables
2134 * @sc: per adapter object
2135 *
2136 * Allocates the memory for all the tables required for host mapping
2137 *
2138 * Return 0 on success or non-zero on failure.
2139 */
2140int
2141mpr_mapping_allocate_memory(struct mpr_softc *sc)
2142{
2143	uint32_t dpm_pg0_sz;
2144
2145	sc->mapping_table = malloc((sizeof(struct dev_mapping_table) *
2146	    sc->max_devices), M_MPR, M_ZERO|M_NOWAIT);
2147	if (!sc->mapping_table)
2148		goto free_resources;
2149
2150	sc->removal_table = malloc((sizeof(struct map_removal_table) *
2151	    sc->max_devices), M_MPR, M_ZERO|M_NOWAIT);
2152	if (!sc->removal_table)
2153		goto free_resources;
2154
2155	sc->enclosure_table = malloc((sizeof(struct enc_mapping_table) *
2156	    sc->max_enclosures), M_MPR, M_ZERO|M_NOWAIT);
2157	if (!sc->enclosure_table)
2158		goto free_resources;
2159
2160	sc->dpm_entry_used = malloc((sizeof(u8) * sc->max_dpm_entries),
2161	    M_MPR, M_ZERO|M_NOWAIT);
2162	if (!sc->dpm_entry_used)
2163		goto free_resources;
2164
2165	sc->dpm_flush_entry = malloc((sizeof(u8) * sc->max_dpm_entries),
2166	    M_MPR, M_ZERO|M_NOWAIT);
2167	if (!sc->dpm_flush_entry)
2168		goto free_resources;
2169
2170	dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) +
2171	    (sc->max_dpm_entries * sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY));
2172
2173	sc->dpm_pg0 = malloc(dpm_pg0_sz, M_MPR, M_ZERO|M_NOWAIT);
2174	if (!sc->dpm_pg0) {
2175		printf("%s: memory alloc failed for dpm page; disabling dpm\n",
2176		    __func__);
2177		sc->is_dpm_enable = 0;
2178	}
2179
2180	return 0;
2181
2182free_resources:
2183	free(sc->mapping_table, M_MPR);
2184	free(sc->removal_table, M_MPR);
2185	free(sc->enclosure_table, M_MPR);
2186	free(sc->dpm_entry_used, M_MPR);
2187	free(sc->dpm_flush_entry, M_MPR);
2188	free(sc->dpm_pg0, M_MPR);
2189	printf("%s: device initialization failed due to failure in mapping "
2190	    "table memory allocation\n", __func__);
2191	return -1;
2192}
2193
2194/**
2195 * mpr_mapping_free_memory- frees the memory allocated for mapping tables
2196 * @sc: per adapter object
2197 *
2198 * Returns nothing.
2199 */
2200void
2201mpr_mapping_free_memory(struct mpr_softc *sc)
2202{
2203	free(sc->mapping_table, M_MPR);
2204	free(sc->removal_table, M_MPR);
2205	free(sc->enclosure_table, M_MPR);
2206	free(sc->dpm_entry_used, M_MPR);
2207	free(sc->dpm_flush_entry, M_MPR);
2208	free(sc->dpm_pg0, M_MPR);
2209}
2210
2211static bool
2212_mapping_process_dpm_pg0(struct mpr_softc *sc)
2213{
2214	u8 missing_cnt, enc_idx;
2215	u16 slot_id, entry_num, num_slots;
2216	u32 map_idx, dev_idx, start_idx, end_idx;
2217	struct dev_mapping_table *mt_entry;
2218	Mpi2DriverMap0Entry_t *dpm_entry;
2219	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
2220	u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
2221	struct enc_mapping_table *et_entry;
2222	u64 physical_id;
2223	u32 phy_bits = 0;
2224
2225	/*
2226	 * start_idx and end_idx are only used for IR.
2227	 */
2228	if (sc->ir_firmware)
2229		_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
2230
2231	/*
2232	 * Look through all of the DPM entries that were read from the
2233	 * controller and copy them over to the driver's internal table if they
2234	 * have a non-zero ID. At this point, any ID with a value of 0 would be
2235	 * invalid, so don't copy it.
2236	 */
2237	mpr_dprint(sc, MPR_MAPPING, "%s: Start copy of %d DPM entries into the "
2238	    "mapping table.\n", __func__, sc->max_dpm_entries);
2239	dpm_entry = (Mpi2DriverMap0Entry_t *) ((uint8_t *) sc->dpm_pg0 +
2240	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
2241	for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++,
2242	    dpm_entry++) {
2243		physical_id = dpm_entry->PhysicalIdentifier.High;
2244		physical_id = (physical_id << 32) |
2245		    dpm_entry->PhysicalIdentifier.Low;
2246		if (!physical_id) {
2247			sc->dpm_entry_used[entry_num] = 0;
2248			continue;
2249		}
2250		sc->dpm_entry_used[entry_num] = 1;
2251		dpm_entry->MappingInformation = le16toh(dpm_entry->
2252		    MappingInformation);
2253		missing_cnt = dpm_entry->MappingInformation &
2254		    MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
2255		dev_idx = le16toh(dpm_entry->DeviceIndex);
2256		phy_bits = le32toh(dpm_entry->PhysicalBitsMapping);
2257
2258		/*
2259		 * Volumes are at special locations in the mapping table so
2260		 * account for that. Volume mapping table entries do not depend
2261		 * on the type of mapping, so continue the loop after adding
2262		 * volumes to the mapping table.
2263		 */
2264		if (sc->ir_firmware && (dev_idx >= start_idx) &&
2265		    (dev_idx <= end_idx)) {
2266			mt_entry = &sc->mapping_table[dev_idx];
2267			mt_entry->physical_id =
2268			    dpm_entry->PhysicalIdentifier.High;
2269			mt_entry->physical_id = (mt_entry->physical_id << 32) |
2270			    dpm_entry->PhysicalIdentifier.Low;
2271			mt_entry->id = dev_idx;
2272			mt_entry->missing_count = missing_cnt;
2273			mt_entry->dpm_entry_num = entry_num;
2274			mt_entry->device_info = MPR_DEV_RESERVED;
2275			continue;
2276		}
2277		if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
2278		    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
2279
2280			/*
2281			 * The dev_idx for an enclosure is the start index. If
2282			 * the start index is within the controller's default
2283			 * enclosure area, set the number of slots for this
2284			 * enclosure to the max allowed. Otherwise, it should be
2285			 * a normal enclosure and the number of slots is in the
2286			 * DPM entry's Mapping Information.
2287			 */
2288			if (dev_idx < (sc->num_rsvd_entries +
2289			    max_num_phy_ids)) {
2290				slot_id = 0;
2291				if (ioc_pg8_flags &
2292				    MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1)
2293					slot_id = 1;
2294				num_slots = max_num_phy_ids;
2295			} else {
2296				slot_id = 0;
2297				num_slots = dpm_entry->MappingInformation &
2298				    MPI2_DRVMAP0_MAPINFO_SLOT_MASK;
2299				num_slots >>= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
2300			}
2301			enc_idx = sc->num_enc_table_entries;
2302			if (enc_idx >= sc->max_enclosures) {
2303				mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: "
2304				    "Number of enclosure entries in DPM exceed "
2305				    "the max allowed of %d.\n", __func__,
2306				    sc->max_enclosures);
2307				break;
2308			}
2309			sc->num_enc_table_entries++;
2310			et_entry = &sc->enclosure_table[enc_idx];
2311			physical_id = dpm_entry->PhysicalIdentifier.High;
2312			et_entry->enclosure_id = (physical_id << 32) |
2313			    dpm_entry->PhysicalIdentifier.Low;
2314			et_entry->start_index = dev_idx;
2315			et_entry->dpm_entry_num = entry_num;
2316			et_entry->num_slots = num_slots;
2317			et_entry->start_slot = slot_id;
2318			et_entry->missing_count = missing_cnt;
2319			et_entry->phy_bits = phy_bits;
2320
2321			/*
2322			 * Initialize all entries for this enclosure in the
2323			 * mapping table and mark them as reserved. The actual
2324			 * devices have not been processed yet but when they are
2325			 * they will use these entries. If an entry is found
2326			 * that already has a valid DPM index, the mapping table
2327			 * is corrupt. This can happen if the mapping type is
2328			 * changed without clearing all of the DPM entries in
2329			 * the controller.
2330			 */
2331			mt_entry = &sc->mapping_table[dev_idx];
2332			for (map_idx = dev_idx; map_idx < (dev_idx + num_slots);
2333			    map_idx++, mt_entry++) {
2334				if (mt_entry->dpm_entry_num !=
2335				    MPR_DPM_BAD_IDX) {
2336					mpr_dprint(sc, MPR_ERROR | MPR_MAPPING,
2337					    "%s: Conflict in mapping table for "
2338					    " enclosure %d\n", __func__,
2339					    enc_idx);
2340					goto fail;
2341				}
2342				physical_id =
2343				    dpm_entry->PhysicalIdentifier.High;
2344				mt_entry->physical_id = (physical_id << 32) |
2345				    dpm_entry->PhysicalIdentifier.Low;
2346				mt_entry->phy_bits = phy_bits;
2347				mt_entry->id = dev_idx;
2348				mt_entry->dpm_entry_num = entry_num;
2349				mt_entry->missing_count = missing_cnt;
2350				mt_entry->device_info = MPR_DEV_RESERVED;
2351			}
2352		} else if ((ioc_pg8_flags &
2353		    MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
2354		    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
2355
2356			/*
2357			 * Device mapping, so simply copy the DPM entries to the
2358			 * mapping table, but check for a corrupt mapping table
2359			 * (as described above in Enc/Slot mapping).
2360			 */
2361			map_idx = dev_idx;
2362			mt_entry = &sc->mapping_table[map_idx];
2363			if (mt_entry->dpm_entry_num != MPR_DPM_BAD_IDX) {
2364				mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: "
2365				    "Conflict in mapping table for device %d\n",
2366				    __func__, map_idx);
2367				goto fail;
2368			}
2369			physical_id = dpm_entry->PhysicalIdentifier.High;
2370			mt_entry->physical_id = (physical_id << 32) |
2371			    dpm_entry->PhysicalIdentifier.Low;
2372			mt_entry->phy_bits = phy_bits;
2373			mt_entry->id = dev_idx;
2374			mt_entry->missing_count = missing_cnt;
2375			mt_entry->dpm_entry_num = entry_num;
2376			mt_entry->device_info = MPR_DEV_RESERVED;
2377		}
2378	} /*close the loop for DPM table */
2379	return (true);
2380
2381fail:
2382	for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) {
2383		sc->dpm_entry_used[entry_num] = 0;
2384		/*
2385		 * for IR firmware, it may be necessary to wipe out
2386		 * sc->mapping_table volumes tooi
2387		 */
2388	}
2389	for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++)
2390		_mapping_clear_enc_entry(sc->enclosure_table + enc_idx);
2391	sc->num_enc_table_entries = 0;
2392	return (false);
2393}
2394
2395/*
2396 * mpr_mapping_check_devices - start of the day check for device availabilty
2397 * @sc: per adapter object
2398 *
2399 * Returns nothing.
2400 */
2401void
2402mpr_mapping_check_devices(void *data)
2403{
2404	u32 i;
2405	struct dev_mapping_table *mt_entry;
2406	struct mpr_softc *sc = (struct mpr_softc *)data;
2407	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
2408	struct enc_mapping_table *et_entry;
2409	u32 start_idx = 0, end_idx = 0;
2410	u8 stop_device_checks = 0;
2411
2412	MPR_FUNCTRACE(sc);
2413
2414	/*
2415	 * Clear this flag so that this function is never called again except
2416	 * within this function if the check needs to be done again. The
2417	 * purpose is to check for missing devices that are currently in the
2418	 * mapping table so do this only at driver init after discovery.
2419	 */
2420	sc->track_mapping_events = 0;
2421
2422	/*
2423	 * callout synchronization
2424	 * This is used to prevent race conditions for the callout.
2425	 */
2426	mpr_dprint(sc, MPR_MAPPING, "%s: Start check for missing devices.\n",
2427	    __func__);
2428	mtx_assert(&sc->mpr_mtx, MA_OWNED);
2429	if ((callout_pending(&sc->device_check_callout)) ||
2430	    (!callout_active(&sc->device_check_callout))) {
2431		mpr_dprint(sc, MPR_MAPPING, "%s: Device Check Callout is "
2432		    "already pending or not active.\n", __func__);
2433		return;
2434	}
2435	callout_deactivate(&sc->device_check_callout);
2436
2437	/*
2438	 * Use callout to check if any devices in the mapping table have been
2439	 * processed yet. If ALL devices are marked as not init_complete, no
2440	 * devices have been processed and mapped. Until devices are mapped
2441	 * there's no reason to mark them as missing. Continue resetting this
2442	 * callout until devices have been mapped.
2443	 */
2444	if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
2445	    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
2446		et_entry = sc->enclosure_table;
2447		for (i = 0; i < sc->num_enc_table_entries; i++, et_entry++) {
2448			if (et_entry->init_complete) {
2449				stop_device_checks = 1;
2450				break;
2451			}
2452		}
2453	} else if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
2454	    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
2455		mt_entry = sc->mapping_table;
2456		for (i = 0; i < sc->max_devices; i++, mt_entry++) {
2457			if (mt_entry->init_complete) {
2458				stop_device_checks = 1;
2459				break;
2460			}
2461		}
2462	}
2463
2464	/*
2465	 * Setup another callout check after a delay. Keep doing this until
2466	 * devices are mapped.
2467	 */
2468	if (!stop_device_checks) {
2469		mpr_dprint(sc, MPR_MAPPING, "%s: No devices have been mapped. "
2470		    "Reset callout to check again after a %d second delay.\n",
2471		    __func__, MPR_MISSING_CHECK_DELAY);
2472		callout_reset(&sc->device_check_callout,
2473		    MPR_MISSING_CHECK_DELAY * hz, mpr_mapping_check_devices,
2474		    sc);
2475		return;
2476	}
2477	mpr_dprint(sc, MPR_MAPPING, "%s: Device check complete.\n", __func__);
2478
2479	/*
2480	 * Depending on the mapping type, check if devices have been processed
2481	 * and update their missing counts if not processed.
2482	 */
2483	if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
2484	    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
2485		et_entry = sc->enclosure_table;
2486		for (i = 0; i < sc->num_enc_table_entries; i++, et_entry++) {
2487			if (!et_entry->init_complete) {
2488				if (et_entry->missing_count <
2489				    MPR_MAX_MISSING_COUNT) {
2490					mpr_dprint(sc, MPR_MAPPING, "%s: "
2491					    "Enclosure %d is missing from the "
2492					    "topology. Update its missing "
2493					    "count.\n", __func__, i);
2494					et_entry->missing_count++;
2495					if (et_entry->dpm_entry_num !=
2496					    MPR_DPM_BAD_IDX) {
2497						_mapping_commit_enc_entry(sc,
2498						    et_entry);
2499					}
2500				}
2501				et_entry->init_complete = 1;
2502			}
2503		}
2504		if (!sc->ir_firmware)
2505			return;
2506		_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
2507		mt_entry = &sc->mapping_table[start_idx];
2508	} else if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
2509	    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
2510		start_idx = 0;
2511		end_idx = sc->max_devices - 1;
2512		mt_entry = sc->mapping_table;
2513	}
2514
2515	/*
2516	 * The start and end indices have been set above according to the
2517	 * mapping type. Go through these mappings and update any entries that
2518	 * do not have the init_complete flag set, which means they are missing.
2519	 */
2520	if (end_idx == 0)
2521		return;
2522	for (i = start_idx; i < (end_idx + 1); i++, mt_entry++) {
2523		if (mt_entry->device_info & MPR_DEV_RESERVED
2524		    && !mt_entry->physical_id)
2525			mt_entry->init_complete = 1;
2526		else if (mt_entry->device_info & MPR_DEV_RESERVED) {
2527			if (!mt_entry->init_complete) {
2528				mpr_dprint(sc, MPR_MAPPING, "%s: Device in "
2529				    "mapping table at index %d is missing from "
2530				    "topology. Update its missing count.\n",
2531				    __func__, i);
2532				if (mt_entry->missing_count <
2533				    MPR_MAX_MISSING_COUNT) {
2534					mt_entry->missing_count++;
2535					if (mt_entry->dpm_entry_num !=
2536					    MPR_DPM_BAD_IDX) {
2537						_mapping_commit_map_entry(sc,
2538						    mt_entry);
2539					}
2540				}
2541				mt_entry->init_complete = 1;
2542			}
2543		}
2544	}
2545}
2546
2547/**
2548 * mpr_mapping_initialize - initialize mapping tables
2549 * @sc: per adapter object
2550 *
2551 * Read controller persitant mapping tables into internal data area.
2552 *
2553 * Return 0 for success or non-zero for failure.
2554 */
2555int
2556mpr_mapping_initialize(struct mpr_softc *sc)
2557{
2558	uint16_t volume_mapping_flags, dpm_pg0_sz;
2559	uint32_t i;
2560	Mpi2ConfigReply_t mpi_reply;
2561	int error;
2562	uint8_t retry_count;
2563	uint16_t ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
2564
2565	/* The additional 1 accounts for the virtual enclosure
2566	 * created for the controller
2567	 */
2568	sc->max_enclosures = sc->facts->MaxEnclosures + 1;
2569	sc->max_expanders = sc->facts->MaxSasExpanders;
2570	sc->max_volumes = sc->facts->MaxVolumes;
2571	sc->max_devices = sc->facts->MaxTargets + sc->max_volumes;
2572	sc->pending_map_events = 0;
2573	sc->num_enc_table_entries = 0;
2574	sc->num_rsvd_entries = 0;
2575	sc->max_dpm_entries = sc->ioc_pg8.MaxPersistentEntries;
2576	sc->is_dpm_enable = (sc->max_dpm_entries) ? 1 : 0;
2577	sc->track_mapping_events = 0;
2578
2579	mpr_dprint(sc, MPR_MAPPING, "%s: Mapping table has a max of %d entries "
2580	    "and DPM has a max of %d entries.\n", __func__, sc->max_devices,
2581	    sc->max_dpm_entries);
2582
2583	if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING)
2584		sc->is_dpm_enable = 0;
2585
2586	if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
2587		sc->num_rsvd_entries = 1;
2588
2589	volume_mapping_flags = sc->ioc_pg8.IRVolumeMappingFlags &
2590	    MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
2591	if (sc->ir_firmware && (volume_mapping_flags ==
2592	    MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING))
2593		sc->num_rsvd_entries += sc->max_volumes;
2594
2595	error = mpr_mapping_allocate_memory(sc);
2596	if (error)
2597		return (error);
2598
2599	for (i = 0; i < sc->max_devices; i++)
2600		_mapping_clear_map_entry(sc->mapping_table + i);
2601
2602	for (i = 0; i < sc->max_enclosures; i++)
2603		_mapping_clear_enc_entry(sc->enclosure_table + i);
2604
2605	for (i = 0; i < sc->max_devices; i++) {
2606		sc->removal_table[i].dev_handle = 0;
2607		sc->removal_table[i].dpm_entry_num = MPR_DPM_BAD_IDX;
2608	}
2609
2610	memset(sc->dpm_entry_used, 0, sc->max_dpm_entries);
2611	memset(sc->dpm_flush_entry, 0, sc->max_dpm_entries);
2612
2613	if (sc->is_dpm_enable) {
2614		dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) +
2615		    (sc->max_dpm_entries *
2616		     sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY));
2617		retry_count = 0;
2618
2619retry_read_dpm:
2620		if (mpr_config_get_dpm_pg0(sc, &mpi_reply, sc->dpm_pg0,
2621		    dpm_pg0_sz)) {
2622			mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: DPM page "
2623			    "read failed.\n", __func__);
2624			if (retry_count < 3) {
2625				retry_count++;
2626				goto retry_read_dpm;
2627			}
2628			sc->is_dpm_enable = 0;
2629		}
2630	}
2631
2632	if (sc->is_dpm_enable) {
2633		if (!_mapping_process_dpm_pg0(sc))
2634			sc->is_dpm_enable = 0;
2635	}
2636	if (! sc->is_dpm_enable) {
2637		mpr_dprint(sc, MPR_MAPPING, "%s: DPM processing is disabled. "
2638		    "Device mappings will not persist across reboots or "
2639		    "resets.\n", __func__);
2640	}
2641
2642	sc->track_mapping_events = 1;
2643	return 0;
2644}
2645
2646/**
2647 * mpr_mapping_exit - clear mapping table and associated memory
2648 * @sc: per adapter object
2649 *
2650 * Returns nothing.
2651 */
2652void
2653mpr_mapping_exit(struct mpr_softc *sc)
2654{
2655	_mapping_flush_dpm_pages(sc);
2656	mpr_mapping_free_memory(sc);
2657}
2658
2659/**
2660 * mpr_mapping_get_tid - return the target id for sas device and handle
2661 * @sc: per adapter object
2662 * @sas_address: sas address of the device
2663 * @handle: device handle
2664 *
2665 * Returns valid target ID on success or BAD_ID.
2666 */
2667unsigned int
2668mpr_mapping_get_tid(struct mpr_softc *sc, uint64_t sas_address, u16 handle)
2669{
2670	u32 map_idx;
2671	struct dev_mapping_table *mt_entry;
2672
2673	for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
2674		mt_entry = &sc->mapping_table[map_idx];
2675		if (mt_entry->dev_handle == handle && mt_entry->physical_id ==
2676		    sas_address)
2677			return mt_entry->id;
2678	}
2679
2680	return MPR_MAP_BAD_ID;
2681}
2682
2683/**
2684 * mpr_mapping_get_tid_from_handle - find a target id in mapping table using
2685 * only the dev handle.  This is just a wrapper function for the local function
2686 * _mapping_get_mt_idx_from_handle.
2687 * @sc: per adapter object
2688 * @handle: device handle
2689 *
2690 * Returns valid target ID on success or BAD_ID.
2691 */
2692unsigned int
2693mpr_mapping_get_tid_from_handle(struct mpr_softc *sc, u16 handle)
2694{
2695	return (_mapping_get_mt_idx_from_handle(sc, handle));
2696}
2697
2698/**
2699 * mpr_mapping_get_raid_tid - return the target id for raid device
2700 * @sc: per adapter object
2701 * @wwid: world wide identifier for raid volume
2702 * @volHandle: volume device handle
2703 *
2704 * Returns valid target ID on success or BAD_ID.
2705 */
2706unsigned int
2707mpr_mapping_get_raid_tid(struct mpr_softc *sc, u64 wwid, u16 volHandle)
2708{
2709	u32 start_idx, end_idx, map_idx;
2710	struct dev_mapping_table *mt_entry;
2711
2712	_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
2713	mt_entry = &sc->mapping_table[start_idx];
2714	for (map_idx  = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) {
2715		if (mt_entry->dev_handle == volHandle &&
2716		    mt_entry->physical_id == wwid)
2717			return mt_entry->id;
2718	}
2719
2720	return MPR_MAP_BAD_ID;
2721}
2722
2723/**
2724 * mpr_mapping_get_raid_tid_from_handle - find raid device in mapping table
2725 * using only the volume dev handle.  This is just a wrapper function for the
2726 * local function _mapping_get_ir_mt_idx_from_handle.
2727 * @sc: per adapter object
2728 * @volHandle: volume device handle
2729 *
2730 * Returns valid target ID on success or BAD_ID.
2731 */
2732unsigned int
2733mpr_mapping_get_raid_tid_from_handle(struct mpr_softc *sc, u16 volHandle)
2734{
2735	return (_mapping_get_ir_mt_idx_from_handle(sc, volHandle));
2736}
2737
2738/**
2739 * mpr_mapping_enclosure_dev_status_change_event - handle enclosure events
2740 * @sc: per adapter object
2741 * @event_data: event data payload
2742 *
2743 * Return nothing.
2744 */
2745void
2746mpr_mapping_enclosure_dev_status_change_event(struct mpr_softc *sc,
2747    Mpi2EventDataSasEnclDevStatusChange_t *event_data)
2748{
2749	u8 enc_idx, missing_count;
2750	struct enc_mapping_table *et_entry;
2751	Mpi2DriverMap0Entry_t *dpm_entry;
2752	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
2753	u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
2754	u8 update_phy_bits = 0;
2755	u32 saved_phy_bits;
2756	uint64_t temp64_var;
2757
2758	if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) !=
2759	    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING)
2760		goto out;
2761
2762	dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
2763	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
2764
2765	if (event_data->ReasonCode == MPI2_EVENT_SAS_ENCL_RC_ADDED) {
2766		if (!event_data->NumSlots) {
2767			mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: Enclosure "
2768			    "with handle = 0x%x reported 0 slots.\n", __func__,
2769			    le16toh(event_data->EnclosureHandle));
2770			goto out;
2771		}
2772		temp64_var = event_data->EnclosureLogicalID.High;
2773		temp64_var = (temp64_var << 32) |
2774		    event_data->EnclosureLogicalID.Low;
2775		enc_idx = _mapping_get_enc_idx_from_id(sc, temp64_var,
2776		    event_data->PhyBits);
2777
2778		/*
2779		 * If the Added enclosure is already in the Enclosure Table,
2780		 * make sure that all the the enclosure info is up to date. If
2781		 * the enclosure was missing and has just been added back, or if
2782		 * the enclosure's Phy Bits have changed, clear the missing
2783		 * count and update the Phy Bits in the mapping table and in the
2784		 * DPM, if it's being used.
2785		 */
2786		if (enc_idx != MPR_ENCTABLE_BAD_IDX) {
2787			et_entry = &sc->enclosure_table[enc_idx];
2788			if (et_entry->init_complete &&
2789			    !et_entry->missing_count) {
2790				mpr_dprint(sc, MPR_MAPPING, "%s: Enclosure %d "
2791				    "is already present with handle = 0x%x\n",
2792				    __func__, enc_idx, et_entry->enc_handle);
2793				goto out;
2794			}
2795			et_entry->enc_handle = le16toh(event_data->
2796			    EnclosureHandle);
2797			et_entry->start_slot = le16toh(event_data->StartSlot);
2798			saved_phy_bits = et_entry->phy_bits;
2799			et_entry->phy_bits |= le32toh(event_data->PhyBits);
2800			if (saved_phy_bits != et_entry->phy_bits)
2801				update_phy_bits = 1;
2802			if (et_entry->missing_count || update_phy_bits) {
2803				et_entry->missing_count = 0;
2804				if (sc->is_dpm_enable &&
2805				    et_entry->dpm_entry_num !=
2806				    MPR_DPM_BAD_IDX) {
2807					dpm_entry += et_entry->dpm_entry_num;
2808					missing_count =
2809					    (u8)(dpm_entry->MappingInformation &
2810					    MPI2_DRVMAP0_MAPINFO_MISSING_MASK);
2811					if (missing_count || update_phy_bits) {
2812						dpm_entry->MappingInformation
2813						    = et_entry->num_slots;
2814						dpm_entry->MappingInformation
2815						    <<= map_shift;
2816						dpm_entry->PhysicalBitsMapping
2817						    = et_entry->phy_bits;
2818						sc->dpm_flush_entry[et_entry->
2819						    dpm_entry_num] = 1;
2820					}
2821				}
2822			}
2823		} else {
2824			/*
2825			 * This is a new enclosure that is being added.
2826			 * Initialize the Enclosure Table entry. It will be
2827			 * finalized when a device is added for the enclosure
2828			 * and the enclosure has enough space in the Mapping
2829			 * Table to map its devices.
2830			 */
2831			enc_idx = sc->num_enc_table_entries;
2832			if (enc_idx >= sc->max_enclosures) {
2833				mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: "
2834				    "Enclosure cannot be added to mapping "
2835				    "table because it's full.\n", __func__);
2836				goto out;
2837			}
2838			sc->num_enc_table_entries++;
2839			et_entry = &sc->enclosure_table[enc_idx];
2840			et_entry->enc_handle = le16toh(event_data->
2841			    EnclosureHandle);
2842			et_entry->enclosure_id = le64toh(event_data->
2843			    EnclosureLogicalID.High);
2844			et_entry->enclosure_id =
2845			    ((et_entry->enclosure_id << 32) |
2846			    le64toh(event_data->EnclosureLogicalID.Low));
2847			et_entry->start_index = MPR_MAPTABLE_BAD_IDX;
2848			et_entry->dpm_entry_num = MPR_DPM_BAD_IDX;
2849			et_entry->num_slots = le16toh(event_data->NumSlots);
2850			et_entry->start_slot = le16toh(event_data->StartSlot);
2851			et_entry->phy_bits = le32toh(event_data->PhyBits);
2852		}
2853		et_entry->init_complete = 1;
2854	} else if (event_data->ReasonCode ==
2855	    MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING) {
2856		/*
2857		 * An enclosure was removed. Update its missing count and then
2858		 * update the DPM entry with the new missing count for the
2859		 * enclosure.
2860		 */
2861		enc_idx = _mapping_get_enc_idx_from_handle(sc,
2862		    le16toh(event_data->EnclosureHandle));
2863		if (enc_idx == MPR_ENCTABLE_BAD_IDX) {
2864			mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: Cannot "
2865			    "unmap enclosure %d because it has already been "
2866			    "deleted.\n", __func__, enc_idx);
2867			goto out;
2868		}
2869		et_entry = &sc->enclosure_table[enc_idx];
2870		if (et_entry->missing_count < MPR_MAX_MISSING_COUNT)
2871			et_entry->missing_count++;
2872		if (sc->is_dpm_enable &&
2873		    et_entry->dpm_entry_num != MPR_DPM_BAD_IDX) {
2874			dpm_entry += et_entry->dpm_entry_num;
2875			dpm_entry->MappingInformation = et_entry->num_slots;
2876			dpm_entry->MappingInformation <<= map_shift;
2877			dpm_entry->MappingInformation |=
2878			    et_entry->missing_count;
2879			sc->dpm_flush_entry[et_entry->dpm_entry_num] = 1;
2880		}
2881		et_entry->init_complete = 1;
2882	}
2883
2884out:
2885	_mapping_flush_dpm_pages(sc);
2886	if (sc->pending_map_events)
2887		sc->pending_map_events--;
2888}
2889
2890/**
2891 * mpr_mapping_topology_change_event - handle topology change events
2892 * @sc: per adapter object
2893 * @event_data: event data payload
2894 *
2895 * Returns nothing.
2896 */
2897void
2898mpr_mapping_topology_change_event(struct mpr_softc *sc,
2899    Mpi2EventDataSasTopologyChangeList_t *event_data)
2900{
2901	struct _map_topology_change topo_change;
2902	struct _map_phy_change *phy_change;
2903	Mpi2EventSasTopoPhyEntry_t *event_phy_change;
2904	u8 i, num_entries;
2905
2906	topo_change.enc_handle = le16toh(event_data->EnclosureHandle);
2907	topo_change.exp_handle = le16toh(event_data->ExpanderDevHandle);
2908	num_entries = event_data->NumEntries;
2909	topo_change.num_entries = num_entries;
2910	topo_change.start_phy_num = event_data->StartPhyNum;
2911	topo_change.num_phys = event_data->NumPhys;
2912	topo_change.exp_status = event_data->ExpStatus;
2913	event_phy_change = event_data->PHY;
2914	topo_change.phy_details = NULL;
2915
2916	if (!num_entries)
2917		goto out;
2918	phy_change = malloc(sizeof(struct _map_phy_change) * num_entries,
2919	    M_MPR, M_NOWAIT|M_ZERO);
2920	topo_change.phy_details = phy_change;
2921	if (!phy_change)
2922		goto out;
2923	for (i = 0; i < num_entries; i++, event_phy_change++, phy_change++) {
2924		phy_change->dev_handle = le16toh(event_phy_change->
2925		    AttachedDevHandle);
2926		phy_change->reason = event_phy_change->PhyStatus &
2927		    MPI2_EVENT_SAS_TOPO_RC_MASK;
2928	}
2929	_mapping_update_missing_count(sc, &topo_change);
2930	_mapping_get_dev_info(sc, &topo_change);
2931	_mapping_clear_removed_entries(sc);
2932	_mapping_add_new_device(sc, &topo_change);
2933
2934out:
2935	free(topo_change.phy_details, M_MPR);
2936	_mapping_flush_dpm_pages(sc);
2937	if (sc->pending_map_events)
2938		sc->pending_map_events--;
2939}
2940
2941/**
2942 * mpr_mapping_pcie_topology_change_event - handle PCIe topology change events
2943 * @sc: per adapter object
2944 * @event_data: event data payload
2945 *
2946 * Returns nothing.
2947 */
2948void
2949mpr_mapping_pcie_topology_change_event(struct mpr_softc *sc,
2950    Mpi26EventDataPCIeTopologyChangeList_t *event_data)
2951{
2952	struct _map_pcie_topology_change topo_change;
2953	struct _map_port_change *port_change;
2954	Mpi26EventPCIeTopoPortEntry_t *event_port_change;
2955	u8 i, num_entries;
2956
2957	topo_change.switch_dev_handle = le16toh(event_data->SwitchDevHandle);
2958	topo_change.enc_handle = le16toh(event_data->EnclosureHandle);
2959	num_entries = event_data->NumEntries;
2960	topo_change.num_entries = num_entries;
2961	topo_change.start_port_num = event_data->StartPortNum;
2962	topo_change.num_ports = event_data->NumPorts;
2963	topo_change.switch_status = event_data->SwitchStatus;
2964	event_port_change = event_data->PortEntry;
2965	topo_change.port_details = NULL;
2966
2967	if (!num_entries)
2968		goto out;
2969	port_change = malloc(sizeof(struct _map_port_change) * num_entries,
2970	    M_MPR, M_NOWAIT|M_ZERO);
2971	topo_change.port_details = port_change;
2972	if (!port_change)
2973		goto out;
2974	for (i = 0; i < num_entries; i++, event_port_change++, port_change++) {
2975		port_change->dev_handle = le16toh(event_port_change->
2976		    AttachedDevHandle);
2977		port_change->reason = event_port_change->PortStatus;
2978	}
2979	_mapping_update_pcie_missing_count(sc, &topo_change);
2980	_mapping_get_pcie_dev_info(sc, &topo_change);
2981	_mapping_clear_removed_entries(sc);
2982	_mapping_add_new_pcie_device(sc, &topo_change);
2983
2984out:
2985	free(topo_change.port_details, M_MPR);
2986	_mapping_flush_dpm_pages(sc);
2987	if (sc->pending_map_events)
2988		sc->pending_map_events--;
2989}
2990
2991/**
2992 * mpr_mapping_ir_config_change_event - handle IR config change list events
2993 * @sc: per adapter object
2994 * @event_data: event data payload
2995 *
2996 * Returns nothing.
2997 */
2998void
2999mpr_mapping_ir_config_change_event(struct mpr_softc *sc,
3000    Mpi2EventDataIrConfigChangeList_t *event_data)
3001{
3002	Mpi2EventIrConfigElement_t *element;
3003	int i;
3004	u64 *wwid_table;
3005	u32 map_idx, flags;
3006	struct dev_mapping_table *mt_entry;
3007	u16 element_flags;
3008
3009	wwid_table = malloc(sizeof(u64) * event_data->NumElements, M_MPR,
3010	    M_NOWAIT | M_ZERO);
3011	if (!wwid_table)
3012		goto out;
3013	element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
3014	flags = le32toh(event_data->Flags);
3015
3016	/*
3017	 * For volume changes, get the WWID for the volume and put it in a
3018	 * table to be used in the processing of the IR change event.
3019	 */
3020	for (i = 0; i < event_data->NumElements; i++, element++) {
3021		element_flags = le16toh(element->ElementFlags);
3022		if ((element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_ADDED) &&
3023		    (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_REMOVED) &&
3024		    (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE)
3025		    && (element->ReasonCode !=
3026			MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED))
3027			continue;
3028		if ((element_flags &
3029		    MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK) ==
3030		    MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT) {
3031			mpr_config_get_volume_wwid(sc,
3032			    le16toh(element->VolDevHandle), &wwid_table[i]);
3033		}
3034	}
3035
3036	/*
3037	 * Check the ReasonCode for each element in the IR event and Add/Remove
3038	 * Volumes or Physical Disks of Volumes to/from the mapping table. Use
3039	 * the WWIDs gotten above in wwid_table.
3040	 */
3041	if (flags == MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
3042		goto out;
3043	else {
3044		element = (Mpi2EventIrConfigElement_t *)&event_data->
3045		    ConfigElement[0];
3046		for (i = 0; i < event_data->NumElements; i++, element++) {
3047			if (element->ReasonCode ==
3048			    MPI2_EVENT_IR_CHANGE_RC_ADDED ||
3049			    element->ReasonCode ==
3050			    MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) {
3051				map_idx = _mapping_get_ir_mt_idx_from_wwid
3052				    (sc, wwid_table[i]);
3053				if (map_idx != MPR_MAPTABLE_BAD_IDX) {
3054					/*
3055					 * The volume is already in the mapping
3056					 * table. Just update it's info.
3057					 */
3058					mt_entry = &sc->mapping_table[map_idx];
3059					mt_entry->id = map_idx;
3060					mt_entry->dev_handle = le16toh
3061					    (element->VolDevHandle);
3062					mt_entry->device_info =
3063					    MPR_DEV_RESERVED | MPR_MAP_IN_USE;
3064					_mapping_update_ir_missing_cnt(sc,
3065					    map_idx, element, wwid_table[i]);
3066					continue;
3067				}
3068
3069				/*
3070				 * Volume is not in mapping table yet. Find a
3071				 * free entry in the mapping table at the
3072				 * volume mapping locations. If no entries are
3073				 * available, this is an error because it means
3074				 * there are more volumes than can be mapped
3075				 * and that should never happen for volumes.
3076				 */
3077				map_idx = _mapping_get_free_ir_mt_idx(sc);
3078				if (map_idx == MPR_MAPTABLE_BAD_IDX)
3079				{
3080					mpr_dprint(sc, MPR_ERROR | MPR_MAPPING,
3081					    "%s: failed to add the volume with "
3082					    "handle 0x%04x because there is no "
3083					    "free space available in the "
3084					    "mapping table\n", __func__,
3085					    le16toh(element->VolDevHandle));
3086					continue;
3087				}
3088				mt_entry = &sc->mapping_table[map_idx];
3089				mt_entry->physical_id = wwid_table[i];
3090				mt_entry->id = map_idx;
3091				mt_entry->dev_handle = le16toh(element->
3092				    VolDevHandle);
3093				mt_entry->device_info = MPR_DEV_RESERVED |
3094				    MPR_MAP_IN_USE;
3095				_mapping_update_ir_missing_cnt(sc, map_idx,
3096				    element, wwid_table[i]);
3097			} else if (element->ReasonCode ==
3098			    MPI2_EVENT_IR_CHANGE_RC_REMOVED) {
3099				map_idx = _mapping_get_ir_mt_idx_from_wwid(sc,
3100				    wwid_table[i]);
3101				if (map_idx == MPR_MAPTABLE_BAD_IDX) {
3102					mpr_dprint(sc, MPR_MAPPING,"%s: Failed "
3103					    "to remove a volume because it has "
3104					    "already been removed.\n",
3105					    __func__);
3106					continue;
3107				}
3108				_mapping_update_ir_missing_cnt(sc, map_idx,
3109				    element, wwid_table[i]);
3110			} else if (element->ReasonCode ==
3111			    MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED) {
3112				map_idx = _mapping_get_mt_idx_from_handle(sc,
3113				    le16toh(element->VolDevHandle));
3114				if (map_idx == MPR_MAPTABLE_BAD_IDX) {
3115					mpr_dprint(sc, MPR_MAPPING,"%s: Failed "
3116					    "to remove volume with handle "
3117					    "0x%04x because it has already "
3118					    "been removed.\n", __func__,
3119					    le16toh(element->VolDevHandle));
3120					continue;
3121				}
3122				mt_entry = &sc->mapping_table[map_idx];
3123				_mapping_update_ir_missing_cnt(sc, map_idx,
3124				    element, mt_entry->physical_id);
3125			}
3126		}
3127	}
3128
3129out:
3130	_mapping_flush_dpm_pages(sc);
3131	free(wwid_table, M_MPR);
3132	if (sc->pending_map_events)
3133		sc->pending_map_events--;
3134}
3135