1d043c564SKenneth D. Merry /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni *
4ef065d89SStephen McConnell * Copyright (c) 2011-2015 LSI Corp.
5ef065d89SStephen McConnell * Copyright (c) 2013-2015 Avago Technologies
6d043c564SKenneth D. Merry * All rights reserved.
7d043c564SKenneth D. Merry *
8d043c564SKenneth D. Merry * Redistribution and use in source and binary forms, with or without
9d043c564SKenneth D. Merry * modification, are permitted provided that the following conditions
10d043c564SKenneth D. Merry * are met:
11d043c564SKenneth D. Merry * 1. Redistributions of source code must retain the above copyright
12d043c564SKenneth D. Merry * notice, this list of conditions and the following disclaimer.
13d043c564SKenneth D. Merry * 2. Redistributions in binary form must reproduce the above copyright
14d043c564SKenneth D. Merry * notice, this list of conditions and the following disclaimer in the
15d043c564SKenneth D. Merry * documentation and/or other materials provided with the distribution.
16d043c564SKenneth D. Merry *
17d043c564SKenneth D. Merry * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18d043c564SKenneth D. Merry * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19d043c564SKenneth D. Merry * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20d043c564SKenneth D. Merry * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21d043c564SKenneth D. Merry * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22d043c564SKenneth D. Merry * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23d043c564SKenneth D. Merry * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24d043c564SKenneth D. Merry * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25d043c564SKenneth D. Merry * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26d043c564SKenneth D. Merry * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27d043c564SKenneth D. Merry * SUCH DAMAGE.
28d043c564SKenneth D. Merry *
29ef065d89SStephen McConnell * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
30d043c564SKenneth D. Merry */
31d043c564SKenneth D. Merry
32d043c564SKenneth D. Merry #include <sys/cdefs.h>
33d043c564SKenneth D. Merry /* TODO Move headers to mpsvar */
34d043c564SKenneth D. Merry #include <sys/types.h>
35d043c564SKenneth D. Merry #include <sys/param.h>
36d043c564SKenneth D. Merry #include <sys/lock.h>
37d043c564SKenneth D. Merry #include <sys/mutex.h>
38d043c564SKenneth D. Merry #include <sys/systm.h>
39d043c564SKenneth D. Merry #include <sys/kernel.h>
40d043c564SKenneth D. Merry #include <sys/malloc.h>
41d043c564SKenneth D. Merry #include <sys/kthread.h>
42d043c564SKenneth D. Merry #include <sys/taskqueue.h>
43d043c564SKenneth D. Merry #include <sys/bus.h>
44d043c564SKenneth D. Merry #include <sys/endian.h>
45d043c564SKenneth D. Merry #include <sys/sysctl.h>
46ee5c196bSScott Long #include <sys/sbuf.h>
47d043c564SKenneth D. Merry #include <sys/eventhandler.h>
48d043c564SKenneth D. Merry #include <sys/uio.h>
49d043c564SKenneth D. Merry #include <machine/bus.h>
50d043c564SKenneth D. Merry #include <machine/resource.h>
51d043c564SKenneth D. Merry #include <dev/mps/mpi/mpi2_type.h>
52d043c564SKenneth D. Merry #include <dev/mps/mpi/mpi2.h>
53d043c564SKenneth D. Merry #include <dev/mps/mpi/mpi2_ioc.h>
54d043c564SKenneth D. Merry #include <dev/mps/mpi/mpi2_sas.h>
55d043c564SKenneth D. Merry #include <dev/mps/mpi/mpi2_cnfg.h>
56d043c564SKenneth D. Merry #include <dev/mps/mpi/mpi2_init.h>
57d043c564SKenneth D. Merry #include <dev/mps/mpi/mpi2_tool.h>
58d043c564SKenneth D. Merry #include <dev/mps/mps_ioctl.h>
59d043c564SKenneth D. Merry #include <dev/mps/mpsvar.h>
60d043c564SKenneth D. Merry #include <dev/mps/mps_mapping.h>
61d043c564SKenneth D. Merry
62d043c564SKenneth D. Merry /**
63635e58c7SStephen McConnell * _mapping_clear_map_entry - Clear a particular mapping entry.
64d043c564SKenneth D. Merry * @map_entry: map table entry
65d043c564SKenneth D. Merry *
66d043c564SKenneth D. Merry * Returns nothing.
67d043c564SKenneth D. Merry */
68d043c564SKenneth D. Merry static inline void
_mapping_clear_map_entry(struct dev_mapping_table * map_entry)69d043c564SKenneth D. Merry _mapping_clear_map_entry(struct dev_mapping_table *map_entry)
70d043c564SKenneth D. Merry {
71d043c564SKenneth D. Merry map_entry->physical_id = 0;
72d043c564SKenneth D. Merry map_entry->device_info = 0;
73d043c564SKenneth D. Merry map_entry->phy_bits = 0;
74d043c564SKenneth D. Merry map_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
75d043c564SKenneth D. Merry map_entry->dev_handle = 0;
76d043c564SKenneth D. Merry map_entry->id = -1;
77d043c564SKenneth D. Merry map_entry->missing_count = 0;
78d043c564SKenneth D. Merry map_entry->init_complete = 0;
79d043c564SKenneth D. Merry map_entry->TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR;
80d043c564SKenneth D. Merry }
81d043c564SKenneth D. Merry
82d043c564SKenneth D. Merry /**
83d043c564SKenneth D. Merry * _mapping_clear_enc_entry - Clear a particular enclosure table entry.
84d043c564SKenneth D. Merry * @enc_entry: enclosure table entry
85d043c564SKenneth D. Merry *
86d043c564SKenneth D. Merry * Returns nothing.
87d043c564SKenneth D. Merry */
88d043c564SKenneth D. Merry static inline void
_mapping_clear_enc_entry(struct enc_mapping_table * enc_entry)89d043c564SKenneth D. Merry _mapping_clear_enc_entry(struct enc_mapping_table *enc_entry)
90d043c564SKenneth D. Merry {
91d043c564SKenneth D. Merry enc_entry->enclosure_id = 0;
92d043c564SKenneth D. Merry enc_entry->start_index = MPS_MAPTABLE_BAD_IDX;
93d043c564SKenneth D. Merry enc_entry->phy_bits = 0;
94d043c564SKenneth D. Merry enc_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
95d043c564SKenneth D. Merry enc_entry->enc_handle = 0;
96d043c564SKenneth D. Merry enc_entry->num_slots = 0;
97d043c564SKenneth D. Merry enc_entry->start_slot = 0;
98d043c564SKenneth D. Merry enc_entry->missing_count = 0;
99d043c564SKenneth D. Merry enc_entry->removal_flag = 0;
100d043c564SKenneth D. Merry enc_entry->skip_search = 0;
101d043c564SKenneth D. Merry enc_entry->init_complete = 0;
102d043c564SKenneth D. Merry }
103d043c564SKenneth D. Merry
104d043c564SKenneth D. Merry /**
105d043c564SKenneth D. Merry * _mapping_commit_enc_entry - write a particular enc entry in DPM page0.
106d043c564SKenneth D. Merry * @sc: per adapter object
107d043c564SKenneth D. Merry * @enc_entry: enclosure table entry
108d043c564SKenneth D. Merry *
109d043c564SKenneth D. Merry * Returns 0 for success, non-zero for failure.
110d043c564SKenneth D. Merry */
111d043c564SKenneth D. Merry static int
_mapping_commit_enc_entry(struct mps_softc * sc,struct enc_mapping_table * et_entry)112d043c564SKenneth D. Merry _mapping_commit_enc_entry(struct mps_softc *sc,
113d043c564SKenneth D. Merry struct enc_mapping_table *et_entry)
114d043c564SKenneth D. Merry {
115d043c564SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry;
116d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry;
117d043c564SKenneth D. Merry Mpi2ConfigReply_t mpi_reply;
118d043c564SKenneth D. Merry Mpi2DriverMappingPage0_t config_page;
119d043c564SKenneth D. Merry
120d043c564SKenneth D. Merry if (!sc->is_dpm_enable)
121d043c564SKenneth D. Merry return 0;
122d043c564SKenneth D. Merry
123d043c564SKenneth D. Merry memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
124d043c564SKenneth D. Merry memcpy(&config_page.Header, (u8 *) sc->dpm_pg0,
125d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
126d043c564SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
127d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
128d043c564SKenneth D. Merry dpm_entry += et_entry->dpm_entry_num;
129d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low =
130d043c564SKenneth D. Merry ( 0xFFFFFFFF & et_entry->enclosure_id);
131d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.High =
132d043c564SKenneth D. Merry ( et_entry->enclosure_id >> 32);
133d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[et_entry->start_index];
134d043c564SKenneth D. Merry dpm_entry->DeviceIndex = htole16(mt_entry->id);
135d043c564SKenneth D. Merry dpm_entry->MappingInformation = et_entry->num_slots;
136d043c564SKenneth D. Merry dpm_entry->MappingInformation <<= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
137d043c564SKenneth D. Merry dpm_entry->MappingInformation |= et_entry->missing_count;
138d043c564SKenneth D. Merry dpm_entry->MappingInformation = htole16(dpm_entry->MappingInformation);
139d043c564SKenneth D. Merry dpm_entry->PhysicalBitsMapping = htole32(et_entry->phy_bits);
140d043c564SKenneth D. Merry dpm_entry->Reserved1 = 0;
141d043c564SKenneth D. Merry
142635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Writing DPM entry %d for enclosure.\n",
143635e58c7SStephen McConnell __func__, et_entry->dpm_entry_num);
144d043c564SKenneth D. Merry memcpy(&config_page.Entry, (u8 *)dpm_entry,
145d043c564SKenneth D. Merry sizeof(Mpi2DriverMap0Entry_t));
146d043c564SKenneth D. Merry if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
147d043c564SKenneth D. Merry et_entry->dpm_entry_num)) {
148635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Write of DPM "
149635e58c7SStephen McConnell "entry %d for enclosure failed.\n", __func__,
150635e58c7SStephen McConnell et_entry->dpm_entry_num);
151d043c564SKenneth D. Merry dpm_entry->MappingInformation = le16toh(dpm_entry->
152d043c564SKenneth D. Merry MappingInformation);
153d043c564SKenneth D. Merry dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
154d043c564SKenneth D. Merry dpm_entry->PhysicalBitsMapping =
155d043c564SKenneth D. Merry le32toh(dpm_entry->PhysicalBitsMapping);
156d043c564SKenneth D. Merry return -1;
157d043c564SKenneth D. Merry }
158d043c564SKenneth D. Merry dpm_entry->MappingInformation = le16toh(dpm_entry->
159d043c564SKenneth D. Merry MappingInformation);
160d043c564SKenneth D. Merry dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
161d043c564SKenneth D. Merry dpm_entry->PhysicalBitsMapping =
162d043c564SKenneth D. Merry le32toh(dpm_entry->PhysicalBitsMapping);
163d043c564SKenneth D. Merry return 0;
164d043c564SKenneth D. Merry }
165d043c564SKenneth D. Merry
166d043c564SKenneth D. Merry /**
167d043c564SKenneth D. Merry * _mapping_commit_map_entry - write a particular map table entry in DPM page0.
168d043c564SKenneth D. Merry * @sc: per adapter object
169635e58c7SStephen McConnell * @mt_entry: mapping table entry
170d043c564SKenneth D. Merry *
171d043c564SKenneth D. Merry * Returns 0 for success, non-zero for failure.
172d043c564SKenneth D. Merry */
173d043c564SKenneth D. Merry
174d043c564SKenneth D. Merry static int
_mapping_commit_map_entry(struct mps_softc * sc,struct dev_mapping_table * mt_entry)175d043c564SKenneth D. Merry _mapping_commit_map_entry(struct mps_softc *sc,
176d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry)
177d043c564SKenneth D. Merry {
178d043c564SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry;
179d043c564SKenneth D. Merry Mpi2ConfigReply_t mpi_reply;
180d043c564SKenneth D. Merry Mpi2DriverMappingPage0_t config_page;
181d043c564SKenneth D. Merry
182d043c564SKenneth D. Merry if (!sc->is_dpm_enable)
183d043c564SKenneth D. Merry return 0;
184d043c564SKenneth D. Merry
185635e58c7SStephen McConnell /*
186635e58c7SStephen McConnell * It's possible that this Map Entry points to a BAD DPM index. This
187635e58c7SStephen McConnell * can happen if the Map Entry is a for a missing device and the DPM
188635e58c7SStephen McConnell * entry that was being used by this device is now being used by some
189635e58c7SStephen McConnell * new device. So, check for a BAD DPM index and just return if so.
190635e58c7SStephen McConnell */
191635e58c7SStephen McConnell if (mt_entry->dpm_entry_num == MPS_DPM_BAD_IDX) {
192635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: DPM entry location for target "
193635e58c7SStephen McConnell "%d is invalid. DPM will not be written.\n", __func__,
194635e58c7SStephen McConnell mt_entry->id);
195635e58c7SStephen McConnell return 0;
196635e58c7SStephen McConnell }
197635e58c7SStephen McConnell
198d043c564SKenneth D. Merry memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
199d043c564SKenneth D. Merry memcpy(&config_page.Header, (u8 *)sc->dpm_pg0,
200d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
201d043c564SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *) sc->dpm_pg0 +
202d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
203d043c564SKenneth D. Merry dpm_entry = dpm_entry + mt_entry->dpm_entry_num;
204d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low = (0xFFFFFFFF &
205d043c564SKenneth D. Merry mt_entry->physical_id);
206d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.High = (mt_entry->physical_id >> 32);
207d043c564SKenneth D. Merry dpm_entry->DeviceIndex = htole16(mt_entry->id);
208d043c564SKenneth D. Merry dpm_entry->MappingInformation = htole16(mt_entry->missing_count);
209d043c564SKenneth D. Merry dpm_entry->PhysicalBitsMapping = 0;
210d043c564SKenneth D. Merry dpm_entry->Reserved1 = 0;
211d043c564SKenneth D. Merry memcpy(&config_page.Entry, (u8 *)dpm_entry,
212d043c564SKenneth D. Merry sizeof(Mpi2DriverMap0Entry_t));
213635e58c7SStephen McConnell
214635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Writing DPM entry %d for target %d.\n",
215635e58c7SStephen McConnell __func__, mt_entry->dpm_entry_num, mt_entry->id);
216d043c564SKenneth D. Merry if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
217d043c564SKenneth D. Merry mt_entry->dpm_entry_num)) {
218635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Write of DPM "
219635e58c7SStephen McConnell "entry %d for target %d failed.\n", __func__,
220635e58c7SStephen McConnell mt_entry->dpm_entry_num, mt_entry->id);
221d043c564SKenneth D. Merry dpm_entry->MappingInformation = le16toh(dpm_entry->
222d043c564SKenneth D. Merry MappingInformation);
223d043c564SKenneth D. Merry dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
224d043c564SKenneth D. Merry return -1;
225d043c564SKenneth D. Merry }
226d043c564SKenneth D. Merry
227d043c564SKenneth D. Merry dpm_entry->MappingInformation = le16toh(dpm_entry->MappingInformation);
228d043c564SKenneth D. Merry dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
229d043c564SKenneth D. Merry return 0;
230d043c564SKenneth D. Merry }
231d043c564SKenneth D. Merry
232d043c564SKenneth D. Merry /**
233d043c564SKenneth D. Merry * _mapping_get_ir_maprange - get start and end index for IR map range.
234d043c564SKenneth D. Merry * @sc: per adapter object
235d043c564SKenneth D. Merry * @start_idx: place holder for start index
236d043c564SKenneth D. Merry * @end_idx: place holder for end index
237d043c564SKenneth D. Merry *
238d043c564SKenneth D. Merry * The IR volumes can be mapped either at start or end of the mapping table
239d043c564SKenneth D. Merry * this function gets the detail of where IR volume mapping starts and ends
240d043c564SKenneth D. Merry * in the device mapping table
241d043c564SKenneth D. Merry *
242d043c564SKenneth D. Merry * Returns nothing.
243d043c564SKenneth D. Merry */
244d043c564SKenneth D. Merry static void
_mapping_get_ir_maprange(struct mps_softc * sc,u32 * start_idx,u32 * end_idx)245d043c564SKenneth D. Merry _mapping_get_ir_maprange(struct mps_softc *sc, u32 *start_idx, u32 *end_idx)
246d043c564SKenneth D. Merry {
247d043c564SKenneth D. Merry u16 volume_mapping_flags;
248d043c564SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
249d043c564SKenneth D. Merry
250d043c564SKenneth D. Merry volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
251d043c564SKenneth D. Merry MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
252d043c564SKenneth D. Merry if (volume_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
253d043c564SKenneth D. Merry *start_idx = 0;
254d043c564SKenneth D. Merry if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
255d043c564SKenneth D. Merry *start_idx = 1;
256d043c564SKenneth D. Merry } else
257d043c564SKenneth D. Merry *start_idx = sc->max_devices - sc->max_volumes;
258d043c564SKenneth D. Merry *end_idx = *start_idx + sc->max_volumes - 1;
259d043c564SKenneth D. Merry }
260d043c564SKenneth D. Merry
261d043c564SKenneth D. Merry /**
262d043c564SKenneth D. Merry * _mapping_get_enc_idx_from_id - get enclosure index from enclosure ID
263d043c564SKenneth D. Merry * @sc: per adapter object
264d043c564SKenneth D. Merry * @enc_id: enclosure logical identifier
265d043c564SKenneth D. Merry *
266d043c564SKenneth D. Merry * Returns the index of enclosure entry on success or bad index.
267d043c564SKenneth D. Merry */
268d043c564SKenneth D. Merry static u8
_mapping_get_enc_idx_from_id(struct mps_softc * sc,u64 enc_id,u64 phy_bits)269d043c564SKenneth D. Merry _mapping_get_enc_idx_from_id(struct mps_softc *sc, u64 enc_id,
270d043c564SKenneth D. Merry u64 phy_bits)
271d043c564SKenneth D. Merry {
272d043c564SKenneth D. Merry struct enc_mapping_table *et_entry;
273d043c564SKenneth D. Merry u8 enc_idx = 0;
274d043c564SKenneth D. Merry
275d043c564SKenneth D. Merry for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
276d043c564SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx];
277d043c564SKenneth D. Merry if ((et_entry->enclosure_id == le64toh(enc_id)) &&
278d043c564SKenneth D. Merry (!et_entry->phy_bits || (et_entry->phy_bits &
279d043c564SKenneth D. Merry le32toh(phy_bits))))
280d043c564SKenneth D. Merry return enc_idx;
281d043c564SKenneth D. Merry }
282d043c564SKenneth D. Merry return MPS_ENCTABLE_BAD_IDX;
283d043c564SKenneth D. Merry }
284d043c564SKenneth D. Merry
285d043c564SKenneth D. Merry /**
286d043c564SKenneth D. Merry * _mapping_get_enc_idx_from_handle - get enclosure index from handle
287d043c564SKenneth D. Merry * @sc: per adapter object
288d043c564SKenneth D. Merry * @enc_id: enclosure handle
289d043c564SKenneth D. Merry *
290d043c564SKenneth D. Merry * Returns the index of enclosure entry on success or bad index.
291d043c564SKenneth D. Merry */
292d043c564SKenneth D. Merry static u8
_mapping_get_enc_idx_from_handle(struct mps_softc * sc,u16 handle)293d043c564SKenneth D. Merry _mapping_get_enc_idx_from_handle(struct mps_softc *sc, u16 handle)
294d043c564SKenneth D. Merry {
295d043c564SKenneth D. Merry struct enc_mapping_table *et_entry;
296d043c564SKenneth D. Merry u8 enc_idx = 0;
297d043c564SKenneth D. Merry
298d043c564SKenneth D. Merry for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
299d043c564SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx];
300d043c564SKenneth D. Merry if (et_entry->missing_count)
301d043c564SKenneth D. Merry continue;
302d043c564SKenneth D. Merry if (et_entry->enc_handle == handle)
303d043c564SKenneth D. Merry return enc_idx;
304d043c564SKenneth D. Merry }
305d043c564SKenneth D. Merry return MPS_ENCTABLE_BAD_IDX;
306d043c564SKenneth D. Merry }
307d043c564SKenneth D. Merry
308d043c564SKenneth D. Merry /**
309d043c564SKenneth D. Merry * _mapping_get_high_missing_et_idx - get missing enclosure index
310d043c564SKenneth D. Merry * @sc: per adapter object
311d043c564SKenneth D. Merry *
312d043c564SKenneth D. Merry * Search through the enclosure table and identifies the enclosure entry
313d043c564SKenneth D. Merry * with high missing count and returns it's index
314d043c564SKenneth D. Merry *
315d043c564SKenneth D. Merry * Returns the index of enclosure entry on success or bad index.
316d043c564SKenneth D. Merry */
317d043c564SKenneth D. Merry static u8
_mapping_get_high_missing_et_idx(struct mps_softc * sc)318d043c564SKenneth D. Merry _mapping_get_high_missing_et_idx(struct mps_softc *sc)
319d043c564SKenneth D. Merry {
320d043c564SKenneth D. Merry struct enc_mapping_table *et_entry;
321d043c564SKenneth D. Merry u8 high_missing_count = 0;
322d043c564SKenneth D. Merry u8 enc_idx, high_idx = MPS_ENCTABLE_BAD_IDX;
323d043c564SKenneth D. Merry
324d043c564SKenneth D. Merry for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
325d043c564SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx];
326d043c564SKenneth D. Merry if ((et_entry->missing_count > high_missing_count) &&
327d043c564SKenneth D. Merry !et_entry->skip_search) {
328d043c564SKenneth D. Merry high_missing_count = et_entry->missing_count;
329d043c564SKenneth D. Merry high_idx = enc_idx;
330d043c564SKenneth D. Merry }
331d043c564SKenneth D. Merry }
332d043c564SKenneth D. Merry return high_idx;
333d043c564SKenneth D. Merry }
334d043c564SKenneth D. Merry
335d043c564SKenneth D. Merry /**
336d043c564SKenneth D. Merry * _mapping_get_high_missing_mt_idx - get missing map table index
337d043c564SKenneth D. Merry * @sc: per adapter object
338d043c564SKenneth D. Merry *
339d043c564SKenneth D. Merry * Search through the map table and identifies the device entry
340d043c564SKenneth D. Merry * with high missing count and returns it's index
341d043c564SKenneth D. Merry *
342d043c564SKenneth D. Merry * Returns the index of map table entry on success or bad index.
343d043c564SKenneth D. Merry */
344d043c564SKenneth D. Merry static u32
_mapping_get_high_missing_mt_idx(struct mps_softc * sc)345d043c564SKenneth D. Merry _mapping_get_high_missing_mt_idx(struct mps_softc *sc)
346d043c564SKenneth D. Merry {
347635e58c7SStephen McConnell u32 map_idx, high_idx = MPS_MAPTABLE_BAD_IDX;
348d043c564SKenneth D. Merry u8 high_missing_count = 0;
349d043c564SKenneth D. Merry u32 start_idx, end_idx, start_idx_ir, end_idx_ir;
350d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry;
351d043c564SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
352d043c564SKenneth D. Merry
353d043c564SKenneth D. Merry start_idx = 0;
3545d0b98f2SSteven Hartland start_idx_ir = 0;
3555d0b98f2SSteven Hartland end_idx_ir = 0;
356d043c564SKenneth D. Merry end_idx = sc->max_devices;
357d043c564SKenneth D. Merry if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
358d043c564SKenneth D. Merry start_idx = 1;
359e248a3d1SSteven Hartland if (sc->ir_firmware) {
360d043c564SKenneth D. Merry _mapping_get_ir_maprange(sc, &start_idx_ir, &end_idx_ir);
361d043c564SKenneth D. Merry if (start_idx == start_idx_ir)
362d043c564SKenneth D. Merry start_idx = end_idx_ir + 1;
363d043c564SKenneth D. Merry else
364d043c564SKenneth D. Merry end_idx = start_idx_ir;
365e248a3d1SSteven Hartland }
366d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[start_idx];
367d043c564SKenneth D. Merry for (map_idx = start_idx; map_idx < end_idx; map_idx++, mt_entry++) {
368d043c564SKenneth D. Merry if (mt_entry->missing_count > high_missing_count) {
369d043c564SKenneth D. Merry high_missing_count = mt_entry->missing_count;
370d043c564SKenneth D. Merry high_idx = map_idx;
371d043c564SKenneth D. Merry }
372d043c564SKenneth D. Merry }
373d043c564SKenneth D. Merry return high_idx;
374d043c564SKenneth D. Merry }
375d043c564SKenneth D. Merry
376d043c564SKenneth D. Merry /**
377d043c564SKenneth D. Merry * _mapping_get_ir_mt_idx_from_wwid - get map table index from volume WWID
378d043c564SKenneth D. Merry * @sc: per adapter object
379d043c564SKenneth D. Merry * @wwid: world wide unique ID of the volume
380d043c564SKenneth D. Merry *
381d043c564SKenneth D. Merry * Returns the index of map table entry on success or bad index.
382d043c564SKenneth D. Merry */
383d043c564SKenneth D. Merry static u32
_mapping_get_ir_mt_idx_from_wwid(struct mps_softc * sc,u64 wwid)384d043c564SKenneth D. Merry _mapping_get_ir_mt_idx_from_wwid(struct mps_softc *sc, u64 wwid)
385d043c564SKenneth D. Merry {
386d043c564SKenneth D. Merry u32 start_idx, end_idx, map_idx;
387d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry;
388d043c564SKenneth D. Merry
389d043c564SKenneth D. Merry _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
390d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[start_idx];
391d043c564SKenneth D. Merry for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
392d043c564SKenneth D. Merry if (mt_entry->physical_id == wwid)
393d043c564SKenneth D. Merry return map_idx;
394d043c564SKenneth D. Merry
395d043c564SKenneth D. Merry return MPS_MAPTABLE_BAD_IDX;
396d043c564SKenneth D. Merry }
397d043c564SKenneth D. Merry
398d043c564SKenneth D. Merry /**
399d043c564SKenneth D. Merry * _mapping_get_mt_idx_from_id - get map table index from a device ID
400d043c564SKenneth D. Merry * @sc: per adapter object
401d043c564SKenneth D. Merry * @dev_id: device identifer (SAS Address)
402d043c564SKenneth D. Merry *
403d043c564SKenneth D. Merry * Returns the index of map table entry on success or bad index.
404d043c564SKenneth D. Merry */
405d043c564SKenneth D. Merry static u32
_mapping_get_mt_idx_from_id(struct mps_softc * sc,u64 dev_id)406d043c564SKenneth D. Merry _mapping_get_mt_idx_from_id(struct mps_softc *sc, u64 dev_id)
407d043c564SKenneth D. Merry {
408d043c564SKenneth D. Merry u32 map_idx;
409d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry;
410d043c564SKenneth D. Merry
411d043c564SKenneth D. Merry for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
412d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx];
413d043c564SKenneth D. Merry if (mt_entry->physical_id == dev_id)
414d043c564SKenneth D. Merry return map_idx;
415d043c564SKenneth D. Merry }
416d043c564SKenneth D. Merry return MPS_MAPTABLE_BAD_IDX;
417d043c564SKenneth D. Merry }
418d043c564SKenneth D. Merry
419d043c564SKenneth D. Merry /**
420d043c564SKenneth D. Merry * _mapping_get_ir_mt_idx_from_handle - get map table index from volume handle
421d043c564SKenneth D. Merry * @sc: per adapter object
422d043c564SKenneth D. Merry * @wwid: volume device handle
423d043c564SKenneth D. Merry *
424d043c564SKenneth D. Merry * Returns the index of map table entry on success or bad index.
425d043c564SKenneth D. Merry */
426d043c564SKenneth D. Merry static u32
_mapping_get_ir_mt_idx_from_handle(struct mps_softc * sc,u16 volHandle)427d043c564SKenneth D. Merry _mapping_get_ir_mt_idx_from_handle(struct mps_softc *sc, u16 volHandle)
428d043c564SKenneth D. Merry {
429d043c564SKenneth D. Merry u32 start_idx, end_idx, map_idx;
430d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry;
431d043c564SKenneth D. Merry
432d043c564SKenneth D. Merry _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
433d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[start_idx];
434d043c564SKenneth D. Merry for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
435d043c564SKenneth D. Merry if (mt_entry->dev_handle == volHandle)
436d043c564SKenneth D. Merry return map_idx;
437d043c564SKenneth D. Merry
438d043c564SKenneth D. Merry return MPS_MAPTABLE_BAD_IDX;
439d043c564SKenneth D. Merry }
440d043c564SKenneth D. Merry
441d043c564SKenneth D. Merry /**
442d043c564SKenneth D. Merry * _mapping_get_mt_idx_from_handle - get map table index from handle
443d043c564SKenneth D. Merry * @sc: per adapter object
444d043c564SKenneth D. Merry * @dev_id: device handle
445d043c564SKenneth D. Merry *
446d043c564SKenneth D. Merry * Returns the index of map table entry on success or bad index.
447d043c564SKenneth D. Merry */
448d043c564SKenneth D. Merry static u32
_mapping_get_mt_idx_from_handle(struct mps_softc * sc,u16 handle)449d043c564SKenneth D. Merry _mapping_get_mt_idx_from_handle(struct mps_softc *sc, u16 handle)
450d043c564SKenneth D. Merry {
451d043c564SKenneth D. Merry u32 map_idx;
452d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry;
453d043c564SKenneth D. Merry
454d043c564SKenneth D. Merry for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
455d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx];
456d043c564SKenneth D. Merry if (mt_entry->dev_handle == handle)
457d043c564SKenneth D. Merry return map_idx;
458d043c564SKenneth D. Merry }
459d043c564SKenneth D. Merry return MPS_MAPTABLE_BAD_IDX;
460d043c564SKenneth D. Merry }
461d043c564SKenneth D. Merry
462d043c564SKenneth D. Merry /**
463d043c564SKenneth D. Merry * _mapping_get_free_ir_mt_idx - get first free index for a volume
464d043c564SKenneth D. Merry * @sc: per adapter object
465d043c564SKenneth D. Merry *
466d043c564SKenneth D. Merry * Search through mapping table for free index for a volume and if no free
467d043c564SKenneth D. Merry * index then looks for a volume with high mapping index
468d043c564SKenneth D. Merry *
469d043c564SKenneth D. Merry * Returns the index of map table entry on success or bad index.
470d043c564SKenneth D. Merry */
471d043c564SKenneth D. Merry static u32
_mapping_get_free_ir_mt_idx(struct mps_softc * sc)472d043c564SKenneth D. Merry _mapping_get_free_ir_mt_idx(struct mps_softc *sc)
473d043c564SKenneth D. Merry {
474d043c564SKenneth D. Merry u8 high_missing_count = 0;
475d043c564SKenneth D. Merry u32 start_idx, end_idx, map_idx;
476d043c564SKenneth D. Merry u32 high_idx = MPS_MAPTABLE_BAD_IDX;
477d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry;
478d043c564SKenneth D. Merry
479635e58c7SStephen McConnell /*
480635e58c7SStephen McConnell * The IN_USE flag should be clear if the entry is available to use.
481635e58c7SStephen McConnell * This flag is cleared on initialization and and when a volume is
482635e58c7SStephen McConnell * deleted. All other times this flag should be set. If, for some
483635e58c7SStephen McConnell * reason, a free entry cannot be found, look for the entry with the
484635e58c7SStephen McConnell * highest missing count just in case there is one.
485635e58c7SStephen McConnell */
486d043c564SKenneth D. Merry _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
487d043c564SKenneth D. Merry
488d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[start_idx];
489635e58c7SStephen McConnell for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) {
490d043c564SKenneth D. Merry if (!(mt_entry->device_info & MPS_MAP_IN_USE))
491d043c564SKenneth D. Merry return map_idx;
492d043c564SKenneth D. Merry
493d043c564SKenneth D. Merry if (mt_entry->missing_count > high_missing_count) {
494d043c564SKenneth D. Merry high_missing_count = mt_entry->missing_count;
495d043c564SKenneth D. Merry high_idx = map_idx;
496d043c564SKenneth D. Merry }
497d043c564SKenneth D. Merry }
498635e58c7SStephen McConnell
499635e58c7SStephen McConnell if (high_idx == MPS_MAPTABLE_BAD_IDX) {
500635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Could not find a "
501635e58c7SStephen McConnell "free entry in the mapping table for a Volume. The mapping "
502635e58c7SStephen McConnell "table is probably corrupt.\n", __func__);
503635e58c7SStephen McConnell }
504635e58c7SStephen McConnell
505d043c564SKenneth D. Merry return high_idx;
506d043c564SKenneth D. Merry }
507d043c564SKenneth D. Merry
508d043c564SKenneth D. Merry /**
509d043c564SKenneth D. Merry * _mapping_get_free_mt_idx - get first free index for a device
510d043c564SKenneth D. Merry * @sc: per adapter object
511d043c564SKenneth D. Merry * @start_idx: offset in the table to start search
512d043c564SKenneth D. Merry *
513d043c564SKenneth D. Merry * Returns the index of map table entry on success or bad index.
514d043c564SKenneth D. Merry */
515d043c564SKenneth D. Merry static u32
_mapping_get_free_mt_idx(struct mps_softc * sc,u32 start_idx)516d043c564SKenneth D. Merry _mapping_get_free_mt_idx(struct mps_softc *sc, u32 start_idx)
517d043c564SKenneth D. Merry {
518d043c564SKenneth D. Merry u32 map_idx, max_idx = sc->max_devices;
519d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry = &sc->mapping_table[start_idx];
520d043c564SKenneth D. Merry u16 volume_mapping_flags;
521d043c564SKenneth D. Merry
522d043c564SKenneth D. Merry volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
523d043c564SKenneth D. Merry MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
524d043c564SKenneth D. Merry if (sc->ir_firmware && (volume_mapping_flags ==
525d043c564SKenneth D. Merry MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING))
526d043c564SKenneth D. Merry max_idx -= sc->max_volumes;
527635e58c7SStephen McConnell
528d043c564SKenneth D. Merry for (map_idx = start_idx; map_idx < max_idx; map_idx++, mt_entry++)
529d043c564SKenneth D. Merry if (!(mt_entry->device_info & (MPS_MAP_IN_USE |
530d043c564SKenneth D. Merry MPS_DEV_RESERVED)))
531d043c564SKenneth D. Merry return map_idx;
532d043c564SKenneth D. Merry
533d043c564SKenneth D. Merry return MPS_MAPTABLE_BAD_IDX;
534d043c564SKenneth D. Merry }
535d043c564SKenneth D. Merry
536d043c564SKenneth D. Merry /**
537d043c564SKenneth D. Merry * _mapping_get_dpm_idx_from_id - get DPM index from ID
538d043c564SKenneth D. Merry * @sc: per adapter object
539d043c564SKenneth D. Merry * @id: volume WWID or enclosure ID or device ID
540d043c564SKenneth D. Merry *
541d043c564SKenneth D. Merry * Returns the index of DPM entry on success or bad index.
542d043c564SKenneth D. Merry */
543d043c564SKenneth D. Merry static u16
_mapping_get_dpm_idx_from_id(struct mps_softc * sc,u64 id,u32 phy_bits)544d043c564SKenneth D. Merry _mapping_get_dpm_idx_from_id(struct mps_softc *sc, u64 id, u32 phy_bits)
545d043c564SKenneth D. Merry {
546d043c564SKenneth D. Merry u16 entry_num;
547d043c564SKenneth D. Merry uint64_t PhysicalIdentifier;
548d043c564SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry;
549d043c564SKenneth D. Merry
550d043c564SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
551d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
552d043c564SKenneth D. Merry PhysicalIdentifier = dpm_entry->PhysicalIdentifier.High;
553d043c564SKenneth D. Merry PhysicalIdentifier = (PhysicalIdentifier << 32) |
554d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low;
555d043c564SKenneth D. Merry for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++,
556d043c564SKenneth D. Merry dpm_entry++)
557d043c564SKenneth D. Merry if ((id == PhysicalIdentifier) &&
558d043c564SKenneth D. Merry (!phy_bits || !dpm_entry->PhysicalBitsMapping ||
559d043c564SKenneth D. Merry (phy_bits & dpm_entry->PhysicalBitsMapping)))
560d043c564SKenneth D. Merry return entry_num;
561d043c564SKenneth D. Merry
562d043c564SKenneth D. Merry return MPS_DPM_BAD_IDX;
563d043c564SKenneth D. Merry }
564d043c564SKenneth D. Merry
565d043c564SKenneth D. Merry /**
566d043c564SKenneth D. Merry * _mapping_get_free_dpm_idx - get first available DPM index
567d043c564SKenneth D. Merry * @sc: per adapter object
568d043c564SKenneth D. Merry *
569d043c564SKenneth D. Merry * Returns the index of DPM entry on success or bad index.
570d043c564SKenneth D. Merry */
571d043c564SKenneth D. Merry static u32
_mapping_get_free_dpm_idx(struct mps_softc * sc)572d043c564SKenneth D. Merry _mapping_get_free_dpm_idx(struct mps_softc *sc)
573d043c564SKenneth D. Merry {
574d043c564SKenneth D. Merry u16 entry_num;
575635e58c7SStephen McConnell Mpi2DriverMap0Entry_t *dpm_entry;
576635e58c7SStephen McConnell u16 current_entry = MPS_DPM_BAD_IDX, missing_cnt, high_missing_cnt = 0;
577635e58c7SStephen McConnell u64 physical_id;
578635e58c7SStephen McConnell struct dev_mapping_table *mt_entry;
579635e58c7SStephen McConnell u32 map_idx;
580d043c564SKenneth D. Merry
581d043c564SKenneth D. Merry for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) {
582635e58c7SStephen McConnell dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
583635e58c7SStephen McConnell sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
584635e58c7SStephen McConnell dpm_entry += entry_num;
585635e58c7SStephen McConnell missing_cnt = dpm_entry->MappingInformation &
586635e58c7SStephen McConnell MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
587635e58c7SStephen McConnell
588635e58c7SStephen McConnell /*
589635e58c7SStephen McConnell * If entry is used and not missing, then this entry can't be
590635e58c7SStephen McConnell * used. Look at next one.
591635e58c7SStephen McConnell */
592635e58c7SStephen McConnell if (sc->dpm_entry_used[entry_num] && !missing_cnt)
593635e58c7SStephen McConnell continue;
594635e58c7SStephen McConnell
595635e58c7SStephen McConnell /*
596635e58c7SStephen McConnell * If this entry is not used at all, then the missing count
597635e58c7SStephen McConnell * doesn't matter. Just use this one. Otherwise, keep looking
598635e58c7SStephen McConnell * and make sure the entry with the highest missing count is
599635e58c7SStephen McConnell * used.
600635e58c7SStephen McConnell */
601635e58c7SStephen McConnell if (!sc->dpm_entry_used[entry_num]) {
602635e58c7SStephen McConnell current_entry = entry_num;
603635e58c7SStephen McConnell break;
604d043c564SKenneth D. Merry }
605635e58c7SStephen McConnell if ((current_entry == MPS_DPM_BAD_IDX) ||
606635e58c7SStephen McConnell (missing_cnt > high_missing_cnt)) {
607635e58c7SStephen McConnell current_entry = entry_num;
608635e58c7SStephen McConnell high_missing_cnt = missing_cnt;
609635e58c7SStephen McConnell }
610635e58c7SStephen McConnell }
611635e58c7SStephen McConnell
612635e58c7SStephen McConnell /*
613635e58c7SStephen McConnell * If an entry has been found to use and it's already marked as used
614635e58c7SStephen McConnell * it means that some device was already using this entry but it's
615635e58c7SStephen McConnell * missing, and that means that the connection between the missing
616635e58c7SStephen McConnell * device's DPM entry and the mapping table needs to be cleared. To do
617635e58c7SStephen McConnell * this, use the Physical ID of the old device still in the DPM entry
618635e58c7SStephen McConnell * to find its mapping table entry, then mark its DPM entry as BAD.
619635e58c7SStephen McConnell */
620635e58c7SStephen McConnell if ((current_entry != MPS_DPM_BAD_IDX) &&
621635e58c7SStephen McConnell sc->dpm_entry_used[current_entry]) {
622635e58c7SStephen McConnell dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
623635e58c7SStephen McConnell sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
624635e58c7SStephen McConnell dpm_entry += current_entry;
625635e58c7SStephen McConnell physical_id = dpm_entry->PhysicalIdentifier.High;
626635e58c7SStephen McConnell physical_id = (physical_id << 32) |
627635e58c7SStephen McConnell dpm_entry->PhysicalIdentifier.Low;
628635e58c7SStephen McConnell map_idx = _mapping_get_mt_idx_from_id(sc, physical_id);
629635e58c7SStephen McConnell if (map_idx != MPS_MAPTABLE_BAD_IDX) {
630635e58c7SStephen McConnell mt_entry = &sc->mapping_table[map_idx];
631635e58c7SStephen McConnell mt_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
632635e58c7SStephen McConnell }
633635e58c7SStephen McConnell }
634635e58c7SStephen McConnell return current_entry;
635d043c564SKenneth D. Merry }
636d043c564SKenneth D. Merry
637d043c564SKenneth D. Merry /**
638d043c564SKenneth D. Merry * _mapping_update_ir_missing_cnt - Updates missing count for a volume
639d043c564SKenneth D. Merry * @sc: per adapter object
640d043c564SKenneth D. Merry * @map_idx: map table index of the volume
641d043c564SKenneth D. Merry * @element: IR configuration change element
642d043c564SKenneth D. Merry * @wwid: IR volume ID.
643d043c564SKenneth D. Merry *
644d043c564SKenneth D. Merry * Updates the missing count in the map table and in the DPM entry for a volume
645d043c564SKenneth D. Merry *
646d043c564SKenneth D. Merry * Returns nothing.
647d043c564SKenneth D. Merry */
648d043c564SKenneth D. Merry static void
_mapping_update_ir_missing_cnt(struct mps_softc * sc,u32 map_idx,Mpi2EventIrConfigElement_t * element,u64 wwid)649d043c564SKenneth D. Merry _mapping_update_ir_missing_cnt(struct mps_softc *sc, u32 map_idx,
650d043c564SKenneth D. Merry Mpi2EventIrConfigElement_t *element, u64 wwid)
651d043c564SKenneth D. Merry {
652d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry;
653635e58c7SStephen McConnell u8 missing_cnt, reason = element->ReasonCode, update_dpm = 1;
654d043c564SKenneth D. Merry u16 dpm_idx;
655d043c564SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry;
656d043c564SKenneth D. Merry
657635e58c7SStephen McConnell /*
658635e58c7SStephen McConnell * Depending on the reason code, update the missing count. Always set
659635e58c7SStephen McConnell * the init_complete flag when here, so just do it first. That flag is
660635e58c7SStephen McConnell * used for volumes to make sure that the DPM entry has been updated.
661635e58c7SStephen McConnell * When a volume is deleted, clear the map entry's IN_USE flag so that
662635e58c7SStephen McConnell * the entry can be used again if another volume is created. Also clear
663635e58c7SStephen McConnell * its dev_handle entry so that other functions can't find this volume
664635e58c7SStephen McConnell * by the handle, since it's not defined any longer.
665635e58c7SStephen McConnell */
666d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx];
667635e58c7SStephen McConnell mt_entry->init_complete = 1;
668635e58c7SStephen McConnell if ((reason == MPI2_EVENT_IR_CHANGE_RC_ADDED) ||
669635e58c7SStephen McConnell (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED)) {
670d043c564SKenneth D. Merry mt_entry->missing_count = 0;
671635e58c7SStephen McConnell } else if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED) {
672d043c564SKenneth D. Merry if (mt_entry->missing_count < MPS_MAX_MISSING_COUNT)
673d043c564SKenneth D. Merry mt_entry->missing_count++;
674635e58c7SStephen McConnell
675635e58c7SStephen McConnell mt_entry->device_info &= ~MPS_MAP_IN_USE;
676d043c564SKenneth D. Merry mt_entry->dev_handle = 0;
677d043c564SKenneth D. Merry }
678d043c564SKenneth D. Merry
679635e58c7SStephen McConnell /*
680635e58c7SStephen McConnell * If persistent mapping is enabled, update the DPM with the new missing
681635e58c7SStephen McConnell * count for the volume. If the DPM index is bad, get a free one. If
682635e58c7SStephen McConnell * it's bad for a volume that's being deleted do nothing because that
683635e58c7SStephen McConnell * volume doesn't have a DPM entry.
684635e58c7SStephen McConnell */
685635e58c7SStephen McConnell if (!sc->is_dpm_enable)
686635e58c7SStephen McConnell return;
687d043c564SKenneth D. Merry dpm_idx = mt_entry->dpm_entry_num;
688d043c564SKenneth D. Merry if (dpm_idx == MPS_DPM_BAD_IDX) {
689635e58c7SStephen McConnell if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED)
690635e58c7SStephen McConnell {
691635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Volume being deleted "
692635e58c7SStephen McConnell "is not in DPM so DPM missing count will not be "
693635e58c7SStephen McConnell "updated.\n", __func__);
694d043c564SKenneth D. Merry return;
695d043c564SKenneth D. Merry }
696635e58c7SStephen McConnell }
697635e58c7SStephen McConnell if (dpm_idx == MPS_DPM_BAD_IDX)
698635e58c7SStephen McConnell dpm_idx = _mapping_get_free_dpm_idx(sc);
699635e58c7SStephen McConnell
700635e58c7SStephen McConnell /*
701635e58c7SStephen McConnell * Got the DPM entry for the volume or found a free DPM entry if this is
702635e58c7SStephen McConnell * a new volume. Check if the current information is outdated.
703635e58c7SStephen McConnell */
704d043c564SKenneth D. Merry if (dpm_idx != MPS_DPM_BAD_IDX) {
705d043c564SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
706d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
707d043c564SKenneth D. Merry dpm_entry += dpm_idx;
708d043c564SKenneth D. Merry missing_cnt = dpm_entry->MappingInformation &
709d043c564SKenneth D. Merry MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
710d043c564SKenneth D. Merry if ((mt_entry->physical_id ==
711635e58c7SStephen McConnell le64toh(((u64)dpm_entry->PhysicalIdentifier.High << 32) |
712635e58c7SStephen McConnell (u64)dpm_entry->PhysicalIdentifier.Low)) && (missing_cnt ==
713635e58c7SStephen McConnell mt_entry->missing_count)) {
714635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: DPM entry for volume "
715635e58c7SStephen McConnell "with target ID %d does not require an update.\n",
716635e58c7SStephen McConnell __func__, mt_entry->id);
717635e58c7SStephen McConnell update_dpm = 0;
718635e58c7SStephen McConnell }
719d043c564SKenneth D. Merry }
720d043c564SKenneth D. Merry
721635e58c7SStephen McConnell /*
722635e58c7SStephen McConnell * Update the volume's persistent info if it's new or the ID or missing
723635e58c7SStephen McConnell * count has changed. If a good DPM index has not been found by now,
724635e58c7SStephen McConnell * there is no space left in the DPM table.
725635e58c7SStephen McConnell */
726635e58c7SStephen McConnell if ((dpm_idx != MPS_DPM_BAD_IDX) && update_dpm) {
727635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Update DPM entry for volume "
728635e58c7SStephen McConnell "with target ID %d.\n", __func__, mt_entry->id);
729635e58c7SStephen McConnell
730d043c564SKenneth D. Merry mt_entry->dpm_entry_num = dpm_idx;
731d043c564SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
732d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
733d043c564SKenneth D. Merry dpm_entry += dpm_idx;
734d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low =
735d043c564SKenneth D. Merry (0xFFFFFFFF & mt_entry->physical_id);
736d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.High =
737d043c564SKenneth D. Merry (mt_entry->physical_id >> 32);
738d043c564SKenneth D. Merry dpm_entry->DeviceIndex = map_idx;
739d043c564SKenneth D. Merry dpm_entry->MappingInformation = mt_entry->missing_count;
740d043c564SKenneth D. Merry dpm_entry->PhysicalBitsMapping = 0;
741d043c564SKenneth D. Merry dpm_entry->Reserved1 = 0;
742d043c564SKenneth D. Merry sc->dpm_flush_entry[dpm_idx] = 1;
743d043c564SKenneth D. Merry sc->dpm_entry_used[dpm_idx] = 1;
744d043c564SKenneth D. Merry } else if (dpm_idx == MPS_DPM_BAD_IDX) {
745635e58c7SStephen McConnell mps_dprint(sc, MPS_INFO | MPS_MAPPING, "%s: No space to add an "
746635e58c7SStephen McConnell "entry in the DPM table for volume with target ID %d.\n",
747635e58c7SStephen McConnell __func__, mt_entry->id);
748d043c564SKenneth D. Merry }
749d043c564SKenneth D. Merry }
750d043c564SKenneth D. Merry
751d043c564SKenneth D. Merry /**
752635e58c7SStephen McConnell * _mapping_add_to_removal_table - add DPM index to the removal table
753d043c564SKenneth D. Merry * @sc: per adapter object
754635e58c7SStephen McConnell * @dpm_idx: Index of DPM entry to remove
755d043c564SKenneth D. Merry *
756635e58c7SStephen McConnell * Adds a DPM entry number to the removal table.
757d043c564SKenneth D. Merry *
758d043c564SKenneth D. Merry * Returns nothing.
759d043c564SKenneth D. Merry */
760d043c564SKenneth D. Merry static void
_mapping_add_to_removal_table(struct mps_softc * sc,u16 dpm_idx)761635e58c7SStephen McConnell _mapping_add_to_removal_table(struct mps_softc *sc, u16 dpm_idx)
762d043c564SKenneth D. Merry {
763d043c564SKenneth D. Merry struct map_removal_table *remove_entry;
764d043c564SKenneth D. Merry u32 i;
765d043c564SKenneth D. Merry
766635e58c7SStephen McConnell /*
767635e58c7SStephen McConnell * This is only used to remove entries from the DPM in the controller.
768635e58c7SStephen McConnell * If DPM is not enabled, just return.
769635e58c7SStephen McConnell */
770635e58c7SStephen McConnell if (!sc->is_dpm_enable)
771635e58c7SStephen McConnell return;
772635e58c7SStephen McConnell
773635e58c7SStephen McConnell /*
774635e58c7SStephen McConnell * Find the first available removal_table entry and add the new entry
775635e58c7SStephen McConnell * there.
776635e58c7SStephen McConnell */
777d043c564SKenneth D. Merry remove_entry = sc->removal_table;
778d043c564SKenneth D. Merry
779d043c564SKenneth D. Merry for (i = 0; i < sc->max_devices; i++, remove_entry++) {
780635e58c7SStephen McConnell if (remove_entry->dpm_entry_num != MPS_DPM_BAD_IDX)
781d043c564SKenneth D. Merry continue;
782635e58c7SStephen McConnell
783635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Adding DPM entry %d to table "
784635e58c7SStephen McConnell "for removal.\n", __func__, dpm_idx);
785d043c564SKenneth D. Merry remove_entry->dpm_entry_num = dpm_idx;
786d043c564SKenneth D. Merry break;
787d043c564SKenneth D. Merry }
788d043c564SKenneth D. Merry
789d043c564SKenneth D. Merry }
790d043c564SKenneth D. Merry
791d043c564SKenneth D. Merry /**
792d043c564SKenneth D. Merry * _mapping_update_missing_count - Update missing count for a device
793d043c564SKenneth D. Merry * @sc: per adapter object
794d043c564SKenneth D. Merry * @topo_change: Topology change event entry
795d043c564SKenneth D. Merry *
796635e58c7SStephen McConnell * Increment the missing count in the mapping table for a device that is not
797635e58c7SStephen McConnell * responding. If Persitent Mapping is used, increment the DPM entry as well.
798635e58c7SStephen McConnell * Currently, this function only increments the missing count if the device
799635e58c7SStephen McConnell * goes missing, so after initialization has completed. This means that the
800635e58c7SStephen McConnell * missing count can only go from 0 to 1 here. The missing count is incremented
801635e58c7SStephen McConnell * during initialization as well, so that's where a target's missing count can
802635e58c7SStephen McConnell * go past 1.
803d043c564SKenneth D. Merry *
804d043c564SKenneth D. Merry * Returns nothing.
805d043c564SKenneth D. Merry */
806d043c564SKenneth D. Merry static void
_mapping_update_missing_count(struct mps_softc * sc,struct _map_topology_change * topo_change)807d043c564SKenneth D. Merry _mapping_update_missing_count(struct mps_softc *sc,
808d043c564SKenneth D. Merry struct _map_topology_change *topo_change)
809d043c564SKenneth D. Merry {
810d043c564SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
811d043c564SKenneth D. Merry u8 entry;
812d043c564SKenneth D. Merry struct _map_phy_change *phy_change;
813d043c564SKenneth D. Merry u32 map_idx;
814d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry;
815d043c564SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry;
816d043c564SKenneth D. Merry
817d043c564SKenneth D. Merry for (entry = 0; entry < topo_change->num_entries; entry++) {
818d043c564SKenneth D. Merry phy_change = &topo_change->phy_details[entry];
819d043c564SKenneth D. Merry if (!phy_change->dev_handle || (phy_change->reason !=
820d043c564SKenneth D. Merry MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING))
821d043c564SKenneth D. Merry continue;
822d043c564SKenneth D. Merry map_idx = _mapping_get_mt_idx_from_handle(sc, phy_change->
823d043c564SKenneth D. Merry dev_handle);
824d043c564SKenneth D. Merry phy_change->is_processed = 1;
825d043c564SKenneth D. Merry if (map_idx == MPS_MAPTABLE_BAD_IDX) {
826635e58c7SStephen McConnell mps_dprint(sc, MPS_INFO | MPS_MAPPING, "%s: device is "
827635e58c7SStephen McConnell "already removed from mapping table\n", __func__);
828d043c564SKenneth D. Merry continue;
829d043c564SKenneth D. Merry }
830d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx];
831d043c564SKenneth D. Merry if (mt_entry->missing_count < MPS_MAX_MISSING_COUNT)
832d043c564SKenneth D. Merry mt_entry->missing_count++;
833d043c564SKenneth D. Merry
834635e58c7SStephen McConnell /*
835635e58c7SStephen McConnell * When using Enc/Slot mapping, when a device is removed, it's
836635e58c7SStephen McConnell * mapping table information should be cleared. Otherwise, the
837635e58c7SStephen McConnell * target ID will be incorrect if this same device is re-added
838635e58c7SStephen McConnell * to a different slot.
839635e58c7SStephen McConnell */
840635e58c7SStephen McConnell if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
841635e58c7SStephen McConnell MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
842635e58c7SStephen McConnell _mapping_clear_map_entry(mt_entry);
843635e58c7SStephen McConnell }
844635e58c7SStephen McConnell
845635e58c7SStephen McConnell /*
846635e58c7SStephen McConnell * When using device mapping, update the missing count in the
847635e58c7SStephen McConnell * DPM entry, but only if the missing count has changed.
848635e58c7SStephen McConnell */
849d043c564SKenneth D. Merry if (((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
850d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) &&
851635e58c7SStephen McConnell sc->is_dpm_enable &&
852d043c564SKenneth D. Merry mt_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
853d043c564SKenneth D. Merry dpm_entry =
854d043c564SKenneth D. Merry (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
855d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
856d043c564SKenneth D. Merry dpm_entry += mt_entry->dpm_entry_num;
857635e58c7SStephen McConnell if (dpm_entry->MappingInformation !=
858635e58c7SStephen McConnell mt_entry->missing_count) {
859635e58c7SStephen McConnell dpm_entry->MappingInformation =
860635e58c7SStephen McConnell mt_entry->missing_count;
861635e58c7SStephen McConnell sc->dpm_flush_entry[mt_entry->dpm_entry_num] =
862635e58c7SStephen McConnell 1;
863d043c564SKenneth D. Merry }
864635e58c7SStephen McConnell }
865d043c564SKenneth D. Merry }
866d043c564SKenneth D. Merry }
867d043c564SKenneth D. Merry
868d043c564SKenneth D. Merry /**
869d043c564SKenneth D. Merry * _mapping_find_enc_map_space -find map table entries for enclosure
870d043c564SKenneth D. Merry * @sc: per adapter object
871d043c564SKenneth D. Merry * @et_entry: enclosure entry
872d043c564SKenneth D. Merry *
873d043c564SKenneth D. Merry * Search through the mapping table defragment it and provide contiguous
874d043c564SKenneth D. Merry * space in map table for a particular enclosure entry
875d043c564SKenneth D. Merry *
876d043c564SKenneth D. Merry * Returns start index in map table or bad index.
877d043c564SKenneth D. Merry */
878d043c564SKenneth D. Merry static u32
_mapping_find_enc_map_space(struct mps_softc * sc,struct enc_mapping_table * et_entry)879d043c564SKenneth D. Merry _mapping_find_enc_map_space(struct mps_softc *sc,
880d043c564SKenneth D. Merry struct enc_mapping_table *et_entry)
881d043c564SKenneth D. Merry {
882d043c564SKenneth D. Merry u16 vol_mapping_flags;
883d043c564SKenneth D. Merry u32 skip_count, end_of_table, map_idx, enc_idx;
884d043c564SKenneth D. Merry u16 num_found;
885d043c564SKenneth D. Merry u32 start_idx = MPS_MAPTABLE_BAD_IDX;
886d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry;
887d043c564SKenneth D. Merry struct enc_mapping_table *enc_entry;
888d043c564SKenneth D. Merry unsigned char done_flag = 0, found_space;
889d043c564SKenneth D. Merry u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
890d043c564SKenneth D. Merry
891d043c564SKenneth D. Merry skip_count = sc->num_rsvd_entries;
892d043c564SKenneth D. Merry num_found = 0;
893d043c564SKenneth D. Merry
894d043c564SKenneth D. Merry vol_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
895d043c564SKenneth D. Merry MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
896d043c564SKenneth D. Merry
897635e58c7SStephen McConnell /*
898635e58c7SStephen McConnell * The end of the mapping table depends on where volumes are kept, if
899635e58c7SStephen McConnell * IR is enabled.
900635e58c7SStephen McConnell */
901d043c564SKenneth D. Merry if (!sc->ir_firmware)
902d043c564SKenneth D. Merry end_of_table = sc->max_devices;
903d043c564SKenneth D. Merry else if (vol_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING)
904d043c564SKenneth D. Merry end_of_table = sc->max_devices;
905d043c564SKenneth D. Merry else
906d043c564SKenneth D. Merry end_of_table = sc->max_devices - sc->max_volumes;
907d043c564SKenneth D. Merry
908635e58c7SStephen McConnell /*
909635e58c7SStephen McConnell * The skip_count is the number of entries that are reserved at the
910635e58c7SStephen McConnell * beginning of the mapping table. But, it does not include the number
911635e58c7SStephen McConnell * of Physical IDs that are reserved for direct attached devices. Look
912635e58c7SStephen McConnell * through the mapping table after these reserved entries to see if
913635e58c7SStephen McConnell * the devices for this enclosure are already mapped. The PHY bit check
914635e58c7SStephen McConnell * is used to make sure that at least one PHY bit is common between the
915635e58c7SStephen McConnell * enclosure and the device that is already mapped.
916635e58c7SStephen McConnell */
917635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Looking for space in the mapping "
918635e58c7SStephen McConnell "table for added enclosure.\n", __func__);
919d043c564SKenneth D. Merry for (map_idx = (max_num_phy_ids + skip_count);
920d043c564SKenneth D. Merry map_idx < end_of_table; map_idx++) {
921d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx];
922d043c564SKenneth D. Merry if ((et_entry->enclosure_id == mt_entry->physical_id) &&
923d043c564SKenneth D. Merry (!mt_entry->phy_bits || (mt_entry->phy_bits &
924d043c564SKenneth D. Merry et_entry->phy_bits))) {
925d043c564SKenneth D. Merry num_found += 1;
926d043c564SKenneth D. Merry if (num_found == et_entry->num_slots) {
927d043c564SKenneth D. Merry start_idx = (map_idx - num_found) + 1;
928635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Found space "
929635e58c7SStephen McConnell "in the mapping for enclosure at map index "
930635e58c7SStephen McConnell "%d.\n", __func__, start_idx);
931d043c564SKenneth D. Merry return start_idx;
932d043c564SKenneth D. Merry }
933d043c564SKenneth D. Merry } else
934d043c564SKenneth D. Merry num_found = 0;
935d043c564SKenneth D. Merry }
936635e58c7SStephen McConnell
937635e58c7SStephen McConnell /*
938635e58c7SStephen McConnell * If the enclosure's devices are not mapped already, look for
939635e58c7SStephen McConnell * contiguous entries in the mapping table that are not reserved. If
940635e58c7SStephen McConnell * enough entries are found, return the starting index for that space.
941635e58c7SStephen McConnell */
942635e58c7SStephen McConnell num_found = 0;
943d043c564SKenneth D. Merry for (map_idx = (max_num_phy_ids + skip_count);
944d043c564SKenneth D. Merry map_idx < end_of_table; map_idx++) {
945d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx];
946d043c564SKenneth D. Merry if (!(mt_entry->device_info & MPS_DEV_RESERVED)) {
947d043c564SKenneth D. Merry num_found += 1;
948d043c564SKenneth D. Merry if (num_found == et_entry->num_slots) {
949d043c564SKenneth D. Merry start_idx = (map_idx - num_found) + 1;
950635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Found space "
951635e58c7SStephen McConnell "in the mapping for enclosure at map index "
952635e58c7SStephen McConnell "%d.\n", __func__, start_idx);
953d043c564SKenneth D. Merry return start_idx;
954d043c564SKenneth D. Merry }
955d043c564SKenneth D. Merry } else
956d043c564SKenneth D. Merry num_found = 0;
957d043c564SKenneth D. Merry }
958d043c564SKenneth D. Merry
959635e58c7SStephen McConnell /*
960635e58c7SStephen McConnell * If here, it means that not enough space in the mapping table was
961635e58c7SStephen McConnell * found to support this enclosure, so go through the enclosure table to
962635e58c7SStephen McConnell * see if any enclosure entries have a missing count. If so, get the
963635e58c7SStephen McConnell * enclosure with the highest missing count and check it to see if there
964635e58c7SStephen McConnell * is enough space for the new enclosure.
965635e58c7SStephen McConnell */
966d043c564SKenneth D. Merry while (!done_flag) {
967d043c564SKenneth D. Merry enc_idx = _mapping_get_high_missing_et_idx(sc);
968635e58c7SStephen McConnell if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
969635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Not enough space was "
970635e58c7SStephen McConnell "found in the mapping for the added enclosure.\n",
971635e58c7SStephen McConnell __func__);
972d043c564SKenneth D. Merry return MPS_MAPTABLE_BAD_IDX;
973635e58c7SStephen McConnell }
974635e58c7SStephen McConnell
975635e58c7SStephen McConnell /*
976635e58c7SStephen McConnell * Found a missing enclosure. Set the skip_search flag so this
977635e58c7SStephen McConnell * enclosure is not checked again for a high missing count if
978635e58c7SStephen McConnell * the loop continues. This way, all missing enclosures can
979635e58c7SStephen McConnell * have their space added together to find enough space in the
980635e58c7SStephen McConnell * mapping table for the added enclosure. The space must be
981635e58c7SStephen McConnell * contiguous.
982635e58c7SStephen McConnell */
983635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Space from a missing "
984635e58c7SStephen McConnell "enclosure was found.\n", __func__);
985d043c564SKenneth D. Merry enc_entry = &sc->enclosure_table[enc_idx];
986d043c564SKenneth D. Merry enc_entry->skip_search = 1;
987635e58c7SStephen McConnell
988635e58c7SStephen McConnell /*
989635e58c7SStephen McConnell * Unmark all of the missing enclosure's device's reserved
990635e58c7SStephen McConnell * space. These will be remarked as reserved if this missing
991635e58c7SStephen McConnell * enclosure's space is not used.
992635e58c7SStephen McConnell */
993635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Clear the reserved flag for "
994635e58c7SStephen McConnell "all of the map entries for the enclosure.\n", __func__);
995d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[enc_entry->start_index];
996d043c564SKenneth D. Merry for (map_idx = enc_entry->start_index; map_idx <
997d043c564SKenneth D. Merry (enc_entry->start_index + enc_entry->num_slots); map_idx++,
998d043c564SKenneth D. Merry mt_entry++)
999d043c564SKenneth D. Merry mt_entry->device_info &= ~MPS_DEV_RESERVED;
1000635e58c7SStephen McConnell
1001635e58c7SStephen McConnell /*
1002635e58c7SStephen McConnell * Now that space has been unreserved, check again to see if
1003635e58c7SStephen McConnell * enough space is available for the new enclosure.
1004635e58c7SStephen McConnell */
1005635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Check if new mapping space is "
1006635e58c7SStephen McConnell "enough for the new enclosure.\n", __func__);
1007d043c564SKenneth D. Merry found_space = 0;
1008635e58c7SStephen McConnell num_found = 0;
1009635e58c7SStephen McConnell for (map_idx = (max_num_phy_ids + skip_count);
1010635e58c7SStephen McConnell map_idx < end_of_table; map_idx++) {
1011d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx];
1012d043c564SKenneth D. Merry if (!(mt_entry->device_info & MPS_DEV_RESERVED)) {
1013d043c564SKenneth D. Merry num_found += 1;
1014d043c564SKenneth D. Merry if (num_found == et_entry->num_slots) {
1015d043c564SKenneth D. Merry start_idx = (map_idx - num_found) + 1;
1016d043c564SKenneth D. Merry found_space = 1;
1017635e58c7SStephen McConnell break;
1018d043c564SKenneth D. Merry }
1019d043c564SKenneth D. Merry } else
1020d043c564SKenneth D. Merry num_found = 0;
1021d043c564SKenneth D. Merry }
1022d043c564SKenneth D. Merry if (!found_space)
1023d043c564SKenneth D. Merry continue;
1024635e58c7SStephen McConnell
1025635e58c7SStephen McConnell /*
1026635e58c7SStephen McConnell * If enough space was found, all of the missing enclosures that
1027635e58c7SStephen McConnell * will be used for the new enclosure must be added to the
1028635e58c7SStephen McConnell * removal table. Then all mappings for the enclosure's devices
1029635e58c7SStephen McConnell * and for the enclosure itself need to be cleared. There may be
1030635e58c7SStephen McConnell * more than one enclosure to add to the removal table and
1031635e58c7SStephen McConnell * clear.
1032635e58c7SStephen McConnell */
1033635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Found space in the mapping "
1034635e58c7SStephen McConnell "for enclosure at map index %d.\n", __func__, start_idx);
1035d043c564SKenneth D. Merry for (map_idx = start_idx; map_idx < (start_idx + num_found);
1036d043c564SKenneth D. Merry map_idx++) {
1037d043c564SKenneth D. Merry enc_entry = sc->enclosure_table;
1038d043c564SKenneth D. Merry for (enc_idx = 0; enc_idx < sc->num_enc_table_entries;
1039d043c564SKenneth D. Merry enc_idx++, enc_entry++) {
1040d043c564SKenneth D. Merry if (map_idx < enc_entry->start_index ||
1041d043c564SKenneth D. Merry map_idx > (enc_entry->start_index +
1042d043c564SKenneth D. Merry enc_entry->num_slots))
1043d043c564SKenneth D. Merry continue;
1044d043c564SKenneth D. Merry if (!enc_entry->removal_flag) {
1045635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: "
1046635e58c7SStephen McConnell "Enclosure %d will be removed from "
1047635e58c7SStephen McConnell "the mapping table.\n", __func__,
1048635e58c7SStephen McConnell enc_idx);
1049d043c564SKenneth D. Merry enc_entry->removal_flag = 1;
1050635e58c7SStephen McConnell _mapping_add_to_removal_table(sc,
1051d043c564SKenneth D. Merry enc_entry->dpm_entry_num);
1052d043c564SKenneth D. Merry }
1053d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx];
1054d043c564SKenneth D. Merry _mapping_clear_map_entry(mt_entry);
1055d043c564SKenneth D. Merry if (map_idx == (enc_entry->start_index +
1056d043c564SKenneth D. Merry enc_entry->num_slots - 1))
1057d043c564SKenneth D. Merry _mapping_clear_enc_entry(et_entry);
1058d043c564SKenneth D. Merry }
1059d043c564SKenneth D. Merry }
1060635e58c7SStephen McConnell
1061635e58c7SStephen McConnell /*
1062635e58c7SStephen McConnell * During the search for space for this enclosure, some entries
1063635e58c7SStephen McConnell * in the mapping table may have been unreserved. Go back and
1064635e58c7SStephen McConnell * change all of these to reserved again. Only the enclosures
1065635e58c7SStephen McConnell * with the removal_flag set should be left as unreserved. The
1066635e58c7SStephen McConnell * skip_search flag needs to be cleared as well so that the
1067635e58c7SStephen McConnell * enclosure's space will be looked at the next time space is
1068635e58c7SStephen McConnell * needed.
1069635e58c7SStephen McConnell */
1070d043c564SKenneth D. Merry enc_entry = sc->enclosure_table;
1071d043c564SKenneth D. Merry for (enc_idx = 0; enc_idx < sc->num_enc_table_entries;
1072d043c564SKenneth D. Merry enc_idx++, enc_entry++) {
1073d043c564SKenneth D. Merry if (!enc_entry->removal_flag) {
1074635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Reset the "
1075635e58c7SStephen McConnell "reserved flag for all of the map entries "
1076635e58c7SStephen McConnell "for enclosure %d.\n", __func__, enc_idx);
1077d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[enc_entry->
1078d043c564SKenneth D. Merry start_index];
1079d043c564SKenneth D. Merry for (map_idx = enc_entry->start_index; map_idx <
1080d043c564SKenneth D. Merry (enc_entry->start_index +
1081d043c564SKenneth D. Merry enc_entry->num_slots); map_idx++,
1082d043c564SKenneth D. Merry mt_entry++)
1083d043c564SKenneth D. Merry mt_entry->device_info |=
1084d043c564SKenneth D. Merry MPS_DEV_RESERVED;
1085d043c564SKenneth D. Merry et_entry->skip_search = 0;
1086d043c564SKenneth D. Merry }
1087d043c564SKenneth D. Merry }
1088d043c564SKenneth D. Merry done_flag = 1;
1089d043c564SKenneth D. Merry }
1090d043c564SKenneth D. Merry return start_idx;
1091d043c564SKenneth D. Merry }
1092d043c564SKenneth D. Merry
1093d043c564SKenneth D. Merry /**
1094d043c564SKenneth D. Merry * _mapping_get_dev_info -get information about newly added devices
1095d043c564SKenneth D. Merry * @sc: per adapter object
1096d043c564SKenneth D. Merry * @topo_change: Topology change event entry
1097d043c564SKenneth D. Merry *
1098d043c564SKenneth D. Merry * Search through the topology change event list and issues sas device pg0
1099d043c564SKenneth D. Merry * requests for the newly added device and reserved entries in tables
1100d043c564SKenneth D. Merry *
1101d043c564SKenneth D. Merry * Returns nothing
1102d043c564SKenneth D. Merry */
1103d043c564SKenneth D. Merry static void
_mapping_get_dev_info(struct mps_softc * sc,struct _map_topology_change * topo_change)1104d043c564SKenneth D. Merry _mapping_get_dev_info(struct mps_softc *sc,
1105d043c564SKenneth D. Merry struct _map_topology_change *topo_change)
1106d043c564SKenneth D. Merry {
1107d043c564SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1108d043c564SKenneth D. Merry Mpi2ConfigReply_t mpi_reply;
1109d043c564SKenneth D. Merry Mpi2SasDevicePage0_t sas_device_pg0;
1110bfa3cf97SMarcelo Araujo u8 entry, enc_idx, phy_idx;
1111d043c564SKenneth D. Merry u32 map_idx, index, device_info;
1112d043c564SKenneth D. Merry struct _map_phy_change *phy_change, *tmp_phy_change;
1113d043c564SKenneth D. Merry uint64_t sas_address;
1114d043c564SKenneth D. Merry struct enc_mapping_table *et_entry;
1115d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry;
1116d043c564SKenneth D. Merry u8 add_code = MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED;
1117ef065d89SStephen McConnell int rc = 1;
1118d043c564SKenneth D. Merry
1119d043c564SKenneth D. Merry for (entry = 0; entry < topo_change->num_entries; entry++) {
1120d043c564SKenneth D. Merry phy_change = &topo_change->phy_details[entry];
1121d043c564SKenneth D. Merry if (phy_change->is_processed || !phy_change->dev_handle ||
1122d043c564SKenneth D. Merry phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED)
1123d043c564SKenneth D. Merry continue;
1124635e58c7SStephen McConnell
1125d043c564SKenneth D. Merry if (mps_config_get_sas_device_pg0(sc, &mpi_reply,
1126d043c564SKenneth D. Merry &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
1127d043c564SKenneth D. Merry phy_change->dev_handle)) {
1128d043c564SKenneth D. Merry phy_change->is_processed = 1;
1129d043c564SKenneth D. Merry continue;
1130d043c564SKenneth D. Merry }
1131d043c564SKenneth D. Merry
1132ef065d89SStephen McConnell /*
1133ef065d89SStephen McConnell * Always get SATA Identify information because this is used
1134ef065d89SStephen McConnell * to determine if Start/Stop Unit should be sent to the drive
1135ef065d89SStephen McConnell * when the system is shutdown.
1136ef065d89SStephen McConnell */
1137d043c564SKenneth D. Merry device_info = le32toh(sas_device_pg0.DeviceInfo);
1138635e58c7SStephen McConnell sas_address = le32toh(sas_device_pg0.SASAddress.High);
1139d043c564SKenneth D. Merry sas_address = (sas_address << 32) |
1140635e58c7SStephen McConnell le32toh(sas_device_pg0.SASAddress.Low);
1141ef065d89SStephen McConnell if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) &&
1142ef065d89SStephen McConnell (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) {
1143ef065d89SStephen McConnell rc = mpssas_get_sas_address_for_sata_disk(sc,
1144ef065d89SStephen McConnell &sas_address, phy_change->dev_handle, device_info,
1145ef065d89SStephen McConnell &phy_change->is_SATA_SSD);
1146ef065d89SStephen McConnell if (rc) {
1147ef065d89SStephen McConnell mps_dprint(sc, MPS_ERROR, "%s: failed to get "
1148ef065d89SStephen McConnell "disk type (SSD or HDD) and SAS Address "
1149ef065d89SStephen McConnell "for SATA device with handle 0x%04x\n",
1150ef065d89SStephen McConnell __func__, phy_change->dev_handle);
1151d043c564SKenneth D. Merry }
1152ef065d89SStephen McConnell }
1153ef065d89SStephen McConnell
1154d043c564SKenneth D. Merry phy_change->physical_id = sas_address;
1155d043c564SKenneth D. Merry phy_change->slot = le16toh(sas_device_pg0.Slot);
1156635e58c7SStephen McConnell phy_change->device_info = device_info;
1157d043c564SKenneth D. Merry
1158635e58c7SStephen McConnell /*
1159635e58c7SStephen McConnell * When using Enc/Slot mapping, if this device is an enclosure
1160635e58c7SStephen McConnell * make sure that all of its slots can fit into the mapping
1161635e58c7SStephen McConnell * table.
1162635e58c7SStephen McConnell */
1163d043c564SKenneth D. Merry if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1164d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1165635e58c7SStephen McConnell /*
1166635e58c7SStephen McConnell * The enclosure should already be in the enclosure
1167635e58c7SStephen McConnell * table due to the Enclosure Add event. If not, just
1168635e58c7SStephen McConnell * continue, nothing can be done.
1169635e58c7SStephen McConnell */
1170d043c564SKenneth D. Merry enc_idx = _mapping_get_enc_idx_from_handle(sc,
1171d043c564SKenneth D. Merry topo_change->enc_handle);
1172d043c564SKenneth D. Merry if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
1173d043c564SKenneth D. Merry phy_change->is_processed = 1;
1174635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: "
1175635e58c7SStephen McConnell "failed to add the device with handle "
1176b99419aeSAlexander Motin "0x%04x because enclosure handle 0x%04x "
1177b99419aeSAlexander Motin "is not in the mapping table\n", __func__,
1178b99419aeSAlexander Motin phy_change->dev_handle,
1179b99419aeSAlexander Motin topo_change->enc_handle);
1180d043c564SKenneth D. Merry continue;
1181d043c564SKenneth D. Merry }
1182d043c564SKenneth D. Merry if (!((phy_change->device_info &
1183d043c564SKenneth D. Merry MPI2_SAS_DEVICE_INFO_END_DEVICE) &&
1184d043c564SKenneth D. Merry (phy_change->device_info &
1185d043c564SKenneth D. Merry (MPI2_SAS_DEVICE_INFO_SSP_TARGET |
1186d043c564SKenneth D. Merry MPI2_SAS_DEVICE_INFO_STP_TARGET |
1187d043c564SKenneth D. Merry MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))) {
1188d043c564SKenneth D. Merry phy_change->is_processed = 1;
1189d043c564SKenneth D. Merry continue;
1190d043c564SKenneth D. Merry }
1191d043c564SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx];
1192635e58c7SStephen McConnell
1193635e58c7SStephen McConnell /*
1194635e58c7SStephen McConnell * If the enclosure already has a start_index, it's been
1195635e58c7SStephen McConnell * mapped, so go to the next Topo change.
1196635e58c7SStephen McConnell */
1197d043c564SKenneth D. Merry if (et_entry->start_index != MPS_MAPTABLE_BAD_IDX)
1198d043c564SKenneth D. Merry continue;
1199635e58c7SStephen McConnell
1200635e58c7SStephen McConnell /*
1201635e58c7SStephen McConnell * If the Expander Handle is 0, the devices are direct
1202635e58c7SStephen McConnell * attached. In that case, the start_index must be just
1203635e58c7SStephen McConnell * after the reserved entries. Otherwise, find space in
1204635e58c7SStephen McConnell * the mapping table for the enclosure's devices.
1205635e58c7SStephen McConnell */
1206d043c564SKenneth D. Merry if (!topo_change->exp_handle) {
1207d043c564SKenneth D. Merry map_idx = sc->num_rsvd_entries;
1208d043c564SKenneth D. Merry et_entry->start_index = map_idx;
1209d043c564SKenneth D. Merry } else {
1210d043c564SKenneth D. Merry map_idx = _mapping_find_enc_map_space(sc,
1211d043c564SKenneth D. Merry et_entry);
1212d043c564SKenneth D. Merry et_entry->start_index = map_idx;
1213635e58c7SStephen McConnell
1214635e58c7SStephen McConnell /*
1215635e58c7SStephen McConnell * If space cannot be found to hold all of the
1216635e58c7SStephen McConnell * enclosure's devices in the mapping table,
1217635e58c7SStephen McConnell * there's no need to continue checking the
1218635e58c7SStephen McConnell * other devices in this event. Set all of the
1219635e58c7SStephen McConnell * phy_details for this event (if the change is
1220635e58c7SStephen McConnell * for an add) as already processed because none
1221635e58c7SStephen McConnell * of these devices can be added to the mapping
1222635e58c7SStephen McConnell * table.
1223635e58c7SStephen McConnell */
1224d043c564SKenneth D. Merry if (et_entry->start_index ==
1225d043c564SKenneth D. Merry MPS_MAPTABLE_BAD_IDX) {
1226635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING,
1227635e58c7SStephen McConnell "%s: failed to add the enclosure "
1228635e58c7SStephen McConnell "with ID 0x%016jx because there is "
1229635e58c7SStephen McConnell "no free space available in the "
1230635e58c7SStephen McConnell "mapping table for all of the "
1231635e58c7SStephen McConnell "enclosure's devices.\n", __func__,
1232635e58c7SStephen McConnell (uintmax_t)et_entry->enclosure_id);
1233d043c564SKenneth D. Merry phy_change->is_processed = 1;
1234d043c564SKenneth D. Merry for (phy_idx = 0; phy_idx <
1235d043c564SKenneth D. Merry topo_change->num_entries;
1236d043c564SKenneth D. Merry phy_idx++) {
1237d043c564SKenneth D. Merry tmp_phy_change =
1238d043c564SKenneth D. Merry &topo_change->phy_details
1239d043c564SKenneth D. Merry [phy_idx];
1240d043c564SKenneth D. Merry if (tmp_phy_change->reason ==
1241d043c564SKenneth D. Merry add_code)
1242d043c564SKenneth D. Merry tmp_phy_change->
1243d043c564SKenneth D. Merry is_processed = 1;
1244d043c564SKenneth D. Merry }
1245d043c564SKenneth D. Merry break;
1246d043c564SKenneth D. Merry }
1247d043c564SKenneth D. Merry }
1248635e58c7SStephen McConnell
1249635e58c7SStephen McConnell /*
1250635e58c7SStephen McConnell * Found space in the mapping table for this enclosure.
1251635e58c7SStephen McConnell * Initialize each mapping table entry for the
1252635e58c7SStephen McConnell * enclosure.
1253635e58c7SStephen McConnell */
1254635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Initialize %d map "
1255635e58c7SStephen McConnell "entries for the enclosure, starting at map index "
1256635e58c7SStephen McConnell " %d.\n", __func__, et_entry->num_slots, map_idx);
1257d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx];
1258d043c564SKenneth D. Merry for (index = map_idx; index < (et_entry->num_slots
1259d043c564SKenneth D. Merry + map_idx); index++, mt_entry++) {
1260d043c564SKenneth D. Merry mt_entry->device_info = MPS_DEV_RESERVED;
1261d043c564SKenneth D. Merry mt_entry->physical_id = et_entry->enclosure_id;
1262d043c564SKenneth D. Merry mt_entry->phy_bits = et_entry->phy_bits;
1263635e58c7SStephen McConnell mt_entry->missing_count = 0;
1264d043c564SKenneth D. Merry }
1265d043c564SKenneth D. Merry }
1266d043c564SKenneth D. Merry }
1267d043c564SKenneth D. Merry }
1268d043c564SKenneth D. Merry
1269d043c564SKenneth D. Merry /**
1270d043c564SKenneth D. Merry * _mapping_set_mid_to_eid -set map table data from enclosure table
1271d043c564SKenneth D. Merry * @sc: per adapter object
1272d043c564SKenneth D. Merry * @et_entry: enclosure entry
1273d043c564SKenneth D. Merry *
1274d043c564SKenneth D. Merry * Returns nothing
1275d043c564SKenneth D. Merry */
1276d043c564SKenneth D. Merry static inline void
_mapping_set_mid_to_eid(struct mps_softc * sc,struct enc_mapping_table * et_entry)1277d043c564SKenneth D. Merry _mapping_set_mid_to_eid(struct mps_softc *sc,
1278d043c564SKenneth D. Merry struct enc_mapping_table *et_entry)
1279d043c564SKenneth D. Merry {
1280d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry;
1281d043c564SKenneth D. Merry u16 slots = et_entry->num_slots, map_idx;
1282d043c564SKenneth D. Merry u32 start_idx = et_entry->start_index;
1283635e58c7SStephen McConnell
1284d043c564SKenneth D. Merry if (start_idx != MPS_MAPTABLE_BAD_IDX) {
1285d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[start_idx];
1286d043c564SKenneth D. Merry for (map_idx = 0; map_idx < slots; map_idx++, mt_entry++)
1287d043c564SKenneth D. Merry mt_entry->physical_id = et_entry->enclosure_id;
1288d043c564SKenneth D. Merry }
1289d043c564SKenneth D. Merry }
1290d043c564SKenneth D. Merry
1291d043c564SKenneth D. Merry /**
1292d043c564SKenneth D. Merry * _mapping_clear_removed_entries - mark the entries to be cleared
1293d043c564SKenneth D. Merry * @sc: per adapter object
1294d043c564SKenneth D. Merry *
1295d043c564SKenneth D. Merry * Search through the removal table and mark the entries which needs to be
1296d043c564SKenneth D. Merry * flushed to DPM and also updates the map table and enclosure table by
1297d043c564SKenneth D. Merry * clearing the corresponding entries.
1298d043c564SKenneth D. Merry *
1299d043c564SKenneth D. Merry * Returns nothing
1300d043c564SKenneth D. Merry */
1301d043c564SKenneth D. Merry static void
_mapping_clear_removed_entries(struct mps_softc * sc)1302d043c564SKenneth D. Merry _mapping_clear_removed_entries(struct mps_softc *sc)
1303d043c564SKenneth D. Merry {
1304d043c564SKenneth D. Merry u32 remove_idx;
1305d043c564SKenneth D. Merry struct map_removal_table *remove_entry;
1306d043c564SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry;
1307d043c564SKenneth D. Merry u8 done_flag = 0, num_entries, m, i;
1308d043c564SKenneth D. Merry struct enc_mapping_table *et_entry, *from, *to;
1309d043c564SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1310d043c564SKenneth D. Merry
1311d043c564SKenneth D. Merry if (sc->is_dpm_enable) {
1312d043c564SKenneth D. Merry remove_entry = sc->removal_table;
1313d043c564SKenneth D. Merry for (remove_idx = 0; remove_idx < sc->max_devices;
1314d043c564SKenneth D. Merry remove_idx++, remove_entry++) {
1315d043c564SKenneth D. Merry if (remove_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
1316d043c564SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *)
1317d043c564SKenneth D. Merry ((u8 *) sc->dpm_pg0 +
1318d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1319d043c564SKenneth D. Merry dpm_entry += remove_entry->dpm_entry_num;
1320d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low = 0;
1321d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.High = 0;
1322d043c564SKenneth D. Merry dpm_entry->DeviceIndex = 0;
1323d043c564SKenneth D. Merry dpm_entry->MappingInformation = 0;
1324d043c564SKenneth D. Merry dpm_entry->PhysicalBitsMapping = 0;
1325d043c564SKenneth D. Merry sc->dpm_flush_entry[remove_entry->
1326d043c564SKenneth D. Merry dpm_entry_num] = 1;
1327d043c564SKenneth D. Merry sc->dpm_entry_used[remove_entry->dpm_entry_num]
1328d043c564SKenneth D. Merry = 0;
1329d043c564SKenneth D. Merry remove_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
1330d043c564SKenneth D. Merry }
1331d043c564SKenneth D. Merry }
1332d043c564SKenneth D. Merry }
1333635e58c7SStephen McConnell
1334635e58c7SStephen McConnell /*
1335635e58c7SStephen McConnell * When using Enc/Slot mapping, if a new enclosure was added and old
1336635e58c7SStephen McConnell * enclosure space was needed, the enclosure table may now have gaps
1337635e58c7SStephen McConnell * that need to be closed. All enclosure mappings need to be contiguous
1338635e58c7SStephen McConnell * so that space can be reused correctly if available.
1339635e58c7SStephen McConnell */
1340d043c564SKenneth D. Merry if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1341d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1342d043c564SKenneth D. Merry num_entries = sc->num_enc_table_entries;
1343d043c564SKenneth D. Merry while (!done_flag) {
1344d043c564SKenneth D. Merry done_flag = 1;
1345d043c564SKenneth D. Merry et_entry = sc->enclosure_table;
1346d043c564SKenneth D. Merry for (i = 0; i < num_entries; i++, et_entry++) {
1347d043c564SKenneth D. Merry if (!et_entry->enc_handle && et_entry->
1348d043c564SKenneth D. Merry init_complete) {
1349d043c564SKenneth D. Merry done_flag = 0;
1350d043c564SKenneth D. Merry if (i != (num_entries - 1)) {
1351d043c564SKenneth D. Merry from = &sc->enclosure_table
1352d043c564SKenneth D. Merry [i+1];
1353d043c564SKenneth D. Merry to = &sc->enclosure_table[i];
1354d043c564SKenneth D. Merry for (m = i; m < (num_entries -
1355d043c564SKenneth D. Merry 1); m++, from++, to++) {
1356d043c564SKenneth D. Merry _mapping_set_mid_to_eid
1357d043c564SKenneth D. Merry (sc, to);
1358d043c564SKenneth D. Merry *to = *from;
1359d043c564SKenneth D. Merry }
1360d043c564SKenneth D. Merry _mapping_clear_enc_entry(to);
1361d043c564SKenneth D. Merry sc->num_enc_table_entries--;
1362d043c564SKenneth D. Merry num_entries =
1363d043c564SKenneth D. Merry sc->num_enc_table_entries;
1364d043c564SKenneth D. Merry } else {
1365d043c564SKenneth D. Merry _mapping_clear_enc_entry
1366d043c564SKenneth D. Merry (et_entry);
1367d043c564SKenneth D. Merry sc->num_enc_table_entries--;
1368d043c564SKenneth D. Merry num_entries =
1369d043c564SKenneth D. Merry sc->num_enc_table_entries;
1370d043c564SKenneth D. Merry }
1371d043c564SKenneth D. Merry }
1372d043c564SKenneth D. Merry }
1373d043c564SKenneth D. Merry }
1374d043c564SKenneth D. Merry }
1375d043c564SKenneth D. Merry }
1376d043c564SKenneth D. Merry
1377d043c564SKenneth D. Merry /**
1378d043c564SKenneth D. Merry * _mapping_add_new_device -Add the new device into mapping table
1379d043c564SKenneth D. Merry * @sc: per adapter object
1380d043c564SKenneth D. Merry * @topo_change: Topology change event entry
1381d043c564SKenneth D. Merry *
1382635e58c7SStephen McConnell * Search through the topology change event list and update map table,
1383635e58c7SStephen McConnell * enclosure table and DPM pages for the newly added devices.
1384d043c564SKenneth D. Merry *
1385d043c564SKenneth D. Merry * Returns nothing
1386d043c564SKenneth D. Merry */
1387d043c564SKenneth D. Merry static void
_mapping_add_new_device(struct mps_softc * sc,struct _map_topology_change * topo_change)1388d043c564SKenneth D. Merry _mapping_add_new_device(struct mps_softc *sc,
1389d043c564SKenneth D. Merry struct _map_topology_change *topo_change)
1390d043c564SKenneth D. Merry {
1391d043c564SKenneth D. Merry u8 enc_idx, missing_cnt, is_removed = 0;
1392d043c564SKenneth D. Merry u16 dpm_idx;
1393d043c564SKenneth D. Merry u32 search_idx, map_idx;
1394d043c564SKenneth D. Merry u32 entry;
1395d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry;
1396d043c564SKenneth D. Merry struct enc_mapping_table *et_entry;
1397d043c564SKenneth D. Merry struct _map_phy_change *phy_change;
1398d043c564SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1399d043c564SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry;
1400d043c564SKenneth D. Merry uint64_t temp64_var;
1401d043c564SKenneth D. Merry u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
1402d043c564SKenneth D. Merry u8 hdr_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER);
1403d043c564SKenneth D. Merry u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
1404d043c564SKenneth D. Merry
1405d043c564SKenneth D. Merry for (entry = 0; entry < topo_change->num_entries; entry++) {
1406d043c564SKenneth D. Merry phy_change = &topo_change->phy_details[entry];
1407d043c564SKenneth D. Merry if (phy_change->is_processed)
1408d043c564SKenneth D. Merry continue;
1409d043c564SKenneth D. Merry if (phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED ||
1410d043c564SKenneth D. Merry !phy_change->dev_handle) {
1411d043c564SKenneth D. Merry phy_change->is_processed = 1;
1412d043c564SKenneth D. Merry continue;
1413d043c564SKenneth D. Merry }
1414d043c564SKenneth D. Merry if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1415d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1416d043c564SKenneth D. Merry enc_idx = _mapping_get_enc_idx_from_handle
1417d043c564SKenneth D. Merry (sc, topo_change->enc_handle);
1418d043c564SKenneth D. Merry if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
1419d043c564SKenneth D. Merry phy_change->is_processed = 1;
1420635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: "
1421635e58c7SStephen McConnell "failed to add the device with handle "
1422b99419aeSAlexander Motin "0x%04x because enclosure handle 0x%04x "
1423b99419aeSAlexander Motin "is not in the mapping table\n", __func__,
1424b99419aeSAlexander Motin phy_change->dev_handle,
1425b99419aeSAlexander Motin topo_change->enc_handle);
1426d043c564SKenneth D. Merry continue;
1427d043c564SKenneth D. Merry }
1428635e58c7SStephen McConnell
1429635e58c7SStephen McConnell /*
1430635e58c7SStephen McConnell * If the enclosure's start_index is BAD here, it means
1431635e58c7SStephen McConnell * that there is no room in the mapping table to cover
1432635e58c7SStephen McConnell * all of the devices that could be in the enclosure.
1433635e58c7SStephen McConnell * There's no reason to process any of the devices for
1434635e58c7SStephen McConnell * this enclosure since they can't be mapped.
1435635e58c7SStephen McConnell */
1436d043c564SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx];
1437d043c564SKenneth D. Merry if (et_entry->start_index == MPS_MAPTABLE_BAD_IDX) {
1438d043c564SKenneth D. Merry phy_change->is_processed = 1;
1439635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: "
1440635e58c7SStephen McConnell "failed to add the device with handle "
1441635e58c7SStephen McConnell "0x%04x because there is no free space "
1442635e58c7SStephen McConnell "available in the mapping table\n",
1443d043c564SKenneth D. Merry __func__, phy_change->dev_handle);
1444d043c564SKenneth D. Merry continue;
1445d043c564SKenneth D. Merry }
1446635e58c7SStephen McConnell
1447635e58c7SStephen McConnell /*
1448635e58c7SStephen McConnell * Add this device to the mapping table at the correct
1449635e58c7SStephen McConnell * offset where space was found to map the enclosure.
1450635e58c7SStephen McConnell * Then setup the DPM entry information if being used.
1451635e58c7SStephen McConnell */
1452d043c564SKenneth D. Merry map_idx = et_entry->start_index + phy_change->slot -
1453d043c564SKenneth D. Merry et_entry->start_slot;
1454d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx];
1455d043c564SKenneth D. Merry mt_entry->physical_id = phy_change->physical_id;
1456d043c564SKenneth D. Merry mt_entry->id = map_idx;
1457d043c564SKenneth D. Merry mt_entry->dev_handle = phy_change->dev_handle;
1458d043c564SKenneth D. Merry mt_entry->missing_count = 0;
1459d043c564SKenneth D. Merry mt_entry->dpm_entry_num = et_entry->dpm_entry_num;
1460d043c564SKenneth D. Merry mt_entry->device_info = phy_change->device_info |
1461d043c564SKenneth D. Merry (MPS_DEV_RESERVED | MPS_MAP_IN_USE);
1462d043c564SKenneth D. Merry if (sc->is_dpm_enable) {
1463d043c564SKenneth D. Merry dpm_idx = et_entry->dpm_entry_num;
1464d043c564SKenneth D. Merry if (dpm_idx == MPS_DPM_BAD_IDX)
1465d043c564SKenneth D. Merry dpm_idx = _mapping_get_dpm_idx_from_id
1466d043c564SKenneth D. Merry (sc, et_entry->enclosure_id,
1467d043c564SKenneth D. Merry et_entry->phy_bits);
1468d043c564SKenneth D. Merry if (dpm_idx == MPS_DPM_BAD_IDX) {
1469d043c564SKenneth D. Merry dpm_idx = _mapping_get_free_dpm_idx(sc);
1470d043c564SKenneth D. Merry if (dpm_idx != MPS_DPM_BAD_IDX) {
1471d043c564SKenneth D. Merry dpm_entry =
1472d043c564SKenneth D. Merry (Mpi2DriverMap0Entry_t *)
1473d043c564SKenneth D. Merry ((u8 *) sc->dpm_pg0 +
1474d043c564SKenneth D. Merry hdr_sz);
1475d043c564SKenneth D. Merry dpm_entry += dpm_idx;
1476d043c564SKenneth D. Merry dpm_entry->
1477d043c564SKenneth D. Merry PhysicalIdentifier.Low =
1478d043c564SKenneth D. Merry (0xFFFFFFFF &
1479d043c564SKenneth D. Merry et_entry->enclosure_id);
1480d043c564SKenneth D. Merry dpm_entry->
1481d043c564SKenneth D. Merry PhysicalIdentifier.High =
1482d043c564SKenneth D. Merry (et_entry->enclosure_id
1483d043c564SKenneth D. Merry >> 32);
1484d043c564SKenneth D. Merry dpm_entry->DeviceIndex =
1485d043c564SKenneth D. Merry (U16)et_entry->start_index;
1486d043c564SKenneth D. Merry dpm_entry->MappingInformation =
1487d043c564SKenneth D. Merry et_entry->num_slots;
1488d043c564SKenneth D. Merry dpm_entry->MappingInformation
1489d043c564SKenneth D. Merry <<= map_shift;
1490d043c564SKenneth D. Merry dpm_entry->PhysicalBitsMapping
1491d043c564SKenneth D. Merry = et_entry->phy_bits;
1492d043c564SKenneth D. Merry et_entry->dpm_entry_num =
1493d043c564SKenneth D. Merry dpm_idx;
1494d043c564SKenneth D. Merry sc->dpm_entry_used[dpm_idx] = 1;
1495d043c564SKenneth D. Merry sc->dpm_flush_entry[dpm_idx] =
1496d043c564SKenneth D. Merry 1;
1497d043c564SKenneth D. Merry phy_change->is_processed = 1;
1498d043c564SKenneth D. Merry } else {
1499d043c564SKenneth D. Merry phy_change->is_processed = 1;
1500635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR |
1501635e58c7SStephen McConnell MPS_MAPPING, "%s: failed "
1502635e58c7SStephen McConnell "to add the device with "
1503635e58c7SStephen McConnell "handle 0x%04x to "
15049b91b192SKenneth D. Merry "persistent table because "
15059b91b192SKenneth D. Merry "there is no free space "
15069b91b192SKenneth D. Merry "available\n", __func__,
1507d043c564SKenneth D. Merry phy_change->dev_handle);
1508d043c564SKenneth D. Merry }
1509d043c564SKenneth D. Merry } else {
1510d043c564SKenneth D. Merry et_entry->dpm_entry_num = dpm_idx;
1511d043c564SKenneth D. Merry mt_entry->dpm_entry_num = dpm_idx;
1512d043c564SKenneth D. Merry }
1513d043c564SKenneth D. Merry }
1514d043c564SKenneth D. Merry et_entry->init_complete = 1;
1515d043c564SKenneth D. Merry } else if ((ioc_pg8_flags &
1516d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1517d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
1518635e58c7SStephen McConnell /*
1519635e58c7SStephen McConnell * Get the mapping table index for this device. If it's
1520635e58c7SStephen McConnell * not in the mapping table yet, find a free entry if
1521635e58c7SStephen McConnell * one is available. If there are no free entries, look
1522635e58c7SStephen McConnell * for the entry that has the highest missing count. If
1523635e58c7SStephen McConnell * none of that works to find an entry in the mapping
1524635e58c7SStephen McConnell * table, there is a problem. Log a message and just
1525635e58c7SStephen McConnell * continue on.
1526635e58c7SStephen McConnell */
1527d043c564SKenneth D. Merry map_idx = _mapping_get_mt_idx_from_id
1528d043c564SKenneth D. Merry (sc, phy_change->physical_id);
1529d043c564SKenneth D. Merry if (map_idx == MPS_MAPTABLE_BAD_IDX) {
1530d043c564SKenneth D. Merry search_idx = sc->num_rsvd_entries;
1531d043c564SKenneth D. Merry if (topo_change->exp_handle)
1532d043c564SKenneth D. Merry search_idx += max_num_phy_ids;
1533d043c564SKenneth D. Merry map_idx = _mapping_get_free_mt_idx(sc,
1534d043c564SKenneth D. Merry search_idx);
1535d043c564SKenneth D. Merry }
1536635e58c7SStephen McConnell
1537635e58c7SStephen McConnell /*
1538635e58c7SStephen McConnell * If an entry will be used that has a missing device,
1539635e58c7SStephen McConnell * clear its entry from the DPM in the controller.
1540635e58c7SStephen McConnell */
1541d043c564SKenneth D. Merry if (map_idx == MPS_MAPTABLE_BAD_IDX) {
1542d043c564SKenneth D. Merry map_idx = _mapping_get_high_missing_mt_idx(sc);
1543d043c564SKenneth D. Merry if (map_idx != MPS_MAPTABLE_BAD_IDX) {
1544d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx];
1545635e58c7SStephen McConnell _mapping_add_to_removal_table(sc,
1546635e58c7SStephen McConnell mt_entry->dpm_entry_num);
1547d043c564SKenneth D. Merry is_removed = 1;
1548d043c564SKenneth D. Merry mt_entry->init_complete = 0;
1549d043c564SKenneth D. Merry }
1550d043c564SKenneth D. Merry }
1551d043c564SKenneth D. Merry if (map_idx != MPS_MAPTABLE_BAD_IDX) {
1552d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx];
1553d043c564SKenneth D. Merry mt_entry->physical_id = phy_change->physical_id;
1554d043c564SKenneth D. Merry mt_entry->id = map_idx;
1555d043c564SKenneth D. Merry mt_entry->dev_handle = phy_change->dev_handle;
1556d043c564SKenneth D. Merry mt_entry->missing_count = 0;
1557d043c564SKenneth D. Merry mt_entry->device_info = phy_change->device_info
1558d043c564SKenneth D. Merry | (MPS_DEV_RESERVED | MPS_MAP_IN_USE);
1559d043c564SKenneth D. Merry } else {
1560d043c564SKenneth D. Merry phy_change->is_processed = 1;
1561635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: "
1562635e58c7SStephen McConnell "failed to add the device with handle "
1563635e58c7SStephen McConnell "0x%04x because there is no free space "
1564635e58c7SStephen McConnell "available in the mapping table\n",
1565d043c564SKenneth D. Merry __func__, phy_change->dev_handle);
1566d043c564SKenneth D. Merry continue;
1567d043c564SKenneth D. Merry }
1568d043c564SKenneth D. Merry if (sc->is_dpm_enable) {
1569d043c564SKenneth D. Merry if (mt_entry->dpm_entry_num !=
1570d043c564SKenneth D. Merry MPS_DPM_BAD_IDX) {
1571d043c564SKenneth D. Merry dpm_idx = mt_entry->dpm_entry_num;
1572d043c564SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *)
1573d043c564SKenneth D. Merry ((u8 *)sc->dpm_pg0 + hdr_sz);
1574d043c564SKenneth D. Merry dpm_entry += dpm_idx;
1575d043c564SKenneth D. Merry missing_cnt = dpm_entry->
1576d043c564SKenneth D. Merry MappingInformation &
1577d043c564SKenneth D. Merry MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
1578d043c564SKenneth D. Merry temp64_var = dpm_entry->
1579d043c564SKenneth D. Merry PhysicalIdentifier.High;
1580d043c564SKenneth D. Merry temp64_var = (temp64_var << 32) |
1581d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low;
1582635e58c7SStephen McConnell
1583635e58c7SStephen McConnell /*
1584635e58c7SStephen McConnell * If the Mapping Table's info is not
1585635e58c7SStephen McConnell * the same as the DPM entry, clear the
1586635e58c7SStephen McConnell * init_complete flag so that it's
1587635e58c7SStephen McConnell * updated.
1588635e58c7SStephen McConnell */
1589d043c564SKenneth D. Merry if ((mt_entry->physical_id ==
1590d043c564SKenneth D. Merry temp64_var) && !missing_cnt)
1591d043c564SKenneth D. Merry mt_entry->init_complete = 1;
1592635e58c7SStephen McConnell else
1593635e58c7SStephen McConnell mt_entry->init_complete = 0;
1594d043c564SKenneth D. Merry } else {
1595d043c564SKenneth D. Merry dpm_idx = _mapping_get_free_dpm_idx(sc);
1596d043c564SKenneth D. Merry mt_entry->init_complete = 0;
1597d043c564SKenneth D. Merry }
1598d043c564SKenneth D. Merry if (dpm_idx != MPS_DPM_BAD_IDX &&
1599d043c564SKenneth D. Merry !mt_entry->init_complete) {
1600d043c564SKenneth D. Merry mt_entry->dpm_entry_num = dpm_idx;
1601d043c564SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *)
1602d043c564SKenneth D. Merry ((u8 *)sc->dpm_pg0 + hdr_sz);
1603d043c564SKenneth D. Merry dpm_entry += dpm_idx;
1604d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low =
1605d043c564SKenneth D. Merry (0xFFFFFFFF &
1606d043c564SKenneth D. Merry mt_entry->physical_id);
1607d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.High =
1608d043c564SKenneth D. Merry (mt_entry->physical_id >> 32);
1609d043c564SKenneth D. Merry dpm_entry->DeviceIndex = (U16) map_idx;
1610d043c564SKenneth D. Merry dpm_entry->MappingInformation = 0;
1611d043c564SKenneth D. Merry dpm_entry->PhysicalBitsMapping = 0;
1612d043c564SKenneth D. Merry sc->dpm_entry_used[dpm_idx] = 1;
1613d043c564SKenneth D. Merry sc->dpm_flush_entry[dpm_idx] = 1;
1614d043c564SKenneth D. Merry phy_change->is_processed = 1;
1615d043c564SKenneth D. Merry } else if (dpm_idx == MPS_DPM_BAD_IDX) {
1616d043c564SKenneth D. Merry phy_change->is_processed = 1;
1617635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING,
1618635e58c7SStephen McConnell "%s: failed to add the device with "
1619635e58c7SStephen McConnell "handle 0x%04x to persistent table "
1620635e58c7SStephen McConnell "because there is no free space "
16219b91b192SKenneth D. Merry "available\n", __func__,
1622d043c564SKenneth D. Merry phy_change->dev_handle);
1623d043c564SKenneth D. Merry }
1624d043c564SKenneth D. Merry }
1625d043c564SKenneth D. Merry mt_entry->init_complete = 1;
1626d043c564SKenneth D. Merry }
1627d043c564SKenneth D. Merry
1628d043c564SKenneth D. Merry phy_change->is_processed = 1;
1629d043c564SKenneth D. Merry }
1630d043c564SKenneth D. Merry if (is_removed)
1631d043c564SKenneth D. Merry _mapping_clear_removed_entries(sc);
1632d043c564SKenneth D. Merry }
1633d043c564SKenneth D. Merry
1634d043c564SKenneth D. Merry /**
1635d043c564SKenneth D. Merry * _mapping_flush_dpm_pages -Flush the DPM pages to NVRAM
1636d043c564SKenneth D. Merry * @sc: per adapter object
1637d043c564SKenneth D. Merry *
1638d043c564SKenneth D. Merry * Returns nothing
1639d043c564SKenneth D. Merry */
1640d043c564SKenneth D. Merry static void
_mapping_flush_dpm_pages(struct mps_softc * sc)1641d043c564SKenneth D. Merry _mapping_flush_dpm_pages(struct mps_softc *sc)
1642d043c564SKenneth D. Merry {
1643d043c564SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry;
1644d043c564SKenneth D. Merry Mpi2ConfigReply_t mpi_reply;
1645d043c564SKenneth D. Merry Mpi2DriverMappingPage0_t config_page;
1646d043c564SKenneth D. Merry u16 entry_num;
1647d043c564SKenneth D. Merry
1648d043c564SKenneth D. Merry for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) {
1649d043c564SKenneth D. Merry if (!sc->dpm_flush_entry[entry_num])
1650d043c564SKenneth D. Merry continue;
1651d043c564SKenneth D. Merry memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
1652d043c564SKenneth D. Merry memcpy(&config_page.Header, (u8 *)sc->dpm_pg0,
1653d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1654d043c564SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
1655d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1656d043c564SKenneth D. Merry dpm_entry += entry_num;
1657d043c564SKenneth D. Merry dpm_entry->MappingInformation = htole16(dpm_entry->
1658d043c564SKenneth D. Merry MappingInformation);
1659d043c564SKenneth D. Merry dpm_entry->DeviceIndex = htole16(dpm_entry->DeviceIndex);
1660d043c564SKenneth D. Merry dpm_entry->PhysicalBitsMapping = htole32(dpm_entry->
1661d043c564SKenneth D. Merry PhysicalBitsMapping);
1662d043c564SKenneth D. Merry memcpy(&config_page.Entry, (u8 *)dpm_entry,
1663d043c564SKenneth D. Merry sizeof(Mpi2DriverMap0Entry_t));
1664d043c564SKenneth D. Merry /* TODO-How to handle failed writes? */
1665635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Flushing DPM entry %d.\n",
1666635e58c7SStephen McConnell __func__, entry_num);
1667d043c564SKenneth D. Merry if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
1668d043c564SKenneth D. Merry entry_num)) {
1669635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Flush of "
1670635e58c7SStephen McConnell "DPM entry %d for device failed\n", __func__,
1671635e58c7SStephen McConnell entry_num);
1672d043c564SKenneth D. Merry } else
1673d043c564SKenneth D. Merry sc->dpm_flush_entry[entry_num] = 0;
1674d043c564SKenneth D. Merry dpm_entry->MappingInformation = le16toh(dpm_entry->
1675d043c564SKenneth D. Merry MappingInformation);
1676d043c564SKenneth D. Merry dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
1677d043c564SKenneth D. Merry dpm_entry->PhysicalBitsMapping = le32toh(dpm_entry->
1678d043c564SKenneth D. Merry PhysicalBitsMapping);
1679d043c564SKenneth D. Merry }
1680d043c564SKenneth D. Merry }
1681d043c564SKenneth D. Merry
1682d043c564SKenneth D. Merry /**
1683d043c564SKenneth D. Merry * _mapping_allocate_memory- allocates the memory required for mapping tables
1684d043c564SKenneth D. Merry * @sc: per adapter object
1685d043c564SKenneth D. Merry *
1686d043c564SKenneth D. Merry * Allocates the memory for all the tables required for host mapping
1687d043c564SKenneth D. Merry *
1688d043c564SKenneth D. Merry * Return 0 on success or non-zero on failure.
1689d043c564SKenneth D. Merry */
1690d043c564SKenneth D. Merry int
mps_mapping_allocate_memory(struct mps_softc * sc)1691d043c564SKenneth D. Merry mps_mapping_allocate_memory(struct mps_softc *sc)
1692d043c564SKenneth D. Merry {
1693d043c564SKenneth D. Merry uint32_t dpm_pg0_sz;
1694d043c564SKenneth D. Merry
1695ac2fffa4SPedro F. Giffuni sc->mapping_table = malloc((sizeof(struct dev_mapping_table) *
1696ac2fffa4SPedro F. Giffuni sc->max_devices), M_MPT2, M_ZERO|M_NOWAIT);
1697d043c564SKenneth D. Merry if (!sc->mapping_table)
1698d043c564SKenneth D. Merry goto free_resources;
1699d043c564SKenneth D. Merry
1700ac2fffa4SPedro F. Giffuni sc->removal_table = malloc((sizeof(struct map_removal_table) *
1701ac2fffa4SPedro F. Giffuni sc->max_devices), M_MPT2, M_ZERO|M_NOWAIT);
1702d043c564SKenneth D. Merry if (!sc->removal_table)
1703d043c564SKenneth D. Merry goto free_resources;
1704d043c564SKenneth D. Merry
1705ac2fffa4SPedro F. Giffuni sc->enclosure_table = malloc((sizeof(struct enc_mapping_table) *
1706ac2fffa4SPedro F. Giffuni sc->max_enclosures), M_MPT2, M_ZERO|M_NOWAIT);
1707d043c564SKenneth D. Merry if (!sc->enclosure_table)
1708d043c564SKenneth D. Merry goto free_resources;
1709d043c564SKenneth D. Merry
1710ac2fffa4SPedro F. Giffuni sc->dpm_entry_used = malloc((sizeof(u8) * sc->max_dpm_entries),
1711d043c564SKenneth D. Merry M_MPT2, M_ZERO|M_NOWAIT);
1712d043c564SKenneth D. Merry if (!sc->dpm_entry_used)
1713d043c564SKenneth D. Merry goto free_resources;
1714d043c564SKenneth D. Merry
1715ac2fffa4SPedro F. Giffuni sc->dpm_flush_entry = malloc((sizeof(u8) * sc->max_dpm_entries),
1716d043c564SKenneth D. Merry M_MPT2, M_ZERO|M_NOWAIT);
1717d043c564SKenneth D. Merry if (!sc->dpm_flush_entry)
1718d043c564SKenneth D. Merry goto free_resources;
1719d043c564SKenneth D. Merry
1720d043c564SKenneth D. Merry dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) +
1721d043c564SKenneth D. Merry (sc->max_dpm_entries * sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY));
1722d043c564SKenneth D. Merry
1723d043c564SKenneth D. Merry sc->dpm_pg0 = malloc(dpm_pg0_sz, M_MPT2, M_ZERO|M_NOWAIT);
1724d043c564SKenneth D. Merry if (!sc->dpm_pg0) {
1725d043c564SKenneth D. Merry printf("%s: memory alloc failed for dpm page; disabling dpm\n",
1726d043c564SKenneth D. Merry __func__);
1727d043c564SKenneth D. Merry sc->is_dpm_enable = 0;
1728d043c564SKenneth D. Merry }
1729d043c564SKenneth D. Merry
1730d043c564SKenneth D. Merry return 0;
1731d043c564SKenneth D. Merry
1732d043c564SKenneth D. Merry free_resources:
1733d043c564SKenneth D. Merry free(sc->mapping_table, M_MPT2);
1734d043c564SKenneth D. Merry free(sc->removal_table, M_MPT2);
1735d043c564SKenneth D. Merry free(sc->enclosure_table, M_MPT2);
1736d043c564SKenneth D. Merry free(sc->dpm_entry_used, M_MPT2);
1737d043c564SKenneth D. Merry free(sc->dpm_flush_entry, M_MPT2);
1738d043c564SKenneth D. Merry free(sc->dpm_pg0, M_MPT2);
1739d043c564SKenneth D. Merry printf("%s: device initialization failed due to failure in mapping "
1740d043c564SKenneth D. Merry "table memory allocation\n", __func__);
1741d043c564SKenneth D. Merry return -1;
1742d043c564SKenneth D. Merry }
1743d043c564SKenneth D. Merry
1744d043c564SKenneth D. Merry /**
1745d043c564SKenneth D. Merry * mps_mapping_free_memory- frees the memory allocated for mapping tables
1746d043c564SKenneth D. Merry * @sc: per adapter object
1747d043c564SKenneth D. Merry *
1748d043c564SKenneth D. Merry * Returns nothing.
1749d043c564SKenneth D. Merry */
1750d043c564SKenneth D. Merry void
mps_mapping_free_memory(struct mps_softc * sc)1751d043c564SKenneth D. Merry mps_mapping_free_memory(struct mps_softc *sc)
1752d043c564SKenneth D. Merry {
1753d043c564SKenneth D. Merry free(sc->mapping_table, M_MPT2);
1754d043c564SKenneth D. Merry free(sc->removal_table, M_MPT2);
1755d043c564SKenneth D. Merry free(sc->enclosure_table, M_MPT2);
1756d043c564SKenneth D. Merry free(sc->dpm_entry_used, M_MPT2);
1757d043c564SKenneth D. Merry free(sc->dpm_flush_entry, M_MPT2);
1758d043c564SKenneth D. Merry free(sc->dpm_pg0, M_MPT2);
1759d043c564SKenneth D. Merry }
1760d043c564SKenneth D. Merry
1761d043c564SKenneth D. Merry static void
_mapping_process_dpm_pg0(struct mps_softc * sc)1762d043c564SKenneth D. Merry _mapping_process_dpm_pg0(struct mps_softc *sc)
1763d043c564SKenneth D. Merry {
1764d043c564SKenneth D. Merry u8 missing_cnt, enc_idx;
1765d043c564SKenneth D. Merry u16 slot_id, entry_num, num_slots;
1766d043c564SKenneth D. Merry u32 map_idx, dev_idx, start_idx, end_idx;
1767d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry;
1768d043c564SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry;
1769d043c564SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1770d043c564SKenneth D. Merry u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
1771d043c564SKenneth D. Merry struct enc_mapping_table *et_entry;
1772d043c564SKenneth D. Merry u64 physical_id;
1773d043c564SKenneth D. Merry u32 phy_bits = 0;
1774d043c564SKenneth D. Merry
1775635e58c7SStephen McConnell /*
1776635e58c7SStephen McConnell * start_idx and end_idx are only used for IR.
1777635e58c7SStephen McConnell */
1778d043c564SKenneth D. Merry if (sc->ir_firmware)
1779d043c564SKenneth D. Merry _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
1780d043c564SKenneth D. Merry
1781635e58c7SStephen McConnell /*
1782635e58c7SStephen McConnell * Look through all of the DPM entries that were read from the
1783635e58c7SStephen McConnell * controller and copy them over to the driver's internal table if they
1784635e58c7SStephen McConnell * have a non-zero ID. At this point, any ID with a value of 0 would be
1785635e58c7SStephen McConnell * invalid, so don't copy it.
1786635e58c7SStephen McConnell */
1787635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Start copy of %d DPM entries into the "
1788635e58c7SStephen McConnell "mapping table.\n", __func__, sc->max_dpm_entries);
1789d043c564SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *) ((uint8_t *) sc->dpm_pg0 +
1790d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1791d043c564SKenneth D. Merry for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++,
1792d043c564SKenneth D. Merry dpm_entry++) {
1793d043c564SKenneth D. Merry physical_id = dpm_entry->PhysicalIdentifier.High;
1794d043c564SKenneth D. Merry physical_id = (physical_id << 32) |
1795d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low;
1796d043c564SKenneth D. Merry if (!physical_id) {
1797d043c564SKenneth D. Merry sc->dpm_entry_used[entry_num] = 0;
1798d043c564SKenneth D. Merry continue;
1799d043c564SKenneth D. Merry }
1800d043c564SKenneth D. Merry sc->dpm_entry_used[entry_num] = 1;
1801d043c564SKenneth D. Merry dpm_entry->MappingInformation = le16toh(dpm_entry->
1802d043c564SKenneth D. Merry MappingInformation);
1803d043c564SKenneth D. Merry missing_cnt = dpm_entry->MappingInformation &
1804d043c564SKenneth D. Merry MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
1805d043c564SKenneth D. Merry dev_idx = le16toh(dpm_entry->DeviceIndex);
1806d043c564SKenneth D. Merry phy_bits = le32toh(dpm_entry->PhysicalBitsMapping);
1807635e58c7SStephen McConnell
1808635e58c7SStephen McConnell /*
1809635e58c7SStephen McConnell * Volumes are at special locations in the mapping table so
1810635e58c7SStephen McConnell * account for that. Volume mapping table entries do not depend
1811635e58c7SStephen McConnell * on the type of mapping, so continue the loop after adding
1812635e58c7SStephen McConnell * volumes to the mapping table.
1813635e58c7SStephen McConnell */
1814d043c564SKenneth D. Merry if (sc->ir_firmware && (dev_idx >= start_idx) &&
1815d043c564SKenneth D. Merry (dev_idx <= end_idx)) {
1816d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[dev_idx];
1817635e58c7SStephen McConnell mt_entry->physical_id =
1818635e58c7SStephen McConnell dpm_entry->PhysicalIdentifier.High;
1819d043c564SKenneth D. Merry mt_entry->physical_id = (mt_entry->physical_id << 32) |
1820d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low;
1821d043c564SKenneth D. Merry mt_entry->id = dev_idx;
1822d043c564SKenneth D. Merry mt_entry->missing_count = missing_cnt;
1823d043c564SKenneth D. Merry mt_entry->dpm_entry_num = entry_num;
1824d043c564SKenneth D. Merry mt_entry->device_info = MPS_DEV_RESERVED;
1825d043c564SKenneth D. Merry continue;
1826d043c564SKenneth D. Merry }
1827d043c564SKenneth D. Merry if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1828d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1829635e58c7SStephen McConnell /*
1830635e58c7SStephen McConnell * The dev_idx for an enclosure is the start index. If
1831635e58c7SStephen McConnell * the start index is within the controller's default
1832635e58c7SStephen McConnell * enclosure area, set the number of slots for this
1833635e58c7SStephen McConnell * enclosure to the max allowed. Otherwise, it should be
1834635e58c7SStephen McConnell * a normal enclosure and the number of slots is in the
1835635e58c7SStephen McConnell * DPM entry's Mapping Information.
1836635e58c7SStephen McConnell */
1837d043c564SKenneth D. Merry if (dev_idx < (sc->num_rsvd_entries +
1838d043c564SKenneth D. Merry max_num_phy_ids)) {
1839d043c564SKenneth D. Merry slot_id = 0;
1840d043c564SKenneth D. Merry if (ioc_pg8_flags &
1841d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1)
1842d043c564SKenneth D. Merry slot_id = 1;
1843d043c564SKenneth D. Merry num_slots = max_num_phy_ids;
1844d043c564SKenneth D. Merry } else {
1845d043c564SKenneth D. Merry slot_id = 0;
1846d043c564SKenneth D. Merry num_slots = dpm_entry->MappingInformation &
1847d043c564SKenneth D. Merry MPI2_DRVMAP0_MAPINFO_SLOT_MASK;
1848d043c564SKenneth D. Merry num_slots >>= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
1849d043c564SKenneth D. Merry }
1850d043c564SKenneth D. Merry enc_idx = sc->num_enc_table_entries;
1851d043c564SKenneth D. Merry if (enc_idx >= sc->max_enclosures) {
1852635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: "
1853635e58c7SStephen McConnell "Number of enclosure entries in DPM exceed "
1854635e58c7SStephen McConnell "the max allowed of %d.\n", __func__,
1855d043c564SKenneth D. Merry sc->max_enclosures);
1856d043c564SKenneth D. Merry break;
1857d043c564SKenneth D. Merry }
1858d043c564SKenneth D. Merry sc->num_enc_table_entries++;
1859d043c564SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx];
1860d043c564SKenneth D. Merry physical_id = dpm_entry->PhysicalIdentifier.High;
1861d043c564SKenneth D. Merry et_entry->enclosure_id = (physical_id << 32) |
1862d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low;
1863d043c564SKenneth D. Merry et_entry->start_index = dev_idx;
1864d043c564SKenneth D. Merry et_entry->dpm_entry_num = entry_num;
1865d043c564SKenneth D. Merry et_entry->num_slots = num_slots;
1866d043c564SKenneth D. Merry et_entry->start_slot = slot_id;
1867d043c564SKenneth D. Merry et_entry->missing_count = missing_cnt;
1868d043c564SKenneth D. Merry et_entry->phy_bits = phy_bits;
1869d043c564SKenneth D. Merry
1870635e58c7SStephen McConnell /*
1871635e58c7SStephen McConnell * Initialize all entries for this enclosure in the
1872635e58c7SStephen McConnell * mapping table and mark them as reserved. The actual
1873635e58c7SStephen McConnell * devices have not been processed yet but when they are
1874635e58c7SStephen McConnell * they will use these entries. If an entry is found
1875635e58c7SStephen McConnell * that already has a valid DPM index, the mapping table
1876635e58c7SStephen McConnell * is corrupt. This can happen if the mapping type is
1877635e58c7SStephen McConnell * changed without clearing all of the DPM entries in
1878635e58c7SStephen McConnell * the controller.
1879635e58c7SStephen McConnell */
1880d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[dev_idx];
1881d043c564SKenneth D. Merry for (map_idx = dev_idx; map_idx < (dev_idx + num_slots);
1882d043c564SKenneth D. Merry map_idx++, mt_entry++) {
1883d043c564SKenneth D. Merry if (mt_entry->dpm_entry_num !=
1884d043c564SKenneth D. Merry MPS_DPM_BAD_IDX) {
1885635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING,
1886635e58c7SStephen McConnell "%s: Conflict in mapping table for "
1887b99419aeSAlexander Motin "enclosure %d device %d\n",
1888b99419aeSAlexander Motin __func__, enc_idx, map_idx);
1889d043c564SKenneth D. Merry break;
1890d043c564SKenneth D. Merry }
1891635e58c7SStephen McConnell physical_id =
1892635e58c7SStephen McConnell dpm_entry->PhysicalIdentifier.High;
1893d043c564SKenneth D. Merry mt_entry->physical_id = (physical_id << 32) |
1894d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low;
1895d043c564SKenneth D. Merry mt_entry->phy_bits = phy_bits;
1896d043c564SKenneth D. Merry mt_entry->id = dev_idx;
1897d043c564SKenneth D. Merry mt_entry->dpm_entry_num = entry_num;
1898d043c564SKenneth D. Merry mt_entry->missing_count = missing_cnt;
1899d043c564SKenneth D. Merry mt_entry->device_info = MPS_DEV_RESERVED;
1900d043c564SKenneth D. Merry }
1901d043c564SKenneth D. Merry } else if ((ioc_pg8_flags &
1902d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1903d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
1904635e58c7SStephen McConnell /*
1905635e58c7SStephen McConnell * Device mapping, so simply copy the DPM entries to the
1906635e58c7SStephen McConnell * mapping table, but check for a corrupt mapping table
1907635e58c7SStephen McConnell * (as described above in Enc/Slot mapping).
1908635e58c7SStephen McConnell */
1909d043c564SKenneth D. Merry map_idx = dev_idx;
1910d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx];
1911d043c564SKenneth D. Merry if (mt_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
1912635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: "
1913635e58c7SStephen McConnell "Conflict in mapping table for device %d\n",
1914635e58c7SStephen McConnell __func__, map_idx);
1915d043c564SKenneth D. Merry break;
1916d043c564SKenneth D. Merry }
1917d043c564SKenneth D. Merry physical_id = dpm_entry->PhysicalIdentifier.High;
1918d043c564SKenneth D. Merry mt_entry->physical_id = (physical_id << 32) |
1919d043c564SKenneth D. Merry dpm_entry->PhysicalIdentifier.Low;
1920d043c564SKenneth D. Merry mt_entry->phy_bits = phy_bits;
1921d043c564SKenneth D. Merry mt_entry->id = dev_idx;
1922d043c564SKenneth D. Merry mt_entry->missing_count = missing_cnt;
1923d043c564SKenneth D. Merry mt_entry->dpm_entry_num = entry_num;
1924d043c564SKenneth D. Merry mt_entry->device_info = MPS_DEV_RESERVED;
1925d043c564SKenneth D. Merry }
1926d043c564SKenneth D. Merry } /*close the loop for DPM table */
1927d043c564SKenneth D. Merry }
1928d043c564SKenneth D. Merry
1929d043c564SKenneth D. Merry /*
1930d043c564SKenneth D. Merry * mps_mapping_check_devices - start of the day check for device availabilty
1931d043c564SKenneth D. Merry * @sc: per adapter object
1932d043c564SKenneth D. Merry *
1933d043c564SKenneth D. Merry * Returns nothing.
1934d043c564SKenneth D. Merry */
1935d043c564SKenneth D. Merry void
mps_mapping_check_devices(void * data)1936635e58c7SStephen McConnell mps_mapping_check_devices(void *data)
1937d043c564SKenneth D. Merry {
1938d043c564SKenneth D. Merry u32 i;
1939d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry;
1940635e58c7SStephen McConnell struct mps_softc *sc = (struct mps_softc *)data;
1941d043c564SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1942d043c564SKenneth D. Merry struct enc_mapping_table *et_entry;
1943635e58c7SStephen McConnell u32 start_idx = 0, end_idx = 0;
1944635e58c7SStephen McConnell u8 stop_device_checks = 0;
1945d043c564SKenneth D. Merry
1946635e58c7SStephen McConnell MPS_FUNCTRACE(sc);
1947635e58c7SStephen McConnell
1948635e58c7SStephen McConnell /*
1949635e58c7SStephen McConnell * Clear this flag so that this function is never called again except
1950635e58c7SStephen McConnell * within this function if the check needs to be done again. The
1951635e58c7SStephen McConnell * purpose is to check for missing devices that are currently in the
1952635e58c7SStephen McConnell * mapping table so do this only at driver init after discovery.
1953635e58c7SStephen McConnell */
1954d043c564SKenneth D. Merry sc->track_mapping_events = 0;
1955635e58c7SStephen McConnell
1956635e58c7SStephen McConnell /*
1957635e58c7SStephen McConnell * callout synchronization
1958635e58c7SStephen McConnell * This is used to prevent race conditions for the callout.
1959635e58c7SStephen McConnell */
1960635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Start check for missing devices.\n",
1961635e58c7SStephen McConnell __func__);
1962635e58c7SStephen McConnell mtx_assert(&sc->mps_mtx, MA_OWNED);
1963635e58c7SStephen McConnell if ((callout_pending(&sc->device_check_callout)) ||
1964635e58c7SStephen McConnell (!callout_active(&sc->device_check_callout))) {
1965635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Device Check Callout is "
1966635e58c7SStephen McConnell "already pending or not active.\n", __func__);
1967635e58c7SStephen McConnell return;
1968635e58c7SStephen McConnell }
1969635e58c7SStephen McConnell callout_deactivate(&sc->device_check_callout);
1970635e58c7SStephen McConnell
1971635e58c7SStephen McConnell /*
1972635e58c7SStephen McConnell * Use callout to check if any devices in the mapping table have been
1973635e58c7SStephen McConnell * processed yet. If ALL devices are marked as not init_complete, no
1974635e58c7SStephen McConnell * devices have been processed and mapped. Until devices are mapped
1975635e58c7SStephen McConnell * there's no reason to mark them as missing. Continue resetting this
1976635e58c7SStephen McConnell * callout until devices have been mapped.
1977635e58c7SStephen McConnell */
1978635e58c7SStephen McConnell if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1979635e58c7SStephen McConnell MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1980635e58c7SStephen McConnell et_entry = sc->enclosure_table;
1981635e58c7SStephen McConnell for (i = 0; i < sc->num_enc_table_entries; i++, et_entry++) {
1982635e58c7SStephen McConnell if (et_entry->init_complete) {
1983635e58c7SStephen McConnell stop_device_checks = 1;
1984d043c564SKenneth D. Merry break;
1985635e58c7SStephen McConnell }
1986635e58c7SStephen McConnell }
1987635e58c7SStephen McConnell } else if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1988635e58c7SStephen McConnell MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
1989635e58c7SStephen McConnell mt_entry = sc->mapping_table;
1990635e58c7SStephen McConnell for (i = 0; i < sc->max_devices; i++, mt_entry++) {
1991635e58c7SStephen McConnell if (mt_entry->init_complete) {
1992635e58c7SStephen McConnell stop_device_checks = 1;
1993635e58c7SStephen McConnell break;
1994635e58c7SStephen McConnell }
1995635e58c7SStephen McConnell }
1996635e58c7SStephen McConnell }
1997d043c564SKenneth D. Merry
1998635e58c7SStephen McConnell /*
1999635e58c7SStephen McConnell * Setup another callout check after a delay. Keep doing this until
2000635e58c7SStephen McConnell * devices are mapped.
2001635e58c7SStephen McConnell */
2002635e58c7SStephen McConnell if (!stop_device_checks) {
2003635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: No devices have been mapped. "
2004635e58c7SStephen McConnell "Reset callout to check again after a %d second delay.\n",
2005635e58c7SStephen McConnell __func__, MPS_MISSING_CHECK_DELAY);
2006635e58c7SStephen McConnell callout_reset(&sc->device_check_callout,
2007635e58c7SStephen McConnell MPS_MISSING_CHECK_DELAY * hz, mps_mapping_check_devices,
2008635e58c7SStephen McConnell sc);
2009635e58c7SStephen McConnell return;
2010635e58c7SStephen McConnell }
2011635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Device check complete.\n", __func__);
2012d043c564SKenneth D. Merry
2013635e58c7SStephen McConnell /*
2014635e58c7SStephen McConnell * Depending on the mapping type, check if devices have been processed
2015635e58c7SStephen McConnell * and update their missing counts if not processed.
2016635e58c7SStephen McConnell */
2017d043c564SKenneth D. Merry if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
2018d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
2019d043c564SKenneth D. Merry et_entry = sc->enclosure_table;
2020d043c564SKenneth D. Merry for (i = 0; i < sc->num_enc_table_entries; i++, et_entry++) {
2021d043c564SKenneth D. Merry if (!et_entry->init_complete) {
2022d043c564SKenneth D. Merry if (et_entry->missing_count <
2023d043c564SKenneth D. Merry MPS_MAX_MISSING_COUNT) {
2024635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: "
2025635e58c7SStephen McConnell "Enclosure %d is missing from the "
2026635e58c7SStephen McConnell "topology. Update its missing "
2027635e58c7SStephen McConnell "count.\n", __func__, i);
2028d043c564SKenneth D. Merry et_entry->missing_count++;
2029d043c564SKenneth D. Merry if (et_entry->dpm_entry_num !=
2030635e58c7SStephen McConnell MPS_DPM_BAD_IDX) {
2031d043c564SKenneth D. Merry _mapping_commit_enc_entry(sc,
2032d043c564SKenneth D. Merry et_entry);
2033d043c564SKenneth D. Merry }
2034635e58c7SStephen McConnell }
2035d043c564SKenneth D. Merry et_entry->init_complete = 1;
2036d043c564SKenneth D. Merry }
2037d043c564SKenneth D. Merry }
2038d043c564SKenneth D. Merry if (!sc->ir_firmware)
2039d043c564SKenneth D. Merry return;
2040d043c564SKenneth D. Merry _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
2041d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[start_idx];
2042635e58c7SStephen McConnell } else if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
2043635e58c7SStephen McConnell MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
2044635e58c7SStephen McConnell start_idx = 0;
2045635e58c7SStephen McConnell end_idx = sc->max_devices - 1;
2046635e58c7SStephen McConnell mt_entry = sc->mapping_table;
2047635e58c7SStephen McConnell }
2048635e58c7SStephen McConnell
2049635e58c7SStephen McConnell /*
2050635e58c7SStephen McConnell * The start and end indices have been set above according to the
2051635e58c7SStephen McConnell * mapping type. Go through these mappings and update any entries that
2052635e58c7SStephen McConnell * do not have the init_complete flag set, which means they are missing.
2053635e58c7SStephen McConnell */
2054635e58c7SStephen McConnell if (end_idx == 0)
2055635e58c7SStephen McConnell return;
2056d043c564SKenneth D. Merry for (i = start_idx; i < (end_idx + 1); i++, mt_entry++) {
2057d043c564SKenneth D. Merry if (mt_entry->device_info & MPS_DEV_RESERVED
2058d043c564SKenneth D. Merry && !mt_entry->physical_id)
2059d043c564SKenneth D. Merry mt_entry->init_complete = 1;
2060d043c564SKenneth D. Merry else if (mt_entry->device_info & MPS_DEV_RESERVED) {
2061d043c564SKenneth D. Merry if (!mt_entry->init_complete) {
2062635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Device in "
2063635e58c7SStephen McConnell "mapping table at index %d is missing from "
2064635e58c7SStephen McConnell "topology. Update its missing count.\n",
2065635e58c7SStephen McConnell __func__, i);
2066d043c564SKenneth D. Merry if (mt_entry->missing_count <
2067d043c564SKenneth D. Merry MPS_MAX_MISSING_COUNT) {
2068d043c564SKenneth D. Merry mt_entry->missing_count++;
2069d043c564SKenneth D. Merry if (mt_entry->dpm_entry_num !=
2070635e58c7SStephen McConnell MPS_DPM_BAD_IDX) {
2071d043c564SKenneth D. Merry _mapping_commit_map_entry(sc,
2072d043c564SKenneth D. Merry mt_entry);
2073d043c564SKenneth D. Merry }
2074d043c564SKenneth D. Merry }
2075d043c564SKenneth D. Merry mt_entry->init_complete = 1;
2076d043c564SKenneth D. Merry }
2077d043c564SKenneth D. Merry }
2078d043c564SKenneth D. Merry }
2079d043c564SKenneth D. Merry }
2080d043c564SKenneth D. Merry
2081d043c564SKenneth D. Merry /**
2082d043c564SKenneth D. Merry * mps_mapping_initialize - initialize mapping tables
2083d043c564SKenneth D. Merry * @sc: per adapter object
2084d043c564SKenneth D. Merry *
2085d043c564SKenneth D. Merry * Read controller persitant mapping tables into internal data area.
2086d043c564SKenneth D. Merry *
2087d043c564SKenneth D. Merry * Return 0 for success or non-zero for failure.
2088d043c564SKenneth D. Merry */
2089d043c564SKenneth D. Merry int
mps_mapping_initialize(struct mps_softc * sc)2090d043c564SKenneth D. Merry mps_mapping_initialize(struct mps_softc *sc)
2091d043c564SKenneth D. Merry {
2092d043c564SKenneth D. Merry uint16_t volume_mapping_flags, dpm_pg0_sz;
2093d043c564SKenneth D. Merry uint32_t i;
2094d043c564SKenneth D. Merry Mpi2ConfigReply_t mpi_reply;
2095d043c564SKenneth D. Merry int error;
2096d043c564SKenneth D. Merry uint8_t retry_count;
2097d043c564SKenneth D. Merry uint16_t ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
2098d043c564SKenneth D. Merry
2099d043c564SKenneth D. Merry /* The additional 1 accounts for the virtual enclosure
2100d043c564SKenneth D. Merry * created for the controller
2101d043c564SKenneth D. Merry */
2102d043c564SKenneth D. Merry sc->max_enclosures = sc->facts->MaxEnclosures + 1;
2103d043c564SKenneth D. Merry sc->max_expanders = sc->facts->MaxSasExpanders;
2104d043c564SKenneth D. Merry sc->max_volumes = sc->facts->MaxVolumes;
2105d043c564SKenneth D. Merry sc->max_devices = sc->facts->MaxTargets + sc->max_volumes;
2106d043c564SKenneth D. Merry sc->pending_map_events = 0;
2107d043c564SKenneth D. Merry sc->num_enc_table_entries = 0;
2108d043c564SKenneth D. Merry sc->num_rsvd_entries = 0;
2109d043c564SKenneth D. Merry sc->max_dpm_entries = sc->ioc_pg8.MaxPersistentEntries;
2110d043c564SKenneth D. Merry sc->is_dpm_enable = (sc->max_dpm_entries) ? 1 : 0;
2111d043c564SKenneth D. Merry sc->track_mapping_events = 0;
2112d043c564SKenneth D. Merry
2113635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Mapping table has a max of %d entries "
2114635e58c7SStephen McConnell "and DPM has a max of %d entries.\n", __func__, sc->max_devices,
2115635e58c7SStephen McConnell sc->max_dpm_entries);
2116d043c564SKenneth D. Merry if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING)
2117d043c564SKenneth D. Merry sc->is_dpm_enable = 0;
2118d043c564SKenneth D. Merry
2119d043c564SKenneth D. Merry if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
2120d043c564SKenneth D. Merry sc->num_rsvd_entries = 1;
2121d043c564SKenneth D. Merry
2122d043c564SKenneth D. Merry volume_mapping_flags = sc->ioc_pg8.IRVolumeMappingFlags &
2123d043c564SKenneth D. Merry MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
2124d043c564SKenneth D. Merry if (sc->ir_firmware && (volume_mapping_flags ==
2125d043c564SKenneth D. Merry MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING))
2126d043c564SKenneth D. Merry sc->num_rsvd_entries += sc->max_volumes;
2127d043c564SKenneth D. Merry
2128d043c564SKenneth D. Merry error = mps_mapping_allocate_memory(sc);
2129d043c564SKenneth D. Merry if (error)
2130d043c564SKenneth D. Merry return (error);
2131d043c564SKenneth D. Merry
2132d043c564SKenneth D. Merry for (i = 0; i < sc->max_devices; i++)
2133d043c564SKenneth D. Merry _mapping_clear_map_entry(sc->mapping_table + i);
2134d043c564SKenneth D. Merry
2135d043c564SKenneth D. Merry for (i = 0; i < sc->max_enclosures; i++)
2136d043c564SKenneth D. Merry _mapping_clear_enc_entry(sc->enclosure_table + i);
2137d043c564SKenneth D. Merry
2138d043c564SKenneth D. Merry for (i = 0; i < sc->max_devices; i++) {
2139d043c564SKenneth D. Merry sc->removal_table[i].dev_handle = 0;
2140d043c564SKenneth D. Merry sc->removal_table[i].dpm_entry_num = MPS_DPM_BAD_IDX;
2141d043c564SKenneth D. Merry }
2142d043c564SKenneth D. Merry
2143d043c564SKenneth D. Merry memset(sc->dpm_entry_used, 0, sc->max_dpm_entries);
2144d043c564SKenneth D. Merry memset(sc->dpm_flush_entry, 0, sc->max_dpm_entries);
2145d043c564SKenneth D. Merry
2146d043c564SKenneth D. Merry if (sc->is_dpm_enable) {
2147d043c564SKenneth D. Merry dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) +
2148d043c564SKenneth D. Merry (sc->max_dpm_entries *
2149d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY));
2150d043c564SKenneth D. Merry retry_count = 0;
2151d043c564SKenneth D. Merry
2152d043c564SKenneth D. Merry retry_read_dpm:
2153d043c564SKenneth D. Merry if (mps_config_get_dpm_pg0(sc, &mpi_reply, sc->dpm_pg0,
2154d043c564SKenneth D. Merry dpm_pg0_sz)) {
2155635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: DPM page "
2156635e58c7SStephen McConnell "read failed.\n", __func__);
2157d043c564SKenneth D. Merry if (retry_count < 3) {
2158d043c564SKenneth D. Merry retry_count++;
2159d043c564SKenneth D. Merry goto retry_read_dpm;
2160d043c564SKenneth D. Merry }
2161d043c564SKenneth D. Merry sc->is_dpm_enable = 0;
2162d043c564SKenneth D. Merry }
2163d043c564SKenneth D. Merry }
2164d043c564SKenneth D. Merry
2165d043c564SKenneth D. Merry if (sc->is_dpm_enable)
2166d043c564SKenneth D. Merry _mapping_process_dpm_pg0(sc);
2167635e58c7SStephen McConnell else {
2168635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: DPM processing is disabled. "
2169635e58c7SStephen McConnell "Device mappings will not persist across reboots or "
2170635e58c7SStephen McConnell "resets.\n", __func__);
2171635e58c7SStephen McConnell }
2172d043c564SKenneth D. Merry
2173d043c564SKenneth D. Merry sc->track_mapping_events = 1;
2174d043c564SKenneth D. Merry return 0;
2175d043c564SKenneth D. Merry }
2176d043c564SKenneth D. Merry
2177d043c564SKenneth D. Merry /**
2178d043c564SKenneth D. Merry * mps_mapping_exit - clear mapping table and associated memory
2179d043c564SKenneth D. Merry * @sc: per adapter object
2180d043c564SKenneth D. Merry *
2181d043c564SKenneth D. Merry * Returns nothing.
2182d043c564SKenneth D. Merry */
2183d043c564SKenneth D. Merry void
mps_mapping_exit(struct mps_softc * sc)2184d043c564SKenneth D. Merry mps_mapping_exit(struct mps_softc *sc)
2185d043c564SKenneth D. Merry {
2186d043c564SKenneth D. Merry _mapping_flush_dpm_pages(sc);
2187d043c564SKenneth D. Merry mps_mapping_free_memory(sc);
2188d043c564SKenneth D. Merry }
2189d043c564SKenneth D. Merry
2190d043c564SKenneth D. Merry /**
2191635e58c7SStephen McConnell * mps_mapping_get_tid - return the target id for sas device and handle
2192d043c564SKenneth D. Merry * @sc: per adapter object
2193d043c564SKenneth D. Merry * @sas_address: sas address of the device
2194d043c564SKenneth D. Merry * @handle: device handle
2195d043c564SKenneth D. Merry *
2196635e58c7SStephen McConnell * Returns valid target ID on success or BAD_ID.
2197d043c564SKenneth D. Merry */
2198d043c564SKenneth D. Merry unsigned int
mps_mapping_get_tid(struct mps_softc * sc,uint64_t sas_address,u16 handle)2199635e58c7SStephen McConnell mps_mapping_get_tid(struct mps_softc *sc, uint64_t sas_address, u16 handle)
2200d043c564SKenneth D. Merry {
2201d043c564SKenneth D. Merry u32 map_idx;
2202d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry;
2203d043c564SKenneth D. Merry
2204d043c564SKenneth D. Merry for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
2205d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx];
2206d043c564SKenneth D. Merry if (mt_entry->dev_handle == handle && mt_entry->physical_id ==
2207d043c564SKenneth D. Merry sas_address)
2208d043c564SKenneth D. Merry return mt_entry->id;
2209d043c564SKenneth D. Merry }
2210d043c564SKenneth D. Merry
2211d043c564SKenneth D. Merry return MPS_MAP_BAD_ID;
2212d043c564SKenneth D. Merry }
2213d043c564SKenneth D. Merry
2214d043c564SKenneth D. Merry /**
2215635e58c7SStephen McConnell * mps_mapping_get_tid_from_handle - find a target id in mapping table using
2216d043c564SKenneth D. Merry * only the dev handle. This is just a wrapper function for the local function
2217d043c564SKenneth D. Merry * _mapping_get_mt_idx_from_handle.
2218d043c564SKenneth D. Merry * @sc: per adapter object
2219d043c564SKenneth D. Merry * @handle: device handle
2220d043c564SKenneth D. Merry *
2221635e58c7SStephen McConnell * Returns valid target ID on success or BAD_ID.
2222d043c564SKenneth D. Merry */
2223d043c564SKenneth D. Merry unsigned int
mps_mapping_get_tid_from_handle(struct mps_softc * sc,u16 handle)2224635e58c7SStephen McConnell mps_mapping_get_tid_from_handle(struct mps_softc *sc, u16 handle)
2225d043c564SKenneth D. Merry {
2226d043c564SKenneth D. Merry return (_mapping_get_mt_idx_from_handle(sc, handle));
2227d043c564SKenneth D. Merry }
2228d043c564SKenneth D. Merry
2229d043c564SKenneth D. Merry /**
2230635e58c7SStephen McConnell * mps_mapping_get_raid_tid - return the target id for raid device
2231d043c564SKenneth D. Merry * @sc: per adapter object
2232d043c564SKenneth D. Merry * @wwid: world wide identifier for raid volume
2233635e58c7SStephen McConnell * @volHandle: volume device handle
2234d043c564SKenneth D. Merry *
2235635e58c7SStephen McConnell * Returns valid target ID on success or BAD_ID.
2236d043c564SKenneth D. Merry */
2237d043c564SKenneth D. Merry unsigned int
mps_mapping_get_raid_tid(struct mps_softc * sc,u64 wwid,u16 volHandle)2238635e58c7SStephen McConnell mps_mapping_get_raid_tid(struct mps_softc *sc, u64 wwid, u16 volHandle)
2239d043c564SKenneth D. Merry {
2240635e58c7SStephen McConnell u32 start_idx, end_idx, map_idx;
2241d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry;
2242d043c564SKenneth D. Merry
2243635e58c7SStephen McConnell _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
2244635e58c7SStephen McConnell mt_entry = &sc->mapping_table[start_idx];
2245635e58c7SStephen McConnell for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) {
2246635e58c7SStephen McConnell if (mt_entry->dev_handle == volHandle &&
2247635e58c7SStephen McConnell mt_entry->physical_id == wwid)
2248d043c564SKenneth D. Merry return mt_entry->id;
2249d043c564SKenneth D. Merry }
2250d043c564SKenneth D. Merry
2251d043c564SKenneth D. Merry return MPS_MAP_BAD_ID;
2252d043c564SKenneth D. Merry }
2253d043c564SKenneth D. Merry
2254d043c564SKenneth D. Merry /**
2255635e58c7SStephen McConnell * mps_mapping_get_raid_tid_from_handle - find raid device in mapping table
2256d043c564SKenneth D. Merry * using only the volume dev handle. This is just a wrapper function for the
2257d043c564SKenneth D. Merry * local function _mapping_get_ir_mt_idx_from_handle.
2258d043c564SKenneth D. Merry * @sc: per adapter object
2259d043c564SKenneth D. Merry * @volHandle: volume device handle
2260d043c564SKenneth D. Merry *
2261635e58c7SStephen McConnell * Returns valid target ID on success or BAD_ID.
2262d043c564SKenneth D. Merry */
2263d043c564SKenneth D. Merry unsigned int
mps_mapping_get_raid_tid_from_handle(struct mps_softc * sc,u16 volHandle)2264635e58c7SStephen McConnell mps_mapping_get_raid_tid_from_handle(struct mps_softc *sc, u16 volHandle)
2265d043c564SKenneth D. Merry {
2266d043c564SKenneth D. Merry return (_mapping_get_ir_mt_idx_from_handle(sc, volHandle));
2267d043c564SKenneth D. Merry }
2268d043c564SKenneth D. Merry
2269d043c564SKenneth D. Merry /**
2270d043c564SKenneth D. Merry * mps_mapping_enclosure_dev_status_change_event - handle enclosure events
2271d043c564SKenneth D. Merry * @sc: per adapter object
2272d043c564SKenneth D. Merry * @event_data: event data payload
2273d043c564SKenneth D. Merry *
2274d043c564SKenneth D. Merry * Return nothing.
2275d043c564SKenneth D. Merry */
2276d043c564SKenneth D. Merry void
mps_mapping_enclosure_dev_status_change_event(struct mps_softc * sc,Mpi2EventDataSasEnclDevStatusChange_t * event_data)2277d043c564SKenneth D. Merry mps_mapping_enclosure_dev_status_change_event(struct mps_softc *sc,
2278d043c564SKenneth D. Merry Mpi2EventDataSasEnclDevStatusChange_t *event_data)
2279d043c564SKenneth D. Merry {
2280d043c564SKenneth D. Merry u8 enc_idx, missing_count;
2281d043c564SKenneth D. Merry struct enc_mapping_table *et_entry;
2282d043c564SKenneth D. Merry Mpi2DriverMap0Entry_t *dpm_entry;
2283d043c564SKenneth D. Merry u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
2284d043c564SKenneth D. Merry u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
2285d043c564SKenneth D. Merry u8 update_phy_bits = 0;
2286d043c564SKenneth D. Merry u32 saved_phy_bits;
2287d043c564SKenneth D. Merry uint64_t temp64_var;
2288d043c564SKenneth D. Merry
2289d043c564SKenneth D. Merry if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) !=
2290d043c564SKenneth D. Merry MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING)
2291d043c564SKenneth D. Merry goto out;
2292d043c564SKenneth D. Merry
2293d043c564SKenneth D. Merry dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
2294d043c564SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
2295d043c564SKenneth D. Merry
2296d043c564SKenneth D. Merry if (event_data->ReasonCode == MPI2_EVENT_SAS_ENCL_RC_ADDED) {
2297d043c564SKenneth D. Merry if (!event_data->NumSlots) {
2298635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Enclosure "
2299635e58c7SStephen McConnell "with handle = 0x%x reported 0 slots.\n", __func__,
2300d043c564SKenneth D. Merry le16toh(event_data->EnclosureHandle));
2301d043c564SKenneth D. Merry goto out;
2302d043c564SKenneth D. Merry }
2303d043c564SKenneth D. Merry temp64_var = event_data->EnclosureLogicalID.High;
2304d043c564SKenneth D. Merry temp64_var = (temp64_var << 32) |
2305d043c564SKenneth D. Merry event_data->EnclosureLogicalID.Low;
2306d043c564SKenneth D. Merry enc_idx = _mapping_get_enc_idx_from_id(sc, temp64_var,
2307d043c564SKenneth D. Merry event_data->PhyBits);
2308635e58c7SStephen McConnell
2309635e58c7SStephen McConnell /*
2310635e58c7SStephen McConnell * If the Added enclosure is already in the Enclosure Table,
2311d6f9a3c0SGordon Bergling * make sure that all the enclosure info is up to date. If
2312635e58c7SStephen McConnell * the enclosure was missing and has just been added back, or if
2313635e58c7SStephen McConnell * the enclosure's Phy Bits have changed, clear the missing
2314635e58c7SStephen McConnell * count and update the Phy Bits in the mapping table and in the
2315635e58c7SStephen McConnell * DPM, if it's being used.
2316635e58c7SStephen McConnell */
2317d043c564SKenneth D. Merry if (enc_idx != MPS_ENCTABLE_BAD_IDX) {
2318d043c564SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx];
2319d043c564SKenneth D. Merry if (et_entry->init_complete &&
2320d043c564SKenneth D. Merry !et_entry->missing_count) {
2321635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING, "%s: Enclosure %d "
2322635e58c7SStephen McConnell "is already present with handle = 0x%x\n",
2323635e58c7SStephen McConnell __func__, enc_idx, et_entry->enc_handle);
2324d043c564SKenneth D. Merry goto out;
2325d043c564SKenneth D. Merry }
2326d043c564SKenneth D. Merry et_entry->enc_handle = le16toh(event_data->
2327d043c564SKenneth D. Merry EnclosureHandle);
2328d043c564SKenneth D. Merry et_entry->start_slot = le16toh(event_data->StartSlot);
2329d043c564SKenneth D. Merry saved_phy_bits = et_entry->phy_bits;
2330d043c564SKenneth D. Merry et_entry->phy_bits |= le32toh(event_data->PhyBits);
2331d043c564SKenneth D. Merry if (saved_phy_bits != et_entry->phy_bits)
2332d043c564SKenneth D. Merry update_phy_bits = 1;
2333d043c564SKenneth D. Merry if (et_entry->missing_count || update_phy_bits) {
2334d043c564SKenneth D. Merry et_entry->missing_count = 0;
2335d043c564SKenneth D. Merry if (sc->is_dpm_enable &&
2336d043c564SKenneth D. Merry et_entry->dpm_entry_num !=
2337d043c564SKenneth D. Merry MPS_DPM_BAD_IDX) {
2338d043c564SKenneth D. Merry dpm_entry += et_entry->dpm_entry_num;
2339d043c564SKenneth D. Merry missing_count =
2340d043c564SKenneth D. Merry (u8)(dpm_entry->MappingInformation &
2341d043c564SKenneth D. Merry MPI2_DRVMAP0_MAPINFO_MISSING_MASK);
2342635e58c7SStephen McConnell if (missing_count || update_phy_bits) {
2343d043c564SKenneth D. Merry dpm_entry->MappingInformation
2344d043c564SKenneth D. Merry = et_entry->num_slots;
2345d043c564SKenneth D. Merry dpm_entry->MappingInformation
2346d043c564SKenneth D. Merry <<= map_shift;
2347d043c564SKenneth D. Merry dpm_entry->PhysicalBitsMapping
2348d043c564SKenneth D. Merry = et_entry->phy_bits;
2349d043c564SKenneth D. Merry sc->dpm_flush_entry[et_entry->
2350d043c564SKenneth D. Merry dpm_entry_num] = 1;
2351d043c564SKenneth D. Merry }
2352d043c564SKenneth D. Merry }
2353d043c564SKenneth D. Merry }
2354d043c564SKenneth D. Merry } else {
2355635e58c7SStephen McConnell /*
2356635e58c7SStephen McConnell * This is a new enclosure that is being added.
2357635e58c7SStephen McConnell * Initialize the Enclosure Table entry. It will be
2358635e58c7SStephen McConnell * finalized when a device is added for the enclosure
2359635e58c7SStephen McConnell * and the enclosure has enough space in the Mapping
2360635e58c7SStephen McConnell * Table to map its devices.
2361635e58c7SStephen McConnell */
2362b99419aeSAlexander Motin if (sc->num_enc_table_entries < sc->max_enclosures) {
2363d043c564SKenneth D. Merry enc_idx = sc->num_enc_table_entries;
2364b99419aeSAlexander Motin sc->num_enc_table_entries++;
2365b99419aeSAlexander Motin } else {
2366b99419aeSAlexander Motin enc_idx = _mapping_get_high_missing_et_idx(sc);
2367b99419aeSAlexander Motin if (enc_idx != MPS_ENCTABLE_BAD_IDX) {
2368b99419aeSAlexander Motin et_entry = &sc->enclosure_table[enc_idx];
2369b99419aeSAlexander Motin _mapping_add_to_removal_table(sc,
2370b99419aeSAlexander Motin et_entry->dpm_entry_num);
2371b99419aeSAlexander Motin _mapping_clear_enc_entry(et_entry);
2372b99419aeSAlexander Motin }
2373b99419aeSAlexander Motin }
2374b99419aeSAlexander Motin if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
2375635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: "
2376635e58c7SStephen McConnell "Enclosure cannot be added to mapping "
2377635e58c7SStephen McConnell "table because it's full.\n", __func__);
2378d043c564SKenneth D. Merry goto out;
2379d043c564SKenneth D. Merry }
2380d043c564SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx];
2381d043c564SKenneth D. Merry et_entry->enc_handle = le16toh(event_data->
2382d043c564SKenneth D. Merry EnclosureHandle);
2383635e58c7SStephen McConnell et_entry->enclosure_id = le64toh(event_data->
2384635e58c7SStephen McConnell EnclosureLogicalID.High);
2385635e58c7SStephen McConnell et_entry->enclosure_id =
2386635e58c7SStephen McConnell ((et_entry->enclosure_id << 32) |
2387635e58c7SStephen McConnell le64toh(event_data->EnclosureLogicalID.Low));
2388d043c564SKenneth D. Merry et_entry->start_index = MPS_MAPTABLE_BAD_IDX;
2389d043c564SKenneth D. Merry et_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
2390d043c564SKenneth D. Merry et_entry->num_slots = le16toh(event_data->NumSlots);
2391d043c564SKenneth D. Merry et_entry->start_slot = le16toh(event_data->StartSlot);
2392d043c564SKenneth D. Merry et_entry->phy_bits = le32toh(event_data->PhyBits);
2393d043c564SKenneth D. Merry }
2394d043c564SKenneth D. Merry et_entry->init_complete = 1;
2395d043c564SKenneth D. Merry } else if (event_data->ReasonCode ==
2396d043c564SKenneth D. Merry MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING) {
2397635e58c7SStephen McConnell /*
2398635e58c7SStephen McConnell * An enclosure was removed. Update its missing count and then
2399635e58c7SStephen McConnell * update the DPM entry with the new missing count for the
2400635e58c7SStephen McConnell * enclosure.
2401635e58c7SStephen McConnell */
2402d043c564SKenneth D. Merry enc_idx = _mapping_get_enc_idx_from_handle(sc,
2403d043c564SKenneth D. Merry le16toh(event_data->EnclosureHandle));
2404d043c564SKenneth D. Merry if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
2405635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING, "%s: Cannot "
2406b99419aeSAlexander Motin "unmap enclosure with handle 0x%04x because it "
2407b99419aeSAlexander Motin "has already been deleted.\n", __func__,
2408b99419aeSAlexander Motin le16toh(event_data->EnclosureHandle));
2409d043c564SKenneth D. Merry goto out;
2410d043c564SKenneth D. Merry }
2411d043c564SKenneth D. Merry et_entry = &sc->enclosure_table[enc_idx];
2412d043c564SKenneth D. Merry if (et_entry->missing_count < MPS_MAX_MISSING_COUNT)
2413d043c564SKenneth D. Merry et_entry->missing_count++;
2414635e58c7SStephen McConnell if (sc->is_dpm_enable &&
2415d043c564SKenneth D. Merry et_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
2416d043c564SKenneth D. Merry dpm_entry += et_entry->dpm_entry_num;
2417d043c564SKenneth D. Merry dpm_entry->MappingInformation = et_entry->num_slots;
2418d043c564SKenneth D. Merry dpm_entry->MappingInformation <<= map_shift;
2419d043c564SKenneth D. Merry dpm_entry->MappingInformation |=
2420d043c564SKenneth D. Merry et_entry->missing_count;
2421d043c564SKenneth D. Merry sc->dpm_flush_entry[et_entry->dpm_entry_num] = 1;
2422d043c564SKenneth D. Merry }
2423d043c564SKenneth D. Merry et_entry->init_complete = 1;
2424d043c564SKenneth D. Merry }
2425d043c564SKenneth D. Merry
2426d043c564SKenneth D. Merry out:
2427d043c564SKenneth D. Merry _mapping_flush_dpm_pages(sc);
2428d043c564SKenneth D. Merry if (sc->pending_map_events)
2429d043c564SKenneth D. Merry sc->pending_map_events--;
2430d043c564SKenneth D. Merry }
2431d043c564SKenneth D. Merry
2432d043c564SKenneth D. Merry /**
2433d043c564SKenneth D. Merry * mps_mapping_topology_change_event - handle topology change events
2434d043c564SKenneth D. Merry * @sc: per adapter object
2435d043c564SKenneth D. Merry * @event_data: event data payload
2436d043c564SKenneth D. Merry *
2437d043c564SKenneth D. Merry * Returns nothing.
2438d043c564SKenneth D. Merry */
2439d043c564SKenneth D. Merry void
mps_mapping_topology_change_event(struct mps_softc * sc,Mpi2EventDataSasTopologyChangeList_t * event_data)2440d043c564SKenneth D. Merry mps_mapping_topology_change_event(struct mps_softc *sc,
2441d043c564SKenneth D. Merry Mpi2EventDataSasTopologyChangeList_t *event_data)
2442d043c564SKenneth D. Merry {
2443d043c564SKenneth D. Merry struct _map_topology_change topo_change;
2444d043c564SKenneth D. Merry struct _map_phy_change *phy_change;
2445d043c564SKenneth D. Merry Mpi2EventSasTopoPhyEntry_t *event_phy_change;
2446d043c564SKenneth D. Merry u8 i, num_entries;
2447d043c564SKenneth D. Merry
2448d043c564SKenneth D. Merry topo_change.enc_handle = le16toh(event_data->EnclosureHandle);
2449d043c564SKenneth D. Merry topo_change.exp_handle = le16toh(event_data->ExpanderDevHandle);
2450d043c564SKenneth D. Merry num_entries = event_data->NumEntries;
2451d043c564SKenneth D. Merry topo_change.num_entries = num_entries;
2452d043c564SKenneth D. Merry topo_change.start_phy_num = event_data->StartPhyNum;
2453d043c564SKenneth D. Merry topo_change.num_phys = event_data->NumPhys;
2454d043c564SKenneth D. Merry topo_change.exp_status = event_data->ExpStatus;
2455d043c564SKenneth D. Merry event_phy_change = event_data->PHY;
2456d043c564SKenneth D. Merry topo_change.phy_details = NULL;
2457d043c564SKenneth D. Merry
2458d043c564SKenneth D. Merry if (!num_entries)
2459d043c564SKenneth D. Merry goto out;
2460ac2fffa4SPedro F. Giffuni phy_change = malloc(sizeof(struct _map_phy_change) * num_entries,
2461d043c564SKenneth D. Merry M_MPT2, M_NOWAIT|M_ZERO);
2462d043c564SKenneth D. Merry topo_change.phy_details = phy_change;
2463d043c564SKenneth D. Merry if (!phy_change)
2464d043c564SKenneth D. Merry goto out;
2465d043c564SKenneth D. Merry for (i = 0; i < num_entries; i++, event_phy_change++, phy_change++) {
2466d043c564SKenneth D. Merry phy_change->dev_handle = le16toh(event_phy_change->
2467d043c564SKenneth D. Merry AttachedDevHandle);
2468d043c564SKenneth D. Merry phy_change->reason = event_phy_change->PhyStatus &
2469d043c564SKenneth D. Merry MPI2_EVENT_SAS_TOPO_RC_MASK;
2470d043c564SKenneth D. Merry }
2471d043c564SKenneth D. Merry _mapping_update_missing_count(sc, &topo_change);
2472d043c564SKenneth D. Merry _mapping_get_dev_info(sc, &topo_change);
2473d043c564SKenneth D. Merry _mapping_clear_removed_entries(sc);
2474d043c564SKenneth D. Merry _mapping_add_new_device(sc, &topo_change);
2475d043c564SKenneth D. Merry
2476d043c564SKenneth D. Merry out:
2477d043c564SKenneth D. Merry free(topo_change.phy_details, M_MPT2);
2478d043c564SKenneth D. Merry _mapping_flush_dpm_pages(sc);
2479d043c564SKenneth D. Merry if (sc->pending_map_events)
2480d043c564SKenneth D. Merry sc->pending_map_events--;
2481d043c564SKenneth D. Merry }
2482d043c564SKenneth D. Merry
2483d043c564SKenneth D. Merry /**
2484d043c564SKenneth D. Merry * mps_mapping_ir_config_change_event - handle IR config change list events
2485d043c564SKenneth D. Merry * @sc: per adapter object
2486d043c564SKenneth D. Merry * @event_data: event data payload
2487d043c564SKenneth D. Merry *
2488d043c564SKenneth D. Merry * Returns nothing.
2489d043c564SKenneth D. Merry */
2490d043c564SKenneth D. Merry void
mps_mapping_ir_config_change_event(struct mps_softc * sc,Mpi2EventDataIrConfigChangeList_t * event_data)2491d043c564SKenneth D. Merry mps_mapping_ir_config_change_event(struct mps_softc *sc,
2492d043c564SKenneth D. Merry Mpi2EventDataIrConfigChangeList_t *event_data)
2493d043c564SKenneth D. Merry {
2494d043c564SKenneth D. Merry Mpi2EventIrConfigElement_t *element;
2495d043c564SKenneth D. Merry int i;
2496d043c564SKenneth D. Merry u64 *wwid_table;
2497d043c564SKenneth D. Merry u32 map_idx, flags;
2498d043c564SKenneth D. Merry struct dev_mapping_table *mt_entry;
2499d043c564SKenneth D. Merry u16 element_flags;
2500d043c564SKenneth D. Merry
2501ac2fffa4SPedro F. Giffuni wwid_table = malloc(sizeof(u64) * event_data->NumElements, M_MPT2,
2502d043c564SKenneth D. Merry M_NOWAIT | M_ZERO);
2503d043c564SKenneth D. Merry if (!wwid_table)
2504d043c564SKenneth D. Merry goto out;
2505d043c564SKenneth D. Merry element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
2506d043c564SKenneth D. Merry flags = le32toh(event_data->Flags);
2507635e58c7SStephen McConnell
2508635e58c7SStephen McConnell /*
2509635e58c7SStephen McConnell * For volume changes, get the WWID for the volume and put it in a
2510635e58c7SStephen McConnell * table to be used in the processing of the IR change event.
2511635e58c7SStephen McConnell */
2512d043c564SKenneth D. Merry for (i = 0; i < event_data->NumElements; i++, element++) {
2513d043c564SKenneth D. Merry element_flags = le16toh(element->ElementFlags);
2514d043c564SKenneth D. Merry if ((element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_ADDED) &&
2515d043c564SKenneth D. Merry (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_REMOVED) &&
2516d043c564SKenneth D. Merry (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE)
2517d043c564SKenneth D. Merry && (element->ReasonCode !=
2518d043c564SKenneth D. Merry MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED))
2519d043c564SKenneth D. Merry continue;
2520d043c564SKenneth D. Merry if ((element_flags &
2521d043c564SKenneth D. Merry MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK) ==
2522d043c564SKenneth D. Merry MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT) {
2523d043c564SKenneth D. Merry mps_config_get_volume_wwid(sc,
2524d043c564SKenneth D. Merry le16toh(element->VolDevHandle), &wwid_table[i]);
2525d043c564SKenneth D. Merry }
2526d043c564SKenneth D. Merry }
2527635e58c7SStephen McConnell
2528635e58c7SStephen McConnell /*
2529635e58c7SStephen McConnell * Check the ReasonCode for each element in the IR event and Add/Remove
2530635e58c7SStephen McConnell * Volumes or Physical Disks of Volumes to/from the mapping table. Use
2531635e58c7SStephen McConnell * the WWIDs gotten above in wwid_table.
2532635e58c7SStephen McConnell */
2533d043c564SKenneth D. Merry if (flags == MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
2534d043c564SKenneth D. Merry goto out;
2535d043c564SKenneth D. Merry else {
2536d043c564SKenneth D. Merry element = (Mpi2EventIrConfigElement_t *)&event_data->
2537d043c564SKenneth D. Merry ConfigElement[0];
2538d043c564SKenneth D. Merry for (i = 0; i < event_data->NumElements; i++, element++) {
2539d043c564SKenneth D. Merry if (element->ReasonCode ==
2540d043c564SKenneth D. Merry MPI2_EVENT_IR_CHANGE_RC_ADDED ||
2541d043c564SKenneth D. Merry element->ReasonCode ==
2542d043c564SKenneth D. Merry MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) {
2543d043c564SKenneth D. Merry map_idx = _mapping_get_ir_mt_idx_from_wwid
2544d043c564SKenneth D. Merry (sc, wwid_table[i]);
2545d043c564SKenneth D. Merry if (map_idx != MPS_MAPTABLE_BAD_IDX) {
2546635e58c7SStephen McConnell /*
2547635e58c7SStephen McConnell * The volume is already in the mapping
2548635e58c7SStephen McConnell * table. Just update it's info.
2549635e58c7SStephen McConnell */
2550d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx];
2551d043c564SKenneth D. Merry mt_entry->id = map_idx;
2552d043c564SKenneth D. Merry mt_entry->dev_handle = le16toh
2553d043c564SKenneth D. Merry (element->VolDevHandle);
2554d043c564SKenneth D. Merry mt_entry->device_info =
2555d043c564SKenneth D. Merry MPS_DEV_RESERVED | MPS_MAP_IN_USE;
2556d043c564SKenneth D. Merry _mapping_update_ir_missing_cnt(sc,
2557d043c564SKenneth D. Merry map_idx, element, wwid_table[i]);
2558d043c564SKenneth D. Merry continue;
2559d043c564SKenneth D. Merry }
2560635e58c7SStephen McConnell
2561635e58c7SStephen McConnell /*
2562635e58c7SStephen McConnell * Volume is not in mapping table yet. Find a
2563635e58c7SStephen McConnell * free entry in the mapping table at the
2564635e58c7SStephen McConnell * volume mapping locations. If no entries are
2565635e58c7SStephen McConnell * available, this is an error because it means
2566635e58c7SStephen McConnell * there are more volumes than can be mapped
2567635e58c7SStephen McConnell * and that should never happen for volumes.
2568635e58c7SStephen McConnell */
2569d043c564SKenneth D. Merry map_idx = _mapping_get_free_ir_mt_idx(sc);
2570d043c564SKenneth D. Merry if (map_idx == MPS_MAPTABLE_BAD_IDX)
2571635e58c7SStephen McConnell {
2572635e58c7SStephen McConnell mps_dprint(sc, MPS_ERROR | MPS_MAPPING,
2573635e58c7SStephen McConnell "%s: failed to add the volume with "
2574635e58c7SStephen McConnell "handle 0x%04x because there is no "
2575635e58c7SStephen McConnell "free space available in the "
2576635e58c7SStephen McConnell "mapping table\n", __func__,
2577635e58c7SStephen McConnell le16toh(element->VolDevHandle));
2578d043c564SKenneth D. Merry continue;
2579d043c564SKenneth D. Merry }
2580d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx];
2581d043c564SKenneth D. Merry mt_entry->physical_id = wwid_table[i];
2582d043c564SKenneth D. Merry mt_entry->id = map_idx;
2583d043c564SKenneth D. Merry mt_entry->dev_handle = le16toh(element->
2584d043c564SKenneth D. Merry VolDevHandle);
2585d043c564SKenneth D. Merry mt_entry->device_info = MPS_DEV_RESERVED |
2586d043c564SKenneth D. Merry MPS_MAP_IN_USE;
2587d043c564SKenneth D. Merry _mapping_update_ir_missing_cnt(sc, map_idx,
2588d043c564SKenneth D. Merry element, wwid_table[i]);
2589d043c564SKenneth D. Merry } else if (element->ReasonCode ==
2590d043c564SKenneth D. Merry MPI2_EVENT_IR_CHANGE_RC_REMOVED) {
2591d043c564SKenneth D. Merry map_idx = _mapping_get_ir_mt_idx_from_wwid(sc,
2592d043c564SKenneth D. Merry wwid_table[i]);
2593d043c564SKenneth D. Merry if (map_idx == MPS_MAPTABLE_BAD_IDX) {
2594635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING,"%s: Failed "
2595635e58c7SStephen McConnell "to remove a volume because it has "
2596635e58c7SStephen McConnell "already been removed.\n",
2597635e58c7SStephen McConnell __func__);
2598d043c564SKenneth D. Merry continue;
2599d043c564SKenneth D. Merry }
2600d043c564SKenneth D. Merry _mapping_update_ir_missing_cnt(sc, map_idx,
2601d043c564SKenneth D. Merry element, wwid_table[i]);
2602d043c564SKenneth D. Merry } else if (element->ReasonCode ==
2603d043c564SKenneth D. Merry MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED) {
2604d043c564SKenneth D. Merry map_idx = _mapping_get_mt_idx_from_handle(sc,
2605d043c564SKenneth D. Merry le16toh(element->VolDevHandle));
2606d043c564SKenneth D. Merry if (map_idx == MPS_MAPTABLE_BAD_IDX) {
2607635e58c7SStephen McConnell mps_dprint(sc, MPS_MAPPING,"%s: Failed "
2608635e58c7SStephen McConnell "to remove volume with handle "
2609635e58c7SStephen McConnell "0x%04x because it has already "
2610635e58c7SStephen McConnell "been removed.\n", __func__,
2611d043c564SKenneth D. Merry le16toh(element->VolDevHandle));
2612d043c564SKenneth D. Merry continue;
2613d043c564SKenneth D. Merry }
2614d043c564SKenneth D. Merry mt_entry = &sc->mapping_table[map_idx];
2615d043c564SKenneth D. Merry _mapping_update_ir_missing_cnt(sc, map_idx,
2616d043c564SKenneth D. Merry element, mt_entry->physical_id);
2617d043c564SKenneth D. Merry }
2618d043c564SKenneth D. Merry }
2619d043c564SKenneth D. Merry }
2620d043c564SKenneth D. Merry
2621d043c564SKenneth D. Merry out:
2622d043c564SKenneth D. Merry _mapping_flush_dpm_pages(sc);
2623d043c564SKenneth D. Merry free(wwid_table, M_MPT2);
2624d043c564SKenneth D. Merry if (sc->pending_map_events)
2625d043c564SKenneth D. Merry sc->pending_map_events--;
2626d043c564SKenneth D. Merry }
2627ee5c196bSScott Long
2628ee5c196bSScott Long int
mps_mapping_dump(SYSCTL_HANDLER_ARGS)2629ee5c196bSScott Long mps_mapping_dump(SYSCTL_HANDLER_ARGS)
2630ee5c196bSScott Long {
2631ee5c196bSScott Long struct mps_softc *sc;
2632ee5c196bSScott Long struct dev_mapping_table *mt_entry;
2633ee5c196bSScott Long struct sbuf sbuf;
2634ee5c196bSScott Long int i, error;
2635ee5c196bSScott Long
2636ee5c196bSScott Long sc = (struct mps_softc *)arg1;
2637ee5c196bSScott Long
2638ee5c196bSScott Long error = sysctl_wire_old_buffer(req, 0);
2639ee5c196bSScott Long if (error != 0)
2640ee5c196bSScott Long return (error);
2641ee5c196bSScott Long sbuf_new_for_sysctl(&sbuf, NULL, 128, req);
2642ee5c196bSScott Long
2643ee5c196bSScott Long sbuf_printf(&sbuf, "\nindex physical_id handle id\n");
2644ee5c196bSScott Long for (i = 0; i < sc->max_devices; i++) {
2645ee5c196bSScott Long mt_entry = &sc->mapping_table[i];
2646ee5c196bSScott Long if (mt_entry->physical_id == 0)
2647ee5c196bSScott Long continue;
2648ee5c196bSScott Long sbuf_printf(&sbuf, "%4d %jx %04x %hd\n",
2649ee5c196bSScott Long i, mt_entry->physical_id, mt_entry->dev_handle,
2650ee5c196bSScott Long mt_entry->id);
2651ee5c196bSScott Long }
2652ee5c196bSScott Long error = sbuf_finish(&sbuf);
2653ee5c196bSScott Long sbuf_delete(&sbuf);
2654ee5c196bSScott Long return (error);
2655ee5c196bSScott Long }
2656ee5c196bSScott Long
2657ee5c196bSScott Long int
mps_mapping_encl_dump(SYSCTL_HANDLER_ARGS)2658ee5c196bSScott Long mps_mapping_encl_dump(SYSCTL_HANDLER_ARGS)
2659ee5c196bSScott Long {
2660ee5c196bSScott Long struct mps_softc *sc;
2661ee5c196bSScott Long struct enc_mapping_table *enc_entry;
2662ee5c196bSScott Long struct sbuf sbuf;
2663ee5c196bSScott Long int i, error;
2664ee5c196bSScott Long
2665ee5c196bSScott Long sc = (struct mps_softc *)arg1;
2666ee5c196bSScott Long
2667ee5c196bSScott Long error = sysctl_wire_old_buffer(req, 0);
2668ee5c196bSScott Long if (error != 0)
2669ee5c196bSScott Long return (error);
2670ee5c196bSScott Long sbuf_new_for_sysctl(&sbuf, NULL, 128, req);
2671ee5c196bSScott Long
2672ee5c196bSScott Long sbuf_printf(&sbuf, "\nindex enclosure_id handle map_index\n");
2673ee5c196bSScott Long for (i = 0; i < sc->max_enclosures; i++) {
2674ee5c196bSScott Long enc_entry = &sc->enclosure_table[i];
2675ee5c196bSScott Long if (enc_entry->enclosure_id == 0)
2676ee5c196bSScott Long continue;
2677ee5c196bSScott Long sbuf_printf(&sbuf, "%4d %jx %04x %d\n",
2678ee5c196bSScott Long i, enc_entry->enclosure_id, enc_entry->enc_handle,
2679ee5c196bSScott Long enc_entry->start_index);
2680ee5c196bSScott Long }
2681ee5c196bSScott Long error = sbuf_finish(&sbuf);
2682ee5c196bSScott Long sbuf_delete(&sbuf);
2683ee5c196bSScott Long return (error);
2684ee5c196bSScott Long }
2685