2 * Copyright (c) 2011 LSI Corp.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * LSI MPT-Fusion Host Adapter FreeBSD
28 * $FreeBSD: src/sys/dev/mps/mps_mapping.c,v 1.1 2012/01/26 18:17:21 ken Exp $
31 /* TODO Move headers to mpsvar */
32 #include <sys/types.h>
33 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/malloc.h>
38 #include <sys/kthread.h>
39 #include <sys/taskqueue.h>
41 #include <sys/endian.h>
42 #include <sys/sysctl.h>
43 #include <sys/eventhandler.h>
45 #include <dev/raid/mps/mpi/mpi2_type.h>
46 #include <dev/raid/mps/mpi/mpi2.h>
47 #include <dev/raid/mps/mpi/mpi2_ioc.h>
48 #include <dev/raid/mps/mpi/mpi2_sas.h>
49 #include <dev/raid/mps/mpi/mpi2_cnfg.h>
50 #include <dev/raid/mps/mpi/mpi2_init.h>
51 #include <dev/raid/mps/mpi/mpi2_tool.h>
52 #include <dev/raid/mps/mps_ioctl.h>
53 #include <dev/raid/mps/mpsvar.h>
54 #include <dev/raid/mps/mps_mapping.h>
57 * _mapping_clear_entry - Clear a particular mapping entry.
58 * @map_entry: map table entry
63 _mapping_clear_map_entry(struct dev_mapping_table *map_entry)
65 map_entry->physical_id = 0;
66 map_entry->device_info = 0;
67 map_entry->phy_bits = 0;
68 map_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
69 map_entry->dev_handle = 0;
70 map_entry->channel = -1;
72 map_entry->missing_count = 0;
73 map_entry->init_complete = 0;
74 map_entry->TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR;
78 * _mapping_clear_enc_entry - Clear a particular enclosure table entry.
79 * @enc_entry: enclosure table entry
84 _mapping_clear_enc_entry(struct enc_mapping_table *enc_entry)
86 enc_entry->enclosure_id = 0;
87 enc_entry->start_index = MPS_MAPTABLE_BAD_IDX;
88 enc_entry->phy_bits = 0;
89 enc_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
90 enc_entry->enc_handle = 0;
91 enc_entry->num_slots = 0;
92 enc_entry->start_slot = 0;
93 enc_entry->missing_count = 0;
94 enc_entry->removal_flag = 0;
95 enc_entry->skip_search = 0;
96 enc_entry->init_complete = 0;
100 * _mapping_commit_enc_entry - write a particular enc entry in DPM page0.
101 * @sc: per adapter object
102 * @enc_entry: enclosure table entry
104 * Returns 0 for success, non-zero for failure.
107 _mapping_commit_enc_entry(struct mps_softc *sc,
108 struct enc_mapping_table *et_entry)
110 Mpi2DriverMap0Entry_t *dpm_entry;
111 struct dev_mapping_table *mt_entry;
112 Mpi2ConfigReply_t mpi_reply;
113 Mpi2DriverMappingPage0_t config_page;
115 if (!sc->is_dpm_enable)
118 memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
119 memcpy(&config_page.Header, (u8 *) sc->dpm_pg0,
120 sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
121 dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
122 sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
123 dpm_entry += et_entry->dpm_entry_num;
124 dpm_entry->PhysicalIdentifier.Low =
125 ( 0xFFFFFFFF & et_entry->enclosure_id);
126 dpm_entry->PhysicalIdentifier.High =
127 ( et_entry->enclosure_id >> 32);
128 mt_entry = &sc->mapping_table[et_entry->start_index];
129 dpm_entry->DeviceIndex = htole16(mt_entry->id);
130 dpm_entry->MappingInformation = et_entry->num_slots;
131 dpm_entry->MappingInformation <<= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
132 dpm_entry->MappingInformation |= et_entry->missing_count;
133 dpm_entry->MappingInformation = htole16(dpm_entry->MappingInformation);
134 dpm_entry->PhysicalBitsMapping = htole32(et_entry->phy_bits);
135 dpm_entry->Reserved1 = 0;
137 memcpy(&config_page.Entry, (u8 *)dpm_entry,
138 sizeof(Mpi2DriverMap0Entry_t));
139 if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
140 et_entry->dpm_entry_num)) {
141 kprintf("%s: write of dpm entry %d for enclosure failed\n",
142 __func__, et_entry->dpm_entry_num);
143 dpm_entry->MappingInformation = le16toh(dpm_entry->
145 dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
146 dpm_entry->PhysicalBitsMapping =
147 le32toh(dpm_entry->PhysicalBitsMapping);
150 dpm_entry->MappingInformation = le16toh(dpm_entry->
152 dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
153 dpm_entry->PhysicalBitsMapping =
154 le32toh(dpm_entry->PhysicalBitsMapping);
159 * _mapping_commit_map_entry - write a particular map table entry in DPM page0.
160 * @sc: per adapter object
161 * @enc_entry: enclosure table entry
163 * Returns 0 for success, non-zero for failure.
167 _mapping_commit_map_entry(struct mps_softc *sc,
168 struct dev_mapping_table *mt_entry)
170 Mpi2DriverMap0Entry_t *dpm_entry;
171 Mpi2ConfigReply_t mpi_reply;
172 Mpi2DriverMappingPage0_t config_page;
174 if (!sc->is_dpm_enable)
177 memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
178 memcpy(&config_page.Header, (u8 *)sc->dpm_pg0,
179 sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
180 dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *) sc->dpm_pg0 +
181 sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
182 dpm_entry = dpm_entry + mt_entry->dpm_entry_num;
183 dpm_entry->PhysicalIdentifier.Low = (0xFFFFFFFF &
184 mt_entry->physical_id);
185 dpm_entry->PhysicalIdentifier.High = (mt_entry->physical_id >> 32);
186 dpm_entry->DeviceIndex = htole16(mt_entry->id);
187 dpm_entry->MappingInformation = htole16(mt_entry->missing_count);
188 dpm_entry->PhysicalBitsMapping = 0;
189 dpm_entry->Reserved1 = 0;
190 dpm_entry->MappingInformation = htole16(dpm_entry->MappingInformation);
191 memcpy(&config_page.Entry, (u8 *)dpm_entry,
192 sizeof(Mpi2DriverMap0Entry_t));
193 if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
194 mt_entry->dpm_entry_num)) {
195 kprintf("%s: write of dpm entry %d for device failed\n",
196 __func__, mt_entry->dpm_entry_num);
197 dpm_entry->MappingInformation = le16toh(dpm_entry->
199 dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
203 dpm_entry->MappingInformation = le16toh(dpm_entry->MappingInformation);
204 dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
209 * _mapping_get_ir_maprange - get start and end index for IR map range.
210 * @sc: per adapter object
211 * @start_idx: place holder for start index
212 * @end_idx: place holder for end index
214 * The IR volumes can be mapped either at start or end of the mapping table
215 * this function gets the detail of where IR volume mapping starts and ends
216 * in the device mapping table
221 _mapping_get_ir_maprange(struct mps_softc *sc, u32 *start_idx, u32 *end_idx)
223 u16 volume_mapping_flags;
224 u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
226 volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
227 MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
228 if (volume_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
230 if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
233 *start_idx = sc->max_devices - sc->max_volumes;
234 *end_idx = *start_idx + sc->max_volumes - 1;
238 * _mapping_get_enc_idx_from_id - get enclosure index from enclosure ID
239 * @sc: per adapter object
240 * @enc_id: enclosure logical identifier
242 * Returns the index of enclosure entry on success or bad index.
245 _mapping_get_enc_idx_from_id(struct mps_softc *sc, u64 enc_id,
248 struct enc_mapping_table *et_entry;
251 for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
252 et_entry = &sc->enclosure_table[enc_idx];
253 if ((et_entry->enclosure_id == le64toh(enc_id)) &&
254 (!et_entry->phy_bits || (et_entry->phy_bits &
258 return MPS_ENCTABLE_BAD_IDX;
262 * _mapping_get_enc_idx_from_handle - get enclosure index from handle
263 * @sc: per adapter object
264 * @enc_id: enclosure handle
266 * Returns the index of enclosure entry on success or bad index.
269 _mapping_get_enc_idx_from_handle(struct mps_softc *sc, u16 handle)
271 struct enc_mapping_table *et_entry;
274 for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
275 et_entry = &sc->enclosure_table[enc_idx];
276 if (et_entry->missing_count)
278 if (et_entry->enc_handle == handle)
281 return MPS_ENCTABLE_BAD_IDX;
285 * _mapping_get_high_missing_et_idx - get missing enclosure index
286 * @sc: per adapter object
288 * Search through the enclosure table and identifies the enclosure entry
289 * with high missing count and returns it's index
291 * Returns the index of enclosure entry on success or bad index.
294 _mapping_get_high_missing_et_idx(struct mps_softc *sc)
296 struct enc_mapping_table *et_entry;
297 u8 high_missing_count = 0;
298 u8 enc_idx, high_idx = MPS_ENCTABLE_BAD_IDX;
300 for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
301 et_entry = &sc->enclosure_table[enc_idx];
302 if ((et_entry->missing_count > high_missing_count) &&
303 !et_entry->skip_search) {
304 high_missing_count = et_entry->missing_count;
312 * _mapping_get_high_missing_mt_idx - get missing map table index
313 * @sc: per adapter object
315 * Search through the map table and identifies the device entry
316 * with high missing count and returns it's index
318 * Returns the index of map table entry on success or bad index.
321 _mapping_get_high_missing_mt_idx(struct mps_softc *sc)
323 u32 map_idx, high_idx = MPS_ENCTABLE_BAD_IDX;
324 u8 high_missing_count = 0;
325 u32 start_idx, end_idx, start_idx_ir, end_idx_ir;
326 struct dev_mapping_table *mt_entry;
327 u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
332 end_idx = sc->max_devices;
333 if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
336 _mapping_get_ir_maprange(sc, &start_idx_ir, &end_idx_ir);
337 if (start_idx == start_idx_ir)
338 start_idx = end_idx_ir + 1;
340 end_idx = start_idx_ir;
341 mt_entry = &sc->mapping_table[start_idx];
342 for (map_idx = start_idx; map_idx < end_idx; map_idx++, mt_entry++) {
343 if (mt_entry->missing_count > high_missing_count) {
344 high_missing_count = mt_entry->missing_count;
352 * _mapping_get_ir_mt_idx_from_wwid - get map table index from volume WWID
353 * @sc: per adapter object
354 * @wwid: world wide unique ID of the volume
356 * Returns the index of map table entry on success or bad index.
359 _mapping_get_ir_mt_idx_from_wwid(struct mps_softc *sc, u64 wwid)
361 u32 start_idx, end_idx, map_idx;
362 struct dev_mapping_table *mt_entry;
364 _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
365 mt_entry = &sc->mapping_table[start_idx];
366 for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
367 if (mt_entry->physical_id == wwid)
370 return MPS_MAPTABLE_BAD_IDX;
374 * _mapping_get_mt_idx_from_id - get map table index from a device ID
375 * @sc: per adapter object
376 * @dev_id: device identifer (SAS Address)
378 * Returns the index of map table entry on success or bad index.
381 _mapping_get_mt_idx_from_id(struct mps_softc *sc, u64 dev_id)
384 struct dev_mapping_table *mt_entry;
386 for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
387 mt_entry = &sc->mapping_table[map_idx];
388 if (mt_entry->physical_id == dev_id)
391 return MPS_MAPTABLE_BAD_IDX;
395 * _mapping_get_ir_mt_idx_from_handle - get map table index from volume handle
396 * @sc: per adapter object
397 * @wwid: volume device handle
399 * Returns the index of map table entry on success or bad index.
402 _mapping_get_ir_mt_idx_from_handle(struct mps_softc *sc, u16 volHandle)
404 u32 start_idx, end_idx, map_idx;
405 struct dev_mapping_table *mt_entry;
407 _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
408 mt_entry = &sc->mapping_table[start_idx];
409 for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
410 if (mt_entry->dev_handle == volHandle)
413 return MPS_MAPTABLE_BAD_IDX;
417 * _mapping_get_mt_idx_from_handle - get map table index from handle
418 * @sc: per adapter object
419 * @dev_id: device handle
421 * Returns the index of map table entry on success or bad index.
424 _mapping_get_mt_idx_from_handle(struct mps_softc *sc, u16 handle)
427 struct dev_mapping_table *mt_entry;
429 for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
430 mt_entry = &sc->mapping_table[map_idx];
431 if (mt_entry->dev_handle == handle)
434 return MPS_MAPTABLE_BAD_IDX;
438 * _mapping_get_free_ir_mt_idx - get first free index for a volume
439 * @sc: per adapter object
441 * Search through mapping table for free index for a volume and if no free
442 * index then looks for a volume with high mapping index
444 * Returns the index of map table entry on success or bad index.
447 _mapping_get_free_ir_mt_idx(struct mps_softc *sc)
449 u8 high_missing_count = 0;
450 u32 start_idx, end_idx, map_idx;
451 u32 high_idx = MPS_MAPTABLE_BAD_IDX;
452 struct dev_mapping_table *mt_entry;
454 _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
456 mt_entry = &sc->mapping_table[start_idx];
457 for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
458 if (!(mt_entry->device_info & MPS_MAP_IN_USE))
461 mt_entry = &sc->mapping_table[start_idx];
462 for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) {
463 if (mt_entry->missing_count > high_missing_count) {
464 high_missing_count = mt_entry->missing_count;
472 * _mapping_get_free_mt_idx - get first free index for a device
473 * @sc: per adapter object
474 * @start_idx: offset in the table to start search
476 * Returns the index of map table entry on success or bad index.
479 _mapping_get_free_mt_idx(struct mps_softc *sc, u32 start_idx)
481 u32 map_idx, max_idx = sc->max_devices;
482 struct dev_mapping_table *mt_entry = &sc->mapping_table[start_idx];
483 u16 volume_mapping_flags;
485 volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
486 MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
487 if (sc->ir_firmware && (volume_mapping_flags ==
488 MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING))
489 max_idx -= sc->max_volumes;
490 for (map_idx = start_idx; map_idx < max_idx; map_idx++, mt_entry++)
491 if (!(mt_entry->device_info & (MPS_MAP_IN_USE |
495 return MPS_MAPTABLE_BAD_IDX;
499 * _mapping_get_dpm_idx_from_id - get DPM index from ID
500 * @sc: per adapter object
501 * @id: volume WWID or enclosure ID or device ID
503 * Returns the index of DPM entry on success or bad index.
506 _mapping_get_dpm_idx_from_id(struct mps_softc *sc, u64 id, u32 phy_bits)
509 uint64_t PhysicalIdentifier;
510 Mpi2DriverMap0Entry_t *dpm_entry;
512 dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
513 sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
514 PhysicalIdentifier = dpm_entry->PhysicalIdentifier.High;
515 PhysicalIdentifier = (PhysicalIdentifier << 32) |
516 dpm_entry->PhysicalIdentifier.Low;
517 for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++,
519 if ((id == PhysicalIdentifier) &&
520 (!phy_bits || !dpm_entry->PhysicalBitsMapping ||
521 (phy_bits & dpm_entry->PhysicalBitsMapping)))
524 return MPS_DPM_BAD_IDX;
529 * _mapping_get_free_dpm_idx - get first available DPM index
530 * @sc: per adapter object
532 * Returns the index of DPM entry on success or bad index.
535 _mapping_get_free_dpm_idx(struct mps_softc *sc)
539 for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) {
540 if (!sc->dpm_entry_used[entry_num])
543 return MPS_DPM_BAD_IDX;
547 * _mapping_update_ir_missing_cnt - Updates missing count for a volume
548 * @sc: per adapter object
549 * @map_idx: map table index of the volume
550 * @element: IR configuration change element
551 * @wwid: IR volume ID.
553 * Updates the missing count in the map table and in the DPM entry for a volume
558 _mapping_update_ir_missing_cnt(struct mps_softc *sc, u32 map_idx,
559 Mpi2EventIrConfigElement_t *element, u64 wwid)
561 struct dev_mapping_table *mt_entry;
562 u8 missing_cnt, reason = element->ReasonCode;
564 Mpi2DriverMap0Entry_t *dpm_entry;
566 if (!sc->is_dpm_enable)
568 mt_entry = &sc->mapping_table[map_idx];
569 if (reason == MPI2_EVENT_IR_CHANGE_RC_ADDED) {
570 mt_entry->missing_count = 0;
571 } else if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) {
572 mt_entry->missing_count = 0;
573 mt_entry->init_complete = 0;
574 } else if ((reason == MPI2_EVENT_IR_CHANGE_RC_REMOVED) ||
575 (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED)) {
576 if (!mt_entry->init_complete) {
577 if (mt_entry->missing_count < MPS_MAX_MISSING_COUNT)
578 mt_entry->missing_count++;
580 mt_entry->init_complete = 1;
582 if (!mt_entry->missing_count)
583 mt_entry->missing_count++;
584 mt_entry->dev_handle = 0;
587 dpm_idx = mt_entry->dpm_entry_num;
588 if (dpm_idx == MPS_DPM_BAD_IDX) {
589 if ((reason == MPI2_EVENT_IR_CHANGE_RC_ADDED) ||
590 (reason == MPI2_EVENT_IR_CHANGE_RC_REMOVED))
591 dpm_idx = _mapping_get_dpm_idx_from_id(sc,
592 mt_entry->physical_id, 0);
593 else if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED)
596 if (dpm_idx != MPS_DPM_BAD_IDX) {
597 dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
598 sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
599 dpm_entry += dpm_idx;
600 missing_cnt = dpm_entry->MappingInformation &
601 MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
602 if ((mt_entry->physical_id ==
603 le64toh((u64)dpm_entry->PhysicalIdentifier.High |
604 dpm_entry->PhysicalIdentifier.Low)) && (missing_cnt ==
605 mt_entry->missing_count))
606 mt_entry->init_complete = 1;
608 dpm_idx = _mapping_get_free_dpm_idx(sc);
609 mt_entry->init_complete = 0;
612 if ((dpm_idx != MPS_DPM_BAD_IDX) && !mt_entry->init_complete) {
613 mt_entry->init_complete = 1;
614 mt_entry->dpm_entry_num = dpm_idx;
615 dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
616 sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
617 dpm_entry += dpm_idx;
618 dpm_entry->PhysicalIdentifier.Low =
619 (0xFFFFFFFF & mt_entry->physical_id);
620 dpm_entry->PhysicalIdentifier.High =
621 (mt_entry->physical_id >> 32);
622 dpm_entry->DeviceIndex = map_idx;
623 dpm_entry->MappingInformation = mt_entry->missing_count;
624 dpm_entry->PhysicalBitsMapping = 0;
625 dpm_entry->Reserved1 = 0;
626 sc->dpm_flush_entry[dpm_idx] = 1;
627 sc->dpm_entry_used[dpm_idx] = 1;
628 } else if (dpm_idx == MPS_DPM_BAD_IDX) {
629 kprintf("%s: no space to add entry in DPM table\n", __func__);
630 mt_entry->init_complete = 1;
635 * _mapping_add_to_removal_table - mark an entry for removal
636 * @sc: per adapter object
637 * @handle: Handle of enclosures/device/volume
639 * Adds the handle or DPM entry number in removal table.
644 _mapping_add_to_removal_table(struct mps_softc *sc, u16 handle,
647 struct map_removal_table *remove_entry;
649 u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
651 remove_entry = sc->removal_table;
653 for (i = 0; i < sc->max_devices; i++, remove_entry++) {
654 if (remove_entry->dev_handle || remove_entry->dpm_entry_num !=
657 if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
658 MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
660 remove_entry->dpm_entry_num = dpm_idx;
661 if (remove_entry->dpm_entry_num == MPS_DPM_BAD_IDX)
662 remove_entry->dev_handle = handle;
663 } else if ((ioc_pg8_flags &
664 MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
665 MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING)
666 remove_entry->dev_handle = handle;
673 * _mapping_update_missing_count - Update missing count for a device
674 * @sc: per adapter object
675 * @topo_change: Topology change event entry
677 * Search through the topology change list and if any device is found not
678 * responding it's associated map table entry and DPM entry is updated
683 _mapping_update_missing_count(struct mps_softc *sc,
684 struct _map_topology_change *topo_change)
686 u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
688 struct _map_phy_change *phy_change;
690 struct dev_mapping_table *mt_entry;
691 Mpi2DriverMap0Entry_t *dpm_entry;
693 for (entry = 0; entry < topo_change->num_entries; entry++) {
694 phy_change = &topo_change->phy_details[entry];
695 if (!phy_change->dev_handle || (phy_change->reason !=
696 MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING))
698 map_idx = _mapping_get_mt_idx_from_handle(sc, phy_change->
700 phy_change->is_processed = 1;
701 if (map_idx == MPS_MAPTABLE_BAD_IDX) {
702 kprintf("%s: device is already removed from mapping "
703 "table\n", __func__);
706 mt_entry = &sc->mapping_table[map_idx];
707 if (!mt_entry->init_complete) {
708 if (mt_entry->missing_count < MPS_MAX_MISSING_COUNT)
709 mt_entry->missing_count++;
711 mt_entry->init_complete = 1;
713 if (!mt_entry->missing_count)
714 mt_entry->missing_count++;
715 _mapping_add_to_removal_table(sc, mt_entry->dev_handle, 0);
716 mt_entry->dev_handle = 0;
718 if (((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
719 MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) &&
720 sc->is_dpm_enable && !mt_entry->init_complete &&
721 mt_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
723 (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
724 sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
725 dpm_entry += mt_entry->dpm_entry_num;
726 dpm_entry->MappingInformation = mt_entry->missing_count;
727 sc->dpm_flush_entry[mt_entry->dpm_entry_num] = 1;
729 mt_entry->init_complete = 1;
734 * _mapping_find_enc_map_space -find map table entries for enclosure
735 * @sc: per adapter object
736 * @et_entry: enclosure entry
738 * Search through the mapping table defragment it and provide contiguous
739 * space in map table for a particular enclosure entry
741 * Returns start index in map table or bad index.
744 _mapping_find_enc_map_space(struct mps_softc *sc,
745 struct enc_mapping_table *et_entry)
747 u16 vol_mapping_flags;
748 u32 skip_count, end_of_table, map_idx, enc_idx;
750 u32 start_idx = MPS_MAPTABLE_BAD_IDX;
751 struct dev_mapping_table *mt_entry;
752 struct enc_mapping_table *enc_entry;
753 unsigned char done_flag = 0, found_space;
754 u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
756 skip_count = sc->num_rsvd_entries;
759 vol_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
760 MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
762 if (!sc->ir_firmware)
763 end_of_table = sc->max_devices;
764 else if (vol_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING)
765 end_of_table = sc->max_devices;
767 end_of_table = sc->max_devices - sc->max_volumes;
769 for (map_idx = (max_num_phy_ids + skip_count);
770 map_idx < end_of_table; map_idx++) {
771 mt_entry = &sc->mapping_table[map_idx];
772 if ((et_entry->enclosure_id == mt_entry->physical_id) &&
773 (!mt_entry->phy_bits || (mt_entry->phy_bits &
774 et_entry->phy_bits))) {
776 if (num_found == et_entry->num_slots) {
777 start_idx = (map_idx - num_found) + 1;
783 for (map_idx = (max_num_phy_ids + skip_count);
784 map_idx < end_of_table; map_idx++) {
785 mt_entry = &sc->mapping_table[map_idx];
786 if (!(mt_entry->device_info & MPS_DEV_RESERVED)) {
788 if (num_found == et_entry->num_slots) {
789 start_idx = (map_idx - num_found) + 1;
797 enc_idx = _mapping_get_high_missing_et_idx(sc);
798 if (enc_idx == MPS_ENCTABLE_BAD_IDX)
799 return MPS_MAPTABLE_BAD_IDX;
800 enc_entry = &sc->enclosure_table[enc_idx];
802 enc_entry->skip_search = 1;
803 mt_entry = &sc->mapping_table[enc_entry->start_index];
804 for (map_idx = enc_entry->start_index; map_idx <
805 (enc_entry->start_index + enc_entry->num_slots); map_idx++,
807 mt_entry->device_info &= ~MPS_DEV_RESERVED;
809 for (map_idx = (max_num_phy_ids +
810 skip_count); map_idx < end_of_table; map_idx++) {
811 mt_entry = &sc->mapping_table[map_idx];
812 if (!(mt_entry->device_info & MPS_DEV_RESERVED)) {
814 if (num_found == et_entry->num_slots) {
815 start_idx = (map_idx - num_found) + 1;
824 for (map_idx = start_idx; map_idx < (start_idx + num_found);
826 enc_entry = sc->enclosure_table;
827 for (enc_idx = 0; enc_idx < sc->num_enc_table_entries;
828 enc_idx++, enc_entry++) {
829 if (map_idx < enc_entry->start_index ||
830 map_idx > (enc_entry->start_index +
831 enc_entry->num_slots))
833 if (!enc_entry->removal_flag) {
834 enc_entry->removal_flag = 1;
835 _mapping_add_to_removal_table(sc, 0,
836 enc_entry->dpm_entry_num);
838 mt_entry = &sc->mapping_table[map_idx];
839 if (mt_entry->device_info &
841 _mapping_add_to_removal_table(sc,
842 mt_entry->dev_handle, 0);
843 _mapping_clear_map_entry(mt_entry);
845 if (map_idx == (enc_entry->start_index +
846 enc_entry->num_slots - 1))
847 _mapping_clear_enc_entry(et_entry);
850 enc_entry = sc->enclosure_table;
851 for (enc_idx = 0; enc_idx < sc->num_enc_table_entries;
852 enc_idx++, enc_entry++) {
853 if (!enc_entry->removal_flag) {
854 mt_entry = &sc->mapping_table[enc_entry->
856 for (map_idx = enc_entry->start_index; map_idx <
857 (enc_entry->start_index +
858 enc_entry->num_slots); map_idx++,
860 mt_entry->device_info |=
862 et_entry->skip_search = 0;
871 * _mapping_get_dev_info -get information about newly added devices
872 * @sc: per adapter object
873 * @topo_change: Topology change event entry
875 * Search through the topology change event list and issues sas device pg0
876 * requests for the newly added device and reserved entries in tables
881 _mapping_get_dev_info(struct mps_softc *sc,
882 struct _map_topology_change *topo_change)
884 u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
885 Mpi2ConfigReply_t mpi_reply;
886 Mpi2SasDevicePage0_t sas_device_pg0;
887 u8 entry, enc_idx, phy_idx;
888 u32 map_idx, index, device_info;
889 struct _map_phy_change *phy_change, *tmp_phy_change;
890 uint64_t sas_address;
891 struct enc_mapping_table *et_entry;
892 struct dev_mapping_table *mt_entry;
893 u8 add_code = MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED;
896 for (entry = 0; entry < topo_change->num_entries; entry++) {
897 phy_change = &topo_change->phy_details[entry];
898 if (phy_change->is_processed || !phy_change->dev_handle ||
899 phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED)
901 if (mps_config_get_sas_device_pg0(sc, &mpi_reply,
902 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
903 phy_change->dev_handle)) {
904 phy_change->is_processed = 1;
908 device_info = le32toh(sas_device_pg0.DeviceInfo);
909 if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
910 MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
911 if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) &&
912 (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) {
913 rc = mpssas_get_sas_address_for_sata_disk(sc,
914 &sas_address, phy_change->dev_handle,
917 kprintf("%s: failed to compute the "
918 "hashed SAS Address for SATA "
919 "device with handle 0x%04x\n",
920 __func__, phy_change->dev_handle);
922 sas_device_pg0.SASAddress.High;
923 sas_address = (sas_address << 32) |
924 sas_device_pg0.SASAddress.Low;
926 mps_dprint(sc, MPS_INFO, "SAS Address for SATA "
927 "device = %jx\n", sas_address);
930 sas_device_pg0.SASAddress.High;
931 sas_address = (sas_address << 32) |
932 sas_device_pg0.SASAddress.Low;
935 sas_address = sas_device_pg0.SASAddress.High;
936 sas_address = (sas_address << 32) |
937 sas_device_pg0.SASAddress.Low;
939 phy_change->physical_id = sas_address;
940 phy_change->slot = le16toh(sas_device_pg0.Slot);
941 phy_change->device_info =
942 le32toh(sas_device_pg0.DeviceInfo);
944 if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
945 MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
946 enc_idx = _mapping_get_enc_idx_from_handle(sc,
947 topo_change->enc_handle);
948 if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
949 phy_change->is_processed = 1;
950 kprintf("%s: failed to add the device with "
951 "handle 0x%04x because the enclosure is "
952 "not in the mapping table\n", __func__,
953 phy_change->dev_handle);
956 if (!((phy_change->device_info &
957 MPI2_SAS_DEVICE_INFO_END_DEVICE) &&
958 (phy_change->device_info &
959 (MPI2_SAS_DEVICE_INFO_SSP_TARGET |
960 MPI2_SAS_DEVICE_INFO_STP_TARGET |
961 MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))) {
962 phy_change->is_processed = 1;
965 et_entry = &sc->enclosure_table[enc_idx];
966 if (et_entry->start_index != MPS_MAPTABLE_BAD_IDX)
968 if (!topo_change->exp_handle) {
969 map_idx = sc->num_rsvd_entries;
970 et_entry->start_index = map_idx;
972 map_idx = _mapping_find_enc_map_space(sc,
974 et_entry->start_index = map_idx;
975 if (et_entry->start_index ==
976 MPS_MAPTABLE_BAD_IDX) {
977 phy_change->is_processed = 1;
978 for (phy_idx = 0; phy_idx <
979 topo_change->num_entries;
982 &topo_change->phy_details
984 if (tmp_phy_change->reason ==
992 mt_entry = &sc->mapping_table[map_idx];
993 for (index = map_idx; index < (et_entry->num_slots
994 + map_idx); index++, mt_entry++) {
995 mt_entry->device_info = MPS_DEV_RESERVED;
996 mt_entry->physical_id = et_entry->enclosure_id;
997 mt_entry->phy_bits = et_entry->phy_bits;
1004 * _mapping_set_mid_to_eid -set map table data from enclosure table
1005 * @sc: per adapter object
1006 * @et_entry: enclosure entry
1011 _mapping_set_mid_to_eid(struct mps_softc *sc,
1012 struct enc_mapping_table *et_entry)
1014 struct dev_mapping_table *mt_entry;
1015 u16 slots = et_entry->num_slots, map_idx;
1016 u32 start_idx = et_entry->start_index;
1017 if (start_idx != MPS_MAPTABLE_BAD_IDX) {
1018 mt_entry = &sc->mapping_table[start_idx];
1019 for (map_idx = 0; map_idx < slots; map_idx++, mt_entry++)
1020 mt_entry->physical_id = et_entry->enclosure_id;
1025 * _mapping_clear_removed_entries - mark the entries to be cleared
1026 * @sc: per adapter object
1028 * Search through the removal table and mark the entries which needs to be
1029 * flushed to DPM and also updates the map table and enclosure table by
1030 * clearing the corresponding entries.
1035 _mapping_clear_removed_entries(struct mps_softc *sc)
1038 struct map_removal_table *remove_entry;
1039 Mpi2DriverMap0Entry_t *dpm_entry;
1040 u8 done_flag = 0, num_entries, m, i;
1041 struct enc_mapping_table *et_entry, *from, *to;
1042 u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1044 if (sc->is_dpm_enable) {
1045 remove_entry = sc->removal_table;
1046 for (remove_idx = 0; remove_idx < sc->max_devices;
1047 remove_idx++, remove_entry++) {
1048 if (remove_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
1049 dpm_entry = (Mpi2DriverMap0Entry_t *)
1050 ((u8 *) sc->dpm_pg0 +
1051 sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1052 dpm_entry += remove_entry->dpm_entry_num;
1053 dpm_entry->PhysicalIdentifier.Low = 0;
1054 dpm_entry->PhysicalIdentifier.High = 0;
1055 dpm_entry->DeviceIndex = 0;
1056 dpm_entry->MappingInformation = 0;
1057 dpm_entry->PhysicalBitsMapping = 0;
1058 sc->dpm_flush_entry[remove_entry->
1060 sc->dpm_entry_used[remove_entry->dpm_entry_num]
1062 remove_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
1066 if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1067 MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1068 num_entries = sc->num_enc_table_entries;
1069 while (!done_flag) {
1071 et_entry = sc->enclosure_table;
1072 for (i = 0; i < num_entries; i++, et_entry++) {
1073 if (!et_entry->enc_handle && et_entry->
1076 if (i != (num_entries - 1)) {
1077 from = &sc->enclosure_table
1079 to = &sc->enclosure_table[i];
1080 for (m = i; m < (num_entries -
1081 1); m++, from++, to++) {
1082 _mapping_set_mid_to_eid
1086 _mapping_clear_enc_entry(to);
1087 sc->num_enc_table_entries--;
1089 sc->num_enc_table_entries;
1091 _mapping_clear_enc_entry
1093 sc->num_enc_table_entries--;
1095 sc->num_enc_table_entries;
1104 * _mapping_add_new_device -Add the new device into mapping table
1105 * @sc: per adapter object
1106 * @topo_change: Topology change event entry
1108 * Search through the topology change event list and updates map table,
1109 * enclosure table and DPM pages for for the newly added devices.
1114 _mapping_add_new_device(struct mps_softc *sc,
1115 struct _map_topology_change *topo_change)
1117 u8 enc_idx, missing_cnt, is_removed = 0;
1119 u32 search_idx, map_idx;
1121 struct dev_mapping_table *mt_entry;
1122 struct enc_mapping_table *et_entry;
1123 struct _map_phy_change *phy_change;
1124 u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1125 Mpi2DriverMap0Entry_t *dpm_entry;
1126 uint64_t temp64_var;
1127 u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
1128 u8 hdr_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER);
1129 u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
1131 for (entry = 0; entry < topo_change->num_entries; entry++) {
1132 phy_change = &topo_change->phy_details[entry];
1133 if (phy_change->is_processed)
1135 if (phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED ||
1136 !phy_change->dev_handle) {
1137 phy_change->is_processed = 1;
1140 if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1141 MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1142 enc_idx = _mapping_get_enc_idx_from_handle
1143 (sc, topo_change->enc_handle);
1144 if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
1145 phy_change->is_processed = 1;
1146 kprintf("%s: failed to add the device with "
1147 "handle 0x%04x because the enclosure is "
1148 "not in the mapping table\n", __func__,
1149 phy_change->dev_handle);
1152 et_entry = &sc->enclosure_table[enc_idx];
1153 if (et_entry->start_index == MPS_MAPTABLE_BAD_IDX) {
1154 phy_change->is_processed = 1;
1155 if (!sc->mt_full_retry) {
1156 sc->mt_add_device_failed = 1;
1159 kprintf("%s: failed to add the device with "
1160 "handle 0x%04x because there is no free "
1161 "space available in the mapping table\n",
1162 __func__, phy_change->dev_handle);
1165 map_idx = et_entry->start_index + phy_change->slot -
1166 et_entry->start_slot;
1167 mt_entry = &sc->mapping_table[map_idx];
1168 mt_entry->physical_id = phy_change->physical_id;
1169 mt_entry->channel = 0;
1170 mt_entry->id = map_idx;
1171 mt_entry->dev_handle = phy_change->dev_handle;
1172 mt_entry->missing_count = 0;
1173 mt_entry->dpm_entry_num = et_entry->dpm_entry_num;
1174 mt_entry->device_info = phy_change->device_info |
1175 (MPS_DEV_RESERVED | MPS_MAP_IN_USE);
1176 if (sc->is_dpm_enable) {
1177 dpm_idx = et_entry->dpm_entry_num;
1178 if (dpm_idx == MPS_DPM_BAD_IDX)
1179 dpm_idx = _mapping_get_dpm_idx_from_id
1180 (sc, et_entry->enclosure_id,
1181 et_entry->phy_bits);
1182 if (dpm_idx == MPS_DPM_BAD_IDX) {
1183 dpm_idx = _mapping_get_free_dpm_idx(sc);
1184 if (dpm_idx != MPS_DPM_BAD_IDX) {
1186 (Mpi2DriverMap0Entry_t *)
1187 ((u8 *) sc->dpm_pg0 +
1189 dpm_entry += dpm_idx;
1191 PhysicalIdentifier.Low =
1193 et_entry->enclosure_id);
1195 PhysicalIdentifier.High =
1196 ( et_entry->enclosure_id
1198 dpm_entry->DeviceIndex =
1199 (U16)et_entry->start_index;
1200 dpm_entry->MappingInformation =
1201 et_entry->num_slots;
1202 dpm_entry->MappingInformation
1204 dpm_entry->PhysicalBitsMapping
1205 = et_entry->phy_bits;
1206 et_entry->dpm_entry_num =
1208 /* FIXME Do I need to set the dpm_idxin mt_entry too */
1209 sc->dpm_entry_used[dpm_idx] = 1;
1210 sc->dpm_flush_entry[dpm_idx] =
1212 phy_change->is_processed = 1;
1214 phy_change->is_processed = 1;
1215 kprintf("%s: failed to add the "
1216 "device with handle 0x%04x "
1217 "to persistent table "
1218 "because there is no free "
1219 "space available\n",
1221 phy_change->dev_handle);
1224 et_entry->dpm_entry_num = dpm_idx;
1225 mt_entry->dpm_entry_num = dpm_idx;
1228 /* FIXME Why not mt_entry too? */
1229 et_entry->init_complete = 1;
1230 } else if ((ioc_pg8_flags &
1231 MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1232 MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
1233 map_idx = _mapping_get_mt_idx_from_id
1234 (sc, phy_change->physical_id);
1235 if (map_idx == MPS_MAPTABLE_BAD_IDX) {
1236 search_idx = sc->num_rsvd_entries;
1237 if (topo_change->exp_handle)
1238 search_idx += max_num_phy_ids;
1239 map_idx = _mapping_get_free_mt_idx(sc,
1242 if (map_idx == MPS_MAPTABLE_BAD_IDX) {
1243 map_idx = _mapping_get_high_missing_mt_idx(sc);
1244 if (map_idx != MPS_MAPTABLE_BAD_IDX) {
1245 mt_entry = &sc->mapping_table[map_idx];
1246 if (mt_entry->dev_handle) {
1247 _mapping_add_to_removal_table
1248 (sc, mt_entry->dev_handle,
1252 mt_entry->init_complete = 0;
1255 if (map_idx != MPS_MAPTABLE_BAD_IDX) {
1256 mt_entry = &sc->mapping_table[map_idx];
1257 mt_entry->physical_id = phy_change->physical_id;
1258 mt_entry->channel = 0;
1259 mt_entry->id = map_idx;
1260 mt_entry->dev_handle = phy_change->dev_handle;
1261 mt_entry->missing_count = 0;
1262 mt_entry->device_info = phy_change->device_info
1263 | (MPS_DEV_RESERVED | MPS_MAP_IN_USE);
1265 phy_change->is_processed = 1;
1266 if (!sc->mt_full_retry) {
1267 sc->mt_add_device_failed = 1;
1270 kprintf("%s: failed to add the device with "
1271 "handle 0x%04x because there is no free "
1272 "space available in the mapping table\n",
1273 __func__, phy_change->dev_handle);
1276 if (sc->is_dpm_enable) {
1277 if (mt_entry->dpm_entry_num !=
1279 dpm_idx = mt_entry->dpm_entry_num;
1280 dpm_entry = (Mpi2DriverMap0Entry_t *)
1281 ((u8 *)sc->dpm_pg0 + hdr_sz);
1282 dpm_entry += dpm_idx;
1283 missing_cnt = dpm_entry->
1284 MappingInformation &
1285 MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
1286 temp64_var = dpm_entry->
1287 PhysicalIdentifier.High;
1288 temp64_var = (temp64_var << 32) |
1289 dpm_entry->PhysicalIdentifier.Low;
1290 if ((mt_entry->physical_id ==
1291 temp64_var) && !missing_cnt)
1292 mt_entry->init_complete = 1;
1294 dpm_idx = _mapping_get_free_dpm_idx(sc);
1295 mt_entry->init_complete = 0;
1297 if (dpm_idx != MPS_DPM_BAD_IDX &&
1298 !mt_entry->init_complete) {
1299 mt_entry->init_complete = 1;
1300 mt_entry->dpm_entry_num = dpm_idx;
1301 dpm_entry = (Mpi2DriverMap0Entry_t *)
1302 ((u8 *)sc->dpm_pg0 + hdr_sz);
1303 dpm_entry += dpm_idx;
1304 dpm_entry->PhysicalIdentifier.Low =
1306 mt_entry->physical_id);
1307 dpm_entry->PhysicalIdentifier.High =
1308 (mt_entry->physical_id >> 32);
1309 dpm_entry->DeviceIndex = (U16) map_idx;
1310 dpm_entry->MappingInformation = 0;
1311 dpm_entry->PhysicalBitsMapping = 0;
1312 sc->dpm_entry_used[dpm_idx] = 1;
1313 sc->dpm_flush_entry[dpm_idx] = 1;
1314 phy_change->is_processed = 1;
1315 } else if (dpm_idx == MPS_DPM_BAD_IDX) {
1316 phy_change->is_processed = 1;
1317 kprintf("%s: failed to add the "
1318 "device with handle 0x%04x "
1319 "to persistent table "
1320 "because there is no free "
1321 "space available\n",
1323 phy_change->dev_handle);
1326 mt_entry->init_complete = 1;
1329 phy_change->is_processed = 1;
1332 _mapping_clear_removed_entries(sc);
1336 * _mapping_flush_dpm_pages -Flush the DPM pages to NVRAM
1337 * @sc: per adapter object
1342 _mapping_flush_dpm_pages(struct mps_softc *sc)
1344 Mpi2DriverMap0Entry_t *dpm_entry;
1345 Mpi2ConfigReply_t mpi_reply;
1346 Mpi2DriverMappingPage0_t config_page;
1349 for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) {
1350 if (!sc->dpm_flush_entry[entry_num])
1352 memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
1353 memcpy(&config_page.Header, (u8 *)sc->dpm_pg0,
1354 sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1355 dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
1356 sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1357 dpm_entry += entry_num;
1358 dpm_entry->MappingInformation = htole16(dpm_entry->
1359 MappingInformation);
1360 dpm_entry->DeviceIndex = htole16(dpm_entry->DeviceIndex);
1361 dpm_entry->PhysicalBitsMapping = htole32(dpm_entry->
1362 PhysicalBitsMapping);
1363 memcpy(&config_page.Entry, (u8 *)dpm_entry,
1364 sizeof(Mpi2DriverMap0Entry_t));
1365 /* TODO-How to handle failed writes? */
1366 if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
1368 kprintf("%s: write of dpm entry %d for device failed\n",
1369 __func__, entry_num);
1371 sc->dpm_flush_entry[entry_num] = 0;
1372 dpm_entry->MappingInformation = le16toh(dpm_entry->
1373 MappingInformation);
1374 dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
1375 dpm_entry->PhysicalBitsMapping = le32toh(dpm_entry->
1376 PhysicalBitsMapping);
1381 * _mapping_allocate_memory- allocates the memory required for mapping tables
1382 * @sc: per adapter object
1384 * Allocates the memory for all the tables required for host mapping
1386 * Return 0 on success or non-zero on failure.
1389 mps_mapping_allocate_memory(struct mps_softc *sc)
1391 uint32_t dpm_pg0_sz;
1393 sc->mapping_table = kmalloc((sizeof(struct dev_mapping_table) *
1394 sc->max_devices), M_MPT2, M_ZERO|M_INTWAIT);
1395 if (!sc->mapping_table)
1396 goto free_resources;
1398 sc->removal_table = kmalloc((sizeof(struct map_removal_table) *
1399 sc->max_devices), M_MPT2, M_ZERO|M_INTWAIT);
1400 if (!sc->removal_table)
1401 goto free_resources;
1403 sc->enclosure_table = kmalloc((sizeof(struct enc_mapping_table) *
1404 sc->max_enclosures), M_MPT2, M_ZERO|M_INTWAIT);
1405 if (!sc->enclosure_table)
1406 goto free_resources;
1408 sc->dpm_entry_used = kmalloc((sizeof(u8) * sc->max_dpm_entries),
1409 M_MPT2, M_ZERO|M_INTWAIT);
1410 if (!sc->dpm_entry_used)
1411 goto free_resources;
1413 sc->dpm_flush_entry = kmalloc((sizeof(u8) * sc->max_dpm_entries),
1414 M_MPT2, M_ZERO|M_INTWAIT);
1415 if (!sc->dpm_flush_entry)
1416 goto free_resources;
1418 dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) +
1419 (sc->max_dpm_entries * sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY));
1421 sc->dpm_pg0 = kmalloc(dpm_pg0_sz, M_MPT2, M_ZERO|M_INTWAIT);
1423 kprintf("%s: memory alloc failed for dpm page; disabling dpm\n",
1425 sc->is_dpm_enable = 0;
1431 kfree(sc->mapping_table, M_MPT2);
1432 kfree(sc->removal_table, M_MPT2);
1433 kfree(sc->enclosure_table, M_MPT2);
1434 kfree(sc->dpm_entry_used, M_MPT2);
1435 kfree(sc->dpm_flush_entry, M_MPT2);
1436 kfree(sc->dpm_pg0, M_MPT2);
1437 kprintf("%s: device initialization failed due to failure in mapping "
1438 "table memory allocation\n", __func__);
1443 * mps_mapping_free_memory- frees the memory allocated for mapping tables
1444 * @sc: per adapter object
1449 mps_mapping_free_memory(struct mps_softc *sc)
1451 kfree(sc->mapping_table, M_MPT2);
1452 kfree(sc->removal_table, M_MPT2);
1453 kfree(sc->enclosure_table, M_MPT2);
1454 kfree(sc->dpm_entry_used, M_MPT2);
1455 kfree(sc->dpm_flush_entry, M_MPT2);
1456 kfree(sc->dpm_pg0, M_MPT2);
1461 _mapping_process_dpm_pg0(struct mps_softc *sc)
1463 u8 missing_cnt, enc_idx;
1464 u16 slot_id, entry_num, num_slots;
1465 u32 map_idx, dev_idx, start_idx, end_idx;
1466 struct dev_mapping_table *mt_entry;
1467 Mpi2DriverMap0Entry_t *dpm_entry;
1468 u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1469 u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
1470 struct enc_mapping_table *et_entry;
1474 start_idx = 0; /* avoid gcc warnings */
1475 end_idx = 0; /* avoid gcc warnings */
1476 if (sc->ir_firmware)
1477 _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
1479 dpm_entry = (Mpi2DriverMap0Entry_t *) ((uint8_t *) sc->dpm_pg0 +
1480 sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1481 for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++,
1483 physical_id = dpm_entry->PhysicalIdentifier.High;
1484 physical_id = (physical_id << 32) |
1485 dpm_entry->PhysicalIdentifier.Low;
1487 sc->dpm_entry_used[entry_num] = 0;
1490 sc->dpm_entry_used[entry_num] = 1;
1491 dpm_entry->MappingInformation = le16toh(dpm_entry->
1492 MappingInformation);
1493 missing_cnt = dpm_entry->MappingInformation &
1494 MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
1495 dev_idx = le16toh(dpm_entry->DeviceIndex);
1496 phy_bits = le32toh(dpm_entry->PhysicalBitsMapping);
1497 if (sc->ir_firmware && (dev_idx >= start_idx) &&
1498 (dev_idx <= end_idx)) {
1499 mt_entry = &sc->mapping_table[dev_idx];
1500 mt_entry->physical_id = dpm_entry->PhysicalIdentifier.High;
1501 mt_entry->physical_id = (mt_entry->physical_id << 32) |
1502 dpm_entry->PhysicalIdentifier.Low;
1503 mt_entry->channel = MPS_RAID_CHANNEL;
1504 mt_entry->id = dev_idx;
1505 mt_entry->missing_count = missing_cnt;
1506 mt_entry->dpm_entry_num = entry_num;
1507 mt_entry->device_info = MPS_DEV_RESERVED;
1510 if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1511 MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1512 if (dev_idx < (sc->num_rsvd_entries +
1516 MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1)
1518 num_slots = max_num_phy_ids;
1521 num_slots = dpm_entry->MappingInformation &
1522 MPI2_DRVMAP0_MAPINFO_SLOT_MASK;
1523 num_slots >>= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
1525 enc_idx = sc->num_enc_table_entries;
1526 if (enc_idx >= sc->max_enclosures) {
1527 kprintf("%s: enclosure entries exceed max "
1528 "enclosures of %d\n", __func__,
1529 sc->max_enclosures);
1532 sc->num_enc_table_entries++;
1533 et_entry = &sc->enclosure_table[enc_idx];
1534 physical_id = dpm_entry->PhysicalIdentifier.High;
1535 et_entry->enclosure_id = (physical_id << 32) |
1536 dpm_entry->PhysicalIdentifier.Low;
1537 et_entry->start_index = dev_idx;
1538 et_entry->dpm_entry_num = entry_num;
1539 et_entry->num_slots = num_slots;
1540 et_entry->start_slot = slot_id;
1541 et_entry->missing_count = missing_cnt;
1542 et_entry->phy_bits = phy_bits;
1544 mt_entry = &sc->mapping_table[dev_idx];
1545 for (map_idx = dev_idx; map_idx < (dev_idx + num_slots);
1546 map_idx++, mt_entry++) {
1547 if (mt_entry->dpm_entry_num !=
1549 kprintf("%s: conflict in mapping table "
1550 "for enclosure %d\n", __func__,
1554 physical_id = dpm_entry->PhysicalIdentifier.High;
1555 mt_entry->physical_id = (physical_id << 32) |
1556 dpm_entry->PhysicalIdentifier.Low;
1557 mt_entry->phy_bits = phy_bits;
1558 mt_entry->channel = 0;
1559 mt_entry->id = dev_idx;
1560 mt_entry->dpm_entry_num = entry_num;
1561 mt_entry->missing_count = missing_cnt;
1562 mt_entry->device_info = MPS_DEV_RESERVED;
1564 } else if ((ioc_pg8_flags &
1565 MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1566 MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
1568 mt_entry = &sc->mapping_table[map_idx];
1569 if (mt_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
1570 kprintf("%s: conflict in mapping table for "
1571 "device %d\n", __func__, map_idx);
1574 physical_id = dpm_entry->PhysicalIdentifier.High;
1575 mt_entry->physical_id = (physical_id << 32) |
1576 dpm_entry->PhysicalIdentifier.Low;
1577 mt_entry->phy_bits = phy_bits;
1578 mt_entry->channel = 0;
1579 mt_entry->id = dev_idx;
1580 mt_entry->missing_count = missing_cnt;
1581 mt_entry->dpm_entry_num = entry_num;
1582 mt_entry->device_info = MPS_DEV_RESERVED;
1584 } /*close the loop for DPM table */
1588 * mps_mapping_check_devices - start of the day check for device availabilty
1589 * @sc: per adapter object
1590 * @sleep_flag: Flag indicating whether this function can sleep or not
1595 mps_mapping_check_devices(struct mps_softc *sc, int sleep_flag)
1600 struct dev_mapping_table *mt_entry;
1601 u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1602 struct enc_mapping_table *et_entry;
1603 u32 start_idx, end_idx;
1605 /* We need to ucomment this when this function is called
1606 * from the port enable complete */
1608 sc->track_mapping_events = 0;
1609 cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
1611 if (!sc->pending_map_events)
1613 if (sleep_flag == CAN_SLEEP)
1614 pause("mps_pause", (hz/1000));/* 1msec sleep */
1616 DELAY(500); /* 500 useconds delay */
1621 kprintf("%s: there are %d"
1622 " pending events after %d seconds of delay\n",
1623 __func__, sc->pending_map_events, timeout);
1625 sc->pending_map_events = 0;
1627 if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1628 MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1629 et_entry = sc->enclosure_table;
1630 for (i = 0; i < sc->num_enc_table_entries; i++, et_entry++) {
1631 if (!et_entry->init_complete) {
1632 if (et_entry->missing_count <
1633 MPS_MAX_MISSING_COUNT) {
1634 et_entry->missing_count++;
1635 if (et_entry->dpm_entry_num !=
1637 _mapping_commit_enc_entry(sc,
1640 et_entry->init_complete = 1;
1643 if (!sc->ir_firmware)
1645 _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
1646 mt_entry = &sc->mapping_table[start_idx];
1647 for (i = start_idx; i < (end_idx + 1); i++, mt_entry++) {
1648 if (mt_entry->device_info & MPS_DEV_RESERVED
1649 && !mt_entry->physical_id)
1650 mt_entry->init_complete = 1;
1651 else if (mt_entry->device_info & MPS_DEV_RESERVED) {
1652 if (!mt_entry->init_complete) {
1653 if (mt_entry->missing_count <
1654 MPS_MAX_MISSING_COUNT) {
1655 mt_entry->missing_count++;
1656 if (mt_entry->dpm_entry_num !=
1658 _mapping_commit_map_entry(sc,
1661 mt_entry->init_complete = 1;
1665 } else if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1666 MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
1667 mt_entry = sc->mapping_table;
1668 for (i = 0; i < sc->max_devices; i++, mt_entry++) {
1669 if (mt_entry->device_info & MPS_DEV_RESERVED
1670 && !mt_entry->physical_id)
1671 mt_entry->init_complete = 1;
1672 else if (mt_entry->device_info & MPS_DEV_RESERVED) {
1673 if (!mt_entry->init_complete) {
1674 if (mt_entry->missing_count <
1675 MPS_MAX_MISSING_COUNT) {
1676 mt_entry->missing_count++;
1677 if (mt_entry->dpm_entry_num !=
1679 _mapping_commit_map_entry(sc,
1682 mt_entry->init_complete = 1;
1691 * mps_mapping_is_reinit_required - check whether event replay required
1692 * @sc: per adapter object
1694 * Checks the per ioc flags and decide whether reinit of events required
1696 * Returns 1 for reinit of ioc 0 for not.
1698 int mps_mapping_is_reinit_required(struct mps_softc *sc)
1700 if (!sc->mt_full_retry && sc->mt_add_device_failed) {
1701 sc->mt_full_retry = 1;
1702 sc->mt_add_device_failed = 0;
1703 _mapping_flush_dpm_pages(sc);
1706 sc->mt_full_retry = 1;
1711 * mps_mapping_initialize - initialize mapping tables
1712 * @sc: per adapter object
1714 * Read controller persitant mapping tables into internal data area.
1716 * Return 0 for success or non-zero for failure.
1719 mps_mapping_initialize(struct mps_softc *sc)
1721 uint16_t volume_mapping_flags, dpm_pg0_sz;
1723 Mpi2ConfigReply_t mpi_reply;
1725 uint8_t retry_count;
1726 uint16_t ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1728 /* The additional 1 accounts for the virtual enclosure
1729 * created for the controller
1731 sc->max_enclosures = sc->facts->MaxEnclosures + 1;
1732 sc->max_expanders = sc->facts->MaxSasExpanders;
1733 sc->max_volumes = sc->facts->MaxVolumes;
1734 sc->max_devices = sc->facts->MaxTargets + sc->max_volumes;
1735 sc->pending_map_events = 0;
1736 sc->num_enc_table_entries = 0;
1737 sc->num_rsvd_entries = 0;
1738 sc->num_channels = 1;
1739 sc->max_dpm_entries = sc->ioc_pg8.MaxPersistentEntries;
1740 sc->is_dpm_enable = (sc->max_dpm_entries) ? 1 : 0;
1741 sc->track_mapping_events = 0;
1743 if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING)
1744 sc->is_dpm_enable = 0;
1746 if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
1747 sc->num_rsvd_entries = 1;
1749 volume_mapping_flags = sc->ioc_pg8.IRVolumeMappingFlags &
1750 MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
1751 if (sc->ir_firmware && (volume_mapping_flags ==
1752 MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING))
1753 sc->num_rsvd_entries += sc->max_volumes;
1755 error = mps_mapping_allocate_memory(sc);
1759 for (i = 0; i < sc->max_devices; i++)
1760 _mapping_clear_map_entry(sc->mapping_table + i);
1762 for (i = 0; i < sc->max_enclosures; i++)
1763 _mapping_clear_enc_entry(sc->enclosure_table + i);
1765 for (i = 0; i < sc->max_devices; i++) {
1766 sc->removal_table[i].dev_handle = 0;
1767 sc->removal_table[i].dpm_entry_num = MPS_DPM_BAD_IDX;
1770 memset(sc->dpm_entry_used, 0, sc->max_dpm_entries);
1771 memset(sc->dpm_flush_entry, 0, sc->max_dpm_entries);
1773 if (sc->is_dpm_enable) {
1774 dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) +
1775 (sc->max_dpm_entries *
1776 sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY));
1780 if (mps_config_get_dpm_pg0(sc, &mpi_reply, sc->dpm_pg0,
1782 kprintf("%s: dpm page read failed; disabling dpm\n",
1784 if (retry_count < 3) {
1786 goto retry_read_dpm;
1788 sc->is_dpm_enable = 0;
1792 if (sc->is_dpm_enable)
1793 _mapping_process_dpm_pg0(sc);
1795 sc->track_mapping_events = 1;
1800 * mps_mapping_exit - clear mapping table and associated memory
1801 * @sc: per adapter object
1806 mps_mapping_exit(struct mps_softc *sc)
1808 _mapping_flush_dpm_pages(sc);
1809 mps_mapping_free_memory(sc);
1813 * mps_mapping_get_sas_id - assign a target id for sas device
1814 * @sc: per adapter object
1815 * @sas_address: sas address of the device
1816 * @handle: device handle
1818 * Returns valid ID on success or BAD_ID.
1821 mps_mapping_get_sas_id(struct mps_softc *sc, uint64_t sas_address, u16 handle)
1824 struct dev_mapping_table *mt_entry;
1826 for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
1827 mt_entry = &sc->mapping_table[map_idx];
1828 if (mt_entry->dev_handle == handle && mt_entry->physical_id ==
1830 return mt_entry->id;
1833 return MPS_MAP_BAD_ID;
1837 * mps_mapping_get_sas_id_from_handle - find a target id in mapping table using
1838 * only the dev handle. This is just a wrapper function for the local function
1839 * _mapping_get_mt_idx_from_handle.
1840 * @sc: per adapter object
1841 * @handle: device handle
1843 * Returns valid ID on success or BAD_ID.
1846 mps_mapping_get_sas_id_from_handle(struct mps_softc *sc, u16 handle)
1848 return (_mapping_get_mt_idx_from_handle(sc, handle));
1852 * mps_mapping_get_raid_id - assign a target id for raid device
1853 * @sc: per adapter object
1854 * @wwid: world wide identifier for raid volume
1855 * @handle: device handle
1857 * Returns valid ID on success or BAD_ID.
1860 mps_mapping_get_raid_id(struct mps_softc *sc, u64 wwid, u16 handle)
1863 struct dev_mapping_table *mt_entry;
1865 for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
1866 mt_entry = &sc->mapping_table[map_idx];
1867 if (mt_entry->dev_handle == handle && mt_entry->physical_id ==
1869 return mt_entry->id;
1872 return MPS_MAP_BAD_ID;
1876 * mps_mapping_get_raid_id_from_handle - find raid device in mapping table
1877 * using only the volume dev handle. This is just a wrapper function for the
1878 * local function _mapping_get_ir_mt_idx_from_handle.
1879 * @sc: per adapter object
1880 * @volHandle: volume device handle
1882 * Returns valid ID on success or BAD_ID.
1885 mps_mapping_get_raid_id_from_handle(struct mps_softc *sc, u16 volHandle)
1887 return (_mapping_get_ir_mt_idx_from_handle(sc, volHandle));
1891 * mps_mapping_enclosure_dev_status_change_event - handle enclosure events
1892 * @sc: per adapter object
1893 * @event_data: event data payload
1898 mps_mapping_enclosure_dev_status_change_event(struct mps_softc *sc,
1899 Mpi2EventDataSasEnclDevStatusChange_t *event_data)
1901 u8 enc_idx, missing_count;
1902 struct enc_mapping_table *et_entry;
1903 Mpi2DriverMap0Entry_t *dpm_entry;
1904 u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1905 u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
1906 u8 update_phy_bits = 0;
1908 uint64_t temp64_var;
1910 if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) !=
1911 MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING)
1914 dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
1915 sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1917 if (event_data->ReasonCode == MPI2_EVENT_SAS_ENCL_RC_ADDED) {
1918 if (!event_data->NumSlots) {
1919 kprintf("%s: enclosure with handle = 0x%x reported 0 "
1920 "slots\n", __func__,
1921 le16toh(event_data->EnclosureHandle));
1924 temp64_var = event_data->EnclosureLogicalID.High;
1925 temp64_var = (temp64_var << 32) |
1926 event_data->EnclosureLogicalID.Low;
1927 enc_idx = _mapping_get_enc_idx_from_id(sc, temp64_var,
1928 event_data->PhyBits);
1929 if (enc_idx != MPS_ENCTABLE_BAD_IDX) {
1930 et_entry = &sc->enclosure_table[enc_idx];
1931 if (et_entry->init_complete &&
1932 !et_entry->missing_count) {
1933 kprintf("%s: enclosure %d is already present "
1934 "with handle = 0x%x\n",__func__, enc_idx,
1935 et_entry->enc_handle);
1938 et_entry->enc_handle = le16toh(event_data->
1940 et_entry->start_slot = le16toh(event_data->StartSlot);
1941 saved_phy_bits = et_entry->phy_bits;
1942 et_entry->phy_bits |= le32toh(event_data->PhyBits);
1943 if (saved_phy_bits != et_entry->phy_bits)
1944 update_phy_bits = 1;
1945 if (et_entry->missing_count || update_phy_bits) {
1946 et_entry->missing_count = 0;
1947 if (sc->is_dpm_enable &&
1948 et_entry->dpm_entry_num !=
1950 dpm_entry += et_entry->dpm_entry_num;
1952 (u8)(dpm_entry->MappingInformation &
1953 MPI2_DRVMAP0_MAPINFO_MISSING_MASK);
1954 if (!et_entry->init_complete && (
1955 missing_count || update_phy_bits)) {
1956 dpm_entry->MappingInformation
1957 = et_entry->num_slots;
1958 dpm_entry->MappingInformation
1960 dpm_entry->PhysicalBitsMapping
1961 = et_entry->phy_bits;
1962 sc->dpm_flush_entry[et_entry->
1968 enc_idx = sc->num_enc_table_entries;
1969 if (enc_idx >= sc->max_enclosures) {
1970 kprintf("%s: enclosure can not be added; "
1971 "mapping table is full\n", __func__);
1974 sc->num_enc_table_entries++;
1975 et_entry = &sc->enclosure_table[enc_idx];
1976 et_entry->enc_handle = le16toh(event_data->
1978 et_entry->enclosure_id = event_data->
1979 EnclosureLogicalID.High;
1980 et_entry->enclosure_id = ( et_entry->enclosure_id <<
1981 32) | event_data->EnclosureLogicalID.Low;
1982 et_entry->start_index = MPS_MAPTABLE_BAD_IDX;
1983 et_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
1984 et_entry->num_slots = le16toh(event_data->NumSlots);
1985 et_entry->start_slot = le16toh(event_data->StartSlot);
1986 et_entry->phy_bits = le32toh(event_data->PhyBits);
1988 et_entry->init_complete = 1;
1989 } else if (event_data->ReasonCode ==
1990 MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING) {
1991 enc_idx = _mapping_get_enc_idx_from_handle(sc,
1992 le16toh(event_data->EnclosureHandle));
1993 if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
1994 kprintf("%s: cannot unmap enclosure %d because it has "
1995 "already been deleted", __func__, enc_idx);
1998 et_entry = &sc->enclosure_table[enc_idx];
1999 if (!et_entry->init_complete) {
2000 if (et_entry->missing_count < MPS_MAX_MISSING_COUNT)
2001 et_entry->missing_count++;
2003 et_entry->init_complete = 1;
2005 if (!et_entry->missing_count)
2006 et_entry->missing_count++;
2007 if (sc->is_dpm_enable && !et_entry->init_complete &&
2008 et_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
2009 dpm_entry += et_entry->dpm_entry_num;
2010 dpm_entry->MappingInformation = et_entry->num_slots;
2011 dpm_entry->MappingInformation <<= map_shift;
2012 dpm_entry->MappingInformation |=
2013 et_entry->missing_count;
2014 sc->dpm_flush_entry[et_entry->dpm_entry_num] = 1;
2016 et_entry->init_complete = 1;
2020 _mapping_flush_dpm_pages(sc);
2021 if (sc->pending_map_events)
2022 sc->pending_map_events--;
2026 * mps_mapping_topology_change_event - handle topology change events
2027 * @sc: per adapter object
2028 * @event_data: event data payload
2033 mps_mapping_topology_change_event(struct mps_softc *sc,
2034 Mpi2EventDataSasTopologyChangeList_t *event_data)
2036 struct _map_topology_change topo_change;
2037 struct _map_phy_change *phy_change;
2038 Mpi2EventSasTopoPhyEntry_t *event_phy_change;
2041 topo_change.enc_handle = le16toh(event_data->EnclosureHandle);
2042 topo_change.exp_handle = le16toh(event_data->ExpanderDevHandle);
2043 num_entries = event_data->NumEntries;
2044 topo_change.num_entries = num_entries;
2045 topo_change.start_phy_num = event_data->StartPhyNum;
2046 topo_change.num_phys = event_data->NumPhys;
2047 topo_change.exp_status = event_data->ExpStatus;
2048 event_phy_change = event_data->PHY;
2049 topo_change.phy_details = NULL;
2053 phy_change = kmalloc(sizeof(struct _map_phy_change) * num_entries,
2054 M_MPT2, M_INTWAIT|M_ZERO);
2055 topo_change.phy_details = phy_change;
2058 for (i = 0; i < num_entries; i++, event_phy_change++, phy_change++) {
2059 phy_change->dev_handle = le16toh(event_phy_change->
2061 phy_change->reason = event_phy_change->PhyStatus &
2062 MPI2_EVENT_SAS_TOPO_RC_MASK;
2064 _mapping_update_missing_count(sc, &topo_change);
2065 _mapping_get_dev_info(sc, &topo_change);
2066 _mapping_clear_removed_entries(sc);
2067 _mapping_add_new_device(sc, &topo_change);
2070 kfree(topo_change.phy_details, M_MPT2);
2071 _mapping_flush_dpm_pages(sc);
2072 if (sc->pending_map_events)
2073 sc->pending_map_events--;
2077 * _mapping_check_update_ir_mt_idx - Check and update IR map table index
2078 * @sc: per adapter object
2079 * @event_data: event data payload
2080 * @evt_idx: current event index
2081 * @map_idx: current index and the place holder for new map table index
2082 * @wwid_table: world wide name for volumes in the element table
2084 * pass through IR events and find whether any events matches and if so
2085 * tries to find new index if not returns failure
2087 * Returns 0 on success and 1 on failure
2090 _mapping_check_update_ir_mt_idx(struct mps_softc *sc,
2091 Mpi2EventDataIrConfigChangeList_t *event_data, int evt_idx, u32 *map_idx,
2094 struct dev_mapping_table *mt_entry;
2095 u32 st_idx, end_idx, mt_idx = *map_idx;
2097 Mpi2EventIrConfigElement_t *element;
2101 mt_entry = &sc->mapping_table[mt_idx];
2102 _mapping_get_ir_maprange(sc, &st_idx, &end_idx);
2105 for (i = evt_idx + 1; i < event_data->NumElements; i++) {
2106 element = (Mpi2EventIrConfigElement_t *)
2107 &event_data->ConfigElement[i];
2108 element_flags = le16toh(element->ElementFlags);
2109 if ((element_flags &
2110 MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK) !=
2111 MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT)
2113 if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_ADDED ||
2114 element->ReasonCode ==
2115 MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) {
2116 if (mt_entry->physical_id == wwid_table[i]) {
2126 if (mt_idx > end_idx)
2128 mt_entry = &sc->mapping_table[mt_idx];
2129 } while (mt_entry->device_info & MPS_MAP_IN_USE);
2137 * mps_mapping_ir_config_change_event - handle IR config change list events
2138 * @sc: per adapter object
2139 * @event_data: event data payload
2144 mps_mapping_ir_config_change_event(struct mps_softc *sc,
2145 Mpi2EventDataIrConfigChangeList_t *event_data)
2147 Mpi2EventIrConfigElement_t *element;
2151 struct dev_mapping_table *mt_entry;
2153 u8 log_full_error = 0;
2155 wwid_table = kmalloc(sizeof(u64) * event_data->NumElements, M_MPT2,
2156 M_INTWAIT | M_ZERO);
2159 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
2160 flags = le32toh(event_data->Flags);
2161 for (i = 0; i < event_data->NumElements; i++, element++) {
2162 element_flags = le16toh(element->ElementFlags);
2163 if ((element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_ADDED) &&
2164 (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_REMOVED) &&
2165 (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE)
2166 && (element->ReasonCode !=
2167 MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED))
2169 if ((element_flags &
2170 MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK) ==
2171 MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT) {
2172 mps_config_get_volume_wwid(sc,
2173 le16toh(element->VolDevHandle), &wwid_table[i]);
2174 map_idx = _mapping_get_ir_mt_idx_from_wwid(sc,
2176 if (map_idx != MPS_MAPTABLE_BAD_IDX) {
2177 mt_entry = &sc->mapping_table[map_idx];
2178 mt_entry->device_info |= MPS_MAP_IN_USE;
2182 if (flags == MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
2185 element = (Mpi2EventIrConfigElement_t *)&event_data->
2187 for (i = 0; i < event_data->NumElements; i++, element++) {
2188 if (element->ReasonCode ==
2189 MPI2_EVENT_IR_CHANGE_RC_ADDED ||
2190 element->ReasonCode ==
2191 MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) {
2192 map_idx = _mapping_get_ir_mt_idx_from_wwid
2193 (sc, wwid_table[i]);
2194 if (map_idx != MPS_MAPTABLE_BAD_IDX) {
2195 mt_entry = &sc->mapping_table[map_idx];
2196 mt_entry->channel = MPS_RAID_CHANNEL;
2197 mt_entry->id = map_idx;
2198 mt_entry->dev_handle = le16toh
2199 (element->VolDevHandle);
2200 mt_entry->device_info =
2201 MPS_DEV_RESERVED | MPS_MAP_IN_USE;
2202 _mapping_update_ir_missing_cnt(sc,
2203 map_idx, element, wwid_table[i]);
2206 map_idx = _mapping_get_free_ir_mt_idx(sc);
2207 if (map_idx == MPS_MAPTABLE_BAD_IDX)
2209 else if (i < (event_data->NumElements - 1)) {
2211 _mapping_check_update_ir_mt_idx
2212 (sc, event_data, i, &map_idx,
2215 if (log_full_error) {
2216 kprintf("%s: no space to add the RAID "
2217 "volume with handle 0x%04x in "
2218 "mapping table\n", __func__, le16toh
2219 (element->VolDevHandle));
2222 mt_entry = &sc->mapping_table[map_idx];
2223 mt_entry->physical_id = wwid_table[i];
2224 mt_entry->channel = MPS_RAID_CHANNEL;
2225 mt_entry->id = map_idx;
2226 mt_entry->dev_handle = le16toh(element->
2228 mt_entry->device_info = MPS_DEV_RESERVED |
2230 mt_entry->init_complete = 0;
2231 _mapping_update_ir_missing_cnt(sc, map_idx,
2232 element, wwid_table[i]);
2233 } else if (element->ReasonCode ==
2234 MPI2_EVENT_IR_CHANGE_RC_REMOVED) {
2235 map_idx = _mapping_get_ir_mt_idx_from_wwid(sc,
2237 if (map_idx == MPS_MAPTABLE_BAD_IDX) {
2238 kprintf("%s: failed to remove a volume "
2239 "because it has already been "
2240 "removed\n", __func__);
2243 _mapping_update_ir_missing_cnt(sc, map_idx,
2244 element, wwid_table[i]);
2245 } else if (element->ReasonCode ==
2246 MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED) {
2247 map_idx = _mapping_get_mt_idx_from_handle(sc,
2248 le16toh(element->VolDevHandle));
2249 if (map_idx == MPS_MAPTABLE_BAD_IDX) {
2250 kprintf("%s: failed to remove volume "
2251 "with handle 0x%04x because it has "
2252 "already been removed\n", __func__,
2253 le16toh(element->VolDevHandle));
2256 mt_entry = &sc->mapping_table[map_idx];
2257 _mapping_update_ir_missing_cnt(sc, map_idx,
2258 element, mt_entry->physical_id);
2264 _mapping_flush_dpm_pages(sc);
2265 kfree(wwid_table, M_MPT2);
2266 if (sc->pending_map_events)
2267 sc->pending_map_events--;