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