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