mps_mapping.c revision 331722
1/*-
2 * Copyright (c) 2011-2015 LSI Corp.
3 * Copyright (c) 2013-2015 Avago Technologies
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: stable/11/sys/dev/mps/mps_mapping.c 331722 2018-03-29 02:50:57Z eadler $");
32
33/* TODO Move headers to mpsvar */
34#include <sys/types.h>
35#include <sys/param.h>
36#include <sys/lock.h>
37#include <sys/mutex.h>
38#include <sys/systm.h>
39#include <sys/kernel.h>
40#include <sys/malloc.h>
41#include <sys/kthread.h>
42#include <sys/taskqueue.h>
43#include <sys/bus.h>
44#include <sys/endian.h>
45#include <sys/sysctl.h>
46#include <sys/sbuf.h>
47#include <sys/eventhandler.h>
48#include <sys/uio.h>
49#include <machine/bus.h>
50#include <machine/resource.h>
51#include <dev/mps/mpi/mpi2_type.h>
52#include <dev/mps/mpi/mpi2.h>
53#include <dev/mps/mpi/mpi2_ioc.h>
54#include <dev/mps/mpi/mpi2_sas.h>
55#include <dev/mps/mpi/mpi2_cnfg.h>
56#include <dev/mps/mpi/mpi2_init.h>
57#include <dev/mps/mpi/mpi2_tool.h>
58#include <dev/mps/mps_ioctl.h>
59#include <dev/mps/mpsvar.h>
60#include <dev/mps/mps_mapping.h>
61
62/**
63 * _mapping_clear_map_entry - Clear a particular mapping entry.
64 * @map_entry: map table entry
65 *
66 * Returns nothing.
67 */
68static inline void
69_mapping_clear_map_entry(struct dev_mapping_table *map_entry)
70{
71	map_entry->physical_id = 0;
72	map_entry->device_info = 0;
73	map_entry->phy_bits = 0;
74	map_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
75	map_entry->dev_handle = 0;
76	map_entry->id = -1;
77	map_entry->missing_count = 0;
78	map_entry->init_complete = 0;
79	map_entry->TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR;
80}
81
82/**
83 * _mapping_clear_enc_entry - Clear a particular enclosure table entry.
84 * @enc_entry: enclosure table entry
85 *
86 * Returns nothing.
87 */
88static inline void
89_mapping_clear_enc_entry(struct enc_mapping_table *enc_entry)
90{
91	enc_entry->enclosure_id = 0;
92	enc_entry->start_index = MPS_MAPTABLE_BAD_IDX;
93	enc_entry->phy_bits = 0;
94	enc_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
95	enc_entry->enc_handle = 0;
96	enc_entry->num_slots = 0;
97	enc_entry->start_slot = 0;
98	enc_entry->missing_count = 0;
99	enc_entry->removal_flag = 0;
100	enc_entry->skip_search = 0;
101	enc_entry->init_complete = 0;
102}
103
104/**
105 * _mapping_commit_enc_entry - write a particular enc entry in DPM page0.
106 * @sc: per adapter object
107 * @enc_entry: enclosure table entry
108 *
109 * Returns 0 for success, non-zero for failure.
110 */
111static int
112_mapping_commit_enc_entry(struct mps_softc *sc,
113    struct enc_mapping_table *et_entry)
114{
115	Mpi2DriverMap0Entry_t *dpm_entry;
116	struct dev_mapping_table *mt_entry;
117	Mpi2ConfigReply_t mpi_reply;
118	Mpi2DriverMappingPage0_t config_page;
119
120	if (!sc->is_dpm_enable)
121		return 0;
122
123	memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
124	memcpy(&config_page.Header, (u8 *) sc->dpm_pg0,
125	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
126	dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
127	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
128	dpm_entry += et_entry->dpm_entry_num;
129	dpm_entry->PhysicalIdentifier.Low =
130	    ( 0xFFFFFFFF & et_entry->enclosure_id);
131	dpm_entry->PhysicalIdentifier.High =
132	    ( et_entry->enclosure_id >> 32);
133	mt_entry = &sc->mapping_table[et_entry->start_index];
134	dpm_entry->DeviceIndex = htole16(mt_entry->id);
135	dpm_entry->MappingInformation = et_entry->num_slots;
136	dpm_entry->MappingInformation <<= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
137	dpm_entry->MappingInformation |= et_entry->missing_count;
138	dpm_entry->MappingInformation = htole16(dpm_entry->MappingInformation);
139	dpm_entry->PhysicalBitsMapping = htole32(et_entry->phy_bits);
140	dpm_entry->Reserved1 = 0;
141
142	mps_dprint(sc, MPS_MAPPING, "%s: Writing DPM entry %d for enclosure.\n",
143	    __func__, et_entry->dpm_entry_num);
144	memcpy(&config_page.Entry, (u8 *)dpm_entry,
145	    sizeof(Mpi2DriverMap0Entry_t));
146	if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
147	    et_entry->dpm_entry_num)) {
148		mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Write of DPM "
149		    "entry %d for enclosure failed.\n", __func__,
150		    et_entry->dpm_entry_num);
151		dpm_entry->MappingInformation = le16toh(dpm_entry->
152		    MappingInformation);
153		dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
154		dpm_entry->PhysicalBitsMapping =
155		    le32toh(dpm_entry->PhysicalBitsMapping);
156		return -1;
157	}
158	dpm_entry->MappingInformation = le16toh(dpm_entry->
159	    MappingInformation);
160	dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
161	dpm_entry->PhysicalBitsMapping =
162	    le32toh(dpm_entry->PhysicalBitsMapping);
163	return 0;
164}
165
166/**
167 * _mapping_commit_map_entry - write a particular map table entry in DPM page0.
168 * @sc: per adapter object
169 * @mt_entry: mapping table entry
170 *
171 * Returns 0 for success, non-zero for failure.
172 */
173
174static int
175_mapping_commit_map_entry(struct mps_softc *sc,
176    struct dev_mapping_table *mt_entry)
177{
178	Mpi2DriverMap0Entry_t *dpm_entry;
179	Mpi2ConfigReply_t mpi_reply;
180	Mpi2DriverMappingPage0_t config_page;
181
182	if (!sc->is_dpm_enable)
183		return 0;
184
185	/*
186	 * It's possible that this Map Entry points to a BAD DPM index. This
187	 * can happen if the Map Entry is a for a missing device and the DPM
188	 * entry that was being used by this device is now being used by some
189	 * new device. So, check for a BAD DPM index and just return if so.
190	 */
191	if (mt_entry->dpm_entry_num == MPS_DPM_BAD_IDX) {
192		mps_dprint(sc, MPS_MAPPING, "%s: DPM entry location for target "
193		    "%d is invalid. DPM will not be written.\n", __func__,
194		    mt_entry->id);
195		return 0;
196	}
197
198	memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
199	memcpy(&config_page.Header, (u8 *)sc->dpm_pg0,
200	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
201	dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *) sc->dpm_pg0 +
202	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
203	dpm_entry = dpm_entry + mt_entry->dpm_entry_num;
204	dpm_entry->PhysicalIdentifier.Low = (0xFFFFFFFF &
205	    mt_entry->physical_id);
206	dpm_entry->PhysicalIdentifier.High = (mt_entry->physical_id >> 32);
207	dpm_entry->DeviceIndex = htole16(mt_entry->id);
208	dpm_entry->MappingInformation = htole16(mt_entry->missing_count);
209	dpm_entry->PhysicalBitsMapping = 0;
210	dpm_entry->Reserved1 = 0;
211	memcpy(&config_page.Entry, (u8 *)dpm_entry,
212	    sizeof(Mpi2DriverMap0Entry_t));
213
214	mps_dprint(sc, MPS_MAPPING, "%s: Writing DPM entry %d for target %d.\n",
215	    __func__, mt_entry->dpm_entry_num, mt_entry->id);
216	if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
217	    mt_entry->dpm_entry_num)) {
218		mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Write of DPM "
219		    "entry %d for target %d failed.\n", __func__,
220		    mt_entry->dpm_entry_num, mt_entry->id);
221		dpm_entry->MappingInformation = le16toh(dpm_entry->
222		    MappingInformation);
223		dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
224		return -1;
225	}
226
227	dpm_entry->MappingInformation = le16toh(dpm_entry->MappingInformation);
228	dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
229	return 0;
230}
231
232/**
233 * _mapping_get_ir_maprange - get start and end index for IR map range.
234 * @sc: per adapter object
235 * @start_idx: place holder for start index
236 * @end_idx: place holder for end index
237 *
238 * The IR volumes can be mapped either at start or end of the mapping table
239 * this function gets the detail of where IR volume mapping starts and ends
240 * in the device mapping table
241 *
242 * Returns nothing.
243 */
244static void
245_mapping_get_ir_maprange(struct mps_softc *sc, u32 *start_idx, u32 *end_idx)
246{
247	u16 volume_mapping_flags;
248	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
249
250	volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
251	    MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
252	if (volume_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
253		*start_idx = 0;
254		if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
255			*start_idx = 1;
256	} else
257		*start_idx = sc->max_devices - sc->max_volumes;
258	*end_idx = *start_idx + sc->max_volumes - 1;
259}
260
261/**
262 * _mapping_get_enc_idx_from_id - get enclosure index from enclosure ID
263 * @sc: per adapter object
264 * @enc_id: enclosure logical identifier
265 *
266 * Returns the index of enclosure entry on success or bad index.
267 */
268static u8
269_mapping_get_enc_idx_from_id(struct mps_softc *sc, u64 enc_id,
270    u64 phy_bits)
271{
272	struct enc_mapping_table *et_entry;
273	u8 enc_idx = 0;
274
275	for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
276		et_entry = &sc->enclosure_table[enc_idx];
277		if ((et_entry->enclosure_id == le64toh(enc_id)) &&
278		    (!et_entry->phy_bits || (et_entry->phy_bits &
279		    le32toh(phy_bits))))
280			return enc_idx;
281	}
282	return MPS_ENCTABLE_BAD_IDX;
283}
284
285/**
286 * _mapping_get_enc_idx_from_handle - get enclosure index from handle
287 * @sc: per adapter object
288 * @enc_id: enclosure handle
289 *
290 * Returns the index of enclosure entry on success or bad index.
291 */
292static u8
293_mapping_get_enc_idx_from_handle(struct mps_softc *sc, u16 handle)
294{
295	struct enc_mapping_table *et_entry;
296	u8 enc_idx = 0;
297
298	for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
299		et_entry = &sc->enclosure_table[enc_idx];
300		if (et_entry->missing_count)
301			continue;
302		if (et_entry->enc_handle == handle)
303			return enc_idx;
304	}
305	return MPS_ENCTABLE_BAD_IDX;
306}
307
308/**
309 * _mapping_get_high_missing_et_idx - get missing enclosure index
310 * @sc: per adapter object
311 *
312 * Search through the enclosure table and identifies the enclosure entry
313 * with high missing count and returns it's index
314 *
315 * Returns the index of enclosure entry on success or bad index.
316 */
317static u8
318_mapping_get_high_missing_et_idx(struct mps_softc *sc)
319{
320	struct enc_mapping_table *et_entry;
321	u8 high_missing_count = 0;
322	u8 enc_idx, high_idx = MPS_ENCTABLE_BAD_IDX;
323
324	for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
325		et_entry = &sc->enclosure_table[enc_idx];
326		if ((et_entry->missing_count > high_missing_count) &&
327		    !et_entry->skip_search) {
328			high_missing_count = et_entry->missing_count;
329			high_idx = enc_idx;
330		}
331	}
332	return high_idx;
333}
334
335/**
336 * _mapping_get_high_missing_mt_idx - get missing map table index
337 * @sc: per adapter object
338 *
339 * Search through the map table and identifies the device entry
340 * with high missing count and returns it's index
341 *
342 * Returns the index of map table entry on success or bad index.
343 */
344static u32
345_mapping_get_high_missing_mt_idx(struct mps_softc *sc)
346{
347	u32 map_idx, high_idx = MPS_MAPTABLE_BAD_IDX;
348	u8 high_missing_count = 0;
349	u32 start_idx, end_idx, start_idx_ir, end_idx_ir;
350	struct dev_mapping_table *mt_entry;
351	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
352
353	start_idx = 0;
354	start_idx_ir = 0;
355	end_idx_ir = 0;
356	end_idx = sc->max_devices;
357	if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
358		start_idx = 1;
359	if (sc->ir_firmware) {
360		_mapping_get_ir_maprange(sc, &start_idx_ir, &end_idx_ir);
361		if (start_idx == start_idx_ir)
362			start_idx = end_idx_ir + 1;
363		else
364			end_idx = start_idx_ir;
365	}
366	mt_entry = &sc->mapping_table[start_idx];
367	for (map_idx = start_idx; map_idx < end_idx; map_idx++, mt_entry++) {
368		if (mt_entry->missing_count > high_missing_count) {
369			high_missing_count =  mt_entry->missing_count;
370			high_idx = map_idx;
371		}
372	}
373	return high_idx;
374}
375
376/**
377 * _mapping_get_ir_mt_idx_from_wwid - get map table index from volume WWID
378 * @sc: per adapter object
379 * @wwid: world wide unique ID of the volume
380 *
381 * Returns the index of map table entry on success or bad index.
382 */
383static u32
384_mapping_get_ir_mt_idx_from_wwid(struct mps_softc *sc, u64 wwid)
385{
386	u32 start_idx, end_idx, map_idx;
387	struct dev_mapping_table *mt_entry;
388
389	_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
390	mt_entry = &sc->mapping_table[start_idx];
391	for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
392		if (mt_entry->physical_id == wwid)
393			return map_idx;
394
395	return MPS_MAPTABLE_BAD_IDX;
396}
397
398/**
399 * _mapping_get_mt_idx_from_id - get map table index from a device ID
400 * @sc: per adapter object
401 * @dev_id: device identifer (SAS Address)
402 *
403 * Returns the index of map table entry on success or bad index.
404 */
405static u32
406_mapping_get_mt_idx_from_id(struct mps_softc *sc, u64 dev_id)
407{
408	u32 map_idx;
409	struct dev_mapping_table *mt_entry;
410
411	for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
412		mt_entry = &sc->mapping_table[map_idx];
413		if (mt_entry->physical_id == dev_id)
414			return map_idx;
415	}
416	return MPS_MAPTABLE_BAD_IDX;
417}
418
419/**
420 * _mapping_get_ir_mt_idx_from_handle - get map table index from volume handle
421 * @sc: per adapter object
422 * @wwid: volume device handle
423 *
424 * Returns the index of map table entry on success or bad index.
425 */
426static u32
427_mapping_get_ir_mt_idx_from_handle(struct mps_softc *sc, u16 volHandle)
428{
429	u32 start_idx, end_idx, map_idx;
430	struct dev_mapping_table *mt_entry;
431
432	_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
433	mt_entry = &sc->mapping_table[start_idx];
434	for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
435		if (mt_entry->dev_handle == volHandle)
436			return map_idx;
437
438	return MPS_MAPTABLE_BAD_IDX;
439}
440
441/**
442 * _mapping_get_mt_idx_from_handle - get map table index from handle
443 * @sc: per adapter object
444 * @dev_id: device handle
445 *
446 * Returns the index of map table entry on success or bad index.
447 */
448static u32
449_mapping_get_mt_idx_from_handle(struct mps_softc *sc, u16 handle)
450{
451	u32 map_idx;
452	struct dev_mapping_table *mt_entry;
453
454	for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
455		mt_entry = &sc->mapping_table[map_idx];
456		if (mt_entry->dev_handle == handle)
457			return map_idx;
458	}
459	return MPS_MAPTABLE_BAD_IDX;
460}
461
462/**
463 * _mapping_get_free_ir_mt_idx - get first free index for a volume
464 * @sc: per adapter object
465 *
466 * Search through mapping table for free index for a volume and if no free
467 * index then looks for a volume with high mapping index
468 *
469 * Returns the index of map table entry on success or bad index.
470 */
471static u32
472_mapping_get_free_ir_mt_idx(struct mps_softc *sc)
473{
474	u8 high_missing_count = 0;
475	u32 start_idx, end_idx, map_idx;
476	u32 high_idx = MPS_MAPTABLE_BAD_IDX;
477	struct dev_mapping_table *mt_entry;
478
479	/*
480	 * The IN_USE flag should be clear if the entry is available to use.
481	 * This flag is cleared on initialization and and when a volume is
482	 * deleted. All other times this flag should be set. If, for some
483	 * reason, a free entry cannot be found, look for the entry with the
484	 * highest missing count just in case there is one.
485	 */
486	_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
487
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 & MPS_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 == MPS_MAPTABLE_BAD_IDX) {
500		mps_dprint(sc, MPS_ERROR | MPS_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 mps_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 & (MPS_MAP_IN_USE |
530		    MPS_DEV_RESERVED)))
531			return map_idx;
532
533	return MPS_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 mps_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 MPS_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 mps_softc *sc)
574{
575	u16 entry_num;
576	Mpi2DriverMap0Entry_t *dpm_entry;
577	u16 current_entry = MPS_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 == MPS_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 != MPS_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 != MPS_MAPTABLE_BAD_IDX) {
631			mt_entry = &sc->mapping_table[map_idx];
632			mt_entry->dpm_entry_num = MPS_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 mps_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 < MPS_MAX_MISSING_COUNT)
674			mt_entry->missing_count++;
675
676		mt_entry->device_info &= ~MPS_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 == MPS_DPM_BAD_IDX) {
690		if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED)
691		{
692			mps_dprint(sc, MPS_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 == MPS_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 != MPS_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			mps_dprint(sc, MPS_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 != MPS_DPM_BAD_IDX) && update_dpm) {
728		mps_dprint(sc, MPS_MAPPING, "%s: Update DPM entry for volume "
729		    "with target ID %d.\n", __func__, mt_entry->id);
730
731		mt_entry->dpm_entry_num = dpm_idx;
732		dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
733		    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
734		dpm_entry += dpm_idx;
735		dpm_entry->PhysicalIdentifier.Low =
736		    (0xFFFFFFFF & mt_entry->physical_id);
737		dpm_entry->PhysicalIdentifier.High =
738		    (mt_entry->physical_id >> 32);
739		dpm_entry->DeviceIndex = map_idx;
740		dpm_entry->MappingInformation = mt_entry->missing_count;
741		dpm_entry->PhysicalBitsMapping = 0;
742		dpm_entry->Reserved1 = 0;
743		sc->dpm_flush_entry[dpm_idx] = 1;
744		sc->dpm_entry_used[dpm_idx] = 1;
745	} else if (dpm_idx == MPS_DPM_BAD_IDX) {
746		mps_dprint(sc, MPS_INFO | MPS_MAPPING, "%s: No space to add an "
747		    "entry in the DPM table for volume with target ID %d.\n",
748		    __func__, mt_entry->id);
749	}
750}
751
752/**
753 * _mapping_add_to_removal_table - add DPM index to the removal table
754 * @sc: per adapter object
755 * @dpm_idx: Index of DPM entry to remove
756 *
757 * Adds a DPM entry number to the removal table.
758 *
759 * Returns nothing.
760 */
761static void
762_mapping_add_to_removal_table(struct mps_softc *sc, u16 dpm_idx)
763{
764	struct map_removal_table *remove_entry;
765	u32 i;
766
767	/*
768	 * This is only used to remove entries from the DPM in the controller.
769	 * If DPM is not enabled, just return.
770	 */
771	if (!sc->is_dpm_enable)
772		return;
773
774	/*
775	 * Find the first available removal_table entry and add the new entry
776	 * there.
777	 */
778	remove_entry = sc->removal_table;
779
780	for (i = 0; i < sc->max_devices; i++, remove_entry++) {
781		if (remove_entry->dpm_entry_num != MPS_DPM_BAD_IDX)
782			continue;
783
784		mps_dprint(sc, MPS_MAPPING, "%s: Adding DPM entry %d to table "
785		    "for removal.\n", __func__, dpm_idx);
786		remove_entry->dpm_entry_num = dpm_idx;
787		break;
788	}
789
790}
791
792/**
793 * _mapping_update_missing_count - Update missing count for a device
794 * @sc: per adapter object
795 * @topo_change: Topology change event entry
796 *
797 * Increment the missing count in the mapping table for a device that is not
798 * responding. If Persitent Mapping is used, increment the DPM entry as well.
799 * Currently, this function only increments the missing count if the device
800 * goes missing, so after initialization has completed. This means that the
801 * missing count can only go from 0 to 1 here. The missing count is incremented
802 * during initialization as well, so that's where a target's missing count can
803 * go past 1.
804 *
805 * Returns nothing.
806 */
807static void
808_mapping_update_missing_count(struct mps_softc *sc,
809    struct _map_topology_change *topo_change)
810{
811	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
812	u8 entry;
813	struct _map_phy_change *phy_change;
814	u32 map_idx;
815	struct dev_mapping_table *mt_entry;
816	Mpi2DriverMap0Entry_t *dpm_entry;
817
818	for (entry = 0; entry < topo_change->num_entries; entry++) {
819		phy_change = &topo_change->phy_details[entry];
820		if (!phy_change->dev_handle || (phy_change->reason !=
821		    MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING))
822			continue;
823		map_idx = _mapping_get_mt_idx_from_handle(sc, phy_change->
824		    dev_handle);
825		phy_change->is_processed = 1;
826		if (map_idx == MPS_MAPTABLE_BAD_IDX) {
827			mps_dprint(sc, MPS_INFO | MPS_MAPPING, "%s: device is "
828			    "already removed from mapping table\n", __func__);
829			continue;
830		}
831		mt_entry = &sc->mapping_table[map_idx];
832		if (mt_entry->missing_count < MPS_MAX_MISSING_COUNT)
833			mt_entry->missing_count++;
834
835		/*
836		 * When using Enc/Slot mapping, when a device is removed, it's
837		 * mapping table information should be cleared. Otherwise, the
838		 * target ID will be incorrect if this same device is re-added
839		 * to a different slot.
840		 */
841		if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
842		    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
843			_mapping_clear_map_entry(mt_entry);
844		}
845
846		/*
847		 * When using device mapping, update the missing count in the
848		 * DPM entry, but only if the missing count has changed.
849		 */
850		if (((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
851		    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) &&
852		    sc->is_dpm_enable &&
853		    mt_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
854			dpm_entry =
855			    (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
856			    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
857			dpm_entry += mt_entry->dpm_entry_num;
858			if (dpm_entry->MappingInformation !=
859			    mt_entry->missing_count) {
860				dpm_entry->MappingInformation =
861				    mt_entry->missing_count;
862				sc->dpm_flush_entry[mt_entry->dpm_entry_num] =
863				    1;
864			}
865		}
866	}
867}
868
869/**
870 * _mapping_find_enc_map_space -find map table entries for enclosure
871 * @sc: per adapter object
872 * @et_entry: enclosure entry
873 *
874 * Search through the mapping table defragment it and provide contiguous
875 * space in map table for a particular enclosure entry
876 *
877 * Returns start index in map table or bad index.
878 */
879static u32
880_mapping_find_enc_map_space(struct mps_softc *sc,
881    struct enc_mapping_table *et_entry)
882{
883	u16 vol_mapping_flags;
884	u32 skip_count, end_of_table, map_idx, enc_idx;
885	u16 num_found;
886	u32 start_idx = MPS_MAPTABLE_BAD_IDX;
887	struct dev_mapping_table *mt_entry;
888	struct enc_mapping_table *enc_entry;
889	unsigned char done_flag = 0, found_space;
890	u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
891
892	skip_count = sc->num_rsvd_entries;
893	num_found = 0;
894
895	vol_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
896	    MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
897
898	/*
899	 * The end of the mapping table depends on where volumes are kept, if
900	 * IR is enabled.
901	 */
902	if (!sc->ir_firmware)
903		end_of_table = sc->max_devices;
904	else if (vol_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING)
905		end_of_table = sc->max_devices;
906	else
907		end_of_table = sc->max_devices - sc->max_volumes;
908
909	/*
910	 * The skip_count is the number of entries that are reserved at the
911	 * beginning of the mapping table. But, it does not include the number
912	 * of Physical IDs that are reserved for direct attached devices. Look
913	 * through the mapping table after these reserved entries to see if
914	 * the devices for this enclosure are already mapped. The PHY bit check
915	 * is used to make sure that at least one PHY bit is common between the
916	 * enclosure and the device that is already mapped.
917	 */
918	mps_dprint(sc, MPS_MAPPING, "%s: Looking for space in the mapping "
919	    "table for added enclosure.\n", __func__);
920	for (map_idx = (max_num_phy_ids + skip_count);
921	    map_idx < end_of_table; map_idx++) {
922		mt_entry = &sc->mapping_table[map_idx];
923		if ((et_entry->enclosure_id == mt_entry->physical_id) &&
924		    (!mt_entry->phy_bits || (mt_entry->phy_bits &
925		    et_entry->phy_bits))) {
926			num_found += 1;
927			if (num_found == et_entry->num_slots) {
928				start_idx = (map_idx - num_found) + 1;
929				mps_dprint(sc, MPS_MAPPING, "%s: Found space "
930				    "in the mapping for enclosure at map index "
931				    "%d.\n", __func__, start_idx);
932				return start_idx;
933			}
934		} else
935			num_found = 0;
936	}
937
938	/*
939	 * If the enclosure's devices are not mapped already, look for
940	 * contiguous entries in the mapping table that are not reserved. If
941	 * enough entries are found, return the starting index for that space.
942	 */
943	num_found = 0;
944	for (map_idx = (max_num_phy_ids + skip_count);
945	    map_idx < end_of_table; map_idx++) {
946		mt_entry = &sc->mapping_table[map_idx];
947		if (!(mt_entry->device_info & MPS_DEV_RESERVED)) {
948			num_found += 1;
949			if (num_found == et_entry->num_slots) {
950				start_idx = (map_idx - num_found) + 1;
951				mps_dprint(sc, MPS_MAPPING, "%s: Found space "
952				    "in the mapping for enclosure at map index "
953				    "%d.\n", __func__, start_idx);
954				return start_idx;
955			}
956		} else
957			num_found = 0;
958	}
959
960	/*
961	 * If here, it means that not enough space in the mapping table was
962	 * found to support this enclosure, so go through the enclosure table to
963	 * see if any enclosure entries have a missing count. If so, get the
964	 * enclosure with the highest missing count and check it to see if there
965	 * is enough space for the new enclosure.
966	 */
967	while (!done_flag) {
968		enc_idx = _mapping_get_high_missing_et_idx(sc);
969		if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
970			mps_dprint(sc, MPS_MAPPING, "%s: Not enough space was "
971			    "found in the mapping for the added enclosure.\n",
972			    __func__);
973			return MPS_MAPTABLE_BAD_IDX;
974		}
975
976		/*
977		 * Found a missing enclosure. Set the skip_search flag so this
978		 * enclosure is not checked again for a high missing count if
979		 * the loop continues. This way, all missing enclosures can
980		 * have their space added together to find enough space in the
981		 * mapping table for the added enclosure. The space must be
982		 * contiguous.
983		 */
984		mps_dprint(sc, MPS_MAPPING, "%s: Space from a missing "
985		    "enclosure was found.\n", __func__);
986		enc_entry = &sc->enclosure_table[enc_idx];
987		enc_entry->skip_search = 1;
988
989		/*
990		 * Unmark all of the missing enclosure's device's reserved
991		 * space. These will be remarked as reserved if this missing
992		 * enclosure's space is not used.
993		 */
994		mps_dprint(sc, MPS_MAPPING, "%s: Clear the reserved flag for "
995		    "all of the map entries for the enclosure.\n", __func__);
996		mt_entry = &sc->mapping_table[enc_entry->start_index];
997		for (map_idx = enc_entry->start_index; map_idx <
998		    (enc_entry->start_index + enc_entry->num_slots); map_idx++,
999		    mt_entry++)
1000			mt_entry->device_info &= ~MPS_DEV_RESERVED;
1001
1002		/*
1003		 * Now that space has been unreserved, check again to see if
1004		 * enough space is available for the new enclosure.
1005		 */
1006		mps_dprint(sc, MPS_MAPPING, "%s: Check if new mapping space is "
1007		    "enough for the new enclosure.\n", __func__);
1008		found_space = 0;
1009		num_found = 0;
1010		for (map_idx = (max_num_phy_ids + skip_count);
1011		    map_idx < end_of_table; map_idx++) {
1012			mt_entry = &sc->mapping_table[map_idx];
1013			if (!(mt_entry->device_info & MPS_DEV_RESERVED)) {
1014				num_found += 1;
1015				if (num_found == et_entry->num_slots) {
1016					start_idx = (map_idx - num_found) + 1;
1017					found_space = 1;
1018					break;
1019				}
1020			} else
1021				num_found = 0;
1022		}
1023		if (!found_space)
1024			continue;
1025
1026		/*
1027		 * If enough space was found, all of the missing enclosures that
1028		 * will be used for the new enclosure must be added to the
1029		 * removal table. Then all mappings for the enclosure's devices
1030		 * and for the enclosure itself need to be cleared. There may be
1031		 * more than one enclosure to add to the removal table and
1032		 * clear.
1033		 */
1034		mps_dprint(sc, MPS_MAPPING, "%s: Found space in the mapping "
1035		    "for enclosure at map index %d.\n", __func__, start_idx);
1036		for (map_idx = start_idx; map_idx < (start_idx + num_found);
1037		    map_idx++) {
1038			enc_entry = sc->enclosure_table;
1039			for (enc_idx = 0; enc_idx < sc->num_enc_table_entries;
1040			    enc_idx++, enc_entry++) {
1041				if (map_idx < enc_entry->start_index ||
1042				    map_idx > (enc_entry->start_index +
1043				    enc_entry->num_slots))
1044					continue;
1045				if (!enc_entry->removal_flag) {
1046					mps_dprint(sc, MPS_MAPPING, "%s: "
1047					    "Enclosure %d will be removed from "
1048					    "the mapping table.\n", __func__,
1049					    enc_idx);
1050					enc_entry->removal_flag = 1;
1051					_mapping_add_to_removal_table(sc,
1052					    enc_entry->dpm_entry_num);
1053				}
1054				mt_entry = &sc->mapping_table[map_idx];
1055				_mapping_clear_map_entry(mt_entry);
1056				if (map_idx == (enc_entry->start_index +
1057				    enc_entry->num_slots - 1))
1058					_mapping_clear_enc_entry(et_entry);
1059			}
1060		}
1061
1062		/*
1063		 * During the search for space for this enclosure, some entries
1064		 * in the mapping table may have been unreserved. Go back and
1065		 * change all of these to reserved again. Only the enclosures
1066		 * with the removal_flag set should be left as unreserved. The
1067		 * skip_search flag needs to be cleared as well so that the
1068		 * enclosure's space will be looked at the next time space is
1069		 * needed.
1070		 */
1071		enc_entry = sc->enclosure_table;
1072		for (enc_idx = 0; enc_idx < sc->num_enc_table_entries;
1073		    enc_idx++, enc_entry++) {
1074			if (!enc_entry->removal_flag) {
1075				mps_dprint(sc, MPS_MAPPING, "%s: Reset the "
1076				    "reserved flag for all of the map entries "
1077				    "for enclosure %d.\n", __func__, enc_idx);
1078				mt_entry = &sc->mapping_table[enc_entry->
1079				    start_index];
1080				for (map_idx = enc_entry->start_index; map_idx <
1081				    (enc_entry->start_index +
1082				    enc_entry->num_slots); map_idx++,
1083				    mt_entry++)
1084					mt_entry->device_info |=
1085					    MPS_DEV_RESERVED;
1086				et_entry->skip_search = 0;
1087			}
1088		}
1089		done_flag = 1;
1090	}
1091	return start_idx;
1092}
1093
1094/**
1095 * _mapping_get_dev_info -get information about newly added devices
1096 * @sc: per adapter object
1097 * @topo_change: Topology change event entry
1098 *
1099 * Search through the topology change event list and issues sas device pg0
1100 * requests for the newly added device and reserved entries in tables
1101 *
1102 * Returns nothing
1103 */
1104static void
1105_mapping_get_dev_info(struct mps_softc *sc,
1106    struct _map_topology_change *topo_change)
1107{
1108	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1109	Mpi2ConfigReply_t mpi_reply;
1110	Mpi2SasDevicePage0_t sas_device_pg0;
1111	u8 entry, enc_idx, phy_idx;
1112	u32 map_idx, index, device_info;
1113	struct _map_phy_change *phy_change, *tmp_phy_change;
1114	uint64_t sas_address;
1115	struct enc_mapping_table *et_entry;
1116	struct dev_mapping_table *mt_entry;
1117	u8 add_code = MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED;
1118	int rc = 1;
1119
1120	for (entry = 0; entry < topo_change->num_entries; entry++) {
1121		phy_change = &topo_change->phy_details[entry];
1122		if (phy_change->is_processed || !phy_change->dev_handle ||
1123		    phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED)
1124			continue;
1125
1126		if (mps_config_get_sas_device_pg0(sc, &mpi_reply,
1127		    &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
1128		    phy_change->dev_handle)) {
1129			phy_change->is_processed = 1;
1130			continue;
1131		}
1132
1133		/*
1134		 * Always get SATA Identify information because this is used
1135		 * to determine if Start/Stop Unit should be sent to the drive
1136		 * when the system is shutdown.
1137		 */
1138		device_info = le32toh(sas_device_pg0.DeviceInfo);
1139		sas_address = le32toh(sas_device_pg0.SASAddress.High);
1140		sas_address = (sas_address << 32) |
1141		    le32toh(sas_device_pg0.SASAddress.Low);
1142		if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) &&
1143		    (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) {
1144			rc = mpssas_get_sas_address_for_sata_disk(sc,
1145			    &sas_address, phy_change->dev_handle, device_info,
1146			    &phy_change->is_SATA_SSD);
1147			if (rc) {
1148				mps_dprint(sc, MPS_ERROR, "%s: failed to get "
1149				    "disk type (SSD or HDD) and SAS Address "
1150				    "for SATA device with handle 0x%04x\n",
1151				    __func__, phy_change->dev_handle);
1152			} else {
1153				mps_dprint(sc, MPS_INFO, "SAS Address for SATA "
1154				    "device = %jx\n", sas_address);
1155			}
1156		}
1157
1158		phy_change->physical_id = sas_address;
1159		phy_change->slot = le16toh(sas_device_pg0.Slot);
1160		phy_change->device_info = device_info;
1161
1162		/*
1163		 * When using Enc/Slot mapping, if this device is an enclosure
1164		 * make sure that all of its slots can fit into the mapping
1165		 * table.
1166		 */
1167		if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1168		    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1169			/*
1170			 * The enclosure should already be in the enclosure
1171			 * table due to the Enclosure Add event. If not, just
1172			 * continue, nothing can be done.
1173			 */
1174			enc_idx = _mapping_get_enc_idx_from_handle(sc,
1175			    topo_change->enc_handle);
1176			if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
1177				phy_change->is_processed = 1;
1178				mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: "
1179				    "failed to add the device with handle "
1180				    "0x%04x because the enclosure is not in "
1181				    "the mapping table\n", __func__,
1182				    phy_change->dev_handle);
1183				continue;
1184			}
1185			if (!((phy_change->device_info &
1186			    MPI2_SAS_DEVICE_INFO_END_DEVICE) &&
1187			    (phy_change->device_info &
1188			    (MPI2_SAS_DEVICE_INFO_SSP_TARGET |
1189			    MPI2_SAS_DEVICE_INFO_STP_TARGET |
1190			    MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))) {
1191				phy_change->is_processed = 1;
1192				continue;
1193			}
1194			et_entry = &sc->enclosure_table[enc_idx];
1195
1196			/*
1197			 * If the enclosure already has a start_index, it's been
1198			 * mapped, so go to the next Topo change.
1199			 */
1200			if (et_entry->start_index != MPS_MAPTABLE_BAD_IDX)
1201				continue;
1202
1203			/*
1204			 * If the Expander Handle is 0, the devices are direct
1205			 * attached. In that case, the start_index must be just
1206			 * after the reserved entries. Otherwise, find space in
1207			 * the mapping table for the enclosure's devices.
1208			 */
1209			if (!topo_change->exp_handle) {
1210				map_idx	= sc->num_rsvd_entries;
1211				et_entry->start_index = map_idx;
1212			} else {
1213				map_idx = _mapping_find_enc_map_space(sc,
1214				    et_entry);
1215				et_entry->start_index = map_idx;
1216
1217				/*
1218				 * If space cannot be found to hold all of the
1219				 * enclosure's devices in the mapping table,
1220				 * there's no need to continue checking the
1221				 * other devices in this event. Set all of the
1222				 * phy_details for this event (if the change is
1223				 * for an add) as already processed because none
1224				 * of these devices can be added to the mapping
1225				 * table.
1226				 */
1227				if (et_entry->start_index ==
1228				    MPS_MAPTABLE_BAD_IDX) {
1229					mps_dprint(sc, MPS_ERROR | MPS_MAPPING,
1230					    "%s: failed to add the enclosure "
1231					    "with ID 0x%016jx because there is "
1232					    "no free space available in the "
1233					    "mapping table for all of the "
1234					    "enclosure's devices.\n", __func__,
1235					    (uintmax_t)et_entry->enclosure_id);
1236					phy_change->is_processed = 1;
1237					for (phy_idx = 0; phy_idx <
1238					    topo_change->num_entries;
1239					    phy_idx++) {
1240						tmp_phy_change =
1241						    &topo_change->phy_details
1242						    [phy_idx];
1243						if (tmp_phy_change->reason ==
1244						    add_code)
1245							tmp_phy_change->
1246							    is_processed = 1;
1247					}
1248					break;
1249				}
1250			}
1251
1252			/*
1253			 * Found space in the mapping table for this enclosure.
1254			 * Initialize each mapping table entry for the
1255			 * enclosure.
1256			 */
1257			mps_dprint(sc, MPS_MAPPING, "%s: Initialize %d map "
1258			    "entries for the enclosure, starting at map index "
1259			    " %d.\n", __func__, et_entry->num_slots, map_idx);
1260			mt_entry = &sc->mapping_table[map_idx];
1261			for (index = map_idx; index < (et_entry->num_slots
1262			    + map_idx); index++, mt_entry++) {
1263				mt_entry->device_info = MPS_DEV_RESERVED;
1264				mt_entry->physical_id = et_entry->enclosure_id;
1265				mt_entry->phy_bits = et_entry->phy_bits;
1266				mt_entry->missing_count = 0;
1267			}
1268		}
1269	}
1270}
1271
1272/**
1273 * _mapping_set_mid_to_eid -set map table data from enclosure table
1274 * @sc: per adapter object
1275 * @et_entry: enclosure entry
1276 *
1277 * Returns nothing
1278 */
1279static inline void
1280_mapping_set_mid_to_eid(struct mps_softc *sc,
1281    struct enc_mapping_table *et_entry)
1282{
1283	struct dev_mapping_table *mt_entry;
1284	u16 slots = et_entry->num_slots, map_idx;
1285	u32 start_idx = et_entry->start_index;
1286
1287	if (start_idx != MPS_MAPTABLE_BAD_IDX) {
1288		mt_entry = &sc->mapping_table[start_idx];
1289		for (map_idx = 0; map_idx < slots; map_idx++, mt_entry++)
1290			mt_entry->physical_id = et_entry->enclosure_id;
1291	}
1292}
1293
1294/**
1295 * _mapping_clear_removed_entries - mark the entries to be cleared
1296 * @sc: per adapter object
1297 *
1298 * Search through the removal table and mark the entries which needs to be
1299 * flushed to DPM and also updates the map table and enclosure table by
1300 * clearing the corresponding entries.
1301 *
1302 * Returns nothing
1303 */
1304static void
1305_mapping_clear_removed_entries(struct mps_softc *sc)
1306{
1307	u32 remove_idx;
1308	struct map_removal_table *remove_entry;
1309	Mpi2DriverMap0Entry_t *dpm_entry;
1310	u8 done_flag = 0, num_entries, m, i;
1311	struct enc_mapping_table *et_entry, *from, *to;
1312	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1313
1314	if (sc->is_dpm_enable) {
1315		remove_entry = sc->removal_table;
1316		for (remove_idx = 0; remove_idx < sc->max_devices;
1317		    remove_idx++, remove_entry++) {
1318			if (remove_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
1319				dpm_entry = (Mpi2DriverMap0Entry_t *)
1320				    ((u8 *) sc->dpm_pg0 +
1321				    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1322				dpm_entry += remove_entry->dpm_entry_num;
1323				dpm_entry->PhysicalIdentifier.Low = 0;
1324				dpm_entry->PhysicalIdentifier.High = 0;
1325				dpm_entry->DeviceIndex = 0;
1326				dpm_entry->MappingInformation = 0;
1327				dpm_entry->PhysicalBitsMapping = 0;
1328				sc->dpm_flush_entry[remove_entry->
1329				    dpm_entry_num] = 1;
1330				sc->dpm_entry_used[remove_entry->dpm_entry_num]
1331				    = 0;
1332				remove_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
1333			}
1334		}
1335	}
1336
1337	/*
1338	 * When using Enc/Slot mapping, if a new enclosure was added and old
1339	 * enclosure space was needed, the enclosure table may now have gaps
1340	 * that need to be closed. All enclosure mappings need to be contiguous
1341	 * so that space can be reused correctly if available.
1342	 */
1343	if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1344	    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1345		num_entries = sc->num_enc_table_entries;
1346		while (!done_flag) {
1347			done_flag = 1;
1348			et_entry = sc->enclosure_table;
1349			for (i = 0; i < num_entries; i++, et_entry++) {
1350				if (!et_entry->enc_handle && et_entry->
1351				    init_complete) {
1352					done_flag = 0;
1353					if (i != (num_entries - 1)) {
1354						from = &sc->enclosure_table
1355						    [i+1];
1356						to = &sc->enclosure_table[i];
1357						for (m = i; m < (num_entries -
1358						    1); m++, from++, to++) {
1359							_mapping_set_mid_to_eid
1360							    (sc, to);
1361							*to = *from;
1362						}
1363						_mapping_clear_enc_entry(to);
1364						sc->num_enc_table_entries--;
1365						num_entries =
1366						    sc->num_enc_table_entries;
1367					} else {
1368						_mapping_clear_enc_entry
1369						    (et_entry);
1370						sc->num_enc_table_entries--;
1371						num_entries =
1372						    sc->num_enc_table_entries;
1373					}
1374				}
1375			}
1376		}
1377	}
1378}
1379
1380/**
1381 * _mapping_add_new_device -Add the new device into mapping table
1382 * @sc: per adapter object
1383 * @topo_change: Topology change event entry
1384 *
1385 * Search through the topology change event list and update map table,
1386 * enclosure table and DPM pages for the newly added devices.
1387 *
1388 * Returns nothing
1389 */
1390static void
1391_mapping_add_new_device(struct mps_softc *sc,
1392    struct _map_topology_change *topo_change)
1393{
1394	u8 enc_idx, missing_cnt, is_removed = 0;
1395	u16 dpm_idx;
1396	u32 search_idx, map_idx;
1397	u32 entry;
1398	struct dev_mapping_table *mt_entry;
1399	struct enc_mapping_table *et_entry;
1400	struct _map_phy_change *phy_change;
1401	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1402	Mpi2DriverMap0Entry_t *dpm_entry;
1403	uint64_t temp64_var;
1404	u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
1405	u8 hdr_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER);
1406	u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
1407
1408	for (entry = 0; entry < topo_change->num_entries; entry++) {
1409		phy_change = &topo_change->phy_details[entry];
1410		if (phy_change->is_processed)
1411			continue;
1412		if (phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED ||
1413		    !phy_change->dev_handle) {
1414			phy_change->is_processed = 1;
1415			continue;
1416		}
1417		if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1418		    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1419			enc_idx = _mapping_get_enc_idx_from_handle
1420			    (sc, topo_change->enc_handle);
1421			if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
1422				phy_change->is_processed = 1;
1423				mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: "
1424				    "failed to add the device with handle "
1425				    "0x%04x because the enclosure is not in "
1426				    "the mapping table\n", __func__,
1427				    phy_change->dev_handle);
1428				continue;
1429			}
1430
1431			/*
1432			 * If the enclosure's start_index is BAD here, it means
1433			 * that there is no room in the mapping table to cover
1434			 * all of the devices that could be in the enclosure.
1435			 * There's no reason to process any of the devices for
1436			 * this enclosure since they can't be mapped.
1437			 */
1438			et_entry = &sc->enclosure_table[enc_idx];
1439			if (et_entry->start_index == MPS_MAPTABLE_BAD_IDX) {
1440				phy_change->is_processed = 1;
1441				mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: "
1442				    "failed to add the device with handle "
1443				    "0x%04x because there is no free space "
1444				    "available in the mapping table\n",
1445				    __func__, phy_change->dev_handle);
1446				continue;
1447			}
1448
1449			/*
1450			 * Add this device to the mapping table at the correct
1451			 * offset where space was found to map the enclosure.
1452			 * Then setup the DPM entry information if being used.
1453			 */
1454			map_idx = et_entry->start_index + phy_change->slot -
1455			    et_entry->start_slot;
1456			mt_entry = &sc->mapping_table[map_idx];
1457			mt_entry->physical_id = phy_change->physical_id;
1458			mt_entry->id = map_idx;
1459			mt_entry->dev_handle = phy_change->dev_handle;
1460			mt_entry->missing_count = 0;
1461			mt_entry->dpm_entry_num = et_entry->dpm_entry_num;
1462			mt_entry->device_info = phy_change->device_info |
1463			    (MPS_DEV_RESERVED | MPS_MAP_IN_USE);
1464			if (sc->is_dpm_enable) {
1465				dpm_idx = et_entry->dpm_entry_num;
1466				if (dpm_idx == MPS_DPM_BAD_IDX)
1467					dpm_idx = _mapping_get_dpm_idx_from_id
1468					    (sc, et_entry->enclosure_id,
1469					     et_entry->phy_bits);
1470				if (dpm_idx == MPS_DPM_BAD_IDX) {
1471					dpm_idx = _mapping_get_free_dpm_idx(sc);
1472					if (dpm_idx != MPS_DPM_BAD_IDX) {
1473						dpm_entry =
1474						    (Mpi2DriverMap0Entry_t *)
1475						    ((u8 *) sc->dpm_pg0 +
1476						     hdr_sz);
1477						dpm_entry += dpm_idx;
1478						dpm_entry->
1479						    PhysicalIdentifier.Low =
1480						    (0xFFFFFFFF &
1481						    et_entry->enclosure_id);
1482						dpm_entry->
1483						    PhysicalIdentifier.High =
1484						    (et_entry->enclosure_id
1485						     >> 32);
1486						dpm_entry->DeviceIndex =
1487						    (U16)et_entry->start_index;
1488						dpm_entry->MappingInformation =
1489						    et_entry->num_slots;
1490						dpm_entry->MappingInformation
1491						    <<= map_shift;
1492						dpm_entry->PhysicalBitsMapping
1493						    = et_entry->phy_bits;
1494						et_entry->dpm_entry_num =
1495						    dpm_idx;
1496						sc->dpm_entry_used[dpm_idx] = 1;
1497						sc->dpm_flush_entry[dpm_idx] =
1498						    1;
1499						phy_change->is_processed = 1;
1500					} else {
1501						phy_change->is_processed = 1;
1502						mps_dprint(sc, MPS_ERROR |
1503						    MPS_MAPPING, "%s: failed "
1504						    "to add the device with "
1505						    "handle 0x%04x to "
1506						    "persistent table because "
1507						    "there is no free space "
1508						    "available\n", __func__,
1509						    phy_change->dev_handle);
1510					}
1511				} else {
1512					et_entry->dpm_entry_num = dpm_idx;
1513					mt_entry->dpm_entry_num = dpm_idx;
1514				}
1515			}
1516			et_entry->init_complete = 1;
1517		} else if ((ioc_pg8_flags &
1518		    MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1519		    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
1520
1521			/*
1522			 * Get the mapping table index for this device. If it's
1523			 * not in the mapping table yet, find a free entry if
1524			 * one is available. If there are no free entries, look
1525			 * for the entry that has the highest missing count. If
1526			 * none of that works to find an entry in the mapping
1527			 * table, there is a problem. Log a message and just
1528			 * continue on.
1529			 */
1530			map_idx = _mapping_get_mt_idx_from_id
1531			    (sc, phy_change->physical_id);
1532			if (map_idx == MPS_MAPTABLE_BAD_IDX) {
1533				search_idx = sc->num_rsvd_entries;
1534				if (topo_change->exp_handle)
1535					search_idx += max_num_phy_ids;
1536				map_idx = _mapping_get_free_mt_idx(sc,
1537				    search_idx);
1538			}
1539
1540			/*
1541			 * If an entry will be used that has a missing device,
1542			 * clear its entry from  the DPM in the controller.
1543			 */
1544			if (map_idx == MPS_MAPTABLE_BAD_IDX) {
1545				map_idx = _mapping_get_high_missing_mt_idx(sc);
1546				if (map_idx != MPS_MAPTABLE_BAD_IDX) {
1547					mt_entry = &sc->mapping_table[map_idx];
1548					_mapping_add_to_removal_table(sc,
1549					    mt_entry->dpm_entry_num);
1550					is_removed = 1;
1551					mt_entry->init_complete = 0;
1552				}
1553			}
1554			if (map_idx != MPS_MAPTABLE_BAD_IDX) {
1555				mt_entry = &sc->mapping_table[map_idx];
1556				mt_entry->physical_id = phy_change->physical_id;
1557				mt_entry->id = map_idx;
1558				mt_entry->dev_handle = phy_change->dev_handle;
1559				mt_entry->missing_count = 0;
1560				mt_entry->device_info = phy_change->device_info
1561				    | (MPS_DEV_RESERVED | MPS_MAP_IN_USE);
1562			} else {
1563				phy_change->is_processed = 1;
1564				mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: "
1565				    "failed to add the device with handle "
1566				    "0x%04x because there is no free space "
1567				    "available in the mapping table\n",
1568				    __func__, phy_change->dev_handle);
1569				continue;
1570			}
1571			if (sc->is_dpm_enable) {
1572				if (mt_entry->dpm_entry_num !=
1573				    MPS_DPM_BAD_IDX) {
1574					dpm_idx = mt_entry->dpm_entry_num;
1575					dpm_entry = (Mpi2DriverMap0Entry_t *)
1576					    ((u8 *)sc->dpm_pg0 + hdr_sz);
1577					dpm_entry += dpm_idx;
1578					missing_cnt = dpm_entry->
1579					    MappingInformation &
1580					    MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
1581					temp64_var = dpm_entry->
1582					    PhysicalIdentifier.High;
1583					temp64_var = (temp64_var << 32) |
1584					   dpm_entry->PhysicalIdentifier.Low;
1585
1586					/*
1587					 * If the Mapping Table's info is not
1588					 * the same as the DPM entry, clear the
1589					 * init_complete flag so that it's
1590					 * updated.
1591					 */
1592					if ((mt_entry->physical_id ==
1593					    temp64_var) && !missing_cnt)
1594						mt_entry->init_complete = 1;
1595					else
1596						mt_entry->init_complete = 0;
1597				} else {
1598					dpm_idx = _mapping_get_free_dpm_idx(sc);
1599					mt_entry->init_complete = 0;
1600				}
1601				if (dpm_idx != MPS_DPM_BAD_IDX &&
1602				    !mt_entry->init_complete) {
1603					mt_entry->dpm_entry_num = dpm_idx;
1604					dpm_entry = (Mpi2DriverMap0Entry_t *)
1605					    ((u8 *)sc->dpm_pg0 + hdr_sz);
1606					dpm_entry += dpm_idx;
1607					dpm_entry->PhysicalIdentifier.Low =
1608					    (0xFFFFFFFF &
1609					    mt_entry->physical_id);
1610					dpm_entry->PhysicalIdentifier.High =
1611					    (mt_entry->physical_id >> 32);
1612					dpm_entry->DeviceIndex = (U16) map_idx;
1613					dpm_entry->MappingInformation = 0;
1614					dpm_entry->PhysicalBitsMapping = 0;
1615					sc->dpm_entry_used[dpm_idx] = 1;
1616					sc->dpm_flush_entry[dpm_idx] = 1;
1617					phy_change->is_processed = 1;
1618				} else if (dpm_idx == MPS_DPM_BAD_IDX) {
1619					phy_change->is_processed = 1;
1620					mps_dprint(sc, MPS_ERROR | MPS_MAPPING,
1621					    "%s: failed to add the device with "
1622					    "handle 0x%04x to persistent table "
1623					    "because there is no free space "
1624					    "available\n", __func__,
1625					    phy_change->dev_handle);
1626				}
1627			}
1628			mt_entry->init_complete = 1;
1629		}
1630
1631		phy_change->is_processed = 1;
1632	}
1633	if (is_removed)
1634		_mapping_clear_removed_entries(sc);
1635}
1636
1637/**
1638 * _mapping_flush_dpm_pages -Flush the DPM pages to NVRAM
1639 * @sc: per adapter object
1640 *
1641 * Returns nothing
1642 */
1643static void
1644_mapping_flush_dpm_pages(struct mps_softc *sc)
1645{
1646	Mpi2DriverMap0Entry_t *dpm_entry;
1647	Mpi2ConfigReply_t mpi_reply;
1648	Mpi2DriverMappingPage0_t config_page;
1649	u16 entry_num;
1650
1651	for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) {
1652		if (!sc->dpm_flush_entry[entry_num])
1653			continue;
1654		memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
1655		memcpy(&config_page.Header, (u8 *)sc->dpm_pg0,
1656		    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1657		dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
1658		    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1659		dpm_entry += entry_num;
1660		dpm_entry->MappingInformation = htole16(dpm_entry->
1661		    MappingInformation);
1662		dpm_entry->DeviceIndex = htole16(dpm_entry->DeviceIndex);
1663		dpm_entry->PhysicalBitsMapping = htole32(dpm_entry->
1664		    PhysicalBitsMapping);
1665		memcpy(&config_page.Entry, (u8 *)dpm_entry,
1666		    sizeof(Mpi2DriverMap0Entry_t));
1667		/* TODO-How to handle failed writes? */
1668		mps_dprint(sc, MPS_MAPPING, "%s: Flushing DPM entry %d.\n",
1669		    __func__, entry_num);
1670		if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
1671		    entry_num)) {
1672			mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Flush of "
1673			    "DPM entry %d for device failed\n", __func__,
1674			    entry_num);
1675		} else
1676			sc->dpm_flush_entry[entry_num] = 0;
1677		dpm_entry->MappingInformation = le16toh(dpm_entry->
1678		    MappingInformation);
1679		dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
1680		dpm_entry->PhysicalBitsMapping = le32toh(dpm_entry->
1681		    PhysicalBitsMapping);
1682	}
1683}
1684
1685/**
1686 * _mapping_allocate_memory- allocates the memory required for mapping tables
1687 * @sc: per adapter object
1688 *
1689 * Allocates the memory for all the tables required for host mapping
1690 *
1691 * Return 0 on success or non-zero on failure.
1692 */
1693int
1694mps_mapping_allocate_memory(struct mps_softc *sc)
1695{
1696	uint32_t dpm_pg0_sz;
1697
1698	sc->mapping_table = malloc((sizeof(struct dev_mapping_table) *
1699	    sc->max_devices), M_MPT2, M_ZERO|M_NOWAIT);
1700	if (!sc->mapping_table)
1701		goto free_resources;
1702
1703	sc->removal_table = malloc((sizeof(struct map_removal_table) *
1704	    sc->max_devices), M_MPT2, M_ZERO|M_NOWAIT);
1705	if (!sc->removal_table)
1706		goto free_resources;
1707
1708	sc->enclosure_table = malloc((sizeof(struct enc_mapping_table) *
1709	    sc->max_enclosures), M_MPT2, M_ZERO|M_NOWAIT);
1710	if (!sc->enclosure_table)
1711		goto free_resources;
1712
1713	sc->dpm_entry_used = malloc((sizeof(u8) * sc->max_dpm_entries),
1714	    M_MPT2, M_ZERO|M_NOWAIT);
1715	if (!sc->dpm_entry_used)
1716		goto free_resources;
1717
1718	sc->dpm_flush_entry = malloc((sizeof(u8) * sc->max_dpm_entries),
1719	    M_MPT2, M_ZERO|M_NOWAIT);
1720	if (!sc->dpm_flush_entry)
1721		goto free_resources;
1722
1723	dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) +
1724	    (sc->max_dpm_entries * sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY));
1725
1726	sc->dpm_pg0 = malloc(dpm_pg0_sz, M_MPT2, M_ZERO|M_NOWAIT);
1727	if (!sc->dpm_pg0) {
1728		printf("%s: memory alloc failed for dpm page; disabling dpm\n",
1729		    __func__);
1730		sc->is_dpm_enable = 0;
1731	}
1732
1733	return 0;
1734
1735free_resources:
1736	free(sc->mapping_table, M_MPT2);
1737	free(sc->removal_table, M_MPT2);
1738	free(sc->enclosure_table, M_MPT2);
1739	free(sc->dpm_entry_used, M_MPT2);
1740	free(sc->dpm_flush_entry, M_MPT2);
1741	free(sc->dpm_pg0, M_MPT2);
1742	printf("%s: device initialization failed due to failure in mapping "
1743	    "table memory allocation\n", __func__);
1744	return -1;
1745}
1746
1747/**
1748 * mps_mapping_free_memory- frees the memory allocated for mapping tables
1749 * @sc: per adapter object
1750 *
1751 * Returns nothing.
1752 */
1753void
1754mps_mapping_free_memory(struct mps_softc *sc)
1755{
1756	free(sc->mapping_table, M_MPT2);
1757	free(sc->removal_table, M_MPT2);
1758	free(sc->enclosure_table, M_MPT2);
1759	free(sc->dpm_entry_used, M_MPT2);
1760	free(sc->dpm_flush_entry, M_MPT2);
1761	free(sc->dpm_pg0, M_MPT2);
1762}
1763
1764static void
1765_mapping_process_dpm_pg0(struct mps_softc *sc)
1766{
1767	u8 missing_cnt, enc_idx;
1768	u16 slot_id, entry_num, num_slots;
1769	u32 map_idx, dev_idx, start_idx, end_idx;
1770	struct dev_mapping_table *mt_entry;
1771	Mpi2DriverMap0Entry_t *dpm_entry;
1772	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1773	u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
1774	struct enc_mapping_table *et_entry;
1775	u64 physical_id;
1776	u32 phy_bits = 0;
1777
1778	/*
1779	 * start_idx and end_idx are only used for IR.
1780	 */
1781	if (sc->ir_firmware)
1782		_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
1783
1784	/*
1785	 * Look through all of the DPM entries that were read from the
1786	 * controller and copy them over to the driver's internal table if they
1787	 * have a non-zero ID. At this point, any ID with a value of 0 would be
1788	 * invalid, so don't copy it.
1789	 */
1790	mps_dprint(sc, MPS_MAPPING, "%s: Start copy of %d DPM entries into the "
1791	    "mapping table.\n", __func__, sc->max_dpm_entries);
1792	dpm_entry = (Mpi2DriverMap0Entry_t *) ((uint8_t *) sc->dpm_pg0 +
1793	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1794	for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++,
1795	    dpm_entry++) {
1796		physical_id = dpm_entry->PhysicalIdentifier.High;
1797		physical_id = (physical_id << 32) |
1798		    dpm_entry->PhysicalIdentifier.Low;
1799		if (!physical_id) {
1800			sc->dpm_entry_used[entry_num] = 0;
1801			continue;
1802		}
1803		sc->dpm_entry_used[entry_num] = 1;
1804		dpm_entry->MappingInformation = le16toh(dpm_entry->
1805		    MappingInformation);
1806		missing_cnt = dpm_entry->MappingInformation &
1807		    MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
1808		dev_idx = le16toh(dpm_entry->DeviceIndex);
1809		phy_bits = le32toh(dpm_entry->PhysicalBitsMapping);
1810
1811		/*
1812		 * Volumes are at special locations in the mapping table so
1813		 * account for that. Volume mapping table entries do not depend
1814		 * on the type of mapping, so continue the loop after adding
1815		 * volumes to the mapping table.
1816		 */
1817		if (sc->ir_firmware && (dev_idx >= start_idx) &&
1818		    (dev_idx <= end_idx)) {
1819			mt_entry = &sc->mapping_table[dev_idx];
1820			mt_entry->physical_id =
1821			    dpm_entry->PhysicalIdentifier.High;
1822			mt_entry->physical_id = (mt_entry->physical_id << 32) |
1823			    dpm_entry->PhysicalIdentifier.Low;
1824			mt_entry->id = dev_idx;
1825			mt_entry->missing_count = missing_cnt;
1826			mt_entry->dpm_entry_num = entry_num;
1827			mt_entry->device_info = MPS_DEV_RESERVED;
1828			continue;
1829		}
1830		if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1831		    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1832
1833			/*
1834			 * The dev_idx for an enclosure is the start index. If
1835			 * the start index is within the controller's default
1836			 * enclosure area, set the number of slots for this
1837			 * enclosure to the max allowed. Otherwise, it should be
1838			 * a normal enclosure and the number of slots is in the
1839			 * DPM entry's Mapping Information.
1840			 */
1841			if (dev_idx < (sc->num_rsvd_entries +
1842			    max_num_phy_ids)) {
1843				slot_id = 0;
1844				if (ioc_pg8_flags &
1845				    MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1)
1846					slot_id = 1;
1847				num_slots = max_num_phy_ids;
1848			} else {
1849				slot_id = 0;
1850				num_slots = dpm_entry->MappingInformation &
1851				    MPI2_DRVMAP0_MAPINFO_SLOT_MASK;
1852				num_slots >>= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
1853			}
1854			enc_idx = sc->num_enc_table_entries;
1855			if (enc_idx >= sc->max_enclosures) {
1856				mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: "
1857				    "Number of enclosure entries in DPM exceed "
1858				    "the max allowed of %d.\n", __func__,
1859				    sc->max_enclosures);
1860				break;
1861			}
1862			sc->num_enc_table_entries++;
1863			et_entry = &sc->enclosure_table[enc_idx];
1864			physical_id = dpm_entry->PhysicalIdentifier.High;
1865			et_entry->enclosure_id = (physical_id << 32) |
1866			    dpm_entry->PhysicalIdentifier.Low;
1867			et_entry->start_index = dev_idx;
1868			et_entry->dpm_entry_num = entry_num;
1869			et_entry->num_slots = num_slots;
1870			et_entry->start_slot = slot_id;
1871			et_entry->missing_count = missing_cnt;
1872			et_entry->phy_bits = phy_bits;
1873
1874			/*
1875			 * Initialize all entries for this enclosure in the
1876			 * mapping table and mark them as reserved. The actual
1877			 * devices have not been processed yet but when they are
1878			 * they will use these entries. If an entry is found
1879			 * that already has a valid DPM index, the mapping table
1880			 * is corrupt. This can happen if the mapping type is
1881			 * changed without clearing all of the DPM entries in
1882			 * the controller.
1883			 */
1884			mt_entry = &sc->mapping_table[dev_idx];
1885			for (map_idx = dev_idx; map_idx < (dev_idx + num_slots);
1886			    map_idx++, mt_entry++) {
1887				if (mt_entry->dpm_entry_num !=
1888				    MPS_DPM_BAD_IDX) {
1889					mps_dprint(sc, MPS_ERROR | MPS_MAPPING,
1890					    "%s: Conflict in mapping table for "
1891					    " enclosure %d\n", __func__,
1892					    enc_idx);
1893					break;
1894				}
1895				physical_id =
1896				    dpm_entry->PhysicalIdentifier.High;
1897				mt_entry->physical_id = (physical_id << 32) |
1898				    dpm_entry->PhysicalIdentifier.Low;
1899				mt_entry->phy_bits = phy_bits;
1900				mt_entry->id = dev_idx;
1901				mt_entry->dpm_entry_num = entry_num;
1902				mt_entry->missing_count = missing_cnt;
1903				mt_entry->device_info = MPS_DEV_RESERVED;
1904			}
1905		} else if ((ioc_pg8_flags &
1906		    MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1907		    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
1908
1909			/*
1910			 * Device mapping, so simply copy the DPM entries to the
1911			 * mapping table, but check for a corrupt mapping table
1912			 * (as described above in Enc/Slot mapping).
1913			 */
1914			map_idx = dev_idx;
1915			mt_entry = &sc->mapping_table[map_idx];
1916			if (mt_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
1917				mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: "
1918				    "Conflict in mapping table for device %d\n",
1919				    __func__, map_idx);
1920				break;
1921			}
1922			physical_id = dpm_entry->PhysicalIdentifier.High;
1923			mt_entry->physical_id = (physical_id << 32) |
1924			    dpm_entry->PhysicalIdentifier.Low;
1925			mt_entry->phy_bits = phy_bits;
1926			mt_entry->id = dev_idx;
1927			mt_entry->missing_count = missing_cnt;
1928			mt_entry->dpm_entry_num = entry_num;
1929			mt_entry->device_info = MPS_DEV_RESERVED;
1930		}
1931	} /*close the loop for DPM table */
1932}
1933
1934/*
1935 * mps_mapping_check_devices - start of the day check for device availabilty
1936 * @sc: per adapter object
1937 *
1938 * Returns nothing.
1939 */
1940void
1941mps_mapping_check_devices(void *data)
1942{
1943	u32 i;
1944	struct dev_mapping_table *mt_entry;
1945	struct mps_softc *sc = (struct mps_softc *)data;
1946	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1947	struct enc_mapping_table *et_entry;
1948	u32 start_idx = 0, end_idx = 0;
1949	u8 stop_device_checks = 0;
1950
1951	MPS_FUNCTRACE(sc);
1952
1953	/*
1954	 * Clear this flag so that this function is never called again except
1955	 * within this function if the check needs to be done again. The
1956	 * purpose is to check for missing devices that are currently in the
1957	 * mapping table so do this only at driver init after discovery.
1958	 */
1959	sc->track_mapping_events = 0;
1960
1961	/*
1962	 * callout synchronization
1963	 * This is used to prevent race conditions for the callout.
1964	 */
1965	mps_dprint(sc, MPS_MAPPING, "%s: Start check for missing devices.\n",
1966	    __func__);
1967	mtx_assert(&sc->mps_mtx, MA_OWNED);
1968	if ((callout_pending(&sc->device_check_callout)) ||
1969	    (!callout_active(&sc->device_check_callout))) {
1970		mps_dprint(sc, MPS_MAPPING, "%s: Device Check Callout is "
1971		    "already pending or not active.\n", __func__);
1972		return;
1973	}
1974	callout_deactivate(&sc->device_check_callout);
1975
1976	/*
1977	 * Use callout to check if any devices in the mapping table have been
1978	 * processed yet. If ALL devices are marked as not init_complete, no
1979	 * devices have been processed and mapped. Until devices are mapped
1980	 * there's no reason to mark them as missing. Continue resetting this
1981	 * callout until devices have been mapped.
1982	 */
1983	if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1984	    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1985		et_entry = sc->enclosure_table;
1986		for (i = 0; i < sc->num_enc_table_entries; i++, et_entry++) {
1987			if (et_entry->init_complete) {
1988				stop_device_checks = 1;
1989				break;
1990			}
1991		}
1992	} else if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1993	    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
1994		mt_entry = sc->mapping_table;
1995		for (i = 0; i < sc->max_devices; i++, mt_entry++) {
1996			if (mt_entry->init_complete) {
1997				stop_device_checks = 1;
1998				break;
1999			}
2000		}
2001	}
2002
2003	/*
2004	 * Setup another callout check after a delay. Keep doing this until
2005	 * devices are mapped.
2006	 */
2007	if (!stop_device_checks) {
2008		mps_dprint(sc, MPS_MAPPING, "%s: No devices have been mapped. "
2009		    "Reset callout to check again after a %d second delay.\n",
2010		    __func__, MPS_MISSING_CHECK_DELAY);
2011		callout_reset(&sc->device_check_callout,
2012		    MPS_MISSING_CHECK_DELAY * hz, mps_mapping_check_devices,
2013		    sc);
2014		return;
2015	}
2016	mps_dprint(sc, MPS_MAPPING, "%s: Device check complete.\n", __func__);
2017
2018	/*
2019	 * Depending on the mapping type, check if devices have been processed
2020	 * and update their missing counts if not processed.
2021	 */
2022	if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
2023	    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
2024		et_entry = sc->enclosure_table;
2025		for (i = 0; i < sc->num_enc_table_entries; i++, et_entry++) {
2026			if (!et_entry->init_complete) {
2027				if (et_entry->missing_count <
2028				    MPS_MAX_MISSING_COUNT) {
2029					mps_dprint(sc, MPS_MAPPING, "%s: "
2030					    "Enclosure %d is missing from the "
2031					    "topology. Update its missing "
2032					    "count.\n", __func__, i);
2033					et_entry->missing_count++;
2034					if (et_entry->dpm_entry_num !=
2035					    MPS_DPM_BAD_IDX) {
2036						_mapping_commit_enc_entry(sc,
2037						    et_entry);
2038					}
2039				}
2040				et_entry->init_complete = 1;
2041			}
2042		}
2043		if (!sc->ir_firmware)
2044			return;
2045		_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
2046		mt_entry = &sc->mapping_table[start_idx];
2047	} else if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
2048	    MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
2049		start_idx = 0;
2050		end_idx = sc->max_devices - 1;
2051		mt_entry = sc->mapping_table;
2052	}
2053
2054	/*
2055	 * The start and end indices have been set above according to the
2056	 * mapping type. Go through these mappings and update any entries that
2057	 * do not have the init_complete flag set, which means they are missing.
2058	 */
2059	if (end_idx == 0)
2060		return;
2061	for (i = start_idx; i < (end_idx + 1); i++, mt_entry++) {
2062		if (mt_entry->device_info & MPS_DEV_RESERVED
2063		    && !mt_entry->physical_id)
2064			mt_entry->init_complete = 1;
2065		else if (mt_entry->device_info & MPS_DEV_RESERVED) {
2066			if (!mt_entry->init_complete) {
2067				mps_dprint(sc, MPS_MAPPING, "%s: Device in "
2068				    "mapping table at index %d is missing from "
2069				    "topology. Update its missing count.\n",
2070				    __func__, i);
2071				if (mt_entry->missing_count <
2072				    MPS_MAX_MISSING_COUNT) {
2073					mt_entry->missing_count++;
2074					if (mt_entry->dpm_entry_num !=
2075					    MPS_DPM_BAD_IDX) {
2076						_mapping_commit_map_entry(sc,
2077						    mt_entry);
2078					}
2079				}
2080				mt_entry->init_complete = 1;
2081			}
2082		}
2083	}
2084}
2085
2086/**
2087 * mps_mapping_initialize - initialize mapping tables
2088 * @sc: per adapter object
2089 *
2090 * Read controller persitant mapping tables into internal data area.
2091 *
2092 * Return 0 for success or non-zero for failure.
2093 */
2094int
2095mps_mapping_initialize(struct mps_softc *sc)
2096{
2097	uint16_t volume_mapping_flags, dpm_pg0_sz;
2098	uint32_t i;
2099	Mpi2ConfigReply_t mpi_reply;
2100	int error;
2101	uint8_t retry_count;
2102	uint16_t ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
2103
2104	/* The additional 1 accounts for the virtual enclosure
2105	 * created for the controller
2106	 */
2107	sc->max_enclosures = sc->facts->MaxEnclosures + 1;
2108	sc->max_expanders = sc->facts->MaxSasExpanders;
2109	sc->max_volumes = sc->facts->MaxVolumes;
2110	sc->max_devices = sc->facts->MaxTargets + sc->max_volumes;
2111	sc->pending_map_events = 0;
2112	sc->num_enc_table_entries = 0;
2113	sc->num_rsvd_entries = 0;
2114	sc->max_dpm_entries = sc->ioc_pg8.MaxPersistentEntries;
2115	sc->is_dpm_enable = (sc->max_dpm_entries) ? 1 : 0;
2116	sc->track_mapping_events = 0;
2117
2118
2119	mps_dprint(sc, MPS_MAPPING, "%s: Mapping table has a max of %d entries "
2120	    "and DPM has a max of %d entries.\n", __func__, sc->max_devices,
2121	    sc->max_dpm_entries);
2122	if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING)
2123		sc->is_dpm_enable = 0;
2124
2125	if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
2126		sc->num_rsvd_entries = 1;
2127
2128	volume_mapping_flags = sc->ioc_pg8.IRVolumeMappingFlags &
2129	    MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
2130	if (sc->ir_firmware && (volume_mapping_flags ==
2131	    MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING))
2132		sc->num_rsvd_entries += sc->max_volumes;
2133
2134	error = mps_mapping_allocate_memory(sc);
2135	if (error)
2136		return (error);
2137
2138	for (i = 0; i < sc->max_devices; i++)
2139		_mapping_clear_map_entry(sc->mapping_table + i);
2140
2141	for (i = 0; i < sc->max_enclosures; i++)
2142		_mapping_clear_enc_entry(sc->enclosure_table + i);
2143
2144	for (i = 0; i < sc->max_devices; i++) {
2145		sc->removal_table[i].dev_handle = 0;
2146		sc->removal_table[i].dpm_entry_num = MPS_DPM_BAD_IDX;
2147	}
2148
2149	memset(sc->dpm_entry_used, 0, sc->max_dpm_entries);
2150	memset(sc->dpm_flush_entry, 0, sc->max_dpm_entries);
2151
2152	if (sc->is_dpm_enable) {
2153		dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) +
2154		    (sc->max_dpm_entries *
2155		     sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY));
2156		retry_count = 0;
2157
2158retry_read_dpm:
2159		if (mps_config_get_dpm_pg0(sc, &mpi_reply, sc->dpm_pg0,
2160		    dpm_pg0_sz)) {
2161			mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: DPM page "
2162			    "read failed.\n", __func__);
2163			if (retry_count < 3) {
2164				retry_count++;
2165				goto retry_read_dpm;
2166			}
2167			sc->is_dpm_enable = 0;
2168		}
2169	}
2170
2171	if (sc->is_dpm_enable)
2172		_mapping_process_dpm_pg0(sc);
2173	else {
2174		mps_dprint(sc, MPS_MAPPING, "%s: DPM processing is disabled. "
2175		    "Device mappings will not persist across reboots or "
2176		    "resets.\n", __func__);
2177	}
2178
2179	sc->track_mapping_events = 1;
2180	return 0;
2181}
2182
2183/**
2184 * mps_mapping_exit - clear mapping table and associated memory
2185 * @sc: per adapter object
2186 *
2187 * Returns nothing.
2188 */
2189void
2190mps_mapping_exit(struct mps_softc *sc)
2191{
2192	_mapping_flush_dpm_pages(sc);
2193	mps_mapping_free_memory(sc);
2194}
2195
2196/**
2197 * mps_mapping_get_tid - return the target id for sas device and handle
2198 * @sc: per adapter object
2199 * @sas_address: sas address of the device
2200 * @handle: device handle
2201 *
2202 * Returns valid target ID on success or BAD_ID.
2203 */
2204unsigned int
2205mps_mapping_get_tid(struct mps_softc *sc, uint64_t sas_address, u16 handle)
2206{
2207	u32 map_idx;
2208	struct dev_mapping_table *mt_entry;
2209
2210	for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
2211		mt_entry = &sc->mapping_table[map_idx];
2212		if (mt_entry->dev_handle == handle && mt_entry->physical_id ==
2213		    sas_address)
2214			return mt_entry->id;
2215	}
2216
2217	return MPS_MAP_BAD_ID;
2218}
2219
2220/**
2221 * mps_mapping_get_tid_from_handle - find a target id in mapping table using
2222 * only the dev handle.  This is just a wrapper function for the local function
2223 * _mapping_get_mt_idx_from_handle.
2224 * @sc: per adapter object
2225 * @handle: device handle
2226 *
2227 * Returns valid target ID on success or BAD_ID.
2228 */
2229unsigned int
2230mps_mapping_get_tid_from_handle(struct mps_softc *sc, u16 handle)
2231{
2232	return (_mapping_get_mt_idx_from_handle(sc, handle));
2233}
2234
2235/**
2236 * mps_mapping_get_raid_tid - return the target id for raid device
2237 * @sc: per adapter object
2238 * @wwid: world wide identifier for raid volume
2239 * @volHandle: volume device handle
2240 *
2241 * Returns valid target ID on success or BAD_ID.
2242 */
2243unsigned int
2244mps_mapping_get_raid_tid(struct mps_softc *sc, u64 wwid, u16 volHandle)
2245{
2246	u32 start_idx, end_idx, map_idx;
2247	struct dev_mapping_table *mt_entry;
2248
2249	_mapping_get_ir_maprange(sc, &start_idx, &end_idx);
2250	mt_entry = &sc->mapping_table[start_idx];
2251	for (map_idx  = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) {
2252		if (mt_entry->dev_handle == volHandle &&
2253		    mt_entry->physical_id == wwid)
2254			return mt_entry->id;
2255	}
2256
2257	return MPS_MAP_BAD_ID;
2258}
2259
2260/**
2261 * mps_mapping_get_raid_tid_from_handle - find raid device in mapping table
2262 * using only the volume dev handle.  This is just a wrapper function for the
2263 * local function _mapping_get_ir_mt_idx_from_handle.
2264 * @sc: per adapter object
2265 * @volHandle: volume device handle
2266 *
2267 * Returns valid target ID on success or BAD_ID.
2268 */
2269unsigned int
2270mps_mapping_get_raid_tid_from_handle(struct mps_softc *sc, u16 volHandle)
2271{
2272	return (_mapping_get_ir_mt_idx_from_handle(sc, volHandle));
2273}
2274
2275/**
2276 * mps_mapping_enclosure_dev_status_change_event - handle enclosure events
2277 * @sc: per adapter object
2278 * @event_data: event data payload
2279 *
2280 * Return nothing.
2281 */
2282void
2283mps_mapping_enclosure_dev_status_change_event(struct mps_softc *sc,
2284    Mpi2EventDataSasEnclDevStatusChange_t *event_data)
2285{
2286	u8 enc_idx, missing_count;
2287	struct enc_mapping_table *et_entry;
2288	Mpi2DriverMap0Entry_t *dpm_entry;
2289	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
2290	u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
2291	u8 update_phy_bits = 0;
2292	u32 saved_phy_bits;
2293	uint64_t temp64_var;
2294
2295	if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) !=
2296	    MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING)
2297		goto out;
2298
2299	dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
2300	    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
2301
2302	if (event_data->ReasonCode == MPI2_EVENT_SAS_ENCL_RC_ADDED) {
2303		if (!event_data->NumSlots) {
2304			mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Enclosure "
2305			    "with handle = 0x%x reported 0 slots.\n", __func__,
2306			    le16toh(event_data->EnclosureHandle));
2307			goto out;
2308		}
2309		temp64_var = event_data->EnclosureLogicalID.High;
2310		temp64_var = (temp64_var << 32) |
2311		    event_data->EnclosureLogicalID.Low;
2312		enc_idx = _mapping_get_enc_idx_from_id(sc, temp64_var,
2313		    event_data->PhyBits);
2314
2315		/*
2316		 * If the Added enclosure is already in the Enclosure Table,
2317		 * make sure that all the the enclosure info is up to date. If
2318		 * the enclosure was missing and has just been added back, or if
2319		 * the enclosure's Phy Bits have changed, clear the missing
2320		 * count and update the Phy Bits in the mapping table and in the
2321		 * DPM, if it's being used.
2322		 */
2323		if (enc_idx != MPS_ENCTABLE_BAD_IDX) {
2324			et_entry = &sc->enclosure_table[enc_idx];
2325			if (et_entry->init_complete &&
2326			    !et_entry->missing_count) {
2327				mps_dprint(sc, MPS_MAPPING, "%s: Enclosure %d "
2328				    "is already present with handle = 0x%x\n",
2329				    __func__, enc_idx, et_entry->enc_handle);
2330				goto out;
2331			}
2332			et_entry->enc_handle = le16toh(event_data->
2333			    EnclosureHandle);
2334			et_entry->start_slot = le16toh(event_data->StartSlot);
2335			saved_phy_bits = et_entry->phy_bits;
2336			et_entry->phy_bits |= le32toh(event_data->PhyBits);
2337			if (saved_phy_bits != et_entry->phy_bits)
2338				update_phy_bits = 1;
2339			if (et_entry->missing_count || update_phy_bits) {
2340				et_entry->missing_count = 0;
2341				if (sc->is_dpm_enable &&
2342				    et_entry->dpm_entry_num !=
2343				    MPS_DPM_BAD_IDX) {
2344					dpm_entry += et_entry->dpm_entry_num;
2345					missing_count =
2346					    (u8)(dpm_entry->MappingInformation &
2347					    MPI2_DRVMAP0_MAPINFO_MISSING_MASK);
2348					if (missing_count || update_phy_bits) {
2349						dpm_entry->MappingInformation
2350						    = et_entry->num_slots;
2351						dpm_entry->MappingInformation
2352						    <<= map_shift;
2353						dpm_entry->PhysicalBitsMapping
2354						    = et_entry->phy_bits;
2355						sc->dpm_flush_entry[et_entry->
2356						    dpm_entry_num] = 1;
2357					}
2358				}
2359			}
2360		} else {
2361			/*
2362			 * This is a new enclosure that is being added.
2363			 * Initialize the Enclosure Table entry. It will be
2364			 * finalized when a device is added for the enclosure
2365			 * and the enclosure has enough space in the Mapping
2366			 * Table to map its devices.
2367			 */
2368			enc_idx = sc->num_enc_table_entries;
2369			if (enc_idx >= sc->max_enclosures) {
2370				mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: "
2371				    "Enclosure cannot be added to mapping "
2372				    "table because it's full.\n", __func__);
2373				goto out;
2374			}
2375			sc->num_enc_table_entries++;
2376			et_entry = &sc->enclosure_table[enc_idx];
2377			et_entry->enc_handle = le16toh(event_data->
2378			    EnclosureHandle);
2379			et_entry->enclosure_id = le64toh(event_data->
2380			    EnclosureLogicalID.High);
2381			et_entry->enclosure_id =
2382			    ((et_entry->enclosure_id << 32) |
2383			    le64toh(event_data->EnclosureLogicalID.Low));
2384			et_entry->start_index = MPS_MAPTABLE_BAD_IDX;
2385			et_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
2386			et_entry->num_slots = le16toh(event_data->NumSlots);
2387			et_entry->start_slot = le16toh(event_data->StartSlot);
2388			et_entry->phy_bits = le32toh(event_data->PhyBits);
2389		}
2390		et_entry->init_complete = 1;
2391	} else if (event_data->ReasonCode ==
2392	    MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING) {
2393		/*
2394		 * An enclosure was removed. Update its missing count and then
2395		 * update the DPM entry with the new missing count for the
2396		 * enclosure.
2397		 */
2398		enc_idx = _mapping_get_enc_idx_from_handle(sc,
2399		    le16toh(event_data->EnclosureHandle));
2400		if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
2401			mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Cannot "
2402			    "unmap enclosure %d because it has already been "
2403			    "deleted.\n", __func__, enc_idx);
2404			goto out;
2405		}
2406		et_entry = &sc->enclosure_table[enc_idx];
2407		if (et_entry->missing_count < MPS_MAX_MISSING_COUNT)
2408			et_entry->missing_count++;
2409		if (sc->is_dpm_enable &&
2410		    et_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
2411			dpm_entry += et_entry->dpm_entry_num;
2412			dpm_entry->MappingInformation = et_entry->num_slots;
2413			dpm_entry->MappingInformation <<= map_shift;
2414			dpm_entry->MappingInformation |=
2415			    et_entry->missing_count;
2416			sc->dpm_flush_entry[et_entry->dpm_entry_num] = 1;
2417		}
2418		et_entry->init_complete = 1;
2419	}
2420
2421out:
2422	_mapping_flush_dpm_pages(sc);
2423	if (sc->pending_map_events)
2424		sc->pending_map_events--;
2425}
2426
2427/**
2428 * mps_mapping_topology_change_event - handle topology change events
2429 * @sc: per adapter object
2430 * @event_data: event data payload
2431 *
2432 * Returns nothing.
2433 */
2434void
2435mps_mapping_topology_change_event(struct mps_softc *sc,
2436    Mpi2EventDataSasTopologyChangeList_t *event_data)
2437{
2438	struct _map_topology_change topo_change;
2439	struct _map_phy_change *phy_change;
2440	Mpi2EventSasTopoPhyEntry_t *event_phy_change;
2441	u8 i, num_entries;
2442
2443	topo_change.enc_handle = le16toh(event_data->EnclosureHandle);
2444	topo_change.exp_handle = le16toh(event_data->ExpanderDevHandle);
2445	num_entries = event_data->NumEntries;
2446	topo_change.num_entries = num_entries;
2447	topo_change.start_phy_num = event_data->StartPhyNum;
2448	topo_change.num_phys = event_data->NumPhys;
2449	topo_change.exp_status = event_data->ExpStatus;
2450	event_phy_change = event_data->PHY;
2451	topo_change.phy_details = NULL;
2452
2453	if (!num_entries)
2454		goto out;
2455	phy_change = malloc(sizeof(struct _map_phy_change) * num_entries,
2456	    M_MPT2, M_NOWAIT|M_ZERO);
2457	topo_change.phy_details = phy_change;
2458	if (!phy_change)
2459		goto out;
2460	for (i = 0; i < num_entries; i++, event_phy_change++, phy_change++) {
2461		phy_change->dev_handle = le16toh(event_phy_change->
2462		    AttachedDevHandle);
2463		phy_change->reason = event_phy_change->PhyStatus &
2464		    MPI2_EVENT_SAS_TOPO_RC_MASK;
2465	}
2466	_mapping_update_missing_count(sc, &topo_change);
2467	_mapping_get_dev_info(sc, &topo_change);
2468	_mapping_clear_removed_entries(sc);
2469	_mapping_add_new_device(sc, &topo_change);
2470
2471out:
2472	free(topo_change.phy_details, M_MPT2);
2473	_mapping_flush_dpm_pages(sc);
2474	if (sc->pending_map_events)
2475		sc->pending_map_events--;
2476}
2477
2478/**
2479 * mps_mapping_ir_config_change_event - handle IR config change list events
2480 * @sc: per adapter object
2481 * @event_data: event data payload
2482 *
2483 * Returns nothing.
2484 */
2485void
2486mps_mapping_ir_config_change_event(struct mps_softc *sc,
2487    Mpi2EventDataIrConfigChangeList_t *event_data)
2488{
2489	Mpi2EventIrConfigElement_t *element;
2490	int i;
2491	u64 *wwid_table;
2492	u32 map_idx, flags;
2493	struct dev_mapping_table *mt_entry;
2494	u16 element_flags;
2495
2496	wwid_table = malloc(sizeof(u64) * event_data->NumElements, M_MPT2,
2497	    M_NOWAIT | M_ZERO);
2498	if (!wwid_table)
2499		goto out;
2500	element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
2501	flags = le32toh(event_data->Flags);
2502
2503	/*
2504	 * For volume changes, get the WWID for the volume and put it in a
2505	 * table to be used in the processing of the IR change event.
2506	 */
2507	for (i = 0; i < event_data->NumElements; i++, element++) {
2508		element_flags = le16toh(element->ElementFlags);
2509		if ((element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_ADDED) &&
2510		    (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_REMOVED) &&
2511		    (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE)
2512		    && (element->ReasonCode !=
2513			MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED))
2514			continue;
2515		if ((element_flags &
2516		    MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK) ==
2517		    MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT) {
2518			mps_config_get_volume_wwid(sc,
2519			    le16toh(element->VolDevHandle), &wwid_table[i]);
2520		}
2521	}
2522
2523	/*
2524	 * Check the ReasonCode for each element in the IR event and Add/Remove
2525	 * Volumes or Physical Disks of Volumes to/from the mapping table. Use
2526	 * the WWIDs gotten above in wwid_table.
2527	 */
2528	if (flags == MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
2529		goto out;
2530	else {
2531		element = (Mpi2EventIrConfigElement_t *)&event_data->
2532		    ConfigElement[0];
2533		for (i = 0; i < event_data->NumElements; i++, element++) {
2534			if (element->ReasonCode ==
2535			    MPI2_EVENT_IR_CHANGE_RC_ADDED ||
2536			    element->ReasonCode ==
2537			    MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) {
2538				map_idx = _mapping_get_ir_mt_idx_from_wwid
2539				    (sc, wwid_table[i]);
2540				if (map_idx != MPS_MAPTABLE_BAD_IDX) {
2541					/*
2542					 * The volume is already in the mapping
2543					 * table. Just update it's info.
2544					 */
2545					mt_entry = &sc->mapping_table[map_idx];
2546					mt_entry->id = map_idx;
2547					mt_entry->dev_handle = le16toh
2548					    (element->VolDevHandle);
2549					mt_entry->device_info =
2550					    MPS_DEV_RESERVED | MPS_MAP_IN_USE;
2551					_mapping_update_ir_missing_cnt(sc,
2552					    map_idx, element, wwid_table[i]);
2553					continue;
2554				}
2555
2556				/*
2557				 * Volume is not in mapping table yet. Find a
2558				 * free entry in the mapping table at the
2559				 * volume mapping locations. If no entries are
2560				 * available, this is an error because it means
2561				 * there are more volumes than can be mapped
2562				 * and that should never happen for volumes.
2563				 */
2564				map_idx = _mapping_get_free_ir_mt_idx(sc);
2565				if (map_idx == MPS_MAPTABLE_BAD_IDX)
2566				{
2567					mps_dprint(sc, MPS_ERROR | MPS_MAPPING,
2568					    "%s: failed to add the volume with "
2569					    "handle 0x%04x because there is no "
2570					    "free space available in the "
2571					    "mapping table\n", __func__,
2572					    le16toh(element->VolDevHandle));
2573					continue;
2574				}
2575				mt_entry = &sc->mapping_table[map_idx];
2576				mt_entry->physical_id = wwid_table[i];
2577				mt_entry->id = map_idx;
2578				mt_entry->dev_handle = le16toh(element->
2579				    VolDevHandle);
2580				mt_entry->device_info = MPS_DEV_RESERVED |
2581				    MPS_MAP_IN_USE;
2582				_mapping_update_ir_missing_cnt(sc, map_idx,
2583				    element, wwid_table[i]);
2584			} else if (element->ReasonCode ==
2585			    MPI2_EVENT_IR_CHANGE_RC_REMOVED) {
2586				map_idx = _mapping_get_ir_mt_idx_from_wwid(sc,
2587				    wwid_table[i]);
2588				if (map_idx == MPS_MAPTABLE_BAD_IDX) {
2589					mps_dprint(sc, MPS_MAPPING,"%s: Failed "
2590					    "to remove a volume because it has "
2591					    "already been removed.\n",
2592					    __func__);
2593					continue;
2594				}
2595				_mapping_update_ir_missing_cnt(sc, map_idx,
2596				    element, wwid_table[i]);
2597			} else if (element->ReasonCode ==
2598			    MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED) {
2599				map_idx = _mapping_get_mt_idx_from_handle(sc,
2600				    le16toh(element->VolDevHandle));
2601				if (map_idx == MPS_MAPTABLE_BAD_IDX) {
2602					mps_dprint(sc, MPS_MAPPING,"%s: Failed "
2603					    "to remove volume with handle "
2604					    "0x%04x because it has already "
2605					    "been removed.\n", __func__,
2606					    le16toh(element->VolDevHandle));
2607					continue;
2608				}
2609				mt_entry = &sc->mapping_table[map_idx];
2610				_mapping_update_ir_missing_cnt(sc, map_idx,
2611				    element, mt_entry->physical_id);
2612			}
2613		}
2614	}
2615
2616out:
2617	_mapping_flush_dpm_pages(sc);
2618	free(wwid_table, M_MPT2);
2619	if (sc->pending_map_events)
2620		sc->pending_map_events--;
2621}
2622
2623int
2624mps_mapping_dump(SYSCTL_HANDLER_ARGS)
2625{
2626	struct mps_softc *sc;
2627	struct dev_mapping_table *mt_entry;
2628	struct sbuf sbuf;
2629	int i, error;
2630
2631	sc = (struct mps_softc *)arg1;
2632
2633	error = sysctl_wire_old_buffer(req, 0);
2634	if (error != 0)
2635		return (error);
2636	sbuf_new_for_sysctl(&sbuf, NULL, 128, req);
2637
2638	sbuf_printf(&sbuf, "\nindex physical_id       handle id\n");
2639	for (i = 0; i < sc->max_devices; i++) {
2640		mt_entry = &sc->mapping_table[i];
2641		if (mt_entry->physical_id == 0)
2642			continue;
2643		sbuf_printf(&sbuf, "%4d  %jx  %04x   %hd\n",
2644		    i, mt_entry->physical_id, mt_entry->dev_handle,
2645		    mt_entry->id);
2646	}
2647	error = sbuf_finish(&sbuf);
2648	sbuf_delete(&sbuf);
2649	return (error);
2650}
2651
2652int
2653mps_mapping_encl_dump(SYSCTL_HANDLER_ARGS)
2654{
2655	struct mps_softc *sc;
2656	struct enc_mapping_table *enc_entry;
2657	struct sbuf sbuf;
2658	int i, error;
2659
2660	sc = (struct mps_softc *)arg1;
2661
2662	error = sysctl_wire_old_buffer(req, 0);
2663	if (error != 0)
2664		return (error);
2665	sbuf_new_for_sysctl(&sbuf, NULL, 128, req);
2666
2667	sbuf_printf(&sbuf, "\nindex enclosure_id      handle map_index\n");
2668	for (i = 0; i < sc->max_enclosures; i++) {
2669		enc_entry = &sc->enclosure_table[i];
2670		if (enc_entry->enclosure_id == 0)
2671			continue;
2672		sbuf_printf(&sbuf, "%4d  %jx  %04x   %d\n",
2673		    i, enc_entry->enclosure_id, enc_entry->enc_handle,
2674		    enc_entry->start_index);
2675	}
2676	error = sbuf_finish(&sbuf);
2677	sbuf_delete(&sbuf);
2678	return (error);
2679}
2680